From 172f3fcb17382faafc71091868370b6765da7a43 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 26 Nov 2015 22:12:02 +0000 Subject: ARM: l2c: tauros2: fix OF-enabled non-DT boot Signed-off-by: Russell King --- arch/arm/mm/cache-tauros2.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c index 1e373d268c04..95eb524ce556 100644 --- a/arch/arm/mm/cache-tauros2.c +++ b/arch/arm/mm/cache-tauros2.c @@ -287,16 +287,15 @@ void __init tauros2_init(unsigned int features) node = of_find_matching_node(NULL, tauros2_ids); if (!node) { pr_info("Not found marvell,tauros2-cache, disable it\n"); - return; + } else { + ret = of_property_read_u32(node, "marvell,tauros2-cache-features", &f); + if (ret) { + pr_info("Not found marvell,tauros-cache-features property, " + "disable extra features\n"); + features = 0; + } else + features = f; } - - ret = of_property_read_u32(node, "marvell,tauros2-cache-features", &f); - if (ret) { - pr_info("Not found marvell,tauros-cache-features property, " - "disable extra features\n"); - features = 0; - } else - features = f; #endif tauros2_internal_init(features); } -- cgit From 1d93ba2aaacc96bef018c5c2e12840f07372a2be Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 26 Nov 2015 22:12:26 +0000 Subject: ARM: l2c: tauros2: use descriptive definitions for register bits Use descriptive definitions for the Tauros2 register bits, and while we're here, clean up the "Tauros2: %s line fill burt8." message. Signed-off-by: Russell King --- arch/arm/mm/cache-tauros2.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c index 95eb524ce556..88255bea65e4 100644 --- a/arch/arm/mm/cache-tauros2.c +++ b/arch/arm/mm/cache-tauros2.c @@ -22,6 +22,11 @@ #include #include +/* CP15 PJ4 Control configuration register */ +#define CCR_L2C_PREFETCH_DISABLE BIT(24) +#define CCR_L2C_ECC_ENABLE BIT(23) +#define CCR_L2C_WAY7_4_DISABLE BIT(21) +#define CCR_L2C_BURST8_ENABLE BIT(20) /* * When Tauros2 is used on a CPU that supports the v7 hierarchical @@ -182,18 +187,18 @@ static void enable_extra_feature(unsigned int features) u = read_extra_features(); if (features & CACHE_TAUROS2_PREFETCH_ON) - u &= ~0x01000000; + u &= ~CCR_L2C_PREFETCH_DISABLE; else - u |= 0x01000000; + u |= CCR_L2C_PREFETCH_DISABLE; pr_info("Tauros2: %s L2 prefetch.\n", (features & CACHE_TAUROS2_PREFETCH_ON) ? "Enabling" : "Disabling"); if (features & CACHE_TAUROS2_LINEFILL_BURST8) - u |= 0x00100000; + u |= CCR_L2C_BURST8_ENABLE; else - u &= ~0x00100000; - pr_info("Tauros2: %s line fill burt8.\n", + u &= ~CCR_L2C_BURST8_ENABLE; + pr_info("Tauros2: %s burst8 line fill.\n", (features & CACHE_TAUROS2_LINEFILL_BURST8) ? "Enabling" : "Disabling"); -- cgit From 505abf99c7315f2229b873cca7a0514481a118e6 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 26 Dec 2015 21:16:14 +0900 Subject: iio: adc: mcp3422: Add support for MCP3425 The MCP3425 is a single channel up to 16-bit A/D converter which has features: - On-Board Programmable Gain Amplifier (PGA): - Gains of 1, 2, 4 or 8 - Programmable Data Rate Options: - 15 SPS (16 bits), 60 SPS (14 bits), 240 SPS (12 bits) The mcp3422 driver also supports the MCP3421 which is a single channel. So we can support MCP3425 with a little changes to mcp3422 driver. Signed-off-by: Akinobu Mita Cc: Sascha Hauer Cc: Angelo Compagnucci Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- Documentation/devicetree/bindings/iio/adc/mcp3422.txt | 1 + drivers/iio/adc/Kconfig | 6 +++--- drivers/iio/adc/mcp3422.c | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt b/Documentation/devicetree/bindings/iio/adc/mcp3422.txt index dcae4ccfcc52..82bcce07255d 100644 --- a/Documentation/devicetree/bindings/iio/adc/mcp3422.txt +++ b/Documentation/devicetree/bindings/iio/adc/mcp3422.txt @@ -6,6 +6,7 @@ Required properties: "microchip,mcp3422" or "microchip,mcp3423" or "microchip,mcp3424" or + "microchip,mcp3425" or "microchip,mcp3426" or "microchip,mcp3427" or "microchip,mcp3428" diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 605ff42c4631..d0dc39a95555 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -265,11 +265,11 @@ config MCP320X called mcp320x. config MCP3422 - tristate "Microchip Technology MCP3422/3/4/6/7/8 driver" + tristate "Microchip Technology MCP3421/2/3/4/5/6/7/8 driver" depends on I2C help - Say yes here to build support for Microchip Technology's - MCP3422, MCP3423, MCP3424, MCP3426, MCP3427 or MCP3428 + Say yes here to build support for Microchip Technology's MCP3421 + MCP3422, MCP3423, MCP3424, MCP3425, MCP3426, MCP3427 or MCP3428 analog to digital converters. This driver can also be built as a module. If so, the module will be diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c index 6eca7aea8a37..ebad83e3fbf7 100644 --- a/drivers/iio/adc/mcp3422.c +++ b/drivers/iio/adc/mcp3422.c @@ -1,11 +1,12 @@ /* - * mcp3422.c - driver for the Microchip mcp3422/3/4/6/7/8 chip family + * mcp3422.c - driver for the Microchip mcp3421/2/3/4/5/6/7/8 chip family * * Copyright (C) 2013, Angelo Compagnucci * Author: Angelo Compagnucci * * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf * http://ww1.microchip.com/downloads/en/DeviceDoc/22226a.pdf + * http://ww1.microchip.com/downloads/en/DeviceDoc/22072b.pdf * * This driver exports the value of analog input voltage to sysfs, the * voltage unit is nV. @@ -357,6 +358,7 @@ static int mcp3422_probe(struct i2c_client *client, switch (adc->id) { case 1: + case 5: indio_dev->channels = mcp3421_channels; indio_dev->num_channels = ARRAY_SIZE(mcp3421_channels); break; @@ -395,6 +397,7 @@ static const struct i2c_device_id mcp3422_id[] = { { "mcp3422", 2 }, { "mcp3423", 3 }, { "mcp3424", 4 }, + { "mcp3425", 5 }, { "mcp3426", 6 }, { "mcp3427", 7 }, { "mcp3428", 8 }, @@ -421,5 +424,5 @@ static struct i2c_driver mcp3422_driver = { module_i2c_driver(mcp3422_driver); MODULE_AUTHOR("Angelo Compagnucci "); -MODULE_DESCRIPTION("Microchip mcp3422/3/4/6/7/8 driver"); +MODULE_DESCRIPTION("Microchip mcp3421/2/3/4/5/6/7/8 driver"); MODULE_LICENSE("GPL v2"); -- cgit From 35f739679a18d7a9680960c9cfc472ef012682dd Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 26 Dec 2015 21:17:22 +0900 Subject: iio: dac: mcp4725: Add basic support for MCP4726 MCP4726 is a single channel 12-bit DAC. We can support MCP4726 with a little changes to mcp4725 driver. In power-down mode, they have different selection of VOUT pull-down registers. MCP4726 also has features: - Output gain options: 1x, 2x - Voltage reference selection: VDD, VREF (Unbuffered or Buffered) But these are not supported in this change. (1x gain, VDD is selected) datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/22272C.pdf Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 2 + drivers/iio/dac/Kconfig | 4 +- drivers/iio/dac/mcp4725.c | 87 +++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 22 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 0439c2aaf741..8fadd272ad8a 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -497,7 +497,9 @@ Description: 6kohm_to_gnd: connected to ground via a 6kOhm resistor, 20kohm_to_gnd: connected to ground via a 20kOhm resistor, 100kohm_to_gnd: connected to ground via an 100kOhm resistor, + 125kohm_to_gnd: connected to ground via an 125kOhm resistor, 500kohm_to_gnd: connected to ground via a 500kOhm resistor, + 640kohm_to_gnd: connected to ground via a 640kOhm resistor, three_state: left floating. For a list of available output power down options read outX_powerdown_mode_available. If Y is not present the diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index e701e28fb1cd..5263c5125fbb 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -176,11 +176,11 @@ config MAX5821 10 bits DAC. config MCP4725 - tristate "MCP4725 DAC driver" + tristate "MCP4725/6 DAC driver" depends on I2C ---help--- Say Y here if you want to build a driver for the Microchip - MCP 4725 12-bit digital-to-analog converter (DAC) with I2C + MCP 4725/6 12-bit digital-to-analog converter (DAC) with I2C interface. To compile this driver as a module, choose M here: the module diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 43d14588448d..fb4b3364d8e0 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -1,5 +1,5 @@ /* - * mcp4725.c - Support for Microchip MCP4725 + * mcp4725.c - Support for Microchip MCP4725/6 * * Copyright (C) 2012 Peter Meerwald * @@ -134,6 +134,12 @@ static const char * const mcp4725_powerdown_modes[] = { "500kohm_to_gnd" }; +static const char * const mcp4726_powerdown_modes[] = { + "1kohm_to_gnd", + "125kohm_to_gnd", + "640kohm_to_gnd" +}; + static int mcp4725_get_powerdown_mode(struct iio_dev *indio_dev, const struct iio_chan_spec *chan) { @@ -182,11 +188,24 @@ static ssize_t mcp4725_write_powerdown(struct iio_dev *indio_dev, return len; } -static const struct iio_enum mcp4725_powerdown_mode_enum = { - .items = mcp4725_powerdown_modes, - .num_items = ARRAY_SIZE(mcp4725_powerdown_modes), - .get = mcp4725_get_powerdown_mode, - .set = mcp4725_set_powerdown_mode, +enum { + MCP4725, + MCP4726, +}; + +static const struct iio_enum mcp472x_powerdown_mode_enum[] = { + [MCP4725] = { + .items = mcp4725_powerdown_modes, + .num_items = ARRAY_SIZE(mcp4725_powerdown_modes), + .get = mcp4725_get_powerdown_mode, + .set = mcp4725_set_powerdown_mode, + }, + [MCP4726] = { + .items = mcp4726_powerdown_modes, + .num_items = ARRAY_SIZE(mcp4726_powerdown_modes), + .get = mcp4725_get_powerdown_mode, + .set = mcp4725_set_powerdown_mode, + }, }; static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { @@ -196,19 +215,46 @@ static const struct iio_chan_spec_ext_info mcp4725_ext_info[] = { .write = mcp4725_write_powerdown, .shared = IIO_SEPARATE, }, - IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp4725_powerdown_mode_enum), - IIO_ENUM_AVAILABLE("powerdown_mode", &mcp4725_powerdown_mode_enum), + IIO_ENUM("powerdown_mode", IIO_SEPARATE, + &mcp472x_powerdown_mode_enum[MCP4725]), + IIO_ENUM_AVAILABLE("powerdown_mode", + &mcp472x_powerdown_mode_enum[MCP4725]), + { }, +}; + +static const struct iio_chan_spec_ext_info mcp4726_ext_info[] = { + { + .name = "powerdown", + .read = mcp4725_read_powerdown, + .write = mcp4725_write_powerdown, + .shared = IIO_SEPARATE, + }, + IIO_ENUM("powerdown_mode", IIO_SEPARATE, + &mcp472x_powerdown_mode_enum[MCP4726]), + IIO_ENUM_AVAILABLE("powerdown_mode", + &mcp472x_powerdown_mode_enum[MCP4726]), { }, }; -static const struct iio_chan_spec mcp4725_channel = { - .type = IIO_VOLTAGE, - .indexed = 1, - .output = 1, - .channel = 0, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), - .ext_info = mcp4725_ext_info, +static const struct iio_chan_spec mcp472x_channel[] = { + [MCP4725] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .ext_info = mcp4725_ext_info, + }, + [MCP4726] = { + .type = IIO_VOLTAGE, + .indexed = 1, + .output = 1, + .channel = 0, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), + .ext_info = mcp4726_ext_info, + }, }; static int mcp4725_set_value(struct iio_dev *indio_dev, int val) @@ -301,7 +347,7 @@ static int mcp4725_probe(struct i2c_client *client, indio_dev->dev.parent = &client->dev; indio_dev->info = &mcp4725_info; - indio_dev->channels = &mcp4725_channel; + indio_dev->channels = &mcp472x_channel[id->driver_data]; indio_dev->num_channels = 1; indio_dev->modes = INDIO_DIRECT_MODE; @@ -315,7 +361,7 @@ static int mcp4725_probe(struct i2c_client *client, } pd = (inbuf[0] >> 1) & 0x3; data->powerdown = pd > 0 ? true : false; - data->powerdown_mode = pd ? pd-1 : 2; /* 500kohm_to_gnd */ + data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */ data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4); return iio_device_register(indio_dev); @@ -328,7 +374,8 @@ static int mcp4725_remove(struct i2c_client *client) } static const struct i2c_device_id mcp4725_id[] = { - { "mcp4725", 0 }, + { "mcp4725", MCP4725 }, + { "mcp4726", MCP4726 }, { } }; MODULE_DEVICE_TABLE(i2c, mcp4725_id); @@ -345,5 +392,5 @@ static struct i2c_driver mcp4725_driver = { module_i2c_driver(mcp4725_driver); MODULE_AUTHOR("Peter Meerwald "); -MODULE_DESCRIPTION("MCP4725 12-bit DAC"); +MODULE_DESCRIPTION("MCP4725/6 12-bit DAC"); MODULE_LICENSE("GPL"); -- cgit From b11a34607ded9b3dfb1992da47ac94bdf5945d53 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 29 Dec 2015 21:44:48 -0800 Subject: iio: health: max30100: add config for LED current Allow the current for both RED and IR LEDs to be set via an device tree property setting. This is an optional setting that is useful for applications that have a known glass attenuation factor. Signed-off-by: Matt Ranostay Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/health/max30100.txt | 8 +++ drivers/iio/health/max30100.c | 81 ++++++++++++++++++++-- 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/health/max30100.txt b/Documentation/devicetree/bindings/iio/health/max30100.txt index f6fbac66ad06..295a9edfa4fd 100644 --- a/Documentation/devicetree/bindings/iio/health/max30100.txt +++ b/Documentation/devicetree/bindings/iio/health/max30100.txt @@ -11,11 +11,19 @@ Required properties: Refer to interrupt-controller/interrupts.txt for generic interrupt client node bindings. +Optional properties: + - maxim,led-current-microamp: configuration for LED current in microamperes + while the engine is running. First indexed value is the configuration for + the RED LED, and second value is for the IR LED. + + Refer to the datasheet for the allowed current values. + Example: max30100@057 { compatible = "maxim,max30100"; reg = <57>; + maxim,led-current-microamp = <24000 50000>; interrupt-parent = <&gpio1>; interrupts = <16 2>; }; diff --git a/drivers/iio/health/max30100.c b/drivers/iio/health/max30100.c index 9d1c81f91dd7..09db89359544 100644 --- a/drivers/iio/health/max30100.c +++ b/drivers/iio/health/max30100.c @@ -13,7 +13,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * TODO: allow LED current and pulse length controls via device tree properties + * TODO: enable pulse length controls via device tree properties */ #include @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,7 @@ #define MAX30100_REG_SPO2_CONFIG_1600US 0x3 #define MAX30100_REG_LED_CONFIG 0x09 +#define MAX30100_REG_LED_CONFIG_LED_MASK 0x0f #define MAX30100_REG_LED_CONFIG_RED_LED_SHIFT 4 #define MAX30100_REG_LED_CONFIG_24MA 0x07 @@ -111,6 +113,12 @@ static const struct regmap_config max30100_regmap_config = { .volatile_reg = max30100_is_volatile_reg, }; +static const unsigned int max30100_led_current_mapping[] = { + 4400, 7600, 11000, 14200, 17400, + 20800, 24000, 27100, 30600, 33800, + 37000, 40200, 43600, 46800, 50000 +}; + static const unsigned long max30100_scan_masks[] = {0x3, 0}; static const struct iio_chan_spec max30100_channels[] = { @@ -243,15 +251,76 @@ static irqreturn_t max30100_interrupt_handler(int irq, void *private) return IRQ_HANDLED; } +static int max30100_get_current_idx(unsigned int val, int *reg) +{ + int idx; + + /* LED turned off */ + if (val == 0) { + *reg = 0; + return 0; + } + + for (idx = 0; idx < ARRAY_SIZE(max30100_led_current_mapping); idx++) { + if (max30100_led_current_mapping[idx] == val) { + *reg = idx + 1; + return 0; + } + } + + return -EINVAL; +} + +static int max30100_led_init(struct max30100_data *data) +{ + struct device *dev = &data->client->dev; + struct device_node *np = dev->of_node; + unsigned int val[2]; + int reg, ret; + + ret = of_property_read_u32_array(np, "maxim,led-current-microamp", + (unsigned int *) &val, 2); + if (ret) { + /* Default to 24 mA RED LED, 50 mA IR LED */ + reg = (MAX30100_REG_LED_CONFIG_24MA << + MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) | + MAX30100_REG_LED_CONFIG_50MA; + dev_warn(dev, "no led-current-microamp set"); + + return regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, reg); + } + + /* RED LED current */ + ret = max30100_get_current_idx(val[0], ®); + if (ret) { + dev_err(dev, "invalid RED current setting %d", val[0]); + return ret; + } + + ret = regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG, + MAX30100_REG_LED_CONFIG_LED_MASK << + MAX30100_REG_LED_CONFIG_RED_LED_SHIFT, + reg << MAX30100_REG_LED_CONFIG_RED_LED_SHIFT); + if (ret) + return ret; + + /* IR LED current */ + ret = max30100_get_current_idx(val[1], ®); + if (ret) { + dev_err(dev, "invalid IR current setting %d", val[1]); + return ret; + } + + return regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG, + MAX30100_REG_LED_CONFIG_LED_MASK, reg); +} + static int max30100_chip_init(struct max30100_data *data) { int ret; - /* RED IR LED = 24mA, IR LED = 50mA */ - ret = regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, - (MAX30100_REG_LED_CONFIG_24MA << - MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) | - MAX30100_REG_LED_CONFIG_50MA); + /* setup LED current settings */ + ret = max30100_led_init(data); if (ret) return ret; -- cgit From c0559ae2fb91fc558d0eb390c17d32d6c309fb06 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Tue, 29 Dec 2015 16:57:30 +0530 Subject: Staging: iio: cdc: ad7150: Prefer using the BIT macro Replace bit shifting on 1 with the BIT(x) macro Signed-off-by: Shraddha Barke Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7150.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index e8d0ff2d5c9b..0b934f7801d5 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -21,8 +21,8 @@ */ #define AD7150_STATUS 0 -#define AD7150_STATUS_OUT1 (1 << 3) -#define AD7150_STATUS_OUT2 (1 << 5) +#define AD7150_STATUS_OUT1 BIT(3) +#define AD7150_STATUS_OUT2 BIT(5) #define AD7150_CH1_DATA_HIGH 1 #define AD7150_CH2_DATA_HIGH 3 #define AD7150_CH1_AVG_HIGH 5 @@ -36,7 +36,7 @@ #define AD7150_CH2_TIMEOUT 13 #define AD7150_CH2_SETUP 14 #define AD7150_CFG 15 -#define AD7150_CFG_FIX (1 << 7) +#define AD7150_CFG_FIX BIT(7) #define AD7150_PD_TIMER 16 #define AD7150_CH1_CAPDAC 17 #define AD7150_CH2_CAPDAC 18 -- cgit From c4f0ebd91467c701b32879bf6091e5c91c6e79c1 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Tue, 29 Dec 2015 16:57:31 +0530 Subject: Staging: iio: cdc: ad7150: Fix alignment should match open parenthesis Fix the checkpatch warning of alignment should match open parenthesis. Signed-off-by: Shraddha Barke Signed-off-by: Jonathan Cameron --- drivers/staging/iio/cdc/ad7150.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 0b934f7801d5..f6b9a10326ea 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -160,8 +160,9 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, /* lock should be held */ static int ad7150_write_event_params(struct iio_dev *indio_dev, - unsigned int chan, enum iio_event_type type, - enum iio_event_direction dir) + unsigned int chan, + enum iio_event_type type, + enum iio_event_direction dir) { int ret; u16 value; @@ -209,8 +210,9 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev, } static int ad7150_write_event_config(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, enum iio_event_type type, - enum iio_event_direction dir, int state) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, int state) { u8 thresh_type, cfg, adaptive; int ret; @@ -302,11 +304,11 @@ static int ad7150_read_event_value(struct iio_dev *indio_dev, } static int ad7150_write_event_value(struct iio_dev *indio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int val, int val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int val, int val2) { int ret; struct ad7150_chip_info *chip = iio_priv(indio_dev); @@ -365,9 +367,9 @@ static ssize_t ad7150_show_timeout(struct device *dev, } static ssize_t ad7150_store_timeout(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 ad7150_chip_info *chip = iio_priv(indio_dev); @@ -580,7 +582,7 @@ static const struct iio_info ad7150_info = { */ static int ad7150_probe(struct i2c_client *client, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { int ret; struct ad7150_chip_info *chip; -- cgit From a9fd053b56c6bb14972ab7a19da0b575fe4c5d66 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 19 Nov 2015 10:15:17 +0100 Subject: iio: st_sensors: support active-low interrupts Most ST MEMS Sensors that support interrupts can also handle sending an active low interrupt, i.e. going from high to low on data ready (or other interrupt) and thus triggering on a falling edge to the interrupt controller. Set up logic to inspect the interrupt line we get for a sensor: if it is triggering on rising edge, leave everything alone, but if it triggers on falling edges, set up active low, and if unsupported configurations appear: warn with errors and reconfigure the interrupt to a rising edge, which all interrupt generating sensors support. Create a local header for st_sensors_core.h to share functions between the sensor core and the trigger setup code. Cc: Giuseppe Barba Cc: Denis Ciocca Signed-off-by: Linus Walleij Signed-off-by: Jonathan Cameron --- drivers/iio/accel/st_accel_core.c | 16 +++++++ drivers/iio/common/st_sensors/st_sensors_core.c | 6 ++- drivers/iio/common/st_sensors/st_sensors_core.h | 8 ++++ drivers/iio/common/st_sensors/st_sensors_trigger.c | 52 +++++++++++++++++----- drivers/iio/gyro/st_gyro_core.c | 15 +++++++ drivers/iio/magnetometer/st_magn_core.c | 4 ++ drivers/iio/pressure/st_pressure_core.c | 8 ++++ include/linux/iio/common/st_sensors.h | 4 ++ 8 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 drivers/iio/common/st_sensors/st_sensors_core.h diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 70f042797f15..a03a1417dd63 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -67,6 +67,8 @@ #define ST_ACCEL_1_DRDY_IRQ_ADDR 0x22 #define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10 #define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08 +#define ST_ACCEL_1_IHL_IRQ_ADDR 0x25 +#define ST_ACCEL_1_IHL_IRQ_MASK 0x02 #define ST_ACCEL_1_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 2 */ @@ -92,6 +94,8 @@ #define ST_ACCEL_2_DRDY_IRQ_ADDR 0x22 #define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02 #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_MULTIREAD_BIT true /* CUSTOM VALUES FOR SENSOR 3 */ @@ -125,6 +129,8 @@ #define ST_ACCEL_3_DRDY_IRQ_ADDR 0x23 #define ST_ACCEL_3_DRDY_IRQ_INT1_MASK 0x80 #define ST_ACCEL_3_DRDY_IRQ_INT2_MASK 0x00 +#define ST_ACCEL_3_IHL_IRQ_ADDR 0x23 +#define ST_ACCEL_3_IHL_IRQ_MASK 0x40 #define ST_ACCEL_3_IG1_EN_ADDR 0x23 #define ST_ACCEL_3_IG1_EN_MASK 0x08 #define ST_ACCEL_3_MULTIREAD_BIT false @@ -169,6 +175,8 @@ #define ST_ACCEL_5_DRDY_IRQ_ADDR 0x22 #define ST_ACCEL_5_DRDY_IRQ_INT1_MASK 0x04 #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_IG1_EN_ADDR 0x21 #define ST_ACCEL_5_IG1_EN_MASK 0x08 #define ST_ACCEL_5_MULTIREAD_BIT false @@ -292,6 +300,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_1_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK, .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, }, .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, .bootime = 2, @@ -355,6 +365,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_2_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK, .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, }, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, .bootime = 2, @@ -430,6 +442,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_3_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK, .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, .ig1 = { .en_addr = ST_ACCEL_3_IG1_EN_ADDR, .en_mask = ST_ACCEL_3_IG1_EN_MASK, @@ -537,6 +551,8 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { .addr = ST_ACCEL_5_DRDY_IRQ_ADDR, .mask_int1 = ST_ACCEL_5_DRDY_IRQ_INT1_MASK, .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, }, .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, .bootime = 2, /* guess */ diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 8447c31e27f2..f5a2d445d0c0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -18,13 +18,15 @@ #include #include +#include "st_sensors_core.h" + static inline u32 st_sensors_get_unaligned_le24(const u8 *p) { return (s32)((p[0] | p[1] << 8 | p[2] << 16) << 8) >> 8; } -static int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, - u8 reg_addr, u8 mask, u8 data) +int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, + u8 reg_addr, u8 mask, u8 data) { int err; u8 new_data; diff --git a/drivers/iio/common/st_sensors/st_sensors_core.h b/drivers/iio/common/st_sensors/st_sensors_core.h new file mode 100644 index 000000000000..cd88098ff6f1 --- /dev/null +++ b/drivers/iio/common/st_sensors/st_sensors_core.h @@ -0,0 +1,8 @@ +/* + * Local functions in the ST Sensors core + */ +#ifndef __ST_SENSORS_CORE_H +#define __ST_SENSORS_CORE_H +int st_sensors_write_data_with_mask(struct iio_dev *indio_dev, + u8 reg_addr, u8 mask, u8 data); +#endif diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c index 3e907040c2c7..6a8c98327945 100644 --- a/drivers/iio/common/st_sensors/st_sensors_trigger.c +++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c @@ -14,32 +14,65 @@ #include #include #include - #include - +#include "st_sensors_core.h" int st_sensors_allocate_trigger(struct iio_dev *indio_dev, const struct iio_trigger_ops *trigger_ops) { - int err; + int err, irq; struct st_sensor_data *sdata = iio_priv(indio_dev); + unsigned long irq_trig; sdata->trig = iio_trigger_alloc("%s-trigger", indio_dev->name); if (sdata->trig == NULL) { - err = -ENOMEM; dev_err(&indio_dev->dev, "failed to allocate iio trigger.\n"); - goto iio_trigger_alloc_error; + return -ENOMEM; } - err = request_threaded_irq(sdata->get_irq_data_ready(indio_dev), + irq = sdata->get_irq_data_ready(indio_dev); + irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq)); + /* + * If the IRQ is triggered on falling edge, we need to mark the + * interrupt as active low, if the hardware supports this. + */ + if (irq_trig == IRQF_TRIGGER_FALLING) { + if (!sdata->sensor_settings->drdy_irq.addr_ihl) { + dev_err(&indio_dev->dev, + "falling edge specified for IRQ but hardware " + "only support rising edge, will request " + "rising edge\n"); + irq_trig = IRQF_TRIGGER_RISING; + } else { + /* Set up INT active low i.e. falling edge */ + err = st_sensors_write_data_with_mask(indio_dev, + sdata->sensor_settings->drdy_irq.addr_ihl, + sdata->sensor_settings->drdy_irq.mask_ihl, 1); + if (err < 0) + goto iio_trigger_free; + dev_info(&indio_dev->dev, + "interrupts on the falling edge\n"); + } + } else if (irq_trig == IRQF_TRIGGER_RISING) { + dev_info(&indio_dev->dev, + "interrupts on the rising edge\n"); + + } else { + dev_err(&indio_dev->dev, + "unsupported IRQ trigger specified (%lx), only " + "rising and falling edges supported, enforce " + "rising edge\n", irq_trig); + irq_trig = IRQF_TRIGGER_RISING; + } + err = request_threaded_irq(irq, iio_trigger_generic_data_rdy_poll, NULL, - IRQF_TRIGGER_RISING, + irq_trig, sdata->trig->name, sdata->trig); if (err) { dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); - goto request_irq_error; + goto iio_trigger_free; } iio_trigger_set_drvdata(sdata->trig, indio_dev); @@ -57,9 +90,8 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, iio_trigger_register_error: free_irq(sdata->get_irq_data_ready(indio_dev), sdata->trig); -request_irq_error: +iio_trigger_free: iio_trigger_free(sdata->trig); -iio_trigger_alloc_error: return err; } EXPORT_SYMBOL(st_sensors_allocate_trigger); diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c index 02eddcebeea3..110f95b6e52f 100644 --- a/drivers/iio/gyro/st_gyro_core.c +++ b/drivers/iio/gyro/st_gyro_core.c @@ -185,6 +185,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .drdy_irq = { .addr = ST_GYRO_1_DRDY_IRQ_ADDR, .mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ }, .multi_read_bit = ST_GYRO_1_MULTIREAD_BIT, .bootime = 2, @@ -248,6 +253,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .drdy_irq = { .addr = ST_GYRO_2_DRDY_IRQ_ADDR, .mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ }, .multi_read_bit = ST_GYRO_2_MULTIREAD_BIT, .bootime = 2, @@ -307,6 +317,11 @@ static const struct st_sensor_settings st_gyro_sensors_settings[] = { .drdy_irq = { .addr = ST_GYRO_3_DRDY_IRQ_ADDR, .mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK, + /* + * The sensor has IHL (active low) and open + * drain settings, but only for INT1 and not + * for the DRDY line on INT2. + */ }, .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 b27f0146647b..501f858df413 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -175,6 +175,8 @@ #define ST_MAGN_3_BDU_MASK 0x10 #define ST_MAGN_3_DRDY_IRQ_ADDR 0x62 #define ST_MAGN_3_DRDY_INT_MASK 0x01 +#define ST_MAGN_3_IHL_IRQ_ADDR 0x63 +#define ST_MAGN_3_IHL_IRQ_MASK 0x04 #define ST_MAGN_3_FS_AVL_15000_GAIN 1500 #define ST_MAGN_3_MULTIREAD_BIT false #define ST_MAGN_3_OUT_X_L_ADDR 0x68 @@ -480,6 +482,8 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { .drdy_irq = { .addr = ST_MAGN_3_DRDY_IRQ_ADDR, .mask_int1 = ST_MAGN_3_DRDY_INT_MASK, + .addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR, + .mask_ihl = ST_MAGN_3_IHL_IRQ_MASK, }, .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 b39a2fb0671c..172393ad34af 100644 --- a/drivers/iio/pressure/st_pressure_core.c +++ b/drivers/iio/pressure/st_pressure_core.c @@ -62,6 +62,8 @@ #define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22 #define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04 #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_MULTIREAD_BIT true #define ST_PRESS_LPS331AP_TEMP_OFFSET 42500 @@ -100,6 +102,8 @@ #define ST_PRESS_LPS25H_DRDY_IRQ_ADDR 0x23 #define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK 0x01 #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_MULTIREAD_BIT true #define ST_PRESS_LPS25H_TEMP_OFFSET 42500 #define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28 @@ -220,6 +224,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR, .mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK, .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, }, .multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT, .bootime = 2, @@ -304,6 +310,8 @@ static const struct st_sensor_settings st_press_sensors_settings[] = { .addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR, .mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK, .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, }, .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 2fe939c73cd2..6670c3d25c58 100644 --- a/include/linux/iio/common/st_sensors.h +++ b/include/linux/iio/common/st_sensors.h @@ -119,6 +119,8 @@ struct st_sensor_bdu { * @addr: address of the register. * @mask_int1: mask to enable/disable IRQ on INT1 pin. * @mask_int2: mask to enable/disable IRQ on INT2 pin. + * @addr_ihl: address to enable/disable active low on the INT lines. + * @mask_ihl: mask to enable/disable active low on the INT lines. * struct ig1 - represents the Interrupt Generator 1 of sensors. * @en_addr: address of the enable ig1 register. * @en_mask: mask to write the on/off value for enable. @@ -127,6 +129,8 @@ struct st_sensor_data_ready_irq { u8 addr; u8 mask_int1; u8 mask_int2; + u8 addr_ihl; + u8 mask_ihl; struct { u8 en_addr; u8 en_mask; -- cgit From f78c5f96547e6eaa894557730af3f66b8116c5c2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 5 Jan 2016 15:56:42 +0100 Subject: iio: ak8975: constify ak_def structures The ak_def structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/magnetometer/ak8975.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c index b13936dacc78..9c5c9ef3f1da 100644 --- a/drivers/iio/magnetometer/ak8975.c +++ b/drivers/iio/magnetometer/ak8975.c @@ -252,7 +252,7 @@ struct ak_def { u8 data_regs[3]; }; -static struct ak_def ak_def_array[AK_MAX_TYPE] = { +static const struct ak_def ak_def_array[AK_MAX_TYPE] = { { .type = AK8975, .raw_to_gauss = ak8975_raw_to_gauss, @@ -360,7 +360,7 @@ static struct ak_def ak_def_array[AK_MAX_TYPE] = { */ struct ak8975_data { struct i2c_client *client; - struct ak_def *def; + const struct ak_def *def; struct attribute_group attrs; struct mutex lock; u8 asa[3]; -- cgit From f872f5400cc01373d8e29d9c7a5296ccfaf4ccf3 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 29 Dec 2015 20:12:19 -0800 Subject: mm: Add a vm_special_mapping.fault() method Requiring special mappings to give a list of struct pages is inflexible: it prevents sane use of IO memory in a special mapping, it's inefficient (it requires arch code to initialize a list of struct pages, and it requires the mm core to walk the entire list just to figure out how long it is), and it prevents arch code from doing anything fancy when a special mapping fault occurs. Add a .fault method as an alternative to filling in a .pages array. Looks-OK-to: Andrew Morton Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/a26d1677c0bc7e774c33f469451a78ca31e9e6af.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- include/linux/mm_types.h | 22 +++++++++++++++++++--- mm/mmap.c | 13 +++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index f8d1492a114f..c88e48a3c155 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -568,10 +568,26 @@ static inline void clear_tlb_flush_pending(struct mm_struct *mm) } #endif -struct vm_special_mapping -{ - const char *name; +struct vm_fault; + +struct vm_special_mapping { + const char *name; /* The name, e.g. "[vdso]". */ + + /* + * If .fault is not provided, this points to a + * NULL-terminated array of pages that back the special mapping. + * + * This must not be NULL unless .fault is provided. + */ struct page **pages; + + /* + * If non-NULL, then this is called to resolve page faults + * on the special mapping. If used, .pages is not checked. + */ + int (*fault)(const struct vm_special_mapping *sm, + struct vm_area_struct *vma, + struct vm_fault *vmf); }; enum tlb_flush_reason { diff --git a/mm/mmap.c b/mm/mmap.c index 2ce04a649f6b..f717453b1a57 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -3030,11 +3030,16 @@ static int special_mapping_fault(struct vm_area_struct *vma, pgoff_t pgoff; struct page **pages; - if (vma->vm_ops == &legacy_special_mapping_vmops) + if (vma->vm_ops == &legacy_special_mapping_vmops) { pages = vma->vm_private_data; - else - pages = ((struct vm_special_mapping *)vma->vm_private_data)-> - pages; + } else { + struct vm_special_mapping *sm = vma->vm_private_data; + + if (sm->fault) + return sm->fault(sm, vma, vmf); + + pages = sm->pages; + } for (pgoff = vmf->pgoff; pgoff && *pages; ++pages) pgoff--; -- cgit From 1745cbc5d0dee0749a6bc0ea8e872c5db0074061 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 29 Dec 2015 20:12:20 -0800 Subject: mm: Add vm_insert_pfn_prot() The x86 vvar vma contains pages with differing cacheability flags. x86 currently implements this by manually inserting all the ptes using (io_)remap_pfn_range when the vma is set up. x86 wants to move to using .fault with VM_FAULT_NOPAGE to set up the mappings as needed. The correct API to use to insert a pfn in .fault is vm_insert_pfn(), but vm_insert_pfn() can't override the vma's cache mode, and the HPET page in particular needs to be uncached despite the fact that the rest of the VMA is cached. Add vm_insert_pfn_prot() to support varying cacheability within the same non-COW VMA in a more sane manner. x86 could alternatively use multiple VMAs, but that's messy, would break CRIU, and would create unnecessary VMAs that would waste memory. Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Acked-by: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/d2938d1eb37be7a5e4f86182db646551f11e45aa.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- include/linux/mm.h | 2 ++ mm/memory.c | 25 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 00bad7793788..87ef1d7730ba 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2080,6 +2080,8 @@ int remap_pfn_range(struct vm_area_struct *, unsigned long addr, int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *); int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); +int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, pgprot_t pgprot); int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len); diff --git a/mm/memory.c b/mm/memory.c index c387430f06c3..a29f0b90fc56 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1563,9 +1563,30 @@ out: */ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) +{ + return vm_insert_pfn_prot(vma, addr, pfn, vma->vm_page_prot); +} +EXPORT_SYMBOL(vm_insert_pfn); + +/** + * vm_insert_pfn_prot - insert single pfn into user vma with specified pgprot + * @vma: user vma to map to + * @addr: target user address of this page + * @pfn: source kernel pfn + * @pgprot: pgprot flags for the inserted page + * + * This is exactly like vm_insert_pfn, except that it allows drivers to + * to override pgprot on a per-page basis. + * + * This only makes sense for IO mappings, and it makes no sense for + * cow mappings. In general, using multiple vmas is preferable; + * vm_insert_pfn_prot should only be used if using multiple VMAs is + * impractical. + */ +int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, pgprot_t pgprot) { int ret; - pgprot_t pgprot = vma->vm_page_prot; /* * Technically, architectures with pte_special can avoid all these * restrictions (same for remap_pfn_range). However we would like @@ -1587,7 +1608,7 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr, return ret; } -EXPORT_SYMBOL(vm_insert_pfn); +EXPORT_SYMBOL(vm_insert_pfn_prot); int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn) -- cgit From 352b78c62f27b356b182008acd3117f3ee03ffd2 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 29 Dec 2015 20:12:21 -0800 Subject: x86/vdso: Track each mm's loaded vDSO image as well as its base As we start to do more intelligent things with the vDSO at runtime (as opposed to just at mm initialization time), we'll need to know which vDSO is in use. In principle, we could guess based on the mm type, but that's over-complicated and error-prone. Instead, just track it in the mmu context. Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/c99ac48681bad709ca7ad5ee899d9042a3af6b00.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/vdso/vma.c | 1 + arch/x86/include/asm/mmu.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index b8f69e264ac4..80b021067bd6 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -121,6 +121,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr) text_start = addr - image->sym_vvar_start; current->mm->context.vdso = (void __user *)text_start; + current->mm->context.vdso_image = image; /* * MAYWRITE to allow gdb to COW and set breakpoints diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 55234d5e7160..1ea0baef1175 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -19,7 +19,8 @@ typedef struct { #endif struct mutex lock; - void __user *vdso; + void __user *vdso; /* vdso base address */ + const struct vdso_image *vdso_image; /* vdso image in use */ atomic_t perf_rdpmc_allowed; /* nonzero if rdpmc is allowed */ } mm_context_t; -- cgit From 05ef76b20fc4297b0d3f8a956f1c809a8a1b3f1d Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 29 Dec 2015 20:12:22 -0800 Subject: x86/vdso: Use .fault for the vDSO text mapping The old scheme for mapping the vDSO text is rather complicated. vdso2c generates a struct vm_special_mapping and a blank .pages array of the correct size for each vdso image. Init code in vdso/vma.c populates the .pages array for each vDSO image, and the mapping code selects the appropriate struct vm_special_mapping. With .fault, we can use a less roundabout approach: vdso_fault() just returns the appropriate page for the selected vDSO image. Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/f886954c186bafd74e1b967c8931d852ae199aa2.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/vdso/vdso2c.h | 7 ------- arch/x86/entry/vdso/vma.c | 26 +++++++++++++++++++------- arch/x86/include/asm/vdso.h | 3 --- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/arch/x86/entry/vdso/vdso2c.h b/arch/x86/entry/vdso/vdso2c.h index 0224987556ce..abe961c7c71c 100644 --- a/arch/x86/entry/vdso/vdso2c.h +++ b/arch/x86/entry/vdso/vdso2c.h @@ -150,16 +150,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, } fprintf(outfile, "\n};\n\n"); - fprintf(outfile, "static struct page *pages[%lu];\n\n", - mapping_size / 4096); - fprintf(outfile, "const struct vdso_image %s = {\n", name); fprintf(outfile, "\t.data = raw_data,\n"); fprintf(outfile, "\t.size = %lu,\n", mapping_size); - fprintf(outfile, "\t.text_mapping = {\n"); - fprintf(outfile, "\t\t.name = \"[vdso]\",\n"); - fprintf(outfile, "\t\t.pages = pages,\n"); - fprintf(outfile, "\t},\n"); if (alt_sec) { fprintf(outfile, "\t.alt = %lu,\n", (unsigned long)GET_LE(&alt_sec->sh_offset)); diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 80b021067bd6..eb50d7c1f161 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -27,13 +27,7 @@ unsigned int __read_mostly vdso64_enabled = 1; void __init init_vdso_image(const struct vdso_image *image) { - int i; - int npages = (image->size) / PAGE_SIZE; - BUG_ON(image->size % PAGE_SIZE != 0); - for (i = 0; i < npages; i++) - image->text_mapping.pages[i] = - virt_to_page(image->data + i*PAGE_SIZE); apply_alternatives((struct alt_instr *)(image->data + image->alt), (struct alt_instr *)(image->data + image->alt + @@ -90,6 +84,24 @@ static unsigned long vdso_addr(unsigned long start, unsigned len) #endif } +static int vdso_fault(const struct vm_special_mapping *sm, + struct vm_area_struct *vma, struct vm_fault *vmf) +{ + const struct vdso_image *image = vma->vm_mm->context.vdso_image; + + if (!image || (vmf->pgoff << PAGE_SHIFT) >= image->size) + return VM_FAULT_SIGBUS; + + vmf->page = virt_to_page(image->data + (vmf->pgoff << PAGE_SHIFT)); + get_page(vmf->page); + return 0; +} + +static const struct vm_special_mapping text_mapping = { + .name = "[vdso]", + .fault = vdso_fault, +}; + static int map_vdso(const struct vdso_image *image, bool calculate_addr) { struct mm_struct *mm = current->mm; @@ -131,7 +143,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr) image->size, VM_READ|VM_EXEC| VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, - &image->text_mapping); + &text_mapping); if (IS_ERR(vma)) { ret = PTR_ERR(vma); diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index deabaf9759b6..43dc55be524e 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h @@ -13,9 +13,6 @@ struct vdso_image { void *data; unsigned long size; /* Always a multiple of PAGE_SIZE */ - /* text_mapping.pages is big enough for data/size page pointers */ - struct vm_special_mapping text_mapping; - unsigned long alt, alt_len; long sym_vvar_start; /* Negative offset to the vvar area */ -- cgit From a48a7042613eb1524d18b7b1ed7d3a6b611fd21f Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 29 Dec 2015 20:12:23 -0800 Subject: x86/vdso: Use ->fault() instead of remap_pfn_range() for the vvar mapping This is IMO much less ugly, and it also opens the door to disallowing unprivileged userspace HPET access on systems with usable TSCs. Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/c19c2909e5ee3c3d8742f916586676bb7c40345f.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/vdso/vma.c | 97 ++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 40 deletions(-) diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index eb50d7c1f161..4b5461ba4f6b 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -102,18 +102,69 @@ static const struct vm_special_mapping text_mapping = { .fault = vdso_fault, }; +static int vvar_fault(const struct vm_special_mapping *sm, + struct vm_area_struct *vma, struct vm_fault *vmf) +{ + const struct vdso_image *image = vma->vm_mm->context.vdso_image; + long sym_offset; + int ret = -EFAULT; + + if (!image) + return VM_FAULT_SIGBUS; + + sym_offset = (long)(vmf->pgoff << PAGE_SHIFT) + + image->sym_vvar_start; + + /* + * Sanity check: a symbol offset of zero means that the page + * does not exist for this vdso image, not that the page is at + * offset zero relative to the text mapping. This should be + * impossible here, because sym_offset should only be zero for + * the page past the end of the vvar mapping. + */ + if (sym_offset == 0) + return VM_FAULT_SIGBUS; + + 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) { + 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(); + if (pvti) { + ret = vm_insert_pfn( + vma, + (unsigned long)vmf->virtual_address, + __pa(pvti) >> PAGE_SHIFT); + } + } + + if (ret == 0 || ret == -EBUSY) + return VM_FAULT_NOPAGE; + + return VM_FAULT_SIGBUS; +} + static int map_vdso(const struct vdso_image *image, bool calculate_addr) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; unsigned long addr, text_start; int ret = 0; - static struct page *no_pages[] = {NULL}; - static struct vm_special_mapping vvar_mapping = { + static const struct vm_special_mapping vvar_mapping = { .name = "[vvar]", - .pages = no_pages, + .fault = vvar_fault, }; - struct pvclock_vsyscall_time_info *pvti; if (calculate_addr) { addr = vdso_addr(current->mm->start_stack, @@ -153,7 +204,8 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr) vma = _install_special_mapping(mm, addr, -image->sym_vvar_start, - VM_READ|VM_MAYREAD, + VM_READ|VM_MAYREAD|VM_IO|VM_DONTDUMP| + VM_PFNMAP, &vvar_mapping); if (IS_ERR(vma)) { @@ -161,41 +213,6 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr) goto up_fail; } - if (image->sym_vvar_page) - ret = remap_pfn_range(vma, - text_start + image->sym_vvar_page, - __pa_symbol(&__vvar_page) >> PAGE_SHIFT, - PAGE_SIZE, - PAGE_READONLY); - - if (ret) - goto up_fail; - -#ifdef CONFIG_HPET_TIMER - if (hpet_address && image->sym_hpet_page) { - ret = io_remap_pfn_range(vma, - text_start + image->sym_hpet_page, - hpet_address >> PAGE_SHIFT, - PAGE_SIZE, - pgprot_noncached(PAGE_READONLY)); - - if (ret) - goto up_fail; - } -#endif - - pvti = pvclock_pvti_cpu0_va(); - if (pvti && image->sym_pvclock_page) { - ret = remap_pfn_range(vma, - text_start + image->sym_pvclock_page, - __pa(pvti) >> PAGE_SHIFT, - PAGE_SIZE, - PAGE_READONLY); - - if (ret) - goto up_fail; - } - up_fail: if (ret) current->mm->context.vdso = NULL; -- cgit From bd902c536298830e4d126dcf6491b46d3f1bf96e Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 29 Dec 2015 20:12:24 -0800 Subject: x86/vdso: Disallow vvar access to vclock IO for never-used vclocks It makes me uncomfortable that even modern systems grant every process direct read access to the HPET. While fixing this for real without regressing anything is a mess (unmapping the HPET is tricky because we don't adequately track all the mappings), we can do almost as well by tracking which vclocks have ever been used and only allowing pages associated with used vclocks to be faulted in. This will cause rogue programs that try to peek at the HPET to get SIGBUS instead on most systems. We can't restrict faults to vclock pages that are associated with the currently selected vclock due to a race: a process could start to access the HPET for the first time and race against a switch away from the HPET as the current clocksource. We can't segfault the process trying to peek at the HPET in this case, even though the process isn't going to do anything useful with the data. Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/e79d06295625c02512277737ab55085a498ac5d8.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/vdso/vma.c | 4 ++-- arch/x86/entry/vsyscall/vsyscall_gtod.c | 9 ++++++++- arch/x86/include/asm/clocksource.h | 9 +++++---- arch/x86/include/asm/vgtod.h | 6 ++++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 4b5461ba4f6b..7c912fefe79b 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -130,7 +130,7 @@ static int vvar_fault(const struct vm_special_mapping *sm, __pa_symbol(&__vvar_page) >> PAGE_SHIFT); } else if (sym_offset == image->sym_hpet_page) { #ifdef CONFIG_HPET_TIMER - if (hpet_address) { + if (hpet_address && vclock_was_used(VCLOCK_HPET)) { ret = vm_insert_pfn_prot( vma, (unsigned long)vmf->virtual_address, @@ -141,7 +141,7 @@ static int vvar_fault(const struct vm_special_mapping *sm, } else if (sym_offset == image->sym_pvclock_page) { struct pvclock_vsyscall_time_info *pvti = pvclock_pvti_cpu0_va(); - if (pvti) { + if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) { ret = vm_insert_pfn( vma, (unsigned long)vmf->virtual_address, diff --git a/arch/x86/entry/vsyscall/vsyscall_gtod.c b/arch/x86/entry/vsyscall/vsyscall_gtod.c index 51e330416995..0fb3a104ac62 100644 --- a/arch/x86/entry/vsyscall/vsyscall_gtod.c +++ b/arch/x86/entry/vsyscall/vsyscall_gtod.c @@ -16,6 +16,8 @@ #include #include +int vclocks_used __read_mostly; + DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data); void update_vsyscall_tz(void) @@ -26,12 +28,17 @@ void update_vsyscall_tz(void) void update_vsyscall(struct timekeeper *tk) { + int vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode; struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data; + /* Mark the new vclock used. */ + BUILD_BUG_ON(VCLOCK_MAX >= 32); + WRITE_ONCE(vclocks_used, READ_ONCE(vclocks_used) | (1 << vclock_mode)); + gtod_write_begin(vdata); /* copy vsyscall data */ - vdata->vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode; + vdata->vclock_mode = vclock_mode; vdata->cycle_last = tk->tkr_mono.cycle_last; vdata->mask = tk->tkr_mono.mask; vdata->mult = tk->tkr_mono.mult; diff --git a/arch/x86/include/asm/clocksource.h b/arch/x86/include/asm/clocksource.h index eda81dc0f4ae..d194266acb28 100644 --- a/arch/x86/include/asm/clocksource.h +++ b/arch/x86/include/asm/clocksource.h @@ -3,10 +3,11 @@ #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_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 struct arch_clocksource_data { int vclock_mode; diff --git a/arch/x86/include/asm/vgtod.h b/arch/x86/include/asm/vgtod.h index f556c4843aa1..e728699db774 100644 --- a/arch/x86/include/asm/vgtod.h +++ b/arch/x86/include/asm/vgtod.h @@ -37,6 +37,12 @@ struct vsyscall_gtod_data { }; extern struct vsyscall_gtod_data vsyscall_gtod_data; +extern int vclocks_used; +static inline bool vclock_was_used(int vclock) +{ + return READ_ONCE(vclocks_used) & (1 << vclock); +} + static inline unsigned gtod_read_begin(const struct vsyscall_gtod_data *s) { unsigned ret; -- cgit From c62db3d5abf89ca5502c7fe1f869c2862e48336d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 12 Jan 2016 15:53:46 +0800 Subject: ASoC: rt5659: Staticise rt5659_i2c_shutdown Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 820d8fa62b5e..47c717f4964a 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -4184,7 +4184,7 @@ static int rt5659_i2c_remove(struct i2c_client *i2c) return 0; } -void rt5659_i2c_shutdown(struct i2c_client *client) +static void rt5659_i2c_shutdown(struct i2c_client *client) { struct rt5659_priv *rt5659 = i2c_get_clientdata(client); -- cgit From c799ba6eab7a1bf02792e2ced933be3ae5f8daa2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 11 Dec 2015 15:31:10 +0100 Subject: cfg80211: remove CFG80211_REG_DEBUG Instead of having this Kconfig option, which just *floods* the kernel log, * remove the per-channel prints that are fairly useless anyway * convert the conditional printing to pr_debug() Signed-off-by: Johannes Berg --- net/wireless/Kconfig | 13 ------ net/wireless/reg.c | 122 ++++++++++++++------------------------------------- 2 files changed, 34 insertions(+), 101 deletions(-) diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index da72ed32f143..ec3bf30dd526 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -61,19 +61,6 @@ config CFG80211_DEVELOPER_WARNINGS on it (or mac80211). -config CFG80211_REG_DEBUG - bool "cfg80211 regulatory debugging" - depends on CFG80211 - default n - ---help--- - You can enable this if you want to debug regulatory changes. - For more information on cfg80211 regulatory refer to the wireless - wiki: - - http://wireless.kernel.org/en/developers/Regulatory - - If unsure, say N. - config CFG80211_CERTIFICATION_ONUS bool "cfg80211 certification onus" depends on CFG80211 && EXPERT diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b0ce1c484a3..bc76b281ed3a 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -60,13 +60,6 @@ #include "regdb.h" #include "nl80211.h" -#ifdef CONFIG_CFG80211_REG_DEBUG -#define REG_DBG_PRINT(format, args...) \ - printk(KERN_DEBUG pr_fmt(format), ##args) -#else -#define REG_DBG_PRINT(args...) -#endif - /* * Grace period we give before making sure all current interfaces reside on * channels allowed by the current regulatory domain. @@ -178,12 +171,10 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy) if (wiphy_regd->dfs_region == regd->dfs_region) goto out; - REG_DBG_PRINT("%s: device specific dfs_region " - "(%s) disagrees with cfg80211's " - "central dfs_region (%s)\n", - dev_name(&wiphy->dev), - reg_dfs_region_str(wiphy_regd->dfs_region), - reg_dfs_region_str(regd->dfs_region)); + pr_debug("%s: device specific dfs_region (%s) disagrees with cfg80211's central dfs_region (%s)\n", + dev_name(&wiphy->dev), + reg_dfs_region_str(wiphy_regd->dfs_region), + reg_dfs_region_str(regd->dfs_region)); out: return regd->dfs_region; @@ -541,7 +532,7 @@ static DECLARE_DELAYED_WORK(crda_timeout, crda_timeout_work); static void crda_timeout_work(struct work_struct *work) { - REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); + pr_debug("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); rtnl_lock(); reg_crda_timeouts++; restore_regulatory_settings(true); @@ -583,7 +574,7 @@ static int call_crda(const char *alpha2) if (!is_world_regdom((char *) alpha2)) pr_debug("Calling CRDA for country: %c%c\n", - alpha2[0], alpha2[1]); + alpha2[0], alpha2[1]); else pr_debug("Calling CRDA to update world regulatory domain\n"); @@ -1130,42 +1121,6 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator) } EXPORT_SYMBOL(reg_initiator_name); -static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, - struct ieee80211_channel *chan, - const struct ieee80211_reg_rule *reg_rule) -{ -#ifdef CONFIG_CFG80211_REG_DEBUG - const struct ieee80211_power_rule *power_rule; - const struct ieee80211_freq_range *freq_range; - char max_antenna_gain[32], bw[32]; - - power_rule = ®_rule->power_rule; - freq_range = ®_rule->freq_range; - - if (!power_rule->max_antenna_gain) - snprintf(max_antenna_gain, sizeof(max_antenna_gain), "N/A"); - else - snprintf(max_antenna_gain, sizeof(max_antenna_gain), "%d mBi", - power_rule->max_antenna_gain); - - if (reg_rule->flags & NL80211_RRF_AUTO_BW) - snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO", - freq_range->max_bandwidth_khz, - reg_get_max_bandwidth(regd, reg_rule)); - else - snprintf(bw, sizeof(bw), "%d KHz", - freq_range->max_bandwidth_khz); - - REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n", - chan->center_freq); - - REG_DBG_PRINT("(%d KHz - %d KHz @ %s), (%s, %d mBm)\n", - freq_range->start_freq_khz, freq_range->end_freq_khz, - bw, max_antenna_gain, - power_rule->max_eirp); -#endif -} - static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd, const struct ieee80211_reg_rule *reg_rule, const struct ieee80211_channel *chan) @@ -1240,20 +1195,19 @@ static void handle_channel(struct wiphy *wiphy, if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && request_wiphy->regulatory_flags & REGULATORY_STRICT_REG) { - REG_DBG_PRINT("Disabling freq %d MHz for good\n", - chan->center_freq); + pr_debug("Disabling freq %d MHz for good\n", + chan->center_freq); chan->orig_flags |= IEEE80211_CHAN_DISABLED; chan->flags = chan->orig_flags; } else { - REG_DBG_PRINT("Disabling freq %d MHz\n", - chan->center_freq); + pr_debug("Disabling freq %d MHz\n", + chan->center_freq); chan->flags |= IEEE80211_CHAN_DISABLED; } return; } regd = reg_get_regdomain(wiphy); - chan_reg_rule_print_dbg(regd, chan, reg_rule); power_rule = ®_rule->power_rule; bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan); @@ -1391,18 +1345,15 @@ static bool ignore_reg_update(struct wiphy *wiphy, return true; if (!lr) { - REG_DBG_PRINT("Ignoring regulatory request set by %s " - "since last_request is not set\n", - reg_initiator_name(initiator)); + pr_debug("Ignoring regulatory request set by %s since last_request is not set\n", + reg_initiator_name(initiator)); return true; } if (initiator == NL80211_REGDOM_SET_BY_CORE && wiphy->regulatory_flags & REGULATORY_CUSTOM_REG) { - REG_DBG_PRINT("Ignoring regulatory request set by %s " - "since the driver uses its own custom " - "regulatory domain\n", - reg_initiator_name(initiator)); + pr_debug("Ignoring regulatory request set by %s since the driver uses its own custom regulatory domain\n", + reg_initiator_name(initiator)); return true; } @@ -1413,10 +1364,8 @@ static bool ignore_reg_update(struct wiphy *wiphy, if (wiphy_strict_alpha2_regd(wiphy) && !wiphy->regd && initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && !is_world_regdom(lr->alpha2)) { - REG_DBG_PRINT("Ignoring regulatory request set by %s " - "since the driver requires its own regulatory " - "domain to be set first\n", - reg_initiator_name(initiator)); + pr_debug("Ignoring regulatory request set by %s since the driver requires its own regulatory domain to be set first\n", + reg_initiator_name(initiator)); return true; } @@ -1697,7 +1646,7 @@ static void reg_check_chans_work(struct work_struct *work) { struct cfg80211_registered_device *rdev; - REG_DBG_PRINT("Verifying active interfaces after reg change\n"); + pr_debug("Verifying active interfaces after reg change\n"); rtnl_lock(); list_for_each_entry(rdev, &cfg80211_rdev_list, list) @@ -1779,8 +1728,8 @@ static void handle_channel_custom(struct wiphy *wiphy, } if (IS_ERR(reg_rule)) { - REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n", - chan->center_freq); + pr_debug("Disabling freq %d MHz as custom regd has no rule that fits it\n", + chan->center_freq); if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) { chan->flags |= IEEE80211_CHAN_DISABLED; } else { @@ -1790,8 +1739,6 @@ static void handle_channel_custom(struct wiphy *wiphy, return; } - chan_reg_rule_print_dbg(regd, chan, reg_rule); - power_rule = ®_rule->power_rule; bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan); @@ -2522,7 +2469,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) if (is_user_regdom_saved()) { /* Unless we're asked to ignore it and reset it */ if (reset_user) { - REG_DBG_PRINT("Restoring regulatory settings including user preference\n"); + pr_debug("Restoring regulatory settings including user preference\n"); user_alpha2[0] = '9'; user_alpha2[1] = '7'; @@ -2532,24 +2479,24 @@ static void restore_alpha2(char *alpha2, bool reset_user) * back as they were for a full restore. */ if (!is_world_regdom(ieee80211_regdom)) { - REG_DBG_PRINT("Keeping preference on module parameter ieee80211_regdom: %c%c\n", - ieee80211_regdom[0], ieee80211_regdom[1]); + pr_debug("Keeping preference on module parameter ieee80211_regdom: %c%c\n", + ieee80211_regdom[0], ieee80211_regdom[1]); alpha2[0] = ieee80211_regdom[0]; alpha2[1] = ieee80211_regdom[1]; } } else { - REG_DBG_PRINT("Restoring regulatory settings while preserving user preference for: %c%c\n", - user_alpha2[0], user_alpha2[1]); + pr_debug("Restoring regulatory settings while preserving user preference for: %c%c\n", + user_alpha2[0], user_alpha2[1]); alpha2[0] = user_alpha2[0]; alpha2[1] = user_alpha2[1]; } } else if (!is_world_regdom(ieee80211_regdom)) { - REG_DBG_PRINT("Keeping preference on module parameter ieee80211_regdom: %c%c\n", - ieee80211_regdom[0], ieee80211_regdom[1]); + pr_debug("Keeping preference on module parameter ieee80211_regdom: %c%c\n", + ieee80211_regdom[0], ieee80211_regdom[1]); alpha2[0] = ieee80211_regdom[0]; alpha2[1] = ieee80211_regdom[1]; } else - REG_DBG_PRINT("Restoring regulatory settings\n"); + pr_debug("Restoring regulatory settings\n"); } static void restore_custom_reg_settings(struct wiphy *wiphy) @@ -2661,14 +2608,14 @@ static void restore_regulatory_settings(bool reset_user) list_splice_tail_init(&tmp_reg_req_list, ®_requests_list); spin_unlock(®_requests_lock); - REG_DBG_PRINT("Kicking the queue\n"); + pr_debug("Kicking the queue\n"); schedule_work(®_work); } void regulatory_hint_disconnect(void) { - REG_DBG_PRINT("All devices are disconnected, going to restore regulatory settings\n"); + pr_debug("All devices are disconnected, going to restore regulatory settings\n"); restore_regulatory_settings(false); } @@ -2716,10 +2663,10 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy, if (!reg_beacon) return -ENOMEM; - REG_DBG_PRINT("Found new beacon on frequency: %d MHz (Ch %d) on %s\n", - beacon_chan->center_freq, - ieee80211_frequency_to_channel(beacon_chan->center_freq), - wiphy_name(wiphy)); + pr_debug("Found new beacon on frequency: %d MHz (Ch %d) on %s\n", + beacon_chan->center_freq, + ieee80211_frequency_to_channel(beacon_chan->center_freq), + wiphy_name(wiphy)); memcpy(®_beacon->chan, beacon_chan, sizeof(struct ieee80211_channel)); @@ -2798,8 +2745,7 @@ bool reg_supported_dfs_region(enum nl80211_dfs_regions dfs_region) case NL80211_DFS_JP: return true; default: - REG_DBG_PRINT("Ignoring uknown DFS master region: %d\n", - dfs_region); + pr_debug("Ignoring uknown DFS master region: %d\n", dfs_region); return false; } } -- cgit From 23a1f8d44c0bca48f04fc2a2f1edafd826ce6133 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 8 Dec 2015 16:04:31 +0200 Subject: mac80211: process and save VHT MU-MIMO group frame The Group ID Management frame is an Action frame of category VHT. It is transmitted by the AP to assign or change the user position of a STA for one or more group IDs. Process and save the group membership data. Notify underlying driver of changes. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 7 +++++++ include/net/mac80211.h | 17 +++++++++++++++++ net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/iface.c | 10 ++++++++++ net/mac80211/mlme.c | 7 +++++++ net/mac80211/rx.c | 5 +++++ net/mac80211/util.c | 3 +++ net/mac80211/vht.c | 25 +++++++++++++++++++++++++ 8 files changed, 76 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 452c0b0d2f32..d9ddb89533a7 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -843,6 +843,8 @@ enum ieee80211_vht_opmode_bits { }; #define WLAN_SA_QUERY_TR_ID_LEN 2 +#define WLAN_MEMBERSHIP_LEN 8 +#define WLAN_USER_POSITION_LEN 16 /** * struct ieee80211_tpc_report_ie @@ -989,6 +991,11 @@ struct ieee80211_mgmt { u8 action_code; u8 operating_mode; } __packed vht_opmode_notif; + struct { + u8 action_code; + u8 membership[WLAN_MEMBERSHIP_LEN]; + u8 position[WLAN_USER_POSITION_LEN]; + } __packed vht_group_notif; struct { u8 action_code; u8 dialog_token; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7c30faff245f..8da483b2c067 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -298,6 +298,7 @@ struct ieee80211_vif_chanctx_switch { * note that this is only called when it changes after the channel * context had been assigned. * @BSS_CHANGED_OCB: OCB join status changed + * @BSS_CHANGED_MU_GROUPS: VHT MU-MIMO group id or user position changed */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -323,6 +324,7 @@ enum ieee80211_bss_change { BSS_CHANGED_BEACON_INFO = 1<<20, BSS_CHANGED_BANDWIDTH = 1<<21, BSS_CHANGED_OCB = 1<<22, + BSS_CHANGED_MU_GROUPS = 1<<23, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -435,6 +437,19 @@ struct ieee80211_event { } u; }; +/** + * struct ieee80211_mu_group_data - STA's VHT MU-MIMO group data + * + * This structure describes the group id data of VHT MU-MIMO + * + * @membership: 64 bits array - a bit is set if station is member of the group + * @position: 2 bits per group id indicating the position in the group + */ +struct ieee80211_mu_group_data { + u8 membership[WLAN_MEMBERSHIP_LEN]; + u8 position[WLAN_USER_POSITION_LEN]; +}; + /** * struct ieee80211_bss_conf - holds the BSS's changing parameters * @@ -477,6 +492,7 @@ struct ieee80211_event { * @enable_beacon: whether beaconing should be enabled or not * @chandef: Channel definition for this BSS -- the hardware might be * configured a higher bandwidth than this BSS uses, for example. + * @mu_group: VHT MU-MIMO group membership data * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation. * This field is only valid when the channel is a wide HT/VHT channel. * Note that with TDLS this can be the case (channel is HT, protection must @@ -535,6 +551,7 @@ struct ieee80211_bss_conf { s32 cqm_rssi_thold; u32 cqm_rssi_hyst; struct cfg80211_chan_def chandef; + struct ieee80211_mu_group_data mu_group; __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; int arp_addr_cnt; bool qos; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b84f6aa32c08..747402d8c7a9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1714,6 +1714,8 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta); enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); void ieee80211_sta_set_rx_nss(struct sta_info *sta); +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); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index c9e325d2e120..33ae3c81bfc5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1271,6 +1271,16 @@ static void ieee80211_iface_work(struct work_struct *work) } } mutex_unlock(&local->sta_mtx); + } else if (ieee80211_is_action(mgmt->frame_control) && + mgmt->u.action.category == WLAN_CATEGORY_VHT) { + switch (mgmt->u.action.u.vht_group_notif.action_code) { + case WLAN_VHT_ACTION_GROUPID_MGMT: + ieee80211_process_mu_groups(sdata, mgmt); + break; + default: + WARN_ON(1); + break; + } } else if (ieee80211_is_data_qos(mgmt->frame_control)) { struct ieee80211_hdr *hdr = (void *)mgmt; /* diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 1c342e2592c4..31d5881b31fa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2079,6 +2079,13 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); memset(&ifmgd->vht_capa, 0, sizeof(ifmgd->vht_capa)); memset(&ifmgd->vht_capa_mask, 0, sizeof(ifmgd->vht_capa_mask)); + + /* reset MU-MIMO ownership and group data */ + memset(sdata->vif.bss_conf.mu_group.membership, 0, + sizeof(sdata->vif.bss_conf.mu_group.membership)); + memset(sdata->vif.bss_conf.mu_group.position, 0, + sizeof(sdata->vif.bss_conf.mu_group.position)); + changed |= BSS_CHANGED_MU_GROUPS; sdata->flags &= ~IEEE80211_SDATA_MU_MIMO_OWNER; sdata->ap_power_level = IEEE80211_UNSET_POWER_LEVEL; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bc081850ac0e..a5668b54015f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2738,6 +2738,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) opmode, status->band); goto handled; } + case WLAN_VHT_ACTION_GROUPID_MGMT: { + if (len < IEEE80211_MIN_ACTION_SIZE + 25) + goto invalid; + goto queue; + } default: break; } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3943d4bf289c..f4b2c04e7d81 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1928,6 +1928,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) BSS_CHANGED_IDLE | BSS_CHANGED_TXPOWER; + if (sdata->flags & IEEE80211_SDATA_MU_MIMO_OWNER) + changed |= BSS_CHANGED_MU_GROUPS; + switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: changed |= BSS_CHANGED_ASSOC | diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index c38b2f07a919..050de08bf82e 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -1,6 +1,9 @@ /* * VHT handling * + * Portions of this file + * Copyright(c) 2015 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 * published by the Free Software Foundation. @@ -425,6 +428,28 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, return changed; } +void ieee80211_process_mu_groups(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt) +{ + struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; + + if (!(sdata->flags & IEEE80211_SDATA_MU_MIMO_OWNER)) + return; + + if (!memcmp(mgmt->u.action.u.vht_group_notif.position, + bss_conf->mu_group.position, WLAN_USER_POSITION_LEN) && + !memcmp(mgmt->u.action.u.vht_group_notif.membership, + bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN)) + return; + + memcpy(mgmt->u.action.u.vht_group_notif.membership, + bss_conf->mu_group.membership, WLAN_MEMBERSHIP_LEN); + memcpy(mgmt->u.action.u.vht_group_notif.position, + bss_conf->mu_group.position, WLAN_USER_POSITION_LEN); + + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS); +} + void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, struct sta_info *sta, u8 opmode, enum ieee80211_band band) -- cgit From f9cfa5f354b11e56cd8f019c12e14a42585586cd Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 8 Dec 2015 16:04:33 +0200 Subject: mac80211: add flag for duplication check Add an option for driver to check for packet duplication by itself. This is needed for example by the iwlwifi driver which parallelizes the RX path and does the duplication check per queue. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/mac80211.h | 2 +- net/mac80211/rx.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 8da483b2c067..ecab934dc8d9 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1063,7 +1063,7 @@ enum mac80211_rx_flags { RX_FLAG_HT_GF = BIT(13), RX_FLAG_AMPDU_DETAILS = BIT(14), RX_FLAG_PN_VALIDATED = BIT(15), - /* bit 16 free */ + RX_FLAG_DUP_VALIDATED = BIT(16), RX_FLAG_AMPDU_LAST_KNOWN = BIT(17), RX_FLAG_AMPDU_IS_LAST = BIT(18), RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19), diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a5668b54015f..fe675d76f29c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1099,6 +1099,9 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + if (status->flag & RX_FLAG_DUP_VALIDATED) + return RX_CONTINUE; + /* * Drop duplicate 802.11 retransmissions * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery") -- cgit From fad471860c097844432c7cf5d3ae6a0a059c2bdc Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 8 Dec 2015 16:04:34 +0200 Subject: mac80211: pass RX aggregation window size to driver Currently mac80211 does not inform the driver of the window size when starting an RX aggregation session. To enable managing the reorder buffer in the driver or hardware the window size is needed. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- include/net/mac80211.h | 8 +++++--- net/mac80211/agg-rx.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index ecab934dc8d9..a990338a766e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3047,9 +3047,11 @@ enum ieee80211_reconfig_type { * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) * is the first frame we expect to perform the action on. Notice * that TX/RX_STOP can pass NULL for this parameter. - * The @buf_size parameter is only valid when the action is set to - * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder - * buffer size (number of subframes) for this session -- the driver + * The @buf_size parameter is valid only when the action is set to + * %IEEE80211_AMPDU_RX_START or %IEEE80211_AMPDU_TX_OPERATIONAL and + * indicates the reorder buffer size (number of subframes) for this + * session. + * When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver * may neither send aggregates containing more subframes than this * nor send aggregates in a way that lost frames would exceed the * buffer size. If just limiting the aggregate size, this would be diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 10ad4ac1fa0b..78672737fe3e 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -323,7 +323,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num, 0, false); + &sta->sta, tid, &start_seq_num, buf_size, false); ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", sta->sta.addr, tid, ret); if (ret) { -- cgit From 4352a4d7f6bfd0aed0276a13fa4993db35714db4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Dec 2015 16:04:35 +0200 Subject: mac80211: document status.freq restrictions It's not always necessary to set the status.freq field, for example when this would be an expensive calculation. It must be set for all management frames (as they might be reported to userspace), but for data frames it's not really required. Document this. Signed-off-by: Johannes Berg --- include/net/mac80211.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a990338a766e..bdee1cc19c7e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1108,6 +1108,8 @@ enum mac80211_rx_vht_flags { * it but can store it and pass it back to the driver for synchronisation * @band: the active band when this frame was received * @freq: frequency the radio was tuned to when receiving this frame, in MHz + * This field must be set for management frames, but isn't strictly needed + * for data (other) frames - for those it only affects radiotap reporting. * @signal: signal strength when receiving this frame, either in dBm, in dB or * unspecified depending on the hardware capabilities flags * @IEEE80211_HW_SIGNAL_* -- cgit From a85a7e28f45f7217b9a2efc3ba323de5c0e5b056 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 1 Jan 2016 23:48:52 +0800 Subject: cfg80211/mac80211: use to_delayed_work Use to_delayed_work() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 3 +-- net/wireless/mlme.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 31d5881b31fa..4af9b2bcc020 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1638,8 +1638,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data) void ieee80211_dfs_cac_timer_work(struct work_struct *work) { - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); + struct delayed_work *delayed_work = to_delayed_work(work); struct ieee80211_sub_if_data *sdata = container_of(delayed_work, struct ieee80211_sub_if_data, dfs_cac_timer_work); diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index fb44fa3bf4ef..ff328250bc44 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -711,7 +711,7 @@ EXPORT_SYMBOL(cfg80211_rx_mgmt); void cfg80211_dfs_channels_update_work(struct work_struct *work) { - struct delayed_work *delayed_work; + struct delayed_work *delayed_work = to_delayed_work(work); struct cfg80211_registered_device *rdev; struct cfg80211_chan_def chandef; struct ieee80211_supported_band *sband; @@ -721,7 +721,6 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) unsigned long timeout, next_time = 0; int bandid, i; - delayed_work = container_of(work, struct delayed_work, work); rdev = container_of(delayed_work, struct cfg80211_registered_device, dfs_update_channels_wk); wiphy = &rdev->wiphy; -- cgit From 50ea05efaf3bed7dd34bcc2635a8b3f53bd0ccc1 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 30 Dec 2015 16:06:04 +0200 Subject: mac80211: pass block ack session timeout to to driver Currently mac80211 does not inform the driver of the session block ack timeout when starting a rx aggregation session. Drivers that manage the reorder buffer need to know this parameter. Seeing that there are now too many arguments for the drv_ampdu_action() function, wrap them inside a structure. Signed-off-by: Sara Sharon Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath10k/mac.c | 7 +-- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 +-- drivers/net/wireless/ath/ath9k/main.c | 8 ++-- drivers/net/wireless/ath/carl9170/main.c | 8 ++-- drivers/net/wireless/ath/wcn36xx/main.c | 8 ++-- .../broadcom/brcm80211/brcmsmac/mac80211_if.c | 8 ++-- drivers/net/wireless/intel/iwlegacy/4965-mac.c | 8 ++-- drivers/net/wireless/intel/iwlegacy/4965.h | 4 +- drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 9 ++-- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 9 ++-- drivers/net/wireless/mac80211_hwsim.c | 8 ++-- drivers/net/wireless/marvell/mwl8k.c | 10 ++-- drivers/net/wireless/mediatek/mt7601u/main.c | 8 ++-- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 7 +-- drivers/net/wireless/ralink/rt2x00/rt2800lib.h | 4 +- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c | 6 +-- drivers/net/wireless/realtek/rtlwifi/core.c | 8 ++-- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 19 +++----- drivers/net/wireless/st/cw1200/sta.c | 4 +- drivers/net/wireless/st/cw1200/sta.h | 4 +- drivers/net/wireless/ti/wlcore/main.c | 8 ++-- include/net/mac80211.h | 44 ++++++++++++------ net/mac80211/agg-rx.c | 25 ++++++++-- net/mac80211/agg-tx.c | 53 ++++++++++++++-------- net/mac80211/driver-ops.c | 10 ++-- net/mac80211/driver-ops.h | 4 +- net/mac80211/trace.h | 43 ++++++++++-------- 27 files changed, 202 insertions(+), 139 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 6146a293601a..368de5e5a04f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6366,12 +6366,13 @@ static u64 ath10k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath10k *ar = hw->priv; struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ampdu vdev_id %i sta %pM tid %hu action %d\n", arvif->vdev_id, sta->addr, tid, action); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index fe1fd1a5ae15..639294a9e34d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1657,13 +1657,14 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw, static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath9k_htc_priv *priv = hw->priv; struct ath9k_htc_sta *ista; int ret = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c1b33fdcca08..cf58a304e9f0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1864,14 +1864,16 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static int ath9k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct ath_softc *sc = hw->priv; struct ath_common *common = ath9k_hw_common(sc->sc_ah); bool flush = false; int ret = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; mutex_lock(&sc->mutex); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 19d3d64416bf..4d1527a2e292 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1413,10 +1413,12 @@ static void carl9170_ampdu_work(struct work_struct *work) static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; struct ar9170 *ar = hw->priv; struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; struct carl9170_sta_tid *tid_info; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 7c169abdbafe..a27279c2c695 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -857,12 +857,14 @@ static int wcn36xx_resume(struct ieee80211_hw *hw) static int wcn36xx_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct wcn36xx *wcn = hw->priv; struct wcn36xx_sta *sta_priv = NULL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n", action, tid); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index bec2dc1ca2e4..61ae2768132a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -818,13 +818,15 @@ brcms_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, static int brcms_ops_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct brcms_info *wl = hw->priv; struct scb *scb = &wl->wlc->pri_scb; int status; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u8 buf_size = params->buf_size; if (WARN_ON(scb->magic != SCB_MAGIC)) return -EIDRM; diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c index fd38aa0763e4..b75f4ef3cdc7 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c @@ -5982,12 +5982,14 @@ il4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct il_priv *il = hw->priv; int ret = -EINVAL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; D_HT("A-MPDU action on addr %pM tid %d\n", sta->addr, tid); diff --git a/drivers/net/wireless/intel/iwlegacy/4965.h b/drivers/net/wireless/intel/iwlegacy/4965.h index 8ab8706f9422..e432715e02d8 100644 --- a/drivers/net/wireless/intel/iwlegacy/4965.h +++ b/drivers/net/wireless/intel/iwlegacy/4965.h @@ -182,9 +182,7 @@ void il4965_mac_update_tkip_key(struct ieee80211_hw *hw, struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 * ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 29ea1c6705b4..151721e4040c 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -732,12 +732,15 @@ static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); int ret = -EINVAL; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d70a1716f3e0..1bd3f0b700d3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -837,13 +837,16 @@ iwl_mvm_ampdu_check_trigger(struct iwl_mvm *mvm, struct ieee80211_vif *vif, static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; bool tx_agg_ref = false; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n", sta->addr, tid, action); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c32889a1e39c..e31a94fd6135 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1845,10 +1845,12 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + switch (action) { case IEEE80211_AMPDU_TX_START: ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c index 30e3aaae32e2..088429d0a634 100644 --- a/drivers/net/wireless/marvell/mwl8k.c +++ b/drivers/net/wireless/marvell/mwl8k.c @@ -5421,11 +5421,13 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, static int mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { - + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; int i, rc = 0; struct mwl8k_priv *priv = hw->priv; struct mwl8k_ampdu_stream *stream; diff --git a/drivers/net/wireless/mediatek/mt7601u/main.c b/drivers/net/wireless/mediatek/mt7601u/main.c index f715eee39851..e70dd9523911 100644 --- a/drivers/net/wireless/mediatek/mt7601u/main.c +++ b/drivers/net/wireless/mediatek/mt7601u/main.c @@ -334,11 +334,13 @@ static int mt7601u_set_rts_threshold(struct ieee80211_hw *hw, u32 value) static int mt76_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { struct mt7601u_dev *dev = hw->priv; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; struct mt76_sta *msta = (struct mt76_sta *) sta->drv_priv; WARN_ON(msta->wcid.idx > GROUP_WCID(0)); diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 9733b31a780d..69c1c09687a3 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -7935,10 +7935,11 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL_GPL(rt2800_get_tsf); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv; int ret = 0; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h index 440790b92b19..83f1a44fb9b4 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h @@ -218,9 +218,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params); u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif); int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c index 6aed923a709a..7d820c395375 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c @@ -5375,13 +5375,13 @@ static int rtl8xxxu_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int rtl8xxxu_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, u8 buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { struct rtl8xxxu_priv *priv = hw->priv; struct device *dev = &priv->udev->dev; u8 ampdu_factor, ampdu_density; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c index 4ae421ef30d9..f2507610314b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/core.c +++ b/drivers/net/wireless/realtek/rtlwifi/core.c @@ -1371,11 +1371,13 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw, static int rtl_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct rtl_priv *rtlpriv = rtl_priv(hw); + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; switch (action) { case IEEE80211_AMPDU_TX_START: diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index b5bcc933a2a6..4df992de7d07 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -659,29 +659,24 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, * informs the f/w regarding this. * @hw: Pointer to the ieee80211_hw structure. * @vif: Pointer to the ieee80211_vif structure. - * @action: ieee80211_ampdu_mlme_action enum. - * @sta: Pointer to the ieee80211_sta structure. - * @tid: Traffic identifier. - * @ssn: Pointer to ssn value. - * @buf_size: Buffer size (for kernel version > 2.6.38). - * @amsdu: is AMSDU in AMPDU allowed + * @params: Pointer to A-MPDU action parameters * * Return: status: 0 on success, negative error code on failure. */ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - unsigned short tid, - unsigned short *ssn, - unsigned char buf_size, - bool amsdu) + struct ieee80211_ampdu_params *params) { int status = -EOPNOTSUPP; struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; u16 seq_no = 0; u8 ii = 0; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; + u8 buf_size = params->buf_size; for (ii = 0; ii < RSI_MAX_VIFS; ii++) { if (vif == adapter->vifs[ii]) diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index 06321c799c90..d0ddcde6c695 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c @@ -2129,9 +2129,7 @@ void cw1200_mcast_timeout(unsigned long arg) int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { /* Aggregation is implemented fully in firmware, * including block ack negotiation. Do not allow diff --git a/drivers/net/wireless/st/cw1200/sta.h b/drivers/net/wireless/st/cw1200/sta.h index bebb3379017f..a0bacaa39b31 100644 --- a/drivers/net/wireless/st/cw1200/sta.h +++ b/drivers/net/wireless/st/cw1200/sta.h @@ -109,9 +109,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev, u32 changed); int cw1200_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); void cw1200_suspend_resume(struct cw1200_common *priv, struct wsm_suspend_resume *arg); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index d1109c4f0f0d..45662cf3169f 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5187,14 +5187,16 @@ out: static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u8 hlid, *ba_bitmap; + struct ieee80211_sta *sta = params->sta; + enum ieee80211_ampdu_mlme_action action = params->action; + u16 tid = params->tid; + u16 *ssn = ¶ms->ssn; wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action, tid); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index bdee1cc19c7e..6c9c559394b0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -2702,6 +2702,33 @@ enum ieee80211_ampdu_mlme_action { IEEE80211_AMPDU_TX_OPERATIONAL, }; +/** + * struct ieee80211_ampdu_params - AMPDU action parameters + * + * @action: the ampdu action, value from %ieee80211_ampdu_mlme_action. + * @sta: peer of this AMPDU session + * @tid: tid of the BA session + * @ssn: start sequence number of the session. TX/RX_STOP can pass 0. When + * action is set to %IEEE80211_AMPDU_RX_START the driver passes back the + * actual ssn value used to start the session and writes the value here. + * @buf_size: reorder buffer size (number of subframes). Valid only when the + * action is set to %IEEE80211_AMPDU_RX_START or + * %IEEE80211_AMPDU_TX_OPERATIONAL + * @amsdu: indicates the peer's ability to receive A-MSDU within A-MPDU. + * valid when the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL + * @timeout: BA session timeout. Valid only when the action is set to + * %IEEE80211_AMPDU_RX_START + */ +struct ieee80211_ampdu_params { + enum ieee80211_ampdu_mlme_action action; + struct ieee80211_sta *sta; + u16 tid; + u16 ssn; + u8 buf_size; + bool amsdu; + u16 timeout; +}; + /** * enum ieee80211_frame_release_type - frame release reason * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll @@ -3046,15 +3073,9 @@ enum ieee80211_reconfig_type { * @ampdu_action: Perform a certain A-MPDU action * The RA/TID combination determines the destination and TID we want * the ampdu action to be performed for. The action is defined through - * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) - * is the first frame we expect to perform the action on. Notice - * that TX/RX_STOP can pass NULL for this parameter. - * The @buf_size parameter is valid only when the action is set to - * %IEEE80211_AMPDU_RX_START or %IEEE80211_AMPDU_TX_OPERATIONAL and - * indicates the reorder buffer size (number of subframes) for this - * session. + * ieee80211_ampdu_mlme_action. * When the action is set to %IEEE80211_AMPDU_TX_OPERATIONAL the driver - * may neither send aggregates containing more subframes than this + * may neither send aggregates containing more subframes than @buf_size * nor send aggregates in a way that lost frames would exceed the * buffer size. If just limiting the aggregate size, this would be * possible with a buf_size of 8: @@ -3065,9 +3086,6 @@ enum ieee80211_reconfig_type { * buffer size of 8. Correct ways to retransmit #1 would be: * - TX: 1 or 18 or 81 * Even "189" would be wrong since 1 could be lost again. - * The @amsdu parameter is valid when the action is set to - * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's ability - * to receive A-MSDU within A-MPDU. * * Returns a negative error code on failure. * The callback can sleep. @@ -3409,9 +3427,7 @@ struct ieee80211_ops { int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*ampdu_action)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn, - u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); int (*get_survey)(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void (*rfkill_poll)(struct ieee80211_hw *hw); diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 78672737fe3e..ec80db7c955c 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015 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 @@ -61,6 +62,14 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_rx *tid_rx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_RX_STOP, + .tid = tid, + .amsdu = false, + .timeout = 0, + .ssn = 0, + }; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -78,8 +87,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", (int)reason); - if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, - &sta->sta, tid, NULL, 0, false)) + if (drv_ampdu_action(local, sta->sdata, ¶ms)) sdata_info(sta->sdata, "HW problem - can not stop rx aggregation for %pM tid %d\n", sta->sta.addr, tid); @@ -237,6 +245,15 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, { struct ieee80211_local *local = sta->sdata->local; struct tid_ampdu_rx *tid_agg_rx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_RX_START, + .tid = tid, + .amsdu = false, + .timeout = timeout, + .ssn = start_seq_num, + }; + int i, ret = -EOPNOTSUPP; u16 status = WLAN_STATUS_REQUEST_DECLINED; @@ -275,6 +292,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, /* make sure the size doesn't exceed the maximum supported by the hw */ if (buf_size > local->hw.max_rx_aggregation_subframes) buf_size = local->hw.max_rx_aggregation_subframes; + params.buf_size = buf_size; /* examine state machine */ mutex_lock(&sta->ampdu_mlme.mtx); @@ -322,8 +340,7 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, for (i = 0; i < buf_size; i++) __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); - ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, - &sta->sta, tid, &start_seq_num, buf_size, false); + ret = drv_ampdu_action(local, sta->sdata, ¶ms); ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", sta->sta.addr, tid, ret); if (ret) { diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index ff757181b0a8..4932e9f243a2 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -7,6 +7,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation + * Copyright(c) 2015 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 @@ -295,7 +296,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, { struct ieee80211_local *local = sta->local; struct tid_ampdu_tx *tid_tx; - enum ieee80211_ampdu_mlme_action action; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .tid = tid, + .buf_size = 0, + .amsdu = false, + .timeout = 0, + .ssn = 0, + }; int ret; lockdep_assert_held(&sta->ampdu_mlme.mtx); @@ -304,10 +312,10 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, case AGG_STOP_DECLINED: case AGG_STOP_LOCAL_REQUEST: case AGG_STOP_PEER_REQUEST: - action = IEEE80211_AMPDU_TX_STOP_CONT; + params.action = IEEE80211_AMPDU_TX_STOP_CONT; break; case AGG_STOP_DESTROY_STA: - action = IEEE80211_AMPDU_TX_STOP_FLUSH; + params.action = IEEE80211_AMPDU_TX_STOP_FLUSH; break; default: WARN_ON_ONCE(1); @@ -330,9 +338,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, spin_unlock_bh(&sta->lock); if (reason != AGG_STOP_DESTROY_STA) return -EALREADY; - ret = drv_ampdu_action(local, sta->sdata, - IEEE80211_AMPDU_TX_STOP_FLUSH_CONT, - &sta->sta, tid, NULL, 0, false); + params.action = IEEE80211_AMPDU_TX_STOP_FLUSH_CONT; + ret = drv_ampdu_action(local, sta->sdata, ¶ms); WARN_ON_ONCE(ret); return 0; } @@ -381,8 +388,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, WLAN_BACK_INITIATOR; tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; - ret = drv_ampdu_action(local, sta->sdata, action, - &sta->sta, tid, NULL, 0, false); + ret = drv_ampdu_action(local, sta->sdata, ¶ms); /* HW shall not deny going back to legacy */ if (WARN_ON(ret)) { @@ -445,7 +451,14 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) struct tid_ampdu_tx *tid_tx; struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; - u16 start_seq_num; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_TX_START, + .tid = tid, + .buf_size = 0, + .amsdu = false, + .timeout = 0, + }; int ret; tid_tx = rcu_dereference_protected_tid_tx(sta, tid); @@ -467,10 +480,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) */ synchronize_net(); - start_seq_num = sta->tid_seq[tid] >> 4; - - ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, - &sta->sta, tid, &start_seq_num, 0, false); + params.ssn = sta->tid_seq[tid] >> 4; + ret = drv_ampdu_action(local, sdata, ¶ms); if (ret) { ht_dbg(sdata, "BA request denied - HW unavailable for %pM tid %d\n", @@ -499,7 +510,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) /* send AddBA request */ ieee80211_send_addba_request(sdata, sta->sta.addr, tid, - tid_tx->dialog_token, start_seq_num, + tid_tx->dialog_token, params.ssn, IEEE80211_MAX_AMPDU_BUF, tid_tx->timeout); } @@ -684,18 +695,24 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { struct tid_ampdu_tx *tid_tx; + struct ieee80211_ampdu_params params = { + .sta = &sta->sta, + .action = IEEE80211_AMPDU_TX_OPERATIONAL, + .tid = tid, + .timeout = 0, + .ssn = 0, + }; lockdep_assert_held(&sta->ampdu_mlme.mtx); tid_tx = rcu_dereference_protected_tid_tx(sta, tid); + params.buf_size = tid_tx->buf_size; + params.amsdu = tid_tx->amsdu; ht_dbg(sta->sdata, "Aggregation is on for %pM tid %d\n", sta->sta.addr, tid); - drv_ampdu_action(local, sta->sdata, - IEEE80211_AMPDU_TX_OPERATIONAL, - &sta->sta, tid, NULL, tid_tx->buf_size, - tid_tx->amsdu); + drv_ampdu_action(local, sta->sdata, ¶ms); /* * synchronize with TX path, while splicing the TX path diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index ca1fe5576103..c258f1041d33 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -284,9 +284,7 @@ int drv_switch_vif_chanctx(struct ieee80211_local *local, int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu) + struct ieee80211_ampdu_params *params) { int ret = -EOPNOTSUPP; @@ -296,12 +294,10 @@ int drv_ampdu_action(struct ieee80211_local *local, if (!check_sdata_in_driver(sdata)) return -EIO; - trace_drv_ampdu_action(local, sdata, action, sta, tid, - ssn, buf_size, amsdu); + trace_drv_ampdu_action(local, sdata, params); if (local->ops->ampdu_action) - ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, - sta, tid, ssn, buf_size, amsdu); + ret = local->ops->ampdu_action(&local->hw, &sdata->vif, params); trace_drv_return_int(local, ret); diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 154ce4b13406..18b0d65baff0 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -585,9 +585,7 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) int drv_ampdu_action(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu); + struct ieee80211_ampdu_params *params); static inline int drv_get_survey(struct ieee80211_local *local, int idx, struct survey_info *survey) diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index a6b4442776a0..2b0a17ee907a 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h @@ -80,7 +80,23 @@ #define KEY_PR_FMT " cipher:0x%x, flags=%#x, keyidx=%d, hw_key_idx=%d" #define KEY_PR_ARG __entry->cipher, __entry->flags, __entry->keyidx, __entry->hw_key_idx - +#define AMPDU_ACTION_ENTRY __field(enum ieee80211_ampdu_mlme_action, \ + ieee80211_ampdu_mlme_action) \ + STA_ENTRY \ + __field(u16, tid) \ + __field(u16, ssn) \ + __field(u8, buf_size) \ + __field(bool, amsdu) \ + __field(u16, timeout) +#define AMPDU_ACTION_ASSIGN STA_NAMED_ASSIGN(params->sta); \ + __entry->tid = params->tid; \ + __entry->ssn = params->ssn; \ + __entry->buf_size = params->buf_size; \ + __entry->amsdu = params->amsdu; \ + __entry->timeout = params->timeout; +#define AMPDU_ACTION_PR_FMT STA_PR_FMT " tid %d, ssn %d, buf_size %u, amsdu %d, timeout %d" +#define AMPDU_ACTION_PR_ARG STA_PR_ARG, __entry->tid, __entry->ssn, \ + __entry->buf_size, __entry->amsdu, __entry->timeout /* * Tracing for driver callbacks. @@ -970,38 +986,25 @@ DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, TRACE_EVENT(drv_ampdu_action, TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, - u16 *ssn, u8 buf_size, bool amsdu), + struct ieee80211_ampdu_params *params), - TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size, amsdu), + TP_ARGS(local, sdata, params), TP_STRUCT__entry( LOCAL_ENTRY - STA_ENTRY - __field(u32, action) - __field(u16, tid) - __field(u16, ssn) - __field(u8, buf_size) - __field(bool, amsdu) VIF_ENTRY + AMPDU_ACTION_ENTRY ), TP_fast_assign( LOCAL_ASSIGN; VIF_ASSIGN; - STA_ASSIGN; - __entry->action = action; - __entry->tid = tid; - __entry->ssn = ssn ? *ssn : 0; - __entry->buf_size = buf_size; - __entry->amsdu = amsdu; + AMPDU_ACTION_ASSIGN; ), TP_printk( - LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d amsdu:%d", - LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, - __entry->tid, __entry->buf_size, __entry->amsdu + LOCAL_PR_FMT VIF_PR_FMT AMPDU_ACTION_PR_FMT, + LOCAL_PR_ARG, VIF_PR_ARG, AMPDU_ACTION_PR_ARG ) ); -- cgit From 7508abc4bdac43dc87d2fdd31527063f72da7020 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Fri, 18 Dec 2015 11:54:55 -0600 Subject: GFS2: Check if iopen is held when deleting inode This patch fixes an error condition in which an inode is partially created in gfs2_create_inode() but then some error is discovered, which causes it to fail and call iput() before the iopen glock is created or held. In that case, gfs2_delete_inode would try to unlock an iopen glock that doesn't yet exist. Therefore, we test its holder (which must exist) for the HIF_HOLDER bit before trying to dq it. Signed-off-by: Bob Peterson Acked-by: Steven Whitehouse --- fs/gfs2/glock.c | 1 + fs/gfs2/super.c | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index a4ff7b56f5cd..5788ebff716a 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -1015,6 +1015,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh) handle_callback(gl, LM_ST_UNLOCKED, 0, false); list_del_init(&gh->gh_list); + clear_bit(HIF_HOLDER, &gh->gh_iflags); if (find_first_holder(gl) == NULL) { if (glops->go_unlock) { GLOCK_BUG_ON(gl, test_and_set_bit(GLF_LOCK, &gl->gl_flags)); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 8f960a51a9a0..f8a0cd821290 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1551,12 +1551,16 @@ static void gfs2_evict_inode(struct inode *inode) goto out_truncate; } - ip->i_iopen_gh.gh_flags |= GL_NOCACHE; - gfs2_glock_dq_wait(&ip->i_iopen_gh); - gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh); - error = gfs2_glock_nq(&ip->i_iopen_gh); - if (error) - goto out_truncate; + if (ip->i_iopen_gh.gh_gl && + test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |= GL_NOCACHE; + gfs2_glock_dq_wait(&ip->i_iopen_gh); + gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, + &ip->i_iopen_gh); + error = gfs2_glock_nq(&ip->i_iopen_gh); + if (error) + goto out_truncate; + } /* Case 1 starts here */ @@ -1606,11 +1610,13 @@ out_unlock: if (gfs2_rs_active(&ip->i_res)) gfs2_rs_deltree(&ip->i_res); - if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { - ip->i_iopen_gh.gh_flags |= GL_NOCACHE; - gfs2_glock_dq_wait(&ip->i_iopen_gh); + if (ip->i_iopen_gh.gh_gl) { + if (test_bit(HIF_HOLDER, &ip->i_iopen_gh.gh_iflags)) { + ip->i_iopen_gh.gh_flags |= GL_NOCACHE; + gfs2_glock_dq_wait(&ip->i_iopen_gh); + } + gfs2_holder_uninit(&ip->i_iopen_gh); } - gfs2_holder_uninit(&ip->i_iopen_gh); gfs2_glock_dq_uninit(&gh); if (error && error != GLR_TRYFAILED && error != -EROFS) fs_warn(sdp, "gfs2_evict_inode: %d\n", error); -- cgit From fcde5a7eca1a28d3f7158399809cb01f83bd0114 Mon Sep 17 00:00:00 2001 From: PC Liao Date: Tue, 12 Jan 2016 14:33:42 +0800 Subject: ASoC: mediatek: Enable 33bit memory address to support 4GB DRAM If platform is embedded with memory more than 3GB, the address will go out of the scope that 32-bit can handle with. This patch sets the dma_mask and MSB properly to describe its address to 33-bit. Signed-off-by: Hidalgo Huang Signed-off-by: PC Liao Signed-off-by: Mark Brown --- sound/soc/mediatek/mtk-afe-common.h | 1 + sound/soc/mediatek/mtk-afe-pcm.c | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/mtk-afe-common.h b/sound/soc/mediatek/mtk-afe-common.h index 9b1af1a70874..f341f623e887 100644 --- a/sound/soc/mediatek/mtk-afe-common.h +++ b/sound/soc/mediatek/mtk-afe-common.h @@ -87,6 +87,7 @@ struct mtk_afe_memif_data { int irq_en_shift; int irq_fs_shift; int irq_clr_shift; + int msb_shift; }; struct mtk_afe_memif { diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c index 08af9f5dc4ab..689c51f23d9f 100644 --- a/sound/soc/mediatek/mtk-afe-pcm.c +++ b/sound/soc/mediatek/mtk-afe-pcm.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include "mtk-afe-common.h" @@ -35,6 +36,7 @@ #define AFE_I2S_CON1 0x0034 #define AFE_I2S_CON2 0x0038 #define AFE_CONN_24BIT 0x006c +#define AFE_MEMIF_MSB 0x00cc #define AFE_CONN1 0x0024 #define AFE_CONN2 0x0028 @@ -592,6 +594,7 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform); struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id]; + int msb_at_bit33 = 0; int ret; dev_dbg(afe->dev, @@ -603,7 +606,8 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - memif->phys_buf_addr = substream->runtime->dma_addr; + msb_at_bit33 = upper_32_bits(substream->runtime->dma_addr) ? 1 : 0; + memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr); memif->buffer_size = substream->runtime->dma_bytes; /* start */ @@ -614,6 +618,11 @@ static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream, memif->data->reg_ofs_base + AFE_BASE_END_OFFSET, memif->phys_buf_addr + memif->buffer_size - 1); + /* set MSB to 33-bit */ + regmap_update_bits(afe->regmap, AFE_MEMIF_MSB, + 1 << memif->data->msb_shift, + msb_at_bit33 << memif->data->msb_shift); + /* set channel */ if (memif->data->mono_shift >= 0) { unsigned int mono = (params_channels(params) == 1) ? 1 : 0; @@ -978,6 +987,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 0, .irq_fs_shift = 4, .irq_clr_shift = 0, + .msb_shift = 0, }, { .name = "DL2", .id = MTK_AFE_MEMIF_DL2, @@ -991,6 +1001,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 2, .irq_fs_shift = 16, .irq_clr_shift = 2, + .msb_shift = 1, }, { .name = "VUL", .id = MTK_AFE_MEMIF_VUL, @@ -1004,6 +1015,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 1, .irq_fs_shift = 8, .irq_clr_shift = 1, + .msb_shift = 6, }, { .name = "DAI", .id = MTK_AFE_MEMIF_DAI, @@ -1017,6 +1029,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 3, .irq_fs_shift = 20, .irq_clr_shift = 3, + .msb_shift = 5, }, { .name = "AWB", .id = MTK_AFE_MEMIF_AWB, @@ -1030,6 +1043,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 14, .irq_fs_shift = 24, .irq_clr_shift = 6, + .msb_shift = 3, }, { .name = "MOD_DAI", .id = MTK_AFE_MEMIF_MOD_DAI, @@ -1043,6 +1057,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 3, .irq_fs_shift = 20, .irq_clr_shift = 3, + .msb_shift = 4, }, { .name = "HDMI", .id = MTK_AFE_MEMIF_HDMI, @@ -1056,6 +1071,7 @@ static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = { .irq_en_shift = 12, .irq_fs_shift = -1, .irq_clr_shift = 4, + .msb_shift = 8, }, }; @@ -1189,6 +1205,10 @@ static int mtk_afe_pcm_dev_probe(struct platform_device *pdev) struct mtk_afe *afe; struct resource *res; + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); + if (ret) + return ret; + afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); if (!afe) return -ENOMEM; -- cgit From ab7cad331155bab5e81381b5e34a333220718385 Mon Sep 17 00:00:00 2001 From: zhangqing Date: Tue, 12 Jan 2016 03:05:56 -0800 Subject: regulator: fan53555: fill set_suspend_enable/disable callback Setting the set_suspend_enable/disable callback to support enable and disable the dcdc when system is suspend. Signed-off-by: zhangqing Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- drivers/regulator/fan53555.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 4940e8287df6..2cb5cc311610 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -114,6 +114,22 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) return 0; } +static int fan53555_set_suspend_enable(struct regulator_dev *rdev) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + + return regmap_update_bits(di->regmap, di->sleep_reg, + VSEL_BUCK_EN, VSEL_BUCK_EN); +} + +static int fan53555_set_suspend_disable(struct regulator_dev *rdev) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + + return regmap_update_bits(di->regmap, di->sleep_reg, + VSEL_BUCK_EN, 0); +} + static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct fan53555_device_info *di = rdev_get_drvdata(rdev); @@ -192,6 +208,8 @@ static struct regulator_ops fan53555_regulator_ops = { .set_mode = fan53555_set_mode, .get_mode = fan53555_get_mode, .set_ramp_delay = fan53555_set_ramp, + .set_suspend_enable = fan53555_set_suspend_enable, + .set_suspend_disable = fan53555_set_suspend_disable, }; static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) -- cgit From 517e7a1537ae4663268be5d0c0ec62c563b9fc99 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 12 Jan 2016 12:35:46 +0000 Subject: ASoC: bcm2835: move to use the clock framework Since the move to the new clock framework with commit 94cb7f76caa0 ("ARM: bcm2835: Switch to using the new clock driver support.") this driver was no longer functional as it was manipulating the clock registers locally without going true the framework. This patch moves to use the new clock framework and also moves away from the hardcoded address offsets for DMA getting the dma-address directly from the device tree. Note that the optimal bclk_ratio selection to avoid jitter due to the use of fractional dividers, which is in the current version has been removed, because not all devices support these non power of 2 sized transfers, which resulted in lots of (downstream) modules that use: snd_soc_dai_set_bclk_ratio(cpu_dai, sample_bits * 2); Signed-off-by: Martin Sperl Signed-off-by: Mark Brown --- sound/soc/bcm/bcm2835-i2s.c | 284 ++++++++++---------------------------------- 1 file changed, 64 insertions(+), 220 deletions(-) diff --git a/sound/soc/bcm/bcm2835-i2s.c b/sound/soc/bcm/bcm2835-i2s.c index 3303d5f58082..1c1f2210387b 100644 --- a/sound/soc/bcm/bcm2835-i2s.c +++ b/sound/soc/bcm/bcm2835-i2s.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -46,55 +47,6 @@ #include #include -/* Clock registers */ -#define BCM2835_CLK_PCMCTL_REG 0x00 -#define BCM2835_CLK_PCMDIV_REG 0x04 - -/* Clock register settings */ -#define BCM2835_CLK_PASSWD (0x5a000000) -#define BCM2835_CLK_PASSWD_MASK (0xff000000) -#define BCM2835_CLK_MASH(v) ((v) << 9) -#define BCM2835_CLK_FLIP BIT(8) -#define BCM2835_CLK_BUSY BIT(7) -#define BCM2835_CLK_KILL BIT(5) -#define BCM2835_CLK_ENAB BIT(4) -#define BCM2835_CLK_SRC(v) (v) - -#define BCM2835_CLK_SHIFT (12) -#define BCM2835_CLK_DIVI(v) ((v) << BCM2835_CLK_SHIFT) -#define BCM2835_CLK_DIVF(v) (v) -#define BCM2835_CLK_DIVF_MASK (0xFFF) - -enum { - BCM2835_CLK_MASH_0 = 0, - BCM2835_CLK_MASH_1, - BCM2835_CLK_MASH_2, - BCM2835_CLK_MASH_3, -}; - -enum { - BCM2835_CLK_SRC_GND = 0, - BCM2835_CLK_SRC_OSC, - BCM2835_CLK_SRC_DBG0, - BCM2835_CLK_SRC_DBG1, - BCM2835_CLK_SRC_PLLA, - BCM2835_CLK_SRC_PLLC, - BCM2835_CLK_SRC_PLLD, - BCM2835_CLK_SRC_HDMI, -}; - -/* Most clocks are not useable (freq = 0) */ -static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { - [BCM2835_CLK_SRC_GND] = 0, - [BCM2835_CLK_SRC_OSC] = 19200000, - [BCM2835_CLK_SRC_DBG0] = 0, - [BCM2835_CLK_SRC_DBG1] = 0, - [BCM2835_CLK_SRC_PLLA] = 0, - [BCM2835_CLK_SRC_PLLC] = 0, - [BCM2835_CLK_SRC_PLLD] = 500000000, - [BCM2835_CLK_SRC_HDMI] = 0, -}; - /* I2S registers */ #define BCM2835_I2S_CS_A_REG 0x00 #define BCM2835_I2S_FIFO_A_REG 0x04 @@ -158,10 +110,6 @@ static const unsigned int bcm2835_clk_freq[BCM2835_CLK_SRC_HDMI+1] = { #define BCM2835_I2S_INT_RXR BIT(1) #define BCM2835_I2S_INT_TXW BIT(0) -/* I2S DMA interface */ -/* FIXME: Needs IOMMU support */ -#define BCM2835_VCMMU_SHIFT (0x7E000000 - 0x20000000) - /* General device struct */ struct bcm2835_i2s_dev { struct device *dev; @@ -169,21 +117,23 @@ struct bcm2835_i2s_dev { unsigned int fmt; unsigned int bclk_ratio; - struct regmap *i2s_regmap; - struct regmap *clk_regmap; + struct regmap *i2s_regmap; + struct clk *clk; + bool clk_prepared; }; static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) { - /* Start the clock if in master mode */ unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; + if (dev->clk_prepared) + return; + switch (master) { case SND_SOC_DAIFMT_CBS_CFS: case SND_SOC_DAIFMT_CBS_CFM: - regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, - BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, - BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); + clk_prepare_enable(dev->clk); + dev->clk_prepared = true; break; default: break; @@ -192,28 +142,9 @@ static void bcm2835_i2s_start_clock(struct bcm2835_i2s_dev *dev) static void bcm2835_i2s_stop_clock(struct bcm2835_i2s_dev *dev) { - uint32_t clkreg; - int timeout = 1000; - - /* Stop clock */ - regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, - BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, - BCM2835_CLK_PASSWD); - - /* Wait for the BUSY flag going down */ - while (--timeout) { - regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); - if (!(clkreg & BCM2835_CLK_BUSY)) - break; - } - - if (!timeout) { - /* KILL the clock */ - dev_err(dev->dev, "I2S clock didn't stop. Kill the clock!\n"); - regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, - BCM2835_CLK_KILL | BCM2835_CLK_PASSWD_MASK, - BCM2835_CLK_KILL | BCM2835_CLK_PASSWD); - } + if (dev->clk_prepared) + clk_disable_unprepare(dev->clk); + dev->clk_prepared = false; } static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, @@ -223,8 +154,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, uint32_t syncval; uint32_t csreg; uint32_t i2s_active_state; - uint32_t clkreg; - uint32_t clk_active_state; + bool clk_was_prepared; uint32_t off; uint32_t clr; @@ -238,15 +168,10 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, regmap_read(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, &csreg); i2s_active_state = csreg & (BCM2835_I2S_RXON | BCM2835_I2S_TXON); - regmap_read(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, &clkreg); - clk_active_state = clkreg & BCM2835_CLK_ENAB; - /* Start clock if not running */ - if (!clk_active_state) { - regmap_update_bits(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, - BCM2835_CLK_PASSWD_MASK | BCM2835_CLK_ENAB, - BCM2835_CLK_PASSWD | BCM2835_CLK_ENAB); - } + clk_was_prepared = dev->clk_prepared; + if (!clk_was_prepared) + bcm2835_i2s_start_clock(dev); /* Stop I2S module */ regmap_update_bits(dev->i2s_regmap, BCM2835_I2S_CS_A_REG, off, 0); @@ -280,7 +205,7 @@ static void bcm2835_i2s_clear_fifos(struct bcm2835_i2s_dev *dev, dev_err(dev->dev, "I2S SYNC error!\n"); /* Stop clock if it was not running before */ - if (!clk_active_state) + if (!clk_was_prepared) bcm2835_i2s_stop_clock(dev); /* Restore I2S state */ @@ -309,19 +234,9 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct bcm2835_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); - unsigned int sampling_rate = params_rate(params); unsigned int data_length, data_delay, bclk_ratio; unsigned int ch1pos, ch2pos, mode, format; - unsigned int mash = BCM2835_CLK_MASH_1; - unsigned int divi, divf, target_frequency; - int clk_src = -1; - unsigned int master = dev->fmt & SND_SOC_DAIFMT_MASTER_MASK; - bool bit_master = (master == SND_SOC_DAIFMT_CBS_CFS - || master == SND_SOC_DAIFMT_CBS_CFM); - - bool frame_master = (master == SND_SOC_DAIFMT_CBS_CFS - || master == SND_SOC_DAIFMT_CBM_CFS); uint32_t csreg; /* @@ -343,11 +258,9 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: data_length = 16; - bclk_ratio = 40; break; case SNDRV_PCM_FORMAT_S32_LE: data_length = 32; - bclk_ratio = 80; break; default: return -EINVAL; @@ -356,69 +269,12 @@ static int bcm2835_i2s_hw_params(struct snd_pcm_substream *substream, /* If bclk_ratio already set, use that one. */ if (dev->bclk_ratio) bclk_ratio = dev->bclk_ratio; + else + /* otherwise calculate a fitting block ratio */ + bclk_ratio = 2 * data_length; - /* - * Clock Settings - * - * The target frequency of the bit clock is - * sampling rate * frame length - * - * Integer mode: - * Sampling rates that are multiples of 8000 kHz - * can be driven by the oscillator of 19.2 MHz - * with an integer divider as long as the frame length - * is an integer divider of 19200000/8000=2400 as set up above. - * This is no longer possible if the sampling rate - * is too high (e.g. 192 kHz), because the oscillator is too slow. - * - * MASH mode: - * For all other sampling rates, it is not possible to - * have an integer divider. Approximate the clock - * with the MASH module that induces a slight frequency - * variance. To minimize that it is best to have the fastest - * clock here. That is PLLD with 500 MHz. - */ - target_frequency = sampling_rate * bclk_ratio; - clk_src = BCM2835_CLK_SRC_OSC; - mash = BCM2835_CLK_MASH_0; - - if (bcm2835_clk_freq[clk_src] % target_frequency == 0 - && bit_master && frame_master) { - divi = bcm2835_clk_freq[clk_src] / target_frequency; - divf = 0; - } else { - uint64_t dividend; - - if (!dev->bclk_ratio) { - /* - * Overwrite bclk_ratio, because the - * above trick is not needed or can - * not be used. - */ - bclk_ratio = 2 * data_length; - } - - target_frequency = sampling_rate * bclk_ratio; - - clk_src = BCM2835_CLK_SRC_PLLD; - mash = BCM2835_CLK_MASH_1; - - dividend = bcm2835_clk_freq[clk_src]; - dividend <<= BCM2835_CLK_SHIFT; - do_div(dividend, target_frequency); - divi = dividend >> BCM2835_CLK_SHIFT; - divf = dividend & BCM2835_CLK_DIVF_MASK; - } - - /* Set clock divider */ - regmap_write(dev->clk_regmap, BCM2835_CLK_PCMDIV_REG, BCM2835_CLK_PASSWD - | BCM2835_CLK_DIVI(divi) - | BCM2835_CLK_DIVF(divf)); - - /* Setup clock, but don't start it yet */ - regmap_write(dev->clk_regmap, BCM2835_CLK_PCMCTL_REG, BCM2835_CLK_PASSWD - | BCM2835_CLK_MASH(mash) - | BCM2835_CLK_SRC(clk_src)); + /* set target clock rate*/ + clk_set_rate(dev->clk, sampling_rate * bclk_ratio); /* Setup the frame format */ format = BCM2835_I2S_CHEN; @@ -692,7 +548,7 @@ static const struct snd_soc_dai_ops bcm2835_i2s_dai_ops = { .trigger = bcm2835_i2s_trigger, .hw_params = bcm2835_i2s_hw_params, .set_fmt = bcm2835_i2s_set_dai_fmt, - .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio + .set_bclk_ratio = bcm2835_i2s_set_dai_bclk_ratio, }; static int bcm2835_i2s_dai_probe(struct snd_soc_dai *dai) @@ -750,34 +606,14 @@ static bool bcm2835_i2s_precious_reg(struct device *dev, unsigned int reg) }; } -static bool bcm2835_clk_volatile_reg(struct device *dev, unsigned int reg) -{ - switch (reg) { - case BCM2835_CLK_PCMCTL_REG: - return true; - default: - return false; - }; -} - -static const struct regmap_config bcm2835_regmap_config[] = { - { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = BCM2835_I2S_GRAY_REG, - .precious_reg = bcm2835_i2s_precious_reg, - .volatile_reg = bcm2835_i2s_volatile_reg, - .cache_type = REGCACHE_RBTREE, - }, - { - .reg_bits = 32, - .reg_stride = 4, - .val_bits = 32, - .max_register = BCM2835_CLK_PCMDIV_REG, - .volatile_reg = bcm2835_clk_volatile_reg, - .cache_type = REGCACHE_RBTREE, - }, +static const struct regmap_config bcm2835_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = BCM2835_I2S_GRAY_REG, + .precious_reg = bcm2835_i2s_precious_reg, + .volatile_reg = bcm2835_i2s_volatile_reg, + .cache_type = REGCACHE_RBTREE, }; static const struct snd_soc_component_driver bcm2835_i2s_component = { @@ -787,42 +623,50 @@ static const struct snd_soc_component_driver bcm2835_i2s_component = { static int bcm2835_i2s_probe(struct platform_device *pdev) { struct bcm2835_i2s_dev *dev; - int i; int ret; - struct regmap *regmap[2]; - struct resource *mem[2]; - - /* Request both ioareas */ - for (i = 0; i <= 1; i++) { - void __iomem *base; - - mem[i] = platform_get_resource(pdev, IORESOURCE_MEM, i); - base = devm_ioremap_resource(&pdev->dev, mem[i]); - if (IS_ERR(base)) - return PTR_ERR(base); - - regmap[i] = devm_regmap_init_mmio(&pdev->dev, base, - &bcm2835_regmap_config[i]); - if (IS_ERR(regmap[i])) - return PTR_ERR(regmap[i]); - } + struct resource *mem; + void __iomem *base; + const __be32 *addr; + dma_addr_t dma_base; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; - dev->i2s_regmap = regmap[0]; - dev->clk_regmap = regmap[1]; + /* get the clock */ + dev->clk_prepared = false; + dev->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) { + dev_err(&pdev->dev, "could not get clk: %ld\n", + PTR_ERR(dev->clk)); + return PTR_ERR(dev->clk); + } + + /* Request ioarea */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(base)) + return PTR_ERR(base); + + dev->i2s_regmap = devm_regmap_init_mmio(&pdev->dev, base, + &bcm2835_regmap_config); + if (IS_ERR(dev->i2s_regmap)) + return PTR_ERR(dev->i2s_regmap); + + /* Set the DMA address - we have to parse DT ourselves */ + addr = of_get_address(pdev->dev.of_node, 0, NULL, NULL); + if (!addr) { + dev_err(&pdev->dev, "could not get DMA-register address\n"); + return -EINVAL; + } + dma_base = be32_to_cpup(addr); - /* Set the DMA address */ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = - (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG - + BCM2835_VCMMU_SHIFT; + dma_base + BCM2835_I2S_FIFO_A_REG; dev->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = - (dma_addr_t)mem[0]->start + BCM2835_I2S_FIFO_A_REG - + BCM2835_VCMMU_SHIFT; + dma_base + BCM2835_I2S_FIFO_A_REG; /* Set the bus width */ dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr_width = -- cgit From 0f48eedacf1914c000c7bebdc44de15412baa6f1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 12 Jan 2016 18:28:51 +0100 Subject: regulator: da9210: fix lockdep warning Commit 70cfef26267474 ("regulator: Add lockdep asserts to help detecting locking misuse") successfully created this WARN, let's fix it: [ 1.218660] WARNING: CPU: 0 PID: 553 at drivers/regulator/core.c:3646 regulator_notifier_call_chain+0x5c/0x88() ... [ 1.220278] [] (regulator_notifier_call_chain) from [] (da9210_irq_handler+0x74/0x10c) [ 1.220412] r7:c0080cac r6:eb1daa00 r5:e64bbf10 r4:00000002 [ 1.220547] [] (da9210_irq_handler) from [] (irq_thread_fn+0x2c/0x44) ... Signed-off-by: Wolfram Sang Signed-off-by: Mark Brown --- drivers/regulator/da9210-regulator.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/regulator/da9210-regulator.c b/drivers/regulator/da9210-regulator.c index b3517830edb6..cfd6e8af67ec 100644 --- a/drivers/regulator/da9210-regulator.c +++ b/drivers/regulator/da9210-regulator.c @@ -132,6 +132,8 @@ static irqreturn_t da9210_irq_handler(int irq, void *data) if (error < 0) goto error_i2c; + mutex_lock(&chip->rdev->mutex); + if (val & DA9210_E_OVCURR) { regulator_notifier_call_chain(chip->rdev, REGULATOR_EVENT_OVER_CURRENT, @@ -155,6 +157,9 @@ static irqreturn_t da9210_irq_handler(int irq, void *data) NULL); handled |= DA9210_E_VMAX; } + + mutex_unlock(&chip->rdev->mutex); + if (handled) { /* Clear handled events */ error = regmap_write(chip->regmap, DA9210_REG_EVENT_B, handled); -- cgit From 22a33632fb607a18148815548478265a672d5295 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 13 Jan 2016 16:20:07 +0200 Subject: spi: pxa2xx: Remove CONFIG_SPI_PXA2XX_DMA After removal of legacy PXA DMA code by the commit 6356437e65c2 ("spi: spi-pxa2xx: remove legacy PXA DMA bits") the CONFIG_SPI_PXA2XX_DMA follows the CONFIG_SPI_PXA2XX and cannot be disabled alone. Therefore remove this config symbol and dead definitions from the spi-pxa2xx.h. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 4 ---- drivers/spi/Makefile | 3 +-- drivers/spi/spi-pxa2xx.h | 35 ----------------------------------- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8b9c2a38d1cc..c0604aecf45f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -415,10 +415,6 @@ config SPI_PPC4xx help This selects a driver for the PPC4xx SPI Controller. -config SPI_PXA2XX_DMA - def_bool y - depends on SPI_PXA2XX - config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on (ARCH_PXA || PCI || ACPI) diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 31fb7fb2a0b6..13cee44ec94d 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -61,8 +61,7 @@ obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o -spi-pxa2xx-platform-objs := spi-pxa2xx.o -spi-pxa2xx-platform-$(CONFIG_SPI_PXA2XX_DMA) += spi-pxa2xx-dma.o +spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o obj-$(CONFIG_SPI_QUP) += spi-qup.o diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h index 58efa98313aa..8e781c8b4374 100644 --- a/drivers/spi/spi-pxa2xx.h +++ b/drivers/spi/spi-pxa2xx.h @@ -147,20 +147,9 @@ static inline void write_SSSR_CS(struct driver_data *drv_data, u32 val) extern int pxa2xx_spi_flush(struct driver_data *drv_data); extern void *pxa2xx_spi_next_transfer(struct driver_data *drv_data); -/* - * Select the right DMA implementation. - */ -#if defined(CONFIG_SPI_PXA2XX_DMA) -#define SPI_PXA2XX_USE_DMA 1 #define MAX_DMA_LEN SZ_64K #define DEFAULT_DMA_CR1 (SSCR1_TSRE | SSCR1_RSRE | SSCR1_TRAIL) -#else -#undef SPI_PXA2XX_USE_DMA -#define MAX_DMA_LEN 0 -#define DEFAULT_DMA_CR1 0 -#endif -#ifdef SPI_PXA2XX_USE_DMA extern bool pxa2xx_spi_dma_is_possible(size_t len); extern int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data); extern irqreturn_t pxa2xx_spi_dma_transfer(struct driver_data *drv_data); @@ -173,29 +162,5 @@ extern int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip, u8 bits_per_word, u32 *burst_code, u32 *threshold); -#else -static inline bool pxa2xx_spi_dma_is_possible(size_t len) { return false; } -static inline int pxa2xx_spi_map_dma_buffers(struct driver_data *drv_data) -{ - return 0; -} -#define pxa2xx_spi_dma_transfer NULL -static inline void pxa2xx_spi_dma_prepare(struct driver_data *drv_data, - u32 dma_burst) {} -static inline void pxa2xx_spi_dma_start(struct driver_data *drv_data) {} -static inline int pxa2xx_spi_dma_setup(struct driver_data *drv_data) -{ - return 0; -} -static inline void pxa2xx_spi_dma_release(struct driver_data *drv_data) {} -static inline int pxa2xx_spi_set_dma_burst_and_threshold(struct chip_data *chip, - struct spi_device *spi, - u8 bits_per_word, - u32 *burst_code, - u32 *threshold) -{ - return -ENODEV; -} -#endif #endif /* SPI_PXA2XX_H */ -- cgit From d51fe1f393a6b99e9133a3360036af2c21983ec2 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Wed, 13 Jan 2016 22:41:12 +0100 Subject: regmap: pass buffer size to regmap_raw_read() in regcache_hw_init() regcache_hw_init() uses regmap_raw_read() to initialize cache when reg_defaults_raw isn't provided. The last parameter to regmap_raw_read() is buffer size in bytes, however regcache_hw_init() called it with number of registers to read instead, which cause problem if they aren't one byte wide in cache. This wasn't triggered by any of current in-tree drivers since they either have one-byte registers or provide reg_defaults_raw explicitly. Signed-off-by: Maciej S. Szmigiero Signed-off-by: Mark Brown --- drivers/base/regmap/regcache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 4c07802986b2..45ae91eb6be9 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -57,7 +57,7 @@ static int regcache_hw_init(struct regmap *map) bool cache_bypass = map->cache_bypass; dev_warn(map->dev, "No cache defaults, reading back from HW\n"); - /* Bypass the cache access till data read from HW*/ + /* Bypass the cache access till data read from HW */ map->cache_bypass = true; tmp_buf = kmalloc(map->cache_size_raw, GFP_KERNEL); if (!tmp_buf) { @@ -65,7 +65,7 @@ static int regcache_hw_init(struct regmap *map) goto err_free; } ret = regmap_raw_read(map, 0, tmp_buf, - map->num_reg_defaults_raw); + map->cache_size_raw); map->cache_bypass = cache_bypass; if (ret < 0) goto err_cache_free; -- cgit From 27e177190891d2ad5174a434d8f09b9315520585 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Thu, 14 Jan 2016 16:38:13 +0100 Subject: iio:adc:at91_adc8xx: introduce new atmel adc driver This driver supports the new version of the Atmel ADC device introduced with the SAMA5D2 SoC family. Signed-off-by: Ludovic Desroches Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../bindings/iio/adc/at91-sama5d2_adc.txt | 28 ++ drivers/iio/adc/Kconfig | 11 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/at91-sama5d2_adc.c | 509 +++++++++++++++++++++ 4 files changed, 549 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt create mode 100644 drivers/iio/adc/at91-sama5d2_adc.c diff --git a/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt new file mode 100644 index 000000000000..3223684a643b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/at91-sama5d2_adc.txt @@ -0,0 +1,28 @@ +* AT91 SAMA5D2 Analog to Digital Converter (ADC) + +Required properties: + - compatible: Should be "atmel,sama5d2-adc". + - reg: Should contain ADC registers location and length. + - interrupts: Should contain the IRQ line for the ADC. + - clocks: phandle to device clock. + - clock-names: Must be "adc_clk". + - vref-supply: Supply used as reference for conversions. + - vddana-supply: Supply for the adc device. + - atmel,min-sample-rate-hz: Minimum sampling rate, it depends on SoC. + - atmel,max-sample-rate-hz: Maximum sampling rate, it depends on SoC. + - atmel,startup-time-ms: Startup time expressed in ms, it depends on SoC. + +Example: + +adc: adc@fc030000 { + compatible = "atmel,sama5d2-adc"; + reg = <0xfc030000 0x100>; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH 7>; + clocks = <&adc_clk>; + clock-names = "adc_clk"; + atmel,min-sample-rate-hz = <200000>; + atmel,max-sample-rate-hz = <20000000>; + atmel,startup-time-ms = <4>; + vddana-supply = <&vdd_3v3_lp_reg>; + vref-supply = <&vdd_3v3_lp_reg>; +} diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index d0dc39a95555..af4cb8e167b7 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -131,6 +131,17 @@ config AT91_ADC To compile this driver as a module, choose M here: the module will be called at91_adc. +config AT91_SAMA5D2_ADC + tristate "Atmel AT91 SAMA5D2 ADC" + depends on ARCH_AT91 + depends on INPUT + help + Say yes here to build support for Atmel SAMA5D2 ADC which is + available on SAMA5D2 SoC family. + + To compile this driver as a module, choose M here: the module will be + called at91-sama5d2_adc. + config AXP288_ADC tristate "X-Powers AXP288 ADC driver" depends on MFD_AXP20X diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 6435780e9b71..fb57e12dbde2 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_AD7793) += ad7793.o obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AD799X) += ad799x.o obj-$(CONFIG_AT91_ADC) += at91_adc.o +obj-$(CONFIG_AT91_SAMA5D2_ADC) += at91-sama5d2_adc.o obj-$(CONFIG_AXP288_ADC) += axp288_adc.o obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c new file mode 100644 index 000000000000..ecb2d90c9c06 --- /dev/null +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -0,0 +1,509 @@ +/* + * Atmel ADC driver for SAMA5D2 devices and compatible. + * + * Copyright (C) 2015 Atmel, + * 2015 Ludovic Desroches + * + * 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 +#include +#include +#include +#include + +/* Control Register */ +#define AT91_SAMA5D2_CR 0x00 +/* Software Reset */ +#define AT91_SAMA5D2_CR_SWRST BIT(0) +/* Start Conversion */ +#define AT91_SAMA5D2_CR_START BIT(1) +/* Touchscreen Calibration */ +#define AT91_SAMA5D2_CR_TSCALIB BIT(2) +/* Comparison Restart */ +#define AT91_SAMA5D2_CR_CMPRST BIT(4) + +/* Mode Register */ +#define AT91_SAMA5D2_MR 0x04 +/* Trigger Selection */ +#define AT91_SAMA5D2_MR_TRGSEL(v) ((v) << 1) +/* ADTRG */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG0 0 +/* TIOA0 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG1 1 +/* TIOA1 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG2 2 +/* TIOA2 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG3 3 +/* PWM event line 0 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG4 4 +/* PWM event line 1 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG5 5 +/* TIOA3 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG6 6 +/* RTCOUT0 */ +#define AT91_SAMA5D2_MR_TRGSEL_TRIG7 7 +/* Sleep Mode */ +#define AT91_SAMA5D2_MR_SLEEP BIT(5) +/* Fast Wake Up */ +#define AT91_SAMA5D2_MR_FWUP BIT(6) +/* Prescaler Rate Selection */ +#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 +/* Startup Time */ +#define AT91_SAMA5D2_MR_STARTUP(v) ((v) << 16) +/* Analog Change */ +#define AT91_SAMA5D2_MR_ANACH BIT(23) +/* Tracking Time */ +#define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24) +#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xff +/* Transfer Time */ +#define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28) +#define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3 +/* Use Sequence Enable */ +#define AT91_SAMA5D2_MR_USEQ BIT(31) + +/* Channel Sequence Register 1 */ +#define AT91_SAMA5D2_SEQR1 0x08 +/* Channel Sequence Register 2 */ +#define AT91_SAMA5D2_SEQR2 0x0c +/* Channel Enable Register */ +#define AT91_SAMA5D2_CHER 0x10 +/* Channel Disable Register */ +#define AT91_SAMA5D2_CHDR 0x14 +/* Channel Status Register */ +#define AT91_SAMA5D2_CHSR 0x18 +/* Last Converted Data Register */ +#define AT91_SAMA5D2_LCDR 0x20 +/* Interrupt Enable Register */ +#define AT91_SAMA5D2_IER 0x24 +/* Interrupt Disable Register */ +#define AT91_SAMA5D2_IDR 0x28 +/* Interrupt Mask Register */ +#define AT91_SAMA5D2_IMR 0x2c +/* Interrupt Status Register */ +#define AT91_SAMA5D2_ISR 0x30 +/* Last Channel Trigger Mode Register */ +#define AT91_SAMA5D2_LCTMR 0x34 +/* Last Channel Compare Window Register */ +#define AT91_SAMA5D2_LCCWR 0x38 +/* Overrun Status Register */ +#define AT91_SAMA5D2_OVER 0x3c +/* Extended Mode Register */ +#define AT91_SAMA5D2_EMR 0x40 +/* Compare Window Register */ +#define AT91_SAMA5D2_CWR 0x44 +/* Channel Gain Register */ +#define AT91_SAMA5D2_CGR 0x48 +/* Channel Offset Register */ +#define AT91_SAMA5D2_COR 0x4c +/* Channel Data Register 0 */ +#define AT91_SAMA5D2_CDR0 0x50 +/* Analog Control Register */ +#define AT91_SAMA5D2_ACR 0x94 +/* Touchscreen Mode Register */ +#define AT91_SAMA5D2_TSMR 0xb0 +/* Touchscreen X Position Register */ +#define AT91_SAMA5D2_XPOSR 0xb4 +/* Touchscreen Y Position Register */ +#define AT91_SAMA5D2_YPOSR 0xb8 +/* Touchscreen Pressure Register */ +#define AT91_SAMA5D2_PRESSR 0xbc +/* Trigger Register */ +#define AT91_SAMA5D2_TRGR 0xc0 +/* Correction Select Register */ +#define AT91_SAMA5D2_COSR 0xd0 +/* Correction Value Register */ +#define AT91_SAMA5D2_CVR 0xd4 +/* Channel Error Correction Register */ +#define AT91_SAMA5D2_CECR 0xd8 +/* Write Protection Mode Register */ +#define AT91_SAMA5D2_WPMR 0xe4 +/* Write Protection Status Register */ +#define AT91_SAMA5D2_WPSR 0xe8 +/* Version Register */ +#define AT91_SAMA5D2_VERSION 0xfc + +#define AT91_AT91_SAMA5D2_CHAN(num, addr) \ + { \ + .type = IIO_VOLTAGE, \ + .channel = num, \ + .address = addr, \ + .scan_type = { \ + .sign = 'u', \ + .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, \ + .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) + +struct at91_adc_soc_info { + unsigned startup_time; + unsigned min_sample_rate; + unsigned max_sample_rate; +}; + +struct at91_adc_state { + void __iomem *base; + int irq; + struct clk *per_clk; + struct regulator *reg; + struct regulator *vref; + u32 vref_uv; + const struct iio_chan_spec *chan; + bool conversion_done; + u32 conversion_value; + struct at91_adc_soc_info soc_info; + wait_queue_head_t wq_data_available; + /* + * lock to prevent concurrent 'single conversion' requests through + * sysfs. + */ + struct mutex lock; +}; + +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), +}; + +static unsigned at91_adc_startup_time(unsigned startup_time_min, + unsigned adc_clk_khz) +{ + const unsigned startup_lookup[] = { + 0, 8, 16, 24, + 64, 80, 96, 112, + 512, 576, 640, 704, + 768, 832, 896, 960 + }; + unsigned ticks_min, i; + + /* + * Since the adc frequency is checked before, there is no reason + * to not meet the startup time constraint. + */ + + ticks_min = startup_time_min * adc_clk_khz / 1000; + for (i = 0; i < ARRAY_SIZE(startup_lookup); i++) + if (startup_lookup[i] > ticks_min) + break; + + return i; +} + +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; + + f_per = clk_get_rate(st->per_clk); + prescal = (f_per / (2 * freq)) - 1; + + 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)); + + dev_dbg(&indio_dev->dev, "freq: %u, startup: %u, prescal: %u\n", + freq, startup, prescal); +} + +static unsigned at91_adc_get_sample_freq(struct at91_adc_state *st) +{ + unsigned f_adc, f_per = clk_get_rate(st->per_clk); + unsigned mr, prescal; + + mr = at91_adc_readl(st, AT91_SAMA5D2_MR); + prescal = (mr >> AT91_SAMA5D2_MR_PRESCAL_OFFSET) + & AT91_SAMA5D2_MR_PRESCAL_MAX; + f_adc = f_per / (2 * (prescal + 1)); + + return f_adc; +} + +static irqreturn_t at91_adc_interrupt(int irq, void *private) +{ + struct iio_dev *indio = private; + struct at91_adc_state *st = iio_priv(indio); + u32 status = at91_adc_readl(st, AT91_SAMA5D2_ISR); + u32 imr = at91_adc_readl(st, AT91_SAMA5D2_IMR); + + if (status & imr) { + st->conversion_value = at91_adc_readl(st, st->chan->address); + st->conversion_done = true; + wake_up_interruptible(&st->wq_data_available); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static int at91_adc_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&st->lock); + + st->chan = chan; + + 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); + + ret = wait_event_interruptible_timeout(st->wq_data_available, + st->conversion_done, + msecs_to_jiffies(1000)); + if (ret == 0) + ret = -ETIMEDOUT; + + if (ret > 0) { + *val = st->conversion_value; + ret = IIO_VAL_INT; + st->conversion_done = false; + } + + at91_adc_writel(st, AT91_SAMA5D2_IDR, BIT(chan->channel)); + at91_adc_writel(st, AT91_SAMA5D2_CHDR, BIT(chan->channel)); + + mutex_unlock(&st->lock); + return ret; + + case IIO_CHAN_INFO_SCALE: + *val = st->vref_uv / 1000; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + + case IIO_CHAN_INFO_SAMP_FREQ: + *val = at91_adc_get_sample_freq(st); + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int at91_adc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct at91_adc_state *st = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + + if (val < st->soc_info.min_sample_rate || + val > st->soc_info.max_sample_rate) + return -EINVAL; + + at91_adc_setup_samp_freq(st, val); + + return 0; +} + +static const struct iio_info at91_adc_info = { + .read_raw = &at91_adc_read_raw, + .write_raw = &at91_adc_write_raw, + .driver_module = THIS_MODULE, +}; + +static int at91_adc_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev; + struct at91_adc_state *st; + struct resource *res; + int ret; + + indio_dev = devm_iio_device_alloc(&pdev->dev, + sizeof(struct at91_adc_state)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->dev.parent = &pdev->dev; + indio_dev->name = dev_name(&pdev->dev); + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &at91_adc_info; + indio_dev->channels = at91_adc_channels; + indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels); + + st = iio_priv(indio_dev); + + ret = of_property_read_u32(pdev->dev.of_node, + "atmel,min-sample-rate-hz", + &st->soc_info.min_sample_rate); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,min-sample-rate-hz\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, + "atmel,max-sample-rate-hz", + &st->soc_info.max_sample_rate); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,max-sample-rate-hz\n"); + return ret; + } + + ret = of_property_read_u32(pdev->dev.of_node, "atmel,startup-time-ms", + &st->soc_info.startup_time); + if (ret) { + dev_err(&pdev->dev, + "invalid or missing value for atmel,startup-time-ms\n"); + return ret; + } + + init_waitqueue_head(&st->wq_data_available); + mutex_init(&st->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + st->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(st->base)) + return PTR_ERR(st->base); + + st->irq = platform_get_irq(pdev, 0); + if (st->irq <= 0) { + if (!st->irq) + st->irq = -ENXIO; + + return st->irq; + } + + st->per_clk = devm_clk_get(&pdev->dev, "adc_clk"); + if (IS_ERR(st->per_clk)) + return PTR_ERR(st->per_clk); + + st->reg = devm_regulator_get(&pdev->dev, "vddana"); + if (IS_ERR(st->reg)) + return PTR_ERR(st->reg); + + st->vref = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(st->vref)) + return PTR_ERR(st->vref); + + ret = devm_request_irq(&pdev->dev, st->irq, at91_adc_interrupt, 0, + pdev->dev.driver->name, indio_dev); + if (ret) + return ret; + + ret = regulator_enable(st->reg); + if (ret) + return ret; + + ret = regulator_enable(st->vref); + if (ret) + goto reg_disable; + + st->vref_uv = regulator_get_voltage(st->vref); + if (st->vref_uv <= 0) { + ret = -EINVAL; + goto vref_disable; + } + + at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST); + at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff); + + at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate); + + ret = clk_prepare_enable(st->per_clk); + if (ret) + goto vref_disable; + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto per_clk_disable_unprepare; + + dev_info(&pdev->dev, "version: %x\n", + readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); + + return 0; + +per_clk_disable_unprepare: + clk_disable_unprepare(st->per_clk); +vref_disable: + regulator_disable(st->vref); +reg_disable: + regulator_disable(st->reg); + return ret; +} + +static int at91_adc_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct at91_adc_state *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + + clk_disable_unprepare(st->per_clk); + + regulator_disable(st->vref); + regulator_disable(st->reg); + + return 0; +} + +static const struct of_device_id at91_adc_dt_match[] = { + { + .compatible = "atmel,sama5d2-adc", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, at91_adc_dt_match); + +static struct platform_driver at91_adc_driver = { + .probe = at91_adc_probe, + .remove = at91_adc_remove, + .driver = { + .name = "at91-sama5d2_adc", + .of_match_table = at91_adc_dt_match, + }, +}; +module_platform_driver(at91_adc_driver) + +MODULE_AUTHOR("Ludovic Desroches "); +MODULE_DESCRIPTION("Atmel AT91 SAMA5D2 ADC"); +MODULE_LICENSE("GPL v2"); -- cgit From b9cd7a254d17dac8098517afdebdac482e59aec4 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Fri, 15 Jan 2016 09:54:18 +0100 Subject: MAINTAINERS: add entry for Atmel SAMA5D2 ADC driver Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- MAINTAINERS | 6 ++++++ drivers/iio/adc/Kconfig | 3 +-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9bff63cf326e..6ddb488d78f6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1903,6 +1903,12 @@ M: Nicolas Ferre S: Supported F: drivers/tty/serial/atmel_serial.c +ATMEL SAMA5D2 ADC DRIVER +M: Ludovic Desroches +L: linux-iio@vger.kernel.org +S: Supported +F: drivers/iio/adc/at91-sama5d2_adc.c + ATMEL Audio ALSA driver M: Nicolas Ferre L: alsa-devel@alsa-project.org (moderated for non-subscribers) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index af4cb8e167b7..60673b40f2c3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -133,8 +133,7 @@ config AT91_ADC config AT91_SAMA5D2_ADC tristate "Atmel AT91 SAMA5D2 ADC" - depends on ARCH_AT91 - depends on INPUT + depends on ARCH_AT91 || COMPILE_TEST help Say yes here to build support for Atmel SAMA5D2 ADC which is available on SAMA5D2 SoC family. -- cgit From 4ea71e5cee8ad52407ee95c3548d0887eedae301 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 8 Jan 2016 00:40:30 +0900 Subject: iio: adc: mcp320x: support more differential voltage measurement mcp320x driver supports the pseudo-differential mode by in_voltage'IN+'-voltage'IN-'_raw where (IN+, IN-) = (0, 1), (2, 3), ... mcp320x chips except MCP3X01 can also select swapped IN+ and IN- pairs in the pseudo-differential mode. i.e. in_voltage'IN+'-voltage'IN-'_raw where (IN+, IN-) = (1, 0), (3, 2), ... If the voltage level of IN+ is equal to or less than IN-, the resultant code will be 000h. So it is useful to provide these, too. Signed-off-by: Akinobu Mita Cc: Oskar Andero Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/adc/mcp320x.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index d1c05f6eed18..a850ca7d1eda 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -187,26 +187,27 @@ out: .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ } -#define MCP320X_VOLTAGE_CHANNEL_DIFF(num) \ +#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2) \ { \ .type = IIO_VOLTAGE, \ .indexed = 1, \ - .channel = (num * 2), \ - .channel2 = (num * 2 + 1), \ - .address = (num * 2), \ + .channel = (chan1), \ + .channel2 = (chan2), \ + .address = (chan1), \ .differential = 1, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ } static const struct iio_chan_spec mcp3201_channels[] = { - MCP320X_VOLTAGE_CHANNEL_DIFF(0), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), }; static const struct iio_chan_spec mcp3202_channels[] = { MCP320X_VOLTAGE_CHANNEL(0), MCP320X_VOLTAGE_CHANNEL(1), - MCP320X_VOLTAGE_CHANNEL_DIFF(0), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), + MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), }; static const struct iio_chan_spec mcp3204_channels[] = { @@ -214,8 +215,10 @@ static const struct iio_chan_spec mcp3204_channels[] = { MCP320X_VOLTAGE_CHANNEL(1), MCP320X_VOLTAGE_CHANNEL(2), MCP320X_VOLTAGE_CHANNEL(3), - MCP320X_VOLTAGE_CHANNEL_DIFF(0), - MCP320X_VOLTAGE_CHANNEL_DIFF(1), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), + MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), + MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), + MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), }; static const struct iio_chan_spec mcp3208_channels[] = { @@ -227,10 +230,14 @@ static const struct iio_chan_spec mcp3208_channels[] = { MCP320X_VOLTAGE_CHANNEL(5), MCP320X_VOLTAGE_CHANNEL(6), MCP320X_VOLTAGE_CHANNEL(7), - MCP320X_VOLTAGE_CHANNEL_DIFF(0), - MCP320X_VOLTAGE_CHANNEL_DIFF(1), - MCP320X_VOLTAGE_CHANNEL_DIFF(2), - MCP320X_VOLTAGE_CHANNEL_DIFF(3), + MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1), + MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0), + MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3), + MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2), + MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5), + MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4), + MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7), + MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6), }; static const struct iio_info mcp320x_info = { -- cgit From d9202af2ffa083f096684fd5f4b530aebbc07439 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Sat, 16 Jan 2016 20:22:07 -0800 Subject: Input: rotary_encoder - convert to devm-* api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use managed resource API for simplifying error paths. Signed-off-by: Timo Teräs Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 86 +++++++++++-------------------------- 1 file changed, 25 insertions(+), 61 deletions(-) diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 8aee71986430..ebbadf3f0579 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -211,8 +211,8 @@ static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct devic if (!of_id || !np) return NULL; - pdata = kzalloc(sizeof(struct rotary_encoder_platform_data), - GFP_KERNEL); + pdata = devm_kzalloc(dev, sizeof(struct rotary_encoder_platform_data), + GFP_KERNEL); if (!pdata) return ERR_PTR(-ENOMEM); @@ -277,12 +277,13 @@ static int rotary_encoder_probe(struct platform_device *pdev) } } - encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); - input = input_allocate_device(); - if (!encoder || !input) { - err = -ENOMEM; - goto exit_free_mem; - } + encoder = devm_kzalloc(dev, sizeof(struct rotary_encoder), GFP_KERNEL); + if (!encoder) + return -ENOMEM; + + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; encoder->input = input; encoder->pdata = pdata; @@ -301,16 +302,18 @@ static int rotary_encoder_probe(struct platform_device *pdev) } /* request the GPIOs */ - err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); + err = devm_gpio_request_one(dev, pdata->gpio_a, GPIOF_IN, + dev_name(dev)); if (err) { dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a); - goto exit_free_mem; + return err; } - err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); + err = devm_gpio_request_one(dev, pdata->gpio_b, GPIOF_IN, + dev_name(dev)); if (err) { dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b); - goto exit_free_gpio_a; + return err; } encoder->irq_a = gpio_to_irq(pdata->gpio_a); @@ -331,30 +334,29 @@ static int rotary_encoder_probe(struct platform_device *pdev) default: dev_err(dev, "'%d' is not a valid steps-per-period value\n", pdata->steps_per_period); - err = -EINVAL; - goto exit_free_gpio_b; + return -EINVAL; } - err = request_irq(encoder->irq_a, handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - DRV_NAME, encoder); + err = devm_request_irq(dev, encoder->irq_a, handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRV_NAME, encoder); if (err) { dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); - goto exit_free_gpio_b; + return err; } - err = request_irq(encoder->irq_b, handler, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - DRV_NAME, encoder); + err = devm_request_irq(dev, encoder->irq_b, handler, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRV_NAME, encoder); if (err) { dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); - goto exit_free_irq_a; + return err; } err = input_register_device(input); if (err) { dev_err(dev, "failed to register input device\n"); - goto exit_free_irq_b; + return err; } device_init_wakeup(&pdev->dev, pdata->wakeup_source); @@ -362,43 +364,6 @@ static int rotary_encoder_probe(struct platform_device *pdev) platform_set_drvdata(pdev, encoder); return 0; - -exit_free_irq_b: - free_irq(encoder->irq_b, encoder); -exit_free_irq_a: - free_irq(encoder->irq_a, encoder); -exit_free_gpio_b: - gpio_free(pdata->gpio_b); -exit_free_gpio_a: - gpio_free(pdata->gpio_a); -exit_free_mem: - input_free_device(input); - kfree(encoder); - if (!dev_get_platdata(&pdev->dev)) - kfree(pdata); - - return err; -} - -static int rotary_encoder_remove(struct platform_device *pdev) -{ - struct rotary_encoder *encoder = platform_get_drvdata(pdev); - const struct rotary_encoder_platform_data *pdata = encoder->pdata; - - device_init_wakeup(&pdev->dev, false); - - free_irq(encoder->irq_a, encoder); - free_irq(encoder->irq_b, encoder); - gpio_free(pdata->gpio_a); - gpio_free(pdata->gpio_b); - - input_unregister_device(encoder->input); - kfree(encoder); - - if (!dev_get_platdata(&pdev->dev)) - kfree(pdata); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -432,7 +397,6 @@ static SIMPLE_DEV_PM_OPS(rotary_encoder_pm_ops, static struct platform_driver rotary_encoder_driver = { .probe = rotary_encoder_probe, - .remove = rotary_encoder_remove, .driver = { .name = DRV_NAME, .pm = &rotary_encoder_pm_ops, -- cgit From 599b082095432f083da89ff53d95b4a878e1fca1 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:14:54 -0800 Subject: HID: wacom - request tool info only when we get general events Move wacom_intuos_schedule_prox_event inside wacom_intuos_general so we don't call it when general event data isn't ready. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 99ef77fcfb80..d5dc59af5bbf 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -750,13 +750,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) return 2; } - /* don't report other events if we don't know the ID */ - if (!wacom->id[idx]) { - /* but reschedule a read of the current tool */ - wacom_intuos_schedule_prox_event(wacom); - return 1; - } - return 0; } @@ -897,6 +890,13 @@ static int wacom_intuos_general(struct wacom_wac *wacom) data[0] != WACOM_REPORT_INTUOS_PEN) return 0; + /* don't report events if we don't know the tool ID */ + if (!wacom->id[idx]) { + /* but reschedule a read of the current tool */ + wacom_intuos_schedule_prox_event(wacom); + return 1; + } + x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1); y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1); distance = data[9] >> 2; -- cgit From 4750f5fe293ae34d334189a77da844f8754862ef Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:15:48 -0800 Subject: HID: wacom - make sure wacom_intuos_inout only process in/out events Move general events related data validation to wacom_intuos_general. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index d5dc59af5bbf..c92ea1a24ee4 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -580,11 +580,12 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; struct input_dev *input = wacom->pen_input; - int idx = 0; + int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0; - /* tool number */ - if (features->type == INTUOS) - idx = data[1] & 0x01; + if (!(((data[1] & 0xfc) == 0xc0) || /* in prox */ + ((data[1] & 0xfe) == 0x20) || /* in range */ + ((data[1] & 0xfe) == 0x80))) /* out prox */ + return 0; /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { @@ -676,26 +677,6 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) return 1; } - /* - * don't report events for invalid data - */ - /* older I4 styli don't work with new Cintiqs */ - if ((!((wacom->id[idx] >> 20) & 0x01) && - (features->type == WACOM_21UX2)) || - /* Only large Intuos support Lense Cursor */ - (wacom->tool[idx] == BTN_TOOL_LENS && - (features->type == INTUOS3 || - features->type == INTUOS3S || - features->type == INTUOS4 || - features->type == INTUOS4S || - features->type == INTUOS5 || - features->type == INTUOS5S || - features->type == INTUOSPM || - features->type == INTUOSPS)) || - /* Cintiq doesn't send data when RDY bit isn't set */ - (features->type == CINTIQ && !(data[1] & 0x40))) - return 1; - wacom->shared->stylus_in_proximity = true; if (wacom->shared->touch_down) return 1; @@ -897,6 +878,26 @@ static int wacom_intuos_general(struct wacom_wac *wacom) return 1; } + /* + * don't report events for invalid data + */ + /* older I4 styli don't work with new Cintiqs */ + if ((!((wacom->id[idx] >> 20) & 0x01) && + (features->type == WACOM_21UX2)) || + /* Only large Intuos support Lense Cursor */ + (wacom->tool[idx] == BTN_TOOL_LENS && + (features->type == INTUOS3 || + features->type == INTUOS3S || + features->type == INTUOS4 || + features->type == INTUOS4S || + features->type == INTUOS5 || + features->type == INTUOS5S || + features->type == INTUOSPM || + features->type == INTUOSPS)) || + /* Cintiq doesn't send data when RDY bit isn't set */ + (features->type == CINTIQ && !(data[1] & 0x40))) + return 1; + x = (be16_to_cpup((__be16 *)&data[2]) << 1) | ((data[9] >> 1) & 1); y = (be16_to_cpup((__be16 *)&data[4]) << 1) | (data[9] & 1); distance = data[9] >> 2; -- cgit From c1b03f5511d6aeab3c141c133b492ea492207e64 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:16:06 -0800 Subject: HID: wacom - Cleanup touch arbitration logic stylus_in_proximity was introduced to support touch arbitration before in range was supported. With in range event, the logic changed. stylus_in_proximity should be set for both in prox and in range events. To finish a clean touch arbitration logic, we should send touch up (if it was down) before posting any general pen events. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index c92ea1a24ee4..28f6a9e2ad6f 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -674,19 +674,22 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) wacom->tool[idx] = BTN_TOOL_PEN; break; } + wacom->shared->stylus_in_proximity = true; return 1; } - wacom->shared->stylus_in_proximity = true; - if (wacom->shared->touch_down) - return 1; + /* in Range */ + if ((data[1] & 0xfe) == 0x20) { + wacom->shared->stylus_in_proximity = true; - /* in Range while exiting */ - if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) { - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_PRESSURE, 0); - input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); - return 2; + /* in Range while exiting */ + if (wacom->reporting_data) { + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_report_abs(input, ABS_DISTANCE, wacom->features.distance_max); + return 2; + } + return 1; } /* Exit report */ @@ -871,6 +874,9 @@ static int wacom_intuos_general(struct wacom_wac *wacom) data[0] != WACOM_REPORT_INTUOS_PEN) return 0; + if (wacom->shared->touch_down) + return 1; + /* don't report events if we don't know the tool ID */ if (!wacom->id[idx]) { /* but reschedule a read of the current tool */ -- cgit From 526d6e7b57062c494346149fb2d6aff0be78ed89 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 8 Jan 2016 17:16:25 -0800 Subject: HID: wacom - Add quirks for INTUOSHT2 in range events INTUOSHT2 in range event is not used to indicate in proximity state. INTUOSHT2 only has one stylus. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 28f6a9e2ad6f..e92e1e855a72 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -613,6 +613,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) case 0x885: /* Intuos3 Marker Pen */ case 0x802: /* Intuos4/5 13HD/24HD General Pen */ case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */ + case 0x8e2: /* IntuosHT2 pen */ case 0x022: case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */ case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */ @@ -680,7 +681,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* in Range */ if ((data[1] & 0xfe) == 0x20) { - wacom->shared->stylus_in_proximity = true; + if (features->type != INTUOSHT2) + wacom->shared->stylus_in_proximity = true; /* in Range while exiting */ if (wacom->reporting_data) { -- cgit From 19f4c2ba869517048add62c202f9645b6adf5dfb Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 8 Jan 2016 17:58:49 +0100 Subject: HID: sony: do not bail out when the sixaxis refuses the output report When setting the operational mode, some third party (Speedlink Strike-FX) gamepads refuse the output report. Failing here means we refuse to initialize the gamepad while this should be harmless. The weird part is that the initial commit that added this: a7de9b8 ("HID: sony: Enable Gasia third-party PS3 controllers") mentions this very same controller as one requiring this output report. Anyway, it's broken for one user at least, so let's change it. We will report an error, but at least the controller should work. And no, these devices present themselves as legacy Sony controllers (VID:PID of 054C:0268, as in the official ones) so there are no ways of discriminating them from the official ones. https://bugzilla.redhat.com/show_bug.cgi?id=1255325 Reported-and-tested-by: Max Fedotov Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 9b8db0e0ef1c..b2d2fae7a082 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1420,8 +1420,10 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) } ret = hid_hw_output_report(hdev, buf, 1); - if (ret < 0) - hid_err(hdev, "can't set operational mode: step 3\n"); + if (ret < 0) { + hid_info(hdev, "can't set operational mode: step 3, ignoring\n"); + ret = 0; + } out: kfree(buf); -- cgit From 74500cc859431de12469f12b8e711d65efdc7604 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Wed, 13 Jan 2016 07:40:42 -0700 Subject: HID: sony: Add nyko core controller support This adds rumble and LED support for nyko core controllers using the sino lite chip vendor:1345 product:3008, for PS3. Setting operational mode and output reports are the same as sixaxis but the input report has a different format since the PS3 accepts HID usb devices. For it to work, an exception is needed to skip overriding the report descriptor and use the original one. Signed-off-by: Scott Moreau Acked-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-sony.c | 7 +++++++ 3 files changed, 11 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7e89288b1537..7c1193a4c86f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2003,6 +2003,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b6ff6e78ac54..a382cab8e575 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -872,6 +872,9 @@ #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 +#define USB_VENDOR_ID_SINO_LITE 0x1345 +#define USB_DEVICE_ID_SINO_LITE_CONTROLLER 0x3008 + #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST 0x0046 diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b2d2fae7a082..123b11a25ce6 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -50,6 +50,7 @@ #define MOTION_CONTROLLER_BT BIT(8) #define NAVIGATION_CONTROLLER_USB BIT(9) #define NAVIGATION_CONTROLLER_BT BIT(10) +#define SINO_LITE_CONTROLLER BIT(11) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) @@ -1118,6 +1119,9 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, { struct sony_sc *sc = hid_get_drvdata(hdev); + if (sc->quirks & SINO_LITE_CONTROLLER) + return rdesc; + /* * Some Sony RF receivers wrongly declare the mouse pointer as a * a constant non-data variable. @@ -2523,6 +2527,9 @@ static const struct hid_device_id sony_devices[] = { .driver_data = DUALSHOCK4_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), .driver_data = DUALSHOCK4_CONTROLLER_BT }, + /* Nyko Core Controller for PS3 */ + { HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER), + .driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER }, { } }; MODULE_DEVICE_TABLE(hid, sony_devices); -- cgit From ad07b7a6cf8898e1ec76a2641f6186c80d0b8a29 Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Wed, 13 Jan 2016 07:40:43 -0700 Subject: HID: sony: Fixup output reports for the nyko core controller The nyko core controller uses the same output report format as the sixaxis controllers, but it expects the report id at offset 1. This does not interfere with the official controllers as this byte is considered a padding byte by the current code. Signed-off-by: Scott Moreau Acked-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 123b11a25ce6..173af01ca080 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1802,7 +1802,7 @@ static void sixaxis_send_output_report(struct sony_sc *sc) static const union sixaxis_output_report_01 default_report = { .buf = { 0x01, - 0x00, 0xff, 0x00, 0xff, 0x00, + 0x01, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, -- cgit From 2024315124b43bb8b25a119ec6c614f0647dcc6d Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Mon, 18 Jan 2016 20:13:14 +0600 Subject: x86/asm/entry: Remove unused SAVE_ALL/RESTORE_ALL macros for !CONFIG_x86_64 SAVE_ALL and RESTORE_ALL macros for !CONFIG_X86_64 were introduced in commit: 1a338ac32 commit ('sched, x86: Optimize the preempt_schedule() call') ... and were used in the ___preempt_schedule() and ___preempt_schedule_context() functions from the arch/x86/kernel/preempt.S. But the arch/x86/kernel/preempt.S file was removed in the following commit: 0ad6e3c5 commit ('x86: Speed up ___preempt_schedule*() by using THUNK helpers') The ___preempt_schedule()/___preempt_schedule_context() functions were reimplemeted and do not use SAVE_ALL/RESTORE_ALL anymore. These macros have no users anymore, so we can remove them. Signed-off-by: Alexander Kuleshov Acked-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov 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/1453126394-13717-1-git-send-email-kuleshovmail@gmail.com [ Improved the changelog. ] Signed-off-by: Ingo Molnar --- arch/x86/entry/calling.h | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h index e32206e09868..9a9e5884066c 100644 --- a/arch/x86/entry/calling.h +++ b/arch/x86/entry/calling.h @@ -201,37 +201,6 @@ For 32-bit we have the following conventions - kernel is built with .byte 0xf1 .endm -#else /* CONFIG_X86_64 */ - -/* - * For 32bit only simplified versions of SAVE_ALL/RESTORE_ALL. These - * are different from the entry_32.S versions in not changing the segment - * registers. So only suitable for in kernel use, not when transitioning - * from or to user space. The resulting stack frame is not a standard - * pt_regs frame. The main use case is calling C code from assembler - * when all the registers need to be preserved. - */ - - .macro SAVE_ALL - pushl %eax - pushl %ebp - pushl %edi - pushl %esi - pushl %edx - pushl %ecx - pushl %ebx - .endm - - .macro RESTORE_ALL - popl %ebx - popl %ecx - popl %edx - popl %esi - popl %edi - popl %ebp - popl %eax - .endm - #endif /* CONFIG_X86_64 */ /* -- cgit From a1ff5726081858a9ad98934eff7af6616c576875 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 16 Jan 2016 10:58:12 +0100 Subject: x86/cpufeature: Add AMD AVIC bit CPUID Fn8000_000A_EDX[13] denotes support for AMD's Virtual Interrupt controller, i.e., APIC virtualization. Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: David Kaplan Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Joerg Roedel Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tom Lendacky Link: http://lkml.kernel.org/r/1452938292-12327-1-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 7ad8c9464297..bbf166e805be 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -268,6 +268,7 @@ #define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ #define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ #define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ +#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ /* * BUG word(s) -- cgit From 43c75f933be26422f166d6d869a19997312f4732 Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 30 Nov 2015 10:47:43 -0600 Subject: x86/mm: Streamline and restore probe_memory_block_size() The cumulative effect of the following two commits: bdee237c0343 ("x86: mm: Use 2GB memory block size on large-memory x86-64 systems") 982792c782ef ("x86, mm: probe memory block size for generic x86 64bit") ... is some pretty convoluted code. The first commit also removed code for the UV case without stated reason, which might lead to unexpected change in behavior. This commit has no other (intended) functional change; just seeks to simplify and make the code more understandable, beyond restoring the UV behavior. The whole section with the "tail size" doesn't seem to be reachable, since both the >= 64GB and < 64GB case return, so it was removed. Signed-off-by: Seth Jennings Cc: Daniel J Blueman Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Yinghai Lu Link: http://lkml.kernel.org/r/1448902063-18885-1-git-send-email-sjennings@variantweb.net [ Rewrote the title and changelog. ] Signed-off-by: Ingo Molnar --- arch/x86/mm/init_64.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 8829482d69ec..8f18fec74e67 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -52,6 +52,7 @@ #include #include #include +#include #include #include "mm_internal.h" @@ -1193,26 +1194,13 @@ int kern_addr_valid(unsigned long addr) static unsigned long probe_memory_block_size(void) { - /* start from 2g */ - unsigned long bz = 1UL<<31; + unsigned long bz = MIN_MEMORY_BLOCK_SIZE; - if (totalram_pages >= (64ULL << (30 - PAGE_SHIFT))) { - pr_info("Using 2GB memory block size for large-memory system\n"); - return 2UL * 1024 * 1024 * 1024; - } - - /* less than 64g installed */ - if ((max_pfn << PAGE_SHIFT) < (16UL << 32)) - return MIN_MEMORY_BLOCK_SIZE; - - /* get the tail size */ - while (bz > MIN_MEMORY_BLOCK_SIZE) { - if (!((max_pfn << PAGE_SHIFT) & (bz - 1))) - break; - bz >>= 1; - } + /* if system is UV or has 64GB of RAM or more, use large blocks */ + if (is_uv_system() || ((max_pfn << PAGE_SHIFT) >= (64UL << 30))) + bz = 2UL << 30; /* 2GB */ - printk(KERN_DEBUG "memory block size : %ldMB\n", bz >> 20); + pr_info("x86/mm: Memory block size: %ldMB\n", bz >> 20); return bz; } -- cgit From 95d97adb2bb85d964bae4538e0574e742e522dda Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 17 Dec 2015 23:56:52 +0000 Subject: x86/signal: Cleanup get_nr_restart_syscall() Check for TS_COMPAT instead of TIF_IA32 to distinguish ia32 tasks from 64-bit tasks. Check for __X32_SYSCALL_BIT iff CONFIG_X86_X32_ABI is defined. Suggested-by: Andy Lutomirski Signed-off-by: Dmitry V. Levin Acked-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Elvira Khabirova Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160111145515.GB29007@altlinux.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/signal.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index cb6282c3638f..c07ff5ddbd47 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -692,12 +692,15 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs) { -#if defined(CONFIG_X86_32) || !defined(CONFIG_X86_64) +#ifdef CONFIG_X86_64 + if (is_ia32_task()) + return __NR_ia32_restart_syscall; +#endif +#ifdef CONFIG_X86_X32_ABI + return __NR_restart_syscall | (regs->orig_ax & __X32_SYSCALL_BIT); +#else return __NR_restart_syscall; -#else /* !CONFIG_X86_32 && CONFIG_X86_64 */ - return test_thread_flag(TIF_IA32) ? __NR_ia32_restart_syscall : - __NR_restart_syscall | (regs->orig_ax & __X32_SYSCALL_BIT); -#endif /* CONFIG_X86_32 || !CONFIG_X86_64 */ +#endif } /* -- cgit From 997963edd912a6d77d68b2bbc19f40ce8facabd7 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Fri, 18 Dec 2015 06:39:18 -0600 Subject: x86/asm: Clean up frame pointer macros The asm macros for setting up and restoring the frame pointer aren't currently being used. However, they will be needed soon to help asm functions to comply with stacktool. Rename FRAME/ENDFRAME to FRAME_BEGIN/FRAME_END for more symmetry. Also make the code more readable and improve the comments. Signed-off-by: Josh Poimboeuf Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Arnaldo Carvalho de Melo Cc: Bernd Petrovitsch Cc: Borislav Petkov Cc: Brian Gerst Cc: Chris J Arges Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jiri Slaby Cc: Linus Torvalds Cc: Michal Marek Cc: Namhyung Kim Cc: Pedro Alves Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/3f488a8e3bfc8ac7d4d3d350953e664e7182b044.1450442274.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/frame.h | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h index 793179cf8e21..cec213bd6eba 100644 --- a/arch/x86/include/asm/frame.h +++ b/arch/x86/include/asm/frame.h @@ -1,23 +1,34 @@ +#ifndef _ASM_X86_FRAME_H +#define _ASM_X86_FRAME_H + #ifdef __ASSEMBLY__ #include -/* The annotation hides the frame from the unwinder and makes it look - like a ordinary ebp save/restore. This avoids some special cases for - frame pointer later */ +/* + * These are stack frame creation macros. They should be used by every + * callable non-leaf asm function to make kernel stack traces more reliable. + */ #ifdef CONFIG_FRAME_POINTER - .macro FRAME - __ASM_SIZE(push,) %__ASM_REG(bp) - __ASM_SIZE(mov) %__ASM_REG(sp), %__ASM_REG(bp) - .endm - .macro ENDFRAME - __ASM_SIZE(pop,) %__ASM_REG(bp) - .endm -#else - .macro FRAME - .endm - .macro ENDFRAME - .endm -#endif + +.macro FRAME_BEGIN + push %_ASM_BP + _ASM_MOV %_ASM_SP, %_ASM_BP +.endm + +.macro FRAME_END + pop %_ASM_BP +.endm + +#define FRAME_OFFSET __ASM_SEL(4, 8) + +#else /* !CONFIG_FRAME_POINTER */ + +#define FRAME_BEGIN +#define FRAME_END +#define FRAME_OFFSET 0 + +#endif /* CONFIG_FRAME_POINTER */ #endif /* __ASSEMBLY__ */ +#endif /* _ASM_X86_FRAME_H */ -- cgit From ec5186557abbe711dfd34e1863735dfecb0602cc Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Fri, 18 Dec 2015 06:39:19 -0600 Subject: x86/asm: Add C versions of frame pointer macros Add C versions of the frame pointer macros which can be used to create a stack frame in inline assembly. Signed-off-by: Josh Poimboeuf Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Arnaldo Carvalho de Melo Cc: Bernd Petrovitsch Cc: Borislav Petkov Cc: Brian Gerst Cc: Chris J Arges Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jiri Slaby Cc: Linus Torvalds Cc: Michal Marek Cc: Namhyung Kim Cc: Pedro Alves Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/f6786a282bf232ede3e2866414eae3cf02c7d662.1450442274.git.jpoimboe@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/frame.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h index cec213bd6eba..6e4d170726b7 100644 --- a/arch/x86/include/asm/frame.h +++ b/arch/x86/include/asm/frame.h @@ -1,16 +1,17 @@ #ifndef _ASM_X86_FRAME_H #define _ASM_X86_FRAME_H -#ifdef __ASSEMBLY__ - #include /* * These are stack frame creation macros. They should be used by every * callable non-leaf asm function to make kernel stack traces more reliable. */ + #ifdef CONFIG_FRAME_POINTER +#ifdef __ASSEMBLY__ + .macro FRAME_BEGIN push %_ASM_BP _ASM_MOV %_ASM_SP, %_ASM_BP @@ -20,6 +21,16 @@ pop %_ASM_BP .endm +#else /* !__ASSEMBLY__ */ + +#define FRAME_BEGIN \ + "push %" _ASM_BP "\n" \ + _ASM_MOV "%" _ASM_SP ", %" _ASM_BP "\n" + +#define FRAME_END "pop %" _ASM_BP "\n" + +#endif /* __ASSEMBLY__ */ + #define FRAME_OFFSET __ASM_SEL(4, 8) #else /* !CONFIG_FRAME_POINTER */ @@ -30,5 +41,4 @@ #endif /* CONFIG_FRAME_POINTER */ -#endif /* __ASSEMBLY__ */ #endif /* _ASM_X86_FRAME_H */ -- cgit From 5137b354bc8a5c04edb10d83f8bdb0bf8896fd68 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 18 Jan 2016 22:40:37 -0800 Subject: HID: fix out of bound access in extract() and implement() extract() and implement() access buffer containing reports in 64-bit chunks, but there is no guarantee that buffers are padded to 64 bit boundary. In fact, KASAN has caught such OOB access with i2c-hid and Synaptics touch controller. Instead of trying to hunt all parties that allocate buffers and make sure they are padded, let's switch extract() and implement() to byte access. It is a bit slower, bit we are not dealing with super fast devices here. Also let's fix link to the HID spec while we are at it. Signed-off-by: Dmitry Torokhov Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 90 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 7e89288b1537..16c2c660ab5a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1075,7 +1075,7 @@ static u32 s32ton(__s32 value, unsigned n) * Extract/implement a data field from/to a little endian report (bit array). * * Code sort-of follows HID spec: - * http://www.usb.org/developers/devclass_docs/HID1_11.pdf + * http://www.usb.org/developers/hidpage/HID1_11.pdf * * While the USB HID spec allows unlimited length bit fields in "report * descriptors", most devices never use more than 16 bits. @@ -1083,20 +1083,37 @@ static u32 s32ton(__s32 value, unsigned n) * Search linux-kernel and linux-usb-devel archives for "hid-core extract". */ -__u32 hid_field_extract(const struct hid_device *hid, __u8 *report, - unsigned offset, unsigned n) -{ - u64 x; +static u32 __extract(u8 *report, unsigned offset, int n) +{ + unsigned int idx = offset / 8; + unsigned int bit_nr = 0; + unsigned int bit_shift = offset % 8; + int bits_to_copy = 8 - bit_shift; + u32 value = 0; + u32 mask = n < 32 ? (1U << n) - 1 : ~0U; + + while (n > 0) { + value |= ((u32)report[idx] >> bit_shift) << bit_nr; + n -= bits_to_copy; + bit_nr += bits_to_copy; + bits_to_copy = 8; + bit_shift = 0; + idx++; + } + + return value & mask; +} - if (n > 32) +u32 hid_field_extract(const struct hid_device *hid, u8 *report, + unsigned offset, unsigned n) +{ + if (n > 32) { hid_warn(hid, "hid_field_extract() called with n (%d) > 32! (%s)\n", n, current->comm); + n = 32; + } - report += offset >> 3; /* adjust byte index */ - offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned_le64(report); - x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ - return (u32) x; + return __extract(report, offset, n); } EXPORT_SYMBOL_GPL(hid_field_extract); @@ -1106,31 +1123,56 @@ EXPORT_SYMBOL_GPL(hid_field_extract); * The data mangled in the bit stream remains in little endian * order the whole time. It make more sense to talk about * endianness of register values by considering a register - * a "cached" copy of the little endiad bit stream. + * a "cached" copy of the little endian bit stream. */ -static void implement(const struct hid_device *hid, __u8 *report, - unsigned offset, unsigned n, __u32 value) + +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] |= 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; + } +} + +static void implement(const struct hid_device *hid, u8 *report, + unsigned offset, unsigned n, u32 value) { - u64 x; - u64 m = (1ULL << n) - 1; + u64 m; - if (n > 32) + if (n > 32) { hid_warn(hid, "%s() called with n (%d) > 32! (%s)\n", __func__, n, current->comm); + n = 32; + } + 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; - report += offset >> 3; - offset &= 7; - - x = get_unaligned_le64(report); - x &= ~(m << offset); - x |= ((u64)value) << offset; - put_unaligned_le64(x, report); + __implement(report, offset, n, value); } /* -- cgit From 50220dead1650609206efe91f0cc116132d59b3f Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 19 Jan 2016 12:34:58 +0100 Subject: HID: core: prevent out-of-bound readings Plugging a Logitech DJ receiver with KASAN activated raises a bunch of out-of-bound readings. The fields are allocated up to MAX_USAGE, meaning that potentially, we do not have enough fields to fit the incoming values. Add checks and silence KASAN. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 16c2c660ab5a..3f6ac5f2862d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1293,6 +1293,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, /* Ignore report if ErrorRollOver */ if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && value[n] >= min && value[n] <= max && + value[n] - min < field->maxusage && field->usage[value[n] - min].hid == HID_UP_KEYBOARD + 1) goto exit; } @@ -1305,11 +1306,13 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, } if (field->value[n] >= min && field->value[n] <= max + && field->value[n] - min < field->maxusage && field->usage[field->value[n] - min].hid && search(value, field->value[n], count)) hid_process_event(hid, field, &field->usage[field->value[n] - min], 0, interrupt); if (value[n] >= min && value[n] <= max + && value[n] - min < field->maxusage && field->usage[value[n] - min].hid && search(field->value, value[n], count)) hid_process_event(hid, field, &field->usage[value[n] - min], 1, interrupt); -- cgit From 320d25b6a05f8b73c23fc21025d2906ecdd2d4fc Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 19 Jan 2016 13:38:58 -0800 Subject: x86/mm/32: Set NX in __supported_pte_mask before enabling paging There's a short window in which very early mappings can end up with NX clear because they are created before we've noticed that we have NX. It turns out that we detect NX very early, so there's no need to defer __supported_pte_mask setup. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Arjan van de Ven Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Mike Galbraith Cc: Pavel Machek Cc: Peter Zijlstra Cc: Stephen Smalley Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/2b544627345f7110160545a3f47031eb45c3ad4f.1453239349.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_32.S | 6 ++++++ arch/x86/mm/setup_nx.c | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 6bc9ae24b6d2..57fc3f8c85fd 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -389,6 +389,12 @@ default_entry: /* Make changes effective */ wrmsr + /* + * And make sure that all the mappings we set up have NX set from + * the beginning. + */ + orl $(1 << (_PAGE_BIT_NX - 32)), pa(__supported_pte_mask + 4) + enable_paging: /* diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 92e2eacb3321..78f5d5907f98 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -31,9 +31,8 @@ early_param("noexec", noexec_setup); void x86_configure_nx(void) { - if (boot_cpu_has(X86_FEATURE_NX) && !disable_nx) - __supported_pte_mask |= _PAGE_NX; - else + /* If disable_nx is set, clear NX on all new mappings going forward. */ + if (disable_nx) __supported_pte_mask &= ~_PAGE_NX; } -- cgit From 7c360572b430a0e9757bafc0c20f26c920f2a07f Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Tue, 19 Jan 2016 13:38:59 -0800 Subject: x86/mm: Make kmap_prot into a #define The value (once we initialize it) is a foregone conclusion. Make it a #define to save a tiny amount of text and data size and to make it more comprehensible. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Arjan van de Ven Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Mike Galbraith Cc: Pavel Machek Cc: Peter Zijlstra Cc: Stephen Smalley Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/0850eb0213de9da88544ff7fae72dc6d06d2b441.1453239349.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/fixmap.h | 2 +- arch/x86/mm/init_32.c | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 6d7d0e52ed5a..8554f960e21b 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -138,7 +138,7 @@ extern void reserve_top_address(unsigned long reserve); extern int fixmaps_set; extern pte_t *kmap_pte; -extern pgprot_t kmap_prot; +#define kmap_prot PAGE_KERNEL extern pte_t *pkmap_page_table; void __native_set_fixmap(enum fixed_addresses idx, pte_t pte); diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index cb4ef3de61f9..a4bb1c7ab65e 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -388,7 +388,6 @@ repeat: } pte_t *kmap_pte; -pgprot_t kmap_prot; static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr) { @@ -405,8 +404,6 @@ static void __init kmap_init(void) */ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - - kmap_prot = PAGE_KERNEL; } #ifdef CONFIG_HIGHMEM -- cgit From a365e668e89d50230737ec20d43fe8fe18412730 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 13 Jan 2016 11:26:44 +0530 Subject: dt: bindings: add bindings for ipq4019 wifi block Add device tree binding documentation details for wifi block present in Qualcomm IPQ4019 SoC into "qcom,ath10k.txt". Right now, ath10k wireless driver has support for PCI based wlan devices. There is a plan to extend ath10k driver to support wifi devices which are connected over AHB as well (enumeration will happen via device tree node). For AHB based devices (ie, ipq4019), all wifi properties are supplied via device tree (including irq, reg addr, cal data,etc). Signed-off-by: Raja Mani Acked-by: Rob Herring [kvalo@qca.qualcomm.com: fixed typos noticed by Rob] Signed-off-by: Kalle Valo --- .../bindings/net/wireless/qcom,ath10k.txt | 89 ++++++++++++++++++++-- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt index edefc26c6204..96aae6b4f736 100644 --- a/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt +++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt @@ -1,17 +1,46 @@ * Qualcomm Atheros ath10k wireless devices -For ath10k devices the calibration data can be provided through Device -Tree. The node is a child node of the PCI controller. - Required properties: --compatible : Should be "qcom,ath10k" +- compatible: Should be one of the following: + * "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. + +AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi" +and also uses most of the properties defined in this doc. Optional properties: +- reg: Address and length of the register set for the device. +- resets: Must contain an entry for each entry in reset-names. + See ../reset/reseti.txt for details. +- reset-names: Must include the list of following reset names, + "wifi_cpu_init" + "wifi_radio_srif" + "wifi_radio_warm" + "wifi_radio_cold" + "wifi_core_warm" + "wifi_core_cold" +- clocks: List of clock specifiers, must contain an entry for each required + entry in clock-names. +- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref", + "wifi_wcss_rtc". +- interrupts: List of interrupt lines. Must contain an entry + for each entry in the interrupt-names property. +- interrupt-names: Must include the entries for MSI interrupt + names ("msi0" to "msi15") and legacy interrupt + name ("legacy"), +- 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 +Example (to supply the calibration data alone): -Example: +In this example, the node is defined as child node of the PCI controller. pci { pcie@0 { @@ -28,3 +57,53 @@ pci { }; }; }; + +Example (to supply ipq4019 SoC wifi block details): + +wifi0: wifi@a000000 { + compatible = "qcom,ipq4019-wifi"; + reg = <0xa000000 0x200000>; + resets = <&gcc WIFI0_CPU_INIT_RESET>, + <&gcc WIFI0_RADIO_SRIF_RESET>, + <&gcc WIFI0_RADIO_WARM_RESET>, + <&gcc WIFI0_RADIO_COLD_RESET>, + <&gcc WIFI0_CORE_WARM_RESET>, + <&gcc WIFI0_CORE_COLD_RESET>; + reset-names = "wifi_cpu_init", + "wifi_radio_srif", + "wifi_radio_warm", + "wifi_radio_cold", + "wifi_core_warm", + "wifi_core_cold"; + clocks = <&gcc GCC_WCSS2G_CLK>, + <&gcc GCC_WCSS2G_REF_CLK>, + <&gcc GCC_WCSS2G_RTC_CLK>; + clock-names = "wifi_wcss_cmd", + "wifi_wcss_ref", + "wifi_wcss_rtc"; + interrupts = <0 0x20 0x1>, + <0 0x21 0x1>, + <0 0x22 0x1>, + <0 0x23 0x1>, + <0 0x24 0x1>, + <0 0x25 0x1>, + <0 0x26 0x1>, + <0 0x27 0x1>, + <0 0x28 0x1>, + <0 0x29 0x1>, + <0 0x2a 0x1>, + <0 0x2b 0x1>, + <0 0x2c 0x1>, + <0 0x2d 0x1>, + <0 0x2e 0x1>, + <0 0x2f 0x1>, + <0 0xa8 0x0>; + interrupt-names = "msi0", "msi1", "msi2", "msi3", + "msi4", "msi5", "msi6", "msi7", + "msi8", "msi9", "msi10", "msi11", + "msi12", "msi13", "msi14", "msi15", + "legacy"; + qcom,msi_addr = <0x0b006040>; + qcom,msi_base = <0x40>; + qcom,ath10k-calibration-data = [ 01 02 03 ... ]; +}; -- cgit From d742c969b3ad9c83ac57579dfd56c90dd437db37 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Wed, 13 Jan 2016 14:52:52 +0100 Subject: ath10k: prevent txrx running for too long On multicore systems it was possible for the txrx tasklet to keep on running for long periods of time on a single CPU due to tx completion processing. Another CPU could feed the running tasklet for an indefinite amount of time. The tasklet is now guaranteed to run a finite amount of time and is limited by HTT CE Rx ring depth. This improves behavior when RPS is used on target system and might improve TCP handling as well. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_rx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 91afa3ae414c..3079434b5d9b 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2156,10 +2156,18 @@ 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_resp *resp; struct sk_buff *skb; + unsigned long flags; - while ((skb = skb_dequeue(&htt->tx_compl_q))) { + __skb_queue_head_init(&tx_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); + + while ((skb = __skb_dequeue(&tx_q))) { ath10k_htt_rx_frm_tx_compl(htt->ar, skb); dev_kfree_skb_any(skb); } -- cgit From de46c015c9b703bb8abb91856ed45e3639c7e7d2 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:28 +0530 Subject: ath10k: add support for parsing per STA rx_duration for 10.2.4 Add support for parsing 'peer_rx_duration' as part of 10.2.4 peer_stats. Also register PEER_STATS service for parsing 'rx_duration' (and for any new fields to be added as part of peer_stats). Have checks for backward compatibility with older 10.2.4 firmware incase PEER_STATS service is not enabled Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 22 ++++++++++++++++++++-- drivers/net/wireless/ath/ath10k/wmi.h | 12 ++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 7840cf3ef7a6..d47a08568bdc 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -159,6 +159,7 @@ struct ath10k_fw_stats_peer { u32 peer_rssi; u32 peer_tx_rate; u32 peer_rx_rate; /* 10x only */ + u32 rx_duration; }; struct ath10k_fw_stats_vdev { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index a7c3d299639b..c610d1761940 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -2862,11 +2862,20 @@ static int ath10k_wmi_10_2_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_2_4_peer_stats *src; + 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) + stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats); + else + stats_len = sizeof(struct wmi_10_2_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); @@ -2876,6 +2885,9 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, ath10k_wmi_pull_peer_stats(&src->common.old, dst); dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); + + if (ext_peer_stats_support) + dst->rx_duration = __le32_to_cpu(src->rx_duration); /* FIXME: expose 10.2 specific values */ list_add_tail(&dst->list, &stats->peers); @@ -5517,6 +5529,9 @@ 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)) + features |= WMI_10_2_PEER_STATS; + cmd->resource_config.feature_mask = __cpu_to_le32(features); memcpy(&cmd->resource_config.common, &config, sizeof(config)); @@ -7126,6 +7141,9 @@ ath10k_wmi_fw_peer_stats_fill(const struct ath10k_fw_stats_peer *peer, "Peer TX rate", peer->peer_tx_rate); len += scnprintf(buf + len, buf_len - len, "%30s %u\n", "Peer RX rate", peer->peer_rx_rate); + len += scnprintf(buf + len, buf_len - len, "%30s %u\n", + "Peer RX duration", peer->rx_duration); + len += scnprintf(buf + len, buf_len - len, "\n"); *length = len; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index d85ad7855d20..e1bb02ba207d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -177,6 +177,7 @@ enum wmi_service { WMI_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_MESH, + WMI_SERVICE_PEER_STATS, /* keep last */ WMI_SERVICE_MAX, @@ -213,6 +214,7 @@ enum wmi_10x_service { WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, WMI_10X_SERVICE_MESH, WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, + WMI_10X_SERVICE_PEER_STATS, }; enum wmi_main_service { @@ -386,6 +388,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); SVCSTR(WMI_SERVICE_MESH); + SVCSTR(WMI_SERVICE_PEER_STATS); default: return NULL; } @@ -463,6 +466,8 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_MESH, len); SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); + SVCMAP(WMI_10X_SERVICE_PEER_STATS, + WMI_SERVICE_PEER_STATS, len); } static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out, @@ -2417,6 +2422,7 @@ enum wmi_10_2_feature_mask { WMI_10_2_RX_BATCH_MODE = BIT(0), WMI_10_2_ATF_CONFIG = BIT(1), WMI_10_2_COEX_GPIO = BIT(3), + WMI_10_2_PEER_STATS = BIT(7), }; struct wmi_resource_config_10_2 { @@ -4230,6 +4236,12 @@ struct wmi_10_2_4_peer_stats { __le32 unknown_value; /* FIXME: what is this word? */ } __packed; +struct wmi_10_2_4_ext_peer_stats { + struct wmi_10_2_peer_stats common; + __le32 peer_rssi_changed; + __le32 rx_duration; +} __packed; + struct wmi_10_4_peer_stats { struct wmi_mac_addr peer_macaddr; __le32 peer_rssi; -- cgit From 962b7a0e77015802f0ceefe6f0e3cad3f10fd4f8 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 4 Jan 2016 10:08:54 +0100 Subject: HID: add HID_QUIRK_NOGET to Quanta 3003 too dmesg shows a lot of: [ 1374.890348] hid-multitouch 0003:0408:3003.0007: usb_submit_urb(ctrl) failed: -1 [ 1384.916388] hid-multitouch 0003:0408:3003.0007: usb_submit_urb(ctrl) failed: -1 [ 1384.916432] hid-multitouch 0003:0408:3003.0007: timeout initializing reports Add the quirk and make the touchscreen happy. Signed-off-by: Benjamin Tissoires Tested-by: Jim lovell Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b6ff6e78ac54..bfd2c9d834d0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -800,6 +800,7 @@ #define USB_VENDOR_ID_QUANTA 0x0408 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH 0x3000 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 +#define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003 0x3003 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 #define USB_VENDOR_ID_RAZER 0x1532 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 7dd0953cd70f..6f0db54c4a9f 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -106,6 +106,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, -- cgit From b429fab4467e2320f67c058d7419c03c7221d125 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 19 Jan 2016 17:14:39 -0800 Subject: regmap: clairify meaning of max_register The exact meaning of max_register is not entierly clear. Follow the common wording and use "address" instead of "index". Signed-off-by: Stefan Agner Signed-off-by: Mark Brown --- include/linux/regmap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 18394343f489..27aaac9027c4 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -162,7 +162,7 @@ typedef void (*regmap_unlock)(void *); * This field is a duplicate of a similar file in * 'struct regmap_bus' and serves exact same purpose. * Use it only for "no-bus" cases. - * @max_register: Optional, specifies the maximum valid register index. + * @max_register: Optional, specifies the maximum valid register address. * @wr_table: Optional, points to a struct regmap_access_table specifying * valid ranges for write access. * @rd_table: As above, for read access. -- cgit From 22363e758770fa24edcc67ba33326f007bcd66a8 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 19 Jan 2016 11:13:12 +0800 Subject: ASoC: ab8500: remove the useless 'break' after 'return' 'break' here is not useful after 'return' or 'goto'. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index affb192238a4..b6820a1f16c7 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2134,7 +2134,6 @@ static int ab8500_codec_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) "%s: ERROR: Unsupporter master mask 0x%x\n", __func__, fmt & SND_SOC_DAIFMT_MASTER_MASK); return -EINVAL; - break; } snd_soc_update_bits(codec, AB8500_DIGIFCONF3, mask, val); -- cgit From 512feb4e19a262ea0dfd7209506a998897feaadc Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 19:35:24 +0800 Subject: ASoC: fsl_sai: Use usleep_range() instead of msleep() Since msleep() will sleep longer than intended time for values less than 20ms, this patch allows the use of usleep_range for just 1ms. usleep_range is a finer precision implementation of msleep and is designed to be a drop-in replacement for udelay where a precise sleep/busy-wait is unnecessary. More details see Documentation/timers/timers-howto.txt. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 43ba5dc26775..4919de9684eb 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -884,7 +885,7 @@ static int fsl_sai_resume(struct device *dev) regcache_cache_only(sai->regmap, false); regmap_write(sai->regmap, FSL_SAI_TCSR, FSL_SAI_CSR_SR); regmap_write(sai->regmap, FSL_SAI_RCSR, FSL_SAI_CSR_SR); - msleep(1); + usleep_range(1000, 2000); regmap_write(sai->regmap, FSL_SAI_TCSR, 0); regmap_write(sai->regmap, FSL_SAI_RCSR, 0); return regcache_sync(sai->regmap); -- cgit From 0d55ad456337487e8cdb72acdd520050e575a0bd Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 19:35:25 +0800 Subject: ASoC: fsl-mpc5200: Use usleep_range() instead of msleep() Since msleep() will sleep longer than intended time for values less than 20ms, this patch allows the use of usleep_range for just 1ms. usleep_range is a finer precision implementation of msleep and is designed to be a drop-in replacement for udelay where a precise sleep/busy-wait is unnecessary. More details see Documentation/timers/timers-howto.txt. Signed-off-by: Xiubo Li Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_psc_ac97.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 0bab76051fd8..243700cc29e6 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -127,7 +128,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97) mutex_unlock(&psc_dma->mutex); - msleep(1); + usleep_range(1000, 2000); psc_ac97_warm_reset(ac97); } -- cgit From 678ea0037263bb8afb139c4035be5ad4bc610a2f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:55:16 +0000 Subject: ASoC: rsnd: remove unsed *parent Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 7ee89da4dd5f..df3ab74adf3e 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -64,7 +64,6 @@ #define SSI_NAME "ssi" struct rsnd_ssi { - struct rsnd_ssi *parent; struct rsnd_mod mod; struct rsnd_mod *dma; -- cgit From 7c89746eede3acbbb67f848a741f8bca412986af Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:55:39 +0000 Subject: ASoC: rsnd: use rsnd_mod_init() for ADG Current ADG doesn't use rsnd_mod_init(), but this limitation is no longer necessary. Let's use common rsnd_mod_init() Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 6d3ef366d536..19f5509f908d 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -518,13 +518,8 @@ int rsnd_adg_probe(struct rsnd_priv *priv) return -ENOMEM; } - /* - * ADG is special module. - * Use ADG mod without rsnd_mod_init() to make debug easy - * for rsnd_write/rsnd_read - */ - adg->mod.ops = &adg_ops; - adg->mod.priv = priv; + rsnd_mod_init(priv, &adg->mod, &adg_ops, + NULL, 0, 0); rsnd_adg_get_clkin(priv, adg); rsnd_adg_get_clkout(priv, adg); -- cgit From 4e880b2674a6d36d6c7b9741d88973e00a76922b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:55:57 +0000 Subject: ASoC: rsnd: add debug message for rsnd_mod_call() rsnd_mod_call() tries to call each IP's relevant function. But it is difficult to understand which function returned error. This patch adds debug message for this purpose Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ca05a0a95a4d..691e22381280 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -337,6 +337,9 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) *status, call ? #func : ""); \ if (call) \ ret = (mod)->ops->func(mod, io, param); \ + if (ret) \ + dev_dbg(dev, "%s[%d] : rsnd_mod_call error %d\n", \ + rsnd_mod_name(mod), rsnd_mod_id(mod), ret); \ ret; \ }) -- cgit From 6c001f3ab4ce20f01a1b3064b2bd1a9352c5d6b1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:56:18 +0000 Subject: ASoC: rsnd: don't update status if rsnd_mod_call() doesn't match If system uses CTU/MUX, and if probe error happened, it will try to call rsnd_dai_call(remove, ...). Then, MUX/DVC/SSIU/SSI might be called without calling rsnd_dai_call(probe, ...). Then, each mod status might be un-matched. It doesn't call un-matched remove function by this patch. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 691e22381280..3eb7e9a7b5dc 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -330,8 +330,11 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ int ret = 0; \ int call = (val == __rsnd_mod_call_##func) && (mod)->ops->func; \ - *status = (*status & ~mask) + \ - (add << __rsnd_mod_shift_##func); \ + if (add == 0xF) \ + call = 0; \ + else \ + *status = (*status & ~mask) + \ + (add << __rsnd_mod_shift_##func); \ dev_dbg(dev, "%s[%d]\t0x%08x %s\n", \ rsnd_mod_name(mod), rsnd_mod_id(mod), \ *status, call ? #func : ""); \ -- cgit From bfa3119c38afb8177f8e403b9e9b2ecd0306bb26 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:56:36 +0000 Subject: ASoC: rsnd: try to connect connected mod is not error If system uses CTU/MUX, CTU/MUX/DVC will try to connect same CMD to system, but it is not error in this case. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 3eb7e9a7b5dc..ad97ce3ae844 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -369,6 +369,9 @@ int rsnd_dai_connect(struct rsnd_mod *mod, if (!mod) return -EIO; + if (io->mod[type] == mod) + return 0; + if (io->mod[type]) return -EINVAL; -- cgit From ea96380baa2794cb6e0d5bfbcca0c78b237a5f8a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:56:59 +0000 Subject: ASoC: rsnd: always call probe/remove for MUX CTU/MUX/DVC/SSIU/SSI/Audio-DMAC-periperi might be used under multipath. So, probe()/remove() need to be called multiple times. This patch allows it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 1 + sound/soc/sh/rcar/rsnd.h | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ad97ce3ae844..ed0918967def 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -163,6 +163,7 @@ void rsnd_mod_quit(struct rsnd_mod *mod) { if (mod->clk) clk_unprepare(mod->clk); + mod->clk = NULL; } void rsnd_mod_interrupt(struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 317dd793149a..c7b2ba0daf2a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -237,29 +237,29 @@ struct rsnd_mod { /* * status * - * 0xH0000CBA + * 0xH0000CB0 * - * A 0: probe 1: remove * B 0: init 1: quit * C 0: start 1: stop * * H is always called (see __rsnd_mod_call) + * H 0: probe 1: remove * H 0: pcm_new * H 0: fallback * H 0: hw_params */ -#define __rsnd_mod_shift_probe 0 -#define __rsnd_mod_shift_remove 0 #define __rsnd_mod_shift_init 4 #define __rsnd_mod_shift_quit 4 #define __rsnd_mod_shift_start 8 #define __rsnd_mod_shift_stop 8 +#define __rsnd_mod_shift_probe 28 /* always called */ +#define __rsnd_mod_shift_remove 28 /* always called */ #define __rsnd_mod_shift_pcm_new 28 /* always called */ #define __rsnd_mod_shift_fallback 28 /* always called */ #define __rsnd_mod_shift_hw_params 28 /* always called */ -#define __rsnd_mod_add_probe 1 -#define __rsnd_mod_add_remove -1 +#define __rsnd_mod_add_probe 0 +#define __rsnd_mod_add_remove 0 #define __rsnd_mod_add_init 1 #define __rsnd_mod_add_quit -1 #define __rsnd_mod_add_start 1 @@ -269,7 +269,7 @@ struct rsnd_mod { #define __rsnd_mod_add_hw_params 0 #define __rsnd_mod_call_probe 0 -#define __rsnd_mod_call_remove 1 +#define __rsnd_mod_call_remove 0 #define __rsnd_mod_call_init 0 #define __rsnd_mod_call_quit 1 #define __rsnd_mod_call_start 0 -- cgit From 654a12b86305b1fd78279616f876b8d21d146a5e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:57:17 +0000 Subject: ASoC: rsnd: don't overwrite io on rsnd_cmd_init() Current rsnd_cmd_init() overwrites "io" which will be used end of this function. This patch solved this issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/cmd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index cd1f064e63c4..e77e4935b4ea 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -38,6 +38,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, if (mix) { struct rsnd_dai *rdai; + struct rsnd_dai_stream *tio; int i; u32 path[] = { [0] = 0, @@ -55,12 +56,12 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, */ data = 0; for_each_rsnd_dai(rdai, priv, i) { - io = &rdai->playback; - if (mix == rsnd_io_to_mod_mix(io)) + tio = &rdai->playback; + if (mix == rsnd_io_to_mod_mix(tio)) data |= path[rsnd_mod_id(src)]; - io = &rdai->capture; - if (mix == rsnd_io_to_mod_mix(io)) + tio = &rdai->capture; + if (mix == rsnd_io_to_mod_mix(tio)) data |= path[rsnd_mod_id(src)]; } -- cgit From 72154e50728e8a08940332db20884b63dfa6590d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:57:37 +0000 Subject: ASoC: rsnd: select each SRC correctly for CMD data path To select CMD data patch, it should use correct SRC from each stream in MUX case. But current code is selecting SRC from fixed stream. This patch solves this issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/cmd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index e77e4935b4ea..4b2d50d9a686 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -29,7 +29,6 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, { struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); struct rsnd_mod *mix = rsnd_io_to_mod_mix(io); - struct rsnd_mod *src = rsnd_io_to_mod_src(io); struct device *dev = rsnd_priv_to_dev(priv); u32 data; @@ -38,6 +37,7 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, if (mix) { struct rsnd_dai *rdai; + struct rsnd_mod *src; struct rsnd_dai_stream *tio; int i; u32 path[] = { @@ -57,15 +57,19 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, data = 0; for_each_rsnd_dai(rdai, priv, i) { tio = &rdai->playback; + src = rsnd_io_to_mod_src(tio); if (mix == rsnd_io_to_mod_mix(tio)) data |= path[rsnd_mod_id(src)]; tio = &rdai->capture; + src = rsnd_io_to_mod_src(tio); if (mix == rsnd_io_to_mod_mix(tio)) data |= path[rsnd_mod_id(src)]; } } else { + struct rsnd_mod *src = rsnd_io_to_mod_src(io); + u32 path[] = { [0] = 0x30000, [1] = 0x30001, -- cgit From 5ba17b42e1755c3c5cfe96370cfd47f34d01f62c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:58:07 +0000 Subject: ASoC: rsnd: each mod has status again for CTU/MUX support SSI will be used as normal SSI or as clock parent SSI. Therefor, rsnd driver wants to control SSI and parent SSI separately. Otherwise it can't use Playback/Capture in the same time. And it has been done by c2dc47d5cf("ASoC: rsnd: rsnd_dai_stream has each mod's status insted of rsnd_mod") before. OTOH, rsnd driver doesn't want to control CTU/MUX/DVC/SSIU/SSI in separately. Otherwise, these will be re-initialized during playing if MUX merges 2 sounds. Because of these picky reasons, this patch re-defines status on each mod, and add new parent_ssi_status on rsnd_dai_stream. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 2 +- sound/soc/sh/rcar/cmd.c | 3 ++- sound/soc/sh/rcar/core.c | 21 ++++++++++++++++----- sound/soc/sh/rcar/ctu.c | 2 +- sound/soc/sh/rcar/dma.c | 2 +- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/mix.c | 2 +- sound/soc/sh/rcar/rsnd.h | 21 ++++++++++++++++----- sound/soc/sh/rcar/src.c | 3 ++- sound/soc/sh/rcar/ssi.c | 37 ++++++++++++++++++++++++++++++++++++- sound/soc/sh/rcar/ssiu.c | 3 ++- 11 files changed, 79 insertions(+), 19 deletions(-) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 19f5509f908d..d74e1ccc0f8f 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -519,7 +519,7 @@ int rsnd_adg_probe(struct rsnd_priv *priv) } rsnd_mod_init(priv, &adg->mod, &adg_ops, - NULL, 0, 0); + NULL, NULL, 0, 0); rsnd_adg_get_clkin(priv, adg); rsnd_adg_get_clkout(priv, adg); diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index 4b2d50d9a686..abb5eaac854a 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -157,7 +157,8 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) for_each_rsnd_cmd(cmd, priv, i) { ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), - &rsnd_cmd_ops, NULL, RSND_MOD_CMD, i); + &rsnd_cmd_ops, NULL, + rsnd_mod_get_status, RSND_MOD_CMD, i); if (ret) return ret; } diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ed0918967def..b460d714d088 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -138,12 +138,22 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, return mod->ops->dma_req(io, mod); } +u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + enum rsnd_mod_type type) +{ + return &mod->status; +} + int rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, - struct rsnd_mod_ops *ops, - struct clk *clk, - enum rsnd_mod_type type, - int id) + struct rsnd_mod_ops *ops, + struct clk *clk, + u32* (*get_status)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + enum rsnd_mod_type type), + enum rsnd_mod_type type, + int id) { int ret = clk_prepare(clk); @@ -155,6 +165,7 @@ int rsnd_mod_init(struct rsnd_priv *priv, mod->type = type; mod->clk = clk; mod->priv = priv; + mod->get_status = get_status; return ret; } @@ -325,7 +336,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) struct rsnd_priv *priv = rsnd_mod_to_priv(mod); \ struct rsnd_mod *mod = (io)->mod[idx]; \ struct device *dev = rsnd_priv_to_dev(priv); \ - u32 *status = (io)->mod_status + idx; \ + u32 *status = mod->get_status(io, mod, idx); \ u32 mask = 0xF << __rsnd_mod_shift_##func; \ u8 val = (*status >> __rsnd_mod_shift_##func) & 0xF; \ u8 add = ((val + __rsnd_mod_add_##func) & 0xF); \ diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index d53a225d19e9..109930a20401 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -129,7 +129,7 @@ int rsnd_ctu_probe(struct rsnd_priv *priv) } ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops, - clk, RSND_MOD_CTU, i); + clk, rsnd_mod_get_status, RSND_MOD_CTU, i); if (ret) goto rsnd_ctu_probe_done; diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 418e6fdd06a3..d1cb3c177572 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -681,7 +681,7 @@ struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, dma_mod = rsnd_mod_get(dma); ret = rsnd_mod_init(priv, dma_mod, - ops, NULL, type, dma_id); + ops, NULL, rsnd_mod_get_status, type, dma_id); if (ret < 0) return ERR_PTR(ret); diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index d45ffe496397..302c193f674d 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -373,7 +373,7 @@ int rsnd_dvc_probe(struct rsnd_priv *priv) } ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops, - clk, RSND_MOD_DVC, i); + clk, rsnd_mod_get_status, RSND_MOD_DVC, i); if (ret) goto rsnd_dvc_probe_done; diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 65542b6a89e9..e0e337ad4206 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -172,7 +172,7 @@ int rsnd_mix_probe(struct rsnd_priv *priv) } ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops, - clk, RSND_MOD_MIX, i); + clk, rsnd_mod_get_status, RSND_MOD_MIX, i); if (ret) goto rsnd_mix_probe_done; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c7b2ba0daf2a..28602607cf5e 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -233,6 +233,10 @@ struct rsnd_mod { struct rsnd_mod_ops *ops; struct rsnd_priv *priv; struct clk *clk; + u32 *(*get_status)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + enum rsnd_mod_type type); + u32 status; }; /* * status @@ -286,10 +290,13 @@ struct rsnd_mod { int rsnd_mod_init(struct rsnd_priv *priv, struct rsnd_mod *mod, - struct rsnd_mod_ops *ops, - struct clk *clk, - enum rsnd_mod_type type, - int id); + struct rsnd_mod_ops *ops, + struct clk *clk, + u32* (*get_status)(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + enum rsnd_mod_type type), + enum rsnd_mod_type type, + int id); void rsnd_mod_quit(struct rsnd_mod *mod); char *rsnd_mod_name(struct rsnd_mod *mod); struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, @@ -297,6 +304,10 @@ struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io, void rsnd_mod_interrupt(struct rsnd_mod *mod, void (*callback)(struct rsnd_mod *mod, struct rsnd_dai_stream *io)); +u32 *rsnd_mod_get_status(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + enum rsnd_mod_type type); + void rsnd_parse_connect_common(struct rsnd_dai *rdai, struct rsnd_mod* (*mod_get)(struct rsnd_priv *priv, int id), struct device_node *node, @@ -319,7 +330,7 @@ struct rsnd_dai_stream { struct rsnd_mod *mod[RSND_MOD_MAX]; struct rsnd_dai_path_info *info; /* rcar_snd.h */ struct rsnd_dai *rdai; - u32 mod_status[RSND_MOD_MAX]; + u32 parent_ssi_status; int byte_pos; int period_pos; int byte_per_period; diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index b438538a0a69..516b0c05451c 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -615,7 +615,8 @@ int rsnd_src_probe(struct rsnd_priv *priv) } ret = rsnd_mod_init(priv, rsnd_mod_get(src), - &rsnd_src_ops, clk, RSND_MOD_SRC, i); + &rsnd_src_ops, clk, rsnd_mod_get_status, + RSND_MOD_SRC, i); if (ret) goto rsnd_src_probe_done; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index df3ab74adf3e..e68f3a1c9cb4 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -857,6 +857,41 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod) return !!(rsnd_ssi_mode_flags(ssi) & RSND_SSI_CLK_PIN_SHARE); } +static u32 *rsnd_ssi_get_status(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, + enum rsnd_mod_type type) +{ + /* + * SSIP (= SSI parent) needs to be special, otherwise, + * 2nd SSI might doesn't start. see also rsnd_mod_call() + * + * We can't include parent SSI status on SSI, because we don't know + * how many SSI requests parent SSI. Thus, it is localed on "io" now. + * ex) trouble case + * Playback: SSI0 + * Capture : SSI1 (needs SSI0) + * + * 1) start Capture -> SSI0/SSI1 are started. + * 2) start Playback -> SSI0 doesn't work, because it is already + * marked as "started" on 1) + * + * OTOH, using each mod's status is good for MUX case. + * It doesn't need to start in 2nd start + * ex) + * IO-0: SRC0 -> CTU1 -+-> MUX -> DVC -> SSIU -> SSI0 + * | + * IO-1: SRC1 -> CTU2 -+ + * + * 1) start IO-0 -> start SSI0 + * 2) start IO-1 -> SSI0 doesn't need to start, because it is + * already started on 1) + */ + if (type == RSND_MOD_SSIP) + return &io->parent_ssi_status; + + return rsnd_mod_get_status(io, mod, type); +} + int rsnd_ssi_probe(struct rsnd_priv *priv) { struct device_node *node; @@ -919,7 +954,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv) ops = &rsnd_ssi_dma_ops; ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk, - RSND_MOD_SSI, i); + rsnd_ssi_get_status, RSND_MOD_SSI, i); if (ret) goto rsnd_ssi_probe_done; diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 06d72828e5bc..11e55889b401 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -206,7 +206,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) for_each_rsnd_ssiu(ssiu, priv, i) { ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu), - ops, NULL, RSND_MOD_SSIU, i); + ops, NULL, rsnd_mod_get_status, + RSND_MOD_SSIU, i); if (ret) return ret; } -- cgit From 355cb84fbe1f098f80c17dad9027ad2c6aec3fa0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:58:33 +0000 Subject: ASoC: rsnd: attach Audio-DMAC-periperi correctly SSI/SRC will try to attach DMAC as Audio-DMAC or Audio-DMAC-periperi. It is fixed IP, but will be attached to each streams as different module in case of MUX (= multi sound path will be merged). This patch solves this issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/dma.c | 56 +++++++++++++++++++++++++----------------------- sound/soc/sh/rcar/rsnd.h | 4 ++-- sound/soc/sh/rcar/src.c | 4 +--- sound/soc/sh/rcar/ssi.c | 5 ++--- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index d1cb3c177572..7658e8fd7bdc 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -622,15 +622,13 @@ static void rsnd_dma_of_path(struct rsnd_mod *this, } } -struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, - struct rsnd_mod *mod, int id) +int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod, + struct rsnd_mod **dma_mod, int id) { - struct rsnd_mod *dma_mod; struct rsnd_mod *mod_from = NULL; struct rsnd_mod *mod_to = NULL; struct rsnd_priv *priv = rsnd_io_to_priv(io); struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); - struct rsnd_dma *dma; struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_mod_ops *ops; enum rsnd_mod_type type; @@ -646,17 +644,10 @@ struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, * rsnd_rdai_continuance_probe() */ if (!dmac) - return ERR_PTR(-EAGAIN); - - dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); - if (!dma) - return ERR_PTR(-ENOMEM); + return -EAGAIN; rsnd_dma_of_path(mod, io, is_play, &mod_from, &mod_to); - dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); - dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); - /* for Gen2 */ if (mod_from && mod_to) { ops = &rsnd_dmapp_ops; @@ -678,27 +669,38 @@ struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, type = RSND_MOD_AUDMA; } - dma_mod = rsnd_mod_get(dma); + if (!(*dma_mod)) { + struct rsnd_dma *dma; - ret = rsnd_mod_init(priv, dma_mod, - ops, NULL, rsnd_mod_get_status, type, dma_id); - if (ret < 0) - return ERR_PTR(ret); + dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL); + if (!dma) + return -ENOMEM; - dev_dbg(dev, "%s[%d] %s[%d] -> %s[%d]\n", - rsnd_mod_name(dma_mod), rsnd_mod_id(dma_mod), - rsnd_mod_name(mod_from), rsnd_mod_id(mod_from), - rsnd_mod_name(mod_to), rsnd_mod_id(mod_to)); + *dma_mod = rsnd_mod_get(dma); - ret = attach(io, dma, id, mod_from, mod_to); - if (ret < 0) - return ERR_PTR(ret); + dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1); + dma->dst_addr = rsnd_dma_addr(io, mod_to, is_play, 0); + + ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, + rsnd_mod_get_status, type, dma_id); + if (ret < 0) + return ret; - ret = rsnd_dai_connect(dma_mod, io, type); + dev_dbg(dev, "%s[%d] %s[%d] -> %s[%d]\n", + rsnd_mod_name(*dma_mod), rsnd_mod_id(*dma_mod), + rsnd_mod_name(mod_from), rsnd_mod_id(mod_from), + rsnd_mod_name(mod_to), rsnd_mod_id(mod_to)); + + ret = attach(io, dma, id, mod_from, mod_to); + if (ret < 0) + return ret; + } + + ret = rsnd_dai_connect(*dma_mod, io, type); if (ret < 0) - return ERR_PTR(ret); + return ret; - return rsnd_mod_get(dma); + return 0; } int rsnd_dma_probe(struct rsnd_priv *priv) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 28602607cf5e..90c732e265a2 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -166,8 +166,8 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io); /* * R-Car DMA */ -struct rsnd_mod *rsnd_dma_attach(struct rsnd_dai_stream *io, - struct rsnd_mod *mod, int id); +int rsnd_dma_attach(struct rsnd_dai_stream *io, + struct rsnd_mod *mod, struct rsnd_mod **dma_mod, int id); int rsnd_dma_probe(struct rsnd_priv *priv); struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, struct rsnd_mod *mod, char *name); diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 516b0c05451c..8dc9b483b5fa 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -495,9 +495,7 @@ static int rsnd_src_probe_(struct rsnd_mod *mod, return ret; } - src->dma = rsnd_dma_attach(io, mod, 0); - if (IS_ERR(src->dma)) - return PTR_ERR(src->dma); + ret = rsnd_dma_attach(io, mod, &src->dma, 0); return ret; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index e68f3a1c9cb4..90674137aa90 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -704,9 +704,8 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod, if (ret) return ret; - ssi->dma = rsnd_dma_attach(io, mod, dma_id); - if (IS_ERR(ssi->dma)) - return PTR_ERR(ssi->dma); + /* SSI probe might be called many times in MUX multi path */ + ret = rsnd_dma_attach(io, mod, &ssi->dma, dma_id); return ret; } -- cgit From bd9a603fe78fa838a9c884b1e67749120a45508c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:58:53 +0000 Subject: ASoC: rsnd: ctu: add rsnd_mix_activation() Based on datasheet Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ctu.c | 9 +++++++++ sound/soc/sh/rcar/gen.c | 1 + sound/soc/sh/rcar/rsnd.h | 1 + 3 files changed, 11 insertions(+) diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 109930a20401..0dc451803eb6 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -24,6 +24,13 @@ struct rsnd_ctu { i++) #define rsnd_ctu_get(priv, id) ((struct rsnd_ctu *)(priv->ctu) + id) + +static void rsnd_ctu_activation(struct rsnd_mod *mod) +{ + rsnd_mod_write(mod, CTU_SWRSR, 0); + rsnd_mod_write(mod, CTU_SWRSR, 1); +} + #define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) #define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) @@ -44,6 +51,8 @@ static int rsnd_ctu_init(struct rsnd_mod *mod, { rsnd_mod_power_on(mod); + rsnd_ctu_activation(mod); + rsnd_ctu_initialize_lock(mod); rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io)); diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index c7aee9e59e86..2f01e5eb462c 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -260,6 +260,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), + RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100), RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 90c732e265a2..12227f6b6221 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -86,6 +86,7 @@ enum rsnd_reg { RSND_REG_CMD_BUSIF_DALIGN, /* Gen2 only */ RSND_REG_CMD_ROUTE_SLCT, RSND_REG_CMDOUT_TIMSEL, /* Gen2 only */ + RSND_REG_CTU_SWRSR, RSND_REG_CTU_CTUIR, RSND_REG_CTU_ADINR, RSND_REG_MIX_SWRSR, -- cgit From d0658b31c712327e04ddc2621742144de5562962 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:59:12 +0000 Subject: ASoC: rsnd: ctu: add rsnd_ctu_halt() Based on datasheet process Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ctu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 0dc451803eb6..7b482f36cb63 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -31,6 +31,12 @@ static void rsnd_ctu_activation(struct rsnd_mod *mod) rsnd_mod_write(mod, CTU_SWRSR, 1); } +static void rsnd_ctu_halt(struct rsnd_mod *mod) +{ + rsnd_mod_write(mod, CTU_CTUIR, 1); + rsnd_mod_write(mod, CTU_SWRSR, 0); +} + #define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) #define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) @@ -66,6 +72,8 @@ static int rsnd_ctu_quit(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { + rsnd_ctu_halt(mod); + rsnd_mod_power_off(mod); return 0; -- cgit From dc037afdbc4f285dc2f8107a0b8eaf89892e28ac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:59:33 +0000 Subject: ASoC: rsnd: ctu: settings matches to datasheet Current CTU settings was rough. This patch makes it match to datasheet. But do nothing at this point. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ctu.c | 61 ++++++++++++++++++++++++++++++++++++++---------- sound/soc/sh/rcar/gen.c | 34 +++++++++++++++++++++++++++ sound/soc/sh/rcar/rsnd.h | 34 +++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 12 deletions(-) diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 7b482f36cb63..a10d0f7b73fa 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -37,13 +37,6 @@ static void rsnd_ctu_halt(struct rsnd_mod *mod) rsnd_mod_write(mod, CTU_SWRSR, 0); } -#define rsnd_ctu_initialize_lock(mod) __rsnd_ctu_initialize_lock(mod, 1) -#define rsnd_ctu_initialize_unlock(mod) __rsnd_ctu_initialize_lock(mod, 0) -static void __rsnd_ctu_initialize_lock(struct rsnd_mod *mod, u32 enable) -{ - rsnd_mod_write(mod, CTU_CTUIR, enable); -} - static int rsnd_ctu_probe_(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -51,6 +44,54 @@ static int rsnd_ctu_probe_(struct rsnd_mod *mod, return rsnd_cmd_attach(io, rsnd_mod_id(mod) / 4); } +static void rsnd_ctu_value_init(struct rsnd_dai_stream *io, + struct rsnd_mod *mod) +{ + rsnd_mod_write(mod, CTU_CTUIR, 1); + + rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io)); + + rsnd_mod_write(mod, CTU_CPMDR, 0); + rsnd_mod_write(mod, CTU_SCMDR, 0); + rsnd_mod_write(mod, CTU_SV00R, 0); + rsnd_mod_write(mod, CTU_SV01R, 0); + rsnd_mod_write(mod, CTU_SV02R, 0); + rsnd_mod_write(mod, CTU_SV03R, 0); + rsnd_mod_write(mod, CTU_SV04R, 0); + rsnd_mod_write(mod, CTU_SV05R, 0); + rsnd_mod_write(mod, CTU_SV06R, 0); + rsnd_mod_write(mod, CTU_SV07R, 0); + + rsnd_mod_write(mod, CTU_SV10R, 0); + rsnd_mod_write(mod, CTU_SV11R, 0); + rsnd_mod_write(mod, CTU_SV12R, 0); + rsnd_mod_write(mod, CTU_SV13R, 0); + rsnd_mod_write(mod, CTU_SV14R, 0); + rsnd_mod_write(mod, CTU_SV15R, 0); + rsnd_mod_write(mod, CTU_SV16R, 0); + rsnd_mod_write(mod, CTU_SV17R, 0); + + rsnd_mod_write(mod, CTU_SV20R, 0); + rsnd_mod_write(mod, CTU_SV21R, 0); + rsnd_mod_write(mod, CTU_SV22R, 0); + rsnd_mod_write(mod, CTU_SV23R, 0); + rsnd_mod_write(mod, CTU_SV24R, 0); + rsnd_mod_write(mod, CTU_SV25R, 0); + rsnd_mod_write(mod, CTU_SV26R, 0); + rsnd_mod_write(mod, CTU_SV27R, 0); + + rsnd_mod_write(mod, CTU_SV30R, 0); + rsnd_mod_write(mod, CTU_SV31R, 0); + rsnd_mod_write(mod, CTU_SV32R, 0); + rsnd_mod_write(mod, CTU_SV33R, 0); + rsnd_mod_write(mod, CTU_SV34R, 0); + rsnd_mod_write(mod, CTU_SV35R, 0); + rsnd_mod_write(mod, CTU_SV36R, 0); + rsnd_mod_write(mod, CTU_SV37R, 0); + + rsnd_mod_write(mod, CTU_CTUIR, 0); +} + static int rsnd_ctu_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) @@ -59,11 +100,7 @@ static int rsnd_ctu_init(struct rsnd_mod *mod, rsnd_ctu_activation(mod); - rsnd_ctu_initialize_lock(mod); - - rsnd_mod_write(mod, CTU_ADINR, rsnd_get_adinr_chan(mod, io)); - - rsnd_ctu_initialize_unlock(mod); + rsnd_ctu_value_init(io, mod); return 0; } diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 2f01e5eb462c..b6e487e06019 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -263,6 +263,40 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100), RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), + RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100), + RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100), + RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100), + RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100), + RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100), + RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100), + RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100), + RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100), + RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100), + RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100), + RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100), + RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100), + RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100), + RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100), + RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100), + RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100), + RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100), + RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100), + RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100), + RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100), + RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100), + RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100), + RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100), + RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100), + RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100), + RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100), + RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100), + RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100), + RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100), + RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100), + RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100), + RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100), + RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100), + RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100), RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40), RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40), RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40), diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 12227f6b6221..4974db6679c3 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -89,6 +89,40 @@ enum rsnd_reg { RSND_REG_CTU_SWRSR, RSND_REG_CTU_CTUIR, RSND_REG_CTU_ADINR, + RSND_REG_CTU_CPMDR, + RSND_REG_CTU_SCMDR, + RSND_REG_CTU_SV00R, + RSND_REG_CTU_SV01R, + RSND_REG_CTU_SV02R, + RSND_REG_CTU_SV03R, + RSND_REG_CTU_SV04R, + RSND_REG_CTU_SV05R, + RSND_REG_CTU_SV06R, + RSND_REG_CTU_SV07R, + RSND_REG_CTU_SV10R, + RSND_REG_CTU_SV11R, + RSND_REG_CTU_SV12R, + RSND_REG_CTU_SV13R, + RSND_REG_CTU_SV14R, + RSND_REG_CTU_SV15R, + RSND_REG_CTU_SV16R, + RSND_REG_CTU_SV17R, + RSND_REG_CTU_SV20R, + RSND_REG_CTU_SV21R, + RSND_REG_CTU_SV22R, + RSND_REG_CTU_SV23R, + RSND_REG_CTU_SV24R, + RSND_REG_CTU_SV25R, + RSND_REG_CTU_SV26R, + RSND_REG_CTU_SV27R, + RSND_REG_CTU_SV30R, + RSND_REG_CTU_SV31R, + RSND_REG_CTU_SV32R, + RSND_REG_CTU_SV33R, + RSND_REG_CTU_SV34R, + RSND_REG_CTU_SV35R, + RSND_REG_CTU_SV36R, + RSND_REG_CTU_SV37R, RSND_REG_MIX_SWRSR, RSND_REG_MIX_MIXIR, RSND_REG_MIX_ADINR, -- cgit From 38587f4cb7937344e12a9eef1ccdc5b8a0e992ba Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:59:55 +0000 Subject: ASoC: rsnd: tidyup Playback/Capture sequence Based on datasheet sequence Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index b460d714d088..1fcefab03ad6 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -358,15 +358,51 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io) ret; \ }) +static enum rsnd_mod_type rsnd_mod_sequence[][RSND_MOD_MAX] = { + { + /* CAPTURE */ + RSND_MOD_AUDMAPP, + RSND_MOD_AUDMA, + RSND_MOD_DVC, + RSND_MOD_MIX, + RSND_MOD_CTU, + RSND_MOD_CMD, + RSND_MOD_SRC, + RSND_MOD_SSIU, + RSND_MOD_SSIM3, + RSND_MOD_SSIM2, + RSND_MOD_SSIM1, + RSND_MOD_SSIP, + RSND_MOD_SSI, + }, { + /* PLAYBACK */ + RSND_MOD_AUDMAPP, + RSND_MOD_AUDMA, + RSND_MOD_SSIM3, + RSND_MOD_SSIM2, + RSND_MOD_SSIM1, + RSND_MOD_SSIP, + RSND_MOD_SSI, + RSND_MOD_SSIU, + RSND_MOD_DVC, + RSND_MOD_MIX, + RSND_MOD_CTU, + RSND_MOD_CMD, + RSND_MOD_SRC, + }, +}; + #define rsnd_dai_call(fn, io, param...) \ ({ \ struct rsnd_mod *mod; \ + int type, is_play = rsnd_io_is_play(io); \ int ret = 0, i; \ for (i = 0; i < RSND_MOD_MAX; i++) { \ - mod = (io)->mod[i]; \ + type = rsnd_mod_sequence[is_play][i]; \ + mod = (io)->mod[type]; \ if (!mod) \ continue; \ - ret |= rsnd_mod_call(i, io, fn, param); \ + ret |= rsnd_mod_call(type, io, fn, param); \ } \ ret; \ }) -- cgit From 31739a689f828345a7ef52fd8dbbb200df1b6555 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 02:00:13 +0000 Subject: ASoC: rsnd: disable SRC.out/in in same time commit b761bf272bce ("ASoC: rsnd: disable SRC.out only when stop timing") disabled SRC.out/in in different timing, but was based on picky HW information. Now, we have confirmed that we can disable both in the same time. This patch do it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/src.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 8dc9b483b5fa..7749615bd404 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -367,11 +367,7 @@ static int rsnd_src_stop(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv) { - /* - * stop SRC output only - * see rsnd_src_quit - */ - rsnd_mod_write(mod, SRC_CTRL, 0x01); + rsnd_mod_write(mod, SRC_CTRL, 0); return 0; } @@ -409,9 +405,6 @@ static int rsnd_src_quit(struct rsnd_mod *mod, rsnd_src_irq_disable(mod); - /* stop both out/in */ - rsnd_mod_write(mod, SRC_CTRL, 0); - rsnd_src_halt(mod); rsnd_mod_power_off(mod); -- cgit From d7bdcc3f57eef075122906e3f38abe2a06868750 Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 18 Jan 2016 09:41:55 +0100 Subject: iio:adc:at91-sama5d2: fix vref_uv type vref_uv has to be an int. Signed-off-by: Ludovic Desroches Reported-by: Julia Lawall Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index ecb2d90c9c06..f2d8bd5deac9 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -171,7 +171,7 @@ struct at91_adc_state { struct clk *per_clk; struct regulator *reg; struct regulator *vref; - u32 vref_uv; + int vref_uv; const struct iio_chan_spec *chan; bool conversion_done; u32 conversion_value; -- cgit From 61be8fde635bf4f7eecaf06af23e7db3c318596a Mon Sep 17 00:00:00 2001 From: Ludovic Desroches Date: Mon, 18 Jan 2016 09:41:56 +0100 Subject: iio:adc:at91-sama5d2: code cleanup Use var type for sizeof argument instead of the struct name. Signed-off-by: Ludovic Desroches Signed-off-by: Jonathan Cameron --- drivers/iio/adc/at91-sama5d2_adc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index f2d8bd5deac9..dbee13ad33a3 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -353,8 +353,7 @@ static int at91_adc_probe(struct platform_device *pdev) struct resource *res; int ret; - indio_dev = devm_iio_device_alloc(&pdev->dev, - sizeof(struct at91_adc_state)); + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; -- cgit From 4b04266abe3ea0c5c8f7a82b4d69f0f8e1e81b0a Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sat, 16 Jan 2016 15:35:20 +0100 Subject: iio: mma8452: add freefall detection for Freescale's accelerometers This adds freefall event detection to the supported devices. It adds the in_accel_x&y&z_mag_falling_en iio event attribute, which activates freefall mode. In freefall mode, the current acceleration magnitude (AND combination of all axis values) is compared to the specified threshold. If it falls under the threshold (in_accel_mag_falling_value), the appropriate IIO event code is generated. This is what the sysfs "events" directory for these devices looks like after this change: -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_falling_period -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_falling_value -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_rising_period -rw-r--r-- 4096 Oct 23 08:45 in_accel_mag_rising_value -r--r--r-- 4096 Oct 23 08:45 in_accel_scale -rw-r--r-- 4096 Oct 23 08:45 in_accel_x&y&z_mag_falling_en -rw-r--r-- 4096 Oct 23 08:45 in_accel_x_mag_rising_en -rw-r--r-- 4096 Oct 23 08:45 in_accel_y_mag_rising_en -rw-r--r-- 4096 Oct 23 08:45 in_accel_z_mag_rising_en Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 160 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 144 insertions(+), 16 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index ccc632a7cf01..77b71c2dfd72 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -15,7 +15,7 @@ * * 7-bit I2C slave address 0x1c/0x1d (pin selectable) * - * TODO: orientation / freefall events, autosleep + * TODO: orientation events, autosleep */ #include @@ -416,6 +416,51 @@ fail: return ret; } +/* returns >0 if in freefall mode, 0 if not or <0 if an error occured */ +static int mma8452_freefall_mode_enabled(struct mma8452_data *data) +{ + int val; + const struct mma_chip_info *chip = data->chip_info; + + val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); + if (val < 0) + return val; + + return !(val & MMA8452_FF_MT_CFG_OAE); +} + +static int mma8452_set_freefall_mode(struct mma8452_data *data, bool state) +{ + int val; + const struct mma_chip_info *chip = data->chip_info; + + if ((state && mma8452_freefall_mode_enabled(data)) || + (!state && !(mma8452_freefall_mode_enabled(data)))) + return 0; + + val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); + if (val < 0) + return val; + + if (state) { + val |= BIT(idx_x + chip->ev_cfg_chan_shift); + val |= BIT(idx_y + chip->ev_cfg_chan_shift); + val |= BIT(idx_z + chip->ev_cfg_chan_shift); + val &= ~MMA8452_FF_MT_CFG_OAE; + } else { + val &= ~BIT(idx_x + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_y + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_z + chip->ev_cfg_chan_shift); + val |= MMA8452_FF_MT_CFG_OAE; + } + + val = mma8452_change_config(data, chip->ev_cfg, val); + if (val) + return val; + + return 0; +} + static int mma8452_set_hp_filter_frequency(struct mma8452_data *data, int val, int val2) { @@ -609,12 +654,22 @@ static int mma8452_read_event_config(struct iio_dev *indio_dev, const struct mma_chip_info *chip = data->chip_info; int ret; - ret = i2c_smbus_read_byte_data(data->client, - data->chip_info->ev_cfg); - if (ret < 0) - return ret; + switch (dir) { + case IIO_EV_DIR_FALLING: + return mma8452_freefall_mode_enabled(data); + case IIO_EV_DIR_RISING: + if (mma8452_freefall_mode_enabled(data)) + return 0; + + ret = i2c_smbus_read_byte_data(data->client, + data->chip_info->ev_cfg); + 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; + } } static int mma8452_write_event_config(struct iio_dev *indio_dev, @@ -627,19 +682,35 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev, const struct mma_chip_info *chip = data->chip_info; int val; - val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); - if (val < 0) - return val; + switch (dir) { + case IIO_EV_DIR_FALLING: + return mma8452_set_freefall_mode(data, state); + case IIO_EV_DIR_RISING: + val = i2c_smbus_read_byte_data(data->client, chip->ev_cfg); + if (val < 0) + return val; + + if (state) { + if (mma8452_freefall_mode_enabled(data)) { + val &= ~BIT(idx_x + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_y + chip->ev_cfg_chan_shift); + val &= ~BIT(idx_z + chip->ev_cfg_chan_shift); + val |= MMA8452_FF_MT_CFG_OAE; + } + val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); + } else { + if (mma8452_freefall_mode_enabled(data)) + return 0; - if (state) - val |= BIT(chan->scan_index + chip->ev_cfg_chan_shift); - else - val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); + val &= ~BIT(chan->scan_index + chip->ev_cfg_chan_shift); + } - val |= chip->ev_cfg_ele; - val |= MMA8452_FF_MT_CFG_OAE; + val |= chip->ev_cfg_ele; - return mma8452_change_config(data, chip->ev_cfg, val); + return mma8452_change_config(data, chip->ev_cfg, val); + default: + return -EINVAL; + } } static void mma8452_transient_interrupt(struct iio_dev *indio_dev) @@ -652,6 +723,16 @@ static void mma8452_transient_interrupt(struct iio_dev *indio_dev) if (src < 0) return; + if (mma8452_freefall_mode_enabled(data)) { + iio_push_event(indio_dev, + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, + IIO_MOD_X_AND_Y_AND_Z, + IIO_EV_TYPE_MAG, + IIO_EV_DIR_FALLING), + ts); + return; + } + if (src & data->chip_info->ev_src_xe) iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, @@ -745,6 +826,27 @@ static int mma8452_reg_access_dbg(struct iio_dev *indio_dev, return 0; } +static const struct iio_event_spec mma8452_freefall_event[] = { + { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) | + BIT(IIO_EV_INFO_HIGH_PASS_FILTER_3DB) + }, +}; + +static const struct iio_event_spec mma8652_freefall_event[] = { + { + .type = IIO_EV_TYPE_MAG, + .dir = IIO_EV_DIR_FALLING, + .mask_separate = BIT(IIO_EV_INFO_ENABLE), + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | + BIT(IIO_EV_INFO_PERIOD) + }, +}; + static const struct iio_event_spec mma8452_transient_event[] = { { .type = IIO_EV_TYPE_MAG, @@ -781,6 +883,24 @@ static struct attribute_group mma8452_event_attribute_group = { .attrs = mma8452_event_attributes, }; +#define MMA8452_FREEFALL_CHANNEL(modifier) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = modifier, \ + .scan_index = -1, \ + .event_spec = mma8452_freefall_event, \ + .num_event_specs = ARRAY_SIZE(mma8452_freefall_event), \ +} + +#define MMA8652_FREEFALL_CHANNEL(modifier) { \ + .type = IIO_ACCEL, \ + .modified = 1, \ + .channel2 = modifier, \ + .scan_index = -1, \ + .event_spec = mma8652_freefall_event, \ + .num_event_specs = ARRAY_SIZE(mma8652_freefall_event), \ +} + #define MMA8452_CHANNEL(axis, idx, bits) { \ .type = IIO_ACCEL, \ .modified = 1, \ @@ -827,6 +947,7 @@ static const struct iio_chan_spec mma8452_channels[] = { MMA8452_CHANNEL(Y, idx_y, 12), MMA8452_CHANNEL(Z, idx_z, 12), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; static const struct iio_chan_spec mma8453_channels[] = { @@ -834,6 +955,7 @@ static const struct iio_chan_spec mma8453_channels[] = { MMA8452_CHANNEL(Y, idx_y, 10), MMA8452_CHANNEL(Z, idx_z, 10), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; static const struct iio_chan_spec mma8652_channels[] = { @@ -841,6 +963,7 @@ static const struct iio_chan_spec mma8652_channels[] = { MMA8652_CHANNEL(Y, idx_y, 12), MMA8652_CHANNEL(Z, idx_z, 12), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; static const struct iio_chan_spec mma8653_channels[] = { @@ -848,6 +971,7 @@ static const struct iio_chan_spec mma8653_channels[] = { MMA8652_CHANNEL(Y, idx_y, 10), MMA8652_CHANNEL(Z, idx_z, 10), IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8652_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), }; enum { @@ -1190,6 +1314,10 @@ static int mma8452_probe(struct i2c_client *client, if (ret < 0) goto buffer_cleanup; + ret = mma8452_set_freefall_mode(data, false); + if (ret) + return ret; + return 0; buffer_cleanup: -- cgit From 36775d57016ec311780c3beed3173ae6fb59f0e2 Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sat, 16 Jan 2016 15:35:21 +0100 Subject: iio: mma8452: whitespace cleanup Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- drivers/iio/accel/mma8452.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 77b71c2dfd72..843169effb34 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -85,8 +85,8 @@ #define MMA8452_INT_FF_MT BIT(2) #define MMA8452_INT_TRANS BIT(5) -#define MMA8452_DEVICE_ID 0x2a -#define MMA8453_DEVICE_ID 0x3a +#define MMA8452_DEVICE_ID 0x2a +#define MMA8453_DEVICE_ID 0x3a #define MMA8652_DEVICE_ID 0x4a #define MMA8653_DEVICE_ID 0x5a -- cgit From 244a93f651937a7f587f8ddf3d8c09516cacf5bd Mon Sep 17 00:00:00 2001 From: Martin Kepplinger Date: Sat, 16 Jan 2016 15:35:22 +0100 Subject: iio: mma8452: add support for MMA8451Q This adds support for this series' 14 bit accelerometer chip, MMA8451Q. It's datasheet is available at the vendor's website: https://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf Signed-off-by: Martin Kepplinger Signed-off-by: Christoph Muellner Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/accel/mma8452.txt | 4 ++- drivers/iio/accel/Kconfig | 2 +- drivers/iio/accel/mma8452.c | 42 ++++++++++++++++++---- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/accel/mma8452.txt b/Documentation/devicetree/bindings/iio/accel/mma8452.txt index 3c10e8581144..165937e1ac1c 100644 --- a/Documentation/devicetree/bindings/iio/accel/mma8452.txt +++ b/Documentation/devicetree/bindings/iio/accel/mma8452.txt @@ -1,8 +1,10 @@ -Freescale MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC triaxial accelerometer +Freescale MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC or MMA8653FC +triaxial accelerometer Required properties: - compatible: should contain one of + * "fsl,mma8451" * "fsl,mma8452" * "fsl,mma8453" * "fsl,mma8652" diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index edc29b173f6c..d9feaa3c1fb8 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig @@ -143,7 +143,7 @@ config MMA8452 select IIO_TRIGGERED_BUFFER help Say yes here to build support for the following Freescale 3-axis - accelerometers: MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. + accelerometers: MMA8451Q, MMA8452Q, MMA8453Q, MMA8652FC, MMA8653FC. 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 843169effb34..7f4994f32a90 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1,6 +1,7 @@ /* * mma8452.c - Support for following Freescale 3-axis accelerometers: * + * MMA8451Q (14 bit) * MMA8452Q (12 bit) * MMA8453Q (10 bit) * MMA8652FC (12 bit) @@ -85,6 +86,7 @@ #define MMA8452_INT_FF_MT BIT(2) #define MMA8452_INT_TRANS BIT(5) +#define MMA8451_DEVICE_ID 0x1a #define MMA8452_DEVICE_ID 0x2a #define MMA8453_DEVICE_ID 0x3a #define MMA8652_DEVICE_ID 0x4a @@ -942,6 +944,14 @@ static struct attribute_group mma8452_event_attribute_group = { .num_event_specs = ARRAY_SIZE(mma8452_motion_event), \ } +static const struct iio_chan_spec mma8451_channels[] = { + MMA8452_CHANNEL(X, idx_x, 14), + MMA8452_CHANNEL(Y, idx_y, 14), + MMA8452_CHANNEL(Z, idx_z, 14), + IIO_CHAN_SOFT_TIMESTAMP(idx_ts), + MMA8452_FREEFALL_CHANNEL(IIO_MOD_X_AND_Y_AND_Z), +}; + static const struct iio_chan_spec mma8452_channels[] = { MMA8452_CHANNEL(X, idx_x, 12), MMA8452_CHANNEL(Y, idx_y, 12), @@ -975,6 +985,7 @@ static const struct iio_chan_spec mma8653_channels[] = { }; enum { + mma8451, mma8452, mma8453, mma8652, @@ -982,17 +993,34 @@ enum { }; static const struct mma_chip_info mma_chip_info_table[] = { - [mma8452] = { - .chip_id = MMA8452_DEVICE_ID, - .channels = mma8452_channels, - .num_channels = ARRAY_SIZE(mma8452_channels), + [mma8451] = { + .chip_id = MMA8451_DEVICE_ID, + .channels = mma8451_channels, + .num_channels = ARRAY_SIZE(mma8451_channels), /* * Hardware has fullscale of -2G, -4G, -8G corresponding to - * raw value -2048 for 12 bit or -512 for 10 bit. + * raw value -8192 for 14 bit, -2048 for 12 bit or -512 for 10 + * 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, + .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, + }, + [mma8452] = { + .chip_id = MMA8452_DEVICE_ID, + .channels = mma8452_channels, + .num_channels = ARRAY_SIZE(mma8452_channels), .mma_scales = { {0, 9577}, {0, 19154}, {0, 38307} }, .ev_cfg = MMA8452_TRANSIENT_CFG, .ev_cfg_ele = MMA8452_TRANSIENT_CFG_ELE, @@ -1173,6 +1201,7 @@ static int mma8452_reset(struct i2c_client *client) } static const struct of_device_id mma8452_dt_ids[] = { + { .compatible = "fsl,mma8451", .data = &mma_chip_info_table[mma8451] }, { .compatible = "fsl,mma8452", .data = &mma_chip_info_table[mma8452] }, { .compatible = "fsl,mma8453", .data = &mma_chip_info_table[mma8453] }, { .compatible = "fsl,mma8652", .data = &mma_chip_info_table[mma8652] }, @@ -1209,6 +1238,7 @@ static int mma8452_probe(struct i2c_client *client, return ret; switch (ret) { + case MMA8451_DEVICE_ID: case MMA8452_DEVICE_ID: case MMA8453_DEVICE_ID: case MMA8652_DEVICE_ID: -- cgit From 7ca6574a7afb669b0b4b30dd63adeb310e97e250 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 22 Jan 2016 17:49:22 +0000 Subject: iio: adc: axp288: remove redundant duplicate const on axp288_adc_channels duplicate const can be removed, it is redundant. Found by static analysis using smatch. Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/iio/adc/axp288_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c index 0c904edd6c00..7fd24949c0c1 100644 --- a/drivers/iio/adc/axp288_adc.c +++ b/drivers/iio/adc/axp288_adc.c @@ -46,7 +46,7 @@ struct axp288_adc_info { struct regmap *regmap; }; -static const struct iio_chan_spec const axp288_adc_channels[] = { +static const struct iio_chan_spec axp288_adc_channels[] = { { .indexed = 1, .type = IIO_TEMP, -- cgit From 131497acd88a4456d99247cee457baefd2817835 Mon Sep 17 00:00:00 2001 From: Ricardo Ribalda Delgado Date: Sat, 16 Jan 2016 14:24:07 +0100 Subject: iio: add ad5761 DAC driver ad5761 is a 1-channel DAC with configurable output range. The driver uses the regulator interface for its voltage ref. It shares its register layout with ad5761r, ad5721 and ad5721r. Differences: ad5761* are 16 bit, ad5721* are 12 bits. ad57*1r have an internal reference. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Jonathan Cameron --- CREDITS | 1 + drivers/iio/dac/Kconfig | 10 + drivers/iio/dac/Makefile | 1 + drivers/iio/dac/ad5761.c | 430 +++++++++++++++++++++++++++++++++++ include/linux/platform_data/ad5761.h | 44 ++++ 5 files changed, 486 insertions(+) create mode 100644 drivers/iio/dac/ad5761.c create mode 100644 include/linux/platform_data/ad5761.h diff --git a/CREDITS b/CREDITS index 8207cc62ee9d..44ea433d70a1 100644 --- a/CREDITS +++ b/CREDITS @@ -3035,6 +3035,7 @@ D: PLX USB338x driver D: PCA9634 driver D: Option GTM671WFS D: Fintek F81216A +D: AD5761 iio driver D: Various kernel hacks S: Qtechnology A/S S: Valby Langgade 142 diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 5263c5125fbb..5dc71505da61 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -111,6 +111,16 @@ config AD5755 To compile this driver as a module, choose M here: the module will be called ad5755. +config AD5761 + tristate "Analog Devices AD5761/61R/21/21R DAC driver" + depends on SPI_MASTER + help + Say yes here to build support for Analog Devices AD5761, AD5761R, AD5721, + AD5721R Digital to Analog Converter. + + To compile this driver as a module, choose M here: the + module will be called ad5761. + config AD5764 tristate "Analog Devices AD5764/64R/44/44R DAC driver" depends on SPI_MASTER diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 63ae05633e0c..cb525b53fc7b 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AD5504) += ad5504.o obj-$(CONFIG_AD5446) += ad5446.o obj-$(CONFIG_AD5449) += ad5449.o obj-$(CONFIG_AD5755) += ad5755.o +obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5791) += ad5791.o obj-$(CONFIG_AD5686) += ad5686.o diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c new file mode 100644 index 000000000000..d6510d6928b3 --- /dev/null +++ b/drivers/iio/dac/ad5761.c @@ -0,0 +1,430 @@ +/* + * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter + * + * Copyright 2016 Qtechnology A/S + * 2016 Ricardo Ribalda + * + * Licensed under the GPL-2. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define AD5761_ADDR(addr) ((addr & 0xf) << 16) +#define AD5761_ADDR_NOOP 0x0 +#define AD5761_ADDR_DAC_WRITE 0x3 +#define AD5761_ADDR_CTRL_WRITE_REG 0x4 +#define AD5761_ADDR_SW_DATA_RESET 0x7 +#define AD5761_ADDR_DAC_READ 0xb +#define AD5761_ADDR_CTRL_READ_REG 0xc +#define AD5761_ADDR_SW_FULL_RESET 0xf + +#define AD5761_CTRL_USE_INTVREF BIT(5) +#define AD5761_CTRL_ETS BIT(6) + +/** + * struct ad5761_chip_info - chip specific information + * @int_vref: Value of the internal reference voltage in mV - 0 if external + * reference voltage is used + * @channel: channel specification +*/ + +struct ad5761_chip_info { + unsigned long int_vref; + const struct iio_chan_spec channel; +}; + +struct ad5761_range_params { + int m; + int c; +}; + +enum ad5761_supported_device_ids { + ID_AD5721, + ID_AD5721R, + ID_AD5761, + ID_AD5761R, +}; + +/** + * struct ad5761_state - driver instance specific data + * @spi: spi_device + * @vref_reg: reference voltage regulator + * @use_intref: true when the internal voltage reference is used + * @vref: actual voltage reference in mVolts + * @range: output range mode used + * @data: cache aligned spi buffer + */ +struct ad5761_state { + struct spi_device *spi; + struct regulator *vref_reg; + + bool use_intref; + int vref; + enum ad5761_voltage_range range; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + union { + __be32 d32; + u8 d8[4]; + } data[3] ____cacheline_aligned; +}; + +static const struct ad5761_range_params ad5761_range_params[] = { + [AD5761_VOLTAGE_RANGE_M10V_10V] = { + .m = 80, + .c = 40, + }, + [AD5761_VOLTAGE_RANGE_0V_10V] = { + .m = 40, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_M5V_5V] = { + .m = 40, + .c = 20, + }, + [AD5761_VOLTAGE_RANGE_0V_5V] = { + .m = 20, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_M2V5_7V5] = { + .m = 40, + .c = 10, + }, + [AD5761_VOLTAGE_RANGE_M3V_3V] = { + .m = 24, + .c = 12, + }, + [AD5761_VOLTAGE_RANGE_0V_16V] = { + .m = 64, + .c = 0, + }, + [AD5761_VOLTAGE_RANGE_0V_20V] = { + .m = 80, + .c = 0, + }, +}; + +static int _ad5761_spi_write(struct ad5761_state *st, u8 addr, u16 val) +{ + st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr) | val); + + return spi_write(st->spi, &st->data[0].d8[1], 3); +} + +static int ad5761_spi_write(struct iio_dev *indio_dev, u8 addr, u16 val) +{ + struct ad5761_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = _ad5761_spi_write(st, addr, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int _ad5761_spi_read(struct ad5761_state *st, u8 addr, u16 *val) +{ + int ret; + struct spi_transfer xfers[] = { + { + .tx_buf = &st->data[0].d8[1], + .bits_per_word = 8, + .len = 3, + .cs_change = true, + }, { + .tx_buf = &st->data[1].d8[1], + .rx_buf = &st->data[2].d8[1], + .bits_per_word = 8, + .len = 3, + }, + }; + + st->data[0].d32 = cpu_to_be32(AD5761_ADDR(addr)); + st->data[1].d32 = cpu_to_be32(AD5761_ADDR(AD5761_ADDR_NOOP)); + + ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + + *val = be32_to_cpu(st->data[2].d32); + + return ret; +} + +static int ad5761_spi_read(struct iio_dev *indio_dev, u8 addr, u16 *val) +{ + struct ad5761_state *st = iio_priv(indio_dev); + int ret; + + mutex_lock(&indio_dev->mlock); + ret = _ad5761_spi_read(st, addr, val); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ad5761_spi_set_range(struct ad5761_state *st, + enum ad5761_voltage_range range) +{ + u16 aux; + int ret; + + aux = (range & 0x7) | AD5761_CTRL_ETS; + + if (st->use_intref) + aux |= AD5761_CTRL_USE_INTVREF; + + ret = _ad5761_spi_write(st, AD5761_ADDR_SW_FULL_RESET, 0); + if (ret) + return ret; + + ret = _ad5761_spi_write(st, AD5761_ADDR_CTRL_WRITE_REG, aux); + if (ret) + return ret; + + st->range = range; + + return 0; +} + +static int ad5761_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, + int *val2, + long mask) +{ + struct ad5761_state *st; + int ret; + u16 aux; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = ad5761_spi_read(indio_dev, AD5761_ADDR_DAC_READ, &aux); + if (ret) + return ret; + *val = aux >> chan->scan_type.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + st = iio_priv(indio_dev); + *val = st->vref * ad5761_range_params[st->range].m; + *val /= 10; + *val2 = chan->scan_type.realbits; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_CHAN_INFO_OFFSET: + st = iio_priv(indio_dev); + *val = -(1 << chan->scan_type.realbits); + *val *= ad5761_range_params[st->range].c; + *val /= ad5761_range_params[st->range].m; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad5761_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, + int val2, + long mask) +{ + u16 aux; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + if (val2 || (val << chan->scan_type.shift) > 0xffff || val < 0) + return -EINVAL; + + aux = val << chan->scan_type.shift; + + return ad5761_spi_write(indio_dev, AD5761_ADDR_DAC_WRITE, aux); +} + +static const struct iio_info ad5761_info = { + .read_raw = &ad5761_read_raw, + .write_raw = &ad5761_write_raw, + .driver_module = THIS_MODULE, +}; + +#define AD5761_CHAN(_bits) { \ + .type = IIO_VOLTAGE, \ + .output = 1, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OFFSET), \ + .scan_type = { \ + .sign = 'u', \ + .realbits = (_bits), \ + .storagebits = 16, \ + .shift = 16 - (_bits), \ + }, \ +} + +static const struct ad5761_chip_info ad5761_chip_infos[] = { + [ID_AD5721] = { + .int_vref = 0, + .channel = AD5761_CHAN(12), + }, + [ID_AD5721R] = { + .int_vref = 2500, + .channel = AD5761_CHAN(12), + }, + [ID_AD5761] = { + .int_vref = 0, + .channel = AD5761_CHAN(16), + }, + [ID_AD5761R] = { + .int_vref = 2500, + .channel = AD5761_CHAN(16), + }, +}; + +static int ad5761_get_vref(struct ad5761_state *st, + const struct ad5761_chip_info *chip_info) +{ + int ret; + + st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref"); + if (PTR_ERR(st->vref_reg) == -ENODEV) { + /* Use Internal regulator */ + if (!chip_info->int_vref) { + dev_err(&st->spi->dev, + "Voltage reference not found\n"); + return -EIO; + } + + st->use_intref = true; + st->vref = chip_info->int_vref; + return 0; + } + + if (IS_ERR(st->vref_reg)) { + dev_err(&st->spi->dev, + "Error getting voltage reference regulator\n"); + return PTR_ERR(st->vref_reg); + } + + ret = regulator_enable(st->vref_reg); + if (ret) { + dev_err(&st->spi->dev, + "Failed to enable voltage reference\n"); + return ret; + } + + ret = regulator_get_voltage(st->vref_reg); + if (ret < 0) { + dev_err(&st->spi->dev, + "Failed to get voltage reference value\n"); + goto disable_regulator_vref; + } + + if (ret < 2000000 || ret > 3000000) { + dev_warn(&st->spi->dev, + "Invalid external voltage ref. value %d uV\n", ret); + ret = -EIO; + goto disable_regulator_vref; + } + + st->vref = ret / 1000; + st->use_intref = false; + + return 0; + +disable_regulator_vref: + regulator_disable(st->vref_reg); + st->vref_reg = NULL; + return ret; +} + +static int ad5761_probe(struct spi_device *spi) +{ + struct iio_dev *iio_dev; + struct ad5761_state *st; + int ret; + const struct ad5761_chip_info *chip_info = + &ad5761_chip_infos[spi_get_device_id(spi)->driver_data]; + enum ad5761_voltage_range voltage_range = AD5761_VOLTAGE_RANGE_0V_5V; + struct ad5761_platform_data *pdata = dev_get_platdata(&spi->dev); + + iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!iio_dev) + return -ENOMEM; + + st = iio_priv(iio_dev); + + st->spi = spi; + spi_set_drvdata(spi, iio_dev); + + ret = ad5761_get_vref(st, chip_info); + if (ret) + return ret; + + if (pdata) + voltage_range = pdata->voltage_range; + + ret = ad5761_spi_set_range(st, voltage_range); + if (ret) + goto disable_regulator_err; + + iio_dev->dev.parent = &spi->dev; + iio_dev->info = &ad5761_info; + iio_dev->modes = INDIO_DIRECT_MODE; + iio_dev->channels = &chip_info->channel; + iio_dev->num_channels = 1; + iio_dev->name = spi_get_device_id(st->spi)->name; + ret = iio_device_register(iio_dev); + if (ret) + goto disable_regulator_err; + + return 0; + +disable_regulator_err: + if (!IS_ERR_OR_NULL(st->vref_reg)) + regulator_disable(st->vref_reg); + + return ret; +} + +static int ad5761_remove(struct spi_device *spi) +{ + struct iio_dev *iio_dev = spi_get_drvdata(spi); + struct ad5761_state *st = iio_priv(iio_dev); + + iio_device_unregister(iio_dev); + + if (!IS_ERR_OR_NULL(st->vref_reg)) + regulator_disable(st->vref_reg); + + return 0; +} + +static const struct spi_device_id ad5761_id[] = { + {"ad5721", ID_AD5721}, + {"ad5721r", ID_AD5721R}, + {"ad5761", ID_AD5761}, + {"ad5761r", ID_AD5761R}, + {} +}; +MODULE_DEVICE_TABLE(spi, ad5761_id); + +static struct spi_driver ad5761_driver = { + .driver = { + .name = "ad5761", + }, + .probe = ad5761_probe, + .remove = ad5761_remove, + .id_table = ad5761_id, +}; +module_spi_driver(ad5761_driver); + +MODULE_AUTHOR("Ricardo Ribalda "); +MODULE_DESCRIPTION("Analog Devices AD5721, AD5721R, AD5761, AD5761R driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/ad5761.h b/include/linux/platform_data/ad5761.h new file mode 100644 index 000000000000..7bd8ed7d978e --- /dev/null +++ b/include/linux/platform_data/ad5761.h @@ -0,0 +1,44 @@ +/* + * AD5721, AD5721R, AD5761, AD5761R, Voltage Output Digital to Analog Converter + * + * Copyright 2016 Qtechnology A/S + * 2016 Ricardo Ribalda + * + * Licensed under the GPL-2. + */ +#ifndef __LINUX_PLATFORM_DATA_AD5761_H__ +#define __LINUX_PLATFORM_DATA_AD5761_H__ + +/** + * enum ad5761_voltage_range - Voltage range the AD5761 is configured for. + * @AD5761_VOLTAGE_RANGE_M10V_10V: -10V to 10V + * @AD5761_VOLTAGE_RANGE_0V_10V: 0V to 10V + * @AD5761_VOLTAGE_RANGE_M5V_5V: -5V to 5V + * @AD5761_VOLTAGE_RANGE_0V_5V: 0V to 5V + * @AD5761_VOLTAGE_RANGE_M2V5_7V5: -2.5V to 7.5V + * @AD5761_VOLTAGE_RANGE_M3V_3V: -3V to 3V + * @AD5761_VOLTAGE_RANGE_0V_16V: 0V to 16V + * @AD5761_VOLTAGE_RANGE_0V_20V: 0V to 20V + */ + +enum ad5761_voltage_range { + AD5761_VOLTAGE_RANGE_M10V_10V, + AD5761_VOLTAGE_RANGE_0V_10V, + AD5761_VOLTAGE_RANGE_M5V_5V, + AD5761_VOLTAGE_RANGE_0V_5V, + AD5761_VOLTAGE_RANGE_M2V5_7V5, + AD5761_VOLTAGE_RANGE_M3V_3V, + AD5761_VOLTAGE_RANGE_0V_16V, + AD5761_VOLTAGE_RANGE_0V_20V, +}; + +/** + * struct ad5761_platform_data - AD5761 DAC driver platform data + * @voltage_range: Voltage range the AD5761 is configured for + */ + +struct ad5761_platform_data { + enum ad5761_voltage_range voltage_range; +}; + +#endif -- cgit From b6acb0cfc21293a1bfc283e9217f58f7474ef728 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Sat, 23 Jan 2016 19:33:10 +0000 Subject: Staging: iio: adc: fix indent on break statement Fix indent warning when building with gcc 6: drivers/staging/iio/adc/ad7192.c:239:4: warning: statement is indented as if it were guarded by... [-Wmisleading-indentation] Signed-off-by: Colin Ian King Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7192.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index 92211039ffa9..92f2b72cce30 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -236,7 +236,7 @@ static int ad7192_setup(struct ad7192_state *st, st->mclk = pdata->ext_clk_hz; else st->mclk = AD7192_INT_FREQ_MHZ; - break; + break; default: ret = -EINVAL; goto out; -- cgit From 9c2863b53fcd54e40e30d25ac83eca2e31fda1e1 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Tue, 8 Dec 2015 02:32:01 +0200 Subject: usb: ohci: nxp: clean up included header files Remove mach/irq.h from the list of included headers, there is no compilation dependency on this include file, the change is needed to prevent a compilation failure, when mach/irq.h is removed. Additionally remove other unneeded includes. Signed-off-by: Vladimir Zapolskiy Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-nxp.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index cfa94275c52c..ebacf97fc406 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -32,13 +31,7 @@ #include "ohci.h" - #include -#include -#include - -#include -#include #define USB_CONFIG_BASE 0x31020000 #define PWRMAN_BASE 0x40004000 -- cgit From fcb42e232a2dd3904f09107bf02904b760a0dd9a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 27 Dec 2015 21:50:29 +0100 Subject: usb: renesas_usbhs: constify usbhs_pkt_handle structures The usbhs_pkt_handle structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/renesas_usbhs/fifo.c | 20 ++++++++++---------- drivers/usb/renesas_usbhs/fifo.h | 20 ++++++++++---------- drivers/usb/renesas_usbhs/pipe.h | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index c0f5c652d272..b4de70ee16d3 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -46,7 +46,7 @@ static int usbhsf_null_handle(struct usbhs_pkt *pkt, int *is_done) return -EINVAL; } -static struct usbhs_pkt_handle usbhsf_null_handler = { +static const struct usbhs_pkt_handle usbhsf_null_handler = { .prepare = usbhsf_null_handle, .try_run = usbhsf_null_handle, }; @@ -422,12 +422,12 @@ static int usbhs_dcp_dir_switch_done(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { +const struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler = { .prepare = usbhs_dcp_dir_switch_to_write, .try_run = usbhs_dcp_dir_switch_done, }; -struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { +const struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler = { .prepare = usbhs_dcp_dir_switch_to_read, .try_run = usbhs_dcp_dir_switch_done, }; @@ -449,7 +449,7 @@ static int usbhsf_dcp_data_stage_try_push(struct usbhs_pkt *pkt, int *is_done) return pkt->handler->prepare(pkt, is_done); } -struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { +const struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler = { .prepare = usbhsf_dcp_data_stage_try_push, }; @@ -488,7 +488,7 @@ static int usbhsf_dcp_data_stage_prepare_pop(struct usbhs_pkt *pkt, return pkt->handler->prepare(pkt, is_done); } -struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { +const struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler = { .prepare = usbhsf_dcp_data_stage_prepare_pop, }; @@ -600,7 +600,7 @@ static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done) return usbhsf_pio_try_push(pkt, is_done); } -struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { +const struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = { .prepare = usbhsf_pio_prepare_push, .try_run = usbhsf_pio_try_push, }; @@ -730,7 +730,7 @@ usbhs_fifo_read_busy: return ret; } -struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { +const struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler = { .prepare = usbhsf_prepare_pop, .try_run = usbhsf_pio_try_pop, }; @@ -747,7 +747,7 @@ static int usbhsf_ctrl_stage_end(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { +const struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler = { .prepare = usbhsf_ctrl_stage_end, .try_run = usbhsf_ctrl_stage_end, }; @@ -934,7 +934,7 @@ static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done) return 0; } -struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { +const struct usbhs_pkt_handle usbhs_fifo_dma_push_handler = { .prepare = usbhsf_dma_prepare_push, .dma_done = usbhsf_dma_push_done, }; @@ -1182,7 +1182,7 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done) return usbhsf_dma_pop_done_with_rx_irq(pkt, is_done); } -struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { +const struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler = { .prepare = usbhsf_dma_prepare_pop, .try_run = usbhsf_dma_try_pop, .dma_done = usbhsf_dma_pop_done diff --git a/drivers/usb/renesas_usbhs/fifo.h b/drivers/usb/renesas_usbhs/fifo.h index c7d9b86d51bf..8b98507d7abc 100644 --- a/drivers/usb/renesas_usbhs/fifo.h +++ b/drivers/usb/renesas_usbhs/fifo.h @@ -54,7 +54,7 @@ struct usbhs_pkt_handle; struct usbhs_pkt { struct list_head node; struct usbhs_pipe *pipe; - struct usbhs_pkt_handle *handler; + const struct usbhs_pkt_handle *handler; void (*done)(struct usbhs_priv *priv, struct usbhs_pkt *pkt); struct work_struct work; @@ -86,18 +86,18 @@ void usbhs_fifo_clear_dcp(struct usbhs_pipe *pipe); /* * packet info */ -extern struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; -extern struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; -extern struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_pio_push_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_pio_pop_handler; +extern const struct usbhs_pkt_handle usbhs_ctrl_stage_end_handler; -extern struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; -extern struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_dma_push_handler; +extern const struct usbhs_pkt_handle usbhs_fifo_dma_pop_handler; -extern struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; -extern struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_status_stage_in_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_status_stage_out_handler; -extern struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; -extern struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_data_stage_in_handler; +extern const struct usbhs_pkt_handle usbhs_dcp_data_stage_out_handler; void usbhs_pkt_init(struct usbhs_pkt *pkt); void usbhs_pkt_push(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt, diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 3212ab51e844..7835747f9803 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h @@ -38,7 +38,7 @@ struct usbhs_pipe { #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2) #define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3) - struct usbhs_pkt_handle *handler; + const struct usbhs_pkt_handle *handler; void *mod_private; }; -- cgit From 64f10edf0751727154e843e8bcf59fb659e579a2 Mon Sep 17 00:00:00 2001 From: Chase Metzger Date: Tue, 22 Dec 2015 20:19:45 -0800 Subject: usb: core: devio.c: Removed unnecessary space Removed an unnecessary space between a function name and arguments. Signed-off-by: Chase Metzger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 59e7a3369084..6aac2425dd9f 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1903,7 +1903,7 @@ static int proc_releaseinterface(struct usb_dev_state *ps, void __user *arg) ret = releaseintf(ps, ifnum); if (ret < 0) return ret; - destroy_async_on_interface (ps, ifnum); + destroy_async_on_interface(ps, ifnum); return 0; } -- cgit From 73a02d32458ecff5b6241e7e7bd6445f70400bad Mon Sep 17 00:00:00 2001 From: Rahul Pathak Date: Fri, 11 Dec 2015 05:40:51 +0000 Subject: usb: Use memdup_user to reuse the code Fixing coccicheck warning which recommends to use memdup_user instead to reimplement its code, using memdup_user simplifies the code ./drivers/usb/core/devio.c:1398:11-18: WARNING opportunity for memdup_user Signed-off-by: Rahul Pathak Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6aac2425dd9f..054eb534c495 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1378,11 +1378,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb number_of_packets = uurb->number_of_packets; isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * number_of_packets; - isopkt = kmalloc(isofrmlen, GFP_KERNEL); - if (!isopkt) - return -ENOMEM; - if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) { - ret = -EFAULT; + isopkt = memdup_user(iso_frame_desc, isofrmlen); + if (IS_ERR(isopkt)) { + ret = PTR_ERR(isopkt); + isopkt = NULL; goto error; } for (totlen = u = 0; u < number_of_packets; u++) { -- cgit From 8a1b2725a60d3267135c15e80984b4406054f650 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:25 +0200 Subject: usb: define USB_SPEED_SUPER_PLUS speed for SuperSpeedPlus USB3.1 devices Add a new USB_SPEED_SUPER_PLUS device speed, and make sure usb core can handle the new speed. In most cases the behaviour is the same as with USB_SPEED_SUPER SuperSpeed devices. In a few places we add a "Plus" string to inform the user of the new speed. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/common/common.c | 1 + drivers/usb/core/config.c | 3 ++- drivers/usb/core/devices.c | 10 ++++++---- drivers/usb/core/hcd-pci.c | 2 +- drivers/usb/core/hcd.c | 6 +++--- drivers/usb/core/hub.c | 26 +++++++++++++++----------- drivers/usb/core/urb.c | 3 ++- drivers/usb/core/usb.h | 2 +- include/uapi/linux/usb/ch9.h | 1 + 9 files changed, 32 insertions(+), 22 deletions(-) diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c index e6ec125e4485..49fbfe8b0f24 100644 --- a/drivers/usb/common/common.c +++ b/drivers/usb/common/common.c @@ -51,6 +51,7 @@ static const char *const speed_names[] = { [USB_SPEED_HIGH] = "high-speed", [USB_SPEED_WIRELESS] = "wireless", [USB_SPEED_SUPER] = "super-speed", + [USB_SPEED_SUPER_PLUS] = "super-speed-plus", }; const char *usb_speed_string(enum usb_device_speed speed) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 5050760f5e17..bbcf4009f99e 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -191,6 +191,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, if (usb_endpoint_xfer_int(d)) { i = 1; switch (to_usb_device(ddev)->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: case USB_SPEED_HIGH: /* Many device manufacturers are using full-speed @@ -274,7 +275,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, } /* Parse a possible SuperSpeed endpoint companion descriptor */ - if (to_usb_device(ddev)->speed == USB_SPEED_SUPER) + if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER) usb_parse_ss_endpoint_companion(ddev, cfgno, inum, asnum, endpoint, buffer, size); diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index cffa0a0d7de2..b35a6a52210f 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, break; case USB_ENDPOINT_XFER_INT: type = "Int."; - if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER) + if (speed == USB_SPEED_HIGH || speed >= USB_SPEED_SUPER) interval = 1 << (desc->bInterval - 1); else interval = desc->bInterval; @@ -230,7 +230,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, return start; } interval *= (speed == USB_SPEED_HIGH || - speed == USB_SPEED_SUPER) ? 125 : 1000; + speed >= USB_SPEED_SUPER) ? 125 : 1000; if (interval % 1000) unit = 'u'; else { @@ -322,7 +322,7 @@ static char *usb_dump_config_descriptor(char *start, char *end, if (start > end) return start; - if (speed == USB_SPEED_SUPER) + if (speed >= USB_SPEED_SUPER) mul = 8; else mul = 2; @@ -534,6 +534,8 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, speed = "480"; break; case USB_SPEED_SUPER: speed = "5000"; break; + case USB_SPEED_SUPER_PLUS: + speed = "10000"; break; default: speed = "??"; } @@ -553,7 +555,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, /* super/high speed reserves 80%, full/low reserves 90% */ if (usbdev->speed == USB_SPEED_HIGH || - usbdev->speed == USB_SPEED_SUPER) + usbdev->speed >= USB_SPEED_SUPER) max = 800; else max = FRAME_TIME_MAX_USECS_ALLOC; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 9eb1cff28bd4..22a9ac25b850 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -197,7 +197,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) * The xHCI driver has its own irq management * make sure irq setup is not touched for xhci in generic hcd code */ - if ((driver->flags & HCD_MASK) != HCD_USB3) { + if ((driver->flags & HCD_MASK) < HCD_USB3) { if (!dev->irq) { dev_err(&dev->dev, "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index df0e3b92533a..0e38ce60d7d5 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1078,7 +1078,7 @@ static int register_root_hub(struct usb_hcd *hcd) retval = usb_get_bos_descriptor(usb_dev); if (!retval) { usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); - } else if (usb_dev->speed == USB_SPEED_SUPER) { + } else if (usb_dev->speed >= USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); @@ -2112,7 +2112,7 @@ int usb_alloc_streams(struct usb_interface *interface, hcd = bus_to_hcd(dev->bus); if (!hcd->driver->alloc_streams || !hcd->driver->free_streams) return -EINVAL; - if (dev->speed != USB_SPEED_SUPER) + if (dev->speed < USB_SPEED_SUPER) return -EINVAL; if (dev->state < USB_STATE_CONFIGURED) return -ENODEV; @@ -2160,7 +2160,7 @@ int usb_free_streams(struct usb_interface *interface, dev = interface_to_usbdev(interface); hcd = bus_to_hcd(dev->bus); - if (dev->speed != USB_SPEED_SUPER) + if (dev->speed < USB_SPEED_SUPER) return -EINVAL; /* Double-free is not allowed */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 51b436918f78..6bdff0ad3930 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -298,7 +298,7 @@ static void usb_set_lpm_parameters(struct usb_device *udev) unsigned int hub_u1_del; unsigned int hub_u2_del; - if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER) + if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER) return; hub = usb_hub_to_struct_hub(udev->parent); @@ -2645,7 +2645,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) */ static bool use_new_scheme(struct usb_device *udev, int retry) { - if (udev->speed == USB_SPEED_SUPER) + if (udev->speed >= USB_SPEED_SUPER) return false; return USE_NEW_SCHEME(retry); @@ -3989,7 +3989,7 @@ int usb_disable_lpm(struct usb_device *udev) struct usb_hcd *hcd; if (!udev || !udev->parent || - udev->speed != USB_SPEED_SUPER || + udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || udev->state < USB_STATE_DEFAULT) return 0; @@ -4048,7 +4048,7 @@ void usb_enable_lpm(struct usb_device *udev) struct usb_port *port_dev; if (!udev || !udev->parent || - udev->speed != USB_SPEED_SUPER || + udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || udev->state < USB_STATE_DEFAULT) return; @@ -4323,7 +4323,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, retval = -ENODEV; - if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) { + /* Don't allow speed changes at reset, except usb 3.0 to faster */ + if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed && + !(oldspeed == USB_SPEED_SUPER && udev->speed > oldspeed)) { dev_dbg(&udev->dev, "device reset changed speed!\n"); goto fail; } @@ -4335,6 +4337,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. */ switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: case USB_SPEED_WIRELESS: /* fixed at 512 */ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); @@ -4361,7 +4364,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, else speed = usb_speed_string(udev->speed); - if (udev->speed != USB_SPEED_SUPER) + if (udev->speed < USB_SPEED_SUPER) dev_info(&udev->dev, "%s %s USB device number %d using %s\n", (udev->config) ? "reset" : "new", speed, @@ -4485,11 +4488,12 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, devnum, retval); goto fail; } - if (udev->speed == USB_SPEED_SUPER) { + if (udev->speed >= USB_SPEED_SUPER) { devnum = udev->devnum; dev_info(&udev->dev, - "%s SuperSpeed USB device number %d using %s\n", + "%s SuperSpeed%s USB device number %d using %s\n", (udev->config) ? "reset" : "new", + (udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "", devnum, udev->bus->controller->driver->name); } @@ -4528,7 +4532,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, * got from those devices show they aren't superspeed devices. Warm * reset the port attached by the devices can fix them. */ - if ((udev->speed == USB_SPEED_SUPER) && + if ((udev->speed >= USB_SPEED_SUPER) && (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { dev_err(&udev->dev, "got a wrong device descriptor, " "warm reset device\n"); @@ -4539,7 +4543,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, } if (udev->descriptor.bMaxPacketSize0 == 0xff || - udev->speed == USB_SPEED_SUPER) + udev->speed >= USB_SPEED_SUPER) i = 512; else i = udev->descriptor.bMaxPacketSize0; @@ -4749,7 +4753,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, udev->level = hdev->level + 1; udev->wusb = hub_is_wusb(hub); - /* Only USB 3.0 devices are connected to SuperSpeed hubs. */ + /* Devices connected to SuperSpeed hubs are USB 3.0 or later */ if (hub_is_superspeed(hub->hdev)) udev->speed = USB_SPEED_SUPER; else diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 3d274778caaf..c601e25b609f 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -401,7 +401,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) /* SuperSpeed isoc endpoints have up to 16 bursts of up to * 3 packets each */ - if (dev->speed == USB_SPEED_SUPER) { + if (dev->speed >= USB_SPEED_SUPER) { int burst = 1 + ep->ss_ep_comp.bMaxBurst; int mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes); max *= burst; @@ -499,6 +499,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) } /* too big? */ switch (dev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: /* units are 125us */ /* Handle up to 2^(16-1) microframes */ if (urb->interval > (1 << 15)) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 05b5e17abf92..53318126ed91 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -45,7 +45,7 @@ static inline unsigned usb_get_max_power(struct usb_device *udev, struct usb_host_config *c) { /* SuperSpeed power is in 8 mA units; others are in 2 mA units */ - unsigned mul = (udev->speed == USB_SPEED_SUPER ? 8 : 2); + unsigned mul = (udev->speed >= USB_SPEED_SUPER ? 8 : 2); return c->desc.bMaxPower * mul; } diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 4338eb7b09b3..779a62aafafe 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -954,6 +954,7 @@ enum usb_device_speed { USB_SPEED_HIGH, /* usb 2.0 */ USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ USB_SPEED_SUPER, /* usb 3.0 */ + USB_SPEED_SUPER_PLUS, /* usb 3.1 */ }; -- cgit From 5f9c3a668b3f75768aec686901d7a4c8782983df Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:26 +0200 Subject: usb: set USB 3.1 roothub device speed to USB_SPEED_SUPER_PLUS A hcd roothub that supports HCD_USB31 is running at SuperSpeedPlus speed Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0e38ce60d7d5..ff3073d522a8 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2778,9 +2778,11 @@ int usb_add_hcd(struct usb_hcd *hcd, rhdev->speed = USB_SPEED_WIRELESS; break; case HCD_USB3: - case HCD_USB31: rhdev->speed = USB_SPEED_SUPER; break; + case HCD_USB31: + rhdev->speed = USB_SPEED_SUPER_PLUS; + break; default: retval = -EINVAL; goto err_set_rh_speed; -- cgit From b2316645ca5ea93eb8f637f57199fbbe88bee07d Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:27 +0200 Subject: usb: show speed "10000" in sysfs for USB 3.1 SuperSpeedPlus devices The same way as SuperSpeed devices show "5000" as device speed we wan't to show "10000" as the default speed for SuperSpeedPlus devices in sysfs. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 65b6e6b84043..f195320d35c0 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -141,6 +141,9 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr, case USB_SPEED_SUPER: speed = "5000"; break; + case USB_SPEED_SUPER_PLUS: + speed = "10000"; + break; default: speed = "unknown"; } -- cgit From 9508e3b7a70c11370d70252147b75d3024754970 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:28 +0200 Subject: usb: add device descriptor for usb 3.1 root hub Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ff3073d522a8..bca13a0e0326 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -128,6 +128,27 @@ static inline int is_root_hub(struct usb_device *udev) #define KERNEL_REL bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff)) #define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff)) +/* usb 3.1 root hub device descriptor */ +static const u8 usb31_rh_dev_descriptor[18] = { + 0x12, /* __u8 bLength; */ + USB_DT_DEVICE, /* __u8 bDescriptorType; Device */ + 0x10, 0x03, /* __le16 bcdUSB; v3.1 */ + + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x03, /* __u8 bDeviceProtocol; USB 3 hub */ + 0x09, /* __u8 bMaxPacketSize0; 2^9 = 512 Bytes */ + + 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */ + 0x03, 0x00, /* __le16 idProduct; device 0x0003 */ + KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */ + + 0x03, /* __u8 iManufacturer; */ + 0x02, /* __u8 iProduct; */ + 0x01, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + /* usb 3.0 root hub device descriptor */ static const u8 usb3_rh_dev_descriptor[18] = { 0x12, /* __u8 bLength; */ @@ -557,6 +578,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) case USB_DT_DEVICE << 8: switch (hcd->speed) { case HCD_USB31: + bufp = usb31_rh_dev_descriptor; + break; case HCD_USB3: bufp = usb3_rh_dev_descriptor; break; -- cgit From 0cdd49a1d1a483d80170d9e592f832274e8bce1b Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 10 Dec 2015 09:59:29 +0200 Subject: usb: Support USB 3.1 extended port status request usb 3.1 extend the hub get-port-status request by adding different request types. the new request types return 4 additional bytes called extended port status, these bytes are returned after the regular portstatus and portchange values. The extended port status contains a speed ID for the currently used sublink speed. A table of supported Speed IDs with details about the link is provided by the hub in the device descriptor BOS SuperSpeedPlus device capability Sublink Speed Attributes. Support this new request. Ask for the extended port status after port reset if hub supports USB 3.1. If link is running at SuperSpeedPlus set the device speed to USB_SPEED_SUPER_PLUS Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 8 ++++- drivers/usb/core/hub.c | 70 +++++++++++++++++++++++++++++++++++++------ drivers/usb/core/hub.h | 7 +++++ include/uapi/linux/usb/ch11.h | 21 +++++++++++++ 4 files changed, 96 insertions(+), 10 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index bca13a0e0326..9af9506352f3 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -668,9 +668,15 @@ nongeneric: /* non-generic request */ switch (typeReq) { case GetHubStatus: - case GetPortStatus: len = 4; break; + case GetPortStatus: + if (wValue == HUB_PORT_STATUS) + len = 4; + else + /* other port status types return 8 bytes */ + len = 8; + break; case GetHubDescriptor: len = sizeof (struct usb_hub_descriptor); break; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6bdff0ad3930..3c9b22eb78ca 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -537,29 +537,34 @@ static int get_hub_status(struct usb_device *hdev, /* * USB 2.0 spec Section 11.24.2.7 + * USB 3.1 takes into use the wValue and wLength fields, spec Section 10.16.2.6 */ static int get_port_status(struct usb_device *hdev, int port1, - struct usb_port_status *data) + void *data, u16 value, u16 length) { int i, status = -ETIMEDOUT; for (i = 0; i < USB_STS_RETRIES && (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1, - data, sizeof(*data), USB_STS_TIMEOUT); + USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, value, + port1, data, length, USB_STS_TIMEOUT); } return status; } -static int hub_port_status(struct usb_hub *hub, int port1, - u16 *status, u16 *change) +static int hub_ext_port_status(struct usb_hub *hub, int port1, int type, + u16 *status, u16 *change, u32 *ext_status) { int ret; + int len = 4; + + if (type != HUB_PORT_STATUS) + len = 8; mutex_lock(&hub->status_mutex); - ret = get_port_status(hub->hdev, port1, &hub->status->port); - if (ret < 4) { + ret = get_port_status(hub->hdev, port1, &hub->status->port, type, len); + if (ret < len) { if (ret != -ENODEV) dev_err(hub->intfdev, "%s failed (err = %d)\n", __func__, ret); @@ -568,13 +573,22 @@ static int hub_port_status(struct usb_hub *hub, int port1, } else { *status = le16_to_cpu(hub->status->port.wPortStatus); *change = le16_to_cpu(hub->status->port.wPortChange); - + if (type != HUB_PORT_STATUS && ext_status) + *ext_status = le32_to_cpu( + hub->status->port.dwExtPortStatus); ret = 0; } mutex_unlock(&hub->status_mutex); return ret; } +static int hub_port_status(struct usb_hub *hub, int port1, + u16 *status, u16 *change) +{ + return hub_ext_port_status(hub, port1, HUB_PORT_STATUS, + status, change, NULL); +} + static void kick_hub_wq(struct usb_hub *hub) { struct usb_interface *intf; @@ -2612,6 +2626,32 @@ out_authorized: return result; } +/* + * Return 1 if port speed is SuperSpeedPlus, 0 otherwise + * check it from the link protocol field of the current speed ID attribute. + * current speed ID is got from ext port status request. Sublink speed attribute + * table is returned with the hub BOS SSP device capability descriptor + */ +static int port_speed_is_ssp(struct usb_device *hdev, int speed_id) +{ + int ssa_count; + u32 ss_attr; + int i; + struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap; + + if (!ssp_cap) + return 0; + + ssa_count = le32_to_cpu(ssp_cap->bmAttributes) & + USB_SSP_SUBLINK_SPEED_ATTRIBS; + + for (i = 0; i <= ssa_count; i++) { + ss_attr = le32_to_cpu(ssp_cap->bmSublinkSpeedAttr[i]); + if (speed_id == (ss_attr & USB_SSP_SUBLINK_SPEED_SSID)) + return !!(ss_attr & USB_SSP_SUBLINK_SPEED_LP); + } + return 0; +} /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */ static unsigned hub_is_wusb(struct usb_hub *hub) @@ -2676,6 +2716,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, int delay_time, ret; u16 portstatus; u16 portchange; + u32 ext_portstatus = 0; for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; @@ -2684,7 +2725,14 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, msleep(delay); /* read and decode port status */ - ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (hub_is_superspeedplus(hub->hdev)) + ret = hub_ext_port_status(hub, port1, + HUB_EXT_PORT_STATUS, + &portstatus, &portchange, + &ext_portstatus); + else + ret = hub_port_status(hub, port1, &portstatus, + &portchange); if (ret < 0) return ret; @@ -2727,6 +2775,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeedplus(hub->hdev) && + port_speed_is_ssp(hub->hdev, ext_portstatus & + USB_EXT_PORT_STAT_RX_SPEED_ID)) + udev->speed = USB_SPEED_SUPER_PLUS; else if (hub_is_superspeed(hub->hdev)) udev->speed = USB_SPEED_SUPER; else if (portstatus & USB_PORT_STAT_HIGH_SPEED) diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 45d070dd1d03..34c1a7e22aae 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -140,6 +140,13 @@ static inline int hub_is_superspeed(struct usb_device *hdev) return hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS; } +static inline int hub_is_superspeedplus(struct usb_device *hdev) +{ + return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS && + le16_to_cpu(hdev->descriptor.bcdUSB) >= 0x0310 && + hdev->bos->ssp_cap); +} + static inline unsigned hub_power_on_good_delay(struct usb_hub *hub) { unsigned delay = hub->descriptor->bPwrOn2PwrGood * 2; diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h index 331499d597fa..361297e96f58 100644 --- a/include/uapi/linux/usb/ch11.h +++ b/include/uapi/linux/usb/ch11.h @@ -29,6 +29,14 @@ #define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) #define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) +/* + * Port status type for GetPortStatus requests added in USB 3.1 + * See USB 3.1 spec Table 10-12 + */ +#define HUB_PORT_STATUS 0 +#define HUB_PORT_PD_STATUS 1 +#define HUB_EXT_PORT_STATUS 2 + /* * Hub class requests * See USB 2.0 spec Table 11-16 @@ -97,10 +105,13 @@ /* * Hub Status and Hub Change results * See USB 2.0 spec Table 11-19 and Table 11-20 + * USB 3.1 extends the port status request and may return 4 additional bytes. + * See USB 3.1 spec section 10.16.2.6 Table 10-12 and 10-15 */ struct usb_port_status { __le16 wPortStatus; __le16 wPortChange; + __le32 dwExtPortStatus; } __attribute__ ((packed)); /* @@ -172,6 +183,16 @@ struct usb_port_status { #define USB_PORT_STAT_C_LINK_STATE 0x0040 #define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 +/* + * USB 3.1 dwExtPortStatus field masks + * See USB 3.1 spec 10.16.2.6.3 Table 10-15 + */ + +#define USB_EXT_PORT_STAT_RX_SPEED_ID 0x0000000f +#define USB_EXT_PORT_STAT_TX_SPEED_ID 0x000000f0 +#define USB_EXT_PORT_STAT_RX_LANES 0x00000f00 +#define USB_EXT_PORT_STAT_TX_LANES 0x0000f000 + /* * wHubCharacteristics (masks) * See USB 2.0 spec Table 11-13, offset 3 -- cgit From d58593426e5cf41009f2e9d6eec3f47fe0cbedeb Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 28 Dec 2015 23:00:15 +0800 Subject: extcon: Use to_i2c_client for both rt8973a and sm5502 Use to_i2c_client() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-rt8973a.c | 4 ++-- drivers/extcon/extcon-sm5502.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index e1bb82809bef..7635a8eaf4c6 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c @@ -663,7 +663,7 @@ MODULE_DEVICE_TABLE(of, rt8973a_dt_match); #ifdef CONFIG_PM_SLEEP static int rt8973a_muic_suspend(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct rt8973a_muic_info *info = i2c_get_clientdata(i2c); enable_irq_wake(info->irq); @@ -673,7 +673,7 @@ static int rt8973a_muic_suspend(struct device *dev) static int rt8973a_muic_resume(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct rt8973a_muic_info *info = i2c_get_clientdata(i2c); disable_irq_wake(info->irq); diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 7aac3cc7efd7..571de2e6e7c4 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -655,7 +655,7 @@ MODULE_DEVICE_TABLE(of, sm5502_dt_match); #ifdef CONFIG_PM_SLEEP static int sm5502_muic_suspend(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct sm5502_muic_info *info = i2c_get_clientdata(i2c); enable_irq_wake(info->irq); @@ -665,7 +665,7 @@ static int sm5502_muic_suspend(struct device *dev) static int sm5502_muic_resume(struct device *dev) { - struct i2c_client *i2c = container_of(dev, struct i2c_client, dev); + struct i2c_client *i2c = to_i2c_client(dev); struct sm5502_muic_info *info = i2c_get_clientdata(i2c); disable_irq_wake(info->irq); -- cgit From b51b387020ee1c2bc27bf9121ca9b9d4113e433d Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Wed, 23 Dec 2015 21:34:07 -0800 Subject: extcon: gpio: Fix typo in comment This patch fixes the typo in comment of extcon-gpio.c driver. - 'interrput' -> 'interrupt' Signed-off-by: Moritz Fischer Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c index 279ff8f6637d..d023789f0fda 100644 --- a/drivers/extcon/extcon-gpio.c +++ b/drivers/extcon/extcon-gpio.c @@ -126,7 +126,7 @@ static int gpio_extcon_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&data->work, gpio_extcon_work); /* - * Request the interrput of gpio to detect whether external connector + * Request the interrupt of gpio to detect whether external connector * is attached or detached. */ ret = devm_request_any_context_irq(&pdev->dev, data->irq, -- cgit From 8b45b6a0741678902810d7be95e635c210fbb198 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Mon, 9 Nov 2015 10:10:15 +0900 Subject: extcon: Add the EXTCON_CHG_USB_SDP to support SDP charing port This patch adds the new EXTCON_CHG_USB_SDP connector to support SDP (Standard Downstream Port) USB charging port. The commit 11eecf910bd8 ("extcon: Modify the id and name of external connector") add the new EXTCON_CHG_USB_SDP connector which support the both data transfer and usb charging at the same time. Signed-off-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski --- drivers/extcon/extcon-max14577.c | 3 +++ drivers/extcon/extcon-max77693.c | 12 +++++++++++- drivers/extcon/extcon-max77843.c | 3 +++ drivers/extcon/extcon-max8997.c | 3 +++ drivers/extcon/extcon-rt8973a.c | 4 ++++ drivers/extcon/extcon-sm5502.c | 4 ++++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-max14577.c b/drivers/extcon/extcon-max14577.c index b30ab97ce75f..852a7112f451 100644 --- a/drivers/extcon/extcon-max14577.c +++ b/drivers/extcon/extcon-max14577.c @@ -150,6 +150,7 @@ enum max14577_muic_acc_type { static const unsigned int max14577_extcon_cable[] = { EXTCON_USB, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_FAST, EXTCON_CHG_USB_SLOW, @@ -454,6 +455,8 @@ static int max14577_muic_chg_handler(struct max14577_muic_info *info) return ret; extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX14577_CHARGER_TYPE_DEDICATED_CHG: extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_DCP, diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index fdf8f5d4d4e9..f17cb76b567c 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -204,6 +204,7 @@ enum max77693_muic_acc_type { static const unsigned int max77693_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_FAST, EXTCON_CHG_USB_SLOW, @@ -512,8 +513,11 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info, break; case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */ dock_id = EXTCON_DOCK; - if (!attached) + if (!attached) { extcon_set_cable_state_(info->edev, EXTCON_USB, false); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + false); + } break; default: dev_err(info->dev, "failed to detect %s dock device\n", @@ -601,6 +605,8 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info) if (ret < 0) return ret; extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77693_MUIC_GND_MHL: case MAX77693_MUIC_GND_MHL_VB: @@ -830,6 +836,8 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) */ extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); if (!cable_attached) extcon_set_cable_state_(info->edev, EXTCON_DOCK, @@ -899,6 +907,8 @@ static int max77693_muic_chg_handler(struct max77693_muic_info *info) extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77693_CHARGER_TYPE_DEDICATED_CHG: /* Only TA cable */ diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index 74dfb7f4f277..7bbc30097771 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c @@ -122,6 +122,7 @@ enum max77843_muic_charger_type { static const unsigned int max77843_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_CDP, EXTCON_CHG_USB_FAST, @@ -486,6 +487,8 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info) return ret; extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; case MAX77843_MUIC_CHG_DOWNSTREAM: ret = max77843_muic_set_path(info, diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index b2b13b3dce14..9a89320d09a8 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -148,6 +148,7 @@ struct max8997_muic_info { static const unsigned int max8997_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_CHG_USB_FAST, EXTCON_CHG_USB_SLOW, @@ -334,6 +335,8 @@ static int max8997_muic_handle_usb(struct max8997_muic_info *info, break; case MAX8997_USB_DEVICE: extcon_set_cable_state_(info->edev, EXTCON_USB, attached); + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); break; default: dev_err(info->dev, "failed to detect %s usb cable\n", diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c index 7635a8eaf4c6..97e074d70eca 100644 --- a/drivers/extcon/extcon-rt8973a.c +++ b/drivers/extcon/extcon-rt8973a.c @@ -93,6 +93,7 @@ static struct reg_data rt8973a_reg_data[] = { static const unsigned int rt8973a_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_JIG, EXTCON_NONE, @@ -398,6 +399,9 @@ static int rt8973a_muic_cable_handler(struct rt8973a_muic_info *info, /* Change the state of external accessory */ extcon_set_cable_state_(info->edev, id, attached); + if (id == EXTCON_USB) + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); return 0; } diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 571de2e6e7c4..df769a17e736 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -95,6 +95,7 @@ static struct reg_data sm5502_reg_data[] = { static const unsigned int sm5502_extcon_cable[] = { EXTCON_USB, EXTCON_USB_HOST, + EXTCON_CHG_USB_SDP, EXTCON_CHG_USB_DCP, EXTCON_NONE, }; @@ -411,6 +412,9 @@ static int sm5502_muic_cable_handler(struct sm5502_muic_info *info, /* Change the state of external accessory */ extcon_set_cable_state_(info->edev, id, attached); + if (id == EXTCON_USB) + extcon_set_cable_state_(info->edev, EXTCON_CHG_USB_SDP, + attached); return 0; } -- cgit From 03bf1adbd68d349eaccf16d42e0ef7e368c3716a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 29 Dec 2015 16:32:03 +0000 Subject: extcon: arizona: Use DAPM mutex helper functions We should be using the helper functions to lock the DAPM mutex not accessing it directly. There are no ill effects of this as the moment but it is best practice, and the implementation could be changed in the future. Signed-off-by: Charles Keepax Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-arizona.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index c121d01a5cd6..1d8e0a57bd51 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -185,7 +185,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, break; }; - mutex_lock(&arizona->dapm->card->dapm_mutex); + snd_soc_dapm_mutex_lock(arizona->dapm); arizona->hpdet_clamp = clamp; @@ -227,7 +227,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, ret); } - mutex_unlock(&arizona->dapm->card->dapm_mutex); + snd_soc_dapm_mutex_unlock(arizona->dapm); } static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) -- cgit From c9784a467380dfbd8070c735e651af07331172d9 Mon Sep 17 00:00:00 2001 From: Jie Yang Date: Thu, 7 Jan 2016 08:39:33 +0800 Subject: dmaengine: dw: fix a typo for bitfields of CTL_LO The offset of SINC should be 9, not 7, here fix this typo. Signed-off-by: Jie Yang Acked-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/dw/regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 241ff2b1402b..0a50c18d85b8 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -150,7 +150,7 @@ enum dw_dma_msize { #define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */ #define DWC_CTLL_DST_DEC (1<<7) #define DWC_CTLL_DST_FIX (2<<7) -#define DWC_CTLL_SRC_INC (0<<7) /* SAR update/not */ +#define DWC_CTLL_SRC_INC (0<<9) /* SAR update/not */ #define DWC_CTLL_SRC_DEC (1<<9) #define DWC_CTLL_SRC_FIX (2<<9) #define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ -- cgit From 94901e1b24496f04bd59176b7f87406e71505e27 Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Thu, 7 Jan 2016 23:05:48 +0100 Subject: dmaengine: ep93xx: Treat STALL and NFB IRQs same way Debugging ALSA hangups it was found that EP9302 (latest E2 rev.) DMA controller sometimes asserts STALL interrupt instead of NFB interrupt. Simply ignoring the difference and simply acting upon the amount of data we still have to transfer seems to work fine. This somehow sounds similar to M2M issue which is already dealt with in the driver, when the controller asserts DONE interrupt too early. The issue is not documented in Cirrus Logic erratas for EP93XX, but original Cirrus DMA driver from 2003 (not based on DMA API) did the similar handling of STALL interrupt. In-tree driver (6d831c65) did it also, before conversion to DMA engine API. Signed-off-by: Alexander Sverdlin Signed-off-by: Vinod Koul --- drivers/dma/ep93xx_dma.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 57ff46284f15..21f08cc3352b 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -421,23 +421,25 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac) desc->size); } - switch (irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB)) { - case M2P_INTERRUPT_STALL: - /* Disable interrupts */ - control = readl(edmac->regs + M2P_CONTROL); - control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT); - m2p_set_control(edmac, control); - - return INTERRUPT_DONE; - - case M2P_INTERRUPT_NFB: - if (ep93xx_dma_advance_active(edmac)) - m2p_fill_desc(edmac); + /* + * Even latest E2 silicon revision sometimes assert STALL interrupt + * instead of NFB. Therefore we treat them equally, basing on the + * amount of data we still have to transfer. + */ + if (!(irq_status & (M2P_INTERRUPT_STALL | M2P_INTERRUPT_NFB))) + return INTERRUPT_UNKNOWN; + if (ep93xx_dma_advance_active(edmac)) { + m2p_fill_desc(edmac); return INTERRUPT_NEXT_BUFFER; } - return INTERRUPT_UNKNOWN; + /* Disable interrupts */ + control = readl(edmac->regs + M2P_CONTROL); + control &= ~(M2P_CONTROL_STALLINT | M2P_CONTROL_NFBINT); + m2p_set_control(edmac, control); + + return INTERRUPT_DONE; } /* -- cgit From 8319f84adb49b5c6d69bbce86442e26c2277376f Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Fri, 8 Jan 2016 14:48:17 -0700 Subject: dmaengine: ioatdma: Squelch framesize warnings CC [M] drivers/dma/ioat/prep.o drivers/dma/ioat/prep.c: In function 'ioat_prep_pqxor': drivers/dma/ioat/prep.c:682:1: warning: the frame size of 1048 bytes is larger than 1024 bytes [-Wframe-larger-than=] } ^ drivers/dma/ioat/prep.c: In function 'ioat_prep_pqxor_val': drivers/dma/ioat/prep.c:714:1: warning: the frame size of 1048 bytes is larger than 1024 bytes [-Wframe-larger-than=] } gcc version 5.3.1 20151219 (Ubuntu 5.3.1-4ubuntu1) Cc: Vinod Koul Cc: Dan Williams Cc: Dave Jiang Cc: Prarit Bhargava Cc: Nicholas Mc Guire Cc: Jarkko Nikula Signed-off-by: Tim Gardner Signed-off-by: Vinod Koul --- drivers/dma/ioat/prep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/ioat/prep.c b/drivers/dma/ioat/prep.c index 6bb4a13a8fbd..243421af888f 100644 --- a/drivers/dma/ioat/prep.c +++ b/drivers/dma/ioat/prep.c @@ -26,7 +26,7 @@ #include "hw.h" #include "dma.h" -#define MAX_SCF 1024 +#define MAX_SCF 256 /* provide a lookup table for setting the source address in the base or * extended descriptor of an xor or pq descriptor -- cgit From cae058610465029cee113ac41c7f5cf881f5cfed Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Thu, 17 Dec 2015 17:02:35 +0530 Subject: drivers/usb/host: fsl: Set DMA_MASK of usb platform device Set DMA_MASK of usb platform device properly. Signed-off-by: Sriram Dash Signed-off-by: Ramneek Mehresh Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fsl-mph-dr-of.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 0c382652a399..1044b0f9d656 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -17,6 +17,7 @@ #include #include #include +#include struct fsl_usb2_dev_data { char *dr_mode; /* controller mode */ @@ -96,7 +97,11 @@ static struct platform_device *fsl_usb2_device_register( pdev->dev.parent = &ofdev->dev; pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; - *pdev->dev.dma_mask = *ofdev->dev.dma_mask; + + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask; + else + dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); if (retval) -- cgit From 6f5429d986f81a5c16d451c5d63d829a785f470a Mon Sep 17 00:00:00 2001 From: Sriram Dash Date: Fri, 18 Dec 2015 14:16:29 +0530 Subject: drivers/usb/host/fsl: Port USB EHCI host driver for LS102xA Change Power architecture specific APIs such as in_be32/out_be32 for registers read/write. Instead using ioread/writebe32 which are defined for power as well as arm architecture Signed-off-by: Nikhil Badola Signed-off-by: Sriram Dash Signed-off-by: Ramneek Mehresh Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-fsl.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3b6eb219de1a..9f5ffb629973 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "ehci.h" #include "ehci-fsl.h" @@ -241,7 +242,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, * to portsc */ if (pdata->check_phy_clk_valid) { - if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) { + if (!(ioread32be(non_ehci + FSL_SOC_USB_CTRL) & + PHY_CLK_VALID)) { dev_warn(hcd->self.controller, "USB PHY clock invalid\n"); return -EINVAL; @@ -273,9 +275,11 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) /* Setup Snooping for all the 4GB space */ /* SNOOP1 starts from 0x0, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); + iowrite32be(0x0 | SNOOP_SIZE_2GB, + non_ehci + FSL_SOC_USB_SNOOP1); /* SNOOP2 starts from 0x80000000, size 2G */ - out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); + iowrite32be(0x80000000 | SNOOP_SIZE_2GB, + non_ehci + FSL_SOC_USB_SNOOP2); } /* Deal with USB erratum A-005275 */ @@ -309,13 +313,13 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) if (pdata->have_sysif_regs) { #ifdef CONFIG_FSL_SOC_BOOKE - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); - out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); + iowrite32be(0x00000008, non_ehci + FSL_SOC_USB_PRICTRL); + iowrite32be(0x00000080, non_ehci + FSL_SOC_USB_AGECNTTHRSH); #else - out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); - out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); + iowrite32be(0x0000000c, non_ehci + FSL_SOC_USB_PRICTRL); + iowrite32be(0x00000040, non_ehci + FSL_SOC_USB_AGECNTTHRSH); #endif - out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); + iowrite32be(0x00000001, non_ehci + FSL_SOC_USB_SICTRL); } return 0; @@ -554,7 +558,7 @@ static int ehci_fsl_drv_suspend(struct device *dev) if (!fsl_deep_sleep()) return 0; - ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL); + ehci_fsl->usb_ctrl = ioread32be(non_ehci + FSL_SOC_USB_CTRL); return 0; } @@ -577,7 +581,7 @@ static int ehci_fsl_drv_resume(struct device *dev) usb_root_hub_lost_power(hcd->self.root_hub); /* Restore USB PHY settings and enable the controller. */ - out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl); + iowrite32be(ehci_fsl->usb_ctrl, non_ehci + FSL_SOC_USB_CTRL); ehci_reset(ehci); ehci_fsl_reinit(ehci); -- cgit From f8868ed0078a8456ac725103a97cbe6d833e13f3 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 16:49:14 +0200 Subject: usb: core: use kbasename() instead of open-coded variant kbasename() helper is dedicated to find a last part of the filename or pathname. USB core uses open-coded variant of that helper. Replace some lines of code by kbasename() call. The current users do not have trailing slash and we are on the safe side to make such change. I dig a history of the code under question up and found the patch [1] that brought it along with the same to tty layer. The check for trailing slash looks like copy'n'paste thing and I consider it as redundant. [1] http://www.kernel.org/pub/linux/kernel//people/akpm/patches/2.5/2.5.69/2.5.69-mm3/broken-out/linus.patch Signed-off-by: Andy Shevchenko Cc: Greg Kroah-Hartman Cc: Rasmus Villemoes Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index ea337a718cc1..822ced9639aa 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "usb.h" @@ -155,7 +156,6 @@ int usb_register_dev(struct usb_interface *intf, int minor_base = class_driver->minor_base; int minor; char name[20]; - char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS /* @@ -192,14 +192,9 @@ int usb_register_dev(struct usb_interface *intf, /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); - temp = strrchr(name, '/'); - if (temp && (temp[1] != '\0')) - ++temp; - else - temp = name; intf->usb_dev = device_create(usb_class->class, &intf->dev, MKDEV(USB_MAJOR, minor), class_driver, - "%s", temp); + "%s", kbasename(name)); if (IS_ERR(intf->usb_dev)) { down_write(&minor_rwsem); usb_minors[minor] = NULL; -- cgit From 352d9e2ee85b43170388599a17cd7b219f270163 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 5 Dec 2015 13:15:06 +0100 Subject: USB: bcma: make helper creating platform dev more generic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having "bool ohci" argument in bcma_hcd_create_pdev function limited it to support two cases only (OHCI and EHCI) and put too much logic in it. Lets make caller pass all required data. This adds few extra arguments to the function call but will allow us to reuse this code and handle more cases in the future (e.g. add XHCI support). Signed-off-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/bcma-hcd.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 291aaa2baed8..dea12e9085ce 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -244,7 +244,10 @@ static const struct usb_ehci_pdata ehci_pdata = { static const struct usb_ohci_pdata ohci_pdata = { }; -static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) +static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, + const char *name, u32 addr, + const void *data, + size_t size) { struct platform_device *hci_dev; struct resource hci_res[2]; @@ -259,8 +262,7 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo hci_res[1].start = dev->irq; hci_res[1].flags = IORESOURCE_IRQ; - hci_dev = platform_device_alloc(ohci ? "ohci-platform" : - "ehci-platform" , 0); + hci_dev = platform_device_alloc(name, 0); if (!hci_dev) return ERR_PTR(-ENOMEM); @@ -271,12 +273,8 @@ static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, boo ARRAY_SIZE(hci_res)); if (ret) goto err_alloc; - if (ohci) - ret = platform_device_add_data(hci_dev, &ohci_pdata, - sizeof(ohci_pdata)); - else - ret = platform_device_add_data(hci_dev, &ehci_pdata, - sizeof(ehci_pdata)); + if (data) + ret = platform_device_add_data(hci_dev, data, size); if (ret) goto err_alloc; ret = platform_device_add(hci_dev); @@ -333,11 +331,15 @@ static int bcma_hcd_probe(struct bcma_device *dev) && chipinfo->rev == 0) ohci_addr = 0x18009000; - usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr); + usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, "ohci-platform", + ohci_addr, &ohci_pdata, + sizeof(ohci_pdata)); if (IS_ERR(usb_dev->ohci_dev)) return PTR_ERR(usb_dev->ohci_dev); - usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr); + usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, "ehci-platform", + dev->addr, &ehci_pdata, + sizeof(ehci_pdata)); if (IS_ERR(usb_dev->ehci_dev)) { err = PTR_ERR(usb_dev->ehci_dev); goto err_unregister_ohci_dev; -- cgit From adbff3a4f93d8501e8ae11906268e21b086d57ed Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 5 Dec 2015 13:15:07 +0100 Subject: USB: bcma: separate code initializing USB 2.0 core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This splits one big probing function into two smaller ones. The main one is now responsible for the generic stuff: allocating memory & enabling power using GPIO. The new one contains code that is specific to the USB 2.0 bcma core. This will allow adding support for the USB 3.0 bcma core (handling XHCI) in the future. Signed-off-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/bcma-hcd.c | 59 ++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index dea12e9085ce..963e2d0e8f92 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -35,6 +35,7 @@ MODULE_DESCRIPTION("Common USB driver for BCMA Bus"); MODULE_LICENSE("GPL"); struct bcma_hcd_device { + struct bcma_device *core; struct platform_device *ehci_dev; struct platform_device *ohci_dev; struct gpio_desc *gpio_desc; @@ -288,31 +289,16 @@ err_alloc: return ERR_PTR(ret); } -static int bcma_hcd_probe(struct bcma_device *dev) +static int bcma_hcd_usb20_init(struct bcma_hcd_device *usb_dev) { - int err; + struct bcma_device *dev = usb_dev->core; + struct bcma_chipinfo *chipinfo = &dev->bus->chipinfo; u32 ohci_addr; - struct bcma_hcd_device *usb_dev; - struct bcma_chipinfo *chipinfo; - - chipinfo = &dev->bus->chipinfo; - - /* TODO: Probably need checks here; is the core connected? */ + int err; if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32))) return -EOPNOTSUPP; - usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device), - GFP_KERNEL); - if (!usb_dev) - return -ENOMEM; - - if (dev->dev.of_node) - usb_dev->gpio_desc = devm_get_gpiod_from_child(&dev->dev, "vcc", - &dev->dev.of_node->fwnode); - if (!IS_ERR_OR_NULL(usb_dev->gpio_desc)) - gpiod_direction_output(usb_dev->gpio_desc, 1); - switch (dev->id.id) { case BCMA_CORE_NS_USB20: bcma_hcd_init_chip_arm(dev); @@ -345,7 +331,6 @@ static int bcma_hcd_probe(struct bcma_device *dev) goto err_unregister_ohci_dev; } - bcma_set_drvdata(dev, usb_dev); return 0; err_unregister_ohci_dev: @@ -353,6 +338,40 @@ err_unregister_ohci_dev: return err; } +static int bcma_hcd_probe(struct bcma_device *core) +{ + int err; + struct bcma_hcd_device *usb_dev; + + /* TODO: Probably need checks here; is the core connected? */ + + usb_dev = devm_kzalloc(&core->dev, sizeof(struct bcma_hcd_device), + GFP_KERNEL); + if (!usb_dev) + return -ENOMEM; + 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); + + switch (core->id.id) { + case BCMA_CORE_USB20_HOST: + case BCMA_CORE_NS_USB20: + err = bcma_hcd_usb20_init(usb_dev); + if (err) + return err; + break; + default: + return -ENODEV; + } + + bcma_set_drvdata(core, usb_dev); + return 0; +} + static void bcma_hcd_remove(struct bcma_device *dev) { struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); -- cgit From 132f5005abbd480b66c58f8113ed876b99b6318e Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:53 -0600 Subject: usb: host: ehci-msm: Allow LS devices to work Disable the silicon quirk which is normally enabled for HSIC host mode. This would otherwise prevent low speed devices from enumerating properly. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 2 ++ include/linux/usb/msm_hsusb_hw.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index c23e2858c815..aed499d64029 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -61,6 +61,8 @@ static int ehci_msm_reset(struct usb_hcd *hcd) writel(0x8, USB_AHBMODE); /* Disable streaming mode and select host mode */ writel(0x13, USB_USBMODE); + /* Disable ULPI_TX_PKT_EN_CLR_FIX which is valid only for HSIC */ + writel(readl(USB_GENCONFIG_2) & ~ULPI_TX_PKT_EN_CLR_FIX, USB_GENCONFIG_2); return 0; } diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h index e159b39f67a2..974c3796a23f 100644 --- a/include/linux/usb/msm_hsusb_hw.h +++ b/include/linux/usb/msm_hsusb_hw.h @@ -22,6 +22,7 @@ #define USB_AHBBURST (MSM_USB_BASE + 0x0090) #define USB_AHBMODE (MSM_USB_BASE + 0x0098) #define USB_GENCONFIG_2 (MSM_USB_BASE + 0x00a0) +#define ULPI_TX_PKT_EN_CLR_FIX BIT(19) #define USB_CAPLENGTH (MSM_USB_BASE + 0x0100) /* 8 bit */ -- cgit From c4398ef609ed1f39b65190867837a6bf517616b6 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:54 -0600 Subject: usb: host: ehci-msm: Remove dependency on OTG PHY Currently the EHCI MSM driver has a hard dependency to be created by an OTG layer, namely the phy-msm-usb driver. In some cases or board configurations we want to allow the EHCI host to be instantiated without OTG capability. Instead, relax the dependency on having an OTG PHY being present and call usb_add_hcd() directly. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 53 ++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index aed499d64029..e1004bc8ca8e 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -106,9 +106,9 @@ static int ehci_msm_probe(struct platform_device *pdev) } /* - * OTG driver takes care of PHY initialization, clock management, - * powering up VBUS, mapping of registers address space and power - * management. + * If there is an OTG driver, let it take care of PHY initialization, + * clock management, powering up VBUS, mapping of registers address + * space and power management. */ if (pdev->dev.of_node) phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); @@ -116,27 +116,35 @@ static int ehci_msm_probe(struct platform_device *pdev) phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR(phy)) { - dev_err(&pdev->dev, "unable to find transceiver\n"); - ret = -EPROBE_DEFER; - goto put_hcd; - } - - ret = otg_set_host(phy->otg, &hcd->self); - if (ret < 0) { - dev_err(&pdev->dev, "unable to register with transceiver\n"); - goto put_hcd; + if (PTR_ERR(phy) == -EPROBE_DEFER) { + dev_err(&pdev->dev, "unable to find transceiver\n"); + ret = -EPROBE_DEFER; + goto put_hcd; + } + phy = NULL; } hcd->usb_phy = phy; device_init_wakeup(&pdev->dev, 1); - /* - * OTG device parent of HCD takes care of putting - * hardware into low power mode. - */ - pm_runtime_no_callbacks(&pdev->dev); - pm_runtime_enable(&pdev->dev); - /* FIXME: need to call usb_add_hcd() here? */ + if (phy && phy->otg) { + /* + * MSM OTG driver takes care of adding the HCD and + * placing hardware into low power mode via runtime PM. + */ + ret = otg_set_host(phy->otg, &hcd->self); + if (ret < 0) { + dev_err(&pdev->dev, "unable to register with transceiver\n"); + goto put_hcd; + } + + pm_runtime_no_callbacks(&pdev->dev); + pm_runtime_enable(&pdev->dev); + } else { + ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); + if (ret) + goto put_hcd; + } return 0; @@ -154,9 +162,10 @@ static int ehci_msm_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - otg_set_host(hcd->usb_phy->otg, NULL); - - /* FIXME: need to call usb_remove_hcd() here? */ + if (hcd->usb_phy && hcd->usb_phy->otg) + otg_set_host(hcd->usb_phy->otg, NULL); + else + usb_remove_hcd(hcd); usb_put_hcd(hcd); -- cgit From f13f0e65606c4877a9c16b3a8d1272fcaaa987a8 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:55 -0600 Subject: usb: host: ehci-msm: Add support for ACPI probing Allow the EHCI MSM driver to probe against an ACPI enumerated device with ID QCOM8040. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index e1004bc8ca8e..102837e58bbf 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "ehci.h" @@ -202,6 +203,12 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = { .resume = ehci_msm_pm_resume, }; +static const struct acpi_device_id msm_ehci_acpi_ids[] = { + { "QCOM8040", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, msm_ehci_acpi_ids); + static const struct of_device_id msm_ehci_dt_match[] = { { .compatible = "qcom,ehci-host", }, {} @@ -215,6 +222,7 @@ static struct platform_driver ehci_msm_driver = { .name = "msm_hsusb_host", .pm = &ehci_msm_dev_pm_ops, .of_match_table = msm_ehci_dt_match, + .acpi_match_table = ACPI_PTR(msm_ehci_acpi_ids), }, }; -- cgit From e8f55b91482247b0b11b2f2f12188d9be55bbd19 Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 10 Dec 2015 18:28:56 -0600 Subject: usb: host: ehci-msm: Fix register initialization The default value for the 'transceiver select' field of the PORTSC register may not always be correct. Previously the phy-msm-usb driver would do this for us, but since ehci-msm can now be instantiated standalone without any PHY driver, the register needs to be explicitly initialized to ULPI mode to properly communicate with the PHY. This is not readily apparent, as firmware or bootloader code also happen to pre-initialize this for us. However, it can manifest when performing a driver unbind/rebind as follows: cd /sys/bus/platform/drivers/msm_hsusb_host echo QCOM8040:00 > unbind echo QCOM8040:00 > bind The EHCI core executes a controller reset as part of this, and as a result the register in question would revert to its default state and must be re-initialized properly. Furthermore this may be useful in the future when adding PM suspend/resume support. Signed-off-by: Jack Pham Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 102837e58bbf..b71947d04fed 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -56,6 +56,8 @@ static int ehci_msm_reset(struct usb_hcd *hcd) if (retval) return retval; + /* select ULPI phy and clear other status/control bits in PORTSC */ + writel(PORTSC_PTS_ULPI, USB_PORTSC); /* bursts of unspecified length. */ writel(0, USB_AHBBURST); /* Use the AHB transactor, allow posted data writes */ -- cgit From 4bb3cad7125ba03255025cf1e4e7c638e4757f6c Mon Sep 17 00:00:00 2001 From: Azriel Samson Date: Thu, 10 Dec 2015 18:28:57 -0600 Subject: usb: host: ehci-msm: Register usb shutdown function Registering usb_hcd_platform_shutdown to be called during shutdown. This is a generic function that performs the generic host stack's shutdown. It ensures that USB operations do not continue while kexec boots a new kernel. Signed-off-by: Azriel Samson Signed-off-by: Timur Tabi Reviewed-by: Andy Gross Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-msm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index b71947d04fed..3e226ef6ca62 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -220,6 +220,7 @@ MODULE_DEVICE_TABLE(of, msm_ehci_dt_match); static struct platform_driver ehci_msm_driver = { .probe = ehci_msm_probe, .remove = ehci_msm_remove, + .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "msm_hsusb_host", .pm = &ehci_msm_dev_pm_ops, -- cgit From d8ff463a4ef22f090df21a3c5b34b336e80b72ca Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Mon, 4 Jan 2016 16:14:43 +0800 Subject: ehci-hcd: Cleanup memory resources when ehci_halt fails The driver calls ehci_mem_init to allocate memory resources. But these resources are not freed when ehci_halt fails. This patch adds "ehci_mem_cleanup" in error handling code to fix this problem. Signed-off-by: Jia-Ju Bai Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 14178bbf0694..00e77cc91053 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -675,8 +675,10 @@ int ehci_setup(struct usb_hcd *hcd) return retval; retval = ehci_halt(ehci); - if (retval) + if (retval) { + ehci_mem_cleanup(ehci); return retval; + } ehci_reset(ehci); -- cgit From e3e2e36c106a1e4212c65ba5b5d2bcb3455cb354 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Mon, 4 Jan 2016 16:14:29 +0800 Subject: ehci-hcd: Disable memory-write-invalidate when the driver is removed The driver calls pci_set_mwi to enable memory-write-invalidate when it is initialized, but does not call pci_clear_mwi when it is removed. Many other drivers calls pci_clear_mwi when pci_set_mwi is called, such as r8169, 8139cp and e1000. This patch adds a function "ehci_pci_remove" to remove the pci driver. This function calls pci_clear_mwi and usb_hcd_pci_remove, which can fix the problem. Signed-off-by: Jia-Ju Bai Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 2a5d2fd76040..3b3649d88c5f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -377,6 +377,12 @@ static int ehci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return usb_hcd_pci_probe(pdev, id); } +static void ehci_pci_remove(struct pci_dev *pdev) +{ + pci_clear_mwi(pdev); + usb_hcd_pci_remove(pdev); +} + /* PCI driver selection metadata; PCI hotplugging uses this */ static const struct pci_device_id pci_ids [] = { { /* handle any USB 2.0 EHCI controller */ @@ -396,7 +402,7 @@ static struct pci_driver ehci_pci_driver = { .id_table = pci_ids, .probe = ehci_pci_probe, - .remove = usb_hcd_pci_remove, + .remove = ehci_pci_remove, .shutdown = usb_hcd_pci_shutdown, #ifdef CONFIG_PM -- cgit From 2f4c8e554bd38c78b5edb43e5ff8bc2341bc276a Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:26 +0800 Subject: usb: host: fotg210: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fotg210-hcd.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c index 2341af4f3490..360a5e95abca 100644 --- a/drivers/usb/host/fotg210-hcd.c +++ b/drivers/usb/host/fotg210-hcd.c @@ -2267,7 +2267,7 @@ static unsigned qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh) { struct fotg210_qtd *last, *end = qh->dummy; - struct list_head *entry, *tmp; + struct fotg210_qtd *qtd, *tmp; int last_status; int stopped; unsigned count = 0; @@ -2301,12 +2301,10 @@ rescan: * then let the queue advance. * if queue is stopped, handles unlinks. */ - list_for_each_safe(entry, tmp, &qh->qtd_list) { - struct fotg210_qtd *qtd; + list_for_each_entry_safe(qtd, tmp, &qh->qtd_list, qtd_list) { struct urb *urb; u32 token = 0; - qtd = list_entry(entry, struct fotg210_qtd, qtd_list); urb = qtd->urb; /* clean up any state from previous QTD ...*/ @@ -2544,14 +2542,11 @@ retry_xacterr: * used for cleanup after errors, before HC sees an URB's TDs. */ static void qtd_list_free(struct fotg210_hcd *fotg210, struct urb *urb, - struct list_head *qtd_list) + struct list_head *head) { - struct list_head *entry, *temp; - - list_for_each_safe(entry, temp, qtd_list) { - struct fotg210_qtd *qtd; + struct fotg210_qtd *qtd, *temp; - qtd = list_entry(entry, struct fotg210_qtd, qtd_list); + list_for_each_entry_safe(qtd, temp, head, qtd_list) { list_del(&qtd->qtd_list); fotg210_qtd_free(fotg210, qtd); } -- cgit From 553c23605717cf4754d9cf35e6428df85c271a39 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sun, 20 Dec 2015 00:11:50 +0800 Subject: usb: host: max3421-hcd: use list_for_each_entry* Use list_for_each_entry*() instead of list_for_each*() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/max3421-hcd.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index bd98706d1ce9..c369c29e496d 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -797,19 +797,16 @@ max3421_check_unlink(struct usb_hcd *hcd) { struct spi_device *spi = to_spi_device(hcd->self.controller); struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd); - struct list_head *pos, *upos, *next_upos; struct max3421_ep *max3421_ep; struct usb_host_endpoint *ep; - struct urb *urb; + struct urb *urb, *next; unsigned long flags; int retval = 0; spin_lock_irqsave(&max3421_hcd->lock, flags); - list_for_each(pos, &max3421_hcd->ep_list) { - max3421_ep = container_of(pos, struct max3421_ep, ep_list); + list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) { ep = max3421_ep->ep; - list_for_each_safe(upos, next_upos, &ep->urb_list) { - urb = container_of(upos, struct urb, urb_list); + list_for_each_entry_safe(urb, next, &ep->urb_list, urb_list) { if (urb->unlinked) { retval = 1; dev_dbg(&spi->dev, "%s: URB %p unlinked=%d", @@ -1184,22 +1181,19 @@ dump_eps(struct usb_hcd *hcd) struct max3421_hcd *max3421_hcd = hcd_to_max3421(hcd); struct max3421_ep *max3421_ep; struct usb_host_endpoint *ep; - struct list_head *pos, *upos; char ubuf[512], *dp, *end; unsigned long flags; struct urb *urb; int epnum, ret; spin_lock_irqsave(&max3421_hcd->lock, flags); - list_for_each(pos, &max3421_hcd->ep_list) { - max3421_ep = container_of(pos, struct max3421_ep, ep_list); + list_for_each_entry(max3421_ep, &max3421_hcd->ep_list, ep_list) { ep = max3421_ep->ep; dp = ubuf; end = dp + sizeof(ubuf); *dp = '\0'; - list_for_each(upos, &ep->urb_list) { - urb = container_of(upos, struct urb, urb_list); + list_for_each_entry(urb, &ep->urb_list, urb_list) { ret = snprintf(dp, end - dp, " %p(%d.%s %d/%d)", urb, usb_pipetype(urb->pipe), usb_urb_dir_in(urb) ? "IN" : "OUT", -- cgit From 7b1585f2099ad65382b09f240e0c3ecdb7bfa92e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:28 +0800 Subject: usb: host: oxu210hp-hcd: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index bc74aca8a54c..4e4d601af35c 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -981,7 +981,7 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); static unsigned qh_completions(struct oxu_hcd *oxu, struct ehci_qh *qh) { struct ehci_qtd *last = NULL, *end = qh->dummy; - struct list_head *entry, *tmp; + struct ehci_qtd *qtd, *tmp; int stopped; unsigned count = 0; int do_status = 0; @@ -1006,12 +1006,10 @@ static unsigned qh_completions(struct oxu_hcd *oxu, struct ehci_qh *qh) * then let the queue advance. * if queue is stopped, handles unlinks. */ - list_for_each_safe(entry, tmp, &qh->qtd_list) { - struct ehci_qtd *qtd; + list_for_each_entry_safe(qtd, tmp, &qh->qtd_list, qtd_list) { struct urb *urb; u32 token = 0; - qtd = list_entry(entry, struct ehci_qtd, qtd_list); urb = qtd->urb; /* Clean up any state from previous QTD ...*/ @@ -1174,14 +1172,11 @@ halt: * used for cleanup after errors, before HC sees an URB's TDs. */ static void qtd_list_free(struct oxu_hcd *oxu, - struct urb *urb, struct list_head *qtd_list) + struct urb *urb, struct list_head *head) { - struct list_head *entry, *temp; - - list_for_each_safe(entry, temp, qtd_list) { - struct ehci_qtd *qtd; + struct ehci_qtd *qtd, *temp; - qtd = list_entry(entry, struct ehci_qtd, qtd_list); + list_for_each_entry_safe(qtd, temp, head, qtd_list) { list_del(&qtd->qtd_list); oxu_qtd_free(oxu, qtd); } -- cgit From 4e5d7a82d3acf8b53f3d72153de142c0ab608b56 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:29 +0800 Subject: usb: host: u132-hcd: use list_for_each_entry Use list_for_each_entry() instead of list_for_each() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/u132-hcd.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 05c85c7baf84..43d52931b5bf 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -1309,13 +1309,9 @@ static void u132_hcd_ring_work_scheduler(struct work_struct *work) u132_ring_put_kref(u132, ring); return; } else if (ring->curr_endp) { - struct u132_endp *last_endp = ring->curr_endp; - struct list_head *scan; - struct list_head *head = &last_endp->endp_ring; + struct u132_endp *endp, *last_endp = ring->curr_endp; unsigned long wakeup = 0; - list_for_each(scan, head) { - struct u132_endp *endp = list_entry(scan, - struct u132_endp, endp_ring); + list_for_each_entry(endp, &last_endp->endp_ring, endp_ring) { if (endp->queue_next == endp->queue_last) { } else if ((endp->delayed == 0) || time_after_eq(jiffies, endp->jiffies)) { @@ -2393,14 +2389,12 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, static int dequeue_from_overflow_chain(struct u132 *u132, struct u132_endp *endp, struct urb *urb) { - struct list_head *scan; - struct list_head *head = &endp->urb_more; - list_for_each(scan, head) { - struct u132_urbq *urbq = list_entry(scan, struct u132_urbq, - urb_more); + struct u132_urbq *urbq; + + list_for_each_entry(urbq, &endp->urb_more, urb_more) { if (urbq->urb == urb) { struct usb_hcd *hcd = u132_to_hcd(u132); - list_del(scan); + list_del(&urbq->urb_more); endp->queue_size -= 1; urb->error_count = 0; usb_hcd_giveback_urb(hcd, urb, 0); -- cgit From 32540ba237411244f04ef783bf0fa61041ab592d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:31 +0800 Subject: usb: chipidea: debug: use list_for_each_entry Use list_for_each_entry() instead of list_for_each() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/chipidea/debug.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index a4f7db2e18dd..de5c5092d078 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c @@ -172,7 +172,6 @@ static int ci_requests_show(struct seq_file *s, void *data) { struct ci_hdrc *ci = s->private; unsigned long flags; - struct list_head *ptr = NULL; struct ci_hw_req *req = NULL; struct td_node *node, *tmpnode; unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); @@ -184,9 +183,7 @@ static int ci_requests_show(struct seq_file *s, void *data) spin_lock_irqsave(&ci->lock, flags); for (i = 0; i < ci->hw_ep_max; i++) - list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { - req = list_entry(ptr, struct ci_hw_req, queue); - + list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) { list_for_each_entry_safe(node, tmpnode, &req->tds, td) { seq_printf(s, "EP=%02i: TD=%08X %s\n", i % (ci->hw_ep_max / 2), -- cgit From f6281af9d62e128aa6efad29cf7265062af114f2 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 19 Dec 2015 00:34:33 +0800 Subject: usb: gadget: rndis: use list_for_each_entry_safe Use list_for_each_entry_safe() instead of list_for_each_safe() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 70d3917cc003..34a76db2c8fd 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -914,7 +914,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v) params->media_state = RNDIS_MEDIA_STATE_DISCONNECTED; params->resp_avail = resp_avail; params->v = v; - INIT_LIST_HEAD(&(params->resp_queue)); + INIT_LIST_HEAD(¶ms->resp_queue); pr_debug("%s: configNr = %d\n", __func__, i); return params; @@ -1006,12 +1006,9 @@ EXPORT_SYMBOL_GPL(rndis_add_hdr); void rndis_free_response(struct rndis_params *params, u8 *buf) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (r && r->buf == buf) { list_del(&r->list); kfree(r); @@ -1022,14 +1019,11 @@ EXPORT_SYMBOL_GPL(rndis_free_response); u8 *rndis_get_next_response(struct rndis_params *params, u32 *length) { - rndis_resp_t *r; - struct list_head *act, *tmp; + rndis_resp_t *r, *n; if (!length) return NULL; - list_for_each_safe(act, tmp, &(params->resp_queue)) - { - r = list_entry(act, rndis_resp_t, list); + list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { if (!r->send) { r->send = 1; *length = r->length; @@ -1053,7 +1047,7 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length) r->length = length; r->send = 0; - list_add_tail(&r->list, &(params->resp_queue)); + list_add_tail(&r->list, ¶ms->resp_queue); return r; } -- cgit From aa742683bbea9f2faa28ec2f61745abf2ad86a9d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 19 Jan 2016 10:51:09 +0100 Subject: USB: uas: add full support for RESPONSE IU Some devices send response IUs when you'd expect a sense IU. As a response to a wrong LUN that is within spec. We cannot get away without handling for response IUs. This version fixes the issues Hans raised. Signed-off-by: Oliver Neukum Reviewed-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 9ff9404f99d7..44b096c1737b 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -246,6 +246,29 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, } } +static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd *cmnd) +{ + u8 response_code = riu->response_code; + + switch (response_code) { + case RC_INCORRECT_LUN: + cmnd->result = DID_BAD_TARGET << 16; + break; + case RC_TMF_SUCCEEDED: + cmnd->result = DID_OK << 16; + break; + case RC_TMF_NOT_SUPPORTED: + cmnd->result = DID_TARGET_FAILURE << 16; + break; + default: + uas_log_cmd_state(cmnd, "response iu", response_code); + cmnd->result = DID_ERROR << 16; + break; + } + + return response_code == RC_TMF_SUCCEEDED; +} + static void uas_stat_cmplt(struct urb *urb) { struct iu *iu = urb->transfer_buffer; @@ -258,6 +281,7 @@ static void uas_stat_cmplt(struct urb *urb) unsigned long flags; unsigned int idx; int status = urb->status; + bool success; spin_lock_irqsave(&devinfo->lock, flags); @@ -313,13 +337,13 @@ static void uas_stat_cmplt(struct urb *urb) uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); break; case IU_ID_RESPONSE: - uas_log_cmd_state(cmnd, "unexpected response iu", - ((struct response_iu *)iu)->response_code); - /* Error, cancel data transfers */ - data_in_urb = usb_get_urb(cmdinfo->data_in_urb); - data_out_urb = usb_get_urb(cmdinfo->data_out_urb); cmdinfo->state &= ~COMMAND_INFLIGHT; - cmnd->result = DID_ERROR << 16; + success = uas_evaluate_response_iu((struct response_iu *)iu, cmnd); + if (!success) { + /* Error, cancel data transfers */ + data_in_urb = usb_get_urb(cmdinfo->data_in_urb); + data_out_urb = usb_get_urb(cmdinfo->data_out_urb); + } uas_try_complete(cmnd, __func__); break; default: -- cgit From 69ab55d7be6c3d69fa2e38f2a2bed4e91b9edf8d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 21:26:50 +0800 Subject: USB: core, devio: use to_usb_device Use to_usb_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 2 +- drivers/usb/core/usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 054eb534c495..13a4b9f48739 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -848,7 +848,7 @@ static struct usb_device *usbdev_lookup_by_devt(dev_t devt) (void *) (unsigned long) devt, match_devt); if (!dev) return NULL; - return container_of(dev, struct usb_device, dev); + return to_usb_device(dev); } /* diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index ebb29caa3fe4..49b011f951b3 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -241,7 +241,7 @@ static int __each_dev(struct device *dev, void *data) if (!is_usb_device(dev)) return 0; - return arg->fn(container_of(dev, struct usb_device, dev), arg->data); + return arg->fn(to_usb_device(dev), arg->data); } /** -- cgit From 6ae706aeaf42cd2fe6e541c72af6e2c0befe057c Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 21:26:51 +0800 Subject: USB: core, wusbcore: use bus_to_hcd Use bus_to_hcd() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 6 +++--- drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.c | 2 +- drivers/usb/wusbcore/wusbhc.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 9af9506352f3..232c8c93dd3a 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2237,7 +2237,7 @@ int usb_hcd_get_frame_number (struct usb_device *udev) int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) { - struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); + struct usb_hcd *hcd = bus_to_hcd(rhdev->bus); int status; int old_state = hcd->state; @@ -2286,7 +2286,7 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) { - struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); + struct usb_hcd *hcd = bus_to_hcd(rhdev->bus); int status; int old_state = hcd->state; @@ -2400,7 +2400,7 @@ int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num) * boards with root hubs hooked up to internal devices (instead of * just the OTG port) may need more attention to resetting... */ - hcd = container_of (bus, struct usb_hcd, self); + hcd = bus_to_hcd(bus); if (port_num && hcd->driver->start_port_reset) status = hcd->driver->start_port_reset(hcd, port_num); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3c9b22eb78ca..9ec5733b62f4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2659,7 +2659,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) struct usb_hcd *hcd; if (hub->hdev->parent != NULL) /* not a root hub? */ return 0; - hcd = container_of(hub->hdev->bus, struct usb_hcd, self); + hcd = bus_to_hcd(hub->hdev->bus); return hcd->wireless; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 49b011f951b3..16ade41759cd 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -397,7 +397,7 @@ struct device_type usb_device_type = { /* Returns 1 if @usb_bus is WUSB, 0 otherwise */ static unsigned usb_bus_is_wusb(struct usb_bus *bus) { - struct usb_hcd *hcd = container_of(bus, struct usb_hcd, self); + struct usb_hcd *hcd = bus_to_hcd(bus); return hcd->wireless; } diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 41838db7f85c..8c5bd000739b 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h @@ -336,7 +336,7 @@ static inline struct usb_hcd *usb_hcd_get_by_usb_dev(struct usb_device *usb_dev) { struct usb_hcd *usb_hcd; - usb_hcd = container_of(usb_dev->bus, struct usb_hcd, self); + usb_hcd = bus_to_hcd(usb_dev->bus); return usb_get_hcd(usb_hcd); } -- cgit From 20db5513b4085d4beb78e7129cf7e56fe4ddafde Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 21:26:52 +0800 Subject: USB: host: use to_platform_device Use to_platform_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-platform.c | 6 ++---- drivers/usb/host/ehci-st.c | 6 ++---- drivers/usb/host/ohci-platform.c | 6 ++---- drivers/usb/host/ohci-st.c | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index bd7082f297bb..1757ebb471b6 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -345,8 +345,7 @@ static int ehci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -364,8 +363,7 @@ static int ehci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); if (pdata->power_on) { diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c index b7c5cfa37a83..a94ed677d937 100644 --- a/drivers/usb/host/ehci-st.c +++ b/drivers/usb/host/ehci-st.c @@ -287,8 +287,7 @@ static int st_ehci_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -308,8 +307,7 @@ static int st_ehci_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ehci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); int err; pinctrl_pm_select_default_state(dev); diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index c2669f185f65..ae1c988da146 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -310,8 +310,7 @@ static int ohci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev->platform_data; - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -329,8 +328,7 @@ static int ohci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); if (pdata->power_on) { int err = pdata->power_on(pdev); diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c index df9028e0d9b4..acf2eb2a5676 100644 --- a/drivers/usb/host/ohci-st.c +++ b/drivers/usb/host/ohci-st.c @@ -270,8 +270,7 @@ static int st_ohci_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev->platform_data; - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); int ret; @@ -289,8 +288,7 @@ static int st_ohci_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct usb_ohci_pdata *pdata = dev_get_platdata(dev); - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); int err; if (pdata->power_on) { -- cgit From f74a039c7e0bf6b7ed71b10dddfdafcf1e87e5ae Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:28 +0100 Subject: usb-misc: sisusbvga: Fix coding style: horizontal whitespace changes This patch fixes whitespace coding style issues that can be fixed within a single line. This patch fixes the following checkpatch warnings: - 83 ERROR: space required after that ',' - 13 ERROR: switch and case should be at the same indent - 08 WARNING: please, no spaces at the start of a line - 03 ERROR: space required before the open parenthesis '(' - 04 WARNING: suspect code indent for conditional statements - 01 WARNING: space prohibited between function name and open parenthesis - 01 ERROR: spaces required around that '=' - 01 ERROR: code indent should use tabs where possible Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 953 ++++++++++++++++++------------------ 1 file changed, 471 insertions(+), 482 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 8efbabacc84e..616a87d7219b 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -243,7 +243,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, /* Set up context */ sisusb->urbout_context[index].actual_length = (timeout) ? - NULL : actual_length; + NULL : actual_length; /* Declare this urb/buffer in use */ sisusb->urbstatus[index] |= SU_URB_BUSY; @@ -254,8 +254,8 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, /* If OK, and if timeout > 0, wait for completion */ if ((retval == 0) && timeout) { wait_event_timeout(sisusb->wait_q, - (!(sisusb->urbstatus[index] & SU_URB_BUSY)), - timeout); + (!(sisusb->urbstatus[index] & SU_URB_BUSY)), + timeout); if (sisusb->urbstatus[index] & SU_URB_BUSY) { /* URB timed out... kill it and report error */ usb_kill_urb(urb); @@ -375,7 +375,7 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, do { passsize = thispass = (sisusb->obufsize < count) ? - sisusb->obufsize : count; + sisusb->obufsize : count; if (index < 0) index = sisusb_get_free_outbuf(sisusb); @@ -549,7 +549,7 @@ static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, } static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len, - struct sisusb_packet *packet) + struct sisusb_packet *packet) { int ret; ssize_t bytes_transferred = 0; @@ -634,7 +634,7 @@ static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len, */ static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, - u32 addr, u8 data) + u32 addr, u8 data) { struct sisusb_packet packet; int ret; @@ -647,7 +647,7 @@ static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type, } static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type, - u32 addr, u16 data) + u32 addr, u16 data) { struct sisusb_packet packet; int ret = 0; @@ -655,36 +655,36 @@ static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0003; - packet.data = (u32)data; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 1: - packet.header = (type << 6) | 0x0006; - packet.data = (u32)data << 8; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 2: - packet.header = (type << 6) | 0x000c; - packet.data = (u32)data << 16; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 3: - packet.header = (type << 6) | 0x0008; - packet.data = (u32)data << 24; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - packet.data = (u32)data >> 8; - ret |= sisusb_send_packet(sisusb, 10, &packet); + case 0: + packet.header = (type << 6) | 0x0003; + packet.data = (u32)data; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 1: + packet.header = (type << 6) | 0x0006; + packet.data = (u32)data << 8; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 2: + packet.header = (type << 6) | 0x000c; + packet.data = (u32)data << 16; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 3: + packet.header = (type << 6) | 0x0008; + packet.data = (u32)data << 24; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + packet.data = (u32)data >> 8; + ret |= sisusb_send_packet(sisusb, 10, &packet); } return ret; } static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 data) + u32 addr, u32 data) { struct sisusb_packet packet; int ret = 0; @@ -692,40 +692,40 @@ static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0007; - packet.data = data & 0x00ffffff; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 1: - packet.header = (type << 6) | 0x000e; - packet.data = data << 8; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 2: - packet.header = (type << 6) | 0x000c; - packet.data = data << 16; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - packet.data = (data >> 16) & 0x00ff; - ret |= sisusb_send_packet(sisusb, 10, &packet); - break; - case 3: - packet.header = (type << 6) | 0x0008; - packet.data = data << 24; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - packet.data = (data >> 8) & 0xffff; - ret |= sisusb_send_packet(sisusb, 10, &packet); + case 0: + packet.header = (type << 6) | 0x0007; + packet.data = data & 0x00ffffff; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 1: + packet.header = (type << 6) | 0x000e; + packet.data = data << 8; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 2: + packet.header = (type << 6) | 0x000c; + packet.data = data << 16; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + packet.data = (data >> 16) & 0x00ff; + ret |= sisusb_send_packet(sisusb, 10, &packet); + break; + case 3: + packet.header = (type << 6) | 0x0008; + packet.data = data << 24; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + packet.data = (data >> 8) & 0xffff; + ret |= sisusb_send_packet(sisusb, 10, &packet); } return ret; } static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 data) + u32 addr, u32 data) { struct sisusb_packet packet; int ret = 0; @@ -733,37 +733,37 @@ static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x000f; - packet.data = data; - ret = sisusb_send_packet(sisusb, 10, &packet); - break; - case 1: - packet.header = (type << 6) | 0x000e; - packet.data = data << 8; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - packet.data = data >> 24; - ret |= sisusb_send_packet(sisusb, 10, &packet); - break; - case 2: - packet.header = (type << 6) | 0x000c; - packet.data = data << 16; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - packet.data = data >> 16; - ret |= sisusb_send_packet(sisusb, 10, &packet); - break; - case 3: - packet.header = (type << 6) | 0x0008; - packet.data = data << 24; - ret = sisusb_send_packet(sisusb, 10, &packet); - packet.header = (type << 6) | 0x0007; - packet.address = (addr & ~3) + 4; - packet.data = data >> 8; - ret |= sisusb_send_packet(sisusb, 10, &packet); + case 0: + packet.header = (type << 6) | 0x000f; + packet.data = data; + ret = sisusb_send_packet(sisusb, 10, &packet); + break; + case 1: + packet.header = (type << 6) | 0x000e; + packet.data = data << 8; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + packet.data = data >> 24; + ret |= sisusb_send_packet(sisusb, 10, &packet); + break; + case 2: + packet.header = (type << 6) | 0x000c; + packet.data = data << 16; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + packet.data = data >> 16; + ret |= sisusb_send_packet(sisusb, 10, &packet); + break; + case 3: + packet.header = (type << 6) | 0x0008; + packet.data = data << 24; + ret = sisusb_send_packet(sisusb, 10, &packet); + packet.header = (type << 6) | 0x0007; + packet.address = (addr & ~3) + 4; + packet.data = data >> 8; + ret |= sisusb_send_packet(sisusb, 10, &packet); } return ret; @@ -803,9 +803,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, length &= 0x00ffffff; while (length) { - - switch (length) { - + switch (length) { case 1: if (userbuffer) { if (get_user(swap8, (u8 __user *)userbuffer)) @@ -892,88 +890,88 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, default: if ((length & ~3) > 0x10000) { - packet.header = 0x001f; - packet.address = 0x000001d4; - packet.data = addr; - ret = sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - packet.header = 0x001f; - packet.address = 0x000001d0; - packet.data = (length & ~3); - ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - packet.header = 0x001f; - packet.address = 0x000001c0; - packet.data = flag | 0x16; - ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - if (userbuffer) { - ret |= sisusb_send_bulk_msg(sisusb, + packet.header = 0x001f; + packet.address = 0x000001d4; + packet.data = addr; + ret = sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + packet.header = 0x001f; + packet.address = 0x000001d0; + packet.data = (length & ~3); + ret |= sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + packet.header = 0x001f; + packet.address = 0x000001c0; + packet.data = flag | 0x16; + ret |= sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + if (userbuffer) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_LBULK_OUT, (length & ~3), NULL, userbuffer, 0, bytes_written, 0, 1); - userbuffer += (*bytes_written); - } else if (fromkern) { - ret |= sisusb_send_bulk_msg(sisusb, + userbuffer += (*bytes_written); + } else if (fromkern) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_LBULK_OUT, (length & ~3), kernbuffer, NULL, 0, bytes_written, 0, 1); - kernbuffer += (*bytes_written); - } else { - ret |= sisusb_send_bulk_msg(sisusb, + kernbuffer += (*bytes_written); + } else { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_LBULK_OUT, (length & ~3), NULL, NULL, index, bytes_written, 0, 1); - kernbuffer += ((*bytes_written) & - (sisusb->obufsize-1)); - } + kernbuffer += ((*bytes_written) & + (sisusb->obufsize-1)); + } } else { - packet.header = 0x001f; - packet.address = 0x00000194; - packet.data = addr; - ret = sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - packet.header = 0x001f; - packet.address = 0x00000190; - packet.data = (length & ~3); - ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - if (sisusb->flagb0 != 0x16) { packet.header = 0x001f; - packet.address = 0x00000180; - packet.data = flag | 0x16; + packet.address = 0x00000194; + packet.data = addr; + ret = sisusb_send_bridge_packet(sisusb, 10, + &packet, 0); + packet.header = 0x001f; + packet.address = 0x00000190; + packet.data = (length & ~3); ret |= sisusb_send_bridge_packet(sisusb, 10, - &packet, 0); - sisusb->flagb0 = 0x16; - } - if (userbuffer) { - ret |= sisusb_send_bulk_msg(sisusb, + &packet, 0); + if (sisusb->flagb0 != 0x16) { + packet.header = 0x001f; + packet.address = 0x00000180; + packet.data = flag | 0x16; + ret |= sisusb_send_bridge_packet(sisusb, + 10, &packet, 0); + sisusb->flagb0 = 0x16; + } + if (userbuffer) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_OUT, (length & ~3), NULL, userbuffer, 0, bytes_written, 0, 1); - userbuffer += (*bytes_written); - } else if (fromkern) { - ret |= sisusb_send_bulk_msg(sisusb, + userbuffer += (*bytes_written); + } else if (fromkern) { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_OUT, (length & ~3), kernbuffer, NULL, 0, bytes_written, 0, 1); - kernbuffer += (*bytes_written); - } else { - ret |= sisusb_send_bulk_msg(sisusb, + kernbuffer += (*bytes_written); + } else { + ret |= sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_OUT, (length & ~3), NULL, NULL, index, bytes_written, 0, 1); - kernbuffer += ((*bytes_written) & - (sisusb->obufsize-1)); - } + kernbuffer += ((*bytes_written) & + (sisusb->obufsize-1)); + } } if (ret) { msgcount++; @@ -985,10 +983,10 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } addr += (*bytes_written); length -= (*bytes_written); - } + } - if (ret) - break; + if (ret) + break; } @@ -1000,7 +998,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, */ static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, - u32 addr, u8 *data) + u32 addr, u8 *data) { struct sisusb_packet packet; int ret; @@ -1014,7 +1012,7 @@ static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type, } static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type, - u32 addr, u16 *data) + u32 addr, u16 *data) { struct sisusb_packet packet; int ret = 0; @@ -1024,36 +1022,36 @@ static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0003; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data); - break; - case 1: - packet.header = (type << 6) | 0x0006; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data >> 8); - break; - case 2: - packet.header = (type << 6) | 0x000c; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data >> 16); - break; - case 3: - packet.header = (type << 6) | 0x0008; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = (u16)(packet.data >> 24); - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (u16)(packet.data << 8); + case 0: + packet.header = (type << 6) | 0x0003; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data); + break; + case 1: + packet.header = (type << 6) | 0x0006; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data >> 8); + break; + case 2: + packet.header = (type << 6) | 0x000c; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data >> 16); + break; + case 3: + packet.header = (type << 6) | 0x0008; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = (u16)(packet.data >> 24); + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (u16)(packet.data << 8); } return ret; } static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 *data) + u32 addr, u32 *data) { struct sisusb_packet packet; int ret = 0; @@ -1061,40 +1059,40 @@ static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x0007; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data & 0x00ffffff; - break; - case 1: - packet.header = (type << 6) | 0x000e; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 8; - break; - case 2: - packet.header = (type << 6) | 0x000c; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 16; - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= ((packet.data & 0xff) << 16); - break; - case 3: - packet.header = (type << 6) | 0x0008; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 24; - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= ((packet.data & 0xffff) << 8); + case 0: + packet.header = (type << 6) | 0x0007; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data & 0x00ffffff; + break; + case 1: + packet.header = (type << 6) | 0x000e; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 8; + break; + case 2: + packet.header = (type << 6) | 0x000c; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 16; + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= ((packet.data & 0xff) << 16); + break; + case 3: + packet.header = (type << 6) | 0x0008; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 24; + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= ((packet.data & 0xffff) << 8); } return ret; } static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, - u32 addr, u32 *data) + u32 addr, u32 *data) { struct sisusb_packet packet; int ret = 0; @@ -1102,37 +1100,37 @@ static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, packet.address = addr & ~3; switch (addr & 3) { - case 0: - packet.header = (type << 6) | 0x000f; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data; - break; - case 1: - packet.header = (type << 6) | 0x000e; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 8; - packet.header = (type << 6) | 0x0001; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (packet.data << 24); - break; - case 2: - packet.header = (type << 6) | 0x000c; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 16; - packet.header = (type << 6) | 0x0003; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (packet.data << 16); - break; - case 3: - packet.header = (type << 6) | 0x0008; - ret = sisusb_send_packet(sisusb, 6, &packet); - *data = packet.data >> 24; - packet.header = (type << 6) | 0x0007; - packet.address = (addr & ~3) + 4; - ret |= sisusb_send_packet(sisusb, 6, &packet); - *data |= (packet.data << 8); + case 0: + packet.header = (type << 6) | 0x000f; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data; + break; + case 1: + packet.header = (type << 6) | 0x000e; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 8; + packet.header = (type << 6) | 0x0001; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (packet.data << 24); + break; + case 2: + packet.header = (type << 6) | 0x000c; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 16; + packet.header = (type << 6) | 0x0003; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (packet.data << 16); + break; + case 3: + packet.header = (type << 6) | 0x0008; + ret = sisusb_send_packet(sisusb, 6, &packet); + *data = packet.data >> 24; + packet.header = (type << 6) | 0x0007; + packet.address = (addr & ~3) + 4; + ret |= sisusb_send_packet(sisusb, 6, &packet); + *data |= (packet.data << 8); } return ret; @@ -1152,13 +1150,10 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, length &= 0x00ffffff; while (length) { - - switch (length) { - + switch (length) { case 1: - ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, - addr, &buf[0]); + addr, &buf[0]); if (!ret) { (*bytes_read)++; if (userbuffer) { @@ -1174,7 +1169,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, case 2: ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, - addr, &swap16); + addr, &swap16); if (!ret) { (*bytes_read) += 2; if (userbuffer) { @@ -1189,7 +1184,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, case 3: ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM, - addr, &swap32); + addr, &swap32); if (!ret) { (*bytes_read) += 3; #ifdef __BIG_ENDIAN @@ -1214,7 +1209,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, default: ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, - addr, &swap32); + addr, &swap32); if (!ret) { (*bytes_read) += 4; if (userbuffer) { @@ -1230,10 +1225,9 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, addr += 4; length -= 4; } - } - - if (ret) - break; + } + if (ret) + break; } return ret; @@ -1350,20 +1344,24 @@ sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb) { - static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; - char destbuffer[10]; - size_t dummy; - int i,j; - - sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); - - for(i = 1; i <= 7; i++) { - dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i); - sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); - for(j = 0; j < i; j++) { - dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]); + static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + char destbuffer[10]; + size_t dummy; + int i, j; + + sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); + + for (i = 1; i <= 7; i++) { + dev_dbg(&sisusb->sisusb_dev->dev, + "sisusb: rwtest %d bytes\n", i); + sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, + i, &dummy); + for (j = 0; j < i; j++) { + dev_dbg(&sisusb->sisusb_dev->dev, + "rwtest read[%d] = %x\n", + j, destbuffer[j]); + } } - } } #endif @@ -1437,17 +1435,17 @@ sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) * a defined mode (640x480@60Hz) */ -#define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) -#define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) -#define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d) -#define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d) -#define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o) -#define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a) -#define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o) -#define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) -#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) -#define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) -#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) +#define GETREG(r, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) +#define SETREG(r, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d) +#define SETIREG(r, i, d) sisusb_setidxreg(sisusb, r, i, d) +#define GETIREG(r, i, d) sisusb_getidxreg(sisusb, r, i, d) +#define SETIREGOR(r, i, o) sisusb_setidxregor(sisusb, r, i, o) +#define SETIREGAND(r, i, a) sisusb_setidxregand(sisusb, r, i, a) +#define SETIREGANDOR(r, i, a, o) sisusb_setidxregandor(sisusb, r, i, a, o) +#define READL(a, d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) +#define WRITEL(a, d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d) +#define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) +#define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) @@ -1526,7 +1524,7 @@ sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab) } if ((t1 != 0x456789ab) || (t0 != 0x01234567)) { *chab = 1; *bw = 64; - ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01); + ret |= SETIREGANDOR(SISSR, 0x14, 0xfc, 0x01); ret |= sisusb_triggersr16(sisusb, ramtype); ret |= WRITEL(ramptr + 0, 0x89abcdef); @@ -1775,18 +1773,18 @@ sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr) for (i = 0; i < modex; i++) { address = sisusb->vrambase + (i * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); address += (modex * (modey-1) * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); } for (i = 0; i < modey; i++) { address = sisusb->vrambase + ((i * modex) * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); address += ((modex - 1) * bpp); ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, - address, 0xf100); + address, 0xf100); } } @@ -1799,23 +1797,23 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) int ret = 0, i, j, modex, modey, bpp, du; u8 sr31, cr63, tmp8; static const char attrdata[] = { - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x01,0x00,0x00,0x00 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x01, 0x00, 0x00, 0x00 }; static const char crtcrdata[] = { - 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e, - 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00, - 0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3, + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xea, 0x8c, 0xdf, 0x28, 0x40, 0xe7, 0x04, 0xa3, 0xff }; static const char grcdata[] = { - 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff }; static const char crtcdata[] = { - 0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e, - 0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05, + 0x5f, 0x4f, 0x4f, 0x83, 0x55, 0x81, 0x0b, 0x3e, + 0xe9, 0x8b, 0xdf, 0xe8, 0x0c, 0x00, 0x00, 0x05, 0x00 }; @@ -2081,12 +2079,12 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); if (iret) { dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n"); - ret |= SETIREG(SISSR,0x14,0x31); + ret |= SETIREG(SISSR, 0x14, 0x31); /* TODO */ } } else { dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n"); - ret |= SETIREG(SISSR,0x14,0x31); + ret |= SETIREG(SISSR, 0x14, 0x31); /* *** TODO *** */ } @@ -2127,7 +2125,7 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) static const char ram_dynamictype[4] = {'D', 'G', 'D', 'G'}; static const int busSDR[4] = {64, 64, 128, 128}; static const int busDDR[4] = {32, 32, 64, 64}; - static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2}; + static const int busDDRA[4] = {64+32, 64+32, (64+32)*2, (64+32)*2}; sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8); sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82); @@ -2366,7 +2364,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) *(tempbufb++) = 0x0700 | bootstring[i++]; ret |= sisusb_copy_memory(sisusb, tempbuf, - sisusb->vrambase, 8192, &written); + sisusb->vrambase, 8192, &written); vfree(tempbuf); @@ -2380,7 +2378,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } if (sisusb->sisusb_cursor_size_from >= 0 && - sisusb->sisusb_cursor_size_to >= 0) { + sisusb->sisusb_cursor_size_to >= 0) { sisusb_setidxreg(sisusb, SISCR, 0x0a, sisusb->sisusb_cursor_size_from); sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, @@ -2392,7 +2390,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } slot = sisusb->sisusb_cursor_loc; - if(slot < 0) slot = 0; + if (slot < 0) slot = 0; sisusb->sisusb_cursor_loc = -1; sisusb->bad_cursor_pos = 1; @@ -2444,7 +2442,7 @@ sisusb_open(struct inode *inode, struct file *file) if (!sisusb->devinit) { if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH || - sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { + sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); @@ -2539,7 +2537,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) } if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && - (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { + (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + @@ -2551,45 +2549,44 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) * in machine-endianness. */ switch (count) { + case 1: + if (sisusb_read_memio_byte(sisusb, + SISUSB_TYPE_IO, + address, &buf8)) + errno = -EIO; + else if (put_user(buf8, (u8 __user *)buffer)) + errno = -EFAULT; + else + bytes_read = 1; - case 1: - if (sisusb_read_memio_byte(sisusb, - SISUSB_TYPE_IO, - address, &buf8)) - errno = -EIO; - else if (put_user(buf8, (u8 __user *)buffer)) - errno = -EFAULT; - else - bytes_read = 1; - - break; + break; - case 2: - if (sisusb_read_memio_word(sisusb, - SISUSB_TYPE_IO, - address, &buf16)) - errno = -EIO; - else if (put_user(buf16, (u16 __user *)buffer)) - errno = -EFAULT; - else - bytes_read = 2; + case 2: + if (sisusb_read_memio_word(sisusb, + SISUSB_TYPE_IO, + address, &buf16)) + errno = -EIO; + else if (put_user(buf16, (u16 __user *)buffer)) + errno = -EFAULT; + else + bytes_read = 2; - break; + break; - case 4: - if (sisusb_read_memio_long(sisusb, - SISUSB_TYPE_IO, - address, &buf32)) - errno = -EIO; - else if (put_user(buf32, (u32 __user *)buffer)) - errno = -EFAULT; - else - bytes_read = 4; + case 4: + if (sisusb_read_memio_long(sisusb, + SISUSB_TYPE_IO, + address, &buf32)) + errno = -EIO; + else if (put_user(buf32, (u32 __user *)buffer)) + errno = -EFAULT; + else + bytes_read = 4; - break; + break; - default: - errno = -EIO; + default: + errno = -EIO; } @@ -2604,7 +2601,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) * Remember: Data delivered is never endian-corrected */ errno = sisusb_read_mem_bulk(sisusb, address, - NULL, count, buffer, &bytes_read); + NULL, count, buffer, &bytes_read); if (bytes_read) errno = bytes_read; @@ -2620,13 +2617,13 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) * Remember: Data delivered is never endian-corrected */ errno = sisusb_read_mem_bulk(sisusb, address, - NULL, count, buffer, &bytes_read); + NULL, count, buffer, &bytes_read); if (bytes_read) errno = bytes_read; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && - (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { + (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { if (count != 4) { mutex_unlock(&sisusb->lock); @@ -2682,7 +2679,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, } if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && - (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { + (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + @@ -2694,45 +2691,44 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, * in machine-endianness. */ switch (count) { + case 1: + if (get_user(buf8, (u8 __user *)buffer)) + errno = -EFAULT; + else if (sisusb_write_memio_byte(sisusb, + SISUSB_TYPE_IO, + address, buf8)) + errno = -EIO; + else + bytes_written = 1; - case 1: - if (get_user(buf8, (u8 __user *)buffer)) - errno = -EFAULT; - else if (sisusb_write_memio_byte(sisusb, - SISUSB_TYPE_IO, - address, buf8)) - errno = -EIO; - else - bytes_written = 1; - - break; + break; - case 2: - if (get_user(buf16, (u16 __user *)buffer)) - errno = -EFAULT; - else if (sisusb_write_memio_word(sisusb, - SISUSB_TYPE_IO, - address, buf16)) - errno = -EIO; - else - bytes_written = 2; + case 2: + if (get_user(buf16, (u16 __user *)buffer)) + errno = -EFAULT; + else if (sisusb_write_memio_word(sisusb, + SISUSB_TYPE_IO, + address, buf16)) + errno = -EIO; + else + bytes_written = 2; - break; + break; - case 4: - if (get_user(buf32, (u32 __user *)buffer)) - errno = -EFAULT; - else if (sisusb_write_memio_long(sisusb, - SISUSB_TYPE_IO, - address, buf32)) - errno = -EIO; - else - bytes_written = 4; + case 4: + if (get_user(buf32, (u32 __user *)buffer)) + errno = -EFAULT; + else if (sisusb_write_memio_long(sisusb, + SISUSB_TYPE_IO, + address, buf32)) + errno = -EIO; + else + bytes_written = 4; - break; + break; - default: - errno = -EIO; + default: + errno = -EIO; } } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && @@ -2749,7 +2745,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, * mode or if YUV data is being transferred). */ errno = sisusb_write_mem_bulk(sisusb, address, NULL, - count, buffer, 0, &bytes_written); + count, buffer, 0, &bytes_written); if (bytes_written) errno = bytes_written; @@ -2767,7 +2763,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, * in advance. */ errno = sisusb_write_mem_bulk(sisusb, address, NULL, - count, buffer, 0, &bytes_written); + count, buffer, 0, &bytes_written); if (bytes_written) errno = bytes_written; @@ -2849,105 +2845,99 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, SISUSB_PCI_IOPORTBASE; switch (y->operation) { - case SUCMD_GET: - retval = sisusb_getidxreg(sisusb, port, - y->data0, &y->data1); - if (!retval) { - if (copy_to_user((void __user *)arg, y, - sizeof(*y))) - retval = -EFAULT; - } - break; + case SUCMD_GET: + retval = sisusb_getidxreg(sisusb, port, y->data0, &y->data1); + if (!retval) { + if (copy_to_user((void __user *)arg, y, sizeof(*y))) + retval = -EFAULT; + } + break; - case SUCMD_SET: - retval = sisusb_setidxreg(sisusb, port, - y->data0, y->data1); - break; + case SUCMD_SET: + retval = sisusb_setidxreg(sisusb, port, y->data0, y->data1); + break; - case SUCMD_SETOR: - retval = sisusb_setidxregor(sisusb, port, - y->data0, y->data1); - break; + case SUCMD_SETOR: + retval = sisusb_setidxregor(sisusb, port, y->data0, y->data1); + break; - case SUCMD_SETAND: - retval = sisusb_setidxregand(sisusb, port, - y->data0, y->data1); - break; + case SUCMD_SETAND: + retval = sisusb_setidxregand(sisusb, port, y->data0, y->data1); + break; - case SUCMD_SETANDOR: - retval = sisusb_setidxregandor(sisusb, port, - y->data0, y->data1, y->data2); - break; + case SUCMD_SETANDOR: + retval = sisusb_setidxregandor(sisusb, port, y->data0, + y->data1, y->data2); + break; - case SUCMD_SETMASK: - retval = sisusb_setidxregmask(sisusb, port, - y->data0, y->data1, y->data2); - break; + case SUCMD_SETMASK: + retval = sisusb_setidxregmask(sisusb, port, y->data0, + y->data1, y->data2); + break; - case SUCMD_CLRSCR: - /* Gfx core must be initialized */ - if (!sisusb->gfxinit) - return -ENODEV; + case SUCMD_CLRSCR: + /* Gfx core must be initialized */ + if (!sisusb->gfxinit) + return -ENODEV; - length = (y->data0 << 16) | (y->data1 << 8) | y->data2; - address = y->data3 - - SISUSB_PCI_PSEUDO_MEMBASE + + length = (y->data0 << 16) | (y->data1 << 8) | y->data2; + address = y->data3 - SISUSB_PCI_PSEUDO_MEMBASE + SISUSB_PCI_MEMBASE; - retval = sisusb_clear_vram(sisusb, address, length); - break; + retval = sisusb_clear_vram(sisusb, address, length); + break; - case SUCMD_HANDLETEXTMODE: - retval = 0; + case SUCMD_HANDLETEXTMODE: + retval = 0; #ifdef INCL_SISUSB_CON - /* Gfx core must be initialized, SiS_Pr must exist */ - if (!sisusb->gfxinit || !sisusb->SiS_Pr) - return -ENODEV; + /* Gfx core must be initialized, SiS_Pr must exist */ + if (!sisusb->gfxinit || !sisusb->SiS_Pr) + return -ENODEV; - switch (y->data0) { - case 0: - retval = sisusb_reset_text_mode(sisusb, 0); - break; - case 1: - sisusb->textmodedestroyed = 1; - break; - } -#endif + switch (y->data0) { + case 0: + retval = sisusb_reset_text_mode(sisusb, 0); + break; + case 1: + sisusb->textmodedestroyed = 1; break; + } +#endif + break; #ifdef INCL_SISUSB_CON - case SUCMD_SETMODE: - /* Gfx core must be initialized, SiS_Pr must exist */ - if (!sisusb->gfxinit || !sisusb->SiS_Pr) - return -ENODEV; + case SUCMD_SETMODE: + /* Gfx core must be initialized, SiS_Pr must exist */ + if (!sisusb->gfxinit || !sisusb->SiS_Pr) + return -ENODEV; - retval = 0; + retval = 0; - sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; - sisusb->SiS_Pr->sisusb = (void *)sisusb; + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; + sisusb->SiS_Pr->sisusb = (void *)sisusb; - if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3)) - retval = -EINVAL; + if (SiSUSBSetMode(sisusb->SiS_Pr, y->data3)) + retval = -EINVAL; - break; + break; - case SUCMD_SETVESAMODE: - /* Gfx core must be initialized, SiS_Pr must exist */ - if (!sisusb->gfxinit || !sisusb->SiS_Pr) - return -ENODEV; + case SUCMD_SETVESAMODE: + /* Gfx core must be initialized, SiS_Pr must exist */ + if (!sisusb->gfxinit || !sisusb->SiS_Pr) + return -ENODEV; - retval = 0; + retval = 0; - sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; - sisusb->SiS_Pr->sisusb = (void *)sisusb; + sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; + sisusb->SiS_Pr->sisusb = (void *)sisusb; - if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3)) - retval = -EINVAL; + if (SiSUSBSetVESAMode(sisusb->SiS_Pr, y->data3)) + retval = -EINVAL; - break; + break; #endif - default: - retval = -EINVAL; + default: + retval = -EINVAL; } if (retval > 0) @@ -2978,52 +2968,51 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } switch (cmd) { + case SISUSB_GET_CONFIG_SIZE: - case SISUSB_GET_CONFIG_SIZE: + if (put_user(sizeof(x), argp)) + retval = -EFAULT; - if (put_user(sizeof(x), argp)) - retval = -EFAULT; - - break; + break; - case SISUSB_GET_CONFIG: - - x.sisusb_id = SISUSB_ID; - x.sisusb_version = SISUSB_VERSION; - x.sisusb_revision = SISUSB_REVISION; - x.sisusb_patchlevel = SISUSB_PATCHLEVEL; - x.sisusb_gfxinit = sisusb->gfxinit; - x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE; - x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE; - x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE; - x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE; - x.sisusb_vramsize = sisusb->vramsize; - x.sisusb_minor = sisusb->minor; - x.sisusb_fbdevactive= 0; + case SISUSB_GET_CONFIG: + + x.sisusb_id = SISUSB_ID; + x.sisusb_version = SISUSB_VERSION; + x.sisusb_revision = SISUSB_REVISION; + x.sisusb_patchlevel = SISUSB_PATCHLEVEL; + x.sisusb_gfxinit = sisusb->gfxinit; + x.sisusb_vrambase = SISUSB_PCI_PSEUDO_MEMBASE; + x.sisusb_mmiobase = SISUSB_PCI_PSEUDO_MMIOBASE; + x.sisusb_iobase = SISUSB_PCI_PSEUDO_IOPORTBASE; + x.sisusb_pcibase = SISUSB_PCI_PSEUDO_PCIBASE; + x.sisusb_vramsize = sisusb->vramsize; + x.sisusb_minor = sisusb->minor; + x.sisusb_fbdevactive = 0; #ifdef INCL_SISUSB_CON - x.sisusb_conactive = sisusb->haveconsole ? 1 : 0; + x.sisusb_conactive = sisusb->haveconsole ? 1 : 0; #else - x.sisusb_conactive = 0; + x.sisusb_conactive = 0; #endif - memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); + memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved)); - if (copy_to_user((void __user *)arg, &x, sizeof(x))) - retval = -EFAULT; + if (copy_to_user((void __user *)arg, &x, sizeof(x))) + retval = -EFAULT; - break; + break; - case SISUSB_COMMAND: + case SISUSB_COMMAND: - if (copy_from_user(&y, (void __user *)arg, sizeof(y))) - retval = -EFAULT; - else - retval = sisusb_handle_command(sisusb, &y, arg); + if (copy_from_user(&y, (void __user *)arg, sizeof(y))) + retval = -EFAULT; + else + retval = sisusb_handle_command(sisusb, &y, arg); - break; + break; - default: - retval = -ENOTTY; - break; + default: + retval = -ENOTTY; + break; } err_out: @@ -3038,14 +3027,14 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) long retval; switch (cmd) { - case SISUSB_GET_CONFIG_SIZE: - case SISUSB_GET_CONFIG: - case SISUSB_COMMAND: - retval = sisusb_ioctl(f, cmd, arg); - return retval; + case SISUSB_GET_CONFIG_SIZE: + case SISUSB_GET_CONFIG: + case SISUSB_COMMAND: + retval = sisusb_ioctl(f, cmd, arg); + return retval; - default: - return -ENOIOCTLCMD; + default: + return -ENOIOCTLCMD; } } #endif @@ -3070,14 +3059,14 @@ static struct usb_class_driver usb_sisusb_class = { }; static int sisusb_probe(struct usb_interface *intf, - const struct usb_device_id *id) + const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct sisusb_usb_data *sisusb; int retval = 0, i; dev_info(&dev->dev, "USB2VGA dongle found at address %d\n", - dev->devnum); + dev->devnum); /* Allocate memory for our private */ sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL); @@ -3254,7 +3243,7 @@ static const struct usb_device_id sisusb_table[] = { { } }; -MODULE_DEVICE_TABLE (usb, sisusb_table); +MODULE_DEVICE_TABLE(usb, sisusb_table); static struct usb_driver sisusb_driver = { .name = "sisusb", -- cgit From 06e21efa2d344b5e29bf680e623fa76dbcb62580 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:29 +0100 Subject: usb-misc: sisusbvga: Fix coding style: vertical whitespace changes This patch fixes whitespace coding style issues that can't be fixed without adding newlines. This patch fixes the following checkpatch warnings: - 20 ERROR: trailing statements should be on next line - 15 WARNING: line over 80 characters - 03 WARNING: Missing a blank line after declarations - 01 ERROR: space required after that ',' Five lines over 80 characters are left. The first three wont change as the fix would require split the cast and variable name in different lines which makes the code less readable. The last two will be fixed by other patch in the series. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 494 +++++++++++++++++------------------- 1 file changed, 236 insertions(+), 258 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 616a87d7219b..ea0e1ad5d4bc 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -71,8 +71,7 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES static struct usb_driver sisusb_driver; -static void -sisusb_free_buffers(struct sisusb_usb_data *sisusb) +static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) { int i; @@ -88,8 +87,7 @@ sisusb_free_buffers(struct sisusb_usb_data *sisusb) } } -static void -sisusb_free_urbs(struct sisusb_usb_data *sisusb) +static void sisusb_free_urbs(struct sisusb_usb_data *sisusb) { int i; @@ -108,8 +106,7 @@ sisusb_free_urbs(struct sisusb_usb_data *sisusb) /* out-urb management */ /* Return 1 if all free, 0 otherwise */ -static int -sisusb_all_free(struct sisusb_usb_data *sisusb) +static int sisusb_all_free(struct sisusb_usb_data *sisusb) { int i; @@ -124,8 +121,7 @@ sisusb_all_free(struct sisusb_usb_data *sisusb) } /* Kill all busy URBs */ -static void -sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) +static void sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) { int i; @@ -141,20 +137,17 @@ sisusb_kill_all_busy(struct sisusb_usb_data *sisusb) } /* Return 1 if ok, 0 if error (not all complete within timeout) */ -static int -sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb) +static int sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb) { int timeout = 5 * HZ, i = 1; - wait_event_timeout(sisusb->wait_q, - (i = sisusb_all_free(sisusb)), - timeout); + wait_event_timeout(sisusb->wait_q, (i = sisusb_all_free(sisusb)), + timeout); return i; } -static int -sisusb_outurb_available(struct sisusb_usb_data *sisusb) +static int sisusb_outurb_available(struct sisusb_usb_data *sisusb) { int i; @@ -168,20 +161,17 @@ sisusb_outurb_available(struct sisusb_usb_data *sisusb) return -1; } -static int -sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb) +static int sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb) { int i, timeout = 5 * HZ; wait_event_timeout(sisusb->wait_q, - ((i = sisusb_outurb_available(sisusb)) >= 0), - timeout); + ((i = sisusb_outurb_available(sisusb)) >= 0), timeout); return i; } -static int -sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) +static int sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) { int i; @@ -193,8 +183,7 @@ sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb) return i; } -static void -sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) +static void sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) { if ((index >= 0) && (index < sisusb->numobufs)) sisusb->urbstatus[index] &= ~SU_URB_ALLOC; @@ -202,8 +191,7 @@ sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index) /* completion callback */ -static void -sisusb_bulk_completeout(struct urb *urb) +static void sisusb_bulk_completeout(struct urb *urb) { struct sisusb_urb_context *context = urb->context; struct sisusb_usb_data *sisusb; @@ -225,9 +213,9 @@ sisusb_bulk_completeout(struct urb *urb) wake_up(&sisusb->wait_q); } -static int -sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data, - int len, int *actual_length, int timeout, unsigned int tflags) +static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, + unsigned int pipe, void *data, int len, int *actual_length, + int timeout, unsigned int tflags) { struct urb *urb = sisusb->sisurbout[index]; int retval, byteswritten = 0; @@ -236,7 +224,8 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, urb->transfer_flags = 0; usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len, - sisusb_bulk_completeout, &sisusb->urbout_context[index]); + sisusb_bulk_completeout, + &sisusb->urbout_context[index]); urb->transfer_flags |= tflags; urb->actual_length = 0; @@ -277,8 +266,7 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, /* completion callback */ -static void -sisusb_bulk_completein(struct urb *urb) +static void sisusb_bulk_completein(struct urb *urb) { struct sisusb_usb_data *sisusb = urb->context; @@ -289,9 +277,9 @@ sisusb_bulk_completein(struct urb *urb) wake_up(&sisusb->wait_q); } -static int -sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, - int len, int *actual_length, int timeout, unsigned int tflags) +static int sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, + unsigned int pipe, void *data, int len, + int *actual_length, int timeout, unsigned int tflags) { struct urb *urb = sisusb->sisurbin; int retval, readbytes = 0; @@ -405,14 +393,9 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, if (!sisusb->sisusb_dev) return -ENODEV; - result = sisusb_bulkout_msg(sisusb, - index, - pipe, - buffer, - thispass, - &transferred_len, - async ? 0 : 5 * HZ, - tflags); + result = sisusb_bulkout_msg(sisusb, index, pipe, + buffer, thispass, &transferred_len, + async ? 0 : 5 * HZ, tflags); if (result == -ETIMEDOUT) { @@ -500,13 +483,8 @@ static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, thispass = (bufsize < count) ? bufsize : count; - result = sisusb_bulkin_msg(sisusb, - pipe, - buffer, - thispass, - &transferred_len, - 5 * HZ, - tflags); + result = sisusb_bulkin_msg(sisusb, pipe, buffer, thispass, + &transferred_len, 5 * HZ, tflags); if (transferred_len) thispass = transferred_len; @@ -585,8 +563,7 @@ static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len, } static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len, - struct sisusb_packet *packet, - unsigned int tflags) + struct sisusb_packet *packet, unsigned int tflags) { int ret; ssize_t bytes_transferred = 0; @@ -780,9 +757,8 @@ static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type, */ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, - char *kernbuffer, int length, - const char __user *userbuffer, int index, - ssize_t *bytes_written) + char *kernbuffer, int length, const char __user *userbuffer, + int index, ssize_t *bytes_written) { struct sisusb_packet packet; int ret = 0; @@ -811,9 +787,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } else swap8 = kernbuffer[0]; - ret = sisusb_write_memio_byte(sisusb, - SISUSB_TYPE_MEM, - addr, swap8); + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, + addr, swap8); if (!ret) (*bytes_written)++; @@ -827,10 +802,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } else swap16 = *((u16 *)kernbuffer); - ret = sisusb_write_memio_word(sisusb, - SISUSB_TYPE_MEM, - addr, - swap16); + ret = sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, + addr, swap16); if (!ret) (*bytes_written) += 2; @@ -861,10 +834,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, kernbuffer[0]; #endif - ret = sisusb_write_memio_24bit(sisusb, - SISUSB_TYPE_MEM, - addr, - swap32); + ret = sisusb_write_memio_24bit(sisusb, SISUSB_TYPE_MEM, + addr, swap32); if (!ret) (*bytes_written) += 3; @@ -878,10 +849,8 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, } else swap32 = *((u32 *)kernbuffer); - ret = sisusb_write_memio_long(sisusb, - SISUSB_TYPE_MEM, - addr, - swap32); + ret = sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, + addr, swap32); if (!ret) (*bytes_written) += 4; @@ -976,10 +945,13 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (ret) { msgcount++; if (msgcount < 500) - dev_err(&sisusb->sisusb_dev->dev, "Wrote %zd of %d bytes, error %d\n", - *bytes_written, length, ret); + dev_err(&sisusb->sisusb_dev->dev, + "Wrote %zd of %d bytes, error %d\n", + *bytes_written, length, + ret); else if (msgcount == 500) - dev_err(&sisusb->sisusb_dev->dev, "Too many errors, logging stopped\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Too many errors, logging stopped\n"); } addr += (*bytes_written); length -= (*bytes_written); @@ -1137,8 +1109,8 @@ static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, } static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, - char *kernbuffer, int length, - char __user *userbuffer, ssize_t *bytes_read) + char *kernbuffer, int length, char __user *userbuffer, + ssize_t *bytes_read) { int ret = 0; char buf[4]; @@ -1157,8 +1129,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read)++; if (userbuffer) { - if (put_user(buf[0], - (u8 __user *)userbuffer)) { + if (put_user(buf[0], (u8 __user *)userbuffer)) { return -EFAULT; } } else { @@ -1173,8 +1144,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read) += 2; if (userbuffer) { - if (put_user(swap16, - (u16 __user *)userbuffer)) + if (put_user(swap16, (u16 __user *)userbuffer)) return -EFAULT; } else { *((u16 *)kernbuffer) = swap16; @@ -1197,7 +1167,8 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, buf[0] = swap32 & 0xff; #endif if (userbuffer) { - if (copy_to_user(userbuffer, &buf[0], 3)) + if (copy_to_user(userbuffer, + &buf[0], 3)) return -EFAULT; } else { kernbuffer[0] = buf[0]; @@ -1213,8 +1184,7 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read) += 4; if (userbuffer) { - if (put_user(swap32, - (u32 __user *)userbuffer)) + if (put_user(swap32, (u32 __user *)userbuffer)) return -EFAULT; userbuffer += 4; @@ -1236,40 +1206,39 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, /* High level: Gfx (indexed) register access */ #ifdef INCL_SISUSB_CON -int -sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data) +int sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data) { return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data); } -int -sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) +int sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data) { return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data); } #endif -int -sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data) +int sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, + u8 index, u8 data) { int ret; + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); return ret; } -int -sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data) +int sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, + u8 index, u8 *data) { int ret; + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); return ret; } -int -sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, - u8 myand, u8 myor) +int sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, + u8 myand, u8 myor) { int ret; u8 tmp; @@ -1282,12 +1251,12 @@ sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, return ret; } -static int -sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, - u8 data, u8 mask) +static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb, + int port, u8 idx, u8 data, u8 mask) { int ret; u8 tmp; + ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp); tmp &= ~(mask); @@ -1296,14 +1265,14 @@ sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, return ret; } -int -sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) +int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, + u8 index, u8 myor) { return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); } -int -sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) +int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, + u8 idx, u8 myand) { return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); } @@ -1311,38 +1280,35 @@ sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) /* Write/read video ram */ #ifdef INCL_SISUSB_CON -int -sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) +int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) { return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); } -int -sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) +int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) { return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); } -int -sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, - u32 dest, int length, size_t *bytes_written) +int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, + u32 dest, int length, size_t *bytes_written) { - return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written)); + return(sisusb_write_mem_bulk(sisusb, dest, src, length, + NULL, 0, bytes_written)); } #ifdef SISUSBENDIANTEST -int -sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, - u32 src, int length, size_t *bytes_written) +int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, + u32 src, int length, size_t *bytes_written) { - return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written)); + return(sisusb_read_mem_bulk(sisusb, src, dest, length, + NULL, bytes_written)); } #endif #endif #ifdef SISUSBENDIANTEST -static void -sisusb_testreadwrite(struct sisusb_usb_data *sisusb) +static void sisusb_testreadwrite(struct sisusb_usb_data *sisusb) { static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; char destbuffer[10]; @@ -1367,8 +1333,8 @@ sisusb_testreadwrite(struct sisusb_usb_data *sisusb) /* access pci config registers (reg numbers 0, 4, 8, etc) */ -static int -sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data) +static int sisusb_write_pci_config(struct sisusb_usb_data *sisusb, + int regnum, u32 data) { struct sisusb_packet packet; int ret; @@ -1380,8 +1346,8 @@ sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data) return ret; } -static int -sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data) +static int sisusb_read_pci_config(struct sisusb_usb_data *sisusb, + int regnum, u32 *data) { struct sisusb_packet packet; int ret; @@ -1395,8 +1361,8 @@ sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data) /* Clear video RAM */ -static int -sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) +static int sisusb_clear_vram(struct sisusb_usb_data *sisusb, + u32 address, int length) { int ret, i; ssize_t j; @@ -1447,8 +1413,7 @@ sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length) #define READB(a, d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) #define WRITEB(a, d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d) -static int -sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) +static int sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) { int ret; u8 tmp8; @@ -1478,8 +1443,8 @@ sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype) return ret; } -static int -sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab) +static int sisusb_getbuswidth(struct sisusb_usb_data *sisusb, + int *bw, int *chab) { int ret; u8 ramtype, done = 0; @@ -1591,8 +1556,7 @@ sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab) return ret; } -static int -sisusb_verify_mclk(struct sisusb_usb_data *sisusb) +static int sisusb_verify_mclk(struct sisusb_usb_data *sisusb) { int ret = 0; u32 ramptr = SISUSB_PCI_MEMBASE; @@ -1620,10 +1584,8 @@ sisusb_verify_mclk(struct sisusb_usb_data *sisusb) return ret; } -static int -sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index, - u8 rankno, u8 chab, const u8 dramtype[][5], - int bw) +static int sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, + int index, u8 rankno, u8 chab, const u8 dramtype[][5], int bw) { int ret = 0, ranksize; u8 tmp; @@ -1639,7 +1601,9 @@ sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index, return ret; tmp = 0; - while ((ranksize >>= 1) > 0) tmp += 0x10; + while ((ranksize >>= 1) > 0) + tmp += 0x10; + tmp |= ((rankno - 1) << 2); tmp |= ((bw / 64) & 0x02); tmp |= (chab & 0x01); @@ -1652,8 +1616,8 @@ sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index, return ret; } -static int -sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn) +static int sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, + u32 inc, int testn) { int ret = 0, i; u32 j, tmp; @@ -1667,7 +1631,9 @@ sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn) for (i = 0, j = 0; i < testn; i++) { ret |= READL(sisusb->vrambase + j, &tmp); - if (tmp != j) return ret; + if (tmp != j) + return ret; + j += inc; } @@ -1675,9 +1641,8 @@ sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn) return ret; } -static int -sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno, - int idx, int bw, const u8 rtype[][5]) +static int sisusb_check_ranks(struct sisusb_usb_data *sisusb, + int *iret, int rankno, int idx, int bw, const u8 rtype[][5]) { int ret = 0, i, i2ret; u32 inc; @@ -1685,10 +1650,8 @@ sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno, *iret = 0; for (i = rankno; i >= 1; i--) { - inc = 1 << (rtype[idx][2] + - rtype[idx][1] + - rtype[idx][0] + - bw / 64 + i); + inc = 1 << (rtype[idx][2] + rtype[idx][1] + rtype[idx][0] + + bw / 64 + i); ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2); if (!i2ret) return ret; @@ -1708,9 +1671,8 @@ sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno, return ret; } -static int -sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw, - int chab) +static int sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, + int bw, int chab) { int ret = 0, i2ret = 0, i, j; static const u8 sdramtype[13][5] = { @@ -1734,13 +1696,13 @@ sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw, for (i = 0; i < 13; i++) { ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]); for (j = 2; j > 0; j--) { - ret |= sisusb_set_rank(sisusb, &i2ret, i, j, - chab, sdramtype, bw); + ret |= sisusb_set_rank(sisusb, &i2ret, i, j, chab, + sdramtype, bw); if (!i2ret) continue; - ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, - bw, sdramtype); + ret |= sisusb_check_ranks(sisusb, &i2ret, j, i, bw, + sdramtype); if (i2ret) { *iret = 0; /* ram size found */ return ret; @@ -1751,8 +1713,8 @@ sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw, return ret; } -static int -sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr) +static int sisusb_setup_screen(struct sisusb_usb_data *sisusb, + int clrall, int drwfr) { int ret = 0; u32 address; @@ -1791,8 +1753,8 @@ sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr) return ret; } -static int -sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) +static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb, + int touchengines) { int ret = 0, i, j, modex, modey, bpp, du; u8 sr31, cr63, tmp8; @@ -1872,12 +1834,16 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5)); SETIREG(SISCR, 0x14, 0x4f); du = (modex / 16) * (bpp * 2); /* offset/pitch */ - if (modex % 16) du += bpp; + if (modex % 16) + du += bpp; + SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f)); SETIREG(SISCR, 0x13, (du & 0xff)); du <<= 5; tmp8 = du >> 8; - if (du & 0xff) tmp8++; + if (du & 0xff) + tmp8++; + SETIREG(SISSR, 0x10, tmp8); SETIREG(SISSR, 0x31, 0x00); /* VCLK */ SETIREG(SISSR, 0x2b, 0x1b); @@ -1923,8 +1889,7 @@ sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines) return ret; } -static int -sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) +static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) { int ret = 0, i, j, bw, chab, iret, retry = 3; u8 tmp8, ramtype; @@ -1968,7 +1933,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= GETREG(SISMISCR, &tmp8); ret |= SETREG(SISMISCW, (tmp8 | 0x01)); - if (ret) continue; + if (ret) + continue; /* Reset registers */ ret |= SETIREGAND(SISCR, 0x5b, 0xdf); @@ -1993,7 +1959,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREG(SISCR, i, 0x00); } - if (ret) continue; + if (ret) + continue; ret |= SETIREG(SISCR, 0x63, 0x80); @@ -2011,13 +1978,16 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREG(SISSR, 0x07, 0x18); ret |= SETIREG(SISSR, 0x11, 0x0f); - if (ret) continue; + if (ret) + continue; for (i = 0x15, j = 0; i <= 0x1b; i++, j++) { - ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]); + ret |= SETIREG(SISSR, i, + ramtypetable1[(j*4) + ramtype]); } for (i = 0x40, j = 0; i <= 0x44; i++, j++) { - ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]); + ret |= SETIREG(SISCR, i, + ramtypetable2[(j*4) + ramtype]); } ret |= SETIREG(SISCR, 0x49, 0xaa); @@ -2034,7 +2004,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREGAND(SISCAP, 0x3f, 0xef); - if (ret) continue; + if (ret) + continue; ret |= SETIREG(SISPART1, 0x00, 0x00); @@ -2056,7 +2027,8 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETIREG(SISSR, 0x32, 0x11); ret |= SETIREG(SISSR, 0x33, 0x00); - if (ret) continue; + if (ret) + continue; ret |= SETIREG(SISCR, 0x83, 0x00); @@ -2078,12 +2050,14 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) if (ramtype <= 1) { ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); if (iret) { - dev_err(&sisusb->sisusb_dev->dev,"RAM size detection failed, assuming 8MB video RAM\n"); + dev_err(&sisusb->sisusb_dev->dev, + "RAM size detection failed, assuming 8MB video RAM\n"); ret |= SETIREG(SISSR, 0x14, 0x31); /* TODO */ } } else { - dev_err(&sisusb->sisusb_dev->dev, "DDR RAM device found, assuming 8MB video RAM\n"); + dev_err(&sisusb->sisusb_dev->dev, + "DDR RAM device found, assuming 8MB video RAM\n"); ret |= SETIREG(SISSR, 0x14, 0x31); /* *** TODO *** */ } @@ -2115,8 +2089,7 @@ sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) #undef READL #undef WRITEL -static void -sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) +static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) { u8 tmp8, tmp82, ramtype; int bw = 0; @@ -2133,35 +2106,38 @@ sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024; ramtype &= 0x03; switch ((tmp8 >> 2) & 0x03) { - case 0: ramtypetext1 = "1 ch/1 r"; + case 0: + ramtypetext1 = "1 ch/1 r"; if (tmp82 & 0x10) { bw = 32; } else { bw = busSDR[(tmp8 & 0x03)]; } break; - case 1: ramtypetext1 = "1 ch/2 r"; + case 1: + ramtypetext1 = "1 ch/2 r"; sisusb->vramsize <<= 1; bw = busSDR[(tmp8 & 0x03)]; break; - case 2: ramtypetext1 = "asymmeric"; + case 2: + ramtypetext1 = "asymmeric"; sisusb->vramsize += sisusb->vramsize/2; bw = busDDRA[(tmp8 & 0x03)]; break; - case 3: ramtypetext1 = "2 channel"; + case 3: + ramtypetext1 = "2 channel"; sisusb->vramsize <<= 1; bw = busDDR[(tmp8 & 0x03)]; break; } - - dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %cDR S%cRAM, bus width %d\n", - sisusb->vramsize >> 20, ramtypetext1, - ram_datarate[ramtype], ram_dynamictype[ramtype], bw); + dev_info(&sisusb->sisusb_dev->dev, + "%dMB %s %cDR S%cRAM, bus width %d\n", + sisusb->vramsize >> 20, ramtypetext1, + ram_datarate[ramtype], ram_dynamictype[ramtype], bw); } -static int -sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) +static int sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) { struct sisusb_packet packet; int ret; @@ -2239,8 +2215,7 @@ sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb) * of the graphics board. */ -static int -sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) +static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) { int ret = 0, test = 0; u32 tmp32; @@ -2248,16 +2223,25 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) if (sisusb->devinit == 1) { /* Read PCI BARs and see if they have been set up */ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); - if (ret) return ret; - if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++; + if (ret) + return ret; + + if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) + test++; ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); - if (ret) return ret; - if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++; + if (ret) + return ret; + + if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) + test++; ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); - if (ret) return ret; - if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++; + if (ret) + return ret; + + if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) + test++; } /* No? So reset the device */ @@ -2292,15 +2276,15 @@ sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) - Upload user font (if available) */ -int -sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) +int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) { int ret = 0, slot = sisusb->font_slot, i; const struct font_desc *myfont; u8 *tempbuf; u16 *tempbufb; size_t written; - static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; + static const char bootstring[] = + "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; static const char bootlogo[] = "(o_ //\\ V_/_"; /* sisusb->lock is down */ @@ -2326,7 +2310,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16); /* Upload default font */ - ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0); + ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, + 0, 1, NULL, 16, 0); vfree(tempbuf); @@ -2373,7 +2358,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } else if (sisusb->scrbuf) { ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf, - sisusb->vrambase, sisusb->scrbuf_size, &written); + sisusb->vrambase, sisusb->scrbuf_size, + &written); } @@ -2390,7 +2376,8 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) } slot = sisusb->sisusb_cursor_loc; - if (slot < 0) slot = 0; + if (slot < 0) + slot = 0; sisusb->sisusb_cursor_loc = -1; sisusb->bad_cursor_pos = 1; @@ -2411,8 +2398,7 @@ sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) /* fops */ -static int -sisusb_open(struct inode *inode, struct file *file) +static int sisusb_open(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; struct usb_interface *interface; @@ -2445,12 +2431,14 @@ sisusb_open(struct inode *inode, struct file *file) sisusb->sisusb_dev->speed == USB_SPEED_SUPER) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); - dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to initialize device\n"); return -EIO; } } else { mutex_unlock(&sisusb->lock); - dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Device not attached to USB 2.0 hub\n"); return -EIO; } } @@ -2467,8 +2455,7 @@ sisusb_open(struct inode *inode, struct file *file) return 0; } -void -sisusb_delete(struct kref *kref) +void sisusb_delete(struct kref *kref) { struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); @@ -2486,8 +2473,7 @@ sisusb_delete(struct kref *kref) kfree(sisusb); } -static int -sisusb_release(struct inode *inode, struct file *file) +static int sisusb_release(struct inode *inode, struct file *file) { struct sisusb_usb_data *sisusb; @@ -2514,8 +2500,8 @@ sisusb_release(struct inode *inode, struct file *file) return 0; } -static ssize_t -sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) +static ssize_t sisusb_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) { struct sisusb_usb_data *sisusb; ssize_t bytes_read = 0; @@ -2539,9 +2525,8 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_IOPORTBASE + - SISUSB_PCI_IOPORTBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + + SISUSB_PCI_IOPORTBASE; /* Read i/o ports * Byte, word and long(32) can be read. As this @@ -2550,8 +2535,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) */ switch (count) { case 1: - if (sisusb_read_memio_byte(sisusb, - SISUSB_TYPE_IO, + if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, address, &buf8)) errno = -EIO; else if (put_user(buf8, (u8 __user *)buffer)) @@ -2562,8 +2546,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) break; case 2: - if (sisusb_read_memio_word(sisusb, - SISUSB_TYPE_IO, + if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO, address, &buf16)) errno = -EIO; else if (put_user(buf16, (u16 __user *)buffer)) @@ -2574,8 +2557,7 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) break; case 4: - if (sisusb_read_memio_long(sisusb, - SISUSB_TYPE_IO, + if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO, address, &buf32)) errno = -EIO; else if (put_user(buf32, (u32 __user *)buffer)) @@ -2590,12 +2572,11 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) } - } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { + } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) < + SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MEMBASE + - SISUSB_PCI_MEMBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + + SISUSB_PCI_MEMBASE; /* Read video ram * Remember: Data delivered is never endian-corrected @@ -2607,11 +2588,11 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) errno = bytes_read; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { + (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOSIZE) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MMIOBASE + - SISUSB_PCI_MMIOBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOBASE; /* Read MMIO * Remember: Data delivered is never endian-corrected @@ -2655,9 +2636,8 @@ sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) return errno ? errno : bytes_read; } -static ssize_t -sisusb_write(struct file *file, const char __user *buffer, size_t count, - loff_t *ppos) +static ssize_t sisusb_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { struct sisusb_usb_data *sisusb; int errno = 0; @@ -2681,9 +2661,8 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_IOPORTBASE + - SISUSB_PCI_IOPORTBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + + SISUSB_PCI_IOPORTBASE; /* Write i/o ports * Byte, word and long(32) can be written. As this @@ -2695,8 +2674,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (get_user(buf8, (u8 __user *)buffer)) errno = -EFAULT; else if (sisusb_write_memio_byte(sisusb, - SISUSB_TYPE_IO, - address, buf8)) + SISUSB_TYPE_IO, address, buf8)) errno = -EIO; else bytes_written = 1; @@ -2707,8 +2685,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (get_user(buf16, (u16 __user *)buffer)) errno = -EFAULT; else if (sisusb_write_memio_word(sisusb, - SISUSB_TYPE_IO, - address, buf16)) + SISUSB_TYPE_IO, address, buf16)) errno = -EIO; else bytes_written = 2; @@ -2719,8 +2696,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, if (get_user(buf32, (u32 __user *)buffer)) errno = -EFAULT; else if (sisusb_write_memio_long(sisusb, - SISUSB_TYPE_IO, - address, buf32)) + SISUSB_TYPE_IO, address, buf32)) errno = -EIO; else bytes_written = 4; @@ -2732,11 +2708,11 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, } } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { + (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + + sisusb->vramsize) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MEMBASE + - SISUSB_PCI_MEMBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + + SISUSB_PCI_MEMBASE; /* Write video ram. * Buffer is copied 1:1, therefore, on big-endian @@ -2751,11 +2727,11 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, errno = bytes_written; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && - (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { + (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOSIZE) { - address = (*ppos) - - SISUSB_PCI_PSEUDO_MMIOBASE + - SISUSB_PCI_MMIOBASE; + address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + + SISUSB_PCI_MMIOBASE; /* Write MMIO. * Buffer is copied 1:1, therefore, on big-endian @@ -2769,7 +2745,8 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, errno = bytes_written; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && - (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) { + (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + + SISUSB_PCI_PCONFSIZE) { if (count != 4) { mutex_unlock(&sisusb->lock); @@ -2803,8 +2780,7 @@ sisusb_write(struct file *file, const char __user *buffer, size_t count, return errno ? errno : bytes_written; } -static loff_t -sisusb_lseek(struct file *file, loff_t offset, int orig) +static loff_t sisusb_lseek(struct file *file, loff_t offset, int orig) { struct sisusb_usb_data *sisusb; loff_t ret; @@ -2827,9 +2803,8 @@ sisusb_lseek(struct file *file, loff_t offset, int orig) return ret; } -static int -sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, - unsigned long arg) +static int sisusb_handle_command(struct sisusb_usb_data *sisusb, + struct sisusb_command *y, unsigned long arg) { int retval, port, length; u32 address; @@ -2946,8 +2921,7 @@ sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y, return retval; } -static long -sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct sisusb_usb_data *sisusb; struct sisusb_info x; @@ -3021,8 +2995,8 @@ err_out: } #ifdef SISUSB_NEW_CONFIG_COMPAT -static long -sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +static long sisusb_compat_ioctl(struct file *f, unsigned int cmd, + unsigned long arg) { long retval; @@ -3081,8 +3055,9 @@ static int sisusb_probe(struct usb_interface *intf, /* Register device */ retval = usb_register_dev(intf, &usb_sisusb_class); if (retval) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to get a minor for device %d\n", - dev->devnum); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to get a minor for device %d\n", + dev->devnum); retval = -ENODEV; goto error_1; } @@ -3128,7 +3103,8 @@ static int sisusb_probe(struct usb_interface *intf, for (i = 0; i < sisusb->numobufs; i++) { if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to allocate URBs\n"); retval = -ENOMEM; goto error_4; } @@ -3137,7 +3113,8 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->urbstatus[i] = 0; } - dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", sisusb->numobufs); + dev_info(&sisusb->sisusb_dev->dev, "Allocated %d output buffers\n", + sisusb->numobufs); #ifdef INCL_SISUSB_CON /* Allocate our SiS_Pr */ @@ -3159,17 +3136,18 @@ static int sisusb_probe(struct usb_interface *intf, if (dev->speed == USB_SPEED_HIGH || dev->speed == USB_SPEED_SUPER) { int initscreen = 1; #ifdef INCL_SISUSB_CON - if (sisusb_first_vc > 0 && - sisusb_last_vc > 0 && - sisusb_first_vc <= sisusb_last_vc && - sisusb_last_vc <= MAX_NR_CONSOLES) + if (sisusb_first_vc > 0 && sisusb_last_vc > 0 && + sisusb_first_vc <= sisusb_last_vc && + sisusb_last_vc <= MAX_NR_CONSOLES) initscreen = 0; #endif if (sisusb_init_gfxdevice(sisusb, initscreen)) - dev_err(&sisusb->sisusb_dev->dev, "Failed to early initialize device\n"); + dev_err(&sisusb->sisusb_dev->dev, + "Failed to early initialize device\n"); } else - dev_info(&sisusb->sisusb_dev->dev, "Not attached to USB 2.0 hub, deferring init\n"); + dev_info(&sisusb->sisusb_dev->dev, + "Not attached to USB 2.0 hub, deferring init\n"); sisusb->ready = 1; -- cgit From f996c49d4fa4e8e33955eb59691e1b116b3d733b Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:30 +0100 Subject: usb-misc: sisusbvga: Fix coding style: braces, parenthesis, comment The file drivers/usb/misc/sisusbvga/sisusb.c contained coding style issues reported by checkpatch. This patch fixes the following errors: - 12 WARNING: braces {} are not necessary for single statement blocks - 04 ERROR: return is not a function, parentheses are not required - 03 ERROR: do not initialise statics to 0 - 1 WARNING: else is not generally useful after a break or return - 1 WARNING: braces {} are not necessary for any arm of this statement - 1 WARNING: Block comments use * on subsequent lines One case in which braces are not necessary is left unchanged as other patch of the series will fix it. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 88 +++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 47 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index ea0e1ad5d4bc..26925f74cd92 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -61,8 +61,8 @@ /* Forward declarations / clean-up routines */ #ifdef INCL_SISUSB_CON -static int sisusb_first_vc = 0; -static int sisusb_last_vc = 0; +static int sisusb_first_vc; +static int sisusb_last_vc; module_param_named(first, sisusb_first_vc, int, 0); module_param_named(last, sisusb_last_vc, int, 0); MODULE_PARM_DESC(first, "Number of first console to take over (1 - MAX_NR_CONSOLES)"); @@ -762,7 +762,7 @@ static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, { struct sisusb_packet packet; int ret = 0; - static int msgcount = 0; + static int msgcount; u8 swap8, fromkern = kernbuffer ? 1 : 0; u16 swap16; u32 swap32, flag = (length >> 28) & 1; @@ -1129,12 +1129,10 @@ static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, if (!ret) { (*bytes_read)++; if (userbuffer) { - if (put_user(buf[0], (u8 __user *)userbuffer)) { + if (put_user(buf[0], (u8 __user *)userbuffer)) return -EFAULT; - } - } else { + } else kernbuffer[0] = buf[0]; - } } return ret; @@ -1268,13 +1266,13 @@ static int sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor) { - return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor)); + return sisusb_setidxregandor(sisusb, port, index, 0xff, myor); } int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand) { - return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00)); + return sisusb_setidxregandor(sisusb, port, idx, myand, 0x00); } /* Write/read video ram */ @@ -1282,27 +1280,27 @@ int sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, #ifdef INCL_SISUSB_CON int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data) { - return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); + return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data); } int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data) { - return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data)); + return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data); } int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, u32 dest, int length, size_t *bytes_written) { - return(sisusb_write_mem_bulk(sisusb, dest, src, length, - NULL, 0, bytes_written)); + return sisusb_write_mem_bulk(sisusb, dest, src, length, + NULL, 0, bytes_written); } #ifdef SISUSBENDIANTEST int sisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, u32 src, int length, size_t *bytes_written) { - return(sisusb_read_mem_bulk(sisusb, src, dest, length, - NULL, bytes_written)); + return sisusb_read_mem_bulk(sisusb, src, dest, length, + NULL, bytes_written); } #endif #endif @@ -1818,18 +1816,18 @@ static int sisusb_set_default_mode(struct sisusb_usb_data *sisusb, SETIREGAND(SISSR, 0x37, 0xfe); SETREG(SISMISCW, 0xef); /* sync */ SETIREG(SISCR, 0x11, 0x00); /* crtc */ - for (j = 0x00, i = 0; i <= 7; i++, j++) { + for (j = 0x00, i = 0; i <= 7; i++, j++) SETIREG(SISCR, j, crtcdata[i]); - } - for (j = 0x10; i <= 10; i++, j++) { + + for (j = 0x10; i <= 10; i++, j++) SETIREG(SISCR, j, crtcdata[i]); - } - for (j = 0x15; i <= 12; i++, j++) { + + for (j = 0x15; i <= 12; i++, j++) SETIREG(SISCR, j, crtcdata[i]); - } - for (j = 0x0A; i <= 15; i++, j++) { + + for (j = 0x0A; i <= 15; i++, j++) SETIREG(SISSR, j, crtcdata[i]); - } + SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0)); SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5)); SETIREG(SISCR, 0x14, 0x4f); @@ -1943,21 +1941,20 @@ static int sisusb_init_gfxcore(struct sisusb_usb_data *sisusb) ret |= SETREG(SISMISCW, 0x67); - for (i = 0x06; i <= 0x1f; i++) { + for (i = 0x06; i <= 0x1f; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x21; i <= 0x27; i++) { + + for (i = 0x21; i <= 0x27; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x31; i <= 0x3d; i++) { + + for (i = 0x31; i <= 0x3d; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x12; i <= 0x1b; i++) { + + for (i = 0x12; i <= 0x1b; i++) ret |= SETIREG(SISSR, i, 0x00); - } - for (i = 0x79; i <= 0x7c; i++) { + + for (i = 0x79; i <= 0x7c; i++) ret |= SETIREG(SISCR, i, 0x00); - } if (ret) continue; @@ -2108,11 +2105,11 @@ static void sisusb_get_ramconfig(struct sisusb_usb_data *sisusb) switch ((tmp8 >> 2) & 0x03) { case 0: ramtypetext1 = "1 ch/1 r"; - if (tmp82 & 0x10) { + if (tmp82 & 0x10) bw = 32; - } else { + else bw = busSDR[(tmp8 & 0x03)]; - } + break; case 1: ramtypetext1 = "1 ch/2 r"; @@ -2271,10 +2268,10 @@ static int sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen) #ifdef INCL_SISUSB_CON /* Set up default text mode: - - Set text mode (0x03) - - Upload default font - - Upload user font (if available) -*/ + * - Set text mode (0x03) + * - Upload default font + * - Upload user font (if available) + */ int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init) { @@ -2405,14 +2402,12 @@ static int sisusb_open(struct inode *inode, struct file *file) int subminor = iminor(inode); interface = usb_find_interface(&sisusb_driver, subminor); - if (!interface) { + if (!interface) return -ENODEV; - } sisusb = usb_get_intfdata(interface); - if (!sisusb) { + if (!sisusb) return -ENODEV; - } mutex_lock(&sisusb->lock); @@ -3088,9 +3083,8 @@ static int sisusb_probe(struct usb_interface *intf, goto error_3; } break; - } else - sisusb->numobufs++; - + } + sisusb->numobufs++; } /* Allocate URBs */ -- cgit From 662bfe7b537f0c199024b252d451727a76449233 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:31 +0100 Subject: usb-misc: sisusbvga: Fix coding style: remove assignment from if tests The file drivers/usb/misc/sisusbvga/sisusb.c had 6 assignments inside if tests. This patch move the assignment outside the test. The changes also fix the remaining 2 lines that were over 80 characters. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 26925f74cd92..40f360ab406d 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -1378,7 +1378,8 @@ static int sisusb_clear_vram(struct sisusb_usb_data *sisusb, return 0; /* allocate free buffer/urb and clear the buffer */ - if ((i = sisusb_alloc_outbuf(sisusb)) < 0) + i = sisusb_alloc_outbuf(sisusb); + if (i < 0) return -EBUSY; memset(sisusb->obuf[i], 0, sisusb->obufsize); @@ -3067,7 +3068,8 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate buffers */ sisusb->ibufsize = SISUSB_IBUF_SIZE; - if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) { + sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL); + if (!sisusb->ibuf) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); retval = -ENOMEM; goto error_2; @@ -3076,7 +3078,8 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->numobufs = 0; sisusb->obufsize = SISUSB_OBUF_SIZE; for (i = 0; i < NUMOBUFS; i++) { - if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) { + sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL); + if (!sisusb->obuf[i]) { if (i == 0) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); retval = -ENOMEM; @@ -3088,7 +3091,8 @@ static int sisusb_probe(struct usb_interface *intf, } /* Allocate URBs */ - if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) { + sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL); + if (!sisusb->sisurbin) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); retval = -ENOMEM; goto error_3; @@ -3096,7 +3100,8 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->completein = 1; for (i = 0; i < sisusb->numobufs; i++) { - if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) { + sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL); + if (!sisusb->sisurbout[i]) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate URBs\n"); retval = -ENOMEM; @@ -3112,7 +3117,8 @@ static int sisusb_probe(struct usb_interface *intf, #ifdef INCL_SISUSB_CON /* Allocate our SiS_Pr */ - if (!(sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL))) { + sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL); + if (!sisusb->SiS_Pr) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n"); } #endif -- cgit From 8a102fd6c99a26a0aa74e3d4bed4092b3c791361 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:32 +0100 Subject: usb-misc: sisusbvga: Remove null test before calls to kfree() This patch removes null test before calls to kfree() as kfree() can handle null pointers safely. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 40f360ab406d..bea6d88f769a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -76,15 +76,11 @@ static void sisusb_free_buffers(struct sisusb_usb_data *sisusb) int i; for (i = 0; i < NUMOBUFS; i++) { - if (sisusb->obuf[i]) { - kfree(sisusb->obuf[i]); - sisusb->obuf[i] = NULL; - } - } - if (sisusb->ibuf) { - kfree(sisusb->ibuf); - sisusb->ibuf = NULL; + kfree(sisusb->obuf[i]); + sisusb->obuf[i] = NULL; } + kfree(sisusb->ibuf); + sisusb->ibuf = NULL; } static void sisusb_free_urbs(struct sisusb_usb_data *sisusb) -- cgit From f40849b86862c00f24db10bc11fe2e972c029ec4 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:33 +0100 Subject: usb-misc: sisusbvga: Remove memory allocation logs This patch remove three calls to dev_err() from sisusb_probe() as reporting memory allocation failures is redundant: - Remove a call to dev_err() that was reporting unsuccesful call to kzalloc(). - Remove two calls to dev_err() that were reporting unsuccesful calls to kmalloc(). One call to dev_err() reporting memory allocation is left unchanged as the last patch of the series removes it. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index bea6d88f769a..b3713d57ce01 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3036,10 +3036,9 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate memory for our private */ sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL); - if (!sisusb) { - dev_err(&dev->dev, "Failed to allocate memory for private data\n"); + if (!sisusb) return -ENOMEM; - } + kref_init(&sisusb->kref); mutex_init(&(sisusb->lock)); @@ -3066,7 +3065,6 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->ibufsize = SISUSB_IBUF_SIZE; sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL); if (!sisusb->ibuf) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); retval = -ENOMEM; goto error_2; } @@ -3077,7 +3075,6 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL); if (!sisusb->obuf[i]) { if (i == 0) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); retval = -ENOMEM; goto error_3; } -- cgit From 0e781c2258ffb2a42bf44f62dea8662f38cbfd34 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Fri, 15 Jan 2016 18:41:34 +0100 Subject: usb-misc: sisusbvga: fix error path Remove a call to dev_err() that was reporting an unsuccesful call to kmalloc(), as reporting memory allocation failures is redundant. Instead of logging the error, clean up previously allocated resources and abort the probe with -ENOMEM. Before this change sisusb->SiS_Pr could be dereferenced even if null after failure of memory allocation. Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index b3713d57ce01..a22de52cb083 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3112,7 +3112,8 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate our SiS_Pr */ sisusb->SiS_Pr = kmalloc(sizeof(struct SiS_Private), GFP_KERNEL); if (!sisusb->SiS_Pr) { - dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate SiS_Pr\n"); + retval = -ENOMEM; + goto error_4; } #endif -- cgit From a9c9d9aca4e7cf75d09faa098785ed991db41c65 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 6 Jan 2016 23:28:39 +0800 Subject: zorro: Use kobj_to_dev() Use kobj_to_dev() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Geert Uytterhoeven --- drivers/zorro/zorro-sysfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 36b210f9b6b2..9282dbf5abdb 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -65,8 +65,7 @@ static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device, - kobj)); + struct zorro_dev *z = to_zorro_dev(kobj_to_dev(kobj)); struct ConfigDev cd; /* Construct a ConfigDev */ -- cgit From 333a6515344f5dc4ed0772b8fe252a2246f2e099 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 07:29:13 -0200 Subject: Revert "[media] Postpone the addition of MEDIA_IOC_G_TOPOLOGY" Enable MEDIA_IOC_G_TOPOLOGY ioctl for Kernel 4.6. This reverts commit be0270ec89e6b9b49de7e533dd1f3a89ad34d205. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-ioc-g-topology.xml | 3 --- drivers/media/media-device.c | 7 +------ include/uapi/linux/media.h | 6 +----- 3 files changed, 2 insertions(+), 14 deletions(-) diff --git a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml index 63152ab9efba..e0d49fa329f0 100644 --- a/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml +++ b/Documentation/DocBook/media/v4l/media-ioc-g-topology.xml @@ -48,9 +48,6 @@ Description - - NOTE: This new ioctl is programmed to be added on Kernel 4.6. Its definition/arguments may change until its final version. - The typical usage of this ioctl is to call it twice. On the first call, the structure defined at &media-v2-topology; should be zeroed. At return, if no errors happen, this ioctl will return the diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c index 7dae0ac0f3ae..4d1c13de494b 100644 --- a/drivers/media/media-device.c +++ b/drivers/media/media-device.c @@ -234,7 +234,6 @@ static long media_device_setup_link(struct media_device *mdev, return ret; } -#if 0 /* Let's postpone it to Kernel 4.6 */ static long __media_device_get_topology(struct media_device *mdev, struct media_v2_topology *topo) { @@ -390,7 +389,6 @@ static long media_device_get_topology(struct media_device *mdev, return 0; } -#endif static long media_device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -424,14 +422,13 @@ static long media_device_ioctl(struct file *filp, unsigned int cmd, mutex_unlock(&dev->graph_mutex); break; -#if 0 /* Let's postpone it to Kernel 4.6 */ 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; -#endif + default: ret = -ENOIOCTLCMD; } @@ -480,9 +477,7 @@ static long media_device_compat_ioctl(struct file *filp, unsigned int cmd, case MEDIA_IOC_DEVICE_INFO: case MEDIA_IOC_ENUM_ENTITIES: case MEDIA_IOC_SETUP_LINK: -#if 0 /* Let's postpone it to Kernel 4.6 */ case MEDIA_IOC_G_TOPOLOGY: -#endif return media_device_ioctl(filp, cmd, arg); case MEDIA_IOC_ENUM_LINKS32: diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1e3c8cb43bd7..5dbb208e5451 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -286,7 +286,7 @@ struct media_links_enum { * later, before the adding this API upstream. */ -#if 0 /* Let's postpone it to Kernel 4.6 */ + struct media_v2_entity { __u32 id; char name[64]; /* FIXME: move to a property? (RFC says so) */ @@ -351,7 +351,6 @@ static inline void __user *media_get_uptr(__u64 arg) { return (void __user *)(uintptr_t)arg; } -#endif /* ioctls */ @@ -359,9 +358,6 @@ static inline void __user *media_get_uptr(__u64 arg) #define MEDIA_IOC_ENUM_ENTITIES _IOWR('|', 0x01, struct media_entity_desc) #define MEDIA_IOC_ENUM_LINKS _IOWR('|', 0x02, struct media_links_enum) #define MEDIA_IOC_SETUP_LINK _IOWR('|', 0x03, struct media_link_desc) - -#if 0 /* Let's postpone it to Kernel 4.6 */ #define MEDIA_IOC_G_TOPOLOGY _IOWR('|', 0x04, struct media_v2_topology) -#endif #endif /* __LINUX_MEDIA_H */ -- cgit From 6f3508f61c814ee852c199988a62bd954c50dfc1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 20 Jan 2016 12:54:51 +0300 Subject: EDAC, amd64_edac: Shift wrapping issue in f1x_get_norm_dct_addr() dct_sel_base_off is declared as a u64 but we're only using the lower 32 bits because of a shift wrapping bug. This can possibly truncate the upper 16 bits of DctSelBaseOffset[47:26], causing us to misdecode the CS row. Fixes: c8e518d5673d ('amd64_edac: Sanitize f10_get_base_addr_offset') Signed-off-by: Dan Carpenter Cc: Aravind Gopalakrishnan Cc: linux-edac Cc: Link: http://lkml.kernel.org/r/20160120095451.GB19898@mwanda Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 9eee13ef83a5..d87a47547ba5 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range, u64 chan_off; u64 dram_base = get_dram_base(pvt, range); u64 hole_off = f10_dhar_offset(pvt); - u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16; + u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16; if (hi_rng) { /* -- cgit From 5979b84dc1f91fa2866aa8223a802f51f87e5b6a Mon Sep 17 00:00:00 2001 From: Loc Ho Date: Fri, 22 Jan 2016 13:47:03 -0700 Subject: Documentation, EDAC: Update xgene binding for missing register bus Update the APM X-Gene SoC EDAC documentation binding to reference the missing register bus for the SoC EDAC. Signed-off-by: Loc Ho Cc: Arnd Bergmann Cc: devicetree@vger.kernel.org Cc: Ian Campbell Cc: Kumar Gala Cc: linux-arm-kernel@lists.infradead.org Cc: linux-edac Cc: Mark Rutland Cc: mchehab@osg.samsung.com Cc: patches@apm.com Cc: Pawel Moll Cc: Rob Herring Link: http://lkml.kernel.org/r/1453495625-28006-2-git-send-email-lho@apm.com Signed-off-by: Borislav Petkov --- Documentation/devicetree/bindings/edac/apm-xgene-edac.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/edac/apm-xgene-edac.txt b/Documentation/devicetree/bindings/edac/apm-xgene-edac.txt index 78e2a31c58d0..1006b0489464 100644 --- a/Documentation/devicetree/bindings/edac/apm-xgene-edac.txt +++ b/Documentation/devicetree/bindings/edac/apm-xgene-edac.txt @@ -16,6 +16,10 @@ Required properties: - regmap-mcba : Regmap of the MCB-A (memory bridge) resource. - regmap-mcbb : Regmap of the MCB-B (memory bridge) resource. - regmap-efuse : Regmap of the PMD efuse resource. +- regmap-rb : Regmap of the register bus resource. This property + is optional only for compatibility. If the RB + error conditions are not cleared, it will + continuously generate interrupt. - reg : First resource shall be the CPU bus (PCP) resource. - interrupts : Interrupt-specifier for MCU, PMD, L3, or SoC error IRQ(s). @@ -64,6 +68,11 @@ Example: reg = <0x0 0x1054a000 0x0 0x20>; }; + rb: rb@7e000000 { + compatible = "apm,xgene-rb", "syscon"; + reg = <0x0 0x7e000000 0x0 0x10>; + }; + edac@78800000 { compatible = "apm,xgene-edac"; #address-cells = <2>; @@ -73,6 +82,7 @@ Example: regmap-mcba = <&mcba>; regmap-mcbb = <&mcbb>; regmap-efuse = <&efuse>; + regmap-rb = <&rb>; reg = <0x0 0x78800000 0x0 0x100>; interrupts = <0x0 0x20 0x4>, <0x0 0x21 0x4>, -- cgit From 4d67e3ce75f97148ed127c53d6b0fc854d8b3867 Mon Sep 17 00:00:00 2001 From: Loc Ho Date: Fri, 22 Jan 2016 13:47:04 -0700 Subject: EDAC, xgene: Add missing SoC register bus error handling Add missing register bus error handling for APM X-Gene EDAC SoC and fix a checking condition for CE error promoted to UE. Signed-off-by: Loc Ho Cc: Arnd Bergmann Cc: devicetree@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-edac Cc: Mauro Carvalho Chehab Cc: patches@apm.com Link: http://lkml.kernel.org/r/1453495625-28006-3-git-send-email-lho@apm.com Signed-off-by: Borislav Petkov --- drivers/edac/xgene_edac.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c index 41f876414a18..bf19b6e3bd12 100644 --- a/drivers/edac/xgene_edac.c +++ b/drivers/edac/xgene_edac.c @@ -61,6 +61,7 @@ struct xgene_edac { struct regmap *mcba_map; struct regmap *mcbb_map; struct regmap *efuse_map; + struct regmap *rb_map; void __iomem *pcp_csr; spinlock_t lock; struct dentry *dfs; @@ -1057,7 +1058,7 @@ static bool xgene_edac_l3_promote_to_uc_err(u32 l3cesr, u32 l3celr) case 0x041: return true; } - } else if (L3C_ELR_ERRSYN(l3celr) == 9) + } else if (L3C_ELR_ERRWAY(l3celr) == 9) return true; return false; @@ -1353,6 +1354,17 @@ static int xgene_edac_l3_remove(struct xgene_edac_dev_ctx *l3) #define GLBL_MDED_ERRH 0x0848 #define GLBL_MDED_ERRHMASK 0x084c +/* IO Bus Registers */ +#define RBCSR 0x0000 +#define STICKYERR_MASK BIT(0) +#define RBEIR 0x0008 +#define AGENT_OFFLINE_ERR_MASK BIT(30) +#define UNIMPL_RBPAGE_ERR_MASK BIT(29) +#define WORD_ALIGNED_ERR_MASK BIT(28) +#define PAGE_ACCESS_ERR_MASK BIT(27) +#define WRITE_ACCESS_MASK BIT(26) +#define RBERRADDR_RD(src) ((src) & 0x03FFFFFF) + static const char * const soc_mem_err_v1[] = { "10GbE0", "10GbE1", @@ -1470,6 +1482,51 @@ static void xgene_edac_rb_report(struct edac_device_ctl_info *edac_dev) u32 err_addr_hi; u32 reg; + /* If the register bus resource isn't available, just skip it */ + if (!ctx->edac->rb_map) + goto rb_skip; + + /* + * Check RB access errors + * 1. Out of range + * 2. Un-implemented page + * 3. Un-aligned access + * 4. Offline slave IP + */ + if (regmap_read(ctx->edac->rb_map, RBCSR, ®)) + return; + if (reg & STICKYERR_MASK) { + bool write; + u32 address; + + dev_err(edac_dev->dev, "IOB bus access error(s)\n"); + if (regmap_read(ctx->edac->rb_map, RBEIR, ®)) + return; + write = reg & WRITE_ACCESS_MASK ? 1 : 0; + address = RBERRADDR_RD(reg); + if (reg & AGENT_OFFLINE_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s access to offline agent error\n", + write ? "write" : "read"); + if (reg & UNIMPL_RBPAGE_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s access to unimplemented page error\n", + write ? "write" : "read"); + if (reg & WORD_ALIGNED_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s word aligned access error\n", + write ? "write" : "read"); + if (reg & PAGE_ACCESS_ERR_MASK) + dev_err(edac_dev->dev, + "IOB bus %s to page out of range access error\n", + write ? "write" : "read"); + if (regmap_write(ctx->edac->rb_map, RBEIR, 0)) + return; + if (regmap_write(ctx->edac->rb_map, RBCSR, 0)) + return; + } +rb_skip: + /* IOB Bridge agent transaction error interrupt */ reg = readl(ctx->dev_csr + IOBBATRANSERRINTSTS); if (!reg) @@ -1852,6 +1909,17 @@ static int xgene_edac_probe(struct platform_device *pdev) goto out_err; } + /* + * NOTE: The register bus resource is optional for compatibility + * reason. + */ + edac->rb_map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "regmap-rb"); + if (IS_ERR(edac->rb_map)) { + dev_warn(edac->dev, "missing syscon regmap rb\n"); + edac->rb_map = NULL; + } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); edac->pcp_csr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(edac->pcp_csr)) { -- cgit From f5793c970888e48542de4ae152d16308873f29e4 Mon Sep 17 00:00:00 2001 From: Loc Ho Date: Fri, 22 Jan 2016 13:47:05 -0700 Subject: arm64: Update the APM X-Gene EDAC node with the RB register resource Add the RB register resource as requires with the updated driver. Signed-off-by: Loc Ho Cc: Arnd Bergmann Cc: Catalin Marinas Cc: devicetree@vger.kernel.org Cc: Duc Dang Cc: Ian Campbell Cc: Kumar Gala Cc: linux-arm-kernel@lists.infradead.org Cc: linux-edac Cc: Mark Rutland Cc: mchehab@osg.samsung.com Cc: patches@apm.com Cc: Pawel Moll Cc: Rob Herring Cc: Will Deacon Link: http://lkml.kernel.org/r/1453495625-28006-4-git-send-email-lho@apm.com Signed-off-by: Borislav Petkov --- arch/arm64/boot/dts/apm/apm-storm.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi index fe30f7671ea3..3e40bd469cea 100644 --- a/arch/arm64/boot/dts/apm/apm-storm.dtsi +++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi @@ -493,6 +493,11 @@ reg = <0x0 0x1054a000 0x0 0x20>; }; + rb: rb@7e000000 { + compatible = "apm,xgene-rb", "syscon"; + reg = <0x0 0x7e000000 0x0 0x10>; + }; + edac@78800000 { compatible = "apm,xgene-edac"; #address-cells = <2>; @@ -502,6 +507,7 @@ regmap-mcba = <&mcba>; regmap-mcbb = <&mcbb>; regmap-efuse = <&efuse>; + regmap-rb = <&rb>; reg = <0x0 0x78800000 0x0 0x100>; interrupts = <0x0 0x20 0x4>, <0x0 0x21 0x4>, -- cgit From 8163ec29c4c2911291d6fb2e9d5b171e17ce4f43 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 16 Sep 2015 20:31:38 -0300 Subject: [media] v4l: omap3isp: Fix module autoloading Platform drivers needs to export the OF id table and this be built into the module or udev will not have the necessary information to autoload the driver module when the device is registered via OF. Signed-off-by: Javier Martinez Canillas Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 0bcfa553c1aa..79a0b953bba3 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2599,6 +2599,7 @@ static const struct of_device_id omap3isp_of_table[] = { { .compatible = "ti,omap3-isp" }, { }, }; +MODULE_DEVICE_TABLE(of, omap3isp_of_table); static struct platform_driver omap3isp_driver = { .probe = isp_probe, -- cgit From 35c5f63773f77a4bfcc3010f6bcc84bdb74c8954 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 18 Sep 2014 18:57:48 -0300 Subject: [media] v4l: omap3isp: Move starting the sensor from streamon IOCTL handler to VB2 QOP Move the starting of the sensor from the VIDIOC_STREAMON handler to the videobuf2 queue op start_streaming. This avoids failing starting the stream after vb2_streamon() has already finished. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 49 ++++++++++++++++++------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index 994dfc0813f6..bc37467e2fe5 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -434,10 +434,40 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) } } +static int isp_video_start_streaming(struct vb2_queue *queue, + unsigned int count) +{ + struct isp_video_fh *vfh = vb2_get_drv_priv(queue); + struct isp_video *video = vfh->video; + struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); + unsigned long flags; + int ret; + + /* In sensor-to-memory mode, the stream can be started synchronously + * to the stream on command. In memory-to-memory mode, it will be + * started when buffers are queued on both the input and output. + */ + if (pipe->input) + return 0; + + ret = omap3isp_pipeline_set_stream(pipe, + ISP_PIPELINE_STREAM_CONTINUOUS); + if (ret < 0) + return ret; + + spin_lock_irqsave(&video->irqlock, flags); + if (list_empty(&video->dmaqueue)) + video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN; + spin_unlock_irqrestore(&video->irqlock, flags); + + return 0; +} + static const struct vb2_ops isp_video_queue_ops = { .queue_setup = isp_video_queue_setup, .buf_prepare = isp_video_buffer_prepare, .buf_queue = isp_video_buffer_queue, + .start_streaming = isp_video_start_streaming, }; /* @@ -1087,29 +1117,10 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) if (ret < 0) goto err_check_format; - /* In sensor-to-memory mode, the stream can be started synchronously - * to the stream on command. In memory-to-memory mode, it will be - * started when buffers are queued on both the input and output. - */ - if (pipe->input == NULL) { - ret = omap3isp_pipeline_set_stream(pipe, - ISP_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) - goto err_set_stream; - spin_lock_irqsave(&video->irqlock, flags); - if (list_empty(&video->dmaqueue)) - video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN; - spin_unlock_irqrestore(&video->irqlock, flags); - } - mutex_unlock(&video->stream_lock); return 0; -err_set_stream: - mutex_lock(&video->queue_lock); - vb2_streamoff(&vfh->queue, type); - mutex_unlock(&video->queue_lock); err_check_format: media_entity_pipeline_stop(&video->video.entity); err_pipeline_start: -- cgit From 87e062d4a93f1d78bd765256c826c338f7a0e921 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 18 Sep 2014 18:57:49 -0300 Subject: [media] v4l: omap3isp: Return buffers back to videobuf2 if pipeline streamon fails When the video buffer queue was stopped before the stream source was started in omap3isp_streamon(), the buffers were not returned back to videobuf2. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 46 +++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index bc37467e2fe5..f82b470c01f9 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -434,6 +434,30 @@ static void isp_video_buffer_queue(struct vb2_buffer *buf) } } +/* + * omap3isp_video_return_buffers - Return all queued buffers to videobuf2 + * @video: ISP video object + * @state: new state for the returned buffers + * + * Return all buffers queued on the video node to videobuf2 in the given state. + * The buffer state should be VB2_BUF_STATE_QUEUED if called due to an error + * when starting the stream, or VB2_BUF_STATE_ERROR otherwise. + * + * The function must be called with the video irqlock held. + */ +static void omap3isp_video_return_buffers(struct isp_video *video, + enum vb2_buffer_state state) +{ + while (!list_empty(&video->dmaqueue)) { + struct isp_buffer *buf; + + buf = list_first_entry(&video->dmaqueue, + struct isp_buffer, irqlist); + list_del(&buf->irqlist); + vb2_buffer_done(&buf->vb.vb2_buf, state); + } +} + static int isp_video_start_streaming(struct vb2_queue *queue, unsigned int count) { @@ -452,8 +476,12 @@ static int isp_video_start_streaming(struct vb2_queue *queue, ret = omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_CONTINUOUS); - if (ret < 0) + if (ret < 0) { + spin_lock_irqsave(&video->irqlock, flags); + omap3isp_video_return_buffers(video, VB2_BUF_STATE_QUEUED); + spin_unlock_irqrestore(&video->irqlock, flags); return ret; + } spin_lock_irqsave(&video->irqlock, flags); if (list_empty(&video->dmaqueue)) @@ -571,26 +599,16 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) * omap3isp_video_cancel_stream - Cancel stream on a video node * @video: ISP video object * - * Cancelling a stream mark all buffers on the video node as erroneous and makes - * sure no new buffer can be queued. + * Cancelling a stream returns all buffers queued on the video node to videobuf2 + * in the erroneous state and makes sure no new buffer can be queued. */ void omap3isp_video_cancel_stream(struct isp_video *video) { unsigned long flags; spin_lock_irqsave(&video->irqlock, flags); - - while (!list_empty(&video->dmaqueue)) { - struct isp_buffer *buf; - - buf = list_first_entry(&video->dmaqueue, - struct isp_buffer, irqlist); - list_del(&buf->irqlist); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - + omap3isp_video_return_buffers(video, VB2_BUF_STATE_ERROR); video->error = true; - spin_unlock_irqrestore(&video->irqlock, flags); } -- cgit From 18ba53f532f2813cb2b278b662c0bb9b7f0295b5 Mon Sep 17 00:00:00 2001 From: "Lad, Prabhakar" Date: Wed, 25 Feb 2015 12:58:14 -0300 Subject: [media] v4l: omap3isp: use vb2_buffer_state enum for vb2 buffer state use the vb2_buffer_state enum for assigning the state of the vb2 buffer, along side making isp_pipeline_state state variable local to the block. This fixes the following sparse warning as well: drivers/media/platform/omap3isp/ispvideo.c:497:35: warning: mixing different enum types drivers/media/platform/omap3isp/ispvideo.c:497:35: int enum isp_pipeline_state versus drivers/media/platform/omap3isp/ispvideo.c:497:35: int enum vb2_buffer_state Signed-off-by: Lad, Prabhakar Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/ispvideo.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index f82b470c01f9..2aff755ff77c 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -517,7 +517,7 @@ static const struct vb2_ops isp_video_queue_ops = { struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) { struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); - enum isp_pipeline_state state; + enum vb2_buffer_state vb_state; struct isp_buffer *buf; unsigned long flags; @@ -553,17 +553,19 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) /* Report pipeline errors to userspace on the capture device side. */ if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) { - state = VB2_BUF_STATE_ERROR; + vb_state = VB2_BUF_STATE_ERROR; pipe->error = false; } else { - state = VB2_BUF_STATE_DONE; + vb_state = VB2_BUF_STATE_DONE; } - vb2_buffer_done(&buf->vb.vb2_buf, state); + vb2_buffer_done(&buf->vb.vb2_buf, vb_state); spin_lock_irqsave(&video->irqlock, flags); if (list_empty(&video->dmaqueue)) { + enum isp_pipeline_state state; + spin_unlock_irqrestore(&video->irqlock, flags); if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) -- cgit From 514580f99af8eae246820fe324a78087972a7d63 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 24 Sep 2015 11:00:12 -0300 Subject: [media] v4l: omap3isp: Fix handling platform_get_irq result The function can return negative value. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/assign_signed_to_unsigned.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2046107 Signed-off-by: Andrzej Hajda Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 79a0b953bba3..97f6b1824577 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2528,12 +2528,13 @@ static int isp_probe(struct platform_device *pdev) } /* Interrupt */ - isp->irq_num = platform_get_irq(pdev, 0); - if (isp->irq_num <= 0) { + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { dev_err(isp->dev, "No IRQ resource\n"); ret = -ENODEV; goto error_iommu; } + isp->irq_num = ret; if (devm_request_irq(isp->dev, isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) { -- cgit From 61d5b9d46d2ea4b3ae9534ed6da608a78ce29ac5 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 10 Nov 2015 21:34:18 -0200 Subject: [media] v4l: omap3isp: preview: Mark output buffer done first The sequence number counter is incremented on each output buffer, and that incremented value is used as the sequence number of that buffer. The input buffer sequence numbering is based just on reading the same counter. If the input buffer is marked done first, its sequence number ends up being that of the output buffer - 1. This is how the resizer works as well. Signed-off-by: Sakari Ailus Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isppreview.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index 84a96670e2e7..ac30a0f83780 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -1480,13 +1480,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev) struct isp_buffer *buffer; int restart = 0; - if (prev->input == PREVIEW_INPUT_MEMORY) { - buffer = omap3isp_video_buffer_next(&prev->video_in); - if (buffer != NULL) - preview_set_inaddr(prev, buffer->dma); - pipe->state |= ISP_PIPELINE_IDLE_INPUT; - } - if (prev->output & PREVIEW_OUTPUT_MEMORY) { buffer = omap3isp_video_buffer_next(&prev->video_out); if (buffer != NULL) { @@ -1496,6 +1489,13 @@ static void preview_isr_buffer(struct isp_prev_device *prev) pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; } + if (prev->input == PREVIEW_INPUT_MEMORY) { + buffer = omap3isp_video_buffer_next(&prev->video_in); + if (buffer != NULL) + preview_set_inaddr(prev, buffer->dma); + pipe->state |= ISP_PIPELINE_IDLE_INPUT; + } + switch (prev->state) { case ISP_PIPELINE_STREAM_SINGLESHOT: if (isp_pipeline_ready(pipe)) -- cgit From 74d1e7c09caed943efce745061f52231bc4c174e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 29 Dec 2015 12:03:19 -0200 Subject: [media] v4l: omap3isp: Fix data lane shift configuration The data-shift DT property speficies the number of bits to be shifted, but the driver still interprets the value as a multiple of two bits as used by now removed platform data support. Fix it. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 2 +- drivers/media/platform/omap3isp/ispccdc.c | 2 +- drivers/media/platform/omap3isp/omap3isp.h | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 97f6b1824577..67efa9ea551e 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -449,7 +449,7 @@ void omap3isp_configure_bridge(struct isp_device *isp, case CCDC_INPUT_PARALLEL: ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL; ispctrl_val |= parcfg->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT; - shift += parcfg->data_lane_shift * 2; + shift += parcfg->data_lane_shift; break; case CCDC_INPUT_CSI2A: diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index bb3974c98e37..882310eb45cc 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -2421,7 +2421,7 @@ static int ccdc_link_validate(struct v4l2_subdev *sd, &((struct isp_bus_cfg *) media_entity_to_v4l2_subdev(link->source->entity) ->host_priv)->bus.parallel; - parallel_shift = parcfg->data_lane_shift * 2; + parallel_shift = parcfg->data_lane_shift; } else { parallel_shift = 0; } diff --git a/drivers/media/platform/omap3isp/omap3isp.h b/drivers/media/platform/omap3isp/omap3isp.h index 190e259a6a2d..443e8f7673e2 100644 --- a/drivers/media/platform/omap3isp/omap3isp.h +++ b/drivers/media/platform/omap3isp/omap3isp.h @@ -33,9 +33,9 @@ enum isp_interface_type { * struct isp_parallel_cfg - Parallel interface configuration * @data_lane_shift: Data lane shifter * 0 - CAMEXT[13:0] -> CAM[13:0] - * 1 - CAMEXT[13:2] -> CAM[11:0] - * 2 - CAMEXT[13:4] -> CAM[9:0] - * 3 - CAMEXT[13:6] -> CAM[7:0] + * 2 - CAMEXT[13:2] -> CAM[11:0] + * 4 - CAMEXT[13:4] -> CAM[9:0] + * 6 - CAMEXT[13:6] -> CAM[7:0] * @clk_pol: Pixel clock polarity * 0 - Sample on rising edge, 1 - Sample on falling edge * @hs_pol: Horizontal synchronization polarity @@ -48,7 +48,7 @@ enum isp_interface_type { * 0 - Normal, 1 - One's complement */ struct isp_parallel_cfg { - unsigned int data_lane_shift:2; + unsigned int data_lane_shift:3; unsigned int clk_pol:1; unsigned int hs_pol:1; unsigned int vs_pol:1; -- cgit From 3c97430d22d58b9c47a9a4573e8ae6976a475e3e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 5 Jan 2016 12:49:57 -0200 Subject: [media] sh_mobile_ceu_camera: use soc_camera_from_vb2q Use soc_camera_from_vb2q() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 90c87f2b4ec0..b9f369c0fb94 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -213,8 +213,7 @@ static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq, unsigned int *count, unsigned int *num_planes, unsigned int sizes[], void *alloc_ctxs[]) { - struct soc_camera_device *icd = container_of(vq, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vq); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -361,8 +360,7 @@ static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb) static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); @@ -413,8 +411,7 @@ error: static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vbuf); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -444,8 +441,7 @@ static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb) static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = container_of(vb->vb2_queue, - struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -460,7 +456,7 @@ static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb) static void sh_mobile_ceu_stop_streaming(struct vb2_queue *q) { - struct soc_camera_device *icd = container_of(q, struct soc_camera_device, vb2_vidq); + struct soc_camera_device *icd = soc_camera_from_vb2q(q); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct sh_mobile_ceu_dev *pcdev = ici->priv; struct list_head *buf_head, *tmp; -- cgit From 1dff3338539e96b2710c34693a6484585dfd7a78 Mon Sep 17 00:00:00 2001 From: Yoshihiko Mori Date: Sun, 13 Dec 2015 13:27:16 -0200 Subject: [media] soc_camera: rcar_vin: Add R-Car Gen3 support Add chip identification for R-Car Gen3. Signed-off-by: Yoshihiko Mori Signed-off-by: Yoshihiro Kaneko Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/rcar_vin.txt | 1 + drivers/media/platform/soc_camera/rcar_vin.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt index 9dafe6b06cd2..619193ccf7ff 100644 --- a/Documentation/devicetree/bindings/media/rcar_vin.txt +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt @@ -6,6 +6,7 @@ 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 + - "renesas,vin-r8a7795" for the R8A7795 device - "renesas,vin-r8a7794" for the R8A7794 device - "renesas,vin-r8a7793" for the R8A7793 device - "renesas,vin-r8a7791" for the R8A7791 device diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index b7fd695b9ed5..dc75a80794fb 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -143,6 +143,7 @@ #define RCAR_VIN_BT656 (1 << 3) enum chip_id { + RCAR_GEN3, RCAR_GEN2, RCAR_H1, RCAR_M1, @@ -1818,6 +1819,7 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { #ifdef CONFIG_OF static const struct of_device_id rcar_vin_of_table[] = { + { .compatible = "renesas,vin-r8a7795", .data = (void *)RCAR_GEN3 }, { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 }, { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, -- cgit From 368a53df02d61bb849e100219c2a758510062f88 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 22 Nov 2015 07:12:56 -0200 Subject: [media] soc_camera: constify v4l2_subdev_sensor_ops structures The v4l2_subdev_sensor_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/soc_camera/mt9m001.c | 2 +- drivers/media/i2c/soc_camera/mt9t031.c | 2 +- drivers/media/i2c/soc_camera/mt9v022.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c index 2e14e52ba2e0..69becc358659 100644 --- a/drivers/media/i2c/soc_camera/mt9m001.c +++ b/drivers/media/i2c/soc_camera/mt9m001.c @@ -632,7 +632,7 @@ static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = { .s_mbus_config = mt9m001_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = { .g_skip_top_lines = mt9m001_g_skip_top_lines, }; diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c index 3b6eeed2e2b9..5c8e3ffe3b27 100644 --- a/drivers/media/i2c/soc_camera/mt9t031.c +++ b/drivers/media/i2c/soc_camera/mt9t031.c @@ -728,7 +728,7 @@ static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = { .s_mbus_config = mt9t031_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = { .g_skip_top_lines = mt9t031_g_skip_top_lines, }; diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index c2ba1fb3694d..2721e583bfa0 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -860,7 +860,7 @@ static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = { .s_mbus_config = mt9v022_s_mbus_config, }; -static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { +static const struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = { .g_skip_top_lines = mt9v022_g_skip_top_lines, }; -- cgit From 7d3ccfe697bceec9fdf7b901da4073cc55fa56de Mon Sep 17 00:00:00 2001 From: Joseph Marrero Date: Wed, 25 Nov 2015 20:38:43 -0200 Subject: [media] davinci_vpfe: make checkpatch happy This WARNING was found using the checkpatch tool: Block comments use * on the subsequent lines Signed-off-by: Joseph Marrero Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h index 7b7e7b26c1e8..3cc9be776f8b 100644 --- a/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h +++ b/drivers/staging/media/davinci_vpfe/davinci_vpfe_user.h @@ -538,7 +538,7 @@ struct vpfe_isif_raw_config { }; /********************************************************************** - IPIPE API Structures +* IPIPE API Structures **********************************************************************/ /* IPIPE module configurations */ -- cgit From 7871597a73b7b8daa7beeba3c36d68f9047d38c2 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:41 -0200 Subject: [media] tvp5150: Restructure version detection Move the version detection code to a separate function and restructure it to prepare for TVP5151 support. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 79 ++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 6c3769d44b75..f80928156ad7 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1105,13 +1105,53 @@ static const struct v4l2_subdev_ops tvp5150_ops = { I2C Client & Driver ****************************************************************************/ +static int tvp5150_detect_version(struct tvp5150 *core) +{ + struct v4l2_subdev *sd = &core->sd; + struct i2c_client *c = v4l2_get_subdevdata(sd); + unsigned int i; + u16 dev_id; + u16 rom_ver; + u8 regs[4]; + int res; + + /* + * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, + * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER + */ + for (i = 0; i < 4; i++) { + res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); + if (res < 0) + return res; + regs[i] = res; + } + + dev_id = (regs[0] << 8) | regs[1]; + rom_ver = (regs[2] << 8) | regs[3]; + + v4l2_info(sd, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n", + dev_id, regs[2], regs[3], c->addr << 1, c->adapter->name); + + if (dev_id == 0x5150 && rom_ver == 0x0321) { /* TVP51510A */ + v4l2_info(sd, "tvp5150a detected.\n"); + } else if (dev_id == 0x5150 && rom_ver == 0x0400) { /* TVP5150AM1 */ + v4l2_info(sd, "tvp5150am1 detected.\n"); + + /* ITU-T BT.656.4 timing */ + tvp5150_write(sd, TVP5150_REV_SELECT, 0); + } else { + v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); + } + + return 0; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct tvp5150 *core; struct v4l2_subdev *sd; - int tvp5150_id[4]; - int i, res; + int res; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(c->adapter, @@ -1124,38 +1164,9 @@ static int tvp5150_probe(struct i2c_client *c, sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); - /* - * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID, - * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER - */ - for (i = 0; i < 4; i++) { - res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i); - if (res < 0) - return res; - tvp5150_id[i] = res; - } - - v4l_info(c, "chip found @ 0x%02x (%s)\n", - c->addr << 1, c->adapter->name); - - if (tvp5150_id[2] == 4 && tvp5150_id[3] == 0) { /* Is TVP5150AM1 */ - v4l2_info(sd, "tvp%02x%02xam1 detected.\n", - tvp5150_id[0], tvp5150_id[1]); - - /* ITU-T BT.656.4 timing */ - tvp5150_write(sd, TVP5150_REV_SELECT, 0); - } else { - /* Is TVP5150A */ - if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) { - v4l2_info(sd, "tvp%02x%02xa detected.\n", - tvp5150_id[0], tvp5150_id[1]); - } else { - v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n", - tvp5150_id[0], tvp5150_id[1]); - v4l2_info(sd, "*** Rom ver is %d.%d\n", - tvp5150_id[2], tvp5150_id[3]); - } - } + res = tvp5150_detect_version(core); + if (res < 0) + return res; core->norm = V4L2_STD_ALL; /* Default is autodetect */ core->input = TVP5150_COMPOSITE1; -- cgit From 05676b3e33fe2fd693f2c0ff3d058db6ca5e7ed6 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:42 -0200 Subject: [media] tvp5150: Add tvp5151 support Expand the version detection code to identity the tvp5151. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index f80928156ad7..2816ceb4874a 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1139,6 +1139,8 @@ static int tvp5150_detect_version(struct tvp5150 *core) /* ITU-T BT.656.4 timing */ tvp5150_write(sd, TVP5150_REV_SELECT, 0); + } else if (dev_id == 0x5151 && rom_ver == 0x0100) { /* TVP5151 */ + v4l2_info(sd, "tvp5151 detected.\n"); } else { v4l2_info(sd, "*** unknown tvp%04x chip detected.\n", dev_id); } -- cgit From b1950b8db9896cca59f61b6b7c6d3a14dc782b80 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:44 -0200 Subject: [media] tvp5150: Add pixel rate control support This patch adds support for the V4L2_CID_PIXEL_RATE control. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 2816ceb4874a..555718ebbf0e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1174,7 +1174,7 @@ static int tvp5150_probe(struct i2c_client *c, core->input = TVP5150_COMPOSITE1; core->enable = 1; - v4l2_ctrl_handler_init(&core->hdl, 4); + v4l2_ctrl_handler_init(&core->hdl, 5); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, @@ -1183,6 +1183,9 @@ static int tvp5150_probe(struct i2c_client *c, V4L2_CID_SATURATION, 0, 255, 1, 128); v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, V4L2_CID_HUE, -128, 127, 1, 0); + v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops, + V4L2_CID_PIXEL_RATE, 27000000, + 27000000, 1, 27000000); sd->ctrl_handler = &core->hdl; if (core->hdl.error) { res = core->hdl.error; -- cgit From 460b6c0831cb52ef349156cfa27e889606b4cb75 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:45 -0200 Subject: [media] tvp5150: Add s_stream subdev operation support This patch adds the .s_stream subdev operation to the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 555718ebbf0e..08383a273e51 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -952,6 +952,21 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) I2C Command ****************************************************************************/ +static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) +{ + /* Initializes TVP5150 to its default values */ + /* # set PCLK (27MHz) */ + tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); + + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + if (enable) + tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + else + tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); + + return 0; +} + static int tvp5150_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config) { @@ -1073,6 +1088,7 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_std = tvp5150_s_std, + .s_stream = tvp5150_s_stream, .s_routing = tvp5150_s_routing, .s_crop = tvp5150_s_crop, .g_crop = tvp5150_g_crop, -- cgit From dd3a46bbbe1d49a70a66d95a435a729f7ecd7e8f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 7 Jan 2016 10:46:46 -0200 Subject: [media] tvp5150: Add g_mbus_config subdev operation support This patch adds the .g_mbus_config subdev operation to the driver. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 08383a273e51..e6ce197d8dbc 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -948,6 +948,16 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) return 0; } +static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, + struct v4l2_mbus_config *cfg) +{ + cfg->type = V4L2_MBUS_BT656; + cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING + | V4L2_MBUS_FIELD_EVEN_LOW | V4L2_MBUS_DATA_ACTIVE_HIGH; + + return 0; +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1093,6 +1103,7 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { .s_crop = tvp5150_s_crop, .g_crop = tvp5150_g_crop, .cropcap = tvp5150_cropcap, + .g_mbus_config = tvp5150_g_mbus_config, }; static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { -- cgit From 367298c6b9dbcf393527ab23aa2b4314ca01bf28 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:47 -0200 Subject: [media] tvp5150: Add device tree binding document Add a Device Tree binding document for the TVP5150 video decoder. Signed-off-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/tvp5150.txt | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/tvp5150.txt diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt new file mode 100644 index 000000000000..8c0fc1a26bf0 --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt @@ -0,0 +1,45 @@ +* Texas Instruments TVP5150 and TVP5151 video decoders + +The TVP5150 and TVP5151 are video decoders that convert baseband NTSC and PAL +(and also SECAM in the TVP5151 case) video signals to either 8-bit 4:2:2 YUV +with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output formats. + +Required Properties: +- compatible: value must be "ti,tvp5150" +- reg: I2C slave address + +Optional Properties: +- pdn-gpios: phandle for the GPIO connected to the PDN pin, if any. +- reset-gpios: phandle for the GPIO connected to the RESETB pin, if any. + +The device node must contain one 'port' child node for its digital output +video port, in accordance with the video interface bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Required Endpoint Properties for parallel synchronization: + +- hsync-active: active state of the HSYNC signal. Must be <1> (HIGH). +- vsync-active: active state of the VSYNC signal. Must be <1> (HIGH). +- field-even-active: field signal level during the even field data + transmission. Must be <0>. + +If none of hsync-active, vsync-active and field-even-active is specified, +the endpoint is assumed to use embedded BT.656 synchronization. + +Example: + +&i2c2 { + ... + tvp5150@5c { + compatible = "ti,tvp5150"; + reg = <0x5c>; + pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>; + + port { + tvp5150_1: endpoint { + remote-endpoint = <&ccdc_ep>; + }; + }; + }; +}; -- cgit From 09aa2609fe69fd4878e5c0f1319410b46afaab8f Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:49 -0200 Subject: [media] tvp5150: Initialize the chip on probe After power-up, the tvp5150 decoder is in a unknown state until the RESETB pin is driven LOW which reset all the registers and restarts the chip's internal state machine. The init sequence has some timing constraints and the RESETB signal can only be used if the PDN (Power-down) pin is first released. So, the initialization sequence is as follows: 1- PDN (active-low) is driven HIGH so the chip is power-up 2- A 20 ms delay is needed before sending a RESETB (active-low) signal. 3- The RESETB pulse duration is 500 ns. 4- A 200 us delay is needed for the I2C client to be active after reset. This patch used as a reference the logic in the IGEPv2 board file from the ISEE 2.6.37 vendor tree. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index e6ce197d8dbc..6f4b0f83973e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1175,6 +1176,36 @@ static int tvp5150_detect_version(struct tvp5150 *core) return 0; } +static int tvp5150_init(struct i2c_client *c) +{ + struct gpio_desc *pdn_gpio; + struct gpio_desc *reset_gpio; + + pdn_gpio = devm_gpiod_get_optional(&c->dev, "pdn", GPIOD_OUT_HIGH); + if (IS_ERR(pdn_gpio)) + return PTR_ERR(pdn_gpio); + + if (pdn_gpio) { + gpiod_set_value_cansleep(pdn_gpio, 0); + /* Delay time between power supplies active and reset */ + msleep(20); + } + + reset_gpio = devm_gpiod_get_optional(&c->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return PTR_ERR(reset_gpio); + + if (reset_gpio) { + /* RESETB pulse duration */ + ndelay(500); + gpiod_set_value_cansleep(reset_gpio, 0); + /* Delay time between end of reset to I2C active */ + usleep_range(200, 250); + } + + return 0; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { @@ -1187,6 +1218,10 @@ static int tvp5150_probe(struct i2c_client *c, I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EIO; + res = tvp5150_init(c); + if (res) + return res; + core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; -- cgit From a2e5f1b3a4f12c8c35313a9052a8928b5b85a391 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 7 Jan 2016 10:46:50 -0200 Subject: [media] tvp5150: Configure data interface via DT The video decoder supports either 8-bit 4:2:2 YUV with discrete syncs or 8-bit ITU-R BT.656 with embedded syncs output format but currently BT.656 it's always reported. Allow to configure the format to use via either platform data or a device tree definition. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 66 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 6f4b0f83973e..57901d613a12 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -43,6 +44,8 @@ struct tvp5150 { u32 input; u32 output; int enable; + + enum v4l2_mbus_type mbus_type; }; static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd) @@ -773,6 +776,10 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) v4l2_ctrl_handler_setup(&decoder->hdl); tvp5150_set_std(sd, decoder->norm); + + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + tvp5150_write(sd, TVP5150_DATA_RATE_SEL, 0x40); + return 0; }; @@ -952,7 +959,9 @@ static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a) static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, struct v4l2_mbus_config *cfg) { - cfg->type = V4L2_MBUS_BT656; + struct tvp5150 *decoder = to_tvp5150(sd); + + cfg->type = decoder->mbus_type; cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_FIELD_EVEN_LOW | V4L2_MBUS_DATA_ACTIVE_HIGH; @@ -965,13 +974,20 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { + struct tvp5150 *decoder = to_tvp5150(sd); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + int val = 0x09; + + /* Output format: 8-bit 4:2:2 YUV with discrete sync */ + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + val = 0x0d; + /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + tvp5150_write(sd, TVP5150_MISC_CTL, val); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); @@ -1206,11 +1222,42 @@ static int tvp5150_init(struct i2c_client *c) return 0; } +static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) +{ + struct v4l2_of_endpoint bus_cfg; + struct device_node *ep; + unsigned int flags; + int ret = 0; + + ep = of_graph_get_next_endpoint(np, NULL); + if (!ep) + return -EINVAL; + + ret = v4l2_of_parse_endpoint(ep, &bus_cfg); + if (ret) + goto err; + + flags = bus_cfg.bus.parallel.flags; + + if (bus_cfg.bus_type == V4L2_MBUS_PARALLEL && + !(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH && + flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH && + flags & V4L2_MBUS_FIELD_EVEN_LOW)) + return -EINVAL; + + decoder->mbus_type = bus_cfg.bus_type; + +err: + of_node_put(ep); + return ret; +} + static int tvp5150_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct tvp5150 *core; struct v4l2_subdev *sd; + struct device_node *np = c->dev.of_node; int res; /* Check if the adapter supports the needed features */ @@ -1225,7 +1272,20 @@ static int tvp5150_probe(struct i2c_client *c, core = devm_kzalloc(&c->dev, sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; + sd = &core->sd; + + if (IS_ENABLED(CONFIG_OF) && np) { + res = tvp5150_parse_dt(core, np); + if (res) { + v4l2_err(sd, "DT parsing error: %d\n", res); + return res; + } + } else { + /* Default to BT.656 embedded sync */ + core->mbus_type = V4L2_MBUS_BT656; + } + v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); res = tvp5150_detect_version(core); -- cgit From 7ef930a7b33677b8227d0a19dcc32d891d3cde8d Mon Sep 17 00:00:00 2001 From: Eduard Gavin Date: Thu, 7 Jan 2016 10:46:48 -0200 Subject: [media] tvp5150: Add OF match table The Documentation/devicetree/bindings/media/i2c/tvp5150.txt DT binding doc lists "ti,tvp5150" as the device compatible string but the driver does not have an OF match table. Add the table to the driver so the I2C core can do an OF style match. Signed-off-by: Eduard Gavin Signed-off-by: Javier Martinez Canillas Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 57901d613a12..437f1a7ecb96 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1359,8 +1359,17 @@ static const struct i2c_device_id tvp5150_id[] = { }; MODULE_DEVICE_TABLE(i2c, tvp5150_id); +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id tvp5150_of_match[] = { + { .compatible = "ti,tvp5150", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, tvp5150_of_match); +#endif + static struct i2c_driver tvp5150_driver = { .driver = { + .of_match_table = of_match_ptr(tvp5150_of_match), .name = "tvp5150", }, .probe = tvp5150_probe, -- cgit From 99e44da7928d4abb3028258ac3cd23a48495cd61 Mon Sep 17 00:00:00 2001 From: Patrick Boettcher Date: Sun, 24 Jan 2016 12:56:58 -0200 Subject: [media] media: change email address Soon my dibcom.fr/parrot.com-address won't respond anymore. Thus I'm replacing it. And, while being at it, let's adapt some other (old) email-addresses as well. Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/README.dvb-usb | 2 +- drivers/media/common/b2c2/flexcop.c | 4 ++-- drivers/media/common/cypress_firmware.c | 2 +- drivers/media/common/cypress_firmware.h | 2 +- drivers/media/dvb-core/dvb-usb-ids.h | 2 +- drivers/media/dvb-frontends/bcm3510.c | 4 ++-- drivers/media/dvb-frontends/bcm3510.h | 2 +- drivers/media/dvb-frontends/bcm3510_priv.h | 2 +- drivers/media/dvb-frontends/dib0070.c | 2 +- drivers/media/dvb-frontends/dib0090.c | 4 ++-- drivers/media/dvb-frontends/dib3000.h | 6 +++--- drivers/media/dvb-frontends/dib3000mb.c | 8 ++++---- drivers/media/dvb-frontends/dib3000mb_priv.h | 2 +- drivers/media/dvb-frontends/dib3000mc.c | 4 ++-- drivers/media/dvb-frontends/dib3000mc.h | 2 +- drivers/media/dvb-frontends/dib7000m.c | 2 +- drivers/media/dvb-frontends/dib7000p.c | 4 ++-- drivers/media/dvb-frontends/dib8000.c | 2 +- drivers/media/dvb-frontends/dib9000.c | 4 ++-- drivers/media/dvb-frontends/dibx000_common.c | 2 +- drivers/media/pci/b2c2/flexcop-pci.c | 2 +- drivers/media/usb/b2c2/flexcop-usb.c | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb.h | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_common.h | 2 +- drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 4 ++-- drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c | 2 +- drivers/media/usb/dvb-usb-v2/usb_urb.c | 2 +- drivers/media/usb/dvb-usb/a800.c | 4 ++-- drivers/media/usb/dvb-usb/cxusb.c | 4 ++-- drivers/media/usb/dvb-usb/dib0700_core.c | 2 +- drivers/media/usb/dvb-usb/dibusb-common.c | 2 +- drivers/media/usb/dvb-usb/dibusb-mb.c | 6 +++--- drivers/media/usb/dvb-usb/dibusb-mc.c | 6 +++--- drivers/media/usb/dvb-usb/dibusb.h | 2 +- drivers/media/usb/dvb-usb/digitv.c | 4 ++-- drivers/media/usb/dvb-usb/dtt200u-fe.c | 2 +- drivers/media/usb/dvb-usb/dtt200u.c | 4 ++-- drivers/media/usb/dvb-usb/dtt200u.h | 2 +- drivers/media/usb/dvb-usb/dvb-usb-common.h | 2 +- drivers/media/usb/dvb-usb/dvb-usb-dvb.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-firmware.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-i2c.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-init.c | 4 ++-- drivers/media/usb/dvb-usb/dvb-usb-remote.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb-urb.c | 2 +- drivers/media/usb/dvb-usb/dvb-usb.h | 2 +- drivers/media/usb/dvb-usb/nova-t-usb2.c | 4 ++-- drivers/media/usb/dvb-usb/ttusb2.c | 2 +- drivers/media/usb/dvb-usb/umt-010.c | 4 ++-- drivers/media/usb/dvb-usb/usb-urb.c | 2 +- drivers/media/usb/dvb-usb/vp702x-fe.c | 2 +- drivers/media/usb/dvb-usb/vp702x.c | 4 ++-- drivers/media/usb/dvb-usb/vp7045-fe.c | 2 +- drivers/media/usb/dvb-usb/vp7045.c | 4 ++-- drivers/media/usb/dvb-usb/vp7045.h | 2 +- 55 files changed, 80 insertions(+), 80 deletions(-) diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb index 669dc6ce4330..6f4b12f7b844 100644 --- a/Documentation/dvb/README.dvb-usb +++ b/Documentation/dvb/README.dvb-usb @@ -190,7 +190,7 @@ and watch another one. Patches, comments and suggestions are very very welcome. 3. Acknowledgements - Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for + Amaury Demol (Amaury.Demol@parrot.com) and Francois Kanounnikoff from DiBcom for providing specs, code and help, on which the dvb-dibusb, dib3000mb and dib3000mc are based. diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c index 412c5daf2b48..0f5114d406f8 100644 --- a/drivers/media/common/b2c2/flexcop.c +++ b/drivers/media/common/b2c2/flexcop.c @@ -1,7 +1,7 @@ /* * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III * flexcop.c - main module part - * Copyright (C) 2004-9 Patrick Boettcher + * Copyright (C) 2004-9 Patrick Boettcher * based on skystar2-driver Copyright (C) 2003 Vadim Catana, skystar@moldova.cc * * Acknowledgements: @@ -34,7 +34,7 @@ #include "flexcop.h" #define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip" -#define DRIVER_AUTHOR "Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * This driver is "hard-coded" to be used with the 1st generation of * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming @@ -865,5 +865,5 @@ static struct dvb_frontend_ops bcm3510_ops = { }; MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/bcm3510.h b/drivers/media/dvb-frontends/bcm3510.h index ff66492fb940..961c2eb87c68 100644 --- a/drivers/media/dvb-frontends/bcm3510.h +++ b/drivers/media/dvb-frontends/bcm3510.h @@ -3,7 +3,7 @@ * * Copyright (C) 2001-5, B2C2 inc. * - * GPL/Linux driver written by Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * 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/media/dvb-frontends/bcm3510_priv.h b/drivers/media/dvb-frontends/bcm3510_priv.h index 3bb1bc2a04f0..67f24686c31b 100644 --- a/drivers/media/dvb-frontends/bcm3510_priv.h +++ b/drivers/media/dvb-frontends/bcm3510_priv.h @@ -3,7 +3,7 @@ * * Copyright (C) 2001-5, B2C2 inc. * - * GPL/Linux driver written by Patrick Boettcher + * GPL/Linux driver written by Patrick Boettcher * * 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/media/dvb-frontends/dib0070.c b/drivers/media/dvb-frontends/dib0070.c index 0b8fb5dd1889..ee7d66997ccd 100644 --- a/drivers/media/dvb-frontends/dib0070.c +++ b/drivers/media/dvb-frontends/dib0070.c @@ -774,6 +774,6 @@ free_mem: } EXPORT_SYMBOL(dib0070_attach); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index 47cb72243b9d..976ee034a430 100644 --- a/drivers/media/dvb-frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c @@ -2669,7 +2669,7 @@ free_mem: } EXPORT_SYMBOL(dib0090_fw_register); -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h index 6ae9899b5b45..d5dfafb4ef13 100644 --- a/drivers/media/dvb-frontends/dib3000.h +++ b/drivers/media/dvb-frontends/dib3000.h @@ -2,11 +2,11 @@ * public header file of the frontend drivers for mobile DVB-T demodulators * DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DibCom, which has * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -14,7 +14,7 @@ * * Acknowledgements * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver + * Amaury Demol from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dvb-usb for more information diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 7a61172d0d45..3ca300939f79 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -2,11 +2,11 @@ * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B * DiBcom (http://www.dibcom.fr/) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DibCom, which has * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -14,7 +14,7 @@ * * Acknowledgements * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver + * Amaury Demol from DiBcom for providing specs and driver * sources, on which this driver (and the dvb-dibusb) are based. * * see Documentation/dvb/README.dvb-usb for more information @@ -36,7 +36,7 @@ /* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator" -#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" +#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@posteo.de" static int debug; module_param(debug, int, 0644); diff --git a/drivers/media/dvb-frontends/dib3000mb_priv.h b/drivers/media/dvb-frontends/dib3000mb_priv.h index 9dc235aa44b7..0459d5c84314 100644 --- a/drivers/media/dvb-frontends/dib3000mb_priv.h +++ b/drivers/media/dvb-frontends/dib3000mb_priv.h @@ -1,7 +1,7 @@ /* * dib3000mb_priv.h * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@posteo.de) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index 583d6b7fabed..ac90ed3af37e 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -2,7 +2,7 @@ * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/) - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * This code is partially based on the previous dib3000mc.c . * @@ -939,6 +939,6 @@ static struct dvb_frontend_ops dib3000mc_ops = { .read_ucblocks = dib3000mc_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h index 74816f793611..b37e69e6a58c 100644 --- a/drivers/media/dvb-frontends/dib3000mc.h +++ b/drivers/media/dvb-frontends/dib3000mc.h @@ -2,7 +2,7 @@ * Driver for DiBcom DiB3000MC/P-demodulator. * * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * This code is partially based on the previous dib3000mc.c . * diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 35eb71fe3c2b..8b21cccf3c3a 100644 --- a/drivers/media/dvb-frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c @@ -1465,6 +1465,6 @@ static struct dvb_frontend_ops dib7000m_ops = { .read_ucblocks = dib7000m_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 33be5d6b9e10..65ab79ed5e3e 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -2834,7 +2834,7 @@ static struct dvb_frontend_ops dib7000p_ops = { .read_ucblocks = dib7000p_read_unc_blocks, }; -MODULE_AUTHOR("Olivier Grenie "); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 94c26270fff0..349d2f1f62ce 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -4516,6 +4516,6 @@ void *dib8000_attach(struct dib8000_ops *ops) } EXPORT_SYMBOL(dib8000_attach); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 8f92aca0b073..91888a2f5301 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -2589,7 +2589,7 @@ static struct dvb_frontend_ops dib9000_ops = { .read_ucblocks = dib9000_read_unc_blocks, }; -MODULE_AUTHOR("Patrick Boettcher "); -MODULE_AUTHOR("Olivier Grenie "); +MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Olivier Grenie "); MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c index 43be7238311e..723358d7ca84 100644 --- a/drivers/media/dvb-frontends/dibx000_common.c +++ b/drivers/media/dvb-frontends/dibx000_common.c @@ -510,6 +510,6 @@ u32 systime(void) } EXPORT_SYMBOL(systime); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c index 8b5e0b3a92a0..4cac1fc233f2 100644 --- a/drivers/media/pci/b2c2/flexcop-pci.c +++ b/drivers/media/pci/b2c2/flexcop-pci.c @@ -39,7 +39,7 @@ MODULE_PARM_DESC(debug, #define DRIVER_VERSION "0.1" #define DRIVER_NAME "flexcop-pci" -#define DRIVER_AUTHOR "Patrick Boettcher " +#define DRIVER_AUTHOR "Patrick Boettcher " struct flexcop_pci { struct pci_dev *pdev; diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 0bd969063392..d4bdba60b0f7 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -10,7 +10,7 @@ /* Version information */ #define DRIVER_VERSION "0.1" #define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver" -#define DRIVER_AUTHOR "Patrick Boettcher " +#define DRIVER_AUTHOR "Patrick Boettcher " /* debug */ #ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h index 023d91f7e654..35f27e2e4e28 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb.h @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h index 45f07090d431..a1622bda2a5e 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index f0565bf3673e..5ec159f22399 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify @@ -1129,7 +1129,7 @@ int dvb_usbv2_reset_resume(struct usb_interface *intf) EXPORT_SYMBOL(dvb_usbv2_reset_resume); MODULE_VERSION("2.0"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_AUTHOR("Antti Palosaari "); MODULE_DESCRIPTION("DVB USB common"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c index 22bdce15ecf3..5bafeb6486be 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c @@ -1,7 +1,7 @@ /* * DVB USB framework * - * Copyright (C) 2004-6 Patrick Boettcher + * Copyright (C) 2004-6 Patrick Boettcher * Copyright (C) 2012 Antti Palosaari * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c index ca8f3c2b1082..55136cde38f5 100644 --- a/drivers/media/usb/dvb-usb-v2/usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/usb_urb.c @@ -1,6 +1,6 @@ /* usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c index 83684ed023cd..7ba975bea96a 100644 --- a/drivers/media/usb/dvb-usb/a800.c +++ b/drivers/media/usb/dvb-usb/a800.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T * USB2.0 (A800) DVB-T receiver. * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to * - AVerMedia who kindly provided information and @@ -185,7 +185,7 @@ static struct usb_driver a800_driver = { module_usb_driver(a800_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index ab7151181728..907ac01ae297 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -13,7 +13,7 @@ * * TODO: Use the cx25840-driver for the analogue part * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org) * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au) * @@ -2314,7 +2314,7 @@ static struct usb_driver cxusb_driver = { module_usb_driver(cxusb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_AUTHOR("Michael Krufky "); MODULE_AUTHOR("Chris Pascoe "); MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design"); diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 0d248ce02a9b..c16f999b9d7c 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -881,7 +881,7 @@ static struct usb_driver dib0700_driver = { module_usb_driver(dib0700_driver); MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index ef3a8f75f82e..35de6095926d 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -1,6 +1,6 @@ /* Common methods for dibusb-based-receivers. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/dibusb-mb.c b/drivers/media/usb/dvb-usb/dibusb-mb.c index a4ac37e0e98b..a0057641cc86 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mb.c +++ b/drivers/media/usb/dvb-usb/dibusb-mb.c @@ -1,10 +1,10 @@ /* DVB USB compliant linux driver for mobile DVB-T USB devices based on * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DiBcom, which has - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * 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 @@ -465,7 +465,7 @@ static struct usb_driver dibusb_driver = { module_usb_driver(dibusb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb-mc.c b/drivers/media/usb/dvb-usb/dibusb-mc.c index 9d1a59d09c52..08fb8a3f6e0c 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mc.c +++ b/drivers/media/usb/dvb-usb/dibusb-mc.c @@ -1,10 +1,10 @@ /* DVB USB compliant linux driver for mobile DVB-T USB devices based on * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P) * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * based on GPL code from DiBcom, which has - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) + * Copyright (C) 2004 Amaury Demol for DiBcom * * 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 @@ -143,7 +143,7 @@ static struct usb_driver dibusb_mc_driver = { module_usb_driver(dibusb_mc_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index 32ab1392313f..3f82163d8ab8 100644 --- a/drivers/media/usb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h @@ -1,6 +1,6 @@ /* Header file for all dibusb-based-receivers. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 772bde3c5020..63134335c994 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -1,7 +1,7 @@ /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0 * receiver * - * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de) * * partly based on the SDK published by Nebula Electronics * @@ -348,7 +348,7 @@ static struct usb_driver digitv_driver = { module_usb_driver(digitv_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0"); MODULE_VERSION("1.0-alpha"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 8637ad1be6be..7e72a1bef76a 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -1,7 +1,7 @@ /* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan DVB-T USB2.0 receiver. * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * 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 diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index c357fb3b0a88..ca3b69aa9688 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c @@ -1,7 +1,7 @@ /* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Steve Chang from WideView for providing support for the WT-220U. * @@ -362,7 +362,7 @@ static struct usb_driver dtt200u_usb_driver = { module_usb_driver(dtt200u_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dtt200u.h b/drivers/media/usb/dvb-usb/dtt200u.h index 005b0a7df358..efccc399b1cb 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.h +++ b/drivers/media/usb/dvb-usb/dtt200u.h @@ -1,7 +1,7 @@ /* Common header file of Linux driver for the WideView/ Yakumo/ Hama/ * Typhoon/ Yuan DVB-T USB2.0 receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 diff --git a/drivers/media/usb/dvb-usb/dvb-usb-common.h b/drivers/media/usb/dvb-usb/dvb-usb-common.h index 6b7b2a89242e..7e619d638809 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-common.h +++ b/drivers/media/usb/dvb-usb/dvb-usb-common.h @@ -1,6 +1,6 @@ /* dvb-usb-common.h is part of the DVB USB library. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * a header file containing prototypes and types for internal use of the dvb-usb-lib diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 9ddfcab268be..71de19ba0e01 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -1,6 +1,6 @@ /* dvb-usb-dvb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c index 733a7ff7b207..dd048a7c461c 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c @@ -1,6 +1,6 @@ /* dvb-usb-firmware.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c index 88e4a62abc44..4f0b0adce7f5 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-i2c.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-i2c.c @@ -1,6 +1,6 @@ /* dvb-usb-i2c.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for (de-)initializing an I2C adapter. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c index 1adf325012f7..3896ba9a4179 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-init.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c @@ -3,7 +3,7 @@ * * dvb-usb-init.c * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -299,6 +299,6 @@ void dvb_usb_device_exit(struct usb_interface *intf) EXPORT_SYMBOL(dvb_usb_device_exit); MODULE_VERSION("1.0"); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c index 7b5dae3077f6..c259f9e43542 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c @@ -1,6 +1,6 @@ /* dvb-usb-remote.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file contains functions for initializing the input-device and for handling remote-control-queries. diff --git a/drivers/media/usb/dvb-usb/dvb-usb-urb.c b/drivers/media/usb/dvb-usb/dvb-usb-urb.c index 5c8f651344fc..95f9097498cb 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-urb.c @@ -1,6 +1,6 @@ /* dvb-usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/dvb-usb.h b/drivers/media/usb/dvb-usb/dvb-usb.h index ce4c4e3b58bb..639c4678c65b 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb.h +++ b/drivers/media/usb/dvb-usb/dvb-usb.h @@ -1,6 +1,6 @@ /* dvb-usb.h is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * the headerfile, all dvb-usb-drivers have to include. diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c index 6c55384e2fca..fc7569e2728d 100644 --- a/drivers/media/usb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -227,7 +227,7 @@ static struct usb_driver nova_t_driver = { module_usb_driver(nova_t_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index f10717311e05..ecc207fbaf3c 100644 --- a/drivers/media/usb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c @@ -820,7 +820,7 @@ static struct usb_driver ttusb2_driver = { module_usb_driver(ttusb2_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/umt-010.c b/drivers/media/usb/dvb-usb/umt-010.c index 9b042292e788..58ad5b4f856c 100644 --- a/drivers/media/usb/dvb-usb/umt-010.c +++ b/drivers/media/usb/dvb-usb/umt-010.c @@ -1,7 +1,7 @@ /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * 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 @@ -145,7 +145,7 @@ static struct usb_driver umt_driver = { module_usb_driver(umt_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/usb-urb.c b/drivers/media/usb/dvb-usb/usb-urb.c index d62ee0f5a165..89173603be67 100644 --- a/drivers/media/usb/dvb-usb/usb-urb.c +++ b/drivers/media/usb/dvb-usb/usb-urb.c @@ -1,6 +1,6 @@ /* usb-urb.c is part of the DVB USB library. * - * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) * see dvb-usb-init.c for copyright information. * * This file keeps functions for initializing and handling the diff --git a/drivers/media/usb/dvb-usb/vp702x-fe.c b/drivers/media/usb/dvb-usb/vp702x-fe.c index d361a72ca0fa..27398c08c69d 100644 --- a/drivers/media/usb/dvb-usb/vp702x-fe.c +++ b/drivers/media/usb/dvb-usb/vp702x-fe.c @@ -4,7 +4,7 @@ * Copyright (C) 2005 Ralph Metzler * Metzler Brothers Systementwicklung GbR * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * Thanks to Twinhan who kindly provided hardware and information. * diff --git a/drivers/media/usb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c index ee1e19e36445..40de33de90a7 100644 --- a/drivers/media/usb/dvb-usb/vp702x.c +++ b/drivers/media/usb/dvb-usb/vp702x.c @@ -4,7 +4,7 @@ * Copyright (C) 2005 Ralph Metzler * Metzler Brothers Systementwicklung GbR * - * Copyright (C) 2005 Patrick Boettcher + * Copyright (C) 2005 Patrick Boettcher * * Thanks to Twinhan who kindly provided hardware and information. * @@ -439,7 +439,7 @@ static struct usb_driver vp702x_usb_driver = { module_usb_driver(vp702x_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/vp7045-fe.c b/drivers/media/usb/dvb-usb/vp7045-fe.c index e708afc6a57f..7765602ea658 100644 --- a/drivers/media/usb/dvb-usb/vp7045-fe.c +++ b/drivers/media/usb/dvb-usb/vp7045-fe.c @@ -1,7 +1,7 @@ /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0 * DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * diff --git a/drivers/media/usb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c index d750724132ee..13340af0d39c 100644 --- a/drivers/media/usb/dvb-usb/vp7045.c +++ b/drivers/media/usb/dvb-usb/vp7045.c @@ -2,7 +2,7 @@ * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver * - DigitalNow TinyUSB2 DVB-t receiver * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * @@ -296,7 +296,7 @@ static struct usb_driver vp7045_usb_driver = { module_usb_driver(vp7045_usb_driver); -MODULE_AUTHOR("Patrick Boettcher "); +MODULE_AUTHOR("Patrick Boettcher "); MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0"); MODULE_VERSION("1.0"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/usb/dvb-usb/vp7045.h b/drivers/media/usb/dvb-usb/vp7045.h index cf5ec46f8bb1..66499932ca76 100644 --- a/drivers/media/usb/dvb-usb/vp7045.h +++ b/drivers/media/usb/dvb-usb/vp7045.h @@ -1,7 +1,7 @@ /* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII * USB2.0 DVB-T receiver. * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) + * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) * * Thanks to Twinhan who kindly provided hardware and information. * -- cgit From 91be260faaf8561dc51e72033c346f6ab28d40d8 Mon Sep 17 00:00:00 2001 From: Nicolas Sugino Date: Thu, 26 Nov 2015 19:00:28 -0200 Subject: [media] dib8000: Add support for Mygica/Geniatech S2870 MyGica/Geniatech S2870 is very similar to the S870 but with dual tuner. The card is recognised as Geniatech STK8096-PVR. [mchehab@osg.samsung.com: Fix some checkpatch.pl issues] Signed-off-by: Nicolas Sugino Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb/dib0700_devices.c | 77 ++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 474582231b5d..7f5d0865acfd 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -118,6 +118,7 @@ #define USB_PID_DIBCOM_STK807XP 0x1f90 #define USB_PID_DIBCOM_STK807XPVR 0x1f98 #define USB_PID_DIBCOM_STK8096GP 0x1fa0 +#define USB_PID_DIBCOM_STK8096PVR 0x1faa #define USB_PID_DIBCOM_NIM8096MD 0x1fa8 #define USB_PID_DIBCOM_TFE8096P 0x1f9C #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 7ed49646a699..ea0391e32d23 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -1736,8 +1736,13 @@ static int dib809x_tuner_attach(struct dvb_usb_adapter *adap) struct dib0700_adapter_state *st = adap->priv; struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1); - if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) - return -ENODEV; + if (adap->id == 0) { + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + } else { + if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL) + return -ENODEV; + } st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params; adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override; @@ -1773,6 +1778,20 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap) return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; } +static int stk809x_frontend1_attach(struct dvb_usb_adapter *adap) +{ + struct dib0700_adapter_state *state = adap->priv; + + if (!dvb_attach(dib8000_attach, &state->dib8000_ops)) + return -ENODEV; + + state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x82, 0); + + adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]); + + return adap->fe_adap[0].fe == NULL ? -ENODEV : 0; +} + static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap) { struct dib0700_adapter_state *st = adap->priv; @@ -3794,6 +3813,7 @@ struct usb_device_id dib0700_usb_id_table[] = { /* 80 */{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_DTT_2) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E) }, { USB_DEVICE(USB_VID_PCTV, USB_PID_PCTV_2002E_SE) }, + { USB_DEVICE(USB_VID_PCTV, USB_PID_DIBCOM_STK8096PVR) }, { 0 } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); @@ -4959,6 +4979,59 @@ struct dvb_usb_device_properties dib0700_devices[] = { RC_BIT_NEC, .change_protocol = dib0700_change_protocol, }, + }, { DIB0700_DEFAULT_DEVICE_PROPERTIES, + .num_adapters = 2, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x02), + } }, + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, { + .num_frontends = 1, + .fe = { { + .caps = DVB_USB_ADAP_HAS_PID_FILTER | + DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF, + .pid_filter_count = 32, + .pid_filter = stk80xx_pid_filter, + .pid_filter_ctrl = stk80xx_pid_filter_ctrl, + .frontend_attach = stk809x_frontend1_attach, + .tuner_attach = dib809x_tuner_attach, + + DIB0700_DEFAULT_STREAMING_CONFIG(0x03), + } }, + .size_of_priv = + sizeof(struct dib0700_adapter_state), + }, + }, + .num_device_descs = 1, + .devices = { + { "DiBcom STK8096-PVR reference design", + { &dib0700_usb_id_table[83], NULL }, + { NULL }, + }, + }, + + .rc.core = { + .rc_interval = DEFAULT_RC_INTERVAL, + .rc_codes = RC_MAP_DIB0700_RC5_TABLE, + .module_name = "dib0700", + .rc_query = dib0700_rc_query_old_firmware, + .allowed_protos = RC_BIT_RC5 | + RC_BIT_RC6_MCE | + RC_BIT_NEC, + .change_protocol = dib0700_change_protocol, + }, }, }; -- cgit From 33cb54015f5eebceb360443498430bdfab79778c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 27 Nov 2015 19:38:44 -0200 Subject: [media] media: rc: nuvoton: mark wakeup-related resources When requesting resources use different names for the normal and the wakeup part. This makes it easier to interpret the output of e.g. /proc/interrupts and /proc/ioports. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 18adf580f502..081435cda30c 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1079,12 +1079,12 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) goto exit_unregister_device; if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr, - CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) + CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake")) goto exit_unregister_device; if (devm_request_irq(&pdev->dev, nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, - NVT_DRIVER_NAME, (void *)nvt)) + NVT_DRIVER_NAME "-wake", (void *)nvt)) goto exit_unregister_device; device_init_wakeup(&pdev->dev, true); -- cgit From 464254e5dbd60124936d47be6679a23b42840b51 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 27 Nov 2015 20:02:38 -0200 Subject: [media] media: rc: raw: improve FIFO handling The FIFO is used for ir_raw_event records, however for some historic reason the FIFO is used on a per byte basis. IMHO this adds unneeded complexity. Therefore set up the FIFO for ir_raw_event records. This also allows to define the FIFO statically as part of ir_raw_event_ctrl instead of having to allocate the FIFO dynamically. In addition: - When writing into the FIFO and it's full return ENOSPC instead of ENOMEM thus making it easier to tell between "FIFO full" and "Dynamic memory allocation failed" when the error is propagated to a higher level. Also add an error message. - When reading from the FIFO check whether it's empty. This is not strictly needed here but kfifo_out is annotated "must check" anyway. Successfully tested it with the nuvoton-cir driver. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/rc-core-priv.h | 6 +++++- drivers/media/rc/rc-ir-raw.c | 23 ++++++++--------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 7359f3d03b64..585d5e52118d 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -16,6 +16,9 @@ #ifndef _RC_CORE_PRIV #define _RC_CORE_PRIV +/* Define the max number of pulse/space transitions to buffer */ +#define MAX_IR_EVENT_SIZE 512 + #include #include #include @@ -35,7 +38,8 @@ struct ir_raw_event_ctrl { struct list_head list; /* to keep track of raw clients */ struct task_struct *thread; spinlock_t lock; - struct kfifo_rec_ptr_1 kfifo; /* fifo for the pulse/space durations */ + /* fifo for the pulse/space durations */ + DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE); ktime_t last_event; /* when last event occurred */ enum raw_event_type last_type; /* last event type */ struct rc_dev *dev; /* pointer to the parent rc_dev */ diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c index c69807fe2fef..144304c94606 100644 --- a/drivers/media/rc/rc-ir-raw.c +++ b/drivers/media/rc/rc-ir-raw.c @@ -20,9 +20,6 @@ #include #include "rc-core-priv.h" -/* Define the max number of pulse/space transitions to buffer */ -#define MAX_IR_EVENT_SIZE 512 - /* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */ static LIST_HEAD(ir_raw_client_list); @@ -36,14 +33,12 @@ static int ir_raw_event_thread(void *data) struct ir_raw_event ev; struct ir_raw_handler *handler; struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; - int retval; while (!kthread_should_stop()) { spin_lock_irq(&raw->lock); - retval = kfifo_len(&raw->kfifo); - if (retval < sizeof(ev)) { + if (!kfifo_len(&raw->kfifo)) { set_current_state(TASK_INTERRUPTIBLE); if (kthread_should_stop()) @@ -54,7 +49,8 @@ static int ir_raw_event_thread(void *data) continue; } - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); + if(!kfifo_out(&raw->kfifo, &ev, 1)) + dev_err(&raw->dev->dev, "IR event FIFO is empty!\n"); spin_unlock_irq(&raw->lock); mutex_lock(&ir_raw_handler_lock); @@ -87,8 +83,10 @@ int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev) IR_dprintk(2, "sample: (%05dus %s)\n", TO_US(ev->duration), TO_STR(ev->pulse)); - if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) - return -ENOMEM; + if (!kfifo_put(&dev->raw->kfifo, *ev)) { + dev_err(&dev->dev, "IR event FIFO is full!\n"); + return -ENOSPC; + } return 0; } @@ -273,11 +271,7 @@ int ir_raw_event_register(struct rc_dev *dev) dev->raw->dev = dev; dev->change_protocol = change_protocol; - rc = kfifo_alloc(&dev->raw->kfifo, - sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE, - GFP_KERNEL); - if (rc < 0) - goto out; + INIT_KFIFO(dev->raw->kfifo); spin_lock_init(&dev->raw->lock); dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw, @@ -319,7 +313,6 @@ void ir_raw_event_unregister(struct rc_dev *dev) handler->raw_unregister(dev); mutex_unlock(&ir_raw_handler_lock); - kfifo_free(&dev->raw->kfifo); kfree(dev->raw); dev->raw = NULL; } -- cgit From eac6d4081d7c3bae0e220859b5a0422cd53f00d8 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Tue, 5 Jan 2016 13:12:21 +0100 Subject: crypto: ansi_cprng - ANSI X9.31 DRNG is not allowed in FIPS 140-2 As per update of the FIPS 140-2 Annex C supported by SP800-131A, the ANSI X9.31 DRNG is not an allowed cipher in FIPS mode any more. CC: Neil Horman Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/testmgr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index ae8c57fd8bc7..5c0963d17de7 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2081,7 +2081,6 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "ansi_cprng", .test = alg_test_cprng, - .fips_allowed = 1, .suite = { .cprng = { .vecs = ansi_cprng_aes_tv_template, -- cgit From a2f5106f0de9ca684b8f6daef49cb1236035712e Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 5 Jan 2016 11:14:55 -0800 Subject: crypto: qat - change name for c6xx dev type change name for c6x dev type to more generic. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_accel_devices.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h index f96d427e502c..5a07208ce778 100644 --- a/drivers/crypto/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h @@ -55,8 +55,8 @@ #define ADF_DH895XCC_DEVICE_NAME "dh895xcc" #define ADF_DH895XCCVF_DEVICE_NAME "dh895xccvf" -#define ADF_C62X_DEVICE_NAME "c62x" -#define ADF_C62XVF_DEVICE_NAME "c62xvf" +#define ADF_C62X_DEVICE_NAME "c6xx" +#define ADF_C62XVF_DEVICE_NAME "c6xxvf" #define ADF_C3XXX_DEVICE_NAME "c3xxx" #define ADF_C3XXXVF_DEVICE_NAME "c3xxxvf" #define ADF_DH895XCC_PCI_DEVICE_ID 0x435 -- cgit From 718837c88bf76e3374fc5a3e2b85cd88d1fc2edb Mon Sep 17 00:00:00 2001 From: Pingchao Yang Date: Wed, 6 Jan 2016 17:56:20 +0800 Subject: crypto: qat - remove redundant function call adf_dev_restore(accel_dev) was called in adf_dev_shutdown,no need to call it in adf_device_reset_worker after adf_dev_shutdown was called. Signed-off-by: Yang Pingchao Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_aer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/crypto/qat/qat_common/adf_aer.c b/drivers/crypto/qat/qat_common/adf_aer.c index e78a1d7d88fc..b40d9c8dad96 100644 --- a/drivers/crypto/qat/qat_common/adf_aer.c +++ b/drivers/crypto/qat/qat_common/adf_aer.c @@ -121,7 +121,6 @@ static void adf_device_reset_worker(struct work_struct *work) adf_dev_restarting_notify(accel_dev); adf_dev_stop(accel_dev); adf_dev_shutdown(accel_dev); - adf_dev_restore(accel_dev); if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) { /* The device hanged and we can't restart it so stop here */ dev_err(&GET_DEV(accel_dev), "Restart device failed\n"); -- cgit From 313becd1ff0eebcc3ee6e6d7e00b3da2f980bb18 Mon Sep 17 00:00:00 2001 From: Krzysztof Koz?owski Date: Mon, 11 Jan 2016 20:45:50 +0900 Subject: crypto: s5p-sss - Fix minor coding style violations Improve a little bit code readability and use dev_info/err for printing messages. Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index f214a8755827..e10284744fd2 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -224,6 +224,7 @@ static inline struct samsung_aes_variant *find_s5p_sss_version { if (IS_ENABLED(CONFIG_OF) && (pdev->dev.of_node)) { const struct of_device_id *match; + match = of_match_node(s5p_sss_dt_match, pdev->dev.of_node); return (struct samsung_aes_variant *)match->data; @@ -397,7 +398,6 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) { struct ablkcipher_request *req = dev->req; - uint32_t aes_control; int err; unsigned long flags; @@ -518,7 +518,7 @@ static int s5p_aes_crypt(struct ablkcipher_request *req, unsigned long mode) struct s5p_aes_dev *dev = ctx->dev; if (!IS_ALIGNED(req->nbytes, AES_BLOCK_SIZE)) { - pr_err("request size is not exact amount of AES blocks\n"); + dev_err(dev->dev, "request size is not exact amount of AES blocks\n"); return -EINVAL; } @@ -566,7 +566,7 @@ static int s5p_aes_cbc_decrypt(struct ablkcipher_request *req) static int s5p_aes_cra_init(struct crypto_tfm *tfm) { - struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); + struct s5p_aes_ctx *ctx = crypto_tfm_ctx(tfm); ctx->dev = s5p_dev; tfm->crt_ablkcipher.reqsize = sizeof(struct s5p_aes_reqctx); @@ -701,7 +701,7 @@ static int s5p_aes_probe(struct platform_device *pdev) goto err_algs; } - pr_info("s5p-sss driver registered\n"); + dev_info(dev, "s5p-sss driver registered\n"); return 0; -- cgit From 1e3012d0fdc5e06309c3031e0989a4b564504713 Mon Sep 17 00:00:00 2001 From: Krzysztof Koz?owski Date: Mon, 11 Jan 2016 20:45:51 +0900 Subject: crypto: s5p-sss - Use memcpy_toio for iomem annotated memory Use memcpy_toio to fix following sparse warning: drivers/crypto/s5p-sss.c:386:40: warning: incorrect type in argument 1 (different address spaces) drivers/crypto/s5p-sss.c:386:40: expected void * drivers/crypto/s5p-sss.c:386:40: got void [noderef] * Signed-off-by: Krzysztof Kozlowski Acked-by: Vladimir Zapolskiy Signed-off-by: Herbert Xu --- drivers/crypto/s5p-sss.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index e10284744fd2..5f161a9777e3 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -383,7 +383,7 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, void __iomem *keystart; if (iv) - memcpy(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10); + memcpy_toio(dev->aes_ioaddr + SSS_REG_AES_IV_DATA(0), iv, 0x10); if (keylen == AES_KEYSIZE_256) keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(0); @@ -392,7 +392,7 @@ static void s5p_set_aes(struct s5p_aes_dev *dev, else keystart = dev->aes_ioaddr + SSS_REG_AES_KEY_DATA(4); - memcpy(keystart, key, keylen); + memcpy_toio(keystart, key, keylen); } static void s5p_aes_crypt_start(struct s5p_aes_dev *dev, unsigned long mode) -- cgit From ba171135bfa584096ca5ee42c9527777b7d48474 Mon Sep 17 00:00:00 2001 From: "Atta, Ahsan" Date: Mon, 11 Jan 2016 15:23:47 +0000 Subject: crypto: qat - Pack cfg ctl structs -This is required to support 32bit adf_ctl utility on a 64bit driver Signed-off-by: Ahsan Atta Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/adf_cfg_user.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/qat/qat_common/adf_cfg_user.h b/drivers/crypto/qat/qat_common/adf_cfg_user.h index ef5988afd4c6..b5484bfa6996 100644 --- a/drivers/crypto/qat/qat_common/adf_cfg_user.h +++ b/drivers/crypto/qat/qat_common/adf_cfg_user.h @@ -58,7 +58,7 @@ struct adf_user_cfg_key_val { uint64_t padding3; }; enum adf_cfg_val_type type; -}; +} __packed; struct adf_user_cfg_section { char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES]; @@ -70,7 +70,7 @@ struct adf_user_cfg_section { struct adf_user_cfg_section *next; uint64_t padding3; }; -}; +} __packed; struct adf_user_cfg_ctl_data { union { @@ -78,5 +78,5 @@ struct adf_user_cfg_ctl_data { uint64_t padding; }; uint8_t device_id; -}; +} __packed; #endif -- cgit From 624144a7eb2c9abcf76722d29f983cdf9801bb2e Mon Sep 17 00:00:00 2001 From: Horia Geant? Date: Tue, 12 Jan 2016 17:14:10 +0200 Subject: crypto: caam - enable LARGE_BURST for enhancing DMA transactions size Increasing CAAM DMA engine transaction size either -reduces the number of required transactions or -adds the ability to transfer more data with same transaction count Signed-off-by: Horia Geant? Signed-off-by: Herbert Xu --- drivers/crypto/caam/ctrl.c | 2 +- drivers/crypto/caam/regs.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 69d4a1326fee..44d30b45f3cc 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -534,7 +534,7 @@ static int caam_probe(struct platform_device *pdev) * long pointers in master configuration register */ clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH | - MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE | + MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE | MCFGR_LARGE_BURST | (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0)); /* diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index a8a79975682f..0ba9c40597dc 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -455,7 +455,8 @@ struct caam_ctrl { #define MCFGR_AXIPIPE_MASK (0xf << MCFGR_AXIPIPE_SHIFT) #define MCFGR_AXIPRI 0x00000008 /* Assert AXI priority sideband */ -#define MCFGR_BURST_64 0x00000001 /* Max burst size */ +#define MCFGR_LARGE_BURST 0x00000004 /* 128/256-byte burst size */ +#define MCFGR_BURST_64 0x00000001 /* 64-byte burst size */ /* JRSTART register offsets */ #define JRSTART_JR0_START 0x00000001 /* Start Job ring 0 */ -- cgit From 952bce9792e6bf36fda09c2e5718abb5d9327369 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 12 Jan 2016 11:17:38 -0600 Subject: crypto: ccp - Add hash state import and export support Commit 8996eafdcbad ("crypto: ahash - ensure statesize is non-zero") added a check to prevent ahash algorithms from successfully registering if the import and export functions were not implemented. This prevents an oops in the hash_accept function of algif_hash. This commit causes the ccp-crypto module SHA support and AES CMAC support from successfully registering and causing the ccp-crypto module load to fail because the ahash import and export functions are not implemented. Update the CCP Crypto API support to provide import and export support for ahash algorithms. Cc: # 3.14.x- Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 23 +++++++++++++++++++++++ drivers/crypto/ccp/ccp-crypto-sha.c | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index d89f20c04266..00207cf5c79b 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -220,6 +220,26 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) return ccp_aes_cmac_finup(req); } +static int ccp_aes_cmac_export(struct ahash_request *req, void *out) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_aes_cmac_req_ctx *state = out; + + *state = *rctx; + + return 0; +} + +static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) +{ + struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); + const struct ccp_aes_cmac_req_ctx *state = in; + + *rctx = *state; + + return 0; +} + static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int key_len) { @@ -352,10 +372,13 @@ int ccp_register_aes_cmac_algs(struct list_head *head) alg->final = ccp_aes_cmac_final; alg->finup = ccp_aes_cmac_finup; alg->digest = ccp_aes_cmac_digest; + alg->export = ccp_aes_cmac_export; + alg->import = ccp_aes_cmac_import; alg->setkey = ccp_aes_cmac_setkey; halg = &alg->halg; halg->digestsize = AES_BLOCK_SIZE; + halg->statesize = sizeof(struct ccp_aes_cmac_req_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index d14b3f28e010..3aae58def106 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -207,6 +207,26 @@ static int ccp_sha_digest(struct ahash_request *req) return ccp_sha_finup(req); } +static int ccp_sha_export(struct ahash_request *req, void *out) +{ + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + struct ccp_sha_req_ctx *state = out; + + *state = *rctx; + + return 0; +} + +static int ccp_sha_import(struct ahash_request *req, const void *in) +{ + struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); + const struct ccp_sha_req_ctx *state = in; + + *rctx = *state; + + return 0; +} + static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key, unsigned int key_len) { @@ -403,9 +423,12 @@ static int ccp_register_sha_alg(struct list_head *head, alg->final = ccp_sha_final; alg->finup = ccp_sha_finup; alg->digest = ccp_sha_digest; + alg->export = ccp_sha_export; + alg->import = ccp_sha_import; halg = &alg->halg; halg->digestsize = def->digest_size; + halg->statesize = sizeof(struct ccp_sha_req_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); -- cgit From 1900c583c8e24df9d07282598166279187dce832 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:31 +0100 Subject: crypto: atmel-sha - fix crash when computing digest on empty message This patch fixes a crash which occured during the computation of the digest of an empty message. Indeed, when processing an empty message, the atmel_sha_handle_queue() function was never called, hence the dd->req pointer remained uninitialized. Later, when the atmel_sha_final_req() function was called, it used to crash while using this uninitialized dd->req pointer. Hence this patch adds missing initializations of dd->req before calls of the atmel_sha_final_req() function. This bug prevented us from passing the tcrypt test suite on SHA algo. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 20de861aa0ea..006b2aefba30 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -939,6 +939,7 @@ static int atmel_sha_final(struct ahash_request *req) if (err) goto err1; + dd->req = req; dd->flags |= SHA_FLAGS_BUSY; err = atmel_sha_final_req(dd); } else { -- cgit From f56809c3c6059327aad3e0718bca9c6c756386f6 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:32 +0100 Subject: crypto: atmel-sha - fix a race between the 'done' tasklet and the crypto client The 'done' tasklet handler used to check the 'BUSY' flag to either finalize the processing of a crypto request which had just completed or manage the crypto queue to start the next crypto request. On request R1 completion, the driver calls atmel_sha_finish_req(), which: 1 - clears the 'BUSY' flag since the hardware is no longer used and is ready again to process new crypto requests. 2 - notifies the above layer (the client) about the completion of the asynchronous crypto request R1 by calling its base.complete() callback. 3 - schedules the 'done' task to check the crypto queue and start to process the next crypto request (the 'BUSY' flag is supposed to be cleared at that moment) if such a pending request exists. However step 2 might wake the client up so it can now ask our driver to process a new crypto request R2. This request is enqueued by calling the atmel_sha_handle_queue() function, which sets the 'BUSY' flags then starts to process R2. If the 'done' tasklet, scheduled by step 3, runs just after, it would see that the 'BUSY' flag is set then understand that R2 has just completed, which is wrong! So the state of 'BUSY' flag is not a proper way to detect and handle crypto request completion. This patch fixes this race condition by using two different tasklets, one to handle the crypto request completion events, the other to manage the crypto queue if needed. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 006b2aefba30..75a8cbcf3121 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -122,6 +122,7 @@ struct atmel_sha_dev { spinlock_t lock; int err; struct tasklet_struct done_task; + struct tasklet_struct queue_task; unsigned long flags; struct crypto_queue queue; @@ -788,7 +789,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err) req->base.complete(&req->base, err); /* handle new request */ - tasklet_schedule(&dd->done_task); + tasklet_schedule(&dd->queue_task); } static int atmel_sha_hw_init(struct atmel_sha_dev *dd) @@ -1101,16 +1102,18 @@ static struct ahash_alg sha_384_512_algs[] = { }, }; +static void atmel_sha_queue_task(unsigned long data) +{ + struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data; + + atmel_sha_handle_queue(dd, NULL); +} + static void atmel_sha_done_task(unsigned long data) { struct atmel_sha_dev *dd = (struct atmel_sha_dev *)data; int err = 0; - if (!(SHA_FLAGS_BUSY & dd->flags)) { - atmel_sha_handle_queue(dd, NULL); - return; - } - if (SHA_FLAGS_CPU & dd->flags) { if (SHA_FLAGS_OUTPUT_READY & dd->flags) { dd->flags &= ~SHA_FLAGS_OUTPUT_READY; @@ -1367,6 +1370,8 @@ static int atmel_sha_probe(struct platform_device *pdev) tasklet_init(&sha_dd->done_task, atmel_sha_done_task, (unsigned long)sha_dd); + tasklet_init(&sha_dd->queue_task, atmel_sha_queue_task, + (unsigned long)sha_dd); crypto_init_queue(&sha_dd->queue, ATMEL_SHA_QUEUE_LENGTH); @@ -1459,6 +1464,7 @@ err_algs: atmel_sha_dma_cleanup(sha_dd); err_sha_dma: res_err: + tasklet_kill(&sha_dd->queue_task); tasklet_kill(&sha_dd->done_task); sha_dd_err: dev_err(dev, "initialization failed.\n"); @@ -1479,6 +1485,7 @@ static int atmel_sha_remove(struct platform_device *pdev) atmel_sha_unregister_algs(sha_dd); + tasklet_kill(&sha_dd->queue_task); tasklet_kill(&sha_dd->done_task); if (sha_dd->caps.has_dma) -- cgit From 507c5cc236a2d751ea423a86486a2d1972369549 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:33 +0100 Subject: crypto: atmel-sha - add support of sama5d2x SoCs This patch adds support of hardware version 5.1.x embedded inside sama5d2x SoCs. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 75a8cbcf3121..7327e11e0ccb 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -1279,6 +1279,12 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) /* keep only major version number */ switch (dd->hw_version & 0xff0) { + case 0x510: + dd->caps.has_dma = 1; + dd->caps.has_dualbuff = 1; + dd->caps.has_sha224 = 1; + dd->caps.has_sha_384_512 = 1; + break; case 0x420: dd->caps.has_dma = 1; dd->caps.has_dualbuff = 1; -- cgit From 7cee3508162a1760bc104c48d14202b01af28e53 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 15 Jan 2016 15:49:34 +0100 Subject: crypto: atmel-sha - fix context switches This patch saves the value of the internal hash register at the end of an 'update' operation then restores this value before starting the next 'update'. This way the driver can now properly handle context switches. WARNING: only hardware versions from sama5d4x and later provide the needed interface to update the internal hash value. Especially, sama5d3x cannot implement this feature so context switches are still broken. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha-regs.h | 4 ++ drivers/crypto/atmel-sha.c | 105 ++++++++++++++++++++++++++++++---------- 2 files changed, 84 insertions(+), 25 deletions(-) diff --git a/drivers/crypto/atmel-sha-regs.h b/drivers/crypto/atmel-sha-regs.h index 83b2d7425666..e08897109cab 100644 --- a/drivers/crypto/atmel-sha-regs.h +++ b/drivers/crypto/atmel-sha-regs.h @@ -8,6 +8,8 @@ #define SHA_CR_START (1 << 0) #define SHA_CR_FIRST (1 << 4) #define SHA_CR_SWRST (1 << 8) +#define SHA_CR_WUIHV (1 << 12) +#define SHA_CR_WUIEHV (1 << 13) #define SHA_MR 0x04 #define SHA_MR_MODE_MASK (0x3 << 0) @@ -15,6 +17,8 @@ #define SHA_MR_MODE_AUTO 0x1 #define SHA_MR_MODE_PDC 0x2 #define SHA_MR_PROCDLY (1 << 4) +#define SHA_MR_UIHV (1 << 5) +#define SHA_MR_UIEHV (1 << 6) #define SHA_MR_ALGO_SHA1 (0 << 8) #define SHA_MR_ALGO_SHA256 (1 << 8) #define SHA_MR_ALGO_SHA384 (2 << 8) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 7327e11e0ccb..da4c3055784f 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -53,6 +53,7 @@ #define SHA_FLAGS_FINUP BIT(16) #define SHA_FLAGS_SG BIT(17) +#define SHA_FLAGS_ALGO_MASK GENMASK(22, 18) #define SHA_FLAGS_SHA1 BIT(18) #define SHA_FLAGS_SHA224 BIT(19) #define SHA_FLAGS_SHA256 BIT(20) @@ -60,6 +61,7 @@ #define SHA_FLAGS_SHA512 BIT(22) #define SHA_FLAGS_ERROR BIT(23) #define SHA_FLAGS_PAD BIT(24) +#define SHA_FLAGS_RESTORE BIT(25) #define SHA_OP_UPDATE 1 #define SHA_OP_FINAL 2 @@ -73,6 +75,7 @@ struct atmel_sha_caps { bool has_dualbuff; bool has_sha224; bool has_sha_384_512; + bool has_uihv; }; struct atmel_sha_dev; @@ -318,7 +321,8 @@ static int atmel_sha_init(struct ahash_request *req) static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma) { struct atmel_sha_reqctx *ctx = ahash_request_ctx(dd->req); - u32 valcr = 0, valmr = SHA_MR_MODE_AUTO; + u32 valmr = SHA_MR_MODE_AUTO; + unsigned int i, hashsize = 0; if (likely(dma)) { if (!dd->caps.has_dma) @@ -330,22 +334,62 @@ static void atmel_sha_write_ctrl(struct atmel_sha_dev *dd, int dma) atmel_sha_write(dd, SHA_IER, SHA_INT_DATARDY); } - if (ctx->flags & SHA_FLAGS_SHA1) + switch (ctx->flags & SHA_FLAGS_ALGO_MASK) { + case SHA_FLAGS_SHA1: valmr |= SHA_MR_ALGO_SHA1; - else if (ctx->flags & SHA_FLAGS_SHA224) + hashsize = SHA1_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA224: valmr |= SHA_MR_ALGO_SHA224; - else if (ctx->flags & SHA_FLAGS_SHA256) + hashsize = SHA256_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA256: valmr |= SHA_MR_ALGO_SHA256; - else if (ctx->flags & SHA_FLAGS_SHA384) + hashsize = SHA256_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA384: valmr |= SHA_MR_ALGO_SHA384; - else if (ctx->flags & SHA_FLAGS_SHA512) + hashsize = SHA512_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA512: valmr |= SHA_MR_ALGO_SHA512; + hashsize = SHA512_DIGEST_SIZE; + break; + + default: + break; + } /* Setting CR_FIRST only for the first iteration */ - if (!(ctx->digcnt[0] || ctx->digcnt[1])) - valcr = SHA_CR_FIRST; + if (!(ctx->digcnt[0] || ctx->digcnt[1])) { + atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST); + } else if (dd->caps.has_uihv && (ctx->flags & SHA_FLAGS_RESTORE)) { + const u32 *hash = (const u32 *)ctx->digest; + + /* + * Restore the hardware context: update the User Initialize + * Hash Value (UIHV) with the value saved when the latest + * 'update' operation completed on this very same crypto + * request. + */ + ctx->flags &= ~SHA_FLAGS_RESTORE; + atmel_sha_write(dd, SHA_CR, SHA_CR_WUIHV); + for (i = 0; i < hashsize / sizeof(u32); ++i) + atmel_sha_write(dd, SHA_REG_DIN(i), hash[i]); + atmel_sha_write(dd, SHA_CR, SHA_CR_FIRST); + valmr |= SHA_MR_UIHV; + } + /* + * WARNING: If the UIHV feature is not available, the hardware CANNOT + * process concurrent requests: the internal registers used to store + * the hash/digest are still set to the partial digest output values + * computed during the latest round. + */ - atmel_sha_write(dd, SHA_CR, valcr); atmel_sha_write(dd, SHA_MR, valmr); } @@ -714,23 +758,31 @@ static void atmel_sha_copy_hash(struct ahash_request *req) { struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); u32 *hash = (u32 *)ctx->digest; - int i; + unsigned int i, hashsize; - if (ctx->flags & SHA_FLAGS_SHA1) - for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else if (ctx->flags & SHA_FLAGS_SHA224) - for (i = 0; i < SHA224_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else if (ctx->flags & SHA_FLAGS_SHA256) - for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else if (ctx->flags & SHA_FLAGS_SHA384) - for (i = 0; i < SHA384_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); - else - for (i = 0; i < SHA512_DIGEST_SIZE / sizeof(u32); i++) - hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); + switch (ctx->flags & SHA_FLAGS_ALGO_MASK) { + case SHA_FLAGS_SHA1: + hashsize = SHA1_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA224: + case SHA_FLAGS_SHA256: + hashsize = SHA256_DIGEST_SIZE; + break; + + case SHA_FLAGS_SHA384: + case SHA_FLAGS_SHA512: + hashsize = SHA512_DIGEST_SIZE; + break; + + default: + /* Should not happen... */ + return; + } + + for (i = 0; i < hashsize / sizeof(u32); ++i) + hash[i] = atmel_sha_read(ctx->dd, SHA_REG_DIGEST(i)); + ctx->flags |= SHA_FLAGS_RESTORE; } static void atmel_sha_copy_ready_hash(struct ahash_request *req) @@ -1276,6 +1328,7 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) dd->caps.has_dualbuff = 0; dd->caps.has_sha224 = 0; dd->caps.has_sha_384_512 = 0; + dd->caps.has_uihv = 0; /* keep only major version number */ switch (dd->hw_version & 0xff0) { @@ -1284,12 +1337,14 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) dd->caps.has_dualbuff = 1; dd->caps.has_sha224 = 1; dd->caps.has_sha_384_512 = 1; + dd->caps.has_uihv = 1; break; case 0x420: dd->caps.has_dma = 1; dd->caps.has_dualbuff = 1; dd->caps.has_sha224 = 1; dd->caps.has_sha_384_512 = 1; + dd->caps.has_uihv = 1; break; case 0x410: dd->caps.has_dma = 1; -- cgit From 3947b335bba390701619bd5c76ed8016f71d3017 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:54 +0100 Subject: hwrng: bcm63xx - remove unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These variables where left as unused in commit 6229c16060fe ("hwrng: bcm63xx - make use of devm_hwrng_register") Fixes the following warning: drivers/char/hw_random/bcm63xx-rng.c: In function 'bcm63xx_rng_probe': drivers/char/hw_random/bcm63xx-rng.c:85:16: warning: unused variable 'rng' [-Wunused-variable] struct hwrng *rng; ^ drivers/char/hw_random/bcm63xx-rng.c:82:14: warning: unused variable 'clk' [-Wunused-variable] struct clk *clk; Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Herbert Xu --- drivers/char/hw_random/bcm63xx-rng.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index 4b31f1387f37..c303f302fb0b 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -79,10 +79,8 @@ static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) static int bcm63xx_rng_probe(struct platform_device *pdev) { struct resource *r; - struct clk *clk; int ret; struct bcm63xx_rng_priv *priv; - struct hwrng *rng; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { -- cgit From 7b651706712b9774e77d89654949a5b1926d73db Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:55 +0100 Subject: hwrng: bcm63xx - add device tree support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds device tree support for BCM6368, which seems to be the only BCM63xx with bcm63xx-rng support. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Herbert Xu --- drivers/char/hw_random/bcm63xx-rng.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index c303f302fb0b..38553f0500c9 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -130,10 +130,17 @@ static int bcm63xx_rng_probe(struct platform_device *pdev) return 0; } +static const struct of_device_id bcm63xx_rng_of_match[] = { + { .compatible = "brcm,bcm6368-rng", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm63xx_rng_of_match); + static struct platform_driver bcm63xx_rng_driver = { .probe = bcm63xx_rng_probe, .driver = { .name = "bcm63xx-rng", + .of_match_table = bcm63xx_rng_of_match, }, }; -- cgit From 90859e6628dcf54a93a5f2017f7b19bc29c2e413 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:56 +0100 Subject: hwrng: bcm63xx - allow building for BMIPS_GENERIC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have device tree support and BCM6368 is supported in BMIPS_GENERIC, we can use it for BMIPS_GENERIC too. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index dbf22719462f..8d895908d608 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -77,7 +77,7 @@ config HW_RANDOM_ATMEL config HW_RANDOM_BCM63XX tristate "Broadcom BCM63xx Random Number Generator support" - depends on BCM63XX + depends on BCM63XX || BMIPS_GENERIC default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number -- cgit From 9dbcc215ad2cee4c07da359cc9e7ac315d031f1d Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sun, 17 Jan 2016 10:03:57 +0100 Subject: hwrng: brcm63xx - document device tree bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents device tree bindings for random number generator present on Broadcom BCM6368 SoC. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Acked-by: Rob Herring Signed-off-by: Herbert Xu --- Documentation/devicetree/bindings/rng/brcm,bcm6368.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Documentation/devicetree/bindings/rng/brcm,bcm6368.txt diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm6368.txt b/Documentation/devicetree/bindings/rng/brcm,bcm6368.txt new file mode 100644 index 000000000000..4b5ac600bfbd --- /dev/null +++ b/Documentation/devicetree/bindings/rng/brcm,bcm6368.txt @@ -0,0 +1,17 @@ +BCM6368 Random number generator + +Required properties: + +- compatible : should be "brcm,bcm6368-rng" +- reg : Specifies base physical address and size of the registers +- clocks : phandle to clock-controller plus clock-specifier pair +- clock-names : "ipsec" as a clock name + +Example: + random: rng@10004180 { + compatible = "brcm,bcm6368-rng"; + reg = <0x10004180 0x14>; + + clocks = <&periph_clk 18>; + clock-names = "ipsec"; + }; -- cgit From 0f987e25cb8a9c23bfd70942a580c2698444e4b4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 19 Jan 2016 09:00:21 +0800 Subject: crypto: ixp4xx - Fix false lastlen uninitialised warning This patch fixes a false positive uninitialised variable warning in aead_perform by moving the source processing in front of the destination processing, thus ensuring that the initialisation of lastlen is always visible to gcc. Reported-by: Arnd Bergmann Signed-off-by: Herbert Xu Acked-by: Arnd Bergmann --- drivers/crypto/ixp4xx_crypto.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index e52496a172d0..2296934455fc 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -1031,6 +1031,18 @@ static int aead_perform(struct aead_request *req, int encrypt, BUG_ON(ivsize && !req->iv); memcpy(crypt->iv, req->iv, ivsize); + buf = chainup_buffers(dev, req->src, crypt->auth_len, + &src_hook, flags, src_direction); + req_ctx->src = src_hook.next; + crypt->src_buf = src_hook.phys_next; + if (!buf) + goto free_buf_src; + + lastlen = buf->buf_len; + if (lastlen >= authsize) + crypt->icv_rev_aes = buf->phys_addr + + buf->buf_len - authsize; + req_ctx->dst = NULL; if (req->src != req->dst) { @@ -1055,20 +1067,6 @@ static int aead_perform(struct aead_request *req, int encrypt, } } - buf = chainup_buffers(dev, req->src, crypt->auth_len, - &src_hook, flags, src_direction); - req_ctx->src = src_hook.next; - crypt->src_buf = src_hook.phys_next; - if (!buf) - goto free_buf_src; - - if (!encrypt || !req_ctx->dst) { - lastlen = buf->buf_len; - if (lastlen >= authsize) - crypt->icv_rev_aes = buf->phys_addr + - buf->buf_len - authsize; - } - if (unlikely(lastlen < authsize)) { /* The 12 hmac bytes are scattered, * we need to copy them into a safe buffer */ -- cgit From 7768fb2ee9e907bfa91d13cb698fa68880ddc80a Mon Sep 17 00:00:00 2001 From: "Cabiddu, Giovanni" Date: Tue, 19 Jan 2016 17:34:04 +0000 Subject: crypto: qat - Reduced reqsize in qat_algs req_alloc functions already take into account the request data structure when allocating memory. Signed-off-by: Giovanni Cabiddu Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/qat/qat_common/qat_algs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c index 59e4c3af15ed..1e8852a8a057 100644 --- a/drivers/crypto/qat/qat_common/qat_algs.c +++ b/drivers/crypto/qat/qat_common/qat_algs.c @@ -1064,8 +1064,7 @@ static int qat_alg_aead_init(struct crypto_aead *tfm, if (IS_ERR(ctx->hash_tfm)) return PTR_ERR(ctx->hash_tfm); ctx->qat_hash_alg = hash; - crypto_aead_set_reqsize(tfm, sizeof(struct aead_request) + - sizeof(struct qat_crypto_request)); + crypto_aead_set_reqsize(tfm, sizeof(struct qat_crypto_request)); return 0; } @@ -1114,8 +1113,7 @@ static int qat_alg_ablkcipher_init(struct crypto_tfm *tfm) struct qat_alg_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm); spin_lock_init(&ctx->lock); - tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) + - sizeof(struct qat_crypto_request); + tfm->crt_ablkcipher.reqsize = sizeof(struct qat_crypto_request); ctx->tfm = tfm; return 0; } -- cgit From 973fb3fb50e3959d90179d09ed3ce454dd7bc6e4 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 21 Jan 2016 17:10:56 +0800 Subject: crypto: skcipher - Add default key size helper While converting ecryptfs over to skcipher I found that it needs to pick a default key size if one isn't given. Rather than having it poke into the guts of the algorithm to get max_keysize, let's provide a helper that is meant to give a sane default (just in case we ever get an algorithm that has no maximum key size). Signed-off-by: Herbert Xu --- crypto/skcipher.c | 4 ++-- include/crypto/skcipher.h | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index d199c0b1751c..69230e9d4ac9 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -118,7 +118,7 @@ static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm) skcipher->decrypt = skcipher_decrypt_blkcipher; skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher); - skcipher->has_setkey = calg->cra_blkcipher.max_keysize; + skcipher->keysize = calg->cra_blkcipher.max_keysize; return 0; } @@ -211,7 +211,7 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm) skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher); skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) + sizeof(struct ablkcipher_request); - skcipher->has_setkey = calg->cra_ablkcipher.max_keysize; + skcipher->keysize = calg->cra_ablkcipher.max_keysize; return 0; } diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index fd8742a40ff3..2f07b4fce3e0 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -60,8 +60,7 @@ struct crypto_skcipher { unsigned int ivsize; unsigned int reqsize; - - bool has_setkey; + unsigned int keysize; struct crypto_tfm base; }; @@ -309,7 +308,13 @@ static inline int crypto_skcipher_setkey(struct crypto_skcipher *tfm, static inline bool crypto_skcipher_has_setkey(struct crypto_skcipher *tfm) { - return tfm->has_setkey; + return tfm->keysize; +} + +static inline unsigned int crypto_skcipher_default_keysize( + struct crypto_skcipher *tfm) +{ + return tfm->keysize; } /** -- cgit From b3614763059b82c26bdd02ffcb1c016c1132aad0 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 22 Jan 2016 09:52:28 +0100 Subject: crypto: drbg - remove FIPS 140-2 continuous test The newly released FIPS 140-2 IG 9.8 specifies that for SP800-90A compliant DRBGs, the FIPS 140-2 continuous random number generator test is not required any more. This patch removes the test and all associated data structures. Signed-off-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/drbg.c | 64 --------------------------------------------------- include/crypto/drbg.h | 4 ---- 2 files changed, 68 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index ab6ef1d08568..1b86310db7b1 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -219,48 +219,6 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) } } -/* - * FIPS 140-2 continuous self test - * The test is performed on the result of one round of the output - * function. Thus, the function implicitly knows the size of the - * buffer. - * - * @drbg DRBG handle - * @buf output buffer of random data to be checked - * - * return: - * true on success - * false on error - */ -static bool drbg_fips_continuous_test(struct drbg_state *drbg, - const unsigned char *buf) -{ -#ifdef CONFIG_CRYPTO_FIPS - int ret = 0; - /* skip test if we test the overall system */ - if (list_empty(&drbg->test_data.list)) - return true; - /* only perform test in FIPS mode */ - if (0 == fips_enabled) - return true; - if (!drbg->fips_primed) { - /* Priming of FIPS test */ - memcpy(drbg->prev, buf, drbg_blocklen(drbg)); - drbg->fips_primed = true; - /* return false due to priming, i.e. another round is needed */ - return false; - } - ret = memcmp(drbg->prev, buf, drbg_blocklen(drbg)); - if (!ret) - panic("DRBG continuous self test failed\n"); - memcpy(drbg->prev, buf, drbg_blocklen(drbg)); - /* the test shall pass when the two compared values are not equal */ - return ret != 0; -#else - return true; -#endif /* CONFIG_CRYPTO_FIPS */ -} - /* * Convert an integer into a byte representation of this integer. * The byte representation is big-endian @@ -603,11 +561,6 @@ static int drbg_ctr_generate(struct drbg_state *drbg, } outlen = (drbg_blocklen(drbg) < (buflen - len)) ? drbg_blocklen(drbg) : (buflen - len); - if (!drbg_fips_continuous_test(drbg, drbg->scratchpad)) { - /* 10.2.1.5.2 step 6 */ - crypto_inc(drbg->V, drbg_blocklen(drbg)); - continue; - } /* 10.2.1.5.2 step 4.3 */ memcpy(buf + len, drbg->scratchpad, outlen); len += outlen; @@ -733,8 +686,6 @@ static int drbg_hmac_generate(struct drbg_state *drbg, return ret; outlen = (drbg_blocklen(drbg) < (buflen - len)) ? drbg_blocklen(drbg) : (buflen - len); - if (!drbg_fips_continuous_test(drbg, drbg->V)) - continue; /* 10.1.2.5 step 4.2 */ memcpy(buf + len, drbg->V, outlen); @@ -963,10 +914,6 @@ static int drbg_hash_hashgen(struct drbg_state *drbg, } outlen = (drbg_blocklen(drbg) < (buflen - len)) ? drbg_blocklen(drbg) : (buflen - len); - if (!drbg_fips_continuous_test(drbg, dst)) { - crypto_inc(src, drbg_statelen(drbg)); - continue; - } /* 10.1.1.4 step hashgen 4.2 */ memcpy(buf + len, dst, outlen); len += outlen; @@ -1201,11 +1148,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) drbg->reseed_ctr = 0; drbg->d_ops = NULL; drbg->core = NULL; -#ifdef CONFIG_CRYPTO_FIPS - kzfree(drbg->prev); - drbg->prev = NULL; - drbg->fips_primed = false; -#endif } /* @@ -1244,12 +1186,6 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) drbg->C = kmalloc(drbg_statelen(drbg), GFP_KERNEL); if (!drbg->C) goto err; -#ifdef CONFIG_CRYPTO_FIPS - drbg->prev = kmalloc(drbg_blocklen(drbg), GFP_KERNEL); - if (!drbg->prev) - goto err; - drbg->fips_primed = false; -#endif /* scratchpad is only generated for CTR and Hash */ if (drbg->core->flags & DRBG_HMAC) sb_size = 0; diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h index 9756c70899d8..d961b2b16f55 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h @@ -117,10 +117,6 @@ struct drbg_state { void *priv_data; /* Cipher handle */ bool seeded; /* DRBG fully seeded? */ bool pr; /* Prediction resistance enabled? */ -#ifdef CONFIG_CRYPTO_FIPS - bool fips_primed; /* Continuous test primed? */ - unsigned char *prev; /* FIPS 140-2 continuous test value */ -#endif struct work_struct seed_work; /* asynchronous seeding support */ struct crypto_rng *jent; const struct drbg_state_ops *d_ops; -- cgit From e67ffe0af4d450e95e5f9bb7d081500e30777857 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 22 Jan 2016 23:17:58 +0800 Subject: crypto: hash - Add helpers to zero stack request/descriptor As the size of an ahash_request or shash_desc is variable, it's awkward to zero them explicitly. This patch adds helpers to do that which should be used when they are created on the stack. Signed-off-by: Herbert Xu --- include/crypto/hash.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/crypto/hash.h b/include/crypto/hash.h index 6361892ea737..aef819247fe8 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -14,6 +14,7 @@ #define _CRYPTO_HASH_H #include +#include struct crypto_ahash; @@ -550,6 +551,12 @@ static inline void ahash_request_free(struct ahash_request *req) kzfree(req); } +static inline void ahash_request_zero(struct ahash_request *req) +{ + memzero_explicit(req, sizeof(*req) + + crypto_ahash_reqsize(crypto_ahash_reqtfm(req))); +} + static inline struct ahash_request *ahash_request_cast( struct crypto_async_request *req) { @@ -872,4 +879,10 @@ int crypto_shash_final(struct shash_desc *desc, u8 *out); int crypto_shash_finup(struct shash_desc *desc, const u8 *data, unsigned int len, u8 *out); +static inline void shash_desc_zero(struct shash_desc *desc) +{ + memzero_explicit(desc, + sizeof(*desc) + crypto_shash_descsize(desc->tfm)); +} + #endif /* _CRYPTO_HASH_H */ -- cgit From 1aaa753d918c48c603195a468766e6a2b32b87f9 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 22 Jan 2016 23:21:10 +0800 Subject: crypto: skcipher - Add helper to zero stack request As the size of an skcipher_request is variable, it's awkward to zero it explicitly. This patch adds a helper to do that which should be used when it is created on the stack. Signed-off-by: Herbert Xu --- include/crypto/skcipher.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index 2f07b4fce3e0..f7a03a17bc1d 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -445,6 +445,13 @@ static inline void skcipher_request_free(struct skcipher_request *req) kzfree(req); } +static inline void skcipher_request_zero(struct skcipher_request *req) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + + memzero_explicit(req, sizeof(*req) + crypto_skcipher_reqsize(tfm)); +} + /** * skcipher_request_set_callback() - set asynchronous callback function * @req: request handle -- cgit From f2aefdab5dff83d3c801449051be1ba72c7e933a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 23 Jan 2016 13:51:01 +0800 Subject: crypto: api - Add crypto_type_has_alg helper This patch adds the helper crypto_type_has_alg which is meant to replace crypto_has_alg for new-style crypto types. Rather than hard-coding type/mask information they're now retrieved from the crypto_type object. Signed-off-by: Herbert Xu --- crypto/algapi.c | 15 +++++++++++++++ crypto/internal.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/crypto/algapi.c b/crypto/algapi.c index 7be76aa31579..731255a6104f 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -987,6 +987,21 @@ unsigned int crypto_alg_extsize(struct crypto_alg *alg) } EXPORT_SYMBOL_GPL(crypto_alg_extsize); +int crypto_type_has_alg(const char *name, const struct crypto_type *frontend, + u32 type, u32 mask) +{ + int ret = 0; + struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask); + + if (!IS_ERR(alg)) { + crypto_mod_put(alg); + ret = 1; + } + + return ret; +} +EXPORT_SYMBOL_GPL(crypto_type_has_alg); + static int __init crypto_algapi_init(void) { crypto_init_proc(); diff --git a/crypto/internal.h b/crypto/internal.h index 00e42a3ed814..7eefcdb00227 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -104,6 +104,9 @@ int crypto_probing_notify(unsigned long val, void *v); unsigned int crypto_alg_extsize(struct crypto_alg *alg); +int crypto_type_has_alg(const char *name, const struct crypto_type *frontend, + u32 type, u32 mask); + static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) { atomic_inc(&alg->cra_refcnt); -- cgit From 8d18e34c1fe22418ae0b5475ab0d1956d69ad195 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 23 Jan 2016 13:52:40 +0800 Subject: crypto: hash - Add crypto_has_ahash helper This patch adds the helper crypto_has_ahash which should replace crypto_has_hash. Signed-off-by: Herbert Xu --- crypto/ahash.c | 6 ++++++ include/crypto/hash.h | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/crypto/ahash.c b/crypto/ahash.c index d19b52324cf5..8b08a59221a6 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -542,6 +542,12 @@ struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type, } EXPORT_SYMBOL_GPL(crypto_alloc_ahash); +int crypto_has_ahash(const char *alg_name, u32 type, u32 mask) +{ + return crypto_type_has_alg(alg_name, &crypto_ahash_type, type, mask); +} +EXPORT_SYMBOL_GPL(crypto_has_ahash); + static int ahash_prepare_alg(struct ahash_alg *alg) { struct crypto_alg *base = &alg->halg.base; diff --git a/include/crypto/hash.h b/include/crypto/hash.h index aef819247fe8..f855efaa2f8c 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -260,6 +260,18 @@ static inline void crypto_free_ahash(struct crypto_ahash *tfm) crypto_destroy_tfm(tfm, crypto_ahash_tfm(tfm)); } +/** + * crypto_has_ahash() - Search for the availability of an ahash. + * @alg_name: is the cra_name / name or cra_driver_name / driver name of the + * ahash + * @type: specifies the type of the ahash + * @mask: specifies the mask for the ahash + * + * Return: true when the ahash is known to the kernel crypto API; false + * otherwise + */ +int crypto_has_ahash(const char *alg_name, u32 type, u32 mask); + static inline unsigned int crypto_ahash_alignmask( struct crypto_ahash *tfm) { -- cgit From c5d89a49fcb47e27a9ef96b63bdbe7fbf0504bd8 Mon Sep 17 00:00:00 2001 From: Benjamin Larsson Date: Sat, 28 Nov 2015 23:53:31 -0200 Subject: [media] Add support for Terratec Cinergy S2 Rev.4 Also Add Terratec Cinergy S2 usb id's Signed-off-by: Benjamin Larsson Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 4 ++++ drivers/media/usb/dvb-usb-v2/dvbsky.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 7f5d0865acfd..750d23f9928d 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -256,6 +256,10 @@ #define USB_PID_TERRATEC_CINERGY_T_EXPRESS 0x0062 #define USB_PID_TERRATEC_CINERGY_T_XXS 0x0078 #define USB_PID_TERRATEC_CINERGY_T_XXS_2 0x00ab +#define USB_PID_TERRATEC_CINERGY_S2_R1 0x00a8 +#define USB_PID_TERRATEC_CINERGY_S2_R2 0x00b0 +#define USB_PID_TERRATEC_CINERGY_S2_R3 0x0102 +#define USB_PID_TERRATEC_CINERGY_S2_R4 0x0105 #define USB_PID_TERRATEC_H7 0x10b4 #define USB_PID_TERRATEC_H7_2 0x10a3 #define USB_PID_TERRATEC_H7_3 0x10a5 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 1dd962535f97..2d922b96ed83 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -851,6 +851,9 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TERRATEC_H7_3, &dvbsky_t680c_props, "Terratec H7 Rev.4", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4, + &dvbsky_s960_props, "Terratec Cinergy S2 Rev.4", + RC_MAP_DVBSKY) }, { } }; MODULE_DEVICE_TABLE(usb, dvbsky_id_table); -- cgit From 10eadc253ddf8325bc6daafdbed67438cfede84c Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Thu, 7 Jan 2016 11:03:14 -0800 Subject: dtc: create tool to diff device trees Create script to diff device trees. The device tree can be in any of the forms recognized by the dtc compiler: - source - binary blob - file system tree (from /proc/devicetree) If the device tree is a source file, then it is pre-processed in the same way as it would be when built in the linux kernel source tree before diffing. Signed-off-by: Frank Rowand Signed-off-by: Rob Herring --- scripts/dtc/dtx_diff | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100755 scripts/dtc/dtx_diff diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff new file mode 100755 index 000000000000..f1160053d75e --- /dev/null +++ b/scripts/dtc/dtx_diff @@ -0,0 +1,343 @@ +#! /bin/bash + +# Copyright (C) 2015 Frank Rowand +# +# 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. + + +usage() { + + # use spaces instead of tabs in the usage message + cat >&2 <tmp_dtx_1.dts + `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts + `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts + rm tmp_dtx_1.dts tmp_dtx_2.dts + + If DTx_1 and DTx_2 are in different directories, then this script will + add the path of DTx_1 and DTx_2 to the include paths. If DTx_2 includes + a local file that exists in both the path of DTx_1 and DTx_2 then the + file in the path of DTx_1 will incorrectly be included. Possible + workaround: + + `basename $0` DTx_1 >tmp_dtx_1.dts + `basename $0` DTx_2 >tmp_dtx_2.dts + `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts + rm tmp_dtx_1.dts tmp_dtx_2.dts + +eod +} + + +compile_to_dts() { + + dtx="$1" + + if [ -d "${dtx}" ] ; then + + # ----- input is file tree + + if ( ! ${DTC} -I fs ${dtx} ) ; then + exit 3 + fi + + elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then + + magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}` + if [ "${magic}" = "d00dfeed" ] ; then + + # ----- input is FDT (binary blob) + + if ( ! ${DTC} -I dtb ${dtx} ) ; then + exit 3 + fi + + return + + fi + + # ----- input is DTS (source) + + if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \ + | ${DTC} -I dts ) ; then + return + fi + + echo "" >&2 + echo "Possible hints to resolve the above error:" >&2 + echo " (hints might not fix the problem)" >&2 + + hint_given=0 + + if [ "${ARCH}" = "" ] ; then + hint_given=1 + echo "" >&2 + echo " shell variable \$ARCH not set" >&2 + fi + + dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'` + + if [ "${dtx_arch}" != "" -a "${dtx_arch}" != "${ARCH}" ] ; then + hint_given=1 + echo "" >&2 + echo " architecture ${dtx_arch} is in file path," >&2 + echo " but does not match shell variable \$ARCH" >&2 + echo " (${ARCH}) does not match shell variable" >&2 + echo " \$ARCH (${ARCH})" >&2 + fi + + if [ ! -d ${srctree}/arch/${ARCH} ] ; then + hint_given=1 + echo "" >&2 + echo " ${srctree}/arch/${ARCH}/ does not exist" >&2 + echo " Is \$ARCH='${ARCH}' correct?" >&2 + echo " Possible fix: use '-s' option" >&2 + + git_root=`git rev-parse --show-toplevel 2>/dev/null` + if [ -d ${git_root}/arch/ ] ; then + echo " Possible fix: use '-S' option" >&2 + fi + fi + + if [ $hint_given = 0 ] ; then + echo "" >&2 + echo " No hints available." >&2 + fi + + echo "" >&2 + + exit 3 + + else + echo "" >&2 + echo "ERROR: ${dtx} does not exist or is not readable" >&2 + echo "" >&2 + exit 2 + fi + +} + + +# ----- start of script + +cmd_diff=0 +diff_flags="-u" +dtx_file_1="" +dtx_file_2="" +dtc_sort="-s" +help=0 +srctree="" + + +while [ $# -gt 0 ] ; do + + case $1 in + + -f ) + diff_flags="--unified=999999" + shift + ;; + + -h | -help | --help ) + help=1 + shift + ;; + + -s ) + srctree="$2" + shift 2 + ;; + + -S ) + git_root=`git rev-parse --show-toplevel 2>/dev/null` + srctree="${git_root}" + shift + ;; + + -u ) + dtc_sort="" + shift + ;; + + *) + if [ "${dtx_file_1}" = "" ] ; then + dtx_file_1="$1" + elif [ "${dtx_file_2}" = "" ] ; then + dtx_file_2="$1" + else + echo "" >&2 + echo "ERROR: Unexpected parameter: $1" >&2 + echo "" >&2 + exit 2 + fi + shift + ;; + + esac + +done + +if [ "${srctree}" = "" ] ; then + srctree="." +fi + +if [ "${dtx_file_2}" != "" ]; then + cmd_diff=1 +fi + +if (( ${help} )) ; then + usage + exit 1 +fi + +# this must follow check for ${help} +if [ "${dtx_file_1}" = "" ]; then + echo "" >&2 + echo "ERROR: parameter DTx required" >&2 + echo "" >&2 + exit 2 +fi + + +# ----- prefer dtc from linux kernel, allow fallback to dtc in $PATH + +if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then + __KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}" +elif [ "${KBUILD_OUTPUT}" = "" ] ; then + __KBUILD_OUTPUT="." +else + __KBUILD_OUTPUT="${KBUILD_OUTPUT}" +fi + +DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc" + +if [ ! -x ${DTC} ] ; then + __DTC="dtc" + if ( ! which ${__DTC} >/dev/null ) ; then + + # use spaces instead of tabs in the error message + cat >&2 < Date: Mon, 25 Jan 2016 12:47:44 -0200 Subject: [media] dw2102: use the new USB ID Terratec Cinergy S2 macros Now that this was defined at usb-id.h, update the values for USB_PID_TERRATEC_CINERGY_S2_R1 and USB_PID_TERRATEC_CINERGY_S2_R2. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 14ef25dc6cd3..bc19da5ad3b7 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1702,13 +1702,13 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)}, [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)}, [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)}, - [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)}, + [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R1)}, [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, - [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, + [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, -- cgit From 7655a3aea2ca14b9d34af929304f3c08140cc91c Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Thu, 3 Dec 2015 18:12:50 -0200 Subject: [media] si2165: Reject DVB-T bandwidth auto mode The si2165 does not support bandwidth auto-detection. Reject the request. Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 2b93241d4bc1..659976612392 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -825,19 +825,19 @@ static int si2165_set_frontend_dvbt(struct dvb_frontend *fe) struct si2165_state *state = fe->demodulator_priv; u32 dvb_rate = 0; u16 bw10k; + u32 bw_hz = p->bandwidth_hz; dprintk("%s: called\n", __func__); if (!state->has_dvbt) return -EINVAL; - if (p->bandwidth_hz > 0) { - dvb_rate = p->bandwidth_hz * 8 / 7; - bw10k = p->bandwidth_hz / 10000; - } else { - dvb_rate = 8 * 8 / 7; - bw10k = 800; - } + /* no bandwidth auto-detection */ + if (bw_hz == 0) + return -EINVAL; + + dvb_rate = bw_hz * 8 / 7; + bw10k = bw_hz / 10000; ret = si2165_adjust_pll_divl(state, 12); if (ret < 0) -- cgit From 71d362be0a9896e094601ac5f723f942cdfb0be9 Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Sat, 23 Jan 2016 15:35:39 -0500 Subject: HID: usbhid: Fix incorrect product id of old 4nes4snes The correct product ID for the old version of the raphnet 4nes4snes device was 0x0a9d, not 0x0a8d. Signed-off-by: Raphael Assenat Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b6ff6e78ac54..de0fb068602a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1047,7 +1047,7 @@ #define USB_DEVICE_ID_RI_KA_WEBMAIL 0x1320 /* Webmail Notifier */ #define USB_VENDOR_ID_MULTIPLE_1781 0x1781 -#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a8d +#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d #define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b #define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 -- cgit From 27524ff8cd6c28ea3735f80f0374e0fc5494768f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 9 Dec 2015 11:46:55 -0200 Subject: [media] : cxd2830r: 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: Antti Palosaari Signed-off-by: Linus Walleij Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/cxd2820r_core.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index 24a457d9d803..ba4cb7557aa5 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -606,8 +606,7 @@ static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, int val) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); u8 gpio[GPIO_COUNT]; dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); @@ -620,8 +619,7 @@ static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr, static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); u8 gpio[GPIO_COUNT]; dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val); @@ -636,8 +634,7 @@ static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val) static int cxd2820r_gpio_get(struct gpio_chip *chip, unsigned nr) { - struct cxd2820r_priv *priv = - container_of(chip, struct cxd2820r_priv, gpio_chip); + struct cxd2820r_priv *priv = gpiochip_get_data(chip); dev_dbg(&priv->i2c->dev, "%s: nr=%d\n", __func__, nr); @@ -731,7 +728,7 @@ struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg, priv->gpio_chip.base = -1; /* dynamic allocation */ priv->gpio_chip.ngpio = GPIO_COUNT; priv->gpio_chip.can_sleep = 1; - ret = gpiochip_add(&priv->gpio_chip); + ret = gpiochip_add_data(&priv->gpio_chip, priv); if (ret) goto error; -- cgit From 6f08cbdaac5a3050ea1898aef8ce326030fd1117 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Thu, 14 Jan 2016 21:57:20 +0100 Subject: ASoC: Intel: Use acpi_dev_present() Use shiny new acpi_dev_present() and remove all the boilerplate to search for a particular ACPI device. No functional change. Cf. 2d12b6b381ba ("ACPI / utils: Add acpi_dev_present()"). Signed-off-by: Lukas Wunner Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_max98090_ti.c | 17 ++--------------- sound/soc/intel/boards/cht_bsw_rt5645.c | 13 +------------ sound/soc/intel/common/sst-match-acpi.c | 16 +--------------- 3 files changed, 4 insertions(+), 42 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c index 90588d6e64fc..e609f089593a 100644 --- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c +++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c @@ -287,33 +287,20 @@ static struct snd_soc_card snd_soc_card_cht = { .num_controls = ARRAY_SIZE(cht_mc_controls), }; -static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level, - void *context, void **ret) -{ - *(bool *)context = true; - return AE_OK; -} - static int snd_cht_mc_probe(struct platform_device *pdev) { int ret_val = 0; - bool found = false; struct cht_mc_private *drv; drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); if (!drv) return -ENOMEM; - if (ACPI_SUCCESS(acpi_get_devices( - "104C227E", - snd_acpi_codec_match, - &found, NULL)) && found) { - drv->ts3a227e_present = true; - } else { + drv->ts3a227e_present = acpi_dev_present("104C227E"); + if (!drv->ts3a227e_present) { /* no need probe TI jack detection chip */ snd_soc_card_cht.aux_dev = NULL; snd_soc_card_cht.num_aux_devs = 0; - drv->ts3a227e_present = false; } /* register the soc card */ diff --git a/sound/soc/intel/boards/cht_bsw_rt5645.c b/sound/soc/intel/boards/cht_bsw_rt5645.c index 2d3afddb0a2e..e6cf800ab231 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5645.c +++ b/sound/soc/intel/boards/cht_bsw_rt5645.c @@ -333,20 +333,12 @@ static struct cht_acpi_card snd_soc_cards[] = { {"10EC5650", CODEC_TYPE_RT5650, &snd_soc_card_chtrt5650}, }; -static acpi_status snd_acpi_codec_match(acpi_handle handle, u32 level, - void *context, void **ret) -{ - *(bool *)context = true; - return AE_OK; -} - static int snd_cht_mc_probe(struct platform_device *pdev) { int ret_val = 0; int i; struct cht_mc_private *drv; struct snd_soc_card *card = snd_soc_cards[0].soc_card; - bool found = false; char codec_name[16]; drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_ATOMIC); @@ -354,10 +346,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_SUCCESS(acpi_get_devices( - snd_soc_cards[i].codec_id, - snd_acpi_codec_match, - &found, NULL)) && found) { + if (acpi_dev_present(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; diff --git a/sound/soc/intel/common/sst-match-acpi.c b/sound/soc/intel/common/sst-match-acpi.c index dd077e116d25..c429e2226d40 100644 --- a/sound/soc/intel/common/sst-match-acpi.c +++ b/sound/soc/intel/common/sst-match-acpi.c @@ -13,29 +13,15 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ -#include -#include -#include -#include #include "sst-acpi.h" -static acpi_status sst_acpi_mach_match(acpi_handle handle, u32 level, - void *context, void **ret) -{ - *(bool *)context = true; - return AE_OK; -} - struct sst_acpi_mach *sst_acpi_find_machine(struct sst_acpi_mach *machines) { struct sst_acpi_mach *mach; - bool found = false; for (mach = machines; mach->id[0]; mach++) - if (ACPI_SUCCESS(acpi_get_devices(mach->id, - sst_acpi_mach_match, - &found, NULL)) && found) + if (acpi_dev_present(mach->id)) return mach; return NULL; -- cgit From 51b2bb3f2568e6d9d81a001d38b8d70c2ba4af99 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Mon, 25 Jan 2016 12:36:43 +0000 Subject: ASoC: wm8974: configure pll and mclk divider automatically This adds a set_sysclk() DAI op so the card driver can set the input clock frequency. If this is done, the pll and mclk divider are configured to produce the required 256x fs clock when the sample rate is set by hw_params(). These additions make the codec work with the simple-card driver. Card drivers calling set_pll() and set_clkdiv() directly are unaffected. Signed-off-by: Mans Rullgard Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8974.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index c284c7b6db8b..dc8c3b1ebb6f 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -28,6 +28,11 @@ #include "wm8974.h" +struct wm8974_priv { + unsigned int mclk; + unsigned int fs; +}; + static const struct reg_default wm8974_reg_defaults[] = { { 0, 0x0000 }, { 1, 0x0000 }, { 2, 0x0000 }, { 3, 0x0000 }, { 4, 0x0050 }, { 5, 0x0000 }, { 6, 0x0140 }, { 7, 0x0000 }, @@ -379,6 +384,79 @@ static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, return 0; } +static unsigned int wm8974_get_mclkdiv(unsigned int f_in, unsigned int f_out, + int *mclkdiv) +{ + unsigned int ratio = 2 * f_in / f_out; + + if (ratio <= 2) { + *mclkdiv = WM8974_MCLKDIV_1; + ratio = 2; + } else if (ratio == 3) { + *mclkdiv = WM8974_MCLKDIV_1_5; + } else if (ratio == 4) { + *mclkdiv = WM8974_MCLKDIV_2; + } else if (ratio <= 6) { + *mclkdiv = WM8974_MCLKDIV_3; + ratio = 6; + } else if (ratio <= 8) { + *mclkdiv = WM8974_MCLKDIV_4; + ratio = 8; + } else if (ratio <= 12) { + *mclkdiv = WM8974_MCLKDIV_6; + ratio = 12; + } else if (ratio <= 16) { + *mclkdiv = WM8974_MCLKDIV_8; + ratio = 16; + } else { + *mclkdiv = WM8974_MCLKDIV_12; + ratio = 24; + } + + return f_out * ratio / 2; +} + +static int wm8974_update_clocks(struct snd_soc_dai *dai) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8974_priv *priv = snd_soc_codec_get_drvdata(codec); + unsigned int fs256; + unsigned int fpll = 0; + unsigned int f; + int mclkdiv; + + if (!priv->mclk || !priv->fs) + return 0; + + fs256 = 256 * priv->fs; + + f = wm8974_get_mclkdiv(priv->mclk, fs256, &mclkdiv); + + if (f != priv->mclk) { + /* The PLL performs best around 90MHz */ + fpll = wm8974_get_mclkdiv(22500000, fs256, &mclkdiv); + } + + wm8974_set_dai_pll(dai, 0, 0, priv->mclk, fpll); + wm8974_set_dai_clkdiv(dai, WM8974_MCLKDIV, mclkdiv); + + return 0; +} + +static int wm8974_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, + unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct wm8974_priv *priv = snd_soc_codec_get_drvdata(codec); + + if (dir != SND_SOC_CLOCK_IN) + return -EINVAL; + + priv->mclk = freq; + + return wm8974_update_clocks(dai); +} + static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { @@ -441,8 +519,15 @@ static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; + struct wm8974_priv *priv = snd_soc_codec_get_drvdata(codec); u16 iface = snd_soc_read(codec, WM8974_IFACE) & 0x19f; u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1; + int err; + + priv->fs = params_rate(params); + err = wm8974_update_clocks(dai); + if (err) + return err; /* bit size */ switch (params_width(params)) { @@ -547,6 +632,7 @@ static const struct snd_soc_dai_ops wm8974_ops = { .set_fmt = wm8974_set_dai_fmt, .set_clkdiv = wm8974_set_dai_clkdiv, .set_pll = wm8974_set_dai_pll, + .set_sysclk = wm8974_set_dai_sysclk, }; static struct snd_soc_dai_driver wm8974_dai = { @@ -606,9 +692,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { static int wm8974_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { + struct wm8974_priv *priv; struct regmap *regmap; int ret; + priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + i2c_set_clientdata(i2c, priv); + regmap = devm_regmap_init_i2c(i2c, &wm8974_regmap); if (IS_ERR(regmap)) return PTR_ERR(regmap); -- cgit From 48295fe932b3306c25ba6157db82f8f9938f2637 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Dec 2015 16:50:18 +0100 Subject: blackfin: gpio: Be sure to clamp return value As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. Cc: Steven Miao Cc: adi-buildroot-devel@lists.sourceforge.net Acked-by: Sonic Zhang Signed-off-by: Linus Walleij --- arch/blackfin/kernel/bfin_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index a017359c1826..84baa6217c03 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1159,7 +1159,7 @@ static int bfin_gpiolib_direction_output(struct gpio_chip *chip, unsigned gpio, static int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio) { - return bfin_gpio_get_value(gpio); + return !!bfin_gpio_get_value(gpio); } static void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value) -- cgit From eecdf59ad2fb90d8238a42e2ec41f165964349bb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Dec 2015 22:41:42 +0100 Subject: powerpc: ppc4cc/gpio: Be sure to clamp return value As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- arch/powerpc/sysdev/ppc4xx_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c index fc65ad1b3293..d7a7ef135b9f 100644 --- a/arch/powerpc/sysdev/ppc4xx_gpio.c +++ b/arch/powerpc/sysdev/ppc4xx_gpio.c @@ -78,7 +78,7 @@ 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); struct ppc4xx_gpio __iomem *regs = mm_gc->regs; - return in_be32(®s->ir) & GPIO_MASK(gpio); + return !!(in_be32(®s->ir) & GPIO_MASK(gpio)); } static inline void -- cgit From e847396b40d07931f5d2835f73220e16a1a413b3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Dec 2015 22:42:59 +0100 Subject: powerpc: qe_lib/gpio: Be sure to clamp return value As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. Cc: Anatolij Gustschin Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Signed-off-by: Linus Walleij --- drivers/soc/fsl/qe/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index aa5c11acf212..65845712571c 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -63,7 +63,7 @@ static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio) struct qe_pio_regs __iomem *regs = mm_gc->regs; u32 pin_mask = 1 << (QE_PIO_PINS - 1 - gpio); - return in_be32(®s->cpdata) & pin_mask; + return !!(in_be32(®s->cpdata) & pin_mask); } static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -- cgit From a4ce4b8dae68e7233ba699f10e9c120df31f5824 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Dec 2015 22:44:02 +0100 Subject: powerpc: simple_gpio: Be sure to clamp return value As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. 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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/sysdev/simple_gpio.c b/arch/powerpc/sysdev/simple_gpio.c index ff5e73230a36..56ce8ca3281b 100644 --- a/arch/powerpc/sysdev/simple_gpio.c +++ b/arch/powerpc/sysdev/simple_gpio.c @@ -46,7 +46,7 @@ static int u8_gpio_get(struct gpio_chip *gc, unsigned int gpio) { struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - return in_8(mm_gc->regs) & u8_pin2mask(gpio); + return !!(in_8(mm_gc->regs) & u8_pin2mask(gpio)); } static void u8_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) -- cgit From a80bb4c9ec200ab4fc3ad502bf80e00ca5db12a7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 21 Dec 2015 22:45:55 +0100 Subject: unicore: gpio: Be sure to clamp return value As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. Cc: Guan Xuetao Signed-off-by: Linus Walleij --- arch/unicore32/kernel/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c index cb12ec39552c..5ab23794ea17 100644 --- a/arch/unicore32/kernel/gpio.c +++ b/arch/unicore32/kernel/gpio.c @@ -52,7 +52,7 @@ device_initcall(puv3_gpio_leds_init); static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset) { - return readl(GPIO_GPLR) & GPIO_GPIO(offset); + return !!(readl(GPIO_GPLR) & GPIO_GPIO(offset)); } static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -- cgit From 47de9bf8931e6bf9c92fdba9867925d1ce482ab1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 25 Jan 2016 14:39:34 -0200 Subject: [media] tvp5150: Fix breakage for serial usage changeset 460b6c0831cb ("tvp5150: Add s_stream subdev operation support") broke for em28xx-based devices with uses tvp5150. On those devices, touching the TVP5150_MISC_CTL register causes em28xx to stop streaming. I suspect that it uses the 27 MHz clock provided by tvp5150 to feed em28xx. So, change the logic to do nothing on s_stream if the tvp5150 is not set up to work with V4L2_MBUS_PARALLEL. Tested with Hauppauge WinTV USB 2 model 42012 Rev. C186 (USB ID: 2040:4200). Cc: Javier Martinez Canillas Cc: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 437f1a7ecb96..779c6f453cc9 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -975,19 +975,18 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ - int val = 0x09; /* Output format: 8-bit 4:2:2 YUV with discrete sync */ - if (decoder->mbus_type == V4L2_MBUS_PARALLEL) - val = 0x0d; + if (decoder->mbus_type != V4L2_MBUS_PARALLEL) + return 0; /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, val); + tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); -- cgit From c1ae8f3ad8758b588b4ba02edcb8d413185a10d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 12 Dec 2015 22:32:01 -0200 Subject: [media] davinci: ccdc_update_raw_params() frees the wrong thing Passing a physical address to free_pages() is a bad idea. config_params->fault_pxl.fpc_table_addr is set to virt_to_phys() of __get_free_pages() return value; what we should pass to free_pages() is its phys_to_virt(). ccdc_close() does that properly, but ccdc_update_raw_params() doesn't. Signed-off-by: Al Viro Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/davinci/dm644x_ccdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index ffbefdff6b5e..6fba32bec974 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -261,7 +261,7 @@ static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) */ if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { if (fpc_physaddr != NULL) { - free_pages((unsigned long)fpc_physaddr, + free_pages((unsigned long)fpc_virtaddr, get_order (config_params->fault_pxl.fp_num * FP_NUM_BYTES)); -- cgit From 28d5bdbe5c0adcc11b7b63e65cf002a1ebaf3ca4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 12:41:51 -0200 Subject: [media] mt9v032: Add reset and standby gpios Add optional reset and standby gpios. The reset gpio is used to reset the chip in power_on(). The standby gpio is not used currently. It is just unset, so the chip is not in standby. Signed-off-by: Markus Pargmann Reviewed-by: Philipp Zabel Acked-by: Rob Herring Acked-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/mt9v032.txt | 2 ++ drivers/media/i2c/mt9v032.c | 28 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt index 202565313e82..100f0ae43269 100644 --- a/Documentation/devicetree/bindings/media/i2c/mt9v032.txt +++ b/Documentation/devicetree/bindings/media/i2c/mt9v032.txt @@ -20,6 +20,8 @@ Optional Properties: - link-frequencies: List of allowed link frequencies in Hz. Each frequency is expressed as a 64-bit big-endian integer. +- reset-gpios: GPIO handle which is connected to the reset pin of the chip. +- standby-gpios: GPIO handle which is connected to the standby pin of the chip. For further reading on port node refer to Documentation/devicetree/bindings/media/video-interfaces.txt. diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c index 2e1d116a64e7..501b37039449 100644 --- a/drivers/media/i2c/mt9v032.c +++ b/drivers/media/i2c/mt9v032.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -251,6 +252,8 @@ struct mt9v032 { struct regmap *regmap; struct clk *clk; + struct gpio_desc *reset_gpio; + struct gpio_desc *standby_gpio; struct mt9v032_platform_data *pdata; const struct mt9v032_model_info *model; @@ -312,16 +315,31 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032) struct regmap *map = mt9v032->regmap; int ret; + if (mt9v032->reset_gpio) + gpiod_set_value_cansleep(mt9v032->reset_gpio, 1); + ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk); if (ret < 0) return ret; + /* System clock has to be enabled before releasing the reset */ ret = clk_prepare_enable(mt9v032->clk); if (ret) return ret; udelay(1); + if (mt9v032->reset_gpio) { + gpiod_set_value_cansleep(mt9v032->reset_gpio, 0); + + /* After releasing reset we need to wait 10 clock cycles + * before accessing the sensor over I2C. As the minimum SYSCLK + * frequency is 13MHz, waiting 1µs will be enough in the worst + * case. + */ + udelay(1); + } + /* Reset the chip and stop data read out */ ret = regmap_write(map, MT9V032_RESET, 1); if (ret < 0) @@ -954,6 +972,16 @@ static int mt9v032_probe(struct i2c_client *client, if (IS_ERR(mt9v032->clk)) return PTR_ERR(mt9v032->clk); + mt9v032->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(mt9v032->reset_gpio)) + return PTR_ERR(mt9v032->reset_gpio); + + mt9v032->standby_gpio = devm_gpiod_get_optional(&client->dev, "standby", + GPIOD_OUT_LOW); + if (IS_ERR(mt9v032->standby_gpio)) + return PTR_ERR(mt9v032->standby_gpio); + mutex_init(&mt9v032->power_lock); mt9v032->pdata = pdata; mt9v032->model = (const void *)did->driver_data; -- cgit From 23c7d7134147f276a09d0e55011cf682a0051093 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:25 -0200 Subject: [media] staging: media: lirc: replace NULL comparisons with !var A NULL comparison can be written as if (var) or if (!var). Reported by checkpatch. Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index d009bcb439f0..7df827856de6 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -647,7 +647,7 @@ static int __init lirc_parallel_init(void) goto exit_device_put; pport = parport_find_base(io); - if (pport == NULL) { + if (!pport) { pr_notice("no port at %x found\n", io); result = -ENXIO; goto exit_device_put; @@ -656,7 +656,7 @@ static int __init lirc_parallel_init(void) pf, kf, lirc_lirc_irq_handler, 0, NULL); parport_put_port(pport); - if (ppdevice == NULL) { + if (!ppdevice) { pr_notice("parport_register_device() failed\n"); result = -ENXIO; goto exit_device_put; -- cgit From b790aea57ecd31786ec2b00f8551261c57db4bd4 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:26 -0200 Subject: [media] staging: media: lirc: no space after cast checkpatch complains about space after type cast. [mchehab@osg.samsung.com: removed an obsolete hunk] Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 7df827856de6..eed6ffac7c90 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -286,9 +286,9 @@ static void lirc_lirc_irq_handler(void *blah) /* adjust value to usecs */ __u64 helper; - helper = ((__u64) signal)*1000000; + helper = ((__u64)signal)*1000000; do_div(helper, timer); - signal = (long) helper; + signal = (long)helper; if (signal > LIRC_SFH506_DELAY) data = signal - LIRC_SFH506_DELAY; @@ -393,9 +393,9 @@ static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, for (i = 0; i < count; i++) { __u64 helper; - helper = ((__u64) wbuf[i])*timer; + helper = ((__u64)wbuf[i])*timer; do_div(helper, 1000000); - wbuf[i] = (int) helper; + wbuf[i] = (int)helper; } local_irq_save(flags); -- cgit From 0d2f79c2bb34d9a9631a43b8d5ea7f2968564a6a Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 18 Dec 2015 11:05:27 -0200 Subject: [media] staging: media: lirc: space around operator checkpatch complains about missing space around operators. [mchehab@osg.samsung.com: removed obsolete hunks] Signed-off-by: Sudip Mukherjee Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index eed6ffac7c90..6e2edb24d9d5 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -193,7 +193,7 @@ static int lirc_claim(void) return 0; } } - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP); is_claimed = 1; return 1; } @@ -264,7 +264,7 @@ static void lirc_lirc_irq_handler(void *blah) init = 1; } - timeout = timer/10; /* timeout after 1/10 sec. */ + timeout = timer / 10; /* timeout after 1/10 sec. */ signal = 1; level = lirc_get_timer(); do { @@ -286,7 +286,7 @@ static void lirc_lirc_irq_handler(void *blah) /* adjust value to usecs */ __u64 helper; - helper = ((__u64)signal)*1000000; + helper = ((__u64)signal) * 1000000; do_div(helper, timer); signal = (long)helper; @@ -294,7 +294,7 @@ static void lirc_lirc_irq_handler(void *blah) data = signal - LIRC_SFH506_DELAY; else data = 1; - rbuf_write(PULSE_BIT|data); /* pulse */ + rbuf_write(PULSE_BIT | data); /* pulse */ } lastkt = ktime_get(); #else @@ -331,7 +331,7 @@ static ssize_t lirc_read(struct file *filep, char __user *buf, size_t n, set_current_state(TASK_INTERRUPTIBLE); while (count < n) { if (rptr != wptr) { - if (copy_to_user(buf+count, &rbuf[rptr], + if (copy_to_user(buf + count, &rbuf[rptr], sizeof(int))) { result = -EFAULT; break; @@ -393,7 +393,7 @@ static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, for (i = 0; i < count; i++) { __u64 helper; - helper = ((__u64)wbuf[i])*timer; + helper = ((__u64)wbuf[i]) * timer; do_div(helper, 1000000); wbuf[i] = (int)helper; } @@ -664,7 +664,7 @@ static int __init lirc_parallel_init(void) if (parport_claim(ppdevice) != 0) goto skip_init; is_claimed = 1; - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); + out(LIRC_LP_CONTROL, LP_PSELECP | LP_PINITP); #ifdef LIRC_TIMER if (debug) -- cgit From d5441ea58ccc70637b75b035dee61685b516a5ca Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 19 Dec 2015 12:28:37 -0200 Subject: [media] gsc-m2m: Use an unsigned data type for a variable The data type "int" was used by the variable "ret" in the gsc_m2m_poll() function despite of the aspect that the type "unsigned int" will usually be needed for the return value from a call of the v4l2_m2m_poll() function. Improve this implementation detail by addition of the type modifier then. This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos-gsc/gsc-m2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 93782f15b825..a600e32e2543 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -700,7 +700,7 @@ static unsigned int gsc_m2m_poll(struct file *file, { struct gsc_ctx *ctx = fh_to_ctx(file->private_data); struct gsc_dev *gsc = ctx->gsc_dev; - int ret; + unsigned int ret; if (mutex_lock_interruptible(&gsc->lock)) return -ERESTARTSYS; -- cgit From 2e490139b137bbac3250d594cef3dcbc461ad4cc Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Mon, 21 Dec 2015 11:54:46 -0200 Subject: [media] media: i2c: ov2659: speedup probe if no device connected The ov2659 driver performs device detection and initialization in the following way: - send reset command REG_SOFTWARE_RESET - load array of predefined register's setting (~150 values) - read device version REG_SC_CHIP_ID_H/REG_SC_CHIP_ID_L - check version and exit if invalid. As result, for not connected device there will be >~150 i2c transactions executed before device version checking and exit (there are no failures detected because ov2659 declared as I2C_CLIENT_SCCB and NACKs are ignored in this case). Let's fix that by checking the chip version first and start initialization only if it's supported. Cc: Benoit Parrot Signed-off-by: Grygorii Strashko Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/ov2659.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 02b9a3440557..1f999e9c0118 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1321,10 +1321,6 @@ static int ov2659_detect(struct v4l2_subdev *sd) } usleep_range(1000, 2000); - ret = ov2659_init(sd, 0); - if (ret < 0) - return ret; - /* Check sensor revision */ ret = ov2659_read(client, REG_SC_CHIP_ID_H, &pid); if (!ret) @@ -1338,8 +1334,10 @@ static int ov2659_detect(struct v4l2_subdev *sd) dev_err(&client->dev, "Sensor detection failed (%04X, %d)\n", id, ret); - else + else { dev_info(&client->dev, "Found OV%04X sensor\n", id); + ret = ov2659_init(sd, 0); + } } return ret; -- cgit From c2e5c951c2d10536a9f17647f3440e5f9f639d8b Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 27 Dec 2015 15:23:57 -0200 Subject: [media] si2165: Refactoring for si2165_writereg_mask8() This issue was detected by using the Coccinelle software. 1. Let us return directly if a call of the si2165_readreg8() function failed. 2. Reduce the scope for the local variables "ret" and "tmp" to one branch of an if statement. 3. Delete the jump label "err" then. 4. Return the value from a call of the si2165_writereg8() function without using an extra assignment for the variable "ret" at the end. Signed-off-by: Markus Elfring Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/si2165.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/dvb-frontends/si2165.c b/drivers/media/dvb-frontends/si2165.c index 659976612392..8bf716a8ea58 100644 --- a/drivers/media/dvb-frontends/si2165.c +++ b/drivers/media/dvb-frontends/si2165.c @@ -225,22 +225,18 @@ static int si2165_writereg32(struct si2165_state *state, const u16 reg, u32 val) static int si2165_writereg_mask8(struct si2165_state *state, const u16 reg, u8 val, u8 mask) { - int ret; - u8 tmp; - if (mask != 0xff) { - ret = si2165_readreg8(state, reg, &tmp); + u8 tmp; + int ret = si2165_readreg8(state, reg, &tmp); + if (ret < 0) - goto err; + return ret; val &= mask; tmp &= ~mask; val |= tmp; } - - ret = si2165_writereg8(state, reg, val); -err: - return ret; + return si2165_writereg8(state, reg, val); } #define REG16(reg, val) { (reg), (val) & 0xff }, { (reg)+1, (val)>>8 & 0xff } -- cgit From 2050d14c6ea23ea7b50b5cc7d05dbf645705cf70 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 12:20:45 -0200 Subject: [media] tuners: Refactoring for m88rs6000t_sleep() This issue was detected by using the Coccinelle software. 1. Let us return directly if a call of the regmap_write() function failed. 2. Delete the jump label "err" then. 3. Return zero as a constant at the end. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/m88rs6000t.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c index 504bfbc4027a..9f3e0fd4cad9 100644 --- a/drivers/media/tuners/m88rs6000t.c +++ b/drivers/media/tuners/m88rs6000t.c @@ -461,13 +461,12 @@ static int m88rs6000t_sleep(struct dvb_frontend *fe) dev_dbg(&dev->client->dev, "%s:\n", __func__); ret = regmap_write(dev->regmap, 0x07, 0x6d); - if (ret) - goto err; - usleep_range(5000, 10000); -err: - if (ret) + if (ret) { dev_dbg(&dev->client->dev, "failed=%d\n", ret); - return ret; + return ret; + } + usleep_range(5000, 10000); + return 0; } static int m88rs6000t_get_frequency(struct dvb_frontend *fe, u32 *frequency) -- cgit From 61f8e1a73296d065abc959e0c0861ffbdfa2d0b3 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 13:36:44 -0200 Subject: [media] r820t: Delete an unnecessary variable initialisation in generic_set_freq() The variable "rc" will be set to an appropriate value from a call of the r820t_set_tv_standard() function. Thus let us omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/r820t.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c index a7a8452e99d2..6ab35e315fe7 100644 --- a/drivers/media/tuners/r820t.c +++ b/drivers/media/tuners/r820t.c @@ -1295,7 +1295,7 @@ static int generic_set_freq(struct dvb_frontend *fe, v4l2_std_id std, u32 delsys) { struct r820t_priv *priv = fe->tuner_priv; - int rc = -EINVAL; + int rc; u32 lo_freq; tuner_dbg("should set frequency to %d kHz, bw %d MHz\n", -- cgit From a73cfe527c10bb023f0e22dd8cf37dd418c093e7 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Dec 2015 09:32:41 -0200 Subject: [media] msi2500: Delete an unnecessary check in msi2500_set_usb_adc() This issue was detected by using the Coccinelle software. Return the value from a call of the msi2500_ctrl_msg() function without using an extra check for the variable "ret" at the end. Signed-off-by: Markus Elfring Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/msi2500/msi2500.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index c104315fdc17..2d33033682af 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -839,8 +839,6 @@ static int msi2500_set_usb_adc(struct msi2500_dev *dev) goto err; ret = msi2500_ctrl_msg(dev, CMD_WREG, reg3); - if (ret) - goto err; err: return ret; } -- cgit From 3def9ad6d3066e597d0ce86801a81eedb130b04a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:22 -0200 Subject: [media] nuvoton-cir: use request_muxed_region for accessing EFM registers The two EFM ioports are accessed by drivers for other parts of the Nuvoton Super-IO chips too. Therefore access to these ioports needs to be protected by using request_muxed_region (like it's implemented e.g. in hwmon/nct6775 already). Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 081435cda30c..62c82c54ec82 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -80,17 +80,24 @@ static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) } /* enter extended function mode */ -static inline void nvt_efm_enable(struct nvt_dev *nvt) +static inline int nvt_efm_enable(struct nvt_dev *nvt) { + if (!request_muxed_region(nvt->cr_efir, 2, NVT_DRIVER_NAME)) + return -EBUSY; + /* Enabling Extended Function Mode explicitly requires writing 2x */ outb(EFER_EFM_ENABLE, nvt->cr_efir); outb(EFER_EFM_ENABLE, nvt->cr_efir); + + return 0; } /* exit extended function mode */ static inline void nvt_efm_disable(struct nvt_dev *nvt) { outb(EFER_EFM_DISABLE, nvt->cr_efir); + + release_region(nvt->cr_efir, 2); } /* -- cgit From 7a89836e994eaad7a17ae293ea1cd2b5597d2b4e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:34 -0200 Subject: [media] nuvoton-cir: simplify nvt_select_logical_ dev Use nvt_cr_write to simplify nvt_select_logical_ dev. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 62c82c54ec82..2539d4f10a0c 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -107,8 +107,7 @@ static inline void nvt_efm_disable(struct nvt_dev *nvt) */ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) { - outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); - outb(ldev, nvt->cr_efdr); + nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } /* write val to cir config register */ -- cgit From 1feac493b08a87b912a09b62666ad6d49bd6b87b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:39:41 -0200 Subject: [media] nuvoton-cir: simplify nvt_cir_tx_inactive Simplify nvt_cir_tx_inactive. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 2539d4f10a0c..f661effac82e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -742,16 +742,13 @@ static void nvt_cir_log_irqs(u8 status, u8 iren) static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) { unsigned long flags; - bool tx_inactive; u8 tx_state; spin_lock_irqsave(&nvt->tx.lock, flags); tx_state = nvt->tx.tx_state; spin_unlock_irqrestore(&nvt->tx.lock, flags); - tx_inactive = (tx_state == ST_TX_NONE); - - return tx_inactive; + return tx_state == ST_TX_NONE; } /* interrupt service routine for incoming and outgoing CIR data */ -- cgit From a17ede9ac1d8164e4d0b0b58e21bfa40890818d2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:05 -0200 Subject: [media] nuvoton-cir: factor out logical device disabling Factor out disabling of a logical device. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f661effac82e..ceb6b95b13fa 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } +/* select and disable logical device with setting EFM mode*/ +static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, ldev); + nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); + nvt_efm_disable(nvt); +} + /* write val to cir config register */ static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) { @@ -937,13 +946,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); - nvt_efm_enable(nvt); - /* disable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } static int nvt_open(struct rc_dev *dev) @@ -1145,13 +1149,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); - nvt_efm_enable(nvt); - /* disable cir logical dev */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); /* make sure wake is enabled */ nvt_enable_wake(nvt); -- cgit From e1a7d981cfefbf8e0261083a10ccad7dd0af6394 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:47 -0200 Subject: [media] nuvoton-cir: fix clearing wake fifo At least on NVT6779D clearing the wake fifo works in learning mode only (although this condition is not mentioned in the chip spec). Setting the clear fifo bit has no effect in wake up mode. Even if clearing the wake fifo should work in wake up mode on other chips this workaround doesn't hurt. If needed the caller of nvt_clear_cir_wake_fifo has to take care of locking. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index ceb6b95b13fa..5f36227a9059 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -370,11 +370,19 @@ static void nvt_clear_cir_fifo(struct nvt_dev *nvt) /* clear out the hardware's cir wake rx fifo */ static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) { - u8 val; + u8 val, config; + + config = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON); + + /* clearing wake fifo works in learning mode only */ + nvt_cir_wake_reg_write(nvt, config & ~CIR_WAKE_IRCON_MODE0, + CIR_WAKE_IRCON); val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, CIR_WAKE_FIFOCON); + + nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON); } /* clear out the hardware's cir tx fifo */ -- cgit From f2c2ba0e251d0b5211ce0397081b087ac623136f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:18 -0200 Subject: [media] nuvoton-cir: use IR_DEFAULT_TIMEOUT and consider SAMPLE_PERIOD Switch to using the recently introduced IR default timeout value (IR_DEFAULT_TIMEOUT) and consider the value of SAMPLE_PERIOD when calculating the limit count register value. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 0ad15d34e9c9..6a3de08a17c0 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -157,8 +157,8 @@ struct nvt_dev { /* total length of CIR and CIR WAKE */ #define CIR_IOREG_LENGTH 0x0f -/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ -#define CIR_RX_LIMIT_COUNT 0x7d0 +/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL */ +#define CIR_RX_LIMIT_COUNT (IR_DEFAULT_TIMEOUT / US_TO_NS(SAMPLE_PERIOD)) /* CIR Regs */ #define CIR_IRCON 0x00 -- cgit From 0890655c29a88765924c46460f38f33f7e34b5fc Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:40:12 -0200 Subject: [media] nuvoton-cir: factor out logical device enabling Factor out enabling of a logical device. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5f36227a9059..f6248519b31e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -110,6 +110,15 @@ static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) nvt_cr_write(nvt, ldev, CR_LOGICAL_DEV_SEL); } +/* select and enable logical device with setting EFM mode*/ +static inline void nvt_enable_logical_dev(struct nvt_dev *nvt, u8 ldev) +{ + nvt_efm_enable(nvt); + nvt_select_logical_dev(nvt, ldev); + nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); + nvt_efm_disable(nvt); +} + /* select and disable logical device with setting EFM mode*/ static inline void nvt_disable_logical_dev(struct nvt_dev *nvt, u8 ldev) { @@ -924,13 +933,8 @@ static void nvt_enable_cir(struct nvt_dev *nvt) CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); - nvt_efm_enable(nvt); - /* enable the CIR logical device */ - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); /* clear all pending interrupts */ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); @@ -1176,11 +1180,7 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_set_cir_iren(nvt); /* Enable CIR logical device */ - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); - - nvt_efm_disable(nvt); + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit From ccca00d6d7c2d6cec282ac3e3942032268d50fe4 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:59 -0200 Subject: [media] nuvoton-cir: improve logical device handling Only enable the logical devices after the registers have been initialized. The call to nvt_enable_logical_dev in nvt_resume is not needed as this is done implicitely by nvt_cir_regs_init now. [mchehab@osg.samsung.com: fixed multiline comment to kernel CodingStyle] Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f6248519b31e..5593a2f5b6c4 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -329,9 +329,8 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) val |= psval; nvt_cr_write(nvt, val, psreg); - /* Select CIR logical device and enable */ + /* Select CIR logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); @@ -344,7 +343,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) { - /* Select ACPI logical device, enable it and CIR Wake */ + /* Select ACPI logical device and anable it */ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); @@ -354,9 +353,8 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) /* enable pme interrupt of cir wakeup event */ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); - /* Select CIR Wake logical device and enable */ + /* Select CIR Wake logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); @@ -440,6 +438,9 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt) /* and finally, enable interrupts */ nvt_set_cir_iren(nvt); + + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); } static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) @@ -474,6 +475,9 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) /* clear any and all stray interrupts */ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); + + /* enable the CIR WAKE logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); } static void nvt_enable_wake(struct nvt_dev *nvt) @@ -1051,7 +1055,10 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) nvt_cir_wake_ldev_init(nvt); nvt_efm_disable(nvt); - /* Initialize CIR & CIR Wake Config Registers */ + /* + * Initialize CIR & CIR Wake Config Registers + * and enable logical devices + */ nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); @@ -1179,9 +1186,6 @@ static int nvt_resume(struct pnp_dev *pdev) /* open interrupt */ nvt_set_cir_iren(nvt); - /* Enable CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit From 0c6fbfdf8663e26a7e29f6142bd7ac2ac35310af Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:42:56 -0200 Subject: [media] nuvoton-cir: remove unneeded EFM operation in nvt_cir_isr Selecting the logical device in the interrupt handler is not needed as no configuration register is accessed. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5593a2f5b6c4..ec14b63a280d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -790,10 +790,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_dbg_verbose("%s firing", __func__); - nvt_efm_enable(nvt); - nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_efm_disable(nvt); - /* * Get IR Status register contents. Write 1 to ack/clear * -- cgit From d790c9b93b0c37a23680c88b63be0e34744f764e Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:44:13 -0200 Subject: [media] nuvoton-cir: remove unneeded call to nvt_set_cir_iren Calling nvt_set_cir_iren separately is not needed as this is done by nvt_cir_regs_init. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index ec14b63a280d..d396dcc11be5 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1179,9 +1179,6 @@ static int nvt_resume(struct pnp_dev *pdev) nvt_dbg("%s called", __func__); - /* open interrupt */ - nvt_set_cir_iren(nvt); - nvt_cir_regs_init(nvt); nvt_cir_wake_regs_init(nvt); -- cgit From fb16aaf58cbe902585fc3a2ce40d74a2de384ac2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:42:05 -0200 Subject: [media] nuvoton-cir: fix setting ioport base address At least on Zotac CI321 ACPI provides an ioport range for the wake up part but accessing these ioports has no effect. Instead the ioport base address is set to another value already (0xa20 in my case) and accessing this ioport range works. Therefore set a new ioport base address only if the current ioport base address is 0 (register reset default). The need to use the existing base address instead of trying to set an own one doesn't seem to be limited to this specific device as other drivers like hwmon/nct6775 do it the same way. This change was successfully tested on the mentioned device. And the change should be generic enough to not break the driver for other chips (however due to lack of appropriate hardware I wasn't able to test this). [mchehab@osg.samsung.com: Tested on Intel NUC NUC5i7RYB with BIOS version RYBDWi35.86A.0350.2015.0812.1722] Signed-off-by: Heiner Kallweit Tested-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d396dcc11be5..5790ee46a38d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -161,6 +161,22 @@ static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) return val; } +/* don't override io address if one is set already */ +static void nvt_set_ioaddr(struct nvt_dev *nvt, unsigned long *ioaddr) +{ + unsigned long old_addr; + + old_addr = nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8; + old_addr |= nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO); + + if (old_addr) + *ioaddr = old_addr; + else { + nvt_cr_write(nvt, *ioaddr >> 8, CR_CIR_BASE_ADDR_HI); + nvt_cr_write(nvt, *ioaddr & 0xff, CR_CIR_BASE_ADDR_LO); + } +} + /* dump current cir register contents */ static void cir_dump_regs(struct nvt_dev *nvt) { @@ -332,8 +348,7 @@ static void nvt_cir_ldev_init(struct nvt_dev *nvt) /* Select CIR logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); - nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); + nvt_set_ioaddr(nvt, &nvt->cir_addr); nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); @@ -356,8 +371,7 @@ static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) /* Select CIR Wake logical device */ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); - nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); - nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); + nvt_set_ioaddr(nvt, &nvt->cir_wake_addr); nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); -- cgit From 6ac9937c976443743962cfe7b6893163adadbda5 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Tue, 15 Dec 2015 12:00:27 +0100 Subject: SubmittingPatches: fix spelling of "git send-email" Signed-off-by: Jakub Wilk Signed-off-by: Jonathan Corbet --- Documentation/SubmittingPatches | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index d603fa078235..8c79f1d53731 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -722,7 +722,7 @@ references. -------------------------------- It can be helpful to manually add In-Reply-To: headers to a patch -(e.g., when using "git send email") to associate the patch with +(e.g., when using "git send-email") to associate the patch with previous relevant discussion, e.g. to link a bug fix to the email with the bug report. However, for a multi-patch series, it is generally best to avoid using In-Reply-To: to link to older versions of the -- cgit From 32fd52d56b3d223c567e17727f30cd6286f8f716 Mon Sep 17 00:00:00 2001 From: Thomas Gardner Date: Mon, 25 Jan 2016 15:54:39 +1000 Subject: Documentation/CodingStyle: add space before parenthesis in example macro Signed-off-by: Thomas Gardner Signed-off-by: Jonathan Corbet --- Documentation/CodingStyle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index db653774c0b7..9a70ddd16584 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle @@ -640,7 +640,7 @@ Things to avoid when using macros: do { \ if (blah(x) < 0) \ return -EBUGGERED; \ - } while(0) + } while (0) is a _very_ bad idea. It looks like a function call but exits the "calling" function; don't break the internal parsers of those who will read the code. -- cgit From 3047bcc537cf90ce73f87271e4bc11e83972632c Mon Sep 17 00:00:00 2001 From: Diego Viola Date: Sat, 5 Dec 2015 17:50:10 -0200 Subject: README: cosmetic fixes Signed-off-by: Diego Viola Signed-off-by: Jonathan Corbet --- README | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README b/README index f4756ee1c918..afc4f0d81ee1 100644 --- a/README +++ b/README @@ -59,7 +59,7 @@ DOCUMENTATION: INSTALLING the kernel source: - If you install the full sources, put the kernel tarball in a - directory where you have permissions (eg. your home directory) and + directory where you have permissions (e.g. your home directory) and unpack it: xz -cd linux-4.X.tar.xz | tar xvf - @@ -125,7 +125,7 @@ BUILD directory for the kernel: When compiling the kernel, all output files will per default be stored together with the kernel source code. - Using the option "make O=output/dir" allow you to specify an alternate + Using the option "make O=output/dir" allows you to specify an alternate place for the output files (including .config). Example: @@ -159,9 +159,9 @@ CONFIGURING the kernel: "make nconfig" Enhanced text based color menus. - "make xconfig" X windows (Qt) based configuration tool. + "make xconfig" Qt based configuration tool. - "make gconfig" X windows (GTK+) based configuration tool. + "make gconfig" GTK+ based configuration tool. "make oldconfig" Default all questions based on the contents of your existing ./.config file and asking about @@ -268,8 +268,8 @@ COMPILING the kernel: Normally, the kernel build system runs in a fairly quiet mode (but not totally silent). However, sometimes you or other kernel developers need to see compile, link, or other commands exactly as they are executed. - For this, use "verbose" build mode. This is done by inserting - "V=1" in the "make" command. E.g.: + For this, use "verbose" build mode. This is done by passing + "V=1" to the "make" command, e.g. make V=1 all @@ -300,7 +300,7 @@ COMPILING the kernel: kernel image file is usually /vmlinuz, /boot/vmlinuz, /bzImage or /boot/bzImage. To use the new kernel, save a copy of the old image and copy the new image over the old one. Then, you MUST RERUN LILO - to update the loading map!! If you don't, you won't be able to boot + 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. -- cgit From 53eeb48b49410a47a0309bbc0516534ad71c1350 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 15 Jan 2016 19:56:47 +0100 Subject: PCI: imx6: Move imx6_pcie_reset_phy() near other PHY handling functions Move imx6_pcie_reset_phy() near the other PHY related functions in the file. This is a cosmetic change, but also allows to do the following changes without introducing needless forward declarations. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index fe600964fa50..52c7a0b1254b 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -202,6 +202,23 @@ static int pcie_phy_write(void __iomem *dbi_base, int addr, int data) return 0; } +static void imx6_pcie_reset_phy(struct pcie_port *pp) +{ + u32 tmp; + + pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); + tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | + PHY_RX_OVRD_IN_LO_RX_PLL_EN); + pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); + + usleep_range(2000, 3000); + + pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); + tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | + PHY_RX_OVRD_IN_LO_RX_PLL_EN); + pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); +} + /* Added for PCI abort handling */ static int imx6q_pcie_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) @@ -441,23 +458,6 @@ static void imx6_pcie_host_init(struct pcie_port *pp) dw_pcie_msi_init(pp); } -static void imx6_pcie_reset_phy(struct pcie_port *pp) -{ - u32 tmp; - - pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); - tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | - PHY_RX_OVRD_IN_LO_RX_PLL_EN); - pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); - - usleep_range(2000, 3000); - - pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &tmp); - tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | - PHY_RX_OVRD_IN_LO_RX_PLL_EN); - pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, tmp); -} - static int imx6_pcie_link_up(struct pcie_port *pp) { u32 rc, debug_r0, rx_valid; -- cgit From 54a47a83421a3b7ee0e0fab7f65d04179bdf59b6 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 16:49:53 -0600 Subject: PCI: imx6: Move PHY reset into imx6_pcie_establish_link() This adds the PHY reset into a common error path of imx6_pcie_establish_link(), deduplicating some of the debug prints. Also reduce the severity of the "no-link" message in the one place where it is expected to be hit when no peripheral is attached. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 52c7a0b1254b..69f47ef2a264 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -355,10 +355,6 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) usleep_range(100, 1000); } - dev_err(pp->dev, "phy link never came up\n"); - dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", - readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), - readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); return -EINVAL; } @@ -407,8 +403,10 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); ret = imx6_pcie_wait_for_link(pp); - if (ret) - return ret; + if (ret) { + dev_info(pp->dev, "Link never came up\n"); + goto err_reset_phy; + } /* Allow Gen2 mode after the link is up. */ tmp = readl(pp->dbi_base + PCIE_RC_LCR); @@ -427,19 +425,28 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) ret = imx6_pcie_wait_for_speed_change(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - return ret; + goto err_reset_phy; } /* Make sure link training is finished as well! */ ret = imx6_pcie_wait_for_link(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - return ret; + goto err_reset_phy; } tmp = readl(pp->dbi_base + PCIE_RC_LCSR); dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); + return 0; + +err_reset_phy: + dev_dbg(pp->dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", + readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), + readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); + imx6_pcie_reset_phy(pp); + + return ret; } static void imx6_pcie_host_init(struct pcie_port *pp) @@ -510,11 +517,6 @@ static int imx6_pcie_link_up(struct pcie_port *pp) if ((debug_r0 & 0x3f) != 0x0d) return 0; - dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); - dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc); - - imx6_pcie_reset_phy(pp); - return 0; } -- cgit From a77c5422d7586003643377afdb9915e76d07d21c Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 16:49:57 -0600 Subject: PCI: imx6: Remove broken Gen2 workaround Remove the remnants of the workaround for erratum ERR005184 which was never completely implemented. The checks alone don't carry any value as we don't act properly on the result. A workaround should be added to the lane speed change in establish_link later. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 69f47ef2a264..6d7dfdcf4d5c 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -467,7 +467,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_link_up(struct pcie_port *pp) { - u32 rc, debug_r0, rx_valid; + u32 rc; int count = 5; /* @@ -501,21 +501,6 @@ static int imx6_pcie_link_up(struct pcie_port *pp) */ usleep_range(1000, 2000); } - /* - * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. - * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2). - * If (MAC/LTSSM.state == Recovery.RcvrLock) - * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition - * to gen2 is stuck - */ - pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); - debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0); - - if (rx_valid & PCIE_PHY_RX_ASIC_OUT_VALID) - return 0; - - if ((debug_r0 & 0x3f) != 0x0d) - return 0; return 0; } -- cgit From 4d107d3b5a686b5834e533a00b73bf7b1cf59df7 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 25 Jan 2016 16:50:02 -0600 Subject: PCI: imx6: Move link up check into imx6_pcie_wait_for_link() imx6_pcie_link_up() previously used usleep_range() to wait for the link to come up. Since it may be called while holding the config spinlock, the sleep causes a "BUG: scheduling while atomic" error. Instead of waiting for the link to come up in imx6_pcie_link_up(), do the waiting in imx6_pcie_wait_for_link(), where we're not holding a lock and sleeping is allowed. [bhelgaas: changelog, references to bugzilla and f95d3ae77191] Link: https://bugzilla.kernel.org/show_bug.cgi?id=100031 Fixes: f95d3ae77191 ("PCI: imx6: Wait for retraining") Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-imx6.c | 60 +++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 6d7dfdcf4d5c..bd3f7d0ef943 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c @@ -349,10 +349,28 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) { unsigned int retries; + /* + * Test if the PHY reports that the link is up and also that the LTSSM + * training finished. There are three possible states of the link when + * this code is called: + * 1) The link is DOWN (unlikely) + * The link didn't come up yet for some reason. This usually means + * we have a real problem somewhere, if it happens with a peripheral + * connected. This state calls for inspection of the DEBUG registers. + * 2) The link is UP, but still in LTSSM training + * Wait for the training to finish, which should take a very short + * time. If the training does not finish, we have a problem and we + * need to inspect the DEBUG registers. If the training does finish, + * the link is up and operating correctly. + * 3) The link is UP and no longer in LTSSM training + * The link is up and operating correctly. + */ for (retries = 0; retries < 200; retries++) { - if (dw_pcie_link_up(pp)) + u32 reg = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); + if ((reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) && + !(reg & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) return 0; - usleep_range(100, 1000); + usleep_range(1000, 2000); } return -EINVAL; @@ -467,42 +485,8 @@ static void imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_link_up(struct pcie_port *pp) { - u32 rc; - int count = 5; - - /* - * Test if the PHY reports that the link is up and also that the LTSSM - * training finished. There are three possible states of the link when - * this code is called: - * 1) The link is DOWN (unlikely) - * The link didn't come up yet for some reason. This usually means - * we have a real problem somewhere. Reset the PHY and exit. This - * state calls for inspection of the DEBUG registers. - * 2) The link is UP, but still in LTSSM training - * Wait for the training to finish, which should take a very short - * time. If the training does not finish, we have a problem and we - * need to inspect the DEBUG registers. If the training does finish, - * the link is up and operating correctly. - * 3) The link is UP and no longer in LTSSM training - * The link is up and operating correctly. - */ - while (1) { - rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); - if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP)) - break; - if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) - return 1; - if (!count--) - break; - dev_dbg(pp->dev, "Link is up, but still in training\n"); - /* - * Wait a little bit, then re-check if the link finished - * the training. - */ - usleep_range(1000, 2000); - } - - return 0; + return readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & + PCIE_PHY_DEBUG_R1_XMLH_LINK_UP; } static struct pcie_host_ops imx6_pcie_host_ops = { -- cgit From f5a5386bcaee222d2565d87ab33f0896f91a11ef Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 6 Dec 2015 20:18:37 -0800 Subject: rcutorture: Add checks for rcutorture writer starvation This commit adds checks for rcutorture writer starvation, so that instances will be added to the test summary. Signed-off-by: Paul E. McKenney --- tools/testing/selftests/rcutorture/bin/parse-console.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh index 844787a0d7be..0f1520fb5f81 100755 --- a/tools/testing/selftests/rcutorture/bin/parse-console.sh +++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh @@ -33,7 +33,7 @@ if grep -Pq '\x00' < $file then print_warning Console output contains nul bytes, old qemu still running? fi -egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|Stall ended before state dump start' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags +egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|Stall ended before state dump start|\?\?\? Writer stall state' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags if test -s $1.diags then print_warning Assertion failure in $file $title @@ -64,7 +64,7 @@ then then summary="$summary lockdep: $n_badness" fi - n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|Stall ended before state dump start' $1` + n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|Stall ended before state dump start|\?\?\? Writer stall state' $1` if test "$n_stalls" -ne 0 then summary="$summary Stalls: $n_stalls" -- cgit From fc91cbab11d43a7d241297886665b9a5f94a1e47 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 6 Dec 2015 20:20:14 -0800 Subject: rcutorture: Don't keep empty console.log.diags files Currently, an error-free run produces an empty console.log.diags file. This can be annoying when using "vi */console.log.diags" to see a full summary of the errors. This commit therefore removes any empty files during the analysis process. Signed-off-by: Paul E. McKenney --- tools/testing/selftests/rcutorture/bin/parse-console.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh index 0f1520fb5f81..c6b0e46214f2 100755 --- a/tools/testing/selftests/rcutorture/bin/parse-console.sh +++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh @@ -70,4 +70,6 @@ then summary="$summary Stalls: $n_stalls" fi print_warning Summary: $summary +else + rm $1.diags fi -- cgit From 5d43edb40779b3d88e9c8006b281a4c828431193 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 9 Dec 2015 16:10:23 -0800 Subject: rcutorture: Check for self-detected stalls The current scripts parse console output only for cases where one CPU detect a stall on some other CPU or task. This commit therefore adds checks for self-detected stalls. Signed-off-by: Paul E. McKenney --- tools/testing/selftests/rcutorture/bin/parse-console.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh index c6b0e46214f2..5eb49b7f864c 100755 --- a/tools/testing/selftests/rcutorture/bin/parse-console.sh +++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh @@ -33,7 +33,7 @@ if grep -Pq '\x00' < $file then print_warning Console output contains nul bytes, old qemu still running? fi -egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|Stall ended before state dump start|\?\?\? Writer stall state' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags +egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags if test -s $1.diags then print_warning Assertion failure in $file $title @@ -64,7 +64,7 @@ then then summary="$summary lockdep: $n_badness" fi - n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|Stall ended before state dump start|\?\?\? Writer stall state' $1` + n_stalls=`egrep -c 'detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' $1` if test "$n_stalls" -ne 0 then summary="$summary Stalls: $n_stalls" -- cgit From 13d52fe40f1f7bbad49128e8ee6a2fe5e13dd18d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jan 2016 06:59:39 -0200 Subject: [media] em28xx: fix implementation of s_stream On em28xx driver, s_stream subdev ops was not implemented properly. It was used only to disable stream, never enabling it. That was the root cause of the regression when we added support for s_stream on tvp5150 driver. With that, we can get rid of the changes on tvp5150 side, e. g. changeset 47de9bf8931e ('[media] tvp5150: Fix breakage for serial usage'). Tested video output on em2820+tvp5150 on WinTV USB2 and video and/or vbi output on em288x+tvp5150 on HVR 950. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 0e86ff423c49..6a015e8e8655 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -196,7 +196,6 @@ static void em28xx_wake_i2c(struct em28xx *dev) v4l2_device_call_all(v4l2_dev, 0, core, reset, 0); v4l2_device_call_all(v4l2_dev, 0, video, s_routing, INPUT(dev->ctl_input)->vmux, 0, 0); - v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0); } static int em28xx_colorlevels_set_default(struct em28xx *dev) @@ -962,6 +961,9 @@ int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count) f.type = V4L2_TUNER_ANALOG_TV; v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, s_frequency, &f); + + /* Enable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 1); } v4l2->streaming_users++; @@ -981,6 +983,9 @@ static void em28xx_stop_streaming(struct vb2_queue *vq) res_free(dev, vq->type); if (v4l2->streaming_users-- == 1) { + /* Disable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0); + /* Last active user, so shutdown all the URBS */ em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); } @@ -1013,6 +1018,9 @@ void em28xx_stop_vbi_streaming(struct vb2_queue *vq) res_free(dev, vq->type); if (v4l2->streaming_users-- == 1) { + /* Disable video stream at TV decoder */ + v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_stream, 0); + /* Last active user, so shutdown all the URBS */ em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); } -- cgit From 841502d731f1708aae907d5bdf1659e8a372fc9a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 26 Jan 2016 07:13:30 -0200 Subject: Revert "[media] tvp5150: Fix breakage for serial usage" This patch were a workaround for a regression at tvp5150, but it causes troubles on devices with omap3+tvp5151 when working in non-parallel bus mode. Now that em28xx was fixed, we can get rid of that. This reverts commit 47de9bf8931e6bf9c92fdba9867925d1ce482ab1. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 779c6f453cc9..437f1a7ecb96 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -975,18 +975,19 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) { struct tvp5150 *decoder = to_tvp5150(sd); + /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ + int val = 0x09; /* Output format: 8-bit 4:2:2 YUV with discrete sync */ - if (decoder->mbus_type != V4L2_MBUS_PARALLEL) - return 0; + if (decoder->mbus_type == V4L2_MBUS_PARALLEL) + val = 0x0d; /* Initializes TVP5150 to its default values */ /* # set PCLK (27MHz) */ tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00); - /* Output format: 8-bit ITU-R BT.656 with embedded syncs */ if (enable) - tvp5150_write(sd, TVP5150_MISC_CTL, 0x09); + tvp5150_write(sd, TVP5150_MISC_CTL, val); else tvp5150_write(sd, TVP5150_MISC_CTL, 0x00); -- cgit From b1a57ddd23f4c596ff74b130373a93cc9f5bbf37 Mon Sep 17 00:00:00 2001 From: Anatoly Pugachev Date: Mon, 25 Jan 2016 19:09:21 +0300 Subject: hwrng: n2 - documentation, add DT bindings, vendor prefixes n2rng: documentation, add DT bindings, vendor prefixes Signed-off-by: Anatoly Pugachev Acked-by: David S. Miller Signed-off-by: Herbert Xu --- .../devicetree/bindings/sparc_sun_oracle_rng.txt | 30 ++++++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.txt | 2 ++ 2 files changed, 32 insertions(+) create mode 100644 Documentation/devicetree/bindings/sparc_sun_oracle_rng.txt diff --git a/Documentation/devicetree/bindings/sparc_sun_oracle_rng.txt b/Documentation/devicetree/bindings/sparc_sun_oracle_rng.txt new file mode 100644 index 000000000000..b0b211194c71 --- /dev/null +++ b/Documentation/devicetree/bindings/sparc_sun_oracle_rng.txt @@ -0,0 +1,30 @@ +HWRNG support for the n2_rng driver + +Required properties: +- reg : base address to sample from +- compatible : should contain one of the following + RNG versions: + - 'SUNW,n2-rng' for Niagara 2 Platform (SUN UltraSPARC T2 CPU) + - 'SUNW,vf-rng' for Victoria Falls Platform (SUN UltraSPARC T2 Plus CPU) + - 'SUNW,kt-rng' for Rainbow/Yosemite Falls Platform (SUN SPARC T3/T4), (UltraSPARC KT/Niagara 3 - development names) + more recent systems (after Oracle acquisition of SUN) + - 'ORCL,m4-rng' for SPARC T5/M5 + - 'ORCL,m7-rng' for SPARC T7/M7 + +Examples: +/* linux LDOM on SPARC T5-2 */ +Node 0xf029a4f4 + .node: f029a4f4 + rng-#units: 00000002 + compatible: 'ORCL,m4-rng' + reg: 0000000e + name: 'random-number-generator' + +/* solaris on SPARC M7-8 */ +Node 0xf028c08c + rng-#units: 00000003 + compatible: 'ORCL,m7-rng' + reg: 0000000e + name: 'random-number-generator' + +PS: see as well prtconfs.git by DaveM diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 72e2c5a2b327..e00029d66d66 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -170,6 +170,7 @@ opencores OpenCores.org option Option NV ortustech Ortus Technology Co., Ltd. ovti OmniVision Technologies +ORCL Oracle Corporation panasonic Panasonic Corporation parade Parade Technologies Inc. pericom Pericom Technology Inc. @@ -227,6 +228,7 @@ startek Startek ste ST-Ericsson stericsson ST-Ericsson synology Synology, Inc. +SUNW Sun Microsystems, Inc tbs TBS Technologies tcl Toby Churchill Ltd. technologic Technologic Systems -- cgit From c1e9b3b0eea12899b7749571af21cc60822cf2b6 Mon Sep 17 00:00:00 2001 From: Anatoly Pugachev Date: Tue, 26 Jan 2016 00:19:02 +0300 Subject: hwrng: n2 - Attach on T5/M5, T7/M7 SPARC CPUs n2rng: Attach on T5/M5, T7/M7 SPARC CPUs (space to tab fixes after variable names) Signed-off-by: Anatoly Pugachev Signed-off-by: Herbert Xu --- drivers/char/hw_random/n2-drv.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 843d6f6aee7a..3b06c1d6cfb2 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -743,6 +743,16 @@ static const struct of_device_id n2rng_match[] = { .compatible = "SUNW,kt-rng", .data = (void *) 1, }, + { + .name = "random-number-generator", + .compatible = "ORCL,m4-rng", + .data = (void *) 1, + }, + { + .name = "random-number-generator", + .compatible = "ORCL,m7-rng", + .data = (void *) 1, + }, {}, }; MODULE_DEVICE_TABLE(of, n2rng_match); -- cgit From 774e656e94cdd8db27a8831abb3d35fbb95d2bc6 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:29 +0530 Subject: ath10k: fix naming Peer stats rssi_changed field in 10.2.4 Fix naming of peer stats rssi_changed field in 10.2.4 to make it more readable. As of now this field is not used, but necessary to pull in fw_stats with appropriate length. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index e1bb02ba207d..187f495c1fbe 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4233,7 +4233,7 @@ struct wmi_10_2_peer_stats { struct wmi_10_2_4_peer_stats { struct wmi_10_2_peer_stats common; - __le32 unknown_value; /* FIXME: what is this word? */ + __le32 peer_rssi_changed; } __packed; struct wmi_10_2_4_ext_peer_stats { -- cgit From 1fe374f5b07ed58e485fdbfa7410876e25ce1a78 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:30 +0530 Subject: ath10k: cleanup setting pdev paramaters Replace the local variable 'burst_enable' with 'param' for mapping and setting pdev paraemeters and with this patch pretty easy to extend support for new parameters adhering to linux kernel coding guidelines Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 6146a293601a..0d7671c778fd 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3988,7 +3988,7 @@ static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) static int ath10k_start(struct ieee80211_hw *hw) { struct ath10k *ar = hw->priv; - u32 burst_enable; + u32 param; int ret = 0; /* @@ -4031,13 +4031,15 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_power_down; } - ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1); + param = ar->wmi.pdev_param->pmf_qos; + ret = ath10k_wmi_pdev_set_param(ar, param, 1); if (ret) { ath10k_warn(ar, "failed to enable PMF QOS: %d\n", ret); goto err_core_stop; } - ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1); + param = ar->wmi.pdev_param->dynamic_bw; + ret = ath10k_wmi_pdev_set_param(ar, param, 1); if (ret) { ath10k_warn(ar, "failed to enable dynamic BW: %d\n", ret); goto err_core_stop; @@ -4053,8 +4055,8 @@ static int ath10k_start(struct ieee80211_hw *hw) } if (test_bit(WMI_SERVICE_BURST, ar->wmi.svc_map)) { - burst_enable = ar->wmi.pdev_param->burst_enable; - ret = ath10k_wmi_pdev_set_param(ar, burst_enable, 0); + param = ar->wmi.pdev_param->burst_enable; + ret = ath10k_wmi_pdev_set_param(ar, param, 0); if (ret) { ath10k_warn(ar, "failed to disable burst: %d\n", ret); goto err_core_stop; @@ -4072,8 +4074,8 @@ static int ath10k_start(struct ieee80211_hw *hw) * this problem. */ - ret = ath10k_wmi_pdev_set_param(ar, - ar->wmi.pdev_param->arp_ac_override, 0); + param = ar->wmi.pdev_param->arp_ac_override; + ret = ath10k_wmi_pdev_set_param(ar, param, 0); if (ret) { ath10k_warn(ar, "failed to set arp ac override parameter: %d\n", ret); @@ -4092,8 +4094,8 @@ static int ath10k_start(struct ieee80211_hw *hw) } } - ret = ath10k_wmi_pdev_set_param(ar, - ar->wmi.pdev_param->ani_enable, 1); + param = ar->wmi.pdev_param->ani_enable; + ret = ath10k_wmi_pdev_set_param(ar, param, 1); if (ret) { ath10k_warn(ar, "failed to enable ani by default: %d\n", ret); -- cgit From b4619ea2f72153df42d8ba2894b2af5e621d6df6 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:31 +0530 Subject: ath10k: rename few function names of firmware stats Prerequisite patch to address checkpatch errors for the next patch in this series, this function names are bit too long, make it short Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 2bdf5408b0d9..4fb1e0eb3408 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -276,7 +276,7 @@ static const struct file_operations fops_wmi_services = { .llseek = default_llseek, }; -static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) +static void ath10k_fw_stats_pdevs_free(struct list_head *head) { struct ath10k_fw_stats_pdev *i, *tmp; @@ -286,7 +286,7 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) } } -static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) +static void ath10k_fw_stats_vdevs_free(struct list_head *head) { struct ath10k_fw_stats_vdev *i, *tmp; @@ -296,7 +296,7 @@ static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head) } } -static void ath10k_debug_fw_stats_peers_free(struct list_head *head) +static void ath10k_fw_stats_peers_free(struct list_head *head) { struct ath10k_fw_stats_peer *i, *tmp; @@ -310,9 +310,9 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) { spin_lock_bh(&ar->data_lock); ar->debug.fw_stats_done = false; - ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); - ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); - ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); + ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); + ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); + ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); spin_unlock_bh(&ar->data_lock); } @@ -391,9 +391,9 @@ free: /* In some cases lists have been spliced and cleared. Free up * resources if that is not the case. */ - ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); - ath10k_debug_fw_stats_vdevs_free(&stats.vdevs); - ath10k_debug_fw_stats_peers_free(&stats.peers); + ath10k_fw_stats_pdevs_free(&stats.pdevs); + ath10k_fw_stats_vdevs_free(&stats.vdevs); + ath10k_fw_stats_peers_free(&stats.peers); spin_unlock_bh(&ar->data_lock); } -- cgit From d57e7f2e7e042a7cef19702abe42f1e9b55d754c Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:32 +0530 Subject: ath10k: provision to support periodic peer stats update Enable support for periodic peer stats update when peer stats service is enabled. The host to update the peer stats received from the firmware periodically, since firmware will reset this to zero after sometime (due to memory constraints) While enabling periodic peer / vdev stats cleanup the existing list in debugfs if max limit is reached, so that the new stats is updated. Ideally speaking based on 'Michal Kazior's' suggestion we need to completely move to periodic update of all the stats making the 'ping - pong' method obselete. This requires a bit of re-work and some testing as well, also confirmation regarding backward comptability for various firmware and chipsets. Hence allow periodic update only for peer_stats. Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/debug.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 4fb1e0eb3408..3b8da817972b 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -347,7 +347,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * delivered which is treated as end-of-data and is itself discarded */ - if (ar->debug.fw_stats_done) { + if (ar->debug.fw_stats_done && + !test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { ath10k_warn(ar, "received unsolicited stats update event\n"); goto free; } @@ -372,11 +373,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) /* Although this is unlikely impose a sane limit to * prevent firmware from DoS-ing the host. */ + ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); ath10k_warn(ar, "dropping fw peer stats\n"); goto free; } if (num_vdevs >= BITS_PER_LONG) { + ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs); ath10k_warn(ar, "dropping fw vdev stats\n"); goto free; } -- cgit From 8351c052194b30f852db6225a568e48ee2a4947b Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:33 +0530 Subject: ath10k: enable periodic peer stats update Register for 500ms as periodic peer stats update period, and parameters like rx_duration that needs to be tracked in host can be achieved by this provision, also periodic stats update is the future of fw_stats and shall be extended for pdev / vdev stats irrespecitive PEER_STATS service is enabled or not Signed-off-by: Mohammed Shafi Shajakhan [kvalo@qca.qualcomm.com: fix a checkpatch warning] Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 0d7671c778fd..ef0438d2cc8f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4104,6 +4104,18 @@ static int ath10k_start(struct ieee80211_hw *hw) ar->ani_enabled = true; + if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + param = ar->wmi.pdev_param->peer_stats_update_period; + ret = ath10k_wmi_pdev_set_param(ar, param, + PEER_DEFAULT_STATS_UPDATE_PERIOD); + if (ret) { + ath10k_warn(ar, + "failed to set peer stats period : %d\n", + ret); + goto err_core_stop; + } + } + ar->num_started_vdevs = 0; ath10k_regd_update(ar); -- cgit From 856e7c3084399fb7e029628dbe43dcb9bb7d7b5b Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Jan 2016 21:16:34 +0530 Subject: ath10k: add debugfs support for Per STA total rx duration Add debugfs support for per client total rx duration, track this via the report of Peer stats rx duration reported for every 500ms Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.h | 1 + drivers/net/wireless/ath/ath10k/debug.c | 9 ++++-- drivers/net/wireless/ath/ath10k/debug.h | 6 ++++ drivers/net/wireless/ath/ath10k/debugfs_sta.c | 41 +++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d47a08568bdc..921b86a4f257 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -316,6 +316,7 @@ struct ath10k_sta { #ifdef CONFIG_MAC80211_DEBUGFS /* protected by conf_mutex */ bool aggr_mode; + u64 rx_duration; #endif }; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 3b8da817972b..8d4148a96af8 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -319,7 +319,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; + bool is_start, is_started, is_end, peer_stats_svc; size_t num_peers; size_t num_vdevs; int ret; @@ -347,8 +347,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * delivered which is treated as end-of-data and is itself discarded */ - if (ar->debug.fw_stats_done && - !test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { + peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map); + if (ar->debug.fw_stats_done && !peer_stats_svc) { ath10k_warn(ar, "received unsolicited stats update event\n"); goto free; } @@ -384,6 +384,9 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } + if (peer_stats_svc) + ath10k_sta_update_rx_duration(ar, &stats.peers); + list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs); } diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 814719cf4f22..f273478e2afb 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -153,6 +153,12 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) #ifdef CONFIG_MAC80211_DEBUGFS void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); +void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *peer); +#else +static inline void ath10k_sta_update_rx_duration(struct ath10k *ar, + struct list_head *peer) +{ +} #endif /* CONFIG_MAC80211_DEBUGFS */ #ifdef CONFIG_ATH10K_DEBUG diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 95b5c49374e0..67ef75b60567 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -18,6 +18,23 @@ #include "wmi-ops.h" #include "debug.h" +void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head) +{ struct ieee80211_sta *sta; + struct ath10k_fw_stats_peer *peer; + struct ath10k_sta *arsta; + + rcu_read_lock(); + list_for_each_entry(peer, head, list) { + sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr, + NULL); + if (!sta) + continue; + arsta = (struct ath10k_sta *)sta->drv_priv; + arsta->rx_duration += (u64)peer->rx_duration; + } + rcu_read_unlock(); +} + static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -232,6 +249,28 @@ static const struct file_operations fops_delba = { .llseek = default_llseek, }; +static ssize_t ath10k_dbg_sta_read_rx_duration(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta = file->private_data; + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + char buf[100]; + int len = 0; + + len = scnprintf(buf, sizeof(buf), + "%llu usecs\n", arsta->rx_duration); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_rx_duration = { + .read = ath10k_dbg_sta_read_rx_duration, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir) { @@ -240,4 +279,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); + debugfs_create_file("rx_duration", S_IRUGO, dir, sta, + &fops_rx_duration); } -- cgit From 8b019fb0d0e75e2f682f17742b99c0ca970ca024 Mon Sep 17 00:00:00 2001 From: Yanbo Li Date: Thu, 14 Jan 2016 15:39:19 -0800 Subject: ath10k: remove the p2p notice of absence info from 10.2.4 FW beacon info The p2p NOA never been supported at 10.2.4 FW, remove it to avoid SWBA event parse error for multi beacon interval case. Signed-off-by: Yanbo Li Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.c | 46 ++++++++++++++++++++++++++++++++++- drivers/net/wireless/ath/ath10k/wmi.h | 10 ++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index c610d1761940..0f01a8d99604 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3256,6 +3256,50 @@ static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, return 0; } +static int ath10k_wmi_10_2_4_op_pull_swba_ev(struct ath10k *ar, + struct sk_buff *skb, + struct wmi_swba_ev_arg *arg) +{ + struct wmi_10_2_4_host_swba_event *ev = (void *)skb->data; + u32 map; + size_t i; + + if (skb->len < sizeof(*ev)) + return -EPROTO; + + skb_pull(skb, sizeof(*ev)); + arg->vdev_map = ev->vdev_map; + + for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) { + if (!(map & BIT(0))) + continue; + + /* If this happens there were some changes in firmware and + * ath10k should update the max size of tim_info array. + */ + if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info))) + break; + + if (__le32_to_cpu(ev->bcn_info[i].tim_info.tim_len) > + sizeof(ev->bcn_info[i].tim_info.tim_bitmap)) { + ath10k_warn(ar, "refusing to parse invalid swba structure\n"); + return -EPROTO; + } + + arg->tim_info[i].tim_len = ev->bcn_info[i].tim_info.tim_len; + arg->tim_info[i].tim_mcast = ev->bcn_info[i].tim_info.tim_mcast; + arg->tim_info[i].tim_bitmap = + ev->bcn_info[i].tim_info.tim_bitmap; + arg->tim_info[i].tim_changed = + ev->bcn_info[i].tim_info.tim_changed; + arg->tim_info[i].tim_num_ps_pending = + ev->bcn_info[i].tim_info.tim_num_ps_pending; + i++; + } + + return 0; +} + static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb, struct wmi_swba_ev_arg *arg) @@ -7584,7 +7628,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { .pull_ch_info = ath10k_wmi_op_pull_ch_info_ev, .pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev, .pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev, - .pull_swba = ath10k_wmi_op_pull_swba_ev, + .pull_swba = ath10k_wmi_10_2_4_op_pull_swba_ev, .pull_phyerr_hdr = ath10k_wmi_op_pull_phyerr_ev_hdr, .pull_phyerr = ath10k_wmi_op_pull_phyerr_ev, .pull_rdy = ath10k_wmi_op_pull_rdy_ev, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 187f495c1fbe..806d4bb6e7d6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -5454,6 +5454,16 @@ struct wmi_host_swba_event { struct wmi_bcn_info bcn_info[0]; } __packed; +struct wmi_10_2_4_bcn_info { + struct wmi_tim_info tim_info; + /* The 10.2.4 FW doesn't have p2p NOA info */ +} __packed; + +struct wmi_10_2_4_host_swba_event { + __le32 vdev_map; + struct wmi_10_2_4_bcn_info bcn_info[0]; +} __packed; + /* 16 words = 512 client + 1 word = for guard */ #define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17 -- cgit From b9a9693fd9aea43f50b107dfc8cbaea317f95a79 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 27 Nov 2015 09:37:14 +0100 Subject: ath9k: request NOA update when chanctx active Request NOA update when chanctx active, also in case of STA. Signed-off-by: Janusz Dziedzic Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/channel.c | 2 +- drivers/net/wireless/ath/ath9k/main.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 50e614b915f1..0bcb82abd094 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -1454,7 +1454,7 @@ static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) if (!sc->p2p_ps_timer) return; - if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p) + if (vif->type != NL80211_IFTYPE_STATION) return; sc->p2p_ps_vif = avp; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c1b33fdcca08..4ae63fd4290e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -978,7 +978,7 @@ static void ath9k_update_bssid_mask(struct ath_softc *sc, if (ctx->nvifs_assigned != 1) continue; - if (!avp->vif->p2p || !iter_data->has_hw_macaddr) + if (!iter_data->has_hw_macaddr) continue; ether_addr_copy(common->curbssid, avp->bssid); @@ -1255,6 +1255,9 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); sc->cur_chan->nvifs++; + if (vif->type == NL80211_IFTYPE_STATION && ath9k_is_chanctx_enabled()) + vif->driver_flags |= IEEE80211_VIF_GET_NOA_UPDATE; + if (ath9k_uses_beacons(vif->type)) ath9k_beacon_assign_slot(sc, vif); -- cgit From aea57edf80c6e96d6dc24757599396af99c02b19 Mon Sep 17 00:00:00 2001 From: Alexander Tsoy Date: Fri, 8 Jan 2016 01:26:03 +0300 Subject: ath9k_htc: add device ID for Toshiba WLM-20U2/GN-1080 This device is available under different marketing names: WLM-20U2 - Wireless USB Dongle for Toshiba TVs GN-1080 - Wireless LAN Module for Toshiba MFPs. Signed-off-by: Alexander Tsoy Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hif_usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 165dd202c365..8cbf4904db7b 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -55,6 +55,8 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { .driver_info = AR9280_USB }, /* Buffalo WLI-UV-AG300P */ { USB_DEVICE(0x04da, 0x3904), .driver_info = AR9280_USB }, + { USB_DEVICE(0x0930, 0x0a08), + .driver_info = AR9280_USB }, /* Toshiba WLM-20U2 and GN-1080 */ { USB_DEVICE(0x0cf3, 0x20ff), .driver_info = STORAGE_DEVICE }, -- cgit From c5a157e4d7d7f1d39dbb382bc3ad7ea9f248ed7d Mon Sep 17 00:00:00 2001 From: Lior David Date: Sun, 17 Jan 2016 12:39:06 +0200 Subject: wil6210: fix privacy flag calculation in change_beacon Currently the privacy flag calculation in change_beacon checks for RSN IE inside proberesp_ies, but normally it is not found there. It works today because of code inside the function wil_fix_bcon, but wil_fix_bcon is not directly related to change_beacon, and it may be changed or removed in the future and break the calculation. To fix this issue, change the privacy flag calculation to check RSN IE inside the beacon itself. The new check is more reliable and will not be sensitive to changes in wil_fix_bcon. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 20d07ef679e8..182f071f722d 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -828,9 +828,9 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, wil_print_bcon_data(bcon); } - if (bcon->proberesp_ies && - cfg80211_find_ie(WLAN_EID_RSN, bcon->proberesp_ies, - bcon->proberesp_ies_len)) + if (bcon->tail && + cfg80211_find_ie(WLAN_EID_RSN, bcon->tail, + bcon->tail_len)) privacy = 1; /* in case privacy has changed, need to restart the AP */ -- cgit From c100c883e785802ab333604237928a65ae62c6bc Mon Sep 17 00:00:00 2001 From: Lior David Date: Sun, 17 Jan 2016 12:39:07 +0200 Subject: wil6210: use extra IEs from probe response In the start_ap/change_beacon API, when we set up probe response offloading, we only use the IE list from the probe response template and not the IE list from the proberesp_ies argument. As a result, we miss important IEs and it causes problems with some scenarios such as P2P. With this change, we merge the list of IEs from the probe response template and proberesp_ies and send the merged list to the FW for offloading. It is still FW responsibility to filter out irrelevant IEs when sending probe response, based on the actual contents of the probe request. Also in case association response termplate is not provided, we will use the merged list of IEs from probe response in the association response as well. Signed-off-by: Lior David Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 141 ++++++++++++++++++++-------- 1 file changed, 102 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 182f071f722d..774352f9e256 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -696,6 +696,79 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, return rc; } +/** + * find a specific IE in a list of IEs + * return a pointer to the beginning of IE in the list + * or NULL if not found + */ +static const u8 *_wil_cfg80211_find_ie(const u8 *ies, u16 ies_len, const u8 *ie, + u16 ie_len) +{ + struct ieee80211_vendor_ie *vie; + u32 oui; + + /* IE tag at offset 0, length at offset 1 */ + if (ie_len < 2 || 2 + ie[1] > ie_len) + return NULL; + + if (ie[0] != WLAN_EID_VENDOR_SPECIFIC) + return cfg80211_find_ie(ie[0], ies, ies_len); + + /* make sure there is room for 3 bytes OUI + 1 byte OUI type */ + if (ie[1] < 4) + return NULL; + vie = (struct ieee80211_vendor_ie *)ie; + oui = vie->oui[0] << 16 | vie->oui[1] << 8 | vie->oui[2]; + return cfg80211_find_vendor_ie(oui, vie->oui_type, ies, + ies_len); +} + +/** + * merge the IEs in two lists into a single list. + * do not include IEs from the second list which exist in the first list. + * add only vendor specific IEs from second list to keep + * the merged list sorted (since vendor-specific IE has the + * highest tag number) + * caller must free the allocated memory for merged IEs + */ +static int _wil_cfg80211_merge_extra_ies(const u8 *ies1, u16 ies1_len, + const u8 *ies2, u16 ies2_len, + u8 **merged_ies, u16 *merged_len) +{ + u8 *buf, *dpos; + const u8 *spos; + + if (ies1_len == 0 && ies2_len == 0) { + *merged_ies = NULL; + *merged_len = 0; + return 0; + } + + buf = kmalloc(ies1_len + ies2_len, GFP_KERNEL); + if (!buf) + return -ENOMEM; + memcpy(buf, ies1, ies1_len); + dpos = buf + ies1_len; + spos = ies2; + while (spos + 1 < ies2 + ies2_len) { + /* IE tag at offset 0, length at offset 1 */ + u16 ielen = 2 + spos[1]; + + if (spos + ielen > ies2 + ies2_len) + break; + if (spos[0] == WLAN_EID_VENDOR_SPECIFIC && + !_wil_cfg80211_find_ie(ies1, ies1_len, spos, ielen)) { + memcpy(dpos, spos, ielen); + dpos += ielen; + } + spos += ielen; + } + + *merged_ies = buf; + *merged_len = dpos - buf; + return 0; +} + static void wil_print_bcon_data(struct cfg80211_beacon_data *b) { print_hex_dump_bytes("head ", DUMP_PREFIX_OFFSET, @@ -712,49 +785,49 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b) b->assocresp_ies, b->assocresp_ies_len); } -static int wil_fix_bcon(struct wil6210_priv *wil, - struct cfg80211_beacon_data *bcon) -{ - struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp; - size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - - if (bcon->probe_resp_len <= hlen) - return 0; - -/* always use IE's from full probe frame, they has more info - * notable RSN - */ - bcon->proberesp_ies = f->u.probe_resp.variable; - bcon->proberesp_ies_len = bcon->probe_resp_len - hlen; - if (!bcon->assocresp_ies) { - bcon->assocresp_ies = bcon->proberesp_ies; - bcon->assocresp_ies_len = bcon->proberesp_ies_len; - } - - return 1; -} - /* internal functions for device reset and starting AP */ static int _wil_cfg80211_set_ies(struct wiphy *wiphy, struct cfg80211_beacon_data *bcon) { int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); + u16 len = 0, proberesp_len = 0; + u8 *ies = NULL, *proberesp = NULL; + + if (bcon->probe_resp) { + struct ieee80211_mgmt *f = + (struct ieee80211_mgmt *)bcon->probe_resp; + size_t hlen = offsetof(struct ieee80211_mgmt, + u.probe_resp.variable); + proberesp = f->u.probe_resp.variable; + proberesp_len = bcon->probe_resp_len - hlen; + } + rc = _wil_cfg80211_merge_extra_ies(proberesp, + proberesp_len, + bcon->proberesp_ies, + bcon->proberesp_ies_len, + &ies, &len); - rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, - bcon->proberesp_ies); if (rc) - return rc; + goto out; - rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, - bcon->assocresp_ies); + rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies); + if (rc) + goto out; + + if (bcon->assocresp_ies) + rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, + bcon->assocresp_ies_len, bcon->assocresp_ies); + else + rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies); #if 0 /* to use beacon IE's, remove this #if 0 */ if (rc) - return rc; + goto out; rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail); #endif - +out: + kfree(ies); return rc; } @@ -823,11 +896,6 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, wil_dbg_misc(wil, "%s()\n", __func__); wil_print_bcon_data(bcon); - if (wil_fix_bcon(wil, bcon)) { - wil_dbg_misc(wil, "Fixed bcon\n"); - wil_print_bcon_data(bcon); - } - if (bcon->tail && cfg80211_find_ie(WLAN_EID_RSN, bcon->tail, bcon->tail_len)) @@ -900,11 +968,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, wil_print_bcon_data(bcon); wil_print_crypto(wil, crypto); - if (wil_fix_bcon(wil, bcon)) { - wil_dbg_misc(wil, "Fixed bcon\n"); - wil_print_bcon_data(bcon); - } - rc = _wil_cfg80211_start_ap(wiphy, ndev, info->ssid, info->ssid_len, info->privacy, info->beacon_interval, channel->hw_value, -- cgit From 640751ac30b2ddfbe06ad712aa7d57a8d89a7eef Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 17 Jan 2016 12:39:08 +0200 Subject: wil6210: handle tx completions only if vring tx data is enabled wil_vring_fini_tx is called in disconnect in order to free the allocated vrings. wil_vring_fini_tx is disabling the vring_tx_data before napi_synchronize is called in order to avoid the tx handling of this vring, while wil_vring_free is called only after napi finished the current handling of the tx completed packets. Due to that, in case of disconnect, wil6210_netdev_poll_tx can be called when vring->va is not NULL but vring_tx_data[i]->enabled is already disabled. This patch checks vring_tx_data[i]->enabled in wil6210_netdev_poll_tx to prevent handling of disabled vrings. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/netdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 56aaa2d4fb0e..ecc3c1bdae4b 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -108,8 +108,9 @@ static int wil6210_netdev_poll_tx(struct napi_struct *napi, int budget) /* always process ALL Tx complete, regardless budget - it is fast */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { struct vring *vring = &wil->vring_tx[i]; + struct vring_tx_data *txdata = &wil->vring_tx_data[i]; - if (!vring->va) + if (!vring->va || !txdata->enabled) continue; tx_done += wil_tx_complete(wil, i); -- cgit From b729aaf066b013458e95cd6c69a5e371eb9ce355 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 17 Jan 2016 12:39:09 +0200 Subject: wil6210: find TX vring only if vring_tx_data is enabled In TX vring allocation, vring_tx->va is allocated before WMI command to configure the vring is sent to the device. As the WMI command can take time to complete, it can lead to scenarios where vring_tx->va is not NULL but vring is still not enabled. This patch adds a check that vring_tx_data is enabled before returning a valid TX vring. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/txrx.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 7887e6cfd817..c22ee8b3ed9b 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -911,10 +911,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, continue; if (wil->vring2cid_tid[i][0] == cid) { struct vring *v = &wil->vring_tx[i]; + struct vring_tx_data *txdata = &wil->vring_tx_data[i]; wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n", __func__, eth->h_dest, i); - if (v->va) { + if (v->va && txdata->enabled) { return v; } else { wil_dbg_txrx(wil, "vring[%d] not valid\n", i); @@ -935,6 +936,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, struct vring *v; int i; u8 cid; + struct vring_tx_data *txdata; /* In the STA mode, it is expected to have only 1 VRING * for the AP we connected to. @@ -942,7 +944,8 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil, */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { v = &wil->vring_tx[i]; - if (!v->va) + txdata = &wil->vring_tx_data[i]; + if (!v->va || !txdata->enabled) continue; cid = wil->vring2cid_tid[i][0]; @@ -978,12 +981,14 @@ static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil, struct sk_buff *skb) { struct vring *v; + struct vring_tx_data *txdata; int i = wil->bcast_vring; if (i < 0) return NULL; v = &wil->vring_tx[i]; - if (!v->va) + txdata = &wil->vring_tx_data[i]; + if (!v->va || !txdata->enabled) return NULL; if (!wil->vring_tx_data[i].dot1x_open && (skb->protocol != cpu_to_be16(ETH_P_PAE))) @@ -1010,11 +1015,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil, u8 cid; struct ethhdr *eth = (void *)skb->data; char *src = eth->h_source; + struct vring_tx_data *txdata; /* find 1-st vring eligible for data */ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) { v = &wil->vring_tx[i]; - if (!v->va) + txdata = &wil->vring_tx_data[i]; + if (!v->va || !txdata->enabled) continue; cid = wil->vring2cid_tid[i][0]; -- cgit From 0916d9f2b6bea53a830ae5061b63a515c04da62e Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 17 Jan 2016 12:39:10 +0200 Subject: wil6210: handle multiple connect/disconnect events In the current solution wil6210 configures the vring in a worker and holds only one pending CID. This implementation may lead to race conditions between connect and disconnect events of multiple stations or fast connect/disconnect events of the same station. In order to allow the removal of the connect worker and handling of WMI_VRING_CFG_DONE_EVENTID in the connect event, the WMI replies that provide the reply in a given buffer needs to be handled immediately in the WMI event interrupt thread. To prevent deadlocks, WMI replies that requires additional handling are still handled via the events list. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 81 +++++++-------- drivers/net/wireless/ath/wil6210/txrx.c | 3 + drivers/net/wireless/ath/wil6210/wil6210.h | 8 +- drivers/net/wireless/ath/wil6210/wmi.c | 157 +++++++++++++++++++++-------- 4 files changed, 156 insertions(+), 93 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index b39f0bfc591e..0652efed6b5d 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -155,7 +155,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) if (sta->status != wil_sta_unused) { if (!from_event) - wmi_disconnect_sta(wil, sta->addr, reason_code); + wmi_disconnect_sta(wil, sta->addr, reason_code, true); switch (wdev->iftype) { case NL80211_IFTYPE_AP: @@ -195,8 +195,8 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, struct wireless_dev *wdev = wil->wdev; might_sleep(); - wil_dbg_misc(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, - reason_code, from_event ? "+" : "-"); + wil_info(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, + reason_code, from_event ? "+" : "-"); /* Cases are: * - disconnect single STA, still connected @@ -258,13 +258,16 @@ static void wil_disconnect_worker(struct work_struct *work) static void wil_connect_timer_fn(ulong x) { struct wil6210_priv *wil = (void *)x; + bool q; - wil_dbg_misc(wil, "Connect timeout\n"); + wil_err(wil, "Connect timeout detected, disconnect station\n"); /* reschedule to thread context - disconnect won't - * run from atomic context + * run from atomic context. + * queue on wmi_wq to prevent race with connect event. */ - schedule_work(&wil->disconnect_worker); + q = queue_work(wil->wmi_wq, &wil->disconnect_worker); + wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q); } static void wil_scan_timer_fn(ulong x) @@ -369,6 +372,32 @@ static int wil_find_free_vring(struct wil6210_priv *wil) return -EINVAL; } +int wil_tx_init(struct wil6210_priv *wil, int cid) +{ + int rc = -EINVAL, ringid; + + if (cid < 0) { + wil_err(wil, "No connection pending\n"); + goto out; + } + ringid = wil_find_free_vring(wil); + if (ringid < 0) { + wil_err(wil, "No free vring found\n"); + goto out; + } + + wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", + cid, ringid); + + rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); + if (rc) + wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n", + cid, ringid); + +out: + return rc; +} + int wil_bcast_init(struct wil6210_priv *wil) { int ri = wil->bcast_vring, rc; @@ -399,41 +428,6 @@ void wil_bcast_fini(struct wil6210_priv *wil) wil_vring_fini_tx(wil, ri); } -static void wil_connect_worker(struct work_struct *work) -{ - int rc, cid, ringid; - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - connect_worker); - struct net_device *ndev = wil_to_ndev(wil); - - mutex_lock(&wil->mutex); - - cid = wil->pending_connect_cid; - if (cid < 0) { - wil_err(wil, "No connection pending\n"); - goto out; - } - ringid = wil_find_free_vring(wil); - if (ringid < 0) { - wil_err(wil, "No free vring found\n"); - goto out; - } - - wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n", - cid, ringid); - - rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0); - wil->pending_connect_cid = -1; - if (rc == 0) { - wil->sta[cid].status = wil_sta_connected; - netif_tx_wake_all_queues(ndev); - } else { - wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); - } -out: - mutex_unlock(&wil->mutex); -} - int wil_priv_init(struct wil6210_priv *wil) { uint i; @@ -453,12 +447,10 @@ int wil_priv_init(struct wil6210_priv *wil) init_completion(&wil->wmi_ready); init_completion(&wil->wmi_call); - wil->pending_connect_cid = -1; 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); - INIT_WORK(&wil->connect_worker, wil_connect_worker); 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); @@ -844,7 +836,6 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } /* init after reset */ - wil->pending_connect_cid = -1; wil->ap_isolate = 0; reinit_completion(&wil->wmi_ready); reinit_completion(&wil->wmi_call); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index c22ee8b3ed9b..9680b970b863 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -794,6 +794,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, txdata->dot1x_open = false; txdata->enabled = 0; wil_vring_free(wil, vring, 1); + wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; + wil->vring2cid_tid[id][1] = 0; + out: return rc; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 235e205ce2bc..1b8fa1d2bae9 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -581,12 +581,10 @@ struct wil6210_priv { struct workqueue_struct *wmi_wq; /* for deferred calls */ struct work_struct wmi_event_worker; struct workqueue_struct *wq_service; - struct work_struct connect_worker; struct work_struct disconnect_worker; struct work_struct fw_error_worker; /* for FW error recovery */ struct timer_list connect_timer; struct timer_list scan_timer; /* detect scan timeout */ - int pending_connect_cid; struct list_head pending_wmi_ev; /* * protect pending_wmi_ev @@ -756,7 +754,8 @@ 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); +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, + bool full_disconnect); int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); @@ -807,6 +806,7 @@ void wil_rx_fini(struct wil6210_priv *wil); int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, int cid, int tid); void wil_vring_fini_tx(struct wil6210_priv *wil, int id); +int wil_tx_init(struct wil6210_priv *wil, int cid); int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size); int wil_bcast_init(struct wil6210_priv *wil); void wil_bcast_fini(struct wil6210_priv *wil); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index e3ea74cdd4aa..e1a6cb8840ed 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -426,6 +426,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) const size_t assoc_req_ie_offset = sizeof(u16) * 2; /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ const size_t assoc_resp_ie_offset = sizeof(u16) * 3; + int rc; if (len < sizeof(*evt)) { wil_err(wil, "Connect event too short : %d bytes\n", len); @@ -445,8 +446,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } ch = evt->channel + 1; - wil_dbg_wmi(wil, "Connect %pM channel [%d] cid %d\n", - evt->bssid, ch, evt->cid); + wil_info(wil, "Connect %pM channel [%d] cid %d\n", + evt->bssid, ch, evt->cid); wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, evt->assoc_info, len - sizeof(*evt), true); @@ -468,20 +469,67 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) assoc_resp_ielen = 0; } + mutex_lock(&wil->mutex); + if (test_bit(wil_status_resetting, wil->status) || + !test_bit(wil_status_fwready, wil->status)) { + wil_err(wil, "status_resetting, cancel connect event, CID %d\n", + evt->cid); + mutex_unlock(&wil->mutex); + /* no need for cleanup, wil_reset will do that */ + return; + } + if ((wdev->iftype == NL80211_IFTYPE_STATION) || (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { if (!test_bit(wil_status_fwconnecting, wil->status)) { wil_err(wil, "Not in connecting state\n"); + mutex_unlock(&wil->mutex); return; } del_timer_sync(&wil->connect_timer); - cfg80211_connect_result(ndev, evt->bssid, - assoc_req_ie, assoc_req_ielen, - assoc_resp_ie, assoc_resp_ielen, - WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + + /* FIXME FW can transmit only ucast frames to peer */ + /* FIXME real ring_id instead of hard coded 0 */ + ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); + wil->sta[evt->cid].status = wil_sta_conn_pending; + rc = wil_tx_init(wil, evt->cid); + if (rc) { + wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n", + __func__, evt->cid, rc); + wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, + WLAN_REASON_UNSPECIFIED, false); + } else { + wil_info(wil, "%s: successful connection to CID %d\n", + __func__, evt->cid); + } + + if ((wdev->iftype == NL80211_IFTYPE_STATION) || + (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { + if (rc) { + netif_tx_stop_all_queues(ndev); + netif_carrier_off(ndev); + wil_err(wil, + "%s: cfg80211_connect_result with failure\n", + __func__); + cfg80211_connect_result(ndev, evt->bssid, NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + goto out; + } else { + cfg80211_connect_result(ndev, evt->bssid, + assoc_req_ie, assoc_req_ielen, + assoc_resp_ie, assoc_resp_ielen, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + } } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { + if (rc) + goto out; + memset(&sinfo, 0, sizeof(sinfo)); sinfo.generation = wil->sinfo_gen++; @@ -492,17 +540,21 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); + } else { + wil_err(wil, "%s: unhandled iftype %d for CID %d\n", + __func__, wdev->iftype, evt->cid); + goto out; } - clear_bit(wil_status_fwconnecting, wil->status); - set_bit(wil_status_fwconnected, wil->status); - /* FIXME FW can transmit only ucast frames to peer */ - /* FIXME real ring_id instead of hard coded 0 */ - ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid); - wil->sta[evt->cid].status = wil_sta_conn_pending; + wil->sta[evt->cid].status = wil_sta_connected; + set_bit(wil_status_fwconnected, wil->status); + netif_tx_wake_all_queues(ndev); - wil->pending_connect_cid = evt->cid; - queue_work(wil->wq_service, &wil->connect_worker); +out: + if (rc) + wil->sta[evt->cid].status = wil_sta_unused; + clear_bit(wil_status_fwconnecting, wil->status); + mutex_unlock(&wil->mutex); } static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, @@ -511,8 +563,8 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, struct wmi_disconnect_event *evt = d; u16 reason_code = le16_to_cpu(evt->protocol_reason_status); - wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", - evt->bssid, reason_code, evt->disconnect_reason); + wil_info(wil, "Disconnect %pM reason [proto %d wmi %d]\n", + evt->bssid, reason_code, evt->disconnect_reason); wil->sinfo_gen++; @@ -727,6 +779,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) void __iomem *src; ulong flags; unsigned n; + unsigned int num_immed_reply = 0; if (!test_bit(wil_status_mbox_ready, wil->status)) { wil_err(wil, "Reset in progress. Cannot handle WMI event\n"); @@ -736,6 +789,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) for (n = 0;; n++) { u16 len; bool q; + bool immed_reply = false; r->head = wil_r(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, rx.head)); @@ -784,6 +838,13 @@ void wmi_recv_cmd(struct wil6210_priv *wil) struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; u16 id = le16_to_cpu(wmi->id); u32 tstamp = le32_to_cpu(wmi->timestamp); + if (wil->reply_id && wil->reply_id == id) { + if (wil->reply_buf) { + memcpy(wil->reply_buf, wmi, + min(len, wil->reply_size)); + immed_reply = true; + } + } wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n", id, wmi->mid, tstamp); @@ -799,15 +860,24 @@ void wmi_recv_cmd(struct wil6210_priv *wil) wil_w(wil, RGF_MBOX + offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail); - /* add to the pending list */ - spin_lock_irqsave(&wil->wmi_ev_lock, flags); - list_add_tail(&evt->list, &wil->pending_wmi_ev); - spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); - q = queue_work(wil->wmi_wq, &wil->wmi_event_worker); - wil_dbg_wmi(wil, "queue_work -> %d\n", q); + if (immed_reply) { + wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", + __func__, wil->reply_id); + kfree(evt); + num_immed_reply++; + complete(&wil->wmi_call); + } else { + /* add to the pending list */ + spin_lock_irqsave(&wil->wmi_ev_lock, flags); + list_add_tail(&evt->list, &wil->pending_wmi_ev); + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); + q = queue_work(wil->wmi_wq, &wil->wmi_event_worker); + wil_dbg_wmi(wil, "queue_work -> %d\n", q); + } } /* normally, 1 event per IRQ should be processed */ - wil_dbg_wmi(wil, "%s -> %d events queued\n", __func__, n); + wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__, + n - num_immed_reply, num_immed_reply); } int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, @@ -1184,7 +1254,8 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) return 0; } -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, + bool full_disconnect) { int rc; u16 reason_code; @@ -1208,19 +1279,20 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason) return rc; } - /* call event handler manually after processing wmi_call, - * to avoid deadlock - disconnect event handler acquires wil->mutex - * while it is already held here - */ - reason_code = le16_to_cpu(reply.evt.protocol_reason_status); - - wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", - reply.evt.bssid, reason_code, - reply.evt.disconnect_reason); + if (full_disconnect) { + /* call event handler manually after processing wmi_call, + * to avoid deadlock - disconnect event handler acquires + * wil->mutex while it is already held here + */ + reason_code = le16_to_cpu(reply.evt.protocol_reason_status); - wil->sinfo_gen++; - wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); + wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n", + reply.evt.bssid, reason_code, + reply.evt.disconnect_reason); + wil->sinfo_gen++; + wil6210_disconnect(wil, reply.evt.bssid, reason_code, true); + } return 0; } @@ -1348,14 +1420,11 @@ static void wmi_event_handle(struct wil6210_priv *wil, id, wil->reply_id); /* check if someone waits for this event */ if (wil->reply_id && wil->reply_id == id) { - if (wil->reply_buf) { - memcpy(wil->reply_buf, wmi, - min(len, wil->reply_size)); - } else { - wmi_evt_call_handler(wil, id, evt_data, - len - sizeof(*wmi)); - } - wil_dbg_wmi(wil, "Complete WMI 0x%04x\n", id); + WARN_ON(wil->reply_buf); + wmi_evt_call_handler(wil, id, evt_data, + len - sizeof(*wmi)); + wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", + __func__, id); complete(&wil->wmi_call); return; } -- cgit From 424aecaa797901708e7f260b642d27b077cdb491 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 14 Jan 2016 03:15:13 +0100 Subject: ath9k_hw: add low power tx gain table for AR953x Used in some newer TP-Link AR9533 devices. Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 3 ++ drivers/net/wireless/ath/ath9k/ar953x_initvals.h | 65 ++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 8b238c15916d..2fe12b0de5b4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -698,6 +698,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah) else if (AR_SREV_9340(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9340Modes_low_ob_db_tx_gain_table_1p0); + else if (AR_SREV_9531_11(ah)) + INIT_INI_ARRAY(&ah->iniModesTxGain, + qca953x_1p1_modes_no_xpa_low_power_tx_gain_table); else if (AR_SREV_9485_11_OR_LATER(ah)) INIT_INI_ARRAY(&ah->iniModesTxGain, ar9485Modes_low_ob_db_tx_gain_1_1); diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 6fc0d07e5ec6..c0b90daa3e3d 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h @@ -757,6 +757,71 @@ static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = { {0x00016448, 0x6c927a70}, }; +static const u32 qca953x_1p1_modes_no_xpa_low_power_tx_gain_table[][2] = { + /* Addr allmodes */ + {0x0000a2dc, 0xfff55592}, + {0x0000a2e0, 0xfff99924}, + {0x0000a2e4, 0xfffe1e00}, + {0x0000a2e8, 0xffffe000}, + {0x0000a410, 0x000050d6}, + {0x0000a500, 0x00000069}, + {0x0000a504, 0x0400006b}, + {0x0000a508, 0x0800006d}, + {0x0000a50c, 0x0c000269}, + {0x0000a510, 0x1000026b}, + {0x0000a514, 0x1400026d}, + {0x0000a518, 0x18000669}, + {0x0000a51c, 0x1c00066b}, + {0x0000a520, 0x1d000a68}, + {0x0000a524, 0x21000a6a}, + {0x0000a528, 0x25000a6c}, + {0x0000a52c, 0x29000a6e}, + {0x0000a530, 0x2d0012a9}, + {0x0000a534, 0x310012ab}, + {0x0000a538, 0x350012ad}, + {0x0000a53c, 0x39001b0a}, + {0x0000a540, 0x3d001b0c}, + {0x0000a544, 0x41001b0e}, + {0x0000a548, 0x43001bae}, + {0x0000a54c, 0x45001914}, + {0x0000a550, 0x47001916}, + {0x0000a554, 0x49001b96}, + {0x0000a558, 0x49001b96}, + {0x0000a55c, 0x49001b96}, + {0x0000a560, 0x49001b96}, + {0x0000a564, 0x49001b96}, + {0x0000a568, 0x49001b96}, + {0x0000a56c, 0x49001b96}, + {0x0000a570, 0x49001b96}, + {0x0000a574, 0x49001b96}, + {0x0000a578, 0x49001b96}, + {0x0000a57c, 0x49001b96}, + {0x0000a600, 0x00000000}, + {0x0000a604, 0x00000000}, + {0x0000a608, 0x00000000}, + {0x0000a60c, 0x00000000}, + {0x0000a610, 0x00000000}, + {0x0000a614, 0x00000000}, + {0x0000a618, 0x00804201}, + {0x0000a61c, 0x01408201}, + {0x0000a620, 0x01408502}, + {0x0000a624, 0x01408502}, + {0x0000a628, 0x01408502}, + {0x0000a62c, 0x01408502}, + {0x0000a630, 0x01408502}, + {0x0000a634, 0x01408502}, + {0x0000a638, 0x01408502}, + {0x0000a63c, 0x01408502}, + {0x0000b2dc, 0xfff55592}, + {0x0000b2e0, 0xfff99924}, + {0x0000b2e4, 0xfffe1e00}, + {0x0000b2e8, 0xffffe000}, + {0x00016044, 0x044922db}, + {0x00016048, 0x6c927a70}, + {0x00016444, 0x044922db}, + {0x00016448, 0x6c927a70}, +}; + static const u32 qca953x_2p0_baseband_core[][2] = { /* Addr allmodes */ {0x00009800, 0xafe68e30}, -- cgit From 344cd850b55e9dfd4f3ec1ba564f8edbc8136aca Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 15 Jan 2016 14:41:30 +0100 Subject: ath9k: Drop useless const on chanctx_event_delta() return type drivers/net/wireless/ath/ath9k/channel.c:230: warning: type qualifiers ignored on function return type Signed-off-by: Geert Uytterhoeven Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 0bcb82abd094..319cb5f25f58 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -226,7 +226,7 @@ static const char *chanctx_state_string(enum ath_chanctx_state state) } } -static const u32 chanctx_event_delta(struct ath_softc *sc) +static u32 chanctx_event_delta(struct ath_softc *sc) { u64 ms; struct timespec ts, *old; -- cgit From c1cab1df9b651d999922e0f04d01dc046121a237 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:46 +0800 Subject: ath9k: avoid ANI restart if no trigger Fixes commit 54da20d83f0e ("ath9k_hw: improve ANI processing and rx desensitizing parameters") Call ath9k_ani_restart() only when the phy error rate reach the ANI immunity threshold. Sync the logic with internal code base. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ani.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 25e45e4d1a60..aa82e1326fff 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -450,7 +450,9 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) } else if (cckPhyErrRate > ah->config.cck_trig_high) { ath9k_hw_ani_cck_err_trigger(ah); aniState->ofdmsTurn = true; - } + } else + return; + ath9k_ani_restart(ah); } } -- cgit From 66b533d5adb3eb0cd111b07e516ab13a47ed34f5 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:47 +0800 Subject: ath9k: clean up ANI per-channel pointer checking commit c24bd3620c50 ("ath9k: Do not maintain ANI state per-channel") removed per-channel handling, the code to check 'curchan' also should be removed as never used. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ani.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index aa82e1326fff..815efe9fd208 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -126,12 +126,8 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, static void ath9k_ani_restart(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - if (!ah->curchan) - return; + struct ar5416AniState *aniState = &ah->ani; - aniState = &ah->ani; aniState->listenTime = 0; ENABLE_REGWRITE_BUFFER(ah); @@ -221,12 +217,7 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel, static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - if (!ah->curchan) - return; - - aniState = &ah->ani; + struct ar5416AniState *aniState = &ah->ani; if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1, false); @@ -281,12 +272,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - if (!ah->curchan) - return; - - aniState = &ah->ani; + struct ar5416AniState *aniState = &ah->ani; if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1, @@ -299,9 +285,7 @@ static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) */ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) { - struct ar5416AniState *aniState; - - aniState = &ah->ani; + struct ar5416AniState *aniState = &ah->ani; /* lower OFDM noise immunity */ if (aniState->ofdmNoiseImmunityLevel > 0 && @@ -329,7 +313,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) struct ath_common *common = ath9k_hw_common(ah); int ofdm_nil, cck_nil; - if (!ah->curchan) + if (!chan) return; BUG_ON(aniState == NULL); @@ -416,14 +400,10 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) { - struct ar5416AniState *aniState; + struct ar5416AniState *aniState = &ah->ani; struct ath_common *common = ath9k_hw_common(ah); u32 ofdmPhyErrRate, cckPhyErrRate; - if (!ah->curchan) - return; - - aniState = &ah->ani; if (!ath9k_hw_ani_read_counters(ah)) return; -- cgit From 3f6cc4e57d304f552abc2bdba716519c5e18b442 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:48 +0800 Subject: ath9k: do not reset while BB panic(0x4000409) on ar9561 BB panic(0x4000409) observed while AP enabling/disabling bursting. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 201425e7f9cb..abd964691d8c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -2071,7 +2071,8 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) * to be disabled. * * 0x04000409: Packet stuck on receive. - * Full chip reset is required for all chips except AR9340. + * Full chip reset is required for all chips except + * AR9340, AR9531 and AR9561. */ /* @@ -2100,7 +2101,7 @@ bool ar9003_hw_bb_watchdog_check(struct ath_hw *ah) case 0x04000b09: return true; case 0x04000409: - if (AR_SREV_9340(ah) || AR_SREV_9531(ah)) + if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) return false; else return true; -- cgit From 1542bc37842d5d51e4aa71286a08be9615eba884 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:49 +0800 Subject: ath9k: fix inconsistent use of tab and space in indentation Minor changes for indenting. Signed-off-by: Miaoqing Pan 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 8b4561e8ce1a..54ed2f72d35e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -5485,11 +5485,11 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, AR9300_PAPRD_SCALE_1); else { if (chan->channel >= 5700) - return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), - AR9300_PAPRD_SCALE_1); + return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), + AR9300_PAPRD_SCALE_1); else if (chan->channel >= 5400) return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), - AR9300_PAPRD_SCALE_2); + AR9300_PAPRD_SCALE_2); else return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), AR9300_PAPRD_SCALE_1); -- cgit From 466b0f0208508b08eb59907fac0958d6da7fa3e2 Mon Sep 17 00:00:00 2001 From: Miaoqing Pan Date: Mon, 18 Jan 2016 09:33:50 +0800 Subject: ath9k: fix data bus error on ar9300 and ar9580 One crash issue be found on ar9300: RTC_RC reg read leads crash, leading the data bus error, due to RTC_RC reg write not happen properly. Warm Reset trigger in continuous beacon stuck for one of the customer for other chip, noticed the MAC was stuck in RTC reset. After analysis noticed DMA did not complete when RTC was put in reset. So, before resetting the MAC need to make sure there are no pending DMA transactions because this reset does not reset all parts of the chip. The 12th and 11th bit of MAC _DMA_CFG register used to do that. 12 cfg_halt_ack 0x0 0 DMA has not yet halted 1 DMA has halted 11 cfg_halt_req 0x0 0 DMA logic operates normally 1 Request DMA logic to stop so software can reset the MAC The Bit [12] of this register indicates when the halt has taken effect or not. the DMA halt IS NOT recoverable; once software sets bit [11] to request a DMA halt, software must wait for bit [12] to be set and reset the MAC. So, the same thing we implemented for ar9580 chip. Signed-off-by: Miaoqing Pan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/hw.c | 10 ++++++++++ drivers/net/wireless/ath/ath9k/reg.h | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 257f46ed4a04..e7a31016f370 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1368,6 +1368,16 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) if (ath9k_hw_mci_is_enabled(ah)) ar9003_mci_check_gpm_offset(ah); + /* DMA HALT added to resolve ar9300 and ar9580 bus error during + * RTC_RC reg read + */ + if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { + REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, + 20 * AH_WAIT_TIMEOUT); + REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); + } + REG_WRITE(ah, AR_RTC_RC, rst_flags); REGWRITE_BUFFER_FLUSH(ah); diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index caba54ddad25..c8d35febaf0f 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -34,8 +34,10 @@ #define AR_CFG_SWRG 0x00000010 #define AR_CFG_AP_ADHOC_INDICATION 0x00000020 #define AR_CFG_PHOK 0x00000100 -#define AR_CFG_CLK_GATE_DIS 0x00000400 #define AR_CFG_EEBS 0x00000200 +#define AR_CFG_CLK_GATE_DIS 0x00000400 +#define AR_CFG_HALT_REQ 0x00000800 +#define AR_CFG_HALT_ACK 0x00001000 #define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 #define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 -- cgit From d85ce830eef6c10d1e9617172dea4681f02b8424 Mon Sep 17 00:00:00 2001 From: Markus Trippelsdorf Date: Mon, 14 Dec 2015 16:44:40 +0100 Subject: perf pmu: Fix misleadingly indented assignment (whitespace) One line in perf_pmu__parse_unit() is indented wrongly, leading to a warning (=> error) from gcc 6: util/pmu.c:156:3: error: statement is indented as if it were guarded by... [-Werror=misleading-indentation] sret = read(fd, alias->unit, UNIT_MAX_LEN); ^~~~ util/pmu.c:153:2: note: ...this 'if' clause, but it is not if (fd == -1) ^~ Signed-off-by: Markus Trippelsdorf Acked-by: Ingo Molnar Cc: Ben Hutchings Cc: Matt Fleming Cc: Peter Zijlstra Fixes: 410136f5dd96 ("tools/perf/stat: Add event unit and scale support") Link: http://lkml.kernel.org/r/20151214154440.GC1409@x4 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/pmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index b597bcc8fc78..41a9c875e492 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -153,7 +153,7 @@ static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, char *dir, char *n if (fd == -1) return -1; - sret = read(fd, alias->unit, UNIT_MAX_LEN); + sret = read(fd, alias->unit, UNIT_MAX_LEN); if (sret < 0) goto error; -- cgit From 403567217d3fa5d4801f820317ada52e5c5f0e53 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 20 Jan 2016 12:56:32 +0100 Subject: perf symbols: Do not read symbols/data from device files With mem sampling we could get data source within mapped device file. Processing such sample would block during report phase on trying to read the device file. Chacking for device files and skip the processing if it's detected. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453290995-18485-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/dso.c | 5 +++++ tools/perf/util/symbol.c | 6 +++++- tools/perf/util/util.c | 10 ++++++++++ tools/perf/util/util.h | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index e8e9a9dbf5e3..8e6395439ca0 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -52,6 +52,11 @@ int dso__read_binary_type_filename(const struct dso *dso, debuglink--; if (*debuglink == '/') debuglink++; + + ret = -1; + if (!is_regular_file(filename)) + break; + ret = filename__read_debuglink(filename, debuglink, size - (debuglink - filename)); } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ab02209a7cf3..90cedfa30e43 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1466,7 +1466,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) * Read the build id if possible. This is required for * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work */ - if (filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) + if (is_regular_file(name) && + filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) dso__set_build_id(dso, build_id); /* @@ -1487,6 +1488,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) root_dir, name, PATH_MAX)) continue; + if (!is_regular_file(name)) + continue; + /* Name is now the name of the next image to try */ if (symsrc__init(ss, dso, name, symtab_type) < 0) continue; diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index ead9509835d2..7a2da7ef556e 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -691,3 +691,13 @@ out: return tip; } + +bool is_regular_file(const char *file) +{ + struct stat st; + + if (stat(file, &st)) + return false; + + return S_ISREG(st.st_mode); +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index fe915e616f9b..61650f05e5c1 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -343,5 +343,6 @@ int fetch_kernel_version(unsigned int *puint, #define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) const char *perf_tip(const char *dirpath); +bool is_regular_file(const char *file); #endif /* GIT_COMPAT_UTIL_H */ -- cgit From 86a2cf3123bfec118bfb98728d88be0668779b2b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 20 Jan 2016 12:56:35 +0100 Subject: perf stat: Making several helper functions static There's no need for the following functions to be global: perf_evsel__reset_stat_priv perf_evsel__alloc_stat_priv perf_evsel__free_stat_priv perf_evsel__alloc_prev_raw_counts perf_evsel__free_prev_raw_counts perf_evsel__alloc_stats They all ended up in util/stat.c, and they no longer need to be called from outside this object. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453290995-18485-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/stat.c | 14 +++++++------- tools/perf/util/stat.h | 10 ---------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 2b58edccd56f..beeed0bd3bee 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c @@ -97,7 +97,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) } } -void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) +static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) { int i; struct perf_stat_evsel *ps = evsel->priv; @@ -108,7 +108,7 @@ void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) perf_stat_evsel_id_init(evsel); } -int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) +static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) { evsel->priv = zalloc(sizeof(struct perf_stat_evsel)); if (evsel->priv == NULL) @@ -117,13 +117,13 @@ int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) return 0; } -void perf_evsel__free_stat_priv(struct perf_evsel *evsel) +static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) { zfree(&evsel->priv); } -int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, - int ncpus, int nthreads) +static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, + int ncpus, int nthreads) { struct perf_counts *counts; @@ -134,13 +134,13 @@ int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, return counts ? 0 : -ENOMEM; } -void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) +static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) { perf_counts__delete(evsel->prev_raw_counts); evsel->prev_raw_counts = NULL; } -int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) +static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) { int ncpus = perf_evsel__nr_cpus(evsel); int nthreads = thread_map__nr(evsel->threads); diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 086f4e128d63..2af63c9cb59f 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -74,16 +74,6 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel, double avg, int cpu, enum aggr_mode aggr); -void perf_evsel__reset_stat_priv(struct perf_evsel *evsel); -int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel); -void perf_evsel__free_stat_priv(struct perf_evsel *evsel); - -int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, - int ncpus, int nthreads); -void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel); - -int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw); - int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); void perf_evlist__free_stats(struct perf_evlist *evlist); void perf_evlist__reset_stats(struct perf_evlist *evlist); -- cgit From c84a5d16711619621f368e84a179790df3377c87 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 20 Jan 2016 10:15:20 +0900 Subject: perf hists: Remove parent filter check in DSO filter function The --exclude-other option sets HIST_FILTER__PARENT bit and it's only set when a hist entry was created. DSO filters don't change this so no need to have the check in hists__filter_by_dso() IMHO. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Acked-by: Pekka Enberg Cc: Andi Kleen Cc: David Ahern Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1453252521-24398-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 68a7612019dc..1d8c8eab9daa 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1266,9 +1266,6 @@ void hists__filter_by_dso(struct hists *hists) for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - if (symbol_conf.exclude_other && !h->parent) - continue; - if (hists__filter_entry_by_dso(hists, h)) continue; -- cgit From 1f7c254132f098d19ff3fd452ba9f826cd85c4c0 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 20 Jan 2016 10:15:21 +0900 Subject: perf hists: Cleanup filtering functions The hists__filter_by_xxx functions share same logic with different filters. Factor out the common code into the hists__filter_by_type. Signed-off-by: Namhyung Kim Acked-by: Jiri Olsa Acked-by: Pekka Enberg Cc: Andi Kleen Cc: David Ahern Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1453252521-24398-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 89 ++++++++++++++++---------------------------------- 1 file changed, 29 insertions(+), 60 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 1d8c8eab9daa..81ce0aff69d1 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1254,25 +1254,6 @@ static bool hists__filter_entry_by_dso(struct hists *hists, return false; } -void hists__filter_by_dso(struct hists *hists) -{ - struct rb_node *nd; - - hists->stats.nr_non_filtered_samples = 0; - - hists__reset_filter_stats(hists); - hists__reset_col_len(hists); - - for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - - if (hists__filter_entry_by_dso(hists, h)) - continue; - - hists__remove_entry_filter(hists, h, HIST_FILTER__DSO); - } -} - static bool hists__filter_entry_by_thread(struct hists *hists, struct hist_entry *he) { @@ -1285,25 +1266,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists, return false; } -void hists__filter_by_thread(struct hists *hists) -{ - struct rb_node *nd; - - hists->stats.nr_non_filtered_samples = 0; - - hists__reset_filter_stats(hists); - hists__reset_col_len(hists); - - for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - - if (hists__filter_entry_by_thread(hists, h)) - continue; - - hists__remove_entry_filter(hists, h, HIST_FILTER__THREAD); - } -} - static bool hists__filter_entry_by_symbol(struct hists *hists, struct hist_entry *he) { @@ -1317,25 +1279,6 @@ static bool hists__filter_entry_by_symbol(struct hists *hists, return false; } -void hists__filter_by_symbol(struct hists *hists) -{ - struct rb_node *nd; - - hists->stats.nr_non_filtered_samples = 0; - - hists__reset_filter_stats(hists); - hists__reset_col_len(hists); - - for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - - if (hists__filter_entry_by_symbol(hists, h)) - continue; - - hists__remove_entry_filter(hists, h, HIST_FILTER__SYMBOL); - } -} - static bool hists__filter_entry_by_socket(struct hists *hists, struct hist_entry *he) { @@ -1348,7 +1291,9 @@ static bool hists__filter_entry_by_socket(struct hists *hists, return false; } -void hists__filter_by_socket(struct hists *hists) +typedef bool (*filter_fn_t)(struct hists *hists, struct hist_entry *he); + +static void hists__filter_by_type(struct hists *hists, int type, filter_fn_t filter) { struct rb_node *nd; @@ -1360,13 +1305,37 @@ void hists__filter_by_socket(struct hists *hists) for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - if (hists__filter_entry_by_socket(hists, h)) + if (filter(hists, h)) continue; - hists__remove_entry_filter(hists, h, HIST_FILTER__SOCKET); + hists__remove_entry_filter(hists, h, type); } } +void hists__filter_by_thread(struct hists *hists) +{ + hists__filter_by_type(hists, HIST_FILTER__THREAD, + hists__filter_entry_by_thread); +} + +void hists__filter_by_dso(struct hists *hists) +{ + hists__filter_by_type(hists, HIST_FILTER__DSO, + hists__filter_entry_by_dso); +} + +void hists__filter_by_symbol(struct hists *hists) +{ + hists__filter_by_type(hists, HIST_FILTER__SYMBOL, + hists__filter_entry_by_symbol); +} + +void hists__filter_by_socket(struct hists *hists) +{ + hists__filter_by_type(hists, HIST_FILTER__SOCKET, + hists__filter_entry_by_socket); +} + void events_stats__inc(struct events_stats *stats, u32 type) { ++stats->nr_events[0]; -- cgit From 3379e0c3effa87d7734fc06277a7023292aadb0c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 19 Jan 2016 21:35:15 +0000 Subject: perf tools: Document the perf sysctls perf_event_paranoid was only documented in source code and a perf error message. Copy the documentation from the error message to Documentation/sysctl/kernel.txt. perf_cpu_time_max_percent was already documented but missing from the list at the top, so add it there. Signed-off-by: Ben Hutchings Cc: Peter Zijlstra Cc: linux-doc@vger.kernel.org Link: http://lkml.kernel.org/r/20160119213515.GG2637@decadent.org.uk [ Remove reference to external Documentation file, provide info inline, as before ] Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/sysctl/kernel.txt | 13 +++++++++++++ tools/perf/util/evsel.c | 15 +++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index 73c6b1ef0e84..c803e7300f0b 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -58,6 +58,8 @@ show up in /proc/sys/kernel: - panic_on_stackoverflow - panic_on_unrecovered_nmi - panic_on_warn +- perf_cpu_time_max_percent +- perf_event_paranoid - pid_max - powersave-nap [ PPC only ] - printk @@ -639,6 +641,17 @@ allowed to execute. ============================================================== +perf_event_paranoid: + +Controls use of the performance events system by unprivileged +users (without CAP_SYS_ADMIN). The default value is 1. + + -1: Allow use of (almost) all events by all users +>=0: Disallow raw tracepoint access by users without CAP_IOC_LOCK +>=1: Disallow CPU event access by users without CAP_SYS_ADMIN +>=2: Disallow kernel profiling by users without CAP_SYS_ADMIN + +============================================================== pid_max: diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cdbaf9b51e42..467808680ee4 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -2362,12 +2362,15 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, case EPERM: case EACCES: return scnprintf(msg, size, - "You may not have permission to collect %sstats.\n" - "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" - " -1 - Not paranoid at all\n" - " 0 - Disallow raw tracepoint access for unpriv\n" - " 1 - Disallow cpu events for unpriv\n" - " 2 - Disallow kernel profiling for unpriv", + "You may not have permission to collect %sstats.\n\n" + "Consider tweaking /proc/sys/kernel/perf_event_paranoid,\n" + "which controls use of the performance events system by\n" + "unprivileged users (without CAP_SYS_ADMIN).\n\n" + "The default value is 1:\n\n" + " -1: Allow use of (almost) all events by all users\n" + ">= 0: Disallow raw tracepoint access by users without CAP_IOC_LOCK\n" + ">= 1: Disallow CPU event access by users without CAP_SYS_ADMIN\n" + ">= 2: Disallow kernel profiling by users without CAP_SYS_ADMIN", target->system_wide ? "system-wide " : ""); case ENOENT: return scnprintf(msg, size, "The %s event is not supported.", -- cgit From 78ce08dfbd180fb85312ee76e607a6c5fe34a06c Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 8 Jan 2016 17:16:11 +0900 Subject: perf annotate: Rename 'colors.code' to 'colors.jump_arrows' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USe 'jump_arrows' config name instead of 'code' on 'colors' section. 'colors.code' config is only for jump arrows on assembly code listings i.e. │ ┌──jmp 1333 │ │ xchg %ax,%ax │ │ mov %r15,%r10 │ └─→cmp %r15,%r14 But this config name seems unfit. 'jump_arrows' is more descriptive than 'code'. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1452240971-25418-1-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 2 +- tools/perf/Documentation/perfconfig.example | 2 +- tools/perf/ui/browser.c | 4 ++-- tools/perf/ui/browser.h | 2 +- tools/perf/ui/browsers/annotate.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index b9ca1e304158..1ee488b9aaf7 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -62,7 +62,7 @@ Given a $HOME/.perfconfig like this: medium = green, default normal = lightgray, default selected = white, lightgray - code = blue, default + jump_arrows = blue, default addr = magenta, default root = white, blue diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example index 767ea2436e1c..1d8d5bc4cd2d 100644 --- a/tools/perf/Documentation/perfconfig.example +++ b/tools/perf/Documentation/perfconfig.example @@ -5,7 +5,7 @@ medium = green, lightgray normal = black, lightgray selected = lightgray, magenta - code = blue, lightgray + jump_arrows = blue, lightgray addr = magenta, lightgray [tui] diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index d37202121689..af68a9d488bf 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -531,8 +531,8 @@ static struct ui_browser_colorset { .bg = "yellow", }, { - .colorset = HE_COLORSET_CODE, - .name = "code", + .colorset = HE_COLORSET_JUMP_ARROWS, + .name = "jump_arrows", .fg = "blue", .bg = "default", }, diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 01781de59532..be3b70eb5fca 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -7,7 +7,7 @@ #define HE_COLORSET_MEDIUM 51 #define HE_COLORSET_NORMAL 52 #define HE_COLORSET_SELECTED 53 -#define HE_COLORSET_CODE 54 +#define HE_COLORSET_JUMP_ARROWS 54 #define HE_COLORSET_ADDR 55 #define HE_COLORSET_ROOT 56 diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 718bd46d47fa..4fc208e82c6f 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -284,7 +284,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) to = (u64)btarget->idx; } - ui_browser__set_color(browser, HE_COLORSET_CODE); + ui_browser__set_color(browser, HE_COLORSET_JUMP_ARROWS); __ui_browser__line_arrow(browser, pcnt_width + 2 + ab->addr_width, from, to); } -- cgit From 89debf178708458ac62f5b53dfc97437009d02d3 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 8 Jan 2016 20:39:31 +0900 Subject: perf config: Document variables for 'colors' section in man page Explain 'colors' section and its variables, used for The variables for customizing the colors used in the output for the 'report', 'top' and 'annotate' in the TUI, those are: 'top', 'medium', 'normal', 'selected', 'jump_arrows', 'addr' and 'root'. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1452253193-30502-2-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 1ee488b9aaf7..80517823b7e5 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -98,6 +98,52 @@ Given a $HOME/.perfconfig like this: order = caller sort-key = function +Variables +~~~~~~~~~ + +colors.*:: + The variables for customizing the colors used in the output for the + 'report', 'top' and 'annotate' in the TUI. They should specify the + foreground and background colors, separated by a comma, for example: + + medium = green, lightgray + + If you want to use the color configured for you terminal, just leave it + as 'default', for example: + + medium = default, lightgray + + Available colors: + red, yellow, green, cyan, gray, black, blue, + white, default, magenta, lightgray + + colors.top:: + 'top' means a overhead percentage which is more than 5%. + And values of this variable specify percentage colors. + Basic key values are foreground-color 'red' and + background-color 'default'. + colors.medium:: + 'medium' means a overhead percentage which has more than 0.5%. + Default values are 'green' and 'default'. + colors.normal:: + 'normal' means the rest of overhead percentages + except 'top', 'medium', 'selected'. + Default values are 'lightgray' and 'default'. + colors.selected:: + This selects the colors for the current entry in a list of entries + from sub-commands (top, report, annotate). + Default values are 'black' and 'lightgray'. + colors.jump_arrows:: + Colors for jump arrows on assembly code listings + such as 'jns', 'jmp', 'jane', etc. + Default values are 'blue', 'default'. + colors.addr:: + This selects colors for addresses from 'annotate'. + Default values are 'magenta', 'default'. + colors.root:: + Colors for headers in the output of a sub-commands (top, report). + Default values are 'white', 'blue'. + SEE ALSO -------- linkperf:perf[1] -- cgit From 3fa9f40718a33d27eb2f4bd36c13318a2d58839d Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 8 Jan 2016 20:39:32 +0900 Subject: perf config: Document variables for 'tui' and 'gtk' sections in man page Explain 'tui' and 'gtk' sections and these variables. 'top', 'report' and 'annotate' Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1452253193-30502-3-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 80517823b7e5..ccbdb64696a7 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -144,6 +144,16 @@ colors.*:: Colors for headers in the output of a sub-commands (top, report). Default values are 'white', 'blue'. +tui.*, gtk.*:: + Subcommands that can be configured here are 'top', 'report' and 'annotate'. + These values are booleans, for example: + + [tui] + top = true + + will make the TUI be the default for the 'top' subcommand. Those will be + available if the required libs were detected at tool build time. + SEE ALSO -------- linkperf:perf[1] -- cgit From 2733525b8c1a5f9b6e55338d836b835c9c698913 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 8 Jan 2016 20:39:33 +0900 Subject: perf config: Document 'buildid.dir' variable in man page Explain 'buildid.dir' variable. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1452253193-30502-4-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index ccbdb64696a7..a095f0cabf5e 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -154,6 +154,21 @@ tui.*, gtk.*:: will make the TUI be the default for the 'top' subcommand. Those will be available if the required libs were detected at tool build time. +buildid.*:: + buildid.dir:: + Each executable and shared library in modern distributions comes with a + content based identifier that, if available, will be inserted in a + 'perf.data' file header to, at analysis time find what is needed to do + symbol resolution, code annotation, etc. + + The recording tools also stores a hard link or copy in a per-user + directory, $HOME/.debug/, of binaries, shared libraries, /proc/kallsyms + and /proc/kcore files to be used at analysis time. + + The buildid.dir variable can be used to either change this directory + cache location, or to disable it altogether. If you want to disable it, + set buildid.dir to /dev/null. The default is $HOME/.debug + SEE ALSO -------- linkperf:perf[1] -- cgit From 3b97629d139b19cbcd15b0b3c128a4d6587d2091 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 8 Jan 2016 20:39:34 +0900 Subject: perf config: Document variables for 'annotate' section in man page Explain 'annotate' section and its variables. 'hide_src_code', 'use_offset', 'jump_arrows', 'show_linenr', 'show_nr_jump' and 'show_total_period'. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1452253193-30502-5-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 110 +++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index a095f0cabf5e..cb7ca507ec5e 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -169,6 +169,116 @@ buildid.*:: cache location, or to disable it altogether. If you want to disable it, set buildid.dir to /dev/null. The default is $HOME/.debug +annotate.*:: + These options work only for TUI. + These are in control of addresses, jump function, source code + in lines of assembly code from a specific program. + + annotate.hide_src_code:: + If a program which is analyzed has source code, + this option lets 'annotate' print a list of assembly code with the source code. + For example, let's see a part of a program. There're four lines. + If this option is 'true', they can be printed + without source code from a program as below. + + │ push %rbp + │ mov %rsp,%rbp + │ sub $0x10,%rsp + │ mov (%rdi),%rdx + + But if this option is 'false', source code of the part + can be also printed as below. Default is 'false'. + + │ struct rb_node *rb_next(const struct rb_node *node) + │ { + │ push %rbp + │ mov %rsp,%rbp + │ sub $0x10,%rsp + │ struct rb_node *parent; + │ + │ if (RB_EMPTY_NODE(node)) + │ mov (%rdi),%rdx + │ return n; + + annotate.use_offset:: + Basing on a first address of a loaded function, offset can be used. + Instead of using original addresses of assembly code, + addresses subtracted from a base address can be printed. + Let's illustrate an example. + If a base address is 0XFFFFFFFF81624d50 as below, + + ffffffff81624d50 + + an address on assembly code has a specific absolute address as below + + ffffffff816250b8:│ mov 0x8(%r14),%rdi + + but if use_offset is 'true', an address subtracted from a base address is printed. + Default is true. This option is only applied to TUI. + + 368:│ mov 0x8(%r14),%rdi + + annotate.jump_arrows:: + There can be jump instruction among assembly code. + Depending on a boolean value of jump_arrows, + arrows can be printed or not which represent + where do the instruction jump into as below. + + │ ┌──jmp 1333 + │ │ xchg %ax,%ax + │1330:│ mov %r15,%r10 + │1333:└─→cmp %r15,%r14 + + If jump_arrow is 'false', the arrows isn't printed as below. + Default is 'false'. + + │ ↓ jmp 1333 + │ xchg %ax,%ax + │1330: mov %r15,%r10 + │1333: cmp %r15,%r14 + + annotate.show_linenr:: + When showing source code if this option is 'true', + line numbers are printed as below. + + │1628 if (type & PERF_SAMPLE_IDENTIFIER) { + │ ↓ jne 508 + │1628 data->id = *array; + │1629 array++; + │1630 } + + However if this option is 'false', they aren't printed as below. + Default is 'false'. + + │ if (type & PERF_SAMPLE_IDENTIFIER) { + │ ↓ jne 508 + │ data->id = *array; + │ array++; + │ } + + annotate.show_nr_jumps:: + Let's see a part of assembly code. + + │1382: movb $0x1,-0x270(%rbp) + + If use this, the number of branches jumping to that address can be printed as below. + Default is 'false'. + + │1 1382: movb $0x1,-0x270(%rbp) + + annotate.show_total_period:: + To compare two records on an instruction base, with this option + provided, display total number of samples that belong to a line + in assembly code. If this option is 'true', total periods are printed + instead of percent values as below. + + 302 │ mov %eax,%eax + + But if this option is 'false', percent values for overhead are printed i.e. + Default is 'false'. + + 99.93 │ mov %eax,%eax + SEE ALSO -------- linkperf:perf[1] -- cgit From 485311d97863f2810646e17c8075be2992225f98 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Fri, 8 Jan 2016 20:39:36 +0900 Subject: perf config: Document 'hist.percentage' variable in man page Explain 'hist.percentage' variable. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1452253193-30502-7-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index cb7ca507ec5e..74589c68558a 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -279,6 +279,23 @@ annotate.*:: 99.93 │ mov %eax,%eax +hist.*:: + hist.percentage:: + This option control the way to calculate overhead of filtered entries - + that means the value of this option is effective only if there's a + filter (by comm, dso or symbol name). Suppose a following example: + + Overhead Symbols + ........ ....... + 33.33% foo + 33.33% bar + 33.33% baz + + This is an original overhead and we'll filter out the first 'foo' + entry. The value of 'relative' would increase the overhead of 'bar' + and 'baz' to 50.00% for each, while 'absolute' would show their + current overhead (33.33%). + SEE ALSO -------- linkperf:perf[1] -- cgit From cfd92dadc5e830268036efb25ff41618f29c3306 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 21 Jan 2016 19:13:24 -0300 Subject: perf sort: Provide a way to find out if per-thread bucketing is in place Now the UI browsers will be able to offer thread related operations only if the thread is part of the sort order in use, i.e. if hist_entry stats are all for a single thread. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1452960197-5323-9-git-send-email-namhyung@kernel.org [ Carved out from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 3 +++ tools/perf/util/sort.h | 1 + 2 files changed, 4 insertions(+) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index ec722346e6ff..898e4b0724bf 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -25,6 +25,7 @@ int sort__has_parent = 0; int sort__has_sym = 0; int sort__has_dso = 0; int sort__has_socket = 0; +int sort__has_thread = 0; enum sort_mode sort__mode = SORT_MODE__NORMAL; @@ -2136,6 +2137,8 @@ static int sort_dimension__add(const char *tok, sort__has_dso = 1; } else if (sd->entry == &sort_socket) { sort__has_socket = 1; + } else if (sd->entry == &sort_thread) { + sort__has_thread = 1; } return __sort_dimension__add(sd); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 687bbb124428..09616f03d412 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -35,6 +35,7 @@ extern int sort__need_collapse; extern int sort__has_parent; extern int sort__has_sym; extern int sort__has_socket; +extern int sort__has_thread; extern enum sort_mode sort__mode; extern struct sort_entry sort_comm; extern struct sort_entry sort_dso; -- cgit From 2eafd410e669c744208f8110940e42caa7d79447 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 21 Jan 2016 19:13:24 -0300 Subject: perf hists browser: Only 'Zoom into thread' only when sort order has 'pid' We can't offer a zoom into thread when a bucket (struct hist_entry) may have samples for more than one thread, i.e. when 'pid' is not part of the sort order, fix it. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1452960197-5323-9-git-send-email-namhyung@kernel.org [ Carved out from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 08c09ad755d2..e66b3a30dd9f 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1782,7 +1782,7 @@ static int add_thread_opt(struct hist_browser *browser, struct popup_action *act, char **optstr, struct thread *thread) { - if (thread == NULL) + if (!sort__has_thread || thread == NULL) return 0; if (asprintf(optstr, "Zoom %s %s(%d) thread", @@ -2307,10 +2307,12 @@ skip_annotation: socked_id); /* perf script support */ if (browser->he_selection) { - nr_options += add_script_opt(browser, - &actions[nr_options], - &options[nr_options], - thread, NULL); + if (sort__has_thread && thread) { + nr_options += add_script_opt(browser, + &actions[nr_options], + &options[nr_options], + thread, NULL); + } /* * Note that browser->selection != NULL * when browser->he_selection is not NULL, -- cgit From c221acb0f970d3b80d72c812cda19c121acf5d52 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 21 Jan 2016 19:50:09 -0300 Subject: perf hists browser: Only offer symbol scripting when a symbol is under the cursor When this feature was introduced a check was made if there was a resolved symbol under the cursor, it got lost in commit ea7cd5923309 ("perf hists browser: Split popup menu actions - part 2"), reinstate it. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Fixes: ea7cd5923309 ("perf hists browser: Split popup menu actions - part 2") Link: http://lkml.kernel.org/r/1452960197-5323-9-git-send-email-namhyung@kernel.org [ Carved out from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index e66b3a30dd9f..2801d80c6903 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2322,10 +2322,12 @@ skip_annotation: * * See hist_browser__show_entry. */ - nr_options += add_script_opt(browser, - &actions[nr_options], - &options[nr_options], - NULL, browser->selection->sym); + if (sort__has_sym && browser->selection->sym) { + nr_options += add_script_opt(browser, + &actions[nr_options], + &options[nr_options], + NULL, browser->selection->sym); + } } nr_options += add_script_opt(browser, &actions[nr_options], &options[nr_options], NULL, NULL); -- cgit From b1447a54f5b41eaf1cc469d9bd3834caa2ff9afb Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 22 Jan 2016 11:22:41 -0300 Subject: perf hists browser: Offer 'Zoom into DSO'/'Map details' only when sort order has 'dso' We can't offer a zoom into DSO when a bucket (struct hist_entry) may have samples for more than one DSO, i.e. when 'dso' is not part of the sort order, ditto for 'Map details', fix it. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1452960197-5323-9-git-send-email-namhyung@kernel.org [ Carved out from a larger patch, moved check to add_{dso,map}_opt() ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 4 ++-- tools/perf/util/sort.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 2801d80c6903..e892106410a7 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1825,7 +1825,7 @@ static int add_dso_opt(struct hist_browser *browser, struct popup_action *act, char **optstr, struct map *map) { - if (map == NULL) + if (!sort__has_dso || map == NULL) return 0; if (asprintf(optstr, "Zoom %s %s DSO", @@ -1850,7 +1850,7 @@ static int add_map_opt(struct hist_browser *browser __maybe_unused, struct popup_action *act, char **optstr, struct map *map) { - if (map == NULL) + if (!sort__has_dso || map == NULL) return 0; if (asprintf(optstr, "Browse map details") < 0) diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 09616f03d412..89a1273fd2da 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -32,6 +32,7 @@ extern const char default_sort_order[]; extern regex_t ignore_callees_regex; extern int have_ignore_callees; extern int sort__need_collapse; +extern int sort__has_dso; extern int sort__has_parent; extern int sort__has_sym; extern int sort__has_socket; -- cgit From d9695d9f93649ecc00877ec2c847739c54a4cbb3 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 22 Jan 2016 12:20:18 -0300 Subject: perf hists browser: Be a bit more strict about presenting CPU socket zoom For consistency with the other sort order checks. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1452960197-5323-9-git-send-email-namhyung@kernel.org [ Carved out from a larger patch, moved check to add_socket_opt() ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index e892106410a7..b919582add0f 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1971,7 +1971,7 @@ static int add_socket_opt(struct hist_browser *browser, struct popup_action *act, char **optstr, int socket_id) { - if (socket_id < 0) + if (!sort__has_socket || socket_id < 0) return 0; if (asprintf(optstr, "Zoom %s Processor Socket %d", -- cgit From 4056132e1072f02bbad77f2071770271cc5b58fc Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 22 Jan 2016 12:26:06 -0300 Subject: perf hists browser: Offer non-symbol specific menu options for --sort without 'sym' Now that we check more strictly what each of the menu entries need, we can stop bailing out when 'sym' is not in the --sort order, instead we let each option be added if what it needs is present. This way, for instance, we can run scripts on all samples, see DSO map details when 'dso' is in the --sort provided, etc. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1452960197-5323-9-git-send-email-namhyung@kernel.org [ Carved out from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index b919582add0f..d07e6be42ab1 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2263,10 +2263,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, continue; } - if (!sort__has_sym) - goto add_exit_option; - - if (browser->selection == NULL) + if (!sort__has_sym || browser->selection == NULL) goto skip_annotation; if (sort__mode == SORT_MODE__BRANCH) { @@ -2333,7 +2330,6 @@ skip_annotation: &options[nr_options], NULL, NULL); nr_options += add_switch_opt(browser, &actions[nr_options], &options[nr_options]); -add_exit_option: nr_options += add_exit_opt(browser, &actions[nr_options], &options[nr_options]); -- cgit From 8acd3da03c3f6e4e31472c5c73402b95a5d0f6cb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 25 Jan 2016 18:01:57 -0300 Subject: perf machine: Introduce machine__find_kernel_symbol_by_name() To be used in the 'vmlinux matches kallsyms' 'perf test' entry. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-m56g1853lz2c6nhnqxibq4jd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 2c2b443df5ba..1a3e45baf97f 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h @@ -179,6 +179,16 @@ struct symbol *machine__find_kernel_symbol(struct machine *machine, mapp, filter); } +static inline +struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, + enum map_type type, const char *name, + struct map **mapp, + symbol_filter_t filter) +{ + return map_groups__find_symbol_by_name(&machine->kmaps, type, name, + mapp, filter); +} + static inline struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr, struct map **mapp, -- cgit From ab414dcda8fa307388c40a540b35e3c98a9da5ae Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 25 Jan 2016 18:04:47 -0300 Subject: perf test: Fixup aliases checking in the 'vmlinux matches kallsyms' test There are cases where looking at just the next and prev entries is not enough, like with: $ readelf -sW /usr/lib/debug/lib/modules/4.3.3-301.fc23.x86_64/vmlinux | grep ffffffff81065ec0 4979: ffffffff81065ec0 53 FUNC LOCAL DEFAULT 1 try_to_free_pud_page 4980: ffffffff81065ec0 53 FUNC LOCAL DEFAULT 1 try_to_free_pte_page 4981: ffffffff81065ec0 53 FUNC LOCAL DEFAULT 1 try_to_free_pmd_page So just search by name to see if the symbol is in kallsyms. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-jj1vlljg7ol4i713l60rt5ai@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/vmlinux-kallsyms.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c index f0bfc9e8fd9f..630b0b409b97 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -110,7 +110,6 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) */ for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { struct symbol *pair, *first_pair; - bool backwards = true; sym = rb_entry(nd, struct symbol, rb_node); @@ -151,27 +150,14 @@ next_pair: continue; } else { - struct rb_node *nnd; -detour: - nnd = backwards ? rb_prev(&pair->rb_node) : - rb_next(&pair->rb_node); - if (nnd) { - struct symbol *next = rb_entry(nnd, struct symbol, rb_node); - - if (UM(next->start) == mem_start) { - pair = next; + pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL, NULL); + if (pair) { + if (UM(pair->start) == mem_start) goto next_pair; - } - } - if (backwards) { - backwards = false; - pair = first_pair; - goto detour; + pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", + mem_start, sym->name, pair->name); } - - pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", - mem_start, sym->name, pair->name); } } else pr_debug("%#" PRIx64 ": %s not on kallsyms\n", -- cgit From 7b6982ce4b38ecc3f63be46beb7bd079aa290fd7 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:55:48 +0000 Subject: perf test: Add libbpf relocation checker There's a bug in LLVM that it can generate unneeded relocation information. See [1] and [2]. Libbpf should check the target section of a relocation symbol. This patch adds a testcase which references a global variable (BPF doesn't support global variables). Before fixing libbpf, the new test case can be loaded into kernel, the global variable acts like the first map. It is incorrect. Result: # ~/perf test BPF 37: Test BPF filter : 37.1: Test basic BPF filtering : Ok 37.2: Test BPF prologue generation : Ok 37.3: Test BPF relocation checker : FAILED! # ~/perf test -v BPF ... libbpf: loading object '[bpf_relocation_test]' from buffer libbpf: section .strtab, size 126, link 0, flags 0, type=3 libbpf: section .text, size 0, link 0, flags 6, type=1 libbpf: section .data, size 0, link 0, flags 3, type=1 libbpf: section .bss, size 0, link 0, flags 3, type=8 libbpf: section func=sys_write, size 104, link 0, flags 6, type=1 libbpf: found program func=sys_write libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9 libbpf: section maps, size 16, link 0, flags 3, type=1 libbpf: maps in [bpf_relocation_test]: 16 bytes libbpf: section license, size 4, link 0, flags 3, type=1 libbpf: license of [bpf_relocation_test] is GPL libbpf: section version, size 4, link 0, flags 3, type=1 libbpf: kernel version of [bpf_relocation_test] is 40400 libbpf: section .symtab, size 144, link 1, flags 0, type=2 libbpf: map 0 is "my_table" libbpf: collecting relocating info for: 'func=sys_write' libbpf: relocation: insn_idx=7 Success unexpectedly: libbpf error when dealing with relocation test child finished with -1 ---- end ---- Test BPF filter subtest 2: FAILED! [1] https://llvm.org/bugs/show_bug.cgi?id=26243 [2] https://patchwork.ozlabs.org/patch/571385/ Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Cc: "David S. Miller" Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 2 +- tools/perf/tests/.gitignore | 1 + tools/perf/tests/Build | 9 ++++- tools/perf/tests/bpf-script-test-relocation.c | 50 +++++++++++++++++++++++++++ tools/perf/tests/bpf.c | 26 +++++++++++--- tools/perf/tests/llvm.c | 17 ++++++--- tools/perf/tests/llvm.h | 5 ++- 7 files changed, 98 insertions(+), 12 deletions(-) create mode 100644 tools/perf/tests/bpf-script-test-relocation.c diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 5d34815c7ccb..97ce8695199e 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -618,7 +618,7 @@ clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \ - $(OUTPUT)tests/llvm-src-{base,kbuild,prologue}.c + $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean $(python-clean) diff --git a/tools/perf/tests/.gitignore b/tools/perf/tests/.gitignore index bf016c439fbd..8cc30e731c73 100644 --- a/tools/perf/tests/.gitignore +++ b/tools/perf/tests/.gitignore @@ -1,3 +1,4 @@ llvm-src-base.c llvm-src-kbuild.c llvm-src-prologue.c +llvm-src-relocation.c diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build index 614899b88b37..1ba628ed049a 100644 --- a/tools/perf/tests/Build +++ b/tools/perf/tests/Build @@ -31,7 +31,7 @@ perf-y += sample-parsing.o perf-y += parse-no-sample-id-all.o perf-y += kmod-path.o perf-y += thread-map.o -perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o +perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o llvm-src-relocation.o perf-y += bpf.o perf-y += topology.o perf-y += cpumap.o @@ -59,6 +59,13 @@ $(OUTPUT)tests/llvm-src-prologue.c: tests/bpf-script-test-prologue.c tests/Build $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ $(Q)echo ';' >> $@ +$(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/Build + $(call rule_mkdir) + $(Q)echo '#include ' > $@ + $(Q)echo 'const char test_llvm__bpf_test_relocation[] =' >> $@ + $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ + $(Q)echo ';' >> $@ + ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o endif diff --git a/tools/perf/tests/bpf-script-test-relocation.c b/tools/perf/tests/bpf-script-test-relocation.c new file mode 100644 index 000000000000..93af77421816 --- /dev/null +++ b/tools/perf/tests/bpf-script-test-relocation.c @@ -0,0 +1,50 @@ +/* + * bpf-script-test-relocation.c + * Test BPF loader checking relocation + */ +#ifndef LINUX_VERSION_CODE +# error Need LINUX_VERSION_CODE +# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig' +#endif +#define BPF_ANY 0 +#define BPF_MAP_TYPE_ARRAY 2 +#define BPF_FUNC_map_lookup_elem 1 +#define BPF_FUNC_map_update_elem 2 + +static void *(*bpf_map_lookup_elem)(void *map, void *key) = + (void *) BPF_FUNC_map_lookup_elem; +static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) = + (void *) BPF_FUNC_map_update_elem; + +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)) +struct bpf_map_def SEC("maps") my_table = { + .type = BPF_MAP_TYPE_ARRAY, + .key_size = sizeof(int), + .value_size = sizeof(int), + .max_entries = 1, +}; + +int this_is_a_global_val; + +SEC("func=sys_write") +int bpf_func__sys_write(void *ctx) +{ + int key = 0; + int value = 0; + + /* + * Incorrect relocation. Should not allow this program be + * loaded into kernel. + */ + bpf_map_update_elem(&this_is_a_global_val, &key, &value, 0); + return 0; +} +char _license[] SEC("license") = "GPL"; +int _version SEC("version") = LINUX_VERSION_CODE; diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 33689a0cf821..952ca99aba6b 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -71,6 +71,15 @@ static struct { (NR_ITERS + 1) / 4, }, #endif + { + LLVM_TESTCASE_BPF_RELOCATION, + "Test BPF relocation checker", + "[bpf_relocation_test]", + "fix 'perf test LLVM' first", + "libbpf error when dealing with relocation", + NULL, + 0, + }, }; static int do_test(struct bpf_object *obj, int (*func)(void), @@ -190,7 +199,7 @@ static int __test__bpf(int idx) ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, bpf_testcase_table[idx].prog_id, - true); + true, NULL); if (ret != TEST_OK || !obj_buf || !obj_buf_sz) { pr_debug("Unable to get BPF object, %s\n", bpf_testcase_table[idx].msg_compile_fail); @@ -202,14 +211,21 @@ static int __test__bpf(int idx) obj = prepare_bpf(obj_buf, obj_buf_sz, bpf_testcase_table[idx].name); - if (!obj) { + if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) { + if (!obj) + pr_debug("Fail to load BPF object: %s\n", + bpf_testcase_table[idx].msg_load_fail); + else + pr_debug("Success unexpectedly: %s\n", + bpf_testcase_table[idx].msg_load_fail); ret = TEST_FAIL; goto out; } - ret = do_test(obj, - bpf_testcase_table[idx].target_func, - bpf_testcase_table[idx].expect_result); + if (obj) + ret = do_test(obj, + bpf_testcase_table[idx].target_func, + bpf_testcase_table[idx].expect_result); out: bpf__clear(); return ret; diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c index 06f45c1d4256..70edcdfa5672 100644 --- a/tools/perf/tests/llvm.c +++ b/tools/perf/tests/llvm.c @@ -35,6 +35,7 @@ static int test__bpf_parsing(void *obj_buf __maybe_unused, static struct { const char *source; const char *desc; + bool should_load_fail; } bpf_source_table[__LLVM_TESTCASE_MAX] = { [LLVM_TESTCASE_BASE] = { .source = test_llvm__bpf_base_prog, @@ -48,14 +49,19 @@ static struct { .source = test_llvm__bpf_test_prologue_prog, .desc = "Compile source for BPF prologue generation test", }, + [LLVM_TESTCASE_BPF_RELOCATION] = { + .source = test_llvm__bpf_test_relocation, + .desc = "Compile source for BPF relocation test", + .should_load_fail = true, + }, }; - int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz, enum test_llvm__testcase idx, - bool force) + bool force, + bool *should_load_fail) { const char *source; const char *desc; @@ -68,6 +74,8 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf, source = bpf_source_table[idx].source; desc = bpf_source_table[idx].desc; + if (should_load_fail) + *should_load_fail = bpf_source_table[idx].should_load_fail; perf_config(perf_config_cb, NULL); @@ -136,14 +144,15 @@ int test__llvm(int subtest) int ret; void *obj_buf = NULL; size_t obj_buf_sz = 0; + bool should_load_fail = false; if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX)) return TEST_FAIL; ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz, - subtest, false); + subtest, false, &should_load_fail); - if (ret == TEST_OK) { + if (ret == TEST_OK && !should_load_fail) { ret = test__bpf_parsing(obj_buf, obj_buf_sz); if (ret != TEST_OK) { pr_debug("Failed to parse test case '%s'\n", diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h index 5150b4d6ef50..0eaa604be99d 100644 --- a/tools/perf/tests/llvm.h +++ b/tools/perf/tests/llvm.h @@ -7,14 +7,17 @@ extern const char test_llvm__bpf_base_prog[]; extern const char test_llvm__bpf_test_kbuild_prog[]; extern const char test_llvm__bpf_test_prologue_prog[]; +extern const char test_llvm__bpf_test_relocation[]; enum test_llvm__testcase { LLVM_TESTCASE_BASE, LLVM_TESTCASE_KBUILD, LLVM_TESTCASE_BPF_PROLOGUE, + LLVM_TESTCASE_BPF_RELOCATION, __LLVM_TESTCASE_MAX, }; int test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz, - enum test_llvm__testcase index, bool force); + enum test_llvm__testcase index, bool force, + bool *should_load_fail); #endif -- cgit From 666810e86a3b7531cce892fbeda3b2f2322e1d72 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:55:49 +0000 Subject: perf bpf: Check relocation target section Libbpf should check the target section before doing relocation to ensure the relocation is correct. If not, a bug in LLVM causes an error. See [1]. Also, if an incorrect BPF script uses both global variable and map, global variable whould be treated as map and be relocated without error. This patch saves the id of the map section into obj->efile and compare target section of a relocation symbol against it during relocation. Previous patch introduces a test case about this problem. After this patch: # ~/perf test BPF 37: Test BPF filter : 37.1: Test basic BPF filtering : Ok 37.2: Test BPF prologue generation : Ok 37.3: Test BPF relocation checker : Ok # perf test -v BPF ... 37.3: Test BPF relocation checker : ... libbpf: loading object '[bpf_relocation_test]' from buffer libbpf: section .strtab, size 126, link 0, flags 0, type=3 libbpf: section .text, size 0, link 0, flags 6, type=1 libbpf: section .data, size 0, link 0, flags 3, type=1 libbpf: section .bss, size 0, link 0, flags 3, type=8 libbpf: section func=sys_write, size 104, link 0, flags 6, type=1 libbpf: found program func=sys_write libbpf: section .relfunc=sys_write, size 16, link 10, flags 0, type=9 libbpf: section maps, size 16, link 0, flags 3, type=1 libbpf: maps in [bpf_relocation_test]: 16 bytes libbpf: section license, size 4, link 0, flags 3, type=1 libbpf: license of [bpf_relocation_test] is GPL libbpf: section version, size 4, link 0, flags 3, type=1 libbpf: kernel version of [bpf_relocation_test] is 40400 libbpf: section .symtab, size 144, link 1, flags 0, type=2 libbpf: map 0 is "my_table" libbpf: collecting relocating info for: 'func=sys_write' libbpf: Program 'func=sys_write' contains non-map related relo data pointing to section 65522 bpf: failed to load buffer Compile BPF program failed. test child finished with 0 ---- end ---- Test BPF filter subtest 2: Ok [1] https://llvm.org/bugs/show_bug.cgi?id=26243 Signed-off-by: Wang Nan Acked-by: Alexei Starovoitov Tested-by: Arnaldo Carvalho de Melo Cc: "David S. Miller" Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/bpf/libbpf.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 8334a5a9d5d7..7e543c3102d4 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -201,6 +201,7 @@ struct bpf_object { Elf_Data *data; } *reloc; int nr_reloc; + int maps_shndx; } efile; /* * All loaded bpf_object is linked in a list, which is @@ -350,6 +351,7 @@ static struct bpf_object *bpf_object__new(const char *path, */ obj->efile.obj_buf = obj_buf; obj->efile.obj_buf_sz = obj_buf_sz; + obj->efile.maps_shndx = -1; obj->loaded = false; @@ -529,12 +531,12 @@ bpf_object__init_maps(struct bpf_object *obj, void *data, } static int -bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx) +bpf_object__init_maps_name(struct bpf_object *obj) { int i; Elf_Data *symbols = obj->efile.symbols; - if (!symbols || maps_shndx < 0) + if (!symbols || obj->efile.maps_shndx < 0) return -EINVAL; for (i = 0; i < symbols->d_size / sizeof(GElf_Sym); i++) { @@ -544,7 +546,7 @@ bpf_object__init_maps_name(struct bpf_object *obj, int maps_shndx) if (!gelf_getsym(symbols, i, &sym)) continue; - if (sym.st_shndx != maps_shndx) + if (sym.st_shndx != obj->efile.maps_shndx) continue; map_name = elf_strptr(obj->efile.elf, @@ -572,7 +574,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) Elf *elf = obj->efile.elf; GElf_Ehdr *ep = &obj->efile.ehdr; Elf_Scn *scn = NULL; - int idx = 0, err = 0, maps_shndx = -1; + int idx = 0, err = 0; /* Elf is corrupted/truncated, avoid calling elf_strptr. */ if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { @@ -625,7 +627,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) else if (strcmp(name, "maps") == 0) { err = bpf_object__init_maps(obj, data->d_buf, data->d_size); - maps_shndx = idx; + obj->efile.maps_shndx = idx; } else if (sh.sh_type == SHT_SYMTAB) { if (obj->efile.symbols) { pr_warning("bpf: multiple SYMTAB in %s\n", @@ -674,8 +676,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj) pr_warning("Corrupted ELF file: index of strtab invalid\n"); return LIBBPF_ERRNO__FORMAT; } - if (maps_shndx >= 0) - err = bpf_object__init_maps_name(obj, maps_shndx); + if (obj->efile.maps_shndx >= 0) + err = bpf_object__init_maps_name(obj); out: return err; } @@ -697,7 +699,8 @@ bpf_object__find_prog_by_idx(struct bpf_object *obj, int idx) static int bpf_program__collect_reloc(struct bpf_program *prog, size_t nr_maps, GElf_Shdr *shdr, - Elf_Data *data, Elf_Data *symbols) + Elf_Data *data, Elf_Data *symbols, + int maps_shndx) { int i, nrels; @@ -724,9 +727,6 @@ bpf_program__collect_reloc(struct bpf_program *prog, return -LIBBPF_ERRNO__FORMAT; } - insn_idx = rel.r_offset / sizeof(struct bpf_insn); - pr_debug("relocation: insn_idx=%u\n", insn_idx); - if (!gelf_getsym(symbols, GELF_R_SYM(rel.r_info), &sym)) { @@ -735,6 +735,15 @@ bpf_program__collect_reloc(struct bpf_program *prog, return -LIBBPF_ERRNO__FORMAT; } + if (sym.st_shndx != maps_shndx) { + pr_warning("Program '%s' contains non-map related relo data pointing to section %u\n", + prog->section_name, sym.st_shndx); + return -LIBBPF_ERRNO__RELOC; + } + + insn_idx = rel.r_offset / sizeof(struct bpf_insn); + pr_debug("relocation: insn_idx=%u\n", insn_idx); + if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n", insn_idx, insns[insn_idx].code); @@ -863,7 +872,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) err = bpf_program__collect_reloc(prog, nr_maps, shdr, data, - obj->efile.symbols); + obj->efile.symbols, + obj->efile.maps_shndx); if (err) return err; } -- cgit From 9fd4186ac19a4c8182dffc9b15dd288b50f09f76 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:55:50 +0000 Subject: tools build: Allow subprojects select all feature checkers Put feature checkers not in original FEATURE_TESTS to a new list and allow subproject select all feature checkers by setting FEATURE_TESTS to 'all'. Signed-off-by: Wang Nan Cc: "David S. Miller" Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Link: http://lkml.kernel.org/r/1453715801-7732-4-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 02db3cdff20f..674c47d5f9d1 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -27,7 +27,7 @@ endef # the rule that uses them - an example for that is the 'bionic' # feature check. ] # -FEATURE_TESTS ?= \ +FEATURE_TESTS_BASIC := \ backtrace \ dwarf \ fortify-source \ @@ -56,6 +56,25 @@ FEATURE_TESTS ?= \ get_cpuid \ bpf +# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list +# of all feature tests +FEATURE_TESTS_EXTRA := \ + bionic \ + compile-32 \ + compile-x32 \ + cplus-demangle \ + hello \ + libbabeltrace \ + liberty \ + liberty-z \ + libunwind-debug-frame + +FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC) + +ifeq ($(FEATURE_TESTS),all) + FEATURE_TESTS := $(FEATURE_TESTS_BASIC) $(FEATURE_TESTS_EXTRA) +endif + FEATURE_DISPLAY ?= \ dwarf \ glibc \ -- cgit From c053a1506faee399cbc2105f2131bb5a5d99eedd Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:55:51 +0000 Subject: perf build: Select all feature checkers for feature-dump Set FEATURE_TESTS to 'all' so all possible feature checkers are executed. Without this setting the output feature dump file miss some feature, for example, liberity. Select all checker so we won't get an incomplete feature dump file. Signed-off-by: Wang Nan Cc: "David S. Miller" Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Link: http://lkml.kernel.org/r/1453715801-7732-5-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 97ce8695199e..0ef3d97d7954 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -165,7 +165,16 @@ ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) endif endif +# Set FEATURE_TESTS to 'all' so all possible feature checkers are executed. +# Without this setting the output feature dump file misses some features, for +# example, liberty. Select all checkers so we won't get an incomplete feature +# dump file. ifeq ($(config),1) +ifdef MAKECMDGOALS +ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump) +FEATURE_TESTS := all +endif +endif include config/Makefile endif -- cgit From b1baae89197e21cd115e9493d5a17f18fca81e6a Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 26 Jan 2016 15:37:30 -0300 Subject: perf hists browser: Skip scripting when perf.data file not available The script and data-switch context menu are only meaningful when it deals with a data file. So add a check so that it cannot be shown when perf-top is run. Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa , Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1453555902-18401-4-git-send-email-namhyung@kernel.org [ Use goto skip_scripting instead of two is_report_browser() tests ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index d07e6be42ab1..1da30f8aa7a5 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2303,6 +2303,9 @@ skip_annotation: &options[nr_options], socked_id); /* perf script support */ + if (!is_report_browser(hbt)) + goto skip_scripting; + if (browser->he_selection) { if (sort__has_thread && thread) { nr_options += add_script_opt(browser, @@ -2330,6 +2333,7 @@ skip_annotation: &options[nr_options], NULL, NULL); nr_options += add_switch_opt(browser, &actions[nr_options], &options[nr_options]); +skip_scripting: nr_options += add_exit_opt(browser, &actions[nr_options], &options[nr_options]); -- cgit From 5ac76283b32b116c58e362e99542182ddcfc8262 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 26 Jan 2016 15:51:46 -0300 Subject: perf cpumap: Auto initialize cpu__max_{node,cpu} Since it was always checking if the initialization was done, use that branch to do the initialization if not done already. With this we reduce the number of exported globals from these files. Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Kan Liang Cc: Mathieu Poirier Cc: Namhyung Kim Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/20160125212955.GG22501@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/cpumap.c | 30 ++++++++++++++++++++++++++++++ tools/perf/util/cpumap.h | 32 +++----------------------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index fa935093a599..9bcf2bed3a6d 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c @@ -8,6 +8,10 @@ #include #include "asm/bug.h" +static int max_cpu_num; +static int max_node_num; +static int *cpunode_map; + static struct cpu_map *cpu_map__default_new(void) { struct cpu_map *cpus; @@ -486,6 +490,32 @@ out: pr_err("Failed to read max nodes, using default of %d\n", max_node_num); } +int cpu__max_node(void) +{ + if (unlikely(!max_node_num)) + set_max_node_num(); + + return max_node_num; +} + +int cpu__max_cpu(void) +{ + if (unlikely(!max_cpu_num)) + set_max_cpu_num(); + + return max_cpu_num; +} + +int cpu__get_node(int cpu) +{ + if (unlikely(cpunode_map == NULL)) { + pr_debug("cpu_map not initialized\n"); + return -1; + } + + return cpunode_map[cpu]; +} + static int init_cpunode_map(void) { int i; diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 71c41b9efabb..81a2562aaa2b 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h @@ -57,37 +57,11 @@ static inline bool cpu_map__empty(const struct cpu_map *map) return map ? map->map[0] == -1 : true; } -int max_cpu_num; -int max_node_num; -int *cpunode_map; - int cpu__setup_cpunode_map(void); -static inline int cpu__max_node(void) -{ - if (unlikely(!max_node_num)) - pr_debug("cpu_map not initialized\n"); - - return max_node_num; -} - -static inline int cpu__max_cpu(void) -{ - if (unlikely(!max_cpu_num)) - pr_debug("cpu_map not initialized\n"); - - return max_cpu_num; -} - -static inline int cpu__get_node(int cpu) -{ - if (unlikely(cpunode_map == NULL)) { - pr_debug("cpu_map not initialized\n"); - return -1; - } - - return cpunode_map[cpu]; -} +int cpu__max_node(void); +int cpu__max_cpu(void); +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), -- cgit From df8a0dde73069b69c7d6f2a1758857c482d59e18 Mon Sep 17 00:00:00 2001 From: dcg Date: Thu, 21 Jan 2016 11:23:43 +0100 Subject: Remove "arch" usage in Documentation/features/list-arch.sh Commit 669f6f96c680a741257ada44a28b580df2e1fc25 introduced the script list-arch.sh, which uses the command "arch": ARCH=${1:-$(arch | sed 's/x86_64/x86/' | sed 's/i386/x86/')} It turns out that the "arch" command does not exist in my system (arch distro). Google found man pages which say "arch is deprecated command since release util-linux 2.13. Use uname -m" (util-linux 2.13 was released in 2007). I also found a debian bug reporting the lack of arch and being told to use uname -m https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=446023 But then, why it works in some distros? Apparently coreutils gained an optional arch command that needs to be explicitly enabled during compilation. Some distros enable it, others don't. Sigh. Signed-off-by: Diego Calleja Acked-by: Ingo Molnar Signed-off-by: Jonathan Corbet --- Documentation/features/list-arch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/features/list-arch.sh b/Documentation/features/list-arch.sh index 6065124a072f..c16b5b595688 100755 --- a/Documentation/features/list-arch.sh +++ b/Documentation/features/list-arch.sh @@ -5,7 +5,7 @@ # (If no arguments are given then it will print the host architecture's status.) # -ARCH=${1:-$(arch | sed 's/x86_64/x86/' | sed 's/i386/x86/')} +ARCH=${1:-$(uname -m | sed 's/x86_64/x86/' | sed 's/i386/x86/')} cd $(dirname $0) echo "#" -- cgit From f19768ce0e84ac8a1ab03f87784bdf94bf94e140 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 19 Oct 2015 16:00:35 +0100 Subject: ARM: orion: implement ARM delay timer Implement an ARM delay timer to be used for udelay() on orion legacy platforms. This allows us to skip the delay loop calibration at boot. It also means that udelay() will be unaffected by CPU frequency changes when cpufreq is enabled on these platforms. Tested-by: Russell King Acked-by: Andrew Lunn Signed-off-by: Russell King --- arch/arm/plat-orion/time.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 8085a8aac812..ffb93db68e9c 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c @@ -18,6 +18,7 @@ #include #include #include +#include /* * MBus bridge block registers. @@ -188,6 +189,15 @@ orion_time_set_base(void __iomem *_timer_base) timer_base = _timer_base; } +static unsigned long orion_delay_timer_read(void) +{ + return ~readl(timer_base + TIMER0_VAL_OFF); +} + +static struct delay_timer orion_delay_timer = { + .read_current_timer = orion_delay_timer_read, +}; + void __init orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask, unsigned int irq, unsigned int tclk) @@ -202,6 +212,9 @@ orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask, ticks_per_jiffy = (tclk + HZ/2) / HZ; + orion_delay_timer.freq = tclk; + register_current_timer_delay(&orion_delay_timer); + /* * Set scale and timer for sched_clock. */ -- cgit From d78e13a8a8b795b605eb58a48365591f2e7c690b Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Thu, 7 Jan 2016 16:27:33 +0100 Subject: ARM: 8497/1: initialize cpu_scale to its default Instead of looping through all cpus calling set_capacity_scale, we can initialise cpu_scale per-cpu variables to SCHED_CAPACITY_SCALE with their definition. Acked-by: Vincent Guittot Signed-off-by: Juri Lelli Signed-off-by: Russell King --- arch/arm/kernel/topology.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 08b7847bf912..ec279d161b32 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -40,7 +40,7 @@ * to run the rebalance_domains for all idle cores and the cpu_capacity can be * updated during this sequence. */ -static DEFINE_PER_CPU(unsigned long, cpu_scale); +static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu) { @@ -306,8 +306,6 @@ void __init init_cpu_topology(void) cpu_topo->socket_id = -1; cpumask_clear(&cpu_topo->core_sibling); cpumask_clear(&cpu_topo->thread_sibling); - - set_capacity_scale(cpu, SCHED_CAPACITY_SCALE); } smp_wmb(); -- cgit From 9023cc8268c6ba358417d31112ed96e1feb73e56 Mon Sep 17 00:00:00 2001 From: Andiii Date: Thu, 14 Jan 2016 07:17:00 +0100 Subject: ARM: 8499/1: irq: l2c: do not print error in case of missing l2c from arm: irq: l2c: do not print error in case of missing l2c from dtb In some architectures the L2 cache controller is integrated in the processor's block itself and it doesn't use any external cache controller. This means that an entry in the board's dtb related to the l2c is not necessary. Distinguish between error codes and do not print anything in case l2x0_of_init() doesn't find any L2C DTB entry and returns -ENODEV. This patch mutes the following error message: L2C: failed to init: -19 on boards like odroid-xu4, cortex A7/A15, which don't have external cache controller. Signed-off-by: Andi Shyti Reported-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Signed-off-by: Russell King --- arch/arm/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 1d45320ee125..ece04a457486 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -95,7 +95,7 @@ void __init init_IRQ(void) outer_cache.write_sec = machine_desc->l2c_write_sec; ret = l2x0_of_init(machine_desc->l2c_aux_val, machine_desc->l2c_aux_mask); - if (ret) + if (ret && ret != -ENODEV) pr_err("L2C: failed to init: %d\n", ret); } -- cgit From 8ba5905c163cbfcc4c21ecef7574626649977439 Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Mon, 18 Jan 2016 16:38:31 +0100 Subject: pinctrl: st: activate strict mux mode This activates strict mode muxing for the ST pin controllers, as these do not allow GPIO and functions to use the same pin simultaneously. Signed-off-by: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-st.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index fac844a85cb4..cab66c64149f 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -985,6 +985,7 @@ static struct pinmux_ops st_pmxops = { .get_function_groups = st_pmx_get_groups, .set_mux = st_pmx_set_mux, .gpio_set_direction = st_pmx_set_gpio_direction, + .strict = true, }; /* Pinconf */ -- cgit From 14365449b6ce34cf6a3040ff8ebbb39d89d67159 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Tue, 26 Jan 2016 18:21:21 +0600 Subject: x86/asm: Remove unused L3_PAGE_OFFSET L3_PAGE_OFFSET was introduced in commit a6523748bd (paravirt/x86, 64-bit: move __PAGE_OFFSET to leave a space for hypervisor), but has no users. Signed-off-by: Alexander Kuleshov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Denys Vlasenko Cc: Andrey Ryabinin Link: http://lkml.kernel.org/r/1453810881-30622-1-git-send-email-kuleshovmail@gmail.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/head_64.S | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index ffdc0e860390..2e974680f5ad 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -38,7 +38,6 @@ #define pud_index(x) (((x) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET) -L3_PAGE_OFFSET = pud_index(__PAGE_OFFSET) L4_START_KERNEL = pgd_index(__START_KERNEL_map) L3_START_KERNEL = pud_index(__START_KERNEL_map) -- cgit From ee03672d961bdac2ac1e593e9c29b0d3b7320409 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 26 Jan 2016 15:33:21 +0200 Subject: spi: pxa2xx: Print actual DMA/PIO transfer mode in debug messages Transfer debug messages don't actually show is the transfer really using DMA. Driver may fall back to PIO in case transfer size is not within the certain limits or fails to map DMA buffers but debug messages don't reveal that. Move these debug messages further in pump_transfers() where the actual transfer mode is known and use drv_data->dma_mapped flag instead of chip->enable_dma for printing the mode. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index ab9914ad8365..227e8bad19e6 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1001,19 +1001,6 @@ static void pump_transfers(unsigned long data) "pump_transfers: DMA burst size reduced to match bits_per_word\n"); } - /* NOTE: PXA25x_SSP _could_ use external clocking ... */ - cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits); - if (!pxa25x_ssp_comp(drv_data)) - dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", - drv_data->master->max_speed_hz - / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)), - chip->enable_dma ? "DMA" : "PIO"); - else - dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", - drv_data->master->max_speed_hz / 2 - / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)), - chip->enable_dma ? "DMA" : "PIO"); - message->state = RUNNING_STATE; drv_data->dma_mapped = 0; @@ -1040,6 +1027,19 @@ static void pump_transfers(unsigned long data) write_SSSR_CS(drv_data, drv_data->clear_sr); } + /* NOTE: PXA25x_SSP _could_ use external clocking ... */ + cr0 = pxa2xx_configure_sscr0(drv_data, clk_div, bits); + if (!pxa25x_ssp_comp(drv_data)) + dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", + drv_data->master->max_speed_hz + / (1 + ((cr0 & SSCR0_SCR(0xfff)) >> 8)), + drv_data->dma_mapped ? "DMA" : "PIO"); + else + dev_dbg(&message->spi->dev, "%u Hz actual, %s\n", + drv_data->master->max_speed_hz / 2 + / (1 + ((cr0 & SSCR0_SCR(0x0ff)) >> 8)), + drv_data->dma_mapped ? "DMA" : "PIO"); + if (is_lpss_ssp(drv_data)) { if ((pxa2xx_spi_read(drv_data, SSIRF) & 0xff) != chip->lpss_rx_threshold) -- cgit From dd42ac8f02aea32661756554aace2095f7181d34 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Fri, 16 Oct 2015 15:20:53 +0600 Subject: clockevents: Rename last parameter of clocks_calc_mult_shift() to maxsec Last parameter of the clocks_calc_mult_shift() was renamed from minsec to maxsec in the 5fdade95 (time: Rename misnamed minsec argument of clocks_calc_mult_shift()). Signed-off-by: Alexander Kuleshov Link: http://lkml.kernel.org/r/1444987253-11018-1-git-send-email-kuleshovmail@gmail.com Signed-off-by: Thomas Gleixner --- include/linux/clockchips.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index bdcf358dfce2..0d442e34c349 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -190,9 +190,9 @@ extern void clockevents_config_and_register(struct clock_event_device *dev, extern int clockevents_update_freq(struct clock_event_device *ce, u32 freq); static inline void -clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec) +clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 maxsec) { - return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, minsec); + return clocks_calc_mult_shift(&ce->mult, &ce->shift, NSEC_PER_SEC, freq, maxsec); } extern void clockevents_suspend(void); -- cgit From 9c808765e88efb6fa6af7e2206ef89512f1840a7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 15 Jan 2016 17:41:08 +0000 Subject: hrtimer: Add support for CLOCK_MONOTONIC_RAW The KVM/ARM timer implementation arms a hrtimer when a vcpu is blocked (usually because it is waiting for an interrupt) while its timer is going to kick in the future. It is essential that this timer doesn't get adjusted, or the guest will end up being woken-up at the wrong time (NTP running on the host seems to confuse the hell out of some guests). In order to allow this, let's add CLOCK_MONOTONIC_RAW support to hrtimer (it is so far only supported for posix timers). It also has the (limited) benefit of fixing de0421d53bfb ("mac80211_hwsim: shuffle code to prepare for dynamic radios"), which already uses this functionnality without realizing wasn't implemented (just being lucky...). Signed-off-by: Marc Zyngier Cc: Tomasz Nowicki Cc: Christoffer Dall Link: http://lkml.kernel.org/r/1452879670-16133-2-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- include/linux/hrtimer.h | 1 + kernel/time/hrtimer.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 76dd4f0da5ca..a6d64af5e73f 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -151,6 +151,7 @@ enum hrtimer_base_type { HRTIMER_BASE_REALTIME, HRTIMER_BASE_BOOTTIME, HRTIMER_BASE_TAI, + HRTIMER_BASE_MONOTONIC_RAW, HRTIMER_MAX_CLOCK_BASES, }; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 435b8850dd80..a125f222fee2 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -90,12 +90,18 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = .clockid = CLOCK_TAI, .get_time = &ktime_get_clocktai, }, + { + .index = HRTIMER_BASE_MONOTONIC_RAW, + .clockid = CLOCK_MONOTONIC_RAW, + .get_time = &ktime_get_raw, + }, } }; static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, + [CLOCK_MONOTONIC_RAW] = HRTIMER_BASE_MONOTONIC_RAW, [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, [CLOCK_TAI] = HRTIMER_BASE_TAI, }; @@ -1268,7 +1274,10 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now) if (!(active & 0x01)) continue; - basenow = ktime_add(now, base->offset); + if (unlikely(base->index == HRTIMER_BASE_MONOTONIC_RAW)) + basenow = ktime_get_raw(); + else + basenow = ktime_add(now, base->offset); while ((node = timerqueue_getnext(&base->active))) { struct hrtimer *timer; -- cgit From 9006a01829a50cfd6bbd4980910ed46e895e93d7 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 15 Jan 2016 17:41:09 +0000 Subject: hrtimer: Catch illegal clockids It is way too easy to take any random clockid and feed it to the hrtimer subsystem. At best, it gets mapped to a monotonic base, but it would be better to just catch illegal values as early as possible. This patch does exactly that, mapping illegal clockids to an illegal base index, and panicing when we detect the illegal condition. Signed-off-by: Marc Zyngier Cc: Tomasz Nowicki Cc: Christoffer Dall Link: http://lkml.kernel.org/r/1452879670-16133-3-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- kernel/time/hrtimer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index a125f222fee2..cb0fe70f3c51 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -99,6 +99,9 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = }; static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { + /* Make sure we catch unsupported clockids */ + [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, + [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, [CLOCK_MONOTONIC_RAW] = HRTIMER_BASE_MONOTONIC_RAW, @@ -108,7 +111,9 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { static inline int hrtimer_clockid_to_base(clockid_t clock_id) { - return hrtimer_clock_to_base_table[clock_id]; + int base = hrtimer_clock_to_base_table[clock_id]; + BUG_ON(base == HRTIMER_MAX_CLOCK_BASES); + return base; } /* -- cgit From a6e707ddbdf150bd1c2a5c0eccc55abdc62a0039 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 15 Jan 2016 17:41:10 +0000 Subject: KVM: arm/arm64: timer: Switch to CLOCK_MONOTONIC_RAW In order to avoid NTP messing with the guest timer behind our back, use the new and improved monotonic raw version of the hrtimers. Signed-off-by: Marc Zyngier Cc: Tomasz Nowicki Cc: Christoffer Dall Link: http://lkml.kernel.org/r/1452879670-16133-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner --- virt/kvm/arm/arch_timer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 69bca185c471..97c58153f923 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -48,7 +48,7 @@ static bool timer_is_armed(struct arch_timer_cpu *timer) static void timer_arm(struct arch_timer_cpu *timer, u64 ns) { timer->armed = true; - hrtimer_start(&timer->timer, ktime_add_ns(ktime_get(), ns), + hrtimer_start(&timer->timer, ktime_add_ns(ktime_get_raw(), ns), HRTIMER_MODE_ABS); } @@ -308,7 +308,7 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); - hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + hrtimer_init(&timer->timer, CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); timer->timer.function = kvm_timer_expire; } -- cgit From bbf66d897adf2bb0c310db96c97e8db6369f39e1 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Fri, 22 Jan 2016 18:31:53 +0100 Subject: clocksource: Allow unregistering the watchdog Hyper-V vmbus module registers TSC page clocksource when loaded. This is the clocksource with the highest rating and thus it becomes the watchdog making unloading of the vmbus module impossible. Separate clocksource_select_watchdog() from clocksource_enqueue_watchdog() and use it on clocksource register/rating change/unregister. After all, lobotomized monkeys may need some love too. Signed-off-by: Vitaly Kuznetsov Cc: John Stultz Cc: Dexuan Cui Cc: K. Y. Srinivasan Link: http://lkml.kernel.org/r/1453483913-25672-1-git-send-email-vkuznets@redhat.com Signed-off-by: Thomas Gleixner --- kernel/time/clocksource.c | 52 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 664de539299b..56ece145a814 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -323,13 +323,42 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs) /* cs is a watchdog. */ if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS) cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; + } + spin_unlock_irqrestore(&watchdog_lock, flags); +} + +static void clocksource_select_watchdog(bool fallback) +{ + struct clocksource *cs, *old_wd; + unsigned long flags; + + spin_lock_irqsave(&watchdog_lock, flags); + /* save current watchdog */ + old_wd = watchdog; + if (fallback) + watchdog = NULL; + + list_for_each_entry(cs, &clocksource_list, list) { + /* cs is a clocksource to be watched. */ + if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) + continue; + + /* Skip current if we were requested for a fallback. */ + if (fallback && cs == old_wd) + continue; + /* Pick the best watchdog. */ - if (!watchdog || cs->rating > watchdog->rating) { + if (!watchdog || cs->rating > watchdog->rating) watchdog = cs; - /* Reset watchdog cycles */ - clocksource_reset_watchdog(); - } } + /* If we failed to find a fallback restore the old one. */ + if (!watchdog) + watchdog = old_wd; + + /* If we changed the watchdog we need to reset cycles. */ + if (watchdog != old_wd) + clocksource_reset_watchdog(); + /* Check if the watchdog timer needs to be started. */ clocksource_start_watchdog(); spin_unlock_irqrestore(&watchdog_lock, flags); @@ -404,6 +433,7 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs) cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES; } +static void clocksource_select_watchdog(bool fallback) { } static inline void clocksource_dequeue_watchdog(struct clocksource *cs) { } static inline void clocksource_resume_watchdog(void) { } static inline int __clocksource_watchdog_kthread(void) { return 0; } @@ -736,6 +766,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) clocksource_enqueue(cs); clocksource_enqueue_watchdog(cs); clocksource_select(); + clocksource_select_watchdog(false); mutex_unlock(&clocksource_mutex); return 0; } @@ -758,6 +789,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating) mutex_lock(&clocksource_mutex); __clocksource_change_rating(cs, rating); clocksource_select(); + clocksource_select_watchdog(false); mutex_unlock(&clocksource_mutex); } EXPORT_SYMBOL(clocksource_change_rating); @@ -767,12 +799,12 @@ EXPORT_SYMBOL(clocksource_change_rating); */ static int clocksource_unbind(struct clocksource *cs) { - /* - * I really can't convince myself to support this on hardware - * designed by lobotomized monkeys. - */ - if (clocksource_is_watchdog(cs)) - return -EBUSY; + if (clocksource_is_watchdog(cs)) { + /* Select and try to install a replacement watchdog. */ + clocksource_select_watchdog(true); + if (clocksource_is_watchdog(cs)) + return -EBUSY; + } if (cs == curr_clocksource) { /* Select and try to install a replacement clock source */ -- cgit From 6a25c8da00284f5612b404368bd07b69efd84aa2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 26 Jan 2016 04:56:14 +0000 Subject: ASoC: rsnd: don't auto-recover when under/over run error Renesas R-Car sound needs recovery (= restart) when under/over run error occurred, and current driver tries it on under/over run error handler automatically. But this recovery should be handled by userland, not kernel. This patch stops XRUN when under/over run error occur, and will leave the recovery of HW in userland. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/src.c | 39 ++++---------------- sound/soc/sh/rcar/ssi.c | 97 +++++++++++-------------------------------------- 2 files changed, 29 insertions(+), 107 deletions(-) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 7749615bd404..cccca154e4c3 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -25,7 +25,6 @@ struct rsnd_src { struct rsnd_kctrl_cfg_s sen; /* sync convert enable */ struct rsnd_kctrl_cfg_s sync; /* sync convert */ u32 convert_rate; /* sampling rate convert */ - int err; int irq; }; @@ -316,7 +315,7 @@ static void rsnd_src_status_clear(struct rsnd_mod *mod) rsnd_mod_bset(mod, SCU_SYS_STATUS1, val, val); } -static bool rsnd_src_record_error(struct rsnd_mod *mod) +static bool rsnd_src_error_occurred(struct rsnd_mod *mod) { struct rsnd_src *src = rsnd_mod_to_src(mod); u32 val0, val1; @@ -333,12 +332,8 @@ static bool rsnd_src_record_error(struct rsnd_mod *mod) val0 = val0 & 0xffff; if ((rsnd_mod_read(mod, SCU_SYS_STATUS0) & val0) || - (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) { - struct rsnd_src *src = rsnd_mod_to_src(mod); - - src->err++; + (rsnd_mod_read(mod, SCU_SYS_STATUS1) & val1)) ret = true; - } return ret; } @@ -388,8 +383,6 @@ static int rsnd_src_init(struct rsnd_mod *mod, rsnd_src_irq_enable(mod); - src->err = 0; - /* reset sync convert_rate */ src->sync.val = 0; @@ -401,7 +394,6 @@ static int rsnd_src_quit(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_src *src = rsnd_mod_to_src(mod); - struct device *dev = rsnd_priv_to_dev(priv); rsnd_src_irq_disable(mod); @@ -409,10 +401,6 @@ static int rsnd_src_quit(struct rsnd_mod *mod, rsnd_mod_power_off(mod); - if (src->err) - dev_warn(dev, "%s[%d] under/over flow err = %d\n", - rsnd_mod_name(mod), rsnd_mod_id(mod), src->err); - src->convert_rate = 0; /* reset sync convert_rate */ @@ -425,8 +413,7 @@ static void __rsnd_src_interrupt(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_src *src = rsnd_mod_to_src(mod); - struct device *dev = rsnd_priv_to_dev(priv); + bool stop = false; spin_lock(&priv->lock); @@ -434,26 +421,16 @@ static void __rsnd_src_interrupt(struct rsnd_mod *mod, if (!rsnd_io_is_working(io)) goto rsnd_src_interrupt_out; - if (rsnd_src_record_error(mod)) { - - dev_dbg(dev, "%s[%d] restart\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - - rsnd_src_stop(mod, io, priv); - rsnd_src_start(mod, io, priv); - } - - if (src->err > 1024) { - rsnd_src_irq_disable(mod); - - dev_warn(dev, "no more %s[%d] restart\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - } + if (rsnd_src_error_occurred(mod)) + stop = true; rsnd_src_status_clear(mod); rsnd_src_interrupt_out: spin_unlock(&priv->lock); + + if (stop) + snd_pcm_stop_xrun(io->substream); } static irqreturn_t rsnd_src_interrupt(int irq, void *data) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 90674137aa90..5870434bbc58 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -74,7 +74,6 @@ struct rsnd_ssi { u32 wsr; int chan; int rate; - int err; int irq; unsigned int usrcnt; }; @@ -385,8 +384,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, if (ret < 0) return ret; - ssi->err = -1; /* ignore 1st error */ - /* clear error status */ rsnd_ssi_status_clear(mod); @@ -409,13 +406,7 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, } if (!rsnd_ssi_is_parent(mod, io)) { - if (ssi->err > 0) - dev_warn(dev, "%s[%d] under/over flow err = %d\n", - rsnd_mod_name(mod), rsnd_mod_id(mod), - ssi->err); - ssi->cr_own = 0; - ssi->err = 0; rsnd_ssi_irq_disable(mod); } @@ -455,21 +446,9 @@ static int rsnd_ssi_hw_params(struct rsnd_mod *mod, return 0; } -static u32 rsnd_ssi_record_error(struct rsnd_ssi *ssi) -{ - struct rsnd_mod *mod = rsnd_mod_get(ssi); - u32 status = rsnd_ssi_status_get(mod); - - /* under/over flow error */ - if (status & (UIRQ | OIRQ)) - ssi->err++; - - return status; -} - -static int __rsnd_ssi_start(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) +static int rsnd_ssi_start(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); u32 cr; @@ -491,25 +470,21 @@ static int __rsnd_ssi_start(struct rsnd_mod *mod, return 0; } -static int rsnd_ssi_start(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) +static int rsnd_ssi_stop(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) { + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + u32 cr; + /* - * no limit to start + * don't stop if not last user * see also - * rsnd_ssi_stop + * rsnd_ssi_start * rsnd_ssi_interrupt */ - return __rsnd_ssi_start(mod, io, priv); -} - -static int __rsnd_ssi_stop(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) -{ - struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - u32 cr; + if (ssi->usrcnt > 1) + return 0; /* * disable all IRQ, @@ -531,33 +506,14 @@ static int __rsnd_ssi_stop(struct rsnd_mod *mod, return 0; } -static int rsnd_ssi_stop(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) -{ - struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); - - /* - * don't stop if not last user - * see also - * rsnd_ssi_start - * rsnd_ssi_interrupt - */ - if (ssi->usrcnt > 1) - return 0; - - return __rsnd_ssi_stop(mod, io, priv); -} - static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { - struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct device *dev = rsnd_priv_to_dev(priv); int is_dma = rsnd_ssi_is_dma_mode(mod); u32 status; bool elapsed = false; + bool stop = false; spin_lock(&priv->lock); @@ -565,7 +521,7 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, if (!rsnd_io_is_working(io)) goto rsnd_ssi_interrupt_out; - status = rsnd_ssi_record_error(ssi); + status = rsnd_ssi_status_get(mod); /* PIO only */ if (!is_dma && (status & DIRQ)) { @@ -587,23 +543,8 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, } /* DMA only */ - if (is_dma && (status & (UIRQ | OIRQ))) { - /* - * restart SSI - */ - dev_dbg(dev, "%s[%d] restart\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - - __rsnd_ssi_stop(mod, io, priv); - __rsnd_ssi_start(mod, io, priv); - } - - if (ssi->err > 1024) { - rsnd_ssi_irq_disable(mod); - - dev_warn(dev, "no more %s[%d] restart\n", - rsnd_mod_name(mod), rsnd_mod_id(mod)); - } + if (is_dma && (status & (UIRQ | OIRQ))) + stop = true; rsnd_ssi_status_clear(mod); rsnd_ssi_interrupt_out: @@ -611,6 +552,10 @@ rsnd_ssi_interrupt_out: if (elapsed) rsnd_dai_period_elapsed(io); + + if (stop) + snd_pcm_stop_xrun(io->substream); + } static irqreturn_t rsnd_ssi_interrupt(int irq, void *data) -- cgit From b5b442abd9d5cfe4f04a1e83be9900c87444bd66 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 26 Jan 2016 04:56:57 +0000 Subject: ASoC: rsnd: add .irq callback Current rsnd driver has .init/.start/.stop/.quit callbacks, and it needs many IPs (SRC/CTU/MUX/DVC/CMD/SSIU/SSI). Because of these relationship, it might get unnecessary error IRQ when start/stop. This patch adds new .irq callback and control IRQ enable/disable timing to avoid it. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 9 ++++++++- sound/soc/sh/rcar/rsnd.h | 6 ++++++ sound/soc/sh/rcar/src.c | 16 ++++++++-------- sound/soc/sh/rcar/ssi.c | 36 +++++++++++++----------------------- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1fcefab03ad6..704ba7ae9eaf 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -568,9 +568,16 @@ static int rsnd_soc_dai_trigger(struct snd_pcm_substream *substream, int cmd, ret = rsnd_dai_call(start, io, priv); if (ret < 0) goto dai_trigger_end; + + ret = rsnd_dai_call(irq, io, priv, 1); + if (ret < 0) + goto dai_trigger_end; + break; case SNDRV_PCM_TRIGGER_STOP: - ret = rsnd_dai_call(stop, io, priv); + ret = rsnd_dai_call(irq, io, priv, 0); + + ret |= rsnd_dai_call(stop, io, priv); ret |= rsnd_dai_call(quit, io, priv); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 4974db6679c3..bbaf89b6de8a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -249,6 +249,9 @@ struct rsnd_mod_ops { int (*stop)(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv); + int (*irq)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv, int enable); int (*pcm_new)(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct snd_soc_pcm_runtime *rtd); @@ -293,6 +296,7 @@ struct rsnd_mod { #define __rsnd_mod_shift_stop 8 #define __rsnd_mod_shift_probe 28 /* always called */ #define __rsnd_mod_shift_remove 28 /* always called */ +#define __rsnd_mod_shift_irq 28 /* always called */ #define __rsnd_mod_shift_pcm_new 28 /* always called */ #define __rsnd_mod_shift_fallback 28 /* always called */ #define __rsnd_mod_shift_hw_params 28 /* always called */ @@ -303,6 +307,7 @@ struct rsnd_mod { #define __rsnd_mod_add_quit -1 #define __rsnd_mod_add_start 1 #define __rsnd_mod_add_stop -1 +#define __rsnd_mod_add_irq 0 #define __rsnd_mod_add_pcm_new 0 #define __rsnd_mod_add_fallback 0 #define __rsnd_mod_add_hw_params 0 @@ -313,6 +318,7 @@ struct rsnd_mod { #define __rsnd_mod_call_quit 1 #define __rsnd_mod_call_start 0 #define __rsnd_mod_call_stop 1 +#define __rsnd_mod_call_irq 0 #define __rsnd_mod_call_pcm_new 0 #define __rsnd_mod_call_fallback 0 #define __rsnd_mod_call_hw_params 0 diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index cccca154e4c3..ab5f13155055 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -271,9 +271,10 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, rsnd_adg_set_convert_timing_gen2(mod, io); } -#define rsnd_src_irq_enable(mod) rsnd_src_irq_ctrol(mod, 1) -#define rsnd_src_irq_disable(mod) rsnd_src_irq_ctrol(mod, 0) -static void rsnd_src_irq_ctrol(struct rsnd_mod *mod, int enable) +static int rsnd_src_irq(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv, + int enable) { struct rsnd_src *src = rsnd_mod_to_src(mod); u32 sys_int_val, int_val, sys_int_mask; @@ -305,6 +306,8 @@ static void rsnd_src_irq_ctrol(struct rsnd_mod *mod, int enable) rsnd_mod_write(mod, SRC_INT_ENABLE0, int_val); rsnd_mod_bset(mod, SCU_SYS_INT_EN0, sys_int_mask, sys_int_val); rsnd_mod_bset(mod, SCU_SYS_INT_EN1, sys_int_mask, sys_int_val); + + return 0; } static void rsnd_src_status_clear(struct rsnd_mod *mod) @@ -381,8 +384,6 @@ static int rsnd_src_init(struct rsnd_mod *mod, rsnd_src_status_clear(mod); - rsnd_src_irq_enable(mod); - /* reset sync convert_rate */ src->sync.val = 0; @@ -395,8 +396,6 @@ static int rsnd_src_quit(struct rsnd_mod *mod, { struct rsnd_src *src = rsnd_mod_to_src(mod); - rsnd_src_irq_disable(mod); - rsnd_src_halt(mod); rsnd_mod_power_off(mod); @@ -455,7 +454,7 @@ static int rsnd_src_probe_(struct rsnd_mod *mod, /* * IRQ is not supported on non-DT * see - * rsnd_src_irq_enable() + * rsnd_src_irq() */ ret = devm_request_irq(dev, irq, rsnd_src_interrupt, @@ -518,6 +517,7 @@ static struct rsnd_mod_ops rsnd_src_ops = { .quit = rsnd_src_quit, .start = rsnd_src_start, .stop = rsnd_src_stop, + .irq = rsnd_src_irq, .hw_params = rsnd_src_hw_params, .pcm_new = rsnd_src_pcm_new, }; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 5870434bbc58..803e9ae65915 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -142,30 +142,24 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, dev_warn(dev, "status check failed\n"); } -static int rsnd_ssi_irq_enable(struct rsnd_mod *ssi_mod) +static int rsnd_ssi_irq(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv, + int enable) { - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); + struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + u32 val = 0; if (rsnd_is_gen1(priv)) return 0; - /* enable SSI interrupt if Gen2 */ - rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, - rsnd_ssi_is_dma_mode(ssi_mod) ? - 0x0e000000 : 0x0f000000); - - return 0; -} - -static int rsnd_ssi_irq_disable(struct rsnd_mod *ssi_mod) -{ - struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); - - if (rsnd_is_gen1(priv)) + if (ssi->usrcnt != 1) return 0; - /* disable SSI interrupt if Gen2 */ - rsnd_mod_write(ssi_mod, SSI_INT_ENABLE, 0x00000000); + if (enable) + val = rsnd_ssi_is_dma_mode(mod) ? 0x0e000000 : 0x0f000000; + + rsnd_mod_write(mod, SSI_INT_ENABLE, val); return 0; } @@ -387,8 +381,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, /* clear error status */ rsnd_ssi_status_clear(mod); - rsnd_ssi_irq_enable(mod); - return 0; } @@ -405,12 +397,9 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, return -EIO; } - if (!rsnd_ssi_is_parent(mod, io)) { + if (!rsnd_ssi_is_parent(mod, io)) ssi->cr_own = 0; - rsnd_ssi_irq_disable(mod); - } - rsnd_ssi_master_clk_stop(ssi, io); rsnd_mod_power_off(mod); @@ -627,6 +616,7 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .quit = rsnd_ssi_quit, .start = rsnd_ssi_start, .stop = rsnd_ssi_stop, + .irq = rsnd_ssi_irq, .hw_params = rsnd_ssi_hw_params, }; -- cgit From a2d382a4f1ffea4f303d906cc63e4b99edc32c1a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 26 Jan 2016 22:14:36 +0800 Subject: crypto: skcipher - Add helper to retrieve driver name This patch adds the helper crypto_skcipher_driver_name which returns the driver name of the alg object for a given tfm. This is needed by ecryptfs. Signed-off-by: Herbert Xu --- include/crypto/skcipher.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index f7a03a17bc1d..5bb70565b13a 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -231,6 +231,12 @@ static inline int crypto_has_skcipher(const char *alg_name, u32 type, crypto_skcipher_mask(mask)); } +static inline const char *crypto_skcipher_driver_name( + struct crypto_skcipher *tfm) +{ + return crypto_tfm_alg_name(crypto_skcipher_tfm(tfm)); +} + /** * crypto_skcipher_ivsize() - obtain IV size * @tfm: cipher handle -- cgit From 84a2c9319dca2cedad13a776c2bc88f41d6beddf Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:06 +0800 Subject: block: cryptoloop - Use new skcipher interface This patch replaces uses of blkcipher with the new skcipher interface. Signed-off-by: Herbert Xu --- drivers/block/cryptoloop.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 99e773cb70d0..3d31761c0ed0 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -21,9 +21,9 @@ #include +#include #include #include -#include #include #include #include @@ -46,7 +46,7 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) char *cipher; char *mode; char *cmsp = cms; /* c-m string pointer */ - struct crypto_blkcipher *tfm; + struct crypto_skcipher *tfm; /* encryption breaks for non sector aligned offsets */ @@ -82,12 +82,12 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) *cmsp++ = ')'; *cmsp = 0; - tfm = crypto_alloc_blkcipher(cms, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_skcipher(cms, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) return PTR_ERR(tfm); - err = crypto_blkcipher_setkey(tfm, info->lo_encrypt_key, - info->lo_encrypt_key_size); + err = crypto_skcipher_setkey(tfm, info->lo_encrypt_key, + info->lo_encrypt_key_size); if (err != 0) goto out_free_tfm; @@ -96,17 +96,14 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) return 0; out_free_tfm: - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); out: return err; } -typedef int (*encdec_cbc_t)(struct blkcipher_desc *desc, - struct scatterlist *sg_out, - struct scatterlist *sg_in, - unsigned int nsg); +typedef int (*encdec_cbc_t)(struct skcipher_request *req); static int cryptoloop_transfer(struct loop_device *lo, int cmd, @@ -114,11 +111,8 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, struct page *loop_page, unsigned loop_off, int size, sector_t IV) { - struct crypto_blkcipher *tfm = lo->key_data; - struct blkcipher_desc desc = { - .tfm = tfm, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP, - }; + struct crypto_skcipher *tfm = lo->key_data; + SKCIPHER_REQUEST_ON_STACK(req, tfm); struct scatterlist sg_out; struct scatterlist sg_in; @@ -127,6 +121,10 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, unsigned in_offs, out_offs; int err; + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + sg_init_table(&sg_out, 1); sg_init_table(&sg_in, 1); @@ -135,13 +133,13 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, in_offs = raw_off; out_page = loop_page; out_offs = loop_off; - encdecfunc = crypto_blkcipher_crt(tfm)->decrypt; + encdecfunc = crypto_skcipher_decrypt; } else { in_page = loop_page; in_offs = loop_off; out_page = raw_page; out_offs = raw_off; - encdecfunc = crypto_blkcipher_crt(tfm)->encrypt; + encdecfunc = crypto_skcipher_encrypt; } while (size > 0) { @@ -152,10 +150,10 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, sg_set_page(&sg_in, in_page, sz, in_offs); sg_set_page(&sg_out, out_page, sz, out_offs); - desc.info = iv; - err = encdecfunc(&desc, &sg_out, &sg_in, sz); + skcipher_request_set_crypt(req, &sg_in, &sg_out, sz, iv); + err = encdecfunc(req); if (err) - return err; + goto out; IV++; size -= sz; @@ -163,7 +161,11 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, out_offs += sz; } - return 0; + err = 0; + +out: + skcipher_request_zero(req); + return err; } static int @@ -175,9 +177,9 @@ cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) static int cryptoloop_release(struct loop_device *lo) { - struct crypto_blkcipher *tfm = lo->key_data; + struct crypto_skcipher *tfm = lo->key_data; if (tfm != NULL) { - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); lo->key_data = NULL; return 0; } -- cgit From fdb89b1b8f814260fd8239b1e09edf9e12c97ef2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:16 +0800 Subject: ppp_mppe: Use skcipher and ahash This patch replaces uses of blkcipher with skcipher, and the long obsolete hash interface with ahash. This is a bug-for-bug conversion and no attempt has been made to fix bugs such as the ignored return values of the crypto operations. Signed-off-by: Herbert Xu --- drivers/net/ppp/ppp_mppe.c | 99 +++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c index 05005c660d4d..f60f7660b451 100644 --- a/drivers/net/ppp/ppp_mppe.c +++ b/drivers/net/ppp/ppp_mppe.c @@ -42,6 +42,8 @@ * deprecated in 2.6 */ +#include +#include #include #include #include @@ -49,7 +51,6 @@ #include #include #include -#include #include #include #include @@ -94,8 +95,8 @@ static inline void sha_pad_init(struct sha_pad *shapad) * State for an MPPE (de)compressor. */ struct ppp_mppe_state { - struct crypto_blkcipher *arc4; - struct crypto_hash *sha1; + struct crypto_skcipher *arc4; + struct crypto_ahash *sha1; unsigned char *sha1_digest; unsigned char master_key[MPPE_MAX_KEY_LEN]; unsigned char session_key[MPPE_MAX_KEY_LEN]; @@ -135,7 +136,7 @@ struct ppp_mppe_state { */ static void get_new_key_from_sha(struct ppp_mppe_state * state) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, state->sha1); struct scatterlist sg[4]; unsigned int nbytes; @@ -148,10 +149,12 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) nbytes += setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); - desc.tfm = state->sha1; - desc.flags = 0; + ahash_request_set_tfm(req, state->sha1); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, state->sha1_digest, nbytes); - crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest); + crypto_ahash_digest(req); + ahash_request_zero(req); } /* @@ -161,20 +164,23 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state) static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) { struct scatterlist sg_in[1], sg_out[1]; - struct blkcipher_desc desc = { .tfm = state->arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, state->arc4); + + skcipher_request_set_tfm(req, state->arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); get_new_key_from_sha(state); if (!initial_key) { - crypto_blkcipher_setkey(state->arc4, state->sha1_digest, - state->keylen); + crypto_skcipher_setkey(state->arc4, state->sha1_digest, + state->keylen); sg_init_table(sg_in, 1); sg_init_table(sg_out, 1); setup_sg(sg_in, state->sha1_digest, state->keylen); setup_sg(sg_out, state->session_key, state->keylen); - if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, - state->keylen) != 0) { + skcipher_request_set_crypt(req, sg_in, sg_out, state->keylen, + NULL); + if (crypto_skcipher_encrypt(req)) printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); - } } else { memcpy(state->session_key, state->sha1_digest, state->keylen); } @@ -184,7 +190,8 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) state->session_key[1] = 0x26; state->session_key[2] = 0x9e; } - crypto_blkcipher_setkey(state->arc4, state->session_key, state->keylen); + crypto_skcipher_setkey(state->arc4, state->session_key, state->keylen); + skcipher_request_zero(req); } /* @@ -204,19 +211,19 @@ static void *mppe_alloc(unsigned char *options, int optlen) goto out; - state->arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + state->arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(state->arc4)) { state->arc4 = NULL; goto out_free; } - state->sha1 = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); + state->sha1 = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(state->sha1)) { state->sha1 = NULL; goto out_free; } - digestsize = crypto_hash_digestsize(state->sha1); + digestsize = crypto_ahash_digestsize(state->sha1); if (digestsize < MPPE_MAX_KEY_LEN) goto out_free; @@ -237,15 +244,12 @@ static void *mppe_alloc(unsigned char *options, int optlen) return (void *)state; - out_free: - if (state->sha1_digest) - kfree(state->sha1_digest); - if (state->sha1) - crypto_free_hash(state->sha1); - if (state->arc4) - crypto_free_blkcipher(state->arc4); - kfree(state); - out: +out_free: + kfree(state->sha1_digest); + crypto_free_ahash(state->sha1); + crypto_free_skcipher(state->arc4); + kfree(state); +out: return NULL; } @@ -256,13 +260,10 @@ static void mppe_free(void *arg) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; if (state) { - if (state->sha1_digest) kfree(state->sha1_digest); - if (state->sha1) - crypto_free_hash(state->sha1); - if (state->arc4) - crypto_free_blkcipher(state->arc4); - kfree(state); + crypto_free_ahash(state->sha1); + crypto_free_skcipher(state->arc4); + kfree(state); } } @@ -368,8 +369,9 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, int isize, int osize) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - struct blkcipher_desc desc = { .tfm = state->arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, state->arc4); int proto; + int err; struct scatterlist sg_in[1], sg_out[1]; /* @@ -426,7 +428,13 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, sg_init_table(sg_out, 1); setup_sg(sg_in, ibuf, isize); setup_sg(sg_out, obuf, osize); - if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) { + + skcipher_request_set_tfm(req, state->arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in, sg_out, isize, NULL); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + if (err) { printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); return -1; } @@ -475,7 +483,7 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, int osize) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - struct blkcipher_desc desc = { .tfm = state->arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, state->arc4); unsigned ccount; int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; struct scatterlist sg_in[1], sg_out[1]; @@ -609,9 +617,14 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, sg_init_table(sg_out, 1); setup_sg(sg_in, ibuf, 1); setup_sg(sg_out, obuf, 1); - if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) { + + skcipher_request_set_tfm(req, state->arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in, sg_out, 1, NULL); + if (crypto_skcipher_decrypt(req)) { printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); - return DECOMP_ERROR; + osize = DECOMP_ERROR; + goto out_zap_req; } /* @@ -629,9 +642,11 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, /* And finally, decrypt the rest of the packet. */ setup_sg(sg_in, ibuf + 1, isize - 1); setup_sg(sg_out, obuf + 1, osize - 1); - if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, isize - 1)) { + skcipher_request_set_crypt(req, sg_in, sg_out, isize - 1, NULL); + if (crypto_skcipher_decrypt(req)) { printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); - return DECOMP_ERROR; + osize = DECOMP_ERROR; + goto out_zap_req; } state->stats.unc_bytes += osize; @@ -642,6 +657,8 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, /* good packet credit */ state->sanity_errors >>= 1; +out_zap_req: + skcipher_request_zero(req); return osize; sanity_error: @@ -714,8 +731,8 @@ static struct compressor ppp_mppe = { static int __init ppp_mppe_init(void) { int answer; - if (!(crypto_has_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) && - crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC))) + if (!(crypto_has_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) && + crypto_has_ahash("sha1", 0, CRYPTO_ALG_ASYNC))) return -ENODEV; sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); -- cgit From a1d383943fdd4279c852b0e5718bcf13a923e4dc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:26 +0800 Subject: staging: rtl8192e: Replace uses of obsolete blkcipher and hash The interfaces blkcipher and hash are obsolete. This patch replaces them with skcipher and ahash respectively. Signed-off-by: Herbert Xu Acked-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_crypt_tkip.c | 99 +++++++++++++++------------- drivers/staging/rtl8192e/rtllib_crypt_wep.c | 48 ++++++++------ 2 files changed, 82 insertions(+), 65 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c index 2096d78913bd..8eac7cdd5f3e 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c @@ -9,6 +9,8 @@ * more details. */ +#include +#include #include #include #include @@ -18,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -48,10 +49,10 @@ struct rtllib_tkip_data { u32 dot11RSNAStatsTKIPLocalMICFailures; int key_idx; - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; + struct crypto_skcipher *rx_tfm_arc4; + struct crypto_ahash *rx_tfm_michael; + struct crypto_skcipher *tx_tfm_arc4; + struct crypto_ahash *tx_tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16]; u8 tx_hdr[16]; @@ -65,32 +66,32 @@ static void *rtllib_tkip_init(int key_idx) if (priv == NULL) goto fail; priv->key_idx = key_idx; - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { pr_debug("Could not allocate crypto API arc4\n"); priv->tx_tfm_arc4 = NULL; goto fail; } - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); + priv->tx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_michael)) { pr_debug("Could not allocate crypto API michael_mic\n"); priv->tx_tfm_michael = NULL; goto fail; } - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { pr_debug("Could not allocate crypto API arc4\n"); priv->rx_tfm_arc4 = NULL; goto fail; } - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); + priv->rx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_michael)) { pr_debug("Could not allocate crypto API michael_mic\n"); priv->rx_tfm_michael = NULL; @@ -100,14 +101,10 @@ static void *rtllib_tkip_init(int key_idx) fail: if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); + crypto_free_ahash(priv->tx_tfm_michael); + crypto_free_skcipher(priv->tx_tfm_arc4); + crypto_free_ahash(priv->rx_tfm_michael); + crypto_free_skcipher(priv->rx_tfm_arc4); kfree(priv); } @@ -120,14 +117,10 @@ static void rtllib_tkip_deinit(void *priv) struct rtllib_tkip_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); + crypto_free_ahash(_priv->tx_tfm_michael); + crypto_free_skcipher(_priv->tx_tfm_arc4); + crypto_free_ahash(_priv->rx_tfm_michael); + crypto_free_skcipher(_priv->rx_tfm_arc4); } kfree(priv); } @@ -301,7 +294,6 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; int ret = 0; u8 rc4key[16], *icv; u32 crc; @@ -347,6 +339,8 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = (tkey->tx_iv32 >> 24) & 0xff; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4); + icv = skb_put(skb, 4); crc = ~crc32_le(~0, pos, len); icv[0] = crc; @@ -357,8 +351,12 @@ static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) sg_init_one(&sg, pos, len+4); - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + skcipher_request_set_tfm(req, tkey->tx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } tkey->tx_iv16++; @@ -384,12 +382,12 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) struct rtllib_hdr_4addr *hdr; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; u8 rc4key[16]; u8 icv[4]; u32 crc; struct scatterlist sg; int plen; + int err; if (skb->len < hdr_len + 8 + 4) return -1; @@ -425,6 +423,8 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (!tcb_desc->bHwSec || (skb->cb[0] == 1)) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4); + if ((iv32 < tkey->rx_iv32 || (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) && tkey->initialized) { @@ -450,8 +450,13 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) sg_init_one(&sg, pos, plen+4); - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + skcipher_request_set_tfm(req, tkey->rx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) { if (net_ratelimit()) { netdev_dbg(skb->dev, "Failed to decrypt received packet from %pM\n", @@ -500,11 +505,12 @@ static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) } -static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, +static int michael_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *hdr, u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; + int err; if (tfm_michael == NULL) { pr_warn("michael_mic: tfm_michael == NULL\n"); @@ -514,12 +520,15 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, sg_set_buf(&sg[0], hdr, 16); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, 8)) + if (crypto_ahash_setkey(tfm_michael, key, 8)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + 16); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) @@ -655,10 +664,10 @@ static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv) { struct rtllib_tkip_data *tkey = priv; int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; + struct crypto_ahash *tfm = tkey->tx_tfm_michael; + struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_ahash *tfm3 = tkey->rx_tfm_michael; + struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c index 21d7eee4c9a9..b3343a5d0fd6 100644 --- a/drivers/staging/rtl8192e/rtllib_crypt_wep.c +++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c @@ -9,6 +9,7 @@ * more details. */ +#include #include #include #include @@ -17,8 +18,6 @@ #include #include "rtllib.h" -#include - #include #include @@ -28,8 +27,8 @@ struct prism2_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; + struct crypto_skcipher *tx_tfm; + struct crypto_skcipher *rx_tfm; }; @@ -42,13 +41,13 @@ static void *prism2_wep_init(int keyidx) goto fail; priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) { pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n"); priv->tx_tfm = NULL; goto fail; } - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) { pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n"); priv->rx_tfm = NULL; @@ -62,10 +61,8 @@ static void *prism2_wep_init(int keyidx) fail: if (priv) { - if (priv->tx_tfm) - crypto_free_blkcipher(priv->tx_tfm); - if (priv->rx_tfm) - crypto_free_blkcipher(priv->rx_tfm); + crypto_free_skcipher(priv->tx_tfm); + crypto_free_skcipher(priv->rx_tfm); kfree(priv); } return NULL; @@ -77,10 +74,8 @@ static void prism2_wep_deinit(void *priv) struct prism2_wep_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); + crypto_free_skcipher(_priv->tx_tfm); + crypto_free_skcipher(_priv->rx_tfm); } kfree(priv); } @@ -99,10 +94,10 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 *pos; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; u32 crc; u8 *icv; struct scatterlist sg; + int err; if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || skb->len < hdr_len){ @@ -140,6 +135,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) memcpy(key + 3, wep->key, wep->key_len); if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); /* Append little-endian CRC32 and encrypt it to produce ICV */ crc = ~crc32_le(~0, pos, len); @@ -150,8 +146,13 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; sg_init_one(&sg, pos, len+4); - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + crypto_skcipher_setkey(wep->tx_tfm, key, klen); + skcipher_request_set_tfm(req, wep->tx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } return 0; @@ -173,10 +174,10 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 keyidx, *pos; struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; u32 crc; u8 icv[4]; struct scatterlist sg; + int err; if (skb->len < hdr_len + 8) return -1; @@ -198,9 +199,16 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 8; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); + sg_init_one(&sg, pos, plen+4); - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + crypto_skcipher_setkey(wep->rx_tfm, key, klen); + skcipher_request_set_tfm(req, wep->rx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) return -7; crc = ~crc32_le(~0, pos, plen); icv[0] = crc; -- cgit From bbdb23b5d69521a2e3059b33d1f6ed8e1216118a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:36 +0800 Subject: dm crypt: Use skcipher and ahash This patch replaces uses of ablkcipher with skcipher, and the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu --- drivers/md/dm-crypt.c | 93 ++++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 3147c8d09ea8..06a4e3cfc66a 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -44,7 +45,7 @@ struct convert_context { struct bvec_iter iter_out; sector_t cc_sector; atomic_t cc_pending; - struct ablkcipher_request *req; + struct skcipher_request *req; }; /* @@ -86,7 +87,7 @@ struct crypt_iv_operations { }; struct iv_essiv_private { - struct crypto_hash *hash_tfm; + struct crypto_ahash *hash_tfm; u8 *salt; }; @@ -153,13 +154,13 @@ struct crypt_config { /* ESSIV: struct crypto_cipher *essiv_tfm */ void *iv_private; - struct crypto_ablkcipher **tfms; + struct crypto_skcipher **tfms; unsigned tfms_count; /* * Layout of each crypto request: * - * struct ablkcipher_request + * struct skcipher_request * context * padding * struct dm_crypt_request @@ -189,7 +190,7 @@ static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq); /* * Use this to access cipher attributes that are the same for each CPU. */ -static struct crypto_ablkcipher *any_tfm(struct crypt_config *cc) +static struct crypto_skcipher *any_tfm(struct crypt_config *cc) { return cc->tfms[0]; } @@ -263,23 +264,25 @@ static int crypt_iv_plain64_gen(struct crypt_config *cc, u8 *iv, static int crypt_iv_essiv_init(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, essiv->hash_tfm); struct scatterlist sg; struct crypto_cipher *essiv_tfm; int err; sg_init_one(&sg, cc->key, cc->key_size); - desc.tfm = essiv->hash_tfm; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + ahash_request_set_tfm(req, essiv->hash_tfm); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); + ahash_request_set_crypt(req, &sg, essiv->salt, cc->key_size); - err = crypto_hash_digest(&desc, &sg, cc->key_size, essiv->salt); + err = crypto_ahash_digest(req); + ahash_request_zero(req); if (err) return err; essiv_tfm = cc->iv_private; err = crypto_cipher_setkey(essiv_tfm, essiv->salt, - crypto_hash_digestsize(essiv->hash_tfm)); + crypto_ahash_digestsize(essiv->hash_tfm)); if (err) return err; @@ -290,7 +293,7 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) static int crypt_iv_essiv_wipe(struct crypt_config *cc) { struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm); + unsigned salt_size = crypto_ahash_digestsize(essiv->hash_tfm); struct crypto_cipher *essiv_tfm; int r, err = 0; @@ -320,7 +323,7 @@ static struct crypto_cipher *setup_essiv_cpu(struct crypt_config *cc, } if (crypto_cipher_blocksize(essiv_tfm) != - crypto_ablkcipher_ivsize(any_tfm(cc))) { + crypto_skcipher_ivsize(any_tfm(cc))) { ti->error = "Block size of ESSIV cipher does " "not match IV size of block cipher"; crypto_free_cipher(essiv_tfm); @@ -342,7 +345,7 @@ static void crypt_iv_essiv_dtr(struct crypt_config *cc) struct crypto_cipher *essiv_tfm; struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; - crypto_free_hash(essiv->hash_tfm); + crypto_free_ahash(essiv->hash_tfm); essiv->hash_tfm = NULL; kzfree(essiv->salt); @@ -360,7 +363,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { struct crypto_cipher *essiv_tfm = NULL; - struct crypto_hash *hash_tfm = NULL; + struct crypto_ahash *hash_tfm = NULL; u8 *salt = NULL; int err; @@ -370,14 +373,14 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, } /* Allocate hash algorithm */ - hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC); + hash_tfm = crypto_alloc_ahash(opts, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(hash_tfm)) { ti->error = "Error initializing ESSIV hash"; err = PTR_ERR(hash_tfm); goto bad; } - salt = kzalloc(crypto_hash_digestsize(hash_tfm), GFP_KERNEL); + salt = kzalloc(crypto_ahash_digestsize(hash_tfm), GFP_KERNEL); if (!salt) { ti->error = "Error kmallocing salt storage in ESSIV"; err = -ENOMEM; @@ -388,7 +391,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, cc->iv_gen_private.essiv.hash_tfm = hash_tfm; essiv_tfm = setup_essiv_cpu(cc, ti, salt, - crypto_hash_digestsize(hash_tfm)); + crypto_ahash_digestsize(hash_tfm)); if (IS_ERR(essiv_tfm)) { crypt_iv_essiv_dtr(cc); return PTR_ERR(essiv_tfm); @@ -399,7 +402,7 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, bad: if (hash_tfm && !IS_ERR(hash_tfm)) - crypto_free_hash(hash_tfm); + crypto_free_ahash(hash_tfm); kfree(salt); return err; } @@ -419,7 +422,7 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { - unsigned bs = crypto_ablkcipher_blocksize(any_tfm(cc)); + unsigned bs = crypto_skcipher_blocksize(any_tfm(cc)); int log = ilog2(bs); /* we need to calculate how far we must shift the sector count @@ -816,27 +819,27 @@ static void crypt_convert_init(struct crypt_config *cc, } static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc, - struct ablkcipher_request *req) + struct skcipher_request *req) { return (struct dm_crypt_request *)((char *)req + cc->dmreq_start); } -static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, +static struct skcipher_request *req_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq) { - return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); + return (struct skcipher_request *)((char *)dmreq - cc->dmreq_start); } static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq) { return (u8 *)ALIGN((unsigned long)(dmreq + 1), - crypto_ablkcipher_alignmask(any_tfm(cc)) + 1); + crypto_skcipher_alignmask(any_tfm(cc)) + 1); } static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, - struct ablkcipher_request *req) + struct skcipher_request *req) { struct bio_vec bv_in = bio_iter_iovec(ctx->bio_in, ctx->iter_in); struct bio_vec bv_out = bio_iter_iovec(ctx->bio_out, ctx->iter_out); @@ -866,13 +869,13 @@ static int crypt_convert_block(struct crypt_config *cc, return r; } - ablkcipher_request_set_crypt(req, &dmreq->sg_in, &dmreq->sg_out, - 1 << SECTOR_SHIFT, iv); + skcipher_request_set_crypt(req, &dmreq->sg_in, &dmreq->sg_out, + 1 << SECTOR_SHIFT, iv); if (bio_data_dir(ctx->bio_in) == WRITE) - r = crypto_ablkcipher_encrypt(req); + r = crypto_skcipher_encrypt(req); else - r = crypto_ablkcipher_decrypt(req); + r = crypto_skcipher_decrypt(req); if (!r && cc->iv_gen_ops && cc->iv_gen_ops->post) r = cc->iv_gen_ops->post(cc, iv, dmreq); @@ -891,23 +894,23 @@ static void crypt_alloc_req(struct crypt_config *cc, if (!ctx->req) ctx->req = mempool_alloc(cc->req_pool, GFP_NOIO); - ablkcipher_request_set_tfm(ctx->req, cc->tfms[key_index]); + skcipher_request_set_tfm(ctx->req, cc->tfms[key_index]); /* * Use REQ_MAY_BACKLOG so a cipher driver internally backlogs * requests if driver request queue is full. */ - ablkcipher_request_set_callback(ctx->req, + skcipher_request_set_callback(ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, kcryptd_async_done, dmreq_of_req(cc, ctx->req)); } static void crypt_free_req(struct crypt_config *cc, - struct ablkcipher_request *req, struct bio *base_bio) + struct skcipher_request *req, struct bio *base_bio) { struct dm_crypt_io *io = dm_per_bio_data(base_bio, cc->per_bio_data_size); - if ((struct ablkcipher_request *)(io + 1) != req) + if ((struct skcipher_request *)(io + 1) != req) mempool_free(req, cc->req_pool); } @@ -1437,7 +1440,7 @@ static void crypt_free_tfms(struct crypt_config *cc) for (i = 0; i < cc->tfms_count; i++) if (cc->tfms[i] && !IS_ERR(cc->tfms[i])) { - crypto_free_ablkcipher(cc->tfms[i]); + crypto_free_skcipher(cc->tfms[i]); cc->tfms[i] = NULL; } @@ -1450,13 +1453,13 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode) unsigned i; int err; - cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_ablkcipher *), + cc->tfms = kmalloc(cc->tfms_count * sizeof(struct crypto_skcipher *), GFP_KERNEL); if (!cc->tfms) return -ENOMEM; for (i = 0; i < cc->tfms_count; i++) { - cc->tfms[i] = crypto_alloc_ablkcipher(ciphermode, 0, 0); + cc->tfms[i] = crypto_alloc_skcipher(ciphermode, 0, 0); if (IS_ERR(cc->tfms[i])) { err = PTR_ERR(cc->tfms[i]); crypt_free_tfms(cc); @@ -1476,9 +1479,9 @@ static int crypt_setkey_allcpus(struct crypt_config *cc) subkey_size = (cc->key_size - cc->key_extra_size) >> ilog2(cc->tfms_count); for (i = 0; i < cc->tfms_count; i++) { - r = crypto_ablkcipher_setkey(cc->tfms[i], - cc->key + (i * subkey_size), - subkey_size); + r = crypto_skcipher_setkey(cc->tfms[i], + cc->key + (i * subkey_size), + subkey_size); if (r) err = r; } @@ -1645,7 +1648,7 @@ static int crypt_ctr_cipher(struct dm_target *ti, } /* Initialize IV */ - cc->iv_size = crypto_ablkcipher_ivsize(any_tfm(cc)); + cc->iv_size = crypto_skcipher_ivsize(any_tfm(cc)); if (cc->iv_size) /* at least a 64 bit sector number should fit in our buffer */ cc->iv_size = max(cc->iv_size, @@ -1763,21 +1766,21 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (ret < 0) goto bad; - cc->dmreq_start = sizeof(struct ablkcipher_request); - cc->dmreq_start += crypto_ablkcipher_reqsize(any_tfm(cc)); + cc->dmreq_start = sizeof(struct skcipher_request); + cc->dmreq_start += crypto_skcipher_reqsize(any_tfm(cc)); cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); - if (crypto_ablkcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) { + if (crypto_skcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) { /* Allocate the padding exactly */ iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request)) - & crypto_ablkcipher_alignmask(any_tfm(cc)); + & crypto_skcipher_alignmask(any_tfm(cc)); } else { /* * If the cipher requires greater alignment than kmalloc * alignment, we don't know the exact position of the * initialization vector. We must assume worst case. */ - iv_size_padding = crypto_ablkcipher_alignmask(any_tfm(cc)); + iv_size_padding = crypto_skcipher_alignmask(any_tfm(cc)); } ret = -ENOMEM; @@ -1922,7 +1925,7 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) io = dm_per_bio_data(bio, cc->per_bio_data_size); crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); - io->ctx.req = (struct ablkcipher_request *)(io + 1); + io->ctx.req = (struct skcipher_request *)(io + 1); if (bio_data_dir(io->base_bio) == READ) { if (kcryptd_io_read(io, GFP_NOWAIT)) -- cgit From a60b7fafd2d3ab51cf085e816627cbb4ef2f311b Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:47 +0800 Subject: orinoco: Use ahash This patch replaces uses the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu --- drivers/net/wireless/intersil/orinoco/mic.c | 29 +++++++++++++++---------- drivers/net/wireless/intersil/orinoco/mic.h | 4 ++-- drivers/net/wireless/intersil/orinoco/orinoco.h | 4 ++-- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/intersil/orinoco/mic.c b/drivers/net/wireless/intersil/orinoco/mic.c index fce4a843e656..bc7397d709d3 100644 --- a/drivers/net/wireless/intersil/orinoco/mic.c +++ b/drivers/net/wireless/intersil/orinoco/mic.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include "orinoco.h" #include "mic.h" @@ -16,7 +16,8 @@ /********************************************************************/ int orinoco_mic_init(struct orinoco_private *priv) { - priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); + priv->tx_tfm_mic = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_mic)) { printk(KERN_DEBUG "orinoco_mic_init: could not allocate " "crypto API michael_mic\n"); @@ -24,7 +25,8 @@ int orinoco_mic_init(struct orinoco_private *priv) return -ENOMEM; } - priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); + priv->rx_tfm_mic = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_mic)) { printk(KERN_DEBUG "orinoco_mic_init: could not allocate " "crypto API michael_mic\n"); @@ -38,18 +40,19 @@ int orinoco_mic_init(struct orinoco_private *priv) void orinoco_mic_free(struct orinoco_private *priv) { if (priv->tx_tfm_mic) - crypto_free_hash(priv->tx_tfm_mic); + crypto_free_ahash(priv->tx_tfm_mic); if (priv->rx_tfm_mic) - crypto_free_hash(priv->rx_tfm_mic); + crypto_free_ahash(priv->rx_tfm_mic); } -int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, +int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *da, u8 *sa, u8 priority, u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; u8 hdr[ETH_HLEN + 2]; /* size of header + padding */ + int err; if (tfm_michael == NULL) { printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n"); @@ -69,11 +72,13 @@ int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, sg_set_buf(&sg[0], hdr, sizeof(hdr)); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN)) + if (crypto_ahash_setkey(tfm_michael, key, MIC_KEYLEN)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr), - mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + sizeof(hdr)); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } diff --git a/drivers/net/wireless/intersil/orinoco/mic.h b/drivers/net/wireless/intersil/orinoco/mic.h index 04d05bc566d6..ce731d05cc98 100644 --- a/drivers/net/wireless/intersil/orinoco/mic.h +++ b/drivers/net/wireless/intersil/orinoco/mic.h @@ -11,11 +11,11 @@ /* Forward declarations */ struct orinoco_private; -struct crypto_hash; +struct crypto_ahash; int orinoco_mic_init(struct orinoco_private *priv); void orinoco_mic_free(struct orinoco_private *priv); -int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, +int orinoco_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *da, u8 *sa, u8 priority, u8 *data, size_t data_len, u8 *mic); diff --git a/drivers/net/wireless/intersil/orinoco/orinoco.h b/drivers/net/wireless/intersil/orinoco/orinoco.h index eebd2be21ee9..2f0c84b1c440 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco.h +++ b/drivers/net/wireless/intersil/orinoco/orinoco.h @@ -152,8 +152,8 @@ struct orinoco_private { u8 *wpa_ie; int wpa_ie_len; - struct crypto_hash *rx_tfm_mic; - struct crypto_hash *tx_tfm_mic; + struct crypto_ahash *rx_tfm_mic; + struct crypto_ahash *tx_tfm_mic; unsigned int wpa_enabled:1; unsigned int tkip_cm_active:1; -- cgit From c3a79227185400bd0e48d63ebad97e98097340b2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:16:57 +0800 Subject: staging: rtl8192u: Use skcipher and ahash This patch replaces uses of blkcipher with skcipher, and the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Acked-by: Greg Kroah-Hartman --- .../rtl8192u/ieee80211/ieee80211_crypt_tkip.c | 92 ++++++++++++---------- .../rtl8192u/ieee80211/ieee80211_crypt_wep.c | 46 +++++++---- 2 files changed, 81 insertions(+), 57 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c index 908bc2eb4d29..6fa96d57d316 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c @@ -21,7 +21,8 @@ #include "ieee80211.h" -#include +#include +#include #include #include @@ -52,10 +53,10 @@ struct ieee80211_tkip_data { int key_idx; - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; + struct crypto_skcipher *rx_tfm_arc4; + struct crypto_ahash *rx_tfm_michael; + struct crypto_skcipher *tx_tfm_arc4; + struct crypto_ahash *tx_tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16], tx_hdr[16]; @@ -70,7 +71,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -79,7 +80,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; } - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + priv->tx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_michael)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -88,7 +89,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; } - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -97,7 +98,7 @@ static void *ieee80211_tkip_init(int key_idx) goto fail; } - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + priv->rx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_michael)) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " @@ -110,14 +111,10 @@ static void *ieee80211_tkip_init(int key_idx) fail: if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); + crypto_free_ahash(priv->tx_tfm_michael); + crypto_free_skcipher(priv->tx_tfm_arc4); + crypto_free_ahash(priv->rx_tfm_michael); + crypto_free_skcipher(priv->rx_tfm_arc4); kfree(priv); } @@ -130,14 +127,10 @@ static void ieee80211_tkip_deinit(void *priv) struct ieee80211_tkip_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); + crypto_free_ahash(_priv->tx_tfm_michael); + crypto_free_skcipher(_priv->tx_tfm_arc4); + crypto_free_ahash(_priv->rx_tfm_michael); + crypto_free_skcipher(_priv->rx_tfm_arc4); } kfree(priv); } @@ -312,7 +305,6 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 *pos; struct rtl_80211_hdr_4addr *hdr; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; int ret = 0; u8 rc4key[16], *icv; u32 crc; @@ -357,15 +349,21 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) *pos++ = (tkey->tx_iv32 >> 24) & 0xff; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4); + icv = skb_put(skb, 4); crc = ~crc32_le(~0, pos, len); icv[0] = crc; icv[1] = crc >> 8; icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); sg_init_one(&sg, pos, len+4); - ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + skcipher_request_set_tfm(req, tkey->tx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } tkey->tx_iv16++; @@ -390,12 +388,12 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u16 iv16; struct rtl_80211_hdr_4addr *hdr; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; u8 rc4key[16]; u8 icv[4]; u32 crc; struct scatterlist sg; int plen; + int err; if (skb->len < hdr_len + 8 + 4) return -1; @@ -429,6 +427,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) pos += 8; if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4); + if (iv32 < tkey->rx_iv32 || (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { if (net_ratelimit()) { @@ -449,10 +449,16 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); sg_init_one(&sg, pos, plen+4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + skcipher_request_set_tfm(req, tkey->rx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) { if (net_ratelimit()) { printk(KERN_DEBUG ": TKIP: failed to decrypt " "received packet from %pM\n", @@ -501,11 +507,12 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return keyidx; } -static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, +static int michael_mic(struct crypto_ahash *tfm_michael, u8 *key, u8 *hdr, u8 *data, size_t data_len, u8 *mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; + int err; if (tfm_michael == NULL) { printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); @@ -516,12 +523,15 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, sg_set_buf(&sg[0], hdr, 16); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, 8)) + if (crypto_ahash_setkey(tfm_michael, key, 8)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + 16); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) @@ -660,10 +670,10 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) { struct ieee80211_tkip_data *tkey = priv; int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; + struct crypto_ahash *tfm = tkey->tx_tfm_michael; + struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_ahash *tfm3 = tkey->rx_tfm_michael; + struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c index 681611dc93d3..ababb6de125b 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -18,7 +18,7 @@ #include "ieee80211.h" -#include +#include #include #include @@ -32,8 +32,8 @@ struct prism2_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; + struct crypto_skcipher *tx_tfm; + struct crypto_skcipher *rx_tfm; }; @@ -46,10 +46,10 @@ static void *prism2_wep_init(int keyidx) return NULL; priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) goto free_priv; - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) goto free_tx; @@ -58,7 +58,7 @@ static void *prism2_wep_init(int keyidx) return priv; free_tx: - crypto_free_blkcipher(priv->tx_tfm); + crypto_free_skcipher(priv->tx_tfm); free_priv: kfree(priv); return NULL; @@ -70,10 +70,8 @@ static void prism2_wep_deinit(void *priv) struct prism2_wep_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); + crypto_free_skcipher(_priv->tx_tfm); + crypto_free_skcipher(_priv->rx_tfm); } kfree(priv); } @@ -91,10 +89,10 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 key[WEP_KEY_LEN + 3]; u8 *pos; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; u32 crc; u8 *icv; struct scatterlist sg; + int err; if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || skb->len < hdr_len) @@ -129,6 +127,8 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) memcpy(key + 3, wep->key, wep->key_len); if (!tcb_desc->bHwSec) { + SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); + /* Append little-endian CRC32 and encrypt it to produce ICV */ crc = ~crc32_le(~0, pos, len); icv = skb_put(skb, 4); @@ -137,10 +137,16 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); + crypto_skcipher_setkey(wep->tx_tfm, key, klen); sg_init_one(&sg, pos, len+4); - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + skcipher_request_set_tfm(req, wep->tx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } return 0; @@ -161,10 +167,10 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 key[WEP_KEY_LEN + 3]; u8 keyidx, *pos; cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); - struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; u32 crc; u8 icv[4]; struct scatterlist sg; + int err; if (skb->len < hdr_len + 8) return -1; @@ -186,10 +192,18 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 8; if (!tcb_desc->bHwSec) { - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); + SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); + + crypto_skcipher_setkey(wep->rx_tfm, key, klen); sg_init_one(&sg, pos, plen+4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + skcipher_request_set_tfm(req, wep->rx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) return -7; crc = ~crc32_le(~0, pos, plen); -- cgit From ab1e6fa405b12e290083c4d0a694e82392dbbb66 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:17:07 +0800 Subject: wusb: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu --- drivers/usb/wusbcore/crypto.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/usb/wusbcore/crypto.c b/drivers/usb/wusbcore/crypto.c index 50ce80d604f3..8ed8e34c3492 100644 --- a/drivers/usb/wusbcore/crypto.c +++ b/drivers/usb/wusbcore/crypto.c @@ -45,6 +45,7 @@ * funneled through AES are...16 bytes in size! */ +#include #include #include #include @@ -195,21 +196,22 @@ static void bytewise_xor(void *_bo, const void *_bi1, const void *_bi2, * NOTE: blen is not aligned to a block size, we'll pad zeros, that's * what sg[4] is for. Maybe there is a smarter way to do this. */ -static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, +static int wusb_ccm_mac(struct crypto_skcipher *tfm_cbc, struct crypto_cipher *tfm_aes, void *mic, const struct aes_ccm_nonce *n, const struct aes_ccm_label *a, const void *b, size_t blen) { int result = 0; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, tfm_cbc); struct aes_ccm_b0 b0; struct aes_ccm_b1 b1; struct aes_ccm_a ax; struct scatterlist sg[4], sg_dst; - void *iv, *dst_buf; - size_t ivsize, dst_size; + void *dst_buf; + size_t dst_size; const u8 bzero[16] = { 0 }; + u8 iv[crypto_skcipher_ivsize(tfm_cbc)]; size_t zero_padding; /* @@ -232,9 +234,7 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, goto error_dst_buf; } - iv = crypto_blkcipher_crt(tfm_cbc)->iv; - ivsize = crypto_blkcipher_ivsize(tfm_cbc); - memset(iv, 0, ivsize); + memset(iv, 0, sizeof(iv)); /* Setup B0 */ b0.flags = 0x59; /* Format B0 */ @@ -259,9 +259,11 @@ static int wusb_ccm_mac(struct crypto_blkcipher *tfm_cbc, sg_set_buf(&sg[3], bzero, zero_padding); sg_init_one(&sg_dst, dst_buf, dst_size); - desc.tfm = tfm_cbc; - desc.flags = 0; - result = crypto_blkcipher_encrypt(&desc, &sg_dst, sg, dst_size); + skcipher_request_set_tfm(req, tfm_cbc); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, &sg_dst, dst_size, iv); + result = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); if (result < 0) { printk(KERN_ERR "E: can't compute CBC-MAC tag (MIC): %d\n", result); @@ -301,18 +303,18 @@ ssize_t wusb_prf(void *out, size_t out_size, { ssize_t result, bytes = 0, bitr; struct aes_ccm_nonce n = *_n; - struct crypto_blkcipher *tfm_cbc; + struct crypto_skcipher *tfm_cbc; struct crypto_cipher *tfm_aes; u64 sfn = 0; __le64 sfn_le; - tfm_cbc = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); + tfm_cbc = crypto_alloc_skcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_cbc)) { result = PTR_ERR(tfm_cbc); printk(KERN_ERR "E: can't load CBC(AES): %d\n", (int)result); goto error_alloc_cbc; } - result = crypto_blkcipher_setkey(tfm_cbc, key, 16); + result = crypto_skcipher_setkey(tfm_cbc, key, 16); if (result < 0) { printk(KERN_ERR "E: can't set CBC key: %d\n", (int)result); goto error_setkey_cbc; @@ -345,7 +347,7 @@ error_setkey_aes: crypto_free_cipher(tfm_aes); error_alloc_aes: error_setkey_cbc: - crypto_free_blkcipher(tfm_cbc); + crypto_free_skcipher(tfm_cbc); error_alloc_cbc: return result; } -- cgit From 9651ddbac81f9c2676a963ce836d2f02ba2fe9c0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:17:17 +0800 Subject: cifs: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu --- fs/cifs/cifsencrypt.c | 32 +++++++++++++++++++++----------- fs/cifs/smbencrypt.c | 26 +++++++++++++++++++------- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index afa09fce8151..d41165433260 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -33,6 +33,7 @@ #include #include #include +#include static int cifs_crypto_shash_md5_allocate(struct TCP_Server_Info *server) @@ -789,38 +790,46 @@ int calc_seckey(struct cifs_ses *ses) { int rc; - struct crypto_blkcipher *tfm_arc4; + struct crypto_skcipher *tfm_arc4; struct scatterlist sgin, sgout; - struct blkcipher_desc desc; + struct skcipher_request *req; unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */ get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE); - tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_arc4)) { rc = PTR_ERR(tfm_arc4); cifs_dbg(VFS, "could not allocate crypto API arc4\n"); return rc; } - desc.tfm = tfm_arc4; - - rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response, + rc = crypto_skcipher_setkey(tfm_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE); if (rc) { cifs_dbg(VFS, "%s: Could not set response as a key\n", __func__); - return rc; + goto out_free_cipher; + } + + req = skcipher_request_alloc(tfm_arc4, GFP_KERNEL); + if (!req) { + rc = -ENOMEM; + cifs_dbg(VFS, "could not allocate crypto API arc4 request\n"); + goto out_free_cipher; } sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); - rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, CIFS_CPHTXT_SIZE); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sgin, &sgout, CIFS_CPHTXT_SIZE, NULL); + + rc = crypto_skcipher_encrypt(req); + skcipher_request_free(req); if (rc) { cifs_dbg(VFS, "could not encrypt session key rc: %d\n", rc); - crypto_free_blkcipher(tfm_arc4); - return rc; + goto out_free_cipher; } /* make secondary_key/nonce as session key */ @@ -828,7 +837,8 @@ calc_seckey(struct cifs_ses *ses) /* and make len as that of session key only */ ses->auth_key.len = CIFS_SESS_KEY_SIZE; - crypto_free_blkcipher(tfm_arc4); +out_free_cipher: + crypto_free_skcipher(tfm_arc4); return rc; } diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index a4232ec4f2ba..699b7868108f 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -23,6 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -70,31 +71,42 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) { int rc; unsigned char key2[8]; - struct crypto_blkcipher *tfm_des; + struct crypto_skcipher *tfm_des; struct scatterlist sgin, sgout; - struct blkcipher_desc desc; + struct skcipher_request *req; str_to_key(key, key2); - tfm_des = crypto_alloc_blkcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); + tfm_des = crypto_alloc_skcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_des)) { rc = PTR_ERR(tfm_des); cifs_dbg(VFS, "could not allocate des crypto API\n"); goto smbhash_err; } - desc.tfm = tfm_des; + req = skcipher_request_alloc(tfm_des, GFP_KERNEL); + if (!req) { + rc = -ENOMEM; + cifs_dbg(VFS, "could not allocate des crypto API\n"); + goto smbhash_free_skcipher; + } - crypto_blkcipher_setkey(tfm_des, key2, 8); + crypto_skcipher_setkey(tfm_des, key2, 8); sg_init_one(&sgin, in, 8); sg_init_one(&sgout, out, 8); - rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sgin, &sgout, 8, NULL); + + rc = crypto_skcipher_encrypt(req); if (rc) cifs_dbg(VFS, "could not encrypt crypt key rc: %d\n", rc); - crypto_free_blkcipher(tfm_des); + skcipher_request_free(req); + +smbhash_free_skcipher: + crypto_free_skcipher(tfm_des); smbhash_err: return rc; } -- cgit From 3f32a5bee0c8b2d4f25138af21620ae164fdb0ff Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:17:38 +0800 Subject: ext4: Use skcipher This patch replaces uses of ablkcipher with skcipher. Signed-off-by: Herbert Xu --- fs/ext4/crypto.c | 24 +++++++++++------------- fs/ext4/crypto_fname.c | 32 +++++++++++++++----------------- fs/ext4/crypto_key.c | 42 ++++++++++++++++++++---------------------- fs/ext4/ext4_crypto.h | 2 +- 4 files changed, 47 insertions(+), 53 deletions(-) diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c index c8021208a7eb..845c22a5a744 100644 --- a/fs/ext4/crypto.c +++ b/fs/ext4/crypto.c @@ -18,11 +18,9 @@ * Special Publication 800-38E and IEEE P1619/D16. */ -#include -#include +#include #include #include -#include #include #include #include @@ -261,21 +259,21 @@ static int ext4_page_crypto(struct inode *inode, { u8 xts_tweak[EXT4_XTS_TWEAK_SIZE]; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_EXT4_COMPLETION_RESULT(ecr); struct scatterlist dst, src; struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { printk_ratelimited(KERN_ERR "%s: crypto_request_alloc() failed\n", __func__); return -ENOMEM; } - ablkcipher_request_set_callback( + skcipher_request_set_callback( req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, ext4_crypt_complete, &ecr); @@ -288,21 +286,21 @@ static int ext4_page_crypto(struct inode *inode, sg_set_page(&dst, dest_page, PAGE_CACHE_SIZE, 0); sg_init_table(&src, 1); sg_set_page(&src, src_page, PAGE_CACHE_SIZE, 0); - ablkcipher_request_set_crypt(req, &src, &dst, PAGE_CACHE_SIZE, - xts_tweak); + skcipher_request_set_crypt(req, &src, &dst, PAGE_CACHE_SIZE, + xts_tweak); if (rw == EXT4_DECRYPT) - res = crypto_ablkcipher_decrypt(req); + res = crypto_skcipher_decrypt(req); else - res = crypto_ablkcipher_encrypt(req); + res = crypto_skcipher_encrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { wait_for_completion(&ecr.completion); res = ecr.res; } - ablkcipher_request_free(req); + skcipher_request_free(req); if (res) { printk_ratelimited( KERN_ERR - "%s: crypto_ablkcipher_encrypt() returned %d\n", + "%s: crypto_skcipher_encrypt() returned %d\n", __func__, res); return res; } diff --git a/fs/ext4/crypto_fname.c b/fs/ext4/crypto_fname.c index 2fbef8a14760..1a2f360405db 100644 --- a/fs/ext4/crypto_fname.c +++ b/fs/ext4/crypto_fname.c @@ -11,11 +11,9 @@ * */ -#include -#include +#include #include #include -#include #include #include #include @@ -65,10 +63,10 @@ static int ext4_fname_encrypt(struct inode *inode, struct ext4_str *oname) { u32 ciphertext_len; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_EXT4_COMPLETION_RESULT(ecr); struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; char iv[EXT4_CRYPTO_BLOCK_SIZE]; struct scatterlist src_sg, dst_sg; @@ -95,14 +93,14 @@ static int ext4_fname_encrypt(struct inode *inode, } /* Allocate request */ - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { printk_ratelimited( KERN_ERR "%s: crypto_request_alloc() failed\n", __func__); kfree(alloc_buf); return -ENOMEM; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, ext4_dir_crypt_complete, &ecr); @@ -117,14 +115,14 @@ static int ext4_fname_encrypt(struct inode *inode, /* Create encryption request */ sg_init_one(&src_sg, workbuf, ciphertext_len); sg_init_one(&dst_sg, oname->name, ciphertext_len); - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); - res = crypto_ablkcipher_encrypt(req); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); + res = crypto_skcipher_encrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { wait_for_completion(&ecr.completion); res = ecr.res; } kfree(alloc_buf); - ablkcipher_request_free(req); + skcipher_request_free(req); if (res < 0) { printk_ratelimited( KERN_ERR "%s: Error (error code %d)\n", __func__, res); @@ -145,11 +143,11 @@ static int ext4_fname_decrypt(struct inode *inode, struct ext4_str *oname) { struct ext4_str tmp_in[2], tmp_out[1]; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_EXT4_COMPLETION_RESULT(ecr); struct scatterlist src_sg, dst_sg; struct ext4_crypt_info *ci = EXT4_I(inode)->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; char iv[EXT4_CRYPTO_BLOCK_SIZE]; unsigned lim = max_name_len(inode); @@ -162,13 +160,13 @@ static int ext4_fname_decrypt(struct inode *inode, tmp_out[0].name = oname->name; /* Allocate request */ - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { printk_ratelimited( KERN_ERR "%s: crypto_request_alloc() failed\n", __func__); return -ENOMEM; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, ext4_dir_crypt_complete, &ecr); @@ -178,13 +176,13 @@ static int ext4_fname_decrypt(struct inode *inode, /* Create encryption request */ sg_init_one(&src_sg, iname->name, iname->len); sg_init_one(&dst_sg, oname->name, oname->len); - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); - res = crypto_ablkcipher_decrypt(req); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); + res = crypto_skcipher_decrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { wait_for_completion(&ecr.completion); res = ecr.res; } - ablkcipher_request_free(req); + skcipher_request_free(req); if (res < 0) { printk_ratelimited( KERN_ERR "%s: Error in ext4_fname_encrypt (error code %d)\n", diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c index 9a16d1e75a49..0129d688d1f7 100644 --- a/fs/ext4/crypto_key.c +++ b/fs/ext4/crypto_key.c @@ -8,6 +8,7 @@ * Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015. */ +#include #include #include #include @@ -41,45 +42,42 @@ static int ext4_derive_key_aes(char deriving_key[EXT4_AES_128_ECB_KEY_SIZE], char derived_key[EXT4_AES_256_XTS_KEY_SIZE]) { int res = 0; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_EXT4_COMPLETION_RESULT(ecr); struct scatterlist src_sg, dst_sg; - struct crypto_ablkcipher *tfm = crypto_alloc_ablkcipher("ecb(aes)", 0, - 0); + struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); if (IS_ERR(tfm)) { res = PTR_ERR(tfm); tfm = NULL; goto out; } - crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { res = -ENOMEM; goto out; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, derive_crypt_complete, &ecr); - res = crypto_ablkcipher_setkey(tfm, deriving_key, - EXT4_AES_128_ECB_KEY_SIZE); + res = crypto_skcipher_setkey(tfm, deriving_key, + EXT4_AES_128_ECB_KEY_SIZE); if (res < 0) goto out; sg_init_one(&src_sg, source_key, EXT4_AES_256_XTS_KEY_SIZE); sg_init_one(&dst_sg, derived_key, EXT4_AES_256_XTS_KEY_SIZE); - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, - EXT4_AES_256_XTS_KEY_SIZE, NULL); - res = crypto_ablkcipher_encrypt(req); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, + EXT4_AES_256_XTS_KEY_SIZE, NULL); + res = crypto_skcipher_encrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { wait_for_completion(&ecr.completion); res = ecr.res; } out: - if (req) - ablkcipher_request_free(req); - if (tfm) - crypto_free_ablkcipher(tfm); + skcipher_request_free(req); + crypto_free_skcipher(tfm); return res; } @@ -90,7 +88,7 @@ void ext4_free_crypt_info(struct ext4_crypt_info *ci) if (ci->ci_keyring_key) key_put(ci->ci_keyring_key); - crypto_free_ablkcipher(ci->ci_ctfm); + crypto_free_skcipher(ci->ci_ctfm); kmem_cache_free(ext4_crypt_info_cachep, ci); } @@ -122,7 +120,7 @@ int _ext4_get_encryption_info(struct inode *inode) struct ext4_encryption_context ctx; const struct user_key_payload *ukp; struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); - struct crypto_ablkcipher *ctfm; + struct crypto_skcipher *ctfm; const char *cipher_str; char raw_key[EXT4_MAX_KEY_SIZE]; char mode; @@ -237,7 +235,7 @@ retry: if (res) goto out; got_key: - ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); + ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG @@ -246,11 +244,11 @@ got_key: goto out; } crypt_info->ci_ctfm = ctfm; - crypto_ablkcipher_clear_flags(ctfm, ~0); - crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), + crypto_skcipher_clear_flags(ctfm, ~0); + crypto_tfm_set_flags(crypto_skcipher_tfm(ctfm), CRYPTO_TFM_REQ_WEAK_KEY); - res = crypto_ablkcipher_setkey(ctfm, raw_key, - ext4_encryption_key_size(mode)); + res = crypto_skcipher_setkey(ctfm, raw_key, + ext4_encryption_key_size(mode)); if (res) goto out; memzero_explicit(raw_key, sizeof(raw_key)); diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h index ac7d4e813796..1f73c29717e1 100644 --- a/fs/ext4/ext4_crypto.h +++ b/fs/ext4/ext4_crypto.h @@ -77,7 +77,7 @@ struct ext4_crypt_info { char ci_data_mode; char ci_filename_mode; char ci_flags; - struct crypto_ablkcipher *ci_ctfm; + struct crypto_skcipher *ci_ctfm; struct key *ci_keyring_key; char ci_master_key[EXT4_KEY_DESCRIPTOR_SIZE]; }; -- cgit From 2731a944f6512b3a2684ebc1d78e2d59c18b06fc Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:17:49 +0800 Subject: f2fs: Use skcipher This patch replaces uses of ablkcipher with skcipher. Signed-off-by: Herbert Xu --- fs/f2fs/crypto.c | 24 +++++++++++------------- fs/f2fs/crypto_fname.c | 32 +++++++++++++++----------------- fs/f2fs/crypto_key.c | 40 ++++++++++++++++++---------------------- fs/f2fs/f2fs_crypto.h | 2 +- 4 files changed, 45 insertions(+), 53 deletions(-) diff --git a/fs/f2fs/crypto.c b/fs/f2fs/crypto.c index 4a62ef14e932..95c5cf039711 100644 --- a/fs/f2fs/crypto.c +++ b/fs/f2fs/crypto.c @@ -23,11 +23,9 @@ * The usage of AES-XTS should conform to recommendations in NIST * Special Publication 800-38E and IEEE P1619/D16. */ -#include -#include +#include #include #include -#include #include #include #include @@ -328,21 +326,21 @@ static int f2fs_page_crypto(struct f2fs_crypto_ctx *ctx, struct page *dest_page) { u8 xts_tweak[F2FS_XTS_TWEAK_SIZE]; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_F2FS_COMPLETION_RESULT(ecr); struct scatterlist dst, src; struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { printk_ratelimited(KERN_ERR "%s: crypto_request_alloc() failed\n", __func__); return -ENOMEM; } - ablkcipher_request_set_callback( + skcipher_request_set_callback( req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, f2fs_crypt_complete, &ecr); @@ -355,21 +353,21 @@ static int f2fs_page_crypto(struct f2fs_crypto_ctx *ctx, sg_set_page(&dst, dest_page, PAGE_CACHE_SIZE, 0); sg_init_table(&src, 1); sg_set_page(&src, src_page, PAGE_CACHE_SIZE, 0); - ablkcipher_request_set_crypt(req, &src, &dst, PAGE_CACHE_SIZE, - xts_tweak); + skcipher_request_set_crypt(req, &src, &dst, PAGE_CACHE_SIZE, + xts_tweak); if (rw == F2FS_DECRYPT) - res = crypto_ablkcipher_decrypt(req); + res = crypto_skcipher_decrypt(req); else - res = crypto_ablkcipher_encrypt(req); + res = crypto_skcipher_encrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { BUG_ON(req->base.data != &ecr); wait_for_completion(&ecr.completion); res = ecr.res; } - ablkcipher_request_free(req); + skcipher_request_free(req); if (res) { printk_ratelimited(KERN_ERR - "%s: crypto_ablkcipher_encrypt() returned %d\n", + "%s: crypto_skcipher_encrypt() returned %d\n", __func__, res); return res; } diff --git a/fs/f2fs/crypto_fname.c b/fs/f2fs/crypto_fname.c index ab377d496a39..16aec6653291 100644 --- a/fs/f2fs/crypto_fname.c +++ b/fs/f2fs/crypto_fname.c @@ -15,11 +15,9 @@ * * This has not yet undergone a rigorous security audit. */ -#include -#include +#include #include #include -#include #include #include #include @@ -70,10 +68,10 @@ static int f2fs_fname_encrypt(struct inode *inode, const struct qstr *iname, struct f2fs_str *oname) { u32 ciphertext_len; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_F2FS_COMPLETION_RESULT(ecr); struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; char iv[F2FS_CRYPTO_BLOCK_SIZE]; struct scatterlist src_sg, dst_sg; @@ -99,14 +97,14 @@ static int f2fs_fname_encrypt(struct inode *inode, } /* Allocate request */ - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { printk_ratelimited(KERN_ERR "%s: crypto_request_alloc() failed\n", __func__); kfree(alloc_buf); return -ENOMEM; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, f2fs_dir_crypt_complete, &ecr); @@ -121,15 +119,15 @@ static int f2fs_fname_encrypt(struct inode *inode, /* Create encryption request */ sg_init_one(&src_sg, workbuf, ciphertext_len); sg_init_one(&dst_sg, oname->name, ciphertext_len); - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); - res = crypto_ablkcipher_encrypt(req); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, ciphertext_len, iv); + res = crypto_skcipher_encrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { BUG_ON(req->base.data != &ecr); wait_for_completion(&ecr.completion); res = ecr.res; } kfree(alloc_buf); - ablkcipher_request_free(req); + skcipher_request_free(req); if (res < 0) { printk_ratelimited(KERN_ERR "%s: Error (error code %d)\n", __func__, res); @@ -148,11 +146,11 @@ static int f2fs_fname_encrypt(struct inode *inode, static int f2fs_fname_decrypt(struct inode *inode, const struct f2fs_str *iname, struct f2fs_str *oname) { - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_F2FS_COMPLETION_RESULT(ecr); struct scatterlist src_sg, dst_sg; struct f2fs_crypt_info *ci = F2FS_I(inode)->i_crypt_info; - struct crypto_ablkcipher *tfm = ci->ci_ctfm; + struct crypto_skcipher *tfm = ci->ci_ctfm; int res = 0; char iv[F2FS_CRYPTO_BLOCK_SIZE]; unsigned lim = max_name_len(inode); @@ -161,13 +159,13 @@ static int f2fs_fname_decrypt(struct inode *inode, return -EIO; /* Allocate request */ - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { printk_ratelimited(KERN_ERR "%s: crypto_request_alloc() failed\n", __func__); return -ENOMEM; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, f2fs_dir_crypt_complete, &ecr); @@ -177,14 +175,14 @@ static int f2fs_fname_decrypt(struct inode *inode, /* Create decryption request */ sg_init_one(&src_sg, iname->name, iname->len); sg_init_one(&dst_sg, oname->name, oname->len); - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); - res = crypto_ablkcipher_decrypt(req); + skcipher_request_set_crypt(req, &src_sg, &dst_sg, iname->len, iv); + res = crypto_skcipher_decrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { BUG_ON(req->base.data != &ecr); wait_for_completion(&ecr.completion); res = ecr.res; } - ablkcipher_request_free(req); + skcipher_request_free(req); if (res < 0) { printk_ratelimited(KERN_ERR "%s: Error in f2fs_fname_decrypt (error code %d)\n", diff --git a/fs/f2fs/crypto_key.c b/fs/f2fs/crypto_key.c index 5de2d866a25c..2aeb6273bd8f 100644 --- a/fs/f2fs/crypto_key.c +++ b/fs/f2fs/crypto_key.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include "f2fs.h" @@ -44,46 +44,43 @@ static int f2fs_derive_key_aes(char deriving_key[F2FS_AES_128_ECB_KEY_SIZE], char derived_key[F2FS_AES_256_XTS_KEY_SIZE]) { int res = 0; - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; DECLARE_F2FS_COMPLETION_RESULT(ecr); struct scatterlist src_sg, dst_sg; - struct crypto_ablkcipher *tfm = crypto_alloc_ablkcipher("ecb(aes)", 0, - 0); + struct crypto_skcipher *tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0); if (IS_ERR(tfm)) { res = PTR_ERR(tfm); tfm = NULL; goto out; } - crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); - req = ablkcipher_request_alloc(tfm, GFP_NOFS); + crypto_skcipher_set_flags(tfm, CRYPTO_TFM_REQ_WEAK_KEY); + req = skcipher_request_alloc(tfm, GFP_NOFS); if (!req) { res = -ENOMEM; goto out; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, derive_crypt_complete, &ecr); - res = crypto_ablkcipher_setkey(tfm, deriving_key, + res = crypto_skcipher_setkey(tfm, deriving_key, F2FS_AES_128_ECB_KEY_SIZE); if (res < 0) goto out; sg_init_one(&src_sg, source_key, F2FS_AES_256_XTS_KEY_SIZE); sg_init_one(&dst_sg, derived_key, F2FS_AES_256_XTS_KEY_SIZE); - ablkcipher_request_set_crypt(req, &src_sg, &dst_sg, + skcipher_request_set_crypt(req, &src_sg, &dst_sg, F2FS_AES_256_XTS_KEY_SIZE, NULL); - res = crypto_ablkcipher_encrypt(req); + res = crypto_skcipher_encrypt(req); if (res == -EINPROGRESS || res == -EBUSY) { BUG_ON(req->base.data != &ecr); wait_for_completion(&ecr.completion); res = ecr.res; } out: - if (req) - ablkcipher_request_free(req); - if (tfm) - crypto_free_ablkcipher(tfm); + skcipher_request_free(req); + crypto_free_skcipher(tfm); return res; } @@ -93,7 +90,7 @@ static void f2fs_free_crypt_info(struct f2fs_crypt_info *ci) return; key_put(ci->ci_keyring_key); - crypto_free_ablkcipher(ci->ci_ctfm); + crypto_free_skcipher(ci->ci_ctfm); kmem_cache_free(f2fs_crypt_info_cachep, ci); } @@ -123,7 +120,7 @@ int _f2fs_get_encryption_info(struct inode *inode) struct f2fs_encryption_key *master_key; struct f2fs_encryption_context ctx; const struct user_key_payload *ukp; - struct crypto_ablkcipher *ctfm; + struct crypto_skcipher *ctfm; const char *cipher_str; char raw_key[F2FS_MAX_KEY_SIZE]; char mode; @@ -213,7 +210,7 @@ retry: if (res) goto out; - ctfm = crypto_alloc_ablkcipher(cipher_str, 0, 0); + ctfm = crypto_alloc_skcipher(cipher_str, 0, 0); if (!ctfm || IS_ERR(ctfm)) { res = ctfm ? PTR_ERR(ctfm) : -ENOMEM; printk(KERN_DEBUG @@ -222,11 +219,10 @@ retry: goto out; } crypt_info->ci_ctfm = ctfm; - crypto_ablkcipher_clear_flags(ctfm, ~0); - crypto_tfm_set_flags(crypto_ablkcipher_tfm(ctfm), - CRYPTO_TFM_REQ_WEAK_KEY); - res = crypto_ablkcipher_setkey(ctfm, raw_key, - f2fs_encryption_key_size(mode)); + crypto_skcipher_clear_flags(ctfm, ~0); + crypto_skcipher_set_flags(ctfm, CRYPTO_TFM_REQ_WEAK_KEY); + res = crypto_skcipher_setkey(ctfm, raw_key, + f2fs_encryption_key_size(mode)); if (res) goto out; diff --git a/fs/f2fs/f2fs_crypto.h b/fs/f2fs/f2fs_crypto.h index c2c1c2b63b25..ea3d1d7c97f3 100644 --- a/fs/f2fs/f2fs_crypto.h +++ b/fs/f2fs/f2fs_crypto.h @@ -78,7 +78,7 @@ struct f2fs_crypt_info { char ci_data_mode; char ci_filename_mode; char ci_flags; - struct crypto_ablkcipher *ci_ctfm; + struct crypto_skcipher *ci_ctfm; struct key *ci_keyring_key; char ci_master_key[F2FS_KEY_DESCRIPTOR_SIZE]; }; -- cgit From 3b5cf20cf439c3e8963c2d2a3f225434d31827e3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:17:59 +0800 Subject: sunrpc: Use skcipher and ahash/shash This patch replaces uses of blkcipher with skcipher and the long obsolete hash interface with either shash (for non-SG users) and ahash. Signed-off-by: Herbert Xu --- include/linux/sunrpc/gss_krb5.h | 32 ++-- net/sunrpc/auth_gss/gss_krb5_crypto.c | 350 +++++++++++++++++++++------------- net/sunrpc/auth_gss/gss_krb5_keys.c | 12 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 89 ++++----- net/sunrpc/auth_gss/gss_krb5_seqnum.c | 22 +-- net/sunrpc/auth_gss/gss_krb5_wrap.c | 24 +-- 6 files changed, 306 insertions(+), 223 deletions(-) diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index df02a4188487..7df625d41e35 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -36,7 +36,7 @@ * */ -#include +#include #include #include #include @@ -71,10 +71,10 @@ struct gss_krb5_enctype { const u32 keyed_cksum; /* is it a keyed cksum? */ const u32 keybytes; /* raw key len, in bytes */ const u32 keylength; /* final key len, in bytes */ - u32 (*encrypt) (struct crypto_blkcipher *tfm, + u32 (*encrypt) (struct crypto_skcipher *tfm, void *iv, void *in, void *out, int length); /* encryption function */ - u32 (*decrypt) (struct crypto_blkcipher *tfm, + u32 (*decrypt) (struct crypto_skcipher *tfm, void *iv, void *in, void *out, int length); /* decryption function */ u32 (*mk_key) (const struct gss_krb5_enctype *gk5e, @@ -98,12 +98,12 @@ struct krb5_ctx { u32 enctype; u32 flags; const struct gss_krb5_enctype *gk5e; /* enctype-specific info */ - struct crypto_blkcipher *enc; - struct crypto_blkcipher *seq; - struct crypto_blkcipher *acceptor_enc; - struct crypto_blkcipher *initiator_enc; - struct crypto_blkcipher *acceptor_enc_aux; - struct crypto_blkcipher *initiator_enc_aux; + struct crypto_skcipher *enc; + struct crypto_skcipher *seq; + struct crypto_skcipher *acceptor_enc; + struct crypto_skcipher *initiator_enc; + struct crypto_skcipher *acceptor_enc_aux; + struct crypto_skcipher *initiator_enc_aux; u8 Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */ u8 cksum[GSS_KRB5_MAX_KEYLEN]; s32 endtime; @@ -262,24 +262,24 @@ gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, u32 -krb5_encrypt(struct crypto_blkcipher *key, +krb5_encrypt(struct crypto_skcipher *key, void *iv, void *in, void *out, int length); u32 -krb5_decrypt(struct crypto_blkcipher *key, +krb5_decrypt(struct crypto_skcipher *key, void *iv, void *in, void *out, int length); int -gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *outbuf, +gss_encrypt_xdr_buf(struct crypto_skcipher *tfm, struct xdr_buf *outbuf, int offset, struct page **pages); int -gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf, +gss_decrypt_xdr_buf(struct crypto_skcipher *tfm, struct xdr_buf *inbuf, int offset); s32 krb5_make_seq_num(struct krb5_ctx *kctx, - struct crypto_blkcipher *key, + struct crypto_skcipher *key, int direction, u32 seqnum, unsigned char *cksum, unsigned char *buf); @@ -320,12 +320,12 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, int krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, - struct crypto_blkcipher *cipher, + struct crypto_skcipher *cipher, unsigned char *cksum); int krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, - struct crypto_blkcipher *cipher, + struct crypto_skcipher *cipher, s32 seqnum); void gss_krb5_make_confounder(char *p, u32 conflen); diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index fee3c15a4b52..d94a8e1e9f05 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -34,11 +34,12 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +#include +#include #include #include #include #include -#include #include #include #include @@ -51,7 +52,7 @@ u32 krb5_encrypt( - struct crypto_blkcipher *tfm, + struct crypto_skcipher *tfm, void * iv, void * in, void * out, @@ -60,24 +61,28 @@ krb5_encrypt( u32 ret = -EINVAL; struct scatterlist sg[1]; u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0}; - struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; + SKCIPHER_REQUEST_ON_STACK(req, tfm); - if (length % crypto_blkcipher_blocksize(tfm) != 0) + if (length % crypto_skcipher_blocksize(tfm) != 0) goto out; - if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) { + if (crypto_skcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) { dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n", - crypto_blkcipher_ivsize(tfm)); + crypto_skcipher_ivsize(tfm)); goto out; } if (iv) - memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm)); + memcpy(local_iv, iv, crypto_skcipher_ivsize(tfm)); memcpy(out, in, length); sg_init_one(sg, out, length); - ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, length, local_iv); + + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); out: dprintk("RPC: krb5_encrypt returns %d\n", ret); return ret; @@ -85,7 +90,7 @@ out: u32 krb5_decrypt( - struct crypto_blkcipher *tfm, + struct crypto_skcipher *tfm, void * iv, void * in, void * out, @@ -94,23 +99,27 @@ krb5_decrypt( u32 ret = -EINVAL; struct scatterlist sg[1]; u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0}; - struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; + SKCIPHER_REQUEST_ON_STACK(req, tfm); - if (length % crypto_blkcipher_blocksize(tfm) != 0) + if (length % crypto_skcipher_blocksize(tfm) != 0) goto out; - if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) { + if (crypto_skcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) { dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n", - crypto_blkcipher_ivsize(tfm)); + crypto_skcipher_ivsize(tfm)); goto out; } if (iv) - memcpy(local_iv,iv, crypto_blkcipher_ivsize(tfm)); + memcpy(local_iv,iv, crypto_skcipher_ivsize(tfm)); memcpy(out, in, length); sg_init_one(sg, out, length); - ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, length, local_iv); + + ret = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); out: dprintk("RPC: gss_k5decrypt returns %d\n",ret); return ret; @@ -119,9 +128,11 @@ out: static int checksummer(struct scatterlist *sg, void *data) { - struct hash_desc *desc = data; + struct ahash_request *req = data; + + ahash_request_set_crypt(req, sg, NULL, sg->length); - return crypto_hash_update(desc, sg, sg->length); + return crypto_ahash_update(req); } static int @@ -152,13 +163,13 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, struct xdr_buf *body, int body_offset, u8 *cksumkey, unsigned int usage, struct xdr_netobj *cksumout) { - struct hash_desc desc; struct scatterlist sg[1]; int err; u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; u8 rc4salt[4]; - struct crypto_hash *md5; - struct crypto_hash *hmac_md5; + struct crypto_ahash *md5; + struct crypto_ahash *hmac_md5; + struct ahash_request *req; if (cksumkey == NULL) return GSS_S_FAILURE; @@ -174,61 +185,79 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen, return GSS_S_FAILURE; } - md5 = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(md5)) return GSS_S_FAILURE; - hmac_md5 = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, - CRYPTO_ALG_ASYNC); + hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(hmac_md5)) { - crypto_free_hash(md5); + crypto_free_ahash(md5); + return GSS_S_FAILURE; + } + + req = ahash_request_alloc(md5, GFP_KERNEL); + if (!req) { + crypto_free_ahash(hmac_md5); + crypto_free_ahash(md5); return GSS_S_FAILURE; } - desc.tfm = md5; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); - err = crypto_hash_init(&desc); + err = crypto_ahash_init(req); if (err) goto out; sg_init_one(sg, rc4salt, 4); - err = crypto_hash_update(&desc, sg, 4); + ahash_request_set_crypt(req, sg, NULL, 4); + err = crypto_ahash_update(req); if (err) goto out; sg_init_one(sg, header, hdrlen); - err = crypto_hash_update(&desc, sg, hdrlen); + ahash_request_set_crypt(req, sg, NULL, hdrlen); + err = crypto_ahash_update(req); if (err) goto out; err = xdr_process_buf(body, body_offset, body->len - body_offset, - checksummer, &desc); + checksummer, req); if (err) goto out; - err = crypto_hash_final(&desc, checksumdata); + ahash_request_set_crypt(req, NULL, checksumdata, 0); + err = crypto_ahash_final(req); if (err) goto out; - desc.tfm = hmac_md5; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + ahash_request_free(req); + req = ahash_request_alloc(hmac_md5, GFP_KERNEL); + if (!req) { + crypto_free_ahash(hmac_md5); + crypto_free_ahash(md5); + return GSS_S_FAILURE; + } + + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); - err = crypto_hash_init(&desc); + err = crypto_ahash_init(req); if (err) goto out; - err = crypto_hash_setkey(hmac_md5, cksumkey, kctx->gk5e->keylength); + err = crypto_ahash_setkey(hmac_md5, cksumkey, kctx->gk5e->keylength); if (err) goto out; - sg_init_one(sg, checksumdata, crypto_hash_digestsize(md5)); - err = crypto_hash_digest(&desc, sg, crypto_hash_digestsize(md5), - checksumdata); + sg_init_one(sg, checksumdata, crypto_ahash_digestsize(md5)); + ahash_request_set_crypt(req, sg, checksumdata, + crypto_ahash_digestsize(md5)); + err = crypto_ahash_digest(req); if (err) goto out; memcpy(cksumout->data, checksumdata, kctx->gk5e->cksumlength); cksumout->len = kctx->gk5e->cksumlength; out: - crypto_free_hash(md5); - crypto_free_hash(hmac_md5); + ahash_request_free(req); + crypto_free_ahash(md5); + crypto_free_ahash(hmac_md5); return err ? GSS_S_FAILURE : 0; } @@ -242,7 +271,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, struct xdr_buf *body, int body_offset, u8 *cksumkey, unsigned int usage, struct xdr_netobj *cksumout) { - struct hash_desc desc; + struct crypto_ahash *tfm; + struct ahash_request *req; struct scatterlist sg[1]; int err; u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; @@ -259,32 +289,41 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, return GSS_S_FAILURE; } - desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) + tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) return GSS_S_FAILURE; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - checksumlen = crypto_hash_digestsize(desc.tfm); + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + crypto_free_ahash(tfm); + return GSS_S_FAILURE; + } + + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); + + checksumlen = crypto_ahash_digestsize(tfm); if (cksumkey != NULL) { - err = crypto_hash_setkey(desc.tfm, cksumkey, - kctx->gk5e->keylength); + err = crypto_ahash_setkey(tfm, cksumkey, + kctx->gk5e->keylength); if (err) goto out; } - err = crypto_hash_init(&desc); + err = crypto_ahash_init(req); if (err) goto out; sg_init_one(sg, header, hdrlen); - err = crypto_hash_update(&desc, sg, hdrlen); + ahash_request_set_crypt(req, sg, NULL, hdrlen); + err = crypto_ahash_update(req); if (err) goto out; err = xdr_process_buf(body, body_offset, body->len - body_offset, - checksummer, &desc); + checksummer, req); if (err) goto out; - err = crypto_hash_final(&desc, checksumdata); + ahash_request_set_crypt(req, NULL, checksumdata, 0); + err = crypto_ahash_final(req); if (err) goto out; @@ -307,7 +346,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen, } cksumout->len = kctx->gk5e->cksumlength; out: - crypto_free_hash(desc.tfm); + ahash_request_free(req); + crypto_free_ahash(tfm); return err ? GSS_S_FAILURE : 0; } @@ -323,7 +363,8 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, struct xdr_buf *body, int body_offset, u8 *cksumkey, unsigned int usage, struct xdr_netobj *cksumout) { - struct hash_desc desc; + struct crypto_ahash *tfm; + struct ahash_request *req; struct scatterlist sg[1]; int err; u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; @@ -340,31 +381,39 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, return GSS_S_FAILURE; } - desc.tfm = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) + tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) return GSS_S_FAILURE; - checksumlen = crypto_hash_digestsize(desc.tfm); - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + checksumlen = crypto_ahash_digestsize(tfm); + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + crypto_free_ahash(tfm); + return GSS_S_FAILURE; + } - err = crypto_hash_setkey(desc.tfm, cksumkey, kctx->gk5e->keylength); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); + + err = crypto_ahash_setkey(tfm, cksumkey, kctx->gk5e->keylength); if (err) goto out; - err = crypto_hash_init(&desc); + err = crypto_ahash_init(req); if (err) goto out; err = xdr_process_buf(body, body_offset, body->len - body_offset, - checksummer, &desc); + checksummer, req); if (err) goto out; if (header != NULL) { sg_init_one(sg, header, hdrlen); - err = crypto_hash_update(&desc, sg, hdrlen); + ahash_request_set_crypt(req, sg, NULL, hdrlen); + err = crypto_ahash_update(req); if (err) goto out; } - err = crypto_hash_final(&desc, checksumdata); + ahash_request_set_crypt(req, NULL, checksumdata, 0); + err = crypto_ahash_final(req); if (err) goto out; @@ -381,13 +430,14 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen, break; } out: - crypto_free_hash(desc.tfm); + ahash_request_free(req); + crypto_free_ahash(tfm); return err ? GSS_S_FAILURE : 0; } struct encryptor_desc { u8 iv[GSS_KRB5_MAX_BLOCKSIZE]; - struct blkcipher_desc desc; + struct skcipher_request *req; int pos; struct xdr_buf *outbuf; struct page **pages; @@ -402,6 +452,7 @@ encryptor(struct scatterlist *sg, void *data) { struct encryptor_desc *desc = data; struct xdr_buf *outbuf = desc->outbuf; + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(desc->req); struct page *in_page; int thislen = desc->fraglen + sg->length; int fraglen, ret; @@ -427,7 +478,7 @@ encryptor(struct scatterlist *sg, void *data) desc->fraglen += sg->length; desc->pos += sg->length; - fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1); + fraglen = thislen & (crypto_skcipher_blocksize(tfm) - 1); thislen -= fraglen; if (thislen == 0) @@ -436,8 +487,10 @@ encryptor(struct scatterlist *sg, void *data) sg_mark_end(&desc->infrags[desc->fragno - 1]); sg_mark_end(&desc->outfrags[desc->fragno - 1]); - ret = crypto_blkcipher_encrypt_iv(&desc->desc, desc->outfrags, - desc->infrags, thislen); + skcipher_request_set_crypt(desc->req, desc->infrags, desc->outfrags, + thislen, desc->iv); + + ret = crypto_skcipher_encrypt(desc->req); if (ret) return ret; @@ -459,18 +512,20 @@ encryptor(struct scatterlist *sg, void *data) } int -gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, +gss_encrypt_xdr_buf(struct crypto_skcipher *tfm, struct xdr_buf *buf, int offset, struct page **pages) { int ret; struct encryptor_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, tfm); + + BUG_ON((buf->len - offset) % crypto_skcipher_blocksize(tfm) != 0); - BUG_ON((buf->len - offset) % crypto_blkcipher_blocksize(tfm) != 0); + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); memset(desc.iv, 0, sizeof(desc.iv)); - desc.desc.tfm = tfm; - desc.desc.info = desc.iv; - desc.desc.flags = 0; + desc.req = req; desc.pos = offset; desc.outbuf = buf; desc.pages = pages; @@ -481,12 +536,13 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, sg_init_table(desc.outfrags, 4); ret = xdr_process_buf(buf, offset, buf->len - offset, encryptor, &desc); + skcipher_request_zero(req); return ret; } struct decryptor_desc { u8 iv[GSS_KRB5_MAX_BLOCKSIZE]; - struct blkcipher_desc desc; + struct skcipher_request *req; struct scatterlist frags[4]; int fragno; int fraglen; @@ -497,6 +553,7 @@ decryptor(struct scatterlist *sg, void *data) { struct decryptor_desc *desc = data; int thislen = desc->fraglen + sg->length; + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(desc->req); int fraglen, ret; /* Worst case is 4 fragments: head, end of page 1, start @@ -507,7 +564,7 @@ decryptor(struct scatterlist *sg, void *data) desc->fragno++; desc->fraglen += sg->length; - fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1); + fraglen = thislen & (crypto_skcipher_blocksize(tfm) - 1); thislen -= fraglen; if (thislen == 0) @@ -515,8 +572,10 @@ decryptor(struct scatterlist *sg, void *data) sg_mark_end(&desc->frags[desc->fragno - 1]); - ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags, - desc->frags, thislen); + skcipher_request_set_crypt(desc->req, desc->frags, desc->frags, + thislen, desc->iv); + + ret = crypto_skcipher_decrypt(desc->req); if (ret) return ret; @@ -535,24 +594,29 @@ decryptor(struct scatterlist *sg, void *data) } int -gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, +gss_decrypt_xdr_buf(struct crypto_skcipher *tfm, struct xdr_buf *buf, int offset) { + int ret; struct decryptor_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, tfm); /* XXXJBF: */ - BUG_ON((buf->len - offset) % crypto_blkcipher_blocksize(tfm) != 0); + BUG_ON((buf->len - offset) % crypto_skcipher_blocksize(tfm) != 0); + + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); memset(desc.iv, 0, sizeof(desc.iv)); - desc.desc.tfm = tfm; - desc.desc.info = desc.iv; - desc.desc.flags = 0; + desc.req = req; desc.fragno = 0; desc.fraglen = 0; sg_init_table(desc.frags, 4); - return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); + ret = xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); + skcipher_request_zero(req); + return ret; } /* @@ -594,12 +658,12 @@ xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen) } static u32 -gss_krb5_cts_crypt(struct crypto_blkcipher *cipher, struct xdr_buf *buf, +gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf, u32 offset, u8 *iv, struct page **pages, int encrypt) { u32 ret; struct scatterlist sg[1]; - struct blkcipher_desc desc = { .tfm = cipher, .info = iv }; + SKCIPHER_REQUEST_ON_STACK(req, cipher); u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2]; struct page **save_pages; u32 len = buf->len - offset; @@ -625,10 +689,16 @@ gss_krb5_cts_crypt(struct crypto_blkcipher *cipher, struct xdr_buf *buf, sg_init_one(sg, data, len); + skcipher_request_set_tfm(req, cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, len, iv); + if (encrypt) - ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, len); + ret = crypto_skcipher_encrypt(req); else - ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, len); + ret = crypto_skcipher_decrypt(req); + + skcipher_request_zero(req); if (ret) goto out; @@ -647,7 +717,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_netobj hmac; u8 *cksumkey; u8 *ecptr; - struct crypto_blkcipher *cipher, *aux_cipher; + struct crypto_skcipher *cipher, *aux_cipher; int blocksize; struct page **save_pages; int nblocks, nbytes; @@ -666,7 +736,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, cksumkey = kctx->acceptor_integ; usage = KG_USAGE_ACCEPTOR_SEAL; } - blocksize = crypto_blkcipher_blocksize(cipher); + blocksize = crypto_skcipher_blocksize(cipher); /* hide the gss token header and insert the confounder */ offset += GSS_KRB5_TOK_HDR_LEN; @@ -719,20 +789,24 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, memset(desc.iv, 0, sizeof(desc.iv)); if (cbcbytes) { + SKCIPHER_REQUEST_ON_STACK(req, aux_cipher); + desc.pos = offset + GSS_KRB5_TOK_HDR_LEN; desc.fragno = 0; desc.fraglen = 0; desc.pages = pages; desc.outbuf = buf; - desc.desc.info = desc.iv; - desc.desc.flags = 0; - desc.desc.tfm = aux_cipher; + desc.req = req; + + skcipher_request_set_tfm(req, aux_cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); sg_init_table(desc.infrags, 4); sg_init_table(desc.outfrags, 4); err = xdr_process_buf(buf, offset + GSS_KRB5_TOK_HDR_LEN, cbcbytes, encryptor, &desc); + skcipher_request_zero(req); if (err) goto out_err; } @@ -763,7 +837,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, struct xdr_buf subbuf; u32 ret = 0; u8 *cksum_key; - struct crypto_blkcipher *cipher, *aux_cipher; + struct crypto_skcipher *cipher, *aux_cipher; struct xdr_netobj our_hmac_obj; u8 our_hmac[GSS_KRB5_MAX_CKSUM_LEN]; u8 pkt_hmac[GSS_KRB5_MAX_CKSUM_LEN]; @@ -782,7 +856,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, cksum_key = kctx->initiator_integ; usage = KG_USAGE_INITIATOR_SEAL; } - blocksize = crypto_blkcipher_blocksize(cipher); + blocksize = crypto_skcipher_blocksize(cipher); /* create a segment skipping the header and leaving out the checksum */ @@ -799,15 +873,19 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, memset(desc.iv, 0, sizeof(desc.iv)); if (cbcbytes) { + SKCIPHER_REQUEST_ON_STACK(req, aux_cipher); + desc.fragno = 0; desc.fraglen = 0; - desc.desc.info = desc.iv; - desc.desc.flags = 0; - desc.desc.tfm = aux_cipher; + desc.req = req; + + skcipher_request_set_tfm(req, aux_cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); sg_init_table(desc.frags, 4); ret = xdr_process_buf(&subbuf, 0, cbcbytes, decryptor, &desc); + skcipher_request_zero(req); if (ret) goto out_err; } @@ -850,61 +928,62 @@ out_err: * Set the key of the given cipher. */ int -krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher, +krb5_rc4_setup_seq_key(struct krb5_ctx *kctx, struct crypto_skcipher *cipher, unsigned char *cksum) { - struct crypto_hash *hmac; - struct hash_desc desc; - struct scatterlist sg[1]; + struct crypto_shash *hmac; + struct shash_desc *desc; u8 Kseq[GSS_KRB5_MAX_KEYLEN]; u32 zeroconstant = 0; int err; dprintk("%s: entered\n", __func__); - hmac = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); + hmac = crypto_alloc_shash(kctx->gk5e->cksum_name, 0, 0); if (IS_ERR(hmac)) { dprintk("%s: error %ld, allocating hash '%s'\n", __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); return PTR_ERR(hmac); } - desc.tfm = hmac; - desc.flags = 0; + desc = kmalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) { + dprintk("%s: failed to allocate shash descriptor for '%s'\n", + __func__, kctx->gk5e->cksum_name); + crypto_free_shash(hmac); + return -ENOMEM; + } - err = crypto_hash_init(&desc); - if (err) - goto out_err; + desc->tfm = hmac; + desc->flags = 0; /* Compute intermediate Kseq from session key */ - err = crypto_hash_setkey(hmac, kctx->Ksess, kctx->gk5e->keylength); + err = crypto_shash_setkey(hmac, kctx->Ksess, kctx->gk5e->keylength); if (err) goto out_err; - sg_init_one(sg, &zeroconstant, 4); - err = crypto_hash_digest(&desc, sg, 4, Kseq); + err = crypto_shash_digest(desc, (u8 *)&zeroconstant, 4, Kseq); if (err) goto out_err; /* Compute final Kseq from the checksum and intermediate Kseq */ - err = crypto_hash_setkey(hmac, Kseq, kctx->gk5e->keylength); + err = crypto_shash_setkey(hmac, Kseq, kctx->gk5e->keylength); if (err) goto out_err; - sg_set_buf(sg, cksum, 8); - - err = crypto_hash_digest(&desc, sg, 8, Kseq); + err = crypto_shash_digest(desc, cksum, 8, Kseq); if (err) goto out_err; - err = crypto_blkcipher_setkey(cipher, Kseq, kctx->gk5e->keylength); + err = crypto_skcipher_setkey(cipher, Kseq, kctx->gk5e->keylength); if (err) goto out_err; err = 0; out_err: - crypto_free_hash(hmac); + kzfree(desc); + crypto_free_shash(hmac); dprintk("%s: returning %d\n", __func__, err); return err; } @@ -914,12 +993,11 @@ out_err: * Set the key of cipher kctx->enc. */ int -krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher, +krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, struct crypto_skcipher *cipher, s32 seqnum) { - struct crypto_hash *hmac; - struct hash_desc desc; - struct scatterlist sg[1]; + struct crypto_shash *hmac; + struct shash_desc *desc; u8 Kcrypt[GSS_KRB5_MAX_KEYLEN]; u8 zeroconstant[4] = {0}; u8 seqnumarray[4]; @@ -927,35 +1005,38 @@ krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher, dprintk("%s: entered, seqnum %u\n", __func__, seqnum); - hmac = crypto_alloc_hash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); + hmac = crypto_alloc_shash(kctx->gk5e->cksum_name, 0, 0); if (IS_ERR(hmac)) { dprintk("%s: error %ld, allocating hash '%s'\n", __func__, PTR_ERR(hmac), kctx->gk5e->cksum_name); return PTR_ERR(hmac); } - desc.tfm = hmac; - desc.flags = 0; + desc = kmalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) { + dprintk("%s: failed to allocate shash descriptor for '%s'\n", + __func__, kctx->gk5e->cksum_name); + crypto_free_shash(hmac); + return -ENOMEM; + } - err = crypto_hash_init(&desc); - if (err) - goto out_err; + desc->tfm = hmac; + desc->flags = 0; /* Compute intermediate Kcrypt from session key */ for (i = 0; i < kctx->gk5e->keylength; i++) Kcrypt[i] = kctx->Ksess[i] ^ 0xf0; - err = crypto_hash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); + err = crypto_shash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); if (err) goto out_err; - sg_init_one(sg, zeroconstant, 4); - err = crypto_hash_digest(&desc, sg, 4, Kcrypt); + err = crypto_shash_digest(desc, zeroconstant, 4, Kcrypt); if (err) goto out_err; /* Compute final Kcrypt from the seqnum and intermediate Kcrypt */ - err = crypto_hash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); + err = crypto_shash_setkey(hmac, Kcrypt, kctx->gk5e->keylength); if (err) goto out_err; @@ -964,20 +1045,19 @@ krb5_rc4_setup_enc_key(struct krb5_ctx *kctx, struct crypto_blkcipher *cipher, seqnumarray[2] = (unsigned char) ((seqnum >> 8) & 0xff); seqnumarray[3] = (unsigned char) ((seqnum >> 0) & 0xff); - sg_set_buf(sg, seqnumarray, 4); - - err = crypto_hash_digest(&desc, sg, 4, Kcrypt); + err = crypto_shash_digest(desc, seqnumarray, 4, Kcrypt); if (err) goto out_err; - err = crypto_blkcipher_setkey(cipher, Kcrypt, kctx->gk5e->keylength); + err = crypto_skcipher_setkey(cipher, Kcrypt, kctx->gk5e->keylength); if (err) goto out_err; err = 0; out_err: - crypto_free_hash(hmac); + kzfree(desc); + crypto_free_shash(hmac); dprintk("%s: returning %d\n", __func__, err); return err; } diff --git a/net/sunrpc/auth_gss/gss_krb5_keys.c b/net/sunrpc/auth_gss/gss_krb5_keys.c index 234fa8d0fd9b..870133146026 100644 --- a/net/sunrpc/auth_gss/gss_krb5_keys.c +++ b/net/sunrpc/auth_gss/gss_krb5_keys.c @@ -54,9 +54,9 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +#include #include #include -#include #include #include #include @@ -147,7 +147,7 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, size_t blocksize, keybytes, keylength, n; unsigned char *inblockdata, *outblockdata, *rawkey; struct xdr_netobj inblock, outblock; - struct crypto_blkcipher *cipher; + struct crypto_skcipher *cipher; u32 ret = EINVAL; blocksize = gk5e->blocksize; @@ -157,11 +157,11 @@ u32 krb5_derive_key(const struct gss_krb5_enctype *gk5e, if ((inkey->len != keylength) || (outkey->len != keylength)) goto err_return; - cipher = crypto_alloc_blkcipher(gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + cipher = crypto_alloc_skcipher(gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) goto err_return; - if (crypto_blkcipher_setkey(cipher, inkey->data, inkey->len)) + if (crypto_skcipher_setkey(cipher, inkey->data, inkey->len)) goto err_return; /* allocate and set up buffers */ @@ -238,7 +238,7 @@ err_free_in: memset(inblockdata, 0, blocksize); kfree(inblockdata); err_free_cipher: - crypto_free_blkcipher(cipher); + crypto_free_skcipher(cipher); err_return: return ret; } diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 28db442a0034..71341ccb9890 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -34,6 +34,8 @@ * */ +#include +#include #include #include #include @@ -42,7 +44,6 @@ #include #include #include -#include #include #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) @@ -217,7 +218,7 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) static inline const void * get_key(const void *p, const void *end, - struct krb5_ctx *ctx, struct crypto_blkcipher **res) + struct krb5_ctx *ctx, struct crypto_skcipher **res) { struct xdr_netobj key; int alg; @@ -245,7 +246,7 @@ get_key(const void *p, const void *end, if (IS_ERR(p)) goto out_err; - *res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0, + *res = crypto_alloc_skcipher(ctx->gk5e->encrypt_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(*res)) { printk(KERN_WARNING "gss_kerberos_mech: unable to initialize " @@ -253,7 +254,7 @@ get_key(const void *p, const void *end, *res = NULL; goto out_err_free_key; } - if (crypto_blkcipher_setkey(*res, key.data, key.len)) { + if (crypto_skcipher_setkey(*res, key.data, key.len)) { printk(KERN_WARNING "gss_kerberos_mech: error setting key for " "crypto algorithm %s\n", ctx->gk5e->encrypt_name); goto out_err_free_tfm; @@ -263,7 +264,7 @@ get_key(const void *p, const void *end, return p; out_err_free_tfm: - crypto_free_blkcipher(*res); + crypto_free_skcipher(*res); out_err_free_key: kfree(key.data); p = ERR_PTR(-EINVAL); @@ -335,30 +336,30 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) return 0; out_err_free_key2: - crypto_free_blkcipher(ctx->seq); + crypto_free_skcipher(ctx->seq); out_err_free_key1: - crypto_free_blkcipher(ctx->enc); + crypto_free_skcipher(ctx->enc); out_err_free_mech: kfree(ctx->mech_used.data); out_err: return PTR_ERR(p); } -static struct crypto_blkcipher * +static struct crypto_skcipher * context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) { - struct crypto_blkcipher *cp; + struct crypto_skcipher *cp; - cp = crypto_alloc_blkcipher(cname, 0, CRYPTO_ALG_ASYNC); + cp = crypto_alloc_skcipher(cname, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(cp)) { dprintk("gss_kerberos_mech: unable to initialize " "crypto algorithm %s\n", cname); return NULL; } - if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) { + if (crypto_skcipher_setkey(cp, key, ctx->gk5e->keylength)) { dprintk("gss_kerberos_mech: error setting key for " "crypto algorithm %s\n", cname); - crypto_free_blkcipher(cp); + crypto_free_skcipher(cp); return NULL; } return cp; @@ -412,9 +413,9 @@ context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask) return 0; out_free_enc: - crypto_free_blkcipher(ctx->enc); + crypto_free_skcipher(ctx->enc); out_free_seq: - crypto_free_blkcipher(ctx->seq); + crypto_free_skcipher(ctx->seq); out_err: return -EINVAL; } @@ -427,18 +428,17 @@ out_err: static int context_derive_keys_rc4(struct krb5_ctx *ctx) { - struct crypto_hash *hmac; + struct crypto_shash *hmac; char sigkeyconstant[] = "signaturekey"; int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ - struct hash_desc desc; - struct scatterlist sg[1]; + struct shash_desc *desc; int err; dprintk("RPC: %s: entered\n", __func__); /* * derive cksum (aka Ksign) key */ - hmac = crypto_alloc_hash(ctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC); + hmac = crypto_alloc_shash(ctx->gk5e->cksum_name, 0, 0); if (IS_ERR(hmac)) { dprintk("%s: error %ld allocating hash '%s'\n", __func__, PTR_ERR(hmac), ctx->gk5e->cksum_name); @@ -446,37 +446,40 @@ context_derive_keys_rc4(struct krb5_ctx *ctx) goto out_err; } - err = crypto_hash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength); + err = crypto_shash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength); if (err) goto out_err_free_hmac; - sg_init_table(sg, 1); - sg_set_buf(sg, sigkeyconstant, slen); - desc.tfm = hmac; - desc.flags = 0; - - err = crypto_hash_init(&desc); - if (err) + desc = kmalloc(sizeof(*desc), GFP_KERNEL); + if (!desc) { + dprintk("%s: failed to allocate hash descriptor for '%s'\n", + __func__, ctx->gk5e->cksum_name); + err = -ENOMEM; goto out_err_free_hmac; + } + + desc->tfm = hmac; + desc->flags = 0; - err = crypto_hash_digest(&desc, sg, slen, ctx->cksum); + err = crypto_shash_digest(desc, sigkeyconstant, slen, ctx->cksum); + kzfree(desc); if (err) goto out_err_free_hmac; /* - * allocate hash, and blkciphers for data and seqnum encryption + * allocate hash, and skciphers for data and seqnum encryption */ - ctx->enc = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + ctx->enc = crypto_alloc_skcipher(ctx->gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(ctx->enc)) { err = PTR_ERR(ctx->enc); goto out_err_free_hmac; } - ctx->seq = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + ctx->seq = crypto_alloc_skcipher(ctx->gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(ctx->seq)) { - crypto_free_blkcipher(ctx->enc); + crypto_free_skcipher(ctx->enc); err = PTR_ERR(ctx->seq); goto out_err_free_hmac; } @@ -486,7 +489,7 @@ context_derive_keys_rc4(struct krb5_ctx *ctx) err = 0; out_err_free_hmac: - crypto_free_hash(hmac); + crypto_free_shash(hmac); out_err: dprintk("RPC: %s: returning %d\n", __func__, err); return err; @@ -588,7 +591,7 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) context_v2_alloc_cipher(ctx, "cbc(aes)", ctx->acceptor_seal); if (ctx->acceptor_enc_aux == NULL) { - crypto_free_blkcipher(ctx->initiator_enc_aux); + crypto_free_skcipher(ctx->initiator_enc_aux); goto out_free_acceptor_enc; } } @@ -596,9 +599,9 @@ context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask) return 0; out_free_acceptor_enc: - crypto_free_blkcipher(ctx->acceptor_enc); + crypto_free_skcipher(ctx->acceptor_enc); out_free_initiator_enc: - crypto_free_blkcipher(ctx->initiator_enc); + crypto_free_skcipher(ctx->initiator_enc); out_err: return -EINVAL; } @@ -710,12 +713,12 @@ static void gss_delete_sec_context_kerberos(void *internal_ctx) { struct krb5_ctx *kctx = internal_ctx; - crypto_free_blkcipher(kctx->seq); - crypto_free_blkcipher(kctx->enc); - crypto_free_blkcipher(kctx->acceptor_enc); - crypto_free_blkcipher(kctx->initiator_enc); - crypto_free_blkcipher(kctx->acceptor_enc_aux); - crypto_free_blkcipher(kctx->initiator_enc_aux); + crypto_free_skcipher(kctx->seq); + crypto_free_skcipher(kctx->enc); + crypto_free_skcipher(kctx->acceptor_enc); + crypto_free_skcipher(kctx->initiator_enc); + crypto_free_skcipher(kctx->acceptor_enc_aux); + crypto_free_skcipher(kctx->initiator_enc_aux); kfree(kctx->mech_used.data); kfree(kctx); } diff --git a/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/net/sunrpc/auth_gss/gss_krb5_seqnum.c index 20d55c793eb6..c8b9082f4a9d 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seqnum.c +++ b/net/sunrpc/auth_gss/gss_krb5_seqnum.c @@ -31,9 +31,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include -#include #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH @@ -43,13 +43,13 @@ static s32 krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum, unsigned char *cksum, unsigned char *buf) { - struct crypto_blkcipher *cipher; + struct crypto_skcipher *cipher; unsigned char plain[8]; s32 code; dprintk("RPC: %s:\n", __func__); - cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + cipher = crypto_alloc_skcipher(kctx->gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) return PTR_ERR(cipher); @@ -68,12 +68,12 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum, code = krb5_encrypt(cipher, cksum, plain, buf, 8); out: - crypto_free_blkcipher(cipher); + crypto_free_skcipher(cipher); return code; } s32 krb5_make_seq_num(struct krb5_ctx *kctx, - struct crypto_blkcipher *key, + struct crypto_skcipher *key, int direction, u32 seqnum, unsigned char *cksum, unsigned char *buf) @@ -101,13 +101,13 @@ static s32 krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, unsigned char *buf, int *direction, s32 *seqnum) { - struct crypto_blkcipher *cipher; + struct crypto_skcipher *cipher; unsigned char plain[8]; s32 code; dprintk("RPC: %s:\n", __func__); - cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + cipher = crypto_alloc_skcipher(kctx->gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) return PTR_ERR(cipher); @@ -130,7 +130,7 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum, *seqnum = ((plain[0] << 24) | (plain[1] << 16) | (plain[2] << 8) | (plain[3])); out: - crypto_free_blkcipher(cipher); + crypto_free_skcipher(cipher); return code; } @@ -142,7 +142,7 @@ krb5_get_seq_num(struct krb5_ctx *kctx, { s32 code; unsigned char plain[8]; - struct crypto_blkcipher *key = kctx->seq; + struct crypto_skcipher *key = kctx->seq; dprintk("RPC: krb5_get_seq_num:\n"); diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index ca7e92a32f84..765088e4ad84 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -28,12 +28,12 @@ * SUCH DAMAGES. */ +#include #include #include #include #include #include -#include #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH @@ -174,7 +174,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, now = get_seconds(); - blocksize = crypto_blkcipher_blocksize(kctx->enc); + blocksize = crypto_skcipher_blocksize(kctx->enc); gss_krb5_add_padding(buf, offset, blocksize); BUG_ON((buf->len - offset) % blocksize); plainlen = conflen + buf->len - offset; @@ -239,10 +239,10 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, return GSS_S_FAILURE; if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { - struct crypto_blkcipher *cipher; + struct crypto_skcipher *cipher; int err; - cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + cipher = crypto_alloc_skcipher(kctx->gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) return GSS_S_FAILURE; @@ -250,7 +250,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, err = gss_encrypt_xdr_buf(cipher, buf, offset + headlen - conflen, pages); - crypto_free_blkcipher(cipher); + crypto_free_skcipher(cipher); if (err) return GSS_S_FAILURE; } else { @@ -327,18 +327,18 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) return GSS_S_BAD_SIG; if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) { - struct crypto_blkcipher *cipher; + struct crypto_skcipher *cipher; int err; - cipher = crypto_alloc_blkcipher(kctx->gk5e->encrypt_name, 0, - CRYPTO_ALG_ASYNC); + cipher = crypto_alloc_skcipher(kctx->gk5e->encrypt_name, 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) return GSS_S_FAILURE; krb5_rc4_setup_enc_key(kctx, cipher, seqnum); err = gss_decrypt_xdr_buf(cipher, buf, crypt_offset); - crypto_free_blkcipher(cipher); + crypto_free_skcipher(cipher); if (err) return GSS_S_DEFECTIVE_TOKEN; } else { @@ -371,7 +371,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) /* Copy the data back to the right position. XXX: Would probably be * better to copy and encrypt at the same time. */ - blocksize = crypto_blkcipher_blocksize(kctx->enc); + blocksize = crypto_skcipher_blocksize(kctx->enc); data_start = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) + conflen; orig_start = buf->head[0].iov_base + offset; @@ -473,7 +473,7 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, *ptr++ = 0xff; be16ptr = (__be16 *)ptr; - blocksize = crypto_blkcipher_blocksize(kctx->acceptor_enc); + blocksize = crypto_skcipher_blocksize(kctx->acceptor_enc); *be16ptr++ = 0; /* "inner" token header always uses 0 for RRC */ *be16ptr++ = 0; -- cgit From 608fb34cff8b11ebe9e4a951e92fad500cab4fe8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:18:09 +0800 Subject: lib80211: Use skcipher and ahash This patch replaces uses of blkcipher with skcipher and the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu --- net/wireless/lib80211_crypt_tkip.c | 99 +++++++++++++++++++++----------------- net/wireless/lib80211_crypt_wep.c | 46 ++++++++++-------- 2 files changed, 81 insertions(+), 64 deletions(-) diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 3cd819539241..71447cf86306 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c @@ -29,7 +29,8 @@ #include #include -#include +#include +#include #include #include @@ -63,10 +64,10 @@ struct lib80211_tkip_data { int key_idx; - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; + struct crypto_skcipher *rx_tfm_arc4; + struct crypto_ahash *rx_tfm_michael; + struct crypto_skcipher *tx_tfm_arc4; + struct crypto_ahash *tx_tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16], tx_hdr[16]; @@ -98,29 +99,29 @@ static void *lib80211_tkip_init(int key_idx) priv->key_idx = key_idx; - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { priv->tx_tfm_arc4 = NULL; goto fail; } - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); + priv->tx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_michael)) { priv->tx_tfm_michael = NULL; goto fail; } - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); + priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { priv->rx_tfm_arc4 = NULL; goto fail; } - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); + priv->rx_tfm_michael = crypto_alloc_ahash("michael_mic", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_michael)) { priv->rx_tfm_michael = NULL; goto fail; @@ -130,14 +131,10 @@ static void *lib80211_tkip_init(int key_idx) fail: if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); + crypto_free_ahash(priv->tx_tfm_michael); + crypto_free_skcipher(priv->tx_tfm_arc4); + crypto_free_ahash(priv->rx_tfm_michael); + crypto_free_skcipher(priv->rx_tfm_arc4); kfree(priv); } @@ -148,14 +145,10 @@ static void lib80211_tkip_deinit(void *priv) { struct lib80211_tkip_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); + crypto_free_ahash(_priv->tx_tfm_michael); + crypto_free_skcipher(_priv->tx_tfm_arc4); + crypto_free_ahash(_priv->rx_tfm_michael); + crypto_free_skcipher(_priv->rx_tfm_arc4); } kfree(priv); } @@ -353,11 +346,12 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = { .tfm = tkey->tx_tfm_arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, tkey->tx_tfm_arc4); int len; u8 rc4key[16], *pos, *icv; u32 crc; struct scatterlist sg; + int err; if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -382,9 +376,14 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); sg_init_one(&sg, pos, len + 4); - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + skcipher_request_set_tfm(req, tkey->tx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } /* @@ -403,7 +402,7 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 }; + SKCIPHER_REQUEST_ON_STACK(req, tkey->rx_tfm_arc4); u8 rc4key[16]; u8 keyidx, *pos; u32 iv32; @@ -413,6 +412,7 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u32 crc; struct scatterlist sg; int plen; + int err; hdr = (struct ieee80211_hdr *)skb->data; @@ -465,9 +465,14 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); sg_init_one(&sg, pos, plen + 4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + skcipher_request_set_tfm(req, tkey->rx_tfm_arc4); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) { net_dbg_ratelimited("TKIP: failed to decrypt received packet from %pM\n", hdr->addr2); return -7; @@ -505,11 +510,12 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) return keyidx; } -static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, +static int michael_mic(struct crypto_ahash *tfm_michael, u8 * key, u8 * hdr, u8 * data, size_t data_len, u8 * mic) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm_michael); struct scatterlist sg[2]; + int err; if (tfm_michael == NULL) { pr_warn("%s(): tfm_michael == NULL\n", __func__); @@ -519,12 +525,15 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, sg_set_buf(&sg[0], hdr, 16); sg_set_buf(&sg[1], data, data_len); - if (crypto_hash_setkey(tfm_michael, key, 8)) + if (crypto_ahash_setkey(tfm_michael, key, 8)) return -1; - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + ahash_request_set_tfm(req, tfm_michael); + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, mic, data_len + 16); + err = crypto_ahash_digest(req); + ahash_request_zero(req); + return err; } static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) @@ -645,10 +654,10 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) { struct lib80211_tkip_data *tkey = priv; int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; + struct crypto_ahash *tfm = tkey->tx_tfm_michael; + struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_ahash *tfm3 = tkey->rx_tfm_michael; + struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c index 1c292e4ea7b6..d05f58b0fd04 100644 --- a/net/wireless/lib80211_crypt_wep.c +++ b/net/wireless/lib80211_crypt_wep.c @@ -22,7 +22,7 @@ #include -#include +#include #include MODULE_AUTHOR("Jouni Malinen"); @@ -35,8 +35,8 @@ struct lib80211_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; + struct crypto_skcipher *tx_tfm; + struct crypto_skcipher *rx_tfm; }; static void *lib80211_wep_init(int keyidx) @@ -48,13 +48,13 @@ static void *lib80211_wep_init(int keyidx) goto fail; priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm)) { priv->tx_tfm = NULL; goto fail; } - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + priv->rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm)) { priv->rx_tfm = NULL; goto fail; @@ -66,10 +66,8 @@ static void *lib80211_wep_init(int keyidx) fail: if (priv) { - if (priv->tx_tfm) - crypto_free_blkcipher(priv->tx_tfm); - if (priv->rx_tfm) - crypto_free_blkcipher(priv->rx_tfm); + crypto_free_skcipher(priv->tx_tfm); + crypto_free_skcipher(priv->rx_tfm); kfree(priv); } return NULL; @@ -79,10 +77,8 @@ static void lib80211_wep_deinit(void *priv) { struct lib80211_wep_data *_priv = priv; if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); + crypto_free_skcipher(_priv->tx_tfm); + crypto_free_skcipher(_priv->rx_tfm); } kfree(priv); } @@ -133,11 +129,12 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->tx_tfm }; + SKCIPHER_REQUEST_ON_STACK(req, wep->tx_tfm); u32 crc, klen, len; u8 *pos, *icv; struct scatterlist sg; u8 key[WEP_KEY_LEN + 3]; + int err; /* other checks are in lib80211_wep_build_iv */ if (skb_tailroom(skb) < 4) @@ -165,9 +162,14 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); + crypto_skcipher_setkey(wep->tx_tfm, key, klen); sg_init_one(&sg, pos, len + 4); - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + skcipher_request_set_tfm(req, wep->tx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, len + 4, NULL); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } /* Perform WEP decryption on given buffer. Buffer includes whole WEP part of @@ -180,11 +182,12 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->rx_tfm }; + SKCIPHER_REQUEST_ON_STACK(req, wep->rx_tfm); u32 crc, klen, plen; u8 key[WEP_KEY_LEN + 3]; u8 keyidx, *pos, icv[4]; struct scatterlist sg; + int err; if (skb->len < hdr_len + 8) return -1; @@ -205,9 +208,14 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) /* Apply RC4 to data and compute CRC32 over decrypted data */ plen = skb->len - hdr_len - 8; - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); + crypto_skcipher_setkey(wep->rx_tfm, key, klen); sg_init_one(&sg, pos, plen + 4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + skcipher_request_set_tfm(req, wep->rx_tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, plen + 4, NULL); + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + if (err) return -7; crc = ~crc32_le(~0, pos, plen); -- cgit From c3917fd9dfbc8e5e4ca145398d7dc13e42a2d52f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:18:19 +0800 Subject: KEYS: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu --- security/keys/encrypted-keys/encrypted.c | 82 +++++++++++++++++++------------- 1 file changed, 50 insertions(+), 32 deletions(-) diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 696ccfa08d10..5adbfc32242f 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c @@ -28,11 +28,10 @@ #include #include #include -#include #include #include #include -#include +#include #include "encrypted.h" #include "ecryptfs_format.h" @@ -85,17 +84,17 @@ static const match_table_t key_tokens = { static int aes_get_sizes(void) { - struct crypto_blkcipher *tfm; + struct crypto_skcipher *tfm; - tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_skcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { pr_err("encrypted_key: failed to alloc_cipher (%ld)\n", PTR_ERR(tfm)); return PTR_ERR(tfm); } - ivsize = crypto_blkcipher_ivsize(tfm); - blksize = crypto_blkcipher_blocksize(tfm); - crypto_free_blkcipher(tfm); + ivsize = crypto_skcipher_ivsize(tfm); + blksize = crypto_skcipher_blocksize(tfm); + crypto_free_skcipher(tfm); return 0; } @@ -401,28 +400,37 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, return ret; } -static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key, - unsigned int key_len, const u8 *iv, - unsigned int ivsize) +static struct skcipher_request *init_skcipher_req(const u8 *key, + unsigned int key_len) { + struct skcipher_request *req; + struct crypto_skcipher *tfm; int ret; - desc->tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc->tfm)) { + tfm = crypto_alloc_skcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { pr_err("encrypted_key: failed to load %s transform (%ld)\n", - blkcipher_alg, PTR_ERR(desc->tfm)); - return PTR_ERR(desc->tfm); + blkcipher_alg, PTR_ERR(tfm)); + return ERR_CAST(tfm); } - desc->flags = 0; - ret = crypto_blkcipher_setkey(desc->tfm, key, key_len); + ret = crypto_skcipher_setkey(tfm, key, key_len); if (ret < 0) { pr_err("encrypted_key: failed to setkey (%d)\n", ret); - crypto_free_blkcipher(desc->tfm); - return ret; + crypto_free_skcipher(tfm); + return ERR_PTR(ret); } - crypto_blkcipher_set_iv(desc->tfm, iv, ivsize); - return 0; + + req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + pr_err("encrypted_key: failed to allocate request for %s\n", + blkcipher_alg); + crypto_free_skcipher(tfm); + return ERR_PTR(-ENOMEM); + } + + skcipher_request_set_callback(req, 0, NULL, NULL); + return req; } static struct key *request_master_key(struct encrypted_key_payload *epayload, @@ -467,7 +475,8 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload, { struct scatterlist sg_in[2]; struct scatterlist sg_out[1]; - struct blkcipher_desc desc; + struct crypto_skcipher *tfm; + struct skcipher_request *req; unsigned int encrypted_datalen; unsigned int padlen; char pad[16]; @@ -476,9 +485,9 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload, encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); padlen = encrypted_datalen - epayload->decrypted_datalen; - ret = init_blkcipher_desc(&desc, derived_key, derived_keylen, - epayload->iv, ivsize); - if (ret < 0) + req = init_skcipher_req(derived_key, derived_keylen); + ret = PTR_ERR(req); + if (IS_ERR(req)) goto out; dump_decrypted_data(epayload); @@ -491,8 +500,12 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload, sg_init_table(sg_out, 1); sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen); - ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, encrypted_datalen); - crypto_free_blkcipher(desc.tfm); + skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, + epayload->iv); + ret = crypto_skcipher_encrypt(req); + tfm = crypto_skcipher_reqtfm(req); + skcipher_request_free(req); + crypto_free_skcipher(tfm); if (ret < 0) pr_err("encrypted_key: failed to encrypt (%d)\n", ret); else @@ -565,15 +578,16 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, { struct scatterlist sg_in[1]; struct scatterlist sg_out[2]; - struct blkcipher_desc desc; + struct crypto_skcipher *tfm; + struct skcipher_request *req; unsigned int encrypted_datalen; char pad[16]; int ret; encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); - ret = init_blkcipher_desc(&desc, derived_key, derived_keylen, - epayload->iv, ivsize); - if (ret < 0) + req = init_skcipher_req(derived_key, derived_keylen); + ret = PTR_ERR(req); + if (IS_ERR(req)) goto out; dump_encrypted_data(epayload, encrypted_datalen); @@ -585,8 +599,12 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload, epayload->decrypted_datalen); sg_set_buf(&sg_out[1], pad, sizeof pad); - ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, encrypted_datalen); - crypto_free_blkcipher(desc.tfm); + skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, + epayload->iv); + ret = crypto_skcipher_decrypt(req); + tfm = crypto_skcipher_reqtfm(req); + skcipher_request_free(req); + crypto_free_skcipher(tfm); if (ret < 0) goto out; dump_decrypted_data(epayload); -- cgit From 71af2f6bb22a4bf42663e10f1d8913d4967ed07f Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:18:30 +0800 Subject: Bluetooth: Use skcipher and hash This patch replaces uses of blkcipher with skcipher and the long obsolete hash interface with shash. Signed-off-by: Herbert Xu Acked-by: Marcel Holtmann --- net/bluetooth/smp.c | 135 ++++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 72 deletions(-) diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index ffed8a1d4f27..78ad7d691fbe 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -21,9 +21,10 @@ */ #include -#include #include #include +#include +#include #include #include @@ -87,8 +88,8 @@ struct smp_dev { u8 min_key_size; u8 max_key_size; - struct crypto_blkcipher *tfm_aes; - struct crypto_hash *tfm_cmac; + struct crypto_skcipher *tfm_aes; + struct crypto_shash *tfm_cmac; }; struct smp_chan { @@ -126,8 +127,8 @@ struct smp_chan { u8 dhkey[32]; u8 mackey[16]; - struct crypto_blkcipher *tfm_aes; - struct crypto_hash *tfm_cmac; + struct crypto_skcipher *tfm_aes; + struct crypto_shash *tfm_cmac; }; /* These debug key values are defined in the SMP section of the core @@ -165,12 +166,11 @@ static inline void swap_buf(const u8 *src, u8 *dst, size_t len) * AES-CMAC, f4, f5, f6, g2 and h6. */ -static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m, +static int aes_cmac(struct crypto_shash *tfm, const u8 k[16], const u8 *m, size_t len, u8 mac[16]) { uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX]; - struct hash_desc desc; - struct scatterlist sg; + SHASH_DESC_ON_STACK(desc, tfm); int err; if (len > CMAC_MSG_MAX) @@ -181,10 +181,8 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m, return -EINVAL; } - desc.tfm = tfm; - desc.flags = 0; - - crypto_hash_init(&desc); + desc->tfm = tfm; + desc->flags = 0; /* Swap key and message from LSB to MSB */ swap_buf(k, tmp, 16); @@ -193,23 +191,16 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m, SMP_DBG("msg (len %zu) %*phN", len, (int) len, m); SMP_DBG("key %16phN", k); - err = crypto_hash_setkey(tfm, tmp, 16); + err = crypto_shash_setkey(tfm, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); return err; } - sg_init_one(&sg, msg_msb, len); - - err = crypto_hash_update(&desc, &sg, len); + err = crypto_shash_digest(desc, msg_msb, len, mac_msb); + shash_desc_zero(desc); if (err) { - BT_ERR("Hash update error %d", err); - return err; - } - - err = crypto_hash_final(&desc, mac_msb); - if (err) { - BT_ERR("Hash final error %d", err); + BT_ERR("Hash computation error %d", err); return err; } @@ -220,8 +211,8 @@ static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m, return 0; } -static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32], - const u8 x[16], u8 z, u8 res[16]) +static int smp_f4(struct crypto_shash *tfm_cmac, const u8 u[32], + const u8 v[32], const u8 x[16], u8 z, u8 res[16]) { u8 m[65]; int err; @@ -243,7 +234,7 @@ static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32], return err; } -static int smp_f5(struct crypto_hash *tfm_cmac, const u8 w[32], +static int smp_f5(struct crypto_shash *tfm_cmac, const u8 w[32], const u8 n1[16], const u8 n2[16], const u8 a1[7], const u8 a2[7], u8 mackey[16], u8 ltk[16]) { @@ -296,7 +287,7 @@ static int smp_f5(struct crypto_hash *tfm_cmac, const u8 w[32], return 0; } -static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16], +static int smp_f6(struct crypto_shash *tfm_cmac, const u8 w[16], const u8 n1[16], const u8 n2[16], const u8 r[16], const u8 io_cap[3], const u8 a1[7], const u8 a2[7], u8 res[16]) @@ -324,7 +315,7 @@ static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16], return err; } -static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32], +static int smp_g2(struct crypto_shash *tfm_cmac, const u8 u[32], const u8 v[32], const u8 x[16], const u8 y[16], u32 *val) { u8 m[80], tmp[16]; @@ -350,7 +341,7 @@ static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32], return 0; } -static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16], +static int smp_h6(struct crypto_shash *tfm_cmac, const u8 w[16], const u8 key_id[4], u8 res[16]) { int err; @@ -370,9 +361,9 @@ static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16], * s1 and ah. */ -static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) +static int smp_e(struct crypto_skcipher *tfm, const u8 *k, u8 *r) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, tfm); struct scatterlist sg; uint8_t tmp[16], data[16]; int err; @@ -384,13 +375,10 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) return -EINVAL; } - desc.tfm = tfm; - desc.flags = 0; - /* The most significant octet of key corresponds to k[0] */ swap_buf(k, tmp, 16); - err = crypto_blkcipher_setkey(tfm, tmp, 16); + err = crypto_skcipher_setkey(tfm, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); return err; @@ -401,7 +389,12 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) sg_init_one(&sg, data, 16); - err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg, &sg, 16, NULL); + + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); if (err) BT_ERR("Encrypt data error %d", err); @@ -413,7 +406,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) return err; } -static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16], +static int smp_c1(struct crypto_skcipher *tfm_aes, const u8 k[16], const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat, const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16]) { @@ -462,7 +455,7 @@ static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16], return err; } -static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16], +static int smp_s1(struct crypto_skcipher *tfm_aes, const u8 k[16], const u8 r1[16], const u8 r2[16], u8 _r[16]) { int err; @@ -478,7 +471,7 @@ static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16], return err; } -static int smp_ah(struct crypto_blkcipher *tfm, const u8 irk[16], +static int smp_ah(struct crypto_skcipher *tfm, const u8 irk[16], const u8 r[3], u8 res[3]) { u8 _res[16]; @@ -766,8 +759,8 @@ static void smp_chan_destroy(struct l2cap_conn *conn) kzfree(smp->slave_csrk); kzfree(smp->link_key); - crypto_free_blkcipher(smp->tfm_aes); - crypto_free_hash(smp->tfm_cmac); + crypto_free_skcipher(smp->tfm_aes); + crypto_free_shash(smp->tfm_cmac); /* Ensure that we don't leave any debug key around if debug key * support hasn't been explicitly enabled. @@ -1382,17 +1375,17 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) if (!smp) return NULL; - smp->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); + smp->tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(smp->tfm_aes)) { BT_ERR("Unable to create ECB crypto context"); kzfree(smp); return NULL; } - smp->tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC); + smp->tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(smp->tfm_cmac)) { BT_ERR("Unable to create CMAC crypto context"); - crypto_free_blkcipher(smp->tfm_aes); + crypto_free_skcipher(smp->tfm_aes); kzfree(smp); return NULL; } @@ -3143,8 +3136,8 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) { struct l2cap_chan *chan; struct smp_dev *smp; - struct crypto_blkcipher *tfm_aes; - struct crypto_hash *tfm_cmac; + struct crypto_skcipher *tfm_aes; + struct crypto_shash *tfm_cmac; if (cid == L2CAP_CID_SMP_BREDR) { smp = NULL; @@ -3155,17 +3148,17 @@ static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid) if (!smp) return ERR_PTR(-ENOMEM); - tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); + tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_aes)) { BT_ERR("Unable to create ECB crypto context"); kzfree(smp); return ERR_CAST(tfm_aes); } - tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC); + tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, 0); if (IS_ERR(tfm_cmac)) { BT_ERR("Unable to create CMAC crypto context"); - crypto_free_blkcipher(tfm_aes); + crypto_free_skcipher(tfm_aes); kzfree(smp); return ERR_CAST(tfm_cmac); } @@ -3179,8 +3172,8 @@ create_chan: chan = l2cap_chan_create(); if (!chan) { if (smp) { - crypto_free_blkcipher(smp->tfm_aes); - crypto_free_hash(smp->tfm_cmac); + crypto_free_skcipher(smp->tfm_aes); + crypto_free_shash(smp->tfm_cmac); kzfree(smp); } return ERR_PTR(-ENOMEM); @@ -3226,10 +3219,8 @@ static void smp_del_chan(struct l2cap_chan *chan) smp = chan->data; if (smp) { chan->data = NULL; - if (smp->tfm_aes) - crypto_free_blkcipher(smp->tfm_aes); - if (smp->tfm_cmac) - crypto_free_hash(smp->tfm_cmac); + crypto_free_skcipher(smp->tfm_aes); + crypto_free_shash(smp->tfm_cmac); kzfree(smp); } @@ -3465,7 +3456,7 @@ void smp_unregister(struct hci_dev *hdev) #if IS_ENABLED(CONFIG_BT_SELFTEST_SMP) -static int __init test_ah(struct crypto_blkcipher *tfm_aes) +static int __init test_ah(struct crypto_skcipher *tfm_aes) { const u8 irk[16] = { 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, @@ -3485,7 +3476,7 @@ static int __init test_ah(struct crypto_blkcipher *tfm_aes) return 0; } -static int __init test_c1(struct crypto_blkcipher *tfm_aes) +static int __init test_c1(struct crypto_skcipher *tfm_aes) { const u8 k[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3515,7 +3506,7 @@ static int __init test_c1(struct crypto_blkcipher *tfm_aes) return 0; } -static int __init test_s1(struct crypto_blkcipher *tfm_aes) +static int __init test_s1(struct crypto_skcipher *tfm_aes) { const u8 k[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -3540,7 +3531,7 @@ static int __init test_s1(struct crypto_blkcipher *tfm_aes) return 0; } -static int __init test_f4(struct crypto_hash *tfm_cmac) +static int __init test_f4(struct crypto_shash *tfm_cmac) { const u8 u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, @@ -3572,7 +3563,7 @@ static int __init test_f4(struct crypto_hash *tfm_cmac) return 0; } -static int __init test_f5(struct crypto_hash *tfm_cmac) +static int __init test_f5(struct crypto_shash *tfm_cmac) { const u8 w[32] = { 0x98, 0xa6, 0xbf, 0x73, 0xf3, 0x34, 0x8d, 0x86, @@ -3609,7 +3600,7 @@ static int __init test_f5(struct crypto_hash *tfm_cmac) return 0; } -static int __init test_f6(struct crypto_hash *tfm_cmac) +static int __init test_f6(struct crypto_shash *tfm_cmac) { const u8 w[16] = { 0x20, 0x6e, 0x63, 0xce, 0x20, 0x6a, 0x3f, 0xfd, @@ -3642,7 +3633,7 @@ static int __init test_f6(struct crypto_hash *tfm_cmac) return 0; } -static int __init test_g2(struct crypto_hash *tfm_cmac) +static int __init test_g2(struct crypto_shash *tfm_cmac) { const u8 u[32] = { 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc, @@ -3674,7 +3665,7 @@ static int __init test_g2(struct crypto_hash *tfm_cmac) return 0; } -static int __init test_h6(struct crypto_hash *tfm_cmac) +static int __init test_h6(struct crypto_shash *tfm_cmac) { const u8 w[16] = { 0x9b, 0x7d, 0x39, 0x0a, 0xa6, 0x10, 0x10, 0x34, @@ -3711,8 +3702,8 @@ static const struct file_operations test_smp_fops = { .llseek = default_llseek, }; -static int __init run_selftests(struct crypto_blkcipher *tfm_aes, - struct crypto_hash *tfm_cmac) +static int __init run_selftests(struct crypto_skcipher *tfm_aes, + struct crypto_shash *tfm_cmac) { ktime_t calltime, delta, rettime; unsigned long long duration; @@ -3789,27 +3780,27 @@ done: int __init bt_selftest_smp(void) { - struct crypto_blkcipher *tfm_aes; - struct crypto_hash *tfm_cmac; + struct crypto_skcipher *tfm_aes; + struct crypto_shash *tfm_cmac; int err; - tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); + tfm_aes = crypto_alloc_skcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_aes)) { BT_ERR("Unable to create ECB crypto context"); return PTR_ERR(tfm_aes); } - tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC); + tfm_cmac = crypto_alloc_shash("cmac(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm_cmac)) { BT_ERR("Unable to create CMAC crypto context"); - crypto_free_blkcipher(tfm_aes); + crypto_free_skcipher(tfm_aes); return PTR_ERR(tfm_cmac); } err = run_selftests(tfm_aes, tfm_cmac); - crypto_free_hash(tfm_cmac); - crypto_free_blkcipher(tfm_aes); + crypto_free_shash(tfm_cmac); + crypto_free_skcipher(tfm_aes); return err; } -- cgit From e59dd982d355a40f08a666ce3ee3feea2af86959 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:18:40 +0800 Subject: libceph: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu --- net/ceph/crypto.c | 97 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 42e8649c6e79..fb9cb2bb0894 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -4,7 +4,8 @@ #include #include #include -#include +#include +#include #include #include @@ -79,9 +80,9 @@ int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *inkey) return 0; } -static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void) +static struct crypto_skcipher *ceph_crypto_alloc_cipher(void) { - return crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); + return crypto_alloc_skcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); } static const u8 *aes_iv = (u8 *)CEPH_AES_IV; @@ -162,11 +163,11 @@ static int ceph_aes_encrypt(const void *key, int key_len, { struct scatterlist sg_in[2], prealloc_sg; struct sg_table sg_out; - struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); - struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; + struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); + SKCIPHER_REQUEST_ON_STACK(req, tfm); int ret; - void *iv; - int ivsize; + int ivsize = AES_BLOCK_SIZE; + char iv[ivsize]; size_t zero_padding = (0x10 - (src_len & 0x0f)); char pad[16]; @@ -184,11 +185,14 @@ static int ceph_aes_encrypt(const void *key, int key_len, if (ret) goto out_tfm; - crypto_blkcipher_setkey((void *)tfm, key, key_len); - iv = crypto_blkcipher_crt(tfm)->iv; - ivsize = crypto_blkcipher_ivsize(tfm); + crypto_skcipher_setkey((void *)tfm, key, key_len); memcpy(iv, aes_iv, ivsize); + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in, sg_out.sgl, + src_len + zero_padding, iv); + /* print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, key, key_len, 1); @@ -197,8 +201,8 @@ static int ceph_aes_encrypt(const void *key, int key_len, print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, pad, zero_padding, 1); */ - ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, - src_len + zero_padding); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); if (ret < 0) { pr_err("ceph_aes_crypt failed %d\n", ret); goto out_sg; @@ -211,7 +215,7 @@ static int ceph_aes_encrypt(const void *key, int key_len, out_sg: teardown_sgtable(&sg_out); out_tfm: - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); return ret; } @@ -222,11 +226,11 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, { struct scatterlist sg_in[3], prealloc_sg; struct sg_table sg_out; - struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); - struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 }; + struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); + SKCIPHER_REQUEST_ON_STACK(req, tfm); int ret; - void *iv; - int ivsize; + int ivsize = AES_BLOCK_SIZE; + char iv[ivsize]; size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f)); char pad[16]; @@ -245,11 +249,14 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, if (ret) goto out_tfm; - crypto_blkcipher_setkey((void *)tfm, key, key_len); - iv = crypto_blkcipher_crt(tfm)->iv; - ivsize = crypto_blkcipher_ivsize(tfm); + crypto_skcipher_setkey((void *)tfm, key, key_len); memcpy(iv, aes_iv, ivsize); + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in, sg_out.sgl, + src1_len + src2_len + zero_padding, iv); + /* print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1, key, key_len, 1); @@ -260,8 +267,8 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1, pad, zero_padding, 1); */ - ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in, - src1_len + src2_len + zero_padding); + ret = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); if (ret < 0) { pr_err("ceph_aes_crypt2 failed %d\n", ret); goto out_sg; @@ -274,7 +281,7 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, out_sg: teardown_sgtable(&sg_out); out_tfm: - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); return ret; } @@ -284,11 +291,11 @@ static int ceph_aes_decrypt(const void *key, int key_len, { struct sg_table sg_in; struct scatterlist sg_out[2], prealloc_sg; - struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); - struct blkcipher_desc desc = { .tfm = tfm }; + struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); + SKCIPHER_REQUEST_ON_STACK(req, tfm); char pad[16]; - void *iv; - int ivsize; + int ivsize = AES_BLOCK_SIZE; + char iv[16]; int ret; int last_byte; @@ -302,18 +309,22 @@ static int ceph_aes_decrypt(const void *key, int key_len, if (ret) goto out_tfm; - crypto_blkcipher_setkey((void *)tfm, key, key_len); - iv = crypto_blkcipher_crt(tfm)->iv; - ivsize = crypto_blkcipher_ivsize(tfm); + crypto_skcipher_setkey((void *)tfm, key, key_len); memcpy(iv, aes_iv, ivsize); + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in.sgl, sg_out, + src_len, iv); + /* print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1, key, key_len, 1); print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, src, src_len, 1); */ - ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); + ret = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); if (ret < 0) { pr_err("ceph_aes_decrypt failed %d\n", ret); goto out_sg; @@ -338,7 +349,7 @@ static int ceph_aes_decrypt(const void *key, int key_len, out_sg: teardown_sgtable(&sg_in); out_tfm: - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); return ret; } @@ -349,11 +360,11 @@ static int ceph_aes_decrypt2(const void *key, int key_len, { struct sg_table sg_in; struct scatterlist sg_out[3], prealloc_sg; - struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher(); - struct blkcipher_desc desc = { .tfm = tfm }; + struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); + SKCIPHER_REQUEST_ON_STACK(req, tfm); char pad[16]; - void *iv; - int ivsize; + int ivsize = AES_BLOCK_SIZE; + char iv[ivsize]; int ret; int last_byte; @@ -368,18 +379,22 @@ static int ceph_aes_decrypt2(const void *key, int key_len, if (ret) goto out_tfm; - crypto_blkcipher_setkey((void *)tfm, key, key_len); - iv = crypto_blkcipher_crt(tfm)->iv; - ivsize = crypto_blkcipher_ivsize(tfm); + crypto_skcipher_setkey((void *)tfm, key, key_len); memcpy(iv, aes_iv, ivsize); + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg_in.sgl, sg_out, + src_len, iv); + /* print_hex_dump(KERN_ERR, "dec key: ", DUMP_PREFIX_NONE, 16, 1, key, key_len, 1); print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1, src, src_len, 1); */ - ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len); + ret = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); if (ret < 0) { pr_err("ceph_aes_decrypt failed %d\n", ret); goto out_sg; @@ -415,7 +430,7 @@ static int ceph_aes_decrypt2(const void *key, int key_len, out_sg: teardown_sgtable(&sg_in); out_tfm: - crypto_free_blkcipher(tfm); + crypto_free_skcipher(tfm); return ret; } -- cgit From 96953718623eb7ee8839ae667dfecad7b257d400 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:18:50 +0800 Subject: mac802154: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu Reviewed-by: Stefan Schmidt --- net/mac802154/llsec.c | 41 +++++++++++++++++++++++------------------ net/mac802154/llsec.h | 3 +-- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index a13d02b7cee4..6a3e1c2181d3 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c @@ -17,9 +17,9 @@ #include #include #include -#include #include #include +#include #include "ieee802154_i.h" #include "llsec.h" @@ -144,18 +144,18 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) goto err_tfm; } - key->tfm0 = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); + key->tfm0 = crypto_alloc_skcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(key->tfm0)) goto err_tfm; - if (crypto_blkcipher_setkey(key->tfm0, template->key, - IEEE802154_LLSEC_KEY_SIZE)) + if (crypto_skcipher_setkey(key->tfm0, template->key, + IEEE802154_LLSEC_KEY_SIZE)) goto err_tfm0; return key; err_tfm0: - crypto_free_blkcipher(key->tfm0); + crypto_free_skcipher(key->tfm0); err_tfm: for (i = 0; i < ARRAY_SIZE(key->tfm); i++) if (key->tfm[i]) @@ -175,7 +175,7 @@ static void llsec_key_release(struct kref *ref) for (i = 0; i < ARRAY_SIZE(key->tfm); i++) crypto_free_aead(key->tfm[i]); - crypto_free_blkcipher(key->tfm0); + crypto_free_skcipher(key->tfm0); kzfree(key); } @@ -620,15 +620,17 @@ llsec_do_encrypt_unauth(struct sk_buff *skb, const struct mac802154_llsec *sec, { u8 iv[16]; struct scatterlist src; - struct blkcipher_desc req = { - .tfm = key->tfm0, - .info = iv, - .flags = 0, - }; + SKCIPHER_REQUEST_ON_STACK(req, key->tfm0); + int err; llsec_geniv(iv, sec->params.hwaddr, &hdr->sec); sg_init_one(&src, skb->data, skb->len); - return crypto_blkcipher_encrypt_iv(&req, &src, &src, skb->len); + skcipher_request_set_tfm(req, key->tfm0); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &src, &src, skb->len, iv); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + return err; } static struct crypto_aead* @@ -830,11 +832,8 @@ llsec_do_decrypt_unauth(struct sk_buff *skb, const struct mac802154_llsec *sec, unsigned char *data; int datalen; struct scatterlist src; - struct blkcipher_desc req = { - .tfm = key->tfm0, - .info = iv, - .flags = 0, - }; + SKCIPHER_REQUEST_ON_STACK(req, key->tfm0); + int err; llsec_geniv(iv, dev_addr, &hdr->sec); data = skb_mac_header(skb) + skb->mac_len; @@ -842,7 +841,13 @@ llsec_do_decrypt_unauth(struct sk_buff *skb, const struct mac802154_llsec *sec, sg_init_one(&src, data, datalen); - return crypto_blkcipher_decrypt_iv(&req, &src, &src, datalen); + skcipher_request_set_tfm(req, key->tfm0); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &src, &src, datalen, iv); + + err = crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + return err; } static int diff --git a/net/mac802154/llsec.h b/net/mac802154/llsec.h index 950578e1d7be..6f3b658e3279 100644 --- a/net/mac802154/llsec.h +++ b/net/mac802154/llsec.h @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -30,7 +29,7 @@ struct mac802154_llsec_key { /* one tfm for each authsize (4/8/16) */ struct crypto_aead *tfm[3]; - struct crypto_blkcipher *tfm0; + struct crypto_skcipher *tfm0; struct kref ref; }; -- cgit From 1afe593b423918ffd5e449cec858b1591cd31781 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:01 +0800 Subject: rxrpc: Use skcipher This patch replaces uses of blkcipher with skcipher. Signed-off-by: Herbert Xu --- net/rxrpc/ar-internal.h | 2 +- net/rxrpc/ar-key.c | 12 ++-- net/rxrpc/rxkad.c | 172 ++++++++++++++++++++++++++++++------------------ 3 files changed, 114 insertions(+), 72 deletions(-) diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 2934a73a5981..71598f5b11b7 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -252,7 +252,7 @@ struct rxrpc_connection { 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_blkcipher *cipher; /* encryption handle */ + struct crypto_skcipher *cipher; /* encryption handle */ struct rxrpc_crypt csum_iv; /* packet checksum base */ unsigned long events; #define RXRPC_CONN_CHALLENGE 0 /* send challenge packet */ diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 3f6571651d32..3fb492eedeb9 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -12,11 +12,11 @@ * "afs@CAMBRIDGE.REDHAT.COM> */ +#include #include #include #include #include -#include #include #include #include @@ -824,7 +824,7 @@ static void rxrpc_free_preparse(struct key_preparsed_payload *prep) */ static int rxrpc_preparse_s(struct key_preparsed_payload *prep) { - struct crypto_blkcipher *ci; + struct crypto_skcipher *ci; _enter("%zu", prep->datalen); @@ -833,13 +833,13 @@ static int rxrpc_preparse_s(struct key_preparsed_payload *prep) memcpy(&prep->payload.data[2], prep->data, 8); - ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); + ci = crypto_alloc_skcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(ci)) { _leave(" = %ld", PTR_ERR(ci)); return PTR_ERR(ci); } - if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) + if (crypto_skcipher_setkey(ci, prep->data, 8) < 0) BUG(); prep->payload.data[0] = ci; @@ -853,7 +853,7 @@ static int rxrpc_preparse_s(struct key_preparsed_payload *prep) static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) { if (prep->payload.data[0]) - crypto_free_blkcipher(prep->payload.data[0]); + crypto_free_skcipher(prep->payload.data[0]); } /* @@ -870,7 +870,7 @@ static void rxrpc_destroy(struct key *key) static void rxrpc_destroy_s(struct key *key) { if (key->payload.data[0]) { - crypto_free_blkcipher(key->payload.data[0]); + crypto_free_skcipher(key->payload.data[0]); key->payload.data[0] = NULL; } } diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index d7a9ab5a9d9c..0d96b48a6492 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c @@ -9,11 +9,11 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include #include -#include #include #include #include @@ -53,7 +53,7 @@ MODULE_LICENSE("GPL"); * alloc routine, but since we have it to hand, we use it to decrypt RESPONSE * packets */ -static struct crypto_blkcipher *rxkad_ci; +static struct crypto_skcipher *rxkad_ci; static DEFINE_MUTEX(rxkad_ci_mutex); /* @@ -61,7 +61,7 @@ static DEFINE_MUTEX(rxkad_ci_mutex); */ static int rxkad_init_connection_security(struct rxrpc_connection *conn) { - struct crypto_blkcipher *ci; + struct crypto_skcipher *ci; struct rxrpc_key_token *token; int ret; @@ -70,15 +70,15 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn) token = conn->key->payload.data[0]; conn->security_ix = token->security_index; - ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); + ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(ci)) { _debug("no cipher"); ret = PTR_ERR(ci); goto error; } - if (crypto_blkcipher_setkey(ci, token->kad->session_key, - sizeof(token->kad->session_key)) < 0) + if (crypto_skcipher_setkey(ci, token->kad->session_key, + sizeof(token->kad->session_key)) < 0) BUG(); switch (conn->security_level) { @@ -113,7 +113,7 @@ error: static void rxkad_prime_packet_security(struct rxrpc_connection *conn) { struct rxrpc_key_token *token; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); struct scatterlist sg[2]; struct rxrpc_crypt iv; struct { @@ -128,10 +128,6 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) token = conn->key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); - desc.tfm = conn->cipher; - desc.info = iv.x; - desc.flags = 0; - tmpbuf.x[0] = conn->epoch; tmpbuf.x[1] = conn->cid; tmpbuf.x[2] = 0; @@ -139,7 +135,13 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn) sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); memcpy(&conn->csum_iv, &tmpbuf.x[2], sizeof(conn->csum_iv)); ASSERTCMP(conn->csum_iv.n[0], ==, tmpbuf.x[2]); @@ -156,7 +158,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, void *sechdr) { struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[2]; struct { @@ -177,13 +179,16 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call, /* start the encryption afresh */ memset(&iv, 0, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); memcpy(sechdr, &tmpbuf, sizeof(tmpbuf)); @@ -203,13 +208,14 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, struct rxkad_level2_hdr rxkhdr __attribute__((aligned(8))); /* must be all on one page */ struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[16]; struct sk_buff *trailer; unsigned int len; u16 check; int nsg; + int err; sp = rxrpc_skb(skb); @@ -223,28 +229,38 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, /* encrypt from the session key */ token = call->conn->key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; sg_init_one(&sg[0], sechdr, sizeof(rxkhdr)); sg_init_one(&sg[1], &rxkhdr, sizeof(rxkhdr)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(rxkhdr)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(rxkhdr), iv.x); + + crypto_skcipher_encrypt(req); /* we want to encrypt the skbuff in-place */ nsg = skb_cow_data(skb, 0, &trailer); + err = -ENOMEM; if (nsg < 0 || nsg > 16) - return -ENOMEM; + goto out; len = data_size + call->conn->size_align - 1; len &= ~(call->conn->size_align - 1); sg_init_table(sg, nsg); skb_to_sgvec(skb, sg, 0, len); - crypto_blkcipher_encrypt_iv(&desc, sg, sg, len); + + skcipher_request_set_crypt(req, sg, sg, len, iv.x); + + crypto_skcipher_encrypt(req); _leave(" = 0"); - return 0; + err = 0; + +out: + skcipher_request_zero(req); + return err; } /* @@ -256,7 +272,7 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, void *sechdr) { struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[2]; struct { @@ -281,9 +297,6 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; /* calculate the security checksum */ x = htonl(call->channel << (32 - RXRPC_CIDSHIFT)); @@ -293,7 +306,13 @@ static int rxkad_secure_packet(const struct rxrpc_call *call, sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); y = ntohl(tmpbuf.x[1]); y = (y >> 16) & 0xffff; @@ -330,7 +349,7 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, { struct rxkad_level1_hdr sechdr; struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[16]; struct sk_buff *trailer; @@ -352,11 +371,13 @@ static int rxkad_verify_packet_auth(const struct rxrpc_call *call, /* start the decryption afresh */ memset(&iv, 0, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; - crypto_blkcipher_decrypt_iv(&desc, sg, sg, 8); + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, 8, iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_zero(req); /* remove the decrypted packet length */ if (skb_copy_bits(skb, 0, &sechdr, sizeof(sechdr)) < 0) @@ -405,7 +426,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, const struct rxrpc_key_token *token; struct rxkad_level2_hdr sechdr; struct rxrpc_skb_priv *sp; - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_crypt iv; struct scatterlist _sg[4], *sg; struct sk_buff *trailer; @@ -435,11 +456,13 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call, /* decrypt from the session key */ token = call->conn->key->payload.data[0]; memcpy(&iv, token->kad->session_key, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; - crypto_blkcipher_decrypt_iv(&desc, sg, sg, skb->len); + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, skb->len, iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_zero(req); if (sg != _sg) kfree(sg); @@ -487,7 +510,7 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, struct sk_buff *skb, u32 *_abort_code) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher); struct rxrpc_skb_priv *sp; struct rxrpc_crypt iv; struct scatterlist sg[2]; @@ -516,9 +539,6 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, /* continue encrypting from where we left off */ memcpy(&iv, call->conn->csum_iv.x, sizeof(iv)); - desc.tfm = call->conn->cipher; - desc.info = iv.x; - desc.flags = 0; /* validate the security checksum */ x = htonl(call->channel << (32 - RXRPC_CIDSHIFT)); @@ -528,7 +548,13 @@ static int rxkad_verify_packet(const struct rxrpc_call *call, sg_init_one(&sg[0], &tmpbuf, sizeof(tmpbuf)); sg_init_one(&sg[1], &tmpbuf, sizeof(tmpbuf)); - crypto_blkcipher_encrypt_iv(&desc, &sg[0], &sg[1], sizeof(tmpbuf)); + + skcipher_request_set_tfm(req, call->conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &sg[1], &sg[0], sizeof(tmpbuf), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); y = ntohl(tmpbuf.x[1]); y = (y >> 16) & 0xffff; @@ -718,18 +744,21 @@ static void rxkad_encrypt_response(struct rxrpc_connection *conn, struct rxkad_response *resp, const struct rxkad_key *s2) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, conn->cipher); struct rxrpc_crypt iv; struct scatterlist sg[2]; /* continue encrypting from where we left off */ memcpy(&iv, s2->session_key, sizeof(iv)); - desc.tfm = conn->cipher; - desc.info = iv.x; - desc.flags = 0; rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); - crypto_blkcipher_encrypt_iv(&desc, sg, sg, sizeof(resp->encrypted)); + + skcipher_request_set_tfm(req, conn->cipher); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); + + crypto_skcipher_encrypt(req); + skcipher_request_zero(req); } /* @@ -822,7 +851,7 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, time_t *_expiry, u32 *_abort_code) { - struct blkcipher_desc desc; + struct skcipher_request *req; struct rxrpc_crypt iv, key; struct scatterlist sg[1]; struct in_addr addr; @@ -853,12 +882,21 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn, memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv)); - desc.tfm = conn->server_key->payload.data[0]; - desc.info = iv.x; - desc.flags = 0; + req = skcipher_request_alloc(conn->server_key->payload.data[0], + GFP_NOFS); + if (!req) { + *_abort_code = RXKADNOAUTH; + ret = -ENOMEM; + goto error; + } sg_init_one(&sg[0], ticket, ticket_len); - crypto_blkcipher_decrypt_iv(&desc, sg, sg, ticket_len); + + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, ticket_len, iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_free(req); p = ticket; end = p + ticket_len; @@ -966,7 +1004,7 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, struct rxkad_response *resp, const struct rxrpc_crypt *session_key) { - struct blkcipher_desc desc; + SKCIPHER_REQUEST_ON_STACK(req, rxkad_ci); struct scatterlist sg[2]; struct rxrpc_crypt iv; @@ -976,17 +1014,21 @@ static void rxkad_decrypt_response(struct rxrpc_connection *conn, ASSERT(rxkad_ci != NULL); mutex_lock(&rxkad_ci_mutex); - if (crypto_blkcipher_setkey(rxkad_ci, session_key->x, - sizeof(*session_key)) < 0) + if (crypto_skcipher_setkey(rxkad_ci, session_key->x, + sizeof(*session_key)) < 0) BUG(); memcpy(&iv, session_key, sizeof(iv)); - desc.tfm = rxkad_ci; - desc.info = iv.x; - desc.flags = 0; rxkad_sg_set_buf2(sg, &resp->encrypted, sizeof(resp->encrypted)); - crypto_blkcipher_decrypt_iv(&desc, sg, sg, sizeof(resp->encrypted)); + + skcipher_request_set_tfm(req, rxkad_ci); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x); + + crypto_skcipher_decrypt(req); + skcipher_request_zero(req); + mutex_unlock(&rxkad_ci_mutex); _leave(""); @@ -1115,7 +1157,7 @@ static void rxkad_clear(struct rxrpc_connection *conn) _enter(""); if (conn->cipher) - crypto_free_blkcipher(conn->cipher); + crypto_free_skcipher(conn->cipher); } /* @@ -1141,7 +1183,7 @@ static __init 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_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); + rxkad_ci = crypto_alloc_skcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(rxkad_ci)) return PTR_ERR(rxkad_ci); @@ -1155,7 +1197,7 @@ static __exit void rxkad_exit(void) _enter(""); rxrpc_unregister_security(&rxkad); - crypto_free_blkcipher(rxkad_ci); + crypto_free_skcipher(rxkad_ci); } module_exit(rxkad_exit); -- cgit From 17bc197022212a8b439b213b2f23a8603a784e56 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:11 +0800 Subject: ipsec: Use skcipher and ahash when probing algorithms This patch removes the last reference to hash and ablkcipher from IPsec and replaces them with ahash and skcipher respectively. For skcipher there is currently no difference at all, while for ahash the current code is actually buggy and would prevent asynchronous algorithms from being discovered. Signed-off-by: Herbert Xu Acked-by: David S. Miller --- net/xfrm/xfrm_algo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index f07224d8b88f..250e567ba3d6 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -9,6 +9,8 @@ * any later version. */ +#include +#include #include #include #include @@ -782,14 +784,13 @@ void xfrm_probe_algs(void) BUG_ON(in_softirq()); for (i = 0; i < aalg_entries(); i++) { - status = crypto_has_hash(aalg_list[i].name, 0, - CRYPTO_ALG_ASYNC); + status = crypto_has_ahash(aalg_list[i].name, 0, 0); if (aalg_list[i].available != status) aalg_list[i].available = status; } for (i = 0; i < ealg_entries(); i++) { - status = crypto_has_ablkcipher(ealg_list[i].name, 0, 0); + status = crypto_has_skcipher(ealg_list[i].name, 0, 0); if (ealg_list[i].available != status) ealg_list[i].available = status; } -- cgit From 9534d67195118c39edf2ec0bb74e59993c4c0677 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:21 +0800 Subject: drbd: Use shash and ahash This patch replaces uses of the long obsolete hash interface with either shash (for non-SG users) or ahash. Signed-off-by: Herbert Xu --- drivers/block/drbd/drbd_int.h | 16 +++++------ drivers/block/drbd/drbd_main.c | 16 +++++------ drivers/block/drbd/drbd_nl.c | 59 ++++++++++++++++++++++++-------------- drivers/block/drbd/drbd_receiver.c | 56 +++++++++++++++++------------------- drivers/block/drbd/drbd_worker.c | 43 +++++++++++++++------------ 5 files changed, 103 insertions(+), 87 deletions(-) diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 34bc84efc29e..c227fd4cad75 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -26,13 +26,13 @@ #ifndef _DRBD_INT_H #define _DRBD_INT_H +#include #include #include #include #include #include #include -#include #include #include #include @@ -724,11 +724,11 @@ struct drbd_connection { struct list_head transfer_log; /* all requests not yet fully processed */ - struct crypto_hash *cram_hmac_tfm; - struct crypto_hash *integrity_tfm; /* checksums we compute, updates protected by connection->data->mutex */ - struct crypto_hash *peer_integrity_tfm; /* checksums we verify, only accessed from receiver thread */ - struct crypto_hash *csums_tfm; - struct crypto_hash *verify_tfm; + struct crypto_shash *cram_hmac_tfm; + struct crypto_ahash *integrity_tfm; /* checksums we compute, updates protected by connection->data->mutex */ + struct crypto_ahash *peer_integrity_tfm; /* checksums we verify, only accessed from receiver thread */ + struct crypto_ahash *csums_tfm; + struct crypto_ahash *verify_tfm; void *int_dig_in; void *int_dig_vv; @@ -1524,8 +1524,8 @@ static inline void ov_out_of_sync_print(struct drbd_device *device) } -extern void drbd_csum_bio(struct crypto_hash *, struct bio *, void *); -extern void drbd_csum_ee(struct crypto_hash *, struct drbd_peer_request *, void *); +extern void drbd_csum_bio(struct crypto_ahash *, struct bio *, void *); +extern void drbd_csum_ee(struct crypto_ahash *, struct drbd_peer_request *, void *); /* worker callbacks */ extern int w_e_end_data_req(struct drbd_work *, int); extern int w_e_end_rsdata_req(struct drbd_work *, int); diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 5b43dfb79819..fa209773d494 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1340,7 +1340,7 @@ void drbd_send_ack_dp(struct drbd_peer_device *peer_device, enum drbd_packet cmd struct p_data *dp, int data_size) { if (peer_device->connection->peer_integrity_tfm) - data_size -= crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm); + data_size -= crypto_ahash_digestsize(peer_device->connection->peer_integrity_tfm); _drbd_send_ack(peer_device, cmd, dp->sector, cpu_to_be32(data_size), dp->block_id); } @@ -1629,7 +1629,7 @@ int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request * sock = &peer_device->connection->data; p = drbd_prepare_command(peer_device, sock); digest_size = peer_device->connection->integrity_tfm ? - crypto_hash_digestsize(peer_device->connection->integrity_tfm) : 0; + crypto_ahash_digestsize(peer_device->connection->integrity_tfm) : 0; if (!p) return -EIO; @@ -1718,7 +1718,7 @@ int drbd_send_block(struct drbd_peer_device *peer_device, enum drbd_packet cmd, p = drbd_prepare_command(peer_device, sock); digest_size = peer_device->connection->integrity_tfm ? - crypto_hash_digestsize(peer_device->connection->integrity_tfm) : 0; + crypto_ahash_digestsize(peer_device->connection->integrity_tfm) : 0; if (!p) return -EIO; @@ -2498,11 +2498,11 @@ void conn_free_crypto(struct drbd_connection *connection) { drbd_free_sock(connection); - crypto_free_hash(connection->csums_tfm); - crypto_free_hash(connection->verify_tfm); - crypto_free_hash(connection->cram_hmac_tfm); - crypto_free_hash(connection->integrity_tfm); - crypto_free_hash(connection->peer_integrity_tfm); + crypto_free_ahash(connection->csums_tfm); + crypto_free_ahash(connection->verify_tfm); + crypto_free_shash(connection->cram_hmac_tfm); + crypto_free_ahash(connection->integrity_tfm); + crypto_free_ahash(connection->peer_integrity_tfm); kfree(connection->int_dig_in); kfree(connection->int_dig_vv); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index c055c5e12f24..226eb0c9f0fb 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -2160,19 +2160,34 @@ check_net_options(struct drbd_connection *connection, struct net_conf *new_net_c } struct crypto { - struct crypto_hash *verify_tfm; - struct crypto_hash *csums_tfm; - struct crypto_hash *cram_hmac_tfm; - struct crypto_hash *integrity_tfm; + struct crypto_ahash *verify_tfm; + struct crypto_ahash *csums_tfm; + struct crypto_shash *cram_hmac_tfm; + struct crypto_ahash *integrity_tfm; }; static int -alloc_hash(struct crypto_hash **tfm, char *tfm_name, int err_alg) +alloc_shash(struct crypto_shash **tfm, char *tfm_name, int err_alg) { if (!tfm_name[0]) return NO_ERROR; - *tfm = crypto_alloc_hash(tfm_name, 0, CRYPTO_ALG_ASYNC); + *tfm = crypto_alloc_shash(tfm_name, 0, 0); + if (IS_ERR(*tfm)) { + *tfm = NULL; + return err_alg; + } + + return NO_ERROR; +} + +static int +alloc_ahash(struct crypto_ahash **tfm, char *tfm_name, int err_alg) +{ + if (!tfm_name[0]) + return NO_ERROR; + + *tfm = crypto_alloc_ahash(tfm_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(*tfm)) { *tfm = NULL; return err_alg; @@ -2187,24 +2202,24 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_net_conf) char hmac_name[CRYPTO_MAX_ALG_NAME]; enum drbd_ret_code rv; - rv = alloc_hash(&crypto->csums_tfm, new_net_conf->csums_alg, - ERR_CSUMS_ALG); + rv = alloc_ahash(&crypto->csums_tfm, new_net_conf->csums_alg, + ERR_CSUMS_ALG); if (rv != NO_ERROR) return rv; - rv = alloc_hash(&crypto->verify_tfm, new_net_conf->verify_alg, - ERR_VERIFY_ALG); + rv = alloc_ahash(&crypto->verify_tfm, new_net_conf->verify_alg, + ERR_VERIFY_ALG); if (rv != NO_ERROR) return rv; - rv = alloc_hash(&crypto->integrity_tfm, new_net_conf->integrity_alg, - ERR_INTEGRITY_ALG); + rv = alloc_ahash(&crypto->integrity_tfm, new_net_conf->integrity_alg, + ERR_INTEGRITY_ALG); if (rv != NO_ERROR) return rv; if (new_net_conf->cram_hmac_alg[0] != 0) { snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)", new_net_conf->cram_hmac_alg); - rv = alloc_hash(&crypto->cram_hmac_tfm, hmac_name, - ERR_AUTH_ALG); + rv = alloc_shash(&crypto->cram_hmac_tfm, hmac_name, + ERR_AUTH_ALG); } return rv; @@ -2212,10 +2227,10 @@ alloc_crypto(struct crypto *crypto, struct net_conf *new_net_conf) static void free_crypto(struct crypto *crypto) { - crypto_free_hash(crypto->cram_hmac_tfm); - crypto_free_hash(crypto->integrity_tfm); - crypto_free_hash(crypto->csums_tfm); - crypto_free_hash(crypto->verify_tfm); + crypto_free_shash(crypto->cram_hmac_tfm); + crypto_free_ahash(crypto->integrity_tfm); + crypto_free_ahash(crypto->csums_tfm); + crypto_free_ahash(crypto->verify_tfm); } int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) @@ -2292,23 +2307,23 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info) rcu_assign_pointer(connection->net_conf, new_net_conf); if (!rsr) { - crypto_free_hash(connection->csums_tfm); + crypto_free_ahash(connection->csums_tfm); connection->csums_tfm = crypto.csums_tfm; crypto.csums_tfm = NULL; } if (!ovr) { - crypto_free_hash(connection->verify_tfm); + crypto_free_ahash(connection->verify_tfm); connection->verify_tfm = crypto.verify_tfm; crypto.verify_tfm = NULL; } - crypto_free_hash(connection->integrity_tfm); + crypto_free_ahash(connection->integrity_tfm); connection->integrity_tfm = crypto.integrity_tfm; if (connection->cstate >= C_WF_REPORT_PARAMS && connection->agreed_pro_version >= 100) /* Do this without trying to take connection->data.mutex again. */ __drbd_send_protocol(connection, P_PROTOCOL_UPDATE); - crypto_free_hash(connection->cram_hmac_tfm); + crypto_free_shash(connection->cram_hmac_tfm); connection->cram_hmac_tfm = crypto.cram_hmac_tfm; mutex_unlock(&connection->resource->conf_update); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 1957fe8601dc..050aaa1c0350 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1627,7 +1627,7 @@ read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector, digest_size = 0; if (!trim && peer_device->connection->peer_integrity_tfm) { - digest_size = crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->peer_integrity_tfm); /* * FIXME: Receive the incoming digest into the receive buffer * here, together with its struct p_data? @@ -1741,7 +1741,7 @@ static int recv_dless_read(struct drbd_peer_device *peer_device, struct drbd_req digest_size = 0; if (peer_device->connection->peer_integrity_tfm) { - digest_size = crypto_hash_digestsize(peer_device->connection->peer_integrity_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->peer_integrity_tfm); err = drbd_recv_all_warn(peer_device->connection, dig_in, digest_size); if (err) return err; @@ -3321,7 +3321,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in int p_proto, p_discard_my_data, p_two_primaries, cf; struct net_conf *nc, *old_net_conf, *new_net_conf = NULL; char integrity_alg[SHARED_SECRET_MAX] = ""; - struct crypto_hash *peer_integrity_tfm = NULL; + struct crypto_ahash *peer_integrity_tfm = NULL; void *int_dig_in = NULL, *int_dig_vv = NULL; p_proto = be32_to_cpu(p->protocol); @@ -3402,14 +3402,14 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in * change. */ - peer_integrity_tfm = crypto_alloc_hash(integrity_alg, 0, CRYPTO_ALG_ASYNC); + peer_integrity_tfm = crypto_alloc_ahash(integrity_alg, 0, CRYPTO_ALG_ASYNC); if (!peer_integrity_tfm) { drbd_err(connection, "peer data-integrity-alg %s not supported\n", integrity_alg); goto disconnect; } - hash_size = crypto_hash_digestsize(peer_integrity_tfm); + hash_size = crypto_ahash_digestsize(peer_integrity_tfm); int_dig_in = kmalloc(hash_size, GFP_KERNEL); int_dig_vv = kmalloc(hash_size, GFP_KERNEL); if (!(int_dig_in && int_dig_vv)) { @@ -3439,7 +3439,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in mutex_unlock(&connection->resource->conf_update); mutex_unlock(&connection->data.mutex); - crypto_free_hash(connection->peer_integrity_tfm); + crypto_free_ahash(connection->peer_integrity_tfm); kfree(connection->int_dig_in); kfree(connection->int_dig_vv); connection->peer_integrity_tfm = peer_integrity_tfm; @@ -3457,7 +3457,7 @@ static int receive_protocol(struct drbd_connection *connection, struct packet_in disconnect_rcu_unlock: rcu_read_unlock(); disconnect: - crypto_free_hash(peer_integrity_tfm); + crypto_free_ahash(peer_integrity_tfm); kfree(int_dig_in); kfree(int_dig_vv); conn_request_state(connection, NS(conn, C_DISCONNECTING), CS_HARD); @@ -3469,15 +3469,15 @@ disconnect: * return: NULL (alg name was "") * ERR_PTR(error) if something goes wrong * or the crypto hash ptr, if it worked out ok. */ -static struct crypto_hash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device, +static struct crypto_ahash *drbd_crypto_alloc_digest_safe(const struct drbd_device *device, const char *alg, const char *name) { - struct crypto_hash *tfm; + struct crypto_ahash *tfm; if (!alg[0]) return NULL; - tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_ahash(alg, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) { drbd_err(device, "Can not allocate \"%s\" as %s (reason: %ld)\n", alg, name, PTR_ERR(tfm)); @@ -3530,8 +3530,8 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i struct drbd_device *device; struct p_rs_param_95 *p; unsigned int header_size, data_size, exp_max_sz; - struct crypto_hash *verify_tfm = NULL; - struct crypto_hash *csums_tfm = NULL; + struct crypto_ahash *verify_tfm = NULL; + struct crypto_ahash *csums_tfm = NULL; struct net_conf *old_net_conf, *new_net_conf = NULL; struct disk_conf *old_disk_conf = NULL, *new_disk_conf = NULL; const int apv = connection->agreed_pro_version; @@ -3678,14 +3678,14 @@ static int receive_SyncParam(struct drbd_connection *connection, struct packet_i if (verify_tfm) { strcpy(new_net_conf->verify_alg, p->verify_alg); new_net_conf->verify_alg_len = strlen(p->verify_alg) + 1; - crypto_free_hash(peer_device->connection->verify_tfm); + crypto_free_ahash(peer_device->connection->verify_tfm); peer_device->connection->verify_tfm = verify_tfm; drbd_info(device, "using verify-alg: \"%s\"\n", p->verify_alg); } if (csums_tfm) { strcpy(new_net_conf->csums_alg, p->csums_alg); new_net_conf->csums_alg_len = strlen(p->csums_alg) + 1; - crypto_free_hash(peer_device->connection->csums_tfm); + crypto_free_ahash(peer_device->connection->csums_tfm); peer_device->connection->csums_tfm = csums_tfm; drbd_info(device, "using csums-alg: \"%s\"\n", p->csums_alg); } @@ -3729,9 +3729,9 @@ disconnect: mutex_unlock(&connection->resource->conf_update); /* just for completeness: actually not needed, * as this is not reached if csums_tfm was ok. */ - crypto_free_hash(csums_tfm); + crypto_free_ahash(csums_tfm); /* but free the verify_tfm again, if csums_tfm did not work out */ - crypto_free_hash(verify_tfm); + crypto_free_ahash(verify_tfm); conn_request_state(peer_device->connection, NS(conn, C_DISCONNECTING), CS_HARD); return -EIO; } @@ -4925,14 +4925,13 @@ static int drbd_do_auth(struct drbd_connection *connection) { struct drbd_socket *sock; char my_challenge[CHALLENGE_LEN]; /* 64 Bytes... */ - struct scatterlist sg; char *response = NULL; char *right_response = NULL; char *peers_ch = NULL; unsigned int key_len; char secret[SHARED_SECRET_MAX]; /* 64 byte */ unsigned int resp_size; - struct hash_desc desc; + SHASH_DESC_ON_STACK(desc, connection->cram_hmac_tfm); struct packet_info pi; struct net_conf *nc; int err, rv; @@ -4945,12 +4944,12 @@ static int drbd_do_auth(struct drbd_connection *connection) memcpy(secret, nc->shared_secret, key_len); rcu_read_unlock(); - desc.tfm = connection->cram_hmac_tfm; - desc.flags = 0; + desc->tfm = connection->cram_hmac_tfm; + desc->flags = 0; - rv = crypto_hash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len); + rv = crypto_shash_setkey(connection->cram_hmac_tfm, (u8 *)secret, key_len); if (rv) { - drbd_err(connection, "crypto_hash_setkey() failed with %d\n", rv); + drbd_err(connection, "crypto_shash_setkey() failed with %d\n", rv); rv = -1; goto fail; } @@ -5011,7 +5010,7 @@ static int drbd_do_auth(struct drbd_connection *connection) goto fail; } - resp_size = crypto_hash_digestsize(connection->cram_hmac_tfm); + resp_size = crypto_shash_digestsize(connection->cram_hmac_tfm); response = kmalloc(resp_size, GFP_NOIO); if (response == NULL) { drbd_err(connection, "kmalloc of response failed\n"); @@ -5019,10 +5018,7 @@ static int drbd_do_auth(struct drbd_connection *connection) goto fail; } - sg_init_table(&sg, 1); - sg_set_buf(&sg, peers_ch, pi.size); - - rv = crypto_hash_digest(&desc, &sg, sg.length, response); + rv = crypto_shash_digest(desc, peers_ch, pi.size, response); if (rv) { drbd_err(connection, "crypto_hash_digest() failed with %d\n", rv); rv = -1; @@ -5070,9 +5066,8 @@ static int drbd_do_auth(struct drbd_connection *connection) goto fail; } - sg_set_buf(&sg, my_challenge, CHALLENGE_LEN); - - rv = crypto_hash_digest(&desc, &sg, sg.length, right_response); + rv = crypto_shash_digest(desc, my_challenge, CHALLENGE_LEN, + right_response); if (rv) { drbd_err(connection, "crypto_hash_digest() failed with %d\n", rv); rv = -1; @@ -5091,6 +5086,7 @@ static int drbd_do_auth(struct drbd_connection *connection) kfree(peers_ch); kfree(response); kfree(right_response); + shash_desc_zero(desc); return rv; } diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index eff716c27b1f..4d87499f0d54 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -274,51 +274,56 @@ void drbd_request_endio(struct bio *bio) complete_master_bio(device, &m); } -void drbd_csum_ee(struct crypto_hash *tfm, struct drbd_peer_request *peer_req, void *digest) +void drbd_csum_ee(struct crypto_ahash *tfm, struct drbd_peer_request *peer_req, void *digest) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm); struct scatterlist sg; struct page *page = peer_req->pages; struct page *tmp; unsigned len; - desc.tfm = tfm; - desc.flags = 0; + ahash_request_set_tfm(req, tfm); + ahash_request_set_callback(req, 0, NULL, NULL); sg_init_table(&sg, 1); - crypto_hash_init(&desc); + crypto_ahash_init(req); while ((tmp = page_chain_next(page))) { /* all but the last page will be fully used */ sg_set_page(&sg, page, PAGE_SIZE, 0); - crypto_hash_update(&desc, &sg, sg.length); + ahash_request_set_crypt(req, &sg, NULL, sg.length); + crypto_ahash_update(req); page = tmp; } /* and now the last, possibly only partially used page */ len = peer_req->i.size & (PAGE_SIZE - 1); sg_set_page(&sg, page, len ?: PAGE_SIZE, 0); - crypto_hash_update(&desc, &sg, sg.length); - crypto_hash_final(&desc, digest); + ahash_request_set_crypt(req, &sg, digest, sg.length); + crypto_ahash_finup(req); + ahash_request_zero(req); } -void drbd_csum_bio(struct crypto_hash *tfm, struct bio *bio, void *digest) +void drbd_csum_bio(struct crypto_ahash *tfm, struct bio *bio, void *digest) { - struct hash_desc desc; + AHASH_REQUEST_ON_STACK(req, tfm); struct scatterlist sg; struct bio_vec bvec; struct bvec_iter iter; - desc.tfm = tfm; - desc.flags = 0; + ahash_request_set_tfm(req, tfm); + ahash_request_set_callback(req, 0, NULL, NULL); sg_init_table(&sg, 1); - crypto_hash_init(&desc); + crypto_ahash_init(req); bio_for_each_segment(bvec, bio, iter) { sg_set_page(&sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset); - crypto_hash_update(&desc, &sg, sg.length); + ahash_request_set_crypt(req, &sg, NULL, sg.length); + crypto_ahash_update(req); } - crypto_hash_final(&desc, digest); + ahash_request_set_crypt(req, NULL, digest, 0); + crypto_ahash_final(req); + ahash_request_zero(req); } /* MAYBE merge common code with w_e_end_ov_req */ @@ -337,7 +342,7 @@ static int w_e_send_csum(struct drbd_work *w, int cancel) if (unlikely((peer_req->flags & EE_WAS_ERROR) != 0)) goto out; - digest_size = crypto_hash_digestsize(peer_device->connection->csums_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->csums_tfm); digest = kmalloc(digest_size, GFP_NOIO); if (digest) { sector_t sector = peer_req->i.sector; @@ -1113,7 +1118,7 @@ int w_e_end_csum_rs_req(struct drbd_work *w, int cancel) * a real fix would be much more involved, * introducing more locking mechanisms */ if (peer_device->connection->csums_tfm) { - digest_size = crypto_hash_digestsize(peer_device->connection->csums_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->csums_tfm); D_ASSERT(device, digest_size == di->digest_size); digest = kmalloc(digest_size, GFP_NOIO); } @@ -1163,7 +1168,7 @@ int w_e_end_ov_req(struct drbd_work *w, int cancel) if (unlikely(cancel)) goto out; - digest_size = crypto_hash_digestsize(peer_device->connection->verify_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->verify_tfm); digest = kmalloc(digest_size, GFP_NOIO); if (!digest) { err = 1; /* terminate the connection in case the allocation failed */ @@ -1235,7 +1240,7 @@ int w_e_end_ov_reply(struct drbd_work *w, int cancel) di = peer_req->digest; if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) { - digest_size = crypto_hash_digestsize(peer_device->connection->verify_tfm); + digest_size = crypto_ahash_digestsize(peer_device->connection->verify_tfm); digest = kmalloc(digest_size, GFP_NOIO); if (digest) { drbd_csum_ee(peer_device->connection->verify_tfm, peer_req, digest); -- cgit From 4a31340b36302d46207c6bb54d103d9fb568e916 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:31 +0800 Subject: nfc: s3fwrn5: Use shash This patch replaces uses of the long obsolete hash interface with shash. Signed-off-by: Herbert Xu --- drivers/nfc/s3fwrn5/firmware.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c index 64a90252c57f..5f97da1947e3 100644 --- a/drivers/nfc/s3fwrn5/firmware.c +++ b/drivers/nfc/s3fwrn5/firmware.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include "s3fwrn5.h" @@ -429,8 +429,7 @@ int s3fwrn5_fw_download(struct s3fwrn5_fw_info *fw_info) { struct s3fwrn5_fw_image *fw = &fw_info->fw; u8 hash_data[SHA1_DIGEST_SIZE]; - struct scatterlist sg; - struct hash_desc desc; + struct crypto_shash *tfm; u32 image_size, off; int ret; @@ -438,12 +437,31 @@ int s3fwrn5_fw_download(struct s3fwrn5_fw_info *fw_info) /* Compute SHA of firmware data */ - sg_init_one(&sg, fw->image, image_size); - desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); - crypto_hash_init(&desc); - crypto_hash_update(&desc, &sg, image_size); - crypto_hash_final(&desc, hash_data); - crypto_free_hash(desc.tfm); + tfm = crypto_alloc_shash("sha1", 0, 0); + if (IS_ERR(tfm)) { + ret = PTR_ERR(tfm); + dev_err(&fw_info->ndev->nfc_dev->dev, + "Cannot allocate shash (code=%d)\n", ret); + goto out; + } + + { + SHASH_DESC_ON_STACK(desc, tfm); + + desc->tfm = tfm; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + ret = crypto_shash_digest(desc, fw->image, image_size, + hash_data); + shash_desc_zero(desc); + } + + crypto_free_shash(tfm); + if (ret) { + dev_err(&fw_info->ndev->nfc_dev->dev, + "Cannot compute hash (code=%d)\n", ret); + goto out; + } /* Firmware update process */ -- cgit From 5d6ac29b9ebf27bb78ab1984371c672c5a975565 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:41 +0800 Subject: iscsi_tcp: Use ahash This patch replaces uses of the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Reviewed-by: Mike Christie --- drivers/scsi/iscsi_tcp.c | 54 +++++++++++++++++++++++++++------------------ drivers/scsi/iscsi_tcp.h | 4 ++-- drivers/scsi/libiscsi_tcp.c | 29 ++++++++++++++---------- include/scsi/libiscsi_tcp.h | 13 ++++++----- 4 files changed, 58 insertions(+), 42 deletions(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0b8af186e707..2e4c82f8329c 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -26,12 +26,12 @@ * Zhenyu Wang */ +#include #include #include #include #include #include -#include #include #include #include @@ -428,7 +428,7 @@ static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, * sufficient room. */ if (conn->hdrdgst_en) { - iscsi_tcp_dgst_header(&tcp_sw_conn->tx_hash, hdr, hdrlen, + iscsi_tcp_dgst_header(tcp_sw_conn->tx_hash, hdr, hdrlen, hdr + hdrlen); hdrlen += ISCSI_DIGEST_SIZE; } @@ -454,7 +454,7 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; - struct hash_desc *tx_hash = NULL; + struct ahash_request *tx_hash = NULL; unsigned int hdr_spec_len; ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s\n", offset, len, @@ -467,7 +467,7 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg, WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len)); if (conn->datadgst_en) - tx_hash = &tcp_sw_conn->tx_hash; + tx_hash = tcp_sw_conn->tx_hash; return iscsi_segment_seek_sg(&tcp_sw_conn->out.data_segment, sg, count, offset, len, @@ -480,7 +480,7 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data, { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; - struct hash_desc *tx_hash = NULL; + struct ahash_request *tx_hash = NULL; unsigned int hdr_spec_len; ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s\n", len, conn->datadgst_en ? @@ -492,7 +492,7 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data, WARN_ON(iscsi_padded(len) != iscsi_padded(hdr_spec_len)); if (conn->datadgst_en) - tx_hash = &tcp_sw_conn->tx_hash; + tx_hash = tcp_sw_conn->tx_hash; iscsi_segment_init_linear(&tcp_sw_conn->out.data_segment, data, len, NULL, tx_hash); @@ -543,6 +543,7 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn; struct iscsi_tcp_conn *tcp_conn; struct iscsi_sw_tcp_conn *tcp_sw_conn; + struct crypto_ahash *tfm; cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*tcp_sw_conn), conn_idx); @@ -552,23 +553,28 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, tcp_conn = conn->dd_data; tcp_sw_conn = tcp_conn->dd_data; - tcp_sw_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - tcp_sw_conn->tx_hash.flags = 0; - if (IS_ERR(tcp_sw_conn->tx_hash.tfm)) + tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) goto free_conn; - tcp_sw_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - tcp_sw_conn->rx_hash.flags = 0; - if (IS_ERR(tcp_sw_conn->rx_hash.tfm)) - goto free_tx_tfm; - tcp_conn->rx_hash = &tcp_sw_conn->rx_hash; + tcp_sw_conn->tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!tcp_sw_conn->tx_hash) + goto free_tfm; + ahash_request_set_callback(tcp_sw_conn->tx_hash, 0, NULL, NULL); + + tcp_sw_conn->rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!tcp_sw_conn->rx_hash) + goto free_tx_hash; + ahash_request_set_callback(tcp_sw_conn->rx_hash, 0, NULL, NULL); + + tcp_conn->rx_hash = tcp_sw_conn->rx_hash; return cls_conn; -free_tx_tfm: - crypto_free_hash(tcp_sw_conn->tx_hash.tfm); +free_tx_hash: + ahash_request_free(tcp_sw_conn->tx_hash); +free_tfm: + crypto_free_ahash(tfm); free_conn: iscsi_conn_printk(KERN_ERR, conn, "Could not create connection due to crc32c " @@ -607,10 +613,14 @@ static void iscsi_sw_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) iscsi_sw_tcp_release_conn(conn); - if (tcp_sw_conn->tx_hash.tfm) - crypto_free_hash(tcp_sw_conn->tx_hash.tfm); - if (tcp_sw_conn->rx_hash.tfm) - crypto_free_hash(tcp_sw_conn->rx_hash.tfm); + ahash_request_free(tcp_sw_conn->rx_hash); + if (tcp_sw_conn->tx_hash) { + struct crypto_ahash *tfm; + + tfm = crypto_ahash_reqtfm(tcp_sw_conn->tx_hash); + ahash_request_free(tcp_sw_conn->tx_hash); + crypto_free_ahash(tfm); + } iscsi_tcp_conn_teardown(cls_conn); } diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index f42ecb238af5..06d42d00a323 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h @@ -45,8 +45,8 @@ struct iscsi_sw_tcp_conn { void (*old_write_space)(struct sock *); /* data and header digests */ - struct hash_desc tx_hash; /* CRC32C (Tx) */ - struct hash_desc rx_hash; /* CRC32C (Rx) */ + struct ahash_request *tx_hash; /* CRC32C (Tx) */ + struct ahash_request *rx_hash; /* CRC32C (Rx) */ /* MIB custom statistics */ uint32_t sendpage_failures_cnt; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 60cb6dc3c6f0..63a1d69ff515 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -26,13 +26,13 @@ * Zhenyu Wang */ +#include #include #include #include #include #include #include -#include #include #include #include @@ -214,7 +214,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, } else sg_init_one(&sg, segment->data + segment->copied, copied); - crypto_hash_update(segment->hash, &sg, copied); + ahash_request_set_crypt(segment->hash, &sg, NULL, copied); + crypto_ahash_update(segment->hash); } segment->copied += copied; @@ -260,7 +261,9 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn, * is completely handled in hdr done function. */ if (segment->hash) { - crypto_hash_final(segment->hash, segment->digest); + ahash_request_set_crypt(segment->hash, NULL, + segment->digest, 0); + crypto_ahash_final(segment->hash); iscsi_tcp_segment_splice_digest(segment, recv ? segment->recv_digest : segment->digest); return 0; @@ -310,13 +313,14 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn, } inline void -iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, size_t hdrlen, - unsigned char digest[ISCSI_DIGEST_SIZE]) +iscsi_tcp_dgst_header(struct ahash_request *hash, const void *hdr, + size_t hdrlen, unsigned char digest[ISCSI_DIGEST_SIZE]) { struct scatterlist sg; sg_init_one(&sg, hdr, hdrlen); - crypto_hash_digest(hash, &sg, hdrlen, digest); + ahash_request_set_crypt(hash, &sg, digest, hdrlen); + crypto_ahash_digest(hash); } EXPORT_SYMBOL_GPL(iscsi_tcp_dgst_header); @@ -341,7 +345,7 @@ iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn, */ static inline void __iscsi_segment_init(struct iscsi_segment *segment, size_t size, - iscsi_segment_done_fn_t *done, struct hash_desc *hash) + iscsi_segment_done_fn_t *done, struct ahash_request *hash) { memset(segment, 0, sizeof(*segment)); segment->total_size = size; @@ -349,14 +353,14 @@ __iscsi_segment_init(struct iscsi_segment *segment, size_t size, if (hash) { segment->hash = hash; - crypto_hash_init(hash); + crypto_ahash_init(hash); } } inline void iscsi_segment_init_linear(struct iscsi_segment *segment, void *data, size_t size, iscsi_segment_done_fn_t *done, - struct hash_desc *hash) + struct ahash_request *hash) { __iscsi_segment_init(segment, size, done, hash); segment->data = data; @@ -368,7 +372,8 @@ inline int iscsi_segment_seek_sg(struct iscsi_segment *segment, struct scatterlist *sg_list, unsigned int sg_count, unsigned int offset, size_t size, - iscsi_segment_done_fn_t *done, struct hash_desc *hash) + iscsi_segment_done_fn_t *done, + struct ahash_request *hash) { struct scatterlist *sg; unsigned int i; @@ -431,7 +436,7 @@ static void iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn) { struct iscsi_conn *conn = tcp_conn->iscsi_conn; - struct hash_desc *rx_hash = NULL; + struct ahash_request *rx_hash = NULL; if (conn->datadgst_en && !(conn->session->tt->caps & CAP_DIGEST_OFFLOAD)) @@ -686,7 +691,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) if (tcp_conn->in.datalen) { struct iscsi_tcp_task *tcp_task = task->dd_data; - struct hash_desc *rx_hash = NULL; + struct ahash_request *rx_hash = NULL; struct scsi_data_buffer *sdb = scsi_in(task->sc); /* diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h index 2a7aa75dd009..30520d5ee3d1 100644 --- a/include/scsi/libiscsi_tcp.h +++ b/include/scsi/libiscsi_tcp.h @@ -26,7 +26,7 @@ struct iscsi_tcp_conn; struct iscsi_segment; struct sk_buff; -struct hash_desc; +struct ahash_request; typedef int iscsi_segment_done_fn_t(struct iscsi_tcp_conn *, struct iscsi_segment *); @@ -38,7 +38,7 @@ struct iscsi_segment { unsigned int total_size; unsigned int total_copied; - struct hash_desc *hash; + struct ahash_request *hash; unsigned char padbuf[ISCSI_PAD_LEN]; unsigned char recv_digest[ISCSI_DIGEST_SIZE]; unsigned char digest[ISCSI_DIGEST_SIZE]; @@ -73,7 +73,7 @@ struct iscsi_tcp_conn { /* control data */ struct iscsi_tcp_recv in; /* TCP receive context */ /* CRC32C (Rx) LLD should set this is they do not offload */ - struct hash_desc *rx_hash; + struct ahash_request *rx_hash; }; struct iscsi_tcp_task { @@ -111,15 +111,16 @@ extern void iscsi_tcp_segment_unmap(struct iscsi_segment *segment); extern void iscsi_segment_init_linear(struct iscsi_segment *segment, void *data, size_t size, iscsi_segment_done_fn_t *done, - struct hash_desc *hash); + struct ahash_request *hash); extern int iscsi_segment_seek_sg(struct iscsi_segment *segment, struct scatterlist *sg_list, unsigned int sg_count, unsigned int offset, size_t size, - iscsi_segment_done_fn_t *done, struct hash_desc *hash); + iscsi_segment_done_fn_t *done, + struct ahash_request *hash); /* digest helpers */ -extern void iscsi_tcp_dgst_header(struct hash_desc *hash, const void *hdr, +extern void iscsi_tcp_dgst_header(struct ahash_request *hash, const void *hdr, size_t hdrlen, unsigned char digest[ISCSI_DIGEST_SIZE]); extern struct iscsi_cls_conn * -- cgit From 69110e3cedbb8aad1c70d91ed58a9f4f0ed9eec6 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:19:52 +0800 Subject: iscsi-target: Use shash and ahash This patch replaces uses of the long obsolete hash interface with either shash (for non-SG users) or ahash. Signed-off-by: Herbert Xu --- drivers/target/iscsi/iscsi_target.c | 86 ++++++++++++++------------- drivers/target/iscsi/iscsi_target_auth.c | 98 ++++++++++++------------------- drivers/target/iscsi/iscsi_target_login.c | 45 +++++++++----- include/target/iscsi/iscsi_target_core.h | 4 +- 4 files changed, 113 insertions(+), 120 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 576a7a43470c..961202f4e9aa 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -16,9 +16,9 @@ * GNU General Public License for more details. ******************************************************************************/ +#include #include #include -#include #include #include #include @@ -1190,7 +1190,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } static u32 iscsit_do_crypto_hash_sg( - struct hash_desc *hash, + struct ahash_request *hash, struct iscsi_cmd *cmd, u32 data_offset, u32 data_length, @@ -1201,7 +1201,7 @@ static u32 iscsit_do_crypto_hash_sg( struct scatterlist *sg; unsigned int page_off; - crypto_hash_init(hash); + crypto_ahash_init(hash); sg = cmd->first_data_sg; page_off = cmd->first_data_sg_off; @@ -1209,7 +1209,8 @@ static u32 iscsit_do_crypto_hash_sg( while (data_length) { u32 cur_len = min_t(u32, data_length, (sg->length - page_off)); - crypto_hash_update(hash, sg, cur_len); + ahash_request_set_crypt(hash, sg, NULL, cur_len); + crypto_ahash_update(hash); data_length -= cur_len; page_off = 0; @@ -1221,33 +1222,34 @@ static u32 iscsit_do_crypto_hash_sg( struct scatterlist pad_sg; sg_init_one(&pad_sg, pad_bytes, padding); - crypto_hash_update(hash, &pad_sg, padding); + ahash_request_set_crypt(hash, &pad_sg, (u8 *)&data_crc, + padding); + crypto_ahash_finup(hash); + } else { + ahash_request_set_crypt(hash, NULL, (u8 *)&data_crc, 0); + crypto_ahash_final(hash); } - crypto_hash_final(hash, (u8 *) &data_crc); return data_crc; } static void iscsit_do_crypto_hash_buf( - struct hash_desc *hash, + struct ahash_request *hash, const void *buf, u32 payload_length, u32 padding, u8 *pad_bytes, u8 *data_crc) { - struct scatterlist sg; + struct scatterlist sg[2]; - crypto_hash_init(hash); + sg_init_table(sg, ARRAY_SIZE(sg)); + sg_set_buf(sg, buf, payload_length); + sg_set_buf(sg + 1, pad_bytes, padding); - sg_init_one(&sg, buf, payload_length); - crypto_hash_update(hash, &sg, payload_length); + ahash_request_set_crypt(hash, sg, data_crc, payload_length + padding); - if (padding) { - sg_init_one(&sg, pad_bytes, padding); - crypto_hash_update(hash, &sg, padding); - } - crypto_hash_final(hash, data_crc); + crypto_ahash_digest(hash); } int @@ -1422,7 +1424,7 @@ iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (conn->conn_ops->DataDigest) { u32 data_crc; - data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd, + data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, be32_to_cpu(hdr->offset), payload_length, padding, cmd->pad_bytes); @@ -1682,7 +1684,7 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, ping_data, payload_length, padding, cmd->pad_bytes, (u8 *)&data_crc); @@ -2101,7 +2103,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, goto reject; if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, text_in, payload_length, padding, (u8 *)&pad_bytes, (u8 *)&data_crc); @@ -2440,7 +2442,7 @@ static int iscsit_handle_immediate_data( if (conn->conn_ops->DataDigest) { u32 data_crc; - data_crc = iscsit_do_crypto_hash_sg(&conn->conn_rx_hash, cmd, + data_crc = iscsit_do_crypto_hash_sg(conn->conn_rx_hash, cmd, cmd->write_data_done, length, padding, cmd->pad_bytes); @@ -2553,7 +2555,7 @@ static int iscsit_send_conn_drop_async_message( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); cmd->tx_size += ISCSI_CRC_LEN; @@ -2683,7 +2685,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->pdu, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -2711,7 +2713,7 @@ static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn) cmd->padding); } if (conn->conn_ops->DataDigest) { - cmd->data_crc = iscsit_do_crypto_hash_sg(&conn->conn_tx_hash, cmd, + cmd->data_crc = iscsit_do_crypto_hash_sg(conn->conn_tx_hash, cmd, datain.offset, datain.length, cmd->padding, cmd->pad_bytes); iov[iov_count].iov_base = &cmd->data_crc; @@ -2857,7 +2859,7 @@ iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, &cmd->pdu[0], + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, &cmd->pdu[0], ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -2915,7 +2917,7 @@ static int iscsit_send_unsolicited_nopin( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); tx_size += ISCSI_CRC_LEN; @@ -2963,7 +2965,7 @@ iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -2993,7 +2995,7 @@ iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn) " padding bytes.\n", padding); } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->buf_ptr, cmd->buf_ptr_size, padding, (u8 *)&cmd->pad_bytes, (u8 *)&cmd->data_crc); @@ -3049,7 +3051,7 @@ static int iscsit_send_r2t( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN; @@ -3239,7 +3241,7 @@ static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn) } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->sense_buffer, (cmd->se_cmd.scsi_sense_length + padding), 0, NULL, (u8 *)&cmd->data_crc); @@ -3262,7 +3264,7 @@ static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->pdu, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->pdu, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -3332,7 +3334,7 @@ iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); cmd->iov_misc[0].iov_len += ISCSI_CRC_LEN; @@ -3601,7 +3603,7 @@ static int iscsit_send_text_rsp( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -3611,7 +3613,7 @@ static int iscsit_send_text_rsp( } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->buf_ptr, text_length, 0, NULL, (u8 *)&cmd->data_crc); @@ -3668,7 +3670,7 @@ static int iscsit_send_reject( if (conn->conn_ops->HeaderDigest) { u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN]; - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, hdr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, hdr, ISCSI_HDR_LEN, 0, NULL, (u8 *)header_digest); iov[0].iov_len += ISCSI_CRC_LEN; @@ -3678,7 +3680,7 @@ static int iscsit_send_reject( } if (conn->conn_ops->DataDigest) { - iscsit_do_crypto_hash_buf(&conn->conn_tx_hash, cmd->buf_ptr, + iscsit_do_crypto_hash_buf(conn->conn_tx_hash, cmd->buf_ptr, ISCSI_HDR_LEN, 0, NULL, (u8 *)&cmd->data_crc); iov[iov_count].iov_base = &cmd->data_crc; @@ -4145,7 +4147,7 @@ int iscsi_target_rx_thread(void *arg) goto transport_err; } - iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, buffer, ISCSI_HDR_LEN, 0, NULL, (u8 *)&checksum); @@ -4359,10 +4361,14 @@ int iscsit_close_connection( */ iscsit_check_conn_usage_count(conn); - if (conn->conn_rx_hash.tfm) - crypto_free_hash(conn->conn_rx_hash.tfm); - if (conn->conn_tx_hash.tfm) - crypto_free_hash(conn->conn_tx_hash.tfm); + ahash_request_free(conn->conn_tx_hash); + if (conn->conn_rx_hash) { + struct crypto_ahash *tfm; + + tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); + ahash_request_free(conn->conn_rx_hash); + crypto_free_ahash(tfm); + } free_cpumask_var(conn->conn_cpumask); diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index 47e249dccb5f..667406fcf4d3 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -16,9 +16,9 @@ * GNU General Public License for more details. ******************************************************************************/ +#include #include #include -#include #include #include @@ -185,9 +185,8 @@ static int chap_server_compute_md5( unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; size_t compare_len; struct iscsi_chap *chap = conn->auth_protocol; - struct crypto_hash *tfm; - struct hash_desc desc; - struct scatterlist sg; + struct crypto_shash *tfm = NULL; + struct shash_desc *desc = NULL; int auth_ret = -1, ret, challenge_len; memset(identifier, 0, 10); @@ -245,52 +244,47 @@ static int chap_server_compute_md5( pr_debug("[server] Got CHAP_R=%s\n", chap_r); chap_string_to_hex(client_digest, chap_r, strlen(chap_r)); - tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_shash("md5", 0, 0); if (IS_ERR(tfm)) { - pr_err("Unable to allocate struct crypto_hash\n"); + tfm = NULL; + pr_err("Unable to allocate struct crypto_shash\n"); goto out; } - desc.tfm = tfm; - desc.flags = 0; - ret = crypto_hash_init(&desc); - if (ret < 0) { - pr_err("crypto_hash_init() failed\n"); - crypto_free_hash(tfm); + desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL); + if (!desc) { + pr_err("Unable to allocate struct shash_desc\n"); goto out; } - sg_init_one(&sg, &chap->id, 1); - ret = crypto_hash_update(&desc, &sg, 1); + desc->tfm = tfm; + desc->flags = 0; + + ret = crypto_shash_init(desc); if (ret < 0) { - pr_err("crypto_hash_update() failed for id\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_init() failed\n"); goto out; } - sg_init_one(&sg, &auth->password, strlen(auth->password)); - ret = crypto_hash_update(&desc, &sg, strlen(auth->password)); + ret = crypto_shash_update(desc, &chap->id, 1); if (ret < 0) { - pr_err("crypto_hash_update() failed for password\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_update() failed for id\n"); goto out; } - sg_init_one(&sg, chap->challenge, CHAP_CHALLENGE_LENGTH); - ret = crypto_hash_update(&desc, &sg, CHAP_CHALLENGE_LENGTH); + ret = crypto_shash_update(desc, (char *)&auth->password, + strlen(auth->password)); if (ret < 0) { - pr_err("crypto_hash_update() failed for challenge\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_update() failed for password\n"); goto out; } - ret = crypto_hash_final(&desc, server_digest); + ret = crypto_shash_finup(desc, chap->challenge, + CHAP_CHALLENGE_LENGTH, server_digest); if (ret < 0) { - pr_err("crypto_hash_final() failed for server digest\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_finup() failed for challenge\n"); goto out; } - crypto_free_hash(tfm); chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE); pr_debug("[server] MD5 Server Digest: %s\n", response); @@ -306,9 +300,8 @@ static int chap_server_compute_md5( * authentication is not enabled. */ if (!auth->authenticate_target) { - kfree(challenge); - kfree(challenge_binhex); - return 0; + auth_ret = 0; + goto out; } /* * Get CHAP_I. @@ -372,58 +365,37 @@ static int chap_server_compute_md5( /* * Generate CHAP_N and CHAP_R for mutual authentication. */ - tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - pr_err("Unable to allocate struct crypto_hash\n"); - goto out; - } - desc.tfm = tfm; - desc.flags = 0; - - ret = crypto_hash_init(&desc); + ret = crypto_shash_init(desc); if (ret < 0) { - pr_err("crypto_hash_init() failed\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_init() failed\n"); goto out; } /* To handle both endiannesses */ id_as_uchar = id; - sg_init_one(&sg, &id_as_uchar, 1); - ret = crypto_hash_update(&desc, &sg, 1); + ret = crypto_shash_update(desc, &id_as_uchar, 1); if (ret < 0) { - pr_err("crypto_hash_update() failed for id\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_update() failed for id\n"); goto out; } - sg_init_one(&sg, auth->password_mutual, - strlen(auth->password_mutual)); - ret = crypto_hash_update(&desc, &sg, strlen(auth->password_mutual)); + ret = crypto_shash_update(desc, auth->password_mutual, + strlen(auth->password_mutual)); if (ret < 0) { - pr_err("crypto_hash_update() failed for" + pr_err("crypto_shash_update() failed for" " password_mutual\n"); - crypto_free_hash(tfm); goto out; } /* * Convert received challenge to binary hex. */ - sg_init_one(&sg, challenge_binhex, challenge_len); - ret = crypto_hash_update(&desc, &sg, challenge_len); + ret = crypto_shash_finup(desc, challenge_binhex, challenge_len, + digest); if (ret < 0) { - pr_err("crypto_hash_update() failed for ma challenge\n"); - crypto_free_hash(tfm); + pr_err("crypto_shash_finup() failed for ma challenge\n"); goto out; } - ret = crypto_hash_final(&desc, digest); - if (ret < 0) { - pr_err("crypto_hash_final() failed for ma digest\n"); - crypto_free_hash(tfm); - goto out; - } - crypto_free_hash(tfm); /* * Generate CHAP_N and CHAP_R. */ @@ -440,6 +412,8 @@ static int chap_server_compute_md5( pr_debug("[server] Sending CHAP_R=0x%s\n", response); auth_ret = 0; out: + kzfree(desc); + crypto_free_shash(tfm); kfree(challenge); kfree(challenge_binhex); return auth_ret; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 96e78c823d13..8436d56c5f0c 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -16,9 +16,9 @@ * GNU General Public License for more details. ******************************************************************************/ +#include #include #include -#include #include #include #include @@ -115,27 +115,36 @@ out_login: */ int iscsi_login_setup_crypto(struct iscsi_conn *conn) { + struct crypto_ahash *tfm; + /* * Setup slicing by CRC32C algorithm for RX and TX libcrypto contexts * which will default to crc32c_intel.ko for cpu_has_xmm4_2, or fallback * to software 1x8 byte slicing from crc32c.ko */ - conn->conn_rx_hash.flags = 0; - conn->conn_rx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(conn->conn_rx_hash.tfm)) { - pr_err("crypto_alloc_hash() failed for conn_rx_tfm\n"); + tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) { + pr_err("crypto_alloc_ahash() failed\n"); return -ENOMEM; } - conn->conn_tx_hash.flags = 0; - conn->conn_tx_hash.tfm = crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(conn->conn_tx_hash.tfm)) { - pr_err("crypto_alloc_hash() failed for conn_tx_tfm\n"); - crypto_free_hash(conn->conn_rx_hash.tfm); + conn->conn_rx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!conn->conn_rx_hash) { + pr_err("ahash_request_alloc() failed for conn_rx_hash\n"); + crypto_free_ahash(tfm); + return -ENOMEM; + } + ahash_request_set_callback(conn->conn_rx_hash, 0, NULL, NULL); + + conn->conn_tx_hash = ahash_request_alloc(tfm, GFP_KERNEL); + if (!conn->conn_tx_hash) { + pr_err("ahash_request_alloc() failed for conn_tx_hash\n"); + ahash_request_free(conn->conn_rx_hash); + conn->conn_rx_hash = NULL; + crypto_free_ahash(tfm); return -ENOMEM; } + ahash_request_set_callback(conn->conn_tx_hash, 0, NULL, NULL); return 0; } @@ -1174,10 +1183,14 @@ old_sess_out: iscsit_dec_session_usage_count(conn->sess); } - if (!IS_ERR(conn->conn_rx_hash.tfm)) - crypto_free_hash(conn->conn_rx_hash.tfm); - if (!IS_ERR(conn->conn_tx_hash.tfm)) - crypto_free_hash(conn->conn_tx_hash.tfm); + ahash_request_free(conn->conn_tx_hash); + if (conn->conn_rx_hash) { + struct crypto_ahash *tfm; + + tfm = crypto_ahash_reqtfm(conn->conn_rx_hash); + ahash_request_free(conn->conn_rx_hash); + crypto_free_ahash(tfm); + } free_cpumask_var(conn->conn_cpumask); diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 373d3342002b..c3371fa548cb 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h @@ -570,8 +570,8 @@ struct iscsi_conn { spinlock_t response_queue_lock; spinlock_t state_lock; /* libcrypto RX and TX contexts for crc32c */ - struct hash_desc conn_rx_hash; - struct hash_desc conn_tx_hash; + struct ahash_request *conn_rx_hash; + struct ahash_request *conn_tx_hash; /* Used for scheduling TX and RX connection kthreads */ cpumask_var_t conn_cpumask; unsigned int conn_rx_reset_cpumask:1; -- cgit From 1edb82d2021c7bae96509c03c4c5ef789f1e09a3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:20:02 +0800 Subject: nfsd: Use shash This patch replaces uses of the long obsolete hash interface with shash. Signed-off-by: Herbert Xu --- fs/nfsd/nfs4recover.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index dc8ebecf5618..195fe2668207 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -32,10 +32,10 @@ * */ +#include #include #include #include -#include #include #include #include @@ -104,29 +104,35 @@ static int nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname) { struct xdr_netobj cksum; - struct hash_desc desc; - struct scatterlist sg; + struct crypto_shash *tfm; int status; dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", clname->len, clname->data); - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) { - status = PTR_ERR(desc.tfm); + tfm = crypto_alloc_shash("md5", 0, 0); + if (IS_ERR(tfm)) { + status = PTR_ERR(tfm); goto out_no_tfm; } - cksum.len = crypto_hash_digestsize(desc.tfm); + cksum.len = crypto_shash_digestsize(tfm); cksum.data = kmalloc(cksum.len, GFP_KERNEL); if (cksum.data == NULL) { status = -ENOMEM; goto out; } - sg_init_one(&sg, clname->data, clname->len); + { + SHASH_DESC_ON_STACK(desc, tfm); + + desc->tfm = tfm; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + status = crypto_shash_digest(desc, clname->data, clname->len, + cksum.data); + shash_desc_zero(desc); + } - status = crypto_hash_digest(&desc, &sg, sg.length, cksum.data); if (status) goto out; @@ -135,7 +141,7 @@ nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname) status = 0; out: kfree(cksum.data); - crypto_free_hash(desc.tfm); + crypto_free_shash(tfm); out_no_tfm: return status; } -- cgit From 5821c769706561da81e9fcec4a6ca6dbbb2f30cb Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:20:12 +0800 Subject: sctp: Use shash This patch replaces uses of the long obsolete hash interface with shash. Signed-off-by: Herbert Xu Acked-by: David S. Miller --- include/net/sctp/auth.h | 4 ++-- include/net/sctp/structs.h | 6 +++--- net/sctp/auth.c | 36 ++++++++++++++++---------------- net/sctp/endpointola.c | 1 - net/sctp/sm_make_chunk.c | 51 ++++++++++++++++++++++++++-------------------- net/sctp/socket.c | 8 ++++---- 6 files changed, 57 insertions(+), 49 deletions(-) diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h index f2d58aa37a6f..9b9fb122b31f 100644 --- a/include/net/sctp/auth.h +++ b/include/net/sctp/auth.h @@ -31,12 +31,12 @@ #define __sctp_auth_h__ #include -#include struct sctp_endpoint; struct sctp_association; struct sctp_authkey; struct sctp_hmacalgo; +struct crypto_shash; /* * Define a generic struct that will hold all the info @@ -90,7 +90,7 @@ int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep, struct sctp_association *asoc, gfp_t gfp); int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp); -void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]); +void sctp_auth_destroy_hmacs(struct crypto_shash *auth_hmacs[]); struct sctp_hmac *sctp_auth_get_hmac(__u16 hmac_id); struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc); void sctp_auth_asoc_set_default_hmac(struct sctp_association *asoc, diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 20e72129be1c..6b1e3838667e 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -82,7 +82,7 @@ struct sctp_bind_addr; struct sctp_ulpq; struct sctp_ep_common; struct sctp_ssnmap; -struct crypto_hash; +struct crypto_shash; #include @@ -166,7 +166,7 @@ struct sctp_sock { struct sctp_pf *pf; /* Access to HMAC transform. */ - struct crypto_hash *hmac; + struct crypto_shash *hmac; char *sctp_hmac_alg; /* What is our base endpointer? */ @@ -1235,7 +1235,7 @@ struct sctp_endpoint { /* SCTP AUTH: array of the HMACs that will be allocated * we need this per association so that we don't serialize */ - struct crypto_hash **auth_hmacs; + struct crypto_shash **auth_hmacs; /* SCTP-AUTH: hmacs for the endpoint encoded into parameter */ struct sctp_hmac_algo_param *auth_hmacs_list; diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 1543e39f47c3..912eb1685a5d 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -27,9 +27,9 @@ * Vlad Yasevich */ +#include #include #include -#include #include #include #include @@ -448,7 +448,7 @@ struct sctp_shared_key *sctp_auth_get_shkey( */ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) { - struct crypto_hash *tfm = NULL; + struct crypto_shash *tfm = NULL; __u16 id; /* If AUTH extension is disabled, we are done */ @@ -462,9 +462,8 @@ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) return 0; /* Allocated the array of pointers to transorms */ - ep->auth_hmacs = kzalloc( - sizeof(struct crypto_hash *) * SCTP_AUTH_NUM_HMACS, - gfp); + ep->auth_hmacs = kzalloc(sizeof(struct crypto_shash *) * + SCTP_AUTH_NUM_HMACS, gfp); if (!ep->auth_hmacs) return -ENOMEM; @@ -483,8 +482,7 @@ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) continue; /* Allocate the ID */ - tfm = crypto_alloc_hash(sctp_hmac_list[id].hmac_name, 0, - CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_shash(sctp_hmac_list[id].hmac_name, 0, 0); if (IS_ERR(tfm)) goto out_err; @@ -500,7 +498,7 @@ out_err: } /* Destroy the hmac tfm array */ -void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]) +void sctp_auth_destroy_hmacs(struct crypto_shash *auth_hmacs[]) { int i; @@ -508,8 +506,7 @@ void sctp_auth_destroy_hmacs(struct crypto_hash *auth_hmacs[]) return; for (i = 0; i < SCTP_AUTH_NUM_HMACS; i++) { - if (auth_hmacs[i]) - crypto_free_hash(auth_hmacs[i]); + crypto_free_shash(auth_hmacs[i]); } kfree(auth_hmacs); } @@ -709,8 +706,7 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc, struct sctp_auth_chunk *auth, gfp_t gfp) { - struct scatterlist sg; - struct hash_desc desc; + struct crypto_shash *tfm; struct sctp_auth_bytes *asoc_key; __u16 key_id, hmac_id; __u8 *digest; @@ -742,16 +738,22 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc, /* set up scatter list */ end = skb_tail_pointer(skb); - sg_init_one(&sg, auth, end - (unsigned char *)auth); - desc.tfm = asoc->ep->auth_hmacs[hmac_id]; - desc.flags = 0; + tfm = asoc->ep->auth_hmacs[hmac_id]; digest = auth->auth_hdr.hmac; - if (crypto_hash_setkey(desc.tfm, &asoc_key->data[0], asoc_key->len)) + if (crypto_shash_setkey(tfm, &asoc_key->data[0], asoc_key->len)) goto free; - crypto_hash_digest(&desc, &sg, sg.length, digest); + { + SHASH_DESC_ON_STACK(desc, tfm); + + desc->tfm = tfm; + desc->flags = 0; + crypto_shash_digest(desc, (u8 *)auth, + end - (unsigned char *)auth, digest); + shash_desc_zero(desc); + } free: if (free_key) diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 2522a6175291..9d494e35e7f9 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -42,7 +42,6 @@ #include #include #include /* get_random_bytes() */ -#include #include #include #include diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 5d6a03fad378..1296e555fe29 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -45,6 +45,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -52,7 +53,6 @@ #include #include #include -#include #include #include @@ -1606,7 +1606,6 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, { sctp_cookie_param_t *retval; struct sctp_signed_cookie *cookie; - struct scatterlist sg; int headersize, bodysize; /* Header size is static data prior to the actual cookie, including @@ -1663,16 +1662,19 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len); if (sctp_sk(ep->base.sk)->hmac) { - struct hash_desc desc; + SHASH_DESC_ON_STACK(desc, sctp_sk(ep->base.sk)->hmac); + int err; /* Sign the message. */ - sg_init_one(&sg, &cookie->c, bodysize); - desc.tfm = sctp_sk(ep->base.sk)->hmac; - desc.flags = 0; - - if (crypto_hash_setkey(desc.tfm, ep->secret_key, - sizeof(ep->secret_key)) || - crypto_hash_digest(&desc, &sg, bodysize, cookie->signature)) + desc->tfm = sctp_sk(ep->base.sk)->hmac; + desc->flags = 0; + + err = crypto_shash_setkey(desc->tfm, ep->secret_key, + sizeof(ep->secret_key)) ?: + crypto_shash_digest(desc, (u8 *)&cookie->c, bodysize, + cookie->signature); + shash_desc_zero(desc); + if (err) goto free_cookie; } @@ -1697,12 +1699,10 @@ struct sctp_association *sctp_unpack_cookie( struct sctp_cookie *bear_cookie; int headersize, bodysize, fixed_size; __u8 *digest = ep->digest; - struct scatterlist sg; unsigned int len; sctp_scope_t scope; struct sk_buff *skb = chunk->skb; ktime_t kt; - struct hash_desc desc; /* Header size is static data prior to the actual cookie, including * any padding. @@ -1733,16 +1733,23 @@ struct sctp_association *sctp_unpack_cookie( goto no_hmac; /* Check the signature. */ - sg_init_one(&sg, bear_cookie, bodysize); - desc.tfm = sctp_sk(ep->base.sk)->hmac; - desc.flags = 0; - - memset(digest, 0x00, SCTP_SIGNATURE_SIZE); - if (crypto_hash_setkey(desc.tfm, ep->secret_key, - sizeof(ep->secret_key)) || - crypto_hash_digest(&desc, &sg, bodysize, digest)) { - *error = -SCTP_IERROR_NOMEM; - goto fail; + { + SHASH_DESC_ON_STACK(desc, sctp_sk(ep->base.sk)->hmac); + int err; + + desc->tfm = sctp_sk(ep->base.sk)->hmac; + desc->flags = 0; + + err = crypto_shash_setkey(desc->tfm, ep->secret_key, + sizeof(ep->secret_key)) ?: + crypto_shash_digest(desc, (u8 *)bear_cookie, bodysize, + digest); + shash_desc_zero(desc); + + if (err) { + *error = -SCTP_IERROR_NOMEM; + goto fail; + } } if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9bb80ec4c08f..4101c5b653d0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -52,6 +52,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -61,7 +62,6 @@ #include #include #include -#include #include #include #include @@ -4160,7 +4160,7 @@ static void sctp_destruct_sock(struct sock *sk) struct sctp_sock *sp = sctp_sk(sk); /* Free up the HMAC transform. */ - crypto_free_hash(sp->hmac); + crypto_free_shash(sp->hmac); inet_sock_destruct(sk); } @@ -6299,13 +6299,13 @@ static int sctp_listen_start(struct sock *sk, int backlog) { struct sctp_sock *sp = sctp_sk(sk); struct sctp_endpoint *ep = sp->ep; - struct crypto_hash *tfm = NULL; + struct crypto_shash *tfm = NULL; char alg[32]; /* Allocate HMAC for generating cookie. */ if (!sp->hmac && sp->sctp_hmac_alg) { sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg); - tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_shash(alg, 0, 0); if (IS_ERR(tfm)) { net_info_ratelimited("failed to load transform for %s: %ld\n", sp->sctp_hmac_alg, PTR_ERR(tfm)); -- cgit From cf80e0e47e0e7a8994dfadefec0e1395c622817a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 24 Jan 2016 21:20:23 +0800 Subject: tcp: Use ahash This patch replaces uses of the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Acked-by: David S. Miller --- include/net/tcp.h | 6 +----- net/ipv4/tcp.c | 41 ++++++++++++++++++++++++++--------------- net/ipv4/tcp_fastopen.c | 1 + net/ipv4/tcp_ipv4.c | 23 +++++++++++++---------- net/ipv6/tcp_ipv6.c | 23 +++++++++++++---------- 5 files changed, 54 insertions(+), 40 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 8ea19977ea53..2a5b3b8daee8 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -1325,9 +1324,6 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp) tp->retransmit_skb_hint = NULL; } -/* MD5 Signature */ -struct crypto_hash; - union tcp_md5_addr { struct in_addr a4; #if IS_ENABLED(CONFIG_IPV6) @@ -1376,7 +1372,7 @@ union tcp_md5sum_block { /* - pool: digest algorithm, hash description and scratch buffer */ struct tcp_md5sig_pool { - struct hash_desc md5_desc; + struct ahash_request *md5_req; union tcp_md5sum_block md5_blk; }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fd17eec93525..91ffef3a55d2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -247,6 +247,7 @@ #define pr_fmt(fmt) "TCP: " fmt +#include #include #include #include @@ -266,7 +267,6 @@ #include #include #include -#include #include #include @@ -2939,17 +2939,26 @@ static bool tcp_md5sig_pool_populated = false; static void __tcp_alloc_md5sig_pool(void) { + struct crypto_ahash *hash; int cpu; + hash = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR_OR_NULL(hash)) + return; + for_each_possible_cpu(cpu) { - if (!per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm) { - struct crypto_hash *hash; + struct ahash_request *req; - hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR_OR_NULL(hash)) - return; - per_cpu(tcp_md5sig_pool, cpu).md5_desc.tfm = hash; - } + if (per_cpu(tcp_md5sig_pool, cpu).md5_req) + continue; + + req = ahash_request_alloc(hash, GFP_KERNEL); + if (!req) + return; + + ahash_request_set_callback(req, 0, NULL, NULL); + + per_cpu(tcp_md5sig_pool, cpu).md5_req = req; } /* before setting tcp_md5sig_pool_populated, we must commit all writes * to memory. See smp_rmb() in tcp_get_md5sig_pool() @@ -2999,7 +3008,6 @@ int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, { struct scatterlist sg; struct tcphdr hdr; - int err; /* We are not allowed to change tcphdr, make a local copy */ memcpy(&hdr, th, sizeof(hdr)); @@ -3007,8 +3015,8 @@ int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, /* options aren't included in the hash */ sg_init_one(&sg, &hdr, sizeof(hdr)); - err = crypto_hash_update(&hp->md5_desc, &sg, sizeof(hdr)); - return err; + ahash_request_set_crypt(hp->md5_req, &sg, NULL, sizeof(hdr)); + return crypto_ahash_update(hp->md5_req); } EXPORT_SYMBOL(tcp_md5_hash_header); @@ -3017,7 +3025,7 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, { struct scatterlist sg; const struct tcphdr *tp = tcp_hdr(skb); - struct hash_desc *desc = &hp->md5_desc; + struct ahash_request *req = hp->md5_req; unsigned int i; const unsigned int head_data_len = skb_headlen(skb) > header_len ? skb_headlen(skb) - header_len : 0; @@ -3027,7 +3035,8 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, sg_init_table(&sg, 1); sg_set_buf(&sg, ((u8 *) tp) + header_len, head_data_len); - if (crypto_hash_update(desc, &sg, head_data_len)) + ahash_request_set_crypt(req, &sg, NULL, head_data_len); + if (crypto_ahash_update(req)) return 1; for (i = 0; i < shi->nr_frags; ++i) { @@ -3037,7 +3046,8 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, sg_set_page(&sg, page, skb_frag_size(f), offset_in_page(offset)); - if (crypto_hash_update(desc, &sg, skb_frag_size(f))) + ahash_request_set_crypt(req, &sg, NULL, skb_frag_size(f)); + if (crypto_ahash_update(req)) return 1; } @@ -3054,7 +3064,8 @@ int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, const struct tcp_md5sig_key *ke struct scatterlist sg; sg_init_one(&sg, key->key, key->keylen); - return crypto_hash_update(&hp->md5_desc, &sg, key->keylen); + ahash_request_set_crypt(hp->md5_req, &sg, NULL, key->keylen); + return crypto_ahash_update(hp->md5_req); } EXPORT_SYMBOL(tcp_md5_hash_key); diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 55be6ac70cff..4c65ca1a86d1 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5ced3e4013e3..85854db3e094 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -81,7 +81,7 @@ #include #include -#include +#include #include int sysctl_tcp_tw_reuse __read_mostly; @@ -1031,21 +1031,22 @@ static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, bp->len = cpu_to_be16(nbytes); sg_init_one(&sg, bp, sizeof(*bp)); - return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); + ahash_request_set_crypt(hp->md5_req, &sg, NULL, sizeof(*bp)); + return crypto_ahash_update(hp->md5_req); } static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, __be32 daddr, __be32 saddr, const struct tcphdr *th) { struct tcp_md5sig_pool *hp; - struct hash_desc *desc; + struct ahash_request *req; hp = tcp_get_md5sig_pool(); if (!hp) goto clear_hash_noput; - desc = &hp->md5_desc; + req = hp->md5_req; - if (crypto_hash_init(desc)) + if (crypto_ahash_init(req)) goto clear_hash; if (tcp_v4_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2)) goto clear_hash; @@ -1053,7 +1054,8 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, goto clear_hash; if (tcp_md5_hash_key(hp, key)) goto clear_hash; - if (crypto_hash_final(desc, md5_hash)) + ahash_request_set_crypt(req, NULL, md5_hash, 0); + if (crypto_ahash_final(req)) goto clear_hash; tcp_put_md5sig_pool(); @@ -1071,7 +1073,7 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, const struct sk_buff *skb) { struct tcp_md5sig_pool *hp; - struct hash_desc *desc; + struct ahash_request *req; const struct tcphdr *th = tcp_hdr(skb); __be32 saddr, daddr; @@ -1087,9 +1089,9 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, hp = tcp_get_md5sig_pool(); if (!hp) goto clear_hash_noput; - desc = &hp->md5_desc; + req = hp->md5_req; - if (crypto_hash_init(desc)) + if (crypto_ahash_init(req)) goto clear_hash; if (tcp_v4_md5_hash_pseudoheader(hp, daddr, saddr, skb->len)) @@ -1100,7 +1102,8 @@ int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key, goto clear_hash; if (tcp_md5_hash_key(hp, key)) goto clear_hash; - if (crypto_hash_final(desc, md5_hash)) + ahash_request_set_crypt(req, NULL, md5_hash, 0); + if (crypto_ahash_final(req)) goto clear_hash; tcp_put_md5sig_pool(); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 006396e31cb0..bd5597227b18 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -66,7 +66,7 @@ #include #include -#include +#include #include static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb); @@ -540,7 +540,8 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, bp->len = cpu_to_be32(nbytes); sg_init_one(&sg, bp, sizeof(*bp)); - return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); + ahash_request_set_crypt(hp->md5_req, &sg, NULL, sizeof(*bp)); + return crypto_ahash_update(hp->md5_req); } static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, @@ -548,14 +549,14 @@ static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, const struct tcphdr *th) { struct tcp_md5sig_pool *hp; - struct hash_desc *desc; + struct ahash_request *req; hp = tcp_get_md5sig_pool(); if (!hp) goto clear_hash_noput; - desc = &hp->md5_desc; + req = hp->md5_req; - if (crypto_hash_init(desc)) + if (crypto_ahash_init(req)) goto clear_hash; if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2)) goto clear_hash; @@ -563,7 +564,8 @@ static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, goto clear_hash; if (tcp_md5_hash_key(hp, key)) goto clear_hash; - if (crypto_hash_final(desc, md5_hash)) + ahash_request_set_crypt(req, NULL, md5_hash, 0); + if (crypto_ahash_final(req)) goto clear_hash; tcp_put_md5sig_pool(); @@ -583,7 +585,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, { const struct in6_addr *saddr, *daddr; struct tcp_md5sig_pool *hp; - struct hash_desc *desc; + struct ahash_request *req; const struct tcphdr *th = tcp_hdr(skb); if (sk) { /* valid for establish/request sockets */ @@ -598,9 +600,9 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, hp = tcp_get_md5sig_pool(); if (!hp) goto clear_hash_noput; - desc = &hp->md5_desc; + req = hp->md5_req; - if (crypto_hash_init(desc)) + if (crypto_ahash_init(req)) goto clear_hash; if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len)) @@ -611,7 +613,8 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, goto clear_hash; if (tcp_md5_hash_key(hp, key)) goto clear_hash; - if (crypto_hash_final(desc, md5_hash)) + ahash_request_set_crypt(req, NULL, md5_hash, 0); + if (crypto_ahash_final(req)) goto clear_hash; tcp_put_md5sig_pool(); -- cgit From 3095e8e366b471f3bcdbf21c9c72a45718ff8756 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 25 Jan 2016 10:29:33 +0800 Subject: eCryptfs: Use skcipher and shash This patch replaces uses of ablkcipher and blkcipher with skcipher, and the long obsolete hash interface with shash. Signed-off-by: Herbert Xu --- fs/ecryptfs/crypto.c | 107 ++++++++++----------- fs/ecryptfs/ecryptfs_kernel.h | 12 +-- fs/ecryptfs/inode.c | 1 - fs/ecryptfs/keystore.c | 218 ++++++++++++++++++++++++------------------ fs/ecryptfs/main.c | 1 - fs/ecryptfs/mmap.c | 1 - fs/ecryptfs/super.c | 1 - 7 files changed, 180 insertions(+), 161 deletions(-) diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 80d6901493cf..11255cbcb2db 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -23,6 +23,8 @@ * 02111-1307, USA. */ +#include +#include #include #include #include @@ -30,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -74,6 +75,19 @@ void ecryptfs_from_hex(char *dst, char *src, int dst_size) } } +static int ecryptfs_hash_digest(struct crypto_shash *tfm, + char *src, int len, char *dst) +{ + SHASH_DESC_ON_STACK(desc, tfm); + int err; + + desc->tfm = tfm; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + err = crypto_shash_digest(desc, src, len, dst); + shash_desc_zero(desc); + return err; +} + /** * ecryptfs_calculate_md5 - calculates the md5 of @src * @dst: Pointer to 16 bytes of allocated memory @@ -88,45 +102,26 @@ static int ecryptfs_calculate_md5(char *dst, struct ecryptfs_crypt_stat *crypt_stat, char *src, int len) { - struct scatterlist sg; - struct hash_desc desc = { - .tfm = crypt_stat->hash_tfm, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; + struct crypto_shash *tfm; int rc = 0; mutex_lock(&crypt_stat->cs_hash_tfm_mutex); - sg_init_one(&sg, (u8 *)src, len); - if (!desc.tfm) { - desc.tfm = crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) { - rc = PTR_ERR(desc.tfm); + 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 = desc.tfm; - } - rc = crypto_hash_init(&desc); - if (rc) { - printk(KERN_ERR - "%s: Error initializing crypto hash; rc = [%d]\n", - __func__, rc); - goto out; + crypt_stat->hash_tfm = tfm; } - rc = crypto_hash_update(&desc, &sg, len); + rc = ecryptfs_hash_digest(tfm, src, len, dst); if (rc) { printk(KERN_ERR - "%s: Error updating crypto hash; rc = [%d]\n", - __func__, rc); - goto out; - } - rc = crypto_hash_final(&desc, dst); - if (rc) { - printk(KERN_ERR - "%s: Error finalizing crypto hash; rc = [%d]\n", + "%s: Error computing crypto hash; rc = [%d]\n", __func__, rc); goto out; } @@ -234,10 +229,8 @@ void ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) { struct ecryptfs_key_sig *key_sig, *key_sig_tmp; - if (crypt_stat->tfm) - crypto_free_ablkcipher(crypt_stat->tfm); - if (crypt_stat->hash_tfm) - crypto_free_hash(crypt_stat->hash_tfm); + crypto_free_skcipher(crypt_stat->tfm); + crypto_free_shash(crypt_stat->hash_tfm); list_for_each_entry_safe(key_sig, key_sig_tmp, &crypt_stat->keysig_list, crypt_stat_list) { list_del(&key_sig->crypt_stat_list); @@ -342,7 +335,7 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv, int op) { - struct ablkcipher_request *req = NULL; + struct skcipher_request *req = NULL; struct extent_crypt_result ecr; int rc = 0; @@ -358,20 +351,20 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, init_completion(&ecr.completion); mutex_lock(&crypt_stat->cs_tfm_mutex); - req = ablkcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); + req = skcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); if (!req) { mutex_unlock(&crypt_stat->cs_tfm_mutex); rc = -ENOMEM; goto out; } - ablkcipher_request_set_callback(req, + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, extent_crypt_complete, &ecr); /* Consider doing this once, when the file is opened */ if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { - rc = crypto_ablkcipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_skcipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", @@ -383,9 +376,9 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, crypt_stat->flags |= ECRYPTFS_KEY_SET; } mutex_unlock(&crypt_stat->cs_tfm_mutex); - ablkcipher_request_set_crypt(req, src_sg, dst_sg, size, iv); - rc = op == ENCRYPT ? crypto_ablkcipher_encrypt(req) : - crypto_ablkcipher_decrypt(req); + skcipher_request_set_crypt(req, src_sg, dst_sg, size, iv); + rc = op == ENCRYPT ? crypto_skcipher_encrypt(req) : + crypto_skcipher_decrypt(req); if (rc == -EINPROGRESS || rc == -EBUSY) { struct extent_crypt_result *ecr = req->base.data; @@ -394,7 +387,7 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, reinit_completion(&ecr->completion); } out: - ablkcipher_request_free(req); + skcipher_request_free(req); return rc; } @@ -622,7 +615,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) crypt_stat->cipher, "cbc"); if (rc) goto out_unlock; - crypt_stat->tfm = crypto_alloc_ablkcipher(full_alg_name, 0, 0); + crypt_stat->tfm = crypto_alloc_skcipher(full_alg_name, 0, 0); if (IS_ERR(crypt_stat->tfm)) { rc = PTR_ERR(crypt_stat->tfm); crypt_stat->tfm = NULL; @@ -631,7 +624,7 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) full_alg_name); goto out_free; } - crypto_ablkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); + crypto_skcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY); rc = 0; out_free: kfree(full_alg_name); @@ -1591,7 +1584,7 @@ out: * event, regardless of whether this function succeeds for fails. */ static int -ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, +ecryptfs_process_key_cipher(struct crypto_skcipher **key_tfm, char *cipher_name, size_t *key_size) { char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; @@ -1609,21 +1602,18 @@ ecryptfs_process_key_cipher(struct crypto_blkcipher **key_tfm, "ecb"); if (rc) goto out; - *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); + *key_tfm = crypto_alloc_skcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(*key_tfm)) { rc = PTR_ERR(*key_tfm); printk(KERN_ERR "Unable to allocate crypto cipher with name " "[%s]; rc = [%d]\n", full_alg_name, rc); goto out; } - crypto_blkcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); - if (*key_size == 0) { - struct blkcipher_alg *alg = crypto_blkcipher_alg(*key_tfm); - - *key_size = alg->max_keysize; - } + crypto_skcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); + if (*key_size == 0) + *key_size = crypto_skcipher_default_keysize(*key_tfm); get_random_bytes(dummy_key, *key_size); - rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size); + rc = crypto_skcipher_setkey(*key_tfm, dummy_key, *key_size); if (rc) { printk(KERN_ERR "Error attempting to set key of size [%zd] for " "cipher [%s]; rc = [%d]\n", *key_size, full_alg_name, @@ -1660,8 +1650,7 @@ int ecryptfs_destroy_crypto(void) list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list, key_tfm_list) { list_del(&key_tfm->key_tfm_list); - if (key_tfm->key_tfm) - crypto_free_blkcipher(key_tfm->key_tfm); + crypto_free_skcipher(key_tfm->key_tfm); kmem_cache_free(ecryptfs_key_tfm_cache, key_tfm); } mutex_unlock(&key_tfm_list_mutex); @@ -1747,7 +1736,7 @@ int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm) * Searches for cached item first, and creates new if not found. * Returns 0 on success, non-zero if adding new cipher failed */ -int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, +int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_skcipher **tfm, struct mutex **tfm_mutex, char *cipher_name) { @@ -2120,7 +2109,7 @@ out: int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, struct ecryptfs_mount_crypt_stat *mount_crypt_stat) { - struct blkcipher_desc desc; + struct crypto_skcipher *tfm; struct mutex *tfm_mutex; size_t cipher_blocksize; int rc; @@ -2130,7 +2119,7 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, return 0; } - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, + rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&tfm, &tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); if (unlikely(rc)) { (*namelen) = 0; @@ -2138,7 +2127,7 @@ int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, } mutex_lock(tfm_mutex); - cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm); + cipher_blocksize = crypto_skcipher_blocksize(tfm); mutex_unlock(tfm_mutex); /* Return an exact amount for the common cases */ diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 7b39260c7bba..b7f81287c688 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -28,6 +28,7 @@ #ifndef ECRYPTFS_KERNEL_H #define ECRYPTFS_KERNEL_H +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #define ECRYPTFS_DEFAULT_IV_BYTES 16 #define ECRYPTFS_DEFAULT_EXTENT_SIZE 4096 @@ -233,9 +233,9 @@ struct ecryptfs_crypt_stat { size_t extent_shift; unsigned int extent_mask; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct crypto_ablkcipher *tfm; - struct crypto_hash *hash_tfm; /* Crypto context for generating - * the initialization vectors */ + struct crypto_skcipher *tfm; + struct crypto_shash *hash_tfm; /* Crypto context for generating + * the initialization vectors */ unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; @@ -309,7 +309,7 @@ struct ecryptfs_global_auth_tok { * keeps a list of crypto API contexts around to use when needed. */ struct ecryptfs_key_tfm { - struct crypto_blkcipher *key_tfm; + struct crypto_skcipher *key_tfm; size_t key_size; struct mutex key_tfm_mutex; struct list_head key_tfm_list; @@ -659,7 +659,7 @@ ecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, int ecryptfs_init_crypto(void); int ecryptfs_destroy_crypto(void); int ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm); -int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, +int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_skcipher **tfm, struct mutex **tfm_mutex, char *cipher_name); int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key, diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 4e685ac1024d..0a8f1b469a63 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 6bd67e2011f0..c5c84dfb5b3e 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -25,11 +25,12 @@ * 02111-1307, USA. */ +#include +#include #include #include #include #include -#include #include #include #include "ecryptfs_kernel.h" @@ -601,12 +602,13 @@ struct ecryptfs_write_tag_70_packet_silly_stack { struct ecryptfs_auth_tok *auth_tok; struct scatterlist src_sg[2]; struct scatterlist dst_sg[2]; - struct blkcipher_desc desc; + struct crypto_skcipher *skcipher_tfm; + struct skcipher_request *skcipher_req; char iv[ECRYPTFS_MAX_IV_BYTES]; char hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; char tmp_hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; - struct hash_desc hash_desc; - struct scatterlist hash_sg; + struct crypto_shash *hash_tfm; + struct shash_desc *hash_desc; }; /** @@ -629,14 +631,13 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, struct key *auth_tok_key = NULL; int rc = 0; - s = kmalloc(sizeof(*s), GFP_KERNEL); + s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) { printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); rc = -ENOMEM; goto out; } - s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; (*packet_size) = 0; rc = ecryptfs_find_auth_tok_for_sig( &auth_tok_key, @@ -649,7 +650,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, goto out; } rc = ecryptfs_get_tfm_and_mutex_for_cipher_name( - &s->desc.tfm, + &s->skcipher_tfm, &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); if (unlikely(rc)) { printk(KERN_ERR "Internal error whilst attempting to get " @@ -658,7 +659,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, goto out; } mutex_lock(s->tfm_mutex); - s->block_size = crypto_blkcipher_blocksize(s->desc.tfm); + s->block_size = crypto_skcipher_blocksize(s->skcipher_tfm); /* Plus one for the \0 separator between the random prefix * and the plaintext filename */ s->num_rand_bytes = (ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES + 1); @@ -691,6 +692,19 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, rc = -EINVAL; goto out_unlock; } + + s->skcipher_req = skcipher_request_alloc(s->skcipher_tfm, GFP_KERNEL); + if (!s->skcipher_req) { + printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " + "skcipher_request_alloc for %s\n", __func__, + crypto_skcipher_driver_name(s->skcipher_tfm)); + rc = -ENOMEM; + goto out_unlock; + } + + skcipher_request_set_callback(s->skcipher_req, + CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); + s->block_aligned_filename = kzalloc(s->block_aligned_filename_size, GFP_KERNEL); if (!s->block_aligned_filename) { @@ -700,7 +714,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, rc = -ENOMEM; goto out_unlock; } - s->i = 0; dest[s->i++] = ECRYPTFS_TAG_70_PACKET_TYPE; rc = ecryptfs_write_packet_length(&dest[s->i], (ECRYPTFS_SIG_SIZE @@ -738,40 +751,36 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, "password tokens\n", __func__); goto out_free_unlock; } - sg_init_one( - &s->hash_sg, - (u8 *)s->auth_tok->token.password.session_key_encryption_key, - s->auth_tok->token.password.session_key_encryption_key_bytes); - s->hash_desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - s->hash_desc.tfm = crypto_alloc_hash(ECRYPTFS_TAG_70_DIGEST, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(s->hash_desc.tfm)) { - rc = PTR_ERR(s->hash_desc.tfm); + s->hash_tfm = crypto_alloc_shash(ECRYPTFS_TAG_70_DIGEST, 0, 0); + if (IS_ERR(s->hash_tfm)) { + rc = PTR_ERR(s->hash_tfm); printk(KERN_ERR "%s: Error attempting to " "allocate hash crypto context; rc = [%d]\n", __func__, rc); goto out_free_unlock; } - rc = crypto_hash_init(&s->hash_desc); - if (rc) { - printk(KERN_ERR - "%s: Error initializing crypto hash; rc = [%d]\n", - __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_update( - &s->hash_desc, &s->hash_sg, - s->auth_tok->token.password.session_key_encryption_key_bytes); - if (rc) { - printk(KERN_ERR - "%s: Error updating crypto hash; rc = [%d]\n", - __func__, rc); + + s->hash_desc = kmalloc(sizeof(*s->hash_desc) + + crypto_shash_descsize(s->hash_tfm), GFP_KERNEL); + if (!s->hash_desc) { + printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " + "kmalloc [%zd] bytes\n", __func__, + sizeof(*s->hash_desc) + + crypto_shash_descsize(s->hash_tfm)); + rc = -ENOMEM; goto out_release_free_unlock; } - rc = crypto_hash_final(&s->hash_desc, s->hash); + + s->hash_desc->tfm = s->hash_tfm; + s->hash_desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + rc = crypto_shash_digest(s->hash_desc, + (u8 *)s->auth_tok->token.password.session_key_encryption_key, + s->auth_tok->token.password.session_key_encryption_key_bytes, + s->hash); if (rc) { printk(KERN_ERR - "%s: Error finalizing crypto hash; rc = [%d]\n", + "%s: Error computing crypto hash; rc = [%d]\n", __func__, rc); goto out_release_free_unlock; } @@ -780,27 +789,12 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, s->hash[(s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)]; if ((s->j % ECRYPTFS_TAG_70_DIGEST_SIZE) == (ECRYPTFS_TAG_70_DIGEST_SIZE - 1)) { - sg_init_one(&s->hash_sg, (u8 *)s->hash, - ECRYPTFS_TAG_70_DIGEST_SIZE); - rc = crypto_hash_init(&s->hash_desc); - if (rc) { - printk(KERN_ERR - "%s: Error initializing crypto hash; " - "rc = [%d]\n", __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_update(&s->hash_desc, &s->hash_sg, - ECRYPTFS_TAG_70_DIGEST_SIZE); + rc = crypto_shash_digest(s->hash_desc, (u8 *)s->hash, + ECRYPTFS_TAG_70_DIGEST_SIZE, + s->tmp_hash); if (rc) { printk(KERN_ERR - "%s: Error updating crypto hash; " - "rc = [%d]\n", __func__, rc); - goto out_release_free_unlock; - } - rc = crypto_hash_final(&s->hash_desc, s->tmp_hash); - if (rc) { - printk(KERN_ERR - "%s: Error finalizing crypto hash; " + "%s: Error computing crypto hash; " "rc = [%d]\n", __func__, rc); goto out_release_free_unlock; } @@ -834,10 +828,8 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, * of the IV here, so we just use 0's for the IV. Note the * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES * >= ECRYPTFS_MAX_IV_BYTES. */ - memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); - s->desc.info = s->iv; - rc = crypto_blkcipher_setkey( - s->desc.tfm, + rc = crypto_skcipher_setkey( + s->skcipher_tfm, s->auth_tok->token.password.session_key_encryption_key, mount_crypt_stat->global_default_fn_cipher_key_bytes); if (rc < 0) { @@ -850,8 +842,9 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, mount_crypt_stat->global_default_fn_cipher_key_bytes); goto out_release_free_unlock; } - rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg, - s->block_aligned_filename_size); + skcipher_request_set_crypt(s->skcipher_req, s->src_sg, s->dst_sg, + s->block_aligned_filename_size, s->iv); + rc = crypto_skcipher_encrypt(s->skcipher_req); if (rc) { printk(KERN_ERR "%s: Error attempting to encrypt filename; " "rc = [%d]\n", __func__, rc); @@ -861,7 +854,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, (*packet_size) = s->i; (*remaining_bytes) -= (*packet_size); out_release_free_unlock: - crypto_free_hash(s->hash_desc.tfm); + crypto_free_shash(s->hash_tfm); out_free_unlock: kzfree(s->block_aligned_filename); out_unlock: @@ -871,6 +864,8 @@ out: up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); } + skcipher_request_free(s->skcipher_req); + kzfree(s->hash_desc); kfree(s); return rc; } @@ -888,7 +883,8 @@ struct ecryptfs_parse_tag_70_packet_silly_stack { struct ecryptfs_auth_tok *auth_tok; struct scatterlist src_sg[2]; struct scatterlist dst_sg[2]; - struct blkcipher_desc desc; + struct crypto_skcipher *skcipher_tfm; + struct skcipher_request *skcipher_req; char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1]; char iv[ECRYPTFS_MAX_IV_BYTES]; char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; @@ -922,14 +918,13 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, (*packet_size) = 0; (*filename_size) = 0; (*filename) = NULL; - s = kmalloc(sizeof(*s), GFP_KERNEL); + s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) { printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); rc = -ENOMEM; goto out; } - s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) { printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " "at least [%d]\n", __func__, max_packet_size, @@ -992,7 +987,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, rc); goto out; } - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm, + rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->skcipher_tfm, &s->tfm_mutex, s->cipher_string); if (unlikely(rc)) { @@ -1030,12 +1025,23 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, __func__, rc, s->block_aligned_filename_size); goto out_free_unlock; } + + s->skcipher_req = skcipher_request_alloc(s->skcipher_tfm, GFP_KERNEL); + if (!s->skcipher_req) { + printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " + "skcipher_request_alloc for %s\n", __func__, + crypto_skcipher_driver_name(s->skcipher_tfm)); + rc = -ENOMEM; + goto out_free_unlock; + } + + skcipher_request_set_callback(s->skcipher_req, + CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); + /* The characters in the first block effectively do the job of * the IV here, so we just use 0's for the IV. Note the * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES * >= ECRYPTFS_MAX_IV_BYTES. */ - memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES); - s->desc.info = s->iv; /* TODO: Support other key modules than passphrase for * filename encryption */ if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { @@ -1044,8 +1050,8 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, "password tokens\n", __func__); goto out_free_unlock; } - rc = crypto_blkcipher_setkey( - s->desc.tfm, + rc = crypto_skcipher_setkey( + s->skcipher_tfm, s->auth_tok->token.password.session_key_encryption_key, mount_crypt_stat->global_default_fn_cipher_key_bytes); if (rc < 0) { @@ -1058,14 +1064,14 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, mount_crypt_stat->global_default_fn_cipher_key_bytes); goto out_free_unlock; } - rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg, - s->block_aligned_filename_size); + skcipher_request_set_crypt(s->skcipher_req, s->src_sg, s->dst_sg, + s->block_aligned_filename_size, s->iv); + rc = crypto_skcipher_decrypt(s->skcipher_req); if (rc) { printk(KERN_ERR "%s: Error attempting to decrypt filename; " "rc = [%d]\n", __func__, rc); goto out_free_unlock; } - s->i = 0; while (s->decrypted_filename[s->i] != '\0' && s->i < s->block_aligned_filename_size) s->i++; @@ -1108,6 +1114,7 @@ out: up_write(&(auth_tok_key->sem)); key_put(auth_tok_key); } + skcipher_request_free(s->skcipher_req); kfree(s); return rc; } @@ -1667,9 +1674,8 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, struct scatterlist dst_sg[2]; struct scatterlist src_sg[2]; struct mutex *tfm_mutex; - struct blkcipher_desc desc = { - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; + struct crypto_skcipher *tfm; + struct skcipher_request *req = NULL; int rc = 0; if (unlikely(ecryptfs_verbosity > 0)) { @@ -1680,7 +1686,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, auth_tok->token.password.session_key_encryption_key, auth_tok->token.password.session_key_encryption_key_bytes); } - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, + rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&tfm, &tfm_mutex, crypt_stat->cipher); if (unlikely(rc)) { printk(KERN_ERR "Internal error whilst attempting to get " @@ -1711,8 +1717,20 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, goto out; } mutex_lock(tfm_mutex); - rc = crypto_blkcipher_setkey( - desc.tfm, auth_tok->token.password.session_key_encryption_key, + req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + mutex_unlock(tfm_mutex); + printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " + "skcipher_request_alloc for %s\n", __func__, + crypto_skcipher_driver_name(tfm)); + rc = -ENOMEM; + goto out; + } + + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + rc = crypto_skcipher_setkey( + tfm, auth_tok->token.password.session_key_encryption_key, crypt_stat->key_size); if (unlikely(rc < 0)) { mutex_unlock(tfm_mutex); @@ -1720,8 +1738,10 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, rc = -EINVAL; goto out; } - rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, - auth_tok->session_key.encrypted_key_size); + skcipher_request_set_crypt(req, src_sg, dst_sg, + auth_tok->session_key.encrypted_key_size, + NULL); + rc = crypto_skcipher_decrypt(req); mutex_unlock(tfm_mutex); if (unlikely(rc)) { printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc); @@ -1738,6 +1758,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, crypt_stat->key_size); } out: + skcipher_request_free(req); return rc; } @@ -2191,16 +2212,14 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, size_t max_packet_size; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = crypt_stat->mount_crypt_stat; - struct blkcipher_desc desc = { - .tfm = NULL, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; + struct crypto_skcipher *tfm; + struct skcipher_request *req; int rc = 0; (*packet_size) = 0; ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature, ECRYPTFS_SIG_SIZE); - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, + rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&tfm, &tfm_mutex, crypt_stat->cipher); if (unlikely(rc)) { printk(KERN_ERR "Internal error whilst attempting to get " @@ -2209,12 +2228,11 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, goto out; } if (mount_crypt_stat->global_default_cipher_key_size == 0) { - struct blkcipher_alg *alg = crypto_blkcipher_alg(desc.tfm); - printk(KERN_WARNING "No key size specified at mount; " - "defaulting to [%d]\n", alg->max_keysize); + "defaulting to [%d]\n", + crypto_skcipher_default_keysize(tfm)); mount_crypt_stat->global_default_cipher_key_size = - alg->max_keysize; + crypto_skcipher_default_keysize(tfm); } if (crypt_stat->key_size == 0) crypt_stat->key_size = @@ -2284,20 +2302,36 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes, goto out; } mutex_lock(tfm_mutex); - rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_skcipher_setkey(tfm, session_key_encryption_key, + crypt_stat->key_size); if (rc < 0) { mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_ERR, "Error setting key for crypto " "context; rc = [%d]\n", rc); goto out; } + + req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) { + mutex_unlock(tfm_mutex); + ecryptfs_printk(KERN_ERR, "Out of kernel memory whilst " + "attempting to skcipher_request_alloc for " + "%s\n", crypto_skcipher_driver_name(tfm)); + rc = -ENOMEM; + goto out; + } + + skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + rc = 0; ecryptfs_printk(KERN_DEBUG, "Encrypting [%zd] bytes of the key\n", crypt_stat->key_size); - rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg, - (*key_rec).enc_key_size); + skcipher_request_set_crypt(req, src_sg, dst_sg, + (*key_rec).enc_key_size, NULL); + rc = crypto_skcipher_encrypt(req); mutex_unlock(tfm_mutex); + skcipher_request_free(req); if (rc) { printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); goto out; diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index e25b6b06bacf..8b0b4a73116d 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index c6ced4cbf0cf..1f5865263b3e 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index afa1b81c3418..77a486d3a51b 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include "ecryptfs_kernel.h" -- cgit From 10cff58c6772587f9df422dc1dfaca936c66be1f Mon Sep 17 00:00:00 2001 From: Megha Dey Date: Mon, 25 Jan 2016 16:46:09 -0800 Subject: crypto: sha1-mb - Add missing args_digest offset The _args_digest is defined as _args+_digest, both of which are the first members of 2 separate structures, effectively yielding _args_digest to have a value of zero. Thus, no errors have spawned yet due to this. To ensure sanity, adding the missing _args_digest offset to the sha1_mb_mgr_submit.S. Signed-off-by: Megha Dey Acked-by: Tim Chen Signed-off-by: Herbert Xu --- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S b/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S index 2ab9560b53c8..c420d89b175f 100644 --- a/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +++ b/arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S @@ -197,7 +197,7 @@ len_is_0: vpinsrd $1, _args_digest+1*32(state , idx, 4), %xmm0, %xmm0 vpinsrd $2, _args_digest+2*32(state , idx, 4), %xmm0, %xmm0 vpinsrd $3, _args_digest+3*32(state , idx, 4), %xmm0, %xmm0 - movl 4*32(state, idx, 4), DWORD_tmp + movl _args_digest+4*32(state, idx, 4), DWORD_tmp vmovdqu %xmm0, _result_digest(job_rax) movl DWORD_tmp, _result_digest+1*16(job_rax) -- cgit From 110492183c4b8f572b16fce096b9d78e2da30baf Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Tue, 26 Jan 2016 17:15:03 +0900 Subject: crypto: compress - remove unused pcomp interface It is unused now, so remove it. Signed-off-by: Joonsoo Kim Signed-off-by: Herbert Xu --- crypto/Kconfig | 19 -- crypto/Makefile | 2 - crypto/pcompress.c | 115 ----------- crypto/testmgr.c | 223 ---------------------- crypto/testmgr.h | 144 -------------- crypto/zlib.c | 381 ------------------------------------- include/crypto/compress.h | 145 -------------- include/crypto/internal/compress.h | 28 --- include/linux/crypto.h | 1 - 9 files changed, 1058 deletions(-) delete mode 100644 crypto/pcompress.c delete mode 100644 crypto/zlib.c delete mode 100644 include/crypto/compress.h delete mode 100644 include/crypto/internal/compress.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 7240821137fd..c80d34fc2f8c 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -84,15 +84,6 @@ config CRYPTO_RNG_DEFAULT tristate select CRYPTO_DRBG_MENU -config CRYPTO_PCOMP - tristate - select CRYPTO_PCOMP2 - select CRYPTO_ALGAPI - -config CRYPTO_PCOMP2 - tristate - select CRYPTO_ALGAPI2 - config CRYPTO_AKCIPHER2 tristate select CRYPTO_ALGAPI2 @@ -122,7 +113,6 @@ config CRYPTO_MANAGER2 select CRYPTO_AEAD2 select CRYPTO_HASH2 select CRYPTO_BLKCIPHER2 - select CRYPTO_PCOMP2 select CRYPTO_AKCIPHER2 config CRYPTO_USER @@ -1504,15 +1494,6 @@ config CRYPTO_DEFLATE You will most probably want this if using IPSec. -config CRYPTO_ZLIB - tristate "Zlib compression algorithm" - select CRYPTO_PCOMP - select ZLIB_INFLATE - select ZLIB_DEFLATE - select NLATTR - help - This is the zlib algorithm. - config CRYPTO_LZO tristate "LZO compression algorithm" select CRYPTO_ALGAPI diff --git a/crypto/Makefile b/crypto/Makefile index 2acdbbd30475..ffe18c9c9bf4 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -28,7 +28,6 @@ crypto_hash-y += ahash.o crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o -obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h @@ -99,7 +98,6 @@ obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o obj-$(CONFIG_CRYPTO_CHACHA20) += chacha20_generic.o obj-$(CONFIG_CRYPTO_POLY1305) += poly1305_generic.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o -obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o obj-$(CONFIG_CRYPTO_CRC32) += crc32.o diff --git a/crypto/pcompress.c b/crypto/pcompress.c deleted file mode 100644 index 7a13b4088857..000000000000 --- a/crypto/pcompress.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Cryptographic API. - * - * Partial (de)compression operations. - * - * Copyright 2008 Sony 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. - * - * 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 "internal.h" - - -static int crypto_pcomp_init(struct crypto_tfm *tfm, u32 type, u32 mask) -{ - return 0; -} - -static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm) -{ - return 0; -} - -#ifdef CONFIG_NET -static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg) -{ - struct crypto_report_comp rpcomp; - - strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type)); - if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS, - sizeof(struct crypto_report_comp), &rpcomp)) - goto nla_put_failure; - return 0; - -nla_put_failure: - return -EMSGSIZE; -} -#else -static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg) -{ - return -ENOSYS; -} -#endif - -static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg) - __attribute__ ((unused)); -static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg) -{ - seq_printf(m, "type : pcomp\n"); -} - -static const struct crypto_type crypto_pcomp_type = { - .extsize = crypto_alg_extsize, - .init = crypto_pcomp_init, - .init_tfm = crypto_pcomp_init_tfm, -#ifdef CONFIG_PROC_FS - .show = crypto_pcomp_show, -#endif - .report = crypto_pcomp_report, - .maskclear = ~CRYPTO_ALG_TYPE_MASK, - .maskset = CRYPTO_ALG_TYPE_MASK, - .type = CRYPTO_ALG_TYPE_PCOMPRESS, - .tfmsize = offsetof(struct crypto_pcomp, base), -}; - -struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type, - u32 mask) -{ - return crypto_alloc_tfm(alg_name, &crypto_pcomp_type, type, mask); -} -EXPORT_SYMBOL_GPL(crypto_alloc_pcomp); - -int crypto_register_pcomp(struct pcomp_alg *alg) -{ - struct crypto_alg *base = &alg->base; - - base->cra_type = &crypto_pcomp_type; - base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; - base->cra_flags |= CRYPTO_ALG_TYPE_PCOMPRESS; - - return crypto_register_alg(base); -} -EXPORT_SYMBOL_GPL(crypto_register_pcomp); - -int crypto_unregister_pcomp(struct pcomp_alg *alg) -{ - return crypto_unregister_alg(&alg->base); -} -EXPORT_SYMBOL_GPL(crypto_unregister_pcomp); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Partial (de)compression type"); -MODULE_AUTHOR("Sony Corporation"); diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 5c0963d17de7..cbd78c954844 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -96,13 +96,6 @@ struct comp_test_suite { } comp, decomp; }; -struct pcomp_test_suite { - struct { - struct pcomp_testvec *vecs; - unsigned int count; - } comp, decomp; -}; - struct hash_test_suite { struct hash_testvec *vecs; unsigned int count; @@ -133,7 +126,6 @@ struct alg_test_desc { struct aead_test_suite aead; struct cipher_test_suite cipher; struct comp_test_suite comp; - struct pcomp_test_suite pcomp; struct hash_test_suite hash; struct cprng_test_suite cprng; struct drbg_test_suite drbg; @@ -1293,183 +1285,6 @@ out: return ret; } -static int test_pcomp(struct crypto_pcomp *tfm, - struct pcomp_testvec *ctemplate, - struct pcomp_testvec *dtemplate, int ctcount, - int dtcount) -{ - const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm)); - unsigned int i; - char result[COMP_BUF_SIZE]; - int res; - - for (i = 0; i < ctcount; i++) { - struct comp_request req; - unsigned int produced = 0; - - res = crypto_compress_setup(tfm, ctemplate[i].params, - ctemplate[i].paramsize); - if (res) { - pr_err("alg: pcomp: compression setup failed on test " - "%d for %s: error=%d\n", i + 1, algo, res); - return res; - } - - res = crypto_compress_init(tfm); - if (res) { - pr_err("alg: pcomp: compression init failed on test " - "%d for %s: error=%d\n", i + 1, algo, res); - return res; - } - - memset(result, 0, sizeof(result)); - - req.next_in = ctemplate[i].input; - req.avail_in = ctemplate[i].inlen / 2; - req.next_out = result; - req.avail_out = ctemplate[i].outlen / 2; - - res = crypto_compress_update(tfm, &req); - if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: compression update failed on test " - "%d for %s: error=%d\n", i + 1, algo, res); - return res; - } - if (res > 0) - produced += res; - - /* Add remaining input data */ - req.avail_in += (ctemplate[i].inlen + 1) / 2; - - res = crypto_compress_update(tfm, &req); - if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: compression update failed on test " - "%d for %s: error=%d\n", i + 1, algo, res); - return res; - } - if (res > 0) - produced += res; - - /* Provide remaining output space */ - req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2; - - res = crypto_compress_final(tfm, &req); - if (res < 0) { - pr_err("alg: pcomp: compression final failed on test " - "%d for %s: error=%d\n", i + 1, algo, res); - return res; - } - produced += res; - - if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) { - pr_err("alg: comp: Compression test %d failed for %s: " - "output len = %d (expected %d)\n", i + 1, algo, - COMP_BUF_SIZE - req.avail_out, - ctemplate[i].outlen); - return -EINVAL; - } - - if (produced != ctemplate[i].outlen) { - pr_err("alg: comp: Compression test %d failed for %s: " - "returned len = %u (expected %d)\n", i + 1, - algo, produced, ctemplate[i].outlen); - return -EINVAL; - } - - if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) { - pr_err("alg: pcomp: Compression test %d failed for " - "%s\n", i + 1, algo); - hexdump(result, ctemplate[i].outlen); - return -EINVAL; - } - } - - for (i = 0; i < dtcount; i++) { - struct comp_request req; - unsigned int produced = 0; - - res = crypto_decompress_setup(tfm, dtemplate[i].params, - dtemplate[i].paramsize); - if (res) { - pr_err("alg: pcomp: decompression setup failed on " - "test %d for %s: error=%d\n", i + 1, algo, res); - return res; - } - - res = crypto_decompress_init(tfm); - if (res) { - pr_err("alg: pcomp: decompression init failed on test " - "%d for %s: error=%d\n", i + 1, algo, res); - return res; - } - - memset(result, 0, sizeof(result)); - - req.next_in = dtemplate[i].input; - req.avail_in = dtemplate[i].inlen / 2; - req.next_out = result; - req.avail_out = dtemplate[i].outlen / 2; - - res = crypto_decompress_update(tfm, &req); - if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: decompression update failed on " - "test %d for %s: error=%d\n", i + 1, algo, res); - return res; - } - if (res > 0) - produced += res; - - /* Add remaining input data */ - req.avail_in += (dtemplate[i].inlen + 1) / 2; - - res = crypto_decompress_update(tfm, &req); - if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: decompression update failed on " - "test %d for %s: error=%d\n", i + 1, algo, res); - return res; - } - if (res > 0) - produced += res; - - /* Provide remaining output space */ - req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2; - - res = crypto_decompress_final(tfm, &req); - if (res < 0 && (res != -EAGAIN || req.avail_in)) { - pr_err("alg: pcomp: decompression final failed on " - "test %d for %s: error=%d\n", i + 1, algo, res); - return res; - } - if (res > 0) - produced += res; - - if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) { - pr_err("alg: comp: Decompression test %d failed for " - "%s: output len = %d (expected %d)\n", i + 1, - algo, COMP_BUF_SIZE - req.avail_out, - dtemplate[i].outlen); - return -EINVAL; - } - - if (produced != dtemplate[i].outlen) { - pr_err("alg: comp: Decompression test %d failed for " - "%s: returned len = %u (expected %d)\n", i + 1, - algo, produced, dtemplate[i].outlen); - return -EINVAL; - } - - if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) { - pr_err("alg: pcomp: Decompression test %d failed for " - "%s\n", i + 1, algo); - hexdump(result, dtemplate[i].outlen); - return -EINVAL; - } - } - - return 0; -} - - static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template, unsigned int tcount) { @@ -1640,28 +1455,6 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver, return err; } -static int alg_test_pcomp(const struct alg_test_desc *desc, const char *driver, - u32 type, u32 mask) -{ - struct crypto_pcomp *tfm; - int err; - - tfm = crypto_alloc_pcomp(driver, type, mask); - if (IS_ERR(tfm)) { - pr_err("alg: pcomp: Failed to load transform for %s: %ld\n", - driver, PTR_ERR(tfm)); - return PTR_ERR(tfm); - } - - err = test_pcomp(tfm, desc->suite.pcomp.comp.vecs, - desc->suite.pcomp.decomp.vecs, - desc->suite.pcomp.comp.count, - desc->suite.pcomp.decomp.count); - - crypto_free_pcomp(tfm); - return err; -} - static int alg_test_hash(const struct alg_test_desc *desc, const char *driver, u32 type, u32 mask) { @@ -3839,22 +3632,6 @@ static const struct alg_test_desc alg_test_descs[] = { } } } - }, { - .alg = "zlib", - .test = alg_test_pcomp, - .fips_allowed = 1, - .suite = { - .pcomp = { - .comp = { - .vecs = zlib_comp_tv_template, - .count = ZLIB_COMP_TEST_VECTORS - }, - .decomp = { - .vecs = zlib_decomp_tv_template, - .count = ZLIB_DECOMP_TEST_VECTORS - } - } - } } }; diff --git a/crypto/testmgr.h b/crypto/testmgr.h index da0a8fd765f4..487ec880e889 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -25,9 +25,6 @@ #define _CRYPTO_TESTMGR_H #include -#include - -#include #define MAX_DIGEST_SIZE 64 #define MAX_TAP 8 @@ -32268,14 +32265,6 @@ struct comp_testvec { char output[COMP_BUF_SIZE]; }; -struct pcomp_testvec { - const void *params; - unsigned int paramsize; - int inlen, outlen; - char input[COMP_BUF_SIZE]; - char output[COMP_BUF_SIZE]; -}; - /* * Deflate test vectors (null-terminated strings). * Params: winbits=-11, Z_DEFAULT_COMPRESSION, MAX_MEM_LEVEL. @@ -32356,139 +32345,6 @@ static struct comp_testvec deflate_decomp_tv_template[] = { }, }; -#define ZLIB_COMP_TEST_VECTORS 2 -#define ZLIB_DECOMP_TEST_VECTORS 2 - -static const struct { - struct nlattr nla; - int val; -} deflate_comp_params[] = { - { - .nla = { - .nla_len = NLA_HDRLEN + sizeof(int), - .nla_type = ZLIB_COMP_LEVEL, - }, - .val = Z_DEFAULT_COMPRESSION, - }, { - .nla = { - .nla_len = NLA_HDRLEN + sizeof(int), - .nla_type = ZLIB_COMP_METHOD, - }, - .val = Z_DEFLATED, - }, { - .nla = { - .nla_len = NLA_HDRLEN + sizeof(int), - .nla_type = ZLIB_COMP_WINDOWBITS, - }, - .val = -11, - }, { - .nla = { - .nla_len = NLA_HDRLEN + sizeof(int), - .nla_type = ZLIB_COMP_MEMLEVEL, - }, - .val = MAX_MEM_LEVEL, - }, { - .nla = { - .nla_len = NLA_HDRLEN + sizeof(int), - .nla_type = ZLIB_COMP_STRATEGY, - }, - .val = Z_DEFAULT_STRATEGY, - } -}; - -static const struct { - struct nlattr nla; - int val; -} deflate_decomp_params[] = { - { - .nla = { - .nla_len = NLA_HDRLEN + sizeof(int), - .nla_type = ZLIB_DECOMP_WINDOWBITS, - }, - .val = -11, - } -}; - -static struct pcomp_testvec zlib_comp_tv_template[] = { - { - .params = &deflate_comp_params, - .paramsize = sizeof(deflate_comp_params), - .inlen = 70, - .outlen = 38, - .input = "Join us now and share the software " - "Join us now and share the software ", - .output = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" - "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" - "\x28\xce\x48\x2c\x4a\x55\x28\xc9" - "\x48\x55\x28\xce\x4f\x2b\x29\x07" - "\x71\xbc\x08\x2b\x01\x00", - }, { - .params = &deflate_comp_params, - .paramsize = sizeof(deflate_comp_params), - .inlen = 191, - .outlen = 122, - .input = "This document describes a compression method based on the DEFLATE" - "compression algorithm. This document defines the application of " - "the DEFLATE algorithm to the IP Payload Compression Protocol.", - .output = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" - "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" - "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" - "\x24\xdb\x67\xd9\x47\xc1\xef\x49" - "\x68\x12\x51\xae\x76\x67\xd6\x27" - "\x19\x88\x1a\xde\x85\xab\x21\xf2" - "\x08\x5d\x16\x1e\x20\x04\x2d\xad" - "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" - "\x42\x83\x23\xb6\x6c\x89\x71\x9b" - "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" - "\xed\x62\xa9\x4c\x80\xff\x13\xaf" - "\x52\x37\xed\x0e\x52\x6b\x59\x02" - "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" - "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" - "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" - "\xfa\x02", - }, -}; - -static struct pcomp_testvec zlib_decomp_tv_template[] = { - { - .params = &deflate_decomp_params, - .paramsize = sizeof(deflate_decomp_params), - .inlen = 122, - .outlen = 191, - .input = "\x5d\x8d\x31\x0e\xc2\x30\x10\x04" - "\xbf\xb2\x2f\xc8\x1f\x10\x04\x09" - "\x89\xc2\x85\x3f\x70\xb1\x2f\xf8" - "\x24\xdb\x67\xd9\x47\xc1\xef\x49" - "\x68\x12\x51\xae\x76\x67\xd6\x27" - "\x19\x88\x1a\xde\x85\xab\x21\xf2" - "\x08\x5d\x16\x1e\x20\x04\x2d\xad" - "\xf3\x18\xa2\x15\x85\x2d\x69\xc4" - "\x42\x83\x23\xb6\x6c\x89\x71\x9b" - "\xef\xcf\x8b\x9f\xcf\x33\xca\x2f" - "\xed\x62\xa9\x4c\x80\xff\x13\xaf" - "\x52\x37\xed\x0e\x52\x6b\x59\x02" - "\xd9\x4e\xe8\x7a\x76\x1d\x02\x98" - "\xfe\x8a\x87\x83\xa3\x4f\x56\x8a" - "\xb8\x9e\x8e\x5c\x57\xd3\xa0\x79" - "\xfa\x02", - .output = "This document describes a compression method based on the DEFLATE" - "compression algorithm. This document defines the application of " - "the DEFLATE algorithm to the IP Payload Compression Protocol.", - }, { - .params = &deflate_decomp_params, - .paramsize = sizeof(deflate_decomp_params), - .inlen = 38, - .outlen = 70, - .input = "\xf3\xca\xcf\xcc\x53\x28\x2d\x56" - "\xc8\xcb\x2f\x57\x48\xcc\x4b\x51" - "\x28\xce\x48\x2c\x4a\x55\x28\xc9" - "\x48\x55\x28\xce\x4f\x2b\x29\x07" - "\x71\xbc\x08\x2b\x01\x00", - .output = "Join us now and share the software " - "Join us now and share the software ", - }, -}; - /* * LZO test vectors (null-terminated strings). */ diff --git a/crypto/zlib.c b/crypto/zlib.c deleted file mode 100644 index d51a30a29e42..000000000000 --- a/crypto/zlib.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Cryptographic API. - * - * Zlib algorithm - * - * Copyright 2008 Sony Corporation - * - * Based on deflate.c, which is - * Copyright (c) 2003 James Morris - * - * 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. - * - * FIXME: deflate transforms will require up to a total of about 436k of kernel - * memory on i386 (390k for compression, the rest for decompression), as the - * current zlib kernel code uses a worst case pre-allocation system by default. - * This needs to be fixed so that the amount of memory required is properly - * related to the winbits and memlevel parameters. - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - - -struct zlib_ctx { - struct z_stream_s comp_stream; - struct z_stream_s decomp_stream; - int decomp_windowBits; -}; - - -static void zlib_comp_exit(struct zlib_ctx *ctx) -{ - struct z_stream_s *stream = &ctx->comp_stream; - - if (stream->workspace) { - zlib_deflateEnd(stream); - vfree(stream->workspace); - stream->workspace = NULL; - } -} - -static void zlib_decomp_exit(struct zlib_ctx *ctx) -{ - struct z_stream_s *stream = &ctx->decomp_stream; - - if (stream->workspace) { - zlib_inflateEnd(stream); - vfree(stream->workspace); - stream->workspace = NULL; - } -} - -static int zlib_init(struct crypto_tfm *tfm) -{ - return 0; -} - -static void zlib_exit(struct crypto_tfm *tfm) -{ - struct zlib_ctx *ctx = crypto_tfm_ctx(tfm); - - zlib_comp_exit(ctx); - zlib_decomp_exit(ctx); -} - - -static int zlib_compress_setup(struct crypto_pcomp *tfm, const void *params, - unsigned int len) -{ - struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &ctx->comp_stream; - struct nlattr *tb[ZLIB_COMP_MAX + 1]; - int window_bits, mem_level; - size_t workspacesize; - int ret; - - ret = nla_parse(tb, ZLIB_COMP_MAX, params, len, NULL); - if (ret) - return ret; - - zlib_comp_exit(ctx); - - window_bits = tb[ZLIB_COMP_WINDOWBITS] - ? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS]) - : MAX_WBITS; - mem_level = tb[ZLIB_COMP_MEMLEVEL] - ? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL]) - : DEF_MEM_LEVEL; - - workspacesize = zlib_deflate_workspacesize(window_bits, mem_level); - stream->workspace = vzalloc(workspacesize); - if (!stream->workspace) - return -ENOMEM; - - ret = zlib_deflateInit2(stream, - tb[ZLIB_COMP_LEVEL] - ? nla_get_u32(tb[ZLIB_COMP_LEVEL]) - : Z_DEFAULT_COMPRESSION, - tb[ZLIB_COMP_METHOD] - ? nla_get_u32(tb[ZLIB_COMP_METHOD]) - : Z_DEFLATED, - window_bits, - mem_level, - tb[ZLIB_COMP_STRATEGY] - ? nla_get_u32(tb[ZLIB_COMP_STRATEGY]) - : Z_DEFAULT_STRATEGY); - if (ret != Z_OK) { - vfree(stream->workspace); - stream->workspace = NULL; - return -EINVAL; - } - - return 0; -} - -static int zlib_compress_init(struct crypto_pcomp *tfm) -{ - int ret; - struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &dctx->comp_stream; - - ret = zlib_deflateReset(stream); - if (ret != Z_OK) - return -EINVAL; - - return 0; -} - -static int zlib_compress_update(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - int ret; - struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &dctx->comp_stream; - - pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); - stream->next_in = req->next_in; - stream->avail_in = req->avail_in; - stream->next_out = req->next_out; - stream->avail_out = req->avail_out; - - ret = zlib_deflate(stream, Z_NO_FLUSH); - switch (ret) { - case Z_OK: - break; - - case Z_BUF_ERROR: - pr_debug("zlib_deflate could not make progress\n"); - return -EAGAIN; - - default: - pr_debug("zlib_deflate failed %d\n", ret); - return -EINVAL; - } - - ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", - stream->avail_in, stream->avail_out, - req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; - return ret; -} - -static int zlib_compress_final(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - int ret; - struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &dctx->comp_stream; - - pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); - stream->next_in = req->next_in; - stream->avail_in = req->avail_in; - stream->next_out = req->next_out; - stream->avail_out = req->avail_out; - - ret = zlib_deflate(stream, Z_FINISH); - if (ret != Z_STREAM_END) { - pr_debug("zlib_deflate failed %d\n", ret); - return -EINVAL; - } - - ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", - stream->avail_in, stream->avail_out, - req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; - return ret; -} - - -static int zlib_decompress_setup(struct crypto_pcomp *tfm, const void *params, - unsigned int len) -{ - struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &ctx->decomp_stream; - struct nlattr *tb[ZLIB_DECOMP_MAX + 1]; - int ret = 0; - - ret = nla_parse(tb, ZLIB_DECOMP_MAX, params, len, NULL); - if (ret) - return ret; - - zlib_decomp_exit(ctx); - - ctx->decomp_windowBits = tb[ZLIB_DECOMP_WINDOWBITS] - ? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS]) - : DEF_WBITS; - - stream->workspace = vzalloc(zlib_inflate_workspacesize()); - if (!stream->workspace) - return -ENOMEM; - - ret = zlib_inflateInit2(stream, ctx->decomp_windowBits); - if (ret != Z_OK) { - vfree(stream->workspace); - stream->workspace = NULL; - return -EINVAL; - } - - return 0; -} - -static int zlib_decompress_init(struct crypto_pcomp *tfm) -{ - int ret; - struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &dctx->decomp_stream; - - ret = zlib_inflateReset(stream); - if (ret != Z_OK) - return -EINVAL; - - return 0; -} - -static int zlib_decompress_update(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - int ret; - struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &dctx->decomp_stream; - - pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); - stream->next_in = req->next_in; - stream->avail_in = req->avail_in; - stream->next_out = req->next_out; - stream->avail_out = req->avail_out; - - ret = zlib_inflate(stream, Z_SYNC_FLUSH); - switch (ret) { - case Z_OK: - case Z_STREAM_END: - break; - - case Z_BUF_ERROR: - pr_debug("zlib_inflate could not make progress\n"); - return -EAGAIN; - - default: - pr_debug("zlib_inflate failed %d\n", ret); - return -EINVAL; - } - - ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", - stream->avail_in, stream->avail_out, - req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; - return ret; -} - -static int zlib_decompress_final(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - int ret; - struct zlib_ctx *dctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); - struct z_stream_s *stream = &dctx->decomp_stream; - - pr_debug("avail_in %u, avail_out %u\n", req->avail_in, req->avail_out); - stream->next_in = req->next_in; - stream->avail_in = req->avail_in; - stream->next_out = req->next_out; - stream->avail_out = req->avail_out; - - if (dctx->decomp_windowBits < 0) { - ret = zlib_inflate(stream, Z_SYNC_FLUSH); - /* - * Work around a bug in zlib, which sometimes wants to taste an - * extra byte when being used in the (undocumented) raw deflate - * mode. (From USAGI). - */ - if (ret == Z_OK && !stream->avail_in && stream->avail_out) { - const void *saved_next_in = stream->next_in; - u8 zerostuff = 0; - - stream->next_in = &zerostuff; - stream->avail_in = 1; - ret = zlib_inflate(stream, Z_FINISH); - stream->next_in = saved_next_in; - stream->avail_in = 0; - } - } else - ret = zlib_inflate(stream, Z_FINISH); - if (ret != Z_STREAM_END) { - pr_debug("zlib_inflate failed %d\n", ret); - return -EINVAL; - } - - ret = req->avail_out - stream->avail_out; - pr_debug("avail_in %lu, avail_out %lu (consumed %lu, produced %u)\n", - stream->avail_in, stream->avail_out, - req->avail_in - stream->avail_in, ret); - req->next_in = stream->next_in; - req->avail_in = stream->avail_in; - req->next_out = stream->next_out; - req->avail_out = stream->avail_out; - return ret; -} - - -static struct pcomp_alg zlib_alg = { - .compress_setup = zlib_compress_setup, - .compress_init = zlib_compress_init, - .compress_update = zlib_compress_update, - .compress_final = zlib_compress_final, - .decompress_setup = zlib_decompress_setup, - .decompress_init = zlib_decompress_init, - .decompress_update = zlib_decompress_update, - .decompress_final = zlib_decompress_final, - - .base = { - .cra_name = "zlib", - .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS, - .cra_ctxsize = sizeof(struct zlib_ctx), - .cra_module = THIS_MODULE, - .cra_init = zlib_init, - .cra_exit = zlib_exit, - } -}; - -static int __init zlib_mod_init(void) -{ - return crypto_register_pcomp(&zlib_alg); -} - -static void __exit zlib_mod_fini(void) -{ - crypto_unregister_pcomp(&zlib_alg); -} - -module_init(zlib_mod_init); -module_exit(zlib_mod_fini); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Zlib Compression Algorithm"); -MODULE_AUTHOR("Sony Corporation"); -MODULE_ALIAS_CRYPTO("zlib"); diff --git a/include/crypto/compress.h b/include/crypto/compress.h deleted file mode 100644 index 5b67af834d83..000000000000 --- a/include/crypto/compress.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Compress: Compression algorithms under the cryptographic API. - * - * Copyright 2008 Sony 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. - * - * 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 _CRYPTO_COMPRESS_H -#define _CRYPTO_COMPRESS_H - -#include - - -struct comp_request { - const void *next_in; /* next input byte */ - void *next_out; /* next output byte */ - unsigned int avail_in; /* bytes available at next_in */ - unsigned int avail_out; /* bytes available at next_out */ -}; - -enum zlib_comp_params { - ZLIB_COMP_LEVEL = 1, /* e.g. Z_DEFAULT_COMPRESSION */ - ZLIB_COMP_METHOD, /* e.g. Z_DEFLATED */ - ZLIB_COMP_WINDOWBITS, /* e.g. MAX_WBITS */ - ZLIB_COMP_MEMLEVEL, /* e.g. DEF_MEM_LEVEL */ - ZLIB_COMP_STRATEGY, /* e.g. Z_DEFAULT_STRATEGY */ - __ZLIB_COMP_MAX, -}; - -#define ZLIB_COMP_MAX (__ZLIB_COMP_MAX - 1) - - -enum zlib_decomp_params { - ZLIB_DECOMP_WINDOWBITS = 1, /* e.g. DEF_WBITS */ - __ZLIB_DECOMP_MAX, -}; - -#define ZLIB_DECOMP_MAX (__ZLIB_DECOMP_MAX - 1) - - -struct crypto_pcomp { - struct crypto_tfm base; -}; - -struct pcomp_alg { - int (*compress_setup)(struct crypto_pcomp *tfm, const void *params, - unsigned int len); - int (*compress_init)(struct crypto_pcomp *tfm); - int (*compress_update)(struct crypto_pcomp *tfm, - struct comp_request *req); - int (*compress_final)(struct crypto_pcomp *tfm, - struct comp_request *req); - int (*decompress_setup)(struct crypto_pcomp *tfm, const void *params, - unsigned int len); - int (*decompress_init)(struct crypto_pcomp *tfm); - int (*decompress_update)(struct crypto_pcomp *tfm, - struct comp_request *req); - int (*decompress_final)(struct crypto_pcomp *tfm, - struct comp_request *req); - - struct crypto_alg base; -}; - -extern struct crypto_pcomp *crypto_alloc_pcomp(const char *alg_name, u32 type, - u32 mask); - -static inline struct crypto_tfm *crypto_pcomp_tfm(struct crypto_pcomp *tfm) -{ - return &tfm->base; -} - -static inline void crypto_free_pcomp(struct crypto_pcomp *tfm) -{ - crypto_destroy_tfm(tfm, crypto_pcomp_tfm(tfm)); -} - -static inline struct pcomp_alg *__crypto_pcomp_alg(struct crypto_alg *alg) -{ - return container_of(alg, struct pcomp_alg, base); -} - -static inline struct pcomp_alg *crypto_pcomp_alg(struct crypto_pcomp *tfm) -{ - return __crypto_pcomp_alg(crypto_pcomp_tfm(tfm)->__crt_alg); -} - -static inline int crypto_compress_setup(struct crypto_pcomp *tfm, - const void *params, unsigned int len) -{ - return crypto_pcomp_alg(tfm)->compress_setup(tfm, params, len); -} - -static inline int crypto_compress_init(struct crypto_pcomp *tfm) -{ - return crypto_pcomp_alg(tfm)->compress_init(tfm); -} - -static inline int crypto_compress_update(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - return crypto_pcomp_alg(tfm)->compress_update(tfm, req); -} - -static inline int crypto_compress_final(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - return crypto_pcomp_alg(tfm)->compress_final(tfm, req); -} - -static inline int crypto_decompress_setup(struct crypto_pcomp *tfm, - const void *params, unsigned int len) -{ - return crypto_pcomp_alg(tfm)->decompress_setup(tfm, params, len); -} - -static inline int crypto_decompress_init(struct crypto_pcomp *tfm) -{ - return crypto_pcomp_alg(tfm)->decompress_init(tfm); -} - -static inline int crypto_decompress_update(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - return crypto_pcomp_alg(tfm)->decompress_update(tfm, req); -} - -static inline int crypto_decompress_final(struct crypto_pcomp *tfm, - struct comp_request *req) -{ - return crypto_pcomp_alg(tfm)->decompress_final(tfm, req); -} - -#endif /* _CRYPTO_COMPRESS_H */ diff --git a/include/crypto/internal/compress.h b/include/crypto/internal/compress.h deleted file mode 100644 index 178a888d1d93..000000000000 --- a/include/crypto/internal/compress.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Compress: Compression algorithms under the cryptographic API. - * - * Copyright 2008 Sony 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. - * - * 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 _CRYPTO_INTERNAL_COMPRESS_H -#define _CRYPTO_INTERNAL_COMPRESS_H - -#include - -extern int crypto_register_pcomp(struct pcomp_alg *alg); -extern int crypto_unregister_pcomp(struct pcomp_alg *alg); - -#endif /* _CRYPTO_INTERNAL_COMPRESS_H */ diff --git a/include/linux/crypto.h b/include/linux/crypto.h index e71cb70a1ac2..ab2a745d85f3 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -54,7 +54,6 @@ #define CRYPTO_ALG_TYPE_AHASH 0x0000000a #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d -#define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f #define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e #define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000c -- cgit From e9f6452e0e55ceea004f5bc0802fb14778d16c42 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 26 Jan 2016 18:54:55 +0800 Subject: libceph: Remove unnecessary ivsize variables This patch removes the unnecessary ivsize variabls as they always have the value of AES_BLOCK_SIZE. Signed-off-by: Ilya Dryomov Signed-off-by: Herbert Xu --- net/ceph/crypto.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index fb9cb2bb0894..db2847ac5f12 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -166,8 +166,7 @@ static int ceph_aes_encrypt(const void *key, int key_len, struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); SKCIPHER_REQUEST_ON_STACK(req, tfm); int ret; - int ivsize = AES_BLOCK_SIZE; - char iv[ivsize]; + char iv[AES_BLOCK_SIZE]; size_t zero_padding = (0x10 - (src_len & 0x0f)); char pad[16]; @@ -186,7 +185,7 @@ static int ceph_aes_encrypt(const void *key, int key_len, goto out_tfm; crypto_skcipher_setkey((void *)tfm, key, key_len); - memcpy(iv, aes_iv, ivsize); + memcpy(iv, aes_iv, AES_BLOCK_SIZE); skcipher_request_set_tfm(req, tfm); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -229,8 +228,7 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); SKCIPHER_REQUEST_ON_STACK(req, tfm); int ret; - int ivsize = AES_BLOCK_SIZE; - char iv[ivsize]; + char iv[AES_BLOCK_SIZE]; size_t zero_padding = (0x10 - ((src1_len + src2_len) & 0x0f)); char pad[16]; @@ -250,7 +248,7 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst, goto out_tfm; crypto_skcipher_setkey((void *)tfm, key, key_len); - memcpy(iv, aes_iv, ivsize); + memcpy(iv, aes_iv, AES_BLOCK_SIZE); skcipher_request_set_tfm(req, tfm); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -294,8 +292,7 @@ static int ceph_aes_decrypt(const void *key, int key_len, struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); SKCIPHER_REQUEST_ON_STACK(req, tfm); char pad[16]; - int ivsize = AES_BLOCK_SIZE; - char iv[16]; + char iv[AES_BLOCK_SIZE]; int ret; int last_byte; @@ -310,7 +307,7 @@ static int ceph_aes_decrypt(const void *key, int key_len, goto out_tfm; crypto_skcipher_setkey((void *)tfm, key, key_len); - memcpy(iv, aes_iv, ivsize); + memcpy(iv, aes_iv, AES_BLOCK_SIZE); skcipher_request_set_tfm(req, tfm); skcipher_request_set_callback(req, 0, NULL, NULL); @@ -363,8 +360,7 @@ static int ceph_aes_decrypt2(const void *key, int key_len, struct crypto_skcipher *tfm = ceph_crypto_alloc_cipher(); SKCIPHER_REQUEST_ON_STACK(req, tfm); char pad[16]; - int ivsize = AES_BLOCK_SIZE; - char iv[ivsize]; + char iv[AES_BLOCK_SIZE]; int ret; int last_byte; @@ -380,7 +376,7 @@ static int ceph_aes_decrypt2(const void *key, int key_len, goto out_tfm; crypto_skcipher_setkey((void *)tfm, key, key_len); - memcpy(iv, aes_iv, ivsize); + memcpy(iv, aes_iv, AES_BLOCK_SIZE); skcipher_request_set_tfm(req, tfm); skcipher_request_set_callback(req, 0, NULL, NULL); -- cgit From bfb2892018ca302d8d659232f5f18f56b4b2b782 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 14:44:50 +0100 Subject: crypto: sunxi - don't print confusing data gcc correctly warns that the printk output contains a variable that it thinks is not initialized in some cases: drivers/crypto/sunxi-ss/sun4i-ss-cipher.c: In function 'sun4i_ss_cipher_poll': drivers/crypto/sunxi-ss/sun4i-ss-cipher.c:254:76: warning: 'todo' may be used uninitialized in this function [-Wmaybe-uninitialized] drivers/crypto/sunxi-ss/sun4i-ss-cipher.c:144:15: note: 'todo' was declared here A closer look at the function reveals that the variable is always initialized at this point (ileft is guaranteed to be positive at the start), but its contents are not well-defined: Depending on some other variables, it might be either a count in words or bytes, and it could refer to either input or output. The easiest solution apparently is to remove the confusing output and let the reader figure out the state from the other variables. Signed-off-by: Arnd Bergmann Signed-off-by: Herbert Xu --- drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index a19ee127edca..7be3fbcd8d78 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -251,11 +251,10 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq) spaces = readl(ss->base + SS_FCSR); rx_cnt = SS_RXFIFO_SPACES(spaces); tx_cnt = SS_TXFIFO_SPACES(spaces); - dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u %u\n", + dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u\n", mode, oi, mi.length, ileft, areq->nbytes, rx_cnt, - oo, mo.length, oleft, areq->nbytes, tx_cnt, - todo, ob); + oo, mo.length, oleft, areq->nbytes, tx_cnt, ob); if (tx_cnt == 0) continue; -- cgit From 2f313e029020f1fa5f58f38f48ff6988d67fc3c1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 14:47:10 +0100 Subject: crypto: jitterentropy - always select CRYPTO_RNG When building the jitterentropy driver by itself, we get a link error when CRYPTO_RNG is not enabled as well: crypto/built-in.o: In function `jent_mod_init': jitterentropy-kcapi.c:(.init.text+0x98): undefined reference to `crypto_register_rng' crypto/built-in.o: In function `jent_mod_exit': jitterentropy-kcapi.c:(.exit.text+0x60): undefined reference to `crypto_unregister_rng' This adds a 'select CRYPTO_RNG' to CRYPTO_JITTERENTROPY to ensure the API is always there when it's used, not just when DRBG is also enabled. CRYPTO_DRBG would set it implicitly through CRYPTO_JITTERENTROPY now, but this leaves it in place to make it explicit what the driver does. Signed-off-by: Arnd Bergmann Signed-off-by: Herbert Xu --- crypto/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/Kconfig b/crypto/Kconfig index c80d34fc2f8c..099f1f1b0857 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1574,6 +1574,7 @@ endif # if CRYPTO_DRBG_MENU config CRYPTO_JITTERENTROPY tristate "Jitterentropy Non-Deterministic Random Number Generator" + select CRYPTO_RNG help The Jitterentropy RNG is a noise that is intended to provide seed to another RNG. The RNG does not -- cgit From c670254f63fe09681b1c4c82d3d059c6cc04ce09 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 27 Jan 2016 15:02:49 +0200 Subject: ASoC: davinci-mcasp: Discourage use of fck_parent for clock reparenting The in-driver clock reparenting had been added when we did not had other means to cleanly set the parent for the fck. Now we can use assigned-clocks/assigned-clock-parents in DT binding. Print warning when the fck_parent is present for McASP and recommend the switch to the proper way to handle the clock selection. Signed-off-by: Peter Ujfalusi Signed-off-by: Mark Brown --- sound/soc/davinci/davinci-mcasp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 2ccb8bccc9d4..3cf46afb353f 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -1517,6 +1517,8 @@ static int mcasp_reparent_fck(struct platform_device *pdev) if (!parent_name) return 0; + dev_warn(&pdev->dev, "Update the bindings to use assigned-clocks!\n"); + gfclk = clk_get(&pdev->dev, "fck"); if (IS_ERR(gfclk)) { dev_err(&pdev->dev, "failed to get fck\n"); -- cgit From 936516bfb3a111982295675055d1659274be70f0 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Thu, 14 Jan 2016 13:16:28 +0100 Subject: Documentation: dt-bindings: Document STM32 pinctrl driver DT bindings Acked-by: Patrice Chotard Signed-off-by: Maxime Coquelin Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/st,stm32-pinctrl.txt | 126 +++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt new file mode 100644 index 000000000000..7b4800cc251e --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt @@ -0,0 +1,126 @@ +* STM32 GPIO and Pin Mux/Config controller + +STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config hardware +controller. It controls the input/output settings on the available pins and +also provides ability to multiplex and configure the output of various on-chip +controllers onto these pads. + +Pin controller node: +Required properies: + - compatible: value should be one of the following: + (a) "st,stm32f429-pinctrl" + - #address-cells: The value of this property must be 1 + - #size-cells : The value of this property must be 1 + - ranges : defines mapping between pin controller node (parent) to + gpio-bank node (children). + - pins-are-numbered: Specify the subnodes are using numbered pinmux to + specify pins. + +GPIO controller/bank node: +Required properties: + - gpio-controller : Indicates this device is a GPIO controller + - #gpio-cells : Should be two. + The first cell is the pin number + The second one is the polarity: + - 0 for active high + - 1 for active low + - reg : The gpio address range, relative to the pinctrl range + - clocks : clock that drives this bank + - st,bank-name : Should be a name string for this bank as specified in + the datasheet + +Optional properties: + - reset: : Reference to the reset controller + +Example: +#include +... + + pin-controller { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32f429-pinctrl"; + ranges = <0 0x40020000 0x3000>; + pins-are-numbered; + + gpioa: gpio@40020000 { + gpio-controller; + #gpio-cells = <2>; + reg = <0x0 0x400>; + resets = <&reset_ahb1 0>; + st,bank-name = "GPIOA"; + }; + ... + pin-functions nodes follow... + }; + +Contents of function subnode node: +---------------------------------- +Subnode format +A pinctrl node should contain at least one subnode representing the +pinctrl group available on the machine. Each subnode will list the +pins it needs, and how they should be configured, with regard to muxer +configuration, pullups, drive, output high/low and output speed. + + node { + pinmux = ; + GENERIC_PINCONFIG; + }; + +Required properties: +- pinmux: integer array, represents gpio pin number and mux setting. + Supported pin number and mux varies for different SoCs, and are defined in + dt-bindings/pinctrl/-pinfunc.h directly. + These defines are calculated as: + ((port * 16 + line) << 8) | function + With: + - port: The gpio port index (PA = 0, PB = 1, ..., PK = 11) + - line: The line offset within the port (PA0 = 0, PA1 = 1, ..., PA15 = 15) + - function: The function number, can be: + * 0 : GPIO + * 1 : Alternate Function 0 + * 2 : Alternate Function 1 + * 3 : Alternate Function 2 + * ... + * 16 : Alternate Function 15 + * 17 : Analog + +Optional properties: +- GENERIC_PINCONFIG: is the generic pinconfig options to use. + Available options are: + - bias-disable, + - bias-pull-down, + - bias-pull-up, + - drive-push-pull, + - drive-open-drain, + - output-low + - output-high + - slew-rate = , with x being: + < 0 > : Low speed + < 1 > : Medium speed + < 2 > : Fast speed + < 3 > : High speed + +Example: + +pin-controller { +... + usart1_pins_a: usart1@0 { + pins1 { + pinmux = ; + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; + bias-disable; + }; + }; +}; + +&usart1 { + pinctrl-0 = <&usart1_pins_a>; + pinctrl-names = "default"; + status = "okay"; +}; -- cgit From aceb16dc2da58341bda939defaff0682fac13747 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Thu, 14 Jan 2016 13:16:30 +0100 Subject: pinctrl: Add STM32 MCUs support This patch adds pinctrl and GPIO support to STMicroelectronic's STM32 family of MCUs. While it only supports STM32F429 for now, it has been designed to enable support of other MCUs of the family (e.g. STM32F746). Acked-by: Patrice Chotard Signed-off-by: Maxime Coquelin Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/stm32/Kconfig | 16 + drivers/pinctrl/stm32/Makefile | 5 + drivers/pinctrl/stm32/pinctrl-stm32.c | 834 +++++++++++++++ drivers/pinctrl/stm32/pinctrl-stm32.h | 43 + drivers/pinctrl/stm32/pinctrl-stm32f429.c | 1598 +++++++++++++++++++++++++++++ 7 files changed, 2498 insertions(+) create mode 100644 drivers/pinctrl/stm32/Kconfig create mode 100644 drivers/pinctrl/stm32/Makefile create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32.c create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32.h create mode 100644 drivers/pinctrl/stm32/pinctrl-stm32f429.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 99a4c10ed43f..f8405cdeb5fb 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -257,6 +257,7 @@ source "drivers/pinctrl/qcom/Kconfig" source "drivers/pinctrl/samsung/Kconfig" source "drivers/pinctrl/sh-pfc/Kconfig" source "drivers/pinctrl/spear/Kconfig" +source "drivers/pinctrl/stm32/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/vt8500/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index bf1b5ca5180b..d4134038cbf9 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_QCOM) += qcom/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ +obj-$(CONFIG_ARCH_STM32) += stm32/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig new file mode 100644 index 000000000000..0f28841b2332 --- /dev/null +++ b/drivers/pinctrl/stm32/Kconfig @@ -0,0 +1,16 @@ +if ARCH_STM32 || COMPILE_TEST + +config PINCTRL_STM32 + bool + depends on OF + select PINMUX + select GENERIC_PINCONF + select GPIOLIB + +config PINCTRL_STM32F429 + bool "STMicroelectronics STM32F429 pin control" if COMPILE_TEST && !MACH_STM32F429 + depends on OF + default MACH_STM32F429 + select PINCTRL_STM32 + +endif diff --git a/drivers/pinctrl/stm32/Makefile b/drivers/pinctrl/stm32/Makefile new file mode 100644 index 000000000000..fc17d4238845 --- /dev/null +++ b/drivers/pinctrl/stm32/Makefile @@ -0,0 +1,5 @@ +# Core +obj-$(CONFIG_PINCTRL_STM32) += pinctrl-stm32.o + +# SoC Drivers +obj-$(CONFIG_PINCTRL_STM32F429) += pinctrl-stm32f429.o diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c new file mode 100644 index 000000000000..d25d4a064bad --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -0,0 +1,834 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + * + * Heavily based on Mediatek's pinctrl driver + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "../core.h" +#include "../pinconf.h" +#include "../pinctrl-utils.h" +#include "pinctrl-stm32.h" + +#define STM32_GPIO_MODER 0x00 +#define STM32_GPIO_TYPER 0x04 +#define STM32_GPIO_SPEEDR 0x08 +#define STM32_GPIO_PUPDR 0x0c +#define STM32_GPIO_IDR 0x10 +#define STM32_GPIO_ODR 0x14 +#define STM32_GPIO_BSRR 0x18 +#define STM32_GPIO_LCKR 0x1c +#define STM32_GPIO_AFRL 0x20 +#define STM32_GPIO_AFRH 0x24 + +#define STM32_GPIO_PINS_PER_BANK 16 + +#define gpio_range_to_bank(chip) \ + container_of(chip, struct stm32_gpio_bank, range) + +#define gpio_chip_to_bank(chip) \ + container_of(chip, struct stm32_gpio_bank, gpio_chip) + +static const char * const stm32_gpio_functions[] = { + "gpio", "af0", "af1", + "af2", "af3", "af4", + "af5", "af6", "af7", + "af8", "af9", "af10", + "af11", "af12", "af13", + "af14", "af15", "analog", +}; + +struct stm32_pinctrl_group { + const char *name; + unsigned long config; + unsigned pin; +}; + +struct stm32_gpio_bank { + void __iomem *base; + struct clk *clk; + spinlock_t lock; + struct gpio_chip gpio_chip; + struct pinctrl_gpio_range range; +}; + +struct stm32_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl_dev; + struct pinctrl_desc pctl_desc; + struct stm32_pinctrl_group *groups; + unsigned ngroups; + const char **grp_names; + struct stm32_gpio_bank *banks; + unsigned nbanks; + const struct stm32_pinctrl_match_data *match_data; +}; + +static inline int stm32_gpio_pin(int gpio) +{ + return gpio % STM32_GPIO_PINS_PER_BANK; +} + +static inline u32 stm32_gpio_get_mode(u32 function) +{ + switch (function) { + case STM32_PIN_GPIO: + return 0; + case STM32_PIN_AF(0) ... STM32_PIN_AF(15): + return 2; + case STM32_PIN_ANALOG: + return 3; + } + + return 0; +} + +static inline u32 stm32_gpio_get_alt(u32 function) +{ + switch (function) { + case STM32_PIN_GPIO: + return 0; + case STM32_PIN_AF(0) ... STM32_PIN_AF(15): + return function - 1; + case STM32_PIN_ANALOG: + return 0; + } + + return 0; +} + +/* GPIO functions */ + +static inline void __stm32_gpio_set(struct stm32_gpio_bank *bank, + unsigned offset, int value) +{ + if (!value) + offset += STM32_GPIO_PINS_PER_BANK; + + clk_enable(bank->clk); + + writel_relaxed(BIT(offset), bank->base + STM32_GPIO_BSRR); + + clk_disable(bank->clk); +} + +static int stm32_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_request_gpio(chip->base + offset); +} + +static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + pinctrl_free_gpio(chip->base + offset); +} + +static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + int ret; + + clk_enable(bank->clk); + + ret = !!(readl_relaxed(bank->base + STM32_GPIO_IDR) & BIT(offset)); + + clk_disable(bank->clk); + + return ret; +} + +static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + + __stm32_gpio_set(bank, offset, value); +} + +static int stm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + return pinctrl_gpio_direction_input(chip->base + offset); +} + +static int stm32_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + + __stm32_gpio_set(bank, offset, value); + pinctrl_gpio_direction_output(chip->base + offset); + + return 0; +} + +static struct gpio_chip stm32_gpio_template = { + .request = stm32_gpio_request, + .free = stm32_gpio_free, + .get = stm32_gpio_get, + .set = stm32_gpio_set, + .direction_input = stm32_gpio_direction_input, + .direction_output = stm32_gpio_direction_output, +}; + +/* Pinctrl functions */ + +static struct stm32_pinctrl_group * +stm32_pctrl_find_group_by_pin(struct stm32_pinctrl *pctl, u32 pin) +{ + int i; + + for (i = 0; i < pctl->ngroups; i++) { + struct stm32_pinctrl_group *grp = pctl->groups + i; + + if (grp->pin == pin) + return grp; + } + + return NULL; +} + +static bool stm32_pctrl_is_function_valid(struct stm32_pinctrl *pctl, + u32 pin_num, u32 fnum) +{ + int i; + + for (i = 0; i < pctl->match_data->npins; i++) { + const struct stm32_desc_pin *pin = pctl->match_data->pins + i; + const struct stm32_desc_function *func = pin->functions; + + if (pin->pin.number != pin_num) + continue; + + while (func && func->name) { + if (func->num == fnum) + return true; + func++; + } + + break; + } + + return false; +} + +static int stm32_pctrl_dt_node_to_map_func(struct stm32_pinctrl *pctl, + u32 pin, u32 fnum, struct stm32_pinctrl_group *grp, + struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps) +{ + if (*num_maps == *reserved_maps) + return -ENOSPC; + + (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; + (*map)[*num_maps].data.mux.group = grp->name; + + if (!stm32_pctrl_is_function_valid(pctl, pin, fnum)) { + dev_err(pctl->dev, "invalid function %d on pin %d .\n", + fnum, pin); + return -EINVAL; + } + + (*map)[*num_maps].data.mux.function = stm32_gpio_functions[fnum]; + (*num_maps)++; + + return 0; +} + +static int stm32_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *node, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) +{ + struct stm32_pinctrl *pctl; + struct stm32_pinctrl_group *grp; + struct property *pins; + u32 pinfunc, pin, func; + unsigned long *configs; + unsigned int num_configs; + bool has_config = 0; + unsigned reserve = 0; + int num_pins, num_funcs, maps_per_pin, i, err; + + pctl = pinctrl_dev_get_drvdata(pctldev); + + pins = of_find_property(node, "pinmux", NULL); + if (!pins) { + dev_err(pctl->dev, "missing pins property in node %s .\n", + node->name); + return -EINVAL; + } + + err = pinconf_generic_parse_dt_config(node, pctldev, &configs, + &num_configs); + if (err) + return err; + + if (num_configs) + has_config = 1; + + num_pins = pins->length / sizeof(u32); + num_funcs = num_pins; + maps_per_pin = 0; + if (num_funcs) + maps_per_pin++; + if (has_config && num_pins >= 1) + maps_per_pin++; + + if (!num_pins || !maps_per_pin) + return -EINVAL; + + reserve = num_pins * maps_per_pin; + + err = pinctrl_utils_reserve_map(pctldev, map, + reserved_maps, num_maps, reserve); + if (err) + return err; + + for (i = 0; i < num_pins; i++) { + err = of_property_read_u32_index(node, "pinmux", + i, &pinfunc); + if (err) + return err; + + pin = STM32_GET_PIN_NO(pinfunc); + func = STM32_GET_PIN_FUNC(pinfunc); + + if (pin >= pctl->match_data->npins) { + dev_err(pctl->dev, "invalid pin number.\n"); + return -EINVAL; + } + + if (!stm32_pctrl_is_function_valid(pctl, pin, func)) { + dev_err(pctl->dev, "invalid function.\n"); + return -EINVAL; + } + + grp = stm32_pctrl_find_group_by_pin(pctl, pin); + if (!grp) { + dev_err(pctl->dev, "unable to match pin %d to group\n", + pin); + return -EINVAL; + } + + err = stm32_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map, + reserved_maps, num_maps); + if (err) + return err; + + if (has_config) { + err = pinctrl_utils_add_map_configs(pctldev, map, + reserved_maps, num_maps, grp->name, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (err) + return err; + } + } + + return 0; +} + +static int stm32_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, unsigned *num_maps) +{ + struct device_node *np; + unsigned reserved_maps; + int ret; + + *map = NULL; + *num_maps = 0; + reserved_maps = 0; + + for_each_child_of_node(np_config, np) { + 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); + return ret; + } + } + + return 0; +} + +static int stm32_pctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->ngroups; +} + +static const char *stm32_pctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->groups[group].name; +} + +static int stm32_pctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *pins = (unsigned *)&pctl->groups[group].pin; + *num_pins = 1; + + return 0; +} + +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, + .get_groups_count = stm32_pctrl_get_groups_count, + .get_group_name = stm32_pctrl_get_group_name, + .get_group_pins = stm32_pctrl_get_group_pins, +}; + + +/* Pinmux functions */ + +static int stm32_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(stm32_gpio_functions); +} + +static const char *stm32_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + return stm32_gpio_functions[selector]; +} + +static int stm32_pmx_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctl->grp_names; + *num_groups = pctl->ngroups; + + return 0; +} + +static void stm32_pmx_set_mode(struct stm32_gpio_bank *bank, + int pin, u32 mode, u32 alt) +{ + u32 val; + int alt_shift = (pin % 8) * 4; + int alt_offset = STM32_GPIO_AFRL + (pin / 8) * 4; + unsigned long flags; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + alt_offset); + val &= ~GENMASK(alt_shift + 3, alt_shift); + val |= (alt << alt_shift); + writel_relaxed(val, bank->base + alt_offset); + + val = readl_relaxed(bank->base + STM32_GPIO_MODER); + val &= ~GENMASK(pin * 2 + 1, pin * 2); + val |= mode << (pin * 2); + writel_relaxed(val, bank->base + STM32_GPIO_MODER); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static int stm32_pmx_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + bool ret; + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct stm32_pinctrl_group *g = pctl->groups + group; + struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; + u32 mode, alt; + int pin; + + ret = stm32_pctrl_is_function_valid(pctl, g->pin, function); + if (!ret) { + dev_err(pctl->dev, "invalid function %d on group %d .\n", + function, group); + return -EINVAL; + } + + range = pinctrl_find_gpio_range_from_pin(pctldev, g->pin); + bank = gpio_range_to_bank(range); + pin = stm32_gpio_pin(g->pin); + + mode = stm32_gpio_get_mode(function); + alt = stm32_gpio_get_alt(function); + + stm32_pmx_set_mode(bank, pin, mode, alt); + + return 0; +} + +static int stm32_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned gpio, + bool input) +{ + struct stm32_gpio_bank *bank = gpio_range_to_bank(range); + int pin = stm32_gpio_pin(gpio); + + stm32_pmx_set_mode(bank, pin, !input, 0); + + return 0; +} + +static const struct pinmux_ops stm32_pmx_ops = { + .get_functions_count = stm32_pmx_get_funcs_cnt, + .get_function_name = stm32_pmx_get_func_name, + .get_function_groups = stm32_pmx_get_func_groups, + .set_mux = stm32_pmx_set_mux, + .gpio_set_direction = stm32_pmx_gpio_set_direction, +}; + +/* Pinconf functions */ + +static void stm32_pconf_set_driving(struct stm32_gpio_bank *bank, + unsigned offset, u32 drive) +{ + unsigned long flags; + u32 val; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_TYPER); + val &= ~BIT(offset); + val |= drive << offset; + writel_relaxed(val, bank->base + STM32_GPIO_TYPER); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static void stm32_pconf_set_speed(struct stm32_gpio_bank *bank, + unsigned offset, u32 speed) +{ + unsigned long flags; + u32 val; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_SPEEDR); + val &= ~GENMASK(offset * 2 + 1, offset * 2); + val |= speed << (offset * 2); + writel_relaxed(val, bank->base + STM32_GPIO_SPEEDR); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static void stm32_pconf_set_bias(struct stm32_gpio_bank *bank, + unsigned offset, u32 bias) +{ + unsigned long flags; + u32 val; + + clk_enable(bank->clk); + spin_lock_irqsave(&bank->lock, flags); + + val = readl_relaxed(bank->base + STM32_GPIO_PUPDR); + val &= ~GENMASK(offset * 2 + 1, offset * 2); + val |= bias << (offset * 2); + writel_relaxed(val, bank->base + STM32_GPIO_PUPDR); + + spin_unlock_irqrestore(&bank->lock, flags); + clk_disable(bank->clk); +} + +static int stm32_pconf_parse_conf(struct pinctrl_dev *pctldev, + unsigned int pin, enum pin_config_param param, + enum pin_config_param arg) +{ + struct pinctrl_gpio_range *range; + struct stm32_gpio_bank *bank; + int offset, ret = 0; + + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + bank = gpio_range_to_bank(range); + offset = stm32_gpio_pin(pin); + + switch (param) { + case PIN_CONFIG_DRIVE_PUSH_PULL: + stm32_pconf_set_driving(bank, offset, 0); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + stm32_pconf_set_driving(bank, offset, 1); + break; + case PIN_CONFIG_SLEW_RATE: + stm32_pconf_set_speed(bank, offset, arg); + break; + case PIN_CONFIG_BIAS_DISABLE: + stm32_pconf_set_bias(bank, offset, 0); + break; + case PIN_CONFIG_BIAS_PULL_UP: + stm32_pconf_set_bias(bank, offset, 1); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + stm32_pconf_set_bias(bank, offset, 2); + break; + case PIN_CONFIG_OUTPUT: + __stm32_gpio_set(bank, offset, arg); + ret = stm32_pmx_gpio_set_direction(pctldev, NULL, pin, false); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int stm32_pconf_group_get(struct pinctrl_dev *pctldev, + unsigned group, + unsigned long *config) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *config = pctl->groups[group].config; + + return 0; +} + +static int stm32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group, + unsigned long *configs, unsigned num_configs) +{ + struct stm32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct stm32_pinctrl_group *g = &pctl->groups[group]; + int i, ret; + + for (i = 0; i < num_configs; i++) { + ret = stm32_pconf_parse_conf(pctldev, g->pin, + pinconf_to_config_param(configs[i]), + pinconf_to_config_argument(configs[i])); + if (ret < 0) + return ret; + + g->config = configs[i]; + } + + return 0; +} + +static const struct pinconf_ops stm32_pconf_ops = { + .pin_config_group_get = stm32_pconf_group_get, + .pin_config_group_set = stm32_pconf_group_set, +}; + +static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, + struct device_node *np) +{ + int bank_nr = pctl->nbanks; + struct stm32_gpio_bank *bank = &pctl->banks[bank_nr]; + struct pinctrl_gpio_range *range = &bank->range; + struct device *dev = pctl->dev; + struct resource res; + struct reset_control *rstc; + int err, npins; + + rstc = of_reset_control_get(np, NULL); + if (!IS_ERR(rstc)) + reset_control_deassert(rstc); + + if (of_address_to_resource(np, 0, &res)) + return -ENODEV; + + bank->base = devm_ioremap_resource(dev, &res); + if (IS_ERR(bank->base)) + return PTR_ERR(bank->base); + + bank->clk = of_clk_get_by_name(np, NULL); + if (IS_ERR(bank->clk)) { + dev_err(dev, "failed to get clk (%ld)\n", PTR_ERR(bank->clk)); + return PTR_ERR(bank->clk); + } + + err = clk_prepare(bank->clk); + if (err) { + dev_err(dev, "failed to prepare clk (%d)\n", err); + return err; + } + + npins = pctl->match_data->npins; + npins -= bank_nr * STM32_GPIO_PINS_PER_BANK; + if (npins < 0) + return -EINVAL; + else if (npins > STM32_GPIO_PINS_PER_BANK) + npins = STM32_GPIO_PINS_PER_BANK; + + bank->gpio_chip = stm32_gpio_template; + bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; + bank->gpio_chip.ngpio = npins; + bank->gpio_chip.of_node = np; + bank->gpio_chip.dev = dev; + spin_lock_init(&bank->lock); + + of_property_read_string(np, "st,bank-name", &range->name); + bank->gpio_chip.label = range->name; + + range->id = bank_nr; + range->pin_base = range->base = range->id * STM32_GPIO_PINS_PER_BANK; + range->npins = bank->gpio_chip.ngpio; + range->gc = &bank->gpio_chip; + err = gpiochip_add(&bank->gpio_chip); + if (err) { + dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); + return err; + } + + dev_info(dev, "%s bank added\n", range->name); + return 0; +} + +static int stm32_pctrl_build_state(struct platform_device *pdev) +{ + struct stm32_pinctrl *pctl = platform_get_drvdata(pdev); + int i; + + pctl->ngroups = pctl->match_data->npins; + + /* Allocate groups */ + pctl->groups = devm_kcalloc(&pdev->dev, pctl->ngroups, + sizeof(*pctl->groups), GFP_KERNEL); + if (!pctl->groups) + return -ENOMEM; + + /* We assume that one pin is one group, use pin name as group name. */ + pctl->grp_names = devm_kcalloc(&pdev->dev, pctl->ngroups, + sizeof(*pctl->grp_names), GFP_KERNEL); + if (!pctl->grp_names) + return -ENOMEM; + + for (i = 0; i < pctl->match_data->npins; i++) { + const struct stm32_desc_pin *pin = pctl->match_data->pins + i; + struct stm32_pinctrl_group *group = pctl->groups + i; + + group->name = pin->pin.name; + group->pin = pin->pin.number; + + pctl->grp_names[i] = pin->pin.name; + } + + return 0; +} + +int stm32_pctl_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *child; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct stm32_pinctrl *pctl; + struct pinctrl_pin_desc *pins; + int i, ret, banks = 0; + + if (!np) + return -EINVAL; + + match = of_match_device(dev->driver->of_match_table, dev); + if (!match || !match->data) + return -EINVAL; + + if (!of_find_property(np, "pins-are-numbered", NULL)) { + dev_err(dev, "only support pins-are-numbered format\n"); + return -EINVAL; + } + + pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + + platform_set_drvdata(pdev, pctl); + + pctl->dev = dev; + pctl->match_data = match->data; + ret = stm32_pctrl_build_state(pdev); + if (ret) { + dev_err(dev, "build state failed: %d\n", ret); + return -EINVAL; + } + + for_each_child_of_node(np, child) + if (of_property_read_bool(child, "gpio-controller")) + banks++; + + if (!banks) { + dev_err(dev, "at least one GPIO bank is required\n"); + return -EINVAL; + } + + pctl->banks = devm_kcalloc(dev, banks, sizeof(*pctl->banks), + GFP_KERNEL); + if (!pctl->banks) + return -ENOMEM; + + for_each_child_of_node(np, child) { + if (of_property_read_bool(child, "gpio-controller")) { + ret = stm32_gpiolib_register_bank(pctl, child); + if (ret) + return ret; + + pctl->nbanks++; + } + } + + pins = devm_kcalloc(&pdev->dev, pctl->match_data->npins, sizeof(*pins), + GFP_KERNEL); + if (!pins) + return -ENOMEM; + + for (i = 0; i < pctl->match_data->npins; i++) + pins[i] = pctl->match_data->pins[i].pin; + + pctl->pctl_desc.name = dev_name(&pdev->dev); + pctl->pctl_desc.owner = THIS_MODULE; + pctl->pctl_desc.pins = pins; + pctl->pctl_desc.npins = pctl->match_data->npins; + pctl->pctl_desc.confops = &stm32_pconf_ops; + pctl->pctl_desc.pctlops = &stm32_pctrl_ops; + 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) { + dev_err(&pdev->dev, "Failed pinctrl registration\n"); + return -EINVAL; + } + + for (i = 0; i < pctl->nbanks; i++) + pinctrl_add_gpio_range(pctl->pctl_dev, &pctl->banks[i].range); + + dev_info(dev, "Pinctrl STM32 initialized\n"); + + return 0; +} + diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.h b/drivers/pinctrl/stm32/pinctrl-stm32.h new file mode 100644 index 000000000000..1b7c369acd8c --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + */ +#ifndef __PINCTRL_STM32_H +#define __PINCTRL_STM32_H + +#include +#include + +struct stm32_desc_function { + const char *name; + const unsigned char num; +}; + +struct stm32_desc_pin { + struct pinctrl_pin_desc pin; + const struct stm32_desc_function *functions; +}; + +#define STM32_PIN(_pin, ...) \ + { \ + .pin = _pin, \ + .functions = (struct stm32_desc_function[]){ \ + __VA_ARGS__, { } }, \ + } + +#define STM32_FUNCTION(_num, _name) \ + { \ + .num = _num, \ + .name = _name, \ + } + +struct stm32_pinctrl_match_data { + const struct stm32_desc_pin *pins; + const unsigned int npins; +}; + +int stm32_pctl_probe(struct platform_device *pdev); + +#endif /* __PINCTRL_STM32_H */ + diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f429.c b/drivers/pinctrl/stm32/pinctrl-stm32f429.c new file mode 100644 index 000000000000..f34016b51375 --- /dev/null +++ b/drivers/pinctrl/stm32/pinctrl-stm32f429.c @@ -0,0 +1,1598 @@ +/* + * Copyright (C) Maxime Coquelin 2015 + * Author: Maxime Coquelin + * License terms: GNU General Public License (GPL), version 2 + */ +#include +#include +#include +#include + +#include "pinctrl-stm32.h" + +static const struct stm32_desc_pin stm32f429_pins[] = { + STM32_PIN( + PINCTRL_PIN(0, "PA0"), + STM32_FUNCTION(0, "GPIOA0"), + STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"), + STM32_FUNCTION(3, "TIM5_CH1"), + STM32_FUNCTION(4, "TIM8_ETR"), + STM32_FUNCTION(8, "USART2_CTS"), + STM32_FUNCTION(9, "UART4_TX"), + STM32_FUNCTION(12, "ETH_MII_CRS"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(1, "PA1"), + STM32_FUNCTION(0, "GPIOA1"), + STM32_FUNCTION(2, "TIM2_CH2"), + STM32_FUNCTION(3, "TIM5_CH2"), + STM32_FUNCTION(8, "USART2_RTS"), + STM32_FUNCTION(9, "UART4_RX"), + STM32_FUNCTION(12, "ETH_MII_RX_CLK ETH_RMII_REF_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(2, "PA2"), + STM32_FUNCTION(0, "GPIOA2"), + STM32_FUNCTION(2, "TIM2_CH3"), + STM32_FUNCTION(3, "TIM5_CH3"), + STM32_FUNCTION(4, "TIM9_CH1"), + STM32_FUNCTION(8, "USART2_TX"), + STM32_FUNCTION(12, "ETH_MDIO"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(3, "PA3"), + STM32_FUNCTION(0, "GPIOA3"), + STM32_FUNCTION(2, "TIM2_CH4"), + STM32_FUNCTION(3, "TIM5_CH4"), + STM32_FUNCTION(4, "TIM9_CH2"), + STM32_FUNCTION(8, "USART2_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D0"), + STM32_FUNCTION(12, "ETH_MII_COL"), + STM32_FUNCTION(15, "LCD_B5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(4, "PA4"), + STM32_FUNCTION(0, "GPIOA4"), + STM32_FUNCTION(6, "SPI1_NSS"), + STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(8, "USART2_CK"), + STM32_FUNCTION(13, "OTG_HS_SOF"), + STM32_FUNCTION(14, "DCMI_HSYNC"), + STM32_FUNCTION(15, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(5, "PA5"), + STM32_FUNCTION(0, "GPIOA5"), + STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"), + STM32_FUNCTION(4, "TIM8_CH1N"), + STM32_FUNCTION(6, "SPI1_SCK"), + STM32_FUNCTION(11, "OTG_HS_ULPI_CK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(6, "PA6"), + STM32_FUNCTION(0, "GPIOA6"), + STM32_FUNCTION(2, "TIM1_BKIN"), + STM32_FUNCTION(3, "TIM3_CH1"), + STM32_FUNCTION(4, "TIM8_BKIN"), + STM32_FUNCTION(6, "SPI1_MISO"), + STM32_FUNCTION(10, "TIM13_CH1"), + STM32_FUNCTION(14, "DCMI_PIXCLK"), + STM32_FUNCTION(15, "LCD_G2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(7, "PA7"), + STM32_FUNCTION(0, "GPIOA7"), + STM32_FUNCTION(2, "TIM1_CH1N"), + STM32_FUNCTION(3, "TIM3_CH2"), + STM32_FUNCTION(4, "TIM8_CH1N"), + STM32_FUNCTION(6, "SPI1_MOSI"), + STM32_FUNCTION(10, "TIM14_CH1"), + STM32_FUNCTION(12, "ETH_MII_RX_DV ETH_RMII_CRS_DV"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(8, "PA8"), + STM32_FUNCTION(0, "GPIOA8"), + STM32_FUNCTION(1, "MCO1"), + STM32_FUNCTION(2, "TIM1_CH1"), + STM32_FUNCTION(5, "I2C3_SCL"), + STM32_FUNCTION(8, "USART1_CK"), + STM32_FUNCTION(11, "OTG_FS_SOF"), + STM32_FUNCTION(15, "LCD_R6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(9, "PA9"), + STM32_FUNCTION(0, "GPIOA9"), + STM32_FUNCTION(2, "TIM1_CH2"), + STM32_FUNCTION(5, "I2C3_SMBA"), + STM32_FUNCTION(8, "USART1_TX"), + STM32_FUNCTION(14, "DCMI_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(10, "PA10"), + STM32_FUNCTION(0, "GPIOA10"), + STM32_FUNCTION(2, "TIM1_CH3"), + STM32_FUNCTION(8, "USART1_RX"), + STM32_FUNCTION(11, "OTG_FS_ID"), + STM32_FUNCTION(14, "DCMI_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(11, "PA11"), + STM32_FUNCTION(0, "GPIOA11"), + STM32_FUNCTION(2, "TIM1_CH4"), + STM32_FUNCTION(8, "USART1_CTS"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(11, "OTG_FS_DM"), + STM32_FUNCTION(15, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(12, "PA12"), + STM32_FUNCTION(0, "GPIOA12"), + STM32_FUNCTION(2, "TIM1_ETR"), + STM32_FUNCTION(8, "USART1_RTS"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(11, "OTG_FS_DP"), + STM32_FUNCTION(15, "LCD_R5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(13, "PA13"), + STM32_FUNCTION(0, "GPIOA13"), + STM32_FUNCTION(1, "JTMS SWDIO"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(14, "PA14"), + STM32_FUNCTION(0, "GPIOA14"), + STM32_FUNCTION(1, "JTCK SWCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(15, "PA15"), + STM32_FUNCTION(0, "GPIOA15"), + STM32_FUNCTION(1, "JTDI"), + STM32_FUNCTION(2, "TIM2_CH1 TIM2_ETR"), + STM32_FUNCTION(6, "SPI1_NSS"), + STM32_FUNCTION(7, "SPI3_NSS I2S3_WS"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(16, "PB0"), + STM32_FUNCTION(0, "GPIOB0"), + STM32_FUNCTION(2, "TIM1_CH2N"), + STM32_FUNCTION(3, "TIM3_CH3"), + STM32_FUNCTION(4, "TIM8_CH2N"), + STM32_FUNCTION(10, "LCD_R3"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D1"), + STM32_FUNCTION(12, "ETH_MII_RXD2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(17, "PB1"), + STM32_FUNCTION(0, "GPIOB1"), + STM32_FUNCTION(2, "TIM1_CH3N"), + STM32_FUNCTION(3, "TIM3_CH4"), + STM32_FUNCTION(4, "TIM8_CH3N"), + STM32_FUNCTION(10, "LCD_R6"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D2"), + STM32_FUNCTION(12, "ETH_MII_RXD3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(18, "PB2"), + STM32_FUNCTION(0, "GPIOB2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(19, "PB3"), + STM32_FUNCTION(0, "GPIOB3"), + STM32_FUNCTION(1, "JTDO TRACESWO"), + STM32_FUNCTION(2, "TIM2_CH2"), + STM32_FUNCTION(6, "SPI1_SCK"), + STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(20, "PB4"), + STM32_FUNCTION(0, "GPIOB4"), + STM32_FUNCTION(1, "NJTRST"), + STM32_FUNCTION(3, "TIM3_CH1"), + STM32_FUNCTION(6, "SPI1_MISO"), + STM32_FUNCTION(7, "SPI3_MISO"), + STM32_FUNCTION(8, "I2S3EXT_SD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(21, "PB5"), + STM32_FUNCTION(0, "GPIOB5"), + STM32_FUNCTION(3, "TIM3_CH2"), + STM32_FUNCTION(5, "I2C1_SMBA"), + STM32_FUNCTION(6, "SPI1_MOSI"), + STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"), + STM32_FUNCTION(10, "CAN2_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D7"), + STM32_FUNCTION(12, "ETH_PPS_OUT"), + STM32_FUNCTION(13, "FMC_SDCKE1"), + STM32_FUNCTION(14, "DCMI_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(22, "PB6"), + STM32_FUNCTION(0, "GPIOB6"), + STM32_FUNCTION(3, "TIM4_CH1"), + STM32_FUNCTION(5, "I2C1_SCL"), + STM32_FUNCTION(8, "USART1_TX"), + STM32_FUNCTION(10, "CAN2_TX"), + STM32_FUNCTION(13, "FMC_SDNE1"), + STM32_FUNCTION(14, "DCMI_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(23, "PB7"), + STM32_FUNCTION(0, "GPIOB7"), + STM32_FUNCTION(3, "TIM4_CH2"), + STM32_FUNCTION(5, "I2C1_SDA"), + STM32_FUNCTION(8, "USART1_RX"), + STM32_FUNCTION(13, "FMC_NL"), + STM32_FUNCTION(14, "DCMI_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(24, "PB8"), + STM32_FUNCTION(0, "GPIOB8"), + STM32_FUNCTION(3, "TIM4_CH3"), + STM32_FUNCTION(4, "TIM10_CH1"), + STM32_FUNCTION(5, "I2C1_SCL"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(12, "ETH_MII_TXD3"), + STM32_FUNCTION(13, "SDIO_D4"), + STM32_FUNCTION(14, "DCMI_D6"), + STM32_FUNCTION(15, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(25, "PB9"), + STM32_FUNCTION(0, "GPIOB9"), + STM32_FUNCTION(3, "TIM4_CH4"), + STM32_FUNCTION(4, "TIM11_CH1"), + STM32_FUNCTION(5, "I2C1_SDA"), + STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(13, "SDIO_D5"), + STM32_FUNCTION(14, "DCMI_D7"), + STM32_FUNCTION(15, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(26, "PB10"), + STM32_FUNCTION(0, "GPIOB10"), + STM32_FUNCTION(2, "TIM2_CH3"), + STM32_FUNCTION(5, "I2C2_SCL"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(8, "USART3_TX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D3"), + STM32_FUNCTION(12, "ETH_MII_RX_ER"), + STM32_FUNCTION(15, "LCD_G4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(27, "PB11"), + STM32_FUNCTION(0, "GPIOB11"), + STM32_FUNCTION(2, "TIM2_CH4"), + STM32_FUNCTION(5, "I2C2_SDA"), + STM32_FUNCTION(8, "USART3_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D4"), + STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"), + STM32_FUNCTION(15, "LCD_G5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(28, "PB12"), + STM32_FUNCTION(0, "GPIOB12"), + STM32_FUNCTION(2, "TIM1_BKIN"), + STM32_FUNCTION(5, "I2C2_SMBA"), + STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(8, "USART3_CK"), + STM32_FUNCTION(10, "CAN2_RX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D5"), + STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"), + STM32_FUNCTION(13, "OTG_HS_ID"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(29, "PB13"), + STM32_FUNCTION(0, "GPIOB13"), + STM32_FUNCTION(2, "TIM1_CH1N"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(8, "USART3_CTS"), + STM32_FUNCTION(10, "CAN2_TX"), + STM32_FUNCTION(11, "OTG_HS_ULPI_D6"), + STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(30, "PB14"), + STM32_FUNCTION(0, "GPIOB14"), + STM32_FUNCTION(2, "TIM1_CH2N"), + STM32_FUNCTION(4, "TIM8_CH2N"), + STM32_FUNCTION(6, "SPI2_MISO"), + STM32_FUNCTION(7, "I2S2EXT_SD"), + STM32_FUNCTION(8, "USART3_RTS"), + STM32_FUNCTION(10, "TIM12_CH1"), + STM32_FUNCTION(13, "OTG_HS_DM"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(31, "PB15"), + STM32_FUNCTION(0, "GPIOB15"), + STM32_FUNCTION(1, "RTC_REFIN"), + STM32_FUNCTION(2, "TIM1_CH3N"), + STM32_FUNCTION(4, "TIM8_CH3N"), + STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"), + STM32_FUNCTION(10, "TIM12_CH2"), + STM32_FUNCTION(13, "OTG_HS_DP"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(32, "PC0"), + STM32_FUNCTION(0, "GPIOC0"), + STM32_FUNCTION(11, "OTG_HS_ULPI_STP"), + STM32_FUNCTION(13, "FMC_SDNWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(33, "PC1"), + STM32_FUNCTION(0, "GPIOC1"), + STM32_FUNCTION(12, "ETH_MDC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(34, "PC2"), + STM32_FUNCTION(0, "GPIOC2"), + STM32_FUNCTION(6, "SPI2_MISO"), + STM32_FUNCTION(7, "I2S2EXT_SD"), + STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"), + STM32_FUNCTION(12, "ETH_MII_TXD2"), + STM32_FUNCTION(13, "FMC_SDNE0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(35, "PC3"), + STM32_FUNCTION(0, "GPIOC3"), + STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"), + STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"), + STM32_FUNCTION(12, "ETH_MII_TX_CLK"), + STM32_FUNCTION(13, "FMC_SDCKE0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(36, "PC4"), + STM32_FUNCTION(0, "GPIOC4"), + STM32_FUNCTION(12, "ETH_MII_RXD0 ETH_RMII_RXD0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(37, "PC5"), + STM32_FUNCTION(0, "GPIOC5"), + STM32_FUNCTION(12, "ETH_MII_RXD1 ETH_RMII_RXD1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(38, "PC6"), + STM32_FUNCTION(0, "GPIOC6"), + STM32_FUNCTION(3, "TIM3_CH1"), + STM32_FUNCTION(4, "TIM8_CH1"), + STM32_FUNCTION(6, "I2S2_MCK"), + STM32_FUNCTION(9, "USART6_TX"), + STM32_FUNCTION(13, "SDIO_D6"), + STM32_FUNCTION(14, "DCMI_D0"), + STM32_FUNCTION(15, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(39, "PC7"), + STM32_FUNCTION(0, "GPIOC7"), + STM32_FUNCTION(3, "TIM3_CH2"), + STM32_FUNCTION(4, "TIM8_CH2"), + STM32_FUNCTION(7, "I2S3_MCK"), + STM32_FUNCTION(9, "USART6_RX"), + STM32_FUNCTION(13, "SDIO_D7"), + STM32_FUNCTION(14, "DCMI_D1"), + STM32_FUNCTION(15, "LCD_G6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(40, "PC8"), + STM32_FUNCTION(0, "GPIOC8"), + STM32_FUNCTION(3, "TIM3_CH3"), + STM32_FUNCTION(4, "TIM8_CH3"), + STM32_FUNCTION(9, "USART6_CK"), + STM32_FUNCTION(13, "SDIO_D0"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(41, "PC9"), + STM32_FUNCTION(0, "GPIOC9"), + STM32_FUNCTION(1, "MCO2"), + STM32_FUNCTION(3, "TIM3_CH4"), + STM32_FUNCTION(4, "TIM8_CH4"), + STM32_FUNCTION(5, "I2C3_SDA"), + STM32_FUNCTION(6, "I2S_CKIN"), + STM32_FUNCTION(13, "SDIO_D1"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(42, "PC10"), + STM32_FUNCTION(0, "GPIOC10"), + STM32_FUNCTION(7, "SPI3_SCK I2S3_CK"), + STM32_FUNCTION(8, "USART3_TX"), + STM32_FUNCTION(9, "UART4_TX"), + STM32_FUNCTION(13, "SDIO_D2"), + STM32_FUNCTION(14, "DCMI_D8"), + STM32_FUNCTION(15, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(43, "PC11"), + STM32_FUNCTION(0, "GPIOC11"), + STM32_FUNCTION(6, "I2S3EXT_SD"), + STM32_FUNCTION(7, "SPI3_MISO"), + STM32_FUNCTION(8, "USART3_RX"), + STM32_FUNCTION(9, "UART4_RX"), + STM32_FUNCTION(13, "SDIO_D3"), + STM32_FUNCTION(14, "DCMI_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(44, "PC12"), + STM32_FUNCTION(0, "GPIOC12"), + STM32_FUNCTION(7, "SPI3_MOSI I2S3_SD"), + STM32_FUNCTION(8, "USART3_CK"), + STM32_FUNCTION(9, "UART5_TX"), + STM32_FUNCTION(13, "SDIO_CK"), + STM32_FUNCTION(14, "DCMI_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(45, "PC13"), + STM32_FUNCTION(0, "GPIOC13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(46, "PC14"), + STM32_FUNCTION(0, "GPIOC14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(47, "PC15"), + STM32_FUNCTION(0, "GPIOC15"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(48, "PD0"), + STM32_FUNCTION(0, "GPIOD0"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(13, "FMC_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(49, "PD1"), + STM32_FUNCTION(0, "GPIOD1"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(13, "FMC_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(50, "PD2"), + STM32_FUNCTION(0, "GPIOD2"), + STM32_FUNCTION(3, "TIM3_ETR"), + STM32_FUNCTION(9, "UART5_RX"), + STM32_FUNCTION(13, "SDIO_CMD"), + STM32_FUNCTION(14, "DCMI_D11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(51, "PD3"), + STM32_FUNCTION(0, "GPIOD3"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(8, "USART2_CTS"), + STM32_FUNCTION(13, "FMC_CLK"), + STM32_FUNCTION(14, "DCMI_D5"), + STM32_FUNCTION(15, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(52, "PD4"), + STM32_FUNCTION(0, "GPIOD4"), + STM32_FUNCTION(8, "USART2_RTS"), + STM32_FUNCTION(13, "FMC_NOE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(53, "PD5"), + STM32_FUNCTION(0, "GPIOD5"), + STM32_FUNCTION(8, "USART2_TX"), + STM32_FUNCTION(13, "FMC_NWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(54, "PD6"), + STM32_FUNCTION(0, "GPIOD6"), + STM32_FUNCTION(6, "SPI3_MOSI I2S3_SD"), + STM32_FUNCTION(7, "SAI1_SD_A"), + STM32_FUNCTION(8, "USART2_RX"), + STM32_FUNCTION(13, "FMC_NWAIT"), + STM32_FUNCTION(14, "DCMI_D10"), + STM32_FUNCTION(15, "LCD_B2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(55, "PD7"), + STM32_FUNCTION(0, "GPIOD7"), + STM32_FUNCTION(8, "USART2_CK"), + STM32_FUNCTION(13, "FMC_NE1 FMC_NCE2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(56, "PD8"), + STM32_FUNCTION(0, "GPIOD8"), + STM32_FUNCTION(8, "USART3_TX"), + STM32_FUNCTION(13, "FMC_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(57, "PD9"), + STM32_FUNCTION(0, "GPIOD9"), + STM32_FUNCTION(8, "USART3_RX"), + STM32_FUNCTION(13, "FMC_D14"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(58, "PD10"), + STM32_FUNCTION(0, "GPIOD10"), + STM32_FUNCTION(8, "USART3_CK"), + STM32_FUNCTION(13, "FMC_D15"), + STM32_FUNCTION(15, "LCD_B3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(59, "PD11"), + STM32_FUNCTION(0, "GPIOD11"), + STM32_FUNCTION(8, "USART3_CTS"), + STM32_FUNCTION(13, "FMC_A16"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(60, "PD12"), + STM32_FUNCTION(0, "GPIOD12"), + STM32_FUNCTION(3, "TIM4_CH1"), + STM32_FUNCTION(8, "USART3_RTS"), + STM32_FUNCTION(13, "FMC_A17"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(61, "PD13"), + STM32_FUNCTION(0, "GPIOD13"), + STM32_FUNCTION(3, "TIM4_CH2"), + STM32_FUNCTION(13, "FMC_A18"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(62, "PD14"), + STM32_FUNCTION(0, "GPIOD14"), + STM32_FUNCTION(3, "TIM4_CH3"), + STM32_FUNCTION(13, "FMC_D0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(63, "PD15"), + STM32_FUNCTION(0, "GPIOD15"), + STM32_FUNCTION(3, "TIM4_CH4"), + STM32_FUNCTION(13, "FMC_D1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(64, "PE0"), + STM32_FUNCTION(0, "GPIOE0"), + STM32_FUNCTION(3, "TIM4_ETR"), + STM32_FUNCTION(9, "UART8_RX"), + STM32_FUNCTION(13, "FMC_NBL0"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(65, "PE1"), + STM32_FUNCTION(0, "GPIOE1"), + STM32_FUNCTION(9, "UART8_TX"), + STM32_FUNCTION(13, "FMC_NBL1"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(66, "PE2"), + STM32_FUNCTION(0, "GPIOE2"), + STM32_FUNCTION(1, "TRACECLK"), + STM32_FUNCTION(6, "SPI4_SCK"), + STM32_FUNCTION(7, "SAI1_MCLK_A"), + STM32_FUNCTION(12, "ETH_MII_TXD3"), + STM32_FUNCTION(13, "FMC_A23"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(67, "PE3"), + STM32_FUNCTION(0, "GPIOE3"), + STM32_FUNCTION(1, "TRACED0"), + STM32_FUNCTION(7, "SAI1_SD_B"), + STM32_FUNCTION(13, "FMC_A19"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(68, "PE4"), + STM32_FUNCTION(0, "GPIOE4"), + STM32_FUNCTION(1, "TRACED1"), + STM32_FUNCTION(6, "SPI4_NSS"), + STM32_FUNCTION(7, "SAI1_FS_A"), + STM32_FUNCTION(13, "FMC_A20"), + STM32_FUNCTION(14, "DCMI_D4"), + STM32_FUNCTION(15, "LCD_B0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(69, "PE5"), + STM32_FUNCTION(0, "GPIOE5"), + STM32_FUNCTION(1, "TRACED2"), + STM32_FUNCTION(4, "TIM9_CH1"), + STM32_FUNCTION(6, "SPI4_MISO"), + STM32_FUNCTION(7, "SAI1_SCK_A"), + STM32_FUNCTION(13, "FMC_A21"), + STM32_FUNCTION(14, "DCMI_D6"), + STM32_FUNCTION(15, "LCD_G0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(70, "PE6"), + STM32_FUNCTION(0, "GPIOE6"), + STM32_FUNCTION(1, "TRACED3"), + STM32_FUNCTION(4, "TIM9_CH2"), + STM32_FUNCTION(6, "SPI4_MOSI"), + STM32_FUNCTION(7, "SAI1_SD_A"), + STM32_FUNCTION(13, "FMC_A22"), + STM32_FUNCTION(14, "DCMI_D7"), + STM32_FUNCTION(15, "LCD_G1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(71, "PE7"), + STM32_FUNCTION(0, "GPIOE7"), + STM32_FUNCTION(2, "TIM1_ETR"), + STM32_FUNCTION(9, "UART7_RX"), + STM32_FUNCTION(13, "FMC_D4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(72, "PE8"), + STM32_FUNCTION(0, "GPIOE8"), + STM32_FUNCTION(2, "TIM1_CH1N"), + STM32_FUNCTION(9, "UART7_TX"), + STM32_FUNCTION(13, "FMC_D5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(73, "PE9"), + STM32_FUNCTION(0, "GPIOE9"), + STM32_FUNCTION(2, "TIM1_CH1"), + STM32_FUNCTION(13, "FMC_D6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(74, "PE10"), + STM32_FUNCTION(0, "GPIOE10"), + STM32_FUNCTION(2, "TIM1_CH2N"), + STM32_FUNCTION(13, "FMC_D7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(75, "PE11"), + STM32_FUNCTION(0, "GPIOE11"), + STM32_FUNCTION(2, "TIM1_CH2"), + STM32_FUNCTION(6, "SPI4_NSS"), + STM32_FUNCTION(13, "FMC_D8"), + STM32_FUNCTION(15, "LCD_G3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(76, "PE12"), + STM32_FUNCTION(0, "GPIOE12"), + STM32_FUNCTION(2, "TIM1_CH3N"), + STM32_FUNCTION(6, "SPI4_SCK"), + STM32_FUNCTION(13, "FMC_D9"), + STM32_FUNCTION(15, "LCD_B4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(77, "PE13"), + STM32_FUNCTION(0, "GPIOE13"), + STM32_FUNCTION(2, "TIM1_CH3"), + STM32_FUNCTION(6, "SPI4_MISO"), + STM32_FUNCTION(13, "FMC_D10"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(78, "PE14"), + STM32_FUNCTION(0, "GPIOE14"), + STM32_FUNCTION(2, "TIM1_CH4"), + STM32_FUNCTION(6, "SPI4_MOSI"), + STM32_FUNCTION(13, "FMC_D11"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(79, "PE15"), + STM32_FUNCTION(0, "GPIOE15"), + STM32_FUNCTION(2, "TIM1_BKIN"), + STM32_FUNCTION(13, "FMC_D12"), + STM32_FUNCTION(15, "LCD_R7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(80, "PF0"), + STM32_FUNCTION(0, "GPIOF0"), + STM32_FUNCTION(5, "I2C2_SDA"), + STM32_FUNCTION(13, "FMC_A0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(81, "PF1"), + STM32_FUNCTION(0, "GPIOF1"), + STM32_FUNCTION(5, "I2C2_SCL"), + STM32_FUNCTION(13, "FMC_A1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(82, "PF2"), + STM32_FUNCTION(0, "GPIOF2"), + STM32_FUNCTION(5, "I2C2_SMBA"), + STM32_FUNCTION(13, "FMC_A2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(83, "PF3"), + STM32_FUNCTION(0, "GPIOF3"), + STM32_FUNCTION(13, "FMC_A3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(84, "PF4"), + STM32_FUNCTION(0, "GPIOF4"), + STM32_FUNCTION(13, "FMC_A4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(85, "PF5"), + STM32_FUNCTION(0, "GPIOF5"), + STM32_FUNCTION(13, "FMC_A5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(86, "PF6"), + STM32_FUNCTION(0, "GPIOF6"), + STM32_FUNCTION(4, "TIM10_CH1"), + STM32_FUNCTION(6, "SPI5_NSS"), + STM32_FUNCTION(7, "SAI1_SD_B"), + STM32_FUNCTION(9, "UART7_RX"), + STM32_FUNCTION(13, "FMC_NIORD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(87, "PF7"), + STM32_FUNCTION(0, "GPIOF7"), + STM32_FUNCTION(4, "TIM11_CH1"), + STM32_FUNCTION(6, "SPI5_SCK"), + STM32_FUNCTION(7, "SAI1_MCLK_B"), + STM32_FUNCTION(9, "UART7_TX"), + STM32_FUNCTION(13, "FMC_NREG"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(88, "PF8"), + STM32_FUNCTION(0, "GPIOF8"), + STM32_FUNCTION(6, "SPI5_MISO"), + STM32_FUNCTION(7, "SAI1_SCK_B"), + STM32_FUNCTION(10, "TIM13_CH1"), + STM32_FUNCTION(13, "FMC_NIOWR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(89, "PF9"), + STM32_FUNCTION(0, "GPIOF9"), + STM32_FUNCTION(6, "SPI5_MOSI"), + STM32_FUNCTION(7, "SAI1_FS_B"), + STM32_FUNCTION(10, "TIM14_CH1"), + STM32_FUNCTION(13, "FMC_CD"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(90, "PF10"), + STM32_FUNCTION(0, "GPIOF10"), + STM32_FUNCTION(13, "FMC_INTR"), + STM32_FUNCTION(14, "DCMI_D11"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(91, "PF11"), + STM32_FUNCTION(0, "GPIOF11"), + STM32_FUNCTION(6, "SPI5_MOSI"), + STM32_FUNCTION(13, "FMC_SDNRAS"), + STM32_FUNCTION(14, "DCMI_D12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(92, "PF12"), + STM32_FUNCTION(0, "GPIOF12"), + STM32_FUNCTION(13, "FMC_A6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(93, "PF13"), + STM32_FUNCTION(0, "GPIOF13"), + STM32_FUNCTION(13, "FMC_A7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(94, "PF14"), + STM32_FUNCTION(0, "GPIOF14"), + STM32_FUNCTION(13, "FMC_A8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(95, "PF15"), + STM32_FUNCTION(0, "GPIOF15"), + STM32_FUNCTION(13, "FMC_A9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(96, "PG0"), + STM32_FUNCTION(0, "GPIOG0"), + STM32_FUNCTION(13, "FMC_A10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(97, "PG1"), + STM32_FUNCTION(0, "GPIOG1"), + STM32_FUNCTION(13, "FMC_A11"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(98, "PG2"), + STM32_FUNCTION(0, "GPIOG2"), + STM32_FUNCTION(13, "FMC_A12"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(99, "PG3"), + STM32_FUNCTION(0, "GPIOG3"), + STM32_FUNCTION(13, "FMC_A13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(100, "PG4"), + STM32_FUNCTION(0, "GPIOG4"), + STM32_FUNCTION(13, "FMC_A14 FMC_BA0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(101, "PG5"), + STM32_FUNCTION(0, "GPIOG5"), + STM32_FUNCTION(13, "FMC_A15 FMC_BA1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(102, "PG6"), + STM32_FUNCTION(0, "GPIOG6"), + STM32_FUNCTION(13, "FMC_INT2"), + STM32_FUNCTION(14, "DCMI_D12"), + STM32_FUNCTION(15, "LCD_R7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(103, "PG7"), + STM32_FUNCTION(0, "GPIOG7"), + STM32_FUNCTION(9, "USART6_CK"), + STM32_FUNCTION(13, "FMC_INT3"), + STM32_FUNCTION(14, "DCMI_D13"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(104, "PG8"), + STM32_FUNCTION(0, "GPIOG8"), + STM32_FUNCTION(6, "SPI6_NSS"), + STM32_FUNCTION(9, "USART6_RTS"), + STM32_FUNCTION(12, "ETH_PPS_OUT"), + STM32_FUNCTION(13, "FMC_SDCLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(105, "PG9"), + STM32_FUNCTION(0, "GPIOG9"), + STM32_FUNCTION(9, "USART6_RX"), + STM32_FUNCTION(13, "FMC_NE2 FMC_NCE3"), + STM32_FUNCTION(14, "DCMI_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(106, "PG10"), + STM32_FUNCTION(0, "GPIOG10"), + STM32_FUNCTION(10, "LCD_G3"), + STM32_FUNCTION(13, "FMC_NCE4_1 FMC_NE3"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(15, "LCD_B2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(107, "PG11"), + STM32_FUNCTION(0, "GPIOG11"), + STM32_FUNCTION(12, "ETH_MII_TX_EN ETH_RMII_TX_EN"), + STM32_FUNCTION(13, "FMC_NCE4_2"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(15, "LCD_B3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(108, "PG12"), + STM32_FUNCTION(0, "GPIOG12"), + STM32_FUNCTION(6, "SPI6_MISO"), + STM32_FUNCTION(9, "USART6_RTS"), + STM32_FUNCTION(10, "LCD_B4"), + STM32_FUNCTION(13, "FMC_NE4"), + STM32_FUNCTION(15, "LCD_B1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(109, "PG13"), + STM32_FUNCTION(0, "GPIOG13"), + STM32_FUNCTION(6, "SPI6_SCK"), + STM32_FUNCTION(9, "USART6_CTS"), + STM32_FUNCTION(12, "ETH_MII_TXD0 ETH_RMII_TXD0"), + STM32_FUNCTION(13, "FMC_A24"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(110, "PG14"), + STM32_FUNCTION(0, "GPIOG14"), + STM32_FUNCTION(6, "SPI6_MOSI"), + STM32_FUNCTION(9, "USART6_TX"), + STM32_FUNCTION(12, "ETH_MII_TXD1 ETH_RMII_TXD1"), + STM32_FUNCTION(13, "FMC_A25"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(111, "PG15"), + STM32_FUNCTION(0, "GPIOG15"), + STM32_FUNCTION(9, "USART6_CTS"), + STM32_FUNCTION(13, "FMC_SDNCAS"), + STM32_FUNCTION(14, "DCMI_D13"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(112, "PH0"), + STM32_FUNCTION(0, "GPIOH0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(113, "PH1"), + STM32_FUNCTION(0, "GPIOH1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(114, "PH2"), + STM32_FUNCTION(0, "GPIOH2"), + STM32_FUNCTION(12, "ETH_MII_CRS"), + STM32_FUNCTION(13, "FMC_SDCKE0"), + STM32_FUNCTION(15, "LCD_R0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(115, "PH3"), + STM32_FUNCTION(0, "GPIOH3"), + STM32_FUNCTION(12, "ETH_MII_COL"), + STM32_FUNCTION(13, "FMC_SDNE0"), + STM32_FUNCTION(15, "LCD_R1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(116, "PH4"), + STM32_FUNCTION(0, "GPIOH4"), + STM32_FUNCTION(5, "I2C2_SCL"), + STM32_FUNCTION(11, "OTG_HS_ULPI_NXT"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(117, "PH5"), + STM32_FUNCTION(0, "GPIOH5"), + STM32_FUNCTION(5, "I2C2_SDA"), + STM32_FUNCTION(6, "SPI5_NSS"), + STM32_FUNCTION(13, "FMC_SDNWE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(118, "PH6"), + STM32_FUNCTION(0, "GPIOH6"), + STM32_FUNCTION(5, "I2C2_SMBA"), + STM32_FUNCTION(6, "SPI5_SCK"), + STM32_FUNCTION(10, "TIM12_CH1"), + STM32_FUNCTION(12, "ETH_MII_RXD2"), + STM32_FUNCTION(13, "FMC_SDNE1"), + STM32_FUNCTION(14, "DCMI_D8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(119, "PH7"), + STM32_FUNCTION(0, "GPIOH7"), + STM32_FUNCTION(5, "I2C3_SCL"), + STM32_FUNCTION(6, "SPI5_MISO"), + STM32_FUNCTION(12, "ETH_MII_RXD3"), + STM32_FUNCTION(13, "FMC_SDCKE1"), + STM32_FUNCTION(14, "DCMI_D9"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(120, "PH8"), + STM32_FUNCTION(0, "GPIOH8"), + STM32_FUNCTION(5, "I2C3_SDA"), + STM32_FUNCTION(13, "FMC_D16"), + STM32_FUNCTION(14, "DCMI_HSYNC"), + STM32_FUNCTION(15, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(121, "PH9"), + STM32_FUNCTION(0, "GPIOH9"), + STM32_FUNCTION(5, "I2C3_SMBA"), + STM32_FUNCTION(10, "TIM12_CH2"), + STM32_FUNCTION(13, "FMC_D17"), + STM32_FUNCTION(14, "DCMI_D0"), + STM32_FUNCTION(15, "LCD_R3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(122, "PH10"), + STM32_FUNCTION(0, "GPIOH10"), + STM32_FUNCTION(3, "TIM5_CH1"), + STM32_FUNCTION(13, "FMC_D18"), + STM32_FUNCTION(14, "DCMI_D1"), + STM32_FUNCTION(15, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(123, "PH11"), + STM32_FUNCTION(0, "GPIOH11"), + STM32_FUNCTION(3, "TIM5_CH2"), + STM32_FUNCTION(13, "FMC_D19"), + STM32_FUNCTION(14, "DCMI_D2"), + STM32_FUNCTION(15, "LCD_R5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(124, "PH12"), + STM32_FUNCTION(0, "GPIOH12"), + STM32_FUNCTION(3, "TIM5_CH3"), + STM32_FUNCTION(13, "FMC_D20"), + STM32_FUNCTION(14, "DCMI_D3"), + STM32_FUNCTION(15, "LCD_R6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(125, "PH13"), + STM32_FUNCTION(0, "GPIOH13"), + STM32_FUNCTION(4, "TIM8_CH1N"), + STM32_FUNCTION(10, "CAN1_TX"), + STM32_FUNCTION(13, "FMC_D21"), + STM32_FUNCTION(15, "LCD_G2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(126, "PH14"), + STM32_FUNCTION(0, "GPIOH14"), + STM32_FUNCTION(4, "TIM8_CH2N"), + STM32_FUNCTION(13, "FMC_D22"), + STM32_FUNCTION(14, "DCMI_D4"), + STM32_FUNCTION(15, "LCD_G3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(127, "PH15"), + STM32_FUNCTION(0, "GPIOH15"), + STM32_FUNCTION(4, "TIM8_CH3N"), + STM32_FUNCTION(13, "FMC_D23"), + STM32_FUNCTION(14, "DCMI_D11"), + STM32_FUNCTION(15, "LCD_G4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(128, "PI0"), + STM32_FUNCTION(0, "GPIOI0"), + STM32_FUNCTION(3, "TIM5_CH4"), + STM32_FUNCTION(6, "SPI2_NSS I2S2_WS"), + STM32_FUNCTION(13, "FMC_D24"), + STM32_FUNCTION(14, "DCMI_D13"), + STM32_FUNCTION(15, "LCD_G5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(129, "PI1"), + STM32_FUNCTION(0, "GPIOI1"), + STM32_FUNCTION(6, "SPI2_SCK I2S2_CK"), + STM32_FUNCTION(13, "FMC_D25"), + STM32_FUNCTION(14, "DCMI_D8"), + STM32_FUNCTION(15, "LCD_G6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(130, "PI2"), + STM32_FUNCTION(0, "GPIOI2"), + STM32_FUNCTION(4, "TIM8_CH4"), + STM32_FUNCTION(6, "SPI2_MISO"), + STM32_FUNCTION(7, "I2S2EXT_SD"), + STM32_FUNCTION(13, "FMC_D26"), + STM32_FUNCTION(14, "DCMI_D9"), + STM32_FUNCTION(15, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(131, "PI3"), + STM32_FUNCTION(0, "GPIOI3"), + STM32_FUNCTION(4, "TIM8_ETR"), + STM32_FUNCTION(6, "SPI2_MOSI I2S2_SD"), + STM32_FUNCTION(13, "FMC_D27"), + STM32_FUNCTION(14, "DCMI_D10"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(132, "PI4"), + STM32_FUNCTION(0, "GPIOI4"), + STM32_FUNCTION(4, "TIM8_BKIN"), + STM32_FUNCTION(13, "FMC_NBL2"), + STM32_FUNCTION(14, "DCMI_D5"), + STM32_FUNCTION(15, "LCD_B4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(133, "PI5"), + STM32_FUNCTION(0, "GPIOI5"), + STM32_FUNCTION(4, "TIM8_CH1"), + STM32_FUNCTION(13, "FMC_NBL3"), + STM32_FUNCTION(14, "DCMI_VSYNC"), + STM32_FUNCTION(15, "LCD_B5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(134, "PI6"), + STM32_FUNCTION(0, "GPIOI6"), + STM32_FUNCTION(4, "TIM8_CH2"), + STM32_FUNCTION(13, "FMC_D28"), + STM32_FUNCTION(14, "DCMI_D6"), + STM32_FUNCTION(15, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(135, "PI7"), + STM32_FUNCTION(0, "GPIOI7"), + STM32_FUNCTION(4, "TIM8_CH3"), + STM32_FUNCTION(13, "FMC_D29"), + STM32_FUNCTION(14, "DCMI_D7"), + STM32_FUNCTION(15, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(136, "PI8"), + STM32_FUNCTION(0, "GPIOI8"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(137, "PI9"), + STM32_FUNCTION(0, "GPIOI9"), + STM32_FUNCTION(10, "CAN1_RX"), + STM32_FUNCTION(13, "FMC_D30"), + STM32_FUNCTION(15, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(138, "PI10"), + STM32_FUNCTION(0, "GPIOI10"), + STM32_FUNCTION(12, "ETH_MII_RX_ER"), + STM32_FUNCTION(13, "FMC_D31"), + STM32_FUNCTION(15, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(139, "PI11"), + STM32_FUNCTION(0, "GPIOI11"), + STM32_FUNCTION(11, "OTG_HS_ULPI_DIR"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(140, "PI12"), + STM32_FUNCTION(0, "GPIOI12"), + STM32_FUNCTION(15, "LCD_HSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(141, "PI13"), + STM32_FUNCTION(0, "GPIOI13"), + STM32_FUNCTION(15, "LCD_VSYNC"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(142, "PI14"), + STM32_FUNCTION(0, "GPIOI14"), + STM32_FUNCTION(15, "LCD_CLK"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(143, "PI15"), + STM32_FUNCTION(0, "GPIOI15"), + STM32_FUNCTION(15, "LCD_R0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(144, "PJ0"), + STM32_FUNCTION(0, "GPIOJ0"), + STM32_FUNCTION(15, "LCD_R1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(145, "PJ1"), + STM32_FUNCTION(0, "GPIOJ1"), + STM32_FUNCTION(15, "LCD_R2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(146, "PJ2"), + STM32_FUNCTION(0, "GPIOJ2"), + STM32_FUNCTION(15, "LCD_R3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(147, "PJ3"), + STM32_FUNCTION(0, "GPIOJ3"), + STM32_FUNCTION(15, "LCD_R4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(148, "PJ4"), + STM32_FUNCTION(0, "GPIOJ4"), + STM32_FUNCTION(15, "LCD_R5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(149, "PJ5"), + STM32_FUNCTION(0, "GPIOJ5"), + STM32_FUNCTION(15, "LCD_R6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(150, "PJ6"), + STM32_FUNCTION(0, "GPIOJ6"), + STM32_FUNCTION(15, "LCD_R7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(151, "PJ7"), + STM32_FUNCTION(0, "GPIOJ7"), + STM32_FUNCTION(15, "LCD_G0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(152, "PJ8"), + STM32_FUNCTION(0, "GPIOJ8"), + STM32_FUNCTION(15, "LCD_G1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(153, "PJ9"), + STM32_FUNCTION(0, "GPIOJ9"), + STM32_FUNCTION(15, "LCD_G2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(154, "PJ10"), + STM32_FUNCTION(0, "GPIOJ10"), + STM32_FUNCTION(15, "LCD_G3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(155, "PJ11"), + STM32_FUNCTION(0, "GPIOJ11"), + STM32_FUNCTION(15, "LCD_G4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(156, "PJ12"), + STM32_FUNCTION(0, "GPIOJ12"), + STM32_FUNCTION(15, "LCD_B0"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(157, "PJ13"), + STM32_FUNCTION(0, "GPIOJ13"), + STM32_FUNCTION(15, "LCD_B1"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(158, "PJ14"), + STM32_FUNCTION(0, "GPIOJ14"), + STM32_FUNCTION(15, "LCD_B2"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(159, "PJ15"), + STM32_FUNCTION(0, "GPIOJ15"), + STM32_FUNCTION(15, "LCD_B3"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(160, "PK0"), + STM32_FUNCTION(0, "GPIOK0"), + STM32_FUNCTION(15, "LCD_G5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(161, "PK1"), + STM32_FUNCTION(0, "GPIOK1"), + STM32_FUNCTION(15, "LCD_G6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(162, "PK2"), + STM32_FUNCTION(0, "GPIOK2"), + STM32_FUNCTION(15, "LCD_G7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(163, "PK3"), + STM32_FUNCTION(0, "GPIOK3"), + STM32_FUNCTION(15, "LCD_B4"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(164, "PK4"), + STM32_FUNCTION(0, "GPIOK4"), + STM32_FUNCTION(15, "LCD_B5"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(165, "PK5"), + STM32_FUNCTION(0, "GPIOK5"), + STM32_FUNCTION(15, "LCD_B6"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(166, "PK6"), + STM32_FUNCTION(0, "GPIOK6"), + STM32_FUNCTION(15, "LCD_B7"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), + STM32_PIN( + PINCTRL_PIN(167, "PK7"), + STM32_FUNCTION(0, "GPIOK7"), + STM32_FUNCTION(15, "LCD_DE"), + STM32_FUNCTION(16, "EVENTOUT"), + STM32_FUNCTION(17, "ANALOG") + ), +}; + +static struct stm32_pinctrl_match_data stm32f429_match_data = { + .pins = stm32f429_pins, + .npins = ARRAY_SIZE(stm32f429_pins), +}; + +static const struct of_device_id stm32f429_pctrl_match[] = { + { + .compatible = "st,stm32f429-pinctrl", + .data = &stm32f429_match_data, + }, + { } +}; +MODULE_DEVICE_TABLE(of, stm32f429_pctrl_match); + +static struct platform_driver stm32f429_pinctrl_driver = { + .probe = stm32_pctl_probe, + .driver = { + .name = "stm32f429-pinctrl", + .of_match_table = stm32f429_pctrl_match, + }, +}; + +static int __init stm32f429_pinctrl_init(void) +{ + return platform_driver_register(&stm32f429_pinctrl_driver); +} + +module_init(stm32f429_pinctrl_init); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("STM32F429 Pinctrl Driver"); +MODULE_AUTHOR("Maxime Coquelin "); -- cgit From 712a8038cc24dba668afe82f0413714ca87184e0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 27 Jan 2016 14:26:18 +0100 Subject: ASoC: ssm4567: Reset device before regcache_sync() When the ssm4567 is powered up the driver calles regcache_sync() to restore the register map content. regcache_sync() assumes that the device is in its power-on reset state. Make sure that this is the case by explicitly resetting the ssm4567 register map before calling regcache_sync() otherwise we might end up with a incorrect register map which leads to undefined behaviour. One such undefined behaviour was observed when returning from system suspend while a playback stream is active, in that case the ssm4567 was kept muted after resume. Fixes: 1ee44ce03011 ("ASoC: ssm4567: Add driver for Analog Devices SSM4567 amplifier") Reported-by: Harsha Priya Tested-by: Fang, Yang A Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/ssm4567.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index e619d5651b09..080c78e88e10 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -352,6 +352,11 @@ static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable) regcache_cache_only(ssm4567->regmap, !enable); if (enable) { + ret = regmap_write(ssm4567->regmap, SSM4567_REG_SOFT_RESET, + 0x00); + if (ret) + return ret; + ret = regmap_update_bits(ssm4567->regmap, SSM4567_REG_POWER_CTRL, SSM4567_POWER_SPWDN, 0x00); -- cgit From 7315917f7ccdf5eb5758f663a781daa7599d63d7 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Mon, 25 Jan 2016 18:23:30 +0100 Subject: ASoC: rk3036: fix missing dependency on REGMAP_MMIO When SND_SOC_INNO_RK3036 is enabled but REGMAP_MMIO is not, the MODPOST step fails with this error: ... Kernel: arch/x86/boot/bzImage is ready (#3) Building modules, stage 2. MODPOST 3203 modules ERROR: "__devm_regmap_init_mmio_clk" [sound/soc/codecs/snd-soc-inno-rk3036.ko] undefined! Signed-off-by: Antonio Ospite 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 50693c867e71..1f7eaa919088 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -497,6 +497,7 @@ config SND_SOC_ICS43432 config SND_SOC_INNO_RK3036 tristate "Inno codec driver for RK3036 SoC" + select REGMAP_MMIO config SND_SOC_ISABELLE tristate -- cgit From cc301fd1fcf28f92b122f7f6105db9d7c182cccc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 4 Jan 2016 12:44:10 -0500 Subject: pinctrl: mediatek: mt8* make driver explicitly non-modular The Kconfig for these drivers are currently: config PINCTRL_MT8127 bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127 config PINCTRL_MT8135 bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135 config PINCTRL_MT8173 bool "Mediatek MT8173 pin control" ...meaning that they are currently 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. A recent commit moved these from module_init to arch_initcall already, so the init ordering remains untouched 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. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Daniel Kurtz Cc: Matthias Brugger Cc: Hongzhou Yang Cc: Yingjoe Chen Cc: linux-gpio@vger.kernel.org Cc: linux-mediatek@lists.infradead.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mt8127.c | 8 +------- drivers/pinctrl/mediatek/pinctrl-mt8135.c | 8 +------- drivers/pinctrl/mediatek/pinctrl-mt8173.c | 8 +------- 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c index 98e0bebfdf92..d76491574841 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c @@ -13,7 +13,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -336,7 +336,6 @@ static const struct of_device_id mt8127_pctrl_match[] = { { .compatible = "mediatek,mt8127-pinctrl", }, { } }; -MODULE_DEVICE_TABLE(of, mt8127_pctrl_match); static struct platform_driver mtk_pinctrl_driver = { .probe = mt8127_pinctrl_probe, @@ -350,9 +349,4 @@ static int __init mtk_pinctrl_init(void) { return platform_driver_register(&mtk_pinctrl_driver); } - arch_initcall(mtk_pinctrl_init); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MediaTek MT8127 Pinctrl Driver"); -MODULE_AUTHOR("Yingjoe Chen "); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c index 1c153b860f36..d8c645f16f21 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c @@ -12,7 +12,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -351,7 +351,6 @@ static const struct of_device_id mt8135_pctrl_match[] = { }, { } }; -MODULE_DEVICE_TABLE(of, mt8135_pctrl_match); static struct platform_driver mtk_pinctrl_driver = { .probe = mt8135_pinctrl_probe, @@ -365,9 +364,4 @@ static int __init mtk_pinctrl_init(void) { return platform_driver_register(&mtk_pinctrl_driver); } - arch_initcall(mtk_pinctrl_init); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MediaTek Pinctrl Driver"); -MODULE_AUTHOR("Hongzhou Yang "); diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c index a62514eb2129..8bfd427b9135 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c @@ -12,7 +12,7 @@ * GNU General Public License for more details. */ -#include +#include #include #include #include @@ -378,7 +378,6 @@ static const struct of_device_id mt8173_pctrl_match[] = { }, { } }; -MODULE_DEVICE_TABLE(of, mt8173_pctrl_match); static struct platform_driver mtk_pinctrl_driver = { .probe = mt8173_pinctrl_probe, @@ -393,9 +392,4 @@ static int __init mtk_pinctrl_init(void) { return platform_driver_register(&mtk_pinctrl_driver); } - arch_initcall(mtk_pinctrl_init); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MediaTek Pinctrl Driver"); -MODULE_AUTHOR("Hongzhou Yang "); -- cgit From 23c3960dfe6faea6fa8b8cb0bfedba2a03bda0c1 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 8 Jan 2016 10:50:30 -0800 Subject: pinctrl: freescale: imx: implement gpio_disable_free for Vybrid The Freescale Vybrid SoC has GPIO capabilities as part of the IOMUXC. To enable GPIO's, the gpio_request_enable callback has been implemented, however the corsponding gpio_disable_free callback is missing. So far, disabling (unexporting) a GPIO left the pin in its last state. Implement a proper gpio_disable_free function which clears the three enable bits which influence the state (IBE, OBE and PUE). Signed-off-by: Stefan Agner Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-imx.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index a5bb93987378..4c435cfa5d6e 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -341,6 +341,31 @@ mux_pin: return 0; } +static void imx_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned offset) +{ + struct imx_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev); + const struct imx_pinctrl_soc_info *info = ipctl->info; + const struct imx_pin_reg *pin_reg; + u32 reg; + + /* + * Only Vybrid has the input/output buffer enable flags (IBE/OBE) + * They are part of the shared mux/conf register. + */ + if (!(info->flags & SHARE_MUX_CONF_REG)) + return; + + pin_reg = &info->pin_regs[offset]; + if (pin_reg->mux_reg == -1) + return; + + /* Clear IBE/OBE/PUE to disable the pin (Hi-Z) */ + reg = readl(ipctl->base + pin_reg->mux_reg); + reg &= ~0x7; + writel(reg, ipctl->base + pin_reg->mux_reg); +} + static int imx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset, bool input) { @@ -377,6 +402,7 @@ static const struct pinmux_ops imx_pmx_ops = { .get_function_groups = imx_pmx_get_groups, .set_mux = imx_pmx_set, .gpio_request_enable = imx_pmx_gpio_request_enable, + .gpio_disable_free = imx_pmx_gpio_disable_free, .gpio_set_direction = imx_pmx_gpio_set_direction, }; -- cgit From ae6d54fd695d7e1bd7b0bdaf457074ae4b5ad7bb Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 8 Jan 2016 12:25:53 -0800 Subject: pinctrl: qcom: spmi-mpp: Skip pullup on ULT type MPPs The ULT type of MPPs don't have a pullup. Skip configuring the pullup on these types of pins. Cc: Bjorn Andersson Signed-off-by: Stephen Boyd Reviewed-by: Andy Gross Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-spmi-mpp.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c index 2f18323571a6..2a3e5490a483 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c @@ -117,6 +117,7 @@ * @output_enabled: Set to true if MPP output logic is enabled. * @input_enabled: Set to true if MPP input buffer logic is enabled. * @paired: Pin operates in paired mode + * @has_pullup: Pin has support to configure pullup * @num_sources: Number of power-sources supported by this MPP. * @power_source: Current power-source used. * @amux_input: Set the source for analog input. @@ -134,6 +135,7 @@ struct pmic_mpp_pad { bool output_enabled; bool input_enabled; bool paired; + bool has_pullup; unsigned int num_sources; unsigned int power_source; unsigned int amux_input; @@ -477,11 +479,14 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin, if (ret < 0) return ret; - val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT; + if (pad->has_pullup) { + val = pad->pullup << PMIC_MPP_REG_PULL_SHIFT; - ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL, val); - if (ret < 0) - return ret; + ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_DIG_PULL_CTL, + val); + if (ret < 0) + return ret; + } val = pad->amux_input & PMIC_MPP_REG_AIN_ROUTE_MASK; @@ -534,7 +539,8 @@ static void pmic_mpp_config_dbg_show(struct pinctrl_dev *pctldev, seq_printf(s, " %-7s", pmic_mpp_functions[pad->function]); seq_printf(s, " vin-%d", pad->power_source); seq_printf(s, " %d", pad->aout_level); - seq_printf(s, " %-8s", biases[pad->pullup]); + if (pad->has_pullup) + seq_printf(s, " %-8s", biases[pad->pullup]); seq_printf(s, " %-4s", pad->out_value ? "high" : "low"); if (pad->dtest) seq_printf(s, " dtest%d", pad->dtest); @@ -748,12 +754,16 @@ static int pmic_mpp_populate(struct pmic_mpp_state *state, pad->power_source = val >> PMIC_MPP_REG_VIN_SHIFT; pad->power_source &= PMIC_MPP_REG_VIN_MASK; - val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL); - if (val < 0) - return val; + if (subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT && + subtype != PMIC_MPP_SUBTYPE_ULT_4CH_NO_SINK) { + val = pmic_mpp_read(state, pad, PMIC_MPP_REG_DIG_PULL_CTL); + if (val < 0) + return val; - pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT; - pad->pullup &= PMIC_MPP_REG_PULL_MASK; + pad->pullup = val >> PMIC_MPP_REG_PULL_SHIFT; + pad->pullup &= PMIC_MPP_REG_PULL_MASK; + pad->has_pullup = true; + } val = pmic_mpp_read(state, pad, PMIC_MPP_REG_AIN_CTL); if (val < 0) -- cgit From 6333ef46bbe514a8ece6c432aab6bcf8637b2d7c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Jan 2016 16:38:59 +0000 Subject: regulator: core: Rely on regulator_dev_release to free constraints As we now free the constraints in regulator_dev_release we will still call free on the constraints pointer even if we went down an error path in regulator_register, because it is only allocated after the device_register. As such we no longer need to free rdev->constraints on the error paths, so this patch removes said frees. Fixes: 29f5f4860a8e ("regulator: core: Move more deallocation into class unregister") Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- drivers/regulator/core.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 744c9889f88d..4405be13eb0e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1057,18 +1057,18 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = machine_constraints_voltage(rdev, rdev->constraints); if (ret != 0) - goto out; + return ret; ret = machine_constraints_current(rdev, rdev->constraints); if (ret != 0) - goto out; + return ret; if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { ret = ops->set_input_current_limit(rdev, rdev->constraints->ilim_uA); if (ret < 0) { rdev_err(rdev, "failed to set input limit\n"); - goto out; + return ret; } } @@ -1077,21 +1077,20 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = suspend_prepare(rdev, rdev->constraints->initial_state); if (ret < 0) { rdev_err(rdev, "failed to set suspend state\n"); - goto out; + return ret; } } if (rdev->constraints->initial_mode) { if (!ops->set_mode) { rdev_err(rdev, "no set_mode operation\n"); - ret = -EINVAL; - goto out; + return -EINVAL; } ret = ops->set_mode(rdev, rdev->constraints->initial_mode); if (ret < 0) { rdev_err(rdev, "failed to set initial mode: %d\n", ret); - goto out; + return ret; } } @@ -1102,7 +1101,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = _regulator_do_enable(rdev); if (ret < 0 && ret != -EINVAL) { rdev_err(rdev, "failed to enable\n"); - goto out; + return ret; } } @@ -1111,7 +1110,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); if (ret < 0) { rdev_err(rdev, "failed to set ramp_delay\n"); - goto out; + return ret; } } @@ -1119,7 +1118,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_pull_down(rdev); if (ret < 0) { rdev_err(rdev, "failed to set pull down\n"); - goto out; + return ret; } } @@ -1127,7 +1126,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_soft_start(rdev); if (ret < 0) { rdev_err(rdev, "failed to set soft start\n"); - goto out; + return ret; } } @@ -1136,16 +1135,12 @@ static int set_machine_constraints(struct regulator_dev *rdev, ret = ops->set_over_current_protection(rdev); if (ret < 0) { rdev_err(rdev, "failed to set over current protection\n"); - goto out; + return ret; } } print_constraints(rdev); return 0; -out: - kfree(rdev->constraints); - rdev->constraints = NULL; - return ret; } /** @@ -3979,7 +3974,7 @@ unset_supplies: scrub: regulator_ena_gpio_free(rdev); - kfree(rdev->constraints); + wash: device_unregister(&rdev->dev); /* device core frees rdev */ -- cgit From cf9162c290447cdf6fca7b64dd6e2200dc52f03b Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Wed, 27 Jan 2016 11:22:22 +0000 Subject: tools build: Check basic headers for test-compile feature checker An i386 binary can be linked correctly even without correct headers. Which causes problem. For exmaple: $ mv /tmp/oxygen_root/usr/include/gnu/stubs-32.h{,.bak} $ make tools/perf Auto-detecting system features: ... dwarf: [ on ] [SNIP] GEN common-cmds.h CC perf-read-vdso32 In file included from /tmp/oxygen_root/usr/include/features.h:388:0, from /tmp/oxygen_root/usr/include/stdio.h:27, from perf-read-vdso.c:1: /tmp/oxygen_root/usr/include/gnu/stubs.h:7:27: fatal error: gnu/stubs-32.h: No such file or directory # include ^ compilation terminated. ... In this patch we checks not only compiler and linker, but also basic headers in test-compile test case, make it fail on a platform lacking correct headers. Signed-off-by: Wang Nan Acked-by: Jiri Olsa Cc: Li Zefan Link: http://lkml.kernel.org/r/1453893742-20603-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/feature/test-compile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/build/feature/test-compile.c b/tools/build/feature/test-compile.c index 31dbf45bf99c..c54e6551ae4c 100644 --- a/tools/build/feature/test-compile.c +++ b/tools/build/feature/test-compile.c @@ -1,4 +1,6 @@ +#include int main(void) { + printf("Hello World!\n"); return 0; } -- cgit From ba4bc32eaa39ba7687f0958ae90eec94da613b46 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 18:07:33 +0100 Subject: ASoC: s3c24xx: use const snd_soc_component_driver pointer An older patch to convert the API in the s3c i2s driver ended up passing a const pointer into a function that takes a non-const pointer, so we now get a warning: sound/soc/samsung/s3c2412-i2s.c: In function 's3c2412_iis_dev_probe': sound/soc/samsung/s3c2412-i2s.c:172:9: error: passing argument 3 of 's3c_i2sv2_register_component' discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers] However, the s3c_i2sv2_register_component() function again passes the pointer into another function taking a const, so we just need to change its prototype. Fixes: eca3b01d0885 ("ASoC: switch over to use snd_soc_register_component() on s3c i2s") Signed-off-by: Arnd Bergmann Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mark Brown --- sound/soc/samsung/s3c-i2s-v2.c | 2 +- sound/soc/samsung/s3c-i2s-v2.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index df65c5b494b1..b6ab3fc5789e 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c @@ -709,7 +709,7 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai) #endif int s3c_i2sv2_register_component(struct device *dev, int id, - struct snd_soc_component_driver *cmp_drv, + const struct snd_soc_component_driver *cmp_drv, struct snd_soc_dai_driver *dai_drv) { struct snd_soc_dai_ops *ops = (struct snd_soc_dai_ops *)dai_drv->ops; diff --git a/sound/soc/samsung/s3c-i2s-v2.h b/sound/soc/samsung/s3c-i2s-v2.h index 90abab364b49..d0684145ed1f 100644 --- a/sound/soc/samsung/s3c-i2s-v2.h +++ b/sound/soc/samsung/s3c-i2s-v2.h @@ -101,7 +101,7 @@ extern int s3c_i2sv2_probe(struct snd_soc_dai *dai, * soc core. */ extern int s3c_i2sv2_register_component(struct device *dev, int id, - struct snd_soc_component_driver *cmp_drv, + const struct snd_soc_component_driver *cmp_drv, struct snd_soc_dai_driver *dai_drv); #endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ -- cgit From 288a89bf436fa3682742d41b2bc1b243ff2ded85 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 25 Jan 2016 11:37:15 -0300 Subject: regulator: mt6397: Add platform device ID table The platform bus_type .match callback attempts to match the platform device name with an entry on the .id_table if provided and fallbacks to match with the driver's name if a table is not provided. Using a platform device ID to match is more explicit, allows the driver to support more than one device and also the MODULE_DEVICE_TABLE macro can be used to export the module aliases information instead of the MODULE_ALIAS. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/mt6397-regulator.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c index a5b2f4762677..585f0399a36b 100644 --- a/drivers/regulator/mt6397-regulator.c +++ b/drivers/regulator/mt6397-regulator.c @@ -317,11 +317,18 @@ static int mt6397_regulator_probe(struct platform_device *pdev) return 0; } +static const struct platform_device_id mt6397_platform_ids[] = { + {"mt6397-regulator", 0}, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(platform, mt6397_platform_ids); + static struct platform_driver mt6397_regulator_driver = { .driver = { .name = "mt6397-regulator", }, .probe = mt6397_regulator_probe, + .id_table = mt6397_platform_ids, }; module_platform_driver(mt6397_regulator_driver); @@ -329,4 +336,3 @@ module_platform_driver(mt6397_regulator_driver); MODULE_AUTHOR("Flora Fu "); MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:mt6397-regulator"); -- cgit From abbf043b6508f6c90477a183b6975c269e913c7b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 25 Jan 2016 11:37:16 -0300 Subject: regulator: mt6397: Add OF match table The Documentation/devicetree/bindings/regulator/mt6397-regulator.txt doc mentions that a compatible "mediatek,mt6397-regulator" is required for the MT6397 device node but the driver doesn't provide a OF match table so the platform bus .match fallbacks to match using the driver name instead. This also means that module auto-loading is broken for this driver since the MFD driver that register the device, has a .of_compatible set so the platform .uevent callback reports a OF modalias that's not in the module. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- drivers/regulator/mt6397-regulator.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/regulator/mt6397-regulator.c b/drivers/regulator/mt6397-regulator.c index 585f0399a36b..17a5b6c2d6a9 100644 --- a/drivers/regulator/mt6397-regulator.c +++ b/drivers/regulator/mt6397-regulator.c @@ -323,9 +323,16 @@ static const struct platform_device_id mt6397_platform_ids[] = { }; MODULE_DEVICE_TABLE(platform, mt6397_platform_ids); +static const struct of_device_id mt6397_of_match[] = { + { .compatible = "mediatek,mt6397-regulator", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, mt6397_of_match); + static struct platform_driver mt6397_regulator_driver = { .driver = { .name = "mt6397-regulator", + .of_match_table = of_match_ptr(mt6397_of_match), }, .probe = mt6397_regulator_probe, .id_table = mt6397_platform_ids, -- cgit From a06c488da0b0c1eebf710017675f00b9d5f9cf42 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 26 Jan 2016 17:59:30 +0000 Subject: regmap: Add explict native endian flag to DT bindings Currently the binding document says that if no endianness is configured we use native endian but this is not in fact true for all binding types and we do have some devices that really want native endianness such as Broadcom MIPS SoCs where switching the endianness of the CPU also switches the endianness of external IPs. Provide an explicit option for this. Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regmap/regmap.txt | 11 +++++++---- drivers/base/regmap/regmap.c | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/regmap/regmap.txt b/Documentation/devicetree/bindings/regmap/regmap.txt index b494f8b8ef72..e98a9652ccc8 100644 --- a/Documentation/devicetree/bindings/regmap/regmap.txt +++ b/Documentation/devicetree/bindings/regmap/regmap.txt @@ -5,15 +5,18 @@ 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. -Required properties: -- {big,little}-endian: these are boolean properties, if absent - meaning that the CPU and the Device are in the same endianness mode, - these properties are for register values and all the buffers only. +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. diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index ee54e841de4a..343263449aff 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -557,6 +557,8 @@ enum regmap_endian regmap_get_val_endian(struct device *dev, endian = REGMAP_ENDIAN_BIG; else if (of_property_read_bool(np, "little-endian")) endian = REGMAP_ENDIAN_LITTLE; + else if (of_property_read_bool(np, "native-endian")) + endian = REGMAP_ENDIAN_NATIVE; /* If the endianness was specified in DT, use that */ if (endian != REGMAP_ENDIAN_DEFAULT) -- cgit From 25d6463e48ea41149c88dc40648a888699e77158 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 26 Jan 2016 18:08:06 +0000 Subject: MIPS: dt: Explicitly specify native endian behaviour for syscon On many MIPS systems the endianness of IP blocks is kept the same as that of the CPU by the hardware. This includes the system controllers on these systems which are controlled via syscon which uses the regmap API which used readl() and writel() to interact with the hardware, meaning that all writes are converted to little endian when writing to the hardware. This caused a bad interaction with the regmap core in big endian mode since it was not aware of the byte swapping and so ended up performing little endian writes. Unfortunately when this issue was noticed it was addressed by updating the DT for the affected devices to specify them as little endian. This happened to work since it resulted in two endianness swaps which cancelled each other out and gave little endian behaviour but meant that the DT was clearly not accurately describing the hardware. The intention of commit 29bb45f25ff305 (regmap-mmio: Use native endianness for read/write) was to fix this by making regmap default to native endianness but this breaks most other MMIO users where the hardware has a fixed endianness and the implementation uses the __raw accessors which are not intended to be used outside of architecture code. Instead use the newly added native-endian DT property to say exactly what we want for these systems. Fixes: 29bb45f25ff305 (regmap-mmio: Use native endianness for read/write) Reported-by: Johannes Berg Signed-off-by: Mark Brown Acked-by: Ralf Baechle --- arch/mips/boot/dts/brcm/bcm6328.dtsi | 1 + arch/mips/boot/dts/brcm/bcm6368.dtsi | 2 +- arch/mips/boot/dts/brcm/bcm7125.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7346.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7358.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7360.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7362.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7420.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7425.dtsi | 1 + arch/mips/boot/dts/brcm/bcm7435.dtsi | 1 + 10 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/mips/boot/dts/brcm/bcm6328.dtsi b/arch/mips/boot/dts/brcm/bcm6328.dtsi index 459b9b252c3b..9d19236f53e7 100644 --- a/arch/mips/boot/dts/brcm/bcm6328.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6328.dtsi @@ -74,6 +74,7 @@ timer: timer@10000040 { compatible = "syscon"; reg = <0x10000040 0x2c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm6368.dtsi b/arch/mips/boot/dts/brcm/bcm6368.dtsi index 9c8d3fe28b31..1f6b9b5cddb4 100644 --- a/arch/mips/boot/dts/brcm/bcm6368.dtsi +++ b/arch/mips/boot/dts/brcm/bcm6368.dtsi @@ -54,7 +54,7 @@ periph_cntl: syscon@10000000 { compatible = "syscon"; reg = <0x10000000 0x14>; - little-endian; + native-endian; }; reboot: syscon-reboot@10000008 { diff --git a/arch/mips/boot/dts/brcm/bcm7125.dtsi b/arch/mips/boot/dts/brcm/bcm7125.dtsi index 4fc7ecee273c..3ae16053a0c9 100644 --- a/arch/mips/boot/dts/brcm/bcm7125.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7125.dtsi @@ -98,6 +98,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7125-sun-top-ctrl", "syscon"; reg = <0x404000 0x60c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7346.dtsi b/arch/mips/boot/dts/brcm/bcm7346.dtsi index a3039bb53477..be7991917d29 100644 --- a/arch/mips/boot/dts/brcm/bcm7346.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7346.dtsi @@ -118,6 +118,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7346-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7358.dtsi b/arch/mips/boot/dts/brcm/bcm7358.dtsi index 4274ff41ec21..060805be619a 100644 --- a/arch/mips/boot/dts/brcm/bcm7358.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7358.dtsi @@ -112,6 +112,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7358-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7360.dtsi b/arch/mips/boot/dts/brcm/bcm7360.dtsi index 0dcc9163c27b..bcdb09bfe07b 100644 --- a/arch/mips/boot/dts/brcm/bcm7360.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7360.dtsi @@ -112,6 +112,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7360-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7362.dtsi b/arch/mips/boot/dts/brcm/bcm7362.dtsi index 2f3f9fc2c478..d3b1b762e6c3 100644 --- a/arch/mips/boot/dts/brcm/bcm7362.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7362.dtsi @@ -118,6 +118,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7362-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7420.dtsi b/arch/mips/boot/dts/brcm/bcm7420.dtsi index bee221b3b568..3302a1b8a5c9 100644 --- a/arch/mips/boot/dts/brcm/bcm7420.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7420.dtsi @@ -99,6 +99,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7420-sun-top-ctrl", "syscon"; reg = <0x404000 0x60c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7425.dtsi b/arch/mips/boot/dts/brcm/bcm7425.dtsi index 571f30f52e3f..15b27aae15a9 100644 --- a/arch/mips/boot/dts/brcm/bcm7425.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7425.dtsi @@ -100,6 +100,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + native-endian; }; reboot { diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi index 614ee211f71a..adb33e355043 100644 --- a/arch/mips/boot/dts/brcm/bcm7435.dtsi +++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi @@ -114,6 +114,7 @@ sun_top_ctrl: syscon@404000 { compatible = "brcm,bcm7425-sun-top-ctrl", "syscon"; reg = <0x404000 0x51c>; + native-endian; }; reboot { -- cgit From 922a9f936e40001f9b921379aab90047d5990923 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 27 Jan 2016 04:50:07 +0000 Subject: regmap: mmio: Convert to regmap_bus and fix accessor usage Currently regmap-mmio uses the __raw accessors to read and write from memory. This is not safe as these interact poorly with spinlocks and are not guaranteed to generate emulated instructions on at least ARM where regmap is commonly used. The APIs that are provided all provide some byte swapping so this is difficult to do with the current regmap-mmio implementation which attempts to use the regmap core byte swapping. We can fix this by modernising the MMIO implementation to use reg_read() and reg_write() operations which were added after the API was implemented and pass simple unsigned integers through to the bus, making use of the formatting provided by the I/O accessors using a similar pattern to that used by the core. This will be less efficient for block I/O operations since we now enable and disable any required clocks per register but it is not clear that any users of regmap-mmio actually use block I/O and there is room to optimise later. This removes support for big endian I/O on 64 bit registers since no I/O accessors are provided, no current users were found and support can be added easily once they are available. In addition make the default endianness little endian. This was the behaviour prior to 29bb45f25ff305 (regmap-mmio: Use native endianness for read/write) and is the behaviour desired by most existing users, the users have been audited and those that need native endianness converted to request it explicitly. Previously native was documented as the default but due to the byte swapping in the accessors this was not correctly implemented. Fixes: 29bb45f25ff305 (regmap-mmio: Use native endianness for read/write) Reported-by: Johannes Berg Tested-by: Johannes Berg Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-mmio.c | 259 ++++++++++++++++++++------------------ 1 file changed, 139 insertions(+), 120 deletions(-) diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 8812bfb9e3b8..7526906ca080 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -25,26 +25,14 @@ struct regmap_mmio_context { void __iomem *regs; - unsigned reg_bytes; unsigned val_bytes; - unsigned pad_bytes; struct clk *clk; -}; -static inline void regmap_mmio_regsize_check(size_t reg_size) -{ - switch (reg_size) { - case 1: - case 2: - case 4: -#ifdef CONFIG_64BIT - case 8: -#endif - break; - default: - BUG(); - } -} + void (*reg_write)(struct regmap_mmio_context *ctx, + unsigned int reg, unsigned int val); + unsigned int (*reg_read)(struct regmap_mmio_context *ctx, + unsigned int reg); +}; static int regmap_mmio_regbits_check(size_t reg_bits) { @@ -88,72 +76,62 @@ static int regmap_mmio_get_min_stride(size_t val_bits) return min_stride; } -static inline void regmap_mmio_count_check(size_t count, u32 offset) +static void regmap_mmio_write8(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeb(val, ctx->regs + reg); +} + +static void regmap_mmio_write16le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) { - BUG_ON(count <= offset); + writew(val, ctx->regs + reg); } -static inline unsigned int -regmap_mmio_get_offset(const void *reg, size_t reg_size) +static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) { - switch (reg_size) { - case 1: - return *(u8 *)reg; - case 2: - return *(u16 *)reg; - case 4: - return *(u32 *)reg; + iowrite16be(val, ctx->regs + reg); +} + +static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writel(val, ctx->regs + reg); +} + +static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite32be(val, ctx->regs + reg); +} + #ifdef CONFIG_64BIT - case 8: - return *(u64 *)reg; -#endif - default: - BUG(); - } +static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + writeq(val, ctx->regs + reg); } +#endif -static int regmap_mmio_gather_write(void *context, - const void *reg, size_t reg_size, - const void *val, size_t val_size) +static int regmap_mmio_write(void *context, unsigned int reg, unsigned int val) { struct regmap_mmio_context *ctx = context; - unsigned int offset; int ret; - regmap_mmio_regsize_check(reg_size); - if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; } - offset = regmap_mmio_get_offset(reg, reg_size); - - while (val_size) { - switch (ctx->val_bytes) { - case 1: - __raw_writeb(*(u8 *)val, ctx->regs + offset); - break; - case 2: - __raw_writew(*(u16 *)val, ctx->regs + offset); - break; - case 4: - __raw_writel(*(u32 *)val, ctx->regs + offset); - break; -#ifdef CONFIG_64BIT - case 8: - __raw_writeq(*(u64 *)val, ctx->regs + offset); - break; -#endif - default: - /* Should be caught by regmap_mmio_check_config */ - BUG(); - } - val_size -= ctx->val_bytes; - val += ctx->val_bytes; - offset += ctx->val_bytes; - } + ctx->reg_write(ctx, reg, val); if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); @@ -161,59 +139,56 @@ static int regmap_mmio_gather_write(void *context, return 0; } -static int regmap_mmio_write(void *context, const void *data, size_t count) +static unsigned int regmap_mmio_read8(struct regmap_mmio_context *ctx, + unsigned int reg) { - struct regmap_mmio_context *ctx = context; - unsigned int offset = ctx->reg_bytes + ctx->pad_bytes; + return readb(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readw(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16be(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readl(ctx->regs + reg); +} - regmap_mmio_count_check(count, offset); +static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32be(ctx->regs + reg); +} - return regmap_mmio_gather_write(context, data, ctx->reg_bytes, - data + offset, count - offset); +#ifdef CONFIG_64BIT +static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return readq(ctx->regs + reg); } +#endif -static int regmap_mmio_read(void *context, - const void *reg, size_t reg_size, - void *val, size_t val_size) +static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) { struct regmap_mmio_context *ctx = context; - unsigned int offset; int ret; - regmap_mmio_regsize_check(reg_size); - if (!IS_ERR(ctx->clk)) { ret = clk_enable(ctx->clk); if (ret < 0) return ret; } - offset = regmap_mmio_get_offset(reg, reg_size); - - while (val_size) { - switch (ctx->val_bytes) { - case 1: - *(u8 *)val = __raw_readb(ctx->regs + offset); - break; - case 2: - *(u16 *)val = __raw_readw(ctx->regs + offset); - break; - case 4: - *(u32 *)val = __raw_readl(ctx->regs + offset); - break; -#ifdef CONFIG_64BIT - case 8: - *(u64 *)val = __raw_readq(ctx->regs + offset); - break; -#endif - default: - /* Should be caught by regmap_mmio_check_config */ - BUG(); - } - val_size -= ctx->val_bytes; - val += ctx->val_bytes; - offset += ctx->val_bytes; - } + *val = ctx->reg_read(ctx, reg); if (!IS_ERR(ctx->clk)) clk_disable(ctx->clk); @@ -232,14 +207,11 @@ static void regmap_mmio_free_context(void *context) kfree(context); } -static struct regmap_bus regmap_mmio = { +static const struct regmap_bus regmap_mmio = { .fast_io = true, - .write = regmap_mmio_write, - .gather_write = regmap_mmio_gather_write, - .read = regmap_mmio_read, + .reg_write = regmap_mmio_write, + .reg_read = regmap_mmio_read, .free_context = regmap_mmio_free_context, - .reg_format_endian_default = REGMAP_ENDIAN_NATIVE, - .val_format_endian_default = REGMAP_ENDIAN_NATIVE, }; static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, @@ -265,24 +237,71 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, if (config->reg_stride < min_stride) return ERR_PTR(-EINVAL); - switch (config->reg_format_endian) { - case REGMAP_ENDIAN_DEFAULT: - case REGMAP_ENDIAN_NATIVE: - break; - default: - return ERR_PTR(-EINVAL); - } - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return ERR_PTR(-ENOMEM); ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; - ctx->reg_bytes = config->reg_bits / 8; - ctx->pad_bytes = config->pad_bits / 8; ctx->clk = ERR_PTR(-ENODEV); + switch (config->reg_format_endian) { + case REGMAP_ENDIAN_DEFAULT: + case REGMAP_ENDIAN_LITTLE: +#ifdef __LITTLE_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16le; + ctx->reg_write = regmap_mmio_write16le; + break; + case 32: + ctx->reg_read = regmap_mmio_read32le; + ctx->reg_write = regmap_mmio_write32le; + break; +#ifdef CONFIG_64BIT + case 64: + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + break; +#endif + default: + ret = -EINVAL; + goto err_free; + } + break; + case REGMAP_ENDIAN_BIG: +#ifdef __BIG_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16be; + ctx->reg_write = regmap_mmio_write16be; + break; + case 32: + ctx->reg_read = regmap_mmio_read32be; + ctx->reg_write = regmap_mmio_write32be; + break; + default: + ret = -EINVAL; + goto err_free; + } + break; + default: + ret = -EINVAL; + goto err_free; + } + if (clk_id == NULL) return ctx; -- cgit From a2e2876aa0bab5939daf1cb20ef07ebf38744c1f Mon Sep 17 00:00:00 2001 From: anish kumar Date: Thu, 14 Jan 2016 14:03:33 -0800 Subject: ASoC: Add max98926 codec driver Signed-off-by: anish kumar Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/max98926.txt | 32 + sound/soc/codecs/Kconfig | 4 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/max98926.c | 604 +++++++++++++++ sound/soc/codecs/max98926.h | 848 +++++++++++++++++++++ 5 files changed, 1490 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/max98926.txt create mode 100644 sound/soc/codecs/max98926.c create mode 100644 sound/soc/codecs/max98926.h diff --git a/Documentation/devicetree/bindings/sound/max98926.txt b/Documentation/devicetree/bindings/sound/max98926.txt new file mode 100644 index 000000000000..0b7f4e4d5f9a --- /dev/null +++ b/Documentation/devicetree/bindings/sound/max98926.txt @@ -0,0 +1,32 @@ +max98926 audio CODEC + +This device supports I2C. + +Required properties: + + - compatible : "maxim,max98926" + + - vmon-slot-no : slot number used to send voltage information + or in inteleave mode this will be used as + interleave slot. + + - imon-slot-no : slot number used to send current information + + - interleave-mode : When using two MAX98926 in a system it is + possible to create ADC data that that will + overflow the frame size. Digital Audio Interleave + mode provides a means to output VMON and IMON data + from two devices on a single DOUT line when running + smaller frames sizes such as 32 BCLKS per LRCLK or + 48 BCLKS per LRCLK. + + - reg : the I2C address of the device for I2C + +Example: + +codec: max98926@1a { + compatible = "maxim,max98926"; + vmon-slot-no = <0>; + imon-slot-no = <2>; + reg = <0x1a>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 50693c867e71..ebaaa51823ef 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -80,6 +80,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX98095 if I2C select SND_SOC_MAX98357A if GPIOLIB select SND_SOC_MAX98925 if I2C + select SND_SOC_MAX98926 if I2C select SND_SOC_MAX9850 if I2C select SND_SOC_MAX9768 if I2C select SND_SOC_MAX9877 if I2C @@ -519,6 +520,9 @@ config SND_SOC_MAX98357A config SND_SOC_MAX98925 tristate +config SND_SOC_MAX98926 + tristate + config SND_SOC_MAX9850 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d44f7d347183..16c014a46ae8 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -75,6 +75,7 @@ snd-soc-max98090-objs := max98090.o snd-soc-max98095-objs := max98095.o snd-soc-max98357a-objs := max98357a.o snd-soc-max98925-objs := max98925.o +snd-soc-max98926-objs := max98926.o snd-soc-max9850-objs := max9850.o snd-soc-mc13783-objs := mc13783.o snd-soc-ml26124-objs := ml26124.o @@ -279,6 +280,7 @@ obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o obj-$(CONFIG_SND_SOC_MAX98357A) += snd-soc-max98357a.o obj-$(CONFIG_SND_SOC_MAX98925) += snd-soc-max98925.o +obj-$(CONFIG_SND_SOC_MAX98926) += snd-soc-max98926.o 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 diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c new file mode 100644 index 000000000000..66884ebdf2bb --- /dev/null +++ b/sound/soc/codecs/max98926.c @@ -0,0 +1,604 @@ +/* + * max98926.c -- ALSA SoC MAX98926 driver + * Copyright 2013-15 Maxim Integrated Products + * 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 +#include +#include +#include "max98926.h" + +static const char * const max98926_boost_voltage_txt[] = { + "8.5V", "8.25V", "8.0V", "7.75V", "7.5V", "7.25V", "7.0V", "6.75V", + "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V", "6.5V" +}; + +static const char * const max98926_boost_current_txt[] = { + "0.6", "0.8", "1.0", "1.2", "1.4", "1.6", "1.8", "2.0", + "2.2", "2.4", "2.6", "2.8", "3.2", "3.6", "4.0", "4.4" +}; + +static const char *const max98926_dai_txt[] = { + "Left", "Right", "LeftRight", "LeftRightDiv2", +}; + +static const char *const max98926_pdm_ch_text[] = { + "Current", "Voltage", +}; + +static const char *const max98926_hpf_cutoff_txt[] = { + "Disable", "DC Block", "100Hz", + "200Hz", "400Hz", "800Hz", +}; + +static struct reg_default max98926_reg[] = { + { 0x0B, 0x00 }, /* IRQ Enable0 */ + { 0x0C, 0x00 }, /* IRQ Enable1 */ + { 0x0D, 0x00 }, /* IRQ Enable2 */ + { 0x0E, 0x00 }, /* IRQ Clear0 */ + { 0x0F, 0x00 }, /* IRQ Clear1 */ + { 0x10, 0x00 }, /* IRQ Clear2 */ + { 0x11, 0xC0 }, /* Map0 */ + { 0x12, 0x00 }, /* Map1 */ + { 0x13, 0x00 }, /* Map2 */ + { 0x14, 0xF0 }, /* Map3 */ + { 0x15, 0x00 }, /* Map4 */ + { 0x16, 0xAB }, /* Map5 */ + { 0x17, 0x89 }, /* Map6 */ + { 0x18, 0x00 }, /* Map7 */ + { 0x19, 0x00 }, /* Map8 */ + { 0x1A, 0x04 }, /* DAI Clock Mode 1 */ + { 0x1B, 0x00 }, /* DAI Clock Mode 2 */ + { 0x1C, 0x00 }, /* DAI Clock Divider Denominator MSBs */ + { 0x1D, 0x00 }, /* DAI Clock Divider Denominator LSBs */ + { 0x1E, 0xF0 }, /* DAI Clock Divider Numerator MSBs */ + { 0x1F, 0x00 }, /* DAI Clock Divider Numerator LSBs */ + { 0x20, 0x50 }, /* Format */ + { 0x21, 0x00 }, /* TDM Slot Select */ + { 0x22, 0x00 }, /* DOUT Configuration VMON */ + { 0x23, 0x00 }, /* DOUT Configuration IMON */ + { 0x24, 0x00 }, /* DOUT Configuration VBAT */ + { 0x25, 0x00 }, /* DOUT Configuration VBST */ + { 0x26, 0x00 }, /* DOUT Configuration FLAG */ + { 0x27, 0xFF }, /* DOUT HiZ Configuration 1 */ + { 0x28, 0xFF }, /* DOUT HiZ Configuration 2 */ + { 0x29, 0xFF }, /* DOUT HiZ Configuration 3 */ + { 0x2A, 0xFF }, /* DOUT HiZ Configuration 4 */ + { 0x2B, 0x02 }, /* DOUT Drive Strength */ + { 0x2C, 0x90 }, /* Filters */ + { 0x2D, 0x00 }, /* Gain */ + { 0x2E, 0x02 }, /* Gain Ramping */ + { 0x2F, 0x00 }, /* Speaker Amplifier */ + { 0x30, 0x0A }, /* Threshold */ + { 0x31, 0x00 }, /* ALC Attack */ + { 0x32, 0x80 }, /* ALC Atten and Release */ + { 0x33, 0x00 }, /* ALC Infinite Hold Release */ + { 0x34, 0x92 }, /* ALC Configuration */ + { 0x35, 0x01 }, /* Boost Converter */ + { 0x36, 0x00 }, /* Block Enable */ + { 0x37, 0x00 }, /* Configuration */ + { 0x38, 0x00 }, /* Global Enable */ + { 0x3A, 0x00 }, /* Boost Limiter */ +}; + +static const struct soc_enum max98926_voltage_enum[] = { + SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, 0, + ARRAY_SIZE(max98926_pdm_ch_text), + max98926_pdm_ch_text), +}; + +static const struct snd_kcontrol_new max98926_voltage_control = + SOC_DAPM_ENUM("Route", max98926_voltage_enum); + +static const struct soc_enum max98926_current_enum[] = { + SOC_ENUM_SINGLE(MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_SOURCE_1_SHIFT, + ARRAY_SIZE(max98926_pdm_ch_text), + max98926_pdm_ch_text), +}; + +static const struct snd_kcontrol_new max98926_current_control = + SOC_DAPM_ENUM("Route", max98926_current_enum); + +static const struct snd_kcontrol_new max98926_mixer_controls[] = { + SOC_DAPM_SINGLE("PCM Single Switch", MAX98926_SPK_AMP, + MAX98926_INSELECT_MODE_SHIFT, 0, 0), + SOC_DAPM_SINGLE("PDM Single Switch", MAX98926_SPK_AMP, + MAX98926_INSELECT_MODE_SHIFT, 1, 0), +}; + +static const struct snd_kcontrol_new max98926_dai_controls[] = { + SOC_DAPM_SINGLE("Left", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 0, 0), + SOC_DAPM_SINGLE("Right", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 1, 0), + SOC_DAPM_SINGLE("LeftRight", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 2, 0), + SOC_DAPM_SINGLE("(Left+Right)/2 Switch", MAX98926_GAIN, + MAX98926_DAC_IN_SEL_SHIFT, 3, 0), +}; + +static const struct snd_soc_dapm_widget max98926_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC("Amp Enable", NULL, MAX98926_BLOCK_ENABLE, + MAX98926_SPK_EN_SHIFT, 0), + SND_SOC_DAPM_SUPPLY("Global Enable", MAX98926_GLOBAL_ENABLE, + MAX98926_EN_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("VI Enable", MAX98926_BLOCK_ENABLE, + MAX98926_ADC_IMON_EN_WIDTH | + MAX98926_ADC_VMON_EN_SHIFT, + 0, NULL, 0), + SND_SOC_DAPM_PGA("BST Enable", MAX98926_BLOCK_ENABLE, + MAX98926_BST_EN_SHIFT, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("BE_OUT"), + SND_SOC_DAPM_MIXER("PCM Sel", MAX98926_SPK_AMP, + MAX98926_INSELECT_MODE_SHIFT, 0, + &max98926_mixer_controls[0], + ARRAY_SIZE(max98926_mixer_controls)), + SND_SOC_DAPM_MIXER("DAI Sel", + MAX98926_GAIN, MAX98926_DAC_IN_SEL_SHIFT, 0, + &max98926_dai_controls[0], + ARRAY_SIZE(max98926_dai_controls)), + SND_SOC_DAPM_MUX("PDM CH1 Source", + MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_CURRENT_SHIFT, + 0, &max98926_current_control), + SND_SOC_DAPM_MUX("PDM CH0 Source", + MAX98926_DAI_CLK_DIV_N_LSBS, + MAX98926_PDM_VOLTAGE_SHIFT, + 0, &max98926_voltage_control), +}; + +static const struct snd_soc_dapm_route max98926_audio_map[] = { + {"VI Enable", NULL, "DAI_OUT"}, + {"DAI Sel", "Left", "VI Enable"}, + {"DAI Sel", "Right", "VI Enable"}, + {"DAI Sel", "LeftRight", "VI Enable"}, + {"DAI Sel", "LeftRightDiv2", "VI Enable"}, + {"PCM Sel", "PCM", "DAI Sel"}, + + {"PDM CH1 Source", "Current", "DAI_OUT"}, + {"PDM CH1 Source", "Voltage", "DAI_OUT"}, + {"PDM CH0 Source", "Current", "DAI_OUT"}, + {"PDM CH0 Source", "Voltage", "DAI_OUT"}, + {"PCM Sel", "Analog", "PDM CH1 Source"}, + {"PCM Sel", "Analog", "PDM CH0 Source"}, + {"Amp Enable", NULL, "PCM Sel"}, + + {"BST Enable", NULL, "Amp Enable"}, + {"BE_OUT", NULL, "BST Enable"}, +}; + +static bool max98926_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98926_VBAT_DATA: + case MAX98926_VBST_DATA: + case MAX98926_LIVE_STATUS0: + case MAX98926_LIVE_STATUS1: + case MAX98926_LIVE_STATUS2: + case MAX98926_STATE0: + case MAX98926_STATE1: + case MAX98926_STATE2: + case MAX98926_FLAG0: + case MAX98926_FLAG1: + case MAX98926_FLAG2: + case MAX98926_VERSION: + return true; + default: + return false; + } +} + +static bool max98926_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98926_IRQ_CLEAR0: + case MAX98926_IRQ_CLEAR1: + case MAX98926_IRQ_CLEAR2: + case MAX98926_ALC_HOLD_RLS: + return false; + default: + return true; + } +}; + +DECLARE_TLV_DB_SCALE(max98926_spk_tlv, -600, 100, 0); +DECLARE_TLV_DB_RANGE(max98926_current_tlv, + 0, 11, TLV_DB_SCALE_ITEM(20, 20, 0), + 12, 15, TLV_DB_SCALE_ITEM(320, 40, 0), +); + +static SOC_ENUM_SINGLE_DECL(max98926_dac_hpf_cutoff, + MAX98926_FILTERS, MAX98926_DAC_HPF_SHIFT, + max98926_hpf_cutoff_txt); + +static SOC_ENUM_SINGLE_DECL(max98926_boost_voltage, + MAX98926_CONFIGURATION, MAX98926_BST_VOUT_SHIFT, + max98926_boost_voltage_txt); + +static const struct snd_kcontrol_new max98926_snd_controls[] = { + SOC_SINGLE_TLV("Speaker Volume", MAX98926_GAIN, + MAX98926_SPK_GAIN_SHIFT, + (1<regmap, + MAX98926_DOUT_CFG_VMON, + MAX98926_DAI_VMON_EN_MASK, + MAX98926_DAI_VMON_EN_MASK); + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_IMON, + MAX98926_DAI_IMON_EN_MASK, + MAX98926_DAI_IMON_EN_MASK); + + if (!max98926->interleave_mode) { + /* set VMON slots */ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_VMON, + MAX98926_DAI_VMON_SLOT_MASK, + max98926->v_slot); + /* set IMON slots */ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_IMON, + MAX98926_DAI_IMON_SLOT_MASK, + max98926->i_slot); + } else { + /* enable interleave mode */ + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_INTERLEAVE_MASK, + MAX98926_DAI_INTERLEAVE_MASK); + /* set interleave slots */ + regmap_update_bits(max98926->regmap, + MAX98926_DOUT_CFG_VBAT, + MAX98926_DAI_INTERLEAVE_SLOT_MASK, + max98926->v_slot); + } +} + +static int max98926_dai_set_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_codec *codec = codec_dai->codec; + struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); + unsigned int invert = 0; + + dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + max98926_set_sense_data(max98926); + break; + default: + dev_err(codec->dev, "DAI clock mode unsupported"); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + invert = MAX98926_DAI_WCI_MASK; + break; + case SND_SOC_DAIFMT_IB_NF: + invert = MAX98926_DAI_BCI_MASK; + break; + case SND_SOC_DAIFMT_IB_IF: + invert = MAX98926_DAI_BCI_MASK | MAX98926_DAI_WCI_MASK; + break; + default: + dev_err(codec->dev, "DAI invert mode unsupported"); + return -EINVAL; + } + + regmap_write(max98926->regmap, + MAX98926_FORMAT, MAX98926_DAI_DLY_MASK); + regmap_update_bits(max98926->regmap, MAX98926_FORMAT, + MAX98926_DAI_BCI_MASK, invert); + return 0; +} + +static int max98926_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + int dai_sr = -EINVAL; + int rate = params_rate(params), i; + struct snd_soc_codec *codec = dai->codec; + struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); + /* BCLK/LRCLK ratio calculation */ + int blr_clk_ratio = params_channels(params) * max98926->ch_size; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_CHANSZ_MASK, + MAX98926_DAI_CHANSZ_16); + max98926->ch_size = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_CHANSZ_MASK, + MAX98926_DAI_CHANSZ_24); + max98926->ch_size = 24; + break; + case SNDRV_PCM_FORMAT_S32_LE: + regmap_update_bits(max98926->regmap, + MAX98926_FORMAT, + MAX98926_DAI_CHANSZ_MASK, + MAX98926_DAI_CHANSZ_32); + max98926->ch_size = 32; + break; + default: + dev_dbg(codec->dev, "format unsupported %d", + params_format(params)); + return -EINVAL; + } + + switch (blr_clk_ratio) { + case 32: + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_BSEL_MASK, + MAX98926_DAI_BSEL_32); + break; + case 48: + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_BSEL_MASK, + MAX98926_DAI_BSEL_48); + break; + case 64: + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_BSEL_MASK, + MAX98926_DAI_BSEL_64); + break; + default: + return -EINVAL; + } + + /* find the closest rate */ + for (i = 0; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i].rate >= rate) { + dai_sr = rate_table[i].sr; + break; + } + } + if (dai_sr < 0) + return -EINVAL; + + /* set DAI_SR to correct LRCLK frequency */ + regmap_update_bits(max98926->regmap, + MAX98926_DAI_CLK_MODE2, + MAX98926_DAI_SR_MASK, dai_sr << MAX98926_DAI_SR_SHIFT); + return 0; +} + +#define MAX98926_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_ops max98926_dai_ops = { + .set_fmt = max98926_dai_set_fmt, + .hw_params = max98926_dai_hw_params, +}; + +static struct snd_soc_dai_driver max98926_dai[] = { +{ + .name = "max98926-aif1", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = MAX98926_FORMATS, + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_48000, + .formats = MAX98926_FORMATS, + }, + .ops = &max98926_dai_ops, +} +}; + +static int max98926_probe(struct snd_soc_codec *codec) +{ + struct max98926_priv *max98926 = snd_soc_codec_get_drvdata(codec); + + max98926->codec = codec; + codec->control_data = max98926->regmap; + /* Hi-Z all the slots */ + regmap_write(max98926->regmap, MAX98926_DOUT_HIZ_CFG4, 0xF0); + return 0; +} + +static struct snd_soc_codec_driver soc_codec_dev_max98926 = { + .probe = max98926_probe, + .controls = max98926_snd_controls, + .num_controls = ARRAY_SIZE(max98926_snd_controls), + .dapm_routes = max98926_audio_map, + .num_dapm_routes = ARRAY_SIZE(max98926_audio_map), + .dapm_widgets = max98926_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(max98926_dapm_widgets), +}; + +static struct regmap_config max98926_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = MAX98926_VERSION, + .reg_defaults = max98926_reg, + .num_reg_defaults = ARRAY_SIZE(max98926_reg), + .volatile_reg = max98926_volatile_register, + .readable_reg = max98926_readable_register, + .cache_type = REGCACHE_RBTREE, +}; + +static int max98926_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + int ret, reg; + u32 value; + struct max98926_priv *max98926; + + max98926 = devm_kzalloc(&i2c->dev, + sizeof(*max98926), GFP_KERNEL); + if (!max98926) + return -ENOMEM; + + i2c_set_clientdata(i2c, max98926); + max98926->regmap = devm_regmap_init_i2c(i2c, &max98926_regmap); + if (IS_ERR(max98926->regmap)) { + ret = PTR_ERR(max98926->regmap); + dev_err(&i2c->dev, + "Failed to allocate regmap: %d\n", ret); + goto err_out; + } + if (of_property_read_bool(i2c->dev.of_node, "interleave-mode")) + max98926->interleave_mode = true; + + if (!of_property_read_u32(i2c->dev.of_node, "vmon-slot-no", &value)) { + if (value > MAX98926_DAI_VMON_SLOT_1E_1F) { + dev_err(&i2c->dev, "vmon slot number is wrong:\n"); + return -EINVAL; + } + max98926->v_slot = value; + } + if (!of_property_read_u32(i2c->dev.of_node, "imon-slot-no", &value)) { + if (value > MAX98926_DAI_IMON_SLOT_1E_1F) { + dev_err(&i2c->dev, "imon slot number is wrong:\n"); + return -EINVAL; + } + max98926->i_slot = value; + } + ret = regmap_read(max98926->regmap, + MAX98926_VERSION, ®); + if (ret < 0) { + dev_err(&i2c->dev, "Failed to read: %x\n", reg); + return ret; + } + + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98926, + max98926_dai, ARRAY_SIZE(max98926_dai)); + if (ret < 0) + dev_err(&i2c->dev, + "Failed to register codec: %d\n", ret); + dev_info(&i2c->dev, "device version: %x\n", reg); +err_out: + return ret; +} + +static int max98926_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + return 0; +} + +static const struct i2c_device_id max98926_i2c_id[] = { + { "max98926", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max98926_i2c_id); + +static const struct of_device_id max98926_of_match[] = { + { .compatible = "maxim,max98926", }, + { } +}; +MODULE_DEVICE_TABLE(of, max98926_of_match); + +static struct i2c_driver max98926_i2c_driver = { + .driver = { + .name = "max98926", + .of_match_table = of_match_ptr(max98926_of_match), + .pm = NULL, + }, + .probe = max98926_i2c_probe, + .remove = max98926_i2c_remove, + .id_table = max98926_i2c_id, +}; + +module_i2c_driver(max98926_i2c_driver) +MODULE_DESCRIPTION("ALSA SoC MAX98926 driver"); +MODULE_AUTHOR("Anish kumar "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max98926.h b/sound/soc/codecs/max98926.h new file mode 100644 index 000000000000..9d7ab6df79ca --- /dev/null +++ b/sound/soc/codecs/max98926.h @@ -0,0 +1,848 @@ +/* + * max98926.h -- MAX98926 ALSA SoC Audio driver + * Copyright 2013-2015 Maxim Integrated Products + * 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 _MAX98926_H +#define _MAX98926_H + +#define MAX98926_CHIP_VERSION 0x40 +#define MAX98926_CHIP_VERSION1 0x50 + +#define MAX98926_VBAT_DATA 0x00 +#define MAX98926_VBST_DATA 0x01 +#define MAX98926_LIVE_STATUS0 0x02 +#define MAX98926_LIVE_STATUS1 0x03 +#define MAX98926_LIVE_STATUS2 0x04 +#define MAX98926_STATE0 0x05 +#define MAX98926_STATE1 0x06 +#define MAX98926_STATE2 0x07 +#define MAX98926_FLAG0 0x08 +#define MAX98926_FLAG1 0x09 +#define MAX98926_FLAG2 0x0A +#define MAX98926_IRQ_ENABLE0 0x0B +#define MAX98926_IRQ_ENABLE1 0x0C +#define MAX98926_IRQ_ENABLE2 0x0D +#define MAX98926_IRQ_CLEAR0 0x0E +#define MAX98926_IRQ_CLEAR1 0x0F +#define MAX98926_IRQ_CLEAR2 0x10 +#define MAX98926_MAP0 0x11 +#define MAX98926_MAP1 0x12 +#define MAX98926_MAP2 0x13 +#define MAX98926_MAP3 0x14 +#define MAX98926_MAP4 0x15 +#define MAX98926_MAP5 0x16 +#define MAX98926_MAP6 0x17 +#define MAX98926_MAP7 0x18 +#define MAX98926_MAP8 0x19 +#define MAX98926_DAI_CLK_MODE1 0x1A +#define MAX98926_DAI_CLK_MODE2 0x1B +#define MAX98926_DAI_CLK_DIV_M_MSBS 0x1C +#define MAX98926_DAI_CLK_DIV_M_LSBS 0x1D +#define MAX98926_DAI_CLK_DIV_N_MSBS 0x1E +#define MAX98926_DAI_CLK_DIV_N_LSBS 0x1F +#define MAX98926_FORMAT 0x20 +#define MAX98926_TDM_SLOT_SELECT 0x21 +#define MAX98926_DOUT_CFG_VMON 0x22 +#define MAX98926_DOUT_CFG_IMON 0x23 +#define MAX98926_DOUT_CFG_VBAT 0x24 +#define MAX98926_DOUT_CFG_VBST 0x25 +#define MAX98926_DOUT_CFG_FLAG 0x26 +#define MAX98926_DOUT_HIZ_CFG1 0x27 +#define MAX98926_DOUT_HIZ_CFG2 0x28 +#define MAX98926_DOUT_HIZ_CFG3 0x29 +#define MAX98926_DOUT_HIZ_CFG4 0x2A +#define MAX98926_DOUT_DRV_STRENGTH 0x2B +#define MAX98926_FILTERS 0x2C +#define MAX98926_GAIN 0x2D +#define MAX98926_GAIN_RAMPING 0x2E +#define MAX98926_SPK_AMP 0x2F +#define MAX98926_THRESHOLD 0x30 +#define MAX98926_ALC_ATTACK 0x31 +#define MAX98926_ALC_ATTEN_RLS 0x32 +#define MAX98926_ALC_HOLD_RLS 0x33 +#define MAX98926_ALC_CONFIGURATION 0x34 +#define MAX98926_BOOST_CONVERTER 0x35 +#define MAX98926_BLOCK_ENABLE 0x36 +#define MAX98926_CONFIGURATION 0x37 +#define MAX98926_GLOBAL_ENABLE 0x38 +#define MAX98926_BOOST_LIMITER 0x3A +#define MAX98926_VERSION 0xFF + +#define MAX98926_REG_CNT (MAX98926_R03A_BOOST_LIMITER+1) + +#define MAX98926_PDM_CURRENT_MASK (1<<7) +#define MAX98926_PDM_CURRENT_SHIFT 7 +#define MAX98926_PDM_VOLTAGE_MASK (1<<3) +#define MAX98926_PDM_VOLTAGE_SHIFT 3 +#define MAX98926_PDM_CHANNEL_0_MASK (1<<2) +#define MAX98926_PDM_CHANNEL_0_SHIFT 2 +#define MAX98926_PDM_CHANNEL_1_MASK (1<<6) +#define MAX98926_PDM_CHANNEL_1_SHIFT 6 +#define MAX98926_PDM_CHANNEL_1_HIZ 5 +#define MAX98926_PDM_CHANNEL_0_HIZ 1 +#define MAX98926_PDM_SOURCE_0_SHIFT 0 +#define MAX98926_PDM_SOURCE_0_MASK (1<<0) +#define MAX98926_PDM_SOURCE_1_MASK (1<<4) +#define MAX98926_PDM_SOURCE_1_SHIFT 4 + +/* MAX98926 Register Bit Fields */ + +/* MAX98926_R002_LIVE_STATUS0 */ +#define MAX98926_THERMWARN_STATUS_MASK (1<<3) +#define MAX98926_THERMWARN_STATUS_SHIFT 3 +#define MAX98926_THERMWARN_STATUS_WIDTH 1 +#define MAX98926_THERMSHDN_STATUS_MASK (1<<1) +#define MAX98926_THERMSHDN_STATUS_SHIFT 1 +#define MAX98926_THERMSHDN_STATUS_WIDTH 1 + +/* MAX98926_R003_LIVE_STATUS1 */ +#define MAX98926_SPKCURNT_STATUS_MASK (1<<5) +#define MAX98926_SPKCURNT_STATUS_SHIFT 5 +#define MAX98926_SPKCURNT_STATUS_WIDTH 1 +#define MAX98926_WATCHFAIL_STATUS_MASK (1<<4) +#define MAX98926_WATCHFAIL_STATUS_SHIFT 4 +#define MAX98926_WATCHFAIL_STATUS_WIDTH 1 +#define MAX98926_ALCINFH_STATUS_MASK (1<<3) +#define MAX98926_ALCINFH_STATUS_SHIFT 3 +#define MAX98926_ALCINFH_STATUS_WIDTH 1 +#define MAX98926_ALCACT_STATUS_MASK (1<<2) +#define MAX98926_ALCACT_STATUS_SHIFT 2 +#define MAX98926_ALCACT_STATUS_WIDTH 1 +#define MAX98926_ALCMUT_STATUS_MASK (1<<1) +#define MAX98926_ALCMUT_STATUS_SHIFT 1 +#define MAX98926_ALCMUT_STATUS_WIDTH 1 +#define MAX98926_ACLP_STATUS_MASK (1<<0) +#define MAX98926_ACLP_STATUS_SHIFT 0 +#define MAX98926_ACLP_STATUS_WIDTH 1 + +/* MAX98926_R004_LIVE_STATUS2 */ +#define MAX98926_SLOTOVRN_STATUS_MASK (1<<6) +#define MAX98926_SLOTOVRN_STATUS_SHIFT 6 +#define MAX98926_SLOTOVRN_STATUS_WIDTH 1 +#define MAX98926_INVALSLOT_STATUS_MASK (1<<5) +#define MAX98926_INVALSLOT_STATUS_SHIFT 5 +#define MAX98926_INVALSLOT_STATUS_WIDTH 1 +#define MAX98926_SLOTCNFLT_STATUS_MASK (1<<4) +#define MAX98926_SLOTCNFLT_STATUS_SHIFT 4 +#define MAX98926_SLOTCNFLT_STATUS_WIDTH 1 +#define MAX98926_VBSTOVFL_STATUS_MASK (1<<3) +#define MAX98926_VBSTOVFL_STATUS_SHIFT 3 +#define MAX98926_VBSTOVFL_STATUS_WIDTH 1 +#define MAX98926_VBATOVFL_STATUS_MASK (1<<2) +#define MAX98926_VBATOVFL_STATUS_SHIFT 2 +#define MAX98926_VBATOVFL_STATUS_WIDTH 1 +#define MAX98926_IMONOVFL_STATUS_MASK (1<<1) +#define MAX98926_IMONOVFL_STATUS_SHIFT 1 +#define MAX98926_IMONOVFL_STATUS_WIDTH 1 +#define MAX98926_VMONOVFL_STATUS_MASK (1<<0) +#define MAX98926_VMONOVFL_STATUS_SHIFT 0 +#define MAX98926_VMONOVFL_STATUS_WIDTH 1 + +/* MAX98926_R005_STATE0 */ +#define MAX98926_THERMWARN_END_STATE_MASK (1<<3) +#define MAX98926_THERMWARN_END_STATE_SHIFT 3 +#define MAX98926_THERMWARN_END_STATE_WIDTH 1 +#define MAX98926_THERMWARN_BGN_STATE_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_STATE_SHIFT 1 +#define MAX98926_THERMWARN_BGN_STATE_WIDTH 1 +#define MAX98926_THERMSHDN_END_STATE_MASK (1<<1) +#define MAX98926_THERMSHDN_END_STATE_SHIFT 1 +#define MAX98926_THERMSHDN_END_STATE_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_STATE_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_STATE_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_STATE_WIDTH 1 + +/* MAX98926_R006_STATE1 */ +#define MAX98926_SPRCURNT_STATE_MASK (1<<5) +#define MAX98926_SPRCURNT_STATE_SHIFT 5 +#define MAX98926_SPRCURNT_STATE_WIDTH 1 +#define MAX98926_WATCHFAIL_STATE_MASK (1<<4) +#define MAX98926_WATCHFAIL_STATE_SHIFT 4 +#define MAX98926_WATCHFAIL_STATE_WIDTH 1 +#define MAX98926_ALCINFH_STATE_MASK (1<<3) +#define MAX98926_ALCINFH_STATE_SHIFT 3 +#define MAX98926_ALCINFH_STATE_WIDTH 1 +#define MAX98926_ALCACT_STATE_MASK (1<<2) +#define MAX98926_ALCACT_STATE_SHIFT 2 +#define MAX98926_ALCACT_STATE_WIDTH 1 +#define MAX98926_ALCMUT_STATE_MASK (1<<1) +#define MAX98926_ALCMUT_STATE_SHIFT 1 +#define MAX98926_ALCMUT_STATE_WIDTH 1 +#define MAX98926_ALCP_STATE_MASK (1<<0) +#define MAX98926_ALCP_STATE_SHIFT 0 +#define MAX98926_ALCP_STATE_WIDTH 1 + +/* MAX98926_R007_STATE2 */ +#define MAX98926_SLOTOVRN_STATE_MASK (1<<6) +#define MAX98926_SLOTOVRN_STATE_SHIFT 6 +#define MAX98926_SLOTOVRN_STATE_WIDTH 1 +#define MAX98926_INVALSLOT_STATE_MASK (1<<5) +#define MAX98926_INVALSLOT_STATE_SHIFT 5 +#define MAX98926_INVALSLOT_STATE_WIDTH 1 +#define MAX98926_SLOTCNFLT_STATE_MASK (1<<4) +#define MAX98926_SLOTCNFLT_STATE_SHIFT 4 +#define MAX98926_SLOTCNFLT_STATE_WIDTH 1 +#define MAX98926_VBSTOVFL_STATE_MASK (1<<3) +#define MAX98926_VBSTOVFL_STATE_SHIFT 3 +#define MAX98926_VBSTOVFL_STATE_WIDTH 1 +#define MAX98926_VBATOVFL_STATE_MASK (1<<2) +#define MAX98926_VBATOVFL_STATE_SHIFT 2 +#define MAX98926_VBATOVFL_STATE_WIDTH 1 +#define MAX98926_IMONOVFL_STATE_MASK (1<<1) +#define MAX98926_IMONOVFL_STATE_SHIFT 1 +#define MAX98926_IMONOVFL_STATE_WIDTH 1 +#define MAX98926_VMONOVFL_STATE_MASK (1<<0) +#define MAX98926_VMONOVFL_STATE_SHIFT 0 +#define MAX98926_VMONOVFL_STATE_WIDTH 1 + +/* MAX98926_R008_FLAG0 */ +#define MAX98926_THERMWARN_END_FLAG_MASK (1<<3) +#define MAX98926_THERMWARN_END_FLAG_SHIFT 3 +#define MAX98926_THERMWARN_END_FLAG_WIDTH 1 +#define MAX98926_THERMWARN_BGN_FLAG_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_FLAG_SHIFT 2 +#define MAX98926_THERMWARN_BGN_FLAG_WIDTH 1 +#define MAX98926_THERMSHDN_END_FLAG_MASK (1<<1) +#define MAX98926_THERMSHDN_END_FLAG_SHIFT 1 +#define MAX98926_THERMSHDN_END_FLAG_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_FLAG_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_FLAG_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_FLAG_WIDTH 1 + +/* MAX98926_R009_FLAG1 */ +#define MAX98926_SPKCURNT_FLAG_MASK (1<<5) +#define MAX98926_SPKCURNT_FLAG_SHIFT 5 +#define MAX98926_SPKCURNT_FLAG_WIDTH 1 +#define MAX98926_WATCHFAIL_FLAG_MASK (1<<4) +#define MAX98926_WATCHFAIL_FLAG_SHIFT 4 +#define MAX98926_WATCHFAIL_FLAG_WIDTH 1 +#define MAX98926_ALCINFH_FLAG_MASK (1<<3) +#define MAX98926_ALCINFH_FLAG_SHIFT 3 +#define MAX98926_ALCINFH_FLAG_WIDTH 1 +#define MAX98926_ALCACT_FLAG_MASK (1<<2) +#define MAX98926_ALCACT_FLAG_SHIFT 2 +#define MAX98926_ALCACT_FLAG_WIDTH 1 +#define MAX98926_ALCMUT_FLAG_MASK (1<<1) +#define MAX98926_ALCMUT_FLAG_SHIFT 1 +#define MAX98926_ALCMUT_FLAG_WIDTH 1 +#define MAX98926_ALCP_FLAG_MASK (1<<0) +#define MAX98926_ALCP_FLAG_SHIFT 0 +#define MAX98926_ALCP_FLAG_WIDTH 1 + +/* MAX98926_R00A_FLAG2 */ +#define MAX98926_SLOTOVRN_FLAG_MASK (1<<6) +#define MAX98926_SLOTOVRN_FLAG_SHIFT 6 +#define MAX98926_SLOTOVRN_FLAG_WIDTH 1 +#define MAX98926_INVALSLOT_FLAG_MASK (1<<5) +#define MAX98926_INVALSLOT_FLAG_SHIFT 5 +#define MAX98926_INVALSLOT_FLAG_WIDTH 1 +#define MAX98926_SLOTCNFLT_FLAG_MASK (1<<4) +#define MAX98926_SLOTCNFLT_FLAG_SHIFT 4 +#define MAX98926_SLOTCNFLT_FLAG_WIDTH 1 +#define MAX98926_VBSTOVFL_FLAG_MASK (1<<3) +#define MAX98926_VBSTOVFL_FLAG_SHIFT 3 +#define MAX98926_VBSTOVFL_FLAG_WIDTH 1 +#define MAX98926_VBATOVFL_FLAG_MASK (1<<2) +#define MAX98926_VBATOVFL_FLAG_SHIFT 2 +#define MAX98926_VBATOVFL_FLAG_WIDTH 1 +#define MAX98926_IMONOVFL_FLAG_MASK (1<<1) +#define MAX98926_IMONOVFL_FLAG_SHIFT 1 +#define MAX98926_IMONOVFL_FLAG_WIDTH 1 +#define MAX98926_VMONOVFL_FLAG_MASK (1<<0) +#define MAX98926_VMONOVFL_FLAG_SHIFT 0 +#define MAX98926_VMONOVFL_FLAG_WIDTH 1 + +/* MAX98926_R00B_IRQ_ENABLE0 */ +#define MAX98926_THERMWARN_END_EN_MASK (1<<3) +#define MAX98926_THERMWARN_END_EN_SHIFT 3 +#define MAX98926_THERMWARN_END_EN_WIDTH 1 +#define MAX98926_THERMWARN_BGN_EN_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_EN_SHIFT 2 +#define MAX98926_THERMWARN_BGN_EN_WIDTH 1 +#define MAX98926_THERMSHDN_END_EN_MASK (1<<1) +#define MAX98926_THERMSHDN_END_EN_SHIFT 1 +#define MAX98926_THERMSHDN_END_EN_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_EN_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_EN_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_EN_WIDTH 1 + +/* MAX98926_R00C_IRQ_ENABLE1 */ +#define MAX98926_SPKCURNT_EN_MASK (1<<5) +#define MAX98926_SPKCURNT_EN_SHIFT 5 +#define MAX98926_SPKCURNT_EN_WIDTH 1 +#define MAX98926_WATCHFAIL_EN_MASK (1<<4) +#define MAX98926_WATCHFAIL_EN_SHIFT 4 +#define MAX98926_WATCHFAIL_EN_WIDTH 1 +#define MAX98926_ALCINFH_EN_MASK (1<<3) +#define MAX98926_ALCINFH_EN_SHIFT 3 +#define MAX98926_ALCINFH_EN_WIDTH 1 +#define MAX98926_ALCACT_EN_MASK (1<<2) +#define MAX98926_ALCACT_EN_SHIFT 2 +#define MAX98926_ALCACT_EN_WIDTH 1 +#define MAX98926_ALCMUT_EN_MASK (1<<1) +#define MAX98926_ALCMUT_EN_SHIFT 1 +#define MAX98926_ALCMUT_EN_WIDTH 1 +#define MAX98926_ALCP_EN_MASK (1<<0) +#define MAX98926_ALCP_EN_SHIFT 0 +#define MAX98926_ALCP_EN_WIDTH 1 + +/* MAX98926_R00D_IRQ_ENABLE2 */ +#define MAX98926_SLOTOVRN_EN_MASK (1<<6) +#define MAX98926_SLOTOVRN_EN_SHIFT 6 +#define MAX98926_SLOTOVRN_EN_WIDTH 1 +#define MAX98926_INVALSLOT_EN_MASK (1<<5) +#define MAX98926_INVALSLOT_EN_SHIFT 5 +#define MAX98926_INVALSLOT_EN_WIDTH 1 +#define MAX98926_SLOTCNFLT_EN_MASK (1<<4) +#define MAX98926_SLOTCNFLT_EN_SHIFT 4 +#define MAX98926_SLOTCNFLT_EN_WIDTH 1 +#define MAX98926_VBSTOVFL_EN_MASK (1<<3) +#define MAX98926_VBSTOVFL_EN_SHIFT 3 +#define MAX98926_VBSTOVFL_EN_WIDTH 1 +#define MAX98926_VBATOVFL_EN_MASK (1<<2) +#define MAX98926_VBATOVFL_EN_SHIFT 2 +#define MAX98926_VBATOVFL_EN_WIDTH 1 +#define MAX98926_IMONOVFL_EN_MASK (1<<1) +#define MAX98926_IMONOVFL_EN_SHIFT 1 +#define MAX98926_IMONOVFL_EN_WIDTH 1 +#define MAX98926_VMONOVFL_EN_MASK (1<<0) +#define MAX98926_VMONOVFL_EN_SHIFT 0 +#define MAX98926_VMONOVFL_EN_WIDTH 1 + +/* MAX98926_R00E_IRQ_CLEAR0 */ +#define MAX98926_THERMWARN_END_CLR_MASK (1<<3) +#define MAX98926_THERMWARN_END_CLR_SHIFT 3 +#define MAX98926_THERMWARN_END_CLR_WIDTH 1 +#define MAX98926_THERMWARN_BGN_CLR_MASK (1<<2) +#define MAX98926_THERMWARN_BGN_CLR_SHIFT 2 +#define MAX98926_THERMWARN_BGN_CLR_WIDTH 1 +#define MAX98926_THERMSHDN_END_CLR_MASK (1<<1) +#define MAX98926_THERMSHDN_END_CLR_SHIFT 1 +#define MAX98926_THERMSHDN_END_CLR_WIDTH 1 +#define MAX98926_THERMSHDN_BGN_CLR_MASK (1<<0) +#define MAX98926_THERMSHDN_BGN_CLR_SHIFT 0 +#define MAX98926_THERMSHDN_BGN_CLR_WIDTH 1 + +/* MAX98926_R00F_IRQ_CLEAR1 */ +#define MAX98926_SPKCURNT_CLR_MASK (1<<5) +#define MAX98926_SPKCURNT_CLR_SHIFT 5 +#define MAX98926_SPKCURNT_CLR_WIDTH 1 +#define MAX98926_WATCHFAIL_CLR_MASK (1<<4) +#define MAX98926_WATCHFAIL_CLR_SHIFT 4 +#define MAX98926_WATCHFAIL_CLR_WIDTH 1 +#define MAX98926_ALCINFH_CLR_MASK (1<<3) +#define MAX98926_ALCINFH_CLR_SHIFT 3 +#define MAX98926_ALCINFH_CLR_WIDTH 1 +#define MAX98926_ALCACT_CLR_MASK (1<<2) +#define MAX98926_ALCACT_CLR_SHIFT 2 +#define MAX98926_ALCACT_CLR_WIDTH 1 +#define MAX98926_ALCMUT_CLR_MASK (1<<1) +#define MAX98926_ALCMUT_CLR_SHIFT 1 +#define MAX98926_ALCMUT_CLR_WIDTH 1 +#define MAX98926_ALCP_CLR_MASK (1<<0) +#define MAX98926_ALCP_CLR_SHIFT 0 +#define MAX98926_ALCP_CLR_WIDTH 1 + +/* MAX98926_R010_IRQ_CLEAR2 */ +#define MAX98926_SLOTOVRN_CLR_MASK (1<<6) +#define MAX98926_SLOTOVRN_CLR_SHIFT 6 +#define MAX98926_SLOTOVRN_CLR_WIDTH 1 +#define MAX98926_INVALSLOT_CLR_MASK (1<<5) +#define MAX98926_INVALSLOT_CLR_SHIFT 5 +#define MAX98926_INVALSLOT_CLR_WIDTH 1 +#define MAX98926_SLOTCNFLT_CLR_MASK (1<<4) +#define MAX98926_SLOTCNFLT_CLR_SHIFT 4 +#define MAX98926_SLOTCNFLT_CLR_WIDTH 1 +#define MAX98926_VBSTOVFL_CLR_MASK (1<<3) +#define MAX98926_VBSTOVFL_CLR_SHIFT 3 +#define MAX98926_VBSTOVFL_CLR_WIDTH 1 +#define MAX98926_VBATOVFL_CLR_MASK (1<<2) +#define MAX98926_VBATOVFL_CLR_SHIFT 2 +#define MAX98926_VBATOVFL_CLR_WIDTH 1 +#define MAX98926_IMONOVFL_CLR_MASK (1<<1) +#define MAX98926_IMONOVFL_CLR_SHIFT 1 +#define MAX98926_IMONOVFL_CLR_WIDTH 1 +#define MAX98926_VMONOVFL_CLR_MASK (1<<0) +#define MAX98926_VMONOVFL_CLR_SHIFT 0 +#define MAX98926_VMONOVFL_CLR_WIDTH 1 + +/* MAX98926_R011_MAP0 */ +#define MAX98926_ER_THERMWARN_EN_MASK (1<<7) +#define MAX98926_ER_THERMWARN_EN_SHIFT 7 +#define MAX98926_ER_THERMWARN_EN_WIDTH 1 +#define MAX98926_ER_THERMWARN_MAP_MASK (0x07<<4) +#define MAX98926_ER_THERMWARN_MAP_SHIFT 4 +#define MAX98926_ER_THERMWARN_MAP_WIDTH 3 + +/* MAX98926_R012_MAP1 */ +#define MAX98926_ER_ALCMUT_EN_MASK (1<<7) +#define MAX98926_ER_ALCMUT_EN_SHIFT 7 +#define MAX98926_ER_ALCMUT_EN_WIDTH 1 +#define MAX98926_ER_ALCMUT_MAP_MASK (0x07<<4) +#define MAX98926_ER_ALCMUT_MAP_SHIFT 4 +#define MAX98926_ER_ALCMUT_MAP_WIDTH 3 +#define MAX98926_ER_ALCP_EN_MASK (1<<3) +#define MAX98926_ER_ALCP_EN_SHIFT 3 +#define MAX98926_ER_ALCP_EN_WIDTH 1 +#define MAX98926_ER_ALCP_MAP_MASK (0x07<<0) +#define MAX98926_ER_ALCP_MAP_SHIFT 0 +#define MAX98926_ER_ALCP_MAP_WIDTH 3 + +/* MAX98926_R013_MAP2 */ +#define MAX98926_ER_ALCINFH_EN_MASK (1<<7) +#define MAX98926_ER_ALCINFH_EN_SHIFT 7 +#define MAX98926_ER_ALCINFH_EN_WIDTH 1 +#define MAX98926_ER_ALCINFH_MAP_MASK (0x07<<4) +#define MAX98926_ER_ALCINFH_MAP_SHIFT 4 +#define MAX98926_ER_ALCINFH_MAP_WIDTH 3 +#define MAX98926_ER_ALCACT_EN_MASK (1<<3) +#define MAX98926_ER_ALCACT_EN_SHIFT 3 +#define MAX98926_ER_ALCACT_EN_WIDTH 1 +#define MAX98926_ER_ALCACT_MAP_MASK (0x07<<0) +#define MAX98926_ER_ALCACT_MAP_SHIFT 0 +#define MAX98926_ER_ALCACT_MAP_WIDTH 3 + +/* MAX98926_R014_MAP3 */ +#define MAX98926_ER_SPKCURNT_EN_MASK (1<<7) +#define MAX98926_ER_SPKCURNT_EN_SHIFT 7 +#define MAX98926_ER_SPKCURNT_EN_WIDTH 1 +#define MAX98926_ER_SPKCURNT_MAP_MASK (0x07<<4) +#define MAX98926_ER_SPKCURNT_MAP_SHIFT 4 +#define MAX98926_ER_SPKCURNT_MAP_WIDTH 3 + +/* MAX98926_R015_MAP4 */ +/* RESERVED */ + +/* MAX98926_R016_MAP5 */ +#define MAX98926_ER_IMONOVFL_EN_MASK (1<<7) +#define MAX98926_ER_IMONOVFL_EN_SHIFT 7 +#define MAX98926_ER_IMONOVFL_EN_WIDTH 1 +#define MAX98926_ER_IMONOVFL_MAP_MASK (0x07<<4) +#define MAX98926_ER_IMONOVFL_MAP_SHIFT 4 +#define MAX98926_ER_IMONOVFL_MAP_WIDTH 3 +#define MAX98926_ER_VMONOVFL_EN_MASK (1<<3) +#define MAX98926_ER_VMONOVFL_EN_SHIFT 3 +#define MAX98926_ER_VMONOVFL_EN_WIDTH 1 +#define MAX98926_ER_VMONOVFL_MAP_MASK (0x07<<0) +#define MAX98926_ER_VMONOVFL_MAP_SHIFT 0 +#define MAX98926_ER_VMONOVFL_MAP_WIDTH 3 + +/* MAX98926_R017_MAP6 */ +#define MAX98926_ER_VBSTOVFL_EN_MASK (1<<7) +#define MAX98926_ER_VBSTOVFL_EN_SHIFT 7 +#define MAX98926_ER_VBSTOVFL_EN_WIDTH 1 +#define MAX98926_ER_VBSTOVFL_MAP_MASK (0x07<<4) +#define MAX98926_ER_VBSTOVFL_MAP_SHIFT 4 +#define MAX98926_ER_VBSTOVFL_MAP_WIDTH 3 +#define MAX98926_ER_VBATOVFL_EN_MASK (1<<3) +#define MAX98926_ER_VBATOVFL_EN_SHIFT 3 +#define MAX98926_ER_VBATOVFL_EN_WIDTH 1 +#define MAX98926_ER_VBATOVFL_MAP_MASK (0x07<<0) +#define MAX98926_ER_VBATOVFL_MAP_SHIFT 0 +#define MAX98926_ER_VBATOVFL_MAP_WIDTH 3 + +/* MAX98926_R018_MAP7 */ +#define MAX98926_ER_INVALSLOT_EN_MASK (1<<7) +#define MAX98926_ER_INVALSLOT_EN_SHIFT 7 +#define MAX98926_ER_INVALSLOT_EN_WIDTH 1 +#define MAX98926_ER_INVALSLOT_MAP_MASK (0x07<<4) +#define MAX98926_ER_INVALSLOT_MAP_SHIFT 4 +#define MAX98926_ER_INVALSLOT_MAP_WIDTH 3 +#define MAX98926_ER_SLOTCNFLT_EN_MASK (1<<3) +#define MAX98926_ER_SLOTCNFLT_EN_SHIFT 3 +#define MAX98926_ER_SLOTCNFLT_EN_WIDTH 1 +#define MAX98926_ER_SLOTCNFLT_MAP_MASK (0x07<<0) +#define MAX98926_ER_SLOTCNFLT_MAP_SHIFT 0 +#define MAX98926_ER_SLOTCNFLT_MAP_WIDTH 3 + +/* MAX98926_R019_MAP8 */ +#define MAX98926_ER_SLOTOVRN_EN_MASK (1<<3) +#define MAX98926_ER_SLOTOVRN_EN_SHIFT 3 +#define MAX98926_ER_SLOTOVRN_EN_WIDTH 1 +#define MAX98926_ER_SLOTOVRN_MAP_MASK (0x07<<0) +#define MAX98926_ER_SLOTOVRN_MAP_SHIFT 0 +#define MAX98926_ER_SLOTOVRN_MAP_WIDTH 3 + +/* MAX98926_R01A_DAI_CLK_MODE1 */ +#define MAX98926_DAI_CLK_SOURCE_MASK (1<<6) +#define MAX98926_DAI_CLK_SOURCE_SHIFT 6 +#define MAX98926_DAI_CLK_SOURCE_WIDTH 1 +#define MAX98926_MDLL_MULT_MASK (0x0F<<0) +#define MAX98926_MDLL_MULT_SHIFT 0 +#define MAX98926_MDLL_MULT_WIDTH 4 + +#define MAX98926_MDLL_MULT_MCLKx8 6 +#define MAX98926_MDLL_MULT_MCLKx16 8 + +/* MAX98926_R01B_DAI_CLK_MODE2 */ +#define MAX98926_DAI_SR_MASK (0x0F<<4) +#define MAX98926_DAI_SR_SHIFT 4 +#define MAX98926_DAI_SR_WIDTH 4 +#define MAX98926_DAI_MAS_MASK (1<<3) +#define MAX98926_DAI_MAS_SHIFT 3 +#define MAX98926_DAI_MAS_WIDTH 1 +#define MAX98926_DAI_BSEL_MASK (0x07<<0) +#define MAX98926_DAI_BSEL_SHIFT 0 +#define MAX98926_DAI_BSEL_WIDTH 3 + +#define MAX98926_DAI_BSEL_32 (0 << MAX98926_DAI_BSEL_SHIFT) +#define MAX98926_DAI_BSEL_48 (1 << MAX98926_DAI_BSEL_SHIFT) +#define MAX98926_DAI_BSEL_64 (2 << MAX98926_DAI_BSEL_SHIFT) +#define MAX98926_DAI_BSEL_256 (6 << MAX98926_DAI_BSEL_SHIFT) + +/* MAX98926_R01C_DAI_CLK_DIV_M_MSBS */ +#define MAX98926_DAI_M_MSBS_MASK (0xFF<<0) +#define MAX98926_DAI_M_MSBS_SHIFT 0 +#define MAX98926_DAI_M_MSBS_WIDTH 8 + +/* MAX98926_R01D_DAI_CLK_DIV_M_LSBS */ +#define MAX98926_DAI_M_LSBS_MASK (0xFF<<0) +#define MAX98926_DAI_M_LSBS_SHIFT 0 +#define MAX98926_DAI_M_LSBS_WIDTH 8 + +/* MAX98926_R01E_DAI_CLK_DIV_N_MSBS */ +#define MAX98926_DAI_N_MSBS_MASK (0x7F<<0) +#define MAX98926_DAI_N_MSBS_SHIFT 0 +#define MAX98926_DAI_N_MSBS_WIDTH 7 + +/* MAX98926_R01F_DAI_CLK_DIV_N_LSBS */ +#define MAX98926_DAI_N_LSBS_MASK (0xFF<<0) +#define MAX98926_DAI_N_LSBS_SHIFT 0 +#define MAX98926_DAI_N_LSBS_WIDTH 8 + +/* MAX98926_R020_FORMAT */ +#define MAX98926_DAI_CHANSZ_MASK (0x03<<6) +#define MAX98926_DAI_CHANSZ_SHIFT 6 +#define MAX98926_DAI_CHANSZ_WIDTH 2 +#define MAX98926_DAI_INTERLEAVE_MASK (1<<5) +#define MAX98926_DAI_INTERLEAVE_SHIFT 5 +#define MAX98926_DAI_INTERLEAVE_WIDTH 1 +#define MAX98926_DAI_EXTBCLK_HIZ_MASK (1<<4) +#define MAX98926_DAI_EXTBCLK_HIZ_SHIFT 4 +#define MAX98926_DAI_EXTBCLK_HIZ_WIDTH 1 +#define MAX98926_DAI_WCI_MASK (1<<3) +#define MAX98926_DAI_WCI_SHIFT 3 +#define MAX98926_DAI_WCI_WIDTH 1 +#define MAX98926_DAI_BCI_MASK (1<<2) +#define MAX98926_DAI_BCI_SHIFT 2 +#define MAX98926_DAI_BCI_WIDTH 1 +#define MAX98926_DAI_DLY_MASK (1<<1) +#define MAX98926_DAI_DLY_SHIFT 1 +#define MAX98926_DAI_DLY_WIDTH 1 +#define MAX98926_DAI_TDM_MASK (1<<0) +#define MAX98926_DAI_TDM_SHIFT 0 +#define MAX98926_DAI_TDM_WIDTH 1 + +#define MAX98926_DAI_CHANSZ_16 (1 << MAX98926_DAI_CHANSZ_SHIFT) +#define MAX98926_DAI_CHANSZ_24 (2 << MAX98926_DAI_CHANSZ_SHIFT) +#define MAX98926_DAI_CHANSZ_32 (3 << MAX98926_DAI_CHANSZ_SHIFT) + +/* MAX98926_R021_TDM_SLOT_SELECT */ +#define MAX98926_DAI_DO_EN_MASK (1<<7) +#define MAX98926_DAI_DO_EN_SHIFT 7 +#define MAX98926_DAI_DO_EN_WIDTH 1 +#define MAX98926_DAI_DIN_EN_MASK (1<<6) +#define MAX98926_DAI_DIN_EN_SHIFT 6 +#define MAX98926_DAI_DIN_EN_WIDTH 1 +#define MAX98926_DAI_INR_SOURCE_MASK (0x07<<3) +#define MAX98926_DAI_INR_SOURCE_SHIFT 3 +#define MAX98926_DAI_INR_SOURCE_WIDTH 3 +#define MAX98926_DAI_INL_SOURCE_MASK (0x07<<0) +#define MAX98926_DAI_INL_SOURCE_SHIFT 0 +#define MAX98926_DAI_INL_SOURCE_WIDTH 3 + +/* MAX98926_R022_DOUT_CFG_VMON */ +#define MAX98926_DAI_VMON_EN_MASK (1<<5) +#define MAX98926_DAI_VMON_EN_SHIFT 5 +#define MAX98926_DAI_VMON_EN_WIDTH 1 +#define MAX98926_DAI_VMON_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_VMON_SLOT_SHIFT 0 +#define MAX98926_DAI_VMON_SLOT_WIDTH 5 + +#define MAX98926_DAI_VMON_SLOT_00_01 (0 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_01_02 (1 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_02_03 (2 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_03_04 (3 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_04_05 (4 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_05_06 (5 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_06_07 (6 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_07_08 (7 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_08_09 (8 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_09_0A (9 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0A_0B (10 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0B_0C (11 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0C_0D (12 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0D_0E (13 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0E_0F (14 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_0F_10 (15 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_10_11 (16 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_11_12 (17 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_12_13 (18 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_13_14 (19 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_14_15 (20 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_15_16 (21 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_16_17 (22 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_17_18 (23 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_18_19 (24 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_19_1A (25 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1A_1B (26 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1B_1C (27 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1C_1D (28 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1D_1E (29 << MAX98926_DAI_VMON_SLOT_SHIFT) +#define MAX98926_DAI_VMON_SLOT_1E_1F (30 << MAX98926_DAI_VMON_SLOT_SHIFT) + +/* MAX98926_R023_DOUT_CFG_IMON */ +#define MAX98926_DAI_IMON_EN_MASK (1<<5) +#define MAX98926_DAI_IMON_EN_SHIFT 5 +#define MAX98926_DAI_IMON_EN_WIDTH 1 +#define MAX98926_DAI_IMON_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_IMON_SLOT_SHIFT 0 +#define MAX98926_DAI_IMON_SLOT_WIDTH 5 + +#define MAX98926_DAI_IMON_SLOT_00_01 (0 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_01_02 (1 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_02_03 (2 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_03_04 (3 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_04_05 (4 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_05_06 (5 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_06_07 (6 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_07_08 (7 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_08_09 (8 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_09_0A (9 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0A_0B (10 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0B_0C (11 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0C_0D (12 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0D_0E (13 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0E_0F (14 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_0F_10 (15 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_10_11 (16 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_11_12 (17 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_12_13 (18 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_13_14 (19 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_14_15 (20 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_15_16 (21 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_16_17 (22 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_17_18 (23 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_18_19 (24 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_19_1A (25 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1A_1B (26 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1B_1C (27 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1C_1D (28 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1D_1E (29 << MAX98926_DAI_IMON_SLOT_SHIFT) +#define MAX98926_DAI_IMON_SLOT_1E_1F (30 << MAX98926_DAI_IMON_SLOT_SHIFT) + +/* MAX98926_R024_DOUT_CFG_VBAT */ +#define MAX98926_DAI_INTERLEAVE_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_INTERLEAVE_SLOT_SHIFT 0 +#define MAX98926_DAI_INTERLEAVE_SLOT_WIDTH 5 + +/* MAX98926_R025_DOUT_CFG_VBST */ +#define MAX98926_DAI_VBST_EN_MASK (1<<5) +#define MAX98926_DAI_VBST_EN_SHIFT 5 +#define MAX98926_DAI_VBST_EN_WIDTH 1 +#define MAX98926_DAI_VBST_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_VBST_SLOT_SHIFT 0 +#define MAX98926_DAI_VBST_SLOT_WIDTH 5 + +/* MAX98926_R026_DOUT_CFG_FLAG */ +#define MAX98926_DAI_FLAG_EN_MASK (1<<5) +#define MAX98926_DAI_FLAG_EN_SHIFT 5 +#define MAX98926_DAI_FLAG_EN_WIDTH 1 +#define MAX98926_DAI_FLAG_SLOT_MASK (0x1F<<0) +#define MAX98926_DAI_FLAG_SLOT_SHIFT 0 +#define MAX98926_DAI_FLAG_SLOT_WIDTH 5 + +/* MAX98926_R027_DOUT_HIZ_CFG1 */ +#define MAX98926_DAI_SLOT_HIZ_CFG1_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG1_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG1_WIDTH 8 + +/* MAX98926_R028_DOUT_HIZ_CFG2 */ +#define MAX98926_DAI_SLOT_HIZ_CFG2_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG2_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG2_WIDTH 8 + +/* MAX98926_R029_DOUT_HIZ_CFG3 */ +#define MAX98926_DAI_SLOT_HIZ_CFG3_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG3_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG3_WIDTH 8 + +/* MAX98926_R02A_DOUT_HIZ_CFG4 */ +#define MAX98926_DAI_SLOT_HIZ_CFG4_MASK (0xFF<<0) +#define MAX98926_DAI_SLOT_HIZ_CFG4_SHIFT 0 +#define MAX98926_DAI_SLOT_HIZ_CFG4_WIDTH 8 + +/* MAX98926_R02B_DOUT_DRV_STRENGTH */ +#define MAX98926_DAI_OUT_DRIVE_MASK (0x03<<0) +#define MAX98926_DAI_OUT_DRIVE_SHIFT 0 +#define MAX98926_DAI_OUT_DRIVE_WIDTH 2 + +/* MAX98926_R02C_FILTERS */ +#define MAX98926_ADC_DITHER_EN_MASK (1<<7) +#define MAX98926_ADC_DITHER_EN_SHIFT 7 +#define MAX98926_ADC_DITHER_EN_WIDTH 1 +#define MAX98926_IV_DCB_EN_MASK (1<<6) +#define MAX98926_IV_DCB_EN_SHIFT 6 +#define MAX98926_IV_DCB_EN_WIDTH 1 +#define MAX98926_DAC_DITHER_EN_MASK (1<<4) +#define MAX98926_DAC_DITHER_EN_SHIFT 4 +#define MAX98926_DAC_DITHER_EN_WIDTH 1 +#define MAX98926_DAC_FILTER_MODE_MASK (1<<3) +#define MAX98926_DAC_FILTER_MODE_SHIFT 3 +#define MAX98926_DAC_FILTER_MODE_WIDTH 1 +#define MAX98926_DAC_HPF_MASK (0x07<<0) +#define MAX98926_DAC_HPF_SHIFT 0 +#define MAX98926_DAC_HPF_WIDTH 3 +#define MAX98926_DAC_HPF_DISABLE (0 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_DC_BLOCK (1 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_100 (2 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_200 (3 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_400 (4 << MAX98926_DAC_HPF_SHIFT) +#define MAX98926_DAC_HPF_EN_800 (5 << MAX98926_DAC_HPF_SHIFT) + +/* MAX98926_R02D_GAIN */ +#define MAX98926_DAC_IN_SEL_MASK (0x03<<5) +#define MAX98926_DAC_IN_SEL_SHIFT 5 +#define MAX98926_DAC_IN_SEL_WIDTH 2 +#define MAX98926_SPK_GAIN_MASK (0x1F<<0) +#define MAX98926_SPK_GAIN_SHIFT 0 +#define MAX98926_SPK_GAIN_WIDTH 5 + +#define MAX98926_DAC_IN_SEL_LEFT_DAI (0 << MAX98926_DAC_IN_SEL_SHIFT) +#define MAX98926_DAC_IN_SEL_RIGHT_DAI (1 << MAX98926_DAC_IN_SEL_SHIFT) +#define MAX98926_DAC_IN_SEL_SUMMED_DAI (2 << MAX98926_DAC_IN_SEL_SHIFT) +#define MAX98926_DAC_IN_SEL_DIV2_SUMMED_DAI (3 << MAX98926_DAC_IN_SEL_SHIFT) + +/* MAX98926_R02E_GAIN_RAMPING */ +#define MAX98926_SPK_RMP_EN_MASK (1<<1) +#define MAX98926_SPK_RMP_EN_SHIFT 1 +#define MAX98926_SPK_RMP_EN_WIDTH 1 +#define MAX98926_SPK_ZCD_EN_MASK (1<<0) +#define MAX98926_SPK_ZCD_EN_SHIFT 0 +#define MAX98926_SPK_ZCD_EN_WIDTH 1 + +/* MAX98926_R02F_SPK_AMP */ +#define MAX98926_SPK_MODE_MASK (1<<0) +#define MAX98926_SPK_MODE_SHIFT 0 +#define MAX98926_SPK_MODE_WIDTH 1 +#define MAX98926_INSELECT_MODE_MASK (1<<1) +#define MAX98926_INSELECT_MODE_SHIFT 1 +#define MAX98926_INSELECT_MODE_WIDTH 1 + +/* MAX98926_R030_THRESHOLD */ +#define MAX98926_ALC_EN_MASK (1<<5) +#define MAX98926_ALC_EN_SHIFT 5 +#define MAX98926_ALC_EN_WIDTH 1 +#define MAX98926_ALC_TH_MASK (0x1F<<0) +#define MAX98926_ALC_TH_SHIFT 0 +#define MAX98926_ALC_TH_WIDTH 5 + +/* MAX98926_R031_ALC_ATTACK */ +#define MAX98926_ALC_ATK_STEP_MASK (0x0F<<4) +#define MAX98926_ALC_ATK_STEP_SHIFT 4 +#define MAX98926_ALC_ATK_STEP_WIDTH 4 +#define MAX98926_ALC_ATK_RATE_MASK (0x7<<0) +#define MAX98926_ALC_ATK_RATE_SHIFT 0 +#define MAX98926_ALC_ATK_RATE_WIDTH 3 + +/* MAX98926_R032_ALC_ATTEN_RLS */ +#define MAX98926_ALC_MAX_ATTEN_MASK (0x0F<<4) +#define MAX98926_ALC_MAX_ATTEN_SHIFT 4 +#define MAX98926_ALC_MAX_ATTEN_WIDTH 4 +#define MAX98926_ALC_RLS_RATE_MASK (0x7<<0) +#define MAX98926_ALC_RLS_RATE_SHIFT 0 +#define MAX98926_ALC_RLS_RATE_WIDTH 3 + +/* MAX98926_R033_ALC_HOLD_RLS */ +#define MAX98926_ALC_RLS_TGR_MASK (1<<0) +#define MAX98926_ALC_RLS_TGR_SHIFT 0 +#define MAX98926_ALC_RLS_TGR_WIDTH 1 + +/* MAX98926_R034_ALC_CONFIGURATION */ +#define MAX98926_ALC_MUTE_EN_MASK (1<<7) +#define MAX98926_ALC_MUTE_EN_SHIFT 7 +#define MAX98926_ALC_MUTE_EN_WIDTH 1 +#define MAX98926_ALC_MUTE_DLY_MASK (0x07<<4) +#define MAX98926_ALC_MUTE_DLY_SHIFT 4 +#define MAX98926_ALC_MUTE_DLY_WIDTH 3 +#define MAX98926_ALC_RLS_DBT_MASK (0x07<<0) +#define MAX98926_ALC_RLS_DBT_SHIFT 0 +#define MAX98926_ALC_RLS_DBT_WIDTH 3 + +/* MAX98926_R035_BOOST_CONVERTER */ +#define MAX98926_BST_SYNC_MASK (1<<7) +#define MAX98926_BST_SYNC_SHIFT 7 +#define MAX98926_BST_SYNC_WIDTH 1 +#define MAX98926_BST_PHASE_MASK (0x03<<4) +#define MAX98926_BST_PHASE_SHIFT 4 +#define MAX98926_BST_PHASE_WIDTH 2 +#define MAX98926_BST_SKIP_MODE_MASK (0x03<<0) +#define MAX98926_BST_SKIP_MODE_SHIFT 0 +#define MAX98926_BST_SKIP_MODE_WIDTH 2 + +/* MAX98926_R036_BLOCK_ENABLE */ +#define MAX98926_BST_EN_MASK (1<<7) +#define MAX98926_BST_EN_SHIFT 7 +#define MAX98926_BST_EN_WIDTH 1 +#define MAX98926_WATCH_EN_MASK (1<<6) +#define MAX98926_WATCH_EN_SHIFT 6 +#define MAX98926_WATCH_EN_WIDTH 1 +#define MAX98926_CLKMON_EN_MASK (1<<5) +#define MAX98926_CLKMON_EN_SHIFT 5 +#define MAX98926_CLKMON_EN_WIDTH 1 +#define MAX98926_SPK_EN_MASK (1<<4) +#define MAX98926_SPK_EN_SHIFT 4 +#define MAX98926_SPK_EN_WIDTH 1 +#define MAX98926_ADC_VBST_EN_MASK (1<<3) +#define MAX98926_ADC_VBST_EN_SHIFT 3 +#define MAX98926_ADC_VBST_EN_WIDTH 1 +#define MAX98926_ADC_VBAT_EN_MASK (1<<2) +#define MAX98926_ADC_VBAT_EN_SHIFT 2 +#define MAX98926_ADC_VBAT_EN_WIDTH 1 +#define MAX98926_ADC_IMON_EN_MASK (1<<1) +#define MAX98926_ADC_IMON_EN_SHIFT 1 +#define MAX98926_ADC_IMON_EN_WIDTH 1 +#define MAX98926_ADC_VMON_EN_MASK (1<<0) +#define MAX98926_ADC_VMON_EN_SHIFT 0 +#define MAX98926_ADC_VMON_EN_WIDTH 1 + +/* MAX98926_R037_CONFIGURATION */ +#define MAX98926_BST_VOUT_MASK (0x0F<<4) +#define MAX98926_BST_VOUT_SHIFT 4 +#define MAX98926_BST_VOUT_WIDTH 4 +#define MAX98926_THERMWARN_LEVEL_MASK (0x03<<2) +#define MAX98926_THERMWARN_LEVEL_SHIFT 2 +#define MAX98926_THERMWARN_LEVEL_WIDTH 2 +#define MAX98926_WATCH_TIME_MASK (0x03<<0) +#define MAX98926_WATCH_TIME_SHIFT 0 +#define MAX98926_WATCH_TIME_WIDTH 2 + +/* MAX98926_R038_GLOBAL_ENABLE */ +#define MAX98926_EN_MASK (1<<7) +#define MAX98926_EN_SHIFT 7 +#define MAX98926_EN_WIDTH 1 + +/* MAX98926_R03A_BOOST_LIMITER */ +#define MAX98926_BST_ILIM_MASK (0xF<<4) +#define MAX98926_BST_ILIM_SHIFT 4 +#define MAX98926_BST_ILIM_WIDTH 4 + +/* MAX98926_R0FF_VERSION */ +#define MAX98926_REV_ID_MASK (0xFF<<0) +#define MAX98926_REV_ID_SHIFT 0 +#define MAX98926_REV_ID_WIDTH 8 + +struct max98926_priv { + struct regmap *regmap; + struct snd_soc_codec *codec; + unsigned int sysclk; + unsigned int v_slot; + unsigned int i_slot; + unsigned int ch_size; + unsigned int interleave_mode; +}; +#endif -- cgit From b786ae8e269b5b30fea5efaab8cba32ba9aece61 Mon Sep 17 00:00:00 2001 From: Andrew Duggan Date: Tue, 26 Jan 2016 15:40:36 -0800 Subject: HID: rmi: Check that the device is a RMI device in suspend and resume callbacks Commit 092563604217 ("HID: rmi: Disable scanning if the device is not a wake source") introduced a regression for devices which use hid-rmi to handle composite USB devices. The suspend or resume callbacks are not checking that the device is a RMI device before calling rmi_read or rmi_write. This results in dereferencing uninitialized variables on non RMI devices. This patch checks that the RMI_DEVICE flag is set before sending RMI commands to the device. Reported-by: Rodrigo Gomes Signed-off-by: Andrew Duggan Signed-off-by: Jiri Kosina --- drivers/hid/hid-rmi.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 67cd059a8f46..9cd2ca34a6be 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -594,6 +594,9 @@ static int rmi_suspend(struct hid_device *hdev, pm_message_t message) int ret; u8 buf[RMI_F11_CTRL_REG_COUNT]; + if (!(data->device_flags & RMI_DEVICE)) + return 0; + ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, RMI_F11_CTRL_REG_COUNT); if (ret) @@ -613,6 +616,9 @@ static int rmi_post_reset(struct hid_device *hdev) struct rmi_data *data = hid_get_drvdata(hdev); int ret; + if (!(data->device_flags & RMI_DEVICE)) + return 0; + ret = rmi_reset_attn_mode(hdev); if (ret) { hid_err(hdev, "can not set rmi mode\n"); @@ -640,6 +646,11 @@ static int rmi_post_reset(struct hid_device *hdev) static int rmi_post_resume(struct hid_device *hdev) { + struct rmi_data *data = hid_get_drvdata(hdev); + + if (!(data->device_flags & RMI_DEVICE)) + return 0; + return rmi_reset_attn_mode(hdev); } #endif /* CONFIG_PM */ -- cgit From c8b710b3e4348119924051551b836c94835331b1 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:46 -0800 Subject: tty: Fix ldisc leak in failed tty_init_dev() release_tty() leaks the ldisc instance when called directly (rather than when releasing the file descriptor from tty_release()). Since tty_ldisc_release() clears tty->ldisc, releasing the ldisc instance at tty teardown if tty->ldisc is non-null is not in danger of double-releasing the ldisc. Remove deinitialize_tty_struct() now that free_tty_struct() always performs the tty_ldisc_deinit(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 5 ++--- drivers/tty/tty_io.c | 20 +++----------------- drivers/tty/tty_ldisc.c | 5 +++-- include/linux/tty.h | 1 - 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index b3110040164a..8cbe802bff1d 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -408,7 +408,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, the easy way .. */ retval = tty_init_termios(tty); if (retval) - goto err_deinit_tty; + goto err_free_tty; retval = tty_init_termios(o_tty); if (retval) @@ -447,8 +447,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, err_free_termios: if (legacy) tty_free_termios(tty); -err_deinit_tty: - deinitialize_tty_struct(o_tty); +err_free_tty: free_tty_struct(o_tty); err_put_module: module_put(driver->other->owner); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 5cec01c75691..c9f2365167df 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -172,6 +172,7 @@ void free_tty_struct(struct tty_struct *tty) { if (!tty) return; + tty_ldisc_deinit(tty); put_device(tty->dev); kfree(tty->write_buf); tty->magic = 0xDEADDEAD; @@ -1529,7 +1530,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) tty_lock(tty); retval = tty_driver_install_tty(driver, tty); if (retval < 0) - goto err_deinit_tty; + goto err_free_tty; if (!tty->port) tty->port = driver->ports[idx]; @@ -1551,9 +1552,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) /* Return the tty locked so that it cannot vanish under the caller */ return tty; -err_deinit_tty: +err_free_tty: tty_unlock(tty); - deinitialize_tty_struct(tty); free_tty_struct(tty); err_module_put: module_put(driver->owner); @@ -3162,20 +3162,6 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) return tty; } -/** - * deinitialize_tty_struct - * @tty: tty to deinitialize - * - * This subroutine deinitializes a tty structure that has been newly - * allocated but tty_release cannot be called on that yet. - * - * Locking: none - tty in question must not be exposed at this point - */ -void deinitialize_tty_struct(struct tty_struct *tty) -{ - tty_ldisc_deinit(tty); -} - /** * tty_put_char - write one character to a tty * @tty: tty diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index a054d03c22e7..49f0cea1e538 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -797,7 +797,7 @@ void tty_ldisc_init(struct tty_struct *tty) } /** - * tty_ldisc_init - ldisc cleanup for new tty + * tty_ldisc_deinit - ldisc cleanup for new tty * @tty: tty that was allocated recently * * The tty structure must not becompletely set up (tty_ldisc_setup) when @@ -805,7 +805,8 @@ void tty_ldisc_init(struct tty_struct *tty) */ void tty_ldisc_deinit(struct tty_struct *tty) { - tty_ldisc_put(tty->ldisc); + if (tty->ldisc) + tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; } diff --git a/include/linux/tty.h b/include/linux/tty.h index d9fb4b043f56..64e301dbf7b9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -509,7 +509,6 @@ extern int tty_alloc_file(struct file *file); extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void tty_free_file(struct file *file); extern void free_tty_struct(struct tty_struct *tty); -extern void deinitialize_tty_struct(struct tty_struct *tty); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); extern int tty_release(struct inode *inode, struct file *filp); extern int tty_init_termios(struct tty_struct *tty); -- cgit From a99cc5d9954651ac7402dcd40b133848303ba596 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:47 -0800 Subject: tty: Remove !tty check from free_tty_struct() free_tty_struct() is never called with NULL tty; the two call sites would already have faulted on earlier access. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c9f2365167df..a59930e59660 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -170,8 +170,6 @@ static void release_tty(struct tty_struct *tty, int idx); void free_tty_struct(struct tty_struct *tty) { - if (!tty) - return; tty_ldisc_deinit(tty); put_device(tty->dev); kfree(tty->write_buf); -- cgit From a3123fd0a4a5f9d71afa0ffa82e2086281d81822 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:48 -0800 Subject: tty: Fix tty_init_termios() declaration tty_init_termios() never returns an error; re-declare as void. Remove unnecessary error handling from callers. Remove extern declarations of tty_free_termios() and free_tty_struct() and re-declare in file scope. Signed-off-by: Peter Hurley Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 15 +++------------ drivers/tty/tty_io.c | 13 ++++--------- drivers/usb/serial/console.c | 6 +----- include/linux/tty.h | 4 +--- 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 8cbe802bff1d..7e885a226f88 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -406,13 +406,8 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, if (legacy) { /* We always use new tty termios data so we can do this the easy way .. */ - retval = tty_init_termios(tty); - if (retval) - goto err_free_tty; - - retval = tty_init_termios(o_tty); - if (retval) - goto err_free_termios; + tty_init_termios(tty); + tty_init_termios(o_tty); driver->other->ttys[idx] = o_tty; driver->ttys[idx] = tty; @@ -444,11 +439,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty, tty->count++; o_tty->count++; return 0; -err_free_termios: - if (legacy) - tty_free_termios(tty); -err_free_tty: - free_tty_struct(o_tty); + err_put_module: module_put(driver->other->owner); err: diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a59930e59660..742860e583ce 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -168,7 +168,7 @@ static void release_tty(struct tty_struct *tty, int idx); * Locking: none. Must be called after tty is definitely unused */ -void free_tty_struct(struct tty_struct *tty) +static void free_tty_struct(struct tty_struct *tty) { tty_ldisc_deinit(tty); put_device(tty->dev); @@ -1377,7 +1377,7 @@ static struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, * the tty_mutex currently so we can be relaxed about ordering. */ -int tty_init_termios(struct tty_struct *tty) +void tty_init_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1395,16 +1395,12 @@ int tty_init_termios(struct tty_struct *tty) /* Compatibility until drivers always set this */ tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios); tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios); - return 0; } EXPORT_SYMBOL_GPL(tty_init_termios); int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty) { - int ret = tty_init_termios(tty); - if (ret) - return ret; - + tty_init_termios(tty); tty_driver_kref_get(driver); tty->count++; driver->ttys[tty->index] = tty; @@ -1566,7 +1562,7 @@ err_release_tty: return ERR_PTR(retval); } -void tty_free_termios(struct tty_struct *tty) +static void tty_free_termios(struct tty_struct *tty) { struct ktermios *tp; int idx = tty->index; @@ -1585,7 +1581,6 @@ void tty_free_termios(struct tty_struct *tty) } *tp = tty->termios; } -EXPORT_SYMBOL(tty_free_termios); /** * tty_flush_works - flush all works of a tty/pty pair diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 3806e7014199..a66b01bb1fa1 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -147,10 +147,7 @@ static int usb_console_setup(struct console *co, char *options) kref_get(&tty->driver->kref); __module_get(tty->driver->owner); tty->ops = &usb_console_fake_tty_ops; - if (tty_init_termios(tty)) { - retval = -ENOMEM; - goto put_tty; - } + tty_init_termios(tty); tty_port_tty_set(&port->port, tty); } @@ -185,7 +182,6 @@ static int usb_console_setup(struct console *co, char *options) fail: tty_port_tty_set(&port->port, NULL); - put_tty: tty_kref_put(tty); reset_open_count: port->port.count = 0; diff --git a/include/linux/tty.h b/include/linux/tty.h index 64e301dbf7b9..d7a7c1efe77f 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -448,7 +448,6 @@ extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); extern void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty); -extern void tty_free_termios(struct tty_struct *tty); extern int is_current_pgrp_orphaned(void); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); @@ -508,10 +507,9 @@ extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx); extern int tty_alloc_file(struct file *file); extern void tty_add_file(struct tty_struct *tty, struct file *file); extern void tty_free_file(struct file *file); -extern void free_tty_struct(struct tty_struct *tty); extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); extern int tty_release(struct inode *inode, struct file *filp); -extern int tty_init_termios(struct tty_struct *tty); +extern void tty_init_termios(struct tty_struct *tty); extern int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty); -- cgit From 05de87ed9531dc19d87136c9204d251abebc60d3 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:49 -0800 Subject: tty: Re-declare tty_driver_remove_tty() file scope tty_driver_remove_tty() is only local-scope; declare as static. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 2 +- include/linux/tty.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 742860e583ce..6cffe0d57d70 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1437,7 +1437,7 @@ static int tty_driver_install_tty(struct tty_driver *driver, * * Locking: tty_mutex for now */ -void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) +static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *tty) { if (driver->ops->remove) driver->ops->remove(driver, tty); diff --git a/include/linux/tty.h b/include/linux/tty.h index d7a7c1efe77f..57c4e03ec2aa 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -446,8 +446,6 @@ extern void tty_unthrottle(struct tty_struct *tty); extern int tty_throttle_safe(struct tty_struct *tty); extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); -extern void tty_driver_remove_tty(struct tty_driver *driver, - struct tty_struct *tty); extern int is_current_pgrp_orphaned(void); extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); -- cgit From c1e33af1ed552258405f2e5a72509af039c0441c Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:50 -0800 Subject: pty: Remove pty_unix98_shutdown() The tty core invokes the optional driver shutdown() just before the optional driver remove() (shutdown() has access to the termios and remove() does not). Because pty drivers must prevent the default remove() action, the Unix98 pty drivers define a dummy remove() function. Instead, release the slave index in the remove() method and delete the optional shutdown() method. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/pty.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 7e885a226f88..be5020d567ae 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -656,20 +656,13 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, return tty; } -/* We have no need to install and remove our tty objects as devpts does all - the work for us */ - static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) { return pty_common_install(driver, tty, false); } -static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) -{ -} - /* this is called once with whichever end is closed last */ -static void pty_unix98_shutdown(struct tty_struct *tty) +static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) { devpts_kill_index(tty->driver_data, tty->index); } @@ -687,7 +680,6 @@ static const struct tty_operations ptm_unix98_ops = { .unthrottle = pty_unthrottle, .ioctl = pty_unix98_ioctl, .resize = pty_resize, - .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup }; @@ -705,7 +697,6 @@ static const struct tty_operations pty_unix98_ops = { .set_termios = pty_set_termios, .start = pty_start, .stop = pty_stop, - .shutdown = pty_unix98_shutdown, .cleanup = pty_cleanup, }; -- cgit From c2bb524b2e1a6eddae65139601bee24cb60856a0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:51 -0800 Subject: tty: Remove __lockfunc annotation from tty lock functions The tty lock/unlock code does not belong in the special lockfunc section which is treated specially by stack backtraces. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 16 +++++++--------- drivers/tty/tty_mutex.c | 8 ++++---- include/linux/tty.h | 8 ++++---- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 49f0cea1e538..713cc2d48846 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -304,13 +304,13 @@ void tty_ldisc_deref(struct tty_ldisc *ld) EXPORT_SYMBOL_GPL(tty_ldisc_deref); -static inline int __lockfunc +static inline int __tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { return ldsem_down_write(&tty->ldisc_sem, timeout); } -static inline int __lockfunc +static inline int __tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout) { return ldsem_down_write_nested(&tty->ldisc_sem, @@ -322,8 +322,7 @@ static inline void __tty_ldisc_unlock(struct tty_struct *tty) ldsem_up_write(&tty->ldisc_sem); } -static int __lockfunc -tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) +static int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout) { int ret; @@ -340,7 +339,7 @@ static void tty_ldisc_unlock(struct tty_struct *tty) __tty_ldisc_unlock(tty); } -static int __lockfunc +static int tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, unsigned long timeout) { @@ -376,14 +375,13 @@ tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2, return 0; } -static void __lockfunc -tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) +static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2) { tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT); } -static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty, - struct tty_struct *tty2) +static void tty_ldisc_unlock_pair(struct tty_struct *tty, + struct tty_struct *tty2) { __tty_ldisc_unlock(tty); if (tty2) diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index d2f3c4cd697f..75351e4b77df 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c @@ -10,7 +10,7 @@ * Getting the big tty mutex. */ -void __lockfunc tty_lock(struct tty_struct *tty) +void tty_lock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty)) return; @@ -27,7 +27,7 @@ int tty_lock_interruptible(struct tty_struct *tty) return mutex_lock_interruptible(&tty->legacy_mutex); } -void __lockfunc tty_unlock(struct tty_struct *tty) +void tty_unlock(struct tty_struct *tty) { if (WARN(tty->magic != TTY_MAGIC, "U Bad %p\n", tty)) return; @@ -36,13 +36,13 @@ void __lockfunc tty_unlock(struct tty_struct *tty) } EXPORT_SYMBOL(tty_unlock); -void __lockfunc tty_lock_slave(struct tty_struct *tty) +void tty_lock_slave(struct tty_struct *tty) { if (tty && tty != tty->link) tty_lock(tty); } -void __lockfunc tty_unlock_slave(struct tty_struct *tty) +void tty_unlock_slave(struct tty_struct *tty) { if (tty && tty != tty->link) tty_unlock(tty); diff --git a/include/linux/tty.h b/include/linux/tty.h index 57c4e03ec2aa..83f127673bc9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -643,11 +643,11 @@ extern long vt_compat_ioctl(struct tty_struct *tty, /* tty_mutex.c */ /* functions for preparation of BKL removal */ -extern void __lockfunc tty_lock(struct tty_struct *tty); +extern void tty_lock(struct tty_struct *tty); extern int tty_lock_interruptible(struct tty_struct *tty); -extern void __lockfunc tty_unlock(struct tty_struct *tty); -extern void __lockfunc tty_lock_slave(struct tty_struct *tty); -extern void __lockfunc tty_unlock_slave(struct tty_struct *tty); +extern void tty_unlock(struct tty_struct *tty); +extern void tty_lock_slave(struct tty_struct *tty); +extern void tty_unlock_slave(struct tty_struct *tty); extern void tty_set_lock_subclass(struct tty_struct *tty); #ifdef CONFIG_PROC_FS -- cgit From 11e1d4aa4da1d0572b00f040ae91da85d3474f4a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:52 -0800 Subject: tty: Consolidate noctty checks in tty_open() Evaluate the conditions which prevent this tty being the controlling terminal in one place, just before setting the controlling terminal. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6cffe0d57d70..741a0d7f51ce 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1960,7 +1960,7 @@ static struct tty_struct *tty_open_current_tty(dev_t device, struct file *filp) * Locking: tty_mutex protects get_tty_driver */ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, - int *noctty, int *index) + int *index) { struct tty_driver *driver; @@ -1970,7 +1970,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, extern struct tty_driver *console_driver; driver = tty_driver_kref_get(console_driver); *index = fg_console; - *noctty = 1; break; } #endif @@ -1981,7 +1980,6 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, if (driver) { /* Don't let /dev/console block */ filp->f_flags |= O_NONBLOCK; - *noctty = 1; break; } } @@ -2036,14 +2034,13 @@ retry_open: if (retval) return -ENOMEM; - noctty = filp->f_flags & O_NOCTTY; index = -1; retval = 0; tty = tty_open_current_tty(device, filp); if (!tty) { mutex_lock(&tty_mutex); - driver = tty_lookup_driver(device, filp, &noctty, &index); + driver = tty_lookup_driver(device, filp, &index); if (IS_ERR(driver)) { retval = PTR_ERR(driver); goto err_unlock; @@ -2091,10 +2088,6 @@ retry_open: tty_add_file(tty, filp); check_tty_count(tty, __func__); - if (tty->driver->type == TTY_DRIVER_TYPE_PTY && - tty->driver->subtype == PTY_TYPE_MASTER) - noctty = 1; - tty_debug_hangup(tty, "opening (count=%d)\n", tty->count); if (tty->ops->open) @@ -2127,6 +2120,12 @@ retry_open: read_lock(&tasklist_lock); spin_lock_irq(¤t->sighand->siglock); + noctty = (filp->f_flags & O_NOCTTY) || + device == MKDEV(TTY_MAJOR, 0) || + device == MKDEV(TTYAUX_MAJOR, 1) || + (tty->driver->type == TTY_DRIVER_TYPE_PTY && + tty->driver->subtype == PTY_TYPE_MASTER); + if (!noctty && current->signal->leader && !current->signal->tty && -- cgit From d6203d0c7b738d7ce75d5629b72640b489487cfa Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:13:53 -0800 Subject: tty: Refactor tty_open() Extract the driver lookup and reopen-or-initialize logic into helper function tty_open_by_driver(). No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 120 ++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 741a0d7f51ce..524703a7df2b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1994,6 +1994,69 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp, return driver; } +/** + * tty_open_by_driver - open a tty device + * @device: dev_t of device to open + * @inode: inode of device file + * @filp: file pointer to tty + * + * Performs the driver lookup, checks for a reopen, or otherwise + * performs the first-time tty initialization. + * + * Returns the locked initialized or re-opened &tty_struct + * + * Claims the global tty_mutex to serialize: + * - concurrent first-time tty initialization + * - concurrent tty driver removal w/ lookup + * - concurrent tty removal from driver table + */ +static struct tty_struct *tty_open_by_driver(dev_t device, struct inode *inode, + struct file *filp) +{ + struct tty_struct *tty; + struct tty_driver *driver = NULL; + int index = -1; + int retval; + + mutex_lock(&tty_mutex); + driver = tty_lookup_driver(device, filp, &index); + if (IS_ERR(driver)) { + mutex_unlock(&tty_mutex); + return ERR_CAST(driver); + } + + /* check whether we're reopening an existing tty */ + tty = tty_driver_lookup_tty(driver, inode, index); + if (IS_ERR(tty)) { + mutex_unlock(&tty_mutex); + goto out; + } + + if (tty) { + mutex_unlock(&tty_mutex); + retval = tty_lock_interruptible(tty); + if (retval) { + if (retval == -EINTR) + retval = -ERESTARTSYS; + tty = ERR_PTR(retval); + goto out; + } + /* safe to drop the kref from tty_driver_lookup_tty() */ + tty_kref_put(tty); + retval = tty_reopen(tty); + if (retval < 0) { + tty_unlock(tty); + tty = ERR_PTR(retval); + } + } else { /* Returns with the tty_lock held for now */ + tty = tty_init_dev(driver, index); + mutex_unlock(&tty_mutex); + } +out: + tty_driver_kref_put(driver); + return tty; +} + /** * tty_open - open a tty device * @inode: inode of device file @@ -2022,8 +2085,6 @@ static int tty_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int noctty, retval; - struct tty_driver *driver = NULL; - int index; dev_t device = inode->i_rdev; unsigned saved_flags = filp->f_flags; @@ -2034,53 +2095,15 @@ retry_open: if (retval) return -ENOMEM; - index = -1; - retval = 0; - tty = tty_open_current_tty(device, filp); - if (!tty) { - mutex_lock(&tty_mutex); - driver = tty_lookup_driver(device, filp, &index); - if (IS_ERR(driver)) { - retval = PTR_ERR(driver); - goto err_unlock; - } - - /* check whether we're reopening an existing tty */ - tty = tty_driver_lookup_tty(driver, inode, index); - if (IS_ERR(tty)) { - retval = PTR_ERR(tty); - goto err_unlock; - } - - if (tty) { - mutex_unlock(&tty_mutex); - retval = tty_lock_interruptible(tty); - if (retval) { - if (retval == -EINTR) - retval = -ERESTARTSYS; - goto err_unref; - } - /* safe to drop the kref from tty_driver_lookup_tty() */ - tty_kref_put(tty); - retval = tty_reopen(tty); - if (retval < 0) { - tty_unlock(tty); - tty = ERR_PTR(retval); - } - } else { /* Returns with the tty_lock held for now */ - tty = tty_init_dev(driver, index); - mutex_unlock(&tty_mutex); - } - - tty_driver_kref_put(driver); - } + if (!tty) + tty = tty_open_by_driver(device, inode, filp); if (IS_ERR(tty)) { + tty_free_file(filp); retval = PTR_ERR(tty); if (retval != -EAGAIN || signal_pending(current)) - goto err_file; - tty_free_file(filp); + return retval; schedule(); goto retry_open; } @@ -2151,15 +2174,6 @@ retry_open: read_unlock(&tasklist_lock); tty_unlock(tty); return 0; -err_unlock: - mutex_unlock(&tty_mutex); -err_unref: - /* after locks to avoid deadlock */ - if (!IS_ERR_OR_NULL(driver)) - tty_driver_kref_put(driver); -err_file: - tty_free_file(filp); - return retval; } -- cgit From e4cf92ba44b86d287bdf1ef6a70417b98c441c7b Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:53:33 -0800 Subject: Input: cyttsp - use devres managed resource allocations Use devm_() functions for allocating memory, input device and IRQ. Signed-off-by: Oreste Salerno Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 68 +++++++++++++++------------------ drivers/input/touchscreen/cyttsp_core.h | 1 - drivers/input/touchscreen/cyttsp_i2c.c | 10 ----- drivers/input/touchscreen/cyttsp_spi.c | 10 ----- 4 files changed, 30 insertions(+), 59 deletions(-) diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 5b74e8b84e79..2d699808b55a 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -528,6 +528,14 @@ static void cyttsp_close(struct input_dev *dev) cyttsp_disable(ts); } +static void cyttsp_platform_exit(void *data) +{ + struct cyttsp *ts = data; + + if (ts->pdata->exit) + ts->pdata->exit(); +} + struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { @@ -536,17 +544,16 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct input_dev *input_dev; int error; - if (!pdata || !pdata->name || irq <= 0) { - error = -EINVAL; - goto err_out; - } + if (!pdata || !pdata->name || irq <= 0) + return ERR_PTR(-EINVAL); - ts = kzalloc(sizeof(*ts) + xfer_buf_size, GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - error = -ENOMEM; - goto err_free_mem; - } + ts = devm_kzalloc(dev, sizeof(*ts) + xfer_buf_size, GFP_KERNEL); + if (!ts) + return ERR_PTR(-ENOMEM); + + input_dev = devm_input_allocate_device(dev); + if (!input_dev) + return ERR_PTR(-ENOMEM); ts->dev = dev; ts->input = input_dev; @@ -557,12 +564,18 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, init_completion(&ts->bl_ready); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); + error = devm_add_action(dev, cyttsp_platform_exit, ts); + if (error) { + dev_err(dev, "failed to install exit action: %d\n", error); + return ERR_PTR(error); + } + if (pdata->init) { error = pdata->init(); if (error) { dev_err(ts->dev, "platform init failed, err: %d\n", error); - goto err_free_mem; + return ERR_PTR(error); } } @@ -586,53 +599,32 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_mt_init_slots(input_dev, CY_MAX_ID, 0); - error = request_threaded_irq(ts->irq, NULL, cyttsp_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - pdata->name, ts); + error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + pdata->name, ts); if (error) { dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", ts->irq, error); - goto err_platform_exit; + return ERR_PTR(error); } disable_irq(ts->irq); error = cyttsp_power_on(ts); if (error) - goto err_free_irq; + return ERR_PTR(error); error = input_register_device(input_dev); if (error) { dev_err(ts->dev, "failed to register input device: %d\n", error); - goto err_free_irq; + return ERR_PTR(error); } return ts; - -err_free_irq: - free_irq(ts->irq, ts); -err_platform_exit: - if (pdata->exit) - pdata->exit(); -err_free_mem: - input_free_device(input_dev); - kfree(ts); -err_out: - return ERR_PTR(error); } EXPORT_SYMBOL_GPL(cyttsp_probe); -void cyttsp_remove(struct cyttsp *ts) -{ - free_irq(ts->irq, ts); - input_unregister_device(ts->input); - if (ts->pdata->exit) - ts->pdata->exit(); - kfree(ts); -} -EXPORT_SYMBOL_GPL(cyttsp_remove); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core"); MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 07074110a902..c5e7afce6de8 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -143,7 +143,6 @@ struct cyttsp { struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size); -void cyttsp_remove(struct cyttsp *ts); int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, const void *values); diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index eee51b3f2e3f..1edfdba96ede 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -56,15 +56,6 @@ static int cyttsp_i2c_probe(struct i2c_client *client, return 0; } -static int cyttsp_i2c_remove(struct i2c_client *client) -{ - struct cyttsp *ts = i2c_get_clientdata(client); - - cyttsp_remove(ts); - - return 0; -} - static const struct i2c_device_id cyttsp_i2c_id[] = { { CY_I2C_NAME, 0 }, { } @@ -77,7 +68,6 @@ static struct i2c_driver cyttsp_i2c_driver = { .pm = &cyttsp_pm_ops, }, .probe = cyttsp_i2c_probe, - .remove = cyttsp_i2c_remove, .id_table = cyttsp_i2c_id, }; diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index bbeeb2488b57..3c9d18b1b6ef 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -170,22 +170,12 @@ static int cyttsp_spi_probe(struct spi_device *spi) return 0; } -static int cyttsp_spi_remove(struct spi_device *spi) -{ - struct cyttsp *ts = spi_get_drvdata(spi); - - cyttsp_remove(ts); - - return 0; -} - static struct spi_driver cyttsp_spi_driver = { .driver = { .name = CY_SPI_NAME, .pm = &cyttsp_pm_ops, }, .probe = cyttsp_spi_probe, - .remove = cyttsp_spi_remove, }; module_spi_driver(cyttsp_spi_driver); -- cgit From 69a124029b4bfcfc66b477ad2c3298f06c905ee6 Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:55:20 -0800 Subject: Input: cyttsp - check return value of input_mt_init_slots Signed-off-by: Oreste Salerno Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 2d699808b55a..b6653aa06108 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -597,7 +597,11 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0); - input_mt_init_slots(input_dev, CY_MAX_ID, 0); + error = input_mt_init_slots(input_dev, CY_MAX_ID, 0); + if (error) { + dev_err(dev, "Unable to init MT slots.\n"); + return ERR_PTR(error); + } error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, -- cgit From 707b61bba8b16adb6a2cbc72b71a75e09cb0f81a Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:55:43 -0800 Subject: Input: cyttsp - switch to using device properties Drop support for platform data passed via a C-structure and switch to device properties instead, which should make the driver compatible with all platforms: OF, ACPI and static boards. Static boards should use property sets to communicate device parameters to the driver. Signed-off-by: Oreste Salerno Acked-by: Rob Herring Signed-off-by: Dmitry Torokhov --- .../bindings/input/touchscreen/cyttsp.txt | 95 ++++++++++++++ drivers/input/touchscreen/cyttsp_core.c | 136 ++++++++++++++------- drivers/input/touchscreen/cyttsp_core.h | 9 +- include/linux/input/cyttsp.h | 15 --- 4 files changed, 197 insertions(+), 58 deletions(-) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt diff --git a/Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt b/Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt new file mode 100644 index 000000000000..b75d4cfd2c36 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/cyttsp.txt @@ -0,0 +1,95 @@ +* Cypress cyttsp touchscreen controller + +Required properties: + - compatible : must be "cypress,cyttsp-i2c" or "cypress,cyttsp-spi" + - reg : Device I2C address or SPI chip select number + - spi-max-frequency : Maximum SPI clocking speed of the device (for cyttsp-spi) + - interrupt-parent : the phandle for the gpio controller + (see interrupt binding[0]). + - interrupts : (gpio) interrupt to which the chip is connected + (see interrupt binding[0]). + - bootloader-key : the 8-byte bootloader key that is required to switch + the chip from bootloader mode (default mode) to + application mode. + This property has to be specified as an array of 8 + '/bits/ 8' values. + +Optional properties: + - reset-gpios : the reset gpio the chip is connected to + (see GPIO binding[1] for more details). + - touchscreen-size-x : horizontal resolution of touchscreen (in pixels) + - touchscreen-size-y : vertical resolution of touchscreen (in pixels) + - touchscreen-fuzz-x : horizontal noise value of the absolute input device + (in pixels) + - touchscreen-fuzz-y : vertical noise value of the absolute input device + (in pixels) + - active-distance : the distance in pixels beyond which a touch must move + before movement is detected and reported by the device. + Valid values: 0-15. + - active-interval-ms : the minimum period in ms between consecutive + scanning/processing cycles when the chip is in active mode. + Valid values: 0-255. + - lowpower-interval-ms : the minimum period in ms between consecutive + scanning/processing cycles when the chip is in low-power mode. + Valid values: 0-2550 + - touch-timeout-ms : minimum time in ms spent in the active power state while no + touches are detected before entering low-power mode. + Valid values: 0-2550 + - use-handshake : enable register-based handshake (boolean). This should + only be used if the chip is configured to use 'blocking + communication with timeout' (in this case the device + generates an interrupt at the end of every + scanning/processing cycle). + +[0]: Documentation/devicetree/bindings/interrupt-controller/interrupts.txt +[1]: Documentation/devicetree/bindings/gpio/gpio.txt + +Example: + &i2c1 { + /* ... */ + cyttsp@a { + compatible = "cypress,cyttsp-i2c"; + reg = <0xa>; + interrupt-parent = <&gpio0>; + interrupts = <28 0>; + reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; + + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; + touchscreen-fuzz-x = <4>; + touchscreen-fuzz-y = <7>; + + bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>; + active-distance = <8>; + active-interval-ms = <0>; + lowpower-interval-ms = <200>; + touch-timeout-ms = <100>; + }; + + /* ... */ + }; + + &mcspi1 { + /* ... */ + cyttsp@0 { + compatible = "cypress,cyttsp-spi"; + spi-max-frequency = <6000000>; + reg = <0>; + interrupt-parent = <&gpio0>; + interrupts = <28 0>; + reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; + + touchscreen-size-x = <800>; + touchscreen-size-y = <480>; + touchscreen-fuzz-x = <4>; + touchscreen-fuzz-y = <7>; + + bootloader-key = /bits/ 8 <0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08>; + active-distance = <8>; + active-interval-ms = <0>; + lowpower-interval-ms = <200>; + touch-timeout-ms = <100>; + }; + + /* ... */ + }; diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index b6653aa06108..8814b6c87097 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -30,9 +30,12 @@ #include #include #include +#include #include #include #include +#include +#include #include "cyttsp_core.h" @@ -57,6 +60,7 @@ #define CY_DELAY_DFLT 20 /* ms */ #define CY_DELAY_MAX 500 #define CY_ACT_DIST_DFLT 0xF8 +#define CY_ACT_DIST_MASK 0x0F #define CY_HNDSHK_BIT 0x80 /* device mode bits */ #define CY_OPERATE_MODE 0x00 @@ -120,7 +124,7 @@ static int ttsp_send_command(struct cyttsp *ts, u8 cmd) static int cyttsp_handshake(struct cyttsp *ts) { - if (ts->pdata->use_hndshk) + if (ts->use_hndshk) return ttsp_send_command(ts, ts->xy_data.hst_mode ^ CY_HNDSHK_BIT); @@ -142,9 +146,9 @@ static int cyttsp_exit_bl_mode(struct cyttsp *ts) u8 bl_cmd[sizeof(bl_command)]; memcpy(bl_cmd, bl_command, sizeof(bl_command)); - if (ts->pdata->bl_keys) + if (ts->bl_keys) memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], - ts->pdata->bl_keys, CY_NUM_BL_KEYS); + ts->bl_keys, CY_NUM_BL_KEYS); error = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(bl_cmd), bl_cmd); @@ -217,14 +221,14 @@ static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) { int retval = 0; - if (ts->pdata->act_intrvl != CY_ACT_INTRVL_DFLT || - ts->pdata->tch_tmout != CY_TCH_TMOUT_DFLT || - ts->pdata->lp_intrvl != CY_LP_INTRVL_DFLT) { + if (ts->act_intrvl != CY_ACT_INTRVL_DFLT || + ts->tch_tmout != CY_TCH_TMOUT_DFLT || + ts->lp_intrvl != CY_LP_INTRVL_DFLT) { u8 intrvl_ray[] = { - ts->pdata->act_intrvl, - ts->pdata->tch_tmout, - ts->pdata->lp_intrvl + ts->act_intrvl, + ts->tch_tmout, + ts->lp_intrvl }; /* set intrvl registers */ @@ -263,7 +267,7 @@ out: static int cyttsp_act_dist_setup(struct cyttsp *ts) { - u8 act_dist_setup = ts->pdata->act_dist; + u8 act_dist_setup = ts->act_dist; /* Init gesture; active distance setup */ return ttsp_write_block_data(ts, CY_REG_ACT_DIST, @@ -528,25 +532,82 @@ static void cyttsp_close(struct input_dev *dev) cyttsp_disable(ts); } -static void cyttsp_platform_exit(void *data) +static int cyttsp_parse_properties(struct cyttsp *ts) { - struct cyttsp *ts = data; + struct device *dev = ts->dev; + u32 dt_value; + int ret; + + ts->bl_keys = devm_kzalloc(dev, CY_NUM_BL_KEYS, GFP_KERNEL); + if (!ts->bl_keys) + return -ENOMEM; + + /* Set some default values */ + ts->use_hndshk = false; + ts->act_dist = CY_ACT_DIST_DFLT; + ts->act_intrvl = CY_ACT_INTRVL_DFLT; + ts->tch_tmout = CY_TCH_TMOUT_DFLT; + ts->lp_intrvl = CY_LP_INTRVL_DFLT; + + ret = device_property_read_u8_array(dev, "bootloader-key", + ts->bl_keys, CY_NUM_BL_KEYS); + if (ret) { + dev_err(dev, + "bootloader-key property could not be retrieved\n"); + return ret; + } + + ts->use_hndshk = device_property_present(dev, "use-handshake"); + + if (!device_property_read_u32(dev, "active-distance", &dt_value)) { + if (dt_value > 15) { + dev_err(dev, "active-distance (%u) must be [0-15]\n", + dt_value); + return -EINVAL; + } + ts->act_dist &= ~CY_ACT_DIST_MASK; + ts->act_dist |= dt_value; + } + + if (!device_property_read_u32(dev, "active-interval-ms", &dt_value)) { + if (dt_value > 255) { + dev_err(dev, "active-interval-ms (%u) must be [0-255]\n", + dt_value); + return -EINVAL; + } + ts->act_intrvl = dt_value; + } - if (ts->pdata->exit) - ts->pdata->exit(); + if (!device_property_read_u32(dev, "lowpower-interval-ms", &dt_value)) { + if (dt_value > 2550) { + dev_err(dev, "lowpower-interval-ms (%u) must be [0-2550]\n", + dt_value); + return -EINVAL; + } + /* Register value is expressed in 0.01s / bit */ + ts->lp_intrvl = dt_value / 10; + } + + if (!device_property_read_u32(dev, "touch-timeout-ms", &dt_value)) { + if (dt_value > 2550) { + dev_err(dev, "touch-timeout-ms (%u) must be [0-2550]\n", + dt_value); + return -EINVAL; + } + /* Register value is expressed in 0.01s / bit */ + ts->tch_tmout = dt_value / 10; + } + + return 0; } struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { - const struct cyttsp_platform_data *pdata = dev_get_platdata(dev); struct cyttsp *ts; struct input_dev *input_dev; int error; - if (!pdata || !pdata->name || irq <= 0) - return ERR_PTR(-EINVAL); - ts = devm_kzalloc(dev, sizeof(*ts) + xfer_buf_size, GFP_KERNEL); if (!ts) return ERR_PTR(-ENOMEM); @@ -557,29 +618,24 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->dev = dev; ts->input = input_dev; - ts->pdata = dev_get_platdata(dev); ts->bus_ops = bus_ops; ts->irq = irq; - init_completion(&ts->bl_ready); - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); - - error = devm_add_action(dev, cyttsp_platform_exit, ts); - if (error) { - dev_err(dev, "failed to install exit action: %d\n", error); + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(ts->reset_gpio)) { + error = PTR_ERR(ts->reset_gpio); + dev_err(dev, "Failed to request reset gpio, error %d\n", error); return ERR_PTR(error); } - if (pdata->init) { - error = pdata->init(); - if (error) { - dev_err(ts->dev, "platform init failed, err: %d\n", - error); - return ERR_PTR(error); - } - } + error = cyttsp_parse_properties(ts); + if (error) + return ERR_PTR(error); + + init_completion(&ts->bl_ready); + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); - input_dev->name = pdata->name; + input_dev->name = "Cypress TTSP TouchScreen"; input_dev->phys = ts->phys; input_dev->id.bustype = bus_ops->bustype; input_dev->dev.parent = ts->dev; @@ -589,13 +645,9 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, input_set_drvdata(input_dev, ts); - __set_bit(EV_ABS, input_dev->evbit); - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, pdata->maxx, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, pdata->maxy, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, - 0, CY_MAXZ, 0, 0); + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); + touchscreen_parse_properties(input_dev, true); error = input_mt_init_slots(input_dev, CY_MAX_ID, 0); if (error) { @@ -605,7 +657,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - pdata->name, ts); + "cyttsp", ts); if (error) { dev_err(ts->dev, "failed to request IRQ %d, err: %d\n", ts->irq, error); diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index c5e7afce6de8..7835e2bacf5a 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -129,7 +129,6 @@ struct cyttsp { int irq; struct input_dev *input; char phys[32]; - const struct cyttsp_platform_data *pdata; const struct cyttsp_bus_ops *bus_ops; struct cyttsp_bootloader_data bl_data; struct cyttsp_sysinfo_data sysinfo_data; @@ -138,6 +137,14 @@ struct cyttsp { enum cyttsp_state state; bool suspended; + struct gpio_desc *reset_gpio; + bool use_hndshk; + u8 act_dist; + u8 act_intrvl; + u8 tch_tmout; + u8 lp_intrvl; + u8 *bl_keys; + u8 xfer_buf[] ____cacheline_aligned; }; diff --git a/include/linux/input/cyttsp.h b/include/linux/input/cyttsp.h index 5af7c66f1fca..586c8c95dcb0 100644 --- a/include/linux/input/cyttsp.h +++ b/include/linux/input/cyttsp.h @@ -40,19 +40,4 @@ /* Active distance in pixels for a gesture to be reported */ #define CY_ACT_DIST_DFLT 0xF8 /* pixels */ -struct cyttsp_platform_data { - u32 maxx; - u32 maxy; - bool use_hndshk; - u8 act_dist; /* Active distance */ - u8 act_intrvl; /* Active refresh interval; ms */ - u8 tch_tmout; /* Active touch timeout; ms */ - u8 lp_intrvl; /* Low power refresh interval; ms */ - int (*init)(void); - void (*exit)(void); - char *name; - s16 irq_gpio; - u8 *bl_keys; -}; - #endif /* _CYTTSP_H_ */ -- cgit From 8fb81d20019db3dea4126e3eac7ef8dc89b10b9e Mon Sep 17 00:00:00 2001 From: Oreste Salerno Date: Wed, 27 Jan 2016 13:58:38 -0800 Subject: Input: cyttsp - perform hard reset of the chip during probe Since we removed support for calling an init() callback from the platform data, introduce a function which initializes the chip by performing a hard reset, using the reset gpio defined in the device properties. Signed-off-by: Oreste Salerno Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/cyttsp_core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 8814b6c87097..91cda8f8119d 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -240,6 +240,16 @@ static int cyttsp_set_sysinfo_regs(struct cyttsp *ts) return retval; } +static void cyttsp_hard_reset(struct cyttsp *ts) +{ + if (ts->reset_gpio) { + gpiod_set_value_cansleep(ts->reset_gpio, 1); + msleep(CY_DELAY_DFLT); + gpiod_set_value_cansleep(ts->reset_gpio, 0); + msleep(CY_DELAY_DFLT); + } +} + static int cyttsp_soft_reset(struct cyttsp *ts) { unsigned long timeout; @@ -666,6 +676,8 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, disable_irq(ts->irq); + cyttsp_hard_reset(ts); + error = cyttsp_power_on(ts); if (error) return ERR_PTR(error); -- cgit From 6aa56785e735fcfffffef7655f113b56f05c0df5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:50 -0800 Subject: staging: digi: Replace open-coded tty_wakeup() The open-coded tty_wakeup()s are attempts to workaround fixed bugs in the line discipline write_wakeup() method. Replace with tty_wakeup(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgap/dgap.c | 28 ++++++---------------------- drivers/staging/dgnc/dgnc_tty.c | 18 ++---------------- 2 files changed, 8 insertions(+), 38 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index bad355100825..dfbae215aec3 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -1665,9 +1665,7 @@ static void dgap_input(struct channel_t *ch) } static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, - struct un_t *un, u32 mask, - unsigned long *irq_flags1, - unsigned long *irq_flags2) + struct un_t *un, u32 mask) { if (!(un->un_flags & mask)) return; @@ -1677,17 +1675,7 @@ static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, if (!(un->un_flags & UN_ISOPEN)) return; - if ((un->un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - un->un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, *irq_flags2); - spin_unlock_irqrestore(&bd->bd_lock, *irq_flags1); - - (un->un_tty->ldisc->ops->write_wakeup)(un->un_tty); - - spin_lock_irqsave(&bd->bd_lock, *irq_flags1); - spin_lock_irqsave(&ch->ch_lock, *irq_flags2); - } - wake_up_interruptible(&un->un_tty->write_wait); + tty_wakeup(un->un_tty); wake_up_interruptible(&un->un_flags_wait); } @@ -1952,10 +1940,8 @@ static int dgap_event(struct board_t *bd) * Process Transmit low. */ if (reason & IFTLW) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW, - &lock_flags, &lock_flags2); + dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW); + dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW); if (ch->ch_flags & CH_WLOW) { ch->ch_flags &= ~CH_WLOW; wake_up_interruptible(&ch->ch_flags_wait); @@ -1966,10 +1952,8 @@ static int dgap_event(struct board_t *bd) * Process Transmit empty. */ if (reason & IFTEM) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY, - &lock_flags, &lock_flags2); + dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY); + dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY); if (ch->ch_flags & CH_WEMPTY) { ch->ch_flags &= ~CH_WEMPTY; wake_up_interruptible(&ch->ch_flags_wait); diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index b79eab084c02..4a3d2c6f7eac 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -933,14 +933,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) } if (ch->ch_tun.un_flags & UN_ISOPEN) { - if ((ch->ch_tun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->ch_tun.un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - ch->ch_tun.un_tty->ldisc->ops->write_wakeup(ch->ch_tun.un_tty); - spin_lock_irqsave(&ch->ch_lock, flags); - } - - wake_up_interruptible(&ch->ch_tun.un_tty->write_wait); + tty_wakeup(ch->ch_tun.un_tty); /* * If unit is set to wait until empty, check to make sure @@ -975,14 +968,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) } if (ch->ch_pun.un_flags & UN_ISOPEN) { - if ((ch->ch_pun.un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - ch->ch_pun.un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - ch->ch_pun.un_tty->ldisc->ops->write_wakeup(ch->ch_pun.un_tty); - spin_lock_irqsave(&ch->ch_lock, flags); - } - - wake_up_interruptible(&ch->ch_pun.un_tty->write_wait); + tty_wakeup(ch->ch_pun.un_tty); /* * If unit is set to wait until empty, check to make sure -- cgit From 46b94e779e8a53b83e8d84e5aeb443d8b8bd45ea Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:51 -0800 Subject: serial: 68328: Remove bogus ldisc reset As the #warning indicates, the open-coded ldisc reset was always not ok. Not only is this code long dead, but now it would have no effect as the ldisc is destroyed when this driver's close() method returns; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/68328serial.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 0982c1a44187..90639b590a10 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1054,17 +1054,7 @@ static void rs_close(struct tty_struct *tty, struct file *filp) tty_ldisc_flush(tty); tty->closing = 0; tty_port_tty_set(&info->tport, NULL); -#warning "This is not and has never been valid so fix it" -#if 0 - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios.c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } -#endif + if (port->blocked_open) { if (port->close_delay) msleep_interruptible(jiffies_to_msecs(port->close_delay)); -- cgit From 582e20a03b9bcbddaeaffb38800323ddcc4a9173 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:53 -0800 Subject: NFC: nci: Remove dead code The N_NCI ldisc does not define a flush_buffer() ldisc method, so the check when opening the ldisc is always false. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- net/nfc/nci/uart.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/net/nfc/nci/uart.c b/net/nfc/nci/uart.c index 21d8875673a4..c468eabd6943 100644 --- a/net/nfc/nci/uart.c +++ b/net/nfc/nci/uart.c @@ -171,14 +171,7 @@ static int nci_uart_tty_open(struct tty_struct *tty) tty->disc_data = NULL; tty->receive_room = 65536; - /* Flush any pending characters in the driver and line discipline. */ - - /* FIXME: why is this needed. Note don't use ldisc_ref here as the - * open path is before the ldisc is referencable. - */ - - if (tty->ldisc->ops->flush_buffer) - tty->ldisc->ops->flush_buffer(tty); + /* Flush any pending characters in the driver */ tty_driver_flush_buffer(tty); return 0; -- cgit From fdfb719e93b55a50f90da2059dc450e7c0c48e8f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:54 -0800 Subject: tty: Remove chars_in_buffer() line discipline method The chars_in_buffer() line discipline method serves no functional purpose, other than as a (dubious) debugging aid for mostly bit-rotting drivers. Despite being documented as an optional method, every caller is unconditionally executed (although conditionally compiled). Furthermore, direct tty->ldisc access without an ldisc ref is unsafe. Lastly, N_TTY's chars_in_buffer() has warned of removal since 3.12. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- Documentation/serial/tty.txt | 3 --- drivers/tty/amiserial.c | 6 ++---- drivers/tty/cyclades.c | 8 ++++---- drivers/tty/n_gsm.c | 16 ---------------- drivers/tty/n_tty.c | 23 ----------------------- drivers/tty/rocket.c | 6 ++---- drivers/tty/serial/crisv10.c | 12 +++++------- include/linux/tty_ldisc.h | 7 ------- 8 files changed, 13 insertions(+), 68 deletions(-) diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt index bc3842dc323a..798cba82c762 100644 --- a/Documentation/serial/tty.txt +++ b/Documentation/serial/tty.txt @@ -72,9 +72,6 @@ flush_buffer() - (optional) May be called at any point between open and close, and instructs the line discipline to empty its input buffer. -chars_in_buffer() - (optional) Report the number of bytes in the input - buffer. - set_termios() - (optional) Called on termios structure changes. The caller passes the old termios data and the current data is in the tty. Called under the diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 2caaf5a2516d..6ba5681b6385 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -965,8 +965,7 @@ static void rs_throttle(struct tty_struct * tty) struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s: %d....\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s ....\n", tty_name(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_throttle")) @@ -988,8 +987,7 @@ static void rs_unthrottle(struct tty_struct * tty) struct serial_state *info = tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %d....\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s ....\n", tty_name(tty)); #endif if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index abbed201dc74..a48e7e66b970 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -2852,8 +2852,8 @@ static void cy_throttle(struct tty_struct *tty) unsigned long flags; #ifdef CY_DEBUG_THROTTLE - printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty), - tty->ldisc.chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:throttle %s ...ttyC%d\n", tty_name(tty), + info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_throttle")) @@ -2891,8 +2891,8 @@ static void cy_unthrottle(struct tty_struct *tty) unsigned long flags; #ifdef CY_DEBUG_THROTTLE - printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", - tty_name(tty), tty_chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:unthrottle %s ...ttyC%d\n", + tty_name(tty), info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c3fe026d3168..e3cc27749344 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2303,21 +2303,6 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, /* If clogged call tty_throttle(tty); */ } -/** - * gsmld_chars_in_buffer - report available bytes - * @tty: tty device - * - * Report the number of characters buffered to be delivered to user - * at this instant in time. - * - * Locking: gsm lock - */ - -static ssize_t gsmld_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - /** * gsmld_flush_buffer - clean input queue * @tty: terminal device @@ -2830,7 +2815,6 @@ static struct tty_ldisc_ops tty_ldisc_packet = { .open = gsmld_open, .close = gsmld_close, .flush_buffer = gsmld_flush_buffer, - .chars_in_buffer = gsmld_chars_in_buffer, .read = gsmld_read, .write = gsmld_write, .ioctl = gsmld_ioctl, diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b280abaad91b..90eca2605fbf 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -380,28 +380,6 @@ static void n_tty_flush_buffer(struct tty_struct *tty) up_write(&tty->termios_rwsem); } -/** - * n_tty_chars_in_buffer - report available bytes - * @tty: tty device - * - * Report the number of characters buffered to be delivered to user - * at this instant in time. - * - * Locking: exclusive termios_rwsem - */ - -static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) -{ - ssize_t n; - - WARN_ONCE(1, "%s is deprecated and scheduled for removal.", __func__); - - down_write(&tty->termios_rwsem); - n = chars_in_buffer(tty); - up_write(&tty->termios_rwsem); - return n; -} - /** * is_utf8_continuation - utf8 multibyte check * @c: byte to check @@ -2525,7 +2503,6 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { .open = n_tty_open, .close = n_tty_close, .flush_buffer = n_tty_flush_buffer, - .chars_in_buffer = n_tty_chars_in_buffer, .read = n_tty_read, .write = n_tty_write, .ioctl = n_tty_ioctl, diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 802eac7e561b..f624b93a237f 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1360,8 +1360,7 @@ static void rp_throttle(struct tty_struct *tty) struct r_port *info = tty->driver_data; #ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "throttle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); + printk(KERN_INFO "throttle %s ....\n", tty->name); #endif if (rocket_paranoia_check(info, "rp_throttle")) @@ -1377,8 +1376,7 @@ static void rp_unthrottle(struct tty_struct *tty) { struct r_port *info = tty->driver_data; #ifdef ROCKET_DEBUG_THROTTLE - printk(KERN_INFO "unthrottle %s: %d....\n", tty->name, - tty->ldisc.chars_in_buffer(tty)); + printk(KERN_INFO "unthrottle %s ....\n", tty->name); #endif if (rocket_paranoia_check(info, "rp_unthrottle")) diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index f13f2ebd215b..e98aef797065 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -2968,7 +2968,7 @@ static int rs_raw_write(struct tty_struct *tty, local_save_flags(flags); DFLOW(DEBUG_LOG(info->line, "write count %i ", count)); - DFLOW(DEBUG_LOG(info->line, "ldisc %i\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line, "ldisc\n")); /* The local_irq_disable/restore_flags pairs below are needed @@ -3161,10 +3161,9 @@ rs_throttle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %s: %lu....\n", tty_name(tty), - (unsigned long)tty->ldisc.chars_in_buffer(tty)); + printk("throttle %s ....\n", tty_name(tty)); #endif - DFLOW(DEBUG_LOG(info->line,"rs_throttle %lu\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_throttle\n")); /* Do RTS before XOFF since XOFF might take some time */ if (tty->termios.c_cflag & CRTSCTS) { @@ -3181,10 +3180,9 @@ rs_unthrottle(struct tty_struct * tty) { struct e100_serial *info = (struct e100_serial *)tty->driver_data; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %lu....\n", tty_name(tty), - (unsigned long)tty->ldisc.chars_in_buffer(tty)); + printk("unthrottle %s ....\n", tty_name(tty)); #endif - DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc %d\n", tty->ldisc.chars_in_buffer(tty))); + DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc\n")); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ if (tty->termios.c_cflag & CRTSCTS) { diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 00c9d688d7b7..6101ab8dc148 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -25,12 +25,6 @@ * buffers of any input characters it may have queued to be * delivered to the user mode process. * - * ssize_t (*chars_in_buffer)(struct tty_struct *tty); - * - * This function returns the number of input characters the line - * discipline may have queued up to be delivered to the user mode - * process. - * * ssize_t (*read)(struct tty_struct * tty, struct file * file, * unsigned char * buf, size_t nr); * @@ -188,7 +182,6 @@ struct tty_ldisc_ops { int (*open)(struct tty_struct *); void (*close)(struct tty_struct *); void (*flush_buffer)(struct tty_struct *tty); - ssize_t (*chars_in_buffer)(struct tty_struct *tty); ssize_t (*read)(struct tty_struct *tty, struct file *file, unsigned char __user *buf, size_t nr); ssize_t (*write)(struct tty_struct *tty, struct file *file, -- cgit From ece53405a1f8ddf60b78e1365addcad521b2c93f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:57 -0800 Subject: tty: Reset c_line from driver's init_termios After the ldisc is released, but before the tty is destroyed, the termios is saved (in tty_free_termios()); this termios is restored if a new tty is created on next open(). However, the line discipline is always reset, which is not obvious in the current method. Instead, reset as part of the restore. Restore the original line discipline, which may not have been N_TTY. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 5 +++-- drivers/tty/tty_ldisc.c | 3 --- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 524703a7df2b..71a9409c8d7e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1387,9 +1387,10 @@ void tty_init_termios(struct tty_struct *tty) else { /* Check for lazy saved data */ tp = tty->driver->termios[idx]; - if (tp != NULL) + if (tp != NULL) { tty->termios = *tp; - else + tty->termios.c_line = tty->driver->init_termios.c_line; + } else tty->termios = tty->driver->init_termios; } /* Compatibility until drivers always set this */ diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 713cc2d48846..b2e8210639dd 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -743,9 +743,6 @@ static void tty_ldisc_kill(struct tty_struct *tty) tty_ldisc_put(tty->ldisc); /* Force an oops if we mess this up */ tty->ldisc = NULL; - - /* Ensure the next open requests the N_TTY ldisc */ - tty_set_termios_ldisc(tty, N_TTY); } /** -- cgit From c0cc1c5d6b67289ea2e77346e0161506b0d4f393 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:40:59 -0800 Subject: tty: Fix comments for tty_ldisc_get() tty_ldisc_get() returns ERR_PTR() values if unsuccessful, not NULL; fix function header documentation. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index b2e8210639dd..4008f5f65345 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -140,9 +140,16 @@ static void put_ldops(struct tty_ldisc_ops *ldops) * @disc: ldisc number * * Takes a reference to a line discipline. Deals with refcounts and - * module locking counts. Returns NULL if the discipline is not available. - * Returns a pointer to the discipline and bumps the ref count if it is - * available + * module locking counts. + * + * Returns: -EINVAL if the discipline index is not [N_TTY..NR_LDISCS] or + * if the discipline is not registered + * -EAGAIN if request_module() failed to load or register the + * the discipline + * -ENOMEM if allocation failure + * + * Otherwise, returns a pointer to the discipline and bumps the + * ref count * * Locking: * takes tty_ldiscs_lock to guard against ldisc races -- cgit From 5b6e6832f41c9422753804671ee06af37ac8caf6 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:00 -0800 Subject: tty: Fix comments for tty_ldisc_release() tty_ldisc_kill() sets tty->ldisc to NULL; _not_ to N_TTY with a valid but unopened ldisc. Fix function header documentation. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 4008f5f65345..14d2165ba270 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -757,8 +757,7 @@ static void tty_ldisc_kill(struct tty_struct *tty) * @tty: tty being shut down (or one end of pty pair) * * Called during the final close of a tty or a pty pair in order to shut - * down the line discpline layer. On exit, each ldisc assigned is N_TTY and - * each ldisc has not been opened. + * down the line discpline layer. On exit, each tty's ldisc is NULL. */ void tty_ldisc_release(struct tty_struct *tty) -- cgit From e55afd11a48354c810caf6b6ad4c103016a88230 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:01 -0800 Subject: tty: Prepare for destroying line discipline on hangup tty file_operations (read/write/ioctl) wait for the ldisc reference indefinitely (until ldisc lifetime events, such as hangup or TIOCSETD, finish). Since hangup now destroys the ldisc and does not instance another copy, file_operations must now be prepared to receive a NULL ldisc reference from tty_ldisc_ref_wait(): CPU 0 CPU 1 ----- ----- (*f_op->read)() => tty_read() __tty_hangup() ... f_op = &hung_up_tty_fops; ... tty_ldisc_hangup() tty_ldisc_lock() tty_ldisc_kill() tty->ldisc = NULL tty_ldisc_unlock() ld = tty_ldisc_ref_wait() /* ld == NULL */ Instead, the action taken now is to return the same value as if the tty had been hungup a moment earlier: CPU 0 CPU 1 ----- ----- __tty_hangup() ... f_op = &hung_up_tty_fops; (*f_op->read)() => hung_up_tty_read() return 0; ... tty_ldisc_hangup() tty_ldisc_lock() tty_ldisc_kill() tty->ldisc = NULL tty_ldisc_unlock() Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 14 ++++++++++++++ drivers/tty/tty_ldisc.c | 4 ++-- drivers/tty/vt/selection.c | 2 ++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 71a9409c8d7e..eb26754b2e5d 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1068,6 +1068,8 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, /* We want to wait for the line discipline to sort out in this situation */ ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_read(file, buf, count, ppos); if (ld->ops->read) i = ld->ops->read(tty, file, buf, count); else @@ -1242,6 +1244,8 @@ static ssize_t tty_write(struct file *file, const char __user *buf, if (tty->ops->write_room == NULL) tty_err(tty, "missing write_room method\n"); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_write(file, buf, count, ppos); if (!ld->ops->write) ret = -EIO; else @@ -2201,6 +2205,8 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) return 0; ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_poll(filp, wait); if (ld->ops->poll) ret = ld->ops->poll(tty, filp, wait); tty_ldisc_deref(ld); @@ -2290,6 +2296,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p) return -EFAULT; tty_audit_tiocsti(tty, ch); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; ld->ops->receive_buf(tty, &ch, &mbz, 1); tty_ldisc_deref(ld); return 0; @@ -2682,6 +2690,8 @@ static int tiocgetd(struct tty_struct *tty, int __user *p) int ret; ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; ret = put_user(ld->ops->num, p); tty_ldisc_deref(ld); return ret; @@ -2979,6 +2989,8 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return retval; } ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_ioctl(file, cmd, arg); retval = -EINVAL; if (ld->ops->ioctl) { retval = ld->ops->ioctl(tty, file, cmd, arg); @@ -3007,6 +3019,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, } ld = tty_ldisc_ref_wait(tty); + if (!ld) + return hung_up_tty_compat_ioctl(file, cmd, arg); if (ld->ops->compat_ioctl) retval = ld->ops->compat_ioctl(tty, file, cmd, arg); else diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 14d2165ba270..d6805e1aee59 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -262,8 +262,8 @@ const struct file_operations tty_ldiscs_proc_fops = { * against a discipline change, such as an existing ldisc reference * (which we check for) * - * Note: only callable from a file_operations routine (which - * guarantees tty->ldisc != NULL when the lock is acquired). + * Note: a file_operations routine (read/poll/write) should use this + * function to wait for any ldisc lifetime events to finish. */ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 381a2b13682c..4dd9dd2270a0 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -347,6 +347,8 @@ int paste_selection(struct tty_struct *tty) console_unlock(); ld = tty_ldisc_ref_wait(tty); + if (!ld) + return -EIO; /* ldisc was hung up */ tty_buffer_lock_exclusive(&vc->port); add_wait_queue(&vc->paste_wait, &wait); -- cgit From a570a49abd343102ce681bbf8273897c3c9fd2d1 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:02 -0800 Subject: tty: Handle NULL tty->ldisc In preparation of destroying line discipline on hangup, fix ldisc core operations to properly handle when the tty's ldisc is NULL. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index d6805e1aee59..982af70c95ce 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -269,7 +269,8 @@ const struct file_operations tty_ldiscs_proc_fops = { struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) { ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT); - WARN_ON(!tty->ldisc); + if (!tty->ldisc) + ldsem_up_read(&tty->ldisc_sem); return tty->ldisc; } EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); @@ -460,7 +461,7 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) if (ret) clear_bit(TTY_LDISC_OPEN, &tty->flags); - tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: opened\n", ld); return ret; } return 0; @@ -481,7 +482,7 @@ static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) clear_bit(TTY_LDISC_OPEN, &tty->flags); if (ld->ops->close) ld->ops->close(tty); - tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: closed\n", ld); } /** @@ -544,6 +545,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (retval) goto err; + if (!tty->ldisc) { + retval = -EIO; + goto out; + } + /* Check the no-op case */ if (tty->ldisc->ops->num == ldisc) goto out; @@ -659,7 +665,7 @@ void tty_ldisc_hangup(struct tty_struct *tty) int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; int err = 0; - tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc); + tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc); ld = tty_ldisc_ref(tty); if (ld != NULL) { @@ -743,6 +749,8 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) static void tty_ldisc_kill(struct tty_struct *tty) { + if (!tty->ldisc) + return; /* * Now kill off the ldisc */ -- cgit From 6ffeb4b2782b31f3d7158795a451ad371955e8a2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:03 -0800 Subject: tty: Move tty_ldisc_kill() In preparation for destroying the line discipline instance on hangup, move tty_ldisc_kill() to eliminate needless forward declarations. No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 982af70c95ce..eac33e104ccc 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -600,6 +600,25 @@ err: return retval; } +/** + * tty_ldisc_kill - teardown ldisc + * @tty: tty being released + * + * Perform final close of the ldisc and reset tty->ldisc + */ +static void tty_ldisc_kill(struct tty_struct *tty) +{ + if (!tty->ldisc) + return; + /* + * Now kill off the ldisc + */ + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + /* Force an oops if we mess this up */ + tty->ldisc = NULL; +} + /** * tty_reset_termios - reset terminal state * @tty: tty to reset @@ -747,19 +766,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) return 0; } -static void tty_ldisc_kill(struct tty_struct *tty) -{ - if (!tty->ldisc) - return; - /* - * Now kill off the ldisc - */ - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* Force an oops if we mess this up */ - tty->ldisc = NULL; -} - /** * tty_ldisc_release - release line discipline * @tty: tty being shut down (or one end of pty pair) -- cgit From c12da96f801a3f45b0634c966b9e7cda307daa72 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:04 -0800 Subject: tty: Use 'disc' for line discipline index name tty->ldisc is a ptr to struct tty_ldisc, but unfortunately 'ldisc' is also used as a parameter or local name to refer to the line discipline index value (ie, N_TTY, N_GSM, etc.); instead prefer the name used by the line discipline registration/ref counting functions. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 6 +++--- drivers/tty/tty_ldisc.c | 22 +++++++++++----------- include/linux/tty.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index eb26754b2e5d..7f556e3c1515 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2662,13 +2662,13 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ static int tiocsetd(struct tty_struct *tty, int __user *p) { - int ldisc; + int disc; int ret; - if (get_user(ldisc, p)) + if (get_user(disc, p)) return -EFAULT; - ret = tty_set_ldisc(tty, ldisc); + ret = tty_set_ldisc(tty, disc); return ret; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index eac33e104ccc..45aa31b923e5 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); /** * tty_set_termios_ldisc - set ldisc field * @tty: tty structure - * @num: line discipline number + * @disc: line discipline number * * This is probably overkill for real world processors but * they are not on hot paths so a little discipline won't do @@ -430,10 +430,10 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); * Locking: takes termios_rwsem */ -static void tty_set_termios_ldisc(struct tty_struct *tty, int num) +static void tty_set_termios_ldisc(struct tty_struct *tty, int disc) { down_write(&tty->termios_rwsem); - tty->termios.c_line = num; + tty->termios.c_line = disc; up_write(&tty->termios_rwsem); tty->disc_data = NULL; @@ -531,12 +531,12 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) * the close of one side of a tty/pty pair, and eventually hangup. */ -int tty_set_ldisc(struct tty_struct *tty, int ldisc) +int tty_set_ldisc(struct tty_struct *tty, int disc) { int retval; struct tty_ldisc *old_ldisc, *new_ldisc; - new_ldisc = tty_ldisc_get(tty, ldisc); + new_ldisc = tty_ldisc_get(tty, disc); if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); @@ -551,7 +551,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) } /* Check the no-op case */ - if (tty->ldisc->ops->num == ldisc) + if (tty->ldisc->ops->num == disc) goto out; if (test_bit(TTY_HUPPED, &tty->flags)) { @@ -567,7 +567,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) /* Now set up the new line discipline. */ tty->ldisc = new_ldisc; - tty_set_termios_ldisc(tty, ldisc); + tty_set_termios_ldisc(tty, disc); retval = tty_ldisc_open(tty, new_ldisc); if (retval < 0) { @@ -639,15 +639,15 @@ static void tty_reset_termios(struct tty_struct *tty) /** * tty_ldisc_reinit - reinitialise the tty ldisc * @tty: tty to reinit - * @ldisc: line discipline to reinitialize + * @disc: line discipline to reinitialize * * Switch the tty to a line discipline and leave the ldisc * state closed */ -static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) +static int tty_ldisc_reinit(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc); + struct tty_ldisc *ld = tty_ldisc_get(tty, disc); if (IS_ERR(ld)) return -1; @@ -658,7 +658,7 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) * Switch the line discipline back */ tty->ldisc = ld; - tty_set_termios_ldisc(tty, ldisc); + tty_set_termios_ldisc(tty, disc); return 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index 83f127673bc9..e3b0afbde7b9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -570,7 +570,7 @@ static inline int tty_port_users(struct tty_port *port) extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); extern int tty_unregister_ldisc(int disc); -extern int tty_set_ldisc(struct tty_struct *tty, int ldisc); +extern int tty_set_ldisc(struct tty_struct *tty, int disc); extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); -- cgit From 7896f30d6fc602f02198999acca4840620288990 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:05 -0800 Subject: tty: Refactor tty_ldisc_reinit() for reuse At tty hangup, the line discipline instance is reinitialized by closing the current ldisc instance and opening a new instance. This operation is complicated by error recovery: if the attempt to reinit the current line discipline fails, the line discipline is reset to N_TTY (which should not but can fail). Re-purpose tty_ldisc_reinit() to return a valid, open line discipline instance, or otherwise, an error. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 53 +++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 45aa31b923e5..e18c8e864110 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -641,26 +641,41 @@ static void tty_reset_termios(struct tty_struct *tty) * @tty: tty to reinit * @disc: line discipline to reinitialize * - * Switch the tty to a line discipline and leave the ldisc - * state closed + * Completely reinitialize the line discipline state, by closing the + * current instance and opening a new instance. If an error occurs opening + * the new non-N_TTY instance, the instance is dropped and tty->ldisc reset + * to NULL. The caller can then retry with N_TTY instead. + * + * Returns 0 if successful, otherwise error code < 0 */ static int tty_ldisc_reinit(struct tty_struct *tty, int disc) { - struct tty_ldisc *ld = tty_ldisc_get(tty, disc); + struct tty_ldisc *ld; + int retval; - if (IS_ERR(ld)) - return -1; + ld = tty_ldisc_get(tty, disc); + if (IS_ERR(ld)) { + BUG_ON(disc == N_TTY); + return PTR_ERR(ld); + } - tty_ldisc_close(tty, tty->ldisc); - tty_ldisc_put(tty->ldisc); - /* - * Switch the line discipline back - */ + if (tty->ldisc) { + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); + } + + /* switch the line discipline */ tty->ldisc = ld; tty_set_termios_ldisc(tty, disc); - - return 0; + retval = tty_ldisc_open(tty, tty->ldisc); + if (retval) { + if (!WARN_ON(disc == N_TTY)) { + tty_ldisc_put(tty->ldisc); + tty->ldisc = NULL; + } + } + return retval; } /** @@ -716,19 +731,13 @@ void tty_ldisc_hangup(struct tty_struct *tty) reopen a new ldisc. We could defer the reopen to the next open but it means auditing a lot of other paths so this is a FIXME */ - if (reset == 0) { + if (reset == 0) + err = tty_ldisc_reinit(tty, tty->termios.c_line); - if (!tty_ldisc_reinit(tty, tty->termios.c_line)) - err = tty_ldisc_open(tty, tty->ldisc); - else - err = 1; - } /* If the re-open fails or we reset then go to N_TTY. The N_TTY open cannot fail */ - if (reset || err) { - BUG_ON(tty_ldisc_reinit(tty, N_TTY)); - WARN_ON(tty_ldisc_open(tty, tty->ldisc)); - } + if (reset || err < 0) + tty_ldisc_reinit(tty, N_TTY); } tty_ldisc_unlock(tty); if (reset) -- cgit From 892d1fa7eaaed9d3c04954cb140c34ebc3393932 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:06 -0800 Subject: tty: Destroy ldisc instance on hangup Currently, when the tty is hungup, the ldisc is re-instanced; ie., the current instance is destroyed and a new instance is created. The purpose of this design was to guarantee a valid, open ldisc for the lifetime of the tty. However, now that tty buffers are owned by and have lifetime equivalent to the tty_port (since v3.10), any data received immediately after the ldisc is re-instanced may cause continued driver i/o operations concurrently with the driver's hangup() operation. For drivers that shutdown h/w on hangup, this is unexpected and usually bad. For example, the serial core may free the xmit buffer page concurrently with an in-progress write() operation (triggered by echo). With the existing stable and robust ldisc reference handling, the cleaned-up tty_reopen(), the straggling unsafe ldisc use cleaned up, and the preparation to properly handle a NULL tty->ldisc, the ldisc instance can be destroyed and only re-instanced when the tty is re-opened. If the tty was opened as /dev/console or /dev/tty0, the original behavior of re-instancing the ldisc is retained (the 'reinit' parameter to tty_ldisc_hangup() is true). This is required since those file descriptors are never hungup. This patch has neglible impact on userspace; the tty file_operations ptr is changed to point to the hungup file operations _before_ the ldisc instance is destroyed, so only racing file operations might now retrieve a NULL ldisc reference (which is simply handled as if the hungup file operation had been called instead -- see "tty: Prepare for destroying line discipline on hangup"). This resolves a long-standing FIXME and several crash reports. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 12 ++++++------ drivers/tty/tty_ldisc.c | 40 +++++++++++++++++----------------------- include/linux/tty.h | 3 ++- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 7f556e3c1515..d3ecbb513fa1 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -727,7 +727,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) while (refs--) tty_kref_put(tty); - tty_ldisc_hangup(tty); + tty_ldisc_hangup(tty, cons_filp != NULL); spin_lock_irq(&tty->ctrl_lock); clear_bit(TTY_THROTTLED, &tty->flags); @@ -752,10 +752,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) } else if (tty->ops->hangup) tty->ops->hangup(tty); /* - * We don't want to have driver/ldisc interactions beyond - * the ones we did here. The driver layer expects no - * calls after ->hangup() from the ldisc side. However we - * can't yet guarantee all that. + * We don't want to have driver/ldisc interactions beyond the ones + * we did here. The driver layer expects no calls after ->hangup() + * from the ldisc side, which is now guaranteed. */ set_bit(TTY_HUPPED, &tty->flags); tty_unlock(tty); @@ -1475,7 +1474,8 @@ static int tty_reopen(struct tty_struct *tty) tty->count++; - WARN_ON(!tty->ldisc); + if (!tty->ldisc) + return tty_ldisc_reinit(tty, tty->termios.c_line); return 0; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index e18c8e864110..c6f970d63060 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -257,6 +257,9 @@ const struct file_operations tty_ldiscs_proc_fops = { * reference to it. If the line discipline is in flux then * wait patiently until it changes. * + * Returns: NULL if the tty has been hungup and not re-opened with + * a new file descriptor, otherwise valid ldisc reference + * * Note: Must not be called from an IRQ/timer context. The caller * must also be careful not to hold other locks that will deadlock * against a discipline change, such as an existing ldisc reference @@ -642,14 +645,15 @@ static void tty_reset_termios(struct tty_struct *tty) * @disc: line discipline to reinitialize * * Completely reinitialize the line discipline state, by closing the - * current instance and opening a new instance. If an error occurs opening - * the new non-N_TTY instance, the instance is dropped and tty->ldisc reset - * to NULL. The caller can then retry with N_TTY instead. + * current instance, if there is one, and opening a new instance. If + * an error occurs opening the new non-N_TTY instance, the instance + * is dropped and tty->ldisc reset to NULL. The caller can then retry + * with N_TTY instead. * * Returns 0 if successful, otherwise error code < 0 */ -static int tty_ldisc_reinit(struct tty_struct *tty, int disc) +int tty_ldisc_reinit(struct tty_struct *tty, int disc) { struct tty_ldisc *ld; int retval; @@ -693,11 +697,9 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int disc) * tty itself so we must be careful about locking rules. */ -void tty_ldisc_hangup(struct tty_struct *tty) +void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) { struct tty_ldisc *ld; - int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS; - int err = 0; tty_ldisc_debug(tty, "%p: hangup\n", tty->ldisc); @@ -725,25 +727,17 @@ void tty_ldisc_hangup(struct tty_struct *tty) */ tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT); - if (tty->ldisc) { + if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) + tty_reset_termios(tty); - /* At this point we have a halted ldisc; we want to close it and - reopen a new ldisc. We could defer the reopen to the next - open but it means auditing a lot of other paths so this is - a FIXME */ - if (reset == 0) - err = tty_ldisc_reinit(tty, tty->termios.c_line); - - /* If the re-open fails or we reset then go to N_TTY. The - N_TTY open cannot fail */ - if (reset || err < 0) - tty_ldisc_reinit(tty, N_TTY); + if (tty->ldisc) { + if (reinit) { + if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0) + tty_ldisc_reinit(tty, N_TTY); + } else + tty_ldisc_kill(tty); } tty_ldisc_unlock(tty); - if (reset) - tty_reset_termios(tty); - - tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc); } /** diff --git a/include/linux/tty.h b/include/linux/tty.h index e3b0afbde7b9..95e52c6b9696 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -490,7 +490,8 @@ extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt); extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *); extern void tty_ldisc_deref(struct tty_ldisc *); extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *); -extern void tty_ldisc_hangup(struct tty_struct *tty); +extern void tty_ldisc_hangup(struct tty_struct *tty, bool reset); +extern int tty_ldisc_reinit(struct tty_struct *tty, int disc); extern const struct file_operations tty_ldiscs_proc_fops; extern void tty_wakeup(struct tty_struct *tty); -- cgit From 133b1306f2068b124a4a00f537896a16786cc544 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:07 -0800 Subject: tty: Document c_line == N_TTY initial condition The line discipline id is stored in the tty's termios; document the implicit initial value of N_TTY. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d3ecbb513fa1..3c90ad44b585 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -123,7 +123,8 @@ struct ktermios tty_std_termios = { /* for the benefit of tty drivers */ ECHOCTL | ECHOKE | IEXTEN, .c_cc = INIT_C_CC, .c_ispeed = 38400, - .c_ospeed = 38400 + .c_ospeed = 38400, + /* .c_line = N_TTY, */ }; EXPORT_SYMBOL(tty_std_termios); -- cgit From 9de2a7cef983579c725564950384e4ea205a7684 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 22:41:08 -0800 Subject: tty: Avoid unnecessary temporaries for tty->ldisc tty_ldisc_setup() is race-free and can reference tty->ldisc without snapshots. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index c6f970d63060..4cb5e572c7b8 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -752,17 +752,14 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) { - struct tty_ldisc *ld = tty->ldisc; - int retval; - - retval = tty_ldisc_open(tty, ld); + int retval = tty_ldisc_open(tty, tty->ldisc); if (retval) return retval; if (o_tty) { retval = tty_ldisc_open(o_tty, o_tty->ldisc); if (retval) { - tty_ldisc_close(tty, ld); + tty_ldisc_close(tty, tty->ldisc); return retval; } } -- cgit From d1d027eff5693c3cea71e4ce2f1c3a707baec02d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:18 -0800 Subject: tty: Unexport system-wide tty_mutex tty_mutex is a core, system-wide lock; there is no reason for any code outside the tty core to have direct access. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 3c90ad44b585..cb0a0c82279b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -135,10 +135,8 @@ EXPORT_SYMBOL(tty_std_termios); LIST_HEAD(tty_drivers); /* linked list of tty drivers */ -/* Mutex to protect creating and releasing a tty. This is shared with - vt.c for deeply disgusting hack reasons */ +/* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex); -EXPORT_SYMBOL(tty_mutex); /* Spinlock to protect the tty->tty_files list */ DEFINE_SPINLOCK(tty_files_lock); -- cgit From 27228732aa94f3883433fab2f43eee373c638f2f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:19 -0800 Subject: tty: Eliminate global symbol tty_ldisc_N_TTY Reduce global tty symbols; move and rename tty_ldisc_begin() as n_tty_init() and redefine the N_TTY ldisc ops as file scope. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 12 ++++++++---- drivers/tty/tty_io.c | 2 +- drivers/tty/tty_ldisc.c | 6 ------ include/linux/tty.h | 3 +-- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 90eca2605fbf..dae628f19912 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2497,7 +2497,7 @@ static void n_tty_fasync(struct tty_struct *tty, int on) } } -struct tty_ldisc_ops tty_ldisc_N_TTY = { +static struct tty_ldisc_ops n_tty_ops = { .magic = TTY_LDISC_MAGIC, .name = "n_tty", .open = n_tty_open, @@ -2518,14 +2518,18 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { * n_tty_inherit_ops - inherit N_TTY methods * @ops: struct tty_ldisc_ops where to save N_TTY methods * - * Enables a 'subclass' line discipline to 'inherit' N_TTY - * methods. + * Enables a 'subclass' line discipline to 'inherit' N_TTY methods. */ void n_tty_inherit_ops(struct tty_ldisc_ops *ops) { - *ops = tty_ldisc_N_TTY; + *ops = n_tty_ops; ops->owner = NULL; ops->refcount = ops->flags = 0; } EXPORT_SYMBOL_GPL(n_tty_inherit_ops); + +void __init n_tty_init(void) +{ + tty_register_ldisc(N_TTY, &n_tty_ops); +} diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index cb0a0c82279b..798acb690092 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3576,7 +3576,7 @@ void __init console_init(void) initcall_t *call; /* Setup the default TTY line discipline. */ - tty_ldisc_begin(); + n_tty_init(); /* * set up the console device so that later boot sequences can diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 4cb5e572c7b8..68947f6de5ad 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -824,9 +824,3 @@ void tty_ldisc_deinit(struct tty_struct *tty) tty_ldisc_put(tty->ldisc); tty->ldisc = NULL; } - -void tty_ldisc_begin(void) -{ - /* Setup the default TTY line discipline. */ - (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); -} diff --git a/include/linux/tty.h b/include/linux/tty.h index 95e52c6b9696..f6c07fd12ef4 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -576,7 +576,6 @@ extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); -extern void tty_ldisc_begin(void); static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, char *f, int count) @@ -593,8 +592,8 @@ static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, /* n_tty.c */ -extern struct tty_ldisc_ops tty_ldisc_N_TTY; extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops); +extern void __init n_tty_init(void); /* tty_audit.c */ #ifdef CONFIG_AUDIT -- cgit From de5583d670a8b10f157fdcc7afaddfd1ec423a69 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:20 -0800 Subject: tty: Remove declarations to non-existent functions tty_read_raw_data() and tty_signal() no longer exist; remove declarations. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/linux/tty.h b/include/linux/tty.h index f6c07fd12ef4..26a9b4b3efe9 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -433,8 +433,6 @@ extern struct device *tty_register_device_attr(struct tty_driver *driver, void *drvdata, const struct attribute_group **attr_grp); extern void tty_unregister_device(struct tty_driver *driver, unsigned index); -extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, - int buflen); extern void tty_write_message(struct tty_struct *tty, char *msg); extern int tty_send_xchar(struct tty_struct *tty, char ch); extern int tty_put_char(struct tty_struct *tty, unsigned char c); @@ -448,7 +446,6 @@ extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); extern int is_current_pgrp_orphaned(void); extern int is_ignored(int sig); -extern int tty_signal(int sig, struct tty_struct *tty); extern void tty_hangup(struct tty_struct *tty); extern void tty_vhangup(struct tty_struct *tty); extern int tty_hung_up_p(struct file *filp); -- cgit From e802ca0e1892865acdde90f1aaed37333c5660c2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:21 -0800 Subject: tty: Move tty_check_change() helper Move is_ignored() to drivers/tty/tty_io.c and re-declare in file scope. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 6 ------ drivers/tty/tty_io.c | 6 ++++++ include/linux/tty.h | 1 - 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index dae628f19912..f4555a261420 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1763,12 +1763,6 @@ static int n_tty_receive_buf2(struct tty_struct *tty, const unsigned char *cp, return n_tty_receive_buf_common(tty, cp, fp, count, 1); } -int is_ignored(int sig) -{ - return (sigismember(¤t->blocked, sig) || - current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); -} - /** * n_tty_set_termios - termios data changed * @tty: terminal diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 798acb690092..e8996fc3ff1c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -381,6 +381,12 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) EXPORT_SYMBOL_GPL(tty_find_polling_driver); #endif +static int is_ignored(int sig) +{ + return (sigismember(¤t->blocked, sig) || + current->sighand->action[sig-1].sa.sa_handler == SIG_IGN); +} + /** * tty_check_change - check for POSIX terminal changes * @tty: tty to check diff --git a/include/linux/tty.h b/include/linux/tty.h index 26a9b4b3efe9..ba7120dccccb 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -445,7 +445,6 @@ extern int tty_throttle_safe(struct tty_struct *tty); extern int tty_unthrottle_safe(struct tty_struct *tty); extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws); extern int is_current_pgrp_orphaned(void); -extern int is_ignored(int sig); extern void tty_hangup(struct tty_struct *tty); extern void tty_vhangup(struct tty_struct *tty); extern int tty_hung_up_p(struct file *filp); -- cgit From 527ffc11e1c0aa049b3a831d6f07ed98e06a0819 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:22 -0800 Subject: tty: Remove unreferenced tty flags macro TTY_DEBUG The TTY_DEBUG macro is not used; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/tty.h b/include/linux/tty.h index ba7120dccccb..da16b5980c25 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -336,7 +336,6 @@ struct tty_file_private { #define TTY_IO_ERROR 1 /* Cause an I/O error (may be no ldisc too) */ #define TTY_OTHER_CLOSED 2 /* Other side (if any) has closed */ #define TTY_EXCLUSIVE 3 /* Exclusive open mode */ -#define TTY_DEBUG 4 /* Debugging */ #define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */ #define TTY_OTHER_DONE 6 /* Closed pty has completed input processing */ #define TTY_LDISC_OPEN 11 /* Line discipline is open */ -- cgit From 4a510969374ab8853451c337e43d28fb864e43fd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:35:23 -0800 Subject: tty: Make tty_files_lock per-tty Access to tty->tty_files list is always per-tty, never for all ttys simultaneously. Replace global tty_files_lock spinlock with per-tty ->files_lock. Initialize when the ->tty_files list is inited, in alloc_tty_struct(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 25 ++++++++++++------------- include/linux/tty.h | 2 +- security/selinux/hooks.c | 4 ++-- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index e8996fc3ff1c..c5b4274584dc 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -138,9 +138,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ /* Mutex to protect creating and releasing a tty */ DEFINE_MUTEX(tty_mutex); -/* Spinlock to protect the tty->tty_files list */ -DEFINE_SPINLOCK(tty_files_lock); - static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); ssize_t redirected_tty_write(struct file *, const char __user *, @@ -202,9 +199,9 @@ void tty_add_file(struct tty_struct *tty, struct file *file) priv->tty = tty; priv->file = file; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_add(&priv->list, &tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); } /** @@ -225,10 +222,11 @@ void tty_free_file(struct file *file) static void tty_del_file(struct file *file) { struct tty_file_private *priv = file->private_data; + struct tty_struct *tty = priv->tty; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del(&priv->list); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_free_file(file); } @@ -286,11 +284,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) struct list_head *p; int count = 0; - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_for_each(p, &tty->tty_files) { count++; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_SLAVE && tty->link && tty->link->count) @@ -713,7 +711,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) workqueue with the lock held */ check_tty_count(tty, "tty_hangup"); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); /* This breaks for file handles being sent over AF_UNIX sockets ? */ list_for_each_entry(priv, &tty->tty_files, list) { filp = priv->file; @@ -725,7 +723,7 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); refs = tty_signal_session_leader(tty, exit_session); /* Account for the p->signal references we killed */ @@ -1637,9 +1635,9 @@ static void release_one_tty(struct work_struct *work) tty_driver_kref_put(driver); module_put(owner); - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); list_del_init(&tty->tty_files); - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); put_pid(tty->pgrp); put_pid(tty->session); @@ -3176,6 +3174,7 @@ struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) mutex_init(&tty->atomic_write_lock); spin_lock_init(&tty->ctrl_lock); spin_lock_init(&tty->flow_lock); + spin_lock_init(&tty->files_lock); INIT_LIST_HEAD(&tty->tty_files); INIT_WORK(&tty->SAK_work, do_SAK_work); diff --git a/include/linux/tty.h b/include/linux/tty.h index da16b5980c25..780adbfc6dce 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -302,6 +302,7 @@ struct tty_struct { struct work_struct hangup_work; void *disc_data; void *driver_data; + spinlock_t files_lock; /* protects tty_files list */ struct list_head tty_files; #define N_TTY_BUF_SIZE 4096 @@ -508,7 +509,6 @@ extern int tty_standard_install(struct tty_driver *driver, struct tty_struct *tty); extern struct mutex tty_mutex; -extern spinlock_t tty_files_lock; #define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock)) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f8110cfd80ff..8010bc5391c3 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2415,7 +2415,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, tty = get_current_tty(); if (tty) { - spin_lock(&tty_files_lock); + spin_lock(&tty->files_lock); if (!list_empty(&tty->tty_files)) { struct tty_file_private *file_priv; @@ -2430,7 +2430,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE)) drop_tty = 1; } - spin_unlock(&tty_files_lock); + spin_unlock(&tty->files_lock); tty_kref_put(tty); } /* Reset controlling tty. */ -- cgit From d7c0ba40ebb32510e2c5d80a392474320cab8a2d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:25 -0800 Subject: tty: audit: Early-out pty master reads earlier Reads from pty masters are not logged; early-out before taking locks. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 3d245cd3d8e6..ead924e4bd53 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -276,16 +276,16 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, if (unlikely(size == 0)) return; + if (tty->driver->type == TTY_DRIVER_TYPE_PTY + && tty->driver->subtype == PTY_TYPE_MASTER) + return; + spin_lock_irqsave(¤t->sighand->siglock, flags); audit_log_tty_passwd = current->signal->audit_tty_log_passwd; spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) return; - if (tty->driver->type == TTY_DRIVER_TYPE_PTY - && tty->driver->subtype == PTY_TYPE_MASTER) - return; - buf = tty_audit_buf_get(tty, icanon); if (!buf) return; -- cgit From eab25a5cd1f91b5c7991affe95f24ce188b8021f Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:26 -0800 Subject: tty: audit: Never audit packet mode tty audit never logs pty master reads, but packet mode only works for pty masters, so tty_audit_add_data() was never logging packet mode anyway. Don't audit packet mode data. As those are the lone call sites, remove tty_put_user(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index f4555a261420..bacafda44bf3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -153,15 +153,6 @@ static inline unsigned char *echo_buf_addr(struct n_tty_data *ldata, size_t i) return &ldata->echo_buf[i & (N_TTY_BUF_SIZE - 1)]; } -static inline int tty_put_user(struct tty_struct *tty, unsigned char x, - unsigned char __user *ptr) -{ - struct n_tty_data *ldata = tty->disc_data; - - tty_audit_add_data(tty, &x, 1, ldata->icanon); - return put_user(x, ptr); -} - static int tty_copy_to_user(struct tty_struct *tty, void __user *to, size_t tail, size_t n) { @@ -2197,11 +2188,11 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; spin_unlock_irq(&tty->link->ctrl_lock); - if (tty_put_user(tty, cs, b++)) { + if (put_user(cs, b)) { retval = -EFAULT; - b--; break; } + b++; nr--; break; } @@ -2247,11 +2238,11 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, /* Deal with packet mode. */ if (packet && b == buf) { - if (tty_put_user(tty, TIOCPKT_DATA, b++)) { + if (put_user(TIOCPKT_DATA, b)) { retval = -EFAULT; - b--; break; } + b++; nr--; } -- cgit From 309426ae69cdf35b0d72a8bd59a5081f8ddccddd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:27 -0800 Subject: tty: audit: Remove icanon mode from call chain The tty termios bits cannot change while n_tty_read() is in the i/o loop; the termios_rwsem ensures mutual exclusion with termios changes in n_tty_set_termios(). Check L_ICANON() directly and eliminate icanon parameter. NB: tty_audit_add_data() => tty_audit_buf_get() => tty_audit_buf_alloc() is a single path; ie., tty_audit_buf_get() and tty_audit_buf_alloc() have no other callers. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 6 +++--- drivers/tty/tty_audit.c | 22 +++++++++------------- include/linux/tty.h | 4 ++-- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index bacafda44bf3..4fbc5defbcd8 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -162,7 +162,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to, int uncopied; if (n > size) { - tty_audit_add_data(tty, from, size, ldata->icanon); + tty_audit_add_data(tty, from, size); uncopied = copy_to_user(to, from, size); if (uncopied) return uncopied; @@ -171,7 +171,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to, from = ldata->read_buf; } - tty_audit_add_data(tty, from, n, ldata->icanon); + tty_audit_add_data(tty, from, n); return copy_to_user(to, from, n); } @@ -1978,7 +1978,7 @@ static int copy_from_read_buf(struct tty_struct *tty, retval = copy_to_user(*b, from, n); n -= retval; is_eof = n == 1 && *from == EOF_CHAR(tty); - tty_audit_add_data(tty, from, n, ldata->icanon); + tty_audit_add_data(tty, from, n); smp_store_release(&ldata->read_tail, ldata->read_tail + n); /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index ead924e4bd53..d2a004abeb5e 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -22,8 +22,7 @@ struct tty_audit_buf { unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; -static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, - unsigned icanon) +static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty) { struct tty_audit_buf *buf; @@ -35,9 +34,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, goto err_buf; atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = major; - buf->minor = minor; - buf->icanon = icanon; + buf->major = tty->driver->major; + buf->minor = tty->driver->minor_start + tty->index; + buf->icanon = !!L_ICANON(tty); buf->valid = 0; return buf; @@ -216,8 +215,7 @@ int tty_audit_push_current(void) * if TTY auditing is disabled or out of memory. Otherwise, return a new * reference to the buffer. */ -static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, - unsigned icanon) +static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) { struct tty_audit_buf *buf, *buf2; unsigned long flags; @@ -234,9 +232,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, } spin_unlock_irqrestore(¤t->sighand->siglock, flags); - buf2 = tty_audit_buf_alloc(tty->driver->major, - tty->driver->minor_start + tty->index, - icanon); + buf2 = tty_audit_buf_alloc(tty); if (buf2 == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; @@ -265,13 +261,13 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, * * Audit @data of @size from @tty, if necessary. */ -void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon) +void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; int major, minor; int audit_log_tty_passwd; unsigned long flags; + unsigned int icanon = !!L_ICANON(tty); if (unlikely(size == 0)) return; @@ -286,7 +282,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) return; - buf = tty_audit_buf_get(tty, icanon); + buf = tty_audit_buf_get(tty); if (!buf) return; diff --git a/include/linux/tty.h b/include/linux/tty.h index 780adbfc6dce..c011dc205e5c 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -593,7 +593,7 @@ extern void __init n_tty_init(void); /* tty_audit.c */ #ifdef CONFIG_AUDIT extern void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon); + size_t size); extern void tty_audit_exit(void); extern void tty_audit_fork(struct signal_struct *sig); extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); @@ -601,7 +601,7 @@ extern void tty_audit_push(struct tty_struct *tty); extern int tty_audit_push_current(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, - size_t size, unsigned icanon) + size_t size) { } static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch) -- cgit From a75c9b091226c0062a498d1cb65f9f6b858ebe55 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:28 -0800 Subject: tty: audit: Defer audit buffer association The tty audit buffer used to audit/record tty input is allocated on the process's first call to tty_audit_add_data(), and not freed until the process exits. On each call to tty_audit_add_data(), the current tty is compared (by major:minor) with the last tty associated with the audit buffer, and if the tty has changed the existing data is logged to the audit log. The audit buffer is then re-associated with the new tty. Currently, the audit buffer is immediately associated with the tty; however, the association must be re-checked when the buffer is locked prior to copying the tty input. This extra step is always necessary, since a concurrent read of a different tty by another thread of the process may have used the buffer in between allocation and buffer lock. Rather than associate the audit buffer with the tty at allocation, leave the buffer initially un-associated (null dev_t); simply let the re-association check also perform the initial association. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index d2a004abeb5e..9effa81acdfc 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -22,7 +22,7 @@ struct tty_audit_buf { unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; -static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty) +static struct tty_audit_buf *tty_audit_buf_alloc(void) { struct tty_audit_buf *buf; @@ -34,9 +34,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty) goto err_buf; atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = tty->driver->major; - buf->minor = tty->driver->minor_start + tty->index; - buf->icanon = !!L_ICANON(tty); + buf->major = 0; + buf->minor = 0; + buf->icanon = 0; buf->valid = 0; return buf; @@ -211,11 +211,11 @@ int tty_audit_push_current(void) /** * tty_audit_buf_get - Get an audit buffer. * - * Get an audit buffer for @tty, allocate it if necessary. Return %NULL + * Get an audit buffer, allocate it if necessary. Return %NULL * if TTY auditing is disabled or out of memory. Otherwise, return a new * reference to the buffer. */ -static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) +static struct tty_audit_buf *tty_audit_buf_get(void) { struct tty_audit_buf *buf, *buf2; unsigned long flags; @@ -232,7 +232,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) } spin_unlock_irqrestore(¤t->sighand->siglock, flags); - buf2 = tty_audit_buf_alloc(tty); + buf2 = tty_audit_buf_alloc(); if (buf2 == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; @@ -282,7 +282,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) return; - buf = tty_audit_buf_get(tty); + buf = tty_audit_buf_get(); if (!buf) return; -- cgit From f229c2c161de94a404fa16a17cb93c4a06938af5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:29 -0800 Subject: tty: audit: Take siglock directly lock_task_sighand() is for situations where the struct task_struct* may disappear while trying to deref the sighand; this never applies to 'current'. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 9effa81acdfc..5f65653cee48 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -180,22 +180,19 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) int tty_audit_push_current(void) { struct tty_audit_buf *buf = ERR_PTR(-EPERM); - struct task_struct *tsk = current; unsigned long flags; - if (!lock_task_sighand(tsk, &flags)) - return -ESRCH; - - if (tsk->signal->audit_tty) { - buf = tsk->signal->tty_audit_buf; + spin_lock_irqsave(¤t->sighand->siglock, flags); + if (current->signal->audit_tty) { + buf = current->signal->tty_audit_buf; if (buf) atomic_inc(&buf->count); } - unlock_task_sighand(tsk, &flags); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); /* * Return 0 when signal->audit_tty set - * but tsk->signal->tty_audit_buf == NULL. + * but current->signal->tty_audit_buf == NULL. */ if (!buf || IS_ERR(buf)) return PTR_ERR(buf); -- cgit From b50819f437c094b4beb2e8684fbe12bbe79fb331 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:30 -0800 Subject: tty: audit: Ignore current association for audit push In canonical read mode, each line read and logged is pushed separately with tty_audit_push(). For all single-threaded processes and multi-threaded processes reading from only one tty, this patch has no effect; the last line read will still be the entry pushed to the audit log because the tty association cannot have changed between tty_audit_add_data() and tty_audit_push(). For multi-threaded processes reading from different ttys concurrently, the audit log will have mixed log entries anyway. Consider two ttys audited concurrently: CPU0 CPU1 ---------- ------------ tty_audit_add_data(ttyA) tty_audit_add_data(ttyB) tty_audit_push() tty_audit_add_data(ttyB) tty_audit_push() This patch will now cause the ttyB output to be split into separate audit log entries. However, this possibility is equally likely without this patch: CPU0 CPU1 ---------- ------------ tty_audit_add_data(ttyB) tty_audit_add_data(ttyA) tty_audit_push() tty_audit_add_data(ttyB) tty_audit_push() Mixed canonical and non-canonical reads have similar races. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- drivers/tty/tty_audit.c | 11 +++-------- include/linux/tty.h | 4 ++-- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 4fbc5defbcd8..827206914b02 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2072,7 +2072,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, ldata->line_start = ldata->read_tail; else ldata->push = 0; - tty_audit_push(tty); + tty_audit_push(); } return 0; } diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 5f65653cee48..5ae48396e265 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -313,9 +313,9 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) /** * tty_audit_push - Push buffered data out * - * Make sure no audit data is pending for @tty on the current process. + * Make sure no audit data is pending on the current process. */ -void tty_audit_push(struct tty_struct *tty) +void tty_audit_push(void) { struct tty_audit_buf *buf; unsigned long flags; @@ -331,13 +331,8 @@ void tty_audit_push(struct tty_struct *tty) spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (buf) { - int major, minor; - - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; mutex_lock(&buf->mutex); - if (buf->major == major && buf->minor == minor) - tty_audit_buf_push(buf); + tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); tty_audit_buf_put(buf); } diff --git a/include/linux/tty.h b/include/linux/tty.h index c011dc205e5c..83d74dcfb3c8 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -597,7 +597,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, const void *data, extern void tty_audit_exit(void); extern void tty_audit_fork(struct signal_struct *sig); extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); -extern void tty_audit_push(struct tty_struct *tty); +extern void tty_audit_push(void); extern int tty_audit_push_current(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, @@ -613,7 +613,7 @@ static inline void tty_audit_exit(void) static inline void tty_audit_fork(struct signal_struct *sig) { } -static inline void tty_audit_push(struct tty_struct *tty) +static inline void tty_audit_push(void) { } static inline int tty_audit_push_current(void) -- cgit From 37282a77954aa2dbb339d15902290f25b868d2e8 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:31 -0800 Subject: tty: audit: Combine push functions tty_audit_push() and tty_audit_push_current() perform identical tasks; eliminate the tty_audit_push() implementation and the tty_audit_push_current() name. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 35 +++-------------------------------- include/linux/tty.h | 8 ++------ kernel/audit.c | 2 +- 3 files changed, 6 insertions(+), 39 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 5ae48396e265..6b82c3ce321f 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -172,12 +172,11 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) } /** - * tty_audit_push_current - Flush current's pending audit data + * tty_audit_push - Flush current's pending audit data * - * Try to lock sighand and get a reference to the tty audit buffer if available. - * Flush the buffer or return an appropriate error code. + * Returns 0 if success, -EPERM if tty audit is disabled */ -int tty_audit_push_current(void) +int tty_audit_push(void) { struct tty_audit_buf *buf = ERR_PTR(-EPERM); unsigned long flags; @@ -309,31 +308,3 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) mutex_unlock(&buf->mutex); tty_audit_buf_put(buf); } - -/** - * tty_audit_push - Push buffered data out - * - * Make sure no audit data is pending on the current process. - */ -void tty_audit_push(void) -{ - struct tty_audit_buf *buf; - unsigned long flags; - - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (likely(!current->signal->audit_tty)) { - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - return; - } - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - - if (buf) { - mutex_lock(&buf->mutex); - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); - } -} diff --git a/include/linux/tty.h b/include/linux/tty.h index 83d74dcfb3c8..dea7d54d00d4 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -597,8 +597,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, const void *data, extern void tty_audit_exit(void); extern void tty_audit_fork(struct signal_struct *sig); extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); -extern void tty_audit_push(void); -extern int tty_audit_push_current(void); +extern int tty_audit_push(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) @@ -613,10 +612,7 @@ static inline void tty_audit_exit(void) static inline void tty_audit_fork(struct signal_struct *sig) { } -static inline void tty_audit_push(void) -{ -} -static inline int tty_audit_push_current(void) +static inline int tty_audit_push(void) { return 0; } diff --git a/kernel/audit.c b/kernel/audit.c index 3a3e5deeda8d..610f221df069 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -920,7 +920,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err == 1) { /* match or error */ err = 0; if (msg_type == AUDIT_USER_TTY) { - err = tty_audit_push_current(); + err = tty_audit_push(); if (err) break; } -- cgit From 4d240b6442824df3b5e401459789bab5ee7777ae Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:32 -0800 Subject: tty: audit: Track tty association with dev_t Use dev_t instead of separate major/minor fields to track tty audit buffer association. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 6b82c3ce321f..50380d87061d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -16,7 +16,7 @@ struct tty_audit_buf { atomic_t count; struct mutex mutex; /* Protects all data below */ - int major, minor; /* The TTY which the data is from */ + dev_t dev; /* The TTY which the data is from */ unsigned icanon:1; size_t valid; unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ @@ -34,8 +34,7 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void) goto err_buf; atomic_set(&buf->count, 1); mutex_init(&buf->mutex); - buf->major = 0; - buf->minor = 0; + buf->dev = MKDEV(0, 0); buf->icanon = 0; buf->valid = 0; return buf; @@ -59,7 +58,7 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf) tty_audit_buf_free(buf); } -static void tty_audit_log(const char *description, int major, int minor, +static void tty_audit_log(const char *description, dev_t dev, unsigned char *data, size_t size) { struct audit_buffer *ab; @@ -75,7 +74,7 @@ static void tty_audit_log(const char *description, int major, int minor, audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" " minor=%d comm=", description, pid, uid, - loginuid, sessionid, major, minor); + loginuid, sessionid, MAJOR(dev), MINOR(dev)); get_task_comm(name, tsk); audit_log_untrustedstring(ab, name); audit_log_format(ab, " data="); @@ -98,7 +97,7 @@ static void tty_audit_buf_push(struct tty_audit_buf *buf) buf->valid = 0; return; } - tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid); + tty_audit_log("tty", buf->dev, buf->data, buf->valid); buf->valid = 0; } @@ -141,7 +140,8 @@ void tty_audit_fork(struct signal_struct *sig) void tty_audit_tiocsti(struct tty_struct *tty, char ch) { struct tty_audit_buf *buf; - int major, minor, should_audit; + dev_t dev; + int should_audit; unsigned long flags; spin_lock_irqsave(¤t->sighand->siglock, flags); @@ -151,11 +151,10 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) atomic_inc(&buf->count); spin_unlock_irqrestore(¤t->sighand->siglock, flags); - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; + dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; if (buf) { mutex_lock(&buf->mutex); - if (buf->major == major && buf->minor == minor) + if (buf->dev == dev) tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); tty_audit_buf_put(buf); @@ -167,7 +166,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) auid = audit_get_loginuid(current); sessionid = audit_get_sessionid(current); - tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1); + tty_audit_log("ioctl=TIOCSTI", dev, &ch, 1); } } @@ -260,10 +259,10 @@ static struct tty_audit_buf *tty_audit_buf_get(void) void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; - int major, minor; int audit_log_tty_passwd; unsigned long flags; unsigned int icanon = !!L_ICANON(tty); + dev_t dev; if (unlikely(size == 0)) return; @@ -283,13 +282,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) return; mutex_lock(&buf->mutex); - major = tty->driver->major; - minor = tty->driver->minor_start + tty->index; - if (buf->major != major || buf->minor != minor - || buf->icanon != icanon) { + dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; + if (buf->dev != dev || buf->icanon != icanon) { tty_audit_buf_push(buf); - buf->major = major; - buf->minor = minor; + buf->dev = dev; buf->icanon = icanon; } do { -- cgit From 2e28d38ae1d9ced6ac2deb4001aca3f267304cdb Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:33 -0800 Subject: tty: audit: Handle tty audit enable atomically The audit_tty and audit_tty_log_passwd fields are actually bool values, so merge into single memory location to access atomically. NB: audit log operations may still occur after tty audit is disabled which is consistent with the existing functionality Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 53 ++++++++++++++++++++----------------------------- include/linux/audit.h | 4 ++++ include/linux/sched.h | 1 - kernel/audit.c | 25 +++++++++++------------ 4 files changed, 38 insertions(+), 45 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 50380d87061d..3d90f88c5ff9 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -131,7 +131,6 @@ void tty_audit_exit(void) void tty_audit_fork(struct signal_struct *sig) { sig->audit_tty = current->signal->audit_tty; - sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd; } /** @@ -141,11 +140,9 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { struct tty_audit_buf *buf; dev_t dev; - int should_audit; unsigned long flags; spin_lock_irqsave(¤t->sighand->siglock, flags); - should_audit = current->signal->audit_tty; buf = current->signal->tty_audit_buf; if (buf) atomic_inc(&buf->count); @@ -160,7 +157,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) tty_audit_buf_put(buf); } - if (should_audit && audit_enabled) { + if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) { kuid_t auid; unsigned int sessionid; @@ -177,29 +174,25 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) */ int tty_audit_push(void) { - struct tty_audit_buf *buf = ERR_PTR(-EPERM); + struct tty_audit_buf *buf; unsigned long flags; + if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) + return -EPERM; + spin_lock_irqsave(¤t->sighand->siglock, flags); - if (current->signal->audit_tty) { - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - } + buf = current->signal->tty_audit_buf; + if (buf) + atomic_inc(&buf->count); spin_unlock_irqrestore(¤t->sighand->siglock, flags); - /* - * Return 0 when signal->audit_tty set - * but current->signal->tty_audit_buf == NULL. - */ - if (!buf || IS_ERR(buf)) - return PTR_ERR(buf); - - mutex_lock(&buf->mutex); - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); + if (buf) { + mutex_lock(&buf->mutex); + tty_audit_buf_push(buf); + mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); + tty_audit_buf_put(buf); + } return 0; } @@ -218,8 +211,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void) buf = NULL; buf2 = NULL; spin_lock_irqsave(¤t->sighand->siglock, flags); - if (likely(!current->signal->audit_tty)) - goto out; buf = current->signal->tty_audit_buf; if (buf) { atomic_inc(&buf->count); @@ -233,9 +224,10 @@ static struct tty_audit_buf *tty_audit_buf_get(void) return NULL; } - spin_lock_irqsave(¤t->sighand->siglock, flags); - if (!current->signal->audit_tty) + if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) goto out; + + spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; if (!buf) { current->signal->tty_audit_buf = buf2; @@ -259,9 +251,8 @@ static struct tty_audit_buf *tty_audit_buf_get(void) void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) { struct tty_audit_buf *buf; - int audit_log_tty_passwd; - unsigned long flags; unsigned int icanon = !!L_ICANON(tty); + unsigned int audit_tty; dev_t dev; if (unlikely(size == 0)) @@ -271,10 +262,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) && tty->driver->subtype == PTY_TYPE_MASTER) return; - spin_lock_irqsave(¤t->sighand->siglock, flags); - audit_log_tty_passwd = current->signal->audit_tty_log_passwd; - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) + audit_tty = READ_ONCE(current->signal->audit_tty); + if (~audit_tty & AUDIT_TTY_ENABLE) + return; + if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty)) return; buf = tty_audit_buf_get(); diff --git a/include/linux/audit.h b/include/linux/audit.h index b40ed5df5542..e38e3fc13ea8 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -109,6 +109,10 @@ extern int audit_classify_compat_syscall(int abi, unsigned syscall); /* maximized args number that audit_socketcall can process */ #define AUDITSC_ARGS 6 +/* bit values for ->signal->audit_tty */ +#define AUDIT_TTY_ENABLE BIT(0) +#define AUDIT_TTY_LOG_PASSWD BIT(1) + struct filename; extern void audit_log_session_info(struct audit_buffer *ab); diff --git a/include/linux/sched.h b/include/linux/sched.h index a10494a94cc3..a389222e9703 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -775,7 +775,6 @@ struct signal_struct { #endif #ifdef CONFIG_AUDIT unsigned audit_tty; - unsigned audit_tty_log_passwd; struct tty_audit_buf *tty_audit_buf; #endif diff --git a/kernel/audit.c b/kernel/audit.c index 610f221df069..2651e423b2dc 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1030,20 +1030,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; case AUDIT_TTY_GET: { struct audit_tty_status s; - struct task_struct *tsk = current; + unsigned int t; - spin_lock(&tsk->sighand->siglock); - s.enabled = tsk->signal->audit_tty; - s.log_passwd = tsk->signal->audit_tty_log_passwd; - spin_unlock(&tsk->sighand->siglock); + t = READ_ONCE(current->signal->audit_tty); + s.enabled = t & AUDIT_TTY_ENABLE; + s.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD); audit_send_reply(skb, seq, AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); break; } case AUDIT_TTY_SET: { struct audit_tty_status s, old; - struct task_struct *tsk = current; struct audit_buffer *ab; + unsigned int t; memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ @@ -1053,14 +1052,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) (s.log_passwd != 0 && s.log_passwd != 1)) err = -EINVAL; - spin_lock(&tsk->sighand->siglock); - old.enabled = tsk->signal->audit_tty; - old.log_passwd = tsk->signal->audit_tty_log_passwd; - if (!err) { - tsk->signal->audit_tty = s.enabled; - tsk->signal->audit_tty_log_passwd = s.log_passwd; + if (err) + t = READ_ONCE(current->signal->audit_tty); + else { + t = s.enabled | (-s.log_passwd & AUDIT_TTY_LOG_PASSWD); + t = xchg(¤t->signal->audit_tty, t); } - spin_unlock(&tsk->sighand->siglock); + old.enabled = t & AUDIT_TTY_ENABLE; + old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD); audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d" -- cgit From 5c8b3185c41cd7f7c1e39c6e300daac8ef547e7e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:34 -0800 Subject: tty: audit: Remove false memory optimization The tty audit buffer is allocated at first use and not freed until the process exits. If tty audit is turned off after the audit buffer has been allocated, no effort is made to release the buffer. So re-checking if tty audit has just been turned off when tty audit was just on is false optimization; the likelihood of triggering this condition is exceedingly small. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 3d90f88c5ff9..79439846d29d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -200,8 +200,7 @@ int tty_audit_push(void) * tty_audit_buf_get - Get an audit buffer. * * Get an audit buffer, allocate it if necessary. Return %NULL - * if TTY auditing is disabled or out of memory. Otherwise, return a new - * reference to the buffer. + * if out of memory. Otherwise, return a new reference to the buffer. */ static struct tty_audit_buf *tty_audit_buf_get(void) { @@ -224,9 +223,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void) return NULL; } - if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) - goto out; - spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; if (!buf) { -- cgit From 5493090fc2341d9f28bdd9e81445fe0a130bafc2 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:35 -0800 Subject: tty: audit: Remove tty_audit_buf reference counting When tty_audit_exit() is called from do_exit(), the process is single-threaded. Since the tty_audit_buf is only shared by threads of a process, no other thread can be concurrently accessing the tty_audit_buf during or after tty_audit_exit(). Thus, no other thread can be holding an extra tty_audit_buf reference which would prevent tty_audit_exit() from freeing the tty_audit_buf. As that is the only purpose of the ref counting, remove the reference counting and free the tty_audit_buf directly. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 47 +++++++---------------------------------------- 1 file changed, 7 insertions(+), 40 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 79439846d29d..71ba8baee14d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -14,7 +14,6 @@ #include struct tty_audit_buf { - atomic_t count; struct mutex mutex; /* Protects all data below */ dev_t dev; /* The TTY which the data is from */ unsigned icanon:1; @@ -32,7 +31,6 @@ static struct tty_audit_buf *tty_audit_buf_alloc(void) buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); if (!buf->data) goto err_buf; - atomic_set(&buf->count, 1); mutex_init(&buf->mutex); buf->dev = MKDEV(0, 0); buf->icanon = 0; @@ -52,12 +50,6 @@ static void tty_audit_buf_free(struct tty_audit_buf *buf) kfree(buf); } -static void tty_audit_buf_put(struct tty_audit_buf *buf) -{ - if (atomic_dec_and_test(&buf->count)) - tty_audit_buf_free(buf); -} - static void tty_audit_log(const char *description, dev_t dev, unsigned char *data, size_t size) { @@ -106,6 +98,9 @@ static void tty_audit_buf_push(struct tty_audit_buf *buf) * * Make sure all buffered data is written out and deallocate the buffer. * Only needs to be called if current->signal->tty_audit_buf != %NULL. + * + * The process is single-threaded at this point; no other threads share + * current->signal. */ void tty_audit_exit(void) { @@ -116,11 +111,8 @@ void tty_audit_exit(void) if (!buf) return; - mutex_lock(&buf->mutex); tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - - tty_audit_buf_put(buf); + tty_audit_buf_free(buf); } /** @@ -140,21 +132,14 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { struct tty_audit_buf *buf; dev_t dev; - unsigned long flags; - - spin_lock_irqsave(¤t->sighand->siglock, flags); - buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; + buf = current->signal->tty_audit_buf; if (buf) { mutex_lock(&buf->mutex); if (buf->dev == dev) tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); } if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) { @@ -175,23 +160,15 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) int tty_audit_push(void) { struct tty_audit_buf *buf; - unsigned long flags; if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) return -EPERM; - spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; - if (buf) - atomic_inc(&buf->count); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (buf) { mutex_lock(&buf->mutex); tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); - - tty_audit_buf_put(buf); } return 0; } @@ -207,15 +184,9 @@ static struct tty_audit_buf *tty_audit_buf_get(void) struct tty_audit_buf *buf, *buf2; unsigned long flags; - buf = NULL; - buf2 = NULL; - spin_lock_irqsave(¤t->sighand->siglock, flags); buf = current->signal->tty_audit_buf; - if (buf) { - atomic_inc(&buf->count); - goto out; - } - spin_unlock_irqrestore(¤t->sighand->siglock, flags); + if (buf) + return buf; buf2 = tty_audit_buf_alloc(); if (buf2 == NULL) { @@ -230,9 +201,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void) buf = buf2; buf2 = NULL; } - atomic_inc(&buf->count); - /* Fall through */ - out: spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (buf2) tty_audit_buf_free(buf2); @@ -289,5 +257,4 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) tty_audit_buf_push(buf); } while (size != 0); mutex_unlock(&buf->mutex); - tty_audit_buf_put(buf); } -- cgit From fbaa122718a1235f4f83baa3abaad21cfefdbc9d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:36 -0800 Subject: tty: audit: Simplify first-use allocation The first-use tty audit buffer allocation is a potential race amongst multiple attempts at 'first-use'; only one 'winner' is acceptable. The successful buffer assignment occurs if tty_audit_buf == NULL (which will also be the return from cmpxchg()); otherwise, another racer 'won' and this buffer allocation is freed. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 71ba8baee14d..6e33e41ec74d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -181,30 +181,22 @@ int tty_audit_push(void) */ static struct tty_audit_buf *tty_audit_buf_get(void) { - struct tty_audit_buf *buf, *buf2; - unsigned long flags; + struct tty_audit_buf *buf; buf = current->signal->tty_audit_buf; if (buf) return buf; - buf2 = tty_audit_buf_alloc(); - if (buf2 == NULL) { + buf = tty_audit_buf_alloc(); + if (buf == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; } - spin_lock_irqsave(¤t->sighand->siglock, flags); - buf = current->signal->tty_audit_buf; - if (!buf) { - current->signal->tty_audit_buf = buf2; - buf = buf2; - buf2 = NULL; - } - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (buf2) - tty_audit_buf_free(buf2); - return buf; + /* Race to use this buffer, free it if another wins */ + if (cmpxchg(¤t->signal->tty_audit_buf, NULL, buf) != NULL) + tty_audit_buf_free(buf); + return current->signal->tty_audit_buf; } /** -- cgit From f17c3662745ea5fd4510c3dff19f9975552e1865 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:37 -0800 Subject: tty: audit: Check audit enable first Audit is unlikely to be enabled; check first to exit asap. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 6e33e41ec74d..269e41f45832 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -211,6 +211,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) unsigned int audit_tty; dev_t dev; + audit_tty = READ_ONCE(current->signal->audit_tty); + if (~audit_tty & AUDIT_TTY_ENABLE) + return; + if (unlikely(size == 0)) return; @@ -218,9 +222,6 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) && tty->driver->subtype == PTY_TYPE_MASTER) return; - audit_tty = READ_ONCE(current->signal->audit_tty); - if (~audit_tty & AUDIT_TTY_ENABLE) - return; if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty)) return; -- cgit From 82b5c93a00169614a75d5fa3b5974f832a7857c7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:38 -0800 Subject: tty: audit: Always push audit buffer before TIOCSTI The data read from another tty may be relevant to the action of the TIOCSTI ioctl; log the audit buffer immediately. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 269e41f45832..fa461dc5b111 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -130,19 +130,13 @@ void tty_audit_fork(struct signal_struct *sig) */ void tty_audit_tiocsti(struct tty_struct *tty, char ch) { - struct tty_audit_buf *buf; dev_t dev; dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; - buf = current->signal->tty_audit_buf; - if (buf) { - mutex_lock(&buf->mutex); - if (buf->dev == dev) - tty_audit_buf_push(buf); - mutex_unlock(&buf->mutex); - } + if (tty_audit_push()) + return; - if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) { + if (audit_enabled) { kuid_t auid; unsigned int sessionid; -- cgit From 55b6314a17e8ad53233e9d0ebf6328734720e93b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 22:55:39 -0800 Subject: tty: audit: Poison tty_audit_buf while process exits Warn if tty_audit_buf use is attempted after tty_audit_exit() has already freed it. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_audit.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index fa461dc5b111..66d53fcf4da0 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -21,6 +21,15 @@ struct tty_audit_buf { unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ }; +static struct tty_audit_buf *tty_audit_buf_ref(void) +{ + struct tty_audit_buf *buf; + + buf = current->signal->tty_audit_buf; + WARN_ON(buf == ERR_PTR(-ESRCH)); + return buf; +} + static struct tty_audit_buf *tty_audit_buf_alloc(void) { struct tty_audit_buf *buf; @@ -106,8 +115,7 @@ void tty_audit_exit(void) { struct tty_audit_buf *buf; - buf = current->signal->tty_audit_buf; - current->signal->tty_audit_buf = NULL; + buf = xchg(¤t->signal->tty_audit_buf, ERR_PTR(-ESRCH)); if (!buf) return; @@ -158,8 +166,8 @@ int tty_audit_push(void) if (~current->signal->audit_tty & AUDIT_TTY_ENABLE) return -EPERM; - buf = current->signal->tty_audit_buf; - if (buf) { + buf = tty_audit_buf_ref(); + if (!IS_ERR_OR_NULL(buf)) { mutex_lock(&buf->mutex); tty_audit_buf_push(buf); mutex_unlock(&buf->mutex); @@ -171,13 +179,14 @@ int tty_audit_push(void) * tty_audit_buf_get - Get an audit buffer. * * Get an audit buffer, allocate it if necessary. Return %NULL - * if out of memory. Otherwise, return a new reference to the buffer. + * if out of memory or ERR_PTR(-ESRCH) if tty_audit_exit() has already + * occurred. Otherwise, return a new reference to the buffer. */ static struct tty_audit_buf *tty_audit_buf_get(void) { struct tty_audit_buf *buf; - buf = current->signal->tty_audit_buf; + buf = tty_audit_buf_ref(); if (buf) return buf; @@ -190,7 +199,7 @@ static struct tty_audit_buf *tty_audit_buf_get(void) /* Race to use this buffer, free it if another wins */ if (cmpxchg(¤t->signal->tty_audit_buf, NULL, buf) != NULL) tty_audit_buf_free(buf); - return current->signal->tty_audit_buf; + return tty_audit_buf_ref(); } /** @@ -220,7 +229,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size) return; buf = tty_audit_buf_get(); - if (!buf) + if (IS_ERR_OR_NULL(buf)) return; mutex_lock(&buf->mutex); -- cgit From 98ee377144935857d8ad5d7d70cdab1da4ede32e Mon Sep 17 00:00:00 2001 From: Chris Diamand Date: Wed, 27 Jan 2016 17:04:35 -0800 Subject: Input: byd - add BYD PS/2 touchpad driver Driver for the BYD BTP10463 touchpad, found in PC Specialist `Lafite' laptops. This patch sends the magic command sequence which causes the touchpad to stream intellimouse-style packets. Gestures are detected inside the touchpad, and exposed as special values in the Z component of each packet - absolute coordinates are not supported, even in the Windows driver. At present, this supports two-finger vertical and horizontal scrolling, and provides the framework to expose the other gestures it can recognize. Signed-off-by: Chris Diamand Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/Kconfig | 10 ++ drivers/input/mouse/Makefile | 1 + drivers/input/mouse/byd.c | 337 +++++++++++++++++++++++++++++++++++++ drivers/input/mouse/byd.h | 18 ++ drivers/input/mouse/psmouse-base.c | 14 ++ drivers/input/mouse/psmouse.h | 1 + 6 files changed, 381 insertions(+) create mode 100644 drivers/input/mouse/byd.c create mode 100644 drivers/input/mouse/byd.h diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 17f97e5e11e7..096abb4ad5cd 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -48,6 +48,16 @@ config MOUSE_PS2_ALPS If unsure, say Y. +config MOUSE_PS2_BYD + bool "BYD PS/2 mouse protocol extension" if EXPERT + default y + depends on MOUSE_PS2 + help + Say Y here if you have a BYD PS/2 touchpad connected to + your system. + + If unsure, say Y. + config MOUSE_PS2_LOGIPS2PP bool "Logitech PS/2++ mouse protocol extension" if EXPERT default y diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index ee6a6e9563d4..6168b134937b 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -28,6 +28,7 @@ cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o cyapa_gen6.o psmouse-objs := psmouse-base.o synaptics.o focaltech.o psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o +psmouse-$(CONFIG_MOUSE_PS2_BYD) += byd.o psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c new file mode 100644 index 000000000000..9425e0f6c5ce --- /dev/null +++ b/drivers/input/mouse/byd.c @@ -0,0 +1,337 @@ +/* + * BYD TouchPad PS/2 mouse driver + * + * Copyright (C) 2015 Chris Diamand + * + * 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 "psmouse.h" +#include "byd.h" + +#define PS2_Y_OVERFLOW BIT_MASK(7) +#define PS2_X_OVERFLOW BIT_MASK(6) +#define PS2_Y_SIGN BIT_MASK(5) +#define PS2_X_SIGN BIT_MASK(4) +#define PS2_ALWAYS_1 BIT_MASK(3) +#define PS2_MIDDLE BIT_MASK(2) +#define PS2_RIGHT BIT_MASK(1) +#define PS2_LEFT BIT_MASK(0) + +/* + * The touchpad reports gestures in the last byte of each packet. It can take + * any of the following values: + */ + +/* One-finger scrolling in one of the edge scroll zones. */ +#define BYD_SCROLLUP 0xCA +#define BYD_SCROLLDOWN 0x36 +#define BYD_SCROLLLEFT 0xCB +#define BYD_SCROLLRIGHT 0x35 +/* Two-finger scrolling. */ +#define BYD_2DOWN 0x2B +#define BYD_2UP 0xD5 +#define BYD_2LEFT 0xD6 +#define BYD_2RIGHT 0x2A +/* Pinching in or out. */ +#define BYD_ZOOMOUT 0xD8 +#define BYD_ZOOMIN 0x28 +/* Three-finger swipe. */ +#define BYD_3UP 0xD3 +#define BYD_3DOWN 0x2D +#define BYD_3LEFT 0xD4 +#define BYD_3RIGHT 0x2C +/* Four-finger swipe. */ +#define BYD_4UP 0xCD +#define BYD_4DOWN 0x33 + +int byd_detect(struct psmouse *psmouse, bool set_properties) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[4]; + + param[0] = 0x03; + param[1] = 0x00; + param[2] = 0x00; + param[3] = 0x00; + + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + if (param[1] != 0x03 || param[2] != 0x64) + return -ENODEV; + + psmouse_dbg(psmouse, "BYD touchpad detected\n"); + + if (set_properties) { + psmouse->vendor = "BYD"; + psmouse->name = "TouchPad"; + } + + return 0; +} + +static psmouse_ret_t byd_process_byte(struct psmouse *psmouse) +{ + struct input_dev *dev = psmouse->dev; + u8 *pkt = psmouse->packet; + + if (psmouse->pktcnt > 0 && !(pkt[0] & PS2_ALWAYS_1)) { + psmouse_warn(psmouse, "Always_1 bit not 1. pkt[0] = %02x\n", + pkt[0]); + return PSMOUSE_BAD_DATA; + } + + if (psmouse->pktcnt < psmouse->pktsize) + return PSMOUSE_GOOD_DATA; + + /* Otherwise, a full packet has been received */ + switch (pkt[3]) { + case 0: { + /* Standard packet */ + /* Sign-extend if a sign bit is set. */ + unsigned int signx = pkt[0] & PS2_X_SIGN ? ~0xFF : 0; + unsigned int signy = pkt[0] & PS2_Y_SIGN ? ~0xFF : 0; + int dx = signx | (int) pkt[1]; + int dy = signy | (int) pkt[2]; + + input_report_rel(psmouse->dev, REL_X, dx); + input_report_rel(psmouse->dev, REL_Y, -dy); + + input_report_key(psmouse->dev, BTN_LEFT, pkt[0] & PS2_LEFT); + input_report_key(psmouse->dev, BTN_RIGHT, pkt[0] & PS2_RIGHT); + input_report_key(psmouse->dev, BTN_MIDDLE, pkt[0] & PS2_MIDDLE); + break; + } + + case BYD_SCROLLDOWN: + case BYD_2DOWN: + input_report_rel(dev, REL_WHEEL, -1); + break; + + case BYD_SCROLLUP: + case BYD_2UP: + input_report_rel(dev, REL_WHEEL, 1); + break; + + case BYD_SCROLLLEFT: + case BYD_2LEFT: + input_report_rel(dev, REL_HWHEEL, -1); + break; + + case BYD_SCROLLRIGHT: + case BYD_2RIGHT: + input_report_rel(dev, REL_HWHEEL, 1); + break; + + case BYD_ZOOMOUT: + case BYD_ZOOMIN: + case BYD_3UP: + case BYD_3DOWN: + case BYD_3LEFT: + case BYD_3RIGHT: + case BYD_4UP: + case BYD_4DOWN: + break; + + default: + psmouse_warn(psmouse, + "Unrecognized Z: pkt = %02x %02x %02x %02x\n", + psmouse->packet[0], psmouse->packet[1], + psmouse->packet[2], psmouse->packet[3]); + return PSMOUSE_BAD_DATA; + } + + input_sync(dev); + + return PSMOUSE_FULL_PACKET; +} + +/* Send a sequence of bytes, where each is ACKed before the next is sent. */ +static int byd_send_sequence(struct psmouse *psmouse, const u8 *seq, size_t len) +{ + unsigned int i; + + for (i = 0; i < len; ++i) { + if (ps2_command(&psmouse->ps2dev, NULL, seq[i])) + return -1; + } + return 0; +} + +/* Keep scrolling after fingers are removed. */ +#define SCROLL_INERTIAL 0x01 +#define SCROLL_NO_INERTIAL 0x02 + +/* Clicking can be done by tapping or pressing. */ +#define CLICK_BOTH 0x01 +/* Clicking can only be done by pressing. */ +#define CLICK_PRESS_ONLY 0x02 + +static int byd_enable(struct psmouse *psmouse) +{ + const u8 seq1[] = { 0xE2, 0x00, 0xE0, 0x02, 0xE0 }; + const u8 seq2[] = { + 0xD3, 0x01, + 0xD0, 0x00, + 0xD0, 0x04, + /* Whether clicking is done by tapping or pressing. */ + 0xD4, CLICK_PRESS_ONLY, + 0xD5, 0x01, + 0xD7, 0x03, + /* Vertical and horizontal one-finger scroll zone inertia. */ + 0xD8, SCROLL_INERTIAL, + 0xDA, 0x05, + 0xDB, 0x02, + 0xE4, 0x05, + 0xD6, 0x01, + 0xDE, 0x04, + 0xE3, 0x01, + 0xCF, 0x00, + 0xD2, 0x03, + /* Vertical and horizontal two-finger scrolling inertia. */ + 0xE5, SCROLL_INERTIAL, + 0xD9, 0x02, + 0xD9, 0x07, + 0xDC, 0x03, + 0xDD, 0x03, + 0xDF, 0x03, + 0xE1, 0x03, + 0xD1, 0x00, + 0xCE, 0x00, + 0xCC, 0x00, + 0xE0, 0x00, + 0xE2, 0x01 + }; + u8 param[4]; + + if (byd_send_sequence(psmouse, seq1, ARRAY_SIZE(seq1))) + return -1; + + /* Send a 0x01 command, which should return 4 bytes. */ + if (ps2_command(&psmouse->ps2dev, param, 0x0401)) + return -1; + + if (byd_send_sequence(psmouse, seq2, ARRAY_SIZE(seq2))) + return -1; + + return 0; +} + +/* + * Send the set of PS/2 commands required to make it identify as an + * intellimouse with 4-byte instead of 3-byte packets. + */ +static int byd_send_intellimouse_sequence(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + u8 param[4]; + int i; + const struct { + u16 command; + u8 arg; + } seq[] = { + { PSMOUSE_CMD_RESET_BAT, 0 }, + { PSMOUSE_CMD_RESET_BAT, 0 }, + { PSMOUSE_CMD_GETID, 0 }, + { PSMOUSE_CMD_SETSCALE11, 0 }, + { PSMOUSE_CMD_SETSCALE11, 0 }, + { PSMOUSE_CMD_SETSCALE11, 0 }, + { PSMOUSE_CMD_GETINFO, 0 }, + { PSMOUSE_CMD_SETRES, 0x03 }, + { PSMOUSE_CMD_SETRATE, 0xC8 }, + { PSMOUSE_CMD_SETRATE, 0x64 }, + { PSMOUSE_CMD_SETRATE, 0x50 }, + { PSMOUSE_CMD_GETID, 0 }, + { PSMOUSE_CMD_SETRATE, 0xC8 }, + { PSMOUSE_CMD_SETRATE, 0xC8 }, + { PSMOUSE_CMD_SETRATE, 0x50 }, + { PSMOUSE_CMD_GETID, 0 }, + { PSMOUSE_CMD_SETRATE, 0x64 }, + { PSMOUSE_CMD_SETRES, 0x03 }, + { PSMOUSE_CMD_ENABLE, 0 } + }; + + memset(param, 0, sizeof(param)); + for (i = 0; i < ARRAY_SIZE(seq); ++i) { + param[0] = seq[i].arg; + if (ps2_command(ps2dev, param, seq[i].command)) + return -1; + } + + return 0; +} + +static int byd_reset_touchpad(struct psmouse *psmouse) +{ + if (byd_send_intellimouse_sequence(psmouse)) + return -EIO; + + if (byd_enable(psmouse)) + return -EIO; + + return 0; +} + +static int byd_reconnect(struct psmouse *psmouse) +{ + int retry = 0, error = 0; + + psmouse_dbg(psmouse, "Reconnect\n"); + do { + psmouse_reset(psmouse); + if (retry) + ssleep(1); + error = byd_detect(psmouse, 0); + } while (error && ++retry < 3); + + if (error) + return error; + + psmouse_dbg(psmouse, "Reconnected after %d attempts\n", retry); + + error = byd_reset_touchpad(psmouse); + if (error) { + psmouse_err(psmouse, "Unable to initialize device\n"); + return error; + } + + return 0; +} + +int byd_init(struct psmouse *psmouse) +{ + struct input_dev *dev = psmouse->dev; + + if (psmouse_reset(psmouse)) + return -EIO; + + if (byd_reset_touchpad(psmouse)) + return -EIO; + + psmouse->reconnect = byd_reconnect; + psmouse->protocol_handler = byd_process_byte; + psmouse->pktsize = 4; + psmouse->resync_time = 0; + + __set_bit(BTN_MIDDLE, dev->keybit); + __set_bit(REL_WHEEL, dev->relbit); + __set_bit(REL_HWHEEL, dev->relbit); + + return 0; +} diff --git a/drivers/input/mouse/byd.h b/drivers/input/mouse/byd.h new file mode 100644 index 000000000000..d6c120cf36cd --- /dev/null +++ b/drivers/input/mouse/byd.h @@ -0,0 +1,18 @@ +#ifndef _BYD_H +#define _BYD_H + +#ifdef CONFIG_MOUSE_PS2_BYD +int byd_detect(struct psmouse *psmouse, bool set_properties); +int byd_init(struct psmouse *psmouse); +#else +static inline int byd_detect(struct psmouse *psmouse, bool set_properties) +{ + return -ENOSYS; +} +static inline int byd_init(struct psmouse *psmouse) +{ + return -ENOSYS; +} +#endif /* CONFIG_MOUSE_PS2_BYD */ + +#endif /* _BYD_H */ diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index b9e4ee34c132..39d1becd35c9 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -37,6 +37,7 @@ #include "cypress_ps2.h" #include "focaltech.h" #include "vmmouse.h" +#include "byd.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -841,6 +842,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { .detect = vmmouse_detect, .init = vmmouse_init, }, +#endif +#ifdef CONFIG_MOUSE_PS2_BYD + { + .type = PSMOUSE_BYD, + .name = "BydPS/2", + .alias = "byd", + .detect = byd_detect, + .init = byd_init, + }, #endif { .type = PSMOUSE_AUTO, @@ -1105,6 +1115,10 @@ static int psmouse_extensions(struct psmouse *psmouse, if (psmouse_try_protocol(psmouse, PSMOUSE_TOUCHKIT_PS2, &max_proto, set_properties, true)) return PSMOUSE_TOUCHKIT_PS2; + + if (psmouse_try_protocol(psmouse, PSMOUSE_BYD, + &max_proto, set_properties, true)) + return PSMOUSE_BYD; } /* diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index ad5a5a1ea872..e0ca6cda3d16 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -104,6 +104,7 @@ enum psmouse_type { PSMOUSE_CYPRESS, PSMOUSE_FOCALTECH, PSMOUSE_VMMOUSE, + PSMOUSE_BYD, PSMOUSE_AUTO /* This one should always be last */ }; -- cgit From 4332e0144fe44cfc9a9c851f0edcab92ead2adbd Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 20 Jan 2016 13:57:31 -0500 Subject: gpio: 104-idi-48: Allow IRQ sharing The ACCES 104-IDI-48 can differentiate between its own and other devices' interrupt requests. Therefore, IRQ sharing is possible and should be permitted. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idi-48.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 52eed328ce99..285a075e1fd7 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -267,7 +267,8 @@ static int __init idi_48_probe(struct platform_device *pdev) goto err_gpiochip_irqchip_add; } - err = request_irq(irq, idi_48_irq_handler, 0, name, idi48gpio); + err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name, + idi48gpio); if (err) { dev_err(dev, "IRQ handler registering failed (%d)\n", err); goto err_request_irq; -- cgit From 9c26df9b27b67c607f4881551222f36d8bde865b Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 20 Jan 2016 13:45:33 -0500 Subject: gpio: Add GPIO support for the WinSystems WS16C48 The WinSystems WS16C48 device provides 48 lines of digital I/O. In addition, the first 24 lines may be used for interrupt-handled edge detection; rising edge detection and falling edge detection are supported. This driver provides GPIO and IRQ support for these 48 channels of digital I/O. The base port address for the device may be configured via the ws16c48_base module parameter. The interrupt line number for the device may be configured via the ws16c48_irq module parameter. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- MAINTAINERS | 6 + drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ws16c48.c | 436 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 452 insertions(+) create mode 100644 drivers/gpio/gpio-ws16c48.c diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..0ba80b692723 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11871,6 +11871,12 @@ M: David Härdeman S: Maintained F: drivers/media/rc/winbond-cir.c +WINSYSTEMS WS16C48 GPIO DRIVER +M: William Breathitt Gray +L: linux-gpio@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-ws16c48.c + WIMAX STACK M: Inaky Perez-Gonzalez M: linux-wimax@intel.com diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c88dd24a4b1f..b5337f2e0eb4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -570,6 +570,15 @@ config GPIO_TS5500 blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 LCD port. +config GPIO_WS16C48 + tristate "WinSystems WS16C48 GPIO support" + select GPIOLIB_IRQCHIP + help + Enables GPIO support for the WinSystems WS16C48. The base port address + for the device may be configured via the ws16c48_base module + parameter. The interrupt line number for the device may be configured + via the ws16c48_irq module parameter. + endmenu menu "I2C GPIO expanders" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ece7d7cbdc80..73121b1b3b94 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -111,6 +111,7 @@ obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o +obj-$(CONFIG_GPIO_WS16C48) += gpio-ws16c48.o obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c new file mode 100644 index 000000000000..9dd947993476 --- /dev/null +++ b/drivers/gpio/gpio-ws16c48.c @@ -0,0 +1,436 @@ +/* + * GPIO driver for the WinSystems WS16C48 + * Copyright (C) 2016 William Breathitt Gray + * + * 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 + +static unsigned ws16c48_base; +module_param(ws16c48_base, uint, 0); +MODULE_PARM_DESC(ws16c48_base, "WinSystems WS16C48 base address"); +static unsigned ws16c48_irq; +module_param(ws16c48_irq, uint, 0); +MODULE_PARM_DESC(ws16c48_irq, "WinSystems WS16C48 interrupt line number"); + +/** + * struct ws16c48_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @io_state: bit I/O state (whether bit is set to input or output) + * @out_state: output bits state + * @lock: synchronization lock to prevent I/O race conditions + * @irq_mask: I/O bits affected by interrupts + * @flow_mask: IRQ flow type mask for the respective I/O bits + * @base: base port address of the GPIO device + * @extent: extent of port address region of the GPIO device + * @irq: Interrupt line number + */ +struct ws16c48_gpio { + struct gpio_chip chip; + unsigned char io_state[6]; + unsigned char out_state[6]; + spinlock_t lock; + unsigned long irq_mask; + unsigned long flow_mask; + unsigned base; + unsigned extent; + unsigned irq; +}; + +static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + + return !!(ws16c48gpio->io_state[port] & mask); +} + +static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->io_state[port] |= mask; + ws16c48gpio->out_state[port] &= ~mask; + outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return 0; +} + +static int ws16c48_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->io_state[port] &= ~mask; + if (value) + ws16c48gpio->out_state[port] |= mask; + else + ws16c48gpio->out_state[port] &= ~mask; + outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return 0; +} + +static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + unsigned port_state; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + /* ensure that GPIO is set for input */ + if (!(ws16c48gpio->io_state[port] & mask)) { + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return -EINVAL; + } + + port_state = inb(ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return !!(port_state & mask); +} + +static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + /* ensure that GPIO is set for output */ + if (ws16c48gpio->io_state[port] & mask) { + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return; + } + + if (value) + ws16c48gpio->out_state[port] |= mask; + else + ws16c48gpio->out_state[port] &= ~mask; + outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static void ws16c48_irq_ack(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + unsigned long flags; + unsigned port_state; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + port_state = ws16c48gpio->irq_mask >> (8*port); + + outb(0x80, ws16c48gpio->base + 7); + outb(port_state & ~mask, ws16c48gpio->base + 8 + port); + outb(port_state | mask, ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static void ws16c48_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned long mask = BIT(offset); + const unsigned port = offset / 8; + unsigned long flags; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->irq_mask &= ~mask; + + outb(0x80, ws16c48gpio->base + 7); + outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static void ws16c48_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned long mask = BIT(offset); + const unsigned port = offset / 8; + unsigned long flags; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + ws16c48gpio->irq_mask |= mask; + + outb(0x80, ws16c48gpio->base + 7); + outb(ws16c48gpio->irq_mask >> (8*port), ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); +} + +static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + const unsigned long mask = BIT(offset); + const unsigned port = offset / 8; + unsigned long flags; + + /* only the first 3 ports support interrupts */ + if (port > 2) + return -EINVAL; + + spin_lock_irqsave(&ws16c48gpio->lock, flags); + + switch (flow_type) { + case IRQ_TYPE_NONE: + break; + case IRQ_TYPE_EDGE_RISING: + ws16c48gpio->flow_mask |= mask; + break; + case IRQ_TYPE_EDGE_FALLING: + ws16c48gpio->flow_mask &= ~mask; + break; + default: + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return -EINVAL; + } + + outb(0x40, ws16c48gpio->base + 7); + outb(ws16c48gpio->flow_mask >> (8*port), ws16c48gpio->base + 8 + port); + outb(0xC0, ws16c48gpio->base + 7); + + spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + + return 0; +} + +static struct irq_chip ws16c48_irqchip = { + .name = "ws16c48", + .irq_ack = ws16c48_irq_ack, + .irq_mask = ws16c48_irq_mask, + .irq_unmask = ws16c48_irq_unmask, + .irq_set_type = ws16c48_irq_set_type +}; + +static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id) +{ + struct ws16c48_gpio *const ws16c48gpio = dev_id; + struct gpio_chip *const chip = &ws16c48gpio->chip; + unsigned long int_pending; + unsigned long port; + unsigned long int_id; + unsigned long gpio; + + int_pending = inb(ws16c48gpio->base + 6) & 0x7; + if (!int_pending) + return IRQ_NONE; + + /* loop until all pending interrupts are handled */ + do { + for_each_set_bit(port, &int_pending, 3) { + int_id = inb(ws16c48gpio->base + 8 + port); + for_each_set_bit(gpio, &int_id, 8) + generic_handle_irq(irq_find_mapping( + chip->irqdomain, gpio + 8*port)); + } + + int_pending = inb(ws16c48gpio->base + 6) & 0x7; + } while (int_pending); + + return IRQ_HANDLED; +} + +static int __init ws16c48_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct ws16c48_gpio *ws16c48gpio; + const unsigned base = ws16c48_base; + const unsigned extent = 16; + const char *const name = dev_name(dev); + int err; + const unsigned irq = ws16c48_irq; + + ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL); + if (!ws16c48gpio) + return -ENOMEM; + + if (!request_region(base, extent, name)) { + dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", + name, base, base + extent); + err = -EBUSY; + goto err_lock_io_port; + } + + ws16c48gpio->chip.label = name; + ws16c48gpio->chip.parent = dev; + ws16c48gpio->chip.owner = THIS_MODULE; + ws16c48gpio->chip.base = -1; + ws16c48gpio->chip.ngpio = 48; + ws16c48gpio->chip.get_direction = ws16c48_gpio_get_direction; + ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; + ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; + ws16c48gpio->chip.get = ws16c48_gpio_get; + ws16c48gpio->chip.set = ws16c48_gpio_set; + ws16c48gpio->base = base; + ws16c48gpio->extent = extent; + ws16c48gpio->irq = irq; + + spin_lock_init(&ws16c48gpio->lock); + + dev_set_drvdata(dev, ws16c48gpio); + + err = gpiochip_add_data(&ws16c48gpio->chip, ws16c48gpio); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + goto err_gpio_register; + } + + /* Disable IRQ by default */ + outb(0x80, base + 7); + outb(0, base + 8); + outb(0, base + 9); + outb(0, base + 10); + outb(0xC0, base + 7); + + err = gpiochip_irqchip_add(&ws16c48gpio->chip, &ws16c48_irqchip, 0, + handle_edge_irq, IRQ_TYPE_NONE); + if (err) { + dev_err(dev, "Could not add irqchip (%d)\n", err); + goto err_gpiochip_irqchip_add; + } + + err = request_irq(irq, ws16c48_irq_handler, IRQF_SHARED, name, + ws16c48gpio); + if (err) { + dev_err(dev, "IRQ handler registering failed (%d)\n", err); + goto err_request_irq; + } + + return 0; + +err_request_irq: +err_gpiochip_irqchip_add: + gpiochip_remove(&ws16c48gpio->chip); +err_gpio_register: + release_region(base, extent); +err_lock_io_port: + return err; +} + +static int ws16c48_remove(struct platform_device *pdev) +{ + struct ws16c48_gpio *const ws16c48gpio = platform_get_drvdata(pdev); + + free_irq(ws16c48gpio->irq, ws16c48gpio); + gpiochip_remove(&ws16c48gpio->chip); + release_region(ws16c48gpio->base, ws16c48gpio->extent); + + return 0; +} + +static struct platform_device *ws16c48_device; + +static struct platform_driver ws16c48_driver = { + .driver = { + .name = "ws16c48" + }, + .remove = ws16c48_remove +}; + +static void __exit ws16c48_exit(void) +{ + platform_device_unregister(ws16c48_device); + platform_driver_unregister(&ws16c48_driver); +} + +static int __init ws16c48_init(void) +{ + int err; + + ws16c48_device = platform_device_alloc(ws16c48_driver.driver.name, -1); + if (!ws16c48_device) + return -ENOMEM; + + err = platform_device_add(ws16c48_device); + if (err) + goto err_platform_device; + + err = platform_driver_probe(&ws16c48_driver, ws16c48_probe); + if (err) + goto err_platform_driver; + + return 0; + +err_platform_driver: + platform_device_del(ws16c48_device); +err_platform_device: + platform_device_put(ws16c48_device); + return err; +} + +module_init(ws16c48_init); +module_exit(ws16c48_exit); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit From df94e702277e14889af5eef5fbfc3a33261c8b33 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:23 +0100 Subject: ath10k: rename some HTT events New names make a bit more sense. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.c | 8 ++++---- drivers/net/wireless/ath/ath10k/htt.h | 8 ++++---- drivers/net/wireless/ath/ath10k/htt_rx.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 3e6ba63dfdff..7561f22f10f9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -131,12 +131,12 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { [HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF, [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] = HTT_T2H_MSG_TYPE_TX_FETCH_IND, - [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF] = - HTT_T2H_MSG_TYPE_TX_FETCH_CONF, + [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM] = + HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, [HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] = HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, - [HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND] = - HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND, + [HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] = + HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, }; int ath10k_htt_connect(struct ath10k_htt *htt) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 47ca048feaf0..edd3b9070de9 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -413,10 +413,10 @@ enum htt_10_4_t2h_msg_type { HTT_10_4_T2H_MSG_TYPE_EN_STATS = 0x14, HTT_10_4_T2H_MSG_TYPE_AGGR_CONF = 0x15, HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND = 0x16, - HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF = 0x17, + HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM = 0x17, HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, /* 0x19 to 0x2f are reserved */ - HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND = 0x30, + HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30, /* keep this last */ HTT_10_4_T2H_NUM_MSGS }; @@ -449,8 +449,8 @@ enum htt_t2h_msg_type { HTT_T2H_MSG_TYPE_TEST, HTT_T2H_MSG_TYPE_EN_STATS, HTT_T2H_MSG_TYPE_TX_FETCH_IND, - HTT_T2H_MSG_TYPE_TX_FETCH_CONF, - HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND, + HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, + HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, /* keep this last */ HTT_T2H_NUM_MSGS }; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 3079434b5d9b..84abe4f25c73 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2125,8 +2125,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; case HTT_T2H_MSG_TYPE_EN_STATS: case HTT_T2H_MSG_TYPE_TX_FETCH_IND: - case HTT_T2H_MSG_TYPE_TX_FETCH_CONF: - case HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND: + case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: + case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: default: ath10k_warn(ar, "htt event (%d) not handled\n", resp->hdr.msg_type); -- cgit From 22e6b3bc5d9668dc711665d255efad89c527b4d6 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:24 +0100 Subject: ath10k: add new htt definitions These definitions are associated with some improvements upcomming for 10.4 and QCA99X0. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 153 +++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index edd3b9070de9..0c5628dafabf 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -52,6 +52,7 @@ enum htt_h2t_msg_type { /* host-to-target */ /* This command is used for sending management frames in HTT < 3.0. * HTT >= 3.0 uses TX_FRM for everything. */ HTT_H2T_MSG_TYPE_MGMT_TX = 7, + HTT_H2T_MSG_TYPE_TX_FETCH_RESP = 11, HTT_H2T_NUM_MSGS /* keep this last */ }; @@ -1306,9 +1307,43 @@ struct htt_frag_desc_bank_id { * so we use a conservatively safe value for now */ #define HTT_FRAG_DESC_BANK_MAX 4 -#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 -#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 -#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP (1 << 2) +#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03 +#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0 +#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP BIT(2) +#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID BIT(3) +#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_MASK BIT(4) +#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_LSB 4 + +enum htt_q_depth_type { + HTT_Q_DEPTH_TYPE_BYTES = 0, + HTT_Q_DEPTH_TYPE_MSDUS = 1, +}; + +#define HTT_TX_Q_STATE_NUM_PEERS (TARGET_10_4_NUM_QCACHE_PEERS_MAX + \ + TARGET_10_4_NUM_VDEVS) +#define HTT_TX_Q_STATE_NUM_TIDS 8 +#define HTT_TX_Q_STATE_ENTRY_SIZE 1 +#define HTT_TX_Q_STATE_ENTRY_MULTIPLIER 0 + +/** + * htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config + * + * Defines host q state format and behavior. See htt_q_state. + * + * @record_size: Defines the size of each host q entry in bytes. In practice + * however firmware (at least 10.4.3-00191) ignores this host + * configuration value and uses hardcoded value of 1. + * @record_multiplier: This is valid only when q depth type is MSDUs. It + * defines the exponent for the power of 2 multiplication. + */ +struct htt_q_state_conf { + __le32 paddr; + __le16 num_peers; + __le16 num_tids; + u8 record_size; + u8 record_multiplier; + u8 pad[2]; +} __packed; struct htt_frag_desc_bank_cfg { u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */ @@ -1316,6 +1351,114 @@ struct htt_frag_desc_bank_cfg { u8 desc_size; __le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX]; struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX]; + struct htt_q_state_conf q_state; +} __packed; + +#define HTT_TX_Q_STATE_ENTRY_COEFFICIENT 128 +#define HTT_TX_Q_STATE_ENTRY_FACTOR_MASK 0x3f +#define HTT_TX_Q_STATE_ENTRY_FACTOR_LSB 0 +#define HTT_TX_Q_STATE_ENTRY_EXP_MASK 0xc0 +#define HTT_TX_Q_STATE_ENTRY_EXP_LSB 6 + +/** + * htt_q_state - shared between host and firmware via DMA + * + * This structure is used for the host to expose it's software queue state to + * firmware so that its rate control can schedule fetch requests for optimized + * performance. This is most notably used for MU-MIMO aggregation when multiple + * MU clients are connected. + * + * @count: Each element defines the host queue depth. When q depth type was + * configured as HTT_Q_DEPTH_TYPE_BYTES then each entry is defined as: + * FACTOR * 128 * 8^EXP (see HTT_TX_Q_STATE_ENTRY_FACTOR_MASK and + * HTT_TX_Q_STATE_ENTRY_EXP_MASK). When q depth type was configured as + * HTT_Q_DEPTH_TYPE_MSDUS the number of packets is scaled by 2 ** + * record_multiplier (see htt_q_state_conf). + * @map: Used by firmware to quickly check which host queues are not empty. It + * is a bitmap simply saying. + * @seq: Used by firmware to quickly check if the host queues were updated + * since it last checked. + * + * FIXME: Is the q_state map[] size calculation really correct? + */ +struct htt_q_state { + u8 count[HTT_TX_Q_STATE_NUM_TIDS][HTT_TX_Q_STATE_NUM_PEERS]; + u32 map[HTT_TX_Q_STATE_NUM_TIDS][(HTT_TX_Q_STATE_NUM_PEERS + 31) / 32]; + __le32 seq; +} __packed; + +#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_MASK 0x0fff +#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_LSB 0 +#define HTT_TX_FETCH_RECORD_INFO_TID_MASK 0xf000 +#define HTT_TX_FETCH_RECORD_INFO_TID_LSB 12 + +struct htt_tx_fetch_record { + __le16 info; /* HTT_TX_FETCH_IND_RECORD_INFO_ */ + __le16 num_msdus; + __le32 num_bytes; +} __packed; + +struct htt_tx_fetch_ind { + u8 pad0; + __le16 fetch_seq_num; + __le32 token; + __le16 num_resp_ids; + __le16 num_records; + struct htt_tx_fetch_record records[0]; + __le32 resp_ids[0]; /* ath10k_htt_get_tx_fetch_ind_resp_ids() */ +} __packed; + +static inline void * +ath10k_htt_get_tx_fetch_ind_resp_ids(struct htt_tx_fetch_ind *ind) +{ + return (void *)&ind->records[le16_to_cpu(ind->num_records)]; +} + +struct htt_tx_fetch_resp { + u8 pad0; + __le16 resp_id; + __le16 fetch_seq_num; + __le16 num_records; + __le32 token; + struct htt_tx_fetch_record records[0]; +} __packed; + +struct htt_tx_fetch_confirm { + u8 pad0; + __le16 num_resp_ids; + __le32 resp_ids[0]; +} __packed; + +enum htt_tx_mode_switch_mode { + HTT_TX_MODE_SWITCH_PUSH = 0, + HTT_TX_MODE_SWITCH_PUSH_PULL = 1, +}; + +#define HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE BIT(0) +#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_MASK 0xfffe +#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_LSB 1 + +#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_MASK 0x0003 +#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_LSB 0 +#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_MASK 0xfffc +#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_LSB 2 + +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_MASK 0x0fff +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_LSB 0 +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_MASK 0xf000 +#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_LSB 12 + +struct htt_tx_mode_switch_record { + __le16 info0; /* HTT_TX_MODE_SWITCH_RECORD_INFO0_ */ + __le16 num_max_msdus; +} __packed; + +struct htt_tx_mode_switch_ind { + u8 pad0; + __le16 info0; /* HTT_TX_MODE_SWITCH_IND_INFO0_ */ + __le16 info1; /* HTT_TX_MODE_SWITCH_IND_INFO1_ */ + u8 pad1[2]; + struct htt_tx_mode_switch_record records[0]; } __packed; union htt_rx_pn_t { @@ -1340,6 +1483,7 @@ struct htt_cmd { struct htt_oob_sync_req oob_sync_req; struct htt_aggr_conf aggr_conf; struct htt_frag_desc_bank_cfg frag_desc_bank_cfg; + struct htt_tx_fetch_resp tx_fetch_resp; }; } __packed; @@ -1364,6 +1508,9 @@ struct htt_resp { struct htt_rx_pn_ind rx_pn_ind; struct htt_rx_offload_ind rx_offload_ind; struct htt_rx_in_ord_ind rx_in_ord_ind; + 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; }; } __packed; -- cgit From 9b783763aa9623dedeed77bec158f7377cb87750 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:25 +0100 Subject: ath10k: add new FW_FEATURE_PEER_FLOW_CONTROL This feature flag will be used for firmware which supports pull-push model where host shares it's software queue state with firmware and firmware generates fetch requests telling host which queues to dequeue tx from. Primary function of this is improved MU-MIMO performance with multiple clients. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 1 + drivers/net/wireless/ath/ath10k/core.h | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b41eb3f4ee56..48a26206c5c1 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -217,6 +217,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", [ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp", + [ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 921b86a4f257..5067a0ff4e89 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -512,6 +512,15 @@ enum ath10k_fw_features { /* Firmware supports management frame protection */ ATH10K_FW_FEATURE_MFP_SUPPORT = 12, + /* Firmware supports pull-push model where host shares it's software + * queue state with firmware and firmware generates fetch requests + * telling host which queues to dequeue tx from. + * + * Primary function of this is improved MU-MIMO performance with + * multiple clients. + */ + ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; -- cgit From 575fc89500d37839eb24ecd258982b24edefed6f Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:26 +0100 Subject: ath10k: clean up cont frag desc init code This makes the code easier to extend and re-use. While at it fix _warn to _err. Other than that there are no functional changes. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt_tx.c | 58 ++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index b3adadb5f824..28b8d7af8506 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -97,6 +97,41 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) idr_remove(&htt->pending_tx, msdu_id); } +static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt) +{ + size_t size; + + if (!htt->frag_desc.vaddr) + return; + + size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); + + dma_free_coherent(htt->ar->dev, + size, + htt->frag_desc.vaddr, + htt->frag_desc.paddr); +} + +static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) +{ + struct ath10k *ar = htt->ar; + size_t size; + + if (!ar->hw_params.continuous_frag_desc) + return 0; + + size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); + htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size, + &htt->frag_desc.paddr, + GFP_KERNEL); + if (!htt->frag_desc.vaddr) { + ath10k_err(ar, "failed to alloc fragment desc memory\n"); + return -ENOMEM; + } + + return 0; +} + int ath10k_htt_tx_alloc(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; @@ -118,20 +153,12 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) goto free_idr_pending_tx; } - if (!ar->hw_params.continuous_frag_desc) - goto skip_frag_desc_alloc; - - size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc); - htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size, - &htt->frag_desc.paddr, - GFP_KERNEL); - if (!htt->frag_desc.vaddr) { - ath10k_warn(ar, "failed to alloc fragment desc memory\n"); - ret = -ENOMEM; + ret = ath10k_htt_tx_alloc_cont_frag_desc(htt); + if (ret) { + ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret); goto free_txbuf; } -skip_frag_desc_alloc: return 0; free_txbuf: @@ -139,8 +166,10 @@ free_txbuf: sizeof(struct ath10k_htt_txbuf); dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); + free_idr_pending_tx: idr_destroy(&htt->pending_tx); + return ret; } @@ -174,12 +203,7 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) htt->txbuf.paddr); } - if (htt->frag_desc.vaddr) { - size = htt->max_num_pending_tx * - sizeof(struct htt_msdu_ext_desc); - dma_free_coherent(htt->ar->dev, size, htt->frag_desc.vaddr, - htt->frag_desc.paddr); - } + ath10k_htt_tx_free_cont_frag_desc(htt); } void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) -- cgit From 9b15873628050fe59ebbfae200be7d50ce5e1491 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Thu, 21 Jan 2016 14:13:27 +0100 Subject: ath10k: implement basic support for new tx path firmware This allows to use the new firmware which implements the new tx data path. Without this patch firmware supporting new tx path stops responding shortly after booting. This patch doesn't implement the entire pull-push logic available in the new firmware. This will be done in subsequent patches. Signed-off-by: Michal Kazior Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/htt.h | 8 +++ drivers/net/wireless/ath/ath10k/htt_rx.c | 4 +- drivers/net/wireless/ath/ath10k/htt_tx.c | 88 +++++++++++++++++++++++++++++--- 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 0c5628dafabf..13391ea4422d 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1665,6 +1665,14 @@ struct ath10k_htt { dma_addr_t paddr; struct ath10k_htt_txbuf *vaddr; } txbuf; + + struct { + struct htt_q_state *vaddr; + dma_addr_t paddr; + u16 num_peers; + u16 num_tids; + enum htt_q_depth_type type; + } tx_q_state; }; #define RX_HTT_HDR_STATUS_LEN 64 diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 84abe4f25c73..cc957a625605 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2123,10 +2123,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) break; case HTT_T2H_MSG_TYPE_AGGR_CONF: break; - case HTT_T2H_MSG_TYPE_EN_STATS: case HTT_T2H_MSG_TYPE_TX_FETCH_IND: case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM: case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND: + /* TODO: Implement pull-push logic */ + break; + case HTT_T2H_MSG_TYPE_EN_STATS: default: ath10k_warn(ar, "htt event (%d) not handled\n", resp->hdr.msg_type); diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index 28b8d7af8506..95acb727c068 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -132,6 +132,50 @@ static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt) return 0; } +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)) + return; + + size = sizeof(*htt->tx_q_state.vaddr); + + dma_unmap_single(ar->dev, htt->tx_q_state.paddr, size, DMA_TO_DEVICE); + kfree(htt->tx_q_state.vaddr); +} + +static int ath10k_htt_tx_alloc_txq(struct ath10k_htt *htt) +{ + struct ath10k *ar = htt->ar; + size_t size; + int ret; + + if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, ar->fw_features)) + return 0; + + htt->tx_q_state.num_peers = HTT_TX_Q_STATE_NUM_PEERS; + htt->tx_q_state.num_tids = HTT_TX_Q_STATE_NUM_TIDS; + htt->tx_q_state.type = HTT_Q_DEPTH_TYPE_BYTES; + + size = sizeof(*htt->tx_q_state.vaddr); + htt->tx_q_state.vaddr = kzalloc(size, GFP_KERNEL); + if (!htt->tx_q_state.vaddr) + return -ENOMEM; + + htt->tx_q_state.paddr = dma_map_single(ar->dev, htt->tx_q_state.vaddr, + size, DMA_TO_DEVICE); + ret = dma_mapping_error(ar->dev, htt->tx_q_state.paddr); + if (ret) { + ath10k_warn(ar, "failed to dma map tx_q_state: %d\n", ret); + kfree(htt->tx_q_state.vaddr); + return -EIO; + } + + return 0; +} + int ath10k_htt_tx_alloc(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; @@ -159,8 +203,17 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) goto free_txbuf; } + ret = ath10k_htt_tx_alloc_txq(htt); + if (ret) { + ath10k_err(ar, "failed to alloc txq: %d\n", ret); + goto free_frag_desc; + } + return 0; +free_frag_desc: + ath10k_htt_tx_free_cont_frag_desc(htt); + free_txbuf: size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); @@ -203,6 +256,7 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) htt->txbuf.paddr); } + ath10k_htt_tx_free_txq(htt); ath10k_htt_tx_free_cont_frag_desc(htt); } @@ -292,7 +346,9 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; struct sk_buff *skb; struct htt_cmd *cmd; + struct htt_frag_desc_bank_cfg *cfg; int ret, size; + u8 info; if (!ar->hw_params.continuous_frag_desc) return 0; @@ -310,14 +366,30 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt) skb_put(skb, size); cmd = (struct htt_cmd *)skb->data; cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG; - cmd->frag_desc_bank_cfg.info = 0; - cmd->frag_desc_bank_cfg.num_banks = 1; - cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc); - cmd->frag_desc_bank_cfg.bank_base_addrs[0] = - __cpu_to_le32(htt->frag_desc.paddr); - cmd->frag_desc_bank_cfg.bank_id[0].bank_min_id = 0; - cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id = - __cpu_to_le16(htt->max_num_pending_tx - 1); + + info = 0; + 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)) + info |= HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID; + + cfg = &cmd->frag_desc_bank_cfg; + cfg->info = info; + cfg->num_banks = 1; + cfg->desc_size = sizeof(struct htt_msdu_ext_desc); + cfg->bank_base_addrs[0] = __cpu_to_le32(htt->frag_desc.paddr); + cfg->bank_id[0].bank_min_id = 0; + cfg->bank_id[0].bank_max_id = __cpu_to_le16(htt->max_num_pending_tx - + 1); + + cfg->q_state.paddr = cpu_to_le32(htt->tx_q_state.paddr); + cfg->q_state.num_peers = cpu_to_le16(htt->tx_q_state.num_peers); + cfg->q_state.num_tids = cpu_to_le16(htt->tx_q_state.num_tids); + cfg->q_state.record_size = HTT_TX_Q_STATE_ENTRY_SIZE; + cfg->q_state.record_multiplier = HTT_TX_Q_STATE_ENTRY_MULTIPLIER; + + ath10k_dbg(ar, ATH10K_DBG_HTT, "htt frag desc bank cmd\n"); ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); if (ret) { -- cgit From f52f517189dea69614bbee9ec5ab2fe366905b16 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:22 +0530 Subject: ath10k: make some of ath10k_pci_* func reusable Some of static functions present in pci.c file are reusable in ahb (qca4019) case. Remove static word for those reusable functions and have those function prototype declaration in pci.h file. So that, pci.h header file can be included in ahb module and reused. There is no functionality changes done in this patch. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 63 +++++++++++++++++------------------ drivers/net/wireless/ath/ath10k/pci.h | 32 ++++++++++++++++++ 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index ee925c618535..956e548fd4a7 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -94,7 +94,6 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = { static void ath10k_pci_buffer_cleanup(struct ath10k *ar); static int ath10k_pci_cold_reset(struct ath10k *ar); static int ath10k_pci_safe_chip_reset(struct ath10k *ar); -static int ath10k_pci_wait_for_target_init(struct ath10k *ar); static int ath10k_pci_init_irq(struct ath10k *ar); static int ath10k_pci_deinit_irq(struct ath10k *ar); static int ath10k_pci_request_irq(struct ath10k *ar); @@ -687,7 +686,7 @@ void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val) ath10k_pci_write32(ar, PCIE_LOCAL_BASE_ADDRESS + addr, val); } -static bool ath10k_pci_irq_pending(struct ath10k *ar) +bool ath10k_pci_irq_pending(struct ath10k *ar) { u32 cause; @@ -700,7 +699,7 @@ static bool ath10k_pci_irq_pending(struct ath10k *ar) return false; } -static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) +void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) { /* IMPORTANT: INTR_CLR register has to be set after * INTR_ENABLE is set to 0, otherwise interrupt can not be @@ -716,7 +715,7 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) PCIE_INTR_ENABLE_ADDRESS); } -static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) +void ath10k_pci_enable_legacy_irq(struct ath10k *ar) { ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + PCIE_INTR_ENABLE_ADDRESS, @@ -809,7 +808,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) } } -static void ath10k_pci_rx_post(struct ath10k *ar) +void ath10k_pci_rx_post(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; @@ -818,7 +817,7 @@ static void ath10k_pci_rx_post(struct ath10k *ar) ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); } -static void ath10k_pci_rx_replenish_retry(unsigned long ptr) +void ath10k_pci_rx_replenish_retry(unsigned long ptr) { struct ath10k *ar = (void *)ptr; @@ -1007,8 +1006,8 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest, #define ath10k_pci_diag_read_hi(ar, dest, src, len) \ __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len) -static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, - const void *data, int nbytes) +int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, + const void *data, int nbytes) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret = 0; @@ -1263,8 +1262,8 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); } -static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, - struct ath10k_hif_sg_item *items, int n_items) +int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, + struct ath10k_hif_sg_item *items, int n_items) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id]; @@ -1332,13 +1331,13 @@ err: return err; } -static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, - size_t buf_len) +int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len) { return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); } -static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) +u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); @@ -1406,8 +1405,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) queue_work(ar->workqueue, &ar->restart_work); } -static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, - int force) +void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, + int force) { ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif send complete check\n"); @@ -1432,7 +1431,7 @@ static void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, ath10k_ce_per_engine_service(ar, pipe); } -static void ath10k_pci_kill_tasklet(struct ath10k *ar) +void ath10k_pci_kill_tasklet(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; @@ -1446,8 +1445,8 @@ static void ath10k_pci_kill_tasklet(struct ath10k *ar) del_timer_sync(&ar_pci->rx_post_retry); } -static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, - u8 *ul_pipe, u8 *dl_pipe) +int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe) { const struct service_to_pipe *entry; bool ul_set = false, dl_set = false; @@ -1491,8 +1490,8 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, return 0; } -static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, - u8 *ul_pipe, u8 *dl_pipe) +void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, + u8 *ul_pipe, u8 *dl_pipe) { ath10k_dbg(ar, ATH10K_DBG_PCI, "pci hif get default pipe\n"); @@ -1668,7 +1667,7 @@ static void ath10k_pci_buffer_cleanup(struct ath10k *ar) } } -static void ath10k_pci_ce_deinit(struct ath10k *ar) +void ath10k_pci_ce_deinit(struct ath10k *ar) { int i; @@ -1676,7 +1675,7 @@ static void ath10k_pci_ce_deinit(struct ath10k *ar) ath10k_ce_deinit_pipe(ar, i); } -static void ath10k_pci_flush(struct ath10k *ar) +void ath10k_pci_flush(struct ath10k *ar) { ath10k_pci_kill_tasklet(ar); ath10k_pci_buffer_cleanup(ar); @@ -1711,9 +1710,9 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) spin_unlock_irqrestore(&ar_pci->ps_lock, flags); } -static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, - void *req, u32 req_len, - void *resp, u32 *resp_len) +int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, + void *req, u32 req_len, + void *resp, u32 *resp_len) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pci_tx = &ar_pci->pipe_info[BMI_CE_NUM_TO_TARG]; @@ -1907,7 +1906,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 1; } -static int ath10k_pci_init_config(struct ath10k *ar) +int ath10k_pci_init_config(struct ath10k *ar) { u32 interconnect_targ_addr; u32 pcie_state_targ_addr = 0; @@ -2071,7 +2070,7 @@ static void ath10k_pci_override_ce_config(struct ath10k *ar) target_service_to_ce_map_wlan[15].pipenum = __cpu_to_le32(1); } -static int ath10k_pci_alloc_pipes(struct ath10k *ar) +int ath10k_pci_alloc_pipes(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci_pipe *pipe; @@ -2102,7 +2101,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar) return 0; } -static void ath10k_pci_free_pipes(struct ath10k *ar) +void ath10k_pci_free_pipes(struct ath10k *ar) { int i; @@ -2110,7 +2109,7 @@ static void ath10k_pci_free_pipes(struct ath10k *ar) ath10k_ce_free_pipe(ar, i); } -static int ath10k_pci_init_pipes(struct ath10k *ar) +int ath10k_pci_init_pipes(struct ath10k *ar) { int i, ret; @@ -2453,7 +2452,7 @@ err_sleep: return ret; } -static void ath10k_pci_hif_power_down(struct ath10k *ar) +void ath10k_pci_hif_power_down(struct ath10k *ar) { ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); @@ -2722,7 +2721,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar) free_irq(ar_pci->pdev->irq + i, ar); } -static void ath10k_pci_init_irq_tasklets(struct ath10k *ar) +void ath10k_pci_init_irq_tasklets(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int i; @@ -2808,7 +2807,7 @@ static int ath10k_pci_deinit_irq(struct ath10k *ar) return 0; } -static int ath10k_pci_wait_for_target_init(struct ath10k *ar) +int ath10k_pci_wait_for_target_init(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); unsigned long timeout; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index f91bf333cb75..ae76131aa081 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -253,6 +253,38 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset); u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr); u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr); +int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, + struct ath10k_hif_sg_item *items, int n_items); +int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, + size_t buf_len); +int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, + const void *data, int nbytes); +int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, void *req, u32 req_len, + void *resp, u32 *resp_len); +int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, u16 service_id, + u8 *ul_pipe, u8 *dl_pipe); +void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, u8 *ul_pipe, + u8 *dl_pipe); +void ath10k_pci_hif_send_complete_check(struct ath10k *ar, u8 pipe, + int force); +u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe); +void ath10k_pci_hif_power_down(struct ath10k *ar); +int ath10k_pci_alloc_pipes(struct ath10k *ar); +void ath10k_pci_free_pipes(struct ath10k *ar); +void ath10k_pci_free_pipes(struct ath10k *ar); +void ath10k_pci_rx_replenish_retry(unsigned long ptr); +void ath10k_pci_ce_deinit(struct ath10k *ar); +void ath10k_pci_init_irq_tasklets(struct ath10k *ar); +void ath10k_pci_kill_tasklet(struct ath10k *ar); +int ath10k_pci_init_pipes(struct ath10k *ar); +int ath10k_pci_init_config(struct ath10k *ar); +void ath10k_pci_rx_post(struct ath10k *ar); +void ath10k_pci_flush(struct ath10k *ar); +void ath10k_pci_enable_legacy_irq(struct ath10k *ar); +bool ath10k_pci_irq_pending(struct ath10k *ar); +void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar); +int ath10k_pci_wait_for_target_init(struct ath10k *ar); + /* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too * frequently. To avoid this put SoC to sleep after a very conservative grace * period. Adjust with great care. -- cgit From 4ddb3299aa49ddeb40680d7427d3259d32aefa6d Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:23 +0530 Subject: ath10k: make ath10k_pci_read32/write32() ops more generic ath10k_pci_read32/write32() does work more specific to PCI by ensuring pci wake/sleep for every read and write. There is a plan to use most of stuff available in pci.c (irq stuff, copy engine, etc) for AHB case. Such kind of pci wake/sleep for every read/write is not required in AHB case (qca4019). All those reusable areas in pci.c and ce.c calls ath10k_pci_read32/write32() for low level read and write. In fact, ath10k_pci_read32/write32() should do what it does today for PCI case. But for AHB, it has to do differently. To make ath10k_pci_read32/write32() more generic, new function pointers are added in ar_pci for the function which does operation more close to the bus. Later, corresponding bus specific read and write function will be mapped to that. ath10k_pci_read32/write32() are changed to call directly those function pointers without worrying which bus underlying to it. Also, the function to get number of bank is changed in the same way. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 34 +++++++++++++++++++++++++++++++--- drivers/net/wireless/ath/ath10k/pci.h | 8 ++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 956e548fd4a7..c5f6604fa76d 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -619,7 +619,7 @@ static void ath10k_pci_sleep_sync(struct ath10k *ar) spin_unlock_irqrestore(&ar_pci->ps_lock, flags); } -void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) +static void ath10k_bus_pci_write32(struct ath10k *ar, u32 offset, u32 value) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; @@ -641,7 +641,7 @@ void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) ath10k_pci_sleep(ar); } -u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) +static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); u32 val; @@ -666,6 +666,20 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) return val; } +inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + ar_pci->bus_ops->write32(ar, offset, value); +} + +inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + return ar_pci->bus_ops->read32(ar, offset); +} + u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) { return ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + addr); @@ -1906,6 +1920,13 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar) return 1; } +static int ath10k_bus_get_num_banks(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + return ar_pci->bus_ops->get_num_banks(ar); +} + int ath10k_pci_init_config(struct ath10k *ar) { u32 interconnect_targ_addr; @@ -2017,7 +2038,7 @@ int ath10k_pci_init_config(struct ath10k *ar) /* first bank is switched to IRAM */ ealloc_value |= ((HI_EARLY_ALLOC_MAGIC << HI_EARLY_ALLOC_MAGIC_SHIFT) & HI_EARLY_ALLOC_MAGIC_MASK); - ealloc_value |= ((ath10k_pci_get_num_banks(ar) << + ealloc_value |= ((ath10k_bus_get_num_banks(ar) << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & HI_EARLY_ALLOC_IRAM_BANKS_MASK); @@ -2988,6 +3009,12 @@ static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id) return false; } +static const struct ath10k_bus_ops ath10k_pci_bus_ops = { + .read32 = ath10k_bus_pci_read32, + .write32 = ath10k_bus_pci_write32, + .get_num_banks = ath10k_pci_get_num_banks, +}; + static int ath10k_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_dev) { @@ -3038,6 +3065,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->ar = ar; ar->dev_id = pci_dev->device; ar_pci->pci_ps = pci_ps; + ar_pci->bus_ops = &ath10k_pci_bus_ops; ar->id.vendor = pdev->vendor; ar->id.device = pdev->device; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index ae76131aa081..41f3faced84c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -157,6 +157,12 @@ struct ath10k_pci_supp_chip { u32 rev_id; }; +struct ath10k_bus_ops { + u32 (*read32)(struct ath10k *ar, u32 offset); + void (*write32)(struct ath10k *ar, u32 offset, u32 value); + int (*get_num_banks)(struct ath10k *ar); +}; + struct ath10k_pci { struct pci_dev *pdev; struct device *dev; @@ -225,6 +231,8 @@ struct ath10k_pci { * on MMIO read/write. */ bool pci_ps; + + const struct ath10k_bus_ops *bus_ops; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) -- cgit From 90188f807f2a8bada8e165b932b56f7e03b0a9b9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:24 +0530 Subject: ath10k: pull reusable code from pci probe and remove for ahb Some of the code present in ath10k_pci_{probe|remove} are reusable in ahb case too. To avoid code duplication, move reusable code to new functions. Later, those new functions can be called from ahb module's probe and exit functions. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/pci.c | 64 +++++++++++++++++++++++------------ drivers/net/wireless/ath/ath10k/pci.h | 2 ++ 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index c5f6604fa76d..6ef878c1eebc 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3009,6 +3009,37 @@ static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id) return false; } +int ath10k_pci_setup_resource(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + int ret; + + spin_lock_init(&ar_pci->ce_lock); + spin_lock_init(&ar_pci->ps_lock); + + setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, + (unsigned long)ar); + + if (QCA_REV_6174(ar)) + ath10k_pci_override_ce_config(ar); + + ret = ath10k_pci_alloc_pipes(ar); + if (ret) { + ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", + ret); + return ret; + } + + return 0; +} + +void ath10k_pci_release_resource(struct ath10k *ar) +{ + ath10k_pci_kill_tasklet(ar); + ath10k_pci_ce_deinit(ar); + ath10k_pci_free_pipes(ar); +} + static const struct ath10k_bus_ops ath10k_pci_bus_ops = { .read32 = ath10k_bus_pci_read32, .write32 = ath10k_bus_pci_write32, @@ -3072,34 +3103,25 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar->id.subsystem_vendor = pdev->subsystem_vendor; ar->id.subsystem_device = pdev->subsystem_device; - spin_lock_init(&ar_pci->ce_lock); - spin_lock_init(&ar_pci->ps_lock); - - setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, - (unsigned long)ar); setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, (unsigned long)ar); - ret = ath10k_pci_claim(ar); + ret = ath10k_pci_setup_resource(ar); if (ret) { - ath10k_err(ar, "failed to claim device: %d\n", ret); + ath10k_err(ar, "failed to setup resource: %d\n", ret); goto err_core_destroy; } - if (QCA_REV_6174(ar)) - ath10k_pci_override_ce_config(ar); - - ret = ath10k_pci_alloc_pipes(ar); + ret = ath10k_pci_claim(ar); if (ret) { - ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", - ret); - goto err_sleep; + ath10k_err(ar, "failed to claim device: %d\n", ret); + goto err_free_pipes; } ret = ath10k_pci_force_wake(ar); if (ret) { ath10k_warn(ar, "failed to wake up device : %d\n", ret); - goto err_free_pipes; + goto err_sleep; } ath10k_pci_ce_deinit(ar); @@ -3108,7 +3130,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ret = ath10k_pci_init_irq(ar); if (ret) { ath10k_err(ar, "failed to init irqs: %d\n", ret); - goto err_free_pipes; + goto err_sleep; } ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", @@ -3154,13 +3176,13 @@ err_free_irq: err_deinit_irq: ath10k_pci_deinit_irq(ar); -err_free_pipes: - ath10k_pci_free_pipes(ar); - err_sleep: ath10k_pci_sleep_sync(ar); ath10k_pci_release(ar); +err_free_pipes: + ath10k_pci_free_pipes(ar); + err_core_destroy: ath10k_core_destroy(ar); @@ -3184,10 +3206,8 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ath10k_core_unregister(ar); ath10k_pci_free_irq(ar); - ath10k_pci_kill_tasklet(ar); ath10k_pci_deinit_irq(ar); - ath10k_pci_ce_deinit(ar); - ath10k_pci_free_pipes(ar); + ath10k_pci_release_resource(ar); ath10k_pci_sleep_sync(ar); ath10k_pci_release(ar); ath10k_core_destroy(ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 41f3faced84c..fcfdbca8e55e 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -292,6 +292,8 @@ void ath10k_pci_enable_legacy_irq(struct ath10k *ar); bool ath10k_pci_irq_pending(struct ath10k *ar); void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar); int ath10k_pci_wait_for_target_init(struct ath10k *ar); +int ath10k_pci_setup_resource(struct ath10k *ar); +void ath10k_pci_release_resource(struct ath10k *ar); /* QCA6174 is known to have Tx/Rx issues when SOC_WAKE register is poked too * frequently. To avoid this put SoC to sleep after a very conservative grace -- cgit From 0b523ced9a3cd05abf240e913b2d80e7d0fa3478 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:25 +0530 Subject: ath10k: add basic skeleton to support ahb qca4019 uses ahb instead of pci where it slightly differs in device enumeration, clock control, reset control, etc. Good thing is that ahb also uses copy engine for the data transaction. So, the most of the stuff implemented in pci.c/ce.c are reusable in ahb case too. Device enumeration in ahb case comes through platform driver/device model. All resource details like irq, memory map, clocks, etc for qca4019 can be fetched from of_node of platform device. Simply flow would look like, device tree => platform device (kernel) => platform driver (ath10k) Device tree entry will have all qca4019 resource details and the same info will be passed to kernel. Kernel will prepare new platform device for that entry and expose DT info to of_node in platform device. Later, ath10k would register platform driver with unique compatible name and then kernels binds to corresponding compatible entry & calls ath10k ahb probe functions. From there onwards, ath10k will take control of it and move forward. New bool flag CONFIG_ATH10K_AHB is added in Kconfig to conditionally enable ahb support in ath10k. On enabling this flag, ath10k_pci.ko will have ahb support. This patch adds only basic skeleton and few macros to support ahb in the context of qca4019. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/Kconfig | 6 +++ drivers/net/wireless/ath/ath10k/Makefile | 2 + drivers/net/wireless/ath/ath10k/ahb.c | 67 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 41 +++++++++++++++++++ drivers/net/wireless/ath/ath10k/core.h | 3 ++ drivers/net/wireless/ath/ath10k/debug.h | 1 + drivers/net/wireless/ath/ath10k/hw.h | 2 + drivers/net/wireless/ath/ath10k/pci.c | 8 ++++ drivers/net/wireless/ath/ath10k/pci.h | 1 + 9 files changed, 131 insertions(+) create mode 100644 drivers/net/wireless/ath/ath10k/ahb.c create mode 100644 drivers/net/wireless/ath/ath10k/ahb.h diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 03aa35f999a1..d7f207a6b0e0 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -15,6 +15,12 @@ config ATH10K_PCI ---help--- This module adds support for PCIE bus +config ATH10K_AHB + bool "Atheros ath10k AHB support" + depends on ATH10K_PCI && OF + ---help--- + This module adds support for AHB bus + config ATH10K_DEBUG bool "Atheros ath10k debugging" depends on ATH10K diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index c04fb00e7930..930fadd940d8 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -25,5 +25,7 @@ obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o ath10k_pci-y += pci.o \ ce.o +ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o + # for tracing framework to find trace.h CFLAGS_trace.o := -I$(src) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c new file mode 100644 index 000000000000..129f4f4491d0 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. + * 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 +#include "core.h" +#include "debug.h" +#include "ahb.h" + +static const struct of_device_id ath10k_ahb_of_match[] = { + /* TODO: enable this entry once everything in place. + * { .compatible = "qcom,ipq4019-wifi", + * .data = (void *)ATH10K_HW_QCA4019 }, + */ + { } +}; + +MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); + +static int ath10k_ahb_probe(struct platform_device *pdev) +{ + return 0; +} + +static int ath10k_ahb_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver ath10k_ahb_driver = { + .driver = { + .name = "ath10k_ahb", + .of_match_table = ath10k_ahb_of_match, + }, + .probe = ath10k_ahb_probe, + .remove = ath10k_ahb_remove, +}; + +int ath10k_ahb_init(void) +{ + int ret; + + printk(KERN_ERR "AHB support is still work in progress\n"); + + ret = platform_driver_register(&ath10k_ahb_driver); + if (ret) + printk(KERN_ERR "failed to register ath10k ahb driver: %d\n", + ret); + return ret; +} + +void ath10k_ahb_exit(void) +{ + platform_driver_unregister(&ath10k_ahb_driver); +} diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h new file mode 100644 index 000000000000..d1afe93f9329 --- /dev/null +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved. + * 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. + */ + +#ifndef _AHB_H_ +#define _AHB_H_ + +#include + +#ifdef CONFIG_ATH10K_AHB + +int ath10k_ahb_init(void); +void ath10k_ahb_exit(void); + +#else /* CONFIG_ATH10K_AHB */ + +static inline int ath10k_ahb_init(void) +{ + return 0; +} + +static inline void ath10k_ahb_exit(void) +{ +} + +#endif /* CONFIG_ATH10K_AHB */ + +#endif /* _AHB_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 5067a0ff4e89..2e411b5258c2 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -69,6 +69,7 @@ struct ath10k; enum ath10k_bus { ATH10K_BUS_PCI, + ATH10K_BUS_AHB, }; static inline const char *ath10k_bus_str(enum ath10k_bus bus) @@ -76,6 +77,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus) switch (bus) { case ATH10K_BUS_PCI: return "pci"; + case ATH10K_BUS_AHB: + return "ahb"; } return "unknown"; diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index f273478e2afb..6206edd7c49f 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -37,6 +37,7 @@ enum ath10k_debug_mask { ATH10K_DBG_TESTMODE = 0x00001000, ATH10K_DBG_WMI_PRINT = 0x00002000, ATH10K_DBG_PCI_PS = 0x00004000, + ATH10K_DBG_AHB = 0x00008000, ATH10K_DBG_ANY = 0xffffffff, }; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 0678831e8671..f8850155140a 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -200,6 +200,7 @@ enum ath10k_hw_rev { ATH10K_HW_QCA6174, ATH10K_HW_QCA99X0, ATH10K_HW_QCA9377, + ATH10K_HW_QCA4019, }; struct ath10k_hw_regs { @@ -253,6 +254,7 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174) #define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0) #define QCA_REV_9377(ar) ((ar)->hw_rev == ATH10K_HW_QCA9377) +#define QCA_REV_40XX(ar) ((ar)->hw_rev == ATH10K_HW_QCA4019) /* Known pecularities: * - raw appears in nwifi decap, raw and nwifi appear in ethernet decap diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 6ef878c1eebc..0e338b657210 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -851,6 +851,7 @@ static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) 0x7ff) << 21; break; case ATH10K_HW_QCA99X0: + case ATH10K_HW_QCA4019: val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); break; } @@ -1529,6 +1530,7 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) CORE_CTRL_ADDRESS, val); break; case ATH10K_HW_QCA99X0: + case ATH10K_HW_QCA4019: /* TODO: Find appropriate register configuration for QCA99X0 * to mask irq/MSI. */ @@ -1551,6 +1553,7 @@ static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) CORE_CTRL_ADDRESS, val); break; case ATH10K_HW_QCA99X0: + case ATH10K_HW_QCA4019: /* TODO: Find appropriate register configuration for QCA99X0 * to unmask irq/MSI. */ @@ -3231,6 +3234,10 @@ static int __init ath10k_pci_init(void) printk(KERN_ERR "failed to register ath10k pci driver: %d\n", ret); + ret = ath10k_ahb_init(); + if (ret) + printk(KERN_ERR "ahb init failed: %d\n", ret); + return ret; } module_init(ath10k_pci_init); @@ -3238,6 +3245,7 @@ module_init(ath10k_pci_init); static void __exit ath10k_pci_exit(void) { pci_unregister_driver(&ath10k_pci_driver); + ath10k_ahb_exit(); } module_exit(ath10k_pci_exit); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index fcfdbca8e55e..c2d4a79aa29a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -22,6 +22,7 @@ #include "hw.h" #include "ce.h" +#include "ahb.h" /* * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite -- cgit From 37a219a556b01b3236156ecf58717c1e41b552d9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:26 +0530 Subject: ath10k: include qca4019 register map table New register table is added for qca4019 to tell about it's register mapping details. Nothing much other than this. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 4 ++++ drivers/net/wireless/ath/ath10k/hw.c | 39 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 2 ++ 3 files changed, 45 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 48a26206c5c1..1f4a27881936 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1980,6 +1980,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->regs = &qca99x0_regs; ar->hw_values = &qca99x0_values; break; + case ATH10K_HW_QCA4019: + ar->regs = &qca4019_regs; + ar->hw_values = &qca4019_values; + break; default: ath10k_err(ar, "unsupported core hardware revision %d\n", hw_rev); diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 7b84d08a5154..f544d48518c3 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -109,6 +109,38 @@ const struct ath10k_hw_regs qca99x0_regs = { .pcie_intr_clr_address = 0x00000010, }; +const struct ath10k_hw_regs qca4019_regs = { + .rtc_soc_base_address = 0x00080000, + .soc_core_base_address = 0x00082000, + .ce_wrapper_base_address = 0x0004d000, + .ce0_base_address = 0x0004a000, + .ce1_base_address = 0x0004a400, + .ce2_base_address = 0x0004a800, + .ce3_base_address = 0x0004ac00, + .ce4_base_address = 0x0004b000, + .ce5_base_address = 0x0004b400, + .ce6_base_address = 0x0004b800, + .ce7_base_address = 0x0004bc00, + /* qca4019 supports upto 12 copy engines. Since base address + * of ce8 to ce11 are not directly referred in the code, + * no need have them in separate members in this table. + * Copy Engine Address + * CE8 0x0004c000 + * CE9 0x0004c400 + * CE10 0x0004c800 + * CE11 0x0004cc00 + */ + .soc_reset_control_si0_rst_mask = 0x00000001, + .soc_reset_control_ce_rst_mask = 0x00000100, + .soc_chip_id_address = 0x000000ec, + .fw_indicator_address = 0x0004f00c, + .ce_wrap_intr_sum_host_msi_lsb = 0x0000000c, + .ce_wrap_intr_sum_host_msi_mask = 0x00fff000, + .pcie_intr_fw_mask = 0x00100000, + .pcie_intr_ce_mask_all = 0x000fff00, + .pcie_intr_clr_address = 0x00000010, +}; + const struct ath10k_hw_values qca988x_values = { .rtc_state_val_on = 3, .ce_count = 8, @@ -136,6 +168,13 @@ const struct ath10k_hw_values qca99x0_values = { .ce_desc_meta_data_lsb = 4, }; +const struct ath10k_hw_values qca4019_values = { + .ce_count = 12, + .num_target_ce_config_wlan = 10, + .ce_desc_meta_data_mask = 0xFFF0, + .ce_desc_meta_data_lsb = 4, +}; + void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f8850155140a..f57a37bfc9f6 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -233,6 +233,7 @@ struct ath10k_hw_regs { extern const struct ath10k_hw_regs qca988x_regs; extern const struct ath10k_hw_regs qca6174_regs; extern const struct ath10k_hw_regs qca99x0_regs; +extern const struct ath10k_hw_regs qca4019_regs; struct ath10k_hw_values { u32 rtc_state_val_on; @@ -246,6 +247,7 @@ struct ath10k_hw_values { extern const struct ath10k_hw_values qca988x_values; extern const struct ath10k_hw_values qca6174_values; extern const struct ath10k_hw_values qca99x0_values; +extern const struct ath10k_hw_values qca4019_values; void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); -- cgit From 7f8e79cdc2534559e3e38f5aee0b9f78e57e8fb3 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:27 +0530 Subject: ath10k: add helper functions in ahb.c for reg rd/wr qca4019 deals with below register memory region to control the clock, reset, etc. - Memory to control wifi core - gcc (outside of wifi) - tcsr (outside of wifi) Add new helper functions to perform read/write in above registers spaces. Actual ioremap for above registers are done in later patch. Struct ath10k_ahb is introduced to maintain ahb specific info and memory this struct will be allocated in the continuation of struct ath10k_pci (again, memory ath10k_ahb is allocated in the later patch). Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 55 +++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 7 +++++ drivers/net/wireless/ath/ath10k/pci.h | 6 ++++ 3 files changed, 68 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 129f4f4491d0..eab4b47237e0 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -17,6 +17,7 @@ #include #include "core.h" #include "debug.h" +#include "pci.h" #include "ahb.h" static const struct of_device_id ath10k_ahb_of_match[] = { @@ -29,6 +30,60 @@ static const struct of_device_id ath10k_ahb_of_match[] = { MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); +static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar) +{ + return &((struct ath10k_pci *)ar->drv_priv)->ahb[0]; +} + +static void ath10k_ahb_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + iowrite32(value, ar_ahb->mem + offset); +} + +static u32 ath10k_ahb_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + return ioread32(ar_ahb->mem + offset); +} + +static u32 ath10k_ahb_gcc_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + return ioread32(ar_ahb->gcc_mem + offset); +} + +static void ath10k_ahb_tcsr_write32(struct ath10k *ar, u32 offset, u32 value) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + iowrite32(value, ar_ahb->tcsr_mem + offset); +} + +static u32 ath10k_ahb_tcsr_read32(struct ath10k *ar, u32 offset) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + return ioread32(ar_ahb->tcsr_mem + offset); +} + +static u32 ath10k_ahb_soc_read32(struct ath10k *ar, u32 addr) +{ + return ath10k_ahb_read32(ar, RTC_SOC_BASE_ADDRESS + addr); +} + +static int ath10k_ahb_get_num_banks(struct ath10k *ar) +{ + if (ar->hw_rev == ATH10K_HW_QCA4019) + return 1; + + ath10k_warn(ar, "unknown number of banks, assuming 1\n"); + return 1; +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index d1afe93f9329..77d15af59c4a 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -20,6 +20,13 @@ #include +struct ath10k_ahb { + struct platform_device *pdev; + void __iomem *mem; + void __iomem *gcc_mem; + void __iomem *tcsr_mem; +}; + #ifdef CONFIG_ATH10K_AHB int ath10k_ahb_init(void); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index c2d4a79aa29a..249c73a69800 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -234,6 +234,12 @@ struct ath10k_pci { bool pci_ps; const struct ath10k_bus_ops *bus_ops; + + /* Keep this entry in the last, memory for struct ath10k_ahb is + * allocated (ahb support enabled case) in the continuation of + * this struct. + */ + struct ath10k_ahb ahb[0]; }; static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) -- cgit From 8beff219c528d19c66e9d2c40fa868d7e7c2e36f Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:28 +0530 Subject: ath10k: add clock ctrl related functions in ahb pre qca4019 chipsets has/uses internal clock generator for the operation. But, qca4019 uses external clocks supplied from outside of target (ie, outside of wifi core). Three different clocks (cmd clock, ref clock, rtc clock) comes into picture in qca4019. All those clocks needs to configured with help of global clock controller (gcc) to make qca4019 functioning. Add functions for clock init/deinit, clock enable/disable in ahb. This is just a preparation, functions added in this patch will be used in later patches. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 123 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 4 ++ 2 files changed, 127 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index eab4b47237e0..11185c0dc6ad 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -15,6 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include +#include #include "core.h" #include "debug.h" #include "pci.h" @@ -84,6 +85,128 @@ static int ath10k_ahb_get_num_banks(struct ath10k *ar) return 1; } +static int ath10k_ahb_clock_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + ar_ahb->cmd_clk = clk_get(dev, "wifi_wcss_cmd"); + if (IS_ERR_OR_NULL(ar_ahb->cmd_clk)) { + ath10k_err(ar, "failed to get cmd clk: %ld\n", + PTR_ERR(ar_ahb->cmd_clk)); + ret = ar_ahb->cmd_clk ? PTR_ERR(ar_ahb->cmd_clk) : -ENODEV; + goto out; + } + + ar_ahb->ref_clk = clk_get(dev, "wifi_wcss_ref"); + if (IS_ERR_OR_NULL(ar_ahb->ref_clk)) { + ath10k_err(ar, "failed to get ref clk: %ld\n", + PTR_ERR(ar_ahb->ref_clk)); + ret = ar_ahb->ref_clk ? PTR_ERR(ar_ahb->ref_clk) : -ENODEV; + goto err_cmd_clk_put; + } + + ar_ahb->rtc_clk = clk_get(dev, "wifi_wcss_rtc"); + if (IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { + ath10k_err(ar, "failed to get rtc clk: %ld\n", + PTR_ERR(ar_ahb->rtc_clk)); + ret = ar_ahb->rtc_clk ? PTR_ERR(ar_ahb->rtc_clk) : -ENODEV; + goto err_ref_clk_put; + } + + return 0; + +err_ref_clk_put: + clk_put(ar_ahb->ref_clk); + +err_cmd_clk_put: + clk_put(ar_ahb->cmd_clk); + +out: + return ret; +} + +static void ath10k_ahb_clock_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) + clk_put(ar_ahb->cmd_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) + clk_put(ar_ahb->ref_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) + clk_put(ar_ahb->rtc_clk); + + ar_ahb->cmd_clk = NULL; + ar_ahb->ref_clk = NULL; + ar_ahb->rtc_clk = NULL; +} + +static int ath10k_ahb_clock_enable(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + if (IS_ERR_OR_NULL(ar_ahb->cmd_clk) || + IS_ERR_OR_NULL(ar_ahb->ref_clk) || + IS_ERR_OR_NULL(ar_ahb->rtc_clk)) { + ath10k_err(ar, "clock(s) is/are not initialized\n"); + ret = -EIO; + goto out; + } + + ret = clk_prepare_enable(ar_ahb->cmd_clk); + if (ret) { + ath10k_err(ar, "failed to enable cmd clk: %d\n", ret); + goto out; + } + + ret = clk_prepare_enable(ar_ahb->ref_clk); + if (ret) { + ath10k_err(ar, "failed to enable ref clk: %d\n", ret); + goto err_cmd_clk_disable; + } + + ret = clk_prepare_enable(ar_ahb->rtc_clk); + if (ret) { + ath10k_err(ar, "failed to enable rtc clk: %d\n", ret); + goto err_ref_clk_disable; + } + + return 0; + +err_ref_clk_disable: + clk_disable_unprepare(ar_ahb->ref_clk); + +err_cmd_clk_disable: + clk_disable_unprepare(ar_ahb->cmd_clk); + +out: + return ret; +} + +static void ath10k_ahb_clock_disable(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) + clk_disable_unprepare(ar_ahb->cmd_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) + clk_disable_unprepare(ar_ahb->ref_clk); + + if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) + clk_disable_unprepare(ar_ahb->rtc_clk); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 77d15af59c4a..753b4330075a 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -25,6 +25,10 @@ struct ath10k_ahb { void __iomem *mem; void __iomem *gcc_mem; void __iomem *tcsr_mem; + + struct clk *cmd_clk; + struct clk *ref_clk; + struct clk *rtc_clk; }; #ifdef CONFIG_ATH10K_AHB -- cgit From 14854bfd9daaa20778db64f224a957c2abaab6fe Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:29 +0530 Subject: ath10k: add reset ctrl related functions in ahb To perform reset on qca4019 wifi, multiple reset lines needs to be toggled in a sequence with help of reset controller support in the kernel. This patch adds functions to reset control init/deinit and release reset. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/Kconfig | 2 +- drivers/net/wireless/ath/ath10k/ahb.c | 138 ++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 6 ++ 3 files changed, 145 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index d7f207a6b0e0..db1ca629cbd6 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -17,7 +17,7 @@ config ATH10K_PCI config ATH10K_AHB bool "Atheros ath10k AHB support" - depends on ATH10K_PCI && OF + depends on ATH10K_PCI && OF && RESET_CONTROLLER ---help--- This module adds support for AHB bus diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 11185c0dc6ad..d1f197220e30 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -16,6 +16,7 @@ */ #include #include +#include #include "core.h" #include "debug.h" #include "pci.h" @@ -207,6 +208,143 @@ static void ath10k_ahb_clock_disable(struct ath10k *ar) clk_disable_unprepare(ar_ahb->rtc_clk); } +static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + int ret; + + dev = &ar_ahb->pdev->dev; + + ar_ahb->core_cold_rst = reset_control_get(dev, "wifi_core_cold"); + if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) { + ath10k_err(ar, "failed to get core cold rst ctrl: %ld\n", + PTR_ERR(ar_ahb->core_cold_rst)); + ret = ar_ahb->core_cold_rst ? + PTR_ERR(ar_ahb->core_cold_rst) : -ENODEV; + goto out; + } + + ar_ahb->radio_cold_rst = reset_control_get(dev, "wifi_radio_cold"); + if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) { + ath10k_err(ar, "failed to get radio cold rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_cold_rst)); + ret = ar_ahb->radio_cold_rst ? + PTR_ERR(ar_ahb->radio_cold_rst) : -ENODEV; + goto err_core_cold_rst_put; + } + + ar_ahb->radio_warm_rst = reset_control_get(dev, "wifi_radio_warm"); + if (IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) { + ath10k_err(ar, "failed to get radio warm rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_warm_rst)); + ret = ar_ahb->radio_warm_rst ? + PTR_ERR(ar_ahb->radio_warm_rst) : -ENODEV; + goto err_radio_cold_rst_put; + } + + ar_ahb->radio_srif_rst = reset_control_get(dev, "wifi_radio_srif"); + if (IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) { + ath10k_err(ar, "failed to get radio srif rst ctrl: %ld\n", + PTR_ERR(ar_ahb->radio_srif_rst)); + ret = ar_ahb->radio_srif_rst ? + PTR_ERR(ar_ahb->radio_srif_rst) : -ENODEV; + goto err_radio_warm_rst_put; + } + + ar_ahb->cpu_init_rst = reset_control_get(dev, "wifi_cpu_init"); + if (IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "failed to get cpu init rst ctrl: %ld\n", + PTR_ERR(ar_ahb->cpu_init_rst)); + ret = ar_ahb->cpu_init_rst ? + PTR_ERR(ar_ahb->cpu_init_rst) : -ENODEV; + goto err_radio_srif_rst_put; + } + + return 0; + +err_radio_srif_rst_put: + reset_control_put(ar_ahb->radio_srif_rst); + +err_radio_warm_rst_put: + reset_control_put(ar_ahb->radio_warm_rst); + +err_radio_cold_rst_put: + reset_control_put(ar_ahb->radio_cold_rst); + +err_core_cold_rst_put: + reset_control_put(ar_ahb->core_cold_rst); + +out: + return ret; +} + +static void ath10k_ahb_rst_ctrl_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + if (!IS_ERR_OR_NULL(ar_ahb->core_cold_rst)) + reset_control_put(ar_ahb->core_cold_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_cold_rst)) + reset_control_put(ar_ahb->radio_cold_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_warm_rst)) + reset_control_put(ar_ahb->radio_warm_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->radio_srif_rst)) + reset_control_put(ar_ahb->radio_srif_rst); + + if (!IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) + reset_control_put(ar_ahb->cpu_init_rst); + + ar_ahb->core_cold_rst = NULL; + ar_ahb->radio_cold_rst = NULL; + ar_ahb->radio_warm_rst = NULL; + ar_ahb->radio_srif_rst = NULL; + ar_ahb->cpu_init_rst = NULL; +} + +static int ath10k_ahb_release_reset(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + int ret; + + if (IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || + IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); + return -EINVAL; + } + + ret = reset_control_deassert(ar_ahb->radio_cold_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio cold rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->radio_warm_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio warm rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->radio_srif_rst); + if (ret) { + ath10k_err(ar, "failed to deassert radio srif rst: %d\n", ret); + return ret; + } + + ret = reset_control_deassert(ar_ahb->cpu_init_rst); + if (ret) { + ath10k_err(ar, "failed to deassert cpu init rst: %d\n", ret); + return ret; + } + + return 0; +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 753b4330075a..2904b7bc9459 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -29,6 +29,12 @@ struct ath10k_ahb { struct clk *cmd_clk; struct clk *ref_clk; struct clk *rtc_clk; + + struct reset_control *core_cold_rst; + struct reset_control *radio_cold_rst; + struct reset_control *radio_warm_rst; + struct reset_control *radio_srif_rst; + struct reset_control *cpu_init_rst; }; #ifdef CONFIG_ATH10K_AHB -- cgit From 133df0f849bc7b5448c62272986af626f2bda6bd Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:30 +0530 Subject: ath10k: add chip and bus halt logic in ahb Add function to perform chip halt sequence and function to halt axi bus in ahb module. Mainly used in the scenario like driver unload. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 113 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 15 +++++ 2 files changed, 128 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index d1f197220e30..230507890fbf 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -345,6 +345,119 @@ static int ath10k_ahb_release_reset(struct ath10k *ar) return 0; } +static void ath10k_ahb_halt_axi_bus(struct ath10k *ar, u32 haltreq_reg, + u32 haltack_reg) +{ + unsigned long timeout; + u32 val; + + /* Issue halt axi bus request */ + val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); + val |= AHB_AXI_BUS_HALT_REQ; + ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); + + /* Wait for axi bus halted ack */ + timeout = jiffies + msecs_to_jiffies(ATH10K_AHB_AXI_BUS_HALT_TIMEOUT); + do { + val = ath10k_ahb_tcsr_read32(ar, haltack_reg); + if (val & AHB_AXI_BUS_HALT_ACK) + break; + + mdelay(1); + } while (time_before(jiffies, timeout)); + + if (!(val & AHB_AXI_BUS_HALT_ACK)) { + ath10k_err(ar, "failed to halt axi bus: %d\n", val); + return; + } + + ath10k_dbg(ar, ATH10K_DBG_AHB, "axi bus halted\n"); +} + +static void ath10k_ahb_halt_chip(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + u32 core_id, glb_cfg_reg, haltreq_reg, haltack_reg; + u32 val; + int ret; + + if (IS_ERR_OR_NULL(ar_ahb->core_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_cold_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_warm_rst) || + IS_ERR_OR_NULL(ar_ahb->radio_srif_rst) || + IS_ERR_OR_NULL(ar_ahb->cpu_init_rst)) { + ath10k_err(ar, "rst ctrl(s) is/are not initialized\n"); + return; + } + + core_id = ath10k_ahb_read32(ar, ATH10K_AHB_WLAN_CORE_ID_REG); + + switch (core_id) { + case 0: + glb_cfg_reg = ATH10K_AHB_TCSR_WIFI0_GLB_CFG; + haltreq_reg = ATH10K_AHB_TCSR_WCSS0_HALTREQ; + haltack_reg = ATH10K_AHB_TCSR_WCSS0_HALTACK; + break; + case 1: + glb_cfg_reg = ATH10K_AHB_TCSR_WIFI1_GLB_CFG; + haltreq_reg = ATH10K_AHB_TCSR_WCSS1_HALTREQ; + haltack_reg = ATH10K_AHB_TCSR_WCSS1_HALTACK; + break; + default: + ath10k_err(ar, "invalid core id %d found, skipping reset sequence\n", + core_id); + return; + } + + ath10k_ahb_halt_axi_bus(ar, haltreq_reg, haltack_reg); + + val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); + val |= TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; + ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); + + ret = reset_control_assert(ar_ahb->core_cold_rst); + if (ret) + ath10k_err(ar, "failed to assert core cold rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->radio_cold_rst); + if (ret) + ath10k_err(ar, "failed to assert radio cold rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->radio_warm_rst); + if (ret) + ath10k_err(ar, "failed to assert radio warm rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->radio_srif_rst); + if (ret) + ath10k_err(ar, "failed to assert radio srif rst: %d\n", ret); + msleep(1); + + ret = reset_control_assert(ar_ahb->cpu_init_rst); + if (ret) + ath10k_err(ar, "failed to assert cpu init rst: %d\n", ret); + msleep(10); + + /* Clear halt req and core clock disable req before + * deasserting wifi core reset. + */ + val = ath10k_ahb_tcsr_read32(ar, haltreq_reg); + val &= ~AHB_AXI_BUS_HALT_REQ; + ath10k_ahb_tcsr_write32(ar, haltreq_reg, val); + + val = ath10k_ahb_tcsr_read32(ar, glb_cfg_reg); + val &= ~TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK; + ath10k_ahb_tcsr_write32(ar, glb_cfg_reg, val); + + ret = reset_control_deassert(ar_ahb->core_cold_rst); + if (ret) + ath10k_err(ar, "failed to deassert core cold rst: %d\n", ret); + + ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 2904b7bc9459..4761eeb475d6 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -39,6 +39,21 @@ struct ath10k_ahb { #ifdef CONFIG_ATH10K_AHB +#define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 + +#define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 +#define ATH10K_AHB_TCSR_WIFI1_GLB_CFG 0x49004 +#define TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK BIT(25) + +#define ATH10K_AHB_TCSR_WCSS0_HALTREQ 0x52000 +#define ATH10K_AHB_TCSR_WCSS1_HALTREQ 0x52010 +#define ATH10K_AHB_TCSR_WCSS0_HALTACK 0x52004 +#define ATH10K_AHB_TCSR_WCSS1_HALTACK 0x52014 + +#define ATH10K_AHB_AXI_BUS_HALT_TIMEOUT 10 /* msec */ +#define AHB_AXI_BUS_HALT_REQ 1 +#define AHB_AXI_BUS_HALT_ACK 1 + int ath10k_ahb_init(void); void ath10k_ahb_exit(void); -- cgit From 1c44fcb9234c80bbf9e4043deab8492e1c0dcf99 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:31 +0530 Subject: ath10k: include irq related functions in ahb Add irq related functions to register,handle,release,disable interrupt. qca4019 supports msi interrupt, but it has the problem. Until the issue gets sorted out, only legacy interrupt model is enabled and used. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 44 +++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 230507890fbf..29d0b6c6b35c 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -458,6 +458,50 @@ static void ath10k_ahb_halt_chip(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_AHB, "core %d reset done\n", core_id); } +static irqreturn_t ath10k_ahb_interrupt_handler(int irq, void *arg) +{ + struct ath10k *ar = arg; + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (!ath10k_pci_irq_pending(ar)) + return IRQ_NONE; + + ath10k_pci_disable_and_clear_legacy_irq(ar); + tasklet_schedule(&ar_pci->intr_tq); + + return IRQ_HANDLED; +} + +static int ath10k_ahb_request_irq_legacy(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + int ret; + + ret = request_irq(ar_ahb->irq, + ath10k_ahb_interrupt_handler, + IRQF_SHARED, "ath10k_ahb", ar); + if (ret) { + ath10k_warn(ar, "failed to request legacy irq %d: %d\n", + ar_ahb->irq, ret); + return ret; + } + + return 0; +} + +static void ath10k_ahb_release_irq_legacy(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + free_irq(ar_ahb->irq, ar); +} + +static void ath10k_ahb_irq_disable(struct ath10k *ar) +{ + ath10k_ce_disable_interrupts(ar); + ath10k_pci_disable_and_clear_legacy_irq(ar); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 4761eeb475d6..97c40e47dc02 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -26,6 +26,8 @@ struct ath10k_ahb { void __iomem *gcc_mem; void __iomem *tcsr_mem; + int irq; + struct clk *cmd_clk; struct clk *ref_clk; struct clk *rtc_clk; -- cgit From 704dc4e36769218145d30c41e81a5fbfed3977c7 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:32 +0530 Subject: ath10k: add resource init and deinit in ahb Add function to gather resources required for qca4019 to operate (memory, irq, dma setting, clock init , rest control init) and function release those resources when it's not needed. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 122 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 7 ++ 2 files changed, 129 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 29d0b6c6b35c..d83a864515a2 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -15,6 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include +#include +#include #include #include #include "core.h" @@ -502,6 +504,126 @@ static void ath10k_ahb_irq_disable(struct ath10k *ar) ath10k_pci_disable_and_clear_legacy_irq(ar); } +static int ath10k_ahb_resource_init(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct platform_device *pdev; + struct device *dev; + struct resource *res; + int ret; + + pdev = ar_ahb->pdev; + dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ath10k_err(ar, "failed to get memory resource\n"); + ret = -ENXIO; + goto out; + } + + ar_ahb->mem = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ar_ahb->mem)) { + ath10k_err(ar, "mem ioremap error\n"); + ret = PTR_ERR(ar_ahb->mem); + goto out; + } + + ar_ahb->mem_len = resource_size(res); + + ar_ahb->gcc_mem = ioremap_nocache(ATH10K_GCC_REG_BASE, + ATH10K_GCC_REG_SIZE); + if (!ar_ahb->gcc_mem) { + ath10k_err(ar, "gcc mem ioremap error\n"); + ret = -ENOMEM; + goto err_mem_unmap; + } + + ar_ahb->tcsr_mem = ioremap_nocache(ATH10K_TCSR_REG_BASE, + ATH10K_TCSR_REG_SIZE); + if (!ar_ahb->tcsr_mem) { + ath10k_err(ar, "tcsr mem ioremap error\n"); + ret = -ENOMEM; + goto err_gcc_mem_unmap; + } + + ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + ath10k_err(ar, "failed to set 32-bit dma mask: %d\n", ret); + goto err_tcsr_mem_unmap; + } + + ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) { + ath10k_err(ar, "failed to set 32-bit consistent dma: %d\n", + ret); + goto err_tcsr_mem_unmap; + } + + ret = ath10k_ahb_clock_init(ar); + if (ret) + goto err_tcsr_mem_unmap; + + ret = ath10k_ahb_rst_ctrl_init(ar); + if (ret) + goto err_clock_deinit; + + ar_ahb->irq = platform_get_irq_byname(pdev, "legacy"); + if (ar_ahb->irq < 0) { + ath10k_err(ar, "failed to get irq number: %d\n", ar_ahb->irq); + goto err_clock_deinit; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "irq: %d\n", ar_ahb->irq); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "mem: 0x%p mem_len: %lu gcc mem: 0x%p tcsr_mem: 0x%p\n", + ar_ahb->mem, ar_ahb->mem_len, + ar_ahb->gcc_mem, ar_ahb->tcsr_mem); + return 0; + +err_clock_deinit: + ath10k_ahb_clock_deinit(ar); + +err_tcsr_mem_unmap: + iounmap(ar_ahb->tcsr_mem); + +err_gcc_mem_unmap: + ar_ahb->tcsr_mem = NULL; + iounmap(ar_ahb->gcc_mem); + +err_mem_unmap: + ar_ahb->gcc_mem = NULL; + devm_iounmap(&pdev->dev, ar_ahb->mem); + +out: + ar_ahb->mem = NULL; + return ret; +} + +static void ath10k_ahb_resource_deinit(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + struct device *dev; + + dev = &ar_ahb->pdev->dev; + + if (ar_ahb->mem) + devm_iounmap(dev, ar_ahb->mem); + + if (ar_ahb->gcc_mem) + iounmap(ar_ahb->gcc_mem); + + if (ar_ahb->tcsr_mem) + iounmap(ar_ahb->tcsr_mem); + + ar_ahb->mem = NULL; + ar_ahb->gcc_mem = NULL; + ar_ahb->tcsr_mem = NULL; + + ath10k_ahb_clock_deinit(ar); + ath10k_ahb_rst_ctrl_deinit(ar); +} + static int ath10k_ahb_probe(struct platform_device *pdev) { return 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 97c40e47dc02..5bd01b49132b 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -23,6 +23,7 @@ struct ath10k_ahb { struct platform_device *pdev; void __iomem *mem; + unsigned long mem_len; void __iomem *gcc_mem; void __iomem *tcsr_mem; @@ -41,6 +42,12 @@ struct ath10k_ahb { #ifdef CONFIG_ATH10K_AHB +#define ATH10K_GCC_REG_BASE 0x1800000 +#define ATH10K_GCC_REG_SIZE 0x60000 + +#define ATH10K_TCSR_REG_BASE 0x1900000 +#define ATH10K_TCSR_REG_SIZE 0x80000 + #define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 #define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 -- cgit From 0d87c9208a17cb82fed66e29180078ab603086ea Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Wed, 27 Jan 2016 15:24:33 +0530 Subject: ath10k: expose hif ops for ahb Like how pci.c exposes hif ops for the bus specific operation, expose similar hif ops table for ahb with all required functions linked to it. Many ath10k_pci_* functions are reused here in hif ops table. If something is not sharable, new functions are added for ahb and linked to hif ops table. Finally, make ath10k_ahb_probe/remove() to perform what is expected out of it. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/ahb.c | 271 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/ahb.h | 5 + drivers/net/wireless/ath/ath10k/hw.h | 1 + 3 files changed, 277 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index d83a864515a2..bd62bc19e758 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -624,13 +624,284 @@ static void ath10k_ahb_resource_deinit(struct ath10k *ar) ath10k_ahb_rst_ctrl_deinit(ar); } +static int ath10k_ahb_prepare_device(struct ath10k *ar) +{ + u32 val; + int ret; + + ret = ath10k_ahb_clock_enable(ar); + if (ret) { + ath10k_err(ar, "failed to enable clocks\n"); + return ret; + } + + /* Clock for the target is supplied from outside of target (ie, + * external clock module controlled by the host). Target needs + * to know what frequency target cpu is configured which is needed + * for target internal use. Read target cpu frequency info from + * gcc register and write into target's scratch register where + * target expects this information. + */ + val = ath10k_ahb_gcc_read32(ar, ATH10K_AHB_GCC_FEPLL_PLL_DIV); + ath10k_ahb_write32(ar, ATH10K_AHB_WIFI_SCRATCH_5_REG, val); + + ret = ath10k_ahb_release_reset(ar); + if (ret) + goto err_clk_disable; + + ath10k_ahb_irq_disable(ar); + + ath10k_ahb_write32(ar, FW_INDICATOR_ADDRESS, FW_IND_HOST_READY); + + ret = ath10k_pci_wait_for_target_init(ar); + if (ret) + goto err_halt_chip; + + return 0; + +err_halt_chip: + ath10k_ahb_halt_chip(ar); + +err_clk_disable: + ath10k_ahb_clock_disable(ar); + + return ret; +} + +static int ath10k_ahb_chip_reset(struct ath10k *ar) +{ + int ret; + + ath10k_ahb_halt_chip(ar); + ath10k_ahb_clock_disable(ar); + + ret = ath10k_ahb_prepare_device(ar); + if (ret) + return ret; + + return 0; +} + +static int ath10k_ahb_wake_target_cpu(struct ath10k *ar) +{ + u32 addr, val; + + addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS; + val = ath10k_ahb_read32(ar, addr); + val |= ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK; + ath10k_ahb_write32(ar, addr, val); + + return 0; +} + +static int ath10k_ahb_hif_start(struct ath10k *ar) +{ + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif start\n"); + + ath10k_ce_enable_interrupts(ar); + ath10k_pci_enable_legacy_irq(ar); + + ath10k_pci_rx_post(ar); + + return 0; +} + +static void ath10k_ahb_hif_stop(struct ath10k *ar) +{ + struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif stop\n"); + + ath10k_ahb_irq_disable(ar); + synchronize_irq(ar_ahb->irq); + + ath10k_pci_flush(ar); +} + +static int ath10k_ahb_hif_power_up(struct ath10k *ar) +{ + int ret; + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot ahb hif power up\n"); + + ret = ath10k_ahb_chip_reset(ar); + if (ret) { + ath10k_err(ar, "failed to reset chip: %d\n", ret); + goto out; + } + + ret = ath10k_pci_init_pipes(ar); + if (ret) { + ath10k_err(ar, "failed to initialize CE: %d\n", ret); + goto out; + } + + ret = ath10k_pci_init_config(ar); + if (ret) { + ath10k_err(ar, "failed to setup init config: %d\n", ret); + goto err_ce_deinit; + } + + ret = ath10k_ahb_wake_target_cpu(ar); + if (ret) { + ath10k_err(ar, "could not wake up target CPU: %d\n", ret); + goto err_ce_deinit; + } + + return 0; + +err_ce_deinit: + ath10k_pci_ce_deinit(ar); +out: + return ret; +} + +static const struct ath10k_hif_ops ath10k_ahb_hif_ops = { + .tx_sg = ath10k_pci_hif_tx_sg, + .diag_read = ath10k_pci_hif_diag_read, + .diag_write = ath10k_pci_diag_write_mem, + .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, + .start = ath10k_ahb_hif_start, + .stop = ath10k_ahb_hif_stop, + .map_service_to_pipe = ath10k_pci_hif_map_service_to_pipe, + .get_default_pipe = ath10k_pci_hif_get_default_pipe, + .send_complete_check = ath10k_pci_hif_send_complete_check, + .get_free_queue_number = ath10k_pci_hif_get_free_queue_number, + .power_up = ath10k_ahb_hif_power_up, + .power_down = ath10k_pci_hif_power_down, + .read32 = ath10k_ahb_read32, + .write32 = ath10k_ahb_write32, +}; + +static const struct ath10k_bus_ops ath10k_ahb_bus_ops = { + .read32 = ath10k_ahb_read32, + .write32 = ath10k_ahb_write32, + .get_num_banks = ath10k_ahb_get_num_banks, +}; + static int ath10k_ahb_probe(struct platform_device *pdev) { + struct ath10k *ar; + struct ath10k_ahb *ar_ahb; + struct ath10k_pci *ar_pci; + const struct of_device_id *of_id; + enum ath10k_hw_rev hw_rev; + size_t size; + int ret; + u32 chip_id; + + of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); + if (!of_id) { + dev_err(&pdev->dev, "failed to find matching device tree id\n"); + return -EINVAL; + } + + hw_rev = (enum ath10k_hw_rev)of_id->data; + + size = sizeof(*ar_pci) + sizeof(*ar_ahb); + ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, + hw_rev, &ath10k_ahb_hif_ops); + if (!ar) { + dev_err(&pdev->dev, "failed to allocate core\n"); + return -ENOMEM; + } + + ath10k_dbg(ar, ATH10K_DBG_BOOT, "ahb probe\n"); + + ar_pci = ath10k_pci_priv(ar); + ar_ahb = ath10k_ahb_priv(ar); + + ar_ahb->pdev = pdev; + platform_set_drvdata(pdev, ar); + + ret = ath10k_ahb_resource_init(ar); + if (ret) + goto err_core_destroy; + + ar->dev_id = 0; + ar_pci->mem = ar_ahb->mem; + ar_pci->mem_len = ar_ahb->mem_len; + ar_pci->ar = ar; + ar_pci->bus_ops = &ath10k_ahb_bus_ops; + + ret = ath10k_pci_setup_resource(ar); + if (ret) { + ath10k_err(ar, "failed to setup resource: %d\n", ret); + goto err_resource_deinit; + } + + ath10k_pci_init_irq_tasklets(ar); + + ret = ath10k_ahb_request_irq_legacy(ar); + if (ret) + goto err_free_pipes; + + ret = ath10k_ahb_prepare_device(ar); + if (ret) + goto err_free_irq; + + ath10k_pci_ce_deinit(ar); + + chip_id = ath10k_ahb_soc_read32(ar, SOC_CHIP_ID_ADDRESS); + if (chip_id == 0xffffffff) { + ath10k_err(ar, "failed to get chip id\n"); + goto err_halt_device; + } + + ret = ath10k_core_register(ar, chip_id); + if (ret) { + ath10k_err(ar, "failed to register driver core: %d\n", ret); + goto err_halt_device; + } + return 0; + +err_halt_device: + ath10k_ahb_halt_chip(ar); + ath10k_ahb_clock_disable(ar); + +err_free_irq: + ath10k_ahb_release_irq_legacy(ar); + +err_free_pipes: + ath10k_pci_free_pipes(ar); + +err_resource_deinit: + ath10k_ahb_resource_deinit(ar); + +err_core_destroy: + ath10k_core_destroy(ar); + platform_set_drvdata(pdev, NULL); + + return ret; } static int ath10k_ahb_remove(struct platform_device *pdev) { + struct ath10k *ar = platform_get_drvdata(pdev); + struct ath10k_ahb *ar_ahb; + + if (!ar) + return -EINVAL; + + ar_ahb = ath10k_ahb_priv(ar); + + if (!ar_ahb) + return -EINVAL; + + ath10k_dbg(ar, ATH10K_DBG_AHB, "ahb remove\n"); + + ath10k_core_unregister(ar); + ath10k_ahb_irq_disable(ar); + ath10k_ahb_release_irq_legacy(ar); + ath10k_pci_release_resource(ar); + ath10k_ahb_halt_chip(ar); + ath10k_ahb_clock_disable(ar); + ath10k_ahb_resource_deinit(ar); + ath10k_core_destroy(ar); + + platform_set_drvdata(pdev, NULL); + return 0; } diff --git a/drivers/net/wireless/ath/ath10k/ahb.h b/drivers/net/wireless/ath/ath10k/ahb.h index 5bd01b49132b..d43e375215c8 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.h +++ b/drivers/net/wireless/ath/ath10k/ahb.h @@ -48,6 +48,9 @@ struct ath10k_ahb { #define ATH10K_TCSR_REG_BASE 0x1900000 #define ATH10K_TCSR_REG_SIZE 0x80000 +#define ATH10K_AHB_GCC_FEPLL_PLL_DIV 0x2f020 +#define ATH10K_AHB_WIFI_SCRATCH_5_REG 0x4f014 + #define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030 #define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000 @@ -63,6 +66,8 @@ struct ath10k_ahb { #define AHB_AXI_BUS_HALT_REQ 1 #define AHB_AXI_BUS_HALT_ACK 1 +#define ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK 1 + int ath10k_ahb_init(void); void ath10k_ahb_exit(void); diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index f57a37bfc9f6..4217bdbe9f01 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -605,6 +605,7 @@ enum ath10k_hw_4addr_pad { #define FW_INDICATOR_ADDRESS ar->regs->fw_indicator_address #define FW_IND_EVENT_PENDING 1 #define FW_IND_INITIALIZED 2 +#define FW_IND_HOST_READY 0x80000000 /* HOST_REG interrupt from firmware */ #define PCIE_INTR_FIRMWARE_MASK ar->regs->pcie_intr_fw_mask -- cgit From 1b06d64f73746c30ddba43bb57c30ba9a126f53b Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 20 Jan 2016 13:50:11 -0500 Subject: gpio: Add GPIO support for the ACCES 104-DIO-48E The ACCES 104-DIO-48E device provides 48 lines digital I/O via two Programmable Peripheral Interface (PPI) chips of type 82C55. Bit C3 at each 24-bit Group can be used as an external interrupt, triggered by a rising edge. This driver provides GPIO and IRQ support for these 48 channels of digital I/O. The base port address for the device may be configured via the dio_48e_base module parameter. The interrupt line number for the device may be configured via the dio_48e_irq module parameter. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- MAINTAINERS | 6 + drivers/gpio/Kconfig | 9 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-104-dio-48e.c | 439 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 455 insertions(+) create mode 100644 drivers/gpio/gpio-104-dio-48e.c diff --git a/MAINTAINERS b/MAINTAINERS index 0ba80b692723..f043e957698d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -240,6 +240,12 @@ L: lm-sensors@lm-sensors.org S: Maintained F: drivers/hwmon/abituguru3.c +ACCES 104-DIO-48E GPIO DRIVER +M: William Breathitt Gray +L: linux-gpio@vger.kernel.org +S: Maintained +F: drivers/gpio/gpio-104-dio-48e.c + ACCES 104-IDI-48 GPIO DRIVER M: "William Breathitt Gray" L: linux-gpio@vger.kernel.org diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b5337f2e0eb4..5e317486a8cc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -487,6 +487,15 @@ endmenu menu "Port-mapped I/O GPIO drivers" depends on X86 # Unconditional I/O space access +config GPIO_104_DIO_48E + tristate "ACCES 104-DIO-48E GPIO support" + select GPIOLIB_IRQCHIP + help + Enables GPIO support for the ACCES 104-DIO-48E family. The base port + address for the device may be configured via the dio_48e_base module + parameter. The interrupt line number for the device may be configured + via the dio_48e_irq module parameter. + config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" select GPIOLIB_IRQCHIP diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 73121b1b3b94..d4cc4f3d3674 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o +obj-$(CONFIG_GPIO_104_DIO_48E) += gpio-104-dio-48e.o obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c new file mode 100644 index 000000000000..279de392ac6c --- /dev/null +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -0,0 +1,439 @@ +/* + * GPIO driver for the ACCES 104-DIO-48E + * Copyright (C) 2016 William Breathitt Gray + * + * 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 + +static unsigned dio_48e_base; +module_param(dio_48e_base, uint, 0); +MODULE_PARM_DESC(dio_48e_base, "ACCES 104-DIO-48E base address"); +static unsigned dio_48e_irq; +module_param(dio_48e_irq, uint, 0); +MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number"); + +/** + * struct dio48e_gpio - GPIO device private data structure + * @chip: instance of the gpio_chip + * @io_state: bit I/O state (whether bit is set to input or output) + * @out_state: output bits state + * @control: Control registers state + * @lock: synchronization lock to prevent I/O race conditions + * @base: base port address of the GPIO device + * @extent: extent of port address region of the GPIO device + * @irq: Interrupt line number + * @irq_mask: I/O bits affected by interrupts + */ +struct dio48e_gpio { + struct gpio_chip chip; + unsigned char io_state[6]; + unsigned char out_state[6]; + unsigned char control[2]; + spinlock_t lock; + unsigned base; + unsigned extent; + unsigned irq; + unsigned char irq_mask; +}; + +static int dio48e_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + + return !!(dio48egpio->io_state[port] & mask); +} + +static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned io_port = offset / 8; + const unsigned control_port = io_port / 2; + const unsigned control_addr = dio48egpio->base + 3 + control_port*4; + unsigned long flags; + unsigned control; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + /* Check if configuring Port C */ + if (io_port == 2 || io_port == 5) { + /* Port C can be configured by nibble */ + if (offset % 8 > 3) { + dio48egpio->io_state[io_port] |= 0xF0; + dio48egpio->control[control_port] |= BIT(3); + } else { + dio48egpio->io_state[io_port] |= 0x0F; + dio48egpio->control[control_port] |= BIT(0); + } + } else { + dio48egpio->io_state[io_port] |= 0xFF; + if (io_port == 0 || io_port == 3) + dio48egpio->control[control_port] |= BIT(4); + else + dio48egpio->control[control_port] |= BIT(1); + } + + control = BIT(7) | dio48egpio->control[control_port]; + outb(control, control_addr); + control &= ~BIT(7); + outb(control, control_addr); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); + + return 0; +} + +static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned io_port = offset / 8; + const unsigned control_port = io_port / 2; + const unsigned mask = BIT(offset % 8); + const unsigned control_addr = dio48egpio->base + 3 + control_port*4; + const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port; + unsigned long flags; + unsigned control; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + /* Check if configuring Port C */ + if (io_port == 2 || io_port == 5) { + /* Port C can be configured by nibble */ + if (offset % 8 > 3) { + dio48egpio->io_state[io_port] &= 0x0F; + dio48egpio->control[control_port] &= ~BIT(3); + } else { + dio48egpio->io_state[io_port] &= 0xF0; + dio48egpio->control[control_port] &= ~BIT(0); + } + } else { + dio48egpio->io_state[io_port] &= 0x00; + if (io_port == 0 || io_port == 3) + dio48egpio->control[control_port] &= ~BIT(4); + else + dio48egpio->control[control_port] &= ~BIT(1); + } + + if (value) + dio48egpio->out_state[io_port] |= mask; + else + dio48egpio->out_state[io_port] &= ~mask; + + control = BIT(7) | dio48egpio->control[control_port]; + outb(control, control_addr); + + outb(dio48egpio->out_state[io_port], dio48egpio->base + out_port); + + control &= ~BIT(7); + outb(control, control_addr); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); + + return 0; +} + +static int dio48e_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + const unsigned in_port = (port > 2) ? port + 1 : port; + unsigned long flags; + unsigned port_state; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + /* ensure that GPIO is set for input */ + if (!(dio48egpio->io_state[port] & mask)) { + spin_unlock_irqrestore(&dio48egpio->lock, flags); + return -EINVAL; + } + + port_state = inb(dio48egpio->base + in_port); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); + + return !!(port_state & mask); +} + +static void dio48e_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned port = offset / 8; + const unsigned mask = BIT(offset % 8); + const unsigned out_port = (port > 2) ? port + 1 : port; + unsigned long flags; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + if (value) + dio48egpio->out_state[port] |= mask; + else + dio48egpio->out_state[port] &= ~mask; + + outb(dio48egpio->out_state[port], dio48egpio->base + out_port); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); +} + +static void dio48e_irq_ack(struct irq_data *data) +{ +} + +static void dio48e_irq_mask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + unsigned long flags; + + /* only bit 3 on each respective Port C supports interrupts */ + if (offset != 19 && offset != 43) + return; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + if (offset == 19) + dio48egpio->irq_mask &= ~BIT(0); + else + dio48egpio->irq_mask &= ~BIT(1); + + if (!dio48egpio->irq_mask) + /* disable interrupts */ + inb(dio48egpio->base + 0xB); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); +} + +static void dio48e_irq_unmask(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); + const unsigned long offset = irqd_to_hwirq(data); + unsigned long flags; + + /* only bit 3 on each respective Port C supports interrupts */ + if (offset != 19 && offset != 43) + return; + + spin_lock_irqsave(&dio48egpio->lock, flags); + + if (!dio48egpio->irq_mask) { + /* enable interrupts */ + outb(0x00, dio48egpio->base + 0xF); + outb(0x00, dio48egpio->base + 0xB); + } + + if (offset == 19) + dio48egpio->irq_mask |= BIT(0); + else + dio48egpio->irq_mask |= BIT(1); + + spin_unlock_irqrestore(&dio48egpio->lock, flags); +} + +static int dio48e_irq_set_type(struct irq_data *data, unsigned flow_type) +{ + const unsigned long offset = irqd_to_hwirq(data); + + /* only bit 3 on each respective Port C supports interrupts */ + if (offset != 19 && offset != 43) + return -EINVAL; + + if (flow_type != IRQ_TYPE_NONE && flow_type != IRQ_TYPE_EDGE_RISING) + return -EINVAL; + + return 0; +} + +static struct irq_chip dio48e_irqchip = { + .name = "104-dio-48e", + .irq_ack = dio48e_irq_ack, + .irq_mask = dio48e_irq_mask, + .irq_unmask = dio48e_irq_unmask, + .irq_set_type = dio48e_irq_set_type +}; + +static irqreturn_t dio48e_irq_handler(int irq, void *dev_id) +{ + struct dio48e_gpio *const dio48egpio = dev_id; + struct gpio_chip *const chip = &dio48egpio->chip; + const unsigned long irq_mask = dio48egpio->irq_mask; + unsigned long gpio; + + for_each_set_bit(gpio, &irq_mask, 2) + generic_handle_irq(irq_find_mapping(chip->irqdomain, + 19 + gpio*24)); + + spin_lock(&dio48egpio->lock); + + outb(0x00, dio48egpio->base + 0xF); + + spin_unlock(&dio48egpio->lock); + + return IRQ_HANDLED; +} + +static int __init dio48e_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct dio48e_gpio *dio48egpio; + const unsigned base = dio_48e_base; + const unsigned extent = 16; + const char *const name = dev_name(dev); + int err; + const unsigned irq = dio_48e_irq; + + dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); + if (!dio48egpio) + return -ENOMEM; + + if (!request_region(base, extent, name)) { + dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", + name, base, base + extent); + err = -EBUSY; + goto err_lock_io_port; + } + + dio48egpio->chip.label = name; + dio48egpio->chip.parent = dev; + dio48egpio->chip.owner = THIS_MODULE; + dio48egpio->chip.base = -1; + dio48egpio->chip.ngpio = 48; + dio48egpio->chip.get_direction = dio48e_gpio_get_direction; + dio48egpio->chip.direction_input = dio48e_gpio_direction_input; + dio48egpio->chip.direction_output = dio48e_gpio_direction_output; + dio48egpio->chip.get = dio48e_gpio_get; + dio48egpio->chip.set = dio48e_gpio_set; + dio48egpio->base = base; + dio48egpio->extent = extent; + dio48egpio->irq = irq; + + spin_lock_init(&dio48egpio->lock); + + dev_set_drvdata(dev, dio48egpio); + + err = gpiochip_add_data(&dio48egpio->chip, dio48egpio); + if (err) { + dev_err(dev, "GPIO registering failed (%d)\n", err); + goto err_gpio_register; + } + + /* initialize all GPIO as output */ + outb(0x80, base + 3); + outb(0x00, base); + outb(0x00, base + 1); + outb(0x00, base + 2); + outb(0x00, base + 3); + outb(0x80, base + 7); + outb(0x00, base + 4); + outb(0x00, base + 5); + outb(0x00, base + 6); + outb(0x00, base + 7); + + /* disable IRQ by default */ + inb(base + 0xB); + + err = gpiochip_irqchip_add(&dio48egpio->chip, &dio48e_irqchip, 0, + handle_edge_irq, IRQ_TYPE_NONE); + if (err) { + dev_err(dev, "Could not add irqchip (%d)\n", err); + goto err_gpiochip_irqchip_add; + } + + err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio); + if (err) { + dev_err(dev, "IRQ handler registering failed (%d)\n", err); + goto err_request_irq; + } + + return 0; + +err_request_irq: +err_gpiochip_irqchip_add: + gpiochip_remove(&dio48egpio->chip); +err_gpio_register: + release_region(base, extent); +err_lock_io_port: + return err; +} + +static int dio48e_remove(struct platform_device *pdev) +{ + struct dio48e_gpio *const dio48egpio = platform_get_drvdata(pdev); + + free_irq(dio48egpio->irq, dio48egpio); + gpiochip_remove(&dio48egpio->chip); + release_region(dio48egpio->base, dio48egpio->extent); + + return 0; +} + +static struct platform_device *dio48e_device; + +static struct platform_driver dio48e_driver = { + .driver = { + .name = "104-dio-48e" + }, + .remove = dio48e_remove +}; + +static void __exit dio48e_exit(void) +{ + platform_device_unregister(dio48e_device); + platform_driver_unregister(&dio48e_driver); +} + +static int __init dio48e_init(void) +{ + int err; + + dio48e_device = platform_device_alloc(dio48e_driver.driver.name, -1); + if (!dio48e_device) + return -ENOMEM; + + err = platform_device_add(dio48e_device); + if (err) + goto err_platform_device; + + err = platform_driver_probe(&dio48e_driver, dio48e_probe); + if (err) + goto err_platform_driver; + + return 0; + +err_platform_driver: + platform_device_del(dio48e_device); +err_platform_device: + platform_device_put(dio48e_device); + return err; +} + +module_init(dio48e_init); +module_exit(dio48e_exit); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit From 1920906f59652b9ac45dff69d56044a98b11233b Mon Sep 17 00:00:00 2001 From: Peter Hung Date: Fri, 22 Jan 2016 15:23:33 +0800 Subject: gpio-f7188x: Add F81866 GPIO supports Add F81866 GPIO supports Fintek F81866 is a SuperIO. It contains HWMON/GPIO/Serial Ports. and it has totally 72(9x8 sets) gpio pins. Here is the PDF spec: http://www.alldatasheet.com/datasheet-pdf/pdf/459085/FINTEK/F81866AD-I.html The control method is the same with F7188x, but we should care the address of GPIO8x. GPIO address is below: GPIO0x based: 0xf0 GPIO1x based: 0xe0 GPIO2x based: 0xd0 GPIO3x based: 0xc0 GPIO4x based: 0xb0 GPIO5x based: 0xa0 GPIO6x based: 0x90 GPIO7x based: 0x80 GPIO8x based: 0x88 <-- not 0x70. Signed-off-by: Peter Hung Acked-by: Simon Guinot Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 4 ++-- drivers/gpio/gpio-f7188x.c | 27 ++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5e317486a8cc..f9f52ec549b7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -515,10 +515,10 @@ config GPIO_104_IDI_48 via the idi_48_irq module parameter. config GPIO_F7188X - tristate "F71869, F71869A, F71882FG and F71889F GPIO support" + tristate "F71869, F71869A, F71882FG, F71889F and F81866 GPIO support" help This option enables support for GPIOs found on Fintek Super-I/O - chips F71869, F71869A, F71882FG and F71889F. + chips F71869, F71869A, F71882FG, F71889F and F81866. To compile this driver as a module, choose M here: the module will be called f7188x-gpio. diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index d62fd6bbaf82..0417798c45f1 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -1,5 +1,5 @@ /* - * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882 and F71889 + * GPIO driver for Fintek Super-I/O F71869, F71869A, F71882, F71889 and F81866 * * Copyright (C) 2010-2013 LaCie * @@ -36,14 +36,16 @@ #define SIO_F71869A_ID 0x1007 /* F71869A chipset ID */ #define SIO_F71882_ID 0x0541 /* F71882 chipset ID */ #define SIO_F71889_ID 0x0909 /* F71889 chipset ID */ +#define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ -enum chips { f71869, f71869a, f71882fg, f71889f }; +enum chips { f71869, f71869a, f71882fg, f71889f, f81866 }; static const char * const f7188x_names[] = { "f71869", "f71869a", "f71882fg", "f71889f", + "f81866", }; struct f7188x_sio { @@ -190,6 +192,18 @@ static struct f7188x_gpio_bank f71889_gpio_bank[] = { F7188X_GPIO_BANK(70, 8, 0x80), }; +static struct f7188x_gpio_bank f81866_gpio_bank[] = { + F7188X_GPIO_BANK(0, 8, 0xF0), + F7188X_GPIO_BANK(10, 8, 0xE0), + F7188X_GPIO_BANK(20, 8, 0xD0), + F7188X_GPIO_BANK(30, 8, 0xC0), + F7188X_GPIO_BANK(40, 8, 0xB0), + F7188X_GPIO_BANK(50, 8, 0xA0), + F7188X_GPIO_BANK(60, 8, 0x90), + F7188X_GPIO_BANK(70, 8, 0x80), + F7188X_GPIO_BANK(80, 8, 0x88), +}; + static int f7188x_gpio_direction_in(struct gpio_chip *chip, unsigned offset) { int err; @@ -318,6 +332,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev) data->nr_bank = ARRAY_SIZE(f71889_gpio_bank); data->bank = f71889_gpio_bank; break; + case f81866: + data->nr_bank = ARRAY_SIZE(f81866_gpio_bank); + data->bank = f81866_gpio_bank; + break; default: return -ENODEV; } @@ -395,6 +413,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) case SIO_F71889_ID: sio->type = f71889f; break; + case SIO_F81866_ID: + sio->type = f81866; + break; default: pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid); goto err; @@ -485,6 +506,6 @@ static void __exit f7188x_gpio_exit(void) } module_exit(f7188x_gpio_exit); -MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG and F71889F"); +MODULE_DESCRIPTION("GPIO driver for Super-I/O chips F71869, F71869A, F71882FG, F71889F and F81866"); MODULE_AUTHOR("Simon Guinot "); MODULE_LICENSE("GPL"); -- cgit From 1286558e45fd90fd0faf5d41df35f511c51f25e7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 22 Jan 2016 01:56:30 +0100 Subject: ath9k: do not limit the number of DFS channel interfaces to 1 I think this limit was added when CSA with multiple interfaces wasn't working yet. It should no longer be necessary Signed-off-by: Felix Fietkau Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath9k/init.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index ab7a1ac37849..d4e0ac946c3a 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -751,14 +751,6 @@ static const struct ieee80211_iface_combination if_comb_multi[] = { #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ -static const struct ieee80211_iface_limit if_dfs_limits[] = { - { .max = 1, .types = BIT(NL80211_IFTYPE_AP) | -#ifdef CONFIG_MAC80211_MESH - BIT(NL80211_IFTYPE_MESH_POINT) | -#endif - BIT(NL80211_IFTYPE_ADHOC) }, -}; - static const struct ieee80211_iface_combination if_comb[] = { { .limits = if_limits, @@ -766,6 +758,11 @@ static const struct ieee80211_iface_combination if_comb[] = { .max_interfaces = 2048, .num_different_channels = 1, .beacon_int_infra_match = true, +#ifdef CONFIG_ATH9K_DFS_CERTIFIED + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40), +#endif }, { .limits = wds_limits, @@ -774,18 +771,6 @@ static const struct ieee80211_iface_combination if_comb[] = { .num_different_channels = 1, .beacon_int_infra_match = true, }, -#ifdef CONFIG_ATH9K_DFS_CERTIFIED - { - .limits = if_dfs_limits, - .n_limits = ARRAY_SIZE(if_dfs_limits), - .max_interfaces = 1, - .num_different_channels = 1, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40), - } -#endif }; #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT -- cgit From 5df7fd46b70bcc5517dcfbd433719cea9ebe5eff Mon Sep 17 00:00:00 2001 From: Liu Gang Date: Tue, 12 Jan 2016 20:10:09 +0800 Subject: gpio/qoriq: Add qoriq platforms support The gpio-mpc8xxx.c should can support qoriq and Layerscape platforms. Signed-off-by: Liu Gang Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f9f52ec549b7..00f17673e7e0 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -281,12 +281,14 @@ config GPIO_MPC5200 depends on PPC_MPC52xx config GPIO_MPC8XXX - bool "MPC512x/MPC8xxx GPIO support" + bool "MPC512x/MPC8xxx/QorIQ GPIO support" depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ - FSL_SOC_BOOKE || PPC_86xx + FSL_SOC_BOOKE || PPC_86xx || ARCH_LAYERSCAPE || ARM || \ + COMPILE_TEST + select GPIO_GENERIC help Say Y here if you're going to use hardware that connects to the - MPC512x/831x/834x/837x/8572/8610 GPIOs. + MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. config GPIO_MVEBU def_bool y -- cgit From 5372381587e06a91ee4c1a0f2bf480a9100c21fd Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 27 Jan 2016 09:24:41 +0800 Subject: pinctrl: dt bindings: Add pinfunc header file for mt2701 Add pinfunc header file, mt2701 related dts will include it Signed-off-by: Biao Huang Acked-by: Linus Walleij Signed-off-by: Linus Walleij --- arch/arm/boot/dts/mt2701-pinfunc.h | 735 +++++++++++++++++++++++++++++++++++++ 1 file changed, 735 insertions(+) create mode 100644 arch/arm/boot/dts/mt2701-pinfunc.h diff --git a/arch/arm/boot/dts/mt2701-pinfunc.h b/arch/arm/boot/dts/mt2701-pinfunc.h new file mode 100644 index 000000000000..e24ebc8d928e --- /dev/null +++ b/arch/arm/boot/dts/mt2701-pinfunc.h @@ -0,0 +1,735 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Biao Huang + * + * 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 __DTS_MT2701_PINFUNC_H +#define __DTS_MT2701_PINFUNC_H + +#include + +#define MT2701_PIN_0_PWRAP_SPI0_MI__FUNC_GPIO0 (MTK_PIN_NO(0) | 0) +#define MT2701_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDO (MTK_PIN_NO(0) | 1) +#define MT2701_PIN_0_PWRAP_SPI0_MI__FUNC_PWRAP_SPIDI (MTK_PIN_NO(0) | 2) + +#define MT2701_PIN_1_PWRAP_SPI0_MO__FUNC_GPIO1 (MTK_PIN_NO(1) | 0) +#define MT2701_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDI (MTK_PIN_NO(1) | 1) +#define MT2701_PIN_1_PWRAP_SPI0_MO__FUNC_PWRAP_SPIDO (MTK_PIN_NO(1) | 2) + +#define MT2701_PIN_2_PWRAP_INT__FUNC_GPIO2 (MTK_PIN_NO(2) | 0) +#define MT2701_PIN_2_PWRAP_INT__FUNC_PWRAP_INT (MTK_PIN_NO(2) | 1) + +#define MT2701_PIN_3_PWRAP_SPI0_CK__FUNC_GPIO3 (MTK_PIN_NO(3) | 0) +#define MT2701_PIN_3_PWRAP_SPI0_CK__FUNC_PWRAP_SPICK_I (MTK_PIN_NO(3) | 1) + +#define MT2701_PIN_4_PWRAP_SPI0_CSN__FUNC_GPIO4 (MTK_PIN_NO(4) | 0) +#define MT2701_PIN_4_PWRAP_SPI0_CSN__FUNC_PWRAP_SPICS_B_I (MTK_PIN_NO(4) | 1) + +#define MT2701_PIN_5_PWRAP_SPI0_CK2__FUNC_GPIO5 (MTK_PIN_NO(5) | 0) +#define MT2701_PIN_5_PWRAP_SPI0_CK2__FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1) +#define MT2701_PIN_5_PWRAP_SPI0_CK2__FUNC_ANT_SEL1 (MTK_PIN_NO(5) | 5) + +#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_GPIO6 (MTK_PIN_NO(6) | 0) +#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1) +#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_ANT_SEL0 (MTK_PIN_NO(6) | 5) +#define MT2701_PIN_6_PWRAP_SPI0_CSN2__FUNC_DBG_MON_A_0 (MTK_PIN_NO(6) | 7) + +#define MT2701_PIN_7_SPI1_CSN__FUNC_GPIO7 (MTK_PIN_NO(7) | 0) +#define MT2701_PIN_7_SPI1_CSN__FUNC_SPI1_CS (MTK_PIN_NO(7) | 1) +#define MT2701_PIN_7_SPI1_CSN__FUNC_KCOL0 (MTK_PIN_NO(7) | 4) +#define MT2701_PIN_7_SPI1_CSN__FUNC_DBG_MON_B_12 (MTK_PIN_NO(7) | 7) + +#define MT2701_PIN_8_SPI1_MI__FUNC_GPIO8 (MTK_PIN_NO(8) | 0) +#define MT2701_PIN_8_SPI1_MI__FUNC_SPI1_MI (MTK_PIN_NO(8) | 1) +#define MT2701_PIN_8_SPI1_MI__FUNC_SPI1_MO (MTK_PIN_NO(8) | 2) +#define MT2701_PIN_8_SPI1_MI__FUNC_KCOL1 (MTK_PIN_NO(8) | 4) +#define MT2701_PIN_8_SPI1_MI__FUNC_DBG_MON_B_13 (MTK_PIN_NO(8) | 7) + +#define MT2701_PIN_9_SPI1_MO__FUNC_GPIO9 (MTK_PIN_NO(9) | 0) +#define MT2701_PIN_9_SPI1_MO__FUNC_SPI1_MO (MTK_PIN_NO(9) | 1) +#define MT2701_PIN_9_SPI1_MO__FUNC_SPI1_MI (MTK_PIN_NO(9) | 2) +#define MT2701_PIN_9_SPI1_MO__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(9) | 3) +#define MT2701_PIN_9_SPI1_MO__FUNC_KCOL2 (MTK_PIN_NO(9) | 4) +#define MT2701_PIN_9_SPI1_MO__FUNC_DBG_MON_B_14 (MTK_PIN_NO(9) | 7) + +#define MT2701_PIN_10_RTC32K_CK__FUNC_GPIO10 (MTK_PIN_NO(10) | 0) +#define MT2701_PIN_10_RTC32K_CK__FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1) + +#define MT2701_PIN_11_WATCHDOG__FUNC_GPIO11 (MTK_PIN_NO(11) | 0) +#define MT2701_PIN_11_WATCHDOG__FUNC_WATCHDOG (MTK_PIN_NO(11) | 1) + +#define MT2701_PIN_12_SRCLKENA__FUNC_GPIO12 (MTK_PIN_NO(12) | 0) +#define MT2701_PIN_12_SRCLKENA__FUNC_SRCLKENA (MTK_PIN_NO(12) | 1) + +#define MT2701_PIN_13_SRCLKENAI__FUNC_GPIO13 (MTK_PIN_NO(13) | 0) +#define MT2701_PIN_13_SRCLKENAI__FUNC_SRCLKENAI (MTK_PIN_NO(13) | 1) + +#define MT2701_PIN_14_URXD2__FUNC_GPIO14 (MTK_PIN_NO(14) | 0) +#define MT2701_PIN_14_URXD2__FUNC_URXD2 (MTK_PIN_NO(14) | 1) +#define MT2701_PIN_14_URXD2__FUNC_UTXD2 (MTK_PIN_NO(14) | 2) +#define MT2701_PIN_14_URXD2__FUNC_SRCCLKENAI2 (MTK_PIN_NO(14) | 5) +#define MT2701_PIN_14_URXD2__FUNC_DBG_MON_B_30 (MTK_PIN_NO(14) | 7) + +#define MT2701_PIN_15_UTXD2__FUNC_GPIO15 (MTK_PIN_NO(15) | 0) +#define MT2701_PIN_15_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(15) | 1) +#define MT2701_PIN_15_UTXD2__FUNC_URXD2 (MTK_PIN_NO(15) | 2) +#define MT2701_PIN_15_UTXD2__FUNC_DBG_MON_B_31 (MTK_PIN_NO(15) | 7) + +#define MT2701_PIN_18_PCM_CLK__FUNC_GPIO18 (MTK_PIN_NO(18) | 0) +#define MT2701_PIN_18_PCM_CLK__FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1) +#define MT2701_PIN_18_PCM_CLK__FUNC_MRG_CLK (MTK_PIN_NO(18) | 2) +#define MT2701_PIN_18_PCM_CLK__FUNC_MM_TEST_CK (MTK_PIN_NO(18) | 4) +#define MT2701_PIN_18_PCM_CLK__FUNC_CONN_DSP_JCK (MTK_PIN_NO(18) | 5) +#define MT2701_PIN_18_PCM_CLK__FUNC_WCN_PCM_CLKO (MTK_PIN_NO(18) | 6) +#define MT2701_PIN_18_PCM_CLK__FUNC_DBG_MON_A_3 (MTK_PIN_NO(18) | 7) + +#define MT2701_PIN_19_PCM_SYNC__FUNC_GPIO19 (MTK_PIN_NO(19) | 0) +#define MT2701_PIN_19_PCM_SYNC__FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1) +#define MT2701_PIN_19_PCM_SYNC__FUNC_MRG_SYNC (MTK_PIN_NO(19) | 2) +#define MT2701_PIN_19_PCM_SYNC__FUNC_CONN_DSP_JINTP (MTK_PIN_NO(19) | 5) +#define MT2701_PIN_19_PCM_SYNC__FUNC_WCN_PCM_SYNC (MTK_PIN_NO(19) | 6) +#define MT2701_PIN_19_PCM_SYNC__FUNC_DBG_MON_A_5 (MTK_PIN_NO(19) | 7) + +#define MT2701_PIN_20_PCM_RX__FUNC_GPIO20 (MTK_PIN_NO(20) | 0) +#define MT2701_PIN_20_PCM_RX__FUNC_PCM_RX (MTK_PIN_NO(20) | 1) +#define MT2701_PIN_20_PCM_RX__FUNC_MRG_RX (MTK_PIN_NO(20) | 2) +#define MT2701_PIN_20_PCM_RX__FUNC_MRG_TX (MTK_PIN_NO(20) | 3) +#define MT2701_PIN_20_PCM_RX__FUNC_PCM_TX (MTK_PIN_NO(20) | 4) +#define MT2701_PIN_20_PCM_RX__FUNC_CONN_DSP_JDI (MTK_PIN_NO(20) | 5) +#define MT2701_PIN_20_PCM_RX__FUNC_WCN_PCM_RX (MTK_PIN_NO(20) | 6) +#define MT2701_PIN_20_PCM_RX__FUNC_DBG_MON_A_4 (MTK_PIN_NO(20) | 7) + +#define MT2701_PIN_21_PCM_TX__FUNC_GPIO21 (MTK_PIN_NO(21) | 0) +#define MT2701_PIN_21_PCM_TX__FUNC_PCM_TX (MTK_PIN_NO(21) | 1) +#define MT2701_PIN_21_PCM_TX__FUNC_MRG_TX (MTK_PIN_NO(21) | 2) +#define MT2701_PIN_21_PCM_TX__FUNC_MRG_RX (MTK_PIN_NO(21) | 3) +#define MT2701_PIN_21_PCM_TX__FUNC_PCM_RX (MTK_PIN_NO(21) | 4) +#define MT2701_PIN_21_PCM_TX__FUNC_CONN_DSP_JMS (MTK_PIN_NO(21) | 5) +#define MT2701_PIN_21_PCM_TX__FUNC_WCN_PCM_TX (MTK_PIN_NO(21) | 6) +#define MT2701_PIN_21_PCM_TX__FUNC_DBG_MON_A_2 (MTK_PIN_NO(21) | 7) + +#define MT2701_PIN_22_EINT0__FUNC_GPIO22 (MTK_PIN_NO(22) | 0) +#define MT2701_PIN_22_EINT0__FUNC_UCTS0 (MTK_PIN_NO(22) | 1) +#define MT2701_PIN_22_EINT0__FUNC_KCOL3 (MTK_PIN_NO(22) | 3) +#define MT2701_PIN_22_EINT0__FUNC_CONN_DSP_JDO (MTK_PIN_NO(22) | 4) +#define MT2701_PIN_22_EINT0__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(22) | 5) +#define MT2701_PIN_22_EINT0__FUNC_DBG_MON_A_30 (MTK_PIN_NO(22) | 7) +#define MT2701_PIN_22_EINT0__FUNC_PCIE0_PERST_N (MTK_PIN_NO(22) | 10) + +#define MT2701_PIN_23_EINT1__FUNC_GPIO23 (MTK_PIN_NO(23) | 0) +#define MT2701_PIN_23_EINT1__FUNC_URTS0 (MTK_PIN_NO(23) | 1) +#define MT2701_PIN_23_EINT1__FUNC_KCOL2 (MTK_PIN_NO(23) | 3) +#define MT2701_PIN_23_EINT1__FUNC_CONN_MCU_TDO (MTK_PIN_NO(23) | 4) +#define MT2701_PIN_23_EINT1__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(23) | 5) +#define MT2701_PIN_23_EINT1__FUNC_DBG_MON_A_29 (MTK_PIN_NO(23) | 7) +#define MT2701_PIN_23_EINT1__FUNC_PCIE1_PERST_N (MTK_PIN_NO(23) | 10) + +#define MT2701_PIN_24_EINT2__FUNC_GPIO24 (MTK_PIN_NO(24) | 0) +#define MT2701_PIN_24_EINT2__FUNC_UCTS1 (MTK_PIN_NO(24) | 1) +#define MT2701_PIN_24_EINT2__FUNC_KCOL1 (MTK_PIN_NO(24) | 3) +#define MT2701_PIN_24_EINT2__FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(24) | 4) +#define MT2701_PIN_24_EINT2__FUNC_DBG_MON_A_28 (MTK_PIN_NO(24) | 7) +#define MT2701_PIN_24_EINT2__FUNC_PCIE2_PERST_N (MTK_PIN_NO(24) | 10) + +#define MT2701_PIN_25_EINT3__FUNC_GPIO25 (MTK_PIN_NO(25) | 0) +#define MT2701_PIN_25_EINT3__FUNC_URTS1 (MTK_PIN_NO(25) | 1) +#define MT2701_PIN_25_EINT3__FUNC_KCOL0 (MTK_PIN_NO(25) | 3) +#define MT2701_PIN_25_EINT3__FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(25) | 4) +#define MT2701_PIN_25_EINT3__FUNC_DBG_MON_A_27 (MTK_PIN_NO(25) | 7) + +#define MT2701_PIN_26_EINT4__FUNC_GPIO26 (MTK_PIN_NO(26) | 0) +#define MT2701_PIN_26_EINT4__FUNC_UCTS3 (MTK_PIN_NO(26) | 1) +#define MT2701_PIN_26_EINT4__FUNC_DRV_VBUS_P1 (MTK_PIN_NO(26) | 2) +#define MT2701_PIN_26_EINT4__FUNC_KROW3 (MTK_PIN_NO(26) | 3) +#define MT2701_PIN_26_EINT4__FUNC_CONN_MCU_TCK0 (MTK_PIN_NO(26) | 4) +#define MT2701_PIN_26_EINT4__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(26) | 5) +#define MT2701_PIN_26_EINT4__FUNC_PCIE2_WAKE_N (MTK_PIN_NO(26) | 6) +#define MT2701_PIN_26_EINT4__FUNC_DBG_MON_A_26 (MTK_PIN_NO(26) | 7) + +#define MT2701_PIN_27_EINT5__FUNC_GPIO27 (MTK_PIN_NO(27) | 0) +#define MT2701_PIN_27_EINT5__FUNC_URTS3 (MTK_PIN_NO(27) | 1) +#define MT2701_PIN_27_EINT5__FUNC_IDDIG_P1 (MTK_PIN_NO(27) | 2) +#define MT2701_PIN_27_EINT5__FUNC_KROW2 (MTK_PIN_NO(27) | 3) +#define MT2701_PIN_27_EINT5__FUNC_CONN_MCU_TDI (MTK_PIN_NO(27) | 4) +#define MT2701_PIN_27_EINT5__FUNC_PCIE1_WAKE_N (MTK_PIN_NO(27) | 6) +#define MT2701_PIN_27_EINT5__FUNC_DBG_MON_A_25 (MTK_PIN_NO(27) | 7) + +#define MT2701_PIN_28_EINT6__FUNC_GPIO28 (MTK_PIN_NO(28) | 0) +#define MT2701_PIN_28_EINT6__FUNC_DRV_VBUS (MTK_PIN_NO(28) | 1) +#define MT2701_PIN_28_EINT6__FUNC_KROW1 (MTK_PIN_NO(28) | 3) +#define MT2701_PIN_28_EINT6__FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(28) | 4) +#define MT2701_PIN_28_EINT6__FUNC_PCIE0_WAKE_N (MTK_PIN_NO(28) | 6) +#define MT2701_PIN_28_EINT6__FUNC_DBG_MON_A_24 (MTK_PIN_NO(28) | 7) + +#define MT2701_PIN_29_EINT7__FUNC_GPIO29 (MTK_PIN_NO(29) | 0) +#define MT2701_PIN_29_EINT7__FUNC_IDDIG (MTK_PIN_NO(29) | 1) +#define MT2701_PIN_29_EINT7__FUNC_MSDC1_WP (MTK_PIN_NO(29) | 2) +#define MT2701_PIN_29_EINT7__FUNC_KROW0 (MTK_PIN_NO(29) | 3) +#define MT2701_PIN_29_EINT7__FUNC_CONN_MCU_TMS (MTK_PIN_NO(29) | 4) +#define MT2701_PIN_29_EINT7__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(29) | 5) +#define MT2701_PIN_29_EINT7__FUNC_DBG_MON_A_23 (MTK_PIN_NO(29) | 7) +#define MT2701_PIN_29_EINT7__FUNC_PCIE2_PERST_N (MTK_PIN_NO(29) | 14) + +#define MT2701_PIN_33_I2S1_DATA__FUNC_GPIO33 (MTK_PIN_NO(33) | 0) +#define MT2701_PIN_33_I2S1_DATA__FUNC_I2S1_DATA (MTK_PIN_NO(33) | 1) +#define MT2701_PIN_33_I2S1_DATA__FUNC_I2S1_DATA_BYPS (MTK_PIN_NO(33) | 2) +#define MT2701_PIN_33_I2S1_DATA__FUNC_PCM_TX (MTK_PIN_NO(33) | 3) +#define MT2701_PIN_33_I2S1_DATA__FUNC_IMG_TEST_CK (MTK_PIN_NO(33) | 4) +#define MT2701_PIN_33_I2S1_DATA__FUNC_G1_RXD0 (MTK_PIN_NO(33) | 5) +#define MT2701_PIN_33_I2S1_DATA__FUNC_WCN_PCM_TX (MTK_PIN_NO(33) | 6) +#define MT2701_PIN_33_I2S1_DATA__FUNC_DBG_MON_B_8 (MTK_PIN_NO(33) | 7) + +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_GPIO34 (MTK_PIN_NO(34) | 0) +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_I2S1_DATA_IN (MTK_PIN_NO(34) | 1) +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_PCM_RX (MTK_PIN_NO(34) | 3) +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_VDEC_TEST_CK (MTK_PIN_NO(34) | 4) +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_G1_RXD1 (MTK_PIN_NO(34) | 5) +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_WCN_PCM_RX (MTK_PIN_NO(34) | 6) +#define MT2701_PIN_34_I2S1_DATA_IN__FUNC_DBG_MON_B_7 (MTK_PIN_NO(34) | 7) + +#define MT2701_PIN_35_I2S1_BCK__FUNC_GPIO35 (MTK_PIN_NO(35) | 0) +#define MT2701_PIN_35_I2S1_BCK__FUNC_I2S1_BCK (MTK_PIN_NO(35) | 1) +#define MT2701_PIN_35_I2S1_BCK__FUNC_PCM_CLK0 (MTK_PIN_NO(35) | 3) +#define MT2701_PIN_35_I2S1_BCK__FUNC_G1_RXD2 (MTK_PIN_NO(35) | 5) +#define MT2701_PIN_35_I2S1_BCK__FUNC_WCN_PCM_CLKO (MTK_PIN_NO(35) | 6) +#define MT2701_PIN_35_I2S1_BCK__FUNC_DBG_MON_B_9 (MTK_PIN_NO(35) | 7) + +#define MT2701_PIN_36_I2S1_LRCK__FUNC_GPIO36 (MTK_PIN_NO(36) | 0) +#define MT2701_PIN_36_I2S1_LRCK__FUNC_I2S1_LRCK (MTK_PIN_NO(36) | 1) +#define MT2701_PIN_36_I2S1_LRCK__FUNC_PCM_SYNC (MTK_PIN_NO(36) | 3) +#define MT2701_PIN_36_I2S1_LRCK__FUNC_G1_RXD3 (MTK_PIN_NO(36) | 5) +#define MT2701_PIN_36_I2S1_LRCK__FUNC_WCN_PCM_SYNC (MTK_PIN_NO(36) | 6) +#define MT2701_PIN_36_I2S1_LRCK__FUNC_DBG_MON_B_10 (MTK_PIN_NO(36) | 7) + +#define MT2701_PIN_37_I2S1_MCLK__FUNC_GPIO37 (MTK_PIN_NO(37) | 0) +#define MT2701_PIN_37_I2S1_MCLK__FUNC_I2S1_MCLK (MTK_PIN_NO(37) | 1) +#define MT2701_PIN_37_I2S1_MCLK__FUNC_G1_RXDV (MTK_PIN_NO(37) | 5) +#define MT2701_PIN_37_I2S1_MCLK__FUNC_DBG_MON_B_11 (MTK_PIN_NO(37) | 7) + +#define MT2701_PIN_39_JTMS__FUNC_GPIO39 (MTK_PIN_NO(39) | 0) +#define MT2701_PIN_39_JTMS__FUNC_JTMS (MTK_PIN_NO(39) | 1) +#define MT2701_PIN_39_JTMS__FUNC_CONN_MCU_TMS (MTK_PIN_NO(39) | 2) +#define MT2701_PIN_39_JTMS__FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(39) | 3) +#define MT2701_PIN_39_JTMS__FUNC_DFD_TMS_XI (MTK_PIN_NO(39) | 4) + +#define MT2701_PIN_40_JTCK__FUNC_GPIO40 (MTK_PIN_NO(40) | 0) +#define MT2701_PIN_40_JTCK__FUNC_JTCK (MTK_PIN_NO(40) | 1) +#define MT2701_PIN_40_JTCK__FUNC_CONN_MCU_TCK1 (MTK_PIN_NO(40) | 2) +#define MT2701_PIN_40_JTCK__FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(40) | 3) +#define MT2701_PIN_40_JTCK__FUNC_DFD_TCK_XI (MTK_PIN_NO(40) | 4) + +#define MT2701_PIN_41_JTDI__FUNC_GPIO41 (MTK_PIN_NO(41) | 0) +#define MT2701_PIN_41_JTDI__FUNC_JTDI (MTK_PIN_NO(41) | 1) +#define MT2701_PIN_41_JTDI__FUNC_CONN_MCU_TDI (MTK_PIN_NO(41) | 2) +#define MT2701_PIN_41_JTDI__FUNC_DFD_TDI_XI (MTK_PIN_NO(41) | 4) + +#define MT2701_PIN_42_JTDO__FUNC_GPIO42 (MTK_PIN_NO(42) | 0) +#define MT2701_PIN_42_JTDO__FUNC_JTDO (MTK_PIN_NO(42) | 1) +#define MT2701_PIN_42_JTDO__FUNC_CONN_MCU_TDO (MTK_PIN_NO(42) | 2) +#define MT2701_PIN_42_JTDO__FUNC_DFD_TDO (MTK_PIN_NO(42) | 4) + +#define MT2701_PIN_43_NCLE__FUNC_GPIO43 (MTK_PIN_NO(43) | 0) +#define MT2701_PIN_43_NCLE__FUNC_NCLE (MTK_PIN_NO(43) | 1) +#define MT2701_PIN_43_NCLE__FUNC_EXT_XCS2 (MTK_PIN_NO(43) | 2) + +#define MT2701_PIN_44_NCEB1__FUNC_GPIO44 (MTK_PIN_NO(44) | 0) +#define MT2701_PIN_44_NCEB1__FUNC_NCEB1 (MTK_PIN_NO(44) | 1) +#define MT2701_PIN_44_NCEB1__FUNC_IDDIG (MTK_PIN_NO(44) | 2) + +#define MT2701_PIN_45_NCEB0__FUNC_GPIO45 (MTK_PIN_NO(45) | 0) +#define MT2701_PIN_45_NCEB0__FUNC_NCEB0 (MTK_PIN_NO(45) | 1) +#define MT2701_PIN_45_NCEB0__FUNC_DRV_VBUS (MTK_PIN_NO(45) | 2) + +#define MT2701_PIN_46_IR__FUNC_GPIO46 (MTK_PIN_NO(46) | 0) +#define MT2701_PIN_46_IR__FUNC_IR (MTK_PIN_NO(46) | 1) + +#define MT2701_PIN_47_NREB__FUNC_GPIO47 (MTK_PIN_NO(47) | 0) +#define MT2701_PIN_47_NREB__FUNC_NREB (MTK_PIN_NO(47) | 1) +#define MT2701_PIN_47_NREB__FUNC_IDDIG_P1 (MTK_PIN_NO(47) | 2) + +#define MT2701_PIN_48_NRNB__FUNC_GPIO48 (MTK_PIN_NO(48) | 0) +#define MT2701_PIN_48_NRNB__FUNC_NRNB (MTK_PIN_NO(48) | 1) +#define MT2701_PIN_48_NRNB__FUNC_DRV_VBUS_P1 (MTK_PIN_NO(48) | 2) + +#define MT2701_PIN_49_I2S0_DATA__FUNC_GPIO49 (MTK_PIN_NO(49) | 0) +#define MT2701_PIN_49_I2S0_DATA__FUNC_I2S0_DATA (MTK_PIN_NO(49) | 1) +#define MT2701_PIN_49_I2S0_DATA__FUNC_I2S0_DATA_BYPS (MTK_PIN_NO(49) | 2) +#define MT2701_PIN_49_I2S0_DATA__FUNC_PCM_TX (MTK_PIN_NO(49) | 3) +#define MT2701_PIN_49_I2S0_DATA__FUNC_WCN_I2S_DO (MTK_PIN_NO(49) | 6) +#define MT2701_PIN_49_I2S0_DATA__FUNC_DBG_MON_B_3 (MTK_PIN_NO(49) | 7) + +#define MT2701_PIN_53_SPI0_CSN__FUNC_GPIO53 (MTK_PIN_NO(53) | 0) +#define MT2701_PIN_53_SPI0_CSN__FUNC_SPI0_CS (MTK_PIN_NO(53) | 1) +#define MT2701_PIN_53_SPI0_CSN__FUNC_SPDIF (MTK_PIN_NO(53) | 3) +#define MT2701_PIN_53_SPI0_CSN__FUNC_ADC_CK (MTK_PIN_NO(53) | 4) +#define MT2701_PIN_53_SPI0_CSN__FUNC_PWM1 (MTK_PIN_NO(53) | 5) +#define MT2701_PIN_53_SPI0_CSN__FUNC_DBG_MON_A_7 (MTK_PIN_NO(53) | 7) + +#define MT2701_PIN_54_SPI0_CK__FUNC_GPIO54 (MTK_PIN_NO(54) | 0) +#define MT2701_PIN_54_SPI0_CK__FUNC_SPI0_CK (MTK_PIN_NO(54) | 1) +#define MT2701_PIN_54_SPI0_CK__FUNC_SPDIF_IN1 (MTK_PIN_NO(54) | 3) +#define MT2701_PIN_54_SPI0_CK__FUNC_ADC_DAT_IN (MTK_PIN_NO(54) | 4) +#define MT2701_PIN_54_SPI0_CK__FUNC_DBG_MON_A_10 (MTK_PIN_NO(54) | 7) + +#define MT2701_PIN_55_SPI0_MI__FUNC_GPIO55 (MTK_PIN_NO(55) | 0) +#define MT2701_PIN_55_SPI0_MI__FUNC_SPI0_MI (MTK_PIN_NO(55) | 1) +#define MT2701_PIN_55_SPI0_MI__FUNC_SPI0_MO (MTK_PIN_NO(55) | 2) +#define MT2701_PIN_55_SPI0_MI__FUNC_MSDC1_WP (MTK_PIN_NO(55) | 3) +#define MT2701_PIN_55_SPI0_MI__FUNC_ADC_WS (MTK_PIN_NO(55) | 4) +#define MT2701_PIN_55_SPI0_MI__FUNC_PWM2 (MTK_PIN_NO(55) | 5) +#define MT2701_PIN_55_SPI0_MI__FUNC_DBG_MON_A_8 (MTK_PIN_NO(55) | 7) + +#define MT2701_PIN_56_SPI0_MO__FUNC_GPIO56 (MTK_PIN_NO(56) | 0) +#define MT2701_PIN_56_SPI0_MO__FUNC_SPI0_MO (MTK_PIN_NO(56) | 1) +#define MT2701_PIN_56_SPI0_MO__FUNC_SPI0_MI (MTK_PIN_NO(56) | 2) +#define MT2701_PIN_56_SPI0_MO__FUNC_SPDIF_IN0 (MTK_PIN_NO(56) | 3) +#define MT2701_PIN_56_SPI0_MO__FUNC_DBG_MON_A_9 (MTK_PIN_NO(56) | 7) + +#define MT2701_PIN_57_SDA1__FUNC_GPIO57 (MTK_PIN_NO(57) | 0) +#define MT2701_PIN_57_SDA1__FUNC_SDA1 (MTK_PIN_NO(57) | 1) + +#define MT2701_PIN_58_SCL1__FUNC_GPIO58 (MTK_PIN_NO(58) | 0) +#define MT2701_PIN_58_SCL1__FUNC_SCL1 (MTK_PIN_NO(58) | 1) + +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_GPIO72 (MTK_PIN_NO(72) | 0) +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_I2S0_DATA_IN (MTK_PIN_NO(72) | 1) +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_PCM_RX (MTK_PIN_NO(72) | 3) +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_PWM0 (MTK_PIN_NO(72) | 4) +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_DISP_PWM (MTK_PIN_NO(72) | 5) +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_WCN_I2S_DI (MTK_PIN_NO(72) | 6) +#define MT2701_PIN_72_I2S0_DATA_IN__FUNC_DBG_MON_B_2 (MTK_PIN_NO(72) | 7) + +#define MT2701_PIN_73_I2S0_LRCK__FUNC_GPIO73 (MTK_PIN_NO(73) | 0) +#define MT2701_PIN_73_I2S0_LRCK__FUNC_I2S0_LRCK (MTK_PIN_NO(73) | 1) +#define MT2701_PIN_73_I2S0_LRCK__FUNC_PCM_SYNC (MTK_PIN_NO(73) | 3) +#define MT2701_PIN_73_I2S0_LRCK__FUNC_WCN_I2S_LRCK (MTK_PIN_NO(73) | 6) +#define MT2701_PIN_73_I2S0_LRCK__FUNC_DBG_MON_B_5 (MTK_PIN_NO(73) | 7) + +#define MT2701_PIN_74_I2S0_BCK__FUNC_GPIO74 (MTK_PIN_NO(74) | 0) +#define MT2701_PIN_74_I2S0_BCK__FUNC_I2S0_BCK (MTK_PIN_NO(74) | 1) +#define MT2701_PIN_74_I2S0_BCK__FUNC_PCM_CLK0 (MTK_PIN_NO(74) | 3) +#define MT2701_PIN_74_I2S0_BCK__FUNC_WCN_I2S_BCK (MTK_PIN_NO(74) | 6) +#define MT2701_PIN_74_I2S0_BCK__FUNC_DBG_MON_B_4 (MTK_PIN_NO(74) | 7) + +#define MT2701_PIN_75_SDA0__FUNC_GPIO75 (MTK_PIN_NO(75) | 0) +#define MT2701_PIN_75_SDA0__FUNC_SDA0 (MTK_PIN_NO(75) | 1) + +#define MT2701_PIN_76_SCL0__FUNC_GPIO76 (MTK_PIN_NO(76) | 0) +#define MT2701_PIN_76_SCL0__FUNC_SCL0 (MTK_PIN_NO(76) | 1) + +#define MT2701_PIN_77_SDA2__FUNC_GPIO77 (MTK_PIN_NO(77) | 0) +#define MT2701_PIN_77_SDA2__FUNC_SDA2 (MTK_PIN_NO(77) | 1) + +#define MT2701_PIN_78_SCL2__FUNC_GPIO78 (MTK_PIN_NO(78) | 0) +#define MT2701_PIN_78_SCL2__FUNC_SCL2 (MTK_PIN_NO(78) | 1) + +#define MT2701_PIN_79_URXD0__FUNC_GPIO79 (MTK_PIN_NO(79) | 0) +#define MT2701_PIN_79_URXD0__FUNC_URXD0 (MTK_PIN_NO(79) | 1) +#define MT2701_PIN_79_URXD0__FUNC_UTXD0 (MTK_PIN_NO(79) | 2) +#define MT2701_PIN_79_URXD0__FUNC_ (MTK_PIN_NO(79) | 5) + +#define MT2701_PIN_80_UTXD0__FUNC_GPIO80 (MTK_PIN_NO(80) | 0) +#define MT2701_PIN_80_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(80) | 1) +#define MT2701_PIN_80_UTXD0__FUNC_URXD0 (MTK_PIN_NO(80) | 2) + +#define MT2701_PIN_81_URXD1__FUNC_GPIO81 (MTK_PIN_NO(81) | 0) +#define MT2701_PIN_81_URXD1__FUNC_URXD1 (MTK_PIN_NO(81) | 1) +#define MT2701_PIN_81_URXD1__FUNC_UTXD1 (MTK_PIN_NO(81) | 2) + +#define MT2701_PIN_82_UTXD1__FUNC_GPIO82 (MTK_PIN_NO(82) | 0) +#define MT2701_PIN_82_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(82) | 1) +#define MT2701_PIN_82_UTXD1__FUNC_URXD1 (MTK_PIN_NO(82) | 2) + +#define MT2701_PIN_83_LCM_RST__FUNC_GPIO83 (MTK_PIN_NO(83) | 0) +#define MT2701_PIN_83_LCM_RST__FUNC_LCM_RST (MTK_PIN_NO(83) | 1) +#define MT2701_PIN_83_LCM_RST__FUNC_VDAC_CK_XI (MTK_PIN_NO(83) | 2) +#define MT2701_PIN_83_LCM_RST__FUNC_DBG_MON_B_1 (MTK_PIN_NO(83) | 7) + +#define MT2701_PIN_84_DSI_TE__FUNC_GPIO84 (MTK_PIN_NO(84) | 0) +#define MT2701_PIN_84_DSI_TE__FUNC_DSI_TE (MTK_PIN_NO(84) | 1) +#define MT2701_PIN_84_DSI_TE__FUNC_DBG_MON_B_0 (MTK_PIN_NO(84) | 7) + +#define MT2701_PIN_91_TDN3__FUNC_GPI91 (MTK_PIN_NO(91) | 0) +#define MT2701_PIN_91_TDN3__FUNC_TDN3 (MTK_PIN_NO(91) | 1) + +#define MT2701_PIN_92_TDP3__FUNC_GPI92 (MTK_PIN_NO(92) | 0) +#define MT2701_PIN_92_TDP3__FUNC_TDP3 (MTK_PIN_NO(92) | 1) + +#define MT2701_PIN_93_TDN2__FUNC_GPI93 (MTK_PIN_NO(93) | 0) +#define MT2701_PIN_93_TDN2__FUNC_TDN2 (MTK_PIN_NO(93) | 1) + +#define MT2701_PIN_94_TDP2__FUNC_GPI94 (MTK_PIN_NO(94) | 0) +#define MT2701_PIN_94_TDP2__FUNC_TDP2 (MTK_PIN_NO(94) | 1) + +#define MT2701_PIN_95_TCN__FUNC_GPI95 (MTK_PIN_NO(95) | 0) +#define MT2701_PIN_95_TCN__FUNC_TCN (MTK_PIN_NO(95) | 1) + +#define MT2701_PIN_96_TCP__FUNC_GPI96 (MTK_PIN_NO(96) | 0) +#define MT2701_PIN_96_TCP__FUNC_TCP (MTK_PIN_NO(96) | 1) + +#define MT2701_PIN_97_TDN1__FUNC_GPI97 (MTK_PIN_NO(97) | 0) +#define MT2701_PIN_97_TDN1__FUNC_TDN1 (MTK_PIN_NO(97) | 1) + +#define MT2701_PIN_98_TDP1__FUNC_GPI98 (MTK_PIN_NO(98) | 0) +#define MT2701_PIN_98_TDP1__FUNC_TDP1 (MTK_PIN_NO(98) | 1) + +#define MT2701_PIN_99_TDN0__FUNC_GPI99 (MTK_PIN_NO(99) | 0) +#define MT2701_PIN_99_TDN0__FUNC_TDN0 (MTK_PIN_NO(99) | 1) + +#define MT2701_PIN_100_TDP0__FUNC_GPI100 (MTK_PIN_NO(100) | 0) +#define MT2701_PIN_100_TDP0__FUNC_TDP0 (MTK_PIN_NO(100) | 1) + +#define MT2701_PIN_101_SPI2_CSN__FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define MT2701_PIN_101_SPI2_CSN__FUNC_SPI2_CS (MTK_PIN_NO(101) | 1) +#define MT2701_PIN_101_SPI2_CSN__FUNC_SCL3 (MTK_PIN_NO(101) | 3) +#define MT2701_PIN_101_SPI2_CSN__FUNC_KROW0 (MTK_PIN_NO(101) | 4) + +#define MT2701_PIN_102_SPI2_MI__FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define MT2701_PIN_102_SPI2_MI__FUNC_SPI2_MI (MTK_PIN_NO(102) | 1) +#define MT2701_PIN_102_SPI2_MI__FUNC_SPI2_MO (MTK_PIN_NO(102) | 2) +#define MT2701_PIN_102_SPI2_MI__FUNC_SDA3 (MTK_PIN_NO(102) | 3) +#define MT2701_PIN_102_SPI2_MI__FUNC_KROW1 (MTK_PIN_NO(102) | 4) + +#define MT2701_PIN_103_SPI2_MO__FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define MT2701_PIN_103_SPI2_MO__FUNC_SPI2_MO (MTK_PIN_NO(103) | 1) +#define MT2701_PIN_103_SPI2_MO__FUNC_SPI2_MI (MTK_PIN_NO(103) | 2) +#define MT2701_PIN_103_SPI2_MO__FUNC_SCL3 (MTK_PIN_NO(103) | 3) +#define MT2701_PIN_103_SPI2_MO__FUNC_KROW2 (MTK_PIN_NO(103) | 4) + +#define MT2701_PIN_104_SPI2_CLK__FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define MT2701_PIN_104_SPI2_CLK__FUNC_SPI2_CK (MTK_PIN_NO(104) | 1) +#define MT2701_PIN_104_SPI2_CLK__FUNC_SDA3 (MTK_PIN_NO(104) | 3) +#define MT2701_PIN_104_SPI2_CLK__FUNC_KROW3 (MTK_PIN_NO(104) | 4) + +#define MT2701_PIN_105_MSDC1_CMD__FUNC_GPIO105 (MTK_PIN_NO(105) | 0) +#define MT2701_PIN_105_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(105) | 1) +#define MT2701_PIN_105_MSDC1_CMD__FUNC_ANT_SEL0 (MTK_PIN_NO(105) | 2) +#define MT2701_PIN_105_MSDC1_CMD__FUNC_SDA1 (MTK_PIN_NO(105) | 3) +#define MT2701_PIN_105_MSDC1_CMD__FUNC_I2SOUT_BCK (MTK_PIN_NO(105) | 6) +#define MT2701_PIN_105_MSDC1_CMD__FUNC_DBG_MON_B_27 (MTK_PIN_NO(105) | 7) + +#define MT2701_PIN_106_MSDC1_CLK__FUNC_GPIO106 (MTK_PIN_NO(106) | 0) +#define MT2701_PIN_106_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(106) | 1) +#define MT2701_PIN_106_MSDC1_CLK__FUNC_ANT_SEL1 (MTK_PIN_NO(106) | 2) +#define MT2701_PIN_106_MSDC1_CLK__FUNC_SCL1 (MTK_PIN_NO(106) | 3) +#define MT2701_PIN_106_MSDC1_CLK__FUNC_I2SOUT_LRCK (MTK_PIN_NO(106) | 6) +#define MT2701_PIN_106_MSDC1_CLK__FUNC_DBG_MON_B_28 (MTK_PIN_NO(106) | 7) + +#define MT2701_PIN_107_MSDC1_DAT0__FUNC_GPIO107 (MTK_PIN_NO(107) | 0) +#define MT2701_PIN_107_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(107) | 1) +#define MT2701_PIN_107_MSDC1_DAT0__FUNC_ANT_SEL2 (MTK_PIN_NO(107) | 2) +#define MT2701_PIN_107_MSDC1_DAT0__FUNC_UTXD0 (MTK_PIN_NO(107) | 5) +#define MT2701_PIN_107_MSDC1_DAT0__FUNC_I2SOUT_DATA_OUT (MTK_PIN_NO(107) | 6) +#define MT2701_PIN_107_MSDC1_DAT0__FUNC_DBG_MON_B_26 (MTK_PIN_NO(107) | 7) + +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_GPIO108 (MTK_PIN_NO(108) | 0) +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(108) | 1) +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_ANT_SEL3 (MTK_PIN_NO(108) | 2) +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_PWM0 (MTK_PIN_NO(108) | 3) +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_URXD0 (MTK_PIN_NO(108) | 5) +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_PWM1 (MTK_PIN_NO(108) | 6) +#define MT2701_PIN_108_MSDC1_DAT1__FUNC_DBG_MON_B_25 (MTK_PIN_NO(108) | 7) + +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_GPIO109 (MTK_PIN_NO(109) | 0) +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(109) | 1) +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_ANT_SEL4 (MTK_PIN_NO(109) | 2) +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_SDA2 (MTK_PIN_NO(109) | 3) +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_UTXD1 (MTK_PIN_NO(109) | 5) +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_PWM2 (MTK_PIN_NO(109) | 6) +#define MT2701_PIN_109_MSDC1_DAT2__FUNC_DBG_MON_B_24 (MTK_PIN_NO(109) | 7) + +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_GPIO110 (MTK_PIN_NO(110) | 0) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(110) | 1) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_ANT_SEL5 (MTK_PIN_NO(110) | 2) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_SCL2 (MTK_PIN_NO(110) | 3) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(110) | 4) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_URXD1 (MTK_PIN_NO(110) | 5) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_PWM3 (MTK_PIN_NO(110) | 6) +#define MT2701_PIN_110_MSDC1_DAT3__FUNC_DBG_MON_B_23 (MTK_PIN_NO(110) | 7) + +#define MT2701_PIN_111_MSDC0_DAT7__FUNC_GPIO111 (MTK_PIN_NO(111) | 0) +#define MT2701_PIN_111_MSDC0_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(111) | 1) +#define MT2701_PIN_111_MSDC0_DAT7__FUNC_NLD7 (MTK_PIN_NO(111) | 4) + +#define MT2701_PIN_112_MSDC0_DAT6__FUNC_GPIO112 (MTK_PIN_NO(112) | 0) +#define MT2701_PIN_112_MSDC0_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(112) | 1) +#define MT2701_PIN_112_MSDC0_DAT6__FUNC_NLD6 (MTK_PIN_NO(112) | 4) + +#define MT2701_PIN_113_MSDC0_DAT5__FUNC_GPIO113 (MTK_PIN_NO(113) | 0) +#define MT2701_PIN_113_MSDC0_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(113) | 1) +#define MT2701_PIN_113_MSDC0_DAT5__FUNC_NLD5 (MTK_PIN_NO(113) | 4) + +#define MT2701_PIN_114_MSDC0_DAT4__FUNC_GPIO114 (MTK_PIN_NO(114) | 0) +#define MT2701_PIN_114_MSDC0_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(114) | 1) +#define MT2701_PIN_114_MSDC0_DAT4__FUNC_NLD4 (MTK_PIN_NO(114) | 4) + +#define MT2701_PIN_115_MSDC0_RSTB__FUNC_GPIO115 (MTK_PIN_NO(115) | 0) +#define MT2701_PIN_115_MSDC0_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(115) | 1) +#define MT2701_PIN_115_MSDC0_RSTB__FUNC_NLD8 (MTK_PIN_NO(115) | 4) + +#define MT2701_PIN_116_MSDC0_CMD__FUNC_GPIO116 (MTK_PIN_NO(116) | 0) +#define MT2701_PIN_116_MSDC0_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(116) | 1) +#define MT2701_PIN_116_MSDC0_CMD__FUNC_NALE (MTK_PIN_NO(116) | 4) + +#define MT2701_PIN_117_MSDC0_CLK__FUNC_GPIO117 (MTK_PIN_NO(117) | 0) +#define MT2701_PIN_117_MSDC0_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(117) | 1) +#define MT2701_PIN_117_MSDC0_CLK__FUNC_NWEB (MTK_PIN_NO(117) | 4) + +#define MT2701_PIN_118_MSDC0_DAT3__FUNC_GPIO118 (MTK_PIN_NO(118) | 0) +#define MT2701_PIN_118_MSDC0_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(118) | 1) +#define MT2701_PIN_118_MSDC0_DAT3__FUNC_NLD3 (MTK_PIN_NO(118) | 4) + +#define MT2701_PIN_119_MSDC0_DAT2__FUNC_GPIO119 (MTK_PIN_NO(119) | 0) +#define MT2701_PIN_119_MSDC0_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(119) | 1) +#define MT2701_PIN_119_MSDC0_DAT2__FUNC_NLD2 (MTK_PIN_NO(119) | 4) + +#define MT2701_PIN_120_MSDC0_DAT1__FUNC_GPIO120 (MTK_PIN_NO(120) | 0) +#define MT2701_PIN_120_MSDC0_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(120) | 1) +#define MT2701_PIN_120_MSDC0_DAT1__FUNC_NLD1 (MTK_PIN_NO(120) | 4) + +#define MT2701_PIN_121_MSDC0_DAT0__FUNC_GPIO121 (MTK_PIN_NO(121) | 0) +#define MT2701_PIN_121_MSDC0_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(121) | 1) +#define MT2701_PIN_121_MSDC0_DAT0__FUNC_NLD0 (MTK_PIN_NO(121) | 4) +#define MT2701_PIN_121_MSDC0_DAT0__FUNC_WATCHDOG (MTK_PIN_NO(121) | 5) + +#define MT2701_PIN_122_CEC__FUNC_GPIO122 (MTK_PIN_NO(122) | 0) +#define MT2701_PIN_122_CEC__FUNC_CEC (MTK_PIN_NO(122) | 1) +#define MT2701_PIN_122_CEC__FUNC_SDA2 (MTK_PIN_NO(122) | 4) +#define MT2701_PIN_122_CEC__FUNC_URXD0 (MTK_PIN_NO(122) | 5) + +#define MT2701_PIN_123_HTPLG__FUNC_GPIO123 (MTK_PIN_NO(123) | 0) +#define MT2701_PIN_123_HTPLG__FUNC_HTPLG (MTK_PIN_NO(123) | 1) +#define MT2701_PIN_123_HTPLG__FUNC_SCL2 (MTK_PIN_NO(123) | 4) +#define MT2701_PIN_123_HTPLG__FUNC_UTXD0 (MTK_PIN_NO(123) | 5) + +#define MT2701_PIN_124_HDMISCK__FUNC_GPIO124 (MTK_PIN_NO(124) | 0) +#define MT2701_PIN_124_HDMISCK__FUNC_HDMISCK (MTK_PIN_NO(124) | 1) +#define MT2701_PIN_124_HDMISCK__FUNC_SDA1 (MTK_PIN_NO(124) | 4) +#define MT2701_PIN_124_HDMISCK__FUNC_PWM3 (MTK_PIN_NO(124) | 5) + +#define MT2701_PIN_125_HDMISD__FUNC_GPIO125 (MTK_PIN_NO(125) | 0) +#define MT2701_PIN_125_HDMISD__FUNC_HDMISD (MTK_PIN_NO(125) | 1) +#define MT2701_PIN_125_HDMISD__FUNC_SCL1 (MTK_PIN_NO(125) | 4) +#define MT2701_PIN_125_HDMISD__FUNC_PWM4 (MTK_PIN_NO(125) | 5) + +#define MT2701_PIN_126_I2S0_MCLK__FUNC_GPIO126 (MTK_PIN_NO(126) | 0) +#define MT2701_PIN_126_I2S0_MCLK__FUNC_I2S0_MCLK (MTK_PIN_NO(126) | 1) +#define MT2701_PIN_126_I2S0_MCLK__FUNC_WCN_I2S_MCLK (MTK_PIN_NO(126) | 6) +#define MT2701_PIN_126_I2S0_MCLK__FUNC_DBG_MON_B_6 (MTK_PIN_NO(126) | 7) + +#define MT2701_PIN_199_SPI1_CLK__FUNC_GPIO199 (MTK_PIN_NO(199) | 0) +#define MT2701_PIN_199_SPI1_CLK__FUNC_SPI1_CK (MTK_PIN_NO(199) | 1) +#define MT2701_PIN_199_SPI1_CLK__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(199) | 3) +#define MT2701_PIN_199_SPI1_CLK__FUNC_KCOL3 (MTK_PIN_NO(199) | 4) +#define MT2701_PIN_199_SPI1_CLK__FUNC_DBG_MON_B_15 (MTK_PIN_NO(199) | 7) + +#define MT2701_PIN_200_SPDIF_OUT__FUNC_GPIO200 (MTK_PIN_NO(200) | 0) +#define MT2701_PIN_200_SPDIF_OUT__FUNC_SPDIF_OUT (MTK_PIN_NO(200) | 1) +#define MT2701_PIN_200_SPDIF_OUT__FUNC_G1_TXD3 (MTK_PIN_NO(200) | 5) +#define MT2701_PIN_200_SPDIF_OUT__FUNC_URXD2 (MTK_PIN_NO(200) | 6) +#define MT2701_PIN_200_SPDIF_OUT__FUNC_DBG_MON_B_16 (MTK_PIN_NO(200) | 7) + +#define MT2701_PIN_201_SPDIF_IN0__FUNC_GPIO201 (MTK_PIN_NO(201) | 0) +#define MT2701_PIN_201_SPDIF_IN0__FUNC_SPDIF_IN0 (MTK_PIN_NO(201) | 1) +#define MT2701_PIN_201_SPDIF_IN0__FUNC_G1_TXEN (MTK_PIN_NO(201) | 5) +#define MT2701_PIN_201_SPDIF_IN0__FUNC_UTXD2 (MTK_PIN_NO(201) | 6) +#define MT2701_PIN_201_SPDIF_IN0__FUNC_DBG_MON_B_17 (MTK_PIN_NO(201) | 7) + +#define MT2701_PIN_202_SPDIF_IN1__FUNC_GPIO202 (MTK_PIN_NO(202) | 0) +#define MT2701_PIN_202_SPDIF_IN1__FUNC_SPDIF_IN1 (MTK_PIN_NO(202) | 1) + +#define MT2701_PIN_203_PWM0__FUNC_GPIO203 (MTK_PIN_NO(203) | 0) +#define MT2701_PIN_203_PWM0__FUNC_PWM0 (MTK_PIN_NO(203) | 1) +#define MT2701_PIN_203_PWM0__FUNC_DISP_PWM (MTK_PIN_NO(203) | 2) +#define MT2701_PIN_203_PWM0__FUNC_G1_TXD2 (MTK_PIN_NO(203) | 5) +#define MT2701_PIN_203_PWM0__FUNC_DBG_MON_B_18 (MTK_PIN_NO(203) | 7) +#define MT2701_PIN_203_PWM0__FUNC_I2S2_DATA (MTK_PIN_NO(203) | 9) + +#define MT2701_PIN_204_PWM1__FUNC_GPIO204 (MTK_PIN_NO(204) | 0) +#define MT2701_PIN_204_PWM1__FUNC_PWM1 (MTK_PIN_NO(204) | 1) +#define MT2701_PIN_204_PWM1__FUNC_CLKM3 (MTK_PIN_NO(204) | 2) +#define MT2701_PIN_204_PWM1__FUNC_G1_TXD1 (MTK_PIN_NO(204) | 5) +#define MT2701_PIN_204_PWM1__FUNC_DBG_MON_B_19 (MTK_PIN_NO(204) | 7) +#define MT2701_PIN_204_PWM1__FUNC_I2S3_DATA (MTK_PIN_NO(204) | 9) + +#define MT2701_PIN_205_PWM2__FUNC_GPIO205 (MTK_PIN_NO(205) | 0) +#define MT2701_PIN_205_PWM2__FUNC_PWM2 (MTK_PIN_NO(205) | 1) +#define MT2701_PIN_205_PWM2__FUNC_CLKM2 (MTK_PIN_NO(205) | 2) +#define MT2701_PIN_205_PWM2__FUNC_G1_TXD0 (MTK_PIN_NO(205) | 5) +#define MT2701_PIN_205_PWM2__FUNC_DBG_MON_B_20 (MTK_PIN_NO(205) | 7) + +#define MT2701_PIN_206_PWM3__FUNC_GPIO206 (MTK_PIN_NO(206) | 0) +#define MT2701_PIN_206_PWM3__FUNC_PWM3 (MTK_PIN_NO(206) | 1) +#define MT2701_PIN_206_PWM3__FUNC_CLKM1 (MTK_PIN_NO(206) | 2) +#define MT2701_PIN_206_PWM3__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(206) | 3) +#define MT2701_PIN_206_PWM3__FUNC_G1_TXC (MTK_PIN_NO(206) | 5) +#define MT2701_PIN_206_PWM3__FUNC_DBG_MON_B_21 (MTK_PIN_NO(206) | 7) + +#define MT2701_PIN_207_PWM4__FUNC_GPIO207 (MTK_PIN_NO(207) | 0) +#define MT2701_PIN_207_PWM4__FUNC_PWM4 (MTK_PIN_NO(207) | 1) +#define MT2701_PIN_207_PWM4__FUNC_CLKM0 (MTK_PIN_NO(207) | 2) +#define MT2701_PIN_207_PWM4__FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(207) | 3) +#define MT2701_PIN_207_PWM4__FUNC_G1_RXC (MTK_PIN_NO(207) | 5) +#define MT2701_PIN_207_PWM4__FUNC_DBG_MON_B_22 (MTK_PIN_NO(207) | 7) + +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_GPIO208 (MTK_PIN_NO(208) | 0) +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_AUD_EXT_CK1 (MTK_PIN_NO(208) | 1) +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_PWM0 (MTK_PIN_NO(208) | 2) +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_ANT_SEL5 (MTK_PIN_NO(208) | 4) +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_DISP_PWM (MTK_PIN_NO(208) | 5) +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_DBG_MON_A_31 (MTK_PIN_NO(208) | 7) +#define MT2701_PIN_208_AUD_EXT_CK1__FUNC_PCIE0_PERST_N (MTK_PIN_NO(208) | 11) + +#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_GPIO209 (MTK_PIN_NO(209) | 0) +#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_AUD_EXT_CK2 (MTK_PIN_NO(209) | 1) +#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_MSDC1_WP (MTK_PIN_NO(209) | 2) +#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_PWM1 (MTK_PIN_NO(209) | 5) +#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_DBG_MON_A_32 (MTK_PIN_NO(209) | 7) +#define MT2701_PIN_209_AUD_EXT_CK2__FUNC_PCIE1_PERST_N (MTK_PIN_NO(209) | 11) + +#define MT2701_PIN_236_EXT_SDIO3__FUNC_GPIO236 (MTK_PIN_NO(236) | 0) +#define MT2701_PIN_236_EXT_SDIO3__FUNC_EXT_SDIO3 (MTK_PIN_NO(236) | 1) +#define MT2701_PIN_236_EXT_SDIO3__FUNC_IDDIG (MTK_PIN_NO(236) | 2) +#define MT2701_PIN_236_EXT_SDIO3__FUNC_DBG_MON_A_1 (MTK_PIN_NO(236) | 7) + +#define MT2701_PIN_237_EXT_SDIO2__FUNC_GPIO237 (MTK_PIN_NO(237) | 0) +#define MT2701_PIN_237_EXT_SDIO2__FUNC_EXT_SDIO2 (MTK_PIN_NO(237) | 1) +#define MT2701_PIN_237_EXT_SDIO2__FUNC_DRV_VBUS (MTK_PIN_NO(237) | 2) + +#define MT2701_PIN_238_EXT_SDIO1__FUNC_GPIO238 (MTK_PIN_NO(238) | 0) +#define MT2701_PIN_238_EXT_SDIO1__FUNC_EXT_SDIO1 (MTK_PIN_NO(238) | 1) +#define MT2701_PIN_238_EXT_SDIO1__FUNC_IDDIG_P1 (MTK_PIN_NO(238) | 2) + +#define MT2701_PIN_239_EXT_SDIO0__FUNC_GPIO239 (MTK_PIN_NO(239) | 0) +#define MT2701_PIN_239_EXT_SDIO0__FUNC_EXT_SDIO0 (MTK_PIN_NO(239) | 1) +#define MT2701_PIN_239_EXT_SDIO0__FUNC_DRV_VBUS_P1 (MTK_PIN_NO(239) | 2) + +#define MT2701_PIN_240_EXT_XCS__FUNC_GPIO240 (MTK_PIN_NO(240) | 0) +#define MT2701_PIN_240_EXT_XCS__FUNC_EXT_XCS (MTK_PIN_NO(240) | 1) + +#define MT2701_PIN_241_EXT_SCK__FUNC_GPIO241 (MTK_PIN_NO(241) | 0) +#define MT2701_PIN_241_EXT_SCK__FUNC_EXT_SCK (MTK_PIN_NO(241) | 1) + +#define MT2701_PIN_242_URTS2__FUNC_GPIO242 (MTK_PIN_NO(242) | 0) +#define MT2701_PIN_242_URTS2__FUNC_URTS2 (MTK_PIN_NO(242) | 1) +#define MT2701_PIN_242_URTS2__FUNC_UTXD3 (MTK_PIN_NO(242) | 2) +#define MT2701_PIN_242_URTS2__FUNC_URXD3 (MTK_PIN_NO(242) | 3) +#define MT2701_PIN_242_URTS2__FUNC_SCL1 (MTK_PIN_NO(242) | 4) +#define MT2701_PIN_242_URTS2__FUNC_DBG_MON_B_32 (MTK_PIN_NO(242) | 7) + +#define MT2701_PIN_243_UCTS2__FUNC_GPIO243 (MTK_PIN_NO(243) | 0) +#define MT2701_PIN_243_UCTS2__FUNC_UCTS2 (MTK_PIN_NO(243) | 1) +#define MT2701_PIN_243_UCTS2__FUNC_URXD3 (MTK_PIN_NO(243) | 2) +#define MT2701_PIN_243_UCTS2__FUNC_UTXD3 (MTK_PIN_NO(243) | 3) +#define MT2701_PIN_243_UCTS2__FUNC_SDA1 (MTK_PIN_NO(243) | 4) +#define MT2701_PIN_243_UCTS2__FUNC_DBG_MON_A_6 (MTK_PIN_NO(243) | 7) + +#define MT2701_PIN_244_HDMI_SDA_RX__FUNC_GPIO244 (MTK_PIN_NO(244) | 0) +#define MT2701_PIN_244_HDMI_SDA_RX__FUNC_HDMI_SDA_RX (MTK_PIN_NO(244) | 1) + +#define MT2701_PIN_245_HDMI_SCL_RX__FUNC_GPIO245 (MTK_PIN_NO(245) | 0) +#define MT2701_PIN_245_HDMI_SCL_RX__FUNC_HDMI_SCL_RX (MTK_PIN_NO(245) | 1) + +#define MT2701_PIN_246_MHL_SENCE__FUNC_GPIO246 (MTK_PIN_NO(246) | 0) + +#define MT2701_PIN_247_HDMI_HPD_CBUS_RX__FUNC_GPIO247 (MTK_PIN_NO(247) | 0) +#define MT2701_PIN_247_HDMI_HPD_CBUS_RX__FUNC_HDMI_HPD_RX (MTK_PIN_NO(247) | 1) + +#define MT2701_PIN_248_HDMI_TESTOUTP_RX__FUNC_GPIO248 (MTK_PIN_NO(248) | 0) +#define MT2701_PIN_248_HDMI_TESTOUTP_RX__FUNC_HDMI_TESTOUTP_RX (MTK_PIN_NO(248) | 1) + +#define MT2701_PIN_249_MSDC0E_RSTB__FUNC_MSDC0E_RSTB (MTK_PIN_NO(249) | 9) + +#define MT2701_PIN_250_MSDC0E_DAT7__FUNC_MSDC3_DAT7 (MTK_PIN_NO(250) | 9) +#define MT2701_PIN_250_MSDC0E_DAT7__FUNC_PCIE0_CLKREQ_N (MTK_PIN_NO(250) | 14) + +#define MT2701_PIN_251_MSDC0E_DAT6__FUNC_MSDC3_DAT6 (MTK_PIN_NO(251) | 9) +#define MT2701_PIN_251_MSDC0E_DAT6__FUNC_PCIE0_WAKE_N (MTK_PIN_NO(251) | 14) + +#define MT2701_PIN_252_MSDC0E_DAT5__FUNC_MSDC3_DAT5 (MTK_PIN_NO(252) | 9) +#define MT2701_PIN_252_MSDC0E_DAT5__FUNC_PCIE1_CLKREQ_N (MTK_PIN_NO(252) | 14) + +#define MT2701_PIN_253_MSDC0E_DAT4__FUNC_MSDC3_DAT4 (MTK_PIN_NO(253) | 9) +#define MT2701_PIN_253_MSDC0E_DAT4__FUNC_PCIE1_WAKE_N (MTK_PIN_NO(253) | 14) + +#define MT2701_PIN_254_MSDC0E_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(254) | 9) +#define MT2701_PIN_254_MSDC0E_DAT3__FUNC_PCIE2_CLKREQ_N (MTK_PIN_NO(254) | 14) + +#define MT2701_PIN_255_MSDC0E_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(255) | 9) +#define MT2701_PIN_255_MSDC0E_DAT2__FUNC_PCIE2_WAKE_N (MTK_PIN_NO(255) | 14) + +#define MT2701_PIN_256_MSDC0E_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(256) | 9) + +#define MT2701_PIN_257_MSDC0E_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(257) | 9) + +#define MT2701_PIN_258_MSDC0E_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(258) | 9) + +#define MT2701_PIN_259_MSDC0E_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(259) | 9) + +#define MT2701_PIN_260_MSDC0E_DSL__FUNC_MSDC3_DSL (MTK_PIN_NO(260) | 9) + +#define MT2701_PIN_261_MSDC1_INS__FUNC_GPIO261 (MTK_PIN_NO(261) | 0) +#define MT2701_PIN_261_MSDC1_INS__FUNC_MSDC1_INS (MTK_PIN_NO(261) | 1) +#define MT2701_PIN_261_MSDC1_INS__FUNC_DBG_MON_B_29 (MTK_PIN_NO(261) | 7) + +#define MT2701_PIN_262_G2_TXEN__FUNC_GPIO262 (MTK_PIN_NO(262) | 0) +#define MT2701_PIN_262_G2_TXEN__FUNC_G2_TXEN (MTK_PIN_NO(262) | 1) + +#define MT2701_PIN_263_G2_TXD3__FUNC_GPIO263 (MTK_PIN_NO(263) | 0) +#define MT2701_PIN_263_G2_TXD3__FUNC_G2_TXD3 (MTK_PIN_NO(263) | 1) +#define MT2701_PIN_263_G2_TXD3__FUNC_ANT_SEL5 (MTK_PIN_NO(263) | 6) + +#define MT2701_PIN_264_G2_TXD2__FUNC_GPIO264 (MTK_PIN_NO(264) | 0) +#define MT2701_PIN_264_G2_TXD2__FUNC_G2_TXD2 (MTK_PIN_NO(264) | 1) +#define MT2701_PIN_264_G2_TXD2__FUNC_ANT_SEL4 (MTK_PIN_NO(264) | 6) + +#define MT2701_PIN_265_G2_TXD1__FUNC_GPIO265 (MTK_PIN_NO(265) | 0) +#define MT2701_PIN_265_G2_TXD1__FUNC_G2_TXD1 (MTK_PIN_NO(265) | 1) +#define MT2701_PIN_265_G2_TXD1__FUNC_ANT_SEL3 (MTK_PIN_NO(265) | 6) + +#define MT2701_PIN_266_G2_TXD0__FUNC_GPIO266 (MTK_PIN_NO(266) | 0) +#define MT2701_PIN_266_G2_TXD0__FUNC_G2_TXD0 (MTK_PIN_NO(266) | 1) +#define MT2701_PIN_266_G2_TXD0__FUNC_ANT_SEL2 (MTK_PIN_NO(266) | 6) + +#define MT2701_PIN_267_G2_TXC__FUNC_GPIO267 (MTK_PIN_NO(267) | 0) +#define MT2701_PIN_267_G2_TXC__FUNC_G2_TXC (MTK_PIN_NO(267) | 1) + +#define MT2701_PIN_268_G2_RXC__FUNC_GPIO268 (MTK_PIN_NO(268) | 0) +#define MT2701_PIN_268_G2_RXC__FUNC_G2_RXC (MTK_PIN_NO(268) | 1) + +#define MT2701_PIN_269_G2_RXD0__FUNC_GPIO269 (MTK_PIN_NO(269) | 0) +#define MT2701_PIN_269_G2_RXD0__FUNC_G2_RXD0 (MTK_PIN_NO(269) | 1) + +#define MT2701_PIN_270_G2_RXD1__FUNC_GPIO270 (MTK_PIN_NO(270) | 0) +#define MT2701_PIN_270_G2_RXD1__FUNC_G2_RXD1 (MTK_PIN_NO(270) | 1) + +#define MT2701_PIN_271_G2_RXD2__FUNC_GPIO271 (MTK_PIN_NO(271) | 0) +#define MT2701_PIN_271_G2_RXD2__FUNC_G2_RXD2 (MTK_PIN_NO(271) | 1) + +#define MT2701_PIN_272_G2_RXD3__FUNC_GPIO272 (MTK_PIN_NO(272) | 0) +#define MT2701_PIN_272_G2_RXD3__FUNC_G2_RXD3 (MTK_PIN_NO(272) | 1) + +#define MT2701_PIN_274_G2_RXDV__FUNC_GPIO274 (MTK_PIN_NO(274) | 0) +#define MT2701_PIN_274_G2_RXDV__FUNC_G2_RXDV (MTK_PIN_NO(274) | 1) + +#define MT2701_PIN_275_MDC__FUNC_GPIO275 (MTK_PIN_NO(275) | 0) +#define MT2701_PIN_275_MDC__FUNC_MDC (MTK_PIN_NO(275) | 1) +#define MT2701_PIN_275_MDC__FUNC_ANT_SEL0 (MTK_PIN_NO(275) | 6) + +#define MT2701_PIN_276_MDIO__FUNC_GPIO276 (MTK_PIN_NO(276) | 0) +#define MT2701_PIN_276_MDIO__FUNC_MDIO (MTK_PIN_NO(276) | 1) +#define MT2701_PIN_276_MDIO__FUNC_ANT_SEL1 (MTK_PIN_NO(276) | 6) + +#define MT2701_PIN_278_JTAG_RESET__FUNC_GPIO278 (MTK_PIN_NO(278) | 0) +#define MT2701_PIN_278_JTAG_RESET__FUNC_JTAG_RESET (MTK_PIN_NO(278) | 1) + +#endif /* __DTS_MT2701_PINFUNC_H */ -- cgit From 148b95eea00b15ee65a57fe1bd4256d325575e00 Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 27 Jan 2016 09:24:42 +0800 Subject: pinctrl: mediatek: Add Pinctrl/GPIO/EINT driver for mt2701 Add mt2701 support using mediatek common pinctrl driver. MT2701 have some special pins need an extra setting register than other ICs, so adding this support to common code. Signed-off-by: Biao Huang Acked-by: Yingjoe Chen Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/Kconfig | 6 + drivers/pinctrl/mediatek/Makefile | 1 + drivers/pinctrl/mediatek/pinctrl-mt2701.c | 586 +++++++ drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 14 + drivers/pinctrl/mediatek/pinctrl-mtk-common.h | 12 +- drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h | 2323 +++++++++++++++++++++++++ 6 files changed, 2941 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/mediatek/pinctrl-mt2701.c create mode 100644 drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 02f6f92df86c..13e9939d9b3a 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -9,6 +9,12 @@ config PINCTRL_MTK_COMMON select OF_GPIO # For ARMv7 SoCs +config PINCTRL_MT2701 + bool "Mediatek MT2701 pin control" if COMPILE_TEST && !MACH_MT2701 + depends on OF + default MACH_MT2701 + select PINCTRL_MTK_COMMON + config PINCTRL_MT8135 bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135 depends on OF diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index eb923d64d387..da30314a5ddc 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_PINCTRL_MTK_COMMON) += pinctrl-mtk-common.o # SoC Drivers +obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o diff --git a/drivers/pinctrl/mediatek/pinctrl-mt2701.c b/drivers/pinctrl/mediatek/pinctrl-mt2701.c new file mode 100644 index 000000000000..65b0d3e69b36 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mt2701.c @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Biao Huang + * + * 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 "pinctrl-mtk-common.h" +#include "pinctrl-mtk-mt2701.h" + +/** + * struct mtk_spec_pinmux_set + * - For special pins' mode setting + * @pin: The pin number. + * @offset: The offset of extra setting register. + * @bit: The bit of extra setting register. + */ +struct mtk_spec_pinmux_set { + unsigned short pin; + unsigned short offset; + unsigned char bit; +}; + +#define MTK_PINMUX_SPEC(_pin, _offset, _bit) \ + { \ + .pin = _pin, \ + .offset = _offset, \ + .bit = _bit, \ + } + +static const struct mtk_drv_group_desc mt2701_drv_grp[] = { + /* 0E4E8SR 4/8/12/16 */ + MTK_DRV_GRP(4, 16, 1, 2, 4), + /* 0E2E4SR 2/4/6/8 */ + MTK_DRV_GRP(2, 8, 1, 2, 2), + /* E8E4E2 2/4/6/8/10/12/14/16 */ + MTK_DRV_GRP(2, 16, 0, 2, 2) +}; + +static const struct mtk_pin_drv_grp mt2701_pin_drv[] = { + MTK_PIN_DRV_GRP(0, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(1, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(2, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(3, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(4, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(5, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(6, 0xf50, 0, 1), + MTK_PIN_DRV_GRP(7, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(8, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(9, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(10, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(11, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(12, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(13, 0xf50, 8, 1), + MTK_PIN_DRV_GRP(14, 0xf50, 12, 0), + MTK_PIN_DRV_GRP(15, 0xf50, 12, 0), + MTK_PIN_DRV_GRP(16, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(17, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(18, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(19, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(20, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(21, 0xf60, 4, 0), + MTK_PIN_DRV_GRP(22, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(23, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(24, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(25, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(26, 0xf60, 8, 0), + MTK_PIN_DRV_GRP(27, 0xf60, 12, 0), + MTK_PIN_DRV_GRP(28, 0xf60, 12, 0), + MTK_PIN_DRV_GRP(29, 0xf60, 12, 0), + MTK_PIN_DRV_GRP(30, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(31, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(32, 0xf60, 0, 0), + MTK_PIN_DRV_GRP(33, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(34, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(35, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(36, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(37, 0xf70, 0, 0), + MTK_PIN_DRV_GRP(38, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(39, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(40, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(41, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(42, 0xf70, 8, 1), + MTK_PIN_DRV_GRP(43, 0xf70, 12, 0), + MTK_PIN_DRV_GRP(44, 0xf70, 12, 0), + MTK_PIN_DRV_GRP(45, 0xf70, 12, 0), + MTK_PIN_DRV_GRP(47, 0xf80, 0, 0), + MTK_PIN_DRV_GRP(48, 0xf80, 0, 0), + MTK_PIN_DRV_GRP(49, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(50, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(51, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(52, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(53, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(54, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(55, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(56, 0xf80, 12, 0), + MTK_PIN_DRV_GRP(60, 0xf90, 8, 1), + MTK_PIN_DRV_GRP(61, 0xf90, 8, 1), + MTK_PIN_DRV_GRP(62, 0xf90, 8, 1), + MTK_PIN_DRV_GRP(63, 0xf90, 12, 1), + MTK_PIN_DRV_GRP(64, 0xf90, 12, 1), + MTK_PIN_DRV_GRP(65, 0xf90, 12, 1), + MTK_PIN_DRV_GRP(66, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(67, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(68, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(69, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(70, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(71, 0xfa0, 0, 1), + MTK_PIN_DRV_GRP(72, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(73, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(74, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(85, 0xda0, 0, 2), + MTK_PIN_DRV_GRP(86, 0xd90, 0, 2), + MTK_PIN_DRV_GRP(87, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(88, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(89, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(90, 0xdb0, 0, 2), + MTK_PIN_DRV_GRP(105, 0xd40, 0, 2), + MTK_PIN_DRV_GRP(106, 0xd30, 0, 2), + MTK_PIN_DRV_GRP(107, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(108, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(109, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(110, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(111, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(112, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(113, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(114, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(115, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(116, 0xcd0, 0, 2), + MTK_PIN_DRV_GRP(117, 0xcc0, 0, 2), + MTK_PIN_DRV_GRP(118, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(119, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(120, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(121, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(126, 0xf80, 4, 0), + MTK_PIN_DRV_GRP(188, 0xf70, 4, 0), + MTK_PIN_DRV_GRP(189, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(190, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(191, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(192, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(193, 0xfe0, 8, 0), + MTK_PIN_DRV_GRP(194, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(195, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(196, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(197, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(198, 0xfe0, 12, 0), + MTK_PIN_DRV_GRP(199, 0xf50, 4, 1), + MTK_PIN_DRV_GRP(200, 0xfd0, 0, 0), + MTK_PIN_DRV_GRP(201, 0xfd0, 0, 0), + MTK_PIN_DRV_GRP(202, 0xfd0, 0, 0), + MTK_PIN_DRV_GRP(203, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(204, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(205, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(206, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(207, 0xfd0, 4, 0), + MTK_PIN_DRV_GRP(208, 0xfd0, 8, 0), + MTK_PIN_DRV_GRP(209, 0xfd0, 8, 0), + MTK_PIN_DRV_GRP(210, 0xfd0, 12, 1), + MTK_PIN_DRV_GRP(211, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(212, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(213, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(214, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(215, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(216, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(217, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(218, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(219, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(220, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(221, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(222, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(223, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(224, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(225, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(226, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(227, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(228, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(229, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(230, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(231, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(232, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(233, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(234, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(235, 0xff0, 0, 1), + MTK_PIN_DRV_GRP(236, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(237, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(238, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(239, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(240, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(241, 0xff0, 4, 0), + MTK_PIN_DRV_GRP(242, 0xff0, 8, 0), + MTK_PIN_DRV_GRP(243, 0xff0, 8, 0), + MTK_PIN_DRV_GRP(248, 0xf00, 0, 0), + MTK_PIN_DRV_GRP(249, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(250, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(251, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(252, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(253, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(254, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(255, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(256, 0xfc0, 0, 2), + MTK_PIN_DRV_GRP(257, 0xce0, 0, 2), + MTK_PIN_DRV_GRP(258, 0xcb0, 0, 2), + MTK_PIN_DRV_GRP(259, 0xc90, 0, 2), + MTK_PIN_DRV_GRP(260, 0x3a0, 0, 2), + MTK_PIN_DRV_GRP(261, 0xd50, 0, 2), + MTK_PIN_DRV_GRP(262, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(263, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(264, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(265, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(266, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(267, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(268, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(269, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(270, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(271, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(272, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(273, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(274, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(275, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(276, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(277, 0xf00, 8, 0), + MTK_PIN_DRV_GRP(278, 0xf70, 8, 1), +}; + +static const struct mtk_pin_spec_pupd_set_samereg mt2701_spec_pupd[] = { + MTK_PIN_PUPD_SPEC_SR(111, 0xd00, 12, 13, 14), /* ms0 data7 */ + MTK_PIN_PUPD_SPEC_SR(112, 0xd00, 8, 9, 10), /* ms0 data6 */ + MTK_PIN_PUPD_SPEC_SR(113, 0xd00, 4, 5, 6), /* ms0 data5 */ + MTK_PIN_PUPD_SPEC_SR(114, 0xd00, 0, 1, 2), /* ms0 data4 */ + MTK_PIN_PUPD_SPEC_SR(115, 0xd10, 0, 1, 2), /* ms0 rstb */ + MTK_PIN_PUPD_SPEC_SR(116, 0xcd0, 8, 9, 10), /* ms0 cmd */ + MTK_PIN_PUPD_SPEC_SR(117, 0xcc0, 8, 9, 10), /* ms0 clk */ + MTK_PIN_PUPD_SPEC_SR(118, 0xcf0, 12, 13, 14), /* ms0 data3 */ + MTK_PIN_PUPD_SPEC_SR(119, 0xcf0, 8, 9, 10), /* ms0 data2 */ + MTK_PIN_PUPD_SPEC_SR(120, 0xcf0, 4, 5, 6), /* ms0 data1 */ + MTK_PIN_PUPD_SPEC_SR(121, 0xcf0, 0, 1, 2), /* ms0 data0 */ + + MTK_PIN_PUPD_SPEC_SR(105, 0xd40, 8, 9, 10), /* ms1 cmd */ + MTK_PIN_PUPD_SPEC_SR(106, 0xd30, 8, 9, 10), /* ms1 clk */ + MTK_PIN_PUPD_SPEC_SR(107, 0xd60, 0, 1, 2), /* ms1 dat0 */ + MTK_PIN_PUPD_SPEC_SR(108, 0xd60, 10, 9, 8), /* ms1 dat1 */ + MTK_PIN_PUPD_SPEC_SR(109, 0xd60, 4, 5, 6), /* ms1 dat2 */ + MTK_PIN_PUPD_SPEC_SR(110, 0xc60, 12, 13, 14), /* ms1 dat3 */ + + MTK_PIN_PUPD_SPEC_SR(85, 0xda0, 8, 9, 10), /* ms2 cmd */ + MTK_PIN_PUPD_SPEC_SR(86, 0xd90, 8, 9, 10), /* ms2 clk */ + MTK_PIN_PUPD_SPEC_SR(87, 0xdc0, 0, 1, 2), /* ms2 dat0 */ + MTK_PIN_PUPD_SPEC_SR(88, 0xdc0, 10, 9, 8), /* ms2 dat1 */ + MTK_PIN_PUPD_SPEC_SR(89, 0xdc0, 4, 5, 6), /* ms2 dat2 */ + MTK_PIN_PUPD_SPEC_SR(90, 0xdc0, 12, 13, 14), /* ms2 dat3 */ + + MTK_PIN_PUPD_SPEC_SR(249, 0x140, 0, 1, 2), /* ms0e rstb */ + MTK_PIN_PUPD_SPEC_SR(250, 0x130, 12, 13, 14), /* ms0e dat7 */ + MTK_PIN_PUPD_SPEC_SR(251, 0x130, 8, 9, 10), /* ms0e dat6 */ + MTK_PIN_PUPD_SPEC_SR(252, 0x130, 4, 5, 6), /* ms0e dat5 */ + MTK_PIN_PUPD_SPEC_SR(253, 0x130, 0, 1, 2), /* ms0e dat4 */ + MTK_PIN_PUPD_SPEC_SR(254, 0xf40, 12, 13, 14), /* ms0e dat3 */ + MTK_PIN_PUPD_SPEC_SR(255, 0xf40, 8, 9, 10), /* ms0e dat2 */ + MTK_PIN_PUPD_SPEC_SR(256, 0xf40, 4, 5, 6), /* ms0e dat1 */ + MTK_PIN_PUPD_SPEC_SR(257, 0xf40, 0, 1, 2), /* ms0e dat0 */ + MTK_PIN_PUPD_SPEC_SR(258, 0xcb0, 8, 9, 10), /* ms0e cmd */ + MTK_PIN_PUPD_SPEC_SR(259, 0xc90, 8, 9, 10), /* ms0e clk */ + MTK_PIN_PUPD_SPEC_SR(261, 0x140, 8, 9, 10), /* ms1 ins */ +}; + +static int mt2701_spec_pull_set(struct regmap *regmap, unsigned int pin, + unsigned char align, bool isup, unsigned int r1r0) +{ + return mtk_pctrl_spec_pull_set_samereg(regmap, mt2701_spec_pupd, + ARRAY_SIZE(mt2701_spec_pupd), pin, align, isup, r1r0); +} + +static const struct mtk_pin_ies_smt_set mt2701_ies_set[] = { + MTK_PIN_IES_SMT_SPEC(0, 6, 0xb20, 0), + MTK_PIN_IES_SMT_SPEC(7, 9, 0xb20, 1), + MTK_PIN_IES_SMT_SPEC(10, 13, 0xb30, 3), + MTK_PIN_IES_SMT_SPEC(14, 15, 0xb30, 13), + MTK_PIN_IES_SMT_SPEC(16, 17, 0xb40, 7), + MTK_PIN_IES_SMT_SPEC(18, 21, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(22, 26, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(27, 29, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(30, 32, 0xb40, 7), + MTK_PIN_IES_SMT_SPEC(33, 37, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(38, 38, 0xb20, 13), + MTK_PIN_IES_SMT_SPEC(39, 42, 0xb40, 13), + MTK_PIN_IES_SMT_SPEC(43, 45, 0xb20, 10), + MTK_PIN_IES_SMT_SPEC(47, 48, 0xb20, 11), + MTK_PIN_IES_SMT_SPEC(49, 49, 0xb20, 12), + MTK_PIN_IES_SMT_SPEC(50, 52, 0xb20, 13), + MTK_PIN_IES_SMT_SPEC(53, 56, 0xb20, 14), + MTK_PIN_IES_SMT_SPEC(57, 58, 0xb20, 15), + MTK_PIN_IES_SMT_SPEC(59, 59, 0xb30, 10), + MTK_PIN_IES_SMT_SPEC(60, 62, 0xb30, 0), + MTK_PIN_IES_SMT_SPEC(63, 65, 0xb30, 1), + MTK_PIN_IES_SMT_SPEC(66, 71, 0xb30, 2), + MTK_PIN_IES_SMT_SPEC(72, 74, 0xb20, 12), + MTK_PIN_IES_SMT_SPEC(75, 76, 0xb30, 3), + MTK_PIN_IES_SMT_SPEC(77, 78, 0xb30, 4), + MTK_PIN_IES_SMT_SPEC(79, 82, 0xb30, 5), + MTK_PIN_IES_SMT_SPEC(83, 84, 0xb30, 2), + MTK_PIN_IES_SMT_SPEC(85, 85, 0xda0, 4), + MTK_PIN_IES_SMT_SPEC(86, 86, 0xd90, 4), + MTK_PIN_IES_SMT_SPEC(87, 90, 0xdb0, 4), + MTK_PIN_IES_SMT_SPEC(101, 104, 0xb30, 6), + MTK_PIN_IES_SMT_SPEC(105, 105, 0xd40, 4), + MTK_PIN_IES_SMT_SPEC(106, 106, 0xd30, 4), + MTK_PIN_IES_SMT_SPEC(107, 110, 0xd50, 4), + MTK_PIN_IES_SMT_SPEC(111, 115, 0xce0, 4), + MTK_PIN_IES_SMT_SPEC(116, 116, 0xcd0, 4), + MTK_PIN_IES_SMT_SPEC(117, 117, 0xcc0, 4), + MTK_PIN_IES_SMT_SPEC(118, 121, 0xce0, 4), + MTK_PIN_IES_SMT_SPEC(122, 125, 0xb30, 7), + MTK_PIN_IES_SMT_SPEC(126, 126, 0xb20, 12), + MTK_PIN_IES_SMT_SPEC(127, 142, 0xb30, 9), + MTK_PIN_IES_SMT_SPEC(143, 160, 0xb30, 10), + MTK_PIN_IES_SMT_SPEC(161, 168, 0xb30, 12), + MTK_PIN_IES_SMT_SPEC(169, 183, 0xb30, 10), + MTK_PIN_IES_SMT_SPEC(184, 186, 0xb30, 9), + MTK_PIN_IES_SMT_SPEC(187, 187, 0xb30, 14), + MTK_PIN_IES_SMT_SPEC(188, 188, 0xb20, 13), + MTK_PIN_IES_SMT_SPEC(189, 193, 0xb30, 15), + MTK_PIN_IES_SMT_SPEC(194, 198, 0xb40, 0), + MTK_PIN_IES_SMT_SPEC(199, 199, 0xb20, 1), + MTK_PIN_IES_SMT_SPEC(200, 202, 0xb40, 1), + MTK_PIN_IES_SMT_SPEC(203, 207, 0xb40, 2), + MTK_PIN_IES_SMT_SPEC(208, 209, 0xb40, 3), + MTK_PIN_IES_SMT_SPEC(210, 210, 0xb40, 4), + MTK_PIN_IES_SMT_SPEC(211, 235, 0xb40, 5), + MTK_PIN_IES_SMT_SPEC(236, 241, 0xb40, 6), + MTK_PIN_IES_SMT_SPEC(242, 243, 0xb40, 7), + MTK_PIN_IES_SMT_SPEC(244, 247, 0xb40, 8), + MTK_PIN_IES_SMT_SPEC(248, 248, 0xb40, 9), + MTK_PIN_IES_SMT_SPEC(249, 257, 0xfc0, 4), + MTK_PIN_IES_SMT_SPEC(258, 258, 0xcb0, 4), + MTK_PIN_IES_SMT_SPEC(259, 259, 0xc90, 4), + MTK_PIN_IES_SMT_SPEC(260, 260, 0x3a0, 4), + MTK_PIN_IES_SMT_SPEC(261, 261, 0xd50, 4), + MTK_PIN_IES_SMT_SPEC(262, 277, 0xb40, 12), + MTK_PIN_IES_SMT_SPEC(278, 278, 0xb40, 13), +}; + +static const struct mtk_pin_ies_smt_set mt2701_smt_set[] = { + MTK_PIN_IES_SMT_SPEC(0, 6, 0xb50, 0), + MTK_PIN_IES_SMT_SPEC(7, 9, 0xb50, 1), + MTK_PIN_IES_SMT_SPEC(10, 13, 0xb60, 3), + MTK_PIN_IES_SMT_SPEC(14, 15, 0xb60, 13), + MTK_PIN_IES_SMT_SPEC(16, 17, 0xb70, 7), + MTK_PIN_IES_SMT_SPEC(18, 21, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(22, 26, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(27, 29, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(30, 32, 0xb70, 7), + MTK_PIN_IES_SMT_SPEC(33, 37, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(38, 38, 0xb50, 13), + MTK_PIN_IES_SMT_SPEC(39, 42, 0xb70, 13), + MTK_PIN_IES_SMT_SPEC(43, 45, 0xb50, 10), + MTK_PIN_IES_SMT_SPEC(47, 48, 0xb50, 11), + MTK_PIN_IES_SMT_SPEC(49, 49, 0xb50, 12), + MTK_PIN_IES_SMT_SPEC(50, 52, 0xb50, 13), + MTK_PIN_IES_SMT_SPEC(53, 56, 0xb50, 14), + MTK_PIN_IES_SMT_SPEC(57, 58, 0xb50, 15), + MTK_PIN_IES_SMT_SPEC(59, 59, 0xb60, 10), + MTK_PIN_IES_SMT_SPEC(60, 62, 0xb60, 0), + MTK_PIN_IES_SMT_SPEC(63, 65, 0xb60, 1), + MTK_PIN_IES_SMT_SPEC(66, 71, 0xb60, 2), + MTK_PIN_IES_SMT_SPEC(72, 74, 0xb50, 12), + MTK_PIN_IES_SMT_SPEC(75, 76, 0xb60, 3), + MTK_PIN_IES_SMT_SPEC(77, 78, 0xb60, 4), + MTK_PIN_IES_SMT_SPEC(79, 82, 0xb60, 5), + MTK_PIN_IES_SMT_SPEC(83, 84, 0xb60, 2), + MTK_PIN_IES_SMT_SPEC(85, 85, 0xda0, 11), + MTK_PIN_IES_SMT_SPEC(86, 86, 0xd90, 11), + MTK_PIN_IES_SMT_SPEC(87, 87, 0xdc0, 3), + MTK_PIN_IES_SMT_SPEC(88, 88, 0xdc0, 7), + MTK_PIN_IES_SMT_SPEC(89, 89, 0xdc0, 11), + MTK_PIN_IES_SMT_SPEC(90, 90, 0xdc0, 15), + MTK_PIN_IES_SMT_SPEC(101, 104, 0xb60, 6), + MTK_PIN_IES_SMT_SPEC(105, 105, 0xd40, 11), + MTK_PIN_IES_SMT_SPEC(106, 106, 0xd30, 11), + MTK_PIN_IES_SMT_SPEC(107, 107, 0xd60, 3), + MTK_PIN_IES_SMT_SPEC(108, 108, 0xd60, 7), + MTK_PIN_IES_SMT_SPEC(109, 109, 0xd60, 11), + MTK_PIN_IES_SMT_SPEC(110, 110, 0xd60, 15), + MTK_PIN_IES_SMT_SPEC(111, 111, 0xd00, 15), + MTK_PIN_IES_SMT_SPEC(112, 112, 0xd00, 11), + MTK_PIN_IES_SMT_SPEC(113, 113, 0xd00, 7), + MTK_PIN_IES_SMT_SPEC(114, 114, 0xd00, 3), + MTK_PIN_IES_SMT_SPEC(115, 115, 0xd10, 3), + MTK_PIN_IES_SMT_SPEC(116, 116, 0xcd0, 11), + MTK_PIN_IES_SMT_SPEC(117, 117, 0xcc0, 11), + MTK_PIN_IES_SMT_SPEC(118, 118, 0xcf0, 15), + MTK_PIN_IES_SMT_SPEC(119, 119, 0xcf0, 11), + MTK_PIN_IES_SMT_SPEC(120, 120, 0xcf0, 7), + MTK_PIN_IES_SMT_SPEC(121, 121, 0xcf0, 3), + MTK_PIN_IES_SMT_SPEC(122, 125, 0xb60, 7), + MTK_PIN_IES_SMT_SPEC(126, 126, 0xb50, 12), + MTK_PIN_IES_SMT_SPEC(127, 142, 0xb60, 9), + MTK_PIN_IES_SMT_SPEC(143, 160, 0xb60, 10), + MTK_PIN_IES_SMT_SPEC(161, 168, 0xb60, 12), + MTK_PIN_IES_SMT_SPEC(169, 183, 0xb60, 10), + MTK_PIN_IES_SMT_SPEC(184, 186, 0xb60, 9), + MTK_PIN_IES_SMT_SPEC(187, 187, 0xb60, 14), + MTK_PIN_IES_SMT_SPEC(188, 188, 0xb50, 13), + MTK_PIN_IES_SMT_SPEC(189, 193, 0xb60, 15), + MTK_PIN_IES_SMT_SPEC(194, 198, 0xb70, 0), + MTK_PIN_IES_SMT_SPEC(199, 199, 0xb50, 1), + MTK_PIN_IES_SMT_SPEC(200, 202, 0xb70, 1), + MTK_PIN_IES_SMT_SPEC(203, 207, 0xb70, 2), + MTK_PIN_IES_SMT_SPEC(208, 209, 0xb70, 3), + MTK_PIN_IES_SMT_SPEC(210, 210, 0xb70, 4), + MTK_PIN_IES_SMT_SPEC(211, 235, 0xb70, 5), + MTK_PIN_IES_SMT_SPEC(236, 241, 0xb70, 6), + MTK_PIN_IES_SMT_SPEC(242, 243, 0xb70, 7), + MTK_PIN_IES_SMT_SPEC(244, 247, 0xb70, 8), + MTK_PIN_IES_SMT_SPEC(248, 248, 0xb70, 9), + MTK_PIN_IES_SMT_SPEC(249, 249, 0x140, 3), + MTK_PIN_IES_SMT_SPEC(250, 250, 0x130, 15), + MTK_PIN_IES_SMT_SPEC(251, 251, 0x130, 11), + MTK_PIN_IES_SMT_SPEC(252, 252, 0x130, 7), + MTK_PIN_IES_SMT_SPEC(253, 253, 0x130, 3), + MTK_PIN_IES_SMT_SPEC(254, 254, 0xf40, 15), + MTK_PIN_IES_SMT_SPEC(255, 255, 0xf40, 11), + MTK_PIN_IES_SMT_SPEC(256, 256, 0xf40, 7), + MTK_PIN_IES_SMT_SPEC(257, 257, 0xf40, 3), + MTK_PIN_IES_SMT_SPEC(258, 258, 0xcb0, 11), + MTK_PIN_IES_SMT_SPEC(259, 259, 0xc90, 11), + MTK_PIN_IES_SMT_SPEC(260, 260, 0x3a0, 11), + MTK_PIN_IES_SMT_SPEC(261, 261, 0x0b0, 3), + MTK_PIN_IES_SMT_SPEC(262, 277, 0xb70, 12), + MTK_PIN_IES_SMT_SPEC(278, 278, 0xb70, 13), +}; + +static int mt2701_ies_smt_set(struct regmap *regmap, unsigned int pin, + unsigned char align, int value, enum pin_config_param arg) +{ + if (arg == PIN_CONFIG_INPUT_ENABLE) + return mtk_pconf_spec_set_ies_smt_range(regmap, mt2701_ies_set, + ARRAY_SIZE(mt2701_ies_set), pin, align, value); + else if (arg == PIN_CONFIG_INPUT_SCHMITT_ENABLE) + return mtk_pconf_spec_set_ies_smt_range(regmap, mt2701_smt_set, + ARRAY_SIZE(mt2701_smt_set), pin, align, value); + return -EINVAL; +} + +static const struct mtk_spec_pinmux_set mt2701_spec_pinmux[] = { + MTK_PINMUX_SPEC(22, 0xb10, 3), + MTK_PINMUX_SPEC(23, 0xb10, 4), + MTK_PINMUX_SPEC(24, 0xb10, 5), + MTK_PINMUX_SPEC(29, 0xb10, 9), + MTK_PINMUX_SPEC(208, 0xb10, 7), + MTK_PINMUX_SPEC(209, 0xb10, 8), + MTK_PINMUX_SPEC(203, 0xf20, 0), + MTK_PINMUX_SPEC(204, 0xf20, 1), + MTK_PINMUX_SPEC(249, 0xef0, 0), + MTK_PINMUX_SPEC(250, 0xef0, 0), + MTK_PINMUX_SPEC(251, 0xef0, 0), + MTK_PINMUX_SPEC(252, 0xef0, 0), + MTK_PINMUX_SPEC(253, 0xef0, 0), + MTK_PINMUX_SPEC(254, 0xef0, 0), + MTK_PINMUX_SPEC(255, 0xef0, 0), + MTK_PINMUX_SPEC(256, 0xef0, 0), + MTK_PINMUX_SPEC(257, 0xef0, 0), + MTK_PINMUX_SPEC(258, 0xef0, 0), + MTK_PINMUX_SPEC(259, 0xef0, 0), + MTK_PINMUX_SPEC(260, 0xef0, 0), +}; + +static void mt2701_spec_pinmux_set(struct regmap *reg, unsigned int pin, + unsigned int mode) +{ + unsigned int i, value, mask; + unsigned int info_num = ARRAY_SIZE(mt2701_spec_pinmux); + unsigned int spec_flag; + + for (i = 0; i < info_num; i++) { + if (pin == mt2701_spec_pinmux[i].pin) + break; + } + + if (i == info_num) + return; + + spec_flag = (mode >> 3); + mask = BIT(mt2701_spec_pinmux[i].bit); + if (!spec_flag) + value = mask; + else + value = 0; + regmap_update_bits(reg, mt2701_spec_pinmux[i].offset, mask, value); +} + +static void mt2701_spec_dir_set(unsigned int *reg_addr, unsigned int pin) +{ + if (pin > 175) + *reg_addr += 0x10; +} + +static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = { + .pins = mtk_pins_mt2701, + .npins = ARRAY_SIZE(mtk_pins_mt2701), + .grp_desc = mt2701_drv_grp, + .n_grp_cls = ARRAY_SIZE(mt2701_drv_grp), + .pin_drv_grp = mt2701_pin_drv, + .n_pin_drv_grps = ARRAY_SIZE(mt2701_pin_drv), + .spec_pull_set = mt2701_spec_pull_set, + .spec_ies_smt_set = mt2701_ies_smt_set, + .spec_pinmux_set = mt2701_spec_pinmux_set, + .spec_dir_set = mt2701_spec_dir_set, + .dir_offset = 0x0000, + .pullen_offset = 0x0150, + .pullsel_offset = 0x0280, + .dout_offset = 0x0500, + .din_offset = 0x0630, + .pinmux_offset = 0x0760, + .type1_start = 280, + .type1_end = 280, + .port_shf = 4, + .port_mask = 0x1f, + .port_align = 4, + .eint_offsets = { + .name = "mt2701_eint", + .stat = 0x000, + .ack = 0x040, + .mask = 0x080, + .mask_set = 0x0c0, + .mask_clr = 0x100, + .sens = 0x140, + .sens_set = 0x180, + .sens_clr = 0x1c0, + .soft = 0x200, + .soft_set = 0x240, + .soft_clr = 0x280, + .pol = 0x300, + .pol_set = 0x340, + .pol_clr = 0x380, + .dom_en = 0x400, + .dbnc_ctrl = 0x500, + .dbnc_set = 0x600, + .dbnc_clr = 0x700, + .port_mask = 6, + .ports = 6, + }, + .ap_num = 169, + .db_cnt = 16, +}; + +static int mt2701_pinctrl_probe(struct platform_device *pdev) +{ + return mtk_pctrl_init(pdev, &mt2701_pinctrl_data, NULL); +} + +static const struct of_device_id mt2701_pctrl_match[] = { + { .compatible = "mediatek,mt2701-pinctrl", }, + {} +}; +MODULE_DEVICE_TABLE(of, mt2701_pctrl_match); + +static struct platform_driver mtk_pinctrl_driver = { + .probe = mt2701_pinctrl_probe, + .driver = { + .name = "mediatek-mt2701-pinctrl", + .owner = THIS_MODULE, + .of_match_table = mt2701_pctrl_match, + .pm = &mtk_eint_pm_ops, + }, +}; + +static int __init mtk_pinctrl_init(void) +{ + return platform_driver_register(&mtk_pinctrl_driver); +} +arch_initcall(mtk_pinctrl_init); diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 16d48a4ed225..8cac73d9c382 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -47,6 +47,8 @@ static const char * const mtk_gpio_functions[] = { "func0", "func1", "func2", "func3", "func4", "func5", "func6", "func7", + "func8", "func9", "func10", "func11", + "func12", "func13", "func14", "func15", }; /* @@ -81,6 +83,9 @@ static int mtk_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset; bit = BIT(offset & 0xf); + if (pctl->devdata->spec_dir_set) + pctl->devdata->spec_dir_set(®_addr, offset); + if (input) /* Different SoC has different alignment offset. */ reg_addr = CLR_ADDR(reg_addr, pctl); @@ -675,9 +680,14 @@ static int mtk_pmx_set_mode(struct pinctrl_dev *pctldev, unsigned int mask = (1L << GPIO_MODE_BITS) - 1; struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + if (pctl->devdata->spec_pinmux_set) + pctl->devdata->spec_pinmux_set(mtk_get_regmap(pctl, pin), + pin, mode); + reg_addr = ((pin / MAX_GPIO_MODE_PER_REG) << pctl->devdata->port_shf) + pctl->devdata->pinmux_offset; + mode &= mask; bit = pin % MAX_GPIO_MODE_PER_REG; mask <<= (GPIO_MODE_BITS * bit); val = (mode << (GPIO_MODE_BITS * bit)); @@ -754,6 +764,10 @@ static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned offset) reg_addr = mtk_get_port(pctl, offset) + pctl->devdata->dir_offset; bit = BIT(offset & 0xf); + + if (pctl->devdata->spec_dir_set) + pctl->devdata->spec_dir_set(®_addr, offset); + regmap_read(pctl->regmap1, reg_addr, &read_val); return !(read_val & bit); } diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h index 55a534338931..8543bc478a1e 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.h @@ -209,7 +209,14 @@ struct mtk_eint_offsets { * means when user set smt, input enable is set at the same time. So they * also need special control. If special control is success, this should * return 0, otherwise return non-zero value. - * + * @spec_pinmux_set: In some cases, there are two pinmux functions share + * the same value in the same segment of pinmux control register. If user + * want to use one of the two functions, they need an extra bit setting to + * select the right one. + * @spec_dir_set: In very few SoCs, direction control registers are not + * arranged continuously, they may be cut to parts. So they need special + * dir setting. + * @dir_offset: The direction register offset. * @pullen_offset: The pull-up/pull-down enable register offset. * @pinmux_offset: The pinmux register offset. @@ -234,6 +241,9 @@ struct mtk_pinctrl_devdata { unsigned char align, bool isup, unsigned int arg); int (*spec_ies_smt_set)(struct regmap *reg, unsigned int pin, unsigned char align, int value, enum pin_config_param arg); + void (*spec_pinmux_set)(struct regmap *reg, unsigned int pin, + unsigned int mode); + void (*spec_dir_set)(unsigned int *reg_addr, unsigned int pin); unsigned int dir_offset; unsigned int ies_offset; unsigned int smt_offset; diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h new file mode 100644 index 000000000000..f90642078c31 --- /dev/null +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt2701.h @@ -0,0 +1,2323 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: Biao Huang + * + * 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 __PINCTRL_MTK_MT2701_H +#define __PINCTRL_MTK_MT2701_H + +#include +#include "pinctrl-mtk-common.h" + +static const struct mtk_desc_pin mtk_pins_mt2701[] = { + MTK_PIN( + PINCTRL_PIN(0, "PWRAP_SPI0_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 148), + MTK_FUNCTION(0, "GPIO0"), + MTK_FUNCTION(1, "PWRAP_SPIDO"), + MTK_FUNCTION(2, "PWRAP_SPIDI") + ), + MTK_PIN( + PINCTRL_PIN(1, "PWRAP_SPI0_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 149), + MTK_FUNCTION(0, "GPIO1"), + MTK_FUNCTION(1, "PWRAP_SPIDI"), + MTK_FUNCTION(2, "PWRAP_SPIDO") + ), + MTK_PIN( + PINCTRL_PIN(2, "PWRAP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 150), + MTK_FUNCTION(0, "GPIO2"), + MTK_FUNCTION(1, "PWRAP_INT") + ), + MTK_PIN( + PINCTRL_PIN(3, "PWRAP_SPI0_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 151), + MTK_FUNCTION(0, "GPIO3"), + MTK_FUNCTION(1, "PWRAP_SPICK_I") + ), + MTK_PIN( + PINCTRL_PIN(4, "PWRAP_SPI0_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 152), + MTK_FUNCTION(0, "GPIO4"), + MTK_FUNCTION(1, "PWRAP_SPICS_B_I") + ), + MTK_PIN( + PINCTRL_PIN(5, "PWRAP_SPI0_CK2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 153), + MTK_FUNCTION(0, "GPIO5"), + MTK_FUNCTION(1, "PWRAP_SPICK2_I"), + MTK_FUNCTION(5, "ANT_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(6, "PWRAP_SPI0_CSN2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 154), + MTK_FUNCTION(0, "GPIO6"), + MTK_FUNCTION(1, "PWRAP_SPICS2_B_I"), + MTK_FUNCTION(5, "ANT_SEL0"), + MTK_FUNCTION(7, "DBG_MON_A[0]") + ), + MTK_PIN( + PINCTRL_PIN(7, "SPI1_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 155), + MTK_FUNCTION(0, "GPIO7"), + MTK_FUNCTION(1, "SPI1_CS"), + MTK_FUNCTION(4, "KCOL0"), + MTK_FUNCTION(7, "DBG_MON_B[12]") + ), + MTK_PIN( + PINCTRL_PIN(8, "SPI1_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 156), + MTK_FUNCTION(0, "GPIO8"), + MTK_FUNCTION(1, "SPI1_MI"), + MTK_FUNCTION(2, "SPI1_MO"), + MTK_FUNCTION(4, "KCOL1"), + MTK_FUNCTION(7, "DBG_MON_B[13]") + ), + MTK_PIN( + PINCTRL_PIN(9, "SPI1_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 157), + MTK_FUNCTION(0, "GPIO9"), + MTK_FUNCTION(1, "SPI1_MO"), + MTK_FUNCTION(2, "SPI1_MI"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "KCOL2"), + MTK_FUNCTION(7, "DBG_MON_B[14]") + ), + MTK_PIN( + PINCTRL_PIN(10, "RTC32K_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 158), + MTK_FUNCTION(0, "GPIO10"), + MTK_FUNCTION(1, "RTC32K_CK") + ), + MTK_PIN( + PINCTRL_PIN(11, "WATCHDOG"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 159), + MTK_FUNCTION(0, "GPIO11"), + MTK_FUNCTION(1, "WATCHDOG") + ), + MTK_PIN( + PINCTRL_PIN(12, "SRCLKENA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 160), + MTK_FUNCTION(0, "GPIO12"), + MTK_FUNCTION(1, "SRCLKENA") + ), + MTK_PIN( + PINCTRL_PIN(13, "SRCLKENAI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 161), + MTK_FUNCTION(0, "GPIO13"), + MTK_FUNCTION(1, "SRCLKENAI") + ), + MTK_PIN( + PINCTRL_PIN(14, "URXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 162), + MTK_FUNCTION(0, "GPIO14"), + MTK_FUNCTION(1, "URXD2"), + MTK_FUNCTION(2, "UTXD2"), + MTK_FUNCTION(5, "SRCCLKENAI2"), + MTK_FUNCTION(7, "DBG_MON_B[30]") + ), + MTK_PIN( + PINCTRL_PIN(15, "UTXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 163), + MTK_FUNCTION(0, "GPIO15"), + MTK_FUNCTION(1, "UTXD2"), + MTK_FUNCTION(2, "URXD2"), + MTK_FUNCTION(7, "DBG_MON_B[31]") + ), + MTK_PIN( + PINCTRL_PIN(16, "I2S5_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 164), + MTK_FUNCTION(0, "GPIO16"), + MTK_FUNCTION(1, "I2S5_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "ANT_SEL4") + ), + MTK_PIN( + PINCTRL_PIN(17, "I2S5_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 165), + MTK_FUNCTION(0, "GPIO17"), + MTK_FUNCTION(1, "I2S5_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(4, "ANT_SEL2") + ), + MTK_PIN( + PINCTRL_PIN(18, "PCM_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 166), + MTK_FUNCTION(0, "GPIO18"), + MTK_FUNCTION(1, "PCM_CLK0"), + MTK_FUNCTION(2, "MRG_CLK"), + MTK_FUNCTION(4, "MM_TEST_CK"), + MTK_FUNCTION(5, "CONN_DSP_JCK"), + MTK_FUNCTION(6, "WCN_PCM_CLKO"), + MTK_FUNCTION(7, "DBG_MON_A[3]") + ), + MTK_PIN( + PINCTRL_PIN(19, "PCM_SYNC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 167), + MTK_FUNCTION(0, "GPIO19"), + MTK_FUNCTION(1, "PCM_SYNC"), + MTK_FUNCTION(2, "MRG_SYNC"), + MTK_FUNCTION(5, "CONN_DSP_JINTP"), + MTK_FUNCTION(6, "WCN_PCM_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A[5]") + ), + MTK_PIN( + PINCTRL_PIN(20, "PCM_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO20"), + MTK_FUNCTION(1, "PCM_RX"), + MTK_FUNCTION(2, "MRG_RX"), + MTK_FUNCTION(3, "MRG_TX"), + MTK_FUNCTION(4, "PCM_TX"), + MTK_FUNCTION(5, "CONN_DSP_JDI"), + MTK_FUNCTION(6, "WCN_PCM_RX"), + MTK_FUNCTION(7, "DBG_MON_A[4]") + ), + MTK_PIN( + PINCTRL_PIN(21, "PCM_TX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO21"), + MTK_FUNCTION(1, "PCM_TX"), + MTK_FUNCTION(2, "MRG_TX"), + MTK_FUNCTION(3, "MRG_RX"), + MTK_FUNCTION(4, "PCM_RX"), + MTK_FUNCTION(5, "CONN_DSP_JMS"), + MTK_FUNCTION(6, "WCN_PCM_TX"), + MTK_FUNCTION(7, "DBG_MON_A[2]") + ), + MTK_PIN( + PINCTRL_PIN(22, "EINT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 0), + MTK_FUNCTION(0, "GPIO22"), + MTK_FUNCTION(1, "UCTS0"), + MTK_FUNCTION(3, "KCOL3"), + MTK_FUNCTION(4, "CONN_DSP_JDO"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A[30]"), + MTK_FUNCTION(10, "PCIE0_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(23, "EINT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 1), + MTK_FUNCTION(0, "GPIO23"), + MTK_FUNCTION(1, "URTS0"), + MTK_FUNCTION(3, "KCOL2"), + MTK_FUNCTION(4, "CONN_MCU_TDO"), + MTK_FUNCTION(5, "EXT_FRAME_SYNC"), + MTK_FUNCTION(7, "DBG_MON_A[29]"), + MTK_FUNCTION(10, "PCIE1_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(24, "EINT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 2), + MTK_FUNCTION(0, "GPIO24"), + MTK_FUNCTION(1, "UCTS1"), + MTK_FUNCTION(3, "KCOL1"), + MTK_FUNCTION(4, "CONN_MCU_DBGACK_N"), + MTK_FUNCTION(7, "DBG_MON_A[28]"), + MTK_FUNCTION(10, "PCIE2_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(25, "EINT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 3), + MTK_FUNCTION(0, "GPIO25"), + MTK_FUNCTION(1, "URTS1"), + MTK_FUNCTION(3, "KCOL0"), + MTK_FUNCTION(4, "CONN_MCU_DBGI_N"), + MTK_FUNCTION(7, "DBG_MON_A[27]") + ), + MTK_PIN( + PINCTRL_PIN(26, "EINT4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 4), + MTK_FUNCTION(0, "GPIO26"), + MTK_FUNCTION(1, "UCTS3"), + MTK_FUNCTION(2, "DRV_VBUS_P1"), + MTK_FUNCTION(3, "KROW3"), + MTK_FUNCTION(4, "CONN_MCU_TCK0"), + MTK_FUNCTION(5, "CONN_MCU_AICE_JCKC"), + MTK_FUNCTION(6, "PCIE2_WAKE_N"), + MTK_FUNCTION(7, "DBG_MON_A[26]") + ), + MTK_PIN( + PINCTRL_PIN(27, "EINT5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 5), + MTK_FUNCTION(0, "GPIO27"), + MTK_FUNCTION(1, "URTS3"), + MTK_FUNCTION(2, "IDDIG_P1"), + MTK_FUNCTION(3, "KROW2"), + MTK_FUNCTION(4, "CONN_MCU_TDI"), + MTK_FUNCTION(6, "PCIE1_WAKE_N"), + MTK_FUNCTION(7, "DBG_MON_A[25]") + ), + MTK_PIN( + PINCTRL_PIN(28, "EINT6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 6), + MTK_FUNCTION(0, "GPIO28"), + MTK_FUNCTION(1, "DRV_VBUS"), + MTK_FUNCTION(3, "KROW1"), + MTK_FUNCTION(4, "CONN_MCU_TRST_B"), + MTK_FUNCTION(6, "PCIE0_WAKE_N"), + MTK_FUNCTION(7, "DBG_MON_A[24]") + ), + MTK_PIN( + PINCTRL_PIN(29, "EINT7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 7), + MTK_FUNCTION(0, "GPIO29"), + MTK_FUNCTION(1, "IDDIG"), + MTK_FUNCTION(2, "MSDC1_WP"), + MTK_FUNCTION(3, "KROW0"), + MTK_FUNCTION(4, "CONN_MCU_TMS"), + MTK_FUNCTION(5, "CONN_MCU_AICE_JMSC"), + MTK_FUNCTION(7, "DBG_MON_A[23]"), + MTK_FUNCTION(14, "PCIE2_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(30, "I2S5_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 12), + MTK_FUNCTION(0, "GPIO30"), + MTK_FUNCTION(1, "I2S5_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(4, "ANT_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(31, "I2S5_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 13), + MTK_FUNCTION(0, "GPIO31"), + MTK_FUNCTION(1, "I2S5_MCLK"), + MTK_FUNCTION(4, "ANT_SEL0") + ), + MTK_PIN( + PINCTRL_PIN(32, "I2S5_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 14), + MTK_FUNCTION(0, "GPIO32"), + MTK_FUNCTION(1, "I2S5_DATA"), + MTK_FUNCTION(2, "I2S5_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(4, "ANT_SEL3") + ), + MTK_PIN( + PINCTRL_PIN(33, "I2S1_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 15), + MTK_FUNCTION(0, "GPIO33"), + MTK_FUNCTION(1, "I2S1_DATA"), + MTK_FUNCTION(2, "I2S1_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(4, "IMG_TEST_CK"), + MTK_FUNCTION(5, "G1_RXD0"), + MTK_FUNCTION(6, "WCN_PCM_TX"), + MTK_FUNCTION(7, "DBG_MON_B[8]") + ), + MTK_PIN( + PINCTRL_PIN(34, "I2S1_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 16), + MTK_FUNCTION(0, "GPIO34"), + MTK_FUNCTION(1, "I2S1_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "VDEC_TEST_CK"), + MTK_FUNCTION(5, "G1_RXD1"), + MTK_FUNCTION(6, "WCN_PCM_RX"), + MTK_FUNCTION(7, "DBG_MON_B[7]") + ), + MTK_PIN( + PINCTRL_PIN(35, "I2S1_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 17), + MTK_FUNCTION(0, "GPIO35"), + MTK_FUNCTION(1, "I2S1_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(5, "G1_RXD2"), + MTK_FUNCTION(6, "WCN_PCM_CLKO"), + MTK_FUNCTION(7, "DBG_MON_B[9]") + ), + MTK_PIN( + PINCTRL_PIN(36, "I2S1_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 18), + MTK_FUNCTION(0, "GPIO36"), + MTK_FUNCTION(1, "I2S1_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(5, "G1_RXD3"), + MTK_FUNCTION(6, "WCN_PCM_SYNC"), + MTK_FUNCTION(7, "DBG_MON_B[10]") + ), + MTK_PIN( + PINCTRL_PIN(37, "I2S1_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 19), + MTK_FUNCTION(0, "GPIO37"), + MTK_FUNCTION(1, "I2S1_MCLK"), + MTK_FUNCTION(5, "G1_RXDV"), + MTK_FUNCTION(7, "DBG_MON_B[11]") + ), + MTK_PIN( + PINCTRL_PIN(38, "I2S2_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 20), + MTK_FUNCTION(0, "GPIO38"), + MTK_FUNCTION(2, "I2S2_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(4, "DMIC_DAT0") + ), + MTK_PIN( + PINCTRL_PIN(39, "JTMS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 21), + MTK_FUNCTION(0, "GPIO39"), + MTK_FUNCTION(1, "JTMS"), + MTK_FUNCTION(2, "CONN_MCU_TMS"), + MTK_FUNCTION(3, "CONN_MCU_AICE_JMSC"), + MTK_FUNCTION(4, "DFD_TMS_XI") + ), + MTK_PIN( + PINCTRL_PIN(40, "JTCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 22), + MTK_FUNCTION(0, "GPIO40"), + MTK_FUNCTION(1, "JTCK"), + MTK_FUNCTION(2, "CONN_MCU_TCK1"), + MTK_FUNCTION(3, "CONN_MCU_AICE_JCKC"), + MTK_FUNCTION(4, "DFD_TCK_XI") + ), + MTK_PIN( + PINCTRL_PIN(41, "JTDI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 23), + MTK_FUNCTION(0, "GPIO41"), + MTK_FUNCTION(1, "JTDI"), + MTK_FUNCTION(2, "CONN_MCU_TDI"), + MTK_FUNCTION(4, "DFD_TDI_XI") + ), + MTK_PIN( + PINCTRL_PIN(42, "JTDO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 24), + MTK_FUNCTION(0, "GPIO42"), + MTK_FUNCTION(1, "JTDO"), + MTK_FUNCTION(2, "CONN_MCU_TDO"), + MTK_FUNCTION(4, "DFD_TDO") + ), + MTK_PIN( + PINCTRL_PIN(43, "NCLE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 25), + MTK_FUNCTION(0, "GPIO43"), + MTK_FUNCTION(1, "NCLE"), + MTK_FUNCTION(2, "EXT_XCS2") + ), + MTK_PIN( + PINCTRL_PIN(44, "NCEB1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 26), + MTK_FUNCTION(0, "GPIO44"), + MTK_FUNCTION(1, "NCEB1"), + MTK_FUNCTION(2, "IDDIG") + ), + MTK_PIN( + PINCTRL_PIN(45, "NCEB0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 27), + MTK_FUNCTION(0, "GPIO45"), + MTK_FUNCTION(1, "NCEB0"), + MTK_FUNCTION(2, "DRV_VBUS") + ), + MTK_PIN( + PINCTRL_PIN(46, "IR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 28), + MTK_FUNCTION(0, "GPIO46"), + MTK_FUNCTION(1, "IR") + ), + MTK_PIN( + PINCTRL_PIN(47, "NREB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 29), + MTK_FUNCTION(0, "GPIO47"), + MTK_FUNCTION(1, "NREB"), + MTK_FUNCTION(2, "IDDIG_P1") + ), + MTK_PIN( + PINCTRL_PIN(48, "NRNB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 30), + MTK_FUNCTION(0, "GPIO48"), + MTK_FUNCTION(1, "NRNB"), + MTK_FUNCTION(2, "DRV_VBUS_P1") + ), + MTK_PIN( + PINCTRL_PIN(49, "I2S0_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 31), + MTK_FUNCTION(0, "GPIO49"), + MTK_FUNCTION(1, "I2S0_DATA"), + MTK_FUNCTION(2, "I2S0_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX"), + MTK_FUNCTION(6, "WCN_I2S_DO"), + MTK_FUNCTION(7, "DBG_MON_B[3]") + ), + MTK_PIN( + PINCTRL_PIN(50, "I2S2_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 32), + MTK_FUNCTION(0, "GPIO50"), + MTK_FUNCTION(1, "I2S2_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(4, "DMIC_SCK1") + ), + MTK_PIN( + PINCTRL_PIN(51, "I2S2_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 33), + MTK_FUNCTION(0, "GPIO51"), + MTK_FUNCTION(1, "I2S2_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "DMIC_SCK0") + ), + MTK_PIN( + PINCTRL_PIN(52, "I2S2_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 34), + MTK_FUNCTION(0, "GPIO52"), + MTK_FUNCTION(1, "I2S2_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(4, "DMIC_DAT1") + ), + MTK_PIN( + PINCTRL_PIN(53, "SPI0_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 35), + MTK_FUNCTION(0, "GPIO53"), + MTK_FUNCTION(1, "SPI0_CS"), + MTK_FUNCTION(3, "SPDIF"), + MTK_FUNCTION(4, "ADC_CK"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(7, "DBG_MON_A[7]") + ), + MTK_PIN( + PINCTRL_PIN(54, "SPI0_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 36), + MTK_FUNCTION(0, "GPIO54"), + MTK_FUNCTION(1, "SPI0_CK"), + MTK_FUNCTION(3, "SPDIF_IN1"), + MTK_FUNCTION(4, "ADC_DAT_IN"), + MTK_FUNCTION(7, "DBG_MON_A[10]") + ), + MTK_PIN( + PINCTRL_PIN(55, "SPI0_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 37), + MTK_FUNCTION(0, "GPIO55"), + MTK_FUNCTION(1, "SPI0_MI"), + MTK_FUNCTION(2, "SPI0_MO"), + MTK_FUNCTION(3, "MSDC1_WP"), + MTK_FUNCTION(4, "ADC_WS"), + MTK_FUNCTION(5, "PWM2"), + MTK_FUNCTION(7, "DBG_MON_A[8]") + ), + MTK_PIN( + PINCTRL_PIN(56, "SPI0_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 38), + MTK_FUNCTION(0, "GPIO56"), + MTK_FUNCTION(1, "SPI0_MO"), + MTK_FUNCTION(2, "SPI0_MI"), + MTK_FUNCTION(3, "SPDIF_IN0"), + MTK_FUNCTION(7, "DBG_MON_A[9]") + ), + MTK_PIN( + PINCTRL_PIN(57, "SDA1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 39), + MTK_FUNCTION(0, "GPIO57"), + MTK_FUNCTION(1, "SDA1") + ), + MTK_PIN( + PINCTRL_PIN(58, "SCL1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 40), + MTK_FUNCTION(0, "GPIO58"), + MTK_FUNCTION(1, "SCL1") + ), + MTK_PIN( + PINCTRL_PIN(59, "RAMBUF_I_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO59"), + MTK_FUNCTION(1, "RAMBUF_I_CLK") + ), + MTK_PIN( + PINCTRL_PIN(60, "WB_RSTB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 41), + MTK_FUNCTION(0, "GPIO60"), + MTK_FUNCTION(1, "WB_RSTB"), + MTK_FUNCTION(7, "DBG_MON_A[11]") + ), + MTK_PIN( + PINCTRL_PIN(61, "F2W_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 42), + MTK_FUNCTION(0, "GPIO61"), + MTK_FUNCTION(1, "F2W_DATA"), + MTK_FUNCTION(7, "DBG_MON_A[16]") + ), + MTK_PIN( + PINCTRL_PIN(62, "F2W_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 43), + MTK_FUNCTION(0, "GPIO62"), + MTK_FUNCTION(1, "F2W_CK"), + MTK_FUNCTION(7, "DBG_MON_A[15]") + ), + MTK_PIN( + PINCTRL_PIN(63, "WB_SCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 44), + MTK_FUNCTION(0, "GPIO63"), + MTK_FUNCTION(1, "WB_SCLK"), + MTK_FUNCTION(7, "DBG_MON_A[13]") + ), + MTK_PIN( + PINCTRL_PIN(64, "WB_SDATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 45), + MTK_FUNCTION(0, "GPIO64"), + MTK_FUNCTION(1, "WB_SDATA"), + MTK_FUNCTION(7, "DBG_MON_A[12]") + ), + MTK_PIN( + PINCTRL_PIN(65, "WB_SEN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 46), + MTK_FUNCTION(0, "GPIO65"), + MTK_FUNCTION(1, "WB_SEN"), + MTK_FUNCTION(7, "DBG_MON_A[14]") + ), + MTK_PIN( + PINCTRL_PIN(66, "WB_CRTL0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 47), + MTK_FUNCTION(0, "GPIO66"), + MTK_FUNCTION(1, "WB_CRTL0"), + MTK_FUNCTION(5, "DFD_NTRST_XI"), + MTK_FUNCTION(7, "DBG_MON_A[17]") + ), + MTK_PIN( + PINCTRL_PIN(67, "WB_CRTL1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 48), + MTK_FUNCTION(0, "GPIO67"), + MTK_FUNCTION(1, "WB_CRTL1"), + MTK_FUNCTION(5, "DFD_TMS_XI"), + MTK_FUNCTION(7, "DBG_MON_A[18]") + ), + MTK_PIN( + PINCTRL_PIN(68, "WB_CRTL2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 49), + MTK_FUNCTION(0, "GPIO68"), + MTK_FUNCTION(1, "WB_CRTL2"), + MTK_FUNCTION(5, "DFD_TCK_XI"), + MTK_FUNCTION(7, "DBG_MON_A[19]") + ), + MTK_PIN( + PINCTRL_PIN(69, "WB_CRTL3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 50), + MTK_FUNCTION(0, "GPIO69"), + MTK_FUNCTION(1, "WB_CRTL3"), + MTK_FUNCTION(5, "DFD_TDI_XI"), + MTK_FUNCTION(7, "DBG_MON_A[20]") + ), + MTK_PIN( + PINCTRL_PIN(70, "WB_CRTL4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 51), + MTK_FUNCTION(0, "GPIO70"), + MTK_FUNCTION(1, "WB_CRTL4"), + MTK_FUNCTION(5, "DFD_TDO"), + MTK_FUNCTION(7, "DBG_MON_A[21]") + ), + MTK_PIN( + PINCTRL_PIN(71, "WB_CRTL5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 52), + MTK_FUNCTION(0, "GPIO71"), + MTK_FUNCTION(1, "WB_CRTL5"), + MTK_FUNCTION(7, "DBG_MON_A[22]") + ), + MTK_PIN( + PINCTRL_PIN(72, "I2S0_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 53), + MTK_FUNCTION(0, "GPIO72"), + MTK_FUNCTION(1, "I2S0_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX"), + MTK_FUNCTION(4, "PWM0"), + MTK_FUNCTION(5, "DISP_PWM"), + MTK_FUNCTION(6, "WCN_I2S_DI"), + MTK_FUNCTION(7, "DBG_MON_B[2]") + ), + MTK_PIN( + PINCTRL_PIN(73, "I2S0_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 54), + MTK_FUNCTION(0, "GPIO73"), + MTK_FUNCTION(1, "I2S0_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC"), + MTK_FUNCTION(6, "WCN_I2S_LRCK"), + MTK_FUNCTION(7, "DBG_MON_B[5]") + ), + MTK_PIN( + PINCTRL_PIN(74, "I2S0_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 55), + MTK_FUNCTION(0, "GPIO74"), + MTK_FUNCTION(1, "I2S0_BCK"), + MTK_FUNCTION(3, "PCM_CLK0"), + MTK_FUNCTION(6, "WCN_I2S_BCK"), + MTK_FUNCTION(7, "DBG_MON_B[4]") + ), + MTK_PIN( + PINCTRL_PIN(75, "SDA0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 56), + MTK_FUNCTION(0, "GPIO75"), + MTK_FUNCTION(1, "SDA0") + ), + MTK_PIN( + PINCTRL_PIN(76, "SCL0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 57), + MTK_FUNCTION(0, "GPIO76"), + MTK_FUNCTION(1, "SCL0") + ), + MTK_PIN( + PINCTRL_PIN(77, "SDA2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 58), + MTK_FUNCTION(0, "GPIO77"), + MTK_FUNCTION(1, "SDA2") + ), + MTK_PIN( + PINCTRL_PIN(78, "SCL2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 59), + MTK_FUNCTION(0, "GPIO78"), + MTK_FUNCTION(1, "SCL2") + ), + MTK_PIN( + PINCTRL_PIN(79, "URXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 60), + MTK_FUNCTION(0, "GPIO79"), + MTK_FUNCTION(1, "URXD0"), + MTK_FUNCTION(2, "UTXD0") + ), + MTK_PIN( + PINCTRL_PIN(80, "UTXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 61), + MTK_FUNCTION(0, "GPIO80"), + MTK_FUNCTION(1, "UTXD0"), + MTK_FUNCTION(2, "URXD0") + ), + MTK_PIN( + PINCTRL_PIN(81, "URXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 62), + MTK_FUNCTION(0, "GPIO81"), + MTK_FUNCTION(1, "URXD1"), + MTK_FUNCTION(2, "UTXD1") + ), + MTK_PIN( + PINCTRL_PIN(82, "UTXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 63), + MTK_FUNCTION(0, "GPIO82"), + MTK_FUNCTION(1, "UTXD1"), + MTK_FUNCTION(2, "URXD1") + ), + MTK_PIN( + PINCTRL_PIN(83, "LCM_RST"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 64), + MTK_FUNCTION(0, "GPIO83"), + MTK_FUNCTION(1, "LCM_RST"), + MTK_FUNCTION(2, "VDAC_CK_XI"), + MTK_FUNCTION(7, "DBG_MON_B[1]") + ), + MTK_PIN( + PINCTRL_PIN(84, "DSI_TE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 65), + MTK_FUNCTION(0, "GPIO84"), + MTK_FUNCTION(1, "DSI_TE"), + MTK_FUNCTION(7, "DBG_MON_B[0]") + ), + MTK_PIN( + PINCTRL_PIN(85, "MSDC2_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 66), + MTK_FUNCTION(0, "GPIO85"), + MTK_FUNCTION(1, "MSDC2_CMD"), + MTK_FUNCTION(2, "ANT_SEL0"), + MTK_FUNCTION(3, "SDA1"), + MTK_FUNCTION(6, "I2SOUT_BCK") + ), + MTK_PIN( + PINCTRL_PIN(86, "MSDC2_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 67), + MTK_FUNCTION(0, "GPIO86"), + MTK_FUNCTION(1, "MSDC2_CLK"), + MTK_FUNCTION(2, "ANT_SEL1"), + MTK_FUNCTION(3, "SCL1"), + MTK_FUNCTION(6, "I2SOUT_LRCK") + ), + MTK_PIN( + PINCTRL_PIN(87, "MSDC2_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 68), + MTK_FUNCTION(0, "GPIO87"), + MTK_FUNCTION(1, "MSDC2_DAT0"), + MTK_FUNCTION(2, "ANT_SEL2"), + MTK_FUNCTION(5, "UTXD0"), + MTK_FUNCTION(6, "I2SOUT_DATA_OUT") + ), + MTK_PIN( + PINCTRL_PIN(88, "MSDC2_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 71), + MTK_FUNCTION(0, "GPIO88"), + MTK_FUNCTION(1, "MSDC2_DAT1"), + MTK_FUNCTION(2, "ANT_SEL3"), + MTK_FUNCTION(3, "PWM0"), + MTK_FUNCTION(5, "URXD0"), + MTK_FUNCTION(6, "PWM1") + ), + MTK_PIN( + PINCTRL_PIN(89, "MSDC2_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 72), + MTK_FUNCTION(0, "GPIO89"), + MTK_FUNCTION(1, "MSDC2_DAT2"), + MTK_FUNCTION(2, "ANT_SEL4"), + MTK_FUNCTION(3, "SDA2"), + MTK_FUNCTION(5, "UTXD1"), + MTK_FUNCTION(6, "PWM2") + ), + MTK_PIN( + PINCTRL_PIN(90, "MSDC2_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 73), + MTK_FUNCTION(0, "GPIO90"), + MTK_FUNCTION(1, "MSDC2_DAT3"), + MTK_FUNCTION(2, "ANT_SEL5"), + MTK_FUNCTION(3, "SCL2"), + MTK_FUNCTION(4, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "URXD1"), + MTK_FUNCTION(6, "PWM3") + ), + MTK_PIN( + PINCTRL_PIN(91, "TDN3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI91"), + MTK_FUNCTION(1, "TDN3") + ), + MTK_PIN( + PINCTRL_PIN(92, "TDP3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI92"), + MTK_FUNCTION(1, "TDP3") + ), + MTK_PIN( + PINCTRL_PIN(93, "TDN2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI93"), + MTK_FUNCTION(1, "TDN2") + ), + MTK_PIN( + PINCTRL_PIN(94, "TDP2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI94"), + MTK_FUNCTION(1, "TDP2") + ), + MTK_PIN( + PINCTRL_PIN(95, "TCN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI95"), + MTK_FUNCTION(1, "TCN") + ), + MTK_PIN( + PINCTRL_PIN(96, "TCP"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI96"), + MTK_FUNCTION(1, "TCP") + ), + MTK_PIN( + PINCTRL_PIN(97, "TDN1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI97"), + MTK_FUNCTION(1, "TDN1") + ), + MTK_PIN( + PINCTRL_PIN(98, "TDP1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI98"), + MTK_FUNCTION(1, "TDP1") + ), + MTK_PIN( + PINCTRL_PIN(99, "TDN0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI99"), + MTK_FUNCTION(1, "TDN0") + ), + MTK_PIN( + PINCTRL_PIN(100, "TDP0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPI100"), + MTK_FUNCTION(1, "TDP0") + ), + MTK_PIN( + PINCTRL_PIN(101, "SPI2_CSN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 74), + MTK_FUNCTION(0, "GPIO101"), + MTK_FUNCTION(1, "SPI2_CS"), + MTK_FUNCTION(3, "SCL3"), + MTK_FUNCTION(4, "KROW0") + ), + MTK_PIN( + PINCTRL_PIN(102, "SPI2_MI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 75), + MTK_FUNCTION(0, "GPIO102"), + MTK_FUNCTION(1, "SPI2_MI"), + MTK_FUNCTION(2, "SPI2_MO"), + MTK_FUNCTION(3, "SDA3"), + MTK_FUNCTION(4, "KROW1") + ), + MTK_PIN( + PINCTRL_PIN(103, "SPI2_MO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 76), + MTK_FUNCTION(0, "GPIO103"), + MTK_FUNCTION(1, "SPI2_MO"), + MTK_FUNCTION(2, "SPI2_MI"), + MTK_FUNCTION(3, "SCL3"), + MTK_FUNCTION(4, "KROW2") + ), + MTK_PIN( + PINCTRL_PIN(104, "SPI2_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 77), + MTK_FUNCTION(0, "GPIO104"), + MTK_FUNCTION(1, "SPI2_CK"), + MTK_FUNCTION(3, "SDA3"), + MTK_FUNCTION(4, "KROW3") + ), + MTK_PIN( + PINCTRL_PIN(105, "MSDC1_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 78), + MTK_FUNCTION(0, "GPIO105"), + MTK_FUNCTION(1, "MSDC1_CMD"), + MTK_FUNCTION(2, "ANT_SEL0"), + MTK_FUNCTION(3, "SDA1"), + MTK_FUNCTION(6, "I2SOUT_BCK"), + MTK_FUNCTION(7, "DBG_MON_B[27]") + ), + MTK_PIN( + PINCTRL_PIN(106, "MSDC1_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 79), + MTK_FUNCTION(0, "GPIO106"), + MTK_FUNCTION(1, "MSDC1_CLK"), + MTK_FUNCTION(2, "ANT_SEL1"), + MTK_FUNCTION(3, "SCL1"), + MTK_FUNCTION(6, "I2SOUT_LRCK"), + MTK_FUNCTION(7, "DBG_MON_B[28]") + ), + MTK_PIN( + PINCTRL_PIN(107, "MSDC1_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 80), + MTK_FUNCTION(0, "GPIO107"), + MTK_FUNCTION(1, "MSDC1_DAT0"), + MTK_FUNCTION(2, "ANT_SEL2"), + MTK_FUNCTION(5, "UTXD0"), + MTK_FUNCTION(6, "I2SOUT_DATA_OUT"), + MTK_FUNCTION(7, "DBG_MON_B[26]") + ), + MTK_PIN( + PINCTRL_PIN(108, "MSDC1_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 81), + MTK_FUNCTION(0, "GPIO108"), + MTK_FUNCTION(1, "MSDC1_DAT1"), + MTK_FUNCTION(2, "ANT_SEL3"), + MTK_FUNCTION(3, "PWM0"), + MTK_FUNCTION(5, "URXD0"), + MTK_FUNCTION(6, "PWM1"), + MTK_FUNCTION(7, "DBG_MON_B[25]") + ), + MTK_PIN( + PINCTRL_PIN(109, "MSDC1_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 82), + MTK_FUNCTION(0, "GPIO109"), + MTK_FUNCTION(1, "MSDC1_DAT2"), + MTK_FUNCTION(2, "ANT_SEL4"), + MTK_FUNCTION(3, "SDA2"), + MTK_FUNCTION(5, "UTXD1"), + MTK_FUNCTION(6, "PWM2"), + MTK_FUNCTION(7, "DBG_MON_B[24]") + ), + MTK_PIN( + PINCTRL_PIN(110, "MSDC1_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 83), + MTK_FUNCTION(0, "GPIO110"), + MTK_FUNCTION(1, "MSDC1_DAT3"), + MTK_FUNCTION(2, "ANT_SEL5"), + MTK_FUNCTION(3, "SCL2"), + MTK_FUNCTION(4, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "URXD1"), + MTK_FUNCTION(6, "PWM3"), + MTK_FUNCTION(7, "DBG_MON_B[23]") + ), + MTK_PIN( + PINCTRL_PIN(111, "MSDC0_DAT7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 84), + MTK_FUNCTION(0, "GPIO111"), + MTK_FUNCTION(1, "MSDC0_DAT7"), + MTK_FUNCTION(4, "NLD7") + ), + MTK_PIN( + PINCTRL_PIN(112, "MSDC0_DAT6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 85), + MTK_FUNCTION(0, "GPIO112"), + MTK_FUNCTION(1, "MSDC0_DAT6"), + MTK_FUNCTION(4, "NLD6") + ), + MTK_PIN( + PINCTRL_PIN(113, "MSDC0_DAT5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 86), + MTK_FUNCTION(0, "GPIO113"), + MTK_FUNCTION(1, "MSDC0_DAT5"), + MTK_FUNCTION(4, "NLD5") + ), + MTK_PIN( + PINCTRL_PIN(114, "MSDC0_DAT4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 87), + MTK_FUNCTION(0, "GPIO114"), + MTK_FUNCTION(1, "MSDC0_DAT4"), + MTK_FUNCTION(4, "NLD4") + ), + MTK_PIN( + PINCTRL_PIN(115, "MSDC0_RSTB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 88), + MTK_FUNCTION(0, "GPIO115"), + MTK_FUNCTION(1, "MSDC0_RSTB"), + MTK_FUNCTION(4, "NLD8") + ), + MTK_PIN( + PINCTRL_PIN(116, "MSDC0_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 89), + MTK_FUNCTION(0, "GPIO116"), + MTK_FUNCTION(1, "MSDC0_CMD"), + MTK_FUNCTION(4, "NALE") + ), + MTK_PIN( + PINCTRL_PIN(117, "MSDC0_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 90), + MTK_FUNCTION(0, "GPIO117"), + MTK_FUNCTION(1, "MSDC0_CLK"), + MTK_FUNCTION(4, "NWEB") + ), + MTK_PIN( + PINCTRL_PIN(118, "MSDC0_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 91), + MTK_FUNCTION(0, "GPIO118"), + MTK_FUNCTION(1, "MSDC0_DAT3"), + MTK_FUNCTION(4, "NLD3") + ), + MTK_PIN( + PINCTRL_PIN(119, "MSDC0_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 92), + MTK_FUNCTION(0, "GPIO119"), + MTK_FUNCTION(1, "MSDC0_DAT2"), + MTK_FUNCTION(4, "NLD2") + ), + MTK_PIN( + PINCTRL_PIN(120, "MSDC0_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 93), + MTK_FUNCTION(0, "GPIO120"), + MTK_FUNCTION(1, "MSDC0_DAT1"), + MTK_FUNCTION(4, "NLD1") + ), + MTK_PIN( + PINCTRL_PIN(121, "MSDC0_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 94), + MTK_FUNCTION(0, "GPIO121"), + MTK_FUNCTION(1, "MSDC0_DAT0"), + MTK_FUNCTION(4, "NLD0"), + MTK_FUNCTION(5, "WATCHDOG") + ), + MTK_PIN( + PINCTRL_PIN(122, "CEC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 95), + MTK_FUNCTION(0, "GPIO122"), + MTK_FUNCTION(1, "CEC"), + MTK_FUNCTION(4, "SDA2"), + MTK_FUNCTION(5, "URXD0") + ), + MTK_PIN( + PINCTRL_PIN(123, "HTPLG"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 96), + MTK_FUNCTION(0, "GPIO123"), + MTK_FUNCTION(1, "HTPLG"), + MTK_FUNCTION(4, "SCL2"), + MTK_FUNCTION(5, "UTXD0") + ), + MTK_PIN( + PINCTRL_PIN(124, "HDMISCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 97), + MTK_FUNCTION(0, "GPIO124"), + MTK_FUNCTION(1, "HDMISCK"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(5, "PWM3") + ), + MTK_PIN( + PINCTRL_PIN(125, "HDMISD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 98), + MTK_FUNCTION(0, "GPIO125"), + MTK_FUNCTION(1, "HDMISD"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(5, "PWM4") + ), + MTK_PIN( + PINCTRL_PIN(126, "I2S0_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 99), + MTK_FUNCTION(0, "GPIO126"), + MTK_FUNCTION(1, "I2S0_MCLK"), + MTK_FUNCTION(6, "WCN_I2S_MCLK"), + MTK_FUNCTION(7, "DBG_MON_B[6]") + ), + MTK_PIN( + PINCTRL_PIN(127, "RAMBUF_IDATA0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO127"), + MTK_FUNCTION(1, "RAMBUF_IDATA0") + ), + MTK_PIN( + PINCTRL_PIN(128, "RAMBUF_IDATA1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO128"), + MTK_FUNCTION(1, "RAMBUF_IDATA1") + ), + MTK_PIN( + PINCTRL_PIN(129, "RAMBUF_IDATA2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO129"), + MTK_FUNCTION(1, "RAMBUF_IDATA2") + ), + MTK_PIN( + PINCTRL_PIN(130, "RAMBUF_IDATA3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO130"), + MTK_FUNCTION(1, "RAMBUF_IDATA3") + ), + MTK_PIN( + PINCTRL_PIN(131, "RAMBUF_IDATA4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO131"), + MTK_FUNCTION(1, "RAMBUF_IDATA4") + ), + MTK_PIN( + PINCTRL_PIN(132, "RAMBUF_IDATA5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO132"), + MTK_FUNCTION(1, "RAMBUF_IDATA5") + ), + MTK_PIN( + PINCTRL_PIN(133, "RAMBUF_IDATA6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO133"), + MTK_FUNCTION(1, "RAMBUF_IDATA6") + ), + MTK_PIN( + PINCTRL_PIN(134, "RAMBUF_IDATA7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO134"), + MTK_FUNCTION(1, "RAMBUF_IDATA7") + ), + MTK_PIN( + PINCTRL_PIN(135, "RAMBUF_IDATA8"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO135"), + MTK_FUNCTION(1, "RAMBUF_IDATA8") + ), + MTK_PIN( + PINCTRL_PIN(136, "RAMBUF_IDATA9"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO136"), + MTK_FUNCTION(1, "RAMBUF_IDATA9") + ), + MTK_PIN( + PINCTRL_PIN(137, "RAMBUF_IDATA10"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO137"), + MTK_FUNCTION(1, "RAMBUF_IDATA10") + ), + MTK_PIN( + PINCTRL_PIN(138, "RAMBUF_IDATA11"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO138"), + MTK_FUNCTION(1, "RAMBUF_IDATA11") + ), + MTK_PIN( + PINCTRL_PIN(139, "RAMBUF_IDATA12"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO139"), + MTK_FUNCTION(1, "RAMBUF_IDATA12") + ), + MTK_PIN( + PINCTRL_PIN(140, "RAMBUF_IDATA13"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO140"), + MTK_FUNCTION(1, "RAMBUF_IDATA13") + ), + MTK_PIN( + PINCTRL_PIN(141, "RAMBUF_IDATA14"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO141"), + MTK_FUNCTION(1, "RAMBUF_IDATA14") + ), + MTK_PIN( + PINCTRL_PIN(142, "RAMBUF_IDATA15"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO142"), + MTK_FUNCTION(1, "RAMBUF_IDATA15") + ), + MTK_PIN( + PINCTRL_PIN(143, "RAMBUF_ODATA0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO143"), + MTK_FUNCTION(1, "RAMBUF_ODATA0") + ), + MTK_PIN( + PINCTRL_PIN(144, "RAMBUF_ODATA1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO144"), + MTK_FUNCTION(1, "RAMBUF_ODATA1") + ), + MTK_PIN( + PINCTRL_PIN(145, "RAMBUF_ODATA2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO145"), + MTK_FUNCTION(1, "RAMBUF_ODATA2") + ), + MTK_PIN( + PINCTRL_PIN(146, "RAMBUF_ODATA3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO146"), + MTK_FUNCTION(1, "RAMBUF_ODATA3") + ), + MTK_PIN( + PINCTRL_PIN(147, "RAMBUF_ODATA4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO147"), + MTK_FUNCTION(1, "RAMBUF_ODATA4") + ), + MTK_PIN( + PINCTRL_PIN(148, "RAMBUF_ODATA5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO148"), + MTK_FUNCTION(1, "RAMBUF_ODATA5") + ), + MTK_PIN( + PINCTRL_PIN(149, "RAMBUF_ODATA6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO149"), + MTK_FUNCTION(1, "RAMBUF_ODATA6") + ), + MTK_PIN( + PINCTRL_PIN(150, "RAMBUF_ODATA7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO150"), + MTK_FUNCTION(1, "RAMBUF_ODATA7") + ), + MTK_PIN( + PINCTRL_PIN(151, "RAMBUF_ODATA8"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO151"), + MTK_FUNCTION(1, "RAMBUF_ODATA8") + ), + MTK_PIN( + PINCTRL_PIN(152, "RAMBUF_ODATA9"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO152"), + MTK_FUNCTION(1, "RAMBUF_ODATA9") + ), + MTK_PIN( + PINCTRL_PIN(153, "RAMBUF_ODATA10"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO153"), + MTK_FUNCTION(1, "RAMBUF_ODATA10") + ), + MTK_PIN( + PINCTRL_PIN(154, "RAMBUF_ODATA11"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO154"), + MTK_FUNCTION(1, "RAMBUF_ODATA11") + ), + MTK_PIN( + PINCTRL_PIN(155, "RAMBUF_ODATA12"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO155"), + MTK_FUNCTION(1, "RAMBUF_ODATA12") + ), + MTK_PIN( + PINCTRL_PIN(156, "RAMBUF_ODATA13"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO156"), + MTK_FUNCTION(1, "RAMBUF_ODATA13") + ), + MTK_PIN( + PINCTRL_PIN(157, "RAMBUF_ODATA14"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO157"), + MTK_FUNCTION(1, "RAMBUF_ODATA14") + ), + MTK_PIN( + PINCTRL_PIN(158, "RAMBUF_ODATA15"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO158"), + MTK_FUNCTION(1, "RAMBUF_ODATA15") + ), + MTK_PIN( + PINCTRL_PIN(159, "RAMBUF_BE0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO159"), + MTK_FUNCTION(1, "RAMBUF_BE0") + ), + MTK_PIN( + PINCTRL_PIN(160, "RAMBUF_BE1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO160"), + MTK_FUNCTION(1, "RAMBUF_BE1") + ), + MTK_PIN( + PINCTRL_PIN(161, "AP2PT_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO161"), + MTK_FUNCTION(1, "AP2PT_INT") + ), + MTK_PIN( + PINCTRL_PIN(162, "AP2PT_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO162"), + MTK_FUNCTION(1, "AP2PT_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(163, "PT2AP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO163"), + MTK_FUNCTION(1, "PT2AP_INT") + ), + MTK_PIN( + PINCTRL_PIN(164, "PT2AP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO164"), + MTK_FUNCTION(1, "PT2AP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(165, "AP2UP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO165"), + MTK_FUNCTION(1, "AP2UP_INT") + ), + MTK_PIN( + PINCTRL_PIN(166, "AP2UP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO166"), + MTK_FUNCTION(1, "AP2UP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(167, "UP2AP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO167"), + MTK_FUNCTION(1, "UP2AP_INT") + ), + MTK_PIN( + PINCTRL_PIN(168, "UP2AP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO168"), + MTK_FUNCTION(1, "UP2AP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(169, "RAMBUF_ADDR0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO169"), + MTK_FUNCTION(1, "RAMBUF_ADDR0") + ), + MTK_PIN( + PINCTRL_PIN(170, "RAMBUF_ADDR1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO170"), + MTK_FUNCTION(1, "RAMBUF_ADDR1") + ), + MTK_PIN( + PINCTRL_PIN(171, "RAMBUF_ADDR2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO171"), + MTK_FUNCTION(1, "RAMBUF_ADDR2") + ), + MTK_PIN( + PINCTRL_PIN(172, "RAMBUF_ADDR3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO172"), + MTK_FUNCTION(1, "RAMBUF_ADDR3") + ), + MTK_PIN( + PINCTRL_PIN(173, "RAMBUF_ADDR4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO173"), + MTK_FUNCTION(1, "RAMBUF_ADDR4") + ), + MTK_PIN( + PINCTRL_PIN(174, "RAMBUF_ADDR5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO174"), + MTK_FUNCTION(1, "RAMBUF_ADDR5") + ), + MTK_PIN( + PINCTRL_PIN(175, "RAMBUF_ADDR6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO175"), + MTK_FUNCTION(1, "RAMBUF_ADDR6") + ), + MTK_PIN( + PINCTRL_PIN(176, "RAMBUF_ADDR7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO176"), + MTK_FUNCTION(1, "RAMBUF_ADDR7") + ), + MTK_PIN( + PINCTRL_PIN(177, "RAMBUF_ADDR8"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO177"), + MTK_FUNCTION(1, "RAMBUF_ADDR8") + ), + MTK_PIN( + PINCTRL_PIN(178, "RAMBUF_ADDR9"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO178"), + MTK_FUNCTION(1, "RAMBUF_ADDR9") + ), + MTK_PIN( + PINCTRL_PIN(179, "RAMBUF_ADDR10"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO179"), + MTK_FUNCTION(1, "RAMBUF_ADDR10") + ), + MTK_PIN( + PINCTRL_PIN(180, "RAMBUF_RW"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO180"), + MTK_FUNCTION(1, "RAMBUF_RW") + ), + MTK_PIN( + PINCTRL_PIN(181, "RAMBUF_LAST"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO181"), + MTK_FUNCTION(1, "RAMBUF_LAST") + ), + MTK_PIN( + PINCTRL_PIN(182, "RAMBUF_HP"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO182"), + MTK_FUNCTION(1, "RAMBUF_HP") + ), + MTK_PIN( + PINCTRL_PIN(183, "RAMBUF_REQ"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO183"), + MTK_FUNCTION(1, "RAMBUF_REQ") + ), + MTK_PIN( + PINCTRL_PIN(184, "RAMBUF_ALE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO184"), + MTK_FUNCTION(1, "RAMBUF_ALE") + ), + MTK_PIN( + PINCTRL_PIN(185, "RAMBUF_DLE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO185"), + MTK_FUNCTION(1, "RAMBUF_DLE") + ), + MTK_PIN( + PINCTRL_PIN(186, "RAMBUF_WDLE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO186"), + MTK_FUNCTION(1, "RAMBUF_WDLE") + ), + MTK_PIN( + PINCTRL_PIN(187, "RAMBUF_O_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO187"), + MTK_FUNCTION(1, "RAMBUF_O_CLK") + ), + MTK_PIN( + PINCTRL_PIN(188, "I2S2_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 100), + MTK_FUNCTION(0, "GPIO188"), + MTK_FUNCTION(1, "I2S2_MCLK") + ), + MTK_PIN( + PINCTRL_PIN(189, "I2S3_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 101), + MTK_FUNCTION(0, "GPIO189"), + MTK_FUNCTION(2, "I2S3_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX") + ), + MTK_PIN( + PINCTRL_PIN(190, "I2S3_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 102), + MTK_FUNCTION(0, "GPIO190"), + MTK_FUNCTION(1, "I2S3_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX") + ), + MTK_PIN( + PINCTRL_PIN(191, "I2S3_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 103), + MTK_FUNCTION(0, "GPIO191"), + MTK_FUNCTION(1, "I2S3_BCK"), + MTK_FUNCTION(3, "PCM_CLK0") + ), + MTK_PIN( + PINCTRL_PIN(192, "I2S3_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 104), + MTK_FUNCTION(0, "GPIO192"), + MTK_FUNCTION(1, "I2S3_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC") + ), + MTK_PIN( + PINCTRL_PIN(193, "I2S3_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 105), + MTK_FUNCTION(0, "GPIO193"), + MTK_FUNCTION(1, "I2S3_MCLK") + ), + MTK_PIN( + PINCTRL_PIN(194, "I2S4_DATA"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 106), + MTK_FUNCTION(0, "GPIO194"), + MTK_FUNCTION(1, "I2S4_DATA"), + MTK_FUNCTION(2, "I2S4_DATA_BYPS"), + MTK_FUNCTION(3, "PCM_TX") + ), + MTK_PIN( + PINCTRL_PIN(195, "I2S4_DATA_IN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 107), + MTK_FUNCTION(0, "GPIO195"), + MTK_FUNCTION(1, "I2S4_DATA_IN"), + MTK_FUNCTION(3, "PCM_RX") + ), + MTK_PIN( + PINCTRL_PIN(196, "I2S4_BCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 108), + MTK_FUNCTION(0, "GPIO196"), + MTK_FUNCTION(1, "I2S4_BCK"), + MTK_FUNCTION(3, "PCM_CLK0") + ), + MTK_PIN( + PINCTRL_PIN(197, "I2S4_LRCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 109), + MTK_FUNCTION(0, "GPIO197"), + MTK_FUNCTION(1, "I2S4_LRCK"), + MTK_FUNCTION(3, "PCM_SYNC") + ), + MTK_PIN( + PINCTRL_PIN(198, "I2S4_MCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 110), + MTK_FUNCTION(0, "GPIO198"), + MTK_FUNCTION(1, "I2S4_MCLK") + ), + MTK_PIN( + PINCTRL_PIN(199, "SPI1_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 111), + MTK_FUNCTION(0, "GPIO199"), + MTK_FUNCTION(1, "SPI1_CK"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(4, "KCOL3"), + MTK_FUNCTION(7, "DBG_MON_B[15]") + ), + MTK_PIN( + PINCTRL_PIN(200, "SPDIF_OUT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 112), + MTK_FUNCTION(0, "GPIO200"), + MTK_FUNCTION(1, "SPDIF_OUT"), + MTK_FUNCTION(5, "G1_TXD3"), + MTK_FUNCTION(6, "URXD2"), + MTK_FUNCTION(7, "DBG_MON_B[16]") + ), + MTK_PIN( + PINCTRL_PIN(201, "SPDIF_IN0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 113), + MTK_FUNCTION(0, "GPIO201"), + MTK_FUNCTION(1, "SPDIF_IN0"), + MTK_FUNCTION(5, "G1_TXEN"), + MTK_FUNCTION(6, "UTXD2"), + MTK_FUNCTION(7, "DBG_MON_B[17]") + ), + MTK_PIN( + PINCTRL_PIN(202, "SPDIF_IN1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 114), + MTK_FUNCTION(0, "GPIO202"), + MTK_FUNCTION(1, "SPDIF_IN1") + ), + MTK_PIN( + PINCTRL_PIN(203, "PWM0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 115), + MTK_FUNCTION(0, "GPIO203"), + MTK_FUNCTION(1, "PWM0"), + MTK_FUNCTION(2, "DISP_PWM"), + MTK_FUNCTION(5, "G1_TXD2"), + MTK_FUNCTION(7, "DBG_MON_B[18]"), + MTK_FUNCTION(9, "I2S2_DATA") + ), + MTK_PIN( + PINCTRL_PIN(204, "PWM1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 116), + MTK_FUNCTION(0, "GPIO204"), + MTK_FUNCTION(1, "PWM1"), + MTK_FUNCTION(2, "CLKM3"), + MTK_FUNCTION(5, "G1_TXD1"), + MTK_FUNCTION(7, "DBG_MON_B[19]"), + MTK_FUNCTION(9, "I2S3_DATA") + ), + MTK_PIN( + PINCTRL_PIN(205, "PWM2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 117), + MTK_FUNCTION(0, "GPIO205"), + MTK_FUNCTION(1, "PWM2"), + MTK_FUNCTION(2, "CLKM2"), + MTK_FUNCTION(5, "G1_TXD0"), + MTK_FUNCTION(7, "DBG_MON_B[20]") + ), + MTK_PIN( + PINCTRL_PIN(206, "PWM3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 118), + MTK_FUNCTION(0, "GPIO206"), + MTK_FUNCTION(1, "PWM3"), + MTK_FUNCTION(2, "CLKM1"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "G1_TXC"), + MTK_FUNCTION(7, "DBG_MON_B[21]") + ), + MTK_PIN( + PINCTRL_PIN(207, "PWM4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 119), + MTK_FUNCTION(0, "GPIO207"), + MTK_FUNCTION(1, "PWM4"), + MTK_FUNCTION(2, "CLKM0"), + MTK_FUNCTION(3, "EXT_FRAME_SYNC"), + MTK_FUNCTION(5, "G1_RXC"), + MTK_FUNCTION(7, "DBG_MON_B[22]") + ), + MTK_PIN( + PINCTRL_PIN(208, "AUD_EXT_CK1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 120), + MTK_FUNCTION(0, "GPIO208"), + MTK_FUNCTION(1, "AUD_EXT_CK1"), + MTK_FUNCTION(2, "PWM0"), + MTK_FUNCTION(4, "ANT_SEL5"), + MTK_FUNCTION(5, "DISP_PWM"), + MTK_FUNCTION(7, "DBG_MON_A[31]"), + MTK_FUNCTION(11, "PCIE0_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(209, "AUD_EXT_CK2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 121), + MTK_FUNCTION(0, "GPIO209"), + MTK_FUNCTION(1, "AUD_EXT_CK2"), + MTK_FUNCTION(2, "MSDC1_WP"), + MTK_FUNCTION(5, "PWM1"), + MTK_FUNCTION(7, "DBG_MON_A[32]"), + MTK_FUNCTION(11, "PCIE1_PERST_N") + ), + MTK_PIN( + PINCTRL_PIN(210, "AUD_CLOCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO210"), + MTK_FUNCTION(1, "AUD_CLOCK") + ), + MTK_PIN( + PINCTRL_PIN(211, "DVP_RESET"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO211"), + MTK_FUNCTION(1, "DVP_RESET") + ), + MTK_PIN( + PINCTRL_PIN(212, "DVP_CLOCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO212"), + MTK_FUNCTION(1, "DVP_CLOCK") + ), + MTK_PIN( + PINCTRL_PIN(213, "DVP_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO213"), + MTK_FUNCTION(1, "DVP_CS") + ), + MTK_PIN( + PINCTRL_PIN(214, "DVP_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO214"), + MTK_FUNCTION(1, "DVP_CK") + ), + MTK_PIN( + PINCTRL_PIN(215, "DVP_DI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO215"), + MTK_FUNCTION(1, "DVP_DI") + ), + MTK_PIN( + PINCTRL_PIN(216, "DVP_DO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO216"), + MTK_FUNCTION(1, "DVP_DO") + ), + MTK_PIN( + PINCTRL_PIN(217, "AP_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO217"), + MTK_FUNCTION(1, "AP_CS") + ), + MTK_PIN( + PINCTRL_PIN(218, "AP_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO218"), + MTK_FUNCTION(1, "AP_CK") + ), + MTK_PIN( + PINCTRL_PIN(219, "AP_DI"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO219"), + MTK_FUNCTION(1, "AP_DI") + ), + MTK_PIN( + PINCTRL_PIN(220, "AP_DO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO220"), + MTK_FUNCTION(1, "AP_DO") + ), + MTK_PIN( + PINCTRL_PIN(221, "DVD_BCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO221"), + MTK_FUNCTION(1, "DVD_BCLK") + ), + MTK_PIN( + PINCTRL_PIN(222, "T8032_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO222"), + MTK_FUNCTION(1, "T8032_CLK") + ), + MTK_PIN( + PINCTRL_PIN(223, "AP_BCLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO223"), + MTK_FUNCTION(1, "AP_BCLK") + ), + MTK_PIN( + PINCTRL_PIN(224, "HOST_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO224"), + MTK_FUNCTION(1, "HOST_CS") + ), + MTK_PIN( + PINCTRL_PIN(225, "HOST_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO225"), + MTK_FUNCTION(1, "HOST_CK") + ), + MTK_PIN( + PINCTRL_PIN(226, "HOST_DO0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO226"), + MTK_FUNCTION(1, "HOST_DO0") + ), + MTK_PIN( + PINCTRL_PIN(227, "HOST_DO1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO227"), + MTK_FUNCTION(1, "HOST_DO1") + ), + MTK_PIN( + PINCTRL_PIN(228, "SLV_CS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO228"), + MTK_FUNCTION(1, "SLV_CS") + ), + MTK_PIN( + PINCTRL_PIN(229, "SLV_CK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO229"), + MTK_FUNCTION(1, "SLV_CK") + ), + MTK_PIN( + PINCTRL_PIN(230, "SLV_DI0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO230"), + MTK_FUNCTION(1, "SLV_DI0") + ), + MTK_PIN( + PINCTRL_PIN(231, "SLV_DI1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO231"), + MTK_FUNCTION(1, "SLV_DI1") + ), + MTK_PIN( + PINCTRL_PIN(232, "AP2DSP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO232"), + MTK_FUNCTION(1, "AP2DSP_INT") + ), + MTK_PIN( + PINCTRL_PIN(233, "AP2DSP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO233"), + MTK_FUNCTION(1, "AP2DSP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(234, "DSP2AP_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO234"), + MTK_FUNCTION(1, "DSP2AP_INT") + ), + MTK_PIN( + PINCTRL_PIN(235, "DSP2AP_INT_CLR"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO235"), + MTK_FUNCTION(1, "DSP2AP_INT_CLR") + ), + MTK_PIN( + PINCTRL_PIN(236, "EXT_SDIO3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 122), + MTK_FUNCTION(0, "GPIO236"), + MTK_FUNCTION(1, "EXT_SDIO3"), + MTK_FUNCTION(2, "IDDIG"), + MTK_FUNCTION(7, "DBG_MON_A[1]") + ), + MTK_PIN( + PINCTRL_PIN(237, "EXT_SDIO2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 123), + MTK_FUNCTION(0, "GPIO237"), + MTK_FUNCTION(1, "EXT_SDIO2"), + MTK_FUNCTION(2, "DRV_VBUS") + ), + MTK_PIN( + PINCTRL_PIN(238, "EXT_SDIO1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 124), + MTK_FUNCTION(0, "GPIO238"), + MTK_FUNCTION(1, "EXT_SDIO1"), + MTK_FUNCTION(2, "IDDIG_P1") + ), + MTK_PIN( + PINCTRL_PIN(239, "EXT_SDIO0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 125), + MTK_FUNCTION(0, "GPIO239"), + MTK_FUNCTION(1, "EXT_SDIO0"), + MTK_FUNCTION(2, "DRV_VBUS_P1") + ), + MTK_PIN( + PINCTRL_PIN(240, "EXT_XCS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 126), + MTK_FUNCTION(0, "GPIO240"), + MTK_FUNCTION(1, "EXT_XCS") + ), + MTK_PIN( + PINCTRL_PIN(241, "EXT_SCK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 127), + MTK_FUNCTION(0, "GPIO241"), + MTK_FUNCTION(1, "EXT_SCK") + ), + MTK_PIN( + PINCTRL_PIN(242, "URTS2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 128), + MTK_FUNCTION(0, "GPIO242"), + MTK_FUNCTION(1, "URTS2"), + MTK_FUNCTION(2, "UTXD3"), + MTK_FUNCTION(3, "URXD3"), + MTK_FUNCTION(4, "SCL1"), + MTK_FUNCTION(7, "DBG_MON_B[32]") + ), + MTK_PIN( + PINCTRL_PIN(243, "UCTS2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 129), + MTK_FUNCTION(0, "GPIO243"), + MTK_FUNCTION(1, "UCTS2"), + MTK_FUNCTION(2, "URXD3"), + MTK_FUNCTION(3, "UTXD3"), + MTK_FUNCTION(4, "SDA1"), + MTK_FUNCTION(7, "DBG_MON_A[6]") + ), + MTK_PIN( + PINCTRL_PIN(244, "HDMI_SDA_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 130), + MTK_FUNCTION(0, "GPIO244"), + MTK_FUNCTION(1, "HDMI_SDA_RX") + ), + MTK_PIN( + PINCTRL_PIN(245, "HDMI_SCL_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 131), + MTK_FUNCTION(0, "GPIO245"), + MTK_FUNCTION(1, "HDMI_SCL_RX") + ), + MTK_PIN( + PINCTRL_PIN(246, "MHL_SENCE"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 132), + MTK_FUNCTION(0, "GPIO246") + ), + MTK_PIN( + PINCTRL_PIN(247, "HDMI_HPD_CBUS_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 69), + MTK_FUNCTION(0, "GPIO247"), + MTK_FUNCTION(1, "HDMI_HPD_RX") + ), + MTK_PIN( + PINCTRL_PIN(248, "HDMI_TESTOUTP_RX"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 133), + MTK_FUNCTION(0, "GPIO248"), + MTK_FUNCTION(1, "HDMI_TESTOUTP_RX") + ), + MTK_PIN( + PINCTRL_PIN(249, "MSDC0E_RSTB"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 134), + MTK_FUNCTION(0, "GPIO249"), + MTK_FUNCTION(1, "MSDC0E_RSTB") + ), + MTK_PIN( + PINCTRL_PIN(250, "MSDC0E_DAT7"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 135), + MTK_FUNCTION(0, "GPIO250"), + MTK_FUNCTION(1, "MSDC3_DAT7"), + MTK_FUNCTION(6, "PCIE0_CLKREQ_N") + ), + MTK_PIN( + PINCTRL_PIN(251, "MSDC0E_DAT6"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 136), + MTK_FUNCTION(0, "GPIO251"), + MTK_FUNCTION(1, "MSDC3_DAT6"), + MTK_FUNCTION(6, "PCIE0_WAKE_N") + ), + MTK_PIN( + PINCTRL_PIN(252, "MSDC0E_DAT5"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 137), + MTK_FUNCTION(0, "GPIO252"), + MTK_FUNCTION(1, "MSDC3_DAT5"), + MTK_FUNCTION(6, "PCIE1_CLKREQ_N") + ), + MTK_PIN( + PINCTRL_PIN(253, "MSDC0E_DAT4"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 138), + MTK_FUNCTION(0, "GPIO253"), + MTK_FUNCTION(1, "MSDC3_DAT4"), + MTK_FUNCTION(6, "PCIE1_WAKE_N") + ), + MTK_PIN( + PINCTRL_PIN(254, "MSDC0E_DAT3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 139), + MTK_FUNCTION(0, "GPIO254"), + MTK_FUNCTION(1, "MSDC3_DAT3"), + MTK_FUNCTION(6, "PCIE2_CLKREQ_N") + ), + MTK_PIN( + PINCTRL_PIN(255, "MSDC0E_DAT2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 140), + MTK_FUNCTION(0, "GPIO255"), + MTK_FUNCTION(1, "MSDC3_DAT2"), + MTK_FUNCTION(6, "PCIE2_WAKE_N") + ), + MTK_PIN( + PINCTRL_PIN(256, "MSDC0E_DAT1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 141), + MTK_FUNCTION(0, "GPIO256"), + MTK_FUNCTION(1, "MSDC3_DAT1") + ), + MTK_PIN( + PINCTRL_PIN(257, "MSDC0E_DAT0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 142), + MTK_FUNCTION(0, "GPIO257"), + MTK_FUNCTION(1, "MSDC3_DAT0") + ), + MTK_PIN( + PINCTRL_PIN(258, "MSDC0E_CMD"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 143), + MTK_FUNCTION(0, "GPIO258"), + MTK_FUNCTION(1, "MSDC3_CMD") + ), + MTK_PIN( + PINCTRL_PIN(259, "MSDC0E_CLK"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 144), + MTK_FUNCTION(0, "GPIO259"), + MTK_FUNCTION(1, "MSDC3_CLK") + ), + MTK_PIN( + PINCTRL_PIN(260, "MSDC0E_DSL"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 145), + MTK_FUNCTION(0, "GPIO260"), + MTK_FUNCTION(1, "MSDC3_DSL") + ), + MTK_PIN( + PINCTRL_PIN(261, "MSDC1_INS"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 146), + MTK_FUNCTION(0, "GPIO261"), + MTK_FUNCTION(1, "MSDC1_INS"), + MTK_FUNCTION(7, "DBG_MON_B[29]") + ), + MTK_PIN( + PINCTRL_PIN(262, "G2_TXEN"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 8), + MTK_FUNCTION(0, "GPIO262"), + MTK_FUNCTION(1, "G2_TXEN") + ), + MTK_PIN( + PINCTRL_PIN(263, "G2_TXD3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 9), + MTK_FUNCTION(0, "GPIO263"), + MTK_FUNCTION(1, "G2_TXD3"), + MTK_FUNCTION(6, "ANT_SEL5") + ), + MTK_PIN( + PINCTRL_PIN(264, "G2_TXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 10), + MTK_FUNCTION(0, "GPIO264"), + MTK_FUNCTION(1, "G2_TXD2"), + MTK_FUNCTION(6, "ANT_SEL4") + ), + MTK_PIN( + PINCTRL_PIN(265, "G2_TXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 11), + MTK_FUNCTION(0, "GPIO265"), + MTK_FUNCTION(1, "G2_TXD1"), + MTK_FUNCTION(6, "ANT_SEL3") + ), + MTK_PIN( + PINCTRL_PIN(266, "G2_TXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO266"), + MTK_FUNCTION(1, "G2_TXD0"), + MTK_FUNCTION(6, "ANT_SEL2") + ), + MTK_PIN( + PINCTRL_PIN(267, "G2_TXC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO267"), + MTK_FUNCTION(1, "G2_TXC") + ), + MTK_PIN( + PINCTRL_PIN(268, "G2_RXC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO268"), + MTK_FUNCTION(1, "G2_RXC") + ), + MTK_PIN( + PINCTRL_PIN(269, "G2_RXD0"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO269"), + MTK_FUNCTION(1, "G2_RXD0") + ), + MTK_PIN( + PINCTRL_PIN(270, "G2_RXD1"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO270"), + MTK_FUNCTION(1, "G2_RXD1") + ), + MTK_PIN( + PINCTRL_PIN(271, "G2_RXD2"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO271"), + MTK_FUNCTION(1, "G2_RXD2") + ), + MTK_PIN( + PINCTRL_PIN(272, "G2_RXD3"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO272"), + MTK_FUNCTION(1, "G2_RXD3") + ), + MTK_PIN( + PINCTRL_PIN(273, "ESW_INT"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 168), + MTK_FUNCTION(0, "GPIO273"), + MTK_FUNCTION(1, "ESW_INT") + ), + MTK_PIN( + PINCTRL_PIN(274, "G2_RXDV"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO274"), + MTK_FUNCTION(1, "G2_RXDV") + ), + MTK_PIN( + PINCTRL_PIN(275, "MDC"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO275"), + MTK_FUNCTION(1, "MDC"), + MTK_FUNCTION(6, "ANT_SEL0") + ), + MTK_PIN( + PINCTRL_PIN(276, "MDIO"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO276"), + MTK_FUNCTION(1, "MDIO"), + MTK_FUNCTION(6, "ANT_SEL1") + ), + MTK_PIN( + PINCTRL_PIN(277, "ESW_RST"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO277"), + MTK_FUNCTION(1, "ESW_RST") + ), + MTK_PIN( + PINCTRL_PIN(278, "JTAG_RESET"), + NULL, "mt2701", + MTK_EINT_FUNCTION(0, 147), + MTK_FUNCTION(0, "GPIO278"), + MTK_FUNCTION(1, "JTAG_RESET") + ), + MTK_PIN( + PINCTRL_PIN(279, "USB3_RES_BOND"), + NULL, "mt2701", + MTK_EINT_FUNCTION(NO_EINT_SUPPORT, NO_EINT_SUPPORT), + MTK_FUNCTION(0, "GPIO279"), + MTK_FUNCTION(1, "USB3_RES_BOND") + ), +}; + +#endif /* __PINCTRL_MTK_MT2701_H */ -- cgit From 64051150c6402be83d77ea343f98755e998cae80 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 00:31:08 +0900 Subject: pinctrl: pxa: guard sub-directory with CONFIG_PINCTRL_PXA CONFIG_PINCTRL_PXA is more suitable than CONFIG_ARCH_PXA to guard the drivers/pinctrl/pxa/ directory. Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/pinctrl/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index d4134038cbf9..ab66e3575193 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -46,7 +46,7 @@ obj-y += freescale/ obj-$(CONFIG_X86) += intel/ obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/ obj-y += nomadik/ -obj-$(CONFIG_ARCH_PXA) += pxa/ +obj-$(CONFIG_PINCTRL_PXA) += pxa/ obj-$(CONFIG_ARCH_QCOM) += qcom/ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ -- cgit From 411a1fb80fb6d7cf50b8ff3811d25dbf262d6328 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 27 Jan 2016 22:38:30 +0100 Subject: pinctrl: nomadik: stn8815 CLCD alternate functions The STn8815 has 22 dedicated pins for CLCD with up to 16 bits in parallel, but pins 32 thru 39 can be used for an additional CLCD signal lines 16 thru 23. Signed-off-by: Linus Walleij --- drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c index 587b222f12f3..e852048c4c04 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c @@ -287,6 +287,10 @@ static const unsigned i2c0_a_1_pins[] = { STN8815_PIN_D3, STN8815_PIN_D2 }; /* Altfunction B */ static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 }; static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 }; +static const unsigned clcd_16_23_b_1_pins[] = { STN8815_PIN_AB6, + STN8815_PIN_AA6, STN8815_PIN_Y6, STN8815_PIN_Y5, STN8815_PIN_AA5, + STN8815_PIN_AB5, STN8815_PIN_AB4, STN8815_PIN_Y4 }; + #define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \ .npins = ARRAY_SIZE(a##_pins), .altsetting = b } @@ -302,6 +306,7 @@ static const struct nmk_pingroup nmk_stn8815_groups[] = { STN8815_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(u1_b_1, NMK_GPIO_ALT_B), STN8815_PIN_GROUP(i2cusb_b_1, NMK_GPIO_ALT_B), + STN8815_PIN_GROUP(clcd_16_23_b_1, NMK_GPIO_ALT_B), }; /* We use this macro to define the groups applicable to a function */ @@ -314,6 +319,7 @@ STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1"); STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1"); STN8815_FUNC_GROUPS(i2c0, "i2c0_a_1"); STN8815_FUNC_GROUPS(i2cusb, "i2cusb_b_1"); +STN8815_FUNC_GROUPS(clcd, "clcd_16_23_b_1"); #define FUNCTION(fname) \ { \ @@ -329,6 +335,7 @@ static const struct nmk_function nmk_stn8815_functions[] = { FUNCTION(i2c1), FUNCTION(i2c0), FUNCTION(i2cusb), + FUNCTION(clcd), }; static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = { -- cgit From 3a42a042f5cbefa925484a9bc4abd1bfeec5d779 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 00:32:09 +0900 Subject: pinctrl: sunxi: guard sub-directory with CONFIG_PINCTRL_SUNXI CONFIG_PINCTRL_SUNXI is more suitable than CONFIG_ARCH_SUNXI to guard the drivers/pinctrl/sunxi/ directory. (I renamed CONFIG_PINCTRL_SUNXI_COMMON to CONFIG_PINCTRL_SUNXI.) Signed-off-by: Masahiro Yamada Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/sunxi/Kconfig | 30 +++++++++++++++--------------- drivers/pinctrl/sunxi/Makefile | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index ab66e3575193..d25dcbd28dfa 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -52,7 +52,7 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/ obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/ obj-$(CONFIG_PINCTRL_SPEAR) += spear/ obj-$(CONFIG_ARCH_STM32) += stm32/ -obj-$(CONFIG_ARCH_SUNXI) += sunxi/ +obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig index f8dbc8bec0e1..ac8388e67340 100644 --- a/drivers/pinctrl/sunxi/Kconfig +++ b/drivers/pinctrl/sunxi/Kconfig @@ -1,67 +1,67 @@ if ARCH_SUNXI -config PINCTRL_SUNXI_COMMON +config PINCTRL_SUNXI bool select PINMUX select GENERIC_PINCONF config PINCTRL_SUN4I_A10 def_bool MACH_SUN4I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN5I_A10S def_bool MACH_SUN5I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN5I_A13 def_bool MACH_SUN5I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN6I_A31 def_bool MACH_SUN6I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN6I_A31S def_bool MACH_SUN6I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN6I_A31_R def_bool MACH_SUN6I depends on RESET_CONTROLLER - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN7I_A20 def_bool MACH_SUN7I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A23 def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A33 def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A83T def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_A23_R def_bool MACH_SUN8I depends on RESET_CONTROLLER - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN8I_H3 def_bool MACH_SUN8I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN9I_A80 def_bool MACH_SUN9I - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI config PINCTRL_SUN9I_A80_R def_bool MACH_SUN9I depends on RESET_CONTROLLER - select PINCTRL_SUNXI_COMMON + select PINCTRL_SUNXI endif diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile index ef82f22bb9ef..dac1bd0cda4a 100644 --- a/drivers/pinctrl/sunxi/Makefile +++ b/drivers/pinctrl/sunxi/Makefile @@ -1,5 +1,5 @@ # Core -obj-$(CONFIG_PINCTRL_SUNXI_COMMON) += pinctrl-sunxi.o +obj-y += pinctrl-sunxi.o # SoC Drivers obj-$(CONFIG_PINCTRL_SUN4I_A10) += pinctrl-sun4i-a10.o -- cgit From ff21a635dd1a9c6ca378847160897649cdbbfae4 Mon Sep 17 00:00:00 2001 From: Edwin Velds Date: Mon, 11 Jan 2016 00:25:15 +0100 Subject: HID: logitech-hidpp: Force feedback support for the Logitech G920 This patch implements force feedback support for the Logitech G920 Driving Force Racing Wheel. It is a generic implementation of feature 0x8123 of the Logitech HID++ protocol and should be usable for any future devices that implement this feature. This patch should be applied after the basic G920 support patch by Simon Wood: http://www.spinics.net/lists/linux-input/msg42174.html The driving supports everything that is supported by the G920 firmware: FF_CONSTANT FF_PERIODIC FF_SINE FF_SQUARE FF_SAW_UP FF_SAW_DOWN FF_TRIANGLE FF_SPRING FF_DAMPER FF_AUTOCENTER FF_GAIN and for version 2 firmware also: FF_FRICTION FF_INERTIA FF_RAMP Both envelopes and replay values are supported as well, but some problems may occur when using firmware release 1. There is also a small residual clockwise damper in the wheel when using the first firmware release. All problems are fixed in the soon te be released firmware version 2. The default spring is disabled by permanently placing a spring force in the wheel. This spring is also used as the autocenter spring. Note: The wheel _DOES_NOT_ auto switch to Logitech/HID mode (it is stuck in XBox since the xpad changes where not included). Michal has an alternative approach documented here (and the changes should be submitted upstream to usb_modeswitch project): === Create a file named "046d:c261" in "/etc/usb_modeswitch.d" with the following content: DefaultVendor=046d DefaultProduct=c261 MessageEndpoint=01 ResponseEndpoint=01 TargetClass=0x03 MessageContent="0f00010142" Then run "usb_modeswitch -c /etc/modeswitch.d/046d:c291" as root and watch the magic happen:) === [jkosina@suse.cz: added information about mode switching from Simon] [jkosina@suse.cz: fixed a few stylistic issues pointed out by Simon] [jkosina@suse.cz: fix merge conflict due to to_hid_device() changes] Signed-off-by: Edwin Velds Tested-by: Elias Vanderstuyft Tested-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 701 +++++++++++++++++++++++++++++++++------ 1 file changed, 593 insertions(+), 108 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index bd2ab476c65e..2869bbff0899 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -15,13 +15,19 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include +#include #include #include #include #include #include #include +#include +#include +#include #include +#include "usbhid/usbhid.h" #include "hid-ids.h" MODULE_LICENSE("GPL"); @@ -773,6 +779,589 @@ static void hidpp_touchpad_raw_xy_event(struct hidpp_device *hidpp_dev, } } +/* -------------------------------------------------------------------------- */ +/* 0x8123: Force feedback support */ +/* -------------------------------------------------------------------------- */ + +#define HIDPP_FF_GET_INFO 0x01 +#define HIDPP_FF_RESET_ALL 0x11 +#define HIDPP_FF_DOWNLOAD_EFFECT 0x21 +#define HIDPP_FF_SET_EFFECT_STATE 0x31 +#define HIDPP_FF_DESTROY_EFFECT 0x41 +#define HIDPP_FF_GET_APERTURE 0x51 +#define HIDPP_FF_SET_APERTURE 0x61 +#define HIDPP_FF_GET_GLOBAL_GAINS 0x71 +#define HIDPP_FF_SET_GLOBAL_GAINS 0x81 + +#define HIDPP_FF_EFFECT_STATE_GET 0x00 +#define HIDPP_FF_EFFECT_STATE_STOP 0x01 +#define HIDPP_FF_EFFECT_STATE_PLAY 0x02 +#define HIDPP_FF_EFFECT_STATE_PAUSE 0x03 + +#define HIDPP_FF_EFFECT_CONSTANT 0x00 +#define HIDPP_FF_EFFECT_PERIODIC_SINE 0x01 +#define HIDPP_FF_EFFECT_PERIODIC_SQUARE 0x02 +#define HIDPP_FF_EFFECT_PERIODIC_TRIANGLE 0x03 +#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP 0x04 +#define HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN 0x05 +#define HIDPP_FF_EFFECT_SPRING 0x06 +#define HIDPP_FF_EFFECT_DAMPER 0x07 +#define HIDPP_FF_EFFECT_FRICTION 0x08 +#define HIDPP_FF_EFFECT_INERTIA 0x09 +#define HIDPP_FF_EFFECT_RAMP 0x0A + +#define HIDPP_FF_EFFECT_AUTOSTART 0x80 + +#define HIDPP_FF_EFFECTID_NONE -1 +#define HIDPP_FF_EFFECTID_AUTOCENTER -2 + +#define HIDPP_FF_MAX_PARAMS 20 +#define HIDPP_FF_RESERVED_SLOTS 1 + +struct hidpp_ff_private_data { + struct hidpp_device *hidpp; + u8 feature_index; + u8 version; + u16 gain; + s16 range; + u8 slot_autocenter; + u8 num_effects; + int *effect_ids; + struct workqueue_struct *wq; + atomic_t workqueue_size; +}; + +struct hidpp_ff_work_data { + struct work_struct work; + struct hidpp_ff_private_data *data; + int effect_id; + u8 command; + u8 params[HIDPP_FF_MAX_PARAMS]; + u8 size; +}; + +static const signed short hiddpp_ff_effects[] = { + FF_CONSTANT, + FF_PERIODIC, + FF_SINE, + FF_SQUARE, + FF_SAW_UP, + FF_SAW_DOWN, + FF_TRIANGLE, + FF_SPRING, + FF_DAMPER, + FF_AUTOCENTER, + FF_GAIN, + -1 +}; + +static const signed short hiddpp_ff_effects_v2[] = { + FF_RAMP, + FF_FRICTION, + FF_INERTIA, + -1 +}; + +static const u8 HIDPP_FF_CONDITION_CMDS[] = { + HIDPP_FF_EFFECT_SPRING, + HIDPP_FF_EFFECT_FRICTION, + HIDPP_FF_EFFECT_DAMPER, + HIDPP_FF_EFFECT_INERTIA +}; + +static const char *HIDPP_FF_CONDITION_NAMES[] = { + "spring", + "friction", + "damper", + "inertia" +}; + + +static u8 hidpp_ff_find_effect(struct hidpp_ff_private_data *data, int effect_id) +{ + int i; + + for (i = 0; i < data->num_effects; i++) + if (data->effect_ids[i] == effect_id) + return i+1; + + return 0; +} + +static void hidpp_ff_work_handler(struct work_struct *w) +{ + struct hidpp_ff_work_data *wd = container_of(w, struct hidpp_ff_work_data, work); + struct hidpp_ff_private_data *data = wd->data; + struct hidpp_report response; + u8 slot; + int ret; + + /* add slot number if needed */ + switch (wd->effect_id) { + case HIDPP_FF_EFFECTID_AUTOCENTER: + wd->params[0] = data->slot_autocenter; + break; + case HIDPP_FF_EFFECTID_NONE: + /* leave slot as zero */ + break; + default: + /* find current slot for effect */ + wd->params[0] = hidpp_ff_find_effect(data, wd->effect_id); + break; + } + + /* send command and wait for reply */ + ret = hidpp_send_fap_command_sync(data->hidpp, data->feature_index, + wd->command, wd->params, wd->size, &response); + + if (ret) { + hid_err(data->hidpp->hid_dev, "Failed to send command to device!\n"); + goto out; + } + + /* parse return data */ + switch (wd->command) { + case HIDPP_FF_DOWNLOAD_EFFECT: + slot = response.fap.params[0]; + if (slot > 0 && slot <= data->num_effects) { + if (wd->effect_id >= 0) + /* regular effect uploaded */ + data->effect_ids[slot-1] = wd->effect_id; + else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER) + /* autocenter spring uploaded */ + data->slot_autocenter = slot; + } + break; + case HIDPP_FF_DESTROY_EFFECT: + if (wd->effect_id >= 0) + /* regular effect destroyed */ + data->effect_ids[wd->params[0]-1] = -1; + else if (wd->effect_id >= HIDPP_FF_EFFECTID_AUTOCENTER) + /* autocenter spring destoyed */ + data->slot_autocenter = 0; + break; + case HIDPP_FF_SET_GLOBAL_GAINS: + data->gain = (wd->params[0] << 8) + wd->params[1]; + break; + case HIDPP_FF_SET_APERTURE: + data->range = (wd->params[0] << 8) + wd->params[1]; + break; + default: + /* no action needed */ + break; + } + +out: + atomic_dec(&data->workqueue_size); + kfree(wd); +} + +static int hidpp_ff_queue_work(struct hidpp_ff_private_data *data, int effect_id, u8 command, u8 *params, u8 size) +{ + struct hidpp_ff_work_data *wd = kzalloc(sizeof(*wd), GFP_KERNEL); + int s; + + if (!wd) + return -ENOMEM; + + INIT_WORK(&wd->work, hidpp_ff_work_handler); + + wd->data = data; + wd->effect_id = effect_id; + wd->command = command; + wd->size = size; + memcpy(wd->params, params, size); + + atomic_inc(&data->workqueue_size); + queue_work(data->wq, &wd->work); + + /* warn about excessive queue size */ + s = atomic_read(&data->workqueue_size); + if (s >= 20 && s % 20 == 0) + hid_warn(data->hidpp->hid_dev, "Force feedback command queue contains %d commands, causing substantial delays!", s); + + return 0; +} + +static int hidpp_ff_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[20]; + u8 size; + int force; + + /* set common parameters */ + params[2] = effect->replay.length >> 8; + params[3] = effect->replay.length & 255; + params[4] = effect->replay.delay >> 8; + params[5] = effect->replay.delay & 255; + + switch (effect->type) { + case FF_CONSTANT: + force = (effect->u.constant.level * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[1] = HIDPP_FF_EFFECT_CONSTANT; + params[6] = force >> 8; + params[7] = force & 255; + params[8] = effect->u.constant.envelope.attack_level >> 7; + params[9] = effect->u.constant.envelope.attack_length >> 8; + params[10] = effect->u.constant.envelope.attack_length & 255; + params[11] = effect->u.constant.envelope.fade_level >> 7; + params[12] = effect->u.constant.envelope.fade_length >> 8; + params[13] = effect->u.constant.envelope.fade_length & 255; + size = 14; + dbg_hid("Uploading constant force level=%d in dir %d = %d\n", + effect->u.constant.level, + effect->direction, force); + dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n", + effect->u.constant.envelope.attack_level, + effect->u.constant.envelope.attack_length, + effect->u.constant.envelope.fade_level, + effect->u.constant.envelope.fade_length); + break; + case FF_PERIODIC: + { + switch (effect->u.periodic.waveform) { + case FF_SINE: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SINE; + break; + case FF_SQUARE: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SQUARE; + break; + case FF_SAW_UP: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP; + break; + case FF_SAW_DOWN: + params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN; + break; + case FF_TRIANGLE: + params[1] = HIDPP_FF_EFFECT_PERIODIC_TRIANGLE; + break; + default: + hid_err(data->hidpp->hid_dev, "Unexpected periodic waveform type %i!\n", effect->u.periodic.waveform); + return -EINVAL; + } + force = (effect->u.periodic.magnitude * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[6] = effect->u.periodic.magnitude >> 8; + params[7] = effect->u.periodic.magnitude & 255; + params[8] = effect->u.periodic.offset >> 8; + params[9] = effect->u.periodic.offset & 255; + params[10] = effect->u.periodic.period >> 8; + params[11] = effect->u.periodic.period & 255; + params[12] = effect->u.periodic.phase >> 8; + params[13] = effect->u.periodic.phase & 255; + params[14] = effect->u.periodic.envelope.attack_level >> 7; + params[15] = effect->u.periodic.envelope.attack_length >> 8; + params[16] = effect->u.periodic.envelope.attack_length & 255; + params[17] = effect->u.periodic.envelope.fade_level >> 7; + params[18] = effect->u.periodic.envelope.fade_length >> 8; + params[19] = effect->u.periodic.envelope.fade_length & 255; + size = 20; + dbg_hid("Uploading periodic force mag=%d/dir=%d, offset=%d, period=%d ms, phase=%d\n", + effect->u.periodic.magnitude, effect->direction, + effect->u.periodic.offset, + effect->u.periodic.period, + effect->u.periodic.phase); + dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n", + effect->u.periodic.envelope.attack_level, + effect->u.periodic.envelope.attack_length, + effect->u.periodic.envelope.fade_level, + effect->u.periodic.envelope.fade_length); + break; + } + case FF_RAMP: + params[1] = HIDPP_FF_EFFECT_RAMP; + force = (effect->u.ramp.start_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[6] = force >> 8; + params[7] = force & 255; + force = (effect->u.ramp.end_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15; + params[8] = force >> 8; + params[9] = force & 255; + params[10] = effect->u.ramp.envelope.attack_level >> 7; + params[11] = effect->u.ramp.envelope.attack_length >> 8; + params[12] = effect->u.ramp.envelope.attack_length & 255; + params[13] = effect->u.ramp.envelope.fade_level >> 7; + params[14] = effect->u.ramp.envelope.fade_length >> 8; + params[15] = effect->u.ramp.envelope.fade_length & 255; + size = 16; + dbg_hid("Uploading ramp force level=%d -> %d in dir %d = %d\n", + effect->u.ramp.start_level, + effect->u.ramp.end_level, + effect->direction, force); + dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n", + effect->u.ramp.envelope.attack_level, + effect->u.ramp.envelope.attack_length, + effect->u.ramp.envelope.fade_level, + effect->u.ramp.envelope.fade_length); + break; + case FF_FRICTION: + case FF_INERTIA: + case FF_SPRING: + case FF_DAMPER: + params[1] = HIDPP_FF_CONDITION_CMDS[effect->type - FF_SPRING]; + params[6] = effect->u.condition[0].left_saturation >> 9; + params[7] = (effect->u.condition[0].left_saturation >> 1) & 255; + params[8] = effect->u.condition[0].left_coeff >> 8; + params[9] = effect->u.condition[0].left_coeff & 255; + params[10] = effect->u.condition[0].deadband >> 9; + params[11] = (effect->u.condition[0].deadband >> 1) & 255; + params[12] = effect->u.condition[0].center >> 8; + params[13] = effect->u.condition[0].center & 255; + params[14] = effect->u.condition[0].right_coeff >> 8; + params[15] = effect->u.condition[0].right_coeff & 255; + params[16] = effect->u.condition[0].right_saturation >> 9; + params[17] = (effect->u.condition[0].right_saturation >> 1) & 255; + size = 18; + dbg_hid("Uploading %s force left coeff=%d, left sat=%d, right coeff=%d, right sat=%d\n", + HIDPP_FF_CONDITION_NAMES[effect->type - FF_SPRING], + effect->u.condition[0].left_coeff, + effect->u.condition[0].left_saturation, + effect->u.condition[0].right_coeff, + effect->u.condition[0].right_saturation); + dbg_hid(" deadband=%d, center=%d\n", + effect->u.condition[0].deadband, + effect->u.condition[0].center); + break; + default: + hid_err(data->hidpp->hid_dev, "Unexpected force type %i!\n", effect->type); + return -EINVAL; + } + + return hidpp_ff_queue_work(data, effect->id, HIDPP_FF_DOWNLOAD_EFFECT, params, size); +} + +static int hidpp_ff_playback(struct input_dev *dev, int effect_id, int value) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[2]; + + params[1] = value ? HIDPP_FF_EFFECT_STATE_PLAY : HIDPP_FF_EFFECT_STATE_STOP; + + dbg_hid("St%sing playback of effect %d.\n", value?"art":"opp", effect_id); + + return hidpp_ff_queue_work(data, effect_id, HIDPP_FF_SET_EFFECT_STATE, params, ARRAY_SIZE(params)); +} + +static int hidpp_ff_erase_effect(struct input_dev *dev, int effect_id) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 slot = 0; + + dbg_hid("Erasing effect %d.\n", effect_id); + + return hidpp_ff_queue_work(data, effect_id, HIDPP_FF_DESTROY_EFFECT, &slot, 1); +} + +static void hidpp_ff_set_autocenter(struct input_dev *dev, u16 magnitude) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[18]; + + dbg_hid("Setting autocenter to %d.\n", magnitude); + + /* start a standard spring effect */ + params[1] = HIDPP_FF_EFFECT_SPRING | HIDPP_FF_EFFECT_AUTOSTART; + /* zero delay and duration */ + params[2] = params[3] = params[4] = params[5] = 0; + /* set coeff to 25% of saturation */ + params[8] = params[14] = magnitude >> 11; + params[9] = params[15] = (magnitude >> 3) & 255; + params[6] = params[16] = magnitude >> 9; + params[7] = params[17] = (magnitude >> 1) & 255; + /* zero deadband and center */ + params[10] = params[11] = params[12] = params[13] = 0; + + hidpp_ff_queue_work(data, HIDPP_FF_EFFECTID_AUTOCENTER, HIDPP_FF_DOWNLOAD_EFFECT, params, ARRAY_SIZE(params)); +} + +static void hidpp_ff_set_gain(struct input_dev *dev, u16 gain) +{ + struct hidpp_ff_private_data *data = dev->ff->private; + u8 params[4]; + + dbg_hid("Setting gain to %d.\n", gain); + + params[0] = gain >> 8; + params[1] = gain & 255; + params[2] = 0; /* no boost */ + params[3] = 0; + + hidpp_ff_queue_work(data, HIDPP_FF_EFFECTID_NONE, HIDPP_FF_SET_GLOBAL_GAINS, params, ARRAY_SIZE(params)); +} + +static ssize_t hidpp_ff_range_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct hid_device *hid = to_hid_device(dev); + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *idev = hidinput->input; + struct hidpp_ff_private_data *data = idev->ff->private; + + return scnprintf(buf, PAGE_SIZE, "%u\n", data->range); +} + +static ssize_t hidpp_ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + struct hid_device *hid = to_hid_device(dev); + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *idev = hidinput->input; + struct hidpp_ff_private_data *data = idev->ff->private; + u8 params[2]; + int range = simple_strtoul(buf, NULL, 10); + + range = clamp(range, 180, 900); + + params[0] = range >> 8; + params[1] = range & 0x00FF; + + hidpp_ff_queue_work(data, -1, HIDPP_FF_SET_APERTURE, params, ARRAY_SIZE(params)); + + return count; +} + +static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, hidpp_ff_range_show, hidpp_ff_range_store); + +static void hidpp_ff_destroy(struct ff_device *ff) +{ + struct hidpp_ff_private_data *data = ff->private; + + kfree(data->effect_ids); +} + +int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) +{ + struct hid_device *hid = hidpp->hid_dev; + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *dev = hidinput->input; + const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); + const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); + struct ff_device *ff; + struct hidpp_report response; + struct hidpp_ff_private_data *data; + int error, j, num_slots; + u8 version; + + if (!dev) { + hid_err(hid, "Struct input_dev not set!\n"); + return -EINVAL; + } + + /* Get firmware release */ + version = bcdDevice & 255; + + /* Set supported force feedback capabilities */ + for (j = 0; hiddpp_ff_effects[j] >= 0; j++) + set_bit(hiddpp_ff_effects[j], dev->ffbit); + if (version > 1) + for (j = 0; hiddpp_ff_effects_v2[j] >= 0; j++) + set_bit(hiddpp_ff_effects_v2[j], dev->ffbit); + + /* Read number of slots available in device */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_GET_INFO, NULL, 0, &response); + if (error) { + if (error < 0) + return error; + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", + __func__, error); + return -EPROTO; + } + + num_slots = response.fap.params[0] - HIDPP_FF_RESERVED_SLOTS; + + error = input_ff_create(dev, num_slots); + + if (error) { + hid_err(dev, "Failed to create FF device!\n"); + return error; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->effect_ids = kcalloc(num_slots, sizeof(int), GFP_KERNEL); + if (!data->effect_ids) { + kfree(data); + return -ENOMEM; + } + data->hidpp = hidpp; + data->feature_index = feature_index; + data->version = version; + data->slot_autocenter = 0; + data->num_effects = num_slots; + for (j = 0; j < num_slots; j++) + data->effect_ids[j] = -1; + + ff = dev->ff; + ff->private = data; + + ff->upload = hidpp_ff_upload_effect; + ff->erase = hidpp_ff_erase_effect; + ff->playback = hidpp_ff_playback; + ff->set_gain = hidpp_ff_set_gain; + ff->set_autocenter = hidpp_ff_set_autocenter; + ff->destroy = hidpp_ff_destroy; + + + /* reset all forces */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_RESET_ALL, NULL, 0, &response); + + /* Read current Range */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_GET_APERTURE, NULL, 0, &response); + if (error) + hid_warn(hidpp->hid_dev, "Failed to read range from device!\n"); + data->range = error ? 900 : get_unaligned_be16(&response.fap.params[0]); + + /* Create sysfs interface */ + error = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range); + if (error) + hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d!\n", error); + + /* Read the current gain values */ + error = hidpp_send_fap_command_sync(hidpp, feature_index, + HIDPP_FF_GET_GLOBAL_GAINS, NULL, 0, &response); + if (error) + hid_warn(hidpp->hid_dev, "Failed to read gain values from device!\n"); + data->gain = error ? 0xffff : get_unaligned_be16(&response.fap.params[0]); + /* ignore boost value at response.fap.params[2] */ + + /* init the hardware command queue */ + data->wq = create_singlethread_workqueue("hidpp-ff-sendqueue"); + atomic_set(&data->workqueue_size, 0); + + /* initialize with zero autocenter to get wheel in usable state */ + hidpp_ff_set_autocenter(dev, 0); + + hid_info(hid, "Force feeback support loaded (firmware release %d).\n", version); + + return 0; +} + +int hidpp_ff_deinit(struct hid_device *hid) +{ + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); + struct input_dev *dev = hidinput->input; + struct hidpp_ff_private_data *data; + + if (!dev) { + hid_err(hid, "Struct input_dev not found!\n"); + return -EINVAL; + } + + hid_info(hid, "Unloading HID++ force feedback.\n"); + data = dev->ff->private; + if (!data) { + hid_err(hid, "Private data not found!\n"); + return -EINVAL; + } + + destroy_workqueue(data->wq); + device_remove_file(&hid->dev, &dev_attr_range); + + return 0; +} + + /* ************************************************************************** */ /* */ /* Device Support */ @@ -1301,121 +1890,22 @@ static int k400_connect(struct hid_device *hdev, bool connected) #define HIDPP_PAGE_G920_FORCE_FEEDBACK 0x8123 -/* Using session ID = 1 */ -#define CMD_G920_FORCE_GET_APERTURE 0x51 -#define CMD_G920_FORCE_SET_APERTURE 0x61 - -struct g920_private_data { - u8 force_feature; - u16 range; -}; - -static ssize_t g920_range_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct hid_device *hid = to_hid_device(dev); - struct hidpp_device *hidpp = hid_get_drvdata(hid); - struct g920_private_data *pdata; - - pdata = hidpp->private_data; - if (!pdata) { - hid_err(hid, "Private driver data not found!\n"); - return -EINVAL; - } - - return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->range); -} - -static ssize_t g920_range_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hid = to_hid_device(dev); - struct hidpp_device *hidpp = hid_get_drvdata(hid); - struct g920_private_data *pdata; - struct hidpp_report response; - u8 params[2]; - int ret; - u16 range = simple_strtoul(buf, NULL, 10); - - pdata = hidpp->private_data; - if (!pdata) { - hid_err(hid, "Private driver data not found!\n"); - return -EINVAL; - } - - if (range < 180) - range = 180; - else if (range > 900) - range = 900; - - params[0] = range >> 8; - params[1] = range & 0x00FF; - - ret = hidpp_send_fap_command_sync(hidpp, pdata->force_feature, - CMD_G920_FORCE_SET_APERTURE, params, 2, &response); - if (ret) - return ret; - - pdata->range = range; - return count; -} - -static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, g920_range_show, g920_range_store); - -static int g920_allocate(struct hid_device *hdev) -{ - struct hidpp_device *hidpp = hid_get_drvdata(hdev); - struct g920_private_data *pdata; - - pdata = devm_kzalloc(&hdev->dev, sizeof(struct g920_private_data), - GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - hidpp->private_data = pdata; - - return 0; -} - static int g920_get_config(struct hidpp_device *hidpp) { - struct g920_private_data *pdata = hidpp->private_data; - struct hidpp_report response; u8 feature_type; u8 feature_index; int ret; - pdata = hidpp->private_data; - if (!pdata) { - hid_err(hidpp->hid_dev, "Private driver data not found!\n"); - return -EINVAL; - } - /* Find feature and store for later use */ ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_G920_FORCE_FEEDBACK, &feature_index, &feature_type); if (ret) return ret; - pdata->force_feature = feature_index; - - /* Read current Range */ - ret = hidpp_send_fap_command_sync(hidpp, feature_index, - CMD_G920_FORCE_GET_APERTURE, NULL, 0, &response); - if (ret > 0) { - hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", - __func__, ret); - return -EPROTO; - } - if (ret) - return ret; - - pdata->range = get_unaligned_be16(&response.fap.params[0]); - - /* Create sysfs interface */ - ret = device_create_file(&(hidpp->hid_dev->dev), &dev_attr_range); + ret = hidpp_ff_init(hidpp, feature_index); if (ret) - hid_warn(hidpp->hid_dev, "Unable to create sysfs interface for \"range\", errno %d\n", ret); + hid_warn(hidpp->hid_dev, "Unable to initialize force feedback support, errno %d\n", + ret); return 0; } @@ -1739,10 +2229,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ret = k400_allocate(hdev); if (ret) goto allocate_fail; - } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - ret = g920_allocate(hdev); - if (ret) - goto allocate_fail; } INIT_WORK(&hidpp->work, delayed_work_cb); @@ -1825,7 +2311,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) hid_hw_open_failed: hid_device_io_stop(hdev); if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - device_remove_file(&hdev->dev, &dev_attr_range); hid_hw_close(hdev); hid_hw_stop(hdev); } @@ -1843,7 +2328,7 @@ static void hidpp_remove(struct hid_device *hdev) struct hidpp_device *hidpp = hid_get_drvdata(hdev); if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) { - device_remove_file(&hdev->dev, &dev_attr_range); + hidpp_ff_deinit(hdev); hid_hw_close(hdev); } hid_hw_stop(hdev); -- cgit From af2e628d6be7a510e2667c3b5358350464d0f5b7 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 28 Jan 2016 14:28:39 +0100 Subject: HID: logitech-hidpp: limit visibility of init/deinit functions hidpp_ff_init() and hidpp_ff_deinit() are not used outside of hid-logitech-hidpp.c, so let's make them static. Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 2869bbff0899..2e2515a4c070 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -1226,7 +1226,7 @@ static void hidpp_ff_destroy(struct ff_device *ff) kfree(data->effect_ids); } -int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) +static int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) { struct hid_device *hid = hidpp->hid_dev; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); @@ -1337,7 +1337,7 @@ int hidpp_ff_init(struct hidpp_device *hidpp, u8 feature_index) return 0; } -int hidpp_ff_deinit(struct hid_device *hid) +static int hidpp_ff_deinit(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct input_dev *dev = hidinput->input; -- cgit From ccdbddfeff58788f7887f39a681b73c3d95b1d2f Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 30 Dec 2015 22:16:38 +0800 Subject: gpio: davinci: use irq_data_get_chip_type Use irq_data_get_chip_type() instead of container_of(). Signed-off-by: Geliang Tang Reviewed-by: Grygorii Strashko Acked-by: Santosh Shilimkar Signed-off-by: Linus Walleij --- drivers/gpio/gpio-davinci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index ec58f4288649..845edffbcc3f 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -432,8 +432,7 @@ static struct irq_chip *davinci_gpio_get_irq_chip(unsigned int irq) { static struct irq_chip_type gpio_unbanked; - gpio_unbanked = *container_of(irq_get_chip(irq), - struct irq_chip_type, chip); + gpio_unbanked = *irq_data_get_chip_type(irq_get_irq_data(irq)); return &gpio_unbanked.chip; }; -- cgit From 9090a2d5e3e6f1f1f1aabd44f9335ff873239b60 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 28 Jan 2016 14:59:16 +0200 Subject: selinux: use absolute path to include directory Compiler warns us a lot that it can't find include folder because it's provided in relative form. CC security/selinux/netlabel.o cc1: warning: security/selinux/include: No such file or directory cc1: warning: security/selinux/include: No such file or directory cc1: warning: security/selinux/include: No such file or directory cc1: warning: security/selinux/include: No such file or directory Add $(srctree) prefix to the path. Signed-off-by: Andy Shevchenko [PM: minor description edits to fit under 80char width] Signed-off-by: Paul Moore --- security/selinux/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/Makefile b/security/selinux/Makefile index ad5cd76ec231..3411c33e2a44 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -13,7 +13,7 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o selinux-$(CONFIG_NETLABEL) += netlabel.o -ccflags-y := -Isecurity/selinux -Isecurity/selinux/include +ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h -- cgit From 633f67a51d078bea627f22d6208442e1e1f391cb Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 17 Jan 2016 16:49:07 +0100 Subject: HSI: nokia-modem: add n950 and n9 support The Nokia N950 and Nokia N9 also have a SSI connected modem, which use the same protocols as the Nokia N900, but with increased link speed (96000 kbps instead of 55000 kbps) and with less GPIOs. Since it's unclear, if the N950 and the N9 use exactly the same modem, each of them gets their own compatible string. Acked-by: Rob Herring Tested-by: Aaro Koskinen Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/hsi/nokia-modem.txt | 12 +++++++----- drivers/hsi/clients/nokia-modem.c | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/hsi/nokia-modem.txt b/Documentation/devicetree/bindings/hsi/nokia-modem.txt index 8a979780452b..53de1d9d0b95 100644 --- a/Documentation/devicetree/bindings/hsi/nokia-modem.txt +++ b/Documentation/devicetree/bindings/hsi/nokia-modem.txt @@ -7,6 +7,8 @@ properties are needed by the Nokia modem HSI client: Required properties: - compatible: Should be one of "nokia,n900-modem" + "nokia,n950-modem" + "nokia,n9-modem" - hsi-channel-names: Should contain the following strings "mcsaab-control" "speech-control" @@ -15,11 +17,11 @@ Required properties: - gpios: Should provide a GPIO handler for each GPIO listed in gpio-names - gpio-names: Should contain the following strings - "cmt_apeslpx" - "cmt_rst_rq" - "cmt_en" - "cmt_rst" - "cmt_bsi" + "cmt_apeslpx" (for n900, n950, n9) + "cmt_rst_rq" (for n900, n950, n9) + "cmt_en" (for n900, n950, n9) + "cmt_rst" (for n900) + "cmt_bsi" (for n900) - interrupts: Should be IRQ handle for modem's reset indication Example: diff --git a/drivers/hsi/clients/nokia-modem.c b/drivers/hsi/clients/nokia-modem.c index 7f82c911ad74..c000780d931f 100644 --- a/drivers/hsi/clients/nokia-modem.c +++ b/drivers/hsi/clients/nokia-modem.c @@ -281,6 +281,8 @@ static int nokia_modem_remove(struct device *dev) #ifdef CONFIG_OF static const struct of_device_id nokia_modem_of_match[] = { { .compatible = "nokia,n900-modem", }, + { .compatible = "nokia,n950-modem", }, + { .compatible = "nokia,n9-modem", }, {}, }; MODULE_DEVICE_TABLE(of, nokia_modem_of_match); -- cgit From 87d99063be016ceee90723a13365a40b21eec0d9 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 17 Jan 2016 16:49:08 +0100 Subject: HSI: ssi-protocol: Use handshake logic from n950 When using the ssi-protocol driver with the Nokia N950, the following error is thrown during modem powered up sequence. [13852.274993] port0: SSI error: 0x01 [13852.279205] ssi-protocol ssi-protocol: RX error detected [13852.284820] ssi-protocol ssi-protocol: Main state: 1 [13852.290069] ssi-protocol ssi-protocol: Recv state: 0 [13852.295288] ssi-protocol ssi-protocol: Send state: 0 [13852.300537] ssi-protocol ssi-protocol: CMT Offline [13852.305603] ssi-protocol ssi-protocol: Wake test 1 [13852.310638] ssi-protocol ssi-protocol: Data RX id: 0 [13852.315887] ssi-protocol ssi-protocol: Data TX id: 0 [13856.001464] ssi-protocol ssi-protocol: Watchdog trigerred [13856.007293] ssi-protocol ssi-protocol: Main state: 1 [13856.012542] ssi-protocol ssi-protocol: Recv state: 0 [13856.017761] ssi-protocol ssi-protocol: Send state: 0 [13856.023010] ssi-protocol ssi-protocol: CMT Offline [13856.028045] ssi-protocol ssi-protocol: Wake test 0 [13856.033111] ssi-protocol ssi-protocol: Data RX id: 0 [13856.038330] ssi-protocol ssi-protocol: Data TX id: 0 This patch fixes the issue by using the handshake setup from the Nokia N950 kernel. The new handshake sequence also works with the N900, so there is no need to differentiate between both modems. Tested-by: Aaro Koskinen Signed-off-by: Sebastian Reichel --- drivers/hsi/clients/ssi_protocol.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index a38af68cf326..6595d2091268 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -521,13 +521,7 @@ static void ssip_start_rx(struct hsi_client *cl) * high transition. Therefore we need to ignore the sencond UP event. */ if ((ssi->main_state != ACTIVE) || (ssi->recv_state == RECV_READY)) { - if (ssi->main_state == INIT) { - ssi->main_state = HANDSHAKE; - spin_unlock(&ssi->lock); - ssip_send_bootinfo_req_cmd(cl); - } else { - spin_unlock(&ssi->lock); - } + spin_unlock(&ssi->lock); return; } ssip_set_rxstate(ssi, RECV_READY); @@ -671,6 +665,7 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) ssip_error(cl); /* Fall through */ case INIT: + case HANDSHAKE: spin_lock(&ssi->lock); ssi->main_state = HANDSHAKE; if (!ssi->waketest) { @@ -688,9 +683,6 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) msg->complete = ssip_release_cmd; hsi_async_write(cl, msg); break; - case HANDSHAKE: - /* Ignore */ - break; default: dev_dbg(&cl->device, "Wrong state M(%d)\n", ssi->main_state); break; @@ -939,9 +931,11 @@ static int ssip_pn_open(struct net_device *dev) ssi->waketest = 1; ssi_waketest(cl, 1); /* FIXME: To be removed */ } - ssi->main_state = INIT; + ssi->main_state = HANDSHAKE; spin_unlock_bh(&ssi->lock); + ssip_send_bootinfo_req_cmd(cl); + return 0; } -- cgit From 33d7136336a94feade73b08b9c4bd1420df4e572 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:08 -0800 Subject: n_tty: Always wake up read()/poll() if new input A read() in non-canonical mode when VMIN > 0 and VTIME == 0 does not complete until at least VMIN chars have been read (or the user buffer is full). In this infrequent read mode, n_tty_read() attempts to reduce wakeups by computing the amount of data still necessary to complete the read (minimum_to_wake) and only waking the read()/poll() when that much unread data has been processed. This is the only read mode for which new data does not necessarily generate a wakeup. However, this optimization is broken and commonly leads to hung reads even though the necessary amount of data has been received. Since the optimization is of marginal value anyway, just remove the whole thing. This also remedies a race between a concurrent poll() and read() in this mode, where the poll() can reset the minimum_to_wake of the read() (and vice versa). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 827206914b02..d04f398d5de3 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -113,8 +113,6 @@ struct n_tty_data { DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE); unsigned char echo_buf[N_TTY_BUF_SIZE]; - int minimum_to_wake; - /* consumer-published */ size_t read_tail; size_t line_start; @@ -1633,7 +1631,7 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp, /* publish read_head to consumer */ smp_store_release(&ldata->commit_head, ldata->read_head); - if ((read_cnt(ldata) >= ldata->minimum_to_wake) || L_EXTPROC(tty)) { + if (read_cnt(ldata)) { kill_fasync(&tty->fasync, SIGIO, POLL_IN); wake_up_interruptible_poll(&tty->read_wait, POLLIN); } @@ -1900,7 +1898,6 @@ static int n_tty_open(struct tty_struct *tty) reset_buffer_flags(tty->disc_data); ldata->column = 0; ldata->canon_column = 0; - ldata->minimum_to_wake = 1; ldata->num_overrun = 0; ldata->no_room = 0; ldata->lnext = 0; @@ -2163,14 +2160,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, minimum = MIN_CHAR(tty); if (minimum) { time = (HZ / 10) * TIME_CHAR(tty); - if (time) - ldata->minimum_to_wake = 1; - else if (!waitqueue_active(&tty->read_wait) || - (ldata->minimum_to_wake > minimum)) - ldata->minimum_to_wake = minimum; } else { timeout = (HZ / 10) * TIME_CHAR(tty); - ldata->minimum_to_wake = minimum = 1; + minimum = 1; } } @@ -2197,10 +2189,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, break; } - if (((minimum - (b - buf)) < ldata->minimum_to_wake) && - ((minimum - (b - buf)) >= 1)) - ldata->minimum_to_wake = (minimum - (b - buf)); - done = check_other_done(tty); if (!input_available_p(tty, 0)) { @@ -2266,9 +2254,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, up_read(&tty->termios_rwsem); remove_wait_queue(&tty->read_wait, &wait); - if (!waitqueue_active(&tty->read_wait)) - ldata->minimum_to_wake = minimum; - mutex_unlock(&ldata->atomic_read_lock); if (b - buf) @@ -2403,7 +2388,6 @@ break_out: static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) { - struct n_tty_data *ldata = tty->disc_data; unsigned int mask = 0; poll_wait(file, &tty->read_wait, wait); @@ -2416,12 +2400,6 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, mask |= POLLPRI | POLLIN | POLLRDNORM; if (tty_hung_up_p(file)) mask |= POLLHUP; - if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) { - if (MIN_CHAR(tty) && !TIME_CHAR(tty)) - ldata->minimum_to_wake = MIN_CHAR(tty); - else - ldata->minimum_to_wake = 1; - } if (tty->ops->write && !tty_is_writelocked(tty) && tty_chars_in_buffer(tty) < WAKEUP_CHARS && tty_write_room(tty) > 0) @@ -2472,14 +2450,6 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, static void n_tty_fasync(struct tty_struct *tty, int on) { - struct n_tty_data *ldata = tty->disc_data; - - if (!waitqueue_active(&tty->read_wait)) { - if (on) - ldata->minimum_to_wake = 1; - else if (!tty->fasync) - ldata->minimum_to_wake = N_TTY_BUF_SIZE; - } } static struct tty_ldisc_ops n_tty_ops = { -- cgit From bee6741ca022f051ea1b46e16fb2ff0097643181 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:09 -0800 Subject: tty, n_tty: Remove fasync() ldisc notification Only the N_TTY line discipline implements the signal-driven i/o notification enabled/disabled by fcntl(F_SETFL, O_ASYNC). The ldisc fasync() notification is sent to the ldisc when the enable state has changed (the tty core is notified via the fasync() VFS file operation). The N_TTY line discipline used the enable state to change the wakeup condition (minimum_to_wake = 1) for notifying the signal handler i/o is available. However, just the presence of data is sufficient and necessary to signal i/o is available, so changing minimum_to_wake is unnecessary (and creates a race condition with read() and poll() which may be concurrently updating minimum_to_wake). Furthermore, since the kill_fasync() VFS helper performs no action if the fasync list is empty, calling unconditionally is preferred; if signal driven i/o just has been disabled, no signal will be sent by kill_fasync() anyway so notification of the change via the ldisc fasync() method is superfluous. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 5 ----- drivers/tty/tty_io.c | 8 -------- include/linux/tty_ldisc.h | 6 ------ 3 files changed, 19 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d04f398d5de3..a93e4c7e82ae 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2448,10 +2448,6 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file, } } -static void n_tty_fasync(struct tty_struct *tty, int on) -{ -} - static struct tty_ldisc_ops n_tty_ops = { .magic = TTY_LDISC_MAGIC, .name = "n_tty", @@ -2465,7 +2461,6 @@ static struct tty_ldisc_ops n_tty_ops = { .poll = n_tty_poll, .receive_buf = n_tty_receive_buf, .write_wakeup = n_tty_write_wakeup, - .fasync = n_tty_fasync, .receive_buf2 = n_tty_receive_buf2, }; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index c5b4274584dc..7533ab1abe72 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2219,7 +2219,6 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) static int __tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty = file_tty(filp); - struct tty_ldisc *ldisc; unsigned long flags; int retval = 0; @@ -2230,13 +2229,6 @@ static int __tty_fasync(int fd, struct file *filp, int on) if (retval <= 0) goto out; - ldisc = tty_ldisc_ref(tty); - if (ldisc) { - if (ldisc->ops->fasync) - ldisc->ops->fasync(tty, on); - tty_ldisc_deref(ldisc); - } - if (on) { enum pid_type type; struct pid *pid; diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h index 6101ab8dc148..3971cf0eb467 100644 --- a/include/linux/tty_ldisc.h +++ b/include/linux/tty_ldisc.h @@ -98,11 +98,6 @@ * seek to perform this action quickly but should wait until * any pending driver I/O is completed. * - * void (*fasync)(struct tty_struct *, int on) - * - * Notify line discipline when signal-driven I/O is enabled or - * disabled. - * * void (*dcd_change)(struct tty_struct *tty, unsigned int status) * * Tells the discipline that the DCD pin has changed its status. @@ -202,7 +197,6 @@ struct tty_ldisc_ops { char *fp, int count); void (*write_wakeup)(struct tty_struct *); void (*dcd_change)(struct tty_struct *, unsigned int); - void (*fasync)(struct tty_struct *tty, int on); int (*receive_buf2)(struct tty_struct *, const unsigned char *cp, char *fp, int count); -- cgit From f557474ca3a23800dffb790846bcb121fa046c71 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:10 -0800 Subject: tty: Add fasync() hung up file operation VFS uses a two-stage check-and-call method for invoking file_operations methods, without explicitly snapshotting either the file_operations ptr or the function ptr. Since the tty core is one of the few VFS users that changes the f_op file_operations ptr of the file descriptor (when the tty has been hung up), and since the likelihood of the compiler generating a reload of either f_op or the function ptr is basically nil, just define a hung up fasync() file operation that returns an error. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 7533ab1abe72..0140c8669ada 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -468,6 +468,11 @@ static long hung_up_tty_compat_ioctl(struct file *file, return cmd == TIOCSPGRP ? -ENOTTY : -EIO; } +static int hung_up_tty_fasync(int fd, struct file *file, int on) +{ + return -ENOTTY; +} + static const struct file_operations tty_fops = { .llseek = no_llseek, .read = tty_read, @@ -500,6 +505,7 @@ static const struct file_operations hung_up_tty_fops = { .unlocked_ioctl = hung_up_tty_ioctl, .compat_ioctl = hung_up_tty_compat_ioctl, .release = tty_release, + .fasync = hung_up_tty_fasync, }; static DEFINE_SPINLOCK(redirect_lock); -- cgit From a8f3a29718f77df3116955d100756f67fafabec0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:11 -0800 Subject: tty: Fix ioctl(FIOASYNC) on hungup file A small race window exists which allows signal-driven async i/o to be enabled for the tty when the file ptr has already been hungup and signal-driven i/o has been disabled: CPU 0 CPU 1 ----- ------ ioctl_fioasync(on) filp->f_op->fasync(on) __tty_hangup() tty_fasync(on) tty_lock() tty_lock() ... . filp->f_op = &hung_up_tty_fops; (waiting) __tty_fasync(off) . tty_unlock() /* gets tty lock */ /* enables FASYNC */ Check the tty has not been hungup while holding tty_lock. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 0140c8669ada..8d26ed79bb4c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2260,10 +2260,11 @@ out: static int tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty = file_tty(filp); - int retval; + int retval = -ENOTTY; tty_lock(tty); - retval = __tty_fasync(fd, filp, on); + if (!tty_hung_up_p(filp)) + retval = __tty_fasync(fd, filp, on); tty_unlock(tty); return retval; -- cgit From 7bccc36544a8b4a7d768f8ccdd6001a52872aca9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:12 -0800 Subject: n_tty: Fix stuck write wakeup If signal-driven i/o is disabled while write wakeup is pending (ie., n_tty_write() has set TTY_DO_WRITE_WAKEUP but then signal-driven i/o is disabled), the TTY_DO_WRITE_WAKEUP bit will never be cleared and will cause tty_wakeup() to always call n_tty_write_wakeup. Unconditionally clear the write wakeup, and since kill_fasync() already checks if the fasync ptr is null, call kill_fasync() unconditionally as well. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index a93e4c7e82ae..086fd9983caa 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -228,8 +228,8 @@ static ssize_t chars_in_buffer(struct tty_struct *tty) static void n_tty_write_wakeup(struct tty_struct *tty) { - if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) - kill_fasync(&tty->fasync, SIGIO, POLL_OUT); + clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + kill_fasync(&tty->fasync, SIGIO, POLL_OUT); } static void n_tty_check_throttle(struct tty_struct *tty) -- cgit From ffb91a459c6cacb10972f5dff893fb1292bac85d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:13 -0800 Subject: n_tty: Remove tty count checks from unthrottle Since n_tty_check_unthrottle() is only called from n_tty_read() which only originates from a userspace read(), the tty count cannot be 0; the read() guarantees the file descriptor has not yet been released. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 086fd9983caa..5ae661cd236e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -261,8 +261,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) if (tty->driver->type == TTY_DRIVER_TYPE_PTY) { if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) return; - if (!tty->count) - return; n_tty_kick_worker(tty); tty_wakeup(tty->link); return; @@ -281,8 +279,6 @@ static void n_tty_check_unthrottle(struct tty_struct *tty) tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE); if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE) break; - if (!tty->count) - break; n_tty_kick_worker(tty); unthrottled = tty_unthrottle_safe(tty); if (!unthrottled) -- cgit From 87108bc9870ae86ca4fcc05115a134af7a0f4e96 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 21:45:14 -0800 Subject: tty: n_tty: fix SIGIO for output According to fcntl(2), "a SIGIO signal is sent whenever input or output becomes possible on that file descriptor", i.e. after the output buffer was full and now has space for new data. But in fact SIGIO is sent after every write. n_tty_write() should set TTY_DO_WRITE_WAKEUP only when not all data could be written to the buffer. [pjh: Also fixes missed SIGIO if amt written just happens to be [ amount still to write Signed-off-by: Johannes Stezenbach [pjh: minor patch edits and re-submit] Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 5ae661cd236e..fad365aa1f5c 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2361,7 +2361,7 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, } break_out: remove_wait_queue(&tty->write_wait, &wait); - if (b - buf != nr && tty->fasync) + if (nr && tty->fasync) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); up_read(&tty->termios_rwsem); return (b - buf) ? b - buf : retval; -- cgit From dcaee813a64368e09878d0cee931d14c9603e925 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 28 Jan 2016 16:43:35 +0800 Subject: ASoC: rt5616: add mclk property for rt5616 document This patch add the mclk property for the CODEC driver, since sometime the CODEC driver needs the clock enabled. The system clock of ALC5616 can be selected from MCLK, That's also make as the codec master clock provider, Signed-off-by: Caesar Wang Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt5616.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rt5616.txt b/Documentation/devicetree/bindings/sound/rt5616.txt index efc48c65198d..e41085818559 100644 --- a/Documentation/devicetree/bindings/sound/rt5616.txt +++ b/Documentation/devicetree/bindings/sound/rt5616.txt @@ -8,6 +8,12 @@ Required properties: - reg : The I2C address of the device. +Optional properties: + +- clocks: The phandle of the master clock to the CODEC. + +- clock-names: Should be "mclk". + Pins on the device (for linking into audio routes) for RT5616: * IN1P -- cgit From 99081589c5ad590e9828ae9febc384612f241164 Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 28 Jan 2016 16:43:36 +0800 Subject: ASoC: rt5616: trivial: fix the typo This patch try to fix the trivial typo. Run "scripts/checkpatch.pl -f --subjective xxx" The enable more subjective tests. Signed-off-by: Caesar Wang Signed-off-by: Mark Brown --- sound/soc/codecs/rt5616.c | 376 +++++++++++++++++++++++----------------------- 1 file changed, 191 insertions(+), 185 deletions(-) diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index 1c10d8ed39d2..d4bdf9f6f0af 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -53,6 +53,7 @@ static const struct reg_sequence init_list[] = { {RT5616_PR_BASE + 0x21, 0x4040}, {RT5616_PR_BASE + 0x23, 0x0004}, }; + #define RT5616_INIT_REG_LEN ARRAY_SIZE(init_list) static const struct reg_default rt5616_reg[] = { @@ -162,9 +163,8 @@ static bool rt5616_volatile_register(struct device *dev, unsigned int reg) for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) { if (reg >= rt5616_ranges[i].range_min && - reg <= rt5616_ranges[i].range_max) { + reg <= rt5616_ranges[i].range_max) return true; - } } switch (reg) { @@ -190,9 +190,8 @@ static bool rt5616_readable_register(struct device *dev, unsigned int reg) for (i = 0; i < ARRAY_SIZE(rt5616_ranges); i++) { if (reg >= rt5616_ranges[i].range_min && - reg <= rt5616_ranges[i].range_max) { + reg <= rt5616_ranges[i].range_max) return true; - } } switch (reg) { @@ -307,45 +306,45 @@ static unsigned int bst_tlv[] = { static const struct snd_kcontrol_new rt5616_snd_controls[] = { /* Headphone Output Volume */ SOC_DOUBLE("HP Playback Switch", RT5616_HP_VOL, - RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1), + RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1), SOC_DOUBLE_TLV("HP Playback Volume", RT5616_HP_VOL, - RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv), + RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv), /* OUTPUT Control */ SOC_DOUBLE("OUT Playback Switch", RT5616_LOUT_CTRL1, - RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1), + RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1), SOC_DOUBLE("OUT Channel Switch", RT5616_LOUT_CTRL1, - RT5616_VOL_L_SFT, RT5616_VOL_R_SFT, 1, 1), + RT5616_VOL_L_SFT, RT5616_VOL_R_SFT, 1, 1), SOC_DOUBLE_TLV("OUT Playback Volume", RT5616_LOUT_CTRL1, - RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv), + RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, 39, 1, out_vol_tlv), /* DAC Digital Volume */ SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5616_DAC1_DIG_VOL, - RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, - 175, 0, dac_vol_tlv), + RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, + 175, 0, dac_vol_tlv), /* IN1/IN2 Control */ SOC_SINGLE_TLV("IN1 Boost Volume", RT5616_IN1_IN2, - RT5616_BST_SFT1, 8, 0, bst_tlv), + RT5616_BST_SFT1, 8, 0, bst_tlv), SOC_SINGLE_TLV("IN2 Boost Volume", RT5616_IN1_IN2, - RT5616_BST_SFT2, 8, 0, bst_tlv), + RT5616_BST_SFT2, 8, 0, bst_tlv), /* INL/INR Volume Control */ SOC_DOUBLE_TLV("IN Capture Volume", RT5616_INL1_INR1_VOL, - RT5616_INL_VOL_SFT, RT5616_INR_VOL_SFT, - 31, 1, in_vol_tlv), + RT5616_INL_VOL_SFT, RT5616_INR_VOL_SFT, + 31, 1, in_vol_tlv), /* ADC Digital Volume Control */ SOC_DOUBLE("ADC Capture Switch", RT5616_ADC_DIG_VOL, - RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1), + RT5616_L_MUTE_SFT, RT5616_R_MUTE_SFT, 1, 1), SOC_DOUBLE_TLV("ADC Capture Volume", RT5616_ADC_DIG_VOL, - RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, - 127, 0, adc_vol_tlv), + RT5616_L_VOL_SFT, RT5616_R_VOL_SFT, + 127, 0, adc_vol_tlv), /* ADC Boost Volume Control */ SOC_DOUBLE_TLV("ADC Boost Volume", RT5616_ADC_BST_VOL, - RT5616_ADC_L_BST_SFT, RT5616_ADC_R_BST_SFT, - 3, 0, adc_bst_tlv), + RT5616_ADC_L_BST_SFT, RT5616_ADC_R_BST_SFT, + 3, 0, adc_bst_tlv), }; static int is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, - struct snd_soc_dapm_widget *sink) + struct snd_soc_dapm_widget *sink) { unsigned int val; @@ -462,20 +461,20 @@ static const struct snd_kcontrol_new rt5616_lout_mix[] = { }; static int rt5616_adc_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, RT5616_ADC_DIG_VOL, - RT5616_L_MUTE | RT5616_R_MUTE, 0); + RT5616_L_MUTE | RT5616_R_MUTE, 0); break; case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, RT5616_ADC_DIG_VOL, - RT5616_L_MUTE | RT5616_R_MUTE, - RT5616_L_MUTE | RT5616_R_MUTE); + RT5616_L_MUTE | RT5616_R_MUTE, + RT5616_L_MUTE | RT5616_R_MUTE); break; default: @@ -486,7 +485,7 @@ static int rt5616_adc_event(struct snd_soc_dapm_widget *w, } static int rt5616_charge_pump_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); @@ -494,54 +493,55 @@ static int rt5616_charge_pump_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: /* depop parameters */ snd_soc_update_bits(codec, RT5616_DEPOP_M2, - RT5616_DEPOP_MASK, RT5616_DEPOP_MAN); + RT5616_DEPOP_MASK, RT5616_DEPOP_MAN); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_HP_CP_MASK | RT5616_HP_SG_MASK | - RT5616_HP_CB_MASK, RT5616_HP_CP_PU | - RT5616_HP_SG_DIS | RT5616_HP_CB_PU); + RT5616_HP_CP_MASK | RT5616_HP_SG_MASK | + RT5616_HP_CB_MASK, RT5616_HP_CP_PU | + RT5616_HP_SG_DIS | RT5616_HP_CB_PU); snd_soc_write(codec, RT5616_PR_BASE + - RT5616_HP_DCC_INT1, 0x9f00); + RT5616_HP_DCC_INT1, 0x9f00); /* headphone amp power on */ snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_FV1 | RT5616_PWR_FV2, 0); + RT5616_PWR_FV1 | RT5616_PWR_FV2, 0); snd_soc_update_bits(codec, RT5616_PWR_VOL, - RT5616_PWR_HV_L | RT5616_PWR_HV_R, - RT5616_PWR_HV_L | RT5616_PWR_HV_R); + RT5616_PWR_HV_L | RT5616_PWR_HV_R, + RT5616_PWR_HV_L | RT5616_PWR_HV_R); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_HP_L | RT5616_PWR_HP_R | - RT5616_PWR_HA, RT5616_PWR_HP_L | - RT5616_PWR_HP_R | RT5616_PWR_HA); + RT5616_PWR_HP_L | RT5616_PWR_HP_R | + RT5616_PWR_HA, RT5616_PWR_HP_L | + RT5616_PWR_HP_R | RT5616_PWR_HA); msleep(50); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_FV1 | RT5616_PWR_FV2, - RT5616_PWR_FV1 | RT5616_PWR_FV2); + RT5616_PWR_FV1 | RT5616_PWR_FV2, + RT5616_PWR_FV1 | RT5616_PWR_FV2); snd_soc_update_bits(codec, RT5616_CHARGE_PUMP, - RT5616_PM_HP_MASK, RT5616_PM_HP_HV); + RT5616_PM_HP_MASK, RT5616_PM_HP_HV); snd_soc_update_bits(codec, RT5616_PR_BASE + - RT5616_CHOP_DAC_ADC, 0x0200, 0x0200); + RT5616_CHOP_DAC_ADC, 0x0200, 0x0200); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_HP_CO_MASK | RT5616_HP_SG_MASK, - RT5616_HP_CO_EN | RT5616_HP_SG_EN); + RT5616_HP_CO_MASK | RT5616_HP_SG_MASK, + RT5616_HP_CO_EN | RT5616_HP_SG_EN); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, RT5616_PR_BASE + - RT5616_CHOP_DAC_ADC, 0x0200, 0x0); + RT5616_CHOP_DAC_ADC, 0x0200, 0x0); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK | - RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS | - RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS); + RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK | + RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS | + RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS); /* headphone amp power down */ snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_SMT_TRIG_MASK | RT5616_HP_CD_PD_MASK | - RT5616_HP_CO_MASK | RT5616_HP_CP_MASK | - RT5616_HP_SG_MASK | RT5616_HP_CB_MASK, - RT5616_SMT_TRIG_DIS | RT5616_HP_CD_PD_EN | - RT5616_HP_CO_DIS | RT5616_HP_CP_PD | - RT5616_HP_SG_EN | RT5616_HP_CB_PD); + RT5616_SMT_TRIG_MASK | + RT5616_HP_CD_PD_MASK | RT5616_HP_CO_MASK | + RT5616_HP_CP_MASK | RT5616_HP_SG_MASK | + RT5616_HP_CB_MASK, + RT5616_SMT_TRIG_DIS | RT5616_HP_CD_PD_EN | + RT5616_HP_CO_DIS | RT5616_HP_CP_PD | + RT5616_HP_SG_EN | RT5616_HP_CB_PD); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_HP_L | RT5616_PWR_HP_R | - RT5616_PWR_HA, 0); + RT5616_PWR_HP_L | RT5616_PWR_HP_R | + RT5616_PWR_HA, 0); break; default: return 0; @@ -551,7 +551,7 @@ static int rt5616_charge_pump_event(struct snd_soc_dapm_widget *w, } static int rt5616_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); @@ -559,57 +559,57 @@ static int rt5616_hp_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: /* headphone unmute sequence */ snd_soc_update_bits(codec, RT5616_DEPOP_M3, - RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK | - RT5616_CP_FQ3_MASK, - (RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ1_SFT) | - (RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT) | - (RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ3_SFT)); + RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK | + RT5616_CP_FQ3_MASK, + RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ1_SFT | + RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT | + RT5616_CP_FQ_192_KHZ << RT5616_CP_FQ3_SFT); snd_soc_write(codec, RT5616_PR_BASE + - RT5616_MAMP_INT_REG2, 0xfc00); + RT5616_MAMP_INT_REG2, 0xfc00); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_SMT_TRIG_MASK, RT5616_SMT_TRIG_EN); + RT5616_SMT_TRIG_MASK, RT5616_SMT_TRIG_EN); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_RSTN_MASK, RT5616_RSTN_EN); + RT5616_RSTN_MASK, RT5616_RSTN_EN); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_RSTN_MASK | RT5616_HP_L_SMT_MASK | - RT5616_HP_R_SMT_MASK, RT5616_RSTN_DIS | - RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN); + RT5616_RSTN_MASK | RT5616_HP_L_SMT_MASK | + RT5616_HP_R_SMT_MASK, RT5616_RSTN_DIS | + RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN); snd_soc_update_bits(codec, RT5616_HP_VOL, - RT5616_L_MUTE | RT5616_R_MUTE, 0); + RT5616_L_MUTE | RT5616_R_MUTE, 0); msleep(100); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK | - RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS | - RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS); + RT5616_HP_SG_MASK | RT5616_HP_L_SMT_MASK | + RT5616_HP_R_SMT_MASK, RT5616_HP_SG_DIS | + RT5616_HP_L_SMT_DIS | RT5616_HP_R_SMT_DIS); msleep(20); snd_soc_update_bits(codec, RT5616_HP_CALIB_AMP_DET, - RT5616_HPD_PS_MASK, RT5616_HPD_PS_EN); + RT5616_HPD_PS_MASK, RT5616_HPD_PS_EN); break; case SND_SOC_DAPM_PRE_PMD: /* headphone mute sequence */ snd_soc_update_bits(codec, RT5616_DEPOP_M3, - RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK | - RT5616_CP_FQ3_MASK, - (RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ1_SFT) | - (RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT) | - (RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ3_SFT)); + RT5616_CP_FQ1_MASK | RT5616_CP_FQ2_MASK | + RT5616_CP_FQ3_MASK, + RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ1_SFT | + RT5616_CP_FQ_12_KHZ << RT5616_CP_FQ2_SFT | + RT5616_CP_FQ_96_KHZ << RT5616_CP_FQ3_SFT); snd_soc_write(codec, RT5616_PR_BASE + - RT5616_MAMP_INT_REG2, 0xfc00); + RT5616_MAMP_INT_REG2, 0xfc00); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_HP_SG_MASK, RT5616_HP_SG_EN); + RT5616_HP_SG_MASK, RT5616_HP_SG_EN); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_RSTP_MASK, RT5616_RSTP_EN); + RT5616_RSTP_MASK, RT5616_RSTP_EN); snd_soc_update_bits(codec, RT5616_DEPOP_M1, - RT5616_RSTP_MASK | RT5616_HP_L_SMT_MASK | - RT5616_HP_R_SMT_MASK, RT5616_RSTP_DIS | - RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN); + RT5616_RSTP_MASK | RT5616_HP_L_SMT_MASK | + RT5616_HP_R_SMT_MASK, RT5616_RSTP_DIS | + RT5616_HP_L_SMT_EN | RT5616_HP_R_SMT_EN); snd_soc_update_bits(codec, RT5616_HP_CALIB_AMP_DET, - RT5616_HPD_PS_MASK, RT5616_HPD_PS_DIS); + RT5616_HPD_PS_MASK, RT5616_HPD_PS_DIS); msleep(90); snd_soc_update_bits(codec, RT5616_HP_VOL, - RT5616_L_MUTE | RT5616_R_MUTE, - RT5616_L_MUTE | RT5616_R_MUTE); + RT5616_L_MUTE | RT5616_R_MUTE, + RT5616_L_MUTE | RT5616_R_MUTE); msleep(30); break; @@ -621,24 +621,24 @@ static int rt5616_hp_event(struct snd_soc_dapm_widget *w, } static int rt5616_lout_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_LM, RT5616_PWR_LM); + RT5616_PWR_LM, RT5616_PWR_LM); snd_soc_update_bits(codec, RT5616_LOUT_CTRL1, - RT5616_L_MUTE | RT5616_R_MUTE, 0); + RT5616_L_MUTE | RT5616_R_MUTE, 0); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, RT5616_LOUT_CTRL1, - RT5616_L_MUTE | RT5616_R_MUTE, - RT5616_L_MUTE | RT5616_R_MUTE); + RT5616_L_MUTE | RT5616_R_MUTE, + RT5616_L_MUTE | RT5616_R_MUTE); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_LM, 0); + RT5616_PWR_LM, 0); break; default: @@ -649,19 +649,19 @@ static int rt5616_lout_event(struct snd_soc_dapm_widget *w, } static int rt5616_bst1_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, RT5616_PWR_ANLG2, - RT5616_PWR_BST1_OP2, RT5616_PWR_BST1_OP2); + RT5616_PWR_BST1_OP2, RT5616_PWR_BST1_OP2); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, RT5616_PWR_ANLG2, - RT5616_PWR_BST1_OP2, 0); + RT5616_PWR_BST1_OP2, 0); break; default: @@ -672,19 +672,19 @@ static int rt5616_bst1_event(struct snd_soc_dapm_widget *w, } static int rt5616_bst2_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); switch (event) { case SND_SOC_DAPM_POST_PMU: snd_soc_update_bits(codec, RT5616_PWR_ANLG2, - RT5616_PWR_BST2_OP2, RT5616_PWR_BST2_OP2); + RT5616_PWR_BST2_OP2, RT5616_PWR_BST2_OP2); break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, RT5616_PWR_ANLG2, - RT5616_PWR_BST2_OP2, 0); + RT5616_PWR_BST2_OP2, 0); break; default: @@ -696,13 +696,13 @@ static int rt5616_bst2_event(struct snd_soc_dapm_widget *w, static const struct snd_soc_dapm_widget rt5616_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("PLL1", RT5616_PWR_ANLG2, - RT5616_PWR_PLL_BIT, 0, NULL, 0), + RT5616_PWR_PLL_BIT, 0, NULL, 0), /* Input Side */ /* micbias */ SND_SOC_DAPM_SUPPLY("LDO", RT5616_PWR_ANLG1, - RT5616_PWR_LDO_BIT, 0, NULL, 0), + RT5616_PWR_LDO_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("micbias1", RT5616_PWR_ANLG2, - RT5616_PWR_MB1_BIT, 0, NULL, 0), + RT5616_PWR_MB1_BIT, 0, NULL, 0), /* Input Lines */ SND_SOC_DAPM_INPUT("MIC1"), @@ -714,45 +714,47 @@ static const struct snd_soc_dapm_widget rt5616_dapm_widgets[] = { /* Boost */ SND_SOC_DAPM_PGA_E("BST1", RT5616_PWR_ANLG2, - RT5616_PWR_BST1_BIT, 0, NULL, 0, rt5616_bst1_event, - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + RT5616_PWR_BST1_BIT, 0, NULL, 0, rt5616_bst1_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_E("BST2", RT5616_PWR_ANLG2, - RT5616_PWR_BST2_BIT, 0, NULL, 0, rt5616_bst2_event, - SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + RT5616_PWR_BST2_BIT, 0, NULL, 0, rt5616_bst2_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), /* Input Volume */ SND_SOC_DAPM_PGA("INL1 VOL", RT5616_PWR_VOL, - RT5616_PWR_IN1_L_BIT, 0, NULL, 0), + RT5616_PWR_IN1_L_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("INR1 VOL", RT5616_PWR_VOL, - RT5616_PWR_IN1_R_BIT, 0, NULL, 0), + RT5616_PWR_IN1_R_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("INL2 VOL", RT5616_PWR_VOL, - RT5616_PWR_IN2_L_BIT, 0, NULL, 0), + RT5616_PWR_IN2_L_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("INR2 VOL", RT5616_PWR_VOL, - RT5616_PWR_IN2_R_BIT, 0, NULL, 0), + RT5616_PWR_IN2_R_BIT, 0, NULL, 0), /* REC Mixer */ SND_SOC_DAPM_MIXER("RECMIXL", RT5616_PWR_MIXER, RT5616_PWR_RM_L_BIT, 0, - rt5616_rec_l_mix, ARRAY_SIZE(rt5616_rec_l_mix)), + rt5616_rec_l_mix, ARRAY_SIZE(rt5616_rec_l_mix)), SND_SOC_DAPM_MIXER("RECMIXR", RT5616_PWR_MIXER, RT5616_PWR_RM_R_BIT, 0, - rt5616_rec_r_mix, ARRAY_SIZE(rt5616_rec_r_mix)), + rt5616_rec_r_mix, ARRAY_SIZE(rt5616_rec_r_mix)), /* ADCs */ SND_SOC_DAPM_ADC_E("ADC L", NULL, RT5616_PWR_DIG1, - RT5616_PWR_ADC_L_BIT, 0, rt5616_adc_event, - SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + RT5616_PWR_ADC_L_BIT, 0, rt5616_adc_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_ADC_E("ADC R", NULL, RT5616_PWR_DIG1, - RT5616_PWR_ADC_R_BIT, 0, rt5616_adc_event, - SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), + RT5616_PWR_ADC_R_BIT, 0, rt5616_adc_event, + SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU), /* ADC Mixer */ SND_SOC_DAPM_SUPPLY("stereo1 filter", RT5616_PWR_DIG2, - RT5616_PWR_ADC_STO1_F_BIT, 0, NULL, 0), + RT5616_PWR_ADC_STO1_F_BIT, 0, NULL, 0), SND_SOC_DAPM_MIXER("Stereo1 ADC MIXL", SND_SOC_NOPM, 0, 0, - rt5616_sto1_adc_l_mix, ARRAY_SIZE(rt5616_sto1_adc_l_mix)), + rt5616_sto1_adc_l_mix, + ARRAY_SIZE(rt5616_sto1_adc_l_mix)), SND_SOC_DAPM_MIXER("Stereo1 ADC MIXR", SND_SOC_NOPM, 0, 0, - rt5616_sto1_adc_r_mix, ARRAY_SIZE(rt5616_sto1_adc_r_mix)), + rt5616_sto1_adc_r_mix, + ARRAY_SIZE(rt5616_sto1_adc_r_mix)), /* Digital Interface */ SND_SOC_DAPM_SUPPLY("I2S1", RT5616_PWR_DIG1, - RT5616_PWR_I2S1_BIT, 0, NULL, 0), + RT5616_PWR_I2S1_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0), @@ -770,68 +772,70 @@ static const struct snd_soc_dapm_widget rt5616_dapm_widgets[] = { /* Output Side */ /* DAC mixer before sound effect */ SND_SOC_DAPM_MIXER("DAC MIXL", SND_SOC_NOPM, 0, 0, - rt5616_dac_l_mix, ARRAY_SIZE(rt5616_dac_l_mix)), + rt5616_dac_l_mix, ARRAY_SIZE(rt5616_dac_l_mix)), SND_SOC_DAPM_MIXER("DAC MIXR", SND_SOC_NOPM, 0, 0, - rt5616_dac_r_mix, ARRAY_SIZE(rt5616_dac_r_mix)), + rt5616_dac_r_mix, ARRAY_SIZE(rt5616_dac_r_mix)), SND_SOC_DAPM_SUPPLY("Stero1 DAC Power", RT5616_PWR_DIG2, - RT5616_PWR_DAC_STO1_F_BIT, 0, NULL, 0), + RT5616_PWR_DAC_STO1_F_BIT, 0, NULL, 0), /* DAC Mixer */ SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0, - rt5616_sto_dac_l_mix, ARRAY_SIZE(rt5616_sto_dac_l_mix)), + rt5616_sto_dac_l_mix, + ARRAY_SIZE(rt5616_sto_dac_l_mix)), SND_SOC_DAPM_MIXER("Stereo DAC MIXR", SND_SOC_NOPM, 0, 0, - rt5616_sto_dac_r_mix, ARRAY_SIZE(rt5616_sto_dac_r_mix)), + rt5616_sto_dac_r_mix, + ARRAY_SIZE(rt5616_sto_dac_r_mix)), /* DACs */ SND_SOC_DAPM_DAC("DAC L1", NULL, RT5616_PWR_DIG1, - RT5616_PWR_DAC_L1_BIT, 0), + RT5616_PWR_DAC_L1_BIT, 0), SND_SOC_DAPM_DAC("DAC R1", NULL, RT5616_PWR_DIG1, - RT5616_PWR_DAC_R1_BIT, 0), + RT5616_PWR_DAC_R1_BIT, 0), /* OUT Mixer */ SND_SOC_DAPM_MIXER("OUT MIXL", RT5616_PWR_MIXER, RT5616_PWR_OM_L_BIT, - 0, rt5616_out_l_mix, ARRAY_SIZE(rt5616_out_l_mix)), + 0, rt5616_out_l_mix, ARRAY_SIZE(rt5616_out_l_mix)), SND_SOC_DAPM_MIXER("OUT MIXR", RT5616_PWR_MIXER, RT5616_PWR_OM_R_BIT, - 0, rt5616_out_r_mix, ARRAY_SIZE(rt5616_out_r_mix)), + 0, rt5616_out_r_mix, ARRAY_SIZE(rt5616_out_r_mix)), /* Output Volume */ SND_SOC_DAPM_PGA("OUTVOL L", RT5616_PWR_VOL, - RT5616_PWR_OV_L_BIT, 0, NULL, 0), + RT5616_PWR_OV_L_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("OUTVOL R", RT5616_PWR_VOL, - RT5616_PWR_OV_R_BIT, 0, NULL, 0), + RT5616_PWR_OV_R_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("HPOVOL L", RT5616_PWR_VOL, - RT5616_PWR_HV_L_BIT, 0, NULL, 0), + RT5616_PWR_HV_L_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("HPOVOL R", RT5616_PWR_VOL, - RT5616_PWR_HV_R_BIT, 0, NULL, 0), + RT5616_PWR_HV_R_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("DAC 1", SND_SOC_NOPM, - 0, 0, NULL, 0), + 0, 0, NULL, 0), SND_SOC_DAPM_PGA("DAC 2", SND_SOC_NOPM, - 0, 0, NULL, 0), + 0, 0, NULL, 0), SND_SOC_DAPM_PGA("HPOVOL", SND_SOC_NOPM, - 0, 0, NULL, 0), + 0, 0, NULL, 0), SND_SOC_DAPM_PGA("INL1", RT5616_PWR_VOL, - RT5616_PWR_IN1_L_BIT, 0, NULL, 0), + RT5616_PWR_IN1_L_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("INR1", RT5616_PWR_VOL, - RT5616_PWR_IN1_R_BIT, 0, NULL, 0), + RT5616_PWR_IN1_R_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("INL2", RT5616_PWR_VOL, - RT5616_PWR_IN2_L_BIT, 0, NULL, 0), + RT5616_PWR_IN2_L_BIT, 0, NULL, 0), SND_SOC_DAPM_PGA("INR2", RT5616_PWR_VOL, - RT5616_PWR_IN2_R_BIT, 0, NULL, 0), + RT5616_PWR_IN2_R_BIT, 0, NULL, 0), /* HPO/LOUT/Mono Mixer */ SND_SOC_DAPM_MIXER("HPO MIX", SND_SOC_NOPM, 0, 0, - rt5616_hpo_mix, ARRAY_SIZE(rt5616_hpo_mix)), + rt5616_hpo_mix, ARRAY_SIZE(rt5616_hpo_mix)), SND_SOC_DAPM_MIXER("LOUT MIX", SND_SOC_NOPM, 0, 0, - rt5616_lout_mix, ARRAY_SIZE(rt5616_lout_mix)), + rt5616_lout_mix, ARRAY_SIZE(rt5616_lout_mix)), SND_SOC_DAPM_PGA_S("HP amp", 1, SND_SOC_NOPM, 0, 0, - rt5616_hp_event, SND_SOC_DAPM_PRE_PMD | - SND_SOC_DAPM_POST_PMU), + rt5616_hp_event, SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_PGA_S("LOUT amp", 1, SND_SOC_NOPM, 0, 0, - rt5616_lout_event, SND_SOC_DAPM_PRE_PMD | - SND_SOC_DAPM_POST_PMU), + rt5616_lout_event, SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_SUPPLY_S("Charge Pump", 1, SND_SOC_NOPM, 0, 0, - rt5616_charge_pump_event, SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD), + rt5616_charge_pump_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), /* Output Lines */ SND_SOC_DAPM_OUTPUT("HPOL"), @@ -950,7 +954,8 @@ static const struct snd_soc_dapm_route rt5616_dapm_routes[] = { }; static int rt5616_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_codec *codec = rtd->codec; @@ -977,7 +982,7 @@ static int rt5616_hw_params(struct snd_pcm_substream *substream, dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", rt5616->bclk[dai->id], rt5616->lrck[dai->id]); dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", - bclk_ms, pre_div, dai->id); + bclk_ms, pre_div, dai->id); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: @@ -998,10 +1003,9 @@ static int rt5616_hw_params(struct snd_pcm_substream *substream, mask_clk = RT5616_I2S_PD1_MASK; val_clk = pre_div << RT5616_I2S_PD1_SFT; snd_soc_update_bits(codec, RT5616_I2S1_SDP, - RT5616_I2S_DL_MASK, val_len); + RT5616_I2S_DL_MASK, val_len); snd_soc_update_bits(codec, RT5616_ADDA_CLK1, mask_clk, val_clk); - return 0; } @@ -1050,15 +1054,14 @@ static int rt5616_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) } snd_soc_update_bits(codec, RT5616_I2S1_SDP, - RT5616_I2S_MS_MASK | RT5616_I2S_BP_MASK | - RT5616_I2S_DF_MASK, reg_val); - + RT5616_I2S_MS_MASK | RT5616_I2S_BP_MASK | + RT5616_I2S_DF_MASK, reg_val); return 0; } static int rt5616_set_dai_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) + int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = dai->codec; struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); @@ -1078,8 +1081,9 @@ static int rt5616_set_dai_sysclk(struct snd_soc_dai *dai, dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); return -EINVAL; } + snd_soc_update_bits(codec, RT5616_GLB_CLK, - RT5616_SCLK_SRC_MASK, reg_val); + RT5616_SCLK_SRC_MASK, reg_val); rt5616->sysclk = freq; rt5616->sysclk_src = clk_id; @@ -1089,7 +1093,7 @@ static int rt5616_set_dai_sysclk(struct snd_soc_dai *dai, } static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, - unsigned int freq_in, unsigned int freq_out) + unsigned int freq_in, unsigned int freq_out) { struct snd_soc_codec *codec = dai->codec; struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); @@ -1106,19 +1110,22 @@ static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, rt5616->pll_in = 0; rt5616->pll_out = 0; snd_soc_update_bits(codec, RT5616_GLB_CLK, - RT5616_SCLK_SRC_MASK, RT5616_SCLK_SRC_MCLK); + RT5616_SCLK_SRC_MASK, + RT5616_SCLK_SRC_MCLK); return 0; } switch (source) { case RT5616_PLL1_S_MCLK: snd_soc_update_bits(codec, RT5616_GLB_CLK, - RT5616_PLL1_SRC_MASK, RT5616_PLL1_SRC_MCLK); + RT5616_PLL1_SRC_MASK, + RT5616_PLL1_SRC_MCLK); break; case RT5616_PLL1_S_BCLK1: case RT5616_PLL1_S_BCLK2: snd_soc_update_bits(codec, RT5616_GLB_CLK, - RT5616_PLL1_SRC_MASK, RT5616_PLL1_SRC_BCLK1); + RT5616_PLL1_SRC_MASK, + RT5616_PLL1_SRC_BCLK1); break; default: dev_err(codec->dev, "Unknown PLL source %d\n", source); @@ -1136,10 +1143,11 @@ static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, pll_code.n_code, pll_code.k_code); snd_soc_write(codec, RT5616_PLL_CTRL1, - pll_code.n_code << RT5616_PLL_N_SFT | pll_code.k_code); + pll_code.n_code << RT5616_PLL_N_SFT | pll_code.k_code); snd_soc_write(codec, RT5616_PLL_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5616_PLL_M_SFT | - pll_code.m_bp << RT5616_PLL_M_BP_SFT); + (pll_code.m_bp ? 0 : pll_code.m_code) << + RT5616_PLL_M_SFT | + pll_code.m_bp << RT5616_PLL_M_BP_SFT); rt5616->pll_in = freq_in; rt5616->pll_out = freq_out; @@ -1149,22 +1157,23 @@ static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, } static int rt5616_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) + enum snd_soc_bias_level level) { switch (level) { case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_VREF1 | RT5616_PWR_MB | - RT5616_PWR_BG | RT5616_PWR_VREF2, - RT5616_PWR_VREF1 | RT5616_PWR_MB | - RT5616_PWR_BG | RT5616_PWR_VREF2); + RT5616_PWR_VREF1 | RT5616_PWR_MB | + RT5616_PWR_BG | RT5616_PWR_VREF2, + RT5616_PWR_VREF1 | RT5616_PWR_MB | + RT5616_PWR_BG | RT5616_PWR_VREF2); mdelay(10); snd_soc_update_bits(codec, RT5616_PWR_ANLG1, - RT5616_PWR_FV1 | RT5616_PWR_FV2, - RT5616_PWR_FV1 | RT5616_PWR_FV2); + RT5616_PWR_FV1 | RT5616_PWR_FV2, + RT5616_PWR_FV1 | RT5616_PWR_FV2); snd_soc_update_bits(codec, RT5616_D_MISC, - RT5616_D_GATE_EN, RT5616_D_GATE_EN); + RT5616_D_GATE_EN, + RT5616_D_GATE_EN); } break; @@ -1222,7 +1231,6 @@ static int rt5616_resume(struct snd_soc_codec *codec) #define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) - struct snd_soc_dai_ops rt5616_aif_dai_ops = { .hw_params = rt5616_hw_params, .set_fmt = rt5616_set_dai_fmt, @@ -1296,15 +1304,15 @@ MODULE_DEVICE_TABLE(of, rt5616_of_match); #endif static int rt5616_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) + const struct i2c_device_id *id) { struct rt5616_priv *rt5616; unsigned int val; int ret; rt5616 = devm_kzalloc(&i2c->dev, sizeof(struct rt5616_priv), - GFP_KERNEL); - if (rt5616 == NULL) + GFP_KERNEL); + if (!rt5616) return -ENOMEM; i2c_set_clientdata(i2c, rt5616); @@ -1326,14 +1334,14 @@ static int rt5616_i2c_probe(struct i2c_client *i2c, } regmap_write(rt5616->regmap, RT5616_RESET, 0); regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1, - RT5616_PWR_VREF1 | RT5616_PWR_MB | - RT5616_PWR_BG | RT5616_PWR_VREF2, - RT5616_PWR_VREF1 | RT5616_PWR_MB | - RT5616_PWR_BG | RT5616_PWR_VREF2); + RT5616_PWR_VREF1 | RT5616_PWR_MB | + RT5616_PWR_BG | RT5616_PWR_VREF2, + RT5616_PWR_VREF1 | RT5616_PWR_MB | + RT5616_PWR_BG | RT5616_PWR_VREF2); mdelay(10); regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1, - RT5616_PWR_FV1 | RT5616_PWR_FV2, - RT5616_PWR_FV1 | RT5616_PWR_FV2); + RT5616_PWR_FV1 | RT5616_PWR_FV2, + RT5616_PWR_FV1 | RT5616_PWR_FV2); ret = regmap_register_patch(rt5616->regmap, init_list, ARRAY_SIZE(init_list)); @@ -1341,11 +1349,10 @@ static int rt5616_i2c_probe(struct i2c_client *i2c, dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); regmap_update_bits(rt5616->regmap, RT5616_PWR_ANLG1, - RT5616_PWR_LDO_DVO_MASK, RT5616_PWR_LDO_DVO_1_2V); + RT5616_PWR_LDO_DVO_MASK, RT5616_PWR_LDO_DVO_1_2V); return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5616, - rt5616_dai, ARRAY_SIZE(rt5616_dai)); - + rt5616_dai, ARRAY_SIZE(rt5616_dai)); } static int rt5616_i2c_remove(struct i2c_client *i2c) @@ -1361,7 +1368,6 @@ static void rt5616_i2c_shutdown(struct i2c_client *client) regmap_write(rt5616->regmap, RT5616_HP_VOL, 0xc8c8); regmap_write(rt5616->regmap, RT5616_LOUT_CTRL1, 0xc8c8); - } static struct i2c_driver rt5616_i2c_driver = { -- cgit From 76d3204eaa9364a662f0fe0f075dfe61e6bd14fe Mon Sep 17 00:00:00 2001 From: Caesar Wang Date: Thu, 28 Jan 2016 16:43:37 +0800 Subject: ASoC: rt5616: add the mclk for the codec driver This patch adds the code to enable the clock to the CODEC driver if it needs the clock enabled. In some case, We need to claim the clock which is driving the codec so that when we enable clock gating, we continue to clock the codec when needed. if mclk provided, to enable and disable the clock source. Signed-off-by: Caesar Wang Signed-off-by: Mark Brown --- sound/soc/codecs/rt5616.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index d4bdf9f6f0af..fdca63694b40 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -144,6 +145,7 @@ struct rt5616_priv { struct snd_soc_codec *codec; struct delayed_work patch_work; struct regmap *regmap; + struct clk *mclk; int sysclk; int sysclk_src; @@ -1159,7 +1161,34 @@ static int rt5616_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, static int rt5616_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { + + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* + * SND_SOC_BIAS_PREPARE is called while preparing for a + * transition to ON or away from ON. If current bias_level + * is SND_SOC_BIAS_ON, then it is preparing for a transition + * away from ON. Disable the clock in that case, otherwise + * enable it. + */ + if (IS_ERR(rt5616->mclk)) + break; + + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_ON) { + clk_disable_unprepare(rt5616->mclk); + } else { + ret = clk_prepare_enable(rt5616->mclk); + if (ret) + return ret; + } + break; + case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { snd_soc_update_bits(codec, RT5616_PWR_ANLG1, @@ -1198,6 +1227,11 @@ static int rt5616_probe(struct snd_soc_codec *codec) { struct rt5616_priv *rt5616 = snd_soc_codec_get_drvdata(codec); + /* Check if MCLK provided */ + rt5616->mclk = devm_clk_get(codec->dev, "mclk"); + if (PTR_ERR(rt5616->mclk) == -EPROBE_DEFER) + return -EPROBE_DEFER; + rt5616->codec = codec; return 0; -- cgit From 76c4aaec41b76afb7f914aaf6080f21ab331b0c6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 28 Jan 2016 16:13:24 -0300 Subject: perf build: Fix feature-dump checks, we need to test all features I see problem with test-all case speedup, because it does not comprise checks for 32bits compilations, fix it. The problem could be noticed by calling: make -C tools/perf feature-dump That would end up misdetecting the feature-compile-x32, that, building using 'gcc -mx32' needs stub headers not present in a fedora 23 devel machine and thus fail to compile, but ended up appearing as detected, i.e. present in tools/perf/FEATURE-DUMP as 'feature-compile-x32=1'. With this fix it correctly appears as 'feature-compile-x32=0' and if we uninstall the libc devel files for 32 bits (glibc-devel.i686), then the relevant variable is flipped from 'feature-compile-32=1' to 'feature-compile-32=0'. The same things happened for bionic and libbabeltrace, that were misdetected because the are no tested in test-all.c Reported-and-Tested-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-u0sjaddf1r9m8icpd98ry7fz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/build/Makefile.feature | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 674c47d5f9d1..7bff2ea831cf 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -119,6 +119,14 @@ ifeq ($(feature-all), 1) # test-all.c passed - just set all the core feature flags to 1: # $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) + # + # test-all.c does not comprise these tests, so we need to + # for this case to get features proper values + # + $(call feature_check,compile-32) + $(call feature_check,compile-x32) + $(call feature_check,bionic) + $(call feature_check,libbabeltrace) else $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) endif -- cgit From 3f6b3ce071d3a3632c82b53077d21f5beab3a4aa Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:31 -0800 Subject: serial: 8250: Refactor serial8250_rx_chars() inner loop Factor the read/process one char inner loop to a separate helper function serial8250_read_char(). No functional change. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 120 +++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 58 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 8d262bce97e4..7580d713cde5 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1412,6 +1412,67 @@ static void serial8250_enable_ms(struct uart_port *port) serial8250_rpm_put(up); } +static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) +{ + struct uart_port *port = &up->port; + unsigned char ch; + char flag = TTY_NORMAL; + + if (likely(lsr & UART_LSR_DR)) + ch = serial_in(up, UART_RX); + else + /* + * Intel 82571 has a Serial Over Lan device that will + * set UART_LSR_BI without setting UART_LSR_DR when + * it receives a break. To avoid reading from the + * receive buffer without UART_LSR_DR bit set, we + * just force the read character to be 0 + */ + ch = 0; + + port->icount.rx++; + + lsr |= up->lsr_saved_flags; + up->lsr_saved_flags = 0; + + if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); + port->icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(port)) + return; + } else if (lsr & UART_LSR_PE) + port->icount.parity++; + else if (lsr & UART_LSR_FE) + port->icount.frame++; + if (lsr & UART_LSR_OE) + port->icount.overrun++; + + /* + * Mask off conditions which should be ignored. + */ + lsr &= port->read_status_mask; + + if (lsr & UART_LSR_BI) { + DEBUG_INTR("handling break...."); + flag = TTY_BREAK; + } else if (lsr & UART_LSR_PE) + flag = TTY_PARITY; + else if (lsr & UART_LSR_FE) + flag = TTY_FRAME; + } + if (uart_handle_sysrq_char(port, ch)) + return; + + uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); +} + /* * serial8250_rx_chars: processes according to the passed in LSR * value, and returns the remaining LSR bits not handled @@ -1421,67 +1482,10 @@ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { struct uart_port *port = &up->port; - unsigned char ch; int max_count = 256; - char flag; do { - if (likely(lsr & UART_LSR_DR)) - ch = serial_in(up, UART_RX); - else - /* - * Intel 82571 has a Serial Over Lan device that will - * set UART_LSR_BI without setting UART_LSR_DR when - * it receives a break. To avoid reading from the - * receive buffer without UART_LSR_DR bit set, we - * just force the read character to be 0 - */ - ch = 0; - - flag = TTY_NORMAL; - port->icount.rx++; - - lsr |= up->lsr_saved_flags; - up->lsr_saved_flags = 0; - - if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { - if (lsr & UART_LSR_BI) { - lsr &= ~(UART_LSR_FE | UART_LSR_PE); - port->icount.brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ - if (uart_handle_break(port)) - goto ignore_char; - } else if (lsr & UART_LSR_PE) - port->icount.parity++; - else if (lsr & UART_LSR_FE) - port->icount.frame++; - if (lsr & UART_LSR_OE) - port->icount.overrun++; - - /* - * Mask off conditions which should be ignored. - */ - lsr &= port->read_status_mask; - - if (lsr & UART_LSR_BI) { - DEBUG_INTR("handling break...."); - flag = TTY_BREAK; - } else if (lsr & UART_LSR_PE) - flag = TTY_PARITY; - else if (lsr & UART_LSR_FE) - flag = TTY_FRAME; - } - if (uart_handle_sysrq_char(port, ch)) - goto ignore_char; - - uart_insert_char(port, lsr, UART_LSR_OE, ch, flag); - -ignore_char: + serial8250_read_char(up, lsr); lsr = serial_in(up, UART_LSR); } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0)); spin_unlock(&port->lock); -- cgit From d22f8f10683c8c0f2675d9fd411a06facaf07c1b Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:32 -0800 Subject: serial: 8250: Fix lost rx state When max_count is reached, the rx loop exits. However, UART_LSR has already been read so those char flags are lost, and subsequent rx status will be for the wrong byte until the rx fifo drains. Reported-by: George Spelvin Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 7580d713cde5..48680565c991 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1478,16 +1478,17 @@ static void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr) * value, and returns the remaining LSR bits not handled * by this Rx routine. */ -unsigned char -serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) +unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) { struct uart_port *port = &up->port; int max_count = 256; do { serial8250_read_char(up, lsr); + if (--max_count == 0) + break; lsr = serial_in(up, UART_LSR); - } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0)); + } while (lsr & (UART_LSR_DR | UART_LSR_BI)); spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); spin_lock(&port->lock); -- cgit From 6a597a38cbaf067019db96645f36e0b1f01f306a Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:33 -0800 Subject: serial: 8250: Remove low_latency workaround The defunct low_latency input steering executed flush_to_ldisc() directly from interrupt context so dropping the port lock was necessary to avoid deadlock. That steering was removed by commit a9c3f68f3cd8d55f809fbdb0c138ed061ea1bd25 Author: Peter Hurley Date: Sat Feb 22 07:31:21 2014 -0500 tty: Fix low_latency BUG Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 48680565c991..9ef77a52c4f2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1489,9 +1489,8 @@ unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) break; lsr = serial_in(up, UART_LSR); } while (lsr & (UART_LSR_DR | UART_LSR_BI)); - spin_unlock(&port->lock); + tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); return lsr; } EXPORT_SYMBOL_GPL(serial8250_rx_chars); -- cgit From d70a7b1626d64c8c57fb9258a81f427198b60700 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:34 -0800 Subject: serial: 8250: Unlink uart console ptr if console setup fails If console setup fails (eg., there is no valid port at that index), unlink the console ptr; otherwise, when the driver unloads, the console will be unregistered (even though setup, and thus registration, failed) and a console disabled message will be printed. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index c9720a97a977..8031e428894f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -597,6 +597,7 @@ static void univ8250_console_write(struct console *co, const char *s, static int univ8250_console_setup(struct console *co, char *options) { struct uart_port *port; + int retval; /* * Check whether an invalid uart number has been specified, and @@ -609,7 +610,10 @@ static int univ8250_console_setup(struct console *co, char *options) /* link port to console */ port->cons = co; - return serial8250_console_setup(port, options, false); + retval = serial8250_console_setup(port, options, false); + if (retval != 0) + port->cons = NULL; + return retval; } /** -- cgit From 611e0d83a83724340d4bf0eed610af01401b2ff4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:35 -0800 Subject: serial: 8250: Wait for irq to complete before shutdown After masking all interrupts, wait for the irq handler to complete before continuing shutdown. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 9ef77a52c4f2..57b3a80b4359 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2088,8 +2088,12 @@ void serial8250_do_shutdown(struct uart_port *port) /* * Disable interrupts from this port */ + spin_lock_irqsave(&port->lock, flags); up->ier = 0; serial_port_out(port, UART_IER, 0); + spin_unlock_irqrestore(&port->lock, flags); + + synchronize_irq(port->irq); if (up->dma) serial8250_release_dma(up); -- cgit From cee10c8cd3fde3da428ffafd4eb8847892a34d52 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:39:36 -0800 Subject: serial: 8250: Unfold < 80 char lines Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 57b3a80b4359..0bd3c6baa300 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1523,11 +1523,9 @@ void serial8250_tx_chars(struct uart_8250_port *up) port->icount.tx++; if (uart_circ_empty(xmit)) break; - if (up->capabilities & UART_CAP_HFIFO) { - if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != - BOTH_EMPTY) - break; - } + if ((up->capabilities & UART_CAP_HFIFO) && + (serial_in(up, UART_LSR) & BOTH_EMPTY) != BOTH_EMPTY) + break; } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -2753,8 +2751,7 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) return 0; } -static const char * -serial8250_type(struct uart_port *port) +static const char *serial8250_type(struct uart_port *port) { int type = port->type; -- cgit From c9c10d912a91735a966d81114b28c4cff81dda59 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:08 -0800 Subject: tty: rocket: Remove private close_wait This driver's private completion variable, close_wait, is no longer used for wait since "tty: Remove ASYNC_CLOSING checks in open()/hangup"; remove. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/rocket.c | 2 -- drivers/tty/rocket_int.h | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index f624b93a237f..9dd02daf45ca 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -643,7 +643,6 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) info->chan = chan; tty_port_init(&info->port); info->port.ops = &rocket_port_ops; - init_completion(&info->close_wait); info->flags &= ~ROCKET_MODE_MASK; switch (pc104[board][line]) { case 422: @@ -1049,7 +1048,6 @@ static void rp_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&port->mutex); tty_port_tty_set(port, NULL); - complete_all(&info->close_wait); atomic_dec(&rp_num_ports_open); #ifdef ROCKET_DEBUG_OPEN diff --git a/drivers/tty/rocket_int.h b/drivers/tty/rocket_int.h index 67e0f1e778a2..ef1e1be6b26d 100644 --- a/drivers/tty/rocket_int.h +++ b/drivers/tty/rocket_int.h @@ -1144,7 +1144,6 @@ struct r_port { int read_status_mask; int cps; - struct completion close_wait; /* Not yet matching the core */ spinlock_t slock; struct mutex write_mtx; }; -- cgit From 7f71b2c1441877141651d96c9a380bfb32e2ff78 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:09 -0800 Subject: n_tty: Ignore all read data when closing On final port close (and thus final tty close), only output flow control requests in the input data should be processed. Ignore all other input data, including parity errors, overruns and breaks. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index fad365aa1f5c..fb76a7d80e7e 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1524,8 +1524,6 @@ n_tty_receive_buf_closing(struct tty_struct *tty, const unsigned char *cp, flag = *fp++; if (likely(flag == TTY_NORMAL)) n_tty_receive_char_closing(tty, *cp++); - else - n_tty_receive_char_flagged(tty, *cp++, flag); } } -- cgit From 02f14c79abe26a2045669e34baf2c8902d13ae54 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:10 -0800 Subject: ia64: Pin controlling tty for unaligned fault message Prevent destruction of the controlling tty before tty_write_message() can determine if the tty is safe to use. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- arch/ia64/kernel/unaligned.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 622772b7fb6c..e7ae6088350a 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1336,8 +1336,11 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) * Don't call tty_write_message() if we're in the kernel; we might * be holding locks... */ - if (user_mode(regs)) - tty_write_message(current->signal->tty, buf); + if (user_mode(regs)) { + struct tty_struct *tty = get_current_tty(); + tty_write_message(tty, buf); + tty_kref_put(tty); + } buf[len-1] = '\0'; /* drop '\r' */ /* watch for command names containing %s */ printk(KERN_WARNING "%s", buf); -- cgit From 2d73b069f816742ba607f65f9dbbff2885365951 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:11 -0800 Subject: staging: dgap: Remove redundant write_wait wakeups Waking the write_wait queue is exactly what tty_wakeup() does; remove the open-coded wakeups. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/dgap/dgap.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index dfbae215aec3..5413ed8c29ff 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -3155,8 +3155,6 @@ static void dgap_tty_flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); tty_wakeup(tty); } @@ -4953,10 +4951,6 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); wake_up_interruptible(&ch->ch_pun.un_flags_wait); } - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - /* Can't hold any locks when calling tty_wakeup! */ spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); tty_wakeup(tty); -- cgit From f33798deecbd59a2955f40ac0ae2bc7dff54c069 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:12 -0800 Subject: tty: Fix GPF in flush_to_ldisc(), part 2 commit 9ce119f318ba ("tty: Fix GPF in flush_to_ldisc()") fixed a GPF caused by a line discipline which does not define a receive_buf() method. However, the vt driver (and speakup driver also) pushes selection data directly to the line discipline receive_buf() method via tty_ldisc_receive_buf(). Fix the same problem in tty_ldisc_receive_buf(). Cc: Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- include/linux/tty.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/tty.h b/include/linux/tty.h index dea7d54d00d4..03e4015fa033 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -579,7 +579,7 @@ static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, count = ld->ops->receive_buf2(ld->tty, p, f, count); else { count = min_t(int, count, ld->tty->receive_room); - if (count) + if (count && ld->ops->receive_buf) ld->ops->receive_buf(ld->tty, p, f, count); } return count; -- cgit From 8d082cd300ab422b7ee9f4629a1c470e4f0d90d5 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:13 -0800 Subject: tty: Unify receive_buf() code paths Instead of two distinct code branches for receive_buf() handling, use tty_ldisc_receive_buf() as the single code path. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_buffer.c | 39 ++++++++++++++++++++++++++++----------- include/linux/tty.h | 16 ++-------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 3cd31e0d4bd9..a946e49a2626 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -435,25 +435,42 @@ int tty_prepare_flip_string(struct tty_port *port, unsigned char **chars, } EXPORT_SYMBOL_GPL(tty_prepare_flip_string); +/** + * tty_ldisc_receive_buf - forward data to line discipline + * @ld: line discipline to process input + * @p: char buffer + * @f: TTY_* flags buffer + * @count: number of bytes to process + * + * Callers other than flush_to_ldisc() need to exclude the kworker + * from concurrent use of the line discipline, see paste_selection(). + * + * Returns the number of bytes not processed + */ +int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, + char *f, int count) +{ + if (ld->ops->receive_buf2) + count = ld->ops->receive_buf2(ld->tty, p, f, count); + else { + count = min_t(int, count, ld->tty->receive_room); + if (count && ld->ops->receive_buf) + ld->ops->receive_buf(ld->tty, p, f, count); + } + return count; +} +EXPORT_SYMBOL_GPL(tty_ldisc_receive_buf); static int -receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) +receive_buf(struct tty_ldisc *ld, struct tty_buffer *head, int count) { - struct tty_ldisc *disc = tty->ldisc; unsigned char *p = char_buf_ptr(head, head->read); char *f = NULL; if (~head->flags & TTYB_NORMAL) f = flag_buf_ptr(head, head->read); - if (disc->ops->receive_buf2) - count = disc->ops->receive_buf2(tty, p, f, count); - else { - count = min_t(int, count, tty->receive_room); - if (count && disc->ops->receive_buf) - disc->ops->receive_buf(tty, p, f, count); - } - return count; + return tty_ldisc_receive_buf(ld, p, f, count); } /** @@ -514,7 +531,7 @@ static void flush_to_ldisc(struct work_struct *work) continue; } - count = receive_buf(tty, head, count); + count = receive_buf(disc, head, count); if (!count) break; head->read += count; diff --git a/include/linux/tty.h b/include/linux/tty.h index 03e4015fa033..3b09f235db66 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -571,20 +571,8 @@ extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); extern void tty_ldisc_release(struct tty_struct *tty); extern void tty_ldisc_init(struct tty_struct *tty); extern void tty_ldisc_deinit(struct tty_struct *tty); - -static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, - char *f, int count) -{ - if (ld->ops->receive_buf2) - count = ld->ops->receive_buf2(ld->tty, p, f, count); - else { - count = min_t(int, count, ld->tty->receive_room); - if (count && ld->ops->receive_buf) - ld->ops->receive_buf(ld->tty, p, f, count); - } - return count; -} - +extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p, + char *f, int count); /* n_tty.c */ extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops); -- cgit From 5823323ea5ed41ea08ef0a36013369d0c65a23de Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:14 -0800 Subject: tty: Allow unreadable mess to be > 80 chars Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_port.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 846ed481c24f..a76aec2ca480 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -510,10 +510,8 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) if (port->blocked_open) { spin_unlock_irqrestore(&port->lock, flags); - if (port->close_delay) { - msleep_interruptible( - jiffies_to_msecs(port->close_delay)); - } + if (port->close_delay) + msleep_interruptible(jiffies_to_msecs(port->close_delay)); spin_lock_irqsave(&port->lock, flags); wake_up_interruptible(&port->open_wait); } -- cgit From 9db276f8f02145068d8c04614bc28c2a4532a8c7 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:36:15 -0800 Subject: tty: Use termios c_*flag macros Expressions of the form "tty->termios.c_*flag & FLAG" are more clearly expressed with the termios flags macros, I_FLAG(), C_FLAG(), O_FLAG(), and L_FLAG(). Convert treewide. Signed-off-by: Peter Hurley Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/synclink_cs.c | 21 ++++++++------------- drivers/mmc/card/sdio_uart.c | 14 +++++++------- drivers/staging/dgap/dgap.c | 2 +- drivers/staging/dgnc/dgnc_tty.c | 2 +- drivers/tty/amiserial.c | 22 ++++++++-------------- drivers/tty/cyclades.c | 14 ++++++-------- drivers/tty/isicom.c | 3 +-- drivers/tty/mxser.c | 10 ++++------ drivers/tty/n_gsm.c | 6 +++--- drivers/tty/pty.c | 3 +-- drivers/tty/rocket.c | 8 ++++---- drivers/tty/serial/68328serial.c | 4 +--- drivers/tty/serial/crisv10.c | 18 +++++++----------- drivers/tty/serial/jsm/jsm_tty.c | 3 +-- drivers/tty/serial/serial_core.c | 20 +++++++++----------- drivers/tty/synclink.c | 23 +++++++++-------------- drivers/tty/synclink_gt.c | 19 +++++++------------ drivers/tty/synclinkmp.c | 19 +++++++------------ drivers/tty/tty_ioctl.c | 12 ++++++------ drivers/tty/tty_port.c | 2 +- drivers/usb/serial/cypress_m8.c | 3 +-- drivers/usb/serial/digi_acceleport.c | 8 ++++---- drivers/usb/serial/io_edgeport.c | 4 ++-- drivers/usb/serial/mct_u232.c | 2 +- drivers/usb/serial/mos7720.c | 4 ++-- drivers/usb/serial/mos7840.c | 4 ++-- net/irda/ircomm/ircomm_tty.c | 11 +++++------ net/irda/ircomm/ircomm_tty_ioctl.c | 13 ++++--------- 28 files changed, 113 insertions(+), 161 deletions(-) diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 45df4bf914f8..22c27652e46a 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1349,7 +1349,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); - if (!tty || tty->termios.c_cflag & HUPCL) { + if (!tty || C_HUPCL(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); set_signals(info); } @@ -1390,7 +1390,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); get_signals(info); - if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) + if (info->netcount || (tty && C_CREAD(tty))) rx_start(info); spin_unlock_irqrestore(&info->lock, flags); @@ -1733,7 +1733,7 @@ static void mgslpc_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1762,7 +1762,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) mgslpc_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -2306,8 +2306,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term mgslpc_change_params(info, tty); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock, flags); set_signals(info); @@ -2315,21 +2314,17 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock, flags); set_signals(info); spin_unlock_irqrestore(&info->lock, flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index d2de5925b73e..5415056f9aa5 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c @@ -493,7 +493,7 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) if (status & UART_MSR_DCTS) { port->icount.cts++; tty = tty_port_tty_get(&port->port); - if (tty && (tty->termios.c_cflag & CRTSCTS)) { + if (tty && C_CRTSCTS(tty)) { int cts = (status & UART_MSR_CTS); if (tty->hw_stopped) { if (cts) { @@ -648,10 +648,10 @@ static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) sdio_uart_change_speed(port, &tty->termios, NULL); - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) tty->hw_stopped = 1; @@ -833,7 +833,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !C_CRTSCTS(tty)) return; if (sdio_uart_claim_func(port) != 0) @@ -844,7 +844,7 @@ static void sdio_uart_throttle(struct tty_struct *tty) sdio_uart_start_tx(port); } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) sdio_uart_clear_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); @@ -855,7 +855,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) { struct sdio_uart_port *port = tty->driver_data; - if (!I_IXOFF(tty) && !(tty->termios.c_cflag & CRTSCTS)) + if (!I_IXOFF(tty) && !C_CRTSCTS(tty)) return; if (sdio_uart_claim_func(port) != 0) @@ -870,7 +870,7 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) sdio_uart_set_mctrl(port, TIOCM_RTS); sdio_uart_irq(port->func); diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index 5413ed8c29ff..294c1c83aa4d 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -1530,7 +1530,7 @@ static void dgap_input(struct channel_t *ch) if ((bd->state != BOARD_READY) || !tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || + !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { writew(head, &bs->rx_tail); writeb(1, &bs->idata); diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index 4a3d2c6f7eac..8b1ba65a6984 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -541,7 +541,7 @@ void dgnc_input(struct channel_t *ch) */ if (!tp || (tp->magic != TTY_MAGIC) || !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || + !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { ch->ch_r_head = tail; diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 6ba5681b6385..eacf4c9f3b29 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c @@ -639,7 +639,7 @@ static void shutdown(struct tty_struct *tty, struct serial_state *info) custom.adkcon = AC_UARTBRK; mb(); - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) info->MCR &= ~(SER_DTR|SER_RTS); rtsdtr_ctrl(info->MCR); @@ -974,7 +974,7 @@ static void rs_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) info->MCR &= ~SER_RTS; local_irq_save(flags); @@ -999,7 +999,7 @@ static void rs_unthrottle(struct tty_struct * tty) else rs_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) info->MCR |= SER_RTS; local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1332,8 +1332,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(tty, info, old_termios); /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { info->MCR &= ~(SER_DTR|SER_RTS); local_irq_save(flags); rtsdtr_ctrl(info->MCR); @@ -1341,21 +1340,17 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { info->MCR |= SER_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->MCR |= SER_RTS; - } local_irq_save(flags); rtsdtr_ctrl(info->MCR); local_irq_restore(flags); } /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; rs_start(tty); } @@ -1367,8 +1362,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->open_wait); #endif } diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index a48e7e66b970..d67e542bab1c 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -1440,7 +1440,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) info->port.xmit_buf = NULL; free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR); cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR); @@ -1469,7 +1469,7 @@ static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty) free_page((unsigned long)temp); } - if (tty->termios.c_cflag & HUPCL) + if (C_HUPCL(tty)) tty_port_lower_dtr_rts(&info->port); set_bit(TTY_IO_ERROR, &tty->flags); @@ -2795,8 +2795,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) cy_set_line_char(info, tty); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; cy_start(tty); } @@ -2807,8 +2806,7 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios.c_cflag & CLOCAL)) + if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->port.open_wait); #endif } /* cy_set_termios */ @@ -2868,7 +2866,7 @@ static void cy_throttle(struct tty_struct *tty) info->throttle = 1; } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); cyy_change_rts_dtr(info, 0, TIOCM_RTS); @@ -2905,7 +2903,7 @@ static void cy_unthrottle(struct tty_struct *tty) cy_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { card = info->card; if (!cy_is_Z(card)) { spin_lock_irqsave(&card->card_lock, flags); diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index 99875949bfb7..8bf67630018b 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c @@ -1204,8 +1204,7 @@ static void isicom_set_termios(struct tty_struct *tty, isicom_config_port(tty); spin_unlock_irqrestore(&port->card->card_lock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; isicom_start(tty); } diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 4c4a23674569..e9600cece8da 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -1864,7 +1864,7 @@ static void mxser_stoprx(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { info->MCR &= ~UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1901,7 +1901,7 @@ static void mxser_unthrottle(struct tty_struct *tty) } } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { info->MCR |= UART_MCR_RTS; outb(info->MCR, info->ioaddr + UART_MCR); } @@ -1949,15 +1949,13 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi mxser_change_speed(tty, old_termios); spin_unlock_irqrestore(&info->slock, flags); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; mxser_start(tty); } /* Handle sw stopped */ - if ((old_termios->c_iflag & IXON) && - !(tty->termios.c_iflag & IXON)) { + if ((old_termios->c_iflag & IXON) && !I_IXON(tty)) { tty->stopped = 0; if (info->board->chip_flag) { diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index e3cc27749344..c01620780f5b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1066,7 +1066,7 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci, /* Carrier drop -> hangup */ if (tty) { if ((mlines & TIOCM_CD) == 0 && (dlci->modem_rx & TIOCM_CD)) - if (!(tty->termios.c_cflag & CLOCAL)) + if (!C_CLOCAL(tty)) tty_hangup(tty); } if (brk & 0x01) @@ -3116,7 +3116,7 @@ static void gsmtty_throttle(struct tty_struct *tty) struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) return; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) dlci->modem_tx &= ~TIOCM_DTR; dlci->throttled = 1; /* Send an MSC with DTR cleared */ @@ -3128,7 +3128,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty) struct gsm_dlci *dlci = tty->driver_data; if (dlci->state == DLCI_CLOSED) return; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) dlci->modem_tx |= TIOCM_DTR; dlci->throttled = 0; /* Send an MSC with DTR set */ diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index be5020d567ae..78170e7aa3a3 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -263,8 +263,7 @@ static void pty_set_termios(struct tty_struct *tty, { /* See if packet mode change of state. */ if (tty->link && tty->link->packet) { - int extproc = (old_termios->c_lflag & EXTPROC) | - (tty->termios.c_lflag & EXTPROC); + int extproc = (old_termios->c_lflag & EXTPROC) | L_EXTPROC(tty); int old_flow = ((old_termios->c_iflag & IXON) && (old_termios->c_cc[VSTOP] == '\023') && (old_termios->c_cc[VSTART] == '\021')); diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 9dd02daf45ca..2ab3b6fdb675 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -959,7 +959,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) tty->alt_speed = 460800; configure_r_port(tty, info, NULL); - if (tty->termios.c_cflag & CBAUD) { + if (C_BAUD(tty)) { sSetDTR(cp); sSetRTS(cp); } @@ -1084,18 +1084,18 @@ static void rp_set_termios(struct tty_struct *tty, cp = &info->channel; /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { sClrDTR(cp); sClrRTS(cp); } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { sSetRTS(cp); sSetDTR(cp); } - if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rp_start(tty); } diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 90639b590a10..4931212e5cf6 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -976,10 +976,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info, tty); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rs_start(tty); - } /* diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index e98aef797065..37f10c4a3faf 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -1413,9 +1413,8 @@ rs_stop(struct tty_struct *tty) xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(info->port.tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, stop); - if (tty->termios.c_iflag & IXON ) { + if (I_IXON(tty)) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; local_irq_restore(flags); @@ -1436,9 +1435,8 @@ rs_start(struct tty_struct *tty) info->xmit.tail,SERIAL_XMIT_SIZE))); xoff = IO_FIELD(R_SERIAL0_XOFF, xoff_char, STOP_CHAR(tty)); xoff |= IO_STATE(R_SERIAL0_XOFF, tx_stop, enable); - if (tty->termios.c_iflag & IXON ) { + if (I_IXON(tty)) xoff |= IO_STATE(R_SERIAL0_XOFF, auto_xoff, enable); - } *((unsigned long *)&info->ioport[REG_XOFF]) = xoff; if (!info->uses_dma_out && @@ -3166,7 +3164,7 @@ rs_throttle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_throttle\n")); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { /* Turn off RTS line */ e100_rts(info, 0); } @@ -3185,7 +3183,7 @@ rs_unthrottle(struct tty_struct * tty) DFLOW(DEBUG_LOG(info->line,"rs_unthrottle ldisc\n")); DFLOW(DEBUG_LOG(info->line,"rs_unthrottle flip.count: %i\n", tty->flip.count)); /* Do RTS before XOFF since XOFF might take some time */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { /* Assert RTS line */ e100_rts(info, 1); } @@ -3553,8 +3551,7 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_speed(info); /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) rs_start(tty); } @@ -3765,9 +3762,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) { - do_clocal = 1; - } + if (C_CLOCAL(tty)) + do_clocal = 1; /* * Block waiting for the carrier detect and the line to become diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 524e86ab3cae..00cac10ae75a 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -569,8 +569,7 @@ void jsm_input(struct jsm_channel *ch) *If the device is not open, or CREAD is off, flush *input data and return immediately. */ - if (!tp || - !(tp->termios.c_cflag & CREAD) ) { + if (!tp || !C_CREAD(tp)) { jsm_dbg(READ, &ch->ch_bd->pci_dev, "input. dropping %d bytes on port %d...\n", diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b1f54ab1818c..1efdc2b476ea 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -171,14 +171,12 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, */ uart_change_speed(tty, state, NULL); - if (init_hw) { - /* - * Setup the RTS and DTR signals once the - * port is open and ready to respond. - */ - if (tty->termios.c_cflag & CBAUD) - uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); - } + /* + * Setup the RTS and DTR signals once the + * port is open and ready to respond. + */ + if (init_hw && C_BAUD(tty)) + uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); } /* @@ -240,7 +238,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) if (uart_console(uport) && tty) uport->cons->cflag = tty->termios.c_cflag; - if (!tty || (tty->termios.c_cflag & HUPCL)) + if (!tty || C_HUPCL(tty)) uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); uart_port_shutdown(port); @@ -639,7 +637,7 @@ static void uart_throttle(struct tty_struct *tty) if (I_IXOFF(tty)) mask |= UPSTAT_AUTOXOFF; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) mask |= UPSTAT_AUTORTS; if (port->status & mask) { @@ -662,7 +660,7 @@ static void uart_unthrottle(struct tty_struct *tty) if (I_IXOFF(tty)) mask |= UPSTAT_AUTOXOFF; - if (tty->termios.c_cflag & CRTSCTS) + if (C_CRTSCTS(tty)) mask |= UPSTAT_AUTORTS; if (port->status & mask) { diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 6188059fd523..f5476e270734 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c @@ -2363,7 +2363,7 @@ static void mgsl_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgsl_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals &= ~SerialSignal_RTS; usc_set_serial_signals(info); @@ -2397,7 +2397,7 @@ static void mgsl_unthrottle(struct tty_struct * tty) mgsl_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->irq_spinlock,flags); info->serial_signals |= SerialSignal_RTS; usc_set_serial_signals(info); @@ -3039,30 +3039,25 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio mgsl_change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); } - + /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->irq_spinlock,flags); usc_set_serial_signals(info); spin_unlock_irqrestore(&info->irq_spinlock,flags); } - + /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; mgsl_start(tty); } @@ -3281,7 +3276,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c index 5505ea842179..c0a2f5a1b1c2 100644 --- a/drivers/tty/synclink_gt.c +++ b/drivers/tty/synclink_gt.c @@ -774,8 +774,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -783,21 +782,17 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1362,7 +1357,7 @@ static void throttle(struct tty_struct * tty) DBGINFO(("%s throttle\n", info->device_name)); if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals &= ~SerialSignal_RTS; set_signals(info); @@ -1387,7 +1382,7 @@ static void unthrottle(struct tty_struct * tty) else send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->signals |= SerialSignal_RTS; set_signals(info); @@ -3280,7 +3275,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index fb00a06dfa4b..4b314b63a2ed 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -871,8 +871,7 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) change_params(info); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock,flags); set_signals(info); @@ -880,21 +879,17 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock,flags); set_signals(info); spin_unlock_irqrestore(&info->lock,flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } @@ -1472,7 +1467,7 @@ static void throttle(struct tty_struct * tty) if (I_IXOFF(tty)) send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1501,7 +1496,7 @@ static void unthrottle(struct tty_struct * tty) send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock,flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -3297,7 +3292,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, return 0; } - if (tty->termios.c_cflag & CLOCAL) + if (C_CLOCAL(tty)) do_clocal = true; /* Wait for carrier detect and the line to become diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 0ea351388724..23bf5bb1d8bf 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -719,16 +719,16 @@ static int get_sgflags(struct tty_struct *tty) { int flags = 0; - if (!(tty->termios.c_lflag & ICANON)) { - if (tty->termios.c_lflag & ISIG) + if (!L_ICANON(tty)) { + if (L_ISIG(tty)) flags |= 0x02; /* cbreak */ else flags |= 0x20; /* raw */ } - if (tty->termios.c_lflag & ECHO) + if (L_ECHO(tty)) flags |= 0x08; /* echo */ - if (tty->termios.c_oflag & OPOST) - if (tty->termios.c_oflag & ONLCR) + if (O_OPOST(tty)) + if (O_ONLCR(tty)) flags |= 0x10; /* crmod */ return flags; } @@ -908,7 +908,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) tty->termios.c_cflag |= bit; if (tty->ops->set_termios) tty->ops->set_termios(tty, &old); - if ((tty->termios.c_cflag & CLOCAL) != bit) + if (C_CLOCAL(tty) != bit) ret = -EINVAL; up_write(&tty->termios_rwsem); return ret; diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index a76aec2ca480..0473fc7543f7 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -370,7 +370,7 @@ int tty_port_block_til_ready(struct tty_port *port, } if (filp->f_flags & O_NONBLOCK) { /* Indicate we are open */ - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; return 0; diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 01bf53392819..b283eb8b86d6 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1165,8 +1165,7 @@ static void cypress_read_int_callback(struct urb *urb) /* hangup, as defined in acm.c... this might be a bad place for it * though */ - if (tty && !(tty->termios.c_cflag & CLOCAL) && - !(priv->current_status & UART_CD)) { + if (tty && !C_CLOCAL(tty) && !(priv->current_status & UART_CD)) { dev_dbg(dev, "%s - calling hangup\n", __func__); tty_hangup(tty); goto continue_read; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 12b0e67473ba..010a42a92688 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -695,11 +695,11 @@ static void digi_set_termios(struct tty_struct *tty, arg = -1; /* reassert DTR and (maybe) RTS on transition from B0 */ - if ((old_cflag&CBAUD) == B0) { + if ((old_cflag & CBAUD) == B0) { /* don't set RTS if using hardware flow control */ /* and throttling input */ modem_signals = TIOCM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) modem_signals |= TIOCM_RTS; digi_set_modem_signals(port, modem_signals, 1); @@ -1491,8 +1491,8 @@ static int digi_read_oob_callback(struct urb *urb) rts = 0; if (tty) - rts = tty->termios.c_cflag & CRTSCTS; - + rts = C_CRTSCTS(tty); + if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { spin_lock(&priv->dp_port_lock); /* convert from digi flags to termiox flags */ diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index f49327d20ee8..f3007ecdd1b4 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1398,7 +1398,7 @@ static void edge_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { edge_port->shadowMCR &= ~MCR_RTS; status = send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); @@ -1435,7 +1435,7 @@ static void edge_unthrottle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { edge_port->shadowMCR |= MCR_RTS; send_cmd_write_uart_register(edge_port, MCR, edge_port->shadowMCR); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index fd707d6a10e2..4446b8d70ac2 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -428,7 +428,7 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) * either. */ spin_lock_irqsave(&priv->lock, flags); - if (tty && (tty->termios.c_cflag & CBAUD)) + if (tty && C_BAUD(tty)) priv->control_state = TIOCM_DTR | TIOCM_RTS; else priv->control_state = 0; diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 78b4f64c6b00..2eddbe538cda 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1308,7 +1308,7 @@ static void mos7720_throttle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7720_port->shadowMCR &= ~UART_MCR_RTS; write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); @@ -1338,7 +1338,7 @@ static void mos7720_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7720_port->shadowMCR |= UART_MCR_RTS; write_mos_reg(port->serial, port->port_number, MOS7720_MCR, mos7720_port->shadowMCR); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2c69bfcdacc6..02ea975754f5 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1425,7 +1425,7 @@ static void mos7840_throttle(struct tty_struct *tty) return; } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7840_port->shadowMCR &= ~MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); @@ -1466,7 +1466,7 @@ static void mos7840_unthrottle(struct tty_struct *tty) } /* if we are implementing RTS/CTS, toggle that line */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { mos7840_port->shadowMCR |= MCR_RTS; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mos7840_port->shadowMCR); diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index a4237707f79d..1776fe5715e5 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -287,14 +287,14 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, if (filp->f_flags & O_NONBLOCK) { /* nonblock mode is set */ - if (tty->termios.c_cflag & CBAUD) + if (C_BAUD(tty)) tty_port_raise_dtr_rts(port); port->flags |= ASYNC_NORMAL_ACTIVE; pr_debug("%s(), O_NONBLOCK requested!\n", __func__); return 0; } - if (tty->termios.c_cflag & CLOCAL) { + if (C_CLOCAL(tty)) { pr_debug("%s(), doing CLOCAL!\n", __func__); do_clocal = 1; } @@ -806,7 +806,7 @@ static void ircomm_tty_throttle(struct tty_struct *tty) ircomm_tty_send_xchar(tty, STOP_CHAR(tty)); /* Hardware flow control? */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { self->settings.dte &= ~IRCOMM_RTS; self->settings.dte |= IRCOMM_DELTA_RTS; @@ -831,12 +831,11 @@ static void ircomm_tty_unthrottle(struct tty_struct *tty) IRDA_ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;); /* Using software flow control? */ - if (I_IXOFF(tty)) { + if (I_IXOFF(tty)) ircomm_tty_send_xchar(tty, START_CHAR(tty)); - } /* Using hardware flow control? */ - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS); ircomm_param_request(self, IRCOMM_DTE, TRUE); diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c index 75ccdbd0728e..d3687aaa23de 100644 --- a/net/irda/ircomm/ircomm_tty_ioctl.c +++ b/net/irda/ircomm/ircomm_tty_ioctl.c @@ -158,26 +158,21 @@ void ircomm_tty_set_termios(struct tty_struct *tty, ircomm_tty_change_speed(self, tty); /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { self->settings.dte &= ~(IRCOMM_DTR|IRCOMM_RTS); ircomm_param_request(self, IRCOMM_DTE, TRUE); } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { self->settings.dte |= IRCOMM_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) self->settings.dte |= IRCOMM_RTS; - } ircomm_param_request(self, IRCOMM_DTE, TRUE); } /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios.c_cflag & CRTSCTS)) + if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; ircomm_tty_start(tty); -- cgit From f5291ecca148e1a4a75498177862040f9ab7b600 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:55 -0800 Subject: serial: core: Fold __uart_put_char() into caller uart_put_char() is the required interface; manually inline __uart_put_char(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1efdc2b476ea..06b1ddc1d76d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -483,12 +483,15 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, spin_unlock_irq(&uport->lock); } -static inline int __uart_put_char(struct uart_port *port, - struct circ_buf *circ, unsigned char c) +static int uart_put_char(struct tty_struct *tty, unsigned char c) { + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->uart_port; + struct circ_buf *circ; unsigned long flags; int ret = 0; + circ = &state->xmit; if (!circ->buf) return 0; @@ -502,13 +505,6 @@ static inline int __uart_put_char(struct uart_port *port, return ret; } -static int uart_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct uart_state *state = tty->driver_data; - - return __uart_put_char(state->uart_port, &state->xmit, ch); -} - static void uart_flush_chars(struct tty_struct *tty) { uart_start(tty); -- cgit From 3abe8c7671a53f2243d1279a1017d3f4483d34c4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:56 -0800 Subject: serial: core: Fold do_uart_get_info() into caller do_uart_get_info() has a single caller: uart_get_info(). Manually inline do_uart_get_info(). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 06b1ddc1d76d..b1785d112e2e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -671,14 +671,18 @@ static void uart_unthrottle(struct tty_struct *tty) uart_set_mctrl(port, TIOCM_RTS); } -static void do_uart_get_info(struct tty_port *port, - struct serial_struct *retinfo) +static void uart_get_info(struct tty_port *port, struct serial_struct *retinfo) { struct uart_state *state = container_of(port, struct uart_state, port); struct uart_port *uport = state->uart_port; memset(retinfo, 0, sizeof(*retinfo)); + /* + * Ensure the state we copy is consistent and no hardware changes + * occur as we go + */ + mutex_lock(&port->mutex); retinfo->type = uport->type; retinfo->line = uport->line; retinfo->port = uport->iobase; @@ -697,15 +701,6 @@ static void do_uart_get_info(struct tty_port *port, retinfo->io_type = uport->iotype; retinfo->iomem_reg_shift = uport->regshift; retinfo->iomem_base = (void *)(unsigned long)uport->mapbase; -} - -static void uart_get_info(struct tty_port *port, - struct serial_struct *retinfo) -{ - /* Ensure the state we copy is consistent and no hardware changes - occur as we go */ - mutex_lock(&port->mutex); - do_uart_get_info(port, retinfo); mutex_unlock(&port->mutex); } @@ -713,6 +708,7 @@ static int uart_get_info_user(struct tty_port *port, struct serial_struct __user *retinfo) { struct serial_struct tmp; + uart_get_info(port, &tmp); if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) -- cgit From 39b3d8929f3d2104772046977ba0781eaf032df4 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:57 -0800 Subject: serial: core: Use tty->index for port # in debug messages The uart port may have already been removed by uart_remove_one_port(); use equivalent tty->index (which is always valid in these contexts) instead. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index b1785d112e2e..1e7430c60ee6 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1381,8 +1381,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) uport = state->uart_port; port = &state->port; - - pr_debug("uart_close(%d) called\n", uport ? uport->line : -1); + pr_debug("uart_close(%d) called\n", tty->index); if (!port->count || tty_port_close_start(port, tty, filp) == 0) return; @@ -1500,7 +1499,7 @@ static void uart_hangup(struct tty_struct *tty) struct tty_port *port = &state->port; unsigned long flags; - pr_debug("uart_hangup(%d)\n", state->uart_port->line); + pr_debug("uart_hangup(%d)\n", tty->index); mutex_lock(&port->mutex); if (port->flags & ASYNC_NORMAL_ACTIVE) { -- cgit From 35373abbce3e63754f96792cc1e5a4b329d3c737 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:58 -0800 Subject: serial: Fix ASYNC_* => UPF_* flags misuse The UPF_* flags are the correct values to use for struct uart_port and struct old_serial_port/SERIAL_PORT_DFNS. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- arch/alpha/include/asm/serial.h | 8 ++++---- arch/frv/include/asm/serial.h | 2 +- arch/m68k/include/asm/serial.h | 8 ++++---- arch/mips/pmcs-msp71xx/msp_serial.c | 2 +- arch/mn10300/include/asm/serial.h | 10 +++++----- arch/xtensa/platforms/xt2000/setup.c | 2 +- drivers/tty/serial/serial_ks8695.c | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/arch/alpha/include/asm/serial.h b/arch/alpha/include/asm/serial.h index 22909b83f473..e31557fc06cc 100644 --- a/arch/alpha/include/asm/serial.h +++ b/arch/alpha/include/asm/serial.h @@ -14,11 +14,11 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif #define SERIAL_PORT_DFNS \ diff --git a/arch/frv/include/asm/serial.h b/arch/frv/include/asm/serial.h index dbb825998689..bce0d0d07e60 100644 --- a/arch/frv/include/asm/serial.h +++ b/arch/frv/include/asm/serial.h @@ -13,6 +13,6 @@ */ #define BASE_BAUD 0 -#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS UPF_BOOT_AUTOCONF #define SERIAL_PORT_DFNS diff --git a/arch/m68k/include/asm/serial.h b/arch/m68k/include/asm/serial.h index 06d0cb19b4e1..6d4497049b4b 100644 --- a/arch/m68k/include/asm/serial.h +++ b/arch/m68k/include/asm/serial.h @@ -18,11 +18,11 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif #ifdef CONFIG_ISA diff --git a/arch/mips/pmcs-msp71xx/msp_serial.c b/arch/mips/pmcs-msp71xx/msp_serial.c index d304be22b963..8e6e8db8dd5f 100644 --- a/arch/mips/pmcs-msp71xx/msp_serial.c +++ b/arch/mips/pmcs-msp71xx/msp_serial.c @@ -110,7 +110,7 @@ void __init msp_serial_setup(void) up.uartclk = uartclk; up.regshift = 2; up.iotype = UPIO_MEM; - up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + up.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; up.type = PORT_16550A; up.line = 0; up.serial_out = msp_serial_out; diff --git a/arch/mn10300/include/asm/serial.h b/arch/mn10300/include/asm/serial.h index c1990218f18c..594ebff15d3f 100644 --- a/arch/mn10300/include/asm/serial.h +++ b/arch/mn10300/include/asm/serial.h @@ -14,15 +14,15 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_8250_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ) +#define STD_COM4_FLAGS (UPF_BOOT_AUTOCONF | UPF_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) +#define STD_COM4_FLAGS UPF_BOOT_AUTOCONF #endif #ifdef CONFIG_SERIAL_8250_MANY_PORTS -#define FOURPORT_FLAGS ASYNC_FOURPORT +#define FOURPORT_FLAGS UPF_FOURPORT #define ACCENT_FLAGS 0 #define BOCA_FLAGS 0 #define HUB6_FLAGS 0 diff --git a/arch/xtensa/platforms/xt2000/setup.c b/arch/xtensa/platforms/xt2000/setup.c index 87678961a8c8..5f4bd71971d6 100644 --- a/arch/xtensa/platforms/xt2000/setup.c +++ b/arch/xtensa/platforms/xt2000/setup.c @@ -113,7 +113,7 @@ void platform_heartbeat(void) } //#define RS_TABLE_SIZE 2 -//#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +//#define STD_COM_FLAGS (UPF_BOOT_AUTOCONF|UPF_SKIP_TEST) #define _SERIAL_PORT(_base,_irq) \ { \ diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c index b4decf8787de..57f152394af5 100644 --- a/drivers/tty/serial/serial_ks8695.c +++ b/drivers/tty/serial/serial_ks8695.c @@ -554,7 +554,7 @@ static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = { .uartclk = KS8695_CLOCK_RATE * 16, .fifosize = 16, .ops = &ks8695uart_pops, - .flags = ASYNC_BOOT_AUTOCONF, + .flags = UPF_BOOT_AUTOCONF, .line = 0, } }; -- cgit From f9d1083da00514ef36a06e915f32b7304ae5b5bd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:23:59 -0800 Subject: serial: core: Cleanup uart_open() exit If aborting uart_open() unsuccessfully, retval is non-zero, so the existing fall-through exit is equivalent. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 1e7430c60ee6..5cf069756497 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1622,15 +1622,12 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * If we succeeded, wait until the port is ready. */ +err_unlock: mutex_unlock(&port->mutex); if (retval == 0) retval = tty_port_block_til_ready(port, tty, filp); - end: return retval; -err_unlock: - mutex_unlock(&port->mutex); - goto end; } static const char *uart_type(struct uart_port *port) -- cgit From 5e3880273fa3c85bc8f14b9719d2c4be00dd3279 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:24:00 -0800 Subject: serial: core: Remove cast from void ptr in uart_open() void * promotes to any pointer type; remove type cast. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 5cf069756497..9fa42acca7c0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1580,7 +1580,7 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) */ static int uart_open(struct tty_struct *tty, struct file *filp) { - struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; + struct uart_driver *drv = tty->driver->driver_state; int retval, line = tty->index; struct uart_state *state = drv->state + line; struct tty_port *port = &state->port; -- cgit From 968af29836297388743d208a360bac6f1a690148 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:24:01 -0800 Subject: serial: core: Unfold < 80 char lines Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9fa42acca7c0..fa7f442424cf 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1686,17 +1686,13 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) seq_printf(m, " tx:%d rx:%d", uport->icount.tx, uport->icount.rx); if (uport->icount.frame) - seq_printf(m, " fe:%d", - uport->icount.frame); + seq_printf(m, " fe:%d", uport->icount.frame); if (uport->icount.parity) - seq_printf(m, " pe:%d", - uport->icount.parity); + seq_printf(m, " pe:%d", uport->icount.parity); if (uport->icount.brk) - seq_printf(m, " brk:%d", - uport->icount.brk); + seq_printf(m, " brk:%d", uport->icount.brk); if (uport->icount.overrun) - seq_printf(m, " oe:%d", - uport->icount.overrun); + seq_printf(m, " oe:%d", uport->icount.overrun); #define INFOBIT(bit, str) \ if (uport->mctrl & (bit)) \ @@ -1731,8 +1727,7 @@ static int uart_proc_show(struct seq_file *m, void *v) struct uart_driver *drv = ttydrv->driver_state; int i; - seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", - "", "", ""); + seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", "", "", ""); for (i = 0; i < drv->nr; i++) uart_line_info(m, drv, i); return 0; -- cgit From b4749b97ae41f02775967bd109a15b2e223f86be Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 20:24:02 -0800 Subject: serial: core: Perform RTS signalling before soft flow ctrl When throttling, time is of the essence; try RTS signalling before soft flow control, which will take longer. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index fa7f442424cf..be9359fdf5c7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -641,11 +641,11 @@ static void uart_throttle(struct tty_struct *tty) mask &= ~port->status; } - if (mask & UPSTAT_AUTOXOFF) - uart_send_xchar(tty, STOP_CHAR(tty)); - if (mask & UPSTAT_AUTORTS) uart_clear_mctrl(port, TIOCM_RTS); + + if (mask & UPSTAT_AUTOXOFF) + uart_send_xchar(tty, STOP_CHAR(tty)); } static void uart_unthrottle(struct tty_struct *tty) @@ -664,11 +664,11 @@ static void uart_unthrottle(struct tty_struct *tty) mask &= ~port->status; } - if (mask & UPSTAT_AUTOXOFF) - uart_send_xchar(tty, START_CHAR(tty)); - if (mask & UPSTAT_AUTORTS) uart_set_mctrl(port, TIOCM_RTS); + + if (mask & UPSTAT_AUTOXOFF) + uart_send_xchar(tty, START_CHAR(tty)); } static void uart_get_info(struct tty_port *port, struct serial_struct *retinfo) -- cgit From cd7b4b3944381713038d39240098908ffeec647d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:51:38 -0800 Subject: tty: mxser: Remove ASYNC_CLOSING The tty core no longer provides ASYNC_CLOSING. Use private flag for same purpose, which is to clear the fifos at each and every interrupt during driver close(). The driver uses this sledgehammer approach because its close/shutdown sequence is hopelessly borked. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/mxser.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index e9600cece8da..9a0791e523b5 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -254,6 +254,7 @@ struct mxser_port { int xmit_head; int xmit_tail; int xmit_cnt; + int closing; struct ktermios normal_termios; @@ -1081,6 +1082,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) return; if (tty_port_close_start(port, tty, filp) == 0) return; + info->closing = 1; mutex_lock(&port->mutex); mxser_close_port(port); mxser_flush_buffer(tty); @@ -1091,6 +1093,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) mxser_shutdown_port(port); clear_bit(ASYNCB_INITIALIZED, &port->flags); mutex_unlock(&port->mutex); + info->closing = 0; /* Right now the tty_port set is done outside of the close_end helper as we don't yet have everyone using refcounts */ tty_port_close_end(port, tty); @@ -2253,10 +2256,8 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) break; iir &= MOXA_MUST_IIR_MASK; tty = tty_port_tty_get(&port->port); - if (!tty || - (port->port.flags & ASYNC_CLOSING) || - !(port->port.flags & - ASYNC_INITIALIZED)) { + if (!tty || port->closing || + !(port->port.flags & ASYNC_INITIALIZED)) { status = inb(port->ioaddr + UART_LSR); outb(0x27, port->ioaddr + UART_FCR); inb(port->ioaddr + UART_MSR); -- cgit From a657eecd022d82c5b1795243f54389112f42c7f9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:51:39 -0800 Subject: isdn: Remove ASYNC_CLOSING The tty core no longer provides ASYNC_CLOSING. Use private flag for same purpose, which is to disable AT-emulator output (why this is necessary is not clear). Cc: Karsten Keil Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/i4l/isdn_tty.c | 12 ++++++------ include/linux/isdn.h | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 2175225af742..947d5c978b8f 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1572,7 +1572,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) #endif return; } - port->flags |= ASYNC_CLOSING; + info->closing = 1; tty->closing = 1; /* @@ -1603,6 +1603,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->ncarrier = 0; tty_port_close_end(port, tty); + info->closing = 0; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif @@ -2236,7 +2237,7 @@ isdn_tty_at_cout(char *msg, modem_info *info) l = strlen(msg); spin_lock_irqsave(&info->readlock, flags); - if (port->flags & ASYNC_CLOSING) { + if (info->closing) { spin_unlock_irqrestore(&info->readlock, flags); return; } @@ -2386,13 +2387,12 @@ isdn_tty_modem_result(int code, modem_info *info) case RESULT_NO_CARRIER: #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->port.flags & ASYNC_CLOSING), - (!info->port.tty)); + info->closing, !info->port.tty); #endif m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || !info->port.tty) return; #ifdef CONFIG_ISDN_AUDIO @@ -2525,7 +2525,7 @@ isdn_tty_modem_result(int code, modem_info *info) } } if (code == RESULT_NO_CARRIER) { - if ((info->port.flags & ASYNC_CLOSING) || (!info->port.tty)) + if (info->closing || (!info->port.tty)) return; if (info->port.flags & ASYNC_CHECK_CD) diff --git a/include/linux/isdn.h b/include/linux/isdn.h index 1e9a0f2a8626..df97c8444f5d 100644 --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -319,6 +319,7 @@ typedef struct modem_info { int online; /* 1 = B-Channel is up, drop data */ /* 2 = B-Channel is up, deliver d.*/ int dialing; /* Dial in progress or ATA */ + int closing; int rcvsched; /* Receive needs schedule */ int isdn_driver; /* Index to isdn-driver */ int isdn_channel; /* Index to isdn-channel */ -- cgit From afc5ab096581e1ad6e7e7d1533a6bbb1d2b12455 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sun, 10 Jan 2016 14:51:40 -0800 Subject: tty: Remove ASYNC_CLOSING The tty core no longer provides nor uses ASYNC_CLOSING; remove from tty_port_close_start() and tty_port_close_end() as well as tty drivers which open-code these state changes. Unfortunately, even though the bit is masked from userspace, its inclusion in a uapi header precludes removing the macro. Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux-s390@vger.kernel.org Cc: Mikael Starvik Cc: Jesper Nilsson Cc: linux-cris-kernel@axis.com Cc: Samuel Ortiz Cc: "David S. Miller" Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/con3215.c | 3 +-- drivers/tty/rocket.c | 2 +- drivers/tty/serial/68328serial.c | 3 +-- drivers/tty/serial/crisv10.c | 3 +-- drivers/tty/serial/serial_core.c | 1 - drivers/tty/tty_port.c | 3 +-- net/irda/ircomm/ircomm_tty.c | 4 ---- 7 files changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 7d82bbcb12df..e7e078b3c7e6 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -643,7 +643,6 @@ static void raw3215_shutdown(struct raw3215_info *raw) if ((raw->flags & RAW3215_WORKING) || raw->queued_write != NULL || raw->queued_read != NULL) { - raw->port.flags |= ASYNC_CLOSING; add_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); @@ -651,7 +650,7 @@ static void raw3215_shutdown(struct raw3215_info *raw) spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); remove_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_RUNNING); - raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING); + raw->port.flags &= ~ASYNC_INITIALIZED; } spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index 2ab3b6fdb675..0b802cdd70d0 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -1042,7 +1042,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) } } spin_lock_irq(&port->lock); - info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); + info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_NORMAL_ACTIVE); tty->closing = 0; spin_unlock_irq(&port->lock); mutex_unlock(&port->mutex); diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index 4931212e5cf6..9587ed1242fe 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c @@ -1028,7 +1028,6 @@ static void rs_close(struct tty_struct *tty, struct file *filp) local_irq_restore(flags); return; } - port->flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -1058,7 +1057,7 @@ static void rs_close(struct tty_struct *tty, struct file *filp) msleep_interruptible(jiffies_to_msecs(port->close_delay)); wake_up_interruptible(&port->open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + port->flags &= ~ASYNC_NORMAL_ACTIVE; local_irq_restore(flags); } diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 37f10c4a3faf..c0172bf54a9b 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c @@ -3610,7 +3610,6 @@ rs_close(struct tty_struct *tty, struct file * filp) local_irq_restore(flags); return; } - info->port.flags |= ASYNC_CLOSING; /* * Now we wait for the transmit buffer to clear; and we notify * the line discipline to only process XON/XOFF characters. @@ -3649,7 +3648,7 @@ rs_close(struct tty_struct *tty, struct file * filp) schedule_timeout_interruptible(info->port.close_delay); wake_up_interruptible(&info->port.open_wait); } - info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); + info->port.flags &= ~ASYNC_NORMAL_ACTIVE; local_irq_restore(flags); /* port closed */ diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index be9359fdf5c7..85829f8568e7 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1423,7 +1423,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * Wake up anyone trying to open this port. */ clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); - clear_bit(ASYNCB_CLOSING, &port->flags); spin_unlock_irq(&port->lock); wake_up_interruptible(&port->open_wait); diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 0473fc7543f7..dbcca30a54b1 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c @@ -476,7 +476,6 @@ int tty_port_close_start(struct tty_port *port, spin_unlock_irqrestore(&port->lock, flags); return 0; } - set_bit(ASYNCB_CLOSING, &port->flags); spin_unlock_irqrestore(&port->lock, flags); tty->closing = 1; @@ -515,7 +514,7 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) spin_lock_irqsave(&port->lock, flags); wake_up_interruptible(&port->open_wait); } - port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); + port->flags &= ~ASYNC_NORMAL_ACTIVE; spin_unlock_irqrestore(&port->lock, flags); } EXPORT_SYMBOL(tty_port_close_end); diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 1776fe5715e5..da126ee6d218 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -1267,10 +1267,6 @@ static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) seq_printf(m, "%cASYNC_LOW_LATENCY", sep); sep = '|'; } - if (self->port.flags & ASYNC_CLOSING) { - seq_printf(m, "%cASYNC_CLOSING", sep); - sep = '|'; - } if (self->port.flags & ASYNC_NORMAL_ACTIVE) { seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); sep = '|'; -- cgit From f1188b898ec5aa2e94da8fb998648a2738f4fb3b Mon Sep 17 00:00:00 2001 From: "Damien.Horsley" Date: Thu, 28 Jan 2016 16:54:20 +0000 Subject: ASoC: pcm3168a: Call clk_set_rate in pcm3168a_set_dai_sysclk Call clk_set_rate in pcm3168a_set_dai_sysclk Signed-off-by: Damien.Horsley Signed-off-by: Mark Brown --- sound/soc/codecs/pcm3168a.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c index 44b268aa4dd8..0c7248ab6a37 100644 --- a/sound/soc/codecs/pcm3168a.c +++ b/sound/soc/codecs/pcm3168a.c @@ -299,10 +299,15 @@ static int pcm3168a_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir) { struct pcm3168a_priv *pcm3168a = snd_soc_codec_get_drvdata(dai->codec); + int ret; if (freq > PCM1368A_MAX_SYSCLK) return -EINVAL; + ret = clk_set_rate(pcm3168a->scki, freq); + if (ret) + return ret; + pcm3168a->sysclk = freq; return 0; -- cgit From 0f9aa09d669b29ae536d51631bf035ad44ae0551 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Jan 2016 17:52:57 +0000 Subject: ASoC: wm5110: Fix up snd_soc_register_platform error path Whilst there is nothing wrong with the error path here it looks a little bit odd, this patches makes the code a little more idiomatic. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5110.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 6088d30962a9..83760b72aa03 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2366,7 +2366,7 @@ static int wm5110_probe(struct platform_device *pdev) ret = snd_soc_register_platform(&pdev->dev, &wm5110_compr_platform); if (ret < 0) { dev_err(&pdev->dev, "Failed to register platform: %d\n", ret); - goto error; + return ret; } ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5110, @@ -2376,7 +2376,6 @@ static int wm5110_probe(struct platform_device *pdev) snd_soc_unregister_platform(&pdev->dev); } -error: return ret; } -- cgit From e6d00f3403c439b8d1e6f9f09d5ae3048aa726e4 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Jan 2016 17:52:58 +0000 Subject: ASoC: wm_adsp: Use more generic naming for regions and caps definitions The region definition will be shared by most firmwares so give this a more generic name and whilst we are there improve the naming of the voice control capabilities array as well. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 33806d487b8a..0392c58dfc5d 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -328,7 +328,7 @@ struct wm_adsp_buffer_region_def { unsigned int size_offset; }; -static struct wm_adsp_buffer_region_def ez2control_regions[] = { +static struct wm_adsp_buffer_region_def default_regions[] = { { .mem_type = WMFW_ADSP2_XM, .base_offset = HOST_BUFFER_FIELD(X_buf_base), @@ -353,7 +353,7 @@ struct wm_adsp_fw_caps { struct wm_adsp_buffer_region_def *region_defs; }; -static const struct wm_adsp_fw_caps ez2control_caps[] = { +static const struct wm_adsp_fw_caps ctrl_caps[] = { { .id = SND_AUDIOCODEC_BESPOKE, .desc = { @@ -362,8 +362,8 @@ static const struct wm_adsp_fw_caps ez2control_caps[] = { .num_sample_rates = 1, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, - .num_regions = ARRAY_SIZE(ez2control_regions), - .region_defs = ez2control_regions, + .num_regions = ARRAY_SIZE(default_regions), + .region_defs = default_regions, }, }; @@ -382,8 +382,8 @@ static const struct { [WM_ADSP_FW_CTRL] = { .file = "ctrl", .compr_direction = SND_COMPRESS_CAPTURE, - .num_caps = ARRAY_SIZE(ez2control_caps), - .caps = ez2control_caps, + .num_caps = ARRAY_SIZE(ctrl_caps), + .caps = ctrl_caps, }, [WM_ADSP_FW_ASR] = { .file = "asr" }, [WM_ADSP_FW_TRACE] = { .file = "trace" }, -- cgit From 7ce4283ca405d459c186960ed39d41ec0e6fb2bf Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Jan 2016 17:52:59 +0000 Subject: ASoC: wm_adsp: Add debug audio trace firmware The audio trace firmware allows the capture of arbitrary streams of audio from the DSP and commonly used for debugging other firmwares. This patch adds support for this firwmare into the ADSP driver. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 0392c58dfc5d..a81f568a9660 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -367,6 +367,24 @@ static const struct wm_adsp_fw_caps ctrl_caps[] = { }, }; +static const struct wm_adsp_fw_caps trace_caps[] = { + { + .id = SND_AUDIOCODEC_BESPOKE, + .desc = { + .max_ch = 8, + .sample_rates = { + 4000, 8000, 11025, 12000, 16000, 22050, + 24000, 32000, 44100, 48000, 64000, 88200, + 96000, 176400, 192000 + }, + .num_sample_rates = 15, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .num_regions = ARRAY_SIZE(default_regions), + .region_defs = default_regions, + }, +}; + static const struct { const char *file; int compr_direction; @@ -386,7 +404,12 @@ static const struct { .caps = ctrl_caps, }, [WM_ADSP_FW_ASR] = { .file = "asr" }, - [WM_ADSP_FW_TRACE] = { .file = "trace" }, + [WM_ADSP_FW_TRACE] = { + .file = "trace", + .compr_direction = SND_COMPRESS_CAPTURE, + .num_caps = ARRAY_SIZE(trace_caps), + .caps = trace_caps, + }, [WM_ADSP_FW_SPK_PROT] = { .file = "spk-prot" }, [WM_ADSP_FW_MISC] = { .file = "misc" }, }; -- cgit From d82d767f0e61da5f1f872d40358904eb316af264 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Jan 2016 17:53:02 +0000 Subject: ASoC: wm_adsp: Move setting of DSP speed into CODEC specific code The ADSP code should be agnostic of which CODEC it runs upon, currently there is only one remaining part of the implementation that doesn't follow this. When the DSP is booted on ADSP2 we read ARIZONA_SYSTEM_CLOCK_1 and use that to set the initial speed for the DSP clock. This patch factors that out into CODEC specific code, leaving the ADSP code entirely CODEC agnostic. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 23 +++++++++++++++++++++-- sound/soc/codecs/wm5102.c | 6 +++--- sound/soc/codecs/wm5110.c | 27 +++++++++++++++++++++++---- sound/soc/codecs/wm_adsp.c | 40 +++++++++++++++------------------------- sound/soc/codecs/wm_adsp.h | 8 +++----- 5 files changed, 65 insertions(+), 39 deletions(-) diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index dc5ae7f7a1bd..9dc77a4da35d 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -57,6 +57,25 @@ static const struct wm_adsp_region *cs47l24_dsp_regions[] = { cs47l24_dsp3_regions, }; +static int cs47l24_adsp_power_ev(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 arizona *arizona = dev_get_drvdata(codec->dev->parent); + unsigned int v; + int ret; + + ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v); + if (ret != 0) { + dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret); + return ret; + } + + v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT; + + return wm_adsp2_early_event(w, kcontrol, event, v); +} + static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); static DECLARE_TLV_DB_SCALE(noise_tlv, -13200, 600, 0); @@ -405,8 +424,8 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, NULL, 0), -WM_ADSP2("DSP2", 1), -WM_ADSP2("DSP3", 2), +WM_ADSP2("DSP2", 1, cs47l24_adsp_power_ev), +WM_ADSP2("DSP3", 2, cs47l24_adsp_power_ev), SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 64637d1cf4e5..7c0860df3204 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -619,7 +619,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct arizona *arizona = dev_get_drvdata(codec->dev->parent); - unsigned int v; + unsigned int v = 0; int ret; switch (event) { @@ -654,7 +654,7 @@ static int wm5102_adsp_power_ev(struct snd_soc_dapm_widget *w, break; } - return wm_adsp2_early_event(w, kcontrol, event); + return wm_adsp2_early_event(w, kcontrol, event, v); } static int wm5102_out_comp_coeff_get(struct snd_kcontrol *kcontrol, @@ -1408,7 +1408,7 @@ ARIZONA_MUX_WIDGETS(ISRC2DEC2, "ISRC2DEC2"), ARIZONA_MUX_WIDGETS(ISRC2INT1, "ISRC2INT1"), ARIZONA_MUX_WIDGETS(ISRC2INT2, "ISRC2INT2"), -WM_ADSP2_E("DSP1", 0, wm5102_adsp_power_ev), +WM_ADSP2("DSP1", 0, wm5102_adsp_power_ev), SND_SOC_DAPM_OUTPUT("HPOUT1L"), SND_SOC_DAPM_OUTPUT("HPOUT1R"), diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 83760b72aa03..b47bc4418e30 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -191,6 +191,25 @@ static int wm5110_sysclk_ev(struct snd_soc_dapm_widget *w, return 0; } +static int wm5110_adsp_power_ev(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 arizona *arizona = dev_get_drvdata(codec->dev->parent); + unsigned int v; + int ret; + + ret = regmap_read(arizona->regmap, ARIZONA_SYSTEM_CLOCK_1, &v); + if (ret != 0) { + dev_err(codec->dev, "Failed to read SYSCLK state: %d\n", ret); + return ret; + } + + v = (v & ARIZONA_SYSCLK_FREQ_MASK) >> ARIZONA_SYSCLK_FREQ_SHIFT; + + return wm_adsp2_early_event(w, kcontrol, event, v); +} + static const struct reg_sequence wm5110_no_dre_left_enable[] = { { 0x3024, 0xE410 }, { 0x3025, 0x0056 }, @@ -1179,10 +1198,10 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, NULL, 0), -WM_ADSP2("DSP1", 0), -WM_ADSP2("DSP2", 1), -WM_ADSP2("DSP3", 2), -WM_ADSP2("DSP4", 3), +WM_ADSP2("DSP1", 0, wm5110_adsp_power_ev), +WM_ADSP2("DSP2", 1, wm5110_adsp_power_ev), +WM_ADSP2("DSP3", 2, wm5110_adsp_power_ev), +WM_ADSP2("DSP4", 3, wm5110_adsp_power_ev), SND_SOC_DAPM_PGA("ISRC1INT1", ARIZONA_ISRC_1_CTRL_3, ARIZONA_ISRC1_INT0_ENA_SHIFT, 0, NULL, 0), diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index a81f568a9660..76ab52d2c670 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -32,9 +32,6 @@ #include #include -#include - -#include "arizona.h" #include "wm_adsp.h" #define adsp_crit(_dsp, fmt, ...) \ @@ -2146,30 +2143,9 @@ static void wm_adsp2_boot_work(struct work_struct *work) struct wm_adsp, boot_work); int ret; - unsigned int val; mutex_lock(&dsp->pwr_lock); - /* - * For simplicity set the DSP clock rate to be the - * SYSCLK rate rather than making it configurable. - */ - ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); - if (ret != 0) { - adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret); - goto err_mutex; - } - val = (val & ARIZONA_SYSCLK_FREQ_MASK) - >> ARIZONA_SYSCLK_FREQ_SHIFT; - - ret = regmap_update_bits_async(dsp->regmap, - dsp->base + ADSP2_CLOCKING, - ADSP2_CLK_SEL_MASK, val); - if (ret != 0) { - adsp_err(dsp, "Failed to set clock rate: %d\n", ret); - goto err_mutex; - } - ret = wm_adsp2_ena(dsp); if (ret != 0) goto err_mutex; @@ -2209,8 +2185,21 @@ err_mutex: mutex_unlock(&dsp->pwr_lock); } +static void wm_adsp2_set_dspclk(struct wm_adsp *dsp, unsigned int freq) +{ + int ret; + + ret = regmap_update_bits_async(dsp->regmap, + dsp->base + ADSP2_CLOCKING, + ADSP2_CLK_SEL_MASK, + freq << ADSP2_CLK_SEL_SHIFT); + if (ret != 0) + adsp_err(dsp, "Failed to set clock rate: %d\n", ret); +} + int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) + struct snd_kcontrol *kcontrol, int event, + unsigned int freq) { struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); @@ -2220,6 +2209,7 @@ int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + wm_adsp2_set_dspclk(dsp, freq); queue_work(system_unbound_wq, &dsp->boot_work); break; default: diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 1a928ec54741..b61cb57e600f 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h @@ -80,7 +80,7 @@ struct wm_adsp { SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) -#define WM_ADSP2_E(wname, num, event_fn) \ +#define WM_ADSP2(wname, num, event_fn) \ { .id = snd_soc_dapm_dai_link, .name = wname " Preloader", \ .reg = SND_SOC_NOPM, .shift = num, .event = event_fn, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD }, \ @@ -88,9 +88,6 @@ struct wm_adsp { .reg = SND_SOC_NOPM, .shift = num, .event = wm_adsp2_event, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } -#define WM_ADSP2(wname, num) \ - WM_ADSP2_E(wname, num, wm_adsp2_early_event) - extern const struct snd_kcontrol_new wm_adsp_fw_controls[]; int wm_adsp1_init(struct wm_adsp *dsp); @@ -100,7 +97,8 @@ int wm_adsp2_codec_remove(struct wm_adsp *dsp, struct snd_soc_codec *codec); int wm_adsp1_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int wm_adsp2_early_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event); + struct snd_kcontrol *kcontrol, int event, + unsigned int freq); int wm_adsp2_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); -- cgit From 1b347b6891335a30131899dd16ec6ca843c578f0 Mon Sep 17 00:00:00 2001 From: Jacob Siverskog Date: Fri, 22 Jan 2016 13:39:53 +0100 Subject: ASoC: pcm179x: Split into core and SPI parts The pcm179x family supports both SPI and I2C for configuration. This patch splits the driver into core and SPI parts, in preparation for I2C support. Signed-off-by: Jacob Siverskog Reviewed-by: Johan Hovold Acked-by: Michael Trimarchi Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 11 +++++-- sound/soc/codecs/Makefile | 2 ++ sound/soc/codecs/pcm179x-spi.c | 72 ++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/pcm179x.c | 52 +++++++----------------------- sound/soc/codecs/pcm179x.h | 5 +++ 5 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 sound/soc/codecs/pcm179x-spi.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 50693c867e71..ae720f1b15e8 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -87,7 +87,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ML26124 if I2C select SND_SOC_NAU8825 if I2C select SND_SOC_PCM1681 if I2C - select SND_SOC_PCM179X if SPI_MASTER + select SND_SOC_PCM179X_SPI if SPI_MASTER select SND_SOC_PCM3008 select SND_SOC_PCM3168A_I2C if I2C select SND_SOC_PCM3168A_SPI if SPI_MASTER @@ -527,8 +527,15 @@ config SND_SOC_PCM1681 depends on I2C config SND_SOC_PCM179X - tristate "Texas Instruments PCM179X CODEC" + tristate + +config SND_SOC_PCM179X_SPI + tristate "Texas Instruments PCM179X CODEC (SPI)" depends on SPI_MASTER + select SND_SOC_PCM179X + help + Enable support for Texas Instruments PCM179x CODEC. + Select this if your PCM179x is connected via an SPI bus. config SND_SOC_PCM3008 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d44f7d347183..56e94d88693f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -81,6 +81,7 @@ snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o +snd-soc-pcm179x-spi-objs := pcm179x-spi.o snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm3168a-objs := pcm3168a.o snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o @@ -285,6 +286,7 @@ obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.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_SPI) += snd-soc-pcm179x-spi.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o obj-$(CONFIG_SND_SOC_PCM3168A_I2C) += snd-soc-pcm3168a-i2c.o diff --git a/sound/soc/codecs/pcm179x-spi.c b/sound/soc/codecs/pcm179x-spi.c new file mode 100644 index 000000000000..da924d444083 --- /dev/null +++ b/sound/soc/codecs/pcm179x-spi.c @@ -0,0 +1,72 @@ +/* + * PCM179X ASoC SPI driver + * + * Copyright (c) Amarula Solutions B.V. 2013 + * + * Michael Trimarchi + * + * 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 "pcm179x.h" + +static int pcm179x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_spi(spi, &pcm179x_regmap_config); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&spi->dev, "Failed to allocate regmap: %d\n", ret); + return ret; + } + + return pcm179x_common_init(&spi->dev, regmap); +} + +static int pcm179x_spi_remove(struct spi_device *spi) +{ + return pcm179x_common_exit(&spi->dev); +} + +static const struct of_device_id pcm179x_of_match[] = { + { .compatible = "ti,pcm1792a", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm179x_of_match); + +static const struct spi_device_id pcm179x_spi_ids[] = { + { "pcm179x", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, pcm179x_spi_ids); + +static struct spi_driver pcm179x_spi_driver = { + .driver = { + .name = "pcm179x", + .of_match_table = of_match_ptr(pcm179x_of_match), + }, + .id_table = pcm179x_spi_ids, + .probe = pcm179x_spi_probe, + .remove = pcm179x_spi_remove, +}; + +module_spi_driver(pcm179x_spi_driver); + +MODULE_DESCRIPTION("ASoC PCM179X SPI driver"); +MODULE_AUTHOR("Michael Trimarchi "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c index a56c7b767d90..8f20f70af23e 100644 --- a/sound/soc/codecs/pcm179x.c +++ b/sound/soc/codecs/pcm179x.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -29,7 +28,6 @@ #include #include #include -#include #include "pcm179x.h" @@ -194,13 +192,7 @@ static struct snd_soc_dai_driver pcm179x_dai = { .ops = &pcm179x_dai_ops, }; -static const struct of_device_id pcm179x_of_match[] = { - { .compatible = "ti,pcm1792a", }, - { } -}; -MODULE_DEVICE_TABLE(of, pcm179x_of_match); - -static const struct regmap_config pcm179x_regmap = { +const struct regmap_config pcm179x_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = 23, @@ -209,6 +201,7 @@ static const struct regmap_config pcm179x_regmap = { .writeable_reg = pcm179x_writeable_reg, .readable_reg = pcm179x_accessible_reg, }; +EXPORT_SYMBOL_GPL(pcm179x_regmap_config); static struct snd_soc_codec_driver soc_codec_dev_pcm179x = { .controls = pcm179x_controls, @@ -219,52 +212,29 @@ static struct snd_soc_codec_driver soc_codec_dev_pcm179x = { .num_dapm_routes = ARRAY_SIZE(pcm179x_dapm_routes), }; -static int pcm179x_spi_probe(struct spi_device *spi) +int pcm179x_common_init(struct device *dev, struct regmap *regmap) { struct pcm179x_private *pcm179x; - int ret; - pcm179x = devm_kzalloc(&spi->dev, sizeof(struct pcm179x_private), + pcm179x = devm_kzalloc(dev, sizeof(struct pcm179x_private), GFP_KERNEL); if (!pcm179x) return -ENOMEM; - spi_set_drvdata(spi, pcm179x); - - pcm179x->regmap = devm_regmap_init_spi(spi, &pcm179x_regmap); - if (IS_ERR(pcm179x->regmap)) { - ret = PTR_ERR(pcm179x->regmap); - dev_err(&spi->dev, "Failed to register regmap: %d\n", ret); - return ret; - } + pcm179x->regmap = regmap; + dev_set_drvdata(dev, pcm179x); - return snd_soc_register_codec(&spi->dev, + return snd_soc_register_codec(dev, &soc_codec_dev_pcm179x, &pcm179x_dai, 1); } +EXPORT_SYMBOL_GPL(pcm179x_common_init); -static int pcm179x_spi_remove(struct spi_device *spi) +int pcm179x_common_exit(struct device *dev) { - snd_soc_unregister_codec(&spi->dev); + snd_soc_unregister_codec(dev); return 0; } - -static const struct spi_device_id pcm179x_spi_ids[] = { - { "pcm179x", 0 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, pcm179x_spi_ids); - -static struct spi_driver pcm179x_codec_driver = { - .driver = { - .name = "pcm179x", - .of_match_table = of_match_ptr(pcm179x_of_match), - }, - .id_table = pcm179x_spi_ids, - .probe = pcm179x_spi_probe, - .remove = pcm179x_spi_remove, -}; - -module_spi_driver(pcm179x_codec_driver); +EXPORT_SYMBOL_GPL(pcm179x_common_exit); MODULE_DESCRIPTION("ASoC PCM179X driver"); MODULE_AUTHOR("Michael Trimarchi "); diff --git a/sound/soc/codecs/pcm179x.h b/sound/soc/codecs/pcm179x.h index c6fdc062a497..c4eea4df915b 100644 --- a/sound/soc/codecs/pcm179x.h +++ b/sound/soc/codecs/pcm179x.h @@ -24,4 +24,9 @@ #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S16_LE) +extern const struct regmap_config pcm179x_regmap_config; + +int pcm179x_common_init(struct device *dev, struct regmap *regmap); +int pcm179x_common_exit(struct device *dev); + #endif -- cgit From 70e3e56e6c3d499be47322037ed4a42314a8e509 Mon Sep 17 00:00:00 2001 From: Jacob Siverskog Date: Fri, 22 Jan 2016 13:39:54 +0100 Subject: ASoC: pcm179x: Add I2C interface driver The PCM179x family supports both SPI and I2C. This patch adds support for the I2C interface. Signed-off-by: Jacob Siverskog Reviewed-by: Johan Hovold Acked-by: Michael Trimarchi Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/pcm179x.txt | 11 +++- sound/soc/codecs/Kconfig | 9 +++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/pcm179x-i2c.c | 73 ++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 sound/soc/codecs/pcm179x-i2c.c diff --git a/Documentation/devicetree/bindings/sound/pcm179x.txt b/Documentation/devicetree/bindings/sound/pcm179x.txt index 4ae70d3462d6..436c2b247693 100644 --- a/Documentation/devicetree/bindings/sound/pcm179x.txt +++ b/Documentation/devicetree/bindings/sound/pcm179x.txt @@ -1,6 +1,6 @@ Texas Instruments pcm179x DT bindings -This driver supports the SPI bus. +This driver supports both the I2C and SPI bus. Required properties: @@ -9,6 +9,11 @@ Required properties: For required properties on SPI, please consult Documentation/devicetree/bindings/spi/spi-bus.txt +Required properties on I2C: + + - reg: the I2C address + + Examples: codec_spi: 1792a@0 { @@ -16,3 +21,7 @@ Examples: spi-max-frequency = <600000>; }; + codec_i2c: 1792a@4c { + compatible = "ti,pcm1792a"; + reg = <0x4c>; + }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index ae720f1b15e8..3a8fcf13200f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -87,6 +87,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_ML26124 if I2C select SND_SOC_NAU8825 if I2C select SND_SOC_PCM1681 if I2C + select SND_SOC_PCM179X_I2C if I2C select SND_SOC_PCM179X_SPI if SPI_MASTER select SND_SOC_PCM3008 select SND_SOC_PCM3168A_I2C if I2C @@ -529,6 +530,14 @@ config SND_SOC_PCM1681 config SND_SOC_PCM179X tristate +config SND_SOC_PCM179X_I2C + tristate "Texas Instruments PCM179X CODEC (I2C)" + depends on I2C + select SND_SOC_PCM179X + help + Enable support for Texas Instruments PCM179x CODEC. + Select this if your PCM179x is connected via an I2C bus. + config SND_SOC_PCM179X_SPI tristate "Texas Instruments PCM179X CODEC (SPI)" depends on SPI_MASTER diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 56e94d88693f..9acd777a7a98 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -81,6 +81,7 @@ snd-soc-ml26124-objs := ml26124.o snd-soc-nau8825-objs := nau8825.o snd-soc-pcm1681-objs := pcm1681.o snd-soc-pcm179x-codec-objs := pcm179x.o +snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o snd-soc-pcm179x-spi-objs := pcm179x-spi.o snd-soc-pcm3008-objs := pcm3008.o snd-soc-pcm3168a-objs := pcm3168a.o @@ -286,6 +287,7 @@ obj-$(CONFIG_SND_SOC_ML26124) += snd-soc-ml26124.o obj-$(CONFIG_SND_SOC_NAU8825) += snd-soc-nau8825.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 obj-$(CONFIG_SND_SOC_PCM179X_SPI) += snd-soc-pcm179x-spi.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_PCM3168A) += snd-soc-pcm3168a.o diff --git a/sound/soc/codecs/pcm179x-i2c.c b/sound/soc/codecs/pcm179x-i2c.c new file mode 100644 index 000000000000..4118106abb8d --- /dev/null +++ b/sound/soc/codecs/pcm179x-i2c.c @@ -0,0 +1,73 @@ +/* + * PCM179X ASoC I2C driver + * + * Copyright (c) Teenage Engineering AB 2016 + * + * Jacob Siverskog + * + * 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 "pcm179x.h" + +static int pcm179x_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + int ret; + + regmap = devm_regmap_init_i2c(client, &pcm179x_regmap_config); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&client->dev, "Failed to allocate regmap: %d\n", ret); + return ret; + } + + return pcm179x_common_init(&client->dev, regmap); +} + +static int pcm179x_i2c_remove(struct i2c_client *client) +{ + return pcm179x_common_exit(&client->dev); +} + +static const struct of_device_id pcm179x_of_match[] = { + { .compatible = "ti,pcm1792a", }, + { } +}; +MODULE_DEVICE_TABLE(of, pcm179x_of_match); + +static const struct i2c_device_id pcm179x_i2c_ids[] = { + { "pcm179x", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pcm179x_i2c_ids); + +static struct i2c_driver pcm179x_i2c_driver = { + .driver = { + .name = "pcm179x", + .of_match_table = of_match_ptr(pcm179x_of_match), + }, + .id_table = pcm179x_i2c_ids, + .probe = pcm179x_i2c_probe, + .remove = pcm179x_i2c_remove, +}; + +module_i2c_driver(pcm179x_i2c_driver); + +MODULE_DESCRIPTION("ASoC PCM179X I2C driver"); +MODULE_AUTHOR("Jacob Siverskog "); +MODULE_LICENSE("GPL"); -- cgit From e0236f541e68aa2187a9a402bf74bec6f007eb84 Mon Sep 17 00:00:00 2001 From: Jacob Siverskog Date: Fri, 22 Jan 2016 13:39:55 +0100 Subject: ASoC: pcm179x: Support continuous rates According to the PCM179x data sheets sampling frequencies between 10 kHz and 200 kHz are supported. Specify support in the driver. Tested with PCM1791A. References: http://www.ti.com/lit/ds/symlink/pcm1791a.pdf http://www.ti.com/lit/ds/symlink/pcm1792a.pdf http://www.ti.com/lit/ds/symlink/pcm1795.pdf http://www.ti.com/lit/ds/symlink/pcm1796.pdf Signed-off-by: Jacob Siverskog Reviewed-by: Johan Hovold Acked-by: Michael Trimarchi Signed-off-by: Mark Brown --- sound/soc/codecs/pcm179x.c | 4 +++- sound/soc/codecs/pcm179x.h | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/pcm179x.c b/sound/soc/codecs/pcm179x.c index 8f20f70af23e..06a66579ca6d 100644 --- a/sound/soc/codecs/pcm179x.c +++ b/sound/soc/codecs/pcm179x.c @@ -187,7 +187,9 @@ static struct snd_soc_dai_driver pcm179x_dai = { .stream_name = "Playback", .channels_min = 2, .channels_max = 2, - .rates = PCM1792A_RATES, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 10000, + .rate_max = 200000, .formats = PCM1792A_FORMATS, }, .ops = &pcm179x_dai_ops, }; diff --git a/sound/soc/codecs/pcm179x.h b/sound/soc/codecs/pcm179x.h index c4eea4df915b..11e331268aae 100644 --- a/sound/soc/codecs/pcm179x.h +++ b/sound/soc/codecs/pcm179x.h @@ -17,10 +17,6 @@ #ifndef __PCM179X_H__ #define __PCM179X_H__ -#define PCM1792A_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_8000_48000 | \ - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ - SNDRV_PCM_RATE_192000) - #define PCM1792A_FORMATS (SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S16_LE) -- cgit From b0639bd2428d61a13b69d2ff247cfceae90b8366 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 21 Jan 2016 01:47:12 +0000 Subject: ASoC: soc-pcm: copy dpcm->hw_params and call be_hw_params_fixup every time Current DPCM doesn't copy dpcm->hw_params and doesn't call be_hw_params if some FE are connected. But 2nd or later FE might want to know BE hw_params. This patch solves this issue. Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e898b427be7e..be2fd5e46182 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1866,18 +1866,6 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) if (!snd_soc_dpcm_be_can_update(fe, be, stream)) continue; - /* only allow hw_params() if no connected FEs are running */ - if (!snd_soc_dpcm_can_be_params(fe, be, stream)) - continue; - - if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE)) - continue; - - dev_dbg(be->dev, "ASoC: hw_params BE %s\n", - dpcm->fe->dai_link->name); - /* copy params for each dpcm */ memcpy(&dpcm->hw_params, &fe->dpcm[stream].hw_params, sizeof(struct snd_pcm_hw_params)); @@ -1894,6 +1882,18 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) } } + /* only allow hw_params() if no connected FEs are running */ + if (!snd_soc_dpcm_can_be_params(fe, be, stream)) + continue; + + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE)) + continue; + + dev_dbg(be->dev, "ASoC: hw_params BE %s\n", + dpcm->fe->dai_link->name); + ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params); if (ret < 0) { dev_err(dpcm->be->dev, -- cgit From 76e9521fc9a400c62585b5fc2465d1103f6ce836 Mon Sep 17 00:00:00 2001 From: "Daniel H. Hemmingsen" Date: Tue, 10 Nov 2015 19:35:30 +0100 Subject: Staging: panel: Fixed a spacing after cast coding style issue Fixed a spacing after cast coding style issue. Signed-off-by: Daniel H. Hemmingsen Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 79ac19246548..96920efa8fc7 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -1788,7 +1788,7 @@ static void phys_scan_contacts(void) gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; /* grounded inputs are signals 40-44 */ - phys_read |= (pmask_t) gndmask << 40; + phys_read |= (pmask_t)gndmask << 40; if (bitmask != gndmask) { /* -- cgit From df44f1504b4d04e523ccc6469a53d37380c9bfbd Mon Sep 17 00:00:00 2001 From: Ricardo Ruedas Date: Tue, 8 Dec 2015 22:30:40 +0100 Subject: staging: panel: remove warnings line over 80 characters This patch removes the warnings reported by checkpatch.pl for line over 80 characters. Signed-off-by: Ricardo Ruedas Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 96920efa8fc7..1e67e26a9e0c 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -947,7 +947,8 @@ static void lcd_clear_fast_s(void) lcd_send_serial(0x5F); /* R/W=W, RS=1 */ lcd_send_serial(' ' & 0x0F); lcd_send_serial((' ' >> 4) & 0x0F); - usleep_range(40, 100); /* the shortest data takes at least 40 us */ + /* the shortest data takes at least 40 us */ + usleep_range(40, 100); } spin_unlock_irq(&pprt_lock); -- cgit From 05c153fa1990a9450d99b2f1a858873a912694d2 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 18 Dec 2015 14:06:14 +0100 Subject: staging: update panel driver's author address I'm realizing that I sometimes miss e-mails sent to my old address, so better update it. Since I only have the relevant hardware at my work place, let's use this address so that I can test code if needed. Signed-off-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- drivers/staging/panel/TODO | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..48d09cca8505 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10401,7 +10401,7 @@ S: Maintained F: drivers/staging/olpc_dcon/ STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER -M: Willy Tarreau +M: Willy Tarreau S: Odd Fixes F: drivers/staging/panel/ diff --git a/drivers/staging/panel/TODO b/drivers/staging/panel/TODO index 2db3f994b632..3a6405ab91e0 100644 --- a/drivers/staging/panel/TODO +++ b/drivers/staging/panel/TODO @@ -5,4 +5,4 @@ TODO: - see if all of this could be easier done in userspace instead. Please send patches to Greg Kroah-Hartman and -Willy Tarreau +Willy Tarreau -- cgit From 7a725972e212c165c7991d06ede952d4c3b6387a Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:32:03 +0100 Subject: Staging: panel: Remove space No space is necessary after a cast, therefore remove it. Found by checkpatch.pl Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 1e67e26a9e0c..04d86f3d8e12 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -1805,7 +1805,7 @@ static void phys_scan_contacts(void) w_dtr(pprt, oldval & ~bitval); /* enable this output */ bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; - phys_read |= (pmask_t) bitmask << (5 * bit); + phys_read |= (pmask_t)bitmask << (5 * bit); } w_dtr(pprt, oldval); /* disable all outputs */ } -- cgit From d938e1eb2fa9c23ea643e03b1834b6ad5b03805f Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:39:49 +0100 Subject: Staging: panel: Use u8 type Declare om, im, omask and imask as u8 to remove any confusion if that describes the 8 bits of the data bus on the parallel port. Also change return type of lcd_write_data() to u8. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 04d86f3d8e12..8bc604d83541 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2042,11 +2042,11 @@ static void init_scan_timer(void) * corresponding to out and in bits respectively. * returns 1 if ok, 0 if error (in which case, nothing is written). */ -static int input_name2mask(const char *name, pmask_t *mask, pmask_t *value, - char *imask, char *omask) +static u8 input_name2mask(const char *name, pmask_t *mask, pmask_t *value, + u8 *imask, u8 *omask) { static char sigtab[10] = "EeSsPpAaBb"; - char im, om; + u8 im, om; pmask_t m, v; om = 0ULL; -- cgit From 35fe0872846efa50b85900542a27694c69c82405 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:40:58 +0100 Subject: Staging: panel: Remove typedef pmask_t Use __u64 instead of pmask_t and remove pmask_t since is useless. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 8bc604d83541..7138ee7d217a 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -172,8 +172,6 @@ static __u8 scan_mask_o; /* logical or of the input bits involved in the scan matrix */ static __u8 scan_mask_i; -typedef __u64 pmask_t; - enum input_type { INPUT_TYPE_STD, INPUT_TYPE_KBD, @@ -188,8 +186,8 @@ enum input_state { struct logical_input { struct list_head list; - pmask_t mask; - pmask_t value; + __u64 mask; + __u64 value; enum input_type type; enum input_state state; __u8 rise_time, fall_time; @@ -219,19 +217,19 @@ static LIST_HEAD(logical_inputs); /* list of all defined logical inputs */ * corresponds to the ground. * Within each group, bits are stored in the same order as read on the port : * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0). - * So, each __u64 (or pmask_t) is represented like this : + * So, each __u64 is represented like this : * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE * <-----unused------> */ /* what has just been read from the I/O ports */ -static pmask_t phys_read; +static __u64 phys_read; /* previous phys_read */ -static pmask_t phys_read_prev; +static __u64 phys_read_prev; /* stabilized phys_read (phys_read|phys_read_prev) */ -static pmask_t phys_curr; +static __u64 phys_curr; /* previous phys_curr */ -static pmask_t phys_prev; +static __u64 phys_prev; /* 0 means that at least one logical signal needs be computed */ static char inputs_stable; @@ -1789,7 +1787,7 @@ static void phys_scan_contacts(void) gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; /* grounded inputs are signals 40-44 */ - phys_read |= (pmask_t)gndmask << 40; + phys_read |= (__u64)gndmask << 40; if (bitmask != gndmask) { /* @@ -1805,7 +1803,7 @@ static void phys_scan_contacts(void) w_dtr(pprt, oldval & ~bitval); /* enable this output */ bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; - phys_read |= (pmask_t)bitmask << (5 * bit); + phys_read |= (__u64)bitmask << (5 * bit); } w_dtr(pprt, oldval); /* disable all outputs */ } @@ -2042,12 +2040,12 @@ static void init_scan_timer(void) * corresponding to out and in bits respectively. * returns 1 if ok, 0 if error (in which case, nothing is written). */ -static u8 input_name2mask(const char *name, pmask_t *mask, pmask_t *value, +static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, u8 *imask, u8 *omask) { static char sigtab[10] = "EeSsPpAaBb"; u8 im, om; - pmask_t m, v; + __u64 m, v; om = 0ULL; im = 0ULL; -- cgit From d12f27e8b2abc1efe9156ff403f4fa6eae4268df Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:42:26 +0100 Subject: Staging: panel: Remove ULL Remove ULL on om and im, since it's useless. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index 7138ee7d217a..e9641ea7e477 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2047,8 +2047,8 @@ static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, u8 im, om; __u64 m, v; - om = 0ULL; - im = 0ULL; + om = 0; + im = 0; m = 0ULL; v = 0ULL; while (*name) { -- cgit From 52ebf93f367f3b749a696dc77ac2e42c186eb924 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:43:27 +0100 Subject: Staging: panel: Reduce value range for *name out is 0-9 so it's too much for om, therefore reduce value range for *name from '0'-'9' to '0'-'7'. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index e9641ea7e477..fcfcda7ff1f4 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2065,7 +2065,7 @@ static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, im |= BIT(in); name++; - if (isdigit(*name)) { + if (*name >= '0' && *name <= '7') { out = *name - '0'; om |= BIT(out); } else if (*name == '-') { -- cgit From 8aa7307b7802cb765fcc11305db3fdeee0920658 Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Sun, 3 Jan 2016 20:44:44 +0100 Subject: Staging: panel: Make code more readable Repace 'for' statement by strchr() function to make code more readable. Signed-off-by: Ksenija Stanojevic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index fcfcda7ff1f4..1219ff7884f8 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -2043,7 +2043,7 @@ static void init_scan_timer(void) static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, u8 *imask, u8 *omask) { - static char sigtab[10] = "EeSsPpAaBb"; + const char sigtab[] = "EeSsPpAaBb"; u8 im, om; __u64 m, v; @@ -2053,13 +2053,13 @@ static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, v = 0ULL; while (*name) { int in, out, bit, neg; + const char *idx; - for (in = 0; (in < sizeof(sigtab)) && (sigtab[in] != *name); - in++) - ; - - if (in >= sizeof(sigtab)) + idx = strchr(sigtab, *name); + if (!idx) return 0; /* input name not found */ + + in = idx - sigtab; neg = (in & 1); /* odd (lower) names are negated */ in >>= 1; im |= BIT(in); -- cgit From 6590faaba4008d84806bf4b570db2e885e3d9e99 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 16 Dec 2015 13:42:41 +0800 Subject: ALSA: hda - hdmi begin to support dynamic PCM assignment Begin to support dynamic PCM assignment to pin in hdmi audio driver. This means PCM will not be statically bound with pin. When there is a monitor connected, the corresponding pin will try to find a proper PCM to bind. When the monitor is disconnected, the corresponding pin will unbind the PCM. This helps to reduce the PCM number when there are many pins (device entries in DP MST mode) and only a few of them work at the same time. This patch adds the pcm member in struct hdmi_spec_per_pin. When PCM is dynamically bound to the pin, the member pcm will pointer to the corresponding pcm_rec[] in hdmi_spec, which means the hda_pcm is bound to the pin. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 426a29a1c19b..aa7bd3f58129 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -86,6 +86,7 @@ struct hdmi_spec_per_pin { struct delayed_work work; struct snd_kcontrol *eld_ctl; struct snd_jack *acomp_jack; /* jack via audio component */ + struct hda_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ int repoll_count; bool setup; /* the stream has been set up by prepare callback */ int channels; /* current number of channels */ @@ -144,7 +145,7 @@ struct hdmi_spec { struct hdmi_ops ops; bool dyn_pin_out; - + bool dyn_pcm_assign; /* * Non-generic VIA/NVIDIA specific */ @@ -389,13 +390,16 @@ static int hinfo_to_pin_index(struct hda_codec *codec, struct hda_pcm_stream *hinfo) { struct hdmi_spec *spec = codec->spec; + struct hdmi_spec_per_pin *per_pin; int pin_idx; - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) - if (get_pcm_rec(spec, pin_idx)->stream == hinfo) + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + per_pin = get_pin(spec, pin_idx); + if (per_pin->pcm && per_pin->pcm->stream == hinfo) return pin_idx; + } - codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo); + codec_dbg(codec, "HDMI: hinfo %p not registered\n", hinfo); return -EINVAL; } @@ -2116,6 +2120,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, static int generic_hdmi_build_pcms(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; + struct hdmi_spec_per_pin *per_pin; int pin_idx; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { @@ -2125,6 +2130,10 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx); if (!info) return -ENOMEM; + if (!spec->dyn_pcm_assign) { + per_pin = get_pin(spec, pin_idx); + per_pin->pcm = info; + } spec->pcm_rec[pin_idx] = info; info->pcm_type = HDA_PCM_TYPE_HDMI; info->own_chmap = true; -- cgit From 42b2987079eca0238b576c08af1144ed5bd52188 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 16 Dec 2015 13:42:42 +0800 Subject: ALSA: hda - hdmi playback without monitor in dynamic pcm bind mode Pulseaudio requires open pcm successfully when probing. This patch handles playback without monitor in dynamic pcm assignment mode. It tries to open/prepare/close pcm successfully even there is no pin bound to the PCM. On the meantime, it will try to find a proper converter for the PCM. As pcm is This patch introduces a pcm_lock in struct hdmi_spec. This lock is used to protect: 1. the variables in struct hdmi_spec; 2. other variables shared for dynamic pcm assignment mode 3. device entry selection. As each device entry is represented by a separate struct struct hdmi_spec_per_pin, the lock in per_pin is not enough. Please see details below. MST audio device entry operation: 1. select device entry on the pin 2. operate on the pin nid Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 171 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 157 insertions(+), 14 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index aa7bd3f58129..ea1e90aa299c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -139,6 +139,7 @@ struct hdmi_spec { int num_pins; struct snd_array pins; /* struct hdmi_spec_per_pin */ struct hda_pcm *pcm_rec[16]; + struct mutex pcm_lock; unsigned int channels_max; /* max over all cvts */ struct hdmi_eld temp_eld; @@ -1341,6 +1342,11 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, return 0; } +/* Try to find an available converter + * If pin_idx is less then zero, just try to find an available converter. + * Otherwise, try to find an available converter and get the cvt mux index + * of the pin. + */ static int hdmi_choose_cvt(struct hda_codec *codec, int pin_idx, int *cvt_id, int *mux_id) { @@ -1349,7 +1355,11 @@ static int hdmi_choose_cvt(struct hda_codec *codec, struct hdmi_spec_per_cvt *per_cvt = NULL; int cvt_idx, mux_idx = 0; - per_pin = get_pin(spec, pin_idx); + /* pin_idx < 0 means no pin will be bound to the converter */ + if (pin_idx < 0) + per_pin = NULL; + else + per_pin = get_pin(spec, pin_idx); /* Dynamically assign converter to stream */ for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { @@ -1358,6 +1368,8 @@ static int hdmi_choose_cvt(struct hda_codec *codec, /* Must not already be assigned */ if (per_cvt->assigned) continue; + if (per_pin == NULL) + break; /* Must be in pin's mux's list of converters */ for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) if (per_pin->mux_nids[mux_idx] == per_cvt->cvt_nid) @@ -1370,9 +1382,10 @@ static int hdmi_choose_cvt(struct hda_codec *codec, /* No free converters */ if (cvt_idx == spec->num_cvts) - return -ENODEV; + return -EBUSY; - per_pin->mux_idx = mux_idx; + if (per_pin != NULL) + per_pin->mux_idx = mux_idx; if (cvt_id) *cvt_id = cvt_idx; @@ -1398,6 +1411,20 @@ static void intel_verify_pin_cvt_connect(struct hda_codec *codec, mux_idx); } +/* get the mux index for the converter of the pins + * converter's mux index is the same for all pins on Intel platform + */ +static int intel_cvt_id_to_mux_idx(struct hdmi_spec *spec, + hda_nid_t cvt_nid) +{ + int i; + + for (i = 0; i < spec->num_cvts; i++) + if (spec->cvt_nids[i] == cvt_nid) + return i; + return -EINVAL; +} + /* Intel HDMI workaround to fix audio routing issue: * For some Intel display codecs, pins share the same connection list. * So a conveter can be selected by multiple pins and playback on any of these @@ -1449,6 +1476,69 @@ static void intel_not_share_assigned_cvt(struct hda_codec *codec, } } +/* A wrapper of intel_not_share_asigned_cvt() */ +static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec, + hda_nid_t pin_nid, hda_nid_t cvt_nid) +{ + 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 + * share the converter. + */ + mux_idx = intel_cvt_id_to_mux_idx(spec, cvt_nid); + if (mux_idx >= 0) + intel_not_share_assigned_cvt(codec, pin_nid, mux_idx); +} + +/* called in hdmi_pcm_open when no pin is assigned to the PCM + * in dyn_pcm_assign mode. + */ +static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct hdmi_spec *spec = codec->spec; + struct snd_pcm_runtime *runtime = substream->runtime; + int cvt_idx; + struct hdmi_spec_per_cvt *per_cvt = NULL; + int err; + + err = hdmi_choose_cvt(codec, -1, &cvt_idx, NULL); + if (err) + return err; + + per_cvt = get_cvt(spec, cvt_idx); + per_cvt->assigned = 1; + hinfo->nid = per_cvt->cvt_nid; + + intel_not_share_assigned_cvt_nid(codec, 0, per_cvt->cvt_nid); + + /* todo: setup spdif ctls assign */ + + /* Initially set the converter's capabilities */ + hinfo->channels_min = per_cvt->channels_min; + hinfo->channels_max = per_cvt->channels_max; + hinfo->rates = per_cvt->rates; + hinfo->formats = per_cvt->formats; + hinfo->maxbps = per_cvt->maxbps; + + /* Store the updated parameters */ + runtime->hw.channels_min = hinfo->channels_min; + runtime->hw.channels_max = hinfo->channels_max; + runtime->hw.formats = hinfo->formats; + runtime->hw.rates = hinfo->rates; + + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, 2); + return 0; +} + /* * HDA PCM callbacks */ @@ -1465,19 +1555,36 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, int err; /* Validate hinfo */ + mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (snd_BUG_ON(pin_idx < 0)) - return -EINVAL; - per_pin = get_pin(spec, pin_idx); - eld = &per_pin->sink_eld; + if (!spec->dyn_pcm_assign) { + if (snd_BUG_ON(pin_idx < 0)) { + mutex_unlock(&spec->pcm_lock); + return -EINVAL; + } + } else { + /* no pin is assigned to the PCM + * PA need pcm open successfully when probe + */ + if (pin_idx < 0) { + err = hdmi_pcm_open_no_pin(hinfo, codec, substream); + mutex_unlock(&spec->pcm_lock); + return err; + } + } err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); - if (err < 0) + if (err < 0) { + mutex_unlock(&spec->pcm_lock); return err; + } per_cvt = get_cvt(spec, cvt_idx); /* Claim converter */ per_cvt->assigned = 1; + + + per_pin = get_pin(spec, pin_idx); per_pin->cvt_nid = per_cvt->cvt_nid; hinfo->nid = per_cvt->cvt_nid; @@ -1498,6 +1605,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, hinfo->formats = per_cvt->formats; hinfo->maxbps = per_cvt->maxbps; + eld = &per_pin->sink_eld; /* Restrict capabilities by ELD if this isn't disabled */ if (!static_hdmi_pcm && eld->eld_valid) { snd_hdmi_eld_update_pcm_info(&eld->info, hinfo); @@ -1506,10 +1614,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, per_cvt->assigned = 0; hinfo->nid = 0; snd_hda_spdif_ctls_unassign(codec, pin_idx); + mutex_unlock(&spec->pcm_lock); return -ENODEV; } } + mutex_unlock(&spec->pcm_lock); /* Store the updated parameters */ runtime->hw.channels_min = hinfo->channels_min; runtime->hw.channels_max = hinfo->channels_max; @@ -1854,13 +1964,34 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, { hda_nid_t cvt_nid = hinfo->nid; struct hdmi_spec *spec = codec->spec; - int pin_idx = hinfo_to_pin_index(codec, hinfo); - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); - hda_nid_t pin_nid = per_pin->pin_nid; + int pin_idx; + struct hdmi_spec_per_pin *per_pin; + hda_nid_t pin_nid; struct snd_pcm_runtime *runtime = substream->runtime; bool non_pcm; int pinctl; + int err; + + mutex_lock(&spec->pcm_lock); + pin_idx = hinfo_to_pin_index(codec, hinfo); + if (spec->dyn_pcm_assign && pin_idx < 0) { + /* when dyn_pcm_assign and pcm is not bound to a pin + * skip pin setup and return 0 to make audio playback + * be ongoing + */ + intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid); + snd_hda_codec_setup_stream(codec, cvt_nid, + stream_tag, 0, format); + mutex_unlock(&spec->pcm_lock); + return 0; + } + if (snd_BUG_ON(pin_idx < 0)) { + mutex_unlock(&spec->pcm_lock); + return -EINVAL; + } + 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 @@ -1885,7 +2016,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); mutex_unlock(&per_pin->lock); - if (spec->dyn_pin_out) { pinctl = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); @@ -1894,7 +2024,10 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, pinctl | PIN_OUT); } - return spec->ops.setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); + err = spec->ops.setup_stream(codec, cvt_nid, pin_nid, + stream_tag, format); + mutex_unlock(&spec->pcm_lock); + return err; } static int generic_hdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, @@ -1925,9 +2058,17 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_cvt->assigned = 0; hinfo->nid = 0; + mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (snd_BUG_ON(pin_idx < 0)) + if (spec->dyn_pcm_assign && pin_idx < 0) { + mutex_unlock(&spec->pcm_lock); + return 0; + } + + if (snd_BUG_ON(pin_idx < 0)) { + mutex_unlock(&spec->pcm_lock); return -EINVAL; + } per_pin = get_pin(spec, pin_idx); if (spec->dyn_pin_out) { @@ -1947,6 +2088,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_pin->setup = false; per_pin->channels = 0; mutex_unlock(&per_pin->lock); + mutex_unlock(&spec->pcm_lock); } return 0; @@ -2461,6 +2603,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) return -ENOMEM; spec->ops = generic_standard_hdmi_ops; + mutex_init(&spec->pcm_lock); codec->spec = spec; hdmi_array_init(spec, 4); -- cgit From 2bf3c85a5b167a6c87d9d7d655af85d85d51769b Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 16 Dec 2015 13:42:43 +0800 Subject: ALSA: hda - hdmi operate spdif based on pcm Currently, the driver operates the spdif based on pin. This is ok for the current driver as pcm is statically bound to the pin. However, if the driver uses dynamically pcm assignment, this will cause confusion for user space. The patch changes spdif operation from pin based to pcm based. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ea1e90aa299c..91c716541f61 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -140,6 +140,7 @@ struct hdmi_spec { struct snd_array pins; /* struct hdmi_spec_per_pin */ struct hda_pcm *pcm_rec[16]; struct mutex pcm_lock; + int pcm_used; /* counter of pcm_rec[] */ unsigned int channels_max; /* max over all cvts */ struct hdmi_eld temp_eld; @@ -387,6 +388,20 @@ static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid) return -EINVAL; } +static int hinfo_to_pcm_index(struct hda_codec *codec, + struct hda_pcm_stream *hinfo) +{ + struct hdmi_spec *spec = codec->spec; + int pcm_idx; + + for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) + if (get_pcm_rec(spec, pcm_idx)->stream == hinfo) + return pcm_idx; + + codec_warn(codec, "HDMI: hinfo %p not registered\n", hinfo); + return -EINVAL; +} + static int hinfo_to_pin_index(struct hda_codec *codec, struct hda_pcm_stream *hinfo) { @@ -1548,13 +1563,17 @@ 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, mux_idx = 0; + int pin_idx, cvt_idx, pcm_idx, mux_idx = 0; struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; struct hdmi_spec_per_cvt *per_cvt = NULL; int err; /* Validate hinfo */ + pcm_idx = hinfo_to_pcm_index(codec, hinfo); + if (pcm_idx < 0) + return -EINVAL; + mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); if (!spec->dyn_pcm_assign) { @@ -1596,7 +1615,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, if (is_haswell_plus(codec) || is_valleyview_plus(codec)) intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); - snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); + snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid); /* Initially set the converter's capabilities */ hinfo->channels_min = per_cvt->channels_min; @@ -1613,7 +1632,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, !hinfo->rates || !hinfo->formats) { per_cvt->assigned = 0; hinfo->nid = 0; - snd_hda_spdif_ctls_unassign(codec, pin_idx); + snd_hda_spdif_ctls_unassign(codec, pcm_idx); mutex_unlock(&spec->pcm_lock); return -ENODEV; } @@ -2043,12 +2062,15 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct hdmi_spec *spec = codec->spec; - int cvt_idx, pin_idx; + int cvt_idx, pin_idx, pcm_idx; struct hdmi_spec_per_cvt *per_cvt; struct hdmi_spec_per_pin *per_pin; int pinctl; if (hinfo->nid) { + pcm_idx = hinfo_to_pcm_index(codec, hinfo); + if (snd_BUG_ON(pcm_idx < 0)) + return -EINVAL; cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); if (snd_BUG_ON(cvt_idx < 0)) return -EINVAL; @@ -2079,7 +2101,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, pinctl & ~PIN_OUT); } - snd_hda_spdif_ctls_unassign(codec, pin_idx); + snd_hda_spdif_ctls_unassign(codec, pcm_idx); mutex_lock(&per_pin->lock); per_pin->chmap_set = false; @@ -2277,6 +2299,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) per_pin->pcm = info; } spec->pcm_rec[pin_idx] = info; + spec->pcm_used++; info->pcm_type = HDA_PCM_TYPE_HDMI; info->own_chmap = true; @@ -2353,6 +2376,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) HDA_PCM_TYPE_HDMI); if (err < 0) return err; + /* pin number is the same with pcm number so far */ snd_hda_spdif_ctls_unassign(codec, pin_idx); /* add control for ELD Bytes */ -- cgit From a76056f2e57ec2825d6ae4be016596dd37300750 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 16 Dec 2015 16:48:15 +0800 Subject: ALSA: hda - hdmi dynamically bind PCM to pin when monitor hotplug Dynamically bind/unbind the PCM to pin when HDMI/DP monitor hotplug. When monitor is connected, find a proper PCM for the monitor. When monitor is disconnected, unbind the PCM from the pin. The binding policy (use Intel platform as example) is: 1. Try to use the legacy pin-pcm mapping for the device entry 0 of the pin. 2. If step 1 fails, try to bind pin to the backup PCMs. For example, on Intel platform, if DP MST is enabled, 5 PCMs will be created. PCM 3, PCM 7, PCM 8 are supposed to be used by device entry 0 of pin 5, pin 6 and pin 7. PCM 9 and PCM 10 are the backup PCMs. 3. If step 2 fails, try to find any PCM to bind to the pin. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 82 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 91c716541f61..6cf25eedf482 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -75,6 +75,8 @@ struct hdmi_spec_per_cvt { struct hdmi_spec_per_pin { hda_nid_t pin_nid; + /* pin idx, different device entries on the same pin use the same idx */ + int pin_nid_idx; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; int mux_idx; @@ -87,6 +89,7 @@ struct hdmi_spec_per_pin { struct snd_kcontrol *eld_ctl; struct snd_jack *acomp_jack; /* jack via audio component */ struct hda_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ + int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ int repoll_count; bool setup; /* the stream has been set up by prepare callback */ int channels; /* current number of channels */ @@ -140,6 +143,8 @@ struct hdmi_spec { struct snd_array pins; /* struct hdmi_spec_per_pin */ struct hda_pcm *pcm_rec[16]; struct mutex pcm_lock; + /* pcm_bitmap means which pcms have been assigned to pins*/ + unsigned long pcm_bitmap; int pcm_used; /* counter of pcm_rec[] */ unsigned int channels_max; /* max over all cvts */ @@ -1673,6 +1678,60 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } +static int hdmi_find_pcm_slot(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin) +{ + int i; + + /* try the prefer PCM */ + if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) + return per_pin->pin_nid_idx; + + /* have a second try; check the "reserved area" over num_pins */ + for (i = spec->num_pins; i < spec->pcm_used; i++) { + if (!test_bit(i, &spec->pcm_bitmap)) + return i; + } + + /* the last try; check the empty slots in pins */ + for (i = 0; i < spec->num_pins; i++) { + if (!test_bit(i, &spec->pcm_bitmap)) + return i; + } + return -EBUSY; +} + +static void hdmi_attach_hda_pcm(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin) +{ + int idx; + + /* pcm already be attached to the pin */ + if (per_pin->pcm) + return; + idx = hdmi_find_pcm_slot(spec, per_pin); + if (idx == -ENODEV) + return; + per_pin->pcm_idx = idx; + per_pin->pcm = spec->pcm_rec[idx]; + set_bit(idx, &spec->pcm_bitmap); +} + +static void hdmi_detach_hda_pcm(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin) +{ + int idx; + + /* pcm already be detached from the pin */ + if (!per_pin->pcm) + return; + idx = per_pin->pcm_idx; + per_pin->pcm_idx = -1; + per_pin->pcm = NULL; + if (idx >= 0 && idx < spec->pcm_used) + clear_bit(idx, &spec->pcm_bitmap); +} + /* update per_pin ELD from the given new ELD; * setup info frame and notification accordingly */ @@ -1681,9 +1740,17 @@ static void update_eld(struct hda_codec *codec, struct hdmi_eld *eld) { struct hdmi_eld *pin_eld = &per_pin->sink_eld; + struct hdmi_spec *spec = codec->spec; bool old_eld_valid = pin_eld->eld_valid; bool eld_changed; + if (spec->dyn_pcm_assign) { + if (eld->eld_valid) + hdmi_attach_hda_pcm(spec, per_pin); + else + hdmi_detach_hda_pcm(spec, per_pin); + } + if (eld->eld_valid) snd_hdmi_show_eld(codec, &eld->info); @@ -1827,13 +1894,19 @@ static void sync_eld_via_acomp(struct hda_codec *codec, static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { struct hda_codec *codec = per_pin->codec; + struct hdmi_spec *spec = codec->spec; + int ret; + mutex_lock(&spec->pcm_lock); if (codec_has_acomp(codec)) { sync_eld_via_acomp(codec, per_pin); - return false; /* don't call snd_hda_jack_report_sync() */ + ret = false; /* don't call snd_hda_jack_report_sync() */ } else { - return hdmi_present_sense_via_verbs(per_pin, repoll); + ret = hdmi_present_sense_via_verbs(per_pin, repoll); } + mutex_unlock(&spec->pcm_lock); + + return ret; } static void hdmi_repoll_eld(struct work_struct *work) @@ -1877,6 +1950,11 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) per_pin->pin_nid = pin_nid; per_pin->non_pcm = false; + if (spec->dyn_pcm_assign) + per_pin->pcm_idx = -1; + else + per_pin->pcm_idx = pin_idx; + per_pin->pin_nid_idx = pin_idx; err = hdmi_read_pin_conn(codec, pin_idx); if (err < 0) -- cgit From ac98379a751e37ba9e5622f9519d9469498572c1 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 16 Dec 2015 16:48:16 +0800 Subject: ALSA: hda - hdmi setup pin when monitor hotplug in pcm dynamic assignment mode Setup pin configuration when monitor is hotplugged in pcm dynamic assignment if the PCM is in open state. When monitor is disconnect, The pin will be reset. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 87 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6cf25eedf482..796d737366ae 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -146,6 +146,11 @@ struct hdmi_spec { /* pcm_bitmap means which pcms have been assigned to pins*/ unsigned long pcm_bitmap; int pcm_used; /* counter of pcm_rec[] */ + /* bitmap shows whether the pcm is opened in user space + * bit 0 means the first playback PCM (PCM3); + * bit 1 means the second playback PCM, and so on. + */ + unsigned long pcm_in_use; unsigned int channels_max; /* max over all cvts */ struct hdmi_eld temp_eld; @@ -1525,10 +1530,14 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, { struct hdmi_spec *spec = codec->spec; struct snd_pcm_runtime *runtime = substream->runtime; - int cvt_idx; + int cvt_idx, pcm_idx; struct hdmi_spec_per_cvt *per_cvt = NULL; int err; + pcm_idx = hinfo_to_pcm_index(codec, hinfo); + if (pcm_idx < 0) + return -EINVAL; + err = hdmi_choose_cvt(codec, -1, &cvt_idx, NULL); if (err) return err; @@ -1539,6 +1548,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, intel_not_share_assigned_cvt_nid(codec, 0, per_cvt->cvt_nid); + set_bit(pcm_idx, &spec->pcm_in_use); /* todo: setup spdif ctls assign */ /* Initially set the converter's capabilities */ @@ -1607,7 +1617,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, /* Claim converter */ per_cvt->assigned = 1; - + set_bit(pcm_idx, &spec->pcm_in_use); per_pin = get_pin(spec, pin_idx); per_pin->cvt_nid = per_cvt->cvt_nid; hinfo->nid = per_cvt->cvt_nid; @@ -1732,6 +1742,71 @@ static void hdmi_detach_hda_pcm(struct hdmi_spec *spec, clear_bit(idx, &spec->pcm_bitmap); } +static int hdmi_get_pin_cvt_mux(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin, hda_nid_t cvt_nid) +{ + int mux_idx; + + for (mux_idx = 0; mux_idx < per_pin->num_mux_nids; mux_idx++) + if (per_pin->mux_nids[mux_idx] == cvt_nid) + break; + return mux_idx; +} + +static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid); + +static void hdmi_pcm_setup_pin(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin) +{ + struct hda_codec *codec = per_pin->codec; + struct hda_pcm *pcm; + struct hda_pcm_stream *hinfo; + struct snd_pcm_substream *substream; + int mux_idx; + bool non_pcm; + + if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used) + pcm = spec->pcm_rec[per_pin->pcm_idx]; + else + return; + if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use)) + return; + + /* hdmi audio only uses playback and one substream */ + hinfo = pcm->stream; + substream = pcm->pcm->streams[0].substream; + + per_pin->cvt_nid = hinfo->nid; + + mux_idx = hdmi_get_pin_cvt_mux(spec, per_pin, hinfo->nid); + if (mux_idx < per_pin->num_mux_nids) + snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, + AC_VERB_SET_CONNECT_SEL, + mux_idx); + snd_hda_spdif_ctls_assign(codec, per_pin->pcm_idx, hinfo->nid); + + non_pcm = check_non_pcm_per_cvt(codec, hinfo->nid); + if (substream->runtime) + per_pin->channels = substream->runtime->channels; + per_pin->setup = true; + per_pin->mux_idx = mux_idx; + + hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); +} + +static void hdmi_pcm_reset_pin(struct hdmi_spec *spec, + struct hdmi_spec_per_pin *per_pin) +{ + if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used) + snd_hda_spdif_ctls_unassign(per_pin->codec, per_pin->pcm_idx); + + per_pin->chmap_set = false; + memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); + + per_pin->setup = false; + per_pin->channels = 0; +} + /* update per_pin ELD from the given new ELD; * setup info frame and notification accordingly */ @@ -1745,10 +1820,13 @@ static void update_eld(struct hda_codec *codec, bool eld_changed; if (spec->dyn_pcm_assign) { - if (eld->eld_valid) + if (eld->eld_valid) { hdmi_attach_hda_pcm(spec, per_pin); - else + hdmi_pcm_setup_pin(spec, per_pin); + } else { + hdmi_pcm_reset_pin(spec, per_pin); hdmi_detach_hda_pcm(spec, per_pin); + } } if (eld->eld_valid) @@ -2159,6 +2237,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, hinfo->nid = 0; mutex_lock(&spec->pcm_lock); + clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); if (spec->dyn_pcm_assign && pin_idx < 0) { mutex_unlock(&spec->pcm_lock); -- cgit From 463c35fb7981acedef5e98fe8252bfaaa91dd74c Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Tue, 12 Jan 2016 11:13:25 +0800 Subject: ALSA: Add documentation about HD-audio DP MST Add the documentation about HD-audio DP MST: 1. Overview 2. Jack Others will be added later. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt diff --git a/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt b/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt new file mode 100644 index 000000000000..82744ac3513d --- /dev/null +++ b/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt @@ -0,0 +1,74 @@ +To support DP MST audio, HD Audio hdmi codec driver introduces virtual pin +and dynamic pcm assignment. + +Virtual pin is an extension of per_pin. The most difference of DP MST +from legacy is that DP MST introduces device entry. Each pin can contain +several device entries. Each device entry behaves as a pin. + +As each pin may contain several device entries and each codec may contain +several pins, if we use one pcm per per_pin, there will be many PCMs. +The new solution is to create a few PCMs and to dynamically bind pcm to +per_pin. Driver uses spec->dyn_pcm_assign flag to indicate whether to use +the new solution. + +PCM +=== +To be added + + +Jack +==== + +Presume: + - MST must be dyn_pcm_assign, and it is acomp (for Intel scenario); + - NON-MST may or may not be dyn_pcm_assign, it can be acomp or !acomp; + +So there are the following scenarios: + a. MST (&& dyn_pcm_assign && acomp) + b. NON-MST && dyn_pcm_assign && acomp + c. NON-MST && !dyn_pcm_assign && !acomp + +Below discussion will ignore MST and NON-MST difference as it doesn't +impact on jack handling too much. + +Driver uses struct hdmi_pcm pcm[] array in hdmi_spec and snd_jack is +a member of hdmi_pcm. Each pin has one struct hdmi_pcm * pcm pointer. + +For !dyn_pcm_assign, per_pin->pcm will assigned to spec->pcm[n] statically. + +For dyn_pcm_assign, per_pin->pcm will assigned to spec->pcm[n] +when monitor is hotplugged. + + +Build Jack +---------- + +- dyn_pcm_assign +Will not use hda_jack but use snd_jack in spec->pcm_rec[pcm_idx].jack directly. + +- !dyn_pcm_assign +Use hda_jack and assign spec->pcm_rec[pcm_idx].jack = jack->jack statically. + + +Unsolicited Event Enabling +-------------------------- +Enable unsolicited event if !acomp. + + +Monitor Hotplug Event Handling +------------------------------ +- acomp +pin_eld_notify() -> check_presence_and_report() -> hdmi_present_sense() -> +sync_eld_via_acomp(). +Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for +both dyn_pcm_assign and !dyn_pcm_assign + +- !acomp +Hdmi_unsol_event() -> hdmi_intrinsic_event() -> check_presence_and_report() -> +hdmi_present_sense() -> hdmi_prepsent_sense_via_verbs() +Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for dyn_pcm_assign. +Use hda_jack mechanism to handle jack events. + + +Others to be added later +======================== -- cgit From 2bea241a03ab67fc841c626c25f09108ffda7a35 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Tue, 12 Jan 2016 11:13:26 +0800 Subject: ALSA: hda - add hdmi_pcm to manage hdmi pcm related features Use struct hdmi_pcm wrapper for hdmi pcm management. All PCM related features, like jack, will be put in this structure. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 796d737366ae..d922fe833a31 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -88,7 +88,7 @@ struct hdmi_spec_per_pin { struct delayed_work work; struct snd_kcontrol *eld_ctl; struct snd_jack *acomp_jack; /* jack via audio component */ - struct hda_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ + struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ int repoll_count; bool setup; /* the stream has been set up by prepare callback */ @@ -134,6 +134,11 @@ struct hdmi_ops { int (*chmap_validate)(int ca, int channels, unsigned char *chmap); }; +struct hdmi_pcm { + struct hda_pcm *pcm; + struct snd_jack *jack; +}; + struct hdmi_spec { int num_cvts; struct snd_array cvts; /* struct hdmi_spec_per_cvt */ @@ -141,7 +146,7 @@ struct hdmi_spec { int num_pins; struct snd_array pins; /* struct hdmi_spec_per_pin */ - struct hda_pcm *pcm_rec[16]; + struct hdmi_pcm pcm_rec[16]; struct mutex pcm_lock; /* pcm_bitmap means which pcms have been assigned to pins*/ unsigned long pcm_bitmap; @@ -383,7 +388,10 @@ static struct cea_channel_speaker_allocation channel_allocations[] = { ((struct hdmi_spec_per_pin *)snd_array_elem(&spec->pins, idx)) #define get_cvt(spec, idx) \ ((struct hdmi_spec_per_cvt *)snd_array_elem(&spec->cvts, idx)) -#define get_pcm_rec(spec, idx) ((spec)->pcm_rec[idx]) +/* obtain hdmi_pcm object assigned to idx */ +#define get_hdmi_pcm(spec, idx) (&(spec)->pcm_rec[idx]) +/* obtain hda_pcm object assigned to idx */ +#define get_pcm_rec(spec, idx) (get_hdmi_pcm(spec, idx)->pcm) static int pin_nid_to_pin_index(struct hda_codec *codec, hda_nid_t pin_nid) { @@ -421,7 +429,8 @@ static int hinfo_to_pin_index(struct hda_codec *codec, for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { per_pin = get_pin(spec, pin_idx); - if (per_pin->pcm && per_pin->pcm->stream == hinfo) + if (per_pin->pcm && + per_pin->pcm->pcm->stream == hinfo) return pin_idx; } @@ -1723,7 +1732,7 @@ static void hdmi_attach_hda_pcm(struct hdmi_spec *spec, if (idx == -ENODEV) return; per_pin->pcm_idx = idx; - per_pin->pcm = spec->pcm_rec[idx]; + per_pin->pcm = get_hdmi_pcm(spec, idx); set_bit(idx, &spec->pcm_bitmap); } @@ -1766,7 +1775,7 @@ static void hdmi_pcm_setup_pin(struct hdmi_spec *spec, bool non_pcm; if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used) - pcm = spec->pcm_rec[per_pin->pcm_idx]; + pcm = get_pcm_rec(spec, per_pin->pcm_idx); else return; if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use)) @@ -2030,8 +2039,10 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) per_pin->non_pcm = false; if (spec->dyn_pcm_assign) per_pin->pcm_idx = -1; - else + else { + per_pin->pcm = get_hdmi_pcm(spec, pin_idx); per_pin->pcm_idx = pin_idx; + } per_pin->pin_nid_idx = pin_idx; err = hdmi_read_pin_conn(codec, pin_idx); @@ -2441,7 +2452,6 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, static int generic_hdmi_build_pcms(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin; int pin_idx; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { @@ -2451,11 +2461,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) info = snd_hda_codec_pcm_new(codec, "HDMI %d", pin_idx); if (!info) return -ENOMEM; - if (!spec->dyn_pcm_assign) { - per_pin = get_pin(spec, pin_idx); - per_pin->pcm = info; - } - spec->pcm_rec[pin_idx] = info; + + spec->pcm_rec[pin_idx].pcm = info; spec->pcm_used++; info->pcm_type = HDA_PCM_TYPE_HDMI; info->own_chmap = true; @@ -2538,7 +2545,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) /* add control for ELD Bytes */ err = hdmi_create_eld_ctl(codec, pin_idx, - get_pcm_rec(spec, pin_idx)->device); + get_pcm_rec(spec, pin_idx)->device); if (err < 0) return err; @@ -2553,7 +2560,7 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) struct snd_kcontrol *kctl; int i; - pcm = spec->pcm_rec[pin_idx]; + pcm = get_pcm_rec(spec, pin_idx); if (!pcm || !pcm->pcm) break; err = snd_pcm_add_chmap_ctls(pcm->pcm, @@ -2859,7 +2866,7 @@ static int simple_playback_build_pcms(struct hda_codec *codec) info = snd_hda_codec_pcm_new(codec, "HDMI 0"); if (!info) return -ENOMEM; - spec->pcm_rec[0] = info; + spec->pcm_rec[0].pcm = info; info->pcm_type = HDA_PCM_TYPE_HDMI; pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; *pstr = spec->pcm_playback; -- cgit From 25e4abb33df3aafa7d1efba8f82f9178268efab1 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Tue, 12 Jan 2016 11:13:27 +0800 Subject: ALSA: hda - hdmi jack created based on pcm Jack is created based on pcm. Apply the acomp jack rule to dyn_pcm_assign. For dyn_pcm_assign: Driver does not use hda_jack. It operates snd_jack directly. snd_jack pointer will be stored in spec->pcm.jack instead of the current spec->acomp_jack. When pcm is assigned to pin, jack will be assigned to pin automatically. For !dyn_pcm_assign: Driver continues using hda_jack for less impact on the old cases. Pcm is statically assigned to pin. So is jack. spec->pcm.jack saves the snd_jack pointer created in hda_jack. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 93 +++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d922fe833a31..c8b11dadbd2a 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -87,7 +87,6 @@ struct hdmi_spec_per_pin { struct mutex lock; struct delayed_work work; struct snd_kcontrol *eld_ctl; - struct snd_jack *acomp_jack; /* jack via audio component */ struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ int repoll_count; @@ -1948,6 +1947,7 @@ static void sync_eld_via_acomp(struct hda_codec *codec, { struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; + struct snd_jack *jack = NULL; int size; mutex_lock(&per_pin->lock); @@ -1971,8 +1971,17 @@ static void sync_eld_via_acomp(struct hda_codec *codec, eld->eld_size = 0; } + /* pcm_idx >=0 before update_eld() means it is in monitor + * disconnected event. Jack must be fetched before update_eld() + */ + if (per_pin->pcm_idx >= 0) + jack = spec->pcm_rec[per_pin->pcm_idx].jack; update_eld(codec, per_pin, eld); - snd_jack_report(per_pin->acomp_jack, + if (jack == NULL && per_pin->pcm_idx >= 0) + jack = spec->pcm_rec[per_pin->pcm_idx].jack; + if (jack == NULL) + goto unlock; + snd_jack_report(jack, eld->monitor_present ? SND_JACK_AVOUT : 0); unlock: mutex_unlock(&per_pin->lock); @@ -2476,15 +2485,16 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) return 0; } -static void free_acomp_jack_priv(struct snd_jack *jack) +static void free_hdmi_jack_priv(struct snd_jack *jack) { - struct hdmi_spec_per_pin *per_pin = jack->private_data; + struct hdmi_pcm *pcm = jack->private_data; - per_pin->acomp_jack = NULL; + pcm->jack = NULL; } -static int add_acomp_jack_kctl(struct hda_codec *codec, - struct hdmi_spec_per_pin *per_pin, +static int add_hdmi_jack_kctl(struct hda_codec *codec, + struct hdmi_spec *spec, + int pcm_idx, const char *name) { struct snd_jack *jack; @@ -2494,45 +2504,68 @@ static int add_acomp_jack_kctl(struct hda_codec *codec, true, false); if (err < 0) return err; - per_pin->acomp_jack = jack; - jack->private_data = per_pin; - jack->private_free = free_acomp_jack_priv; + + spec->pcm_rec[pcm_idx].jack = jack; + jack->private_data = &spec->pcm_rec[pcm_idx]; + jack->private_free = free_hdmi_jack_priv; return 0; } -static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) +static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) { char hdmi_str[32] = "HDMI/DP"; struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); - int pcmdev = get_pcm_rec(spec, pin_idx)->device; + struct hdmi_spec_per_pin *per_pin; + struct hda_jack_tbl *jack; + int pcmdev = get_pcm_rec(spec, pcm_idx)->device; bool phantom_jack; + int ret; if (pcmdev > 0) sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); - if (codec_has_acomp(codec)) - return add_acomp_jack_kctl(codec, per_pin, hdmi_str); + + if (spec->dyn_pcm_assign) + return add_hdmi_jack_kctl(codec, spec, pcm_idx, hdmi_str); + + /* for !dyn_pcm_assign, we still use hda_jack for compatibility */ + /* if !dyn_pcm_assign, it must be non-MST mode. + * This means pcms and pins are statically mapped. + * And pcm_idx is pin_idx. + */ + per_pin = get_pin(spec, pcm_idx); phantom_jack = !is_jack_detectable(codec, per_pin->pin_nid); if (phantom_jack) strncat(hdmi_str, " Phantom", sizeof(hdmi_str) - strlen(hdmi_str) - 1); - - return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, - phantom_jack); + ret = snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, + phantom_jack); + if (ret < 0) + return ret; + jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + if (jack == NULL) + return 0; + /* assign jack->jack to pcm_rec[].jack to + * align with dyn_pcm_assign mode + */ + spec->pcm_rec[pcm_idx].jack = jack->jack; + return 0; } static int generic_hdmi_build_controls(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; int err; - int pin_idx; + int pin_idx, pcm_idx; - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); - err = generic_hdmi_build_jack(codec, pin_idx); + for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { + err = generic_hdmi_build_jack(codec, pcm_idx); if (err < 0) return err; + } + + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); err = snd_hda_create_dig_out_ctls(codec, per_pin->pin_nid, @@ -2631,18 +2664,25 @@ static void hdmi_array_free(struct hdmi_spec *spec) static void generic_hdmi_free(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; - int pin_idx; + int pin_idx, pcm_idx; if (codec_has_acomp(codec)) snd_hdac_i915_register_notifier(NULL); for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); - cancel_delayed_work_sync(&per_pin->work); eld_proc_free(per_pin); - if (per_pin->acomp_jack) - snd_device_free(codec->card, per_pin->acomp_jack); + } + + for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { + if (spec->pcm_rec[pcm_idx].jack == NULL) + continue; + if (spec->dyn_pcm_assign) + snd_device_free(codec->card, + spec->pcm_rec[pcm_idx].jack); + else + spec->pcm_rec[pcm_idx].jack = NULL; } if (spec->i915_bound) @@ -2844,6 +2884,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) init_channel_allocations(); + WARN_ON(spec->dyn_pcm_assign && !codec_has_acomp(codec)); return 0; } -- cgit From b09887f89159a6883a4e1837bbe1698167def91e Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 29 Jan 2016 13:53:27 +0800 Subject: ALSA: hda - hdmi create spdif ctl based on pcm SPDIF ctl should be based on pcm. Each spdif ctl controls one pcm state. This patch creates spdif based on pcm and no longer based on pin. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c8b11dadbd2a..275b68afb575 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2257,6 +2257,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, hinfo->nid = 0; mutex_lock(&spec->pcm_lock); + snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); if (spec->dyn_pcm_assign && pin_idx < 0) { @@ -2278,8 +2279,6 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, pinctl & ~PIN_OUT); } - snd_hda_spdif_ctls_unassign(codec, pcm_idx); - mutex_lock(&per_pin->lock); per_pin->chmap_set = false; memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); @@ -2562,19 +2561,29 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) err = generic_hdmi_build_jack(codec, pcm_idx); if (err < 0) return err; - } - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); - - err = snd_hda_create_dig_out_ctls(codec, + /* create the spdif for each pcm + * pin will be bound when monitor is connected + */ + if (spec->dyn_pcm_assign) + err = snd_hda_create_dig_out_ctls(codec, + 0, spec->cvt_nids[0], + HDA_PCM_TYPE_HDMI); + else { + struct hdmi_spec_per_pin *per_pin = + get_pin(spec, pcm_idx); + err = snd_hda_create_dig_out_ctls(codec, per_pin->pin_nid, per_pin->mux_nids[0], HDA_PCM_TYPE_HDMI); + } if (err < 0) return err; - /* pin number is the same with pcm number so far */ - snd_hda_spdif_ctls_unassign(codec, pin_idx); + snd_hda_spdif_ctls_unassign(codec, pcm_idx); + } + + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); /* add control for ELD Bytes */ err = hdmi_create_eld_ctl(codec, pin_idx, -- cgit From 79289e24194a9d099bf18f200894832c5760cd83 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Jan 2016 11:33:34 +0100 Subject: ALSA: usb-audio: Refer to chip->usb_id for quirks and MIDI creation This is a preliminary patch for the later change to allow a better quirk ID management. In the current USB-audio code, there are a few places looking at usb_device idVendor and idProduct fields directly even though we have already a static member in snd_usb_audio.usb_id. This patch modifies such codes to refer to the latter field. For achieving this, two slightly intensive changes have been done: - The snd_usb_audio object is set/reset via dev_getdrv() for the given USB device; it's needed for minimizing the changes for some existing quirks that take only usb_device object. - __snd_usbmidi_create() is introduced to receive the pre-given usb_id argument. The exported snd_usbmidi_create() is unchanged by calling this new function internally. Signed-off-by: Takashi Iwai --- sound/usb/card.c | 9 ++++++--- sound/usb/midi.c | 15 +++++++++------ sound/usb/midi.h | 14 ++++++++++++-- sound/usb/quirks.c | 36 +++++++++++++++++++++--------------- sound/usb/quirks.h | 3 ++- 5 files changed, 50 insertions(+), 27 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index 1f09d9591276..2c0269014b85 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -171,8 +171,9 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) { - int err = snd_usbmidi_create(chip->card, iface, - &chip->midi_list, NULL); + int err = __snd_usbmidi_create(chip->card, iface, + &chip->midi_list, NULL, + chip->usb_id); if (err < 0) { dev_err(&dev->dev, "%u:%d: cannot create sequencer device\n", @@ -311,6 +312,7 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip) snd_usb_endpoint_free(ep); mutex_destroy(&chip->mutex); + dev_set_drvdata(&chip->dev->dev, NULL); kfree(chip); return 0; } @@ -484,7 +486,7 @@ static int usb_audio_probe(struct usb_interface *intf, if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) return -ENXIO; - err = snd_usb_apply_boot_quirk(dev, intf, quirk); + err = snd_usb_apply_boot_quirk(dev, intf, quirk, id); if (err < 0) return err; @@ -503,6 +505,7 @@ static int usb_audio_probe(struct usb_interface *intf, goto __error; } chip = usb_chip[i]; + dev_set_drvdata(&dev->dev, chip); atomic_inc(&chip->active); /* avoid autopm */ break; } diff --git a/sound/usb/midi.c b/sound/usb/midi.c index cc39f63299ef..b79875ebec1e 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -2320,10 +2320,11 @@ EXPORT_SYMBOL(snd_usbmidi_resume); /* * Creates and registers everything needed for a MIDI streaming interface. */ -int snd_usbmidi_create(struct snd_card *card, - struct usb_interface *iface, - struct list_head *midi_list, - const struct snd_usb_audio_quirk *quirk) +int __snd_usbmidi_create(struct snd_card *card, + struct usb_interface *iface, + struct list_head *midi_list, + const struct snd_usb_audio_quirk *quirk, + unsigned int usb_id) { struct snd_usb_midi *umidi; struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS]; @@ -2341,8 +2342,10 @@ int snd_usbmidi_create(struct snd_card *card, spin_lock_init(&umidi->disc_lock); init_rwsem(&umidi->disc_rwsem); mutex_init(&umidi->mutex); - umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), + if (!usb_id) + usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), le16_to_cpu(umidi->dev->descriptor.idProduct)); + umidi->usb_id = usb_id; setup_timer(&umidi->error_timer, snd_usbmidi_error_timer, (unsigned long)umidi); @@ -2464,4 +2467,4 @@ int snd_usbmidi_create(struct snd_card *card, list_add_tail(&umidi->list, midi_list); return 0; } -EXPORT_SYMBOL(snd_usbmidi_create); +EXPORT_SYMBOL(__snd_usbmidi_create); diff --git a/sound/usb/midi.h b/sound/usb/midi.h index ad8a3211f8e7..5e25a3fd6c1d 100644 --- a/sound/usb/midi.h +++ b/sound/usb/midi.h @@ -39,10 +39,20 @@ struct snd_usb_midi_endpoint_info { /* for QUIRK_MIDI_AKAI, data is NULL */ -int snd_usbmidi_create(struct snd_card *card, +int __snd_usbmidi_create(struct snd_card *card, + struct usb_interface *iface, + struct list_head *midi_list, + const struct snd_usb_audio_quirk *quirk, + unsigned int usb_id); + +static inline int snd_usbmidi_create(struct snd_card *card, struct usb_interface *iface, struct list_head *midi_list, - const struct snd_usb_audio_quirk *quirk); + const struct snd_usb_audio_quirk *quirk) +{ + return __snd_usbmidi_create(card, iface, midi_list, quirk, 0); +} + void snd_usbmidi_input_stop(struct list_head *p); void snd_usbmidi_input_start(struct list_head *p); void snd_usbmidi_disconnect(struct list_head *p); diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index a75d9ce7d77a..16364d94f17b 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -446,8 +446,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, const struct snd_usb_audio_quirk *quirk = chip->usb_id == USB_ID(0x0582, 0x002b) ? &ua700_quirk : &uaxx_quirk; - return snd_usbmidi_create(chip->card, iface, - &chip->midi_list, quirk); + return __snd_usbmidi_create(chip->card, iface, + &chip->midi_list, quirk, + chip->usb_id); } if (altsd->bNumEndpoints != 1) @@ -974,11 +975,9 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, int snd_usb_apply_boot_quirk(struct usb_device *dev, struct usb_interface *intf, - const struct snd_usb_audio_quirk *quirk) + const struct snd_usb_audio_quirk *quirk, + unsigned int id) { - u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - switch (id) { case USB_ID(0x041e, 0x3000): /* SB Extigy needs special boot-up sequence */ @@ -1182,7 +1181,7 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) * "Playback Design" products send bogus feedback data at the start * of the stream. Ignore them. */ - if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) && + if (USB_ID_VENDOR(ep->chip->usb_id) == 0x23ba && ep->type == SND_USB_ENDPOINT_TYPE_SYNC) ep->skip_packets = 4; @@ -1201,11 +1200,15 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) void snd_usb_set_interface_quirk(struct usb_device *dev) { + struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev); + + if (!chip) + return; /* * "Playback Design" products need a 50ms delay after setting the * USB interface. */ - switch (le16_to_cpu(dev->descriptor.idVendor)) { + switch (USB_ID_VENDOR(chip->usb_id)) { case 0x23ba: /* Playback Design */ case 0x0644: /* TEAC Corp. */ mdelay(50); @@ -1213,15 +1216,20 @@ void snd_usb_set_interface_quirk(struct usb_device *dev) } } +/* quirk applied after snd_usb_ctl_msg(); not applied during boot quirks */ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size) { + struct snd_usb_audio *chip = dev_get_drvdata(&dev->dev); + + if (!chip) + return; /* * "Playback Design" products need a 20ms delay after each * class compliant request */ - if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && + if (USB_ID_VENDOR(chip->usb_id) == 0x23ba && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) mdelay(20); @@ -1229,23 +1237,21 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, * "TEAC Corp." products need a 20ms delay after each * class compliant request */ - if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) && + if (USB_ID_VENDOR(chip->usb_id) == 0x0644 && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) mdelay(20); /* Marantz/Denon devices with USB DAC functionality need a delay * after each class compliant request */ - if (is_marantz_denon_dac(USB_ID(le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct))) + if (is_marantz_denon_dac(chip->usb_id) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) mdelay(20); /* Zoom R16/24 needs a tiny delay here, otherwise requests like * get/set frequency return as failed despite actually succeeding. */ - if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1686) && - (le16_to_cpu(dev->descriptor.idProduct) == 0x00dd) && + if (chip->usb_id == USB_ID(0x1686, 0x00dd) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) mdelay(1); } @@ -1262,7 +1268,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, unsigned int sample_bytes) { /* Playback Designs */ - if (le16_to_cpu(chip->dev->descriptor.idVendor) == 0x23ba) { + if (USB_ID_VENDOR(chip->usb_id) == 0x23ba) { switch (fp->altsetting) { case 1: fp->dsd_dop = true; diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 2cd71ed1201f..192ff5ce9452 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -16,7 +16,8 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, int snd_usb_apply_boot_quirk(struct usb_device *dev, struct usb_interface *intf, - const struct snd_usb_audio_quirk *quirk); + const struct snd_usb_audio_quirk *quirk, + unsigned int usb_id); void snd_usb_set_format_quirk(struct snd_usb_substream *subs, struct audioformat *fmt); -- cgit From e2703363316278cd4a8880671d38f783f7de18ba Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Jan 2016 14:39:12 +0100 Subject: ALSA: usb-audio: Add quirk_alias option This patch adds a new option "quirk_alias" to snd-usb-audio driver for allowing user to pass the quirk alias list. A quirk alias consists of a string form like 0123abcd:5678beef, which makes to apply a quirk to a device with USB ID 0123:abcd treated as if it were 5678:beef. This feature is useful to test an existing quirk, typically for a newer model of the same vendor, without patching / rebuilding the kernel driver. The current implementation is fairly simplistic: since there is no API for matching a usb_device_id to the given ID pair, it has an open code to loop over the id table and matches only with vendor:product pair. So far, this is OK, as all existing entries are with vendor:product pairs, indeed. Once when we have another matching entry, however, we'd need to update get_alias_quirk() as well. Note that this option is provided only for testing / development. If you want to have a proper support, contact to upstream for adding the matching quirk in the driver code statically. Signed-off-by: Takashi Iwai --- sound/usb/card.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/sound/usb/card.c b/sound/usb/card.c index 2c0269014b85..3fc63583a537 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -82,6 +82,7 @@ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; static int device_setup[SNDRV_CARDS]; /* device parameter for this card */ static bool ignore_ctl_error; static bool autoclock = true; +static char *quirk_alias[SNDRV_CARDS]; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for the USB audio adapter."); @@ -100,6 +101,8 @@ MODULE_PARM_DESC(ignore_ctl_error, "Ignore errors from USB controller for mixer interfaces."); module_param(autoclock, bool, 0444); MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes)."); +module_param_array(quirk_alias, charp, NULL, 0444); +MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef."); /* * we keep the snd_usb_audio_t instances by ourselves for merging @@ -457,6 +460,48 @@ static int snd_usb_audio_create(struct usb_interface *intf, return 0; } +/* look for a matching quirk alias id */ +static bool get_alias_id(struct usb_device *dev, unsigned int *id) +{ + int i; + unsigned int src, dst; + + for (i = 0; i < ARRAY_SIZE(quirk_alias); i++) { + if (!quirk_alias[i] || + sscanf(quirk_alias[i], "%x:%x", &src, &dst) != 2 || + src != *id) + continue; + dev_info(&dev->dev, + "device (%04x:%04x): applying quirk alias %04x:%04x\n", + USB_ID_VENDOR(*id), USB_ID_PRODUCT(*id), + USB_ID_VENDOR(dst), USB_ID_PRODUCT(dst)); + *id = dst; + return true; + } + + return false; +} + +static struct usb_device_id usb_audio_ids[]; /* defined below */ + +/* look for the corresponding quirk */ +static const struct snd_usb_audio_quirk * +get_alias_quirk(struct usb_device *dev, unsigned int id) +{ + const struct usb_device_id *p; + + for (p = usb_audio_ids; p->match_flags; p++) { + /* FIXME: this checks only vendor:product pair in the list */ + if ((p->match_flags & USB_DEVICE_ID_MATCH_DEVICE) == + USB_DEVICE_ID_MATCH_DEVICE && + p->idVendor == USB_ID_VENDOR(id) && + p->idProduct == USB_ID_PRODUCT(id)) + return (const struct snd_usb_audio_quirk *)p->driver_info; + } + + return NULL; +} + /* * probe the active usb device * @@ -483,6 +528,8 @@ static int usb_audio_probe(struct usb_interface *intf, ifnum = get_iface_desc(alts)->bInterfaceNumber; id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); + if (get_alias_id(dev, &id)) + quirk = get_alias_quirk(dev, id); if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum) return -ENXIO; -- cgit From 1f5e35636cc2737ccf1f67815cb33b978621f0f6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 11 Jan 2016 14:57:56 +0100 Subject: ALSA: doc: Update option descriptions for snd-usb-audio The autoclock and quirk_alias options have been added. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 48148d6d9307..fc53ccd9a629 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1910,6 +1910,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. - Default: 0x0000 ignore_ctl_error - Ignore any USB-controller regarding mixer interface (default: no) + autoclock - Enable auto-clock selection for UAC2 devices + (default: yes) + quirk_alias - Quirk alias list, pass strings like + "0123abcd:5678beef", which applies the existing + quirk for the device 5678:beef to a new device + 0123:abcd. This module supports multiple devices, autoprobe and hotplugging. @@ -1919,6 +1925,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. NB: ignore_ctl_error=1 may help when you get an error at accessing the mixer element such as URB error -22. This happens on some buggy USB device or the controller. + NB: quirk_alias option is provided only for testing / development. + If you want to have a proper support, contact to upstream for + adding the matching quirk in the driver code statically. Module snd-usb-caiaq -------------------- -- cgit From a4efe6fd5dead8d82b73a7ab726aa18cfa11b734 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 14:40:59 +0100 Subject: staging: speakup: (coding style) Add spaces around operands (checkpatch checks) Fix checkpatch check: CHECK: spaces preferred around that '-' (ctx:VxV) Add spaces around operands to fix these warnings. Signed-off-by: Christian Colic Reviewed-by: Luis de Bethencourt Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/keyhelp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c index 02d5c706aee7..d14089a8dbd9 100644 --- a/drivers/staging/speakup/keyhelp.c +++ b/drivers/staging/speakup/keyhelp.c @@ -74,7 +74,7 @@ static void build_key_data(void) for (i = 0; i < nstates; i++, kp++) { if (!*kp) continue; - if ((state_tbl[i]&16) != 0 && *kp == SPK_KEY) + if ((state_tbl[i] & 16) != 0 && *kp == SPK_KEY) continue; counters[*kp]++; } @@ -83,7 +83,7 @@ static void build_key_data(void) if (counters[i] == 0) continue; key_offsets[i] = offset; - offset += (counters[i]+1); + offset += (counters[i] + 1); if (offset >= MAXKEYS) break; } @@ -97,7 +97,7 @@ static void build_key_data(void) ch1 = *kp++; if (!ch1) continue; - if ((state_tbl[i]&16) != 0 && ch1 == SPK_KEY) + if ((state_tbl[i] & 16) != 0 && ch1 == SPK_KEY) continue; key = (state_tbl[i] << 8) + ch; counters[ch1]--; @@ -130,14 +130,14 @@ static int help_init(void) int i; int num_funcs = MSG_FUNCNAMES_END - MSG_FUNCNAMES_START + 1; - state_tbl = spk_our_keys[0]+SHIFT_TBL_SIZE+2; + state_tbl = spk_our_keys[0] + SHIFT_TBL_SIZE + 2; for (i = 0; i < num_funcs; i++) { char *cur_funcname = spk_msg_get(MSG_FUNCNAMES_START + i); if (start == *cur_funcname) continue; start = *cur_funcname; - letter_offsets[(start&31)-1] = i; + letter_offsets[(start & 31) - 1] = i; } return 0; } @@ -160,12 +160,12 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) ch |= 32; /* lower case */ if (ch < 'a' || ch > 'z') return -1; - if (letter_offsets[ch-'a'] == -1) { + if (letter_offsets[ch - 'a'] == -1) { synth_printf(spk_msg_get(MSG_NO_COMMAND), ch); synth_printf("\n"); return 1; } - cur_item = letter_offsets[ch-'a']; + cur_item = letter_offsets[ch - 'a']; } else if (type == KT_CUR) { if (ch == 0 && (MSG_FUNCNAMES_START + cur_item + 1) <= @@ -186,7 +186,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) name = NULL; if ((type != KT_SPKUP) && (key > 0) && (key <= num_key_names)) { synth_printf("%s\n", - spk_msg_get(MSG_KEYNAMES_START + key-1)); + spk_msg_get(MSG_KEYNAMES_START + key - 1)); return 1; } for (i = 0; funcvals[i] != 0 && !name; i++) { @@ -195,7 +195,7 @@ int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key) } if (!name) return -1; - kp = spk_our_keys[key]+1; + kp = spk_our_keys[key] + 1; for (i = 0; i < nstates; i++) { if (ch == kp[i]) break; -- cgit From 1fd16a31256cc867a7212e3399bd493a92cbd177 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 17:08:06 +0100 Subject: staging: speakup: (coding style) Add braces around all arms of if-statement Fix checkpatch error: "braces {} should be used on all arms of this statement" by adding the necessary braces around the "if". Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/devsynth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/speakup/devsynth.c b/drivers/staging/speakup/devsynth.c index d1ffdf4c0c4b..84989711ae67 100644 --- a/drivers/staging/speakup/devsynth.c +++ b/drivers/staging/speakup/devsynth.c @@ -76,9 +76,9 @@ void speakup_register_devsynth(void) if (misc_registered != 0) return; /* zero it so if register fails, deregister will not ref invalid ptrs */ - if (misc_register(&synth_device)) + if (misc_register(&synth_device)) { pr_warn("Couldn't initialize miscdevice /dev/synth.\n"); - else { + } else { pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n", MISC_MAJOR, SYNTH_MINOR); misc_registered = 1; -- cgit From d3da1cbaef8d92b1bb4103feee03b888f5bead24 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 17:18:43 +0100 Subject: staging: speakup: (coding style) Rewrite comparisons to NULL Rewrite comparisons to NULL so they dont show any checkpatch errors anymore. "vc_cons[i].d != NULL" => "vc_cons[i].d" Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/buffers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/speakup/buffers.c b/drivers/staging/speakup/buffers.c index 8565c2343968..723d5df44221 100644 --- a/drivers/staging/speakup/buffers.c +++ b/drivers/staging/speakup/buffers.c @@ -27,7 +27,7 @@ void speakup_start_ttys(void) for (i = 0; i < MAX_NR_CONSOLES; i++) { if (speakup_console[i] && speakup_console[i]->tty_stopped) continue; - if ((vc_cons[i].d != NULL) && (vc_cons[i].d->port.tty != NULL)) + if ((vc_cons[i].d) && (vc_cons[i].d->port.tty)) start_tty(vc_cons[i].d->port.tty); } } @@ -38,7 +38,7 @@ static void speakup_stop_ttys(void) int i; for (i = 0; i < MAX_NR_CONSOLES; i++) - if ((vc_cons[i].d != NULL) && (vc_cons[i].d->port.tty != NULL)) + if ((vc_cons[i].d && (vc_cons[i].d->port.tty))) stop_tty(vc_cons[i].d->port.tty); } -- cgit From d86b4a71ca579914c971ae949335b4e971eec213 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Mon, 7 Dec 2015 18:35:11 +0530 Subject: Staging: speakup: varhandlers: cleanup of function spk_get_punc_var This patch does the following: * changed the complicated if statements to simple case statements * in case of E_DEFAULT, no need to return error as ERESTART, because this is the user asked for. Hence function should return success. * ret variable is 0 always, hence removed it. * removed one ternary operator, as it was always returning the status value only, and hence removed the status variable too Signed-off-by: Saurabh Sengar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/varhandlers.c | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c index ab4fe8de415f..e1393d2a2b0f 100644 --- a/drivers/staging/speakup/varhandlers.c +++ b/drivers/staging/speakup/varhandlers.c @@ -176,7 +176,6 @@ struct punc_var_t *spk_get_punc_var(enum var_id_t var_id) int spk_set_num_var(int input, struct st_var_header *var, int how) { int val; - short ret = 0; int *p_val = var->p_val; int l; char buf[32]; @@ -186,50 +185,51 @@ int spk_set_num_var(int input, struct st_var_header *var, int how) if (!var_data) return -ENODATA; - if (how == E_NEW_DEFAULT) { + val = var_data->u.n.value; + switch (how) { + case E_NEW_DEFAULT: if (input < var_data->u.n.low || input > var_data->u.n.high) return -ERANGE; var_data->u.n.default_val = input; return 0; - } - if (how == E_DEFAULT) { + case E_DEFAULT: val = var_data->u.n.default_val; - ret = -ERESTART; - } else { - if (how == E_SET) - val = input; - else - val = var_data->u.n.value; - if (how == E_INC) - val += input; - else if (how == E_DEC) - val -= input; - if (val < var_data->u.n.low || val > var_data->u.n.high) - return -ERANGE; + break; + case E_SET: + val = input; + break; + case E_INC: + val += input; + break; + case E_DEC: + val -= input; + break; } + + if (val < var_data->u.n.low || val > var_data->u.n.high) + return -ERANGE; + var_data->u.n.value = val; if (var->var_type == VAR_TIME && p_val != NULL) { *p_val = msecs_to_jiffies(val); - return ret; + return 0; } if (p_val != NULL) *p_val = val; if (var->var_id == PUNC_LEVEL) { spk_punc_mask = spk_punc_masks[val]; - return ret; + return 0; } if (var_data->u.n.multiplier != 0) val *= var_data->u.n.multiplier; val += var_data->u.n.offset; if (var->var_id < FIRST_SYNTH_VAR || !synth) - return ret; - if (synth->synth_adjust) { - int status = synth->synth_adjust(var); + return 0; + if (synth->synth_adjust) + return synth->synth_adjust(var); - return (status != 0) ? status : ret; - } if (!var_data->u.n.synth_fmt) - return ret; + return 0; if (var->var_id == PITCH) cp = spk_pitch_buff; else @@ -240,7 +240,7 @@ int spk_set_num_var(int input, struct st_var_header *var, int how) l = sprintf(cp, var_data->u.n.synth_fmt, var_data->u.n.out_str[val]); synth_printf("%s", cp); - return ret; + return 0; } int spk_set_string_var(const char *page, struct st_var_header *var, int len) -- cgit From 911b04d61d28667f2841319939121678198bf1db Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Fri, 18 Dec 2015 12:42:51 -0800 Subject: STAGING/SPEAKUP: Fix "expression using sizeof bool" warnings Fix "warning: expression using sizeof bool" messages caught by sparse. Resending directly to SPEAKUP maintainers. Signed-off-by: Jeff Becker Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/fakekey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c index 5e1f16c36b49..092dbe2c636a 100644 --- a/drivers/staging/speakup/fakekey.c +++ b/drivers/staging/speakup/fakekey.c @@ -28,7 +28,7 @@ #define PRESSED 1 #define RELEASED 0 -static DEFINE_PER_CPU(bool, reporting_keystroke); +static DEFINE_PER_CPU(int, reporting_keystroke); static struct input_dev *virt_keyboard; -- cgit From 5cb10d42de412c69dbf3f5670b3099037c35cc78 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sun, 27 Dec 2015 20:10:38 +0530 Subject: Staging: speakup: Remove FSF mailing address FSF mailing address is no longer required to be specified. Hence removed. Detected using checkpatch Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/fakekey.c | 4 ---- drivers/staging/speakup/keyhelp.c | 4 ---- drivers/staging/speakup/main.c | 4 ---- drivers/staging/speakup/speakup_acntpc.c | 5 ----- drivers/staging/speakup/speakup_acntsa.c | 4 ---- drivers/staging/speakup/speakup_apollo.c | 4 ---- drivers/staging/speakup/speakup_audptr.c | 4 ---- drivers/staging/speakup/speakup_bns.c | 4 ---- drivers/staging/speakup/speakup_decext.c | 4 ---- drivers/staging/speakup/speakup_decpc.c | 4 ---- drivers/staging/speakup/speakup_dectlk.c | 4 ---- drivers/staging/speakup/speakup_dtlk.c | 4 ---- drivers/staging/speakup/speakup_dummy.c | 4 ---- drivers/staging/speakup/speakup_keypc.c | 4 ---- drivers/staging/speakup/speakup_ltlk.c | 4 ---- drivers/staging/speakup/speakup_soft.c | 3 --- drivers/staging/speakup/speakup_spkout.c | 4 ---- drivers/staging/speakup/speakup_txprt.c | 4 ---- drivers/staging/speakup/spk_priv.h | 4 ---- drivers/staging/speakup/spk_priv_keyinfo.h | 4 ---- drivers/staging/speakup/spkguide.txt | 1 - 21 files changed, 81 deletions(-) diff --git a/drivers/staging/speakup/fakekey.c b/drivers/staging/speakup/fakekey.c index 092dbe2c636a..8f058b42f68d 100644 --- a/drivers/staging/speakup/fakekey.c +++ b/drivers/staging/speakup/fakekey.c @@ -12,10 +12,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c index d14089a8dbd9..ce94cb13e256 100644 --- a/drivers/staging/speakup/keyhelp.c +++ b/drivers/staging/speakup/keyhelp.c @@ -14,10 +14,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 63c59bc89b04..456f65043355 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -16,10 +16,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include diff --git a/drivers/staging/speakup/speakup_acntpc.c b/drivers/staging/speakup/speakup_acntpc.c index f418893928ec..efb791bb642b 100644 --- a/drivers/staging/speakup/speakup_acntpc.c +++ b/drivers/staging/speakup/speakup_acntpc.c @@ -14,11 +14,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. * This driver is for the Aicom Acent PC internal synthesizer. diff --git a/drivers/staging/speakup/speakup_acntsa.c b/drivers/staging/speakup/speakup_acntsa.c index af2690f38950..34f45d3549b2 100644 --- a/drivers/staging/speakup/speakup_acntsa.c +++ b/drivers/staging/speakup/speakup_acntsa.c @@ -15,10 +15,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 - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_apollo.c b/drivers/staging/speakup/speakup_apollo.c index 51788f7d4480..3cbc8a7ad1ef 100644 --- a/drivers/staging/speakup/speakup_apollo.c +++ b/drivers/staging/speakup/speakup_apollo.c @@ -15,10 +15,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 - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_audptr.c b/drivers/staging/speakup/speakup_audptr.c index a9a687232955..7a12b8408b67 100644 --- a/drivers/staging/speakup/speakup_audptr.c +++ b/drivers/staging/speakup/speakup_audptr.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_bns.c b/drivers/staging/speakup/speakup_bns.c index 80f8358d4199..570f0c21745e 100644 --- a/drivers/staging/speakup/speakup_bns.c +++ b/drivers/staging/speakup/speakup_bns.c @@ -15,10 +15,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 - * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c index e0b5db9bb46e..fdd7488f554c 100644 --- a/drivers/staging/speakup/speakup_decext.c +++ b/drivers/staging/speakup/speakup_decext.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/staging/speakup/speakup_decpc.c index 4893fef3f894..d6479bd2163b 100644 --- a/drivers/staging/speakup/speakup_decpc.c +++ b/drivers/staging/speakup/speakup_decpc.c @@ -24,10 +24,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. */ #include #include diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/staging/speakup/speakup_dectlk.c index 09063b82326f..764656759fbf 100644 --- a/drivers/staging/speakup/speakup_dectlk.c +++ b/drivers/staging/speakup/speakup_dectlk.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_dtlk.c b/drivers/staging/speakup/speakup_dtlk.c index 345efd3344b0..38aa4013bf62 100644 --- a/drivers/staging/speakup/speakup_dtlk.c +++ b/drivers/staging/speakup/speakup_dtlk.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * package it's not a general device driver. * This driver is for the RC Systems DoubleTalk PC internal synthesizer. diff --git a/drivers/staging/speakup/speakup_dummy.c b/drivers/staging/speakup/speakup_dummy.c index f66811269475..87d2a8002b47 100644 --- a/drivers/staging/speakup/speakup_dummy.c +++ b/drivers/staging/speakup/speakup_dummy.c @@ -17,10 +17,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_keypc.c b/drivers/staging/speakup/speakup_keypc.c index 6ea027365664..5e2170bf4a8b 100644 --- a/drivers/staging/speakup/speakup_keypc.c +++ b/drivers/staging/speakup/speakup_keypc.c @@ -13,10 +13,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 - * * specificly written as a driver for the speakup screenreview * package it's not a general device driver. * This driver is for the Keynote Gold internal synthesizer. diff --git a/drivers/staging/speakup/speakup_ltlk.c b/drivers/staging/speakup/speakup_ltlk.c index cc4806be806b..b474e8b65f9a 100644 --- a/drivers/staging/speakup/speakup_ltlk.c +++ b/drivers/staging/speakup/speakup_ltlk.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index b2eb5b133a5d..6b1d0f538bbd 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -14,9 +14,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 * * this code is specificly written as a driver for the speakup screenreview * package and is not a general device driver. diff --git a/drivers/staging/speakup/speakup_spkout.c b/drivers/staging/speakup/speakup_spkout.c index 1007a6168c3c..e449f2770c1f 100644 --- a/drivers/staging/speakup/speakup_spkout.c +++ b/drivers/staging/speakup/speakup_spkout.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/speakup_txprt.c b/drivers/staging/speakup/speakup_txprt.c index 6c21e7112210..fd98d4ffcb3e 100644 --- a/drivers/staging/speakup/speakup_txprt.c +++ b/drivers/staging/speakup/speakup_txprt.c @@ -15,10 +15,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 - * * specificly written as a driver for the speakup screenreview * s not a general device driver. */ diff --git a/drivers/staging/speakup/spk_priv.h b/drivers/staging/speakup/spk_priv.h index 9bb281d36556..98c4b6f0344a 100644 --- a/drivers/staging/speakup/spk_priv.h +++ b/drivers/staging/speakup/spk_priv.h @@ -16,10 +16,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SPEAKUP_PRIVATE_H #define _SPEAKUP_PRIVATE_H diff --git a/drivers/staging/speakup/spk_priv_keyinfo.h b/drivers/staging/speakup/spk_priv_keyinfo.h index 3116ef78c196..130e9cb0118b 100644 --- a/drivers/staging/speakup/spk_priv_keyinfo.h +++ b/drivers/staging/speakup/spk_priv_keyinfo.h @@ -16,10 +16,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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SPEAKUP_KEYINFO_H diff --git a/drivers/staging/speakup/spkguide.txt b/drivers/staging/speakup/spkguide.txt index b699de3c649f..c23549c54c3c 100644 --- a/drivers/staging/speakup/spkguide.txt +++ b/drivers/staging/speakup/spkguide.txt @@ -1179,7 +1179,6 @@ if desired. Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -- cgit From 3fe9f21ae88e9b8f17fb2ab48745f926b5eb54b7 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sat, 7 Nov 2015 09:22:55 +0530 Subject: Staging: fwserial: Declare fwtty_port_get as static Declare the function fwtty_port_get as static since it is used only in this particular file. Also remove the corresponding declaration from header file. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 3 +-- drivers/staging/fwserial/fwserial.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index b676c486cb18..e481d3230f86 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -828,7 +828,7 @@ static void fwtty_write_xchar(struct fwtty_port *port, char ch) rcu_read_unlock(); } -struct fwtty_port *fwtty_port_get(unsigned index) +static struct fwtty_port *fwtty_port_get(unsigned index) { struct fwtty_port *port; @@ -842,7 +842,6 @@ struct fwtty_port *fwtty_port_get(unsigned index) mutex_unlock(&port_table_lock); return port; } -EXPORT_SYMBOL(fwtty_port_get); static int fwtty_ports_add(struct fw_serial *serial) { diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index e13fe33a6897..6fa936501b3f 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h @@ -341,7 +341,6 @@ static const char loop_dev_name[] = "fwloop"; extern struct tty_driver *fwtty_driver; -struct fwtty_port *fwtty_port_get(unsigned index); /* * Returns the max send async payload size in bytes based on the unit device * link speed. Self-limiting asynchronous bandwidth (via reducing the payload) -- cgit From 82ef33af9dd30075adbd9f3dd161b606b8ba88ac Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sat, 26 Dec 2015 16:44:34 +0530 Subject: Staging: olpc_dcon: Remove obsolete driver Remove support for One Laptop Per Child organization since it is dead. http://www.olpcnews.com/about_olpc_news/goodbye_one_laptop_per_child.html Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 8 - drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/olpc_dcon/Kconfig | 35 -- drivers/staging/olpc_dcon/Makefile | 6 - drivers/staging/olpc_dcon/TODO | 9 - drivers/staging/olpc_dcon/olpc_dcon.c | 813 --------------------------- drivers/staging/olpc_dcon/olpc_dcon.h | 111 ---- drivers/staging/olpc_dcon/olpc_dcon_xo_1.c | 205 ------- drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c | 161 ------ 10 files changed, 1351 deletions(-) delete mode 100644 drivers/staging/olpc_dcon/Kconfig delete mode 100644 drivers/staging/olpc_dcon/Makefile delete mode 100644 drivers/staging/olpc_dcon/TODO delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon.c delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon.h delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon_xo_1.c delete mode 100644 drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c diff --git a/MAINTAINERS b/MAINTAINERS index 48d09cca8505..0d85f01e7deb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10392,14 +10392,6 @@ L: linux-tegra@vger.kernel.org S: Maintained F: drivers/staging/nvec/ -STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON) -M: Jens Frederich -M: Daniel Drake -M: Jon Nettleton -W: http://wiki.laptop.org/go/DCON -S: Maintained -F: drivers/staging/olpc_dcon/ - STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER M: Willy Tarreau S: Odd Fixes diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 5d3b86a33857..6c12a4871f19 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -30,8 +30,6 @@ source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" -source "drivers/staging/olpc_dcon/Kconfig" - source "drivers/staging/panel/Kconfig" source "drivers/staging/rtl8192u/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 30918edef5e3..af207f0492d6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -7,7 +7,6 @@ obj-y += media/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_COMEDI) += comedi/ -obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ obj-$(CONFIG_PANEL) += panel/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig deleted file mode 100644 index d277f048789e..000000000000 --- a/drivers/staging/olpc_dcon/Kconfig +++ /dev/null @@ -1,35 +0,0 @@ -config FB_OLPC_DCON - tristate "One Laptop Per Child Display CONtroller support" - depends on OLPC && FB - depends on I2C - depends on (GPIO_CS5535 || GPIO_CS5535=n) - select BACKLIGHT_CLASS_DEVICE - ---help--- - In order to support very low power operation, the XO laptop uses a - secondary Display CONtroller, or DCON. This secondary controller - is present in the video pipeline between the primary display - controller (integrate into the processor or chipset) and the LCD - panel. It allows the main processor/display controller to be - completely powered off while still retaining an image on the display. - This controller is only available on OLPC platforms. Unless you have - one of these platforms, you will want to say 'N'. - -config FB_OLPC_DCON_1 - bool "OLPC XO-1 DCON support" - depends on FB_OLPC_DCON && GPIO_CS5535 - default y - ---help--- - Enable support for the DCON in XO-1 model laptops. The kernel - communicates with the DCON using model-specific code. If you - have an XO-1 (or if you're unsure what model you have), you should - say 'Y'. - -config FB_OLPC_DCON_1_5 - bool "OLPC XO-1.5 DCON support" - depends on FB_OLPC_DCON && ACPI - default y - ---help--- - Enable support for the DCON in XO-1.5 model laptops. The kernel - communicates with the DCON using model-specific code. If you - have an XO-1.5 (or if you're unsure what model you have), you - should say 'Y'. diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile deleted file mode 100644 index 36c7e67fec20..000000000000 --- a/drivers/staging/olpc_dcon/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -olpc-dcon-objs += olpc_dcon.o -olpc-dcon-$(CONFIG_FB_OLPC_DCON_1) += olpc_dcon_xo_1.o -olpc-dcon-$(CONFIG_FB_OLPC_DCON_1_5) += olpc_dcon_xo_1_5.o -obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o - - diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO deleted file mode 100644 index 61c2e65ac354..000000000000 --- a/drivers/staging/olpc_dcon/TODO +++ /dev/null @@ -1,9 +0,0 @@ -TODO: - - see if vx855 gpio API can be made similar enough to cs5535 so we can - share more code - - allow simultaneous XO-1 and XO-1.5 support - -Please send patches to Greg Kroah-Hartman and -copy: - Daniel Drake - Jens Frederich diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c deleted file mode 100644 index f45b2ef05f48..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * Mainly by David Woodhouse, somewhat modified by Jordan Crouse - * - * Copyright © 2006-2007 Red Hat, Inc. - * Copyright © 2006-2007 Advanced Micro Devices, Inc. - * Copyright © 2009 VIA Technology, Inc. - * Copyright (c) 2010-2011 Andres Salomon - * - * 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "olpc_dcon.h" - -/* Module definitions */ - -static ushort resumeline = 898; -module_param(resumeline, ushort, 0444); - -static struct dcon_platform_data *pdata; - -/* I2C structures */ - -/* Platform devices */ -static struct platform_device *dcon_device; - -static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END }; - -static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val) -{ - return i2c_smbus_write_word_data(dcon->client, reg, val); -} - -static s32 dcon_read(struct dcon_priv *dcon, u8 reg) -{ - return i2c_smbus_read_word_data(dcon->client, reg); -} - -/* ===== API functions - these are called by a variety of users ==== */ - -static int dcon_hw_init(struct dcon_priv *dcon, int is_init) -{ - u16 ver; - int rc = 0; - - ver = dcon_read(dcon, DCON_REG_ID); - if ((ver >> 8) != 0xDC) { - pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver); - rc = -ENXIO; - goto err; - } - - if (is_init) { - pr_info("Discovered DCON version %x\n", ver & 0xFF); - rc = pdata->init(dcon); - if (rc != 0) { - pr_err("Unable to init.\n"); - goto err; - } - } - - if (ver < 0xdc02) { - dev_err(&dcon->client->dev, - "DCON v1 is unsupported, giving up..\n"); - rc = -ENODEV; - goto err; - } - - /* SDRAM setup/hold time */ - dcon_write(dcon, 0x3a, 0xc040); - dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */ - dcon_write(dcon, DCON_REG_MEM_OPT_A, - MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN); - dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET); - - /* Colour swizzle, AA, no passthrough, backlight */ - if (is_init) { - dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE | - MODE_CSWIZZLE | MODE_COL_AA; - } - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - - /* Set the scanline to interrupt on during resume */ - dcon_write(dcon, DCON_REG_SCAN_INT, resumeline); - -err: - return rc; -} - -/* - * The smbus doesn't always come back due to what is believed to be - * hardware (power rail) bugs. For older models where this is known to - * occur, our solution is to attempt to wait for the bus to stabilize; - * if it doesn't happen, cut power to the dcon, repower it, and wait - * for the bus to stabilize. Rinse, repeat until we have a working - * smbus. For newer models, we simply BUG(); we want to know if this - * still happens despite the power fixes that have been made! - */ -static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down) -{ - unsigned long timeout; - u8 pm; - int x; - -power_up: - if (is_powered_down) { - pm = 1; - x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - if (x) { - pr_warn("unable to force dcon to power up: %d!\n", x); - return x; - } - usleep_range(10000, 11000); /* we'll be conservative */ - } - - pdata->bus_stabilize_wiggle(); - - for (x = -1, timeout = 50; timeout && x < 0; timeout--) { - usleep_range(1000, 1100); - x = dcon_read(dcon, DCON_REG_ID); - } - if (x < 0) { - pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n"); - BUG_ON(olpc_board_at_least(olpc_board(0xc2))); - pm = 0; - olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - msleep(100); - is_powered_down = 1; - goto power_up; /* argh, stupid hardware.. */ - } - - if (is_powered_down) - return dcon_hw_init(dcon, 0); - return 0; -} - -static void dcon_set_backlight(struct dcon_priv *dcon, u8 level) -{ - dcon->bl_val = level; - dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val); - - /* Purposely turn off the backlight when we go to level 0 */ - if (dcon->bl_val == 0) { - dcon->disp_mode &= ~MODE_BL_ENABLE; - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - } else if (!(dcon->disp_mode & MODE_BL_ENABLE)) { - dcon->disp_mode |= MODE_BL_ENABLE; - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - } -} - -/* Set the output type to either color or mono */ -static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono) -{ - if (dcon->mono == enable_mono) - return 0; - - dcon->mono = enable_mono; - - if (enable_mono) { - dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA); - dcon->disp_mode |= MODE_MONO_LUMA; - } else { - dcon->disp_mode &= ~(MODE_MONO_LUMA); - dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA; - } - - dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode); - return 0; -} - -/* For now, this will be really stupid - we need to address how - * DCONLOAD works in a sleep and account for it accordingly - */ - -static void dcon_sleep(struct dcon_priv *dcon, bool sleep) -{ - int x; - - /* Turn off the backlight and put the DCON to sleep */ - - if (dcon->asleep == sleep) - return; - - if (!olpc_board_at_least(olpc_board(0xc2))) - return; - - if (sleep) { - u8 pm = 0; - - x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0); - if (x) - pr_warn("unable to force dcon to power down: %d!\n", x); - else - dcon->asleep = sleep; - } else { - /* Only re-enable the backlight if the backlight value is set */ - if (dcon->bl_val != 0) - dcon->disp_mode |= MODE_BL_ENABLE; - x = dcon_bus_stabilize(dcon, 1); - if (x) - pr_warn("unable to reinit dcon hardware: %d!\n", x); - else - dcon->asleep = sleep; - - /* Restore backlight */ - dcon_set_backlight(dcon, dcon->bl_val); - } - - /* We should turn off some stuff in the framebuffer - but what? */ -} - -/* the DCON seems to get confused if we change DCONLOAD too - * frequently -- i.e., approximately faster than frame time. - * normally we don't change it this fast, so in general we won't - * delay here. - */ -static void dcon_load_holdoff(struct dcon_priv *dcon) -{ - ktime_t delta_t, now; - - while (1) { - now = ktime_get(); - delta_t = ktime_sub(now, dcon->load_time); - if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20) - break; - mdelay(4); - } -} - -static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank) -{ - int err; - - console_lock(); - if (!lock_fb_info(dcon->fbinfo)) { - console_unlock(); - dev_err(&dcon->client->dev, "unable to lock framebuffer\n"); - return false; - } - - dcon->ignore_fb_events = true; - err = fb_blank(dcon->fbinfo, - blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); - dcon->ignore_fb_events = false; - unlock_fb_info(dcon->fbinfo); - console_unlock(); - - if (err) { - dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n", - blank ? "" : "un"); - return false; - } - return true; -} - -/* Set the source of the display (CPU or DCON) */ -static void dcon_source_switch(struct work_struct *work) -{ - struct dcon_priv *dcon = container_of(work, struct dcon_priv, - switch_source); - int source = dcon->pending_src; - - if (dcon->curr_src == source) - return; - - dcon_load_holdoff(dcon); - - dcon->switched = false; - - switch (source) { - case DCON_SOURCE_CPU: - pr_info("dcon_source_switch to CPU\n"); - /* Enable the scanline interrupt bit */ - if (dcon_write(dcon, DCON_REG_MODE, - dcon->disp_mode | MODE_SCAN_INT)) - pr_err("couldn't enable scanline interrupt!\n"); - else - /* Wait up to one second for the scanline interrupt */ - wait_event_timeout(dcon->waitq, dcon->switched, HZ); - - if (!dcon->switched) - pr_err("Timeout entering CPU mode; expect a screen glitch.\n"); - - /* Turn off the scanline interrupt */ - if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode)) - pr_err("couldn't disable scanline interrupt!\n"); - - /* - * Ideally we'd like to disable interrupts here so that the - * fb unblanking and DCON turn on happen at a known time value; - * however, we can't do that right now with fb_blank - * messing with semaphores. - * - * For now, we just hope.. - */ - if (!dcon_blank_fb(dcon, false)) { - pr_err("Failed to enter CPU mode\n"); - dcon->pending_src = DCON_SOURCE_DCON; - return; - } - - /* And turn off the DCON */ - pdata->set_dconload(1); - dcon->load_time = ktime_get(); - - pr_info("The CPU has control\n"); - break; - case DCON_SOURCE_DCON: - { - ktime_t delta_t; - - pr_info("dcon_source_switch to DCON\n"); - - /* Clear DCONLOAD - this implies that the DCON is in control */ - pdata->set_dconload(0); - dcon->load_time = ktime_get(); - - wait_event_timeout(dcon->waitq, dcon->switched, HZ/2); - - if (!dcon->switched) { - pr_err("Timeout entering DCON mode; expect a screen glitch.\n"); - } else { - /* sometimes the DCON doesn't follow its own rules, - * and doesn't wait for two vsync pulses before - * ack'ing the frame load with an IRQ. the result - * is that the display shows the *previously* - * loaded frame. we can detect this by looking at - * the time between asserting DCONLOAD and the IRQ -- - * if it's less than 20msec, then the DCON couldn't - * have seen two VSYNC pulses. in that case we - * deassert and reassert, and hope for the best. - * see http://dev.laptop.org/ticket/9664 - */ - delta_t = ktime_sub(dcon->irq_time, dcon->load_time); - if (dcon->switched && ktime_to_ns(delta_t) - < NSEC_PER_MSEC * 20) { - pr_err("missed loading, retrying\n"); - pdata->set_dconload(1); - mdelay(41); - pdata->set_dconload(0); - dcon->load_time = ktime_get(); - mdelay(41); - } - } - - dcon_blank_fb(dcon, true); - pr_info("The DCON has control\n"); - break; - } - default: - BUG(); - } - - dcon->curr_src = source; -} - -static void dcon_set_source(struct dcon_priv *dcon, int arg) -{ - if (dcon->pending_src == arg) - return; - - dcon->pending_src = arg; - - if (dcon->curr_src != arg) - schedule_work(&dcon->switch_source); -} - -static void dcon_set_source_sync(struct dcon_priv *dcon, int arg) -{ - dcon_set_source(dcon, arg); - flush_scheduled_work(); -} - -static ssize_t dcon_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%4.4X\n", dcon->disp_mode); -} - -static ssize_t dcon_sleep_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->asleep); -} - -static ssize_t dcon_freeze_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0); -} - -static ssize_t dcon_mono_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", dcon->mono); -} - -static ssize_t dcon_resumeline_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", resumeline); -} - -static ssize_t dcon_mono_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long enable_mono; - int rc; - - rc = kstrtoul(buf, 10, &enable_mono); - if (rc) - return rc; - - dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false); - - return count; -} - -static ssize_t dcon_freeze_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct dcon_priv *dcon = dev_get_drvdata(dev); - unsigned long output; - int ret; - - ret = kstrtoul(buf, 10, &output); - if (ret) - return ret; - - pr_info("dcon_freeze_store: %lu\n", output); - - switch (output) { - case 0: - dcon_set_source(dcon, DCON_SOURCE_CPU); - break; - case 1: - dcon_set_source_sync(dcon, DCON_SOURCE_DCON); - break; - case 2: /* normally unused */ - dcon_set_source(dcon, DCON_SOURCE_DCON); - break; - default: - return -EINVAL; - } - - return count; -} - -static ssize_t dcon_resumeline_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned short rl; - int rc; - - rc = kstrtou16(buf, 10, &rl); - if (rc) - return rc; - - resumeline = rl; - dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline); - - return count; -} - -static ssize_t dcon_sleep_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - unsigned long output; - int ret; - - ret = kstrtoul(buf, 10, &output); - if (ret) - return ret; - - dcon_sleep(dev_get_drvdata(dev), output ? true : false); - return count; -} - -static struct device_attribute dcon_device_files[] = { - __ATTR(mode, 0444, dcon_mode_show, NULL), - __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store), - __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store), - __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store), - __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store), -}; - -static int dcon_bl_update(struct backlight_device *dev) -{ - struct dcon_priv *dcon = bl_get_data(dev); - u8 level = dev->props.brightness & 0x0F; - - if (dev->props.power != FB_BLANK_UNBLANK) - level = 0; - - if (level != dcon->bl_val) - dcon_set_backlight(dcon, level); - - /* power down the DCON when the screen is blanked */ - if (!dcon->ignore_fb_events) - dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK)); - - return 0; -} - -static int dcon_bl_get(struct backlight_device *dev) -{ - struct dcon_priv *dcon = bl_get_data(dev); - - return dcon->bl_val; -} - -static const struct backlight_ops dcon_bl_ops = { - .update_status = dcon_bl_update, - .get_brightness = dcon_bl_get, -}; - -static struct backlight_properties dcon_bl_props = { - .max_brightness = 15, - .type = BACKLIGHT_RAW, - .power = FB_BLANK_UNBLANK, -}; - -static int dcon_reboot_notify(struct notifier_block *nb, - unsigned long foo, void *bar) -{ - struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb); - - if (!dcon || !dcon->client) - return NOTIFY_DONE; - - /* Turn off the DCON. Entirely. */ - dcon_write(dcon, DCON_REG_MODE, 0x39); - dcon_write(dcon, DCON_REG_MODE, 0x32); - return NOTIFY_DONE; -} - -static int unfreeze_on_panic(struct notifier_block *nb, - unsigned long e, void *p) -{ - pdata->set_dconload(1); - return NOTIFY_DONE; -} - -static struct notifier_block dcon_panic_nb = { - .notifier_call = unfreeze_on_panic, -}; - -static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - strlcpy(info->type, "olpc_dcon", I2C_NAME_SIZE); - - return 0; -} - -static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct dcon_priv *dcon; - int rc, i, j; - - if (!pdata) - return -ENXIO; - - dcon = kzalloc(sizeof(*dcon), GFP_KERNEL); - if (!dcon) - return -ENOMEM; - - dcon->client = client; - init_waitqueue_head(&dcon->waitq); - INIT_WORK(&dcon->switch_source, dcon_source_switch); - dcon->reboot_nb.notifier_call = dcon_reboot_notify; - dcon->reboot_nb.priority = -1; - - i2c_set_clientdata(client, dcon); - - if (num_registered_fb < 1) { - dev_err(&client->dev, "DCON driver requires a registered fb\n"); - rc = -EIO; - goto einit; - } - dcon->fbinfo = registered_fb[0]; - - rc = dcon_hw_init(dcon, 1); - if (rc) - goto einit; - - /* Add the DCON device */ - - dcon_device = platform_device_alloc("dcon", -1); - - if (!dcon_device) { - pr_err("Unable to create the DCON device\n"); - rc = -ENOMEM; - goto eirq; - } - rc = platform_device_add(dcon_device); - platform_set_drvdata(dcon_device, dcon); - - if (rc) { - pr_err("Unable to add the DCON device\n"); - goto edev; - } - - for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) { - rc = device_create_file(&dcon_device->dev, - &dcon_device_files[i]); - if (rc) { - dev_err(&dcon_device->dev, "Cannot create sysfs file\n"); - goto ecreate; - } - } - - dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F; - - /* Add the backlight device for the DCON */ - dcon_bl_props.brightness = dcon->bl_val; - dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev, - dcon, &dcon_bl_ops, &dcon_bl_props); - if (IS_ERR(dcon->bl_dev)) { - dev_err(&client->dev, "cannot register backlight dev (%ld)\n", - PTR_ERR(dcon->bl_dev)); - dcon->bl_dev = NULL; - } - - register_reboot_notifier(&dcon->reboot_nb); - atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb); - - return 0; - - ecreate: - for (j = 0; j < i; j++) - device_remove_file(&dcon_device->dev, &dcon_device_files[j]); - edev: - platform_device_unregister(dcon_device); - dcon_device = NULL; - eirq: - free_irq(DCON_IRQ, dcon); - einit: - kfree(dcon); - return rc; -} - -static int dcon_remove(struct i2c_client *client) -{ - struct dcon_priv *dcon = i2c_get_clientdata(client); - - unregister_reboot_notifier(&dcon->reboot_nb); - atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb); - - free_irq(DCON_IRQ, dcon); - - backlight_device_unregister(dcon->bl_dev); - - if (dcon_device) - platform_device_unregister(dcon_device); - cancel_work_sync(&dcon->switch_source); - - kfree(dcon); - - return 0; -} - -#ifdef CONFIG_PM -static int dcon_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dcon_priv *dcon = i2c_get_clientdata(client); - - if (!dcon->asleep) { - /* Set up the DCON to have the source */ - dcon_set_source_sync(dcon, DCON_SOURCE_DCON); - } - - return 0; -} - -static int dcon_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dcon_priv *dcon = i2c_get_clientdata(client); - - if (!dcon->asleep) { - dcon_bus_stabilize(dcon, 0); - dcon_set_source(dcon, DCON_SOURCE_CPU); - } - - return 0; -} - -#else - -#define dcon_suspend NULL -#define dcon_resume NULL - -#endif /* CONFIG_PM */ - -irqreturn_t dcon_interrupt(int irq, void *id) -{ - struct dcon_priv *dcon = id; - u8 status; - - if (pdata->read_status(&status)) - return IRQ_NONE; - - switch (status & 3) { - case 3: - pr_debug("DCONLOAD_MISSED interrupt\n"); - break; - - case 2: /* switch to DCON mode */ - case 1: /* switch to CPU mode */ - dcon->switched = true; - dcon->irq_time = ktime_get(); - wake_up(&dcon->waitq); - break; - - case 0: - /* workaround resume case: the DCON (on 1.5) doesn't - * ever assert status 0x01 when switching to CPU mode - * during resume. this is because DCONLOAD is de-asserted - * _immediately_ upon exiting S3, so the actual release - * of the DCON happened long before this point. - * see http://dev.laptop.org/ticket/9869 - */ - if (dcon->curr_src != dcon->pending_src && !dcon->switched) { - dcon->switched = true; - dcon->irq_time = ktime_get(); - wake_up(&dcon->waitq); - pr_debug("switching w/ status 0/0\n"); - } else { - pr_debug("scanline interrupt w/CPU\n"); - } - } - - return IRQ_HANDLED; -} - -static const struct dev_pm_ops dcon_pm_ops = { - .suspend = dcon_suspend, - .resume = dcon_resume, -}; - -static const struct i2c_device_id dcon_idtable[] = { - { "olpc_dcon", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, dcon_idtable); - -static struct i2c_driver dcon_driver = { - .driver = { - .name = "olpc_dcon", - .pm = &dcon_pm_ops, - }, - .class = I2C_CLASS_DDC | I2C_CLASS_HWMON, - .id_table = dcon_idtable, - .probe = dcon_probe, - .remove = dcon_remove, - .detect = dcon_detect, - .address_list = normal_i2c, -}; - -static int __init olpc_dcon_init(void) -{ -#ifdef CONFIG_FB_OLPC_DCON_1_5 - /* XO-1.5 */ - if (olpc_board_at_least(olpc_board(0xd0))) - pdata = &dcon_pdata_xo_1_5; -#endif -#ifdef CONFIG_FB_OLPC_DCON_1 - if (!pdata) - pdata = &dcon_pdata_xo_1; -#endif - - return i2c_add_driver(&dcon_driver); -} - -static void __exit olpc_dcon_exit(void) -{ - i2c_del_driver(&dcon_driver); -} - -module_init(olpc_dcon_init); -module_exit(olpc_dcon_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h deleted file mode 100644 index 215e7ec4dea2..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef OLPC_DCON_H_ -#define OLPC_DCON_H_ - -#include -#include - -/* DCON registers */ - -#define DCON_REG_ID 0 -#define DCON_REG_MODE 1 - -#define MODE_PASSTHRU (1<<0) -#define MODE_SLEEP (1<<1) -#define MODE_SLEEP_AUTO (1<<2) -#define MODE_BL_ENABLE (1<<3) -#define MODE_BLANK (1<<4) -#define MODE_CSWIZZLE (1<<5) -#define MODE_COL_AA (1<<6) -#define MODE_MONO_LUMA (1<<7) -#define MODE_SCAN_INT (1<<8) -#define MODE_CLOCKDIV (1<<9) -#define MODE_DEBUG (1<<14) -#define MODE_SELFTEST (1<<15) - -#define DCON_REG_HRES 0x2 -#define DCON_REG_HTOTAL 0x3 -#define DCON_REG_HSYNC_WIDTH 0x4 -#define DCON_REG_VRES 0x5 -#define DCON_REG_VTOTAL 0x6 -#define DCON_REG_VSYNC_WIDTH 0x7 -#define DCON_REG_TIMEOUT 0x8 -#define DCON_REG_SCAN_INT 0x9 -#define DCON_REG_BRIGHT 0xa -#define DCON_REG_MEM_OPT_A 0x41 -#define DCON_REG_MEM_OPT_B 0x42 - -/* Load Delay Locked Loop (DLL) settings for clock delay */ -#define MEM_DLL_CLOCK_DELAY (1<<0) -/* Memory controller power down function */ -#define MEM_POWER_DOWN (1<<8) -/* Memory controller software reset */ -#define MEM_SOFT_RESET (1<<0) - -/* Status values */ - -#define DCONSTAT_SCANINT 0 -#define DCONSTAT_SCANINT_DCON 1 -#define DCONSTAT_DISPLAYLOAD 2 -#define DCONSTAT_MISSED 3 - -/* Source values */ - -#define DCON_SOURCE_DCON 0 -#define DCON_SOURCE_CPU 1 - -/* Interrupt */ -#define DCON_IRQ 6 - -struct dcon_priv { - struct i2c_client *client; - struct fb_info *fbinfo; - struct backlight_device *bl_dev; - - wait_queue_head_t waitq; - struct work_struct switch_source; - struct notifier_block reboot_nb; - - /* Shadow register for the DCON_REG_MODE register */ - u8 disp_mode; - - /* The current backlight value - this saves us some smbus traffic */ - u8 bl_val; - - /* Current source, initialized at probe time */ - int curr_src; - - /* Desired source */ - int pending_src; - - /* Variables used during switches */ - bool switched; - ktime_t irq_time; - ktime_t load_time; - - /* Current output type; true == mono, false == color */ - bool mono; - bool asleep; - /* This get set while controlling fb blank state from the driver */ - bool ignore_fb_events; -}; - -struct dcon_platform_data { - int (*init)(struct dcon_priv *); - void (*bus_stabilize_wiggle)(void); - void (*set_dconload)(int); - int (*read_status)(u8 *); -}; - -#include - -irqreturn_t dcon_interrupt(int irq, void *id); - -#ifdef CONFIG_FB_OLPC_DCON_1 -extern struct dcon_platform_data dcon_pdata_xo_1; -#endif - -#ifdef CONFIG_FB_OLPC_DCON_1_5 -extern struct dcon_platform_data dcon_pdata_xo_1_5; -#endif - -#endif diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c deleted file mode 100644 index 0c5a10c69401..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Mainly by David Woodhouse, somewhat modified by Jordan Crouse - * - * Copyright © 2006-2007 Red Hat, Inc. - * Copyright © 2006-2007 Advanced Micro Devices, Inc. - * Copyright © 2009 VIA Technology, Inc. - * Copyright (c) 2010 Andres Salomon - * - * 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -#include "olpc_dcon.h" - -static int dcon_init_xo_1(struct dcon_priv *dcon) -{ - unsigned char lob; - - if (gpio_request(OLPC_GPIO_DCON_STAT0, "OLPC-DCON")) { - pr_err("failed to request STAT0 GPIO\n"); - return -EIO; - } - if (gpio_request(OLPC_GPIO_DCON_STAT1, "OLPC-DCON")) { - pr_err("failed to request STAT1 GPIO\n"); - goto err_gp_stat1; - } - if (gpio_request(OLPC_GPIO_DCON_IRQ, "OLPC-DCON")) { - pr_err("failed to request IRQ GPIO\n"); - goto err_gp_irq; - } - if (gpio_request(OLPC_GPIO_DCON_LOAD, "OLPC-DCON")) { - pr_err("failed to request LOAD GPIO\n"); - goto err_gp_load; - } - if (gpio_request(OLPC_GPIO_DCON_BLANK, "OLPC-DCON")) { - pr_err("failed to request BLANK GPIO\n"); - goto err_gp_blank; - } - - /* Turn off the event enable for GPIO7 just to be safe */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); - - /* - * Determine the current state by reading the GPIO bit; earlier - * stages of the boot process have established the state. - * - * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here; - * this is because OFW will disable input for the pin and set a value.. - * READ_BACK will only contain a valid value if input is enabled and - * then a value is set. So, future readings of the pin can use - * READ_BACK, but the first one cannot. Awesome, huh? - */ - dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL) - ? DCON_SOURCE_CPU - : DCON_SOURCE_DCON; - dcon->pending_src = dcon->curr_src; - - /* Set the directions for the GPIO pins */ - gpio_direction_input(OLPC_GPIO_DCON_STAT0); - gpio_direction_input(OLPC_GPIO_DCON_STAT1); - gpio_direction_input(OLPC_GPIO_DCON_IRQ); - gpio_direction_input(OLPC_GPIO_DCON_BLANK); - gpio_direction_output(OLPC_GPIO_DCON_LOAD, - dcon->curr_src == DCON_SOURCE_CPU); - - /* Set up the interrupt mappings */ - - /* Set the IRQ to pair 2 */ - cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0); - - /* Enable group 2 to trigger the DCON interrupt */ - cs5535_gpio_set_irq(2, DCON_IRQ); - - /* Select edge level for interrupt (in PIC) */ - lob = inb(0x4d0); - lob &= ~(1 << DCON_IRQ); - outb(lob, 0x4d0); - - /* Register the interrupt handler */ - if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) { - pr_err("failed to request DCON's irq\n"); - goto err_req_irq; - } - - /* Clear INV_EN for GPIO7 (DCONIRQ) */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT); - - /* Enable filter for GPIO12 (DCONBLANK) */ - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER); - - /* Disable filter for GPIO7 */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER); - - /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ - cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT); - cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT); - - /* Add GPIO12 to the Filter Event Pair #7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL); - - /* Turn off negative Edge Enable for GPIO12 */ - cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN); - - /* Enable negative Edge Enable for GPIO7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN); - - /* Zero the filter amount for Filter Event Pair #7 */ - cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT); - - /* Clear the negative edge status for GPIO7 and GPIO12 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS); - - /* FIXME: Clear the positive status as well, just to be sure */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS); - - /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE); - cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE); - - return 0; - -err_req_irq: - gpio_free(OLPC_GPIO_DCON_BLANK); -err_gp_blank: - gpio_free(OLPC_GPIO_DCON_LOAD); -err_gp_load: - gpio_free(OLPC_GPIO_DCON_IRQ); -err_gp_irq: - gpio_free(OLPC_GPIO_DCON_STAT1); -err_gp_stat1: - gpio_free(OLPC_GPIO_DCON_STAT0); - return -EIO; -} - -static void dcon_wiggle_xo_1(void) -{ - int x; - - /* - * According to HiMax, when powering the DCON up we should hold - * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON - * state machine to reset to a (sane) initial state. Mitch Bradley - * did some testing and discovered that holding for 16 SMB_CLK cycles - * worked a lot more reliably, so that's what we do here. - * - * According to the cs5536 spec, to set GPIO14 to SMB_CLK we must - * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and - * GPIO15. - */ - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); - cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); - - for (x = 0; x < 16; x++) { - udelay(5); - cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - udelay(5); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL); - } - udelay(5); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1); - cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1); -} - -static void dcon_set_dconload_1(int val) -{ - gpio_set_value(OLPC_GPIO_DCON_LOAD, val); -} - -static int dcon_read_status_xo_1(u8 *status) -{ - *status = gpio_get_value(OLPC_GPIO_DCON_STAT0); - *status |= gpio_get_value(OLPC_GPIO_DCON_STAT1) << 1; - - /* Clear the negative edge status for GPIO7 */ - cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS); - - return 0; -} - -struct dcon_platform_data dcon_pdata_xo_1 = { - .init = dcon_init_xo_1, - .bus_stabilize_wiggle = dcon_wiggle_xo_1, - .set_dconload = dcon_set_dconload_1, - .read_status = dcon_read_status_xo_1, -}; diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c deleted file mode 100644 index 6a4d379c16a3..000000000000 --- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2009,2010 One Laptop per Child - * - * 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include - -/* TODO: this eventually belongs in linux/vx855.h */ -#define NR_VX855_GPI 14 -#define NR_VX855_GPO 13 -#define NR_VX855_GPIO 15 - -#define VX855_GPI(n) (n) -#define VX855_GPO(n) (NR_VX855_GPI + (n)) -#define VX855_GPIO(n) (NR_VX855_GPI + NR_VX855_GPO + (n)) - -#include "olpc_dcon.h" - -/* Hardware setup on the XO 1.5: - * DCONLOAD connects to VX855_GPIO1 (not SMBCK2) - * DCONBLANK connects to VX855_GPIO8 (not SSPICLK) unused in driver - * DCONSTAT0 connects to VX855_GPI10 (not SSPISDI) - * DCONSTAT1 connects to VX855_GPI11 (not nSSPISS) - * DCONIRQ connects to VX855_GPIO12 - * DCONSMBDATA connects to VX855 graphics CRTSPD - * DCONSMBCLK connects to VX855 graphics CRTSPCLK - */ - -#define VX855_GENL_PURPOSE_OUTPUT 0x44c /* PMIO_Rx4c-4f */ -#define VX855_GPI_STATUS_CHG 0x450 /* PMIO_Rx50 */ -#define VX855_GPI_SCI_SMI 0x452 /* PMIO_Rx52 */ -#define BIT_GPIO12 0x40 - -#define PREFIX "OLPC DCON:" - -static void dcon_clear_irq(void) -{ - /* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */ - outb(BIT_GPIO12, VX855_GPI_STATUS_CHG); -} - -static int dcon_was_irq(void) -{ - u_int8_t tmp; - - /* irq status will appear in PMIO_Rx50[6] on gpio12 */ - tmp = inb(VX855_GPI_STATUS_CHG); - return !!(tmp & BIT_GPIO12); - - return 0; -} - -static int dcon_init_xo_1_5(struct dcon_priv *dcon) -{ - unsigned int irq; - - dcon_clear_irq(); - - /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */ - outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI); - - /* Determine the current state of DCONLOAD, likely set by firmware */ - /* GPIO1 */ - dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ? - DCON_SOURCE_CPU : DCON_SOURCE_DCON; - dcon->pending_src = dcon->curr_src; - - /* we're sharing the IRQ with ACPI */ - irq = acpi_gbl_FADT.sci_interrupt; - if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) { - pr_err("DCON (IRQ%d) allocation failed\n", irq); - return 1; - } - - return 0; -} - -static void set_i2c_line(int sda, int scl) -{ - unsigned char tmp; - unsigned int port = 0x26; - - /* FIXME: This directly accesses the CRT GPIO controller !!! */ - outb(port, 0x3c4); - tmp = inb(0x3c5); - - if (scl) - tmp |= 0x20; - else - tmp &= ~0x20; - - if (sda) - tmp |= 0x10; - else - tmp &= ~0x10; - - tmp |= 0x01; - - outb(port, 0x3c4); - outb(tmp, 0x3c5); -} - - -static void dcon_wiggle_xo_1_5(void) -{ - int x; - - /* - * According to HiMax, when powering the DCON up we should hold - * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON - * state machine to reset to a (sane) initial state. Mitch Bradley - * did some testing and discovered that holding for 16 SMB_CLK cycles - * worked a lot more reliably, so that's what we do here. - */ - set_i2c_line(1, 1); - - for (x = 0; x < 16; x++) { - udelay(5); - set_i2c_line(1, 0); - udelay(5); - set_i2c_line(1, 1); - } - udelay(5); - - /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */ - outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI); -} - -static void dcon_set_dconload_xo_1_5(int val) -{ - gpio_set_value(VX855_GPIO(1), val); -} - -static int dcon_read_status_xo_1_5(u8 *status) -{ - if (!dcon_was_irq()) - return -1; - - /* i believe this is the same as "inb(0x44b) & 3" */ - *status = gpio_get_value(VX855_GPI(10)); - *status |= gpio_get_value(VX855_GPI(11)) << 1; - - dcon_clear_irq(); - - return 0; -} - -struct dcon_platform_data dcon_pdata_xo_1_5 = { - .init = dcon_init_xo_1_5, - .bus_stabilize_wiggle = dcon_wiggle_xo_1_5, - .set_dconload = dcon_set_dconload_xo_1_5, - .read_status = dcon_read_status_xo_1_5, -}; -- cgit From 7e3933df9874b70745548ce9177295d11c58fc21 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Sat, 26 Dec 2015 17:36:07 +0530 Subject: Staging: dgap: Remove obsolete driver Remove support for dgap driver since there is no way to get the firmware files required by the dgap driver into the linux- firmware tree. The dgap driver is rendered useless without this firmware and hence this product is considered obsolete by DIGI. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 7 - drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/dgap/Kconfig | 6 - drivers/staging/dgap/Makefile | 1 - drivers/staging/dgap/dgap.c | 7079 ----------------------------------------- drivers/staging/dgap/dgap.h | 1229 ------- 7 files changed, 8325 deletions(-) delete mode 100644 drivers/staging/dgap/Kconfig delete mode 100644 drivers/staging/dgap/Makefile delete mode 100644 drivers/staging/dgap/dgap.c delete mode 100644 drivers/staging/dgap/dgap.h diff --git a/MAINTAINERS b/MAINTAINERS index 0d85f01e7deb..79f7eb25ecd8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3538,13 +3538,6 @@ L: driverdev-devel@linuxdriverproject.org S: Maintained F: drivers/staging/dgnc/ -DIGI EPCA PCI PRODUCTS -M: Lidza Louina -M: Daeseok Youn -L: driverdev-devel@linuxdriverproject.org -S: Maintained -F: drivers/staging/dgap/ - DIOLAN U2C-12 I2C DRIVER M: Guenter Roeck L: linux-i2c@vger.kernel.org diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 6c12a4871f19..e80268ae8c9d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -90,8 +90,6 @@ source "drivers/staging/lustre/Kconfig" source "drivers/staging/dgnc/Kconfig" -source "drivers/staging/dgap/Kconfig" - source "drivers/staging/gs_fpgaboot/Kconfig" source "drivers/staging/skein/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index af207f0492d6..ba160f1ec02d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -36,7 +36,6 @@ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_GOLDFISH) += goldfish/ obj-$(CONFIG_LUSTRE_FS) += lustre/ obj-$(CONFIG_DGNC) += dgnc/ -obj-$(CONFIG_DGAP) += dgap/ obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ diff --git a/drivers/staging/dgap/Kconfig b/drivers/staging/dgap/Kconfig deleted file mode 100644 index 3bbe9e122365..000000000000 --- a/drivers/staging/dgap/Kconfig +++ /dev/null @@ -1,6 +0,0 @@ -config DGAP - tristate "Digi EPCA PCI products" - default n - depends on TTY && HAS_IOMEM - ---help--- - Driver for the Digi International EPCA PCI based product line diff --git a/drivers/staging/dgap/Makefile b/drivers/staging/dgap/Makefile deleted file mode 100644 index 0063d044ca71..000000000000 --- a/drivers/staging/dgap/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_DGAP) += dgap.o diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c deleted file mode 100644 index bad355100825..000000000000 --- a/drivers/staging/dgap/dgap.c +++ /dev/null @@ -1,7079 +0,0 @@ -/* - * Copyright 2003 Digi International (www.digi.com) - * Scott H Kilau - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, 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. - * - */ - -/* - * In the original out of kernel Digi dgap driver, firmware - * loading was done via user land to driver handshaking. - * - * For cards that support a concentrator (port expander), - * I believe the concentrator its self told the card which - * concentrator is actually attached and then that info - * was used to tell user land which concentrator firmware - * image was to be downloaded. I think even the BIOS or - * FEP images required could change with the connection - * of a particular concentrator. - * - * Since I have no access to any of these cards or - * concentrators, I cannot put the correct concentrator - * firmware file names into the firmware_info structure - * as is now done for the BIOS and FEP images. - * - * I think, but am not certain, that the cards supporting - * concentrators will function without them. So support - * of these cards has been left in this driver. - * - * In order to fully support those cards, they would - * either have to be acquired for dissection or maybe - * Digi International could provide some assistance. - */ -#undef DIGI_CONCENTRATORS_SUPPORTED - -#define pr_fmt(fmt) "dgap: " fmt - -#include -#include -#include -#include /* For udelay */ -#include -#include -#include - -#include /* For tasklet and interrupt structs/defines */ -#include -#include -#include -#include -#include /* For read[bwl]/write[bwl] */ - -#include -#include -#include -#include - -#include "dgap.h" - -/* - * File operations permitted on Control/Management major. - */ -static const struct file_operations dgap_board_fops = { - .owner = THIS_MODULE, -}; - -static uint dgap_numboards; -static struct board_t *dgap_board[MAXBOARDS]; -static ulong dgap_poll_counter; -static int dgap_driver_state = DRIVER_INITIALIZED; -static int dgap_poll_tick = 20; /* Poll interval - 20 ms */ - -static struct class *dgap_class; - -static uint dgap_count = 500; - -/* - * Poller stuff - */ -static DEFINE_SPINLOCK(dgap_poll_lock); /* Poll scheduling lock */ -static ulong dgap_poll_time; /* Time of next poll */ -static uint dgap_poll_stop; /* Used to tell poller to stop */ -static struct timer_list dgap_poll_timer; - -/* - SUPPORTED PRODUCTS - - Card Model Number of Ports Interface - ---------------------------------------------------------------- - Acceleport Xem 4 - 64 (EIA232 & EIA422) - Acceleport Xr 4 & 8 (EIA232) - Acceleport Xr 920 4 & 8 (EIA232) - Acceleport C/X 8 - 128 (EIA232) - Acceleport EPC/X 8 - 224 (EIA232) - Acceleport Xr/422 4 & 8 (EIA422) - Acceleport 2r/920 2 (EIA232) - Acceleport 4r/920 4 (EIA232) - Acceleport 8r/920 8 (EIA232) - - IBM 8-Port Asynchronous PCI Adapter (EIA232) - IBM 128-Port Asynchronous PCI Adapter (EIA232 & EIA422) -*/ - -static struct pci_device_id dgap_pci_tbl[] = { - { DIGI_VID, PCI_DEV_XEM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { DIGI_VID, PCI_DEV_CX_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { DIGI_VID, PCI_DEV_CX_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, - { DIGI_VID, PCI_DEV_EPCJ_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - { DIGI_VID, PCI_DEV_920_2_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { DIGI_VID, PCI_DEV_920_4_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, - { DIGI_VID, PCI_DEV_920_8_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, - { DIGI_VID, PCI_DEV_XR_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 }, - { DIGI_VID, PCI_DEV_XRJ_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { DIGI_VID, PCI_DEV_XR_422_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 }, - { DIGI_VID, PCI_DEV_XR_IBM_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 }, - { DIGI_VID, PCI_DEV_XR_SAIP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 }, - { DIGI_VID, PCI_DEV_XR_BULL_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 }, - { DIGI_VID, PCI_DEV_920_8_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 }, - { DIGI_VID, PCI_DEV_XEM_HP_DID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 }, - {0,} /* 0 terminated list. */ -}; -MODULE_DEVICE_TABLE(pci, dgap_pci_tbl); - -/* - * A generic list of Product names, PCI Vendor ID, and PCI Device ID. - */ -struct board_id { - uint config_type; - u8 *name; - uint maxports; - uint dpatype; -}; - -static struct board_id dgap_ids[] = { - {PPCM, PCI_DEV_XEM_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)}, - {PCX, PCI_DEV_CX_NAME, 128, (T_CX | T_PCIBUS) }, - {PCX, PCI_DEV_CX_IBM_NAME, 128, (T_CX | T_PCIBUS) }, - {PEPC, PCI_DEV_EPCJ_NAME, 224, (T_EPC | T_PCIBUS) }, - {APORT2_920P, PCI_DEV_920_2_NAME, 2, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {APORT4_920P, PCI_DEV_920_4_NAME, 4, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {APORT8_920P, PCI_DEV_920_8_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XRJ_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_422_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_IBM_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_SAIP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PAPORT8, PCI_DEV_XR_BULL_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {APORT8_920P, PCI_DEV_920_8_HP_NAME, 8, (T_PCXR | T_PCLITE | T_PCIBUS)}, - {PPCM, PCI_DEV_XEM_HP_NAME, 64, (T_PCXM | T_PCLITE | T_PCIBUS)}, - {0,} /* 0 terminated list. */ -}; - -struct firmware_info { - u8 *conf_name; /* dgap.conf */ - u8 *bios_name; /* BIOS filename */ - u8 *fep_name; /* FEP filename */ - u8 *con_name; /* Concentrator filename FIXME*/ - int num; /* sequence number */ -}; - -/* - * Firmware - BIOS, FEP, and CONC filenames - */ -static struct firmware_info fw_info[] = { - { "dgap/dgap.conf", "dgap/sxbios.bin", "dgap/sxfep.bin", NULL, 0 }, - { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", NULL, 1 }, - { "dgap/dgap.conf", "dgap/cxpbios.bin", "dgap/cxpfep.bin", NULL, 2 }, - { "dgap/dgap.conf", "dgap/pcibios.bin", "dgap/pcifep.bin", NULL, 3 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 4 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 5 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 6 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 7 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 8 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 9 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 10 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 11 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 12 }, - { "dgap/dgap.conf", "dgap/xrbios.bin", "dgap/xrfep.bin", NULL, 13 }, - { "dgap/dgap.conf", "dgap/sxbios.bin", "dgap/sxfep.bin", NULL, 14 }, - {NULL,} -}; - -/* - * Default transparent print information. - */ -static struct digi_t dgap_digi_init = { - .digi_flags = DIGI_COOK, /* Flags */ - .digi_maxcps = 100, /* Max CPS */ - .digi_maxchar = 50, /* Max chars in print queue */ - .digi_bufsize = 100, /* Printer buffer size */ - .digi_onlen = 4, /* size of printer on string */ - .digi_offlen = 4, /* size of printer off string */ - .digi_onstr = "\033[5i", /* ANSI printer on string ] */ - .digi_offstr = "\033[4i", /* ANSI printer off string ] */ - .digi_term = "ansi" /* default terminal type */ -}; - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. - * - * This defines a raw port at 9600 baud, 8 data bits, no parity, - * 1 stop bit. - */ - -static struct ktermios dgap_default_termios = { - .c_iflag = (DEFAULT_IFLAGS), /* iflags */ - .c_oflag = (DEFAULT_OFLAGS), /* oflags */ - .c_cflag = (DEFAULT_CFLAGS), /* cflags */ - .c_lflag = (DEFAULT_LFLAGS), /* lflags */ - .c_cc = INIT_C_CC, - .c_line = 0, -}; - -/* - * Our needed internal static variables from dgap_parse.c - */ -static struct cnode dgap_head; -#define MAXCWORD 200 -static char dgap_cword[MAXCWORD]; - -struct toklist { - int token; - char *string; -}; - -static struct toklist dgap_brdtype[] = { - { PCX, "Digi_AccelePort_C/X_PCI" }, - { PEPC, "Digi_AccelePort_EPC/X_PCI" }, - { PPCM, "Digi_AccelePort_Xem_PCI" }, - { APORT2_920P, "Digi_AccelePort_2r_920_PCI" }, - { APORT4_920P, "Digi_AccelePort_4r_920_PCI" }, - { APORT8_920P, "Digi_AccelePort_8r_920_PCI" }, - { PAPORT4, "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" }, - { PAPORT8, "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" }, - { 0, NULL } -}; - -static struct toklist dgap_tlist[] = { - { BEGIN, "config_begin" }, - { END, "config_end" }, - { BOARD, "board" }, - { PCIINFO, "pciinfo" }, - { LINE, "line" }, - { CONC, "conc" }, - { CONC, "concentrator" }, - { CX, "cx" }, - { CX, "ccon" }, - { EPC, "epccon" }, - { EPC, "epc" }, - { MOD, "module" }, - { ID, "id" }, - { STARTO, "start" }, - { SPEED, "speed" }, - { CABLE, "cable" }, - { CONNECT, "connect" }, - { METHOD, "method" }, - { STATUS, "status" }, - { CUSTOM, "Custom" }, - { BASIC, "Basic" }, - { MEM, "mem" }, - { MEM, "memory" }, - { PORTS, "ports" }, - { MODEM, "modem" }, - { NPORTS, "nports" }, - { TTYN, "ttyname" }, - { CU, "cuname" }, - { PRINT, "prname" }, - { CMAJOR, "major" }, - { ALTPIN, "altpin" }, - { USEINTR, "useintr" }, - { TTSIZ, "ttysize" }, - { CHSIZ, "chsize" }, - { BSSIZ, "boardsize" }, - { UNTSIZ, "schedsize" }, - { F2SIZ, "f2200size" }, - { VPSIZ, "vpixsize" }, - { 0, NULL } -}; - -/* - * get a word from the input stream, also keep track of current line number. - * words are separated by whitespace. - */ -static char *dgap_getword(char **in) -{ - char *ret_ptr = *in; - - char *ptr = strpbrk(*in, " \t\n"); - - /* If no word found, return null */ - if (!ptr) - return NULL; - - /* Mark new location for our buffer */ - *ptr = '\0'; - *in = ptr + 1; - - /* Eat any extra spaces/tabs/newlines that might be present */ - while (*in && **in && ((**in == ' ') || - (**in == '\t') || - (**in == '\n'))) { - **in = '\0'; - *in = *in + 1; - } - - return ret_ptr; -} - - -/* - * Get a token from the input file; return 0 if end of file is reached - */ -static int dgap_gettok(char **in) -{ - char *w; - struct toklist *t; - - if (strstr(dgap_cword, "board")) { - w = dgap_getword(in); - if (!w) - return 0; - snprintf(dgap_cword, MAXCWORD, "%s", w); - for (t = dgap_brdtype; t->token != 0; t++) { - if (!strcmp(w, t->string)) - return t->token; - } - } else { - while ((w = dgap_getword(in))) { - snprintf(dgap_cword, MAXCWORD, "%s", w); - for (t = dgap_tlist; t->token != 0; t++) { - if (!strcmp(w, t->string)) - return t->token; - } - } - } - - return 0; -} - -/* - * dgap_checknode: see if all the necessary info has been supplied for a node - * before creating the next node. - */ -static int dgap_checknode(struct cnode *p) -{ - switch (p->type) { - case LNODE: - if (p->u.line.v_speed == 0) { - pr_err("line speed not specified"); - return 1; - } - return 0; - - case CNODE: - if (p->u.conc.v_speed == 0) { - pr_err("concentrator line speed not specified"); - return 1; - } - if (p->u.conc.v_nport == 0) { - pr_err("number of ports on concentrator not specified"); - return 1; - } - if (p->u.conc.v_id == 0) { - pr_err("concentrator id letter not specified"); - return 1; - } - return 0; - - case MNODE: - if (p->u.module.v_nport == 0) { - pr_err("number of ports on EBI module not specified"); - return 1; - } - if (p->u.module.v_id == 0) { - pr_err("EBI module id letter not specified"); - return 1; - } - return 0; - } - return 0; -} - -/* - * Given a board pointer, returns whether we should use interrupts or not. - */ -static uint dgap_config_get_useintr(struct board_t *bd) -{ - struct cnode *p; - - if (!bd) - return 0; - - for (p = bd->bd_config; p; p = p->next) { - if (p->type == INTRNODE) { - /* - * check for pcxr types. - */ - return p->u.useintr; - } - } - - /* If not found, then don't turn on interrupts. */ - return 0; -} - -/* - * Given a board pointer, returns whether we turn on altpin or not. - */ -static uint dgap_config_get_altpin(struct board_t *bd) -{ - struct cnode *p; - - if (!bd) - return 0; - - for (p = bd->bd_config; p; p = p->next) { - if (p->type == ANODE) { - /* - * check for pcxr types. - */ - return p->u.altpin; - } - } - - /* If not found, then don't turn on interrupts. */ - return 0; -} - -/* - * Given a specific type of board, if found, detached link and - * returns the first occurrence in the list. - */ -static struct cnode *dgap_find_config(int type, int bus, int slot) -{ - struct cnode *p, *prev, *prev2, *found; - - p = &dgap_head; - - while (p->next) { - prev = p; - p = p->next; - - if (p->type != BNODE) - continue; - - if (p->u.board.type != type) - continue; - - if (p->u.board.v_pcibus && - p->u.board.pcibus != bus) - continue; - - if (p->u.board.v_pcislot && - p->u.board.pcislot != slot) - continue; - - found = p; - /* - * Keep walking thru the list till we - * find the next board. - */ - while (p->next) { - prev2 = p; - p = p->next; - - if (p->type != BNODE) - continue; - - /* - * Mark the end of our 1 board - * chain of configs. - */ - prev2->next = NULL; - - /* - * Link the "next" board to the - * previous board, effectively - * "unlinking" our board from - * the main config. - */ - prev->next = p; - - return found; - } - /* - * It must be the last board in the list. - */ - prev->next = NULL; - return found; - } - return NULL; -} - -/* - * Given a board pointer, walks the config link, counting up - * all ports user specified should be on the board. - * (This does NOT mean they are all actually present right now tho) - */ -static uint dgap_config_get_num_prts(struct board_t *bd) -{ - int count = 0; - struct cnode *p; - - if (!bd) - return 0; - - for (p = bd->bd_config; p; p = p->next) { - switch (p->type) { - case BNODE: - /* - * check for pcxr types. - */ - if (p->u.board.type > EPCFE) - count += p->u.board.nport; - break; - case CNODE: - count += p->u.conc.nport; - break; - case MNODE: - count += p->u.module.nport; - break; - } - } - return count; -} - -static char *dgap_create_config_string(struct board_t *bd, char *string) -{ - char *ptr = string; - struct cnode *p; - struct cnode *q; - int speed; - - if (!bd) { - *ptr = 0xff; - return string; - } - - for (p = bd->bd_config; p; p = p->next) { - switch (p->type) { - case LNODE: - *ptr = '\0'; - ptr++; - *ptr = p->u.line.speed; - ptr++; - break; - case CNODE: - /* - * Because the EPC/con concentrators can have EM modules - * hanging off of them, we have to walk ahead in the - * list and keep adding the number of ports on each EM - * to the config. UGH! - */ - speed = p->u.conc.speed; - q = p->next; - if (q && (q->type == MNODE)) { - *ptr = (p->u.conc.nport + 0x80); - ptr++; - p = q; - while (q->next && (q->next->type) == MNODE) { - *ptr = (q->u.module.nport + 0x80); - ptr++; - p = q; - q = q->next; - } - *ptr = q->u.module.nport; - ptr++; - } else { - *ptr = p->u.conc.nport; - ptr++; - } - - *ptr = speed; - ptr++; - break; - } - } - - *ptr = 0xff; - return string; -} - -/* - * Parse a configuration file read into memory as a string. - */ -static int dgap_parsefile(char **in) -{ - struct cnode *p, *brd, *line, *conc; - int rc; - char *s; - int linecnt = 0; - - p = &dgap_head; - brd = line = conc = NULL; - - /* perhaps we are adding to an existing list? */ - while (p->next) - p = p->next; - - /* file must start with a BEGIN */ - while ((rc = dgap_gettok(in)) != BEGIN) { - if (rc == 0) { - pr_err("unexpected EOF"); - return -1; - } - } - - for (; ;) { - int board_type = 0; - int conc_type = 0; - int module_type = 0; - - rc = dgap_gettok(in); - if (rc == 0) { - pr_err("unexpected EOF"); - return -1; - } - - switch (rc) { - case BEGIN: /* should only be 1 begin */ - pr_err("unexpected config_begin\n"); - return -1; - - case END: - return 0; - - case BOARD: /* board info */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - - p->type = BNODE; - p->u.board.status = kstrdup("No", GFP_KERNEL); - line = conc = NULL; - brd = p; - linecnt = -1; - - board_type = dgap_gettok(in); - if (board_type == 0) { - pr_err("board !!type not specified"); - return -1; - } - - p->u.board.type = board_type; - - break; - - case MEM: /* memory address */ - if (p->type != BNODE) { - pr_err("memory address only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.addrstr); - p->u.board.addrstr = kstrdup(s, GFP_KERNEL); - if (kstrtoul(s, 0, &p->u.board.addr)) { - pr_err("bad number for memory address"); - return -1; - } - p->u.board.v_addr = 1; - break; - - case PCIINFO: /* pci information */ - if (p->type != BNODE) { - pr_err("memory address only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.pcibusstr); - p->u.board.pcibusstr = kstrdup(s, GFP_KERNEL); - if (kstrtoul(s, 0, &p->u.board.pcibus)) { - pr_err("bad number for pci bus"); - return -1; - } - p->u.board.v_pcibus = 1; - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.pcislotstr); - p->u.board.pcislotstr = kstrdup(s, GFP_KERNEL); - if (kstrtoul(s, 0, &p->u.board.pcislot)) { - pr_err("bad number for pci slot"); - return -1; - } - p->u.board.v_pcislot = 1; - break; - - case METHOD: - if (p->type != BNODE) { - pr_err("install method only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.method); - p->u.board.method = kstrdup(s, GFP_KERNEL); - p->u.board.v_method = 1; - break; - - case STATUS: - if (p->type != BNODE) { - pr_err("config status only valid for boards"); - return -1; - } - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.status); - p->u.board.status = kstrdup(s, GFP_KERNEL); - break; - - case NPORTS: /* number of ports */ - if (p->type == BNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.board.nport)) { - pr_err("bad number for number of ports"); - return -1; - } - p->u.board.v_nport = 1; - } else if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.conc.nport)) { - pr_err("bad number for number of ports"); - return -1; - } - p->u.conc.v_nport = 1; - } else if (p->type == MNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.module.nport)) { - pr_err("bad number for number of ports"); - return -1; - } - p->u.module.v_nport = 1; - } else { - pr_err("nports only valid for concentrators or modules"); - return -1; - } - break; - - case ID: /* letter ID used in tty name */ - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.board.status); - p->u.board.status = kstrdup(s, GFP_KERNEL); - - if (p->type == CNODE) { - kfree(p->u.conc.id); - p->u.conc.id = kstrdup(s, GFP_KERNEL); - p->u.conc.v_id = 1; - } else if (p->type == MNODE) { - kfree(p->u.module.id); - p->u.module.id = kstrdup(s, GFP_KERNEL); - p->u.module.v_id = 1; - } else { - pr_err("id only valid for concentrators or modules"); - return -1; - } - break; - - case STARTO: /* start offset of ID */ - if (p->type == BNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.board.start)) { - pr_err("bad number for start of tty count"); - return -1; - } - p->u.board.v_start = 1; - } else if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.conc.start)) { - pr_err("bad number for start of tty count"); - return -1; - } - p->u.conc.v_start = 1; - } else if (p->type == MNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.module.start)) { - pr_err("bad number for start of tty count"); - return -1; - } - p->u.module.v_start = 1; - } else { - pr_err("start only valid for concentrators or modules"); - return -1; - } - break; - - case TTYN: /* tty name prefix */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = TNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpeced end of file"); - return -1; - } - p->u.ttyname = kstrdup(s, GFP_KERNEL); - if (!p->u.ttyname) - return -1; - - break; - - case CU: /* cu name prefix */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = CUNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpeced end of file"); - return -1; - } - p->u.cuname = kstrdup(s, GFP_KERNEL); - if (!p->u.cuname) - return -1; - - break; - - case LINE: /* line information */ - if (dgap_checknode(p)) - return -1; - if (!brd) { - pr_err("must specify board before line info"); - return -1; - } - switch (brd->u.board.type) { - case PPCM: - pr_err("line not valid for PC/em"); - return -1; - } - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = LNODE; - conc = NULL; - line = p; - linecnt++; - break; - - case CONC: /* concentrator information */ - if (dgap_checknode(p)) - return -1; - if (!line) { - pr_err("must specify line info before concentrator"); - return -1; - } - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = CNODE; - conc = p; - - if (linecnt) - brd->u.board.conc2++; - else - brd->u.board.conc1++; - - conc_type = dgap_gettok(in); - if (conc_type == 0 || - (conc_type != CX && conc_type != EPC)) { - pr_err("failed to set a type of concentratros"); - return -1; - } - - p->u.conc.type = conc_type; - - break; - - case MOD: /* EBI module */ - if (dgap_checknode(p)) - return -1; - if (!brd) { - pr_err("must specify board info before EBI modules"); - return -1; - } - switch (brd->u.board.type) { - case PPCM: - linecnt = 0; - break; - default: - if (!conc) { - pr_err("must specify concentrator info before EBI module"); - return -1; - } - } - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = MNODE; - - if (linecnt) - brd->u.board.module2++; - else - brd->u.board.module1++; - - module_type = dgap_gettok(in); - if (module_type == 0 || - (module_type != PORTS && module_type != MODEM)) { - pr_err("failed to set a type of module"); - return -1; - } - - p->u.module.type = module_type; - - break; - - case CABLE: - if (p->type == LNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.line.cable); - p->u.line.cable = kstrdup(s, GFP_KERNEL); - p->u.line.v_cable = 1; - } - break; - - case SPEED: /* sync line speed indication */ - if (p->type == LNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.line.speed)) { - pr_err("bad number for line speed"); - return -1; - } - p->u.line.v_speed = 1; - } else if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.conc.speed)) { - pr_err("bad number for line speed"); - return -1; - } - p->u.conc.v_speed = 1; - } else { - pr_err("speed valid only for lines or concentrators."); - return -1; - } - break; - - case CONNECT: - if (p->type == CNODE) { - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - kfree(p->u.conc.connect); - p->u.conc.connect = kstrdup(s, GFP_KERNEL); - p->u.conc.v_connect = 1; - } - break; - case PRINT: /* transparent print name prefix */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = PNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpeced end of file"); - return -1; - } - p->u.printname = kstrdup(s, GFP_KERNEL); - if (!p->u.printname) - return -1; - - break; - - case CMAJOR: /* major number */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = JNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.majornumber)) { - pr_err("bad number for major number"); - return -1; - } - break; - - case ALTPIN: /* altpin setting */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = ANODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.altpin)) { - pr_err("bad number for altpin"); - return -1; - } - break; - - case USEINTR: /* enable interrupt setting */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = INTRNODE; - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.useintr)) { - pr_err("bad number for useintr"); - return -1; - } - break; - - case TTSIZ: /* size of tty structure */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = TSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.ttysize)) { - pr_err("bad number for ttysize"); - return -1; - } - break; - - case CHSIZ: /* channel structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = CSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.chsize)) { - pr_err("bad number for chsize"); - return -1; - } - break; - - case BSSIZ: /* board structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = BSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.bssize)) { - pr_err("bad number for bssize"); - return -1; - } - break; - - case UNTSIZ: /* sched structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = USNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.unsize)) { - pr_err("bad number for schedsize"); - return -1; - } - break; - - case F2SIZ: /* f2200 structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = FSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.f2size)) { - pr_err("bad number for f2200size"); - return -1; - } - break; - - case VPSIZ: /* vpix structure size */ - if (dgap_checknode(p)) - return -1; - - p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); - if (!p->next) - return -ENOMEM; - - p = p->next; - p->type = VSNODE; - - s = dgap_getword(in); - if (!s) { - pr_err("unexpected end of file"); - return -1; - } - if (kstrtol(s, 0, &p->u.vpixsize)) { - pr_err("bad number for vpixsize"); - return -1; - } - break; - } - } -} - -static void dgap_cleanup_nodes(void) -{ - struct cnode *p; - - p = &dgap_head; - - while (p) { - struct cnode *tmp = p->next; - - if (p->type == NULLNODE) { - p = tmp; - continue; - } - - switch (p->type) { - case BNODE: - kfree(p->u.board.addrstr); - kfree(p->u.board.pcibusstr); - kfree(p->u.board.pcislotstr); - kfree(p->u.board.method); - break; - case CNODE: - kfree(p->u.conc.id); - kfree(p->u.conc.connect); - break; - case MNODE: - kfree(p->u.module.id); - break; - case TNODE: - kfree(p->u.ttyname); - break; - case CUNODE: - kfree(p->u.cuname); - break; - case LNODE: - kfree(p->u.line.cable); - break; - case PNODE: - kfree(p->u.printname); - break; - } - - kfree(p->u.board.status); - kfree(p); - p = tmp; - } -} - -/* - * Retrives the current custom baud rate from FEP memory, - * and returns it back to the user. - * Returns 0 on error. - */ -static uint dgap_get_custom_baud(struct channel_t *ch) -{ - u8 __iomem *vaddr; - ulong offset; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) - return 0; - - if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS)) - return 0; - - vaddr = ch->ch_bd->re_map_membase; - - if (!vaddr) - return 0; - - /* - * Go get from fep mem, what the fep - * believes the custom baud rate is. - */ - offset = (ioread16(vaddr + ECS_SEG) << 4) + (ch->ch_portnum * 0x28) - + LINE_SPEED; - - return readw(vaddr + offset); -} - -/* - * Remap PCI memory. - */ -static int dgap_remap(struct board_t *brd) -{ - if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - if (!request_mem_region(brd->membase, 0x200000, "dgap")) - return -ENOMEM; - - if (!request_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000, "dgap")) - goto err_req_mem; - - brd->re_map_membase = ioremap(brd->membase, 0x200000); - if (!brd->re_map_membase) - goto err_remap_mem; - - brd->re_map_port = ioremap((brd->membase + PCI_IO_OFFSET), 0x200000); - if (!brd->re_map_port) - goto err_remap_port; - - return 0; - -err_remap_port: - iounmap(brd->re_map_membase); -err_remap_mem: - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); -err_req_mem: - release_mem_region(brd->membase, 0x200000); - - return -ENOMEM; -} - -static void dgap_unmap(struct board_t *brd) -{ - iounmap(brd->re_map_port); - iounmap(brd->re_map_membase); - release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); - release_mem_region(brd->membase, 0x200000); -} - -/* - * dgap_parity_scan() - * - * Convert the FEP5 way of reporting parity errors and breaks into - * the Linux line discipline way. - */ -static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, - unsigned char *fbuf, int *len) -{ - int l = *len; - int count = 0; - unsigned char *in, *cout, *fout; - unsigned char c; - - in = cbuf; - cout = cbuf; - fout = fbuf; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - while (l--) { - c = *in++; - switch (ch->pscan_state) { - default: - /* reset to sanity and fall through */ - ch->pscan_state = 0; - - case 0: - /* No FF seen yet */ - if (c == (unsigned char)'\377') - /* delete this character from stream */ - ch->pscan_state = 1; - else { - *cout++ = c; - *fout++ = TTY_NORMAL; - count += 1; - } - break; - - case 1: - /* first FF seen */ - if (c == (unsigned char)'\377') { - /* doubled ff, transform to single ff */ - *cout++ = c; - *fout++ = TTY_NORMAL; - count += 1; - ch->pscan_state = 0; - } else { - /* save value examination in next state */ - ch->pscan_savechar = c; - ch->pscan_state = 2; - } - break; - - case 2: - /* third character of ff sequence */ - - *cout++ = c; - - if (ch->pscan_savechar == 0x0) { - if (c == 0x0) { - ch->ch_err_break++; - *fout++ = TTY_BREAK; - } else { - ch->ch_err_parity++; - *fout++ = TTY_PARITY; - } - } - - count += 1; - ch->pscan_state = 0; - } - } - *len = count; -} - -/*======================================================================= - * - * dgap_input - Process received data. - * - * ch - Pointer to channel structure. - * - *=======================================================================*/ - -static void dgap_input(struct channel_t *ch) -{ - struct board_t *bd; - struct bs_t __iomem *bs; - struct tty_struct *tp; - struct tty_ldisc *ld; - uint rmask; - uint head; - uint tail; - int data_len; - ulong lock_flags; - ulong lock_flags2; - int flip_len; - int len; - int n; - u8 *buf; - u8 tmpchar; - int s; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - tp = ch->ch_tun.un_tty; - - bs = ch->ch_bs; - if (!bs) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* - * Figure the number of characters in the buffer. - * Exit immediately if none. - */ - - rmask = ch->ch_rsize - 1; - - head = readw(&bs->rx_head); - head &= rmask; - tail = readw(&bs->rx_tail); - tail &= rmask; - - data_len = (head - tail) & rmask; - - if (data_len == 0) { - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - /* - * If the device is not open, or CREAD is off, flush - * input data and return immediately. - */ - if ((bd->state != BOARD_READY) || !tp || - (tp->magic != TTY_MAGIC) || - !(ch->ch_tun.un_flags & UN_ISOPEN) || - !(tp->termios.c_cflag & CREAD) || - (ch->ch_tun.un_flags & UN_CLOSING)) { - writew(head, &bs->rx_tail); - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - /* - * If we are throttled, simply don't read any data. - */ - if (ch->ch_flags & CH_RXBLOCK) { - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - /* - * Ignore oruns. - */ - tmpchar = readb(&bs->orun); - if (tmpchar) { - ch->ch_err_overrun++; - writeb(0, &bs->orun); - } - - /* Decide how much data we can send into the tty layer */ - flip_len = TTY_FLIPBUF_SIZE; - - /* Chop down the length, if needed */ - len = min(data_len, flip_len); - len = min(len, (N_TTY_BUF_SIZE - 1)); - - ld = tty_ldisc_ref(tp); - -#ifdef TTY_DONT_FLIP - /* - * If the DONT_FLIP flag is on, don't flush our buffer, and act - * like the ld doesn't have any space to put the data right now. - */ - if (test_bit(TTY_DONT_FLIP, &tp->flags)) - len = 0; -#endif - - /* - * If we were unable to get a reference to the ld, - * don't flush our buffer, and act like the ld doesn't - * have any space to put the data right now. - */ - if (!ld) { - len = 0; - } else { - /* - * If ld doesn't have a pointer to a receive_buf function, - * flush the data, then act like the ld doesn't have any - * space to put the data right now. - */ - if (!ld->ops->receive_buf) { - writew(head, &bs->rx_tail); - len = 0; - } - } - - if (len <= 0) { - writeb(1, &bs->idata); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (ld) - tty_ldisc_deref(ld); - return; - } - - buf = ch->ch_bd->flipbuf; - n = len; - - /* - * n now contains the most amount of data we can copy, - * bounded either by our buffer size or the amount - * of data the card actually has pending... - */ - while (n) { - s = ((head >= tail) ? head : ch->ch_rsize) - tail; - s = min(s, n); - - if (s <= 0) - break; - - memcpy_fromio(buf, ch->ch_raddr + tail, s); - - tail += s; - buf += s; - - n -= s; - /* Flip queue if needed */ - tail &= rmask; - } - - writew(tail, &bs->rx_tail); - writeb(1, &bs->idata); - ch->ch_rxcount += len; - - /* - * If we are completely raw, we don't need to go through a lot - * of the tty layers that exist. - * In this case, we take the shortest and fastest route we - * can to relay the data to the user. - * - * On the other hand, if we are not raw, we need to go through - * the tty layer, which has its API more well defined. - */ - if (I_PARMRK(tp) || I_BRKINT(tp) || I_INPCK(tp)) { - dgap_parity_scan(ch, ch->ch_bd->flipbuf, - ch->ch_bd->flipflagbuf, &len); - - len = tty_buffer_request_room(tp->port, len); - tty_insert_flip_string_flags(tp->port, ch->ch_bd->flipbuf, - ch->ch_bd->flipflagbuf, len); - } else { - len = tty_buffer_request_room(tp->port, len); - tty_insert_flip_string(tp->port, ch->ch_bd->flipbuf, len); - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - /* Tell the tty layer its okay to "eat" the data now */ - tty_flip_buffer_push(tp->port); - - if (ld) - tty_ldisc_deref(ld); -} - -static void dgap_write_wakeup(struct board_t *bd, struct channel_t *ch, - struct un_t *un, u32 mask, - unsigned long *irq_flags1, - unsigned long *irq_flags2) -{ - if (!(un->un_flags & mask)) - return; - - un->un_flags &= ~mask; - - if (!(un->un_flags & UN_ISOPEN)) - return; - - if ((un->un_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - un->un_tty->ldisc->ops->write_wakeup) { - spin_unlock_irqrestore(&ch->ch_lock, *irq_flags2); - spin_unlock_irqrestore(&bd->bd_lock, *irq_flags1); - - (un->un_tty->ldisc->ops->write_wakeup)(un->un_tty); - - spin_lock_irqsave(&bd->bd_lock, *irq_flags1); - spin_lock_irqsave(&ch->ch_lock, *irq_flags2); - } - wake_up_interruptible(&un->un_tty->write_wait); - wake_up_interruptible(&un->un_flags_wait); -} - -/************************************************************************ - * Determines when CARRIER changes state and takes appropriate - * action. - ************************************************************************/ -static void dgap_carrier(struct channel_t *ch) -{ - struct board_t *bd; - - int virt_carrier = 0; - int phys_carrier = 0; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - /* Make sure altpin is always set correctly */ - if (ch->ch_digi.digi_flags & DIGI_ALTPIN) { - ch->ch_dsr = DM_CD; - ch->ch_cd = DM_DSR; - } else { - ch->ch_dsr = DM_DSR; - ch->ch_cd = DM_CD; - } - - if (ch->ch_mistat & D_CD(ch)) - phys_carrier = 1; - - if (ch->ch_digi.digi_flags & DIGI_FORCEDCD) - virt_carrier = 1; - - if (ch->ch_c_cflag & CLOCAL) - virt_carrier = 1; - - /* - * Test for a VIRTUAL carrier transition to HIGH. - */ - if (((ch->ch_flags & CH_FCAR) == 0) && (virt_carrier == 1)) { - /* - * When carrier rises, wake any threads waiting - * for carrier in the open routine. - */ - - if (waitqueue_active(&(ch->ch_flags_wait))) - wake_up_interruptible(&ch->ch_flags_wait); - } - - /* - * Test for a PHYSICAL carrier transition to HIGH. - */ - if (((ch->ch_flags & CH_CD) == 0) && (phys_carrier == 1)) { - /* - * When carrier rises, wake any threads waiting - * for carrier in the open routine. - */ - - if (waitqueue_active(&(ch->ch_flags_wait))) - wake_up_interruptible(&ch->ch_flags_wait); - } - - /* - * Test for a PHYSICAL transition to low, so long as we aren't - * currently ignoring physical transitions (which is what "virtual - * carrier" indicates). - * - * The transition of the virtual carrier to low really doesn't - * matter... it really only means "ignore carrier state", not - * "make pretend that carrier is there". - */ - if ((virt_carrier == 0) && - ((ch->ch_flags & CH_CD) != 0) && - (phys_carrier == 0)) { - /* - * When carrier drops: - * - * Drop carrier on all open units. - * - * Flush queues, waking up any task waiting in the - * line discipline. - * - * Send a hangup to the control terminal. - * - * Enable all select calls. - */ - if (waitqueue_active(&(ch->ch_flags_wait))) - wake_up_interruptible(&ch->ch_flags_wait); - - if (ch->ch_tun.un_open_count > 0) - tty_hangup(ch->ch_tun.un_tty); - - if (ch->ch_pun.un_open_count > 0) - tty_hangup(ch->ch_pun.un_tty); - } - - /* - * Make sure that our cached values reflect the current reality. - */ - if (virt_carrier == 1) - ch->ch_flags |= CH_FCAR; - else - ch->ch_flags &= ~CH_FCAR; - - if (phys_carrier == 1) - ch->ch_flags |= CH_CD; - else - ch->ch_flags &= ~CH_CD; -} - -/*======================================================================= - * - * dgap_event - FEP to host event processing routine. - * - * bd - Board of current event. - * - *=======================================================================*/ -static int dgap_event(struct board_t *bd) -{ - struct channel_t *ch; - ulong lock_flags; - ulong lock_flags2; - struct bs_t __iomem *bs; - u8 __iomem *event; - u8 __iomem *vaddr; - struct ev_t __iomem *eaddr; - uint head; - uint tail; - int port; - int reason; - int modem; - - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - - vaddr = bd->re_map_membase; - - if (!vaddr) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EIO; - } - - eaddr = (struct ev_t __iomem *)(vaddr + EVBUF); - - /* Get our head and tail */ - head = readw(&eaddr->ev_head); - tail = readw(&eaddr->ev_tail); - - /* - * Forget it if pointers out of range. - */ - - if (head >= EVMAX - EVSTART || tail >= EVMAX - EVSTART || - (head | tail) & 03) { - /* Let go of board lock */ - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EIO; - } - - /* - * Loop to process all the events in the buffer. - */ - while (tail != head) { - /* - * Get interrupt information. - */ - - event = bd->re_map_membase + tail + EVSTART; - - port = ioread8(event); - reason = ioread8(event + 1); - modem = ioread8(event + 2); - ioread8(event + 3); - - /* - * Make sure the interrupt is valid. - */ - if (port >= bd->nasync) - goto next; - - if (!(reason & (IFMODEM | IFBREAK | IFTLW | IFTEM | IFDATA))) - goto next; - - ch = bd->channels[port]; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - goto next; - - /* - * If we have made it here, the event was valid. - * Lock down the channel. - */ - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - bs = ch->ch_bs; - - if (!bs) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - goto next; - } - - /* - * Process received data. - */ - if (reason & IFDATA) { - /* - * ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT! - * input could send some data to ld, which in turn - * could do a callback to one of our other functions. - */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - dgap_input(ch); - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (ch->ch_flags & CH_RACTIVE) - ch->ch_flags |= CH_RENABLE; - else - writeb(1, &bs->idata); - - if (ch->ch_flags & CH_RWAIT) { - ch->ch_flags &= ~CH_RWAIT; - - wake_up_interruptible - (&ch->ch_tun.un_flags_wait); - } - } - - /* - * Process Modem change signals. - */ - if (reason & IFMODEM) { - ch->ch_mistat = modem; - dgap_carrier(ch); - } - - /* - * Process break. - */ - if (reason & IFBREAK) { - if (ch->ch_tun.un_tty) { - /* A break has been indicated */ - ch->ch_err_break++; - tty_buffer_request_room - (ch->ch_tun.un_tty->port, 1); - tty_insert_flip_char(ch->ch_tun.un_tty->port, - 0, TTY_BREAK); - tty_flip_buffer_push(ch->ch_tun.un_tty->port); - } - } - - /* - * Process Transmit low. - */ - if (reason & IFTLW) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_LOW, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_LOW, - &lock_flags, &lock_flags2); - if (ch->ch_flags & CH_WLOW) { - ch->ch_flags &= ~CH_WLOW; - wake_up_interruptible(&ch->ch_flags_wait); - } - } - - /* - * Process Transmit empty. - */ - if (reason & IFTEM) { - dgap_write_wakeup(bd, ch, &ch->ch_tun, UN_EMPTY, - &lock_flags, &lock_flags2); - dgap_write_wakeup(bd, ch, &ch->ch_pun, UN_EMPTY, - &lock_flags, &lock_flags2); - if (ch->ch_flags & CH_WEMPTY) { - ch->ch_flags &= ~CH_WEMPTY; - wake_up_interruptible(&ch->ch_flags_wait); - } - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - -next: - tail = (tail + 4) & (EVMAX - EVSTART - 4); - } - - writew(tail, &eaddr->ev_tail); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * Our board poller function. - */ -static void dgap_poll_tasklet(unsigned long data) -{ - struct board_t *bd = (struct board_t *)data; - ulong lock_flags; - char __iomem *vaddr; - u16 head, tail; - - if (!bd || (bd->magic != DGAP_BOARD_MAGIC)) - return; - - if (bd->inhibit_poller) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - - vaddr = bd->re_map_membase; - - /* - * If board is ready, parse deeper to see if there is anything to do. - */ - if (bd->state == BOARD_READY) { - struct ev_t __iomem *eaddr; - - if (!bd->re_map_membase) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - if (!bd->re_map_port) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - if (!bd->nasync) - goto out; - - eaddr = (struct ev_t __iomem *)(vaddr + EVBUF); - - /* Get our head and tail */ - head = readw(&eaddr->ev_head); - tail = readw(&eaddr->ev_tail); - - /* - * If there is an event pending. Go service it. - */ - if (head != tail) { - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - dgap_event(bd); - spin_lock_irqsave(&bd->bd_lock, lock_flags); - } - -out: - /* - * If board is doing interrupts, ACK the interrupt. - */ - if (bd->intr_running) - readb(bd->re_map_port + 2); - - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return; - } - - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/* - * dgap_found_board() - * - * A board has been found, init it. - */ -static struct board_t *dgap_found_board(struct pci_dev *pdev, int id, - int boardnum) -{ - struct board_t *brd; - unsigned int pci_irq; - int i; - int ret; - - /* get the board structure and prep it */ - brd = kzalloc(sizeof(struct board_t), GFP_KERNEL); - if (!brd) - return ERR_PTR(-ENOMEM); - - /* store the info for the board we've found */ - brd->magic = DGAP_BOARD_MAGIC; - brd->boardnum = boardnum; - brd->vendor = dgap_pci_tbl[id].vendor; - brd->device = dgap_pci_tbl[id].device; - brd->pdev = pdev; - brd->pci_bus = pdev->bus->number; - brd->pci_slot = PCI_SLOT(pdev->devfn); - brd->name = dgap_ids[id].name; - brd->maxports = dgap_ids[id].maxports; - brd->type = dgap_ids[id].config_type; - brd->dpatype = dgap_ids[id].dpatype; - brd->dpastatus = BD_NOFEP; - init_waitqueue_head(&brd->state_wait); - - spin_lock_init(&brd->bd_lock); - - brd->inhibit_poller = FALSE; - brd->wait_for_bios = 0; - brd->wait_for_fep = 0; - - for (i = 0; i < MAXPORTS; i++) - brd->channels[i] = NULL; - - /* store which card & revision we have */ - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &brd->subvendor); - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &brd->subdevice); - pci_read_config_byte(pdev, PCI_REVISION_ID, &brd->rev); - - pci_irq = pdev->irq; - brd->irq = pci_irq; - - /* get the PCI Base Address Registers */ - - /* Xr Jupiter and EPC use BAR 2 */ - if (brd->device == PCI_DEV_XRJ_DID || brd->device == PCI_DEV_EPCJ_DID) { - brd->membase = pci_resource_start(pdev, 2); - brd->membase_end = pci_resource_end(pdev, 2); - } - /* Everyone else uses BAR 0 */ - else { - brd->membase = pci_resource_start(pdev, 0); - brd->membase_end = pci_resource_end(pdev, 0); - } - - if (!brd->membase) { - ret = -ENODEV; - goto free_brd; - } - - if (brd->membase & 1) - brd->membase &= ~3; - else - brd->membase &= ~15; - - /* - * On the PCI boards, there is no IO space allocated - * The I/O registers will be in the first 3 bytes of the - * upper 2MB of the 4MB memory space. The board memory - * will be mapped into the low 2MB of the 4MB memory space - */ - brd->port = brd->membase + PCI_IO_OFFSET; - brd->port_end = brd->port + PCI_IO_SIZE_DGAP; - - /* - * Special initialization for non-PLX boards - */ - if (brd->device != PCI_DEV_XRJ_DID && brd->device != PCI_DEV_EPCJ_DID) { - unsigned short cmd; - - pci_write_config_byte(pdev, 0x40, 0); - pci_write_config_byte(pdev, 0x46, 0); - - /* Limit burst length to 2 doubleword transactions */ - pci_write_config_byte(pdev, 0x42, 1); - - /* - * Enable IO and mem if not already done. - * This was needed for support on Itanium. - */ - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(pdev, PCI_COMMAND, cmd); - } - - /* init our poll helper tasklet */ - tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, - (unsigned long)brd); - - ret = dgap_remap(brd); - if (ret) - goto free_brd; - - pr_info("dgap: board %d: %s (rev %d), irq %ld\n", - boardnum, brd->name, brd->rev, brd->irq); - - return brd; - -free_brd: - kfree(brd); - - return ERR_PTR(ret); -} - -/* - * dgap_intr() - * - * Driver interrupt handler. - */ -static irqreturn_t dgap_intr(int irq, void *voidbrd) -{ - struct board_t *brd = voidbrd; - - if (!brd) - return IRQ_NONE; - - /* - * Check to make sure its for us. - */ - if (brd->magic != DGAP_BOARD_MAGIC) - return IRQ_NONE; - - brd->intr_count++; - - /* - * Schedule tasklet to run at a better time. - */ - tasklet_schedule(&brd->helper_tasklet); - return IRQ_HANDLED; -} - -/***************************************************************************** -* -* Function: -* -* dgap_poll_handler -* -* Author: -* -* Scott H Kilau -* -* Parameters: -* -* dummy -- ignored -* -* Return Values: -* -* none -* -* Description: -* -* As each timer expires, it determines (a) whether the "transmit" -* waiter needs to be woken up, and (b) whether the poller needs to -* be rescheduled. -* -******************************************************************************/ - -static void dgap_poll_handler(ulong dummy) -{ - unsigned int i; - struct board_t *brd; - unsigned long lock_flags; - ulong new_time; - - dgap_poll_counter++; - - /* - * Do not start the board state machine until - * driver tells us its up and running, and has - * everything it needs. - */ - if (dgap_driver_state != DRIVER_READY) - goto schedule_poller; - - /* - * If we have just 1 board, or the system is not SMP, - * then use the typical old style poller. - * Otherwise, use our new tasklet based poller, which should - * speed things up for multiple boards. - */ - if ((dgap_numboards == 1) || (num_online_cpus() <= 1)) { - for (i = 0; i < dgap_numboards; i++) { - brd = dgap_board[i]; - - if (brd->state == BOARD_FAILED) - continue; - if (!brd->intr_running) - /* Call the real board poller directly */ - dgap_poll_tasklet((unsigned long)brd); - } - } else { - /* - * Go thru each board, kicking off a - * tasklet for each if needed - */ - for (i = 0; i < dgap_numboards; i++) { - brd = dgap_board[i]; - - /* - * Attempt to grab the board lock. - * - * If we can't get it, no big deal, the next poll - * will get it. Basically, I just really don't want - * to spin in here, because I want to kick off my - * tasklets as fast as I can, and then get out the - * poller. - */ - if (!spin_trylock(&brd->bd_lock)) - continue; - - /* - * If board is in a failed state, don't bother - * scheduling a tasklet - */ - if (brd->state == BOARD_FAILED) { - spin_unlock(&brd->bd_lock); - continue; - } - - /* Schedule a poll helper task */ - if (!brd->intr_running) - tasklet_schedule(&brd->helper_tasklet); - - /* - * Can't do DGAP_UNLOCK here, as we don't have - * lock_flags because we did a trylock above. - */ - spin_unlock(&brd->bd_lock); - } - } - -schedule_poller: - - /* - * Schedule ourself back at the nominal wakeup interval. - */ - spin_lock_irqsave(&dgap_poll_lock, lock_flags); - dgap_poll_time += dgap_jiffies_from_ms(dgap_poll_tick); - - new_time = dgap_poll_time - jiffies; - - if ((ulong)new_time >= 2 * dgap_poll_tick) { - dgap_poll_time = - jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - } - - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data = 0; - dgap_poll_timer.expires = dgap_poll_time; - spin_unlock_irqrestore(&dgap_poll_lock, lock_flags); - - if (!dgap_poll_stop) - add_timer(&dgap_poll_timer); -} - -/*======================================================================= - * - * dgap_cmdb - Sends a 2 byte command to the FEP. - * - * ch - Pointer to channel structure. - * cmd - Command to be sent. - * byte1 - Integer containing first byte to be sent. - * byte2 - Integer containing second byte to be sent. - * ncmds - Wait until ncmds or fewer cmds are left - * in the cmd buffer before returning. - * - *=======================================================================*/ -static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1, - u8 byte2, uint ncmds) -{ - char __iomem *vaddr; - struct __iomem cm_t *cm_addr; - uint count; - uint n; - u16 head; - u16 tail; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check if board is still alive. - */ - if (ch->ch_bd->state == BOARD_FAILED) - return; - - /* - * Make sure the pointers are in range before - * writing to the FEP memory. - */ - vaddr = ch->ch_bd->re_map_membase; - - if (!vaddr) - return; - - cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF); - head = readw(&cm_addr->cm_head); - - /* - * Forget it if pointers out of range. - */ - if (head >= (CMDMAX - CMDSTART) || (head & 03)) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - - /* - * Put the data in the circular command buffer. - */ - writeb(cmd, (vaddr + head + CMDSTART + 0)); - writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1)); - writeb(byte1, (vaddr + head + CMDSTART + 2)); - writeb(byte2, (vaddr + head + CMDSTART + 3)); - - head = (head + 4) & (CMDMAX - CMDSTART - 4); - - writew(head, &cm_addr->cm_head); - - /* - * Wait if necessary before updating the head - * pointer to limit the number of outstanding - * commands to the FEP. If the time spent waiting - * is outlandish, declare the FEP dead. - */ - for (count = dgap_count ;;) { - head = readw(&cm_addr->cm_head); - tail = readw(&cm_addr->cm_tail); - - n = (head - tail) & (CMDMAX - CMDSTART - 4); - - if (n <= ncmds * sizeof(struct cm_t)) - break; - - if (--count == 0) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - udelay(10); - } -} - -/*======================================================================= - * - * dgap_cmdw - Sends a 1 word command to the FEP. - * - * ch - Pointer to channel structure. - * cmd - Command to be sent. - * word - Integer containing word to be sent. - * ncmds - Wait until ncmds or fewer cmds are left - * in the cmd buffer before returning. - * - *=======================================================================*/ -static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds) -{ - char __iomem *vaddr; - struct __iomem cm_t *cm_addr; - uint count; - uint n; - u16 head; - u16 tail; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check if board is still alive. - */ - if (ch->ch_bd->state == BOARD_FAILED) - return; - - /* - * Make sure the pointers are in range before - * writing to the FEP memory. - */ - vaddr = ch->ch_bd->re_map_membase; - if (!vaddr) - return; - - cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF); - head = readw(&cm_addr->cm_head); - - /* - * Forget it if pointers out of range. - */ - if (head >= (CMDMAX - CMDSTART) || (head & 03)) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - - /* - * Put the data in the circular command buffer. - */ - writeb(cmd, (vaddr + head + CMDSTART + 0)); - writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1)); - writew((u16)word, (vaddr + head + CMDSTART + 2)); - - head = (head + 4) & (CMDMAX - CMDSTART - 4); - - writew(head, &cm_addr->cm_head); - - /* - * Wait if necessary before updating the head - * pointer to limit the number of outstanding - * commands to the FEP. If the time spent waiting - * is outlandish, declare the FEP dead. - */ - for (count = dgap_count ;;) { - head = readw(&cm_addr->cm_head); - tail = readw(&cm_addr->cm_tail); - - n = (head - tail) & (CMDMAX - CMDSTART - 4); - - if (n <= ncmds * sizeof(struct cm_t)) - break; - - if (--count == 0) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - udelay(10); - } -} - -/*======================================================================= - * - * dgap_cmdw_ext - Sends a extended word command to the FEP. - * - * ch - Pointer to channel structure. - * cmd - Command to be sent. - * word - Integer containing word to be sent. - * ncmds - Wait until ncmds or fewer cmds are left - * in the cmd buffer before returning. - * - *=======================================================================*/ -static void dgap_cmdw_ext(struct channel_t *ch, u16 cmd, u16 word, uint ncmds) -{ - char __iomem *vaddr; - struct __iomem cm_t *cm_addr; - uint count; - uint n; - u16 head; - u16 tail; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check if board is still alive. - */ - if (ch->ch_bd->state == BOARD_FAILED) - return; - - /* - * Make sure the pointers are in range before - * writing to the FEP memory. - */ - vaddr = ch->ch_bd->re_map_membase; - if (!vaddr) - return; - - cm_addr = (struct cm_t __iomem *)(vaddr + CMDBUF); - head = readw(&cm_addr->cm_head); - - /* - * Forget it if pointers out of range. - */ - if (head >= (CMDMAX - CMDSTART) || (head & 03)) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - - /* - * Put the data in the circular command buffer. - */ - - /* Write an FF to tell the FEP that we want an extended command */ - writeb((u8)0xff, (vaddr + head + CMDSTART + 0)); - - writeb((u8)ch->ch_portnum, (vaddr + head + CMDSTART + 1)); - writew((u16)cmd, (vaddr + head + CMDSTART + 2)); - - /* - * If the second part of the command won't fit, - * put it at the beginning of the circular buffer. - */ - if (((head + 4) >= ((CMDMAX - CMDSTART)) || (head & 03))) - writew((u16)word, (vaddr + CMDSTART)); - else - writew((u16)word, (vaddr + head + CMDSTART + 4)); - - head = (head + 8) & (CMDMAX - CMDSTART - 4); - - writew(head, &cm_addr->cm_head); - - /* - * Wait if necessary before updating the head - * pointer to limit the number of outstanding - * commands to the FEP. If the time spent waiting - * is outlandish, declare the FEP dead. - */ - for (count = dgap_count ;;) { - head = readw(&cm_addr->cm_head); - tail = readw(&cm_addr->cm_tail); - - n = (head - tail) & (CMDMAX - CMDSTART - 4); - - if (n <= ncmds * sizeof(struct cm_t)) - break; - - if (--count == 0) { - ch->ch_bd->state = BOARD_FAILED; - return; - } - udelay(10); - } -} - -/*======================================================================= - * - * dgap_wmove - Write data to FEP buffer. - * - * ch - Pointer to channel structure. - * buf - Pointer to characters to be moved. - * cnt - Number of characters to move. - * - *=======================================================================*/ -static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt) -{ - int n; - char __iomem *taddr; - struct bs_t __iomem *bs; - u16 head; - - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - /* - * Check parameters. - */ - bs = ch->ch_bs; - head = readw(&bs->tx_head); - - /* - * If pointers are out of range, just return. - */ - if ((cnt > ch->ch_tsize) || - (unsigned)(head - ch->ch_tstart) >= ch->ch_tsize) - return; - - /* - * If the write wraps over the top of the circular buffer, - * move the portion up to the wrap point, and reset the - * pointers to the bottom. - */ - n = ch->ch_tstart + ch->ch_tsize - head; - - if (cnt >= n) { - cnt -= n; - taddr = ch->ch_taddr + head; - memcpy_toio(taddr, buf, n); - head = ch->ch_tstart; - buf += n; - } - - /* - * Move rest of data. - */ - taddr = ch->ch_taddr + head; - n = cnt; - memcpy_toio(taddr, buf, n); - head += cnt; - - writew(head, &bs->tx_head); -} - -/* - * Calls the firmware to reset this channel. - */ -static void dgap_firmware_reset_port(struct channel_t *ch) -{ - dgap_cmdb(ch, CHRESET, 0, 0, 0); - - /* - * Now that the channel is reset, we need to make sure - * all the current settings get reapplied to the port - * in the firmware. - * - * So we will set the driver's cache of firmware - * settings all to 0, and then call param. - */ - ch->ch_fepiflag = 0; - ch->ch_fepcflag = 0; - ch->ch_fepoflag = 0; - ch->ch_fepstartc = 0; - ch->ch_fepstopc = 0; - ch->ch_fepastartc = 0; - ch->ch_fepastopc = 0; - ch->ch_mostat = 0; - ch->ch_hflow = 0; -} - -/*======================================================================= - * - * dgap_param - Set Digi parameters. - * - * struct tty_struct * - TTY for port. - * - *=======================================================================*/ -static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type) -{ - u16 head; - u16 cflag; - u16 iflag; - u8 mval; - u8 hflow; - - /* - * If baud rate is zero, flush queues, and set mval to drop DTR. - */ - if ((ch->ch_c_cflag & (CBAUD)) == 0) { - /* flush rx */ - head = readw(&ch->ch_bs->rx_head); - writew(head, &ch->ch_bs->rx_tail); - - /* flush tx */ - head = readw(&ch->ch_bs->tx_head); - writew(head, &ch->ch_bs->tx_tail); - - ch->ch_flags |= (CH_BAUD0); - - /* Drop RTS and DTR */ - ch->ch_mval &= ~(D_RTS(ch) | D_DTR(ch)); - mval = D_DTR(ch) | D_RTS(ch); - ch->ch_baud_info = 0; - - } else if (ch->ch_custom_speed && (bd->bd_flags & BD_FEP5PLUS)) { - /* - * Tell the fep to do the command - */ - - dgap_cmdw_ext(ch, 0xff01, ch->ch_custom_speed, 0); - - /* - * Now go get from fep mem, what the fep - * believes the custom baud rate is. - */ - ch->ch_custom_speed = dgap_get_custom_baud(ch); - ch->ch_baud_info = ch->ch_custom_speed; - - /* Handle transition from B0 */ - if (ch->ch_flags & CH_BAUD0) { - ch->ch_flags &= ~(CH_BAUD0); - ch->ch_mval |= (D_RTS(ch) | D_DTR(ch)); - } - mval = D_DTR(ch) | D_RTS(ch); - - } else { - /* - * Set baud rate, character size, and parity. - */ - - - int iindex = 0; - int jindex = 0; - int baud = 0; - - ulong bauds[4][16] = { - { /* slowbaud */ - 0, 50, 75, 110, - 134, 150, 200, 300, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* slowbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 }, - { /* fastbaud */ - 0, 57600, 76800, 115200, - 14400, 57600, 230400, 76800, - 115200, 230400, 28800, 460800, - 921600, 9600, 19200, 38400 }, - { /* fastbaud & CBAUDEX */ - 0, 57600, 115200, 230400, - 460800, 150, 200, 921600, - 600, 1200, 1800, 2400, - 4800, 9600, 19200, 38400 } - }; - - /* - * Only use the TXPrint baud rate if the - * terminal unit is NOT open - */ - if (!(ch->ch_tun.un_flags & UN_ISOPEN) && - un_type == DGAP_PRINT) - baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; - else - baud = C_BAUD(ch->ch_tun.un_tty) & 0xff; - - if (ch->ch_c_cflag & CBAUDEX) - iindex = 1; - - if (ch->ch_digi.digi_flags & DIGI_FAST) - iindex += 2; - - jindex = baud; - - if ((iindex >= 0) && (iindex < 4) && - (jindex >= 0) && (jindex < 16)) - baud = bauds[iindex][jindex]; - else - baud = 0; - - if (baud == 0) - baud = 9600; - - ch->ch_baud_info = baud; - - /* - * CBAUD has bit position 0x1000 set these days to - * indicate Linux baud rate remap. - * We use a different bit assignment for high speed. - * Clear this bit out while grabbing the parts of - * "cflag" we want. - */ - cflag = ch->ch_c_cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | - CSTOPB | CSIZE); - - /* - * HUPCL bit is used by FEP to indicate fast baud - * table is to be used. - */ - if ((ch->ch_digi.digi_flags & DIGI_FAST) || - (ch->ch_c_cflag & CBAUDEX)) - cflag |= HUPCL; - - if ((ch->ch_c_cflag & CBAUDEX) && - !(ch->ch_digi.digi_flags & DIGI_FAST)) { - /* - * The below code is trying to guarantee that only - * baud rates 115200, 230400, 460800, 921600 are - * remapped. We use exclusive or because the various - * baud rates share common bit positions and therefore - * can't be tested for easily. - */ - tcflag_t tcflag = (ch->ch_c_cflag & CBAUD) | CBAUDEX; - int baudpart = 0; - - /* - * Map high speed requests to index - * into FEP's baud table - */ - switch (tcflag) { - case B57600: - baudpart = 1; - break; -#ifdef B76800 - case B76800: - baudpart = 2; - break; -#endif - case B115200: - baudpart = 3; - break; - case B230400: - baudpart = 9; - break; - case B460800: - baudpart = 11; - break; -#ifdef B921600 - case B921600: - baudpart = 12; - break; -#endif - default: - baudpart = 0; - } - - if (baudpart) - cflag = (cflag & ~(CBAUD | CBAUDEX)) | baudpart; - } - - cflag &= 0xffff; - - if (cflag != ch->ch_fepcflag) { - ch->ch_fepcflag = (u16)(cflag & 0xffff); - - /* - * Okay to have channel and board - * locks held calling this - */ - dgap_cmdw(ch, SCFLAG, (u16)cflag, 0); - } - - /* Handle transition from B0 */ - if (ch->ch_flags & CH_BAUD0) { - ch->ch_flags &= ~(CH_BAUD0); - ch->ch_mval |= (D_RTS(ch) | D_DTR(ch)); - } - mval = D_DTR(ch) | D_RTS(ch); - } - - /* - * Get input flags. - */ - iflag = ch->ch_c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | - INPCK | ISTRIP | IXON | IXANY | IXOFF); - - if ((ch->ch_startc == _POSIX_VDISABLE) || - (ch->ch_stopc == _POSIX_VDISABLE)) { - iflag &= ~(IXON | IXOFF); - ch->ch_c_iflag &= ~(IXON | IXOFF); - } - - /* - * Only the IBM Xr card can switch between - * 232 and 422 modes on the fly - */ - if (bd->device == PCI_DEV_XR_IBM_DID) { - if (ch->ch_digi.digi_flags & DIGI_422) - dgap_cmdb(ch, SCOMMODE, MODE_422, 0, 0); - else - dgap_cmdb(ch, SCOMMODE, MODE_232, 0, 0); - } - - if (ch->ch_digi.digi_flags & DIGI_ALTPIN) - iflag |= IALTPIN; - - if (iflag != ch->ch_fepiflag) { - ch->ch_fepiflag = iflag; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdw(ch, SIFLAG, (u16)ch->ch_fepiflag, 0); - } - - /* - * Select hardware handshaking. - */ - hflow = 0; - - if (ch->ch_c_cflag & CRTSCTS) - hflow |= (D_RTS(ch) | D_CTS(ch)); - if (ch->ch_digi.digi_flags & RTSPACE) - hflow |= D_RTS(ch); - if (ch->ch_digi.digi_flags & DTRPACE) - hflow |= D_DTR(ch); - if (ch->ch_digi.digi_flags & CTSPACE) - hflow |= D_CTS(ch); - if (ch->ch_digi.digi_flags & DSRPACE) - hflow |= D_DSR(ch); - if (ch->ch_digi.digi_flags & DCDPACE) - hflow |= D_CD(ch); - - if (hflow != ch->ch_hflow) { - ch->ch_hflow = hflow; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SHFLOW, (u8)hflow, 0xff, 0); - } - - /* - * Set RTS and/or DTR Toggle if needed, - * but only if product is FEP5+ based. - */ - if (bd->bd_flags & BD_FEP5PLUS) { - u16 hflow2 = 0; - - if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) - hflow2 |= (D_RTS(ch)); - if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) - hflow2 |= (D_DTR(ch)); - - dgap_cmdw_ext(ch, 0xff03, hflow2, 0); - } - - /* - * Set modem control lines. - */ - - mval ^= ch->ch_mforce & (mval ^ ch->ch_mval); - - if (ch->ch_mostat ^ mval) { - ch->ch_mostat = mval; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SMODEM, (u8)mval, D_RTS(ch) | D_DTR(ch), 0); - } - - /* - * Read modem signals, and then call carrier function. - */ - ch->ch_mistat = readb(&ch->ch_bs->m_stat); - dgap_carrier(ch); - - /* - * Set the start and stop characters. - */ - if (ch->ch_startc != ch->ch_fepstartc || - ch->ch_stopc != ch->ch_fepstopc) { - ch->ch_fepstartc = ch->ch_startc; - ch->ch_fepstopc = ch->ch_stopc; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SFLOWC, ch->ch_fepstartc, ch->ch_fepstopc, 0); - } - - /* - * Set the Auxiliary start and stop characters. - */ - if (ch->ch_astartc != ch->ch_fepastartc || - ch->ch_astopc != ch->ch_fepastopc) { - ch->ch_fepastartc = ch->ch_astartc; - ch->ch_fepastopc = ch->ch_astopc; - - /* Okay to have channel and board locks held calling this */ - dgap_cmdb(ch, SAFLOWC, ch->ch_fepastartc, ch->ch_fepastopc, 0); - } - - return 0; -} - -/* - * dgap_block_til_ready() - * - * Wait for DCD, if needed. - */ -static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, - struct channel_t *ch) -{ - int retval = 0; - struct un_t *un; - ulong lock_flags; - uint old_flags; - int sleep_on_un_flags; - - if (!tty || tty->magic != TTY_MAGIC || !file || !ch || - ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - ch->ch_wopen++; - - /* Loop forever */ - while (1) { - sleep_on_un_flags = 0; - - /* - * If board has failed somehow during our sleep, - * bail with error. - */ - if (ch->ch_bd->state == BOARD_FAILED) { - retval = -EIO; - break; - } - - /* If tty was hung up, break out of loop and set error. */ - if (tty_hung_up_p(file)) { - retval = -EAGAIN; - break; - } - - /* - * If either unit is in the middle of the fragile part of close, - * we just cannot touch the channel safely. - * Go back to sleep, knowing that when the channel can be - * touched safely, the close routine will signal the - * ch_wait_flags to wake us back up. - */ - if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & - UN_CLOSING)) { - /* - * Our conditions to leave cleanly and happily: - * 1) NONBLOCKING on the tty is set. - * 2) CLOCAL is set. - * 3) DCD (fake or real) is active. - */ - - if (file->f_flags & O_NONBLOCK) - break; - - if (tty->flags & (1 << TTY_IO_ERROR)) - break; - - if (ch->ch_flags & CH_CD) - break; - - if (ch->ch_flags & CH_FCAR) - break; - } else { - sleep_on_un_flags = 1; - } - - /* - * If there is a signal pending, the user probably - * interrupted (ctrl-c) us. - * Leave loop with error set. - */ - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - - /* - * Store the flags before we let go of channel lock - */ - if (sleep_on_un_flags) - old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags; - else - old_flags = ch->ch_flags; - - /* - * Let go of channel lock before calling schedule. - * Our poller will get any FEP events and wake us up when DCD - * eventually goes active. - */ - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - /* - * Wait for something in the flags to change - * from the current value. - */ - if (sleep_on_un_flags) { - retval = wait_event_interruptible(un->un_flags_wait, - (old_flags != (ch->ch_tun.un_flags | - ch->ch_pun.un_flags))); - } else { - retval = wait_event_interruptible(ch->ch_flags_wait, - (old_flags != ch->ch_flags)); - } - - /* - * We got woken up for some reason. - * Before looping around, grab our channel lock. - */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - } - - ch->ch_wopen--; - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return retval; -} - -/* - * dgap_tty_flush_buffer() - * - * Flush Tx buffer (make in == out) - */ -static void dgap_tty_flush_buffer(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - u16 head; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_flags &= ~CH_STOP; - head = readw(&ch->ch_bs->tx_head); - dgap_cmdw(ch, FLUSHTX, (u16)head, 0); - dgap_cmdw(ch, RESUMETX, 0, 0); - if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_tun.un_flags_wait); - } - if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_pun.un_flags_wait); - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - tty_wakeup(tty); -} - -/* - * dgap_tty_hangup() - * - * Hangup the port. Like a close, but don't wait for output to drain. - */ -static void dgap_tty_hangup(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - /* flush the transmit queues */ - dgap_tty_flush_buffer(tty); -} - -/* - * dgap_tty_chars_in_buffer() - * - * Return number of characters that have not been transmitted yet. - * - * This routine is used by the line discipline to determine if there - * is data waiting to be transmitted/drained/flushed or not. - */ -static int dgap_tty_chars_in_buffer(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - u8 tbusy; - uint chars; - u16 thead, ttail, tmask, chead, ctail; - ulong lock_flags = 0; - ulong lock_flags2 = 0; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - - bs = ch->ch_bs; - if (!bs) - return 0; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - tmask = (ch->ch_tsize - 1); - - /* Get Transmit queue pointers */ - thead = readw(&bs->tx_head) & tmask; - ttail = readw(&bs->tx_tail) & tmask; - - /* Get tbusy flag */ - tbusy = readb(&bs->tbusy); - - /* Get Command queue pointers */ - chead = readw(&ch->ch_cm->cm_head); - ctail = readw(&ch->ch_cm->cm_tail); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - /* - * The only way we know for sure if there is no pending - * data left to be transferred, is if: - * 1) Transmit head and tail are equal (empty). - * 2) Command queue head and tail are equal (empty). - * 3) The "TBUSY" flag is 0. (Transmitter not busy). - */ - - if ((ttail == thead) && (tbusy == 0) && (chead == ctail)) { - chars = 0; - } else { - if (thead >= ttail) - chars = thead - ttail; - else - chars = thead - ttail + ch->ch_tsize; - /* - * Fudge factor here. - * If chars is zero, we know that the command queue had - * something in it or tbusy was set. Because we cannot - * be sure if there is still some data to be transmitted, - * lets lie, and tell ld we have 1 byte left. - */ - if (chars == 0) { - /* - * If TBUSY is still set, and our tx buffers are empty, - * force the firmware to send me another wakeup after - * TBUSY has been cleared. - */ - if (tbusy != 0) { - spin_lock_irqsave(&ch->ch_lock, lock_flags); - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - spin_unlock_irqrestore(&ch->ch_lock, - lock_flags); - } - chars = 1; - } - } - - return chars; -} - -static int dgap_wait_for_drain(struct tty_struct *tty) -{ - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - int ret = 0; - uint count = 1; - ulong lock_flags = 0; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bs = ch->ch_bs; - if (!bs) - return -EIO; - - /* Loop until data is drained */ - while (count != 0) { - count = dgap_tty_chars_in_buffer(tty); - - if (count == 0) - break; - - /* Set flag waiting for drain */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - /* Go to sleep till we get woken up */ - ret = wait_event_interruptible(un->un_flags_wait, - ((un->un_flags & UN_EMPTY) == 0)); - /* If ret is non-zero, user ctrl-c'ed us */ - if (ret) - break; - } - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - un->un_flags &= ~(UN_EMPTY); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return ret; -} - -/* - * dgap_maxcps_room - * - * Reduces bytes_available to the max number of characters - * that can be sent currently given the maxcps value, and - * returns the new bytes_available. This only affects printer - * output. - */ -static int dgap_maxcps_room(struct channel_t *ch, struct un_t *un, - int bytes_available) -{ - /* - * If its not the Transparent print device, return - * the full data amount. - */ - if (un->un_type != DGAP_PRINT) - return bytes_available; - - if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) { - int cps_limit = 0; - unsigned long current_time = jiffies; - unsigned long buffer_time = current_time + - (HZ * ch->ch_digi.digi_bufsize) / - ch->ch_digi.digi_maxcps; - - if (ch->ch_cpstime < current_time) { - /* buffer is empty */ - ch->ch_cpstime = current_time; /* reset ch_cpstime */ - cps_limit = ch->ch_digi.digi_bufsize; - } else if (ch->ch_cpstime < buffer_time) { - /* still room in the buffer */ - cps_limit = ((buffer_time - ch->ch_cpstime) * - ch->ch_digi.digi_maxcps) / HZ; - } else { - /* no room in the buffer */ - cps_limit = 0; - } - - bytes_available = min(cps_limit, bytes_available); - } - - return bytes_available; -} - -static inline void dgap_set_firmware_event(struct un_t *un, unsigned int event) -{ - struct channel_t *ch; - struct bs_t __iomem *bs; - - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - bs = ch->ch_bs; - if (!bs) - return; - - if ((event & UN_LOW) != 0) { - if ((un->un_flags & UN_LOW) == 0) { - un->un_flags |= UN_LOW; - writeb(1, &bs->ilow); - } - } - if ((event & UN_LOW) != 0) { - if ((un->un_flags & UN_EMPTY) == 0) { - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - } - } -} - -/* - * dgap_tty_write_room() - * - * Return space available in Tx buffer - */ -static int dgap_tty_write_room(struct tty_struct *tty) -{ - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - u16 head, tail, tmask; - int ret; - ulong lock_flags = 0; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - bs = ch->ch_bs; - if (!bs) - return 0; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - tmask = ch->ch_tsize - 1; - head = readw(&bs->tx_head) & tmask; - tail = readw(&bs->tx_tail) & tmask; - - ret = tail - head - 1; - if (ret < 0) - ret += ch->ch_tsize; - - /* Limit printer to maxcps */ - ret = dgap_maxcps_room(ch, un, ret); - - /* - * If we are printer device, leave space for - * possibly both the on and off strings. - */ - if (un->un_type == DGAP_PRINT) { - if (!(ch->ch_flags & CH_PRON)) - ret -= ch->ch_digi.digi_onlen; - ret -= ch->ch_digi.digi_offlen; - } else { - if (ch->ch_flags & CH_PRON) - ret -= ch->ch_digi.digi_offlen; - } - - if (ret < 0) - ret = 0; - - /* - * Schedule FEP to wake us up if needed. - * - * TODO: This might be overkill... - * Do we really need to schedule callbacks from the FEP - * in every case? Can we get smarter based on ret? - */ - dgap_set_firmware_event(un, UN_LOW | UN_EMPTY); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return ret; -} - -/* - * dgap_tty_write() - * - * Take data from the user or kernel and send it out to the FEP. - * In here exists all the Transparent Print magic as well. - */ -static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - char __iomem *vaddr; - u16 head, tail, tmask, remain; - int bufcount, n; - ulong lock_flags; - - if (!tty) - return 0; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - - bs = ch->ch_bs; - if (!bs) - return 0; - - if (!count) - return 0; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - /* Get our space available for the channel from the board */ - tmask = ch->ch_tsize - 1; - head = readw(&(bs->tx_head)) & tmask; - tail = readw(&(bs->tx_tail)) & tmask; - - bufcount = tail - head - 1; - if (bufcount < 0) - bufcount += ch->ch_tsize; - - /* - * Limit printer output to maxcps overall, with bursts allowed - * up to bufsize characters. - */ - bufcount = dgap_maxcps_room(ch, un, bufcount); - - /* - * Take minimum of what the user wants to send, and the - * space available in the FEP buffer. - */ - count = min(count, bufcount); - - /* - * Bail if no space left. - */ - if (count <= 0) { - dgap_set_firmware_event(un, UN_LOW | UN_EMPTY); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - return 0; - } - - /* - * Output the printer ON string, if we are in terminal mode, but - * need to be in printer mode. - */ - if ((un->un_type == DGAP_PRINT) && !(ch->ch_flags & CH_PRON)) { - dgap_wmove(ch, ch->ch_digi.digi_onstr, - (int)ch->ch_digi.digi_onlen); - head = readw(&bs->tx_head) & tmask; - ch->ch_flags |= CH_PRON; - } - - /* - * On the other hand, output the printer OFF string, if we are - * currently in printer mode, but need to output to the terminal. - */ - if ((un->un_type != DGAP_PRINT) && (ch->ch_flags & CH_PRON)) { - dgap_wmove(ch, ch->ch_digi.digi_offstr, - (int)ch->ch_digi.digi_offlen); - head = readw(&bs->tx_head) & tmask; - ch->ch_flags &= ~CH_PRON; - } - - n = count; - - /* - * If the write wraps over the top of the circular buffer, - * move the portion up to the wrap point, and reset the - * pointers to the bottom. - */ - remain = ch->ch_tstart + ch->ch_tsize - head; - - if (n >= remain) { - n -= remain; - vaddr = ch->ch_taddr + head; - - memcpy_toio(vaddr, (u8 *)buf, remain); - - head = ch->ch_tstart; - buf += remain; - } - - if (n > 0) { - /* - * Move rest of data. - */ - vaddr = ch->ch_taddr + head; - remain = n; - - memcpy_toio(vaddr, (u8 *)buf, remain); - head += remain; - } - - if (count) { - ch->ch_txcount += count; - head &= tmask; - writew(head, &bs->tx_head); - } - - dgap_set_firmware_event(un, UN_LOW | UN_EMPTY); - - /* - * If this is the print device, and the - * printer is still on, we need to turn it - * off before going idle. If the buffer is - * non-empty, wait until it goes empty. - * Otherwise turn it off right now. - */ - if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) { - tail = readw(&bs->tx_tail) & tmask; - - if (tail != head) { - un->un_flags |= UN_EMPTY; - writeb(1, &bs->iempty); - } else { - dgap_wmove(ch, ch->ch_digi.digi_offstr, - (int)ch->ch_digi.digi_offlen); - head = readw(&bs->tx_head) & tmask; - ch->ch_flags &= ~CH_PRON; - } - } - - /* Update printer buffer empty time. */ - if ((un->un_type == DGAP_PRINT) && (ch->ch_digi.digi_maxcps > 0) - && (ch->ch_digi.digi_bufsize > 0)) { - ch->ch_cpstime += (HZ * count) / ch->ch_digi.digi_maxcps; - } - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return count; -} - -/* - * dgap_tty_put_char() - * - * Put a character into ch->ch_buf - * - * - used by the line discipline for OPOST processing - */ -static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c) -{ - /* - * Simply call tty_write. - */ - dgap_tty_write(tty, &c, 1); - return 1; -} - -/* - * Return modem signals to ld. - */ -static int dgap_tty_tiocmget(struct tty_struct *tty) -{ - struct channel_t *ch; - struct un_t *un; - int result; - u8 mstat; - ulong lock_flags; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - mstat = readb(&ch->ch_bs->m_stat); - /* Append any outbound signals that might be pending... */ - mstat |= ch->ch_mostat; - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - result = 0; - - if (mstat & D_DTR(ch)) - result |= TIOCM_DTR; - if (mstat & D_RTS(ch)) - result |= TIOCM_RTS; - if (mstat & D_CTS(ch)) - result |= TIOCM_CTS; - if (mstat & D_DSR(ch)) - result |= TIOCM_DSR; - if (mstat & D_RI(ch)) - result |= TIOCM_RI; - if (mstat & D_CD(ch)) - result |= TIOCM_CD; - - return result; -} - -/* - * dgap_tty_tiocmset() - * - * Set modem signals, called by ld. - */ -static int dgap_tty_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (set & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval |= D_RTS(ch); - } - - if (set & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval |= D_DTR(ch); - } - - if (clear & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval &= ~(D_RTS(ch)); - } - - if (clear & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval &= ~(D_DTR(ch)); - } - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_send_break() - * - * Send a Break, called by ld. - */ -static int dgap_tty_send_break(struct tty_struct *tty, int msec) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - switch (msec) { - case -1: - msec = 0xFFFF; - break; - case 0: - msec = 1; - break; - default: - msec /= 10; - break; - } - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); -#if 0 - dgap_cmdw(ch, SBREAK, (u16) SBREAK_TIME, 0); -#endif - dgap_cmdw(ch, SBREAK, (u16)msec, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_wait_until_sent() - * - * wait until data has been transmitted, called by ld. - */ -static void dgap_tty_wait_until_sent(struct tty_struct *tty, int timeout) -{ - dgap_wait_for_drain(tty); -} - -/* - * dgap_send_xchar() - * - * send a high priority character, called by ld. - */ -static void dgap_tty_send_xchar(struct tty_struct *tty, char c) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* - * This is technically what we should do. - * However, the NIST tests specifically want - * to see each XON or XOFF character that it - * sends, so lets just send each character - * by hand... - */ -#if 0 - if (c == STOP_CHAR(tty)) - dgap_cmdw(ch, RPAUSE, 0, 0); - else if (c == START_CHAR(tty)) - dgap_cmdw(ch, RRESUME, 0, 0); - else - dgap_wmove(ch, &c, 1); -#else - dgap_wmove(ch, &c, 1); -#endif - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/* - * Return modem signals to ld. - */ -static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value) -{ - int result; - u8 mstat; - ulong lock_flags; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - mstat = readb(&ch->ch_bs->m_stat); - /* Append any outbound signals that might be pending... */ - mstat |= ch->ch_mostat; - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - result = 0; - - if (mstat & D_DTR(ch)) - result |= TIOCM_DTR; - if (mstat & D_RTS(ch)) - result |= TIOCM_RTS; - if (mstat & D_CTS(ch)) - result |= TIOCM_CTS; - if (mstat & D_DSR(ch)) - result |= TIOCM_DSR; - if (mstat & D_RI(ch)) - result |= TIOCM_RI; - if (mstat & D_CD(ch)) - result |= TIOCM_CD; - - return put_user(result, value); -} - -/* - * dgap_set_modem_info() - * - * Set modem signals, called by ld. - */ -static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd, - struct un_t *un, unsigned int command, - unsigned int __user *value) -{ - int ret; - unsigned int arg; - ulong lock_flags; - ulong lock_flags2; - - ret = get_user(arg, value); - if (ret) - return ret; - - switch (command) { - case TIOCMBIS: - if (arg & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval |= D_RTS(ch); - } - - if (arg & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval |= D_DTR(ch); - } - - break; - - case TIOCMBIC: - if (arg & TIOCM_RTS) { - ch->ch_mforce |= D_RTS(ch); - ch->ch_mval &= ~(D_RTS(ch)); - } - - if (arg & TIOCM_DTR) { - ch->ch_mforce |= D_DTR(ch); - ch->ch_mval &= ~(D_DTR(ch)); - } - - break; - - case TIOCMSET: - ch->ch_mforce = D_DTR(ch) | D_RTS(ch); - - if (arg & TIOCM_RTS) - ch->ch_mval |= D_RTS(ch); - else - ch->ch_mval &= ~(D_RTS(ch)); - - if (arg & TIOCM_DTR) - ch->ch_mval |= (D_DTR(ch)); - else - ch->ch_mval &= ~(D_DTR(ch)); - - break; - - default: - return -EINVAL; - } - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_digigeta() - * - * Ioctl to get the information for ditty. - * - * - * - */ -static int dgap_tty_digigeta(struct channel_t *ch, - struct digi_t __user *retinfo) -{ - struct digi_t tmp; - ulong lock_flags; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - memcpy(&tmp, &ch->ch_digi, sizeof(tmp)); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * dgap_tty_digiseta() - * - * Ioctl to set the information for ditty. - * - * - * - */ -static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd, - struct un_t *un, struct digi_t __user *new_info) -{ - struct digi_t new_digi; - ulong lock_flags = 0; - unsigned long lock_flags2; - - if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) - return -EFAULT; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - memcpy(&ch->ch_digi, &new_digi, sizeof(struct digi_t)); - - if (ch->ch_digi.digi_maxcps < 1) - ch->ch_digi.digi_maxcps = 1; - - if (ch->ch_digi.digi_maxcps > 10000) - ch->ch_digi.digi_maxcps = 10000; - - if (ch->ch_digi.digi_bufsize < 10) - ch->ch_digi.digi_bufsize = 10; - - if (ch->ch_digi.digi_maxchar < 1) - ch->ch_digi.digi_maxchar = 1; - - if (ch->ch_digi.digi_maxchar > ch->ch_digi.digi_bufsize) - ch->ch_digi.digi_maxchar = ch->ch_digi.digi_bufsize; - - if (ch->ch_digi.digi_onlen > DIGI_PLEN) - ch->ch_digi.digi_onlen = DIGI_PLEN; - - if (ch->ch_digi.digi_offlen > DIGI_PLEN) - ch->ch_digi.digi_offlen = DIGI_PLEN; - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_digigetedelay() - * - * Ioctl to get the current edelay setting. - * - * - * - */ -static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo) -{ - struct channel_t *ch; - struct un_t *un; - int tmp; - ulong lock_flags; - - if (!retinfo) - return -EFAULT; - - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - tmp = readw(&ch->ch_bs->edelay); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * dgap_tty_digisetedelay() - * - * Ioctl to set the EDELAY setting - * - */ -static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd, - struct un_t *un, int __user *new_info) -{ - int new_digi; - ulong lock_flags; - ulong lock_flags2; - - if (copy_from_user(&new_digi, new_info, sizeof(int))) - return -EFAULT; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - writew((u16)new_digi, &ch->ch_bs->edelay); - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; -} - -/* - * dgap_tty_digigetcustombaud() - * - * Ioctl to get the current custom baud rate setting. - */ -static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un, - int __user *retinfo) -{ - int tmp; - ulong lock_flags; - - if (!retinfo) - return -EFAULT; - - memset(&tmp, 0, sizeof(tmp)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - tmp = dgap_get_custom_baud(ch); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -/* - * dgap_tty_digisetcustombaud() - * - * Ioctl to set the custom baud rate setting - */ -static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd, - struct un_t *un, int __user *new_info) -{ - uint new_rate; - ulong lock_flags; - ulong lock_flags2; - - if (copy_from_user(&new_rate, new_info, sizeof(unsigned int))) - return -EFAULT; - - if (bd->bd_flags & BD_FEP5PLUS) { - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_custom_speed = new_rate; - - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - } - - return 0; -} - -/* - * dgap_set_termios() - */ -static void dgap_tty_set_termios(struct tty_struct *tty, - struct ktermios *old_termios) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - unsigned long lock_flags; - unsigned long lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_c_cflag = tty->termios.c_cflag; - ch->ch_c_iflag = tty->termios.c_iflag; - ch->ch_c_oflag = tty->termios.c_oflag; - ch->ch_c_lflag = tty->termios.c_lflag; - ch->ch_startc = tty->termios.c_cc[VSTART]; - ch->ch_stopc = tty->termios.c_cc[VSTOP]; - - dgap_carrier(ch); - dgap_param(ch, bd, un->un_type); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static void dgap_tty_throttle(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_flags |= (CH_RXBLOCK); -#if 1 - dgap_cmdw(ch, RPAUSE, 0, 0); -#endif - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static void dgap_tty_unthrottle(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - ch->ch_flags &= ~(CH_RXBLOCK); - -#if 1 - dgap_cmdw(ch, RRESUME, 0, 0); -#endif - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static struct board_t *find_board_by_major(unsigned int major) -{ - unsigned int i; - - for (i = 0; i < MAXBOARDS; i++) { - struct board_t *brd = dgap_board[i]; - - if (!brd) - return NULL; - if (major == brd->serial_driver->major || - major == brd->print_driver->major) - return brd; - } - - return NULL; -} - -/************************************************************************ - * - * TTY Entry points and helper functions - * - ************************************************************************/ - -/* - * dgap_tty_open() - * - */ -static int dgap_tty_open(struct tty_struct *tty, struct file *file) -{ - struct board_t *brd; - struct channel_t *ch; - struct un_t *un; - struct bs_t __iomem *bs; - uint major; - uint minor; - int rc; - ulong lock_flags; - ulong lock_flags2; - u16 head; - - major = MAJOR(tty_devnum(tty)); - minor = MINOR(tty_devnum(tty)); - - brd = find_board_by_major(major); - if (!brd) - return -EIO; - - /* - * If board is not yet up to a state of READY, go to - * sleep waiting for it to happen or they cancel the open. - */ - rc = wait_event_interruptible(brd->state_wait, - (brd->state & BOARD_READY)); - - if (rc) - return rc; - - spin_lock_irqsave(&brd->bd_lock, lock_flags); - - /* The wait above should guarantee this cannot happen */ - if (brd->state != BOARD_READY) { - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* If opened device is greater than our number of ports, bail. */ - if (MINOR(tty_devnum(tty)) > brd->nasync) { - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - ch = brd->channels[minor]; - if (!ch) { - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* Grab channel lock */ - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* Figure out our type */ - if (major == brd->serial_driver->major) { - un = &brd->channels[minor]->ch_tun; - un->un_type = DGAP_SERIAL; - } else if (major == brd->print_driver->major) { - un = &brd->channels[minor]->ch_pun; - un->un_type = DGAP_PRINT; - } else { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* Store our unit into driver_data, so we always have it available. */ - tty->driver_data = un; - - /* - * Error if channel info pointer is NULL. - */ - bs = ch->ch_bs; - if (!bs) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - return -EIO; - } - - /* - * Initialize tty's - */ - if (!(un->un_flags & UN_ISOPEN)) { - /* Store important variables. */ - un->un_tty = tty; - - /* Maybe do something here to the TTY struct as well? */ - } - - /* - * Initialize if neither terminal or printer is open. - */ - if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_ISOPEN)) { - ch->ch_mforce = 0; - ch->ch_mval = 0; - - /* - * Flush input queue. - */ - head = readw(&bs->rx_head); - writew(head, &bs->rx_tail); - - ch->ch_flags = 0; - ch->pscan_state = 0; - ch->pscan_savechar = 0; - - ch->ch_c_cflag = tty->termios.c_cflag; - ch->ch_c_iflag = tty->termios.c_iflag; - ch->ch_c_oflag = tty->termios.c_oflag; - ch->ch_c_lflag = tty->termios.c_lflag; - ch->ch_startc = tty->termios.c_cc[VSTART]; - ch->ch_stopc = tty->termios.c_cc[VSTOP]; - - /* TODO: flush our TTY struct here? */ - } - - dgap_carrier(ch); - /* - * Run param in case we changed anything - */ - dgap_param(ch, brd, un->un_type); - - /* - * follow protocol for opening port - */ - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&brd->bd_lock, lock_flags); - - rc = dgap_block_til_ready(tty, file, ch); - - if (!un->un_tty) - return -ENODEV; - - /* No going back now, increment our unit and channel counters */ - spin_lock_irqsave(&ch->ch_lock, lock_flags); - ch->ch_open_count++; - un->un_open_count++; - un->un_flags |= (UN_ISOPEN); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - return rc; -} - -/* - * dgap_tty_close() - * - */ -static void dgap_tty_close(struct tty_struct *tty, struct file *file) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - /* - * Determine if this is the last close or not - and if we agree about - * which type of close it is with the Line Discipline - */ - if ((tty->count == 1) && (un->un_open_count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. un_open_count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - un->un_open_count = 1; - } - - if (--un->un_open_count < 0) - un->un_open_count = 0; - - ch->ch_open_count--; - - if (ch->ch_open_count && un->un_open_count) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - return; - } - - /* OK, its the last close on the unit */ - - un->un_flags |= UN_CLOSING; - - tty->closing = 1; - - /* - * Only officially close channel if count is 0 and - * DIGI_PRINTER bit is not set. - */ - if ((ch->ch_open_count == 0) && - !(ch->ch_digi.digi_flags & DIGI_PRINTER)) { - ch->ch_flags &= ~(CH_RXBLOCK); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - - /* wait for output to drain */ - /* This will also return if we take an interrupt */ - - dgap_wait_for_drain(tty); - - dgap_tty_flush_buffer(tty); - tty_ldisc_flush(tty); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - - tty->closing = 0; - - /* - * If we have HUPCL set, lower DTR and RTS - */ - if (ch->ch_c_cflag & HUPCL) { - ch->ch_mostat &= ~(D_RTS(ch) | D_DTR(ch)); - dgap_cmdb(ch, SMODEM, 0, D_DTR(ch) | D_RTS(ch), 0); - - /* - * Go to sleep to ensure RTS/DTR - * have been dropped for modems to see it. - */ - spin_unlock_irqrestore(&ch->ch_lock, - lock_flags); - - /* .25 second delay for dropping RTS/DTR */ - schedule_timeout_interruptible(msecs_to_jiffies(250)); - - spin_lock_irqsave(&ch->ch_lock, lock_flags); - } - - ch->pscan_state = 0; - ch->pscan_savechar = 0; - ch->ch_baud_info = 0; - } - - /* - * turn off print device when closing print device. - */ - if ((un->un_type == DGAP_PRINT) && (ch->ch_flags & CH_PRON)) { - dgap_wmove(ch, ch->ch_digi.digi_offstr, - (int)ch->ch_digi.digi_offlen); - ch->ch_flags &= ~CH_PRON; - } - - un->un_tty = NULL; - un->un_flags &= ~(UN_ISOPEN | UN_CLOSING); - tty->driver_data = NULL; - - wake_up_interruptible(&ch->ch_flags_wait); - wake_up_interruptible(&un->un_flags_wait); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags); -} - -static void dgap_tty_start(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, RESUMETX, 0, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -static void dgap_tty_stop(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, PAUSETX, 0, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/* - * dgap_tty_flush_chars() - * - * Flush the cook buffer - * - * Note to self, and any other poor souls who venture here: - * - * flush in this case DOES NOT mean dispose of the data. - * instead, it means "stop buffering and send it if you - * haven't already." Just guess how I figured that out... SRW 2-Jun-98 - * - * It is also always called in interrupt context - JAR 8-Sept-99 - */ -static void dgap_tty_flush_chars(struct tty_struct *tty) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - ulong lock_flags; - ulong lock_flags2; - - if (!tty || tty->magic != TTY_MAGIC) - return; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - /* TODO: Do something here */ - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); -} - -/***************************************************************************** - * - * The IOCTL function and all of its helpers - * - *****************************************************************************/ - -/* - * dgap_tty_ioctl() - * - * The usual assortment of ioctl's - */ -static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - int rc; - u16 head; - ulong lock_flags = 0; - ulong lock_flags2 = 0; - void __user *uarg = (void __user *)arg; - - if (!tty || tty->magic != TTY_MAGIC) - return -ENODEV; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -ENODEV; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -ENODEV; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -ENODEV; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (un->un_open_count <= 0) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EIO; - } - - switch (cmd) { - /* Here are all the standard ioctl's that we MUST implement */ - case TCSBRK: - /* - * TCSBRK is SVID version: non-zero arg --> no break - * this behaviour is exploited by tcdrain(). - * - * According to POSIX.1 spec (7.2.2.1.2) breaks should be - * between 0.25 and 0.5 seconds so we'll ask for something - * in the middle: 0.375 seconds. - */ - rc = tty_check_change(tty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (rc) - return rc; - - rc = dgap_wait_for_drain(tty); - - if (rc) - return -EINTR; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - if (((cmd == TCSBRK) && (!arg)) || (cmd == TCSBRKP)) - dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TCSBRKP: - /* support for POSIX tcsendbreak() - - * According to POSIX.1 spec (7.2.2.1.2) breaks should be - * between 0.25 and 0.5 seconds so we'll ask for something - * in the middle: 0.375 seconds. - */ - rc = tty_check_change(tty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (rc) - return rc; - - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TIOCSBRK: - /* - * FEP5 doesn't support turning on a break unconditionally. - * The FEP5 device will stop sending a break automatically - * after the specified time value that was sent when turning on - * the break. - */ - rc = tty_check_change(tty); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - if (rc) - return rc; - - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - - dgap_cmdw(ch, SBREAK, (u16)SBREAK_TIME, 0); - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TIOCCBRK: - /* - * FEP5 doesn't support turning off a break unconditionally. - * The FEP5 device will stop sending a break automatically - * after the specified time value that was sent when turning on - * the break. - */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return 0; - - case TIOCGSOFTCAR: - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long __user *)arg); - - case TIOCSSOFTCAR: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - rc = get_user(arg, (unsigned long __user *)arg); - if (rc) - return rc; - - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - dgap_param(ch, bd, un->un_type); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return 0; - - case TIOCMGET: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_get_modem_info(ch, uarg); - - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_set_modem_info(ch, bd, un, cmd, uarg); - - /* - * Here are any additional ioctl's that we want to implement - */ - - case TCFLSH: - /* - * The linux tty driver doesn't have a flush - * input routine for the driver, assuming all backed - * up data is in the line disc. buffers. However, - * we all know that's not the case. Here, we - * act on the ioctl, but then lie and say we didn't - * so the line discipline will process the flush - * also. - */ - rc = tty_check_change(tty); - if (rc) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return rc; - } - - if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) { - if (!(un->un_type == DGAP_PRINT)) { - head = readw(&ch->ch_bs->rx_head); - writew(head, &ch->ch_bs->rx_tail); - writeb(0, &ch->ch_bs->orun); - } - } - - if ((arg != TCOFLUSH) && (arg != TCIOFLUSH)) { - /* pretend we didn't recognize this IOCTL */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return -ENOIOCTLCMD; - } - - ch->ch_flags &= ~CH_STOP; - head = readw(&ch->ch_bs->tx_head); - dgap_cmdw(ch, FLUSHTX, (u16)head, 0); - dgap_cmdw(ch, RESUMETX, 0, 0); - if (ch->ch_tun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_tun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_tun.un_flags_wait); - } - if (ch->ch_pun.un_flags & (UN_LOW | UN_EMPTY)) { - ch->ch_pun.un_flags &= ~(UN_LOW | UN_EMPTY); - wake_up_interruptible(&ch->ch_pun.un_flags_wait); - } - if (waitqueue_active(&tty->write_wait)) - wake_up_interruptible(&tty->write_wait); - - /* Can't hold any locks when calling tty_wakeup! */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - tty_wakeup(tty); - - /* pretend we didn't recognize this IOCTL */ - return -ENOIOCTLCMD; - - case TCSETSF: - case TCSETSW: - /* - * The linux tty driver doesn't have a flush - * input routine for the driver, assuming all backed - * up data is in the line disc. buffers. However, - * we all know that's not the case. Here, we - * act on the ioctl, but then lie and say we didn't - * so the line discipline will process the flush - * also. - */ - if (cmd == TCSETSF) { - /* flush rx */ - ch->ch_flags &= ~CH_STOP; - head = readw(&ch->ch_bs->rx_head); - writew(head, &ch->ch_bs->rx_tail); - } - - /* now wait for all the output to drain */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - /* pretend we didn't recognize this */ - return -ENOIOCTLCMD; - - case TCSETAW: - - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - - /* pretend we didn't recognize this */ - return -ENOIOCTLCMD; - - case TCXONC: - /* - * The Linux Line Discipline (LD) would do this for us if we - * let it, but we have the special firmware options to do this - * the "right way" regardless of hardware or software flow - * control so we'll do it outselves instead of letting the LD - * do it. - */ - rc = tty_check_change(tty); - if (rc) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return rc; - } - - switch (arg) { - case TCOON: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - dgap_tty_start(tty); - return 0; - case TCOOFF: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - dgap_tty_stop(tty); - return 0; - case TCION: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - /* Make the ld do it */ - return -ENOIOCTLCMD; - case TCIOFF: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - /* Make the ld do it */ - return -ENOIOCTLCMD; - default: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return -EINVAL; - } - - case DIGI_GETA: - /* get information for ditty */ - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigeta(ch, uarg); - - case DIGI_SETAW: - case DIGI_SETAF: - - /* set information for ditty */ - if (cmd == (DIGI_SETAW)) { - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - rc = dgap_wait_for_drain(tty); - if (rc) - return -EINTR; - spin_lock_irqsave(&bd->bd_lock, lock_flags); - spin_lock_irqsave(&ch->ch_lock, lock_flags2); - } else - tty_ldisc_flush(tty); - /* fall thru */ - - case DIGI_SETA: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digiseta(ch, bd, un, uarg); - - case DIGI_GEDELAY: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigetedelay(tty, uarg); - - case DIGI_SEDELAY: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digisetedelay(ch, bd, un, uarg); - - case DIGI_GETCUSTOMBAUD: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigetcustombaud(ch, un, uarg); - - case DIGI_SETCUSTOMBAUD: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digisetcustombaud(ch, bd, un, uarg); - - case DIGI_RESET_PORT: - dgap_firmware_reset_port(ch); - dgap_param(ch, bd, un->un_type); - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return 0; - - default: - spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); - spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return -ENOIOCTLCMD; - } -} - -static const struct tty_operations dgap_tty_ops = { - .open = dgap_tty_open, - .close = dgap_tty_close, - .write = dgap_tty_write, - .write_room = dgap_tty_write_room, - .flush_buffer = dgap_tty_flush_buffer, - .chars_in_buffer = dgap_tty_chars_in_buffer, - .flush_chars = dgap_tty_flush_chars, - .ioctl = dgap_tty_ioctl, - .set_termios = dgap_tty_set_termios, - .stop = dgap_tty_stop, - .start = dgap_tty_start, - .throttle = dgap_tty_throttle, - .unthrottle = dgap_tty_unthrottle, - .hangup = dgap_tty_hangup, - .put_char = dgap_tty_put_char, - .tiocmget = dgap_tty_tiocmget, - .tiocmset = dgap_tty_tiocmset, - .break_ctl = dgap_tty_send_break, - .wait_until_sent = dgap_tty_wait_until_sent, - .send_xchar = dgap_tty_send_xchar -}; - -/************************************************************************ - * - * TTY Initialization/Cleanup Functions - * - ************************************************************************/ - -/* - * dgap_tty_register() - * - * Init the tty subsystem for this board. - */ -static int dgap_tty_register(struct board_t *brd) -{ - int rc; - - brd->serial_driver = tty_alloc_driver(MAXPORTS, - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - if (IS_ERR(brd->serial_driver)) - return PTR_ERR(brd->serial_driver); - - snprintf(brd->serial_name, MAXTTYNAMELEN, "tty_dgap_%d_", - brd->boardnum); - brd->serial_driver->name = brd->serial_name; - brd->serial_driver->name_base = 0; - brd->serial_driver->major = 0; - brd->serial_driver->minor_start = 0; - brd->serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - brd->serial_driver->subtype = SERIAL_TYPE_NORMAL; - brd->serial_driver->init_termios = dgap_default_termios; - brd->serial_driver->driver_name = DRVSTR; - - /* - * Entry points for driver. Called by the kernel from - * tty_io.c and n_tty.c. - */ - tty_set_operations(brd->serial_driver, &dgap_tty_ops); - - /* - * If we're doing transparent print, we have to do all of the above - * again, separately so we don't get the LD confused about what major - * we are when we get into the dgap_tty_open() routine. - */ - brd->print_driver = tty_alloc_driver(MAXPORTS, - TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV | - TTY_DRIVER_HARDWARE_BREAK); - if (IS_ERR(brd->print_driver)) { - rc = PTR_ERR(brd->print_driver); - goto free_serial_drv; - } - - snprintf(brd->print_name, MAXTTYNAMELEN, "pr_dgap_%d_", - brd->boardnum); - brd->print_driver->name = brd->print_name; - brd->print_driver->name_base = 0; - brd->print_driver->major = 0; - brd->print_driver->minor_start = 0; - brd->print_driver->type = TTY_DRIVER_TYPE_SERIAL; - brd->print_driver->subtype = SERIAL_TYPE_NORMAL; - brd->print_driver->init_termios = dgap_default_termios; - brd->print_driver->driver_name = DRVSTR; - - /* - * Entry points for driver. Called by the kernel from - * tty_io.c and n_tty.c. - */ - tty_set_operations(brd->print_driver, &dgap_tty_ops); - - /* Register tty devices */ - rc = tty_register_driver(brd->serial_driver); - if (rc < 0) - goto free_print_drv; - - /* Register Transparent Print devices */ - rc = tty_register_driver(brd->print_driver); - if (rc < 0) - goto unregister_serial_drv; - - return 0; - -unregister_serial_drv: - tty_unregister_driver(brd->serial_driver); -free_print_drv: - put_tty_driver(brd->print_driver); -free_serial_drv: - put_tty_driver(brd->serial_driver); - - return rc; -} - -static void dgap_tty_unregister(struct board_t *brd) -{ - tty_unregister_driver(brd->print_driver); - tty_unregister_driver(brd->serial_driver); - put_tty_driver(brd->print_driver); - put_tty_driver(brd->serial_driver); -} - -static int dgap_alloc_flipbuf(struct board_t *brd) -{ - /* - * allocate flip buffer for board. - */ - brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); - if (!brd->flipbuf) - return -ENOMEM; - - brd->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); - if (!brd->flipflagbuf) { - kfree(brd->flipbuf); - return -ENOMEM; - } - - return 0; -} - -static void dgap_free_flipbuf(struct board_t *brd) -{ - kfree(brd->flipbuf); - kfree(brd->flipflagbuf); -} - -static struct board_t *dgap_verify_board(struct device *p) -{ - struct board_t *bd; - - if (!p) - return NULL; - - bd = dev_get_drvdata(p); - if (!bd || bd->magic != DGAP_BOARD_MAGIC || bd->state != BOARD_READY) - return NULL; - - return bd; -} - -static ssize_t dgap_ports_state_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) { - count += snprintf(buf + count, PAGE_SIZE - count, - "%d %s\n", bd->channels[i]->ch_portnum, - bd->channels[i]->ch_open_count ? "Open" : "Closed"); - } - return count; -} -static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL); - -static ssize_t dgap_ports_baud_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) { - count += snprintf(buf + count, PAGE_SIZE - count, "%d %d\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_baud_info); - } - return count; -} -static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL); - -static ssize_t dgap_ports_msignals_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) { - if (bd->channels[i]->ch_open_count) - count += snprintf(buf + count, PAGE_SIZE - count, - "%d %s %s %s %s %s %s\n", - bd->channels[i]->ch_portnum, - (bd->channels[i]->ch_mostat & - UART_MCR_RTS) ? "RTS" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_CTS) ? "CTS" : "", - (bd->channels[i]->ch_mostat & - UART_MCR_DTR) ? "DTR" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_DSR) ? "DSR" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_DCD) ? "DCD" : "", - (bd->channels[i]->ch_mistat & - UART_MSR_RI) ? "RI" : ""); - else - count += snprintf(buf + count, PAGE_SIZE - count, - "%d\n", bd->channels[i]->ch_portnum); - } - return count; -} -static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL); - -static ssize_t dgap_ports_iflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_iflag); - return count; -} -static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL); - -static ssize_t dgap_ports_cflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_cflag); - return count; -} -static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL); - -static ssize_t dgap_ports_oflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_oflag); - return count; -} -static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL); - -static ssize_t dgap_ports_lflag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_c_lflag); - return count; -} -static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL); - -static ssize_t dgap_ports_digi_flag_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_digi.digi_flags); - return count; -} -static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL); - -static ssize_t dgap_ports_rxcount_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_rxcount); - return count; -} -static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL); - -static ssize_t dgap_ports_txcount_show(struct device *p, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - int count = 0; - unsigned int i; - - bd = dgap_verify_board(p); - if (!bd) - return 0; - - for (i = 0; i < bd->nasync; i++) - count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n", - bd->channels[i]->ch_portnum, - bd->channels[i]->ch_txcount); - return count; -} -static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL); - -static ssize_t dgap_tty_state_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? - "Open" : "Closed"); -} -static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL); - -static ssize_t dgap_tty_baud_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info); -} -static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL); - -static ssize_t dgap_tty_msignals_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - if (ch->ch_open_count) { - return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n", - (ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "", - (ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "", - (ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "", - (ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "", - (ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "", - (ch->ch_mistat & UART_MSR_RI) ? "RI" : ""); - } - return 0; -} -static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL); - -static ssize_t dgap_tty_iflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag); -} -static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL); - -static ssize_t dgap_tty_cflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag); -} -static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL); - -static ssize_t dgap_tty_oflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag); -} -static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL); - -static ssize_t dgap_tty_lflag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag); -} -static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL); - -static ssize_t dgap_tty_digi_flag_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags); -} -static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL); - -static ssize_t dgap_tty_rxcount_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount); -} -static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL); - -static ssize_t dgap_tty_txcount_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount); -} -static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL); - -static ssize_t dgap_tty_name_show(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; - int cn; - int bn; - struct cnode *cptr; - int found = FALSE; - int ncount = 0; - int starto = 0; - int i; - - if (!d) - return 0; - un = dev_get_drvdata(d); - if (!un || un->magic != DGAP_UNIT_MAGIC) - return 0; - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return 0; - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return 0; - if (bd->state != BOARD_READY) - return 0; - - bn = bd->boardnum; - cn = ch->ch_portnum; - - for (cptr = bd->bd_config; cptr; cptr = cptr->next) { - if ((cptr->type == BNODE) && - ((cptr->u.board.type == APORT2_920P) || - (cptr->u.board.type == APORT4_920P) || - (cptr->u.board.type == APORT8_920P) || - (cptr->u.board.type == PAPORT4) || - (cptr->u.board.type == PAPORT8))) { - found = TRUE; - if (cptr->u.board.v_start) - starto = cptr->u.board.start; - else - starto = 1; - } - - if (cptr->type == TNODE && found == TRUE) { - char *ptr1; - - if (strstr(cptr->u.ttyname, "tty")) { - ptr1 = cptr->u.ttyname; - ptr1 += 3; - } else - ptr1 = cptr->u.ttyname; - - for (i = 0; i < dgap_config_get_num_prts(bd); i++) { - if (cn != i) - continue; - - return snprintf(buf, PAGE_SIZE, "%s%s%02d\n", - (un->un_type == DGAP_PRINT) ? - "pr" : "tty", - ptr1, i + starto); - } - } - - if (cptr->type == CNODE) { - for (i = 0; i < cptr->u.conc.nport; i++) { - if (cn != (i + ncount)) - continue; - - return snprintf(buf, PAGE_SIZE, "%s%s%02ld\n", - (un->un_type == DGAP_PRINT) ? - "pr" : "tty", - cptr->u.conc.id, - i + (cptr->u.conc.v_start ? - cptr->u.conc.start : 1)); - } - - ncount += cptr->u.conc.nport; - } - - if (cptr->type == MNODE) { - for (i = 0; i < cptr->u.module.nport; i++) { - if (cn != (i + ncount)) - continue; - - return snprintf(buf, PAGE_SIZE, "%s%s%02ld\n", - (un->un_type == DGAP_PRINT) ? - "pr" : "tty", - cptr->u.module.id, - i + (cptr->u.module.v_start ? - cptr->u.module.start : 1)); - } - - ncount += cptr->u.module.nport; - } - } - - return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n", - (un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn); -} -static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL); - -static struct attribute *dgap_sysfs_tty_entries[] = { - &dev_attr_state.attr, - &dev_attr_baud.attr, - &dev_attr_msignals.attr, - &dev_attr_iflag.attr, - &dev_attr_cflag.attr, - &dev_attr_oflag.attr, - &dev_attr_lflag.attr, - &dev_attr_digi_flag.attr, - &dev_attr_rxcount.attr, - &dev_attr_txcount.attr, - &dev_attr_custom_name.attr, - NULL -}; - - -/* this function creates the sys files that will export each signal status - * to sysfs each value will be put in a separate filename - */ -static void dgap_create_ports_sysfiles(struct board_t *bd) -{ - dev_set_drvdata(&bd->pdev->dev, bd); - device_create_file(&bd->pdev->dev, &dev_attr_ports_state); - device_create_file(&bd->pdev->dev, &dev_attr_ports_baud); - device_create_file(&bd->pdev->dev, &dev_attr_ports_msignals); - device_create_file(&bd->pdev->dev, &dev_attr_ports_iflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_cflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_oflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_lflag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_digi_flag); - device_create_file(&bd->pdev->dev, &dev_attr_ports_rxcount); - device_create_file(&bd->pdev->dev, &dev_attr_ports_txcount); -} - -/* removes all the sys files created for that port */ -static void dgap_remove_ports_sysfiles(struct board_t *bd) -{ - device_remove_file(&bd->pdev->dev, &dev_attr_ports_state); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_baud); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_msignals); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_iflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_cflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_oflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_lflag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_digi_flag); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_rxcount); - device_remove_file(&bd->pdev->dev, &dev_attr_ports_txcount); -} - -/* - * Copies the BIOS code from the user to the board, - * and starts the BIOS running. - */ -static void dgap_do_bios_load(struct board_t *brd, const u8 *ubios, int len) -{ - u8 __iomem *addr; - uint offset; - unsigned int i; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return; - - addr = brd->re_map_membase; - - /* - * clear POST area - */ - for (i = 0; i < 16; i++) - writeb(0, addr + POSTAREA + i); - - /* - * Download bios - */ - offset = 0x1000; - memcpy_toio(addr + offset, ubios, len); - - writel(0x0bf00401, addr); - writel(0, (addr + 4)); - - /* Clear the reset, and change states. */ - writeb(FEPCLR, brd->re_map_port); -} - -/* - * Checks to see if the BIOS completed running on the card. - */ -static int dgap_test_bios(struct board_t *brd) -{ - u8 __iomem *addr; - u16 word; - u16 err1; - u16 err2; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return -EINVAL; - - addr = brd->re_map_membase; - word = readw(addr + POSTAREA); - - /* - * It can take 5-6 seconds for a board to - * pass the bios self test and post results. - * Give it 10 seconds. - */ - brd->wait_for_bios = 0; - while (brd->wait_for_bios < 1000) { - /* Check to see if BIOS thinks board is good. (GD). */ - if (word == *(u16 *)"GD") - return 0; - msleep_interruptible(10); - brd->wait_for_bios++; - word = readw(addr + POSTAREA); - } - - /* Gave up on board after too long of time taken */ - err1 = readw(addr + SEQUENCE); - err2 = readw(addr + ERROR); - dev_warn(&brd->pdev->dev, "%s failed diagnostics. Error #(%x,%x).\n", - brd->name, err1, err2); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOBIOS; - - return -EIO; -} - -/* - * Copies the FEP code from the user to the board, - * and starts the FEP running. - */ -static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len) -{ - u8 __iomem *addr; - uint offset; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return; - - addr = brd->re_map_membase; - - /* - * Download FEP - */ - offset = 0x1000; - memcpy_toio(addr + offset, ufep, len); - - /* - * If board is a concentrator product, we need to give - * it its config string describing how the concentrators look. - */ - if ((brd->type == PCX) || (brd->type == PEPC)) { - u8 string[100]; - u8 __iomem *config; - u8 *xconfig; - unsigned int i = 0; - - xconfig = dgap_create_config_string(brd, string); - - /* Write string to board memory */ - config = addr + CONFIG; - for (; i < CONFIGSIZE; i++, config++, xconfig++) { - writeb(*xconfig, config); - if ((*xconfig & 0xff) == 0xff) - break; - } - } - - writel(0xbfc01004, (addr + 0xc34)); - writel(0x3, (addr + 0xc30)); -} - -/* - * Waits for the FEP to report thats its ready for us to use. - */ -static int dgap_test_fep(struct board_t *brd) -{ - u8 __iomem *addr; - u16 word; - u16 err1; - u16 err2; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return -EINVAL; - - addr = brd->re_map_membase; - word = readw(addr + FEPSTAT); - - /* - * It can take 2-3 seconds for the FEP to - * be up and running. Give it 5 secs. - */ - brd->wait_for_fep = 0; - while (brd->wait_for_fep < 500) { - /* Check to see if FEP is up and running now. */ - if (word == *(u16 *)"OS") { - /* - * Check to see if the board can support FEP5+ commands. - */ - word = readw(addr + FEP5_PLUS); - if (word == *(u16 *)"5A") - brd->bd_flags |= BD_FEP5PLUS; - - return 0; - } - msleep_interruptible(10); - brd->wait_for_fep++; - word = readw(addr + FEPSTAT); - } - - /* Gave up on board after too long of time taken */ - err1 = readw(addr + SEQUENCE); - err2 = readw(addr + ERROR); - dev_warn(&brd->pdev->dev, - "FEPOS for %s not functioning. Error #(%x,%x).\n", - brd->name, err1, err2); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - - return -EIO; -} - -/* - * Physically forces the FEP5 card to reset itself. - */ -static void dgap_do_reset_board(struct board_t *brd) -{ - u8 check; - u32 check1; - u32 check2; - unsigned int i; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || - !brd->re_map_membase || !brd->re_map_port) - return; - - /* FEPRST does not vary among supported boards */ - writeb(FEPRST, brd->re_map_port); - - for (i = 0; i <= 1000; i++) { - check = readb(brd->re_map_port) & 0xe; - if (check == FEPRST) - break; - udelay(10); - } - if (i > 1000) { - dev_warn(&brd->pdev->dev, - "dgap: Board not resetting... Failing board.\n"); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - return; - } - - /* - * Make sure there really is memory out there. - */ - writel(0xa55a3cc3, (brd->re_map_membase + LOWMEM)); - writel(0x5aa5c33c, (brd->re_map_membase + HIGHMEM)); - check1 = readl(brd->re_map_membase + LOWMEM); - check2 = readl(brd->re_map_membase + HIGHMEM); - - if ((check1 != 0xa55a3cc3) || (check2 != 0x5aa5c33c)) { - dev_warn(&brd->pdev->dev, - "No memory at %p for board.\n", - brd->re_map_membase); - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - return; - } -} - -#ifdef DIGI_CONCENTRATORS_SUPPORTED -/* - * Sends a concentrator image into the FEP5 board. - */ -static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len) -{ - char __iomem *vaddr; - u16 offset; - struct downld_t *to_dp; - - if (!brd || (brd->magic != DGAP_BOARD_MAGIC) || !brd->re_map_membase) - return; - - vaddr = brd->re_map_membase; - - offset = readw((u16 *)(vaddr + DOWNREQ)); - to_dp = (struct downld_t *)(vaddr + (int)offset); - memcpy_toio(to_dp, uaddr, len); - - /* Tell card we have data for it */ - writew(0, vaddr + (DOWNREQ)); - - brd->conc_dl_status = NO_PENDING_CONCENTRATOR_REQUESTS; -} -#endif - -#define EXPANSION_ROM_SIZE (64 * 1024) -#define FEP5_ROM_MAGIC (0xFEFFFFFF) - -static void dgap_get_vpd(struct board_t *brd) -{ - u32 magic; - u32 base_offset; - u16 rom_offset; - u16 vpd_offset; - u16 image_length; - u16 i; - u8 byte1; - u8 byte2; - - /* - * Poke the magic number at the PCI Rom Address location. - * If VPD is supported, the value read from that address - * will be non-zero. - */ - magic = FEP5_ROM_MAGIC; - pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic); - pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic); - - /* VPD not supported, bail */ - if (!magic) - return; - - /* - * To get to the OTPROM memory, we have to send the boards base - * address or'ed with 1 into the PCI Rom Address location. - */ - magic = brd->membase | 0x01; - pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic); - pci_read_config_dword(brd->pdev, PCI_ROM_ADDRESS, &magic); - - byte1 = readb(brd->re_map_membase); - byte2 = readb(brd->re_map_membase + 1); - - /* - * If the board correctly swapped to the OTPROM memory, - * the first 2 bytes (header) should be 0x55, 0xAA - */ - if (byte1 == 0x55 && byte2 == 0xAA) { - base_offset = 0; - - /* - * We have to run through all the OTPROM memory looking - * for the VPD offset. - */ - while (base_offset <= EXPANSION_ROM_SIZE) { - /* - * Lots of magic numbers here. - * - * The VPD offset is located inside the ROM Data - * Structure. - * - * We also have to remember the length of each - * ROM Data Structure, so we can "hop" to the next - * entry if the VPD isn't in the current - * ROM Data Structure. - */ - rom_offset = readw(brd->re_map_membase + - base_offset + 0x18); - image_length = readw(brd->re_map_membase + - rom_offset + 0x10) * 512; - vpd_offset = readw(brd->re_map_membase + - rom_offset + 0x08); - - /* Found the VPD entry */ - if (vpd_offset) - break; - - /* We didn't find a VPD entry, go to next ROM entry. */ - base_offset += image_length; - - byte1 = readb(brd->re_map_membase + base_offset); - byte2 = readb(brd->re_map_membase + base_offset + 1); - - /* - * If the new ROM offset doesn't have 0x55, 0xAA - * as its header, we have run out of ROM. - */ - if (byte1 != 0x55 || byte2 != 0xAA) - break; - } - - /* - * If we have a VPD offset, then mark the board - * as having a valid VPD, and copy VPDSIZE (512) bytes of - * that VPD to the buffer we have in our board structure. - */ - if (vpd_offset) { - brd->bd_flags |= BD_HAS_VPD; - for (i = 0; i < VPDSIZE; i++) { - brd->vpd[i] = readb(brd->re_map_membase + - vpd_offset + i); - } - } - } - - /* - * We MUST poke the magic number at the PCI Rom Address location again. - * This makes the card report the regular board memory back to us, - * rather than the OTPROM memory. - */ - magic = FEP5_ROM_MAGIC; - pci_write_config_dword(brd->pdev, PCI_ROM_ADDRESS, magic); -} - - -static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART); -} -static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL); - - -static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", dgap_numboards); -} -static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL); - - -static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS); -} -static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL); - - -static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter); -} -static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL); - -static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick); -} - -static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, - const char *buf, size_t count) -{ - if (sscanf(buf, "%d\n", &dgap_poll_tick) != 1) - return -EINVAL; - return count; -} -static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, - dgap_driver_pollrate_store); - - -static int dgap_create_driver_sysfiles(struct pci_driver *dgap_driver) -{ - int rc = 0; - struct device_driver *driverfs = &dgap_driver->driver; - - rc |= driver_create_file(driverfs, &driver_attr_version); - rc |= driver_create_file(driverfs, &driver_attr_boards); - rc |= driver_create_file(driverfs, &driver_attr_maxboards); - rc |= driver_create_file(driverfs, &driver_attr_pollrate); - rc |= driver_create_file(driverfs, &driver_attr_pollcounter); - - return rc; -} - -static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver) -{ - struct device_driver *driverfs = &dgap_driver->driver; - - driver_remove_file(driverfs, &driver_attr_version); - driver_remove_file(driverfs, &driver_attr_boards); - driver_remove_file(driverfs, &driver_attr_maxboards); - driver_remove_file(driverfs, &driver_attr_pollrate); - driver_remove_file(driverfs, &driver_attr_pollcounter); -} - -static struct attribute_group dgap_tty_attribute_group = { - .name = NULL, - .attrs = dgap_sysfs_tty_entries, -}; - -static void dgap_create_tty_sysfs(struct un_t *un, struct device *c) -{ - int ret; - - ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group); - if (ret) - return; - - dev_set_drvdata(c, un); -} - -static void dgap_remove_tty_sysfs(struct device *c) -{ - sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group); -} - -/* - * Create pr and tty device entries - */ -static int dgap_tty_register_ports(struct board_t *brd) -{ - struct channel_t *ch; - int i; - int ret; - - brd->serial_ports = kcalloc(brd->nasync, sizeof(*brd->serial_ports), - GFP_KERNEL); - if (!brd->serial_ports) - return -ENOMEM; - - brd->printer_ports = kcalloc(brd->nasync, sizeof(*brd->printer_ports), - GFP_KERNEL); - if (!brd->printer_ports) { - ret = -ENOMEM; - goto free_serial_ports; - } - - for (i = 0; i < brd->nasync; i++) { - tty_port_init(&brd->serial_ports[i]); - tty_port_init(&brd->printer_ports[i]); - } - - ch = brd->channels[0]; - for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) { - struct device *classp; - - classp = tty_port_register_device(&brd->serial_ports[i], - brd->serial_driver, - i, NULL); - - if (IS_ERR(classp)) { - ret = PTR_ERR(classp); - goto unregister_ttys; - } - - dgap_create_tty_sysfs(&ch->ch_tun, classp); - ch->ch_tun.un_sysfs = classp; - - classp = tty_port_register_device(&brd->printer_ports[i], - brd->print_driver, - i, NULL); - - if (IS_ERR(classp)) { - ret = PTR_ERR(classp); - goto unregister_ttys; - } - - dgap_create_tty_sysfs(&ch->ch_pun, classp); - ch->ch_pun.un_sysfs = classp; - } - dgap_create_ports_sysfiles(brd); - - return 0; - -unregister_ttys: - while (i >= 0) { - ch = brd->channels[i]; - if (ch->ch_tun.un_sysfs) { - dgap_remove_tty_sysfs(ch->ch_tun.un_sysfs); - tty_unregister_device(brd->serial_driver, i); - } - - if (ch->ch_pun.un_sysfs) { - dgap_remove_tty_sysfs(ch->ch_pun.un_sysfs); - tty_unregister_device(brd->print_driver, i); - } - i--; - } - - for (i = 0; i < brd->nasync; i++) { - tty_port_destroy(&brd->serial_ports[i]); - tty_port_destroy(&brd->printer_ports[i]); - } - - kfree(brd->printer_ports); - brd->printer_ports = NULL; - -free_serial_ports: - kfree(brd->serial_ports); - brd->serial_ports = NULL; - - return ret; -} - -/* - * dgap_cleanup_tty() - * - * Uninitialize the TTY portion of this driver. Free all memory and - * resources. - */ -static void dgap_cleanup_tty(struct board_t *brd) -{ - struct device *dev; - unsigned int i; - - for (i = 0; i < brd->nasync; i++) { - tty_port_destroy(&brd->serial_ports[i]); - dev = brd->channels[i]->ch_tun.un_sysfs; - dgap_remove_tty_sysfs(dev); - tty_unregister_device(brd->serial_driver, i); - } - tty_unregister_driver(brd->serial_driver); - put_tty_driver(brd->serial_driver); - kfree(brd->serial_ports); - - for (i = 0; i < brd->nasync; i++) { - tty_port_destroy(&brd->printer_ports[i]); - dev = brd->channels[i]->ch_pun.un_sysfs; - dgap_remove_tty_sysfs(dev); - tty_unregister_device(brd->print_driver, i); - } - tty_unregister_driver(brd->print_driver); - put_tty_driver(brd->print_driver); - kfree(brd->printer_ports); -} - -static int dgap_request_irq(struct board_t *brd) -{ - int rc; - - if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return -ENODEV; - - /* - * Set up our interrupt handler if we are set to do interrupts. - */ - if (dgap_config_get_useintr(brd) && brd->irq) { - rc = request_irq(brd->irq, dgap_intr, IRQF_SHARED, "DGAP", brd); - - if (!rc) - brd->intr_used = 1; - } - return 0; -} - -static void dgap_free_irq(struct board_t *brd) -{ - if (brd->intr_used && brd->irq) - free_irq(brd->irq, brd); -} - -static int dgap_firmware_load(struct pci_dev *pdev, int card_type, - struct board_t *brd) -{ - const struct firmware *fw; - char *tmp_ptr; - int ret; - char *dgap_config_buf; - - dgap_get_vpd(brd); - dgap_do_reset_board(brd); - - if (fw_info[card_type].conf_name) { - ret = request_firmware(&fw, fw_info[card_type].conf_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "config file %s not found\n", - fw_info[card_type].conf_name); - return ret; - } - - dgap_config_buf = kzalloc(fw->size + 1, GFP_KERNEL); - if (!dgap_config_buf) { - release_firmware(fw); - return -ENOMEM; - } - - memcpy(dgap_config_buf, fw->data, fw->size); - release_firmware(fw); - - /* - * preserve dgap_config_buf - * as dgap_parsefile would - * otherwise alter it. - */ - tmp_ptr = dgap_config_buf; - - if (dgap_parsefile(&tmp_ptr) != 0) { - kfree(dgap_config_buf); - return -EINVAL; - } - kfree(dgap_config_buf); - } - - /* - * Match this board to a config the user created for us. - */ - brd->bd_config = - dgap_find_config(brd->type, brd->pci_bus, brd->pci_slot); - - /* - * Because the 4 port Xr products share the same PCI ID - * as the 8 port Xr products, if we receive a NULL config - * back, and this is a PAPORT8 board, retry with a - * PAPORT4 attempt as well. - */ - if (brd->type == PAPORT8 && !brd->bd_config) - brd->bd_config = - dgap_find_config(PAPORT4, brd->pci_bus, brd->pci_slot); - - if (!brd->bd_config) { - dev_err(&pdev->dev, "No valid configuration found\n"); - return -EINVAL; - } - - if (fw_info[card_type].bios_name) { - ret = request_firmware(&fw, fw_info[card_type].bios_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "bios file %s not found\n", - fw_info[card_type].bios_name); - return ret; - } - dgap_do_bios_load(brd, fw->data, fw->size); - release_firmware(fw); - - /* Wait for BIOS to test board... */ - ret = dgap_test_bios(brd); - if (ret) - return ret; - } - - if (fw_info[card_type].fep_name) { - ret = request_firmware(&fw, fw_info[card_type].fep_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "dgap: fep file %s not found\n", - fw_info[card_type].fep_name); - return ret; - } - dgap_do_fep_load(brd, fw->data, fw->size); - release_firmware(fw); - - /* Wait for FEP to load on board... */ - ret = dgap_test_fep(brd); - if (ret) - return ret; - } - -#ifdef DIGI_CONCENTRATORS_SUPPORTED - /* - * If this is a CX or EPCX, we need to see if the firmware - * is requesting a concentrator image from us. - */ - if ((bd->type == PCX) || (bd->type == PEPC)) { - chk_addr = (u16 *)(vaddr + DOWNREQ); - /* Nonzero if FEP is requesting concentrator image. */ - check = readw(chk_addr); - vaddr = brd->re_map_membase; - } - - if (fw_info[card_type].con_name && check && vaddr) { - ret = request_firmware(&fw, fw_info[card_type].con_name, - &pdev->dev); - if (ret) { - dev_err(&pdev->dev, "conc file %s not found\n", - fw_info[card_type].con_name); - return ret; - } - /* Put concentrator firmware loading code here */ - offset = readw((u16 *)(vaddr + DOWNREQ)); - memcpy_toio(offset, fw->data, fw->size); - - dgap_do_conc_load(brd, (char *)fw->data, fw->size) - release_firmware(fw); - } -#endif - - return 0; -} - -/* - * dgap_tty_init() - * - * Init the tty subsystem. Called once per board after board has been - * downloaded and init'ed. - */ -static int dgap_tty_init(struct board_t *brd) -{ - int i; - int tlw; - uint true_count; - u8 __iomem *vaddr; - u8 modem; - struct channel_t *ch; - struct bs_t __iomem *bs; - struct cm_t __iomem *cm; - int ret; - - /* - * Initialize board structure elements. - */ - - vaddr = brd->re_map_membase; - true_count = readw((vaddr + NCHAN)); - - brd->nasync = dgap_config_get_num_prts(brd); - - if (!brd->nasync) - brd->nasync = brd->maxports; - - if (brd->nasync > brd->maxports) - brd->nasync = brd->maxports; - - if (true_count != brd->nasync) { - dev_warn(&brd->pdev->dev, - "%s configured for %d ports, has %d ports.\n", - brd->name, brd->nasync, true_count); - - if ((brd->type == PPCM) && - (true_count == 64 || true_count == 0)) { - dev_warn(&brd->pdev->dev, - "Please make SURE the EBI cable running from the card\n"); - dev_warn(&brd->pdev->dev, - "to each EM module is plugged into EBI IN!\n"); - } - - brd->nasync = true_count; - - /* If no ports, don't bother going any further */ - if (!brd->nasync) { - brd->state = BOARD_FAILED; - brd->dpastatus = BD_NOFEP; - return -EIO; - } - } - - /* - * Allocate channel memory that might not have been allocated - * when the driver was first loaded. - */ - for (i = 0; i < brd->nasync; i++) { - brd->channels[i] = - kzalloc(sizeof(struct channel_t), GFP_KERNEL); - if (!brd->channels[i]) { - ret = -ENOMEM; - goto free_chan; - } - } - - ch = brd->channels[0]; - vaddr = brd->re_map_membase; - - bs = (struct bs_t __iomem *)((ulong)vaddr + CHANBUF); - cm = (struct cm_t __iomem *)((ulong)vaddr + CMDBUF); - - brd->bd_bs = bs; - - /* Set up channel variables */ - for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) { - spin_lock_init(&ch->ch_lock); - - /* Store all our magic numbers */ - ch->magic = DGAP_CHANNEL_MAGIC; - ch->ch_tun.magic = DGAP_UNIT_MAGIC; - ch->ch_tun.un_type = DGAP_SERIAL; - ch->ch_tun.un_ch = ch; - ch->ch_tun.un_dev = i; - - ch->ch_pun.magic = DGAP_UNIT_MAGIC; - ch->ch_pun.un_type = DGAP_PRINT; - ch->ch_pun.un_ch = ch; - ch->ch_pun.un_dev = i; - - ch->ch_vaddr = vaddr; - ch->ch_bs = bs; - ch->ch_cm = cm; - ch->ch_bd = brd; - ch->ch_portnum = i; - ch->ch_digi = dgap_digi_init; - - /* - * Set up digi dsr and dcd bits based on altpin flag. - */ - if (dgap_config_get_altpin(brd)) { - ch->ch_dsr = DM_CD; - ch->ch_cd = DM_DSR; - ch->ch_digi.digi_flags |= DIGI_ALTPIN; - } else { - ch->ch_cd = DM_CD; - ch->ch_dsr = DM_DSR; - } - - ch->ch_taddr = vaddr + (ioread16(&ch->ch_bs->tx_seg) << 4); - ch->ch_raddr = vaddr + (ioread16(&ch->ch_bs->rx_seg) << 4); - ch->ch_tx_win = 0; - ch->ch_rx_win = 0; - ch->ch_tsize = readw(&ch->ch_bs->tx_max) + 1; - ch->ch_rsize = readw(&ch->ch_bs->rx_max) + 1; - ch->ch_tstart = 0; - ch->ch_rstart = 0; - - /* - * Set queue water marks, interrupt mask, - * and general tty parameters. - */ - tlw = ch->ch_tsize >= 2000 ? ((ch->ch_tsize * 5) / 8) : - ch->ch_tsize / 2; - ch->ch_tlw = tlw; - - dgap_cmdw(ch, STLOW, tlw, 0); - - dgap_cmdw(ch, SRLOW, ch->ch_rsize / 2, 0); - - dgap_cmdw(ch, SRHIGH, 7 * ch->ch_rsize / 8, 0); - - ch->ch_mistat = readb(&ch->ch_bs->m_stat); - - init_waitqueue_head(&ch->ch_flags_wait); - init_waitqueue_head(&ch->ch_tun.un_flags_wait); - init_waitqueue_head(&ch->ch_pun.un_flags_wait); - - /* Turn on all modem interrupts for now */ - modem = (DM_CD | DM_DSR | DM_CTS | DM_RI); - writeb(modem, &ch->ch_bs->m_int); - - /* - * Set edelay to 0 if interrupts are turned on, - * otherwise set edelay to the usual 100. - */ - if (brd->intr_used) - writew(0, &ch->ch_bs->edelay); - else - writew(100, &ch->ch_bs->edelay); - - writeb(1, &ch->ch_bs->idata); - } - - return 0; - -free_chan: - while (--i >= 0) { - kfree(brd->channels[i]); - brd->channels[i] = NULL; - } - return ret; -} - -/* - * dgap_tty_free() - * - * Free the channles which are allocated in dgap_tty_init(). - */ -static void dgap_tty_free(struct board_t *brd) -{ - int i; - - for (i = 0; i < brd->nasync; i++) - kfree(brd->channels[i]); -} - -static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int rc; - struct board_t *brd; - - if (dgap_numboards >= MAXBOARDS) - return -EPERM; - - rc = pci_enable_device(pdev); - if (rc) - return -EIO; - - brd = dgap_found_board(pdev, ent->driver_data, dgap_numboards); - if (IS_ERR(brd)) - return PTR_ERR(brd); - - rc = dgap_firmware_load(pdev, ent->driver_data, brd); - if (rc) - goto cleanup_brd; - - rc = dgap_alloc_flipbuf(brd); - if (rc) - goto cleanup_brd; - - rc = dgap_tty_register(brd); - if (rc) - goto free_flipbuf; - - rc = dgap_request_irq(brd); - if (rc) - goto unregister_tty; - - /* - * Do tty device initialization. - */ - rc = dgap_tty_init(brd); - if (rc < 0) - goto free_irq; - - rc = dgap_tty_register_ports(brd); - if (rc) - goto tty_free; - - brd->state = BOARD_READY; - brd->dpastatus = BD_RUNNING; - - dgap_board[dgap_numboards++] = brd; - - return 0; - -tty_free: - dgap_tty_free(brd); -free_irq: - dgap_free_irq(brd); -unregister_tty: - dgap_tty_unregister(brd); -free_flipbuf: - dgap_free_flipbuf(brd); -cleanup_brd: - dgap_cleanup_nodes(); - dgap_unmap(brd); - kfree(brd); - - return rc; -} - -/* - * dgap_cleanup_board() - * - * Free all the memory associated with a board - */ -static void dgap_cleanup_board(struct board_t *brd) -{ - unsigned int i; - - if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return; - - dgap_free_irq(brd); - - tasklet_kill(&brd->helper_tasklet); - - dgap_unmap(brd); - - /* Free all allocated channels structs */ - for (i = 0; i < MAXPORTS ; i++) - kfree(brd->channels[i]); - - kfree(brd->flipbuf); - kfree(brd->flipflagbuf); - - dgap_board[brd->boardnum] = NULL; - - kfree(brd); -} - -static void dgap_stop(bool removesys, struct pci_driver *drv) -{ - unsigned long lock_flags; - - spin_lock_irqsave(&dgap_poll_lock, lock_flags); - dgap_poll_stop = 1; - spin_unlock_irqrestore(&dgap_poll_lock, lock_flags); - - del_timer_sync(&dgap_poll_timer); - if (removesys) - dgap_remove_driver_sysfiles(drv); - - device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0)); - class_destroy(dgap_class); - unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); -} - -static void dgap_remove_one(struct pci_dev *dev) -{ - unsigned int i; - struct pci_driver *drv = to_pci_driver(dev->dev.driver); - - dgap_stop(true, drv); - for (i = 0; i < dgap_numboards; ++i) { - dgap_remove_ports_sysfiles(dgap_board[i]); - dgap_cleanup_tty(dgap_board[i]); - dgap_cleanup_board(dgap_board[i]); - } - - dgap_cleanup_nodes(); -} - -static struct pci_driver dgap_driver = { - .name = "dgap", - .probe = dgap_init_one, - .id_table = dgap_pci_tbl, - .remove = dgap_remove_one, -}; - -/* - * Start of driver. - */ -static int dgap_start(void) -{ - int rc; - unsigned long flags; - struct device *device; - - dgap_numboards = 0; - - pr_info("For the tools package please visit http://www.digi.com\n"); - - /* - * Register our base character device into the kernel. - */ - - /* - * Register management/dpa devices - */ - rc = register_chrdev(DIGI_DGAP_MAJOR, "dgap", &dgap_board_fops); - if (rc < 0) - return rc; - - dgap_class = class_create(THIS_MODULE, "dgap_mgmt"); - if (IS_ERR(dgap_class)) { - rc = PTR_ERR(dgap_class); - goto failed_class; - } - - device = device_create(dgap_class, NULL, - MKDEV(DIGI_DGAP_MAJOR, 0), - NULL, "dgap_mgmt"); - if (IS_ERR(device)) { - rc = PTR_ERR(device); - goto failed_device; - } - - /* Start the poller */ - spin_lock_irqsave(&dgap_poll_lock, flags); - setup_timer(&dgap_poll_timer, dgap_poll_handler, 0); - dgap_poll_timer.data = 0; - dgap_poll_time = jiffies + dgap_jiffies_from_ms(dgap_poll_tick); - dgap_poll_timer.expires = dgap_poll_time; - spin_unlock_irqrestore(&dgap_poll_lock, flags); - - add_timer(&dgap_poll_timer); - - return rc; - -failed_device: - class_destroy(dgap_class); -failed_class: - unregister_chrdev(DIGI_DGAP_MAJOR, "dgap"); - return rc; -} - -/************************************************************************ - * - * Driver load/unload functions - * - ************************************************************************/ - -/* - * init_module() - * - * Module load. This is where it all starts. - */ -static int dgap_init_module(void) -{ - int rc; - - pr_info("%s, Digi International Part Number %s\n", DG_NAME, DG_PART); - - rc = dgap_start(); - if (rc) - return rc; - - rc = pci_register_driver(&dgap_driver); - if (rc) { - dgap_stop(false, NULL); - return rc; - } - - rc = dgap_create_driver_sysfiles(&dgap_driver); - if (rc) - goto err_unregister; - - dgap_driver_state = DRIVER_READY; - - return 0; - -err_unregister: - pci_unregister_driver(&dgap_driver); - return rc; -} - -/* - * dgap_cleanup_module() - * - * Module unload. This is where it all ends. - */ -static void dgap_cleanup_module(void) -{ - if (dgap_numboards) - pci_unregister_driver(&dgap_driver); -} - -module_init(dgap_init_module); -module_exit(dgap_cleanup_module); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Digi International, http://www.digi.com"); -MODULE_DESCRIPTION("Driver for the Digi International EPCA PCI based product line"); -MODULE_SUPPORTED_DEVICE("dgap"); diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h deleted file mode 100644 index c84dbf2a0684..000000000000 --- a/drivers/staging/dgap/dgap.h +++ /dev/null @@ -1,1229 +0,0 @@ -/* - * Copyright 2003 Digi International (www.digi.com) - * Scott H Kilau - * - * 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, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY, 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. - * - * 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. - * - * NOTE: THIS IS A SHARED HEADER. DO NOT CHANGE CODING STYLE!!! - * - ************************************************************************* - * - * Driver includes - * - *************************************************************************/ - -#ifndef __DGAP_DRIVER_H -#define __DGAP_DRIVER_H - -#include /* To pick up the varions Linux types */ -#include /* To pick up the various tty structs/defines */ -#include /* For irqreturn_t type */ - -#ifndef TRUE -# define TRUE 1 -#endif - -#ifndef FALSE -# define FALSE 0 -#endif - -#if !defined(TTY_FLIPBUF_SIZE) -# define TTY_FLIPBUF_SIZE 512 -#endif - -/************************************************************************* - * - * Driver defines - * - *************************************************************************/ - -/* - * Driver identification - */ -#define DG_NAME "dgap-1.3-16" -#define DG_PART "40002347_C" -#define DRVSTR "dgap" - -/* - * defines from dgap_pci.h - */ -#define PCIMAX 32 /* maximum number of PCI boards */ - -#define DIGI_VID 0x114F - -#define PCI_DEV_EPC_DID 0x0002 -#define PCI_DEV_XEM_DID 0x0004 -#define PCI_DEV_XR_DID 0x0005 -#define PCI_DEV_CX_DID 0x0006 -#define PCI_DEV_XRJ_DID 0x0009 /* PLX-based Xr adapter */ -#define PCI_DEV_XR_IBM_DID 0x0011 /* IBM 8-port Async Adapter */ -#define PCI_DEV_XR_BULL_DID 0x0013 /* BULL 8-port Async Adapter */ -#define PCI_DEV_XR_SAIP_DID 0x001c /* SAIP card - Xr adapter */ -#define PCI_DEV_XR_422_DID 0x0012 /* Xr-422 */ -#define PCI_DEV_920_2_DID 0x0034 /* XR-Plus 920 K, 2 port */ -#define PCI_DEV_920_4_DID 0x0026 /* XR-Plus 920 K, 4 port */ -#define PCI_DEV_920_8_DID 0x0027 /* XR-Plus 920 K, 8 port */ -#define PCI_DEV_EPCJ_DID 0x000a /* PLX 9060 chip for PCI */ -#define PCI_DEV_CX_IBM_DID 0x001b /* IBM 128-port Async Adapter */ -#define PCI_DEV_920_8_HP_DID 0x0058 /* HP XR-Plus 920 K, 8 port */ -#define PCI_DEV_XEM_HP_DID 0x0059 /* HP Xem PCI */ - -#define PCI_DEV_XEM_NAME "AccelePort XEM" -#define PCI_DEV_CX_NAME "AccelePort CX" -#define PCI_DEV_XR_NAME "AccelePort Xr" -#define PCI_DEV_XRJ_NAME "AccelePort Xr (PLX)" -#define PCI_DEV_XR_SAIP_NAME "AccelePort Xr (SAIP)" -#define PCI_DEV_920_2_NAME "AccelePort Xr920 2 port" -#define PCI_DEV_920_4_NAME "AccelePort Xr920 4 port" -#define PCI_DEV_920_8_NAME "AccelePort Xr920 8 port" -#define PCI_DEV_XR_422_NAME "AccelePort Xr 422" -#define PCI_DEV_EPCJ_NAME "AccelePort EPC (PLX)" -#define PCI_DEV_XR_BULL_NAME "AccelePort Xr (BULL)" -#define PCI_DEV_XR_IBM_NAME "AccelePort Xr (IBM)" -#define PCI_DEV_CX_IBM_NAME "AccelePort CX (IBM)" -#define PCI_DEV_920_8_HP_NAME "AccelePort Xr920 8 port (HP)" -#define PCI_DEV_XEM_HP_NAME "AccelePort XEM (HP)" - -/* - * On the PCI boards, there is no IO space allocated - * The I/O registers will be in the first 3 bytes of the - * upper 2MB of the 4MB memory space. The board memory - * will be mapped into the low 2MB of the 4MB memory space - */ - -/* Potential location of PCI Bios from E0000 to FFFFF*/ -#define PCI_BIOS_SIZE 0x00020000 - -/* Size of Memory and I/O for PCI (4MB) */ -#define PCI_RAM_SIZE 0x00400000 - -/* Size of Memory (2MB) */ -#define PCI_MEM_SIZE 0x00200000 - -/* Max PCI Window Size (2MB) */ -#define PCI_WIN_SIZE 0x00200000 - -#define PCI_WIN_SHIFT 21 /* 21 bits max */ - -/* Offset of I/0 in Memory (2MB) */ -#define PCI_IO_OFFSET 0x00200000 - -/* Size of IO (2MB) */ -#define PCI_IO_SIZE_DGAP 0x00200000 - -/* Number of boards we support at once. */ -#define MAXBOARDS 32 -#define MAXPORTS 224 -#define MAXTTYNAMELEN 200 - -/* Our 3 magic numbers for our board, channel and unit structs */ -#define DGAP_BOARD_MAGIC 0x5c6df104 -#define DGAP_CHANNEL_MAGIC 0x6c6df104 -#define DGAP_UNIT_MAGIC 0x7c6df104 - -/* Serial port types */ -#define DGAP_SERIAL 0 -#define DGAP_PRINT 1 - -#define SERIAL_TYPE_NORMAL 1 - -/* 4 extra for alignment play space */ -#define WRITEBUFLEN ((4096) + 4) -#define MYFLIPLEN N_TTY_BUF_SIZE - -#define SBREAK_TIME 0x25 -#define U2BSIZE 0x400 - -#define dgap_jiffies_from_ms(a) (((a) * HZ) / 1000) - -/* - * Our major for the mgmt devices. - * - * We can use 22, because Digi was allocated 22 and 23 for the epca driver. - * 22 has now become obsolete now that the "cu" devices have - * been removed from 2.6. - * Also, this *IS* the epca driver, just PCI only now. - */ -#ifndef DIGI_DGAP_MAJOR -# define DIGI_DGAP_MAJOR 22 -#endif - -/* - * The parameters we use to define the periods of the moving averages. - */ -#define MA_PERIOD (HZ / 10) -#define SMA_DUR (1 * HZ) -#define EMA_DUR (1 * HZ) -#define SMA_NPERIODS (SMA_DUR / MA_PERIOD) -#define EMA_NPERIODS (EMA_DUR / MA_PERIOD) - -/* - * Define a local default termios struct. All ports will be created - * with this termios initially. This is the same structure that is defined - * as the default in tty_io.c with the same settings overridden as in serial.c - * - * In short, this should match the internal serial ports' defaults. - */ -#define DEFAULT_IFLAGS (ICRNL | IXON) -#define DEFAULT_OFLAGS (OPOST | ONLCR) -#define DEFAULT_CFLAGS (B9600 | CS8 | CREAD | HUPCL | CLOCAL) -#define DEFAULT_LFLAGS (ISIG | ICANON | ECHO | ECHOE | ECHOK | \ - ECHOCTL | ECHOKE | IEXTEN) - -#ifndef _POSIX_VDISABLE -#define _POSIX_VDISABLE ('\0') -#endif - -#define SNIFF_MAX 65536 /* Sniff buffer size (2^n) */ -#define SNIFF_MASK (SNIFF_MAX - 1) /* Sniff wrap mask */ - -#define VPDSIZE (512) - -/************************************************************************ - * FEP memory offsets - ************************************************************************/ -#define START 0x0004L /* Execution start address */ - -#define CMDBUF 0x0d10L /* Command (cm_t) structure offset */ -#define CMDSTART 0x0400L /* Start of command buffer */ -#define CMDMAX 0x0800L /* End of command buffer */ - -#define EVBUF 0x0d18L /* Event (ev_t) structure */ -#define EVSTART 0x0800L /* Start of event buffer */ -#define EVMAX 0x0c00L /* End of event buffer */ -#define FEP5_PLUS 0x0E40 /* ASCII '5' and ASCII 'A' is here */ -#define ECS_SEG 0x0E44 /* Segment of the extended */ - /* channel structure */ -#define LINE_SPEED 0x10 /* Offset into ECS_SEG for line */ - /* speed if the fep has extended */ - /* capabilities */ - -/* BIOS MAGIC SPOTS */ -#define ERROR 0x0C14L /* BIOS error code */ -#define SEQUENCE 0x0C12L /* BIOS sequence indicator */ -#define POSTAREA 0x0C00L /* POST complete message area */ - -/* FEP MAGIC SPOTS */ -#define FEPSTAT POSTAREA /* OS here when FEP comes up */ -#define NCHAN 0x0C02L /* number of ports FEP sees */ -#define PANIC 0x0C10L /* PANIC area for FEP */ -#define KMEMEM 0x0C30L /* Memory for KME use */ -#define CONFIG 0x0CD0L /* Concentrator configuration info */ -#define CONFIGSIZE 0x0030 /* configuration info size */ -#define DOWNREQ 0x0D00 /* Download request buffer pointer */ - -#define CHANBUF 0x1000L /* Async channel (bs_t) structs */ -#define FEPOSSIZE 0x1FFF /* 8K FEPOS */ - -#define XEMPORTS 0xC02 /* - * Offset in board memory where FEP5 stores - * how many ports it has detected. - * NOTE: FEP5 reports 64 ports when the user - * has the cable in EBI OUT instead of EBI IN. - */ - -#define FEPCLR 0x00 -#define FEPMEM 0x02 -#define FEPRST 0x04 -#define FEPINT 0x08 -#define FEPMASK 0x0e -#define FEPWIN 0x80 - -#define LOWMEM 0x0100 -#define HIGHMEM 0x7f00 - -#define FEPTIMEOUT 200000 - -#define ENABLE_INTR 0x0e04 /* Enable interrupts flag */ -#define FEPPOLL_MIN 1 /* minimum of 1 millisecond */ -#define FEPPOLL_MAX 20 /* maximum of 20 milliseconds */ -#define FEPPOLL 0x0c26 /* Fep event poll interval */ - -#define IALTPIN 0x0080 /* Input flag to swap DSR <-> DCD */ - -/************************************************************************ - * FEP supported functions - ************************************************************************/ -#define SRLOW 0xe0 /* Set receive low water */ -#define SRHIGH 0xe1 /* Set receive high water */ -#define FLUSHTX 0xe2 /* Flush transmit buffer */ -#define PAUSETX 0xe3 /* Pause data transmission */ -#define RESUMETX 0xe4 /* Resume data transmission */ -#define SMINT 0xe5 /* Set Modem Interrupt */ -#define SAFLOWC 0xe6 /* Set Aux. flow control chars */ -#define SBREAK 0xe8 /* Send break */ -#define SMODEM 0xe9 /* Set 8530 modem control lines */ -#define SIFLAG 0xea /* Set UNIX iflags */ -#define SFLOWC 0xeb /* Set flow control characters */ -#define STLOW 0xec /* Set transmit low water mark */ -#define RPAUSE 0xee /* Pause receive */ -#define RRESUME 0xef /* Resume receive */ -#define CHRESET 0xf0 /* Reset Channel */ -#define BUFSETALL 0xf2 /* Set Tx & Rx buffer size avail*/ -#define SOFLAG 0xf3 /* Set UNIX oflags */ -#define SHFLOW 0xf4 /* Set hardware handshake */ -#define SCFLAG 0xf5 /* Set UNIX cflags */ -#define SVNEXT 0xf6 /* Set VNEXT character */ -#define SPINTFC 0xfc /* Reserved */ -#define SCOMMODE 0xfd /* Set RS232/422 mode */ - -/************************************************************************ - * Modes for SCOMMODE - ************************************************************************/ -#define MODE_232 0x00 -#define MODE_422 0x01 - -/************************************************************************ - * Event flags. - ************************************************************************/ -#define IFBREAK 0x01 /* Break received */ -#define IFTLW 0x02 /* Transmit low water */ -#define IFTEM 0x04 /* Transmitter empty */ -#define IFDATA 0x08 /* Receive data present */ -#define IFMODEM 0x20 /* Modem status change */ - -/************************************************************************ - * Modem flags - ************************************************************************/ -# define DM_RTS 0x02 /* Request to send */ -# define DM_CD 0x80 /* Carrier detect */ -# define DM_DSR 0x20 /* Data set ready */ -# define DM_CTS 0x10 /* Clear to send */ -# define DM_RI 0x40 /* Ring indicator */ -# define DM_DTR 0x01 /* Data terminal ready */ - -/* - * defines from dgap_conf.h - */ -#define NULLNODE 0 /* header node, not used */ -#define BNODE 1 /* Board node */ -#define LNODE 2 /* Line node */ -#define CNODE 3 /* Concentrator node */ -#define MNODE 4 /* EBI Module node */ -#define TNODE 5 /* tty name prefix node */ -#define CUNODE 6 /* cu name prefix (non-SCO) */ -#define PNODE 7 /* trans. print prefix node */ -#define JNODE 8 /* maJor number node */ -#define ANODE 9 /* altpin */ -#define TSNODE 10 /* tty structure size */ -#define CSNODE 11 /* channel structure size */ -#define BSNODE 12 /* board structure size */ -#define USNODE 13 /* unit schedule structure size */ -#define FSNODE 14 /* f2200 structure size */ -#define VSNODE 15 /* size of VPIX structures */ -#define INTRNODE 16 /* enable interrupt */ - -/* Enumeration of tokens */ -#define BEGIN 1 -#define END 2 -#define BOARD 10 - -#define EPCFS 11 /* start of EPC family definitions */ -#define ICX 11 -#define MCX 13 -#define PCX 14 -#define IEPC 15 -#define EEPC 16 -#define MEPC 17 -#define IPCM 18 -#define EPCM 19 -#define MPCM 20 -#define PEPC 21 -#define PPCM 22 -#ifdef CP -#define ICP 23 -#define ECP 24 -#define MCP 25 -#endif -#define EPCFE 25 /* end of EPC family definitions */ -#define PC2E 26 -#define PC4E 27 -#define PC4E8K 28 -#define PC8E 29 -#define PC8E8K 30 -#define PC16E 31 -#define MC2E8K 34 -#define MC4E8K 35 -#define MC8E8K 36 - -#define AVANFS 42 /* start of Avanstar family definitions */ -#define A8P 42 -#define A16P 43 -#define AVANFE 43 /* end of Avanstar family definitions */ - -#define DA2000FS 44 /* start of AccelePort 2000 family definitions */ -#define DA22 44 /* AccelePort 2002 */ -#define DA24 45 /* AccelePort 2004 */ -#define DA28 46 /* AccelePort 2008 */ -#define DA216 47 /* AccelePort 2016 */ -#define DAR4 48 /* AccelePort RAS 4 port */ -#define DAR8 49 /* AccelePort RAS 8 port */ -#define DDR24 50 /* DataFire RAS 24 port */ -#define DDR30 51 /* DataFire RAS 30 port */ -#define DDR48 52 /* DataFire RAS 48 port */ -#define DDR60 53 /* DataFire RAS 60 port */ -#define DA2000FE 53 /* end of AccelePort 2000/RAS family definitions */ - -#define PCXRFS 106 /* start of PCXR family definitions */ -#define APORT4 106 -#define APORT8 107 -#define PAPORT4 108 -#define PAPORT8 109 -#define APORT4_920I 110 -#define APORT8_920I 111 -#define APORT4_920P 112 -#define APORT8_920P 113 -#define APORT2_920P 114 -#define PCXRFE 117 /* end of PCXR family definitions */ - -#define LINE 82 -#ifdef T1 -#define T1M 83 -#define E1M 84 -#endif -#define CONC 64 -#define CX 65 -#define EPC 66 -#define MOD 67 -#define PORTS 68 -#define METHOD 69 -#define CUSTOM 70 -#define BASIC 71 -#define STATUS 72 -#define MODEM 73 -/* The following tokens can appear in multiple places */ -#define SPEED 74 -#define NPORTS 75 -#define ID 76 -#define CABLE 77 -#define CONNECT 78 -#define MEM 80 -#define DPSZ 81 - -#define TTYN 90 -#define CU 91 -#define PRINT 92 -#define XPRINT 93 -#define CMAJOR 94 -#define ALTPIN 95 -#define STARTO 96 -#define USEINTR 97 -#define PCIINFO 98 - -#define TTSIZ 100 -#define CHSIZ 101 -#define BSSIZ 102 -#define UNTSIZ 103 -#define F2SIZ 104 -#define VPSIZ 105 - -#define TOTAL_BOARD 2 -#define CURRENT_BRD 4 -#define BOARD_TYPE 6 -#define IO_ADDRESS 8 -#define MEM_ADDRESS 10 - -#define FIELDS_PER_PAGE 18 - -#define TB_FIELD 1 -#define CB_FIELD 3 -#define BT_FIELD 5 -#define IO_FIELD 7 -#define ID_FIELD 8 -#define ME_FIELD 9 -#define TTY_FIELD 11 -#define CU_FIELD 13 -#define PR_FIELD 15 -#define MPR_FIELD 17 - -#define MAX_FIELD 512 - -#define INIT 0 -#define NITEMS 128 -#define MAX_ITEM 512 - -#define DSCRINST 1 -#define DSCRNUM 3 -#define ALTPINQ 5 -#define SSAVE 7 - -#define DSCR "32" -#define ONETONINE "123456789" -#define ALL "1234567890" - -/* - * All the possible states the driver can be while being loaded. - */ -enum { - DRIVER_INITIALIZED = 0, - DRIVER_READY -}; - -/* - * All the possible states the board can be while booting up. - */ -enum { - BOARD_FAILED = 0, - BOARD_READY -}; - -/* - * All the possible states that a requested concentrator image can be in. - */ -enum { - NO_PENDING_CONCENTRATOR_REQUESTS = 0, - NEED_CONCENTRATOR, - REQUESTED_CONCENTRATOR -}; - -/* - * Modem line constants are defined as macros because DSR and - * DCD are swapable using the ditty altpin option. - */ -#define D_CD(ch) ch->ch_cd /* Carrier detect */ -#define D_DSR(ch) ch->ch_dsr /* Data set ready */ -#define D_RTS(ch) DM_RTS /* Request to send */ -#define D_CTS(ch) DM_CTS /* Clear to send */ -#define D_RI(ch) DM_RI /* Ring indicator */ -#define D_DTR(ch) DM_DTR /* Data terminal ready */ - -/************************************************************************* - * - * Structures and closely related defines. - * - *************************************************************************/ - -/* - * A structure to hold a statistics counter. We also - * compute moving averages for this counter. - */ -struct macounter { - u32 cnt; /* Total count */ - ulong accum; /* Acuumulator per period */ - ulong sma; /* Simple moving average */ - ulong ema; /* Exponential moving average */ -}; - -/************************************************************************ - * Device flag definitions for bd_flags. - ************************************************************************/ -#define BD_FEP5PLUS 0x0001 /* Supports FEP5 Plus commands */ -#define BD_HAS_VPD 0x0002 /* Board has VPD info available */ - -/* - * Per-board information - */ -struct board_t { - int magic; /* Board Magic number. */ - int boardnum; /* Board number: 0-3 */ - - int type; /* Type of board */ - char *name; /* Product Name */ - struct pci_dev *pdev; /* Pointer to the pci_dev struct */ - u16 vendor; /* PCI vendor ID */ - u16 device; /* PCI device ID */ - u16 subvendor; /* PCI subsystem vendor ID */ - u16 subdevice; /* PCI subsystem device ID */ - u8 rev; /* PCI revision ID */ - uint pci_bus; /* PCI bus value */ - uint pci_slot; /* PCI slot value */ - u16 maxports; /* MAX ports this board can handle */ - u8 vpd[VPDSIZE]; /* VPD of board, if found */ - u32 bd_flags; /* Board flags */ - - spinlock_t bd_lock; /* Used to protect board */ - - u32 state; /* State of card. */ - wait_queue_head_t state_wait; /* Place to sleep on for state change */ - - struct tasklet_struct helper_tasklet; /* Poll helper tasklet */ - - u32 wait_for_bios; - u32 wait_for_fep; - - struct cnode *bd_config; /* Config of board */ - - u16 nasync; /* Number of ports on card */ - - ulong irq; /* Interrupt request number */ - ulong intr_count; /* Count of interrupts */ - u32 intr_used; /* Non-zero if using interrupts */ - u32 intr_running; /* Non-zero if FEP knows its doing */ - /* interrupts */ - - ulong port; /* Start of base io port of the card */ - ulong port_end; /* End of base io port of the card */ - ulong membase; /* Start of base memory of the card */ - ulong membase_end; /* End of base memory of the card */ - - u8 __iomem *re_map_port; /* Remapped io port of the card */ - u8 __iomem *re_map_membase;/* Remapped memory of the card */ - - u8 inhibit_poller; /* Tells the poller to leave us alone */ - - struct channel_t *channels[MAXPORTS]; /* array of pointers to our */ - /* channels. */ - - struct tty_driver *serial_driver; - struct tty_port *serial_ports; - char serial_name[200]; - struct tty_driver *print_driver; - struct tty_port *printer_ports; - char print_name[200]; - - struct bs_t __iomem *bd_bs; /* Base structure pointer */ - - char *flipbuf; /* Our flip buffer, alloced if */ - /* board is found */ - char *flipflagbuf; /* Our flip flag buffer, alloced */ - /* if board is found */ - - u16 dpatype; /* The board "type", as defined */ - /* by DPA */ - u16 dpastatus; /* The board "status", as defined */ - /* by DPA */ - - u32 conc_dl_status; /* Status of any pending conc */ - /* download */ -}; - -/************************************************************************ - * Unit flag definitions for un_flags. - ************************************************************************/ -#define UN_ISOPEN 0x0001 /* Device is open */ -#define UN_CLOSING 0x0002 /* Line is being closed */ -#define UN_IMM 0x0004 /* Service immediately */ -#define UN_BUSY 0x0008 /* Some work this channel */ -#define UN_BREAKI 0x0010 /* Input break received */ -#define UN_PWAIT 0x0020 /* Printer waiting for terminal */ -#define UN_TIME 0x0040 /* Waiting on time */ -#define UN_EMPTY 0x0080 /* Waiting output queue empty */ -#define UN_LOW 0x0100 /* Waiting output low water mark*/ -#define UN_EXCL_OPEN 0x0200 /* Open for exclusive use */ -#define UN_WOPEN 0x0400 /* Device waiting for open */ -#define UN_WIOCTL 0x0800 /* Device waiting for open */ -#define UN_HANGUP 0x8000 /* Carrier lost */ - -struct device; - -/************************************************************************ - * Structure for terminal or printer unit. - ************************************************************************/ -struct un_t { - int magic; /* Unit Magic Number. */ - struct channel_t *un_ch; - u32 un_time; - u32 un_type; - int un_open_count; /* Counter of opens to port */ - struct tty_struct *un_tty;/* Pointer to unit tty structure */ - u32 un_flags; /* Unit flags */ - wait_queue_head_t un_flags_wait; /* Place to sleep to wait on unit */ - u32 un_dev; /* Minor device number */ - tcflag_t un_oflag; /* oflags being done on board */ - tcflag_t un_lflag; /* lflags being done on board */ - struct device *un_sysfs; -}; - -/************************************************************************ - * Device flag definitions for ch_flags. - ************************************************************************/ -#define CH_PRON 0x0001 /* Printer on string */ -#define CH_OUT 0x0002 /* Dial-out device open */ -#define CH_STOP 0x0004 /* Output is stopped */ -#define CH_STOPI 0x0008 /* Input is stopped */ -#define CH_CD 0x0010 /* Carrier is present */ -#define CH_FCAR 0x0020 /* Carrier forced on */ - -#define CH_RXBLOCK 0x0080 /* Enable rx blocked flag */ -#define CH_WLOW 0x0100 /* Term waiting low event */ -#define CH_WEMPTY 0x0200 /* Term waiting empty event */ -#define CH_RENABLE 0x0400 /* Buffer just emptied */ -#define CH_RACTIVE 0x0800 /* Process active in xxread() */ -#define CH_RWAIT 0x1000 /* Process waiting in xxread() */ -#define CH_BAUD0 0x2000 /* Used for checking B0 transitions */ -#define CH_HANGUP 0x8000 /* Hangup received */ - -/* - * Definitions for ch_sniff_flags - */ -#define SNIFF_OPEN 0x1 -#define SNIFF_WAIT_DATA 0x2 -#define SNIFF_WAIT_SPACE 0x4 - -/************************************************************************ - *** Definitions for Digi ditty(1) command. - ************************************************************************/ - -/************************************************************************ - * This module provides application access to special Digi - * serial line enhancements which are not standard UNIX(tm) features. - ************************************************************************/ - -#if !defined(TIOCMODG) - -#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ -#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ - -#ifndef TIOCM_LE -#define TIOCM_LE 0x01 /* line enable */ -#define TIOCM_DTR 0x02 /* data terminal ready */ -#define TIOCM_RTS 0x04 /* request to send */ -#define TIOCM_ST 0x08 /* secondary transmit */ -#define TIOCM_SR 0x10 /* secondary receive */ -#define TIOCM_CTS 0x20 /* clear to send */ -#define TIOCM_CAR 0x40 /* carrier detect */ -#define TIOCM_RNG 0x80 /* ring indicator */ -#define TIOCM_DSR 0x100 /* data set ready */ -#define TIOCM_RI TIOCM_RNG /* ring (alternate) */ -#define TIOCM_CD TIOCM_CAR /* carrier detect (alt) */ -#endif - -#endif - -#if !defined(TIOCMSET) -#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ -#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ -#endif - -#if !defined(TIOCMBIC) -#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ -#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ -#endif - -#if !defined(TIOCSDTR) -#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ -#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ -#endif - -/************************************************************************ - * Ioctl command arguments for DIGI parameters. - ************************************************************************/ -#define DIGI_GETA (('e'<<8) | 94) /* Read params */ - -#define DIGI_SETA (('e'<<8) | 95) /* Set params */ -#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ -#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ - -#define DIGI_KME (('e'<<8) | 98) /* Read/Write Host */ - /* Adapter Memory */ - -#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ - /* control characters */ -#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ - /* control characters */ -#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ - /* flow control chars */ -#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ - /* flow control chars */ - -#define DIGI_GEDELAY (('d'<<8) | 246) /* Get edelay */ -#define DIGI_SEDELAY (('d'<<8) | 247) /* Set edelay */ - -struct digiflow_t { - unsigned char startc; /* flow cntl start char */ - unsigned char stopc; /* flow cntl stop char */ -}; - -#ifdef FLOW_2200 -#define F2200_GETA (('e'<<8) | 104) /* Get 2x36 flow cntl flags */ -#define F2200_SETAW (('e'<<8) | 105) /* Set 2x36 flow cntl flags */ -#define F2200_MASK 0x03 /* 2200 flow cntl bit mask */ -#define FCNTL_2200 0x01 /* 2x36 terminal flow cntl */ -#define PCNTL_2200 0x02 /* 2x36 printer flow cntl */ -#define F2200_XON 0xf8 -#define P2200_XON 0xf9 -#define F2200_XOFF 0xfa -#define P2200_XOFF 0xfb - -#define FXOFF_MASK 0x03 /* 2200 flow status mask */ -#define RCVD_FXOFF 0x01 /* 2x36 Terminal XOFF rcvd */ -#define RCVD_PXOFF 0x02 /* 2x36 Printer XOFF rcvd */ -#endif - -/************************************************************************ - * Values for digi_flags - ************************************************************************/ -#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ -#define DIGI_FAST 0x0002 /* Fast baud rates */ -#define RTSPACE 0x0004 /* RTS input flow control */ -#define CTSPACE 0x0008 /* CTS output flow control */ -#define DSRPACE 0x0010 /* DSR output flow control */ -#define DCDPACE 0x0020 /* DCD output flow control */ -#define DTRPACE 0x0040 /* DTR input flow control */ -#define DIGI_COOK 0x0080 /* Cooked processing done in FEP */ -#define DIGI_FORCEDCD 0x0100 /* Force carrier */ -#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ -#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ -#define DIGI_PRINTER 0x0800 /* Hold port open for flow cntrl*/ -#define DIGI_PP_INPUT 0x1000 /* Change parallel port to input*/ -#define DIGI_DTR_TOGGLE 0x2000 /* Support DTR Toggle */ -#define DIGI_422 0x4000 /* for 422/232 selectable panel */ -#define DIGI_RTS_TOGGLE 0x8000 /* Support RTS Toggle */ - -/************************************************************************ - * These options are not supported on the comxi. - ************************************************************************/ -#define DIGI_COMXI (DIGI_FAST|DIGI_COOK|DSRPACE|DCDPACE|DTRPACE) - -#define DIGI_PLEN 28 /* String length */ -#define DIGI_TSIZ 10 /* Terminal string len */ - -/************************************************************************ - * Structure used with ioctl commands for DIGI parameters. - ************************************************************************/ -struct digi_t { - unsigned short digi_flags; /* Flags (see above) */ - unsigned short digi_maxcps; /* Max printer CPS */ - unsigned short digi_maxchar; /* Max chars in print queue */ - unsigned short digi_bufsize; /* Buffer size */ - unsigned char digi_onlen; /* Length of ON string */ - unsigned char digi_offlen; /* Length of OFF string */ - char digi_onstr[DIGI_PLEN]; /* Printer on string */ - char digi_offstr[DIGI_PLEN]; /* Printer off string */ - char digi_term[DIGI_TSIZ]; /* terminal string */ -}; - -/************************************************************************ - * KME definitions and structures. - ************************************************************************/ -#define RW_IDLE 0 /* Operation complete */ -#define RW_READ 1 /* Read Concentrator Memory */ -#define RW_WRITE 2 /* Write Concentrator Memory */ - -struct rw_t { - unsigned char rw_req; /* Request type */ - unsigned char rw_board; /* Host Adapter board number */ - unsigned char rw_conc; /* Concentrator number */ - unsigned char rw_reserved; /* Reserved for expansion */ - unsigned long rw_addr; /* Address in concentrator */ - unsigned short rw_size; /* Read/write request length */ - unsigned char rw_data[128]; /* Data to read/write */ -}; - -/************************************************************************ - * Structure to get driver status information - ************************************************************************/ -struct digi_dinfo { - unsigned long dinfo_nboards; /* # boards configured */ - char dinfo_reserved[12]; /* for future expansion */ - char dinfo_version[16]; /* driver version */ -}; - -#define DIGI_GETDD (('d'<<8) | 248) /* get driver info */ - -/************************************************************************ - * Structure used with ioctl commands for per-board information - * - * physsize and memsize differ when board has "windowed" memory - ************************************************************************/ -struct digi_info { - unsigned long info_bdnum; /* Board number (0 based) */ - unsigned long info_ioport; /* io port address */ - unsigned long info_physaddr; /* memory address */ - unsigned long info_physsize; /* Size of host mem window */ - unsigned long info_memsize; /* Amount of dual-port mem */ - /* on board */ - unsigned short info_bdtype; /* Board type */ - unsigned short info_nports; /* number of ports */ - char info_bdstate; /* board state */ - char info_reserved[7]; /* for future expansion */ -}; - -#define DIGI_GETBD (('d'<<8) | 249) /* get board info */ - -struct digi_stat { - unsigned int info_chan; /* Channel number (0 based) */ - unsigned int info_brd; /* Board number (0 based) */ - unsigned long info_cflag; /* cflag for channel */ - unsigned long info_iflag; /* iflag for channel */ - unsigned long info_oflag; /* oflag for channel */ - unsigned long info_mstat; /* mstat for channel */ - unsigned long info_tx_data; /* tx_data for channel */ - unsigned long info_rx_data; /* rx_data for channel */ - unsigned long info_hflow; /* hflow for channel */ - unsigned long info_reserved[8]; /* for future expansion */ -}; - -#define DIGI_GETSTAT (('d'<<8) | 244) /* get board info */ -/************************************************************************ - * - * Structure used with ioctl commands for per-channel information - * - ************************************************************************/ -struct digi_ch { - unsigned long info_bdnum; /* Board number (0 based) */ - unsigned long info_channel; /* Channel index number */ - unsigned long info_ch_cflag; /* Channel cflag */ - unsigned long info_ch_iflag; /* Channel iflag */ - unsigned long info_ch_oflag; /* Channel oflag */ - unsigned long info_chsize; /* Channel structure size */ - unsigned long info_sleep_stat; /* sleep status */ - dev_t info_dev; /* device number */ - unsigned char info_initstate; /* Channel init state */ - unsigned char info_running; /* Channel running state */ - long reserved[8]; /* reserved for future use */ -}; - -/* -* This structure is used with the DIGI_FEPCMD ioctl to -* tell the driver which port to send the command for. -*/ -struct digi_cmd { - int cmd; - int word; - int ncmds; - int chan; /* channel index (zero based) */ - int bdid; /* board index (zero based) */ -}; - -/* -* info_sleep_stat defines -*/ -#define INFO_RUNWAIT 0x0001 -#define INFO_WOPEN 0x0002 -#define INFO_TTIOW 0x0004 -#define INFO_CH_RWAIT 0x0008 -#define INFO_CH_WEMPTY 0x0010 -#define INFO_CH_WLOW 0x0020 -#define INFO_XXBUF_BUSY 0x0040 - -#define DIGI_GETCH (('d'<<8) | 245) /* get board info */ - -/* Board type definitions */ - -#define SUBTYPE 0007 -#define T_PCXI 0000 -#define T_PCXM 0001 -#define T_PCXE 0002 -#define T_PCXR 0003 -#define T_SP 0004 -#define T_SP_PLUS 0005 -# define T_HERC 0000 -# define T_HOU 0001 -# define T_LON 0002 -# define T_CHA 0003 -#define FAMILY 0070 -#define T_COMXI 0000 -#define T_PCXX 0010 -#define T_CX 0020 -#define T_EPC 0030 -#define T_PCLITE 0040 -#define T_SPXX 0050 -#define T_AVXX 0060 -#define T_DXB 0070 -#define T_A2K_4_8 0070 -#define BUSTYPE 0700 -#define T_ISABUS 0000 -#define T_MCBUS 0100 -#define T_EISABUS 0200 -#define T_PCIBUS 0400 - -/* Board State Definitions */ - -#define BD_RUNNING 0x0 -#define BD_REASON 0x7f -#define BD_NOTFOUND 0x1 -#define BD_NOIOPORT 0x2 -#define BD_NOMEM 0x3 -#define BD_NOBIOS 0x4 -#define BD_NOFEP 0x5 -#define BD_FAILED 0x6 -#define BD_ALLOCATED 0x7 -#define BD_TRIBOOT 0x8 -#define BD_BADKME 0x80 - -#define DIGI_LOOPBACK (('d'<<8) | 252) /* Enable/disable UART */ - /* internal loopback */ -#define DIGI_SPOLL (('d'<<8) | 254) /* change poller rate */ - -#define DIGI_SETCUSTOMBAUD _IOW('e', 106, int) /* Set integer baud rate */ -#define DIGI_GETCUSTOMBAUD _IOR('e', 107, int) /* Get integer baud rate */ -#define DIGI_RESET_PORT (('e'<<8) | 93) /* Reset port */ - -/************************************************************************ - * Channel information structure. - ************************************************************************/ -struct channel_t { - int magic; /* Channel Magic Number */ - struct bs_t __iomem *ch_bs; /* Base structure pointer */ - struct cm_t __iomem *ch_cm; /* Command queue pointer */ - struct board_t *ch_bd; /* Board structure pointer */ - u8 __iomem *ch_vaddr; /* FEP memory origin */ - u8 __iomem *ch_taddr; /* Write buffer origin */ - u8 __iomem *ch_raddr; /* Read buffer origin */ - struct digi_t ch_digi; /* Transparent Print structure */ - struct un_t ch_tun; /* Terminal unit info */ - struct un_t ch_pun; /* Printer unit info */ - - spinlock_t ch_lock; /* provide for serialization */ - wait_queue_head_t ch_flags_wait; - - u32 pscan_state; - u8 pscan_savechar; - - u32 ch_portnum; /* Port number, 0 offset. */ - u32 ch_open_count; /* open count */ - u32 ch_flags; /* Channel flags */ - - u32 ch_cpstime; /* Time for CPS calculations */ - - tcflag_t ch_c_iflag; /* channel iflags */ - tcflag_t ch_c_cflag; /* channel cflags */ - tcflag_t ch_c_oflag; /* channel oflags */ - tcflag_t ch_c_lflag; /* channel lflags */ - - u16 ch_fepiflag; /* FEP tty iflags */ - u16 ch_fepcflag; /* FEP tty cflags */ - u16 ch_fepoflag; /* FEP tty oflags */ - u16 ch_wopen; /* Waiting for open process cnt */ - u16 ch_tstart; /* Transmit buffer start */ - u16 ch_tsize; /* Transmit buffer size */ - u16 ch_rstart; /* Receive buffer start */ - u16 ch_rsize; /* Receive buffer size */ - u16 ch_rdelay; /* Receive delay time */ - - u16 ch_tlw; /* Our currently set low water mark */ - - u16 ch_cook; /* Output character mask */ - - u8 ch_card; /* Card channel is on */ - u8 ch_stopc; /* Stop character */ - u8 ch_startc; /* Start character */ - - u8 ch_mostat; /* FEP output modem status */ - u8 ch_mistat; /* FEP input modem status */ - u8 ch_mforce; /* Modem values to be forced */ - u8 ch_mval; /* Force values */ - u8 ch_fepstopc; /* FEP stop character */ - u8 ch_fepstartc; /* FEP start character */ - - u8 ch_astopc; /* Auxiliary Stop character */ - u8 ch_astartc; /* Auxiliary Start character */ - u8 ch_fepastopc; /* Auxiliary FEP stop char */ - u8 ch_fepastartc; /* Auxiliary FEP start char */ - - u8 ch_hflow; /* FEP hardware handshake */ - u8 ch_dsr; /* stores real dsr value */ - u8 ch_cd; /* stores real cd value */ - u8 ch_tx_win; /* channel tx buffer window */ - u8 ch_rx_win; /* channel rx buffer window */ - uint ch_custom_speed; /* Custom baud, if set */ - uint ch_baud_info; /* Current baud info for /proc output */ - ulong ch_rxcount; /* total of data received so far */ - ulong ch_txcount; /* total of data transmitted so far */ - ulong ch_err_parity; /* Count of parity errors on channel */ - ulong ch_err_frame; /* Count of framing errors on channel */ - ulong ch_err_break; /* Count of breaks on channel */ - ulong ch_err_overrun; /* Count of overruns on channel */ -}; - -/************************************************************************ - * Command structure definition. - ************************************************************************/ -struct cm_t { - unsigned short cm_head; /* Command buffer head offset */ - unsigned short cm_tail; /* Command buffer tail offset */ - unsigned short cm_start; /* start offset of buffer */ - unsigned short cm_max; /* last offset of buffer */ -}; - -/************************************************************************ - * Event structure definition. - ************************************************************************/ -struct ev_t { - unsigned short ev_head; /* Command buffer head offset */ - unsigned short ev_tail; /* Command buffer tail offset */ - unsigned short ev_start; /* start offset of buffer */ - unsigned short ev_max; /* last offset of buffer */ -}; - -/************************************************************************ - * Download buffer structure. - ************************************************************************/ -struct downld_t { - u8 dl_type; /* Header */ - u8 dl_seq; /* Download sequence */ - ushort dl_srev; /* Software revision number */ - ushort dl_lrev; /* Low revision number */ - ushort dl_hrev; /* High revision number */ - ushort dl_seg; /* Start segment address */ - ushort dl_size; /* Number of bytes to download */ - u8 dl_data[1024]; /* Download data */ -}; - -/************************************************************************ - * Per channel buffer structure - ************************************************************************ - * Base Structure Entries Usage Meanings to Host * - * * - * W = read write R = read only * - * C = changed by commands only * - * U = unknown (may be changed w/o notice) * - ************************************************************************/ -struct bs_t { - unsigned short tp_jmp; /* Transmit poll jump */ - unsigned short tc_jmp; /* Cooked procedure jump */ - unsigned short ri_jmp; /* Not currently used */ - unsigned short rp_jmp; /* Receive poll jump */ - - unsigned short tx_seg; /* W Tx segment */ - unsigned short tx_head; /* W Tx buffer head offset */ - unsigned short tx_tail; /* R Tx buffer tail offset */ - unsigned short tx_max; /* W Tx buffer size - 1 */ - - unsigned short rx_seg; /* W Rx segment */ - unsigned short rx_head; /* W Rx buffer head offset */ - unsigned short rx_tail; /* R Rx buffer tail offset */ - unsigned short rx_max; /* W Rx buffer size - 1 */ - - unsigned short tx_lw; /* W Tx buffer low water mark */ - unsigned short rx_lw; /* W Rx buffer low water mark */ - unsigned short rx_hw; /* W Rx buffer high water mark*/ - unsigned short incr; /* W Increment to next channel*/ - - unsigned short fepdev; /* U SCC device base address */ - unsigned short edelay; /* W Exception delay */ - unsigned short blen; /* W Break length */ - unsigned short btime; /* U Break complete time */ - - unsigned short iflag; /* C UNIX input flags */ - unsigned short oflag; /* C UNIX output flags */ - unsigned short cflag; /* C UNIX control flags */ - unsigned short wfill[13]; /* U Reserved for expansion */ - - unsigned char num; /* U Channel number */ - unsigned char ract; /* U Receiver active counter */ - unsigned char bstat; /* U Break status bits */ - unsigned char tbusy; /* W Transmit busy */ - unsigned char iempty; /* W Transmit empty event */ - /* enable */ - unsigned char ilow; /* W Transmit low-water event */ - /* enable */ - unsigned char idata; /* W Receive data interrupt */ - /* enable */ - unsigned char eflag; /* U Host event flags */ - - unsigned char tflag; /* U Transmit flags */ - unsigned char rflag; /* U Receive flags */ - unsigned char xmask; /* U Transmit ready flags */ - unsigned char xval; /* U Transmit ready value */ - unsigned char m_stat; /* RC Modem status bits */ - unsigned char m_change; /* U Modem bits which changed */ - unsigned char m_int; /* W Modem interrupt enable */ - /* bits */ - unsigned char m_last; /* U Last modem status */ - - unsigned char mtran; /* C Unreported modem trans */ - unsigned char orun; /* C Buffer overrun occurred */ - unsigned char astartc; /* W Auxiliary Xon char */ - unsigned char astopc; /* W Auxiliary Xoff char */ - unsigned char startc; /* W Xon character */ - unsigned char stopc; /* W Xoff character */ - unsigned char vnextc; /* W Vnext character */ - unsigned char hflow; /* C Software flow control */ - - unsigned char fillc; /* U Delay Fill character */ - unsigned char ochar; /* U Saved output character */ - unsigned char omask; /* U Output character mask */ - - unsigned char bfill[13]; /* U Reserved for expansion */ - - unsigned char scc[16]; /* U SCC registers */ -}; - -struct cnode { - struct cnode *next; - int type; - int numbrd; - - union { - struct { - char type; /* Board Type */ - long addr; /* Memory Address */ - char *addrstr; /* Memory Address in string */ - long pcibus; /* PCI BUS */ - char *pcibusstr; /* PCI BUS in string */ - long pcislot; /* PCI SLOT */ - char *pcislotstr; /* PCI SLOT in string */ - long nport; /* Number of Ports */ - char *id; /* tty id */ - long start; /* start of tty counting */ - char *method; /* Install method */ - char v_addr; - char v_pcibus; - char v_pcislot; - char v_nport; - char v_id; - char v_start; - char v_method; - char line1; - char line2; - char conc1; /* total concs in line1 */ - char conc2; /* total concs in line2 */ - char module1; /* total modules for line1 */ - char module2; /* total modules for line2 */ - char *status; /* config status */ - char *dimstatus; /* Y/N */ - int status_index; /* field pointer */ - } board; - - struct { - char *cable; - char v_cable; - long speed; - char v_speed; - } line; - - struct { - char type; - char *connect; - long speed; - long nport; - char *id; - char *idstr; - long start; - char v_connect; - char v_speed; - char v_nport; - char v_id; - char v_start; - } conc; - - struct { - char type; - long nport; - char *id; - char *idstr; - long start; - char v_nport; - char v_id; - char v_start; - } module; - - char *ttyname; - char *cuname; - char *printname; - long majornumber; - long altpin; - long ttysize; - long chsize; - long bssize; - long unsize; - long f2size; - long vpixsize; - long useintr; - } u; -}; -#endif -- cgit From bd2f348db5033b88b8b81caf58e7bdabf0b6961d Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 6 Jan 2016 14:04:13 +0000 Subject: goldfish: refactor goldfish platform configs On new virtual devices, the goldfish virtual bus can be replaced with autoprobing infrastructure like Device Tree. Refactor the goldfish kernel configs to better accommodate this. Move the goldfish platform into a menuconfig in the style of the chrome platform, and separate the goldfish bus into its own config option. Signed-off-by: Greg Hackmann Signed-off-by: Jin Qian [Corrected a tristate to bool] Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/Kconfig | 3 +-- drivers/platform/goldfish/Kconfig | 18 ++++++++++++++++++ drivers/platform/goldfish/Makefile | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig index 0adccbf5c83f..c11db8bceea1 100644 --- a/drivers/platform/Kconfig +++ b/drivers/platform/Kconfig @@ -4,8 +4,7 @@ endif if MIPS source "drivers/platform/mips/Kconfig" endif -if GOLDFISH + source "drivers/platform/goldfish/Kconfig" -endif source "drivers/platform/chrome/Kconfig" diff --git a/drivers/platform/goldfish/Kconfig b/drivers/platform/goldfish/Kconfig index 635ef25cc722..2be762743592 100644 --- a/drivers/platform/goldfish/Kconfig +++ b/drivers/platform/goldfish/Kconfig @@ -1,5 +1,23 @@ +menuconfig GOLDFISH + bool "Platform support for Goldfish virtual devices" + depends on X86_32 || X86_64 || ARM || ARM64 + ---help--- + Say Y here to get to see options for the Goldfish virtual platform. + This option alone does not add any kernel code. + + Unless you are building for the Android Goldfish emulator say N here. + +if GOLDFISH + +config GOLDFISH_BUS + bool "Goldfish platform bus" + ---help--- + This is a virtual bus to host Goldfish Android Virtual Devices. + config GOLDFISH_PIPE tristate "Goldfish virtual device for QEMU pipes" ---help--- This is a virtual device to drive the QEMU pipe interface used by the Goldfish Android Virtual Device. + +endif # GOLDFISH diff --git a/drivers/platform/goldfish/Makefile b/drivers/platform/goldfish/Makefile index a0022395eee9..d3487125838c 100644 --- a/drivers/platform/goldfish/Makefile +++ b/drivers/platform/goldfish/Makefile @@ -1,5 +1,5 @@ # # Makefile for Goldfish platform specific drivers # -obj-$(CONFIG_GOLDFISH) += pdev_bus.o +obj-$(CONFIG_GOLDFISH_BUS) += pdev_bus.o obj-$(CONFIG_GOLDFISH_PIPE) += goldfish_pipe.o -- cgit From 23c5ee21c46ba694681e2378e64a475b5c68f02c Mon Sep 17 00:00:00 2001 From: Alex Bennée Date: Wed, 6 Jan 2016 14:04:31 +0000 Subject: goldfish_pipe: don't be clever with #define offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It just makes it harder to figure out which commands are being used. Signed-off-by: Alex Bennée Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index e7a29e2750c6..0fb3a34f5991 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -90,12 +90,6 @@ #define CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */ #define CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing is possible */ - -/* The following commands are related to read operations, they must be - * listed in the same order than the corresponding write ones, since we - * will use (CMD_READ_BUFFER - CMD_WRITE_BUFFER) as a special offset - * in goldfish_pipe_read_write() below. - */ #define CMD_READ_BUFFER 6 /* receive a user buffer from the emulator */ #define CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading * is possible */ @@ -272,8 +266,6 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, unsigned long irq_flags; struct goldfish_pipe *pipe = filp->private_data; struct goldfish_pipe_dev *dev = pipe->dev; - const int cmd_offset = is_write ? 0 - : (CMD_READ_BUFFER - CMD_WRITE_BUFFER); unsigned long address, address_end; int ret = 0; @@ -325,7 +317,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); - if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, + if (access_with_param(dev, + is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, address, avail, pipe, &status)) { gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, dev->base + PIPE_REG_CHANNEL_HIGH); @@ -333,7 +326,7 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, gf_write_ptr((void *)address, dev->base + PIPE_REG_ADDRESS, dev->base + PIPE_REG_ADDRESS_HIGH); - writel(CMD_WRITE_BUFFER + cmd_offset, + writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, dev->base + PIPE_REG_COMMAND); status = readl(dev->base + PIPE_REG_STATUS); } @@ -370,7 +363,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, set_bit(wakeBit, &pipe->flags); /* Tell the emulator we're going to wait for a wake event */ - goldfish_cmd(pipe, CMD_WAKE_ON_WRITE + cmd_offset); + goldfish_cmd(pipe, + is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ); /* Unlock the pipe, then wait for the wake signal */ mutex_unlock(&pipe->lock); -- cgit From 2f3be88237a301ab83b8ba4a0fdf0381bbb3f6ac Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Wed, 6 Jan 2016 14:05:15 +0000 Subject: goldfish_pipe: Pin pages to memory while copying and other cleanups The existing code had a troubling TODO statement concerning the fact that it just did a check if the page that the QEMU backend was going to read from / write to was there before the call to the QEMU backend and then relying on the fact that the page stayed around, even in a preemptible SMP kernel. Obviously the page could go away or be reassigned, and strange things may happen. Further, writes were not tracked, so any use of COW or KSM-like features would break completely. Probably that was never used by adbd (the only current active user of the pipe), but could prove much more dangerous for the GPU passthrough mechanism. Instead, use get_user_pages() as the comment suggested and cleanup the error path and add the set_page_dirt() call on a successful read operation. Also clarify the count used to return from successful read/write calls and use Linux style commentary in various places of the file. Note: The "just ignore error and return whatever we read so far" error handling is really quite horrific. I cannot change it without a more careful study of all user space ABIs reliance on this 'feature'. Signed-off-by: Christoffer Dall Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 129 +++++++++++++++++------------- 1 file changed, 72 insertions(+), 57 deletions(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 0fb3a34f5991..20a933726ac1 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -2,6 +2,7 @@ * Copyright (C) 2011 Google, Inc. * Copyright (C) 2012 Intel, Inc. * Copyright (C) 2013 Intel, Inc. + * Copyright (C) 2014 Linaro Limited * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -57,6 +58,7 @@ #include #include #include +#include /* * IMPORTANT: The following constants must match the ones used and defined @@ -257,17 +259,14 @@ static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, return 0; } -/* This function is used for both reading from and writing to a given - * pipe. - */ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, - size_t bufflen, int is_write) + size_t bufflen, int is_write) { unsigned long irq_flags; struct goldfish_pipe *pipe = filp->private_data; struct goldfish_pipe_dev *dev = pipe->dev; unsigned long address, address_end; - int ret = 0; + int count = 0, ret = -EINVAL; /* If the emulator already closed the pipe, no need to go further */ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) @@ -290,30 +289,23 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, address_end = address + bufflen; while (address < address_end) { - unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; - unsigned long next = page_end < address_end ? page_end - : address_end; - unsigned long avail = next - address; + unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; + unsigned long next = page_end < address_end ? page_end + : address_end; + unsigned long avail = next - address; int status, wakeBit; - - /* Ensure that the corresponding page is properly mapped */ - /* FIXME: this isn't safe or sufficient - use get_user_pages */ - if (is_write) { - char c; - /* Ensure that the page is mapped and readable */ - if (__get_user(c, (char __user *)address)) { - if (!ret) - ret = -EFAULT; - break; - } - } else { - /* Ensure that the page is mapped and writable */ - if (__put_user(0, (char __user *)address)) { - if (!ret) - ret = -EFAULT; - break; - } - } + struct page *page; + + /* + * We grab the pages on a page-by-page basis in case user + * space gives us a potentially huge buffer but the read only + * returns a small amount, then there's no need to pin that + * much memory to the process. + */ + ret = get_user_pages(current, current->mm, address, 1, + !is_write, 0, &page, NULL); + if (ret < 0) + return ret; /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); @@ -332,33 +324,48 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, } spin_unlock_irqrestore(&dev->lock, irq_flags); + if (status > 0 && !is_write) + set_page_dirty(page); + put_page(page); + if (status > 0) { /* Correct transfer */ - ret += status; + count += status; address += status; continue; - } - - if (status == 0) /* EOF */ + } else if (status == 0) { /* EOF */ + ret = 0; break; - - /* An error occured. If we already transfered stuff, just - * return with its count. We expect the next call to return - * an error code */ - if (ret > 0) + } else if (status < 0 && count > 0) { + /* + * An error occurred and we already transferred + * something on one of the previous pages. + * Just return what we already copied and log this + * err. + * + * Note: This seems like an incorrect approach but + * cannot change it until we check if any user space + * ABI relies on this behavior. + */ + pr_info_ratelimited("android_pipe: backend returned error %d on %s\n", + status, is_write ? "write" : "read"); + ret = 0; break; + } - /* If the error is not PIPE_ERROR_AGAIN, or if we are not in - * non-blocking mode, just return the error code. - */ + /* + * If the error is not PIPE_ERROR_AGAIN, or if we are not in + * non-blocking mode, just return the error code. + */ if (status != PIPE_ERROR_AGAIN || (filp->f_flags & O_NONBLOCK) != 0) { ret = goldfish_pipe_error_convert(status); break; } - /* We will have to wait until more data/space is available. - * First, mark the pipe as waiting for a specific wake signal. - */ + /* + * The backend blocked the read/write, wait until the backend + * tells us it's ready to process more data. + */ wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; set_bit(wakeBit, &pipe->flags); @@ -372,22 +379,29 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, while (test_bit(wakeBit, &pipe->flags)) { if (wait_event_interruptible( pipe->wake_queue, - !test_bit(wakeBit, &pipe->flags))) - return -ERESTARTSYS; + !test_bit(wakeBit, &pipe->flags))) { + ret = -ERESTARTSYS; + break; + } - if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) - return -EIO; + if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) { + ret = -EIO; + break; + } } /* Try to re-acquire the lock */ - if (mutex_lock_interruptible(&pipe->lock)) - return -ERESTARTSYS; - - /* Try the transfer again */ - continue; + if (mutex_lock_interruptible(&pipe->lock)) { + ret = -ERESTARTSYS; + break; + } } mutex_unlock(&pipe->lock); - return ret; + + if (ret < 0) + return ret; + else + return count; } static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, @@ -440,10 +454,11 @@ static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) unsigned long irq_flags; int count = 0; - /* We're going to read from the emulator a list of (channel,flags) - * pairs corresponding to the wake events that occured on each - * blocked pipe (i.e. channel). - */ + /* + * We're going to read from the emulator a list of (channel,flags) + * pairs corresponding to the wake events that occurred on each + * blocked pipe (i.e. channel). + */ spin_lock_irqsave(&dev->lock, irq_flags); for (;;) { /* First read the channel, 0 means the end of the list */ -- cgit From 91a18a414185a2b937e2cc8bf0cc32de1863d11a Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 6 Jan 2016 14:05:36 +0000 Subject: platform: goldfish: pipe: add devicetree bindings Add bindings so we don't need to rely on goldfish virtual bus for probing any more, which means we don't need ARM and MIPS goldfish board code for instantiating the bus. In the long term we would like to move towards replacing the Android pipe with virtio-vsock that is currently under development. Signed-off-by: Greg Hackmann Signed-off-by: Jin Qian Acked-by: Rob Herring Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/goldfish/pipe.txt | 17 +++++++++++++++++ drivers/platform/goldfish/goldfish_pipe.c | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/goldfish/pipe.txt diff --git a/Documentation/devicetree/bindings/goldfish/pipe.txt b/Documentation/devicetree/bindings/goldfish/pipe.txt new file mode 100644 index 000000000000..e417a31a1ee3 --- /dev/null +++ b/Documentation/devicetree/bindings/goldfish/pipe.txt @@ -0,0 +1,17 @@ +Android Goldfish QEMU Pipe + +Andorid pipe virtual device generated by android emulator. + +Required properties: + +- compatible : should contain "google,android-pipe" to match emulator +- reg : +- interrupts : + +Example: + + android_pipe@a010000 { + compatible = "google,android-pipe"; + reg = ; + interrupts = <0x12>; + }; diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 20a933726ac1..0b187ff7a35b 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -624,11 +624,19 @@ static int goldfish_pipe_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id goldfish_pipe_of_match[] = { + { .compatible = "google,android-pipe", }, + {}, +}; +MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); + static struct platform_driver goldfish_pipe = { .probe = goldfish_pipe_probe, .remove = goldfish_pipe_remove, .driver = { - .name = "goldfish_pipe" + .name = "goldfish_pipe", + .owner = THIS_MODULE, + .of_match_table = goldfish_pipe_of_match, } }; -- cgit From 25dd0f407307c54de5025250ca1dfbd4bdbb2fba Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 6 Jan 2016 14:05:55 +0000 Subject: platform: goldfish: pipe: don't log when dropping PIPE_ERROR_AGAIN On PIPE_ERROR_AGAIN, just stopping in the middle of a transfer and returning the number of bytes actually handled is the right behavior. Other errors should be returned on the next read() or write() call. Continue logging those until we confirm nothing actually relies on the existing (wrong) behavior of dropping errors on the floor. Signed-off-by: Greg Hackmann Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 0b187ff7a35b..7a56be9c9432 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -346,7 +346,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, * cannot change it until we check if any user space * ABI relies on this behavior. */ - pr_info_ratelimited("android_pipe: backend returned error %d on %s\n", + if (status != PIPE_ERROR_AGAIN) + pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n", status, is_write ? "write" : "read"); ret = 0; break; -- cgit From 2e5fc89ac5a0b1460316f19b21c38284949daf38 Mon Sep 17 00:00:00 2001 From: Miodrag Dinic Date: Wed, 6 Jan 2016 14:06:08 +0000 Subject: Enable platform support for Goldfish virtual devices Enable CONFIG_GOLDFISH for MIPS platforms. Signed-off-by: Miodrag Dinic Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/goldfish/Kconfig b/drivers/platform/goldfish/Kconfig index 2be762743592..50331e3e54f3 100644 --- a/drivers/platform/goldfish/Kconfig +++ b/drivers/platform/goldfish/Kconfig @@ -1,6 +1,6 @@ menuconfig GOLDFISH bool "Platform support for Goldfish virtual devices" - depends on X86_32 || X86_64 || ARM || ARM64 + depends on X86_32 || X86_64 || ARM || ARM64 || MIPS ---help--- Say Y here to get to see options for the Goldfish virtual platform. This option alone does not add any kernel code. -- cgit From 4f42071c943977e91e7fda8230e4f85bc3ba117a Mon Sep 17 00:00:00 2001 From: Yu Ning Date: Wed, 6 Jan 2016 14:06:40 +0000 Subject: goldfish_pipe: Pass physical addresses to the device if supported For reading and writing guest user space buffers, currently the kernel sends the guest virtual address of the buffer to the pipe device. This virtual address has to be first converted to a guest physical address. Doing this translation on the QEMU side is inefficient and requires additional handling when KVM is enabled, whose implementation would either incur intrusive changes to QEMU's KVM support code or suffer from poor performance, see commit 08c7228c50f8 ("x86-kvm: only sync SREGS when doing address translation") of $AOSP/external/qemu for details, and thus should be avoided if possible. There is a TODO comment in hw/misc/android_pipe.c in the new Android emulator source tree ($AOSP/external/qemu-android) which requests that the translation be done on the kernel side and that physical addresses be passed to the device instead of virtual ones. Once the QEMU-side implementation is done, the kernel will need to support both the new paddr-based pipe device and the old vaddr-based one (which will continue to be used by the classic emulator). This patch achieves that by leveraging the device version register available in the new device. See https://android-review.googlesource.com/128280 for the QEMU-side patch. In addition, use the mmap semaphore (in read mode) to safeguard the call to get_user_pages(). Signed-off-by: Yu Ning Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 7a56be9c9432..c214434e8811 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -77,6 +77,7 @@ #define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ #define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ #define PIPE_REG_ACCESS_PARAMS 0x20 /* write: batch access */ +#define PIPE_REG_VERSION 0x24 /* read: device version */ /* list of commands for PIPE_REG_COMMAND */ #define CMD_OPEN 1 /* open new channel */ @@ -126,6 +127,7 @@ struct goldfish_pipe_dev { unsigned char __iomem *base; struct access_params *aps; int irq; + u32 version; }; static struct goldfish_pipe_dev pipe_dev[1]; @@ -296,26 +298,43 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, int status, wakeBit; struct page *page; + /* Either vaddr or paddr depending on the device version */ + unsigned long xaddr; + /* * We grab the pages on a page-by-page basis in case user * space gives us a potentially huge buffer but the read only * returns a small amount, then there's no need to pin that * much memory to the process. */ + down_read(¤t->mm->mmap_sem); ret = get_user_pages(current, current->mm, address, 1, !is_write, 0, &page, NULL); + up_read(¤t->mm->mmap_sem); if (ret < 0) return ret; + if (dev->version) { + /* Device version 1 or newer (qemu-android) expects the + * physical address. + */ + xaddr = page_to_phys(page) | (address & ~PAGE_MASK); + } else { + /* Device version 0 (classic emulator) expects the + * virtual address. + */ + xaddr = address; + } + /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); if (access_with_param(dev, is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, - address, avail, pipe, &status)) { + xaddr, avail, pipe, &status)) { gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, dev->base + PIPE_REG_CHANNEL_HIGH); writel(avail, dev->base + PIPE_REG_SIZE); - gf_write_ptr((void *)address, + gf_write_ptr((void *)xaddr, dev->base + PIPE_REG_ADDRESS, dev->base + PIPE_REG_ADDRESS_HIGH); writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, @@ -610,6 +629,12 @@ static int goldfish_pipe_probe(struct platform_device *pdev) goto error; } setup_access_params_addr(pdev, dev); + + /* Although the pipe device in the classic Android emulator does not + * recognize the 'version' register, it won't treat this as an error + * either and will simply return 0, which is fine. + */ + dev->version = readl(dev->base + PIPE_REG_VERSION); return 0; error: -- cgit From d62f324b0ac80c3923ebbf897735c7c24ba887b8 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Wed, 6 Jan 2016 14:06:55 +0000 Subject: goldfish: Enable ACPI-based enumeration for android pipe Add ACPI binding to the android pipe driver Signed-off-by: Jason Hu Signed-off-by: Jin Qian Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index c214434e8811..e3fab9a1d9f7 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -59,6 +59,7 @@ #include #include #include +#include /* * IMPORTANT: The following constants must match the ones used and defined @@ -650,6 +651,12 @@ static int goldfish_pipe_remove(struct platform_device *pdev) return 0; } +static const struct acpi_device_id goldfish_pipe_acpi_match[] = { + { "GFSH0003", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); + static const struct of_device_id goldfish_pipe_of_match[] = { { .compatible = "google,android-pipe", }, {}, @@ -663,6 +670,7 @@ static struct platform_driver goldfish_pipe = { .name = "goldfish_pipe", .owner = THIS_MODULE, .of_match_table = goldfish_pipe_of_match, + .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), } }; -- cgit From 3e2fbc7feec4426feba609b94aa89a147e02c67e Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Thu, 21 Jan 2016 02:38:53 +0530 Subject: Staging: goldfish: goldfish_nand: Add DMA Support using dmam_alloc_coherent Function nand_setup_cmd_params has 2 goals- -Initialize the cmd_params field so that it can be used to send and read commands from the device. -Get a bus address for the allocated memory to transfer to the device. Replace the combination of devm_kzalloc and _pa() with dmam_alloc_coherent. Coherent mapping guarantees that the device and CPU are in sync. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_nand.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/staging/goldfish/goldfish_nand.c b/drivers/staging/goldfish/goldfish_nand.c index 623353db5a08..f223b3a5a428 100644 --- a/drivers/staging/goldfish/goldfish_nand.c +++ b/drivers/staging/goldfish/goldfish_nand.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "goldfish_nand_reg.h" @@ -284,17 +285,18 @@ invalid_arg: static int nand_setup_cmd_params(struct platform_device *pdev, struct goldfish_nand *nand) { - u64 paddr; + dma_addr_t dma_handle; unsigned char __iomem *base = nand->base; - nand->cmd_params = devm_kzalloc(&pdev->dev, - sizeof(struct cmd_params), GFP_KERNEL); - if (!nand->cmd_params) - return -1; - - paddr = __pa(nand->cmd_params); - writel((u32)(paddr >> 32), base + NAND_CMD_PARAMS_ADDR_HIGH); - writel((u32)paddr, base + NAND_CMD_PARAMS_ADDR_LOW); + nand->cmd_params = dmam_alloc_coherent(&pdev->dev, + sizeof(struct cmd_params), + &dma_handle, GFP_KERNEL); + if (!nand->cmd_params) { + dev_err(&pdev->dev, "allocate buffer failed\n"); + return -ENOMEM; + } + writel((u32)((u64)dma_handle >> 32), base + NAND_CMD_PARAMS_ADDR_HIGH); + writel((u32)dma_handle, base + NAND_CMD_PARAMS_ADDR_LOW); return 0; } -- cgit From bd922477d9350a3006d73dabb241400e6c4181b0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 28 Jan 2016 19:02:29 +0200 Subject: locking/x86: Add cc clobber for ADDL ADDL clobbers flags (such as CF) but barrier.h didn't tell this to GCC. Historically, GCC doesn't need one on x86, and always considers flags clobbered. We are probably missing the cc clobber in a *lot* of places for this reason. But even if not necessary, it's probably a good thing to add for documentation, and in case GCC semantcs ever change. Reported-by: Borislav Petkov Signed-off-by: Michael S. Tsirkin Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Andrey Konovalov Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Davidlohr Bueso Cc: Davidlohr Bueso Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: virtualization Link: http://lkml.kernel.org/r/1453921746-16178-2-git-send-email-mst@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/barrier.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index a584e1c50918..a65bdb10246a 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -15,9 +15,12 @@ * Some non-Intel clones support out of order store. wmb() ceases to be a * nop for these. */ -#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) -#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) -#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) +#define mb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "mfence", \ + X86_FEATURE_XMM2) ::: "memory", "cc") +#define rmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "lfence", \ + X86_FEATURE_XMM2) ::: "memory", "cc") +#define wmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "sfence", \ + X86_FEATURE_XMM2) ::: "memory", "cc") #else #define mb() asm volatile("mfence":::"memory") #define rmb() asm volatile("lfence":::"memory") -- cgit From e37cee133c72c9529f74a20d9b7eb3b6dfb928b5 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 28 Jan 2016 19:02:37 +0200 Subject: locking/x86: Drop a comment left over from X86_OOSTORE The comment about wmb being non-NOP to deal with non-Intel CPUs is a left over from before the following commit: 09df7c4c8097 ("x86: Remove CONFIG_X86_OOSTORE") It makes no sense now: in particular, wmb() is not a NOP even for regular Intel CPUs because of weird use-cases e.g. dealing with WC memory. Drop this comment. Signed-off-by: Michael S. Tsirkin Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Andrey Konovalov Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Davidlohr Bueso Cc: Davidlohr Bueso Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: virtualization Link: http://lkml.kernel.org/r/1453921746-16178-3-git-send-email-mst@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/barrier.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index a65bdb10246a..a29174599a98 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -11,10 +11,6 @@ */ #ifdef CONFIG_X86_32 -/* - * Some non-Intel clones support out of order store. wmb() ceases to be a - * nop for these. - */ #define mb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "mfence", \ X86_FEATURE_XMM2) ::: "memory", "cc") #define rmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "lfence", \ -- cgit From 57d9b1b43433a6ba7267c80b87d8e8f6e86edceb Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 28 Jan 2016 19:02:44 +0200 Subject: locking/x86: Tweak the comment about use of wmb() for IO On x86, we *do* still use the non-NOP rmb()/wmb() for IO barriers, but even that is generally questionable. Leave them around as historial unless somebody can point to a case where they care about the performance, but tweak the comment so people don't think they are strictly required in all cases. Signed-off-by: Michael S. Tsirkin Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Andrey Konovalov Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Borislav Petkov Cc: Brian Gerst Cc: Davidlohr Bueso Cc: Davidlohr Bueso Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: virtualization Link: http://lkml.kernel.org/r/1453921746-16178-4-git-send-email-mst@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index a29174599a98..bfb28caf97b1 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -6,7 +6,7 @@ /* * Force strict CPU ordering. - * And yes, this is required on UP too when we're talking + * And yes, this might be required on UP too when we're talking * to devices. */ -- cgit From ca59809ff6d572ae58fc6bedf7500f5a60fdbd64 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 28 Jan 2016 19:02:51 +0200 Subject: locking/x86: Use mb() around clflush() The following commit: f8e617f4582995f ("sched/idle/x86: Optimize unnecessary mwait_idle() resched IPIs") adds memory barriers around clflush(), but this seems wrong for UP since barrier() has no effect on clflush(). We really want MFENCE, so switch to mb() instead. Signed-off-by: Michael S. Tsirkin Acked-by: Peter Zijlstra (Intel) Cc: Andrew Morton Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Davidlohr Bueso Cc: Davidlohr Bueso Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Len Brown Cc: Linus Torvalds Cc: Mike Galbraith Cc: Oleg Nesterov Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: virtualization Link: http://lkml.kernel.org/r/1453921746-16178-5-git-send-email-mst@redhat.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 9f7c21c22477..9decee2bfdbe 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -418,9 +418,9 @@ static void mwait_idle(void) if (!current_set_polling_and_test()) { trace_cpu_idle_rcuidle(1, smp_processor_id()); if (this_cpu_has(X86_BUG_CLFLUSH_MONITOR)) { - smp_mb(); /* quirk */ + mb(); /* quirk */ clflush((void *)¤t_thread_info()->flags); - smp_mb(); /* quirk */ + mb(); /* quirk */ } __monitor((void *)¤t_thread_info()->flags, 0, 0); -- cgit From c31b34255b48d1a169693c9c70c49ad6418cfd20 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:19 -0800 Subject: selftests/x86: Extend Makefile to allow 64-bit-only tests Previously the Makefile supported 32-bit-only tests and tests that were 32-bit and 64-bit. This adds the support for tests that are only built as 64-bit binaries. There aren't any yet, but there might be a few some day. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-api@vger.kernel.org Link: http://lkml.kernel.org/r/99789bfe65706e6df32cc7e13f656e8c9fa92031.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- tools/testing/selftests/x86/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index d0c473f65850..9c81f263a396 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -11,8 +11,9 @@ TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall vdso_restorer TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) +TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY) BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) -BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64) +BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64) CFLAGS := -O2 -g -std=gnu99 -pthread -Wall @@ -40,7 +41,7 @@ clean: $(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm -$(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c +$(TARGETS_C_64BIT_ALL:%=%_64): %_64: %.c $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl # x86_64 users should be encouraged to install 32-bit libraries -- cgit From e21d50f3864e2a8995f5d2a41dea3f0fa07758b4 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:20 -0800 Subject: selftests/x86: Add check_initial_reg_state() This checks that ELF binaries are started with an appropriately blank register state. ( There's currently a nasty special case in the entry asm to arrange for this. I'm planning on removing the special case, and this will help make sure I don't break it. ) Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/ef54f8d066b30a3eb36bbf26300eebb242185700.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- tools/testing/selftests/x86/Makefile | 9 +- .../selftests/x86/check_initial_reg_state.c | 109 +++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/x86/check_initial_reg_state.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 9c81f263a396..df4f767f48da 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -4,7 +4,8 @@ include ../lib.mk .PHONY: all all_32 all_64 warn_32bit_failure clean -TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall +TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall \ + check_initial_reg_state TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ ldt_gdt \ @@ -66,3 +67,9 @@ endif sysret_ss_attrs_64: thunks.S ptrace_syscall_32: raw_syscall_helper_32.S test_syscall_vdso_32: thunks_32.S + +# check_initial_reg_state is special: it needs a custom entry, and it +# needs to be static so that its interpreter doesn't destroy its initial +# state. +check_initial_reg_state_32: CFLAGS += -Wl,-ereal_start -static +check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static diff --git a/tools/testing/selftests/x86/check_initial_reg_state.c b/tools/testing/selftests/x86/check_initial_reg_state.c new file mode 100644 index 000000000000..6aaed9b85baf --- /dev/null +++ b/tools/testing/selftests/x86/check_initial_reg_state.c @@ -0,0 +1,109 @@ +/* + * check_initial_reg_state.c - check that execve sets the correct state + * Copyright (c) 2014-2016 Andrew Lutomirski + * + * 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. + */ + +#define _GNU_SOURCE + +#include + +unsigned long ax, bx, cx, dx, si, di, bp, sp, flags; +unsigned long r8, r9, r10, r11, r12, r13, r14, r15; + +asm ( + ".pushsection .text\n\t" + ".type real_start, @function\n\t" + ".global real_start\n\t" + "real_start:\n\t" +#ifdef __x86_64__ + "mov %rax, ax\n\t" + "mov %rbx, bx\n\t" + "mov %rcx, cx\n\t" + "mov %rdx, dx\n\t" + "mov %rsi, si\n\t" + "mov %rdi, di\n\t" + "mov %rbp, bp\n\t" + "mov %rsp, sp\n\t" + "mov %r8, r8\n\t" + "mov %r9, r9\n\t" + "mov %r10, r10\n\t" + "mov %r11, r11\n\t" + "mov %r12, r12\n\t" + "mov %r13, r13\n\t" + "mov %r14, r14\n\t" + "mov %r15, r15\n\t" + "pushfq\n\t" + "popq flags\n\t" +#else + "mov %eax, ax\n\t" + "mov %ebx, bx\n\t" + "mov %ecx, cx\n\t" + "mov %edx, dx\n\t" + "mov %esi, si\n\t" + "mov %edi, di\n\t" + "mov %ebp, bp\n\t" + "mov %esp, sp\n\t" + "pushfl\n\t" + "popl flags\n\t" +#endif + "jmp _start\n\t" + ".size real_start, . - real_start\n\t" + ".popsection"); + +int main() +{ + int nerrs = 0; + + if (sp == 0) { + printf("[FAIL]\tTest was built incorrectly\n"); + return 1; + } + + if (ax || bx || cx || dx || si || di || bp +#ifdef __x86_64__ + || r8 || r9 || r10 || r11 || r12 || r13 || r14 || r15 +#endif + ) { + printf("[FAIL]\tAll GPRs except SP should be 0\n"); +#define SHOW(x) printf("\t" #x " = 0x%lx\n", x); + SHOW(ax); + SHOW(bx); + SHOW(cx); + SHOW(dx); + SHOW(si); + SHOW(di); + SHOW(bp); + SHOW(sp); +#ifdef __x86_64__ + SHOW(r8); + SHOW(r9); + SHOW(r10); + SHOW(r11); + SHOW(r12); + SHOW(r13); + SHOW(r14); + SHOW(r15); +#endif + nerrs++; + } else { + printf("[OK]\tAll GPRs except SP are 0\n"); + } + + if (flags != 0x202) { + printf("[FAIL]\tFLAGS is 0x%lx, but it should be 0x202\n", flags); + nerrs++; + } else { + printf("[OK]\tFLAGS is 0x202\n"); + } + + return nerrs ? 1 : 0; +} -- cgit From fba324744bfd2a7948a7710d7a021d76dafb9b67 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:21 -0800 Subject: x86/syscalls: Refactor syscalltbl.sh This splits out the code to emit a syscall line. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1bfcbba991f5cfaa9291ff950a593daa972a205f.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/syscalls/syscalltbl.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index 0e7f8ec071e7..167965ee742e 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -3,13 +3,21 @@ in="$1" out="$2" +emit() { + abi="$1" + nr="$2" + entry="$3" + compat="$4" + if [ -n "$compat" ]; then + echo "__SYSCALL_${abi}($nr, $entry, $compat)" + elif [ -n "$entry" ]; then + echo "__SYSCALL_${abi}($nr, $entry, $entry)" + fi +} + grep '^[0-9]' "$in" | sort -n | ( while read nr abi name entry compat; do abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` - if [ -n "$compat" ]; then - echo "__SYSCALL_${abi}($nr, $entry, $compat)" - elif [ -n "$entry" ]; then - echo "__SYSCALL_${abi}($nr, $entry, $entry)" - fi + emit "$abi" "$nr" "$entry" "$compat" done ) > "$out" -- cgit From 32324ce15ea8cb4c8acc28acb2fd36fabf73e9db Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:22 -0800 Subject: x86/syscalls: Remove __SYSCALL_COMMON and __SYSCALL_X32 The common/64/x32 distinction has no effect other than determining which kernels actually support the syscall. Move the logic into syscalltbl.sh. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/58d4a95f40e43b894f93288b4a3633963d0ee22e.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/syscall_64.c | 8 -------- arch/x86/entry/syscalls/syscalltbl.sh | 17 ++++++++++++++++- arch/x86/kernel/asm-offsets_64.c | 6 ------ arch/x86/um/sys_call_table_64.c | 3 --- arch/x86/um/user-offsets.c | 2 -- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index 41283d22be7a..974fd89ac806 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -6,14 +6,6 @@ #include #include -#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) - -#ifdef CONFIG_X86_X32_ABI -# define __SYSCALL_X32(nr, sym, compat) __SYSCALL_64(nr, sym, compat) -#else -# define __SYSCALL_X32(nr, sym, compat) /* nothing */ -#endif - #define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_64 diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index 167965ee742e..5ebeaf1041e7 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -18,6 +18,21 @@ emit() { grep '^[0-9]' "$in" | sort -n | ( while read nr abi name entry compat; do abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` - emit "$abi" "$nr" "$entry" "$compat" + if [ "$abi" == "COMMON" -o "$abi" == "64" ]; then + # COMMON is the same as 64, except that we don't expect X32 + # programs to use it. Our expectation has nothing to do with + # any generated code, so treat them the same. + emit 64 "$nr" "$entry" "$compat" + elif [ "$abi" == "X32" ]; then + # X32 is equivalent to 64 on an X32-compatible kernel. + echo "#ifdef CONFIG_X86_X32_ABI" + emit 64 "$nr" "$entry" "$compat" + echo "#endif" + elif [ "$abi" == "I386" ]; then + emit "$abi" "$nr" "$entry" "$compat" + else + echo "Unknown abi $abi" >&2 + exit 1 + fi done ) > "$out" diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index f2edafb5f24e..29db3b3f550c 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -5,12 +5,6 @@ #include #define __SYSCALL_64(nr, sym, compat) [nr] = 1, -#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1, -#ifdef CONFIG_X86_X32_ABI -# define __SYSCALL_X32(nr, sym, compat) [nr] = 1, -#else -# define __SYSCALL_X32(nr, sym, compat) /* nothing */ -#endif static char syscalls_64[] = { #include }; diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c index b74ea6c2c0e7..71a497cde921 100644 --- a/arch/x86/um/sys_call_table_64.c +++ b/arch/x86/um/sys_call_table_64.c @@ -35,9 +35,6 @@ #define stub_execveat sys_execveat #define stub_rt_sigreturn sys_rt_sigreturn -#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) -#define __SYSCALL_X32(nr, sym, compat) /* Not supported */ - #define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index ce7e3607a870..5edf4f4bbf53 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -15,8 +15,6 @@ static char syscalls[] = { }; #else #define __SYSCALL_64(nr, sym, compat) [nr] = 1, -#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1, -#define __SYSCALL_X32(nr, sym, compat) /* Not supported */ static char syscalls[] = { #include }; -- cgit From 3e65654e3db6df6aba9c5b895f8b8e6a8d8eb508 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:23 -0800 Subject: x86/syscalls: Move compat syscall entry handling into syscalltbl.sh Rather than duplicating the compat entry handling in all consumers of syscalls_BITS.h, handle it directly in syscalltbl.sh. Now we generate entries in syscalls_32.h like: __SYSCALL_I386(5, sys_open) __SYSCALL_I386(5, compat_sys_open) and all of its consumers implicitly get the right entry point. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/b7c2b501dc0e6e43050e916b95807c3e2e16e9bb.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/syscall_32.c | 10 ++-------- arch/x86/entry/syscall_64.c | 4 ++-- arch/x86/entry/syscalls/syscalltbl.sh | 22 ++++++++++++++++++---- arch/x86/kernel/asm-offsets_32.c | 2 +- arch/x86/kernel/asm-offsets_64.c | 4 ++-- arch/x86/um/sys_call_table_32.c | 4 ++-- arch/x86/um/sys_call_table_64.c | 4 ++-- arch/x86/um/user-offsets.c | 4 ++-- 8 files changed, 31 insertions(+), 23 deletions(-) diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c index 9a6649857106..3e2829759da2 100644 --- a/arch/x86/entry/syscall_32.c +++ b/arch/x86/entry/syscall_32.c @@ -6,17 +6,11 @@ #include #include -#ifdef CONFIG_IA32_EMULATION -#define SYM(sym, compat) compat -#else -#define SYM(sym, compat) sym -#endif - -#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long SYM(sym, compat)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_I386(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_I386 -#define __SYSCALL_I386(nr, sym, compat) [nr] = SYM(sym, compat), +#define __SYSCALL_I386(nr, sym) [nr] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index 974fd89ac806..3781989b180e 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -6,11 +6,11 @@ #include #include -#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym, compat) [nr] = sym, +#define __SYSCALL_64(nr, sym) [nr] = sym, extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index 5ebeaf1041e7..b81479c8c5fb 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -8,10 +8,24 @@ emit() { nr="$2" entry="$3" compat="$4" - if [ -n "$compat" ]; then - echo "__SYSCALL_${abi}($nr, $entry, $compat)" - elif [ -n "$entry" ]; then - echo "__SYSCALL_${abi}($nr, $entry, $entry)" + + if [ "$abi" == "64" -a -n "$compat" ]; then + echo "a compat entry for a 64-bit syscall makes no sense" >&2 + exit 1 + fi + + if [ -z "$compat" ]; then + if [ -n "$entry" ]; then + echo "__SYSCALL_${abi}($nr, $entry)" + fi + else + echo "#ifdef CONFIG_X86_32" + if [ -n "$entry" ]; then + echo "__SYSCALL_${abi}($nr, $entry)" + fi + echo "#else" + echo "__SYSCALL_${abi}($nr, $compat)" + echo "#endif" fi } diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 6ce39025f467..abec4c9f1c97 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -7,7 +7,7 @@ #include #include "../../../drivers/lguest/lg.h" -#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +#define __SYSCALL_I386(nr, sym) [nr] = 1, static char syscalls[] = { #include }; diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 29db3b3f550c..9677bf9a616f 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -4,11 +4,11 @@ #include -#define __SYSCALL_64(nr, sym, compat) [nr] = 1, +#define __SYSCALL_64(nr, sym) [nr] = 1, static char syscalls_64[] = { #include }; -#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +#define __SYSCALL_I386(nr, sym) [nr] = 1, static char syscalls_ia32[] = { #include }; diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 439c0994b696..d4669a679fd0 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c @@ -25,11 +25,11 @@ #define old_mmap sys_old_mmap -#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_I386(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_I386 -#define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym, +#define __SYSCALL_I386(nr, sym) [ nr ] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c index 71a497cde921..6ee5268beb05 100644 --- a/arch/x86/um/sys_call_table_64.c +++ b/arch/x86/um/sys_call_table_64.c @@ -35,11 +35,11 @@ #define stub_execveat sys_execveat #define stub_rt_sigreturn sys_rt_sigreturn -#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym, compat) [ nr ] = sym, +#define __SYSCALL_64(nr, sym) [ nr ] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index 5edf4f4bbf53..6c9a9c1eae32 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -9,12 +9,12 @@ #include #ifdef __i386__ -#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +#define __SYSCALL_I386(nr, sym) [nr] = 1, static char syscalls[] = { #include }; #else -#define __SYSCALL_64(nr, sym, compat) [nr] = 1, +#define __SYSCALL_64(nr, sym) [nr] = 1, static char syscalls[] = { #include }; -- cgit From cfcbadb49dabb05efa23e1a0f95f3391c0a815bc Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:24 -0800 Subject: x86/syscalls: Add syscall entry qualifiers This will let us specify something like 'sys_xyz/foo' instead of 'sys_xyz' in the syscall table, where the 'foo' qualifier conveys some extra information to the C code. The intent is to allow things like sys_execve/ptregs to indicate that sys_execve() touches pt_regs. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/2de06e33dce62556b3ec662006fcb295504e296e.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/syscall_32.c | 4 ++-- arch/x86/entry/syscall_64.c | 4 ++-- arch/x86/entry/syscalls/syscalltbl.sh | 19 ++++++++++++++++--- arch/x86/kernel/asm-offsets_32.c | 2 +- arch/x86/kernel/asm-offsets_64.c | 4 ++-- arch/x86/um/sys_call_table_32.c | 4 ++-- arch/x86/um/sys_call_table_64.c | 4 ++-- arch/x86/um/user-offsets.c | 4 ++-- 8 files changed, 29 insertions(+), 16 deletions(-) diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c index 3e2829759da2..8f895ee13a1c 100644 --- a/arch/x86/entry/syscall_32.c +++ b/arch/x86/entry/syscall_32.c @@ -6,11 +6,11 @@ #include #include -#define __SYSCALL_I386(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_I386 -#define __SYSCALL_I386(nr, sym) [nr] = sym, +#define __SYSCALL_I386(nr, sym, qual) [nr] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index 3781989b180e..a1d408772ae6 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -6,11 +6,11 @@ #include #include -#define __SYSCALL_64(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym) [nr] = sym, +#define __SYSCALL_64(nr, sym, qual) [nr] = sym, extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index b81479c8c5fb..cd3d3015d7df 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -3,6 +3,19 @@ in="$1" out="$2" +syscall_macro() { + abi="$1" + nr="$2" + entry="$3" + + # Entry can be either just a function name or "function/qualifier" + real_entry="${entry%%/*}" + qualifier="${entry:${#real_entry}}" # Strip the function name + qualifier="${qualifier:1}" # Strip the slash, if any + + echo "__SYSCALL_${abi}($nr, $real_entry, $qualifier)" +} + emit() { abi="$1" nr="$2" @@ -16,15 +29,15 @@ emit() { if [ -z "$compat" ]; then if [ -n "$entry" ]; then - echo "__SYSCALL_${abi}($nr, $entry)" + syscall_macro "$abi" "$nr" "$entry" fi else echo "#ifdef CONFIG_X86_32" if [ -n "$entry" ]; then - echo "__SYSCALL_${abi}($nr, $entry)" + syscall_macro "$abi" "$nr" "$entry" fi echo "#else" - echo "__SYSCALL_${abi}($nr, $compat)" + syscall_macro "$abi" "$nr" "$compat" echo "#endif" fi } diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index abec4c9f1c97..fdeb0ce07c16 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -7,7 +7,7 @@ #include #include "../../../drivers/lguest/lg.h" -#define __SYSCALL_I386(nr, sym) [nr] = 1, +#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls[] = { #include }; diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 9677bf9a616f..d875f97d4e0b 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -4,11 +4,11 @@ #include -#define __SYSCALL_64(nr, sym) [nr] = 1, +#define __SYSCALL_64(nr, sym, qual) [nr] = 1, static char syscalls_64[] = { #include }; -#define __SYSCALL_I386(nr, sym) [nr] = 1, +#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls_ia32[] = { #include }; diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index d4669a679fd0..bfce503dffae 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c @@ -25,11 +25,11 @@ #define old_mmap sys_old_mmap -#define __SYSCALL_I386(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_I386 -#define __SYSCALL_I386(nr, sym) [ nr ] = sym, +#define __SYSCALL_I386(nr, sym, qual) [ nr ] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c index 6ee5268beb05..f306413d3eb6 100644 --- a/arch/x86/um/sys_call_table_64.c +++ b/arch/x86/um/sys_call_table_64.c @@ -35,11 +35,11 @@ #define stub_execveat sys_execveat #define stub_rt_sigreturn sys_rt_sigreturn -#define __SYSCALL_64(nr, sym) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym) [ nr ] = sym, +#define __SYSCALL_64(nr, sym, qual) [ nr ] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index 6c9a9c1eae32..470564bbd08e 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -9,12 +9,12 @@ #include #ifdef __i386__ -#define __SYSCALL_I386(nr, sym) [nr] = 1, +#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls[] = { #include }; #else -#define __SYSCALL_64(nr, sym) [nr] = 1, +#define __SYSCALL_64(nr, sym, qual) [nr] = 1, static char syscalls[] = { #include }; -- cgit From 302f5b260c322696cbeb962a263a4d2d99864aed Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:25 -0800 Subject: x86/entry/64: Always run ptregs-using syscalls on the slow path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 64-bit syscalls currently have an optimization in which they are called with partial pt_regs. A small handful require full pt_regs. In the 32-bit and compat cases, I cleaned this up by forcing full pt_regs for all syscalls. The performance hit doesn't really matter as the affected system calls are fundamentally heavy and this is the 32-bit compat case. I want to clean up the 64-bit case as well, but I don't want to hurt fast path performance. To do that, I want to force the syscalls that use pt_regs onto the slow path. This will enable us to make slow path syscalls be real ABI-compliant C functions. Use the new syscall entry qualification machinery for this. 'stub_clone' is now 'stub_clone/ptregs'. The next patch will eliminate the stubs, and we'll just have 'sys_clone/ptregs'. As of this patch, two-phase entry tracing is no longer used. It has served its purpose (namely a huge speedup on some workloads prior to more general opportunistic SYSRET support), and once the dust settles I'll send patches to back it out. The implementation is heavily based on a patch from Brian Gerst: http://lkml.kernel.org/g/1449666173-15366-1-git-send-email-brgerst@gmail.com Originally-From: Brian Gerst Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: Frédéric Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Linux Kernel Mailing List Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/b9beda88460bcefec6e7d792bd44eca9b760b0c4.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 56 +++++++++++++++++++++++++--------- arch/x86/entry/syscall_64.c | 7 +++-- arch/x86/entry/syscalls/syscall_64.tbl | 16 +++++----- 3 files changed, 55 insertions(+), 24 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 9d34d3cfceb6..f1c8f150728e 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -182,7 +182,15 @@ entry_SYSCALL_64_fastpath: #endif ja 1f /* return -ENOSYS (already in pt_regs->ax) */ movq %r10, %rcx + + /* + * This call instruction is handled specially in stub_ptregs_64. + * It might end up jumping to the slow path. If it jumps, RAX is + * clobbered. + */ call *sys_call_table(, %rax, 8) +.Lentry_SYSCALL_64_after_fastpath_call: + movq %rax, RAX(%rsp) 1: /* @@ -235,25 +243,13 @@ GLOBAL(int_ret_from_sys_call_irqs_off) /* Do syscall entry tracing */ tracesys: - movq %rsp, %rdi - movl $AUDIT_ARCH_X86_64, %esi - call syscall_trace_enter_phase1 - test %rax, %rax - jnz tracesys_phase2 /* if needed, run the slow path */ - RESTORE_C_REGS_EXCEPT_RAX /* else restore clobbered regs */ - movq ORIG_RAX(%rsp), %rax - jmp entry_SYSCALL_64_fastpath /* and return to the fast path */ - -tracesys_phase2: SAVE_EXTRA_REGS movq %rsp, %rdi - movl $AUDIT_ARCH_X86_64, %esi - movq %rax, %rdx - call syscall_trace_enter_phase2 + call syscall_trace_enter /* * Reload registers from stack in case ptrace changed them. - * We don't reload %rax because syscall_trace_entry_phase2() returned + * We don't reload %rax because syscall_trace_enter() returned * the value it wants us to use in the table lookup. */ RESTORE_C_REGS_EXCEPT_RAX @@ -355,6 +351,38 @@ opportunistic_sysret_failed: jmp restore_c_regs_and_iret END(entry_SYSCALL_64) +ENTRY(stub_ptregs_64) + /* + * Syscalls marked as needing ptregs land here. + * If we are on the fast path, we need to save the extra regs. + * If we are on the slow path, the extra regs are already saved. + * + * RAX stores a pointer to the C function implementing the syscall. + */ + cmpq $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp) + jne 1f + + /* Called from fast path -- pop return address and jump to slow path */ + popq %rax + jmp tracesys /* called from fast path */ + +1: + /* Called from C */ + jmp *%rax /* called from C */ +END(stub_ptregs_64) + +.macro ptregs_stub func +ENTRY(ptregs_\func) + leaq \func(%rip), %rax + jmp stub_ptregs_64 +END(ptregs_\func) +.endm + +/* Instantiate ptregs_stub for each ptregs-using syscall */ +#define __SYSCALL_64_QUAL_(sym) +#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_stub sym +#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym) +#include .macro FORK_LIKE func ENTRY(stub_\func) diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index a1d408772ae6..9dbc5abb6162 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -6,11 +6,14 @@ #include #include -#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64_QUAL_(sym) sym +#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_##sym + +#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long __SYSCALL_64_QUAL_##qual(sym)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); #include #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym, qual) [nr] = sym, +#define __SYSCALL_64(nr, sym, qual) [nr] = __SYSCALL_64_QUAL_##qual(sym), extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index dc1040a50bdc..5de342a729d0 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -21,7 +21,7 @@ 12 common brk sys_brk 13 64 rt_sigaction sys_rt_sigaction 14 common rt_sigprocmask sys_rt_sigprocmask -15 64 rt_sigreturn stub_rt_sigreturn +15 64 rt_sigreturn stub_rt_sigreturn/ptregs 16 64 ioctl sys_ioctl 17 common pread64 sys_pread64 18 common pwrite64 sys_pwrite64 @@ -62,10 +62,10 @@ 53 common socketpair sys_socketpair 54 64 setsockopt sys_setsockopt 55 64 getsockopt sys_getsockopt -56 common clone stub_clone -57 common fork stub_fork -58 common vfork stub_vfork -59 64 execve stub_execve +56 common clone stub_clone/ptregs +57 common fork stub_fork/ptregs +58 common vfork stub_vfork/ptregs +59 64 execve stub_execve/ptregs 60 common exit sys_exit 61 common wait4 sys_wait4 62 common kill sys_kill @@ -328,7 +328,7 @@ 319 common memfd_create sys_memfd_create 320 common kexec_file_load sys_kexec_file_load 321 common bpf sys_bpf -322 64 execveat stub_execveat +322 64 execveat stub_execveat/ptregs 323 common userfaultfd sys_userfaultfd 324 common membarrier sys_membarrier 325 common mlock2 sys_mlock2 @@ -346,7 +346,7 @@ 517 x32 recvfrom compat_sys_recvfrom 518 x32 sendmsg compat_sys_sendmsg 519 x32 recvmsg compat_sys_recvmsg -520 x32 execve stub_x32_execve +520 x32 execve stub_x32_execve/ptregs 521 x32 ptrace compat_sys_ptrace 522 x32 rt_sigpending compat_sys_rt_sigpending 523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait @@ -371,4 +371,4 @@ 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 stub_x32_execveat +545 x32 execveat stub_x32_execveat/ptregs -- cgit From 46eabf06c04a6847a694a0c1413d4ac57e5b058a Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:26 -0800 Subject: x86/entry/64: Call all native slow-path syscalls with full pt-regs This removes all of the remaining asm syscall stubs except for stub_ptregs_64. Entries in the main syscall table are now all callable from C. The resulting asm is every bit as ridiculous as it looks. The next few patches will clean it up. This patch is here to let reviewers rest their brains and for bisection. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/a6b3801be0d505d50aefabda02d3b93efbfc9c73.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 79 +--------------------------------- arch/x86/entry/syscalls/syscall_64.tbl | 18 ++++---- 2 files changed, 10 insertions(+), 87 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index f1c8f150728e..f7050a5d9dbc 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -253,7 +253,6 @@ tracesys: * the value it wants us to use in the table lookup. */ RESTORE_C_REGS_EXCEPT_RAX - RESTORE_EXTRA_REGS #if __SYSCALL_MASK == ~0 cmpq $__NR_syscall_max, %rax #else @@ -264,6 +263,7 @@ tracesys: movq %r10, %rcx /* fixup for C */ call *sys_call_table(, %rax, 8) movq %rax, RAX(%rsp) + RESTORE_EXTRA_REGS 1: /* Use IRET because user could have changed pt_regs->foo */ @@ -384,83 +384,6 @@ END(ptregs_\func) #define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym) #include - .macro FORK_LIKE func -ENTRY(stub_\func) - SAVE_EXTRA_REGS 8 - jmp sys_\func -END(stub_\func) - .endm - - FORK_LIKE clone - FORK_LIKE fork - FORK_LIKE vfork - -ENTRY(stub_execve) - call sys_execve -return_from_execve: - testl %eax, %eax - jz 1f - /* exec failed, can use fast SYSRET code path in this case */ - ret -1: - /* must use IRET code path (pt_regs->cs may have changed) */ - addq $8, %rsp - ZERO_EXTRA_REGS - movq %rax, RAX(%rsp) - jmp int_ret_from_sys_call -END(stub_execve) -/* - * Remaining execve stubs are only 7 bytes long. - * ENTRY() often aligns to 16 bytes, which in this case has no benefits. - */ - .align 8 -GLOBAL(stub_execveat) - call sys_execveat - jmp return_from_execve -END(stub_execveat) - -#if defined(CONFIG_X86_X32_ABI) - .align 8 -GLOBAL(stub_x32_execve) - call compat_sys_execve - jmp return_from_execve -END(stub_x32_execve) - .align 8 -GLOBAL(stub_x32_execveat) - call compat_sys_execveat - jmp return_from_execve -END(stub_x32_execveat) -#endif - -/* - * sigreturn is special because it needs to restore all registers on return. - * This cannot be done with SYSRET, so use the IRET return path instead. - */ -ENTRY(stub_rt_sigreturn) - /* - * SAVE_EXTRA_REGS result is not normally needed: - * sigreturn overwrites all pt_regs->GPREGS. - * But sigreturn can fail (!), and there is no easy way to detect that. - * To make sure RESTORE_EXTRA_REGS doesn't restore garbage on error, - * we SAVE_EXTRA_REGS here. - */ - SAVE_EXTRA_REGS 8 - call sys_rt_sigreturn -return_from_stub: - addq $8, %rsp - RESTORE_EXTRA_REGS - movq %rax, RAX(%rsp) - jmp int_ret_from_sys_call -END(stub_rt_sigreturn) - -#ifdef CONFIG_X86_X32_ABI -ENTRY(stub_x32_rt_sigreturn) - SAVE_EXTRA_REGS 8 - call sys32_x32_rt_sigreturn - jmp return_from_stub -END(stub_x32_rt_sigreturn) -#endif - /* * A newly forked process directly context switches into this address. * diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 5de342a729d0..dcf107ce2cd4 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -21,7 +21,7 @@ 12 common brk sys_brk 13 64 rt_sigaction sys_rt_sigaction 14 common rt_sigprocmask sys_rt_sigprocmask -15 64 rt_sigreturn stub_rt_sigreturn/ptregs +15 64 rt_sigreturn sys_rt_sigreturn/ptregs 16 64 ioctl sys_ioctl 17 common pread64 sys_pread64 18 common pwrite64 sys_pwrite64 @@ -62,10 +62,10 @@ 53 common socketpair sys_socketpair 54 64 setsockopt sys_setsockopt 55 64 getsockopt sys_getsockopt -56 common clone stub_clone/ptregs -57 common fork stub_fork/ptregs -58 common vfork stub_vfork/ptregs -59 64 execve stub_execve/ptregs +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 @@ -328,7 +328,7 @@ 319 common memfd_create sys_memfd_create 320 common kexec_file_load sys_kexec_file_load 321 common bpf sys_bpf -322 64 execveat stub_execveat/ptregs +322 64 execveat sys_execveat/ptregs 323 common userfaultfd sys_userfaultfd 324 common membarrier sys_membarrier 325 common mlock2 sys_mlock2 @@ -339,14 +339,14 @@ # for native 64-bit operation. # 512 x32 rt_sigaction compat_sys_rt_sigaction -513 x32 rt_sigreturn stub_x32_rt_sigreturn +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 stub_x32_execve/ptregs +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 @@ -371,4 +371,4 @@ 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 stub_x32_execveat/ptregs +545 x32 execveat compat_sys_execveat/ptregs -- cgit From 24d978b76ffd20ecff8a8d1c21b16fe740f8b119 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:27 -0800 Subject: x86/entry/64: Stop using int_ret_from_sys_call in ret_from_fork ret_from_fork is now open-coded and is no longer tangled up with the syscall code. This isn't so bad -- this adds very little code, and IMO the result is much easier to understand. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/a0747e2a5e47084655a1e96351c545b755c41fa7.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index f7050a5d9dbc..cb5d940a7abd 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -390,7 +390,6 @@ END(ptregs_\func) * rdi: prev task we switched from */ ENTRY(ret_from_fork) - LOCK ; btr $TIF_FORK, TI_flags(%r8) pushq $0x0002 @@ -398,28 +397,32 @@ ENTRY(ret_from_fork) call schedule_tail /* rdi: 'prev' task parameter */ - RESTORE_EXTRA_REGS - testb $3, CS(%rsp) /* from kernel_thread? */ + jnz 1f /* - * By the time we get here, we have no idea whether our pt_regs, - * ti flags, and ti status came from the 64-bit SYSCALL fast path, - * the slow path, or one of the 32-bit compat paths. - * Use IRET code path to return, since it can safely handle - * all of the above. + * We came from kernel_thread. This code path is quite twisted, and + * someone should clean it up. + * + * copy_thread_tls stashes the function pointer in RBX and the + * parameter to be passed in RBP. The called function is permitted + * to call do_execve and thereby jump to user mode. */ - jnz int_ret_from_sys_call + movq RBP(%rsp), %rdi + call *RBX(%rsp) + movl $0, RAX(%rsp) /* - * We came from kernel_thread - * nb: we depend on RESTORE_EXTRA_REGS above + * Fall through as though we're exiting a syscall. This makes a + * twisted sort of sense if we just called do_execve. */ - movq %rbp, %rdi - call *%rbx - movl $0, RAX(%rsp) - RESTORE_EXTRA_REGS - jmp int_ret_from_sys_call + +1: + movq %rsp, %rdi + call syscall_return_slowpath /* returns with IRQs disabled */ + TRACE_IRQS_ON /* user mode is traced as IRQS on */ + SWAPGS + jmp restore_regs_and_iret END(ret_from_fork) /* -- cgit From 1e423bff959e48166f5b7efca01fdb0dbdf05846 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Thu, 28 Jan 2016 15:11:28 -0800 Subject: x86/entry/64: Migrate the 64-bit syscall slow path to C This is more complicated than the 32-bit and compat cases because it preserves an asm fast path for the case where the callee-saved regs aren't needed in pt_regs and no entry or exit work needs to be done. This appears to slow down fastpath syscalls by no more than one cycle on my Skylake laptop. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/ce2335a4d42dc164b24132ee5e8c7716061f947b.1454022279.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/common.c | 26 +++++++++++ arch/x86/entry/entry_64.S | 117 ++++++++++++++++------------------------------ 2 files changed, 65 insertions(+), 78 deletions(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 03663740c866..75175f92f462 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -344,6 +344,32 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs) prepare_exit_to_usermode(regs); } +#ifdef CONFIG_X86_64 +__visible void do_syscall_64(struct pt_regs *regs) +{ + struct thread_info *ti = pt_regs_to_thread_info(regs); + unsigned long nr = regs->orig_ax; + + local_irq_enable(); + + if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) + nr = syscall_trace_enter(regs); + + /* + * NB: Native and x32 syscalls are dispatched from the same + * table. The only functional difference is the x32 bit in + * regs->orig_ax, which changes the behavior of some syscalls. + */ + if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) { + regs->ax = sys_call_table[nr & __SYSCALL_MASK]( + regs->di, regs->si, regs->dx, + regs->r10, regs->r8, regs->r9); + } + + syscall_return_slowpath(regs); +} +#endif + #if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) /* * Does a 32-bit syscall. Called with IRQs on and does all entry and diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index cb5d940a7abd..567aa522ac0a 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -145,17 +145,11 @@ GLOBAL(entry_SYSCALL_64_after_swapgs) movq %rsp, PER_CPU_VAR(rsp_scratch) movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp + TRACE_IRQS_OFF + /* Construct struct pt_regs on stack */ pushq $__USER_DS /* pt_regs->ss */ pushq PER_CPU_VAR(rsp_scratch) /* pt_regs->sp */ - /* - * Re-enable interrupts. - * We use 'rsp_scratch' as a scratch space, hence irq-off block above - * must execute atomically in the face of possible interrupt-driven - * task preemption. We must enable interrupts only after we're done - * with using rsp_scratch: - */ - ENABLE_INTERRUPTS(CLBR_NONE) pushq %r11 /* pt_regs->flags */ pushq $__USER_CS /* pt_regs->cs */ pushq %rcx /* pt_regs->ip */ @@ -171,9 +165,21 @@ GLOBAL(entry_SYSCALL_64_after_swapgs) pushq %r11 /* pt_regs->r11 */ sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */ - testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) - jnz tracesys + /* + * If we need to do entry work or if we guess we'll need to do + * exit work, go straight to the slow path. + */ + testl $_TIF_WORK_SYSCALL_ENTRY|_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) + jnz entry_SYSCALL64_slow_path + entry_SYSCALL_64_fastpath: + /* + * Easy case: enable interrupts and issue the syscall. If the syscall + * needs pt_regs, we'll call a stub that disables interrupts again + * and jumps to the slow path. + */ + TRACE_IRQS_ON + ENABLE_INTERRUPTS(CLBR_NONE) #if __SYSCALL_MASK == ~0 cmpq $__NR_syscall_max, %rax #else @@ -193,88 +199,43 @@ entry_SYSCALL_64_fastpath: movq %rax, RAX(%rsp) 1: -/* - * Syscall return path ending with SYSRET (fast path). - * Has incompletely filled pt_regs. - */ - LOCKDEP_SYS_EXIT - /* - * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON, - * it is too small to ever cause noticeable irq latency. - */ - DISABLE_INTERRUPTS(CLBR_NONE) /* - * We must check ti flags with interrupts (or at least preemption) - * off because we must *never* return to userspace without - * processing exit work that is enqueued if we're preempted here. - * In particular, returning to userspace with any of the one-shot - * flags (TIF_NOTIFY_RESUME, TIF_USER_RETURN_NOTIFY, etc) set is - * very bad. + * If we get here, then we know that pt_regs is clean for SYSRET64. + * If we see that no exit work is required (which we are required + * to check with IRQs off), then we can go straight to SYSRET64. */ + DISABLE_INTERRUPTS(CLBR_NONE) + TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) - jnz int_ret_from_sys_call_irqs_off /* Go to the slow path */ + jnz 1f - RESTORE_C_REGS_EXCEPT_RCX_R11 - movq RIP(%rsp), %rcx - movq EFLAGS(%rsp), %r11 + LOCKDEP_SYS_EXIT + TRACE_IRQS_ON /* user mode is traced as IRQs on */ + RESTORE_C_REGS movq RSP(%rsp), %rsp - /* - * 64-bit SYSRET restores rip from rcx, - * rflags from r11 (but RF and VM bits are forced to 0), - * cs and ss are loaded from MSRs. - * Restoration of rflags re-enables interrupts. - * - * NB: On AMD CPUs with the X86_BUG_SYSRET_SS_ATTRS bug, the ss - * descriptor is not reinitialized. This means that we should - * avoid SYSRET with SS == NULL, which could happen if we schedule, - * exit the kernel, and re-enter using an interrupt vector. (All - * interrupt entries on x86_64 set SS to NULL.) We prevent that - * from happening by reloading SS in __switch_to. (Actually - * detecting the failure in 64-bit userspace is tricky but can be - * done.) - */ USERGS_SYSRET64 -GLOBAL(int_ret_from_sys_call_irqs_off) +1: + /* + * The fast path looked good when we started, but something changed + * along the way and we need to switch to the slow path. Calling + * raise(3) will trigger this, for example. IRQs are off. + */ TRACE_IRQS_ON ENABLE_INTERRUPTS(CLBR_NONE) - jmp int_ret_from_sys_call - - /* Do syscall entry tracing */ -tracesys: SAVE_EXTRA_REGS movq %rsp, %rdi - call syscall_trace_enter - - /* - * Reload registers from stack in case ptrace changed them. - * We don't reload %rax because syscall_trace_enter() returned - * the value it wants us to use in the table lookup. - */ - RESTORE_C_REGS_EXCEPT_RAX -#if __SYSCALL_MASK == ~0 - cmpq $__NR_syscall_max, %rax -#else - andl $__SYSCALL_MASK, %eax - cmpl $__NR_syscall_max, %eax -#endif - ja 1f /* return -ENOSYS (already in pt_regs->ax) */ - movq %r10, %rcx /* fixup for C */ - call *sys_call_table(, %rax, 8) - movq %rax, RAX(%rsp) - RESTORE_EXTRA_REGS -1: - /* Use IRET because user could have changed pt_regs->foo */ + call syscall_return_slowpath /* returns with IRQs disabled */ + jmp return_from_SYSCALL_64 -/* - * Syscall return path ending with IRET. - * Has correct iret frame. - */ -GLOBAL(int_ret_from_sys_call) +entry_SYSCALL64_slow_path: + /* IRQs are off. */ SAVE_EXTRA_REGS movq %rsp, %rdi - call syscall_return_slowpath /* returns with IRQs disabled */ + call do_syscall_64 /* returns with IRQs disabled */ + +return_from_SYSCALL_64: RESTORE_EXTRA_REGS TRACE_IRQS_IRETQ /* we're about to change IF */ @@ -364,7 +325,7 @@ ENTRY(stub_ptregs_64) /* Called from fast path -- pop return address and jump to slow path */ popq %rax - jmp tracesys /* called from fast path */ + jmp entry_SYSCALL64_slow_path /* called from fast path */ 1: /* Called from C */ -- cgit From 4c1ce07bcf62536ed42a4ba43e5fb580be61ac48 Mon Sep 17 00:00:00 2001 From: Uri Mashiach Date: Wed, 30 Dec 2015 15:35:31 +0200 Subject: wlcore/wl12xx: spi: add power operation function The power function uses a consumer regulator access to update the WiFi enable GPIO value. Signed-off-by: Uri Mashiach Tested-By: Sebastian Reichel Reviewed-by: Grygorii Strashko Acked-by: Igor Grinberg Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/spi.c | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 44f059f7f34e..dec151247d0d 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "wlcore.h" #include "wl12xx_80211.h" @@ -81,6 +82,7 @@ struct wl12xx_spi_glue { struct device *dev; struct platform_device *core; + struct regulator *reg; /* Power regulator */ }; static void wl12xx_spi_reset(struct device *child) @@ -318,11 +320,40 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, return 0; } +/** + * wl12xx_spi_set_power - power on/off the wl12xx unit + * @child: wl12xx device handle. + * @enable: true/false to power on/off the unit. + * + * use the WiFi enable regulator to enable/disable the WiFi unit. + */ +static int wl12xx_spi_set_power(struct device *child, bool enable) +{ + int ret = 0; + struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); + + WARN_ON(!glue->reg); + + /* Update regulator state */ + if (enable) { + ret = regulator_enable(glue->reg); + if (ret) + dev_err(child, "Power enable failure\n"); + } else { + ret = regulator_disable(glue->reg); + if (ret) + dev_err(child, "Power disable failure\n"); + } + + return ret; +} + static struct wl1271_if_operations spi_ops = { .read = wl12xx_spi_raw_read, .write = wl12xx_spi_raw_write, .reset = wl12xx_spi_reset, .init = wl12xx_spi_init, + .power = wl12xx_spi_set_power, .set_block_size = NULL, }; @@ -353,6 +384,14 @@ static int wl1271_probe(struct spi_device *spi) * comes from the board-peripherals file */ spi->bits_per_word = 32; + glue->reg = devm_regulator_get(&spi->dev, "vwlan"); + if (PTR_ERR(glue->reg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (IS_ERR(glue->reg)) { + dev_err(glue->dev, "can't get regulator\n"); + return PTR_ERR(glue->reg); + } + ret = spi_setup(spi); if (ret < 0) { dev_err(glue->dev, "spi_setup failed\n"); -- cgit From 04654c386145239c8bcb35878b0b0537ce916766 Mon Sep 17 00:00:00 2001 From: Uri Mashiach Date: Wed, 30 Dec 2015 15:35:32 +0200 Subject: wlcore/wl12xx: spi: add device tree support Add DT support for the wl1271 SPI WiFi. Add documentation file for the wl1271 SPI WiFi. Signed-off-by: Uri Mashiach Acked-by: Rob Herring Tested-By: Sebastian Reichel Reviewed-by: Grygorii Strashko Acked-by: Igor Grinberg Signed-off-by: Kalle Valo --- .../bindings/net/wireless/ti,wlcore,spi.txt | 36 +++++++++++++++++ drivers/net/wireless/ti/wlcore/Kconfig | 2 +- drivers/net/wireless/ti/wlcore/spi.c | 47 ++++++++++++++++++++-- 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt diff --git a/Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt b/Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt new file mode 100644 index 000000000000..9180724e182c --- /dev/null +++ b/Documentation/devicetree/bindings/net/wireless/ti,wlcore,spi.txt @@ -0,0 +1,36 @@ +* Texas Instruments wl1271 wireless lan controller + +The wl1271 chip can be connected via SPI or via SDIO. This +document describes the binding for the SPI connected chip. + +Required properties: +- compatible : Should be "ti,wl1271" +- reg : Chip select address of device +- spi-max-frequency : Maximum SPI clocking speed of device in Hz +- ref-clock-frequency : Reference clock frequency +- interrupt-parent, interrupts : + Should contain parameters for 1 interrupt line. + Interrupt parameters: parent, line number, type. +- vwlan-supply : Point the node of the regulator that powers/enable the wl1271 chip + +Optional properties: +- clock-xtal : boolean, clock is generated from XTAL + +- Please consult Documentation/devicetree/bindings/spi/spi-bus.txt + for optional SPI connection related properties, + +Examples: + +&spi1 { + wl1271@1 { + compatible = "ti,wl1271"; + + reg = <1>; + spi-max-frequency = <48000000>; + clock-xtal; + ref-clock-frequency = <38400000>; + interrupt-parent = <&gpio3>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; + vwlan-supply = <&vwlan_fixed>; + }; +}; diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig index 969c9d79bfc8..8a8f1e711384 100644 --- a/drivers/net/wireless/ti/wlcore/Kconfig +++ b/drivers/net/wireless/ti/wlcore/Kconfig @@ -13,7 +13,7 @@ config WLCORE config WLCORE_SPI tristate "TI wlcore SPI support" - depends on WLCORE && SPI_MASTER + depends on WLCORE && SPI_MASTER && OF select CRC7 ---help--- This module adds support for the SPI interface of adapters using diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index dec151247d0d..020ac1a4b408 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "wlcore.h" @@ -357,6 +358,39 @@ static struct wl1271_if_operations spi_ops = { .set_block_size = NULL, }; +static const struct of_device_id wlcore_spi_of_match_table[] = { + { .compatible = "ti,wl1271" }, + { } +}; +MODULE_DEVICE_TABLE(of, wlcore_spi_of_match_table); + +/** + * wlcore_probe_of - DT node parsing. + * @spi: SPI slave device parameters. + * @res: resource parameters. + * @glue: wl12xx SPI bus to slave device glue parameters. + * @pdev_data: wlcore device parameters + */ +static int wlcore_probe_of(struct spi_device *spi, struct wl12xx_spi_glue *glue, + struct wlcore_platdev_data *pdev_data) +{ + struct device_node *dt_node = spi->dev.of_node; + int ret; + + if (of_find_property(dt_node, "clock-xtal", NULL)) + pdev_data->ref_clock_xtal = true; + + ret = of_property_read_u32(dt_node, "ref-clock-frequency", + &pdev_data->ref_clock_freq); + if (IS_ERR_VALUE(ret)) { + dev_err(glue->dev, + "can't get reference clock frequency (%d)\n", ret); + return ret; + } + + return 0; +} + static int wl1271_probe(struct spi_device *spi) { struct wl12xx_spi_glue *glue; @@ -366,8 +400,6 @@ static int wl1271_probe(struct spi_device *spi) memset(&pdev_data, 0x00, sizeof(pdev_data)); - /* TODO: add DT parsing when needed */ - pdev_data.if_ops = &spi_ops; glue = devm_kzalloc(&spi->dev, sizeof(*glue), GFP_KERNEL); @@ -392,6 +424,13 @@ static int wl1271_probe(struct spi_device *spi) return PTR_ERR(glue->reg); } + ret = wlcore_probe_of(spi, glue, &pdev_data); + if (IS_ERR_VALUE(ret)) { + dev_err(glue->dev, + "can't get device tree parameters (%d)\n", ret); + return ret; + } + ret = spi_setup(spi); if (ret < 0) { dev_err(glue->dev, "spi_setup failed\n"); @@ -409,7 +448,7 @@ static int wl1271_probe(struct spi_device *spi) memset(res, 0x00, sizeof(res)); res[0].start = spi->irq; - res[0].flags = IORESOURCE_IRQ; + res[0].flags = IORESOURCE_IRQ | irq_get_trigger_type(spi->irq); res[0].name = "irq"; ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); @@ -447,10 +486,10 @@ static int wl1271_remove(struct spi_device *spi) return 0; } - static struct spi_driver wl1271_spi_driver = { .driver = { .name = "wl1271_spi", + .of_match_table = of_match_ptr(wlcore_spi_of_match_table), }, .probe = wl1271_probe, -- cgit From 2fd5c6ed0b4fbf3c2d9314a24c82862ce5254d42 Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 6 Jan 2016 23:40:47 -0800 Subject: mwifiex: firmware download enhancements Same chip is being used by WLAN as well as bluetooth drivers. Each driver needs to check during initialisation if firmware is already active or it needs to be freshly downloaded. If one driver has started downloading the firmware, other finds the winner flag as false. mwifiex_check_fw_status() checks firmware status and also check if WLAN is the winner for firmware downloading. Once we detect that other interface is downloading the firmware, we call this routine again with max poll count to wait until firmware is ready. This patch splits the routine to avoid checking winner status unnecessarily multiple times and ensures that correct messages are displayed to user. Firmware status poll count is also increased to 150. Signed-off-by: Chunfan Chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/init.c | 16 +++++++++--- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/pcie.c | 40 +++++++++++++++++------------ drivers/net/wireless/marvell/mwifiex/sdio.c | 33 ++++++++++++++---------- 5 files changed, 57 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index ced7af2be29a..426e76ade30c 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -96,7 +96,7 @@ enum KEY_TYPE_ID { #define WAPI_KEY_LEN (WLAN_KEY_LEN_SMS4 + PN_LEN + 2) #define MAX_POLL_TRIES 100 -#define MAX_FIRMWARE_POLL_TRIES 100 +#define MAX_FIRMWARE_POLL_TRIES 150 #define FIRMWARE_READY_SDIO 0xfedc #define FIRMWARE_READY_PCIE 0xfedcba00 diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c index 6f7876ec31b7..517653b3adab 100644 --- a/drivers/net/wireless/marvell/mwifiex/init.c +++ b/drivers/net/wireless/marvell/mwifiex/init.c @@ -741,8 +741,6 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, u32 poll_num = 1; if (adapter->if_ops.check_fw_status) { - adapter->winner = 0; - /* check if firmware is already running */ ret = adapter->if_ops.check_fw_status(adapter, poll_num); if (!ret) { @@ -750,13 +748,23 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, "WLAN FW already running! Skip FW dnld\n"); return 0; } + } + + /* check if we are the winner for downloading FW */ + if (adapter->if_ops.check_winner_status) { + adapter->winner = 0; + ret = adapter->if_ops.check_winner_status(adapter); poll_num = MAX_FIRMWARE_POLL_TRIES; + if (ret) { + mwifiex_dbg(adapter, MSG, + "WLAN read winner status failed!\n"); + return ret; + } - /* check if we are the winner for downloading FW */ if (!adapter->winner) { mwifiex_dbg(adapter, MSG, - "FW already running! Skip FW dnld\n"); + "WLAN is not the winner! Skip FW dnld\n"); goto poll_fw; } } diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 2f7f478ce04b..c08be798905f 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -791,6 +791,7 @@ struct mwifiex_if_ops { int (*init_if) (struct mwifiex_adapter *); void (*cleanup_if) (struct mwifiex_adapter *); int (*check_fw_status) (struct mwifiex_adapter *, u32); + int (*check_winner_status)(struct mwifiex_adapter *); int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); int (*register_dev) (struct mwifiex_adapter *); void (*unregister_dev) (struct mwifiex_adapter *); diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 6d0dc40e20e5..f448d7ca4e7c 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2007,14 +2007,12 @@ done: /* * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. */ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { int ret = 0; - u32 firmware_stat, winner_status; + u32 firmware_stat; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; u32 tries; @@ -2054,19 +2052,28 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) } } - if (ret) { - if (mwifiex_read_reg(adapter, reg->fw_status, - &winner_status)) - ret = -1; - else if (!winner_status) { - mwifiex_dbg(adapter, INFO, - "PCI-E is the winner\n"); - adapter->winner = 1; - } else { - mwifiex_dbg(adapter, ERROR, - "PCI-E is not the winner <%#x,%d>, exit dnld\n", - ret, adapter->winner); - } + return ret; +} + +/* This function checks if WLAN is the winner. + */ +static int +mwifiex_check_winner_status(struct mwifiex_adapter *adapter) +{ + u32 winner = 0; + int ret = 0; + struct pcie_service_card *card = adapter->card; + const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + + if (mwifiex_read_reg(adapter, reg->fw_status, &winner)) { + ret = -1; + } else if (!winner) { + mwifiex_dbg(adapter, INFO, "PCI-E is the winner\n"); + adapter->winner = 1; + } else { + mwifiex_dbg(adapter, ERROR, + "PCI-E is not the winner <%#x,%d>, exit dnld\n", + ret, adapter->winner); } return ret; @@ -2675,6 +2682,7 @@ static struct mwifiex_if_ops pcie_ops = { .init_if = mwifiex_pcie_init, .cleanup_if = mwifiex_pcie_cleanup, .check_fw_status = mwifiex_check_fw_status, + .check_winner_status = mwifiex_check_winner_status, .prog_fw = mwifiex_prog_fw_w_helper, .register_dev = mwifiex_register_dev, .unregister_dev = mwifiex_unregister_dev, diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 4c8cae682c89..33771d3fd843 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -1039,19 +1039,14 @@ done: /* * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. */ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { - struct sdio_mmc_card *card = adapter->card; int ret = 0; u16 firmware_stat; u32 tries; - u8 winner_status; - /* Wait for firmware initialization event */ for (tries = 0; tries < poll_num; tries++) { ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); if (ret) @@ -1065,16 +1060,25 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, } } - if (ret) { - if (mwifiex_read_reg - (adapter, card->reg->status_reg_0, &winner_status)) - winner_status = 0; + return ret; +} + +/* This function checks if WLAN is the winner. + */ +static int mwifiex_check_winner_status(struct mwifiex_adapter *adapter) +{ + int ret = 0; + u8 winner = 0; + struct sdio_mmc_card *card = adapter->card; + + if (mwifiex_read_reg(adapter, card->reg->status_reg_0, &winner)) + return -1; + + if (winner) + adapter->winner = 0; + else + adapter->winner = 1; - if (winner_status) - adapter->winner = 0; - else - adapter->winner = 1; - } return ret; } @@ -2620,6 +2624,7 @@ static struct mwifiex_if_ops sdio_ops = { .init_if = mwifiex_init_sdio, .cleanup_if = mwifiex_cleanup_sdio, .check_fw_status = mwifiex_check_fw_status, + .check_winner_status = mwifiex_check_winner_status, .prog_fw = mwifiex_prog_fw_w_helper, .register_dev = mwifiex_register_dev, .unregister_dev = mwifiex_unregister_dev, -- cgit From dc386ce76dedaeeaaf006fceb6ed8cf2e20ff026 Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 6 Jan 2016 23:40:48 -0800 Subject: mwifiex: fix IBSS data path issue. The port_open flag is not applicable for IBSS mode. IBSS data path was broken when port_open flag was introduced. This patch fixes the problem by correcting the checks. Fixes: 5c8946330abfa4c ("mwifiex: enable traffic only when port is open") Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sta_event.c | 10 ++++++---- drivers/net/wireless/marvell/mwifiex/wmm.c | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index ff3ee9dfbbd5..23bae87d4d3d 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -607,11 +607,13 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) case EVENT_PS_AWAKE: mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n"); - if (!adapter->pps_uapsd_mode && priv->port_open && + if (!adapter->pps_uapsd_mode && + (priv->port_open || + (priv->bss_mode == NL80211_IFTYPE_ADHOC)) && priv->media_connected && adapter->sleep_period.period) { - adapter->pps_uapsd_mode = true; - mwifiex_dbg(adapter, EVENT, - "event: PPS/UAPSD mode activated\n"); + adapter->pps_uapsd_mode = true; + mwifiex_dbg(adapter, EVENT, + "event: PPS/UAPSD mode activated\n"); } adapter->tx_lock_flag = false; if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index acccd6734e3b..499e5a741c62 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -475,7 +475,8 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) priv = adapter->priv[i]; if (!priv) continue; - if (!priv->port_open) + if (!priv->port_open && + (priv->bss_mode != NL80211_IFTYPE_ADHOC)) continue; if (adapter->if_ops.is_port_ready && !adapter->if_ops.is_port_ready(priv)) @@ -1099,7 +1100,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv; - if (!priv_tmp->port_open || + if (((priv_tmp->bss_mode != NL80211_IFTYPE_ADHOC) && + !priv_tmp->port_open) || (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)) continue; -- cgit From 17934b6a32b2fdfcc0a9e83d17c780f15627aa30 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Wed, 6 Jan 2016 23:40:49 -0800 Subject: mwifiex: add debugfs file to read chip information This patch add 'verext' debugfs item, which can be used to get detailed chip specific information from our firmware. Examples: echo "1" > /sys/kernel/debug/mwifiex/mlan0/verext cat /sys/kernel/debug/mwifiex/mlan0/verext Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/README | 10 +++++ drivers/net/wireless/marvell/mwifiex/debugfs.c | 51 +++++++++++++++++++++++- drivers/net/wireless/marvell/mwifiex/main.h | 3 +- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 3 +- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/README b/drivers/net/wireless/marvell/mwifiex/README index 2f0f9b5609d0..24e649b1eb24 100644 --- a/drivers/net/wireless/marvell/mwifiex/README +++ b/drivers/net/wireless/marvell/mwifiex/README @@ -237,4 +237,14 @@ device_dump cat fw_dump +verext + This command is used to get extended firmware version string using + different configuration parameters. + + Usage: + echo "[version_str_sel]" > verext + cat verext + + [version_str_sel]: firmware support several extend version + string cases, include 0/1/10/20/21/99 =============================================================================== diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c index 0b9c580af988..df28836a1d11 100644 --- a/drivers/net/wireless/marvell/mwifiex/debugfs.c +++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c @@ -95,8 +95,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf, mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); - if (!priv->version_str[0]) - mwifiex_get_ver_ext(priv); + mwifiex_get_ver_ext(priv, 0); p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); p += sprintf(p, "driver_version = %s", fmt); @@ -583,6 +582,52 @@ done: return ret; } +/* debugfs verext file write handler. + * This function is called when the 'verext' file is opened for write + */ +static ssize_t +mwifiex_verext_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + int ret; + u32 versionstrsel; + struct mwifiex_private *priv = (void *)file->private_data; + char buf[16]; + + memset(buf, 0, sizeof(buf)); + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + ret = kstrtou32(buf, 10, &versionstrsel); + if (ret) + return ret; + + priv->versionstrsel = versionstrsel; + + return count; +} + +/* Proc verext file read handler. + * This function is called when the 'verext' file is opened for reading + * This function can be used read driver exteneed verion string. + */ +static ssize_t +mwifiex_verext_read(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwifiex_private *priv = + (struct mwifiex_private *)file->private_data; + char buf[256]; + int ret; + + mwifiex_get_ver_ext(priv, priv->versionstrsel); + ret = snprintf(buf, sizeof(buf), "version string: %s\n", + priv->version_str); + + return simple_read_from_buffer(ubuf, count, ppos, buf, ret); +} + /* Proc memrw file write handler. * This function is called when the 'memrw' file is opened for writing * This function can be used to write to a memory location. @@ -940,6 +985,7 @@ MWIFIEX_DFS_FILE_OPS(histogram); MWIFIEX_DFS_FILE_OPS(debug_mask); MWIFIEX_DFS_FILE_OPS(timeshare_coex); MWIFIEX_DFS_FILE_WRITE_OPS(reset); +MWIFIEX_DFS_FILE_OPS(verext); /* * This function creates the debug FS directory structure and the files. @@ -968,6 +1014,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv) MWIFIEX_DFS_ADD_FILE(debug_mask); MWIFIEX_DFS_ADD_FILE(timeshare_coex); MWIFIEX_DFS_ADD_FILE(reset); + MWIFIEX_DFS_ADD_FILE(verext); } /* diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index c08be798905f..35ab052c8a36 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -616,6 +616,7 @@ struct mwifiex_private { spinlock_t curr_bcn_buf_lock; struct wireless_dev wdev; struct mwifiex_chan_freq_power cfp; + u32 versionstrsel; char version_str[128]; #ifdef CONFIG_DEBUG_FS struct dentry *dfs_dev_dir; @@ -1418,7 +1419,7 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len); -int mwifiex_get_ver_ext(struct mwifiex_private *priv); +int mwifiex_get_ver_ext(struct mwifiex_private *priv, u32 version_str_sel); int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, struct ieee80211_channel *chan, diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 6a4fc5d183cf..210b257aad6b 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1114,11 +1114,12 @@ int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, * with requisite parameters and calls the IOCTL handler. */ int -mwifiex_get_ver_ext(struct mwifiex_private *priv) +mwifiex_get_ver_ext(struct mwifiex_private *priv, u32 version_str_sel) { struct mwifiex_ver_ext ver_ext; memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); + ver_ext.version_str_sel = version_str_sel; if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT, HostCmd_ACT_GEN_GET, 0, &ver_ext, true)) return -1; -- cgit From 68f37e5d7a2e00306adab033fba6c3042b33e8e1 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 7 Jan 2016 14:28:50 +0100 Subject: wlcore: fix error handling in wlcore_event_fw_logger wlcore_read/wlcore_write can return negative values so it should be assigned to signed variable. The problem has been detected using proposed semantic patch scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci [1]. [1]: http://permalink.gmane.org/gmane.linux.kernel/2120705 Fixes: 3719c17e1816 ("wlcore/wl18xx: fw logger over sdio") Signed-off-by: Andrzej Hajda Signed-off-by: Kalle Valo --- drivers/net/wireless/ti/wlcore/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index c96405498bf4..4b59f67724de 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -38,7 +38,7 @@ int wlcore_event_fw_logger(struct wl1271 *wl) { - u32 ret; + int ret; struct fw_logger_information fw_log; u8 *buffer; u32 internal_fw_addrbase = WL18XX_DATA_RAM_BASE_ADDRESS; -- cgit From 99074fc1e67b374b5c72406a23ac01fed806d634 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Mon, 11 Jan 2016 02:16:40 -0800 Subject: mwifiex: enable pcie MSIx interrupt mode support Newer pcie chipsets (8997 onwards) support MSIx. This patch enables it. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 187 +++++++++++++++++++++++----- drivers/net/wireless/marvell/mwifiex/pcie.h | 17 +++ 2 files changed, 176 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index f448d7ca4e7c..5e154649c6a2 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2082,20 +2082,28 @@ mwifiex_check_winner_status(struct mwifiex_adapter *adapter) /* * This function reads the interrupt status from card. */ -static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) +static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, + int msg_id) { u32 pcie_ireg; unsigned long flags; + struct pcie_service_card *card = adapter->card; if (!mwifiex_pcie_ok_to_access_hw(adapter)) return; - if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, "Read register failed\n"); - return; - } + if (card->msix_enable && msg_id >= 0) { + pcie_ireg = BIT(msg_id); + } else { + if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, + &pcie_ireg)) { + mwifiex_dbg(adapter, ERROR, "Read register failed\n"); + return; + } + + if ((pcie_ireg == 0xFFFFFFFF) || !pcie_ireg) + return; - if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { mwifiex_pcie_disable_host_int(adapter); @@ -2106,20 +2114,23 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) "Write register failed\n"); return; } - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= pcie_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - - if (!adapter->pps_uapsd_mode && - adapter->ps_state == PS_STATE_SLEEP && - mwifiex_pcie_ok_to_access_hw(adapter)) { - /* Potentially for PCIe we could get other - * interrupts like shared. Don't change power - * state until cookie is set */ - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - } + } + + spin_lock_irqsave(&adapter->int_lock, flags); + adapter->int_status |= pcie_ireg; + spin_unlock_irqrestore(&adapter->int_lock, flags); + mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg); + + if (!adapter->pps_uapsd_mode && + adapter->ps_state == PS_STATE_SLEEP && + mwifiex_pcie_ok_to_access_hw(adapter)) { + /* Potentially for PCIe we could get other + * interrupts like shared. Don't change power + * state until cookie is set + */ + adapter->ps_state = PS_STATE_AWAKE; + adapter->pm_wakeup_fw_try = false; + del_timer(&adapter->wakeup_timer); } } @@ -2131,7 +2142,8 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) */ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) { - struct pci_dev *pdev = (struct pci_dev *)context; + struct mwifiex_msix_context *ctx = context; + struct pci_dev *pdev = ctx->dev; struct pcie_service_card *card; struct mwifiex_adapter *adapter; @@ -2151,7 +2163,11 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) if (adapter->surprise_removed) goto exit; - mwifiex_interrupt_status(adapter); + if (card->msix_enable) + mwifiex_interrupt_status(adapter, ctx->msg_id); + else + mwifiex_interrupt_status(adapter, -1); + mwifiex_queue_main_work(adapter); exit: @@ -2171,7 +2187,7 @@ exit: * In case of Rx packets received, the packets are uploaded from card to * host and processed accordingly. */ -static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) +static int mwifiex_process_pcie_int(struct mwifiex_adapter *adapter) { int ret; u32 pcie_ireg; @@ -2251,6 +2267,69 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) return 0; } +static int mwifiex_process_msix_int(struct mwifiex_adapter *adapter) +{ + int ret; + u32 pcie_ireg; + unsigned long flags; + + spin_lock_irqsave(&adapter->int_lock, flags); + /* Clear out unused interrupts */ + pcie_ireg = adapter->int_status; + adapter->int_status = 0; + spin_unlock_irqrestore(&adapter->int_lock, flags); + + if (pcie_ireg & HOST_INTR_DNLD_DONE) { + mwifiex_dbg(adapter, INTR, + "info: TX DNLD Done\n"); + ret = mwifiex_pcie_send_data_complete(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_UPLD_RDY) { + mwifiex_dbg(adapter, INTR, + "info: Rx DATA\n"); + ret = mwifiex_pcie_process_recv_data(adapter); + if (ret) + return ret; + } + if (pcie_ireg & HOST_INTR_EVENT_RDY) { + mwifiex_dbg(adapter, INTR, + "info: Rx EVENT\n"); + ret = mwifiex_pcie_process_event_ready(adapter); + if (ret) + return ret; + } + + if (pcie_ireg & HOST_INTR_CMD_DONE) { + if (adapter->cmd_sent) { + mwifiex_dbg(adapter, INTR, + "info: CMD sent Interrupt\n"); + adapter->cmd_sent = false; + } + /* Handle command response */ + ret = mwifiex_pcie_process_cmd_complete(adapter); + if (ret) + return ret; + } + + mwifiex_dbg(adapter, INTR, + "info: cmd_sent=%d data_sent=%d\n", + adapter->cmd_sent, adapter->data_sent); + + return 0; +} + +static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) +{ + struct pcie_service_card *card = adapter->card; + + if (card->msix_enable) + return mwifiex_process_msix_int(adapter); + else + return mwifiex_process_pcie_int(adapter); +} + /* * This function downloads data from driver to card. * @@ -2602,10 +2681,43 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) { - int ret; + int ret, i, j; struct pcie_service_card *card = adapter->card; struct pci_dev *pdev = card->dev; + if (card->pcie.reg->msix_support) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + card->msix_entries[i].entry = i; + ret = pci_enable_msix_exact(pdev, card->msix_entries, + MWIFIEX_NUM_MSIX_VECTORS); + if (!ret) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) { + card->msix_ctx[i].dev = pdev; + card->msix_ctx[i].msg_id = i; + + ret = request_irq(card->msix_entries[i].vector, + mwifiex_pcie_interrupt, 0, + "MWIFIEX_PCIE_MSIX", + &card->msix_ctx[i]); + if (ret) + break; + } + + if (ret) { + mwifiex_dbg(adapter, INFO, "request_irq fail: %d\n", + ret); + for (j = 0; j < i; j++) + free_irq(card->msix_entries[j].vector, + &card->msix_ctx[i]); + pci_disable_msix(pdev); + } else { + mwifiex_dbg(adapter, MSG, "MSIx enabled!"); + card->msix_enable = 1; + return 0; + } + } + } + if (pci_enable_msi(pdev) != 0) pci_disable_msi(pdev); else @@ -2613,8 +2725,10 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable); + card->share_irq_ctx.dev = pdev; + card->share_irq_ctx.msg_id = -1; ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED, - "MRVL_PCIE", pdev); + "MRVL_PCIE", &card->share_irq_ctx); if (ret) { pr_err("request_irq failed: ret=%d\n", ret); adapter->card = NULL; @@ -2660,11 +2774,28 @@ static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg; + struct pci_dev *pdev = card->dev; + int i; if (card) { - mwifiex_dbg(adapter, INFO, - "%s(): calling free_irq()\n", __func__); - free_irq(card->dev->irq, card->dev); + if (card->msix_enable) { + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + synchronize_irq(card->msix_entries[i].vector); + + for (i = 0; i < MWIFIEX_NUM_MSIX_VECTORS; i++) + free_irq(card->msix_entries[i].vector, + &card->msix_ctx[i]); + + card->msix_enable = 0; + pci_disable_msix(pdev); + } else { + mwifiex_dbg(adapter, INFO, + "%s(): calling free_irq()\n", __func__); + free_irq(card->dev->irq, &card->share_irq_ctx); + + if (card->msi_enable) + pci_disable_msi(pdev); + } reg = card->pcie.reg; if (reg->sleep_cookie) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 6fc28737b576..9700ac355e55 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -135,6 +135,7 @@ struct mwifiex_pcie_card_reg { u16 fw_dump_ctrl; u16 fw_dump_start; u16 fw_dump_end; + u8 msix_support; }; static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = { @@ -166,6 +167,7 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = { .ring_tx_start_ptr = 0, .pfu_enabled = 0, .sleep_cookie = 1, + .msix_support = 0, }; static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { @@ -200,6 +202,7 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { .fw_dump_ctrl = 0xcf4, .fw_dump_start = 0xcf8, .fw_dump_end = 0xcff, + .msix_support = 0, }; static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { @@ -231,6 +234,7 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, .pfu_enabled = 1, .sleep_cookie = 0, + .msix_support = 1, }; struct mwifiex_pcie_device { @@ -290,6 +294,13 @@ struct mwifiex_pfu_buf_desc { u32 reserved; } __packed; +#define MWIFIEX_NUM_MSIX_VECTORS 4 + +struct mwifiex_msix_context { + struct pci_dev *dev; + u16 msg_id; +}; + struct pcie_service_card { struct pci_dev *dev; struct mwifiex_adapter *adapter; @@ -327,6 +338,12 @@ struct pcie_service_card { void __iomem *pci_mmap; void __iomem *pci_mmap1; int msi_enable; + int msix_enable; +#ifdef CONFIG_PCI + struct msix_entry msix_entries[MWIFIEX_NUM_MSIX_VECTORS]; +#endif + struct mwifiex_msix_context msix_ctx[MWIFIEX_NUM_MSIX_VECTORS]; + struct mwifiex_msix_context share_irq_ctx; }; static inline int -- cgit From dc896b15fe94345912ff13fa8eb581b5c6acccde Mon Sep 17 00:00:00 2001 From: Shengzhen Li Date: Tue, 12 Jan 2016 05:43:16 -0800 Subject: mwifiex: fix power state out of sync problem It's been observed that driver's power state goes out of sync with firmware in some corner cases. When this happens, driver tries to download the data to firmware assuming it's awake which causes Tx data timeout. Main thread will process interrupt as soon as interrupt handler fills 'int_status' variable. This patch fixes the race issue by updating 'int_status' at the end of mwifiex_interrupt_status(). Signed-off-by: Shengzhen Li Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 5e154649c6a2..918e04954afe 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2116,11 +2116,6 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, } } - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= pcie_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg); - if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP && mwifiex_pcie_ok_to_access_hw(adapter)) { @@ -2132,6 +2127,11 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter, adapter->pm_wakeup_fw_try = false; del_timer(&adapter->wakeup_timer); } + + spin_lock_irqsave(&adapter->int_lock, flags); + adapter->int_status |= pcie_ireg; + spin_unlock_irqrestore(&adapter->int_lock, flags); + mwifiex_dbg(adapter, INTR, "ireg: 0x%08x\n", pcie_ireg); } /* -- cgit From 0c9b7f22e8e1f3aa5b88d7530db8b3a7d647adb6 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Wed, 13 Jan 2016 01:26:52 -0800 Subject: mwifiex: add schedule scan support This patch add sched scan support for mwifiex, include cfg80211 sched_scan_start/sched_scan_stop handler, corresponding bgscan command path and event handler. Signed-off-by: Xinming Hu Signed-off-by: chunfan chen Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 134 +++++++++++ drivers/net/wireless/marvell/mwifiex/fw.h | 59 +++++ drivers/net/wireless/marvell/mwifiex/ioctl.h | 1 + drivers/net/wireless/marvell/mwifiex/main.c | 7 + drivers/net/wireless/marvell/mwifiex/main.h | 10 + drivers/net/wireless/marvell/mwifiex/scan.c | 261 +++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 4 + drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 3 + drivers/net/wireless/marvell/mwifiex/sta_event.c | 7 + drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 7 + 10 files changed, 493 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index e7adef72c05f..c27c6cc5f93e 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -1962,6 +1962,9 @@ mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + if (!mwifiex_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy); + if (mwifiex_deauthenticate(priv, NULL)) return -EFAULT; @@ -2217,6 +2220,9 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, "info: Trying to associate to %s and bssid %pM\n", (char *)sme->ssid, sme->bssid); + if (!mwifiex_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy); + ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); if (!ret) { @@ -2420,6 +2426,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return -EBUSY; } + if (!mwifiex_stop_bg_scan(priv)) + cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy); + user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); if (!user_scan_cfg) return -ENOMEM; @@ -2487,6 +2496,121 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, return 0; } +/* CFG802.11 operation handler for sched_scan_start. + * + * This function issues a bgscan config request to the firmware based upon + * the user specified sched_scan configuration. On successful completion, + * firmware will generate BGSCAN_REPORT event, driver should issue bgscan + * query command to get sched_scan results from firmware. + */ +static int +mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + int i, offset; + struct ieee80211_channel *chan; + struct mwifiex_bg_scan_cfg *bgscan_cfg; + struct ieee_types_header *ie; + + if (!request || (!request->n_ssids && !request->n_match_sets)) { + wiphy_err(wiphy, "%s : Invalid Sched_scan parameters", + __func__); + return -EINVAL; + } + + wiphy_info(wiphy, "sched_scan start : n_ssids=%d n_match_sets=%d ", + request->n_ssids, request->n_match_sets); + wiphy_info(wiphy, "n_channels=%d interval=%d ie_len=%d\n", + request->n_channels, request->scan_plans->interval, + (int)request->ie_len); + + bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL); + if (!bgscan_cfg) + return -ENOMEM; + + if (priv->scan_request || priv->scan_aborting) + bgscan_cfg->start_later = true; + + bgscan_cfg->num_ssids = request->n_match_sets; + bgscan_cfg->ssid_list = request->match_sets; + + if (request->ie && request->ie_len) { + offset = 0; + for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { + if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR) + continue; + priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_BGSCAN; + ie = (struct ieee_types_header *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); + offset += sizeof(*ie) + ie->len; + + if (offset >= request->ie_len) + break; + } + } + + for (i = 0; i < min_t(u32, request->n_channels, + MWIFIEX_BG_SCAN_CHAN_MAX); i++) { + chan = request->channels[i]; + bgscan_cfg->chan_list[i].chan_number = chan->hw_value; + bgscan_cfg->chan_list[i].radio_type = chan->band; + + if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids) + bgscan_cfg->chan_list[i].scan_type = + MWIFIEX_SCAN_TYPE_PASSIVE; + else + bgscan_cfg->chan_list[i].scan_type = + MWIFIEX_SCAN_TYPE_ACTIVE; + + bgscan_cfg->chan_list[i].scan_time = 0; + } + + bgscan_cfg->chan_per_scan = min_t(u32, request->n_channels, + MWIFIEX_BG_SCAN_CHAN_MAX); + + /* Use at least 15 second for per scan cycle */ + bgscan_cfg->scan_interval = (request->scan_plans->interval > + MWIFIEX_BGSCAN_INTERVAL) ? + request->scan_plans->interval : + MWIFIEX_BGSCAN_INTERVAL; + + bgscan_cfg->repeat_count = MWIFIEX_BGSCAN_REPEAT_COUNT; + bgscan_cfg->report_condition = MWIFIEX_BGSCAN_SSID_MATCH | + MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE; + bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA; + bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET; + bgscan_cfg->enable = true; + + if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG, + HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) { + kfree(bgscan_cfg); + return -EFAULT; + } + + priv->sched_scanning = true; + + kfree(bgscan_cfg); + return 0; +} + +/* CFG802.11 operation handler for sched_scan_stop. + * + * This function issues a bgscan config command to disable + * previous bgscan configuration in the firmware + */ +static int mwifiex_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); + + wiphy_info(wiphy, "sched scan stop!"); + mwifiex_stop_bg_scan(priv); + + return 0; +} + static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, struct mwifiex_private *priv) { @@ -2848,6 +2972,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) mwifiex_dev_debugfs_remove(priv); #endif + if (priv->sched_scanning) + priv->sched_scanning = false; + mwifiex_stop_net_dev_queue(priv->netdev, adapter); skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) @@ -3701,6 +3828,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, .set_antenna = mwifiex_cfg80211_set_antenna, .del_station = mwifiex_cfg80211_del_station, + .sched_scan_start = mwifiex_cfg80211_sched_scan_start, + .sched_scan_stop = mwifiex_cfg80211_sched_scan_stop, #ifdef CONFIG_PM .suspend = mwifiex_cfg80211_suspend, .resume = mwifiex_cfg80211_resume, @@ -3829,6 +3958,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_AP_UAPSD | + WIPHY_FLAG_SUPPORTS_SCHED_SCAN | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAS_CHANNEL_SWITCH | WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -3847,6 +3977,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; + wiphy->max_sched_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; + wiphy->max_sched_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; + wiphy->max_match_sets = MWIFIEX_MAX_SSID_LIST_LENGTH; + wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 426e76ade30c..07bdc2a96b8a 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -144,6 +144,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) +#define TLV_TYPE_BGSCAN_START_LATER (PROPRIETARY_TLV_BASE_ID + 30) #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) #define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) #define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) @@ -177,6 +178,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_TX_PAUSE (PROPRIETARY_TLV_BASE_ID + 148) #define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) #define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) +#define TLV_TYPE_REPEAT_COUNT (PROPRIETARY_TLV_BASE_ID + 176) #define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) #define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184) #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) @@ -331,6 +333,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D #define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b #define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e +#define HostCmd_CMD_802_11_BG_SCAN_CONFIG 0x006b #define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c #define HostCmd_CMD_WMM_GET_STATUS 0x0071 #define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 @@ -523,6 +526,7 @@ enum P2P_MODES { #define EVENT_CHANNEL_REPORT_RDY 0x00000054 #define EVENT_TX_DATA_PAUSE 0x00000055 #define EVENT_EXT_SCAN_REPORT 0x00000058 +#define EVENT_BG_SCAN_STOPPED 0x00000065 #define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f #define EVENT_MULTI_CHAN_INFO 0x0000006a #define EVENT_TX_STATUS_REPORT 0x00000074 @@ -733,6 +737,16 @@ struct mwifiex_ie_types_num_probes { __le16 num_probes; } __packed; +struct mwifiex_ie_types_repeat_count { + struct mwifiex_ie_types_header header; + __le16 repeat_count; +} __packed; + +struct mwifiex_ie_types_bgscan_start_later { + struct mwifiex_ie_types_header header; + __le16 start_later; +} __packed; + struct mwifiex_ie_types_scan_chan_gap { struct mwifiex_ie_types_header header; /* time gap in TUs to be used between two consecutive channels scan */ @@ -1425,6 +1439,36 @@ struct mwifiex_user_scan_cfg { u16 scan_chan_gap; } __packed; +#define MWIFIEX_BG_SCAN_CHAN_MAX 38 +#define MWIFIEX_BSS_MODE_INFRA 1 +#define MWIFIEX_BGSCAN_ACT_GET 0x0000 +#define MWIFIEX_BGSCAN_ACT_SET 0x0001 +#define MWIFIEX_BGSCAN_ACT_SET_ALL 0xff01 +/** ssid match */ +#define MWIFIEX_BGSCAN_SSID_MATCH 0x0001 +/** ssid match and RSSI exceeded */ +#define MWIFIEX_BGSCAN_SSID_RSSI_MATCH 0x0004 +/**wait for all channel scan to complete to report scan result*/ +#define MWIFIEX_BGSCAN_WAIT_ALL_CHAN_DONE 0x80000000 + +struct mwifiex_bg_scan_cfg { + u16 action; + u8 enable; + u8 bss_type; + u8 chan_per_scan; + u32 scan_interval; + u32 report_condition; + u8 num_probes; + u8 rssi_threshold; + u8 snr_threshold; + u16 repeat_count; + u16 start_later; + struct cfg80211_match_set *ssid_list; + u8 num_ssids; + struct mwifiex_user_scan_chan chan_list[MWIFIEX_BG_SCAN_CHAN_MAX]; + u16 scan_chan_gap; +} __packed; + struct ie_body { u8 grp_key_oui[4]; u8 ptk_cnt[2]; @@ -1470,6 +1514,20 @@ struct mwifiex_ie_types_bss_scan_info { __le64 tsf; } __packed; +struct host_cmd_ds_802_11_bg_scan_config { + __le16 action; + u8 enable; + u8 bss_type; + u8 chan_per_scan; + u8 reserved; + __le16 reserved1; + __le32 scan_interval; + __le32 reserved2; + __le32 report_condition; + __le16 reserved3; + u8 tlv[0]; +} __packed; + struct host_cmd_ds_802_11_bg_scan_query { u8 flush; } __packed; @@ -2124,6 +2182,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_802_11_scan scan; struct host_cmd_ds_802_11_scan_ext ext_scan; struct host_cmd_ds_802_11_scan_rsp scan_resp; + struct host_cmd_ds_802_11_bg_scan_config bg_scan_config; struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; struct host_cmd_ds_802_11_associate associate; diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 4f0174c64946..6333b163acef 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -414,6 +414,7 @@ struct mwifiex_ds_mef_cfg { #define MWIFIEX_VSIE_MASK_SCAN 0x01 #define MWIFIEX_VSIE_MASK_ASSOC 0x02 #define MWIFIEX_VSIE_MASK_ADHOC 0x04 +#define MWIFIEX_VSIE_MASK_BGSCAN 0x08 enum { MWIFIEX_FUNC_INIT = 1, diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index 79c16de8743e..a99b72bbde51 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -746,6 +746,13 @@ 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; } diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 35ab052c8a36..5f5bcf8b9fc9 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -198,6 +198,11 @@ do { \ buf, len, false); \ } while (0) +/** Min BGSCAN interval 15 second */ +#define MWIFIEX_BGSCAN_INTERVAL 15000 +/** default repeat count */ +#define MWIFIEX_BGSCAN_REPEAT_COUNT 6 + struct mwifiex_dbg { u32 num_cmd_host_to_card_failure; u32 num_cmd_sleep_cfm_host_to_card_failure; @@ -641,6 +646,7 @@ struct mwifiex_private { u32 mgmt_frame_mask; struct mwifiex_roc_cfg roc_cfg; bool scan_aborting; + u8 sched_scanning; u8 csa_chan; unsigned long csa_expire_time; u8 del_list_idx; @@ -1198,6 +1204,10 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, struct host_cmd_ds_command *resp); int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, void *buf); +int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf); +int mwifiex_stop_bg_scan(struct mwifiex_private *priv); /* * This function checks if the queuing is RA based or not. diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index c20017ced566..d4e214385f54 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -547,6 +547,61 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv, return chan_idx; } +/* This function creates a channel list tlv for bgscan config, based + * on region/band information. + */ +static int +mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv, + const struct mwifiex_bg_scan_cfg + *bgscan_cfg_in, + struct mwifiex_chan_scan_param_set + *scan_chan_list) +{ + enum ieee80211_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++) { + if (!priv->wdev.wiphy->bands[band]) + continue; + + sband = priv->wdev.wiphy->bands[band]; + + for (i = 0; (i < sband->n_channels) ; i++) { + ch = &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) + continue; + scan_chan_list[chan_idx].radio_type = band; + + if (bgscan_cfg_in->chan_list[0].scan_time) + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16((u16)bgscan_cfg_in-> + chan_list[0].scan_time); + else if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter->passive_scan_time); + else + scan_chan_list[chan_idx].max_scan_time = + cpu_to_le16(adapter-> + specific_scan_time); + + if (ch->flags & IEEE80211_CHAN_NO_IR) + scan_chan_list[chan_idx].chan_scan_mode_bitmap + |= MWIFIEX_PASSIVE_SCAN; + else + scan_chan_list[chan_idx].chan_scan_mode_bitmap + &= ~MWIFIEX_PASSIVE_SCAN; + + scan_chan_list[chan_idx].chan_number = + (u32)ch->hw_value; + chan_idx++; + } + } + return chan_idx; +} + /* This function appends rate TLV to scan config command. */ static int mwifiex_append_rate_tlv(struct mwifiex_private *priv, @@ -2155,6 +2210,212 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, return 0; } +/* This function prepares an background scan config command to be sent + * to the firmware + */ +int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd, + void *data_buf) +{ + struct host_cmd_ds_802_11_bg_scan_config *bgscan_config = + &cmd->params.bg_scan_config; + struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf; + u8 *tlv_pos = bgscan_config->tlv; + u8 num_probes; + u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num; + int i; + struct mwifiex_ie_types_num_probes *num_probes_tlv; + struct mwifiex_ie_types_repeat_count *repeat_count_tlv; + struct mwifiex_ie_types_bgscan_start_later *start_later_tlv; + struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; + struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv; + struct mwifiex_chan_scan_param_set *temp_chan; + + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG); + cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN); + + bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action); + bgscan_config->enable = bgscan_cfg_in->enable; + bgscan_config->bss_type = bgscan_cfg_in->bss_type; + bgscan_config->scan_interval = + cpu_to_le32(bgscan_cfg_in->scan_interval); + bgscan_config->report_condition = + cpu_to_le32(bgscan_cfg_in->report_condition); + + /* stop sched scan */ + if (!bgscan_config->enable) + return 0; + + bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan; + + num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in-> + num_probes : priv->adapter->scan_probes); + + if (num_probes) { + num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos; + num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); + num_probes_tlv->header.len = + cpu_to_le16(sizeof(num_probes_tlv->num_probes)); + num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes); + + tlv_pos += sizeof(num_probes_tlv->header) + + le16_to_cpu(num_probes_tlv->header.len); + } + + if (bgscan_cfg_in->repeat_count) { + repeat_count_tlv = + (struct mwifiex_ie_types_repeat_count *)tlv_pos; + repeat_count_tlv->header.type = + cpu_to_le16(TLV_TYPE_REPEAT_COUNT); + repeat_count_tlv->header.len = + cpu_to_le16(sizeof(repeat_count_tlv->repeat_count)); + repeat_count_tlv->repeat_count = + cpu_to_le16(bgscan_cfg_in->repeat_count); + + tlv_pos += sizeof(repeat_count_tlv->header) + + le16_to_cpu(repeat_count_tlv->header.len); + } + + for (i = 0; i < bgscan_cfg_in->num_ssids; i++) { + ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len; + + wildcard_ssid_tlv = + (struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos; + wildcard_ssid_tlv->header.type = + cpu_to_le16(TLV_TYPE_WILDCARDSSID); + wildcard_ssid_tlv->header.len = cpu_to_le16( + (u16)(ssid_len + sizeof(wildcard_ssid_tlv-> + max_ssid_length))); + + /* max_ssid_length = 0 tells firmware to perform + * specific scan for the SSID filled, whereas + * max_ssid_length = IEEE80211_MAX_SSID_LEN is for + * wildcard scan. + */ + if (ssid_len) + wildcard_ssid_tlv->max_ssid_length = 0; + else + wildcard_ssid_tlv->max_ssid_length = + IEEE80211_MAX_SSID_LEN; + + memcpy(wildcard_ssid_tlv->ssid, + bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len); + + tlv_pos += (sizeof(wildcard_ssid_tlv->header) + + le16_to_cpu(wildcard_ssid_tlv->header.len)); + } + + chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos; + + if (bgscan_cfg_in->chan_list[0].chan_number) { + dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n"); + + chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); + + for (chan_idx = 0; + chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX && + bgscan_cfg_in->chan_list[chan_idx].chan_number; + chan_idx++) { + temp_chan = chan_list_tlv->chan_scan_param + chan_idx; + + /* Increment the TLV header length by size appended */ + le16_add_cpu(&chan_list_tlv->header.len, + sizeof(chan_list_tlv->chan_scan_param)); + + temp_chan->chan_number = + bgscan_cfg_in->chan_list[chan_idx].chan_number; + temp_chan->radio_type = + bgscan_cfg_in->chan_list[chan_idx].radio_type; + + scan_type = + bgscan_cfg_in->chan_list[chan_idx].scan_type; + + if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) + temp_chan->chan_scan_mode_bitmap + |= MWIFIEX_PASSIVE_SCAN; + else + temp_chan->chan_scan_mode_bitmap + &= ~MWIFIEX_PASSIVE_SCAN; + + if (bgscan_cfg_in->chan_list[chan_idx].scan_time) { + scan_dur = (u16)bgscan_cfg_in-> + chan_list[chan_idx].scan_time; + } else { + scan_dur = (scan_type == + MWIFIEX_SCAN_TYPE_PASSIVE) ? + priv->adapter->passive_scan_time : + priv->adapter->specific_scan_time; + } + + temp_chan->min_scan_time = cpu_to_le16(scan_dur); + temp_chan->max_scan_time = cpu_to_le16(scan_dur); + } + } else { + dev_dbg(priv->adapter->dev, + "info: bgscan: Creating full region channel list\n"); + chan_num = + mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in, + chan_list_tlv-> + chan_scan_param); + le16_add_cpu(&chan_list_tlv->header.len, + chan_num * + sizeof(chan_list_tlv->chan_scan_param[0])); + } + + tlv_pos += (sizeof(chan_list_tlv->header) + + le16_to_cpu(chan_list_tlv->header.len)); + + if (bgscan_cfg_in->start_later) { + start_later_tlv = + (struct mwifiex_ie_types_bgscan_start_later *)tlv_pos; + start_later_tlv->header.type = + cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER); + start_later_tlv->header.len = + cpu_to_le16(sizeof(start_later_tlv->start_later)); + start_later_tlv->start_later = + cpu_to_le16(bgscan_cfg_in->start_later); + + tlv_pos += sizeof(start_later_tlv->header) + + le16_to_cpu(start_later_tlv->header.len); + } + + /* Append vendor specific IE TLV */ + mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos); + + le16_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv); + + return 0; +} + +int mwifiex_stop_bg_scan(struct mwifiex_private *priv) +{ + struct mwifiex_bg_scan_cfg *bgscan_cfg; + + if (!priv->sched_scanning) { + dev_dbg(priv->adapter->dev, "bgscan already stopped!\n"); + return 0; + } + + bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL); + if (!bgscan_cfg) + return -ENOMEM; + + bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA; + bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET; + bgscan_cfg->enable = false; + + if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG, + HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) { + kfree(bgscan_cfg); + return -EFAULT; + } + + kfree(bgscan_cfg); + priv->sched_scanning = false; + + return 0; +} + static void mwifiex_update_chan_statistics(struct mwifiex_private *priv, struct mwifiex_ietypes_chanstats *tlv_stat) diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index e486867a4c67..60f3ded747c9 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1873,6 +1873,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, case HostCmd_CMD_802_11_SCAN: ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf); break; + case HostCmd_CMD_802_11_BG_SCAN_CONFIG: + ret = mwifiex_cmd_802_11_bg_scan_config(priv, cmd_ptr, + data_buf); + break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr); break; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 9ac7aa2431b4..4b23d3b95a20 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1076,9 +1076,12 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, break; case HostCmd_CMD_802_11_BG_SCAN_QUERY: ret = mwifiex_ret_802_11_scan(priv, resp); + cfg80211_sched_scan_results(priv->wdev.wiphy); mwifiex_dbg(adapter, CMD, "info: CMD_RESP: BG_SCAN result is ready!\n"); break; + case HostCmd_CMD_802_11_BG_SCAN_CONFIG: + break; case HostCmd_CMD_TXPWR_CFG: ret = mwifiex_ret_tx_power_cfg(priv, resp); break; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index 23bae87d4d3d..fd8061c73091 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -688,6 +688,13 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) HostCmd_ACT_GEN_GET, 0, NULL, false); break; + case EVENT_BG_SCAN_STOPPED: + dev_dbg(adapter->dev, "event: BGS_STOPPED\n"); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + if (priv->sched_scanning) + priv->sched_scanning = false; + break; + case EVENT_PORT_RELEASE: mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n"); priv->port_open = true; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 210b257aad6b..2cc1a32691bd 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -504,6 +504,13 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) } } + priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + if (priv && priv->sched_scanning) { + dev_dbg(adapter->dev, "aborting bgscan!\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); + } + if (adapter->hs_activated) { mwifiex_dbg(adapter, CMD, "cmd: HS Already activated\n"); -- cgit From 5323b53d80fc17604b2c60b725af116827330b2c Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 13 Jan 2016 01:26:53 -0800 Subject: mwifiex: add wowlan info messages This patch adds informative messages in wake up on magic packet, disconnect, pattern configuration paths. Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index c27c6cc5f93e..6d36d081e953 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3171,10 +3171,12 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, sizeof(byte_seq)); mef_entry->filter[filt_num].filt_type = TYPE_EQ; - if (first_pat) + if (first_pat) { first_pat = false; - else + mwifiex_dbg(priv->adapter, INFO, "Wake on patterns\n"); + } else { mef_entry->filter[filt_num].filt_action = TYPE_AND; + } filt_num++; } @@ -3200,6 +3202,7 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, mef_entry->filter[filt_num].offset = 56; mef_entry->filter[filt_num].filt_type = TYPE_EQ; mef_entry->filter[filt_num].filt_action = TYPE_OR; + mwifiex_dbg(priv->adapter, INFO, "Wake on magic packet\n"); } return ret; } @@ -3295,6 +3298,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, "Failed to set HS params\n"); return ret; } + mwifiex_dbg(priv->adapter, INFO, "Wake on device disconnect\n"); } return ret; -- cgit From 7d7f07d8c5d35ebfb207650b0dbcf437dad76bab Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 13 Jan 2016 01:26:54 -0800 Subject: mwifiex: add wowlan net-detect support This patch adds support for wakeup when configured network is detected. Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Xinming Hu Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 40 +++++++++++++++--------- drivers/net/wireless/marvell/mwifiex/fw.h | 2 ++ drivers/net/wireless/marvell/mwifiex/main.c | 7 +++++ drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/scan.c | 34 ++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 13 ++++++-- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 6d36d081e953..a1b8d89d399f 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3273,7 +3273,7 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); - if (!priv->media_connected) { + if (!priv->media_connected && !wowlan->nd_config) { mwifiex_dbg(adapter, ERROR, "Can not configure WOWLAN in disconnected state\n"); return 0; @@ -3285,22 +3285,32 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, return ret; } + memset(&hs_cfg, 0, sizeof(hs_cfg)); + hs_cfg.conditions = le32_to_cpu(adapter->hs_cfg.conditions); + + if (wowlan->nd_config) { + mwifiex_dbg(adapter, INFO, "Wake on net detect\n"); + hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT; + mwifiex_cfg80211_sched_scan_start(wiphy, priv->netdev, + wowlan->nd_config); + } + if (wowlan->disconnect) { - memset(&hs_cfg, 0, sizeof(hs_cfg)); - hs_cfg.is_invoke_hostcmd = false; - hs_cfg.conditions = HS_CFG_COND_MAC_EVENT; - hs_cfg.gpio = adapter->hs_cfg.gpio; - hs_cfg.gap = adapter->hs_cfg.gap; - ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - MWIFIEX_SYNC_CMD, &hs_cfg); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "Failed to set HS params\n"); - return ret; - } + hs_cfg.conditions |= HS_CFG_COND_MAC_EVENT; mwifiex_dbg(priv->adapter, INFO, "Wake on device disconnect\n"); } + hs_cfg.is_invoke_hostcmd = false; + hs_cfg.gpio = adapter->hs_cfg.gpio; + hs_cfg.gap = adapter->hs_cfg.gap; + ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, + MWIFIEX_SYNC_CMD, &hs_cfg); + if (ret) { + mwifiex_dbg(adapter, ERROR, + "Failed to set HS params\n"); + return ret; + } + return ret; } @@ -3853,11 +3863,13 @@ 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, + .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_NET_DETECT, .n_patterns = MWIFIEX_MEF_MAX_FILTERS, .pattern_min_len = 1, .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, + .max_nd_match_sets = MWIFIEX_MAX_ND_MATCH_SETS, }; #endif diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 07bdc2a96b8a..81b491aac343 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -543,6 +543,8 @@ enum P2P_MODES { #define MWIFIEX_MAX_PATTERN_LEN 40 #define MWIFIEX_MAX_OFFSET_LEN 100 +#define MWIFIEX_MAX_ND_MATCH_SETS 10 + #define STACK_NBYTES 100 #define TYPE_DNUM 1 #define TYPE_BYTESEQ 2 diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index a99b72bbde51..3cfa94677a8e 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -132,6 +132,13 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) } } + if (adapter->nd_info) { + for (i = 0 ; i < adapter->nd_info->n_matches ; i++) + kfree(adapter->nd_info->matches[i]); + kfree(adapter->nd_info); + adapter->nd_info = NULL; + } + vfree(adapter->chan_stats); kfree(adapter); return 0; diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 5f5bcf8b9fc9..bf9b24ae46fc 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1002,6 +1002,7 @@ struct mwifiex_adapter { u8 active_scan_triggered; bool usb_mc_status; bool usb_mc_setup; + struct cfg80211_wowlan_nd_info *nd_info; }; void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index d4e214385f54..2702bd93f74d 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2092,6 +2092,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, u8 is_bgscan_resp; __le64 fw_tsf = 0; u8 *radio_type; + struct cfg80211_wowlan_nd_match *pmatch; + struct cfg80211_sched_scan_request *nd_config = NULL; is_bgscan_resp = (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_BG_SCAN_QUERY); @@ -2154,6 +2156,21 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, (struct mwifiex_ie_types_data **) &chan_band_tlv); +#ifdef CONFIG_PM + if (priv->wdev.wiphy->wowlan_config) + nd_config = priv->wdev.wiphy->wowlan_config->nd_config; +#endif + + if (nd_config) { + adapter->nd_info = + kzalloc(sizeof(struct cfg80211_wowlan_nd_match) + + sizeof(struct cfg80211_wowlan_nd_match *) * + scan_rsp->number_of_sets, GFP_ATOMIC); + + if (adapter->nd_info) + adapter->nd_info->n_matches = scan_rsp->number_of_sets; + } + for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { /* * If the TSF TLV was appended to the scan results, save this @@ -2172,6 +2189,23 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, radio_type = NULL; } + if (chan_band_tlv && adapter->nd_info) { + adapter->nd_info->matches[idx] = + kzalloc(sizeof(*pmatch) + + sizeof(u32), GFP_ATOMIC); + + pmatch = adapter->nd_info->matches[idx]; + + if (!pmatch) { + memset(pmatch, 0, sizeof(*pmatch)); + if (chan_band_tlv) { + pmatch->n_channels = 1; + pmatch->channels[0] = + chan_band->chan_number; + } + } + } + ret = mwifiex_parse_single_response_buf(priv, &bss_info, &bytes_left, le64_to_cpu(fw_tsf), diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 2cc1a32691bd..7277c24ee9aa 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -505,10 +505,17 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) } priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + if (priv && priv->sched_scanning) { - dev_dbg(adapter->dev, "aborting bgscan!\n"); - mwifiex_stop_bg_scan(priv); - cfg80211_sched_scan_stopped(priv->wdev.wiphy); +#ifdef CONFIG_PM + if (!priv->wdev.wiphy->wowlan_config->nd_config) { +#endif + mwifiex_dbg(adapter, CMD, "aborting bgscan!\n"); + mwifiex_stop_bg_scan(priv); + cfg80211_sched_scan_stopped(priv->wdev.wiphy); +#ifdef CONFIG_PM + } +#endif } if (adapter->hs_activated) { -- cgit From 8de00f1b1c7f37e523430efba8e4257b2761df7c Mon Sep 17 00:00:00 2001 From: chunfan chen Date: Wed, 13 Jan 2016 01:26:55 -0800 Subject: mwifiex: report wakeup reason to cfg80211 This patch adds code to report wakeup reason to cfg80211 when system is resumed. Signed-off-by: chunfan chen Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 58 ++++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/cmdevt.c | 13 +++++ drivers/net/wireless/marvell/mwifiex/fw.h | 20 ++++++++ drivers/net/wireless/marvell/mwifiex/ioctl.h | 4 ++ drivers/net/wireless/marvell/mwifiex/main.h | 6 +++ drivers/net/wireless/marvell/mwifiex/sta_cmd.c | 19 +++++++ drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c | 3 ++ drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 16 ++++++ 8 files changed, 139 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index a1b8d89d399f..c80d9e2daa16 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3316,6 +3316,64 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, static int mwifiex_cfg80211_resume(struct wiphy *wiphy) { + struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv = + mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); + struct mwifiex_ds_wakeup_reason wakeup_reason; + struct cfg80211_wowlan_wakeup wakeup_report; + int i; + + mwifiex_get_wakeup_reason(priv, HostCmd_ACT_GEN_GET, MWIFIEX_SYNC_CMD, + &wakeup_reason); + memset(&wakeup_report, 0, sizeof(struct cfg80211_wowlan_wakeup)); + + wakeup_report.pattern_idx = -1; + + switch (wakeup_reason.hs_wakeup_reason) { + case NO_HSWAKEUP_REASON: + break; + case BCAST_DATA_MATCHED: + break; + case MCAST_DATA_MATCHED: + break; + case UCAST_DATA_MATCHED: + break; + case MASKTABLE_EVENT_MATCHED: + break; + case NON_MASKABLE_EVENT_MATCHED: + if (wiphy->wowlan_config->disconnect) + wakeup_report.disconnect = true; + if (wiphy->wowlan_config->nd_config) + wakeup_report.net_detect = adapter->nd_info; + break; + case NON_MASKABLE_CONDITION_MATCHED: + break; + case MAGIC_PATTERN_MATCHED: + if (wiphy->wowlan_config->magic_pkt) + wakeup_report.magic_pkt = true; + if (wiphy->wowlan_config->n_patterns) + wakeup_report.pattern_idx = 1; + break; + case CONTROL_FRAME_MATCHED: + break; + case MANAGEMENT_FRAME_MATCHED: + break; + default: + break; + } + + if ((wakeup_reason.hs_wakeup_reason > 0) && + (wakeup_reason.hs_wakeup_reason <= 7)) + cfg80211_report_wowlan_wakeup(&priv->wdev, &wakeup_report, + GFP_KERNEL); + + if (adapter->nd_info) { + for (i = 0 ; i < adapter->nd_info->n_matches ; i++) + kfree(adapter->nd_info->matches[i]); + kfree(adapter->nd_info); + adapter->nd_info = NULL; + } + return 0; } diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c index cb25aa7e90db..a12adee776c6 100644 --- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c +++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c @@ -1657,3 +1657,16 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, return 0; } + +/* This function handles the command response of hs wakeup reason + * command. + */ +int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + struct host_cmd_ds_wakeup_reason *wakeup_reason) +{ + wakeup_reason->wakeup_reason = + resp->params.hs_wakeup_reason.wakeup_reason; + + return 0; +} diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 81b491aac343..d293e485189b 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -373,6 +373,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_MGMT_FRAME_REG 0x010c #define HostCmd_CMD_REMAIN_ON_CHAN 0x010d #define HostCmd_CMD_11AC_CFG 0x0112 +#define HostCmd_CMD_HS_WAKEUP_REASON 0x0116 #define HostCmd_CMD_TDLS_CONFIG 0x0100 #define HostCmd_CMD_MC_POLICY 0x0121 #define HostCmd_CMD_TDLS_OPER 0x0122 @@ -607,6 +608,20 @@ struct mwifiex_ie_types_data { #define MWIFIEX_RXPD_FLAGS_TDLS_PACKET 0x01 #define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS 0x20 +enum HS_WAKEUP_REASON { + NO_HSWAKEUP_REASON = 0, + BCAST_DATA_MATCHED, + MCAST_DATA_MATCHED, + UCAST_DATA_MATCHED, + MASKTABLE_EVENT_MATCHED, + NON_MASKABLE_EVENT_MATCHED, + NON_MASKABLE_CONDITION_MATCHED, + MAGIC_PATTERN_MATCHED, + CONTROL_FRAME_MATCHED, + MANAGEMENT_FRAME_MATCHED, + RESERVED +}; + struct txpd { u8 bss_type; u8 bss_num; @@ -2159,6 +2174,10 @@ struct host_cmd_ds_robust_coex { __le16 reserved; } __packed; +struct host_cmd_ds_wakeup_reason { + u16 wakeup_reason; +} __packed; + struct host_cmd_ds_command { __le16 command; __le16 size; @@ -2231,6 +2250,7 @@ struct host_cmd_ds_command { struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; 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; } params; } __packed; diff --git a/drivers/net/wireless/marvell/mwifiex/ioctl.h b/drivers/net/wireless/marvell/mwifiex/ioctl.h index 6333b163acef..14cfa37deb00 100644 --- a/drivers/net/wireless/marvell/mwifiex/ioctl.h +++ b/drivers/net/wireless/marvell/mwifiex/ioctl.h @@ -271,6 +271,10 @@ struct mwifiex_ds_hs_cfg { u32 gap; }; +struct mwifiex_ds_wakeup_reason { + u16 hs_wakeup_reason; +}; + #define DEEP_SLEEP_ON 1 #define DEEP_SLEEP_OFF 0 #define DEEP_SLEEP_IDLE_TIME 100 diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index bf9b24ae46fc..c755be54cc83 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -1599,6 +1599,12 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter); void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter); void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); +int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, + int cmd_type, + struct mwifiex_ds_wakeup_reason *wakeup_reason); +int mwifiex_ret_wakeup_reason(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + struct host_cmd_ds_wakeup_reason *wakeup_reason); void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter); void mwifiex_11n_delba(struct mwifiex_private *priv, int tid); int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c index 60f3ded747c9..30f152601c57 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c @@ -1813,6 +1813,22 @@ static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd, return 0; } +/* This function prepares command to get HS wakeup reason. + * + * Preparation includes - + * - Setting command ID, action and proper size + * - Ensuring correct endian-ness + */ +static int mwifiex_cmd_get_wakeup_reason(struct mwifiex_private *priv, + struct host_cmd_ds_command *cmd) +{ + cmd->command = cpu_to_le16(HostCmd_CMD_HS_WAKEUP_REASON); + cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_wakeup_reason) + + S_DS_GEN); + + return 0; +} + /* * This function prepares the commands before sending them to the firmware. * @@ -2067,6 +2083,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, data_buf); break; + case HostCmd_CMD_HS_WAKEUP_REASON: + ret = mwifiex_cmd_get_wakeup_reason(priv, cmd_ptr); + break; case HostCmd_CMD_MC_POLICY: ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action, data_buf); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 4b23d3b95a20..d96523e10eb4 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -1236,6 +1236,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp); break; + case HostCmd_CMD_HS_WAKEUP_REASON: + ret = mwifiex_ret_wakeup_reason(priv, resp, data_buf); + break; case HostCmd_CMD_TDLS_CONFIG: break; case HostCmd_CMD_ROBUST_COEX: diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 7277c24ee9aa..5cbee58f8781 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1465,3 +1465,19 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len) return 0; } + +/* This function get Host Sleep wake up reason. + * + */ +int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action, + int cmd_type, + struct mwifiex_ds_wakeup_reason *wakeup_reason) +{ + int status = 0; + + status = mwifiex_send_cmd(priv, HostCmd_CMD_HS_WAKEUP_REASON, + HostCmd_ACT_GEN_GET, 0, wakeup_reason, + cmd_type == MWIFIEX_SYNC_CMD); + + return status; +} -- cgit From fdcab083055d759325c8e0f8999d9e192417fc20 Mon Sep 17 00:00:00 2001 From: Ganapathi Bhat Date: Wed, 13 Jan 2016 01:26:56 -0800 Subject: mwifiex: add RSSI support for net-detect This patch adds support for waking up the device on finding better RSSI. Threshold RSSI value will be configured by application. Signed-off-by: Ganapathi Bhat Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 ++++ drivers/net/wireless/marvell/mwifiex/fw.h | 5 +++++ drivers/net/wireless/marvell/mwifiex/scan.c | 15 +++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index c80d9e2daa16..84615533986c 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -2582,6 +2582,10 @@ mwifiex_cfg80211_sched_scan_start(struct wiphy *wiphy, bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA; bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET; bgscan_cfg->enable = true; + if (request->min_rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) { + bgscan_cfg->report_condition |= MWIFIEX_BGSCAN_SSID_RSSI_MATCH; + bgscan_cfg->rssi_threshold = request->min_rssi_thold; + } if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG, HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) { diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index d293e485189b..4af916817bcd 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -759,6 +759,11 @@ struct mwifiex_ie_types_repeat_count { __le16 repeat_count; } __packed; +struct mwifiex_ie_types_min_rssi_threshold { + struct mwifiex_ie_types_header header; + __le16 rssi_threshold; +} __packed; + struct mwifiex_ie_types_bgscan_start_later { struct mwifiex_ie_types_header header; __le16 start_later; diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 2702bd93f74d..fc8d8ca67453 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2260,6 +2260,7 @@ int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, int i; struct mwifiex_ie_types_num_probes *num_probes_tlv; struct mwifiex_ie_types_repeat_count *repeat_count_tlv; + struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv; struct mwifiex_ie_types_bgscan_start_later *start_later_tlv; struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv; @@ -2310,6 +2311,20 @@ int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv, le16_to_cpu(repeat_count_tlv->header.len); } + if (bgscan_cfg_in->rssi_threshold) { + rssi_threshold_tlv = + (struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos; + rssi_threshold_tlv->header.type = + cpu_to_le16(TLV_TYPE_RSSI_LOW); + rssi_threshold_tlv->header.len = + cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold)); + rssi_threshold_tlv->rssi_threshold = + cpu_to_le16(bgscan_cfg_in->rssi_threshold); + + tlv_pos += sizeof(rssi_threshold_tlv->header) + + le16_to_cpu(rssi_threshold_tlv->header.len); + } + for (i = 0; i < bgscan_cfg_in->num_ssids; i++) { ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len; -- cgit From a92277bc3bfe7c41cac13ca4a7d5070033543732 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Wed, 13 Jan 2016 01:26:57 -0800 Subject: mwifiex: use SYNC flag for canceling host sleep Host sleep is cancelled in sdio resume() handler. Cfg80211's resume handler is immediately called after this. SYNC flag here ensures that host sleep handshake gets completed and we have valid "adapter->nd_config" before we report host wakeup reason in cfg80211's resume handler. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c index 33771d3fd843..abf15dbdfe08 100644 --- a/drivers/net/wireless/marvell/mwifiex/sdio.c +++ b/drivers/net/wireless/marvell/mwifiex/sdio.c @@ -181,7 +181,7 @@ static int mwifiex_sdio_resume(struct device *dev) /* Disable Host Sleep */ mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); + MWIFIEX_SYNC_CMD); return 0; } -- cgit From 4e26ad80cbd3a6b0d606201892e81a9a9c6864ce Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Fri, 29 Jan 2016 01:47:12 +0000 Subject: ASoC: rt5616: Add support sample rate to 192KHz Reference the TRM, the ALC5616 support one 24bit/8KHz ~ 192KHz I2S/PCM Interface for stereo DAC and stereo ADC. Signed-off-by: Xing Zheng Signed-off-by: Mark Brown --- sound/soc/codecs/rt5616.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index fdca63694b40..3704d0716c04 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1261,7 +1261,7 @@ static int rt5616_resume(struct snd_soc_codec *codec) #define rt5616_resume NULL #endif -#define RT5616_STEREO_RATES SNDRV_PCM_RATE_8000_96000 +#define RT5616_STEREO_RATES SNDRV_PCM_RATE_8000_192000 #define RT5616_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -- cgit From 4f57d27be2a5a10ad042fcfd97c5ea9f4d5215f7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Jan 2016 10:46:23 -0200 Subject: [media] tvp5150: fix tvp5150_fill_fmt() The tvp5150 output video is interlaced so mark the format field as alternate and reduce the height to the half. [javier: split patch and write commit message] Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/tvp5150.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 437f1a7ecb96..c277caaad8be 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -852,10 +852,10 @@ static int tvp5150_fill_fmt(struct v4l2_subdev *sd, tvp5150_reset(sd, 0); f->width = decoder->rect.width; - f->height = decoder->rect.height; + f->height = decoder->rect.height / 2; f->code = MEDIA_BUS_FMT_UYVY8_2X8; - f->field = V4L2_FIELD_SEQ_TB; + f->field = V4L2_FIELD_ALTERNATE; f->colorspace = V4L2_COLORSPACE_SMPTE170M; v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width, -- cgit From e545ac872ff884801a48beb7e6e0fc7513555fd9 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 26 Jan 2016 10:46:24 -0200 Subject: [media] tvp5150: Add pad-level subdev operations This patch enables the tvp5150 decoder driver to be used with the media controller framework by adding pad-level subdev operations and init the media entity pad. Signed-off-by: Laurent Pinchart Signed-off-by: Javier Martinez Canillas --- drivers/media/i2c/tvp5150.c | 53 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index c277caaad8be..0ad122fcd632 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -37,6 +37,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; + struct media_pad pad; struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -826,17 +827,6 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) } } -static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) -{ - if (code->pad || code->index) - return -EINVAL; - - code->code = MEDIA_BUS_FMT_UYVY8_2X8; - return 0; -} - static int tvp5150_fill_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -968,6 +958,38 @@ static int tvp5150_g_mbus_config(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + V4L2 subdev pad ops + ****************************************************************************/ +static int tvp5150_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->pad || code->index) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_UYVY8_2X8; + return 0; +} + +static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct tvp5150 *decoder = to_tvp5150(sd); + + if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_UYVY8_2X8) + return -EINVAL; + + fse->code = MEDIA_BUS_FMT_UYVY8_2X8; + fse->min_width = decoder->rect.width; + fse->max_width = decoder->rect.width; + fse->min_height = decoder->rect.height / 2; + fse->max_height = decoder->rect.height / 2; + + return 0; +} + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1132,6 +1154,7 @@ static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { static const struct v4l2_subdev_pad_ops tvp5150_pad_ops = { .enum_mbus_code = tvp5150_enum_mbus_code, + .enum_frame_size = tvp5150_enum_frame_size, .set_fmt = tvp5150_fill_fmt, .get_fmt = tvp5150_fill_fmt, }; @@ -1287,6 +1310,14 @@ static int tvp5150_probe(struct i2c_client *c, } v4l2_i2c_subdev_init(sd, c, &tvp5150_ops); + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + +#if defined(CONFIG_MEDIA_CONTROLLER) + core->pad.flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_pads_init(&sd->entity, 1, &core->pad); + if (res < 0) + return res; +#endif res = tvp5150_detect_version(core); if (res < 0) -- cgit From 31889507fd84a6a1c8dce36a214a070cec1fc559 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Jan 2016 17:53:00 +0000 Subject: ASoC: wm5110: Add support for audio trace firmware Mainly this adds DAI links for the audio trace, however, it is also necessary to update the data IRQ handler to check more cores. We have the handler check every core so it should not be necessary to update this function if more compressed firmwares are added in the future. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.h | 2 +- sound/soc/codecs/wm5110.c | 43 +++++++++++++++++++++++++++++++++++++++---- sound/soc/codecs/wm_adsp.c | 1 - 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 8b6adb5419bb..0c64a5731513 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -57,7 +57,7 @@ #define ARIZONA_CLK_98MHZ 5 #define ARIZONA_CLK_147MHZ 6 -#define ARIZONA_MAX_DAI 8 +#define ARIZONA_MAX_DAI 10 #define ARIZONA_MAX_ADSP 4 #define ARIZONA_DVFS_SR1_RQ 0x001 diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index b47bc4418e30..92b6a6a564df 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -1828,6 +1828,9 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { { "Voice Control DSP", NULL, "DSP3" }, { "Voice Control DSP", NULL, "SYSCLK" }, + { "Audio Trace DSP", NULL, "DSP1" }, + { "Audio Trace DSP", NULL, "SYSCLK" }, + { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -2171,6 +2174,27 @@ static struct snd_soc_dai_driver wm5110_dai[] = { .formats = WM5110_FORMATS, }, }, + { + .name = "wm5110-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + .compress_new = snd_soc_new_compress, + }, + { + .name = "wm5110-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 6, + .rates = WM5110_RATES, + .formats = WM5110_FORMATS, + }, + }, }; static int wm5110_open(struct snd_compr_stream *stream) @@ -2182,6 +2206,8 @@ static int wm5110_open(struct snd_compr_stream *stream) if (strcmp(rtd->codec_dai->name, "wm5110-dsp-voicectrl") == 0) { n_adsp = 2; + } else if (strcmp(rtd->codec_dai->name, "wm5110-dsp-trace") == 0) { + n_adsp = 0; } else { dev_err(arizona->dev, "No suitable compressed stream for DAI '%s'\n", @@ -2194,12 +2220,21 @@ static int wm5110_open(struct snd_compr_stream *stream) static irqreturn_t wm5110_adsp2_irq(int irq, void *data) { - struct wm5110_priv *florida = data; - int ret; + struct wm5110_priv *priv = data; + struct arizona *arizona = priv->core.arizona; + int serviced = 0; + int i, ret; + + for (i = 0; i < WM5110_NUM_ADSP; ++i) { + ret = wm_adsp_compr_handle_irq(&priv->core.adsp[i]); + if (ret != -ENODEV) + serviced++; + } - ret = wm_adsp_compr_handle_irq(&florida->core.adsp[2]); - if (ret == -ENODEV) + if (!serviced) { + dev_err(arizona->dev, "Spurious compressed data IRQ\n"); return IRQ_NONE; + } return IRQ_HANDLED; } diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 76ab52d2c670..653dbff81fee 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2823,7 +2823,6 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp) mutex_lock(&dsp->pwr_lock); if (!buf) { - adsp_err(dsp, "Spurious buffer IRQ\n"); ret = -ENODEV; goto out; } -- cgit From 69fa80584f69554275ef1257d41b90f4e0d417fc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 21 Jan 2016 17:53:01 +0000 Subject: ASoC: wm5102: Add support for the audio trace firmware wm5102 also supports the audio trace firmware, this patch adds support for this into the wm5102 driver. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 7c0860df3204..aa1e96ab4bd2 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1599,6 +1599,9 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { { "Slim2 Capture", NULL, "SYSCLK" }, { "Slim3 Capture", NULL, "SYSCLK" }, + { "Audio Trace DSP", NULL, "DSP1" }, + { "Audio Trace DSP", NULL, "SYSCLK" }, + { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -1864,14 +1867,67 @@ static struct snd_soc_dai_driver wm5102_dai[] = { }, .ops = &arizona_simple_dai_ops, }, + { + .name = "wm5102-cpu-trace", + .capture = { + .stream_name = "Audio Trace CPU", + .channels_min = 1, + .channels_max = 6, + .rates = WM5102_RATES, + .formats = WM5102_FORMATS, + }, + .compress_new = snd_soc_new_compress, + }, + { + .name = "wm5102-dsp-trace", + .capture = { + .stream_name = "Audio Trace DSP", + .channels_min = 1, + .channels_max = 4, + .rates = WM5102_RATES, + .formats = WM5102_FORMATS, + }, + }, }; +static int wm5102_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct wm5102_priv *priv = snd_soc_codec_get_drvdata(rtd->codec); + + return wm_adsp_compr_open(&priv->core.adsp[0], stream); +} + +static irqreturn_t wm5102_adsp2_irq(int irq, void *data) +{ + struct wm5102_priv *priv = data; + struct arizona *arizona = priv->core.arizona; + int ret; + + ret = wm_adsp_compr_handle_irq(&priv->core.adsp[0]); + if (ret == -ENODEV) { + dev_err(arizona->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + static int wm5102_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); + struct arizona *arizona = priv->core.arizona; int ret; + ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", wm5102_adsp2_irq, + priv); + if (ret != 0) { + dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret); + return ret; + } + ret = wm_adsp2_codec_probe(&priv->core.adsp[0], codec); if (ret) return ret; @@ -1946,6 +2002,20 @@ static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { .num_dapm_routes = ARRAY_SIZE(wm5102_dapm_routes), }; +static struct snd_compr_ops wm5102_compr_ops = { + .open = wm5102_open, + .free = wm_adsp_compr_free, + .set_params = wm_adsp_compr_set_params, + .get_caps = wm_adsp_compr_get_caps, + .trigger = wm_adsp_compr_trigger, + .pointer = wm_adsp_compr_pointer, + .copy = wm_adsp_compr_copy, +}; + +static struct snd_soc_platform_driver wm5102_compr_platform = { + .compr_ops = &wm5102_compr_ops, +}; + static int wm5102_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); @@ -2005,12 +2075,25 @@ static int wm5102_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_idle(&pdev->dev); - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102, + ret = snd_soc_register_platform(&pdev->dev, &wm5102_compr_platform); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register platform: %d\n", ret); + return ret; + } + + ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm5102, wm5102_dai, ARRAY_SIZE(wm5102_dai)); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register codec: %d\n", ret); + snd_soc_unregister_platform(&pdev->dev); + } + + return ret; } static int wm5102_remove(struct platform_device *pdev) { + snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_codec(&pdev->dev); pm_runtime_disable(&pdev->dev); -- cgit From 7eec55d7a2f2932b3b4a799bc5d0d6718e1ee9e2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Fri, 22 Jan 2016 13:49:59 +0000 Subject: ASoC: cs47l24: Add voice control compressed stream This patch adds firmware compressed stream capture support and DAI hookups for voice control firmware (based on the wm5110 implementation.) Signed-off-by: Richard Fitzgerald Signed-off-by: Mark Brown --- sound/soc/codecs/cs47l24.c | 98 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index 9dc77a4da35d..b8d3cd031d7d 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -798,6 +798,9 @@ static const struct snd_soc_dapm_route cs47l24_dapm_routes[] = { { "AIF2 Capture", NULL, "SYSCLK" }, { "AIF3 Capture", NULL, "SYSCLK" }, + { "Voice Control DSP", NULL, "DSP3" }, + { "Voice Control DSP", NULL, "SYSCLK" }, + { "IN1L PGA", NULL, "IN1L" }, { "IN1R PGA", NULL, "IN1R" }, @@ -992,12 +995,68 @@ static struct snd_soc_dai_driver cs47l24_dai[] = { .symmetric_rates = 1, .symmetric_samplebits = 1, }, + { + .name = "cs47l24-cpu-voicectrl", + .capture = { + .stream_name = "Voice Control CPU", + .channels_min = 1, + .channels_max = 1, + .rates = CS47L24_RATES, + .formats = CS47L24_FORMATS, + }, + .compress_new = snd_soc_new_compress, + }, + { + .name = "cs47l24-dsp-voicectrl", + .capture = { + .stream_name = "Voice Control DSP", + .channels_min = 1, + .channels_max = 1, + .rates = CS47L24_RATES, + .formats = CS47L24_FORMATS, + }, + }, }; +static int cs47l24_open(struct snd_compr_stream *stream) +{ + struct snd_soc_pcm_runtime *rtd = stream->private_data; + struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(rtd->codec); + struct arizona *arizona = priv->core.arizona; + int n_adsp; + + if (strcmp(rtd->codec_dai->name, "cs47l24-dsp-voicectrl") == 0) { + n_adsp = 2; + } else { + dev_err(arizona->dev, + "No suitable compressed stream for DAI '%s'\n", + rtd->codec_dai->name); + return -EINVAL; + } + + return wm_adsp_compr_open(&priv->core.adsp[n_adsp], stream); +} + +static irqreturn_t cs47l24_adsp2_irq(int irq, void *data) +{ + struct cs47l24_priv *priv = data; + struct arizona *arizona = priv->core.arizona; + int ret; + + ret = wm_adsp_compr_handle_irq(&priv->core.adsp[2]); + if (ret == -ENODEV) { + dev_err(arizona->dev, "Spurious compressed data IRQ\n"); + return IRQ_NONE; + } + + return IRQ_HANDLED; +} + static int cs47l24_codec_probe(struct snd_soc_codec *codec) { struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec); + struct arizona *arizona = priv->core.arizona; int ret; priv->core.arizona->dapm = dapm; @@ -1006,6 +1065,14 @@ static int cs47l24_codec_probe(struct snd_soc_codec *codec) arizona_init_gpio(codec); arizona_init_mono(codec); + ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", cs47l24_adsp2_irq, + priv); + if (ret != 0) { + dev_err(codec->dev, "Failed to request DSP IRQ: %d\n", ret); + return ret; + } + ret = wm_adsp2_codec_probe(&priv->core.adsp[1], codec); if (ret) goto err_adsp2_codec_probe; @@ -1033,13 +1100,14 @@ err_adsp2_codec_probe: static int cs47l24_codec_remove(struct snd_soc_codec *codec) { struct cs47l24_priv *priv = snd_soc_codec_get_drvdata(codec); - + struct arizona *arizona = priv->core.arizona; wm_adsp2_codec_remove(&priv->core.adsp[1], codec); wm_adsp2_codec_remove(&priv->core.adsp[2], codec); priv->core.arizona->dapm = NULL; + arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, priv); return 0; } @@ -1076,6 +1144,19 @@ static struct snd_soc_codec_driver soc_codec_dev_cs47l24 = { .num_dapm_routes = ARRAY_SIZE(cs47l24_dapm_routes), }; +static struct snd_compr_ops cs47l24_compr_ops = { + .open = cs47l24_open, + .free = wm_adsp_compr_free, + .set_params = wm_adsp_compr_set_params, + .get_caps = wm_adsp_compr_get_caps, + .trigger = wm_adsp_compr_trigger, + .pointer = wm_adsp_compr_pointer, + .copy = wm_adsp_compr_copy, +}; + +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); @@ -1139,12 +1220,25 @@ static int cs47l24_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_idle(&pdev->dev); - return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_cs47l24, + ret = snd_soc_register_platform(&pdev->dev, &cs47l24_compr_platform); + if (ret < 0) { + 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); + } + + return ret; } static int cs47l24_remove(struct platform_device *pdev) { + snd_soc_unregister_platform(&pdev->dev); snd_soc_unregister_codec(&pdev->dev); pm_runtime_disable(&pdev->dev); -- cgit From a382c30c662a31dd8f51cc4b6dad82d39205d50c Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Fri, 29 Jan 2016 22:38:07 +0900 Subject: HID: quirks: Add no_init_reports for AKAI midi controller The midi controller times-out while initializing reports, this causes boot to take an extra 10 seconds. The device descriptor advertises that it has an internal HID device but seems to not actually do anything useful. Signed-off-by: Stafford Horne Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index bfd2c9d834d0..953257b390c3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -61,6 +61,9 @@ #define USB_VENDOR_ID_AIREN 0x1a2c #define USB_DEVICE_ID_AIREN_SLIMPLUS 0x0002 +#define USB_VENDOR_ID_AKAI 0x2011 +#define USB_DEVICE_ID_AKAI_MPKMINI2 0x0715 + #define USB_VENDOR_ID_ALCOR 0x058f #define USB_DEVICE_ID_ALCOR_USBRS232 0x9720 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 6f0db54c4a9f..cb8cbdd07c4e 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -55,6 +55,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET }, -- cgit From 313726cad3b68039c8e4dcad5a2840a0d375678c Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 28 Jan 2016 18:23:41 +0100 Subject: HID: dragonrise: fix a typo in descriptors comments s/Joystik/Joystick/ Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-dr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index 1d78ba3b799e..8fd4bf77f264 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -151,7 +151,7 @@ static inline int drff_init(struct hid_device *hid) * descriptor. In any case, it's a wonder it works on Windows. * * Usage Page (Desktop), ; Generic desktop controls (01h) - * Usage (Joystik), ; Joystik (04h, application collection) + * Usage (Joystick), ; Joystick (04h, application collection) * Collection (Application), * Collection (Logical), * Report Size (8), @@ -207,7 +207,7 @@ static inline int drff_init(struct hid_device *hid) /* Fixed report descriptor for PID 0x011 joystick */ static __u8 pid0011_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x04, /* Usage (Joystik), */ + 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x14, /* Logical Minimum (0), */ -- cgit From d542176f94c790016cc340dff74ba00d57410728 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 28 Jan 2016 18:23:43 +0100 Subject: HID: sony: fix a typo in descriptors comments s/Joystik/Joystick/ Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 9b8db0e0ef1c..0b5015fd864a 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -251,7 +251,7 @@ static __u8 motion_rdesc[] = { /* PS/3 Navigation controller */ static __u8 navigation_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x04, /* Usage (Joystik), */ + 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x01, /* Report ID (1), */ -- cgit From 5a155bb77a673dda941121142d686c3f47b49981 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 29 Jan 2016 05:57:30 +0000 Subject: perf build: Remove all condition feature check {C,LD}FLAGS 'make feature-dump' should give a stable result, so even 'NO_SOMETHING=1' is given (for babeltrace, if LIBBABELTRACE=1 is not given), we should try to detect those feature and {C,LD}FLAGS. Build or not should be controled independent. Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Li Zefan Link: http://lkml.kernel.org/r/1454047050-204993-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/config/Makefile | 101 +++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 54 deletions(-) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 511141b102e8..0045a5ddd0ca 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -61,50 +61,45 @@ endif ifeq ($(LIBUNWIND_LIBS),) NO_LIBUNWIND := 1 -else - # - # For linking with debug library, run like: - # - # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ - # - ifdef LIBUNWIND_DIR - LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include - LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib - endif - LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS) - - # Set per-feature check compilation flags - FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) - FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) - FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) - FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) endif +# +# For linking with debug library, run like: +# +# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ +# +ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib +endif +LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS) + +# Set per-feature check compilation flags +FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) +FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) ifeq ($(NO_PERF_REGS),0) CFLAGS += -DHAVE_PERF_REGS_SUPPORT endif -ifndef NO_LIBELF - # for linking with debug library, run like: - # make DEBUG=1 LIBDW_DIR=/opt/libdw/ - ifdef LIBDW_DIR - LIBDW_CFLAGS := -I$(LIBDW_DIR)/include - LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib - endif - FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) - FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw +# for linking with debug library, run like: +# make DEBUG=1 LIBDW_DIR=/opt/libdw/ +ifdef LIBDW_DIR + LIBDW_CFLAGS := -I$(LIBDW_DIR)/include + LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib endif +FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) +FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw -ifdef LIBBABELTRACE - # for linking with debug library, run like: - # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ - ifdef LIBBABELTRACE_DIR - LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include - LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib - endif - FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) - FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf +# for linking with debug library, run like: +# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ +ifdef LIBBABELTRACE_DIR + LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include + LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib endif +FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) +FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi # include ARCH specific config @@ -145,28 +140,26 @@ ifdef PARSER_DEBUG $(call detected_var,PARSER_DEBUG_FLEX) endif -ifndef NO_LIBPYTHON - # Try different combinations to accommodate systems that only have - # python[2][-config] in weird combinations but always preferring - # python2 and python2-config as per pep-0394. If we catch a - # python[-config] in version 3, the version check will kill it. - PYTHON2 := $(if $(call get-executable,python2),python2,python) - override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2)) - PYTHON2_CONFIG := \ - $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config) - override PYTHON_CONFIG := \ - $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG)) +# Try different combinations to accommodate systems that only have +# python[2][-config] in weird combinations but always preferring +# python2 and python2-config as per pep-0394. If we catch a +# python[-config] in version 3, the version check will kill it. +PYTHON2 := $(if $(call get-executable,python2),python2,python) +override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2)) +PYTHON2_CONFIG := \ + $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config) +override PYTHON_CONFIG := \ + $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG)) - PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) +PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) - PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) - PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) +PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) +PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) - FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) - FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) - FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) - FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) -endif +FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) +FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) +FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) +FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) CFLAGS += -fno-omit-frame-pointer CFLAGS += -ggdb3 -- cgit From 79191c89a049a9c525ce22a7d1e5674699c58818 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 29 Jan 2016 11:51:09 +0000 Subject: perf build: Use feature dump file for build-test To prevent the feature check tests to run repeately, one time per 'tests/make' target/test, this patch utilizes the previously introduced 'feature-dump' make target and FEATURES_DUMP variable, making sure that the feature checkers run only once when doing build-test for normal test cases. However, since standard users doesn't reuse features dump result, we'd better give an option to check their behaviors. The above feature should be used to make build-test faster only. Only utilize it for build-test. Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454068269-235999-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 +- tools/perf/tests/make | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index dcd9a70c7193..e4ff0bd08870 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -78,7 +78,7 @@ clean: # The build-test target is not really parallel, don't print the jobs info: # build-test: - @$(MAKE) SHUF=1 -f tests/make --no-print-directory + @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 --no-print-directory # # All other targets get passed through: diff --git a/tools/perf/tests/make b/tools/perf/tests/make index f918015512af..7f663f4611c6 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -15,6 +15,7 @@ else PERF := . PERF_O := $(PERF) O_OPT := +FULL_O := $(shell readlink -f $(PERF_O) || echo $(PERF_O)) ifneq ($(O),) FULL_O := $(shell readlink -f $(O) || echo $(O)) @@ -313,11 +314,43 @@ make_kernelsrc_tools: (make -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \ test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false) +FEATURES_DUMP_FILE := $(FULL_O)/BUILD_TEST_FEATURE_DUMP +FEATURES_DUMP_FILE_STATIC := $(FULL_O)/BUILD_TEST_FEATURE_DUMP_STATIC + all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools @echo OK + @rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC) out: $(run_O) @echo OK + @rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC) + +ifeq ($(REUSE_FEATURES_DUMP),1) +$(FEATURES_DUMP_FILE): + $(call clean) + @cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) feature-dump"; \ + echo "- $@: $$cmd" && echo $$cmd && \ + ( eval $$cmd ) > /dev/null 2>&1 + +$(FEATURES_DUMP_FILE_STATIC): + $(call clean) + @cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) LDFLAGS='-static' feature-dump"; \ + echo "- $@: $$cmd" && echo $$cmd && \ + ( eval $$cmd ) > /dev/null 2>&1 + +# Add feature dump dependency for run/run_O targets +$(foreach t,$(run) $(run_O),$(eval \ + $(t): $(if $(findstring make_static,$(t)),\ + $(FEATURES_DUMP_FILE_STATIC),\ + $(FEATURES_DUMP_FILE)))) + +# Append 'FEATURES_DUMP=' option to all test cases. For example: +# make_no_libbpf: NO_LIBBPF=1 --> NO_LIBBPF=1 FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP +# make_static: LDFLAGS=-static --> LDFLAGS=-static FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP_STATIC +$(foreach t,$(run),$(if $(findstring make_static,$(t)),\ + $(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE_STATIC)),\ + $(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE)))) +endif .PHONY: all $(run) $(run_O) tarpkg clean make_kernelsrc make_kernelsrc_tools endif # ifndef MK -- cgit From e0d9b7c45d987d94674d98ef2b74cbe657e00230 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 29 Jan 2016 13:09:00 -0300 Subject: regulator: max77802: Fix DT binding document reference The DT binding doc references the max77802 clocks header file which makes no sense since of course it doesn't contain data related to the regulators. It's a copy and paste error, so add a reference to the correct header file. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/max77802.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/max77802.txt b/Documentation/devicetree/bindings/regulator/max77802.txt index 09d796ed48be..879e98d3b9aa 100644 --- a/Documentation/devicetree/bindings/regulator/max77802.txt +++ b/Documentation/devicetree/bindings/regulator/max77802.txt @@ -60,7 +60,7 @@ The possible values for "regulator-initial-mode" and "regulator-mode" are: 1: Normal regulator voltage output mode. 3: Low Power which reduces the quiescent current down to only 1uA -The list of valid modes are defined in the dt-bindings/clock/maxim,max77802.h +The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h header and can be included by device tree source files. The standard "regulator-mode" property can only be used for regulators that -- cgit From a639a623904cc526cebd7679debf86e5c8e5590b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 29 Jan 2016 14:49:31 -0300 Subject: perf tools: Speed up build-tests by reducing the number of builds tested The 'tools/perf/test/make' makefile has in its default, 'all' target builds that will pollute the source code directory, i.e. that will not use O= variable. The 'build-test' should be run as often as possible, preferrably after each non strictly non-code commit, so speed it up by selecting just the O= targets. Furthermore it tests both the Makefile.perf file, that is normally driven by the main Makefile, and the Makefile, reduce the time in half by having just MK=Makefile, the most usual, tested by 'build-test'. Please run: make -C tools/perf -f tests/make from time to time for testing also the in-place build tests. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-jrt9utscsiqkmjy3ccufostd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index e4ff0bd08870..4b68f465195c 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -75,10 +75,17 @@ clean: $(make) # -# The build-test target is not really parallel, don't print the jobs info: +# The build-test target is not really parallel, don't print the jobs info, +# it also uses only the tests/make targets that don't pollute the source +# repository, i.e. that uses O= or builds the tarpkg outside the source +# repo directories. +# +# For a full test, use: +# +# make -C tools/perf -f tests/make # build-test: - @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 --no-print-directory + @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile --no-print-directory tarpkg out # # All other targets get passed through: -- cgit From 14a05e13a044c1cd6aaa3eb1a5fcdad7b4f6c990 Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Thu, 14 Jan 2016 14:46:15 -0700 Subject: perf auxtrace: Add perf_evlist pointer to *info_priv_size() On some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct perf_evlist *" parameter, which should contain all the required information. Also adjusting the existing client of the interface to take the new parameter into account. Signed-off-by: Mathieu Poirier Acked-by: Adrian Hunter Cc: Al Grant Cc: Chunyan Zhang Cc: linux-arm-kernel@lists.infradead.org Cc: linux-doc@vger.kernel.org Cc: Mike Leach Cc: Peter Zijlstra Cc: Rabin Vincent Cc: Tor Jeremiassen Link: http://lkml.kernel.org/r/1452807977-8069-22-git-send-email-mathieu.poirier@linaro.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c index 8d8150f1cf9b..d66f9ad4df2e 100644 --- a/tools/perf/arch/x86/util/intel-bts.c +++ b/tools/perf/arch/x86/util/intel-bts.c @@ -60,7 +60,9 @@ struct branch { u64 misc; }; -static size_t intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused) +static size_t +intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { return INTEL_BTS_AUXTRACE_PRIV_SIZE; } diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index f05daacc9e78..6f7d453b0e32 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu) return attr; } -static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused) +static size_t +intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused, + struct perf_evlist *evlist __maybe_unused) { return INTEL_PT_AUXTRACE_PRIV_SIZE; } diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 360fda01f3b0..ec164fe70718 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr, + struct perf_evlist *evlist) { if (itr) - return itr->info_priv_size(itr); + return itr->info_priv_size(itr, evlist); return 0; } @@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr, int err; pr_debug2("Synthesizing auxtrace information\n"); - priv_size = auxtrace_record__info_priv_size(itr); + priv_size = auxtrace_record__info_priv_size(itr, session->evlist); ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size); if (!ev) return -ENOMEM; diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index b86f90db1352..e5a8e2d4f2af 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h @@ -293,7 +293,8 @@ struct auxtrace_record { int (*recording_options)(struct auxtrace_record *itr, struct perf_evlist *evlist, struct record_opts *opts); - size_t (*info_priv_size)(struct auxtrace_record *itr); + size_t (*info_priv_size)(struct auxtrace_record *itr, + struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, @@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, int auxtrace_record__options(struct auxtrace_record *itr, struct perf_evlist *evlist, struct record_opts *opts); -size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr, + struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, -- cgit From fd786fac78affe4a005065bc2b6f90d8f8953961 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 29 Jan 2016 17:40:51 +0000 Subject: perf buildid: Fix cpumode of buildid event There is a nasty confusion that, for kernel module, dso->kernel is not necessary to be DSO_TYPE_KERNEL or DSO_TYPE_GUEST_KERNEL. These two enums are for vmlinux. See thread [1]. We tried to fix this part but it is costy. Code machine__write_buildid_table() is another unfortunate function fall into this trap that, when issuing buildid event for a kernel module, cpumode it gives to the event is PERF_RECORD_MISC_USER, not PERF_RECORD_MISC_KERNEL. However, even with this bug, most of the time it doesn't causes real problem. I find this issue when trying to use a perf before commit 3d39ac538629 ("perf machine: No need to have two DSOs lists") to parse a perf.data generated by newest perf. [1] https://lkml.org/lkml/2015/9/21/908 Signed-off-by: Wang Nan Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1454089251-203152-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 6a7e273a514a..b28100ee1732 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -211,6 +211,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd) dsos__for_each_with_build_id(pos, &machine->dsos.head) { const char *name; size_t name_len; + bool in_kernel = false; if (!pos->hit) continue; @@ -227,8 +228,11 @@ static int machine__write_buildid_table(struct machine *machine, int fd) name_len = pos->long_name_len + 1; } + in_kernel = pos->kernel || + is_kernel_module(name, + PERF_RECORD_MISC_CPUMODE_UNKNOWN); err = write_buildid(name, name_len, pos->build_id, machine->pid, - pos->kernel ? kmisc : umisc, fd); + in_kernel ? kmisc : umisc, fd); if (err) break; } -- cgit From 6a7d550e8b2eeb380ab85d9bc53571123b98345b Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:55:53 +0000 Subject: perf test: Check environment before start real BPF test Copying perf to old kernel system results: # perf test bpf 37: Test BPF filter : 37.1: Test basic BPF filtering : FAILED! 37.2: Test BPF prologue generation : Skip However, in case when kernel doesn't support a test case it should return 'Skip', 'FAILED!' should be reserved for kernel tests for when the kernel supports a feature that then fails to work as advertised. This patch checks environment before real testcase. Signed-off-by: Wang Nan Suggested-by: Arnaldo Carvalho de Melo Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-7-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/bpf.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c index 952ca99aba6b..4aed5cb4ac2d 100644 --- a/tools/perf/tests/bpf.c +++ b/tools/perf/tests/bpf.c @@ -1,7 +1,11 @@ #include #include +#include #include #include +#include +#include +#include #include "tests.h" #include "llvm.h" #include "debug.h" @@ -243,6 +247,36 @@ const char *test__bpf_subtest_get_desc(int i) return bpf_testcase_table[i].desc; } +static int check_env(void) +{ + int err; + unsigned int kver_int; + char license[] = "GPL"; + + struct bpf_insn insns[] = { + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }; + + err = fetch_kernel_version(&kver_int, NULL, 0); + if (err) { + pr_debug("Unable to get kernel version\n"); + return err; + } + + err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, + sizeof(insns) / sizeof(insns[0]), + license, kver_int, NULL, 0); + if (err < 0) { + pr_err("Missing basic BPF support, skip this test: %s\n", + strerror(errno)); + return err; + } + close(err); + + return 0; +} + int test__bpf(int i) { int err; @@ -255,6 +289,9 @@ int test__bpf(int i) return TEST_SKIP; } + if (check_env()) + return TEST_SKIP; + err = __test__bpf(i); return err; } -- cgit From 8fd34e1cce180eb0c726e7ed88f7b70c11c38e21 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:55:55 +0000 Subject: perf test: Improve bp_signal Will Deacon [1] has some question on patch [2]. This patch improves test__bp_signal so we can test: 1. A watchpoint and a breakpoint that fire on the same instruction 2. Nested signals Test result: On x86_64 and ARM64 (result are similar with patch [2] on ARM64): # ./perf test -v signal 17: Test breakpoint overflow signal handler : --- start --- test child forked, pid 10213 count1 1, count2 3, count3 2, overflow 3, overflows_2 3 test child finished with 0 ---- end ---- Test breakpoint overflow signal handler: Ok So at least 2 cases Will doubted are handled correctly. [1] http://lkml.kernel.org/g/20160104165535.GI1616@arm.com [2] http://lkml.kernel.org/g/1450921362-198371-1-git-send-email-wangnan0@huawei.com Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-9-git-send-email-wangnan0@huawei.com Signed-off-by: Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/bp_signal.c | 140 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 118 insertions(+), 22 deletions(-) diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index fb80c9eb6a95..1d1bb489b4e8 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c @@ -29,14 +29,59 @@ static int fd1; static int fd2; +static int fd3; static int overflows; +static int overflows_2; + +volatile long the_var; + + +/* + * Use ASM to ensure watchpoint and breakpoint can be triggered + * at one instruction. + */ +#if defined (__x86_64__) +extern void __test_function(volatile long *ptr); +asm ( + ".globl __test_function\n" + "__test_function:\n" + "incq (%rdi)\n" + "ret\n"); +#elif defined (__aarch64__) +extern void __test_function(volatile long *ptr); +asm ( + ".globl __test_function\n" + "__test_function:\n" + "str x30, [x0]\n" + "ret\n"); + +#else +static void __test_function(volatile long *ptr) +{ + *ptr = 0x1234; +} +#endif __attribute__ ((noinline)) static int test_function(void) { + __test_function(&the_var); + the_var++; return time(NULL); } +static void sig_handler_2(int signum __maybe_unused, + siginfo_t *oh __maybe_unused, + void *uc __maybe_unused) +{ + overflows_2++; + if (overflows_2 > 10) { + ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); + ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); + ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0); + } +} + static void sig_handler(int signum __maybe_unused, siginfo_t *oh __maybe_unused, void *uc __maybe_unused) @@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused, */ ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); + ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0); } } -static int bp_event(void *fn, int setup_signal) +static int __event(bool is_x, void *addr, int signal) { struct perf_event_attr pe; int fd; @@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal) pe.size = sizeof(struct perf_event_attr); pe.config = 0; - pe.bp_type = HW_BREAKPOINT_X; - pe.bp_addr = (unsigned long) fn; + pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W; + pe.bp_addr = (unsigned long) addr; pe.bp_len = sizeof(long); pe.sample_period = 1; @@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal) return TEST_FAIL; } - if (setup_signal) { - fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); - fcntl(fd, F_SETSIG, SIGIO); - fcntl(fd, F_SETOWN, getpid()); - } + fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); + fcntl(fd, F_SETSIG, signal); + fcntl(fd, F_SETOWN, getpid()); ioctl(fd, PERF_EVENT_IOC_RESET, 0); return fd; } +static int bp_event(void *addr, int signal) +{ + return __event(true, addr, signal); +} + +static int wp_event(void *addr, int signal) +{ + return __event(false, addr, signal); +} + static long long bp_count(int fd) { long long count; @@ -114,7 +168,7 @@ static long long bp_count(int fd) int test__bp_signal(int subtest __maybe_unused) { struct sigaction sa; - long long count1, count2; + long long count1, count2, count3; /* setup SIGIO signal handler */ memset(&sa, 0, sizeof(struct sigaction)); @@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused) return TEST_FAIL; } + sa.sa_sigaction = (void *) sig_handler_2; + if (sigaction(SIGUSR1, &sa, NULL) < 0) { + pr_debug("failed setting up signal handler 2\n"); + return TEST_FAIL; + } + /* * We create following events: * - * fd1 - breakpoint event on test_function with SIGIO + * fd1 - breakpoint event on __test_function with SIGIO * signal configured. We should get signal * notification each time the breakpoint is hit * - * fd2 - breakpoint event on sig_handler without SIGIO + * fd2 - breakpoint event on sig_handler with SIGUSR1 + * configured. We should get SIGUSR1 each time when + * breakpoint is hit + * + * fd3 - watchpoint event on __test_function with SIGIO * configured. * * Following processing should happen: - * - execute test_function - * - fd1 event breakpoint hit -> count1 == 1 - * - SIGIO is delivered -> overflows == 1 - * - fd2 event breakpoint hit -> count2 == 1 + * Exec: Action: Result: + * incq (%rdi) - fd1 event breakpoint hit -> count1 == 1 + * - SIGIO is delivered + * sig_handler - fd2 event breakpoint hit -> count2 == 1 + * - SIGUSR1 is delivered + * sig_handler_2 -> overflows_2 == 1 (nested signal) + * sys_rt_sigreturn - return from sig_handler_2 + * overflows++ -> overflows = 1 + * sys_rt_sigreturn - return from sig_handler + * incq (%rdi) - fd3 event watchpoint hit -> count3 == 1 (wp and bp in one insn) + * - SIGIO is delivered + * sig_handler - fd2 event breakpoint hit -> count2 == 2 + * - SIGUSR1 is delivered + * sig_handler_2 -> overflows_2 == 2 (nested signal) + * sys_rt_sigreturn - return from sig_handler_2 + * overflows++ -> overflows = 2 + * sys_rt_sigreturn - return from sig_handler + * the_var++ - fd3 event watchpoint hit -> count3 == 2 (standalone watchpoint) + * - SIGIO is delivered + * sig_handler - fd2 event breakpoint hit -> count2 == 3 + * - SIGUSR1 is delivered + * sig_handler_2 -> overflows_2 == 3 (nested signal) + * sys_rt_sigreturn - return from sig_handler_2 + * overflows++ -> overflows == 3 + * sys_rt_sigreturn - return from sig_handler * * The test case check following error conditions: * - we get stuck in signal handler because of debug @@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused) * */ - fd1 = bp_event(test_function, 1); - fd2 = bp_event(sig_handler, 0); + fd1 = bp_event(__test_function, SIGIO); + fd2 = bp_event(sig_handler, SIGUSR1); + fd3 = wp_event((void *)&the_var, SIGIO); ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); + ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0); /* * Kick off the test by trigering 'fd1' @@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused) ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); + ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0); count1 = bp_count(fd1); count2 = bp_count(fd2); + count3 = bp_count(fd3); close(fd1); close(fd2); + close(fd3); - pr_debug("count1 %lld, count2 %lld, overflow %d\n", - count1, count2, overflows); + pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n", + count1, count2, count3, overflows, overflows_2); if (count1 != 1) { if (count1 == 11) @@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused) pr_debug("failed: wrong count for bp1%lld\n", count1); } - if (overflows != 1) + if (overflows != 3) pr_debug("failed: wrong overflow hit\n"); - if (count2 != 1) + if (overflows_2 != 3) + pr_debug("failed: wrong overflow_2 hit\n"); + + if (count2 != 3) pr_debug("failed: wrong count for bp2\n"); - return count1 == 1 && overflows == 1 && count2 == 1 ? + if (count3 != 2) + pr_debug("failed: wrong count for bp3\n"); + + return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ? TEST_OK : TEST_FAIL; } -- cgit From 37b20151efe002a4a43532d3791d11d39d080248 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:56:13 +0000 Subject: perf tools: Move timestamp creation to util Timestamp generation becomes a public available helper. Which will be used by 'perf record', help it output to split output file based on time. For example: perf.data.2015122620363710 perf.data.2015122620364092 perf.data.2015122620365423 ... Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-27-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-buildid-cache.c | 14 +------------- tools/perf/util/util.c | 17 +++++++++++++++++ tools/perf/util/util.h | 1 + 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index d93bff7fc0e4..632efc6b79a0 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c @@ -38,19 +38,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) static int build_id_cache__kcore_dir(char *dir, size_t sz) { - struct timeval tv; - struct tm tm; - char dt[32]; - - if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm)) - return -1; - - if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm)) - return -1; - - scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000); - - return 0; + return fetch_current_timestamp(dir, sz); } static bool same_kallsyms_reloc(const char *from_dir, char *to_dir) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 7a2da7ef556e..b9e2843cfbe7 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -701,3 +701,20 @@ bool is_regular_file(const char *file) return S_ISREG(st.st_mode); } + +int fetch_current_timestamp(char *buf, size_t sz) +{ + struct timeval tv; + struct tm tm; + char dt[32]; + + if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm)) + return -1; + + if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm)) + return -1; + + scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000); + + return 0; +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 61650f05e5c1..a8615816a00d 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -344,5 +344,6 @@ int fetch_kernel_version(unsigned int *puint, const char *perf_tip(const char *dirpath); bool is_regular_file(const char *file); +int fetch_current_timestamp(char *buf, size_t sz); #endif /* GIT_COMPAT_UTIL_H */ -- cgit From d2db9a98c3058a45780f7fcd0cc8584858cf6b29 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 25 Jan 2016 09:56:19 +0000 Subject: perf record: Use OPT_BOOLEAN_SET for buildid cache related options 'perf record' knows whether buildid cache is enabled (via --no-no-buildid-cache) deliberately. Buildid cache can be turned off in some situations. Output switching support needs this feature to turn off buildid cache by default. Signed-off-by: Wang Nan Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Jiri Olsa Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Will Deacon Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1453715801-7732-33-git-send-email-wangnan0@huawei.com Signed-off-by: He Kuang Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 319712a4e02b..0ee0d5cd31a7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -49,7 +49,9 @@ struct record { const char *progname; int realtime_prio; bool no_buildid; + bool no_buildid_set; bool no_buildid_cache; + bool no_buildid_cache_set; bool buildid_all; unsigned long long samples; }; @@ -1097,10 +1099,12 @@ struct option __record_options[] = { OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, "don't sample"), - OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, - "do not update the buildid cache"), - OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, - "do not collect buildids in perf.data"), + OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache, + &record.no_buildid_cache_set, + "do not update the buildid cache"), + OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid, + &record.no_buildid_set, + "do not collect buildids in perf.data"), OPT_CALLBACK('G', "cgroup", &record.evlist, "name", "monitor event in cgroup name only", parse_cgroups), -- cgit From 162607ea20fafb4a76234ebe4314cd733345482e Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 28 Jan 2016 12:03:04 +0530 Subject: perf kvm/{x86,s390}: Remove dependency on uapi/kvm_perf.h Its better to remove the dependency on uapi/kvm_perf.h to allow dynamic discovery of kvm events (if its needed). To do this, some extern variables have been introduced with which we can keep the generic functions generic. Signed-off-by: Hemant Kumar Acked-by: Alexander Yarygin Acked-by: David Ahern Cc: Michael Ellerman Cc: Naveen N. Rao Cc: Paul Mackerras Cc: Scott Wood Cc: Srikar Dronamraju Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1453962787-15376-1-git-send-email-hemant@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/util/kvm-stat.c | 8 +++++++- tools/perf/arch/x86/util/kvm-stat.c | 14 +++++++++++--- tools/perf/builtin-kvm.c | 20 ++++++++++---------- tools/perf/util/kvm-stat.h | 5 +++++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c index a5dbc07ec9dc..b85a94b19c25 100644 --- a/tools/perf/arch/s390/util/kvm-stat.c +++ b/tools/perf/arch/s390/util/kvm-stat.c @@ -10,7 +10,7 @@ */ #include "../../util/kvm-stat.h" -#include +#include define_exit_reasons_table(sie_exit_reasons, sie_intercept_code); define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes); @@ -18,6 +18,12 @@ define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); define_exit_reasons_table(sie_diagnose_codes, diagnose_codes); define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); +const char *vcpu_id_str = "id"; +const int decode_str_len = 40; +const char *kvm_exit_reason = "icptcode"; +const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter"; +const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit"; + static void event_icpt_insn_get_key(struct perf_evsel *evsel, struct perf_sample *sample, struct event_key *key) diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c index 14e4e668fad7..babefda4c862 100644 --- a/tools/perf/arch/x86/util/kvm-stat.c +++ b/tools/perf/arch/x86/util/kvm-stat.c @@ -1,5 +1,7 @@ #include "../../util/kvm-stat.h" -#include +#include +#include +#include define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); @@ -11,6 +13,12 @@ static struct kvm_events_ops exit_events = { .name = "VM-EXIT" }; +const char *vcpu_id_str = "vcpu_id"; +const int decode_str_len = 20; +const char *kvm_exit_reason = "exit_reason"; +const char *kvm_entry_trace = "kvm:kvm_entry"; +const char *kvm_exit_trace = "kvm:kvm_exit"; + /* * For the mmio events, we treat: * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry @@ -65,7 +73,7 @@ static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, struct event_key *key, char *decode) { - scnprintf(decode, DECODE_STR_LEN, "%#lx:%s", + scnprintf(decode, decode_str_len, "%#lx:%s", (unsigned long)key->key, key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); } @@ -109,7 +117,7 @@ static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, struct event_key *key, char *decode) { - scnprintf(decode, DECODE_STR_LEN, "%#llx:%s", + scnprintf(decode, decode_str_len, "%#llx:%s", (unsigned long long)key->key, key->info ? "POUT" : "PIN"); } diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 4418d9214872..ab5645cf39d2 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -30,7 +30,6 @@ #include #ifdef HAVE_KVM_STAT_SUPPORT -#include #include "util/kvm-stat.h" void exit_event_get_key(struct perf_evsel *evsel, @@ -38,12 +37,12 @@ void exit_event_get_key(struct perf_evsel *evsel, struct event_key *key) { key->info = 0; - key->key = perf_evsel__intval(evsel, sample, KVM_EXIT_REASON); + key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason); } bool kvm_exit_event(struct perf_evsel *evsel) { - return !strcmp(evsel->name, KVM_EXIT_TRACE); + return !strcmp(evsel->name, kvm_exit_trace); } bool exit_event_begin(struct perf_evsel *evsel, @@ -59,7 +58,7 @@ bool exit_event_begin(struct perf_evsel *evsel, bool kvm_entry_event(struct perf_evsel *evsel) { - return !strcmp(evsel->name, KVM_ENTRY_TRACE); + return !strcmp(evsel->name, kvm_entry_trace); } bool exit_event_end(struct perf_evsel *evsel, @@ -91,7 +90,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm, const char *exit_reason = get_exit_reason(kvm, key->exit_reasons, key->key); - scnprintf(decode, DECODE_STR_LEN, "%s", exit_reason); + scnprintf(decode, decode_str_len, "%s", exit_reason); } static bool register_kvm_events_ops(struct perf_kvm_stat *kvm) @@ -357,7 +356,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm, time_diff = sample->time - time_begin; if (kvm->duration && time_diff > kvm->duration) { - char decode[DECODE_STR_LEN]; + char decode[decode_str_len]; kvm->events_ops->decode_key(kvm, &event->key, decode); if (!skip_event(decode)) { @@ -385,7 +384,8 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, return NULL; } - vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); + vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, + vcpu_id_str); thread__set_priv(thread, vcpu_record); } @@ -574,7 +574,7 @@ static void show_timeofday(void) static void print_result(struct perf_kvm_stat *kvm) { - char decode[DECODE_STR_LEN]; + char decode[decode_str_len]; struct kvm_event *event; int vcpu = kvm->trace_vcpu; @@ -585,7 +585,7 @@ static void print_result(struct perf_kvm_stat *kvm) pr_info("\n\n"); print_vcpu_info(kvm); - pr_info("%*s ", DECODE_STR_LEN, kvm->events_ops->name); + pr_info("%*s ", decode_str_len, kvm->events_ops->name); pr_info("%10s ", "Samples"); pr_info("%9s ", "Samples%"); @@ -604,7 +604,7 @@ static void print_result(struct perf_kvm_stat *kvm) min = get_event_min(event, vcpu); kvm->events_ops->decode_key(kvm, &event->key, decode); - pr_info("%*s ", DECODE_STR_LEN, decode); + pr_info("%*s ", decode_str_len, decode); pr_info("%10llu ", (unsigned long long)ecount); pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index ae825d4ec110..dd55548ef66a 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -136,5 +136,10 @@ int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid); extern const char * const kvm_events_tp[]; extern struct kvm_reg_events_ops kvm_reg_events_ops[]; extern const char * const kvm_skip_events[]; +extern const char *vcpu_id_str; +extern const int decode_str_len; +extern const char *kvm_exit_reason; +extern const char *kvm_entry_trace; +extern const char *kvm_exit_trace; #endif /* __PERF_KVM_STAT_H */ -- cgit From 48deaa74fcdad516a94fe38a4af706747d9e4745 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 28 Jan 2016 12:03:05 +0530 Subject: perf kvm/{x86,s390}: Remove const from kvm_events_tp This patch removes the "const" qualifier from kvm_events_tp declaration to account for the fact that some architectures may need to update this variable dynamically. For instance, powerpc will need to update this variable dynamically depending on the machine type. Signed-off-by: Hemant Kumar Acked-by: David Ahern Cc: Alexander Yarygin Cc: Michael Ellerman Cc: Naveen N. Rao Cc: Paul Mackerras Cc: Scott Wood Cc: Srikar Dronamraju Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1453962787-15376-2-git-send-email-hemant@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/util/kvm-stat.c | 2 +- tools/perf/arch/x86/util/kvm-stat.c | 2 +- tools/perf/util/kvm-stat.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/arch/s390/util/kvm-stat.c b/tools/perf/arch/s390/util/kvm-stat.c index b85a94b19c25..ed57df2e6d68 100644 --- a/tools/perf/arch/s390/util/kvm-stat.c +++ b/tools/perf/arch/s390/util/kvm-stat.c @@ -79,7 +79,7 @@ static struct kvm_events_ops exit_events = { .name = "VM-EXIT" }; -const char * const kvm_events_tp[] = { +const char *kvm_events_tp[] = { "kvm:kvm_s390_sie_enter", "kvm:kvm_s390_sie_exit", "kvm:kvm_s390_intercept_instruction", diff --git a/tools/perf/arch/x86/util/kvm-stat.c b/tools/perf/arch/x86/util/kvm-stat.c index babefda4c862..b63d4be655a2 100644 --- a/tools/perf/arch/x86/util/kvm-stat.c +++ b/tools/perf/arch/x86/util/kvm-stat.c @@ -129,7 +129,7 @@ static struct kvm_events_ops ioport_events = { .name = "IO Port Access" }; -const char * const kvm_events_tp[] = { +const char *kvm_events_tp[] = { "kvm:kvm_entry", "kvm:kvm_exit", "kvm:kvm_mmio", diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index dd55548ef66a..c965dc844df3 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -133,7 +133,7 @@ bool kvm_entry_event(struct perf_evsel *evsel); */ int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid); -extern const char * const kvm_events_tp[]; +extern const char *kvm_events_tp[]; extern struct kvm_reg_events_ops kvm_reg_events_ops[]; extern const char * const kvm_skip_events[]; extern const char *vcpu_id_str; -- cgit From 066d3593e1b14690dc1131d50cacbb0b7eb3f160 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 28 Jan 2016 12:03:06 +0530 Subject: perf kvm/powerpc: Port perf kvm stat to powerpc perf kvm can be used to analyze guest exit reasons. This support already exists in x86. Hence, porting it to powerpc. - To trace KVM events : perf kvm stat record If many guests are running, we can track for a specific guest by using --pid as in : perf kvm stat record --pid - To see the results : perf kvm stat report The result shows the number of exits (from the guest context to host/hypervisor context) grouped by their respective exit reasons with their frequency. Since, different powerpc machines have different KVM tracepoints, this patch discovers the available tracepoints dynamically and accordingly looks for them. If any single tracepoint is not present, this support won't be enabled for reporting. To record, this will fail if any of the events we are looking to record isn't available. Right now, its only supported on PowerPC Book3S_HV architectures. To analyze the different exits, group them and present them (in a slight descriptive way) to the user, we need a mapping between the "exit code" (dumped in the kvm_guest_exit tracepoint data) and to its related Interrupt vector description (exit reason). This patch adds this mapping in book3s_hv_exits.h. It records on two available KVM tracepoints for book3s_hv: "kvm_hv:kvm_guest_exit" and "kvm_hv:kvm_guest_enter". Here is a sample o/p: # pgrep qemu 19378 60515 2 Guests are running on the host. # perf kvm stat record -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 4.153 MB perf.data.guest (39624 samples) ] # perf kvm stat report -p 60515 Analyze events for pid(s) 60515, all VCPUs: VM-EXIT Samples Samples% Time% MinTime MaxTime Avg time SYSCALL 9141 63.67% 7.49% 1.26us 5782.39us 9.87us (+- 6.46%) H_DATA_STORAGE 4114 28.66% 5.07% 1.72us 4597.68us 14.84us (+-20.06%) HV_DECREMENTER 418 2.91% 4.26% 0.70us 30002.22us 122.58us (+-70.29%) EXTERNAL 392 2.73% 0.06% 0.64us 104.10us 1.94us (+-18.83%) RETURN_TO_HOST 287 2.00% 83.11% 1.53us 124240.15us 3486.52us (+-16.81%) H_INST_STORAGE 5 0.03% 0.00% 1.88us 3.73us 2.39us (+-14.20%) Total Samples:14357, Total events handled time:1203918.42us. Signed-off-by: Hemant Kumar Cc: Alexander Yarygin Cc: David Ahern Cc: Michael Ellerman Cc: Naveen N. Rao Cc: Paul Mackerras Cc: Scott Wood Cc: Srikar Dronamraju Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1453962787-15376-3-git-send-email-hemant@linux.vnet.ibm.com Signed-off-by: Srikar Dronamraju Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/powerpc/Makefile | 2 + tools/perf/arch/powerpc/util/Build | 1 + tools/perf/arch/powerpc/util/book3s_hv_exits.h | 33 ++++++++ tools/perf/arch/powerpc/util/kvm-stat.c | 107 +++++++++++++++++++++++++ tools/perf/builtin-kvm.c | 18 +++++ tools/perf/util/kvm-stat.h | 1 + 6 files changed, 162 insertions(+) create mode 100644 tools/perf/arch/powerpc/util/book3s_hv_exits.h create mode 100644 tools/perf/arch/powerpc/util/kvm-stat.c diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile index 7fbca175099e..9f9cea3478fd 100644 --- a/tools/perf/arch/powerpc/Makefile +++ b/tools/perf/arch/powerpc/Makefile @@ -1,3 +1,5 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif + +HAVE_KVM_STAT_SUPPORT := 1 diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build index 7b8b0d1a1b62..c8fe2074d217 100644 --- a/tools/perf/arch/powerpc/util/Build +++ b/tools/perf/arch/powerpc/util/Build @@ -1,5 +1,6 @@ libperf-y += header.o libperf-y += sym-handling.o +libperf-y += kvm-stat.o libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_DWARF) += skip-callchain-idx.o diff --git a/tools/perf/arch/powerpc/util/book3s_hv_exits.h b/tools/perf/arch/powerpc/util/book3s_hv_exits.h new file mode 100644 index 000000000000..e68ba2da8970 --- /dev/null +++ b/tools/perf/arch/powerpc/util/book3s_hv_exits.h @@ -0,0 +1,33 @@ +#ifndef ARCH_PERF_BOOK3S_HV_EXITS_H +#define ARCH_PERF_BOOK3S_HV_EXITS_H + +/* + * PowerPC Interrupt vectors : exit code to name mapping + */ + +#define kvm_trace_symbol_exit \ + {0x0, "RETURN_TO_HOST"}, \ + {0x100, "SYSTEM_RESET"}, \ + {0x200, "MACHINE_CHECK"}, \ + {0x300, "DATA_STORAGE"}, \ + {0x380, "DATA_SEGMENT"}, \ + {0x400, "INST_STORAGE"}, \ + {0x480, "INST_SEGMENT"}, \ + {0x500, "EXTERNAL"}, \ + {0x501, "EXTERNAL_LEVEL"}, \ + {0x502, "EXTERNAL_HV"}, \ + {0x600, "ALIGNMENT"}, \ + {0x700, "PROGRAM"}, \ + {0x800, "FP_UNAVAIL"}, \ + {0x900, "DECREMENTER"}, \ + {0x980, "HV_DECREMENTER"}, \ + {0xc00, "SYSCALL"}, \ + {0xd00, "TRACE"}, \ + {0xe00, "H_DATA_STORAGE"}, \ + {0xe20, "H_INST_STORAGE"}, \ + {0xe40, "H_EMUL_ASSIST"}, \ + {0xf00, "PERFMON"}, \ + {0xf20, "ALTIVEC"}, \ + {0xf40, "VSX"} + +#endif diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c new file mode 100644 index 000000000000..27bc559b8b3a --- /dev/null +++ b/tools/perf/arch/powerpc/util/kvm-stat.c @@ -0,0 +1,107 @@ +#include "util/kvm-stat.h" +#include "util/parse-events.h" + +#include "book3s_hv_exits.h" + +#define NR_TPS 2 + +const char *vcpu_id_str = "vcpu_id"; +const int decode_str_len = 40; +const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter"; +const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit"; + +define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit); + +/* Tracepoints specific to ppc_book3s_hv */ +const char *ppc_book3s_hv_kvm_tp[] = { + "kvm_hv:kvm_guest_enter", + "kvm_hv:kvm_guest_exit", +}; + +/* 1 extra placeholder for NULL */ +const char *kvm_events_tp[NR_TPS + 1]; +const char *kvm_exit_reason; + +static struct kvm_events_ops exit_events = { + .is_begin_event = exit_event_begin, + .is_end_event = exit_event_end, + .decode_key = exit_event_decode_key, + .name = "VM-EXIT" +}; + +struct kvm_reg_events_ops kvm_reg_events_ops[] = { + { .name = "vmexit", .ops = &exit_events }, + { NULL, NULL }, +}; + +const char * const kvm_skip_events[] = { + NULL, +}; + + +static int is_tracepoint_available(const char *str, struct perf_evlist *evlist) +{ + struct parse_events_error err; + int ret; + + err.str = NULL; + ret = parse_events(evlist, str, &err); + if (err.str) + pr_err("%s : %s\n", str, err.str); + return ret; +} + +static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm, + struct perf_evlist *evlist) +{ + const char **events_ptr; + int i, nr_tp = 0, err = -1; + + /* Check for book3s_hv tracepoints */ + for (events_ptr = ppc_book3s_hv_kvm_tp; *events_ptr; events_ptr++) { + err = is_tracepoint_available(*events_ptr, evlist); + if (err) + return -1; + nr_tp++; + } + + for (i = 0; i < nr_tp; i++) + kvm_events_tp[i] = ppc_book3s_hv_kvm_tp[i]; + + kvm_events_tp[i] = NULL; + kvm_exit_reason = "trap"; + kvm->exit_reasons = hv_exit_reasons; + kvm->exit_reasons_isa = "HV"; + + return 0; +} + +/* Wrapper to setup kvm tracepoints */ +static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm) +{ + struct perf_evlist *evlist = perf_evlist__new(); + + if (evlist == NULL) + return -ENOMEM; + + /* Right now, only supported on book3s_hv */ + return ppc__setup_book3s_hv(kvm, evlist); +} + +int setup_kvm_events_tp(struct perf_kvm_stat *kvm) +{ + return ppc__setup_kvm_tp(kvm); +} + +int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused) +{ + int ret; + + ret = ppc__setup_kvm_tp(kvm); + if (ret) { + kvm->exit_reasons = NULL; + kvm->exit_reasons_isa = NULL; + } + + return ret; +} diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index ab5645cf39d2..bff666458b28 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1132,6 +1132,11 @@ exit: _p; \ }) +int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused) +{ + return 0; +} + static int kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) { @@ -1148,7 +1153,14 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) NULL }; const char * const *events_tp; + int ret; + events_tp_size = 0; + ret = setup_kvm_events_tp(kvm); + if (ret < 0) { + pr_err("Unable to setup the kvm tracepoints\n"); + return ret; + } for (events_tp = kvm_events_tp; *events_tp; events_tp++) events_tp_size++; @@ -1377,6 +1389,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, /* * generate the event list */ + err = setup_kvm_events_tp(kvm); + if (err < 0) { + pr_err("Unable to setup the kvm tracepoints\n"); + return err; + } + kvm->evlist = kvm_live_event_list(); if (kvm->evlist == NULL) { err = -1; diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h index c965dc844df3..d01e73592f6e 100644 --- a/tools/perf/util/kvm-stat.h +++ b/tools/perf/util/kvm-stat.h @@ -122,6 +122,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm, bool kvm_exit_event(struct perf_evsel *evsel); bool kvm_entry_event(struct perf_evsel *evsel); +int setup_kvm_events_tp(struct perf_kvm_stat *kvm); #define define_exit_reasons_table(name, symbols) \ static struct exit_reasons_table name[] = { \ -- cgit From 78e6c39b231a8e31e193534fdbe29291b7fd8f37 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 28 Jan 2016 12:03:07 +0530 Subject: perf kvm/powerpc: Add support for HCALL reasons Powerpc provides hcall events that also provides insights into guest behaviour. Enhance perf kvm stat to record and analyze hcall events. - To trace hcall events : perf kvm stat record - To show the results : perf kvm stat report --event=hcall The result shows the number of hypervisor calls from the guest grouped by their respective reasons displayed with the frequency. This patch makes use of two additional tracepoints "kvm_hv:kvm_hcall_enter" and "kvm_hv:kvm_hcall_exit". To map the hcall codes to their respective names, it needs a mapping. Such mapping is added in this patch in book3s_hcalls.h. # pgrep qemu A sample output : 19378 60515 2 VMs running. # perf kvm stat record -a ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 4.153 MB perf.data.guest (39624 samples) ] # perf kvm stat report -p 60515 --event=hcall Analyze events for all VMs, all VCPUs: HCALL-EVENT Samples Samples% Time% MinTime MaxTime AvgTime H_IPI 822 66.08% 88.10% 0.63us 11.38us 2.05us (+- 1.42%) H_SEND_CRQ 144 11.58% 3.77% 0.41us 0.88us 0.50us (+- 1.47%) H_VIO_SIGNAL 118 9.49% 2.86% 0.37us 0.83us 0.47us (+- 1.43%) H_PUT_TERM_CHAR 76 6.11% 2.07% 0.37us 0.90us 0.52us (+- 2.43%) H_GET_TERM_CHAR 74 5.95% 2.23% 0.37us 1.70us 0.58us (+- 4.77%) H_RTAS 6 0.48% 0.85% 1.10us 9.25us 2.70us (+-48.57%) H_PERFMON 4 0.32% 0.12% 0.41us 0.96us 0.59us (+-20.92%) Total Samples:1244, Total events handled time:1916.69us. Signed-off-by: Hemant Kumar Cc: Alexander Yarygin Cc: David Ahern Cc: Michael Ellerman Cc: Naveen N. Rao Cc: Paul Mackerras Cc: Scott Wood Cc: Srikar Dronamraju Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1453962787-15376-4-git-send-email-hemant@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/powerpc/util/book3s_hcalls.h | 123 +++++++++++++++++++++++++++ tools/perf/arch/powerpc/util/kvm-stat.c | 65 +++++++++++++- 2 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/powerpc/util/book3s_hcalls.h diff --git a/tools/perf/arch/powerpc/util/book3s_hcalls.h b/tools/perf/arch/powerpc/util/book3s_hcalls.h new file mode 100644 index 000000000000..0dd6b7f2d44f --- /dev/null +++ b/tools/perf/arch/powerpc/util/book3s_hcalls.h @@ -0,0 +1,123 @@ +#ifndef ARCH_PERF_BOOK3S_HV_HCALLS_H +#define ARCH_PERF_BOOK3S_HV_HCALLS_H + +/* + * PowerPC HCALL codes : hcall code to name mapping + */ +#define kvm_trace_symbol_hcall \ + {0x4, "H_REMOVE"}, \ + {0x8, "H_ENTER"}, \ + {0xc, "H_READ"}, \ + {0x10, "H_CLEAR_MOD"}, \ + {0x14, "H_CLEAR_REF"}, \ + {0x18, "H_PROTECT"}, \ + {0x1c, "H_GET_TCE"}, \ + {0x20, "H_PUT_TCE"}, \ + {0x24, "H_SET_SPRG0"}, \ + {0x28, "H_SET_DABR"}, \ + {0x2c, "H_PAGE_INIT"}, \ + {0x30, "H_SET_ASR"}, \ + {0x34, "H_ASR_ON"}, \ + {0x38, "H_ASR_OFF"}, \ + {0x3c, "H_LOGICAL_CI_LOAD"}, \ + {0x40, "H_LOGICAL_CI_STORE"}, \ + {0x44, "H_LOGICAL_CACHE_LOAD"}, \ + {0x48, "H_LOGICAL_CACHE_STORE"}, \ + {0x4c, "H_LOGICAL_ICBI"}, \ + {0x50, "H_LOGICAL_DCBF"}, \ + {0x54, "H_GET_TERM_CHAR"}, \ + {0x58, "H_PUT_TERM_CHAR"}, \ + {0x5c, "H_REAL_TO_LOGICAL"}, \ + {0x60, "H_HYPERVISOR_DATA"}, \ + {0x64, "H_EOI"}, \ + {0x68, "H_CPPR"}, \ + {0x6c, "H_IPI"}, \ + {0x70, "H_IPOLL"}, \ + {0x74, "H_XIRR"}, \ + {0x78, "H_MIGRATE_DMA"}, \ + {0x7c, "H_PERFMON"}, \ + {0xdc, "H_REGISTER_VPA"}, \ + {0xe0, "H_CEDE"}, \ + {0xe4, "H_CONFER"}, \ + {0xe8, "H_PROD"}, \ + {0xec, "H_GET_PPP"}, \ + {0xf0, "H_SET_PPP"}, \ + {0xf4, "H_PURR"}, \ + {0xf8, "H_PIC"}, \ + {0xfc, "H_REG_CRQ"}, \ + {0x100, "H_FREE_CRQ"}, \ + {0x104, "H_VIO_SIGNAL"}, \ + {0x108, "H_SEND_CRQ"}, \ + {0x110, "H_COPY_RDMA"}, \ + {0x114, "H_REGISTER_LOGICAL_LAN"}, \ + {0x118, "H_FREE_LOGICAL_LAN"}, \ + {0x11c, "H_ADD_LOGICAL_LAN_BUFFER"}, \ + {0x120, "H_SEND_LOGICAL_LAN"}, \ + {0x124, "H_BULK_REMOVE"}, \ + {0x130, "H_MULTICAST_CTRL"}, \ + {0x134, "H_SET_XDABR"}, \ + {0x138, "H_STUFF_TCE"}, \ + {0x13c, "H_PUT_TCE_INDIRECT"}, \ + {0x14c, "H_CHANGE_LOGICAL_LAN_MAC"}, \ + {0x150, "H_VTERM_PARTNER_INFO"}, \ + {0x154, "H_REGISTER_VTERM"}, \ + {0x158, "H_FREE_VTERM"}, \ + {0x15c, "H_RESET_EVENTS"}, \ + {0x160, "H_ALLOC_RESOURCE"}, \ + {0x164, "H_FREE_RESOURCE"}, \ + {0x168, "H_MODIFY_QP"}, \ + {0x16c, "H_QUERY_QP"}, \ + {0x170, "H_REREGISTER_PMR"}, \ + {0x174, "H_REGISTER_SMR"}, \ + {0x178, "H_QUERY_MR"}, \ + {0x17c, "H_QUERY_MW"}, \ + {0x180, "H_QUERY_HCA"}, \ + {0x184, "H_QUERY_PORT"}, \ + {0x188, "H_MODIFY_PORT"}, \ + {0x18c, "H_DEFINE_AQP1"}, \ + {0x190, "H_GET_TRACE_BUFFER"}, \ + {0x194, "H_DEFINE_AQP0"}, \ + {0x198, "H_RESIZE_MR"}, \ + {0x19c, "H_ATTACH_MCQP"}, \ + {0x1a0, "H_DETACH_MCQP"}, \ + {0x1a4, "H_CREATE_RPT"}, \ + {0x1a8, "H_REMOVE_RPT"}, \ + {0x1ac, "H_REGISTER_RPAGES"}, \ + {0x1b0, "H_DISABLE_AND_GETC"}, \ + {0x1b4, "H_ERROR_DATA"}, \ + {0x1b8, "H_GET_HCA_INFO"}, \ + {0x1bc, "H_GET_PERF_COUNT"}, \ + {0x1c0, "H_MANAGE_TRACE"}, \ + {0x1d4, "H_FREE_LOGICAL_LAN_BUFFER"}, \ + {0x1d8, "H_POLL_PENDING"}, \ + {0x1e4, "H_QUERY_INT_STATE"}, \ + {0x244, "H_ILLAN_ATTRIBUTES"}, \ + {0x250, "H_MODIFY_HEA_QP"}, \ + {0x254, "H_QUERY_HEA_QP"}, \ + {0x258, "H_QUERY_HEA"}, \ + {0x25c, "H_QUERY_HEA_PORT"}, \ + {0x260, "H_MODIFY_HEA_PORT"}, \ + {0x264, "H_REG_BCMC"}, \ + {0x268, "H_DEREG_BCMC"}, \ + {0x26c, "H_REGISTER_HEA_RPAGES"}, \ + {0x270, "H_DISABLE_AND_GET_HEA"}, \ + {0x274, "H_GET_HEA_INFO"}, \ + {0x278, "H_ALLOC_HEA_RESOURCE"}, \ + {0x284, "H_ADD_CONN"}, \ + {0x288, "H_DEL_CONN"}, \ + {0x298, "H_JOIN"}, \ + {0x2a4, "H_VASI_STATE"}, \ + {0x2b0, "H_ENABLE_CRQ"}, \ + {0x2b8, "H_GET_EM_PARMS"}, \ + {0x2d0, "H_SET_MPP"}, \ + {0x2d4, "H_GET_MPP"}, \ + {0x2ec, "H_HOME_NODE_ASSOCIATIVITY"}, \ + {0x2f4, "H_BEST_ENERGY"}, \ + {0x2fc, "H_XIRR_X"}, \ + {0x300, "H_RANDOM"}, \ + {0x304, "H_COP"}, \ + {0x314, "H_GET_MPP_X"}, \ + {0x31c, "H_SET_MODE"}, \ + {0xf000, "H_RTAS"} \ + +#endif diff --git a/tools/perf/arch/powerpc/util/kvm-stat.c b/tools/perf/arch/powerpc/util/kvm-stat.c index 27bc559b8b3a..74eee30398f8 100644 --- a/tools/perf/arch/powerpc/util/kvm-stat.c +++ b/tools/perf/arch/powerpc/util/kvm-stat.c @@ -1,9 +1,11 @@ #include "util/kvm-stat.h" #include "util/parse-events.h" +#include "util/debug.h" #include "book3s_hv_exits.h" +#include "book3s_hcalls.h" -#define NR_TPS 2 +#define NR_TPS 4 const char *vcpu_id_str = "vcpu_id"; const int decode_str_len = 40; @@ -11,17 +13,77 @@ const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter"; const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit"; define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit); +define_exit_reasons_table(hcall_reasons, kvm_trace_symbol_hcall); /* Tracepoints specific to ppc_book3s_hv */ const char *ppc_book3s_hv_kvm_tp[] = { "kvm_hv:kvm_guest_enter", "kvm_hv:kvm_guest_exit", + "kvm_hv:kvm_hcall_enter", + "kvm_hv:kvm_hcall_exit", + NULL, }; /* 1 extra placeholder for NULL */ const char *kvm_events_tp[NR_TPS + 1]; const char *kvm_exit_reason; +static void hcall_event_get_key(struct perf_evsel *evsel, + struct perf_sample *sample, + struct event_key *key) +{ + key->info = 0; + key->key = perf_evsel__intval(evsel, sample, "req"); +} + +static const char *get_hcall_exit_reason(u64 exit_code) +{ + struct exit_reasons_table *tbl = hcall_reasons; + + while (tbl->reason != NULL) { + if (tbl->exit_code == exit_code) + return tbl->reason; + tbl++; + } + + pr_debug("Unknown hcall code: %lld\n", + (unsigned long long)exit_code); + return "UNKNOWN"; +} + +static bool hcall_event_end(struct perf_evsel *evsel, + struct perf_sample *sample __maybe_unused, + struct event_key *key __maybe_unused) +{ + return (!strcmp(evsel->name, kvm_events_tp[3])); +} + +static bool hcall_event_begin(struct perf_evsel *evsel, + struct perf_sample *sample, struct event_key *key) +{ + if (!strcmp(evsel->name, kvm_events_tp[2])) { + hcall_event_get_key(evsel, sample, key); + return true; + } + + return false; +} +static void hcall_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, + struct event_key *key, + char *decode) +{ + const char *hcall_reason = get_hcall_exit_reason(key->key); + + scnprintf(decode, decode_str_len, "%s", hcall_reason); +} + +static struct kvm_events_ops hcall_events = { + .is_begin_event = hcall_event_begin, + .is_end_event = hcall_event_end, + .decode_key = hcall_event_decode_key, + .name = "HCALL-EVENT", +}; + static struct kvm_events_ops exit_events = { .is_begin_event = exit_event_begin, .is_end_event = exit_event_end, @@ -31,6 +93,7 @@ static struct kvm_events_ops exit_events = { struct kvm_reg_events_ops kvm_reg_events_ops[] = { { .name = "vmexit", .ops = &exit_events }, + { .name = "hcall", .ops = &hcall_events }, { NULL, NULL }, }; -- cgit From 814568db641f6587c1e98a3a85f214cb6a30fe10 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 29 Jan 2016 17:51:04 -0300 Subject: perf build: Align the names of the build tests: $ make -C tools/perf build-test make[1]: Entering directory `/home/acme/git/linux/tools/perf' make_pure_O: cd . && make -f Makefile O=/tmp/tmp.mPx0Cmik3f DESTDIR=/tmp/tmp.U0SUmVbtJm make_clean_all_O: cd . && make -f Makefile O=/tmp/tmp.Yl5UzhTU7T DESTDIR=/tmp/tmp.fop1E4jdER clean all make_debug_O: cd . && make -f Makefile O=/tmp/tmp.pMn2ozBoXC DESTDIR=/tmp/tmp.azxhDp5sEp DEBUG=1 make_no_libperl_O: cd . && make -f Makefile O=/tmp/tmp.qJPiINMtA7 DESTDIR=/tmp/tmp.KNMrLeGDxZ NO_LIBPERL=1 More needs to be done to make it more compact, i.e. elide the '-f Makefile', remove that 'cd . &&', move the DESTDIR= and O= to the end, as they don't convey that much information besides the fact that they are being set to some random directory just for this build, move the meat, i.e. the meaningful feature disabling bits to the start, etc. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-wir3w3o4f1nmbgcxgnx8cj9c@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 7f663f4611c6..cc72b67bde5e 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -261,6 +261,8 @@ run := $(shell shuf -e $(run)) run_O := $(shell shuf -e $(run_O)) endif +max_width := $(shell echo $(run_O) | sed 's/ /\n/g' | wc -L) + ifdef DEBUG d := $(info run $(run)) d := $(info run_O $(run_O)) @@ -274,7 +276,7 @@ $(run): $(call clean) @TMP_DEST=$$(mktemp -d); \ cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \ - echo "- $@: $$cmd" && echo $$cmd > $@ && \ + printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1; \ echo " test: $(call test,$@)" >> $@ 2>&1; \ $(call test,$@) && \ @@ -285,7 +287,7 @@ $(run_O): @TMP_O=$$(mktemp -d); \ TMP_DEST=$$(mktemp -d); \ cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ - echo "- $@: $$cmd" && echo $$cmd > $@ && \ + printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 && \ echo " test: $(call test_O,$@)" >> $@ 2>&1; \ $(call test_O,$@) && \ -- cgit From a66a5114b34bb23396568bf485e05a311b3ee22f Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Fri, 28 Aug 2015 18:08:19 -0700 Subject: remoteproc: report error if resource table doesn't exist Currently, if the resource table is completely missing in the firmware, powering up the remoteproc fails silently. Add a message indicating that the resource table is missing in the firmware. Signed-off-by: Stefan Agner Acked-by: Suman Anna Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/remoteproc_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 9e03d158f411..3d7d58a109d8 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -823,8 +823,10 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) /* look for the resource table */ table = rproc_find_rsc_table(rproc, fw, &tablesz); - if (!table) + if (!table) { + dev_err(dev, "Failed to find resource table\n"); goto clean_up; + } /* Verify that resource table in loaded fw is unchanged */ if (rproc->table_csum != crc32(0, table, tablesz)) { -- cgit From 99c429cb4e628e8b6b8131910952436ad10b21f5 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Wed, 16 Sep 2015 07:32:54 -0500 Subject: remoteproc/wkup_m3: Use MODULE_DEVICE_TABLE to export alias Use MODULE_DEVICE_TABLE with wkup_m3_rproc_of_match so the module alias is exported and the wkup_m3_rproc driver can automatically probe. Signed-off-by: Dave Gerlach Signed-off-by: Ohad Ben-Cohen --- drivers/remoteproc/wkup_m3_rproc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c index edf81819cce1..02d271d101b4 100644 --- a/drivers/remoteproc/wkup_m3_rproc.c +++ b/drivers/remoteproc/wkup_m3_rproc.c @@ -122,6 +122,7 @@ static const struct of_device_id wkup_m3_rproc_of_match[] = { { .compatible = "ti,am4372-wkup-m3", }, {}, }; +MODULE_DEVICE_TABLE(of, wkup_m3_rproc_of_match); static int wkup_m3_rproc_probe(struct platform_device *pdev) { -- cgit From 47fff9fd8a7848c44c83b34ad7825d2185b9b319 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:15 +0000 Subject: remoteproc: debugfs: Return error on invalid 'count' value If 'count' value is invalid, return -EINVAL. Signed-off-by: Lee Jones [bjorn: changed commit message] Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 916af5096f57..6fdfa688281a 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -157,7 +157,7 @@ rproc_recovery_write(struct file *filp, const char __user *user_buf, int ret; if (count < 1 || count > sizeof(buf)) - return count; + return -EINVAL; ret = copy_from_user(buf, user_buf, count); if (ret) -- cgit From 6cb0e0f6a46a6c2f1d6f9d4a0539f2ed7d8487fb Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:16 +0000 Subject: remoteproc: dt: Provide bindings for ST's Remote Processor Controller driver Signed-off-by: Ludovic Barre Signed-off-by: Lee Jones Acked-by: Rob Herring Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/remoteproc/st-rproc.txt | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/st-rproc.txt diff --git a/Documentation/devicetree/bindings/remoteproc/st-rproc.txt b/Documentation/devicetree/bindings/remoteproc/st-rproc.txt new file mode 100644 index 000000000000..1031bcd90a79 --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/st-rproc.txt @@ -0,0 +1,41 @@ +STMicroelectronics Co-Processor Bindings +---------------------------------------- + +This binding provides support for adjunct processors found on ST SoCs. + +Co-processors can be controlled from the bootloader or the primary OS. If +the bootloader starts a co-processor, the primary OS must detect its state +and act accordingly. + +Required properties: +- compatible Should be one of: + "st,st231-rproc" + "st,st40-rproc" +- memory-region Reserved memory (See: ../reserved-memory/reserved-memory.txt) +- resets Reset lines (See: ../reset/reset.txt) +- reset-names Must be "sw_reset" and "pwr_reset" +- clocks Clock for co-processor (See: ../clock/clock-bindings.txt) +- clock-frequency Clock frequency to set co-processor at if the bootloader + hasn't already done so +- st,syscfg System configuration register which holds the boot vector + for the co-processor + 1st cell: Phandle to syscon block + 2nd cell: Boot vector register offset + +Example: + + audio_reserved: rproc@42000000 { + compatible = "shared-dma-pool"; + reg = <0x42000000 0x01000000>; + no-map; + }; + + st231-audio { + compatible = "st,st231-rproc"; + memory-region = <&audio_reserved>; + 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>; + }; -- cgit From 69e50479bd6b99a377223104be46f7b894ca4208 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:17 +0000 Subject: remoteproc: debugfs: Add ability to boot remote processor using debugfs This functionality is especially useful during the testing phase. When used in conjunction with Mailbox's Test Framework we can trivially conduct end-to-end testing i.e. boot co-processor, send and receive messages to the co-processor, then shut it down again (repeat as required). Signed-off-by: Ludovic Barre Signed-off-by: Lee Jones Signed-off-by: Bjorn Andersson --- drivers/remoteproc/remoteproc_debugfs.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c index 6fdfa688281a..74a120b6e206 100644 --- a/drivers/remoteproc/remoteproc_debugfs.c +++ b/drivers/remoteproc/remoteproc_debugfs.c @@ -88,8 +88,42 @@ static ssize_t rproc_state_read(struct file *filp, char __user *userbuf, return simple_read_from_buffer(userbuf, count, ppos, buf, i); } +static ssize_t rproc_state_write(struct file *filp, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct rproc *rproc = filp->private_data; + char buf[10]; + int ret; + + if (count > sizeof(buf) || count <= 0) + return -EINVAL; + + ret = copy_from_user(buf, userbuf, count); + if (ret) + return -EFAULT; + + if (buf[count - 1] == '\n') + buf[count - 1] = '\0'; + + if (!strncmp(buf, "start", count)) { + ret = rproc_boot(rproc); + if (ret) { + dev_err(&rproc->dev, "Boot failed: %d\n", ret); + return ret; + } + } else if (!strncmp(buf, "stop", count)) { + rproc_shutdown(rproc); + } else { + dev_err(&rproc->dev, "Unrecognised option: %s\n", buf); + return -EINVAL; + } + + return count; +} + static const struct file_operations rproc_state_ops = { .read = rproc_state_read, + .write = rproc_state_write, .open = simple_open, .llseek = generic_file_llseek, }; -- cgit From 63edb0310a5ca736c81aaba661b365cd4887cd3b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Jan 2016 12:46:18 +0000 Subject: remoteproc: Supply controller driver for ST's Remote Processors Signed-off-by: Ludovic Barre Signed-off-by: Lee Jones Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 9 ++ drivers/remoteproc/Makefile | 1 + drivers/remoteproc/st_remoteproc.c | 297 +++++++++++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 drivers/remoteproc/st_remoteproc.c diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 28c711f0ac6b..72e97d7a5209 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -77,4 +77,13 @@ config DA8XX_REMOTEPROC It's safe to say n here if you're not interested in multimedia offloading. +config ST_REMOTEPROC + tristate "ST remoteproc support" + depends on ARCH_STI + select REMOTEPROC + help + Say y here to support ST's adjunct processors via the remote + processor framework. + This can be either built-in or a loadable module. + endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 81b04d1e2e58..279cb2edc880 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_STE_MODEM_RPROC) += ste_modem_rproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o +obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c new file mode 100644 index 000000000000..6bb04d453247 --- /dev/null +++ b/drivers/remoteproc/st_remoteproc.c @@ -0,0 +1,297 @@ +/* + * ST's Remote Processor Control Driver + * + * Copyright (C) 2015 STMicroelectronics - All Rights Reserved + * + * Author: Ludovic Barre + * + * 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 +#include +#include +#include +#include +#include +#include + +struct st_rproc_config { + bool sw_reset; + bool pwr_reset; + unsigned long bootaddr_mask; +}; + +struct st_rproc { + struct st_rproc_config *config; + struct reset_control *sw_reset; + struct reset_control *pwr_reset; + struct clk *clk; + u32 clk_rate; + struct regmap *boot_base; + u32 boot_offset; +}; + +static int st_rproc_start(struct rproc *rproc) +{ + struct st_rproc *ddata = rproc->priv; + int err; + + regmap_update_bits(ddata->boot_base, ddata->boot_offset, + ddata->config->bootaddr_mask, rproc->bootaddr); + + err = clk_enable(ddata->clk); + if (err) { + dev_err(&rproc->dev, "Failed to enable clock\n"); + return err; + } + + if (ddata->config->sw_reset) { + err = reset_control_deassert(ddata->sw_reset); + if (err) { + dev_err(&rproc->dev, "Failed to deassert S/W Reset\n"); + goto sw_reset_fail; + } + } + + if (ddata->config->pwr_reset) { + err = reset_control_deassert(ddata->pwr_reset); + if (err) { + dev_err(&rproc->dev, "Failed to deassert Power Reset\n"); + goto pwr_reset_fail; + } + } + + dev_info(&rproc->dev, "Started from 0x%x\n", rproc->bootaddr); + + return 0; + + +pwr_reset_fail: + if (ddata->config->pwr_reset) + reset_control_assert(ddata->sw_reset); +sw_reset_fail: + clk_disable(ddata->clk); + + return err; +} + +static int st_rproc_stop(struct rproc *rproc) +{ + struct st_rproc *ddata = rproc->priv; + int sw_err = 0, pwr_err = 0; + + if (ddata->config->sw_reset) { + sw_err = reset_control_assert(ddata->sw_reset); + if (sw_err) + dev_err(&rproc->dev, "Failed to assert S/W Reset\n"); + } + + if (ddata->config->pwr_reset) { + pwr_err = reset_control_assert(ddata->pwr_reset); + if (pwr_err) + dev_err(&rproc->dev, "Failed to assert Power Reset\n"); + } + + clk_disable(ddata->clk); + + return sw_err ?: pwr_err; +} + +static struct rproc_ops st_rproc_ops = { + .start = st_rproc_start, + .stop = st_rproc_stop, +}; + +/* + * Fetch state of the processor: 0 is off, 1 is on. + */ +static int st_rproc_state(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + struct st_rproc *ddata = rproc->priv; + int reset_sw = 0, reset_pwr = 0; + + if (ddata->config->sw_reset) + reset_sw = reset_control_status(ddata->sw_reset); + + if (ddata->config->pwr_reset) + reset_pwr = reset_control_status(ddata->pwr_reset); + + if (reset_sw < 0 || reset_pwr < 0) + return -EINVAL; + + return !reset_sw && !reset_pwr; +} + +static const struct st_rproc_config st40_rproc_cfg = { + .sw_reset = true, + .pwr_reset = true, + .bootaddr_mask = GENMASK(28, 1), +}; + +static const struct st_rproc_config st231_rproc_cfg = { + .sw_reset = true, + .pwr_reset = false, + .bootaddr_mask = GENMASK(31, 6), +}; + +static const struct of_device_id st_rproc_match[] = { + { .compatible = "st,st40-rproc", .data = &st40_rproc_cfg }, + { .compatible = "st,st231-rproc", .data = &st231_rproc_cfg }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_rproc_match); + +static int st_rproc_parse_dt(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rproc *rproc = platform_get_drvdata(pdev); + struct st_rproc *ddata = rproc->priv; + struct device_node *np = dev->of_node; + int err; + + if (ddata->config->sw_reset) { + ddata->sw_reset = devm_reset_control_get(dev, "sw_reset"); + if (IS_ERR(ddata->sw_reset)) { + dev_err(dev, "Failed to get S/W Reset\n"); + return PTR_ERR(ddata->sw_reset); + } + } + + if (ddata->config->pwr_reset) { + ddata->pwr_reset = devm_reset_control_get(dev, "pwr_reset"); + if (IS_ERR(ddata->pwr_reset)) { + dev_err(dev, "Failed to get Power Reset\n"); + return PTR_ERR(ddata->pwr_reset); + } + } + + ddata->clk = devm_clk_get(dev, NULL); + if (IS_ERR(ddata->clk)) { + dev_err(dev, "Failed to get clock\n"); + return PTR_ERR(ddata->clk); + } + + err = of_property_read_u32(np, "clock-frequency", &ddata->clk_rate); + if (err) { + dev_err(dev, "failed to get clock frequency\n"); + return err; + } + + ddata->boot_base = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (!ddata->boot_base) { + dev_err(dev, "Boot base not found\n"); + return -EINVAL; + } + + err = of_property_read_u32_index(np, "st,syscfg", 1, + &ddata->boot_offset); + if (err) { + dev_err(dev, "Boot offset not found\n"); + return -EINVAL; + } + + err = of_reserved_mem_device_init(dev); + if (err) { + dev_err(dev, "Failed to obtain shared memory\n"); + return err; + } + + err = clk_prepare(ddata->clk); + if (err) + dev_err(dev, "failed to get clock\n"); + + return err; +} + +static int st_rproc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct of_device_id *match; + struct st_rproc *ddata; + struct device_node *np = dev->of_node; + struct rproc *rproc; + int enabled; + int ret; + + match = of_match_device(st_rproc_match, dev); + if (!match || !match->data) { + dev_err(dev, "No device match found\n"); + return -ENODEV; + } + + rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata)); + if (!rproc) + return -ENOMEM; + + rproc->has_iommu = false; + ddata = rproc->priv; + ddata->config = (struct st_rproc_config *)match->data; + + platform_set_drvdata(pdev, rproc); + + ret = st_rproc_parse_dt(pdev); + if (ret) + goto free_rproc; + + enabled = st_rproc_state(pdev); + if (enabled < 0) + goto free_rproc; + + if (enabled) { + atomic_inc(&rproc->power); + rproc->state = RPROC_RUNNING; + } else { + clk_set_rate(ddata->clk, ddata->clk_rate); + } + + ret = rproc_add(rproc); + if (ret) + goto free_rproc; + + return 0; + +free_rproc: + rproc_put(rproc); + return ret; +} + +static int st_rproc_remove(struct platform_device *pdev) +{ + struct rproc *rproc = platform_get_drvdata(pdev); + struct st_rproc *ddata = rproc->priv; + + rproc_del(rproc); + + clk_disable_unprepare(ddata->clk); + + of_reserved_mem_device_release(&pdev->dev); + + rproc_put(rproc); + + return 0; +} + +static struct platform_driver st_rproc_driver = { + .probe = st_rproc_probe, + .remove = st_rproc_remove, + .driver = { + .name = "st-rproc", + .of_match_table = of_match_ptr(st_rproc_match), + }, +}; +module_platform_driver(st_rproc_driver); + +MODULE_DESCRIPTION("ST Remote Processor Control Driver"); +MODULE_AUTHOR("Ludovic Barre "); +MODULE_LICENSE("GPL v2"); -- cgit From 5e9ebbd87a99ecc6abb74325b0ac63c46891f6f3 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Sat, 30 Jan 2016 14:01:12 +0600 Subject: x86/boot: Micro-optimize reset_early_page_tables() Save 25 bytes of code and make the bootup a tiny bit faster: text data bss dec filename 9735144 4970776 15474688 30180608 vmlinux.old 9735119 4970776 15474688 30180583 vmlinux Signed-off-by: Alexander Kuleshov Cc: Alexander Popov Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1454140872-16926-1-git-send-email-kuleshovmail@gmail.com [ Fixed various small details. ] Signed-off-by: Ingo Molnar --- arch/x86/kernel/head64.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index f129a9af6357..35843caa4ea7 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -40,13 +40,8 @@ pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX); /* Wipe all early page tables except for the kernel symbol map */ static void __init reset_early_page_tables(void) { - unsigned long i; - - for (i = 0; i < PTRS_PER_PGD-1; i++) - early_level4_pgt[i].pgd = 0; - + memset(early_level4_pgt, 0, sizeof(pgd_t)*(PTRS_PER_PGD-1)); next_early_pgt = 0; - write_cr3(__pa_nodebug(early_level4_pgt)); } @@ -54,7 +49,6 @@ static void __init reset_early_page_tables(void) int __init early_make_pgtable(unsigned long address) { unsigned long physaddr = address - __PAGE_OFFSET; - unsigned long i; pgdval_t pgd, *pgd_p; pudval_t pud, *pud_p; pmdval_t pmd, *pmd_p; @@ -81,8 +75,7 @@ again: } pud_p = (pudval_t *)early_dynamic_pgts[next_early_pgt++]; - for (i = 0; i < PTRS_PER_PUD; i++) - pud_p[i] = 0; + memset(pud_p, 0, sizeof(pud_p) * PTRS_PER_PUD); *pgd_p = (pgdval_t)pud_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE; } pud_p += pud_index(address); @@ -97,8 +90,7 @@ again: } pmd_p = (pmdval_t *)early_dynamic_pgts[next_early_pgt++]; - for (i = 0; i < PTRS_PER_PMD; i++) - pmd_p[i] = 0; + memset(pmd_p, 0, sizeof(pmd_p) * PTRS_PER_PMD); *pud_p = (pudval_t)pmd_p - __START_KERNEL_map + phys_base + _KERNPG_TABLE; } pmd = (physaddr & PMD_MASK) + early_pmd_flags; -- cgit From 9babd5c8caa6e62c116efc3a64a09f65af4112b0 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:17 +0100 Subject: resource: Add System RAM resource type The IORESOURCE_MEM I/O resource type is used for all types of memory-mapped ranges, ex. System RAM, System ROM, Video RAM, Persistent Memory, PCI Bus, PCI MMCONFIG, ACPI Tables, IOAPIC, reserved, and so on. This requires walk_system_ram_range(), walk_system_ram_res(), and region_intersects() to use strcmp() against string "System RAM" to search for System RAM ranges in the iomem table, which is inefficient. __ioremap_caller() and reserve_memtype() on x86, for instance, call walk_system_ram_range() for every request to check if a given range is in System RAM ranges. However, adding a new I/O resource type for System RAM is not a viable option, see [1]. There are approx. 3800 references to IORESOURCE_MEM in the kernel/drivers, which makes it very difficult to distinguish their usages between new type and IORESOURCE_MEM. The I/O resource types are also used by the PNP subsystem. Therefore, introduce an extended I/O resource type, IORESOURCE_SYSTEM_RAM, which consists of IORESOURCE_MEM and a new modifier flag IORESOURCE_SYSRAM, see [2]. To keep the code 'if (resource_type(r) == IORESOURCE_MEM)' still working for System RAM, resource_ext_type() is added for extracting extended type bits. Link[1]: http://lkml.kernel.org/r/1449168859.9855.54.camel@hpe.com Link[2]: http://lkml.kernel.org/r/CA+55aFy4WQrWexC4u2LxX9Mw2NVoznw7p3Yh=iF4Xtf7zKWnRw@mail.gmail.com Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Hanjun Guo Cc: Jakub Sitnicki Cc: Jiang Liu Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- include/linux/ioport.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 24bea087e7af..4b65d944717f 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -49,12 +49,19 @@ struct resource { #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ #define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */ +#define IORESOURCE_EXT_TYPE_BITS 0x01000000 /* Resource extended types */ +#define IORESOURCE_SYSRAM 0x01000000 /* System RAM (modifier) */ + #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ + #define IORESOURCE_DISABLED 0x10000000 #define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */ #define IORESOURCE_AUTO 0x40000000 #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ +/* I/O resource extended types */ +#define IORESOURCE_SYSTEM_RAM (IORESOURCE_MEM|IORESOURCE_SYSRAM) + /* PnP IRQ specific bits (IORESOURCE_BITS) */ #define IORESOURCE_IRQ_HIGHEDGE (1<<0) #define IORESOURCE_IRQ_LOWEDGE (1<<1) @@ -170,6 +177,10 @@ static inline unsigned long resource_type(const struct resource *res) { return res->flags & IORESOURCE_TYPE_BITS; } +static inline unsigned long resource_ext_type(const struct resource *res) +{ + return res->flags & IORESOURCE_EXT_TYPE_BITS; +} /* True iff r1 completely contains r2 */ static inline bool resource_contains(struct resource *r1, struct resource *r2) { -- cgit From a3650d53ba16ec412185abb98f231e9ba6bcdc65 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:18 +0100 Subject: resource: Handle resource flags properly I/O resource flags consist of I/O resource types and modifier bits. Therefore, checking an I/O resource type in 'flags' must be performed with a bitwise operation. Fix find_next_iomem_res() and region_intersects() that simply compare 'flags' against a given value. Also change __request_region() to set 'res->flags' from resource_type() and resource_ext_type() of the parent, so that children nodes will inherit the extended I/O resource type. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jakub Sitnicki Cc: Jiang Liu Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Cc: Toshi Kani Cc: Vinod Koul Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- kernel/resource.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index 09c0597840b0..96afc8027487 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -358,7 +358,7 @@ static int find_next_iomem_res(struct resource *res, char *name, read_lock(&resource_lock); for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) { - if (p->flags != res->flags) + if ((p->flags & res->flags) != res->flags) continue; if (name && strcmp(p->name, name)) continue; @@ -519,7 +519,8 @@ int region_intersects(resource_size_t start, size_t size, const char *name) read_lock(&resource_lock); for (p = iomem_resource.child; p ; p = p->sibling) { - bool is_type = strcmp(p->name, name) == 0 && p->flags == flags; + bool is_type = strcmp(p->name, name) == 0 && + ((p->flags & flags) == flags); if (start >= p->start && start <= p->end) is_type ? type++ : other++; @@ -1071,7 +1072,7 @@ struct resource * __request_region(struct resource *parent, res->name = name; res->start = start; res->end = start + n - 1; - res->flags = resource_type(parent); + res->flags = resource_type(parent) | resource_ext_type(parent); res->flags |= IORESOURCE_BUSY | flags; write_lock(&resource_lock); -- cgit From 43ee493bde78da00deaf5737925365c691a036ad Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:19 +0100 Subject: resource: Add I/O resource descriptor walk_iomem_res() and region_intersects() still need to use strcmp() for searching a resource entry by @name in the iomem table. This patch introduces I/O resource descriptor 'desc' in struct resource for the iomem search interfaces. Drivers can assign their unique descriptor to a range when they support the search interfaces. Otherwise, 'desc' is set to IORES_DESC_NONE (0). This avoids changing most of the drivers as they typically allocate resource entries statically, or by calling alloc_resource(), kzalloc(), or alloc_bootmem_low(), which set the field to zero by default. A later patch will address some drivers that use kmalloc() without zero'ing the field. Also change release_mem_region_adjustable() to set 'desc' when its resource entry gets separated. Other resource interfaces are also changed to initialize 'desc' explicitly although alloc_resource() sets it to 0. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jakub Sitnicki Cc: Jiang Liu Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-4-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- include/linux/ioport.h | 18 ++++++++++++++++++ kernel/resource.c | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 4b65d944717f..983bea05d69c 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -20,6 +20,7 @@ struct resource { resource_size_t end; const char *name; unsigned long flags; + unsigned long desc; struct resource *parent, *sibling, *child; }; @@ -112,6 +113,22 @@ struct resource { /* PCI control bits. Shares IORESOURCE_BITS with above PCI ROM. */ #define IORESOURCE_PCI_FIXED (1<<4) /* Do not move resource */ +/* + * I/O Resource Descriptors + * + * Descriptors are used by walk_iomem_res_desc() and region_intersects() + * for searching a specific resource range in the iomem table. Assign + * a new descriptor when a resource range supports the search interfaces. + * Otherwise, resource.desc must be set to IORES_DESC_NONE (0). + */ +enum { + IORES_DESC_NONE = 0, + IORES_DESC_CRASH_KERNEL = 1, + IORES_DESC_ACPI_TABLES = 2, + IORES_DESC_ACPI_NV_STORAGE = 3, + IORES_DESC_PERSISTENT_MEMORY = 4, + IORES_DESC_PERSISTENT_MEMORY_LEGACY = 5, +}; /* helpers to define resources */ #define DEFINE_RES_NAMED(_start, _size, _name, _flags) \ @@ -120,6 +137,7 @@ struct resource { .end = (_start) + (_size) - 1, \ .name = (_name), \ .flags = (_flags), \ + .desc = IORES_DESC_NONE, \ } #define DEFINE_RES_IO_NAMED(_start, _size, _name) \ diff --git a/kernel/resource.c b/kernel/resource.c index 96afc8027487..61512e972ece 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -949,6 +949,7 @@ static void __init __reserve_region_with_split(struct resource *root, res->start = start; res->end = end; res->flags = IORESOURCE_BUSY; + res->desc = IORES_DESC_NONE; while (1) { @@ -983,6 +984,7 @@ static void __init __reserve_region_with_split(struct resource *root, next_res->start = conflict->end + 1; next_res->end = end; next_res->flags = IORESOURCE_BUSY; + next_res->desc = IORES_DESC_NONE; } } else { res->start = conflict->end + 1; @@ -1074,6 +1076,7 @@ struct resource * __request_region(struct resource *parent, res->end = start + n - 1; res->flags = resource_type(parent) | resource_ext_type(parent); res->flags |= IORESOURCE_BUSY | flags; + res->desc = IORES_DESC_NONE; write_lock(&resource_lock); @@ -1238,6 +1241,7 @@ int release_mem_region_adjustable(struct resource *parent, new_res->start = end + 1; new_res->end = res->end; new_res->flags = res->flags; + new_res->desc = res->desc; new_res->parent = res->parent; new_res->sibling = res->sibling; new_res->child = NULL; @@ -1413,6 +1417,7 @@ static int __init reserve_setup(char *str) res->start = io_start; res->end = io_start + io_num - 1; res->flags = IORESOURCE_BUSY; + res->desc = IORES_DESC_NONE; res->child = NULL; if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0) reserved = x+1; -- cgit From f33b14a4b96b185634848046f54fb0d5028566a9 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:20 +0100 Subject: x86/e820: Set System RAM type and descriptor Change e820_reserve_resources() to set 'flags' and 'desc' from e820 types. Set E820_RESERVED_KERN and E820_RAM's (System RAM) io resource type to IORESOURCE_SYSTEM_RAM. Do the same for "Kernel data", "Kernel code", and "Kernel bss", which are child nodes of System RAM. I/O resource descriptor is set to 'desc' for entries that are (and will be) target ranges of walk_iomem_res() and region_intersects(). Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Dave Young Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jiri Kosina Cc: Joerg Roedel Cc: Juergen Gross Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Mark Salter Cc: Paolo Bonzini Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: Toshi Kani Cc: WANG Chao Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/e820.c | 38 +++++++++++++++++++++++++++++++++++++- arch/x86/kernel/setup.c | 6 +++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 569c1e4f96fe..837365f10912 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -925,6 +925,41 @@ static const char *e820_type_to_string(int e820_type) } } +static unsigned long e820_type_to_iomem_type(int e820_type) +{ + switch (e820_type) { + case E820_RESERVED_KERN: + case E820_RAM: + return IORESOURCE_SYSTEM_RAM; + case E820_ACPI: + case E820_NVS: + case E820_UNUSABLE: + case E820_PRAM: + case E820_PMEM: + default: + return IORESOURCE_MEM; + } +} + +static unsigned long e820_type_to_iores_desc(int e820_type) +{ + switch (e820_type) { + case E820_ACPI: + return IORES_DESC_ACPI_TABLES; + case E820_NVS: + return IORES_DESC_ACPI_NV_STORAGE; + case E820_PMEM: + return IORES_DESC_PERSISTENT_MEMORY; + case E820_PRAM: + return IORES_DESC_PERSISTENT_MEMORY_LEGACY; + case E820_RESERVED_KERN: + case E820_RAM: + case E820_UNUSABLE: + default: + return IORES_DESC_NONE; + } +} + static bool do_mark_busy(u32 type, struct resource *res) { /* this is the legacy bios/dos rom-shadow + mmio region */ @@ -967,7 +1002,8 @@ void __init e820_reserve_resources(void) res->start = e820.map[i].addr; res->end = end; - res->flags = IORESOURCE_MEM; + res->flags = e820_type_to_iomem_type(e820.map[i].type); + res->desc = e820_type_to_iores_desc(e820.map[i].type); /* * don't register the region that could be conflicted with diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d3d80e6d42a2..aa52c1009475 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -152,21 +152,21 @@ static struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource bss_resource = { .name = "Kernel bss", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; -- cgit From 03cb525eb25018cf5f3da01d0f1391fc8b37805a Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:21 +0100 Subject: ia64: Set System RAM type and descriptor Change efi_initialize_iomem_resources() to set 'flags' and 'desc' for EFI memory types. IORESOURCE_SYSRAM, a modifier bit, is set for System RAM as IORESOURCE_MEM is already set. IORESOURCE_SYSTEM_RAM is defined as (IORESOURCE_MEM|IORESOURCE_SYSRAM). I/O resource descriptor is set for "ACPI Non-volatile Storage" and "Persistent Memory". Also set IORESOURCE_SYSTEM_RAM for "Kernel code", "Kernel data", and "Kernel bss". Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: Tony Luck Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Matt Fleming Cc: Peter Zijlstra Cc: Rusty Russell Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-efi Cc: linux-ia64@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/ia64/kernel/efi.c | 13 ++++++++++--- arch/ia64/kernel/setup.c | 6 +++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index caae3f4e4341..300dac3702f1 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -1178,7 +1178,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, efi_memory_desc_t *md; u64 efi_desc_size; char *name; - unsigned long flags; + unsigned long flags, desc; efi_map_start = __va(ia64_boot_param->efi_memmap); efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; @@ -1193,6 +1193,8 @@ efi_initialize_iomem_resources(struct resource *code_resource, continue; flags = IORESOURCE_MEM | IORESOURCE_BUSY; + desc = IORES_DESC_NONE; + switch (md->type) { case EFI_MEMORY_MAPPED_IO: @@ -1207,14 +1209,17 @@ efi_initialize_iomem_resources(struct resource *code_resource, if (md->attribute & EFI_MEMORY_WP) { name = "System ROM"; flags |= IORESOURCE_READONLY; - } else if (md->attribute == EFI_MEMORY_UC) + } else if (md->attribute == EFI_MEMORY_UC) { name = "Uncached RAM"; - else + } else { name = "System RAM"; + flags |= IORESOURCE_SYSRAM; + } break; case EFI_ACPI_MEMORY_NVS: name = "ACPI Non-volatile Storage"; + desc = IORES_DESC_ACPI_NV_STORAGE; break; case EFI_UNUSABLE_MEMORY: @@ -1224,6 +1229,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, case EFI_PERSISTENT_MEMORY: name = "Persistent Memory"; + desc = IORES_DESC_PERSISTENT_MEMORY; break; case EFI_RESERVED_TYPE: @@ -1246,6 +1252,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, res->start = md->phys_addr; res->end = md->phys_addr + efi_md_size(md) - 1; res->flags = flags; + res->desc = desc; if (insert_resource(&iomem_resource, res) < 0) kfree(res); diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 4f118b0d3091..2029a38a72ae 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -80,17 +80,17 @@ unsigned long vga_console_membase; static struct resource data_resource = { .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource code_resource = { .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource bss_resource = { .name = "Kernel bss", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; unsigned long ia64_max_cacheline_size; -- cgit From 35d98e93fe6a7ab612f6b389ce42c1dc135d6eef Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:22 +0100 Subject: arch: Set IORESOURCE_SYSTEM_RAM flag for System RAM Set IORESOURCE_SYSTEM_RAM in flags of resource ranges with "System RAM", "Kernel code", "Kernel data", and "Kernel bss". Note that: - IORESOURCE_SYSRAM (i.e. modifier bit) is set in flags when IORESOURCE_MEM is already set. IORESOURCE_SYSTEM_RAM is defined as (IORESOURCE_MEM|IORESOURCE_SYSRAM). - Some archs do not set 'flags' for children nodes, such as "Kernel code". This patch does not change 'flags' in this case. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mips@linux-mips.org Cc: linux-mm Cc: linux-parisc@vger.kernel.org Cc: linux-s390@vger.kernel.org Cc: linux-sh@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Cc: sparclinux@vger.kernel.org Link: http://lkml.kernel.org/r/1453841853-11383-7-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/arm/kernel/setup.c | 6 +++--- arch/arm64/kernel/setup.c | 6 +++--- arch/avr32/kernel/setup.c | 6 +++--- arch/m32r/kernel/setup.c | 4 ++-- arch/mips/kernel/setup.c | 10 ++++++---- arch/parisc/mm/init.c | 6 +++--- arch/powerpc/mm/mem.c | 2 +- arch/s390/kernel/setup.c | 8 ++++---- arch/score/kernel/setup.c | 2 +- arch/sh/kernel/setup.c | 8 ++++---- arch/sparc/mm/init_64.c | 8 ++++---- arch/tile/kernel/setup.c | 11 ++++++++--- arch/unicore32/kernel/setup.c | 6 +++--- 13 files changed, 45 insertions(+), 38 deletions(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7d0cba6f1cc5..139791ed473d 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -176,13 +176,13 @@ static struct resource mem_res[] = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_SYSTEM_RAM }, { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_SYSTEM_RAM } }; @@ -851,7 +851,7 @@ static void __init request_standard_resources(const struct machine_desc *mdesc) res->name = "System RAM"; res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 8119479147db..450987d99b9b 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -73,13 +73,13 @@ static struct resource mem_res[] = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_SYSTEM_RAM }, { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_SYSTEM_RAM } }; @@ -210,7 +210,7 @@ static void __init request_standard_resources(void) res->name = "System RAM"; res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index 209ae5ad3495..e6928896da2a 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c @@ -49,13 +49,13 @@ static struct resource __initdata kernel_data = { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_MEM, + .flags = IORESOURCE_SYSTEM_RAM, }; static struct resource __initdata kernel_code = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_MEM, + .flags = IORESOURCE_SYSTEM_RAM, .sibling = &kernel_data, }; @@ -134,7 +134,7 @@ add_physical_memory(resource_size_t start, resource_size_t end) new->start = start; new->end = end; new->name = "System RAM"; - new->flags = IORESOURCE_MEM; + new->flags = IORESOURCE_SYSTEM_RAM; *pprev = new; } diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index a5ecef7188ba..136c69f1fb8a 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c @@ -70,14 +70,14 @@ static struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; unsigned long memory_start; diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 569a7d5242dd..c745f0ea2577 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -732,21 +732,23 @@ static void __init resource_init(void) end = HIGHMEM_START - 1; res = alloc_bootmem(sizeof(struct resource)); + + res->start = start; + res->end = end; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + switch (boot_mem_map.map[i].type) { case BOOT_MEM_RAM: case BOOT_MEM_INIT_RAM: case BOOT_MEM_ROM_DATA: res->name = "System RAM"; + res->flags |= IORESOURCE_SYSRAM; break; case BOOT_MEM_RESERVED: default: res->name = "reserved"; } - res->start = start; - res->end = end; - - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); /* diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 1b366c477687..3c07d6b96877 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -55,12 +55,12 @@ signed char pfnnid_map[PFNNID_MAP_MAX] __read_mostly; static struct resource data_resource = { .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource code_resource = { .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource pdcdata_resource = { @@ -201,7 +201,7 @@ static void __init setup_bootmem(void) res->name = "System RAM"; res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT; res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); } diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index d0f0a514b04e..f078a1f94fc2 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -541,7 +541,7 @@ static int __init add_system_ram_resources(void) res->name = "System RAM"; res->start = base; res->end = base + size - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; WARN_ON(request_resource(&iomem_resource, res) < 0); } } diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 9220db5c996a..cedb0198675f 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -374,17 +374,17 @@ static void __init setup_lowcore(void) static struct resource code_resource = { .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource data_resource = { .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource bss_resource = { .name = "Kernel bss", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource __initdata *standard_resources[] = { @@ -408,7 +408,7 @@ static void __init setup_resources(void) for_each_memblock(memory, reg) { res = alloc_bootmem_low(sizeof(*res)); - res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; + res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM; res->name = "System RAM"; res->start = reg->base; diff --git a/arch/score/kernel/setup.c b/arch/score/kernel/setup.c index b48459afefdd..f3a0649ab521 100644 --- a/arch/score/kernel/setup.c +++ b/arch/score/kernel/setup.c @@ -101,7 +101,7 @@ static void __init resource_init(void) res->name = "System RAM"; res->start = MEMORY_START; res->end = MEMORY_START + MEMORY_SIZE - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); request_resource(res, &code_resource); diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index de19cfa768f2..3f1c18b28e8a 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -78,17 +78,17 @@ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, }; static struct resource code_resource = { .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource data_resource = { .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; static struct resource bss_resource = { .name = "Kernel bss", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM, + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, }; unsigned long memory_start; @@ -202,7 +202,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, res->name = "System RAM"; res->start = start; res->end = end - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; if (request_resource(&iomem_resource, res)) { pr_err("unable to request memory_resource 0x%lx 0x%lx\n", diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 6f216853f272..1cfe6aab7a11 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -2863,17 +2863,17 @@ void hugetlb_setup(struct pt_regs *regs) static struct resource code_resource = { .name = "Kernel code", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource data_resource = { .name = "Kernel data", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource bss_resource = { .name = "Kernel bss", - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static inline resource_size_t compute_kern_paddr(void *addr) @@ -2909,7 +2909,7 @@ static int __init report_memory(void) res->name = "System RAM"; res->start = pavail[i].phys_addr; res->end = pavail[i].phys_addr + pavail[i].reg_size - 1; - res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; + res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM; if (insert_resource(&iomem_resource, res) < 0) { pr_warn("Resource insertion failed.\n"); diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index bbb855de6569..a992238e9b58 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -1632,14 +1632,14 @@ static struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; static struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; /* @@ -1673,10 +1673,15 @@ insert_ram_resource(u64 start_pfn, u64 end_pfn, bool reserved) kzalloc(sizeof(struct resource), GFP_ATOMIC); if (!res) return NULL; - res->name = reserved ? "Reserved" : "System RAM"; res->start = start_pfn << PAGE_SHIFT; res->end = (end_pfn << PAGE_SHIFT) - 1; res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; + if (reserved) { + res->name = "Reserved"; + } else { + res->name = "System RAM"; + res->flags |= IORESOURCE_SYSRAM; + } if (insert_resource(&iomem_resource, res)) { kfree(res); return NULL; diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c index 3fa317f96122..c2bffa5614a4 100644 --- a/arch/unicore32/kernel/setup.c +++ b/arch/unicore32/kernel/setup.c @@ -72,13 +72,13 @@ static struct resource mem_res[] = { .name = "Kernel code", .start = 0, .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_SYSTEM_RAM }, { .name = "Kernel data", .start = 0, .end = 0, - .flags = IORESOURCE_MEM + .flags = IORESOURCE_SYSTEM_RAM } }; @@ -211,7 +211,7 @@ request_standard_resources(struct meminfo *mi) res->name = "System RAM"; res->start = mi->bank[i].start; res->end = mi->bank[i].start + mi->bank[i].size - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); -- cgit From 1a085d0727afaedb9506f04798516298b1676e11 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:23 +0100 Subject: kexec: Set IORESOURCE_SYSTEM_RAM for System RAM Set proper ioresource flags and types for crash kernel reservation areas. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Dave Young Cc: Andrew Morton Cc: Andy Lutomirski Cc: Baoquan He Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: HATAYAMA Daisuke Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Minfei Huang Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: Vivek Goyal Cc: kexec@lists.infradead.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- kernel/kexec_core.c | 8 +++++--- kernel/kexec_file.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index 8dc659144869..8d34308ea449 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -66,13 +66,15 @@ struct resource crashk_res = { .name = "Crash kernel", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, + .desc = IORES_DESC_CRASH_KERNEL }; struct resource crashk_low_res = { .name = "Crash kernel", .start = 0, .end = 0, - .flags = IORESOURCE_BUSY | IORESOURCE_MEM + .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM, + .desc = IORES_DESC_CRASH_KERNEL }; int kexec_should_crash(struct task_struct *p) @@ -959,7 +961,7 @@ int crash_shrink_memory(unsigned long new_size) ram_res->start = end; ram_res->end = crashk_res.end; - ram_res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; + ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM; ram_res->name = "System RAM"; crashk_res.end = end - 1; diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 007b791f676d..2bfcdc064116 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -525,7 +525,7 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, /* Walk the RAM ranges and allocate a suitable range for the buffer */ if (image->type == KEXEC_TYPE_CRASH) ret = walk_iomem_res("Crash kernel", - IORESOURCE_MEM | IORESOURCE_BUSY, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, crashk_res.start, crashk_res.end, kbuf, locate_mem_hole_callback); else -- cgit From 782b86641e5d471e9eb1cf0072c012d2f758e568 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:24 +0100 Subject: xen, mm: Set IORESOURCE_SYSTEM_RAM to System RAM Set IORESOURCE_SYSTEM_RAM in struct resource.flags of "System RAM" entries. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: David Vrabel # xen Cc: Andrew Banman Cc: Andrew Morton Cc: Andy Lutomirski Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: David Rientjes Cc: Denys Vlasenko Cc: Gu Zheng Cc: H. Peter Anvin Cc: Konrad Rzeszutek Wilk Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Mel Gorman Cc: Naoya Horiguchi Cc: Peter Zijlstra Cc: Tang Chen Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1453841853-11383-9-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- drivers/xen/balloon.c | 2 +- mm/memory_hotplug.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 12eab503efd1..dc4305b407bf 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -257,7 +257,7 @@ static struct resource *additional_memory_resource(phys_addr_t size) return NULL; res->name = "System RAM"; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; ret = allocate_resource(&iomem_resource, res, size, 0, -1, diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 4af58a3a8ffa..979b18cbd343 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -138,7 +138,7 @@ static struct resource *register_memory_resource(u64 start, u64 size) res->name = "System RAM"; res->start = start; res->end = start + size - 1; - res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; if (request_resource(&iomem_resource, res) < 0) { pr_debug("System RAM resource %pR cannot be added\n", res); kfree(res); -- cgit From 9a975bee4b3945b271bcff18a520d4863c210f8b Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:25 +0100 Subject: drivers: Initialize resource entry to zero I/O resource descriptor, 'desc' in struct resource, needs to be initialized to zero by default. Some drivers call kmalloc() to allocate a resource entry, but do not initialize it to zero by memset(). Change these drivers to call kzalloc(), instead. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: Alexandre Bounine Acked-by: Helge Deller Acked-by: Rafael J. Wysocki Acked-by: Simon Horman Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-acpi@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: linux-parisc@vger.kernel.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-sh@vger.kernel.org Link: http://lkml.kernel.org/r/1453841853-11383-10-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- drivers/acpi/acpi_platform.c | 2 +- drivers/parisc/eisa_enumerator.c | 4 ++-- drivers/rapidio/rio.c | 8 ++++---- drivers/sh/superhyway/superhyway.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 296b7a14893a..b6f7fa3a1d40 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -62,7 +62,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) if (count < 0) { return NULL; } else if (count > 0) { - resources = kmalloc(count * sizeof(struct resource), + resources = kzalloc(count * sizeof(struct resource), GFP_KERNEL); if (!resources) { dev_err(&adev->dev, "No memory for resources\n"); diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c index a656d9e83343..21905fef2cbf 100644 --- a/drivers/parisc/eisa_enumerator.c +++ b/drivers/parisc/eisa_enumerator.c @@ -91,7 +91,7 @@ static int configure_memory(const unsigned char *buf, for (i=0;iname = name; @@ -183,7 +183,7 @@ static int configure_port(const unsigned char *buf, struct resource *io_parent, for (i=0;iname = board; res->start = get_16(buf+len+1); res->end = get_16(buf+len+1)+(c&HPEE_PORT_SIZE_MASK)+1; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index d7b87c64b7cd..e220edc85c68 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -117,7 +117,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, if (mport->ops->open_inb_mbox == NULL) goto out; - res = kmalloc(sizeof(struct resource), GFP_KERNEL); + res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_mbox_res(res, mbox, mbox); @@ -185,7 +185,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, if (mport->ops->open_outb_mbox == NULL) goto out; - res = kmalloc(sizeof(struct resource), GFP_KERNEL); + res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_mbox_res(res, mbox, mbox); @@ -285,7 +285,7 @@ int rio_request_inb_dbell(struct rio_mport *mport, { int rc = 0; - struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_dbell_res(res, start, end); @@ -360,7 +360,7 @@ int rio_release_inb_dbell(struct rio_mport *mport, u16 start, u16 end) struct resource *rio_request_outb_dbell(struct rio_dev *rdev, u16 start, u16 end) { - struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL); + struct resource *res = kzalloc(sizeof(struct resource), GFP_KERNEL); if (res) { rio_init_dbell_res(res, start, end); diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 2d9e7f3d5611..bb1fb7712134 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -66,7 +66,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, superhyway_read_vcr(dev, base, &dev->vcr); if (!dev->resource) { - dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL); + dev->resource = kzalloc(sizeof(struct resource), GFP_KERNEL); if (!dev->resource) { kfree(dev); return -ENOMEM; -- cgit From bd7e6cb30ced147292d854a54d4a1f5c5a05d927 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:26 +0100 Subject: resource: Change walk_system_ram() to use System RAM type Now that all System RAM resource entries have been initialized to IORESOURCE_SYSTEM_RAM type, change walk_system_ram_res() and walk_system_ram_range() to call find_next_iomem_res() by setting @res.flags to IORESOURCE_SYSTEM_RAM and @name to NULL. With this change, they walk through the iomem table to find System RAM ranges without the need to do strcmp() on the resource names. No functional change is made to the interfaces. Signed-off-by: Toshi Kani [ Boris: fixup comments. ] Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jakub Sitnicki Cc: Jiang Liu Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-11-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- kernel/resource.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/kernel/resource.c b/kernel/resource.c index 61512e972ece..994f1e41269b 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -415,11 +415,11 @@ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, } /* - * This function calls callback against all memory range of "System RAM" - * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. - * Now, this function is only for "System RAM". This function deals with - * full ranges and not pfn. If resources are not pfn aligned, dealing - * with pfn can truncate ranges. + * This function calls the @func callback against all memory ranges of type + * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY. + * Now, this function is only for System RAM, it deals with full ranges and + * not PFNs. If resources are not PFN-aligned, dealing with PFNs can truncate + * ranges. */ int walk_system_ram_res(u64 start, u64 end, void *arg, int (*func)(u64, u64, void *)) @@ -430,10 +430,10 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, res.start = start; res.end = end; - res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && - (!find_next_iomem_res(&res, "System RAM", true))) { + (!find_next_iomem_res(&res, NULL, true))) { ret = (*func)(res.start, res.end, arg); if (ret) break; @@ -446,9 +446,9 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, #if !defined(CONFIG_ARCH_HAS_WALK_MEMORY) /* - * This function calls callback against all memory range of "System RAM" - * which are marked as IORESOURCE_MEM and IORESOUCE_BUSY. - * Now, this function is only for "System RAM". + * This function calls the @func callback against all memory ranges of type + * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY. + * It is to be used only for System RAM. */ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, void *arg, int (*func)(unsigned long, unsigned long, void *)) @@ -460,10 +460,10 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, res.start = (u64) start_pfn << PAGE_SHIFT; res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1; - res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && - (find_next_iomem_res(&res, "System RAM", true) >= 0)) { + (find_next_iomem_res(&res, NULL, true) >= 0)) { pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; end_pfn = (res.end + 1) >> PAGE_SHIFT; if (end_pfn > pfn) @@ -484,7 +484,7 @@ static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg) } /* * This generic page_is_ram() returns true if specified address is - * registered as "System RAM" in iomem_resource list. + * registered as System RAM in iomem_resource list. */ int __weak page_is_ram(unsigned long pfn) { -- cgit From 05fee7cfab7fa9d57e71f00bdd8fcff0cf5044a0 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:27 +0100 Subject: arm/samsung: Change s3c_pm_run_res() to use System RAM type Change s3c_pm_run_res() to check with IORESOURCE_SYSTEM_RAM, instead of strcmp() with "System RAM", to walk through System RAM ranges in the iomem table. No functional change is made to the interface. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Krzysztof Kozlowski Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Kukjin Kim Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mm Cc: linux-samsung-soc@vger.kernel.org Link: http://lkml.kernel.org/r/1453841853-11383-12-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/arm/plat-samsung/pm-check.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c index 04aff2c31b46..70f2f699bed3 100644 --- a/arch/arm/plat-samsung/pm-check.c +++ b/arch/arm/plat-samsung/pm-check.c @@ -53,8 +53,8 @@ static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg) if (ptr->child != NULL) s3c_pm_run_res(ptr->child, fn, arg); - if ((ptr->flags & IORESOURCE_MEM) && - strcmp(ptr->name, "System RAM") == 0) { + if ((ptr->flags & IORESOURCE_SYSTEM_RAM) + == IORESOURCE_SYSTEM_RAM) { S3C_PMDBG("Found system RAM at %08lx..%08lx\n", (unsigned long)ptr->start, (unsigned long)ptr->end); -- cgit From 1c29f25bf5d6c557017f619b638c619cbbf798c4 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:28 +0100 Subject: memremap: Change region_intersects() to take @flags and @desc Change region_intersects() to identify a target with @flags and @desc, instead of @name with strcmp(). Change the callers of region_intersects(), memremap() and devm_memremap(), to set IORESOURCE_SYSTEM_RAM in @flags and IORES_DESC_NONE in @desc when searching System RAM. Also, export region_intersects() so that the ACPI EINJ error injection driver can call this function in a later patch. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: Dan Williams Cc: Andrew Morton Cc: Andy Lutomirski Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jakub Sitnicki Cc: Jan Kara Cc: Jiang Liu Cc: Kees Cook Cc: Kirill A. Shutemov Cc: Konstantin Khlebnikov Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Michal Hocko Cc: Naoya Horiguchi Cc: Peter Zijlstra Cc: Tejun Heo Cc: Thomas Gleixner Cc: Toshi Kani Cc: Vlastimil Babka Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-13-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- include/linux/mm.h | 3 ++- kernel/memremap.c | 13 +++++++------ kernel/resource.c | 26 +++++++++++++++----------- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index f1cd22f2df1a..cd5a300d3397 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -385,7 +385,8 @@ enum { REGION_MIXED, }; -int region_intersects(resource_size_t offset, size_t size, const char *type); +int region_intersects(resource_size_t offset, size_t size, unsigned long flags, + unsigned long desc); /* Support for virtually mapped pages */ struct page *vmalloc_to_page(const void *addr); diff --git a/kernel/memremap.c b/kernel/memremap.c index e517a16cb426..293309cac061 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -47,7 +47,7 @@ static void *try_ram_remap(resource_size_t offset, size_t size) * being mapped does not have i/o side effects and the __iomem * annotation is not applicable. * - * MEMREMAP_WB - matches the default mapping for "System RAM" on + * MEMREMAP_WB - matches the default mapping for System RAM on * the architecture. This is usually a read-allocate write-back cache. * Morever, if MEMREMAP_WB is specified and the requested remap region is RAM * memremap() will bypass establishing a new mapping and instead return @@ -56,11 +56,12 @@ static void *try_ram_remap(resource_size_t offset, size_t size) * MEMREMAP_WT - establish a mapping whereby writes either bypass the * cache or are written through to memory and never exist in a * cache-dirty state with respect to program visibility. Attempts to - * map "System RAM" with this mapping type will fail. + * map System RAM with this mapping type will fail. */ void *memremap(resource_size_t offset, size_t size, unsigned long flags) { - int is_ram = region_intersects(offset, size, "System RAM"); + int is_ram = region_intersects(offset, size, + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE); void *addr = NULL; if (is_ram == REGION_MIXED) { @@ -76,7 +77,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags) * MEMREMAP_WB is special in that it can be satisifed * from the direct map. Some archs depend on the * capability of memremap() to autodetect cases where - * the requested range is potentially in "System RAM" + * the requested range is potentially in System RAM. */ if (is_ram == REGION_INTERSECTS) addr = try_ram_remap(offset, size); @@ -88,7 +89,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags) * If we don't have a mapping yet and more request flags are * pending then we will be attempting to establish a new virtual * address mapping. Enforce that this mapping is not aliasing - * "System RAM" + * System RAM. */ if (!addr && is_ram == REGION_INTERSECTS && flags) { WARN_ONCE(1, "memremap attempted on ram %pa size: %#lx\n", @@ -266,7 +267,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res, struct percpu_ref *ref, struct vmem_altmap *altmap) { int is_ram = region_intersects(res->start, resource_size(res), - "System RAM"); + IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE); resource_size_t key, align_start, align_size; struct dev_pagemap *pgmap; struct page_map *page_map; diff --git a/kernel/resource.c b/kernel/resource.c index 994f1e41269b..0041cedc47d6 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -496,31 +496,34 @@ EXPORT_SYMBOL_GPL(page_is_ram); * region_intersects() - determine intersection of region with known resources * @start: region start address * @size: size of region - * @name: name of resource (in iomem_resource) + * @flags: flags of resource (in iomem_resource) + * @desc: descriptor of resource (in iomem_resource) or IORES_DESC_NONE * * Check if the specified region partially overlaps or fully eclipses a - * resource identified by @name. Return REGION_DISJOINT if the region - * does not overlap @name, return REGION_MIXED if the region overlaps - * @type and another resource, and return REGION_INTERSECTS if the - * region overlaps @type and no other defined resource. Note, that - * REGION_INTERSECTS is also returned in the case when the specified - * region overlaps RAM and undefined memory holes. + * resource identified by @flags and @desc (optional with IORES_DESC_NONE). + * Return REGION_DISJOINT if the region does not overlap @flags/@desc, + * return REGION_MIXED if the region overlaps @flags/@desc and another + * resource, and return REGION_INTERSECTS if the region overlaps @flags/@desc + * and no other defined resource. Note that REGION_INTERSECTS is also + * returned in the case when the specified region overlaps RAM and undefined + * memory holes. * * region_intersect() is used by memory remapping functions to ensure * the user is not remapping RAM and is a vast speed up over walking * through the resource table page by page. */ -int region_intersects(resource_size_t start, size_t size, const char *name) +int region_intersects(resource_size_t start, size_t size, unsigned long flags, + unsigned long desc) { - unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY; resource_size_t end = start + size - 1; int type = 0; int other = 0; struct resource *p; read_lock(&resource_lock); for (p = iomem_resource.child; p ; p = p->sibling) { - bool is_type = strcmp(p->name, name) == 0 && - ((p->flags & flags) == flags); + bool is_type = (((p->flags & flags) == flags) && + ((desc == IORES_DESC_NONE) || + (desc == p->desc))); if (start >= p->start && start <= p->end) is_type ? type++ : other++; @@ -539,6 +542,7 @@ int region_intersects(resource_size_t start, size_t size, const char *name) return REGION_DISJOINT; } +EXPORT_SYMBOL_GPL(region_intersects); void __weak arch_remove_reservations(struct resource *avail) { -- cgit From 3f33647c41962401272bb60dce67e6094d14dbf2 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:29 +0100 Subject: resource: Add walk_iomem_res_desc() Add a new interface, walk_iomem_res_desc(), which walks through the iomem table by identifying a target with @flags and @desc. This interface provides the same functionality as walk_iomem_res(), but does not use strcmp() to @name for better efficiency. walk_iomem_res() is deprecated and will be removed in a later patch. Requested-by: Borislav Petkov Signed-off-by: Toshi Kani [ Fixup comments. ] Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Hanjun Guo Cc: Jakub Sitnicki Cc: Jiang Liu Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-14-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- include/linux/ioport.h | 3 +++ kernel/resource.c | 66 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 983bea05d69c..2a4a5e839965 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -268,6 +268,9 @@ extern int walk_system_ram_res(u64 start, u64 end, void *arg, int (*func)(u64, u64, void *)); extern int +walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end, + void *arg, int (*func)(u64, u64, void *)); +extern int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, void *arg, int (*func)(u64, u64, void *)); diff --git a/kernel/resource.c b/kernel/resource.c index 0041cedc47d6..37ed2fcb8246 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -333,14 +333,15 @@ int release_resource(struct resource *old) EXPORT_SYMBOL(release_resource); /* - * Finds the lowest iomem reosurce exists with-in [res->start.res->end) - * the caller must specify res->start, res->end, res->flags and "name". - * If found, returns 0, res is overwritten, if not found, returns -1. - * This walks through whole tree and not just first level children - * until and unless first_level_children_only is true. + * Finds the lowest iomem resource existing within [res->start.res->end). + * The caller must specify res->start, res->end, res->flags, and optionally + * desc and "name". If found, returns 0, res is overwritten, if not found, + * returns -1. + * This function walks the whole tree and not just first level children until + * and unless first_level_children_only is true. */ -static int find_next_iomem_res(struct resource *res, char *name, - bool first_level_children_only) +static int find_next_iomem_res(struct resource *res, unsigned long desc, + char *name, bool first_level_children_only) { resource_size_t start, end; struct resource *p; @@ -360,6 +361,8 @@ static int find_next_iomem_res(struct resource *res, char *name, for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) { if ((p->flags & res->flags) != res->flags) continue; + if ((desc != IORES_DESC_NONE) && (desc != p->desc)) + continue; if (name && strcmp(p->name, name)) continue; if (p->start > end) { @@ -385,12 +388,55 @@ static int find_next_iomem_res(struct resource *res, char *name, * Walks through iomem resources and calls func() with matching resource * ranges. This walks through whole tree and not just first level children. * All the memory ranges which overlap start,end and also match flags and + * desc are valid candidates. + * + * @desc: I/O resource descriptor. Use IORES_DESC_NONE to skip @desc check. + * @flags: I/O resource flags + * @start: start addr + * @end: end addr + * + * NOTE: For a new descriptor search, define a new IORES_DESC in + * and set it in 'desc' of a target resource entry. + */ +int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, + u64 end, void *arg, int (*func)(u64, u64, void *)) +{ + struct resource res; + u64 orig_end; + int ret = -1; + + res.start = start; + res.end = end; + res.flags = flags; + orig_end = res.end; + + while ((res.start < res.end) && + (!find_next_iomem_res(&res, desc, NULL, false))) { + + ret = (*func)(res.start, res.end, arg); + if (ret) + break; + + res.start = res.end + 1; + res.end = orig_end; + } + + return ret; +} + +/* + * Walks through iomem resources and calls @func with matching resource + * ranges. This walks the whole tree and not just first level children. + * All the memory ranges which overlap start,end and also match flags and * name are valid candidates. * * @name: name of resource * @flags: resource flags * @start: start addr * @end: end addr + * + * NOTE: This function is deprecated and should not be used in new code. + * Use walk_iomem_res_desc(), instead. */ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, void *arg, int (*func)(u64, u64, void *)) @@ -404,7 +450,7 @@ int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, res.flags = flags; orig_end = res.end; while ((res.start < res.end) && - (!find_next_iomem_res(&res, name, false))) { + (!find_next_iomem_res(&res, IORES_DESC_NONE, name, false))) { ret = (*func)(res.start, res.end, arg); if (ret) break; @@ -433,7 +479,7 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && - (!find_next_iomem_res(&res, NULL, true))) { + (!find_next_iomem_res(&res, IORES_DESC_NONE, NULL, true))) { ret = (*func)(res.start, res.end, arg); if (ret) break; @@ -463,7 +509,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && - (find_next_iomem_res(&res, NULL, true) >= 0)) { + (find_next_iomem_res(&res, IORES_DESC_NONE, NULL, true) >= 0)) { pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; end_pfn = (res.end + 1) >> PAGE_SHIFT; if (end_pfn > pfn) -- cgit From f0f4711aa16b82016c0b6e59871934bbd71258da Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:30 +0100 Subject: x86, kexec, nvdimm: Use walk_iomem_res_desc() for iomem search Change the callers of walk_iomem_res() scanning for the following resources by name to use walk_iomem_res_desc() instead. "ACPI Tables" "ACPI Non-volatile Storage" "Persistent Memory (legacy)" "Crash kernel" Note, the caller of walk_iomem_res() with "GART" will be removed in a later patch. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Dave Young Cc: Andrew Morton Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Chun-Yi Cc: Dan Williams Cc: Denys Vlasenko Cc: Don Zickus Cc: H. Peter Anvin Cc: Lee, Chun-Yi Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Minfei Huang Cc: Peter Zijlstra (Intel) Cc: Ross Zwisler Cc: Stephen Rothwell Cc: Takao Indoh Cc: Thomas Gleixner Cc: Toshi Kani Cc: kexec@lists.infradead.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: linux-nvdimm@lists.01.org Link: http://lkml.kernel.org/r/1453841853-11383-15-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/crash.c | 4 ++-- arch/x86/kernel/pmem.c | 4 ++-- drivers/nvdimm/e820.c | 2 +- kernel/kexec_file.c | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 58f34319b29a..35e152eeb6e0 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -599,12 +599,12 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) /* Add ACPI tables */ cmd.type = E820_ACPI; flags = IORESOURCE_MEM | IORESOURCE_BUSY; - walk_iomem_res("ACPI Tables", flags, 0, -1, &cmd, + walk_iomem_res_desc(IORES_DESC_ACPI_TABLES, flags, 0, -1, &cmd, memmap_entry_callback); /* Add ACPI Non-volatile Storage */ cmd.type = E820_NVS; - walk_iomem_res("ACPI Non-volatile Storage", flags, 0, -1, &cmd, + walk_iomem_res_desc(IORES_DESC_ACPI_NV_STORAGE, flags, 0, -1, &cmd, memmap_entry_callback); /* Add crashk_low_res region */ diff --git a/arch/x86/kernel/pmem.c b/arch/x86/kernel/pmem.c index 14415aff1813..92f70147a9a6 100644 --- a/arch/x86/kernel/pmem.c +++ b/arch/x86/kernel/pmem.c @@ -13,11 +13,11 @@ static int found(u64 start, u64 end, void *data) static __init int register_e820_pmem(void) { - char *pmem = "Persistent Memory (legacy)"; struct platform_device *pdev; int rc; - rc = walk_iomem_res(pmem, IORESOURCE_MEM, 0, -1, NULL, found); + rc = walk_iomem_res_desc(IORES_DESC_PERSISTENT_MEMORY_LEGACY, + IORESOURCE_MEM, 0, -1, NULL, found); if (rc <= 0) return 0; diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c index b0045a505dc8..95825b38559a 100644 --- a/drivers/nvdimm/e820.c +++ b/drivers/nvdimm/e820.c @@ -55,7 +55,7 @@ static int e820_pmem_probe(struct platform_device *pdev) for (p = iomem_resource.child; p ; p = p->sibling) { struct nd_region_desc ndr_desc; - if (strncmp(p->name, "Persistent Memory (legacy)", 26) != 0) + if (p->desc != IORES_DESC_PERSISTENT_MEMORY_LEGACY) continue; memset(&ndr_desc, 0, sizeof(ndr_desc)); diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 2bfcdc064116..56b18eb1f001 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -524,10 +524,10 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz, /* Walk the RAM ranges and allocate a suitable range for the buffer */ if (image->type == KEXEC_TYPE_CRASH) - ret = walk_iomem_res("Crash kernel", - IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, - crashk_res.start, crashk_res.end, kbuf, - locate_mem_hole_callback); + ret = walk_iomem_res_desc(crashk_res.desc, + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, + crashk_res.start, crashk_res.end, kbuf, + locate_mem_hole_callback); else ret = walk_system_ram_res(0, -1, kbuf, locate_mem_hole_callback); -- cgit From f296f2634920d205b93d878b48d87bb7e0a4c256 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:31 +0100 Subject: x86/kexec: Remove walk_iomem_res() call with GART type There is no longer any driver inserting a "GART" region in the kernel since 707d4eefbdb3 ("Revert "[PATCH] Insert GART region into resource map""). Remove the call to walk_iomem_res() with "GART" type, its callback function, and GART-specific variables set by the callback. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Dave Young Cc: Andrew Morton Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Chun-Yi Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Lee, Chun-Yi Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Minfei Huang Cc: Peter Zijlstra (Intel) Cc: Stephen Rothwell Cc: Takao Indoh Cc: Thomas Gleixner Cc: Toshi Kani Cc: Viresh Kumar Cc: kexec@lists.infradead.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-16-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/crash.c | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 35e152eeb6e0..9ef978d69c22 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -57,10 +57,9 @@ struct crash_elf_data { struct kimage *image; /* * Total number of ram ranges we have after various adjustments for - * GART, crash reserved region etc. + * crash reserved region, etc. */ unsigned int max_nr_ranges; - unsigned long gart_start, gart_end; /* Pointer to elf header */ void *ehdr; @@ -201,17 +200,6 @@ static int get_nr_ram_ranges_callback(u64 start, u64 end, void *arg) return 0; } -static int get_gart_ranges_callback(u64 start, u64 end, void *arg) -{ - struct crash_elf_data *ced = arg; - - ced->gart_start = start; - ced->gart_end = end; - - /* Not expecting more than 1 gart aperture */ - return 1; -} - /* Gather all the required information to prepare elf headers for ram regions */ static void fill_up_crash_elf_data(struct crash_elf_data *ced, @@ -226,22 +214,6 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced, ced->max_nr_ranges = nr_ranges; - /* - * We don't create ELF headers for GART aperture as an attempt - * to dump this memory in second kernel leads to hang/crash. - * If gart aperture is present, one needs to exclude that region - * and that could lead to need of extra phdr. - */ - walk_iomem_res("GART", IORESOURCE_MEM, 0, -1, - ced, get_gart_ranges_callback); - - /* - * If we have gart region, excluding that could potentially split - * a memory range, resulting in extra header. Account for that. - */ - if (ced->gart_end) - ced->max_nr_ranges++; - /* Exclusion of crash region could split memory ranges */ ced->max_nr_ranges++; @@ -350,13 +322,6 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced, return ret; } - /* Exclude GART region */ - if (ced->gart_end) { - ret = exclude_mem_range(cmem, ced->gart_start, ced->gart_end); - if (ret) - return ret; - } - return ret; } -- cgit From a8fc42530ddd19d7580fe8c9f2ea86220a97e94c Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:32 +0100 Subject: resource: Kill walk_iomem_res() walk_iomem_res_desc() replaced walk_iomem_res() and there is no caller to walk_iomem_res() any more. Kill it. Also remove @name from find_next_iomem_res() as it is no longer used. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Acked-by: Dave Young Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dan Williams Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Hanjun Guo Cc: Jakub Sitnicki Cc: Jiang Liu Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: Vinod Koul Cc: linux-arch@vger.kernel.org Cc: linux-mm Link: http://lkml.kernel.org/r/1453841853-11383-17-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- include/linux/ioport.h | 3 --- kernel/resource.c | 49 +++++-------------------------------------------- 2 files changed, 5 insertions(+), 47 deletions(-) diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 2a4a5e839965..afb45597fb5f 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -270,9 +270,6 @@ walk_system_ram_res(u64 start, u64 end, void *arg, extern int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end, void *arg, int (*func)(u64, u64, void *)); -extern int -walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, void *arg, - int (*func)(u64, u64, void *)); /* True if any part of r1 overlaps r2 */ static inline bool resource_overlaps(struct resource *r1, struct resource *r2) diff --git a/kernel/resource.c b/kernel/resource.c index 37ed2fcb8246..49834309043c 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -335,13 +335,12 @@ EXPORT_SYMBOL(release_resource); /* * Finds the lowest iomem resource existing within [res->start.res->end). * The caller must specify res->start, res->end, res->flags, and optionally - * desc and "name". If found, returns 0, res is overwritten, if not found, - * returns -1. + * desc. If found, returns 0, res is overwritten, if not found, returns -1. * This function walks the whole tree and not just first level children until * and unless first_level_children_only is true. */ static int find_next_iomem_res(struct resource *res, unsigned long desc, - char *name, bool first_level_children_only) + bool first_level_children_only) { resource_size_t start, end; struct resource *p; @@ -363,8 +362,6 @@ static int find_next_iomem_res(struct resource *res, unsigned long desc, continue; if ((desc != IORES_DESC_NONE) && (desc != p->desc)) continue; - if (name && strcmp(p->name, name)) - continue; if (p->start > end) { p = NULL; break; @@ -411,7 +408,7 @@ int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, orig_end = res.end; while ((res.start < res.end) && - (!find_next_iomem_res(&res, desc, NULL, false))) { + (!find_next_iomem_res(&res, desc, false))) { ret = (*func)(res.start, res.end, arg); if (ret) @@ -424,42 +421,6 @@ int walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, return ret; } -/* - * Walks through iomem resources and calls @func with matching resource - * ranges. This walks the whole tree and not just first level children. - * All the memory ranges which overlap start,end and also match flags and - * name are valid candidates. - * - * @name: name of resource - * @flags: resource flags - * @start: start addr - * @end: end addr - * - * NOTE: This function is deprecated and should not be used in new code. - * Use walk_iomem_res_desc(), instead. - */ -int walk_iomem_res(char *name, unsigned long flags, u64 start, u64 end, - void *arg, int (*func)(u64, u64, void *)) -{ - struct resource res; - u64 orig_end; - int ret = -1; - - res.start = start; - res.end = end; - res.flags = flags; - orig_end = res.end; - while ((res.start < res.end) && - (!find_next_iomem_res(&res, IORES_DESC_NONE, name, false))) { - ret = (*func)(res.start, res.end, arg); - if (ret) - break; - res.start = res.end + 1; - res.end = orig_end; - } - return ret; -} - /* * This function calls the @func callback against all memory ranges of type * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY. @@ -479,7 +440,7 @@ int walk_system_ram_res(u64 start, u64 end, void *arg, res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && - (!find_next_iomem_res(&res, IORES_DESC_NONE, NULL, true))) { + (!find_next_iomem_res(&res, IORES_DESC_NONE, true))) { ret = (*func)(res.start, res.end, arg); if (ret) break; @@ -509,7 +470,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; orig_end = res.end; while ((res.start < res.end) && - (find_next_iomem_res(&res, IORES_DESC_NONE, NULL, true) >= 0)) { + (find_next_iomem_res(&res, IORES_DESC_NONE, true) >= 0)) { pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT; end_pfn = (res.end + 1) >> PAGE_SHIFT; if (end_pfn > pfn) -- cgit From 4650bac1fc45d64aef62ab99aa4db93d41dedbd9 Mon Sep 17 00:00:00 2001 From: Toshi Kani Date: Tue, 26 Jan 2016 21:57:33 +0100 Subject: ACPI/EINJ: Allow memory error injection to NVDIMM In the case of memory error injection, einj_error_inject() checks if a target address is System RAM. Change this check to allow injecting a memory error into NVDIMM memory by calling region_intersects() with IORES_DESC_PERSISTENT_MEMORY. This enables memory error testing on both System RAM and NVDIMM. In addition, page_is_ram() is replaced with region_intersects() with IORESOURCE_SYSTEM_RAM, so that it can verify a target address range with the requested size. Signed-off-by: Toshi Kani Signed-off-by: Borislav Petkov Reviewed-by: Dan Williams Acked-by: Tony Luck Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Jarkko Nikula Cc: Len Brown Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Peter Zijlstra Cc: Rafael J. Wysocki Cc: Thomas Gleixner Cc: Toshi Kani Cc: Vishal Verma Cc: linux-acpi@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-mm Cc: linux-nvdimm@lists.01.org Link: http://lkml.kernel.org/r/1453841853-11383-18-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- drivers/acpi/apei/einj.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c index 0431883653be..559c1173de1c 100644 --- a/drivers/acpi/apei/einj.c +++ b/drivers/acpi/apei/einj.c @@ -519,7 +519,7 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, u64 param4) { int rc; - unsigned long pfn; + u64 base_addr, size; /* If user manually set "flags", make sure it is legal */ if (flags && (flags & @@ -545,10 +545,17 @@ static int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, /* * Disallow crazy address masks that give BIOS leeway to pick * injection address almost anywhere. Insist on page or - * better granularity and that target address is normal RAM. + * better granularity and that target address is normal RAM or + * NVDIMM. */ - pfn = PFN_DOWN(param1 & param2); - if (!page_is_ram(pfn) || ((param2 & PAGE_MASK) != PAGE_MASK)) + base_addr = param1 & param2; + size = ~param2 + 1; + + if (((param2 & PAGE_MASK) != PAGE_MASK) || + ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) + != REGION_INTERSECTS) && + (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY) + != REGION_INTERSECTS))) return -EINVAL; inject: -- cgit From cd4d09ec6f6c12a2cc3db5b7d8876a325a53545b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 26 Jan 2016 22:12:04 +0100 Subject: x86/cpufeature: Carve out X86_FEATURE_* Move them to a separate header and have the following dependency: x86/cpufeatures.h <- x86/processor.h <- x86/cpufeature.h This makes it easier to use the header in asm code and not include the whole cpufeature.h and add guards for asm. Suggested-by: H. Peter Anvin Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453842730-28463-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 2 +- arch/x86/boot/cpuflags.h | 2 +- arch/x86/boot/mkcpustr.c | 2 +- arch/x86/crypto/crc32-pclmul_glue.c | 2 +- arch/x86/crypto/crc32c-intel_glue.c | 2 +- arch/x86/crypto/crct10dif-pclmul_glue.c | 2 +- arch/x86/entry/common.c | 1 + arch/x86/entry/entry_32.S | 2 +- arch/x86/entry/vdso/vdso32-setup.c | 1 - arch/x86/entry/vdso/vdso32/system_call.S | 2 +- arch/x86/entry/vdso/vma.c | 1 + arch/x86/include/asm/alternative.h | 6 - arch/x86/include/asm/apic.h | 1 - arch/x86/include/asm/arch_hweight.h | 2 + arch/x86/include/asm/cmpxchg.h | 1 + arch/x86/include/asm/cpufeature.h | 284 +----------------------------- arch/x86/include/asm/cpufeatures.h | 288 +++++++++++++++++++++++++++++++ arch/x86/include/asm/fpu/internal.h | 1 + arch/x86/include/asm/irq_work.h | 2 +- arch/x86/include/asm/mwait.h | 2 + arch/x86/include/asm/processor.h | 3 +- arch/x86/include/asm/smap.h | 2 +- arch/x86/include/asm/smp.h | 1 - arch/x86/include/asm/thread_info.h | 2 +- arch/x86/include/asm/tlbflush.h | 1 + arch/x86/include/asm/uaccess_64.h | 2 +- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/cyrix.c | 1 + arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/match.c | 2 +- arch/x86/kernel/cpu/mkcapflags.sh | 6 +- arch/x86/kernel/cpu/mtrr/main.c | 2 +- arch/x86/kernel/cpu/transmeta.c | 2 +- arch/x86/kernel/e820.c | 1 + arch/x86/kernel/head_32.S | 2 +- arch/x86/kernel/hpet.c | 1 + arch/x86/kernel/msr.c | 2 +- arch/x86/kernel/verify_cpu.S | 2 +- arch/x86/lib/clear_page_64.S | 2 +- arch/x86/lib/copy_page_64.S | 2 +- arch/x86/lib/copy_user_64.S | 2 +- arch/x86/lib/memcpy_64.S | 2 +- arch/x86/lib/memmove_64.S | 2 +- arch/x86/lib/memset_64.S | 2 +- arch/x86/mm/setup_nx.c | 1 + arch/x86/oprofile/op_model_amd.c | 1 - arch/x86/um/asm/barrier.h | 2 +- lib/atomic64_test.c | 2 +- 50 files changed, 336 insertions(+), 328 deletions(-) create mode 100644 arch/x86/include/asm/cpufeatures.h diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 87d40a72f6a1..c0c62532150d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -666,7 +666,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. clearcpuid=BITNUM [X86] Disable CPUID feature X for the kernel. See - arch/x86/include/asm/cpufeature.h for the valid bit + arch/x86/include/asm/cpufeatures.h for the valid bit numbers. Note the Linux specific bits are not necessarily stable over kernel options, but the vendor specific ones should be. diff --git a/arch/x86/boot/cpuflags.h b/arch/x86/boot/cpuflags.h index ea97697e51e4..4cb404fd45ce 100644 --- a/arch/x86/boot/cpuflags.h +++ b/arch/x86/boot/cpuflags.h @@ -1,7 +1,7 @@ #ifndef BOOT_CPUFLAGS_H #define BOOT_CPUFLAGS_H -#include +#include #include struct cpu_features { diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c index 637097e66a62..f72498dc90d2 100644 --- a/arch/x86/boot/mkcpustr.c +++ b/arch/x86/boot/mkcpustr.c @@ -17,7 +17,7 @@ #include "../include/asm/required-features.h" #include "../include/asm/disabled-features.h" -#include "../include/asm/cpufeature.h" +#include "../include/asm/cpufeatures.h" #include "../kernel/cpu/capflags.c" int main(void) diff --git a/arch/x86/crypto/crc32-pclmul_glue.c b/arch/x86/crypto/crc32-pclmul_glue.c index 07d2c6c86a54..27226df3f7d8 100644 --- a/arch/x86/crypto/crc32-pclmul_glue.c +++ b/arch/x86/crypto/crc32-pclmul_glue.c @@ -33,7 +33,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/crypto/crc32c-intel_glue.c b/arch/x86/crypto/crc32c-intel_glue.c index 0e9871693f24..0857b1a1de3b 100644 --- a/arch/x86/crypto/crc32c-intel_glue.c +++ b/arch/x86/crypto/crc32c-intel_glue.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/crypto/crct10dif-pclmul_glue.c b/arch/x86/crypto/crct10dif-pclmul_glue.c index a3fcfc97a311..cd4df9322501 100644 --- a/arch/x86/crypto/crct10dif-pclmul_glue.c +++ b/arch/x86/crypto/crct10dif-pclmul_glue.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include asmlinkage __u16 crc_t10dif_pcl(__u16 crc, const unsigned char *buf, diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 75175f92f462..c6ab2ebb5f4f 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -26,6 +26,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 77d8c5112900..4c5228352744 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/entry/vdso/vdso32-setup.c b/arch/x86/entry/vdso/vdso32-setup.c index 08a317a9ae4b..7853b53959cd 100644 --- a/arch/x86/entry/vdso/vdso32-setup.c +++ b/arch/x86/entry/vdso/vdso32-setup.c @@ -11,7 +11,6 @@ #include #include -#include #include #include diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S index 3a1d9297074b..0109ac6cb79c 100644 --- a/arch/x86/entry/vdso/vdso32/system_call.S +++ b/arch/x86/entry/vdso/vdso32/system_call.S @@ -3,7 +3,7 @@ */ #include -#include +#include #include /* diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 7c912fefe79b..429d54d01b38 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -20,6 +20,7 @@ #include #include #include +#include #if defined(CONFIG_X86_64) unsigned int __read_mostly vdso64_enabled = 1; diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 7bfc85bbb8ff..99afb665a004 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -151,12 +151,6 @@ static inline int alternatives_text_reserved(void *start, void *end) ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \ ".popsection" -/* - * This must be included *after* the definition of ALTERNATIVE due to - * - */ -#include - /* * Alternative instructions for different CPU types or capabilities. * diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index c80f6b6f3da2..0899cfc8dfe8 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h index 259a7c1ef709..02e799fa43d1 100644 --- a/arch/x86/include/asm/arch_hweight.h +++ b/arch/x86/include/asm/arch_hweight.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_HWEIGHT_H #define _ASM_X86_HWEIGHT_H +#include + #ifdef CONFIG_64BIT /* popcnt %edi, %eax -- redundant REX prefix for alignment */ #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7" diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h index ad19841eddfe..9733361fed6f 100644 --- a/arch/x86/include/asm/cmpxchg.h +++ b/arch/x86/include/asm/cmpxchg.h @@ -2,6 +2,7 @@ #define ASM_X86_CMPXCHG_H #include +#include #include /* Provides LOCK_PREFIX */ /* diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index bbf166e805be..3cce9f3c5cb1 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -1,289 +1,7 @@ -/* - * Defines x86 CPU feature bits - */ #ifndef _ASM_X86_CPUFEATURE_H #define _ASM_X86_CPUFEATURE_H -#ifndef _ASM_X86_REQUIRED_FEATURES_H -#include -#endif - -#ifndef _ASM_X86_DISABLED_FEATURES_H -#include -#endif - -#define NCAPINTS 16 /* N 32-bit words worth of info */ -#define NBUGINTS 1 /* N 32-bit bug flags */ - -/* - * Note: If the comment begins with a quoted string, that string is used - * in /proc/cpuinfo instead of the macro name. If the string is "", - * this feature bit is not displayed in /proc/cpuinfo at all. - */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ -#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */ -#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */ -#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */ -#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */ -#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */ -#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */ -#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */ -#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */ -#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */ -#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */ -#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */ -#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */ -#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions */ - /* (plus FCMOVcc, FCOMI with FPU) */ -#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */ -#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */ -#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */ -#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */ -#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */ -#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */ -#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */ -#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ -#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */ -#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */ -#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */ -#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */ -#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */ -#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */ -#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */ - -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ -/* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */ -#define X86_FEATURE_MP ( 1*32+19) /* MP Capable. */ -#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */ -#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */ -#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */ -#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */ -#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */ -#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64) */ -#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow! extensions */ -#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow! */ - -/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ -#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */ -#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */ -#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */ - -/* Other features, Linux-defined mapping, word 3 */ -/* This range is used for feature bits which conflict or are synthesized */ -#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */ -#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ -#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ -#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ -/* cpu types for specific tunings: */ -#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ -#define X86_FEATURE_K7 ( 3*32+ 5) /* "" Athlon */ -#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ -#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ -#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ -#define X86_FEATURE_UP ( 3*32+ 9) /* smp kernel running on up */ -/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */ -#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */ -#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */ -#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in ia32 userspace */ -#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */ -#define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */ -#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */ -#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */ -/* free, was #define X86_FEATURE_11AP ( 3*32+19) * "" Bad local APIC aka 11AP */ -#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ -#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ -#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ -#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */ -#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */ -/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */ -#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */ -#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ -#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ -#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */ -#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */ -#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */ -#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */ -#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" Monitor/Mwait support */ -#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */ -#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */ -#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer mode */ -#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */ -#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */ -#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */ -#define X86_FEATURE_CID ( 4*32+10) /* Context ID */ -#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */ -#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */ -#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B */ -#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */ -#define X86_FEATURE_PDCM ( 4*32+15) /* Performance Capabilities */ -#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */ -#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */ -#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */ -#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */ -#define X86_FEATURE_X2APIC ( 4*32+21) /* x2APIC */ -#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */ -#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */ -#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */ -#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */ -#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ -#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE enabled in the OS */ -#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */ -#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit fp conversions */ -#define X86_FEATURE_RDRAND ( 4*32+30) /* The RDRAND instruction */ -#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */ - -/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ -#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */ -#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */ -#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */ -#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */ -#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */ -#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */ -#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */ -#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */ -#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */ -#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */ - -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ -#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */ -#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure virtual machine */ -#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */ -#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */ -#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */ -#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */ -#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */ -#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */ -#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */ -#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */ -#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */ -#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */ -#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */ -#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */ -#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */ -#define X86_FEATURE_TCE ( 6*32+17) /* translation cache extension */ -#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */ -#define X86_FEATURE_TBM ( 6*32+21) /* trailing bit manipulations */ -#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */ -#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_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ -#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */ - -/* - * Auxiliary flags: Linux defined - For features scattered in various - * CPUID levels like 0x6, 0xA etc, word 7. - * - * Reuse free bits when adding new feature flags! - */ - -#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ -#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ - -#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ -#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ - -#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ - -/* Virtualization flags: Linux defined, word 8 */ -#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ -#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ -#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ -#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ -#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ - -#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ -#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ - - -/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ -#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ -#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */ -#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */ -#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */ -#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */ -#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */ -#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */ -#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */ -#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */ -#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */ -#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */ -#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */ -#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */ -#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */ -#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */ -#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */ -#define X86_FEATURE_PCOMMIT ( 9*32+22) /* PCOMMIT instruction */ -#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */ -#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */ -#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */ -#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */ -#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */ -#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */ - -/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */ -#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT */ -#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC */ -#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 */ -#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS */ - -/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */ -#define X86_FEATURE_CQM_LLC (11*32+ 1) /* LLC QoS if 1 */ - -/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */ -#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */ - -/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ -#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ - -/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ -#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ -#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */ -#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */ -#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */ -#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */ -#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */ -#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ -#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */ -#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ - -/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */ -#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */ -#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */ -#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */ -#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */ -#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */ -#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ -#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ -#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ -#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ -#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ -#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ - -/* - * BUG word(s) - */ -#define X86_BUG(x) (NCAPINTS*32 + (x)) - -#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ -#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ -#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ -#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */ -#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */ -#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */ -#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 */ +#include #if defined(__KERNEL__) && !defined(__ASSEMBLY__) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h new file mode 100644 index 000000000000..0ceb6adc8a48 --- /dev/null +++ b/arch/x86/include/asm/cpufeatures.h @@ -0,0 +1,288 @@ +#ifndef _ASM_X86_CPUFEATURES_H +#define _ASM_X86_CPUFEATURES_H + +#ifndef _ASM_X86_REQUIRED_FEATURES_H +#include +#endif + +#ifndef _ASM_X86_DISABLED_FEATURES_H +#include +#endif + +/* + * Defines x86 CPU feature bits + */ +#define NCAPINTS 16 /* N 32-bit words worth of info */ +#define NBUGINTS 1 /* N 32-bit bug flags */ + +/* + * Note: If the comment begins with a quoted string, that string is used + * in /proc/cpuinfo instead of the macro name. If the string is "", + * this feature bit is not displayed in /proc/cpuinfo at all. + */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */ +#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */ +#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions */ + /* (plus FCMOVcc, FCOMI with FPU) */ +#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */ +#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */ +#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ +#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */ +#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */ +#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */ +#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */ +#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */ +#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP ( 1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */ +#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */ +#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */ +#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ +#define X86_FEATURE_K7 ( 3*32+ 5) /* "" Athlon */ +#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ +#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ +#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ +#define X86_FEATURE_UP ( 3*32+ 9) /* smp kernel running on up */ +/* free, was #define X86_FEATURE_FXSAVE_LEAK ( 3*32+10) * "" FXSAVE leaks FOP/FIP/FOP */ +#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */ +#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */ +#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */ +#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in ia32 userspace */ +#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */ +#define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */ +#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */ +#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */ +/* free, was #define X86_FEATURE_11AP ( 3*32+19) * "" Bad local APIC aka 11AP */ +#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ +#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ +#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ +#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */ +#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */ +/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */ +#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */ +#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */ +#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */ +#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */ +#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */ +#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */ +#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */ +#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" Monitor/Mwait support */ +#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */ +#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */ +#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer mode */ +#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */ +#define X86_FEATURE_CID ( 4*32+10) /* Context ID */ +#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */ +#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */ +#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */ +#define X86_FEATURE_PDCM ( 4*32+15) /* Performance Capabilities */ +#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */ +#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */ +#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */ +#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */ +#define X86_FEATURE_X2APIC ( 4*32+21) /* x2APIC */ +#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */ +#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */ +#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */ +#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */ +#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ +#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE enabled in the OS */ +#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */ +#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit fp conversions */ +#define X86_FEATURE_RDRAND ( 4*32+30) /* The RDRAND instruction */ +#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */ +#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */ +#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */ +#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */ +#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */ +#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */ +#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */ +#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */ +#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */ +#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */ +#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure virtual machine */ +#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */ +#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */ +#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */ +#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */ +#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */ +#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */ +#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */ +#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */ +#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */ +#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */ +#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */ +#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */ +#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */ +#define X86_FEATURE_TCE ( 6*32+17) /* translation cache extension */ +#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */ +#define X86_FEATURE_TBM ( 6*32+21) /* trailing bit manipulations */ +#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */ +#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_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */ +#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */ + +/* + * Auxiliary flags: Linux defined - For features scattered in various + * CPUID levels like 0x6, 0xA etc, word 7. + * + * Reuse free bits when adding new feature flags! + */ + +#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */ +#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ + +#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */ +#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ + +#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */ + +/* Virtualization flags: Linux defined, word 8 */ +#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */ +#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */ +#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ +#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */ +#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */ + +#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */ +#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */ + + +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ +#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/ +#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */ +#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */ +#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */ +#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */ +#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */ +#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */ +#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */ +#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */ +#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */ +#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */ +#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */ +#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */ +#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */ +#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */ +#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */ +#define X86_FEATURE_PCOMMIT ( 9*32+22) /* PCOMMIT instruction */ +#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */ +#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */ +#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */ +#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */ +#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */ +#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */ + +/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */ +#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT */ +#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC */ +#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 */ +#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS */ + +/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */ +#define X86_FEATURE_CQM_LLC (11*32+ 1) /* LLC QoS if 1 */ + +/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */ +#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */ + +/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ +#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ + +/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ +#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */ +#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */ +#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */ +#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */ +#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */ +#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */ +#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */ +#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ +#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */ +#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ + +/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */ +#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */ +#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */ +#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */ +#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */ +#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */ +#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ +#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ +#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ +#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ +#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ +#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ + +/* + * BUG word(s) + */ +#define X86_BUG(x) (NCAPINTS*32 + (x)) + +#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */ +#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */ +#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */ +#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */ +#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */ +#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */ +#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 */ + +#endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index 0fd440df63f1..d01199def781 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -17,6 +17,7 @@ #include #include #include +#include /* * High level FPU state handling functions: diff --git a/arch/x86/include/asm/irq_work.h b/arch/x86/include/asm/irq_work.h index 78162f8e248b..d0afb05c84fc 100644 --- a/arch/x86/include/asm/irq_work.h +++ b/arch/x86/include/asm/irq_work.h @@ -1,7 +1,7 @@ #ifndef _ASM_IRQ_WORK_H #define _ASM_IRQ_WORK_H -#include +#include static inline bool arch_irq_work_has_interrupt(void) { diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index c70689b5e5aa..0deeb2d26df7 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -3,6 +3,8 @@ #include +#include + #define MWAIT_SUBSTATE_MASK 0xf #define MWAIT_CSTATE_MASK 0xf #define MWAIT_SUBSTATE_SIZE 4 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 2d5a50cb61a2..491a3d9dbb15 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -13,7 +13,7 @@ struct vm86; #include #include #include -#include +#include #include #include #include @@ -24,7 +24,6 @@ struct vm86; #include #include -#include #include #include #include diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h index ba665ebd17bb..db333300bd4b 100644 --- a/arch/x86/include/asm/smap.h +++ b/arch/x86/include/asm/smap.h @@ -15,7 +15,7 @@ #include #include -#include +#include /* "Raw" instruction opcodes */ #define __ASM_CLAC .byte 0x0f,0x01,0xca diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index dfcf0727623b..20a3de5cb3b0 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -16,7 +16,6 @@ #endif #include #include -#include extern int smp_num_siblings; extern unsigned int num_processors; diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index c7b551028740..c0778fcab06d 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -49,7 +49,7 @@ */ #ifndef __ASSEMBLY__ struct task_struct; -#include +#include #include struct thread_info { diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 6df2029405a3..0bb31cb8c73b 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -5,6 +5,7 @@ #include #include +#include #include #ifdef CONFIG_PARAVIRT diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h index b89c34c4019b..307698688fa1 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include /* diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 58031303e304..faa7b5204129 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -64,7 +64,7 @@ ifdef CONFIG_X86_FEATURE_NAMES quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $< $@ -cpufeature = $(src)/../../include/asm/cpufeature.h +cpufeature = $(src)/../../include/asm/cpufeatures.h targets += capflags.c $(obj)/capflags.c: $(cpufeature) $(src)/mkcapflags.sh FORCE diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index ae20be6e483c..6608c03c2126 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index aaf152e79637..15e47c1cd412 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "cpu.h" diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 565648bc1a0a..9299e3bdfad6 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 0b6c52388cf4..341449c49f34 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index afa9f0d487ea..fbb5e90557a5 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/mkcapflags.sh b/arch/x86/kernel/cpu/mkcapflags.sh index 3f20710a5b23..6988c74409a8 100644 --- a/arch/x86/kernel/cpu/mkcapflags.sh +++ b/arch/x86/kernel/cpu/mkcapflags.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeature.h +# Generate the x86_cap/bug_flags[] arrays from include/asm/cpufeatures.h # IN=$1 @@ -49,8 +49,8 @@ dump_array() trap 'rm "$OUT"' EXIT ( - echo "#ifndef _ASM_X86_CPUFEATURE_H" - echo "#include " + echo "#ifndef _ASM_X86_CPUFEATURES_H" + echo "#include " echo "#endif" echo "" diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 5c3d149ee91c..74f1d90f9c29 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -47,7 +47,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 252da7aceca6..a19a663282b5 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include "cpu.h" diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 569c1e4f96fe..b3c2a697820a 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * The e820 map is the map that gets modified e.g. with command line parameters diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 6bc9ae24b6d2..af1112980dd4 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index b8e6ff5cd5d0..be0ebbb6d1d1 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 64f9616f93f1..7f3550acde1b 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -40,7 +40,7 @@ #include #include -#include +#include #include static struct class *msr_class; diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S index 07efb35ee4bc..014ea59aa153 100644 --- a/arch/x86/kernel/verify_cpu.S +++ b/arch/x86/kernel/verify_cpu.S @@ -30,7 +30,7 @@ * appropriately. Either display a message or halt. */ -#include +#include #include verify_cpu: diff --git a/arch/x86/lib/clear_page_64.S b/arch/x86/lib/clear_page_64.S index a2fe51b00cce..65be7cfaf947 100644 --- a/arch/x86/lib/clear_page_64.S +++ b/arch/x86/lib/clear_page_64.S @@ -1,5 +1,5 @@ #include -#include +#include #include /* diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S index 009f98216b7e..24ef1c2104d4 100644 --- a/arch/x86/lib/copy_page_64.S +++ b/arch/x86/lib/copy_page_64.S @@ -1,7 +1,7 @@ /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */ #include -#include +#include #include /* diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index 982ce34f4a9b..fba343062055 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index 16698bba87de..a0de849435ad 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S @@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen */ #include -#include +#include #include /* diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S index ca2afdd6d98e..90ce01bee00c 100644 --- a/arch/x86/lib/memmove_64.S +++ b/arch/x86/lib/memmove_64.S @@ -6,7 +6,7 @@ * - Copyright 2011 Fenghua Yu */ #include -#include +#include #include #undef memmove diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S index 2661fad05827..c9c81227ea37 100644 --- a/arch/x86/lib/memset_64.S +++ b/arch/x86/lib/memset_64.S @@ -1,7 +1,7 @@ /* Copyright 2002 Andi Kleen, SuSE Labs */ #include -#include +#include #include .weak memset diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 92e2eacb3321..f65a33f505b6 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -4,6 +4,7 @@ #include #include +#include static int disable_nx; diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 50d86c0e9ba4..660a83c8287b 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "op_x86_model.h" #include "op_counter.h" diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h index 174781a404ff..00c319048d52 100644 --- a/arch/x86/um/asm/barrier.h +++ b/arch/x86/um/asm/barrier.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index d62de8bf022d..123481814320 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -17,7 +17,7 @@ #include #ifdef CONFIG_X86 -#include /* for boot_cpu_has below */ +#include /* for boot_cpu_has below */ #endif #define TEST(bit, op, c_op, val) \ -- cgit From bc696ca05f5a8927329ec276a892341e006b00ba Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 26 Jan 2016 22:12:05 +0100 Subject: x86/cpufeature: Replace the old static_cpu_has() with safe variant So the old one didn't work properly before alternatives had run. And it was supposed to provide an optimized JMP because the assumption was that the offset it is jumping to is within a signed byte and thus a two-byte JMP. So I did an x86_64 allyesconfig build and dumped all possible sites where static_cpu_has() was used. The optimization amounted to all in all 12(!) places where static_cpu_has() had generated a 2-byte JMP. Which has saved us a whopping 36 bytes! This clearly is not worth the trouble so we can remove it. The only place where the optimization might count - in __switch_to() - we will handle differently. But that's not subject of this patch. 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/1453842730-28463-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/Kconfig.debug | 10 ---- arch/x86/include/asm/cpufeature.h | 100 +++-------------------------------- arch/x86/include/asm/fpu/internal.h | 14 ++--- arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/cpu/common.c | 12 +---- arch/x86/kernel/vm86_32.c | 2 +- drivers/cpufreq/intel_pstate.c | 2 +- fs/btrfs/disk-io.c | 2 +- 8 files changed, 21 insertions(+), 125 deletions(-) diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 9b18ed97a8a2..68a2d1f0a683 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -350,16 +350,6 @@ config DEBUG_IMR_SELFTEST If unsure say N here. -config X86_DEBUG_STATIC_CPU_HAS - bool "Debug alternatives" - depends on DEBUG_KERNEL - ---help--- - This option causes additional code to be generated which - fails if static_cpu_has() is used before alternatives have - run. - - If unsure, say N. - config X86_DEBUG_FPU bool "Debug the x86 FPU code" depends on DEBUG_KERNEL diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 3cce9f3c5cb1..a261cf2e7907 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -125,103 +125,19 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; #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_safe() for + * Do not add any more of those clumsy macros - use static_cpu_has() for * fast paths and boot_cpu_has() otherwise! */ #if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) -extern void warn_pre_alternatives(void); -extern bool __static_cpu_has_safe(u16 bit); +extern bool __static_cpu_has(u16 bit); /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These are only valid after alternatives have run, but will statically * patch the target code for additional performance. */ -static __always_inline __pure bool __static_cpu_has(u16 bit) -{ -#ifdef CC_HAVE_ASM_GOTO - -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS - - /* - * Catch too early usage of this before alternatives - * have run. - */ - asm_volatile_goto("1: jmp %l[t_warn]\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 0\n" /* no replacement */ - " .word %P0\n" /* 1: do replace */ - " .byte 2b - 1b\n" /* source len */ - " .byte 0\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - /* skipping size check since replacement size = 0 */ - : : "i" (X86_FEATURE_ALWAYS) : : t_warn); - -#endif - - asm_volatile_goto("1: jmp %l[t_no]\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 0\n" /* no replacement */ - " .word %P0\n" /* feature bit */ - " .byte 2b - 1b\n" /* source len */ - " .byte 0\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - /* skipping size check since replacement size = 0 */ - : : "i" (bit) : : t_no); - return true; - t_no: - return false; - -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS - t_warn: - warn_pre_alternatives(); - return false; -#endif - -#else /* CC_HAVE_ASM_GOTO */ - - u8 flag; - /* Open-coded due to __stringify() in ALTERNATIVE() */ - asm volatile("1: movb $0,%0\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" - " .long 3f - .\n" - " .word %P1\n" /* feature bit */ - " .byte 2b - 1b\n" /* source len */ - " .byte 4f - 3f\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "3: movb $1,%0\n" - "4:\n" - ".previous\n" - : "=qm" (flag) : "i" (bit)); - return flag; - -#endif /* CC_HAVE_ASM_GOTO */ -} - -#define static_cpu_has(bit) \ -( \ - __builtin_constant_p(boot_cpu_has(bit)) ? \ - boot_cpu_has(bit) : \ - __builtin_constant_p(bit) ? \ - __static_cpu_has(bit) : \ - boot_cpu_has(bit) \ -) - -static __always_inline __pure bool _static_cpu_has_safe(u16 bit) +static __always_inline __pure bool _static_cpu_has(u16 bit) { #ifdef CC_HAVE_ASM_GOTO asm_volatile_goto("1: jmp %l[t_dynamic]\n" @@ -255,7 +171,7 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) t_no: return false; t_dynamic: - return __static_cpu_has_safe(bit); + return __static_cpu_has(bit); #else u8 flag; /* Open-coded due to __stringify() in ALTERNATIVE() */ @@ -293,22 +209,21 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) ".previous\n" : "=qm" (flag) : "i" (bit), "i" (X86_FEATURE_ALWAYS)); - return (flag == 2 ? __static_cpu_has_safe(bit) : flag); + return (flag == 2 ? __static_cpu_has(bit) : flag); #endif /* CC_HAVE_ASM_GOTO */ } -#define static_cpu_has_safe(bit) \ +#define static_cpu_has(bit) \ ( \ __builtin_constant_p(boot_cpu_has(bit)) ? \ boot_cpu_has(bit) : \ - _static_cpu_has_safe(bit) \ + _static_cpu_has(bit) \ ) #else /* * gcc 3.x is too stupid to do the static test; fall back to dynamic. */ #define static_cpu_has(bit) boot_cpu_has(bit) -#define static_cpu_has_safe(bit) boot_cpu_has(bit) #endif #define cpu_has_bug(c, bit) cpu_has(c, (bit)) @@ -316,7 +231,6 @@ static __always_inline __pure bool _static_cpu_has_safe(u16 bit) #define clear_cpu_bug(c, bit) clear_cpu_cap(c, (bit)) #define static_cpu_has_bug(bit) static_cpu_has((bit)) -#define static_cpu_has_bug_safe(bit) static_cpu_has_safe((bit)) #define boot_cpu_has_bug(bit) cpu_has_bug(&boot_cpu_data, (bit)) #define MAX_CPU_FEATURES (NCAPINTS * 32) diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index d01199def781..c2e46eb96b6d 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -59,22 +59,22 @@ extern u64 fpu__get_supported_xfeatures_mask(void); */ static __always_inline __pure bool use_eager_fpu(void) { - return static_cpu_has_safe(X86_FEATURE_EAGER_FPU); + return static_cpu_has(X86_FEATURE_EAGER_FPU); } static __always_inline __pure bool use_xsaveopt(void) { - return static_cpu_has_safe(X86_FEATURE_XSAVEOPT); + return static_cpu_has(X86_FEATURE_XSAVEOPT); } static __always_inline __pure bool use_xsave(void) { - return static_cpu_has_safe(X86_FEATURE_XSAVE); + return static_cpu_has(X86_FEATURE_XSAVE); } static __always_inline __pure bool use_fxsr(void) { - return static_cpu_has_safe(X86_FEATURE_FXSR); + return static_cpu_has(X86_FEATURE_FXSR); } /* @@ -301,7 +301,7 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) WARN_ON(system_state != SYSTEM_BOOTING); - if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + if (static_cpu_has(X86_FEATURE_XSAVES)) XSTATE_OP(XSAVES, xstate, lmask, hmask, err); else XSTATE_OP(XSAVE, xstate, lmask, hmask, err); @@ -323,7 +323,7 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate) WARN_ON(system_state != SYSTEM_BOOTING); - if (static_cpu_has_safe(X86_FEATURE_XSAVES)) + if (static_cpu_has(X86_FEATURE_XSAVES)) XSTATE_OP(XRSTORS, xstate, lmask, hmask, err); else XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); @@ -461,7 +461,7 @@ static inline void copy_kernel_to_fpregs(union fpregs_state *fpstate) * pending. Clear the x87 state here by setting it to fixed values. * "m" is a random variable that should be in L1. */ - if (unlikely(static_cpu_has_bug_safe(X86_BUG_FXSAVE_LEAK))) { + if (unlikely(static_cpu_has_bug(X86_BUG_FXSAVE_LEAK))) { asm volatile( "fnclex\n\t" "emms\n\t" diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index c80c02c6ec49..ab5c2c685a3c 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -30,7 +30,7 @@ static unsigned int numachip1_get_apic_id(unsigned long x) unsigned long value; unsigned int id = (x >> 24) & 0xff; - if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) { + if (static_cpu_has(X86_FEATURE_NODEID_MSR)) { rdmsrl(MSR_FAM10H_NODE_ID, value); id |= (value << 2) & 0xff00; } @@ -178,7 +178,7 @@ static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) this_cpu_write(cpu_llc_id, node); /* Account for nodes per socket in multi-core-module processors */ - if (static_cpu_has_safe(X86_FEATURE_NODEID_MSR)) { + if (static_cpu_has(X86_FEATURE_NODEID_MSR)) { rdmsrl(MSR_FAM10H_NODE_ID, val); nodes = ((val >> 3) & 7) + 1; } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 37830de8f60a..ee499817f3f5 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1475,19 +1475,11 @@ void cpu_init(void) } #endif -#ifdef CONFIG_X86_DEBUG_STATIC_CPU_HAS -void warn_pre_alternatives(void) -{ - WARN(1, "You're using static_cpu_has before alternatives have run!\n"); -} -EXPORT_SYMBOL_GPL(warn_pre_alternatives); -#endif - -inline bool __static_cpu_has_safe(u16 bit) +inline bool __static_cpu_has(u16 bit) { return boot_cpu_has(bit); } -EXPORT_SYMBOL_GPL(__static_cpu_has_safe); +EXPORT_SYMBOL_GPL(__static_cpu_has); static void bsp_resume(void) { diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index e574b8546518..3dce1ca0a653 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -362,7 +362,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus) /* make room for real-mode segments */ tsk->thread.sp0 += 16; - if (static_cpu_has_safe(X86_FEATURE_SEP)) + if (static_cpu_has(X86_FEATURE_SEP)) tsk->thread.sysenter_cs = 0; load_sp0(tss, &tsk->thread); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index cd83d477e32d..3a4b39afc0ab 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1431,7 +1431,7 @@ static int __init intel_pstate_init(void) if (!all_cpu_data) return -ENOMEM; - if (static_cpu_has_safe(X86_FEATURE_HWP) && !no_hwp) { + if (static_cpu_has(X86_FEATURE_HWP) && !no_hwp) { pr_info("intel_pstate: HWP enabled\n"); hwp_active++; } diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index dd08e29f5117..d9286497924f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -930,7 +930,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags) if (bio_flags & EXTENT_BIO_TREE_LOG) return 0; #ifdef CONFIG_X86 - if (static_cpu_has_safe(X86_FEATURE_XMM4_2)) + if (static_cpu_has(X86_FEATURE_XMM4_2)) return 0; #endif return 1; -- cgit From a362bf9f5e7dd659b96d01382da7b855f4e5a7a1 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 27 Jan 2016 09:43:25 +0100 Subject: x86/cpufeature: Get rid of the non-asm goto variant I can simply quote hpa from the mail: "Get rid of the non-asm goto variant and just fall back to dynamic if asm goto is unavailable. It doesn't make any sense, really, if it is supposed to be safe, and by now the asm goto-capable gcc is in more wide use. (Originally the gcc 3.x fallback to pure dynamic didn't exist, either.)" Booy, am I lazy. Cleanup the whole CC_HAVE_ASM_GOTO ifdeffery too, while at it. Suggested-by: H. Peter Anvin Signed-off-by: Borislav Petkov Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20160127084325.GB30712@pd.tnic Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 49 ++++----------------------------------- 1 file changed, 5 insertions(+), 44 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index a261cf2e7907..9048c1bbc519 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -129,17 +129,16 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; * fast paths and boot_cpu_has() otherwise! */ -#if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) +#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS) extern bool __static_cpu_has(u16 bit); /* * Static testing of CPU features. Used the same as boot_cpu_has(). - * These are only valid after alternatives have run, but will statically - * patch the target code for additional performance. + * These will statically patch the target code for additional + * performance. */ static __always_inline __pure bool _static_cpu_has(u16 bit) { -#ifdef CC_HAVE_ASM_GOTO asm_volatile_goto("1: jmp %l[t_dynamic]\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " @@ -172,45 +171,6 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) return false; t_dynamic: return __static_cpu_has(bit); -#else - u8 flag; - /* Open-coded due to __stringify() in ALTERNATIVE() */ - asm volatile("1: movb $2,%0\n" - "2:\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 3f - .\n" /* repl offset */ - " .word %P2\n" /* always replace */ - " .byte 2b - 1b\n" /* source len */ - " .byte 4f - 3f\n" /* replacement len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (4f-3f) - (2b-1b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "3: movb $0,%0\n" - "4:\n" - ".previous\n" - ".section .altinstructions,\"a\"\n" - " .long 1b - .\n" /* src offset */ - " .long 5f - .\n" /* repl offset */ - " .word %P1\n" /* feature bit */ - " .byte 4b - 3b\n" /* src len */ - " .byte 6f - 5f\n" /* repl len */ - " .byte 0\n" /* pad len */ - ".previous\n" - ".section .discard,\"aw\",@progbits\n" - " .byte 0xff + (6f-5f) - (4b-3b)\n" /* size check */ - ".previous\n" - ".section .altinstr_replacement,\"ax\"\n" - "5: movb $1,%0\n" - "6:\n" - ".previous\n" - : "=qm" (flag) - : "i" (bit), "i" (X86_FEATURE_ALWAYS)); - return (flag == 2 ? __static_cpu_has(bit) : flag); -#endif /* CC_HAVE_ASM_GOTO */ } #define static_cpu_has(bit) \ @@ -221,7 +181,8 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) ) #else /* - * gcc 3.x is too stupid to do the static test; fall back to dynamic. + * Fall back to dynamic for gcc versions which don't support asm goto. Should be + * a minority now anyway. */ #define static_cpu_has(bit) boot_cpu_has(bit) #endif -- cgit From 337e4cc84021212a87b04b77b65cccc49304909e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 26 Jan 2016 22:12:07 +0100 Subject: x86/alternatives: Add an auxilary section Add .altinstr_aux for additional instructions which will be used before and/or during patching. All stuff which needs more sophisticated patching should go there. See next patch. 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/1453842730-28463-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/vmlinux.lds.S | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 74e4bf11f562..92dc211c11db 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -195,6 +195,17 @@ SECTIONS :init #endif + /* + * Section for code used exclusively before alternatives are run. All + * references to such code must be patched out by alternatives, normally + * by using X86_FEATURE_ALWAYS CPU feature bit. + * + * See static_cpu_has() for an example. + */ + .altinstr_aux : AT(ADDR(.altinstr_aux) - LOAD_OFFSET) { + *(.altinstr_aux) + } + INIT_DATA_SECTION(16) .x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) { -- cgit From 2476f2fa20568bd5d9e09cd35bcd73e99a6f4cc6 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Wed, 27 Jan 2016 09:45:25 +0100 Subject: x86/alternatives: Discard dynamic check after init Move the code to do the dynamic check to the altinstr_aux section so that it is discarded after alternatives have run and a static branch has been chosen. This way we're changing the dynamic branch from C code to assembly, which makes it *substantially* smaller while avoiding a completely unnecessary call to an out of line function. Signed-off-by: Brian Gerst [ Changed it to do TESTB, as hpa suggested. ] Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Dave Young Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Kristen Carlson Accardi Cc: Laura Abbott Cc: Linus Torvalds Cc: Peter Zijlstra (Intel) Cc: Peter Zijlstra Cc: Prarit Bhargava Cc: Ross Zwisler Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1452972124-7380-1-git-send-email-brgerst@gmail.com Link: http://lkml.kernel.org/r/20160127084525.GC30712@pd.tnic Signed-off-by: Ingo Molnar --- arch/x86/include/asm/cpufeature.h | 19 ++++++++++++------- arch/x86/kernel/cpu/common.c | 6 ------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 9048c1bbc519..9fba7a5dd24a 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -130,8 +130,6 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; */ #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_X86_FAST_FEATURE_TESTS) -extern bool __static_cpu_has(u16 bit); - /* * Static testing of CPU features. Used the same as boot_cpu_has(). * These will statically patch the target code for additional @@ -139,7 +137,7 @@ extern bool __static_cpu_has(u16 bit); */ static __always_inline __pure bool _static_cpu_has(u16 bit) { - asm_volatile_goto("1: jmp %l[t_dynamic]\n" + asm_volatile_goto("1: jmp 6f\n" "2:\n" ".skip -(((5f-4f) - (2b-1b)) > 0) * " "((5f-4f) - (2b-1b)),0x90\n" @@ -164,13 +162,20 @@ static __always_inline __pure bool _static_cpu_has(u16 bit) " .byte 0\n" /* repl len */ " .byte 0\n" /* pad len */ ".previous\n" - : : "i" (bit), "i" (X86_FEATURE_ALWAYS) - : : t_dynamic, t_no); + ".section .altinstr_aux,\"ax\"\n" + "6:\n" + " testb %[bitnum],%[cap_byte]\n" + " jnz %l[t_yes]\n" + " jmp %l[t_no]\n" + ".previous\n" + : : "i" (bit), "i" (X86_FEATURE_ALWAYS), + [bitnum] "i" (1 << (bit & 7)), + [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) + : : t_yes, t_no); + t_yes: return true; t_no: return false; - t_dynamic: - return __static_cpu_has(bit); } #define static_cpu_has(bit) \ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index ee499817f3f5..079d83fc6488 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1475,12 +1475,6 @@ void cpu_init(void) } #endif -inline bool __static_cpu_has(u16 bit) -{ - return boot_cpu_has(bit); -} -EXPORT_SYMBOL_GPL(__static_cpu_has); - static void bsp_resume(void) { if (this_cpu->c_bsp_resume) -- cgit From 8c725306993198f845038dc9e45a1267099867a6 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 26 Jan 2016 22:12:09 +0100 Subject: x86/vdso: Use static_cpu_has() ... and simplify and speed up a tad. 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/1453842730-28463-10-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/entry/vdso/vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 429d54d01b38..10f704584922 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c @@ -285,7 +285,7 @@ static void vgetcpu_cpu_init(void *arg) #ifdef CONFIG_NUMA node = cpu_to_node(cpu); #endif - if (cpu_has(&cpu_data(cpu), X86_FEATURE_RDTSCP)) + if (static_cpu_has(X86_FEATURE_RDTSCP)) write_rdtscp_aux((node << 12) | cpu); /* -- cgit From a4733143085d6c782ac1e6c85778655b6bac1d4e Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Tue, 26 Jan 2016 22:12:10 +0100 Subject: x86/boot: Simplify kernel load address alignment check We are using %rax as temporary register to check the kernel address alignment. We don't really have to since the TEST instruction does not clobber the destination operand. Suggested-by: Brian Gerst Signed-off-by: Alexander Kuleshov Signed-off-by: Borislav Petkov Cc: Alexander Popov Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1453531828-19291-1-git-send-email-kuleshovmail@gmail.com Link: http://lkml.kernel.org/r/1453842730-28463-11-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/head_64.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index ffdc0e860390..7c21029cb733 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -76,9 +76,7 @@ startup_64: subq $_text - __START_KERNEL_map, %rbp /* Is the address not 2M aligned? */ - movq %rbp, %rax - andl $~PMD_PAGE_MASK, %eax - testl %eax, %eax + testl $~PMD_PAGE_MASK, %ebp jnz bad_address /* -- cgit From ddef482420b1ba8ec45e6123a7e8d3f67b21e5e3 Mon Sep 17 00:00:00 2001 From: "Wang, Rui Y" Date: Wed, 27 Jan 2016 17:08:36 +0800 Subject: crypto: mcryptd - Fix load failure mcryptd_create_hash() fails by returning -EINVAL, causing any driver using mcryptd to fail to load. It is because it needs to set its statesize properly. Signed-off-by: Rui Wang Signed-off-by: Herbert Xu --- crypto/mcryptd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c index f78d4fc4e38a..c4eb9da49d4f 100644 --- a/crypto/mcryptd.c +++ b/crypto/mcryptd.c @@ -522,6 +522,7 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb, inst->alg.halg.base.cra_flags = type; inst->alg.halg.digestsize = salg->digestsize; + inst->alg.halg.statesize = salg->statesize; inst->alg.halg.base.cra_ctxsize = sizeof(struct mcryptd_hash_ctx); inst->alg.halg.base.cra_init = mcryptd_hash_init_tfm; -- cgit From a7c58ac06224b83dba93eaafde88535d5da60aef Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 29 Jan 2016 18:20:17 +0800 Subject: crypto: crc32 - Rename generic implementation The generic crc32 implementation is currently called crc32. This is a problem because it clashes with the lib implementation of crc32. This patch renames the crypto crc32 to crc32_generic so that it is consistent with crc32c. An alias for the driver is also added. Signed-off-by: Herbert Xu --- crypto/Makefile | 2 +- crypto/crc32.c | 159 ------------------------------------------------ crypto/crc32_generic.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 160 deletions(-) delete mode 100644 crypto/crc32.c create mode 100644 crypto/crc32_generic.c diff --git a/crypto/Makefile b/crypto/Makefile index ffe18c9c9bf4..059de1bb254b 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -100,7 +100,7 @@ obj-$(CONFIG_CRYPTO_POLY1305) += poly1305_generic.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_generic.o -obj-$(CONFIG_CRYPTO_CRC32) += crc32.o +obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o diff --git a/crypto/crc32.c b/crypto/crc32.c deleted file mode 100644 index 187ded28cb0b..000000000000 --- a/crypto/crc32.c +++ /dev/null @@ -1,159 +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.gnu.org/licenses - * - * Please visit http://www.xyratex.com/contact if you need additional - * information or have any questions. - * - * GPL HEADER END - */ - -/* - * Copyright 2012 Xyratex Technology Limited - */ - -/* - * This is crypto api shash wrappers to crc32_le. - */ - -#include -#include -#include -#include -#include -#include - -#define CHKSUM_BLOCK_SIZE 1 -#define CHKSUM_DIGEST_SIZE 4 - -static u32 __crc32_le(u32 crc, unsigned char const *p, size_t len) -{ - return crc32_le(crc, p, len); -} - -/** No default init with ~0 */ -static int crc32_cra_init(struct crypto_tfm *tfm) -{ - u32 *key = crypto_tfm_ctx(tfm); - - *key = 0; - - return 0; -} - - -/* - * Setting the seed allows arbitrary accumulators and flexible XOR policy - * If your algorithm starts with ~0, then XOR with ~0 before you set - * the seed. - */ -static int crc32_setkey(struct crypto_shash *hash, const u8 *key, - unsigned int keylen) -{ - u32 *mctx = crypto_shash_ctx(hash); - - if (keylen != sizeof(u32)) { - crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - *mctx = le32_to_cpup((__le32 *)key); - return 0; -} - -static int crc32_init(struct shash_desc *desc) -{ - u32 *mctx = crypto_shash_ctx(desc->tfm); - u32 *crcp = shash_desc_ctx(desc); - - *crcp = *mctx; - - return 0; -} - -static int crc32_update(struct shash_desc *desc, const u8 *data, - unsigned int len) -{ - u32 *crcp = shash_desc_ctx(desc); - - *crcp = __crc32_le(*crcp, data, len); - return 0; -} - -/* No final XOR 0xFFFFFFFF, like crc32_le */ -static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len, - u8 *out) -{ - *(__le32 *)out = cpu_to_le32(__crc32_le(*crcp, data, len)); - return 0; -} - -static int crc32_finup(struct shash_desc *desc, const u8 *data, - unsigned int len, u8 *out) -{ - return __crc32_finup(shash_desc_ctx(desc), data, len, out); -} - -static int crc32_final(struct shash_desc *desc, u8 *out) -{ - u32 *crcp = shash_desc_ctx(desc); - - *(__le32 *)out = cpu_to_le32p(crcp); - return 0; -} - -static int crc32_digest(struct shash_desc *desc, const u8 *data, - unsigned int len, u8 *out) -{ - return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len, - out); -} -static struct shash_alg alg = { - .setkey = crc32_setkey, - .init = crc32_init, - .update = crc32_update, - .final = crc32_final, - .finup = crc32_finup, - .digest = crc32_digest, - .descsize = sizeof(u32), - .digestsize = CHKSUM_DIGEST_SIZE, - .base = { - .cra_name = "crc32", - .cra_driver_name = "crc32-table", - .cra_priority = 100, - .cra_blocksize = CHKSUM_BLOCK_SIZE, - .cra_ctxsize = sizeof(u32), - .cra_module = THIS_MODULE, - .cra_init = crc32_cra_init, - } -}; - -static int __init crc32_mod_init(void) -{ - return crypto_register_shash(&alg); -} - -static void __exit crc32_mod_fini(void) -{ - crypto_unregister_shash(&alg); -} - -module_init(crc32_mod_init); -module_exit(crc32_mod_fini); - -MODULE_AUTHOR("Alexander Boyko "); -MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CRYPTO("crc32"); diff --git a/crypto/crc32_generic.c b/crypto/crc32_generic.c new file mode 100644 index 000000000000..aa2a25fc7482 --- /dev/null +++ b/crypto/crc32_generic.c @@ -0,0 +1,160 @@ +/* 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 + * + * Please visit http://www.xyratex.com/contact if you need additional + * information or have any questions. + * + * GPL HEADER END + */ + +/* + * Copyright 2012 Xyratex Technology Limited + */ + +/* + * This is crypto api shash wrappers to crc32_le. + */ + +#include +#include +#include +#include +#include +#include + +#define CHKSUM_BLOCK_SIZE 1 +#define CHKSUM_DIGEST_SIZE 4 + +static u32 __crc32_le(u32 crc, unsigned char const *p, size_t len) +{ + return crc32_le(crc, p, len); +} + +/** No default init with ~0 */ +static int crc32_cra_init(struct crypto_tfm *tfm) +{ + u32 *key = crypto_tfm_ctx(tfm); + + *key = 0; + + return 0; +} + + +/* + * Setting the seed allows arbitrary accumulators and flexible XOR policy + * If your algorithm starts with ~0, then XOR with ~0 before you set + * the seed. + */ +static int crc32_setkey(struct crypto_shash *hash, const u8 *key, + unsigned int keylen) +{ + u32 *mctx = crypto_shash_ctx(hash); + + if (keylen != sizeof(u32)) { + crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + *mctx = le32_to_cpup((__le32 *)key); + return 0; +} + +static int crc32_init(struct shash_desc *desc) +{ + u32 *mctx = crypto_shash_ctx(desc->tfm); + u32 *crcp = shash_desc_ctx(desc); + + *crcp = *mctx; + + return 0; +} + +static int crc32_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + u32 *crcp = shash_desc_ctx(desc); + + *crcp = __crc32_le(*crcp, data, len); + return 0; +} + +/* No final XOR 0xFFFFFFFF, like crc32_le */ +static int __crc32_finup(u32 *crcp, const u8 *data, unsigned int len, + u8 *out) +{ + *(__le32 *)out = cpu_to_le32(__crc32_le(*crcp, data, len)); + return 0; +} + +static int crc32_finup(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + return __crc32_finup(shash_desc_ctx(desc), data, len, out); +} + +static int crc32_final(struct shash_desc *desc, u8 *out) +{ + u32 *crcp = shash_desc_ctx(desc); + + *(__le32 *)out = cpu_to_le32p(crcp); + return 0; +} + +static int crc32_digest(struct shash_desc *desc, const u8 *data, + unsigned int len, u8 *out) +{ + return __crc32_finup(crypto_shash_ctx(desc->tfm), data, len, + out); +} +static struct shash_alg alg = { + .setkey = crc32_setkey, + .init = crc32_init, + .update = crc32_update, + .final = crc32_final, + .finup = crc32_finup, + .digest = crc32_digest, + .descsize = sizeof(u32), + .digestsize = CHKSUM_DIGEST_SIZE, + .base = { + .cra_name = "crc32", + .cra_driver_name = "crc32-generic", + .cra_priority = 100, + .cra_blocksize = CHKSUM_BLOCK_SIZE, + .cra_ctxsize = sizeof(u32), + .cra_module = THIS_MODULE, + .cra_init = crc32_cra_init, + } +}; + +static int __init crc32_mod_init(void) +{ + return crypto_register_shash(&alg); +} + +static void __exit crc32_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + +module_init(crc32_mod_init); +module_exit(crc32_mod_fini); + +MODULE_AUTHOR("Alexander Boyko "); +MODULE_DESCRIPTION("CRC32 calculations wrapper for lib/crc32"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_CRYPTO("crc32"); +MODULE_ALIAS_CRYPTO("crc32-generic"); -- cgit From cc831d32d7b1bd45c5d74c44d8e39d354049c369 Mon Sep 17 00:00:00 2001 From: Cyrille Pitchen Date: Fri, 29 Jan 2016 17:04:02 +0100 Subject: crypto: atmel-sha - fix algorihtm registration This patch implements the missing .import() and .export() mandatory hooks for asynchronous hash algorithms. It also sets the relevant, non zero, value for the .statesize field when declaring the supported SHA algorithms. Indeed a zero value of .statesize prevents the algorithm from being registered. Signed-off-by: Cyrille Pitchen Signed-off-by: Herbert Xu --- drivers/crypto/atmel-sha.c | 61 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index da4c3055784f..63b09e01075c 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -66,7 +66,7 @@ #define SHA_OP_UPDATE 1 #define SHA_OP_FINAL 2 -#define SHA_BUFFER_LEN PAGE_SIZE +#define SHA_BUFFER_LEN (PAGE_SIZE / 16) #define ATMEL_SHA_DMA_THRESHOLD 56 @@ -80,6 +80,17 @@ struct atmel_sha_caps { struct atmel_sha_dev; +/* + * .statesize = sizeof(struct atmel_sha_state) must be <= PAGE_SIZE / 8 as + * tested by the ahash_prepare_alg() function. + */ +struct atmel_sha_state { + u8 digest[SHA512_DIGEST_SIZE]; + u8 buffer[SHA_BUFFER_LEN]; + u64 digcnt[2]; + size_t bufcnt; +}; + struct atmel_sha_reqctx { struct atmel_sha_dev *dd; unsigned long flags; @@ -1033,6 +1044,39 @@ static int atmel_sha_digest(struct ahash_request *req) return atmel_sha_init(req) ?: atmel_sha_finup(req); } + +static int atmel_sha_export(struct ahash_request *req, void *out) +{ + const struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_state state; + + memcpy(state.digest, ctx->digest, SHA512_DIGEST_SIZE); + memcpy(state.buffer, ctx->buffer, ctx->bufcnt); + state.bufcnt = ctx->bufcnt; + state.digcnt[0] = ctx->digcnt[0]; + state.digcnt[1] = ctx->digcnt[1]; + + /* out might be unaligned. */ + memcpy(out, &state, sizeof(state)); + return 0; +} + +static int atmel_sha_import(struct ahash_request *req, const void *in) +{ + struct atmel_sha_reqctx *ctx = ahash_request_ctx(req); + struct atmel_sha_state state; + + /* in might be unaligned. */ + memcpy(&state, in, sizeof(state)); + + memcpy(ctx->digest, state.digest, SHA512_DIGEST_SIZE); + memcpy(ctx->buffer, state.buffer, state.bufcnt); + ctx->bufcnt = state.bufcnt; + ctx->digcnt[0] = state.digcnt[0]; + ctx->digcnt[1] = state.digcnt[1]; + return 0; +} + static int atmel_sha_cra_init(struct crypto_tfm *tfm) { crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), @@ -1049,8 +1093,11 @@ static struct ahash_alg sha_1_256_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA1_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha1", .cra_driver_name = "atmel-sha1", @@ -1070,8 +1117,11 @@ static struct ahash_alg sha_1_256_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA256_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha256", .cra_driver_name = "atmel-sha256", @@ -1093,8 +1143,11 @@ static struct ahash_alg sha_224_alg = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA224_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha224", .cra_driver_name = "atmel-sha224", @@ -1116,8 +1169,11 @@ static struct ahash_alg sha_384_512_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha384", .cra_driver_name = "atmel-sha384", @@ -1137,8 +1193,11 @@ static struct ahash_alg sha_384_512_algs[] = { .final = atmel_sha_final, .finup = atmel_sha_finup, .digest = atmel_sha_digest, + .export = atmel_sha_export, + .import = atmel_sha_import, .halg = { .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct atmel_sha_state), .base = { .cra_name = "sha512", .cra_driver_name = "atmel-sha512", -- cgit From 564cff826fd14b8a2f71e663dec8e53b2243a836 Mon Sep 17 00:00:00 2001 From: Alexander Koch Date: Sat, 16 Jan 2016 17:14:36 +0100 Subject: iio: light: opt3001: extract int. time constants Extract integration times as #define constants. This prepares using them for delay/timeout length determination. Signed-off-by: Alexander Koch Signed-off-by: Michael Hornung Tested-by: Andreas Dannenberg Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index 01e111e72d4b..aefbd7989bda 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -65,6 +65,9 @@ #define OPT3001_REG_EXPONENT(n) ((n) >> 12) #define OPT3001_REG_MANTISSA(n) ((n) & 0xfff) +#define OPT3001_INT_TIME_LONG 800000 +#define OPT3001_INT_TIME_SHORT 100000 + /* * Time to wait for conversion result to be ready. The device datasheet * worst-case max value is 880ms. Add some slack to be on the safe side. @@ -325,13 +328,13 @@ static int opt3001_set_int_time(struct opt3001 *opt, int time) reg = ret; switch (time) { - case 100000: + case OPT3001_INT_TIME_SHORT: reg &= ~OPT3001_CONFIGURATION_CT; - opt->int_time = 100000; + opt->int_time = OPT3001_INT_TIME_SHORT; break; - case 800000: + case OPT3001_INT_TIME_LONG: reg |= OPT3001_CONFIGURATION_CT; - opt->int_time = 800000; + opt->int_time = OPT3001_INT_TIME_LONG; break; default: return -EINVAL; @@ -597,9 +600,9 @@ static int opt3001_configure(struct opt3001 *opt) /* Reflect status of the device's integration time setting */ if (reg & OPT3001_CONFIGURATION_CT) - opt->int_time = 800000; + opt->int_time = OPT3001_INT_TIME_LONG; else - opt->int_time = 100000; + opt->int_time = OPT3001_INT_TIME_SHORT; /* Ensure device is in shutdown initially */ opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN); -- cgit From 84e8d090c57522c5f8ae59f5b922bedb929165c7 Mon Sep 17 00:00:00 2001 From: Alexander Koch Date: Sat, 16 Jan 2016 17:14:37 +0100 Subject: iio: light: opt3001: trivial type refactoring Change variable type of struct opt3001 members 'ok_to_ignore_lock' and 'result_ready' uint16-bitfield of length one to bool. They are used as bool, let the compiler do the optimization. Signed-off-by: Alexander Koch Signed-off-by: Michael Hornung Tested-by: Andreas Dannenberg Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index aefbd7989bda..b05c484a1646 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -79,8 +79,8 @@ struct opt3001 { struct device *dev; struct mutex lock; - u16 ok_to_ignore_lock:1; - u16 result_ready:1; + bool ok_to_ignore_lock; + bool result_ready; wait_queue_head_t result_ready_queue; u16 result; -- cgit From ac663db3678a62f69a2a73126e51a9a302b27ff2 Mon Sep 17 00:00:00 2001 From: Alexander Koch Date: Sat, 16 Jan 2016 17:14:38 +0100 Subject: iio: light: opt3001: enable operation w/o IRQ Enable operation of the TI OPT3001 light sensor without having an interrupt line available to connect the INT pin to. In this operation mode, we issue a conversion request and simply wait for the conversion time available as timeout value, determined from integration time configuration and the worst-case time given in the data sheet (sect. 6.5, table on p. 5): short integration time (100ms): 110ms + 3ms = 113ms long integration time (800ms): 880ms + 3ms = 883ms This change is transparent as behaviour defaults to using the interrupt method if an interrupt no. is configured via device tree. Interrupt-less operation mode is performed when no valid interrupt no. is given. Signed-off-by: Alexander Koch Signed-off-by: Michael Hornung Tested-by: Andreas Dannenberg Signed-off-by: Jonathan Cameron --- drivers/iio/light/opt3001.c | 137 ++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 42 deletions(-) diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c index b05c484a1646..b776c8ed4387 100644 --- a/drivers/iio/light/opt3001.c +++ b/drivers/iio/light/opt3001.c @@ -70,9 +70,12 @@ /* * Time to wait for conversion result to be ready. The device datasheet - * worst-case max value is 880ms. Add some slack to be on the safe side. + * sect. 6.5 states results are ready after total integration time plus 3ms. + * This results in worst-case max values of 113ms or 883ms, respectively. + * Add some slack to be on the safe side. */ -#define OPT3001_RESULT_READY_TIMEOUT msecs_to_jiffies(1000) +#define OPT3001_RESULT_READY_SHORT 150 +#define OPT3001_RESULT_READY_LONG 1000 struct opt3001 { struct i2c_client *client; @@ -92,6 +95,8 @@ struct opt3001 { u8 high_thresh_exp; u8 low_thresh_exp; + + bool use_irq; }; struct opt3001_scale { @@ -230,26 +235,30 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2) u16 reg; u8 exponent; u16 value; + long timeout; - /* - * Enable the end-of-conversion interrupt mechanism. Note that doing - * so will overwrite the low-level limit value however we will restore - * this value later on. - */ - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, - OPT3001_LOW_LIMIT_EOC_ENABLE); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; + if (opt->use_irq) { + /* + * Enable the end-of-conversion interrupt mechanism. Note that + * doing so will overwrite the low-level limit value however we + * will restore this value later on. + */ + ret = i2c_smbus_write_word_swapped(opt->client, + OPT3001_LOW_LIMIT, + OPT3001_LOW_LIMIT_EOC_ENABLE); + if (ret < 0) { + dev_err(opt->dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + return ret; + } + + /* Allow IRQ to access the device despite lock being set */ + opt->ok_to_ignore_lock = true; } - /* Reset data-ready indicator flag (will be set in the IRQ routine) */ + /* Reset data-ready indicator flag */ opt->result_ready = false; - /* Allow IRQ to access the device despite lock being set */ - opt->ok_to_ignore_lock = true; - /* Configure for single-conversion mode and start a new conversion */ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); if (ret < 0) { @@ -269,32 +278,69 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2) goto err; } - /* Wait for the IRQ to indicate the conversion is complete */ - ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready, - OPT3001_RESULT_READY_TIMEOUT); + if (opt->use_irq) { + /* Wait for the IRQ to indicate the conversion is complete */ + ret = wait_event_timeout(opt->result_ready_queue, + opt->result_ready, + msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); + } else { + /* Sleep for result ready time */ + timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? + OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG; + msleep(timeout); + + /* Check result ready flag */ + ret = i2c_smbus_read_word_swapped(opt->client, + OPT3001_CONFIGURATION); + if (ret < 0) { + dev_err(opt->dev, "failed to read register %02x\n", + OPT3001_CONFIGURATION); + goto err; + } + + if (!(ret & OPT3001_CONFIGURATION_CRF)) { + ret = -ETIMEDOUT; + goto err; + } + + /* Obtain value */ + ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT); + if (ret < 0) { + dev_err(opt->dev, "failed to read register %02x\n", + OPT3001_RESULT); + goto err; + } + opt->result = ret; + opt->result_ready = true; + } err: - /* Disallow IRQ to access the device while lock is active */ - opt->ok_to_ignore_lock = false; + if (opt->use_irq) + /* Disallow IRQ to access the device while lock is active */ + opt->ok_to_ignore_lock = false; if (ret == 0) return -ETIMEDOUT; else if (ret < 0) return ret; - /* - * Disable the end-of-conversion interrupt mechanism by restoring the - * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note - * that selectively clearing those enable bits would affect the actual - * limit value due to bit-overlap and therefore can't be done. - */ - value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, - value); - if (ret < 0) { - dev_err(opt->dev, "failed to write register %02x\n", - OPT3001_LOW_LIMIT); - return ret; + if (opt->use_irq) { + /* + * Disable the end-of-conversion interrupt mechanism by + * restoring the low-level limit value (clearing + * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing + * those enable bits would affect the actual limit value due to + * bit-overlap and therefore can't be done. + */ + value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; + ret = i2c_smbus_write_word_swapped(opt->client, + OPT3001_LOW_LIMIT, + value); + if (ret < 0) { + dev_err(opt->dev, "failed to write register %02x\n", + OPT3001_LOW_LIMIT); + return ret; + } } exponent = OPT3001_REG_EXPONENT(opt->result); @@ -736,12 +782,18 @@ static int opt3001_probe(struct i2c_client *client, return ret; } - ret = request_threaded_irq(irq, NULL, opt3001_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "opt3001", iio); - if (ret) { - dev_err(dev, "failed to request IRQ #%d\n", irq); - return ret; + /* Make use of INT pin only if valid IRQ no. is given */ + if (irq > 0) { + ret = request_threaded_irq(irq, NULL, opt3001_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "opt3001", iio); + if (ret) { + dev_err(dev, "failed to request IRQ #%d\n", irq); + return ret; + } + opt->use_irq = true; + } else { + dev_dbg(opt->dev, "enabling interrupt-less operation\n"); } return 0; @@ -754,7 +806,8 @@ static int opt3001_remove(struct i2c_client *client) int ret; u16 reg; - free_irq(client->irq, iio); + if (opt->use_irq) + free_irq(client->irq, iio); ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); if (ret < 0) { -- cgit From 255ec44451f07334e4c4d54826fc9f2d21025b9e Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Thu, 21 Jan 2016 12:22:59 +0530 Subject: Staging: iio: Documentation: Remove unused sysfs attributes This patch removes the unused sysfs attributes range, range_available, adc_resolution and adc_resolution_available. Signed-off-by: Shraddha Barke Signed-off-by: Jonathan Cameron --- .../staging/iio/Documentation/sysfs-bus-iio-light | 28 ---------------------- 1 file changed, 28 deletions(-) diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-light b/drivers/staging/iio/Documentation/sysfs-bus-iio-light index 17e5c9c515d4..7c7cd8456060 100644 --- a/drivers/staging/iio/Documentation/sysfs-bus-iio-light +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-light @@ -1,31 +1,3 @@ - -What: /sys/bus/iio/devices/device[n]/range -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent ADC Full Scale Range used for some ambient - light sensors in calculating lux. - -What: /sys/bus/iio/devices/device[n]/range_available -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent supported vales for ADC Full Scale Range. - -What: /sys/bus/iio/devices/device[n]/adc_resolution -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent ADC resolution of the ambient light sensor - used in calculating the lux. - -What: /sys/bus/iio/devices/device[n]/adc_resolution_available -KernelVersion: 2.6.37 -Contact: linux-iio@vger.kernel.org -Description: - Hardware dependent list of possible values supported for the - adc_resolution of the given sensor. - What: /sys/bus/iio/devices/device[n]/in_illuminance0[_input|_raw] KernelVersion: 2.6.35 Contact: linux-iio@vger.kernel.org -- cgit From 0b767b31889539fbc31383469317264ebee3cf08 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 16 Jan 2016 01:00:02 +0900 Subject: iio: pressure: mpl115: don't set unused i2c clientdata mpl115 sets i2c clientdata, but it is not used anywhere. So remove it. Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/mpl115.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index f5ecd6e19f5d..3e1e33535fe1 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -163,7 +163,6 @@ static int mpl115_probe(struct i2c_client *client, data->client = client; mutex_init(&data->lock); - i2c_set_clientdata(client, indio_dev); indio_dev->info = &mpl115_info; indio_dev->name = id->name; indio_dev->dev.parent = &client->dev; -- cgit From c984b9cbbd17d3eb602de3802e25d975182474fa Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 16 Jan 2016 01:00:03 +0900 Subject: iio: pressure: mpl115: support MPL115A1 mpl115 driver currently supports i2c interface (MPL115A2). There is also SPI version (MPL115A1). The difference between them is only physical transport so we can easily support both while sharing most of the code. Split the driver into a core support module and one module each for I2C and SPI support. Signed-off-by: Akinobu Mita Cc: Jonathan Cameron Cc: Hartmut Knaack Cc: Lars-Peter Clausen Cc: Peter Meerwald Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 17 +++++- drivers/iio/pressure/Makefile | 2 + drivers/iio/pressure/mpl115.c | 65 ++++++++++------------- drivers/iio/pressure/mpl115.h | 24 +++++++++ drivers/iio/pressure/mpl115_i2c.c | 67 ++++++++++++++++++++++++ drivers/iio/pressure/mpl115_spi.c | 106 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 242 insertions(+), 39 deletions(-) create mode 100644 drivers/iio/pressure/mpl115.h create mode 100644 drivers/iio/pressure/mpl115_i2c.c create mode 100644 drivers/iio/pressure/mpl115_spi.c diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index 6f2e7c9ac23e..e8f60dbf646e 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -31,14 +31,29 @@ config HID_SENSOR_PRESS will be called hid-sensor-press. config MPL115 + tristate + +config MPL115_I2C tristate "Freescale MPL115A2 pressure sensor driver" depends on I2C + select MPL115 help Say yes here to build support for the Freescale MPL115A2 pressure sensor connected via I2C. To compile this driver as a module, choose M here: the module - will be called mpl115. + will be called mpl115_i2c. + +config MPL115_SPI + tristate "Freescale MPL115A1 pressure sensor driver" + depends on SPI_MASTER + select MPL115 + help + Say yes here to build support for the Freescale MPL115A1 + pressure sensor connected via SPI. + + To compile this driver as a module, choose M here: the module + will be called mpl115_spi. config MPL3115 tristate "Freescale MPL3115A2 pressure sensor driver" diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 46571c96823f..d336af14f3fe 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_BMP280) += bmp280.o obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o obj-$(CONFIG_MPL115) += mpl115.o +obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o +obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o obj-$(CONFIG_MPL3115) += mpl3115.o obj-$(CONFIG_MS5611) += ms5611_core.o obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c index 3e1e33535fe1..138344ca3ffd 100644 --- a/drivers/iio/pressure/mpl115.c +++ b/drivers/iio/pressure/mpl115.c @@ -1,5 +1,5 @@ /* - * mpl115.c - Support for Freescale MPL115A2 pressure/temperature sensor + * mpl115.c - Support for Freescale MPL115A pressure/temperature sensor * * Copyright (c) 2014 Peter Meerwald * @@ -7,17 +7,16 @@ * the GNU General Public License. See the file COPYING in the main * directory of this archive for more details. * - * (7-bit I2C slave address 0x60) - * * TODO: shutdown pin * */ #include -#include #include #include +#include "mpl115.h" + #define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */ #define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */ #define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */ @@ -27,16 +26,18 @@ #define MPL115_CONVERT 0x12 /* convert temperature and pressure */ struct mpl115_data { - struct i2c_client *client; + struct device *dev; struct mutex lock; s16 a0; s16 b1, b2; s16 c12; + const struct mpl115_ops *ops; }; static int mpl115_request(struct mpl115_data *data) { - int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0); + int ret = data->ops->write(data->dev, MPL115_CONVERT, 0); + if (ret < 0) return ret; @@ -57,12 +58,12 @@ static int mpl115_comp_pressure(struct mpl115_data *data, int *val, int *val2) if (ret < 0) goto done; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC); + ret = data->ops->read(data->dev, MPL115_PADC); if (ret < 0) goto done; padc = ret >> 6; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); + ret = data->ops->read(data->dev, MPL115_TADC); if (ret < 0) goto done; tadc = ret >> 6; @@ -90,7 +91,7 @@ static int mpl115_read_temp(struct mpl115_data *data) ret = mpl115_request(data); if (ret < 0) goto done; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); + ret = data->ops->read(data->dev, MPL115_TADC); done: mutex_unlock(&data->lock); return ret; @@ -145,65 +146,53 @@ static const struct iio_info mpl115_info = { .driver_module = THIS_MODULE, }; -static int mpl115_probe(struct i2c_client *client, - const struct i2c_device_id *id) +int mpl115_probe(struct device *dev, const char *name, + const struct mpl115_ops *ops) { struct mpl115_data *data; struct iio_dev *indio_dev; int ret; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - 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); - data->client = client; + data->dev = dev; + data->ops = ops; mutex_init(&data->lock); indio_dev->info = &mpl115_info; - indio_dev->name = id->name; - indio_dev->dev.parent = &client->dev; + indio_dev->name = name; + indio_dev->dev.parent = dev; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = mpl115_channels; indio_dev->num_channels = ARRAY_SIZE(mpl115_channels); - ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0); + ret = data->ops->init(data->dev); + if (ret) + return ret; + + ret = data->ops->read(data->dev, MPL115_A0); if (ret < 0) return ret; data->a0 = ret; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1); + ret = data->ops->read(data->dev, MPL115_B1); if (ret < 0) return ret; data->b1 = ret; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2); + ret = data->ops->read(data->dev, MPL115_B2); if (ret < 0) return ret; data->b2 = ret; - ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12); + ret = data->ops->read(data->dev, MPL115_C12); if (ret < 0) return ret; data->c12 = ret; - return devm_iio_device_register(&client->dev, indio_dev); + return devm_iio_device_register(dev, indio_dev); } - -static const struct i2c_device_id mpl115_id[] = { - { "mpl115", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mpl115_id); - -static struct i2c_driver mpl115_driver = { - .driver = { - .name = "mpl115", - }, - .probe = mpl115_probe, - .id_table = mpl115_id, -}; -module_i2c_driver(mpl115_driver); +EXPORT_SYMBOL_GPL(mpl115_probe); MODULE_AUTHOR("Peter Meerwald "); MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver"); diff --git a/drivers/iio/pressure/mpl115.h b/drivers/iio/pressure/mpl115.h new file mode 100644 index 000000000000..01b652774dc3 --- /dev/null +++ b/drivers/iio/pressure/mpl115.h @@ -0,0 +1,24 @@ +/* + * Freescale MPL115A pressure/temperature sensor + * + * Copyright (c) 2014 Peter Meerwald + * Copyright (c) 2016 Akinobu Mita + * + * 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. + */ + +#ifndef _MPL115_H_ +#define _MPL115_H_ + +struct mpl115_ops { + int (*init)(struct device *); + int (*read)(struct device *, u8); + int (*write)(struct device *, u8, u8); +}; + +int mpl115_probe(struct device *dev, const char *name, + const struct mpl115_ops *ops); + +#endif diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c new file mode 100644 index 000000000000..9ea055c3f89e --- /dev/null +++ b/drivers/iio/pressure/mpl115_i2c.c @@ -0,0 +1,67 @@ +/* + * Freescale MPL115A2 pressure/temperature sensor + * + * Copyright (c) 2014 Peter Meerwald + * + * 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 0x60) + * + * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A2.pdf + */ + +#include +#include + +#include "mpl115.h" + +static int mpl115_i2c_init(struct device *dev) +{ + return 0; +} + +static int mpl115_i2c_read(struct device *dev, u8 address) +{ + return i2c_smbus_read_word_swapped(to_i2c_client(dev), address); +} + +static int mpl115_i2c_write(struct device *dev, u8 address, u8 value) +{ + return i2c_smbus_write_byte_data(to_i2c_client(dev), address, value); +} + +static const struct mpl115_ops mpl115_i2c_ops = { + .init = mpl115_i2c_init, + .read = mpl115_i2c_read, + .write = mpl115_i2c_write, +}; + +static int mpl115_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + return mpl115_probe(&client->dev, id->name, &mpl115_i2c_ops); +} + +static const struct i2c_device_id mpl115_i2c_id[] = { + { "mpl115", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, mpl115_i2c_id); + +static struct i2c_driver mpl115_i2c_driver = { + .driver = { + .name = "mpl115", + }, + .probe = mpl115_i2c_probe, + .id_table = mpl115_i2c_id, +}; +module_i2c_driver(mpl115_i2c_driver); + +MODULE_AUTHOR("Peter Meerwald "); +MODULE_DESCRIPTION("Freescale MPL115A2 pressure/temperature driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/pressure/mpl115_spi.c b/drivers/iio/pressure/mpl115_spi.c new file mode 100644 index 000000000000..9ebf55f5b3aa --- /dev/null +++ b/drivers/iio/pressure/mpl115_spi.c @@ -0,0 +1,106 @@ +/* + * Freescale MPL115A1 pressure/temperature sensor + * + * Copyright (c) 2016 Akinobu Mita + * + * 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. + * + * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A1.pdf + */ + +#include +#include + +#include "mpl115.h" + +#define MPL115_SPI_WRITE(address) ((address) << 1) +#define MPL115_SPI_READ(address) (0x80 | (address) << 1) + +struct mpl115_spi_buf { + u8 tx[4]; + u8 rx[4]; +}; + +static int mpl115_spi_init(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct mpl115_spi_buf *buf; + + buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + spi_set_drvdata(spi, buf); + + return 0; +} + +static int mpl115_spi_read(struct device *dev, u8 address) +{ + struct spi_device *spi = to_spi_device(dev); + struct mpl115_spi_buf *buf = spi_get_drvdata(spi); + struct spi_transfer xfer = { + .tx_buf = buf->tx, + .rx_buf = buf->rx, + .len = 4, + }; + int ret; + + buf->tx[0] = MPL115_SPI_READ(address); + buf->tx[2] = MPL115_SPI_READ(address + 1); + + ret = spi_sync_transfer(spi, &xfer, 1); + if (ret) + return ret; + + return (buf->rx[1] << 8) | buf->rx[3]; +} + +static int mpl115_spi_write(struct device *dev, u8 address, u8 value) +{ + struct spi_device *spi = to_spi_device(dev); + struct mpl115_spi_buf *buf = spi_get_drvdata(spi); + struct spi_transfer xfer = { + .tx_buf = buf->tx, + .len = 2, + }; + + buf->tx[0] = MPL115_SPI_WRITE(address); + buf->tx[1] = value; + + return spi_sync_transfer(spi, &xfer, 1); +} + +static const struct mpl115_ops mpl115_spi_ops = { + .init = mpl115_spi_init, + .read = mpl115_spi_read, + .write = mpl115_spi_write, +}; + +static int mpl115_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + + return mpl115_probe(&spi->dev, id->name, &mpl115_spi_ops); +} + +static const struct spi_device_id mpl115_spi_ids[] = { + { "mpl115", 0 }, + {} +}; +MODULE_DEVICE_TABLE(spi, mpl115_spi_ids); + +static struct spi_driver mpl115_spi_driver = { + .driver = { + .name = "mpl115", + }, + .probe = mpl115_spi_probe, + .id_table = mpl115_spi_ids, +}; +module_spi_driver(mpl115_spi_driver); + +MODULE_AUTHOR("Akinobu Mita "); +MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver"); +MODULE_LICENSE("GPL"); -- cgit From 22acc120a141ce0a3b6e98799d15970ef687bc70 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 17 Jan 2016 16:13:29 +0000 Subject: iio: dht11: Improve reliability - be more tolerant about missing start bits Instead of guessing where the data starts, we now just try to decode from every possible start position. This causes no additional overhead if we properly received the full preamble and only costs a few extra CPU cycles in the case where the preamble is corrupted. This is much more efficient than to return an error to userspace and start over again. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 1165b1c4f9d6..1ca284aaacfc 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -161,7 +161,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, int *val, int *val2, long m) { struct dht11 *dht11 = iio_priv(iio_dev); - int ret, timeres; + int ret, timeres, offset; mutex_lock(&dht11->lock); if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) { @@ -208,11 +208,14 @@ static int dht11_read_raw(struct iio_dev *iio_dev, if (ret < 0) goto err; - ret = dht11_decode(dht11, - dht11->num_edges == DHT11_EDGES_PER_READ ? - DHT11_EDGES_PREAMBLE : - DHT11_EDGES_PREAMBLE - 2, - timeres); + offset = DHT11_EDGES_PREAMBLE + + dht11->num_edges - DHT11_EDGES_PER_READ; + for (; offset >= 0; --offset) { + ret = dht11_decode(dht11, offset, timeres); + if (!ret) + break; + } + if (ret) goto err; } -- cgit From 155a57593d38cf7153c01cc037373462aa1e1cc1 Mon Sep 17 00:00:00 2001 From: Harald Geyer Date: Sun, 17 Jan 2016 16:13:30 +0000 Subject: iio: dht11: Simplify decoding algorithm The new algorithm uses a 'one size fits em all' threshold, which should be easier to understand and debug. I believe there are no regressions compared to the old adaptive threshold algorithm. I don't remember why I chose the old algorithm when I initially wrote the driver. Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 64 +++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 1ca284aaacfc..96185f8fad88 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c @@ -50,12 +50,32 @@ #define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \ DHT11_EDGES_PREAMBLE + 1) -/* Data transmission timing (nano seconds) */ +/* + * Data transmission timing: + * Data bits are encoded as pulse length (high time) on the data line. + * 0-bit: 22-30uS -- typically 26uS (AM2302) + * 1-bit: 68-75uS -- typically 70uS (AM2302) + * The acutal timings also depend on the properties of the cable, with + * longer cables typically making pulses shorter. + * + * Our decoding depends on the time resolution of the system: + * timeres > 34uS ... don't know what a 1-tick pulse is + * 34uS > timeres > 30uS ... no problem (30kHz and 32kHz clocks) + * 30uS > timeres > 23uS ... don't know what a 2-tick pulse is + * timeres < 23uS ... no problem + * + * Luckily clocks in the 33-44kHz range are quite uncommon, so we can + * support most systems if the threshold for decoding a pulse as 1-bit + * is chosen carefully. If somebody really wants to support clocks around + * 40kHz, where this driver is most unreliable, there are two options. + * a) select an implementation using busy loop polling on those systems + * b) use the checksum to do some probabilistic decoding + */ #define DHT11_START_TRANSMISSION 18 /* ms */ -#define DHT11_SENSOR_RESPONSE 80000 -#define DHT11_START_BIT 50000 -#define DHT11_DATA_BIT_LOW 27000 -#define DHT11_DATA_BIT_HIGH 70000 +#define DHT11_MIN_TIMERES 34000 /* ns */ +#define DHT11_THRESHOLD 49000 /* ns */ +#define DHT11_AMBIG_LOW 23000 /* ns */ +#define DHT11_AMBIG_HIGH 30000 /* ns */ struct dht11 { struct device *dev; @@ -76,43 +96,39 @@ struct dht11 { struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ]; }; -static unsigned char dht11_decode_byte(int *timing, int threshold) +static unsigned char dht11_decode_byte(char *bits) { unsigned char ret = 0; int i; for (i = 0; i < 8; ++i) { ret <<= 1; - if (timing[i] >= threshold) + if (bits[i]) ++ret; } return ret; } -static int dht11_decode(struct dht11 *dht11, int offset, int timeres) +static int dht11_decode(struct dht11 *dht11, int offset) { - int i, t, timing[DHT11_BITS_PER_READ], threshold; + int i, t; + char bits[DHT11_BITS_PER_READ]; unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum; - threshold = DHT11_DATA_BIT_HIGH / timeres; - if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold) - pr_err("dht11: WARNING: decoding ambiguous\n"); - - /* scale down with timeres and check validity */ 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 */ - timing[i] = t / timeres; + bits[i] = t > DHT11_THRESHOLD; } - hum_int = dht11_decode_byte(timing, threshold); - hum_dec = dht11_decode_byte(&timing[8], threshold); - temp_int = dht11_decode_byte(&timing[16], threshold); - temp_dec = dht11_decode_byte(&timing[24], threshold); - checksum = dht11_decode_byte(&timing[32], threshold); + hum_int = dht11_decode_byte(bits); + hum_dec = dht11_decode_byte(&bits[8]); + temp_int = dht11_decode_byte(&bits[16]); + temp_dec = dht11_decode_byte(&bits[24]); + checksum = dht11_decode_byte(&bits[32]); if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum) return -EIO; @@ -166,7 +182,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, mutex_lock(&dht11->lock); if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) { timeres = ktime_get_resolution_ns(); - if (DHT11_DATA_BIT_HIGH < 2 * timeres) { + if (timeres > DHT11_MIN_TIMERES) { dev_err(dht11->dev, "timeresolution %dns too low\n", timeres); /* In theory a better clock could become available @@ -176,6 +192,10 @@ static int dht11_read_raw(struct iio_dev *iio_dev, ret = -EAGAIN; goto err; } + if (timeres > DHT11_AMBIG_LOW && timeres < DHT11_AMBIG_HIGH) + dev_warn(dht11->dev, + "timeresolution: %dns - decoding ambiguous\n", + timeres); reinit_completion(&dht11->completion); @@ -211,7 +231,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, offset = DHT11_EDGES_PREAMBLE + dht11->num_edges - DHT11_EDGES_PER_READ; for (; offset >= 0; --offset) { - ret = dht11_decode(dht11, offset, timeres); + ret = dht11_decode(dht11, offset); if (!ret) break; } -- cgit From 21cb454dc7c065d213efe8d578d67b65ecec8e02 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sun, 24 Jan 2016 17:06:50 +0000 Subject: iio:pressure:Kconfig white space cleanup. Clearly a high degree of cut and paste has gone on in this file, propogating a particularly random combination of tabs and spaces. This patch at least should make it all consistent going forward. Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index e8f60dbf646e..cf03a43545a1 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -10,11 +10,11 @@ config BMP280 depends on I2C 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 BMP280 + pressure and temperature sensor. - To compile this driver as a module, choose M here: the module - will be called bmp280. + To compile this driver as a module, choose M here: the module + will be called bmp280. config HID_SENSOR_PRESS depends on HID_SENSOR_HUB @@ -27,8 +27,8 @@ config HID_SENSOR_PRESS Say yes here to build support for the HID SENSOR Pressure driver - To compile this driver as a module, choose M here: the module - will be called hid-sensor-press. + To compile this driver as a module, choose M here: the module + will be called hid-sensor-press. config MPL115 tristate @@ -41,8 +41,8 @@ config MPL115_I2C Say yes here to build support for the Freescale MPL115A2 pressure sensor connected via I2C. - To compile this driver as a module, choose M here: the module - will be called mpl115_i2c. + To compile this driver as a module, choose M here: the module + will be called mpl115_i2c. config MPL115_SPI tristate "Freescale MPL115A1 pressure sensor driver" @@ -52,8 +52,8 @@ config MPL115_SPI Say yes here to build support for the Freescale MPL115A1 pressure sensor connected via SPI. - To compile this driver as a module, choose M here: the module - will be called mpl115_spi. + To compile this driver as a module, choose M here: the module + will be called mpl115_spi. config MPL3115 tristate "Freescale MPL3115A2 pressure sensor driver" @@ -64,8 +64,8 @@ config MPL3115 Say yes here to build support for the Freescale MPL3115A2 pressure sensor / altimeter. - To compile this driver as a module, choose M here: the module - will be called mpl3115. + To compile this driver as a module, choose M here: the module + will be called mpl3115. config MS5611 tristate "Measurement Specialties MS5611 pressure sensor driver" @@ -97,7 +97,7 @@ config MS5611_SPI config MS5637 tristate "Measurement Specialties MS5637 pressure & temperature sensor" depends on I2C - select IIO_MS_SENSORS_I2C + select IIO_MS_SENSORS_I2C help If you say yes here you get support for the Measurement Specialties MS5637 pressure and temperature sensor. @@ -143,7 +143,7 @@ config T5403 Say yes here to build support for the EPCOS T5403 pressure sensor connected via I2C. - To compile this driver as a module, choose M here: the module - will be called t5403. + To compile this driver as a module, choose M here: the module + will be called t5403. endmenu -- cgit From 3f4202652ea742a79294bd7b8a945ff96696b966 Mon Sep 17 00:00:00 2001 From: Cristina Moraru Date: Tue, 26 Jan 2016 22:21:07 +0200 Subject: iio: si7005: add support for Hoperf th02 This patch adds support for Hoperf th02 humidity and temperature sensor as it uses same register definitions as si7005 th02 Datasheet: http://www.anglia-live.com/netalogue/pdfs/hrf/datasheets/TH02_V1.1.pdf Signed-off-by: Cristina Moraru Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 3 ++- drivers/iio/humidity/si7005.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 6a23698d347c..63823379830b 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -43,7 +43,8 @@ config SI7005 humidity and temperature sensor. To compile this driver as a module, choose M here: the module - will be called si7005. + will be called si7005. This driver also + supports Hoperf TH02 Humidity and Temperature Sensor. config SI7020 tristate "Si7013/20/21 Relative Humidity and Temperature Sensors" diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c index 91972ccd8aaf..98a022fa26ad 100644 --- a/drivers/iio/humidity/si7005.c +++ b/drivers/iio/humidity/si7005.c @@ -170,6 +170,7 @@ static int si7005_probe(struct i2c_client *client, static const struct i2c_device_id si7005_id[] = { { "si7005", 0 }, + { "th02", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, si7005_id); -- cgit From 920dad0ce3f8893fa41a630435da44b4b719bdcb Mon Sep 17 00:00:00 2001 From: Cristina Moraru Date: Tue, 26 Jan 2016 22:17:49 +0200 Subject: iio: si7020: add support for Hoperf th06 This patch adds support for Hoperf th06 humidity and temperature sensor as it uses same register definitions as si7020 th06 Datasheet: http://www.hoperf.com/upload/sensor/TH06.pdf Signed-off-by: Cristina Moraru Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/Kconfig | 3 ++- drivers/iio/humidity/si7020.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig index 63823379830b..866dda133336 100644 --- a/drivers/iio/humidity/Kconfig +++ b/drivers/iio/humidity/Kconfig @@ -51,7 +51,8 @@ config SI7020 depends on I2C help Say yes here to build support for the Silicon Labs Si7013/20/21 - Relative Humidity and Temperature Sensors. + Relative Humidity and Temperature Sensors. This driver also + supports Hoperf TH06 Humidity and Temperature Sensor. To compile this driver as a module, choose M here: the module will be called si7020. diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c index 71991b5c0658..5ab4e06fb544 100644 --- a/drivers/iio/humidity/si7020.c +++ b/drivers/iio/humidity/si7020.c @@ -149,6 +149,7 @@ static int si7020_probe(struct i2c_client *client, static const struct i2c_device_id si7020_id[] = { { "si7020", 0 }, + { "th06", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, si7020_id); -- cgit From 5f9c95d8516e9383f545be6f7178eef8aea008c8 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 26 Jan 2016 18:34:29 -0800 Subject: devicetree: add Atlas Scientific LLC vendor prefix Add the "atlas" vendor prefix for Atlas Scientific LLC Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- 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 55df1d444e9f..cd5180b4e477 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -28,6 +28,7 @@ arm ARM Ltd. armadeus ARMadeus Systems SARL artesyn Artesyn Embedded Technologies Inc. asahi-kasei Asahi Kasei Corp. +atlas Atlas Scientific LLC atmel Atmel Corporation auo AU Optronics Corporation avago Avago Technologies -- cgit From ecb3a7ccc653fc8007edd0591d32d839386673f1 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 26 Jan 2016 18:34:30 -0800 Subject: iio: ph: add IIO_PH channel type Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++ drivers/iio/industrialio-core.c | 1 + include/uapi/linux/iio/types.h | 1 + 3 files changed, 9 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 8fadd272ad8a..80c6fce9935b 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1493,3 +1493,10 @@ Description: This ABI is especially applicable for humidity sensors to heatup the device and get rid of any condensation in some humidity environment + +What: /sys/bus/iio/devices/iio:deviceX/in_ph_raw +KernelVersion: 4.5 +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. diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index fd01f3493fc7..eb01a83a5b7c 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -77,6 +77,7 @@ static const char * const iio_chan_type_name_spec[] = { [IIO_VELOCITY] = "velocity", [IIO_CONCENTRATION] = "concentration", [IIO_RESISTANCE] = "resistance", + [IIO_PH] = "ph", }; static const char * const iio_modifier_names[] = { diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h index 7c63bd67c36e..c077617f3304 100644 --- a/include/uapi/linux/iio/types.h +++ b/include/uapi/linux/iio/types.h @@ -37,6 +37,7 @@ enum iio_chan_type { IIO_VELOCITY, IIO_CONCENTRATION, IIO_RESISTANCE, + IIO_PH, }; enum iio_modifier { -- cgit From 27dec00ecf2dfc830c6a407a9870776ea8efabcb Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Tue, 26 Jan 2016 18:34:31 -0800 Subject: iio: chemical: add Atlas pH-SM sensor support Add support for the Atlas Scientific pH-SM chemical sensor that can detect pH levels of solutions in the range of 0-14. Signed-off-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- .../bindings/iio/chemical/atlas,ph-sm.txt | 22 + drivers/iio/chemical/Kconfig | 13 + drivers/iio/chemical/Makefile | 1 + drivers/iio/chemical/atlas-ph-sensor.c | 511 +++++++++++++++++++++ 4 files changed, 547 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt create mode 100644 drivers/iio/chemical/atlas-ph-sensor.c diff --git a/Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt b/Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt new file mode 100644 index 000000000000..cffa1907463a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/chemical/atlas,ph-sm.txt @@ -0,0 +1,22 @@ +* Atlas Scientific pH-SM OEM sensor + +http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf + +Required properties: + + - compatible: must be "atlas,ph-sm" + - reg: the I2C address of the sensor + - interrupt-parent: should be the phandle for the interrupt controller + - interrupts: the sole interrupt generated by the device + + Refer to interrupt-controller/interrupts.txt for generic interrupt client + node bindings. + +Example: + +atlas@65 { + compatible = "atlas,ph-sm"; + reg = <0x65>; + interrupt-parent = <&gpio1>; + interrupts = <16 2>; +}; diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index f16de61be46d..ce7cd1370f74 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -4,6 +4,19 @@ menu "Chemical Sensors" +config ATLAS_PH_SENSOR + tristate "Atlas Scientific OEM pH-SM sensor" + depends on I2C + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say Y here to build I2C interface support for the Atlas + Scientific OEM pH-SM sensor. + + To compile this driver as module, choose M here: the + module will be called atlas-ph-sensor. + config IAQCORE tristate "AMS iAQ-Core VOC sensors" depends on I2C diff --git a/drivers/iio/chemical/Makefile b/drivers/iio/chemical/Makefile index 167861fadfab..b02202b41289 100644 --- a/drivers/iio/chemical/Makefile +++ b/drivers/iio/chemical/Makefile @@ -3,5 +3,6 @@ # # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_ATLAS_PH_SENSOR) += atlas-ph-sensor.o obj-$(CONFIG_IAQCORE) += ams-iaq-core.o obj-$(CONFIG_VZ89X) += vz89x.o diff --git a/drivers/iio/chemical/atlas-ph-sensor.c b/drivers/iio/chemical/atlas-ph-sensor.c new file mode 100644 index 000000000000..06cd49cbfae1 --- /dev/null +++ b/drivers/iio/chemical/atlas-ph-sensor.c @@ -0,0 +1,511 @@ +/* + * atlas-ph-sensor.c - Support for Atlas Scientific OEM pH-SM sensor + * + * Copyright (C) 2015 Matt Ranostay + * + * 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 +#include +#include + +#define ATLAS_REGMAP_NAME "atlas_ph_regmap" +#define ATLAS_DRV_NAME "atlas_ph" + +#define ATLAS_REG_DEV_TYPE 0x00 +#define ATLAS_REG_DEV_VERSION 0x01 + +#define ATLAS_REG_INT_CONTROL 0x04 +#define ATLAS_REG_INT_CONTROL_EN BIT(3) + +#define ATLAS_REG_PWR_CONTROL 0x06 + +#define ATLAS_REG_CALIB_STATUS 0x0d +#define ATLAS_REG_CALIB_STATUS_MASK 0x07 +#define ATLAS_REG_CALIB_STATUS_LOW BIT(0) +#define ATLAS_REG_CALIB_STATUS_MID BIT(1) +#define ATLAS_REG_CALIB_STATUS_HIGH BIT(2) + +#define ATLAS_REG_TEMP_DATA 0x0e +#define ATLAS_REG_PH_DATA 0x16 + +#define ATLAS_PH_INT_TIME_IN_US 450000 + +struct atlas_data { + struct i2c_client *client; + struct iio_trigger *trig; + struct regmap *regmap; + struct irq_work work; + + __be32 buffer[4]; /* 32-bit pH data + 32-bit pad + 64-bit timestamp */ +}; + +static const struct regmap_range atlas_volatile_ranges[] = { + regmap_reg_range(ATLAS_REG_INT_CONTROL, ATLAS_REG_INT_CONTROL), + regmap_reg_range(ATLAS_REG_CALIB_STATUS, ATLAS_REG_CALIB_STATUS), + regmap_reg_range(ATLAS_REG_TEMP_DATA, ATLAS_REG_TEMP_DATA + 4), + regmap_reg_range(ATLAS_REG_PH_DATA, ATLAS_REG_PH_DATA + 4), +}; + +static const struct regmap_access_table atlas_volatile_table = { + .yes_ranges = atlas_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(atlas_volatile_ranges), +}; + +static const struct regmap_config atlas_regmap_config = { + .name = ATLAS_REGMAP_NAME, + + .reg_bits = 8, + .val_bits = 8, + + .volatile_table = &atlas_volatile_table, + .max_register = ATLAS_REG_PH_DATA + 4, + .cache_type = REGCACHE_FLAT, +}; + +static const struct iio_chan_spec atlas_channels[] = { + { + .type = IIO_PH, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 'u', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_BE, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(1), + { + .type = IIO_TEMP, + .address = ATLAS_REG_TEMP_DATA, + .info_mask_separate = + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), + .output = 1, + .scan_index = -1 + }, +}; + +static int atlas_set_powermode(struct atlas_data *data, int on) +{ + return regmap_write(data->regmap, ATLAS_REG_PWR_CONTROL, on); +} + +static int atlas_set_interrupt(struct atlas_data *data, bool state) +{ + return regmap_update_bits(data->regmap, ATLAS_REG_INT_CONTROL, + ATLAS_REG_INT_CONTROL_EN, + state ? ATLAS_REG_INT_CONTROL_EN : 0); +} + +static int atlas_buffer_postenable(struct iio_dev *indio_dev) +{ + struct atlas_data *data = iio_priv(indio_dev); + int ret; + + ret = iio_triggered_buffer_postenable(indio_dev); + if (ret) + return ret; + + ret = pm_runtime_get_sync(&data->client->dev); + if (ret < 0) { + pm_runtime_put_noidle(&data->client->dev); + return ret; + } + + return atlas_set_interrupt(data, true); +} + +static int atlas_buffer_predisable(struct iio_dev *indio_dev) +{ + struct atlas_data *data = iio_priv(indio_dev); + int ret; + + ret = iio_triggered_buffer_predisable(indio_dev); + if (ret) + return ret; + + ret = atlas_set_interrupt(data, false); + if (ret) + return ret; + + pm_runtime_mark_last_busy(&data->client->dev); + return pm_runtime_put_autosuspend(&data->client->dev); +} + +static const struct iio_trigger_ops atlas_interrupt_trigger_ops = { + .owner = THIS_MODULE, +}; + +static const struct iio_buffer_setup_ops atlas_buffer_setup_ops = { + .postenable = atlas_buffer_postenable, + .predisable = atlas_buffer_predisable, +}; + +static void atlas_work_handler(struct irq_work *work) +{ + struct atlas_data *data = container_of(work, struct atlas_data, work); + + iio_trigger_poll(data->trig); +} + +static irqreturn_t atlas_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct atlas_data *data = iio_priv(indio_dev); + int ret; + + ret = i2c_smbus_read_i2c_block_data(data->client, ATLAS_REG_PH_DATA, + sizeof(data->buffer[0]), (u8 *) &data->buffer); + + if (ret > 0) + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns()); + + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static irqreturn_t atlas_interrupt_handler(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct atlas_data *data = iio_priv(indio_dev); + + irq_work_queue(&data->work); + + return IRQ_HANDLED; +} + +static int atlas_read_ph_measurement(struct atlas_data *data, __be32 *val) +{ + struct device *dev = &data->client->dev; + int suspended = pm_runtime_suspended(dev); + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) { + pm_runtime_put_noidle(dev); + return ret; + } + + if (suspended) + usleep_range(ATLAS_PH_INT_TIME_IN_US, + ATLAS_PH_INT_TIME_IN_US + 100000); + + ret = regmap_bulk_read(data->regmap, ATLAS_REG_PH_DATA, + (u8 *) val, sizeof(*val)); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static int atlas_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct atlas_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: { + int ret; + __be32 reg; + + switch (chan->type) { + case IIO_TEMP: + ret = regmap_bulk_read(data->regmap, chan->address, + (u8 *) ®, sizeof(reg)); + break; + case IIO_PH: + mutex_lock(&indio_dev->mlock); + + if (iio_buffer_enabled(indio_dev)) + ret = -EBUSY; + else + ret = atlas_read_ph_measurement(data, ®); + + mutex_unlock(&indio_dev->mlock); + break; + default: + ret = -EINVAL; + } + + if (!ret) { + *val = be32_to_cpu(reg); + ret = IIO_VAL_INT; + } + return ret; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = 1; /* 0.01 */ + *val2 = 100; + break; + case IIO_PH: + *val = 1; /* 0.001 */ + *val2 = 1000; + break; + default: + return -EINVAL; + } + return IIO_VAL_FRACTIONAL; + } + + return -EINVAL; +} + +static int atlas_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct atlas_data *data = iio_priv(indio_dev); + __be32 reg = cpu_to_be32(val); + + if (val2 != 0 || val < 0 || val > 20000) + return -EINVAL; + + if (mask != IIO_CHAN_INFO_RAW || chan->type != IIO_TEMP) + return -EINVAL; + + return regmap_bulk_write(data->regmap, chan->address, + ®, sizeof(reg)); +} + +static const struct iio_info atlas_info = { + .driver_module = THIS_MODULE, + .read_raw = atlas_read_raw, + .write_raw = atlas_write_raw, +}; + +static int atlas_check_calibration(struct atlas_data *data) +{ + struct device *dev = &data->client->dev; + int ret; + unsigned int val; + + ret = regmap_read(data->regmap, ATLAS_REG_CALIB_STATUS, &val); + if (ret) + return ret; + + if (!(val & ATLAS_REG_CALIB_STATUS_MASK)) { + dev_warn(dev, "device has not been calibrated\n"); + return 0; + } + + if (!(val & ATLAS_REG_CALIB_STATUS_LOW)) + dev_warn(dev, "device missing low point calibration\n"); + + if (!(val & ATLAS_REG_CALIB_STATUS_MID)) + dev_warn(dev, "device missing mid point calibration\n"); + + if (!(val & ATLAS_REG_CALIB_STATUS_HIGH)) + dev_warn(dev, "device missing high point calibration\n"); + + return 0; +}; + +static int atlas_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct atlas_data *data; + struct iio_trigger *trig; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + indio_dev->info = &atlas_info; + indio_dev->name = ATLAS_DRV_NAME; + indio_dev->channels = atlas_channels; + indio_dev->num_channels = ARRAY_SIZE(atlas_channels); + indio_dev->modes = INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE; + indio_dev->dev.parent = &client->dev; + + trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d", + indio_dev->name, indio_dev->id); + + if (!trig) + return -ENOMEM; + + data = iio_priv(indio_dev); + data->client = client; + data->trig = trig; + trig->dev.parent = indio_dev->dev.parent; + trig->ops = &atlas_interrupt_trigger_ops; + iio_trigger_set_drvdata(trig, indio_dev); + + i2c_set_clientdata(client, indio_dev); + + data->regmap = devm_regmap_init_i2c(client, &atlas_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(&client->dev, "regmap initialization failed\n"); + return PTR_ERR(data->regmap); + } + + ret = pm_runtime_set_active(&client->dev); + if (ret) + return ret; + + if (client->irq <= 0) { + dev_err(&client->dev, "no valid irq defined\n"); + return -EINVAL; + } + + ret = atlas_check_calibration(data); + if (ret) + return ret; + + ret = iio_trigger_register(trig); + if (ret) { + dev_err(&client->dev, "failed to register trigger\n"); + return ret; + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &atlas_trigger_handler, &atlas_buffer_setup_ops); + if (ret) { + dev_err(&client->dev, "cannot setup iio trigger\n"); + goto unregister_trigger; + } + + init_irq_work(&data->work, atlas_work_handler); + + /* interrupt pin toggles on new conversion */ + ret = devm_request_threaded_irq(&client->dev, client->irq, + NULL, atlas_interrupt_handler, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "atlas_irq", + indio_dev); + if (ret) { + dev_err(&client->dev, "request irq (%d) failed\n", client->irq); + goto unregister_buffer; + } + + ret = atlas_set_powermode(data, 1); + if (ret) { + dev_err(&client->dev, "cannot power device on"); + goto unregister_buffer; + } + + pm_runtime_enable(&client->dev); + pm_runtime_set_autosuspend_delay(&client->dev, 2500); + pm_runtime_use_autosuspend(&client->dev); + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(&client->dev, "unable to register device\n"); + goto unregister_pm; + } + + return 0; + +unregister_pm: + pm_runtime_disable(&client->dev); + atlas_set_powermode(data, 0); + +unregister_buffer: + iio_triggered_buffer_cleanup(indio_dev); + +unregister_trigger: + iio_trigger_unregister(data->trig); + + return ret; +} + +static int atlas_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct atlas_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + iio_trigger_unregister(data->trig); + + pm_runtime_disable(&client->dev); + pm_runtime_set_suspended(&client->dev); + pm_runtime_put_noidle(&client->dev); + + return atlas_set_powermode(data, 0); +} + +#ifdef CONFIG_PM +static int atlas_runtime_suspend(struct device *dev) +{ + struct atlas_data *data = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return atlas_set_powermode(data, 0); +} + +static int atlas_runtime_resume(struct device *dev) +{ + struct atlas_data *data = + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); + + return atlas_set_powermode(data, 1); +} +#endif + +static const struct dev_pm_ops atlas_pm_ops = { + SET_RUNTIME_PM_OPS(atlas_runtime_suspend, + atlas_runtime_resume, NULL) +}; + +static const struct i2c_device_id atlas_id[] = { + { "atlas-ph-sm", 0 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, atlas_id); + +static const struct of_device_id atlas_dt_ids[] = { + { .compatible = "atlas,ph-sm" }, + { } +}; +MODULE_DEVICE_TABLE(of, atlas_dt_ids); + +static struct i2c_driver atlas_driver = { + .driver = { + .name = ATLAS_DRV_NAME, + .of_match_table = of_match_ptr(atlas_dt_ids), + .pm = &atlas_pm_ops, + }, + .probe = atlas_probe, + .remove = atlas_remove, + .id_table = atlas_id, +}; +module_i2c_driver(atlas_driver); + +MODULE_AUTHOR("Matt Ranostay "); +MODULE_DESCRIPTION("Atlas Scientific pH-SM sensor"); +MODULE_LICENSE("GPL"); -- cgit From c2472d0bbcec8920ac9ce4393894bf7844275e81 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Sat, 30 Jan 2016 11:43:45 +0200 Subject: iio: inv_mpu6050: Remove unused parameter The inv_check_and_setup_chip function does not use the i2c_device_id parameter. Therefore remove it. Signed-off-by: Adriana Reus Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index f0e06093b5e8..0852b7fa777e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -727,8 +727,7 @@ static const struct iio_info mpu_info = { /** * inv_check_and_setup_chip() - check and setup chip. */ -static int inv_check_and_setup_chip(struct inv_mpu6050_state *st, - const struct i2c_device_id *id) +static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) { int result; @@ -795,7 +794,7 @@ static int inv_mpu_probe(struct i2c_client *client, if (pdata) st->plat_data = *pdata; /* power is turned on inside check chip type*/ - result = inv_check_and_setup_chip(st, id); + result = inv_check_and_setup_chip(st); if (result) return result; -- cgit From e11b956e9ebef098cc4f81964a1f57e40fe75cd4 Mon Sep 17 00:00:00 2001 From: Li Bin Date: Sat, 30 Jan 2016 11:54:03 +0800 Subject: kernel/Makefile: remove the useless CFLAGS_REMOVE_cgroup-debug.o The file cgroup-debug.c had been removed from commit fe6934354f8e (cgroups: move the cgroup debug subsys into cgroup.c to access internal state). Remain the CFLAGS_REMOVE_cgroup-debug.o = $(CC_FLAGS_FTRACE) useless in kernel/Makefile. Signed-off-by: Li Bin Acked-by: Zefan Li Signed-off-by: Tejun Heo --- kernel/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 53abf008ecb3..baa55e50a315 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -14,8 +14,7 @@ obj-y = fork.o exec_domain.o panic.o \ obj-$(CONFIG_MULTIUSER) += groups.o ifdef CONFIG_FUNCTION_TRACER -# Do not trace debug files and internal ftrace files -CFLAGS_REMOVE_cgroup-debug.o = $(CC_FLAGS_FTRACE) +# Do not trace internal ftrace files CFLAGS_REMOVE_irq_work.o = $(CC_FLAGS_FTRACE) endif -- cgit From 3955525d5d17118ed8900e9e79753057120eb02a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 14 Jan 2016 09:39:21 +0200 Subject: iwlwifi: pcie: buffer packets to avoid overflowing Tx queues When the Tx queues are full above a threshold, we immediately stop the mac80211's queue to stop getting new packets. This worked until TSO was enabled. With TSO, one single packet from mac80211 can use many descriptors since a large send needs to be split into several segments. This means that stopping mac80211's queues is not enough and we also need to ensure that we don't overflow the Tx queues with one single packet from mac80211. Add code to transport layer to do just that. Stop mac80211's queue as soon as the queue is full above the same threshold as before, and keep pushing the current packet along with its segments on the queue, but check that we don't overflow. If that would happen, buffer the segments, and send them when there is room in the Tx queue again. Of course, we first need to send the buffered segments and only then, wake up mac80211's queues. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 69 +++++++++++++++++++--- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index cc3888e2700d..2d8b415fa55e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -280,6 +280,7 @@ struct iwl_txq { bool ampdu; bool block; unsigned long wd_timeout; + struct sk_buff_head overflow_q; }; static inline dma_addr_t diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 5262028b5505..b0b0fd9e2eff 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -571,6 +571,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, return ret; spin_lock_init(&txq->lock); + __skb_queue_head_init(&txq->overflow_q); /* * Tell nic where to find circular buffer of Tx Frame Descriptors for @@ -621,6 +622,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr); } txq->active = false; + + while (!skb_queue_empty(&txq->overflow_q)) { + struct sk_buff *skb = __skb_dequeue(&txq->overflow_q); + + iwl_op_mode_free_skb(trans->op_mode, skb); + } + spin_unlock_bh(&txq->lock); /* just in case - this queue may have been stopped */ @@ -1052,8 +1060,41 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, iwl_pcie_txq_progress(txq); - if (iwl_queue_space(&txq->q) > txq->q.low_mark) - iwl_wake_queue(trans, txq); + if (iwl_queue_space(&txq->q) > txq->q.low_mark && + test_bit(txq_id, trans_pcie->queue_stopped)) { + struct sk_buff_head skbs; + + __skb_queue_head_init(&skbs); + skb_queue_splice_init(&txq->overflow_q, &skbs); + + /* + * This is tricky: we are in reclaim path which is non + * re-entrant, so noone will try to take the access the + * txq data from that path. We stopped tx, so we can't + * have tx as well. Bottom line, we can unlock and re-lock + * later. + */ + spin_unlock_bh(&txq->lock); + + while (!skb_queue_empty(&skbs)) { + struct sk_buff *skb = __skb_dequeue(&skbs); + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + u8 dev_cmd_idx = IWL_TRANS_FIRST_DRIVER_DATA + 1; + struct iwl_device_cmd *dev_cmd = + info->driver_data[dev_cmd_idx]; + + /* + * Note that we can very well be overflowing again. + * In that case, iwl_queue_space will be small again + * and we won't wake mac80211's queue. + */ + iwl_trans_pcie_tx(trans, skb, dev_cmd, txq_id); + } + spin_lock_bh(&txq->lock); + + if (iwl_queue_space(&txq->q) > txq->q.low_mark) + iwl_wake_queue(trans, txq); + } if (q->read_ptr == q->write_ptr) { IWL_DEBUG_RPM(trans, "Q %d - last tx reclaimed\n", q->id); @@ -2161,6 +2202,8 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, csum = skb_checksum(skb, offs, skb->len - offs, 0); *(__sum16 *)(skb->data + csum_offs) = csum_fold(csum); + + skb->ip_summed = CHECKSUM_UNNECESSARY; } if (skb_is_nonlinear(skb) && @@ -2177,6 +2220,22 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, spin_lock(&txq->lock); + if (iwl_queue_space(q) < q->high_mark) { + iwl_stop_queue(trans, txq); + + /* don't put the packet on the ring, if there is no room */ + if (unlikely(iwl_queue_space(q) < 3)) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + + info->driver_data[IWL_TRANS_FIRST_DRIVER_DATA + 1] = + dev_cmd; + __skb_queue_tail(&txq->overflow_q, skb); + + spin_unlock(&txq->lock); + return 0; + } + } + /* In AGG mode, the index in the ring must correspond to the WiFi * sequence number. This is a HW requirements to help the SCD to parse * the BA. @@ -2281,12 +2340,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, * At this point the frame is "transmitted" successfully * and we will get a TX status notification eventually. */ - if (iwl_queue_space(q) < q->high_mark) { - if (wait_write_ptr) - iwl_pcie_txq_inc_wr_ptr(trans, txq); - else - iwl_stop_queue(trans, txq); - } spin_unlock(&txq->lock); return 0; out_err: -- cgit From 7848505416be4e96af14c3387775622d26a13146 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 14 Dec 2015 17:44:11 +0200 Subject: iwlwifi: pcie: add infrastructure for multi-queue rx The 9000 series devices will support multi rx queues. Current code has one static rx queue - change it to allocate a number of queues per the device capability (pre-9000 devices have the number of rx queues set to one). Subsequent generalizations are: Change the code to access an explicit numbered rx queue only when the queue number is known - when handling interrupt, when accessing the default queue and when iterating the queues. The rest of the functions will receive the rx queue as a pointer. Generalize the warning in allocation failure to consider the allocator status instead of a single rx queue status. Move the rx initial pool of memory buffers to be shared among all the queues and allocated to the default queue on init. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 8 +- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 264 +++++++++++---------- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 73 ++++-- 3 files changed, 191 insertions(+), 154 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 2d8b415fa55e..11ad87fca67a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -57,7 +57,7 @@ #define RX_POST_REQ_ALLOC 2 #define RX_CLAIM_REQ_ALLOC 8 #define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES) -#define RX_LOW_WATERMARK 8 +#define RX_PENDING_WATERMARK 16 struct iwl_host_cmd; @@ -103,7 +103,6 @@ struct isr_statistics { * @rb_stts: driver's pointer to receive buffer status * @rb_stts_dma: bus address of receive buffer status * @lock: - * @pool: initial pool of iwl_rx_mem_buffer for the queue * @queue: actual rx queue * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers @@ -122,7 +121,6 @@ struct iwl_rxq { struct iwl_rb_status *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE]; struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; }; @@ -298,6 +296,7 @@ struct iwl_tso_hdr_page { /** * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data + * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues * @rba: allocator for RX replenishing * @drv - pointer to iwl_drv * @trans: pointer to the generic transport area @@ -324,7 +323,8 @@ struct iwl_tso_hdr_page { * @fw_mon_size: size of the buffer for the firmware monitor */ struct iwl_trans_pcie { - struct iwl_rxq rxq; + struct iwl_rxq *rxq; + struct iwl_rx_mem_buffer rx_pool[RX_QUEUE_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 ccafbd8cf4b3..f557f3dc4db8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -173,10 +173,9 @@ int iwl_pcie_rx_stop(struct iwl_trans *trans) /* * iwl_pcie_rxq_inc_wr_ptr - Update the write pointer for the RX queue */ -static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans) +static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, + struct iwl_rxq *rxq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; u32 reg; lockdep_assert_held(&rxq->lock); @@ -207,18 +206,18 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans) static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - - spin_lock(&rxq->lock); - - if (!rxq->need_update) - goto exit_unlock; + int i; - iwl_pcie_rxq_inc_wr_ptr(trans); - rxq->need_update = false; + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - exit_unlock: - spin_unlock(&rxq->lock); + if (!rxq->need_update) + continue; + spin_lock(&rxq->lock); + iwl_pcie_rxq_inc_wr_ptr(trans, rxq); + rxq->need_update = false; + spin_unlock(&rxq->lock); + } } /* @@ -232,10 +231,8 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) * also updates the memory address in the firmware to reference the new * target buffer. */ -static void iwl_pcie_rxq_restock(struct iwl_trans *trans) +static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; /* @@ -272,7 +269,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans) * Increment device's write pointer in multiples of 8. */ if (rxq->write_actual != (rxq->write & ~0x7)) { spin_lock(&rxq->lock); - iwl_pcie_rxq_inc_wr_ptr(trans); + iwl_pcie_rxq_inc_wr_ptr(trans, rxq); spin_unlock(&rxq->lock); } } @@ -285,13 +282,9 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, gfp_t priority) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct page *page; gfp_t gfp_mask = priority; - if (rxq->free_count > RX_LOW_WATERMARK) - gfp_mask |= __GFP_NOWARN; - if (trans_pcie->rx_page_order > 0) gfp_mask |= __GFP_COMP; @@ -301,16 +294,13 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, if (net_ratelimit()) IWL_DEBUG_INFO(trans, "alloc_pages failed, order: %d\n", trans_pcie->rx_page_order); - /* Issue an error if the hardware has consumed more than half - * of its free buffer list and we don't have enough - * pre-allocated buffers. + /* + * Issue an error if we don't have enough pre-allocated + * buffers. ` */ - if (rxq->free_count <= RX_LOW_WATERMARK && - iwl_rxq_space(rxq) > (RX_QUEUE_SIZE / 2) && - net_ratelimit()) + if (!(gfp_mask & __GFP_NOWARN) && net_ratelimit()) IWL_CRIT(trans, - "Failed to alloc_pages with GFP_KERNEL. Only %u free buffers remaining.\n", - rxq->free_count); + "Failed to alloc_pages\n"); return NULL; } return page; @@ -325,10 +315,10 @@ static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans, * iwl_pcie_rxq_restock. The latter function will update the HW to use the newly * allocated buffers. */ -static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) +static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, + struct iwl_rxq *rxq) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rx_mem_buffer *rxb; struct page *page; @@ -386,40 +376,23 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority) } } -static void iwl_pcie_rxq_free_rbs(struct iwl_trans *trans) +static void iwl_pcie_free_rbs_pool(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; int i; - lockdep_assert_held(&rxq->lock); - for (i = 0; i < RX_QUEUE_SIZE; i++) { - if (!rxq->pool[i].page) + if (!trans_pcie->rx_pool[i].page) continue; - dma_unmap_page(trans->dev, rxq->pool[i].page_dma, + dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - __free_pages(rxq->pool[i].page, trans_pcie->rx_page_order); - rxq->pool[i].page = NULL; + __free_pages(trans_pcie->rx_pool[i].page, + trans_pcie->rx_page_order); + trans_pcie->rx_pool[i].page = NULL; } } -/* - * iwl_pcie_rx_replenish - Move all used buffers from rx_used to rx_free - * - * When moving to rx_free an page is allocated for the slot. - * - * Also restock the Rx queue via iwl_pcie_rxq_restock. - * This is called only during initialization - */ -static void iwl_pcie_rx_replenish(struct iwl_trans *trans) -{ - iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL); - - iwl_pcie_rxq_restock(trans); -} - /* * iwl_pcie_rx_allocator - Allocates pages in the background for RX queues * @@ -444,6 +417,11 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) while (pending) { int i; struct list_head local_allocated; + gfp_t gfp_mask = GFP_KERNEL; + + /* Do not post a warning if there are only a few requests */ + if (pending < RX_PENDING_WATERMARK) + gfp_mask |= __GFP_NOWARN; INIT_LIST_HEAD(&local_allocated); @@ -463,7 +441,7 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) BUG_ON(rxb->page); /* Alloc a new receive buffer */ - page = iwl_pcie_rx_alloc_page(trans, GFP_KERNEL); + page = iwl_pcie_rx_alloc_page(trans, gfp_mask); if (!page) continue; rxb->page = page; @@ -561,38 +539,60 @@ static void iwl_pcie_rx_allocator_work(struct work_struct *data) static int iwl_pcie_rx_alloc(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; struct device *dev = trans->dev; + int i; + + if (WARN_ON(trans_pcie->rxq)) + return -EINVAL; - memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq)); + trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq), + GFP_KERNEL); + if (!trans_pcie->rxq) + return -EINVAL; - spin_lock_init(&rxq->lock); spin_lock_init(&rba->lock); - if (WARN_ON(rxq->bd || rxq->rb_stts)) - return -EINVAL; + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - /* Allocate the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = dma_zalloc_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + spin_lock_init(&rxq->lock); + /* + * Allocate the circular buffer of Read Buffer Descriptors + * (RBDs) + */ + rxq->bd = dma_zalloc_coherent(dev, + sizeof(__le32) * RX_QUEUE_SIZE, &rxq->bd_dma, GFP_KERNEL); - if (!rxq->bd) - goto err_bd; + if (!rxq->bd) + goto err; - /*Allocate the driver's pointer to receive buffer status */ - rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), - &rxq->rb_stts_dma, GFP_KERNEL); - if (!rxq->rb_stts) - goto err_rb_stts; + /*Allocate the driver's pointer to receive buffer status */ + rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), + &rxq->rb_stts_dma, + GFP_KERNEL); + if (!rxq->rb_stts) + goto err; + } return 0; -err_rb_stts: - dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, - rxq->bd, rxq->bd_dma); - rxq->bd_dma = 0; - rxq->bd = NULL; -err_bd: +err: + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + + if (rxq->bd) + dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + rxq->bd_dma = 0; + rxq->bd = NULL; + + if (rxq->rb_stts) + dma_free_coherent(trans->dev, + sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + } + kfree(trans_pcie->rxq); return -ENOMEM; } @@ -661,17 +661,12 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) { - int i; - lockdep_assert_held(&rxq->lock); INIT_LIST_HEAD(&rxq->rx_free); INIT_LIST_HEAD(&rxq->rx_used); rxq->free_count = 0; rxq->used_count = 0; - - for (i = 0; i < RX_QUEUE_SIZE; i++) - list_add(&rxq->pool[i].list, &rxq->rx_used); } static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba) @@ -709,15 +704,16 @@ static void iwl_pcie_rx_free_rba(struct iwl_trans *trans) int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rxq *def_rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; int i, err; - if (!rxq->bd) { + if (!trans_pcie->rxq) { err = iwl_pcie_rx_alloc(trans); if (err) return err; } + def_rxq = trans_pcie->rxq; if (!rba->alloc_wq) rba->alloc_wq = alloc_workqueue("rb_allocator", WQ_HIGHPRI | WQ_UNBOUND, 1); @@ -731,29 +727,42 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) iwl_pcie_rx_init_rba(rba); spin_unlock(&rba->lock); - spin_lock(&rxq->lock); - /* free all first - we might be reconfigured for a different size */ - iwl_pcie_rxq_free_rbs(trans); - iwl_pcie_rx_init_rxb_lists(rxq); + iwl_pcie_free_rbs_pool(trans); for (i = 0; i < RX_QUEUE_SIZE; i++) - rxq->queue[i] = NULL; + def_rxq->queue[i] = NULL; - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->write_actual = 0; - memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); - spin_unlock(&rxq->lock); + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; - iwl_pcie_rx_replenish(trans); + spin_lock(&rxq->lock); + /* + * Set read write pointer to reflect that we have processed + * and used all buffers, but have not restocked the Rx queue + * with fresh buffers + */ + rxq->read = 0; + rxq->write = 0; + rxq->write_actual = 0; + memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts)); - iwl_pcie_rx_hw_init(trans, rxq); + iwl_pcie_rx_init_rxb_lists(rxq); - spin_lock(&rxq->lock); - iwl_pcie_rxq_inc_wr_ptr(trans); - spin_unlock(&rxq->lock); + spin_unlock(&rxq->lock); + } + + /* move the entire pool to the default queue ownership */ + for (i = 0; i < RX_QUEUE_SIZE; i++) + list_add(&trans_pcie->rx_pool[i].list, &def_rxq->rx_used); + + iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); + iwl_pcie_rxq_restock(trans, def_rxq); + iwl_pcie_rx_hw_init(trans, def_rxq); + + spin_lock(&def_rxq->lock); + iwl_pcie_rxq_inc_wr_ptr(trans, def_rxq); + spin_unlock(&def_rxq->lock); return 0; } @@ -761,12 +770,14 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; + int i; - /*if rxq->bd is NULL, it means that nothing has been allocated, - * exit now */ - if (!rxq->bd) { + /* + * if rxq is NULL, it means that nothing has been allocated, + * exit now + */ + if (!trans_pcie->rxq) { IWL_DEBUG_INFO(trans, "Free NULL rx context\n"); return; } @@ -781,23 +792,28 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) iwl_pcie_rx_free_rba(trans); spin_unlock(&rba->lock); - spin_lock(&rxq->lock); - iwl_pcie_rxq_free_rbs(trans); - spin_unlock(&rxq->lock); - - dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE, - rxq->bd, rxq->bd_dma); - rxq->bd_dma = 0; - rxq->bd = NULL; + iwl_pcie_free_rbs_pool(trans); + + for (i = 0; i < trans->num_rx_queues; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + + if (rxq->bd) + dma_free_coherent(trans->dev, + sizeof(__le32) * RX_QUEUE_SIZE, + rxq->bd, rxq->bd_dma); + rxq->bd_dma = 0; + rxq->bd = NULL; + + if (rxq->rb_stts) + dma_free_coherent(trans->dev, + sizeof(struct iwl_rb_status), + rxq->rb_stts, rxq->rb_stts_dma); + else + IWL_DEBUG_INFO(trans, + "Free rxq->rb_stts which is NULL\n"); + } - if (rxq->rb_stts) - dma_free_coherent(trans->dev, - sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); - else - IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); - rxq->rb_stts_dma = 0; - rxq->rb_stts = NULL; + kfree(trans_pcie->rxq); } /* @@ -841,11 +857,11 @@ static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans, } static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, + struct iwl_rxq *rxq, struct iwl_rx_mem_buffer *rxb, bool emergency) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; struct iwl_txq *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; bool page_stolen = false; int max_len = PAGE_SIZE << trans_pcie->rx_page_order; @@ -975,7 +991,7 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, static void iwl_pcie_rx_handle(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; + struct iwl_rxq *rxq = &trans_pcie->rxq[0]; u32 r, i, j, count = 0; bool emergency = false; @@ -1000,7 +1016,7 @@ restart: rxq->queue[i] = NULL; IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d\n", r, i); - iwl_pcie_rx_handle_rb(trans, rxb, emergency); + iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency); i = (i + 1) & RX_QUEUE_MASK; @@ -1043,7 +1059,7 @@ restart: if (rxq->used_count < RX_QUEUE_SIZE / 3) emergency = false; spin_unlock(&rxq->lock); - iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC); + iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); spin_lock(&rxq->lock); } } @@ -1055,7 +1071,7 @@ restart: if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) { rxq->read = i; spin_unlock(&rxq->lock); - iwl_pcie_rxq_restock(trans); + iwl_pcie_rxq_restock(trans, rxq); goto restart; } } @@ -1077,7 +1093,7 @@ restart: * will be restocked by the next call of iwl_pcie_rxq_restock. */ if (unlikely(emergency && count)) - iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC); + iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); if (trans_pcie->napi.poll) napi_gro_flush(&trans_pcie->napi, false); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d60a467a983c..0302aede4fdf 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2001,29 +2001,48 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, { struct iwl_trans *trans = file->private_data; struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", - rxq->read); - pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", - rxq->write); - pos += scnprintf(buf + pos, bufsz - pos, "write_actual: %u\n", - rxq->write_actual); - pos += scnprintf(buf + pos, bufsz - pos, "need_update: %d\n", - rxq->need_update); - pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", - rxq->free_count); - if (rxq->rb_stts) { - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", - le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); - } else { - pos += scnprintf(buf + pos, bufsz - pos, - "closed_rb_num: Not Allocated\n"); + char *buf; + int pos = 0, i, ret; + size_t bufsz = sizeof(buf); + + bufsz = sizeof(char) * 121 * trans->num_rx_queues; + + if (!trans_pcie->rxq) + return -EAGAIN; + + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + for (i = 0; i < trans->num_rx_queues && pos < bufsz; i++) { + struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + + pos += scnprintf(buf + pos, bufsz - pos, "queue#: %2d\n", + i); + pos += scnprintf(buf + pos, bufsz - pos, "\tread: %u\n", + rxq->read); + pos += scnprintf(buf + pos, bufsz - pos, "\twrite: %u\n", + rxq->write); + pos += scnprintf(buf + pos, bufsz - pos, "\twrite_actual: %u\n", + rxq->write_actual); + pos += scnprintf(buf + pos, bufsz - pos, "\tneed_update: %2d\n", + rxq->need_update); + pos += scnprintf(buf + pos, bufsz - pos, "\tfree_count: %u\n", + rxq->free_count); + if (rxq->rb_stts) { + pos += scnprintf(buf + pos, bufsz - pos, + "\tclosed_rb_num: %u\n", + le16_to_cpu(rxq->rb_stts->closed_rb_num) & + 0x0FFF); + } else { + pos += scnprintf(buf + pos, bufsz - pos, + "\tclosed_rb_num: Not Allocated\n"); + } } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + + return ret; } static ssize_t iwl_dbgfs_interrupt_read(struct file *file, @@ -2188,7 +2207,8 @@ static u32 iwl_trans_pcie_dump_rbs(struct iwl_trans *trans, { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int max_len = PAGE_SIZE << trans_pcie->rx_page_order; - struct iwl_rxq *rxq = &trans_pcie->rxq; + /* Dump RBs is supported only for pre-9000 devices (1 queue) */ + struct iwl_rxq *rxq = &trans_pcie->rxq[0]; u32 i, r, j, rb_len = 0; spin_lock(&rxq->lock); @@ -2438,11 +2458,12 @@ static struct iwl_trans_dump_data len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND); if (dump_rbs) { + /* Dump RBs is supported only for pre-9000 devices (1 queue) */ + struct iwl_rxq *rxq = &trans_pcie->rxq[0]; /* RBs */ - num_rbs = le16_to_cpu(ACCESS_ONCE( - trans_pcie->rxq.rb_stts->closed_rb_num)) + num_rbs = le16_to_cpu(ACCESS_ONCE(rxq->rb_stts->closed_rb_num)) & 0x0FFF; - num_rbs = (num_rbs - trans_pcie->rxq.read) & RX_QUEUE_MASK; + num_rbs = (num_rbs - rxq->read) & RX_QUEUE_MASK; len += num_rbs * (sizeof(*data) + sizeof(struct iwl_fw_error_dump_rb) + (PAGE_SIZE << trans_pcie->rx_page_order)); -- cgit From 96a6497bc3ed1c19d877e5f4f95f2cfa27448abe Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 23 Dec 2015 15:10:03 +0200 Subject: iwlwifi: pcie: add 9000 series multi queue rx DMA support The 9000 series introduces several changes in the device DMA operation. As the device now supports multi-queue rx, several DMA channels should be configured. The flows of providing the device with the allocated RBDs now changes as well - the device maintains a separate table of used and free table. The hardware may use the free table to feed RBDs to any queue. This requires maintaing a shared table to map returned RBDs to the original RXB - for that purpose the VID is introduced - an internal identifier of the RB placed in the lower 12 bits and returned by HW in the used data. Another change is the support of 64 bit DMA address. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-9000.c | 3 +- drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 + drivers/net/wireless/intel/iwlwifi/iwl-fh.h | 77 ++++++ drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 28 ++- drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 277 ++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 15 +- 6 files changed, 322 insertions(+), 80 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c index ecbf4822cd69..4b93404f46a7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-9000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-9000.c @@ -138,7 +138,8 @@ static const struct iwl_tt_params iwl9000_tt_params = { .smem_offset = IWL9000_SMEM_OFFSET, \ .smem_len = IWL9000_SMEM_LEN, \ .thermal_params = &iwl9000_tt_params, \ - .apmg_not_supported = true + .apmg_not_supported = true, \ + .mq_rx_supported = true const struct iwl_cfg iwl9260_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 9260", diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index f99048135fb9..dad5570d6cc8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -311,6 +311,7 @@ struct iwl_pwr_tx_backoff { * @dccm2_len: length of the second DCCM * @smem_offset: offset from which the SMEM begins * @smem_len: the length of SMEM + * @mq_rx_supported: multi-queue rx support * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -362,6 +363,7 @@ struct iwl_cfg { const u32 smem_len; const struct iwl_tt_params *thermal_params; bool apmg_not_supported; + bool mq_rx_supported; }; /* diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index 5cc6be927eab..4ab6682ea53e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * 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 @@ -31,6 +32,7 @@ * BSD LICENSE * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -312,6 +314,77 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 #define FH_MEM_TB_MAX_LENGTH (0x00020000) +/* 9000 rx series registers */ + +#define RFH_Q0_FRBDCB_BA_LSB 0xA08000 /* 64 bit address */ +#define RFH_Q_FRBDCB_BA_LSB(q) (RFH_Q0_FRBDCB_BA_LSB + (q) * 8) +/* Write index table */ +#define RFH_Q0_FRBDCB_WIDX 0xA08080 +#define RFH_Q_FRBDCB_WIDX(q) (RFH_Q0_FRBDCB_WIDX + (q) * 4) +/* Read index table */ +#define RFH_Q0_FRBDCB_RIDX 0xA080C0 +#define RFH_Q_FRBDCB_RIDX(q) (RFH_Q0_FRBDCB_RIDX + (q) * 4) +/* Used list table */ +#define RFH_Q0_URBDCB_BA_LSB 0xA08100 /* 64 bit address */ +#define RFH_Q_URBDCB_BA_LSB(q) (RFH_Q0_URBDCB_BA_LSB + (q) * 8) +/* Write index table */ +#define RFH_Q0_URBDCB_WIDX 0xA08180 +#define RFH_Q_URBDCB_WIDX(q) (RFH_Q0_URBDCB_WIDX + (q) * 4) +#define RFH_Q0_URBDCB_VAID 0xA081C0 +#define RFH_Q_URBDCB_VAID(q) (RFH_Q0_URBDCB_VAID + (q) * 4) +/* stts */ +#define RFH_Q0_URBD_STTS_WPTR_LSB 0xA08200 /*64 bits address */ +#define RFH_Q_URBD_STTS_WPTR_LSB(q) (RFH_Q0_URBD_STTS_WPTR_LSB + (q) * 8) + +#define RFH_Q0_ORB_WPTR_LSB 0xA08280 +#define RFH_Q_ORB_WPTR_LSB(q) (RFH_Q0_ORB_WPTR_LSB + (q) * 8) +#define RFH_RBDBUF_RBD0_LSB 0xA08300 +#define RFH_RBDBUF_RBD_LSB(q) (RFH_RBDBUF_RBD0_LSB + (q) * 8) + +/* DMA configuration */ +#define RFH_RXF_DMA_CFG 0xA09820 +/* RB size */ +#define RFH_RXF_DMA_RB_SIZE_MASK (0x000F0000) /* bits 16-19 */ +#define RFH_RXF_DMA_RB_SIZE_POS 16 +#define RFH_RXF_DMA_RB_SIZE_1K (0x1 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_2K (0x2 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_4K (0x4 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_8K (0x8 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_12K (0x9 << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_16K (0xA << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_20K (0xB << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_24K (0xC << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_28K (0xD << RFH_RXF_DMA_RB_SIZE_POS) +#define RFH_RXF_DMA_RB_SIZE_32K (0xE << RFH_RXF_DMA_RB_SIZE_POS) +/* RB Circular Buffer size:defines the table sizes in RBD units */ +#define RFH_RXF_DMA_RBDCB_SIZE_MASK (0x00F00000) /* bits 20-23 */ +#define RFH_RXF_DMA_RBDCB_SIZE_POS 20 +#define RFH_RXF_DMA_RBDCB_SIZE_8 (0x3 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_16 (0x4 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_32 (0x5 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_64 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_128 (0x7 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_256 (0x8 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_512 (0x9 << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_1024 (0xA << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_RBDCB_SIZE_2048 (0xB << RFH_RXF_DMA_RBDCB_SIZE_POS) +#define RFH_RXF_DMA_MIN_RB_SIZE_MASK (0x03000000) /* bit 24-25 */ +#define RFH_RXF_DMA_MIN_RB_SIZE_POS 24 +#define RFH_RXF_DMA_MIN_RB_4_8 (3 << RFH_RXF_DMA_MIN_RB_SIZE_POS) +#define RFH_RXF_DMA_SINGLE_FRAME_MASK (0x20000000) /* bit 29 */ +#define RFH_DMA_EN_MASK (0xC0000000) /* bits 30-31*/ +#define RFH_DMA_EN_ENABLE_VAL BIT(31) + +#define RFH_RXF_RXQ_ACTIVE 0xA0980C + +#define RFH_GEN_CFG 0xA09800 +#define RFH_GEN_CFG_DEFAULT_RXQ_NUM_MASK 0xF00 +#define RFH_GEN_CFG_SERVICE_DMA_SNOOP BIT(0) +#define RFH_GEN_CFG_RFH_DMA_SNOOP BIT(1) +#define DEFAULT_RXQ_NUM 8 + +/* end of 9000 rx series registers */ + /* TFDB Area - TFDs buffer table */ #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) #define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900) @@ -434,6 +507,10 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl) */ #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) +#define MQ_RX_TABLE_SIZE 512 +#define MQ_RX_TABLE_MASK (MQ_RX_TABLE_SIZE - 1) +#define MQ_RX_POOL_SIZE MQ_RX_TABLE_MASK + #define RX_QUEUE_SIZE 256 #define RX_QUEUE_MASK 255 #define RX_QUEUE_SIZE_LOG 8 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 11ad87fca67a..bdda7028c393 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -56,7 +56,6 @@ #define RX_NUM_QUEUES 1 #define RX_POST_REQ_ALLOC 2 #define RX_CLAIM_REQ_ALLOC 8 -#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES) #define RX_PENDING_WATERMARK 16 struct iwl_host_cmd; @@ -64,9 +63,16 @@ struct iwl_host_cmd; /*This file includes the declaration that are internal to the * trans_pcie layer */ +/** + * struct iwl_rx_mem_buffer + * @page_dma: bus address of rxb page + * @page: driver's pointer to the rxb page + * @vid: index of this rxb in the global table + */ struct iwl_rx_mem_buffer { dma_addr_t page_dma; struct page *page; + u16 vid; struct list_head list; }; @@ -90,8 +96,12 @@ struct isr_statistics { /** * struct iwl_rxq - Rx queue - * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) + * @id: queue index + * @bd: driver's pointer to buffer of receive buffer descriptors (rbd). + * Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices. * @bd_dma: bus address of buffer of receive buffer descriptors (rbd) + * @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd) + * @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd) * @read: Shared index to newest available Rx buffer * @write: Shared index to oldest written Rx packet * @free_count: Number of pre-allocated buffers in rx_free @@ -103,18 +113,22 @@ struct isr_statistics { * @rb_stts: driver's pointer to receive buffer status * @rb_stts_dma: bus address of receive buffer status * @lock: - * @queue: actual rx queue + * @queue: actual rx queue. Not used for multi-rx queue. * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ struct iwl_rxq { - __le32 *bd; + int id; + void *bd; dma_addr_t bd_dma; + __le32 *used_bd; + dma_addr_t used_bd_dma; u32 read; u32 write; u32 free_count; u32 used_count; u32 write_actual; + u32 queue_size; struct list_head rx_free; struct list_head rx_used; bool need_update; @@ -126,7 +140,6 @@ struct iwl_rxq { /** * struct iwl_rb_allocator - Rx allocator - * @pool: initial pool of allocator * @req_pending: number of requests the allcator had not processed yet * @req_ready: number of requests honored and ready for claiming * @rbd_allocated: RBDs with pages allocated and ready to be handled to @@ -138,7 +151,6 @@ struct iwl_rxq { * @rx_alloc: work struct for background calls */ struct iwl_rb_allocator { - struct iwl_rx_mem_buffer pool[RX_POOL_SIZE]; atomic_t req_pending; atomic_t req_ready; struct list_head rbd_allocated; @@ -297,6 +309,7 @@ struct iwl_tso_hdr_page { * struct iwl_trans_pcie - PCIe transport specific data * @rxq: all the RX queue data * @rx_pool: initial pool of iwl_rx_mem_buffer for all the queues + * @global_table: table mapping received VID from hw to rxb * @rba: allocator for RX replenishing * @drv - pointer to iwl_drv * @trans: pointer to the generic transport area @@ -324,7 +337,8 @@ struct iwl_tso_hdr_page { */ struct iwl_trans_pcie { struct iwl_rxq *rxq; - struct iwl_rx_mem_buffer rx_pool[RX_QUEUE_SIZE]; + struct iwl_rx_mem_buffer rx_pool[MQ_RX_POOL_SIZE]; + struct iwl_rx_mem_buffer *global_table[MQ_RX_TABLE_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 f557f3dc4db8..a385f3cddb5d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -140,8 +140,8 @@ */ static int iwl_rxq_space(const struct iwl_rxq *rxq) { - /* Make sure RX_QUEUE_SIZE is a power of 2 */ - BUILD_BUG_ON(RX_QUEUE_SIZE & (RX_QUEUE_SIZE - 1)); + /* Make sure rx queue size is a power of 2 */ + WARN_ON(rxq->queue_size & (rxq->queue_size - 1)); /* * There can be up to (RX_QUEUE_SIZE - 1) free slots, to avoid ambiguity @@ -149,7 +149,7 @@ static int iwl_rxq_space(const struct iwl_rxq *rxq) * The following is equivalent to modulo by RX_QUEUE_SIZE and is well * defined for negative dividends. */ - return (rxq->read - rxq->write - 1) & (RX_QUEUE_SIZE - 1); + return (rxq->read - rxq->write - 1) & (rxq->queue_size - 1); } /* @@ -160,6 +160,12 @@ static inline __le32 iwl_pcie_dma_addr2rbd_ptr(dma_addr_t dma_addr) return cpu_to_le32((u32)(dma_addr >> 8)); } +static void iwl_pcie_write_prph_64(struct iwl_trans *trans, u64 ofs, u64 val) +{ + iwl_write_prph(trans, ofs, val & 0xffffffff); + iwl_write_prph(trans, ofs + 4, val >> 32); +} + /* * iwl_pcie_rx_stop - stops the Rx DMA */ @@ -200,7 +206,11 @@ static void iwl_pcie_rxq_inc_wr_ptr(struct iwl_trans *trans, } rxq->write_actual = round_down(rxq->write, 8); - iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, rxq->write_actual); + 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); } static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) @@ -220,6 +230,51 @@ static void iwl_pcie_rxq_check_wrptr(struct iwl_trans *trans) } } +static void iwl_pcie_rxq_mq_restock(struct iwl_trans *trans, + struct iwl_rxq *rxq) +{ + struct iwl_rx_mem_buffer *rxb; + + /* + * If the device isn't enabled - no need to try to add buffers... + * This can happen when we stop the device and still have an interrupt + * pending. We stop the APM before we sync the interrupts because we + * have to (see comment there). On the other hand, since the APM is + * stopped, we cannot access the HW (in particular not prph). + * So don't try to restock if the APM has been already stopped. + */ + if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status)) + return; + + spin_lock(&rxq->lock); + while (rxq->free_count) { + __le64 *bd = (__le64 *)rxq->bd; + + /* Get next free Rx buffer, remove from free list */ + rxb = list_first_entry(&rxq->rx_free, struct iwl_rx_mem_buffer, + list); + list_del(&rxb->list); + + /* 12 first bits are expected to be empty */ + WARN_ON(rxb->page_dma & DMA_BIT_MASK(12)); + /* Point to Rx buffer via next RBD in circular buffer */ + bd[rxq->write] = cpu_to_le64(rxb->page_dma | rxb->vid); + rxq->write = (rxq->write + 1) & MQ_RX_TABLE_MASK; + rxq->free_count--; + } + spin_unlock(&rxq->lock); + + /* + * If we've added more space for the firmware to place data, tell it. + * Increment device's write pointer in multiples of 8. + */ + if (rxq->write_actual != (rxq->write & ~0x7)) { + spin_lock(&rxq->lock); + iwl_pcie_rxq_inc_wr_ptr(trans, rxq); + spin_unlock(&rxq->lock); + } +} + /* * iwl_pcie_rxq_restock - refill RX queue from pre-allocated pool * @@ -248,6 +303,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) spin_lock(&rxq->lock); while ((iwl_rxq_space(rxq) > 0) && (rxq->free_count)) { + __le32 *bd = (__le32 *)rxq->bd; /* The overwritten rxb must be a used one */ rxb = rxq->queue[rxq->write]; BUG_ON(rxb && rxb->page); @@ -258,7 +314,7 @@ static void iwl_pcie_rxq_restock(struct iwl_trans *trans, struct iwl_rxq *rxq) list_del(&rxb->list); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma); + bd[rxq->write] = iwl_pcie_dma_addr2rbd_ptr(rxb->page_dma); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -362,10 +418,6 @@ static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority, __free_pages(page, trans_pcie->rx_page_order); return; } - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); spin_lock(&rxq->lock); @@ -381,7 +433,7 @@ static void iwl_pcie_free_rbs_pool(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; - for (i = 0; i < RX_QUEUE_SIZE; i++) { + for (i = 0; i < MQ_RX_POOL_SIZE; i++) { if (!trans_pcie->rx_pool[i].page) continue; dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma, @@ -455,10 +507,6 @@ static void iwl_pcie_rx_allocator(struct iwl_trans *trans) __free_pages(page, trans_pcie->rx_page_order); continue; } - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); /* move the allocated entry to the out list */ list_move(&rxb->list, &local_allocated); @@ -542,6 +590,8 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) struct iwl_rb_allocator *rba = &trans_pcie->rba; struct device *dev = trans->dev; int i; + int free_size = trans->cfg->mq_rx_supported ? sizeof(__le64) : + sizeof(__le32); if (WARN_ON(trans_pcie->rxq)) return -EINVAL; @@ -557,16 +607,30 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans) struct iwl_rxq *rxq = &trans_pcie->rxq[i]; spin_lock_init(&rxq->lock); + if (trans->cfg->mq_rx_supported) + rxq->queue_size = MQ_RX_TABLE_SIZE; + else + rxq->queue_size = RX_QUEUE_SIZE; + /* * Allocate the circular buffer of Read Buffer Descriptors * (RBDs) */ rxq->bd = dma_zalloc_coherent(dev, - sizeof(__le32) * RX_QUEUE_SIZE, - &rxq->bd_dma, GFP_KERNEL); + free_size * rxq->queue_size, + &rxq->bd_dma, GFP_KERNEL); if (!rxq->bd) goto err; + if (trans->cfg->mq_rx_supported) { + rxq->used_bd = dma_zalloc_coherent(dev, + sizeof(__le32) * + rxq->queue_size, + &rxq->used_bd_dma, + GFP_KERNEL); + if (!rxq->used_bd) + goto err; + } /*Allocate the driver's pointer to receive buffer status */ rxq->rb_stts = dma_zalloc_coherent(dev, sizeof(*rxq->rb_stts), @@ -582,7 +646,7 @@ err: struct iwl_rxq *rxq = &trans_pcie->rxq[i]; if (rxq->bd) - dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE, + dma_free_coherent(dev, free_size * rxq->queue_size, rxq->bd, rxq->bd_dma); rxq->bd_dma = 0; rxq->bd = NULL; @@ -591,8 +655,15 @@ err: dma_free_coherent(trans->dev, sizeof(struct iwl_rb_status), rxq->rb_stts, rxq->rb_stts_dma); + + if (rxq->used_bd) + dma_free_coherent(dev, sizeof(__le32) * rxq->queue_size, + rxq->used_bd, rxq->used_bd_dma); + rxq->used_bd_dma = 0; + rxq->used_bd = NULL; } kfree(trans_pcie->rxq); + return -ENOMEM; } @@ -659,46 +730,82 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } -static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) +static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) { - lockdep_assert_held(&rxq->lock); + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + u32 rb_size, enabled = 0; + int i; - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - rxq->free_count = 0; - rxq->used_count = 0; -} + switch (trans_pcie->rx_buf_size) { + case IWL_AMSDU_4K: + rb_size = RFH_RXF_DMA_RB_SIZE_4K; + break; + case IWL_AMSDU_8K: + rb_size = RFH_RXF_DMA_RB_SIZE_8K; + break; + case IWL_AMSDU_12K: + rb_size = RFH_RXF_DMA_RB_SIZE_12K; + break; + default: + WARN_ON(1); + rb_size = RFH_RXF_DMA_RB_SIZE_4K; + } -static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba) -{ - int i; + /* Stop Rx DMA */ + iwl_write_prph(trans, RFH_RXF_DMA_CFG, 0); + /* disable free amd used rx queue operation */ + iwl_write_prph(trans, RFH_RXF_RXQ_ACTIVE, 0); - lockdep_assert_held(&rba->lock); + for (i = 0; i < trans->num_rx_queues; i++) { + /* Tell device where to find RBD free table in DRAM */ + iwl_pcie_write_prph_64(trans, RFH_Q_FRBDCB_BA_LSB(i), + (u64)(rxq->bd_dma)); + /* Tell device where to find RBD used table in DRAM */ + iwl_pcie_write_prph_64(trans, RFH_Q_URBDCB_BA_LSB(i), + (u64)(rxq->used_bd_dma)); + /* Tell device where in DRAM to update its Rx status */ + iwl_pcie_write_prph_64(trans, RFH_Q_URBD_STTS_WPTR_LSB(i), + rxq->rb_stts_dma); + /* Reset device indice tables */ + iwl_write_prph(trans, RFH_Q_FRBDCB_WIDX(i), 0); + iwl_write_prph(trans, RFH_Q_FRBDCB_RIDX(i), 0); + iwl_write_prph(trans, RFH_Q_URBDCB_WIDX(i), 0); + + enabled |= BIT(i) | BIT(i + 16); + } - INIT_LIST_HEAD(&rba->rbd_allocated); - INIT_LIST_HEAD(&rba->rbd_empty); + /* restock default queue */ + iwl_pcie_rxq_mq_restock(trans, &trans_pcie->rxq[0]); - for (i = 0; i < RX_POOL_SIZE; i++) - list_add(&rba->pool[i].list, &rba->rbd_empty); + /* + * Enable Rx DMA + * Single frame mode + * Rx buffer size 4 or 8k or 12k + * Min RB size 4 or 8 + * 512 RBDs + */ + iwl_write_prph(trans, RFH_RXF_DMA_CFG, + RFH_DMA_EN_ENABLE_VAL | + rb_size | RFH_RXF_DMA_SINGLE_FRAME_MASK | + RFH_RXF_DMA_MIN_RB_4_8 | + RFH_RXF_DMA_RBDCB_SIZE_512); + + iwl_write_prph(trans, RFH_GEN_CFG, RFH_GEN_CFG_RFH_DMA_SNOOP | + RFH_GEN_CFG_SERVICE_DMA_SNOOP); + iwl_write_prph(trans, RFH_RXF_RXQ_ACTIVE, enabled); + + /* Set interrupt coalescing timer to default (2048 usecs) */ + iwl_write8(trans, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); } -static void iwl_pcie_rx_free_rba(struct iwl_trans *trans) +static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) { - struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i; - - lockdep_assert_held(&rba->lock); + lockdep_assert_held(&rxq->lock); - for (i = 0; i < RX_POOL_SIZE; i++) { - if (!rba->pool[i].page) - continue; - dma_unmap_page(trans->dev, rba->pool[i].page_dma, - PAGE_SIZE << trans_pcie->rx_page_order, - DMA_FROM_DEVICE); - __free_pages(rba->pool[i].page, trans_pcie->rx_page_order); - rba->pool[i].page = NULL; - } + INIT_LIST_HEAD(&rxq->rx_free); + INIT_LIST_HEAD(&rxq->rx_used); + rxq->free_count = 0; + rxq->used_count = 0; } int iwl_pcie_rx_init(struct iwl_trans *trans) @@ -706,7 +813,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rxq *def_rxq; struct iwl_rb_allocator *rba = &trans_pcie->rba; - int i, err; + int i, err, num_rbds, allocator_pool_size; if (!trans_pcie->rxq) { err = iwl_pcie_rx_alloc(trans); @@ -722,9 +829,8 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) spin_lock(&rba->lock); atomic_set(&rba->req_pending, 0); atomic_set(&rba->req_ready, 0); - /* free all first - we might be reconfigured for a different size */ - iwl_pcie_rx_free_rba(trans); - iwl_pcie_rx_init_rba(rba); + INIT_LIST_HEAD(&rba->rbd_allocated); + INIT_LIST_HEAD(&rba->rbd_empty); spin_unlock(&rba->lock); /* free all first - we might be reconfigured for a different size */ @@ -736,6 +842,8 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) for (i = 0; i < trans->num_rx_queues; i++) { struct iwl_rxq *rxq = &trans_pcie->rxq[i]; + rxq->id = i; + spin_lock(&rxq->lock); /* * Set read write pointer to reflect that we have processed @@ -752,13 +860,29 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) spin_unlock(&rxq->lock); } - /* move the entire pool to the default queue ownership */ - for (i = 0; i < RX_QUEUE_SIZE; i++) - list_add(&trans_pcie->rx_pool[i].list, &def_rxq->rx_used); + /* move the pool to the default queue and allocator ownerships */ + num_rbds = trans->cfg->mq_rx_supported ? + MQ_RX_POOL_SIZE : RX_QUEUE_SIZE; + allocator_pool_size = trans->num_rx_queues * + (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC); + for (i = 0; i < num_rbds; i++) { + struct iwl_rx_mem_buffer *rxb = &trans_pcie->rx_pool[i]; + + if (i < allocator_pool_size) + list_add(&rxb->list, &rba->rbd_empty); + else + list_add(&rxb->list, &def_rxq->rx_used); + trans_pcie->global_table[i] = rxb; + rxb->vid = (u16)i; + } iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); - iwl_pcie_rxq_restock(trans, def_rxq); - iwl_pcie_rx_hw_init(trans, def_rxq); + if (trans->cfg->mq_rx_supported) { + iwl_pcie_rx_mq_hw_init(trans, def_rxq); + } else { + iwl_pcie_rxq_restock(trans, def_rxq); + iwl_pcie_rx_hw_init(trans, def_rxq); + } spin_lock(&def_rxq->lock); iwl_pcie_rxq_inc_wr_ptr(trans, def_rxq); @@ -771,6 +895,8 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rb_allocator *rba = &trans_pcie->rba; + int free_size = trans->cfg->mq_rx_supported ? sizeof(__le64) : + sizeof(__le32); int i; /* @@ -788,10 +914,6 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) rba->alloc_wq = NULL; } - spin_lock(&rba->lock); - iwl_pcie_rx_free_rba(trans); - spin_unlock(&rba->lock); - iwl_pcie_free_rbs_pool(trans); for (i = 0; i < trans->num_rx_queues; i++) { @@ -799,7 +921,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) if (rxq->bd) dma_free_coherent(trans->dev, - sizeof(__le32) * RX_QUEUE_SIZE, + free_size * rxq->queue_size, rxq->bd, rxq->bd_dma); rxq->bd_dma = 0; rxq->bd = NULL; @@ -811,8 +933,14 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) else IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n"); - } + if (rxq->used_bd) + dma_free_coherent(trans->dev, + sizeof(__le32) * rxq->queue_size, + rxq->used_bd, rxq->used_bd_dma); + rxq->used_bd_dma = 0; + rxq->used_bd = NULL; + } kfree(trans_pcie->rxq); } @@ -1009,16 +1137,26 @@ restart: while (i != r) { struct iwl_rx_mem_buffer *rxb; - if (unlikely(rxq->used_count == RX_QUEUE_SIZE / 2)) + if (unlikely(rxq->used_count == rxq->queue_size / 2)) emergency = true; - rxb = rxq->queue[i]; - rxq->queue[i] = NULL; + if (trans->cfg->mq_rx_supported) { + /* + * used_bd is a 32 bit but only 12 are used to retrieve + * the vid + */ + u16 vid = (u16)le32_to_cpu(rxq->used_bd[i]); + + rxb = trans_pcie->global_table[vid]; + } else { + rxb = rxq->queue[i]; + rxq->queue[i] = NULL; + } IWL_DEBUG_RX(trans, "rxbuf: HW = %d, SW = %d\n", r, i); iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency); - i = (i + 1) & RX_QUEUE_MASK; + i = (i + 1) & (rxq->queue_size - 1); /* If we have RX_CLAIM_REQ_ALLOC released rx buffers - * try to claim the pre-allocated buffers from the allocator */ @@ -1056,7 +1194,7 @@ restart: count++; if (count == 8) { count = 0; - if (rxq->used_count < RX_QUEUE_SIZE / 3) + if (rxq->used_count < rxq->queue_size / 3) emergency = false; spin_unlock(&rxq->lock); iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); @@ -1071,7 +1209,10 @@ restart: if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) { rxq->read = i; spin_unlock(&rxq->lock); - iwl_pcie_rxq_restock(trans, rxq); + if (trans->cfg->mq_rx_supported) + iwl_pcie_rxq_mq_restock(trans, rxq); + else + iwl_pcie_rxq_restock(trans, rxq); goto restart; } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 0302aede4fdf..35810965221c 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2403,7 +2403,8 @@ static struct iwl_trans_dump_data u32 len, num_rbs; u32 monitor_len; int i, ptr; - bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status); + bool dump_rbs = test_bit(STATUS_FW_ERROR, &trans->status) && + !trans->cfg->mq_rx_supported; /* transport dump header */ len = sizeof(*dump_data); @@ -2562,7 +2563,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans_pcie *trans_pcie; struct iwl_trans *trans; u16 pci_cmd; - int ret; + int ret, addr_size; trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, cfg, &trans_ops_pcie, 0); @@ -2600,11 +2601,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, PCIE_LINK_STATE_CLKPM); } + if (cfg->mq_rx_supported) + addr_size = 64; + else + addr_size = 36; + pci_set_master(pdev); - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(addr_size)); if (!ret) - ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); + ret = pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(addr_size)); if (ret) { ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!ret) -- cgit From b7765086b7c5a5be029a739c2caa161da51c2076 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 31 Jan 2016 09:33:26 -0800 Subject: x86/entry/64: Fix an IRQ state error on ptregs-using syscalls I messed up the IRQ state when jumping off the fast path due to invocation of a ptregs-using syscall. This bug shouldn't have had any impact yet, but it would have caused problems with subsequent context tracking cleanups. Reported-and-tested-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: Thomas Gleixner Fixes: 1e423bff959e x86/entry/64: ("Migrate the 64-bit syscall slow path to C") Link: http://lkml.kernel.org/r/ab92cd365fb7b0a56869e920017790d96610fdca.1454261517.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 567aa522ac0a..9f7bb808035e 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -191,8 +191,8 @@ entry_SYSCALL_64_fastpath: /* * This call instruction is handled specially in stub_ptregs_64. - * It might end up jumping to the slow path. If it jumps, RAX is - * clobbered. + * It might end up jumping to the slow path. If it jumps, RAX + * and all argument registers are clobbered. */ call *sys_call_table(, %rax, 8) .Lentry_SYSCALL_64_after_fastpath_call: @@ -315,17 +315,24 @@ END(entry_SYSCALL_64) ENTRY(stub_ptregs_64) /* * Syscalls marked as needing ptregs land here. - * If we are on the fast path, we need to save the extra regs. - * If we are on the slow path, the extra regs are already saved. + * If we are on the fast path, we need to save the extra regs, + * which we achieve by trying again on the slow path. If we are on + * the slow path, the extra regs are already saved. * * RAX stores a pointer to the C function implementing the syscall. + * IRQs are on. */ cmpq $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp) jne 1f - /* Called from fast path -- pop return address and jump to slow path */ + /* + * Called from fast path -- disable IRQs again, pop return address + * and jump to slow path + */ + DISABLE_INTERRUPTS(CLBR_NONE) + TRACE_IRQS_OFF popq %rax - jmp entry_SYSCALL64_slow_path /* called from fast path */ + jmp entry_SYSCALL64_slow_path 1: /* Called from C */ -- cgit From eb2a54c3271cb6443ae93ec44a91687b60c559a3 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 31 Jan 2016 09:33:27 -0800 Subject: x86/entry/64: Fix fast-path syscall return register state I was fishing RIP (i.e. RCX) out of pt_regs->cx and RFLAGS (i.e. R11) out of pt_regs->r11. While it usually worked (pt_regs started out with CX == IP and R11 == FLAGS), it was very fragile. In particular, it broke sys_iopl() because sys_iopl() forgot to mark itself as using ptregs. Undo that part of the syscall rework. There was no compelling reason to do it this way. While I'm at it, load RCX and R11 before the other regs to be a little friendlier to the CPU, as they will be the first of the reloaded registers to be used. Reported-and-tested-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: Thomas Gleixner Fixes: 1e423bff959e x86/entry/64: ("Migrate the 64-bit syscall slow path to C") Link: http://lkml.kernel.org/r/a85f8360c397e48186a9bc3e565ad74307a7b011.1454261517.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/entry_64.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 9f7bb808035e..70eadb0ea5fa 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -212,7 +212,9 @@ entry_SYSCALL_64_fastpath: LOCKDEP_SYS_EXIT TRACE_IRQS_ON /* user mode is traced as IRQs on */ - RESTORE_C_REGS + movq RIP(%rsp), %rcx + movq EFLAGS(%rsp), %r11 + RESTORE_C_REGS_EXCEPT_RCX_R11 movq RSP(%rsp), %rsp USERGS_SYSRET64 -- cgit From bb56968a37a44070de92d5690c4b08dd98a5d3f1 Mon Sep 17 00:00:00 2001 From: Andy Lutomirski Date: Sun, 31 Jan 2016 09:33:28 -0800 Subject: x86/syscalls/64: Mark sys_iopl() as using ptregs sys_iopl() both reads and writes pt_regs->flags. Mark it as using ptregs. This isn't strictly necessary, as pt_regs->flags is available even in the fast path, but this is very lightweight now that we have syscall qualifiers and it could avoid some pain down the road. Reported-and-tested-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: Thomas Gleixner Link: http://lkml.kernel.org/r/3de0ca692fa8bf414c5e3d7afe3e6195d1a10e1f.1454261517.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/entry/syscalls/syscall_64.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index dcf107ce2cd4..2e5b565adacc 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -178,7 +178,7 @@ 169 common reboot sys_reboot 170 common sethostname sys_sethostname 171 common setdomainname sys_setdomainname -172 common iopl sys_iopl +172 common iopl sys_iopl/ptregs 173 common ioperm sys_ioperm 174 64 create_module 175 common init_module sys_init_module -- cgit From d83a96a53dd2c36948be37b64a85a761b942ddfd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 09:24:29 -0200 Subject: [media] em28xx: remove unused input types The em28xx driver have lots of different input types but only 4 of such types are actually used. The others are bogus. Remove them, in order to cleanup the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 134 ++++++++++++++++---------------- drivers/media/usb/em28xx/em28xx-video.c | 16 ++-- drivers/media/usb/em28xx/em28xx.h | 8 +- 3 files changed, 73 insertions(+), 85 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index a1b6ef5894a6..ab0fe0319991 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -570,7 +570,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, .gpio = silvercrest_reg_seq, @@ -583,7 +583,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -605,7 +605,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -616,7 +616,7 @@ struct em28xx_board em28xx_boards[] = { .tda9887_conf = TDA9887_PRESENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -635,7 +635,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -655,7 +655,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -675,7 +675,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -715,7 +715,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -735,7 +735,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -755,7 +755,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -775,7 +775,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -800,7 +800,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE4, .amux = EM28XX_AMUX_AUX, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE5, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -819,7 +819,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -829,7 +829,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, .gpio = silvercrest_reg_seq, @@ -848,7 +848,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_LINE_IN, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { @@ -863,7 +863,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -879,7 +879,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = 0, .amux = EM28XX_AMUX_VIDEO, } }, @@ -889,7 +889,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -909,7 +909,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -930,7 +930,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -952,7 +952,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -974,7 +974,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -992,7 +992,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1006,7 +1006,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1029,7 +1029,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, @@ -1100,7 +1100,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = terratec_cinergy_USB_XS_FR_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = terratec_cinergy_USB_XS_FR_analog, @@ -1186,7 +1186,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1213,7 +1213,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1239,7 +1239,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1265,7 +1265,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1291,7 +1291,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1317,7 +1317,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1343,7 +1343,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1368,7 +1368,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1392,7 +1392,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE4, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1413,7 +1413,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1428,7 +1428,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* capture only board */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1443,7 +1443,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture-only board */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, .gpio = vc211a_enable, @@ -1465,7 +1465,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1485,7 +1485,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1500,7 +1500,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* capture only board */ .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1520,7 +1520,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE2, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1541,7 +1541,7 @@ struct em28xx_board em28xx_boards[] = { .aout = EM28XX_AOUT_MONO | /* I2S */ EM28XX_AOUT_MASTER, /* Line out pin */ }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1563,7 +1563,7 @@ struct em28xx_board em28xx_boards[] = { .aout = EM28XX_AOUT_MONO | /* I2S */ EM28XX_AOUT_MASTER, /* Line out pin */ }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1581,7 +1581,7 @@ struct em28xx_board em28xx_boards[] = { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, } }, }, @@ -1610,7 +1610,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = em2880_msi_digivox_ad_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2880_msi_digivox_ad_analog, @@ -1633,7 +1633,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = em2880_msi_digivox_ad_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2880_msi_digivox_ad_analog, @@ -1654,7 +1654,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1677,7 +1677,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1708,7 +1708,7 @@ struct em28xx_board em28xx_boards[] = { .gpio = em2882_kworld_315u_analog, .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, .gpio = em2882_kworld_315u_analog1, @@ -1735,7 +1735,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1758,7 +1758,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = default_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = default_analog, @@ -1782,7 +1782,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = pinnacle_hybrid_pro_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = pinnacle_hybrid_pro_analog, @@ -1808,7 +1808,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1834,7 +1834,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1859,7 +1859,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = hauppauge_wintv_hvr_900_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = hauppauge_wintv_hvr_900_analog, @@ -1904,7 +1904,7 @@ struct em28xx_board em28xx_boards[] = { .gpio = kworld_330u_analog, .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = kworld_330u_analog, @@ -1951,7 +1951,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1970,7 +1970,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -1990,7 +1990,7 @@ struct em28xx_board em28xx_boards[] = { .vmux = TVP5150_COMPOSITE0, .amux = EM28XX_AMUX_VIDEO, }, { /* Composite has not been tested yet */ - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_VIDEO, }, { /* S-video has not been tested yet */ @@ -2006,7 +2006,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2023,7 +2023,7 @@ struct em28xx_board em28xx_boards[] = { .xclk = EM28XX_XCLK_FREQUENCY_12MHZ, .mute_gpio = terratec_av350_mute_gpio, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AUDIO_SRC_LINE, .gpio = terratec_av350_unmute_gpio, @@ -2041,7 +2041,7 @@ struct em28xx_board em28xx_boards[] = { .decoder = EM28XX_SAA711X, .tuner_type = TUNER_ABSENT, /* Capture only device */ .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2067,7 +2067,7 @@ struct em28xx_board em28xx_boards[] = { .amux = EM28XX_AMUX_VIDEO, .gpio = evga_indtube_analog, }, { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, .gpio = evga_indtube_analog, @@ -2125,7 +2125,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .decoder = EM28XX_SAA711X, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = SAA7115_COMPOSITE0, .amux = EM28XX_AMUX_LINE_IN, }, { @@ -2238,7 +2238,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, .is_webcam = 1, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .amux = EM28XX_AMUX_VIDEO, .gpio = speedlink_vad_laplace_reg_seq, } }, @@ -2272,7 +2272,7 @@ struct em28xx_board em28xx_boards[] = { .tuner_type = TUNER_ABSENT, /* Capture only device */ .decoder = EM28XX_TVP5150, .input = { { - .type = EM28XX_VMUX_COMPOSITE1, + .type = EM28XX_VMUX_COMPOSITE, .vmux = TVP5150_COMPOSITE1, .amux = EM28XX_AMUX_LINE_IN, }, { diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 6a015e8e8655..52428b4cce5f 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1442,16 +1442,11 @@ static int vidioc_s_parm(struct file *file, void *priv, 0, video, s_parm, p); } -static const char *iname[] = { - [EM28XX_VMUX_COMPOSITE1] = "Composite1", - [EM28XX_VMUX_COMPOSITE2] = "Composite2", - [EM28XX_VMUX_COMPOSITE3] = "Composite3", - [EM28XX_VMUX_COMPOSITE4] = "Composite4", - [EM28XX_VMUX_SVIDEO] = "S-Video", +static const char * const iname[] = { + [EM28XX_VMUX_COMPOSITE] = "Composite", + [EM28XX_VMUX_SVIDEO] = "S-Video", [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_VMUX_CABLE] = "Cable TV", - [EM28XX_VMUX_DVB] = "DVB", - [EM28XX_VMUX_DEBUG] = "for debug only", + [EM28XX_RADIO] = "Radio", }; static int vidioc_enum_input(struct file *file, void *priv, @@ -1471,8 +1466,7 @@ static int vidioc_enum_input(struct file *file, void *priv, strcpy(i->name, iname[INPUT(n)->type]); - if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) || - (EM28XX_VMUX_CABLE == INPUT(n)->type)) + if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type)) i->type = V4L2_INPUT_TYPE_TUNER; i->std = dev->v4l2->vdev.tvnorms; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index 8ff066c977d9..b23bf6a64011 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -291,15 +291,9 @@ struct em28xx_dmaqueue { #define MAX_EM28XX_INPUT 4 enum enum28xx_itype { - EM28XX_VMUX_COMPOSITE1 = 1, - EM28XX_VMUX_COMPOSITE2, - EM28XX_VMUX_COMPOSITE3, - EM28XX_VMUX_COMPOSITE4, + EM28XX_VMUX_COMPOSITE = 1, EM28XX_VMUX_SVIDEO, EM28XX_VMUX_TELEVISION, - EM28XX_VMUX_CABLE, - EM28XX_VMUX_DVB, - EM28XX_VMUX_DEBUG, EM28XX_RADIO, }; -- cgit From 8dfbcc4351a0b6d2f2d77f367552f48ffefafe18 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 09:22:44 -0200 Subject: [media] xc2028: avoid use after free If struct xc2028_config is passed without a firmware name, the following trouble may happen: [11009.907205] xc2028 5-0061: type set to XCeive xc2028/xc3028 tuner [11009.907491] ================================================================== [11009.907750] BUG: KASAN: use-after-free in strcmp+0x96/0xb0 at addr ffff8803bd78ab40 [11009.907992] Read of size 1 by task modprobe/28992 [11009.907994] ============================================================================= [11009.907997] BUG kmalloc-16 (Tainted: G W ): kasan: bad access detected [11009.907999] ----------------------------------------------------------------------------- [11009.908008] INFO: Allocated in xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] age=0 cpu=3 pid=28992 [11009.908012] ___slab_alloc+0x581/0x5b0 [11009.908014] __slab_alloc+0x51/0x90 [11009.908017] __kmalloc+0x27b/0x350 [11009.908022] xhci_urb_enqueue+0x214/0x14c0 [xhci_hcd] [11009.908026] usb_hcd_submit_urb+0x1e8/0x1c60 [11009.908029] usb_submit_urb+0xb0e/0x1200 [11009.908032] usb_serial_generic_write_start+0xb6/0x4c0 [11009.908035] usb_serial_generic_write+0x92/0xc0 [11009.908039] usb_console_write+0x38a/0x560 [11009.908045] call_console_drivers.constprop.14+0x1ee/0x2c0 [11009.908051] console_unlock+0x40d/0x900 [11009.908056] vprintk_emit+0x4b4/0x830 [11009.908061] vprintk_default+0x1f/0x30 [11009.908064] printk+0x99/0xb5 [11009.908067] kasan_report_error+0x10a/0x550 [11009.908070] __asan_report_load1_noabort+0x43/0x50 [11009.908074] INFO: Freed in xc2028_set_config+0x90/0x630 [tuner_xc2028] age=1 cpu=3 pid=28992 [11009.908077] __slab_free+0x2ec/0x460 [11009.908080] kfree+0x266/0x280 [11009.908083] xc2028_set_config+0x90/0x630 [tuner_xc2028] [11009.908086] xc2028_attach+0x310/0x8a0 [tuner_xc2028] [11009.908090] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] [11009.908094] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] [11009.908098] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] [11009.908101] em28xx_register_extension+0xd9/0x190 [em28xx] [11009.908105] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] [11009.908108] do_one_initcall+0x141/0x300 [11009.908111] do_init_module+0x1d0/0x5ad [11009.908114] load_module+0x6666/0x9ba0 [11009.908117] SyS_finit_module+0x108/0x130 [11009.908120] entry_SYSCALL_64_fastpath+0x16/0x76 [11009.908123] INFO: Slab 0xffffea000ef5e280 objects=25 used=25 fp=0x (null) flags=0x2ffff8000004080 [11009.908126] INFO: Object 0xffff8803bd78ab40 @offset=2880 fp=0x0000000000000001 [11009.908130] Bytes b4 ffff8803bd78ab30: 01 00 00 00 2a 07 00 00 9d 28 00 00 01 00 00 00 ....*....(...... [11009.908133] Object ffff8803bd78ab40: 01 00 00 00 00 00 00 00 b0 1d c3 6a 00 88 ff ff ...........j.... [11009.908137] CPU: 3 PID: 28992 Comm: modprobe Tainted: G B W 4.5.0-rc1+ #43 [11009.908140] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [11009.908142] ffff8803bd78a000 ffff8802c273f1b8 ffffffff81932007 ffff8803c6407a80 [11009.908148] ffff8802c273f1e8 ffffffff81556759 ffff8803c6407a80 ffffea000ef5e280 [11009.908153] ffff8803bd78ab40 dffffc0000000000 ffff8802c273f210 ffffffff8155ccb4 [11009.908158] Call Trace: [11009.908162] [] dump_stack+0x4b/0x64 [11009.908165] [] print_trailer+0xf9/0x150 [11009.908168] [] object_err+0x34/0x40 [11009.908171] [] kasan_report_error+0x230/0x550 [11009.908175] [] ? trace_hardirqs_off_caller+0x21/0x290 [11009.908179] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908182] [] __asan_report_load1_noabort+0x43/0x50 [11009.908185] [] ? __asan_register_globals+0x50/0xa0 [11009.908189] [] ? strcmp+0x96/0xb0 [11009.908192] [] strcmp+0x96/0xb0 [11009.908196] [] xc2028_set_config+0x15c/0x630 [tuner_xc2028] [11009.908200] [] xc2028_attach+0x310/0x8a0 [tuner_xc2028] [11009.908203] [] ? memset+0x28/0x30 [11009.908206] [] ? xc2028_set_config+0x630/0x630 [tuner_xc2028] [11009.908211] [] em28xx_attach_xc3028.constprop.7+0x1f9/0x30d [em28xx_dvb] [11009.908215] [] ? em28xx_dvb_init.part.3+0x37c/0x5cf4 [em28xx_dvb] [11009.908219] [] ? hauppauge_hvr930c_init+0x487/0x487 [em28xx_dvb] [11009.908222] [] ? lgdt330x_attach+0x1cc/0x370 [lgdt330x] [11009.908226] [] ? i2c_read_demod_bytes.isra.2+0x210/0x210 [lgdt330x] [11009.908230] [] ? ref_module.part.15+0x10/0x10 [11009.908233] [] ? module_assert_mutex_or_preempt+0x80/0x80 [11009.908238] [] em28xx_dvb_init.part.3+0x8e4/0x5cf4 [em28xx_dvb] [11009.908242] [] ? em28xx_attach_xc3028.constprop.7+0x30d/0x30d [em28xx_dvb] [11009.908245] [] ? string+0x14d/0x1f0 [11009.908249] [] ? symbol_string+0xff/0x1a0 [11009.908253] [] ? uuid_string+0x6f0/0x6f0 [11009.908257] [] ? __kernel_text_address+0x7e/0xa0 [11009.908260] [] ? print_context_stack+0x7f/0xf0 [11009.908264] [] ? __module_address+0xb6/0x360 [11009.908268] [] ? is_ftrace_trampoline+0x99/0xe0 [11009.908271] [] ? __kernel_text_address+0x7e/0xa0 [11009.908275] [] ? debug_check_no_locks_freed+0x290/0x290 [11009.908278] [] ? dump_trace+0x11b/0x300 [11009.908282] [] ? em28xx_register_extension+0x23/0x190 [em28xx] [11009.908285] [] ? trace_hardirqs_off_caller+0x21/0x290 [11009.908289] [] ? trace_hardirqs_on_caller+0x16/0x590 [11009.908292] [] ? trace_hardirqs_on+0xd/0x10 [11009.908296] [] ? em28xx_register_extension+0x23/0x190 [em28xx] [11009.908299] [] ? mutex_trylock+0x400/0x400 [11009.908302] [] ? do_one_initcall+0x131/0x300 [11009.908306] [] ? call_rcu_sched+0x17/0x20 [11009.908309] [] ? put_object+0x48/0x70 [11009.908314] [] em28xx_dvb_init+0x81/0x8a [em28xx_dvb] [11009.908317] [] em28xx_register_extension+0xd9/0x190 [em28xx] [11009.908320] [] ? 0xffffffffa0150000 [11009.908324] [] em28xx_dvb_register+0x10/0x1000 [em28xx_dvb] [11009.908327] [] do_one_initcall+0x141/0x300 [11009.908330] [] ? try_to_run_init_process+0x40/0x40 [11009.908333] [] ? trace_hardirqs_on_caller+0x16/0x590 [11009.908337] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908340] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908343] [] ? kasan_unpoison_shadow+0x36/0x50 [11009.908346] [] ? __asan_register_globals+0x87/0xa0 [11009.908350] [] do_init_module+0x1d0/0x5ad [11009.908353] [] load_module+0x6666/0x9ba0 [11009.908356] [] ? symbol_put_addr+0x50/0x50 [11009.908361] [] ? em28xx_dvb_init.part.3+0x5989/0x5cf4 [em28xx_dvb] [11009.908366] [] ? module_frob_arch_sections+0x20/0x20 [11009.908369] [] ? open_exec+0x50/0x50 [11009.908374] [] ? ns_capable+0x5b/0xd0 [11009.908377] [] SyS_finit_module+0x108/0x130 [11009.908379] [] ? SyS_init_module+0x1f0/0x1f0 [11009.908383] [] ? lockdep_sys_exit_thunk+0x12/0x14 [11009.908394] [] entry_SYSCALL_64_fastpath+0x16/0x76 [11009.908396] Memory state around the buggy address: [11009.908398] ffff8803bd78aa00: 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908401] ffff8803bd78aa80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908403] >ffff8803bd78ab00: fc fc fc fc fc fc fc fc 00 00 fc fc fc fc fc fc [11009.908405] ^ [11009.908407] ffff8803bd78ab80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908409] ffff8803bd78ac00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [11009.908411] ================================================================== In order to avoid it, let's set the cached value of the firmware name to NULL after freeing it. While here, return an error if the memory allocation fails. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tuner-xc2028.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 4e941f00b600..082ff5608455 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1403,11 +1403,12 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) * in order to avoid troubles during device release. */ kfree(priv->ctrl.fname); + priv->ctrl.fname = NULL; memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); if (p->fname) { priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); if (priv->ctrl.fname == NULL) - rc = -ENOMEM; + return -ENOMEM; } /* -- cgit From 163c9bca101caf000691b56fb3834905e62cbba3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 08:39:33 -0200 Subject: [media] tuner.h: rename TUNER_PAD_IF_OUTPUT to TUNER_PAD_OUTPUT The output of a tuner is not only IF frequencies. They may also output audio on some of its pins, and may even be a zero-IF tuner, with outputs a baseband. So, rename the PAD name to make it clearer and add a proper documentation about that at tuner.h. No functional changes. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- drivers/media/usb/au0828/au0828-core.c | 2 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 +- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- drivers/media/v4l2-core/tuner-core.c | 2 +- include/media/tuner.h | 21 ++++++++++++++++++--- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 560450a0b32a..a7de62ebc415 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -661,7 +661,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, if (ntuner && ndemod) { ret = media_create_pad_links(mdev, MEDIA_ENT_F_TUNER, - tuner, TUNER_PAD_IF_OUTPUT, + tuner, TUNER_PAD_OUTPUT, MEDIA_ENT_F_DTV_DEMOD, demod, 0, MEDIA_LNK_FL_ENABLED, false); diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index 9e29e70a78d7..df2bc3f732b6 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -276,7 +276,7 @@ static int au0828_create_media_graph(struct au0828_dev *dev) return -EINVAL; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret) diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 620b83d03f75..54e43fe13e6d 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1259,7 +1259,7 @@ static int cx231xx_create_media_graph(struct cx231xx *dev) return 0; if (tuner) { - ret = media_create_pad_link(tuner, TUNER_PAD_IF_OUTPUT, decoder, 0, + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, decoder, 0, MEDIA_LNK_FL_ENABLED); if (ret < 0) return ret; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index b669deccc34c..e7978e4e40ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -888,7 +888,7 @@ static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap) state->tuner.function = MEDIA_ENT_F_TUNER; state->tuner.name = "mxl111sf tuner"; state->tuner_pads[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - state->tuner_pads[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + state->tuner_pads[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; ret = media_entity_pads_init(&state->tuner, TUNER_NUM_PADS, state->tuner_pads); diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index 76496fd282aa..a1f858b34187 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -697,7 +697,7 @@ static int tuner_probe(struct i2c_client *client, register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_IF_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/tuner.h b/include/media/tuner.h index e5321fda5489..c5994fe865a0 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -21,11 +21,26 @@ #include -/* Tuner PADs */ -/* FIXME: is this the right place for it? */ +/** + * enum tuner_pad_index - tuner pad index + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, - TUNER_PAD_IF_OUTPUT, + TUNER_PAD_OUTPUT, TUNER_NUM_PADS }; -- cgit From 6aad127d37b609ca40ee3b93454a58ee6ed5a1ce Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 06:11:30 -0200 Subject: [media] v4l2-mc.h: move tuner PAD definitions to this new header The customer PC hardware can be shipped with lots of different configurations, as vendors use to replace some of the chips on their hardware along the time. All drivers that support such devices are prepared to handle the hardware differences, using their own auto-probing logic. They do it in a way that number of inputs and outputs for a given hardware type doesn't change. Now that we're adding media controller capabilities to those drivers, we need to standardize the number of inputs and outputs for each hardware type, as we want to have a generic function at the V4L2 core that would create the links for the entities that are expected on such hardware. Such standard is already there for tuners, but tuner.h is not the best place to store such data, as we'll need to add definitions also for analog TV demodulators. Also, we'll need a place to put a set of MC handling functions. So, let's create a v4l2-mc.h to store such kind of definitions. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/device-drivers.tmpl | 1 + include/media/tuner.h | 24 +------------------ include/media/v4l2-mc.h | 38 +++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 23 deletions(-) create mode 100644 include/media/v4l2-mc.h diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index cdd8b24db68d..cc303a2f641c 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -229,6 +229,7 @@ X!Isound/sound_firmware.c !Iinclude/media/v4l2-dv-timings.h !Iinclude/media/v4l2-event.h !Iinclude/media/v4l2-flash-led-class.h +!Iinclude/media/v4l2-mc.h !Iinclude/media/v4l2-mediabus.h !Iinclude/media/v4l2-mem2mem.h !Iinclude/media/v4l2-of.h diff --git a/include/media/tuner.h b/include/media/tuner.h index c5994fe865a0..b3edc14e763f 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -20,29 +20,7 @@ #ifdef __KERNEL__ #include - -/** - * enum tuner_pad_index - tuner pad index - * - * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a - * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. - * @TUNER_NUM_PADS: Number of pads of the tuner. - */ -enum tuner_pad_index { - TUNER_PAD_RF_INPUT, - TUNER_PAD_OUTPUT, - TUNER_NUM_PADS -}; +#include #define ADDR_UNSET (255) diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h new file mode 100644 index 000000000000..f6fcd70f3548 --- /dev/null +++ b/include/media/v4l2-mc.h @@ -0,0 +1,38 @@ +/* + * v4l2-mc.h - Media Controller V4L2 types and prototypes + * + * Copyright (C) 2016 Mauro Carvalho Chehab + * + * 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. + */ + +/** + * enum tuner_pad_index - tuner pad index for MEDIA_ENT_F_TUNER + * + * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a + * RF connector entity. + * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than + * a single pad output, as, in addition to luminance and + * chrominance IF a tuner may have internally an + * audio decoder (like xc3028) or it may produce an audio + * IF that will be used by an audio decoder like msp34xx. + * It may also have an IF-PLL demodulator on it, like + * tuners with tda9887. Yet, currently, we don't need to + * represent all the dirty details, as this is transparent + * for the V4L2 API usage. So, let's represent all kinds + * of different outputs as a single source pad. + * @TUNER_NUM_PADS: Number of pads of the tuner. + */ +enum tuner_pad_index { + TUNER_PAD_RF_INPUT, + TUNER_PAD_OUTPUT, + TUNER_NUM_PADS +}; \ No newline at end of file -- cgit From 5c9077eabc9a0ffbd4c8b0724ddcd69ef2b1a7ed Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:08 -0200 Subject: [media] v4l2-mc.h: Split audio from baseband output Analog TV tuners have a separate output pad for the audio IF or audio sampled data. This pad is connected to a different chipset. Add an extra pad for it and improve the documentation. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 1 + include/media/v4l2-mc.h | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index a1f858b34187..d6bd9ce1101d 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -698,6 +698,7 @@ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index f6fcd70f3548..c174e5b4f188 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -19,20 +19,26 @@ * * @TUNER_PAD_RF_INPUT: Radiofrequency (RF) sink pad, usually linked to a * RF connector entity. - * @TUNER_PAD_OUTPUT: Tuner output pad. This is actually more complex than - * a single pad output, as, in addition to luminance and - * chrominance IF a tuner may have internally an - * audio decoder (like xc3028) or it may produce an audio - * IF that will be used by an audio decoder like msp34xx. - * It may also have an IF-PLL demodulator on it, like - * tuners with tda9887. Yet, currently, we don't need to - * represent all the dirty details, as this is transparent - * for the V4L2 API usage. So, let's represent all kinds - * of different outputs as a single source pad. + * @TUNER_PAD_OUTPUT: Tuner video output source pad. Contains the video + * chrominance and luminance or the hole bandwidth + * of the signal converted to an Intermediate Frequency + * (IF) or to baseband (on zero-IF tuners). + * @TUNER_PAD_AUD_OUT: Tuner audio output source pad. Tuners used to decode + * analog TV signals have an extra pad for audio output. + * Old tuners use an analog stage with a saw filter for + * the audio IF frequency. The output of the pad is, in + * this case, the audio IF, with should be decoded either + * by the bridge chipset (that's the case of cx2388x + * chipsets) or may require an external IF sound + * processor, like msp34xx. On modern silicon tuners, + * the audio IF decoder is usually incorporated at the + * tuner. On such case, the output of this pad is an + * audio sampled data. * @TUNER_NUM_PADS: Number of pads of the tuner. */ enum tuner_pad_index { TUNER_PAD_RF_INPUT, TUNER_PAD_OUTPUT, + TUNER_PAD_AUD_OUT, TUNER_NUM_PADS -}; \ No newline at end of file +}; -- cgit From 06131932c1d5f1bd09832f42be658906a27749fb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 07:28:08 -0200 Subject: [media] media.h: add support for IF-PLL video/sound decoder Very old hardware may have an analog stage tuner. Those hardware consists of a PLL that converts a RF signal into IF signals. Depending on the hardware, those video IF signal can be decoded directly by the bridge chipset. Most Conexant chips (bt8x8, cx2388x, etc) have internally the decoders for that. Yet, even on such hardware, the tuner may have internally its own TV multi-standard decoder like tda9887. The same happens with the audio IF signal, where some bridges are capable of receiving it, while others require an external IF-PLL sound decoder, like msp3400. Those external IF-PLL audio and video decoders have their own I2C address, and use different drivers to handle them. So, they're mapped as different subdevices on Linux. Thankfully, all modern hardware comes with an IC chip that has both the RF and the IF stages on it, being capable of decoding audio and video IF signals internally. Yet, as we need to support drivers that can work with either analog or silicon tuners, we need to add two entity types for those old hardware. Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/media-types.xml | 29 ++++++++++++++++++++++++- include/uapi/linux/media.h | 17 +++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/Documentation/DocBook/media/v4l/media-types.xml b/Documentation/DocBook/media/v4l/media-types.xml index 1af384250910..751c3d027103 100644 --- a/Documentation/DocBook/media/v4l/media-types.xml +++ b/Documentation/DocBook/media/v4l/media-types.xml @@ -84,7 +84,34 @@ MEDIA_ENT_F_TUNER - Digital TV, analog TV, radio and/or software radio tuner. + Digital TV, analog TV, radio and/or software radio tuner, + with consists on a PLL tuning stage that converts radio + frequency (RF) signal into an Intermediate Frequency (IF). + Modern tuners have internally IF-PLL decoders for audio + and video, but older models have those stages implemented + on separate entities. + + + + MEDIA_ENT_F_IF_VID_DECODER + IF-PLL video decoder. It receives the IF from a PLL + and decodes the analog TV video signal. This is commonly + found on some very old analog tuners, like Philips MK3 + designs. They all contain a tda9887 (or some software + compatible similar chip, like tda9885). Those devices + use a different I2C address than the tuner PLL. + + + + MEDIA_ENT_F_IF_AUD_DECODER + IF-PLL sound decoder. It receives the IF from a PLL + and decodes the analog TV audio signal. This is commonly + found on some very old analog hardware, like Micronas + msp3400, Philips tda9840, tda985x, etc. Those devices + use a different I2C address than the tuner PLL and + should be controlled together with the IF-PLL video + decoder. + diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 5dbb208e5451..c9eb42a6c021 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -88,6 +88,15 @@ struct media_device_info { #define MEDIA_ENT_F_IO_VBI (MEDIA_ENT_F_BASE + 32) #define MEDIA_ENT_F_IO_SWRADIO (MEDIA_ENT_F_BASE + 33) +/* + * Analog TV IF-PLL decoders + * + * It is a responsibility of the master/bridge drivers to create links + * for MEDIA_ENT_F_IF_VID_DECODER and MEDIA_ENT_F_IF_AUD_DECODER. + */ +#define MEDIA_ENT_F_IF_VID_DECODER (MEDIA_ENT_F_BASE + 41) +#define MEDIA_ENT_F_IF_AUD_DECODER (MEDIA_ENT_F_BASE + 42) + /* * Don't touch on those. The ranges MEDIA_ENT_F_OLD_BASE and * MEDIA_ENT_F_OLD_SUBDEV_BASE are kept to keep backward compatibility @@ -107,8 +116,12 @@ struct media_device_info { #define MEDIA_ENT_F_LENS (MEDIA_ENT_F_OLD_SUBDEV_BASE + 3) #define MEDIA_ENT_F_ATV_DECODER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 4) /* - * It is a responsibility of the entity drivers to add connectors and links - * for the tuner entities. + * It is a responsibility of the master/bridge drivers to add connectors + * and links for MEDIA_ENT_F_TUNER. Please notice that some old tuners + * may require the usage of separate I2C chips to decode analog TV signals, + * when the master/bridge chipset doesn't have its own TV standard decoder. + * On such cases, the IF-PLL staging is mapped via one or two entities: + * MEDIA_ENT_F_IF_VID_DECODER and/or MEDIA_ENT_F_IF_AUD_DECODER. */ #define MEDIA_ENT_F_TUNER (MEDIA_ENT_F_OLD_SUBDEV_BASE + 5) -- cgit From 953a457e50958494cfa90b41a13c26e9fb04195c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:37 -0200 Subject: [media] v4l2-mc.h Add pads for audio and video IF-PLL decoders The audio and video IF-PLL decoders have one sink and one source PAD. Add macro names for those pads and describe what kind of signals are represented at such pads. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/tuner-core.c | 27 +++++++++++++++++++++------ include/media/v4l2-mc.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index d6bd9ce1101d..731487be5baa 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -696,17 +696,32 @@ static int tuner_probe(struct i2c_client *client, /* Should be just before return */ register_client: #if defined(CONFIG_MEDIA_CONTROLLER) - t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; - t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; - t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; - t->sd.entity.function = MEDIA_ENT_F_TUNER; t->sd.entity.name = t->name; + /* + * Handle the special case where the tuner has actually + * two stages: the PLL to tune into a frequency and the + * IF-PLL demodulator (tda988x). + */ + if (t->type == TUNER_TDA9887) { + t->pad[IF_VID_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[IF_VID_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, + IF_VID_DEC_PAD_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_IF_VID_DECODER; + } else { + t->pad[TUNER_PAD_RF_INPUT].flags = MEDIA_PAD_FL_SINK; + t->pad[TUNER_PAD_OUTPUT].flags = MEDIA_PAD_FL_SOURCE; + t->pad[TUNER_PAD_AUD_OUT].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, + &t->pad[0]); + t->sd.entity.function = MEDIA_ENT_F_TUNER; + } - ret = media_entity_pads_init(&t->sd.entity, TUNER_NUM_PADS, &t->pad[0]); if (ret < 0) { tuner_err("failed to initialize media entity!\n"); kfree(t); - return -ENODEV; + return ret; } #endif /* Sets a default mode */ diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index c174e5b4f188..6a6ef5bc767e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -42,3 +42,35 @@ enum tuner_pad_index { TUNER_PAD_AUD_OUT, TUNER_NUM_PADS }; + +/** + * enum if_vid_dec_index - video IF-PLL pad index for + * MEDIA_ENT_F_IF_VID_DECODER + * + * @IF_VID_DEC_PAD_IF_INPUT: video Intermediate Frequency (IF) sink pad + * @IF_VID_DEC_PAD_OUT: IF-PLL video output source pad. Contains the + * video chrominance and luminance IF signals. + * @IF_VID_DEC_PAD_NUM_PADS: Number of pads of the video IF-PLL. + */ +enum if_vid_dec_pad_index { + IF_VID_DEC_PAD_IF_INPUT, + IF_VID_DEC_PAD_OUT, + IF_VID_DEC_PAD_NUM_PADS +}; + +/** + * enum if_aud_dec_index - audio/sound IF-PLL pad index for + * MEDIA_ENT_F_IF_AUD_DECODER + * + * @IF_AUD_DEC_PAD_IF_INPUT: audio Intermediate Frequency (IF) sink pad + * @IF_AUD_DEC_PAD_OUT: IF-PLL audio output source pad. Contains the + * audio sampled stream data, usually connected + * to the bridge bus via an Inter-IC Sound (I2S) + * bus. + * @IF_AUD_DEC_PAD_NUM_PADS: Number of pads of the audio IF-PLL. + */ +enum if_aud_dec_pad_index { + IF_AUD_DEC_PAD_IF_INPUT, + IF_AUD_DEC_PAD_OUT, + IF_AUD_DEC_PAD_NUM_PADS +}; -- cgit From e4001e955bec5566848624635cfb2d353ebac507 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 07:00:57 -0200 Subject: [media] v4l2-mc: add analog TV demodulator pad index macros We also need to standardize the PAD index macros for demods, as they all should look the same in a media graph. Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-mc.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h index 6a6ef5bc767e..df115195690e 100644 --- a/include/media/v4l2-mc.h +++ b/include/media/v4l2-mc.h @@ -74,3 +74,18 @@ enum if_aud_dec_pad_index { IF_AUD_DEC_PAD_OUT, IF_AUD_DEC_PAD_NUM_PADS }; + +/** + * enum demod_pad_index - analog TV pad index for MEDIA_ENT_F_ATV_DECODER + * + * @DEMOD_PAD_IF_INPUT: IF input sink pad. + * @DEMOD_PAD_VID_OUT: Video output source pad. + * @DEMOD_PAD_VBI_OUT: Vertical Blank Interface (VBI) output source pad. + * @DEMOD_NUM_PADS: Maximum number of output pads. + */ +enum demod_pad_index { + DEMOD_PAD_IF_INPUT, + DEMOD_PAD_VID_OUT, + DEMOD_PAD_VBI_OUT, + DEMOD_NUM_PADS +}; -- cgit From 55606310e77f5099d01b59ea9a25401f521c5713 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 12:08:13 -0200 Subject: [media] tvp5150: create the expected number of pads The tvp5150 doesn't have just one pad. It has 3 ones: - IF input - Video output - VBI output Fix it and use the macros for the pad indexes. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 0ad122fcd632..20428f052506 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "tvp5150_reg.h" @@ -37,7 +38,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct tvp5150 { struct v4l2_subdev sd; - struct media_pad pad; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[DEMOD_NUM_PADS]; +#endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -1313,8 +1316,10 @@ static int tvp5150_probe(struct i2c_client *c, sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; #if defined(CONFIG_MEDIA_CONTROLLER) - core->pad.flags = MEDIA_PAD_FL_SOURCE; - res = media_entity_pads_init(&sd->entity, 1, &core->pad); + core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; #endif -- cgit From fb4932821731f58353d23f6673b55a9612a1cb57 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 28 Jan 2016 08:51:01 -0200 Subject: [media] msp3400: initialize MC data Add pads and set the device type when used with the media controller. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/msp3400-driver.c | 14 ++++++++++++++ drivers/media/i2c/msp3400-driver.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c index a84561d0d4a8..e016626ebf89 100644 --- a/drivers/media/i2c/msp3400-driver.c +++ b/drivers/media/i2c/msp3400-driver.c @@ -688,6 +688,9 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) int msp_revision; int msp_product, msp_prod_hi, msp_prod_lo; int msp_rom; +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret; +#endif if (!id) strlcpy(client->name, "msp3400", sizeof(client->name)); @@ -704,6 +707,17 @@ static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id) sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &msp_ops); +#if defined(CONFIG_MEDIA_CONTROLLER) + state->pads[IF_AUD_DEC_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[IF_AUD_DEC_PAD_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_IF_AUD_DECODER; + + ret = media_entity_pads_init(&sd->entity, 2, state->pads); + if (ret < 0) + return ret; +#endif + state->v4l2_std = V4L2_STD_NTSC; state->detected_std = V4L2_STD_ALL; state->audmode = V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index 6cae21366ed5..f0bb37dc9013 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -7,6 +7,7 @@ #include #include #include +#include /* ---------------------------------------------------------------------- */ @@ -102,6 +103,10 @@ struct msp_state { wait_queue_head_t wq; unsigned int restart:1; unsigned int watch_stereo:1; + +#if CONFIG_MEDIA_CONTROLLER + struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; +#endif }; static inline struct msp_state *to_state(struct v4l2_subdev *sd) -- cgit From f92c70ad28341b6430c64332521428768058dd17 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 15:09:15 -0200 Subject: [media] tvp5150: identify it as a MEDIA_ENT_F_ATV_DECODER The tvp5150 is an analog TV decoder. Identify as such at the media graph, or otherwise devices using it would fail. That avoids the following warning: [ 1546.669139] usb 2-3.3: Entity type for entity tvp5150 5-005c was not initialized! Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 20428f052506..19b52736b24e 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -1319,6 +1319,9 @@ static int tvp5150_probe(struct i2c_client *c, core->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; core->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; core->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; -- cgit From af7d374a4cf715d7b7f535bcc30d814faf6a5cf6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 08:44:28 -0200 Subject: [media] saa7115: initialize demod type and add the needed pads The saa7115 driver is used on several em28xx-based devices. Now that we're about to add MC support to em28xx, we need to be sure that the saa711x demod will be properly mapped at MC. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/saa7115.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c index 24d2b76dbe97..d2a1ce2bc7f5 100644 --- a/drivers/media/i2c/saa7115.c +++ b/drivers/media/i2c/saa7115.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,9 @@ enum saa711x_model { struct saa711x_state { struct v4l2_subdev sd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pads[DEMOD_NUM_PADS]; +#endif struct v4l2_ctrl_handler hdl; struct { @@ -1809,6 +1813,9 @@ static int saa711x_probe(struct i2c_client *client, struct saa7115_platform_data *pdata; int ident; char name[CHIP_VER_SIZE + 1]; +#if defined(CONFIG_MEDIA_CONTROLLER) + int ret; +#endif /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -1832,6 +1839,18 @@ static int saa711x_probe(struct i2c_client *client, sd = &state->sd; v4l2_i2c_subdev_init(sd, client, &saa711x_ops); +#if defined(CONFIG_MEDIA_CONTROLLER) + state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK; + state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE; + state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.function = MEDIA_ENT_F_ATV_DECODER; + + ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads); + if (ret < 0) + return ret; +#endif + v4l_info(client, "%s found @ 0x%x (%s)\n", name, client->addr << 1, client->adapter->name); hdl = &state->hdl; -- cgit From 56a7f51554b22729cee87042ea697a0d59b13d6b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 13:08:19 -0200 Subject: [media] em28xx: unregister devices in case of failure If something bad happens during device registration, unregister the already registered devices. Without that, it will have lots of KASAN errors when udev would try to open the devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 52428b4cce5f..8c87f3fbd0cf 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2579,6 +2579,22 @@ static int em28xx_v4l2_init(struct em28xx *dev) return 0; unregister_dev: + if (video_is_registered(&v4l2->radio_dev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->radio_dev)); + video_unregister_device(&v4l2->radio_dev); + } + if (video_is_registered(&v4l2->vbi_dev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->vbi_dev)); + video_unregister_device(&v4l2->vbi_dev); + } + if (video_is_registered(&v4l2->vdev)) { + em28xx_info("V4L2 device %s deregistered\n", + video_device_node_name(&v4l2->vdev)); + video_unregister_device(&v4l2->vdev); + } + v4l2_ctrl_handler_free(&v4l2->ctrl_handler); v4l2_device_unregister(&v4l2->v4l2_dev); err: -- cgit From 41a5e7ea7d25f207e5d1c71c9cfe5c07aa5fd055 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 10:11:57 -0200 Subject: [media] em28xx: fix tuner detection for Pixelview Prolink PlayTV USB 2.0 The tuner is at address 0x60. This address is not probed by default by tuner anymore, so we need to explicitly add it. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ab0fe0319991..2001c9c14784 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -1555,6 +1555,7 @@ struct em28xx_board em28xx_boards[] = { .buttons = std_snapshot_button, .tda9887_conf = TDA9887_PRESENT, .tuner_type = TUNER_YMEC_TVF_5533MF, + .tuner_addr = 0x60, .decoder = EM28XX_SAA711X, .input = { { .type = EM28XX_VMUX_TELEVISION, -- cgit From 22580f7cb9dfc11db233f48a5e257566f508f5c3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 12:53:56 -0200 Subject: [media] em28xx: make sure that the device has video There are some devices, like Terratec Cinergy HTC, where while the device supports analog TV, the driver is not capable yet of handling it, because the analog TV driver was not written. So, don't bind the em28xx-v4l drivers on such devices. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-cards.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 2001c9c14784..ec4e95119877 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3468,7 +3468,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* save our data pointer in this interface device */ usb_set_intfdata(interface, dev); - /* allocate device struct */ + /* allocate device struct and check if the device is a webcam */ mutex_init(&dev->lock); retval = em28xx_init_dev(dev, udev, interface, nr); if (retval) { @@ -3484,6 +3484,15 @@ static int em28xx_usb_probe(struct usb_interface *interface, try_bulk = usb_xfer_mode > 0; } + /* Disable V4L2 if the device doesn't have a decoder */ + if (has_video && + dev->board.decoder == EM28XX_NODECODER && !dev->board.is_webcam) { + printk(DRIVER_NAME + ": Currently, V4L2 is not supported on this model\n"); + has_video = false; + dev->has_video = false; + } + /* Select USB transfer types to use */ if (has_video) { if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk)) -- cgit From 0962a763327bd33fd18c3a4d0a613cad0976a930 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 14:05:11 -0200 Subject: [media] em28xx: avoid divide by zero error [ 1841.243670] divide error: 0000 [#1] SMP KASAN [ 1841.243994] Modules linked in: em28xx_rc rc_core tda18271 drxk em28xx_dvb dvb_core em28xx_alsa mt9v011 em28xx_v4l videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core em28xx tveeprom v4l2_common videodev media cpufreq_powersave cpufreq_conservative cpufreq_userspace cpufreq_stats parport_pc ppdev lp parport snd_hda_codec_hdmi intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm iTCO_wdt iTCO_vendor_support irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel sha256_ssse3 sha256_generic hmac drbg i915 snd_hda_codec_realtek snd_hda_codec_generic aesni_intel aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd btusb i2c_algo_bit snd_hda_intel btrtl drm_kms_helper btbcm evdev snd_hda_codec btintel psmouse bluetooth pcspkr snd_hwdep sg drm serio_raw [ 1841.244845] snd_hda_core snd_pcm mei_me rfkill snd_timer mei snd lpc_ich soundcore shpchp i2c_i801 mfd_core battery dw_dmac i2c_designware_platform i2c_designware_core dw_dmac_core video acpi_pad button tpm_tis tpm ext4 crc16 mbcache jbd2 dm_mod hid_generic usbhid sd_mod ahci libahci libata ehci_pci e1000e xhci_pci ptp scsi_mod ehci_hcd xhci_hcd pps_core fan thermal sdhci_acpi sdhci mmc_core i2c_hid hid [last unloaded: tveeprom] [ 1841.245342] CPU: 2 PID: 38 Comm: kworker/2:1 Tainted: G W 4.5.0-rc1+ #43 [ 1841.245413] Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0350.2015.0812.1722 08/12/2015 [ 1841.245503] Workqueue: events request_module_async [em28xx] [ 1841.245557] task: ffff88009df10000 ti: ffff88009df18000 task.ti: ffff88009df18000 [ 1841.245626] RIP: 0010:[] [] size_to_scale+0xed/0x2c0 [em28xx_v4l] [ 1841.245714] RSP: 0018:ffff88009df1faa8 EFLAGS: 00010246 [ 1841.245756] RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff8803bb933b38 [ 1841.245815] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8803bb933b00 [ 1841.245879] RBP: ffff88009df1fad8 R08: ffff8803bb933b3c R09: 1ffff10077726760 [ 1841.245944] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 1841.246006] R13: 0000000000000000 R14: dffffc0000000000 R15: ffff8803b391a130 [ 1841.246071] FS: 0000000000000000(0000) GS:ffff8803c6900000(0000) knlGS:0000000000000000 [ 1841.246141] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1841.246194] CR2: 0000000001d97008 CR3: 00000003bdd85000 CR4: 00000000003406e0 [ 1841.246256] Stack: [ 1841.246278] 0000000000000246 ffff8803bb9321f0 ffff8803bb932270 ffffffffa136f7a0 [ 1841.246359] 0000000000000000 ffff8803bb932130 ffff88009df1fb20 ffffffffa13646a0 [ 1841.246439] ffffffffa127f206 ffff8803bb932130 ffff8803bb932130 ffff8803b391a130 [ 1841.246517] Call Trace: [ 1841.246548] [] em28xx_set_video_format+0x140/0x1e0 [em28xx_v4l] Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-video.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 8c87f3fbd0cf..86db1e1f8ab5 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1232,6 +1232,12 @@ static void scale_to_size(struct em28xx *dev, *width = (((unsigned long)maxw) << 12) / (hscale + 4096L); *height = (((unsigned long)maxh) << 12) / (vscale + 4096L); + + /* Don't let width or height to be zero */ + if (*width < 1) + *width = 1; + if (*height < 1) + *height = 1; } /* ------------------------------------------------------------------ @@ -1307,6 +1313,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0); } + /* Avoid division by zero at size_to_scale */ + if (width < 1) + width = 1; + if (height < 1) + height = 1; size_to_scale(dev, width, height, &hscale, &vscale); scale_to_size(dev, hscale, vscale, &width, &height); -- cgit From ac88fce987bd3433706b1082e8a85408de63512c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 29 Jan 2016 14:33:12 -0200 Subject: [media] mt9v011: add media controller support Create a source pad and set the media controller type to the sensor. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/mt9v011.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c index b9fea11d6b0b..9ed1b26b6549 100644 --- a/drivers/media/i2c/mt9v011.c +++ b/drivers/media/i2c/mt9v011.c @@ -50,6 +50,9 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)"); struct mt9v011 { struct v4l2_subdev sd; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad pad; +#endif struct v4l2_ctrl_handler ctrls; unsigned width, height; unsigned xtal; @@ -493,6 +496,9 @@ static int mt9v011_probe(struct i2c_client *c, u16 version; struct mt9v011 *core; struct v4l2_subdev *sd; +#ifdef CONFIG_MEDIA_CONTROLLER + int ret; +#endif /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(c->adapter, @@ -506,6 +512,15 @@ static int mt9v011_probe(struct i2c_client *c, sd = &core->sd; v4l2_i2c_subdev_init(sd, c, &mt9v011_ops); +#ifdef CONFIG_MEDIA_CONTROLLER + core->pad.flags = MEDIA_PAD_FL_SOURCE; + sd->entity.function = MEDIA_ENT_F_CAM_SENSOR; + + ret = media_entity_pads_init(&sd->entity, 1, &core->pad); + if (ret < 0) + return ret; +#endif + /* Check if the sensor is really a MT9V011 */ version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION); if ((version != MT9V011_VERSION) && -- cgit From 37ecc7b1278f4184a6869504f7074b4a54f112c5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 27 Jan 2016 07:07:24 -0200 Subject: [media] em28xx: add media controller support Add the needed bits to make em28xx to create a media controller graph. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/em28xx/em28xx-camera.c | 4 + drivers/media/usb/em28xx/em28xx-cards.c | 55 +++++- drivers/media/usb/em28xx/em28xx-dvb.c | 10 ++ drivers/media/usb/em28xx/em28xx-video.c | 294 ++++++++++++++++++++++++++++++- drivers/media/usb/em28xx/em28xx.h | 13 +- 5 files changed, 366 insertions(+), 10 deletions(-) diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index b58acd3fcd99..72f3f4d50253 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -64,6 +64,8 @@ static int em28xx_initialize_mt9m111(struct em28xx *dev) i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®s[i][0], 3); + /* FIXME: This won't be creating a sensor at the media graph */ + return 0; } @@ -91,6 +93,8 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) i2c_master_send(&dev->i2c_client[dev->def_i2c_bus], ®s[i][0], 3); + /* FIXME: This won't be creating a sensor at the media graph */ + return 0; } diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ec4e95119877..ba442c967415 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -3013,6 +3013,48 @@ static void flush_request_modules(struct em28xx *dev) flush_work(&dev->request_module_wk); } +static int em28xx_media_device_init(struct em28xx *dev, + struct usb_device *udev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mdev->dev = &udev->dev; + + if (!dev->name) + strlcpy(mdev->model, "unknown em28xx", sizeof(mdev->model)); + else + strlcpy(mdev->model, dev->name, sizeof(mdev->model)); + if (udev->serial) + strlcpy(mdev->serial, udev->serial, sizeof(mdev->serial)); + strcpy(mdev->bus_info, udev->devpath); + mdev->hw_revision = le16_to_cpu(udev->descriptor.bcdDevice); + mdev->driver_version = LINUX_VERSION_CODE; + + media_device_init(mdev); + + dev->media_dev = mdev; +#endif + return 0; +} + +static void em28xx_unregister_media_device(struct em28xx *dev) +{ + +#ifdef CONFIG_MEDIA_CONTROLLER + if (dev->media_dev) { + media_device_unregister(dev->media_dev); + media_device_cleanup(dev->media_dev); + kfree(dev->media_dev); + dev->media_dev = NULL; + } +#endif +} + /* * em28xx_release_resources() * unregisters the v4l2,i2c and usb devices @@ -3024,6 +3066,8 @@ static void em28xx_release_resources(struct em28xx *dev) mutex_lock(&dev->lock); + em28xx_unregister_media_device(dev); + if (dev->def_i2c_bus) em28xx_i2c_unregister(dev, 1); em28xx_i2c_unregister(dev, 0); @@ -3168,6 +3212,8 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, */ snprintf(dev->name, sizeof(dev->name), "%s #%d", chip_name, dev->devno); + em28xx_media_device_init(dev, udev); + if (dev->is_audio_only) { retval = em28xx_audio_setup(dev); if (retval) @@ -3511,9 +3557,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, request_modules(dev); - /* Should be the last thing to do, to avoid newer udev's to - open the device before fully initializing it + /* + * Do it at the end, to reduce dynamic configuration changes during + * the device init. Yet, as request_modules() can be async, the + * topology will likely change after the load of the em28xx subdrivers. */ +#ifdef CONFIG_MEDIA_CONTROLLER + retval = media_device_register(dev->media_dev); +#endif return 0; diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index bf5c24467c65..ea80541d58f0 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -916,6 +916,9 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, dev->name, result); goto fail_adapter; } +#ifdef CONFIG_MEDIA_CONTROLLER_DVB + dvb->adapter.mdev = dev->media_dev; +#endif /* Ensure all frontends negotiate bus access */ dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl; @@ -994,8 +997,15 @@ static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module, /* register network adapter */ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx); + + result = dvb_create_media_graph(&dvb->adapter, false); + if (result < 0) + goto fail_create_graph; + return 0; +fail_create_graph: + dvb_net_release(&dvb->net); fail_fe_conn: dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem); fail_fe_mem: diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 86db1e1f8ab5..16a2d4039330 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -866,6 +866,275 @@ static void res_free(struct em28xx *dev, enum v4l2_buf_type f_type) em28xx_videodbg("res: put %d\n", res_type); } +static void em28xx_v4l2_media_release(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + int i; + + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + if (!INPUT(i)->type) + return; + media_device_unregister_entity(&dev->input_ent[i]); + } +#endif +} + +/* + * Media Controller helper functions + */ + +static int em28xx_v4l2_create_media_graph(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct media_device *mdev = dev->media_dev; + struct media_entity *entity; + struct media_entity *if_vid = NULL, *if_aud = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; + int i, ret; + + if (!mdev) + return 0; + + /* Webcams are really simple */ + if (dev->board.is_webcam) { + media_device_for_each_entity(entity, mdev) { + if (entity->function != MEDIA_ENT_F_CAM_SENSOR) + continue; + ret = media_create_pad_link(entity, 0, + &v4l2->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + return 0; + } + + /* Non-webcams have analog TV decoder and other complexities */ + + media_device_for_each_entity(entity, mdev) { + switch (entity->function) { + case MEDIA_ENT_F_IF_VID_DECODER: + if_vid = entity; + break; + case MEDIA_ENT_F_IF_AUD_DECODER: + if_aud = entity; + break; + case MEDIA_ENT_F_TUNER: + tuner = entity; + break; + case MEDIA_ENT_F_ATV_DECODER: + decoder = entity; + break; + } + } + + /* Analog setup, using tuner as a link */ + + /* Something bad happened! */ + if (!decoder) + return -EINVAL; + + if (tuner) { + if (if_vid) { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + if_vid, + IF_VID_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + ret = media_create_pad_link(if_vid, IF_VID_DEC_PAD_OUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + ret = media_create_pad_link(tuner, TUNER_PAD_OUTPUT, + decoder, DEMOD_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + if (if_aud) { + ret = media_create_pad_link(tuner, TUNER_PAD_AUD_OUT, + if_aud, + IF_AUD_DEC_PAD_IF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } else { + if_aud = tuner; + } + + } + ret = media_create_pad_link(decoder, DEMOD_PAD_VID_OUT, + &v4l2->vdev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + + if (em28xx_vbi_supported(dev)) { + ret = media_create_pad_link(decoder, DEMOD_PAD_VBI_OUT, + &v4l2->vbi_dev.entity, 0, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + } + + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + switch (INPUT(i)->type) { + case EM28XX_VMUX_COMPOSITE: + case EM28XX_VMUX_SVIDEO: + ret = media_create_pad_link(ent, 0, decoder, + DEMOD_PAD_IF_INPUT, 0); + if (ret) + return ret; + break; + default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ + if (!tuner) + break; + + ret = media_create_pad_link(ent, 0, tuner, + TUNER_PAD_RF_INPUT, + MEDIA_LNK_FL_ENABLED); + if (ret) + return ret; + break; + } + } +#endif + return 0; +} + +static int em28xx_enable_analog_tuner(struct em28xx *dev) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *mdev = dev->media_dev; + struct em28xx_v4l2 *v4l2 = dev->v4l2; + struct media_entity *source; + struct media_link *link, *found_link = NULL; + int ret, active_links = 0; + + if (!mdev || !v4l2->decoder) + return 0; + + /* + * This will find the tuner that is connected into the decoder. + * Technically, this is not 100% correct, as the device may be + * using an analog input instead of the tuner. However, as we can't + * do DVB streaming while the DMA engine is being used for V4L2, + * this should be enough for the actual needs. + */ + list_for_each_entry(link, &v4l2->decoder->links, list) { + if (link->sink->entity == v4l2->decoder) { + found_link = link; + if (link->flags & MEDIA_LNK_FL_ENABLED) + active_links++; + break; + } + } + + if (active_links == 1 || !found_link) + return 0; + + source = found_link->source->entity; + list_for_each_entry(link, &source->links, list) { + struct media_entity *sink; + int flags = 0; + + sink = link->sink->entity; + + if (sink == v4l2->decoder) + flags = MEDIA_LNK_FL_ENABLED; + + ret = media_entity_setup_link(link, flags); + if (ret) { + pr_err("Couldn't change link %s->%s to %s. Error %d\n", + source->name, sink->name, + flags ? "enabled" : "disabled", + ret); + return ret; + } else + em28xx_videodbg("link %s->%s was %s\n", + source->name, sink->name, + flags ? "ENABLED" : "disabled"); + } +#endif + return 0; +} + +static const char * const iname[] = { + [EM28XX_VMUX_COMPOSITE] = "Composite", + [EM28XX_VMUX_SVIDEO] = "S-Video", + [EM28XX_VMUX_TELEVISION] = "Television", + [EM28XX_RADIO] = "Radio", +}; + +static void em28xx_v4l2_create_entities(struct em28xx *dev) +{ +#if defined(CONFIG_MEDIA_CONTROLLER) + struct em28xx_v4l2 *v4l2 = dev->v4l2; + int ret, i; + + /* Initialize Video, VBI and Radio pads */ + v4l2->video_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad); + if (ret < 0) + pr_err("failed to initialize video media entity!\n"); + + if (em28xx_vbi_supported(dev)) { + v4l2->vbi_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&v4l2->vbi_dev.entity, 1, + &v4l2->vbi_pad); + if (ret < 0) + pr_err("failed to initialize vbi media entity!\n"); + } + + /* Webcams don't have input connectors */ + if (dev->board.is_webcam) + return; + + /* Create entities for each input connector */ + for (i = 0; i < MAX_EM28XX_INPUT; i++) { + struct media_entity *ent = &dev->input_ent[i]; + + if (!INPUT(i)->type) + break; + + ent->name = iname[INPUT(i)->type]; + ent->flags = MEDIA_ENT_FL_CONNECTOR; + dev->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + switch (INPUT(i)->type) { + case EM28XX_VMUX_COMPOSITE: + ent->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case EM28XX_VMUX_SVIDEO: + ent->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + default: /* EM28XX_VMUX_TELEVISION or EM28XX_RADIO */ + ent->function = MEDIA_ENT_F_CONN_RF; + break; + } + + ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]); + if (ret < 0) + pr_err("failed to initialize input pad[%d]!\n", i); + + ret = media_device_register_entity(dev->media_dev, ent); + if (ret < 0) + pr_err("failed to register input entity %d!\n", i); + } +#endif +} + + /* ------------------------------------------------------------------ Videobuf2 operations ------------------------------------------------------------------*/ @@ -883,6 +1152,9 @@ static int queue_setup(struct vb2_queue *vq, return sizes[0] < size ? -EINVAL : 0; *nplanes = 1; sizes[0] = size; + + em28xx_enable_analog_tuner(dev); + return 0; } @@ -1453,13 +1725,6 @@ static int vidioc_s_parm(struct file *file, void *priv, 0, video, s_parm, p); } -static const char * const iname[] = { - [EM28XX_VMUX_COMPOSITE] = "Composite", - [EM28XX_VMUX_SVIDEO] = "S-Video", - [EM28XX_VMUX_TELEVISION] = "Television", - [EM28XX_RADIO] = "Radio", -}; - static int vidioc_enum_input(struct file *file, void *priv, struct v4l2_input *i) { @@ -1974,6 +2239,8 @@ static int em28xx_v4l2_fini(struct em28xx *dev) em28xx_uninit_usb_xfer(dev, EM28XX_ANALOG_MODE); + em28xx_v4l2_media_release(dev); + if (video_is_registered(&v4l2->radio_dev)) { em28xx_info("V4L2 device %s deregistered\n", video_device_node_name(&v4l2->radio_dev)); @@ -2297,6 +2564,9 @@ static int em28xx_v4l2_init(struct em28xx *dev) v4l2->dev = dev; dev->v4l2 = v4l2; +#ifdef CONFIG_MEDIA_CONTROLLER + v4l2->v4l2_dev.mdev = dev->media_dev; +#endif ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev); if (ret < 0) { em28xx_errdev("Call to v4l2_device_register() failed!\n"); @@ -2569,6 +2839,16 @@ static int em28xx_v4l2_init(struct em28xx *dev) video_device_node_name(&v4l2->radio_dev)); } + /* Init entities at the Media Controller */ + em28xx_v4l2_create_entities(dev); + + ret = em28xx_v4l2_create_media_graph(dev); + if (ret) { + em28xx_errdev("failed to create media graph\n"); + em28xx_v4l2_media_release(dev); + goto unregister_dev; + } + em28xx_info("V4L2 video device registered as %s\n", video_device_node_name(&v4l2->vdev)); diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index b23bf6a64011..267444961775 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -26,7 +26,7 @@ #ifndef _EM28XX_H #define _EM28XX_H -#define EM28XX_VERSION "0.2.1" +#define EM28XX_VERSION "0.2.2" #define DRIVER_DESC "Empia em28xx device driver" #include @@ -552,6 +552,11 @@ struct em28xx_v4l2 { bool top_field; int vbi_read; unsigned int field_count; + +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_pad video_pad, vbi_pad; + struct media_entity *decoder; +#endif }; struct em28xx_audio { @@ -712,6 +717,12 @@ struct em28xx { /* Snapshot button input device */ char snapshot_button_path[30]; /* path of the input dev */ struct input_dev *sbutton_input_dev; + +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device *media_dev; + struct media_entity input_ent[MAX_EM28XX_INPUT]; + struct media_pad input_pad[MAX_EM28XX_INPUT]; +#endif }; #define kref_to_dev(d) container_of(d, struct em28xx, ref) -- cgit From 242c5033508991221d787043b734740770c850be Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 6 Dec 2015 13:34:26 -0200 Subject: [media] constify stv6110x_devctl structure The stv6110x_devctl structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/stv6110x.c | 4 ++-- drivers/media/dvb-frontends/stv6110x.h | 4 ++-- drivers/media/dvb-frontends/stv6110x_priv.h | 2 +- drivers/media/pci/ddbridge/ddbridge-core.c | 2 +- drivers/media/pci/ngene/ngene-cards.c | 2 +- drivers/media/pci/ttpci/budget.c | 4 ++-- drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c | 2 +- drivers/media/usb/dvb-usb/technisat-usb2.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c index e66154e5c1d7..a62c01e454f5 100644 --- a/drivers/media/dvb-frontends/stv6110x.c +++ b/drivers/media/dvb-frontends/stv6110x.c @@ -355,7 +355,7 @@ static struct dvb_tuner_ops stv6110x_ops = { .release = stv6110x_release }; -static struct stv6110x_devctl stv6110x_ctl = { +static const struct stv6110x_devctl stv6110x_ctl = { .tuner_init = stv6110x_init, .tuner_sleep = stv6110x_sleep, .tuner_set_mode = stv6110x_set_mode, @@ -369,7 +369,7 @@ static struct stv6110x_devctl stv6110x_ctl = { .tuner_get_status = stv6110x_get_status, }; -struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c) { diff --git a/drivers/media/dvb-frontends/stv6110x.h b/drivers/media/dvb-frontends/stv6110x.h index 9f7eb251aec3..696b6e5b9e7b 100644 --- a/drivers/media/dvb-frontends/stv6110x.h +++ b/drivers/media/dvb-frontends/stv6110x.h @@ -55,12 +55,12 @@ struct stv6110x_devctl { #if IS_REACHABLE(CONFIG_DVB_STV6110x) -extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +extern const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c); #else -static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, +static inline const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_config *config, struct i2c_adapter *i2c) { diff --git a/drivers/media/dvb-frontends/stv6110x_priv.h b/drivers/media/dvb-frontends/stv6110x_priv.h index 0ec936a660a7..a993aba27b7e 100644 --- a/drivers/media/dvb-frontends/stv6110x_priv.h +++ b/drivers/media/dvb-frontends/stv6110x_priv.h @@ -70,7 +70,7 @@ struct stv6110x_state { const struct stv6110x_config *config; u8 regs[8]; - struct stv6110x_devctl *devctl; + const struct stv6110x_devctl *devctl; }; #endif /* __STV6110x_PRIV_H */ diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 9d5b314142f1..6e995ef8c37e 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -690,7 +690,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; struct stv6110x_config *tunerconf = (input->nr & 1) ? &stv6110b : &stv6110a; - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); if (!ctl) { diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c index 039bed3cc919..4e783a68bf4a 100644 --- a/drivers/media/pci/ngene/ngene-cards.c +++ b/drivers/media/pci/ngene/ngene-cards.c @@ -57,7 +57,7 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) chan->dev->card_info->fe_config[chan->number]; struct stv6110x_config *tunerconf = (struct stv6110x_config *) chan->dev->card_info->tuner_config[chan->number]; - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; /* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */ if (chan->number < 2) diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index de54310a2660..9f48100227f1 100644 --- a/drivers/media/pci/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -644,7 +644,7 @@ static void frontend_init(struct budget *budget) } case 0x101c: { /* TT S2-1600 */ - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); msleep(50); saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); @@ -697,7 +697,7 @@ static void frontend_init(struct budget *budget) break; case 0x1020: { /* Omicom S2 */ - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO); msleep(50); saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI); diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c index 69d7fe4471c2..2c0015b1264d 100644 --- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c +++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c @@ -118,7 +118,7 @@ int c8sectpfe_frontend_attach(struct dvb_frontend **fe, struct channel_info *tsin, int chan_num) { struct tda18212_config *tda18212; - struct stv6110x_devctl *fe2; + const struct stv6110x_devctl *fe2; struct i2c_client *client; struct i2c_board_info tda18212_info = { .type = "tda18212", diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index 6c3c47722955..51487d2f7764 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -512,7 +512,7 @@ static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a) &a->dev->i2c_adap, STV090x_DEMODULATOR_0); if (a->fe_adap[0].fe) { - struct stv6110x_devctl *ctl; + const struct stv6110x_devctl *ctl; ctl = dvb_attach(stv6110x_attach, a->fe_adap[0].fe, -- cgit From f691ba9864ad0ed1bd67ad27ed95ed2dce6e15e2 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 6 Dec 2015 13:51:38 -0200 Subject: [media] drivers/media/usb/as102: constify as102_priv_ops_t structure The as102_priv_ops_t structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/as102/as102_drv.h | 2 +- drivers/media/usb/as102/as102_usb_drv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/usb/as102/as102_drv.h b/drivers/media/usb/as102/as102_drv.h index aee2d76e8dfc..8def19d9ab92 100644 --- a/drivers/media/usb/as102/as102_drv.h +++ b/drivers/media/usb/as102/as102_drv.h @@ -52,7 +52,7 @@ struct as10x_bus_adapter_t { struct as10x_cmd_t *cmd, *rsp; /* bus adapter private ops callback */ - struct as102_priv_ops_t *ops; + const struct as102_priv_ops_t *ops; }; struct as102_dev_t { diff --git a/drivers/media/usb/as102/as102_usb_drv.c b/drivers/media/usb/as102/as102_usb_drv.c index 3f669066ccf6..0e8030c071b8 100644 --- a/drivers/media/usb/as102/as102_usb_drv.c +++ b/drivers/media/usb/as102/as102_usb_drv.c @@ -189,7 +189,7 @@ static int as102_read_ep2(struct as10x_bus_adapter_t *bus_adap, return actual_len; } -static struct as102_priv_ops_t as102_priv_ops = { +static const struct as102_priv_ops_t as102_priv_ops = { .upload_fw_pkt = as102_send_ep1, .xfer_cmd = as102_usb_xfer_cmd, .as102_read_ep2 = as102_read_ep2, -- cgit From 9637b03251dea31d99c0742932b9fcbfa015e5f0 Mon Sep 17 00:00:00 2001 From: "Wu, Xia" Date: Wed, 9 Dec 2015 05:26:26 -0200 Subject: [media] media: videobuf2-core: Fix one __qbuf_dmabuf() error path Add dma_buf_put() to decrease refcount of the dmabuf in error path if DMABUF size is smaller than the requirement. Signed-off-by: wu xia Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index c5d49d7a0d76..ec5b78ee6e72 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -1220,6 +1220,7 @@ static int __qbuf_dmabuf(struct vb2_buffer *vb, const void *pb) if (planes[plane].length < vb->planes[plane].min_length) { dprintk(1, "invalid dmabuf length for plane %d\n", plane); + dma_buf_put(dbuf); ret = -EINVAL; goto err; } -- cgit From 2874bf3ec453f50cfe1f7bf000efdadeb6f30db6 Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Thu, 10 Dec 2015 12:00:31 -0200 Subject: [media] tc358743: Print timings only when debug level is set Prevent unnecessary kernel log spamming. Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 3397eb99c67b..0325f7ed45d9 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -859,15 +859,16 @@ static void tc358743_format_change(struct v4l2_subdev *sd) if (tc358743_get_detected_timings(sd, &timings)) { enable_stream(sd, false); - v4l2_dbg(1, debug, sd, "%s: Format changed. No signal\n", + v4l2_dbg(1, debug, sd, "%s: No signal\n", __func__); } else { if (!v4l2_match_dv_timings(&state->timings, &timings, 0, false)) enable_stream(sd, false); - v4l2_print_dv_timings(sd->name, - "tc358743_format_change: Format changed. New format: ", - &timings, false); + if (debug) + v4l2_print_dv_timings(sd->name, + "tc358743_format_change: New format: ", + &timings, false); } if (sd->devnode) -- cgit From ff880348e74e0fd1196ab39ec765f5fd330ed3c6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 11 Dec 2015 14:16:48 -0200 Subject: [media] go7007: constify go7007_hpi_ops structures The go7007_hpi_ops structures are never modified, so declare them as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-go7007.c | 2 +- drivers/media/usb/go7007/go7007-priv.h | 2 +- drivers/media/usb/go7007/go7007-usb.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-go7007.c b/drivers/media/pci/saa7134/saa7134-go7007.c index 8a2abb34186b..2799538e2d7e 100644 --- a/drivers/media/pci/saa7134/saa7134-go7007.c +++ b/drivers/media/pci/saa7134/saa7134-go7007.c @@ -378,7 +378,7 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len) return 0; } -static struct go7007_hpi_ops saa7134_go7007_hpi_ops = { +static const struct go7007_hpi_ops saa7134_go7007_hpi_ops = { .interface_reset = saa7134_go7007_interface_reset, .write_interrupt = saa7134_go7007_write_interrupt, .read_interrupt = saa7134_go7007_read_interrupt, diff --git a/drivers/media/usb/go7007/go7007-priv.h b/drivers/media/usb/go7007/go7007-priv.h index 745185eb060b..bebee8ca9981 100644 --- a/drivers/media/usb/go7007/go7007-priv.h +++ b/drivers/media/usb/go7007/go7007-priv.h @@ -250,7 +250,7 @@ struct go7007 { struct i2c_adapter i2c_adapter; /* HPI driver */ - struct go7007_hpi_ops *hpi_ops; + const struct go7007_hpi_ops *hpi_ops; void *hpi_context; int interrupt_available; wait_queue_head_t interrupt_waitq; diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c index 3dbf14c85c5c..14d3f8c1ce4a 100644 --- a/drivers/media/usb/go7007/go7007-usb.c +++ b/drivers/media/usb/go7007/go7007-usb.c @@ -932,7 +932,7 @@ static void go7007_usb_release(struct go7007 *go) kfree(go->hpi_context); } -static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { +static const struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { .interface_reset = go7007_usb_interface_reset, .write_interrupt = go7007_usb_ezusb_write_interrupt, .read_interrupt = go7007_usb_read_interrupt, @@ -942,7 +942,7 @@ static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { .release = go7007_usb_release, }; -static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { +static const struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { .interface_reset = go7007_usb_interface_reset, .write_interrupt = go7007_usb_onboard_write_interrupt, .read_interrupt = go7007_usb_read_interrupt, -- cgit From 9f1830206d5e2c6fc85185de4d22c5188ff00232 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 14 Dec 2015 08:17:00 -0200 Subject: [media] saa7134: add DMABUF support Since saa7134 is now using vb2, there is no reason why we can't support dmabuf for this driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/saa7134/saa7134-empress.c | 3 ++- drivers/media/pci/saa7134/saa7134-video.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 56b932c97196..ca417a454d67 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -189,6 +189,7 @@ static const struct v4l2_ioctl_ops ts_ioctl_ops = { .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_streamon = vb2_ioctl_streamon, .vidioc_streamoff = vb2_ioctl_streamoff, .vidioc_g_frequency = saa7134_g_frequency, @@ -286,7 +287,7 @@ static int empress_init(struct saa7134_dev *dev) * transfers that do not start at the beginning of a page. A USERPTR * can start anywhere in a page, so USERPTR support is a no-go. */ - q->io_modes = VB2_MMAP | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; q->drv_priv = &dev->ts_q; q->ops = &saa7134_empress_qops; q->gfp_flags = GFP_DMA32; diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index a63c1366a64e..7a42d3ae3ac9 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1906,6 +1906,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_querybuf = vb2_ioctl_querybuf, .vidioc_qbuf = vb2_ioctl_qbuf, .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_expbuf = vb2_ioctl_expbuf, .vidioc_s_std = saa7134_s_std, .vidioc_g_std = saa7134_g_std, .vidioc_querystd = saa7134_querystd, @@ -2089,7 +2090,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) * USERPTR support is a no-go unless the application knows about these * limitations and has special support for this. */ - q->io_modes = VB2_MMAP | VB2_READ; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; if (saa7134_userptr) q->io_modes |= VB2_USERPTR; q->drv_priv = &dev->video_q; -- cgit From 80fa4f07fd6d33500b26275a5405d5b49cf2ff6a Mon Sep 17 00:00:00 2001 From: Nikola Forró Date: Sun, 20 Dec 2015 09:57:17 -0200 Subject: [media] usbtv: discard redundant video fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are many dropped fields with some sources, leading to many redundant fields without counterparts. When this redundant field is odd, a new frame is pushed containing this odd field interleaved with whatever was left in the buffer, causing video artifacts. Do not push a new frame after processing every odd field, but do it only after those which come after an even field. Signed-off-by: Nikola Forró Acked-by: Lubomir Rintel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv-video.c | 33 +++++++++++++++++++-------------- drivers/media/usb/usbtv/usbtv.h | 1 + 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 4ebb33943f9a..4ecb27b2d619 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -312,20 +312,24 @@ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); usbtv->chunks_done++; - /* Last chunk in a frame, signalling an end */ - if (odd && chunk_no == usbtv->n_chunks-1) { - int size = vb2_plane_size(&buf->vb.vb2_buf, 0); - enum vb2_buffer_state state = usbtv->chunks_done == - usbtv->n_chunks ? - VB2_BUF_STATE_DONE : - VB2_BUF_STATE_ERROR; - - buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.sequence = usbtv->sequence++; - buf->vb.vb2_buf.timestamp = ktime_get_ns(); - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); - vb2_buffer_done(&buf->vb.vb2_buf, state); - list_del(&buf->list); + /* Last chunk in a field */ + if (chunk_no == usbtv->n_chunks-1) { + /* Last chunk in a frame, signalling an end */ + if (odd && !usbtv->last_odd) { + int size = vb2_plane_size(&buf->vb.vb2_buf, 0); + enum vb2_buffer_state state = usbtv->chunks_done == + usbtv->n_chunks ? + VB2_BUF_STATE_DONE : + VB2_BUF_STATE_ERROR; + + buf->vb.field = V4L2_FIELD_INTERLACED; + buf->vb.sequence = usbtv->sequence++; + buf->vb.vb2_buf.timestamp = ktime_get_ns(); + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + vb2_buffer_done(&buf->vb.vb2_buf, state); + list_del(&buf->list); + } + usbtv->last_odd = odd; } spin_unlock_irqrestore(&usbtv->buflock, flags); @@ -639,6 +643,7 @@ static int usbtv_start_streaming(struct vb2_queue *vq, unsigned int count) if (usbtv->udev == NULL) return -ENODEV; + usbtv->last_odd = 1; usbtv->sequence = 0; return usbtv_start(usbtv); } diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 19cb8bf7c4e9..161b38d5cfa0 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -95,6 +95,7 @@ struct usbtv { int width, height; int n_chunks; int iso_size; + int last_odd; unsigned int sequence; struct urb *isoc_urbs[USBTV_ISOC_TRANSFERS]; -- cgit From 03c6bdfc65f157f2de4cc98926fc26778b28b0d1 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 22 Dec 2015 13:38:04 -0200 Subject: [media] bttv-driver, usbvision-video: use to_video_device() Use to_video_device() instead of open-coding it. Signed-off-by: Geliang Tang Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 2 +- drivers/media/usb/usbvision/usbvision-video.c | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 9400e996087b..a04329adc0e5 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -186,7 +186,7 @@ MODULE_VERSION(BTTV_VERSION); static ssize_t show_card(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vfd = container_of(cd, struct video_device, dev); + struct video_device *vfd = to_video_device(cd); struct bttv *btv = video_get_drvdata(vfd); return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET); } diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index de9ff3bb8edd..7f5d6f15a49f 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -162,8 +162,7 @@ MODULE_ALIAS(DRIVER_ALIAS); static inline struct usb_usbvision *cd_to_usbvision(struct device *cd) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); return video_get_drvdata(vdev); } @@ -177,8 +176,7 @@ static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); static ssize_t show_model(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", usbvision_device_data[usbvision->dev_model].model_string); @@ -188,8 +186,7 @@ static DEVICE_ATTR(model, S_IRUGO, show_model, NULL); static ssize_t show_hue(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_HUE; @@ -203,8 +200,7 @@ static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); static ssize_t show_contrast(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_CONTRAST; @@ -218,8 +214,7 @@ static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); static ssize_t show_brightness(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_BRIGHTNESS; @@ -233,8 +228,7 @@ static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); static ssize_t show_saturation(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); struct v4l2_control ctrl; ctrl.id = V4L2_CID_SATURATION; @@ -248,8 +242,7 @@ static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); static ssize_t show_streaming(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", YES_NO(usbvision->streaming == stream_on ? 1 : 0)); @@ -259,8 +252,7 @@ static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL); static ssize_t show_compression(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%s\n", YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS)); @@ -270,8 +262,7 @@ static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL); static ssize_t show_device_bridge(struct device *cd, struct device_attribute *attr, char *buf) { - struct video_device *vdev = - container_of(cd, struct video_device, dev); + struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); return sprintf(buf, "%d\n", usbvision->bridge_type); } -- cgit From faccb05ca8fb56c140fdeb70ae599e559c01c815 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 24 Dec 2015 18:06:45 -0200 Subject: [media] stk1160: Remove redundant vb2_buf payload set Calling vb2_set_plane_payload is enough, there's no need to set the planes[] bytesused field. Remove it. Signed-off-by: Ezequiel Garcia Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/stk1160/stk1160-video.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c index 46191d5262eb..6ecb0b48423f 100644 --- a/drivers/media/usb/stk1160/stk1160-video.c +++ b/drivers/media/usb/stk1160/stk1160-video.c @@ -98,7 +98,6 @@ void stk1160_buffer_done(struct stk1160 *dev) buf->vb.sequence = dev->sequence++; buf->vb.field = V4L2_FIELD_INTERLACED; - buf->vb.vb2_buf.planes[0].bytesused = buf->bytesused; buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); -- cgit From b20b51f090f81418b4f74232a0f414b886e8ba8c Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 25 Dec 2015 15:25:16 -0200 Subject: [media] vim2m: return error if driver registration fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't hide the error code. Signed-off-by: Niklas Söderlund Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vim2m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 418113c99801..c4b5fab83666 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -1074,7 +1074,7 @@ static int __init vim2m_init(void) if (ret) platform_device_unregister(&vim2m_pdev); - return 0; + return ret; } module_init(vim2m_init); -- cgit From 490ba9c29d5b82df2bed59d6007314c03d597716 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sun, 27 Dec 2015 19:02:21 -0200 Subject: [media] bttv: Returning only value constants in two functions Return constant integer values without storing them in the local variable "err" or "rc". Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/bttv-driver.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index a04329adc0e5..2c412377507b 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -1726,22 +1726,15 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id id) struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; unsigned int i; - int err = 0; for (i = 0; i < BTTV_TVNORMS; i++) if (id & bttv_tvnorms[i].v4l2_id) break; - if (i == BTTV_TVNORMS) { - err = -EINVAL; - goto err; - } - + if (i == BTTV_TVNORMS) + return -EINVAL; btv->std = id; set_tvnorm(btv, i); - -err: - - return err; + return 0; } static int bttv_g_std(struct file *file, void *priv, v4l2_std_id *id) @@ -1770,12 +1763,9 @@ static int bttv_enum_input(struct file *file, void *priv, { struct bttv_fh *fh = priv; struct bttv *btv = fh->btv; - int rc = 0; - if (i->index >= bttv_tvcards[btv->c.type].video_inputs) { - rc = -EINVAL; - goto err; - } + if (i->index >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; i->type = V4L2_INPUT_TYPE_CAMERA; i->audioset = 0; @@ -1799,10 +1789,7 @@ static int bttv_enum_input(struct file *file, void *priv, } i->std = BTTV_NORMS; - -err: - - return rc; + return 0; } static int bttv_g_input(struct file *file, void *priv, unsigned int *i) -- cgit From 80c1bce9aa315ac70738f79afb4f7c93ae27d9fa Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 28 Dec 2015 19:52:48 -0200 Subject: [media] au0828: Refactoring for start_urb_transfer() This issue was detected by using the Coccinelle software. 1. Let us return directly if a buffer allocation failed. 2. Delete the jump label "err" then. 3. Drop the explicit initialisation for the variable "ret" at the beginning. 4. Return zero as a constant at the end. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/au0828/au0828-dvb.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c index 94363a3ba400..0e174e860614 100644 --- a/drivers/media/usb/au0828/au0828-dvb.c +++ b/drivers/media/usb/au0828/au0828-dvb.c @@ -181,7 +181,7 @@ static int stop_urb_transfer(struct au0828_dev *dev) static int start_urb_transfer(struct au0828_dev *dev) { struct urb *purb; - int i, ret = -ENOMEM; + int i, ret; dprintk(2, "%s()\n", __func__); @@ -194,7 +194,7 @@ static int start_urb_transfer(struct au0828_dev *dev) dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); if (!dev->urbs[i]) - goto err; + return -ENOMEM; purb = dev->urbs[i]; @@ -207,9 +207,10 @@ static int start_urb_transfer(struct au0828_dev *dev) if (!purb->transfer_buffer) { usb_free_urb(purb); dev->urbs[i] = NULL; + ret = -ENOMEM; pr_err("%s: failed big buffer allocation, err = %d\n", __func__, ret); - goto err; + return ret; } purb->status = -EINPROGRESS; @@ -235,10 +236,7 @@ static int start_urb_transfer(struct au0828_dev *dev) } dev->urb_streaming = true; - ret = 0; - -err: - return ret; + return 0; } static void au0828_start_transport(struct au0828_dev *dev) -- cgit From b68554cd76bfed57a3aac2fc4ac4c60478d90050 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Tue, 29 Dec 2015 08:02:43 -0200 Subject: [media] hdpvr: Refactoring for hdpvr_read() Let us return directly if the element "status" of the variable "buf" indicates "BUFSTAT_READY". A check repetition can be excluded for the variable "ret" at the end then. Signed-off-by: Markus Elfring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-video.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index 7dee22deebf3..ba7f02270c83 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -462,10 +462,8 @@ static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count, } if (wait_event_interruptible(dev->wait_data, - buf->status == BUFSTAT_READY)) { - ret = -ERESTARTSYS; - goto err; - } + buf->status == BUFSTAT_READY)) + return -ERESTARTSYS; } if (buf->status != BUFSTAT_READY) -- cgit From f8433226d1b3eb035693724dca786c4445221368 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 16:53:35 -0200 Subject: [media] cx231xx: correctly handling failed allocation Since kmalloc can be failed in memory pressure, if not properly handled, NULL dereference can be happend Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-417.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 48643b94e694..c9320d6c6131 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1382,6 +1382,8 @@ static int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) buffer_size = urb->actual_length; buffer = kmalloc(buffer_size, GFP_ATOMIC); + if (!buffer) + return -ENOMEM; memcpy(buffer, dma_q->ps_head, 3); memcpy(buffer+3, p_buffer, buffer_size-3); -- cgit From e22a3b34a1f2ee53f89aef86b15d6f677de6bdc5 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Tue, 29 Dec 2015 19:48:29 -0200 Subject: [media] usbtv: correctly handling failed allocation Since kzalloc can be failed, if not properly handled, NULL dereference could be happened. Signed-off-by: Insu Yun Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbtv/usbtv-video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index 4ecb27b2d619..f6cfad46547e 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -393,6 +393,10 @@ static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv) ip->transfer_flags = URB_ISO_ASAP; ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS, GFP_KERNEL); + if (!ip->transfer_buffer) { + usb_free_urb(ip); + return NULL; + } ip->complete = usbtv_iso_cb; ip->number_of_packets = USBTV_ISOC_PACKETS; ip->transfer_buffer_length = size * USBTV_ISOC_PACKETS; -- cgit From d99e1bd175f4291ddb6e62b22bb5bdbe3976389a Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Mon, 25 Jan 2016 20:41:46 +0100 Subject: x86/entry/traps: Refactor preemption and interrupt flag handling Make the preemption and interrupt flag handling more readable by removing preempt_conditional_sti() and preempt_conditional_cli() helpers and using preempt_disable() and preempt_enable_no_resched() instead. Rename contitional_sti() and conditional_cli() to the more understandable cond_local_irq_enable() and cond_local_irq_disable() respectively, while at it. Suggested-by: Borislav Petkov Signed-off-by: Alexander Kuleshov [ Boris: massage text. ] Signed-off-by: Borislav Petkov Acked-by: Thomas Gleixner Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: H Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Tony Luck Cc: Wang Nan Link: http://lkml.kernel.org/r/1453750913-4781-2-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/traps.c | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ade185a46b1d..410e8e2700c5 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -83,30 +83,16 @@ gate_desc idt_table[NR_VECTORS] __page_aligned_bss; DECLARE_BITMAP(used_vectors, NR_VECTORS); EXPORT_SYMBOL_GPL(used_vectors); -static inline void conditional_sti(struct pt_regs *regs) +static inline void cond_local_irq_enable(struct pt_regs *regs) { if (regs->flags & X86_EFLAGS_IF) local_irq_enable(); } -static inline void preempt_conditional_sti(struct pt_regs *regs) -{ - preempt_count_inc(); - if (regs->flags & X86_EFLAGS_IF) - local_irq_enable(); -} - -static inline void conditional_cli(struct pt_regs *regs) -{ - if (regs->flags & X86_EFLAGS_IF) - local_irq_disable(); -} - -static inline void preempt_conditional_cli(struct pt_regs *regs) +static inline void cond_local_irq_disable(struct pt_regs *regs) { if (regs->flags & X86_EFLAGS_IF) local_irq_disable(); - preempt_count_dec(); } void ist_enter(struct pt_regs *regs) @@ -286,7 +272,7 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str, if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) != NOTIFY_STOP) { - conditional_sti(regs); + cond_local_irq_enable(regs); do_trap(trapnr, signr, str, regs, error_code, fill_trap_info(regs, signr, trapnr, &info)); } @@ -368,7 +354,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) if (notify_die(DIE_TRAP, "bounds", regs, error_code, X86_TRAP_BR, SIGSEGV) == NOTIFY_STOP) return; - conditional_sti(regs); + cond_local_irq_enable(regs); if (!user_mode(regs)) die("bounds", regs, error_code); @@ -443,7 +429,7 @@ do_general_protection(struct pt_regs *regs, long error_code) struct task_struct *tsk; RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU"); - conditional_sti(regs); + cond_local_irq_enable(regs); if (v8086_mode(regs)) { local_irq_enable(); @@ -517,9 +503,11 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) * as we may switch to the interrupt stack. */ debug_stack_usage_inc(); - preempt_conditional_sti(regs); + preempt_disable(); + cond_local_irq_enable(regs); do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); - preempt_conditional_cli(regs); + cond_local_irq_disable(regs); + preempt_enable_no_resched(); debug_stack_usage_dec(); exit: ist_exit(regs); @@ -648,12 +636,14 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) debug_stack_usage_inc(); /* It's safe to allow irq's after DR6 has been saved */ - preempt_conditional_sti(regs); + preempt_disable(); + cond_local_irq_enable(regs); if (v8086_mode(regs)) { handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, X86_TRAP_DB); - preempt_conditional_cli(regs); + cond_local_irq_disable(regs); + preempt_enable_no_resched(); debug_stack_usage_dec(); goto exit; } @@ -673,7 +663,8 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) si_code = get_si_code(tsk->thread.debugreg6); if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) send_sigtrap(tsk, regs, error_code, si_code); - preempt_conditional_cli(regs); + cond_local_irq_disable(regs); + preempt_enable_no_resched(); debug_stack_usage_dec(); exit: @@ -696,7 +687,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP) return; - conditional_sti(regs); + cond_local_irq_enable(regs); if (!user_mode(regs)) { if (!fixup_exception(regs)) { @@ -743,7 +734,7 @@ do_simd_coprocessor_error(struct pt_regs *regs, long error_code) dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) { - conditional_sti(regs); + cond_local_irq_enable(regs); } dotraplinkage void @@ -756,7 +747,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) if (read_cr0() & X86_CR0_EM) { struct math_emu_info info = { }; - conditional_sti(regs); + cond_local_irq_enable(regs); info.regs = regs; math_emulate(&info); @@ -765,7 +756,7 @@ do_device_not_available(struct pt_regs *regs, long error_code) #endif fpu__restore(¤t->thread.fpu); /* interrupts still off */ #ifdef CONFIG_X86_32 - conditional_sti(regs); + cond_local_irq_enable(regs); #endif } NOKPROBE_SYMBOL(do_device_not_available); -- cgit From 16aaa53756501914a863ae7a15fcb070dc27c3d7 Mon Sep 17 00:00:00 2001 From: Huaitong Han Date: Mon, 25 Jan 2016 20:41:47 +0100 Subject: x86/cpufeature: Use enum cpuid_leafs instead of magic numbers Most of the magic numbers in x86_capability[] have been converted to 'enum cpuid_leafs', and this patch updates the remaining part. Signed-off-by: Huaitong Han Signed-off-by: Borislav Petkov Cc: Alexander Kuleshov Cc: Andrew Morton Cc: Andy Lutomirski Cc: Boris Ostrovsky Cc: Borislav Petkov Cc: Brian Gerst Cc: David Vrabel Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Hector Marco-Gisbert Cc: Jiang Liu Cc: Kees Cook Cc: Konrad Rzeszutek Wilk Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Rusty Russell Cc: Thomas Gleixner Cc: Tony Luck Cc: Viresh Kumar Cc: lguest@lists.ozlabs.org Cc: xen-devel@lists.xenproject.org Link: http://lkml.kernel.org/r/1453750913-4781-3-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/elf.h | 2 +- arch/x86/kernel/mpparse.c | 2 +- arch/x86/lguest/boot.c | 2 +- arch/x86/xen/enlighten.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 1514753fd435..15340e36ddcb 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -256,7 +256,7 @@ extern int force_personality32; instruction set this CPU supports. This could be done in user space, but it's not easy, and we've already done it here. */ -#define ELF_HWCAP (boot_cpu_data.x86_capability[0]) +#define ELF_HWCAP (boot_cpu_data.x86_capability[CPUID_1_EDX]) /* This yields a string that ld.so will use to load implementation specific libraries for optimization. This is more specific in diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 30ca7607cbbb..97340f2c437c 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -408,7 +408,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) processor.cpuflag = CPU_ENABLED; processor.cpufeature = (boot_cpu_data.x86 << 8) | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; - processor.featureflag = boot_cpu_data.x86_capability[0]; + processor.featureflag = boot_cpu_data.x86_capability[CPUID_1_EDX]; processor.reserved[0] = 0; processor.reserved[1] = 0; for (i = 0; i < 2; i++) { diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 4ba229ac3f4f..a9033ae13369 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1535,7 +1535,7 @@ __init void lguest_init(void) */ cpu_detect(&new_cpu_data); /* head.S usually sets up the first capability word, so do it here. */ - new_cpu_data.x86_capability[0] = cpuid_edx(1); + new_cpu_data.x86_capability[CPUID_1_EDX] = cpuid_edx(1); /* Math is always hard! */ set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index d09e4c9d7cc5..2c261082eadf 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1654,7 +1654,7 @@ asmlinkage __visible void __init xen_start_kernel(void) cpu_detect(&new_cpu_data); set_cpu_cap(&new_cpu_data, X86_FEATURE_FPU); new_cpu_data.wp_works_ok = 1; - new_cpu_data.x86_capability[0] = cpuid_edx(1); + new_cpu_data.x86_capability[CPUID_1_EDX] = cpuid_edx(1); #endif if (xen_start_info->mod_start) { -- cgit From bfbe0eeb769e2aff2cb1fc6845c4e4b7eac40bb3 Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Mon, 25 Jan 2016 20:41:48 +0100 Subject: x86/mce: Fix order of AMD MCE init function call In mce_amd_feature_init() we take decisions based on mce_flags being set or not. So the feature detection using CPUID should naturally be ordered before we call mce_amd_feature_init(). Fix that here. Signed-off-by: Aravind Gopalakrishnan Signed-off-by: Borislav Petkov Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1453750913-4781-4-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index a006f4cd792b..b7180801ea33 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1617,10 +1617,10 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) case X86_VENDOR_AMD: { u32 ebx = cpuid_ebx(0x80000007); - mce_amd_feature_init(c); mce_flags.overflow_recov = !!(ebx & BIT(0)); mce_flags.succor = !!(ebx & BIT(1)); mce_flags.smca = !!(ebx & BIT(3)); + mce_amd_feature_init(c); break; } -- cgit From 284b965c146f482b4a411133f62288d52b7e3a72 Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Mon, 25 Jan 2016 20:41:49 +0100 Subject: x86/mce/AMD: Do not perform shared bank check for future processors Fam17h and above should not require a check to see if a bank is shared or not. For shared banks, there will always be only one core that has visibility over the MSRs and only that particular core will be allowed to write to the MSRs. Fix the code to return early if we have Scalable MCA support. No change in functionality for earlier processors. Signed-off-by: Aravind Gopalakrishnan Signed-off-by: Fengguang Wu [ Massaged the changelog text, fixed kbuild test robot build warning. ] Signed-off-by: Borislav Petkov Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1453750913-4781-5-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index e99b15077e94..3068ce25dfa1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -84,6 +84,13 @@ struct thresh_restart { static inline bool is_shared_bank(int bank) { + /* + * Scalable MCA provides for only one core to have access to the MSRs of + * a shared bank. + */ + if (mce_flags.smca) + return false; + /* Bank 4 is for northbridge reporting and is thus shared */ return (bank == 4); } -- cgit From 60f116fca162d9488f783f5014779463243ab7a2 Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Mon, 25 Jan 2016 20:41:50 +0100 Subject: x86/mce/AMD: Reduce number of blocks scanned per bank From Fam17h onwards, the number of extended MCx_MISC register blocks is reduced to 4. It is an architectural change from what we had on earlier processors. Although theoritically the total number of extended MCx_MISC registers was 8 in earlier processor families, in practice we only had to use the extra registers for MC4. And only 2 of those were used. So this change does not affect older processors. Tested on Fam10h and Fam15h systems. Signed-off-by: Aravind Gopalakrishnan Signed-off-by: Borislav Petkov Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1453750913-4781-6-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 3068ce25dfa1..5982227990c9 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -28,7 +28,7 @@ #include #include -#define NR_BLOCKS 9 +#define NR_BLOCKS 5 #define THRESHOLD_MAX 0xFFF #define INT_TYPE_APIC 0x00020000 #define MASK_VALID_HI 0x80000000 -- cgit From f57a1f3c14b9182f1fea667f5a38a1094699db7c Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Mon, 25 Jan 2016 20:41:51 +0100 Subject: x86/mce/AMD: Fix LVT offset configuration for thresholding For processor families with the Scalable MCA feature, the LVT offset for threshold interrupts is configured only in MSR 0xC0000410 and not in each per bank MISC register as was done in earlier families. Obtain the LVT offset from the correct MSR for those families. Signed-off-by: Aravind Gopalakrishnan Signed-off-by: Borislav Petkov Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1453750913-4781-7-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 5982227990c9..a77a4521976a 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -49,6 +49,11 @@ #define DEF_LVT_OFF 0x2 #define DEF_INT_TYPE_APIC 0x2 +/* Scalable MCA: */ + +/* Threshold LVT offset is at MSR0xC0000410[15:12] */ +#define SMCA_THR_LVT_OFF 0xF000 + static const char * const th_names[] = { "load_store", "insn_fetch", @@ -142,6 +147,14 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) } if (apic != msr) { + /* + * On SMCA CPUs, LVT offset is programmed at a different MSR, and + * the BIOS provides the value. The original field where LVT offset + * was set is reserved. Return early here: + */ + if (mce_flags.smca) + return 0; + pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d " "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu, apic, b->bank, b->block, b->address, hi, lo); @@ -300,7 +313,19 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) goto init; b.interrupt_enable = 1; - new = (high & MASK_LVTOFF_HI) >> 20; + + if (mce_flags.smca) { + u32 smca_low, smca_high; + + /* Gather LVT offset for thresholding: */ + if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high)) + break; + + new = (smca_low & SMCA_THR_LVT_OFF) >> 12; + } else { + new = (high & MASK_LVTOFF_HI) >> 20; + } + offset = setup_APIC_mce_threshold(offset, new); if ((offset == new) && -- cgit From 429893b16d35d309ed6b35136aad5f908a08d9b9 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 25 Jan 2016 20:41:52 +0100 Subject: x86/mce/AMD: Carve out threshold block preparation mce_amd_feature_init() was getting pretty fat, carve out the threshold_block setup into a separate function in order to simplify flow and make it more understandable. No functionality change. Signed-off-by: Borislav Petkov Cc: Aravind Gopalakrishnan Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Link: http://lkml.kernel.org/r/1453750913-4781-8-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 87 ++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index a77a4521976a..f2860a118b71 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -267,14 +267,59 @@ static void deferred_error_interrupt_enable(struct cpuinfo_x86 *c) wrmsr(MSR_CU_DEF_ERR, low, high); } +static int +prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, + int offset, u32 misc_high) +{ + unsigned int cpu = smp_processor_id(); + struct threshold_block b; + int new; + + if (!block) + per_cpu(bank_map, cpu) |= (1 << bank); + + memset(&b, 0, sizeof(b)); + b.cpu = cpu; + b.bank = bank; + b.block = block; + b.address = addr; + b.interrupt_capable = lvt_interrupt_supported(bank, misc_high); + + if (!b.interrupt_capable) + goto done; + + b.interrupt_enable = 1; + + if (mce_flags.smca) { + u32 smca_low, smca_high; + + /* Gather LVT offset for thresholding: */ + if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high)) + goto out; + + new = (smca_low & SMCA_THR_LVT_OFF) >> 12; + } else { + new = (misc_high & MASK_LVTOFF_HI) >> 20; + } + + offset = setup_APIC_mce_threshold(offset, new); + + if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt)) + mce_threshold_vector = amd_threshold_interrupt; + +done: + mce_threshold_block_init(&b, offset); + +out: + return offset; +} + /* cpu init entry point, called from mce.c with preempt off */ void mce_amd_feature_init(struct cpuinfo_x86 *c) { - struct threshold_block b; - unsigned int cpu = smp_processor_id(); u32 low = 0, high = 0, address = 0; unsigned int bank, block; - int offset = -1, new; + int offset = -1; for (bank = 0; bank < mca_cfg.banks; ++bank) { for (block = 0; block < NR_BLOCKS; ++block) { @@ -299,41 +344,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) (high & MASK_LOCKED_HI)) continue; - if (!block) - per_cpu(bank_map, cpu) |= (1 << bank); - - memset(&b, 0, sizeof(b)); - b.cpu = cpu; - b.bank = bank; - b.block = block; - b.address = address; - b.interrupt_capable = lvt_interrupt_supported(bank, high); - - if (!b.interrupt_capable) - goto init; - - b.interrupt_enable = 1; - - if (mce_flags.smca) { - u32 smca_low, smca_high; - - /* Gather LVT offset for thresholding: */ - if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high)) - break; - - new = (smca_low & SMCA_THR_LVT_OFF) >> 12; - } else { - new = (high & MASK_LVTOFF_HI) >> 20; - } - - offset = setup_APIC_mce_threshold(offset, new); - - if ((offset == new) && - (mce_threshold_vector != amd_threshold_interrupt)) - mce_threshold_vector = amd_threshold_interrupt; - -init: - mce_threshold_block_init(&b, offset); + offset = prepare_threshold_block(bank, block, address, offset, high); } } -- cgit From e6c8f1873be8a14c7e44202df1f7e6ea61bf3352 Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Mon, 25 Jan 2016 20:41:53 +0100 Subject: x86/mce/AMD: Set MCAX Enable bit It is required for the OS to acknowledge that it is using the MCAX register set and its associated fields by setting the 'McaXEnable' bit in each bank's MCi_CONFIG register. If it is not set, then all UC errors will cause a system panic. Signed-off-by: Aravind Gopalakrishnan Signed-off-by: Borislav Petkov Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Tony Luck Cc: linux-edac Link: http://lkml.kernel.org/r/1453750913-4781-9-git-send-email-bp@alien8.de Signed-off-by: Ingo Molnar --- arch/x86/include/asm/msr-index.h | 4 ++++ arch/x86/kernel/cpu/mcheck/mce_amd.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index b05402ef3b84..552346598dab 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -264,6 +264,10 @@ #define MSR_IA32_MC0_CTL2 0x00000280 #define MSR_IA32_MCx_CTL2(x) (MSR_IA32_MC0_CTL2 + (x)) +/* 'SMCA': AMD64 Scalable MCA */ +#define MSR_AMD64_SMCA_MC0_CONFIG 0xc0002004 +#define MSR_AMD64_SMCA_MCx_CONFIG(x) (MSR_AMD64_SMCA_MC0_CONFIG + 0x10*(x)) + #define MSR_P6_PERFCTR0 0x000000c1 #define MSR_P6_PERFCTR1 0x000000c2 #define MSR_P6_EVNTSEL0 0x00000186 diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index f2860a118b71..88de27bd5797 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -54,6 +54,14 @@ /* Threshold LVT offset is at MSR0xC0000410[15:12] */ #define SMCA_THR_LVT_OFF 0xF000 +/* + * OS is required to set the MCAX bit to acknowledge that it is now using the + * new MSR ranges and new registers under each bank. It also means that the OS + * will configure deferred errors in the new MCx_CONFIG register. If the bit is + * not set, uncorrectable errors will cause a system panic. + */ +#define SMCA_MCAX_EN_OFF 0x1 + static const char * const th_names[] = { "load_store", "insn_fetch", @@ -292,6 +300,12 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, if (mce_flags.smca) { u32 smca_low, smca_high; + u32 smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank); + + if (!rdmsr_safe(smca_addr, &smca_low, &smca_high)) { + smca_high |= SMCA_MCAX_EN_OFF; + wrmsr(smca_addr, smca_low, smca_high); + } /* Gather LVT offset for thresholding: */ if (rdmsr_safe(MSR_CU_DEF_ERR, &smca_low, &smca_high)) -- cgit From 3defe84a76d5055b24e2e04b5171892fa9455566 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 09:58:14 -0200 Subject: [media] av7110: constify sp8870_config structure This sp8870_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/ttpci/av7110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index a69dc6a0752b..18d229fa65cf 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -1739,7 +1739,7 @@ static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct fir #endif } -static struct sp8870_config alps_tdlb7_config = { +static const struct sp8870_config alps_tdlb7_config = { .demod_address = 0x71, .request_firmware = alps_tdlb7_request_firmware, -- cgit From 40205163ff84277747347ad0e522a7e2152a7677 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:11:06 -0200 Subject: [media] drivers/media/usb/dvb-usb-v2: constify mxl111sf_tuner_config structure This mxl111sf_tuner_config structure is never modified, so declare it as const. There are some indentation changes to remain within 80 columns. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Reviewed-by: Michael Ira Krufky Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c | 6 +++--- drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h | 8 ++++---- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c index 444579be0b77..7d16252dbb71 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c @@ -36,7 +36,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."); struct mxl111sf_tuner_state { struct mxl111sf_state *mxl_state; - struct mxl111sf_tuner_config *cfg; + const struct mxl111sf_tuner_config *cfg; enum mxl_if_freq if_freq; @@ -489,8 +489,8 @@ static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = { }; struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg) + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg) { struct mxl111sf_tuner_state *state = NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h index e6caab21a197..509b55071218 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h @@ -63,13 +63,13 @@ struct mxl111sf_tuner_config { #if IS_ENABLED(CONFIG_DVB_USB_MXL111SF) extern struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg); + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg); #else static inline struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe, - struct mxl111sf_state *mxl_state, - struct mxl111sf_tuner_config *cfg) + struct mxl111sf_state *mxl_state, + const struct mxl111sf_tuner_config *cfg) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index e7978e4e40ea..5d676b533a3a 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -856,7 +856,7 @@ static int mxl111sf_ant_hunt(struct dvb_frontend *fe) return 0; } -static struct mxl111sf_tuner_config mxl_tuner_config = { +static const struct mxl111sf_tuner_config mxl_tuner_config = { .if_freq = MXL_IF_6_0, /* applies to external IF output, only */ .invert_spectrum = 0, .read_reg = mxl111sf_read_reg, -- cgit From 4a40c73e5b27910edafe000fcc50a905de13447f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:19:52 -0200 Subject: [media] media: bt8xx: constify or51211_config structure The or51211_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index d407244fd1bc..8aeb14cfb89c 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -458,7 +458,7 @@ static void or51211_sleep(struct dvb_frontend * fe) bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000); } -static struct or51211_config or51211_config = { +static const struct or51211_config or51211_config = { .demod_address = 0x15, .request_firmware = or51211_request_firmware, .setmode = or51211_setmode, -- cgit From 64e423d4fb7d561131a2dcc91930c401ab6bc217 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 3 Jan 2016 10:27:53 -0200 Subject: [media] media: bt8xx: constify sp887x_config structure This sp887x_config structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/bt8xx/dvb-bt8xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c index 8aeb14cfb89c..e69d338ab9be 100644 --- a/drivers/media/pci/bt8xx/dvb-bt8xx.c +++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c @@ -318,7 +318,7 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s return request_firmware(fw, name, &bt->bt->dev->dev); } -static struct sp887x_config microtune_mt7202dtf_config = { +static const struct sp887x_config microtune_mt7202dtf_config = { .demod_address = 0x70, .request_firmware = microtune_mt7202dtf_request_firmware, }; -- cgit From 74dc385cb450089b28c28be2c8a0baca296b95f9 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:30:09 -0200 Subject: [media] coda: fix first encoded frame payload During the recent vb2_buffer restructuring, the calculation of the buffer payload reported to userspace was accidentally broken for the first encoded frame, counting only the length of the headers. This patch re-adds the length of the actual frame data. Fixes: 2d7007153f0c ("[media] media: videobuf2: Restructure vb2_buffer") Reported-by: Michael Olbrich Signed-off-by: Philipp Zabel Tested-by: Jan Luebbe Cc: # for v4.4 and up Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-bit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 7d28899f89ce..6efe9d002961 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1342,7 +1342,7 @@ static void coda_finish_encode(struct coda_ctx *ctx) /* Calculate bytesused field */ if (dst_buf->sequence == 0) { - vb2_set_plane_payload(&dst_buf->vb2_buf, 0, + vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr + ctx->vpu_header_size[0] + ctx->vpu_header_size[1] + ctx->vpu_header_size[2]); -- cgit From 39de7d95f88d95a07f64b047c985fff31c006b5c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 Jan 2016 08:05:52 -0200 Subject: [media] vpx3220: signedness bug in vpx3220_fp_read() The intent was to return -1 on error and that's what the callers expect but the current code returns USHRT_MAX instead. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/vpx3220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c index 4b564f17f618..90b693f4e2ab 100644 --- a/drivers/media/i2c/vpx3220.c +++ b/drivers/media/i2c/vpx3220.c @@ -124,7 +124,7 @@ static int vpx3220_fp_write(struct v4l2_subdev *sd, u8 fpaddr, u16 data) return 0; } -static u16 vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) +static int vpx3220_fp_read(struct v4l2_subdev *sd, u16 fpaddr) { struct i2c_client *client = v4l2_get_subdevdata(sd); s16 data; -- cgit From 199964b1d080d82cc8d39a7df1ece8671ef07753 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 08:57:58 -0200 Subject: [media] staging: media: lirc: fix MODULE_PARM_DESC typo It "tx_mask" was intended instead of "tx_maxk". Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/lirc/lirc_parallel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c index 6e2edb24d9d5..68ede6c56e6d 100644 --- a/drivers/staging/media/lirc/lirc_parallel.c +++ b/drivers/staging/media/lirc/lirc_parallel.c @@ -730,7 +730,7 @@ module_param(irq, int, S_IRUGO); MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); module_param(tx_mask, int, S_IRUGO); -MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); +MODULE_PARM_DESC(tx_mask, "Transmitter mask (default: 0x01)"); module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging messages"); -- cgit From aeae69daa312246e8f03ed2f6bc792d25a531118 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 09:02:56 -0200 Subject: [media] wl128x: fix typo in MODULE_PARM_DESC The module_param() is "default_rds_buf" and the MODULE_PARM_DESC() should match. Signed-off-by: Dan Carpenter Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index ebc73b034249..3f9e6df7d837 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -68,7 +68,7 @@ MODULE_PARM_DESC(default_radio_region, "Region: 0=Europe/US, 1=Japan"); /* RDS buffer blocks */ static u32 default_rds_buf = 300; module_param(default_rds_buf, uint, 0444); -MODULE_PARM_DESC(rds_buf, "RDS buffer entries"); +MODULE_PARM_DESC(default_rds_buf, "RDS buffer entries"); /* Radio Nr */ static u32 radio_nr = -1; -- cgit From 9dd73448c6a98b1971e626627e4b020b8898a3f6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Theou Date: Fri, 8 Jan 2016 20:02:03 -0200 Subject: [media] cx231xx: Fix memory leak dma_area needs to be freed when the device is closed. Based on em23xx-audio.c Signed-off-by: Jean-Baptiste Theou Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/cx231xx/cx231xx-audio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index de4ae5eb4830..a6a9508418f8 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -499,6 +499,11 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) } dev->adev.users--; + if (substream->runtime->dma_area) { + dev_dbg(dev->dev, "freeing\n"); + vfree(substream->runtime->dma_area); + substream->runtime->dma_area = NULL; + } mutex_unlock(&dev->lock); if (dev->adev.users == 0 && dev->adev.shutdown == 1) { -- cgit From 949cf70636bfe12c160c36608d18c5f8d89d2940 Mon Sep 17 00:00:00 2001 From: Fugang Duan Date: Mon, 11 Jan 2016 05:13:35 -0200 Subject: [media] radio-si476x: add return value check to avoid dead code Dead code found on below code: si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); if (rval < 0) goto exit; si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); if (rval < 0) ====> Dead code !!! goto exit; The piece of code miss return value check after calling .si476x_radio_add_new_custom(), the patch fix it. Signed-off-by: Fugang Duan Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si476x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index 859f0c08ee05..271f725b17e8 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -1530,11 +1530,11 @@ static int si476x_radio_probe(struct platform_device *pdev) if (si476x_core_has_diversity(radio->core)) { si476x_ctrls[SI476X_IDX_DIVERSITY_MODE].def = si476x_phase_diversity_mode_to_idx(radio->core->diversity_mode); - si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); + rval = si476x_radio_add_new_custom(radio, SI476X_IDX_DIVERSITY_MODE); if (rval < 0) goto exit; - si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); + rval = si476x_radio_add_new_custom(radio, SI476X_IDX_INTERCHIP_LINK); if (rval < 0) goto exit; } -- cgit From 8e20b80344148dd8b7ec23d546e931d54810a1b7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 13 Jan 2016 11:44:41 -0200 Subject: [media] v4l2-dv-timings: skip standards check for V4L2_DV_BT_CAP_CUSTOM Skip validating the standards field in v4l2_valid_dv_timings() if the V4L2_DV_BT_CAP_CUSTOM capability is set, since that implies that non-standard timings are allowed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-dv-timings.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-dv-timings.c b/drivers/media/v4l2-core/v4l2-dv-timings.c index ec258b73001a..889de0a32152 100644 --- a/drivers/media/v4l2-core/v4l2-dv-timings.c +++ b/drivers/media/v4l2-core/v4l2-dv-timings.c @@ -165,7 +165,8 @@ bool v4l2_valid_dv_timings(const struct v4l2_dv_timings *t, bt->width > cap->max_width || bt->pixelclock < cap->min_pixelclock || bt->pixelclock > cap->max_pixelclock || - (cap->standards && bt->standards && + (!(caps & V4L2_DV_BT_CAP_CUSTOM) && + cap->standards && bt->standards && !(bt->standards & cap->standards)) || (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) || (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE))) -- cgit From fcae73fac1b45053766c92f08fb3afee6d30dbbc Mon Sep 17 00:00:00 2001 From: Mats Randgaard Date: Thu, 10 Dec 2015 11:38:07 -0200 Subject: [media] tc358743: Use local array with fixed size in i2c write i2c_wr() is called from ops and the interrupt service routine, while state->wr_data is shared and unprotected, and could be overwritten. This shared buffer is therefore replaced with a local array with fixed size. The array has the size of one EDID block (128 bytes) + 2 bytes i2c address, and the EDID is written block by block (up to 8 blocks). Signed-off-by: Mats Randgaard Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tc358743.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 0325f7ed45d9..da7469bc6e56 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -59,8 +59,7 @@ MODULE_LICENSE("GPL"); #define EDID_NUM_BLOCKS_MAX 8 #define EDID_BLOCK_SIZE 128 -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE (EDID_NUM_BLOCKS_MAX * EDID_BLOCK_SIZE + 2) +#define I2C_MAX_XFER_SIZE (EDID_BLOCK_SIZE + 2) static const struct v4l2_dv_timings_cap tc358743_timings_cap = { .type = V4L2_DV_BT_656_1120, @@ -97,9 +96,6 @@ struct tc358743_state { /* edid */ u8 edid_blocks_written; - /* used by i2c_wr() */ - u8 wr_data[MAX_XFER_SIZE]; - struct v4l2_dv_timings timings; u32 mbus_fmt_code; @@ -149,13 +145,15 @@ static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) { struct tc358743_state *state = to_state(sd); struct i2c_client *client = state->i2c_client; - u8 *data = state->wr_data; int err, i; struct i2c_msg msg; + u8 data[I2C_MAX_XFER_SIZE]; - if ((2 + n) > sizeof(state->wr_data)) + if ((2 + n) > I2C_MAX_XFER_SIZE) { + n = I2C_MAX_XFER_SIZE - 2; v4l2_warn(sd, "i2c wr reg=%04x: len=%d is too big!\n", reg, 2 + n); + } msg.addr = client->addr; msg.buf = data; @@ -1582,6 +1580,7 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, { struct tc358743_state *state = to_state(sd); u16 edid_len = edid->blocks * EDID_BLOCK_SIZE; + int i; v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", __func__, edid->pad, edid->start_block, edid->blocks); @@ -1607,7 +1606,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd, return 0; } - i2c_wr(sd, EDID_RAM, edid->edid, edid_len); + for (i = 0; i < edid_len; i += EDID_BLOCK_SIZE) + i2c_wr(sd, EDID_RAM + i, edid->edid + i, EDID_BLOCK_SIZE); state->edid_blocks_written = edid->blocks; -- cgit From b7d4d2f8d8517e1b3759568ef20a88d1022598ff Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 22 Dec 2015 12:22:01 -0200 Subject: [media] media: adv7604: implement get_selection The rcar_vin driver relies on this. Signed-off-by: Ulrich Hecht Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f8dd7505b529..5d4dbd05f9d6 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -1884,6 +1884,26 @@ static int adv76xx_get_format(struct v4l2_subdev *sd, return 0; } +static int adv76xx_get_selection(struct v4l2_subdev *sd, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_selection *sel) +{ + struct adv76xx_state *state = to_state(sd); + + if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + /* Only CROP, CROP_DEFAULT and CROP_BOUNDS are supported */ + if (sel->target > V4L2_SEL_TGT_CROP_BOUNDS) + return -EINVAL; + + sel->r.left = 0; + sel->r.top = 0; + sel->r.width = state->timings.bt.width; + sel->r.height = state->timings.bt.height; + + return 0; +} + static int adv76xx_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_format *format) @@ -2404,6 +2424,7 @@ static const struct v4l2_subdev_video_ops adv76xx_video_ops = { static const struct v4l2_subdev_pad_ops adv76xx_pad_ops = { .enum_mbus_code = adv76xx_enum_mbus_code, + .get_selection = adv76xx_get_selection, .get_fmt = adv76xx_get_format, .set_fmt = adv76xx_set_format, .get_edid = adv76xx_get_edid, -- cgit From 49fe73400d94027c9402d8fc11d1f8ed1a5aeb61 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 24 Dec 2015 11:18:10 -0200 Subject: [media] DocBook media: make explicit that standard/timings never change automatically A driver might detect a new standard or DV timings, but it will never change to those new timings automatically. Instead it will send an event and let the application take care of it. Make this explicit in the documentation. Signed-off-by: Hans Verkuil Acked-by: Laurent Pinchart Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- .../DocBook/media/v4l/vidioc-query-dv-timings.xml | 14 ++++++++++++-- Documentation/DocBook/media/v4l/vidioc-querystd.xml | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml index e9c70a8f3476..0c93677d16b4 100644 --- a/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml +++ b/Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml @@ -60,9 +60,19 @@ input automatically, similar to sensing the video standard. To do so, applications call VIDIOC_QUERY_DV_TIMINGS with a pointer to a &v4l2-dv-timings;. Once the hardware detects the timings, it will fill in the -timings structure. +timings structure. -If the timings could not be detected because there was no signal, then +Please note that drivers shall not switch timings automatically +if new timings are detected. Instead, drivers should send the +V4L2_EVENT_SOURCE_CHANGE event (if they support this) and expect +that userspace will take action by calling VIDIOC_QUERY_DV_TIMINGS. +The reason is that new timings usually mean different buffer sizes as well, and you +cannot change buffer sizes on the fly. In general, applications that receive the +Source Change event will have to call VIDIOC_QUERY_DV_TIMINGS, +and if the detected timings are valid they will have to stop streaming, set the new +timings, allocate new buffers and start streaming again. + +If the timings could not be detected because there was no signal, then ENOLINK is returned. If a signal was detected, but it was unstable and the receiver could not lock to the signal, then ENOLCK is returned. If the receiver could lock to the signal, diff --git a/Documentation/DocBook/media/v4l/vidioc-querystd.xml b/Documentation/DocBook/media/v4l/vidioc-querystd.xml index 222348542182..3ceae35fab03 100644 --- a/Documentation/DocBook/media/v4l/vidioc-querystd.xml +++ b/Documentation/DocBook/media/v4l/vidioc-querystd.xml @@ -59,6 +59,16 @@ then the driver will return V4L2_STD_UNKNOWN. When detection is not possible or fails, the set must contain all standards supported by the current video input or output. +Please note that drivers shall not switch the video standard +automatically if a new video standard is detected. Instead, drivers should send the +V4L2_EVENT_SOURCE_CHANGE event (if they support this) and expect +that userspace will take action by calling VIDIOC_QUERYSTD. +The reason is that a new video standard can mean different buffer sizes as well, and you +cannot change buffer sizes on the fly. In general, applications that receive the +Source Change event will have to call VIDIOC_QUERYSTD, +and if the detected video standard is valid they will have to stop streaming, set the new +standard, allocate new buffers and start streaming again. + -- cgit From 7df5ab8774aa383c6d2bff00688d004585d96dfd Mon Sep 17 00:00:00 2001 From: Tiffany Lin Date: Tue, 19 Jan 2016 05:56:50 -0200 Subject: [media] media: v4l2-compat-ioctl32: fix missing length copy in put_v4l2_buffer32 In v4l2-compliance utility, test QUERYBUF required correct length value to go through each planar to check planar's length in multi-planar buffer type Signed-off-by: Tiffany Lin Reviewed-by: Laurent Pinchart Signed-off-by: Hans Verkuil Cc: # for v3.7 and up Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 8fd84a67478a..019644ff627d 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -415,7 +415,8 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user get_user(kp->index, &up->index) || get_user(kp->type, &up->type) || get_user(kp->flags, &up->flags) || - get_user(kp->memory, &up->memory)) + get_user(kp->memory, &up->memory) || + get_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(kp->type)) @@ -427,9 +428,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { - if (get_user(kp->length, &up->length)) - return -EFAULT; - num_planes = kp->length; if (num_planes == 0) { kp->m.planes = NULL; @@ -462,16 +460,14 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (get_user(kp->length, &up->length) || - get_user(kp->m.offset, &up->m.offset)) + if (get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: { compat_long_t tmp; - if (get_user(kp->length, &up->length) || - get_user(tmp, &up->m.userptr)) + if (get_user(tmp, &up->m.userptr)) return -EFAULT; kp->m.userptr = (unsigned long)compat_ptr(tmp); @@ -513,7 +509,8 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) || put_user(kp->sequence, &up->sequence) || put_user(kp->reserved2, &up->reserved2) || - put_user(kp->reserved, &up->reserved)) + put_user(kp->reserved, &up->reserved) || + put_user(kp->length, &up->length)) return -EFAULT; if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) { @@ -536,13 +533,11 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: - if (put_user(kp->length, &up->length) || - put_user(kp->m.offset, &up->m.offset)) + if (put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; case V4L2_MEMORY_USERPTR: - if (put_user(kp->length, &up->length) || - put_user(kp->m.userptr, &up->m.userptr)) + if (put_user(kp->m.userptr, &up->m.userptr)) return -EFAULT; break; case V4L2_MEMORY_OVERLAY: -- cgit From 3541e349e18eeacbe8e5e97ed984f018be4cfdaf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 22 Jan 2016 13:13:25 -0200 Subject: [media] vivid: fix broken Bayer text rendering Sometimes when a Bayer pixelformat is selected the rendering of the OSD text by vivid was all wrong: every other line of the text was shifted by half the width or more. It turned out that to render Bayer formats the interleaved boolean is set to true in the tpg. This mode indicates a semi-biplanar mode where two interleaved planes are used to render the frame. From outside the tpg it looks like a single plane, but internally it is two planes. However, in the tpg_s_bytesperline() function the interleaved bool wasn't checked and only the bytesperline value for plane 0 was updated. But for the interleaved mode the same value has to be copied to bytesperline[1] as well. The effect was that whatever old value was left in bytesperline[1] was used, which caused all sorts of weird and seemingly unpredictable shifts. Reported-by: Ove Brynestad Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-tpg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h index 9baed6a10334..93fbaee69675 100644 --- a/drivers/media/platform/vivid/vivid-tpg.h +++ b/drivers/media/platform/vivid/vivid-tpg.h @@ -418,6 +418,8 @@ static inline void tpg_s_bytesperline(struct tpg_data *tpg, unsigned plane, unsi tpg->bytesperline[p] = plane_w / tpg->hdownsampling[p]; } + if (tpg_g_interleaved(tpg)) + tpg->bytesperline[1] = tpg->bytesperline[0]; } -- cgit From 9f14bab72cccc0f4adb2fefde2c3c3740e7be86c Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:24 -0200 Subject: [media] media: ti-vpe: Document CAL driver Device Tree bindings for the Camera Adaptation Layer (CAL) driver Signed-off-by: Benoit Parrot Acked-by: Rob Herring Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/ti-cal.txt | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/ti-cal.txt diff --git a/Documentation/devicetree/bindings/media/ti-cal.txt b/Documentation/devicetree/bindings/media/ti-cal.txt new file mode 100644 index 000000000000..ae9b52f37576 --- /dev/null +++ b/Documentation/devicetree/bindings/media/ti-cal.txt @@ -0,0 +1,72 @@ +Texas Instruments DRA72x CAMERA ADAPTATION LAYER (CAL) +------------------------------------------------------ + +The Camera Adaptation Layer (CAL) is a key component for image capture +applications. The capture module provides the system interface and the +processing capability to connect CSI2 image-sensor modules to the +DRA72x device. + +Required properties: +- compatible: must be "ti,dra72-cal" +- reg: CAL Top level, Receiver Core #0, Receiver Core #1 and Camera RX + control address space +- reg-names: cal_top, cal_rx_core0, cal_rx_core1, and camerrx_control + registers +- interrupts: should contain IRQ line for the CAL; + +CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes +should contain a 'port' child node with child 'endpoint' node. Please +refer to the bindings defined in +Documentation/devicetree/bindings/media/video-interfaces.txt. + +Example: + cal: cal@4845b000 { + compatible = "ti,dra72-cal"; + ti,hwmods = "cal"; + reg = <0x4845B000 0x400>, + <0x4845B800 0x40>, + <0x4845B900 0x40>, + <0x4A002e94 0x4>; + reg-names = "cal_top", + "cal_rx_core0", + "cal_rx_core1", + "camerrx_control"; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + csi2_0: port@0 { + reg = <0>; + endpoint { + slave-mode; + remote-endpoint = <&ar0330_1>; + }; + }; + csi2_1: port@1 { + reg = <1>; + }; + }; + }; + + i2c5: i2c@4807c000 { + ar0330@10 { + compatible = "ti,ar0330"; + reg = <0x10>; + + port { + #address-cells = <1>; + #size-cells = <0>; + + ar0330_1: endpoint { + reg = <0>; + clock-lanes = <1>; + data-lanes = <0 2 3 4>; + remote-endpoint = <&csi2_0>; + }; + }; + }; + }; -- cgit From ccf963d3276e318fb952fffd1829ed47876bbec9 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:25 -0200 Subject: [media] MAINTAINERS: Add ti-vpe maintainer entry Signed-off-by: Benoit Parrot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..9f1a401922de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10853,6 +10853,14 @@ L: linux-omap@vger.kernel.org S: Maintained F: drivers/thermal/ti-soc-thermal/ +TI VPE/CAL DRIVERS +M: Benoit Parrot +L: linux-media@vger.kernel.org +W: http://linuxtv.org/ +Q: http://patchwork.linuxtv.org/project/linux-media/list/ +S: Maintained +F: drivers/media/platform/ti-vpe/ + TI CDCE706 CLOCK DRIVER M: Max Filippov S: Maintained -- cgit From 343e89a792a571b28b9c02850db7af2ef25ffb20 Mon Sep 17 00:00:00 2001 From: Benoit Parrot Date: Wed, 6 Jan 2016 21:37:26 -0200 Subject: [media] media: ti-vpe: Add CAL v4l2 camera capture driver The Camera Adaptation Layer (CAL) is a block which consists of a dual port CSI2/MIPI camera capture engine. Port #0 can handle CSI2 camera connected to up to 4 data lanes. Port #1 can handle CSI2 camera connected to up to 2 data lanes. The driver implements the required API/ioctls to be V4L2 compliant. Driver supports the following: - V4L2 API using DMABUF/MMAP buffer access based on videobuf2 api - Asynchronous sensor sub device registration - DT support Signed-off-by: Benoit Parrot Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/Kconfig | 12 + drivers/media/platform/Makefile | 2 + drivers/media/platform/ti-vpe/Makefile | 4 + drivers/media/platform/ti-vpe/cal.c | 1970 ++++++++++++++++++++++++++++++ drivers/media/platform/ti-vpe/cal_regs.h | 479 ++++++++ 5 files changed, 2467 insertions(+) create mode 100644 drivers/media/platform/ti-vpe/cal.c create mode 100644 drivers/media/platform/ti-vpe/cal_regs.h diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 526359447ff9..6f0f28fc4e2f 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -120,6 +120,18 @@ source "drivers/media/platform/s5p-tv/Kconfig" source "drivers/media/platform/am437x/Kconfig" source "drivers/media/platform/xilinx/Kconfig" +config VIDEO_TI_CAL + tristate "TI CAL (Camera Adaptation Layer) driver" + depends on VIDEO_DEV && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on SOC_DRA7XX || COMPILE_TEST + select VIDEOBUF2_DMA_CONTIG + default n + ---help--- + Support for the TI CAL (Camera Adaptation Layer) block + found on DRA72X SoC. + In TI Technical Reference Manual this module is referred as + Camera Interface Subsystem (CAMSS). + endif # V4L_PLATFORM_DRIVERS menuconfig V4L_MEM2MEM_DRIVERS diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile index efa0295af87b..028a7233096b 100644 --- a/drivers/media/platform/Makefile +++ b/drivers/media/platform/Makefile @@ -18,6 +18,8 @@ obj-$(CONFIG_VIDEO_VIM2M) += vim2m.o obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe/ +obj-$(CONFIG_VIDEO_TI_CAL) += ti-vpe/ + obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o obj-$(CONFIG_VIDEO_CODA) += coda/ diff --git a/drivers/media/platform/ti-vpe/Makefile b/drivers/media/platform/ti-vpe/Makefile index be680f839e77..e236059a60ad 100644 --- a/drivers/media/platform/ti-vpe/Makefile +++ b/drivers/media/platform/ti-vpe/Makefile @@ -3,3 +3,7 @@ obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o ti-vpe-y := vpe.o sc.o csc.o vpdma.o ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG + +obj-$(CONFIG_VIDEO_TI_CAL) += ti-cal.o + +ti-cal-y := cal.o diff --git a/drivers/media/platform/ti-vpe/cal.c b/drivers/media/platform/ti-vpe/cal.c new file mode 100644 index 000000000000..69ec79ba49ee --- /dev/null +++ b/drivers/media/platform/ti-vpe/cal.c @@ -0,0 +1,1970 @@ +/* + * TI CAL camera interface driver + * + * Copyright (c) 2015 Texas Instruments Inc. + * Benoit Parrot, + * + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cal_regs.h" + +#define CAL_MODULE_NAME "cal" + +#define MAX_WIDTH 1920 +#define MAX_HEIGHT 1200 + +#define CAL_VERSION "0.1.0" + +MODULE_DESCRIPTION("TI CAL driver"); +MODULE_AUTHOR("Benoit Parrot, "); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(CAL_VERSION); + +static unsigned video_nr = -1; +module_param(video_nr, uint, 0644); +MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect"); + +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +/* timeperframe: min/max and default */ +static const struct v4l2_fract + tpf_default = {.numerator = 1001, .denominator = 30000}; + +#define cal_dbg(level, caldev, fmt, arg...) \ + v4l2_dbg(level, debug, &caldev->v4l2_dev, fmt, ##arg) +#define cal_info(caldev, fmt, arg...) \ + v4l2_info(&caldev->v4l2_dev, fmt, ##arg) +#define cal_err(caldev, fmt, arg...) \ + v4l2_err(&caldev->v4l2_dev, fmt, ##arg) + +#define ctx_dbg(level, ctx, fmt, arg...) \ + v4l2_dbg(level, debug, &ctx->v4l2_dev, fmt, ##arg) +#define ctx_info(ctx, fmt, arg...) \ + v4l2_info(&ctx->v4l2_dev, fmt, ##arg) +#define ctx_err(ctx, fmt, arg...) \ + v4l2_err(&ctx->v4l2_dev, fmt, ##arg) + +#define CAL_NUM_INPUT 1 +#define CAL_NUM_CONTEXT 2 + +#define bytes_per_line(pixel, bpp) (ALIGN(pixel * bpp, 16)) + +#define reg_read(dev, offset) ioread32(dev->base + offset) +#define reg_write(dev, offset, val) iowrite32(val, dev->base + offset) + +#define reg_read_field(dev, offset, mask) get_field(reg_read(dev, offset), \ + mask) +#define reg_write_field(dev, offset, field, mask) { \ + u32 val = reg_read(dev, offset); \ + set_field(&val, field, mask); \ + reg_write(dev, offset, val); } + +/* ------------------------------------------------------------------ + * Basic structures + * ------------------------------------------------------------------ + */ + +struct cal_fmt { + u32 fourcc; + u32 code; + u8 depth; +}; + +static struct cal_fmt cal_formats[] = { + { + .fourcc = V4L2_PIX_FMT_YUYV, + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_UYVY, + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_YVYU, + .code = MEDIA_BUS_FMT_YVYU8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_VYUY, + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565, /* gggbbbbb rrrrrggg */ + .code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB565_2X8_BE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB555, /* gggbbbbb arrrrrgg */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB555X, /* arrrrrgg gggbbbbb */ + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_RGB24, /* rgb */ + .code = MEDIA_BUS_FMT_RGB888_2X12_LE, + .depth = 24, + }, { + .fourcc = V4L2_PIX_FMT_BGR24, /* bgr */ + .code = MEDIA_BUS_FMT_RGB888_2X12_BE, + .depth = 24, + }, { + .fourcc = V4L2_PIX_FMT_RGB32, /* argb */ + .code = MEDIA_BUS_FMT_ARGB8888_1X32, + .depth = 32, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG8, + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG8, + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB8, + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .depth = 8, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR10, + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG10, + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG10, + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB10, + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SBGGR12, + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGBRG12, + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SGRBG12, + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .depth = 16, + }, { + .fourcc = V4L2_PIX_FMT_SRGGB12, + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .depth = 16, + }, +}; + +/* Print Four-character-code (FOURCC) */ +static char *fourcc_to_str(u32 fmt) +{ + static char code[5]; + + code[0] = (unsigned char)(fmt & 0xff); + code[1] = (unsigned char)((fmt >> 8) & 0xff); + code[2] = (unsigned char)((fmt >> 16) & 0xff); + code[3] = (unsigned char)((fmt >> 24) & 0xff); + code[4] = '\0'; + + return code; +} + +/* buffer for one video frame */ +struct cal_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; + struct list_head list; + const struct cal_fmt *fmt; +}; + +struct cal_dmaqueue { + struct list_head active; + + /* Counters to control fps rate */ + int frame; + int ini_jiffies; +}; + +struct cm_data { + void __iomem *base; + struct resource *res; + + unsigned int camerrx_control; + + struct platform_device *pdev; +}; + +struct cc_data { + void __iomem *base; + struct resource *res; + + struct platform_device *pdev; +}; + +/* + * there is one cal_dev structure in the driver, it is shared by + * all instances. + */ +struct cal_dev { + int irq; + void __iomem *base; + struct resource *res; + struct platform_device *pdev; + struct v4l2_device v4l2_dev; + + /* Control Module handle */ + struct cm_data *cm; + /* Camera Core Module handle */ + struct cc_data *cc[CAL_NUM_CSI2_PORTS]; + + struct cal_ctx *ctx[CAL_NUM_CONTEXT]; +}; + +/* + * There is one cal_ctx structure for each camera core context. + */ +struct cal_ctx { + struct v4l2_device v4l2_dev; + struct v4l2_ctrl_handler ctrl_handler; + struct video_device vdev; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *sensor; + struct v4l2_of_endpoint endpoint; + + struct v4l2_async_subdev asd; + struct v4l2_async_subdev *asd_list[1]; + + struct v4l2_fh fh; + struct cal_dev *dev; + struct cc_data *cc; + + /* v4l2_ioctl mutex */ + struct mutex mutex; + /* v4l2 buffers lock */ + spinlock_t slock; + + /* Several counters */ + unsigned long jiffies; + + struct vb2_alloc_ctx *alloc_ctx; + struct cal_dmaqueue vidq; + + /* Input Number */ + int input; + + /* video capture */ + const struct cal_fmt *fmt; + /* Used to store current pixel format */ + struct v4l2_format v_fmt; + /* Used to store current mbus frame format */ + struct v4l2_mbus_framefmt m_fmt; + + /* Current subdev enumerated format */ + struct cal_fmt *active_fmt[ARRAY_SIZE(cal_formats)]; + int num_active_fmt; + + struct v4l2_fract timeperframe; + unsigned int sequence; + unsigned int external_rate; + struct vb2_queue vb_vidq; + unsigned int seq_count; + unsigned int csi2_port; + unsigned int virtual_channel; + + /* Pointer pointing to current v4l2_buffer */ + struct cal_buffer *cur_frm; + /* Pointer pointing to next v4l2_buffer */ + struct cal_buffer *next_frm; +}; + +static const struct cal_fmt *find_format_by_pix(struct cal_ctx *ctx, + u32 pixelformat) +{ + const struct cal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ctx->num_active_fmt; k++) { + fmt = ctx->active_fmt[k]; + if (fmt->fourcc == pixelformat) + return fmt; + } + + return NULL; +} + +static const struct cal_fmt *find_format_by_code(struct cal_ctx *ctx, + u32 code) +{ + const struct cal_fmt *fmt; + unsigned int k; + + for (k = 0; k < ctx->num_active_fmt; k++) { + fmt = ctx->active_fmt[k]; + if (fmt->code == code) + return fmt; + } + + return NULL; +} + +static inline struct cal_ctx *notifier_to_ctx(struct v4l2_async_notifier *n) +{ + return container_of(n, struct cal_ctx, notifier); +} + +static inline int get_field(u32 value, u32 mask) +{ + return (value & mask) >> __ffs(mask); +} + +static inline void set_field(u32 *valp, u32 field, u32 mask) +{ + u32 val = *valp; + + val &= ~mask; + val |= (field << __ffs(mask)) & mask; + *valp = val; +} + +/* + * Control Module block access + */ +static struct cm_data *cm_create(struct cal_dev *dev) +{ + struct platform_device *pdev = dev->pdev; + struct cm_data *cm; + + cm = devm_kzalloc(&pdev->dev, sizeof(*cm), GFP_KERNEL); + if (!cm) + return ERR_PTR(-ENOMEM); + + cm->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "camerrx_control"); + cm->base = devm_ioremap_resource(&pdev->dev, cm->res); + if (IS_ERR(cm->base)) { + cal_err(dev, "failed to ioremap\n"); + return cm->base; + } + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + cm->res->name, &cm->res->start, &cm->res->end); + + return cm; +} + +static void camerarx_phy_enable(struct cal_ctx *ctx) +{ + u32 val; + + if (!ctx->dev->cm->base) { + ctx_err(ctx, "cm not mapped\n"); + return; + } + + val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL); + if (ctx->csi2_port == 1) { + set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK); + set_field(&val, 0, CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK); + /* enable all lanes by default */ + set_field(&val, 0xf, CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK); + set_field(&val, 1, CM_CAMERRX_CTRL_CSI0_MODE_MASK); + } else if (ctx->csi2_port == 2) { + set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK); + set_field(&val, 0, CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK); + /* enable all lanes by default */ + set_field(&val, 0x3, CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK); + set_field(&val, 1, CM_CAMERRX_CTRL_CSI1_MODE_MASK); + } + reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val); +} + +static void camerarx_phy_disable(struct cal_ctx *ctx) +{ + u32 val; + + if (!ctx->dev->cm->base) { + ctx_err(ctx, "cm not mapped\n"); + return; + } + + val = reg_read(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL); + if (ctx->csi2_port == 1) + set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK); + else if (ctx->csi2_port == 2) + set_field(&val, 0x0, CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK); + reg_write(ctx->dev->cm, CM_CTRL_CORE_CAMERRX_CONTROL, val); +} + +/* + * Camera Instance access block + */ +static struct cc_data *cc_create(struct cal_dev *dev, unsigned int core) +{ + struct platform_device *pdev = dev->pdev; + struct cc_data *cc; + + cc = devm_kzalloc(&pdev->dev, sizeof(*cc), GFP_KERNEL); + if (!cc) + return ERR_PTR(-ENOMEM); + + cc->res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, + (core == 0) ? + "cal_rx_core0" : + "cal_rx_core1"); + cc->base = devm_ioremap_resource(&pdev->dev, cc->res); + if (IS_ERR(cc->base)) { + cal_err(dev, "failed to ioremap\n"); + return cc->base; + } + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + cc->res->name, &cc->res->start, &cc->res->end); + + return cc; +} + +/* + * Get Revision and HW info + */ +static void cal_get_hwinfo(struct cal_dev *dev) +{ + u32 revision = 0; + u32 hwinfo = 0; + + revision = reg_read(dev, CAL_HL_REVISION); + cal_dbg(3, dev, "CAL_HL_REVISION = 0x%08x (expecting 0x40000200)\n", + revision); + + hwinfo = reg_read(dev, CAL_HL_HWINFO); + cal_dbg(3, dev, "CAL_HL_HWINFO = 0x%08x (expecting 0xA3C90469)\n", + hwinfo); +} + +static inline int cal_runtime_get(struct cal_dev *dev) +{ + int r; + + r = pm_runtime_get_sync(&dev->pdev->dev); + + return r; +} + +static inline void cal_runtime_put(struct cal_dev *dev) +{ + pm_runtime_put_sync(&dev->pdev->dev); +} + +static void cal_quickdump_regs(struct cal_dev *dev) +{ + cal_info(dev, "CAL Registers @ 0x%pa:\n", &dev->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->base, resource_size(dev->res), false); + + if (dev->ctx[0]) { + cal_info(dev, "CSI2 Core 0 Registers @ %pa:\n", + &dev->ctx[0]->cc->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->ctx[0]->cc->base, + resource_size(dev->ctx[0]->cc->res), + false); + } + + if (dev->ctx[1]) { + cal_info(dev, "CSI2 Core 1 Registers @ %pa:\n", + &dev->ctx[1]->cc->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->ctx[1]->cc->base, + resource_size(dev->ctx[1]->cc->res), + false); + } + + cal_info(dev, "CAMERRX_Control Registers @ %pa:\n", + &dev->cm->res->start); + print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 4, + dev->cm->base, + resource_size(dev->cm->res), false); +} + +/* + * Enable the expected IRQ sources + */ +static void enable_irqs(struct cal_ctx *ctx) +{ + /* Enable IRQ_WDMA_END 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_SET(2), + CAL_HL_IRQ_ENABLE, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Enable IRQ_WDMA_START 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_SET(3), + CAL_HL_IRQ_ENABLE, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */ + reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0xFF000000); +} + +static void disable_irqs(struct cal_ctx *ctx) +{ + /* Disable IRQ_WDMA_END 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_CLR(2), + CAL_HL_IRQ_CLEAR, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Disable IRQ_WDMA_START 0/1 */ + reg_write_field(ctx->dev, + CAL_HL_IRQENABLE_CLR(3), + CAL_HL_IRQ_CLEAR, + CAL_HL_IRQ_MASK(ctx->csi2_port)); + /* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */ + reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0); +} + +static void csi2_init(struct cal_ctx *ctx) +{ + int i; + u32 val; + + val = reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port)); + set_field(&val, CAL_GEN_ENABLE, + CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK); + set_field(&val, CAL_GEN_ENABLE, + CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK); + set_field(&val, CAL_GEN_DISABLE, + CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK); + set_field(&val, 407, CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK); + reg_write(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_TIMING(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_TIMING(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); + set_field(&val, CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL, + CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK); + set_field(&val, CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON, + CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK); + reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val); + for (i = 0; i < 10; i++) { + if (reg_read_field(ctx->dev, + CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), + CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK) == + CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON) + break; + usleep_range(1000, 1100); + } + ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_CTRL); + set_field(&val, CAL_CTRL_BURSTSIZE_BURST128, CAL_CTRL_BURSTSIZE_MASK); + set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK); + set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED, + CAL_CTRL_POSTED_WRITES_MASK); + set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK); + set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK); + reg_write(ctx->dev, CAL_CTRL, val); + ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", reg_read(ctx->dev, CAL_CTRL)); +} + +static void csi2_lane_config(struct cal_ctx *ctx) +{ + u32 val = reg_read(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port)); + u32 lane_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK; + u32 polarity_mask = CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK; + struct v4l2_of_bus_mipi_csi2 *mipi_csi2 = &ctx->endpoint.bus.mipi_csi2; + int lane; + + set_field(&val, mipi_csi2->clock_lane + 1, lane_mask); + set_field(&val, mipi_csi2->lane_polarities[0], polarity_mask); + for (lane = 0; lane < mipi_csi2->num_data_lanes; lane++) { + /* + * Every lane are one nibble apart starting with the + * clock followed by the data lanes so shift masks by 4. + */ + lane_mask <<= 4; + polarity_mask <<= 4; + set_field(&val, mipi_csi2->data_lanes[lane] + 1, lane_mask); + set_field(&val, mipi_csi2->lane_polarities[lane + 1], + polarity_mask); + } + + reg_write(ctx->dev, CAL_CSI2_COMPLEXIO_CFG(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x\n", + ctx->csi2_port, val); +} + +static void csi2_ppi_enable(struct cal_ctx *ctx) +{ + reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), + CAL_GEN_ENABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK); +} + +static void csi2_ppi_disable(struct cal_ctx *ctx) +{ + reg_write_field(ctx->dev, CAL_CSI2_PPI_CTRL(ctx->csi2_port), + CAL_GEN_DISABLE, CAL_CSI2_PPI_CTRL_IF_EN_MASK); +} + +static void csi2_ctx_config(struct cal_ctx *ctx) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port)); + set_field(&val, ctx->csi2_port, CAL_CSI2_CTX_CPORT_MASK); + /* + * DT type: MIPI CSI-2 Specs + * 0x1: All - DT filter is disabled + * 0x24: RGB888 1 pixel = 3 bytes + * 0x2B: RAW10 4 pixels = 5 bytes + * 0x2A: RAW8 1 pixel = 1 byte + * 0x1E: YUV422 2 pixels = 4 bytes + */ + set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK); + /* Virtual Channel from the CSI2 sensor usually 0! */ + set_field(&val, ctx->virtual_channel, CAL_CSI2_CTX_VC_MASK); + /* NUM_LINES_PER_FRAME => 0 means auto detect */ + set_field(&val, 0, CAL_CSI2_CTX_LINES_MASK); + set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK); + set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE, + CAL_CSI2_CTX_PACK_MODE_MASK); + reg_write(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_CSI2_CTX0(ctx->csi2_port))); +} + +static void pix_proc_config(struct cal_ctx *ctx) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port)); + set_field(&val, CAL_PIX_PROC_EXTRACT_B8, CAL_PIX_PROC_EXTRACT_MASK); + set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK); + set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK); + set_field(&val, CAL_PIX_PROC_PACK_B8, CAL_PIX_PROC_PACK_MASK); + set_field(&val, ctx->csi2_port, CAL_PIX_PROC_CPORT_MASK); + set_field(&val, CAL_GEN_ENABLE, CAL_PIX_PROC_EN_MASK); + reg_write(ctx->dev, CAL_PIX_PROC(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_PIX_PROC(ctx->csi2_port))); +} + +static void cal_wr_dma_config(struct cal_ctx *ctx, + unsigned int width) +{ + u32 val; + + val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port)); + set_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK); + set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT, + CAL_WR_DMA_CTRL_DTAG_MASK); + set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST, + CAL_WR_DMA_CTRL_MODE_MASK); + set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR, + CAL_WR_DMA_CTRL_PATTERN_MASK); + set_field(&val, CAL_GEN_ENABLE, CAL_WR_DMA_CTRL_STALL_RD_MASK); + reg_write(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port))); + + /* + * width/16 not sure but giving it a whirl. + * zero does not work right + */ + reg_write_field(ctx->dev, + CAL_WR_DMA_OFST(ctx->csi2_port), + (width / 16), + CAL_WR_DMA_OFST_MASK); + ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_OFST(ctx->csi2_port))); + + val = reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port)); + /* 64 bit word means no skipping */ + set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK); + /* + * (width*8)/64 this should be size of an entire line + * in 64bit word but 0 means all data until the end + * is detected automagically + */ + set_field(&val, (width / 8), CAL_WR_DMA_XSIZE_MASK); + reg_write(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port), val); + ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->csi2_port, + reg_read(ctx->dev, CAL_WR_DMA_XSIZE(ctx->csi2_port))); +} + +static void cal_wr_dma_addr(struct cal_ctx *ctx, unsigned int dmaaddr) +{ + reg_write(ctx->dev, CAL_WR_DMA_ADDR(ctx->csi2_port), dmaaddr); +} + +/* + * TCLK values are OK at their reset values + */ +#define TCLK_TERM 0 +#define TCLK_MISS 1 +#define TCLK_SETTLE 14 +#define THS_SETTLE 15 + +static void csi2_phy_config(struct cal_ctx *ctx) +{ + unsigned int reg0, reg1; + unsigned int ths_term, ths_settle; + unsigned int ddrclkperiod_us; + + /* + * THS_TERM: Programmed value = floor(20 ns/DDRClk period) - 2. + */ + ddrclkperiod_us = ctx->external_rate / 2000000; + ddrclkperiod_us = 1000000 / ddrclkperiod_us; + ctx_dbg(1, ctx, "ddrclkperiod_us: %d\n", ddrclkperiod_us); + + ths_term = 20000 / ddrclkperiod_us; + ths_term = (ths_term >= 2) ? ths_term - 2 : ths_term; + ctx_dbg(1, ctx, "ths_term: %d (0x%02x)\n", ths_term, ths_term); + + /* + * THS_SETTLE: Programmed value = floor(176.3 ns/CtrlClk period) - 1. + * Since CtrlClk is fixed at 96Mhz then we get + * ths_settle = floor(176.3 / 10.416) - 1 = 15 + * If we ever switch to a dynamic clock then this code might be useful + * + * unsigned int ctrlclkperiod_us; + * ctrlclkperiod_us = 96000000 / 1000000; + * ctrlclkperiod_us = 1000000 / ctrlclkperiod_us; + * ctx_dbg(1, ctx, "ctrlclkperiod_us: %d\n", ctrlclkperiod_us); + + * ths_settle = 176300 / ctrlclkperiod_us; + * ths_settle = (ths_settle > 1) ? ths_settle - 1 : ths_settle; + */ + + ths_settle = THS_SETTLE; + ctx_dbg(1, ctx, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle); + + reg0 = reg_read(ctx->cc, CAL_CSI2_PHY_REG0); + set_field(®0, CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE, + CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK); + set_field(®0, ths_term, CAL_CSI2_PHY_REG0_THS_TERM_MASK); + set_field(®0, ths_settle, CAL_CSI2_PHY_REG0_THS_SETTLE_MASK); + + ctx_dbg(1, ctx, "CSI2_%d_REG0 = 0x%08x\n", (ctx->csi2_port - 1), reg0); + reg_write(ctx->cc, CAL_CSI2_PHY_REG0, reg0); + + reg1 = reg_read(ctx->cc, CAL_CSI2_PHY_REG1); + set_field(®1, TCLK_TERM, CAL_CSI2_PHY_REG1_TCLK_TERM_MASK); + set_field(®1, 0xb8, CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK); + set_field(®1, TCLK_MISS, CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK); + set_field(®1, TCLK_SETTLE, CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK); + + ctx_dbg(1, ctx, "CSI2_%d_REG1 = 0x%08x\n", (ctx->csi2_port - 1), reg1); + reg_write(ctx->cc, CAL_CSI2_PHY_REG1, reg1); +} + +static int cal_get_external_info(struct cal_ctx *ctx) +{ + struct v4l2_ctrl *ctrl; + + ctrl = v4l2_ctrl_find(ctx->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE); + if (!ctrl) { + ctx_err(ctx, "no pixel rate control in subdev: %s\n", + ctx->sensor->name); + return -EPIPE; + } + + ctx->external_rate = v4l2_ctrl_g_ctrl_int64(ctrl); + ctx_dbg(3, ctx, "sensor Pixel Rate: %d\n", ctx->external_rate); + + return 0; +} + +static inline void cal_schedule_next_buffer(struct cal_ctx *ctx) +{ + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf; + unsigned long addr; + + buf = list_entry(dma_q->active.next, struct cal_buffer, list); + ctx->next_frm = buf; + list_del(&buf->list); + + addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0); + cal_wr_dma_addr(ctx, addr); +} + +static inline void cal_process_buffer_complete(struct cal_ctx *ctx) +{ + ctx->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns(); + ctx->cur_frm->vb.field = ctx->m_fmt.field; + ctx->cur_frm->vb.sequence = ctx->sequence++; + + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE); + ctx->cur_frm = ctx->next_frm; +} + +#define isvcirqset(irq, vc, ff) (irq & \ + (CAL_CSI2_VC_IRQENABLE_ ##ff ##_IRQ_##vc ##_MASK)) + +#define isportirqset(irq, port) (irq & CAL_HL_IRQ_MASK(port)) + +static irqreturn_t cal_irq(int irq_cal, void *data) +{ + struct cal_dev *dev = (struct cal_dev *)data; + struct cal_ctx *ctx; + struct cal_dmaqueue *dma_q; + u32 irqst2, irqst3; + + /* Check which DMA just finished */ + irqst2 = reg_read(dev, CAL_HL_IRQSTATUS(2)); + if (irqst2) { + /* Clear Interrupt status */ + reg_write(dev, CAL_HL_IRQSTATUS(2), irqst2); + + /* Need to check both port */ + if (isportirqset(irqst2, 1)) { + ctx = dev->ctx[0]; + + if (ctx->cur_frm != ctx->next_frm) + cal_process_buffer_complete(ctx); + } + + if (isportirqset(irqst2, 2)) { + ctx = dev->ctx[1]; + + if (ctx->cur_frm != ctx->next_frm) + cal_process_buffer_complete(ctx); + } + } + + /* Check which DMA just started */ + irqst3 = reg_read(dev, CAL_HL_IRQSTATUS(3)); + if (irqst3) { + /* Clear Interrupt status */ + reg_write(dev, CAL_HL_IRQSTATUS(3), irqst3); + + /* Need to check both port */ + if (isportirqset(irqst3, 1)) { + ctx = dev->ctx[0]; + dma_q = &ctx->vidq; + + spin_lock(&ctx->slock); + if (!list_empty(&dma_q->active) && + ctx->cur_frm == ctx->next_frm) + cal_schedule_next_buffer(ctx); + spin_unlock(&ctx->slock); + } + + if (isportirqset(irqst3, 2)) { + ctx = dev->ctx[1]; + dma_q = &ctx->vidq; + + spin_lock(&ctx->slock); + if (!list_empty(&dma_q->active) && + ctx->cur_frm == ctx->next_frm) + cal_schedule_next_buffer(ctx); + spin_unlock(&ctx->slock); + } + } + + return IRQ_HANDLED; +} + +/* + * video ioctls + */ +static int cal_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct cal_ctx *ctx = video_drvdata(file); + + strlcpy(cap->driver, CAL_MODULE_NAME, sizeof(cap->driver)); + strlcpy(cap->card, CAL_MODULE_NAME, sizeof(cap->card)); + + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", ctx->v4l2_dev.name); + 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 cal_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt = NULL; + + if (f->index >= ctx->num_active_fmt) + return -EINVAL; + + fmt = ctx->active_fmt[f->index]; + + f->pixelformat = fmt->fourcc; + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + return 0; +} + +static int __subdev_get_format(struct cal_ctx *ctx, + struct v4l2_mbus_framefmt *fmt) +{ + struct v4l2_subdev_format sd_fmt; + struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format; + int ret; + + if (!ctx->sensor) + return -EINVAL; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = 0; + + ret = v4l2_subdev_call(ctx->sensor, pad, get_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + *fmt = *mbus_fmt; + + ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__, + fmt->width, fmt->height, fmt->code); + + return 0; +} + +static int __subdev_set_format(struct cal_ctx *ctx, + struct v4l2_mbus_framefmt *fmt) +{ + struct v4l2_subdev_format sd_fmt; + struct v4l2_mbus_framefmt *mbus_fmt = &sd_fmt.format; + int ret; + + if (!ctx->sensor) + return -EINVAL; + + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; + sd_fmt.pad = 0; + *mbus_fmt = *fmt; + + ret = v4l2_subdev_call(ctx->sensor, pad, set_fmt, NULL, &sd_fmt); + if (ret) + return ret; + + ctx_dbg(1, ctx, "%s %dx%d code:%04X\n", __func__, + fmt->width, fmt->height, fmt->code); + + return 0; +} + +static int cal_calc_format_size(struct cal_ctx *ctx, + const struct cal_fmt *fmt, + struct v4l2_format *f) +{ + if (!fmt) { + ctx_dbg(3, ctx, "No cal_fmt provided!\n"); + return -EINVAL; + } + + v4l_bound_align_image(&f->fmt.pix.width, 48, MAX_WIDTH, 2, + &f->fmt.pix.height, 32, MAX_HEIGHT, 0, 0); + f->fmt.pix.bytesperline = bytes_per_line(f->fmt.pix.width, + fmt->depth >> 3); + f->fmt.pix.sizeimage = f->fmt.pix.height * + f->fmt.pix.bytesperline; + + ctx_dbg(3, ctx, "%s: fourcc: %s size: %dx%d bpl:%d img_size:%d\n", + __func__, fourcc_to_str(f->fmt.pix.pixelformat), + f->fmt.pix.width, f->fmt.pix.height, + f->fmt.pix.bytesperline, f->fmt.pix.sizeimage); + + return 0; +} + +static int cal_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + + *f = ctx->v_fmt; + + return 0; +} + +static int cal_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret, found; + + fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + if (!fmt) { + ctx_dbg(3, ctx, "Fourcc format (0x%08x) not found.\n", + f->fmt.pix.pixelformat); + + /* Just get the first one enumerated */ + fmt = ctx->active_fmt[0]; + f->fmt.pix.pixelformat = fmt->fourcc; + } + + f->fmt.pix.field = ctx->v_fmt.fmt.pix.field; + + /* check for/find a valid width/height */ + ret = 0; + found = false; + fse.pad = 0; + fse.code = fmt->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + for (fse.index = 0; ; fse.index++) { + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, + NULL, &fse); + if (ret) + break; + + if ((f->fmt.pix.width == fse.max_width) && + (f->fmt.pix.height == fse.max_height)) { + found = true; + break; + } else if ((f->fmt.pix.width >= fse.min_width) && + (f->fmt.pix.width <= fse.max_width) && + (f->fmt.pix.height >= fse.min_height) && + (f->fmt.pix.height <= fse.max_height)) { + found = true; + break; + } + } + + if (!found) { + /* use existing values as default */ + f->fmt.pix.width = ctx->v_fmt.fmt.pix.width; + f->fmt.pix.height = ctx->v_fmt.fmt.pix.height; + } + + /* + * Use current colorspace for now, it will get + * updated properly during s_fmt + */ + f->fmt.pix.colorspace = ctx->v_fmt.fmt.pix.colorspace; + return cal_calc_format_size(ctx, fmt, f); +} + +static int cal_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct cal_ctx *ctx = video_drvdata(file); + struct vb2_queue *q = &ctx->vb_vidq; + const struct cal_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; + int ret; + + if (vb2_is_busy(q)) { + ctx_dbg(3, ctx, "%s device busy\n", __func__); + return -EBUSY; + } + + ret = cal_try_fmt_vid_cap(file, priv, f); + if (ret < 0) + return ret; + + fmt = find_format_by_pix(ctx, f->fmt.pix.pixelformat); + + v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, fmt->code); + + ret = __subdev_set_format(ctx, &mbus_fmt); + if (ret) + return ret; + + /* Just double check nothing has gone wrong */ + if (mbus_fmt.code != fmt->code) { + ctx_dbg(3, ctx, + "%s subdev changed format on us, this should not happen\n", + __func__); + return -EINVAL; + } + + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; + cal_calc_format_size(ctx, fmt, &ctx->v_fmt); + ctx->fmt = fmt; + ctx->m_fmt = mbus_fmt; + *f = ctx->v_fmt; + + return 0; +} + +static int cal_enum_framesizes(struct file *file, void *fh, + struct v4l2_frmsizeenum *fsize) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret; + + /* check for valid format */ + fmt = find_format_by_pix(ctx, fsize->pixel_format); + if (!fmt) { + ctx_dbg(3, ctx, "Invalid pixel code: %x\n", + fsize->pixel_format); + return -EINVAL; + } + + fse.index = fsize->index; + fse.pad = 0; + fse.code = fmt->code; + + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, NULL, &fse); + if (ret) + return -EINVAL; + + ctx_dbg(1, ctx, "%s: index: %d code: %x W:[%d,%d] H:[%d,%d]\n", + __func__, fse.index, fse.code, fse.min_width, fse.max_width, + fse.min_height, fse.max_height); + + fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fsize->discrete.width = fse.max_width; + fsize->discrete.height = fse.max_height; + + return 0; +} + +static int cal_enum_input(struct file *file, void *priv, + struct v4l2_input *inp) +{ + if (inp->index >= CAL_NUM_INPUT) + return -EINVAL; + + inp->type = V4L2_INPUT_TYPE_CAMERA; + sprintf(inp->name, "Camera %u", inp->index); + return 0; +} + +static int cal_g_input(struct file *file, void *priv, unsigned int *i) +{ + struct cal_ctx *ctx = video_drvdata(file); + + *i = ctx->input; + return 0; +} + +static int cal_s_input(struct file *file, void *priv, unsigned int i) +{ + struct cal_ctx *ctx = video_drvdata(file); + + if (i >= CAL_NUM_INPUT) + return -EINVAL; + + ctx->input = i; + return 0; +} + +/* timeperframe is arbitrary and continuous */ +static int cal_enum_frameintervals(struct file *file, void *priv, + struct v4l2_frmivalenum *fival) +{ + struct cal_ctx *ctx = video_drvdata(file); + const struct cal_fmt *fmt; + struct v4l2_subdev_frame_size_enum fse; + int ret; + + if (fival->index) + return -EINVAL; + + fmt = find_format_by_pix(ctx, fival->pixel_format); + if (!fmt) + return -EINVAL; + + /* check for valid width/height */ + ret = 0; + fse.pad = 0; + fse.code = fmt->code; + fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; + for (fse.index = 0; ; fse.index++) { + ret = v4l2_subdev_call(ctx->sensor, pad, enum_frame_size, + NULL, &fse); + if (ret) + return -EINVAL; + + if ((fival->width == fse.max_width) && + (fival->height == fse.max_height)) + break; + else if ((fival->width >= fse.min_width) && + (fival->width <= fse.max_width) && + (fival->height >= fse.min_height) && + (fival->height <= fse.max_height)) + break; + + return -EINVAL; + } + + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; + fival->discrete.numerator = 1; + fival->discrete.denominator = 30; + + return 0; +} + +/* + * Videobuf operations + */ +static int cal_queue_setup(struct vb2_queue *vq, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + unsigned size = ctx->v_fmt.fmt.pix.sizeimage; + + if (vq->num_buffers + *nbuffers < 3) + *nbuffers = 3 - vq->num_buffers; + alloc_ctxs[0] = ctx->alloc_ctx; + + if (*nplanes) { + if (sizes[0] < size) + return -EINVAL; + size = sizes[0]; + } + + *nplanes = 1; + sizes[0] = size; + + ctx_dbg(3, ctx, "nbuffers=%d, size=%d\n", *nbuffers, sizes[0]); + + return 0; +} + +static int cal_buffer_prepare(struct vb2_buffer *vb) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct cal_buffer *buf = container_of(vb, struct cal_buffer, + vb.vb2_buf); + unsigned long size; + + if (WARN_ON(!ctx->fmt)) + return -EINVAL; + + size = ctx->v_fmt.fmt.pix.sizeimage; + if (vb2_plane_size(vb, 0) < size) { + ctx_err(ctx, + "data will not fit into plane (%lu < %lu)\n", + vb2_plane_size(vb, 0), size); + return -EINVAL; + } + + vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); + return 0; +} + +static void cal_buffer_queue(struct vb2_buffer *vb) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); + struct cal_buffer *buf = container_of(vb, struct cal_buffer, + vb.vb2_buf); + struct cal_dmaqueue *vidq = &ctx->vidq; + unsigned long flags = 0; + + /* recheck locking */ + spin_lock_irqsave(&ctx->slock, flags); + list_add_tail(&buf->list, &vidq->active); + spin_unlock_irqrestore(&ctx->slock, flags); +} + +static int cal_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf, *tmp; + unsigned long addr = 0; + unsigned long flags; + int ret; + + spin_lock_irqsave(&ctx->slock, flags); + if (list_empty(&dma_q->active)) { + spin_unlock_irqrestore(&ctx->slock, flags); + ctx_dbg(3, ctx, "buffer queue is empty\n"); + return -EIO; + } + + buf = list_entry(dma_q->active.next, struct cal_buffer, list); + ctx->cur_frm = buf; + ctx->next_frm = buf; + list_del(&buf->list); + spin_unlock_irqrestore(&ctx->slock, flags); + + addr = vb2_dma_contig_plane_dma_addr(&ctx->cur_frm->vb.vb2_buf, 0); + ctx->sequence = 0; + + ret = cal_get_external_info(ctx); + if (ret < 0) + goto err; + + cal_runtime_get(ctx->dev); + + enable_irqs(ctx); + camerarx_phy_enable(ctx); + csi2_init(ctx); + csi2_phy_config(ctx); + csi2_lane_config(ctx); + csi2_ctx_config(ctx); + pix_proc_config(ctx); + cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline); + cal_wr_dma_addr(ctx, addr); + csi2_ppi_enable(ctx); + + if (ctx->sensor) { + if (v4l2_subdev_call(ctx->sensor, video, s_stream, 1)) { + ctx_err(ctx, "stream on failed in subdev\n"); + cal_runtime_put(ctx->dev); + ret = -EINVAL; + goto err; + } + } + + if (debug >= 4) + cal_quickdump_regs(ctx->dev); + + return 0; + +err: + list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED); + } + return ret; +} + +static void cal_stop_streaming(struct vb2_queue *vq) +{ + struct cal_ctx *ctx = vb2_get_drv_priv(vq); + struct cal_dmaqueue *dma_q = &ctx->vidq; + struct cal_buffer *buf, *tmp; + unsigned long flags; + + if (ctx->sensor) { + if (v4l2_subdev_call(ctx->sensor, video, s_stream, 0)) + ctx_err(ctx, "stream off failed in subdev\n"); + } + + csi2_ppi_disable(ctx); + disable_irqs(ctx); + + /* Release all active buffers */ + spin_lock_irqsave(&ctx->slock, flags); + list_for_each_entry_safe(buf, tmp, &dma_q->active, list) { + list_del(&buf->list); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + if (ctx->cur_frm == ctx->next_frm) { + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } else { + vb2_buffer_done(&ctx->cur_frm->vb.vb2_buf, VB2_BUF_STATE_ERROR); + vb2_buffer_done(&ctx->next_frm->vb.vb2_buf, + VB2_BUF_STATE_ERROR); + } + ctx->cur_frm = NULL; + ctx->next_frm = NULL; + spin_unlock_irqrestore(&ctx->slock, flags); + + cal_runtime_put(ctx->dev); +} + +static struct vb2_ops cal_video_qops = { + .queue_setup = cal_queue_setup, + .buf_prepare = cal_buffer_prepare, + .buf_queue = cal_buffer_queue, + .start_streaming = cal_start_streaming, + .stop_streaming = cal_stop_streaming, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, +}; + +static const struct v4l2_file_operations cal_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .read = vb2_fop_read, + .poll = vb2_fop_poll, + .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ + .mmap = vb2_fop_mmap, +}; + +static const struct v4l2_ioctl_ops cal_ioctl_ops = { + .vidioc_querycap = cal_querycap, + .vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap, + .vidioc_enum_framesizes = cal_enum_framesizes, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_create_bufs = vb2_ioctl_create_bufs, + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_enum_input = cal_enum_input, + .vidioc_g_input = cal_g_input, + .vidioc_s_input = cal_s_input, + .vidioc_enum_frameintervals = cal_enum_frameintervals, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static struct video_device cal_videodev = { + .name = CAL_MODULE_NAME, + .fops = &cal_fops, + .ioctl_ops = &cal_ioctl_ops, + .minor = -1, + .release = video_device_release_empty, +}; + +/* ----------------------------------------------------------------- + * Initialization and module stuff + * ------------------------------------------------------------------ + */ +static int cal_complete_ctx(struct cal_ctx *ctx); + +static int cal_async_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *subdev, + struct v4l2_async_subdev *asd) +{ + struct cal_ctx *ctx = notifier_to_ctx(notifier); + struct v4l2_subdev_mbus_code_enum mbus_code; + int ret = 0; + int i, j, k; + + if (ctx->sensor) { + ctx_info(ctx, "Rejecting subdev %s (Already set!!)", + subdev->name); + return 0; + } + + ctx->sensor = subdev; + ctx_dbg(1, ctx, "Using sensor %s for capture\n", subdev->name); + + /* Enumerate sub device formats and enable all matching local formats */ + ctx->num_active_fmt = 0; + for (j = 0, i = 0; ret != -EINVAL; ++j) { + struct cal_fmt *fmt; + + memset(&mbus_code, 0, sizeof(mbus_code)); + mbus_code.index = j; + ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, + NULL, &mbus_code); + if (ret) + continue; + + ctx_dbg(2, ctx, + "subdev %s: code: %04x idx: %d\n", + subdev->name, mbus_code.code, j); + + for (k = 0; k < ARRAY_SIZE(cal_formats); k++) { + fmt = &cal_formats[k]; + + if (mbus_code.code == fmt->code) { + ctx->active_fmt[i] = fmt; + ctx_dbg(2, ctx, + "matched fourcc: %s: code: %04x idx: %d\n", + fourcc_to_str(fmt->fourcc), + fmt->code, i); + ctx->num_active_fmt = ++i; + } + } + } + + if (i == 0) { + ctx_err(ctx, "No suitable format reported by subdev %s\n", + subdev->name); + return -EINVAL; + } + + cal_complete_ctx(ctx); + + return 0; +} + +static int cal_async_complete(struct v4l2_async_notifier *notifier) +{ + struct cal_ctx *ctx = notifier_to_ctx(notifier); + const struct cal_fmt *fmt; + struct v4l2_mbus_framefmt mbus_fmt; + int ret; + + ret = __subdev_get_format(ctx, &mbus_fmt); + if (ret) + return ret; + + fmt = find_format_by_code(ctx, mbus_fmt.code); + if (!fmt) { + ctx_dbg(3, ctx, "mbus code format (0x%08x) not found.\n", + mbus_fmt.code); + return -EINVAL; + } + + /* Save current subdev format */ + v4l2_fill_pix_format(&ctx->v_fmt.fmt.pix, &mbus_fmt); + ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ctx->v_fmt.fmt.pix.pixelformat = fmt->fourcc; + cal_calc_format_size(ctx, fmt, &ctx->v_fmt); + ctx->fmt = fmt; + ctx->m_fmt = mbus_fmt; + + return 0; +} + +static int cal_complete_ctx(struct cal_ctx *ctx) +{ + struct video_device *vfd; + struct vb2_queue *q; + int ret; + + ctx->timeperframe = tpf_default; + ctx->external_rate = 192000000; + + /* initialize locks */ + spin_lock_init(&ctx->slock); + mutex_init(&ctx->mutex); + + /* initialize queue */ + q = &ctx->vb_vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_READ; + q->drv_priv = ctx; + q->buf_struct_size = sizeof(struct cal_buffer); + q->ops = &cal_video_qops; + q->mem_ops = &vb2_dma_contig_memops; + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ctx->mutex; + q->min_buffers_needed = 3; + + ret = vb2_queue_init(q); + if (ret) + return ret; + + /* init video dma queues */ + INIT_LIST_HEAD(&ctx->vidq.active); + + vfd = &ctx->vdev; + *vfd = cal_videodev; + vfd->v4l2_dev = &ctx->v4l2_dev; + vfd->queue = q; + + /* + * Provide a mutex to v4l2 core. It will be used to protect + * all fops and v4l2 ioctls. + */ + vfd->lock = &ctx->mutex; + video_set_drvdata(vfd, ctx); + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr); + if (ret < 0) + return ret; + + v4l2_info(&ctx->v4l2_dev, "V4L2 device registered as %s\n", + video_device_node_name(vfd)); + + ctx->alloc_ctx = vb2_dma_contig_init_ctx(vfd->v4l2_dev->dev); + if (IS_ERR(ctx->alloc_ctx)) { + ctx_err(ctx, "Failed to alloc vb2 context\n"); + ret = PTR_ERR(ctx->alloc_ctx); + goto vdev_unreg; + } + + return 0; + +vdev_unreg: + video_unregister_device(vfd); + return ret; +} + +static struct device_node * +of_get_next_port(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *port = NULL; + + if (!parent) + return NULL; + + if (!prev) { + struct device_node *ports; + /* + * It's the first call, we have to find a port subnode + * within this node or within an optional 'ports' node. + */ + ports = of_get_child_by_name(parent, "ports"); + if (ports) + parent = ports; + + port = of_get_child_by_name(parent, "port"); + + /* release the 'ports' node */ + of_node_put(ports); + } else { + struct device_node *ports; + + ports = of_get_parent(prev); + if (!ports) + return NULL; + + do { + port = of_get_next_child(ports, prev); + if (!port) { + of_node_put(ports); + return NULL; + } + prev = port; + } while (of_node_cmp(port->name, "port") != 0); + } + + return port; +} + +static struct device_node * +of_get_next_endpoint(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *ep = NULL; + + if (!parent) + return NULL; + + do { + ep = of_get_next_child(parent, prev); + if (!ep) + return NULL; + prev = ep; + } while (of_node_cmp(ep->name, "endpoint") != 0); + + return ep; +} + +static int of_cal_create_instance(struct cal_ctx *ctx, int inst) +{ + struct platform_device *pdev = ctx->dev->pdev; + struct device_node *ep_node, *port, *remote_ep, + *sensor_node, *parent; + struct v4l2_of_endpoint *endpoint; + struct v4l2_async_subdev *asd; + u32 regval = 0; + int ret, index, found_port = 0, lane; + + parent = pdev->dev.of_node; + + asd = &ctx->asd; + endpoint = &ctx->endpoint; + + ep_node = NULL; + port = NULL; + remote_ep = NULL; + sensor_node = NULL; + ret = -EINVAL; + + ctx_dbg(3, ctx, "Scanning Port node for csi2 port: %d\n", inst); + for (index = 0; index < CAL_NUM_CSI2_PORTS; index++) { + port = of_get_next_port(parent, port); + if (!port) { + ctx_dbg(1, ctx, "No port node found for csi2 port:%d\n", + index); + goto cleanup_exit; + } + + /* Match the slice number with */ + of_property_read_u32(port, "reg", ®val); + ctx_dbg(3, ctx, "port:%d inst:%d :%d\n", + index, inst, regval); + if ((regval == inst) && (index == inst)) { + found_port = 1; + break; + } + } + + if (!found_port) { + ctx_dbg(1, ctx, "No port node matches csi2 port:%d\n", + inst); + goto cleanup_exit; + } + + ctx_dbg(3, ctx, "Scanning sub-device for csi2 port: %d\n", + inst); + + ep_node = of_get_next_endpoint(port, ep_node); + if (!ep_node) { + ctx_dbg(3, ctx, "can't get next endpoint\n"); + goto cleanup_exit; + } + + sensor_node = of_graph_get_remote_port_parent(ep_node); + if (!sensor_node) { + ctx_dbg(3, ctx, "can't get remote parent\n"); + goto cleanup_exit; + } + asd->match_type = V4L2_ASYNC_MATCH_OF; + asd->match.of.node = sensor_node; + + remote_ep = of_parse_phandle(ep_node, "remote-endpoint", 0); + if (!remote_ep) { + ctx_dbg(3, ctx, "can't get remote-endpoint\n"); + goto cleanup_exit; + } + v4l2_of_parse_endpoint(remote_ep, endpoint); + + if (endpoint->bus_type != V4L2_MBUS_CSI2) { + ctx_err(ctx, "Port:%d sub-device %s is not a CSI2 device\n", + inst, sensor_node->name); + goto cleanup_exit; + } + + /* Store Virtual Channel number */ + ctx->virtual_channel = endpoint->base.id; + + ctx_dbg(3, ctx, "Port:%d v4l2-endpoint: CSI2\n", inst); + ctx_dbg(3, ctx, "Virtual Channel=%d\n", ctx->virtual_channel); + ctx_dbg(3, ctx, "flags=0x%08x\n", endpoint->bus.mipi_csi2.flags); + ctx_dbg(3, ctx, "clock_lane=%d\n", endpoint->bus.mipi_csi2.clock_lane); + ctx_dbg(3, ctx, "num_data_lanes=%d\n", + endpoint->bus.mipi_csi2.num_data_lanes); + ctx_dbg(3, ctx, "data_lanes= <\n"); + for (lane = 0; lane < endpoint->bus.mipi_csi2.num_data_lanes; lane++) + ctx_dbg(3, ctx, "\t%d\n", + endpoint->bus.mipi_csi2.data_lanes[lane]); + ctx_dbg(3, ctx, "\t>\n"); + + ctx_dbg(1, ctx, "Port: %d found sub-device %s\n", + inst, sensor_node->name); + + ctx->asd_list[0] = asd; + ctx->notifier.subdevs = ctx->asd_list; + ctx->notifier.num_subdevs = 1; + ctx->notifier.bound = cal_async_bound; + ctx->notifier.complete = cal_async_complete; + ret = v4l2_async_notifier_register(&ctx->v4l2_dev, + &ctx->notifier); + if (ret) { + ctx_err(ctx, "Error registering async notifier\n"); + ret = -EINVAL; + } + +cleanup_exit: + if (!remote_ep) + of_node_put(remote_ep); + if (!sensor_node) + of_node_put(sensor_node); + if (!ep_node) + of_node_put(ep_node); + if (!port) + of_node_put(port); + + return ret; +} + +static struct cal_ctx *cal_create_instance(struct cal_dev *dev, int inst) +{ + struct cal_ctx *ctx; + struct v4l2_ctrl_handler *hdl; + int ret; + + ctx = devm_kzalloc(&dev->pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return 0; + + /* save the cal_dev * for future ref */ + ctx->dev = dev; + + snprintf(ctx->v4l2_dev.name, sizeof(ctx->v4l2_dev.name), + "%s-%03d", CAL_MODULE_NAME, inst); + ret = v4l2_device_register(&dev->pdev->dev, &ctx->v4l2_dev); + if (ret) + goto err_exit; + + hdl = &ctx->ctrl_handler; + ret = v4l2_ctrl_handler_init(hdl, 11); + if (ret) { + ctx_err(ctx, "Failed to init ctrl handler\n"); + goto unreg_dev; + } + ctx->v4l2_dev.ctrl_handler = hdl; + + /* Make sure Camera Core H/W register area is available */ + ctx->cc = dev->cc[inst]; + + /* Store the instance id */ + ctx->csi2_port = inst + 1; + + ret = of_cal_create_instance(ctx, inst); + if (ret) { + ret = -EINVAL; + goto free_hdl; + } + return ctx; + +free_hdl: + v4l2_ctrl_handler_free(hdl); +unreg_dev: + v4l2_device_unregister(&ctx->v4l2_dev); +err_exit: + return 0; +} + +static int cal_probe(struct platform_device *pdev) +{ + struct cal_dev *dev; + int ret; + int irq; + + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + /* set pseudo v4l2 device name so we can use v4l2_printk */ + strlcpy(dev->v4l2_dev.name, CAL_MODULE_NAME, + sizeof(dev->v4l2_dev.name)); + + /* save pdev pointer */ + dev->pdev = pdev; + + dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "cal_top"); + dev->base = devm_ioremap_resource(&pdev->dev, dev->res); + if (IS_ERR(dev->base)) + return PTR_ERR(dev->base); + + cal_dbg(1, dev, "ioresource %s at %pa - %pa\n", + dev->res->name, &dev->res->start, &dev->res->end); + + irq = platform_get_irq(pdev, 0); + cal_dbg(1, dev, "got irq# %d\n", irq); + ret = devm_request_irq(&pdev->dev, irq, cal_irq, 0, CAL_MODULE_NAME, + dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, dev); + + dev->cm = cm_create(dev); + if (IS_ERR(dev->cm)) + return PTR_ERR(dev->cm); + + dev->cc[0] = cc_create(dev, 0); + if (IS_ERR(dev->cc[0])) + return PTR_ERR(dev->cc[0]); + + dev->cc[1] = cc_create(dev, 1); + if (IS_ERR(dev->cc[1])) + return PTR_ERR(dev->cc[1]); + + dev->ctx[0] = NULL; + dev->ctx[1] = NULL; + + dev->ctx[0] = cal_create_instance(dev, 0); + dev->ctx[1] = cal_create_instance(dev, 1); + if (!dev->ctx[0] && !dev->ctx[1]) { + cal_err(dev, "Neither port is configured, no point in staying up\n"); + return -ENODEV; + } + + pm_runtime_enable(&pdev->dev); + + ret = cal_runtime_get(dev); + if (ret) + goto runtime_disable; + + /* Just check we can actually access the module */ + cal_get_hwinfo(dev); + + cal_runtime_put(dev); + + return 0; + +runtime_disable: + pm_runtime_disable(&pdev->dev); + return ret; +} + +static int cal_remove(struct platform_device *pdev) +{ + struct cal_dev *dev = + (struct cal_dev *)platform_get_drvdata(pdev); + struct cal_ctx *ctx; + int i; + + cal_dbg(1, dev, "Removing %s\n", CAL_MODULE_NAME); + + cal_runtime_get(dev); + + for (i = 0; i < CAL_NUM_CONTEXT; i++) { + ctx = dev->ctx[i]; + if (ctx) { + ctx_dbg(1, ctx, "unregistering %s\n", + video_device_node_name(&ctx->vdev)); + camerarx_phy_disable(ctx); + v4l2_async_notifier_unregister(&ctx->notifier); + vb2_dma_contig_cleanup_ctx(ctx->alloc_ctx); + v4l2_ctrl_handler_free(&ctx->ctrl_handler); + v4l2_device_unregister(&ctx->v4l2_dev); + video_unregister_device(&ctx->vdev); + } + } + + cal_runtime_put(dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +#if defined(CONFIG_OF) +static const struct of_device_id cal_of_match[] = { + { .compatible = "ti,dra72-cal", }, + {}, +}; +MODULE_DEVICE_TABLE(of, cal_of_match); +#endif + +static struct platform_driver cal_pdrv = { + .probe = cal_probe, + .remove = cal_remove, + .driver = { + .name = CAL_MODULE_NAME, + .of_match_table = of_match_ptr(cal_of_match), + }, +}; + +module_platform_driver(cal_pdrv); diff --git a/drivers/media/platform/ti-vpe/cal_regs.h b/drivers/media/platform/ti-vpe/cal_regs.h new file mode 100644 index 000000000000..82b3dcf87128 --- /dev/null +++ b/drivers/media/platform/ti-vpe/cal_regs.h @@ -0,0 +1,479 @@ +/* + * TI CAL camera interface driver + * + * Copyright (c) 2015 Texas Instruments Inc. + * + * Benoit Parrot, + * + * 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 __TI_CAL_REGS_H +#define __TI_CAL_REGS_H + +#define CAL_NUM_CSI2_PORTS 2 + +/* CAL register offsets */ + +#define CAL_HL_REVISION 0x0000 +#define CAL_HL_HWINFO 0x0004 +#define CAL_HL_SYSCONFIG 0x0010 +#define CAL_HL_IRQ_EOI 0x001c +#define CAL_HL_IRQSTATUS_RAW(m) (0x20U + ((m-1) * 0x10U)) +#define CAL_HL_IRQSTATUS(m) (0x24U + ((m-1) * 0x10U)) +#define CAL_HL_IRQENABLE_SET(m) (0x28U + ((m-1) * 0x10U)) +#define CAL_HL_IRQENABLE_CLR(m) (0x2cU + ((m-1) * 0x10U)) +#define CAL_PIX_PROC(m) (0xc0U + ((m-1) * 0x4U)) +#define CAL_CTRL 0x100 +#define CAL_CTRL1 0x104 +#define CAL_LINE_NUMBER_EVT 0x108 +#define CAL_VPORT_CTRL1 0x120 +#define CAL_VPORT_CTRL2 0x124 +#define CAL_BYS_CTRL1 0x130 +#define CAL_BYS_CTRL2 0x134 +#define CAL_RD_DMA_CTRL 0x140 +#define CAL_RD_DMA_PIX_ADDR 0x144 +#define CAL_RD_DMA_PIX_OFST 0x148 +#define CAL_RD_DMA_XSIZE 0x14c +#define CAL_RD_DMA_YSIZE 0x150 +#define CAL_RD_DMA_INIT_ADDR 0x154 +#define CAL_RD_DMA_INIT_OFST 0x168 +#define CAL_RD_DMA_CTRL2 0x16c +#define CAL_WR_DMA_CTRL(m) (0x200U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_ADDR(m) (0x204U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_OFST(m) (0x208U + ((m-1) * 0x10U)) +#define CAL_WR_DMA_XSIZE(m) (0x20cU + ((m-1) * 0x10U)) +#define CAL_CSI2_PPI_CTRL(m) (0x300U + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_CFG(m) (0x304U + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_IRQSTATUS(m) (0x308U + ((m-1) * 0x80U)) +#define CAL_CSI2_SHORT_PACKET(m) (0x30cU + ((m-1) * 0x80U)) +#define CAL_CSI2_COMPLEXIO_IRQENABLE(m) (0x310U + ((m-1) * 0x80U)) +#define CAL_CSI2_TIMING(m) (0x314U + ((m-1) * 0x80U)) +#define CAL_CSI2_VC_IRQENABLE(m) (0x318U + ((m-1) * 0x80U)) +#define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX0(m) (0x330U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX1(m) (0x334U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX2(m) (0x338U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX3(m) (0x33cU + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX4(m) (0x340U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX5(m) (0x344U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX6(m) (0x348U + ((m-1) * 0x80U)) +#define CAL_CSI2_CTX7(m) (0x34cU + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS0(m) (0x350U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS1(m) (0x354U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS2(m) (0x358U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS3(m) (0x35cU + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS4(m) (0x360U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS5(m) (0x364U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS6(m) (0x368U + ((m-1) * 0x80U)) +#define CAL_CSI2_STATUS7(m) (0x36cU + ((m-1) * 0x80U)) + +/* CAL CSI2 PHY register offsets */ +#define CAL_CSI2_PHY_REG0 0x000 +#define CAL_CSI2_PHY_REG1 0x004 +#define CAL_CSI2_PHY_REG2 0x008 + +/* CAL Control Module Core Camerrx Control register offsets */ +#define CM_CTRL_CORE_CAMERRX_CONTROL 0x000 + +/********************************************************************* +* Generic value used in various field below +*********************************************************************/ + +#define CAL_GEN_DISABLE 0 +#define CAL_GEN_ENABLE 1 +#define CAL_GEN_FALSE 0 +#define CAL_GEN_TRUE 1 + +/********************************************************************* +* Field Definition Macros +*********************************************************************/ + +#define CAL_HL_REVISION_MINOR_MASK GENMASK(5, 0) +#define CAL_HL_REVISION_CUSTOM_MASK GENMASK(7, 6) +#define CAL_HL_REVISION_MAJOR_MASK GENMASK(10, 8) +#define CAL_HL_REVISION_RTL_MASK GENMASK(15, 11) +#define CAL_HL_REVISION_FUNC_MASK GENMASK(27, 16) +#define CAL_HL_REVISION_SCHEME_MASK GENMASK(31, 30) +#define CAL_HL_REVISION_SCHEME_H08 1 +#define CAL_HL_REVISION_SCHEME_LEGACY 0 + +#define CAL_HL_HWINFO_WFIFO_MASK GENMASK(3, 0) +#define CAL_HL_HWINFO_RFIFO_MASK GENMASK(7, 4) +#define CAL_HL_HWINFO_PCTX_MASK GENMASK(12, 8) +#define CAL_HL_HWINFO_WCTX_MASK GENMASK(18, 13) +#define CAL_HL_HWINFO_VFIFO_MASK GENMASK(22, 19) +#define CAL_HL_HWINFO_NCPORT_MASK GENMASK(27, 23) +#define CAL_HL_HWINFO_NPPI_CTXS0_MASK GENMASK(29, 28) +#define CAL_HL_HWINFO_NPPI_CTXS1_MASK GENMASK(31, 30) +#define CAL_HL_HWINFO_NPPI_CONTEXTS_ZERO 0 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_FOUR 1 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_EIGHT 2 +#define CAL_HL_HWINFO_NPPI_CONTEXTS_RESERVED 3 + +#define CAL_HL_SYSCONFIG_SOFTRESET_MASK BIT_MASK(0) +#define CAL_HL_SYSCONFIG_SOFTRESET_DONE 0x0 +#define CAL_HL_SYSCONFIG_SOFTRESET_PENDING 0x1 +#define CAL_HL_SYSCONFIG_SOFTRESET_NOACTION 0x0 +#define CAL_HL_SYSCONFIG_SOFTRESET_RESET 0x1 +#define CAL_HL_SYSCONFIG_IDLE_MASK GENMASK(3, 2) +#define CAL_HL_SYSCONFIG_IDLEMODE_FORCE 0 +#define CAL_HL_SYSCONFIG_IDLEMODE_NO 1 +#define CAL_HL_SYSCONFIG_IDLEMODE_SMART1 2 +#define CAL_HL_SYSCONFIG_IDLEMODE_SMART2 3 + +#define CAL_HL_IRQ_EOI_LINE_NUMBER_MASK BIT_MASK(0) +#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0 +#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0 + +#define CAL_HL_IRQ_MASK(m) BIT_MASK(m-1) +#define CAL_HL_IRQ_NOACTION 0x0 +#define CAL_HL_IRQ_ENABLE 0x1 +#define CAL_HL_IRQ_CLEAR 0x1 +#define CAL_HL_IRQ_DISABLED 0x0 +#define CAL_HL_IRQ_ENABLED 0x1 +#define CAL_HL_IRQ_PENDING 0x1 + +#define CAL_PIX_PROC_EN_MASK BIT_MASK(0) +#define CAL_PIX_PROC_EXTRACT_MASK GENMASK(4, 1) +#define CAL_PIX_PROC_EXTRACT_B6 0x0 +#define CAL_PIX_PROC_EXTRACT_B7 0x1 +#define CAL_PIX_PROC_EXTRACT_B8 0x2 +#define CAL_PIX_PROC_EXTRACT_B10 0x3 +#define CAL_PIX_PROC_EXTRACT_B10_MIPI 0x4 +#define CAL_PIX_PROC_EXTRACT_B12 0x5 +#define CAL_PIX_PROC_EXTRACT_B12_MIPI 0x6 +#define CAL_PIX_PROC_EXTRACT_B14 0x7 +#define CAL_PIX_PROC_EXTRACT_B14_MIPI 0x8 +#define CAL_PIX_PROC_EXTRACT_B16_BE 0x9 +#define CAL_PIX_PROC_EXTRACT_B16_LE 0xa +#define CAL_PIX_PROC_DPCMD_MASK GENMASK(9, 5) +#define CAL_PIX_PROC_DPCMD_BYPASS 0x0 +#define CAL_PIX_PROC_DPCMD_DPCM_10_8_1 0x2 +#define CAL_PIX_PROC_DPCMD_DPCM_12_8_1 0x8 +#define CAL_PIX_PROC_DPCMD_DPCM_10_7_1 0x4 +#define CAL_PIX_PROC_DPCMD_DPCM_10_7_2 0x5 +#define CAL_PIX_PROC_DPCMD_DPCM_10_6_1 0x6 +#define CAL_PIX_PROC_DPCMD_DPCM_10_6_2 0x7 +#define CAL_PIX_PROC_DPCMD_DPCM_12_7_1 0xa +#define CAL_PIX_PROC_DPCMD_DPCM_12_6_1 0xc +#define CAL_PIX_PROC_DPCMD_DPCM_14_10 0xe +#define CAL_PIX_PROC_DPCMD_DPCM_14_8_1 0x10 +#define CAL_PIX_PROC_DPCMD_DPCM_16_12_1 0x12 +#define CAL_PIX_PROC_DPCMD_DPCM_16_10_1 0x14 +#define CAL_PIX_PROC_DPCMD_DPCM_16_8_1 0x16 +#define CAL_PIX_PROC_DPCME_MASK GENMASK(15, 11) +#define CAL_PIX_PROC_DPCME_BYPASS 0x0 +#define CAL_PIX_PROC_DPCME_DPCM_10_8_1 0x2 +#define CAL_PIX_PROC_DPCME_DPCM_12_8_1 0x8 +#define CAL_PIX_PROC_DPCME_DPCM_14_10 0xe +#define CAL_PIX_PROC_DPCME_DPCM_14_8_1 0x10 +#define CAL_PIX_PROC_DPCME_DPCM_16_12_1 0x12 +#define CAL_PIX_PROC_DPCME_DPCM_16_10_1 0x14 +#define CAL_PIX_PROC_DPCME_DPCM_16_8_1 0x16 +#define CAL_PIX_PROC_PACK_MASK GENMASK(18, 16) +#define CAL_PIX_PROC_PACK_B8 0x0 +#define CAL_PIX_PROC_PACK_B10_MIPI 0x2 +#define CAL_PIX_PROC_PACK_B12 0x3 +#define CAL_PIX_PROC_PACK_B12_MIPI 0x4 +#define CAL_PIX_PROC_PACK_B16 0x5 +#define CAL_PIX_PROC_PACK_ARGB 0x6 +#define CAL_PIX_PROC_CPORT_MASK GENMASK(23, 19) + +#define CAL_CTRL_POSTED_WRITES_MASK BIT_MASK(0) +#define CAL_CTRL_POSTED_WRITES_NONPOSTED 0 +#define CAL_CTRL_POSTED_WRITES 1 +#define CAL_CTRL_TAGCNT_MASK GENMASK(4, 1) +#define CAL_CTRL_BURSTSIZE_MASK GENMASK(6, 5) +#define CAL_CTRL_BURSTSIZE_BURST16 0x0 +#define CAL_CTRL_BURSTSIZE_BURST32 0x1 +#define CAL_CTRL_BURSTSIZE_BURST64 0x2 +#define CAL_CTRL_BURSTSIZE_BURST128 0x3 +#define CAL_CTRL_LL_FORCE_STATE_MASK GENMASK(12, 7) +#define CAL_CTRL_MFLAGL_MASK GENMASK(20, 13) +#define CAL_CTRL_PWRSCPCLK_MASK BIT_MASK(21) +#define CAL_CTRL_PWRSCPCLK_AUTO 0 +#define CAL_CTRL_PWRSCPCLK_FORCE 1 +#define CAL_CTRL_RD_DMA_STALL_MASK BIT_MASK(22) +#define CAL_CTRL_MFLAGH_MASK GENMASK(31, 24) + +#define CAL_CTRL1_PPI_GROUPING_MASK GENMASK(1, 0) +#define CAL_CTRL1_PPI_GROUPING_DISABLED 0 +#define CAL_CTRL1_PPI_GROUPING_RESERVED 1 +#define CAL_CTRL1_PPI_GROUPING_0 2 +#define CAL_CTRL1_PPI_GROUPING_1 3 +#define CAL_CTRL1_INTERLEAVE01_MASK GENMASK(3, 2) +#define CAL_CTRL1_INTERLEAVE01_DISABLED 0 +#define CAL_CTRL1_INTERLEAVE01_PIX1 1 +#define CAL_CTRL1_INTERLEAVE01_PIX4 2 +#define CAL_CTRL1_INTERLEAVE01_RESERVED 3 +#define CAL_CTRL1_INTERLEAVE23_MASK GENMASK(5, 4) +#define CAL_CTRL1_INTERLEAVE23_DISABLED 0 +#define CAL_CTRL1_INTERLEAVE23_PIX1 1 +#define CAL_CTRL1_INTERLEAVE23_PIX4 2 +#define CAL_CTRL1_INTERLEAVE23_RESERVED 3 + +#define CAL_LINE_NUMBER_EVT_CPORT_MASK GENMASK(4, 0) +#define CAL_LINE_NUMBER_EVT_MASK GENMASK(29, 16) + +#define CAL_VPORT_CTRL1_PCLK_MASK GENMASK(16, 0) +#define CAL_VPORT_CTRL1_XBLK_MASK GENMASK(24, 17) +#define CAL_VPORT_CTRL1_YBLK_MASK GENMASK(30, 25) +#define CAL_VPORT_CTRL1_WIDTH_MASK BIT_MASK(31) +#define CAL_VPORT_CTRL1_WIDTH_ONE 0 +#define CAL_VPORT_CTRL1_WIDTH_TWO 1 + +#define CAL_VPORT_CTRL2_CPORT_MASK GENMASK(4, 0) +#define CAL_VPORT_CTRL2_FREERUNNING_MASK BIT_MASK(15) +#define CAL_VPORT_CTRL2_FREERUNNING_GATED 0 +#define CAL_VPORT_CTRL2_FREERUNNING_FREE 1 +#define CAL_VPORT_CTRL2_FS_RESETS_MASK BIT_MASK(16) +#define CAL_VPORT_CTRL2_FS_RESETS_NO 0 +#define CAL_VPORT_CTRL2_FS_RESETS_YES 1 +#define CAL_VPORT_CTRL2_FSM_RESET_MASK BIT_MASK(17) +#define CAL_VPORT_CTRL2_FSM_RESET_NOEFFECT 0 +#define CAL_VPORT_CTRL2_FSM_RESET 1 +#define CAL_VPORT_CTRL2_RDY_THR_MASK GENMASK(31, 18) + +#define CAL_BYS_CTRL1_PCLK_MASK GENMASK(16, 0) +#define CAL_BYS_CTRL1_XBLK_MASK GENMASK(24, 17) +#define CAL_BYS_CTRL1_YBLK_MASK GENMASK(30, 25) +#define CAL_BYS_CTRL1_BYSINEN_MASK BIT_MASK(31) + +#define CAL_BYS_CTRL2_CPORTIN_MASK GENMASK(4, 0) +#define CAL_BYS_CTRL2_CPORTOUT_MASK GENMASK(9, 5) +#define CAL_BYS_CTRL2_DUPLICATEDDATA_MASK BIT_MASK(10) +#define CAL_BYS_CTRL2_DUPLICATEDDATA_NO 0 +#define CAL_BYS_CTRL2_DUPLICATEDDATA_YES 1 +#define CAL_BYS_CTRL2_FREERUNNING_MASK BIT_MASK(11) +#define CAL_BYS_CTRL2_FREERUNNING_NO 0 +#define CAL_BYS_CTRL2_FREERUNNING_YES 1 + +#define CAL_RD_DMA_CTRL_GO_MASK BIT_MASK(0) +#define CAL_RD_DMA_CTRL_GO_DIS 0 +#define CAL_RD_DMA_CTRL_GO_EN 1 +#define CAL_RD_DMA_CTRL_GO_IDLE 0 +#define CAL_RD_DMA_CTRL_GO_BUSY 1 +#define CAL_RD_DMA_CTRL_INIT_MASK BIT_MASK(1) +#define CAL_RD_DMA_CTRL_BW_LIMITER_MASK GENMASK(10, 2) +#define CAL_RD_DMA_CTRL_OCP_TAG_CNT_MASK GENMASK(14, 11) +#define CAL_RD_DMA_CTRL_PCLK_MASK GENMASK(31, 15) + +#define CAL_RD_DMA_PIX_ADDR_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_PIX_OFST_MASK GENMASK(31, 4) + +#define CAL_RD_DMA_XSIZE_MASK GENMASK(31, 19) + +#define CAL_RD_DMA_YSIZE_MASK GENMASK(29, 16) + +#define CAL_RD_DMA_INIT_ADDR_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_INIT_OFST_MASK GENMASK(31, 3) + +#define CAL_RD_DMA_CTRL2_CIRC_MODE_MASK GENMASK(2, 0) +#define CAL_RD_DMA_CTRL2_CIRC_MODE_DIS 0 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_ONE 1 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_FOUR 2 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTEEN 3 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_SIXTYFOUR 4 +#define CAL_RD_DMA_CTRL2_CIRC_MODE_RESERVED 5 +#define CAL_RD_DMA_CTRL2_ICM_CSTART_MASK BIT_MASK(3) +#define CAL_RD_DMA_CTRL2_PATTERN_MASK GENMASK(5, 4) +#define CAL_RD_DMA_CTRL2_PATTERN_LINEAR 0 +#define CAL_RD_DMA_CTRL2_PATTERN_YUV420 1 +#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP2 2 +#define CAL_RD_DMA_CTRL2_PATTERN_RD2SKIP4 3 +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_MASK BIT_MASK(6) +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_FREERUNNING 0 +#define CAL_RD_DMA_CTRL2_BYSOUT_LE_WAIT_WAITFORBYSOUT 1 +#define CAL_RD_DMA_CTRL2_CIRC_SIZE_MASK GENMASK(29, 16) + +#define CAL_WR_DMA_CTRL_MODE_MASK GENMASK(2, 0) +#define CAL_WR_DMA_CTRL_MODE_DIS 0 +#define CAL_WR_DMA_CTRL_MODE_SHD 1 +#define CAL_WR_DMA_CTRL_MODE_CNT 2 +#define CAL_WR_DMA_CTRL_MODE_CNT_INIT 3 +#define CAL_WR_DMA_CTRL_MODE_CONST 4 +#define CAL_WR_DMA_CTRL_MODE_RESERVED 5 +#define CAL_WR_DMA_CTRL_PATTERN_MASK GENMASK(4, 3) +#define CAL_WR_DMA_CTRL_PATTERN_LINEAR 0 +#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP2 2 +#define CAL_WR_DMA_CTRL_PATTERN_WR2SKIP4 3 +#define CAL_WR_DMA_CTRL_PATTERN_RESERVED 1 +#define CAL_WR_DMA_CTRL_ICM_PSTART_MASK BIT_MASK(5) +#define CAL_WR_DMA_CTRL_DTAG_MASK GENMASK(8, 6) +#define CAL_WR_DMA_CTRL_DTAG_ATT_HDR 0 +#define CAL_WR_DMA_CTRL_DTAG_ATT_DAT 1 +#define CAL_WR_DMA_CTRL_DTAG 2 +#define CAL_WR_DMA_CTRL_DTAG_PIX_HDR 3 +#define CAL_WR_DMA_CTRL_DTAG_PIX_DAT 4 +#define CAL_WR_DMA_CTRL_DTAG_D5 5 +#define CAL_WR_DMA_CTRL_DTAG_D6 6 +#define CAL_WR_DMA_CTRL_DTAG_D7 7 +#define CAL_WR_DMA_CTRL_CPORT_MASK GENMASK(13, 9) +#define CAL_WR_DMA_CTRL_STALL_RD_MASK BIT_MASK(14) +#define CAL_WR_DMA_CTRL_YSIZE_MASK GENMASK(31, 18) + +#define CAL_WR_DMA_ADDR_MASK GENMASK(31, 4) + +#define CAL_WR_DMA_OFST_MASK GENMASK(18, 4) +#define CAL_WR_DMA_OFST_CIRC_MODE_MASK GENMASK(23, 22) +#define CAL_WR_DMA_OFST_CIRC_MODE_ONE 1 +#define CAL_WR_DMA_OFST_CIRC_MODE_FOUR 2 +#define CAL_WR_DMA_OFST_CIRC_MODE_SIXTYFOUR 3 +#define CAL_WR_DMA_OFST_CIRC_MODE_DISABLED 0 +#define CAL_WR_DMA_OFST_CIRC_SIZE_MASK GENMASK(31, 24) + +#define CAL_WR_DMA_XSIZE_XSKIP_MASK GENMASK(15, 3) +#define CAL_WR_DMA_XSIZE_MASK GENMASK(31, 19) + +#define CAL_CSI2_PPI_CTRL_IF_EN_MASK BIT_MASK(0) +#define CAL_CSI2_PPI_CTRL_ECC_EN_MASK BIT_MASK(2) +#define CAL_CSI2_PPI_CTRL_FRAME_MASK BIT_MASK(3) +#define CAL_CSI2_PPI_CTRL_FRAME_IMMEDIATE 0 +#define CAL_CSI2_PPI_CTRL_FRAME 1 + +#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POSITION_MASK GENMASK(2, 0) +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_5 5 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_4 4 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_3 3 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_2 2 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_1 1 +#define CAL_CSI2_COMPLEXIO_CFG_POSITION_NOT_USED 0 +#define CAL_CSI2_COMPLEXIO_CFG_CLOCK_POL_MASK BIT_MASK(3) +#define CAL_CSI2_COMPLEXIO_CFG_POL_PLUSMINUS 0 +#define CAL_CSI2_COMPLEXIO_CFG_POL_MINUSPLUS 1 +#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POSITION_MASK GENMASK(6, 4) +#define CAL_CSI2_COMPLEXIO_CFG_DATA1_POL_MASK BIT_MASK(7) +#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POSITION_MASK GENMASK(10, 8) +#define CAL_CSI2_COMPLEXIO_CFG_DATA2_POL_MASK BIT_MASK(11) +#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POSITION_MASK GENMASK(14, 12) +#define CAL_CSI2_COMPLEXIO_CFG_DATA3_POL_MASK BIT_MASK(15) +#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POSITION_MASK GENMASK(18, 16) +#define CAL_CSI2_COMPLEXIO_CFG_DATA4_POL_MASK BIT_MASK(19) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_AUTO_MASK BIT_MASK(24) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_MASK GENMASK(26, 25) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_OFF 0 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ON 1 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_STATUS_STATE_ULP 2 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_MASK GENMASK(28, 27) +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_OFF 0 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ON 1 +#define CAL_CSI2_COMPLEXIO_CFG_PWR_CMD_STATE_ULP 2 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK BIT_MASK(29) +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETCOMPLETED 1 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING 0 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK BIT_MASK(30) +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL 0 +#define CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_OPERATIONAL 1 + +#define CAL_CSI2_SHORT_PACKET_MASK GENMASK(23, 0) + +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS1_MASK BIT_MASK(0) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS2_MASK BIT_MASK(1) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS3_MASK BIT_MASK(2) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS4_MASK BIT_MASK(3) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTHS5_MASK BIT_MASK(4) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS1_MASK BIT_MASK(5) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS2_MASK BIT_MASK(6) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS3_MASK BIT_MASK(7) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS4_MASK BIT_MASK(8) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRSOTSYNCHS5_MASK BIT_MASK(9) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC1_MASK BIT_MASK(10) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC2_MASK BIT_MASK(11) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC3_MASK BIT_MASK(12) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC4_MASK BIT_MASK(13) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRESC5_MASK BIT_MASK(14) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL1_MASK BIT_MASK(15) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL2_MASK BIT_MASK(16) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL3_MASK BIT_MASK(17) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL4_MASK BIT_MASK(18) +#define CAL_CSI2_COMPLEXIO_IRQ_ERRCONTROL5_MASK BIT_MASK(19) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM1_MASK BIT_MASK(20) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM2_MASK BIT_MASK(21) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM3_MASK BIT_MASK(22) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM4_MASK BIT_MASK(23) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEULPM5_MASK BIT_MASK(24) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEALLULPMENTER_MASK BIT_MASK(25) +#define CAL_CSI2_COMPLEXIO_IRQ_STATEALLULPMEXIT_MASK BIT_MASK(26) +#define CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK BIT_MASK(27) +#define CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK BIT_MASK(28) +#define CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK BIT_MASK(30) + +#define CAL_CSI2_TIMING_STOP_STATE_COUNTER_IO1_MASK GENMASK(12, 0) +#define CAL_CSI2_TIMING_STOP_STATE_X4_IO1_MASK BIT_MASK(13) +#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT_MASK(14) +#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT_MASK(15) + +#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT_MASK(0) +#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT_MASK(1) +#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT_MASK(2) +#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT_MASK(3) +#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT_MASK(4) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT_MASK(5) +#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT_MASK(8) +#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT_MASK(9) +#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT_MASK(10) +#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT_MASK(11) +#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT_MASK(12) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT_MASK(13) +#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT_MASK(16) +#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT_MASK(17) +#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT_MASK(18) +#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT_MASK(19) +#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT_MASK(20) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT_MASK(21) +#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT_MASK(24) +#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT_MASK(25) +#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT_MASK(26) +#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT_MASK(27) +#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT_MASK(28) +#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT_MASK(29) + +#define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0) +#define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6) +#define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8) +#define CAL_CSI2_CTX_ATT_MASK BIT_MASK(13) +#define CAL_CSI2_CTX_ATT_PIX 0 +#define CAL_CSI2_CTX_ATT 1 +#define CAL_CSI2_CTX_PACK_MODE_MASK BIT_MASK(14) +#define CAL_CSI2_CTX_PACK_MODE_LINE 0 +#define CAL_CSI2_CTX_PACK_MODE_FRAME 1 +#define CAL_CSI2_CTX_LINES_MASK GENMASK(29, 16) + +#define CAL_CSI2_STATUS_FRAME_MASK GENMASK(15, 0) + +#define CAL_CSI2_PHY_REG0_THS_SETTLE_MASK GENMASK(7, 0) +#define CAL_CSI2_PHY_REG0_THS_TERM_MASK GENMASK(15, 8) +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_MASK BIT_MASK(24) +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_DISABLE 1 +#define CAL_CSI2_PHY_REG0_HSCLOCKCONFIG_ENABLE 0 + +#define CAL_CSI2_PHY_REG1_TCLK_SETTLE_MASK GENMASK(7, 0) +#define CAL_CSI2_PHY_REG1_CTRLCLK_DIV_FACTOR_MASK GENMASK(9, 8) +#define CAL_CSI2_PHY_REG1_DPHY_HS_SYNC_PATTERN_MASK GENMASK(17, 10) +#define CAL_CSI2_PHY_REG1_TCLK_TERM_MASK GENMASK(24, 18) +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_MASK BIT_MASK(25) +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_ERROR 1 +#define CAL_CSI2_PHY_REG1_CLOCK_MISS_DETECTOR_STATUS_SUCCESS 0 +#define CAL_CSI2_PHY_REG1_RESET_DONE_STATUS_MASK GENMASK(29, 28) + +#define CAL_CSI2_PHY_REG2_CCP2_SYNC_PATTERN_MASK GENMASK(23, 0) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK GENMASK(25, 24) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK GENMASK(27, 26) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK GENMASK(29, 28) +#define CAL_CSI2_PHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK GENMASK(31, 30) + +#define CM_CAMERRX_CTRL_CSI1_CTRLCLKEN_MASK BIT_MASK(0) +#define CM_CAMERRX_CTRL_CSI1_CAMMODE_MASK GENMASK(2, 1) +#define CM_CAMERRX_CTRL_CSI1_LANEENABLE_MASK GENMASK(4, 3) +#define CM_CAMERRX_CTRL_CSI1_MODE_MASK BIT_MASK(5) +#define CM_CAMERRX_CTRL_CSI0_CTRLCLKEN_MASK BIT_MASK(10) +#define CM_CAMERRX_CTRL_CSI0_CAMMODE_MASK GENMASK(12, 11) +#define CM_CAMERRX_CTRL_CSI0_LANEENABLE_MASK GENMASK(16, 13) +#define CM_CAMERRX_CTRL_CSI0_MODE_MASK BIT_MASK(17) + +#endif -- cgit From 80100fd9ebb9f2414892a1178d26a4253e6c0bcf Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 11 Jan 2016 11:21:15 -0200 Subject: [media] media: v4l: Dual license v4l2-common.h under GPL v2 and BSD licenses The v4l2-common.h user space header was split off from videodev2.h, but the dual licensing of the videodev2.h (as well as other V4L2 headers) was missed. Change the license of the v4l2-common.h from GNU GPL v2 to both GNU GPL v2 and BSD. Sakari Ailus : > Would you approve a license change of the patches to > include/uapi/linux/v4l2-common.h (formerly include/linux/v4l2-common.h) you > or your company have contributed from GNU GPL v2 to dual GNU GPL v2 and BSD > licenses, changing the copyright notice in the file as below (from > videodev2.h): > > -------------8<------------ > * 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. > * > * Alternatively you can redistribute this file under the terms of the > * BSD license as stated below: > * > * 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. The names of its contributors may not 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. > -------------8<------------ Mauro Carvalho Chehab : > No problem from my side. Hans Verkuil : > Acked-by: Hans Verkuil Aaro Koskinen : > This fine also for us. > > Acked-by: Aaro Koskinen Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Acked-by: Aaro Koskinen Acked-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- include/uapi/linux/v4l2-common.h | 46 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/include/uapi/linux/v4l2-common.h b/include/uapi/linux/v4l2-common.h index 15273987093e..5b3f685a2d50 100644 --- a/include/uapi/linux/v4l2-common.h +++ b/include/uapi/linux/v4l2-common.h @@ -10,19 +10,43 @@ * Copyright (C) 2012 Nokia Corporation * Contact: Sakari Ailus * - * 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 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 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 St, Fifth Floor, Boston, MA - * 02110-1301 USA + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * 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. The names of its contributors may not 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. * */ -- cgit From 3f1321cbaa1f2221be7444b7fab0905a31bdfd9f Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:43:29 -0200 Subject: [media] media: rc: nuvoton-cir: improve nvt_hw_detect Check for the case that no Nuvoton chip is found on either EFM port. Also move the position of nvt_efm_disable to reduce the time the EFM ports are locked. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 17 +++++++++++++---- drivers/media/rc/nuvoton-cir.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 5790ee46a38d..f587a727df2e 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -291,7 +291,7 @@ static inline const char *nvt_find_chip(struct nvt_dev *nvt, int id) /* detect hardware features */ -static void nvt_hw_detect(struct nvt_dev *nvt) +static int nvt_hw_detect(struct nvt_dev *nvt) { const char *chip_name; int chip_id; @@ -306,10 +306,17 @@ static void nvt_hw_detect(struct nvt_dev *nvt) nvt_efm_enable(nvt); nvt->chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); } - nvt->chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); + nvt_efm_disable(nvt); + chip_id = nvt->chip_major << 8 | nvt->chip_minor; + if (chip_id == NVT_INVALID) { + dev_err(&nvt->pdev->dev, + "No device found on either EFM port\n"); + return -ENODEV; + } + chip_name = nvt_find_chip(nvt, chip_id); /* warn, but still let the driver load, if we don't know this chip */ @@ -322,7 +329,7 @@ static void nvt_hw_detect(struct nvt_dev *nvt) "found %s or compatible: chip id: 0x%02x 0x%02x", chip_name, nvt->chip_major, nvt->chip_minor); - nvt_efm_disable(nvt); + return 0; } static void nvt_cir_ldev_init(struct nvt_dev *nvt) @@ -1057,7 +1064,9 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) init_waitqueue_head(&nvt->tx.queue); - nvt_hw_detect(nvt); + ret = nvt_hw_detect(nvt); + if (ret) + goto exit_free_dev_rdev; /* Initialize CIR & CIR Wake Logical Devices */ nvt_efm_enable(nvt); diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 6a3de08a17c0..48c09c7a101c 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -68,7 +68,8 @@ enum nvt_chip_ver { NVT_W83667HG = 0xa510, NVT_6775F = 0xb470, NVT_6776F = 0xc330, - NVT_6779D = 0xc560 + NVT_6779D = 0xc560, + NVT_INVALID = 0xffff, }; struct nvt_chip { -- cgit From fb2b0065756a5ed6b6852e663574f9331d47fdec Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:44:36 -0200 Subject: [media] media: rc: nuvoton-cir: add locking to calls of nvt_enable_wake Add locking to nvt_enable_wake calls. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index f587a727df2e..3097ff0eb176 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -1174,16 +1174,16 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) nvt_dbg("%s called", __func__); - /* zero out misc state tracking */ - spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt->study_state = ST_STUDY_NONE; - nvt->wake_state = ST_WAKE_NONE; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - spin_lock_irqsave(&nvt->tx.lock, flags); nvt->tx.tx_state = ST_TX_NONE; spin_unlock_irqrestore(&nvt->tx.lock, flags); + spin_lock_irqsave(&nvt->nvt_lock, flags); + + /* zero out misc state tracking */ + nvt->study_state = ST_STUDY_NONE; + nvt->wake_state = ST_WAKE_NONE; + /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -1193,6 +1193,8 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* make sure wake is enabled */ nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + return 0; } @@ -1211,7 +1213,11 @@ static int nvt_resume(struct pnp_dev *pdev) static void nvt_shutdown(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_enable_wake(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static const struct pnp_device_id nvt_ids[] = { -- cgit From 88205f01fe30590d04c81f09f003af8c2cf6aeaf Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:45:00 -0200 Subject: [media] media: rc: nuvoton-cir: fix wakeup interrupt bits Most likely a copy & paste error. The wakeup interrupt supports less triggering events. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 48c09c7a101c..4a5650dffa29 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -293,10 +293,7 @@ struct nvt_dev { #define CIR_WAKE_IREN_RTR 0x40 #define CIR_WAKE_IREN_PE 0x20 #define CIR_WAKE_IREN_RFO 0x10 -#define CIR_WAKE_IREN_TE 0x08 -#define CIR_WAKE_IREN_TTR 0x04 -#define CIR_WAKE_IREN_TFU 0x02 -#define CIR_WAKE_IREN_GH 0x01 +#define CIR_WAKE_IREN_GH 0x08 /* CIR WAKE FIFOCON settings */ #define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 -- cgit From d42fd29769f52c056032bbf1b9b2d1d914fd145a Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:45:51 -0200 Subject: [media] media: rc: nuvoton-cir: fix interrupt handling Only handle an interrupt if at least one combination of event bit and related interrupt bit is set. Previously it was just checked that at least one event bit and at least one interrupt bit are set. This fixes issues like the following which was caused by interrupt sharing: An interrupt intended for nvt_cir_isr was handled by nvt_cir_wake_isr first and because status bit CIR_WAKE_IRSTS_IR_PENDING was set the wake fifo was accidently cleared. This patch also fixes the bug that nvt_cir_wake_isr returned IRQ_HANDLED even if it detected that the (shared) interrupt was meant for another handler. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 3097ff0eb176..291d870e618f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -825,9 +825,13 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * 0: CIR_IRSTS_GH - Min Length Detected */ status = nvt_cir_reg_read(nvt, CIR_IRSTS); - if (!status) { + iren = nvt_cir_reg_read(nvt, CIR_IREN); + + /* IRQ may be shared with CIR WAKE, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) { nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); return IRQ_NONE; } @@ -835,13 +839,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_cir_reg_write(nvt, status, CIR_IRSTS); nvt_cir_reg_write(nvt, 0, CIR_IRSTS); - /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ - iren = nvt_cir_reg_read(nvt, CIR_IREN); - if (!iren) { - nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); - return IRQ_NONE; - } - nvt_cir_log_irqs(status, iren); if (status & CIR_IRSTS_RTR) { @@ -914,7 +911,12 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); - if (!status) + iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); + + /* IRQ may be shared with CIR, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) return IRQ_NONE; if (status & CIR_WAKE_IRSTS_IR_PENDING) @@ -923,13 +925,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); - /* Interrupt may be shared with CIR, bail if Wake not enabled */ - iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); - if (!iren) { - nvt_dbg_wake("%s exiting, wake not enabled", __func__); - return IRQ_HANDLED; - } - if ((status & CIR_WAKE_IRSTS_PE) && (nvt->wake_state == ST_WAKE_START)) { while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { -- cgit From e60c1e87c76068c3756369048cd63ed6e55b0155 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 30 Dec 2015 14:46:29 -0200 Subject: [media] media: rc: nuvoton-cir: improve locking in both interrupt handlers Extend the locking to protect more critical actions like register accesses in the interrupt handlers. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 291d870e618f..d428b4e6e26f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -727,7 +727,6 @@ static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt) /* copy data from hardware rx fifo into driver buffer */ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) { - unsigned long flags; u8 fifocount, val; unsigned int b_idx; bool overrun = false; @@ -746,8 +745,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); - spin_lock_irqsave(&nvt->nvt_lock, flags); - b_idx = nvt->pkts; /* This should never happen, but lets check anyway... */ @@ -769,8 +766,6 @@ static void nvt_get_rx_ir_data(struct nvt_dev *nvt) if (overrun) nvt_handle_rx_fifo_overrun(nvt); - - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static void nvt_cir_log_irqs(u8 status, u8 iren) @@ -811,6 +806,8 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_dbg_verbose("%s firing", __func__); + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* * Get IR Status register contents. Write 1 to ack/clear * @@ -831,6 +828,7 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * status bit whether the related interrupt source is enabled */ if (!(status & iren)) { + spin_unlock_irqrestore(&nvt->nvt_lock, flags); nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); return IRQ_NONE; } @@ -852,16 +850,14 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) if (nvt_cir_tx_inactive(nvt)) nvt_get_rx_ir_data(nvt); - spin_lock_irqsave(&nvt->nvt_lock, flags); - cur_state = nvt->study_state; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - if (cur_state == ST_STUDY_NONE) nvt_clear_cir_fifo(nvt); } + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + if (status & CIR_IRSTS_TE) nvt_clear_tx_fifo(nvt); @@ -910,14 +906,18 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); + spin_lock_irqsave(&nvt->nvt_lock, flags); + status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); /* IRQ may be shared with CIR, therefore check for each * status bit whether the related interrupt source is enabled */ - if (!(status & iren)) + if (!(status & iren)) { + spin_unlock_irqrestore(&nvt->nvt_lock, flags); return IRQ_NONE; + } if (status & CIR_WAKE_IRSTS_IR_PENDING) nvt_clear_cir_wake_fifo(nvt); @@ -933,11 +933,11 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) } nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt->wake_state = ST_WAKE_FINISH; - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + nvt_dbg_wake("%s done", __func__); return IRQ_HANDLED; } -- cgit From 9398ddfe4ef38f26b8e25f510c5f6ffe01698e8b Mon Sep 17 00:00:00 2001 From: Andrei Koshkosh Date: Sun, 3 Jan 2016 23:31:26 -0200 Subject: [media] si2157.c: fix frequency range According with: https://www.silabs.com/Support%20Documents/TechnicalDocs/Si2157-short.pdf The RF input frequency range of this demod is from 42MHz to 870 MHz. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 0e1ca2b00e61..5da5b421d310 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -364,8 +364,8 @@ static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) static const struct dvb_tuner_ops si2157_ops = { .info = { .name = "Silicon Labs Si2146/2147/2148/2157/2158", - .frequency_min = 55000000, - .frequency_max = 862000000, + .frequency_min = 42000000, + .frequency_max = 870000000, }, .init = si2157_init, -- cgit From 93b66420a4eb846ed8859d25c0a2056486f2929d Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Mon, 4 Jan 2016 17:32:51 -0200 Subject: [media] dw2102: Add support for Terratec Cinergy S2 USB BOX The Terratec Cinergy S2 USB BOX uses a Montage M88TS2022 tuner and a M88DS3103 demodulator, same as Technotrend TT-connect S2-4600. This patch adds the missing USB Product ID to make it work. Signed-off-by: Philipp Zabel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/dw2102.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index bc19da5ad3b7..dd46d6c78c4e 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1688,6 +1688,7 @@ enum dw2102_table_entry { TECHNOTREND_S2_4600, TEVII_S482_1, TEVII_S482_2, + TERRATEC_CINERGY_S2_BOX, }; static struct usb_device_id dw2102_table[] = { @@ -1715,6 +1716,7 @@ static struct usb_device_id dw2102_table[] = { USB_PID_TECHNOTREND_CONNECT_S2_4600)}, [TEVII_S482_1] = {USB_DEVICE(0x9022, 0xd483)}, [TEVII_S482_2] = {USB_DEVICE(0x9022, 0xd484)}, + [TERRATEC_CINERGY_S2_BOX] = {USB_DEVICE(USB_VID_TERRATEC, 0x0105)}, { } }; @@ -2232,7 +2234,7 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { } }, } }, - .num_device_descs = 3, + .num_device_descs = 4, .devices = { { "TechnoTrend TT-connect S2-4600", { &dw2102_table[TECHNOTREND_S2_4600], NULL }, @@ -2246,6 +2248,10 @@ static struct dvb_usb_device_properties tt_s2_4600_properties = { { &dw2102_table[TEVII_S482_2], NULL }, { NULL }, }, + { "Terratec Cinergy S2 USB BOX", + { &dw2102_table[TERRATEC_CINERGY_S2_BOX], NULL }, + { NULL }, + }, } }; -- cgit From b8278f8b961a6a65a4939f646483866fb5bef112 Mon Sep 17 00:00:00 2001 From: Stefan Pöschel Date: Mon, 4 Jan 2016 19:16:55 -0200 Subject: [media] af9035: add support for 2nd tuner of MSI DigiVox Diversity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PIP tested with VLC. Diversity tested with the Windows driver. Signed-off-by: Stefan Pöschel Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/af9035.c | 4 ++-- drivers/media/usb/dvb-usb-v2/af9035.h | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index 6e02a15d39ce..b3c09fe54d9b 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -684,7 +684,7 @@ static int af9035_download_firmware(struct dvb_usb_device *d, if (ret < 0) goto err; - if (tmp == 1 || tmp == 3) { + if (tmp == 1 || tmp == 3 || tmp == 5) { /* configure gpioh1, reset & power slave demod */ ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); if (ret < 0) @@ -823,7 +823,7 @@ static int af9035_read_config(struct dvb_usb_device *d) if (ret < 0) goto err; - if (tmp == 1 || tmp == 3) + if (tmp == 1 || tmp == 3 || tmp == 5) state->dual_mode = true; dev_dbg(&d->udev->dev, "%s: ts mode=%d dual mode=%d\n", __func__, diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index 416a97f05ec8..df22001f9e41 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -112,9 +112,10 @@ static const u32 clock_lut_it9135[] = { * 0 TS * 1 DCA + PIP * 3 PIP + * 5 DCA + PIP * n DCA * - * Values 0 and 3 are seen to this day. 0 for single TS and 3 for dual TS. + * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS. */ #define EEPROM_BASE_AF9035 0x42fd -- cgit From d309c8bb70beef4128a78d5208e692800c68b8f0 Mon Sep 17 00:00:00 2001 From: Torbjörn Jansson Date: Wed, 6 Jan 2016 14:26:31 -0200 Subject: [media] dvb-usb-dvbsky: add new product id for TT CT2-4650 CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new product id to dvb-usb-dvbsky for new version of TechnoTrend CT2-4650 CI Signed-off-by: Torbjörn Jansson Reviewed-by: Olli Salonen Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb-usb-ids.h | 1 + drivers/media/usb/dvb-usb-v2/dvbsky.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h index 750d23f9928d..dbdbb84294c5 100644 --- a/drivers/media/dvb-core/dvb-usb-ids.h +++ b/drivers/media/dvb-core/dvb-usb-ids.h @@ -248,6 +248,7 @@ #define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d #define USB_PID_TECHNOTREND_CONNECT_S2_4600 0x3011 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI 0x3012 +#define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2 0x3015 #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c index 2d922b96ed83..02dbc6c45423 100644 --- a/drivers/media/usb/dvb-usb-v2/dvbsky.c +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c @@ -847,6 +847,10 @@ static const struct usb_device_id dvbsky_id_table[] = { USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI, &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI", RC_MAP_TT_1500) }, + { DVB_USB_DEVICE(USB_VID_TECHNOTREND, + USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2, + &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1", + RC_MAP_TT_1500) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_3, &dvbsky_t680c_props, "Terratec H7 Rev.4", -- cgit From 4c7cad4bbf718e73a49e236e2b79489f1ee83810 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Thu, 7 Jan 2016 06:35:21 -0200 Subject: [media] rtl28xxu: retry failed i2c messages Sometimes i2c transfer fails. That happens especially when large amount of data is written sequentially eg. firmware download. Problem arises with both integrated rtl2832 demod and external mn88472 demod, which is clear indicator it is busy i2c bus issue. Use i2c core retry logic in order fix the issue by repeating failed message. Another solution which also works is to add ~100us delay between i2c messages - but repeating sounds more elegant and does not cause any extra delay for success cases. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb-v2/rtl28xxu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index eb5787a3191e..c4c6e92e8643 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -259,6 +259,10 @@ static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ret = -EOPNOTSUPP; } + /* Retry failed I2C messages */ + if (ret == -EPIPE) + ret = -EAGAIN; + err_mutex_unlock: mutex_unlock(&d->i2c_mutex); @@ -619,6 +623,10 @@ static int rtl28xxu_identify_state(struct dvb_usb_device *d, const char **name) } dev_dbg(&d->intf->dev, "chip_id=%u\n", dev->chip_id); + /* Retry failed I2C messages */ + d->i2c_adap.retries = 1; + d->i2c_adap.timeout = msecs_to_jiffies(10); + return WARM; err: dev_dbg(&d->intf->dev, "failed=%d\n", ret); -- cgit From 631c694f7d7e17147bcf6c7c3669c8f4dc84cc09 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:45 -0200 Subject: [media] af9013: cancel_delayed_work_sync before device removal / kfree af9013_remove was calling kfree(state) with possibly still active schedule_delayed_work(&state->statistics_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9013.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index e23197da84af..41ab5defb798 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -1344,6 +1344,10 @@ err: static void af9013_release(struct dvb_frontend *fe) { struct af9013_state *state = fe->demodulator_priv; + + /* stop statistics polling */ + cancel_delayed_work_sync(&state->statistics_work); + kfree(state); } -- cgit From 4bdcaa054e1c73697b390c32c434d96836121306 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:46 -0200 Subject: [media] af9033: cancel_delayed_work_sync before device removal / kfree af9033_remove was calling kfree(dev) with possibly still active schedule_delayed_work(&dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/af9033.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index bc35206a0821..8b328d1ca8d3 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -1372,6 +1372,9 @@ static int af9033_remove(struct i2c_client *client) dev_dbg(&dev->client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + dev->fe.ops.release = NULL; dev->fe.demodulator_priv = NULL; kfree(dev); -- cgit From 01d1d714e26624bc50ba95c49cf6e15bb215c150 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:43 -0200 Subject: [media] si2157: cancel_delayed_work_sync before device removal / kfree si2157_remove was calling kfree(dev) with possibly still active schedule_delayed_work(dev->stat_work). This caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/si2157.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c index 5da5b421d310..3450dfb7c427 100644 --- a/drivers/media/tuners/si2157.c +++ b/drivers/media/tuners/si2157.c @@ -458,6 +458,9 @@ static int si2157_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops)); fe->tuner_priv = NULL; kfree(dev); -- cgit From 4fd57ed61564bd4706e71cfd8c5a259079ddabf3 Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:47 -0200 Subject: [media] rtl2830: cancel_delayed_work_sync before device removal / kfree rtl2830_remove was calling kfree(dev) with possibly still active schedule_delayed_work(&dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/rtl2830.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index b792f305cf15..74b771218033 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -900,6 +900,9 @@ static int rtl2830_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + cancel_delayed_work_sync(&dev->stat_work); + i2c_del_mux_adapter(dev->adapter); regmap_exit(dev->regmap); kfree(dev); -- cgit From 41ff9142df375ac319b1d9fe50d88e4247da6f1a Mon Sep 17 00:00:00 2001 From: Ernst Martin Witte Date: Sat, 9 Jan 2016 18:18:44 -0200 Subject: [media] ts2020: cancel_delayed_work_sync before device removal / kfree ts2020_remove was calling kfree(dev) with possibly still active schedule_delayed_work(dev->stat_work). A similar bug in si2157 caused kernel panics in call_timer_fn e.g. after rmmod cx23885. Signed-off-by: Ernst Martin Witte Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/ts2020.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c index 7979e5d6498b..14b410ffe612 100644 --- a/drivers/media/dvb-frontends/ts2020.c +++ b/drivers/media/dvb-frontends/ts2020.c @@ -712,6 +712,10 @@ static int ts2020_remove(struct i2c_client *client) dev_dbg(&client->dev, "\n"); + /* stop statistics polling */ + if (!dev->dont_poll) + cancel_delayed_work_sync(&dev->stat_work); + regmap_exit(dev->regmap); kfree(dev); return 0; -- cgit From df47512d59c0db59a6785f0208001a4b7dd90aaf Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 10 Jan 2016 05:20:16 -0200 Subject: [media] netup_unidvb: Remove a useless memset This memory is allocated using kzalloc so there is no need to call memset(..., 0, ...) [mchehab@osg.samsung.com: as suggested by Joe Perches, It's unusual to not see the alloc above the if, removed a blank line between kzalloc/if and added a blank line after if] Signed-off-by: Christophe JAILLET Signed-off-by: Mauro Carvalho Chehab --- drivers/media/pci/netup_unidvb/netup_unidvb_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 525ebfefeee8..c94cecd2aa40 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -771,10 +771,9 @@ static int netup_unidvb_initdev(struct pci_dev *pci_dev, /* allocate device context */ ndev = kzalloc(sizeof(*ndev), GFP_KERNEL); - if (!ndev) goto dev_alloc_err; - memset(ndev, 0, sizeof(*ndev)); + ndev->old_fw = old_firmware; ndev->wq = create_singlethread_workqueue(NETUP_UNIDVB_NAME); if (!ndev->wq) { -- cgit From 417b552331df8181e8033503c1cb2749290073e7 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 11 Jan 2016 00:13:20 -0200 Subject: [media] rcar_jpu: Add R-Car Gen2 Fallback Compatibility String Add fallback compatibility string. This is in keeping with the fallback scheme being adopted wherever appropriate for drivers for Renesas SoCs. Signed-off-by: Simon Horman Acked-by: Rob Herring Signed-off-by: Mauro Carvalho Chehab --- Documentation/devicetree/bindings/media/renesas,jpu.txt | 13 +++++++------ drivers/media/platform/rcar_jpu.c | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/media/renesas,jpu.txt b/Documentation/devicetree/bindings/media/renesas,jpu.txt index 0cb94201bf92..d3436e5190f9 100644 --- a/Documentation/devicetree/bindings/media/renesas,jpu.txt +++ b/Documentation/devicetree/bindings/media/renesas,jpu.txt @@ -5,11 +5,12 @@ and decoding function conforming to the JPEG baseline process, so that the JPU can encode image data and decode JPEG data quickly. Required properties: - - compatible: should containg one of the following: - - "renesas,jpu-r8a7790" for R-Car H2 - - "renesas,jpu-r8a7791" for R-Car M2-W - - "renesas,jpu-r8a7792" for R-Car V2H - - "renesas,jpu-r8a7793" for R-Car M2-N +- compatible: "renesas,jpu-", "renesas,rcar-gen2-jpu" as fallback. + Examples with soctypes are: + - "renesas,jpu-r8a7790" for R-Car H2 + - "renesas,jpu-r8a7791" for R-Car M2-W + - "renesas,jpu-r8a7792" for R-Car V2H + - "renesas,jpu-r8a7793" for R-Car M2-N - reg: Base address and length of the registers block for the JPU. - interrupts: JPU interrupt specifier. @@ -17,7 +18,7 @@ Required properties: Example: R8A7790 (R-Car H2) JPU node jpeg-codec@fe980000 { - compatible = "renesas,jpu-r8a7790"; + compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu"; reg = <0 0xfe980000 0 0x10300>; interrupts = <0 272 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7790_CLK_JPU>; diff --git a/drivers/media/platform/rcar_jpu.c b/drivers/media/platform/rcar_jpu.c index 485f5259acb0..552789a69c86 100644 --- a/drivers/media/platform/rcar_jpu.c +++ b/drivers/media/platform/rcar_jpu.c @@ -1613,6 +1613,7 @@ static const struct of_device_id jpu_dt_ids[] = { { .compatible = "renesas,jpu-r8a7791" }, /* M2-W */ { .compatible = "renesas,jpu-r8a7792" }, /* V2H */ { .compatible = "renesas,jpu-r8a7793" }, /* M2-N */ + { .compatible = "renesas,rcar-gen2-jpu" }, { }, }; MODULE_DEVICE_TABLE(of, jpu_dt_ids); -- cgit From 8aeec38f9c61b4dfdfd2a4a74d111590b4b83230 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 11 Jan 2016 02:07:42 -0200 Subject: [media] v4l: Merge the YUV and YVU 4:2:0 tri-planar non-contiguous formats docs The two formats are very similar, having two separate pages to describe them is overkill. Signed-off-by: Laurent Pinchart Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml | 26 ++-- Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml | 154 --------------------- Documentation/DocBook/media/v4l/pixfmt.xml | 1 - 3 files changed, 17 insertions(+), 164 deletions(-) delete mode 100644 Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml index e781cc61786c..7d13fe96657d 100644 --- a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml +++ b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml @@ -1,35 +1,43 @@ - + - V4L2_PIX_FMT_YUV420M ('YM12') + V4L2_PIX_FMT_YUV420M ('YM12'), V4L2_PIX_FMT_YVU420M ('YM21') &manvol; - V4L2_PIX_FMT_YUV420M - Variation of V4L2_PIX_FMT_YUV420 - with planes non contiguous in memory. + V4L2_PIX_FMT_YUV420M + V4L2_PIX_FMT_YVU420M + Variation of V4L2_PIX_FMT_YUV420 and + V4L2_PIX_FMT_YVU420 with planes non contiguous + in memory. Description This is a multi-planar format, as opposed to a packed format. -The three components are separated into three sub- images or planes. +The three components are separated into three sub-images or planes. -The Y plane is first. The Y plane has one byte per pixel. The Cb data + The Y plane is first. The Y plane has one byte per pixel. +For V4L2_PIX_FMT_YUV420M the Cb data constitutes the second plane which is half the width and half the height of the Y plane (and of the image). Each Cb belongs to four pixels, a two-by-two square of the image. For example, Cb0 belongs to Y'00, Y'01, Y'10, and Y'11. The Cr data, just like the Cb plane, is -in the third plane. +in the third plane. + + V4L2_PIX_FMT_YVU420M is the same except +the Cr data is stored in the second plane and the Cb data in the third plane. + If the Y plane has pad bytes after each row, then the Cb and Cr planes have half as many pad bytes after their rows. In other words, two Cx rows (including padding) is exactly as long as one Y row (including padding). - V4L2_PIX_FMT_YUV420M is intended to be + V4L2_PIX_FMT_YUV420M and +V4L2_PIX_FMT_YVU420M are intended to be used only in drivers and applications that support the multi-planar API, described in . diff --git a/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml deleted file mode 100644 index 2330667907c7..000000000000 --- a/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml +++ /dev/null @@ -1,154 +0,0 @@ - - - V4L2_PIX_FMT_YVU420M ('YM21') - &manvol; - - - V4L2_PIX_FMT_YVU420M - Variation of V4L2_PIX_FMT_YVU420 - with planes non contiguous in memory. - - - - Description - - This is a multi-planar format, as opposed to a packed format. -The three components are separated into three sub-images or planes. - -The Y plane is first. The Y plane has one byte per pixel. The Cr data -constitutes the second plane which is half the width and half -the height of the Y plane (and of the image). Each Cr belongs to four -pixels, a two-by-two square of the image. For example, -Cr0 belongs to Y'00, -Y'01, Y'10, and -Y'11. The Cb data, just like the Cr plane, constitutes -the third plane. - - If the Y plane has pad bytes after each row, then the Cr -and Cb planes have half as many pad bytes after their rows. In other -words, two Cx rows (including padding) is exactly as long as one Y row -(including padding). - - V4L2_PIX_FMT_YVU420M is intended to be -used only in drivers and applications that support the multi-planar API, -described in . - - - <constant>V4L2_PIX_FMT_YVU420M</constant> 4 × 4 -pixel image - - - Byte Order. - Each cell is one byte. - - - - - - start0 + 0: - Y'00 - Y'01 - Y'02 - Y'03 - - - start0 + 4: - Y'10 - Y'11 - Y'12 - Y'13 - - - start0 + 8: - Y'20 - Y'21 - Y'22 - Y'23 - - - start0 + 12: - Y'30 - Y'31 - Y'32 - Y'33 - - - - start1 + 0: - Cr00 - Cr01 - - - start1 + 2: - Cr10 - Cr11 - - - - start2 + 0: - Cb00 - Cb01 - - - start2 + 2: - Cb10 - Cb11 - - - - - - - - - Color Sample Location. - - - - - - - 01 - 23 - - - 0 - YY - YY - - - - C - C - - - 1 - YY - YY - - - - - - 2 - YY - YY - - - - C - C - - - 3 - YY - YY - - - - - - - - - diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml index d871245d2973..9e77ff353feb 100644 --- a/Documentation/DocBook/media/v4l/pixfmt.xml +++ b/Documentation/DocBook/media/v4l/pixfmt.xml @@ -1628,7 +1628,6 @@ information. &sub-y41p; &sub-yuv420; &sub-yuv420m; - &sub-yvu420m; &sub-yuv410; &sub-yuv422p; &sub-yuv411p; -- cgit From f7842cfd3cab4566b28ede860344fcf8a7b409f6 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:09 -0200 Subject: [media] v4l: of: Correct v4l2_of_parse_endpoint() kernel-doc The v4l2_of_parse_endpoint function kernel-doc says that the return value is always 0. But that is not true since the function can fail and a error negative code is returned on failure. So correct the kernel-doc to match. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-of.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-of.c b/drivers/media/v4l2-core/v4l2-of.c index b27cbb1f5afe..93b33681776c 100644 --- a/drivers/media/v4l2-core/v4l2-of.c +++ b/drivers/media/v4l2-core/v4l2-of.c @@ -146,7 +146,7 @@ static void v4l2_of_parse_parallel_bus(const struct device_node *node, * variable without a low fixed limit. Please use * v4l2_of_alloc_parse_endpoint() in new drivers instead. * - * Return: 0. + * Return: 0 on success or a negative error code on failure. */ int v4l2_of_parse_endpoint(const struct device_node *node, struct v4l2_of_endpoint *endpoint) -- cgit From 7f6cd6c40d7bf3c640294359a8a835d03c94d634 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:10 -0200 Subject: [media] adv7604: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 5d4dbd05f9d6..801a9b09d5e5 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2820,6 +2820,7 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) struct device_node *endpoint; struct device_node *np; unsigned int flags; + int ret; u32 v; np = state->i2c_clients[ADV76XX_PAGE_IO]->dev.of_node; @@ -2829,7 +2830,11 @@ static int adv76xx_parse_dt(struct adv76xx_state *state) if (!endpoint) return -EINVAL; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); + ret = v4l2_of_parse_endpoint(endpoint, &bus_cfg); + if (ret) { + of_node_put(endpoint); + return ret; + } if (!of_property_read_u32(endpoint, "default-input", &v)) state->pdata.default_input = v; -- cgit From fda8b13ddce96335de2c6ae46bd3b14829318afe Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:11 -0200 Subject: [media] s5c73m3: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 57b3d27993a4..08af58fb8e7d 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1639,8 +1639,10 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) return 0; } - v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_of_parse_endpoint(node_ep, &ep); of_node_put(node_ep); + if (ret) + return ret; if (ep.bus_type != V4L2_MBUS_CSI2) { dev_err(dev, "unsupported bus type\n"); -- cgit From 2388309c7480550e64e20221640f6a5c717be662 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:12 -0200 Subject: [media] s5k5baf: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k5baf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index fc3a5a8e6c9c..db82ed05792e 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -1868,8 +1868,11 @@ static int s5k5baf_parse_device_node(struct s5k5baf *state, struct device *dev) return -EINVAL; } - v4l2_of_parse_endpoint(node_ep, &ep); + ret = v4l2_of_parse_endpoint(node_ep, &ep); of_node_put(node_ep); + if (ret) + return ret; + state->bus_type = ep.bus_type; switch (state->bus_type) { -- cgit From fe1e6ac6145b82f17c19653fc6bde626dfd8d861 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:13 -0200 Subject: [media] tvp514x: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp514x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c index 7fa5f1e4fe37..7cdd94842938 100644 --- a/drivers/media/i2c/tvp514x.c +++ b/drivers/media/i2c/tvp514x.c @@ -1001,7 +1001,7 @@ static struct tvp514x_decoder tvp514x_dev = { static struct tvp514x_platform_data * tvp514x_get_pdata(struct i2c_client *client) { - struct tvp514x_platform_data *pdata; + struct tvp514x_platform_data *pdata = NULL; struct v4l2_of_endpoint bus_cfg; struct device_node *endpoint; unsigned int flags; @@ -1013,11 +1013,13 @@ tvp514x_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; + if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + goto done; + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) goto done; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) -- cgit From baf40b5f79e0d8579cef5beaa18a91980dc77bfd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:14 -0200 Subject: [media] tvp7002: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Acked-by: Lad, Prabhakar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp7002.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c index 83c79fa5f61d..4df640c3aa40 100644 --- a/drivers/media/i2c/tvp7002.c +++ b/drivers/media/i2c/tvp7002.c @@ -894,7 +894,7 @@ static struct tvp7002_config * tvp7002_get_pdata(struct i2c_client *client) { struct v4l2_of_endpoint bus_cfg; - struct tvp7002_config *pdata; + struct tvp7002_config *pdata = NULL; struct device_node *endpoint; unsigned int flags; @@ -905,11 +905,13 @@ tvp7002_get_pdata(struct i2c_client *client) if (!endpoint) return NULL; + if (v4l2_of_parse_endpoint(endpoint, &bus_cfg)) + goto done; + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) goto done; - v4l2_of_parse_endpoint(endpoint, &bus_cfg); flags = bus_cfg.bus.parallel.flags; if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) -- cgit From 234eab8407afbedb4428012f8292357db75e24cd Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:15 -0200 Subject: [media] exynos4-is: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 8 +++++++- drivers/media/platform/exynos4-is/mipi-csis.c | 10 +++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f3b2dd30ec77..662d4a5c584e 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -332,13 +332,19 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, struct fimc_source_info *pd = &fmd->sensor[index].pdata; struct device_node *rem, *ep, *np; struct v4l2_of_endpoint endpoint; + int ret; /* Assume here a port node can have only one endpoint node. */ ep = of_get_next_child(port, NULL); if (!ep) return 0; - v4l2_of_parse_endpoint(ep, &endpoint); + ret = v4l2_of_parse_endpoint(ep, &endpoint); + if (ret) { + of_node_put(ep); + return ret; + } + if (WARN_ON(endpoint.base.port == 0) || index >= FIMC_MAX_SENSORS) return -EINVAL; diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index ac5e50e595be..bd5c46c3d4b7 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -736,6 +736,7 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, { struct device_node *node = pdev->dev.of_node; struct v4l2_of_endpoint endpoint; + int ret; if (of_property_read_u32(node, "clock-frequency", &state->clk_frequency)) @@ -751,7 +752,9 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, return -EINVAL; } /* Get port node and validate MIPI-CSI channel id. */ - v4l2_of_parse_endpoint(node, &endpoint); + ret = v4l2_of_parse_endpoint(node, &endpoint); + if (ret) + goto err; state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0; if (state->index >= CSIS_MAX_ENTITIES) @@ -764,9 +767,10 @@ static int s5pcsis_parse_dt(struct platform_device *pdev, "samsung,csis-wclk"); state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes; - of_node_put(node); - return 0; +err: + of_node_put(node); + return ret; } static int s5pcsis_pm_resume(struct device *dev, bool runtime); -- cgit From c517b35211aed34cb7c78d508a0b9fb209fd60c9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 11 Jan 2016 14:47:16 -0200 Subject: [media] omap3isp: Check v4l2_of_parse_endpoint() return value The v4l2_of_parse_endpoint() function can fail so check the return value. Signed-off-by: Javier Martinez Canillas Acked-by: Sakari Ailus Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/omap3isp/isp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 67efa9ea551e..f9e5245f26ac 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2235,8 +2235,11 @@ static int isp_of_parse_node(struct device *dev, struct device_node *node, struct isp_bus_cfg *buscfg = &isd->bus; struct v4l2_of_endpoint vep; unsigned int i; + int ret; - v4l2_of_parse_endpoint(node, &vep); + ret = v4l2_of_parse_endpoint(node, &vep); + if (ret) + return ret; dev_dbg(dev, "parsing endpoint %s, interface %u\n", node->full_name, vep.base.port); -- cgit From c89f8d47a171243fcac56b136e8526189035f8ee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 12:23:51 -0200 Subject: [media] s5c73m3: remove duplicate module device table Clang complains about an extraneous definition of the module device table after the patch to add it was accidentally merged twice: ../drivers/media/i2c/s5c73m3/s5c73m3-spi.c:40:1: error: redefinition of '__mod_of__s5c73m3_spi_ids_device_table' MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); ^ ../include/linux/module.h:223:27: note: expanded from macro 'MODULE_DEVICE_TABLE' extern const typeof(name) __mod_##type##__##name##_device_table \ ^ :99:1: note: expanded from here __mod_of__s5c73m3_spi_ids_device_table This removes the second definition. Fixes: f934a94bb566 ("[media] s5c73m3: Export OF module alias information") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5c73m3/s5c73m3-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c index 7d65b36434b1..72ef9f936e6c 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c @@ -37,7 +37,6 @@ enum spi_direction { SPI_DIR_RX, SPI_DIR_TX }; -MODULE_DEVICE_TABLE(of, s5c73m3_spi_ids); static int spi_xmit(struct spi_device *spi_dev, void *addr, const int len, enum spi_direction dir) -- cgit From 7445e45d19a09e5269dc85f17f9635be29d2f76c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 22 Jan 2016 08:53:55 -0200 Subject: [media] pwc: Add USB id for Philips Spc880nc webcam SPC 880NC PC camera discussions: http://www.pclinuxos.com/forum/index.php/topic,135688.0.html Cc: stable@vger.kernel.org Reported-by: Kikim Signed-off-by: Hans de Goede Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/pwc/pwc-if.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 086cf1c7bd7d..18aed5dd325e 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -91,6 +91,7 @@ static const struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */ + { USB_DEVICE(0x0471, 0x032C) }, /* Philips SPC 880NC PC Camera */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ @@ -810,6 +811,11 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id name = "Philips SPC 900NC webcam"; type_id = 740; break; + case 0x032C: + PWC_INFO("Philips SPC 880NC USB webcam detected.\n"); + name = "Philips SPC 880NC webcam"; + type_id = 740; + break; default: return -ENODEV; break; -- cgit From eac287adb305820661f528e35a50bd54d7c515f1 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:15:00 -0200 Subject: [media] dvbdev: remove useless parentheses after return The parentheses are not required after return, and just remove it. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a7de62ebc415..a48421e96b5e 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -352,7 +352,7 @@ static int dvb_create_media_entity(struct dvb_device *dvbdev, ret = media_device_register_entity(dvbdev->adapter->mdev, dvbdev->entity); if (ret) - return (ret); + return ret; printk(KERN_DEBUG "%s: media entity '%s' registered.\n", __func__, dvbdev->entity->name); -- cgit From 5c3fbc5e033ae2e089883c7294304a9a5bf404b2 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:14:58 -0200 Subject: [media] dvbdev: replace kcalloc with kzalloc Since the number of elements equals to 1, so just use kzalloc to simplify the code and make it more readable. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index a48421e96b5e..9fd687a1f593 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -620,8 +620,7 @@ int dvb_create_media_graph(struct dvb_adapter *adap, return -ENOMEM; adap->conn = conn; - adap->conn_pads = kcalloc(1, sizeof(*adap->conn_pads), - GFP_KERNEL); + adap->conn_pads = kzalloc(sizeof(*adap->conn_pads), GFP_KERNEL); if (!adap->conn_pads) return -ENOMEM; -- cgit From 0ede1876f7eb43ee6a47f5081d8902db6dd8b4ab Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Fri, 15 Jan 2016 03:14:59 -0200 Subject: [media] dvbdev: the space is required after ',' The space is missing after ',', and this will be introduce much noise when checking new patch around them. Signed-off-by: Xiubo Li Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c index 9fd687a1f593..1b9732ee0a4f 100644 --- a/drivers/media/dvb-core/dvbdev.c +++ b/drivers/media/dvb-core/dvbdev.c @@ -58,7 +58,7 @@ static const char * const dnames[] = { #define DVB_MAX_IDS MAX_DVB_MINORS #else #define DVB_MAX_IDS 4 -#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) +#define nums2minor(num, type, id) ((num << 6) | (id << 4) | type) #define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64) #endif @@ -85,7 +85,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) file->private_data = dvbdev; replace_fops(file, new_fops); if (file->f_op->open) - err = file->f_op->open(inode,file); + err = file->f_op->open(inode, file); up_read(&minor_rwsem); mutex_unlock(&dvbdev_mutex); return err; @@ -867,7 +867,7 @@ int dvb_usercopy(struct file *file, parg = sbuf; } else { /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); if (NULL == mbuf) return -ENOMEM; parg = mbuf; -- cgit From 458a39523542c4479a69b98743436fb761f03796 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Mon, 25 Jan 2016 13:21:37 -0200 Subject: [media] media: platform: exynos4-is: media-dev: Add missing of_node_put for_each_available_child_of_node and for_each_child_of_node perform an of_node_get on each iteration, so to break out of the loop an of_node_put is required. Found using Coccinelle. The simplified version of the semantic patch that is used for this is as follows: // @@ local idexpression n; expression e,r; @@ for_each_available_child_of_node(r,n) { ... ( of_node_put(n); | e = n | + of_node_put(n); ? break; ) ... } ... when != n // Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Krzysztof Kozlowski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/exynos4-is/media-dev.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index 662d4a5c584e..26a4e5c7b47a 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -435,8 +435,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) continue; ret = fimc_md_parse_port_node(fmd, port, index); - if (ret < 0) + if (ret < 0) { + of_node_put(node); goto rpm_put; + } index++; } @@ -447,8 +449,10 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) for_each_child_of_node(ports, node) { ret = fimc_md_parse_port_node(fmd, node, index); - if (ret < 0) + if (ret < 0) { + of_node_put(node); break; + } index++; } rpm_put: @@ -656,8 +660,10 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd, ret = fimc_md_register_platform_entity(fmd, pdev, plat_entity); put_device(&pdev->dev); - if (ret < 0) + if (ret < 0) { + of_node_put(node); break; + } } return ret; -- cgit From 9f93a8a0ba91fa3babe76a428e6c24f4c39f125e Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 26 Jan 2016 20:25:38 +0800 Subject: crypto: api - Introduce crypto_queue_len() helper function This patch introduces crypto_queue_len() helper function to help to get the queue length in the crypto queue list now. Signed-off-by: Baolin Wang Signed-off-by: Herbert Xu --- include/crypto/algapi.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index c9fe145f7dd3..4f861c44d066 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -184,6 +184,10 @@ int crypto_enqueue_request(struct crypto_queue *queue, struct crypto_async_request *request); struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue); int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm); +static inline unsigned int crypto_queue_len(struct crypto_queue *queue) +{ + return queue->qlen; +} /* These functions require the input/output to be aligned as u32. */ void crypto_inc(u8 *a, unsigned int size); -- cgit From 735d37b5424b27aa685276b8b90b7e57c4705ac1 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 26 Jan 2016 20:25:39 +0800 Subject: crypto: engine - Introduce the block request crypto engine framework Now block cipher engines need to implement and maintain their own queue/thread for processing requests, moreover currently helpers provided for only the queue itself (in crypto_enqueue_request() and crypto_dequeue_request()) but they don't help with the mechanics of driving the hardware (things like running the request immediately, DMA map it or providing a thread to process the queue in) even though a lot of that code really shouldn't vary that much from device to device. Thus this patch provides a mechanism for pushing requests to the hardware as it becomes free that drivers could use. And this framework is patterned on the SPI code and has worked out well there. (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/ drivers/spi/spi.c?id=ffbbdd21329f3e15eeca6df2d4bc11c04d9d91c0) Signed-off-by: Baolin Wang Signed-off-by: Herbert Xu --- crypto/Kconfig | 3 + crypto/Makefile | 1 + crypto/crypto_engine.c | 355 ++++++++++++++++++++++++++++++++++++++++++++++++ include/crypto/algapi.h | 70 ++++++++++ 4 files changed, 429 insertions(+) create mode 100644 crypto/crypto_engine.c diff --git a/crypto/Kconfig b/crypto/Kconfig index 099f1f1b0857..f6bfdda1a0b9 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -217,6 +217,9 @@ config CRYPTO_GLUE_HELPER_X86 depends on X86 select CRYPTO_ALGAPI +config CRYPTO_ENGINE + tristate + comment "Authenticated Encryption with Associated Data" config CRYPTO_CCM diff --git a/crypto/Makefile b/crypto/Makefile index 059de1bb254b..4f4ef7eaae3f 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -7,6 +7,7 @@ crypto-y := api.o cipher.o compress.o memneq.o obj-$(CONFIG_CRYPTO_WORKQUEUE) += crypto_wq.o +obj-$(CONFIG_CRYPTO_ENGINE) += crypto_engine.o obj-$(CONFIG_CRYPTO_FIPS) += fips.o crypto_algapi-$(CONFIG_PROC_FS) += proc.o diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c new file mode 100644 index 000000000000..a55c82dd48ef --- /dev/null +++ b/crypto/crypto_engine.c @@ -0,0 +1,355 @@ +/* + * Handle async block request by crypto hardware engine. + * + * Copyright (C) 2016 Linaro, Inc. + * + * Author: Baolin Wang + * + * 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 "internal.h" + +#define CRYPTO_ENGINE_MAX_QLEN 10 + +void crypto_finalize_request(struct crypto_engine *engine, + struct ablkcipher_request *req, int err); + +/** + * crypto_pump_requests - dequeue one request from engine queue to process + * @engine: the hardware engine + * @in_kthread: true if we are in the context of the request pump thread + * + * This function checks if there is any request in the engine queue that + * needs processing and if so call out to the driver to initialize hardware + * and handle each request. + */ +static void crypto_pump_requests(struct crypto_engine *engine, + bool in_kthread) +{ + struct crypto_async_request *async_req, *backlog; + struct ablkcipher_request *req; + unsigned long flags; + bool was_busy = false; + int ret; + + spin_lock_irqsave(&engine->queue_lock, flags); + + /* Make sure we are not already running a request */ + if (engine->cur_req) + goto out; + + /* If another context is idling then defer */ + if (engine->idling) { + queue_kthread_work(&engine->kworker, &engine->pump_requests); + goto out; + } + + /* Check if the engine queue is idle */ + if (!crypto_queue_len(&engine->queue) || !engine->running) { + if (!engine->busy) + goto out; + + /* Only do teardown in the thread */ + if (!in_kthread) { + queue_kthread_work(&engine->kworker, + &engine->pump_requests); + goto out; + } + + engine->busy = false; + engine->idling = true; + spin_unlock_irqrestore(&engine->queue_lock, flags); + + if (engine->unprepare_crypt_hardware && + engine->unprepare_crypt_hardware(engine)) + pr_err("failed to unprepare crypt hardware\n"); + + spin_lock_irqsave(&engine->queue_lock, flags); + engine->idling = false; + goto out; + } + + /* Get the fist request from the engine queue to handle */ + backlog = crypto_get_backlog(&engine->queue); + async_req = crypto_dequeue_request(&engine->queue); + if (!async_req) + goto out; + + req = ablkcipher_request_cast(async_req); + + engine->cur_req = req; + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + if (engine->busy) + was_busy = true; + else + engine->busy = true; + + spin_unlock_irqrestore(&engine->queue_lock, flags); + + /* Until here we get the request need to be encrypted successfully */ + if (!was_busy && engine->prepare_crypt_hardware) { + ret = engine->prepare_crypt_hardware(engine); + if (ret) { + pr_err("failed to prepare crypt hardware\n"); + goto req_err; + } + } + + if (engine->prepare_request) { + ret = engine->prepare_request(engine, engine->cur_req); + if (ret) { + pr_err("failed to prepare request: %d\n", ret); + goto req_err; + } + engine->cur_req_prepared = true; + } + + ret = engine->crypt_one_request(engine, engine->cur_req); + if (ret) { + pr_err("failed to crypt one request from queue\n"); + goto req_err; + } + return; + +req_err: + crypto_finalize_request(engine, engine->cur_req, ret); + return; + +out: + spin_unlock_irqrestore(&engine->queue_lock, flags); +} + +static void crypto_pump_work(struct kthread_work *work) +{ + struct crypto_engine *engine = + container_of(work, struct crypto_engine, pump_requests); + + crypto_pump_requests(engine, true); +} + +/** + * crypto_transfer_request - transfer the new request into the engine queue + * @engine: the hardware engine + * @req: the request need to be listed into the engine queue + */ +int crypto_transfer_request(struct crypto_engine *engine, + struct ablkcipher_request *req, bool need_pump) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&engine->queue_lock, flags); + + if (!engine->running) { + spin_unlock_irqrestore(&engine->queue_lock, flags); + return -ESHUTDOWN; + } + + ret = ablkcipher_enqueue_request(&engine->queue, req); + + if (!engine->busy && need_pump) + queue_kthread_work(&engine->kworker, &engine->pump_requests); + + spin_unlock_irqrestore(&engine->queue_lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(crypto_transfer_request); + +/** + * crypto_transfer_request_to_engine - transfer one request to list into the + * engine queue + * @engine: the hardware engine + * @req: the request need to be listed into the engine queue + */ +int crypto_transfer_request_to_engine(struct crypto_engine *engine, + struct ablkcipher_request *req) +{ + return crypto_transfer_request(engine, req, true); +} +EXPORT_SYMBOL_GPL(crypto_transfer_request_to_engine); + +/** + * crypto_finalize_request - finalize one request if the request is done + * @engine: the hardware engine + * @req: the request need to be finalized + * @err: error number + */ +void crypto_finalize_request(struct crypto_engine *engine, + struct ablkcipher_request *req, int err) +{ + unsigned long flags; + bool finalize_cur_req = false; + int ret; + + spin_lock_irqsave(&engine->queue_lock, flags); + if (engine->cur_req == req) + finalize_cur_req = true; + spin_unlock_irqrestore(&engine->queue_lock, flags); + + if (finalize_cur_req) { + if (engine->cur_req_prepared && engine->unprepare_request) { + ret = engine->unprepare_request(engine, req); + if (ret) + pr_err("failed to unprepare request\n"); + } + + spin_lock_irqsave(&engine->queue_lock, flags); + engine->cur_req = NULL; + engine->cur_req_prepared = false; + spin_unlock_irqrestore(&engine->queue_lock, flags); + } + + req->base.complete(&req->base, err); + + queue_kthread_work(&engine->kworker, &engine->pump_requests); +} +EXPORT_SYMBOL_GPL(crypto_finalize_request); + +/** + * crypto_engine_start - start the hardware engine + * @engine: the hardware engine need to be started + * + * Return 0 on success, else on fail. + */ +int crypto_engine_start(struct crypto_engine *engine) +{ + unsigned long flags; + + spin_lock_irqsave(&engine->queue_lock, flags); + + if (engine->running || engine->busy) { + spin_unlock_irqrestore(&engine->queue_lock, flags); + return -EBUSY; + } + + engine->running = true; + spin_unlock_irqrestore(&engine->queue_lock, flags); + + queue_kthread_work(&engine->kworker, &engine->pump_requests); + + return 0; +} +EXPORT_SYMBOL_GPL(crypto_engine_start); + +/** + * crypto_engine_stop - stop the hardware engine + * @engine: the hardware engine need to be stopped + * + * Return 0 on success, else on fail. + */ +int crypto_engine_stop(struct crypto_engine *engine) +{ + unsigned long flags; + unsigned limit = 500; + int ret = 0; + + spin_lock_irqsave(&engine->queue_lock, flags); + + /* + * If the engine queue is not empty or the engine is on busy state, + * we need to wait for a while to pump the requests of engine queue. + */ + while ((crypto_queue_len(&engine->queue) || engine->busy) && limit--) { + spin_unlock_irqrestore(&engine->queue_lock, flags); + msleep(20); + spin_lock_irqsave(&engine->queue_lock, flags); + } + + if (crypto_queue_len(&engine->queue) || engine->busy) + ret = -EBUSY; + else + engine->running = false; + + spin_unlock_irqrestore(&engine->queue_lock, flags); + + if (ret) + pr_warn("could not stop engine\n"); + + return ret; +} +EXPORT_SYMBOL_GPL(crypto_engine_stop); + +/** + * crypto_engine_alloc_init - allocate crypto hardware engine structure and + * initialize it. + * @dev: the device attached with one hardware engine + * @rt: whether this queue is set to run as a realtime task + * + * This must be called from context that can sleep. + * Return: the crypto engine structure on success, else NULL. + */ +struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt) +{ + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + struct crypto_engine *engine; + + if (!dev) + return NULL; + + engine = devm_kzalloc(dev, sizeof(*engine), GFP_KERNEL); + if (!engine) + return NULL; + + engine->rt = rt; + engine->running = false; + engine->busy = false; + engine->idling = false; + engine->cur_req_prepared = false; + engine->priv_data = dev; + snprintf(engine->name, sizeof(engine->name), + "%s-engine", dev_name(dev)); + + crypto_init_queue(&engine->queue, CRYPTO_ENGINE_MAX_QLEN); + spin_lock_init(&engine->queue_lock); + + init_kthread_worker(&engine->kworker); + engine->kworker_task = kthread_run(kthread_worker_fn, + &engine->kworker, "%s", + engine->name); + if (IS_ERR(engine->kworker_task)) { + dev_err(dev, "failed to create crypto request pump task\n"); + return NULL; + } + init_kthread_work(&engine->pump_requests, crypto_pump_work); + + if (engine->rt) { + dev_info(dev, "will run requests pump with realtime priority\n"); + sched_setscheduler(engine->kworker_task, SCHED_FIFO, ¶m); + } + + return engine; +} +EXPORT_SYMBOL_GPL(crypto_engine_alloc_init); + +/** + * crypto_engine_exit - free the resources of hardware engine when exit + * @engine: the hardware engine need to be freed + * + * Return 0 for success. + */ +int crypto_engine_exit(struct crypto_engine *engine) +{ + int ret; + + ret = crypto_engine_stop(engine); + if (ret) + return ret; + + flush_kthread_worker(&engine->kworker); + kthread_stop(engine->kworker_task); + + return 0; +} +EXPORT_SYMBOL_GPL(crypto_engine_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Crypto hardware engine framework"); diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index 4f861c44d066..b09d43f612e1 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -15,6 +15,7 @@ #include #include #include +#include #include struct crypto_aead; @@ -128,6 +129,75 @@ struct ablkcipher_walk { unsigned int blocksize; }; +#define ENGINE_NAME_LEN 30 +/* + * struct crypto_engine - crypto hardware engine + * @name: the engine name + * @idling: the engine is entering idle state + * @busy: request pump is busy + * @running: the engine is on working + * @cur_req_prepared: current request is prepared + * @list: link with the global crypto engine list + * @queue_lock: spinlock to syncronise access to request queue + * @queue: the crypto queue of the engine + * @rt: whether this queue is set to run as a realtime task + * @prepare_crypt_hardware: a request will soon arrive from the queue + * so the subsystem requests the driver to prepare the hardware + * by issuing this call + * @unprepare_crypt_hardware: there are currently no more requests on the + * queue so the subsystem notifies the driver that it may relax the + * hardware by issuing this call + * @prepare_request: do some prepare if need before handle the current request + * @unprepare_request: undo any work done by prepare_message() + * @crypt_one_request: do encryption for current request + * @kworker: thread struct for request pump + * @kworker_task: pointer to task for request pump kworker thread + * @pump_requests: work struct for scheduling work to the request pump + * @priv_data: the engine private data + * @cur_req: the current request which is on processing + */ +struct crypto_engine { + char name[ENGINE_NAME_LEN]; + bool idling; + bool busy; + bool running; + bool cur_req_prepared; + + struct list_head list; + spinlock_t queue_lock; + struct crypto_queue queue; + + bool rt; + + int (*prepare_crypt_hardware)(struct crypto_engine *engine); + int (*unprepare_crypt_hardware)(struct crypto_engine *engine); + + int (*prepare_request)(struct crypto_engine *engine, + struct ablkcipher_request *req); + int (*unprepare_request)(struct crypto_engine *engine, + struct ablkcipher_request *req); + int (*crypt_one_request)(struct crypto_engine *engine, + struct ablkcipher_request *req); + + struct kthread_worker kworker; + struct task_struct *kworker_task; + struct kthread_work pump_requests; + + void *priv_data; + struct ablkcipher_request *cur_req; +}; + +int crypto_transfer_request(struct crypto_engine *engine, + struct ablkcipher_request *req, bool need_pump); +int crypto_transfer_request_to_engine(struct crypto_engine *engine, + struct ablkcipher_request *req); +void crypto_finalize_request(struct crypto_engine *engine, + struct ablkcipher_request *req, int err); +int crypto_engine_start(struct crypto_engine *engine); +int crypto_engine_stop(struct crypto_engine *engine); +struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt); +int crypto_engine_exit(struct crypto_engine *engine); + extern const struct crypto_type crypto_ablkcipher_type; extern const struct crypto_type crypto_blkcipher_type; -- cgit From 0529900a01cb840feb7f7e2f64ed88f7a9ed0031 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 26 Jan 2016 20:25:40 +0800 Subject: crypto: omap-aes - Support crypto engine framework Integrate with the newly added crypto engine to make the crypto hardware engine underutilized as each block needs to be processed before the crypto hardware can start working on the next block. The requests from dm-crypt will be listed into engine queue and processed by engine automatically, so remove the 'queue' and 'queue_task' things in omap aes driver. Signed-off-by: Baolin Wang Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 1 + drivers/crypto/omap-aes.c | 97 +++++++++++++++++++++-------------------------- 2 files changed, 45 insertions(+), 53 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 07d494276aad..0a6e0b72284b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -296,6 +296,7 @@ config CRYPTO_DEV_OMAP_AES depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP2PLUS select CRYPTO_AES select CRYPTO_BLKCIPHER + select CRYPTO_ENGINE help OMAP processors have AES module accelerator. Select this if you want to use the OMAP module for AES algorithms. diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index dd355bd19474..d420ec751c7c 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -36,6 +36,7 @@ #include #include #include +#include #define DST_MAXBURST 4 #define DMA_MIN (DST_MAXBURST * sizeof(u32)) @@ -152,13 +153,10 @@ struct omap_aes_dev { unsigned long flags; int err; - spinlock_t lock; - struct crypto_queue queue; - struct tasklet_struct done_task; - struct tasklet_struct queue_task; struct ablkcipher_request *req; + struct crypto_engine *engine; /* * total is used by PIO mode for book keeping so introduce @@ -532,9 +530,7 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err) pr_debug("err: %d\n", err); - dd->flags &= ~FLAGS_BUSY; - - req->base.complete(&req->base, err); + crypto_finalize_request(dd->engine, req, err); } static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd) @@ -604,34 +600,25 @@ static int omap_aes_copy_sgs(struct omap_aes_dev *dd) } static int omap_aes_handle_queue(struct omap_aes_dev *dd, - struct ablkcipher_request *req) + struct ablkcipher_request *req) { - struct crypto_async_request *async_req, *backlog; - struct omap_aes_ctx *ctx; - struct omap_aes_reqctx *rctx; - unsigned long flags; - int err, ret = 0, len; - - spin_lock_irqsave(&dd->lock, flags); if (req) - ret = ablkcipher_enqueue_request(&dd->queue, req); - if (dd->flags & FLAGS_BUSY) { - spin_unlock_irqrestore(&dd->lock, flags); - return ret; - } - backlog = crypto_get_backlog(&dd->queue); - async_req = crypto_dequeue_request(&dd->queue); - if (async_req) - dd->flags |= FLAGS_BUSY; - spin_unlock_irqrestore(&dd->lock, flags); + return crypto_transfer_request_to_engine(dd->engine, req); - if (!async_req) - return ret; + return 0; +} - if (backlog) - backlog->complete(backlog, -EINPROGRESS); +static int omap_aes_prepare_req(struct crypto_engine *engine, + struct ablkcipher_request *req) +{ + struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + struct omap_aes_dev *dd = omap_aes_find_dev(ctx); + struct omap_aes_reqctx *rctx; + int len; - req = ablkcipher_request_cast(async_req); + if (!dd) + return -ENODEV; /* assign new request to device */ dd->req = req; @@ -662,16 +649,20 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd, dd->ctx = ctx; ctx->dd = dd; - err = omap_aes_write_ctrl(dd); - if (!err) - err = omap_aes_crypt_dma_start(dd); - if (err) { - /* aes_task will not finish it, so do it here */ - omap_aes_finish_req(dd, err); - tasklet_schedule(&dd->queue_task); - } + return omap_aes_write_ctrl(dd); +} - return ret; /* return ret, which is enqueue return value */ +static int omap_aes_crypt_req(struct crypto_engine *engine, + struct ablkcipher_request *req) +{ + struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( + crypto_ablkcipher_reqtfm(req)); + struct omap_aes_dev *dd = omap_aes_find_dev(ctx); + + if (!dd) + return -ENODEV; + + return omap_aes_crypt_dma_start(dd); } static void omap_aes_done_task(unsigned long data) @@ -704,18 +695,10 @@ static void omap_aes_done_task(unsigned long data) } omap_aes_finish_req(dd, 0); - omap_aes_handle_queue(dd, NULL); pr_debug("exit\n"); } -static void omap_aes_queue_task(unsigned long data) -{ - struct omap_aes_dev *dd = (struct omap_aes_dev *)data; - - omap_aes_handle_queue(dd, NULL); -} - static int omap_aes_crypt(struct ablkcipher_request *req, unsigned long mode) { struct omap_aes_ctx *ctx = crypto_ablkcipher_ctx( @@ -1175,9 +1158,6 @@ static int omap_aes_probe(struct platform_device *pdev) dd->dev = dev; platform_set_drvdata(pdev, dd); - spin_lock_init(&dd->lock); - crypto_init_queue(&dd->queue, OMAP_AES_QUEUE_LENGTH); - err = (dev->of_node) ? omap_aes_get_res_of(dd, dev, &res) : omap_aes_get_res_pdev(dd, pdev, &res); if (err) @@ -1209,7 +1189,6 @@ static int omap_aes_probe(struct platform_device *pdev) (reg & dd->pdata->minor_mask) >> dd->pdata->minor_shift); tasklet_init(&dd->done_task, omap_aes_done_task, (unsigned long)dd); - tasklet_init(&dd->queue_task, omap_aes_queue_task, (unsigned long)dd); err = omap_aes_dma_init(dd); if (err && AES_REG_IRQ_STATUS(dd) && AES_REG_IRQ_ENABLE(dd)) { @@ -1250,7 +1229,20 @@ static int omap_aes_probe(struct platform_device *pdev) } } + /* Initialize crypto engine */ + dd->engine = crypto_engine_alloc_init(dev, 1); + if (!dd->engine) + goto err_algs; + + dd->engine->prepare_request = omap_aes_prepare_req; + dd->engine->crypt_one_request = omap_aes_crypt_req; + err = crypto_engine_start(dd->engine); + if (err) + goto err_engine; + return 0; +err_engine: + crypto_engine_exit(dd->engine); err_algs: for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) @@ -1260,7 +1252,6 @@ err_algs: omap_aes_dma_cleanup(dd); err_irq: tasklet_kill(&dd->done_task); - tasklet_kill(&dd->queue_task); pm_runtime_disable(dev); err_res: dd = NULL; @@ -1286,8 +1277,8 @@ static int omap_aes_remove(struct platform_device *pdev) crypto_unregister_alg( &dd->pdata->algs_info[i].algs_list[j]); + crypto_engine_exit(dd->engine); tasklet_kill(&dd->done_task); - tasklet_kill(&dd->queue_task); omap_aes_dma_cleanup(dd); pm_runtime_disable(dd->dev); dd = NULL; -- cgit From d1662165ae612ec8b5f94a6b07e65ea58b6dce34 Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Fri, 29 Jan 2016 12:45:14 -0600 Subject: crypto: ccp - Limit the amount of information exported Since the exported information can be exposed to user-space, instead of exporting the entire request context only export the minimum information needed. Cc: # 3.14.x- Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 16 +++++++++++----- drivers/crypto/ccp/ccp-crypto-sha.c | 20 +++++++++++++++----- drivers/crypto/ccp/ccp-crypto.h | 22 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index 00207cf5c79b..6a2d836eb2d9 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -223,9 +223,12 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) static int ccp_aes_cmac_export(struct ahash_request *req, void *out) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_aes_cmac_req_ctx *state = out; + struct ccp_aes_cmac_exp_ctx *state = out; - *state = *rctx; + state->null_msg = rctx->null_msg; + memcpy(state->iv, rctx->iv, sizeof(state->iv)); + state->buf_count = rctx->buf_count; + memcpy(state->buf, rctx->buf, sizeof(state->buf)); return 0; } @@ -233,9 +236,12 @@ static int ccp_aes_cmac_export(struct ahash_request *req, void *out) static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_aes_cmac_req_ctx *state = in; + const struct ccp_aes_cmac_exp_ctx *state = in; - *rctx = *state; + rctx->null_msg = state->null_msg; + memcpy(rctx->iv, state->iv, sizeof(rctx->iv)); + rctx->buf_count = state->buf_count; + memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); return 0; } @@ -378,7 +384,7 @@ int ccp_register_aes_cmac_algs(struct list_head *head) halg = &alg->halg; halg->digestsize = AES_BLOCK_SIZE; - halg->statesize = sizeof(struct ccp_aes_cmac_req_ctx); + halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)"); diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index 3aae58def106..a67128a7af23 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -210,9 +210,14 @@ static int ccp_sha_digest(struct ahash_request *req) static int ccp_sha_export(struct ahash_request *req, void *out) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_sha_req_ctx *state = out; + struct ccp_sha_exp_ctx *state = out; - *state = *rctx; + state->type = rctx->type; + state->msg_bits = rctx->msg_bits; + state->first = rctx->first; + memcpy(state->ctx, rctx->ctx, sizeof(state->ctx)); + state->buf_count = rctx->buf_count; + memcpy(state->buf, rctx->buf, sizeof(state->buf)); return 0; } @@ -220,9 +225,14 @@ static int ccp_sha_export(struct ahash_request *req, void *out) static int ccp_sha_import(struct ahash_request *req, const void *in) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_sha_req_ctx *state = in; + const struct ccp_sha_exp_ctx *state = in; - *rctx = *state; + rctx->type = state->type; + rctx->msg_bits = state->msg_bits; + rctx->first = state->first; + memcpy(rctx->ctx, state->ctx, sizeof(rctx->ctx)); + rctx->buf_count = state->buf_count; + memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); return 0; } @@ -428,7 +438,7 @@ static int ccp_register_sha_alg(struct list_head *head, halg = &alg->halg; halg->digestsize = def->digest_size; - halg->statesize = sizeof(struct ccp_sha_req_ctx); + halg->statesize = sizeof(struct ccp_sha_exp_ctx); base = &halg->base; snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); diff --git a/drivers/crypto/ccp/ccp-crypto.h b/drivers/crypto/ccp/ccp-crypto.h index 76a96f0f44c6..a326ec20bfa8 100644 --- a/drivers/crypto/ccp/ccp-crypto.h +++ b/drivers/crypto/ccp/ccp-crypto.h @@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx { struct ccp_cmd cmd; }; +struct ccp_aes_cmac_exp_ctx { + unsigned int null_msg; + + u8 iv[AES_BLOCK_SIZE]; + + unsigned int buf_count; + u8 buf[AES_BLOCK_SIZE]; +}; + /***** SHA related defines *****/ #define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE #define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE @@ -171,6 +180,19 @@ struct ccp_sha_req_ctx { struct ccp_cmd cmd; }; +struct ccp_sha_exp_ctx { + enum ccp_sha_type type; + + u64 msg_bits; + + unsigned int first; + + u8 ctx[MAX_SHA_CONTEXT_SIZE]; + + unsigned int buf_count; + u8 buf[MAX_SHA_BLOCK_SIZE]; +}; + /***** Common Context Structure *****/ struct ccp_ctx { int (*complete)(struct crypto_async_request *req, int ret); -- cgit From 2b8b28fd232233c22fb61009dd8b0587390d2875 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 30 Jan 2016 17:38:28 +0300 Subject: crypto: keywrap - memzero the correct memory We're clearing the wrong memory. The memory corruption is likely harmless because we weren't going to use that stack memory again but not zeroing is a potential information leak. Fixes: e28facde3c39 ('crypto: keywrap - add key wrapping block chaining mode') Signed-off-by: Dan Carpenter Acked-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/keywrap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/keywrap.c b/crypto/keywrap.c index b1d106ce55f3..72014f963ba7 100644 --- a/crypto/keywrap.c +++ b/crypto/keywrap.c @@ -212,7 +212,7 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc, SEMIBSIZE)) ret = -EBADMSG; - memzero_explicit(&block, sizeof(struct crypto_kw_block)); + memzero_explicit(block, sizeof(struct crypto_kw_block)); return ret; } @@ -297,7 +297,7 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc, /* establish the IV for the caller to pick up */ memcpy(desc->info, block->A, SEMIBSIZE); - memzero_explicit(&block, sizeof(struct crypto_kw_block)); + memzero_explicit(block, sizeof(struct crypto_kw_block)); return 0; } -- cgit From b3ff1270566d41eb8ab2d67844bf17b7fa9fee78 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Wed, 6 Jan 2016 18:40:38 -0200 Subject: iwlwifi: pcie: add initial RTPM support for PCI Add an initial implementation of runtime power management (RTPM) for PCI devices. With this patch, RTPM is only used when wifi is off (i.e. the wifi interface is down). This implementation is behind a new Kconfig flag, IWLWIFI_PCIE_RTPM. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/Kconfig | 12 +++++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 60 +++++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 27 +++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 866067789330..11932d53ea24 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig @@ -99,6 +99,18 @@ config IWLWIFI_UAPSD If unsure, say N. +config IWLWIFI_PCIE_RTPM + bool "Enable runtime power management mode for PCIe devices" + depends on IWLMVM && PM + default false + help + Say Y here to enable runtime power management for PCIe + devices. If enabled, the device will go into low power mode + when idle for a short period of time, allowing for improved + power saving during runtime. + + If unsure, say N. + menu "Debugging Options" config IWLWIFI_DEBUG diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 6261a68cae90..676d2391eb66 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -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 @@ -66,6 +67,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#ifdef CONFIG_IWLWIFI_PCIE_RTPM +#include +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include #include #include @@ -623,6 +627,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_free_drv; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_set_active(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, + iwlwifi_mod_params.d0i3_entry_delay); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); +#endif return 0; out_free_drv: @@ -689,15 +700,58 @@ static int iwl_pci_resume(struct device *device) return 0; } -static SIMPLE_DEV_PM_OPS(iwl_dev_pm_ops, iwl_pci_suspend, iwl_pci_resume); +#ifdef CONFIG_IWLWIFI_PCIE_RTPM +static int iwl_pci_runtime_suspend(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct iwl_trans *trans = pci_get_drvdata(pdev); + + IWL_DEBUG_RPM(trans, "entering runtime suspend\n"); + + /* For now we only allow D0I3 if the device is off */ + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) + return -EBUSY; + + trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3; + + iwl_trans_d3_suspend(trans, false); + + return 0; +} + +static int iwl_pci_runtime_resume(struct device *device) +{ + struct pci_dev *pdev = to_pci_dev(device); + struct iwl_trans *trans = pci_get_drvdata(pdev); + enum iwl_d3_status d3_status; + + IWL_DEBUG_RPM(trans, "exiting runtime suspend (resume)\n"); + + iwl_trans_d3_resume(trans, &d3_status, false); + + trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; + + return 0; +} +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + +static const struct dev_pm_ops iwl_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(iwl_pci_suspend, + iwl_pci_resume) +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + SET_RUNTIME_PM_OPS(iwl_pci_runtime_suspend, + iwl_pci_runtime_resume, + NULL) +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ +}; #define IWL_PM_OPS (&iwl_dev_pm_ops) -#else +#else /* CONFIG_PM_SLEEP */ #define IWL_PM_OPS NULL -#endif +#endif /* CONFIG_PM_SLEEP */ static struct pci_driver iwl_pci_driver = { .name = DRV_NAME, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 35810965221c..db94fe1e1bc6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -72,6 +72,9 @@ #include #include #include +#ifdef CONFIG_IWLWIFI_PCIE_RTPM +#include +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include "iwl-drv.h" #include "iwl-trans.h" @@ -1194,6 +1197,9 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) if (hw_rfkill != was_hw_rfkill) iwl_trans_pcie_rf_kill(trans, hw_rfkill); +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_put_sync(trans->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ /* re-take ownership to prevent other users from stealing the deivce */ iwl_pcie_prepare_card_hw(trans); } @@ -1353,6 +1359,9 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) /* ... rfkill can call stop_device and set it false if needed */ iwl_trans_pcie_rf_kill(trans, hw_rfkill); +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_get_sync(trans->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ return 0; } @@ -1476,6 +1485,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + /* TODO: check if this is really needed */ + pm_runtime_disable(trans->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ synchronize_irq(trans_pcie->pci_dev->irq); iwl_pcie_tx_free(trans); @@ -1831,6 +1844,9 @@ void iwl_trans_pcie_ref(struct iwl_trans *trans) spin_lock_irqsave(&trans_pcie->ref_lock, flags); IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count); trans_pcie->ref_count++; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_get(&trans_pcie->pci_dev->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -1849,6 +1865,11 @@ void iwl_trans_pcie_unref(struct iwl_trans *trans) return; } trans_pcie->ref_count--; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev); + pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev); +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -2728,6 +2749,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, trans_pcie->inta_mask = CSR_INI_SET_MASK; +#ifdef CONFIG_IWLWIFI_PCIE_RTPM + trans->runtime_pm_mode = IWL_PLAT_PM_MODE_D0I3; +#else + trans->runtime_pm_mode = IWL_PLAT_PM_MODE_DISABLED; +#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + return trans; out_free_ict: -- cgit From 4cbb8e50338a2f2453ba399ce52562e0a111fc1f Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Tue, 18 Aug 2015 16:02:38 +0300 Subject: iwlwifi: pcie: add RTPM support when wifi is enabled Enable runtime power management (RTPM) for PCIe devices and implement the corresponding functions to enable D0i3 mode when the device is idle. Additionally, remove some unnecessary #ifdef's because the RTPM code will not be called if runtime PM is not configured. Signed-off-by: Luca Coelho Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 5 ++ drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 98 +++++++++++++++++++--- drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 5 ++ drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 43 ++++++---- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 17 +++- 5 files changed, 141 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 82fb3a97a46d..fe170a3fb1a6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -736,6 +736,11 @@ enum iwl_plat_pm_mode { IWL_PLAT_PM_MODE_D0I3, }; +/* Max time to wait for trans to become idle/non-idle on d0i3 + * enter/exit (in msecs). + */ +#define IWL_TRANS_IDLE_TIMEOUT 2000 + /** * struct iwl_trans - transport common data * diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 676d2391eb66..16b579a5aa6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -67,9 +67,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#ifdef CONFIG_IWLWIFI_PCIE_RTPM #include -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include #include #include @@ -627,13 +625,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto out_free_drv; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM - pm_runtime_set_active(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, + /* if RTPM is in use, enable it in our device */ + if (iwl_trans->runtime_pm_mode != IWL_PLAT_PM_MODE_DISABLED) { + pm_runtime_set_active(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, iwlwifi_mod_params.d0i3_entry_delay); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_allow(&pdev->dev); -#endif + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_allow(&pdev->dev); + } + return 0; out_free_drv: @@ -700,17 +700,90 @@ static int iwl_pci_resume(struct device *device) return 0; } +int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int ret; + + if (test_bit(STATUS_FW_ERROR, &trans->status)) + return 0; + + set_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + + /* config the fw */ + ret = iwl_op_mode_enter_d0i3(trans->op_mode); + if (ret == 1) { + IWL_DEBUG_RPM(trans, "aborting d0i3 entrance\n"); + clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + return -EBUSY; + } + if (ret) + goto err; + + ret = wait_event_timeout(trans_pcie->d0i3_waitq, + test_bit(STATUS_TRANS_IDLE, &trans->status), + msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT)); + if (!ret) { + IWL_ERR(trans, "Timeout entering D0i3\n"); + ret = -ETIMEDOUT; + goto err; + } + + clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + + return 0; +err: + clear_bit(STATUS_TRANS_GOING_IDLE, &trans->status); + iwl_trans_fw_error(trans); + return ret; +} + +int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + int ret; + + /* sometimes a D0i3 entry is not followed through */ + if (!test_bit(STATUS_TRANS_IDLE, &trans->status)) + return 0; + + /* config the fw */ + ret = iwl_op_mode_exit_d0i3(trans->op_mode); + if (ret) + goto err; + + /* we clear STATUS_TRANS_IDLE only when D0I3_END command is completed */ + + ret = wait_event_timeout(trans_pcie->d0i3_waitq, + !test_bit(STATUS_TRANS_IDLE, &trans->status), + msecs_to_jiffies(IWL_TRANS_IDLE_TIMEOUT)); + if (!ret) { + IWL_ERR(trans, "Timeout exiting D0i3\n"); + ret = -ETIMEDOUT; + goto err; + } + + return 0; +err: + clear_bit(STATUS_TRANS_IDLE, &trans->status); + iwl_trans_fw_error(trans); + return ret; +} + #ifdef CONFIG_IWLWIFI_PCIE_RTPM static int iwl_pci_runtime_suspend(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct iwl_trans *trans = pci_get_drvdata(pdev); + int ret; IWL_DEBUG_RPM(trans, "entering runtime suspend\n"); - /* For now we only allow D0I3 if the device is off */ - if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - return -EBUSY; + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) { + ret = iwl_pci_fw_enter_d0i3(trans); + if (ret < 0) + return ret; + } trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3; @@ -729,7 +802,8 @@ static int iwl_pci_runtime_resume(struct device *device) iwl_trans_d3_resume(trans, &d3_status, false); - trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; + if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) + return iwl_pci_fw_exit_d0i3(trans); return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index bdda7028c393..7bc02e0cdd93 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -2,6 +2,7 @@ * * Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -374,6 +375,7 @@ struct iwl_trans_pcie { bool ucode_write_complete; wait_queue_head_t ucode_write_waitq; wait_queue_head_t wait_command_queue; + wait_queue_head_t d0i3_waitq; u8 cmd_queue; u8 cmd_fifo; @@ -594,4 +596,7 @@ static inline int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans) } #endif +int iwl_pci_fw_exit_d0i3(struct iwl_trans *trans); +int iwl_pci_fw_enter_d0i3(struct iwl_trans *trans); + #endif /* __iwl_trans_int_pcie_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index db94fe1e1bc6..cfdc7f6e554a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -72,9 +72,7 @@ #include #include #include -#ifdef CONFIG_IWLWIFI_PCIE_RTPM #include -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ #include "iwl-drv.h" #include "iwl-trans.h" @@ -1197,9 +1195,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) if (hw_rfkill != was_hw_rfkill) iwl_trans_pcie_rf_kill(trans, hw_rfkill); -#ifdef CONFIG_IWLWIFI_PCIE_RTPM - pm_runtime_put_sync(trans->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ /* re-take ownership to prevent other users from stealing the deivce */ iwl_pcie_prepare_card_hw(trans); } @@ -1359,9 +1354,10 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) /* ... rfkill can call stop_device and set it false if needed */ iwl_trans_pcie_rf_kill(trans, hw_rfkill); -#ifdef CONFIG_IWLWIFI_PCIE_RTPM - pm_runtime_get_sync(trans->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + /* Make sure we sync here, because we'll need full access later */ + if (low_power) + pm_runtime_resume(trans->dev); + return 0; } @@ -1485,10 +1481,9 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); int i; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM /* TODO: check if this is really needed */ pm_runtime_disable(trans->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ + synchronize_irq(trans_pcie->pci_dev->irq); iwl_pcie_tx_free(trans); @@ -1844,9 +1839,7 @@ void iwl_trans_pcie_ref(struct iwl_trans *trans) spin_lock_irqsave(&trans_pcie->ref_lock, flags); IWL_DEBUG_RPM(trans, "ref_counter: %d\n", trans_pcie->ref_count); trans_pcie->ref_count++; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM pm_runtime_get(&trans_pcie->pci_dev->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -1865,10 +1858,9 @@ void iwl_trans_pcie_unref(struct iwl_trans *trans) return; } trans_pcie->ref_count--; -#ifdef CONFIG_IWLWIFI_PCIE_RTPM + pm_runtime_mark_last_busy(&trans_pcie->pci_dev->dev); pm_runtime_put_autosuspend(&trans_pcie->pci_dev->dev); -#endif /* CONFIG_IWLWIFI_PCIE_RTPM */ spin_unlock_irqrestore(&trans_pcie->ref_lock, flags); } @@ -2536,6 +2528,22 @@ static struct iwl_trans_dump_data return dump_data; } +#ifdef CONFIG_PM_SLEEP +static int iwl_trans_pcie_suspend(struct iwl_trans *trans) +{ + if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) + return iwl_pci_fw_enter_d0i3(trans); + + return 0; +} + +static void iwl_trans_pcie_resume(struct iwl_trans *trans) +{ + if (trans->runtime_pm_mode == IWL_PLAT_PM_MODE_D0I3) + iwl_pci_fw_exit_d0i3(trans); +} +#endif /* CONFIG_PM_SLEEP */ + static const struct iwl_trans_ops trans_ops_pcie = { .start_hw = iwl_trans_pcie_start_hw, .op_mode_leave = iwl_trans_pcie_op_mode_leave, @@ -2546,6 +2554,11 @@ static const struct iwl_trans_ops trans_ops_pcie = { .d3_suspend = iwl_trans_pcie_d3_suspend, .d3_resume = iwl_trans_pcie_d3_resume, +#ifdef CONFIG_PM_SLEEP + .suspend = iwl_trans_pcie_suspend, + .resume = iwl_trans_pcie_resume, +#endif /* CONFIG_PM_SLEEP */ + .send_cmd = iwl_trans_pcie_send_hcmd, .tx = iwl_trans_pcie_tx, @@ -2735,6 +2748,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, /* Initialize the wait queue for commands */ init_waitqueue_head(&trans_pcie->wait_command_queue); + init_waitqueue_head(&trans_pcie->d0i3_waitq); + ret = iwl_pcie_alloc_ict(trans); if (ret) goto out_pci_disable_msi; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index b0b0fd9e2eff..c499345ba526 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -1,7 +1,8 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -1727,6 +1728,20 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, wake_up(&trans_pcie->wait_command_queue); } + if (meta->flags & CMD_MAKE_TRANS_IDLE) { + IWL_DEBUG_INFO(trans, "complete %s - mark trans as idle\n", + iwl_get_cmd_string(trans, cmd->hdr.cmd)); + set_bit(STATUS_TRANS_IDLE, &trans->status); + wake_up(&trans_pcie->d0i3_waitq); + } + + if (meta->flags & CMD_WAKE_UP_TRANS) { + IWL_DEBUG_INFO(trans, "complete %s - clear trans idle flag\n", + iwl_get_cmd_string(trans, cmd->hdr.cmd)); + clear_bit(STATUS_TRANS_IDLE, &trans->status); + wake_up(&trans_pcie->d0i3_waitq); + } + meta->flags = 0; spin_unlock_bh(&txq->lock); -- cgit From 23ae61282b88873bec2d56c78fea531f8485146c Mon Sep 17 00:00:00 2001 From: Matti Gottlieb Date: Thu, 31 Dec 2015 18:18:02 +0200 Subject: iwlwifi: mvm: Do not switch to D3 image on suspend Currently when the driver is configured with wowlan parameters, and enters D3 mode, the driver switches the FW image to D3, and when it exists suspend, it reloads the D0 image. If the firmware supports the consolidation of the D0 & D3 images there is no need to load the D3 image on suspend, and no need to reload the D0 image on resume. Do not switch images on suspend / resume, for firmwares that support consolidated images. Signed-off-by: Matti Gottlieb Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c | 4 +- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 + drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 13 +++-- drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 70 ++++++++++++++++------- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 +- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 4 +- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 11 ++-- 7 files changed, 70 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c index 29ea1c6705b4..4db4cb7aa73a 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c @@ -396,7 +396,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw, iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); - iwl_trans_d3_suspend(priv->trans, false); + iwl_trans_d3_suspend(priv->trans, false, true); goto out; @@ -469,7 +469,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) /* we'll clear ctx->vif during iwlagn_prepare_restart() */ vif = ctx->vif; - ret = iwl_trans_d3_resume(priv->trans, &d3_status, false); + ret = iwl_trans_d3_resume(priv->trans, &d3_status, false, true); if (ret) goto out_unlock; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 84f8aeb926c8..2273908ad83a 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -297,6 +297,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA), * which also implies support for the scheduler configuration command * @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching + * @IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG: Consolidated D3-D0 image * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command * @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command * @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload @@ -330,6 +331,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = (__force iwl_ucode_tlv_capa_t)11, IWL_UCODE_TLV_CAPA_DQA_SUPPORT = (__force iwl_ucode_tlv_capa_t)12, IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH = (__force iwl_ucode_tlv_capa_t)13, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG = (__force iwl_ucode_tlv_capa_t)17, IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = (__force iwl_ucode_tlv_capa_t)18, IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19, IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index fe170a3fb1a6..e6a5e99f95e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -618,9 +618,9 @@ struct iwl_trans_ops { void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr); void (*stop_device)(struct iwl_trans *trans, bool low_power); - void (*d3_suspend)(struct iwl_trans *trans, bool test); + void (*d3_suspend)(struct iwl_trans *trans, bool test, bool reset); int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status, - bool test); + bool test, bool reset); int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); @@ -925,22 +925,23 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans) _iwl_trans_stop_device(trans, true); } -static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test) +static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, + bool reset) { might_sleep(); if (trans->ops->d3_suspend) - trans->ops->d3_suspend(trans, test); + trans->ops->d3_suspend(trans, test, reset); } static inline int iwl_trans_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, - bool test) + bool test, bool reset) { might_sleep(); if (!trans->ops->d3_resume) return 0; - return trans->ops->d3_resume(trans, status, test); + return trans->ops->d3_resume(trans, status, test, reset); } static inline void iwl_trans_ref(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index d3e21d95cece..78572ef89b26 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 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) 2012 - 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 @@ -1023,14 +1025,18 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, struct ieee80211_sta *ap_sta) { int ret; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); - ret = iwl_mvm_switch_to_d3(mvm); - if (ret) - return ret; + if (!unified_image) { + ret = iwl_mvm_switch_to_d3(mvm); + if (ret) + return ret; - ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); - if (ret) - return ret; + ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); + if (ret) + return ret; + } if (!iwlwifi_mod_params.sw_crypto) { /* @@ -1072,10 +1078,14 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm, { struct iwl_wowlan_config_cmd wowlan_config_cmd = {}; int ret; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); - ret = iwl_mvm_switch_to_d3(mvm); - if (ret) - return ret; + if (!unified_image) { + ret = iwl_mvm_switch_to_d3(mvm); + if (ret) + return ret; + } /* rfkill release can be either for wowlan or netdetect */ if (wowlan->rfkill_release) @@ -1151,6 +1161,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, }; int ret; int len __maybe_unused; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); if (!wowlan) { /* @@ -1236,7 +1248,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); - iwl_trans_d3_suspend(mvm->trans, test); + iwl_trans_d3_suspend(mvm->trans, test, !unified_image); out: if (ret < 0) { iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); @@ -1299,7 +1311,7 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags); mutex_unlock(&mvm->d0i3_suspend_mutex); - iwl_trans_d3_suspend(trans, false); + iwl_trans_d3_suspend(trans, false, false); return 0; } @@ -2041,9 +2053,14 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) { struct ieee80211_vif *vif = NULL; - int ret; + int ret = 1; enum iwl_d3_status d3_status; bool keep = false; + bool unified_image = fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG); + + u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE | + CMD_WAKE_UP_TRANS; mutex_lock(&mvm->mutex); @@ -2052,7 +2069,7 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) if (IS_ERR_OR_NULL(vif)) goto err; - ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); + ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image); if (ret) goto err; @@ -2095,17 +2112,28 @@ out_iterate: iwl_mvm_d3_disconnect_iter, keep ? vif : NULL); out: - /* return 1 to reconfigure the device */ + if (unified_image && !ret) { + ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL); + if (!ret) /* D3 ended successfully - no need to reset device */ + return 0; + } + + /* + * Reconfigure the device in one of the following cases: + * 1. We are not using a unified image + * 2. We are using a unified image but had an error while exiting D3 + */ set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status); - - /* We always return 1, which causes mac80211 to do a reconfig - * with IEEE80211_RECONFIG_TYPE_RESTART. This type of - * reconfig calls iwl_mvm_restart_complete(), where we unref - * the IWL_MVM_REF_UCODE_DOWN, so we need to take the - * reference here. + /* + * When switching images we return 1, which causes mac80211 + * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART. + * This type of reconfig calls iwl_mvm_restart_complete(), + * where we unref the IWL_MVM_REF_UCODE_DOWN, so we need + * to take the reference here. */ iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN); + return 1; } @@ -2122,7 +2150,7 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm) enum iwl_d3_status d3_status; struct iwl_trans *trans = mvm->trans; - iwl_trans_d3_resume(trans, &d3_status, false); + iwl_trans_d3_resume(trans, &d3_status, false, false); /* * make sure to clear D0I3_DEFER_WAKEUP before diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 9a15642f80dd..0476e7688e9b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -1109,7 +1109,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params, vif)); - if (type == IWL_MVM_SCAN_SCHED) + if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); if (iwl_mvm_scan_use_ebs(mvm, vif)) @@ -1351,7 +1351,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) { hcmd.id = iwl_cmd_id(SCAN_REQ_UMAC, IWL_ALWAYS_LONG_GROUP, 0); - ret = iwl_mvm_scan_umac(mvm, vif, ¶ms, IWL_MVM_SCAN_SCHED); + ret = iwl_mvm_scan_umac(mvm, vif, ¶ms, type); } else { hcmd.id = SCAN_OFFLOAD_REQUEST_CMD; ret = iwl_mvm_scan_lmac(mvm, vif, ¶ms); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 16b579a5aa6b..762e7c4d96b6 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -787,7 +787,7 @@ static int iwl_pci_runtime_suspend(struct device *device) trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3; - iwl_trans_d3_suspend(trans, false); + iwl_trans_d3_suspend(trans, false, false); return 0; } @@ -800,7 +800,7 @@ static int iwl_pci_runtime_resume(struct device *device) IWL_DEBUG_RPM(trans, "exiting runtime suspend (resume)\n"); - iwl_trans_d3_resume(trans, &d3_status, false); + iwl_trans_d3_resume(trans, &d3_status, false, false); if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) return iwl_pci_fw_exit_d0i3(trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index cfdc7f6e554a..abe091698471 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1219,11 +1219,12 @@ void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state) _iwl_trans_pcie_stop_device(trans, true); } -static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) +static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test, + bool reset) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) { + if (!reset) { /* Enable persistence mode to avoid reset */ iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PERSIST_MODE); @@ -1247,7 +1248,7 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - if (trans->system_pm_mode == IWL_PLAT_PM_MODE_D3) { + if (reset) { /* * reset TX queues -- some of their registers reset during S3 * so if we don't reset everything here the D3 image would try @@ -1261,7 +1262,7 @@ static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test) static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, enum iwl_d3_status *status, - bool test) + bool test, bool reset) { u32 val; int ret; @@ -1296,7 +1297,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, iwl_pcie_set_pwr(trans, false); - if (trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) { + if (!reset) { iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } else { -- cgit From 15ffd075e4088d3fc83ce8db914e7d3b6f31bc1c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 24 Jan 2016 23:04:22 +0200 Subject: iwlwifi: various comments and code cleanups No need to include net/ip6_checksum.h twice. Remove TODOs. Remove trailing space. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 3 --- drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 - drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index e6a5e99f95e0..0ca0f13b69b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -506,7 +506,7 @@ struct iwl_trans_config { bool sw_csum_tx; const struct iwl_hcmd_arr *command_groups; int command_groups_size; - + u32 sdio_adma_addr; }; 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 fb6d341d6f3d..ab467cb9b97c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -287,16 +287,13 @@ enum iwl_rx_mpdu_status { IWL_RX_MPDU_STATUS_KEY_ERROR = BIT(4), IWL_RX_MPDU_STATUS_ICV_OK = BIT(5), IWL_RX_MPDU_STATUS_MIC_OK = BIT(6), - /* TODO - verify this is the correct value */ IWL_RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), IWL_RX_MPDU_STATUS_SEC_MASK = 0x7 << 8, IWL_RX_MPDU_STATUS_SEC_NONE = 0x0 << 8, IWL_RX_MPDU_STATUS_SEC_WEP = 0x1 << 8, IWL_RX_MPDU_STATUS_SEC_CCM = 0x2 << 8, IWL_RX_MPDU_STATUS_SEC_TKIP = 0x3 << 8, - /* TODO - define IWL_RX_MPDU_STATUS_SEC_EXT_ENC - this is a stub */ IWL_RX_MPDU_STATUS_SEC_EXT_ENC = 0x4 << 8, - /* TODO - define IWL_RX_MPDU_STATUS_SEC_GCM - this is a stub */ IWL_RX_MPDU_STATUS_SEC_GCM = 0x5 << 8, IWL_RX_MPDU_STATUS_DECRYPTED = BIT(11), IWL_RX_MPDU_STATUS_WEP_MATCH = BIT(12), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 89ea70deeb84..6bf2bde239a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -392,7 +392,6 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = { [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), }; - /* this forward declaration can avoid to export the function */ static void iwl_mvm_async_handlers_wk(struct work_struct *wk); static void iwl_mvm_d0i3_exit_work(struct work_struct *wk); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index c499345ba526..837a7d536874 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -34,7 +34,6 @@ #include #include #include -#include #include "iwl-debug.h" #include "iwl-csr.h" -- cgit From bdf408eca877a2ae310e3df9f05e865ffe10e4de Mon Sep 17 00:00:00 2001 From: Hubert Tarasiuk Date: Sun, 24 Jan 2016 13:35:06 +0100 Subject: iwlwifi: dvm: handle zero brightness for wifi LED In order to have the LED being OFF constantly when the brightness is set to 0, we need to pass IWL_LED_SOLID to iwl_led_cmd as the off parameter, otherwise the led will stay on constantly. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=110551 Signed-off-by: Hubert Tarasiuk [reworked the commit message] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/dvm/led.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/led.c b/drivers/net/wireless/intel/iwlwifi/dvm/led.c index 1aabb5ec096f..1bbd17ada974 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/led.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/led.c @@ -152,11 +152,14 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, { struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led); unsigned long on = 0; + unsigned long off = 0; if (brightness > 0) on = IWL_LED_SOLID; + else + off = IWL_LED_SOLID; - iwl_led_cmd(priv, on, 0); + iwl_led_cmd(priv, on, off); } static int iwl_led_blink_set(struct led_classdev *led_cdev, -- cgit From d1cae0fd22e9d0c55c97da29dcdfe28d99d96ea6 Mon Sep 17 00:00:00 2001 From: Rodrigo Freire Date: Wed, 6 Jan 2016 20:24:01 -0200 Subject: iwlwifi: Document missing module options This patch documents two missing module options in the internal code comment block. Signed-off-by: Rodrigo Freire Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-modparams.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h index fd42f63f5e84..b88ecc7892a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h @@ -108,6 +108,8 @@ enum iwl_amsdu_size { * @power_level: power level, default = 1 * @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 * @d0i3_disable: disable d0i3, default = 1, * @d0i3_entry_delay: time to wait after no refs are taken before * entering D0i3 (in msecs) -- cgit From 25657fec94f87308da19bb3d5063feef04d5ba20 Mon Sep 17 00:00:00 2001 From: Golan Ben-Ami Date: Wed, 2 Sep 2015 12:34:23 +0300 Subject: iwlwifi: mvm: add trigger for firmware dump upon TX response status This will allow to collect the data when the firmware sends a specific tx response status. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/iwl-fw-error-dump.h | 3 ++ drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 13 +++++++++ drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 33 ++++++++++++++++++++++ 3 files changed, 49 insertions(+) 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 a5aaf6853704..8425e1a587d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-error-dump.h @@ -293,6 +293,8 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data) * @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a * threshold. * @FW_DBG_TDLS: trigger log collection upon TDLS related events. + * @FW_DBG_TRIGGER_TX_STATUS: trigger log collection upon tx status when + * the firmware sends a tx reply. */ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_INVALID = 0, @@ -309,6 +311,7 @@ enum iwl_fw_dbg_trigger { FW_DBG_TRIGGER_BA, FW_DBG_TRIGGER_TX_LATENCY, FW_DBG_TRIGGER_TDLS, + FW_DBG_TRIGGER_TX_STATUS, /* must be last */ FW_DBG_TRIGGER_MAX, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 2273908ad83a..4050b4af7e45 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -749,6 +749,19 @@ struct iwl_fw_dbg_trigger_tdls { u8 reserved[4]; } __packed; +/** + * struct iwl_fw_dbg_trigger_tx_status - configures trigger for tx response + * status. + * @statuses: the list of statuses to trigger the collection on + */ +struct iwl_fw_dbg_trigger_tx_status { + struct tx_status { + u8 status; + u8 reserved[3]; + } __packed statuses[16]; + __le32 reserved[2]; +} __packed; + /** * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration. * @id: conf id diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 8bf48a7d0f4e..5d73db2534a0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -736,6 +736,37 @@ static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags, iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r); } +static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm, + u32 status) +{ + struct iwl_fw_dbg_trigger_tlv *trig; + struct iwl_fw_dbg_trigger_tx_status *status_trig; + int i; + + if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TX_STATUS)) + return; + + trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TX_STATUS); + status_trig = (void *)trig->data; + + if (!iwl_fw_dbg_trigger_check_stop(mvm, NULL, trig)) + return; + + for (i = 0; i < ARRAY_SIZE(status_trig->statuses); i++) { + /* don't collect on status 0 */ + if (!status_trig->statuses[i].status) + break; + + if (status_trig->statuses[i].status != (status & TX_STATUS_MSK)) + continue; + + iwl_mvm_fw_dbg_collect_trig(mvm, trig, + "Tx status %d was received", + status & TX_STATUS_MSK); + break; + } +} + static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) { @@ -784,6 +815,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, break; } + iwl_mvm_tx_status_check_trigger(mvm, status); + info->status.rates[0].count = tx_resp->failure_frame + 1; iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate), info); -- cgit From ee95ed3728cb3ed70b76fb770fff66133ff8b1fa Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Wed, 25 Nov 2015 13:17:10 +0200 Subject: iwlwifi: mvm: Add P2P client snoozing Enable snoozing and U-APSD on P2P client. The firwmare will support this only if the BSS vif is not associated. Make this configurable by a constant variable and disable it by default. Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 8 +++++ drivers/net/wireless/intel/iwlwifi/mvm/power.c | 39 ++++++++++++++++++++-- 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 4050b4af7e45..dbf08c493654 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -302,6 +302,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command * @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics + * @IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD: support p2p standalone U-APSD * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running * @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different * sources for the MCC. This TLV bit is a future replacement to @@ -336,6 +337,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19, IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21, IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = (__force iwl_ucode_tlv_capa_t)22, + IWL_UCODE_TLV_CAPA_P2P_STANDALONE_UAPSD = (__force iwl_ucode_tlv_capa_t)26, IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = (__force iwl_ucode_tlv_capa_t)28, IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index b00c03fcd447..959fc4d33d16 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -73,6 +73,7 @@ #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/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5f3ac8cccf49..5a92ab1b3787 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1005,6 +1005,14 @@ static inline bool iwl_mvm_is_mplut_supported(struct iwl_mvm *mvm) IWL_MVM_BT_COEX_MPLUT; } +static inline +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; +} + static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) { /* firmware flag isn't defined yet */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 9de159f1ef2d..16b3e36fb1ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -259,6 +259,26 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm, IWL_MVM_PS_HEAVY_RX_THLD_PERCENT; } +static void iwl_mvm_p2p_standalone_iterator(void *_data, u8 *mac, + struct ieee80211_vif *vif) +{ + bool *is_p2p_standalone = _data; + + switch (ieee80211_vif_type_p2p(vif)) { + case NL80211_IFTYPE_P2P_GO: + case NL80211_IFTYPE_AP: + *is_p2p_standalone = false; + break; + case NL80211_IFTYPE_STATION: + if (vif->bss_conf.assoc) + *is_p2p_standalone = false; + break; + + default: + break; + } +} + static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -268,9 +288,6 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, ETH_ALEN)) return false; - if (vif->p2p && - !(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD)) - return false; /* * Avoid using uAPSD if P2P client is associated to GO that uses * opportunistic power save. This is due to current FW limitation. @@ -287,6 +304,22 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm, if (iwl_mvm_phy_ctx_count(mvm) >= 2) return false; + if (vif->p2p) { + /* Allow U-APSD only if p2p is stand alone */ + bool is_p2p_standalone = true; + + if (!iwl_mvm_is_p2p_standalone_uapsd_supported(mvm)) + return false; + + ieee80211_iterate_active_interfaces_atomic(mvm->hw, + IEEE80211_IFACE_ITER_NORMAL, + iwl_mvm_p2p_standalone_iterator, + &is_p2p_standalone); + + if (!is_p2p_standalone) + return false; + } + return true; } -- cgit From 33efe947e797c0f26b81bfe1b1eaf53501a6cd8e Mon Sep 17 00:00:00 2001 From: Golan Ben-Ami Date: Wed, 23 Dec 2015 17:53:27 +0200 Subject: iwlwifi: mvm: make collecting fw debug data optional Slow platforms may have issues with dumping data upon firmware assert. Make it easier to disable it for those platform. Signed-off-by: Golan Ben-Ami Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/constants.h | 7 +++++-- drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 959fc4d33d16..4b560e4417ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -6,7 +6,8 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 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 @@ -32,7 +33,8 @@ * BSD LICENSE * * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2015 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -108,6 +110,7 @@ #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 #define IWL_MVM_TOF_IS_RESPONDER 0 #define IWL_MVM_SW_TX_CSUM_OFFLOAD 0 +#define IWL_MVM_COLLECT_FW_ERR_DUMP 1 #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 0813f8184e10..94ec3f0c15cf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -435,6 +435,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) bool monitor_dump_only = false; int i; + if (!IWL_MVM_COLLECT_FW_ERR_DUMP && + !mvm->trans->dbg_dest_tlv) + return; + lockdep_assert_held(&mvm->mutex); /* there's no point in fw dump if the bus is dead */ -- cgit From d8f7c5115d09e4b6b72b5b33414853aaa39bf837 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Jan 2016 10:46:38 +0100 Subject: iwlwifi: mvm: remove shadowing variable The outer scope has a perfectly suitable 'i' variable, use it instead of adding a shadowing one in the inner scope. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c index 94ec3f0c15cf..4856eac120f6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c @@ -644,8 +644,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) /* Dump fw's virtual image */ if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) { - u32 i; - for (i = 1; i < mvm->num_of_paging_blk + 1; i++) { struct iwl_fw_error_dump_paging *paging; struct page *pages = -- cgit From 27e070d3d3c2f6ab925ffd7c54814cabd95db51c Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Jan 2016 10:55:22 +0100 Subject: iwlwifi: mvm: fix debugfs signedness warning Using kstrtouint() with a signed int isn't really right, use kstrotoint() instead. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 90500e2d107b..8059efafcb80 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -983,7 +983,7 @@ static ssize_t iwl_dbgfs_cont_recording_write(struct iwl_mvm *mvm, trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) return -EOPNOTSUPP; - ret = kstrtouint(buf, 0, &rec_mode); + ret = kstrtoint(buf, 0, &rec_mode); if (ret) return ret; -- cgit From 7869318e4296e27d4cb97505e8739d62b48b2d58 Mon Sep 17 00:00:00 2001 From: Chaya Rachel Ivgi Date: Sun, 27 Dec 2015 13:45:42 +0200 Subject: iwlwifi: mvm: add support for negative temperatures The driver should support also negative temperatures. So there is a need to separate between the return value and temperature in order to be able to distinguish between a negative temperature and error value. Signed-off-by: Chaya Rachel Ivgi Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 9 +++++---- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 17 ++++++++--------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 8059efafcb80..5c0f93997b7b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -261,17 +261,18 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file, { struct iwl_mvm *mvm = file->private_data; char buf[16]; - int pos, temp; + int pos, ret; + s32 temp; if (!mvm->ucode_loaded) return -EIO; mutex_lock(&mvm->mutex); - temp = iwl_mvm_get_temp(mvm); + ret = iwl_mvm_get_temp(mvm, &temp); mutex_unlock(&mvm->mutex); - if (temp < 0) - return temp; + if (ret) + return -EIO; pos = scnprintf(buf , sizeof(buf), "%d\n", temp); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5a92ab1b3787..216c8d6275a1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1489,7 +1489,7 @@ void iwl_mvm_tt_handler(struct iwl_mvm *mvm); void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff); void iwl_mvm_tt_exit(struct iwl_mvm *mvm); void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state); -int iwl_mvm_get_temp(struct iwl_mvm *mvm); +int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp); /* Location Aware Regulatory */ struct iwl_mcc_update_resp * diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index fb76004eede4..758d05a8c6aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -194,12 +194,12 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); } -int iwl_mvm_get_temp(struct iwl_mvm *mvm) +int iwl_mvm_get_temp(struct iwl_mvm *mvm, s32 *temp) { struct iwl_notification_wait wait_temp_notif; static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE) }; - int ret, temp; + int ret; if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) temp_notif[0] = DTS_MEASUREMENT_NOTIFICATION; @@ -208,7 +208,7 @@ int iwl_mvm_get_temp(struct iwl_mvm *mvm) iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif, temp_notif, ARRAY_SIZE(temp_notif), - iwl_mvm_temp_notif_wait, &temp); + iwl_mvm_temp_notif_wait, temp); ret = iwl_mvm_get_temp_cmd(mvm); if (ret) { @@ -219,12 +219,10 @@ int iwl_mvm_get_temp(struct iwl_mvm *mvm) ret = iwl_wait_notification(&mvm->notif_wait, &wait_temp_notif, IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT); - if (ret) { + if (ret) IWL_ERR(mvm, "Getting the temperature timed out\n"); - return ret; - } - return temp; + return ret; } static void check_exit_ctkill(struct work_struct *work) @@ -233,6 +231,7 @@ static void check_exit_ctkill(struct work_struct *work) struct iwl_mvm *mvm; u32 duration; s32 temp; + int ret; tt = container_of(work, struct iwl_mvm_tt_mgmt, ct_kill_exit.work); mvm = container_of(tt, struct iwl_mvm, thermal_throttle); @@ -250,13 +249,13 @@ static void check_exit_ctkill(struct work_struct *work) goto reschedule; } - temp = iwl_mvm_get_temp(mvm); + ret = iwl_mvm_get_temp(mvm, &temp); iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL); __iwl_mvm_mac_stop(mvm); - if (temp < 0) + if (ret) goto reschedule; IWL_DEBUG_TEMP(mvm, "NIC temperature: %d\n", temp); -- cgit From 0db056d32490181be48efc2ca7cfa7494b13e6b5 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 29 Dec 2015 11:07:15 +0200 Subject: iwlwifi: mvm: support beacon storing Currently firmware is configured to filter out beacons. In case a beacon was changed - it is waking the host. However, some vendors change their IEs frequently without any significant change, and redundant wakeups are triggered as a result. As a solution disable beacon filtering when entering d0i3. Instead, firmware will store the latest beacon and upon exiting d0i3 it will send it up to the host, so the host can act upon changes (if there were any). This beacon will arrive as a dedicated notification - support it as well. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 3 ++ drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 +- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 29 +++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 41 ++++++++++++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 22 ++++++++++-- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 33 ++++++++++++----- 8 files changed, 120 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index dbf08c493654..5152987c8b8d 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -315,6 +315,8 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT * @IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION: firmware will decide on what * antenna the beacon should be transmitted + * @IWL_UCODE_TLV_CAPA_BEACON_STORING: firmware will store the latest beacon + * from AP and will send it upon d0i3 exit. * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2: support LAR API V2 * * @NUM_IWL_UCODE_TLV_CAPA: number of bits used @@ -346,6 +348,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, + IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, NUM_IWL_UCODE_TLV_CAPA diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 78572ef89b26..346376187ef8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -853,7 +853,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm, wowlan_config_cmd->is_11n_connection = ap_sta->ht_cap.ht_supported; wowlan_config_cmd->flags = ENABLE_L3_FILTERING | - ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING; + ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING | + ENABLE_STORE_BEACON; /* Query the last used seqno and set it */ ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h index 62b9a0a96700..eec52c57f718 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-d3.h @@ -251,6 +251,7 @@ enum iwl_wowlan_flags { ENABLE_L3_FILTERING = BIT(1), ENABLE_NBNS_FILTERING = BIT(2), ENABLE_DHCP_FILTERING = BIT(3), + ENABLE_STORE_BEACON = BIT(4), }; struct iwl_wowlan_config_cmd { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index 82049bb139c2..b6b57273b8ba 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -280,11 +280,16 @@ enum iwl_phy_ops_subcmd_ids { DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, }; +enum iwl_prot_offload_subcmd_ids { + STORED_BEACON_NTF = 0xFF, +}; + /* command groups */ enum { LEGACY_GROUP = 0x0, LONG_GROUP = 0x1, PHY_OPS_GROUP = 0x4, + PROT_OFFLOAD_GROUP = 0xb, }; /** @@ -1851,4 +1856,28 @@ struct iwl_shared_mem_cfg { __le32 page_buff_size; } __packed; /* SHARED_MEM_ALLOC_API_S_VER_1 */ +#define MAX_STORED_BEACON_SIZE 600 + +/** + * Stored beacon notification + * + * @system_time: system time on air rise + * @tsf: TSF on air rise + * @beacon_timestamp: beacon on air rise + * @phy_flags: general phy flags: band, modulation, etc. + * @channel: channel this beacon was received on + * @rates: rate in ucode internal format + * @byte_count: frame's byte count + */ +struct iwl_stored_beacon_notif { + __le32 system_time; + __le64 tsf; + __le32 beacon_timestamp; + __le16 phy_flags; + __le16 channel; + __le32 rates; + __le32 byte_count; + u8 data[MAX_STORED_BEACON_SIZE]; +} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_1 */ + #endif /* __fw_api_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index bf1e5eb5dbdb..62927f567afc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -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 @@ -1462,3 +1462,40 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, iwl_mvm_beacon_loss_iterator, mb); } + +void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb) +{ + struct iwl_rx_packet *pkt = rxb_addr(rxb); + struct iwl_stored_beacon_notif *sb = (void *)pkt->data; + struct ieee80211_rx_status rx_status; + struct sk_buff *skb; + u32 size = le32_to_cpu(sb->byte_count); + + if (size == 0) + return; + + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { + IWL_ERR(mvm, "alloc_skb failed\n"); + return; + } + + /* update rx_status according to the notification's metadata */ + memset(&rx_status, 0, sizeof(rx_status)); + rx_status.mactime = le64_to_cpu(sb->tsf); + 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; + rx_status.freq = + ieee80211_channel_to_frequency(le16_to_cpu(sb->channel), + rx_status.band); + + /* copy the data */ + memcpy(skb_put(skb, size), sb->data, size); + memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); + + /* pass it as regular rx to mac80211 */ + ieee80211_rx_napi(mvm->hw, skb, NULL); +} diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 216c8d6275a1..b45cf4f63781 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1192,6 +1192,8 @@ void iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb); +void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm, + struct iwl_rx_cmd_buffer *rxb); void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, struct ieee80211_vif *vif); unsigned long iwl_mvm_get_used_hw_queues(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 6bf2bde239a0..3c869ad6aaec 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -33,6 +33,7 @@ * * Copyright(c) 2012 - 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 @@ -267,6 +268,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { true), RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false), RX_HANDLER(TOF_NOTIFICATION, iwl_mvm_tof_resp_handler, true), + RX_HANDLER_GRP(PROT_OFFLOAD_GROUP, STORED_BEACON_NTF, + iwl_mvm_rx_stored_beacon_notif, false), }; #undef RX_HANDLER @@ -386,10 +389,18 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = { HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE), }; +/* Please keep this array *SORTED* by hex value. + * Access is done through binary search + */ +static const struct iwl_hcmd_names iwl_mvm_prot_offload_names[] = { + HCMD_NAME(STORED_BEACON_NTF), +}; + 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), [PHY_OPS_GROUP] = HCMD_ARR(iwl_mvm_phy_names), + [PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mvm_prot_offload_names), }; /* this forward declaration can avoid to export the function */ @@ -1195,7 +1206,7 @@ static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm, cmd->is_11n_connection = ap_sta->ht_cap.ht_supported; cmd->offloading_tid = iter_data->offloading_tid; cmd->flags = ENABLE_L3_FILTERING | ENABLE_NBNS_FILTERING | - ENABLE_DHCP_FILTERING; + ENABLE_DHCP_FILTERING | ENABLE_STORE_BEACON; /* * The d0i3 uCode takes care of the nonqos counters, * so configure only the qos seq ones. @@ -1216,8 +1227,7 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) struct iwl_wowlan_config_cmd wowlan_config_cmd = { .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME | IWL_WOWLAN_WAKEUP_BEACON_MISS | - IWL_WOWLAN_WAKEUP_LINK_CHANGE | - IWL_WOWLAN_WAKEUP_BCN_FILTERING), + IWL_WOWLAN_WAKEUP_LINK_CHANGE), }; struct iwl_d3_manager_config d3_cfg_cmd = { .min_sleep_time = cpu_to_le32(1000), @@ -1267,6 +1277,12 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) /* configure wowlan configuration only if needed */ if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) { + /* wake on beacons only if beacon storing isn't supported */ + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BEACON_STORING)) + wowlan_config_cmd.wakeup_filter |= + cpu_to_le32(IWL_WOWLAN_WAKEUP_BCN_FILTERING); + iwl_mvm_wowlan_config_key_params(mvm, d0i3_iter_data.connected_vif, true, flags); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 16b3e36fb1ba..0d03b3e3cf4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -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 @@ -903,9 +903,9 @@ static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); } -int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - u32 flags) +static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 flags, bool d0i3) { struct iwl_beacon_filter_cmd cmd = {}; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); @@ -916,12 +916,20 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags); - if (!ret) + /* don't change bf_enabled in case of temporary d0i3 configuration */ + if (!ret && !d0i3) mvmvif->bf_data.bf_enabled = false; return ret; } +int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + u32 flags) +{ + return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false); +} + static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) { bool disable_ps; @@ -1058,8 +1066,17 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, IWL_BF_CMD_CONFIG_D0I3, .bf_enable_beacon_filter = cpu_to_le32(1), }; - ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, - flags, true); + /* + * When beacon storing is supported - disable beacon filtering + * altogether - the latest beacon will be sent when exiting d0i3 + */ + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BEACON_STORING)) + ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags, + true); + else + ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf, + flags, true); } else { if (mvmvif->bf_data.bf_enabled) ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags); -- cgit From b525d08125e61e262be63ea250e3e13e93b6a92a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 6 Jan 2016 10:01:41 +0100 Subject: iwlwifi: mvm: track low-latency sources separately To be able to test low-latency behaviour properly, split the different low-latency sources so that setting any one of them, for example from debugfs, is sufficient; this avoids getting the debug setting overwritten by other sources. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 19 ++++++++++++++----- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 12 +++++++----- drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 6 ++---- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 9e0d46368cdd..c286a5f8d8bd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 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) 2012 - 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 @@ -1255,6 +1257,7 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; + bool prev; u8 value; int ret; @@ -1265,7 +1268,9 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, return -EINVAL; mutex_lock(&mvm->mutex); - iwl_mvm_update_low_latency(mvm, vif, value); + prev = iwl_mvm_vif_low_latency(mvmvif); + mvmvif->low_latency_dbgfs = value; + iwl_mvm_update_low_latency(mvm, vif, prev); mutex_unlock(&mvm->mutex); return count; @@ -1277,11 +1282,15 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, { struct ieee80211_vif *vif = file->private_data; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - char buf[2]; + char buf[30] = {}; + int len; - buf[0] = mvmvif->low_latency ? '1' : '0'; - buf[1] = '\n'; - return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); + len = snprintf(buf, sizeof(buf) - 1, + "traffic=%d\ndbgfs=%d\nvcmd=%d\n", + mvmvif->low_latency_traffic, + mvmvif->low_latency_dbgfs, + mvmvif->low_latency_vcmd); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); } static ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index b45cf4f63781..418aeffd9bab 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -346,8 +346,9 @@ struct iwl_mvm_vif_bf_data { * @pm_enabled - Indicate if MAC power management is allowed * @monitor_active: indicates that monitor context is configured, and that the * interface should get quota etc. - * @low_latency: indicates that this interface is in low-latency mode - * (VMACLowLatencyMode) + * @low_latency_traffic: indicates low latency traffic was detected + * @low_latency_dbgfs: low latency mode set from debugfs + * @low_latency_vcmd: low latency mode set from vendor command * @ps_disabled: indicates that this interface requires PS to be disabled * @queue_params: QoS params for this MAC * @bcast_sta: station used for broadcast packets. Used by the following @@ -375,7 +376,7 @@ struct iwl_mvm_vif { bool ap_ibss_active; bool pm_enabled; bool monitor_active; - bool low_latency; + bool low_latency_traffic, low_latency_dbgfs, low_latency_vcmd; bool ps_disabled; struct iwl_mvm_vif_bf_data bf_data; @@ -1427,8 +1428,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) * binding, so this has no real impact. For now, just return * the current desired low-latency state. */ - - return mvmvif->low_latency; + return mvmvif->low_latency_dbgfs || + mvmvif->low_latency_traffic || + mvmvif->low_latency_vcmd; } /* hw scheduler queue config */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 3a989f5c20db..59453c176580 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -937,18 +937,16 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) } int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - bool value) + bool prev) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int res; lockdep_assert_held(&mvm->mutex); - if (mvmvif->low_latency == value) + if (iwl_mvm_vif_low_latency(mvmvif) == prev) return 0; - mvmvif->low_latency = value; - res = iwl_mvm_update_quotas(mvm, false, NULL); if (res) return res; -- cgit From a80c1cf9b4b2937cfe782aba7b54a5144fe7eec2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Jan 2016 15:01:00 +0100 Subject: iwlwifi: mvm: support setting minimum quota from debugfs For debug purposes, allow setting minimum quota (for a single virtual interface) from debugfs. This is an absolute minimum, so it can only be set up to 95%. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/debugfs-vif.c | 56 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/quota.c | 16 +++++++ 3 files changed, 73 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index c286a5f8d8bd..14004456bf55 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -1372,6 +1372,59 @@ static ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); } +static void iwl_dbgfs_quota_check(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int *ret = data; + + if (mvmvif->dbgfs_quota_min) + *ret = -EINVAL; +} + +static ssize_t iwl_dbgfs_quota_min_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; + u16 value; + int ret; + + ret = kstrtou16(buf, 0, &value); + if (ret) + return ret; + + if (value > 95) + return -EINVAL; + + mutex_lock(&mvm->mutex); + + mvmvif->dbgfs_quota_min = 0; + ieee80211_iterate_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL, + iwl_dbgfs_quota_check, &ret); + if (ret == 0) { + mvmvif->dbgfs_quota_min = value; + iwl_mvm_update_quotas(mvm, false, NULL); + } + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + +static ssize_t iwl_dbgfs_quota_min_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_vif *vif = file->private_data; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + char buf[10]; + int len; + + len = snprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + #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) \ @@ -1395,6 +1448,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(tof_range_req_ext, 32); 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); void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { @@ -1432,6 +1486,8 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif) S_IRUSR | S_IWUSR); MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, S_IRUSR | S_IWUSR); + MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, + S_IRUSR | S_IWUSR); if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p && mvmvif == mvm->bf_allowed_vif) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 418aeffd9bab..5a34808fdeed 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -433,6 +433,7 @@ struct iwl_mvm_vif { struct iwl_dbgfs_pm dbgfs_pm; struct iwl_dbgfs_bf dbgfs_bf; struct iwl_mac_power_cmd mac_pwr_cmd; + int dbgfs_quota_min; #endif enum ieee80211_smps_mode smps_requests[NUM_IWL_MVM_SMPS_REQ]; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c index 0b762b4f8fad..2141db5bff82 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/quota.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/quota.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 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) 2012 - 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 @@ -74,6 +76,9 @@ struct iwl_mvm_quota_iterator_data { int n_interfaces[MAX_BINDINGS]; int colors[MAX_BINDINGS]; int low_latency[MAX_BINDINGS]; +#ifdef CONFIG_IWLWIFI_DEBUGFS + int dbgfs_min[MAX_BINDINGS]; +#endif int n_low_latency_bindings; struct ieee80211_vif *disabled_vif; }; @@ -129,6 +134,12 @@ static void iwl_mvm_quota_iterator(void *_data, u8 *mac, data->n_interfaces[id]++; +#ifdef CONFIG_IWLWIFI_DEBUGFS + if (mvmvif->dbgfs_quota_min) + data->dbgfs_min[id] = max(data->dbgfs_min[id], + mvmvif->dbgfs_quota_min); +#endif + if (iwl_mvm_vif_low_latency(mvmvif) && !data->low_latency[id]) { data->n_low_latency_bindings++; data->low_latency[id] = true; @@ -259,6 +270,11 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, if (data.n_interfaces[i] <= 0) cmd.quotas[idx].quota = cpu_to_le32(0); +#ifdef CONFIG_IWLWIFI_DEBUGFS + else if (data.dbgfs_min[i]) + cmd.quotas[idx].quota = + cpu_to_le32(data.dbgfs_min[i] * QUOTA_100 / 100); +#endif else if (data.n_low_latency_bindings == 1 && n_non_lowlat && data.low_latency[i]) /* -- cgit From 0c1c6e37137fc2333ef9898c24ea0cb9efbd8df0 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 16 Dec 2015 21:17:06 +0200 Subject: iwlwifi: mvm: change access to ieee80211_hdr Make the code clearer. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 0c073e02fd4c..4cce37238a08 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -294,7 +294,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, struct ieee80211_rx_status *rx_status; struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_mpdu_desc *desc = (void *)pkt->data; - struct ieee80211_hdr *hdr = (void *)(desc + 1); + struct ieee80211_hdr *hdr = (void *)(pkt->data + sizeof(*desc)); u32 len = le16_to_cpu(desc->mpdu_len); u32 rate_n_flags = le32_to_cpu(desc->rate_n_flags); struct ieee80211_sta *sta = NULL; -- cgit From 1c4e15a23d27e2efd56d2b9b7436bff060f126ef Mon Sep 17 00:00:00 2001 From: Max Stepanov Date: Mon, 4 Jan 2016 11:09:14 +0200 Subject: iwlwifi: mvm: add debug print if scan config is ignored Print a debug message in iwl_mvm_config_scan() if a scan configuration data is decided not to be sent to FW. Signed-off-by: Max Stepanov Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 0476e7688e9b..1e1ab9daaec9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -930,8 +930,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm) if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels)) return -ENOBUFS; - if (type == mvm->scan_type) + if (type == mvm->scan_type) { + IWL_DEBUG_SCAN(mvm, + "Ignoring UMAC scan config of the same type\n"); return 0; + } cmd_size = sizeof(*scan_config) + mvm->fw->ucode_capa.n_scan_channels; -- cgit From 837c4da98481d4e504b2aba077c8528fee1b6d13 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 7 Jan 2016 16:50:45 +0200 Subject: iwlwifi: mvm: change the check for ADD_STA status The firmware will return the baid for BA session in the ADD_STA command response. This requires masking the check of the status, which is actually only 8 bits, and not the whole 32 bits. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h index 6fca4fb1d306..1eb3983decc3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h @@ -253,6 +253,9 @@ struct iwl_mvm_keyinfo { __le64 hw_tkip_mic_tx_key; } __packed; +#define IWL_ADD_STA_STATUS_MASK 0xFF +#define IWL_ADD_STA_BAID_MASK 0xFF00 + /** * struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. * ( REPLY_ADD_STA = 0x18 ) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index b556e33658d7..84b7fd1c4c70 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -192,7 +192,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_ASSOC(mvm, "ADD_STA PASSED\n"); break; @@ -362,7 +362,7 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_INFO(mvm, "Frames for staid %d will drained in fw\n", mvmsta->sta_id); @@ -628,7 +628,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_INFO(mvm, "Internal station added.\n"); return 0; @@ -851,7 +851,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: IWL_DEBUG_INFO(mvm, "RX BA Session %sed in fw\n", start ? "start" : "stopp"); @@ -909,7 +909,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (ret) return ret; - switch (status) { + switch (status & IWL_ADD_STA_STATUS_MASK) { case ADD_STA_SUCCESS: break; default: -- cgit From 81f02ba3dbe0c9133dc4490f0a7d3acd99a89aad Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Wed, 30 Dec 2015 23:58:29 +0200 Subject: iwlwifi: mvm: add tlv for multi queue rx support Previous patches enabled the multi-queue rx path based on iwl_mvm_has_new_rx_api() which returned false by default. Change it to return the actual value based on the firmware TLV which is now defined. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h index 5152987c8b8d..e2dbc67a367b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h @@ -347,6 +347,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, + IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT = (__force iwl_ucode_tlv_capa_t)68, IWL_UCODE_TLV_CAPA_BEACON_ANT_SELECTION = (__force iwl_ucode_tlv_capa_t)71, IWL_UCODE_TLV_CAPA_BEACON_STORING = (__force iwl_ucode_tlv_capa_t)72, IWL_UCODE_TLV_CAPA_LAR_SUPPORT_V2 = (__force iwl_ucode_tlv_capa_t)73, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 5a34808fdeed..f87aa972fdce 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1017,8 +1017,8 @@ bool iwl_mvm_is_p2p_standalone_uapsd_supported(struct iwl_mvm *mvm) static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) { - /* firmware flag isn't defined yet */ - return false; + return fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_MULTI_QUEUE_RX_SUPPORT); } extern const u8 iwl_mvm_ac_to_tx_fifo[]; -- cgit From c257d5fb52872213f33016c0750bc2334a781700 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 24 Jan 2016 15:28:43 +0100 Subject: iwlwifi: treat iwl_parse_nvm_data() MAC addr as little endian The MAC address parameters passed to iwl_parse_nvm_data() are passed on to iwl_set_hw_address_family_8000() which treats them as little endian. Annotate them as such, and add the missing byte-swapping in mvm. While at it, add the MAC address to the error to make debugging issues with it easier. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 7 ++++--- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/nvm.c | 8 +++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 7b89bfc8c8ac..50f4cc60cf3e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -539,7 +539,7 @@ static void iwl_set_hw_address_family_8000(struct device *dev, struct iwl_nvm_data *data, const __le16 *mac_override, const __le16 *nvm_hw, - u32 mac_addr0, u32 mac_addr1) + __le32 mac_addr0, __le32 mac_addr1) { const u8 *hw_addr; @@ -583,7 +583,8 @@ static void iwl_set_hw_address_family_8000(struct device *dev, if (!is_valid_ether_addr(data->hw_addr)) IWL_ERR_DEV(dev, - "mac address from hw section is not valid\n"); + "mac address (%pM) from hw section is not valid\n", + data->hw_addr); return; } @@ -597,7 +598,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1) + __le32 mac_addr0, __le32 mac_addr1) { struct iwl_nvm_data *data; u32 sku; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h index 92466ee72806..4e8e0dc474d4 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h @@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *mac_override, const __le16 *phy_sku, u8 tx_chains, u8 rx_chains, bool lar_fw_supported, - u32 mac_addr0, u32 mac_addr1); + __le32 mac_addr0, __le32 mac_addr1); /** * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 7a3da2da6fd0..c446e0da9789 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -300,7 +300,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) struct iwl_nvm_section *sections = mvm->nvm_sections; const __le16 *hw, *sw, *calib, *regulatory, *mac_override, *phy_sku; bool lar_enabled; - u32 mac_addr0, mac_addr1; + __le32 mac_addr0, mac_addr1; /* Checking for required sections */ if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) { @@ -337,8 +337,10 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) return NULL; /* read the mac address from WFMP registers */ - mac_addr0 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_0); - mac_addr1 = iwl_trans_read_prph(mvm->trans, WFMP_MAC_ADDR_1); + mac_addr0 = cpu_to_le32(iwl_trans_read_prph(mvm->trans, + WFMP_MAC_ADDR_0)); + mac_addr1 = cpu_to_le32(iwl_trans_read_prph(mvm->trans, + WFMP_MAC_ADDR_1)); hw = (const __le16 *)sections[mvm->cfg->nvm_hw_section_num].data; sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; -- cgit From 8812182e5df31e49cd888bafa36bcccf87787940 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Sun, 24 Jan 2016 15:18:59 +0200 Subject: iwlwifi: mvm: Remove bf_vif from iwl_power_vifs This member is actually not needed as beacon abort is only allowed for a bss station. Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 28 ++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 0d03b3e3cf4e..83e686dd86ee 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -577,7 +577,6 @@ void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm, struct iwl_power_vifs { struct iwl_mvm *mvm; - struct ieee80211_vif *bf_vif; struct ieee80211_vif *bss_vif; struct ieee80211_vif *p2p_vif; struct ieee80211_vif *ap_vif; @@ -650,11 +649,6 @@ static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac, if (mvmvif->phy_ctxt) if (mvmvif->phy_ctxt->id < MAX_PHYS) power_iterator->bss_active = true; - - if (mvmvif->bf_data.bf_enabled && - !WARN_ON(power_iterator->bf_vif)) - power_iterator->bf_vif = vif; - break; default: @@ -959,21 +953,19 @@ static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm) } static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm, - struct iwl_power_vifs *vifs) + struct ieee80211_vif *vif) { - struct iwl_mvm_vif *mvmvif; + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); bool ba_enable; - if (!vifs->bf_vif) + if (!mvmvif->bf_data.bf_enabled) return 0; - mvmvif = iwl_mvm_vif_from_mac80211(vifs->bf_vif); - ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || - !vifs->bf_vif->bss_conf.ps || + !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif)); - return iwl_mvm_update_beacon_abort(mvm, vifs->bf_vif, ba_enable); + return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); } int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) @@ -994,7 +986,10 @@ int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) if (ret) return ret; - return iwl_mvm_power_set_ba(mvm, &vifs); + if (vifs.bss_vif) + return iwl_mvm_power_set_ba(mvm, vifs.bss_vif); + + return 0; } int iwl_mvm_power_update_mac(struct iwl_mvm *mvm) @@ -1029,7 +1024,10 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm) return ret; } - return iwl_mvm_power_set_ba(mvm, &vifs); + if (vifs.bss_vif) + return iwl_mvm_power_set_ba(mvm, vifs.bss_vif); + + return 0; } int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, -- cgit From 416ec4f3928544fcedba5a4d98866e74ce44f369 Mon Sep 17 00:00:00 2001 From: Avri Altman Date: Sun, 24 Jan 2016 15:56:11 +0200 Subject: iwlwifi: mvm: Remove iwl_mvm_update_beacon_abort It is only called from iwl_mvm_power_set_ba() so simplify things by removing it. Signed-off-by: Avri Altman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/power.c | 37 +++++++++----------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c index 83e686dd86ee..f313910cd026 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c @@ -877,26 +877,6 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm, return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false); } -static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - bool enable) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - struct iwl_beacon_filter_cmd cmd = { - IWL_BF_CMD_CONFIG_DEFAULTS, - .bf_enable_beacon_filter = cpu_to_le32(1), - }; - - if (!mvmvif->bf_data.bf_enabled) - return 0; - - if (mvm->cur_ucode == IWL_UCODE_WOWLAN) - cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); - - mvmvif->bf_data.ba_enabled = enable; - return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); -} - static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u32 flags, bool d0i3) @@ -956,16 +936,23 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm, struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - bool ba_enable; + struct iwl_beacon_filter_cmd cmd = { + IWL_BF_CMD_CONFIG_DEFAULTS, + .bf_enable_beacon_filter = cpu_to_le32(1), + }; if (!mvmvif->bf_data.bf_enabled) return 0; - ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled || - !vif->bss_conf.ps || - iwl_mvm_vif_low_latency(mvmvif)); + if (mvm->cur_ucode == IWL_UCODE_WOWLAN) + cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3); + + mvmvif->bf_data.ba_enabled = !(!mvmvif->pm_enabled || + mvm->ps_disabled || + !vif->bss_conf.ps || + iwl_mvm_vif_low_latency(mvmvif)); - return iwl_mvm_update_beacon_abort(mvm, vif, ba_enable); + return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false); } int iwl_mvm_power_update_ps(struct iwl_mvm *mvm) -- cgit From 854c57057390e45041a56c3d3228eb805e980c99 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 26 Jan 2016 13:17:47 +0200 Subject: iwlwifi: mvm: add new ADD_STA command version The 9000 hardware introduces the frame releaser, which keeps track of the aggregation window and notifies host of the window status. This requires in turn updating the hardware with the RX BA session window size. Firmware API was changed to enable that, update the driver accordingly. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- .../net/wireless/intel/iwlwifi/mvm/fw-api-sta.h | 66 +++++++++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 4 +- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 40 ++++++++++--- drivers/net/wireless/intel/iwlwifi/mvm/sta.h | 2 +- 4 files changed, 99 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h index 1eb3983decc3..90d911394836 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 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) 2012 - 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 @@ -256,6 +258,65 @@ struct iwl_mvm_keyinfo { #define IWL_ADD_STA_STATUS_MASK 0xFF #define IWL_ADD_STA_BAID_MASK 0xFF00 +/** + * struct iwl_mvm_add_sta_cmd_v7 - Add/modify a station in the fw's sta table. + * ( REPLY_ADD_STA = 0x18 ) + * @add_modify: 1: modify existing, 0: add new station + * @awake_acs: + * @tid_disable_tx: is tid BIT(tid) enabled for Tx. Clear BIT(x) to enable + * AMPDU for tid x. Set %STA_MODIFY_TID_DISABLE_TX to change this field. + * @mac_id_n_color: the Mac context this station belongs to + * @addr[ETH_ALEN]: station's MAC address + * @sta_id: index of station in uCode's station table + * @modify_mask: STA_MODIFY_*, selects which parameters to modify vs. leave + * alone. 1 - modify, 0 - don't change. + * @station_flags: look at %iwl_sta_flags + * @station_flags_msk: what of %station_flags have changed + * @add_immediate_ba_tid: tid for which to add block-ack support (Rx) + * Set %STA_MODIFY_ADD_BA_TID to use this field, and also set + * add_immediate_ba_ssn. + * @remove_immediate_ba_tid: tid for which to remove block-ack support (Rx) + * Set %STA_MODIFY_REMOVE_BA_TID to use this field + * @add_immediate_ba_ssn: ssn for the Rx block-ack session. Used together with + * add_immediate_ba_tid. + * @sleep_tx_count: number of packets to transmit to station even though it is + * asleep. Used to synchronise PS-poll and u-APSD responses while ucode + * keeps track of STA sleep state. + * @sleep_state_flags: Look at %iwl_sta_sleep_flag. + * @assoc_id: assoc_id to be sent in VHT PLCP (9-bit), for grp use 0, for AP + * mac-addr. + * @beamform_flags: beam forming controls + * @tfd_queue_msk: tfd queues used by this station + * + * The device contains an internal table of per-station information, with info + * on security keys, aggregation parameters, and Tx rates for initial Tx + * attempt and any retries (set by REPLY_TX_LINK_QUALITY_CMD). + * + * ADD_STA sets up the table entry for one station, either creating a new + * entry, or modifying a pre-existing one. + */ +struct iwl_mvm_add_sta_cmd_v7 { + u8 add_modify; + u8 awake_acs; + __le16 tid_disable_tx; + __le32 mac_id_n_color; + u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */ + __le16 reserved2; + u8 sta_id; + u8 modify_mask; + __le16 reserved3; + __le32 station_flags; + __le32 station_flags_msk; + u8 add_immediate_ba_tid; + u8 remove_immediate_ba_tid; + __le16 add_immediate_ba_ssn; + __le16 sleep_tx_count; + __le16 sleep_state_flags; + __le16 assoc_id; + __le16 beamform_flags; + __le32 tfd_queue_msk; +} __packed; /* ADD_STA_CMD_API_S_VER_7 */ + /** * struct iwl_mvm_add_sta_cmd - Add/modify a station in the fw's sta table. * ( REPLY_ADD_STA = 0x18 ) @@ -285,6 +346,7 @@ struct iwl_mvm_keyinfo { * mac-addr. * @beamform_flags: beam forming controls * @tfd_queue_msk: tfd queues used by this station + * @rx_ba_window: aggregation window size * * The device contains an internal table of per-station information, with info * on security keys, aggregation parameters, and Tx rates for initial Tx @@ -313,7 +375,9 @@ struct iwl_mvm_add_sta_cmd { __le16 assoc_id; __le16 beamform_flags; __le32 tfd_queue_msk; -} __packed; /* ADD_STA_CMD_API_S_VER_7 */ + __le16 rx_ba_window; + __le16 reserved; +} __packed; /* ADD_STA_CMD_API_S_VER_8 */ /** * struct iwl_mvm_add_sta_key_cmd - add/modify sta key diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d70a1716f3e0..01476f545695 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -884,10 +884,10 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, ret = -EINVAL; break; } - ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true); + ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true, buf_size); break; case IEEE80211_AMPDU_RX_STOP: - ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); + ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false, buf_size); break; case IEEE80211_AMPDU_TX_START: if (!iwl_enable_tx_ampdu(mvm->cfg)) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 84b7fd1c4c70..4854e79cbda8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 2015 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) 2012 - 2015 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 @@ -68,6 +70,18 @@ #include "sta.h" #include "rs.h" +/* + * New version of ADD_STA_sta command added new fields at the end of the + * structure, so sending the size of the relevant API's structure is enough to + * support both API versions. + */ +static inline int iwl_mvm_add_sta_cmd_size(struct iwl_mvm *mvm) +{ + return iwl_mvm_has_new_rx_api(mvm) ? + sizeof(struct iwl_mvm_add_sta_cmd) : + sizeof(struct iwl_mvm_add_sta_cmd_v7); +} + static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm, enum nl80211_iftype iftype) { @@ -187,7 +201,8 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta, cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(add_sta_cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &add_sta_cmd, &status); if (ret) return ret; @@ -357,7 +372,8 @@ int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, cmd.station_flags_msk = cpu_to_le32(STA_FLG_DRAIN_FLOW); status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -623,7 +639,8 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, if (addr) memcpy(cmd.addr, addr, ETH_ALEN); - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -819,7 +836,7 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) #define IWL_MAX_RX_BA_SESSIONS 16 int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - int tid, u16 ssn, bool start) + int tid, u16 ssn, bool start, u8 buf_size) { struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_add_sta_cmd cmd = {}; @@ -839,6 +856,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (start) { cmd.add_immediate_ba_tid = (u8) tid; cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); + cmd.rx_ba_window = cpu_to_le16((u16)buf_size); } else { cmd.remove_immediate_ba_tid = (u8) tid; } @@ -846,7 +864,8 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, STA_MODIFY_REMOVE_BA_TID; status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -904,7 +923,8 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, cmd.tid_disable_tx = cpu_to_le16(mvm_sta->tid_disable_agg); status = ADD_STA_SUCCESS; - ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd), + ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, + iwl_mvm_add_sta_cmd_size(mvm), &cmd, &status); if (ret) return ret; @@ -1640,7 +1660,8 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, }; int ret; - ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, + iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); } @@ -1731,7 +1752,7 @@ void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC | CMD_WANT_ASYNC_CALLBACK, - sizeof(cmd), &cmd); + iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); } @@ -1766,7 +1787,8 @@ void iwl_mvm_sta_modify_disable_tx(struct iwl_mvm *mvm, }; int ret; - ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd); + ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, + iwl_mvm_add_sta_cmd_size(mvm), &cmd); if (ret) IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index 39fdf5224e81..e3b9446ee995 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -401,7 +401,7 @@ void iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm, /* AMPDU */ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, - int tid, u16 ssn, bool start); + int tid, u16 ssn, bool start, u8 buf_size); int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid, u16 *ssn); int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, -- cgit From 6ad6c01fa74f649722eeca7308dc1fc4e43235cd Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Wed, 27 Jan 2016 00:10:15 +0200 Subject: iwlwifi: mvm: rs: fix TPC action decision algorithm Decreasing Tx power is allowed only when success ratio is above the threshold defined in the algorithm. Add this condition. Signed-off-by: Gregory Greenman Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index 7bb6fd0e4391..986e12ab9dc2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -2040,7 +2040,8 @@ static enum tpc_action rs_get_tpc_action(struct iwl_mvm *mvm, } /* try decreasing first if applicable */ - if (weak != TPC_INVALID) { + if (sr >= RS_PERCENT(IWL_MVM_RS_TPC_SR_NO_INCREASE) && + weak != TPC_INVALID) { if (weak_tpt == IWL_INVALID_VALUE && (strong_tpt == IWL_INVALID_VALUE || current_tpt >= strong_tpt)) { -- cgit From 43413a975d06e5e34016751fac27e29ec3d4d10f Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Thu, 31 Dec 2015 11:49:18 +0200 Subject: iwlwifi: mvm: support rss queues configuration command 9000 series supports multi-queue rx. The hardware needs to be configured with the hash functions to perform and indirection table that maps hash results to the relevant CPUs\queues. Support this configuration. Add debugfs hook to configure the indirection table in order to enable performance analysis. The configuration is stateless, receives a partial or full pattern and sends the command to the firmware. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 44 ++++++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 33 +++++++++++++++- drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h | 2 + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 29 ++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 1 + drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 4 ++ 6 files changed, 111 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 5c0f93997b7b..005cc09757d2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 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 @@ -943,6 +944,47 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf, return count; } +static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm, + char *buf, size_t count, + loff_t *ppos) +{ + 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_PAYLOAD | + IWL_RSS_HASH_TYPE_IPV6_TCP | + IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, + }; + int ret, i, num_repeats, nbytes = count / 2; + + ret = hex2bin(cmd.indirection_table, buf, nbytes); + if (ret) + return ret; + + /* + * The input is the redirection table, partial or full. + * Repeat the pattern if needed. + * For example, input of 01020F will be repeated 42 times, + * indirecting RSS hash results to queues 1, 2, 15 (skipping + * queues 3 - 14). + */ + num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes; + for (i = 1; i < num_repeats; i++) + memcpy(&cmd.indirection_table[i * nbytes], + cmd.indirection_table, nbytes); + /* handle cut in the middle pattern for the last places */ + memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table, + ARRAY_SIZE(cmd.indirection_table) % nbytes); + + memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key)); + + mutex_lock(&mvm->mutex); + ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); + mutex_unlock(&mvm->mutex); + + return ret ?: count; +} + static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -1455,6 +1497,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); +MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, 16); #ifdef CONFIG_IWLWIFI_BCAST_FILTERING MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); @@ -1499,6 +1542,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR); + MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR); if (!debugfs_create_bool("enable_scan_iteration_notif", S_IRUSR | S_IWUSR, mvm->debugfs_dir, 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 ab467cb9b97c..b45c61e1f45c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -7,7 +7,7 @@ * * Copyright(c) 2012 - 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 @@ -34,7 +34,7 @@ * * Copyright(c) 2012 - 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 @@ -362,4 +362,33 @@ struct iwl_frame_release { __le16 nssn; }; +enum iwl_rss_hash_func_en { + 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, +}; + +#define IWL_RSS_HASH_KEY_CNT 10 +#define IWL_RSS_INDIRECTION_TABLE_SIZE 128 +#define IWL_RSS_ENABLE 1 + +/** + * struct iwl_rss_config_cmd - RSS (Receive Side Scaling) configuration + * + * @flags: 1 - enable, 0 - disable + * @hash_mask: Type of RSS to use. Values are from %iwl_rss_hash_func_en + * @secret_key: 320 bit input of random key configuration from driver + * @indirection_table: indirection table + */ +struct iwl_rss_config_cmd { + __le32 flags; + u8 hash_mask; + u8 reserved[3]; + __le32 secret_key[IWL_RSS_HASH_KEY_CNT]; + u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE]; +} __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */ + #endif /* __fw_api_rx_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h index b6b57273b8ba..f332497e29d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h @@ -213,6 +213,8 @@ enum { MFUART_LOAD_NOTIFICATION = 0xb1, + RSS_CONFIG_CMD = 0xb3, + REPLY_RX_PHY_CMD = 0xc0, REPLY_RX_MPDU_CMD = 0xc1, FRAME_RELEASE = 0xc3, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 4ed5180c547b..070e2af05ca2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -7,6 +7,7 @@ * * Copyright(c) 2012 - 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 @@ -107,6 +108,24 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) sizeof(tx_ant_cmd), &tx_ant_cmd); } +static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm) +{ + int i; + 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_PAYLOAD | + IWL_RSS_HASH_TYPE_IPV6_TCP | + IWL_RSS_HASH_TYPE_IPV6_PAYLOAD, + }; + + 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, ARRAY_SIZE(cmd.secret_key)); + + return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd); +} + static void iwl_free_fw_paging(struct iwl_mvm *mvm) { int i; @@ -894,6 +913,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (ret) goto error; + /* Init RSS configuration */ + if (iwl_mvm_has_new_rx_api(mvm)) { + ret = iwl_send_rss_cfg_cmd(mvm); + if (ret) { + IWL_ERR(mvm, "Failed to configure RSS queues: %d\n", + ret); + goto error; + } + } + /* init the fw <-> mac80211 STA mapping */ for (i = 0; i < IWL_MVM_STATION_COUNT; i++) RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index f87aa972fdce..747f7eb80f47 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -647,6 +647,7 @@ 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 3c869ad6aaec..325ff8aa33f5 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -347,6 +347,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(MAC_PM_POWER_TABLE), HCMD_NAME(TDLS_CHANNEL_SWITCH_NOTIFICATION), HCMD_NAME(MFUART_LOAD_NOTIFICATION), + HCMD_NAME(RSS_CONFIG_CMD), HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), HCMD_NAME(REPLY_RX_PHY_CMD), HCMD_NAME(REPLY_RX_MPDU_CMD), @@ -651,6 +652,9 @@ 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, ARRAY_SIZE(mvm->secret_key)); + return op_mode; out_unregister: -- cgit From bce977310416a2b6c9ad774dfe2071eaacd3d90b Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Mon, 25 Jan 2016 18:14:49 +0200 Subject: iwlwifi: pcie: enable multi-queue rx path Previous patches enabled new 9000 hardware DMA for one queue only. Enable the actual multi-queue path and configuration now. This requires also per-queue NAPI struct. 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 | 35 +++++++++++++++++----- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 14 +-------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 7bc02e0cdd93..2f959162d045 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -136,6 +136,7 @@ struct iwl_rxq { struct iwl_rb_status *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; + struct napi_struct napi; struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; }; @@ -345,7 +346,6 @@ struct iwl_trans_pcie { struct iwl_drv *drv; struct net_device napi_dev; - struct napi_struct napi; struct __percpu iwl_tso_hdr_page *tso_hdr_page; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index a385f3cddb5d..51314e56209d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -2,6 +2,7 @@ * * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -730,7 +731,7 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) iwl_set_bit(trans, CSR_INT_COALESCING, IWL_HOST_INT_OPER_MODE); } -static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) +static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u32 rb_size, enabled = 0; @@ -759,13 +760,13 @@ static void iwl_pcie_rx_mq_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq) for (i = 0; i < trans->num_rx_queues; i++) { /* Tell device where to find RBD free table in DRAM */ iwl_pcie_write_prph_64(trans, RFH_Q_FRBDCB_BA_LSB(i), - (u64)(rxq->bd_dma)); + (u64)(trans_pcie->rxq[i].bd_dma)); /* Tell device where to find RBD used table in DRAM */ iwl_pcie_write_prph_64(trans, RFH_Q_URBDCB_BA_LSB(i), - (u64)(rxq->used_bd_dma)); + (u64)(trans_pcie->rxq[i].used_bd_dma)); /* Tell device where in DRAM to update its Rx status */ iwl_pcie_write_prph_64(trans, RFH_Q_URBD_STTS_WPTR_LSB(i), - rxq->rb_stts_dma); + trans_pcie->rxq[i].rb_stts_dma); /* Reset device indice tables */ iwl_write_prph(trans, RFH_Q_FRBDCB_WIDX(i), 0); iwl_write_prph(trans, RFH_Q_FRBDCB_RIDX(i), 0); @@ -808,6 +809,12 @@ static void iwl_pcie_rx_init_rxb_lists(struct iwl_rxq *rxq) rxq->used_count = 0; } +static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget) +{ + WARN_ON(1); + return 0; +} + int iwl_pcie_rx_init(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -857,6 +864,10 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) iwl_pcie_rx_init_rxb_lists(rxq); + if (!rxq->napi.poll) + netif_napi_add(&trans_pcie->napi_dev, &rxq->napi, + iwl_pcie_dummy_napi_poll, 64); + spin_unlock(&rxq->lock); } @@ -878,7 +889,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans) iwl_pcie_rxq_alloc_rbs(trans, GFP_KERNEL, def_rxq); if (trans->cfg->mq_rx_supported) { - iwl_pcie_rx_mq_hw_init(trans, def_rxq); + iwl_pcie_rx_mq_hw_init(trans); } else { iwl_pcie_rxq_restock(trans, def_rxq); iwl_pcie_rx_hw_init(trans, def_rxq); @@ -940,6 +951,9 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) rxq->used_bd, rxq->used_bd_dma); rxq->used_bd_dma = 0; rxq->used_bd = NULL; + + if (rxq->napi.poll) + netif_napi_del(&rxq->napi); } kfree(trans_pcie->rxq); } @@ -1055,7 +1069,12 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, index = SEQ_TO_INDEX(sequence); cmd_index = get_cmd_index(&txq->q, index); - iwl_op_mode_rx(trans->op_mode, &trans_pcie->napi, &rxcb); + if (rxq->id == 0) + iwl_op_mode_rx(trans->op_mode, &rxq->napi, + &rxcb); + else + iwl_op_mode_rx_rss(trans->op_mode, &rxq->napi, + &rxcb, rxq->id); if (reclaim) { kzfree(txq->entries[cmd_index].free_buf); @@ -1236,8 +1255,8 @@ restart: if (unlikely(emergency && count)) iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq); - if (trans_pcie->napi.poll) - napi_gro_flush(&trans_pcie->napi, false); + if (rxq->napi.poll) + napi_gro_flush(&rxq->napi, false); } /* diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index abe091698471..b796952da644 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -1428,12 +1428,6 @@ static void iwl_trans_pcie_write_prph(struct iwl_trans *trans, u32 addr, iwl_trans_pcie_write32(trans, HBUS_TARG_PRPH_WDAT, val); } -static int iwl_pcie_dummy_napi_poll(struct napi_struct *napi, int budget) -{ - WARN_ON(1); - return 0; -} - static void iwl_trans_pcie_configure(struct iwl_trans *trans, const struct iwl_trans_config *trans_cfg) { @@ -1470,11 +1464,8 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, * As this function may be called again in some corner cases don't * do anything if NAPI was already initialized. */ - if (!trans_pcie->napi.poll) { + if (trans_pcie->napi_dev.reg_state != NETREG_DUMMY) init_dummy_netdev(&trans_pcie->napi_dev); - netif_napi_add(&trans_pcie->napi_dev, &trans_pcie->napi, - iwl_pcie_dummy_napi_poll, 64); - } } void iwl_trans_pcie_free(struct iwl_trans *trans) @@ -1498,9 +1489,6 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) pci_release_regions(trans_pcie->pci_dev); pci_disable_device(trans_pcie->pci_dev); - if (trans_pcie->napi.poll) - netif_napi_del(&trans_pcie->napi); - iwl_pcie_free_fw_monitor(trans); for_each_possible_cpu(i) { -- cgit From d56a7801b544d63b0d32bc8bca0c12a259b1d8e9 Mon Sep 17 00:00:00 2001 From: Sara Sharon Date: Tue, 26 Jan 2016 12:35:13 +0200 Subject: iwlwifi: pcie: update iwl_mpdu_desc fields Final API of iwl_mpdu_desc has a change in the order of the fields and does not include energy from the third antenna (which is perfectly fine, since we don't have one). Update the structure accordingly. Signed-off-by: Sara Sharon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h | 6 +++--- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 11 ++++------- 2 files changed, 7 insertions(+), 10 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 b45c61e1f45c..df939f51d9b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h @@ -347,11 +347,11 @@ struct iwl_rx_mpdu_desc { /* DW8 */ __le32 filter_match; /* DW9 */ - __le32 gp2_on_air_rise; - /* DW10 */ __le32 rate_n_flags; + /* DW10 */ + u8 energy_a, energy_b, channel, reserved; /* DW11 */ - u8 energy_a, energy_b, energy_c, channel; + __le32 gp2_on_air_rise; /* DW12 & DW13 */ __le64 tsf_on_air_rise; } __packed; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 4cce37238a08..615dea143d4e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -201,25 +201,22 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, struct iwl_rx_mpdu_desc *desc, struct ieee80211_rx_status *rx_status) { - int energy_a, energy_b, energy_c, max_energy; + int energy_a, energy_b, max_energy; energy_a = desc->energy_a; energy_a = energy_a ? -energy_a : S8_MIN; energy_b = desc->energy_b; energy_b = energy_b ? -energy_b : S8_MIN; - energy_c = desc->energy_c; - energy_c = energy_c ? -energy_c : S8_MIN; max_energy = max(energy_a, energy_b); - max_energy = max(max_energy, energy_c); - IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n", - energy_a, energy_b, energy_c, max_energy); + IWL_DEBUG_STATS(mvm, "energy In A %d B %d, and max %d\n", + energy_a, energy_b, max_energy); rx_status->signal = max_energy; rx_status->chains = 0; /* TODO: phy info */ rx_status->chain_signal[0] = energy_a; rx_status->chain_signal[1] = energy_b; - rx_status->chain_signal[2] = energy_c; + rx_status->chain_signal[2] = S8_MIN; } static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, -- cgit From c89e333d5e4a27f736c960b29040b261c21563a5 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Tue, 26 Jan 2016 18:12:28 +0200 Subject: iwlwifi: mvm: allow to disable beacon filtering for AP/GO interface When in AP mode we need to filter in beacons from other APs to update HT operation mode. As a power optimization the beacons are filtered out when there are no associated stations. As a result, when there are no associated stations, we will not update the HT operation mode until a station connects. Add a debugfs parameter that allows to disable this optimization. Signed-off-by: Andrei Otcheretianski Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 3 +++ drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 6 ++++++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 005cc09757d2..c529e5355803 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1548,6 +1548,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) mvm->debugfs_dir, &mvm->scan_iter_notif_enabled)) goto err; + if (!debugfs_create_bool("drop_bcn_ap_mode", S_IRUSR | S_IWUSR, + mvm->debugfs_dir, &mvm->drop_bcn_ap_mode)) + goto err; #ifdef CONFIG_IWLWIFI_BCAST_FILTERING if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index 62927f567afc..535134d639e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -744,7 +744,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm, * wake-ups. */ cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); - if (mvmvif->ap_assoc_sta_count) { + if (mvmvif->ap_assoc_sta_count || !mvm->drop_bcn_ap_mode) { cmd->filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n"); } else { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 747f7eb80f47..ebe37bb0ce4c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -859,6 +859,12 @@ struct iwl_mvm { u32 ciphers[6]; struct iwl_mvm_tof_data tof_data; + + /* + * Drop beacons from other APs in AP mode when there are no connected + * clients. + */ + bool drop_bcn_ap_mode; }; /* Extract MVM priv from op_mode and _hw */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 325ff8aa33f5..09a94a5efb61 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -492,6 +492,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, } mvm->sf_state = SF_UNINIT; mvm->cur_ucode = IWL_UCODE_INIT; + mvm->drop_bcn_ap_mode = true; mutex_init(&mvm->mutex); mutex_init(&mvm->d0i3_suspend_mutex); -- cgit From b97baa3e22e18dac42001e665cf27ad1211bf878 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 12:09:56 -0200 Subject: [media] hdpvr: hide unused variable The i2c client pointer is only used when CONFIG_I2C is set, and otherwise produces a compile-time warning: drivers/media/usb/hdpvr/hdpvr-core.c: In function 'hdpvr_probe': drivers/media/usb/hdpvr/hdpvr-core.c:276:21: error: unused variable 'client' [-Werror=unused-variable] This uses the same #ifdef to hide the variable when the code using it is hidden. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/hdpvr/hdpvr-core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 3fc64197b4e6..08f0ca7aa012 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -273,7 +273,9 @@ static int hdpvr_probe(struct usb_interface *interface, struct hdpvr_device *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; +#if IS_ENABLED(CONFIG_I2C) struct i2c_client *client; +#endif size_t buffer_size; int i; int retval = -ENOMEM; -- cgit From 733d0def3ebdd1d088330d904149af21fa4b9ae2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 12:09:58 -0200 Subject: [media] b2c2: flexcop: avoid unused function warnings The flexcop driver has two functions that are normally used, except when multiple frontend drivers are disabled: drivers/media/common/b2c2/flexcop-fe-tuner.c:42:12: warning: 'flexcop_set_voltage' defined but not used [-Wunused-function] drivers/media/common/b2c2/flexcop-fe-tuner.c:71:12: warning: 'flexcop_sleep' defined but not used [-Wunused-function] This avoids the build warning by updating the #ifdef for flexcop_set_voltage to the exact condition under which it is used. For flexcop_sleep, the condition is rather complex, so I resort to marking it as __maybe_unused, so the compiler can silently drop it. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/b2c2/flexcop-fe-tuner.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c index 9c59f4306883..f5956402fc69 100644 --- a/drivers/media/common/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c @@ -38,7 +38,7 @@ static int flexcop_fe_request_firmware(struct dvb_frontend *fe, #endif /* lnb control */ -#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) +#if (FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)) && FE_SUPPORTED(PLL) static int flexcop_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) { @@ -68,7 +68,7 @@ static int flexcop_set_voltage(struct dvb_frontend *fe, #endif #if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312) -static int flexcop_sleep(struct dvb_frontend* fe) +static int __maybe_unused flexcop_sleep(struct dvb_frontend* fe) { struct flexcop_device *fc = fe->dvb->priv; if (fc->fe_sleep) -- cgit From 7c8fe516bd81d991feb73ccd969ec29850af3013 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 Jan 2016 19:46:02 -0200 Subject: [media] v4l: remove MEDIA_TUNER dependency for VIDEO_TUNER em28xx selects VIDEO_TUNER, which has a dependency on MEDIA_TUNER, so we get a Kconfig warning if that is disabled: warning: (VIDEO_PVRUSB2 && VIDEO_USBVISION && VIDEO_GO7007 && VIDEO_AU0828_V4L2 && VIDEO_CX231XX && VIDEO_TM6000 && VIDEO_EM28XX && VIDEO_IVTV && VIDEO_MXB && VIDEO_CX18 && VIDEO_CX23885 && VIDEO_CX88 && VIDEO_BT848 && VIDEO_SAA7134 && VIDEO_SAA7164) selects VIDEO_TUNER which has unmet direct dependencies (MEDIA_SUPPORT && MEDIA_TUNER) VIDEO_TUNER does not actually depend on MEDIA_TUNER, and the dependency does nothing except cause the above warning, so let's remove it. Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig index 9beece00869b..29b3436d0910 100644 --- a/drivers/media/v4l2-core/Kconfig +++ b/drivers/media/v4l2-core/Kconfig @@ -37,7 +37,6 @@ config VIDEO_PCI_SKELETON # Used by drivers that need tuner.ko config VIDEO_TUNER tristate - depends on MEDIA_TUNER # Used by drivers that need v4l2-mem2mem.ko config V4L2_MEM2MEM_DEV -- cgit From d40ec6fdb0b03b7be4c7923a3da0e46bf943740a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Jan 2016 21:49:33 -0200 Subject: [media] media: Fix media_open() to clear filp->private_data in error leg Fix media_open() to clear filp->private_data when file open fails. Signed-off-by: Shuah Khan Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-devnode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c index cea35bf20011..29409f440f1c 100644 --- a/drivers/media/media-devnode.c +++ b/drivers/media/media-devnode.c @@ -181,6 +181,7 @@ static int media_open(struct inode *inode, struct file *filp) ret = mdev->fops->open(filp); if (ret) { put_device(&mdev->dev); + filp->private_data = NULL; return ret; } } -- cgit From 3801bc7d1b8dd70d47a92e58d6fb5653c10b7c95 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Sat, 30 Jan 2016 18:10:52 -0200 Subject: [media] media: Media Controller fix to not let stream_count go negative Change media_entity_pipeline_stop() to not decrement stream_count of an inactive media pipeline. Doing so, results in preventing starting the pipeline. Signed-off-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/media-entity.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c index e89d85a7d31b..f2e43603d6d2 100644 --- a/drivers/media/media-entity.c +++ b/drivers/media/media-entity.c @@ -452,9 +452,12 @@ error: media_entity_graph_walk_start(graph, entity_err); while ((entity_err = media_entity_graph_walk_next(graph))) { - entity_err->stream_count--; - if (entity_err->stream_count == 0) - entity_err->pipe = NULL; + /* don't let the stream_count go negative */ + if (entity->stream_count > 0) { + entity_err->stream_count--; + if (entity_err->stream_count == 0) + entity_err->pipe = NULL; + } /* * We haven't increased stream_count further than this @@ -486,9 +489,12 @@ void media_entity_pipeline_stop(struct media_entity *entity) media_entity_graph_walk_start(graph, entity); while ((entity = media_entity_graph_walk_next(graph))) { - entity->stream_count--; - if (entity->stream_count == 0) - entity->pipe = NULL; + /* don't let the stream_count go negative */ + if (entity->stream_count > 0) { + entity->stream_count--; + if (entity->stream_count == 0) + entity->pipe = NULL; + } } if (!--pipe->streaming_count) -- cgit From 6b3f99989eb73e5250bba9dfeaa852939acfbf70 Mon Sep 17 00:00:00 2001 From: Abhilash Jindal Date: Sun, 31 Jan 2016 03:47:31 -0200 Subject: [media] dvb-frontend: Use boottime Wall time obtained from ktime_get_real is susceptible to sudden jumps due to user setting the time or due to NTP. Boot time is constantly increasing time better suited for comparing two timestamps. [mchehab@osg.samsung.com: fix trivial merge conflicts] Signed-off-by: Abhilash Jindal Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 8 ++++---- drivers/media/dvb-frontends/stv0299.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 40080645341e..03cc508b8c42 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -899,10 +899,10 @@ void dvb_frontend_sleep_until(ktime_t *waketime, u32 add_usec) s32 delta; *waketime = ktime_add_us(*waketime, add_usec); - delta = ktime_us_delta(ktime_get_real(), *waketime); + delta = ktime_us_delta(ktime_get_boottime(), *waketime); if (delta > 2500) { msleep((delta - 1500) / 1000); - delta = ktime_us_delta(ktime_get_real(), *waketime); + delta = ktime_us_delta(ktime_get_boottime(), *waketime); } if (delta > 0) udelay(delta); @@ -2451,7 +2451,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, u8 last = 1; if (dvb_frontend_debug) printk("%s switch command: 0x%04lx\n", __func__, swcmd); - nexttime = ktime_get_real(); + nexttime = ktime_get_boottime(); if (dvb_frontend_debug) tv[0] = nexttime; /* before sending a command, initialize by sending @@ -2462,7 +2462,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, for (i = 0; i < 9; i++) { if (dvb_frontend_debug) - tv[i+1] = ktime_get_real(); + tv[i+1] = ktime_get_boottime(); if ((swcmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index a8177807fb65..c43f36d32340 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -422,7 +422,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long if (debug_legacy_dish_switch) printk ("%s switch command: 0x%04lx\n",__func__, cmd); - nexttime = ktime_get_real(); + nexttime = ktime_get_boottime(); if (debug_legacy_dish_switch) tv[0] = nexttime; stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */ @@ -431,7 +431,7 @@ static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long for (i=0; i<9; i++) { if (debug_legacy_dish_switch) - tv[i+1] = ktime_get_real(); + tv[i+1] = ktime_get_boottime(); if((cmd & 0x01) != last) { /* set voltage to (last ? 13V : 18V) */ stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50)); -- cgit From 744070e0e4ac691bb43608f7bf46a9641a9cf342 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:48 +0900 Subject: perf hists: Fix min callchain hits calculation The total period should be get using hists__total_period() since it takes filtered entries into account. In addition, if callchain mode is 'fractal', the total period should be the entry's period. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 81ce0aff69d1..b96194676c91 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1163,9 +1163,18 @@ static void __hists__insert_output_entry(struct rb_root *entries, struct rb_node *parent = NULL; struct hist_entry *iter; - if (use_callchain) + if (use_callchain) { + if (callchain_param.mode == CHAIN_GRAPH_REL) { + u64 total = he->stat.period; + + if (symbol_conf.cumulate_callchain) + total = he->stat_acc->period; + + min_callchain_hits = total * (callchain_param.min_percent / 100); + } callchain_param.sort(&he->sorted_chain, he->callchain, min_callchain_hits, &callchain_param); + } while (*p != NULL) { parent = *p; @@ -1195,7 +1204,7 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog) else use_callchain = symbol_conf.use_callchain; - min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100); + min_callchain_hits = hists__total_period(hists) * (callchain_param.min_percent / 100); if (sort__need_collapse) root = &hists->entries_collapsed; -- cgit From 0f58474ec835f6fc80af2cde2c7ed5495cd212ba Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:49 +0900 Subject: perf hists: Update hists' total period when adding entries Currently the hist entry addition path doesn't update total_period of hists and it's calculated during 'resort' path. But the resort path needs to know the total period before doing its job because it's used for calculating percent limit of callchains in hist entries. So this patch update the total period during the addition path. It makes the percent limit of callchains working (again). Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-3-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b96194676c91..098310bc4489 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -432,8 +432,12 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, cmp = hist_entry__cmp(he, entry); if (!cmp) { - if (sample_self) + if (sample_self) { he_stat__add_period(&he->stat, period, weight); + hists->stats.total_period += period; + if (!he->filtered) + hists->stats.total_non_filtered_period += period; + } if (symbol_conf.cumulate_callchain) he_stat__add_period(he->stat_acc, period, weight); @@ -466,7 +470,10 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, if (!he) return NULL; - hists->nr_entries++; + if (sample_self) + hists__inc_stats(hists, he); + else + hists->nr_entries++; rb_link_node(&he->rb_node_in, parent, p); rb_insert_color(&he->rb_node_in, hists->entries_in); -- cgit From ea4570d6c29994017e09196d1f8077fb5942b676 Mon Sep 17 00:00:00 2001 From: Andreas Dannenberg Date: Fri, 29 Jan 2016 13:03:00 -0600 Subject: iio: light: opt3001: Add device tree binding documentation The original documentation as submitted with the driver appears to have dropped down a rabbit hole. Signed-off-by: Andreas Dannenberg Acked-by: Rob Herring Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/light/opt3001.txt | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/light/opt3001.txt diff --git a/Documentation/devicetree/bindings/iio/light/opt3001.txt b/Documentation/devicetree/bindings/iio/light/opt3001.txt new file mode 100644 index 000000000000..eac30d508849 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/light/opt3001.txt @@ -0,0 +1,26 @@ +* Texas Instruments OPT3001 Ambient Light Sensor + +The driver supports interrupt-driven and interrupt-less operation, depending +on whether an interrupt property has been populated into the DT. Note that +the optional generation of IIO events on rising/falling light threshold changes +requires the use of interrupts. Without interrupts, only the simple reading +of the current light value is supported through the IIO API. + +http://www.ti.com/product/opt3001 + +Required properties: + - compatible: should be "ti,opt3001" + - reg: the I2C address of the sensor + +Optional properties: + - interrupt-parent: should be the phandle for the interrupt controller + - interrupts: interrupt mapping for GPIO IRQ (configure for falling edge) + +Example: + +opt3001@44 { + compatible = "ti,opt3001"; + reg = <0x44>; + interrupt-parent = <&gpio1>; + interrupts = <28 IRQ_TYPE_EDGE_FALLING>; +}; -- cgit From 2665b4528d0522ef073c2bde33cf9a7bd7391164 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:50 +0900 Subject: perf report: Apply --percent-limit to callchains also Currently --percent-limit option only works for hist entries. However it'd be better to have same effect to callchains as well Requested-by: Andi Kleen Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 2bf537f190a0..72ed0b46d5a1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -75,7 +75,10 @@ static int report__config(const char *var, const char *value, void *cb) return 0; } if (!strcmp(var, "report.percent-limit")) { - rep->min_percent = strtof(value, NULL); + double pcnt = strtof(value, NULL); + + rep->min_percent = pcnt; + callchain_param.min_percent = pcnt; return 0; } if (!strcmp(var, "report.children")) { @@ -633,8 +636,10 @@ parse_percent_limit(const struct option *opt, const char *str, int unset __maybe_unused) { struct report *rep = opt->value; + double pcnt = strtof(str, NULL); - rep->min_percent = strtof(str, NULL); + rep->min_percent = pcnt; + callchain_param.min_percent = pcnt; return 0; } -- cgit From 7e597d327eca3d92a759542ff707cba61af3a718 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:51 +0900 Subject: perf report: Get rid of hist_entry__callchain_fprintf() It's just a wrapper function to align the start position ofcallchains to 'comm' of each thread if it's a first sort key. But it doesn't not work with tracepoint events and also with upcoming hierarchy view. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-5-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/stdio/hist.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 387110d50b00..8e25f7dd6e84 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -349,30 +349,6 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he, return 0; } -static size_t hist_entry__callchain_fprintf(struct hist_entry *he, - struct hists *hists, - FILE *fp) -{ - int left_margin = 0; - u64 total_period = hists->stats.total_period; - - if (field_order == NULL && (sort_order == NULL || - !prefixcmp(sort_order, "comm"))) { - struct perf_hpp_fmt *fmt; - - perf_hpp__for_each_format(fmt) { - if (!perf_hpp__is_sort_entry(fmt)) - continue; - - /* must be 'comm' sort entry */ - left_margin = fmt->width(fmt, NULL, hists_to_evsel(hists)); - left_margin -= thread__comm_len(he->thread); - break; - } - } - return hist_entry_callchain__fprintf(he, total_period, left_margin, fp); -} - static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) { const char *sep = symbol_conf.field_sep; @@ -418,6 +394,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, .buf = bf, .size = size, }; + u64 total_period = hists->stats.total_period; if (size == 0 || size > bfsz) size = hpp.size = bfsz; @@ -427,7 +404,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, ret = fprintf(fp, "%s\n", bf); if (symbol_conf.use_callchain) - ret += hist_entry__callchain_fprintf(he, hists, fp); + ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); return ret; } -- cgit From 54d27b3119e2eecbb3dfbf821db90fab25f6c523 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:52 +0900 Subject: perf callchain: Pass parent_samples to __callchain__fprintf_graph() Pass hist entry's period to graph callchain print function. This info is needed by later patch to determine whether it can omit percentage of top-level node or not. No functional change intended. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-6-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/stdio/hist.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 8e25f7dd6e84..96188ea12771 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -166,7 +166,8 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, } static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, - u64 total_samples, int left_margin) + u64 total_samples, u64 parent_samples, + int left_margin) { struct callchain_node *cnode; struct callchain_list *chain; @@ -213,6 +214,9 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, root = &cnode->rb_root; } + if (callchain_param.mode == CHAIN_GRAPH_REL) + total_samples = parent_samples; + ret += __callchain__fprintf_graph(fp, root, total_samples, 1, 1, left_margin); ret += fprintf(fp, "\n"); @@ -323,16 +327,19 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he, u64 total_samples, int left_margin, FILE *fp) { + u64 parent_samples = he->stat.period; + + if (symbol_conf.cumulate_callchain) + parent_samples = he->stat_acc->period; + switch (callchain_param.mode) { case CHAIN_GRAPH_REL: - return callchain__fprintf_graph(fp, &he->sorted_chain, - symbol_conf.cumulate_callchain ? - he->stat_acc->period : he->stat.period, - left_margin); + return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, + parent_samples, left_margin); break; case CHAIN_GRAPH_ABS: return callchain__fprintf_graph(fp, &he->sorted_chain, total_samples, - left_margin); + parent_samples, left_margin); break; case CHAIN_FLAT: return callchain__fprintf_flat(fp, &he->sorted_chain, total_samples); -- cgit From 7ed5d6e28a0a1a54f554b0ab9c38a6061e7cac9e Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:53 +0900 Subject: perf report: Fix percent display in callchains on --stdio When there's only a single callchain, perf doesn't print its percentage in front of the symbols. This is because it assumes that the percentage is same as parents. But if a percent limit is applied, it's possible that there are actually a couple of child nodes but only one of them is shown. In this case it should display the percent to prevent misunderstanding of its percentage is same as the parent's. For example, let's see the following callchain. $ perf report -s comm --percent-limit 0.01 --stdio ... 9.95% swapper | |--7.57%--intel_idle | cpuidle_enter_state | cpuidle_enter | call_cpuidle | cpu_startup_entry | | | |--4.89%--start_secondary | | | --2.68%--rest_init | start_kernel | x86_64_start_reservations | x86_64_start_kernel | |--0.15%--__schedule | | | |--0.13%--schedule | | schedule_preempt_disable | | cpu_startup_entry | | | | | |--0.09%--start_secondary | | | | | --0.04%--rest_init | | start_kernel | | x86_64_start_reservations | | x86_64_start_kernel | | | --0.01%--schedule_preempt_disabled | cpu_startup_entry ... Current code omits the percent if 'intel_idle' becomes the only node when percent limit is set to 0.5%, its percent is not 9.95% but users will assume it incorrectly. Before: $ perf report --percent-limit 0.5 --stdio ... 9.95% swapper | ---intel_idle cpuidle_enter_state cpuidle_enter call_cpuidle cpu_startup_entry | |--4.89%--start_secondary | --2.68%--rest_init start_kernel x86_64_start_reservations x86_64_start_kernel After: $ perf report --percent-limit 0.5 --stdio ... 9.95% swapper | --7.57%--intel_idle cpuidle_enter_state cpuidle_enter call_cpuidle cpu_startup_entry | |--4.89%--start_secondary | --2.68%--rest_init start_kernel x86_64_start_reservations x86_64_start_kernel Signed-off-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-7-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/stdio/hist.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 96188ea12771..76ff46becac8 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -165,6 +165,25 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct rb_root *root, return ret; } +/* + * If have one single callchain root, don't bother printing + * its percentage (100 % in fractal mode and the same percentage + * than the hist in graph mode). This also avoid one level of column. + * + * However when percent-limit applied, it's possible that single callchain + * node have different (non-100% in fractal mode) percentage. + */ +static bool need_percent_display(struct rb_node *node, u64 parent_samples) +{ + struct callchain_node *cnode; + + if (rb_next(node)) + return true; + + cnode = rb_entry(node, struct callchain_node, rb_node); + return callchain_cumul_hits(cnode) != parent_samples; +} + static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, u64 total_samples, u64 parent_samples, int left_margin) @@ -178,13 +197,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, int ret = 0; char bf[1024]; - /* - * If have one single callchain root, don't bother printing - * its percentage (100 % in fractal mode and the same percentage - * than the hist in graph mode). This also avoid one level of column. - */ node = rb_first(root); - if (node && !rb_next(node)) { + if (node && !need_percent_display(node, parent_samples)) { cnode = rb_entry(node, struct callchain_node, rb_node); list_for_each_entry(chain, &cnode->val, list) { /* -- cgit From 0c841c6c16f320704f75970bbe6a9800c53e6cf5 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:54 +0900 Subject: perf hists browser: Fix dump to show correct callchain style The commit 8c430a348699 ("perf hists browser: Support folded callchains") missed to update hist_browser__dump() so it always shows graph-style callchains regardless of current setting. To fix that, factor out callchain printing code and rename the existing function which prints graph-style callchain. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Fixes: 8c430a348699 ("perf hists browser: Support folded callchains") Link: http://lkml.kernel.org/r/1453909257-26015-8-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 73 ++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 1da30f8aa7a5..6b22baf525dd 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -844,7 +844,7 @@ next: return row - first_row; } -static int hist_browser__show_callchain(struct hist_browser *browser, +static int hist_browser__show_callchain_graph(struct hist_browser *browser, struct rb_root *root, int level, unsigned short row, u64 total, print_callchain_entry_fn print, @@ -898,7 +898,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, else new_total = total; - row += hist_browser__show_callchain(browser, &child->rb_root, + row += hist_browser__show_callchain_graph(browser, &child->rb_root, new_level, row, new_total, print, arg, is_output_full); } @@ -910,6 +910,43 @@ out: return row - first_row; } +static int hist_browser__show_callchain(struct hist_browser *browser, + struct hist_entry *entry, int level, + unsigned short row, + print_callchain_entry_fn print, + struct callchain_print_arg *arg, + check_output_full_fn is_output_full) +{ + u64 total = hists__total_period(entry->hists); + int printed; + + if (callchain_param.mode == CHAIN_GRAPH_REL) { + if (symbol_conf.cumulate_callchain) + total = entry->stat_acc->period; + else + total = entry->stat.period; + } + + if (callchain_param.mode == CHAIN_FLAT) { + printed = hist_browser__show_callchain_flat(browser, + &entry->sorted_chain, row, total, + print, arg, is_output_full); + } else if (callchain_param.mode == CHAIN_FOLDED) { + printed = hist_browser__show_callchain_folded(browser, + &entry->sorted_chain, row, total, + print, arg, is_output_full); + } else { + printed = hist_browser__show_callchain_graph(browser, + &entry->sorted_chain, level, row, total, + print, arg, is_output_full); + } + + if (arg->is_current_entry) + browser->he_selection = entry; + + return printed; +} + struct hpp_arg { struct ui_browser *b; char folded_sign; @@ -1084,38 +1121,14 @@ static int hist_browser__show_entry(struct hist_browser *browser, --row_offset; if (folded_sign == '-' && row != browser->b.rows) { - u64 total = hists__total_period(entry->hists); struct callchain_print_arg arg = { .row_offset = row_offset, .is_current_entry = current_entry, }; - if (callchain_param.mode == CHAIN_GRAPH_REL) { - if (symbol_conf.cumulate_callchain) - total = entry->stat_acc->period; - else - total = entry->stat.period; - } - - if (callchain_param.mode == CHAIN_FLAT) { - printed += hist_browser__show_callchain_flat(browser, - &entry->sorted_chain, row, total, + printed += hist_browser__show_callchain(browser, entry, 1, row, hist_browser__show_callchain_entry, &arg, hist_browser__check_output_full); - } else if (callchain_param.mode == CHAIN_FOLDED) { - printed += hist_browser__show_callchain_folded(browser, - &entry->sorted_chain, row, total, - hist_browser__show_callchain_entry, &arg, - hist_browser__check_output_full); - } else { - printed += hist_browser__show_callchain(browser, - &entry->sorted_chain, 1, row, total, - hist_browser__show_callchain_entry, &arg, - hist_browser__check_output_full); - } - - if (arg.is_current_entry) - browser->he_selection = entry; } return printed; @@ -1380,15 +1393,11 @@ do_offset: static int hist_browser__fprintf_callchain(struct hist_browser *browser, struct hist_entry *he, FILE *fp) { - u64 total = hists__total_period(he->hists); struct callchain_print_arg arg = { .fp = fp, }; - if (symbol_conf.cumulate_callchain) - total = he->stat_acc->period; - - hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total, + hist_browser__show_callchain(browser, he, 1, 0, hist_browser__fprintf_callchain_entry, &arg, hist_browser__check_dump_full); return arg.printed; -- cgit From 5eca104eee7edfe7155523849750ced539b16e94 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:55 +0900 Subject: perf hists browser: Pass parent_total to callchain print functions Pass parent node's total period to callchain print functions. This info is needed by later patch to determine whether it can omit percent or not correctly. No functional change intended. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-9-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 44 +++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 6b22baf525dd..41dbb79c992e 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -660,6 +660,7 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, static int hist_browser__show_callchain_flat(struct hist_browser *browser, struct rb_root *root, unsigned short row, u64 total, + u64 parent_total __maybe_unused, print_callchain_entry_fn print, struct callchain_print_arg *arg, check_output_full_fn is_output_full) @@ -763,6 +764,7 @@ static char *hist_browser__folded_callchain_str(struct hist_browser *browser, static int hist_browser__show_callchain_folded(struct hist_browser *browser, struct rb_root *root, unsigned short row, u64 total, + u64 parent_total __maybe_unused, print_callchain_entry_fn print, struct callchain_print_arg *arg, check_output_full_fn is_output_full) @@ -847,14 +849,18 @@ next: static int hist_browser__show_callchain_graph(struct hist_browser *browser, struct rb_root *root, int level, unsigned short row, u64 total, + u64 parent_total, print_callchain_entry_fn print, struct callchain_print_arg *arg, check_output_full_fn is_output_full) { struct rb_node *node; int first_row = row, offset = level * LEVEL_OFFSET_STEP; - u64 new_total; bool need_percent; + u64 percent_total = total; + + if (callchain_param.mode == CHAIN_GRAPH_REL) + percent_total = parent_total; node = rb_first(root); need_percent = node && rb_next(node); @@ -878,7 +884,7 @@ static int hist_browser__show_callchain_graph(struct hist_browser *browser, folded_sign = callchain_list__folded(chain); row += hist_browser__show_callchain_list(browser, child, - chain, row, total, + chain, row, percent_total, was_first && need_percent, offset + extra_offset, print, arg); @@ -893,13 +899,9 @@ static int hist_browser__show_callchain_graph(struct hist_browser *browser, if (folded_sign == '-') { const int new_level = level + (extra_offset ? 2 : 1); - if (callchain_param.mode == CHAIN_GRAPH_REL) - new_total = child->children_hit; - else - new_total = total; - row += hist_browser__show_callchain_graph(browser, &child->rb_root, - new_level, row, new_total, + new_level, row, total, + child->children_hit, print, arg, is_output_full); } if (is_output_full(browser, row)) @@ -918,27 +920,29 @@ static int hist_browser__show_callchain(struct hist_browser *browser, check_output_full_fn is_output_full) { u64 total = hists__total_period(entry->hists); + u64 parent_total; int printed; - if (callchain_param.mode == CHAIN_GRAPH_REL) { - if (symbol_conf.cumulate_callchain) - total = entry->stat_acc->period; - else - total = entry->stat.period; - } + if (symbol_conf.cumulate_callchain) + parent_total = entry->stat_acc->period; + else + parent_total = entry->stat.period; if (callchain_param.mode == CHAIN_FLAT) { printed = hist_browser__show_callchain_flat(browser, - &entry->sorted_chain, row, total, - print, arg, is_output_full); + &entry->sorted_chain, row, + total, parent_total, print, arg, + is_output_full); } else if (callchain_param.mode == CHAIN_FOLDED) { printed = hist_browser__show_callchain_folded(browser, - &entry->sorted_chain, row, total, - print, arg, is_output_full); + &entry->sorted_chain, row, + total, parent_total, print, arg, + is_output_full); } else { printed = hist_browser__show_callchain_graph(browser, - &entry->sorted_chain, level, row, total, - print, arg, is_output_full); + &entry->sorted_chain, level, row, + total, parent_total, print, arg, + is_output_full); } if (arg->is_current_entry) -- cgit From 59c624e2391080fa6315a376a4ee74d0eb393d1d Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 00:40:56 +0900 Subject: perf hists browser: Fix percent display in callchains When there's only a single callchain, perf doesn't print its percentage in front of the symbols. This is because it assumes that the percentage is same as parents. But if a percent limit is applied, it's possible that there are actually a couple of child nodes but only one of them is shown. In this case it should display the percent to prevent misunderstanding of its percentage is same as the parent's. For example, let's see the following callchain. $ perf report --no-children --percent-limit 0.01 --tui ... - 0.06% sleep [kernel.vmlinux] [k] kmem_cache_alloc_trace kmem_cache_alloc_trace - perf_event_mmap - 0.04% mmap_region do_mmap_pgoff - vm_mmap_pgoff + 0.02% sys_mmap_pgoff + 0.02% vm_mmap + 0.02% mprotect_fixup Current code omits the percent if 'mmap_region' becomes the only node when percent limit is set to 0.03%, its percent is not 0.06% but users will assume it incorrectly. Before: $ perf report --no-children --percent-limit 0.03 --tui ... 0.06% sleep [kernel.vmlinux] [k] kmem_cache_alloc_trace kmem_cache_alloc_trace - perf_event_mmap - mmap_region do_mmap_pgoff vm_mmap_pgoff After: $ perf report --no-children --percent-limit 0.03 --tui ... 0.06% sleep [kernel.vmlinux] [k] kmem_cache_alloc_trace kmem_cache_alloc_trace - perf_event_mmap - 0.04% mmap_region do_mmap_pgoff vm_mmap_pgoff Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/1453909257-26015-10-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 41dbb79c992e..61d578bf4ffd 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -657,10 +657,24 @@ static int hist_browser__show_callchain_list(struct hist_browser *browser, return 1; } +static bool check_percent_display(struct rb_node *node, u64 parent_total) +{ + struct callchain_node *child; + + if (node == NULL) + return false; + + if (rb_next(node)) + return true; + + child = rb_entry(node, struct callchain_node, rb_node); + return callchain_cumul_hits(child) != parent_total; +} + static int hist_browser__show_callchain_flat(struct hist_browser *browser, struct rb_root *root, unsigned short row, u64 total, - u64 parent_total __maybe_unused, + u64 parent_total, print_callchain_entry_fn print, struct callchain_print_arg *arg, check_output_full_fn is_output_full) @@ -670,7 +684,7 @@ static int hist_browser__show_callchain_flat(struct hist_browser *browser, bool need_percent; node = rb_first(root); - need_percent = node && rb_next(node); + need_percent = check_percent_display(node, parent_total); while (node) { struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); @@ -764,7 +778,7 @@ static char *hist_browser__folded_callchain_str(struct hist_browser *browser, static int hist_browser__show_callchain_folded(struct hist_browser *browser, struct rb_root *root, unsigned short row, u64 total, - u64 parent_total __maybe_unused, + u64 parent_total, print_callchain_entry_fn print, struct callchain_print_arg *arg, check_output_full_fn is_output_full) @@ -774,7 +788,7 @@ static int hist_browser__show_callchain_folded(struct hist_browser *browser, bool need_percent; node = rb_first(root); - need_percent = node && rb_next(node); + need_percent = check_percent_display(node, parent_total); while (node) { struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); @@ -863,7 +877,7 @@ static int hist_browser__show_callchain_graph(struct hist_browser *browser, percent_total = parent_total; node = rb_first(root); - need_percent = node && rb_next(node); + need_percent = check_percent_display(node, parent_total); while (node) { struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); -- cgit From 3848c23b19e07188bfa15e3d9a2ac27692f2ff3c Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Thu, 28 Jan 2016 21:24:54 +0900 Subject: perf report: Don't show blank lines if entry has no callchain When all callchains of a hist entry is percent-limited, do not add a blank line at the end. It makes the entry look like it doesn't have callchains. Reported-and-Tested-by: Jiri Olsa Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Frederic Weisbecker Cc: Peter Zijlstra Cc: Wang Nan Link: http://lkml.kernel.org/r/20160128122454.GA27446@danjae.kornet Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/stdio/hist.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 76ff46becac8..691e52ce7510 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -233,7 +233,10 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root, ret += __callchain__fprintf_graph(fp, root, total_samples, 1, 1, left_margin); - ret += fprintf(fp, "\n"); + if (ret) { + /* do not add a blank line if it printed nothing */ + ret += fprintf(fp, "\n"); + } return ret; } -- cgit From bb2bb45d1be28987e6cb50f50e4819795537ab83 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 1 Feb 2016 21:09:14 +0000 Subject: regmap: Return an error if a caller attempts to do an unsupported raw read regmaps without raw I/O access can't implement raw I/O operations, return an error if someone tries to do that rather than crashing. Signed-off-by: Mark Brown --- drivers/base/regmap/regmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 343263449aff..e2f68807d970 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2255,6 +2255,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, WARN_ON(!map->bus); + if (!map->bus || !map->bus->read) + return -EINVAL; + range = _regmap_range_lookup(map, reg); if (range) { ret = _regmap_select_page(map, ®, range, -- cgit From 6f68b002715460c7552e8688b6f289659d5f8046 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 6 Sep 2015 21:38:49 +0200 Subject: batman-adv: Fix kerneldoc parsing of structs/enums Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/multicast.h | 2 +- net/batman-adv/packet.h | 8 ++++---- net/batman-adv/types.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h index 8f3cb04b9f13..685219f3fec9 100644 --- a/net/batman-adv/multicast.h +++ b/net/batman-adv/multicast.h @@ -23,7 +23,7 @@ struct sk_buff; /** - * batadv_forw_mode - the way a packet should be forwarded as + * enum batadv_forw_mode - the way a packet should be forwarded as * @BATADV_FORW_ALL: forward the packet to all nodes (currently via classic * flooding) * @BATADV_FORW_SINGLE: forward the packet to a single node (currently via the diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 0558e3237e0e..e80a8fc9f49e 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -158,7 +158,7 @@ enum batadv_tt_client_flags { }; /** - * batadv_vlan_flags - flags for the four MSB of any vlan ID field + * enum batadv_vlan_flags - flags for the four MSB of any vlan ID field * @BATADV_VLAN_HAS_TAG: whether the field contains a valid vlan tag or not */ enum batadv_vlan_flags { @@ -230,7 +230,7 @@ struct batadv_ogm_packet { #define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet) /** - * batadv_icmp_header - common members among all the ICMP packets + * struct batadv_icmp_header - common members among all the ICMP packets * @packet_type: batman-adv packet type, part of the general header * @version: batman-adv protocol version, part of the genereal header * @ttl: time to live for this packet, part of the genereal header @@ -256,7 +256,7 @@ struct batadv_icmp_header { }; /** - * batadv_icmp_packet - ICMP packet + * struct batadv_icmp_packet - ICMP packet * @packet_type: batman-adv packet type, part of the general header * @version: batman-adv protocol version, part of the genereal header * @ttl: time to live for this packet, part of the genereal header @@ -282,7 +282,7 @@ struct batadv_icmp_packet { #define BATADV_RR_LEN 16 /** - * batadv_icmp_packet_rr - ICMP RouteRecord packet + * struct batadv_icmp_packet_rr - ICMP RouteRecord packet * @packet_type: batman-adv packet type, part of the general header * @version: batman-adv protocol version, part of the genereal header * @ttl: time to live for this packet, part of the genereal header diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 3437b667a2cd..8c3dda36d9ec 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -346,7 +346,7 @@ struct batadv_gw_node { }; /** - * batadv_hardif_neigh_node - unique neighbor per hard interface + * struct batadv_hardif_neigh_node - unique neighbor per hard interface * @list: list node for batadv_hard_iface::neigh_list * @addr: the MAC address of the neighboring interface * @if_incoming: pointer to incoming hard interface -- cgit From 42ea22fe2c5da2ebd7123518a1b2cd7597ebffd7 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 6 Sep 2015 21:38:50 +0200 Subject: batman-adv: Remove kerneldoc for missing parameters Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/fragmentation.c | 1 - net/batman-adv/packet.h | 1 - net/batman-adv/routing.c | 1 - net/batman-adv/translation-table.c | 4 ---- 4 files changed, 7 deletions(-) diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 20d9282f895b..fedddbe0cd28 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -242,7 +242,6 @@ err: /** * batadv_frag_merge_packets - merge a chain of fragments * @chain: head of chain with fragments - * @skb: packet with total size of skb after merging * * Expand the first skb in the chain and copy the content of the remaining * skb's into the expanded one. After doing so, clear the chain. diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index e80a8fc9f49e..6d5b17841ff5 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -413,7 +413,6 @@ struct batadv_bcast_packet { * @packet_type: batman-adv packet type, part of the general header * @version: batman-adv protocol version, part of the genereal header * @ttl: time to live for this packet, part of the genereal header - * @reserved: Align following fields to 2-byte boundaries * @first_source: original source of first included packet * @first_orig_dest: original destinal of first included packet * @first_crc: checksum of first included packet diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index e4f2646d9246..54d660806c2a 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -904,7 +904,6 @@ rx_success: * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets * @skb: unicast tvlv packet to process * @recv_if: pointer to interface this packet was received on - * @dst_addr: the payload destination * * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP * otherwise. diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index cdfc85fa2743..3ccede59c842 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -217,7 +217,6 @@ batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) /** * batadv_tt_global_hash_count - count the number of orig entries - * @hash: hash table containing the tt entries * @addr: the mac address of the client to count entries for * @vid: VLAN identifier * @@ -288,7 +287,6 @@ static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv, /** * batadv_tt_global_size_mod - change the size by v of the local table * identified by vid - * @bat_priv: the bat priv with all the soft interface information * @vid: the VLAN identifier * @v: the amount to sum to the global table size */ @@ -2406,7 +2404,6 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, * @orig_node: originator for which the CRCs have to be checked * @tt_vlan: pointer to the first tvlv VLAN entry * @num_vlan: number of tvlv VLAN entries - * @create: if true, create VLAN objects if not found * * Return true if all the received CRCs match the locally stored ones, false * otherwise @@ -3375,7 +3372,6 @@ out: * @tt_change: pointer to the first entry in the TT buffer * @tt_num_changes: number of tt changes inside the tt buffer * @ttvn: translation table version number of this changeset - * @tt_crc: crc32 checksum of orig node's translation table */ static void batadv_tt_update_orig(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, -- cgit From e51f0397ded5bcbc2dd1694bc3d6f24cb2d42fa5 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 6 Sep 2015 21:38:51 +0200 Subject: batman-adv: Fix names in kerneldoc of functions Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/originator.c | 4 ++-- net/batman-adv/packet.h | 2 +- net/batman-adv/send.c | 2 +- net/batman-adv/soft-interface.c | 2 +- net/batman-adv/translation-table.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index fe578f75c391..dfeebc89ed9a 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -375,7 +375,7 @@ out: /** * batadv_neigh_ifinfo_get - find the ifinfo from an neigh_node - * @neigh_node: the neigh node to be queried + * @neigh: the neigh node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * * The object is returned with refcounter increased by 1. @@ -408,7 +408,7 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, /** * batadv_neigh_ifinfo_new - search and possibly create an neigh_ifinfo object - * @neigh_node: the neigh node to be queried + * @neigh: the neigh node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * * Returns NULL in case of failure or the neigh_ifinfo object for the diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 6d5b17841ff5..72fd5b0a4183 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -494,7 +494,7 @@ struct batadv_tvlv_gateway_data { * struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container * @flags: translation table flags (see batadv_tt_data_flags) * @ttvn: translation table version number - * @vlan_num: number of announced VLANs. In the TVLV this struct is followed by + * @num_vlan: number of announced VLANs. In the TVLV this struct is followed by * one batadv_tvlv_tt_vlan_data object per announced vlan */ struct batadv_tvlv_tt_data { diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 782fa33ec296..3fbf7910c4d1 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -211,7 +211,7 @@ static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb, * unicast 4addr header * @bat_priv: the bat priv with all the soft interface information * @skb: the skb containing the payload to encapsulate - * @orig_node: the destination node + * @orig: the destination node * @packet_subtype: the unicast 4addr packet subtype to use * * Returns false if the payload could not be encapsulated or true otherwise. diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index ac4d08de5df4..c923e3c7b6ac 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -480,7 +480,7 @@ out: /** * batadv_softif_vlan_free_ref - decrease the vlan object refcounter and * possibly free it - * @softif_vlan: the vlan object to release + * @vlan: the vlan object to release */ void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) { diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 3ccede59c842..7d8fc90c9e38 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -3366,8 +3366,8 @@ out: * batadv_tt_update_orig - update global translation table with new tt * information received via ogms * @bat_priv: the bat priv with all the soft interface information - * @orig: the orig_node of the ogm - * @tt_vlan: pointer to the first tvlv VLAN entry + * @orig_node: the orig_node of the ogm + * @tt_buff: pointer to the first tvlv VLAN entry * @tt_num_vlan: number of tvlv VLAN entries * @tt_change: pointer to the first entry in the TT buffer * @tt_num_changes: number of tt changes inside the tt buffer -- cgit From f34ac9d4ec1fcb02fc70aad8d1ce0c0641a90b12 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 6 Sep 2015 21:38:53 +0200 Subject: batman-adv: Drop invalid kerneldoc for variable batadv_vlan_attrs Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/sysfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index fe87777fda8a..33772d9bd613 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -620,9 +620,7 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { BATADV_ATTR_VLAN_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); -/** - * batadv_vlan_attrs - array of vlan specific sysfs attributes - */ +/* array of vlan specific sysfs attributes */ static struct batadv_attribute *batadv_vlan_attrs[] = { &batadv_attr_vlan_ap_isolation, NULL, -- cgit From d1f6825067b9c167b3853c9af67e68d5412c2c63 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sat, 15 Aug 2015 18:04:59 +0800 Subject: batman-adv: kernel doc readability updates Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/types.h | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 8c3dda36d9ec..7f7a0f1eaf75 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -73,7 +73,7 @@ enum batadv_dhcp_recipient { #define BATADV_TT_SYNC_MASK 0x00F0 /** - * struct batadv_hard_iface_bat_iv - per hard interface B.A.T.M.A.N. IV data + * struct batadv_hard_iface_bat_iv - per hard-interface B.A.T.M.A.N. IV data * @ogm_buff: buffer holding the OGM packet * @ogm_buff_len: length of the OGM packet buffer * @ogm_seqno: OGM sequence number - used to identify each OGM @@ -97,8 +97,8 @@ struct batadv_hard_iface_bat_iv { * batman-adv for this interface * @soft_iface: the batman-adv interface which uses this network interface * @rcu: struct used for freeing in an RCU-safe manner - * @bat_iv: BATMAN IV specific per hard interface data - * @cleanup_work: work queue callback item for hard interface deinit + * @bat_iv: per hard-interface B.A.T.M.A.N. IV data + * @cleanup_work: work queue callback item for hard-interface deinit * @debug_dir: dentry for nc subdir in batman-adv directory in debugfs * @neigh_list: list of unique single hop neighbors via this interface * @neigh_list_lock: lock protecting neigh_list @@ -125,7 +125,7 @@ struct batadv_hard_iface { /** * struct batadv_orig_ifinfo - originator info per outgoing interface * @list: list node for orig_node::ifinfo_list - * @if_outgoing: pointer to outgoing hard interface + * @if_outgoing: pointer to outgoing hard-interface * @router: router that should be used to reach this originator * @last_real_seqno: last and best known sequence number * @last_ttl: ttl of last received packet @@ -202,7 +202,7 @@ struct batadv_orig_node_vlan { /** * struct batadv_orig_bat_iv - B.A.T.M.A.N. IV private orig_node members - * @bcast_own: set of bitfields (one per hard interface) where each one counts + * @bcast_own: set of bitfields (one per hard-interface) where each one counts * the number of our OGMs this orig_node rebroadcasted "back" to us (relative * to last_real_seqno). Every bitfield is BATADV_TQ_LOCAL_WINDOW_SIZE bits long. * @bcast_own_sum: sum of bcast_own @@ -346,10 +346,11 @@ struct batadv_gw_node { }; /** - * struct batadv_hardif_neigh_node - unique neighbor per hard interface + * struct batadv_hardif_neigh_node - unique neighbor per hard-interface * @list: list node for batadv_hard_iface::neigh_list * @addr: the MAC address of the neighboring interface - * @if_incoming: pointer to incoming hard interface + * @if_incoming: pointer to incoming hard-interface + * @last_seen: when last packet via this neighbor was received * @refcount: number of contexts the object is used * @rcu: struct used for freeing in a RCU-safe manner */ @@ -369,7 +370,7 @@ struct batadv_hardif_neigh_node { * @addr: the MAC address of the neighboring interface * @ifinfo_list: list for routing metrics per outgoing interface * @ifinfo_lock: lock protecting private ifinfo members and list - * @if_incoming: pointer to incoming hard interface + * @if_incoming: pointer to incoming hard-interface * @last_seen: when last packet via this neighbor was received * @refcount: number of contexts the object is used * @rcu: struct used for freeing in an RCU-safe manner @@ -388,7 +389,7 @@ struct batadv_neigh_node { /** * struct batadv_neigh_ifinfo_bat_iv - neighbor information per outgoing - * interface for BATMAN IV + * interface for B.A.T.M.A.N. IV * @tq_recv: ring buffer of received TQ values from this neigh node * @tq_index: ring buffer index * @tq_avg: averaged tq of all tq values in the ring buffer (tq_recv) @@ -407,7 +408,7 @@ struct batadv_neigh_ifinfo_bat_iv { /** * struct batadv_neigh_ifinfo - neighbor information per outgoing interface * @list: list node for batadv_neigh_node::ifinfo_list - * @if_outgoing: pointer to outgoing hard interface + * @if_outgoing: pointer to outgoing hard-interface * @bat_iv: B.A.T.M.A.N. IV private structure * @last_ttl: last received ttl from this neigh node * @refcount: number of contexts the object is used @@ -783,8 +784,8 @@ struct batadv_softif_vlan { * @forw_bat_list_lock: lock protecting forw_bat_list * @forw_bcast_list_lock: lock protecting forw_bcast_list * @orig_work: work queue callback item for orig node purging - * @cleanup_work: work queue callback item for soft interface deinit - * @primary_if: one of the hard interfaces assigned to this mesh interface + * @cleanup_work: work queue callback item for soft-interface deinit + * @primary_if: one of the hard-interfaces assigned to this mesh interface * becomes the primary interface * @bat_algo_ops: routing algorithm used by this mesh interface * @softif_vlan_list: a list of softif_vlan structs, one per VLAN created on top -- cgit From 62fe710f6e2fdf4c337763bc0774cb3232fa2139 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 15 Sep 2015 19:00:48 +0200 Subject: batman-adv: Fix kerneldoc parsing of return description Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bat_iv_ogm.c | 18 +++---- net/batman-adv/bitarray.c | 2 +- net/batman-adv/bitarray.h | 11 +++-- net/batman-adv/bridge_loop_avoidance.c | 68 ++++++++++++++++++-------- net/batman-adv/distributed-arp-table.c | 37 +++++++------- net/batman-adv/fragmentation.c | 17 ++++--- net/batman-adv/fragmentation.h | 2 +- net/batman-adv/gateway_client.c | 14 +++--- net/batman-adv/gateway_common.c | 2 +- net/batman-adv/hard-interface.c | 7 +-- net/batman-adv/hash.h | 22 +++++---- net/batman-adv/main.c | 26 +++++----- net/batman-adv/main.h | 13 +++-- net/batman-adv/multicast.c | 35 +++++++------- net/batman-adv/network-coding.c | 42 ++++++++-------- net/batman-adv/originator.c | 48 +++++++++++-------- net/batman-adv/routing.c | 30 +++++++----- net/batman-adv/send.c | 24 +++++----- net/batman-adv/send.h | 4 +- net/batman-adv/soft-interface.c | 14 +++--- net/batman-adv/sysfs.c | 10 ++-- net/batman-adv/translation-table.c | 88 ++++++++++++++++++++-------------- 22 files changed, 305 insertions(+), 229 deletions(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index df625de55ef2..a6d389b0563c 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -88,7 +88,7 @@ static void batadv_ring_buffer_set(u8 lq_recv[], u8 *lq_index, u8 value) * in the given ring buffer * @lq_recv: pointer to the ring buffer * - * Returns computed average value. + * Return: computed average value. */ static u8 batadv_ring_buffer_avg(const u8 lq_recv[]) { @@ -132,7 +132,7 @@ static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node) * @orig_node: the orig_node that has to be changed * @max_if_num: the current amount of interfaces * - * Returns 0 on success, a negative error code otherwise. + * Return: 0 on success, a negative error code otherwise. */ static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node, int max_if_num) @@ -180,7 +180,7 @@ unlock: * @max_if_num: the current amount of interfaces * @del_if_num: the index of the interface being removed * - * Returns 0 on success, a negative error code otherwise. + * Return: 0 on success, a negative error code otherwise. */ static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node, int max_if_num, int del_if_num) @@ -246,7 +246,7 @@ unlock: * @bat_priv: the bat priv with all the soft interface information * @addr: mac address of the originator * - * Returns the originator object corresponding to the passed mac address or NULL + * Return: the originator object corresponding to the passed mac address or NULL * on failure. * If the object does not exists it is created an initialised. */ @@ -522,7 +522,7 @@ out: * @if_outgoing: interface for which the retransmission should be considered * @forw_packet: the forwarded packet which should be checked * - * Returns true if new_packet can be aggregated with forw_packet + * Return: true if new_packet can be aggregated with forw_packet */ static bool batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, @@ -1125,7 +1125,7 @@ out: * @if_incoming: interface where the packet was received * @if_outgoing: interface for which the retransmission should be considered * - * Returns 1 if the link can be considered bidirectional, 0 otherwise + * Return: 1 if the link can be considered bidirectional, 0 otherwise */ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, struct batadv_orig_node *orig_neigh_node, @@ -1269,7 +1269,7 @@ out: * @if_incoming: interface on which the OGM packet was received * @if_outgoing: interface for which the retransmission should be considered * - * Returns duplicate status as enum batadv_dup_status + * Return: duplicate status as enum batadv_dup_status */ static enum batadv_dup_status batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, @@ -1929,7 +1929,7 @@ static void batadv_iv_neigh_print(struct batadv_priv *bat_priv, * @neigh2: the second neighbor object of the comparison * @if_outgoing2: outgoing interface for the second neighbor * - * Returns a value less, equal to or greater than 0 if the metric via neigh1 is + * Return: a value less, equal to or greater than 0 if the metric via neigh1 is * lower, the same as or higher than the metric via neigh2 */ static int batadv_iv_ogm_neigh_cmp(struct batadv_neigh_node *neigh1, @@ -1970,7 +1970,7 @@ out: * @neigh2: the second neighbor object of the comparison * @if_outgoing2: outgoing interface for the second neighbor * - * Returns true if the metric via neigh1 is equally good or better than + * Return: true if the metric via neigh1 is equally good or better than * the metric via neigh2, false otherwise. */ static bool diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index 25cbc36e997a..06bab5179bf9 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c @@ -31,7 +31,7 @@ static void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n) /* receive and process one packet within the sequence number window. * - * returns: + * Return: * 1 if the window was moved (either new or very old) * 0 if the window was not moved/shifted. */ diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index 0226b220fe5b..cf2aeb0831a4 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h @@ -24,7 +24,10 @@ #include #include -/* Returns 1 if the corresponding bit in the given seq_bits indicates true +/** + * batadv_test_bit + * + * Return: 1 if the corresponding bit in the given seq_bits indicates true * and curr_seqno is within range of last_seqno. Otherwise returns 0. */ static inline int batadv_test_bit(const unsigned long *seq_bits, @@ -48,8 +51,10 @@ static inline void batadv_set_bit(unsigned long *seq_bits, s32 n) set_bit(n, seq_bits); /* turn the position on */ } -/* receive and process one packet, returns 1 if received seq_num is considered - * new, 0 if old +/** + * batadv_bit_get_packet - receive and process one packet + * + * Return: 1 if received seq_num is considered new, 0 if old */ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff, int set_mark); diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index c24c481b666f..90c79948979c 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -58,7 +58,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, struct batadv_bla_backbone_gw *backbone_gw); -/* return the index of the claim */ +/** + * batadv_choose_claim + * + * Return: the index of the claim + */ static inline u32 batadv_choose_claim(const void *data, u32 size) { struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data; @@ -70,7 +74,11 @@ static inline u32 batadv_choose_claim(const void *data, u32 size) return hash % size; } -/* return the index of the backbone gateway */ +/** + * batadv_choose_backbone_gw + * + * Return: the index of the backbone gateway + */ static inline u32 batadv_choose_backbone_gw(const void *data, u32 size) { const struct batadv_bla_claim *claim = (struct batadv_bla_claim *)data; @@ -145,8 +153,9 @@ static void batadv_claim_free_ref(struct batadv_bla_claim *claim) * @bat_priv: the bat priv with all the soft interface information * @data: search data (may be local/static data) * - * looks for a claim in the hash, and returns it if found - * or NULL otherwise. + * looks for a claim in the hash + * + * Return: claim if found or NULL otherwise. */ static struct batadv_bla_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv, @@ -186,7 +195,7 @@ static struct batadv_bla_claim * @addr: the address of the originator * @vid: the VLAN ID * - * Returns claim if found or NULL otherwise. + * Return: claim if found or NULL otherwise. */ static struct batadv_bla_backbone_gw * batadv_backbone_hash_find(struct batadv_priv *bat_priv, u8 *addr, @@ -666,7 +675,11 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, batadv_claim_free_ref(claim); } -/* check for ANNOUNCE frame, return 1 if handled */ +/** + * batadv_handle_announce - check for ANNOUNCE frame + * + * Return: 1 if handled + */ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr, u8 *backbone_addr, unsigned short vid) { @@ -716,7 +729,11 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr, return 1; } -/* check for REQUEST frame, return 1 if handled */ +/** + * batadv_handle_request - check for REQUEST frame + * + * Return: 1 if handled + */ static int batadv_handle_request(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, u8 *backbone_addr, struct ethhdr *ethhdr, @@ -740,7 +757,11 @@ static int batadv_handle_request(struct batadv_priv *bat_priv, return 1; } -/* check for UNCLAIM frame, return 1 if handled */ +/** + * batadv_handle_unclaim - check for UNCLAIM frame + * + * Return: 1 if handled + */ static int batadv_handle_unclaim(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, u8 *backbone_addr, u8 *claim_addr, @@ -769,7 +790,11 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv, return 1; } -/* check for CLAIM frame, return 1 if handled */ +/** + * batadv_handle_claim - check for CLAIM frame + * + * Return: 1 if handled + */ static int batadv_handle_claim(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, u8 *backbone_addr, u8 *claim_addr, @@ -809,7 +834,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, * This function also applies the group ID of the sender * if it is in the same mesh. * - * returns: + * Return: * 2 - if it is a claim packet and on the same group * 1 - if is a claim packet from another group * 0 - if it is not a claim packet @@ -880,7 +905,7 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv, * * Check if this is a claim frame, and process it accordingly. * - * returns 1 if it was a claim frame, otherwise return 0 to + * Return: 1 if it was a claim frame, otherwise return 0 to * tell the callee that it can use the frame on its own. */ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, @@ -1397,7 +1422,7 @@ out: * * Check if the originator is a gateway for the VLAN identified by vid. * - * Returns true if orig is a backbone for this vid, false otherwise. + * Return: true if orig is a backbone for this vid, false otherwise. */ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig, unsigned short vid) @@ -1436,9 +1461,10 @@ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig, * @orig_node: the orig_node of the frame * @hdr_size: maximum length of the frame * - * bla_is_backbone_gw inspects the skb for the VLAN ID and returns 1 - * if the orig_node is also a gateway on the soft interface, otherwise it - * returns 0. + * bla_is_backbone_gw inspects the skb for the VLAN ID + * + * Return: 1 if the orig_node is also a gateway on the soft interface, otherwise + * it returns 0. */ int batadv_bla_is_backbone_gw(struct sk_buff *skb, struct batadv_orig_node *orig_node, int hdr_size) @@ -1498,8 +1524,9 @@ void batadv_bla_free(struct batadv_priv *bat_priv) * * we have to race for a claim * * if the frame is allowed on the LAN * - * in these cases, the skb is further handled by this function and - * returns 1, otherwise it returns 0 and the caller shall further + * in these cases, the skb is further handled by this function + * + * Return: 1 if handled, otherwise it returns 0 and the caller shall further * process the skb. */ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, @@ -1592,11 +1619,12 @@ out: * * a claim was received which has to be processed * * the frame is allowed on the mesh * - * in these cases, the skb is further handled by this function and - * returns 1, otherwise it returns 0 and the caller shall further - * process the skb. + * in these cases, the skb is further handled by this function. * * This call might reallocate skb data. + * + * Return: 1 if handled, otherwise it returns 0 and the caller shall further + * process the skb. */ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, unsigned short vid) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index a49c705fb86b..2f13429ce5d3 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -76,7 +76,7 @@ static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry) * batadv_dat_to_purge - check whether a dat_entry has to be purged or not * @dat_entry: the entry to check * - * Returns true if the entry has to be purged now, false otherwise. + * Return: true if the entry has to be purged now, false otherwise. */ static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry) { @@ -151,7 +151,7 @@ static void batadv_dat_purge(struct work_struct *work) * @node: node in the local table * @data2: second object to compare the node to * - * Returns 1 if the two entries are the same, 0 otherwise. + * Return: 1 if the two entries are the same, 0 otherwise. */ static int batadv_compare_dat(const struct hlist_node *node, const void *data2) { @@ -166,7 +166,7 @@ static int batadv_compare_dat(const struct hlist_node *node, const void *data2) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the hw_src field in the ARP packet. + * Return: the value of the hw_src field in the ARP packet. */ static u8 *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) { @@ -183,7 +183,7 @@ static u8 *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the ip_src field in the ARP packet. + * Return: the value of the ip_src field in the ARP packet. */ static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) { @@ -195,7 +195,7 @@ static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the hw_dst field in the ARP packet. + * Return: the value of the hw_dst field in the ARP packet. */ static u8 *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) { @@ -207,7 +207,7 @@ static u8 *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size) * @skb: ARP packet * @hdr_size: size of the possible header before the ARP packet * - * Returns the value of the ip_dst field in the ARP packet. + * Return: the value of the ip_dst field in the ARP packet. */ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) { @@ -219,7 +219,7 @@ static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size) * @data: data to hash * @size: size of the hash table * - * Returns the selected index in the hash table for the given data. + * Return: the selected index in the hash table for the given data. */ static u32 batadv_hash_dat(const void *data, u32 size) { @@ -256,7 +256,7 @@ static u32 batadv_hash_dat(const void *data, u32 size) * @ip: search key * @vid: VLAN identifier * - * Returns the dat_entry if found, NULL otherwise. + * Return: the dat_entry if found, NULL otherwise. */ static struct batadv_dat_entry * batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip, @@ -440,7 +440,7 @@ static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb, * @candidate: orig_node under evaluation * @max_orig_node: last selected candidate * - * Returns true if the node has been elected as next candidate or false + * Return: true if the node has been elected as next candidate or false * otherwise. */ static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res, @@ -558,7 +558,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, * closest values (from the LEFT, with wrap around if needed) then the hash * value of the key. ip_dst is the key. * - * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM. + * Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM. */ static struct batadv_dat_candidate * batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) @@ -602,7 +602,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) * This function copies the skb with pskb_copy() and is sent as unicast packet * to each of the selected candidates. * - * Returns true if the packet is sent to at least one candidate, false + * Return: true if the packet is sent to at least one candidate, false * otherwise. */ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, @@ -831,7 +831,7 @@ out: * @skb: packet to analyse * @hdr_size: size of the possible header before the ARP packet in the skb * - * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise. + * Return: the ARP type if the skb contains a valid ARP packet, 0 otherwise. */ static u16 batadv_arp_get_type(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) @@ -904,8 +904,9 @@ out: * @skb: the buffer containing the packet to extract the VID from * @hdr_size: the size of the batman-adv header encapsulating the packet * - * If the packet embedded in the skb is vlan tagged this function returns the - * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned. + * Return: If the packet embedded in the skb is vlan tagged this function + * returns the VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS + * is returned. */ static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size) { @@ -930,7 +931,7 @@ static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size) * @bat_priv: the bat priv with all the soft interface information * @skb: packet to check * - * Returns true if the message has been sent to the dht candidates, false + * Return: true if the message has been sent to the dht candidates, false * otherwise. In case of a positive return value the message has to be enqueued * to permit the fallback. */ @@ -1020,7 +1021,7 @@ out: * @skb: packet to check * @hdr_size: size of the encapsulation header * - * Returns true if the request has been answered, false otherwise. + * Return: true if the request has been answered, false otherwise. */ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) @@ -1143,7 +1144,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, * @skb: packet to check * @hdr_size: size of the encapsulation header * - * Returns true if the packet was snooped and consumed by DAT. False if the + * Return: true if the packet was snooped and consumed by DAT. False if the * packet has to be delivered to the interface */ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, @@ -1200,7 +1201,7 @@ out: * @bat_priv: the bat priv with all the soft interface information * @forw_packet: the broadcast packet * - * Returns true if the node can drop the packet, false otherwise. + * Return: true if the node can drop the packet, false otherwise. */ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv, struct batadv_forw_packet *forw_packet) diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index fedddbe0cd28..80eddf44a827 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -85,7 +85,7 @@ void batadv_frag_purge_orig(struct batadv_orig_node *orig_node, /** * batadv_frag_size_limit - maximum possible size of packet to be fragmented * - * Returns the maximum size of payload that can be fragmented. + * Return: the maximum size of payload that can be fragmented. */ static int batadv_frag_size_limit(void) { @@ -107,7 +107,7 @@ static int batadv_frag_size_limit(void) * * Caller must hold chain->lock. * - * Returns true if chain is empty and caller can just insert the new fragment + * Return: true if chain is empty and caller can just insert the new fragment * without searching for the right position. */ static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain, @@ -136,7 +136,7 @@ static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain, * Insert a new fragment into the reverse ordered chain in the right table * entry. The hash table entry is cleared if "old" fragments exist in it. * - * Returns true if skb is buffered, false on error. If the chain has all the + * Return: true if skb is buffered, false on error. If the chain has all the * fragments needed to merge the packet, the chain is moved to the passed head * to avoid locking the chain in the table. */ @@ -246,7 +246,7 @@ err: * Expand the first skb in the chain and copy the content of the remaining * skb's into the expanded one. After doing so, clear the chain. * - * Returns the merged skb or NULL on error. + * Return: the merged skb or NULL on error. */ static struct sk_buff * batadv_frag_merge_packets(struct hlist_head *chain) @@ -306,6 +306,9 @@ free: * There are three possible outcomes: 1) Packet is merged: Return true and * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb * to NULL; 3) Error: Return false and leave skb as is. + * + * Return: true when packet is merged or buffered, false when skb is not not + * used. */ bool batadv_frag_skb_buffer(struct sk_buff **skb, struct batadv_orig_node *orig_node_src) @@ -343,7 +346,7 @@ out_err: * will exceed the MTU towards the next-hop. If so, the fragment is forwarded * without merging it. * - * Returns true if the fragment is consumed/forwarded, false otherwise. + * Return: true if the fragment is consumed/forwarded, false otherwise. */ bool batadv_frag_skb_fwd(struct sk_buff *skb, struct batadv_hard_iface *recv_if, @@ -398,7 +401,7 @@ out: * passed mtu and the old one with the rest. The new skb contains data from the * tail of the old skb. * - * Returns the new fragment, NULL on error. + * Return: the new fragment, NULL on error. */ static struct sk_buff *batadv_frag_create(struct sk_buff *skb, struct batadv_frag_packet *frag_head, @@ -432,7 +435,7 @@ err: * @orig_node: final destination of the created fragments * @neigh_node: next-hop of the created fragments * - * Returns true on success, false otherwise. + * Return: true on success, false otherwise. */ bool batadv_frag_send_packet(struct sk_buff *skb, struct batadv_orig_node *orig_node, diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h index 8b9877e70b95..c5476fe79dc6 100644 --- a/net/batman-adv/fragmentation.h +++ b/net/batman-adv/fragmentation.h @@ -42,7 +42,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb, * batadv_frag_check_entry - check if a list of fragments has timed out * @frags_entry: table entry to check * - * Returns true if the frags entry has timed out, false otherwise. + * Return: true if the frags entry has timed out, false otherwise. */ static inline bool batadv_frag_check_entry(struct batadv_frag_table_entry *frags_entry) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index e6c8382c79ba..83507750bb66 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -456,7 +456,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @orig_node: originator announcing gateway capabilities * - * Returns gateway node if found or NULL otherwise. + * Return: gateway node if found or NULL otherwise. */ static struct batadv_gw_node * batadv_gw_node_get(struct batadv_priv *bat_priv, @@ -655,13 +655,13 @@ out: * @chaddr: buffer where the client address will be stored. Valid * only if the function returns BATADV_DHCP_TO_CLIENT * - * Returns: + * This function may re-allocate the data buffer of the skb passed as argument. + * + * Return: * - BATADV_DHCP_NO if the packet is not a dhcp message or if there was an error * while parsing it * - BATADV_DHCP_TO_SERVER if this is a message going to the DHCP server * - BATADV_DHCP_TO_CLIENT if this is a message going to a DHCP client - * - * This function may re-allocate the data buffer of the skb passed as argument. */ enum batadv_dhcp_recipient batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, @@ -776,11 +776,11 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, * server. Due to topology changes it may be the case that the GW server * previously selected is not the best one anymore. * - * Returns true if the packet destination is unicast and it is not the best gw, - * false otherwise. - * * This call might reallocate skb data. * Must be invoked only when the DHCP packet is going TO a DHCP SERVER. + * + * Return: true if the packet destination is unicast and it is not the best gw, + * false otherwise. */ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct sk_buff *skb) diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index b51bface8bdd..b287448b9921 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c @@ -38,7 +38,7 @@ * @description: text shown when throughput string cannot be parsed * @throughput: pointer holding the returned throughput information * - * Returns false on parse error and true otherwise. + * Return: false on parse error and true otherwise. */ static bool batadv_parse_throughput(struct net_device *net_dev, char *buff, const char *description, u32 *throughput) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 01acccc4d218..49e05d238667 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -85,7 +85,7 @@ out: * This function recursively checks all the fathers of the device passed as * argument looking for a batman-adv soft interface. * - * Returns true if the device is descendant of a batman-adv mesh interface (or + * Return: true if the device is descendant of a batman-adv mesh interface (or * if it is a batman-adv interface itself), false otherwise */ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) @@ -136,7 +136,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev) * interface * @net_device: the device to check * - * Returns true if the net device is a 802.11 wireless device, false otherwise. + * Return: true if the net device is a 802.11 wireless device, false otherwise. */ bool batadv_is_wifi_netdev(struct net_device *net_device) { @@ -401,7 +401,8 @@ batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface) * * Invoke ndo_del_slave on master passing slave as argument. In this way slave * is free'd and master can correctly change its internal state. - * Return 0 on success, a negative value representing the error otherwise + * + * Return: 0 on success, a negative value representing the error otherwise */ static int batadv_master_del_slave(struct batadv_hard_iface *slave, struct net_device *master) diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index 377626250ac7..071a87ea4f2f 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h @@ -30,14 +30,17 @@ struct lock_class_key; /* callback to a compare function. should compare 2 element datas for their - * keys, return 0 if same and not 0 if not same + * keys + * + * Return: 0 if same and not 0 if not same */ typedef int (*batadv_hashdata_compare_cb)(const struct hlist_node *, const void *); -/* the hashfunction, should return an index - * based on the key in the data of the first - * argument and the size the second +/* the hashfunction + * + * Return: an index based on the key in the data of the first argument and the + * size the second */ typedef u32 (*batadv_hashdata_choose_cb)(const void *, u32); typedef void (*batadv_hashdata_free_cb)(struct hlist_node *, void *); @@ -96,7 +99,7 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash, * @data: data passed to the aforementioned callbacks as argument * @data_node: to be added element * - * Returns 0 on success, 1 if the element already is in the hash + * Return: 0 on success, 1 if the element already is in the hash * and -1 on error. */ static inline int batadv_hash_add(struct batadv_hashtable *hash, @@ -139,10 +142,11 @@ out: return ret; } -/* removes data from hash, if found. returns pointer do data on success, so you - * can remove the used structure yourself, or NULL on error . data could be the - * structure you use with just the key filled, we just need the key for - * comparing. +/* removes data from hash, if found. data could be the structure you use with + * just the key filled, we just need the key for comparing. + * + * Return: returns pointer do data on success, so you can remove the used + * structure yourself, or NULL on error */ static inline void *batadv_hash_remove(struct batadv_hashtable *hash, batadv_hashdata_compare_cb compare, diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 4b5d61fbadb1..70907f6f37ed 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -233,7 +233,7 @@ void batadv_mesh_free(struct net_device *soft_iface) * @bat_priv: the bat priv with all the soft interface information * @addr: the address to check * - * Returns 'true' if the mac address was found, false otherwise. + * Return: 'true' if the mac address was found, false otherwise. */ bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr) { @@ -262,7 +262,7 @@ bool batadv_is_my_mac(struct batadv_priv *bat_priv, const u8 *addr) * function that requires the primary interface * @seq: debugfs table seq_file struct * - * Returns primary interface if found or NULL otherwise. + * Return: primary interface if found or NULL otherwise. */ struct batadv_hard_iface * batadv_seq_print_text_primary_if_get(struct seq_file *seq) @@ -297,7 +297,7 @@ out: * batadv_max_header_len - calculate maximum encapsulation overhead for a * payload packet * - * Return the maximum encapsulation overhead in bytes. + * Return: the maximum encapsulation overhead in bytes. */ int batadv_max_header_len(void) { @@ -640,7 +640,7 @@ batadv_tvlv_handler_free_ref(struct batadv_tvlv_handler *tvlv_handler) * @type: tvlv handler type to look for * @version: tvlv handler version to look for * - * Returns tvlv handler if found or NULL otherwise. + * Return: tvlv handler if found or NULL otherwise. */ static struct batadv_tvlv_handler *batadv_tvlv_handler_get(struct batadv_priv *bat_priv, u8 type, u8 version) @@ -688,7 +688,7 @@ static void batadv_tvlv_container_free_ref(struct batadv_tvlv_container *tvlv) * Has to be called with the appropriate locks being acquired * (tvlv.container_list_lock). * - * Returns tvlv container if found or NULL otherwise. + * Return: tvlv container if found or NULL otherwise. */ static struct batadv_tvlv_container *batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version) @@ -720,7 +720,7 @@ static struct batadv_tvlv_container * Has to be called with the appropriate locks being acquired * (tvlv.container_list_lock). * - * Returns size of all currently registered tvlv containers in bytes. + * Return: size of all currently registered tvlv containers in bytes. */ static u16 batadv_tvlv_container_list_size(struct batadv_priv *bat_priv) { @@ -826,7 +826,7 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv, * @additional_packet_len: requested additional packet size on top of minimum * size * - * Returns true of the packet buffer could be changed to the requested size, + * Return: true of the packet buffer could be changed to the requested size, * false otherwise. */ static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff, @@ -862,7 +862,7 @@ static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff, * The ogm packet might be enlarged or shrunk depending on the current size * and the size of the to-be-appended tvlv containers. * - * Returns size of all appended tvlv containers in bytes. + * Return: size of all appended tvlv containers in bytes. */ u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, unsigned char **packet_buff, @@ -915,7 +915,7 @@ end: * @tvlv_value: tvlv content * @tvlv_value_len: tvlv content length * - * Returns success if handler was not found or the return value of the handler + * Return: success if handler was not found or the return value of the handler * callback. */ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, @@ -968,7 +968,7 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, * @tvlv_value: tvlv content * @tvlv_value_len: tvlv content length * - * Returns success when processing an OGM or the return value of all called + * Return: success when processing an OGM or the return value of all called * handler callbacks. */ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, @@ -1190,8 +1190,8 @@ out: * @skb: the buffer containing the packet * @header_len: length of the batman header preceding the ethernet header * - * If the packet embedded in the skb is vlan tagged this function returns the - * VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS is returned. + * Return: VID with the BATADV_VLAN_HAS_TAG flag when the packet embedded in the + * skb is vlan tagged. Otherwise BATADV_NO_FLAGS. */ unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len) { @@ -1218,7 +1218,7 @@ unsigned short batadv_get_vid(struct sk_buff *skb, size_t header_len) * @vid: the VLAN identifier for which the AP isolation attributed as to be * looked up * - * Returns true if AP isolation is on for the VLAN idenfied by vid, false + * Return: true if AP isolation is on for the VLAN idenfied by vid, false * otherwise */ bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid) diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 9dbd9107e7e1..8a48d4a40828 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -273,9 +273,12 @@ static inline void _batadv_dbg(int type __always_unused, pr_err("%s: " fmt, _netdev->name, ## arg); \ } while (0) -/* returns 1 if they are the same ethernet addr +/** + * batadv_compare_eth - Compare two not u16 aligned Ethernet addresses * * note: can't use ether_addr_equal() as it requires aligned memory + * + * Return: 1 if they are the same ethernet addr */ static inline bool batadv_compare_eth(const void *data1, const void *data2) { @@ -287,7 +290,7 @@ static inline bool batadv_compare_eth(const void *data1, const void *data2) * @timestamp: base value to compare with (in jiffies) * @timeout: added to base value before comparing (in milliseconds) * - * Returns true if current time is after timestamp + timeout + * Return: true if current time is after timestamp + timeout */ static inline bool batadv_has_timed_out(unsigned long timestamp, unsigned int timeout) @@ -326,7 +329,11 @@ static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx, #define batadv_inc_counter(b, i) batadv_add_counter(b, i, 1) -/* Sum and return the cpu-local counters for index 'idx' */ +/** + * batadv_sum_counter - Sum the cpu-local counters for index 'idx' + * + * Return: sum of all cpu-local counters + */ static inline u64 batadv_sum_counter(struct batadv_priv *bat_priv, size_t idx) { u64 *counters, sum = 0; diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 75fa5013af72..d984eee1776c 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -55,7 +55,7 @@ * Collect multicast addresses of the local multicast listeners * on the given soft interface, dev, in the given mcast_list. * - * Returns -ENOMEM on memory allocation error or the number of + * Return: -ENOMEM on memory allocation error or the number of * items added to the mcast_list otherwise. */ static int batadv_mcast_mla_softif_get(struct net_device *dev, @@ -87,7 +87,7 @@ static int batadv_mcast_mla_softif_get(struct net_device *dev, * @mcast_addr: the multicast address to check * @mcast_list: the list with multicast addresses to search in * - * Returns true if the given address is already in the given list. + * Return: true if the given address is already in the given list. * Otherwise returns false. */ static bool batadv_mcast_mla_is_duplicate(u8 *mcast_addr, @@ -195,8 +195,9 @@ static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv, * batadv_mcast_has_bridge - check whether the soft-iface is bridged * @bat_priv: the bat priv with all the soft interface information * - * Checks whether there is a bridge on top of our soft interface. Returns - * true if so, false otherwise. + * Checks whether there is a bridge on top of our soft interface. + * + * Return: true if there is a bridge, false otherwise. */ static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) { @@ -218,7 +219,7 @@ static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) * Updates the own multicast tvlv with our current multicast related settings, * capabilities and inabilities. * - * Returns true if the tvlv container is registered afterwards. Otherwise + * Return: true if the tvlv container is registered afterwards. Otherwise * returns false. */ static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) @@ -289,8 +290,8 @@ out: * Checks whether the given IPv4 packet has the potential to be forwarded with a * mode more optimal than classic flooding. * - * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM in case of - * memory allocation failure. + * Return: If so then 0. Otherwise -EINVAL or -ENOMEM in case of memory + * allocation failure. */ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, struct sk_buff *skb, @@ -327,8 +328,7 @@ static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, * Checks whether the given IPv6 packet has the potential to be forwarded with a * mode more optimal than classic flooding. * - * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out - * of memory. + * Return: If so then 0. Otherwise -EINVAL is or -ENOMEM if we are out of memory */ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, struct sk_buff *skb, @@ -366,8 +366,7 @@ static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, * Checks whether the given multicast ethernet frame has the potential to be * forwarded with a mode more optimal than classic flooding. * - * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out - * of memory. + * Return: If so then 0. Otherwise -EINVAL is or -ENOMEM if we are out of memory */ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, struct sk_buff *skb, @@ -398,7 +397,7 @@ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @ethhdr: ethernet header of a packet * - * Returns the number of nodes which want all IPv4 multicast traffic if the + * Return: the number of nodes which want all IPv4 multicast traffic if the * given ethhdr is from an IPv4 packet or the number of nodes which want all * IPv6 traffic if it matches an IPv6 packet. */ @@ -421,7 +420,7 @@ static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @ethhdr: the ether header containing the multicast destination * - * Returns an orig_node matching the multicast address provided by ethhdr + * Return: an orig_node matching the multicast address provided by ethhdr * via a translation table lookup. This increases the returned nodes refcount. */ static struct batadv_orig_node * @@ -436,7 +435,7 @@ batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv, * batadv_mcast_want_forw_ipv4_node_get - get a node with an ipv4 flag * @bat_priv: the bat priv with all the soft interface information * - * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and + * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and * increases its refcount. */ static struct batadv_orig_node * @@ -463,7 +462,7 @@ batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv) * batadv_mcast_want_forw_ipv6_node_get - get a node with an ipv6 flag * @bat_priv: the bat priv with all the soft interface information * - * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set + * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set * and increases its refcount. */ static struct batadv_orig_node * @@ -491,7 +490,7 @@ batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv) * @bat_priv: the bat priv with all the soft interface information * @ethhdr: an ethernet header to determine the protocol family from * - * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or + * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and * increases its refcount. */ @@ -514,7 +513,7 @@ batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv, * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag * @bat_priv: the bat priv with all the soft interface information * - * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag + * Return: an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag * set and increases its refcount. */ static struct batadv_orig_node * @@ -543,7 +542,7 @@ batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv) * @skb: The multicast packet to check * @orig: an originator to be set to forward the skb to * - * Returns the forwarding mode as enum batadv_forw_mode and in case of + * Return: the forwarding mode as enum batadv_forw_mode and in case of * BATADV_FORW_SINGLE set the orig to the single originator the skb * should be forwarded to. */ diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index cc63b44f0d2e..1a75d288f8a7 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -251,7 +251,7 @@ static void batadv_nc_packet_free(struct batadv_nc_packet *nc_packet) * @bat_priv: the bat priv with all the soft interface information * @nc_node: the nc node to check * - * Returns true if the entry has to be purged now, false otherwise + * Return: true if the entry has to be purged now, false otherwise */ static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv, struct batadv_nc_node *nc_node) @@ -267,7 +267,7 @@ static bool batadv_nc_to_purge_nc_node(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @nc_path: the nc path to check * - * Returns true if the entry has to be purged now, false otherwise + * Return: true if the entry has to be purged now, false otherwise */ static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv, struct batadv_nc_path *nc_path) @@ -287,7 +287,7 @@ static bool batadv_nc_to_purge_nc_path_coding(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @nc_path: the nc path to check * - * Returns true if the entry has to be purged now, false otherwise + * Return: true if the entry has to be purged now, false otherwise */ static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv, struct batadv_nc_path *nc_path) @@ -470,7 +470,7 @@ static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src, * @data: data to hash * @size: size of the hash table * - * Returns the selected index in the hash table for the given data. + * Return: the selected index in the hash table for the given data. */ static u32 batadv_nc_hash_choose(const void *data, u32 size) { @@ -489,7 +489,7 @@ static u32 batadv_nc_hash_choose(const void *data, u32 size) * @node: node in the local table * @data2: second object to compare the node to * - * Returns 1 if the two entry are the same, 0 otherwise + * Return: 1 if the two entry are the same, 0 otherwise */ static int batadv_nc_hash_compare(const struct hlist_node *node, const void *data2) @@ -516,7 +516,7 @@ static int batadv_nc_hash_compare(const struct hlist_node *node, * @hash: hash table containing the nc path * @data: search key * - * Returns the nc_path if found, NULL otherwise. + * Return: the nc_path if found, NULL otherwise. */ static struct batadv_nc_path * batadv_nc_hash_find(struct batadv_hashtable *hash, @@ -571,7 +571,7 @@ static void batadv_nc_send_packet(struct batadv_nc_packet *nc_packet) * timeout. If so, the packet is no longer kept and the entry deleted from the * queue. Has to be called with the appropriate locks. * - * Returns false as soon as the entry in the fifo queue has not been timed out + * Return: false as soon as the entry in the fifo queue has not been timed out * yet and true otherwise. */ static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv, @@ -610,7 +610,7 @@ out: * packet is no longer delayed, immediately sent and the entry deleted from the * queue. Has to be called with the appropriate locks. * - * Returns false as soon as the entry in the fifo queue has not been timed out + * Return: false as soon as the entry in the fifo queue has not been timed out * yet and true otherwise. */ static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv, @@ -731,7 +731,7 @@ static void batadv_nc_worker(struct work_struct *work) * @orig_node: neighboring orig node which may be used as nc candidate * @ogm_packet: incoming ogm packet also used for the checks * - * Returns true if: + * Return: true if: * 1) The OGM must have the most recent sequence number. * 2) The TTL must be decremented by one and only one. * 3) The OGM must be received from the first hop from orig_node. @@ -772,7 +772,7 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv, * (can be equal to orig_node) * @in_coding: traverse incoming or outgoing network coding list * - * Returns the nc_node if found, NULL otherwise. + * Return: the nc_node if found, NULL otherwise. */ static struct batadv_nc_node *batadv_nc_find_nc_node(struct batadv_orig_node *orig_node, @@ -814,7 +814,7 @@ static struct batadv_nc_node * (can be equal to orig_node) * @in_coding: traverse incoming or outgoing network coding list * - * Returns the nc_node if found or created, NULL in case of an error. + * Return: the nc_node if found or created, NULL in case of an error. */ static struct batadv_nc_node *batadv_nc_get_nc_node(struct batadv_priv *bat_priv, @@ -932,7 +932,7 @@ out: * @src: ethernet source address - first half of the nc path search key * @dst: ethernet destination address - second half of the nc path search key * - * Returns pointer to nc_path if the path was found or created, returns NULL + * Return: pointer to nc_path if the path was found or created, returns NULL * on error. */ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, @@ -1029,7 +1029,7 @@ static void batadv_nc_memxor(char *dst, const char *src, unsigned int len) * @nc_packet: structure containing the packet to the skb can be coded with * @neigh_node: next hop to forward packet to * - * Returns true if both packets are consumed, false otherwise. + * Return: true if both packets are consumed, false otherwise. */ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, struct sk_buff *skb, @@ -1228,7 +1228,7 @@ out: * Since the source encoded the packet we can be certain it has all necessary * decode information. * - * Returns true if coding of a decoded packet is allowed. + * Return: true if coding of a decoded packet is allowed. */ static bool batadv_nc_skb_coding_possible(struct sk_buff *skb, u8 *dst, u8 *src) { @@ -1246,7 +1246,7 @@ static bool batadv_nc_skb_coding_possible(struct sk_buff *skb, u8 *dst, u8 *src) * @skb: data skb to forward * @eth_dst: next hop mac address of skb * - * Returns true if coding of a decoded skb is allowed. + * Return: true if coding of a decoded skb is allowed. */ static struct batadv_nc_packet * batadv_nc_path_search(struct batadv_priv *bat_priv, @@ -1314,7 +1314,7 @@ batadv_nc_path_search(struct batadv_priv *bat_priv, * @eth_src: source mac address of skb * @in_nc_node: pointer to skb next hop's neighbor nc node * - * Returns an nc packet if a suitable coding packet was found, NULL otherwise. + * Return: an nc packet if a suitable coding packet was found, NULL otherwise. */ static struct batadv_nc_packet * batadv_nc_skb_src_search(struct batadv_priv *bat_priv, @@ -1397,7 +1397,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, * next hop that potentially sent a packet which our next hop also received * (overheard) and has stored for later decoding. * - * Returns true if the skb was consumed (encoded packet sent) or false otherwise + * Return: true if the skb was consumed (encoded packet sent) or false otherwise */ static bool batadv_nc_skb_dst_search(struct sk_buff *skb, struct batadv_neigh_node *neigh_node, @@ -1451,7 +1451,7 @@ static bool batadv_nc_skb_dst_search(struct sk_buff *skb, * @neigh_node: next hop to forward packet to * @packet_id: checksum to identify packet * - * Returns true if the packet was buffered or false in case of an error. + * Return: true if the packet was buffered or false in case of an error. */ static bool batadv_nc_skb_add_to_path(struct sk_buff *skb, struct batadv_nc_path *nc_path, @@ -1485,7 +1485,7 @@ static bool batadv_nc_skb_add_to_path(struct sk_buff *skb, * @skb: data skb to forward * @neigh_node: next hop to forward packet to * - * Returns true if the skb was consumed (encoded packet sent) or false otherwise + * Return: true if the skb was consumed (encoded packet sent) or false otherwise */ bool batadv_nc_skb_forward(struct sk_buff *skb, struct batadv_neigh_node *neigh_node) @@ -1624,7 +1624,7 @@ void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv, * @skb: unicast skb to decode * @nc_packet: decode data needed to decode the skb * - * Returns pointer to decoded unicast packet if the packet was decoded or NULL + * Return: pointer to decoded unicast packet if the packet was decoded or NULL * in case of an error. */ static struct batadv_unicast_packet * @@ -1718,7 +1718,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, * @ethhdr: pointer to the ethernet header inside the coded packet * @coded: coded packet we try to find decode data for * - * Returns pointer to nc packet if the needed data was found or NULL otherwise. + * Return: pointer to nc packet if the needed data was found or NULL otherwise. */ static struct batadv_nc_packet * batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv, diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index dfeebc89ed9a..ed1d6d7b717e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -47,7 +47,11 @@ static struct lock_class_key batadv_orig_hash_lock_class_key; static void batadv_purge_orig(struct work_struct *work); -/* returns 1 if they are the same originator */ +/** + * batadv_compare_orig + * + * Return: 1 if they are the same originator + */ int batadv_compare_orig(const struct hlist_node *node, const void *data2) { const void *data1 = container_of(node, struct batadv_orig_node, @@ -61,7 +65,7 @@ int batadv_compare_orig(const struct hlist_node *node, const void *data2) * @orig_node: the originator serving the VLAN * @vid: the VLAN identifier * - * Returns the vlan object identified by vid and belonging to orig_node or NULL + * Return: the vlan object identified by vid and belonging to orig_node or NULL * if it does not exist. */ struct batadv_orig_node_vlan * @@ -93,7 +97,7 @@ batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node, * @orig_node: the originator serving the VLAN * @vid: the VLAN identifier * - * Returns NULL in case of failure or the vlan object identified by vid and + * Return: NULL in case of failure or the vlan object identified by vid and * belonging to orig_node otherwise. The object is created and added to the list * if it does not exist. * @@ -266,7 +270,7 @@ void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) * @if_outgoing: the interface where the payload packet has been received or * the OGM should be sent to * - * Returns the neighbor which should be router for this orig_node/iface. + * Return: the neighbor which should be router for this orig_node/iface. * * The object is returned with refcounter increased by 1. */ @@ -298,7 +302,7 @@ batadv_orig_router_get(struct batadv_orig_node *orig_node, * @orig_node: the orig node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * - * Returns the requested orig_ifinfo or NULL if not found. + * Return: the requested orig_ifinfo or NULL if not found. * * The object is returned with refcounter increased by 1. */ @@ -330,7 +334,7 @@ batadv_orig_ifinfo_get(struct batadv_orig_node *orig_node, * @orig_node: the orig node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * - * Returns NULL in case of failure or the orig_ifinfo object for the if_outgoing + * Return: NULL in case of failure or the orig_ifinfo object for the if_outgoing * interface otherwise. The object is created and added to the list * if it does not exist. * @@ -380,7 +384,7 @@ out: * * The object is returned with refcounter increased by 1. * - * Returns the requested neigh_ifinfo or NULL if not found + * Return: the requested neigh_ifinfo or NULL if not found */ struct batadv_neigh_ifinfo * batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, @@ -411,7 +415,7 @@ batadv_neigh_ifinfo_get(struct batadv_neigh_node *neigh, * @neigh: the neigh node to be queried * @if_outgoing: the interface for which the ifinfo should be acquired * - * Returns NULL in case of failure or the neigh_ifinfo object for the + * Return: NULL in case of failure or the neigh_ifinfo object for the * if_outgoing interface otherwise. The object is created and added to the list * if it does not exist. * @@ -459,7 +463,8 @@ out: * * Looks for and possibly returns a neighbour belonging to this originator list * which is connected through the provided hard interface. - * Returns NULL if the neighbour is not found. + * + * Return: neighbor when found. Othwerwise NULL */ static struct batadv_neigh_node * batadv_neigh_node_get(const struct batadv_orig_node *orig_node, @@ -492,7 +497,7 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node, * @hard_iface: the interface this neighbour is connected to * @neigh_addr: the interface address of the neighbour to retrieve * - * Returns the hardif neighbour node if found or created or NULL otherwise. + * Return: the hardif neighbour node if found or created or NULL otherwise. */ static struct batadv_hardif_neigh_node * batadv_hardif_neigh_create(struct batadv_hard_iface *hard_iface, @@ -540,7 +545,7 @@ out: * @hard_iface: the interface this neighbour is connected to * @neigh_addr: the interface address of the neighbour to retrieve * - * Returns the hardif neighbour node if found or created or NULL otherwise. + * Return: the hardif neighbour node if found or created or NULL otherwise. */ static struct batadv_hardif_neigh_node * batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface, @@ -562,7 +567,8 @@ batadv_hardif_neigh_get_or_create(struct batadv_hard_iface *hard_iface, * @neigh_addr: the address of the neighbour * * Looks for and possibly returns a neighbour belonging to this hard interface. - * Returns NULL if the neighbour is not found. + * + * Return: neighbor when found. Othwerwise NULL */ struct batadv_hardif_neigh_node * batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, @@ -594,7 +600,8 @@ batadv_hardif_neigh_get(const struct batadv_hard_iface *hard_iface, * @neigh_addr: the mac address of the neighbour interface * * Allocates a new neigh_node object and initialises all the generic fields. - * Returns the new object or NULL on failure. + * + * Return: neighbor when found. Othwerwise NULL */ struct batadv_neigh_node * batadv_neigh_node_new(struct batadv_orig_node *orig_node, @@ -656,7 +663,7 @@ out: * @seq: neighbour table seq_file struct * @offset: not used * - * Always returns 0. + * Return: always 0 */ int batadv_hardif_neigh_seq_print_text(struct seq_file *seq, void *offset) { @@ -820,7 +827,8 @@ void batadv_originator_free(struct batadv_priv *bat_priv) * * Creates a new originator object and initialise all the generic fields. * The new object is not added to the originator list. - * Returns the newly created object or NULL on failure. + * + * Return: the newly created object or NULL on failure. */ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, const u8 *addr) @@ -937,7 +945,7 @@ batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node which is to be checked * - * Returns true if any ifinfo entry was purged, false otherwise. + * Return: true if any ifinfo entry was purged, false otherwise. */ static bool batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv, @@ -989,7 +997,7 @@ batadv_purge_orig_ifinfo(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node which is to be checked * - * Returns true if any neighbor was purged, false otherwise + * Return: true if any neighbor was purged, false otherwise */ static bool batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, @@ -1048,7 +1056,7 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, * @orig_node: orig node which is to be checked * @if_outgoing: the interface for which the metric should be compared * - * Returns the current best neighbor, with refcount increased. + * Return: the current best neighbor, with refcount increased. */ static struct batadv_neigh_node * batadv_find_best_neighbor(struct batadv_priv *bat_priv, @@ -1085,7 +1093,7 @@ batadv_find_best_neighbor(struct batadv_priv *bat_priv, * This function checks if the orig_node or substructures of it have become * obsolete, and purges this information if that's the case. * - * Returns true if the orig_node is to be removed, false otherwise. + * Return: true if the orig_node is to be removed, false otherwise. */ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node) @@ -1230,7 +1238,7 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset) * @seq: debugfs table seq_file struct * @offset: not used * - * Returns 0 + * Return: 0 */ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) { diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 54d660806c2a..bcaa7870038b 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -140,9 +140,12 @@ out: batadv_neigh_node_free_ref(router); } -/* checks whether the host restarted and is in the protection time. - * returns: - * 0 if the packet is to be accepted +/** + * batadv_window_protected checks whether the host restarted and is in the + * protection time. + * + * Return: + * 0 if the packet is to be accepted. * 1 if the packet is to be ignored. */ int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff, @@ -198,7 +201,7 @@ bool batadv_check_management_packet(struct sk_buff *skb, * @bat_priv: the bat priv with all the soft interface information * @skb: icmp packet to process * - * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP + * Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP * otherwise. */ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, @@ -398,10 +401,11 @@ out: * @skb: packet to check * @hdr_size: size of header to pull * - * Check for short header and bad addresses in given packet. Returns negative - * value when check fails and 0 otherwise. The negative value depends on the - * reason: -ENODATA for bad header, -EBADR for broadcast destination or source, - * and -EREMOTE for non-local (other host) destination. + * Check for short header and bad addresses in given packet. + * + * Return: negative value when check fails and 0 otherwise. The negative value + * depends on the reason: -ENODATA for bad header, -EBADR for broadcast + * destination or source, and -EREMOTE for non-local (other host) destination. */ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, int hdr_size) @@ -435,7 +439,7 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, * @orig_node: the destination node * @recv_if: pointer to interface this packet was received on * - * Returns the router which should be used for this orig_node on + * Return: the router which should be used for this orig_node on * this interface, or NULL if not available. */ struct batadv_neigh_node * @@ -648,7 +652,7 @@ out: * the new corresponding information (originator address where the destination * client currently is and its known TTVN) * - * Returns true if the packet header has been updated, false otherwise + * Return: true if the packet header has been updated, false otherwise */ static bool batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, @@ -805,7 +809,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, * @skb: unicast tvlv packet to process * @recv_if: pointer to interface this packet was received on * - * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP + * Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP * otherwise. */ int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb, @@ -905,7 +909,7 @@ rx_success: * @skb: unicast tvlv packet to process * @recv_if: pointer to interface this packet was received on * - * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP + * Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP * otherwise. */ int batadv_recv_unicast_tvlv(struct sk_buff *skb, @@ -959,7 +963,7 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb, * the assembled packet will exceed our MTU; 2) Buffer fragment, if we till * lack further fragments; 3) Merge fragments, if we have all needed parts. * - * Return NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise. + * Return: NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise. */ int batadv_recv_frag_packet(struct sk_buff *skb, struct batadv_hard_iface *recv_if) diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 3fbf7910c4d1..d9b93c567bbc 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -111,7 +111,7 @@ send_skb_err: * host, NULL can be passed as recv_if and no interface alternating is * attempted. * - * Returns NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or + * Return: NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or * NET_XMIT_POLICED if the skb is buffered for later transmit. */ int batadv_send_skb_to_orig(struct sk_buff *skb, @@ -165,7 +165,7 @@ out: * @hdr_size: amount of bytes to push at the beginning of the skb * @orig_node: the destination node * - * Returns false if the buffer extension was not possible or true otherwise. + * Return: false if the buffer extension was not possible or true otherwise. */ static bool batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size, @@ -196,7 +196,7 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size, * @skb: the skb containing the payload to encapsulate * @orig_node: the destination node * - * Returns false if the payload could not be encapsulated or true otherwise. + * Return: false if the payload could not be encapsulated or true otherwise. */ static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb, struct batadv_orig_node *orig_node) @@ -214,7 +214,7 @@ static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb, * @orig: the destination node * @packet_subtype: the unicast 4addr packet subtype to use * - * Returns false if the payload could not be encapsulated or true otherwise. + * Return: false if the payload could not be encapsulated or true otherwise. */ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv, struct sk_buff *skb, @@ -265,7 +265,7 @@ out: * as packet_type. Then send this frame to the given orig_node and release a * reference to this orig_node. * - * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. + * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */ int batadv_send_skb_unicast(struct batadv_priv *bat_priv, struct sk_buff *skb, int packet_type, @@ -339,7 +339,7 @@ out: * BATADV_UNICAST_4ADDR was supplied as packet_type. Then send this frame * to the according destination node. * - * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. + * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */ int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, struct sk_buff *skb, int packet_type, @@ -373,7 +373,7 @@ int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, * Look up the currently selected gateway. Wrap the given skb into a batman-adv * unicast header and send this frame to this gateway node. * - * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. + * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, unsigned short vid) @@ -430,14 +430,16 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, send_time); } -/* add a broadcast packet to the queue and setup timers. broadcast packets - * are sent multiple times to increase probability for being received. +/** + * batadv_add_bcast_packet_to_list * - * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on - * errors. + * add a broadcast packet to the queue and setup timers. broadcast packets + * are sent multiple times to increase probability for being received. * * The skb is not consumed, so the caller should make sure that the * skb is freed. + * + * Return: NETDEV_TX_OK on success and NETDEV_TX_BUSY on errors. */ int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, const struct sk_buff *skb, diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 82059f259e46..3adc11fe1586 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@ -69,7 +69,7 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, * header via the translation table. Wrap the given skb into a batman-adv * unicast header. Then send this frame to the according destination node. * - * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. + * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */ static inline int batadv_send_skb_via_tt(struct batadv_priv *bat_priv, struct sk_buff *skb, u8 *dst_hint, @@ -92,7 +92,7 @@ static inline int batadv_send_skb_via_tt(struct batadv_priv *bat_priv, * unicast-4addr header. Then send this frame to the according destination * node. * - * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. + * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. */ static inline int batadv_send_skb_via_tt_4addr(struct batadv_priv *bat_priv, struct sk_buff *skb, diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c923e3c7b6ac..5ee794b62392 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -501,7 +501,7 @@ void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) * @bat_priv: the bat priv with all the soft interface information * @vid: the identifier of the vlan object to retrieve * - * Returns the private data of the vlan matching the vid passed as argument or + * Return: the private data of the vlan matching the vid passed as argument or * NULL otherwise. The refcounter of the returned object is incremented by 1. */ struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv, @@ -530,7 +530,7 @@ struct batadv_softif_vlan *batadv_softif_vlan_get(struct batadv_priv *bat_priv, * @bat_priv: the bat priv with all the soft interface information * @vid: the VLAN identifier * - * Returns 0 on success, a negative error otherwise. + * Return: 0 on success, a negative error otherwise. */ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid) { @@ -599,7 +599,7 @@ static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv, * Set up all the internal structures for handling the new vlan on top of the * mesh interface * - * Returns 0 on success or a negative error code in case of failure. + * Return: 0 on success or a negative error code in case of failure. */ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto, unsigned short vid) @@ -656,7 +656,7 @@ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto, * Destroy all the internal structures used to handle the vlan identified by vid * on top of the mesh interface * - * Returns 0 on success, -EINVAL if the specified prototype is not ETH_P_8021Q + * Return: 0 on success, -EINVAL if the specified prototype is not ETH_P_8021Q * or -ENOENT if the specified vlan id wasn't registered. */ static int batadv_interface_kill_vid(struct net_device *dev, __be16 proto, @@ -745,7 +745,7 @@ static void batadv_softif_destroy_finish(struct work_struct *work) * batadv_softif_init_late - late stage initialization of soft interface * @dev: registered network device to modify * - * Returns error code on failures + * Return: error code on failures */ static int batadv_softif_init_late(struct net_device *dev) { @@ -847,7 +847,7 @@ free_bat_counters: * @dev: batadv_soft_interface used as master interface * @slave_dev: net_device which should become the slave interface * - * Return 0 if successful or error otherwise. + * Return: 0 if successful or error otherwise. */ static int batadv_softif_slave_add(struct net_device *dev, struct net_device *slave_dev) @@ -872,7 +872,7 @@ out: * @dev: batadv_soft_interface used as master interface * @slave_dev: net_device which should be removed from the master interface * - * Return 0 if successful or error otherwise. + * Return: 0 if successful or error otherwise. */ static int batadv_softif_slave_del(struct net_device *dev, struct net_device *slave_dev) diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 33772d9bd613..7658e6ea0596 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -64,7 +64,7 @@ static struct batadv_priv *batadv_kobj_to_batpriv(struct kobject *obj) * batadv_vlan_kobj_to_batpriv - convert a vlan kobj in the associated batpriv * @obj: kobject to covert * - * Returns the associated batadv_priv struct. + * Return: the associated batadv_priv struct. */ static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) { @@ -84,7 +84,7 @@ static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct * @obj: kobject to covert * - * Returns the associated softif_vlan struct if found, NULL otherwise. + * Return: the associated softif_vlan struct if found, NULL otherwise. */ static struct batadv_softif_vlan * batadv_kobj_to_vlan(struct batadv_priv *bat_priv, struct kobject *obj) @@ -491,7 +491,7 @@ static ssize_t batadv_store_gw_bwidth(struct kobject *kobj, * @attr: the batman-adv attribute the user is interacting with * @buff: the buffer that will contain the data to send back to the user * - * Returns the number of bytes written into 'buff' on success or a negative + * Return: the number of bytes written into 'buff' on success or a negative * error code in case of failure */ static ssize_t batadv_show_isolation_mark(struct kobject *kobj, @@ -511,7 +511,7 @@ static ssize_t batadv_show_isolation_mark(struct kobject *kobj, * @buff: the buffer containing the user data * @count: number of bytes in the buffer * - * Returns 'count' on success or a negative error code in case of failure + * Return: 'count' on success or a negative error code in case of failure */ static ssize_t batadv_store_isolation_mark(struct kobject *kobj, struct attribute *attr, char *buff, @@ -681,7 +681,7 @@ void batadv_sysfs_del_meshif(struct net_device *dev) * @dev: netdev of the mesh interface * @vlan: private data of the newly added VLAN interface * - * Returns 0 on success and -ENOMEM if any of the structure allocations fails. + * Return: 0 on success and -ENOMEM if any of the structure allocations fails. */ int batadv_sysfs_add_vlan(struct net_device *dev, struct batadv_softif_vlan *vlan) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 7d8fc90c9e38..af1d24ce420f 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -68,7 +68,11 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, unsigned short vid, const char *message, bool roaming); -/* returns 1 if they are the same mac addr and vid */ +/** + * batadv_compare_tt + * + * Return: 1 if they are the same mac addr and vid + */ static int batadv_compare_tt(const struct hlist_node *node, const void *data2) { const void *data1 = container_of(node, struct batadv_tt_common_entry, @@ -84,7 +88,7 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2) * @data: pointer to the tt_common_entry object to map * @size: the size of the hash table * - * Returns the hash index where the object represented by 'data' should be + * Return: the hash index where the object represented by 'data' should be * stored at. */ static inline u32 batadv_choose_tt(const void *data, u32 size) @@ -105,7 +109,7 @@ static inline u32 batadv_choose_tt(const void *data, u32 size) * @addr: the mac address of the client to look for * @vid: VLAN identifier * - * Returns a pointer to the tt_common struct belonging to the searched client if + * Return: a pointer to the tt_common struct belonging to the searched client if * found, NULL otherwise. */ static struct batadv_tt_common_entry * @@ -150,7 +154,7 @@ batadv_tt_hash_find(struct batadv_hashtable *hash, const u8 *addr, * @addr: the mac address of the client to look for * @vid: VLAN identifier * - * Returns a pointer to the corresponding tt_local_entry struct if the client is + * Return: a pointer to the corresponding tt_local_entry struct if the client is * found, NULL otherwise. */ static struct batadv_tt_local_entry * @@ -175,7 +179,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const u8 *addr, * @addr: the mac address of the client to look for * @vid: VLAN identifier * - * Returns a pointer to the corresponding tt_global_entry struct if the client + * Return: a pointer to the corresponding tt_global_entry struct if the client * is found, NULL otherwise. */ static struct batadv_tt_global_entry * @@ -220,7 +224,7 @@ batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) * @addr: the mac address of the client to count entries for * @vid: VLAN identifier * - * Return the number of originators advertising the given address/data + * Return: the number of originators advertising the given address/data * (excluding ourself). */ int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, @@ -433,7 +437,7 @@ unlock: * batadv_tt_len - compute length in bytes of given number of tt changes * @changes_num: number of tt changes * - * Returns computed length in bytes. + * Return: computed length in bytes. */ static int batadv_tt_len(int changes_num) { @@ -444,7 +448,7 @@ static int batadv_tt_len(int changes_num) * batadv_tt_entries - compute the number of entries fitting in tt_len bytes * @tt_len: available space * - * Returns the number of entries. + * Return: the number of entries. */ static u16 batadv_tt_entries(u16 tt_len) { @@ -456,7 +460,7 @@ static u16 batadv_tt_entries(u16 tt_len) * size when transmitted over the air * @bat_priv: the bat priv with all the soft interface information * - * Returns local translation table size in bytes. + * Return: local translation table size in bytes. */ static int batadv_tt_local_table_transmit_size(struct batadv_priv *bat_priv) { @@ -522,7 +526,7 @@ static void batadv_tt_global_free(struct batadv_priv *bat_priv, * @mark: the value contained in the skb->mark field of the received packet (if * any) * - * Returns true if the client was successfully added, false otherwise. + * Return: true if the client was successfully added, false otherwise. */ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, unsigned short vid, int ifindex, u32 mark) @@ -722,7 +726,7 @@ out: * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data * objects, one per active VLAN served by the originator node. * - * Return the size of the allocated buffer or 0 in case of failure. + * Return: the size of the allocated buffer or 0 in case of failure. */ static u16 batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, @@ -796,7 +800,7 @@ out: * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data * objects, one per active VLAN. * - * Return the size of the allocated buffer or 0 in case of failure. + * Return: the size of the allocated buffer or 0 in case of failure. */ static u16 batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, @@ -1038,7 +1042,7 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv, * @message: message to append to the log on deletion * @roaming: true if the deletion is due to a roaming event * - * Returns the flags assigned to the local entry before being deleted + * Return: the flags assigned to the local entry before being deleted */ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr, unsigned short vid, const char *message, @@ -1238,10 +1242,13 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv) spin_unlock_bh(&bat_priv->tt.changes_list_lock); } -/* retrieves the orig_tt_list_entry belonging to orig_node from the +/** + * batadv_tt_global_orig_entry_find + * + * retrieves the orig_tt_list_entry belonging to orig_node from the * batadv_tt_global_entry list * - * returns it with an increased refcounter, NULL if not found + * Return: it with an increased refcounter, NULL if not found */ static struct batadv_tt_orig_list_entry * batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, @@ -1266,8 +1273,12 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, return orig_entry; } -/* find out if an orig_node is already in the list of a tt_global_entry. - * returns true if found, false otherwise +/** + * batadv_tt_global_entry_has_orig + * + * find out if an orig_node is already in the list of a tt_global_entry. + * + * Return: true if found, false otherwise */ static bool batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, @@ -1339,7 +1350,7 @@ out: * * The caller must hold orig_node refcount. * - * Return true if the new entry has been added, false otherwise + * Return: true if the new entry has been added, false otherwise */ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, @@ -1497,7 +1508,7 @@ out: * @tt_global_entry: global translation table entry to be analyzed * * This functon assumes the caller holds rcu_read_lock(). - * Returns best originator list entry or NULL on errors. + * Return: best originator list entry or NULL on errors. */ static struct batadv_tt_orig_list_entry * batadv_transtable_best_orig(struct batadv_priv *bat_priv, @@ -2027,7 +2038,7 @@ _batadv_is_ap_isolated(struct batadv_tt_local_entry *tt_local_entry, * @addr: mac address of the destination client * @vid: VLAN identifier * - * Returns a pointer to the originator that was selected as destination in the + * Return: a pointer to the originator that was selected as destination in the * mesh for contacting the client 'addr', NULL otherwise. * In case of multiple originators serving the same client, the function returns * the best one (best in terms of metric towards the destination node). @@ -2102,7 +2113,7 @@ out: * because the XOR operation can combine them all while trying to reduce the * noise as much as possible. * - * Returns the checksum of the global table of a given originator. + * Return: the checksum of the global table of a given originator. */ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, struct batadv_orig_node *orig_node, @@ -2179,7 +2190,7 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, * For details about the computation, please refer to the documentation for * batadv_tt_global_crc(). * - * Returns the checksum of the local table + * Return: the checksum of the local table */ static u32 batadv_tt_local_crc(struct batadv_priv *bat_priv, unsigned short vid) @@ -2285,7 +2296,7 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv) * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node this request is being issued for * - * Returns the pointer to the new tt_req_node struct if no request + * Return: the pointer to the new tt_req_node struct if no request * has already been issued for this orig_node, NULL otherwise. */ static struct batadv_tt_req_node * @@ -2320,7 +2331,7 @@ unlock: * @entry_ptr: to be checked local tt entry * @data_ptr: not used but definition required to satisfy the callback prototype * - * Returns 1 if the entry is a valid, 0 otherwise. + * Return: 1 if the entry is a valid, 0 otherwise. */ static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr) { @@ -2405,7 +2416,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, * @tt_vlan: pointer to the first tvlv VLAN entry * @num_vlan: number of tvlv VLAN entries * - * Return true if all the received CRCs match the locally stored ones, false + * Return: true if all the received CRCs match the locally stored ones, false * otherwise */ static bool batadv_tt_global_check_crc(struct batadv_orig_node *orig_node, @@ -2588,7 +2599,7 @@ out: * @req_src: mac address of tt request sender * @req_dst: mac address of tt request recipient * - * Returns true if tt request reply was sent, false otherwise. + * Return: true if tt request reply was sent, false otherwise. */ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv, struct batadv_tvlv_tt_data *tt_data, @@ -2720,7 +2731,7 @@ out: * @tt_data: tt data containing the tt request information * @req_src: mac address of tt request sender * - * Returns true if tt request reply was sent, false otherwise. + * Return: true if tt request reply was sent, false otherwise. */ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv, struct batadv_tvlv_tt_data *tt_data, @@ -2838,7 +2849,7 @@ out: * @req_src: mac address of tt request sender * @req_dst: mac address of tt request recipient * - * Returns true if tt request reply was sent, false otherwise. + * Return: true if tt request reply was sent, false otherwise. */ static bool batadv_send_tt_response(struct batadv_priv *bat_priv, struct batadv_tvlv_tt_data *tt_data, @@ -2933,7 +2944,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv, * @addr: the mac address of the client to check * @vid: VLAN identifier * - * Returns true if the client is served by this node, false otherwise. + * Return: true if the client is served by this node, false otherwise. */ bool batadv_is_my_client(struct batadv_priv *bat_priv, const u8 *addr, unsigned short vid) @@ -3050,11 +3061,14 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) spin_unlock_bh(&bat_priv->tt.roam_list_lock); } -/* This function checks whether the client already reached the +/** + * batadv_tt_check_roam_count + * + * This function checks whether the client already reached the * maximum number of possible roaming phases. In this case the ROAMING_ADV * will not be sent. * - * returns true if the ROAMING_ADV can be sent, false otherwise + * Return: true if the ROAMING_ADV can be sent, false otherwise */ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, u8 *client) { @@ -3453,7 +3467,7 @@ request_table: * @addr: the mac address of the client to check * @vid: VLAN identifier * - * Returns true if we know that the client has moved from its old originator + * Return: true if we know that the client has moved from its old originator * to another one. This entry is still kept for consistency purposes and will be * deleted later by a DEL or because of timeout */ @@ -3479,7 +3493,7 @@ out: * @addr: the mac address of the local client to query * @vid: VLAN identifier * - * Returns true if the local client is known to be roaming (it is not served by + * Return: true if the local client is known to be roaming (it is not served by * this node anymore) or not. If yes, the client is still present in the table * to keep the latter consistent with the node TTVN */ @@ -3608,7 +3622,7 @@ static void batadv_tt_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, * @tvlv_value: tvlv buffer containing the tt data * @tvlv_value_len: tvlv buffer length * - * Returns NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS + * Return: NET_RX_DROP if the tt tvlv is to be re-routed, NET_RX_SUCCESS * otherwise. */ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv, @@ -3689,7 +3703,7 @@ static int batadv_tt_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv, * @tvlv_value: tvlv buffer containing the tt data * @tvlv_value_len: tvlv buffer length * - * Returns NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS + * Return: NET_RX_DROP if the tt roam tvlv is to be re-routed, NET_RX_SUCCESS * otherwise. */ static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv, @@ -3735,7 +3749,7 @@ out: * batadv_tt_init - initialise the translation table internals * @bat_priv: the bat priv with all the soft interface information * - * Return 0 on success or negative error number in case of failure. + * Return: 0 on success or negative error number in case of failure. */ int batadv_tt_init(struct batadv_priv *bat_priv) { @@ -3773,7 +3787,7 @@ int batadv_tt_init(struct batadv_priv *bat_priv) * @addr: the mac address of the client * @vid: the identifier of the VLAN where this client is connected * - * Returns true if the client is marked with the TT_CLIENT_ISOLA flag, false + * Return: true if the client is marked with the TT_CLIENT_ISOLA flag, false * otherwise */ bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv, -- cgit From 7afcbbef6471130a1eb586fea0f5c06609b8341f Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 31 Oct 2015 12:29:29 +0100 Subject: batman-adv: Fix kerneldoc of main functions Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bitarray.c | 12 +++++++++--- net/batman-adv/bitarray.h | 11 +++++------ net/batman-adv/debugfs.c | 6 ++++++ net/batman-adv/main.c | 2 ++ net/batman-adv/main.h | 4 ++++ net/batman-adv/originator.c | 4 +++- net/batman-adv/packet.h | 6 ++++++ net/batman-adv/routing.c | 7 ++++++- net/batman-adv/send.c | 5 ++++- net/batman-adv/soft-interface.c | 2 ++ net/batman-adv/sysfs.c | 1 + 11 files changed, 48 insertions(+), 12 deletions(-) diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index 06bab5179bf9..3404195f2561 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c @@ -29,10 +29,16 @@ static void batadv_bitmap_shift_left(unsigned long *seq_bits, s32 n) bitmap_shift_left(seq_bits, seq_bits, n, BATADV_TQ_LOCAL_WINDOW_SIZE); } -/* receive and process one packet within the sequence number window. +/** + * batadv_bit_get_packet - receive and process one packet within the sequence + * number window + * @priv: the bat priv with all the soft interface information + * @seq_bits: pointer to the sequence number receive packet + * @seq_num_diff: difference between the current/received sequence number and + * the last sequence number + * @set_mark: whether this packet should be marked in seq_bits * - * Return: - * 1 if the window was moved (either new or very old) + * Return: 1 if the window was moved (either new or very old), * 0 if the window was not moved/shifted. */ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff, diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index cf2aeb0831a4..2b64d7a1bc9b 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h @@ -25,7 +25,11 @@ #include /** - * batadv_test_bit + * batadv_test_bit - check if bit is set in the current window + * + * @seq_bits: pointer to the sequence number receive packet + * @last_seqno: latest sequence number in seq_bits + * @curr_seqno: sequence number to test for * * Return: 1 if the corresponding bit in the given seq_bits indicates true * and curr_seqno is within range of last_seqno. Otherwise returns 0. @@ -51,11 +55,6 @@ static inline void batadv_set_bit(unsigned long *seq_bits, s32 n) set_bit(n, seq_bits); /* turn the position on */ } -/** - * batadv_bit_get_packet - receive and process one packet - * - * Return: 1 if received seq_num is considered new, 0 if old - */ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits, s32 seq_num_diff, int set_mark); diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 037ad0a5f485..0fc9df52f3d9 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -281,6 +281,8 @@ static int batadv_originators_open(struct inode *inode, struct file *file) * originator table of an hard interface * @inode: inode pointer to debugfs file * @file: pointer to the seq_file + * + * Return: 0 on success or negative error number in case of failure */ static int batadv_originators_hardif_open(struct inode *inode, struct file *file) @@ -329,6 +331,8 @@ static int batadv_bla_backbone_table_open(struct inode *inode, * batadv_dat_cache_open - Prepare file handler for reads from dat_chache * @inode: inode which was opened * @file: file handle to be initialized + * + * Return: 0 on success or negative error number in case of failure */ static int batadv_dat_cache_open(struct inode *inode, struct file *file) { @@ -483,6 +487,8 @@ void batadv_debugfs_destroy(void) * batadv_debugfs_add_hardif - creates the base directory for a hard interface * in debugfs. * @hard_iface: hard interface which should be added. + * + * Return: 0 on success or negative error number in case of failure */ int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface) { diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 70907f6f37ed..9d34be628304 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -599,6 +599,8 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset) * * payload_ptr must always point to an address in the skb head buffer and not to * a fragment. + * + * Return: big endian crc32c of the checksummed data */ __be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr) { diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 8a48d4a40828..34f56efa2e4e 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -275,6 +275,8 @@ static inline void _batadv_dbg(int type __always_unused, /** * batadv_compare_eth - Compare two not u16 aligned Ethernet addresses + * @data1: Pointer to a six-byte array containing the Ethernet address + * @data2: Pointer other six-byte array containing the Ethernet address * * note: can't use ether_addr_equal() as it requires aligned memory * @@ -331,6 +333,8 @@ static inline void batadv_add_counter(struct batadv_priv *bat_priv, size_t idx, /** * batadv_sum_counter - Sum the cpu-local counters for index 'idx' + * @bat_priv: the bat priv with all the soft interface information + * @idx: index of counter to sum up * * Return: sum of all cpu-local counters */ diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ed1d6d7b717e..f6ca4e509729 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -48,7 +48,9 @@ static struct lock_class_key batadv_orig_hash_lock_class_key; static void batadv_purge_orig(struct work_struct *work); /** - * batadv_compare_orig + * batadv_compare_orig - comparing function used in the originator hash table + * @node: node in the local table + * @data2: second object to compare the node to * * Return: 1 if they are the same originator */ diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 72fd5b0a4183..fdb01637ad1f 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -209,6 +209,11 @@ struct batadv_bla_claim_dst { * @version: batman-adv protocol version, part of the genereal header * @ttl: time to live for this packet, part of the genereal header * @flags: contains routing relevant flags - see enum batadv_iv_flags + * @seqno: sequence identification + * @orig: address of the source node + * @prev_sender: address of the previous sender + * @reserved: reserved byte for alignment + * @tq: transmission quality * @tvlv_len: length of tvlv data following the ogm header */ struct batadv_ogm_packet { @@ -345,6 +350,7 @@ struct batadv_unicast_packet { * @u: common unicast packet header * @src: address of the source * @subtype: packet subtype + * @reserved: reserved byte for alignment */ struct batadv_unicast_4addr_packet { struct batadv_unicast_packet u; diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index bcaa7870038b..1fb1be31bf3a 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -141,8 +141,13 @@ out: } /** - * batadv_window_protected checks whether the host restarted and is in the + * batadv_window_protected - checks whether the host restarted and is in the * protection time. + * @bat_priv: the bat priv with all the soft interface information + * @seq_num_diff: difference between the current/received sequence number and + * the last sequence number + * @last_reset: jiffies timestamp of the last reset, will be updated when reset + * is detected * * Return: * 0 if the packet is to be accepted. diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index d9b93c567bbc..c188f4660981 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -431,7 +431,10 @@ _batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv, } /** - * batadv_add_bcast_packet_to_list + * batadv_add_bcast_packet_to_list - queue broadcast packet for multiple sends + * @bat_priv: the bat priv with all the soft interface information + * @skb: broadcast packet to add + * @delay: number of jiffies to wait before sending * * add a broadcast packet to the queue and setup timers. broadcast packets * are sent multiple times to increase probability for being received. diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 5ee794b62392..6c65de97126c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -594,6 +594,7 @@ static void batadv_softif_destroy_vlan(struct batadv_priv *bat_priv, /** * batadv_interface_add_vid - ndo_add_vid API implementation * @dev: the netdev of the mesh interface + * @proto: protocol of the the vlan id * @vid: identifier of the new vlan * * Set up all the internal structures for handling the new vlan on top of the @@ -651,6 +652,7 @@ static int batadv_interface_add_vid(struct net_device *dev, __be16 proto, /** * batadv_interface_kill_vid - ndo_kill_vid API implementation * @dev: the netdev of the mesh interface + * @proto: protocol of the the vlan id * @vid: identifier of the deleted vlan * * Destroy all the internal structures used to handle the vlan identified by vid diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 7658e6ea0596..f38d7b75b0a5 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -82,6 +82,7 @@ static struct batadv_priv *batadv_vlan_kobj_to_batpriv(struct kobject *obj) /** * batadv_kobj_to_vlan - convert a kobj in the associated softif_vlan struct + * @bat_priv: the bat priv with all the soft interface information * @obj: kobject to covert * * Return: the associated softif_vlan struct if found, NULL otherwise. -- cgit From 672e797850422bdbbcd3c781a07fe777042ee068 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 31 Oct 2015 12:29:30 +0100 Subject: batman-adv: Fix kerneldoc of network-coding functions Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/network-coding.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 1a75d288f8a7..3a752bea55fa 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -64,6 +64,8 @@ static int batadv_nc_recv_coded_packet(struct sk_buff *skb, /** * batadv_nc_init - one-time initialization for network coding + * + * Return: 0 on success or negative error number in case of failure */ int __init batadv_nc_init(void) { @@ -142,6 +144,8 @@ static void batadv_nc_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, /** * batadv_nc_mesh_init - initialise coding hash table and start house keeping * @bat_priv: the bat priv with all the soft interface information + * + * Return: 0 on success or negative error number in case of failure */ int batadv_nc_mesh_init(struct batadv_priv *bat_priv) { @@ -989,6 +993,8 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, * batadv_nc_random_weight_tq - scale the receivers TQ-value to avoid unfair * selection of a receiver with slightly lower TQ than the other * @tq: to be weighted tq value + * + * Return: scaled tq value */ static u8 batadv_nc_random_weight_tq(u8 tq) { @@ -1781,6 +1787,9 @@ batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv, * resulting unicast packet * @skb: incoming coded packet * @recv_if: pointer to interface this packet was received on + * + * Return: NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP + * otherwise. */ static int batadv_nc_recv_coded_packet(struct sk_buff *skb, struct batadv_hard_iface *recv_if) @@ -1865,6 +1874,8 @@ void batadv_nc_mesh_free(struct batadv_priv *bat_priv) * batadv_nc_nodes_seq_print_text - print the nc node information * @seq: seq file to print on * @offset: not used + * + * Return: always 0 */ int batadv_nc_nodes_seq_print_text(struct seq_file *seq, void *offset) { @@ -1927,6 +1938,8 @@ out: /** * batadv_nc_init_debugfs - create nc folder and related files in debugfs * @bat_priv: the bat priv with all the soft interface information + * + * Return: 0 on success or negative error number in case of failure */ int batadv_nc_init_debugfs(struct batadv_priv *bat_priv) { -- cgit From 04e14be65bdb09f8ed87f75e0b5463ced6706949 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Fri, 6 Nov 2015 10:45:19 +0100 Subject: batman-adv: Update/repair bridge loop avoidance kerneldoc Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 178 ++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 48 deletions(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 90c79948979c..131aca049907 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -59,9 +59,11 @@ batadv_bla_send_announce(struct batadv_priv *bat_priv, struct batadv_bla_backbone_gw *backbone_gw); /** - * batadv_choose_claim + * batadv_choose_claim - choose the right bucket for a claim. + * @data: data to hash + * @size: size of the hash table * - * Return: the index of the claim + * Return: the hash index of the claim */ static inline u32 batadv_choose_claim(const void *data, u32 size) { @@ -75,9 +77,11 @@ static inline u32 batadv_choose_claim(const void *data, u32 size) } /** - * batadv_choose_backbone_gw + * batadv_choose_backbone_gw - choose the right bucket for a backbone gateway. + * @data: data to hash + * @size: size of the hash table * - * Return: the index of the backbone gateway + * Return: the hash index of the backbone gateway */ static inline u32 batadv_choose_backbone_gw(const void *data, u32 size) { @@ -90,7 +94,13 @@ static inline u32 batadv_choose_backbone_gw(const void *data, u32 size) return hash % size; } -/* compares address and vid of two backbone gws */ +/** + * batadv_compare_backbone_gw - compare address and vid of two backbone gws + * @node: list node of the first entry to compare + * @data2: pointer to the second backbone gateway + * + * Return: 1 if the backbones have the same data, 0 otherwise + */ static int batadv_compare_backbone_gw(const struct hlist_node *node, const void *data2) { @@ -108,7 +118,13 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node, return 1; } -/* compares address and vid of two claims */ +/** + * batadv_compare_backbone_gw - compare address and vid of two claims + * @node: list node of the first entry to compare + * @data2: pointer to the second claims + * + * Return: 1 if the claim have the same data, 0 otherwise + */ static int batadv_compare_claim(const struct hlist_node *node, const void *data2) { @@ -126,7 +142,10 @@ static int batadv_compare_claim(const struct hlist_node *node, return 1; } -/* free a backbone gw */ +/** + * batadv_compare_backbone_gw - free backbone gw + * @backbone_gw: backbone gateway to be free'd + */ static void batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw) { @@ -134,14 +153,21 @@ batadv_backbone_gw_free_ref(struct batadv_bla_backbone_gw *backbone_gw) kfree_rcu(backbone_gw, rcu); } -/* finally deinitialize the claim */ +/** + * batadv_claim_release - release claim from lists and queue for free after rcu + * grace period + * @ref: kref pointer of the claim + */ static void batadv_claim_release(struct batadv_bla_claim *claim) { batadv_backbone_gw_free_ref(claim->backbone_gw); kfree_rcu(claim, rcu); } -/* free a claim, call claim_free_rcu if its the last reference */ +/** + * batadv_claim_free_rcu - free a claim + * @claim: claim to be free'd + */ static void batadv_claim_free_ref(struct batadv_bla_claim *claim) { if (atomic_dec_and_test(&claim->refcount)) @@ -149,12 +175,10 @@ static void batadv_claim_free_ref(struct batadv_bla_claim *claim) } /** - * batadv_claim_hash_find + * batadv_claim_hash_find - looks for a claim in the claim hash * @bat_priv: the bat priv with all the soft interface information * @data: search data (may be local/static data) * - * looks for a claim in the hash - * * Return: claim if found or NULL otherwise. */ static struct batadv_bla_claim @@ -190,12 +214,12 @@ static struct batadv_bla_claim } /** - * batadv_backbone_hash_find - looks for a claim in the hash + * batadv_backbone_hash_find - looks for a backbone gateway in the hash * @bat_priv: the bat priv with all the soft interface information * @addr: the address of the originator * @vid: the VLAN ID * - * Return: claim if found or NULL otherwise. + * Return: backbone gateway if found or NULL otherwise */ static struct batadv_bla_backbone_gw * batadv_backbone_hash_find(struct batadv_priv *bat_priv, u8 *addr, @@ -233,7 +257,10 @@ batadv_backbone_hash_find(struct batadv_priv *bat_priv, u8 *addr, return backbone_gw_tmp; } -/* delete all claims for a backbone */ +/** + * batadv_bla_del_backbone_claims - delete all claims for a backbone + * @backbone_gw: backbone gateway where the claims should be removed + */ static void batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw) { @@ -381,14 +408,13 @@ out: } /** - * batadv_bla_get_backbone_gw + * batadv_bla_get_backbone_gw - finds or creates a backbone gateway * @bat_priv: the bat priv with all the soft interface information * @orig: the mac address of the originator * @vid: the VLAN ID * @own_backbone: set if the requested backbone is local * - * searches for the backbone gw or creates a new one if it could not - * be found. + * Return: the (possibly created) backbone gateway or NULL on error */ static struct batadv_bla_backbone_gw * batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig, @@ -454,7 +480,13 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig, return entry; } -/* update or add the own backbone gw to make sure we announce +/** + * batadv_bla_update_own_backbone_gw - updates the own backbone gw for a VLAN + * @bat_priv: the bat priv with all the soft interface information + * @primary_if: the selected primary interface + * @vid: VLAN identifier + * + * update or add the own backbone gw to make sure we announce * where we receive other backbone gws */ static void @@ -551,12 +583,9 @@ static void batadv_bla_send_request(struct batadv_bla_backbone_gw *backbone_gw) } /** - * batadv_bla_send_announce + * batadv_bla_send_announce - Send an announcement frame * @bat_priv: the bat priv with all the soft interface information * @backbone_gw: our backbone gateway which should be announced - * - * This function sends an announcement. It is called from multiple - * places. */ static void batadv_bla_send_announce(struct batadv_priv *bat_priv, struct batadv_bla_backbone_gw *backbone_gw) @@ -646,8 +675,11 @@ claim_free_ref: batadv_claim_free_ref(claim); } -/* Delete a claim from the claim hash which has the - * given mac address and vid. +/** + * batadv_bla_del_claim - delete a claim from the claim hash + * @bat_priv: the bat priv with all the soft interface information + * @mac: mac address of the claim to be removed + * @vid: VLAN id for the claim to be removed */ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, const u8 *mac, const unsigned short vid) @@ -677,6 +709,10 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, /** * batadv_handle_announce - check for ANNOUNCE frame + * @bat_priv: the bat priv with all the soft interface information + * @an_addr: announcement mac address (ARP Sender HW address) + * @backbone_addr: originator address of the sender (Ethernet source MAC) + * @vid: the VLAN ID of the frame * * Return: 1 if handled */ @@ -731,6 +767,11 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr, /** * batadv_handle_request - check for REQUEST frame + * @bat_priv: the bat priv with all the soft interface information + * @primary_if: the primary hard interface of this batman soft interface + * @backbone_addr: backbone address to be requested (ARP sender HW MAC) + * @ethhdr: ethernet header of a packet + * @vid: the VLAN ID of the frame * * Return: 1 if handled */ @@ -759,6 +800,11 @@ static int batadv_handle_request(struct batadv_priv *bat_priv, /** * batadv_handle_unclaim - check for UNCLAIM frame + * @bat_priv: the bat priv with all the soft interface information + * @primary_if: the primary hard interface of this batman soft interface + * @backbone_addr: originator address of the backbone (Ethernet source) + * @claim_addr: Client to be unclaimed (ARP sender HW MAC) + * @vid: the VLAN ID of the frame * * Return: 1 if handled */ @@ -792,6 +838,11 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv, /** * batadv_handle_claim - check for CLAIM frame + * @bat_priv: the bat priv with all the soft interface information + * @primary_if: the primary hard interface of this batman soft interface + * @backbone_addr: originator address of the backbone (Ethernet Source) + * @claim_addr: client mac address to be claimed (ARP sender HW MAC) + * @vid: the VLAN ID of the frame * * Return: 1 if handled */ @@ -823,7 +874,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, } /** - * batadv_check_claim_group + * batadv_check_claim_group - check for claim group membership * @bat_priv: the bat priv with all the soft interface information * @primary_if: the primary interface of this batman interface * @hw_src: the Hardware source in the ARP Header @@ -898,13 +949,11 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv, } /** - * batadv_bla_process_claim + * batadv_bla_process_claim - Check if this is a claim frame, and process it * @bat_priv: the bat priv with all the soft interface information * @primary_if: the primary hard interface of this batman soft interface * @skb: the frame to be checked * - * Check if this is a claim frame, and process it accordingly. - * * Return: 1 if it was a claim frame, otherwise return 0 to * tell the callee that it can use the frame on its own. */ @@ -1036,7 +1085,13 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, return 1; } -/* Check when we last heard from other nodes, and remove them in case of +/** + * batadv_bla_purge_backbone_gw - Remove backbone gateways after a timeout or + * immediately + * @bat_priv: the bat priv with all the soft interface information + * @now: whether the whole hash shall be wiped now + * + * Check when we last heard from other nodes, and remove them in case of * a time out, or clean all backbone gws if now is set. */ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now) @@ -1084,7 +1139,7 @@ purge_now: } /** - * batadv_bla_purge_claims + * batadv_bla_purge_claims - Remove claims after a timeout or immediately * @bat_priv: the bat priv with all the soft interface information * @primary_if: the selected primary interface, may be NULL if now is set * @now: whether the whole hash shall be wiped now @@ -1133,12 +1188,11 @@ purge_now: } /** - * batadv_bla_update_orig_address + * batadv_bla_update_orig_address - Update the backbone gateways when the own + * originator address changes * @bat_priv: the bat priv with all the soft interface information * @primary_if: the new selected primary_if * @oldif: the old primary interface, may be NULL - * - * Update the backbone gateways when the own orig address changes. */ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, struct batadv_hard_iface *primary_if, @@ -1209,7 +1263,11 @@ void batadv_bla_status_update(struct net_device *net_dev) batadv_hardif_free_ref(primary_if); } -/* periodic work to do: +/** + * batadv_bla_periodic_work - performs periodic bla work + * @work: kernel work struct + * + * periodic work to do: * * purge structures when they are too old * * send announcements */ @@ -1290,7 +1348,12 @@ out: static struct lock_class_key batadv_claim_hash_lock_class_key; static struct lock_class_key batadv_backbone_hash_lock_class_key; -/* initialize all bla structures */ +/** + * batadv_bla_init - initialize all bla structures + * @bat_priv: the bat priv with all the soft interface information + * + * Return: 0 on success, < 0 on error. + */ int batadv_bla_init(struct batadv_priv *bat_priv) { int i; @@ -1345,7 +1408,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv) } /** - * batadv_bla_check_bcast_duplist + * batadv_bla_check_bcast_duplist - Check if a frame is in the broadcast dup. * @bat_priv: the bat priv with all the soft interface information * @skb: contains the bcast_packet to be checked * @@ -1357,6 +1420,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv) * with a good chance that it is the same packet. If it is furthermore * sent by another host, drop it. We allow equal packets from * the same host however as this might be intended. + * + * Return: 1 if a packet is in the duplicate list, 0 otherwise. */ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, struct sk_buff *skb) @@ -1415,13 +1480,12 @@ out: } /** - * batadv_bla_is_backbone_gw_orig + * batadv_bla_is_backbone_gw_orig - Check if the originator is a gateway for + * the VLAN identified by vid. * @bat_priv: the bat priv with all the soft interface information * @orig: originator mac address * @vid: VLAN identifier * - * Check if the originator is a gateway for the VLAN identified by vid. - * * Return: true if orig is a backbone for this vid, false otherwise. */ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig, @@ -1456,13 +1520,11 @@ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig, } /** - * batadv_bla_is_backbone_gw + * batadv_bla_is_backbone_gw - check if originator is a backbone gw for a VLAN. * @skb: the frame to be checked * @orig_node: the orig_node of the frame * @hdr_size: maximum length of the frame * - * bla_is_backbone_gw inspects the skb for the VLAN ID - * * Return: 1 if the orig_node is also a gateway on the soft interface, otherwise * it returns 0. */ @@ -1491,7 +1553,12 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb, return 1; } -/* free all bla structures (for softinterface free or module unload) */ +/** + * batadv_bla_init - free all bla structures + * @bat_priv: the bat priv with all the soft interface information + * + * for softinterface free or module unload + */ void batadv_bla_free(struct batadv_priv *bat_priv) { struct batadv_hard_iface *primary_if; @@ -1514,13 +1581,13 @@ void batadv_bla_free(struct batadv_priv *bat_priv) } /** - * batadv_bla_rx + * batadv_bla_rx - check packets coming from the mesh. * @bat_priv: the bat priv with all the soft interface information * @skb: the frame to be checked * @vid: the VLAN ID of the frame * @is_bcast: the packet came in a broadcast packet type. * - * bla_rx avoidance checks if: + * batadv_bla_rx avoidance checks if: * * we have to race for a claim * * if the frame is allowed on the LAN * @@ -1610,12 +1677,12 @@ out: } /** - * batadv_bla_tx + * batadv_bla_tx - check packets going into the mesh * @bat_priv: the bat priv with all the soft interface information * @skb: the frame to be checked * @vid: the VLAN ID of the frame * - * bla_tx checks if: + * batadv_bla_tx checks if: * * a claim was received which has to be processed * * the frame is allowed on the mesh * @@ -1698,6 +1765,13 @@ out: return ret; } +/** + * batadv_bla_claim_table_seq_print_text - print the claim table in a seq file + * @seq: seq file to print on + * @offset: not used + * + * Return: always 0 + */ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; @@ -1747,6 +1821,14 @@ out: return 0; } +/** + * batadv_bla_backbone_table_seq_print_text - print the backbone table in a seq + * file + * @seq: seq file to print on + * @offset: not used + * + * Return: always 0 + */ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; -- cgit From fe13c2aadf208e6210ee125f550dcf725c48721b Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 17 Nov 2015 16:40:51 +0800 Subject: batman-adv: fix kerneldoc for DAT functions Signed-off-by: Antonio Quartulli --- net/batman-adv/distributed-arp-table.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 2f13429ce5d3..60df82385495 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -741,6 +741,8 @@ static void batadv_dat_hash_free(struct batadv_priv *bat_priv) /** * batadv_dat_init - initialise the DAT internals * @bat_priv: the bat priv with all the soft interface information + * + * Return: 0 in case of success, a negative error code otherwise */ int batadv_dat_init(struct batadv_priv *bat_priv) { @@ -779,6 +781,8 @@ void batadv_dat_free(struct batadv_priv *bat_priv) * batadv_dat_cache_seq_print_text - print the local DAT hash table * @seq: seq file to print on * @offset: not used + * + * Return: always 0 */ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) { -- cgit From d15cd6221c74027af005d5acbefa43f67ff3df37 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 17 Nov 2015 16:40:52 +0800 Subject: batman-adv: fix kerneldoc for TT functions Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index af1d24ce420f..9fcf6bf9fa11 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -69,9 +69,13 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, bool roaming); /** - * batadv_compare_tt + * batadv_compare_tt - check if two TT entries are the same + * @node: the list element pointer of the first TT entry + * @data2: pointer to the tt_common_entry of the second TT entry * - * Return: 1 if they are the same mac addr and vid + * Compare the MAC address and the VLAN ID of the two TT entries and check if + * they are the same TT client. + * Return: 1 if the two TT clients are the same, 0 otherwise */ static int batadv_compare_tt(const struct hlist_node *node, const void *data2) { @@ -221,6 +225,7 @@ batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) /** * batadv_tt_global_hash_count - count the number of orig entries + * @bat_priv: the bat priv with all the soft interface information * @addr: the mac address of the client to count entries for * @vid: VLAN identifier * @@ -289,8 +294,9 @@ static void batadv_tt_local_size_dec(struct batadv_priv *bat_priv, } /** - * batadv_tt_global_size_mod - change the size by v of the local table - * identified by vid + * batadv_tt_global_size_mod - change the size by v of the global table + * for orig_node identified by vid + * @orig_node: the originator for which the table has to be modified * @vid: the VLAN identifier * @v: the amount to sum to the global table size */ @@ -721,7 +727,6 @@ out: * function reserves the amount of space needed to send the entire global TT * table. In case of success the value is updated with the real amount of * reserved bytes - * Allocate the needed amount of memory for the entire TT TVLV and write its * header made up by one tvlv_tt_data object and a series of tvlv_tt_vlan_data * objects, one per active VLAN served by the originator node. @@ -1243,9 +1248,12 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv) } /** - * batadv_tt_global_orig_entry_find + * batadv_tt_global_orig_entry_find - find a TT orig_list_entry + * @entry: the TT global entry where the orig_list_entry has to be + * extracted from + * @orig_node: the originator for which the orig_list_entry has to be found * - * retrieves the orig_tt_list_entry belonging to orig_node from the + * retrieve the orig_tt_list_entry belonging to orig_node from the * batadv_tt_global_entry list * * Return: it with an increased refcounter, NULL if not found @@ -1274,7 +1282,10 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, } /** - * batadv_tt_global_entry_has_orig + * batadv_tt_global_entry_has_orig - check if a TT global entry is also handled + * by a given originator + * @entry: the TT global entry to check + * @orig_node: the originator to search in the list * * find out if an orig_node is already in the list of a tt_global_entry. * @@ -2519,6 +2530,8 @@ static void batadv_tt_global_update_crc(struct batadv_priv *bat_priv, * @num_vlan: number of tvlv VLAN entries * @full_table: ask for the entire translation table if true, while only for the * last TT diff otherwise + * + * Return: true if the TT Request was sent, false otherwise */ static int batadv_send_tt_request(struct batadv_priv *bat_priv, struct batadv_orig_node *dst_orig_node, @@ -3062,7 +3075,9 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) } /** - * batadv_tt_check_roam_count + * batadv_tt_check_roam_count - check if a client has roamed too frequently + * @bat_priv: the bat priv with all the soft interface information + * @client: mac address of the roaming client * * This function checks whether the client already reached the * maximum number of possible roaming phases. In this case the ROAMING_ADV -- cgit From a14c131d8c056397b34bfde63b398b712637d60f Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 17 Nov 2015 16:40:53 +0800 Subject: batman-adv: add kernel doc for AP isolation attributes in bat_priv Signed-off-by: Antonio Quartulli --- net/batman-adv/types.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 7f7a0f1eaf75..5e8c8df4c4ac 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -772,6 +772,9 @@ struct batadv_softif_vlan { * @orig_interval: OGM broadcast interval in milliseconds * @hop_penalty: penalty which will be applied to an OGM's tq-field on every hop * @log_level: configured log level (see batadv_dbg_level) + * @isolation_mark: the skb->mark value used to match packets for AP isolation + * @isolation_mark_mask: bitmask identifying the bits in skb->mark to be used + * for the isolation mark * @bcast_seqno: last sent broadcast packet sequence number * @bcast_queue_left: number of remaining buffered broadcast packet slots * @batman_queue_left: number of remaining OGM packet slots -- cgit From 600184b705ae040f5ff7442466d0ec2bbae5560c Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Mon, 23 Nov 2015 19:57:21 +0100 Subject: batman-adv: add kerneldoc for batadv_iv_ogm_aggr_packet Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bat_iv_ogm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index a6d389b0563c..7377313d3e42 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -396,7 +396,14 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv) return new_tq; } -/* is there another aggregated packet here? */ +/** + * batadv_iv_ogm_aggr_packet - checks if there is another OGM attached + * @buff_pos: current position in the skb + * @packet_len: total length of the skb + * @tvlv_len: tvlv length of the previously considered OGM + * + * Return: true if there is enough space for another OGM, false otherwise. + */ static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, __be16 tvlv_len) { -- cgit From ec9b83ca5fc1b39ed6e710b24484a272f9bcc3ae Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 5 Jan 2016 12:06:16 +0100 Subject: batman-adv: Fix kernel-doc for batadv_claim_free_ref Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/bridge_loop_avoidance.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 131aca049907..b3a72e29a167 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -165,7 +165,8 @@ static void batadv_claim_release(struct batadv_bla_claim *claim) } /** - * batadv_claim_free_rcu - free a claim + * batadv_claim_free_ref - decrement the claim refcounter and possibly + * release it * @claim: claim to be free'd */ static void batadv_claim_free_ref(struct batadv_bla_claim *claim) -- cgit From 0046b0402ac284a31940e3354614ac88c64881a3 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Fri, 1 Jan 2016 00:01:03 +0100 Subject: batman-adv: update copyright years for 2016 Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- net/batman-adv/Makefile | 2 +- net/batman-adv/bat_algo.h | 2 +- net/batman-adv/bat_iv_ogm.c | 2 +- net/batman-adv/bitarray.c | 2 +- net/batman-adv/bitarray.h | 2 +- net/batman-adv/bridge_loop_avoidance.c | 2 +- net/batman-adv/bridge_loop_avoidance.h | 2 +- net/batman-adv/debugfs.c | 2 +- net/batman-adv/debugfs.h | 2 +- net/batman-adv/distributed-arp-table.c | 2 +- net/batman-adv/distributed-arp-table.h | 2 +- net/batman-adv/fragmentation.c | 2 +- net/batman-adv/fragmentation.h | 2 +- net/batman-adv/gateway_client.c | 2 +- net/batman-adv/gateway_client.h | 2 +- net/batman-adv/gateway_common.c | 2 +- net/batman-adv/gateway_common.h | 2 +- net/batman-adv/hard-interface.c | 2 +- net/batman-adv/hard-interface.h | 2 +- net/batman-adv/hash.c | 2 +- net/batman-adv/hash.h | 2 +- net/batman-adv/icmp_socket.c | 2 +- net/batman-adv/icmp_socket.h | 2 +- net/batman-adv/main.c | 2 +- net/batman-adv/main.h | 2 +- net/batman-adv/multicast.c | 2 +- net/batman-adv/multicast.h | 2 +- net/batman-adv/network-coding.c | 2 +- net/batman-adv/network-coding.h | 2 +- net/batman-adv/originator.c | 2 +- net/batman-adv/originator.h | 2 +- net/batman-adv/packet.h | 2 +- net/batman-adv/routing.c | 2 +- net/batman-adv/routing.h | 2 +- net/batman-adv/send.c | 2 +- net/batman-adv/send.h | 2 +- net/batman-adv/soft-interface.c | 2 +- net/batman-adv/soft-interface.h | 2 +- net/batman-adv/sysfs.c | 2 +- net/batman-adv/sysfs.h | 2 +- net/batman-adv/translation-table.c | 2 +- net/batman-adv/translation-table.h | 2 +- net/batman-adv/types.h | 2 +- 43 files changed, 43 insertions(+), 43 deletions(-) diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index 21434ab79d2c..207e2af316c7 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +# Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: # # Marek Lindner, Simon Wunderlich # diff --git a/net/batman-adv/bat_algo.h b/net/batman-adv/bat_algo.h index 4e59cf3eb079..a7485d676088 100644 --- a/net/batman-adv/bat_algo.h +++ b/net/batman-adv/bat_algo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 7377313d3e42..3266bcb5bb06 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index 3404195f2561..b56bb000a0ab 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2016 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index 2b64d7a1bc9b..3e41bb80eb81 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2016 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index b3a72e29a167..779160934844 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors: * * Simon Wunderlich * diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index 7ea199b8b5ab..579f0fa6fe6a 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors: * * Simon Wunderlich * diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 0fc9df52f3d9..48253cf8341b 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h index 80ab8d6f0ab3..1ab4e2e63afc 100644 --- a/net/batman-adv/debugfs.h +++ b/net/batman-adv/debugfs.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 60df82385495..017fffe9a5b8 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index 26d4a525a798..813ecea96cf9 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2011-2016 B.A.T.M.A.N. contributors: * * Antonio Quartulli * diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 80eddf44a827..55656e84bc7e 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors: * * Martin Hundebøll * diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h index c5476fe79dc6..9ff77c7ef7c7 100644 --- a/net/batman-adv/fragmentation.h +++ b/net/batman-adv/fragmentation.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2013-2016 B.A.T.M.A.N. contributors: * * Martin Hundebøll * diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 83507750bb66..5950974de7b1 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index fa9527785ed3..582dd8c413c8 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c index b287448b9921..5ee04f7140af 100644 --- a/net/batman-adv/gateway_common.c +++ b/net/batman-adv/gateway_common.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h index ab893e318229..b58346350024 100644 --- a/net/batman-adv/gateway_common.h +++ b/net/batman-adv/gateway_common.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 49e05d238667..db90022c00a4 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index 7b12ea8ea29d..4d6b5e12331f 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c index 2ea6a18d793f..a0a0fdb85805 100644 --- a/net/batman-adv/hash.c +++ b/net/batman-adv/hash.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2016 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index 071a87ea4f2f..9bb57b87447c 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2006-2016 B.A.T.M.A.N. contributors: * * Simon Wunderlich, Marek Lindner * diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index bcabb5e3f4d3..a69da37bbad5 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/icmp_socket.h b/net/batman-adv/icmp_socket.h index e937143f0b10..618d5de06f20 100644 --- a/net/batman-adv/icmp_socket.h +++ b/net/batman-adv/icmp_socket.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 9d34be628304..5f319fd6ecd7 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 34f56efa2e4e..a7dc41a2709b 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index d984eee1776c..155565e0fecc 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2014-2016 B.A.T.M.A.N. contributors: * * Linus Lüssing * diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h index 685219f3fec9..80bceec55592 100644 --- a/net/batman-adv/multicast.h +++ b/net/batman-adv/multicast.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2014-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2014-2016 B.A.T.M.A.N. contributors: * * Linus Lüssing * diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 3a752bea55fa..0b30c15eee5f 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2016 B.A.T.M.A.N. contributors: * * Martin Hundebøll, Jeppe Ledet-Pedersen * diff --git a/net/batman-adv/network-coding.h b/net/batman-adv/network-coding.h index 8f6d4ad8778a..d6d7fb4ec5d5 100644 --- a/net/batman-adv/network-coding.h +++ b/net/batman-adv/network-coding.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2016 B.A.T.M.A.N. contributors: * * Martin Hundebøll, Jeppe Ledet-Pedersen * diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index f6ca4e509729..d4a30db0158a 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2009-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index cf0730414ed2..745b4e4fcdc4 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index fdb01637ad1f..e7f915181aba 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 1fb1be31bf3a..f4b60b1fb50e 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index 204bbe4952a6..c776e9655b9b 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index c188f4660981..d8b03fd604e0 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 3adc11fe1586..7ff95cada2e7 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 6c65de97126c..4bf35b8c3d23 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index 8e82176f40b1..d17cfbacf809 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index f38d7b75b0a5..964fc5986b2c 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/sysfs.h b/net/batman-adv/sysfs.h index 61974428a7af..c76021b4e198 100644 --- a/net/batman-adv/sysfs.h +++ b/net/batman-adv/sysfs.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2010-2016 B.A.T.M.A.N. contributors: * * Marek Lindner * diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 9fcf6bf9fa11..0dc8a5ca33bf 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich, Antonio Quartulli * diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index abd8e116e5fb..7c7e2c006bfe 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich, Antonio Quartulli * diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 5e8c8df4c4ac..8974bc0dc15c 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors: +/* Copyright (C) 2007-2016 B.A.T.M.A.N. contributors: * * Marek Lindner, Simon Wunderlich * -- cgit From 096676061987c613bdacddbae838cb63a815db94 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 2 Feb 2016 10:59:53 +0100 Subject: EDAC: Balance workqueue setup and teardown We use the ->edac_check function pointers to determine whether we need to setup a polling workqueue. However, the destroy path is not balanced and we might try to teardown an unitialized workqueue. Balance init and destroy paths by looking at ->edac_check in both cases. Set op_state to OP_OFFLINE *before* destroying anything. Reported-by: Zhiqiang Hou Cc: Varun Sethi Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 15 +++++++-------- drivers/edac/edac_pci.c | 8 +++----- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 8adfc167c2e3..50802c154915 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -583,8 +583,6 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) */ static void edac_mc_workq_teardown(struct mem_ctl_info *mci) { - mci->op_state = OP_OFFLINE; - edac_stop_work(&mci->work); } @@ -772,7 +770,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, } /* If there IS a check routine, then we are running POLLED */ - if (mci->edac_check != NULL) { + if (mci->edac_check) { /* This instance is NOW RUNNING */ mci->op_state = OP_RUNNING_POLL; @@ -823,15 +821,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) return NULL; } + /* mark MCI offline: */ + mci->op_state = OP_OFFLINE; + if (!del_mc_from_global_list(mci)) edac_mc_owner = NULL; - mutex_unlock(&mem_ctls_mutex); - /* flush workq processes */ - edac_mc_workq_teardown(mci); + mutex_unlock(&mem_ctls_mutex); - /* marking MCI offline */ - mci->op_state = OP_OFFLINE; + if (mci->edac_check) + edac_mc_workq_teardown(mci); /* remove from sysfs */ edac_remove_sysfs_mci_device(mci); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 99685388d3fb..f0e8c3d01ed5 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -241,8 +241,6 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) { edac_dbg(0, "\n"); - pci->op_state = OP_OFFLINE; - edac_stop_work(&pci->work); } @@ -289,7 +287,7 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) goto fail1; } - if (pci->edac_check != NULL) { + if (pci->edac_check) { pci->op_state = OP_RUNNING_POLL; edac_pci_workq_setup(pci, 1000); @@ -350,8 +348,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) mutex_unlock(&edac_pci_ctls_mutex); - /* stop the workq timer */ - edac_pci_workq_teardown(pci); + if (pci->edac_check) + edac_pci_workq_teardown(pci); edac_printk(KERN_INFO, EDAC_PCI, "Removed device %d for %s %s: DEV %s\n", -- cgit From 626a7a4dba2ad672b66b675f961de214f0ad0c74 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 2 Feb 2016 11:06:41 +0100 Subject: EDAC: Kill workqueue setup/teardown functions We have the generic wrappers now, use those. edac_pci_workq_setup() had an unused argument anyway. Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 43 ++++--------------------------------------- drivers/edac/edac_pci.c | 35 ++++------------------------------- 2 files changed, 8 insertions(+), 70 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 50802c154915..050493edb505 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -551,41 +551,6 @@ static void edac_mc_workq_function(struct work_struct *work_req) edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec())); } -/* - * edac_mc_workq_setup - * initialize a workq item for this mci - * passing in the new delay period in msec - * - * locking model: - * - * called with the mem_ctls_mutex held - */ -static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec) -{ - edac_dbg(0, "\n"); - - /* if this instance is not in the POLL state, then simply return */ - if (mci->op_state != OP_RUNNING_POLL) - return; - - INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function); - - edac_queue_work(&mci->work, msecs_to_jiffies(msec)); -} - -/* - * edac_mc_workq_teardown - * stop the workq processing on this mci - * - * locking model: - * - * called WITHOUT lock held - */ -static void edac_mc_workq_teardown(struct mem_ctl_info *mci) -{ - edac_stop_work(&mci->work); -} - /* * edac_mc_reset_delay_period(unsigned long value) * @@ -769,12 +734,12 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, goto fail1; } - /* If there IS a check routine, then we are running POLLED */ if (mci->edac_check) { - /* This instance is NOW RUNNING */ mci->op_state = OP_RUNNING_POLL; - edac_mc_workq_setup(mci, edac_mc_get_poll_msec()); + INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function); + edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec())); + } else { mci->op_state = OP_RUNNING_INTERRUPT; } @@ -830,7 +795,7 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) mutex_unlock(&mem_ctls_mutex); if (mci->edac_check) - edac_mc_workq_teardown(mci); + edac_stop_work(&mci->work); /* remove from sysfs */ edac_remove_sysfs_mci_device(mci); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index f0e8c3d01ed5..79945e0df0dc 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -215,35 +215,6 @@ static void edac_pci_workq_function(struct work_struct *work_req) mutex_unlock(&edac_pci_ctls_mutex); } -/* - * edac_pci_workq_setup() - * initialize a workq item for this edac_pci instance - * passing in the new delay period in msec - * - * locking model: - * called when 'edac_pci_ctls_mutex' is locked - */ -static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci, - unsigned int msec) -{ - edac_dbg(0, "\n"); - - INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); - - edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec())); -} - -/* - * edac_pci_workq_teardown() - * stop the workq processing on this edac_pci instance - */ -static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) -{ - edac_dbg(0, "\n"); - - edac_stop_work(&pci->work); -} - /* * edac_pci_alloc_index: Allocate a unique PCI index number * @@ -290,7 +261,9 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) if (pci->edac_check) { pci->op_state = OP_RUNNING_POLL; - edac_pci_workq_setup(pci, 1000); + INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function); + edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec())); + } else { pci->op_state = OP_RUNNING_INTERRUPT; } @@ -349,7 +322,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) mutex_unlock(&edac_pci_ctls_mutex); if (pci->edac_check) - edac_pci_workq_teardown(pci); + edac_stop_work(&pci->work); edac_printk(KERN_INFO, EDAC_PCI, "Removed device %d for %s %s: DEV %s\n", -- cgit From 06e912d4d4c2624c169997e26b3d7b5746735a14 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 2 Feb 2016 11:36:11 +0100 Subject: EDAC: Cleanup/sync workqueue functions They're both running only when ->edac_check is initialized so remove that check from the workqueue function itself. Synchronize/generalize the ->op_state check between the two. Kill useless comments, while at it. Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc.c | 8 +++----- drivers/edac/edac_pci.c | 30 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 050493edb505..1472f48c8ac6 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -535,19 +535,17 @@ static void edac_mc_workq_function(struct work_struct *work_req) mutex_lock(&mem_ctls_mutex); - /* if this control struct has movd to offline state, we are done */ - if (mci->op_state == OP_OFFLINE) { + if (mci->op_state != OP_RUNNING_POLL) { mutex_unlock(&mem_ctls_mutex); return; } - /* Only poll controllers that are running polled and have a check */ - if (edac_mc_assert_error_check_and_clear() && (mci->edac_check != NULL)) + if (edac_mc_assert_error_check_and_clear()) mci->edac_check(mci); mutex_unlock(&mem_ctls_mutex); - /* Reschedule */ + /* Queue ourselves again. */ edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec())); } diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 79945e0df0dc..8f2f2899a7a2 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -195,23 +195,23 @@ static void edac_pci_workq_function(struct work_struct *work_req) mutex_lock(&edac_pci_ctls_mutex); - if (pci->op_state == OP_RUNNING_POLL) { - /* we might be in POLL mode, but there may NOT be a poll func - */ - if ((pci->edac_check != NULL) && edac_pci_get_check_errors()) - pci->edac_check(pci); - - /* if we are on a one second period, then use round */ - msec = edac_pci_get_poll_msec(); - if (msec == 1000) - delay = round_jiffies_relative(msecs_to_jiffies(msec)); - else - delay = msecs_to_jiffies(msec); - - /* Reschedule only if we are in POLL mode */ - edac_queue_work(&pci->work, delay); + if (pci->op_state != OP_RUNNING_POLL) { + mutex_unlock(&edac_pci_ctls_mutex); + return; } + if (edac_pci_get_check_errors()) + pci->edac_check(pci); + + /* if we are on a one second period, then use round */ + msec = edac_pci_get_poll_msec(); + if (msec == 1000) + delay = round_jiffies_relative(msecs_to_jiffies(msec)); + else + delay = msecs_to_jiffies(msec); + + edac_queue_work(&pci->work, delay); + mutex_unlock(&edac_pci_ctls_mutex); } -- cgit From 875e94392ad2be9776c8325d3573160eb1455a2b Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 28 Jan 2016 19:24:02 +0200 Subject: wil6210: prevent access to vring_tx_data lock during its init wil_tx_vring locks the vring_tx_data lock before accessing the TX vring to check if it is enabled and valid for use. In case of quick disconnect / connect events for the same station, spin_lock(&txdata->lock) can be called during the lock initialization in the vring init function. To prevent such a race, the TX vrings spin lock should be initialized once during wil6210 driver initialization. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/main.c | 3 +++ drivers/net/wireless/ath/wil6210/txrx.c | 26 +++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 0652efed6b5d..712ebbfbdeb8 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -438,6 +438,9 @@ int wil_priv_init(struct wil6210_priv *wil) for (i = 0; i < WIL6210_MAX_CID; i++) spin_lock_init(&wil->sta[i].tid_rx_lock); + for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) + spin_lock_init(&wil->vring_tx_data[i].lock); + mutex_init(&wil->mutex); mutex_init(&wil->wmi_mutex); mutex_init(&wil->back_rx_mutex); diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 9680b970b863..6af20903cf89 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -717,6 +717,21 @@ void wil_rx_fini(struct wil6210_priv *wil) wil_vring_free(wil, vring, 0); } +static inline void wil_tx_data_init(struct vring_tx_data *txdata) +{ + spin_lock_bh(&txdata->lock); + txdata->dot1x_open = 0; + txdata->enabled = 0; + txdata->idle = 0; + txdata->last_idle = 0; + txdata->begin = 0; + txdata->agg_wsize = 0; + txdata->agg_timeout = 0; + txdata->agg_amsdu = 0; + txdata->addba_in_progress = false; + spin_unlock_bh(&txdata->lock); +} + int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, int cid, int tid) { @@ -758,8 +773,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, goto out; } - memset(txdata, 0, sizeof(*txdata)); - spin_lock_init(&txdata->lock); + wil_tx_data_init(txdata); vring->size = size; rc = wil_vring_alloc(wil, vring); if (rc) @@ -791,8 +805,10 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, return 0; out_free: + spin_lock_bh(&txdata->lock); txdata->dot1x_open = false; txdata->enabled = 0; + spin_unlock_bh(&txdata->lock); wil_vring_free(wil, vring, 1); wil->vring2cid_tid[id][0] = WIL6210_MAX_CID; wil->vring2cid_tid[id][1] = 0; @@ -834,8 +850,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) goto out; } - memset(txdata, 0, sizeof(*txdata)); - spin_lock_init(&txdata->lock); + wil_tx_data_init(txdata); vring->size = size; rc = wil_vring_alloc(wil, vring); if (rc) @@ -865,8 +880,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) return 0; out_free: + spin_lock_bh(&txdata->lock); txdata->enabled = 0; txdata->dot1x_open = false; + spin_unlock_bh(&txdata->lock); wil_vring_free(wil, vring, 1); out: @@ -894,7 +911,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) napi_synchronize(&wil->napi_tx); wil_vring_free(wil, vring, 1); - memset(txdata, 0, sizeof(*txdata)); } static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, -- cgit From 78771d76f826202012201d700028a2d866d03fb3 Mon Sep 17 00:00:00 2001 From: Vladimir Kondratiev Date: Thu, 28 Jan 2016 19:24:03 +0200 Subject: wil6210: wait for disconnect completion cfg80211_ops.disconnect() should wait for disconnect flow to complete. If it does not, internal state becomes out of sync with one in cfg80211. If one does stress test connect/disconnect sequence, cfg80211 will issue next connect before disconnect completed internally. Signed-off-by: Vladimir Kondratiev Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/cfg80211.c | 13 ++++++++++++- drivers/net/wireless/ath/wil6210/main.c | 28 +++++++++------------------- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 774352f9e256..97ad91eef4a6 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -535,7 +535,18 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code); - rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); + if (!(test_bit(wil_status_fwconnecting, wil->status) || + test_bit(wil_status_fwconnected, wil->status))) { + wil_err(wil, "%s: Disconnect was called while disconnected\n", + __func__); + return 0; + } + + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, + WMI_DISCONNECT_EVENTID, NULL, 0, + WIL6210_DISCONNECT_TO_MS); + if (rc) + wil_err(wil, "%s: disconnect error %d\n", __func__, rc); return rc; } diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 712ebbfbdeb8..78ba6e04c944 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -23,9 +23,6 @@ #include "wmi.h" #include "boot_loader.h" -#define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000 -#define WAIT_FOR_DISCONNECT_INTERVAL_MS 10 - bool debug_fw; /* = false; */ module_param(debug_fw, bool, S_IRUGO); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); @@ -942,8 +939,7 @@ int wil_up(struct wil6210_priv *wil) int __wil_down(struct wil6210_priv *wil) { - int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS / - WAIT_FOR_DISCONNECT_INTERVAL_MS; + int rc; WARN_ON(!mutex_is_locked(&wil->mutex)); @@ -967,22 +963,16 @@ int __wil_down(struct wil6210_priv *wil) } if (test_bit(wil_status_fwconnected, wil->status) || - test_bit(wil_status_fwconnecting, wil->status)) - wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); + test_bit(wil_status_fwconnecting, wil->status)) { - /* make sure wil is idle (not connected) */ - mutex_unlock(&wil->mutex); - while (iter--) { - int idle = !test_bit(wil_status_fwconnected, wil->status) && - !test_bit(wil_status_fwconnecting, wil->status); - if (idle) - break; - msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS); + mutex_unlock(&wil->mutex); + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0, + WMI_DISCONNECT_EVENTID, NULL, 0, + WIL6210_DISCONNECT_TO_MS); + mutex_lock(&wil->mutex); + if (rc) + wil_err(wil, "timeout waiting for disconnect\n"); } - mutex_lock(&wil->mutex); - - if (iter < 0) - wil_err(wil, "timeout waiting for idle FW/HW\n"); wil_reset(wil, false); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 1b8fa1d2bae9..950296507dd1 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -92,6 +92,7 @@ static inline u32 wil_mtu2macbuf(u32 mtu) #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) #define WIL6210_SCAN_TO msecs_to_jiffies(10000) +#define WIL6210_DISCONNECT_TO_MS (2000) #define WIL6210_RX_HIGH_TRSH_INIT (0) #define WIL6210_RX_HIGH_TRSH_DEFAULT \ (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) -- cgit From fe5c271e2878fb080f1b32fec5b4e3f7a6070152 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Thu, 28 Jan 2016 19:24:04 +0200 Subject: wil6210: protect synchronous wmi commands handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case there are multiple WMI commands with the same reply_id, the following scenario can occur: - Driver sends the first command to the device - The reply didn’t get on time and there is timeout - Reply_id, reply_buf and reply_size are set to 0 - Driver sends second wmi command with the same reply_id as the first - Driver sets wil->reply_id - Reply for the first wmi command arrives and handled by wmi_recv_cmd - As its ID fits the reply_id but the reply_buf is not set yet it is handled as a reply with event handler, and WARN_ON is printed This patch guarantee atomic setting of all the reply variables and prevents the above scenario. Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/wmi.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index e1a6cb8840ed..493e721c4fa7 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -838,6 +838,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi; u16 id = le16_to_cpu(wmi->id); u32 tstamp = le32_to_cpu(wmi->timestamp); + spin_lock_irqsave(&wil->wmi_ev_lock, flags); if (wil->reply_id && wil->reply_id == id) { if (wil->reply_buf) { memcpy(wil->reply_buf, wmi, @@ -845,6 +846,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) immed_reply = true; } } + spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n", id, wmi->mid, tstamp); @@ -888,13 +890,16 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, mutex_lock(&wil->wmi_mutex); + spin_lock(&wil->wmi_ev_lock); + wil->reply_id = reply_id; + wil->reply_buf = reply; + wil->reply_size = reply_size; + spin_unlock(&wil->wmi_ev_lock); + rc = __wmi_send(wil, cmdid, buf, len); if (rc) goto out; - wil->reply_id = reply_id; - wil->reply_buf = reply; - wil->reply_size = reply_size; remain = wait_for_completion_timeout(&wil->wmi_call, msecs_to_jiffies(to_msec)); if (0 == remain) { @@ -907,10 +912,14 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, cmdid, reply_id, to_msec - jiffies_to_msecs(remain)); } + +out: + spin_lock(&wil->wmi_ev_lock); wil->reply_id = 0; wil->reply_buf = NULL; wil->reply_size = 0; - out: + spin_unlock(&wil->wmi_ev_lock); + mutex_unlock(&wil->wmi_mutex); return rc; -- cgit From ee5dfe0d240e21afe63bdd77bf1d4a386203aa6e Mon Sep 17 00:00:00 2001 From: Hamad Kadmany Date: Thu, 28 Jan 2016 19:24:05 +0200 Subject: wil6210: TX vring optimization Tx vring needs to be enlarged to get better performance for traffic over 2Gbps. Signed-off-by: Hamad Kadmany Signed-off-by: Maya Erez Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/wil6210/debugfs.c | 6 +++--- drivers/net/wireless/ath/wil6210/wil6210.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 97bc186f9728..98c9148a3450 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 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 @@ -68,13 +68,13 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, seq_puts(s, "???\n"); } - if (vring->va && (vring->size < 1025)) { + if (vring->va && (vring->size <= (1 << WIL_RING_SIZE_ORDER_MAX))) { uint i; for (i = 0; i < vring->size; i++) { volatile struct vring_tx_desc *d = &vring->va[i].tx; - if ((i % 64) == 0 && (i != 0)) + if ((i % 128) == 0 && (i != 0)) seq_puts(s, "\n"); seq_printf(s, "%c", (d->dma.status & BIT(0)) ? _s : (vring->ctx[i].skb ? _h : 'h')); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 950296507dd1..8427d68b6fa8 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -51,7 +51,7 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) #define WIL_TX_Q_LEN_DEFAULT (4000) #define WIL_RX_RING_SIZE_ORDER_DEFAULT (10) -#define WIL_TX_RING_SIZE_ORDER_DEFAULT (10) +#define WIL_TX_RING_SIZE_ORDER_DEFAULT (12) #define WIL_BCAST_RING_SIZE_ORDER_DEFAULT (7) #define WIL_BCAST_MCS0_LIMIT (1024) /* limit for MCS0 frame size */ /* limit ring size in range [32..32k] */ -- cgit From 0b3d76e9f8b4a2b67358b454843ede30555f93a5 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:07 -0800 Subject: ath10k: rename Mesh related service names WMI_10_4_SERVICE_MESH bit is for non IEEE802.11s Mesh. Hence rename it to WMI_10_4_SERVICE_MESH_NON_11S. Also add _11S as post-fix to each of WMI_SERVICE_MESH and WMI_VDEV_SUBTYPE_MESH specifying the service is for 11s Mesh. This will help users to distinguish 11s Mesh from non 11s Mesh. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 4 ++-- drivers/net/wireless/ath/ath10k/wmi.h | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ef0438d2cc8f..1406b0f1d883 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4380,8 +4380,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->vdev_type = WMI_VDEV_TYPE_IBSS; break; case NL80211_IFTYPE_MESH_POINT: - if (test_bit(WMI_SERVICE_MESH, ar->wmi.svc_map)) { - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH; + if (test_bit(WMI_SERVICE_MESH_11S, ar->wmi.svc_map)) { + arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { ret = -EINVAL; ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 806d4bb6e7d6..0458bf6bcdfc 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -176,7 +176,8 @@ enum wmi_service { WMI_SERVICE_AUX_CHAN_LOAD_INTF, WMI_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_EXT_RES_CFG_SUPPORT, - WMI_SERVICE_MESH, + WMI_SERVICE_MESH_11S, + WMI_SERVICE_MESH_NON_11S, WMI_SERVICE_PEER_STATS, /* keep last */ @@ -296,7 +297,7 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF, WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, - WMI_10_4_SERVICE_MESH, + WMI_10_4_SERVICE_MESH_NON_11S, }; static inline char *wmi_service_name(int service_id) @@ -387,7 +388,8 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF); SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT); - SVCSTR(WMI_SERVICE_MESH); + SVCSTR(WMI_SERVICE_MESH_11S); + SVCSTR(WMI_SERVICE_MESH_NON_11S); SVCSTR(WMI_SERVICE_PEER_STATS); default: return NULL; @@ -463,7 +465,7 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out, SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_BSS_CHANNEL_INFO_64, len); SVCMAP(WMI_10X_SERVICE_MESH, - WMI_SERVICE_MESH, len); + WMI_SERVICE_MESH_11S, len); SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); SVCMAP(WMI_10X_SERVICE_PEER_STATS, @@ -628,8 +630,8 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_BSS_CHANNEL_INFO_64, len); SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); - SVCMAP(WMI_10_4_SERVICE_MESH, - WMI_SERVICE_MESH, len); + SVCMAP(WMI_10_4_SERVICE_MESH_NON_11S, + WMI_SERVICE_MESH_NON_11S, len); } #undef SVCMAP @@ -4287,7 +4289,7 @@ enum wmi_vdev_subtype { WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, WMI_VDEV_SUBTYPE_P2P_GO = 3, WMI_VDEV_SUBTYPE_PROXY_STA = 4, - WMI_VDEV_SUBTYPE_MESH = 5, + WMI_VDEV_SUBTYPE_MESH_11S = 5, }; /* values for vdev_subtype */ -- cgit From e70e9ba9df8609908c34d042cf980c1a59c56900 Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:08 -0800 Subject: ath10k: update 10.4 WMI service map Update 10.4 WMI service map to sync to the latest 10.4 firmware as of 1/20/2016. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/wmi.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 0458bf6bcdfc..031018a07231 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -179,6 +179,7 @@ enum wmi_service { WMI_SERVICE_MESH_11S, WMI_SERVICE_MESH_NON_11S, WMI_SERVICE_PEER_STATS, + WMI_SERVICE_RESTRT_CHNL_SUPPORT, /* keep last */ WMI_SERVICE_MAX, @@ -298,6 +299,9 @@ enum wmi_10_4_service { WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT, WMI_10_4_SERVICE_MESH_NON_11S, + WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, + WMI_10_4_SERVICE_PEER_STATS, + WMI_10_4_SERVICE_MESH_11S, }; static inline char *wmi_service_name(int service_id) @@ -391,6 +395,7 @@ static inline char *wmi_service_name(int service_id) SVCSTR(WMI_SERVICE_MESH_11S); SVCSTR(WMI_SERVICE_MESH_NON_11S); SVCSTR(WMI_SERVICE_PEER_STATS); + SVCSTR(WMI_SERVICE_RESTRT_CHNL_SUPPORT); default: return NULL; } @@ -632,6 +637,12 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out, WMI_SERVICE_EXT_RES_CFG_SUPPORT, len); SVCMAP(WMI_10_4_SERVICE_MESH_NON_11S, WMI_SERVICE_MESH_NON_11S, len); + SVCMAP(WMI_10_4_SERVICE_RESTRT_CHNL_SUPPORT, + WMI_SERVICE_RESTRT_CHNL_SUPPORT, len); + SVCMAP(WMI_10_4_SERVICE_PEER_STATS, + WMI_SERVICE_PEER_STATS, len); + SVCMAP(WMI_10_4_SERVICE_MESH_11S, + WMI_SERVICE_MESH_11S, len); } #undef SVCMAP -- cgit From 08c27be1db84dcdad14e86ec76d9c9915deb14eb Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:09 -0800 Subject: ath10k: use vif->type and vif->p2p for P2P_GO check Interface type P2P_GO can be checked by either arvif->vdev_type and arvif->vdev_subtype or vif->type and vif->p2p. Use later one to avoid more cpu consumption that could happen when subtype abstraction layer change is introduced. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 8 ++------ drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 1406b0f1d883..addf3cb3aeb1 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1358,10 +1358,7 @@ static int ath10k_mac_setup_bcn_p2p_ie(struct ath10k_vif *arvif, const u8 *p2p_ie; int ret; - if (arvif->vdev_type != WMI_VDEV_TYPE_AP) - return 0; - - if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + if (arvif->vif->type != NL80211_IFTYPE_AP || !arvif->vif->p2p) return 0; mgmt = (void *)bcn->data; @@ -3259,8 +3256,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); /* This is case only for P2P_GO */ - if (arvif->vdev_type != WMI_VDEV_TYPE_AP || - arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + if (vif->type != NL80211_IFTYPE_AP || !vif->p2p) return; if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 0f01a8d99604..5158716d6dff 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -3196,7 +3196,7 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, struct sk_buff *bcn, const struct wmi_p2p_noa_info *noa) { - if (arvif->vdev_subtype != WMI_VDEV_SUBTYPE_P2P_GO) + if (!arvif->vif->p2p) return; ath10k_dbg(ar, ATH10K_DBG_MGMT, "noa changed: %d\n", noa->changed); -- cgit From 6e4de1a49aa3254f46f66db5aac530707c193cde Mon Sep 17 00:00:00 2001 From: Peter Oh Date: Thu, 28 Jan 2016 13:54:10 -0800 Subject: ath10k: add abstraction layer for vdev subtype Abstraction layer for vdev subtype is added to solve subtype mismatch and to give flexible compatibility among different firmware revisions. For instance, 10.2 and 10.4 firmware has different definition of their vdev subtypes for Mesh. 10.4 defined subtype 6 for 802.11s Mesh while 10.2 uses 5. Hence use the abstraction API to get right subtype to use. Signed-off-by: Peter Oh Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/mac.c | 15 ++++--- drivers/net/wireless/ath/ath10k/wmi-ops.h | 11 +++++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 1 + drivers/net/wireless/ath/ath10k/wmi.c | 70 +++++++++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/wmi.h | 42 ++++++++++++++++--- 5 files changed, 128 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index addf3cb3aeb1..96e2f8ad22fc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4359,25 +4359,29 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, bit, ar->free_vdev_map); arvif->vdev_id = bit; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; + arvif->vdev_subtype = + ath10k_wmi_get_vdev_subtype(ar, WMI_VDEV_SUBTYPE_NONE); switch (vif->type) { case NL80211_IFTYPE_P2P_DEVICE: arvif->vdev_type = WMI_VDEV_TYPE_STA; - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_P2P_DEVICE); break; case NL80211_IFTYPE_UNSPECIFIED: case NL80211_IFTYPE_STATION: arvif->vdev_type = WMI_VDEV_TYPE_STA; if (vif->p2p) - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_CLIENT; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_P2P_CLIENT); break; case NL80211_IFTYPE_ADHOC: arvif->vdev_type = WMI_VDEV_TYPE_IBSS; break; case NL80211_IFTYPE_MESH_POINT: if (test_bit(WMI_SERVICE_MESH_11S, ar->wmi.svc_map)) { - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_MESH_11S); } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { ret = -EINVAL; ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); @@ -4389,7 +4393,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->vdev_type = WMI_VDEV_TYPE_AP; if (vif->p2p) - arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_GO; + arvif->vdev_subtype = ath10k_wmi_get_vdev_subtype + (ar, WMI_VDEV_SUBTYPE_P2P_GO); break; case NL80211_IFTYPE_MONITOR: arvif->vdev_type = WMI_VDEV_TYPE_MONITOR; diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index 8f4f6a892581..32ab34edceb5 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -186,6 +186,8 @@ struct wmi_ops { u8 enable, u32 detect_level, u32 detect_margin); + int (*get_vdev_subtype)(struct ath10k *ar, + enum wmi_vdev_subtype subtype); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1327,4 +1329,13 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); } +static inline int +ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype) +{ + if (!ar->wmi.ops->get_vdev_subtype) + return -EOPNOTSUPP; + + return ar->wmi.ops->get_vdev_subtype(ar, subtype); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 3b3a27b859f3..108593202052 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3483,6 +3483,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, }; static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 5158716d6dff..04799c73ebc8 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -7413,6 +7413,71 @@ unlock: buf[len] = 0; } +int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_VDEV_SUBTYPE_LEGACY_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_VDEV_SUBTYPE_LEGACY_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return -ENOTSUPP; + } + return -ENOTSUPP; +} + +static int ath10k_wmi_10_2_4_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_VDEV_SUBTYPE_10_2_4_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_VDEV_SUBTYPE_10_2_4_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + return WMI_VDEV_SUBTYPE_10_2_4_MESH_11S; + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return -ENOTSUPP; + } + return -ENOTSUPP; +} + +static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype) +{ + switch (subtype) { + case WMI_VDEV_SUBTYPE_NONE: + return WMI_VDEV_SUBTYPE_10_4_NONE; + case WMI_VDEV_SUBTYPE_P2P_DEVICE: + return WMI_VDEV_SUBTYPE_10_4_P2P_DEV; + case WMI_VDEV_SUBTYPE_P2P_CLIENT: + return WMI_VDEV_SUBTYPE_10_4_P2P_CLI; + case WMI_VDEV_SUBTYPE_P2P_GO: + return WMI_VDEV_SUBTYPE_10_4_P2P_GO; + case WMI_VDEV_SUBTYPE_PROXY_STA: + return WMI_VDEV_SUBTYPE_10_4_PROXY_STA; + case WMI_VDEV_SUBTYPE_MESH_11S: + return WMI_VDEV_SUBTYPE_10_4_MESH_11S; + case WMI_VDEV_SUBTYPE_MESH_NON_11S: + return WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S; + } + return -ENOTSUPP; +} + static const struct wmi_ops wmi_ops = { .rx = ath10k_wmi_op_rx, .map_svc = wmi_main_svc_map, @@ -7472,6 +7537,7 @@ static const struct wmi_ops wmi_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_main_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -7539,6 +7605,7 @@ static const struct wmi_ops wmi_10_1_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_10x_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -7607,6 +7674,7 @@ static const struct wmi_ops wmi_10_2_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_10x_op_fw_stats_fill, + .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, /* .gen_pdev_enable_adaptive_cca not implemented */ }; @@ -7673,6 +7741,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill, .gen_pdev_enable_adaptive_cca = ath10k_wmi_op_gen_pdev_enable_adaptive_cca, + .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype, /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ @@ -7739,6 +7808,7 @@ static const struct wmi_ops wmi_10_4_ops = { /* shared with 10.2 */ .gen_request_stats = ath10k_wmi_op_gen_request_stats, .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature, + .get_vdev_subtype = ath10k_wmi_10_4_op_get_vdev_subtype, }; int ath10k_wmi_attach(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 031018a07231..049c61820765 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4295,12 +4295,40 @@ enum wmi_vdev_type { }; enum wmi_vdev_subtype { - WMI_VDEV_SUBTYPE_NONE = 0, - WMI_VDEV_SUBTYPE_P2P_DEVICE = 1, - WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, - WMI_VDEV_SUBTYPE_P2P_GO = 3, - WMI_VDEV_SUBTYPE_PROXY_STA = 4, - WMI_VDEV_SUBTYPE_MESH_11S = 5, + WMI_VDEV_SUBTYPE_NONE, + WMI_VDEV_SUBTYPE_P2P_DEVICE, + WMI_VDEV_SUBTYPE_P2P_CLIENT, + WMI_VDEV_SUBTYPE_P2P_GO, + WMI_VDEV_SUBTYPE_PROXY_STA, + WMI_VDEV_SUBTYPE_MESH_11S, + WMI_VDEV_SUBTYPE_MESH_NON_11S, +}; + +enum wmi_vdev_subtype_legacy { + WMI_VDEV_SUBTYPE_LEGACY_NONE = 0, + WMI_VDEV_SUBTYPE_LEGACY_P2P_DEV = 1, + WMI_VDEV_SUBTYPE_LEGACY_P2P_CLI = 2, + WMI_VDEV_SUBTYPE_LEGACY_P2P_GO = 3, + WMI_VDEV_SUBTYPE_LEGACY_PROXY_STA = 4, +}; + +enum wmi_vdev_subtype_10_2_4 { + WMI_VDEV_SUBTYPE_10_2_4_NONE = 0, + WMI_VDEV_SUBTYPE_10_2_4_P2P_DEV = 1, + WMI_VDEV_SUBTYPE_10_2_4_P2P_CLI = 2, + WMI_VDEV_SUBTYPE_10_2_4_P2P_GO = 3, + WMI_VDEV_SUBTYPE_10_2_4_PROXY_STA = 4, + WMI_VDEV_SUBTYPE_10_2_4_MESH_11S = 5, +}; + +enum wmi_vdev_subtype_10_4 { + WMI_VDEV_SUBTYPE_10_4_NONE = 0, + WMI_VDEV_SUBTYPE_10_4_P2P_DEV = 1, + WMI_VDEV_SUBTYPE_10_4_P2P_CLI = 2, + WMI_VDEV_SUBTYPE_10_4_P2P_GO = 3, + WMI_VDEV_SUBTYPE_10_4_PROXY_STA = 4, + WMI_VDEV_SUBTYPE_10_4_MESH_NON_11S = 5, + WMI_VDEV_SUBTYPE_10_4_MESH_11S = 6, }; /* values for vdev_subtype */ @@ -6471,5 +6499,7 @@ size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); +int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar, + enum wmi_vdev_subtype subtype); #endif /* _WMI_H_ */ -- cgit From b1a958c933c5b0f967844ec05e76ec2985450782 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 29 Jan 2016 16:35:11 +0530 Subject: ath10k: add qca4019 hw params Add a new entry in hw_params_list for qca4019 with list of it's own details. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 20 ++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 8 ++++++++ drivers/net/wireless/ath/ath10k/targaddrs.h | 3 +++ 3 files changed, 31 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 1f4a27881936..79043872e7ac 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -201,6 +201,26 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, }, }, + { + .id = QCA4019_HW_1_0_DEV_VERSION, + .dev_id = 0, + .name = "qca4019 hw1.0", + .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, + .uart_pin = 7, + .otp_exe_param = 0x0010000, + .continuous_frag_desc = true, + .channel_counters_freq_hz = 125000, + .max_probe_resp_desc_thres = 24, + .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, + .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, + }, + }, }; static const char *const ath10k_core_fw_feature_str[] = { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 4217bdbe9f01..291ca1f798e3 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -106,6 +106,14 @@ enum qca9377_chip_id_rev { #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 + #define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin" diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h index 05a421bc322a..361f143b019c 100644 --- a/drivers/net/wireless/ath/ath10k/targaddrs.h +++ b/drivers/net/wireless/ath/ath10k/targaddrs.h @@ -456,4 +456,7 @@ Fw Mode/SubMode Mask #define QCA99X0_BOARD_DATA_SZ 12288 #define QCA99X0_BOARD_EXT_DATA_SZ 0 +#define QCA4019_BOARD_DATA_SZ 12064 +#define QCA4019_BOARD_EXT_DATA_SZ 0 + #endif /* __TARGADDRS_H__ */ -- cgit From 5699a6f238ebfc8a6be3963a30d86d6f1e8aaaf9 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 29 Jan 2016 16:35:12 +0530 Subject: ath10k: populate qca4019 fw specific wmi init params Some of the parameter like tx/rx chain mask, number of htt tx desc, qcache active peer count, etc goes via wmi init cmd to qca4019 firmware are different. To make use of 10.4 gen_init function for qca4019, change wmi service ready handler and 10.4 wmi init functions to adapt qca4019 specific init values. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath10k/core.c | 14 ++++++++++++-- drivers/net/wireless/ath/ath10k/core.h | 6 ++++++ drivers/net/wireless/ath/ath10k/hw.h | 6 ------ drivers/net/wireless/ath/ath10k/wmi.c | 12 ++++++------ drivers/net/wireless/ath/ath10k/wmi.h | 1 - 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 79043872e7ac..4d3176492ae7 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -156,6 +156,11 @@ 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, .fw = { .dir = QCA99X0_HW_2_0_FW_DIR, .fw = QCA99X0_HW_2_0_FW_FILE, @@ -212,6 +217,11 @@ 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, .fw = { .dir = QCA4019_HW_1_0_FW_DIR, .fw = QCA4019_HW_1_0_FW_FILE, @@ -1523,9 +1533,9 @@ 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 = TARGET_10_4_NUM_MSDU_DESC; + ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc; ar->fw_stats_req_mask = WMI_STAT_PEER; - ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM; + ar->max_spatial_stream = ar->hw_params.max_spatial_stream; 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 2e411b5258c2..a62b62a62266 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -680,6 +680,12 @@ 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; + struct ath10k_hw_params_fw { const char *dir; const char *fw; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 291ca1f798e3..2dece8db83f8 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -426,16 +426,11 @@ 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_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_AST_SKID_LIMIT 32 -#define TARGET_10_4_TX_CHAIN_MASK (BIT(0) | BIT(1) | \ - BIT(2) | BIT(3)) -#define TARGET_10_4_RX_CHAIN_MASK (BIT(0) | BIT(1) | \ - BIT(2) | BIT(3)) /* 100 ms for video, best-effort, and background */ #define TARGET_10_4_RX_TIMEOUT_LO_PRI 100 @@ -461,7 +456,6 @@ enum ath10k_hw_4addr_pad { #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1 #define TARGET_10_4_VOW_CONFIG 0 #define TARGET_10_4_GTK_OFFLOAD_MAX_VDEV 3 -#define TARGET_10_4_NUM_MSDU_DESC (1024 + 400) #define TARGET_10_4_11AC_TX_MAX_FRAGS 2 #define TARGET_10_4_MAX_PEER_EXT_STATS 16 #define TARGET_10_4_SMART_ANT_CAP 0 diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 04799c73ebc8..1ce67423224a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4618,9 +4618,9 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX + - TARGET_10_4_NUM_VDEVS; - ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS + - TARGET_10_4_NUM_VDEVS; + 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; } @@ -5602,8 +5602,8 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) __cpu_to_le32(TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS); config.num_peer_keys = __cpu_to_le32(TARGET_10_4_NUM_PEER_KEYS); config.ast_skid_limit = __cpu_to_le32(TARGET_10_4_AST_SKID_LIMIT); - config.tx_chain_mask = __cpu_to_le32(TARGET_10_4_TX_CHAIN_MASK); - config.rx_chain_mask = __cpu_to_le32(TARGET_10_4_RX_CHAIN_MASK); + config.tx_chain_mask = __cpu_to_le32(ar->hw_params.tx_chain_mask); + config.rx_chain_mask = __cpu_to_le32(ar->hw_params.rx_chain_mask); config.rx_timeout_pri[0] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); config.rx_timeout_pri[1] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI); @@ -5634,7 +5634,7 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar) config.vow_config = __cpu_to_le32(TARGET_10_4_VOW_CONFIG); config.gtk_offload_max_vdev = __cpu_to_le32(TARGET_10_4_GTK_OFFLOAD_MAX_VDEV); - config.num_msdu_desc = __cpu_to_le32(TARGET_10_4_NUM_MSDU_DESC); + config.num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx); config.max_frag_entries = __cpu_to_le32(TARGET_10_4_11AC_TX_MAX_FRAGS); config.max_peer_ext_stats = __cpu_to_le32(TARGET_10_4_MAX_PEER_EXT_STATS); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 049c61820765..4d3cbc44fcd2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -1818,7 +1818,6 @@ enum wmi_channel_change_cause { #define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13) #define WMI_MAX_SPATIAL_STREAM 3 /* default max ss */ -#define WMI_10_4_MAX_SPATIAL_STREAM 4 /* HT Capabilities*/ #define WMI_HT_CAP_ENABLED 0x0001 /* HT Enabled/ disabled */ -- cgit From 842096fc40519e85bd4c0751e65a07cc3e23bd66 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:49:32 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue with nvt_enable_cir nvt_enable_cir calls nvt_enable_logical_dev (that may sleep) while holding a spinlock. This patch fixes this and moves the content of nvt_enable_cir to nvt_open as this is the only caller. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index d428b4e6e26f..46a9ece66f75 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -942,23 +942,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) return IRQ_HANDLED; } -static void nvt_enable_cir(struct nvt_dev *nvt) -{ - /* set function enable flags */ - nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | - CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, - CIR_IRCON); - - /* enable the CIR logical device */ - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); - - /* clear all pending interrupts */ - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); - - /* enable interrupts */ - nvt_set_cir_iren(nvt); -} - static void nvt_disable_cir(struct nvt_dev *nvt) { /* disable CIR interrupts */ @@ -984,9 +967,23 @@ static int nvt_open(struct rc_dev *dev) unsigned long flags; spin_lock_irqsave(&nvt->nvt_lock, flags); - nvt_enable_cir(nvt); + + /* set function enable flags */ + nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | + CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, + CIR_IRCON); + + /* clear all pending interrupts */ + nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); + + /* enable interrupts */ + nvt_set_cir_iren(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* enable the CIR logical device */ + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR); + return 0; } -- cgit From b883af30bcd1f37ed39948be529a13f5ac4ec6a2 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:50:26 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue when calling nvt_enable_wake nvt_enable_wake calls nvt_select_logical_dev (that may sleep) and is called from contexts holding a spinlock. Fix this. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 46a9ece66f75..efff08a37d4d 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -503,6 +503,8 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) static void nvt_enable_wake(struct nvt_dev *nvt) { + unsigned long flags; + nvt_efm_enable(nvt); nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); @@ -514,12 +516,16 @@ static void nvt_enable_wake(struct nvt_dev *nvt) nvt_efm_disable(nvt); + spin_lock_irqsave(&nvt->nvt_lock, flags); + nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); + + spin_unlock_irqrestore(&nvt->nvt_lock, flags); } #if 0 /* Currently unused */ @@ -1152,9 +1158,10 @@ static void nvt_remove(struct pnp_dev *pdev) /* disable CIR */ nvt_cir_reg_write(nvt, 0, CIR_IREN); nvt_disable_cir(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); rc_unregister_device(nvt->rdev); } @@ -1179,14 +1186,14 @@ static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) /* disable all CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* disable cir logical dev */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); /* make sure wake is enabled */ nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); - return 0; } @@ -1205,11 +1212,8 @@ static int nvt_resume(struct pnp_dev *pdev) static void nvt_shutdown(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_enable_wake(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } static const struct pnp_device_id nvt_ids[] = { -- cgit From 137aa3617b3e7e780800855cdc5d3258aa0ea8d9 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 1 Feb 2016 18:50:55 -0200 Subject: [media] rc/nuvoton_cir: fix locking issue when calling nvt_disable_cir nvt_disable_cir calls nvt_disable_logical_dev (that may sleep) and is called from contexts holding a spinlock. Fix this and remove the unneeded clearing of CIR_IREN as this is done in nvt_cir_disable already. Signed-off-by: Heiner Kallweit Signed-off-by: Mauro Carvalho Chehab --- drivers/media/rc/nuvoton-cir.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index efff08a37d4d..c96da3aaf00b 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -950,6 +950,10 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) static void nvt_disable_cir(struct nvt_dev *nvt) { + unsigned long flags; + + spin_lock_irqsave(&nvt->nvt_lock, flags); + /* disable CIR interrupts */ nvt_cir_reg_write(nvt, 0, CIR_IREN); @@ -963,6 +967,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt) nvt_clear_cir_fifo(nvt); nvt_clear_tx_fifo(nvt); + spin_unlock_irqrestore(&nvt->nvt_lock, flags); + /* disable the CIR logical device */ nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR); } @@ -996,11 +1002,8 @@ static int nvt_open(struct rc_dev *dev) static void nvt_close(struct rc_dev *dev) { struct nvt_dev *nvt = dev->priv; - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); } /* Allocate memory, probe hardware, and initialize everything */ @@ -1152,13 +1155,8 @@ exit_free_dev_rdev: static void nvt_remove(struct pnp_dev *pdev) { struct nvt_dev *nvt = pnp_get_drvdata(pdev); - unsigned long flags; - spin_lock_irqsave(&nvt->nvt_lock, flags); - /* disable CIR */ - nvt_cir_reg_write(nvt, 0, CIR_IREN); nvt_disable_cir(nvt); - spin_unlock_irqrestore(&nvt->nvt_lock, flags); /* enable CIR Wake (for IR power-on) */ nvt_enable_wake(nvt); -- cgit From 5ce625a42d6206d5a18222c6475f6b866ef68569 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Mon, 1 Feb 2016 13:59:30 -0200 Subject: [media] usbvision: fix locking error When remove_pending is non-zero, v4l2_lock is never unlocked. Signed-off-by: Insu Yun Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/usbvision/usbvision-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index 7f5d6f15a49f..12f5ebbd0436 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1147,6 +1147,7 @@ static int usbvision_radio_close(struct file *file) usbvision_audio_off(usbvision); usbvision->radio = 0; usbvision->user--; + mutex_unlock(&usbvision->v4l2_lock); if (usbvision->remove_pending) { printk(KERN_INFO "%s: Final disconnect\n", __func__); @@ -1155,7 +1156,6 @@ static int usbvision_radio_close(struct file *file) return 0; } - mutex_unlock(&usbvision->v4l2_lock); PDEBUG(DBG_IO, "success"); return v4l2_fh_release(file); } -- cgit From 24095e766037018e7a4b636834a383f86a9b30f2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Feb 2016 13:47:58 -0200 Subject: [media] msp3400: use IS_ENABLED check instead of #if A recent patch broke the msp3400 driver when CONFIG_MEDIA_CONTROLLER is not set: drivers/media/i2c/msp3400-driver.h:107:5: error: "CONFIG_MEDIA_CONTROLLER" is not defined [-Werror=undef] It was clearly a typo, and this patch changes the "#if CONFIG_MEDIA_CONTROLLER" to a working IS_ENABLED() check. Fixes: fb4932821731 ("[media] msp3400: initialize MC data") Signed-off-by: Arnd Bergmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/msp3400-driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h index f0bb37dc9013..a8702aca187a 100644 --- a/drivers/media/i2c/msp3400-driver.h +++ b/drivers/media/i2c/msp3400-driver.h @@ -104,7 +104,7 @@ struct msp_state { unsigned int restart:1; unsigned int watch_stereo:1; -#if CONFIG_MEDIA_CONTROLLER +#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER) struct media_pad pads[IF_AUD_DEC_PAD_NUM_PADS]; #endif }; -- cgit From f2b59ac66f980e7636c15e2ebbd09f0ef46881ab Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 2 Feb 2016 21:09:33 +0530 Subject: EDAC, mpc85xx: Silence unused variable warning We were getting this build warning: drivers/edac/mpc85xx_edac.c:1247:6: warning: unused variable 'pvr' pvr is only used if CONFIG_FSL_SOC_BOOKE is defined. Declare it __maybe_unused. Suggested-by: Guenter Roeck Signed-off-by: Sudip Mukherjee Reviewed-by: Johannes Thumshirn Cc: linux-edac Link: http://lkml.kernel.org/r/1454427573-7994-1-git-send-email-sudipm.mukherjee@gmail.com Signed-off-by: Borislav Petkov --- drivers/edac/mpc85xx_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index b7139c160baf..ca63d0da8889 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -1244,7 +1244,7 @@ static struct platform_driver * const drivers[] = { static int __init mpc85xx_mc_init(void) { int res = 0; - u32 pvr = 0; + u32 __maybe_unused pvr = 0; printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, " "(C) 2006 Montavista Software\n"); -- cgit From 3245d460a1eb55b5c3ca31dde7b5c5ac71546edf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Feb 2016 10:16:51 -0200 Subject: regmap: cache: Fall back to register by register read for cache defaults If we are unable to read the cache defaults for a regmap then fall back on attempting to read them word by word. This is going to be painfully slow for large regmaps but might be adequate for smaller ones. Signed-off-by: Mark Brown [maciej: Use cache_bypass around read and skipping of unreadable regs] Signed-off-by: Maciej S. Szmigiero Signed-off-by: Fabio Estevam Tested-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/base/regmap/regcache.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 348be3a35410..cccceb599b02 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -30,7 +30,7 @@ static int regcache_hw_init(struct regmap *map) int i, j; int ret; int count; - unsigned int val; + unsigned int reg, val; void *tmp_buf; if (!map->num_reg_defaults_raw) @@ -67,27 +67,46 @@ static int regcache_hw_init(struct regmap *map) ret = regmap_raw_read(map, 0, tmp_buf, map->num_reg_defaults_raw); map->cache_bypass = cache_bypass; - if (ret < 0) - goto err_cache_free; - - map->reg_defaults_raw = tmp_buf; - map->cache_free = 1; + if (ret == 0) { + map->reg_defaults_raw = tmp_buf; + map->cache_free = 1; + } else { + kfree(tmp_buf); + } } /* fill the reg_defaults */ for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { - if (regmap_volatile(map, i * map->reg_stride)) + reg = i * map->reg_stride; + + if (!regmap_readable(map, reg)) continue; - val = regcache_get_val(map, map->reg_defaults_raw, i); - map->reg_defaults[j].reg = i * map->reg_stride; + + if (regmap_volatile(map, reg)) + continue; + + if (map->reg_defaults_raw) { + val = regcache_get_val(map, map->reg_defaults_raw, i); + } else { + bool cache_bypass = map->cache_bypass; + + map->cache_bypass = true; + ret = regmap_read(map, reg, &val); + map->cache_bypass = cache_bypass; + if (ret != 0) { + dev_err(map->dev, "Failed to read %d: %d\n", + reg, ret); + goto err_free; + } + } + + map->reg_defaults[j].reg = reg; map->reg_defaults[j].def = val; j++; } return 0; -err_cache_free: - kfree(tmp_buf); err_free: kfree(map->reg_defaults); -- cgit From 3a9686c4ba7eec9201c6e8793705d32f24748771 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Mon, 1 Feb 2016 15:22:34 +0000 Subject: ASoC: wm_adsp: Add missing const from region definitions Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 653dbff81fee..28d3851c5063 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -325,7 +325,7 @@ struct wm_adsp_buffer_region_def { unsigned int size_offset; }; -static struct wm_adsp_buffer_region_def default_regions[] = { +static const struct wm_adsp_buffer_region_def default_regions[] = { { .mem_type = WMFW_ADSP2_XM, .base_offset = HOST_BUFFER_FIELD(X_buf_base), @@ -347,7 +347,7 @@ struct wm_adsp_fw_caps { u32 id; struct snd_codec_desc desc; int num_regions; - struct wm_adsp_buffer_region_def *region_defs; + const struct wm_adsp_buffer_region_def *region_defs; }; static const struct wm_adsp_fw_caps ctrl_caps[] = { -- cgit From da2b33589013b4cb3dad163f50fae060896cb8b6 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 2 Feb 2016 16:41:36 +0000 Subject: ASoC: wm_adsp: Return sample rate in wm_adsp_compr_pointer We should return a valid sample rate from the pointer callback, this patch adds this into the driver. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 33806d487b8a..68b85ee67586 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -295,6 +295,8 @@ struct wm_adsp_compr { u32 *raw_buf; unsigned int copied_total; + + unsigned int sample_rate; }; #define WM_ADSP_DATA_WORD_SIZE 3 @@ -2471,6 +2473,8 @@ int wm_adsp_compr_set_params(struct snd_compr_stream *stream, if (!compr->raw_buf) return -ENOMEM; + compr->sample_rate = params->codec.sample_rate; + return 0; } EXPORT_SYMBOL_GPL(wm_adsp_compr_set_params); @@ -2911,6 +2915,7 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream, tstamp->copied_total = compr->copied_total; tstamp->copied_total += buf->avail * WM_ADSP_DATA_WORD_SIZE; + tstamp->sampling_rate = compr->sample_rate; out: mutex_unlock(&dsp->pwr_lock); -- cgit From 7b5e73961915438d623cb80eea97868b3a66cc48 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 6 Dec 2015 16:15:07 +0100 Subject: batman-adv: Switch to HTTPS version of links open-mesh.org and its subdomains can only be accessed via HTTPS. HTTP-only requests are currently redirected automatically to HTTPS but references in the source code should be only https. Signed-off-by: Sven Eckelmann Signed-off-by: Marek Lindner Signed-off-by: Antonio Quartulli --- Documentation/networking/batman-adv.txt | 2 +- MAINTAINERS | 2 +- net/batman-adv/Kconfig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt index ff23b755f5e4..1b5e7a7f2185 100644 --- a/Documentation/networking/batman-adv.txt +++ b/Documentation/networking/batman-adv.txt @@ -187,7 +187,7 @@ interfaces to the kernel module settings. For more information, please see the manpage (man batctl). -batctl is available on http://www.open-mesh.org/ +batctl is available on https://www.open-mesh.org/ CONTACT diff --git a/MAINTAINERS b/MAINTAINERS index f678c37107f5..1e216aa4d25c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2147,7 +2147,7 @@ M: Marek Lindner M: Simon Wunderlich M: Antonio Quartulli L: b.a.t.m.a.n@lists.open-mesh.org -W: http://www.open-mesh.org/ +W: https://www.open-mesh.org/ S: Maintained F: net/batman-adv/ diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index c6fc8f756c9a..2dd40e5ea030 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig @@ -12,7 +12,7 @@ config BATMAN_ADV B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is a routing protocol for multi-hop ad-hoc mesh networks. The networks may be wired or wireless. See - http://www.open-mesh.org/ for more information and user space + https://www.open-mesh.org/ for more information and user space tools. config BATMAN_ADV_BLA -- cgit From 022f344b41a54a995d90450726842518e91aec29 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Wed, 3 Feb 2016 10:48:34 +0800 Subject: ALSA: hda - build chmap kctl based on pcm in hdmi audio Build chmap kctl based on pcm. The first chmap kctl will be mapped to the first pcm, and so on. When a monitor is connected to a pin, the chmap kctl can find the pin and the monitor through the pcm index. Signed-off-by: Libin Yang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 275b68afb575..1a46f45de736 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -437,6 +437,20 @@ static int hinfo_to_pin_index(struct hda_codec *codec, return -EINVAL; } +static struct hdmi_spec_per_pin *pcm_idx_to_pin(struct hdmi_spec *spec, + int pcm_idx) +{ + int i; + struct hdmi_spec_per_pin *per_pin; + + for (i = 0; i < spec->num_pins; i++) { + per_pin = get_pin(spec, i); + if (per_pin->pcm_idx == pcm_idx) + return per_pin; + } + return NULL; +} + static int cvt_nid_to_cvt_index(struct hda_codec *codec, hda_nid_t cvt_nid) { struct hdmi_spec *spec = codec->spec; @@ -2398,10 +2412,16 @@ static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = info->private_data; struct hdmi_spec *spec = codec->spec; - int pin_idx = kcontrol->private_value; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); + int pcm_idx = kcontrol->private_value; + struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); int i; + if (!per_pin) { + for (i = 0; i < spec->channels_max; i++) + ucontrol->value.integer.value[i] = 0; + return 0; + } + for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) ucontrol->value.integer.value[i] = per_pin->chmap[i]; return 0; @@ -2413,13 +2433,19 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = info->private_data; struct hdmi_spec *spec = codec->spec; - int pin_idx = kcontrol->private_value; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); + int pcm_idx = kcontrol->private_value; + struct hdmi_spec_per_pin *per_pin = pcm_idx_to_pin(spec, pcm_idx); unsigned int ctl_idx; struct snd_pcm_substream *substream; unsigned char chmap[8]; int i, err, ca, prepared = 0; + /* No monitor is connected in dyn_pcm_assign. + * It's invalid to setup the chmap + */ + if (!per_pin) + return 0; + ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); substream = snd_pcm_chmap_substream(info, ctl_idx); if (!substream || !substream->runtime) @@ -2596,18 +2622,18 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) } /* add channel maps */ - for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { struct hda_pcm *pcm; struct snd_pcm_chmap *chmap; struct snd_kcontrol *kctl; int i; - pcm = get_pcm_rec(spec, pin_idx); + pcm = get_pcm_rec(spec, pcm_idx); if (!pcm || !pcm->pcm) break; err = snd_pcm_add_chmap_ctls(pcm->pcm, SNDRV_PCM_STREAM_PLAYBACK, - NULL, 0, pin_idx, &chmap); + NULL, 0, pcm_idx, &chmap); if (err < 0) return err; /* override handlers */ -- cgit From 1b74dde7c47c19a73ea3e9fac95ac27b5d3d50c5 Mon Sep 17 00:00:00 2001 From: Chen Yucong Date: Tue, 2 Feb 2016 11:45:02 +0800 Subject: x86/cpu: Convert printk(KERN_ ...) to pr_(...) - Use the more current logging style pr_(...) instead of the old printk(KERN_ ...). - Convert pr_warning() to pr_warn(). Signed-off-by: Chen Yucong Cc: Borislav Petkov Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1454384702-21707-1-git-send-email-slaoub@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/amd.c | 23 +++++++-------- arch/x86/kernel/cpu/bugs_64.c | 2 +- arch/x86/kernel/cpu/centaur.c | 10 +++---- arch/x86/kernel/cpu/common.c | 42 +++++++++++++-------------- arch/x86/kernel/cpu/cyrix.c | 10 +++---- arch/x86/kernel/cpu/hypervisor.c | 2 +- arch/x86/kernel/cpu/intel.c | 10 +++---- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/mcheck/mce-inject.c | 15 +++++----- arch/x86/kernel/cpu/mcheck/p5.c | 18 +++++------- arch/x86/kernel/cpu/mcheck/therm_throt.c | 15 +++++----- arch/x86/kernel/cpu/mcheck/threshold.c | 4 +-- arch/x86/kernel/cpu/mcheck/winchip.c | 5 ++-- arch/x86/kernel/cpu/microcode/amd.c | 2 +- arch/x86/kernel/cpu/mshyperv.c | 8 +++--- arch/x86/kernel/cpu/mtrr/centaur.c | 2 +- arch/x86/kernel/cpu/mtrr/cleanup.c | 44 ++++++++++++++--------------- arch/x86/kernel/cpu/mtrr/generic.c | 23 ++++++++------- arch/x86/kernel/cpu/mtrr/main.c | 20 ++++++------- arch/x86/kernel/cpu/perf_event.c | 9 +++--- arch/x86/kernel/cpu/perf_event_amd_ibs.c | 10 +++---- arch/x86/kernel/cpu/perf_event_amd_uncore.c | 4 +-- arch/x86/kernel/cpu/perf_event_intel_ds.c | 6 ++-- arch/x86/kernel/cpu/rdrand.c | 2 +- arch/x86/kernel/cpu/topology.c | 4 +-- arch/x86/kernel/cpu/transmeta.c | 8 +++--- arch/x86/kernel/cpu/vmware.c | 5 ++-- 27 files changed, 146 insertions(+), 159 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index a07956a08936..97c59fd60702 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -117,7 +117,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c) void (*f_vide)(void); u64 d, d2; - printk(KERN_INFO "AMD K6 stepping B detected - "); + pr_info("AMD K6 stepping B detected - "); /* * It looks like AMD fixed the 2.6.2 bug and improved indirect @@ -133,10 +133,9 @@ static void init_amd_k6(struct cpuinfo_x86 *c) d = d2-d; if (d > 20*K6_BUG_LOOP) - printk(KERN_CONT - "system stability may be impaired when more than 32 MB are used.\n"); + pr_cont("system stability may be impaired when more than 32 MB are used.\n"); else - printk(KERN_CONT "probably OK (after B9730xxxx).\n"); + pr_cont("probably OK (after B9730xxxx).\n"); } /* K6 with old style WHCR */ @@ -154,7 +153,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c) wbinvd(); wrmsr(MSR_K6_WHCR, l, h); local_irq_restore(flags); - printk(KERN_INFO "Enabling old style K6 write allocation for %d Mb\n", + pr_info("Enabling old style K6 write allocation for %d Mb\n", mbytes); } return; @@ -175,7 +174,7 @@ static void init_amd_k6(struct cpuinfo_x86 *c) wbinvd(); wrmsr(MSR_K6_WHCR, l, h); local_irq_restore(flags); - printk(KERN_INFO "Enabling new style K6 write allocation for %d Mb\n", + pr_info("Enabling new style K6 write allocation for %d Mb\n", mbytes); } @@ -202,7 +201,7 @@ static void init_amd_k7(struct cpuinfo_x86 *c) */ if (c->x86_model >= 6 && c->x86_model <= 10) { if (!cpu_has(c, X86_FEATURE_XMM)) { - printk(KERN_INFO "Enabling disabled K7/SSE Support.\n"); + pr_info("Enabling disabled K7/SSE Support.\n"); msr_clear_bit(MSR_K7_HWCR, 15); set_cpu_cap(c, X86_FEATURE_XMM); } @@ -216,9 +215,8 @@ static void init_amd_k7(struct cpuinfo_x86 *c) if ((c->x86_model == 8 && c->x86_mask >= 1) || (c->x86_model > 8)) { rdmsr(MSR_K7_CLK_CTL, l, h); if ((l & 0xfff00000) != 0x20000000) { - printk(KERN_INFO - "CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", - l, ((l & 0x000fffff)|0x20000000)); + pr_info("CPU: CLK_CTL MSR was %x. Reprogramming to %x\n", + l, ((l & 0x000fffff)|0x20000000)); wrmsr(MSR_K7_CLK_CTL, (l & 0x000fffff)|0x20000000, h); } } @@ -485,7 +483,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) if (!rdmsrl_safe(MSR_K8_TSEG_ADDR, &tseg)) { unsigned long pfn = tseg >> PAGE_SHIFT; - printk(KERN_DEBUG "tseg: %010llx\n", tseg); + pr_debug("tseg: %010llx\n", tseg); if (pfn_range_is_mapped(pfn, pfn + 1)) set_memory_4k((unsigned long)__va(tseg), 1); } @@ -500,8 +498,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) rdmsrl(MSR_K7_HWCR, val); if (!(val & BIT(24))) - printk(KERN_WARNING FW_BUG "TSC doesn't count " - "with P0 frequency!\n"); + pr_warn(FW_BUG "TSC doesn't count with P0 frequency!\n"); } } diff --git a/arch/x86/kernel/cpu/bugs_64.c b/arch/x86/kernel/cpu/bugs_64.c index 04f0fe5af83e..a972ac4c7e7d 100644 --- a/arch/x86/kernel/cpu/bugs_64.c +++ b/arch/x86/kernel/cpu/bugs_64.c @@ -15,7 +15,7 @@ void __init check_bugs(void) { identify_boot_cpu(); #if !defined(CONFIG_SMP) - printk(KERN_INFO "CPU: "); + pr_info("CPU: "); print_cpu_info(&boot_cpu_data); #endif alternative_instructions(); diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index ae20be6e483c..ce197bb7c129 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -29,7 +29,7 @@ static void init_c3(struct cpuinfo_x86 *c) rdmsr(MSR_VIA_FCR, lo, hi); lo |= ACE_FCR; /* enable ACE unit */ wrmsr(MSR_VIA_FCR, lo, hi); - printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n"); + pr_info("CPU: Enabled ACE h/w crypto\n"); } /* enable RNG unit, if present and disabled */ @@ -37,7 +37,7 @@ static void init_c3(struct cpuinfo_x86 *c) rdmsr(MSR_VIA_RNG, lo, hi); lo |= RNG_ENABLE; /* enable RNG unit */ wrmsr(MSR_VIA_RNG, lo, hi); - printk(KERN_INFO "CPU: Enabled h/w RNG\n"); + pr_info("CPU: Enabled h/w RNG\n"); } /* store Centaur Extended Feature Flags as @@ -130,7 +130,7 @@ static void init_centaur(struct cpuinfo_x86 *c) name = "C6"; fcr_set = ECX8|DSMC|EDCTLB|EMMX|ERETSTK; fcr_clr = DPDC; - printk(KERN_NOTICE "Disabling bugged TSC.\n"); + pr_notice("Disabling bugged TSC.\n"); clear_cpu_cap(c, X86_FEATURE_TSC); break; case 8: @@ -163,11 +163,11 @@ static void init_centaur(struct cpuinfo_x86 *c) newlo = (lo|fcr_set) & (~fcr_clr); if (newlo != lo) { - printk(KERN_INFO "Centaur FCR was 0x%X now 0x%X\n", + pr_info("Centaur FCR was 0x%X now 0x%X\n", lo, newlo); wrmsr(MSR_IDT_FCR1, newlo, hi); } else { - printk(KERN_INFO "Centaur FCR is 0x%X\n", lo); + pr_info("Centaur FCR is 0x%X\n", lo); } /* Emulate MTRRs using Centaur's MCR. */ set_cpu_cap(c, X86_FEATURE_CENTAUR_MCR); diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 37830de8f60a..68a80e9b67fc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -228,7 +228,7 @@ static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) lo |= 0x200000; wrmsr(MSR_IA32_BBL_CR_CTL, lo, hi); - printk(KERN_NOTICE "CPU serial number disabled.\n"); + pr_notice("CPU serial number disabled.\n"); clear_cpu_cap(c, X86_FEATURE_PN); /* Disabling the serial number may affect the cpuid level */ @@ -329,9 +329,8 @@ static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) if (!warn) continue; - printk(KERN_WARNING - "CPU: CPU feature " X86_CAP_FMT " disabled, no CPUID level 0x%x\n", - x86_cap_flag(df->feature), df->level); + pr_warn("CPU: CPU feature " X86_CAP_FMT " disabled, no CPUID level 0x%x\n", + x86_cap_flag(df->feature), df->level); } } @@ -510,7 +509,7 @@ void detect_ht(struct cpuinfo_x86 *c) smp_num_siblings = (ebx & 0xff0000) >> 16; if (smp_num_siblings == 1) { - printk_once(KERN_INFO "CPU0: Hyper-Threading is disabled\n"); + pr_info_once("CPU0: Hyper-Threading is disabled\n"); goto out; } @@ -531,10 +530,10 @@ void detect_ht(struct cpuinfo_x86 *c) out: if (!printed && (c->x86_max_cores * smp_num_siblings) > 1) { - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", - c->phys_proc_id); - printk(KERN_INFO "CPU: Processor Core ID: %d\n", - c->cpu_core_id); + pr_info("CPU: Physical Processor ID: %d\n", + c->phys_proc_id); + pr_info("CPU: Processor Core ID: %d\n", + c->cpu_core_id); printed = 1; } #endif @@ -559,9 +558,8 @@ static void get_cpu_vendor(struct cpuinfo_x86 *c) } } - printk_once(KERN_ERR - "CPU: vendor_id '%s' unknown, using generic init.\n" \ - "CPU: Your system may be unstable.\n", v); + pr_err_once("CPU: vendor_id '%s' unknown, using generic init.\n" \ + "CPU: Your system may be unstable.\n", v); c->x86_vendor = X86_VENDOR_UNKNOWN; this_cpu = &default_cpu; @@ -760,7 +758,7 @@ void __init early_cpu_init(void) int count = 0; #ifdef CONFIG_PROCESSOR_SELECT - printk(KERN_INFO "KERNEL supported cpus:\n"); + pr_info("KERNEL supported cpus:\n"); #endif for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) { @@ -778,7 +776,7 @@ void __init early_cpu_init(void) for (j = 0; j < 2; j++) { if (!cpudev->c_ident[j]) continue; - printk(KERN_INFO " %s %s\n", cpudev->c_vendor, + pr_info(" %s %s\n", cpudev->c_vendor, cpudev->c_ident[j]); } } @@ -1061,7 +1059,7 @@ static void __print_cpu_msr(void) for (index = index_min; index < index_max; index++) { if (rdmsrl_safe(index, &val)) continue; - printk(KERN_INFO " MSR%08x: %016llx\n", index, val); + pr_info(" MSR%08x: %016llx\n", index, val); } } } @@ -1100,19 +1098,19 @@ void print_cpu_info(struct cpuinfo_x86 *c) } if (vendor && !strstr(c->x86_model_id, vendor)) - printk(KERN_CONT "%s ", vendor); + pr_cont("%s ", vendor); if (c->x86_model_id[0]) - printk(KERN_CONT "%s", c->x86_model_id); + pr_cont("%s", c->x86_model_id); else - printk(KERN_CONT "%d86", c->x86); + pr_cont("%d86", c->x86); - printk(KERN_CONT " (family: 0x%x, model: 0x%x", c->x86, c->x86_model); + pr_cont(" (family: 0x%x, model: 0x%x", c->x86, c->x86_model); if (c->x86_mask || c->cpuid_level >= 0) - printk(KERN_CONT ", stepping: 0x%x)\n", c->x86_mask); + pr_cont(", stepping: 0x%x)\n", c->x86_mask); else - printk(KERN_CONT ")\n"); + pr_cont(")\n"); print_cpu_msr(c); } @@ -1438,7 +1436,7 @@ void cpu_init(void) show_ucode_info_early(); - printk(KERN_INFO "Initializing CPU#%d\n", cpu); + pr_info("Initializing CPU#%d\n", cpu); if (cpu_feature_enabled(X86_FEATURE_VME) || cpu_has_tsc || diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index aaf152e79637..187bb583d0df 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -103,7 +103,7 @@ static void check_cx686_slop(struct cpuinfo_x86 *c) local_irq_restore(flags); if (ccr5 & 2) { /* possible wrong calibration done */ - printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n"); + pr_info("Recalibrating delay loop with SLOP bit reset\n"); calibrate_delay(); c->loops_per_jiffy = loops_per_jiffy; } @@ -115,7 +115,7 @@ static void set_cx86_reorder(void) { u8 ccr3; - printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n"); + pr_info("Enable Memory access reorder on Cyrix/NSC processor.\n"); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ @@ -128,7 +128,7 @@ static void set_cx86_reorder(void) static void set_cx86_memwb(void) { - printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); + pr_info("Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); /* CCR2 bit 2: unlock NW bit */ setCx86_old(CX86_CCR2, getCx86_old(CX86_CCR2) & ~0x04); @@ -268,7 +268,7 @@ static void init_cyrix(struct cpuinfo_x86 *c) * VSA1 we work around however. */ - printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n"); + pr_info("Working around Cyrix MediaGX virtual DMA bugs.\n"); isa_dma_bridge_buggy = 2; /* We do this before the PCI layer is running. However we @@ -426,7 +426,7 @@ static void cyrix_identify(struct cpuinfo_x86 *c) if (dir0 == 5 || dir0 == 3) { unsigned char ccr3; unsigned long flags; - printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n"); + pr_info("Enabling CPUID on Cyrix processor.\n"); local_irq_save(flags); ccr3 = getCx86(CX86_CCR3); /* enable MAPEN */ diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index d820d8eae96b..73d391ae452f 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -56,7 +56,7 @@ detect_hypervisor_vendor(void) } if (max_pri) - printk(KERN_INFO "Hypervisor detected: %s\n", x86_hyper->name); + pr_info("Hypervisor detected: %s\n", x86_hyper->name); } void init_hypervisor(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 565648bc1a0a..05b9211ea0f7 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -61,7 +61,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) */ if (c->x86 == 6 && c->x86_model == 0x1c && c->x86_mask <= 2 && c->microcode < 0x20e) { - printk(KERN_WARNING "Atom PSE erratum detected, BIOS microcode update recommended\n"); + pr_warn("Atom PSE erratum detected, BIOS microcode update recommended\n"); clear_cpu_cap(c, X86_FEATURE_PSE); } @@ -140,7 +140,7 @@ static void early_init_intel(struct cpuinfo_x86 *c) if (c->x86 > 6 || (c->x86 == 6 && c->x86_model >= 0xd)) { rdmsrl(MSR_IA32_MISC_ENABLE, misc_enable); if (!(misc_enable & MSR_IA32_MISC_ENABLE_FAST_STRING)) { - printk(KERN_INFO "Disabled fast string operations\n"); + pr_info("Disabled fast string operations\n"); setup_clear_cpu_cap(X86_FEATURE_REP_GOOD); setup_clear_cpu_cap(X86_FEATURE_ERMS); } @@ -176,7 +176,7 @@ int ppro_with_ram_bug(void) boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 1 && boot_cpu_data.x86_mask < 8) { - printk(KERN_INFO "Pentium Pro with Errata#50 detected. Taking evasive action.\n"); + pr_info("Pentium Pro with Errata#50 detected. Taking evasive action.\n"); return 1; } return 0; @@ -225,7 +225,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c) set_cpu_bug(c, X86_BUG_F00F); if (!f00f_workaround_enabled) { - printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n"); + pr_notice("Intel Pentium with F0 0F bug - workaround enabled.\n"); f00f_workaround_enabled = 1; } } @@ -244,7 +244,7 @@ static void intel_workarounds(struct cpuinfo_x86 *c) * Forcefully enable PAE if kernel parameter "forcepae" is present. */ if (forcepae) { - printk(KERN_WARNING "PAE forced!\n"); + pr_warn("PAE forced!\n"); set_cpu_cap(c, X86_FEATURE_PAE); add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_NOW_UNRELIABLE); } diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 0b6c52388cf4..6ed779efff26 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -444,7 +444,7 @@ static ssize_t store_cache_disable(struct cacheinfo *this_leaf, err = amd_set_l3_disable_slot(nb, cpu, slot, val); if (err) { if (err == -EEXIST) - pr_warning("L3 slot %d in use/index already disabled!\n", + pr_warn("L3 slot %d in use/index already disabled!\n", slot); return err; } diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index 4cfba4371a71..517619ea6498 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -115,7 +115,7 @@ static int raise_local(void) int cpu = m->extcpu; if (m->inject_flags & MCJ_EXCEPTION) { - printk(KERN_INFO "Triggering MCE exception on CPU %d\n", cpu); + pr_info("Triggering MCE exception on CPU %d\n", cpu); switch (context) { case MCJ_CTX_IRQ: /* @@ -128,15 +128,15 @@ static int raise_local(void) raise_exception(m, NULL); break; default: - printk(KERN_INFO "Invalid MCE context\n"); + pr_info("Invalid MCE context\n"); ret = -EINVAL; } - printk(KERN_INFO "MCE exception done on CPU %d\n", cpu); + pr_info("MCE exception done on CPU %d\n", cpu); } else if (m->status) { - printk(KERN_INFO "Starting machine check poll CPU %d\n", cpu); + pr_info("Starting machine check poll CPU %d\n", cpu); raise_poll(m); mce_notify_irq(); - printk(KERN_INFO "Machine check poll done on CPU %d\n", cpu); + pr_info("Machine check poll done on CPU %d\n", cpu); } else m->finished = 0; @@ -183,8 +183,7 @@ static void raise_mce(struct mce *m) start = jiffies; while (!cpumask_empty(mce_inject_cpumask)) { if (!time_before(jiffies, start + 2*HZ)) { - printk(KERN_ERR - "Timeout waiting for mce inject %lx\n", + pr_err("Timeout waiting for mce inject %lx\n", *cpumask_bits(mce_inject_cpumask)); break; } @@ -241,7 +240,7 @@ static int inject_init(void) { if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL)) return -ENOMEM; - printk(KERN_INFO "Machine check injector initialized\n"); + pr_info("Machine check injector initialized\n"); register_mce_write_callback(mce_write); register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0, "mce_notify"); diff --git a/arch/x86/kernel/cpu/mcheck/p5.c b/arch/x86/kernel/cpu/mcheck/p5.c index 12402e10aeff..2a0717bf8033 100644 --- a/arch/x86/kernel/cpu/mcheck/p5.c +++ b/arch/x86/kernel/cpu/mcheck/p5.c @@ -26,14 +26,12 @@ static void pentium_machine_check(struct pt_regs *regs, long error_code) rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi); rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi); - printk(KERN_EMERG - "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", - smp_processor_id(), loaddr, lotype); + pr_emerg("CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", + smp_processor_id(), loaddr, lotype); if (lotype & (1<<5)) { - printk(KERN_EMERG - "CPU#%d: Possible thermal failure (CPU on fire ?).\n", - smp_processor_id()); + pr_emerg("CPU#%d: Possible thermal failure (CPU on fire ?).\n", + smp_processor_id()); } add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); @@ -61,12 +59,10 @@ void intel_p5_mcheck_init(struct cpuinfo_x86 *c) /* Read registers before enabling: */ rdmsr(MSR_IA32_P5_MC_ADDR, l, h); rdmsr(MSR_IA32_P5_MC_TYPE, l, h); - printk(KERN_INFO - "Intel old style machine check architecture supported.\n"); + pr_info("Intel old style machine check architecture supported.\n"); /* Enable MCE: */ cr4_set_bits(X86_CR4_MCE); - printk(KERN_INFO - "Intel old style machine check reporting enabled on CPU#%d.\n", - smp_processor_id()); + pr_info("Intel old style machine check reporting enabled on CPU#%d.\n", + smp_processor_id()); } diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 2c5aaf8c2e2f..0b445c2ff735 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -190,7 +190,7 @@ static int therm_throt_process(bool new_event, int event, int level) /* if we just entered the thermal event */ if (new_event) { if (event == THERMAL_THROTTLING_EVENT) - printk(KERN_CRIT "CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n", + pr_crit("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n", this_cpu, level == CORE_LEVEL ? "Core" : "Package", state->count); @@ -198,8 +198,7 @@ static int therm_throt_process(bool new_event, int event, int level) } if (old_event) { if (event == THERMAL_THROTTLING_EVENT) - printk(KERN_INFO "CPU%d: %s temperature/speed normal\n", - this_cpu, + pr_info("CPU%d: %s temperature/speed normal\n", this_cpu, level == CORE_LEVEL ? "Core" : "Package"); return 1; } @@ -417,8 +416,8 @@ static void intel_thermal_interrupt(void) static void unexpected_thermal_interrupt(void) { - printk(KERN_ERR "CPU%d: Unexpected LVT thermal interrupt!\n", - smp_processor_id()); + pr_err("CPU%d: Unexpected LVT thermal interrupt!\n", + smp_processor_id()); } static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt; @@ -499,7 +498,7 @@ void intel_init_thermal(struct cpuinfo_x86 *c) if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) { if (system_state == SYSTEM_BOOTING) - printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n", cpu); + pr_debug("CPU%d: Thermal monitoring handled by SMI\n", cpu); return; } @@ -557,8 +556,8 @@ void intel_init_thermal(struct cpuinfo_x86 *c) l = apic_read(APIC_LVTTHMR); apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); - printk_once(KERN_INFO "CPU0: Thermal monitoring enabled (%s)\n", - tm2 ? "TM2" : "TM1"); + pr_info_once("CPU0: Thermal monitoring enabled (%s)\n", + tm2 ? "TM2" : "TM1"); /* enable thermal throttle processing */ atomic_set(&therm_throt_en, 1); diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index 7245980186ee..fcf9ae9384f4 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c @@ -12,8 +12,8 @@ static void default_threshold_interrupt(void) { - printk(KERN_ERR "Unexpected threshold interrupt at vector %x\n", - THRESHOLD_APIC_VECTOR); + pr_err("Unexpected threshold interrupt at vector %x\n", + THRESHOLD_APIC_VECTOR); } void (*mce_threshold_vector)(void) = default_threshold_interrupt; diff --git a/arch/x86/kernel/cpu/mcheck/winchip.c b/arch/x86/kernel/cpu/mcheck/winchip.c index 01dd8702880b..c6a722e1d011 100644 --- a/arch/x86/kernel/cpu/mcheck/winchip.c +++ b/arch/x86/kernel/cpu/mcheck/winchip.c @@ -17,7 +17,7 @@ static void winchip_machine_check(struct pt_regs *regs, long error_code) { ist_enter(regs); - printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); + pr_emerg("CPU0: Machine Check Exception.\n"); add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); ist_exit(regs); @@ -39,6 +39,5 @@ void winchip_mcheck_init(struct cpuinfo_x86 *c) cr4_set_bits(X86_CR4_MCE); - printk(KERN_INFO - "Winchip machine check reporting enabled on CPU#0.\n"); + pr_info("Winchip machine check reporting enabled on CPU#0.\n"); } diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 2233f8a76615..75d3aab5f7b2 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c @@ -953,7 +953,7 @@ struct microcode_ops * __init init_amd_microcode(void) struct cpuinfo_x86 *c = &boot_cpu_data; if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { - pr_warning("AMD CPU family 0x%x not supported\n", c->x86); + pr_warn("AMD CPU family 0x%x not supported\n", c->x86); return NULL; } diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 20e242ea1bc4..4e7c6933691c 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -161,8 +161,8 @@ static void __init ms_hyperv_init_platform(void) ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES); ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO); - printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", - ms_hyperv.features, ms_hyperv.hints); + pr_info("HyperV: features 0x%x, hints 0x%x\n", + ms_hyperv.features, ms_hyperv.hints); #ifdef CONFIG_X86_LOCAL_APIC if (ms_hyperv.features & HV_X64_MSR_APIC_FREQUENCY_AVAILABLE) { @@ -174,8 +174,8 @@ static void __init ms_hyperv_init_platform(void) rdmsrl(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency); hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ); lapic_timer_frequency = hv_lapic_frequency; - printk(KERN_INFO "HyperV: LAPIC Timer Frequency: %#x\n", - lapic_timer_frequency); + pr_info("HyperV: LAPIC Timer Frequency: %#x\n", + lapic_timer_frequency); } #endif diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c index 316fe3e60a97..3d689937fc1b 100644 --- a/arch/x86/kernel/cpu/mtrr/centaur.c +++ b/arch/x86/kernel/cpu/mtrr/centaur.c @@ -103,7 +103,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t */ if (type != MTRR_TYPE_WRCOMB && (centaur_mcr_type == 0 || type != MTRR_TYPE_UNCACHABLE)) { - pr_warning("mtrr: only write-combining%s supported\n", + pr_warn("mtrr: only write-combining%s supported\n", centaur_mcr_type ? " and uncacheable are" : " is"); return -EINVAL; } diff --git a/arch/x86/kernel/cpu/mtrr/cleanup.c b/arch/x86/kernel/cpu/mtrr/cleanup.c index 0d98503c2245..31e951ce6dff 100644 --- a/arch/x86/kernel/cpu/mtrr/cleanup.c +++ b/arch/x86/kernel/cpu/mtrr/cleanup.c @@ -57,9 +57,9 @@ static int __initdata nr_range; static struct var_mtrr_range_state __initdata range_state[RANGE_NUM]; static int __initdata debug_print; -#define Dprintk(x...) do { if (debug_print) printk(KERN_DEBUG x); } while (0) +#define Dprintk(x...) do { if (debug_print) pr_debug(x); } while (0) -#define BIOS_BUG_MSG KERN_WARNING \ +#define BIOS_BUG_MSG \ "WARNING: BIOS bug: VAR MTRR %d contains strange UC entry under 1M, check with your system vendor!\n" static int __init @@ -81,9 +81,9 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, base, base + size); } if (debug_print) { - printk(KERN_DEBUG "After WB checking\n"); + pr_debug("After WB checking\n"); for (i = 0; i < nr_range; i++) - printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", + pr_debug("MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } @@ -101,7 +101,7 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, (mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED) && (mtrr_state.enabled & MTRR_STATE_MTRR_FIXED_ENABLED)) { /* Var MTRR contains UC entry below 1M? Skip it: */ - printk(BIOS_BUG_MSG, i); + pr_warn(BIOS_BUG_MSG, i); if (base + size <= (1<<(20-PAGE_SHIFT))) continue; size -= (1<<(20-PAGE_SHIFT)) - base; @@ -114,11 +114,11 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, extra_remove_base + extra_remove_size); if (debug_print) { - printk(KERN_DEBUG "After UC checking\n"); + pr_debug("After UC checking\n"); for (i = 0; i < RANGE_NUM; i++) { if (!range[i].end) continue; - printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", + pr_debug("MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } } @@ -126,9 +126,9 @@ x86_get_mtrr_mem_range(struct range *range, int nr_range, /* sort the ranges */ nr_range = clean_sort_range(range, RANGE_NUM); if (debug_print) { - printk(KERN_DEBUG "After sorting\n"); + pr_debug("After sorting\n"); for (i = 0; i < nr_range; i++) - printk(KERN_DEBUG "MTRR MAP PFN: %016llx - %016llx\n", + pr_debug("MTRR MAP PFN: %016llx - %016llx\n", range[i].start, range[i].end); } @@ -544,7 +544,7 @@ static void __init print_out_mtrr_range_state(void) start_base = to_size_factor(start_base, &start_factor), type = range_state[i].type; - printk(KERN_DEBUG "reg %d, base: %ld%cB, range: %ld%cB, type %s\n", + pr_debug("reg %d, base: %ld%cB, range: %ld%cB, type %s\n", i, start_base, start_factor, size_base, size_factor, (type == MTRR_TYPE_UNCACHABLE) ? "UC" : @@ -713,7 +713,7 @@ int __init mtrr_cleanup(unsigned address_bits) return 0; /* Print original var MTRRs at first, for debugging: */ - printk(KERN_DEBUG "original variable MTRRs\n"); + pr_debug("original variable MTRRs\n"); print_out_mtrr_range_state(); memset(range, 0, sizeof(range)); @@ -733,7 +733,7 @@ int __init mtrr_cleanup(unsigned address_bits) x_remove_base, x_remove_size); range_sums = sum_ranges(range, nr_range); - printk(KERN_INFO "total RAM covered: %ldM\n", + pr_info("total RAM covered: %ldM\n", range_sums >> (20 - PAGE_SHIFT)); if (mtrr_chunk_size && mtrr_gran_size) { @@ -745,12 +745,11 @@ int __init mtrr_cleanup(unsigned address_bits) if (!result[i].bad) { set_var_mtrr_all(address_bits); - printk(KERN_DEBUG "New variable MTRRs\n"); + pr_debug("New variable MTRRs\n"); print_out_mtrr_range_state(); return 1; } - printk(KERN_INFO "invalid mtrr_gran_size or mtrr_chunk_size, " - "will find optimal one\n"); + pr_info("invalid mtrr_gran_size or mtrr_chunk_size, will find optimal one\n"); } i = 0; @@ -768,7 +767,7 @@ int __init mtrr_cleanup(unsigned address_bits) x_remove_base, x_remove_size, i); if (debug_print) { mtrr_print_out_one_result(i); - printk(KERN_INFO "\n"); + pr_info("\n"); } i++; @@ -779,7 +778,7 @@ int __init mtrr_cleanup(unsigned address_bits) index_good = mtrr_search_optimal_index(); if (index_good != -1) { - printk(KERN_INFO "Found optimal setting for mtrr clean up\n"); + pr_info("Found optimal setting for mtrr clean up\n"); i = index_good; mtrr_print_out_one_result(i); @@ -790,7 +789,7 @@ int __init mtrr_cleanup(unsigned address_bits) gran_size <<= 10; x86_setup_var_mtrrs(range, nr_range, chunk_size, gran_size); set_var_mtrr_all(address_bits); - printk(KERN_DEBUG "New variable MTRRs\n"); + pr_debug("New variable MTRRs\n"); print_out_mtrr_range_state(); return 1; } else { @@ -799,8 +798,8 @@ int __init mtrr_cleanup(unsigned address_bits) mtrr_print_out_one_result(i); } - printk(KERN_INFO "mtrr_cleanup: can not find optimal value\n"); - printk(KERN_INFO "please specify mtrr_gran_size/mtrr_chunk_size\n"); + pr_info("mtrr_cleanup: can not find optimal value\n"); + pr_info("please specify mtrr_gran_size/mtrr_chunk_size\n"); return 0; } @@ -918,7 +917,7 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) /* kvm/qemu doesn't have mtrr set right, don't trim them all: */ if (!highest_pfn) { - printk(KERN_INFO "CPU MTRRs all blank - virtualized system.\n"); + pr_info("CPU MTRRs all blank - virtualized system.\n"); return 0; } @@ -973,7 +972,8 @@ int __init mtrr_trim_uncached_memory(unsigned long end_pfn) end_pfn); if (total_trim_size) { - pr_warning("WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing %lluMB of RAM.\n", total_trim_size >> 20); + pr_warn("WARNING: BIOS bug: CPU MTRRs don't cover all of memory, losing %lluMB of RAM.\n", + total_trim_size >> 20); if (!changed_by_mtrr_cleanup) WARN_ON(1); diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index c870af161008..fcbcb2f678ca 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -55,7 +55,7 @@ static inline void k8_check_syscfg_dram_mod_en(void) rdmsr(MSR_K8_SYSCFG, lo, hi); if (lo & K8_MTRRFIXRANGE_DRAM_MODIFY) { - printk(KERN_ERR FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]" + pr_err(FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]" " not cleared by BIOS, clearing this bit\n", smp_processor_id()); lo &= ~K8_MTRRFIXRANGE_DRAM_MODIFY; @@ -501,14 +501,14 @@ void __init mtrr_state_warn(void) if (!mask) return; if (mask & MTRR_CHANGE_MASK_FIXED) - pr_warning("mtrr: your CPUs had inconsistent fixed MTRR settings\n"); + pr_warn("mtrr: your CPUs had inconsistent fixed MTRR settings\n"); if (mask & MTRR_CHANGE_MASK_VARIABLE) - pr_warning("mtrr: your CPUs had inconsistent variable MTRR settings\n"); + pr_warn("mtrr: your CPUs had inconsistent variable MTRR settings\n"); if (mask & MTRR_CHANGE_MASK_DEFTYPE) - pr_warning("mtrr: your CPUs had inconsistent MTRRdefType settings\n"); + pr_warn("mtrr: your CPUs had inconsistent MTRRdefType settings\n"); - printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n"); - printk(KERN_INFO "mtrr: corrected configuration.\n"); + pr_info("mtrr: probably your BIOS does not setup all CPUs.\n"); + pr_info("mtrr: corrected configuration.\n"); } /* @@ -519,8 +519,7 @@ void __init mtrr_state_warn(void) void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b) { if (wrmsr_safe(msr, a, b) < 0) { - printk(KERN_ERR - "MTRR: CPU %u: Writing MSR %x to %x:%x failed\n", + pr_err("MTRR: CPU %u: Writing MSR %x to %x:%x failed\n", smp_processor_id(), msr, a, b); } } @@ -607,7 +606,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, tmp |= ~((1ULL<<(hi - 1)) - 1); if (tmp != mask) { - printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); + pr_warn("mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); mask = tmp; } @@ -858,13 +857,13 @@ int generic_validate_add_page(unsigned long base, unsigned long size, boot_cpu_data.x86_model == 1 && boot_cpu_data.x86_mask <= 7) { if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) { - pr_warning("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base); + pr_warn("mtrr: base(0x%lx000) is not 4 MiB aligned\n", base); return -EINVAL; } if (!(base + size < 0x70000 || base > 0x7003F) && (type == MTRR_TYPE_WRCOMB || type == MTRR_TYPE_WRBACK)) { - pr_warning("mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n"); + pr_warn("mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n"); return -EINVAL; } } @@ -878,7 +877,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, lbase = lbase >> 1, last = last >> 1) ; if (lbase != last) { - pr_warning("mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size); + pr_warn("mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size); return -EINVAL; } return 0; diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 5c3d149ee91c..ba80d68f683e 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -300,24 +300,24 @@ int mtrr_add_page(unsigned long base, unsigned long size, return error; if (type >= MTRR_NUM_TYPES) { - pr_warning("mtrr: type: %u invalid\n", type); + pr_warn("mtrr: type: %u invalid\n", type); return -EINVAL; } /* If the type is WC, check that this processor supports it */ if ((type == MTRR_TYPE_WRCOMB) && !have_wrcomb()) { - pr_warning("mtrr: your processor doesn't support write-combining\n"); + pr_warn("mtrr: your processor doesn't support write-combining\n"); return -ENOSYS; } if (!size) { - pr_warning("mtrr: zero sized request\n"); + pr_warn("mtrr: zero sized request\n"); return -EINVAL; } if ((base | (base + size - 1)) >> (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) { - pr_warning("mtrr: base or size exceeds the MTRR width\n"); + pr_warn("mtrr: base or size exceeds the MTRR width\n"); return -EINVAL; } @@ -348,7 +348,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, } else if (types_compatible(type, ltype)) continue; } - pr_warning("mtrr: 0x%lx000,0x%lx000 overlaps existing" + pr_warn("mtrr: 0x%lx000,0x%lx000 overlaps existing" " 0x%lx000,0x%lx000\n", base, size, lbase, lsize); goto out; @@ -357,7 +357,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, if (ltype != type) { if (types_compatible(type, ltype)) continue; - pr_warning("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", + pr_warn("mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", base, size, mtrr_attrib_to_str(ltype), mtrr_attrib_to_str(type)); goto out; @@ -395,7 +395,7 @@ int mtrr_add_page(unsigned long base, unsigned long size, static int mtrr_check(unsigned long base, unsigned long size) { if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { - pr_warning("mtrr: size and base must be multiples of 4 kiB\n"); + pr_warn("mtrr: size and base must be multiples of 4 kiB\n"); pr_debug("mtrr: size: 0x%lx base: 0x%lx\n", size, base); dump_stack(); return -1; @@ -493,16 +493,16 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size) } } if (reg >= max) { - pr_warning("mtrr: register: %d too big\n", reg); + pr_warn("mtrr: register: %d too big\n", reg); goto out; } mtrr_if->get(reg, &lbase, &lsize, <ype); if (lsize < 1) { - pr_warning("mtrr: MTRR %d not used\n", reg); + pr_warn("mtrr: MTRR %d not used\n", reg); goto out; } if (mtrr_usage_table[reg] < 1) { - pr_warning("mtrr: reg: %d has count=0\n", reg); + pr_warn("mtrr: reg: %d has count=0\n", reg); goto out; } if (--mtrr_usage_table[reg] < 1) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1b443db2db50..7402c8182813 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -254,15 +254,16 @@ static bool check_hw_exists(void) * We still allow the PMU driver to operate: */ if (bios_fail) { - printk(KERN_CONT "Broken BIOS detected, complain to your hardware vendor.\n"); - printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg_fail, val_fail); + pr_cont("Broken BIOS detected, complain to your hardware vendor.\n"); + pr_err(FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", + reg_fail, val_fail); } return true; msr_fail: - printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n"); - printk("%sFailed to access perfctr msr (MSR %x is %Lx)\n", + pr_cont("Broken PMU hardware detected, using software events only.\n"); + pr_info("%sFailed to access perfctr msr (MSR %x is %Lx)\n", boot_cpu_has(X86_FEATURE_HYPERVISOR) ? KERN_INFO : KERN_ERR, reg, val_new); diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index 989d3c215d2b..aa12f9509cfb 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -670,7 +670,7 @@ static __init int perf_event_ibs_init(void) perf_ibs_pmu_init(&perf_ibs_op, "ibs_op"); register_nmi_handler(NMI_LOCAL, perf_ibs_nmi_handler, 0, "perf_ibs"); - printk(KERN_INFO "perf: AMD IBS detected (0x%08x)\n", ibs_caps); + pr_info("perf: AMD IBS detected (0x%08x)\n", ibs_caps); return 0; } @@ -774,14 +774,14 @@ static int setup_ibs_ctl(int ibs_eilvt_off) pci_read_config_dword(cpu_cfg, IBSCTL, &value); if (value != (ibs_eilvt_off | IBSCTL_LVT_OFFSET_VALID)) { pci_dev_put(cpu_cfg); - printk(KERN_DEBUG "Failed to setup IBS LVT offset, " - "IBSCTL = 0x%08x\n", value); + pr_debug("Failed to setup IBS LVT offset, IBSCTL = 0x%08x\n", + value); return -EINVAL; } } while (1); if (!nodes) { - printk(KERN_DEBUG "No CPU node configured for IBS\n"); + pr_debug("No CPU node configured for IBS\n"); return -ENODEV; } @@ -810,7 +810,7 @@ static void force_ibs_eilvt_setup(void) preempt_enable(); if (offset == APIC_EILVT_NR_MAX) { - printk(KERN_DEBUG "No EILVT entry available\n"); + pr_debug("No EILVT entry available\n"); return; } diff --git a/arch/x86/kernel/cpu/perf_event_amd_uncore.c b/arch/x86/kernel/cpu/perf_event_amd_uncore.c index 49742746a6c9..19a17363a21d 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_amd_uncore.c @@ -536,7 +536,7 @@ static int __init amd_uncore_init(void) if (ret) goto fail_nb; - printk(KERN_INFO "perf: AMD NB counters detected\n"); + pr_info("perf: AMD NB counters detected\n"); ret = 0; } @@ -550,7 +550,7 @@ static int __init amd_uncore_init(void) if (ret) goto fail_l2; - printk(KERN_INFO "perf: AMD L2I counters detected\n"); + pr_info("perf: AMD L2I counters detected\n"); ret = 0; } diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 10602f0a438f..7c79261ed939 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -1325,13 +1325,13 @@ void __init intel_ds_init(void) switch (format) { case 0: - printk(KERN_CONT "PEBS fmt0%c, ", pebs_type); + pr_cont("PEBS fmt0%c, ", pebs_type); x86_pmu.pebs_record_size = sizeof(struct pebs_record_core); x86_pmu.drain_pebs = intel_pmu_drain_pebs_core; break; case 1: - printk(KERN_CONT "PEBS fmt1%c, ", pebs_type); + pr_cont("PEBS fmt1%c, ", pebs_type); x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm); x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; break; @@ -1351,7 +1351,7 @@ void __init intel_ds_init(void) break; default: - printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type); + pr_cont("no PEBS fmt%d%c, ", format, pebs_type); x86_pmu.pebs = 0; } } diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index 819d94982e07..f6f50c4ceaec 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c @@ -51,7 +51,7 @@ void x86_init_rdrand(struct cpuinfo_x86 *c) for (i = 0; i < SANITY_CHECK_LOOPS; i++) { if (!rdrand_long(&tmp)) { clear_cpu_cap(c, X86_FEATURE_RDRAND); - printk_once(KERN_WARNING "rdrand: disabled\n"); + pr_warn_once("rdrand: disabled\n"); return; } } diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index 4c60eaf0571c..cd531355e838 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -87,10 +87,10 @@ void detect_extended_topology(struct cpuinfo_x86 *c) c->x86_max_cores = (core_level_siblings / smp_num_siblings); if (!printed) { - printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + pr_info("CPU: Physical Processor ID: %d\n", c->phys_proc_id); if (c->x86_max_cores > 1) - printk(KERN_INFO "CPU: Processor Core ID: %d\n", + pr_info("CPU: Processor Core ID: %d\n", c->cpu_core_id); printed = 1; } diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 252da7aceca6..e3b4d1841175 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -33,7 +33,7 @@ static void init_transmeta(struct cpuinfo_x86 *c) if (max >= 0x80860001) { cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); if (cpu_rev != 0x02000000) { - printk(KERN_INFO "CPU: Processor revision %u.%u.%u.%u, %u MHz\n", + pr_info("CPU: Processor revision %u.%u.%u.%u, %u MHz\n", (cpu_rev >> 24) & 0xff, (cpu_rev >> 16) & 0xff, (cpu_rev >> 8) & 0xff, @@ -44,10 +44,10 @@ static void init_transmeta(struct cpuinfo_x86 *c) if (max >= 0x80860002) { cpuid(0x80860002, &new_cpu_rev, &cms_rev1, &cms_rev2, &dummy); if (cpu_rev == 0x02000000) { - printk(KERN_INFO "CPU: Processor revision %08X, %u MHz\n", + pr_info("CPU: Processor revision %08X, %u MHz\n", new_cpu_rev, cpu_freq); } - printk(KERN_INFO "CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n", + pr_info("CPU: Code Morphing Software revision %u.%u.%u-%u-%u\n", (cms_rev1 >> 24) & 0xff, (cms_rev1 >> 16) & 0xff, (cms_rev1 >> 8) & 0xff, @@ -76,7 +76,7 @@ static void init_transmeta(struct cpuinfo_x86 *c) (void *)&cpu_info[56], (void *)&cpu_info[60]); cpu_info[64] = '\0'; - printk(KERN_INFO "CPU: %s\n", cpu_info); + pr_info("CPU: %s\n", cpu_info); } /* Unhide possibly hidden capability flags */ diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 628a059a9a06..364e58346897 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -62,7 +62,7 @@ static unsigned long vmware_get_tsc_khz(void) tsc_hz = eax | (((uint64_t)ebx) << 32); do_div(tsc_hz, 1000); BUG_ON(tsc_hz >> 32); - printk(KERN_INFO "TSC freq read from hypervisor : %lu.%03lu MHz\n", + pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n", (unsigned long) tsc_hz / 1000, (unsigned long) tsc_hz % 1000); @@ -84,8 +84,7 @@ static void __init vmware_platform_setup(void) if (ebx != UINT_MAX) x86_platform.calibrate_tsc = vmware_get_tsc_khz; else - printk(KERN_WARNING - "Failed to get TSC freq from the hypervisor\n"); + pr_warn("Failed to get TSC freq from the hypervisor\n"); } /* -- cgit From 27ea43fe2a32f63bb6f442dafc2133232b8af4a6 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Sat, 24 Oct 2015 21:15:34 +0200 Subject: nbd: Fix debugfs error handling Static checker complains about the implemented error handling. It is indeed wrong. We don't care about the return values of created debugfs files. We only have to check the return values of created dirs for NULL pointer. If we use a null pointer as parent directory for files, this may lead to debugfs files in wrong places. Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 55 ++++++++++++++--------------------------------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index e4c5cc107934..d61a04155d99 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -892,50 +892,23 @@ static const struct file_operations nbd_dbg_flags_ops = { static int nbd_dev_dbg_init(struct nbd_device *nbd) { struct dentry *dir; - struct dentry *f; + + if (!nbd_dbg_dir) + return -EIO; dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir); - if (IS_ERR_OR_NULL(dir)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s' (%ld)\n", - nbd_name(nbd), PTR_ERR(dir)); - return PTR_ERR(dir); + if (!dir) { + dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n", + nbd_name(nbd)); + return -EIO; } nbd->dbg_dir = dir; - f = debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'tasks', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'size_bytes', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'timeout', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'blocksize', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } - - f = debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops); - if (IS_ERR_OR_NULL(f)) { - dev_err(nbd_to_dev(nbd), "Failed to create debugfs file 'flags', %ld\n", - PTR_ERR(f)); - return PTR_ERR(f); - } + debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops); + debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize); + debugfs_create_u32("timeout", 0444, dir, &nbd->xmit_timeout); + debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize); + debugfs_create_file("flags", 0444, dir, &nbd, &nbd_dbg_flags_ops); return 0; } @@ -950,8 +923,8 @@ static int nbd_dbg_init(void) struct dentry *dbg_dir; dbg_dir = debugfs_create_dir("nbd", NULL); - if (IS_ERR(dbg_dir)) - return PTR_ERR(dbg_dir); + if (!dbg_dir) + return -EIO; nbd_dbg_dir = dbg_dir; -- cgit From e32bb8709fce66ff7f392a33d7689402d3e2ba2e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 2 Feb 2016 11:27:42 +0000 Subject: spi: Fix sorting in Kconfig Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 64 ++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 77064160dd76..7caf18cb3e5e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -75,6 +75,14 @@ config SPI_ATMEL This selects a driver for the Atmel SPI Controller, present on many AT32 (AVR32) and AT91 (ARM) chips. +config SPI_AU1550 + tristate "Au1550/Au1200/Au1300 SPI Controller" + depends on MIPS_ALCHEMY + select SPI_BITBANG + help + If you say yes to this option, support will be included for the + PSC SPI controller found on Au1550, Au1200 and Au1300 series. + config SPI_BCM2835 tristate "BCM2835 SPI controller" depends on GPIOLIB @@ -118,14 +126,6 @@ config SPI_BFIN_SPORT help Enable support for a SPI bus via the Blackfin SPORT peripheral. -config SPI_AU1550 - tristate "Au1550/Au1200/Au1300 SPI Controller" - depends on MIPS_ALCHEMY - select SPI_BITBANG - help - If you say yes to this option, support will be included for the - PSC SPI controller found on Au1550, Au1200 and Au1300 series. - config SPI_BCM53XX tristate "Broadcom BCM53xx SPI controller" depends on ARCH_BCM_5301X @@ -197,6 +197,23 @@ config SPI_DAVINCI help SPI master controller for DaVinci/DA8x/OMAP-L/AM1x SPI modules. +config SPI_DESIGNWARE + tristate "DesignWare SPI controller core support" + help + general driver for SPI controller core from DesignWare + +config SPI_DW_PCI + tristate "PCI interface driver for DW SPI core" + depends on SPI_DESIGNWARE && PCI + +config SPI_DW_MID_DMA + bool "DMA support for DW SPI controller on Intel MID platform" + depends on SPI_DW_PCI && DW_DMAC_PCI + +config SPI_DW_MMIO + tristate "Memory-mapped io interface driver for DW SPI core" + depends on SPI_DESIGNWARE + config SPI_DLN2 tristate "Diolan DLN-2 USB SPI adapter" depends on MFD_DLN2 @@ -346,6 +363,13 @@ config SPI_MT65XX say Y or M here.If you are not sure, say N. SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs. +config SPI_NUC900 + tristate "Nuvoton NUC900 series SPI" + depends on ARCH_W90X900 + select SPI_BITBANG + help + SPI driver for Nuvoton NUC900 series ARM SoCs + config SPI_OC_TINY tristate "OpenCores tiny SPI" depends on GPIOLIB || COMPILE_TEST @@ -647,34 +671,10 @@ config SPI_ZYNQMP_GQSPI help Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC. -config SPI_NUC900 - tristate "Nuvoton NUC900 series SPI" - depends on ARCH_W90X900 - select SPI_BITBANG - help - SPI driver for Nuvoton NUC900 series ARM SoCs - # # Add new SPI master controllers in alphabetical order above this line # -config SPI_DESIGNWARE - tristate "DesignWare SPI controller core support" - help - general driver for SPI controller core from DesignWare - -config SPI_DW_PCI - tristate "PCI interface driver for DW SPI core" - depends on SPI_DESIGNWARE && PCI - -config SPI_DW_MID_DMA - bool "DMA support for DW SPI controller on Intel MID platform" - depends on SPI_DW_PCI && DW_DMAC_PCI - -config SPI_DW_MMIO - tristate "Memory-mapped io interface driver for DW SPI core" - depends on SPI_DESIGNWARE - # # There are lots of SPI device types, with sensors and memory # being probably the most widely used ones. -- cgit From 02afeaae9843733a39cd9b11053748b2d1dc5ae7 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Dec 2015 14:52:38 -0800 Subject: x86/boot: Fix early command-line parsing when matching at end The x86 early command line parsing in cmdline_find_option_bool() is buggy. If it matches a specified 'option' all the way to the end of the command-line, it will consider it a match. For instance, cmdline = "foo"; cmdline_find_option_bool(cmdline, "fool"); will return 1. This is particularly annoying since we have actual FPU options like "noxsave" and "noxsaves" So, command-line "foo bar noxsave" will match *BOTH* a "noxsave" and "noxsaves". (This turns out not to be an actual problem because "noxsave" implies "noxsaves", but it's still confusing.) To fix this, we simplify the code and stop tracking 'len'. 'len' was trying to indicate either the NULL terminator *OR* the end of a non-NULL-terminated command line at 'COMMAND_LINE_SIZE'. But, each of the three states is *already* checking 'cmdline' for a NULL terminator. We _only_ need to check if we have overrun 'COMMAND_LINE_SIZE', and that we can do without keeping 'len' around. Also add some commends to clarify what is going on. Signed-off-by: Dave Hansen 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: fenghua.yu@intel.com Cc: yu-cheng.yu@intel.com Link: http://lkml.kernel.org/r/20151222225238.9AEB560C@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/lib/cmdline.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index 422db000d727..49548bed2301 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -21,12 +21,14 @@ static inline int myisspace(u8 c) * @option: option string to look for * * Returns the position of that @option (starts counting with 1) - * or 0 on not found. + * or 0 on not found. @option will only be found if it is found + * as an entire word in @cmdline. For instance, if @option="car" + * then a cmdline which contains "cart" will not match. */ int cmdline_find_option_bool(const char *cmdline, const char *option) { char c; - int len, pos = 0, wstart = 0; + int pos = 0, wstart = 0; const char *opptr = NULL; enum { st_wordstart = 0, /* Start of word/after whitespace */ @@ -37,11 +39,14 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) if (!cmdline) return -1; /* No command line */ - len = min_t(int, strlen(cmdline), COMMAND_LINE_SIZE); - if (!len) + if (!strlen(cmdline)) return 0; - while (len--) { + /* + * This 'pos' check ensures we do not overrun + * a non-NULL-terminated 'cmdline' + */ + while (pos < COMMAND_LINE_SIZE) { c = *(char *)cmdline++; pos++; @@ -58,17 +63,26 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) /* fall through */ case st_wordcmp: - if (!*opptr) + if (!*opptr) { + /* + * We matched all the way to the end of the + * option we were looking for. If the + * command-line has a space _or_ ends, then + * we matched! + */ if (!c || myisspace(c)) return wstart; else state = st_wordskip; - else if (!c) + } else if (!c) { + /* + * Hit the NULL terminator on the end of + * cmdline. + */ return 0; - else if (c != *opptr++) + } else if (c != *opptr++) { state = st_wordskip; - else if (!len) /* last word and is matching */ - return wstart; + } break; case st_wordskip: -- cgit From abcdc1c694fa4055323cbec1cde4c2cb6b68398c Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Dec 2015 14:52:39 -0800 Subject: x86/boot: Fix early command-line parsing when partial word matches cmdline_find_option_bool() keeps track of position in two strings: 1. the command-line 2. the option we are searchign for in the command-line We plow through each character in the command-line one at a time, always moving forward. We move forward in the option ('opptr') when we match characters in 'cmdline'. We reset the 'opptr' only when we go in to the 'st_wordstart' state. But, if we fail to match an option because we see a space (state=st_wordcmp, *opptr='\0',c=' '), we set state='st_wordskip' and 'break', moving to the next character. But, that move to the next character is the one *after* the ' '. This means that we will miss a 'st_wordstart' state. For instance, if we have cmdline = "foo fool"; and are searching for "fool", we have: "fool" opptr = ----^ "foo fool" c = --------^ We see that 'l' != ' ', set state=st_wordskip, break, and then move 'c', so: "foo fool" c = ---------^ and are still in state=st_wordskip. We will stay in wordskip until we have skipped "fool", thus missing the option we were looking for. This *only* happens when you have a partially- matching word followed by a matching one. To fix this, we always fall *into* the 'st_wordskip' state when we set it. Signed-off-by: Dave Hansen 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: fenghua.yu@intel.com Cc: yu-cheng.yu@intel.com Link: http://lkml.kernel.org/r/20151222225239.8E1DCA58@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/lib/cmdline.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index 49548bed2301..ff8d1beead6c 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -72,18 +72,26 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) */ if (!c || myisspace(c)) return wstart; - else - state = st_wordskip; + /* + * We hit the end of the option, but _not_ + * the end of a word on the cmdline. Not + * a match. + */ } else if (!c) { /* * Hit the NULL terminator on the end of * cmdline. */ return 0; - } else if (c != *opptr++) { - state = st_wordskip; + } else if (c == *opptr++) { + /* + * We are currently matching, so continue + * to the next character on the cmdline. + */ + break; } - break; + state = st_wordskip; + /* fall through */ case st_wordskip: if (!c) -- cgit From 4de07ea481361b08fe13735004dafae862482d38 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Dec 2015 14:52:41 -0800 Subject: x86/boot: Simplify early command line parsing __cmdline_find_option_bool() tries to account for both NULL-terminated and non-NULL-terminated strings. It keeps 'pos' to look for the end of the buffer and also looks for '!c' in a bunch of places to look for NULL termination. But, it also calls strlen(). You can't call strlen on a non-NULL-terminated string. If !strlen(cmdline), then cmdline[0]=='\0'. In that case, we will go in to the while() loop, set c='\0', hit st_wordstart, notice !c, and will immediately return 0. So, remove the strlen(). It is unnecessary and unsafe. Signed-off-by: Dave Hansen 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: fenghua.yu@intel.com Cc: yu-cheng.yu@intel.com Link: http://lkml.kernel.org/r/20151222225241.15365E43@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/lib/cmdline.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index ff8d1beead6c..945a639c02dd 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -39,9 +39,6 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) if (!cmdline) return -1; /* No command line */ - if (!strlen(cmdline)) - return 0; - /* * This 'pos' check ensures we do not overrun * a non-NULL-terminated 'cmdline' -- cgit From 8c0517759a1a100a8b83134cf3c7f254774aaeba Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 22 Dec 2015 14:52:43 -0800 Subject: x86/boot: Pass in size to early cmdline parsing We will use this in a few patches to implement tests for early parsing. Signed-off-by: Dave Hansen [ Aligned args properly. ] 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: fenghua.yu@intel.com Cc: yu-cheng.yu@intel.com Link: http://lkml.kernel.org/r/20151222225243.5CC47EB6@viggo.jf.intel.com Signed-off-by: Ingo Molnar --- arch/x86/lib/cmdline.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index 945a639c02dd..5cc78bf57232 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -25,7 +25,9 @@ static inline int myisspace(u8 c) * as an entire word in @cmdline. For instance, if @option="car" * then a cmdline which contains "cart" will not match. */ -int cmdline_find_option_bool(const char *cmdline, const char *option) +static int +__cmdline_find_option_bool(const char *cmdline, int max_cmdline_size, + const char *option) { char c; int pos = 0, wstart = 0; @@ -43,7 +45,7 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) * This 'pos' check ensures we do not overrun * a non-NULL-terminated 'cmdline' */ - while (pos < COMMAND_LINE_SIZE) { + while (pos < max_cmdline_size) { c = *(char *)cmdline++; pos++; @@ -101,3 +103,8 @@ int cmdline_find_option_bool(const char *cmdline, const char *option) return 0; /* Buffer overrun */ } + +int cmdline_find_option_bool(const char *cmdline, const char *option) +{ + return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option); +} -- cgit From 01441af5df438a171bce36bc3c7cfb588bc98a7a Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:23:59 +0100 Subject: perf hists: Factor output_resort from hists__output_resort Currently hists__output_resort() depends on hists based on hists_evsel struct, but we need to be able to sort common hists as well. Cutting out the sorting base sorting code into output_resort function, so it can be reused in following patch. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-2-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 098310bc4489..7797d06d4993 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1197,19 +1197,13 @@ static void __hists__insert_output_entry(struct rb_root *entries, rb_insert_color(&he->rb_node, entries); } -void hists__output_resort(struct hists *hists, struct ui_progress *prog) +static void output_resort(struct hists *hists, struct ui_progress *prog, + bool use_callchain) { struct rb_root *root; struct rb_node *next; struct hist_entry *n; u64 min_callchain_hits; - struct perf_evsel *evsel = hists_to_evsel(hists); - bool use_callchain; - - if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) - use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; - else - use_callchain = symbol_conf.use_callchain; min_callchain_hits = hists__total_period(hists) * (callchain_param.min_percent / 100); @@ -1239,6 +1233,19 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog) } } +void hists__output_resort(struct hists *hists, struct ui_progress *prog) +{ + struct perf_evsel *evsel = hists_to_evsel(hists); + bool use_callchain; + + if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) + use_callchain = evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN; + else + use_callchain = symbol_conf.use_callchain; + + output_resort(hists, prog, use_callchain); +} + static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, enum hist_filter filter) { -- cgit From 452ce03b1e686f0b2da6c1644dce7cdc71e3c69c Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:00 +0100 Subject: perf hists: Introduce perf_evsel__output_resort function Adding evsel specific function to sort hists_evsel based hists. The hists__output_resort can be now used to sort common hists object. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 10 ++++++---- tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_filter.c | 2 +- tools/perf/tests/hists_output.c | 10 +++++----- tools/perf/util/hist.c | 10 +++++++--- tools/perf/util/hist.h | 1 + 8 files changed, 23 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index cc5c1267c738..cfe366375c4b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -245,7 +245,7 @@ static int __cmd_annotate(struct perf_annotate *ann) hists__collapse_resort(hists, NULL); /* Don't sort callchain */ perf_evsel__reset_sample_bit(pos, CALLCHAIN); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(pos, NULL); if (symbol_conf.event_group && !perf_evsel__is_group_leader(pos)) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 72ed0b46d5a1..54ce0479ca28 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -507,7 +507,7 @@ static void report__output_resort(struct report *rep) ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); evlist__for_each(rep->session->evlist, pos) - hists__output_resort(evsel__hists(pos), &prog); + perf_evsel__output_resort(pos, &prog); ui_progress__finish(); } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index bf01cbb0ef23..f1bbe2a589f5 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -252,7 +252,8 @@ static void perf_top__print_sym_table(struct perf_top *top) char bf[160]; int printed = 0; const int win_width = top->winsize.ws_col - 1; - struct hists *hists = evsel__hists(top->sym_evsel); + struct perf_evsel *evsel = top->sym_evsel; + struct hists *hists = evsel__hists(evsel); puts(CONSOLE_CLEAR); @@ -288,7 +289,7 @@ static void perf_top__print_sym_table(struct perf_top *top) } hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); hists__output_recalc_col_len(hists, top->print_entries - printed); putchar('\n'); @@ -540,6 +541,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c) static void perf_top__sort_new_samples(void *arg) { struct perf_top *t = arg; + struct perf_evsel *evsel = t->sym_evsel; struct hists *hists; perf_top__reset_sample_counters(t); @@ -547,7 +549,7 @@ static void perf_top__sort_new_samples(void *arg) if (t->evlist->selected != NULL) t->sym_evsel = t->evlist->selected; - hists = evsel__hists(t->sym_evsel); + hists = evsel__hists(evsel); if (t->evlist->enabled) { if (t->zero) { @@ -559,7 +561,7 @@ static void perf_top__sort_new_samples(void *arg) } hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); } static void *display_thread_tui(void *arg) diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index 5e6a86e50fb9..ecf136c385d5 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c @@ -191,7 +191,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec * function since TEST_ASSERT_VAL() returns in case of failure. */ hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(hists_to_evsel(hists), NULL); if (verbose > 2) { pr_info("use callchain: %d, cumulate callchain: %d\n", diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 351a42463444..34b945a55d4d 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c @@ -145,7 +145,7 @@ int test__hists_filter(int subtest __maybe_unused) struct hists *hists = evsel__hists(evsel); hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("Normal histogram\n"); diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index b231265148d8..23cce67c7e48 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c @@ -156,7 +156,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -256,7 +256,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -310,7 +310,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -388,7 +388,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); @@ -491,7 +491,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine) goto out; hists__collapse_resort(hists, NULL); - hists__output_resort(hists, NULL); + perf_evsel__output_resort(evsel, NULL); if (verbose > 2) { pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 7797d06d4993..d07955c145e5 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1233,9 +1233,8 @@ static void output_resort(struct hists *hists, struct ui_progress *prog, } } -void hists__output_resort(struct hists *hists, struct ui_progress *prog) +void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog) { - struct perf_evsel *evsel = hists_to_evsel(hists); bool use_callchain; if (evsel && symbol_conf.use_callchain && !symbol_conf.show_ref_callgraph) @@ -1243,7 +1242,12 @@ void hists__output_resort(struct hists *hists, struct ui_progress *prog) else use_callchain = symbol_conf.use_callchain; - output_resort(hists, prog, use_callchain); + output_resort(evsel__hists(evsel), prog, use_callchain); +} + +void hists__output_resort(struct hists *hists, struct ui_progress *prog) +{ + output_resort(hists, prog, symbol_conf.use_callchain); } static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d4ec4822a103..bc2499794bef 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -128,6 +128,7 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, struct hists *hists); void hist_entry__delete(struct hist_entry *he); +void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); void hists__output_resort(struct hists *hists, struct ui_progress *prog); void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); -- cgit From b21a763edd5f832c6d966d9e60376f3d21009859 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:01 +0100 Subject: perf hists: Add _idx fields into struct perf_hpp_fmt Currently there's no way of comparing hpp format entries, which is needed in following patches. Adding _idx fields into struct perf_hpp_fmt to recognize and be able to compare hpp format entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 25 ++++++++++++++----------- tools/perf/util/hist.h | 1 + 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index bf2a66e254ea..d392801ea17e 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -371,7 +371,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, return 0; } -#define HPP__COLOR_PRINT_FNS(_name, _fn) \ +#define HPP__COLOR_PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ .header = hpp__header_fn, \ @@ -381,9 +381,10 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .cmp = hpp__nop_cmp, \ .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ + .idx = PERF_HPP__ ## _idx, \ } -#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn) \ +#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ .header = hpp__header_fn, \ @@ -393,9 +394,10 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .cmp = hpp__nop_cmp, \ .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ + .idx = PERF_HPP__ ## _idx, \ } -#define HPP__PRINT_FNS(_name, _fn) \ +#define HPP__PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ .header = hpp__header_fn, \ @@ -404,17 +406,18 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .cmp = hpp__nop_cmp, \ .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ + .idx = PERF_HPP__ ## _idx, \ } struct perf_hpp_fmt perf_hpp__format[] = { - HPP__COLOR_PRINT_FNS("Overhead", overhead), - HPP__COLOR_PRINT_FNS("sys", overhead_sys), - HPP__COLOR_PRINT_FNS("usr", overhead_us), - HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys), - HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us), - HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc), - HPP__PRINT_FNS("Samples", samples), - HPP__PRINT_FNS("Period", period) + HPP__COLOR_PRINT_FNS("Overhead", overhead, OVERHEAD), + HPP__COLOR_PRINT_FNS("sys", overhead_sys, OVERHEAD_SYS), + HPP__COLOR_PRINT_FNS("usr", overhead_us, OVERHEAD_US), + HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys, OVERHEAD_GUEST_SYS), + HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us, OVERHEAD_GUEST_US), + HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc, OVERHEAD_ACC), + HPP__PRINT_FNS("Samples", samples, SAMPLES), + HPP__PRINT_FNS("Period", period, PERIOD) }; LIST_HEAD(perf_hpp__list); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bc2499794bef..8a0cbdeb449e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -221,6 +221,7 @@ struct perf_hpp_fmt { bool elide; int len; int user_len; + int idx; }; extern struct list_head perf_hpp__list; -- cgit From 2e8b79e706f504801fbce19fa9f16f3c858a105e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:02 +0100 Subject: perf hists: Use struct perf_hpp_fmt::idx in perf_hpp__reset_width We are going to add dynamic hpp format fields, so we need to make the 'len' change for the format itself, not in the perf_hpp__format template. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index d392801ea17e..5a11bf0aabc7 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -629,20 +629,12 @@ unsigned int hists__sort_list_width(struct hists *hists) void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) { - int idx; - if (perf_hpp__is_sort_entry(fmt)) return perf_hpp__reset_sort_width(fmt, hists); - for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) { - if (fmt == &perf_hpp__format[idx]) - break; - } - - if (idx == PERF_HPP__MAX_INDEX) - return; + BUG_ON(fmt->idx >= PERF_HPP__MAX_INDEX); - switch (idx) { + switch (fmt->idx) { case PERF_HPP__OVERHEAD: case PERF_HPP__OVERHEAD_SYS: case PERF_HPP__OVERHEAD_US: -- cgit From 97358084b91e94e5f8fcf0379f0430c0ea16bd3b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:03 +0100 Subject: perf hists: Add 'equal' method to perf_hpp_fmt struct To easily compare format entries and make it available for all kinds of format entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 9 +++++++-- tools/perf/util/hist.h | 2 +- tools/perf/util/sort.c | 39 ++++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 5a11bf0aabc7..71c8bb71a350 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -524,6 +524,11 @@ void perf_hpp__cancel_cumulate(void) perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead"; } +static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +{ + return a->equal && a->equal(a, b); +} + void perf_hpp__setup_output_field(void) { struct perf_hpp_fmt *fmt; @@ -542,7 +547,7 @@ void perf_hpp__setup_output_field(void) struct perf_hpp_fmt *pos; perf_hpp__for_each_format(pos) { - if (perf_hpp__same_sort_entry(pos, fmt)) + if (fmt_equal(fmt, pos)) goto next; } } @@ -571,7 +576,7 @@ void perf_hpp__append_sort_keys(void) struct perf_hpp_fmt *pos; perf_hpp__for_each_sort_list(pos) { - if (perf_hpp__same_sort_entry(pos, fmt)) + if (fmt_equal(fmt, pos)) goto next; } } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 8a0cbdeb449e..9a240d7b8d3b 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -215,6 +215,7 @@ struct perf_hpp_fmt { struct hist_entry *a, struct hist_entry *b); int64_t (*sort)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b); + bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); struct list_head list; struct list_head sort_list; @@ -268,7 +269,6 @@ void perf_hpp__reset_output_field(void); void perf_hpp__append_sort_keys(void); bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); -bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format); bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hists); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 898e4b0724bf..170f7f73fe93 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1441,20 +1441,6 @@ struct hpp_sort_entry { struct sort_entry *se; }; -bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) -{ - struct hpp_sort_entry *hse_a; - struct hpp_sort_entry *hse_b; - - if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b)) - return false; - - hse_a = container_of(a, struct hpp_sort_entry, hpp); - hse_b = container_of(b, struct hpp_sort_entry, hpp); - - return hse_a->se == hse_b->se; -} - void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists) { struct hpp_sort_entry *hse; @@ -1540,6 +1526,25 @@ static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt, return sort_fn(a, b); } +bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) +{ + return format->header == __sort__hpp_header; +} + +static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +{ + struct hpp_sort_entry *hse_a; + struct hpp_sort_entry *hse_b; + + if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b)) + return false; + + hse_a = container_of(a, struct hpp_sort_entry, hpp); + hse_b = container_of(b, struct hpp_sort_entry, hpp); + + return hse_a->se == hse_b->se; +} + static struct hpp_sort_entry * __sort_dimension__alloc_hpp(struct sort_dimension *sd) { @@ -1561,6 +1566,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.cmp = __sort__hpp_cmp; hse->hpp.collapse = __sort__hpp_collapse; hse->hpp.sort = __sort__hpp_sort; + hse->hpp.equal = __sort__hpp_equal; INIT_LIST_HEAD(&hse->hpp.list); INIT_LIST_HEAD(&hse->hpp.sort_list); @@ -1571,11 +1577,6 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } -bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format) -{ - return format->header == __sort__hpp_header; -} - static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) { struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); -- cgit From c0020efa079c5fc2388945ae7e856b362731442d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:04 +0100 Subject: perf hists: Add 'hpp__equal' callback function Adding 'hpp__equal' callback function to compare hpp output format entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 71c8bb71a350..b543f4b7d7d3 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -371,6 +371,19 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, return 0; } +static bool perf_hpp__is_hpp_entry(struct perf_hpp_fmt *a) +{ + return a->header == hpp__header_fn; +} + +static bool hpp__equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) +{ + if (!perf_hpp__is_hpp_entry(a) || !perf_hpp__is_hpp_entry(b)) + return false; + + return a->idx == b->idx; +} + #define HPP__COLOR_PRINT_FNS(_name, _fn, _idx) \ { \ .name = _name, \ @@ -382,6 +395,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ .idx = PERF_HPP__ ## _idx, \ + .equal = hpp__equal, \ } #define HPP__COLOR_ACC_PRINT_FNS(_name, _fn, _idx) \ @@ -395,6 +409,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ .idx = PERF_HPP__ ## _idx, \ + .equal = hpp__equal, \ } #define HPP__PRINT_FNS(_name, _fn, _idx) \ @@ -407,6 +422,7 @@ static int64_t hpp__nop_cmp(struct perf_hpp_fmt *fmt __maybe_unused, .collapse = hpp__nop_cmp, \ .sort = hpp__sort_ ## _fn, \ .idx = PERF_HPP__ ## _idx, \ + .equal = hpp__equal, \ } struct perf_hpp_fmt perf_hpp__format[] = { -- cgit From 3f931f2c4274565fd6c6a642b16387358cbe6266 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:05 +0100 Subject: perf hists: Make hpp setup function generic Now that we have the 'equal' method implemented for hpp format entries we can ease up the logic in the following functions and make them generic wrt comparing format entries: perf_hpp__setup_output_field perf_hpp__append_sort_keys Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-8-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index b543f4b7d7d3..b0fcaecb7d1d 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -551,21 +551,11 @@ void perf_hpp__setup_output_field(void) /* append sort keys to output field */ perf_hpp__for_each_sort_list(fmt) { - if (!list_empty(&fmt->list)) - continue; + struct perf_hpp_fmt *pos; - /* - * sort entry fields are dynamically created, - * so they can share a same sort key even though - * the list is empty. - */ - if (perf_hpp__is_sort_entry(fmt)) { - struct perf_hpp_fmt *pos; - - perf_hpp__for_each_format(pos) { - if (fmt_equal(fmt, pos)) - goto next; - } + perf_hpp__for_each_format(pos) { + if (fmt_equal(fmt, pos)) + goto next; } perf_hpp__column_register(fmt); @@ -580,21 +570,11 @@ void perf_hpp__append_sort_keys(void) /* append output fields to sort keys */ perf_hpp__for_each_format(fmt) { - if (!list_empty(&fmt->sort_list)) - continue; + struct perf_hpp_fmt *pos; - /* - * sort entry fields are dynamically created, - * so they can share a same sort key even though - * the list is empty. - */ - if (perf_hpp__is_sort_entry(fmt)) { - struct perf_hpp_fmt *pos; - - perf_hpp__for_each_sort_list(pos) { - if (fmt_equal(fmt, pos)) - goto next; - } + perf_hpp__for_each_sort_list(pos) { + if (fmt_equal(fmt, pos)) + goto next; } perf_hpp__register_sort_field(fmt); -- cgit From 9887804d01abf7a4e03cfd6be0312d0a5c4e4aba Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:06 +0100 Subject: perf report: Move UI initialization ahead of sort setup The ui initialization changes hpp format callbacks, based on the used browser. Thus we need this init being processed before setup_sorting. 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/1453109064-1026-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-report.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 54ce0479ca28..1eab50ac1ef6 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -912,15 +912,6 @@ repeat: symbol_conf.cumulate_callchain = false; } - if (setup_sorting(session->evlist) < 0) { - if (sort_order) - parse_options_usage(report_usage, options, "s", 1); - if (field_order) - parse_options_usage(sort_order ? NULL : report_usage, - options, "F", 1); - goto error; - } - /* Force tty output for header output and per-thread stat. */ if (report.header || report.header_only || report.show_threads) use_browser = 0; @@ -930,6 +921,15 @@ repeat: else use_browser = 0; + if (setup_sorting(session->evlist) < 0) { + if (sort_order) + parse_options_usage(report_usage, options, "s", 1); + if (field_order) + parse_options_usage(sort_order ? NULL : report_usage, + options, "F", 1); + goto error; + } + if (report.header || report.header_only) { perf_session__fprintf_info(session, stdout, report.show_full_info); -- cgit From 3ee60c3b18bd4bf30ea9b70e7542116bb5c205ba Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 18 Jan 2016 10:24:06 +0100 Subject: perf top: Move UI initialization ahead of sort setup The ui initialization changes hpp format callbacks, based on the used browser. Thus we need this init being processed before setup_sorting. Replica of a patch by Jiri for 'perf report'. Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f1bbe2a589f5..a75de3940b97 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1245,6 +1245,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) /* display thread wants entries to be collapsed in a different tree */ sort__need_collapse = 1; + if (top.use_stdio) + use_browser = 0; + else if (top.use_tui) + use_browser = 1; + + setup_browser(false); + if (setup_sorting(top.evlist) < 0) { if (sort_order) parse_options_usage(top_usage, options, "s", 1); @@ -1254,13 +1261,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) goto out_delete_evlist; } - if (top.use_stdio) - use_browser = 0; - else if (top.use_tui) - use_browser = 1; - - setup_browser(false); - status = target__validate(target); if (status) { target__strerror(target, status, errbuf, BUFSIZ); -- cgit From 1945c3e734cd1f01535dc76de47c38bbe9a87352 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:07 +0100 Subject: perf hists: Allocate output sort field Currently we use static output fields, because we have single global list of all sort/output fields. We will add hists specific sort and output lists in following patches, so we need all format entries to be dynamically allocated. Adding support to allocate output sort field. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-10-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 16 ++++++++++++++-- tools/perf/util/sort.c | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index b0fcaecb7d1d..c877c52ff4bc 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -533,11 +533,23 @@ void perf_hpp__column_disable(unsigned col) void perf_hpp__cancel_cumulate(void) { + struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp; + if (is_strict_order(field_order)) return; - perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC); - perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead"; + ovh = &perf_hpp__format[PERF_HPP__OVERHEAD]; + acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC]; + + perf_hpp__for_each_format_safe(fmt, tmp) { + if (acc->equal(acc, fmt)) { + perf_hpp__column_unregister(fmt); + continue; + } + + if (ovh->equal(ovh, fmt)) + fmt->name = "Overhead"; + } } static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 170f7f73fe93..52e4a3674985 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1577,6 +1577,19 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } +static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) +{ + struct perf_hpp_fmt *fmt; + + fmt = memdup(hd->fmt, sizeof(*fmt)); + if (fmt) { + INIT_LIST_HEAD(&fmt->list); + INIT_LIST_HEAD(&fmt->sort_list); + } + + return fmt; +} + static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) { struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); @@ -2066,11 +2079,17 @@ static int __sort_dimension__add(struct sort_dimension *sd) static int __hpp_dimension__add(struct hpp_dimension *hd) { - if (!hd->taken) { - hd->taken = 1; + struct perf_hpp_fmt *fmt; - perf_hpp__register_sort_field(hd->fmt); - } + if (hd->taken) + return 0; + + fmt = __hpp_dimension__alloc_hpp(hd); + if (!fmt) + return -1; + + hd->taken = 1; + perf_hpp__register_sort_field(fmt); return 0; } @@ -2088,11 +2107,17 @@ static int __sort_dimension__add_output(struct sort_dimension *sd) static int __hpp_dimension__add_output(struct hpp_dimension *hd) { - if (!hd->taken) { - hd->taken = 1; + struct perf_hpp_fmt *fmt; - perf_hpp__column_register(hd->fmt); - } + if (hd->taken) + return 0; + + fmt = __hpp_dimension__alloc_hpp(hd); + if (!fmt) + return -1; + + hd->taken = 1; + perf_hpp__column_register(fmt); return 0; } -- cgit From 12cb4397fb398545207acf772b219bd751786015 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:08 +0100 Subject: perf hists: Remove perf_hpp__column_(disable|enable) Those functions are no longer needed. They operate over perf_hpp__format array which is now used only as template for dynamic entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-11-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 12 ------------ tools/perf/util/hist.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index c877c52ff4bc..80d63a997287 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -519,18 +519,6 @@ void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) list_add_tail(&format->sort_list, &perf_hpp__sort_list); } -void perf_hpp__column_enable(unsigned col) -{ - BUG_ON(col >= PERF_HPP__MAX_INDEX); - perf_hpp__column_register(&perf_hpp__format[col]); -} - -void perf_hpp__column_disable(unsigned col) -{ - BUG_ON(col >= PERF_HPP__MAX_INDEX); - perf_hpp__column_unregister(&perf_hpp__format[col]); -} - void perf_hpp__cancel_cumulate(void) { struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 9a240d7b8d3b..1f9e21dd53f3 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -259,8 +259,6 @@ enum { void perf_hpp__init(void); void perf_hpp__column_register(struct perf_hpp_fmt *format); void perf_hpp__column_unregister(struct perf_hpp_fmt *format); -void perf_hpp__column_enable(unsigned col); -void perf_hpp__column_disable(unsigned col); void perf_hpp__cancel_cumulate(void); void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); -- cgit From 564132f3116cf376fdc04b2380e621f35efbb6c7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:09 +0100 Subject: perf hists: Properly release format fields With multiple list holding format entries, we need the support properly releasing format output/sort fields. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-12-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 8 ++++++++ tools/perf/util/hist.h | 1 + tools/perf/util/sort.c | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 80d63a997287..2cd1a03bf375 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -583,6 +583,12 @@ next: } } +static void fmt_free(struct perf_hpp_fmt *fmt) +{ + if (fmt->free) + fmt->free(fmt); +} + void perf_hpp__reset_output_field(void) { struct perf_hpp_fmt *fmt, *tmp; @@ -591,12 +597,14 @@ void perf_hpp__reset_output_field(void) perf_hpp__for_each_format_safe(fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); + fmt_free(fmt); } /* reset sort keys */ perf_hpp__for_each_sort_list_safe(fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); + fmt_free(fmt); } } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1f9e21dd53f3..f3bcf2d38733 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -216,6 +216,7 @@ struct perf_hpp_fmt { int64_t (*sort)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b); bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); + void (*free)(struct perf_hpp_fmt *fmt); struct list_head list; struct list_head sort_list; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 52e4a3674985..b5389a54356d 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1545,6 +1545,14 @@ static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) return hse_a->se == hse_b->se; } +static void hse_free(struct perf_hpp_fmt *fmt) +{ + struct hpp_sort_entry *hse; + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + free(hse); +} + static struct hpp_sort_entry * __sort_dimension__alloc_hpp(struct sort_dimension *sd) { @@ -1567,6 +1575,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.collapse = __sort__hpp_collapse; hse->hpp.sort = __sort__hpp_sort; hse->hpp.equal = __sort__hpp_equal; + hse->hpp.free = hse_free; INIT_LIST_HEAD(&hse->hpp.list); INIT_LIST_HEAD(&hse->hpp.sort_list); @@ -1577,6 +1586,11 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } +static void hpp_free(struct perf_hpp_fmt *fmt) +{ + free(fmt); +} + static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) { struct perf_hpp_fmt *fmt; @@ -1585,6 +1599,7 @@ static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) if (fmt) { INIT_LIST_HEAD(&fmt->list); INIT_LIST_HEAD(&fmt->sort_list); + fmt->free = hpp_free; } return fmt; @@ -1818,6 +1833,14 @@ bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt) return fmt->cmp == __sort__hde_cmp; } +static void hde_free(struct perf_hpp_fmt *fmt) +{ + struct hpp_dynamic_entry *hde; + + hde = container_of(fmt, struct hpp_dynamic_entry, hpp); + free(hde); +} + static struct hpp_dynamic_entry * __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) { @@ -1842,6 +1865,7 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) hde->hpp.cmp = __sort__hde_cmp; hde->hpp.collapse = __sort__hde_cmp; hde->hpp.sort = __sort__hde_cmp; + hde->hpp.free = hde_free; INIT_LIST_HEAD(&hde->hpp.list); INIT_LIST_HEAD(&hde->hpp.sort_list); -- cgit From 2fbaa39079672bf52a9208ec1263385b48933cc3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:10 +0100 Subject: perf hists: Separate sort fields parsing into setup_sort_list function Separating sort fields parsing into setup_sort_list function, so it's separated from sort_order string setup and could be reused later in following patches. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-13-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index b5389a54356d..ab1c21a950f6 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2241,6 +2241,26 @@ static int sort_dimension__add(const char *tok, return -ESRCH; } +static int setup_sort_list(char *str, struct perf_evlist *evlist) +{ + char *tmp, *tok; + int ret = 0; + + for (tok = strtok_r(str, ", ", &tmp); + tok; tok = strtok_r(NULL, ", ", &tmp)) { + ret = sort_dimension__add(tok, evlist); + if (ret == -EINVAL) { + error("Invalid --sort key: `%s'", tok); + break; + } else if (ret == -ESRCH) { + error("Unknown --sort key: `%s'", tok); + break; + } + } + + return ret; +} + static const char *get_default_sort_order(struct perf_evlist *evlist) { const char *default_sort_orders[] = { @@ -2335,7 +2355,7 @@ static char *setup_overhead(char *keys) static int __setup_sorting(struct perf_evlist *evlist) { - char *tmp, *tok, *str; + char *str; const char *sort_keys; int ret = 0; @@ -2373,17 +2393,7 @@ static int __setup_sorting(struct perf_evlist *evlist) } } - for (tok = strtok_r(str, ", ", &tmp); - tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = sort_dimension__add(tok, evlist); - if (ret == -EINVAL) { - error("Invalid --sort key: `%s'", tok); - break; - } else if (ret == -ESRCH) { - error("Unknown --sort key: `%s'", tok); - break; - } - } + ret = setup_sort_list(str, evlist); free(str); return ret; -- cgit From 6d3375efebe906ad0ce55ddaa883bf41fd8c444b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:11 +0100 Subject: perf hists: Separate output fields parsing into setup_output_list function Separating output fields parsing into setup_output_list function, so it's separated from field_order string setup and could be reused later in following patches. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-14-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index ab1c21a950f6..36dbd5554f0e 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2535,6 +2535,26 @@ static int output_field_add(char *tok) return -ESRCH; } +static int setup_output_list(char *str) +{ + char *tmp, *tok; + int ret = 0; + + for (tok = strtok_r(str, ", ", &tmp); + tok; tok = strtok_r(NULL, ", ", &tmp)) { + ret = output_field_add(tok); + if (ret == -EINVAL) { + error("Invalid --fields key: `%s'", tok); + break; + } else if (ret == -ESRCH) { + error("Unknown --fields key: `%s'", tok); + break; + } + } + + return ret; +} + static void reset_dimensions(void) { unsigned int i; @@ -2559,7 +2579,7 @@ bool is_strict_order(const char *order) static int __setup_output_field(void) { - char *tmp, *tok, *str, *strp; + char *str, *strp; int ret = -EINVAL; if (field_order == NULL) @@ -2579,17 +2599,7 @@ static int __setup_output_field(void) goto out; } - for (tok = strtok_r(strp, ", ", &tmp); - tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = output_field_add(tok); - if (ret == -EINVAL) { - error("Invalid --fields key: `%s'", tok); - break; - } else if (ret == -ESRCH) { - error("Unknown --fields key: `%s'", tok); - break; - } - } + ret = setup_output_list(strp); out: free(str); -- cgit From 7c31e10266bd18de163d5c60899591c0540bb002 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:12 +0100 Subject: perf hists: Introduce struct perf_hpp_list Gather output and sort lists under struct perf_hpp_list, so we could have multiple instancies of sort/output format entries. Replacing current perf_hpp__list and perf_hpp__sort_list lists with single perf_hpp_list instance. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-15-git-send-email-jolsa@kernel.org [ Renamed fields to .{fields,sorts} as suggested by Namhyung and acked by Jiri ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 11 ++++++----- tools/perf/util/hist.h | 16 ++++++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 2cd1a03bf375..74dbeac4753b 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -436,9 +436,10 @@ struct perf_hpp_fmt perf_hpp__format[] = { HPP__PRINT_FNS("Period", period, PERIOD) }; -LIST_HEAD(perf_hpp__list); -LIST_HEAD(perf_hpp__sort_list); - +struct perf_hpp_list perf_hpp_list = { + .fields = LIST_HEAD_INIT(perf_hpp_list.fields), + .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts), +}; #undef HPP__COLOR_PRINT_FNS #undef HPP__COLOR_ACC_PRINT_FNS @@ -506,7 +507,7 @@ void perf_hpp__init(void) void perf_hpp__column_register(struct perf_hpp_fmt *format) { - list_add_tail(&format->list, &perf_hpp__list); + list_add_tail(&format->list, &perf_hpp_list.fields); } void perf_hpp__column_unregister(struct perf_hpp_fmt *format) @@ -516,7 +517,7 @@ void perf_hpp__column_unregister(struct perf_hpp_fmt *format) void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) { - list_add_tail(&format->sort_list, &perf_hpp__sort_list); + list_add_tail(&format->sort_list, &perf_hpp_list.sorts); } void perf_hpp__cancel_cumulate(void) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f3bcf2d38733..203397a6ea07 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -226,20 +226,24 @@ struct perf_hpp_fmt { int idx; }; -extern struct list_head perf_hpp__list; -extern struct list_head perf_hpp__sort_list; +struct perf_hpp_list { + struct list_head fields; + struct list_head sorts; +}; + +extern struct perf_hpp_list perf_hpp_list; #define perf_hpp__for_each_format(format) \ - list_for_each_entry(format, &perf_hpp__list, list) + list_for_each_entry(format, &perf_hpp_list.fields, list) #define perf_hpp__for_each_format_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp__list, list) + list_for_each_entry_safe(format, tmp, &perf_hpp_list.fields, list) #define perf_hpp__for_each_sort_list(format) \ - list_for_each_entry(format, &perf_hpp__sort_list, sort_list) + list_for_each_entry(format, &perf_hpp_list.sorts, sort_list) #define perf_hpp__for_each_sort_list_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp__sort_list, sort_list) + list_for_each_entry_safe(format, tmp, &perf_hpp_list.sorts, sort_list) extern struct perf_hpp_fmt perf_hpp__format[]; -- cgit From 94b3dc3865097e11073f1abf5b20b5f80af223af Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:13 +0100 Subject: perf hists: Introduce perf_hpp_list__init function Introducing perf_hpp_list__init function to have an easy way to initialize perf_hpp_list struct. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-16-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 6 ++++++ tools/perf/util/hist.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index d07955c145e5..b762ecc31505 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1642,3 +1642,9 @@ int hists__init(void) return err; } + +void perf_hpp_list__init(struct perf_hpp_list *list) +{ + INIT_LIST_HEAD(&list->fields); + INIT_LIST_HEAD(&list->sorts); +} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 203397a6ea07..e22f98e3fc6d 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -386,4 +386,6 @@ int parse_filter_percentage(const struct option *opt __maybe_unused, const char *arg, int unset __maybe_unused); int perf_hist_config(const char *var, const char *value); +void perf_hpp_list__init(struct perf_hpp_list *list); + #endif /* __PERF_HIST_H */ -- cgit From ebdd98e030f5ed6dd1bae9ab01b084f97685bd60 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:14 +0100 Subject: perf hists: Add perf_hpp_list register helpers Adding 2 perf_hpp_list register helpers: perf_hpp_list__column_register() perf_hpp_list__register_sort_field() to be called within existing helpers: perf_hpp__column_register() perf_hpp__register_sort_field() to register format entries within global perf_hpp_list object. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-17-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 14 ++++++++------ tools/perf/util/hist.h | 18 +++++++++++++++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 74dbeac4753b..1655c0d9c089 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -505,19 +505,21 @@ void perf_hpp__init(void) hpp_dimension__add_output(PERF_HPP__PERIOD); } -void perf_hpp__column_register(struct perf_hpp_fmt *format) +void perf_hpp_list__column_register(struct perf_hpp_list *list, + struct perf_hpp_fmt *format) { - list_add_tail(&format->list, &perf_hpp_list.fields); + list_add_tail(&format->list, &list->fields); } -void perf_hpp__column_unregister(struct perf_hpp_fmt *format) +void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, + struct perf_hpp_fmt *format) { - list_del(&format->list); + list_add_tail(&format->sort_list, &list->sorts); } -void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) +void perf_hpp__column_unregister(struct perf_hpp_fmt *format) { - list_add_tail(&format->sort_list, &perf_hpp_list.sorts); + list_del(&format->list); } void perf_hpp__cancel_cumulate(void) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index e22f98e3fc6d..a7769d778374 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -233,6 +233,21 @@ struct perf_hpp_list { extern struct perf_hpp_list perf_hpp_list; +void perf_hpp_list__column_register(struct perf_hpp_list *list, + struct perf_hpp_fmt *format); +void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, + struct perf_hpp_fmt *format); + +static inline void perf_hpp__column_register(struct perf_hpp_fmt *format) +{ + perf_hpp_list__column_register(&perf_hpp_list, format); +} + +static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) +{ + perf_hpp_list__register_sort_field(&perf_hpp_list, format); +} + #define perf_hpp__for_each_format(format) \ list_for_each_entry(format, &perf_hpp_list.fields, list) @@ -262,11 +277,8 @@ enum { }; void perf_hpp__init(void); -void perf_hpp__column_register(struct perf_hpp_fmt *format); void perf_hpp__column_unregister(struct perf_hpp_fmt *format); void perf_hpp__cancel_cumulate(void); - -void perf_hpp__register_sort_field(struct perf_hpp_fmt *format); void perf_hpp__setup_output_field(void); void perf_hpp__reset_output_field(void); void perf_hpp__append_sort_keys(void); -- cgit From 07600027fb7114bf7bcabdd121e5178f200d8a44 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:16 +0100 Subject: perf hists: Pass perf_hpp_list all the way through setup_output_list Passing perf_hpp_list all the way through setup_output_list so the output entry could be added on the arbitrary list. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-19-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 36dbd5554f0e..f643bed8f63b 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1616,14 +1616,15 @@ static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) return 0; } -static int __sort_dimension__add_hpp_output(struct sort_dimension *sd) +static int __sort_dimension__add_hpp_output(struct perf_hpp_list *list, + struct sort_dimension *sd) { struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); if (hse == NULL) return -1; - perf_hpp__column_register(&hse->hpp); + perf_hpp_list__column_register(list, &hse->hpp); return 0; } @@ -2117,19 +2118,21 @@ static int __hpp_dimension__add(struct hpp_dimension *hd) return 0; } -static int __sort_dimension__add_output(struct sort_dimension *sd) +static int __sort_dimension__add_output(struct perf_hpp_list *list, + struct sort_dimension *sd) { if (sd->taken) return 0; - if (__sort_dimension__add_hpp_output(sd) < 0) + if (__sort_dimension__add_hpp_output(list, sd) < 0) return -1; sd->taken = 1; return 0; } -static int __hpp_dimension__add_output(struct hpp_dimension *hd) +static int __hpp_dimension__add_output(struct perf_hpp_list *list, + struct hpp_dimension *hd) { struct perf_hpp_fmt *fmt; @@ -2141,14 +2144,14 @@ static int __hpp_dimension__add_output(struct hpp_dimension *hd) return -1; hd->taken = 1; - perf_hpp__column_register(fmt); + perf_hpp_list__column_register(list, fmt); return 0; } int hpp_dimension__add_output(unsigned col) { BUG_ON(col >= PERF_HPP__MAX_INDEX); - return __hpp_dimension__add_output(&hpp_sort_dimensions[col]); + return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]); } static int sort_dimension__add(const char *tok, @@ -2492,7 +2495,7 @@ void sort__setup_elide(FILE *output) } } -static int output_field_add(char *tok) +static int output_field_add(struct perf_hpp_list *list, char *tok) { unsigned int i; @@ -2502,7 +2505,7 @@ static int output_field_add(char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - return __sort_dimension__add_output(sd); + return __sort_dimension__add_output(list, sd); } for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { @@ -2511,7 +2514,7 @@ static int output_field_add(char *tok) if (strncasecmp(tok, hd->name, strlen(tok))) continue; - return __hpp_dimension__add_output(hd); + return __hpp_dimension__add_output(list, hd); } for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { @@ -2520,7 +2523,7 @@ static int output_field_add(char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - return __sort_dimension__add_output(sd); + return __sort_dimension__add_output(list, sd); } for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) { @@ -2529,20 +2532,20 @@ static int output_field_add(char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - return __sort_dimension__add_output(sd); + return __sort_dimension__add_output(list, sd); } return -ESRCH; } -static int setup_output_list(char *str) +static int setup_output_list(struct perf_hpp_list *list, char *str) { char *tmp, *tok; int ret = 0; for (tok = strtok_r(str, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = output_field_add(tok); + ret = output_field_add(list, tok); if (ret == -EINVAL) { error("Invalid --fields key: `%s'", tok); break; @@ -2599,7 +2602,7 @@ static int __setup_output_field(void) goto out; } - ret = setup_output_list(strp); + ret = setup_output_list(&perf_hpp_list, strp); out: free(str); -- cgit From cf094045d718437e3d5cd42ac09d77561cb2f368 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:17 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_format macro Introducing perf_hpp_list__for_each_format macro to iterate perf_hpp_list object's output entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-20-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 8 ++++---- tools/perf/ui/gtk/hists.c | 6 +++--- tools/perf/ui/hist.c | 8 ++++---- tools/perf/ui/stdio/hist.c | 8 ++++---- tools/perf/util/hist.h | 4 ++-- tools/perf/util/sort.c | 8 ++++---- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 61d578bf4ffd..df0aedfaea75 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1095,7 +1095,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, hist_browser__gotorc(browser, row, 0); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, entry->hists) || column++ < browser->b.horiz_scroll) continue; @@ -1175,7 +1175,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * return ret; } - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) continue; @@ -1441,7 +1441,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) printed += fprintf(fp, "%c ", folded_sign); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -2104,7 +2104,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, memset(options, 0, sizeof(options)); memset(actions, 0, sizeof(actions)); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { perf_hpp__reset_width(fmt, hists); /* * This is done just once, and activates the horizontal scrolling diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index 0f8dcfdfb10f..eca5151f91d7 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -306,7 +306,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, nr_cols = 0; - perf_hpp__for_each_format(fmt) + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) col_types[nr_cols++] = G_TYPE_STRING; store = gtk_tree_store_newv(nr_cols, col_types); @@ -317,7 +317,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -367,7 +367,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, h->hists)) continue; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 1655c0d9c089..7b5e8cedf853 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -556,7 +556,7 @@ void perf_hpp__setup_output_field(void) perf_hpp__for_each_sort_list(fmt) { struct perf_hpp_fmt *pos; - perf_hpp__for_each_format(pos) { + perf_hpp_list__for_each_format(&perf_hpp_list, pos) { if (fmt_equal(fmt, pos)) goto next; } @@ -572,7 +572,7 @@ void perf_hpp__append_sort_keys(void) struct perf_hpp_fmt *fmt; /* append output fields to sort keys */ - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { struct perf_hpp_fmt *pos; perf_hpp__for_each_sort_list(pos) { @@ -621,7 +621,7 @@ unsigned int hists__sort_list_width(struct hists *hists) bool first = true; struct perf_hpp dummy_hpp; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -674,7 +674,7 @@ void perf_hpp__set_user_width(const char *width_list_str) struct perf_hpp_fmt *fmt; const char *ptr = width_list_str; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { char *p; int len = strtol(ptr, &p, 10); diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 691e52ce7510..83e0bf2ab986 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -384,7 +384,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) if (symbol_conf.exclude_other && !he->parent) return 0; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -453,7 +453,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, init_rem_hits(); - perf_hpp__for_each_format(fmt) + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) perf_hpp__reset_width(fmt, hists); if (symbol_conf.col_width_list_str) @@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -488,7 +488,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { unsigned int i; if (perf_hpp__should_skip(fmt, hists)) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index a7769d778374..eadffca1a501 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -248,8 +248,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) perf_hpp_list__register_sort_field(&perf_hpp_list, format); } -#define perf_hpp__for_each_format(format) \ - list_for_each_entry(format, &perf_hpp_list.fields, list) +#define perf_hpp_list__for_each_format(_list, format) \ + list_for_each_entry(format, &(_list)->fields, list) #define perf_hpp__for_each_format_safe(format, tmp) \ list_for_each_entry_safe(format, tmp, &perf_hpp_list.fields, list) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index f643bed8f63b..1e134ff56ad4 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2407,7 +2407,7 @@ void perf_hpp__set_elide(int idx, bool elide) struct perf_hpp_fmt *fmt; struct hpp_sort_entry *hse; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; @@ -2467,7 +2467,7 @@ void sort__setup_elide(FILE *output) struct perf_hpp_fmt *fmt; struct hpp_sort_entry *hse; - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; @@ -2479,7 +2479,7 @@ void sort__setup_elide(FILE *output) * It makes no sense to elide all of sort entries. * Just revert them to show up again. */ - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; @@ -2487,7 +2487,7 @@ void sort__setup_elide(FILE *output) return; } - perf_hpp__for_each_format(fmt) { + perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { if (!perf_hpp__is_sort_entry(fmt)) continue; -- cgit From 7a1799e0a276069d8b903ba17179b4983b98c04b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:18 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_format_safe macro Introducing perf_hpp_list__for_each_format_safe macro to iterate perf_hpp_list object's output entries safely. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-21-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 4 ++-- tools/perf/util/hist.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 7b5e8cedf853..348706a908f9 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -532,7 +532,7 @@ void perf_hpp__cancel_cumulate(void) ovh = &perf_hpp__format[PERF_HPP__OVERHEAD]; acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC]; - perf_hpp__for_each_format_safe(fmt, tmp) { + perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { if (acc->equal(acc, fmt)) { perf_hpp__column_unregister(fmt); continue; @@ -597,7 +597,7 @@ void perf_hpp__reset_output_field(void) struct perf_hpp_fmt *fmt, *tmp; /* reset output fields */ - perf_hpp__for_each_format_safe(fmt, tmp) { + perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index eadffca1a501..f5b2309de16e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -251,8 +251,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_format(_list, format) \ list_for_each_entry(format, &(_list)->fields, list) -#define perf_hpp__for_each_format_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp_list.fields, list) +#define perf_hpp_list__for_each_format_safe(_list, format, tmp) \ + list_for_each_entry_safe(format, tmp, &(_list)->fields, list) #define perf_hpp__for_each_sort_list(format) \ list_for_each_entry(format, &perf_hpp_list.sorts, sort_list) -- cgit From d29a497090845002ee449c8dc682dd59ad8bab42 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:19 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_sort_list macro Introducing perf_hpp_list__for_each_sort_list macro to iterate perf_hpp_list object's sort entries. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-22-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 4 ++-- tools/perf/util/hist.c | 6 +++--- tools/perf/util/hist.h | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 348706a908f9..f09eabe18167 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -553,7 +553,7 @@ void perf_hpp__setup_output_field(void) struct perf_hpp_fmt *fmt; /* append sort keys to output field */ - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { struct perf_hpp_fmt *pos; perf_hpp_list__for_each_format(&perf_hpp_list, pos) { @@ -575,7 +575,7 @@ void perf_hpp__append_sort_keys(void) perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { struct perf_hpp_fmt *pos; - perf_hpp__for_each_sort_list(pos) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, pos) { if (fmt_equal(fmt, pos)) goto next; } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b762ecc31505..dea475d1fab0 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -961,7 +961,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { cmp = fmt->cmp(fmt, left, right); if (cmp) break; @@ -976,7 +976,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { cmp = fmt->collapse(fmt, left, right); if (cmp) break; @@ -1120,7 +1120,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b) struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp__for_each_sort_list(fmt) { + perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { if (perf_hpp__should_skip(fmt, a->hists)) continue; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f5b2309de16e..c9b2ea4a4929 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -254,8 +254,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_format_safe(_list, format, tmp) \ list_for_each_entry_safe(format, tmp, &(_list)->fields, list) -#define perf_hpp__for_each_sort_list(format) \ - list_for_each_entry(format, &perf_hpp_list.sorts, sort_list) +#define perf_hpp_list__for_each_sort_list(_list, format) \ + list_for_each_entry(format, &(_list)->sorts, sort_list) #define perf_hpp__for_each_sort_list_safe(format, tmp) \ list_for_each_entry_safe(format, tmp, &perf_hpp_list.sorts, sort_list) -- cgit From 1a8ebd243a0b65c2a6d1458705d04dece937ab52 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:20 +0100 Subject: perf hists: Introduce perf_hpp_list__for_each_sort_list_safe macro Introducing perf_hpp_list__for_each_sort_list_safe macro to iterate perf_hpp_list object's sort entries safely. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-23-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 2 +- tools/perf/util/hist.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index f09eabe18167..9cda51edfdbd 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -604,7 +604,7 @@ void perf_hpp__reset_output_field(void) } /* reset sort keys */ - perf_hpp__for_each_sort_list_safe(fmt, tmp) { + perf_hpp_list__for_each_sort_list_safe(&perf_hpp_list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index c9b2ea4a4929..61d35a9f928b 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -257,8 +257,8 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_sort_list(_list, format) \ list_for_each_entry(format, &(_list)->sorts, sort_list) -#define perf_hpp__for_each_sort_list_safe(format, tmp) \ - list_for_each_entry_safe(format, tmp, &perf_hpp_list.sorts, sort_list) +#define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp) \ + list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) extern struct perf_hpp_fmt perf_hpp__format[]; -- cgit From 43e0a68f13047750a3728c983a539c61fb4121c5 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:21 +0100 Subject: perf hists: Add struct perf_hpp_list argument to helper functions Adding struct perf_hpp_list argument to following helper functions: void perf_hpp__setup_output_field(struct perf_hpp_list *list); void perf_hpp__reset_output_field(struct perf_hpp_list *list); void perf_hpp__append_sort_keys(struct perf_hpp_list *list); so they could be used on hists's hpp_list. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-24-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 19 ++++++++++--------- tools/perf/util/hist.h | 7 ++++--- tools/perf/util/sort.c | 6 +++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 9cda51edfdbd..8075d4cc54a8 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -548,15 +548,15 @@ static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) return a->equal && a->equal(a, b); } -void perf_hpp__setup_output_field(void) +void perf_hpp__setup_output_field(struct perf_hpp_list *list) { struct perf_hpp_fmt *fmt; /* append sort keys to output field */ - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + perf_hpp_list__for_each_sort_list(list, fmt) { struct perf_hpp_fmt *pos; - perf_hpp_list__for_each_format(&perf_hpp_list, pos) { + perf_hpp_list__for_each_format(list, pos) { if (fmt_equal(fmt, pos)) goto next; } @@ -567,15 +567,15 @@ next: } } -void perf_hpp__append_sort_keys(void) +void perf_hpp__append_sort_keys(struct perf_hpp_list *list) { struct perf_hpp_fmt *fmt; /* append output fields to sort keys */ - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + perf_hpp_list__for_each_format(list, fmt) { struct perf_hpp_fmt *pos; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, pos) { + perf_hpp_list__for_each_sort_list(list, pos) { if (fmt_equal(fmt, pos)) goto next; } @@ -586,25 +586,26 @@ next: } } + static void fmt_free(struct perf_hpp_fmt *fmt) { if (fmt->free) fmt->free(fmt); } -void perf_hpp__reset_output_field(void) +void perf_hpp__reset_output_field(struct perf_hpp_list *list) { struct perf_hpp_fmt *fmt, *tmp; /* reset output fields */ - perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { + perf_hpp_list__for_each_format_safe(list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); } /* reset sort keys */ - perf_hpp_list__for_each_sort_list_safe(&perf_hpp_list, fmt, tmp) { + perf_hpp_list__for_each_sort_list_safe(list, fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); fmt_free(fmt); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 61d35a9f928b..a39c9c1159ff 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -279,9 +279,10 @@ enum { void perf_hpp__init(void); void perf_hpp__column_unregister(struct perf_hpp_fmt *format); void perf_hpp__cancel_cumulate(void); -void perf_hpp__setup_output_field(void); -void perf_hpp__reset_output_field(void); -void perf_hpp__append_sort_keys(void); +void perf_hpp__setup_output_field(struct perf_hpp_list *list); +void perf_hpp__reset_output_field(struct perf_hpp_list *list); +void perf_hpp__append_sort_keys(struct perf_hpp_list *list); + bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *format); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 1e134ff56ad4..de620f7f40f4 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -2636,9 +2636,9 @@ int setup_sorting(struct perf_evlist *evlist) return err; /* copy sort keys to output fields */ - perf_hpp__setup_output_field(); + perf_hpp__setup_output_field(&perf_hpp_list); /* and then copy output fields to sort keys */ - perf_hpp__append_sort_keys(); + perf_hpp__append_sort_keys(&perf_hpp_list); return 0; } @@ -2654,5 +2654,5 @@ void reset_output_field(void) sort_order = NULL; reset_dimensions(); - perf_hpp__reset_output_field(); + perf_hpp__reset_output_field(&perf_hpp_list); } -- cgit From 5b65855e20348a9e2772a1cb7c1e6ab477859ba6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:22 +0100 Subject: perf tools: Add hpp_list into struct hists object Adding hpp_list into struct hists object. Initializing struct hists_evsel hists object to carry global perf_hpp_list list. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-25-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 5 +++-- tools/perf/util/hist.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index dea475d1fab0..2b9cc9129692 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1578,7 +1578,7 @@ int perf_hist_config(const char *var, const char *value) return 0; } -int __hists__init(struct hists *hists) +int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list) { memset(hists, 0, sizeof(*hists)); hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; @@ -1587,6 +1587,7 @@ int __hists__init(struct hists *hists) hists->entries = RB_ROOT; pthread_mutex_init(&hists->lock, NULL); hists->socket_filter = -1; + hists->hpp_list = hpp_list; return 0; } @@ -1623,7 +1624,7 @@ static int hists_evsel__init(struct perf_evsel *evsel) { struct hists *hists = evsel__hists(evsel); - __hists__init(hists); + __hists__init(hists, &perf_hpp_list); return 0; } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index a39c9c1159ff..b296ff5b9683 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -75,6 +75,7 @@ struct hists { u64 event_stream; u16 col_len[HISTC_NR_COLS]; int socket_filter; + struct perf_hpp_list *hpp_list; }; struct hist_entry_iter; @@ -186,7 +187,7 @@ static inline struct hists *evsel__hists(struct perf_evsel *evsel) } int hists__init(void); -int __hists__init(struct hists *hists); +int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); struct rb_root *hists__get_rotate_entries_in(struct hists *hists); bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, -- cgit From f0786af536bb0ba54cb516eee493af03cefdbaa3 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:23 +0100 Subject: perf hists: Introduce hists__for_each_format macro With the hist object having the perf_hpp_list we can now iterate output format entries based in the hists object. Adding hists__for_each_format macro to do that. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-26-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 8 ++++---- tools/perf/ui/gtk/hists.c | 6 +++--- tools/perf/ui/hist.c | 2 +- tools/perf/ui/stdio/hist.c | 8 ++++---- tools/perf/util/hist.h | 3 +++ 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index df0aedfaea75..3a1e0965a8fd 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1095,7 +1095,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, hist_browser__gotorc(browser, row, 0); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, entry->hists) || column++ < browser->b.horiz_scroll) continue; @@ -1175,7 +1175,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char * return ret; } - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) continue; @@ -1441,7 +1441,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) printed += fprintf(fp, "%c ", folded_sign); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -2104,7 +2104,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, memset(options, 0, sizeof(options)); memset(actions, 0, sizeof(actions)); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(browser->hists, fmt) { perf_hpp__reset_width(fmt, hists); /* * This is done just once, and activates the horizontal scrolling diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index eca5151f91d7..32cc38a5b57f 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c @@ -306,7 +306,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, nr_cols = 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) + hists__for_each_format(hists, fmt) col_types[nr_cols++] = G_TYPE_STRING; store = gtk_tree_store_newv(nr_cols, col_types); @@ -317,7 +317,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -367,7 +367,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, col_idx = 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, h->hists)) continue; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 8075d4cc54a8..1ba4117d9c2d 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -622,7 +622,7 @@ unsigned int hists__sort_list_width(struct hists *hists) bool first = true; struct perf_hpp dummy_hpp; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 83e0bf2ab986..1a6e8f7f38c4 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -384,7 +384,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) if (symbol_conf.exclude_other && !he->parent) return 0; - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(he->hists, fmt) { if (perf_hpp__should_skip(fmt, he->hists)) continue; @@ -453,7 +453,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, init_rem_hits(); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) + hists__for_each_format(hists, fmt) perf_hpp__reset_width(fmt, hists); if (symbol_conf.col_width_list_str) @@ -464,7 +464,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { if (perf_hpp__should_skip(fmt, hists)) continue; @@ -488,7 +488,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, fprintf(fp, "# "); - perf_hpp_list__for_each_format(&perf_hpp_list, fmt) { + hists__for_each_format(hists, fmt) { unsigned int i; if (perf_hpp__should_skip(fmt, hists)) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b296ff5b9683..bc900448e36f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -261,6 +261,9 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define perf_hpp_list__for_each_sort_list_safe(_list, format, tmp) \ list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list) +#define hists__for_each_format(hists, format) \ + perf_hpp_list__for_each_format((hists)->hpp_list, fmt) + extern struct perf_hpp_fmt perf_hpp__format[]; enum { -- cgit From aa6f50af822a552b579252ecd42224e09e11e879 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:24 +0100 Subject: perf hists: Introduce hists__for_each_sort_list macro With the hist object having the perf_hpp_list we can now iterate sort format entries based in the hists object. Adding hists__for_each_sort_list macro to do that. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-27-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 9 ++++++--- tools/perf/util/hist.h | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 2b9cc9129692..12f2d794dc28 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -958,10 +958,11 @@ out: int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) { + struct hists *hists = left->hists; struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + hists__for_each_sort_list(hists, fmt) { cmp = fmt->cmp(fmt, left, right); if (cmp) break; @@ -973,10 +974,11 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) { + struct hists *hists = left->hists; struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + hists__for_each_sort_list(hists, fmt) { cmp = fmt->collapse(fmt, left, right); if (cmp) break; @@ -1117,10 +1119,11 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog) static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b) { + struct hists *hists = a->hists; struct perf_hpp_fmt *fmt; int64_t cmp = 0; - perf_hpp_list__for_each_sort_list(&perf_hpp_list, fmt) { + hists__for_each_sort_list(hists, fmt) { if (perf_hpp__should_skip(fmt, a->hists)) continue; diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bc900448e36f..1c7544a8fe1a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -264,6 +264,9 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) #define hists__for_each_format(hists, format) \ perf_hpp_list__for_each_format((hists)->hpp_list, fmt) +#define hists__for_each_sort_list(hists, format) \ + perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt) + extern struct perf_hpp_fmt perf_hpp__format[]; enum { -- cgit From c6f5f6b662719ded53700deefec7dbc4227c9778 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 3 Feb 2016 23:11:20 +0900 Subject: perf report: Update documentation of --sort option The description of the memory sort key (used by --mem-mode) was misplaced. Move it under the --sort option so that it can be referenced properly. Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1454508683-5735-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-report.txt | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 8a301f6afb37..1cb8fac596b1 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -117,6 +117,22 @@ OPTIONS And default sort keys are changed to comm, dso_from, symbol_from, dso_to and symbol_to, see '--branch-stack'. + If the --mem-mode option is used, the following sort keys are also available + (incompatible with --branch-stack): + symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. + + - symbol_daddr: name of data symbol being executed on at the time of sample + - dso_daddr: name of library or module containing the data being executed + on at the time of the sample + - locked: whether the bus was locked at the time of the sample + - tlb: type of tlb access for the data at the time of the sample + - mem: type of memory access for the data at the time of the sample + - snoop: type of snoop (if any) for the data at the time of the sample + - dcacheline: the cacheline the data address is on at the time of the sample + + And the default sort keys are changed to local_weight, mem, sym, dso, + symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. + If the data file has tracepoint event(s), following (dynamic) sort keys are also available: trace, trace_fields, [.][/raw] @@ -151,22 +167,6 @@ OPTIONS By default, every sort keys not specified in -F will be appended automatically. - If --mem-mode option is used, following sort keys are also available - (incompatible with --branch-stack): - symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. - - - symbol_daddr: name of data symbol being executed on at the time of sample - - dso_daddr: name of library or module containing the data being executed - on at the time of sample - - locked: whether the bus was locked at the time of sample - - tlb: type of tlb access for the data at the time of sample - - mem: type of memory access for the data at the time of sample - - snoop: type of snoop (if any) for the data at the time of sample - - dcacheline: the cacheline the data address is on at the time of sample - - And default sort keys are changed to local_weight, mem, sym, dso, - symbol_daddr, dso_daddr, snoop, tlb, locked, see '--mem-mode'. - -p:: --parent=:: A regex filter to identify parent. The parent is a caller of this -- cgit From 1ba2fc6de4ac1a87e3ece65651795760ea5cf658 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 3 Feb 2016 23:11:21 +0900 Subject: perf report: Update documention of --percent-limit option The --percent-limit option was changed to be applied to callchains as well as to hist entries recently, but it missed to update the doc. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1454508683-5735-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-report.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 1cb8fac596b1..89cab84e92fd 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -351,7 +351,10 @@ OPTIONS --percent-limit:: Do not show entries which have an overhead under that percent. - (Default: 0). + (Default: 0). Note that this option also sets the percent limit (threshold) + of callchains. However the default value of callchain threshold is + different than the default value of hist entries. Please see the + --call-graph option for details. --percentage:: Determine how to display the overhead percentage of filtered entries. -- cgit From b62e8dfcda8cb133c062c0e1207afea2476eb7fd Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 3 Feb 2016 23:11:23 +0900 Subject: perf hists browser: Add 'L' hotkey to change percent limit Add 'L' key action to change the percent limit applied to both of hist entries and callchains. Suggested-by: Arnaldo Carvalho de Melo Signed-off-by: Namhyung Kim Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Wang Nan Link: http://lkml.kernel.org/r/1454508683-5735-4-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 3a1e0965a8fd..a5a5390476ac 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -2029,6 +2029,42 @@ static void hist_browser__update_nr_entries(struct hist_browser *hb) hb->nr_non_filtered_entries = nr_entries; } +static void hist_browser__update_percent_limit(struct hist_browser *hb, + double percent) +{ + struct hist_entry *he; + struct rb_node *nd = rb_first(&hb->hists->entries); + u64 total = hists__total_period(hb->hists); + u64 min_callchain_hits = total * (percent / 100); + + hb->min_pcnt = callchain_param.min_percent = percent; + + if (!symbol_conf.use_callchain) + return; + + while ((nd = hists__filter_entries(nd, hb->min_pcnt)) != NULL) { + he = rb_entry(nd, struct hist_entry, rb_node); + + if (callchain_param.mode == CHAIN_GRAPH_REL) { + total = he->stat.period; + + if (symbol_conf.cumulate_callchain) + total = he->stat_acc->period; + + min_callchain_hits = total * (percent / 100); + } + + callchain_param.sort(&he->sorted_chain, he->callchain, + min_callchain_hits, &callchain_param); + + /* force to re-evaluate folding state of callchains */ + he->init_have_children = false; + hist_entry__set_folding(he, false); + + nd = rb_next(nd); + } +} + static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, const char *helpline, bool left_exits, @@ -2064,6 +2100,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "E Expand all callchains\n" \ "F Toggle percentage of filtered entries\n" \ "H Display column headers\n" \ + "L Change percent limit\n" \ "m Display context menu\n" \ "S Zoom into current Processor Socket\n" \ @@ -2219,6 +2256,24 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, top->zero = !top->zero; } continue; + case 'L': + if (ui_browser__input_window("Percent Limit", + "Please enter the value you want to hide entries under that percent.", + buf, "ENTER: OK, ESC: Cancel", + delay_secs * 2) == K_ENTER) { + char *end; + double new_percent = strtod(buf, &end); + + if (new_percent < 0 || new_percent > 100) { + ui_browser__warning(&browser->b, delay_secs * 2, + "Invalid percent: %.2f", new_percent); + continue; + } + + hist_browser__update_percent_limit(browser, new_percent); + hist_browser__reset(browser); + } + continue; case K_F1: case 'h': case '?': -- cgit From 4a6180ea7399b945cd380dc63e2e8118f9b432d3 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Wed, 3 Feb 2016 19:53:24 +0800 Subject: ASoC: rt5514: add rt5514 codec driver This is the initial codec driver for rt5514. The codec includes a low power DSP for voice wake up. The register address is incremental by 4 in the DSP memory map. In order to recover the codec settings in the codec mode and manipulate the DSP mode for voice wake up, we use the multi-level register map. One is for ALSA API in codec mode that can be recovered by cache before recording. Another is for DSP related settings that can be accessed with 32bit address of the DSP in the application of voice wake up. Signed-off-by: Oder Chiou Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt5514.txt | 25 + sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt5514.c | 982 +++++++++++++++++++++ sound/soc/codecs/rt5514.h | 252 ++++++ 5 files changed, 1267 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rt5514.txt create mode 100644 sound/soc/codecs/rt5514.c create mode 100644 sound/soc/codecs/rt5514.h diff --git a/Documentation/devicetree/bindings/sound/rt5514.txt b/Documentation/devicetree/bindings/sound/rt5514.txt new file mode 100644 index 000000000000..e24436fc5ea9 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5514.txt @@ -0,0 +1,25 @@ +RT5514 audio CODEC + +This device supports I2C only. + +Required properties: + +- compatible : "realtek,rt5514". + +- reg : The I2C address of the device. + +Pins on the device (for linking into audio routes) for RT5514: + + * DMIC1L + * DMIC1R + * DMIC2L + * DMIC2R + * AMICL + * AMICR + +Example: + +codec: rt5514@57 { + compatible = "realtek,rt5514"; + reg = <0x57>; +}; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 50693c867e71..dabd479bf1f0 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -95,6 +95,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_PCM512x_SPI if SPI_MASTER select SND_SOC_RT286 if I2C select SND_SOC_RT298 if I2C + select SND_SOC_RT5514 if I2C select SND_SOC_RT5616 if I2C select SND_SOC_RT5631 if I2C select SND_SOC_RT5640 if I2C @@ -565,6 +566,7 @@ config SND_SOC_PCM512x_SPI config SND_SOC_RL6231 tristate + default y if SND_SOC_RT5514=y default y if SND_SOC_RT5616=y default y if SND_SOC_RT5640=y default y if SND_SOC_RT5645=y @@ -572,6 +574,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT5659=y default y if SND_SOC_RT5670=y default y if SND_SOC_RT5677=y + default m if SND_SOC_RT5514=m default m if SND_SOC_RT5616=m default m if SND_SOC_RT5640=m default m if SND_SOC_RT5645=m @@ -595,6 +598,9 @@ config SND_SOC_RT298 tristate depends on I2C +config SND_SOC_RT5514 + tristate + config SND_SOC_RT5616 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index d44f7d347183..79f95dd4ed68 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -92,6 +92,7 @@ snd-soc-rl6231-objs := rl6231.o snd-soc-rl6347a-objs := rl6347a.o snd-soc-rt286-objs := rt286.o snd-soc-rt298-objs := rt298.o +snd-soc-rt5514-objs := rt5514.o snd-soc-rt5616-objs := rt5616.o snd-soc-rt5631-objs := rt5631.o snd-soc-rt5640-objs := rt5640.o @@ -296,6 +297,7 @@ obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o +obj-$(CONFIG_SND_SOC_RT5514) += snd-soc-rt5514.o obj-$(CONFIG_SND_SOC_RT5616) += snd-soc-rt5616.o obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c new file mode 100644 index 000000000000..879bf60f4965 --- /dev/null +++ b/sound/soc/codecs/rt5514.c @@ -0,0 +1,982 @@ +/* + * rt5514.c -- RT5514 ALSA SoC audio codec driver + * + * Copyright 2015 Realtek Semiconductor Corp. + * Author: Oder Chiou + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt5514.h" + +static const struct reg_sequence rt5514_i2c_patch[] = { + {0x1800101c, 0x00000000}, + {0x18001100, 0x0000031f}, + {0x18001104, 0x00000007}, + {0x18001108, 0x00000000}, + {0x1800110c, 0x00000000}, + {0x18001110, 0x00000000}, + {0x18001114, 0x00000001}, + {0x18001118, 0x00000000}, + {0x18002f08, 0x00000006}, + {0x18002f00, 0x00055149}, + {0x18002f00, 0x0005514b}, + {0x18002f00, 0x00055149}, + {0xfafafafa, 0x00000001}, + {0x18002f10, 0x00000001}, + {0x18002f10, 0x00000000}, + {0x18002f10, 0x00000001}, + {0xfafafafa, 0x00000001}, + {0x18002000, 0x000010ec}, + {0xfafafafa, 0x00000000}, +}; + +static const struct reg_sequence rt5514_patch[] = { + {RT5514_DIG_IO_CTRL, 0x00000040}, + {RT5514_CLK_CTRL1, 0x38020041}, + {RT5514_SRC_CTRL, 0x44000eee}, + {RT5514_ANA_CTRL_LDO10, 0x00028604}, + {RT5514_ANA_CTRL_ADCFED, 0x00000800}, +}; + +static const struct reg_default rt5514_reg[] = { + {RT5514_RESET, 0x00000000}, + {RT5514_PWR_ANA1, 0x00808880}, + {RT5514_PWR_ANA2, 0x00220000}, + {RT5514_I2S_CTRL1, 0x00000330}, + {RT5514_I2S_CTRL2, 0x20000000}, + {RT5514_VAD_CTRL6, 0xc00007d2}, + {RT5514_EXT_VAD_CTRL, 0x80000080}, + {RT5514_DIG_IO_CTRL, 0x00000040}, + {RT5514_PAD_CTRL1, 0x00804000}, + {RT5514_DMIC_DATA_CTRL, 0x00000005}, + {RT5514_DIG_SOURCE_CTRL, 0x00000002}, + {RT5514_SRC_CTRL, 0x44000eee}, + {RT5514_DOWNFILTER2_CTRL1, 0x0000882f}, + {RT5514_PLL_SOURCE_CTRL, 0x00000004}, + {RT5514_CLK_CTRL1, 0x38020041}, + {RT5514_CLK_CTRL2, 0x00000000}, + {RT5514_PLL3_CALIB_CTRL1, 0x00400200}, + {RT5514_PLL3_CALIB_CTRL5, 0x40220012}, + {RT5514_DELAY_BUF_CTRL1, 0x7fff006a}, + {RT5514_DELAY_BUF_CTRL3, 0x00000000}, + {RT5514_DOWNFILTER0_CTRL1, 0x00020c2f}, + {RT5514_DOWNFILTER0_CTRL2, 0x00020c2f}, + {RT5514_DOWNFILTER0_CTRL3, 0x00000362}, + {RT5514_DOWNFILTER1_CTRL1, 0x00020c2f}, + {RT5514_DOWNFILTER1_CTRL2, 0x00020c2f}, + {RT5514_DOWNFILTER1_CTRL3, 0x00000362}, + {RT5514_ANA_CTRL_LDO10, 0x00028604}, + {RT5514_ANA_CTRL_LDO18_16, 0x02000345}, + {RT5514_ANA_CTRL_ADC12, 0x0000a2a8}, + {RT5514_ANA_CTRL_ADC21, 0x00001180}, + {RT5514_ANA_CTRL_ADC22, 0x0000aaa8}, + {RT5514_ANA_CTRL_ADC23, 0x00151427}, + {RT5514_ANA_CTRL_MICBST, 0x00002000}, + {RT5514_ANA_CTRL_ADCFED, 0x00000800}, + {RT5514_ANA_CTRL_INBUF, 0x00000143}, + {RT5514_ANA_CTRL_VREF, 0x00008d50}, + {RT5514_ANA_CTRL_PLL3, 0x0000000e}, + {RT5514_ANA_CTRL_PLL1_1, 0x00000000}, + {RT5514_ANA_CTRL_PLL1_2, 0x00030220}, + {RT5514_DMIC_LP_CTRL, 0x00000000}, + {RT5514_MISC_CTRL_DSP, 0x00000000}, + {RT5514_DSP_CTRL1, 0x00055149}, + {RT5514_DSP_CTRL3, 0x00000006}, + {RT5514_DSP_CTRL4, 0x00000001}, + {RT5514_VENDOR_ID1, 0x00000001}, + {RT5514_VENDOR_ID2, 0x10ec5514}, +}; + +static bool rt5514_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5514_VENDOR_ID1: + case RT5514_VENDOR_ID2: + return true; + + default: + return false; + } +} + +static bool rt5514_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT5514_RESET: + case RT5514_PWR_ANA1: + case RT5514_PWR_ANA2: + case RT5514_I2S_CTRL1: + case RT5514_I2S_CTRL2: + case RT5514_VAD_CTRL6: + case RT5514_EXT_VAD_CTRL: + case RT5514_DIG_IO_CTRL: + case RT5514_PAD_CTRL1: + case RT5514_DMIC_DATA_CTRL: + case RT5514_DIG_SOURCE_CTRL: + case RT5514_SRC_CTRL: + case RT5514_DOWNFILTER2_CTRL1: + case RT5514_PLL_SOURCE_CTRL: + case RT5514_CLK_CTRL1: + case RT5514_CLK_CTRL2: + case RT5514_PLL3_CALIB_CTRL1: + case RT5514_PLL3_CALIB_CTRL5: + case RT5514_DELAY_BUF_CTRL1: + case RT5514_DELAY_BUF_CTRL3: + case RT5514_DOWNFILTER0_CTRL1: + case RT5514_DOWNFILTER0_CTRL2: + case RT5514_DOWNFILTER0_CTRL3: + case RT5514_DOWNFILTER1_CTRL1: + case RT5514_DOWNFILTER1_CTRL2: + case RT5514_DOWNFILTER1_CTRL3: + case RT5514_ANA_CTRL_LDO10: + case RT5514_ANA_CTRL_LDO18_16: + case RT5514_ANA_CTRL_ADC12: + case RT5514_ANA_CTRL_ADC21: + case RT5514_ANA_CTRL_ADC22: + case RT5514_ANA_CTRL_ADC23: + case RT5514_ANA_CTRL_MICBST: + case RT5514_ANA_CTRL_ADCFED: + case RT5514_ANA_CTRL_INBUF: + case RT5514_ANA_CTRL_VREF: + case RT5514_ANA_CTRL_PLL3: + case RT5514_ANA_CTRL_PLL1_1: + case RT5514_ANA_CTRL_PLL1_2: + case RT5514_DMIC_LP_CTRL: + case RT5514_MISC_CTRL_DSP: + case RT5514_DSP_CTRL1: + case RT5514_DSP_CTRL3: + case RT5514_DSP_CTRL4: + case RT5514_VENDOR_ID1: + case RT5514_VENDOR_ID2: + return true; + + default: + return false; + } +} + +static bool rt5514_i2c_readable_register(struct device *dev, + unsigned int reg) +{ + switch (reg) { + case RT5514_DSP_MAPPING | RT5514_RESET: + case RT5514_DSP_MAPPING | RT5514_PWR_ANA1: + case RT5514_DSP_MAPPING | RT5514_PWR_ANA2: + case RT5514_DSP_MAPPING | RT5514_I2S_CTRL1: + case RT5514_DSP_MAPPING | RT5514_I2S_CTRL2: + case RT5514_DSP_MAPPING | RT5514_VAD_CTRL6: + case RT5514_DSP_MAPPING | RT5514_EXT_VAD_CTRL: + case RT5514_DSP_MAPPING | RT5514_DIG_IO_CTRL: + case RT5514_DSP_MAPPING | RT5514_PAD_CTRL1: + case RT5514_DSP_MAPPING | RT5514_DMIC_DATA_CTRL: + case RT5514_DSP_MAPPING | RT5514_DIG_SOURCE_CTRL: + case RT5514_DSP_MAPPING | RT5514_SRC_CTRL: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER2_CTRL1: + case RT5514_DSP_MAPPING | RT5514_PLL_SOURCE_CTRL: + case RT5514_DSP_MAPPING | RT5514_CLK_CTRL1: + case RT5514_DSP_MAPPING | RT5514_CLK_CTRL2: + case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL1: + case RT5514_DSP_MAPPING | RT5514_PLL3_CALIB_CTRL5: + case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL1: + case RT5514_DSP_MAPPING | RT5514_DELAY_BUF_CTRL3: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL1: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL2: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER0_CTRL3: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL1: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL2: + case RT5514_DSP_MAPPING | RT5514_DOWNFILTER1_CTRL3: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO10: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_LDO18_16: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC12: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC21: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC22: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADC23: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_MICBST: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_ADCFED: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_INBUF: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_VREF: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL3: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_1: + case RT5514_DSP_MAPPING | RT5514_ANA_CTRL_PLL1_2: + case RT5514_DSP_MAPPING | RT5514_DMIC_LP_CTRL: + case RT5514_DSP_MAPPING | RT5514_MISC_CTRL_DSP: + case RT5514_DSP_MAPPING | RT5514_DSP_CTRL1: + case RT5514_DSP_MAPPING | RT5514_DSP_CTRL3: + case RT5514_DSP_MAPPING | RT5514_DSP_CTRL4: + case RT5514_DSP_MAPPING | RT5514_VENDOR_ID1: + case RT5514_DSP_MAPPING | RT5514_VENDOR_ID2: + return true; + + default: + return false; + } +} + +/* {-3, 0, +3, +4.5, +7.5, +9.5, +12, +14, +17} dB */ +static const DECLARE_TLV_DB_RANGE(bst_tlv, + 0, 2, TLV_DB_SCALE_ITEM(-300, 300, 0), + 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), + 4, 4, TLV_DB_SCALE_ITEM(750, 0, 0), + 5, 5, TLV_DB_SCALE_ITEM(950, 0, 0), + 6, 6, TLV_DB_SCALE_ITEM(1200, 0, 0), + 7, 7, TLV_DB_SCALE_ITEM(1400, 0, 0), + 8, 8, TLV_DB_SCALE_ITEM(1700, 0, 0) +); + +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); + +static const struct snd_kcontrol_new rt5514_snd_controls[] = { + SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST, + RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv), + SOC_DOUBLE_R_TLV("ADC1 Capture Volume", RT5514_DOWNFILTER0_CTRL1, + RT5514_DOWNFILTER0_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, + adc_vol_tlv), + SOC_DOUBLE_R_TLV("ADC2 Capture Volume", RT5514_DOWNFILTER1_CTRL1, + RT5514_DOWNFILTER1_CTRL2, RT5514_AD_GAIN_SFT, 127, 0, + adc_vol_tlv), +}; + +/* ADC Mixer*/ +static const struct snd_kcontrol_new rt5514_sto1_adc_l_mix[] = { + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL1, + RT5514_AD_DMIC_MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL1, + RT5514_AD_AD_MIX_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5514_sto1_adc_r_mix[] = { + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER0_CTRL2, + RT5514_AD_DMIC_MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER0_CTRL2, + RT5514_AD_AD_MIX_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5514_sto2_adc_l_mix[] = { + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL1, + RT5514_AD_DMIC_MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL1, + RT5514_AD_AD_MIX_BIT, 1, 1), +}; + +static const struct snd_kcontrol_new rt5514_sto2_adc_r_mix[] = { + SOC_DAPM_SINGLE("DMIC Switch", RT5514_DOWNFILTER1_CTRL2, + RT5514_AD_DMIC_MIX_BIT, 1, 1), + SOC_DAPM_SINGLE("ADC Switch", RT5514_DOWNFILTER1_CTRL2, + RT5514_AD_AD_MIX_BIT, 1, 1), +}; + +/* DMIC Source */ +static const char * const rt5514_dmic_src[] = { + "DMIC1", "DMIC2" +}; + +static const SOC_ENUM_SINGLE_DECL( + rt5514_stereo1_dmic_enum, RT5514_DIG_SOURCE_CTRL, + RT5514_AD0_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); + +static const struct snd_kcontrol_new rt5514_sto1_dmic_mux = + SOC_DAPM_ENUM("Stereo1 DMIC Source", rt5514_stereo1_dmic_enum); + +static const SOC_ENUM_SINGLE_DECL( + rt5514_stereo2_dmic_enum, RT5514_DIG_SOURCE_CTRL, + RT5514_AD1_DMIC_INPUT_SEL_SFT, rt5514_dmic_src); + +static const struct snd_kcontrol_new rt5514_sto2_dmic_mux = + SOC_DAPM_ENUM("Stereo2 DMIC Source", rt5514_stereo2_dmic_enum); + +/** + * rt5514_calc_dmic_clk - Calculate the frequency divider parameter of dmic. + * + * @rate: base clock rate. + * + * Choose divider parameter that gives the highest possible DMIC frequency in + * 1MHz - 3MHz range. + */ +static int rt5514_calc_dmic_clk(struct snd_soc_codec *codec, int rate) +{ + int div[] = {2, 3, 4, 8, 12, 16, 24, 32}; + int i; + + if (rate < 1000000 * div[0]) { + pr_warn("Base clock rate %d is too low\n", rate); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(div); i++) { + /* find divider that gives DMIC frequency below 3.072MHz */ + if (3072000 * div[i] >= rate) + return i; + } + + dev_warn(codec->dev, "Base clock rate %d is too high\n", rate); + return -EINVAL; +} + +static int rt5514_set_dmic_clk(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 rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + int idx; + + idx = rt5514_calc_dmic_clk(codec, rt5514->sysclk); + if (idx < 0) + dev_err(codec->dev, "Failed to set DMIC clock\n"); + else + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL1, + RT5514_CLK_DMIC_OUT_SEL_MASK, + idx << RT5514_CLK_DMIC_OUT_SEL_SFT); + + return idx; +} + +static int rt5514_is_sys_clk_from_pll(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + + if (rt5514->sysclk_src == RT5514_SCLK_S_PLL1) + return 1; + else + return 0; +} + +static const struct snd_soc_dapm_widget rt5514_dapm_widgets[] = { + /* Input Lines */ + SND_SOC_DAPM_INPUT("DMIC1L"), + SND_SOC_DAPM_INPUT("DMIC1R"), + SND_SOC_DAPM_INPUT("DMIC2L"), + SND_SOC_DAPM_INPUT("DMIC2R"), + + SND_SOC_DAPM_INPUT("AMICL"), + SND_SOC_DAPM_INPUT("AMICR"), + + SND_SOC_DAPM_PGA("DMIC1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("DMIC2", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DMIC CLK", SND_SOC_NOPM, 0, 0, + rt5514_set_dmic_clk, SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY("ADC CLK", RT5514_CLK_CTRL1, + RT5514_CLK_AD_ANA1_EN_BIT, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("LDO18 IN", RT5514_PWR_ANA1, + RT5514_POW_LDO18_IN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("LDO18 ADC", RT5514_PWR_ANA1, + RT5514_POW_LDO18_ADC_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("LDO21", RT5514_PWR_ANA1, RT5514_POW_LDO21_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("BG LDO18 IN", RT5514_PWR_ANA1, + RT5514_POW_BG_LDO18_IN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BG LDO21", RT5514_PWR_ANA1, + RT5514_POW_BG_LDO21_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("BG MBIAS", RT5514_PWR_ANA2, + RT5514_POW_BG_MBIAS_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MBIAS", RT5514_PWR_ANA2, RT5514_POW_MBIAS_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("VREF2", RT5514_PWR_ANA2, RT5514_POW_VREF2_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("VREF1", RT5514_PWR_ANA2, RT5514_POW_VREF1_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC Power", SND_SOC_NOPM, 0, 0, NULL, 0), + + + SND_SOC_DAPM_SUPPLY("LDO16L", RT5514_PWR_ANA2, RT5514_POWL_LDO16_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC1L", RT5514_PWR_ANA2, RT5514_POW_ADC1_L_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("BSTL2", RT5514_PWR_ANA2, RT5514_POW2_BSTL_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("BSTL", RT5514_PWR_ANA2, RT5514_POW_BSTL_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("ADCFEDL", RT5514_PWR_ANA2, RT5514_POW_ADCFEDL_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADCL Power", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("LDO16R", RT5514_PWR_ANA2, RT5514_POWR_LDO16_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC1R", RT5514_PWR_ANA2, RT5514_POW_ADC1_R_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("BSTR2", RT5514_PWR_ANA2, RT5514_POW2_BSTR_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("BSTR", RT5514_PWR_ANA2, RT5514_POW_BSTR_BIT, 0, + NULL, 0), + SND_SOC_DAPM_SUPPLY("ADCFEDR", RT5514_PWR_ANA2, RT5514_POW_ADCFEDR_BIT, + 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADCR Power", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("PLL1 LDO ENABLE", RT5514_ANA_CTRL_PLL1_2, + RT5514_EN_LDO_PLL1_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL1 LDO", RT5514_PWR_ANA2, + RT5514_POW_PLL1_LDO_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("PLL1", RT5514_PWR_ANA2, RT5514_POW_PLL1_BIT, 0, + NULL, 0), + + /* ADC Mux */ + SND_SOC_DAPM_MUX("Stereo1 DMIC Mux", SND_SOC_NOPM, 0, 0, + &rt5514_sto1_dmic_mux), + SND_SOC_DAPM_MUX("Stereo2 DMIC Mux", SND_SOC_NOPM, 0, 0, + &rt5514_sto2_dmic_mux), + + /* ADC Mixer */ + SND_SOC_DAPM_SUPPLY("adc stereo1 filter", RT5514_CLK_CTRL1, + RT5514_CLK_AD0_EN_BIT, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("adc stereo2 filter", RT5514_CLK_CTRL1, + RT5514_CLK_AD1_EN_BIT, 0, NULL, 0), + + SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, + rt5514_sto1_adc_l_mix, ARRAY_SIZE(rt5514_sto1_adc_l_mix)), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5514_sto1_adc_r_mix, ARRAY_SIZE(rt5514_sto1_adc_r_mix)), + SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, + rt5514_sto2_adc_l_mix, ARRAY_SIZE(rt5514_sto2_adc_l_mix)), + SND_SOC_DAPM_MIXER("Sto2 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5514_sto2_adc_r_mix, ARRAY_SIZE(rt5514_sto2_adc_r_mix)), + + SND_SOC_DAPM_ADC("Stereo1 ADC MIXL", NULL, RT5514_DOWNFILTER0_CTRL1, + RT5514_AD_AD_MUTE_BIT, 1), + SND_SOC_DAPM_ADC("Stereo1 ADC MIXR", NULL, RT5514_DOWNFILTER0_CTRL2, + RT5514_AD_AD_MUTE_BIT, 1), + SND_SOC_DAPM_ADC("Stereo2 ADC MIXL", NULL, RT5514_DOWNFILTER1_CTRL1, + RT5514_AD_AD_MUTE_BIT, 1), + SND_SOC_DAPM_ADC("Stereo2 ADC MIXR", NULL, RT5514_DOWNFILTER1_CTRL2, + RT5514_AD_AD_MUTE_BIT, 1), + + /* ADC PGA */ + SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("Stereo2 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* Audio Interface */ + SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route rt5514_dapm_routes[] = { + { "DMIC1", NULL, "DMIC1L" }, + { "DMIC1", NULL, "DMIC1R" }, + { "DMIC2", NULL, "DMIC2L" }, + { "DMIC2", NULL, "DMIC2R" }, + + { "DMIC1L", NULL, "DMIC CLK" }, + { "DMIC1R", NULL, "DMIC CLK" }, + { "DMIC2L", NULL, "DMIC CLK" }, + { "DMIC2R", NULL, "DMIC CLK" }, + + { "Stereo1 DMIC Mux", "DMIC1", "DMIC1" }, + { "Stereo1 DMIC Mux", "DMIC2", "DMIC2" }, + + { "Sto1 ADC MIXL", "DMIC Switch", "Stereo1 DMIC Mux" }, + { "Sto1 ADC MIXL", "ADC Switch", "AMICL" }, + { "Sto1 ADC MIXR", "DMIC Switch", "Stereo1 DMIC Mux" }, + { "Sto1 ADC MIXR", "ADC Switch", "AMICR" }, + + { "ADC Power", NULL, "LDO18 IN" }, + { "ADC Power", NULL, "LDO18 ADC" }, + { "ADC Power", NULL, "LDO21" }, + { "ADC Power", NULL, "BG LDO18 IN" }, + { "ADC Power", NULL, "BG LDO21" }, + { "ADC Power", NULL, "BG MBIAS" }, + { "ADC Power", NULL, "MBIAS" }, + { "ADC Power", NULL, "VREF2" }, + { "ADC Power", NULL, "VREF1" }, + + { "ADCL Power", NULL, "LDO16L" }, + { "ADCL Power", NULL, "ADC1L" }, + { "ADCL Power", NULL, "BSTL2" }, + { "ADCL Power", NULL, "BSTL" }, + { "ADCL Power", NULL, "ADCFEDL" }, + + { "ADCR Power", NULL, "LDO16R" }, + { "ADCR Power", NULL, "ADC1R" }, + { "ADCR Power", NULL, "BSTR2" }, + { "ADCR Power", NULL, "BSTR" }, + { "ADCR Power", NULL, "ADCFEDR" }, + + { "AMICL", NULL, "ADC CLK" }, + { "AMICL", NULL, "ADC Power" }, + { "AMICL", NULL, "ADCL Power" }, + { "AMICR", NULL, "ADC CLK" }, + { "AMICR", NULL, "ADC Power" }, + { "AMICR", NULL, "ADCR Power" }, + + { "PLL1 LDO", NULL, "PLL1 LDO ENABLE" }, + { "PLL1", NULL, "PLL1 LDO" }, + + { "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" }, + { "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" }, + + { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXL" }, + { "Stereo1 ADC MIX", NULL, "Stereo1 ADC MIXR" }, + { "Stereo1 ADC MIX", NULL, "adc stereo1 filter" }, + { "adc stereo1 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, + + { "Stereo2 DMIC Mux", "DMIC1", "DMIC1" }, + { "Stereo2 DMIC Mux", "DMIC2", "DMIC2" }, + + { "Sto2 ADC MIXL", "DMIC Switch", "Stereo2 DMIC Mux" }, + { "Sto2 ADC MIXL", "ADC Switch", "AMICL" }, + { "Sto2 ADC MIXR", "DMIC Switch", "Stereo2 DMIC Mux" }, + { "Sto2 ADC MIXR", "ADC Switch", "AMICR" }, + + { "Stereo2 ADC MIXL", NULL, "Sto2 ADC MIXL" }, + { "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" }, + + { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXL" }, + { "Stereo2 ADC MIX", NULL, "Stereo2 ADC MIXR" }, + { "Stereo2 ADC MIX", NULL, "adc stereo2 filter" }, + { "adc stereo2 filter", NULL, "PLL1", rt5514_is_sys_clk_from_pll }, + + { "AIF1TX", NULL, "Stereo1 ADC MIX"}, + { "AIF1TX", NULL, "Stereo2 ADC MIX"}, +}; + +static int rt5514_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; + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + int pre_div, bclk_ms, frame_size; + unsigned int val_len = 0; + + rt5514->lrck = params_rate(params); + pre_div = rl6231_get_clk_info(rt5514->sysclk, rt5514->lrck); + if (pre_div < 0) { + dev_err(codec->dev, "Unsupported clock setting\n"); + return -EINVAL; + } + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(codec->dev, "Unsupported frame size: %d\n", frame_size); + return -EINVAL; + } + + bclk_ms = frame_size > 32; + rt5514->bclk = rt5514->lrck * (32 << bclk_ms); + + dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", + rt5514->bclk, rt5514->lrck); + dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", + bclk_ms, pre_div, dai->id); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + break; + case SNDRV_PCM_FORMAT_S20_3LE: + val_len = RT5514_I2S_DL_20; + break; + case SNDRV_PCM_FORMAT_S24_LE: + val_len = RT5514_I2S_DL_24; + break; + case SNDRV_PCM_FORMAT_S8: + val_len = RT5514_I2S_DL_8; + break; + default: + return -EINVAL; + } + + regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_I2S_DL_MASK, + val_len); + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, + RT5514_CLK_SYS_DIV_OUT_MASK | RT5514_SEL_ADC_OSR_MASK, + pre_div << RT5514_CLK_SYS_DIV_OUT_SFT | + pre_div << RT5514_SEL_ADC_OSR_SFT); + + return 0; +} + +static int rt5514_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + + case SND_SOC_DAIFMT_NB_IF: + reg_val |= RT5514_I2S_LR_INV; + break; + + case SND_SOC_DAIFMT_IB_NF: + reg_val |= RT5514_I2S_BP_INV; + break; + + case SND_SOC_DAIFMT_IB_IF: + reg_val |= RT5514_I2S_BP_INV | RT5514_I2S_LR_INV; + break; + + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT5514_I2S_DF_LEFT; + break; + + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT5514_I2S_DF_PCM_A; + break; + + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT5514_I2S_DF_PCM_B; + break; + + default: + return -EINVAL; + } + + regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, + RT5514_I2S_DF_MASK | RT5514_I2S_BP_MASK | RT5514_I2S_LR_MASK, + reg_val); + + return 0; +} + +static int rt5514_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + unsigned int reg_val = 0; + + if (freq == rt5514->sysclk && clk_id == rt5514->sysclk_src) + return 0; + + switch (clk_id) { + case RT5514_SCLK_S_MCLK: + reg_val |= RT5514_CLK_SYS_PRE_SEL_MCLK; + break; + + case RT5514_SCLK_S_PLL1: + reg_val |= RT5514_CLK_SYS_PRE_SEL_PLL; + break; + + default: + dev_err(codec->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, + RT5514_CLK_SYS_PRE_SEL_MASK, reg_val); + + rt5514->sysclk = freq; + rt5514->sysclk_src = clk_id; + + dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); + + return 0; +} + +static int rt5514_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, + unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_codec *codec = dai->codec; + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + struct rl6231_pll_code pll_code; + int ret; + + if (!freq_in || !freq_out) { + dev_dbg(codec->dev, "PLL disabled\n"); + + rt5514->pll_in = 0; + rt5514->pll_out = 0; + regmap_update_bits(rt5514->regmap, RT5514_CLK_CTRL2, + RT5514_CLK_SYS_PRE_SEL_MASK, + RT5514_CLK_SYS_PRE_SEL_MCLK); + + return 0; + } + + if (source == rt5514->pll_src && freq_in == rt5514->pll_in && + freq_out == rt5514->pll_out) + return 0; + + switch (source) { + case RT5514_PLL1_S_MCLK: + regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, + RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_MCLK); + break; + + case RT5514_PLL1_S_BCLK: + regmap_update_bits(rt5514->regmap, RT5514_PLL_SOURCE_CTRL, + RT5514_PLL_1_SEL_MASK, RT5514_PLL_1_SEL_SCLK); + break; + + default: + dev_err(codec->dev, "Unknown PLL source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + regmap_write(rt5514->regmap, RT5514_ANA_CTRL_PLL1_1, + pll_code.k_code << RT5514_PLL_K_SFT | + pll_code.n_code << RT5514_PLL_N_SFT | + (pll_code.m_bp ? 0 : pll_code.m_code) << RT5514_PLL_M_SFT); + regmap_update_bits(rt5514->regmap, RT5514_ANA_CTRL_PLL1_2, + RT5514_PLL_M_BP, pll_code.m_bp << RT5514_PLL_M_BP_SFT); + + rt5514->pll_in = freq_in; + rt5514->pll_out = freq_out; + rt5514->pll_src = source; + + return 0; +} + +static int rt5514_set_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; + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + unsigned int val = 0; + + if (rx_mask || tx_mask) + val |= RT5514_TDM_MODE; + + if (slots == 4) + val |= RT5514_TDMSLOT_SEL_RX_4CH | RT5514_TDMSLOT_SEL_TX_4CH; + + + switch (slot_width) { + case 20: + val |= RT5514_CH_LEN_RX_20 | RT5514_CH_LEN_TX_20; + break; + + case 24: + val |= RT5514_CH_LEN_RX_24 | RT5514_CH_LEN_TX_24; + break; + + case 32: + val |= RT5514_CH_LEN_RX_32 | RT5514_CH_LEN_TX_32; + break; + + case 16: + default: + break; + } + + regmap_update_bits(rt5514->regmap, RT5514_I2S_CTRL1, RT5514_TDM_MODE | + RT5514_TDMSLOT_SEL_RX_MASK | RT5514_TDMSLOT_SEL_TX_MASK | + RT5514_CH_LEN_RX_MASK | RT5514_CH_LEN_TX_MASK, val); + + return 0; +} + +static int rt5514_probe(struct snd_soc_codec *codec) +{ + struct rt5514_priv *rt5514 = snd_soc_codec_get_drvdata(codec); + + rt5514->codec = codec; + + return 0; +} + +static int rt5514_i2c_read(void *context, unsigned int reg, unsigned int *val) +{ + struct i2c_client *client = context; + struct rt5514_priv *rt5514 = i2c_get_clientdata(client); + + regmap_read(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); + + return 0; +} + +static int rt5514_i2c_write(void *context, unsigned int reg, unsigned int val) +{ + struct i2c_client *client = context; + struct rt5514_priv *rt5514 = i2c_get_clientdata(client); + + regmap_write(rt5514->i2c_regmap, reg | RT5514_DSP_MAPPING, val); + + return 0; +} + +#define RT5514_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT5514_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +struct snd_soc_dai_ops rt5514_aif_dai_ops = { + .hw_params = rt5514_hw_params, + .set_fmt = rt5514_set_dai_fmt, + .set_sysclk = rt5514_set_dai_sysclk, + .set_pll = rt5514_set_dai_pll, + .set_tdm_slot = rt5514_set_tdm_slot, +}; + +struct snd_soc_dai_driver rt5514_dai[] = { + { + .name = "rt5514-aif1", + .id = 0, + .capture = { + .stream_name = "AIF1 Capture", + .channels_min = 1, + .channels_max = 4, + .rates = RT5514_STEREO_RATES, + .formats = RT5514_FORMATS, + }, + .ops = &rt5514_aif_dai_ops, + } +}; + +static struct snd_soc_codec_driver soc_codec_dev_rt5514 = { + .probe = rt5514_probe, + .idle_bias_off = true, + .controls = rt5514_snd_controls, + .num_controls = ARRAY_SIZE(rt5514_snd_controls), + .dapm_widgets = rt5514_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt5514_dapm_widgets), + .dapm_routes = rt5514_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt5514_dapm_routes), +}; + +static const struct regmap_config rt5514_i2c_regmap = { + .name = "i2c", + .reg_bits = 32, + .val_bits = 32, + + .max_register = RT5514_DSP_MAPPING | RT5514_VENDOR_ID2, + .readable_reg = rt5514_i2c_readable_register, + + .cache_type = REGCACHE_NONE, +}; + +static const struct regmap_config rt5514_regmap = { + .reg_bits = 16, + .val_bits = 32, + + .max_register = RT5514_VENDOR_ID2, + .volatile_reg = rt5514_volatile_register, + .readable_reg = rt5514_readable_register, + .reg_read = rt5514_i2c_read, + .reg_write = rt5514_i2c_write, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt5514_reg, + .num_reg_defaults = ARRAY_SIZE(rt5514_reg), + .use_single_rw = true, +}; + +static const struct i2c_device_id rt5514_i2c_id[] = { + { "rt5514", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); + +#if defined(CONFIG_OF) +static const struct of_device_id rt5514_of_match[] = { + { .compatible = "realtek,rt5514", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt5514_of_match); +#endif + +static int rt5514_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt5514_priv *rt5514; + int ret; + unsigned int val; + + rt5514 = devm_kzalloc(&i2c->dev, sizeof(struct rt5514_priv), + GFP_KERNEL); + if (rt5514 == NULL) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt5514); + + rt5514->i2c_regmap = devm_regmap_init_i2c(i2c, &rt5514_i2c_regmap); + if (IS_ERR(rt5514->i2c_regmap)) { + ret = PTR_ERR(rt5514->i2c_regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + rt5514->regmap = devm_regmap_init(&i2c->dev, NULL, i2c, &rt5514_regmap); + if (IS_ERR(rt5514->regmap)) { + ret = PTR_ERR(rt5514->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt5514->regmap, RT5514_VENDOR_ID2, &val); + if (val != RT5514_DEVICE_ID) { + dev_err(&i2c->dev, + "Device with ID register %x is not rt5514\n", val); + return -ENODEV; + } + + ret = regmap_register_patch(rt5514->i2c_regmap, rt5514_i2c_patch, + ARRAY_SIZE(rt5514_i2c_patch)); + if (ret != 0) + dev_warn(&i2c->dev, "Failed to apply i2c_regmap patch: %d\n", + ret); + + ret = regmap_register_patch(rt5514->regmap, rt5514_patch, + ARRAY_SIZE(rt5514_patch)); + if (ret != 0) + dev_warn(&i2c->dev, "Failed to apply regmap patch: %d\n", ret); + + return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5514, + rt5514_dai, ARRAY_SIZE(rt5514_dai)); +} + +static int rt5514_i2c_remove(struct i2c_client *i2c) +{ + snd_soc_unregister_codec(&i2c->dev); + + return 0; +} + +struct i2c_driver rt5514_i2c_driver = { + .driver = { + .name = "rt5514", + .of_match_table = of_match_ptr(rt5514_of_match), + }, + .probe = rt5514_i2c_probe, + .remove = rt5514_i2c_remove, + .id_table = rt5514_i2c_id, +}; +module_i2c_driver(rt5514_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT5514 driver"); +MODULE_AUTHOR("Oder Chiou "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt5514.h b/sound/soc/codecs/rt5514.h new file mode 100644 index 000000000000..6ad8a612f659 --- /dev/null +++ b/sound/soc/codecs/rt5514.h @@ -0,0 +1,252 @@ +/* + * rt5514.h -- RT5514 ALSA SoC audio driver + * + * Copyright 2015 Realtek Microelectronics + * Author: Oder Chiou + * + * 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 __RT5514_H__ +#define __RT5514_H__ + +#define RT5514_DEVICE_ID 0x10ec5514 + +#define RT5514_RESET 0x2000 +#define RT5514_PWR_ANA1 0x2004 +#define RT5514_PWR_ANA2 0x2008 +#define RT5514_I2S_CTRL1 0x2010 +#define RT5514_I2S_CTRL2 0x2014 +#define RT5514_VAD_CTRL6 0x2030 +#define RT5514_EXT_VAD_CTRL 0x206c +#define RT5514_DIG_IO_CTRL 0x2070 +#define RT5514_PAD_CTRL1 0x2080 +#define RT5514_DMIC_DATA_CTRL 0x20a0 +#define RT5514_DIG_SOURCE_CTRL 0x20a4 +#define RT5514_SRC_CTRL 0x20ac +#define RT5514_DOWNFILTER2_CTRL1 0x20d0 +#define RT5514_PLL_SOURCE_CTRL 0x2100 +#define RT5514_CLK_CTRL1 0x2104 +#define RT5514_CLK_CTRL2 0x2108 +#define RT5514_PLL3_CALIB_CTRL1 0x2110 +#define RT5514_PLL3_CALIB_CTRL5 0x2124 +#define RT5514_DELAY_BUF_CTRL1 0x2140 +#define RT5514_DELAY_BUF_CTRL3 0x2148 +#define RT5514_DOWNFILTER0_CTRL1 0x2190 +#define RT5514_DOWNFILTER0_CTRL2 0x2194 +#define RT5514_DOWNFILTER0_CTRL3 0x2198 +#define RT5514_DOWNFILTER1_CTRL1 0x21a0 +#define RT5514_DOWNFILTER1_CTRL2 0x21a4 +#define RT5514_DOWNFILTER1_CTRL3 0x21a8 +#define RT5514_ANA_CTRL_LDO10 0x2200 +#define RT5514_ANA_CTRL_LDO18_16 0x2204 +#define RT5514_ANA_CTRL_ADC12 0x2210 +#define RT5514_ANA_CTRL_ADC21 0x2214 +#define RT5514_ANA_CTRL_ADC22 0x2218 +#define RT5514_ANA_CTRL_ADC23 0x221c +#define RT5514_ANA_CTRL_MICBST 0x2220 +#define RT5514_ANA_CTRL_ADCFED 0x2224 +#define RT5514_ANA_CTRL_INBUF 0x2228 +#define RT5514_ANA_CTRL_VREF 0x222c +#define RT5514_ANA_CTRL_PLL3 0x2240 +#define RT5514_ANA_CTRL_PLL1_1 0x2260 +#define RT5514_ANA_CTRL_PLL1_2 0x2264 +#define RT5514_DMIC_LP_CTRL 0x2e00 +#define RT5514_MISC_CTRL_DSP 0x2e04 +#define RT5514_DSP_CTRL1 0x2f00 +#define RT5514_DSP_CTRL3 0x2f08 +#define RT5514_DSP_CTRL4 0x2f10 +#define RT5514_VENDOR_ID1 0x2ff0 +#define RT5514_VENDOR_ID2 0x2ff4 + +#define RT5514_DSP_MAPPING 0x18000000 + +/* RT5514_PWR_ANA1 (0x2004) */ +#define RT5514_POW_LDO18_IN (0x1 << 5) +#define RT5514_POW_LDO18_IN_BIT 5 +#define RT5514_POW_LDO18_ADC (0x1 << 4) +#define RT5514_POW_LDO18_ADC_BIT 4 +#define RT5514_POW_LDO21 (0x1 << 3) +#define RT5514_POW_LDO21_BIT 3 +#define RT5514_POW_BG_LDO18_IN (0x1 << 2) +#define RT5514_POW_BG_LDO18_IN_BIT 2 +#define RT5514_POW_BG_LDO21 (0x1 << 1) +#define RT5514_POW_BG_LDO21_BIT 1 + +/* RT5514_PWR_ANA2 (0x2008) */ +#define RT5514_POW_PLL1 (0x1 << 18) +#define RT5514_POW_PLL1_BIT 18 +#define RT5514_POW_PLL1_LDO (0x1 << 16) +#define RT5514_POW_PLL1_LDO_BIT 16 +#define RT5514_POW_BG_MBIAS (0x1 << 15) +#define RT5514_POW_BG_MBIAS_BIT 15 +#define RT5514_POW_MBIAS (0x1 << 14) +#define RT5514_POW_MBIAS_BIT 14 +#define RT5514_POW_VREF2 (0x1 << 13) +#define RT5514_POW_VREF2_BIT 13 +#define RT5514_POW_VREF1 (0x1 << 12) +#define RT5514_POW_VREF1_BIT 12 +#define RT5514_POWR_LDO16 (0x1 << 11) +#define RT5514_POWR_LDO16_BIT 11 +#define RT5514_POWL_LDO16 (0x1 << 10) +#define RT5514_POWL_LDO16_BIT 10 +#define RT5514_POW_ADC2 (0x1 << 9) +#define RT5514_POW_ADC2_BIT 9 +#define RT5514_POW_INPUT_BUF (0x1 << 8) +#define RT5514_POW_INPUT_BUF_BIT 8 +#define RT5514_POW_ADC1_R (0x1 << 7) +#define RT5514_POW_ADC1_R_BIT 7 +#define RT5514_POW_ADC1_L (0x1 << 6) +#define RT5514_POW_ADC1_L_BIT 6 +#define RT5514_POW2_BSTR (0x1 << 5) +#define RT5514_POW2_BSTR_BIT 5 +#define RT5514_POW2_BSTL (0x1 << 4) +#define RT5514_POW2_BSTL_BIT 4 +#define RT5514_POW_BSTR (0x1 << 3) +#define RT5514_POW_BSTR_BIT 3 +#define RT5514_POW_BSTL (0x1 << 2) +#define RT5514_POW_BSTL_BIT 2 +#define RT5514_POW_ADCFEDR (0x1 << 1) +#define RT5514_POW_ADCFEDR_BIT 1 +#define RT5514_POW_ADCFEDL (0x1 << 0) +#define RT5514_POW_ADCFEDL_BIT 0 + +/* RT5514_I2S_CTRL1 (0x2010) */ +#define RT5514_TDM_MODE (0x1 << 28) +#define RT5514_TDM_MODE_SFT 28 +#define RT5514_I2S_LR_MASK (0x1 << 26) +#define RT5514_I2S_LR_SFT 26 +#define RT5514_I2S_LR_NOR (0x0 << 26) +#define RT5514_I2S_LR_INV (0x1 << 26) +#define RT5514_I2S_BP_MASK (0x1 << 25) +#define RT5514_I2S_BP_SFT 25 +#define RT5514_I2S_BP_NOR (0x0 << 25) +#define RT5514_I2S_BP_INV (0x1 << 25) +#define RT5514_I2S_DF_MASK (0x7 << 16) +#define RT5514_I2S_DF_SFT 16 +#define RT5514_I2S_DF_I2S (0x0 << 16) +#define RT5514_I2S_DF_LEFT (0x1 << 16) +#define RT5514_I2S_DF_PCM_A (0x2 << 16) +#define RT5514_I2S_DF_PCM_B (0x3 << 16) +#define RT5514_TDMSLOT_SEL_RX_MASK (0x3 << 10) +#define RT5514_TDMSLOT_SEL_RX_SFT 10 +#define RT5514_TDMSLOT_SEL_RX_4CH (0x1 << 10) +#define RT5514_CH_LEN_RX_MASK (0x3 << 8) +#define RT5514_CH_LEN_RX_SFT 8 +#define RT5514_CH_LEN_RX_16 (0x0 << 8) +#define RT5514_CH_LEN_RX_20 (0x1 << 8) +#define RT5514_CH_LEN_RX_24 (0x2 << 8) +#define RT5514_CH_LEN_RX_32 (0x3 << 8) +#define RT5514_TDMSLOT_SEL_TX_MASK (0x3 << 6) +#define RT5514_TDMSLOT_SEL_TX_SFT 6 +#define RT5514_TDMSLOT_SEL_TX_4CH (0x1 << 6) +#define RT5514_CH_LEN_TX_MASK (0x3 << 4) +#define RT5514_CH_LEN_TX_SFT 4 +#define RT5514_CH_LEN_TX_16 (0x0 << 4) +#define RT5514_CH_LEN_TX_20 (0x1 << 4) +#define RT5514_CH_LEN_TX_24 (0x2 << 4) +#define RT5514_CH_LEN_TX_32 (0x3 << 4) +#define RT5514_I2S_DL_MASK (0x3 << 0) +#define RT5514_I2S_DL_SFT 0 +#define RT5514_I2S_DL_16 (0x0 << 0) +#define RT5514_I2S_DL_20 (0x1 << 0) +#define RT5514_I2S_DL_24 (0x2 << 0) +#define RT5514_I2S_DL_8 (0x3 << 0) + +/* RT5514_DIG_SOURCE_CTRL (0x20a4) */ +#define RT5514_AD1_DMIC_INPUT_SEL (0x1 << 1) +#define RT5514_AD1_DMIC_INPUT_SEL_SFT 1 +#define RT5514_AD0_DMIC_INPUT_SEL (0x1 << 0) +#define RT5514_AD0_DMIC_INPUT_SEL_SFT 0 + +/* RT5514_PLL_SOURCE_CTRL (0x2100) */ +#define RT5514_PLL_1_SEL_MASK (0x7 << 12) +#define RT5514_PLL_1_SEL_SFT 12 +#define RT5514_PLL_1_SEL_SCLK (0x3 << 12) +#define RT5514_PLL_1_SEL_MCLK (0x4 << 12) + +/* RT5514_CLK_CTRL1 (0x2104) */ +#define RT5514_CLK_AD_ANA1_EN (0x1 << 31) +#define RT5514_CLK_AD_ANA1_EN_BIT 31 +#define RT5514_CLK_AD1_EN (0x1 << 24) +#define RT5514_CLK_AD1_EN_BIT 24 +#define RT5514_CLK_AD0_EN (0x1 << 23) +#define RT5514_CLK_AD0_EN_BIT 23 +#define RT5514_CLK_DMIC_OUT_SEL_MASK (0x7 << 8) +#define RT5514_CLK_DMIC_OUT_SEL_SFT 8 + +/* RT5514_CLK_CTRL2 (0x2108) */ +#define RT5514_CLK_SYS_DIV_OUT_MASK (0x7 << 8) +#define RT5514_CLK_SYS_DIV_OUT_SFT 8 +#define RT5514_SEL_ADC_OSR_MASK (0x7 << 4) +#define RT5514_SEL_ADC_OSR_SFT 4 +#define RT5514_CLK_SYS_PRE_SEL_MASK (0x3 << 0) +#define RT5514_CLK_SYS_PRE_SEL_SFT 0 +#define RT5514_CLK_SYS_PRE_SEL_MCLK (0x2 << 0) +#define RT5514_CLK_SYS_PRE_SEL_PLL (0x3 << 0) + +/* RT5514_DOWNFILTER_CTRL (0x2190 0x2194 0x21a0 0x21a4) */ +#define RT5514_AD_DMIC_MIX (0x1 << 11) +#define RT5514_AD_DMIC_MIX_BIT 11 +#define RT5514_AD_AD_MIX (0x1 << 10) +#define RT5514_AD_AD_MIX_BIT 10 +#define RT5514_AD_AD_MUTE (0x1 << 7) +#define RT5514_AD_AD_MUTE_BIT 7 +#define RT5514_AD_GAIN_MASK (0x7f << 0) +#define RT5514_AD_GAIN_SFT 0 + +/* RT5514_ANA_CTRL_MICBST (0x2220) */ +#define RT5514_SEL_BSTL_MASK (0xf << 4) +#define RT5514_SEL_BSTL_SFT 4 +#define RT5514_SEL_BSTR_MASK (0xf << 0) +#define RT5514_SEL_BSTR_SFT 0 + +/* RT5514_ANA_CTRL_PLL1_1 (0x2260) */ +#define RT5514_PLL_K_MAX 0x1f +#define RT5514_PLL_K_MASK (RT5514_PLL_K_MAX << 16) +#define RT5514_PLL_K_SFT 16 +#define RT5514_PLL_N_MAX 0x1ff +#define RT5514_PLL_N_MASK (RT5514_PLL_N_MAX << 7) +#define RT5514_PLL_N_SFT 4 +#define RT5514_PLL_M_MAX 0xf +#define RT5514_PLL_M_MASK (RT5514_PLL_M_MAX << 0) +#define RT5514_PLL_M_SFT 0 + +/* RT5514_ANA_CTRL_PLL1_2 (0x2264) */ +#define RT5514_PLL_M_BP (0x1 << 2) +#define RT5514_PLL_M_BP_SFT 2 +#define RT5514_PLL_K_BP (0x1 << 1) +#define RT5514_PLL_K_BP_SFT 1 +#define RT5514_EN_LDO_PLL1 (0x1 << 0) +#define RT5514_EN_LDO_PLL1_BIT 0 + +#define RT5514_PLL_INP_MAX 40000000 +#define RT5514_PLL_INP_MIN 256000 + +/* System Clock Source */ +enum { + RT5514_SCLK_S_MCLK, + RT5514_SCLK_S_PLL1, +}; + +/* PLL1 Source */ +enum { + RT5514_PLL1_S_MCLK, + RT5514_PLL1_S_BCLK, +}; + +struct rt5514_priv { + struct snd_soc_codec *codec; + struct regmap *i2c_regmap, *regmap; + int sysclk; + int sysclk_src; + int lrck; + int bclk; + int pll_src; + int pll_in; + int pll_out; +}; + +#endif /* __RT5514_H__ */ -- cgit From 94c39041ae0c0e83d10bc1a56974a2eefd9386c8 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 2 Feb 2016 18:27:37 +0800 Subject: regulator: axp20x: Remove voltage readout support for switch regulators Switch-type regulators, such as DC1SW on AXP22X, are a secondary output from DCDC1. They are just an on/off switch, and the driver should not try to read its voltage directly from the DCDC1 control registers. Instead, the core will pass down the voltage from the regulator supply chain. Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index f2e1a39ce0f3..fafaaa8eb8b3 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -78,8 +78,7 @@ .ops = &axp20x_ops, \ } -#define AXP_DESC_SW(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ - _vmask, _ereg, _emask) \ +#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \ [_family##_##_id] = { \ .name = #_id, \ .supply_name = (_supply), \ @@ -87,12 +86,7 @@ .regulators_node = of_match_ptr("regulators"), \ .type = REGULATOR_VOLTAGE, \ .id = _family##_##_id, \ - .n_voltages = (((_max) - (_min)) / (_step) + 1), \ .owner = THIS_MODULE, \ - .min_uV = (_min) * 1000, \ - .uV_step = (_step) * 1000, \ - .vsel_reg = (_vreg), \ - .vsel_mask = (_vmask), \ .enable_reg = (_ereg), \ .enable_mask = (_emask), \ .ops = &axp20x_ops_sw, \ @@ -160,8 +154,6 @@ static struct regulator_ops axp20x_ops = { }; static struct regulator_ops axp20x_ops_sw = { - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = regulator_list_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -196,8 +188,8 @@ static const struct regulator_desc axp22x_regulators[] = { AXP_DESC(AXP22X, DCDC5, "dcdc5", "vin5", 1000, 2550, 50, AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)), /* secondary switchable output of DCDC1 */ - AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, 1600, 3400, 100, - AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(7)), + AXP_DESC_SW(AXP22X, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2, + BIT(7)), /* LDO regulator internally chained to DCDC5 */ AXP_DESC(AXP22X, DC5LDO, "dc5ldo", NULL, 700, 1400, 100, AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)), -- cgit From 13d57e64352a5d3457d7782bc2f8b576e12b05f3 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Tue, 2 Feb 2016 18:27:38 +0800 Subject: regulator: axp20x: Use linear voltage ranges for AXP20X LDO4 AXP20X datasheet lists the possible voltage settings for LDO4, so it was implemented using a voltage table. Upon closer examination, the valid voltages can be mapped into 3 linear ranges. Move AXP20X LDO4 to use linear ranges. The supporting code can be reused with later AXP8xx PMICs, which have a number of regulators that have 2 linear ranges. Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index fafaaa8eb8b3..7d29893f833c 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -106,8 +106,8 @@ .ops = &axp20x_ops_fixed \ } -#define AXP_DESC_TABLE(_family, _id, _match, _supply, _table, _vreg, _vmask, \ - _ereg, _emask) \ +#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \ + _vreg, _vmask, _ereg, _emask) \ [_family##_##_id] = { \ .name = #_id, \ .supply_name = (_supply), \ @@ -115,30 +115,25 @@ .regulators_node = of_match_ptr("regulators"), \ .type = REGULATOR_VOLTAGE, \ .id = _family##_##_id, \ - .n_voltages = ARRAY_SIZE(_table), \ + .n_voltages = (_n_voltages), \ .owner = THIS_MODULE, \ .vsel_reg = (_vreg), \ .vsel_mask = (_vmask), \ .enable_reg = (_ereg), \ .enable_mask = (_emask), \ - .volt_table = (_table), \ - .ops = &axp20x_ops_table, \ + .linear_ranges = (_ranges), \ + .n_linear_ranges = ARRAY_SIZE(_ranges), \ + .ops = &axp20x_ops_range, \ } -static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000, - 1700000, 1800000, 1900000, 2000000, 2500000, - 2700000, 2800000, 3000000, 3100000, 3200000, - 3300000 }; - static struct regulator_ops axp20x_ops_fixed = { .list_voltage = regulator_list_voltage_linear, }; -static struct regulator_ops axp20x_ops_table = { +static struct regulator_ops axp20x_ops_range = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = regulator_list_voltage_table, - .map_voltage = regulator_map_voltage_ascend, + .list_voltage = regulator_list_voltage_linear_range, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, @@ -159,6 +154,12 @@ static struct regulator_ops axp20x_ops_sw = { .is_enabled = regulator_is_enabled_regmap, }; +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), +}; + static const struct regulator_desc axp20x_regulators[] = { AXP_DESC(AXP20X, DCDC2, "dcdc2", "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f, AXP20X_PWR_OUT_CTRL, 0x10), @@ -169,8 +170,9 @@ static const struct regulator_desc axp20x_regulators[] = { AXP20X_LDO24_V_OUT, 0xf0, AXP20X_PWR_OUT_CTRL, 0x04), AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f, AXP20X_PWR_OUT_CTRL, 0x40), - AXP_DESC_TABLE(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_data, - AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, 0x08), + AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in", axp20x_ldo4_ranges, + 16, AXP20X_LDO24_V_OUT, 0x0f, AXP20X_PWR_OUT_CTRL, + 0x08), AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0, AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED, AXP20X_IO_DISABLED), -- cgit From 917e50d6941ed8b2bbde0a066f15f0d19e8f9409 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 29 Jan 2016 13:09:00 -0300 Subject: regulator: max77802: Fix DT binding document reference The DT binding doc references the max77802 clocks header file which makes no sense since of course it doesn't contain data related to the regulators. It's a copy and paste error, so add a reference to the correct header file. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Acked-by: Rob Herring Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/regulator/max77802.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/regulator/max77802.txt b/Documentation/devicetree/bindings/regulator/max77802.txt index 09d796ed48be..879e98d3b9aa 100644 --- a/Documentation/devicetree/bindings/regulator/max77802.txt +++ b/Documentation/devicetree/bindings/regulator/max77802.txt @@ -60,7 +60,7 @@ The possible values for "regulator-initial-mode" and "regulator-mode" are: 1: Normal regulator voltage output mode. 3: Low Power which reduces the quiescent current down to only 1uA -The list of valid modes are defined in the dt-bindings/clock/maxim,max77802.h +The valid modes list is defined in the dt-bindings/regulator/maxim,max77802.h header and can be included by device tree source files. The standard "regulator-mode" property can only be used for regulators that -- cgit From fcc5184ec1521c7d85124421e593660c94e9a9fb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:42:04 -0500 Subject: USB: EHCI: store reason for unlinking a QH This patch replaces the "exception" bitflag in the ehci_qh structure with a more explicit "unlink_reason" bitmask. This is for use in the following patch, where we will need to have a good idea of the reason for unlinking a QH, not just "something exceptional happened". Signed-off-by: Alan Stern Tested-by: Michael Reutman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 11 +++++++---- drivers/usb/host/ehci-q.c | 13 +++++++++---- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/ehci-timer.c | 1 + drivers/usb/host/ehci.h | 10 ++++++++-- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 00e77cc91053..c5465bf9a798 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -911,7 +911,7 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) */ } else { qh = (struct ehci_qh *) urb->hcpriv; - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_REQUESTED; switch (qh->qh_state) { case QH_STATE_LINKED: if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) @@ -972,10 +972,13 @@ rescan: goto done; } - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_REQUESTED; switch (qh->qh_state) { case QH_STATE_LINKED: - WARN_ON(!list_empty(&qh->qtd_list)); + if (list_empty(&qh->qtd_list)) + qh->unlink_reason |= QH_UNLINK_QUEUE_EMPTY; + else + WARN_ON(1); if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT) start_unlink_async(ehci, qh); else @@ -1042,7 +1045,7 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) * re-linking will call qh_refresh(). */ usb_settoggle(qh->ps.udev, epnum, is_out, 0); - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_REQUESTED; if (eptype == USB_ENDPOINT_XFER_BULK) start_unlink_async(ehci, qh); else diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index aad0777240d3..1b42bcb59743 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -394,6 +394,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) goto retry_xacterr; } stopped = 1; + qh->unlink_reason |= QH_UNLINK_HALTED; /* magic dummy for some short reads; qh won't advance. * that silicon quirk can kick in with this dummy too. @@ -408,6 +409,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) && !(qtd->hw_alt_next & EHCI_LIST_END(ehci))) { stopped = 1; + qh->unlink_reason |= QH_UNLINK_SHORT_READ; } /* stop scanning when we reach qtds the hc is using */ @@ -420,8 +422,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) stopped = 1; /* cancel everything if we halt, suspend, etc */ - if (ehci->rh_state < EHCI_RH_RUNNING) + if (ehci->rh_state < EHCI_RH_RUNNING) { last_status = -ESHUTDOWN; + qh->unlink_reason |= QH_UNLINK_SHUTDOWN; + } /* this qtd is active; skip it unless a previous qtd * for its urb faulted, or its urb was canceled. @@ -538,10 +542,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * except maybe high bandwidth ... */ if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) - qh->exception = 1; + qh->unlink_reason |= QH_UNLINK_DUMMY_OVERLAY; /* Let the caller know if the QH needs to be unlinked. */ - return qh->exception; + return qh->unlink_reason; } /*-------------------------------------------------------------------------*/ @@ -1003,7 +1007,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_LINKED; qh->xacterrs = 0; - qh->exception = 0; + qh->unlink_reason = 0; /* qtd completions reported later by interrupt */ enable_async(ehci); @@ -1395,6 +1399,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci) /* If nothing else is being unlinked, unlink the last empty QH */ if (list_empty(&ehci->async_unlink) && qh_to_unlink) { + qh_to_unlink->unlink_reason |= QH_UNLINK_QUEUE_EMPTY; start_unlink_async(ehci, qh_to_unlink); --count; } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f9a332775c47..c1704a57e803 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -595,7 +595,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) } qh->qh_state = QH_STATE_LINKED; qh->xacterrs = 0; - qh->exception = 0; + qh->unlink_reason = 0; /* update per-qh bandwidth for debugfs */ ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.bw_period diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 424ac5d83714..37a3e0dece84 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -237,6 +237,7 @@ static void ehci_handle_start_intr_unlinks(struct ehci_hcd *ehci) ehci->intr_unlink_wait_cycle)) break; list_del_init(&qh->unlink_node); + qh->unlink_reason |= QH_UNLINK_QUEUE_EMPTY; start_unlink_intr(ehci, qh); } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index ec61aedb0067..f11b9dc53981 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -432,13 +432,19 @@ struct ehci_qh { u8 xacterrs; /* XactErr retry counter */ #define QH_XACTERR_MAX 32 /* XactErr retry limit */ + u8 unlink_reason; +#define QH_UNLINK_HALTED 0x01 /* Halt flag is set */ +#define QH_UNLINK_SHORT_READ 0x02 /* Recover from a short read */ +#define QH_UNLINK_DUMMY_OVERLAY 0x04 /* QH overlayed the dummy TD */ +#define QH_UNLINK_SHUTDOWN 0x08 /* The HC isn't running */ +#define QH_UNLINK_QUEUE_EMPTY 0x10 /* Reached end of the queue */ +#define QH_UNLINK_REQUESTED 0x20 /* Disable, reset, or dequeue */ + u8 gap_uf; /* uframes split/csplit gap */ unsigned is_out:1; /* bulk or intr OUT */ unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ unsigned dequeue_during_giveback:1; - unsigned exception:1; /* got a fault, or an unlink - was requested */ unsigned should_be_inactive:1; }; -- cgit From f96fba0dbf8f6b0eaa313b4c230f93c9bb0dd759 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:44:16 -0500 Subject: USB: EHCI: improve handling of the ehci->iaa_in_progress flag This patch improves the way ehci-hcd handles the iaa_in_progress flag. The current code is somewhat careless in this regard: The flag is meaningless when the root hub isn't running, most particularly after the root hub has been suspended. But in start_iaa_cycle(), the driver checks the flag before checking the root hub's state. They should be checked in the opposite order. That routine also sets the flag too early, before it has definitely committed to starting an IAA cycle. The flag is turned off in end_unlink_async(). Upcoming changes will call that routine at other times, not just at the end of an IAA cycle. The two actions are logically separate (although related), so we separate out a new routine to be called in place of end_unlink_async() whenever an IAA cycle ends: end_iaa_cycle(). iaa_in_progress should be turned off when the root hub is suspended -- we certainly don't want it still to be set when the root hub resumes. Therefore the call to end_unlink_async() in ehci_bus_suspend() should also be replaced with a call to end_iaa_cycle(). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 3 ++- drivers/usb/host/ehci-hub.c | 3 ++- drivers/usb/host/ehci-q.c | 28 +++++++++++++++------------- drivers/usb/host/ehci-timer.c | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c5465bf9a798..84c41262109c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -306,6 +306,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ +static void end_iaa_cycle(struct ehci_hcd *ehci); static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); static void unlink_empty_async_suspended(struct ehci_hcd *ehci); @@ -758,7 +759,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) ehci_dbg(ehci, "IAA with IAAD still set?\n"); if (ehci->iaa_in_progress) COUNT(ehci->stats.iaa); - end_unlink_async(ehci); + end_iaa_cycle(ehci); } /* remote wakeup [4.3.1] */ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 086a7115d263..6d84ce2edc27 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -347,7 +347,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) goto done; ehci->rh_state = EHCI_RH_SUSPENDED; - end_unlink_async(ehci); + /* Any IAA cycle that started before the suspend is now invalid */ + end_iaa_cycle(ehci); unlink_empty_async_suspended(ehci); ehci_handle_start_intr_unlinks(ehci); ehci_handle_intr_unlinks(ehci); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 1b42bcb59743..15dcae8f0631 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1283,17 +1283,13 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) static void start_iaa_cycle(struct ehci_hcd *ehci) { - /* Do nothing if an IAA cycle is already running */ - if (ehci->iaa_in_progress) - return; - ehci->iaa_in_progress = true; - /* If the controller isn't running, we don't have to wait for it */ if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { end_unlink_async(ehci); - /* Otherwise start a new IAA cycle */ - } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { + /* Otherwise start a new IAA cycle if one isn't already running */ + } else if (ehci->rh_state == EHCI_RH_RUNNING && + !ehci->iaa_in_progress) { /* Make sure the unlinks are all visible to the hardware */ wmb(); @@ -1301,17 +1297,13 @@ static void start_iaa_cycle(struct ehci_hcd *ehci) ehci_writel(ehci, ehci->command | CMD_IAAD, &ehci->regs->command); ehci_readl(ehci, &ehci->regs->command); + ehci->iaa_in_progress = true; ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true); } } -/* the async qh for the qtds being unlinked are now gone from the HC */ - -static void end_unlink_async(struct ehci_hcd *ehci) +static void end_iaa_cycle(struct ehci_hcd *ehci) { - struct ehci_qh *qh; - bool early_exit; - if (ehci->has_synopsys_hc_bug) ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); @@ -1319,6 +1311,16 @@ static void end_unlink_async(struct ehci_hcd *ehci) /* The current IAA cycle has ended */ ehci->iaa_in_progress = false; + end_unlink_async(ehci); +} + +/* See if the async qh for the qtds being unlinked are now gone from the HC */ + +static void end_unlink_async(struct ehci_hcd *ehci) +{ + struct ehci_qh *qh; + bool early_exit; + if (list_empty(&ehci->async_unlink)) return; qh = list_first_entry(&ehci->async_unlink, struct ehci_qh, diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 37a3e0dece84..6bea4d553ec5 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -361,7 +361,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci) } ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); - end_unlink_async(ehci); + end_iaa_cycle(ehci); } -- cgit From 87d61912c23a746ee9a8a8d2fe17af217c87f761 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:45:25 -0500 Subject: USB: EHCI: add a delay when unlinking an active QH Michael Reutman reports that an AMD/ATI EHCI host controller on one of his computers does not stop transferring data when an active bulk QH is unlinked from the async schedule. Apparently that host controller fails to implement the IAA mechanism correctly when an active QH is unlinked. This leads to data corruption, because the controller continues to update the QH in memory when the driver doesn't expect it. As a result, the next URB submitted for that QH can hang, because the link pointers for the TD queue have been messed up. This misbehavior is observed quite regularly. To be fair, the EHCI spec (section 4.8.2) says that active QHs should not be unlinked. It goes on to recommend a procedure that involves waiting for the QH to go inactive before unlinking it. In the real world this is impractical, not least because the QH may _never_ go inactive. (What were they thinking?) Sometimes we have no choice but to unlink an active QH. In an attempt to avoid the problems that can ensue, this patch changes how the driver decides when the unlink is complete. In addition to waiting through two IAA cycles, in cases where the QH was not known to be inactive beforehand we now wait until a 2-ms period has elapsed with the host controller making no change to the QH data structure (the hw_current and hw_token fields in particular). The intuition here is that after such a long period, the endpoint must be NAKing and hopefully the QH has been dropped from the host controller's internal cache. There's no way to know if this reasoning is really valid -- the spec is no help in this regard -- but at least this approach fixes Michael's problem. The test for whether the QH is already known to be inactive involves the reason for unlinking the QH originally. If it was unlinked because it had halted, or it stopped in response to a short read, or it overlaid a dummy TD (a silicon bug), then it certainly is inactive. If it was unlinked because the TD queue was empty and no TDs have been added to the queue in the meantime, then it must be inactive. Or if the hardware status indicates that the QH is currently halted (even if that wasn't the reason for unlinking it), then it is inactive. Otherwise, if none of those checks apply, we go through the 2-ms delay. Signed-off-by: Alan Stern Reported-by: Michael Reutman Tested-by: Michael Reutman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 3 +++ drivers/usb/host/ehci-q.c | 56 +++++++++++++++++++++++++++++++++++++++---- drivers/usb/host/ehci-timer.c | 2 ++ drivers/usb/host/ehci.h | 3 +++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 84c41262109c..a93d445b63a4 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -566,6 +566,9 @@ static int ehci_init(struct usb_hcd *hcd) /* Accept arbitrarily long scatter-gather lists */ if (!(hcd->driver->flags & HCD_LOCAL_MEM)) hcd->self.sg_tablesize = ~0; + + /* Prepare for unlinking active QHs */ + ehci->old_current = ~0; return 0; } diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 15dcae8f0631..a24341ef863d 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1341,14 +1341,60 @@ static void end_unlink_async(struct ehci_hcd *ehci) * after the IAA interrupt occurs. In self-defense, always go * through two IAA cycles for each QH. */ - else if (qh->qh_state == QH_STATE_UNLINK_WAIT) { + else if (qh->qh_state == QH_STATE_UNLINK) { + /* + * Second IAA cycle has finished. Process only the first + * waiting QH (NVIDIA (?) bug). + */ + list_move_tail(&qh->unlink_node, &ehci->async_idle); + } + + /* + * AMD/ATI (?) bug: The HC can continue to use an active QH long + * after the IAA interrupt occurs. To prevent problems, QHs that + * may still be active will wait until 2 ms have passed with no + * change to the hw_current and hw_token fields (this delay occurs + * between the two IAA cycles). + * + * The EHCI spec (4.8.2) says that active QHs must not be removed + * from the async schedule and recommends waiting until the QH + * goes inactive. This is ridiculous because the QH will _never_ + * become inactive if the endpoint NAKs indefinitely. + */ + + /* Some reasons for unlinking guarantee the QH can't be active */ + else if (qh->unlink_reason & (QH_UNLINK_HALTED | + QH_UNLINK_SHORT_READ | QH_UNLINK_DUMMY_OVERLAY)) + goto DelayDone; + + /* The QH can't be active if the queue was and still is empty... */ + else if ((qh->unlink_reason & QH_UNLINK_QUEUE_EMPTY) && + list_empty(&qh->qtd_list)) + goto DelayDone; + + /* ... or if the QH has halted */ + else if (qh->hw->hw_token & cpu_to_hc32(ehci, QTD_STS_HALT)) + goto DelayDone; + + /* Otherwise we have to wait until the QH stops changing */ + else { + __hc32 qh_current, qh_token; + + qh_current = qh->hw->hw_current; + qh_token = qh->hw->hw_token; + if (qh_current != ehci->old_current || + qh_token != ehci->old_token) { + ehci->old_current = qh_current; + ehci->old_token = qh_token; + ehci_enable_event(ehci, + EHCI_HRTIMER_ACTIVE_UNLINK, true); + return; + } + DelayDone: qh->qh_state = QH_STATE_UNLINK; early_exit = true; } - - /* Otherwise process only the first waiting QH (NVIDIA bug?) */ - else - list_move_tail(&qh->unlink_node, &ehci->async_idle); + ehci->old_current = ~0; /* Prepare for next QH */ /* Start a new IAA cycle if any QHs are waiting for it */ if (!list_empty(&ehci->async_unlink)) diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 6bea4d553ec5..69f50e6533a6 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -72,6 +72,7 @@ static unsigned event_delays_ns[] = { 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_DEAD */ 1125 * NSEC_PER_USEC, /* EHCI_HRTIMER_UNLINK_INTR */ 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_FREE_ITDS */ + 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ACTIVE_UNLINK */ 5 * NSEC_PER_MSEC, /* EHCI_HRTIMER_START_UNLINK_INTR */ 6 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ASYNC_UNLINKS */ 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IAA_WATCHDOG */ @@ -395,6 +396,7 @@ static void (*event_handlers[])(struct ehci_hcd *) = { ehci_handle_controller_death, /* EHCI_HRTIMER_POLL_DEAD */ ehci_handle_intr_unlinks, /* EHCI_HRTIMER_UNLINK_INTR */ end_free_itds, /* EHCI_HRTIMER_FREE_ITDS */ + end_unlink_async, /* EHCI_HRTIMER_ACTIVE_UNLINK */ ehci_handle_start_intr_unlinks, /* EHCI_HRTIMER_START_UNLINK_INTR */ unlink_empty_async, /* EHCI_HRTIMER_ASYNC_UNLINKS */ ehci_iaa_watchdog, /* EHCI_HRTIMER_IAA_WATCHDOG */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index f11b9dc53981..b13894550139 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -110,6 +110,7 @@ enum ehci_hrtimer_event { EHCI_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ EHCI_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ + EHCI_HRTIMER_ACTIVE_UNLINK, /* Wait while unlinking an active QH */ EHCI_HRTIMER_START_UNLINK_INTR, /* Unlink empty interrupt QHs */ EHCI_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ EHCI_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ @@ -156,6 +157,8 @@ struct ehci_hcd { /* one per controller */ struct list_head async_idle; unsigned async_unlink_cycle; unsigned async_count; /* async activity count */ + __hc32 old_current; /* Test for QH becoming */ + __hc32 old_token; /* inactive during unlink */ /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ -- cgit From 8df0d77d8ce065ef536676fb4e1f36bfbf1dd809 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 25 Jan 2016 15:45:38 -0500 Subject: USB: EHCI: improvements to unlink_empty_async_suspended() unlink_empty_async_suspended() is marked __maybe_unused. This is because its caller, ehci_bus_suspend(), is protected by "#ifdef CONFIG_PM". We should use the same protection here instead of __maybe_unused. unlink_empty_async_suspended() gets called only when the root hub is suspended. It's silly for it to call start_iaa_cycle() at such a time; the IAA mechanism doesn't work when the root hub isn't running. It should call end_unlink_async() instead. But even this isn't necessary, since there already is a call to end_iaa_cycle() right before the call to unlink_empty_async_suspended(). All we have to do is interchange the two subroutine calls. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 3 ++- drivers/usb/host/ehci-q.c | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6d84ce2edc27..6333d3c2be9c 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -347,9 +347,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) goto done; ehci->rh_state = EHCI_RH_SUSPENDED; + unlink_empty_async_suspended(ehci); + /* Any IAA cycle that started before the suspend is now invalid */ end_iaa_cycle(ehci); - unlink_empty_async_suspended(ehci); ehci_handle_start_intr_unlinks(ehci); ehci_handle_intr_unlinks(ehci); end_free_itds(ehci); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index a24341ef863d..eca3710d8fc4 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1459,8 +1459,10 @@ static void unlink_empty_async(struct ehci_hcd *ehci) } } +#ifdef CONFIG_PM + /* The root hub is suspended; unlink all the async QHs */ -static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) +static void unlink_empty_async_suspended(struct ehci_hcd *ehci) { struct ehci_qh *qh; @@ -1469,9 +1471,10 @@ static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) WARN_ON(!list_empty(&qh->qtd_list)); single_unlink_async(ehci, qh); } - start_iaa_cycle(ehci); } +#endif + /* makes sure the async qh will become idle */ /* caller must own ehci->lock */ -- cgit From 0caf6b33452112e5a1186c8c964e90310e49e6bd Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:44 +0200 Subject: xhci: Make sure xhci handles USB_SPEED_SUPER_PLUS devices. In most cases the devices with the speed set to USB_SPEED_SUPER_PLUS are handled like regular SuperSpeed devices. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 9 ++++++--- drivers/usb/host/xhci-ring.c | 3 ++- drivers/usb/host/xhci.c | 7 +++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 5cd080e0a685..9c3da214a515 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1070,7 +1070,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_device *top_dev; struct usb_hcd *hcd; - if (udev->speed == USB_SPEED_SUPER) + if (udev->speed >= USB_SPEED_SUPER) hcd = xhci->shared_hcd; else hcd = xhci->main_hcd; @@ -1105,6 +1105,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud /* 3) Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route); switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); max_packets = MAX_PACKET(512); @@ -1292,6 +1293,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, } /* Fall through - SS and HS isoc/int have same decoding */ + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: if (usb_endpoint_xfer_int(&ep->desc) || usb_endpoint_xfer_isoc(&ep->desc)) { @@ -1332,7 +1334,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, static u32 xhci_get_endpoint_mult(struct usb_device *udev, struct usb_host_endpoint *ep) { - if (udev->speed != USB_SPEED_SUPER || + if (udev->speed < USB_SPEED_SUPER || !usb_endpoint_xfer_isoc(&ep->desc)) return 0; return ep->ss_ep_comp.bmAttributes; @@ -1382,7 +1384,7 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, usb_endpoint_xfer_bulk(&ep->desc)) return 0; - if (udev->speed == USB_SPEED_SUPER) + if (udev->speed >= USB_SPEED_SUPER) return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); @@ -1453,6 +1455,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); max_burst = 0; switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: /* dig out max burst from ep companion desc */ max_burst = ep->ss_ep_comp.bMaxBurst; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f1c21c40b4a6..cd336226ad47 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3573,7 +3573,7 @@ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, { unsigned int max_burst; - if (xhci->hci_version < 0x100 || udev->speed != USB_SPEED_SUPER) + if (xhci->hci_version < 0x100 || udev->speed < USB_SPEED_SUPER) return 0; max_burst = urb->ep->ss_ep_comp.bMaxBurst; @@ -3599,6 +3599,7 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, return 0; switch (udev->speed) { + case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: /* bMaxBurst is zero based: 0 means 1 packet per burst */ max_burst = urb->ep->ss_ep_comp.bMaxBurst; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 26a44c0e969e..32d23e1301b8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2084,6 +2084,7 @@ static unsigned int xhci_get_block_size(struct usb_device *udev) case USB_SPEED_HIGH: return HS_BLOCK; case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: return SS_BLOCK; case USB_SPEED_UNKNOWN: case USB_SPEED_WIRELESS: @@ -2209,7 +2210,7 @@ static int xhci_check_bw_table(struct xhci_hcd *xhci, unsigned int packets_remaining = 0; unsigned int i; - if (virt_dev->udev->speed == USB_SPEED_SUPER) + if (virt_dev->udev->speed >= USB_SPEED_SUPER) return xhci_check_ss_bw(xhci, virt_dev); if (virt_dev->udev->speed == USB_SPEED_HIGH) { @@ -2410,7 +2411,7 @@ void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, if (xhci_is_async_ep(ep_bw->type)) return; - if (udev->speed == USB_SPEED_SUPER) { + if (udev->speed >= USB_SPEED_SUPER) { if (xhci_is_sync_in_ep(ep_bw->type)) xhci->devs[udev->slot_id]->bw_table->ss_bw_in -= xhci_get_ss_bw_consumed(ep_bw); @@ -2448,6 +2449,7 @@ void xhci_drop_ep_from_interval_table(struct xhci_hcd *xhci, interval_bw->overhead[HS_OVERHEAD_TYPE] -= 1; break; case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: case USB_SPEED_UNKNOWN: case USB_SPEED_WIRELESS: /* Should never happen because only LS/FS/HS endpoints will get @@ -2507,6 +2509,7 @@ static void xhci_add_ep_to_interval_table(struct xhci_hcd *xhci, interval_bw->overhead[HS_OVERHEAD_TYPE] += 1; break; case USB_SPEED_SUPER: + case USB_SPEED_SUPER_PLUS: case USB_SPEED_UNKNOWN: case USB_SPEED_WIRELESS: /* Should never happen because only LS/FS/HS endpoints will get -- cgit From 2c0e06f8829a542e71b14ffcaa14b8fafa2223c3 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:45 +0200 Subject: xhci: set roothub speed to USB_SPEED_SUPER_PLUS for USB3.1 capable controllers Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 32d23e1301b8..503d82fb0dd5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4898,6 +4898,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) if (xhci->sbrn == 0x31) { xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n"); hcd->speed = HCD_USB31; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; } /* xHCI private pointer was set in xhci_pci_probe for the second * registered roothub. -- cgit From 5da665fcec1a308f5273aacb9da8e87b89da8b4f Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:46 +0200 Subject: xhci: USB 3.1 add default Speed Attributes to SuperSpeedPlus device capability If a xhci controller does not provide a protocol speed ID (PSI) table, a default one should be used instead. Add the default values to the SuperSpeedPlus device capability. Overwrite the default ones if a PSI table exists. See xHCI 1.1 sectio 7.2.2.1.1 for more info Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hub.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index b30b4ce294d3..d61fcc48099e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -50,14 +50,18 @@ static u8 usb_bos_descriptor [] = { 0x00, /* bU1DevExitLat, set later. */ 0x00, 0x00, /* __le16 bU2DevExitLat, set later. */ /* Second device capability, SuperSpeedPlus */ - 0x0c, /* bLength 12, will be adjusted later */ + 0x1c, /* bLength 28, will be adjusted later */ USB_DT_DEVICE_CAPABILITY, /* Device Capability */ USB_SSP_CAP_TYPE, /* bDevCapabilityType SUPERSPEED_PLUS */ 0x00, /* bReserved 0 */ - 0x00, 0x00, 0x00, 0x00, /* bmAttributes, get from xhci psic */ - 0x00, 0x00, /* wFunctionalitySupport */ + 0x23, 0x00, 0x00, 0x00, /* bmAttributes, SSAC=3 SSIC=1 */ + 0x01, 0x00, /* wFunctionalitySupport */ 0x00, 0x00, /* wReserved 0 */ - /* Sublink Speed Attributes are added in xhci_create_usb3_bos_desc() */ + /* Default Sublink Speed Attributes, overwrite if custom PSI exists */ + 0x34, 0x00, 0x05, 0x00, /* 5Gbps, symmetric, rx, ID = 4 */ + 0xb4, 0x00, 0x05, 0x00, /* 5Gbps, symmetric, tx, ID = 4 */ + 0x35, 0x40, 0x0a, 0x00, /* 10Gbps, SSP, symmetric, rx, ID = 5 */ + 0xb5, 0x40, 0x0a, 0x00, /* 10Gbps, SSP, symmetric, tx, ID = 5 */ }; static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, @@ -72,10 +76,14 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size; /* does xhci support USB 3.1 Enhanced SuperSpeed */ - if (xhci->usb3_rhub.min_rev >= 0x01 && xhci->usb3_rhub.psi_uid_count) { - /* two SSA entries for each unique PSI ID, one RX and one TX */ - ssa_count = xhci->usb3_rhub.psi_uid_count * 2; - ssa_size = ssa_count * sizeof(u32); + if (xhci->usb3_rhub.min_rev >= 0x01) { + /* does xhci provide a PSI table for SSA speed attributes? */ + if (xhci->usb3_rhub.psi_count) { + /* two SSA entries for each unique PSI ID, RX and TX */ + ssa_count = xhci->usb3_rhub.psi_uid_count * 2; + ssa_size = ssa_count * sizeof(u32); + ssp_cap_size -= 16; /* skip copying the default SSA */ + } desc_size += ssp_cap_size; usb3_1 = true; } @@ -102,7 +110,8 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); } - if (usb3_1) { + /* If PSI table exists, add the custom speed attributes from it */ + if (usb3_1 && xhci->usb3_rhub.psi_count) { u32 ssp_cap_base, bm_attrib, psi; int offset; -- cgit From d78540419866887345cec480016b0f87f6a5aca2 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Mon, 25 Jan 2016 15:30:47 +0200 Subject: xhci: set slot context speed field to SuperSpeedPlus for USB 3.1 SSP devices The speed field of the input slot context should represent the speed the device is working at. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 3 +++ drivers/usb/host/xhci.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 9c3da214a515..42f2bec759aa 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1106,6 +1106,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route); switch (udev->speed) { case USB_SPEED_SUPER_PLUS: + slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SSP); + max_packets = MAX_PACKET(512); + break; case USB_SPEED_SUPER: slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); max_packets = MAX_PACKET(512); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 9be7348872ba..9f28bea65fed 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -343,6 +343,7 @@ struct xhci_op_regs { #define SLOT_SPEED_LS (XDEV_LS << 10) #define SLOT_SPEED_HS (XDEV_HS << 10) #define SLOT_SPEED_SS (XDEV_SS << 10) +#define SLOT_SPEED_SSP (XDEV_SSP << 10) /* Port Indicator Control */ #define PORT_LED_OFF (0 << 14) #define PORT_LED_AMBER (1 << 14) -- cgit From 5363de75307e333d89df7531f9dd8310d973ecdb Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 25 Jan 2016 20:30:30 +0100 Subject: usb: core: switch bus numbering to using idr USB bus numbering is based on directly dealing with bitmaps and defines a separate list of busses. This can be simplified and unified by using existing idr functionality. Signed-off-by: Heiner Kallweit Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 10 ++-------- drivers/usb/core/hcd.c | 21 ++++++--------------- drivers/usb/core/usb.c | 1 + drivers/usb/host/r8a66597-hcd.c | 9 ++------- drivers/usb/mon/mon_main.c | 5 ++--- include/linux/usb.h | 1 - include/linux/usb/hcd.h | 3 ++- 7 files changed, 15 insertions(+), 35 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index b35a6a52210f..6118a04f0b84 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -110,13 +110,6 @@ static const char format_endpt[] = /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; - -/* - * Need access to the driver and USB bus lists. - * extern struct list_head usb_bus_list; - * However, these will come from functions that return ptrs to each of them. - */ - /* * Wait for an connect/disconnect event to happen. We initialize * the event counter with an odd number, and each event will increment @@ -618,6 +611,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, struct usb_bus *bus; ssize_t ret, total_written = 0; loff_t skip_bytes = *ppos; + int id; if (*ppos < 0) return -EINVAL; @@ -628,7 +622,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, mutex_lock(&usb_bus_list_lock); /* print devices for all busses */ - list_for_each_entry(bus, &usb_bus_list, bus_list) { + idr_for_each_entry(&usb_bus_idr, bus, id) { /* recurse through all children of the root hub */ if (!bus_to_hcd(bus)->rh_registered) continue; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 232c8c93dd3a..cf3eb22dbeb4 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -90,12 +90,11 @@ unsigned long usb_hcds_loaded; EXPORT_SYMBOL_GPL(usb_hcds_loaded); /* host controllers we manage */ -LIST_HEAD (usb_bus_list); -EXPORT_SYMBOL_GPL (usb_bus_list); +DEFINE_IDR (usb_bus_idr); +EXPORT_SYMBOL_GPL (usb_bus_idr); /* used when allocating bus numbers */ #define USB_MAXBUS 64 -static DECLARE_BITMAP(busmap, USB_MAXBUS); /* used when updating list of hcds */ DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ @@ -996,8 +995,6 @@ static void usb_bus_init (struct usb_bus *bus) bus->bandwidth_int_reqs = 0; bus->bandwidth_isoc_reqs = 0; mutex_init(&bus->usb_address0_mutex); - - INIT_LIST_HEAD (&bus->bus_list); } /*-------------------------------------------------------------------------*/ @@ -1018,16 +1015,12 @@ static int usb_register_bus(struct usb_bus *bus) int busnum; mutex_lock(&usb_bus_list_lock); - busnum = find_next_zero_bit(busmap, USB_MAXBUS, 1); - if (busnum >= USB_MAXBUS) { - printk (KERN_ERR "%s: too many buses\n", usbcore_name); + busnum = idr_alloc(&usb_bus_idr, bus, 1, USB_MAXBUS, GFP_KERNEL); + if (busnum < 0) { + pr_err("%s: failed to get bus number\n", usbcore_name); goto error_find_busnum; } - set_bit(busnum, busmap); bus->busnum = busnum; - - /* Add it to the local list of buses */ - list_add (&bus->bus_list, &usb_bus_list); mutex_unlock(&usb_bus_list_lock); usb_notify_add_bus(bus); @@ -1059,12 +1052,10 @@ static void usb_deregister_bus (struct usb_bus *bus) * itself up */ mutex_lock(&usb_bus_list_lock); - list_del (&bus->bus_list); + idr_remove(&usb_bus_idr, bus->busnum); mutex_unlock(&usb_bus_list_lock); usb_notify_remove_bus(bus); - - clear_bit(bus->busnum, busmap); } /** diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 16ade41759cd..524c9822d2bb 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1115,6 +1115,7 @@ static void __exit usb_exit(void) bus_unregister(&usb_bus_type); usb_acpi_unregister(); usb_debugfs_cleanup(); + idr_destroy(&usb_bus_idr); } subsys_initcall(usb_init); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 4cbd0633c5c2..1ef887361ac0 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2099,13 +2099,8 @@ static void r8a66597_check_detect_child(struct r8a66597 *r8a66597, memset(now_map, 0, sizeof(now_map)); - list_for_each_entry(bus, &usb_bus_list, bus_list) { - if (!bus->root_hub) - continue; - - if (bus->busnum != hcd->self.busnum) - continue; - + bus = idr_find(&usb_bus_idr, hcd->self.busnum); + if (bus && bus->root_hub) { collect_usb_address_map(bus->root_hub, now_map); update_usb_address_map(r8a66597, bus->root_hub, now_map); } diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index fec3f1128fdc..9b87efb0e50d 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -349,7 +349,7 @@ struct mon_bus *mon_bus_lookup(unsigned int num) static int __init mon_init(void) { struct usb_bus *ubus; - int rc; + int rc, id; if ((rc = mon_text_init()) != 0) goto err_text; @@ -366,9 +366,8 @@ static int __init mon_init(void) // MOD_INC_USE_COUNT(which_module?); mutex_lock(&usb_bus_list_lock); - list_for_each_entry (ubus, &usb_bus_list, bus_list) { + idr_for_each_entry(&usb_bus_idr, ubus, id) mon_bus_init(ubus); - } usb_register_notify(&mon_nb); mutex_unlock(&usb_bus_list_lock); return 0; diff --git a/include/linux/usb.h b/include/linux/usb.h index 89533ba38691..0d348fa84a66 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -375,7 +375,6 @@ struct usb_bus { struct usb_devmap devmap; /* device address allocation map */ struct usb_device *root_hub; /* Root hub */ struct usb_bus *hs_companion; /* Companion EHCI bus, if any */ - struct list_head bus_list; /* list of busses */ struct mutex usb_address0_mutex; /* unaddressed device mutex */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 4dcf8446dbcd..c293dd044599 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -23,6 +23,7 @@ #include #include +#include #define MAX_TOPO_LEVEL 6 @@ -630,7 +631,7 @@ extern void usb_set_device_state(struct usb_device *udev, /* exported only within usbcore */ -extern struct list_head usb_bus_list; +extern struct idr usb_bus_idr; extern struct mutex usb_bus_list_lock; extern wait_queue_head_t usb_kill_urb_queue; -- cgit From 7dd9cba5bb90ffa9c60c1533b715dc91c5082cd9 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 21 Jan 2016 15:18:47 +0100 Subject: usb: sysfs: make locking interruptible 232275a USB: fix substandard locking for the sysfs files introduced needed locking into sysfs operations on USB devices It, however, uses uninterruptible sleep and if the error handling is on extreme cases of sleep lengths of 10s of seconds are possible. Unless we are removing the device we should use interruptible sleep. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 69 ++++++++++++++++++++++++++++++++++-------------- include/linux/device.h | 5 ++++ include/linux/usb.h | 7 ++--- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index f195320d35c0..7a6209314997 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -23,10 +23,12 @@ static ssize_t field##_show(struct device *dev, \ { \ struct usb_device *udev; \ struct usb_host_config *actconfig; \ - ssize_t rc = 0; \ + ssize_t rc; \ \ udev = to_usb_device(dev); \ - usb_lock_device(udev); \ + rc = usb_lock_device_interruptible(udev); \ + if (rc < 0) \ + return -EINTR; \ actconfig = udev->actconfig; \ if (actconfig) \ rc = sprintf(buf, format_string, \ @@ -47,10 +49,12 @@ static ssize_t bMaxPower_show(struct device *dev, { struct usb_device *udev; struct usb_host_config *actconfig; - ssize_t rc = 0; + ssize_t rc; udev = to_usb_device(dev); - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; actconfig = udev->actconfig; if (actconfig) rc = sprintf(buf, "%dmA\n", usb_get_max_power(udev, actconfig)); @@ -64,10 +68,12 @@ static ssize_t configuration_show(struct device *dev, { struct usb_device *udev; struct usb_host_config *actconfig; - ssize_t rc = 0; + ssize_t rc; udev = to_usb_device(dev); - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; actconfig = udev->actconfig; if (actconfig && actconfig->string) rc = sprintf(buf, "%s\n", actconfig->string); @@ -84,11 +90,13 @@ static ssize_t bConfigurationValue_store(struct device *dev, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int config, value; + int config, value, rc; if (sscanf(buf, "%d", &config) != 1 || config < -1 || config > 255) return -EINVAL; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; value = usb_set_configuration(udev, config); usb_unlock_device(udev); return (value < 0) ? value : count; @@ -105,7 +113,9 @@ static ssize_t name##_show(struct device *dev, \ int retval; \ \ udev = to_usb_device(dev); \ - usb_lock_device(udev); \ + retval = usb_lock_device_interruptible(udev); \ + if (retval < 0) \ + return -EINTR; \ retval = sprintf(buf, "%s\n", udev->name); \ usb_unlock_device(udev); \ return retval; \ @@ -227,11 +237,13 @@ static ssize_t avoid_reset_quirk_store(struct device *dev, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int val; + int val, rc; if (sscanf(buf, "%d", &val) != 1 || val < 0 || val > 1) return -EINVAL; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; if (val) udev->quirks |= USB_QUIRK_RESET; else @@ -297,7 +309,7 @@ static ssize_t persist_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int value; + int value, rc; /* Hubs are always enabled for USB_PERSIST */ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) @@ -306,7 +318,9 @@ static ssize_t persist_store(struct device *dev, struct device_attribute *attr, if (sscanf(buf, "%d", &value) != 1) return -EINVAL; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; udev->persist_enabled = !!value; usb_unlock_device(udev); return count; @@ -423,13 +437,16 @@ static ssize_t level_store(struct device *dev, struct device_attribute *attr, int len = count; char *cp; int rc = count; + int rv; warn_level(); cp = memchr(buf, '\n', count); if (cp) len = cp - buf; - usb_lock_device(udev); + rv = usb_lock_device_interruptible(udev); + if (rv < 0) + return -EINTR; if (len == sizeof on_string - 1 && strncmp(buf, on_string, len) == 0) @@ -469,7 +486,9 @@ static ssize_t usb2_hardware_lpm_store(struct device *dev, bool value; int ret; - usb_lock_device(udev); + ret = usb_lock_device_interruptible(udev); + if (ret < 0) + return -EINTR; ret = strtobool(buf, &value); @@ -539,8 +558,11 @@ static ssize_t usb3_hardware_lpm_u1_show(struct device *dev, { struct usb_device *udev = to_usb_device(dev); const char *p; + int rc; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; if (udev->usb3_lpm_u1_enabled) p = "enabled"; @@ -558,8 +580,11 @@ static ssize_t usb3_hardware_lpm_u2_show(struct device *dev, { struct usb_device *udev = to_usb_device(dev); const char *p; + int rc; - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; if (udev->usb3_lpm_u2_enabled) p = "enabled"; @@ -818,14 +843,16 @@ read_descriptors(struct file *filp, struct kobject *kobj, struct usb_device *udev = to_usb_device(dev); size_t nleft = count; size_t srclen, n; - int cfgno; + int cfgno, rc; void *src; /* The binary attribute begins with the device descriptor. * Following that are the raw descriptor entries for all the * configurations (config plus subsidiary descriptors). */ - usb_lock_device(udev); + rc = usb_lock_device_interruptible(udev); + if (rc < 0) + return -EINTR; for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations && nleft > 0; ++cfgno) { if (cfgno < 0) { @@ -972,7 +999,9 @@ static ssize_t supports_autosuspend_show(struct device *dev, { int s; - device_lock(dev); + s = device_lock_interruptible(dev); + if (s < 0) + return -EINTR; /* Devices will be autosuspended even when an interface isn't claimed */ s = (!dev->driver || to_usb_driver(dev->driver)->supports_autosuspend); device_unlock(dev); diff --git a/include/linux/device.h b/include/linux/device.h index 6d6f1fec092f..2d0e6e541d52 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -958,6 +958,11 @@ static inline void device_lock(struct device *dev) mutex_lock(&dev->mutex); } +static inline int device_lock_interruptible(struct device *dev) +{ + return mutex_lock_interruptible(&dev->mutex); +} + static inline int device_trylock(struct device *dev) { return mutex_trylock(&dev->mutex); diff --git a/include/linux/usb.h b/include/linux/usb.h index 0d348fa84a66..dc0ea0de8a81 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -641,9 +641,10 @@ extern struct usb_device *usb_hub_find_child(struct usb_device *hdev, if (!child) continue; else /* USB device locking */ -#define usb_lock_device(udev) device_lock(&(udev)->dev) -#define usb_unlock_device(udev) device_unlock(&(udev)->dev) -#define usb_trylock_device(udev) device_trylock(&(udev)->dev) +#define usb_lock_device(udev) device_lock(&(udev)->dev) +#define usb_unlock_device(udev) device_unlock(&(udev)->dev) +#define usb_lock_device_interruptible(udev) device_lock_interruptible(&(udev)->dev) +#define usb_trylock_device(udev) device_trylock(&(udev)->dev) extern int usb_lock_device_for_reset(struct usb_device *udev, const struct usb_interface *iface); -- cgit From b4a90d04ac79349799f65dfd7fa30b2aac6b2a4d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 21 Jan 2016 15:18:48 +0100 Subject: usb: no locking for reading descriptors in sysfs Quting the relevant thread: > In fact, I suspect the locking added by the kernel 3.13 commit for > read_descriptors() is invalid because read_descriptors() performs no USB > activity; read_descriptors() just reads information from an allocated > memory structure. This structure is protected as the structure is > existing before and after the sysfs vfs descriptors entry is created or > destroyed. You're right. For some reason I thought that usb_deauthorize_device() would destroy the rawdescriptor structures (as mentioned in that commit's Changelog), but it doesn't. The locking in read_descriptors() is unnecessary. > The information is only written at the time of enumeration > and does not change. At least that is my understanding. > > It is noted that in our testing of kernel 3.8 on ARM, that sysfs > read_descriptors() was non-blocking because the kernel 3.13 comment was > not there. > > The pre-kernel 3.13 sysfs read_descriptors() seemed to work OK. > > Proposal: > ========= > > Remove the usb_lock_device(udev) and usb_unlock_device(udev) from > devices/usb/core/sysfs.c in read_descriptors() that was added by the > kernel 3.13 commit > "232275a USB: fix substandard locking for the sysfs files" > > Any comments to this proposal ? It seems okay to me. Please submit a patch. So this removes the locking making the point about -EINTR in the first path moot. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/sysfs.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 7a6209314997..c953a0f1c695 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -843,16 +843,13 @@ read_descriptors(struct file *filp, struct kobject *kobj, struct usb_device *udev = to_usb_device(dev); size_t nleft = count; size_t srclen, n; - int cfgno, rc; + int cfgno; void *src; /* The binary attribute begins with the device descriptor. * Following that are the raw descriptor entries for all the * configurations (config plus subsidiary descriptors). */ - rc = usb_lock_device_interruptible(udev); - if (rc < 0) - return -EINTR; for (cfgno = -1; cfgno < udev->descriptor.bNumConfigurations && nleft > 0; ++cfgno) { if (cfgno < 0) { @@ -873,7 +870,6 @@ read_descriptors(struct file *filp, struct kobject *kobj, off -= srclen; } } - usb_unlock_device(udev); return count - nleft; } -- cgit From 1c17a353c5a8346b1ce128c60ffb862d156f7e7e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 25 Jan 2016 16:21:54 +0100 Subject: usb: gadget: rndis: fix itnull.cocci warnings The index variable of list_for_each_entry_safe is an offset from a list pointer, and thus should not be NULL. Generated by: scripts/coccinelle/iterators/itnull.cocci CC: Geliang Tang Signed-off-by: Fengguang Wu Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c index 34a76db2c8fd..943c21aafd3b 100644 --- a/drivers/usb/gadget/function/rndis.c +++ b/drivers/usb/gadget/function/rndis.c @@ -1009,7 +1009,7 @@ void rndis_free_response(struct rndis_params *params, u8 *buf) rndis_resp_t *r, *n; list_for_each_entry_safe(r, n, ¶ms->resp_queue, list) { - if (r && r->buf == buf) { + if (r->buf == buf) { list_del(&r->list); kfree(r); } -- cgit From b5566d074d163f052283ec5f5df643a023feebc0 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:44 -0300 Subject: usb: host: ehci.h: remove space before comma Get rid of spaces before comma. Caught by checkpatch: "ERROR: space prohibited before that ','" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index b13894550139..54a69d8b0abe 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -861,13 +861,13 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) /*-------------------------------------------------------------------------*/ #define ehci_dbg(ehci, fmt, args...) \ - dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_dbg(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #define ehci_err(ehci, fmt, args...) \ - dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_err(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #define ehci_info(ehci, fmt, args...) \ - dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_info(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #define ehci_warn(ehci, fmt, args...) \ - dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + dev_warn(ehci_to_hcd(ehci)->self.controller, fmt, ## args) #ifndef CONFIG_DYNAMIC_DEBUG -- cgit From e06e2264a3c9922c6f20c5ee020e9ba96b6917ab Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:45 -0300 Subject: usb: host: ehci.h: remove space before function open parenthesis Get rid of space between function name and open parenthesis. Caught by checkpatch: "WARNING: space prohibited between function name and open parenthesis '('" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 54a69d8b0abe..8d1943cbfc7a 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -271,13 +271,13 @@ struct ehci_hcd { /* one per controller */ }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ -static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd) +static inline struct ehci_hcd *hcd_to_ehci(struct usb_hcd *hcd) { return (struct ehci_hcd *) (hcd->hcd_priv); } -static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) +static inline struct usb_hcd *ehci_to_hcd(struct ehci_hcd *ehci) { - return container_of ((void *) ehci, struct usb_hcd, hcd_priv); + return container_of((void *) ehci, struct usb_hcd, hcd_priv); } /*-------------------------------------------------------------------------*/ @@ -330,9 +330,9 @@ struct ehci_qtd { } __attribute__ ((aligned (32))); /* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f) +#define QTD_MASK(ehci) cpu_to_hc32(ehci, ~0x1f) -#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) +#define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) /*-------------------------------------------------------------------------*/ @@ -815,7 +815,7 @@ static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) #define ehci_big_endian_desc(e) ((e)->big_endian_desc) /* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) +static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x) { return ehci_big_endian_desc(ehci) ? (__force __hc32)cpu_to_be32(x) @@ -823,14 +823,14 @@ static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) } /* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) +static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x) { return ehci_big_endian_desc(ehci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x); } -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) +static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) { return ehci_big_endian_desc(ehci) ? be32_to_cpup((__force __be32 *)x) @@ -840,18 +840,18 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) #else /* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) +static inline __hc32 cpu_to_hc32(const struct ehci_hcd *ehci, const u32 x) { return cpu_to_le32(x); } /* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) +static inline u32 hc32_to_cpu(const struct ehci_hcd *ehci, const __hc32 x) { return le32_to_cpu(x); } -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) +static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) { return le32_to_cpup(x); } -- cgit From 9dc3af5ed21fa7ec8ccd315a10b1f9a7771b244b Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:46 -0300 Subject: usb: host: ehci.h: remove space before open square bracket Get rid of space before open square bracket. Caught by checkpatch: "ERROR: space prohibited before open square bracket '['" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 8d1943cbfc7a..484ab1a09166 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -188,7 +188,7 @@ struct ehci_hcd { /* one per controller */ struct ehci_sitd *last_sitd_to_free; /* per root hub port */ - unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; + unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; /* bit vectors (one bit per port) */ unsigned long bus_suspended; /* which ports were @@ -319,8 +319,8 @@ struct ehci_qtd { #define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT) #define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS) - __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ - __hc32 hw_buf_hi [5]; /* Appendix B */ + __hc32 hw_buf[5]; /* see EHCI 3.5.4 */ + __hc32 hw_buf_hi[5]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t qtd_dma; /* qtd address */ @@ -408,8 +408,8 @@ struct ehci_qh_hw { __hc32 hw_qtd_next; __hc32 hw_alt_next; __hc32 hw_token; - __hc32 hw_buf [5]; - __hc32 hw_buf_hi [5]; + __hc32 hw_buf[5]; + __hc32 hw_buf_hi[5]; } __attribute__ ((aligned(32))); struct ehci_qh { @@ -471,7 +471,7 @@ struct ehci_iso_sched { struct list_head td_list; unsigned span; unsigned first_packet; - struct ehci_iso_packet packet [0]; + struct ehci_iso_packet packet[0]; }; /* @@ -519,7 +519,7 @@ struct ehci_iso_stream { struct ehci_itd { /* first part defined by EHCI spec */ __hc32 hw_next; /* see EHCI 3.3.1 */ - __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */ + __hc32 hw_transaction[8]; /* see EHCI 3.3.2 */ #define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ #define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ #define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ @@ -529,8 +529,8 @@ struct ehci_itd { #define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE) - __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */ - __hc32 hw_bufp_hi [7]; /* Appendix B */ + __hc32 hw_bufp[7]; /* see EHCI 3.3.3 */ + __hc32 hw_bufp_hi[7]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t itd_dma; /* for this itd */ @@ -574,9 +574,9 @@ struct ehci_sitd { #define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE) - __hc32 hw_buf [2]; /* EHCI table 3-12 */ + __hc32 hw_buf[2]; /* EHCI table 3-12 */ __hc32 hw_backpointer; /* EHCI table 3-13 */ - __hc32 hw_buf_hi [2]; /* Appendix B */ + __hc32 hw_buf_hi[2]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t sitd_dma; -- cgit From bc4beadabf53a26268b12c930557b364fd4e2b28 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:47 -0300 Subject: usb: host: ehci.h: fix single statement macros Don't use the 'do {} while (0)' wrapper in a single statement macro. Caught by checkpatch: "WARNING: Single statement macros should not use a do {} while (0) loop" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 484ab1a09166..06e20bc3ebb8 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -247,9 +247,9 @@ struct ehci_hcd { /* one per controller */ /* irq statistics */ #ifdef EHCI_STATS struct ehci_stats stats; -# define COUNT(x) do { (x)++; } while (0) +# define COUNT(x) ((x)++) #else -# define COUNT(x) do {} while (0) +# define COUNT(x) #endif /* debug files */ -- cgit From 3a9e742f3c2cc63167abe10ea8099861dde28085 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:48 -0300 Subject: usb: host: ehci.h: remove direct use of __attribute__ keyword Prefer to use __aligned(size) macro instead of __attribute__((aligned(size))). Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 06e20bc3ebb8..29b9617fd503 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -327,7 +327,7 @@ struct ehci_qtd { struct list_head qtd_list; /* sw qtd list */ struct urb *urb; /* qtd's urb */ size_t length; /* length of buffer */ -} __attribute__ ((aligned (32))); +} __aligned(32); /* mask NakCnt+T in qh->hw_alt_next */ #define QTD_MASK(ehci) cpu_to_hc32(ehci, ~0x1f) @@ -410,7 +410,7 @@ struct ehci_qh_hw { __hc32 hw_token; __hc32 hw_buf[5]; __hc32 hw_buf_hi[5]; -} __attribute__ ((aligned(32))); +} __aligned(32); struct ehci_qh { struct ehci_qh_hw *hw; /* Must come first */ @@ -544,7 +544,7 @@ struct ehci_itd { unsigned frame; /* where scheduled */ unsigned pg; unsigned index[8]; /* in urb->iso_frame_desc */ -} __attribute__ ((aligned (32))); +} __aligned(32); /*-------------------------------------------------------------------------*/ @@ -587,7 +587,7 @@ struct ehci_sitd { struct list_head sitd_list; /* list of stream's sitds */ unsigned frame; unsigned index; -} __attribute__ ((aligned (32))); +} __aligned(32); /*-------------------------------------------------------------------------*/ @@ -607,7 +607,7 @@ struct ehci_fstn { /* the rest is HCD-private */ dma_addr_t fstn_dma; union ehci_shadow fstn_next; /* ptr to periodic q entry */ -} __attribute__ ((aligned (32))); +} __aligned(32); /*-------------------------------------------------------------------------*/ -- cgit From 10f2b962e65d4ef346ecacbb28f768f273b2a060 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:49 -0300 Subject: usb: host: ehci.h: use space after comma Put space after comma. This patch also changes QH_NEXT macro for better reading. Caught by checkpatch: "ERROR: space required after that ','" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 29b9617fd503..bbed8750afb2 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -337,7 +337,7 @@ struct ehci_qtd { /*-------------------------------------------------------------------------*/ /* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(ehci,dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) +#define Q_NEXT_TYPE(ehci, dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) /* * Now the following defines are not converted using the @@ -353,7 +353,8 @@ struct ehci_qtd { #define Q_TYPE_FSTN (3 << 1) /* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(ehci,dma) (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH)) +#define QH_NEXT(ehci, dma) \ + (cpu_to_hc32(ehci, (((u32) dma) & ~0x01f) | Q_TYPE_QH)) /* for periodic/async schedules and qtd lists, mark end of list */ #define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */ -- cgit From 8af0219eea6387248f0d46b47742bb8c83b1b4f3 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:50 -0300 Subject: usb: host: ehci.h: remove macros trailing semicolon Removes trailing semicolon from macros. Caught by checkpatch: "WARNING: macros should not use a trailing semicolon" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bbed8750afb2..e587d4529e7a 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -644,10 +644,10 @@ struct ehci_tt { /* Prepare the PORTSC wakeup flags during controller suspend/resume */ #define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ - ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup); + ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup) #define ehci_prepare_ports_for_controller_resume(ehci) \ - ehci_adjust_port_wakeup_flags(ehci, false, false); + ehci_adjust_port_wakeup_flags(ehci, false, false) /*-------------------------------------------------------------------------*/ -- cgit From c021170f1da3448d398614b6bc546f3dee256979 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:51 -0300 Subject: usb: host: ehci.h: move pointer operator to name side The pointer operator must be sticked to name. Caught by checkpatch: ERROR: "foo * bar" should be "foo *bar" Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index e587d4529e7a..30bf43750c67 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -741,7 +741,7 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) #endif static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, - __u32 __iomem * regs) + __u32 __iomem *regs) { #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO return ehci_big_endian_mmio(ehci) ? -- cgit From 4510a072c60855d0e28000cbb3d7c718801023de Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:52 -0300 Subject: usb: host: ehci.h: move constant to right This patch moves the constant 0x3ff to right and put spaces in the right shift. Caught by coccinelle: scripts/coccinelle/misc/compare_const_fl.cocci Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 30bf43750c67..d1b29b36b347 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -564,7 +564,7 @@ struct ehci_sitd { __hc32 hw_results; /* EHCI table 3-11 */ #define SITD_IOC (1 << 31) /* interrupt on completion */ #define SITD_PAGE (1 << 30) /* buffer 0/1 */ -#define SITD_LENGTH(x) (0x3ff & ((x)>>16)) +#define SITD_LENGTH(x) (((x) >> 16) & 0x3ff) #define SITD_STS_ACTIVE (1 << 7) /* HC may execute this */ #define SITD_STS_ERR (1 << 6) /* error from TT */ #define SITD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -- cgit From 668ab0db27cbb4857d0f207d78bff2f96b537e13 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:53 -0300 Subject: usb: host: ehci-dbg: remove space before open parenthesis This patch fixes coding style issues reported by checkpatch. The vast majority of changes in this patch are removing spaces before opening parenthesis, but in some cases, a few additional changes are made to fix other coding style issues. These additional changes are: - Spaces around >> on line 50. - On line 55 a call to ehci_dbg reduced to a single line. - sizeof operands surrounded with parenthesis on lines 877, 883, 889 and 901. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 199 ++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 100 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index b7d623f1523c..fcbbdfa25766 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -24,41 +24,40 @@ * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value */ -static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) +static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) { u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci_dbg (ehci, + ehci_dbg(ehci, "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", label, params, - HCS_DEBUG_PORT (params), - HCS_INDICATOR (params) ? " ind" : "", - HCS_N_CC (params), - HCS_N_PCC (params), - HCS_PORTROUTED (params) ? "" : " ordered", - HCS_PPC (params) ? "" : " !ppc", - HCS_N_PORTS (params) + HCS_DEBUG_PORT(params), + HCS_INDICATOR(params) ? " ind" : "", + HCS_N_CC(params), + HCS_N_PCC(params), + HCS_PORTROUTED(params) ? "" : " ordered", + HCS_PPC(params) ? "" : " !ppc", + HCS_N_PORTS(params) ); /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ - if (HCS_PORTROUTED (params)) { + if (HCS_PORTROUTED(params)) { int i; char buf [46], tmp [7], byte; buf[0] = 0; - for (i = 0; i < HCS_N_PORTS (params); i++) { + for (i = 0; i < HCS_N_PORTS(params); i++) { // FIXME MIPS won't readb() ... - byte = readb (&ehci->caps->portroute[(i>>1)]); + byte = readb(&ehci->caps->portroute[(i >> 1)]); sprintf(tmp, "%d ", ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); strcat(buf, tmp); } - ehci_dbg (ehci, "%s portroute %s\n", - label, buf); + ehci_dbg(ehci, "%s portroute %s\n", label, buf); } } #else -static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} +static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label) {} #endif @@ -68,19 +67,19 @@ static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} * (host controller _Capability_ parameters) * see EHCI Spec, Table 2-5 for each value * */ -static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) +static void dbg_hcc_params(struct ehci_hcd *ehci, char *label) { u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); - if (HCC_ISOC_CACHE (params)) { - ehci_dbg (ehci, + if (HCC_ISOC_CACHE(params)) { + ehci_dbg(ehci, "%s hcc_params %04x caching frame %s%s%s\n", label, params, HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", HCC_CANPARK(params) ? " park" : "", HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); } else { - ehci_dbg (ehci, + ehci_dbg(ehci, "%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n", label, params, @@ -97,14 +96,14 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) } #else -static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} +static inline void dbg_hcc_params(struct ehci_hcd *ehci, char *label) {} #endif #ifdef CONFIG_DYNAMIC_DEBUG static void __maybe_unused -dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) +dbg_qtd(const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) { ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, hc32_to_cpup(ehci, &qtd->hw_next), @@ -120,22 +119,22 @@ dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) } static void __maybe_unused -dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) +dbg_qh(const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) { struct ehci_qh_hw *hw = qh->hw; - ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, + ehci_dbg(ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next); } static void __maybe_unused -dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) +dbg_itd(const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) { - ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", + ehci_dbg(ehci, "%s [%d] itd %p, next %08x, urb %p\n", label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), itd->urb); - ehci_dbg (ehci, + ehci_dbg(ehci, " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", hc32_to_cpu(ehci, itd->hw_transaction[0]), hc32_to_cpu(ehci, itd->hw_transaction[1]), @@ -145,7 +144,7 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) hc32_to_cpu(ehci, itd->hw_transaction[5]), hc32_to_cpu(ehci, itd->hw_transaction[6]), hc32_to_cpu(ehci, itd->hw_transaction[7])); - ehci_dbg (ehci, + ehci_dbg(ehci, " buf: %08x %08x %08x %08x %08x %08x %08x\n", hc32_to_cpu(ehci, itd->hw_bufp[0]), hc32_to_cpu(ehci, itd->hw_bufp[1]), @@ -154,19 +153,19 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) hc32_to_cpu(ehci, itd->hw_bufp[4]), hc32_to_cpu(ehci, itd->hw_bufp[5]), hc32_to_cpu(ehci, itd->hw_bufp[6])); - ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n", + ehci_dbg(ehci, " index: %d %d %d %d %d %d %d %d\n", itd->index[0], itd->index[1], itd->index[2], itd->index[3], itd->index[4], itd->index[5], itd->index[6], itd->index[7]); } static void __maybe_unused -dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) +dbg_sitd(const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) { - ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", + ehci_dbg(ehci, "%s [%d] sitd %p, next %08x, urb %p\n", label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), sitd->urb); - ehci_dbg (ehci, + ehci_dbg(ehci, " addr %08x sched %04x result %08x buf %08x %08x\n", hc32_to_cpu(ehci, sitd->hw_fullspeed_ep), hc32_to_cpu(ehci, sitd->hw_uframe), @@ -176,9 +175,9 @@ dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) } static int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) { - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", status, (status & STS_PPCE_MASK) ? " PPCE" : "", @@ -196,9 +195,9 @@ dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) } static int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) { - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s%s", label, label [0] ? " " : "", enable, (enable & STS_PPCE_MASK) ? " PPCE" : "", @@ -215,9 +214,9 @@ static const char *const fls_strings [] = { "1024", "512", "256", "??" }; static int -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) { - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " "period=%s%s %s", label, label [0] ? " " : "", command, @@ -227,7 +226,7 @@ dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) (command & CMD_ASPE) ? " ASPE" : "", (command & CMD_PSPE) ? " PSPE" : "", (command & CMD_PARK) ? " park" : "(park)", - CMD_PARK_CNT (command), + CMD_PARK_CNT(command), (command >> 16) & 0x3f, (command & CMD_LRESET) ? " LReset" : "", (command & CMD_IAAD) ? " IAAD" : "", @@ -240,7 +239,7 @@ dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) } static int -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) { char *sig; @@ -252,7 +251,7 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) default: sig = "?"; break; } - return scnprintf (buf, len, + return scnprintf(buf, len, "%s%sport:%d status %06x %d %s%s%s%s%s%s " "sig=%s%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", port, status, @@ -282,23 +281,23 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) #else static inline void __maybe_unused -dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) +dbg_qh(char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) {} static inline int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) +dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) { return 0; } static inline int __maybe_unused -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) +dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) { return 0; } static inline int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) +dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) { return 0; } static inline int __maybe_unused -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) +dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) { return 0; } #endif /* CONFIG_DYNAMIC_DEBUG */ @@ -326,8 +325,8 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) #ifdef STUB_DEBUG_FILES -static inline void create_debug_files (struct ehci_hcd *bus) { } -static inline void remove_debug_files (struct ehci_hcd *bus) { } +static inline void create_debug_files(struct ehci_hcd *bus) { } +static inline void remove_debug_files(struct ehci_hcd *bus) { } #else @@ -397,13 +396,13 @@ static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) return '*'; if (v & QTD_STS_HALT) return '-'; - if (!IS_SHORT_READ (v)) + if (!IS_SHORT_READ(v)) return ' '; /* tries to advance through hw_alt_next */ return '/'; } -static void qh_lines ( +static void qh_lines( struct ehci_hcd *ehci, struct ehci_qh *qh, char **nextp, @@ -435,7 +434,7 @@ static void qh_lines ( } scratch = hc32_to_cpup(ehci, &hw->hw_info1); hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0; - temp = scnprintf (next, size, + temp = scnprintf(next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)" " [cur %08x next %08x buf[0] %08x]", qh, scratch & 0x007f, @@ -453,21 +452,21 @@ static void qh_lines ( next += temp; /* hc may be modifying the list as we read it ... */ - list_for_each (entry, &qh->qtd_list) { - td = list_entry (entry, struct ehci_qtd, qtd_list); + list_for_each(entry, &qh->qtd_list) { + td = list_entry(entry, struct ehci_qtd, qtd_list); scratch = hc32_to_cpup(ehci, &td->hw_token); mark = ' '; if (hw_curr == td->qtd_dma) mark = '*'; else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) mark = '+'; - else if (QTD_LENGTH (scratch)) { + else if (QTD_LENGTH(scratch)) { if (td->hw_alt_next == ehci->async->hw->hw_alt_next) mark = '#'; else if (td->hw_alt_next != list_end) mark = '/'; } - temp = snprintf (next, size, + temp = snprintf(next, size, "\n\t%p%c%s len=%d %08x urb %p" " [td %08x buf[0] %08x]", td, mark, ({ char *tmp; @@ -490,7 +489,7 @@ static void qh_lines ( goto done; } - temp = snprintf (next, size, "\n"); + temp = snprintf(next, size, "\n"); if (size < temp) temp = size; size -= temp; @@ -511,7 +510,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) struct ehci_qh *qh; hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); + ehci = hcd_to_ehci(hcd); next = buf->output_buf; size = buf->alloc_size; @@ -521,9 +520,9 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) * usually empty except for long-term bulk reads, or head. * one QH per line, and TDs we know about */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) - qh_lines (ehci, qh, &next, &size); + qh_lines(ehci, qh, &next, &size); if (!list_empty(&ehci->async_unlink) && size > 0) { temp = scnprintf(next, size, "\nunlink =\n"); size -= temp; @@ -535,7 +534,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) qh_lines(ehci, qh, &next, &size); } } - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return strlen(buf->output_buf); } @@ -641,25 +640,25 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) seen_count = 0; hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); + ehci = hcd_to_ehci(hcd); next = buf->output_buf; size = buf->alloc_size; - temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); + temp = scnprintf(next, size, "size = %d\n", ehci->periodic_size); size -= temp; next += temp; /* dump a snapshot of the periodic schedule. * iso changes, interrupt usually doesn't. */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < ehci->periodic_size; i++) { p = ehci->pshadow [i]; - if (likely (!p.ptr)) + if (likely(!p.ptr)) continue; tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); - temp = scnprintf (next, size, "%4d: ", i); + temp = scnprintf(next, size, "%4d: ", i); size -= temp; next += temp; @@ -669,7 +668,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) switch (hc32_to_cpu(ehci, tag)) { case Q_TYPE_QH: hw = p.qh->hw; - temp = scnprintf (next, size, " qh%d-%04x/%p", + temp = scnprintf(next, size, " qh%d-%04x/%p", p.qh->ps.period, hc32_to_cpup(ehci, &hw->hw_info2) @@ -683,7 +682,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) if (seen [temp].ptr != p.ptr) continue; if (p.qh->qh_next.ptr) { - temp = scnprintf (next, size, + temp = scnprintf(next, size, " ..."); size -= temp; next += temp; @@ -699,7 +698,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) /* count tds, get ep direction */ temp = 0; - list_for_each_entry (qtd, + list_for_each_entry(qtd, &p.qh->qtd_list, qtd_list) { temp++; @@ -711,7 +710,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) } } - temp = scnprintf (next, size, + temp = scnprintf(next, size, " (%c%d ep%d%s " "[%d/%d] q%d p%d)", speed_char (scratch), @@ -730,20 +729,20 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) p = p.qh->qh_next; break; case Q_TYPE_FSTN: - temp = scnprintf (next, size, + temp = scnprintf(next, size, " fstn-%8x/%p", p.fstn->hw_prev, p.fstn); tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next); p = p.fstn->fstn_next; break; case Q_TYPE_ITD: - temp = scnprintf (next, size, + temp = scnprintf(next, size, " itd/%p", p.itd); tag = Q_NEXT_TYPE(ehci, p.itd->hw_next); p = p.itd->itd_next; break; case Q_TYPE_SITD: - temp = scnprintf (next, size, + temp = scnprintf(next, size, " sitd%d-%04x/%p", p.sitd->stream->ps.period, hc32_to_cpup(ehci, &p.sitd->hw_uframe) @@ -757,12 +756,12 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) next += temp; } while (p.ptr); - temp = scnprintf (next, size, "\n"); + temp = scnprintf(next, size, "\n"); size -= temp; next += temp; } - spin_unlock_irqrestore (&ehci->lock, flags); - kfree (seen); + spin_unlock_irqrestore(&ehci->lock, flags); + kfree(seen); return buf->alloc_size - size; } @@ -794,14 +793,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) static char label [] = ""; hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); + ehci = hcd_to_ehci(hcd); next = buf->output_buf; size = buf->alloc_size; - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { - size = scnprintf (next, size, + size = scnprintf(next, size, "bus %s, device %s\n" "%s\n" "SUSPENDED (no register access)\n", @@ -813,7 +812,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) /* Capability Registers */ i = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - temp = scnprintf (next, size, + temp = scnprintf(next, size, "bus %s, device %s\n" "%s\n" "EHCI %x.%02x, rh state %s\n", @@ -835,10 +834,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) offset = HCC_EXT_CAPS(ehci_readl(ehci, &ehci->caps->hcc_params)); while (offset && count--) { - pci_read_config_dword (pdev, offset, &cap); + pci_read_config_dword(pdev, offset, &cap); switch (cap & 0xff) { case 1: - temp = scnprintf (next, size, + temp = scnprintf(next, size, "ownership %08x%s%s\n", cap, (cap & (1 << 24)) ? " linux" : "", (cap & (1 << 16)) ? " firmware" : ""); @@ -846,8 +845,8 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) next += temp; offset += 4; - pci_read_config_dword (pdev, offset, &cap2); - temp = scnprintf (next, size, + pci_read_config_dword(pdev, offset, &cap2); + temp = scnprintf(next, size, "SMI sts/enable 0x%08x\n", cap2); size -= temp; next += temp; @@ -865,48 +864,48 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) // FIXME interpret both types of params i = ehci_readl(ehci, &ehci->caps->hcs_params); - temp = scnprintf (next, size, "structural params 0x%08x\n", i); + temp = scnprintf(next, size, "structural params 0x%08x\n", i); size -= temp; next += temp; i = ehci_readl(ehci, &ehci->caps->hcc_params); - temp = scnprintf (next, size, "capability params 0x%08x\n", i); + temp = scnprintf(next, size, "capability params 0x%08x\n", i); size -= temp; next += temp; /* Operational Registers */ - temp = dbg_status_buf (scratch, sizeof scratch, label, + temp = dbg_status_buf(scratch, sizeof(scratch), label, ehci_readl(ehci, &ehci->regs->status)); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = dbg_command_buf (scratch, sizeof scratch, label, + temp = dbg_command_buf(scratch, sizeof(scratch), label, ehci_readl(ehci, &ehci->regs->command)); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = dbg_intr_buf (scratch, sizeof scratch, label, + temp = dbg_intr_buf(scratch, sizeof(scratch), label, ehci_readl(ehci, &ehci->regs->intr_enable)); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = scnprintf (next, size, "uframe %04x\n", + temp = scnprintf(next, size, "uframe %04x\n", ehci_read_frame_index(ehci)); size -= temp; next += temp; - for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { - temp = dbg_port_buf (scratch, sizeof scratch, label, i, + for (i = 1; i <= HCS_N_PORTS(ehci->hcs_params); i++) { + temp = dbg_port_buf(scratch, sizeof(scratch), label, i, ehci_readl(ehci, &ehci->regs->port_status[i - 1])); - temp = scnprintf (next, size, fmt, temp, scratch); + temp = scnprintf(next, size, fmt, temp, scratch); size -= temp; next += temp; if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { - temp = scnprintf (next, size, + temp = scnprintf(next, size, " debug control %08x\n", ehci_readl(ehci, &ehci->debug->control)); @@ -924,21 +923,21 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) } #ifdef EHCI_STATS - temp = scnprintf (next, size, + temp = scnprintf(next, size, "irq normal %ld err %ld iaa %ld (lost %ld)\n", ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, ehci->stats.lost_iaa); size -= temp; next += temp; - temp = scnprintf (next, size, "complete %ld unlink %ld\n", + temp = scnprintf(next, size, "complete %ld unlink %ld\n", ehci->stats.complete, ehci->stats.unlink); size -= temp; next += temp; #endif done: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return buf->alloc_size - size; } @@ -1054,7 +1053,7 @@ static int debug_registers_open(struct inode *inode, struct file *file) return file->private_data ? 0 : -ENOMEM; } -static inline void create_debug_files (struct ehci_hcd *ehci) +static inline void create_debug_files(struct ehci_hcd *ehci) { struct usb_bus *bus = &ehci_to_hcd(ehci)->self; @@ -1084,7 +1083,7 @@ file_error: debugfs_remove_recursive(ehci->debug_dir); } -static inline void remove_debug_files (struct ehci_hcd *ehci) +static inline void remove_debug_files(struct ehci_hcd *ehci) { debugfs_remove_recursive(ehci->debug_dir); } -- cgit From 1cb1d1c0d0de5c69937ed781211da8abcf03112f Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:54 -0300 Subject: usb: host: ehci-dbg: remove space before open square bracket This patch fixes coding style issues reported by checkpatch. The only change in this patch that isn't just removing spaces before opening square brackets is at line 213 where the initialization of fls_strings[] is placed in same line. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index fcbbdfa25766..52bf3fe2a965 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -42,7 +42,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ if (HCS_PORTROUTED(params)) { int i; - char buf [46], tmp [7], byte; + char buf[46], tmp[7], byte; buf[0] = 0; for (i = 0; i < HCS_N_PORTS(params); i++) { @@ -109,8 +109,8 @@ dbg_qtd(const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) hc32_to_cpup(ehci, &qtd->hw_next), hc32_to_cpup(ehci, &qtd->hw_alt_next), hc32_to_cpup(ehci, &qtd->hw_token), - hc32_to_cpup(ehci, &qtd->hw_buf [0])); - if (qtd->hw_buf [1]) + hc32_to_cpup(ehci, &qtd->hw_buf[0])); + if (qtd->hw_buf[1]) ehci_dbg(ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", hc32_to_cpup(ehci, &qtd->hw_buf[1]), hc32_to_cpup(ehci, &qtd->hw_buf[2]), @@ -179,7 +179,7 @@ dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) { return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", status, + label, label[0] ? " " : "", status, (status & STS_PPCE_MASK) ? " PPCE" : "", (status & STS_ASS) ? " Async" : "", (status & STS_PSS) ? " Periodic" : "", @@ -199,7 +199,7 @@ dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) { return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s%s", - label, label [0] ? " " : "", enable, + label, label[0] ? " " : "", enable, (enable & STS_PPCE_MASK) ? " PPCE" : "", (enable & STS_IAA) ? " IAA" : "", (enable & STS_FATAL) ? " FATAL" : "", @@ -210,8 +210,7 @@ dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) ); } -static const char *const fls_strings [] = - { "1024", "512", "256", "??" }; +static const char *const fls_strings[] = { "1024", "512", "256", "??" }; static int dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) @@ -219,7 +218,7 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) return scnprintf(buf, len, "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " "period=%s%s %s", - label, label [0] ? " " : "", command, + label, label[0] ? " " : "", command, (command & CMD_HIRD) ? " HIRD" : "", (command & CMD_PPCEE) ? " PPCEE" : "", (command & CMD_FSP) ? " FSP" : "", @@ -232,7 +231,7 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) (command & CMD_IAAD) ? " IAAD" : "", (command & CMD_ASE) ? " Async" : "", (command & CMD_PSE) ? " Periodic" : "", - fls_strings [(command >> 2) & 0x3], + fls_strings[(command >> 2) & 0x3], (command & CMD_RESET) ? " Reset" : "", (command & CMD_RUN) ? "RUN" : "HALT" ); @@ -254,7 +253,7 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) return scnprintf(buf, len, "%s%sport:%d status %06x %d %s%s%s%s%s%s " "sig=%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", port, status, + label, label[0] ? " " : "", port, status, status>>25,/*device address */ (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? " ACK" : "", @@ -653,10 +652,10 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) */ spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < ehci->periodic_size; i++) { - p = ehci->pshadow [i]; + p = ehci->pshadow[i]; if (likely(!p.ptr)) continue; - tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); + tag = Q_NEXT_TYPE(ehci, ehci->periodic[i]); temp = scnprintf(next, size, "%4d: ", i); size -= temp; @@ -679,7 +678,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) next += temp; /* don't repeat what follows this qh */ for (temp = 0; temp < seen_count; temp++) { - if (seen [temp].ptr != p.ptr) + if (seen[temp].ptr != p.ptr) continue; if (p.qh->qh_next.ptr) { temp = scnprintf(next, size, @@ -722,7 +721,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) 0x7ff & (scratch >> 16)); if (seen_count < DBG_SCHED_LIMIT) - seen [seen_count++].qh = p.qh; + seen[seen_count++].qh = p.qh; } else temp = 0; tag = Q_NEXT_TYPE(ehci, hw->hw_next); @@ -788,9 +787,9 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) struct ehci_hcd *ehci; unsigned long flags; unsigned temp, size, i; - char *next, scratch [80]; - static char fmt [] = "%*s\n"; - static char label [] = ""; + char *next, scratch[80]; + static char fmt[] = "%*s\n"; + static char label[] = ""; hcd = bus_to_hcd(buf->bus); ehci = hcd_to_ehci(hcd); -- cgit From 0784b4d5a2a691394c1d4034d4879ac428365383 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:55 -0300 Subject: usb: host: ehci-dbg: use C89-style comments This patch fixes coding style issues reported by checkpatch. Coding style demands usage of C89-style comments and a specific format when it's multiline. This also removes the Free Software Foundation address because FSF can change it again. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 52bf3fe2a965..df9f5986696f 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -11,16 +11,14 @@ * 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. */ /* this file is part of ehci-hcd.c */ #ifdef CONFIG_DYNAMIC_DEBUG -/* check the values in the HCSPARAMS register +/* + * check the values in the HCSPARAMS register * (host controller _Structural_ parameters) * see EHCI spec, Table 2-4 for each value */ @@ -46,7 +44,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) buf[0] = 0; for (i = 0; i < HCS_N_PORTS(params); i++) { - // FIXME MIPS won't readb() ... + /* FIXME MIPS won't readb() ... */ byte = readb(&ehci->caps->portroute[(i >> 1)]); sprintf(tmp, "%d ", ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); @@ -63,10 +61,11 @@ static inline void dbg_hcs_params(struct ehci_hcd *ehci, char *label) {} #ifdef CONFIG_DYNAMIC_DEBUG -/* check the values in the HCCPARAMS register +/* + * check the values in the HCCPARAMS register * (host controller _Capability_ parameters) * see EHCI Spec, Table 2-5 for each value - * */ + */ static void dbg_hcc_params(struct ehci_hcd *ehci, char *label) { u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); @@ -515,7 +514,8 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf) *next = 0; - /* dumps a snapshot of the async schedule. + /* + * dumps a snapshot of the async schedule. * usually empty except for long-term bulk reads, or head. * one QH per line, and TDs we know about */ @@ -647,7 +647,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) size -= temp; next += temp; - /* dump a snapshot of the periodic schedule. + /* + * dump a snapshot of the periodic schedule. * iso changes, interrupt usually doesn't. */ spin_lock_irqsave(&ehci->lock, flags); @@ -861,7 +862,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) } #endif - // FIXME interpret both types of params + /* FIXME interpret both types of params */ i = ehci_readl(ehci, &ehci->caps->hcs_params); temp = scnprintf(next, size, "structural params 0x%08x\n", i); size -= temp; -- cgit From 5bb95ec8d74a99bdf69fd1cf28c340fd680effce Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:56 -0300 Subject: usb: host: ehci-dbg: move trailing statements to next line This patch fixes coding style issues reported by checkpatch concerning to switch case statements. There are few additional changes made to fix other coding styles issues. These additional changes are: - The compound statement "({...})" on line 474 is pulled out from snprintf parameters. - On line 723 the constant "0x03" is moved to right. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 54 +++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index df9f5986696f..c409e4ff9d95 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -243,10 +243,18 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) /* signaling state */ switch (status & (3 << 10)) { - case 0 << 10: sig = "se0"; break; - case 1 << 10: sig = "k"; break; /* low speed */ - case 2 << 10: sig = "j"; break; - default: sig = "?"; break; + case 0 << 10: + sig = "se0"; + break; + case 1 << 10: /* low speed */ + sig = "k"; + break; + case 2 << 10: + sig = "j"; + break; + default: + sig = "?"; + break; } return scnprintf(buf, len, @@ -451,6 +459,8 @@ static void qh_lines( /* hc may be modifying the list as we read it ... */ list_for_each(entry, &qh->qtd_list) { + char *type; + td = list_entry(entry, struct ehci_qtd, qtd_list); scratch = hc32_to_cpup(ehci, &td->hw_token); mark = ' '; @@ -464,16 +474,24 @@ static void qh_lines( else if (td->hw_alt_next != list_end) mark = '/'; } + switch ((scratch >> 8) & 0x03) { + case 0: + type = "out"; + break; + case 1: + type = "in"; + break; + case 2: + type = "setup"; + break; + default: + type = "?"; + break; + } temp = snprintf(next, size, "\n\t%p%c%s len=%d %08x urb %p" " [td %08x buf[0] %08x]", - td, mark, ({ char *tmp; - switch ((scratch>>8)&0x03) { - case 0: tmp = "out"; break; - case 1: tmp = "in"; break; - case 2: tmp = "setup"; break; - default: tmp = "?"; break; - } tmp;}), + td, mark, type, (scratch >> 16) & 0x7fff, scratch, td->urb, @@ -702,11 +720,15 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) &p.qh->qtd_list, qtd_list) { temp++; - switch (0x03 & (hc32_to_cpu( - ehci, - qtd->hw_token) >> 8)) { - case 0: type = "out"; continue; - case 1: type = "in"; continue; + switch ((hc32_to_cpu(ehci, + qtd->hw_token) >> 8) + & 0x03) { + case 0: + type = "out"; + continue; + case 1: + type = "in"; + continue; } } -- cgit From 78698d66a1a7747b02e73e427d503c1426b8cd32 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:57 -0300 Subject: usb: host: ehci-dbg: fix up closing parenthesis This patch puts the closing parenthesis at the statement end removing unnecessary "new line". Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index c409e4ff9d95..3b423e122423 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -35,8 +35,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) HCS_N_PCC(params), HCS_PORTROUTED(params) ? "" : " ordered", HCS_PPC(params) ? "" : " !ppc", - HCS_N_PORTS(params) - ); + HCS_N_PORTS(params)); /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ if (HCS_PORTROUTED(params)) { int i; @@ -189,8 +188,7 @@ dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) (status & STS_FLR) ? " FLR" : "", (status & STS_PCD) ? " PCD" : "", (status & STS_ERR) ? " ERR" : "", - (status & STS_INT) ? " INT" : "" - ); + (status & STS_INT) ? " INT" : ""); } static int __maybe_unused @@ -205,8 +203,7 @@ dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) (enable & STS_FLR) ? " FLR" : "", (enable & STS_PCD) ? " PCD" : "", (enable & STS_ERR) ? " ERR" : "", - (enable & STS_INT) ? " INT" : "" - ); + (enable & STS_INT) ? " INT" : ""); } static const char *const fls_strings[] = { "1024", "512", "256", "??" }; @@ -232,8 +229,7 @@ dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) (command & CMD_PSE) ? " Periodic" : "", fls_strings[(command >> 2) & 0x3], (command & CMD_RESET) ? " Reset" : "", - (command & CMD_RUN) ? "RUN" : "HALT" - ); + (command & CMD_RUN) ? "RUN" : "HALT"); } static int -- cgit From c2fb017104eaceb3245640d2bec988d8751552bc Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:58 -0300 Subject: usb: host: ehci-dbg: put spaces around operators This patch fixes coding style issues reported by checkpatch concerning to missing spaces around operators. There is an additional change on line 49 that removes unnecessary parentheses around ternary operands. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 3b423e122423..980ca55f466a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -46,7 +46,7 @@ static void dbg_hcs_params(struct ehci_hcd *ehci, char *label) /* FIXME MIPS won't readb() ... */ byte = readb(&ehci->caps->portroute[(i >> 1)]); sprintf(tmp, "%d ", - ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); + (i & 0x1) ? byte & 0xf : (byte >> 4) & 0xf); strcat(buf, tmp); } ehci_dbg(ehci, "%s portroute %s\n", label, buf); @@ -257,14 +257,14 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) "%s%sport:%d status %06x %d %s%s%s%s%s%s " "sig=%s%s%s%s%s%s%s%s%s%s%s", label, label[0] ? " " : "", port, status, - status>>25,/*device address */ - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? + status >> 25, /*device address */ + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_ACK ? " ACK" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ? + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_NYET ? " NYET" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ? + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_STALL ? " STALL" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ? + (status & PORT_SSTS) >> 23 == PORTSC_SUSPEND_STS_ERR ? " ERR" : "", (status & PORT_POWER) ? " POWER" : "", (status & PORT_OWNER) ? " OWNER" : "", @@ -846,7 +846,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) if (dev_is_pci(hcd->self.controller)) { struct pci_dev *pdev; u32 offset, cap, cap2; - unsigned count = 256/4; + unsigned count = 256 / 4; pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); offset = HCC_EXT_CAPS(ehci_readl(ehci, @@ -1058,7 +1058,7 @@ static int debug_periodic_open(struct inode *inode, struct file *file) if (!buf) return -ENOMEM; - buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; + buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8) * PAGE_SIZE; file->private_data = buf; return 0; } -- cgit From a5355977947dc4da93ac05a72989fecc95bc6dca Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:44:59 -0300 Subject: usb: host: ehci-dbg: use scnprintf() in qh_lines() This patch replaces two snprintf() calls with scnprintf() in qh_lines() and hence removes the unneeded sequential truncation tests. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 980ca55f466a..97a0582849b4 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -484,7 +484,7 @@ static void qh_lines( type = "?"; break; } - temp = snprintf(next, size, + temp = scnprintf(next, size, "\n\t%p%c%s len=%d %08x urb %p" " [td %08x buf[0] %08x]", td, mark, type, @@ -493,17 +493,13 @@ static void qh_lines( td->urb, (u32) td->qtd_dma, hc32_to_cpup(ehci, &td->hw_buf[0])); - if (size < temp) - temp = size; size -= temp; next += temp; if (temp == size) goto done; } - temp = snprintf(next, size, "\n"); - if (size < temp) - temp = size; + temp = scnprintf(next, size, "\n"); size -= temp; next += temp; -- cgit From c768ffb891df375bc111515047fa56521401bab3 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:00 -0300 Subject: usb: host: ehci-dbg: fix up function definitions This patch indents not empty functions to have the opening brace at the beginning of the next line and body conforming coding style. This also makes the function definition consistent with the file coding style aligning parameters in sequential lines and indenting them with two tabs. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 97a0582849b4..44ca22639841 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -288,19 +288,27 @@ dbg_qh(char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) static inline int __maybe_unused dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) -{ return 0; } +{ + return 0; +} static inline int __maybe_unused dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) -{ return 0; } +{ + return 0; +} static inline int __maybe_unused dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } +{ + return 0; +} static inline int __maybe_unused dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } +{ + return 0; +} #endif /* CONFIG_DYNAMIC_DEBUG */ @@ -404,12 +412,8 @@ static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) return '/'; } -static void qh_lines( - struct ehci_hcd *ehci, - struct ehci_qh *qh, - char **nextp, - unsigned *sizep -) +static void qh_lines(struct ehci_hcd *ehci, struct ehci_qh *qh, + char **nextp, unsigned *sizep) { u32 scratch; u32 hw_curr; @@ -957,7 +961,7 @@ done: } static struct debug_buffer *alloc_buffer(struct usb_bus *bus, - ssize_t (*fill_func)(struct debug_buffer *)) + ssize_t (*fill_func)(struct debug_buffer *)) { struct debug_buffer *buf; @@ -997,7 +1001,7 @@ out: } static ssize_t debug_output(struct file *file, char __user *user_buf, - size_t len, loff_t *offset) + size_t len, loff_t *offset) { struct debug_buffer *buf = file->private_data; int ret = 0; -- cgit From e1666317d8c543b80cedacece72ebb17d80e2994 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:01 -0300 Subject: usb: host: ehci-dbg: use a blank line after struct declarations This patch fixes coding style issues reported by checkpatch concerning to missing line after struct declarations. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 44ca22639841..7e070144ec69 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -357,6 +357,7 @@ static const struct file_operations debug_async_fops = { .release = debug_close, .llseek = default_llseek, }; + static const struct file_operations debug_bandwidth_fops = { .owner = THIS_MODULE, .open = debug_bandwidth_open, @@ -364,6 +365,7 @@ static const struct file_operations debug_bandwidth_fops = { .release = debug_close, .llseek = default_llseek, }; + static const struct file_operations debug_periodic_fops = { .owner = THIS_MODULE, .open = debug_periodic_open, @@ -371,6 +373,7 @@ static const struct file_operations debug_periodic_fops = { .release = debug_close, .llseek = default_llseek, }; + static const struct file_operations debug_registers_fops = { .owner = THIS_MODULE, .open = debug_registers_open, -- cgit From 1f8e5afdb28510eda75700e5c12af03550c10a8d Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:02 -0300 Subject: usb: host: ehci-dbg: convert macro to inline function This patch converts macros into inline functions since the usage of second is encouraged by Coding Style instead of the first. Macros converted to functions: - dbg_status - dbg_cmd - dbg_port - speed_char The size after changes remains the same. Before: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o After: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 54 ++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 7e070144ec69..9efb2d1ca036 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -312,23 +312,31 @@ dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) #endif /* CONFIG_DYNAMIC_DEBUG */ -/* functions have the "wrong" filename when they're output... */ -#define dbg_status(ehci, label, status) { \ - char _buf [80]; \ - dbg_status_buf (_buf, sizeof _buf, label, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ +static inline void +dbg_status(struct ehci_hcd *ehci, const char *label, u32 status) +{ + char buf[80]; + + dbg_status_buf(buf, sizeof(buf), label, status); + ehci_dbg(ehci, "%s\n", buf); } -#define dbg_cmd(ehci, label, command) { \ - char _buf [80]; \ - dbg_command_buf (_buf, sizeof _buf, label, command); \ - ehci_dbg (ehci, "%s\n", _buf); \ +static inline void +dbg_cmd(struct ehci_hcd *ehci, const char *label, u32 command) +{ + char buf[80]; + + dbg_command_buf(buf, sizeof(buf), label, command); + ehci_dbg(ehci, "%s\n", buf); } -#define dbg_port(ehci, label, port, status) { \ - char _buf [80]; \ - dbg_port_buf (_buf, sizeof _buf, label, port, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ +static inline void +dbg_port(struct ehci_hcd *ehci, const char *label, int port, u32 status) +{ + char buf[80]; + + dbg_port_buf(buf, sizeof(buf), label, port, status); + ehci_dbg(ehci, "%s\n", buf); } /*-------------------------------------------------------------------------*/ @@ -393,13 +401,19 @@ struct debug_buffer { size_t alloc_size; }; -#define speed_char(info1) ({ char tmp; \ - switch (info1 & (3 << 12)) { \ - case QH_FULL_SPEED: tmp = 'f'; break; \ - case QH_LOW_SPEED: tmp = 'l'; break; \ - case QH_HIGH_SPEED: tmp = 'h'; break; \ - default: tmp = '?'; break; \ - } tmp; }) +static inline char speed_char(u32 info1) +{ + switch (info1 & (3 << 12)) { + case QH_FULL_SPEED: + return 'f'; + case QH_LOW_SPEED: + return 'l'; + case QH_HIGH_SPEED: + return 'h'; + default: + return '?'; + } +} static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) { -- cgit From 8d587d64955c42167e6fd413560452d064cd02d1 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:03 -0300 Subject: usb: host: ehci-dbg: add blank line after declarations This patch fixes coding style issues reported by checkpatch concerning to missing line after variable declarations. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 9efb2d1ca036..8c55d9a4be83 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -1071,6 +1071,7 @@ static int debug_bandwidth_open(struct inode *inode, struct file *file) static int debug_periodic_open(struct inode *inode, struct file *file) { struct debug_buffer *buf; + buf = alloc_buffer(inode->i_private, fill_periodic_buffer); if (!buf) return -ENOMEM; -- cgit From e2432f06b5669538f79d64d18e60b2c8c05d59f2 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:04 -0300 Subject: usb: host: ehci-dbg: remove blank line before close brace This patch fixes coding style issue reported by checkpatch concerning to an unnecessary line before close brace. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 8c55d9a4be83..37dac751bac5 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -1038,7 +1038,6 @@ static ssize_t debug_output(struct file *file, char __user *user_buf, out: return ret; - } static int debug_close(struct inode *inode, struct file *file) -- cgit From 12ef7dd97c3302c6c308484ffce392ef2383783a Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:05 -0300 Subject: usb: host: ehci-dbg: replace sizeof operand This patch fixes a coding style issue reported by checkpatch concerning to usage of sizeof operand as a variable instead the type. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 37dac751bac5..22e6d4c4548a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -982,7 +982,7 @@ static struct debug_buffer *alloc_buffer(struct usb_bus *bus, { struct debug_buffer *buf; - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + buf = kzalloc(sizeof(*buf), GFP_KERNEL); if (buf) { buf->bus = bus; -- cgit From 04b8ad436848b11ef6cc54589bd96cacd69fa6e7 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:06 -0300 Subject: usb: host: ehci-dbg: enclose conditional blocks with braces This patch fixes coding style issues reported by checkpatch concerning to conditional blocks without braces. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 22e6d4c4548a..760b1d6e429f 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -481,11 +481,11 @@ static void qh_lines(struct ehci_hcd *ehci, struct ehci_qh *qh, td = list_entry(entry, struct ehci_qtd, qtd_list); scratch = hc32_to_cpup(ehci, &td->hw_token); mark = ' '; - if (hw_curr == td->qtd_dma) + if (hw_curr == td->qtd_dma) { mark = '*'; - else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) + } else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) { mark = '+'; - else if (QTD_LENGTH(scratch)) { + } else if (QTD_LENGTH(scratch)) { if (td->hw_alt_next == ehci->async->hw->hw_alt_next) mark = '#'; else if (td->hw_alt_next != list_end) @@ -758,8 +758,9 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) if (seen_count < DBG_SCHED_LIMIT) seen[seen_count++].qh = p.qh; - } else + } else { temp = 0; + } tag = Q_NEXT_TYPE(ehci, hw->hw_next); p = p.qh->qh_next; break; -- cgit From cb272521760a604924162487a6b73ff5531a5648 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:07 -0300 Subject: usb: host: ehci-dbg: prefer kmalloc_array over kmalloc times size This patch fixes a coding style issue reported by checkpatch related to kmalloc_array usage. On the same line the sizeof operand was enclosed in parentheses. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 760b1d6e429f..da4133492a5f 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -664,7 +664,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) unsigned i; __hc32 tag; - seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC); + seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC); if (!seen) return 0; seen_count = 0; -- cgit From 3fd29009f87ba49bcbba516a31f5cf582c4ba613 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:08 -0300 Subject: usb: host: ehci-dbg: add function output_buf_tds_dir() This patch fixes a coding style issue reported by checkpatch related to too many leading tabs. This moves part of the fill_periodic_buffer() to the new function output_buf_tds_dir(). Because it's inline, the file size has not changed. Before: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o After: text data bss dec hex filename 36920 81 12 37013 9095 drivers/usb/host/ehci-hcd.o Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 62 +++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index da4133492a5f..d2c0711d13e8 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -652,6 +652,33 @@ static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf) return next - buf->output_buf; } +static unsigned output_buf_tds_dir(char *buf, struct ehci_hcd *ehci, + struct ehci_qh_hw *hw, struct ehci_qh *qh, unsigned size) +{ + u32 scratch = hc32_to_cpup(ehci, &hw->hw_info1); + struct ehci_qtd *qtd; + char *type = ""; + unsigned temp = 0; + + /* count tds, get ep direction */ + list_for_each_entry(qtd, &qh->qtd_list, qtd_list) { + temp++; + switch ((hc32_to_cpu(ehci, qtd->hw_token) >> 8) & 0x03) { + case 0: + type = "out"; + continue; + case 1: + type = "in"; + continue; + } + } + + return scnprintf(buf, size, " (%c%d ep%d%s [%d/%d] q%d p%d)", + speed_char(scratch), scratch & 0x007f, + (scratch >> 8) & 0x000f, type, qh->ps.usecs, + qh->ps.c_usecs, temp, 0x7ff & (scratch >> 16)); +} + #define DBG_SCHED_LIMIT 64 static ssize_t fill_periodic_buffer(struct debug_buffer *buf) { @@ -722,39 +749,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) } /* show more info the first time around */ if (temp == seen_count) { - u32 scratch = hc32_to_cpup(ehci, - &hw->hw_info1); - struct ehci_qtd *qtd; - char *type = ""; - - /* count tds, get ep direction */ - temp = 0; - list_for_each_entry(qtd, - &p.qh->qtd_list, - qtd_list) { - temp++; - switch ((hc32_to_cpu(ehci, - qtd->hw_token) >> 8) - & 0x03) { - case 0: - type = "out"; - continue; - case 1: - type = "in"; - continue; - } - } - - temp = scnprintf(next, size, - " (%c%d ep%d%s " - "[%d/%d] q%d p%d)", - speed_char (scratch), - scratch & 0x007f, - (scratch >> 8) & 0x000f, type, - p.qh->ps.usecs, - p.qh->ps.c_usecs, - temp, - 0x7ff & (scratch >> 16)); + temp = output_buf_tds_dir(next, ehci, + hw, p.qh, size); if (seen_count < DBG_SCHED_LIMIT) seen[seen_count++].qh = p.qh; -- cgit From 93df42ba1b4fe5bc3157e4fbd15baf11b2129217 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:09 -0300 Subject: usb: ehci: remove old stub_debug_files definition This patch removes the local STUB_DEBUG_FILES debugging definition. STUB_DEBUG_FILES was used only in ehci-hcd, whereas CONFIG_DYNAMIC_DEBUG is used all over the kernel. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 4 ++-- drivers/usb/host/ehci.h | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index d2c0711d13e8..79d12b2ba3c4 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -341,7 +341,7 @@ dbg_port(struct ehci_hcd *ehci, const char *label, int port, u32 status) /*-------------------------------------------------------------------------*/ -#ifdef STUB_DEBUG_FILES +#ifndef CONFIG_DYNAMIC_DEBUG static inline void create_debug_files(struct ehci_hcd *bus) { } static inline void remove_debug_files(struct ehci_hcd *bus) { } @@ -1120,4 +1120,4 @@ static inline void remove_debug_files(struct ehci_hcd *ehci) debugfs_remove_recursive(ehci->debug_dir); } -#endif /* STUB_DEBUG_FILES */ +#endif /* CONFIG_DYNAMIC_DEBUG */ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index d1b29b36b347..2ddf35203c05 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -870,11 +870,6 @@ static inline u32 hc32_to_cpup(const struct ehci_hcd *ehci, const __hc32 *x) #define ehci_warn(ehci, fmt, args...) \ dev_warn(ehci_to_hcd(ehci)->self.controller, fmt, ## args) - -#ifndef CONFIG_DYNAMIC_DEBUG -#define STUB_DEBUG_FILES -#endif - /*-------------------------------------------------------------------------*/ /* Declarations of things exported for use by ehci platform drivers */ -- cgit From 3f122a997eddd518ac480e658ab034cbc98deabe Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:10 -0300 Subject: usb: host: ehci-sched: refactor scan_isoc function This patch removes an infinite 'for' loop and makes use of the already existing 'restart' tag instead, reducing one leading tab. The comments and code were corrected conforming file coding style. Tested by compilation only. Caught by checkpatch: WARNING: Too many leading tabs - consider code refactoring Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 202 +++++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 101 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index c1704a57e803..74c2023763ad 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -2379,9 +2379,11 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, static void scan_isoc(struct ehci_hcd *ehci) { - unsigned uf, now_frame, frame; - unsigned fmask = ehci->periodic_size - 1; - bool modified, live; + unsigned uf, now_frame, frame; + unsigned fmask = ehci->periodic_size - 1; + bool modified, live; + union ehci_shadow q, *q_p; + __hc32 type, *hw_p; /* * When running, scan from last scan point up to "now" @@ -2399,119 +2401,117 @@ static void scan_isoc(struct ehci_hcd *ehci) ehci->now_frame = now_frame; frame = ehci->last_iso_frame; - for (;;) { - union ehci_shadow q, *q_p; - __hc32 type, *hw_p; restart: - /* scan each element in frame's queue for completions */ - q_p = &ehci->pshadow [frame]; - hw_p = &ehci->periodic [frame]; - q.ptr = q_p->ptr; - type = Q_NEXT_TYPE(ehci, *hw_p); - modified = false; - - while (q.ptr != NULL) { - switch (hc32_to_cpu(ehci, type)) { - case Q_TYPE_ITD: - /* If this ITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (frame == now_frame && live) { - rmb(); - for (uf = 0; uf < 8; uf++) { - if (q.itd->hw_transaction[uf] & - ITD_ACTIVE(ehci)) - break; - } - if (uf < 8) { - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(ehci, - q.itd->hw_next); - q = *q_p; + /* Scan each element in frame's queue for completions */ + q_p = &ehci->pshadow[frame]; + hw_p = &ehci->periodic[frame]; + q.ptr = q_p->ptr; + type = Q_NEXT_TYPE(ehci, *hw_p); + modified = false; + + while (q.ptr != NULL) { + switch (hc32_to_cpu(ehci, type)) { + case Q_TYPE_ITD: + /* + * If this ITD is still active, leave it for + * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. + */ + if (frame == now_frame && live) { + rmb(); + for (uf = 0; uf < 8; uf++) { + if (q.itd->hw_transaction[uf] & + ITD_ACTIVE(ehci)) break; - } } - - /* Take finished ITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. HC won't cache the - * pointer for much longer, if at all. - */ - *q_p = q.itd->itd_next; - if (!ehci->use_dummy_qh || - q.itd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.itd->hw_next; - else - *hw_p = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); - type = Q_NEXT_TYPE(ehci, q.itd->hw_next); - wmb(); - modified = itd_complete (ehci, q.itd); - q = *q_p; - break; - case Q_TYPE_SITD: - /* If this SITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (((frame == now_frame) || - (((frame + 1) & fmask) == now_frame)) - && live - && (q.sitd->hw_results & - SITD_ACTIVE(ehci))) { - - q_p = &q.sitd->sitd_next; - hw_p = &q.sitd->hw_next; + if (uf < 8) { + q_p = &q.itd->itd_next; + hw_p = &q.itd->hw_next; type = Q_NEXT_TYPE(ehci, - q.sitd->hw_next); + q.itd->hw_next); q = *q_p; break; } + } + + /* + * Take finished ITDs out of the schedule + * and process them: recycle, maybe report + * URB completion. HC won't cache the + * pointer for much longer, if at all. + */ + *q_p = q.itd->itd_next; + if (!ehci->use_dummy_qh || + q.itd->hw_next != EHCI_LIST_END(ehci)) + *hw_p = q.itd->hw_next; + else + *hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma); + type = Q_NEXT_TYPE(ehci, q.itd->hw_next); + wmb(); + modified = itd_complete(ehci, q.itd); + q = *q_p; + break; + case Q_TYPE_SITD: + /* + * If this SITD is still active, leave it for + * later processing ... check the next entry. + * No need to check for activity unless the + * frame is current. + */ + if (((frame == now_frame) || + (((frame + 1) & fmask) == now_frame)) + && live + && (q.sitd->hw_results & SITD_ACTIVE(ehci))) { - /* Take finished SITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. - */ - *q_p = q.sitd->sitd_next; - if (!ehci->use_dummy_qh || - q.sitd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.sitd->hw_next; - else - *hw_p = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); + q_p = &q.sitd->sitd_next; + hw_p = &q.sitd->hw_next; type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); - wmb(); - modified = sitd_complete (ehci, q.sitd); q = *q_p; break; - default: - ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", - type, frame, q.ptr); - // BUG (); - /* FALL THROUGH */ - case Q_TYPE_QH: - case Q_TYPE_FSTN: - /* End of the iTDs and siTDs */ - q.ptr = NULL; - break; } - /* assume completion callbacks modify the queue */ - if (unlikely(modified && ehci->isoc_count > 0)) - goto restart; - } - - /* Stop when we have reached the current frame */ - if (frame == now_frame) + /* + * Take finished SITDs out of the schedule + * and process them: recycle, maybe report + * URB completion. + */ + *q_p = q.sitd->sitd_next; + if (!ehci->use_dummy_qh || + q.sitd->hw_next != EHCI_LIST_END(ehci)) + *hw_p = q.sitd->hw_next; + else + *hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma); + type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); + wmb(); + modified = sitd_complete(ehci, q.sitd); + q = *q_p; break; + default: + ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", + type, frame, q.ptr); + /* BUG(); */ + /* FALL THROUGH */ + case Q_TYPE_QH: + case Q_TYPE_FSTN: + /* End of the iTDs and siTDs */ + q.ptr = NULL; + break; + } - /* The last frame may still have active siTDs */ - ehci->last_iso_frame = frame; - frame = (frame + 1) & fmask; + /* Assume completion callbacks modify the queue */ + if (unlikely(modified && ehci->isoc_count > 0)) + goto restart; } + + /* Stop when we have reached the current frame */ + if (frame == now_frame) + return; + + /* The last frame may still have active siTDs */ + ehci->last_iso_frame = frame; + frame = (frame + 1) & fmask; + + goto restart; } -- cgit From 25d108696c00142a083c61dc5892856516d38c0d Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:11 -0300 Subject: usb: host: ehci-sched: move constants to right This patch moves the constants to right. Tested by compilation only. Caught by coccinelle: scripts/coccinelle/misc/compare_const_fl.cocci Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 74c2023763ad..f4a94d443abe 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -330,7 +330,7 @@ static int __maybe_unused same_tt(struct usb_device *dev1, */ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) { - unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask); + unsigned char smask = hc32_to_cpu(ehci, mask) & QH_SMASK; if (!smask) { ehci_err(ehci, "invalid empty smask!\n"); /* uframe 7 can't have bw so this will indicate failure */ @@ -409,11 +409,11 @@ static int tt_available ( * must be empty, so as to not illegally delay * already scheduled transactions */ - if (125 < usecs) { + if (usecs > 125) { int ufs = (usecs / 125); for (i = uframe; i < (uframe + ufs) && i < 8; i++) - if (0 < tt_usecs[i]) + if (tt_usecs[i] > 0) return 0; } -- cgit From 77d6554d1b40be5c522b0dc0dc0df5e164150753 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:12 -0300 Subject: usb: host: ehci-sched: remove useless initializations This patch removes useless initializations. Tested by compilation only. Caught by cppcheck. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index f4a94d443abe..b28ec83361e1 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -2132,7 +2132,7 @@ sitd_patch( ) { struct ehci_iso_packet *uf = &iso_sched->packet [index]; - u64 bufp = uf->bufp; + u64 bufp; sitd->hw_next = EHCI_LIST_END(ehci); sitd->hw_fullspeed_ep = stream->address; @@ -2242,7 +2242,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) struct urb *urb = sitd->urb; struct usb_iso_packet_descriptor *desc; u32 t; - int urb_index = -1; + int urb_index; struct ehci_iso_stream *stream = sitd->stream; struct usb_device *dev; bool retval = false; -- cgit From 189b8ff0daa1b12befddf03b009d55a702aeecb2 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:13 -0300 Subject: usb: host: ehci-sched: add spaces around operators This patch adds spaces around operators. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b28ec83361e1..b8cc9d4fcb66 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -346,7 +346,7 @@ max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) { int i; - for (i=0; i<7; i++) { + for (i = 0; i < 7; i++) { if (max_tt_usecs[i] < tt_usecs[i]) { tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; tt_usecs[i] = max_tt_usecs[i]; -- cgit From ee906470618fcc03f4ae94334f600ee4d3e67b20 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:14 -0300 Subject: usb: host: ehci-sched: remove prohibited spaces This patch removes prohibited spaces before open parenthesis and open brackets. It also removes an assignment inside condition and unnecessary braces in single statement block. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 265 +++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 132 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b8cc9d4fcb66..11d5efdddae2 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -34,7 +34,7 @@ * pre-calculated schedule data to make appending to the queue be quick. */ -static int ehci_get_frame (struct usb_hcd *hcd); +static int ehci_get_frame(struct usb_hcd *hcd); /* * periodic_next_shadow - return "next" pointer on shadow list @@ -73,7 +73,7 @@ shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, } /* caller must hold ehci->lock */ -static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) +static void periodic_unlink(struct ehci_hcd *ehci, unsigned frame, void *ptr) { union ehci_shadow *prev_p = &ehci->pshadow[frame]; __hc32 *hw_p = &ehci->periodic[frame]; @@ -375,7 +375,7 @@ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, * since proper scheduling limits ssplits to less than 16 per uframe. */ -static int tt_available ( +static int tt_available( struct ehci_hcd *ehci, struct ehci_per_sched *ps, struct ehci_tt *tt, @@ -435,7 +435,7 @@ static int tt_available ( * for a periodic transfer starting at the specified frame, using * all the uframes in the mask. */ -static int tt_no_collision ( +static int tt_no_collision( struct ehci_hcd *ehci, unsigned period, struct usb_device *dev, @@ -455,8 +455,8 @@ static int tt_no_collision ( __hc32 type; struct ehci_qh_hw *hw; - here = ehci->pshadow [frame]; - type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); + here = ehci->pshadow[frame]; + type = Q_NEXT_TYPE(ehci, ehci->periodic[frame]); while (here.ptr) { switch (hc32_to_cpu(ehci, type)) { case Q_TYPE_ITD: @@ -479,7 +479,7 @@ static int tt_no_collision ( here = here.qh->qh_next; continue; case Q_TYPE_SITD: - if (same_tt (dev, here.sitd->urb->dev)) { + if (same_tt(dev, here.sitd->urb->dev)) { u16 mask; mask = hc32_to_cpu(ehci, here.sitd @@ -494,7 +494,7 @@ static int tt_no_collision ( continue; // case Q_TYPE_FSTN: default: - ehci_dbg (ehci, + ehci_dbg(ehci, "periodic frame %d bogus type %d\n", frame, type); } @@ -588,9 +588,9 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_next = here; if (here.qh) qh->hw->hw_next = *hw_p; - wmb (); + wmb(); prev->qh = qh; - *hw_p = QH_NEXT (ehci, qh->qh_dma); + *hw_p = QH_NEXT(ehci, qh->qh_dma); } } qh->qh_state = QH_STATE_LINKED; @@ -633,7 +633,7 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) period = qh->ps.period ? : 1; for (i = qh->ps.phase; i < ehci->periodic_size; i += period) - periodic_unlink (ehci, i, qh); + periodic_unlink(ehci, i, qh); /* update per-qh bandwidth for debugfs */ ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.bw_period @@ -679,7 +679,7 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) /* if the qh is waiting for unlink, cancel it now */ cancel_unlink_wait_intr(ehci, qh); - qh_unlink_periodic (ehci, qh); + qh_unlink_periodic(ehci, qh); /* Make sure the unlinks are visible before starting the timer */ wmb(); @@ -763,7 +763,7 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) /*-------------------------------------------------------------------------*/ -static int check_period ( +static int check_period( struct ehci_hcd *ehci, unsigned frame, unsigned uframe, @@ -789,7 +789,7 @@ static int check_period ( return 1; } -static int check_intr_schedule ( +static int check_intr_schedule( struct ehci_hcd *ehci, unsigned frame, unsigned uframe, @@ -925,7 +925,7 @@ done: return status; } -static int intr_submit ( +static int intr_submit( struct ehci_hcd *ehci, struct urb *urb, struct list_head *qtd_list, @@ -940,7 +940,7 @@ static int intr_submit ( /* get endpoint and transfer/schedule data */ epnum = urb->ep->desc.bEndpointAddress; - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; @@ -951,20 +951,21 @@ static int intr_submit ( goto done_not_linked; /* get qh and force any scheduling errors */ - INIT_LIST_HEAD (&empty); + INIT_LIST_HEAD(&empty); qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv); if (qh == NULL) { status = -ENOMEM; goto done; } if (qh->qh_state == QH_STATE_IDLE) { - if ((status = qh_schedule (ehci, qh)) != 0) + status = qh_schedule(ehci, qh); + if (status) goto done; } /* then queue the urb's tds to the qh */ qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); - BUG_ON (qh == NULL); + BUG_ON(qh == NULL); /* stuff into the periodic schedule */ if (qh->qh_state == QH_STATE_IDLE) { @@ -982,9 +983,9 @@ done: if (unlikely(status)) usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); if (status) - qtd_list_free (ehci, urb, qtd_list); + qtd_list_free(ehci, urb, qtd_list); return status; } @@ -1022,12 +1023,12 @@ static void scan_intr(struct ehci_hcd *ehci) /* ehci_iso_stream ops work with both ITD and SITD */ static struct ehci_iso_stream * -iso_stream_alloc (gfp_t mem_flags) +iso_stream_alloc(gfp_t mem_flags) { struct ehci_iso_stream *stream; stream = kzalloc(sizeof *stream, mem_flags); - if (likely (stream != NULL)) { + if (likely(stream != NULL)) { INIT_LIST_HEAD(&stream->td_list); INIT_LIST_HEAD(&stream->free_list); stream->next_uframe = NO_FRAME; @@ -1037,13 +1038,13 @@ iso_stream_alloc (gfp_t mem_flags) } static void -iso_stream_init ( +iso_stream_init( struct ehci_hcd *ehci, struct ehci_iso_stream *stream, struct urb *urb ) { - static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; + static const u8 smask_out[] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; struct usb_device *dev = urb->dev; u32 buf1; @@ -1111,7 +1112,7 @@ iso_stream_init ( think_time = dev->tt ? dev->tt->think_time : 0; stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time( dev->speed, is_input, 1, maxp)); - hs_transfers = max (1u, (maxp + 187) / 188); + hs_transfers = max(1u, (maxp + 187) / 188); if (is_input) { u32 tmp; @@ -1151,7 +1152,7 @@ iso_stream_init ( } static struct ehci_iso_stream * -iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) +iso_stream_find(struct ehci_hcd *ehci, struct urb *urb) { unsigned epnum; struct ehci_iso_stream *stream; @@ -1164,25 +1165,25 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) else ep = urb->dev->ep_out[epnum]; - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); stream = ep->hcpriv; - if (unlikely (stream == NULL)) { + if (unlikely(stream == NULL)) { stream = iso_stream_alloc(GFP_ATOMIC); - if (likely (stream != NULL)) { + if (likely(stream != NULL)) { ep->hcpriv = stream; iso_stream_init(ehci, stream, urb); } /* if dev->ep [epnum] is a QH, hw is set */ - } else if (unlikely (stream->hw != NULL)) { - ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", + } else if (unlikely(stream->hw != NULL)) { + ehci_dbg(ehci, "dev %s ep%d%s, not iso??\n", urb->dev->devpath, epnum, usb_pipein(urb->pipe) ? "in" : "out"); stream = NULL; } - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return stream; } @@ -1191,16 +1192,16 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) /* ehci_iso_sched ops can be ITD-only or SITD-only */ static struct ehci_iso_sched * -iso_sched_alloc (unsigned packets, gfp_t mem_flags) +iso_sched_alloc(unsigned packets, gfp_t mem_flags) { struct ehci_iso_sched *iso_sched; int size = sizeof *iso_sched; - size += packets * sizeof (struct ehci_iso_packet); + size += packets * sizeof(struct ehci_iso_packet); iso_sched = kzalloc(size, mem_flags); - if (likely (iso_sched != NULL)) { - INIT_LIST_HEAD (&iso_sched->td_list); - } + if (likely(iso_sched != NULL)) + INIT_LIST_HEAD(&iso_sched->td_list); + return iso_sched; } @@ -1222,17 +1223,17 @@ itd_sched_init( * when we fit new itds into the schedule. */ for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *uframe = &iso_sched->packet [i]; + struct ehci_iso_packet *uframe = &iso_sched->packet[i]; unsigned length; dma_addr_t buf; u32 trans; - length = urb->iso_frame_desc [i].length; - buf = dma + urb->iso_frame_desc [i].offset; + length = urb->iso_frame_desc[i].length; + buf = dma + urb->iso_frame_desc[i].offset; trans = EHCI_ISOC_ACTIVE; trans |= buf & 0x0fff; - if (unlikely (((i + 1) == urb->number_of_packets)) + if (unlikely(((i + 1) == urb->number_of_packets)) && !(urb->transfer_flags & URB_NO_INTERRUPT)) trans |= EHCI_ITD_IOC; trans |= length << 16; @@ -1241,13 +1242,13 @@ itd_sched_init( /* might need to cross a buffer page within a uframe */ uframe->bufp = (buf & ~(u64)0x0fff); buf += length; - if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) + if (unlikely((uframe->bufp != (buf & ~(u64)0x0fff)))) uframe->cross = 1; } } static void -iso_sched_free ( +iso_sched_free( struct ehci_iso_stream *stream, struct ehci_iso_sched *iso_sched ) @@ -1255,12 +1256,12 @@ iso_sched_free ( if (!iso_sched) return; // caller must hold ehci->lock! - list_splice (&iso_sched->td_list, &stream->free_list); - kfree (iso_sched); + list_splice(&iso_sched->td_list, &stream->free_list); + kfree(iso_sched); } static int -itd_urb_transaction ( +itd_urb_transaction( struct ehci_iso_stream *stream, struct ehci_hcd *ehci, struct urb *urb, @@ -1274,8 +1275,8 @@ itd_urb_transaction ( struct ehci_iso_sched *sched; unsigned long flags; - sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (unlikely (sched == NULL)) + sched = iso_sched_alloc(urb->number_of_packets, mem_flags); + if (unlikely(sched == NULL)) return -ENOMEM; itd_sched_init(ehci, sched, stream, urb); @@ -1286,7 +1287,7 @@ itd_urb_transaction ( num_itds = urb->number_of_packets; /* allocate/init ITDs */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < num_itds; i++) { /* @@ -1298,14 +1299,14 @@ itd_urb_transaction ( struct ehci_itd, itd_list); if (itd->frame == ehci->now_frame) goto alloc_itd; - list_del (&itd->itd_list); + list_del(&itd->itd_list); itd_dma = itd->itd_dma; } else { alloc_itd: - spin_unlock_irqrestore (&ehci->lock, flags); - itd = dma_pool_alloc (ehci->itd_pool, mem_flags, + spin_unlock_irqrestore(&ehci->lock, flags); + itd = dma_pool_alloc(ehci->itd_pool, mem_flags, &itd_dma); - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (!itd) { iso_sched_free(stream, sched); spin_unlock_irqrestore(&ehci->lock, flags); @@ -1313,12 +1314,12 @@ itd_urb_transaction ( } } - memset (itd, 0, sizeof *itd); + memset(itd, 0, sizeof *itd); itd->itd_dma = itd_dma; itd->frame = NO_FRAME; - list_add (&itd->itd_list, &sched->td_list); + list_add(&itd->itd_list, &sched->td_list); } - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); /* temporarily store schedule info in hcpriv */ urb->hcpriv = sched; @@ -1385,7 +1386,7 @@ static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci, } static inline int -itd_slot_ok ( +itd_slot_ok( struct ehci_hcd *ehci, struct ehci_iso_stream *stream, unsigned uframe @@ -1405,7 +1406,7 @@ itd_slot_ok ( } static inline int -sitd_slot_ok ( +sitd_slot_ok( struct ehci_hcd *ehci, struct ehci_iso_stream *stream, unsigned uframe, @@ -1492,7 +1493,7 @@ sitd_slot_ok ( */ static int -iso_stream_schedule ( +iso_stream_schedule( struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream @@ -1693,9 +1694,9 @@ itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream, /* it's been recently zeroed */ itd->hw_next = EHCI_LIST_END(ehci); - itd->hw_bufp [0] = stream->buf0; - itd->hw_bufp [1] = stream->buf1; - itd->hw_bufp [2] = stream->buf2; + itd->hw_bufp[0] = stream->buf0; + itd->hw_bufp[1] = stream->buf1; + itd->hw_bufp[2] = stream->buf2; for (i = 0; i < 8; i++) itd->index[i] = -1; @@ -1712,13 +1713,13 @@ itd_patch( u16 uframe ) { - struct ehci_iso_packet *uf = &iso_sched->packet [index]; + struct ehci_iso_packet *uf = &iso_sched->packet[index]; unsigned pg = itd->pg; // BUG_ON (pg == 6 && uf->cross); uframe &= 0x07; - itd->index [uframe] = index; + itd->index[uframe] = index; itd->hw_transaction[uframe] = uf->transaction; itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12); @@ -1726,7 +1727,7 @@ itd_patch( itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32)); /* iso_frame_desc[].offset must be strictly increasing */ - if (unlikely (uf->cross)) { + if (unlikely(uf->cross)) { u64 bufp = uf->bufp + 4096; itd->pg = ++pg; @@ -1736,7 +1737,7 @@ itd_patch( } static inline void -itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) +itd_link(struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) { union ehci_shadow *prev = &ehci->pshadow[frame]; __hc32 *hw_p = &ehci->periodic[frame]; @@ -1757,7 +1758,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) itd->hw_next = *hw_p; prev->itd = itd; itd->frame = frame; - wmb (); + wmb(); *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); } @@ -1776,7 +1777,7 @@ static void itd_link_urb( next_uframe = stream->next_uframe & (mod - 1); - if (unlikely (list_empty(&stream->td_list))) + if (unlikely(list_empty(&stream->td_list))) ehci_to_hcd(ehci)->self.bandwidth_allocated += stream->bandwidth; @@ -1796,12 +1797,12 @@ static void itd_link_urb( /* ASSERT: no itds for this endpoint in this uframe */ - itd = list_entry (iso_sched->td_list.next, + itd = list_entry(iso_sched->td_list.next, struct ehci_itd, itd_list); - list_move_tail (&itd->itd_list, &stream->td_list); + list_move_tail(&itd->itd_list, &stream->td_list); itd->stream = stream; itd->urb = urb; - itd_init (ehci, stream, itd); + itd_init(ehci, stream, itd); } uframe = next_uframe & 0x07; @@ -1823,7 +1824,7 @@ static void itd_link_urb( stream->next_uframe = next_uframe; /* don't need that schedule data any more */ - iso_sched_free (stream, iso_sched); + iso_sched_free(stream, iso_sched); urb->hcpriv = stream; ++ehci->isoc_count; @@ -1855,19 +1856,19 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) /* for each uframe with a packet */ for (uframe = 0; uframe < 8; uframe++) { - if (likely (itd->index[uframe] == -1)) + if (likely(itd->index[uframe] == -1)) continue; urb_index = itd->index[uframe]; - desc = &urb->iso_frame_desc [urb_index]; + desc = &urb->iso_frame_desc[urb_index]; - t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); - itd->hw_transaction [uframe] = 0; + t = hc32_to_cpup(ehci, &itd->hw_transaction[uframe]); + itd->hw_transaction[uframe] = 0; /* report transfer status */ - if (unlikely (t & ISO_ERRS)) { + if (unlikely(t & ISO_ERRS)) { urb->error_count++; if (t & EHCI_ISOC_BUF_ERR) - desc->status = usb_pipein (urb->pipe) + desc->status = usb_pipein(urb->pipe) ? -ENOSR /* hc couldn't read */ : -ECOMM; /* hc couldn't write */ else if (t & EHCI_ISOC_BABBLE) @@ -1880,7 +1881,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) desc->actual_length = EHCI_ITD_LENGTH(t); urb->actual_length += desc->actual_length; } - } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { + } else if (likely((t & EHCI_ISOC_ACTIVE) == 0)) { desc->status = 0; desc->actual_length = EHCI_ITD_LENGTH(t); urb->actual_length += desc->actual_length; @@ -1891,7 +1892,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) } /* handle completion now? */ - if (likely ((urb_index + 1) != urb->number_of_packets)) + if (likely((urb_index + 1) != urb->number_of_packets)) goto done; /* ASSERT: it's really the last itd for this urb @@ -1936,7 +1937,7 @@ done: /*-------------------------------------------------------------------------*/ -static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, +static int itd_submit(struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) { int status = -EINVAL; @@ -1944,37 +1945,37 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream; /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); - if (unlikely (stream == NULL)) { - ehci_dbg (ehci, "can't get iso stream\n"); + stream = iso_stream_find(ehci, urb); + if (unlikely(stream == NULL)) { + ehci_dbg(ehci, "can't get iso stream\n"); return -ENOMEM; } if (unlikely(urb->interval != stream->uperiod)) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", + ehci_dbg(ehci, "can't change iso interval %d --> %d\n", stream->uperiod, urb->interval); goto done; } #ifdef EHCI_URB_TRACE - ehci_dbg (ehci, + ehci_dbg(ehci, "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", __func__, urb->dev->devpath, urb, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", urb->transfer_buffer_length, urb->number_of_packets, urb->interval, stream); #endif /* allocate ITDs w/o locking anything */ - status = itd_urb_transaction (stream, ehci, urb, mem_flags); - if (unlikely (status < 0)) { - ehci_dbg (ehci, "can't init itds\n"); + status = itd_urb_transaction(stream, ehci, urb, mem_flags); + if (unlikely(status < 0)) { + ehci_dbg(ehci, "can't init itds\n"); goto done; } /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; @@ -1984,7 +1985,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, goto done_not_linked; status = iso_stream_schedule(ehci, urb, stream); if (likely(status == 0)) { - itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); + itd_link_urb(ehci, urb, ehci->periodic_size << 3, stream); } else if (status > 0) { status = 0; ehci_urb_done(ehci, urb, 0); @@ -1992,7 +1993,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); } done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); done: return status; } @@ -2022,13 +2023,13 @@ sitd_sched_init( * when we fit new sitds into the schedule. */ for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *packet = &iso_sched->packet [i]; + struct ehci_iso_packet *packet = &iso_sched->packet[i]; unsigned length; dma_addr_t buf; u32 trans; - length = urb->iso_frame_desc [i].length & 0x03ff; - buf = dma + urb->iso_frame_desc [i].offset; + length = urb->iso_frame_desc[i].length & 0x03ff; + buf = dma + urb->iso_frame_desc[i].offset; trans = SITD_STS_ACTIVE; if (((i + 1) == urb->number_of_packets) @@ -2054,7 +2055,7 @@ sitd_sched_init( } static int -sitd_urb_transaction ( +sitd_urb_transaction( struct ehci_iso_stream *stream, struct ehci_hcd *ehci, struct urb *urb, @@ -2067,14 +2068,14 @@ sitd_urb_transaction ( struct ehci_iso_sched *iso_sched; unsigned long flags; - iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); + iso_sched = iso_sched_alloc(urb->number_of_packets, mem_flags); if (iso_sched == NULL) return -ENOMEM; sitd_sched_init(ehci, iso_sched, stream, urb); /* allocate/init sITDs */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); for (i = 0; i < urb->number_of_packets; i++) { /* NOTE: for now, we don't try to handle wraparound cases @@ -2091,14 +2092,14 @@ sitd_urb_transaction ( struct ehci_sitd, sitd_list); if (sitd->frame == ehci->now_frame) goto alloc_sitd; - list_del (&sitd->sitd_list); + list_del(&sitd->sitd_list); sitd_dma = sitd->sitd_dma; } else { alloc_sitd: - spin_unlock_irqrestore (&ehci->lock, flags); - sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, + spin_unlock_irqrestore(&ehci->lock, flags); + sitd = dma_pool_alloc(ehci->sitd_pool, mem_flags, &sitd_dma); - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (!sitd) { iso_sched_free(stream, iso_sched); spin_unlock_irqrestore(&ehci->lock, flags); @@ -2106,17 +2107,17 @@ sitd_urb_transaction ( } } - memset (sitd, 0, sizeof *sitd); + memset(sitd, 0, sizeof *sitd); sitd->sitd_dma = sitd_dma; sitd->frame = NO_FRAME; - list_add (&sitd->sitd_list, &iso_sched->td_list); + list_add(&sitd->sitd_list, &iso_sched->td_list); } /* temporarily store schedule info in hcpriv */ urb->hcpriv = iso_sched; urb->error_count = 0; - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); return 0; } @@ -2131,7 +2132,7 @@ sitd_patch( unsigned index ) { - struct ehci_iso_packet *uf = &iso_sched->packet [index]; + struct ehci_iso_packet *uf = &iso_sched->packet[index]; u64 bufp; sitd->hw_next = EHCI_LIST_END(ehci); @@ -2152,14 +2153,14 @@ sitd_patch( } static inline void -sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) +sitd_link(struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) { /* note: sitd ordering could matter (CSPLIT then SSPLIT) */ - sitd->sitd_next = ehci->pshadow [frame]; - sitd->hw_next = ehci->periodic [frame]; - ehci->pshadow [frame].sitd = sitd; + sitd->sitd_next = ehci->pshadow[frame]; + sitd->hw_next = ehci->periodic[frame]; + ehci->pshadow[frame].sitd = sitd; sitd->frame = frame; - wmb (); + wmb(); ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD); } @@ -2196,13 +2197,13 @@ static void sitd_link_urb( packet++) { /* ASSERT: we have all necessary sitds */ - BUG_ON (list_empty (&sched->td_list)); + BUG_ON(list_empty(&sched->td_list)); /* ASSERT: no itds for this endpoint in this frame */ - sitd = list_entry (sched->td_list.next, + sitd = list_entry(sched->td_list.next, struct ehci_sitd, sitd_list); - list_move_tail (&sitd->sitd_list, &stream->td_list); + list_move_tail(&sitd->sitd_list, &stream->td_list); sitd->stream = stream; sitd->urb = urb; @@ -2215,7 +2216,7 @@ static void sitd_link_urb( stream->next_uframe = next_uframe & (mod - 1); /* don't need that schedule data any more */ - iso_sched_free (stream, sched); + iso_sched_free(stream, sched); urb->hcpriv = stream; ++ehci->isoc_count; @@ -2248,14 +2249,14 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) bool retval = false; urb_index = sitd->index; - desc = &urb->iso_frame_desc [urb_index]; + desc = &urb->iso_frame_desc[urb_index]; t = hc32_to_cpup(ehci, &sitd->hw_results); /* report transfer status */ if (unlikely(t & SITD_ERRS)) { urb->error_count++; if (t & SITD_STS_DBE) - desc->status = usb_pipein (urb->pipe) + desc->status = usb_pipein(urb->pipe) ? -ENOSR /* hc couldn't read */ : -ECOMM; /* hc couldn't write */ else if (t & SITD_STS_BABBLE) @@ -2316,7 +2317,7 @@ done: } -static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, +static int sitd_submit(struct ehci_hcd *ehci, struct urb *urb, gfp_t mem_flags) { int status = -EINVAL; @@ -2324,35 +2325,35 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream; /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); + stream = iso_stream_find(ehci, urb); if (stream == NULL) { - ehci_dbg (ehci, "can't get iso stream\n"); + ehci_dbg(ehci, "can't get iso stream\n"); return -ENOMEM; } if (urb->interval != stream->ps.period) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", + ehci_dbg(ehci, "can't change iso interval %d --> %d\n", stream->ps.period, urb->interval); goto done; } #ifdef EHCI_URB_TRACE - ehci_dbg (ehci, + ehci_dbg(ehci, "submit %p dev%s ep%d%s-iso len %d\n", urb, urb->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", + usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", urb->transfer_buffer_length); #endif /* allocate SITDs */ - status = sitd_urb_transaction (stream, ehci, urb, mem_flags); + status = sitd_urb_transaction(stream, ehci, urb, mem_flags); if (status < 0) { - ehci_dbg (ehci, "can't init sitds\n"); + ehci_dbg(ehci, "can't init sitds\n"); goto done; } /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); + spin_lock_irqsave(&ehci->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; @@ -2362,7 +2363,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, goto done_not_linked; status = iso_stream_schedule(ehci, urb, stream); if (likely(status == 0)) { - sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); + sitd_link_urb(ehci, urb, ehci->periodic_size << 3, stream); } else if (status > 0) { status = 0; ehci_urb_done(ehci, urb, 0); @@ -2370,7 +2371,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); } done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); + spin_unlock_irqrestore(&ehci->lock, flags); done: return status; } -- cgit From 2fee2fed78cb8952982ffc22cbdcf8e6327c1407 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:15 -0300 Subject: usb: host: ehci-sched: remove useless else branch This patch removes an useless else branch after a break, reducing one indent block. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 11d5efdddae2..8b3abdcca08f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -296,10 +296,9 @@ static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE], if (x <= 125) { budget_line[uf] = x; break; - } else { - budget_line[uf] = 125; - x -= 125; } + budget_line[uf] = 125; + x -= 125; } } } -- cgit From 1ec2780cd7d25619faf9db1aa97eef6c453f0fad Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:16 -0300 Subject: usb: host: ehci-sched: use C89-style comments This patch changes comments conforming coding style. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 8b3abdcca08f..682fb42ca508 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -52,7 +52,7 @@ periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, return &periodic->fstn->fstn_next; case Q_TYPE_ITD: return &periodic->itd->itd_next; - // case Q_TYPE_SITD: + /* case Q_TYPE_SITD: */ default: return &periodic->sitd->sitd_next; } @@ -491,7 +491,7 @@ static int tt_no_collision( type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); here = here.sitd->sitd_next; continue; - // case Q_TYPE_FSTN: + /* case Q_TYPE_FSTN: */ default: ehci_dbg(ehci, "periodic frame %d bogus type %d\n", @@ -784,7 +784,7 @@ static int check_period( return 0; } - // success! + /* success! */ return 1; } @@ -1254,7 +1254,7 @@ iso_sched_free( { if (!iso_sched) return; - // caller must hold ehci->lock! + /* caller must hold ehci->lock! */ list_splice(&iso_sched->td_list, &stream->free_list); kfree(iso_sched); } @@ -1715,7 +1715,7 @@ itd_patch( struct ehci_iso_packet *uf = &iso_sched->packet[index]; unsigned pg = itd->pg; - // BUG_ON (pg == 6 && uf->cross); + /* BUG_ON(pg == 6 && uf->cross); */ uframe &= 0x07; itd->index[uframe] = index; @@ -1792,7 +1792,7 @@ static void itd_link_urb( packet < urb->number_of_packets;) { if (itd == NULL) { /* ASSERT: we have all necessary itds */ - // BUG_ON (list_empty (&iso_sched->td_list)); + /* BUG_ON(list_empty(&iso_sched->td_list)); */ /* ASSERT: no itds for this endpoint in this uframe */ @@ -1894,9 +1894,10 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) if (likely((urb_index + 1) != urb->number_of_packets)) goto done; - /* ASSERT: it's really the last itd for this urb - list_for_each_entry (itd, &stream->td_list, itd_list) - BUG_ON (itd->urb == urb); + /* + * ASSERT: it's really the last itd for this urb + * list_for_each_entry (itd, &stream->td_list, itd_list) + * BUG_ON(itd->urb == urb); */ /* give urb back to the driver; completion often (re)submits */ @@ -2275,9 +2276,10 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) if ((urb_index + 1) != urb->number_of_packets) goto done; - /* ASSERT: it's really the last sitd for this urb - list_for_each_entry (sitd, &stream->td_list, sitd_list) - BUG_ON (sitd->urb == urb); + /* + * ASSERT: it's really the last sitd for this urb + * list_for_each_entry (sitd, &stream->td_list, sitd_list) + * BUG_ON(sitd->urb == urb); */ /* give urb back to the driver; completion often (re)submits */ -- cgit From 6d0febcd271902bc6dba20aceea66a8bd9023198 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:17 -0300 Subject: usb: host: ehci-sched: add line after declarations This patch adds a blank line after declarations. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 682fb42ca508..b7b40ed6eeba 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -330,6 +330,7 @@ static int __maybe_unused same_tt(struct usb_device *dev1, static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) { unsigned char smask = hc32_to_cpu(ehci, mask) & QH_SMASK; + if (!smask) { ehci_err(ehci, "invalid empty smask!\n"); /* uframe 7 can't have bw so this will indicate failure */ @@ -345,6 +346,7 @@ max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) { int i; + for (i = 0; i < 7; i++) { if (max_tt_usecs[i] < tt_usecs[i]) { tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; -- cgit From ee2a1d24b9b37686214aecfccccf611be6bc0144 Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:18 -0300 Subject: usb: host: ehci-sched: use sizeof operator with parens This patch adds parens to sizeof operator uses. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b7b40ed6eeba..5e5d50b40d04 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1028,7 +1028,7 @@ iso_stream_alloc(gfp_t mem_flags) { struct ehci_iso_stream *stream; - stream = kzalloc(sizeof *stream, mem_flags); + stream = kzalloc(sizeof(*stream), mem_flags); if (likely(stream != NULL)) { INIT_LIST_HEAD(&stream->td_list); INIT_LIST_HEAD(&stream->free_list); @@ -1196,7 +1196,7 @@ static struct ehci_iso_sched * iso_sched_alloc(unsigned packets, gfp_t mem_flags) { struct ehci_iso_sched *iso_sched; - int size = sizeof *iso_sched; + int size = sizeof(*iso_sched); size += packets * sizeof(struct ehci_iso_packet); iso_sched = kzalloc(size, mem_flags); @@ -1315,7 +1315,7 @@ itd_urb_transaction( } } - memset(itd, 0, sizeof *itd); + memset(itd, 0, sizeof(*itd)); itd->itd_dma = itd_dma; itd->frame = NO_FRAME; list_add(&itd->itd_list, &sched->td_list); @@ -2109,7 +2109,7 @@ sitd_urb_transaction( } } - memset(sitd, 0, sizeof *sitd); + memset(sitd, 0, sizeof(*sitd)); sitd->sitd_dma = sitd_dma; sitd->frame = NO_FRAME; list_add(&sitd->sitd_list, &iso_sched->td_list); -- cgit From d078c6e4ea5e6a93d44d5815d0ee4a9bb5c5718b Mon Sep 17 00:00:00 2001 From: "Geyslan G. Bem" Date: Mon, 25 Jan 2016 22:45:19 -0300 Subject: usb: host: ehci-sched: remove unnecessary braces This patch removes unnecessary braces in single statement blocks at the same time as replaces the if statement with a ternary conditional. Tested by compilation only. Caught by checkpatch. Signed-off-by: Geyslan G. Bem Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 5e5d50b40d04..1dfe54f14737 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1060,11 +1060,7 @@ iso_stream_init( epnum = usb_pipeendpoint(urb->pipe); is_input = usb_pipein(urb->pipe) ? USB_DIR_IN : 0; maxp = usb_endpoint_maxp(&urb->ep->desc); - if (is_input) { - buf1 = (1 << 11); - } else { - buf1 = 0; - } + buf1 = is_input ? 1 << 11 : 0; /* knows about ITD vs SITD */ if (dev->speed == USB_SPEED_HIGH) { -- cgit From e6533e879fd24f36c50a9db3b41d3433784222ff Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 27 Jan 2016 00:12:23 +0530 Subject: usb: storage: ene_ub6250: Remove unnecessary cast in kfree Remove unnecassary casts in the argument to kfree. Found using Coccinelle. The semantic patch used to find this is as follows: // @@ type T; expression *f; @@ - kfree((T *)(f)); + kfree(f); // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/ene_ub6250.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index f3cf4cecd2b7..d3a17c65a702 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -1067,12 +1067,12 @@ static void ms_lib_free_writebuf(struct us_data *us) ms_lib_clear_pagemap(info); /* (pdx)->MS_Lib.pagemap memset 0 in ms.h */ if (info->MS_Lib.blkpag) { - kfree((u8 *)(info->MS_Lib.blkpag)); /* Arnold test ... */ + kfree(info->MS_Lib.blkpag); /* Arnold test ... */ info->MS_Lib.blkpag = NULL; } if (info->MS_Lib.blkext) { - kfree((u8 *)(info->MS_Lib.blkext)); /* Arnold test ... */ + kfree(info->MS_Lib.blkext); /* Arnold test ... */ info->MS_Lib.blkext = NULL; } } -- cgit From 1b83349fddd1efa814a83735e44e684a139d2425 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Wed, 27 Jan 2016 15:05:49 +0100 Subject: usb/storage: misc fixes to comments in include/linux/usb/storage.h The fixes are: - fix indentation of a comment - fix a typo in the comment about bulk_cb_wrap.Length - make comment about US_BULK_CB_SIGN look like the one about US_BULK_CS_SIGN below - make the comment about bulk_cs_wrap.Signature look more like the one about bulk_cb_wrap.Signature Signed-off-by: Antonio Ospite Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/storage.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h index cb33fff2ba0b..305ee8db7faf 100644 --- a/include/linux/usb/storage.h +++ b/include/linux/usb/storage.h @@ -45,9 +45,9 @@ #define USB_PR_DEVICE 0xff /* Use device's value */ - /* - * Bulk only data structures - */ +/* + * Bulk only data structures + */ /* command block wrapper */ struct bulk_cb_wrap { @@ -56,18 +56,18 @@ struct bulk_cb_wrap { __le32 DataTransferLength; /* size of data */ __u8 Flags; /* direction in bit 0 */ __u8 Lun; /* LUN normally 0 */ - __u8 Length; /* of of the CDB */ + __u8 Length; /* length of the CDB */ __u8 CDB[16]; /* max command */ }; #define US_BULK_CB_WRAP_LEN 31 -#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ +#define US_BULK_CB_SIGN 0x43425355 /* spells out 'USBC' */ #define US_BULK_FLAG_IN (1 << 7) #define US_BULK_FLAG_OUT 0 /* command status wrapper */ struct bulk_cs_wrap { - __le32 Signature; /* should = 'USBS' */ + __le32 Signature; /* contains 'USBS' */ __u32 Tag; /* same as original command */ __le32 Residue; /* amount not transferred */ __u8 Status; /* see below */ -- cgit From 46e3cafb01feb107a681e89fd9b4f1cd938a601f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 30 Jan 2016 17:34:55 +0300 Subject: USB: cxacru: fix an bounds check warning This is a privileged operation so it doesn't matter much. We use "tmp" as an offset into an array. If it were invalid we could read out of bounds and trigger an oops if the memory is not mapped. Plus it makes static checkers complain. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 1173f9cbc137..0a866e90b49c 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -476,6 +476,8 @@ static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev, return -EINVAL; if (index < 0 || index > 0x7f) return -EINVAL; + if (tmp < 0 || tmp > len - pos) + return -EINVAL; pos += tmp; /* skip trailing newline */ -- cgit From 21619792d1eca7e772ca190ba68588e57f29595b Mon Sep 17 00:00:00 2001 From: Andrew Goodbody Date: Tue, 2 Feb 2016 17:36:39 +0000 Subject: usb: usbip: Fix possible deadlocks reported by lockdep Change spin_lock calls to spin_lock_irqsave to prevent attmpted recursive lock taking in interrupt context. This patch fixes Bug 109351 https://bugzilla.kernel.org/show_bug.cgi?id=109351 Signed-off-by: Andrew Goodbody Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_event.c | 5 ++- drivers/usb/usbip/vhci_hcd.c | 88 ++++++++++++++++++++++++----------------- drivers/usb/usbip/vhci_rx.c | 30 ++++++++------ drivers/usb/usbip/vhci_sysfs.c | 19 +++++---- drivers/usb/usbip/vhci_tx.c | 14 ++++--- 5 files changed, 91 insertions(+), 65 deletions(-) diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 64933b993d7a..2580a32bcdff 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -117,11 +117,12 @@ EXPORT_SYMBOL_GPL(usbip_event_add); int usbip_event_happened(struct usbip_device *ud) { int happened = 0; + unsigned long flags; - spin_lock(&ud->lock); + spin_lock_irqsave(&ud->lock, flags); if (ud->event != 0) happened = 1; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); return happened; } diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 7fbe19d5279e..fca51105974e 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -121,9 +121,11 @@ static void dump_port_status_diff(u32 prev_status, u32 new_status) void rh_port_connect(int rhport, enum usb_device_speed speed) { + unsigned long flags; + usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION | (1 << USB_PORT_FEAT_C_CONNECTION); @@ -139,22 +141,24 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) break; } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } static void rh_port_disconnect(int rhport) { + unsigned long flags; + usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION; the_controller->port_status[rhport] |= (1 << USB_PORT_FEAT_C_CONNECTION); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); } @@ -182,13 +186,14 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) int retval; int rhport; int changed = 0; + unsigned long flags; retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8); memset(buf, 0, retval); vhci = hcd_to_vhci(hcd); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) { usbip_dbg_vhci_rh("hw accessible flag not on?\n"); goto done; @@ -209,7 +214,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) usb_hcd_resume_root_hub(hcd); done: - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return changed ? retval : 0; } @@ -231,6 +236,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, struct vhci_hcd *dum; int retval = 0; int rhport; + unsigned long flags; u32 prev_port_status[VHCI_NPORTS]; @@ -249,7 +255,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, dum = hcd_to_vhci(hcd); - spin_lock(&dum->lock); + spin_lock_irqsave(&dum->lock, flags); /* store old status and compare now and old later */ if (usbip_dbg_flag_vhci_rh) { @@ -403,7 +409,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } usbip_dbg_vhci_rh(" bye\n"); - spin_unlock(&dum->lock); + spin_unlock_irqrestore(&dum->lock, flags); return retval; } @@ -426,6 +432,7 @@ static void vhci_tx_urb(struct urb *urb) { struct vhci_device *vdev = get_vdev(urb->dev); struct vhci_priv *priv; + unsigned long flags; if (!vdev) { pr_err("could not get virtual device"); @@ -438,7 +445,7 @@ static void vhci_tx_urb(struct urb *urb) return; } - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); priv->seqnum = atomic_inc_return(&the_controller->seqnum); if (priv->seqnum == 0xffff) @@ -452,7 +459,7 @@ static void vhci_tx_urb(struct urb *urb) list_add_tail(&priv->list, &vdev->priv_tx); wake_up(&vdev->waitq_tx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); } static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, @@ -461,6 +468,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct device *dev = &urb->dev->dev; int ret = 0; struct vhci_device *vdev; + unsigned long flags; usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); @@ -468,11 +476,11 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, /* patch to usb_sg_init() is in 2.5.60 */ BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); if (urb->status != -EINPROGRESS) { dev_err(dev, "URB already unlinked!, status %d\n", urb->status); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return urb->status; } @@ -484,7 +492,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, vdev->ud.status == VDEV_ST_ERROR) { dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport); spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -ENODEV; } spin_unlock(&vdev->ud.lock); @@ -557,14 +565,14 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, out: vhci_tx_urb(urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return 0; no_need_xmit: usb_hcd_unlink_urb_from_ep(hcd, urb); no_need_unlink: - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); if (!ret) usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -621,16 +629,17 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { struct vhci_priv *priv; struct vhci_device *vdev; + unsigned long flags; pr_info("dequeue a urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); priv = urb->hcpriv; if (!priv) { /* URB was never linked! or will be soon given back by * vhci_rx. */ - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -EIDRM; } @@ -639,7 +648,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ret = usb_hcd_check_unlink_urb(hcd, urb, status); if (ret) { - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return ret; } } @@ -667,10 +676,10 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) usb_hcd_unlink_urb_from_ep(hcd, urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); } else { /* tcp connection is alive */ @@ -682,7 +691,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC); if (!unlink) { spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC); return -ENOMEM; } @@ -703,7 +712,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) spin_unlock(&vdev->priv_lock); } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_dbg_vhci_hc("leave\n"); return 0; @@ -712,8 +721,9 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { @@ -747,19 +757,19 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) list_del(&unlink->list); spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); spin_lock(&vdev->priv_lock); kfree(unlink); } spin_unlock(&vdev->priv_lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); } /* @@ -826,8 +836,9 @@ static void vhci_shutdown_connection(struct usbip_device *ud) static void vhci_device_reset(struct usbip_device *ud) { struct vhci_device *vdev = container_of(ud, struct vhci_device, ud); + unsigned long flags; - spin_lock(&ud->lock); + spin_lock_irqsave(&ud->lock, flags); vdev->speed = 0; vdev->devid = 0; @@ -841,14 +852,16 @@ static void vhci_device_reset(struct usbip_device *ud) } ud->status = VDEV_ST_NULL; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); } static void vhci_device_unusable(struct usbip_device *ud) { - spin_lock(&ud->lock); + unsigned long flags; + + spin_lock_irqsave(&ud->lock, flags); ud->status = VDEV_ST_ERROR; - spin_unlock(&ud->lock); + spin_unlock_irqrestore(&ud->lock, flags); } static void vhci_device_init(struct vhci_device *vdev) @@ -938,12 +951,13 @@ static int vhci_get_frame_number(struct usb_hcd *hcd) static int vhci_bus_suspend(struct usb_hcd *hcd) { struct vhci_hcd *vhci = hcd_to_vhci(hcd); + unsigned long flags; dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); hcd->state = HC_STATE_SUSPENDED; - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return 0; } @@ -952,15 +966,16 @@ static int vhci_bus_resume(struct usb_hcd *hcd) { struct vhci_hcd *vhci = hcd_to_vhci(hcd); int rc = 0; + unsigned long flags; dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); - spin_lock(&vhci->lock); + spin_lock_irqsave(&vhci->lock, flags); if (!HCD_HW_ACCESSIBLE(hcd)) rc = -ESHUTDOWN; else hcd->state = HC_STATE_RUNNING; - spin_unlock(&vhci->lock); + spin_unlock_irqrestore(&vhci->lock, flags); return rc; } @@ -1058,17 +1073,18 @@ static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state) int rhport = 0; int connected = 0; int ret = 0; + unsigned long flags; hcd = platform_get_drvdata(pdev); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); for (rhport = 0; rhport < VHCI_NPORTS; rhport++) if (the_controller->port_status[rhport] & USB_PORT_STAT_CONNECTION) connected += 1; - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); if (connected > 0) { dev_info(&pdev->dev, diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c index 00e4a54308e4..d656e0edc3d5 100644 --- a/drivers/usb/usbip/vhci_rx.c +++ b/drivers/usb/usbip/vhci_rx.c @@ -72,10 +72,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); if (!urb) { pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum); @@ -104,9 +105,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %p\n", urb); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -117,8 +118,9 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, struct usbip_header *pdu) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { pr_info("unlink->seqnum %lu\n", unlink->seqnum); @@ -127,12 +129,12 @@ static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev, unlink->seqnum); list_del(&unlink->list); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return unlink; } } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } @@ -142,6 +144,7 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; + unsigned long flags; usbip_dump_header(pdu); @@ -152,9 +155,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); if (!urb) { /* @@ -171,9 +174,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -185,10 +188,11 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, static int vhci_priv_tx_empty(struct vhci_device *vdev) { int empty = 0; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); empty = list_empty(&vdev->priv_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return empty; } diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index 211f43f67ea2..5b5462eb1665 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -32,10 +32,11 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, { char *s = out; int i = 0; + unsigned long flags; BUG_ON(!the_controller || !out); - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); /* * output example: @@ -70,7 +71,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, spin_unlock(&vdev->ud.lock); } - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return out - s; } @@ -80,11 +81,12 @@ static DEVICE_ATTR_RO(status); static int vhci_port_disconnect(__u32 rhport) { struct vhci_device *vdev; + unsigned long flags; usbip_dbg_vhci_sysfs("enter\n"); /* lock */ - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); vdev = port_to_vdev(rhport); @@ -94,14 +96,14 @@ static int vhci_port_disconnect(__u32 rhport) /* unlock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); return -EINVAL; } /* unlock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); @@ -177,6 +179,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, int sockfd = 0; __u32 rhport = 0, devid = 0, speed = 0; int err; + unsigned long flags; /* * @rhport: port number of vhci_hcd @@ -202,14 +205,14 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, /* now need lock until setting vdev status as used */ /* begin a lock */ - spin_lock(&the_controller->lock); + spin_lock_irqsave(&the_controller->lock, flags); vdev = port_to_vdev(rhport); spin_lock(&vdev->ud.lock); if (vdev->ud.status != VDEV_ST_NULL) { /* end of the lock */ spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); sockfd_put(socket); @@ -227,7 +230,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, vdev->ud.status = VDEV_ST_NOTASSIGNED; spin_unlock(&vdev->ud.lock); - spin_unlock(&the_controller->lock); + spin_unlock_irqrestore(&the_controller->lock, flags); /* end the lock */ vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx"); diff --git a/drivers/usb/usbip/vhci_tx.c b/drivers/usb/usbip/vhci_tx.c index 409fd99f3257..3e7878fe2fd4 100644 --- a/drivers/usb/usbip/vhci_tx.c +++ b/drivers/usb/usbip/vhci_tx.c @@ -47,16 +47,17 @@ static void setup_cmd_submit_pdu(struct usbip_header *pdup, struct urb *urb) static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev) { struct vhci_priv *priv, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) { list_move_tail(&priv->list, &vdev->priv_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return priv; } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } @@ -136,16 +137,17 @@ static int vhci_send_cmd_submit(struct vhci_device *vdev) static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; + unsigned long flags; - spin_lock(&vdev->priv_lock); + spin_lock_irqsave(&vdev->priv_lock, flags); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { list_move_tail(&unlink->list, &vdev->unlink_rx); - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return unlink; } - spin_unlock(&vdev->priv_lock); + spin_unlock_irqrestore(&vdev->priv_lock, flags); return NULL; } -- cgit From dbf3e7f654c0f06a932b8fcafac78de9d0b81d68 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:09:24 +0100 Subject: Implement an ioctl to support the USMTMC-USB488 READ_STATUS_BYTE operation. Background: When performing a read on an instrument that is executing a function that runs longer than the USB timeout the instrument may hang and require a device reset to recover. The READ_STATUS_BYTE operation always returns even when the instrument is busy permitting to poll for the appropriate condition. This capability is referred to in instrument application notes on synchronizing acquisitions for other platforms. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 201 +++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 2 + 2 files changed, 203 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 7a11a8263171..c2eb6fe9f4c8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -87,6 +87,19 @@ struct usbtmc_device_data { u8 bTag_last_write; /* needed for abort */ u8 bTag_last_read; /* needed for abort */ + /* data for interrupt in endpoint handling */ + u8 bNotify1; + u8 bNotify2; + u16 ifnum; + u8 iin_bTag; + u8 *iin_buffer; + atomic_t iin_data_valid; + unsigned int iin_ep; + int iin_ep_present; + int iin_interval; + struct urb *iin_urb; + u16 iin_wMaxPacketSize; + u8 rigol_quirk; /* attributes from the USB TMC spec for this device */ @@ -99,6 +112,7 @@ struct usbtmc_device_data { struct usbtmc_dev_capabilities capabilities; struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ + wait_queue_head_t waitq; }; #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) @@ -373,6 +387,84 @@ exit: return rv; } +static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data, + void __user *arg) +{ + struct device *dev = &data->intf->dev; + u8 *buffer; + u8 tag; + __u8 stb; + int rv; + + dev_dbg(dev, "Enter ioctl_read_stb iin_ep_present: %d\n", + data->iin_ep_present); + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + atomic_set(&data->iin_data_valid, 0); + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + USBTMC488_REQUEST_READ_STATUS_BYTE, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + data->iin_bTag, + data->ifnum, + buffer, 0x03, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "stb usb_control_msg returned %d\n", rv); + goto exit; + } + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "control status returned %x\n", buffer[0]); + rv = -EIO; + goto exit; + } + + if (data->iin_ep_present) { + rv = wait_event_interruptible_timeout( + data->waitq, + atomic_read(&data->iin_data_valid) != 0, + USBTMC_TIMEOUT); + if (rv < 0) { + dev_dbg(dev, "wait interrupted %d\n", rv); + goto exit; + } + + if (rv == 0) { + dev_dbg(dev, "wait timed out\n"); + rv = -ETIME; + goto exit; + } + + tag = data->bNotify1 & 0x7f; + if (tag != data->iin_bTag) { + dev_err(dev, "expected bTag %x got %x\n", + data->iin_bTag, tag); + } + + stb = data->bNotify2; + } else { + stb = buffer[2]; + } + + rv = copy_to_user(arg, &stb, sizeof(stb)); + if (rv) + rv = -EFAULT; + + exit: + /* bump interrupt bTag */ + data->iin_bTag += 1; + if (data->iin_bTag > 127) + /* 1 is for SRQ see USBTMC-USB488 subclass spec section 4.3.1 */ + data->iin_bTag = 2; + + kfree(buffer); + return rv; +} + /* * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint. * @transfer_size: number of bytes to request from the device. @@ -1069,6 +1161,10 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case USBTMC_IOCTL_ABORT_BULK_IN: retval = usbtmc_ioctl_abort_bulk_in(data); break; + + case USBTMC488_IOCTL_READ_STB: + retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg); + break; } skip_io_on_zombie: @@ -1092,6 +1188,57 @@ static struct usb_class_driver usbtmc_class = { .minor_base = USBTMC_MINOR_BASE, }; +static void usbtmc_interrupt(struct urb *urb) +{ + struct usbtmc_device_data *data = urb->context; + struct device *dev = &data->intf->dev; + int status = urb->status; + int rv; + + dev_dbg(&data->intf->dev, "int status: %d len %d\n", + status, urb->actual_length); + + switch (status) { + case 0: /* SUCCESS */ + /* check for valid STB notification */ + if (data->iin_buffer[0] > 0x81) { + data->bNotify1 = data->iin_buffer[0]; + data->bNotify2 = data->iin_buffer[1]; + atomic_set(&data->iin_data_valid, 1); + wake_up_interruptible(&data->waitq); + goto exit; + } + dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]); + break; + case -EOVERFLOW: + dev_err(dev, "overflow with length %d, actual length is %d\n", + data->iin_wMaxPacketSize, urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + case -EILSEQ: + case -ETIME: + /* urb terminated, clean up */ + dev_dbg(dev, "urb terminated, status: %d\n", status); + return; + default: + dev_err(dev, "unknown status received: %d\n", status); + } +exit: + rv = usb_submit_urb(urb, GFP_ATOMIC); + if (rv) + dev_err(dev, "usb_submit_urb failed: %d\n", rv); +} + +static void usbtmc_free_int(struct usbtmc_device_data *data) +{ + if (!data->iin_ep_present || !data->iin_urb) + return; + usb_kill_urb(data->iin_urb); + kfree(data->iin_buffer); + usb_free_urb(data->iin_urb); + kref_put(&data->kref, usbtmc_delete); +} static int usbtmc_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1114,6 +1261,8 @@ static int usbtmc_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); kref_init(&data->kref); mutex_init(&data->io_mutex); + init_waitqueue_head(&data->waitq); + atomic_set(&data->iin_data_valid, 0); data->zombie = 0; /* Determine if it is a Rigol or not */ @@ -1134,9 +1283,12 @@ static int usbtmc_probe(struct usb_interface *intf, data->bTag = 1; data->TermCharEnabled = 0; data->TermChar = '\n'; + /* 2 <= bTag <= 127 USBTMC-USB488 subclass specification 4.3.1 */ + data->iin_bTag = 2; /* USBTMC devices have only one setting, so use that */ iface_desc = data->intf->cur_altsetting; + data->ifnum = iface_desc->desc.bInterfaceNumber; /* Find bulk in endpoint */ for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { @@ -1161,6 +1313,20 @@ static int usbtmc_probe(struct usb_interface *intf, break; } } + /* Find int endpoint */ + for (n = 0; n < iface_desc->desc.bNumEndpoints; n++) { + endpoint = &iface_desc->endpoint[n].desc; + + if (usb_endpoint_is_int_in(endpoint)) { + data->iin_ep_present = 1; + data->iin_ep = endpoint->bEndpointAddress; + data->iin_wMaxPacketSize = usb_endpoint_maxp(endpoint); + data->iin_interval = endpoint->bInterval; + dev_dbg(&intf->dev, "Found Int in endpoint at %u\n", + data->iin_ep); + break; + } + } retcode = get_capabilities(data); if (retcode) @@ -1169,6 +1335,39 @@ static int usbtmc_probe(struct usb_interface *intf, retcode = sysfs_create_group(&intf->dev.kobj, &capability_attr_grp); + if (data->iin_ep_present) { + /* allocate int urb */ + data->iin_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!data->iin_urb) { + dev_err(&intf->dev, "Failed to allocate int urb\n"); + goto error_register; + } + + /* will reference data in int urb */ + kref_get(&data->kref); + + /* allocate buffer for interrupt in */ + data->iin_buffer = kmalloc(data->iin_wMaxPacketSize, + GFP_KERNEL); + if (!data->iin_buffer) { + dev_err(&intf->dev, "Failed to allocate int buf\n"); + goto error_register; + } + + /* fill interrupt urb */ + usb_fill_int_urb(data->iin_urb, data->usb_dev, + usb_rcvintpipe(data->usb_dev, data->iin_ep), + data->iin_buffer, data->iin_wMaxPacketSize, + usbtmc_interrupt, + data, data->iin_interval); + + retcode = usb_submit_urb(data->iin_urb, GFP_KERNEL); + if (retcode) { + dev_err(&intf->dev, "Failed to submit iin_urb\n"); + goto error_register; + } + } + retcode = sysfs_create_group(&intf->dev.kobj, &data_attr_grp); retcode = usb_register_dev(intf, &usbtmc_class); @@ -1185,6 +1384,7 @@ static int usbtmc_probe(struct usb_interface *intf, error_register: sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); + usbtmc_free_int(data); kref_put(&data->kref, usbtmc_delete); return retcode; } @@ -1196,6 +1396,7 @@ static void usbtmc_disconnect(struct usb_interface *intf) dev_dbg(&intf->dev, "usbtmc_disconnect called\n"); data = usb_get_intfdata(intf); + usbtmc_free_int(data); usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index c045ae12556c..7e5ced80548f 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -30,6 +30,7 @@ #define USBTMC_REQUEST_CHECK_CLEAR_STATUS 6 #define USBTMC_REQUEST_GET_CAPABILITIES 7 #define USBTMC_REQUEST_INDICATOR_PULSE 64 +#define USBTMC488_REQUEST_READ_STATUS_BYTE 128 /* Request values for USBTMC driver's ioctl entry point */ #define USBTMC_IOC_NR 91 @@ -39,5 +40,6 @@ #define USBTMC_IOCTL_ABORT_BULK_IN _IO(USBTMC_IOC_NR, 4) #define USBTMC_IOCTL_CLEAR_OUT_HALT _IO(USBTMC_IOC_NR, 6) #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) +#define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) #endif -- cgit From 82ed33811d7214198e071b785ee34dbe99f82140 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:15:15 +0100 Subject: Add support for USBTMC USB488 SRQ notification with fasync Background: By configuring an instrument's event status register various conditions can be reported via an SRQ notification. This complements the synchronous polling approach using the READ_STATUS_BYTE ioctl with an asynchronous notification. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index c2eb6fe9f4c8..d77da2fd7b70 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -99,6 +99,7 @@ struct usbtmc_device_data { int iin_interval; struct urb *iin_urb; u16 iin_wMaxPacketSize; + atomic_t srq_asserted; u8 rigol_quirk; @@ -113,6 +114,7 @@ struct usbtmc_device_data { struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ wait_queue_head_t waitq; + struct fasync_struct *fasync; }; #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) @@ -405,6 +407,9 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data, atomic_set(&data->iin_data_valid, 0); + /* must issue read_stb before using poll or select */ + atomic_set(&data->srq_asserted, 0); + rv = usb_control_msg(data->usb_dev, usb_rcvctrlpipe(data->usb_dev, 0), USBTMC488_REQUEST_READ_STATUS_BYTE, @@ -1172,6 +1177,13 @@ skip_io_on_zombie: return retval; } +static int usbtmc_fasync(int fd, struct file *file, int on) +{ + struct usbtmc_device_data *data = file->private_data; + + return fasync_helper(fd, file, on, &data->fasync); +} + static const struct file_operations fops = { .owner = THIS_MODULE, .read = usbtmc_read, @@ -1179,6 +1191,7 @@ static const struct file_operations fops = { .open = usbtmc_open, .release = usbtmc_release, .unlocked_ioctl = usbtmc_ioctl, + .fasync = usbtmc_fasync, .llseek = default_llseek, }; @@ -1208,6 +1221,16 @@ static void usbtmc_interrupt(struct urb *urb) wake_up_interruptible(&data->waitq); goto exit; } + /* check for SRQ notification */ + if (data->iin_buffer[0] == 0x81) { + if (data->fasync) + kill_fasync(&data->fasync, + SIGIO, POLL_IN); + + atomic_set(&data->srq_asserted, 1); + wake_up_interruptible(&data->waitq); + goto exit; + } dev_warn(dev, "invalid notification: %x\n", data->iin_buffer[0]); break; case -EOVERFLOW: @@ -1263,6 +1286,7 @@ static int usbtmc_probe(struct usb_interface *intf, mutex_init(&data->io_mutex); init_waitqueue_head(&data->waitq); atomic_set(&data->iin_data_valid, 0); + atomic_set(&data->srq_asserted, 0); data->zombie = 0; /* Determine if it is a Rigol or not */ -- cgit From eb6b92ecc0f9412623ab1584ddd8389b371638d4 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:19:14 +0100 Subject: Add support for receiving USBTMC USB488 SRQ notifications via poll/select Background: In many situations operations on multiple instruments need to be synchronized. poll/select provide a convenient way of waiting on a number of different instruments and other peripherals simultaneously. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index d77da2fd7b70..867842951ea0 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1184,6 +1185,27 @@ static int usbtmc_fasync(int fd, struct file *file, int on) return fasync_helper(fd, file, on, &data->fasync); } +static unsigned int usbtmc_poll(struct file *file, poll_table *wait) +{ + struct usbtmc_device_data *data = file->private_data; + unsigned int mask; + + mutex_lock(&data->io_mutex); + + if (data->zombie) { + mask = POLLHUP | POLLERR; + goto no_poll; + } + + poll_wait(file, &data->waitq, wait); + + mask = (atomic_read(&data->srq_asserted)) ? POLLIN | POLLRDNORM : 0; + +no_poll: + mutex_unlock(&data->io_mutex); + return mask; +} + static const struct file_operations fops = { .owner = THIS_MODULE, .read = usbtmc_read, @@ -1192,6 +1214,7 @@ static const struct file_operations fops = { .release = usbtmc_release, .unlocked_ioctl = usbtmc_ioctl, .fasync = usbtmc_fasync, + .poll = usbtmc_poll, .llseek = default_llseek, }; -- cgit From 29779d89fd049bfc6c07f19aaf9b8d19fe2ecc8c Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:22:28 +0100 Subject: Add ioctl to retrieve USBTMC-USB488 capabilities This is a convenience function to obtain an instrument's capabilities from its file descriptor without having to access sysfs from the user program. Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 12 ++++++++++++ include/uapi/linux/usb/tmc.h | 21 ++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 867842951ea0..6edb21ca9989 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -102,6 +102,9 @@ struct usbtmc_device_data { u16 iin_wMaxPacketSize; atomic_t srq_asserted; + /* coalesced usb488_caps from usbtmc_dev_capabilities */ + __u8 usb488_caps; + u8 rigol_quirk; /* attributes from the USB TMC spec for this device */ @@ -993,6 +996,7 @@ static int get_capabilities(struct usbtmc_device_data *data) data->capabilities.device_capabilities = buffer[5]; data->capabilities.usb488_interface_capabilities = buffer[14]; data->capabilities.usb488_device_capabilities = buffer[15]; + data->usb488_caps = (buffer[14] & 0x07) | ((buffer[15] & 0x0f) << 4); rv = 0; err_out: @@ -1168,6 +1172,14 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) retval = usbtmc_ioctl_abort_bulk_in(data); break; + case USBTMC488_IOCTL_GET_CAPS: + retval = copy_to_user((void __user *)arg, + &data->usb488_caps, + sizeof(data->usb488_caps)); + if (retval) + retval = -EFAULT; + break; + case USBTMC488_IOCTL_READ_STB: retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg); break; diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index 7e5ced80548f..b512fb2d403e 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -2,12 +2,14 @@ * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Greg Kroah-Hartman + * Copyright (C) 2015 Dave Penkler * * This file holds USB constants defined by the USB Device Class - * Definition for Test and Measurement devices published by the USB-IF. + * and USB488 Subclass Definitions for Test and Measurement devices + * published by the USB-IF. * - * It also has the ioctl definitions for the usbtmc kernel driver that - * userspace needs to know about. + * It also has the ioctl and capability definitions for the + * usbtmc kernel driver that userspace needs to know about. */ #ifndef __LINUX_USB_TMC_H @@ -40,6 +42,19 @@ #define USBTMC_IOCTL_ABORT_BULK_IN _IO(USBTMC_IOC_NR, 4) #define USBTMC_IOCTL_CLEAR_OUT_HALT _IO(USBTMC_IOC_NR, 6) #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) +#define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) +/* Driver encoded usb488 capabilities */ +#define USBTMC488_CAPABILITY_TRIGGER 1 +#define USBTMC488_CAPABILITY_SIMPLE 2 +#define USBTMC488_CAPABILITY_REN_CONTROL 2 +#define USBTMC488_CAPABILITY_GOTO_LOCAL 2 +#define USBTMC488_CAPABILITY_LOCAL_LOCKOUT 2 +#define USBTMC488_CAPABILITY_488_DOT_2 4 +#define USBTMC488_CAPABILITY_DT1 16 +#define USBTMC488_CAPABILITY_RL1 32 +#define USBTMC488_CAPABILITY_SR1 64 +#define USBTMC488_CAPABILITY_FULL_SCPI 128 + #endif -- cgit From 379d3d33c83b667b0edad0110693567306463882 Mon Sep 17 00:00:00 2001 From: Dave Penkler Date: Wed, 27 Jan 2016 19:25:24 +0100 Subject: Add ioctls to enable and disable local controls on an instrument These ioctls provide support for the USBTMC-USB488 control requests for REN_CONTROL, GO_TO_LOCAL and LOCAL_LOCKOUT Signed-off-by: Dave Penkler Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/usb/tmc.h | 6 ++++ 2 files changed, 76 insertions(+) diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 6edb21ca9989..419c72e10464 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -474,6 +474,61 @@ static int usbtmc488_ioctl_read_stb(struct usbtmc_device_data *data, return rv; } +static int usbtmc488_ioctl_simple(struct usbtmc_device_data *data, + void __user *arg, unsigned int cmd) +{ + struct device *dev = &data->intf->dev; + __u8 val; + u8 *buffer; + u16 wValue; + int rv; + + if (!(data->usb488_caps & USBTMC488_CAPABILITY_SIMPLE)) + return -EINVAL; + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + if (cmd == USBTMC488_REQUEST_REN_CONTROL) { + rv = copy_from_user(&val, arg, sizeof(val)); + if (rv) { + rv = -EFAULT; + goto exit; + } + wValue = val ? 1 : 0; + } else { + wValue = 0; + } + + rv = usb_control_msg(data->usb_dev, + usb_rcvctrlpipe(data->usb_dev, 0), + cmd, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + wValue, + data->ifnum, + buffer, 0x01, USBTMC_TIMEOUT); + if (rv < 0) { + dev_err(dev, "simple usb_control_msg failed %d\n", rv); + goto exit; + } else if (rv != 1) { + dev_warn(dev, "simple usb_control_msg returned %d\n", rv); + rv = -EIO; + goto exit; + } + + if (buffer[0] != USBTMC_STATUS_SUCCESS) { + dev_err(dev, "simple control status returned %x\n", buffer[0]); + rv = -EIO; + goto exit; + } + rv = 0; + + exit: + kfree(buffer); + return rv; +} + /* * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint. * @transfer_size: number of bytes to request from the device. @@ -1183,6 +1238,21 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case USBTMC488_IOCTL_READ_STB: retval = usbtmc488_ioctl_read_stb(data, (void __user *)arg); break; + + case USBTMC488_IOCTL_REN_CONTROL: + retval = usbtmc488_ioctl_simple(data, (void __user *)arg, + USBTMC488_REQUEST_REN_CONTROL); + break; + + case USBTMC488_IOCTL_GOTO_LOCAL: + retval = usbtmc488_ioctl_simple(data, (void __user *)arg, + USBTMC488_REQUEST_GOTO_LOCAL); + break; + + case USBTMC488_IOCTL_LOCAL_LOCKOUT: + retval = usbtmc488_ioctl_simple(data, (void __user *)arg, + USBTMC488_REQUEST_LOCAL_LOCKOUT); + break; } skip_io_on_zombie: diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h index b512fb2d403e..2e59d9c50b8d 100644 --- a/include/uapi/linux/usb/tmc.h +++ b/include/uapi/linux/usb/tmc.h @@ -33,6 +33,9 @@ #define USBTMC_REQUEST_GET_CAPABILITIES 7 #define USBTMC_REQUEST_INDICATOR_PULSE 64 #define USBTMC488_REQUEST_READ_STATUS_BYTE 128 +#define USBTMC488_REQUEST_REN_CONTROL 160 +#define USBTMC488_REQUEST_GOTO_LOCAL 161 +#define USBTMC488_REQUEST_LOCAL_LOCKOUT 162 /* Request values for USBTMC driver's ioctl entry point */ #define USBTMC_IOC_NR 91 @@ -44,6 +47,9 @@ #define USBTMC_IOCTL_CLEAR_IN_HALT _IO(USBTMC_IOC_NR, 7) #define USBTMC488_IOCTL_GET_CAPS _IOR(USBTMC_IOC_NR, 17, unsigned char) #define USBTMC488_IOCTL_READ_STB _IOR(USBTMC_IOC_NR, 18, unsigned char) +#define USBTMC488_IOCTL_REN_CONTROL _IOW(USBTMC_IOC_NR, 19, unsigned char) +#define USBTMC488_IOCTL_GOTO_LOCAL _IO(USBTMC_IOC_NR, 20) +#define USBTMC488_IOCTL_LOCAL_LOCKOUT _IO(USBTMC_IOC_NR, 21) /* Driver encoded usb488 capabilities */ #define USBTMC488_CAPABILITY_TRIGGER 1 -- cgit From 305b37bd01c220a7a6285911d43c9884270257be Mon Sep 17 00:00:00 2001 From: Ksenija Stanojevic Date: Wed, 3 Feb 2016 12:31:49 +0100 Subject: misc: Move panel driver out of staging Move panel driver from drivers/staging/panel to drivers/misc. Signed-off-by: Ksenija Stanojevic Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/lcd-panel-cgram.txt | 24 + MAINTAINERS | 12 +- drivers/misc/Kconfig | 278 +++ drivers/misc/Makefile | 1 + drivers/misc/panel.c | 2445 ++++++++++++++++++++++++ drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/panel/Kconfig | 278 --- drivers/staging/panel/Makefile | 1 - drivers/staging/panel/TODO | 8 - drivers/staging/panel/lcd-panel-cgram.txt | 24 - drivers/staging/panel/panel.c | 2445 ------------------------ 12 files changed, 2755 insertions(+), 2764 deletions(-) create mode 100644 Documentation/misc-devices/lcd-panel-cgram.txt create mode 100644 drivers/misc/panel.c delete mode 100644 drivers/staging/panel/Kconfig delete mode 100644 drivers/staging/panel/Makefile delete mode 100644 drivers/staging/panel/TODO delete mode 100644 drivers/staging/panel/lcd-panel-cgram.txt delete mode 100644 drivers/staging/panel/panel.c diff --git a/Documentation/misc-devices/lcd-panel-cgram.txt b/Documentation/misc-devices/lcd-panel-cgram.txt new file mode 100644 index 000000000000..7f82c905763d --- /dev/null +++ b/Documentation/misc-devices/lcd-panel-cgram.txt @@ -0,0 +1,24 @@ +Some LCDs allow you to define up to 8 characters, mapped to ASCII +characters 0 to 7. The escape code to define a new character is +'\e[LG' followed by one digit from 0 to 7, representing the character +number, and up to 8 couples of hex digits terminated by a semi-colon +(';'). Each couple of digits represents a line, with 1-bits for each +illuminated pixel with LSB on the right. Lines are numbered from the +top of the character to the bottom. On a 5x7 matrix, only the 5 lower +bits of the 7 first bytes are used for each character. If the string +is incomplete, only complete lines will be redefined. Here are some +examples : + + printf "\e[LG0010101050D1F0C04;" => 0 = [enter] + printf "\e[LG1040E1F0000000000;" => 1 = [up] + printf "\e[LG2000000001F0E0400;" => 2 = [down] + printf "\e[LG3040E1F001F0E0400;" => 3 = [up-down] + printf "\e[LG40002060E1E0E0602;" => 4 = [left] + printf "\e[LG500080C0E0F0E0C08;" => 5 = [right] + printf "\e[LG60016051516141400;" => 6 = "IP" + + printf "\e[LG00103071F1F070301;" => big speaker + printf "\e[LG00002061E1E060200;" => small speaker + +Willy + diff --git a/MAINTAINERS b/MAINTAINERS index 369f6aefc189..7c39a48b4118 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8168,6 +8168,13 @@ S: Maintained F: Documentation/mn10300/ F: arch/mn10300/ +PARALLEL LCD/KEYPAD PANEL DRIVER +M: Willy Tarreau +M: Ksenija Stanojevic +S: Odd Fixes +F: Documentation/misc-devices/lcd-panel-cgram.txt +F: drivers/misc/panel.c + PARALLEL PORT SUBSYSTEM M: Sudip Mukherjee M: Sudip Mukherjee @@ -10391,11 +10398,6 @@ L: linux-tegra@vger.kernel.org S: Maintained F: drivers/staging/nvec/ -STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER -M: Willy Tarreau -S: Odd Fixes -F: drivers/staging/panel/ - STAGING - REALTEK RTL8712U DRIVERS M: Larry Finger M: Florian Schilhabel . diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 054fc10cb3b6..f0ba78289504 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -525,6 +525,284 @@ config VEXPRESS_SYSCFG ARM Ltd. Versatile Express uses specialised platform configuration bus. System Configuration interface is one of the possible means of generating transactions on this bus. +config PANEL + tristate "Parallel port LCD/Keypad Panel support" + depends on PARPORT + ---help--- + Say Y here if you have an HD44780 or KS-0074 LCD connected to your + parallel port. This driver also features 4 and 6-key keypads. The LCD + is accessible through the /dev/lcd char device (10, 156), and the + keypad through /dev/keypad (10, 185). Both require misc device to be + enabled. This code can either be compiled as a module, or linked into + the kernel and started at boot. If you don't understand what all this + is about, say N. + +config PANEL_PARPORT + int "Default parallel port number (0=LPT1)" + depends on PANEL + range 0 255 + default "0" + ---help--- + This is the index of the parallel port the panel is connected to. One + driver instance only supports one parallel port, so if your keypad + and LCD are connected to two separate ports, you have to start two + modules with different arguments. Numbering starts with '0' for LPT1, + and so on. + +config PANEL_PROFILE + int "Default panel profile (0-5, 0=custom)" + depends on PANEL + range 0 5 + default "5" + ---help--- + To ease configuration, the driver supports different configuration + profiles for past and recent wirings. These profiles can also be + used to define an approximative configuration, completed by a few + other options. Here are the profiles : + + 0 = custom (see further) + 1 = 2x16 parallel LCD, old keypad + 2 = 2x16 serial LCD (KS-0074), new keypad + 3 = 2x16 parallel LCD (Hantronix), no keypad + 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad + 5 = 2x40 parallel LCD (old one), with old keypad + + Custom configurations allow you to define how your display is + wired to the parallel port, and how it works. This is only intended + for experts. + +config PANEL_KEYPAD + depends on PANEL && PANEL_PROFILE="0" + int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)" + range 0 3 + default 0 + ---help--- + This enables and configures a keypad connected to the parallel port. + The keys will be read from character device 10,185. Valid values are : + + 0 : do not enable this driver + 1 : old 6 keys keypad + 2 : new 6 keys keypad, as used on the server at www.ant-computing.com + 3 : Nexcom NSA1045's 4 keys keypad + + New profiles can be described in the driver source. The driver also + supports simultaneous keys pressed when the keypad supports them. + +config PANEL_LCD + depends on PANEL && PANEL_PROFILE="0" + int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)" + range 0 5 + default 0 + ---help--- + This enables and configures an LCD connected to the parallel port. + The driver includes an interpreter for escape codes starting with + '\e[L' which are specific to the LCD, and a few ANSI codes. The + driver will be registered as character device 10,156, usually + under the name '/dev/lcd'. There are a total of 6 supported types : + + 0 : do not enable the driver + 1 : custom configuration and wiring (see further) + 2 : 2x16 & 2x40 parallel LCD (old wiring) + 3 : 2x16 serial LCD (KS-0074 based) + 4 : 2x16 parallel LCD (Hantronix wiring) + 5 : 2x16 parallel LCD (Nexcom wiring) + + When type '1' is specified, other options will appear to configure + more precise aspects (wiring, dimensions, protocol, ...). Please note + that those values changed from the 2.4 driver for better consistency. + +config PANEL_LCD_HEIGHT + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Number of lines on the LCD (1-2)" + range 1 2 + default 2 + ---help--- + This is the number of visible character lines on the LCD in custom profile. + It can either be 1 or 2. + +config PANEL_LCD_WIDTH + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Number of characters per line on the LCD (1-40)" + range 1 40 + default 40 + ---help--- + This is the number of characters per line on the LCD in custom profile. + Common values are 16,20,24,40. + +config PANEL_LCD_BWIDTH + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Internal LCD line width (1-40, 40 by default)" + range 1 40 + default 40 + ---help--- + Most LCDs use a standard controller which supports hardware lines of 40 + characters, although sometimes only 16, 20 or 24 of them are really wired + to the terminal. This results in some non-visible but addressable characters, + and is the case for most parallel LCDs. Other LCDs, and some serial ones, + however, use the same line width internally as what is visible. The KS0074 + for example, uses 16 characters per line for 16 visible characters per line. + + This option lets you configure the value used by your LCD in 'custom' profile. + If you don't know, put '40' here. + +config PANEL_LCD_HWIDTH + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Hardware LCD line width (1-64, 64 by default)" + range 1 64 + default 64 + ---help--- + Most LCDs use a single address bit to differentiate line 0 and line 1. Since + some of them need to be able to address 40 chars with the lower bits, they + often use the immediately superior power of 2, which is 64, to address the + next line. + + If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and + 64 here for a 2x40. + +config PANEL_LCD_CHARSET + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "LCD character set (0=normal, 1=KS0074)" + range 0 1 + default 0 + ---help--- + Some controllers such as the KS0074 use a somewhat strange character set + where many symbols are at unusual places. The driver knows how to map + 'standard' ASCII characters to the character sets used by these controllers. + Valid values are : + + 0 : normal (untranslated) character set + 1 : KS0074 character set + + If you don't know, use the normal one (0). + +config PANEL_LCD_PROTO + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "LCD communication mode (0=parallel 8 bits, 1=serial)" + range 0 1 + default 0 + ---help--- + This driver now supports any serial or parallel LCD wired to a parallel + port. But before assigning signals, the driver needs to know if it will + be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires + (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals + (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits + parallel LCD, and 1 for a serial LCD. + +config PANEL_LCD_PIN_E + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" + int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) " + range -17 17 + default 14 + ---help--- + This describes the number of the parallel port pin to which the LCD 'E' + signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'E' pin in custom profile is '14' (AUTOFEED). + +config PANEL_LCD_PIN_RS + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" + int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) " + range -17 17 + default 17 + ---help--- + This describes the number of the parallel port pin to which the LCD 'RS' + signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'RS' pin in custom profile is '17' (SELECT IN). + +config PANEL_LCD_PIN_RW + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" + int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) " + range -17 17 + default 16 + ---help--- + This describes the number of the parallel port pin to which the LCD 'RW' + signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'RW' pin in custom profile is '16' (INIT). + +config PANEL_LCD_PIN_SCL + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" + int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) " + range -17 17 + default 1 + ---help--- + This describes the number of the parallel port pin to which the serial + LCD 'SCL' signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'SCL' pin in custom profile is '1' (STROBE). + +config PANEL_LCD_PIN_SDA + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" + int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) " + range -17 17 + default 2 + ---help--- + This describes the number of the parallel port pin to which the serial + LCD 'SDA' signal has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'SDA' pin in custom profile is '2' (D0). + +config PANEL_LCD_PIN_BL + depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" + int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) " + range -17 17 + default 0 + ---help--- + This describes the number of the parallel port pin to which the LCD 'BL' signal + has been connected. It can be : + + 0 : no connection (eg: connected to ground) + 1..17 : directly connected to any of these pins on the DB25 plug + -1..-17 : connected to the same pin through an inverter (eg: transistor). + + Default for the 'BL' pin in custom profile is '0' (uncontrolled). + +config PANEL_CHANGE_MESSAGE + depends on PANEL + bool "Change LCD initialization message ?" + default "n" + ---help--- + This allows you to replace the boot message indicating the kernel version + and the driver version with a custom message. This is useful on appliances + where a simple 'Starting system' message can be enough to stop a customer + from worrying. + + If you say 'Y' here, you'll be able to choose a message yourself. Otherwise, + say 'N' and keep the default message with the version. + +config PANEL_BOOT_MESSAGE + depends on PANEL && PANEL_CHANGE_MESSAGE="y" + string "New initialization message" + default "" + ---help--- + This allows you to replace the boot message indicating the kernel version + and the driver version with a custom message. This is useful on appliances + where a simple 'Starting system' message can be enough to stop a customer + from worrying. + + An empty message will only clear the display at driver init time. Any other + printf()-formatted message is valid with newline and escape codes. source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 537d7f3b78da..b2fb6dbffcef 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE) += genwqe/ obj-$(CONFIG_ECHO) += echo/ obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o obj-$(CONFIG_CXL_BASE) += cxl/ +obj-$(CONFIG_PANEL) += panel.o diff --git a/drivers/misc/panel.c b/drivers/misc/panel.c new file mode 100644 index 000000000000..4262db0237f9 --- /dev/null +++ b/drivers/misc/panel.c @@ -0,0 +1,2445 @@ +/* + * Front panel driver for Linux + * Copyright (C) 2000-2008, Willy Tarreau + * + * 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 code drives an LCD module (/dev/lcd), and a keypad (/dev/keypad) + * connected to a parallel printer port. + * + * The LCD module may either be an HD44780-like 8-bit parallel LCD, or a 1-bit + * serial module compatible with Samsung's KS0074. The pins may be connected in + * any combination, everything is programmable. + * + * The keypad consists in a matrix of push buttons connecting input pins to + * data output pins or to the ground. The combinations have to be hard-coded + * in the driver, though several profiles exist and adding new ones is easy. + * + * Several profiles are provided for commonly found LCD+keypad modules on the + * market, such as those found in Nexcom's appliances. + * + * FIXME: + * - the initialization/deinitialization process is very dirty and should + * be rewritten. It may even be buggy. + * + * TODO: + * - document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs) + * - make the LCD a part of a virtual screen of Vx*Vy + * - make the inputs list smp-safe + * - change the keyboard to a double mapping : signals -> key_id -> values + * so that applications can change values without knowing signals + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define LCD_MINOR 156 +#define KEYPAD_MINOR 185 + +#define PANEL_VERSION "0.9.5" + +#define LCD_MAXBYTES 256 /* max burst write */ + +#define KEYPAD_BUFFER 64 + +/* poll the keyboard this every second */ +#define INPUT_POLL_TIME (HZ / 50) +/* a key starts to repeat after this times INPUT_POLL_TIME */ +#define KEYPAD_REP_START (10) +/* a key repeats this times INPUT_POLL_TIME */ +#define KEYPAD_REP_DELAY (2) + +/* keep the light on this times INPUT_POLL_TIME for each flash */ +#define FLASH_LIGHT_TEMPO (200) + +/* converts an r_str() input to an active high, bits string : 000BAOSE */ +#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3) + +#define PNL_PBUSY 0x80 /* inverted input, active low */ +#define PNL_PACK 0x40 /* direct input, active low */ +#define PNL_POUTPA 0x20 /* direct input, active high */ +#define PNL_PSELECD 0x10 /* direct input, active high */ +#define PNL_PERRORP 0x08 /* direct input, active low */ + +#define PNL_PBIDIR 0x20 /* bi-directional ports */ +/* high to read data in or-ed with data out */ +#define PNL_PINTEN 0x10 +#define PNL_PSELECP 0x08 /* inverted output, active low */ +#define PNL_PINITP 0x04 /* direct output, active low */ +#define PNL_PAUTOLF 0x02 /* inverted output, active low */ +#define PNL_PSTROBE 0x01 /* inverted output */ + +#define PNL_PD0 0x01 +#define PNL_PD1 0x02 +#define PNL_PD2 0x04 +#define PNL_PD3 0x08 +#define PNL_PD4 0x10 +#define PNL_PD5 0x20 +#define PNL_PD6 0x40 +#define PNL_PD7 0x80 + +#define PIN_NONE 0 +#define PIN_STROBE 1 +#define PIN_D0 2 +#define PIN_D1 3 +#define PIN_D2 4 +#define PIN_D3 5 +#define PIN_D4 6 +#define PIN_D5 7 +#define PIN_D6 8 +#define PIN_D7 9 +#define PIN_AUTOLF 14 +#define PIN_INITP 16 +#define PIN_SELECP 17 +#define PIN_NOT_SET 127 + +#define LCD_FLAG_S 0x0001 +#define LCD_FLAG_ID 0x0002 +#define LCD_FLAG_B 0x0004 /* blink on */ +#define LCD_FLAG_C 0x0008 /* cursor on */ +#define LCD_FLAG_D 0x0010 /* display on */ +#define LCD_FLAG_F 0x0020 /* large font mode */ +#define LCD_FLAG_N 0x0040 /* 2-rows mode */ +#define LCD_FLAG_L 0x0080 /* backlight enabled */ + +/* LCD commands */ +#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */ + +#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */ +#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */ + +#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */ +#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */ +#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */ +#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */ + +#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */ +#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */ +#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */ + +#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */ +#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */ +#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */ +#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */ + +#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */ + +#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */ + +#define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ +#define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ + +#define NOT_SET -1 + +/* macros to simplify use of the parallel port */ +#define r_ctr(x) (parport_read_control((x)->port)) +#define r_dtr(x) (parport_read_data((x)->port)) +#define r_str(x) (parport_read_status((x)->port)) +#define w_ctr(x, y) (parport_write_control((x)->port, (y))) +#define w_dtr(x, y) (parport_write_data((x)->port, (y))) + +/* this defines which bits are to be used and which ones to be ignored */ +/* logical or of the output bits involved in the scan matrix */ +static __u8 scan_mask_o; +/* logical or of the input bits involved in the scan matrix */ +static __u8 scan_mask_i; + +enum input_type { + INPUT_TYPE_STD, + INPUT_TYPE_KBD, +}; + +enum input_state { + INPUT_ST_LOW, + INPUT_ST_RISING, + INPUT_ST_HIGH, + INPUT_ST_FALLING, +}; + +struct logical_input { + struct list_head list; + __u64 mask; + __u64 value; + enum input_type type; + enum input_state state; + __u8 rise_time, fall_time; + __u8 rise_timer, fall_timer, high_timer; + + union { + struct { /* valid when type == INPUT_TYPE_STD */ + void (*press_fct)(int); + void (*release_fct)(int); + int press_data; + int release_data; + } std; + struct { /* valid when type == INPUT_TYPE_KBD */ + /* strings can be non null-terminated */ + char press_str[sizeof(void *) + sizeof(int)]; + char repeat_str[sizeof(void *) + sizeof(int)]; + char release_str[sizeof(void *) + sizeof(int)]; + } kbd; + } u; +}; + +static LIST_HEAD(logical_inputs); /* list of all defined logical inputs */ + +/* physical contacts history + * Physical contacts are a 45 bits string of 9 groups of 5 bits each. + * The 8 lower groups correspond to output bits 0 to 7, and the 9th group + * corresponds to the ground. + * Within each group, bits are stored in the same order as read on the port : + * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0). + * So, each __u64 is represented like this : + * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE + * <-----unused------> + */ + +/* what has just been read from the I/O ports */ +static __u64 phys_read; +/* previous phys_read */ +static __u64 phys_read_prev; +/* stabilized phys_read (phys_read|phys_read_prev) */ +static __u64 phys_curr; +/* previous phys_curr */ +static __u64 phys_prev; +/* 0 means that at least one logical signal needs be computed */ +static char inputs_stable; + +/* these variables are specific to the keypad */ +static struct { + bool enabled; +} keypad; + +static char keypad_buffer[KEYPAD_BUFFER]; +static int keypad_buflen; +static int keypad_start; +static char keypressed; +static wait_queue_head_t keypad_read_wait; + +/* lcd-specific variables */ +static struct { + bool enabled; + bool initialized; + bool must_clear; + + int height; + int width; + int bwidth; + int hwidth; + int charset; + int proto; + int light_tempo; + + /* TODO: use union here? */ + struct { + int e; + int rs; + int rw; + int cl; + int da; + int bl; + } pins; + + /* contains the LCD config state */ + unsigned long int flags; + + /* Contains the LCD X and Y offset */ + struct { + unsigned long int x; + unsigned long int y; + } addr; + + /* Current escape sequence and it's length or -1 if outside */ + struct { + char buf[LCD_ESCAPE_LEN + 1]; + int len; + } esc_seq; +} lcd; + +/* Needed only for init */ +static int selected_lcd_type = NOT_SET; + +/* + * Bit masks to convert LCD signals to parallel port outputs. + * _d_ are values for data port, _c_ are for control port. + * [0] = signal OFF, [1] = signal ON, [2] = mask + */ +#define BIT_CLR 0 +#define BIT_SET 1 +#define BIT_MSK 2 +#define BIT_STATES 3 +/* + * one entry for each bit on the LCD + */ +#define LCD_BIT_E 0 +#define LCD_BIT_RS 1 +#define LCD_BIT_RW 2 +#define LCD_BIT_BL 3 +#define LCD_BIT_CL 4 +#define LCD_BIT_DA 5 +#define LCD_BITS 6 + +/* + * each bit can be either connected to a DATA or CTRL port + */ +#define LCD_PORT_C 0 +#define LCD_PORT_D 1 +#define LCD_PORTS 2 + +static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; + +/* + * LCD protocols + */ +#define LCD_PROTO_PARALLEL 0 +#define LCD_PROTO_SERIAL 1 +#define LCD_PROTO_TI_DA8XX_LCD 2 + +/* + * LCD character sets + */ +#define LCD_CHARSET_NORMAL 0 +#define LCD_CHARSET_KS0074 1 + +/* + * LCD types + */ +#define LCD_TYPE_NONE 0 +#define LCD_TYPE_CUSTOM 1 +#define LCD_TYPE_OLD 2 +#define LCD_TYPE_KS0074 3 +#define LCD_TYPE_HANTRONIX 4 +#define LCD_TYPE_NEXCOM 5 + +/* + * keypad types + */ +#define KEYPAD_TYPE_NONE 0 +#define KEYPAD_TYPE_OLD 1 +#define KEYPAD_TYPE_NEW 2 +#define KEYPAD_TYPE_NEXCOM 3 + +/* + * panel profiles + */ +#define PANEL_PROFILE_CUSTOM 0 +#define PANEL_PROFILE_OLD 1 +#define PANEL_PROFILE_NEW 2 +#define PANEL_PROFILE_HANTRONIX 3 +#define PANEL_PROFILE_NEXCOM 4 +#define PANEL_PROFILE_LARGE 5 + +/* + * Construct custom config from the kernel's configuration + */ +#define DEFAULT_PARPORT 0 +#define DEFAULT_PROFILE PANEL_PROFILE_LARGE +#define DEFAULT_KEYPAD_TYPE KEYPAD_TYPE_OLD +#define DEFAULT_LCD_TYPE LCD_TYPE_OLD +#define DEFAULT_LCD_HEIGHT 2 +#define DEFAULT_LCD_WIDTH 40 +#define DEFAULT_LCD_BWIDTH 40 +#define DEFAULT_LCD_HWIDTH 64 +#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL +#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL + +#define DEFAULT_LCD_PIN_E PIN_AUTOLF +#define DEFAULT_LCD_PIN_RS PIN_SELECP +#define DEFAULT_LCD_PIN_RW PIN_INITP +#define DEFAULT_LCD_PIN_SCL PIN_STROBE +#define DEFAULT_LCD_PIN_SDA PIN_D0 +#define DEFAULT_LCD_PIN_BL PIN_NOT_SET + +#ifdef CONFIG_PANEL_PARPORT +#undef DEFAULT_PARPORT +#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT +#endif + +#ifdef CONFIG_PANEL_PROFILE +#undef DEFAULT_PROFILE +#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE +#endif + +#if DEFAULT_PROFILE == 0 /* custom */ +#ifdef CONFIG_PANEL_KEYPAD +#undef DEFAULT_KEYPAD_TYPE +#define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD +#endif + +#ifdef CONFIG_PANEL_LCD +#undef DEFAULT_LCD_TYPE +#define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD +#endif + +#ifdef CONFIG_PANEL_LCD_HEIGHT +#undef DEFAULT_LCD_HEIGHT +#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT +#endif + +#ifdef CONFIG_PANEL_LCD_WIDTH +#undef DEFAULT_LCD_WIDTH +#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH +#endif + +#ifdef CONFIG_PANEL_LCD_BWIDTH +#undef DEFAULT_LCD_BWIDTH +#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH +#endif + +#ifdef CONFIG_PANEL_LCD_HWIDTH +#undef DEFAULT_LCD_HWIDTH +#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH +#endif + +#ifdef CONFIG_PANEL_LCD_CHARSET +#undef DEFAULT_LCD_CHARSET +#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET +#endif + +#ifdef CONFIG_PANEL_LCD_PROTO +#undef DEFAULT_LCD_PROTO +#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_E +#undef DEFAULT_LCD_PIN_E +#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_RS +#undef DEFAULT_LCD_PIN_RS +#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_RW +#undef DEFAULT_LCD_PIN_RW +#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_SCL +#undef DEFAULT_LCD_PIN_SCL +#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_SDA +#undef DEFAULT_LCD_PIN_SDA +#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA +#endif + +#ifdef CONFIG_PANEL_LCD_PIN_BL +#undef DEFAULT_LCD_PIN_BL +#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL +#endif + +#endif /* DEFAULT_PROFILE == 0 */ + +/* global variables */ + +/* Device single-open policy control */ +static atomic_t lcd_available = ATOMIC_INIT(1); +static atomic_t keypad_available = ATOMIC_INIT(1); + +static struct pardevice *pprt; + +static int keypad_initialized; + +static void (*lcd_write_cmd)(int); +static void (*lcd_write_data)(int); +static void (*lcd_clear_fast)(void); + +static DEFINE_SPINLOCK(pprt_lock); +static struct timer_list scan_timer; + +MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver"); + +static int parport = DEFAULT_PARPORT; +module_param(parport, int, 0000); +MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)"); + +static int profile = DEFAULT_PROFILE; +module_param(profile, int, 0000); +MODULE_PARM_DESC(profile, + "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; " + "4=16x2 nexcom; default=40x2, old kp"); + +static int keypad_type = NOT_SET; +module_param(keypad_type, int, 0000); +MODULE_PARM_DESC(keypad_type, + "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys"); + +static int lcd_type = NOT_SET; +module_param(lcd_type, int, 0000); +MODULE_PARM_DESC(lcd_type, + "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom"); + +static int lcd_height = NOT_SET; +module_param(lcd_height, int, 0000); +MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD"); + +static int lcd_width = NOT_SET; +module_param(lcd_width, int, 0000); +MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD"); + +static int lcd_bwidth = NOT_SET; /* internal buffer width (usually 40) */ +module_param(lcd_bwidth, int, 0000); +MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)"); + +static int lcd_hwidth = NOT_SET; /* hardware buffer width (usually 64) */ +module_param(lcd_hwidth, int, 0000); +MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)"); + +static int lcd_charset = NOT_SET; +module_param(lcd_charset, int, 0000); +MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074"); + +static int lcd_proto = NOT_SET; +module_param(lcd_proto, int, 0000); +MODULE_PARM_DESC(lcd_proto, + "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface"); + +/* + * These are the parallel port pins the LCD control signals are connected to. + * Set this to 0 if the signal is not used. Set it to its opposite value + * (negative) if the signal is negated. -MAXINT is used to indicate that the + * pin has not been explicitly specified. + * + * WARNING! no check will be performed about collisions with keypad ! + */ + +static int lcd_e_pin = PIN_NOT_SET; +module_param(lcd_e_pin, int, 0000); +MODULE_PARM_DESC(lcd_e_pin, + "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)"); + +static int lcd_rs_pin = PIN_NOT_SET; +module_param(lcd_rs_pin, int, 0000); +MODULE_PARM_DESC(lcd_rs_pin, + "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)"); + +static int lcd_rw_pin = PIN_NOT_SET; +module_param(lcd_rw_pin, int, 0000); +MODULE_PARM_DESC(lcd_rw_pin, + "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)"); + +static int lcd_cl_pin = PIN_NOT_SET; +module_param(lcd_cl_pin, int, 0000); +MODULE_PARM_DESC(lcd_cl_pin, + "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)"); + +static int lcd_da_pin = PIN_NOT_SET; +module_param(lcd_da_pin, int, 0000); +MODULE_PARM_DESC(lcd_da_pin, + "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)"); + +static int lcd_bl_pin = PIN_NOT_SET; +module_param(lcd_bl_pin, int, 0000); +MODULE_PARM_DESC(lcd_bl_pin, + "# of the // port pin connected to LCD backlight, with polarity (-17..17)"); + +/* Deprecated module parameters - consider not using them anymore */ + +static int lcd_enabled = NOT_SET; +module_param(lcd_enabled, int, 0000); +MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead"); + +static int keypad_enabled = NOT_SET; +module_param(keypad_enabled, int, 0000); +MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); + +static const unsigned char *lcd_char_conv; + +/* for some LCD drivers (ks0074) we need a charset conversion table. */ +static const unsigned char lcd_char_conv_ks0074[256] = { + /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */ + /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + /* 0x08 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + /* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + /* 0x18 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + /* 0x20 */ 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27, + /* 0x28 */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + /* 0x30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + /* 0x38 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + /* 0x40 */ 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + /* 0x48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + /* 0x50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + /* 0x58 */ 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4, + /* 0x60 */ 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + /* 0x68 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + /* 0x70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + /* 0x78 */ 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20, + /* 0x80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + /* 0x88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + /* 0x90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + /* 0x98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + /* 0xA0 */ 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f, + /* 0xA8 */ 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96, + /* 0xB0 */ 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd, + /* 0xB8 */ 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60, + /* 0xC0 */ 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9, + /* 0xC8 */ 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3, + /* 0xD0 */ 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78, + /* 0xD8 */ 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe, + /* 0xE0 */ 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8, + /* 0xE8 */ 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69, + /* 0xF0 */ 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25, + /* 0xF8 */ 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79, +}; + +static const char old_keypad_profile[][4][9] = { + {"S0", "Left\n", "Left\n", ""}, + {"S1", "Down\n", "Down\n", ""}, + {"S2", "Up\n", "Up\n", ""}, + {"S3", "Right\n", "Right\n", ""}, + {"S4", "Esc\n", "Esc\n", ""}, + {"S5", "Ret\n", "Ret\n", ""}, + {"", "", "", ""} +}; + +/* signals, press, repeat, release */ +static const char new_keypad_profile[][4][9] = { + {"S0", "Left\n", "Left\n", ""}, + {"S1", "Down\n", "Down\n", ""}, + {"S2", "Up\n", "Up\n", ""}, + {"S3", "Right\n", "Right\n", ""}, + {"S4s5", "", "Esc\n", "Esc\n"}, + {"s4S5", "", "Ret\n", "Ret\n"}, + {"S4S5", "Help\n", "", ""}, + /* add new signals above this line */ + {"", "", "", ""} +}; + +/* signals, press, repeat, release */ +static const char nexcom_keypad_profile[][4][9] = { + {"a-p-e-", "Down\n", "Down\n", ""}, + {"a-p-E-", "Ret\n", "Ret\n", ""}, + {"a-P-E-", "Esc\n", "Esc\n", ""}, + {"a-P-e-", "Up\n", "Up\n", ""}, + /* add new signals above this line */ + {"", "", "", ""} +}; + +static const char (*keypad_profile)[4][9] = old_keypad_profile; + +/* FIXME: this should be converted to a bit array containing signals states */ +static struct { + unsigned char e; /* parallel LCD E (data latch on falling edge) */ + unsigned char rs; /* parallel LCD RS (0 = cmd, 1 = data) */ + unsigned char rw; /* parallel LCD R/W (0 = W, 1 = R) */ + unsigned char bl; /* parallel LCD backlight (0 = off, 1 = on) */ + unsigned char cl; /* serial LCD clock (latch on rising edge) */ + unsigned char da; /* serial LCD data */ +} bits; + +static void init_scan_timer(void); + +/* sets data port bits according to current signals values */ +static int set_data_bits(void) +{ + int val, bit; + + val = r_dtr(pprt); + for (bit = 0; bit < LCD_BITS; bit++) + val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK]; + + val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e] + | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs] + | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw] + | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl] + | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl] + | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da]; + + w_dtr(pprt, val); + return val; +} + +/* sets ctrl port bits according to current signals values */ +static int set_ctrl_bits(void) +{ + int val, bit; + + val = r_ctr(pprt); + for (bit = 0; bit < LCD_BITS; bit++) + val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK]; + + val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e] + | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs] + | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw] + | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl] + | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl] + | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da]; + + w_ctr(pprt, val); + return val; +} + +/* sets ctrl & data port bits according to current signals values */ +static void panel_set_bits(void) +{ + set_data_bits(); + set_ctrl_bits(); +} + +/* + * Converts a parallel port pin (from -25 to 25) to data and control ports + * masks, and data and control port bits. The signal will be considered + * unconnected if it's on pin 0 or an invalid pin (<-25 or >25). + * + * Result will be used this way : + * out(dport, in(dport) & d_val[2] | d_val[signal_state]) + * out(cport, in(cport) & c_val[2] | c_val[signal_state]) + */ +static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val) +{ + int d_bit, c_bit, inv; + + d_val[0] = 0; + c_val[0] = 0; + d_val[1] = 0; + c_val[1] = 0; + d_val[2] = 0xFF; + c_val[2] = 0xFF; + + if (pin == 0) + return; + + inv = (pin < 0); + if (inv) + pin = -pin; + + d_bit = 0; + c_bit = 0; + + switch (pin) { + case PIN_STROBE: /* strobe, inverted */ + c_bit = PNL_PSTROBE; + inv = !inv; + break; + case PIN_D0...PIN_D7: /* D0 - D7 = 2 - 9 */ + d_bit = 1 << (pin - 2); + break; + case PIN_AUTOLF: /* autofeed, inverted */ + c_bit = PNL_PAUTOLF; + inv = !inv; + break; + case PIN_INITP: /* init, direct */ + c_bit = PNL_PINITP; + break; + case PIN_SELECP: /* select_in, inverted */ + c_bit = PNL_PSELECP; + inv = !inv; + break; + default: /* unknown pin, ignore */ + break; + } + + if (c_bit) { + c_val[2] &= ~c_bit; + c_val[!inv] = c_bit; + } else if (d_bit) { + d_val[2] &= ~d_bit; + d_val[!inv] = d_bit; + } +} + +/* sleeps that many milliseconds with a reschedule */ +static void long_sleep(int ms) +{ + if (in_interrupt()) + mdelay(ms); + else + schedule_timeout_interruptible(msecs_to_jiffies(ms)); +} + +/* + * send a serial byte to the LCD panel. The caller is responsible for locking + * if needed. + */ +static void lcd_send_serial(int byte) +{ + int bit; + + /* + * the data bit is set on D0, and the clock on STROBE. + * LCD reads D0 on STROBE's rising edge. + */ + for (bit = 0; bit < 8; bit++) { + bits.cl = BIT_CLR; /* CLK low */ + panel_set_bits(); + bits.da = byte & 1; + panel_set_bits(); + udelay(2); /* maintain the data during 2 us before CLK up */ + bits.cl = BIT_SET; /* CLK high */ + panel_set_bits(); + udelay(1); /* maintain the strobe during 1 us */ + byte >>= 1; + } +} + +/* turn the backlight on or off */ +static void lcd_backlight(int on) +{ + if (lcd.pins.bl == PIN_NONE) + return; + + /* The backlight is activated by setting the AUTOFEED line to +5V */ + spin_lock_irq(&pprt_lock); + bits.bl = on; + panel_set_bits(); + spin_unlock_irq(&pprt_lock); +} + +/* send a command to the LCD panel in serial mode */ +static void lcd_write_cmd_s(int cmd) +{ + spin_lock_irq(&pprt_lock); + lcd_send_serial(0x1F); /* R/W=W, RS=0 */ + lcd_send_serial(cmd & 0x0F); + lcd_send_serial((cmd >> 4) & 0x0F); + udelay(40); /* the shortest command takes at least 40 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send data to the LCD panel in serial mode */ +static void lcd_write_data_s(int data) +{ + spin_lock_irq(&pprt_lock); + lcd_send_serial(0x5F); /* R/W=W, RS=1 */ + lcd_send_serial(data & 0x0F); + lcd_send_serial((data >> 4) & 0x0F); + udelay(40); /* the shortest data takes at least 40 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send a command to the LCD panel in 8 bits parallel mode */ +static void lcd_write_cmd_p8(int cmd) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the data port */ + w_dtr(pprt, cmd); + udelay(20); /* maintain the data during 20 us before the strobe */ + + bits.e = BIT_SET; + bits.rs = BIT_CLR; + bits.rw = BIT_CLR; + set_ctrl_bits(); + + udelay(40); /* maintain the strobe during 40 us */ + + bits.e = BIT_CLR; + set_ctrl_bits(); + + udelay(120); /* the shortest command takes at least 120 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send data to the LCD panel in 8 bits parallel mode */ +static void lcd_write_data_p8(int data) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the data port */ + w_dtr(pprt, data); + udelay(20); /* maintain the data during 20 us before the strobe */ + + bits.e = BIT_SET; + bits.rs = BIT_SET; + bits.rw = BIT_CLR; + set_ctrl_bits(); + + udelay(40); /* maintain the strobe during 40 us */ + + bits.e = BIT_CLR; + set_ctrl_bits(); + + udelay(45); /* the shortest data takes at least 45 us */ + spin_unlock_irq(&pprt_lock); +} + +/* send a command to the TI LCD panel */ +static void lcd_write_cmd_tilcd(int cmd) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the control port */ + w_ctr(pprt, cmd); + udelay(60); + spin_unlock_irq(&pprt_lock); +} + +/* send data to the TI LCD panel */ +static void lcd_write_data_tilcd(int data) +{ + spin_lock_irq(&pprt_lock); + /* present the data to the data port */ + w_dtr(pprt, data); + udelay(60); + spin_unlock_irq(&pprt_lock); +} + +static void lcd_gotoxy(void) +{ + lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR + | (lcd.addr.y ? lcd.hwidth : 0) + /* + * we force the cursor to stay at the end of the + * line if it wants to go farther + */ + | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x & + (lcd.hwidth - 1) : lcd.bwidth - 1)); +} + +static void lcd_print(char c) +{ + if (lcd.addr.x < lcd.bwidth) { + if (lcd_char_conv) + c = lcd_char_conv[(unsigned char)c]; + lcd_write_data(c); + lcd.addr.x++; + } + /* prevents the cursor from wrapping onto the next line */ + if (lcd.addr.x == lcd.bwidth) + lcd_gotoxy(); +} + +/* fills the display with spaces and resets X/Y */ +static void lcd_clear_fast_s(void) +{ + int pos; + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + + spin_lock_irq(&pprt_lock); + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { + lcd_send_serial(0x5F); /* R/W=W, RS=1 */ + lcd_send_serial(' ' & 0x0F); + lcd_send_serial((' ' >> 4) & 0x0F); + /* the shortest data takes at least 40 us */ + udelay(40); + } + spin_unlock_irq(&pprt_lock); + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); +} + +/* fills the display with spaces and resets X/Y */ +static void lcd_clear_fast_p8(void) +{ + int pos; + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + + spin_lock_irq(&pprt_lock); + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { + /* present the data to the data port */ + w_dtr(pprt, ' '); + + /* maintain the data during 20 us before the strobe */ + udelay(20); + + bits.e = BIT_SET; + bits.rs = BIT_SET; + bits.rw = BIT_CLR; + set_ctrl_bits(); + + /* maintain the strobe during 40 us */ + udelay(40); + + bits.e = BIT_CLR; + set_ctrl_bits(); + + /* the shortest data takes at least 45 us */ + udelay(45); + } + spin_unlock_irq(&pprt_lock); + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); +} + +/* fills the display with spaces and resets X/Y */ +static void lcd_clear_fast_tilcd(void) +{ + int pos; + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + + spin_lock_irq(&pprt_lock); + for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { + /* present the data to the data port */ + w_dtr(pprt, ' '); + udelay(60); + } + + spin_unlock_irq(&pprt_lock); + + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); +} + +/* clears the display and resets X/Y */ +static void lcd_clear_display(void) +{ + lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR); + lcd.addr.x = 0; + lcd.addr.y = 0; + /* we must wait a few milliseconds (15) */ + long_sleep(15); +} + +static void lcd_init_display(void) +{ + lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0) + | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B; + + long_sleep(20); /* wait 20 ms after power-up for the paranoid */ + + /* 8bits, 1 line, small fonts; let's do it 3 times */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); + long_sleep(10); + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); + long_sleep(10); + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); + long_sleep(10); + + /* set font height and lines number */ + lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) + | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0) + ); + long_sleep(10); + + /* display off, cursor off, blink off */ + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL); + long_sleep(10); + + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */ + | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0) + ); + + lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); + + long_sleep(10); + + /* entry mode set : increment, cursor shifting */ + lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC); + + lcd_clear_display(); +} + +/* + * These are the file operation function for user access to /dev/lcd + * This function can also be called from inside the kernel, by + * setting file and ppos to NULL. + * + */ + +static inline int handle_lcd_special_code(void) +{ + /* LCD special codes */ + + int processed = 0; + + char *esc = lcd.esc_seq.buf + 2; + int oldflags = lcd.flags; + + /* check for display mode flags */ + switch (*esc) { + case 'D': /* Display ON */ + lcd.flags |= LCD_FLAG_D; + processed = 1; + break; + case 'd': /* Display OFF */ + lcd.flags &= ~LCD_FLAG_D; + processed = 1; + break; + case 'C': /* Cursor ON */ + lcd.flags |= LCD_FLAG_C; + processed = 1; + break; + case 'c': /* Cursor OFF */ + lcd.flags &= ~LCD_FLAG_C; + processed = 1; + break; + case 'B': /* Blink ON */ + lcd.flags |= LCD_FLAG_B; + processed = 1; + break; + case 'b': /* Blink OFF */ + lcd.flags &= ~LCD_FLAG_B; + processed = 1; + break; + case '+': /* Back light ON */ + lcd.flags |= LCD_FLAG_L; + processed = 1; + break; + case '-': /* Back light OFF */ + lcd.flags &= ~LCD_FLAG_L; + processed = 1; + break; + case '*': + /* flash back light using the keypad timer */ + if (scan_timer.function) { + if (lcd.light_tempo == 0 && + ((lcd.flags & LCD_FLAG_L) == 0)) + lcd_backlight(1); + lcd.light_tempo = FLASH_LIGHT_TEMPO; + } + processed = 1; + break; + case 'f': /* Small Font */ + lcd.flags &= ~LCD_FLAG_F; + processed = 1; + break; + case 'F': /* Large Font */ + lcd.flags |= LCD_FLAG_F; + processed = 1; + break; + case 'n': /* One Line */ + lcd.flags &= ~LCD_FLAG_N; + processed = 1; + break; + case 'N': /* Two Lines */ + lcd.flags |= LCD_FLAG_N; + break; + case 'l': /* Shift Cursor Left */ + if (lcd.addr.x > 0) { + /* back one char if not at end of line */ + if (lcd.addr.x < lcd.bwidth) + lcd_write_cmd(LCD_CMD_SHIFT); + lcd.addr.x--; + } + processed = 1; + break; + case 'r': /* shift cursor right */ + if (lcd.addr.x < lcd.width) { + /* allow the cursor to pass the end of the line */ + if (lcd.addr.x < (lcd.bwidth - 1)) + lcd_write_cmd(LCD_CMD_SHIFT | + LCD_CMD_SHIFT_RIGHT); + lcd.addr.x++; + } + processed = 1; + break; + case 'L': /* shift display left */ + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT); + processed = 1; + break; + case 'R': /* shift display right */ + lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT | + LCD_CMD_SHIFT_RIGHT); + processed = 1; + break; + case 'k': { /* kill end of line */ + int x; + + for (x = lcd.addr.x; x < lcd.bwidth; x++) + lcd_write_data(' '); + + /* restore cursor position */ + lcd_gotoxy(); + processed = 1; + break; + } + case 'I': /* reinitialize display */ + lcd_init_display(); + processed = 1; + break; + case 'G': { + /* Generator : LGcxxxxx...xx; must have between '0' + * and '7', representing the numerical ASCII code of the + * redefined character, and a sequence of 16 + * hex digits representing 8 bytes for each character. + * Most LCDs will only use 5 lower bits of the 7 first + * bytes. + */ + + unsigned char cgbytes[8]; + unsigned char cgaddr; + int cgoffset; + int shift; + char value; + int addr; + + if (!strchr(esc, ';')) + break; + + esc++; + + cgaddr = *(esc++) - '0'; + if (cgaddr > 7) { + processed = 1; + break; + } + + cgoffset = 0; + shift = 0; + value = 0; + while (*esc && cgoffset < 8) { + shift ^= 4; + if (*esc >= '0' && *esc <= '9') { + value |= (*esc - '0') << shift; + } else if (*esc >= 'A' && *esc <= 'Z') { + value |= (*esc - 'A' + 10) << shift; + } else if (*esc >= 'a' && *esc <= 'z') { + value |= (*esc - 'a' + 10) << shift; + } else { + esc++; + continue; + } + + if (shift == 0) { + cgbytes[cgoffset++] = value; + value = 0; + } + + esc++; + } + + lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); + for (addr = 0; addr < cgoffset; addr++) + lcd_write_data(cgbytes[addr]); + + /* ensures that we stop writing to CGRAM */ + lcd_gotoxy(); + processed = 1; + break; + } + case 'x': /* gotoxy : LxXXX[yYYY]; */ + case 'y': /* gotoxy : LyYYY[xXXX]; */ + if (!strchr(esc, ';')) + break; + + while (*esc) { + if (*esc == 'x') { + esc++; + if (kstrtoul(esc, 10, &lcd.addr.x) < 0) + break; + } else if (*esc == 'y') { + esc++; + if (kstrtoul(esc, 10, &lcd.addr.y) < 0) + break; + } else { + break; + } + } + + lcd_gotoxy(); + processed = 1; + break; + } + + /* TODO: This indent party here got ugly, clean it! */ + /* Check whether one flag was changed */ + if (oldflags != lcd.flags) { + /* check whether one of B,C,D flags were changed */ + if ((oldflags ^ lcd.flags) & + (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) + /* set display mode */ + lcd_write_cmd(LCD_CMD_DISPLAY_CTRL + | ((lcd.flags & LCD_FLAG_D) + ? LCD_CMD_DISPLAY_ON : 0) + | ((lcd.flags & LCD_FLAG_C) + ? LCD_CMD_CURSOR_ON : 0) + | ((lcd.flags & LCD_FLAG_B) + ? LCD_CMD_BLINK_ON : 0)); + /* check whether one of F,N flags was changed */ + else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) + lcd_write_cmd(LCD_CMD_FUNCTION_SET + | LCD_CMD_DATA_LEN_8BITS + | ((lcd.flags & LCD_FLAG_F) + ? LCD_CMD_TWO_LINES : 0) + | ((lcd.flags & LCD_FLAG_N) + ? LCD_CMD_FONT_5X10_DOTS + : 0)); + /* check whether L flag was changed */ + else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { + if (lcd.flags & (LCD_FLAG_L)) + lcd_backlight(1); + else if (lcd.light_tempo == 0) + /* + * switch off the light only when the tempo + * lighting is gone + */ + lcd_backlight(0); + } + } + + return processed; +} + +static void lcd_write_char(char c) +{ + /* first, we'll test if we're in escape mode */ + if ((c != '\n') && lcd.esc_seq.len >= 0) { + /* yes, let's add this char to the buffer */ + lcd.esc_seq.buf[lcd.esc_seq.len++] = c; + lcd.esc_seq.buf[lcd.esc_seq.len] = 0; + } else { + /* aborts any previous escape sequence */ + lcd.esc_seq.len = -1; + + switch (c) { + case LCD_ESCAPE_CHAR: + /* start of an escape sequence */ + lcd.esc_seq.len = 0; + lcd.esc_seq.buf[lcd.esc_seq.len] = 0; + break; + case '\b': + /* go back one char and clear it */ + if (lcd.addr.x > 0) { + /* + * check if we're not at the + * end of the line + */ + if (lcd.addr.x < lcd.bwidth) + /* back one char */ + lcd_write_cmd(LCD_CMD_SHIFT); + lcd.addr.x--; + } + /* replace with a space */ + lcd_write_data(' '); + /* back one char again */ + lcd_write_cmd(LCD_CMD_SHIFT); + break; + case '\014': + /* quickly clear the display */ + lcd_clear_fast(); + break; + case '\n': + /* + * flush the remainder of the current line and + * go to the beginning of the next line + */ + for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++) + lcd_write_data(' '); + lcd.addr.x = 0; + lcd.addr.y = (lcd.addr.y + 1) % lcd.height; + lcd_gotoxy(); + break; + case '\r': + /* go to the beginning of the same line */ + lcd.addr.x = 0; + lcd_gotoxy(); + break; + case '\t': + /* print a space instead of the tab */ + lcd_print(' '); + break; + default: + /* simply print this char */ + lcd_print(c); + break; + } + } + + /* + * now we'll see if we're in an escape mode and if the current + * escape sequence can be understood. + */ + if (lcd.esc_seq.len >= 2) { + int processed = 0; + + if (!strcmp(lcd.esc_seq.buf, "[2J")) { + /* clear the display */ + lcd_clear_fast(); + processed = 1; + } else if (!strcmp(lcd.esc_seq.buf, "[H")) { + /* cursor to home */ + lcd.addr.x = 0; + lcd.addr.y = 0; + lcd_gotoxy(); + processed = 1; + } + /* codes starting with ^[[L */ + else if ((lcd.esc_seq.len >= 3) && + (lcd.esc_seq.buf[0] == '[') && + (lcd.esc_seq.buf[1] == 'L')) { + processed = handle_lcd_special_code(); + } + + /* LCD special escape codes */ + /* + * flush the escape sequence if it's been processed + * or if it is getting too long. + */ + if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN)) + lcd.esc_seq.len = -1; + } /* escape codes */ +} + +static ssize_t lcd_write(struct file *file, + const char __user *buf, size_t count, loff_t *ppos) +{ + const char __user *tmp = buf; + char c; + + for (; count-- > 0; (*ppos)++, tmp++) { + if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) + /* + * let's be a little nice with other processes + * that need some CPU + */ + schedule(); + + if (get_user(c, tmp)) + return -EFAULT; + + lcd_write_char(c); + } + + return tmp - buf; +} + +static int lcd_open(struct inode *inode, struct file *file) +{ + if (!atomic_dec_and_test(&lcd_available)) + return -EBUSY; /* open only once at a time */ + + if (file->f_mode & FMODE_READ) /* device is write-only */ + return -EPERM; + + if (lcd.must_clear) { + lcd_clear_display(); + lcd.must_clear = false; + } + return nonseekable_open(inode, file); +} + +static int lcd_release(struct inode *inode, struct file *file) +{ + atomic_inc(&lcd_available); + return 0; +} + +static const struct file_operations lcd_fops = { + .write = lcd_write, + .open = lcd_open, + .release = lcd_release, + .llseek = no_llseek, +}; + +static struct miscdevice lcd_dev = { + .minor = LCD_MINOR, + .name = "lcd", + .fops = &lcd_fops, +}; + +/* public function usable from the kernel for any purpose */ +static void panel_lcd_print(const char *s) +{ + const char *tmp = s; + int count = strlen(s); + + if (lcd.enabled && lcd.initialized) { + for (; count-- > 0; tmp++) { + if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) + /* + * let's be a little nice with other processes + * that need some CPU + */ + schedule(); + + lcd_write_char(*tmp); + } + } +} + +/* initialize the LCD driver */ +static void lcd_init(void) +{ + switch (selected_lcd_type) { + case LCD_TYPE_OLD: + /* parallel mode, 8 bits */ + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_STROBE; + lcd.pins.rs = PIN_AUTOLF; + + lcd.width = 40; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; + break; + case LCD_TYPE_KS0074: + /* serial mode, ks0074 */ + lcd.proto = LCD_PROTO_SERIAL; + lcd.charset = LCD_CHARSET_KS0074; + lcd.pins.bl = PIN_AUTOLF; + lcd.pins.cl = PIN_STROBE; + lcd.pins.da = PIN_D0; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 16; + lcd.height = 2; + break; + case LCD_TYPE_NEXCOM: + /* parallel mode, 8 bits, generic */ + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_AUTOLF; + lcd.pins.rs = PIN_SELECP; + lcd.pins.rw = PIN_INITP; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; + break; + case LCD_TYPE_CUSTOM: + /* customer-defined */ + lcd.proto = DEFAULT_LCD_PROTO; + lcd.charset = DEFAULT_LCD_CHARSET; + /* default geometry will be set later */ + break; + case LCD_TYPE_HANTRONIX: + /* parallel mode, 8 bits, hantronix-like */ + default: + lcd.proto = LCD_PROTO_PARALLEL; + lcd.charset = LCD_CHARSET_NORMAL; + lcd.pins.e = PIN_STROBE; + lcd.pins.rs = PIN_SELECP; + + lcd.width = 16; + lcd.bwidth = 40; + lcd.hwidth = 64; + lcd.height = 2; + break; + } + + /* Overwrite with module params set on loading */ + if (lcd_height != NOT_SET) + lcd.height = lcd_height; + if (lcd_width != NOT_SET) + lcd.width = lcd_width; + if (lcd_bwidth != NOT_SET) + lcd.bwidth = lcd_bwidth; + if (lcd_hwidth != NOT_SET) + lcd.hwidth = lcd_hwidth; + if (lcd_charset != NOT_SET) + lcd.charset = lcd_charset; + if (lcd_proto != NOT_SET) + lcd.proto = lcd_proto; + if (lcd_e_pin != PIN_NOT_SET) + lcd.pins.e = lcd_e_pin; + if (lcd_rs_pin != PIN_NOT_SET) + lcd.pins.rs = lcd_rs_pin; + if (lcd_rw_pin != PIN_NOT_SET) + lcd.pins.rw = lcd_rw_pin; + if (lcd_cl_pin != PIN_NOT_SET) + lcd.pins.cl = lcd_cl_pin; + if (lcd_da_pin != PIN_NOT_SET) + lcd.pins.da = lcd_da_pin; + if (lcd_bl_pin != PIN_NOT_SET) + lcd.pins.bl = lcd_bl_pin; + + /* this is used to catch wrong and default values */ + if (lcd.width <= 0) + lcd.width = DEFAULT_LCD_WIDTH; + if (lcd.bwidth <= 0) + lcd.bwidth = DEFAULT_LCD_BWIDTH; + if (lcd.hwidth <= 0) + lcd.hwidth = DEFAULT_LCD_HWIDTH; + if (lcd.height <= 0) + lcd.height = DEFAULT_LCD_HEIGHT; + + if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */ + lcd_write_cmd = lcd_write_cmd_s; + lcd_write_data = lcd_write_data_s; + lcd_clear_fast = lcd_clear_fast_s; + + if (lcd.pins.cl == PIN_NOT_SET) + lcd.pins.cl = DEFAULT_LCD_PIN_SCL; + if (lcd.pins.da == PIN_NOT_SET) + lcd.pins.da = DEFAULT_LCD_PIN_SDA; + + } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ + lcd_write_cmd = lcd_write_cmd_p8; + lcd_write_data = lcd_write_data_p8; + lcd_clear_fast = lcd_clear_fast_p8; + + if (lcd.pins.e == PIN_NOT_SET) + lcd.pins.e = DEFAULT_LCD_PIN_E; + if (lcd.pins.rs == PIN_NOT_SET) + lcd.pins.rs = DEFAULT_LCD_PIN_RS; + if (lcd.pins.rw == PIN_NOT_SET) + lcd.pins.rw = DEFAULT_LCD_PIN_RW; + } else { + lcd_write_cmd = lcd_write_cmd_tilcd; + lcd_write_data = lcd_write_data_tilcd; + lcd_clear_fast = lcd_clear_fast_tilcd; + } + + if (lcd.pins.bl == PIN_NOT_SET) + lcd.pins.bl = DEFAULT_LCD_PIN_BL; + + if (lcd.pins.e == PIN_NOT_SET) + lcd.pins.e = PIN_NONE; + if (lcd.pins.rs == PIN_NOT_SET) + lcd.pins.rs = PIN_NONE; + if (lcd.pins.rw == PIN_NOT_SET) + lcd.pins.rw = PIN_NONE; + if (lcd.pins.bl == PIN_NOT_SET) + lcd.pins.bl = PIN_NONE; + if (lcd.pins.cl == PIN_NOT_SET) + lcd.pins.cl = PIN_NONE; + if (lcd.pins.da == PIN_NOT_SET) + lcd.pins.da = PIN_NONE; + + if (lcd.charset == NOT_SET) + lcd.charset = DEFAULT_LCD_CHARSET; + + if (lcd.charset == LCD_CHARSET_KS0074) + lcd_char_conv = lcd_char_conv_ks0074; + else + lcd_char_conv = NULL; + + if (lcd.pins.bl != PIN_NONE) + init_scan_timer(); + + pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], + lcd_bits[LCD_PORT_C][LCD_BIT_E]); + pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS], + lcd_bits[LCD_PORT_C][LCD_BIT_RS]); + pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW], + lcd_bits[LCD_PORT_C][LCD_BIT_RW]); + pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL], + lcd_bits[LCD_PORT_C][LCD_BIT_BL]); + pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL], + lcd_bits[LCD_PORT_C][LCD_BIT_CL]); + pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA], + lcd_bits[LCD_PORT_C][LCD_BIT_DA]); + + /* + * before this line, we must NOT send anything to the display. + * Since lcd_init_display() needs to write data, we have to + * enable mark the LCD initialized just before. + */ + lcd.initialized = true; + lcd_init_display(); + + /* display a short message */ +#ifdef CONFIG_PANEL_CHANGE_MESSAGE +#ifdef CONFIG_PANEL_BOOT_MESSAGE + panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE); +#endif +#else + panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-" + PANEL_VERSION); +#endif + lcd.addr.x = 0; + lcd.addr.y = 0; + /* clear the display on the next device opening */ + lcd.must_clear = true; + lcd_gotoxy(); +} + +/* + * These are the file operation function for user access to /dev/keypad + */ + +static ssize_t keypad_read(struct file *file, + char __user *buf, size_t count, loff_t *ppos) +{ + unsigned i = *ppos; + char __user *tmp = buf; + + if (keypad_buflen == 0) { + if (file->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(keypad_read_wait, + keypad_buflen != 0)) + return -EINTR; + } + + for (; count-- > 0 && (keypad_buflen > 0); + ++i, ++tmp, --keypad_buflen) { + put_user(keypad_buffer[keypad_start], tmp); + keypad_start = (keypad_start + 1) % KEYPAD_BUFFER; + } + *ppos = i; + + return tmp - buf; +} + +static int keypad_open(struct inode *inode, struct file *file) +{ + if (!atomic_dec_and_test(&keypad_available)) + return -EBUSY; /* open only once at a time */ + + if (file->f_mode & FMODE_WRITE) /* device is read-only */ + return -EPERM; + + keypad_buflen = 0; /* flush the buffer on opening */ + return 0; +} + +static int keypad_release(struct inode *inode, struct file *file) +{ + atomic_inc(&keypad_available); + return 0; +} + +static const struct file_operations keypad_fops = { + .read = keypad_read, /* read */ + .open = keypad_open, /* open */ + .release = keypad_release, /* close */ + .llseek = default_llseek, +}; + +static struct miscdevice keypad_dev = { + .minor = KEYPAD_MINOR, + .name = "keypad", + .fops = &keypad_fops, +}; + +static void keypad_send_key(const char *string, int max_len) +{ + /* send the key to the device only if a process is attached to it. */ + if (!atomic_read(&keypad_available)) { + while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { + keypad_buffer[(keypad_start + keypad_buflen++) % + KEYPAD_BUFFER] = *string++; + } + wake_up_interruptible(&keypad_read_wait); + } +} + +/* this function scans all the bits involving at least one logical signal, + * and puts the results in the bitfield "phys_read" (one bit per established + * contact), and sets "phys_read_prev" to "phys_read". + * + * Note: to debounce input signals, we will only consider as switched a signal + * which is stable across 2 measures. Signals which are different between two + * reads will be kept as they previously were in their logical form (phys_prev). + * A signal which has just switched will have a 1 in + * (phys_read ^ phys_read_prev). + */ +static void phys_scan_contacts(void) +{ + int bit, bitval; + char oldval; + char bitmask; + char gndmask; + + phys_prev = phys_curr; + phys_read_prev = phys_read; + phys_read = 0; /* flush all signals */ + + /* keep track of old value, with all outputs disabled */ + oldval = r_dtr(pprt) | scan_mask_o; + /* activate all keyboard outputs (active low) */ + w_dtr(pprt, oldval & ~scan_mask_o); + + /* will have a 1 for each bit set to gnd */ + bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; + /* disable all matrix signals */ + w_dtr(pprt, oldval); + + /* now that all outputs are cleared, the only active input bits are + * directly connected to the ground + */ + + /* 1 for each grounded input */ + gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; + + /* grounded inputs are signals 40-44 */ + phys_read |= (__u64)gndmask << 40; + + if (bitmask != gndmask) { + /* + * since clearing the outputs changed some inputs, we know + * that some input signals are currently tied to some outputs. + * So we'll scan them. + */ + for (bit = 0; bit < 8; bit++) { + bitval = BIT(bit); + + if (!(scan_mask_o & bitval)) /* skip unused bits */ + continue; + + w_dtr(pprt, oldval & ~bitval); /* enable this output */ + bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; + phys_read |= (__u64)bitmask << (5 * bit); + } + w_dtr(pprt, oldval); /* disable all outputs */ + } + /* + * this is easy: use old bits when they are flapping, + * use new ones when stable + */ + phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) | + (phys_read & ~(phys_read ^ phys_read_prev)); +} + +static inline int input_state_high(struct logical_input *input) +{ +#if 0 + /* FIXME: + * this is an invalid test. It tries to catch + * transitions from single-key to multiple-key, but + * doesn't take into account the contacts polarity. + * The only solution to the problem is to parse keys + * from the most complex to the simplest combinations, + * and mark them as 'caught' once a combination + * matches, then unmatch it for all other ones. + */ + + /* try to catch dangerous transitions cases : + * someone adds a bit, so this signal was a false + * positive resulting from a transition. We should + * invalidate the signal immediately and not call the + * release function. + * eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release. + */ + if (((phys_prev & input->mask) == input->value) && + ((phys_curr & input->mask) > input->value)) { + input->state = INPUT_ST_LOW; /* invalidate */ + return 1; + } +#endif + + if ((phys_curr & input->mask) == input->value) { + if ((input->type == INPUT_TYPE_STD) && + (input->high_timer == 0)) { + input->high_timer++; + if (input->u.std.press_fct) + input->u.std.press_fct(input->u.std.press_data); + } else if (input->type == INPUT_TYPE_KBD) { + /* will turn on the light */ + keypressed = 1; + + if (input->high_timer == 0) { + char *press_str = input->u.kbd.press_str; + + if (press_str[0]) { + int s = sizeof(input->u.kbd.press_str); + + keypad_send_key(press_str, s); + } + } + + if (input->u.kbd.repeat_str[0]) { + char *repeat_str = input->u.kbd.repeat_str; + + if (input->high_timer >= KEYPAD_REP_START) { + int s = sizeof(input->u.kbd.repeat_str); + + input->high_timer -= KEYPAD_REP_DELAY; + keypad_send_key(repeat_str, s); + } + /* we will need to come back here soon */ + inputs_stable = 0; + } + + if (input->high_timer < 255) + input->high_timer++; + } + return 1; + } + + /* else signal falling down. Let's fall through. */ + input->state = INPUT_ST_FALLING; + input->fall_timer = 0; + + return 0; +} + +static inline void input_state_falling(struct logical_input *input) +{ +#if 0 + /* FIXME !!! same comment as in input_state_high */ + if (((phys_prev & input->mask) == input->value) && + ((phys_curr & input->mask) > input->value)) { + input->state = INPUT_ST_LOW; /* invalidate */ + return; + } +#endif + + if ((phys_curr & input->mask) == input->value) { + if (input->type == INPUT_TYPE_KBD) { + /* will turn on the light */ + keypressed = 1; + + if (input->u.kbd.repeat_str[0]) { + char *repeat_str = input->u.kbd.repeat_str; + + if (input->high_timer >= KEYPAD_REP_START) { + int s = sizeof(input->u.kbd.repeat_str); + + input->high_timer -= KEYPAD_REP_DELAY; + keypad_send_key(repeat_str, s); + } + /* we will need to come back here soon */ + inputs_stable = 0; + } + + if (input->high_timer < 255) + input->high_timer++; + } + input->state = INPUT_ST_HIGH; + } else if (input->fall_timer >= input->fall_time) { + /* call release event */ + if (input->type == INPUT_TYPE_STD) { + void (*release_fct)(int) = input->u.std.release_fct; + + if (release_fct) + release_fct(input->u.std.release_data); + } else if (input->type == INPUT_TYPE_KBD) { + char *release_str = input->u.kbd.release_str; + + if (release_str[0]) { + int s = sizeof(input->u.kbd.release_str); + + keypad_send_key(release_str, s); + } + } + + input->state = INPUT_ST_LOW; + } else { + input->fall_timer++; + inputs_stable = 0; + } +} + +static void panel_process_inputs(void) +{ + struct list_head *item; + struct logical_input *input; + + keypressed = 0; + inputs_stable = 1; + list_for_each(item, &logical_inputs) { + input = list_entry(item, struct logical_input, list); + + switch (input->state) { + case INPUT_ST_LOW: + if ((phys_curr & input->mask) != input->value) + break; + /* if all needed ones were already set previously, + * this means that this logical signal has been + * activated by the releasing of another combined + * signal, so we don't want to match. + * eg: AB -(release B)-> A -(release A)-> 0 : + * don't match A. + */ + if ((phys_prev & input->mask) == input->value) + break; + input->rise_timer = 0; + input->state = INPUT_ST_RISING; + /* no break here, fall through */ + case INPUT_ST_RISING: + if ((phys_curr & input->mask) != input->value) { + input->state = INPUT_ST_LOW; + break; + } + if (input->rise_timer < input->rise_time) { + inputs_stable = 0; + input->rise_timer++; + break; + } + input->high_timer = 0; + input->state = INPUT_ST_HIGH; + /* no break here, fall through */ + case INPUT_ST_HIGH: + if (input_state_high(input)) + break; + /* no break here, fall through */ + case INPUT_ST_FALLING: + input_state_falling(input); + } + } +} + +static void panel_scan_timer(void) +{ + if (keypad.enabled && keypad_initialized) { + if (spin_trylock_irq(&pprt_lock)) { + phys_scan_contacts(); + + /* no need for the parport anymore */ + spin_unlock_irq(&pprt_lock); + } + + if (!inputs_stable || phys_curr != phys_prev) + panel_process_inputs(); + } + + if (lcd.enabled && lcd.initialized) { + if (keypressed) { + if (lcd.light_tempo == 0 && + ((lcd.flags & LCD_FLAG_L) == 0)) + lcd_backlight(1); + lcd.light_tempo = FLASH_LIGHT_TEMPO; + } else if (lcd.light_tempo > 0) { + lcd.light_tempo--; + if (lcd.light_tempo == 0 && + ((lcd.flags & LCD_FLAG_L) == 0)) + lcd_backlight(0); + } + } + + mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME); +} + +static void init_scan_timer(void) +{ + if (scan_timer.function) + return; /* already started */ + + setup_timer(&scan_timer, (void *)&panel_scan_timer, 0); + scan_timer.expires = jiffies + INPUT_POLL_TIME; + add_timer(&scan_timer); +} + +/* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits. + * if or are non-null, they will be or'ed with the bits + * corresponding to out and in bits respectively. + * returns 1 if ok, 0 if error (in which case, nothing is written). + */ +static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, + u8 *imask, u8 *omask) +{ + const char sigtab[] = "EeSsPpAaBb"; + u8 im, om; + __u64 m, v; + + om = 0; + im = 0; + m = 0ULL; + v = 0ULL; + while (*name) { + int in, out, bit, neg; + const char *idx; + + idx = strchr(sigtab, *name); + if (!idx) + return 0; /* input name not found */ + + in = idx - sigtab; + neg = (in & 1); /* odd (lower) names are negated */ + in >>= 1; + im |= BIT(in); + + name++; + if (*name >= '0' && *name <= '7') { + out = *name - '0'; + om |= BIT(out); + } else if (*name == '-') { + out = 8; + } else { + return 0; /* unknown bit name */ + } + + bit = (out * 5) + in; + + m |= 1ULL << bit; + if (!neg) + v |= 1ULL << bit; + name++; + } + *mask = m; + *value = v; + if (imask) + *imask |= im; + if (omask) + *omask |= om; + return 1; +} + +/* tries to bind a key to the signal name . The key will send the + * strings , , for these respective events. + * Returns the pointer to the new key if ok, NULL if the key could not be bound. + */ +static struct logical_input *panel_bind_key(const char *name, const char *press, + const char *repeat, + const char *release) +{ + struct logical_input *key; + + key = kzalloc(sizeof(*key), GFP_KERNEL); + if (!key) + return NULL; + + if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i, + &scan_mask_o)) { + kfree(key); + return NULL; + } + + key->type = INPUT_TYPE_KBD; + key->state = INPUT_ST_LOW; + key->rise_time = 1; + key->fall_time = 1; + + strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str)); + strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str)); + strncpy(key->u.kbd.release_str, release, + sizeof(key->u.kbd.release_str)); + list_add(&key->list, &logical_inputs); + return key; +} + +#if 0 +/* tries to bind a callback function to the signal name . The function + * will be called with the arg when the signal is + * activated, and so on for / + * Returns the pointer to the new signal if ok, NULL if the signal could not + * be bound. + */ +static struct logical_input *panel_bind_callback(char *name, + void (*press_fct)(int), + int press_data, + void (*release_fct)(int), + int release_data) +{ + struct logical_input *callback; + + callback = kmalloc(sizeof(*callback), GFP_KERNEL); + if (!callback) + return NULL; + + memset(callback, 0, sizeof(struct logical_input)); + if (!input_name2mask(name, &callback->mask, &callback->value, + &scan_mask_i, &scan_mask_o)) + return NULL; + + callback->type = INPUT_TYPE_STD; + callback->state = INPUT_ST_LOW; + callback->rise_time = 1; + callback->fall_time = 1; + callback->u.std.press_fct = press_fct; + callback->u.std.press_data = press_data; + callback->u.std.release_fct = release_fct; + callback->u.std.release_data = release_data; + list_add(&callback->list, &logical_inputs); + return callback; +} +#endif + +static void keypad_init(void) +{ + int keynum; + + init_waitqueue_head(&keypad_read_wait); + keypad_buflen = 0; /* flushes any eventual noisy keystroke */ + + /* Let's create all known keys */ + + for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) { + panel_bind_key(keypad_profile[keynum][0], + keypad_profile[keynum][1], + keypad_profile[keynum][2], + keypad_profile[keynum][3]); + } + + init_scan_timer(); + keypad_initialized = 1; +} + +/**************************************************/ +/* device initialization */ +/**************************************************/ + +static int panel_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (lcd.enabled && lcd.initialized) { + switch (code) { + case SYS_DOWN: + panel_lcd_print + ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+"); + break; + case SYS_HALT: + panel_lcd_print + ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+"); + break; + case SYS_POWER_OFF: + panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+"); + break; + default: + break; + } + } + return NOTIFY_DONE; +} + +static struct notifier_block panel_notifier = { + panel_notify_sys, + NULL, + 0 +}; + +static void panel_attach(struct parport *port) +{ + struct pardev_cb panel_cb; + + if (port->number != parport) + return; + + if (pprt) { + pr_err("%s: port->number=%d parport=%d, already registered!\n", + __func__, port->number, parport); + return; + } + + memset(&panel_cb, 0, sizeof(panel_cb)); + panel_cb.private = &pprt; + /* panel_cb.flags = 0 should be PARPORT_DEV_EXCL? */ + + pprt = parport_register_dev_model(port, "panel", &panel_cb, 0); + if (!pprt) { + pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n", + __func__, port->number, parport); + return; + } + + if (parport_claim(pprt)) { + pr_err("could not claim access to parport%d. Aborting.\n", + parport); + goto err_unreg_device; + } + + /* must init LCD first, just in case an IRQ from the keypad is + * generated at keypad init + */ + if (lcd.enabled) { + lcd_init(); + if (misc_register(&lcd_dev)) + goto err_unreg_device; + } + + if (keypad.enabled) { + keypad_init(); + if (misc_register(&keypad_dev)) + goto err_lcd_unreg; + } + register_reboot_notifier(&panel_notifier); + return; + +err_lcd_unreg: + if (lcd.enabled) + misc_deregister(&lcd_dev); +err_unreg_device: + parport_unregister_device(pprt); + pprt = NULL; +} + +static void panel_detach(struct parport *port) +{ + if (port->number != parport) + return; + + if (!pprt) { + pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n", + __func__, port->number, parport); + return; + } + if (scan_timer.function) + del_timer_sync(&scan_timer); + + if (pprt) { + if (keypad.enabled) { + misc_deregister(&keypad_dev); + keypad_initialized = 0; + } + + if (lcd.enabled) { + panel_lcd_print("\x0cLCD driver " PANEL_VERSION + "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); + misc_deregister(&lcd_dev); + lcd.initialized = false; + } + + /* TODO: free all input signals */ + parport_release(pprt); + parport_unregister_device(pprt); + pprt = NULL; + unregister_reboot_notifier(&panel_notifier); + } +} + +static struct parport_driver panel_driver = { + .name = "panel", + .match_port = panel_attach, + .detach = panel_detach, + .devmodel = true, +}; + +/* init function */ +static int __init panel_init_module(void) +{ + int selected_keypad_type = NOT_SET, err; + + /* take care of an eventual profile */ + switch (profile) { + case PANEL_PROFILE_CUSTOM: + /* custom profile */ + selected_keypad_type = DEFAULT_KEYPAD_TYPE; + selected_lcd_type = DEFAULT_LCD_TYPE; + break; + case PANEL_PROFILE_OLD: + /* 8 bits, 2*16, old keypad */ + selected_keypad_type = KEYPAD_TYPE_OLD; + selected_lcd_type = LCD_TYPE_OLD; + + /* TODO: This two are a little hacky, sort it out later */ + if (lcd_width == NOT_SET) + lcd_width = 16; + if (lcd_hwidth == NOT_SET) + lcd_hwidth = 16; + break; + case PANEL_PROFILE_NEW: + /* serial, 2*16, new keypad */ + selected_keypad_type = KEYPAD_TYPE_NEW; + selected_lcd_type = LCD_TYPE_KS0074; + break; + case PANEL_PROFILE_HANTRONIX: + /* 8 bits, 2*16 hantronix-like, no keypad */ + selected_keypad_type = KEYPAD_TYPE_NONE; + selected_lcd_type = LCD_TYPE_HANTRONIX; + break; + case PANEL_PROFILE_NEXCOM: + /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */ + selected_keypad_type = KEYPAD_TYPE_NEXCOM; + selected_lcd_type = LCD_TYPE_NEXCOM; + break; + case PANEL_PROFILE_LARGE: + /* 8 bits, 2*40, old keypad */ + selected_keypad_type = KEYPAD_TYPE_OLD; + selected_lcd_type = LCD_TYPE_OLD; + break; + } + + /* + * Overwrite selection with module param values (both keypad and lcd), + * where the deprecated params have lower prio. + */ + if (keypad_enabled != NOT_SET) + selected_keypad_type = keypad_enabled; + if (keypad_type != NOT_SET) + selected_keypad_type = keypad_type; + + keypad.enabled = (selected_keypad_type > 0); + + if (lcd_enabled != NOT_SET) + selected_lcd_type = lcd_enabled; + if (lcd_type != NOT_SET) + selected_lcd_type = lcd_type; + + lcd.enabled = (selected_lcd_type > 0); + + if (lcd.enabled) { + /* + * Init lcd struct with load-time values to preserve exact + * current functionality (at least for now). + */ + lcd.height = lcd_height; + lcd.width = lcd_width; + lcd.bwidth = lcd_bwidth; + lcd.hwidth = lcd_hwidth; + lcd.charset = lcd_charset; + lcd.proto = lcd_proto; + lcd.pins.e = lcd_e_pin; + lcd.pins.rs = lcd_rs_pin; + lcd.pins.rw = lcd_rw_pin; + lcd.pins.cl = lcd_cl_pin; + lcd.pins.da = lcd_da_pin; + lcd.pins.bl = lcd_bl_pin; + + /* Leave it for now, just in case */ + lcd.esc_seq.len = -1; + } + + switch (selected_keypad_type) { + case KEYPAD_TYPE_OLD: + keypad_profile = old_keypad_profile; + break; + case KEYPAD_TYPE_NEW: + keypad_profile = new_keypad_profile; + break; + case KEYPAD_TYPE_NEXCOM: + keypad_profile = nexcom_keypad_profile; + break; + default: + keypad_profile = NULL; + break; + } + + if (!lcd.enabled && !keypad.enabled) { + /* no device enabled, let's exit */ + pr_err("driver version " PANEL_VERSION " disabled.\n"); + return -ENODEV; + } + + err = parport_register_driver(&panel_driver); + if (err) { + pr_err("could not register with parport. Aborting.\n"); + return err; + } + + if (pprt) + pr_info("driver version " PANEL_VERSION + " registered on parport%d (io=0x%lx).\n", parport, + pprt->port->base); + else + pr_info("driver version " PANEL_VERSION + " not yet registered\n"); + return 0; +} + +static void __exit panel_cleanup_module(void) +{ + parport_unregister_driver(&panel_driver); +} + +module_init(panel_init_module); +module_exit(panel_cleanup_module); +MODULE_AUTHOR("Willy Tarreau"); +MODULE_LICENSE("GPL"); + +/* + * Local variables: + * c-indent-level: 4 + * tab-width: 8 + * End: + */ diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e80268ae8c9d..5f9a97a77393 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -30,8 +30,6 @@ source "drivers/staging/wlan-ng/Kconfig" source "drivers/staging/comedi/Kconfig" -source "drivers/staging/panel/Kconfig" - source "drivers/staging/rtl8192u/Kconfig" source "drivers/staging/rtl8192e/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ba160f1ec02d..dbab17e9d45c 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -7,7 +7,6 @@ obj-y += media/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_COMEDI) += comedi/ -obj-$(CONFIG_PANEL) += panel/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ diff --git a/drivers/staging/panel/Kconfig b/drivers/staging/panel/Kconfig deleted file mode 100644 index 3defa0133f2e..000000000000 --- a/drivers/staging/panel/Kconfig +++ /dev/null @@ -1,278 +0,0 @@ -config PANEL - tristate "Parallel port LCD/Keypad Panel support" - depends on PARPORT - ---help--- - Say Y here if you have an HD44780 or KS-0074 LCD connected to your - parallel port. This driver also features 4 and 6-key keypads. The LCD - is accessible through the /dev/lcd char device (10, 156), and the - keypad through /dev/keypad (10, 185). Both require misc device to be - enabled. This code can either be compiled as a module, or linked into - the kernel and started at boot. If you don't understand what all this - is about, say N. - -config PANEL_PARPORT - int "Default parallel port number (0=LPT1)" - depends on PANEL - range 0 255 - default "0" - ---help--- - This is the index of the parallel port the panel is connected to. One - driver instance only supports one parallel port, so if your keypad - and LCD are connected to two separate ports, you have to start two - modules with different arguments. Numbering starts with '0' for LPT1, - and so on. - -config PANEL_PROFILE - int "Default panel profile (0-5, 0=custom)" - depends on PANEL - range 0 5 - default "5" - ---help--- - To ease configuration, the driver supports different configuration - profiles for past and recent wirings. These profiles can also be - used to define an approximative configuration, completed by a few - other options. Here are the profiles : - - 0 = custom (see further) - 1 = 2x16 parallel LCD, old keypad - 2 = 2x16 serial LCD (KS-0074), new keypad - 3 = 2x16 parallel LCD (Hantronix), no keypad - 4 = 2x16 parallel LCD (Nexcom NSA1045) with Nexcom's keypad - 5 = 2x40 parallel LCD (old one), with old keypad - - Custom configurations allow you to define how your display is - wired to the parallel port, and how it works. This is only intended - for experts. - -config PANEL_KEYPAD - depends on PANEL && PANEL_PROFILE="0" - int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)" - range 0 3 - default 0 - ---help--- - This enables and configures a keypad connected to the parallel port. - The keys will be read from character device 10,185. Valid values are : - - 0 : do not enable this driver - 1 : old 6 keys keypad - 2 : new 6 keys keypad, as used on the server at www.ant-computing.com - 3 : Nexcom NSA1045's 4 keys keypad - - New profiles can be described in the driver source. The driver also - supports simultaneous keys pressed when the keypad supports them. - -config PANEL_LCD - depends on PANEL && PANEL_PROFILE="0" - int "LCD type (0=none, 1=custom, 2=old //, 3=ks0074, 4=hantronix, 5=Nexcom)" - range 0 5 - default 0 - ---help--- - This enables and configures an LCD connected to the parallel port. - The driver includes an interpreter for escape codes starting with - '\e[L' which are specific to the LCD, and a few ANSI codes. The - driver will be registered as character device 10,156, usually - under the name '/dev/lcd'. There are a total of 6 supported types : - - 0 : do not enable the driver - 1 : custom configuration and wiring (see further) - 2 : 2x16 & 2x40 parallel LCD (old wiring) - 3 : 2x16 serial LCD (KS-0074 based) - 4 : 2x16 parallel LCD (Hantronix wiring) - 5 : 2x16 parallel LCD (Nexcom wiring) - - When type '1' is specified, other options will appear to configure - more precise aspects (wiring, dimensions, protocol, ...). Please note - that those values changed from the 2.4 driver for better consistency. - -config PANEL_LCD_HEIGHT - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Number of lines on the LCD (1-2)" - range 1 2 - default 2 - ---help--- - This is the number of visible character lines on the LCD in custom profile. - It can either be 1 or 2. - -config PANEL_LCD_WIDTH - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Number of characters per line on the LCD (1-40)" - range 1 40 - default 40 - ---help--- - This is the number of characters per line on the LCD in custom profile. - Common values are 16,20,24,40. - -config PANEL_LCD_BWIDTH - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Internal LCD line width (1-40, 40 by default)" - range 1 40 - default 40 - ---help--- - Most LCDs use a standard controller which supports hardware lines of 40 - characters, although sometimes only 16, 20 or 24 of them are really wired - to the terminal. This results in some non-visible but addressable characters, - and is the case for most parallel LCDs. Other LCDs, and some serial ones, - however, use the same line width internally as what is visible. The KS0074 - for example, uses 16 characters per line for 16 visible characters per line. - - This option lets you configure the value used by your LCD in 'custom' profile. - If you don't know, put '40' here. - -config PANEL_LCD_HWIDTH - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Hardware LCD line width (1-64, 64 by default)" - range 1 64 - default 64 - ---help--- - Most LCDs use a single address bit to differentiate line 0 and line 1. Since - some of them need to be able to address 40 chars with the lower bits, they - often use the immediately superior power of 2, which is 64, to address the - next line. - - If you don't know what your LCD uses, in doubt let 16 here for a 2x16, and - 64 here for a 2x40. - -config PANEL_LCD_CHARSET - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "LCD character set (0=normal, 1=KS0074)" - range 0 1 - default 0 - ---help--- - Some controllers such as the KS0074 use a somewhat strange character set - where many symbols are at unusual places. The driver knows how to map - 'standard' ASCII characters to the character sets used by these controllers. - Valid values are : - - 0 : normal (untranslated) character set - 1 : KS0074 character set - - If you don't know, use the normal one (0). - -config PANEL_LCD_PROTO - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "LCD communication mode (0=parallel 8 bits, 1=serial)" - range 0 1 - default 0 - ---help--- - This driver now supports any serial or parallel LCD wired to a parallel - port. But before assigning signals, the driver needs to know if it will - be driving a serial LCD or a parallel one. Serial LCDs only use 2 wires - (SDA/SCL), while parallel ones use 2 or 3 wires for the control signals - (E, RS, sometimes RW), and 4 or 8 for the data. Use 0 here for a 8 bits - parallel LCD, and 1 for a serial LCD. - -config PANEL_LCD_PIN_E - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" - int "Parallel port pin number & polarity connected to the LCD E signal (-17...17) " - range -17 17 - default 14 - ---help--- - This describes the number of the parallel port pin to which the LCD 'E' - signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'E' pin in custom profile is '14' (AUTOFEED). - -config PANEL_LCD_PIN_RS - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" - int "Parallel port pin number & polarity connected to the LCD RS signal (-17...17) " - range -17 17 - default 17 - ---help--- - This describes the number of the parallel port pin to which the LCD 'RS' - signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'RS' pin in custom profile is '17' (SELECT IN). - -config PANEL_LCD_PIN_RW - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO="0" - int "Parallel port pin number & polarity connected to the LCD RW signal (-17...17) " - range -17 17 - default 16 - ---help--- - This describes the number of the parallel port pin to which the LCD 'RW' - signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'RW' pin in custom profile is '16' (INIT). - -config PANEL_LCD_PIN_SCL - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" - int "Parallel port pin number & polarity connected to the LCD SCL signal (-17...17) " - range -17 17 - default 1 - ---help--- - This describes the number of the parallel port pin to which the serial - LCD 'SCL' signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'SCL' pin in custom profile is '1' (STROBE). - -config PANEL_LCD_PIN_SDA - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" && PANEL_LCD_PROTO!="0" - int "Parallel port pin number & polarity connected to the LCD SDA signal (-17...17) " - range -17 17 - default 2 - ---help--- - This describes the number of the parallel port pin to which the serial - LCD 'SDA' signal has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'SDA' pin in custom profile is '2' (D0). - -config PANEL_LCD_PIN_BL - depends on PANEL && PANEL_PROFILE="0" && PANEL_LCD="1" - int "Parallel port pin number & polarity connected to the LCD backlight signal (-17...17) " - range -17 17 - default 0 - ---help--- - This describes the number of the parallel port pin to which the LCD 'BL' signal - has been connected. It can be : - - 0 : no connection (eg: connected to ground) - 1..17 : directly connected to any of these pins on the DB25 plug - -1..-17 : connected to the same pin through an inverter (eg: transistor). - - Default for the 'BL' pin in custom profile is '0' (uncontrolled). - -config PANEL_CHANGE_MESSAGE - depends on PANEL - bool "Change LCD initialization message ?" - default "n" - ---help--- - This allows you to replace the boot message indicating the kernel version - and the driver version with a custom message. This is useful on appliances - where a simple 'Starting system' message can be enough to stop a customer - from worrying. - - If you say 'Y' here, you'll be able to choose a message yourself. Otherwise, - say 'N' and keep the default message with the version. - -config PANEL_BOOT_MESSAGE - depends on PANEL && PANEL_CHANGE_MESSAGE="y" - string "New initialization message" - default "" - ---help--- - This allows you to replace the boot message indicating the kernel version - and the driver version with a custom message. This is useful on appliances - where a simple 'Starting system' message can be enough to stop a customer - from worrying. - - An empty message will only clear the display at driver init time. Any other - printf()-formatted message is valid with newline and escape codes. diff --git a/drivers/staging/panel/Makefile b/drivers/staging/panel/Makefile deleted file mode 100644 index 747c238b82f9..000000000000 --- a/drivers/staging/panel/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_PANEL) += panel.o diff --git a/drivers/staging/panel/TODO b/drivers/staging/panel/TODO deleted file mode 100644 index 3a6405ab91e0..000000000000 --- a/drivers/staging/panel/TODO +++ /dev/null @@ -1,8 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - review major/minor usages - - review userspace api - - see if all of this could be easier done in userspace instead. - -Please send patches to Greg Kroah-Hartman and -Willy Tarreau diff --git a/drivers/staging/panel/lcd-panel-cgram.txt b/drivers/staging/panel/lcd-panel-cgram.txt deleted file mode 100644 index 7f82c905763d..000000000000 --- a/drivers/staging/panel/lcd-panel-cgram.txt +++ /dev/null @@ -1,24 +0,0 @@ -Some LCDs allow you to define up to 8 characters, mapped to ASCII -characters 0 to 7. The escape code to define a new character is -'\e[LG' followed by one digit from 0 to 7, representing the character -number, and up to 8 couples of hex digits terminated by a semi-colon -(';'). Each couple of digits represents a line, with 1-bits for each -illuminated pixel with LSB on the right. Lines are numbered from the -top of the character to the bottom. On a 5x7 matrix, only the 5 lower -bits of the 7 first bytes are used for each character. If the string -is incomplete, only complete lines will be redefined. Here are some -examples : - - printf "\e[LG0010101050D1F0C04;" => 0 = [enter] - printf "\e[LG1040E1F0000000000;" => 1 = [up] - printf "\e[LG2000000001F0E0400;" => 2 = [down] - printf "\e[LG3040E1F001F0E0400;" => 3 = [up-down] - printf "\e[LG40002060E1E0E0602;" => 4 = [left] - printf "\e[LG500080C0E0F0E0C08;" => 5 = [right] - printf "\e[LG60016051516141400;" => 6 = "IP" - - printf "\e[LG00103071F1F070301;" => big speaker - printf "\e[LG00002061E1E060200;" => small speaker - -Willy - diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c deleted file mode 100644 index 4262db0237f9..000000000000 --- a/drivers/staging/panel/panel.c +++ /dev/null @@ -1,2445 +0,0 @@ -/* - * Front panel driver for Linux - * Copyright (C) 2000-2008, Willy Tarreau - * - * 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 code drives an LCD module (/dev/lcd), and a keypad (/dev/keypad) - * connected to a parallel printer port. - * - * The LCD module may either be an HD44780-like 8-bit parallel LCD, or a 1-bit - * serial module compatible with Samsung's KS0074. The pins may be connected in - * any combination, everything is programmable. - * - * The keypad consists in a matrix of push buttons connecting input pins to - * data output pins or to the ground. The combinations have to be hard-coded - * in the driver, though several profiles exist and adding new ones is easy. - * - * Several profiles are provided for commonly found LCD+keypad modules on the - * market, such as those found in Nexcom's appliances. - * - * FIXME: - * - the initialization/deinitialization process is very dirty and should - * be rewritten. It may even be buggy. - * - * TODO: - * - document 24 keys keyboard (3 rows of 8 cols, 32 diodes + 2 inputs) - * - make the LCD a part of a virtual screen of Vx*Vy - * - make the inputs list smp-safe - * - change the keyboard to a double mapping : signals -> key_id -> values - * so that applications can change values without knowing signals - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define LCD_MINOR 156 -#define KEYPAD_MINOR 185 - -#define PANEL_VERSION "0.9.5" - -#define LCD_MAXBYTES 256 /* max burst write */ - -#define KEYPAD_BUFFER 64 - -/* poll the keyboard this every second */ -#define INPUT_POLL_TIME (HZ / 50) -/* a key starts to repeat after this times INPUT_POLL_TIME */ -#define KEYPAD_REP_START (10) -/* a key repeats this times INPUT_POLL_TIME */ -#define KEYPAD_REP_DELAY (2) - -/* keep the light on this times INPUT_POLL_TIME for each flash */ -#define FLASH_LIGHT_TEMPO (200) - -/* converts an r_str() input to an active high, bits string : 000BAOSE */ -#define PNL_PINPUT(a) ((((unsigned char)(a)) ^ 0x7F) >> 3) - -#define PNL_PBUSY 0x80 /* inverted input, active low */ -#define PNL_PACK 0x40 /* direct input, active low */ -#define PNL_POUTPA 0x20 /* direct input, active high */ -#define PNL_PSELECD 0x10 /* direct input, active high */ -#define PNL_PERRORP 0x08 /* direct input, active low */ - -#define PNL_PBIDIR 0x20 /* bi-directional ports */ -/* high to read data in or-ed with data out */ -#define PNL_PINTEN 0x10 -#define PNL_PSELECP 0x08 /* inverted output, active low */ -#define PNL_PINITP 0x04 /* direct output, active low */ -#define PNL_PAUTOLF 0x02 /* inverted output, active low */ -#define PNL_PSTROBE 0x01 /* inverted output */ - -#define PNL_PD0 0x01 -#define PNL_PD1 0x02 -#define PNL_PD2 0x04 -#define PNL_PD3 0x08 -#define PNL_PD4 0x10 -#define PNL_PD5 0x20 -#define PNL_PD6 0x40 -#define PNL_PD7 0x80 - -#define PIN_NONE 0 -#define PIN_STROBE 1 -#define PIN_D0 2 -#define PIN_D1 3 -#define PIN_D2 4 -#define PIN_D3 5 -#define PIN_D4 6 -#define PIN_D5 7 -#define PIN_D6 8 -#define PIN_D7 9 -#define PIN_AUTOLF 14 -#define PIN_INITP 16 -#define PIN_SELECP 17 -#define PIN_NOT_SET 127 - -#define LCD_FLAG_S 0x0001 -#define LCD_FLAG_ID 0x0002 -#define LCD_FLAG_B 0x0004 /* blink on */ -#define LCD_FLAG_C 0x0008 /* cursor on */ -#define LCD_FLAG_D 0x0010 /* display on */ -#define LCD_FLAG_F 0x0020 /* large font mode */ -#define LCD_FLAG_N 0x0040 /* 2-rows mode */ -#define LCD_FLAG_L 0x0080 /* backlight enabled */ - -/* LCD commands */ -#define LCD_CMD_DISPLAY_CLEAR 0x01 /* Clear entire display */ - -#define LCD_CMD_ENTRY_MODE 0x04 /* Set entry mode */ -#define LCD_CMD_CURSOR_INC 0x02 /* Increment cursor */ - -#define LCD_CMD_DISPLAY_CTRL 0x08 /* Display control */ -#define LCD_CMD_DISPLAY_ON 0x04 /* Set display on */ -#define LCD_CMD_CURSOR_ON 0x02 /* Set cursor on */ -#define LCD_CMD_BLINK_ON 0x01 /* Set blink on */ - -#define LCD_CMD_SHIFT 0x10 /* Shift cursor/display */ -#define LCD_CMD_DISPLAY_SHIFT 0x08 /* Shift display instead of cursor */ -#define LCD_CMD_SHIFT_RIGHT 0x04 /* Shift display/cursor to the right */ - -#define LCD_CMD_FUNCTION_SET 0x20 /* Set function */ -#define LCD_CMD_DATA_LEN_8BITS 0x10 /* Set data length to 8 bits */ -#define LCD_CMD_TWO_LINES 0x08 /* Set to two display lines */ -#define LCD_CMD_FONT_5X10_DOTS 0x04 /* Set char font to 5x10 dots */ - -#define LCD_CMD_SET_CGRAM_ADDR 0x40 /* Set char generator RAM address */ - -#define LCD_CMD_SET_DDRAM_ADDR 0x80 /* Set display data RAM address */ - -#define LCD_ESCAPE_LEN 24 /* max chars for LCD escape command */ -#define LCD_ESCAPE_CHAR 27 /* use char 27 for escape command */ - -#define NOT_SET -1 - -/* macros to simplify use of the parallel port */ -#define r_ctr(x) (parport_read_control((x)->port)) -#define r_dtr(x) (parport_read_data((x)->port)) -#define r_str(x) (parport_read_status((x)->port)) -#define w_ctr(x, y) (parport_write_control((x)->port, (y))) -#define w_dtr(x, y) (parport_write_data((x)->port, (y))) - -/* this defines which bits are to be used and which ones to be ignored */ -/* logical or of the output bits involved in the scan matrix */ -static __u8 scan_mask_o; -/* logical or of the input bits involved in the scan matrix */ -static __u8 scan_mask_i; - -enum input_type { - INPUT_TYPE_STD, - INPUT_TYPE_KBD, -}; - -enum input_state { - INPUT_ST_LOW, - INPUT_ST_RISING, - INPUT_ST_HIGH, - INPUT_ST_FALLING, -}; - -struct logical_input { - struct list_head list; - __u64 mask; - __u64 value; - enum input_type type; - enum input_state state; - __u8 rise_time, fall_time; - __u8 rise_timer, fall_timer, high_timer; - - union { - struct { /* valid when type == INPUT_TYPE_STD */ - void (*press_fct)(int); - void (*release_fct)(int); - int press_data; - int release_data; - } std; - struct { /* valid when type == INPUT_TYPE_KBD */ - /* strings can be non null-terminated */ - char press_str[sizeof(void *) + sizeof(int)]; - char repeat_str[sizeof(void *) + sizeof(int)]; - char release_str[sizeof(void *) + sizeof(int)]; - } kbd; - } u; -}; - -static LIST_HEAD(logical_inputs); /* list of all defined logical inputs */ - -/* physical contacts history - * Physical contacts are a 45 bits string of 9 groups of 5 bits each. - * The 8 lower groups correspond to output bits 0 to 7, and the 9th group - * corresponds to the ground. - * Within each group, bits are stored in the same order as read on the port : - * BAPSE (busy=4, ack=3, paper empty=2, select=1, error=0). - * So, each __u64 is represented like this : - * 0000000000000000000BAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSEBAPSE - * <-----unused------> - */ - -/* what has just been read from the I/O ports */ -static __u64 phys_read; -/* previous phys_read */ -static __u64 phys_read_prev; -/* stabilized phys_read (phys_read|phys_read_prev) */ -static __u64 phys_curr; -/* previous phys_curr */ -static __u64 phys_prev; -/* 0 means that at least one logical signal needs be computed */ -static char inputs_stable; - -/* these variables are specific to the keypad */ -static struct { - bool enabled; -} keypad; - -static char keypad_buffer[KEYPAD_BUFFER]; -static int keypad_buflen; -static int keypad_start; -static char keypressed; -static wait_queue_head_t keypad_read_wait; - -/* lcd-specific variables */ -static struct { - bool enabled; - bool initialized; - bool must_clear; - - int height; - int width; - int bwidth; - int hwidth; - int charset; - int proto; - int light_tempo; - - /* TODO: use union here? */ - struct { - int e; - int rs; - int rw; - int cl; - int da; - int bl; - } pins; - - /* contains the LCD config state */ - unsigned long int flags; - - /* Contains the LCD X and Y offset */ - struct { - unsigned long int x; - unsigned long int y; - } addr; - - /* Current escape sequence and it's length or -1 if outside */ - struct { - char buf[LCD_ESCAPE_LEN + 1]; - int len; - } esc_seq; -} lcd; - -/* Needed only for init */ -static int selected_lcd_type = NOT_SET; - -/* - * Bit masks to convert LCD signals to parallel port outputs. - * _d_ are values for data port, _c_ are for control port. - * [0] = signal OFF, [1] = signal ON, [2] = mask - */ -#define BIT_CLR 0 -#define BIT_SET 1 -#define BIT_MSK 2 -#define BIT_STATES 3 -/* - * one entry for each bit on the LCD - */ -#define LCD_BIT_E 0 -#define LCD_BIT_RS 1 -#define LCD_BIT_RW 2 -#define LCD_BIT_BL 3 -#define LCD_BIT_CL 4 -#define LCD_BIT_DA 5 -#define LCD_BITS 6 - -/* - * each bit can be either connected to a DATA or CTRL port - */ -#define LCD_PORT_C 0 -#define LCD_PORT_D 1 -#define LCD_PORTS 2 - -static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; - -/* - * LCD protocols - */ -#define LCD_PROTO_PARALLEL 0 -#define LCD_PROTO_SERIAL 1 -#define LCD_PROTO_TI_DA8XX_LCD 2 - -/* - * LCD character sets - */ -#define LCD_CHARSET_NORMAL 0 -#define LCD_CHARSET_KS0074 1 - -/* - * LCD types - */ -#define LCD_TYPE_NONE 0 -#define LCD_TYPE_CUSTOM 1 -#define LCD_TYPE_OLD 2 -#define LCD_TYPE_KS0074 3 -#define LCD_TYPE_HANTRONIX 4 -#define LCD_TYPE_NEXCOM 5 - -/* - * keypad types - */ -#define KEYPAD_TYPE_NONE 0 -#define KEYPAD_TYPE_OLD 1 -#define KEYPAD_TYPE_NEW 2 -#define KEYPAD_TYPE_NEXCOM 3 - -/* - * panel profiles - */ -#define PANEL_PROFILE_CUSTOM 0 -#define PANEL_PROFILE_OLD 1 -#define PANEL_PROFILE_NEW 2 -#define PANEL_PROFILE_HANTRONIX 3 -#define PANEL_PROFILE_NEXCOM 4 -#define PANEL_PROFILE_LARGE 5 - -/* - * Construct custom config from the kernel's configuration - */ -#define DEFAULT_PARPORT 0 -#define DEFAULT_PROFILE PANEL_PROFILE_LARGE -#define DEFAULT_KEYPAD_TYPE KEYPAD_TYPE_OLD -#define DEFAULT_LCD_TYPE LCD_TYPE_OLD -#define DEFAULT_LCD_HEIGHT 2 -#define DEFAULT_LCD_WIDTH 40 -#define DEFAULT_LCD_BWIDTH 40 -#define DEFAULT_LCD_HWIDTH 64 -#define DEFAULT_LCD_CHARSET LCD_CHARSET_NORMAL -#define DEFAULT_LCD_PROTO LCD_PROTO_PARALLEL - -#define DEFAULT_LCD_PIN_E PIN_AUTOLF -#define DEFAULT_LCD_PIN_RS PIN_SELECP -#define DEFAULT_LCD_PIN_RW PIN_INITP -#define DEFAULT_LCD_PIN_SCL PIN_STROBE -#define DEFAULT_LCD_PIN_SDA PIN_D0 -#define DEFAULT_LCD_PIN_BL PIN_NOT_SET - -#ifdef CONFIG_PANEL_PARPORT -#undef DEFAULT_PARPORT -#define DEFAULT_PARPORT CONFIG_PANEL_PARPORT -#endif - -#ifdef CONFIG_PANEL_PROFILE -#undef DEFAULT_PROFILE -#define DEFAULT_PROFILE CONFIG_PANEL_PROFILE -#endif - -#if DEFAULT_PROFILE == 0 /* custom */ -#ifdef CONFIG_PANEL_KEYPAD -#undef DEFAULT_KEYPAD_TYPE -#define DEFAULT_KEYPAD_TYPE CONFIG_PANEL_KEYPAD -#endif - -#ifdef CONFIG_PANEL_LCD -#undef DEFAULT_LCD_TYPE -#define DEFAULT_LCD_TYPE CONFIG_PANEL_LCD -#endif - -#ifdef CONFIG_PANEL_LCD_HEIGHT -#undef DEFAULT_LCD_HEIGHT -#define DEFAULT_LCD_HEIGHT CONFIG_PANEL_LCD_HEIGHT -#endif - -#ifdef CONFIG_PANEL_LCD_WIDTH -#undef DEFAULT_LCD_WIDTH -#define DEFAULT_LCD_WIDTH CONFIG_PANEL_LCD_WIDTH -#endif - -#ifdef CONFIG_PANEL_LCD_BWIDTH -#undef DEFAULT_LCD_BWIDTH -#define DEFAULT_LCD_BWIDTH CONFIG_PANEL_LCD_BWIDTH -#endif - -#ifdef CONFIG_PANEL_LCD_HWIDTH -#undef DEFAULT_LCD_HWIDTH -#define DEFAULT_LCD_HWIDTH CONFIG_PANEL_LCD_HWIDTH -#endif - -#ifdef CONFIG_PANEL_LCD_CHARSET -#undef DEFAULT_LCD_CHARSET -#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET -#endif - -#ifdef CONFIG_PANEL_LCD_PROTO -#undef DEFAULT_LCD_PROTO -#define DEFAULT_LCD_PROTO CONFIG_PANEL_LCD_PROTO -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_E -#undef DEFAULT_LCD_PIN_E -#define DEFAULT_LCD_PIN_E CONFIG_PANEL_LCD_PIN_E -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_RS -#undef DEFAULT_LCD_PIN_RS -#define DEFAULT_LCD_PIN_RS CONFIG_PANEL_LCD_PIN_RS -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_RW -#undef DEFAULT_LCD_PIN_RW -#define DEFAULT_LCD_PIN_RW CONFIG_PANEL_LCD_PIN_RW -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_SCL -#undef DEFAULT_LCD_PIN_SCL -#define DEFAULT_LCD_PIN_SCL CONFIG_PANEL_LCD_PIN_SCL -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_SDA -#undef DEFAULT_LCD_PIN_SDA -#define DEFAULT_LCD_PIN_SDA CONFIG_PANEL_LCD_PIN_SDA -#endif - -#ifdef CONFIG_PANEL_LCD_PIN_BL -#undef DEFAULT_LCD_PIN_BL -#define DEFAULT_LCD_PIN_BL CONFIG_PANEL_LCD_PIN_BL -#endif - -#endif /* DEFAULT_PROFILE == 0 */ - -/* global variables */ - -/* Device single-open policy control */ -static atomic_t lcd_available = ATOMIC_INIT(1); -static atomic_t keypad_available = ATOMIC_INIT(1); - -static struct pardevice *pprt; - -static int keypad_initialized; - -static void (*lcd_write_cmd)(int); -static void (*lcd_write_data)(int); -static void (*lcd_clear_fast)(void); - -static DEFINE_SPINLOCK(pprt_lock); -static struct timer_list scan_timer; - -MODULE_DESCRIPTION("Generic parallel port LCD/Keypad driver"); - -static int parport = DEFAULT_PARPORT; -module_param(parport, int, 0000); -MODULE_PARM_DESC(parport, "Parallel port index (0=lpt1, 1=lpt2, ...)"); - -static int profile = DEFAULT_PROFILE; -module_param(profile, int, 0000); -MODULE_PARM_DESC(profile, - "1=16x2 old kp; 2=serial 16x2, new kp; 3=16x2 hantronix; " - "4=16x2 nexcom; default=40x2, old kp"); - -static int keypad_type = NOT_SET; -module_param(keypad_type, int, 0000); -MODULE_PARM_DESC(keypad_type, - "Keypad type: 0=none, 1=old 6 keys, 2=new 6+1 keys, 3=nexcom 4 keys"); - -static int lcd_type = NOT_SET; -module_param(lcd_type, int, 0000); -MODULE_PARM_DESC(lcd_type, - "LCD type: 0=none, 1=compiled-in, 2=old, 3=serial ks0074, 4=hantronix, 5=nexcom"); - -static int lcd_height = NOT_SET; -module_param(lcd_height, int, 0000); -MODULE_PARM_DESC(lcd_height, "Number of lines on the LCD"); - -static int lcd_width = NOT_SET; -module_param(lcd_width, int, 0000); -MODULE_PARM_DESC(lcd_width, "Number of columns on the LCD"); - -static int lcd_bwidth = NOT_SET; /* internal buffer width (usually 40) */ -module_param(lcd_bwidth, int, 0000); -MODULE_PARM_DESC(lcd_bwidth, "Internal LCD line width (40)"); - -static int lcd_hwidth = NOT_SET; /* hardware buffer width (usually 64) */ -module_param(lcd_hwidth, int, 0000); -MODULE_PARM_DESC(lcd_hwidth, "LCD line hardware address (64)"); - -static int lcd_charset = NOT_SET; -module_param(lcd_charset, int, 0000); -MODULE_PARM_DESC(lcd_charset, "LCD character set: 0=standard, 1=KS0074"); - -static int lcd_proto = NOT_SET; -module_param(lcd_proto, int, 0000); -MODULE_PARM_DESC(lcd_proto, - "LCD communication: 0=parallel (//), 1=serial, 2=TI LCD Interface"); - -/* - * These are the parallel port pins the LCD control signals are connected to. - * Set this to 0 if the signal is not used. Set it to its opposite value - * (negative) if the signal is negated. -MAXINT is used to indicate that the - * pin has not been explicitly specified. - * - * WARNING! no check will be performed about collisions with keypad ! - */ - -static int lcd_e_pin = PIN_NOT_SET; -module_param(lcd_e_pin, int, 0000); -MODULE_PARM_DESC(lcd_e_pin, - "# of the // port pin connected to LCD 'E' signal, with polarity (-17..17)"); - -static int lcd_rs_pin = PIN_NOT_SET; -module_param(lcd_rs_pin, int, 0000); -MODULE_PARM_DESC(lcd_rs_pin, - "# of the // port pin connected to LCD 'RS' signal, with polarity (-17..17)"); - -static int lcd_rw_pin = PIN_NOT_SET; -module_param(lcd_rw_pin, int, 0000); -MODULE_PARM_DESC(lcd_rw_pin, - "# of the // port pin connected to LCD 'RW' signal, with polarity (-17..17)"); - -static int lcd_cl_pin = PIN_NOT_SET; -module_param(lcd_cl_pin, int, 0000); -MODULE_PARM_DESC(lcd_cl_pin, - "# of the // port pin connected to serial LCD 'SCL' signal, with polarity (-17..17)"); - -static int lcd_da_pin = PIN_NOT_SET; -module_param(lcd_da_pin, int, 0000); -MODULE_PARM_DESC(lcd_da_pin, - "# of the // port pin connected to serial LCD 'SDA' signal, with polarity (-17..17)"); - -static int lcd_bl_pin = PIN_NOT_SET; -module_param(lcd_bl_pin, int, 0000); -MODULE_PARM_DESC(lcd_bl_pin, - "# of the // port pin connected to LCD backlight, with polarity (-17..17)"); - -/* Deprecated module parameters - consider not using them anymore */ - -static int lcd_enabled = NOT_SET; -module_param(lcd_enabled, int, 0000); -MODULE_PARM_DESC(lcd_enabled, "Deprecated option, use lcd_type instead"); - -static int keypad_enabled = NOT_SET; -module_param(keypad_enabled, int, 0000); -MODULE_PARM_DESC(keypad_enabled, "Deprecated option, use keypad_type instead"); - -static const unsigned char *lcd_char_conv; - -/* for some LCD drivers (ks0074) we need a charset conversion table. */ -static const unsigned char lcd_char_conv_ks0074[256] = { - /* 0|8 1|9 2|A 3|B 4|C 5|D 6|E 7|F */ - /* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - /* 0x08 */ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - /* 0x10 */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - /* 0x18 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - /* 0x20 */ 0x20, 0x21, 0x22, 0x23, 0xa2, 0x25, 0x26, 0x27, - /* 0x28 */ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - /* 0x30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - /* 0x38 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - /* 0x40 */ 0xa0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - /* 0x48 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - /* 0x50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - /* 0x58 */ 0x58, 0x59, 0x5a, 0xfa, 0xfb, 0xfc, 0x1d, 0xc4, - /* 0x60 */ 0x96, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - /* 0x68 */ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - /* 0x70 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - /* 0x78 */ 0x78, 0x79, 0x7a, 0xfd, 0xfe, 0xff, 0xce, 0x20, - /* 0x80 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - /* 0x88 */ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - /* 0x90 */ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - /* 0x98 */ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - /* 0xA0 */ 0x20, 0x40, 0xb1, 0xa1, 0x24, 0xa3, 0xfe, 0x5f, - /* 0xA8 */ 0x22, 0xc8, 0x61, 0x14, 0x97, 0x2d, 0xad, 0x96, - /* 0xB0 */ 0x80, 0x8c, 0x82, 0x83, 0x27, 0x8f, 0x86, 0xdd, - /* 0xB8 */ 0x2c, 0x81, 0x6f, 0x15, 0x8b, 0x8a, 0x84, 0x60, - /* 0xC0 */ 0xe2, 0xe2, 0xe2, 0x5b, 0x5b, 0xae, 0xbc, 0xa9, - /* 0xC8 */ 0xc5, 0xbf, 0xc6, 0xf1, 0xe3, 0xe3, 0xe3, 0xe3, - /* 0xD0 */ 0x44, 0x5d, 0xa8, 0xe4, 0xec, 0xec, 0x5c, 0x78, - /* 0xD8 */ 0xab, 0xa6, 0xe5, 0x5e, 0x5e, 0xe6, 0xaa, 0xbe, - /* 0xE0 */ 0x7f, 0xe7, 0xaf, 0x7b, 0x7b, 0xaf, 0xbd, 0xc8, - /* 0xE8 */ 0xa4, 0xa5, 0xc7, 0xf6, 0xa7, 0xe8, 0x69, 0x69, - /* 0xF0 */ 0xed, 0x7d, 0xa8, 0xe4, 0xec, 0x5c, 0x5c, 0x25, - /* 0xF8 */ 0xac, 0xa6, 0xea, 0xef, 0x7e, 0xeb, 0xb2, 0x79, -}; - -static const char old_keypad_profile[][4][9] = { - {"S0", "Left\n", "Left\n", ""}, - {"S1", "Down\n", "Down\n", ""}, - {"S2", "Up\n", "Up\n", ""}, - {"S3", "Right\n", "Right\n", ""}, - {"S4", "Esc\n", "Esc\n", ""}, - {"S5", "Ret\n", "Ret\n", ""}, - {"", "", "", ""} -}; - -/* signals, press, repeat, release */ -static const char new_keypad_profile[][4][9] = { - {"S0", "Left\n", "Left\n", ""}, - {"S1", "Down\n", "Down\n", ""}, - {"S2", "Up\n", "Up\n", ""}, - {"S3", "Right\n", "Right\n", ""}, - {"S4s5", "", "Esc\n", "Esc\n"}, - {"s4S5", "", "Ret\n", "Ret\n"}, - {"S4S5", "Help\n", "", ""}, - /* add new signals above this line */ - {"", "", "", ""} -}; - -/* signals, press, repeat, release */ -static const char nexcom_keypad_profile[][4][9] = { - {"a-p-e-", "Down\n", "Down\n", ""}, - {"a-p-E-", "Ret\n", "Ret\n", ""}, - {"a-P-E-", "Esc\n", "Esc\n", ""}, - {"a-P-e-", "Up\n", "Up\n", ""}, - /* add new signals above this line */ - {"", "", "", ""} -}; - -static const char (*keypad_profile)[4][9] = old_keypad_profile; - -/* FIXME: this should be converted to a bit array containing signals states */ -static struct { - unsigned char e; /* parallel LCD E (data latch on falling edge) */ - unsigned char rs; /* parallel LCD RS (0 = cmd, 1 = data) */ - unsigned char rw; /* parallel LCD R/W (0 = W, 1 = R) */ - unsigned char bl; /* parallel LCD backlight (0 = off, 1 = on) */ - unsigned char cl; /* serial LCD clock (latch on rising edge) */ - unsigned char da; /* serial LCD data */ -} bits; - -static void init_scan_timer(void); - -/* sets data port bits according to current signals values */ -static int set_data_bits(void) -{ - int val, bit; - - val = r_dtr(pprt); - for (bit = 0; bit < LCD_BITS; bit++) - val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK]; - - val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e] - | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs] - | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw] - | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl] - | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl] - | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da]; - - w_dtr(pprt, val); - return val; -} - -/* sets ctrl port bits according to current signals values */ -static int set_ctrl_bits(void) -{ - int val, bit; - - val = r_ctr(pprt); - for (bit = 0; bit < LCD_BITS; bit++) - val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK]; - - val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e] - | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs] - | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw] - | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl] - | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl] - | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da]; - - w_ctr(pprt, val); - return val; -} - -/* sets ctrl & data port bits according to current signals values */ -static void panel_set_bits(void) -{ - set_data_bits(); - set_ctrl_bits(); -} - -/* - * Converts a parallel port pin (from -25 to 25) to data and control ports - * masks, and data and control port bits. The signal will be considered - * unconnected if it's on pin 0 or an invalid pin (<-25 or >25). - * - * Result will be used this way : - * out(dport, in(dport) & d_val[2] | d_val[signal_state]) - * out(cport, in(cport) & c_val[2] | c_val[signal_state]) - */ -static void pin_to_bits(int pin, unsigned char *d_val, unsigned char *c_val) -{ - int d_bit, c_bit, inv; - - d_val[0] = 0; - c_val[0] = 0; - d_val[1] = 0; - c_val[1] = 0; - d_val[2] = 0xFF; - c_val[2] = 0xFF; - - if (pin == 0) - return; - - inv = (pin < 0); - if (inv) - pin = -pin; - - d_bit = 0; - c_bit = 0; - - switch (pin) { - case PIN_STROBE: /* strobe, inverted */ - c_bit = PNL_PSTROBE; - inv = !inv; - break; - case PIN_D0...PIN_D7: /* D0 - D7 = 2 - 9 */ - d_bit = 1 << (pin - 2); - break; - case PIN_AUTOLF: /* autofeed, inverted */ - c_bit = PNL_PAUTOLF; - inv = !inv; - break; - case PIN_INITP: /* init, direct */ - c_bit = PNL_PINITP; - break; - case PIN_SELECP: /* select_in, inverted */ - c_bit = PNL_PSELECP; - inv = !inv; - break; - default: /* unknown pin, ignore */ - break; - } - - if (c_bit) { - c_val[2] &= ~c_bit; - c_val[!inv] = c_bit; - } else if (d_bit) { - d_val[2] &= ~d_bit; - d_val[!inv] = d_bit; - } -} - -/* sleeps that many milliseconds with a reschedule */ -static void long_sleep(int ms) -{ - if (in_interrupt()) - mdelay(ms); - else - schedule_timeout_interruptible(msecs_to_jiffies(ms)); -} - -/* - * send a serial byte to the LCD panel. The caller is responsible for locking - * if needed. - */ -static void lcd_send_serial(int byte) -{ - int bit; - - /* - * the data bit is set on D0, and the clock on STROBE. - * LCD reads D0 on STROBE's rising edge. - */ - for (bit = 0; bit < 8; bit++) { - bits.cl = BIT_CLR; /* CLK low */ - panel_set_bits(); - bits.da = byte & 1; - panel_set_bits(); - udelay(2); /* maintain the data during 2 us before CLK up */ - bits.cl = BIT_SET; /* CLK high */ - panel_set_bits(); - udelay(1); /* maintain the strobe during 1 us */ - byte >>= 1; - } -} - -/* turn the backlight on or off */ -static void lcd_backlight(int on) -{ - if (lcd.pins.bl == PIN_NONE) - return; - - /* The backlight is activated by setting the AUTOFEED line to +5V */ - spin_lock_irq(&pprt_lock); - bits.bl = on; - panel_set_bits(); - spin_unlock_irq(&pprt_lock); -} - -/* send a command to the LCD panel in serial mode */ -static void lcd_write_cmd_s(int cmd) -{ - spin_lock_irq(&pprt_lock); - lcd_send_serial(0x1F); /* R/W=W, RS=0 */ - lcd_send_serial(cmd & 0x0F); - lcd_send_serial((cmd >> 4) & 0x0F); - udelay(40); /* the shortest command takes at least 40 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send data to the LCD panel in serial mode */ -static void lcd_write_data_s(int data) -{ - spin_lock_irq(&pprt_lock); - lcd_send_serial(0x5F); /* R/W=W, RS=1 */ - lcd_send_serial(data & 0x0F); - lcd_send_serial((data >> 4) & 0x0F); - udelay(40); /* the shortest data takes at least 40 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send a command to the LCD panel in 8 bits parallel mode */ -static void lcd_write_cmd_p8(int cmd) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the data port */ - w_dtr(pprt, cmd); - udelay(20); /* maintain the data during 20 us before the strobe */ - - bits.e = BIT_SET; - bits.rs = BIT_CLR; - bits.rw = BIT_CLR; - set_ctrl_bits(); - - udelay(40); /* maintain the strobe during 40 us */ - - bits.e = BIT_CLR; - set_ctrl_bits(); - - udelay(120); /* the shortest command takes at least 120 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send data to the LCD panel in 8 bits parallel mode */ -static void lcd_write_data_p8(int data) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the data port */ - w_dtr(pprt, data); - udelay(20); /* maintain the data during 20 us before the strobe */ - - bits.e = BIT_SET; - bits.rs = BIT_SET; - bits.rw = BIT_CLR; - set_ctrl_bits(); - - udelay(40); /* maintain the strobe during 40 us */ - - bits.e = BIT_CLR; - set_ctrl_bits(); - - udelay(45); /* the shortest data takes at least 45 us */ - spin_unlock_irq(&pprt_lock); -} - -/* send a command to the TI LCD panel */ -static void lcd_write_cmd_tilcd(int cmd) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the control port */ - w_ctr(pprt, cmd); - udelay(60); - spin_unlock_irq(&pprt_lock); -} - -/* send data to the TI LCD panel */ -static void lcd_write_data_tilcd(int data) -{ - spin_lock_irq(&pprt_lock); - /* present the data to the data port */ - w_dtr(pprt, data); - udelay(60); - spin_unlock_irq(&pprt_lock); -} - -static void lcd_gotoxy(void) -{ - lcd_write_cmd(LCD_CMD_SET_DDRAM_ADDR - | (lcd.addr.y ? lcd.hwidth : 0) - /* - * we force the cursor to stay at the end of the - * line if it wants to go farther - */ - | ((lcd.addr.x < lcd.bwidth) ? lcd.addr.x & - (lcd.hwidth - 1) : lcd.bwidth - 1)); -} - -static void lcd_print(char c) -{ - if (lcd.addr.x < lcd.bwidth) { - if (lcd_char_conv) - c = lcd_char_conv[(unsigned char)c]; - lcd_write_data(c); - lcd.addr.x++; - } - /* prevents the cursor from wrapping onto the next line */ - if (lcd.addr.x == lcd.bwidth) - lcd_gotoxy(); -} - -/* fills the display with spaces and resets X/Y */ -static void lcd_clear_fast_s(void) -{ - int pos; - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - - spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { - lcd_send_serial(0x5F); /* R/W=W, RS=1 */ - lcd_send_serial(' ' & 0x0F); - lcd_send_serial((' ' >> 4) & 0x0F); - /* the shortest data takes at least 40 us */ - udelay(40); - } - spin_unlock_irq(&pprt_lock); - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); -} - -/* fills the display with spaces and resets X/Y */ -static void lcd_clear_fast_p8(void) -{ - int pos; - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - - spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { - /* present the data to the data port */ - w_dtr(pprt, ' '); - - /* maintain the data during 20 us before the strobe */ - udelay(20); - - bits.e = BIT_SET; - bits.rs = BIT_SET; - bits.rw = BIT_CLR; - set_ctrl_bits(); - - /* maintain the strobe during 40 us */ - udelay(40); - - bits.e = BIT_CLR; - set_ctrl_bits(); - - /* the shortest data takes at least 45 us */ - udelay(45); - } - spin_unlock_irq(&pprt_lock); - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); -} - -/* fills the display with spaces and resets X/Y */ -static void lcd_clear_fast_tilcd(void) -{ - int pos; - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - - spin_lock_irq(&pprt_lock); - for (pos = 0; pos < lcd.height * lcd.hwidth; pos++) { - /* present the data to the data port */ - w_dtr(pprt, ' '); - udelay(60); - } - - spin_unlock_irq(&pprt_lock); - - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); -} - -/* clears the display and resets X/Y */ -static void lcd_clear_display(void) -{ - lcd_write_cmd(LCD_CMD_DISPLAY_CLEAR); - lcd.addr.x = 0; - lcd.addr.y = 0; - /* we must wait a few milliseconds (15) */ - long_sleep(15); -} - -static void lcd_init_display(void) -{ - lcd.flags = ((lcd.height > 1) ? LCD_FLAG_N : 0) - | LCD_FLAG_D | LCD_FLAG_C | LCD_FLAG_B; - - long_sleep(20); /* wait 20 ms after power-up for the paranoid */ - - /* 8bits, 1 line, small fonts; let's do it 3 times */ - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); - long_sleep(10); - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); - long_sleep(10); - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS); - long_sleep(10); - - /* set font height and lines number */ - lcd_write_cmd(LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS - | ((lcd.flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) - | ((lcd.flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0) - ); - long_sleep(10); - - /* display off, cursor off, blink off */ - lcd_write_cmd(LCD_CMD_DISPLAY_CTRL); - long_sleep(10); - - lcd_write_cmd(LCD_CMD_DISPLAY_CTRL /* set display mode */ - | ((lcd.flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) - | ((lcd.flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) - | ((lcd.flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0) - ); - - lcd_backlight((lcd.flags & LCD_FLAG_L) ? 1 : 0); - - long_sleep(10); - - /* entry mode set : increment, cursor shifting */ - lcd_write_cmd(LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC); - - lcd_clear_display(); -} - -/* - * These are the file operation function for user access to /dev/lcd - * This function can also be called from inside the kernel, by - * setting file and ppos to NULL. - * - */ - -static inline int handle_lcd_special_code(void) -{ - /* LCD special codes */ - - int processed = 0; - - char *esc = lcd.esc_seq.buf + 2; - int oldflags = lcd.flags; - - /* check for display mode flags */ - switch (*esc) { - case 'D': /* Display ON */ - lcd.flags |= LCD_FLAG_D; - processed = 1; - break; - case 'd': /* Display OFF */ - lcd.flags &= ~LCD_FLAG_D; - processed = 1; - break; - case 'C': /* Cursor ON */ - lcd.flags |= LCD_FLAG_C; - processed = 1; - break; - case 'c': /* Cursor OFF */ - lcd.flags &= ~LCD_FLAG_C; - processed = 1; - break; - case 'B': /* Blink ON */ - lcd.flags |= LCD_FLAG_B; - processed = 1; - break; - case 'b': /* Blink OFF */ - lcd.flags &= ~LCD_FLAG_B; - processed = 1; - break; - case '+': /* Back light ON */ - lcd.flags |= LCD_FLAG_L; - processed = 1; - break; - case '-': /* Back light OFF */ - lcd.flags &= ~LCD_FLAG_L; - processed = 1; - break; - case '*': - /* flash back light using the keypad timer */ - if (scan_timer.function) { - if (lcd.light_tempo == 0 && - ((lcd.flags & LCD_FLAG_L) == 0)) - lcd_backlight(1); - lcd.light_tempo = FLASH_LIGHT_TEMPO; - } - processed = 1; - break; - case 'f': /* Small Font */ - lcd.flags &= ~LCD_FLAG_F; - processed = 1; - break; - case 'F': /* Large Font */ - lcd.flags |= LCD_FLAG_F; - processed = 1; - break; - case 'n': /* One Line */ - lcd.flags &= ~LCD_FLAG_N; - processed = 1; - break; - case 'N': /* Two Lines */ - lcd.flags |= LCD_FLAG_N; - break; - case 'l': /* Shift Cursor Left */ - if (lcd.addr.x > 0) { - /* back one char if not at end of line */ - if (lcd.addr.x < lcd.bwidth) - lcd_write_cmd(LCD_CMD_SHIFT); - lcd.addr.x--; - } - processed = 1; - break; - case 'r': /* shift cursor right */ - if (lcd.addr.x < lcd.width) { - /* allow the cursor to pass the end of the line */ - if (lcd.addr.x < (lcd.bwidth - 1)) - lcd_write_cmd(LCD_CMD_SHIFT | - LCD_CMD_SHIFT_RIGHT); - lcd.addr.x++; - } - processed = 1; - break; - case 'L': /* shift display left */ - lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT); - processed = 1; - break; - case 'R': /* shift display right */ - lcd_write_cmd(LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT | - LCD_CMD_SHIFT_RIGHT); - processed = 1; - break; - case 'k': { /* kill end of line */ - int x; - - for (x = lcd.addr.x; x < lcd.bwidth; x++) - lcd_write_data(' '); - - /* restore cursor position */ - lcd_gotoxy(); - processed = 1; - break; - } - case 'I': /* reinitialize display */ - lcd_init_display(); - processed = 1; - break; - case 'G': { - /* Generator : LGcxxxxx...xx; must have between '0' - * and '7', representing the numerical ASCII code of the - * redefined character, and a sequence of 16 - * hex digits representing 8 bytes for each character. - * Most LCDs will only use 5 lower bits of the 7 first - * bytes. - */ - - unsigned char cgbytes[8]; - unsigned char cgaddr; - int cgoffset; - int shift; - char value; - int addr; - - if (!strchr(esc, ';')) - break; - - esc++; - - cgaddr = *(esc++) - '0'; - if (cgaddr > 7) { - processed = 1; - break; - } - - cgoffset = 0; - shift = 0; - value = 0; - while (*esc && cgoffset < 8) { - shift ^= 4; - if (*esc >= '0' && *esc <= '9') { - value |= (*esc - '0') << shift; - } else if (*esc >= 'A' && *esc <= 'Z') { - value |= (*esc - 'A' + 10) << shift; - } else if (*esc >= 'a' && *esc <= 'z') { - value |= (*esc - 'a' + 10) << shift; - } else { - esc++; - continue; - } - - if (shift == 0) { - cgbytes[cgoffset++] = value; - value = 0; - } - - esc++; - } - - lcd_write_cmd(LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8)); - for (addr = 0; addr < cgoffset; addr++) - lcd_write_data(cgbytes[addr]); - - /* ensures that we stop writing to CGRAM */ - lcd_gotoxy(); - processed = 1; - break; - } - case 'x': /* gotoxy : LxXXX[yYYY]; */ - case 'y': /* gotoxy : LyYYY[xXXX]; */ - if (!strchr(esc, ';')) - break; - - while (*esc) { - if (*esc == 'x') { - esc++; - if (kstrtoul(esc, 10, &lcd.addr.x) < 0) - break; - } else if (*esc == 'y') { - esc++; - if (kstrtoul(esc, 10, &lcd.addr.y) < 0) - break; - } else { - break; - } - } - - lcd_gotoxy(); - processed = 1; - break; - } - - /* TODO: This indent party here got ugly, clean it! */ - /* Check whether one flag was changed */ - if (oldflags != lcd.flags) { - /* check whether one of B,C,D flags were changed */ - if ((oldflags ^ lcd.flags) & - (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D)) - /* set display mode */ - lcd_write_cmd(LCD_CMD_DISPLAY_CTRL - | ((lcd.flags & LCD_FLAG_D) - ? LCD_CMD_DISPLAY_ON : 0) - | ((lcd.flags & LCD_FLAG_C) - ? LCD_CMD_CURSOR_ON : 0) - | ((lcd.flags & LCD_FLAG_B) - ? LCD_CMD_BLINK_ON : 0)); - /* check whether one of F,N flags was changed */ - else if ((oldflags ^ lcd.flags) & (LCD_FLAG_F | LCD_FLAG_N)) - lcd_write_cmd(LCD_CMD_FUNCTION_SET - | LCD_CMD_DATA_LEN_8BITS - | ((lcd.flags & LCD_FLAG_F) - ? LCD_CMD_TWO_LINES : 0) - | ((lcd.flags & LCD_FLAG_N) - ? LCD_CMD_FONT_5X10_DOTS - : 0)); - /* check whether L flag was changed */ - else if ((oldflags ^ lcd.flags) & (LCD_FLAG_L)) { - if (lcd.flags & (LCD_FLAG_L)) - lcd_backlight(1); - else if (lcd.light_tempo == 0) - /* - * switch off the light only when the tempo - * lighting is gone - */ - lcd_backlight(0); - } - } - - return processed; -} - -static void lcd_write_char(char c) -{ - /* first, we'll test if we're in escape mode */ - if ((c != '\n') && lcd.esc_seq.len >= 0) { - /* yes, let's add this char to the buffer */ - lcd.esc_seq.buf[lcd.esc_seq.len++] = c; - lcd.esc_seq.buf[lcd.esc_seq.len] = 0; - } else { - /* aborts any previous escape sequence */ - lcd.esc_seq.len = -1; - - switch (c) { - case LCD_ESCAPE_CHAR: - /* start of an escape sequence */ - lcd.esc_seq.len = 0; - lcd.esc_seq.buf[lcd.esc_seq.len] = 0; - break; - case '\b': - /* go back one char and clear it */ - if (lcd.addr.x > 0) { - /* - * check if we're not at the - * end of the line - */ - if (lcd.addr.x < lcd.bwidth) - /* back one char */ - lcd_write_cmd(LCD_CMD_SHIFT); - lcd.addr.x--; - } - /* replace with a space */ - lcd_write_data(' '); - /* back one char again */ - lcd_write_cmd(LCD_CMD_SHIFT); - break; - case '\014': - /* quickly clear the display */ - lcd_clear_fast(); - break; - case '\n': - /* - * flush the remainder of the current line and - * go to the beginning of the next line - */ - for (; lcd.addr.x < lcd.bwidth; lcd.addr.x++) - lcd_write_data(' '); - lcd.addr.x = 0; - lcd.addr.y = (lcd.addr.y + 1) % lcd.height; - lcd_gotoxy(); - break; - case '\r': - /* go to the beginning of the same line */ - lcd.addr.x = 0; - lcd_gotoxy(); - break; - case '\t': - /* print a space instead of the tab */ - lcd_print(' '); - break; - default: - /* simply print this char */ - lcd_print(c); - break; - } - } - - /* - * now we'll see if we're in an escape mode and if the current - * escape sequence can be understood. - */ - if (lcd.esc_seq.len >= 2) { - int processed = 0; - - if (!strcmp(lcd.esc_seq.buf, "[2J")) { - /* clear the display */ - lcd_clear_fast(); - processed = 1; - } else if (!strcmp(lcd.esc_seq.buf, "[H")) { - /* cursor to home */ - lcd.addr.x = 0; - lcd.addr.y = 0; - lcd_gotoxy(); - processed = 1; - } - /* codes starting with ^[[L */ - else if ((lcd.esc_seq.len >= 3) && - (lcd.esc_seq.buf[0] == '[') && - (lcd.esc_seq.buf[1] == 'L')) { - processed = handle_lcd_special_code(); - } - - /* LCD special escape codes */ - /* - * flush the escape sequence if it's been processed - * or if it is getting too long. - */ - if (processed || (lcd.esc_seq.len >= LCD_ESCAPE_LEN)) - lcd.esc_seq.len = -1; - } /* escape codes */ -} - -static ssize_t lcd_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - const char __user *tmp = buf; - char c; - - for (; count-- > 0; (*ppos)++, tmp++) { - if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) - /* - * let's be a little nice with other processes - * that need some CPU - */ - schedule(); - - if (get_user(c, tmp)) - return -EFAULT; - - lcd_write_char(c); - } - - return tmp - buf; -} - -static int lcd_open(struct inode *inode, struct file *file) -{ - if (!atomic_dec_and_test(&lcd_available)) - return -EBUSY; /* open only once at a time */ - - if (file->f_mode & FMODE_READ) /* device is write-only */ - return -EPERM; - - if (lcd.must_clear) { - lcd_clear_display(); - lcd.must_clear = false; - } - return nonseekable_open(inode, file); -} - -static int lcd_release(struct inode *inode, struct file *file) -{ - atomic_inc(&lcd_available); - return 0; -} - -static const struct file_operations lcd_fops = { - .write = lcd_write, - .open = lcd_open, - .release = lcd_release, - .llseek = no_llseek, -}; - -static struct miscdevice lcd_dev = { - .minor = LCD_MINOR, - .name = "lcd", - .fops = &lcd_fops, -}; - -/* public function usable from the kernel for any purpose */ -static void panel_lcd_print(const char *s) -{ - const char *tmp = s; - int count = strlen(s); - - if (lcd.enabled && lcd.initialized) { - for (; count-- > 0; tmp++) { - if (!in_interrupt() && (((count + 1) & 0x1f) == 0)) - /* - * let's be a little nice with other processes - * that need some CPU - */ - schedule(); - - lcd_write_char(*tmp); - } - } -} - -/* initialize the LCD driver */ -static void lcd_init(void) -{ - switch (selected_lcd_type) { - case LCD_TYPE_OLD: - /* parallel mode, 8 bits */ - lcd.proto = LCD_PROTO_PARALLEL; - lcd.charset = LCD_CHARSET_NORMAL; - lcd.pins.e = PIN_STROBE; - lcd.pins.rs = PIN_AUTOLF; - - lcd.width = 40; - lcd.bwidth = 40; - lcd.hwidth = 64; - lcd.height = 2; - break; - case LCD_TYPE_KS0074: - /* serial mode, ks0074 */ - lcd.proto = LCD_PROTO_SERIAL; - lcd.charset = LCD_CHARSET_KS0074; - lcd.pins.bl = PIN_AUTOLF; - lcd.pins.cl = PIN_STROBE; - lcd.pins.da = PIN_D0; - - lcd.width = 16; - lcd.bwidth = 40; - lcd.hwidth = 16; - lcd.height = 2; - break; - case LCD_TYPE_NEXCOM: - /* parallel mode, 8 bits, generic */ - lcd.proto = LCD_PROTO_PARALLEL; - lcd.charset = LCD_CHARSET_NORMAL; - lcd.pins.e = PIN_AUTOLF; - lcd.pins.rs = PIN_SELECP; - lcd.pins.rw = PIN_INITP; - - lcd.width = 16; - lcd.bwidth = 40; - lcd.hwidth = 64; - lcd.height = 2; - break; - case LCD_TYPE_CUSTOM: - /* customer-defined */ - lcd.proto = DEFAULT_LCD_PROTO; - lcd.charset = DEFAULT_LCD_CHARSET; - /* default geometry will be set later */ - break; - case LCD_TYPE_HANTRONIX: - /* parallel mode, 8 bits, hantronix-like */ - default: - lcd.proto = LCD_PROTO_PARALLEL; - lcd.charset = LCD_CHARSET_NORMAL; - lcd.pins.e = PIN_STROBE; - lcd.pins.rs = PIN_SELECP; - - lcd.width = 16; - lcd.bwidth = 40; - lcd.hwidth = 64; - lcd.height = 2; - break; - } - - /* Overwrite with module params set on loading */ - if (lcd_height != NOT_SET) - lcd.height = lcd_height; - if (lcd_width != NOT_SET) - lcd.width = lcd_width; - if (lcd_bwidth != NOT_SET) - lcd.bwidth = lcd_bwidth; - if (lcd_hwidth != NOT_SET) - lcd.hwidth = lcd_hwidth; - if (lcd_charset != NOT_SET) - lcd.charset = lcd_charset; - if (lcd_proto != NOT_SET) - lcd.proto = lcd_proto; - if (lcd_e_pin != PIN_NOT_SET) - lcd.pins.e = lcd_e_pin; - if (lcd_rs_pin != PIN_NOT_SET) - lcd.pins.rs = lcd_rs_pin; - if (lcd_rw_pin != PIN_NOT_SET) - lcd.pins.rw = lcd_rw_pin; - if (lcd_cl_pin != PIN_NOT_SET) - lcd.pins.cl = lcd_cl_pin; - if (lcd_da_pin != PIN_NOT_SET) - lcd.pins.da = lcd_da_pin; - if (lcd_bl_pin != PIN_NOT_SET) - lcd.pins.bl = lcd_bl_pin; - - /* this is used to catch wrong and default values */ - if (lcd.width <= 0) - lcd.width = DEFAULT_LCD_WIDTH; - if (lcd.bwidth <= 0) - lcd.bwidth = DEFAULT_LCD_BWIDTH; - if (lcd.hwidth <= 0) - lcd.hwidth = DEFAULT_LCD_HWIDTH; - if (lcd.height <= 0) - lcd.height = DEFAULT_LCD_HEIGHT; - - if (lcd.proto == LCD_PROTO_SERIAL) { /* SERIAL */ - lcd_write_cmd = lcd_write_cmd_s; - lcd_write_data = lcd_write_data_s; - lcd_clear_fast = lcd_clear_fast_s; - - if (lcd.pins.cl == PIN_NOT_SET) - lcd.pins.cl = DEFAULT_LCD_PIN_SCL; - if (lcd.pins.da == PIN_NOT_SET) - lcd.pins.da = DEFAULT_LCD_PIN_SDA; - - } else if (lcd.proto == LCD_PROTO_PARALLEL) { /* PARALLEL */ - lcd_write_cmd = lcd_write_cmd_p8; - lcd_write_data = lcd_write_data_p8; - lcd_clear_fast = lcd_clear_fast_p8; - - if (lcd.pins.e == PIN_NOT_SET) - lcd.pins.e = DEFAULT_LCD_PIN_E; - if (lcd.pins.rs == PIN_NOT_SET) - lcd.pins.rs = DEFAULT_LCD_PIN_RS; - if (lcd.pins.rw == PIN_NOT_SET) - lcd.pins.rw = DEFAULT_LCD_PIN_RW; - } else { - lcd_write_cmd = lcd_write_cmd_tilcd; - lcd_write_data = lcd_write_data_tilcd; - lcd_clear_fast = lcd_clear_fast_tilcd; - } - - if (lcd.pins.bl == PIN_NOT_SET) - lcd.pins.bl = DEFAULT_LCD_PIN_BL; - - if (lcd.pins.e == PIN_NOT_SET) - lcd.pins.e = PIN_NONE; - if (lcd.pins.rs == PIN_NOT_SET) - lcd.pins.rs = PIN_NONE; - if (lcd.pins.rw == PIN_NOT_SET) - lcd.pins.rw = PIN_NONE; - if (lcd.pins.bl == PIN_NOT_SET) - lcd.pins.bl = PIN_NONE; - if (lcd.pins.cl == PIN_NOT_SET) - lcd.pins.cl = PIN_NONE; - if (lcd.pins.da == PIN_NOT_SET) - lcd.pins.da = PIN_NONE; - - if (lcd.charset == NOT_SET) - lcd.charset = DEFAULT_LCD_CHARSET; - - if (lcd.charset == LCD_CHARSET_KS0074) - lcd_char_conv = lcd_char_conv_ks0074; - else - lcd_char_conv = NULL; - - if (lcd.pins.bl != PIN_NONE) - init_scan_timer(); - - pin_to_bits(lcd.pins.e, lcd_bits[LCD_PORT_D][LCD_BIT_E], - lcd_bits[LCD_PORT_C][LCD_BIT_E]); - pin_to_bits(lcd.pins.rs, lcd_bits[LCD_PORT_D][LCD_BIT_RS], - lcd_bits[LCD_PORT_C][LCD_BIT_RS]); - pin_to_bits(lcd.pins.rw, lcd_bits[LCD_PORT_D][LCD_BIT_RW], - lcd_bits[LCD_PORT_C][LCD_BIT_RW]); - pin_to_bits(lcd.pins.bl, lcd_bits[LCD_PORT_D][LCD_BIT_BL], - lcd_bits[LCD_PORT_C][LCD_BIT_BL]); - pin_to_bits(lcd.pins.cl, lcd_bits[LCD_PORT_D][LCD_BIT_CL], - lcd_bits[LCD_PORT_C][LCD_BIT_CL]); - pin_to_bits(lcd.pins.da, lcd_bits[LCD_PORT_D][LCD_BIT_DA], - lcd_bits[LCD_PORT_C][LCD_BIT_DA]); - - /* - * before this line, we must NOT send anything to the display. - * Since lcd_init_display() needs to write data, we have to - * enable mark the LCD initialized just before. - */ - lcd.initialized = true; - lcd_init_display(); - - /* display a short message */ -#ifdef CONFIG_PANEL_CHANGE_MESSAGE -#ifdef CONFIG_PANEL_BOOT_MESSAGE - panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*" CONFIG_PANEL_BOOT_MESSAGE); -#endif -#else - panel_lcd_print("\x1b[Lc\x1b[Lb\x1b[L*Linux-" UTS_RELEASE "\nPanel-" - PANEL_VERSION); -#endif - lcd.addr.x = 0; - lcd.addr.y = 0; - /* clear the display on the next device opening */ - lcd.must_clear = true; - lcd_gotoxy(); -} - -/* - * These are the file operation function for user access to /dev/keypad - */ - -static ssize_t keypad_read(struct file *file, - char __user *buf, size_t count, loff_t *ppos) -{ - unsigned i = *ppos; - char __user *tmp = buf; - - if (keypad_buflen == 0) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - if (wait_event_interruptible(keypad_read_wait, - keypad_buflen != 0)) - return -EINTR; - } - - for (; count-- > 0 && (keypad_buflen > 0); - ++i, ++tmp, --keypad_buflen) { - put_user(keypad_buffer[keypad_start], tmp); - keypad_start = (keypad_start + 1) % KEYPAD_BUFFER; - } - *ppos = i; - - return tmp - buf; -} - -static int keypad_open(struct inode *inode, struct file *file) -{ - if (!atomic_dec_and_test(&keypad_available)) - return -EBUSY; /* open only once at a time */ - - if (file->f_mode & FMODE_WRITE) /* device is read-only */ - return -EPERM; - - keypad_buflen = 0; /* flush the buffer on opening */ - return 0; -} - -static int keypad_release(struct inode *inode, struct file *file) -{ - atomic_inc(&keypad_available); - return 0; -} - -static const struct file_operations keypad_fops = { - .read = keypad_read, /* read */ - .open = keypad_open, /* open */ - .release = keypad_release, /* close */ - .llseek = default_llseek, -}; - -static struct miscdevice keypad_dev = { - .minor = KEYPAD_MINOR, - .name = "keypad", - .fops = &keypad_fops, -}; - -static void keypad_send_key(const char *string, int max_len) -{ - /* send the key to the device only if a process is attached to it. */ - if (!atomic_read(&keypad_available)) { - while (max_len-- && keypad_buflen < KEYPAD_BUFFER && *string) { - keypad_buffer[(keypad_start + keypad_buflen++) % - KEYPAD_BUFFER] = *string++; - } - wake_up_interruptible(&keypad_read_wait); - } -} - -/* this function scans all the bits involving at least one logical signal, - * and puts the results in the bitfield "phys_read" (one bit per established - * contact), and sets "phys_read_prev" to "phys_read". - * - * Note: to debounce input signals, we will only consider as switched a signal - * which is stable across 2 measures. Signals which are different between two - * reads will be kept as they previously were in their logical form (phys_prev). - * A signal which has just switched will have a 1 in - * (phys_read ^ phys_read_prev). - */ -static void phys_scan_contacts(void) -{ - int bit, bitval; - char oldval; - char bitmask; - char gndmask; - - phys_prev = phys_curr; - phys_read_prev = phys_read; - phys_read = 0; /* flush all signals */ - - /* keep track of old value, with all outputs disabled */ - oldval = r_dtr(pprt) | scan_mask_o; - /* activate all keyboard outputs (active low) */ - w_dtr(pprt, oldval & ~scan_mask_o); - - /* will have a 1 for each bit set to gnd */ - bitmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; - /* disable all matrix signals */ - w_dtr(pprt, oldval); - - /* now that all outputs are cleared, the only active input bits are - * directly connected to the ground - */ - - /* 1 for each grounded input */ - gndmask = PNL_PINPUT(r_str(pprt)) & scan_mask_i; - - /* grounded inputs are signals 40-44 */ - phys_read |= (__u64)gndmask << 40; - - if (bitmask != gndmask) { - /* - * since clearing the outputs changed some inputs, we know - * that some input signals are currently tied to some outputs. - * So we'll scan them. - */ - for (bit = 0; bit < 8; bit++) { - bitval = BIT(bit); - - if (!(scan_mask_o & bitval)) /* skip unused bits */ - continue; - - w_dtr(pprt, oldval & ~bitval); /* enable this output */ - bitmask = PNL_PINPUT(r_str(pprt)) & ~gndmask; - phys_read |= (__u64)bitmask << (5 * bit); - } - w_dtr(pprt, oldval); /* disable all outputs */ - } - /* - * this is easy: use old bits when they are flapping, - * use new ones when stable - */ - phys_curr = (phys_prev & (phys_read ^ phys_read_prev)) | - (phys_read & ~(phys_read ^ phys_read_prev)); -} - -static inline int input_state_high(struct logical_input *input) -{ -#if 0 - /* FIXME: - * this is an invalid test. It tries to catch - * transitions from single-key to multiple-key, but - * doesn't take into account the contacts polarity. - * The only solution to the problem is to parse keys - * from the most complex to the simplest combinations, - * and mark them as 'caught' once a combination - * matches, then unmatch it for all other ones. - */ - - /* try to catch dangerous transitions cases : - * someone adds a bit, so this signal was a false - * positive resulting from a transition. We should - * invalidate the signal immediately and not call the - * release function. - * eg: 0 -(press A)-> A -(press B)-> AB : don't match A's release. - */ - if (((phys_prev & input->mask) == input->value) && - ((phys_curr & input->mask) > input->value)) { - input->state = INPUT_ST_LOW; /* invalidate */ - return 1; - } -#endif - - if ((phys_curr & input->mask) == input->value) { - if ((input->type == INPUT_TYPE_STD) && - (input->high_timer == 0)) { - input->high_timer++; - if (input->u.std.press_fct) - input->u.std.press_fct(input->u.std.press_data); - } else if (input->type == INPUT_TYPE_KBD) { - /* will turn on the light */ - keypressed = 1; - - if (input->high_timer == 0) { - char *press_str = input->u.kbd.press_str; - - if (press_str[0]) { - int s = sizeof(input->u.kbd.press_str); - - keypad_send_key(press_str, s); - } - } - - if (input->u.kbd.repeat_str[0]) { - char *repeat_str = input->u.kbd.repeat_str; - - if (input->high_timer >= KEYPAD_REP_START) { - int s = sizeof(input->u.kbd.repeat_str); - - input->high_timer -= KEYPAD_REP_DELAY; - keypad_send_key(repeat_str, s); - } - /* we will need to come back here soon */ - inputs_stable = 0; - } - - if (input->high_timer < 255) - input->high_timer++; - } - return 1; - } - - /* else signal falling down. Let's fall through. */ - input->state = INPUT_ST_FALLING; - input->fall_timer = 0; - - return 0; -} - -static inline void input_state_falling(struct logical_input *input) -{ -#if 0 - /* FIXME !!! same comment as in input_state_high */ - if (((phys_prev & input->mask) == input->value) && - ((phys_curr & input->mask) > input->value)) { - input->state = INPUT_ST_LOW; /* invalidate */ - return; - } -#endif - - if ((phys_curr & input->mask) == input->value) { - if (input->type == INPUT_TYPE_KBD) { - /* will turn on the light */ - keypressed = 1; - - if (input->u.kbd.repeat_str[0]) { - char *repeat_str = input->u.kbd.repeat_str; - - if (input->high_timer >= KEYPAD_REP_START) { - int s = sizeof(input->u.kbd.repeat_str); - - input->high_timer -= KEYPAD_REP_DELAY; - keypad_send_key(repeat_str, s); - } - /* we will need to come back here soon */ - inputs_stable = 0; - } - - if (input->high_timer < 255) - input->high_timer++; - } - input->state = INPUT_ST_HIGH; - } else if (input->fall_timer >= input->fall_time) { - /* call release event */ - if (input->type == INPUT_TYPE_STD) { - void (*release_fct)(int) = input->u.std.release_fct; - - if (release_fct) - release_fct(input->u.std.release_data); - } else if (input->type == INPUT_TYPE_KBD) { - char *release_str = input->u.kbd.release_str; - - if (release_str[0]) { - int s = sizeof(input->u.kbd.release_str); - - keypad_send_key(release_str, s); - } - } - - input->state = INPUT_ST_LOW; - } else { - input->fall_timer++; - inputs_stable = 0; - } -} - -static void panel_process_inputs(void) -{ - struct list_head *item; - struct logical_input *input; - - keypressed = 0; - inputs_stable = 1; - list_for_each(item, &logical_inputs) { - input = list_entry(item, struct logical_input, list); - - switch (input->state) { - case INPUT_ST_LOW: - if ((phys_curr & input->mask) != input->value) - break; - /* if all needed ones were already set previously, - * this means that this logical signal has been - * activated by the releasing of another combined - * signal, so we don't want to match. - * eg: AB -(release B)-> A -(release A)-> 0 : - * don't match A. - */ - if ((phys_prev & input->mask) == input->value) - break; - input->rise_timer = 0; - input->state = INPUT_ST_RISING; - /* no break here, fall through */ - case INPUT_ST_RISING: - if ((phys_curr & input->mask) != input->value) { - input->state = INPUT_ST_LOW; - break; - } - if (input->rise_timer < input->rise_time) { - inputs_stable = 0; - input->rise_timer++; - break; - } - input->high_timer = 0; - input->state = INPUT_ST_HIGH; - /* no break here, fall through */ - case INPUT_ST_HIGH: - if (input_state_high(input)) - break; - /* no break here, fall through */ - case INPUT_ST_FALLING: - input_state_falling(input); - } - } -} - -static void panel_scan_timer(void) -{ - if (keypad.enabled && keypad_initialized) { - if (spin_trylock_irq(&pprt_lock)) { - phys_scan_contacts(); - - /* no need for the parport anymore */ - spin_unlock_irq(&pprt_lock); - } - - if (!inputs_stable || phys_curr != phys_prev) - panel_process_inputs(); - } - - if (lcd.enabled && lcd.initialized) { - if (keypressed) { - if (lcd.light_tempo == 0 && - ((lcd.flags & LCD_FLAG_L) == 0)) - lcd_backlight(1); - lcd.light_tempo = FLASH_LIGHT_TEMPO; - } else if (lcd.light_tempo > 0) { - lcd.light_tempo--; - if (lcd.light_tempo == 0 && - ((lcd.flags & LCD_FLAG_L) == 0)) - lcd_backlight(0); - } - } - - mod_timer(&scan_timer, jiffies + INPUT_POLL_TIME); -} - -static void init_scan_timer(void) -{ - if (scan_timer.function) - return; /* already started */ - - setup_timer(&scan_timer, (void *)&panel_scan_timer, 0); - scan_timer.expires = jiffies + INPUT_POLL_TIME; - add_timer(&scan_timer); -} - -/* converts a name of the form "({BbAaPpSsEe}{01234567-})*" to a series of bits. - * if or are non-null, they will be or'ed with the bits - * corresponding to out and in bits respectively. - * returns 1 if ok, 0 if error (in which case, nothing is written). - */ -static u8 input_name2mask(const char *name, __u64 *mask, __u64 *value, - u8 *imask, u8 *omask) -{ - const char sigtab[] = "EeSsPpAaBb"; - u8 im, om; - __u64 m, v; - - om = 0; - im = 0; - m = 0ULL; - v = 0ULL; - while (*name) { - int in, out, bit, neg; - const char *idx; - - idx = strchr(sigtab, *name); - if (!idx) - return 0; /* input name not found */ - - in = idx - sigtab; - neg = (in & 1); /* odd (lower) names are negated */ - in >>= 1; - im |= BIT(in); - - name++; - if (*name >= '0' && *name <= '7') { - out = *name - '0'; - om |= BIT(out); - } else if (*name == '-') { - out = 8; - } else { - return 0; /* unknown bit name */ - } - - bit = (out * 5) + in; - - m |= 1ULL << bit; - if (!neg) - v |= 1ULL << bit; - name++; - } - *mask = m; - *value = v; - if (imask) - *imask |= im; - if (omask) - *omask |= om; - return 1; -} - -/* tries to bind a key to the signal name . The key will send the - * strings , , for these respective events. - * Returns the pointer to the new key if ok, NULL if the key could not be bound. - */ -static struct logical_input *panel_bind_key(const char *name, const char *press, - const char *repeat, - const char *release) -{ - struct logical_input *key; - - key = kzalloc(sizeof(*key), GFP_KERNEL); - if (!key) - return NULL; - - if (!input_name2mask(name, &key->mask, &key->value, &scan_mask_i, - &scan_mask_o)) { - kfree(key); - return NULL; - } - - key->type = INPUT_TYPE_KBD; - key->state = INPUT_ST_LOW; - key->rise_time = 1; - key->fall_time = 1; - - strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str)); - strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str)); - strncpy(key->u.kbd.release_str, release, - sizeof(key->u.kbd.release_str)); - list_add(&key->list, &logical_inputs); - return key; -} - -#if 0 -/* tries to bind a callback function to the signal name . The function - * will be called with the arg when the signal is - * activated, and so on for / - * Returns the pointer to the new signal if ok, NULL if the signal could not - * be bound. - */ -static struct logical_input *panel_bind_callback(char *name, - void (*press_fct)(int), - int press_data, - void (*release_fct)(int), - int release_data) -{ - struct logical_input *callback; - - callback = kmalloc(sizeof(*callback), GFP_KERNEL); - if (!callback) - return NULL; - - memset(callback, 0, sizeof(struct logical_input)); - if (!input_name2mask(name, &callback->mask, &callback->value, - &scan_mask_i, &scan_mask_o)) - return NULL; - - callback->type = INPUT_TYPE_STD; - callback->state = INPUT_ST_LOW; - callback->rise_time = 1; - callback->fall_time = 1; - callback->u.std.press_fct = press_fct; - callback->u.std.press_data = press_data; - callback->u.std.release_fct = release_fct; - callback->u.std.release_data = release_data; - list_add(&callback->list, &logical_inputs); - return callback; -} -#endif - -static void keypad_init(void) -{ - int keynum; - - init_waitqueue_head(&keypad_read_wait); - keypad_buflen = 0; /* flushes any eventual noisy keystroke */ - - /* Let's create all known keys */ - - for (keynum = 0; keypad_profile[keynum][0][0]; keynum++) { - panel_bind_key(keypad_profile[keynum][0], - keypad_profile[keynum][1], - keypad_profile[keynum][2], - keypad_profile[keynum][3]); - } - - init_scan_timer(); - keypad_initialized = 1; -} - -/**************************************************/ -/* device initialization */ -/**************************************************/ - -static int panel_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - if (lcd.enabled && lcd.initialized) { - switch (code) { - case SYS_DOWN: - panel_lcd_print - ("\x0cReloading\nSystem...\x1b[Lc\x1b[Lb\x1b[L+"); - break; - case SYS_HALT: - panel_lcd_print - ("\x0cSystem Halted.\x1b[Lc\x1b[Lb\x1b[L+"); - break; - case SYS_POWER_OFF: - panel_lcd_print("\x0cPower off.\x1b[Lc\x1b[Lb\x1b[L+"); - break; - default: - break; - } - } - return NOTIFY_DONE; -} - -static struct notifier_block panel_notifier = { - panel_notify_sys, - NULL, - 0 -}; - -static void panel_attach(struct parport *port) -{ - struct pardev_cb panel_cb; - - if (port->number != parport) - return; - - if (pprt) { - pr_err("%s: port->number=%d parport=%d, already registered!\n", - __func__, port->number, parport); - return; - } - - memset(&panel_cb, 0, sizeof(panel_cb)); - panel_cb.private = &pprt; - /* panel_cb.flags = 0 should be PARPORT_DEV_EXCL? */ - - pprt = parport_register_dev_model(port, "panel", &panel_cb, 0); - if (!pprt) { - pr_err("%s: port->number=%d parport=%d, parport_register_device() failed\n", - __func__, port->number, parport); - return; - } - - if (parport_claim(pprt)) { - pr_err("could not claim access to parport%d. Aborting.\n", - parport); - goto err_unreg_device; - } - - /* must init LCD first, just in case an IRQ from the keypad is - * generated at keypad init - */ - if (lcd.enabled) { - lcd_init(); - if (misc_register(&lcd_dev)) - goto err_unreg_device; - } - - if (keypad.enabled) { - keypad_init(); - if (misc_register(&keypad_dev)) - goto err_lcd_unreg; - } - register_reboot_notifier(&panel_notifier); - return; - -err_lcd_unreg: - if (lcd.enabled) - misc_deregister(&lcd_dev); -err_unreg_device: - parport_unregister_device(pprt); - pprt = NULL; -} - -static void panel_detach(struct parport *port) -{ - if (port->number != parport) - return; - - if (!pprt) { - pr_err("%s: port->number=%d parport=%d, nothing to unregister.\n", - __func__, port->number, parport); - return; - } - if (scan_timer.function) - del_timer_sync(&scan_timer); - - if (pprt) { - if (keypad.enabled) { - misc_deregister(&keypad_dev); - keypad_initialized = 0; - } - - if (lcd.enabled) { - panel_lcd_print("\x0cLCD driver " PANEL_VERSION - "\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-"); - misc_deregister(&lcd_dev); - lcd.initialized = false; - } - - /* TODO: free all input signals */ - parport_release(pprt); - parport_unregister_device(pprt); - pprt = NULL; - unregister_reboot_notifier(&panel_notifier); - } -} - -static struct parport_driver panel_driver = { - .name = "panel", - .match_port = panel_attach, - .detach = panel_detach, - .devmodel = true, -}; - -/* init function */ -static int __init panel_init_module(void) -{ - int selected_keypad_type = NOT_SET, err; - - /* take care of an eventual profile */ - switch (profile) { - case PANEL_PROFILE_CUSTOM: - /* custom profile */ - selected_keypad_type = DEFAULT_KEYPAD_TYPE; - selected_lcd_type = DEFAULT_LCD_TYPE; - break; - case PANEL_PROFILE_OLD: - /* 8 bits, 2*16, old keypad */ - selected_keypad_type = KEYPAD_TYPE_OLD; - selected_lcd_type = LCD_TYPE_OLD; - - /* TODO: This two are a little hacky, sort it out later */ - if (lcd_width == NOT_SET) - lcd_width = 16; - if (lcd_hwidth == NOT_SET) - lcd_hwidth = 16; - break; - case PANEL_PROFILE_NEW: - /* serial, 2*16, new keypad */ - selected_keypad_type = KEYPAD_TYPE_NEW; - selected_lcd_type = LCD_TYPE_KS0074; - break; - case PANEL_PROFILE_HANTRONIX: - /* 8 bits, 2*16 hantronix-like, no keypad */ - selected_keypad_type = KEYPAD_TYPE_NONE; - selected_lcd_type = LCD_TYPE_HANTRONIX; - break; - case PANEL_PROFILE_NEXCOM: - /* generic 8 bits, 2*16, nexcom keypad, eg. Nexcom. */ - selected_keypad_type = KEYPAD_TYPE_NEXCOM; - selected_lcd_type = LCD_TYPE_NEXCOM; - break; - case PANEL_PROFILE_LARGE: - /* 8 bits, 2*40, old keypad */ - selected_keypad_type = KEYPAD_TYPE_OLD; - selected_lcd_type = LCD_TYPE_OLD; - break; - } - - /* - * Overwrite selection with module param values (both keypad and lcd), - * where the deprecated params have lower prio. - */ - if (keypad_enabled != NOT_SET) - selected_keypad_type = keypad_enabled; - if (keypad_type != NOT_SET) - selected_keypad_type = keypad_type; - - keypad.enabled = (selected_keypad_type > 0); - - if (lcd_enabled != NOT_SET) - selected_lcd_type = lcd_enabled; - if (lcd_type != NOT_SET) - selected_lcd_type = lcd_type; - - lcd.enabled = (selected_lcd_type > 0); - - if (lcd.enabled) { - /* - * Init lcd struct with load-time values to preserve exact - * current functionality (at least for now). - */ - lcd.height = lcd_height; - lcd.width = lcd_width; - lcd.bwidth = lcd_bwidth; - lcd.hwidth = lcd_hwidth; - lcd.charset = lcd_charset; - lcd.proto = lcd_proto; - lcd.pins.e = lcd_e_pin; - lcd.pins.rs = lcd_rs_pin; - lcd.pins.rw = lcd_rw_pin; - lcd.pins.cl = lcd_cl_pin; - lcd.pins.da = lcd_da_pin; - lcd.pins.bl = lcd_bl_pin; - - /* Leave it for now, just in case */ - lcd.esc_seq.len = -1; - } - - switch (selected_keypad_type) { - case KEYPAD_TYPE_OLD: - keypad_profile = old_keypad_profile; - break; - case KEYPAD_TYPE_NEW: - keypad_profile = new_keypad_profile; - break; - case KEYPAD_TYPE_NEXCOM: - keypad_profile = nexcom_keypad_profile; - break; - default: - keypad_profile = NULL; - break; - } - - if (!lcd.enabled && !keypad.enabled) { - /* no device enabled, let's exit */ - pr_err("driver version " PANEL_VERSION " disabled.\n"); - return -ENODEV; - } - - err = parport_register_driver(&panel_driver); - if (err) { - pr_err("could not register with parport. Aborting.\n"); - return err; - } - - if (pprt) - pr_info("driver version " PANEL_VERSION - " registered on parport%d (io=0x%lx).\n", parport, - pprt->port->base); - else - pr_info("driver version " PANEL_VERSION - " not yet registered\n"); - return 0; -} - -static void __exit panel_cleanup_module(void) -{ - parport_unregister_driver(&panel_driver); -} - -module_init(panel_init_module); -module_exit(panel_cleanup_module); -MODULE_AUTHOR("Willy Tarreau"); -MODULE_LICENSE("GPL"); - -/* - * Local variables: - * c-indent-level: 4 - * tab-width: 8 - * End: - */ -- cgit From de01e10c1571188a02b2fc3be7c3641f9d90d84b Mon Sep 17 00:00:00 2001 From: Niranjan Dighe Date: Wed, 23 Dec 2015 09:40:18 +0000 Subject: staging: lustre: Remove unused memhog functionality Remove IOC_LIBCFS_MEMHOG ioctl functionality as it is no longer needed thereby making functions like - kportal_memhog_alloc(), kportal_memhog_free() and type - struct libcfs_device_userstate unused. Signed-off-by: Niranjan Dighe Acked-by: James Simmons Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_private.h | 5 - .../lustre/lustre/libcfs/linux/linux-module.c | 14 +-- drivers/staging/lustre/lustre/libcfs/module.c | 139 --------------------- 3 files changed, 2 insertions(+), 156 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h index a80d993b882e..dab486261154 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h @@ -387,11 +387,6 @@ int cfs_percpt_atomic_summary(atomic_t **refs); * Support for temporary event tracing with minimal Heisenberg effect. * -------------------------------------------------------------------- */ -struct libcfs_device_userstate { - int ldu_memhog_pages; - struct page *ldu_memhog_root_page; -}; - #define MKSTR(ptr) ((ptr)) ? (ptr) : "" static inline int cfs_size_round4(int val) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index 70a99cf019de..eccfe8bd57a2 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -98,14 +98,12 @@ int libcfs_ioctl_popdata(void *arg, void *data, int size) static int libcfs_psdev_open(struct inode *inode, struct file *file) { - struct libcfs_device_userstate **pdu = NULL; int rc = 0; if (!inode) return -EINVAL; - pdu = (struct libcfs_device_userstate **)&file->private_data; if (libcfs_psdev_ops.p_open != NULL) - rc = libcfs_psdev_ops.p_open(0, (void *)pdu); + rc = libcfs_psdev_ops.p_open(0, NULL); else return -EPERM; return rc; @@ -115,14 +113,12 @@ libcfs_psdev_open(struct inode *inode, struct file *file) static int libcfs_psdev_release(struct inode *inode, struct file *file) { - struct libcfs_device_userstate *pdu; int rc = 0; if (!inode) return -EINVAL; - pdu = file->private_data; if (libcfs_psdev_ops.p_close != NULL) - rc = libcfs_psdev_ops.p_close(0, (void *)pdu); + rc = libcfs_psdev_ops.p_close(0, NULL); else rc = -EPERM; return rc; @@ -152,14 +148,8 @@ static long libcfs_ioctl(struct file *file, return -EPERM; panic("debugctl-invoked panic"); return 0; - case IOC_LIBCFS_MEMHOG: - if (!capable(CFS_CAP_SYS_ADMIN)) - return -EPERM; - /* go thought */ } - pfile.off = 0; - pfile.private_data = file->private_data; if (libcfs_psdev_ops.p_ioctl != NULL) rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); else diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 329d78ce272d..0067e5347884 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -68,142 +68,16 @@ MODULE_LICENSE("GPL"); static struct dentry *lnet_debugfs_root; -static void kportal_memhog_free(struct libcfs_device_userstate *ldu) -{ - struct page **level0p = &ldu->ldu_memhog_root_page; - struct page **level1p; - struct page **level2p; - int count1; - int count2; - - if (*level0p != NULL) { - - level1p = (struct page **)page_address(*level0p); - count1 = 0; - - while (count1 < PAGE_CACHE_SIZE/sizeof(struct page *) && - *level1p != NULL) { - - level2p = (struct page **)page_address(*level1p); - count2 = 0; - - while (count2 < PAGE_CACHE_SIZE/sizeof(struct page *) && - *level2p != NULL) { - - __free_page(*level2p); - ldu->ldu_memhog_pages--; - level2p++; - count2++; - } - - __free_page(*level1p); - ldu->ldu_memhog_pages--; - level1p++; - count1++; - } - - __free_page(*level0p); - ldu->ldu_memhog_pages--; - - *level0p = NULL; - } - - LASSERT(ldu->ldu_memhog_pages == 0); -} - -static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages, - gfp_t flags) -{ - struct page **level0p; - struct page **level1p; - struct page **level2p; - int count1; - int count2; - - LASSERT(ldu->ldu_memhog_pages == 0); - LASSERT(ldu->ldu_memhog_root_page == NULL); - - if (npages < 0) - return -EINVAL; - - if (npages == 0) - return 0; - - level0p = &ldu->ldu_memhog_root_page; - *level0p = alloc_page(flags); - if (*level0p == NULL) - return -ENOMEM; - ldu->ldu_memhog_pages++; - - level1p = (struct page **)page_address(*level0p); - count1 = 0; - memset(level1p, 0, PAGE_CACHE_SIZE); - - while (ldu->ldu_memhog_pages < npages && - count1 < PAGE_CACHE_SIZE/sizeof(struct page *)) { - - if (cfs_signal_pending()) - return -EINTR; - - *level1p = alloc_page(flags); - if (*level1p == NULL) - return -ENOMEM; - ldu->ldu_memhog_pages++; - - level2p = (struct page **)page_address(*level1p); - count2 = 0; - memset(level2p, 0, PAGE_CACHE_SIZE); - - while (ldu->ldu_memhog_pages < npages && - count2 < PAGE_CACHE_SIZE/sizeof(struct page *)) { - - if (cfs_signal_pending()) - return -EINTR; - - *level2p = alloc_page(flags); - if (*level2p == NULL) - return -ENOMEM; - ldu->ldu_memhog_pages++; - - level2p++; - count2++; - } - - level1p++; - count1++; - } - - return 0; -} - /* called when opening /dev/device */ static int libcfs_psdev_open(unsigned long flags, void *args) { - struct libcfs_device_userstate *ldu; - try_module_get(THIS_MODULE); - - LIBCFS_ALLOC(ldu, sizeof(*ldu)); - if (ldu != NULL) { - ldu->ldu_memhog_pages = 0; - ldu->ldu_memhog_root_page = NULL; - } - *(struct libcfs_device_userstate **)args = ldu; - return 0; } /* called when closing /dev/device */ static int libcfs_psdev_release(unsigned long flags, void *args) { - struct libcfs_device_userstate *ldu; - - ldu = (struct libcfs_device_userstate *)args; - if (ldu != NULL) { - kportal_memhog_free(ldu); - LIBCFS_FREE(ldu, sizeof(*ldu)); - } - module_put(THIS_MODULE); return 0; } @@ -260,19 +134,6 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd, return -EINVAL; libcfs_debug_mark_buffer(data->ioc_inlbuf1); return 0; - case IOC_LIBCFS_MEMHOG: - if (pfile->private_data == NULL) { - err = -EINVAL; - } else { - kportal_memhog_free(pfile->private_data); - /* XXX The ioc_flags is not GFP flags now, need to be fixed */ - err = kportal_memhog_alloc(pfile->private_data, - data->ioc_count, - data->ioc_flags); - if (err != 0) - kportal_memhog_free(pfile->private_data); - } - break; default: { struct libcfs_ioctl_handler *hand; -- cgit From d3ae87be4ccc6d241677405f17f984f853822b1b Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 12:32:08 -0500 Subject: staging: lustre: Handle nodemask on UMP machines For UMP and SMP machines the struct cfs_cpt_table are defined differently. In the case handled by this patch nodemask is defined as a integer for the UMP case and as a pointer for the SMP case. This will cause a problem for ost_setup which reads the nodemask directly. Instead we create a UMP version of cfs_cpt_nodemask and use that in ost_setup. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4199 Reviewed-on: http://review.whamcloud.com/9219 Starting in 3.14 kernels nodemask_t was changed from a a unsigned long to a linux bitmap so more than 32 cores could be supported. Using set_bit in cfs_cpt_table_alloc no longer compiles so this patch backports bits of the node management function that use a linux bitmap back end. Cleaned up libcfs bitmap.h to use the libcfs layers memory allocation function. This was pulling in lustre related code that was not defined. Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4993 Reviewed-on: http://review.whamcloud.com/10332 Signed-off-by: James Simmons Reviewed-by: Liang Zhen Reviewed-by: Li Xi Reviewed-by: Andreas Dilger Reviewed-by: Bob Glossman Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c index 933525c73da1..ba97c79a31bd 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c @@ -58,6 +58,7 @@ cfs_cpt_table_alloc(unsigned int ncpt) LIBCFS_ALLOC(cptab, sizeof(*cptab)); if (cptab != NULL) { cptab->ctb_version = CFS_CPU_VERSION_MAGIC; + node_set(0, cptab->ctb_nodemask); cptab->ctb_nparts = ncpt; } @@ -111,6 +112,13 @@ cfs_cpt_online(struct cfs_cpt_table *cptab, int cpt) } EXPORT_SYMBOL(cfs_cpt_online); +nodemask_t * +cfs_cpt_nodemask(struct cfs_cpt_table *cptab, int cpt) +{ + return &cptab->ctb_nodemask; +} +EXPORT_SYMBOL(cfs_cpt_cpumask); + int cfs_cpt_set_cpu(struct cfs_cpt_table *cptab, int cpt, int cpu) { -- cgit From a161de8608909e8d07fb162bf3dabdbf9190c69d Mon Sep 17 00:00:00 2001 From: frank zago Date: Wed, 23 Dec 2015 12:32:11 -0500 Subject: staging: lustre: add sparse locking annotations Adds __acquires / __releases / __must_hold sparse locking annotations to several functions. Fixes sparse warnings such as: libcfs/libcfs/hash.c:127:1: warning: context imbalance in 'cfs_hash_spin_lock' - wrong count at exit libcfs/libcfs/hash.c:133:1: warning: context imbalance in 'cfs_hash_spin_unlock' - unexpected unlock libcfs/libcfs/hash.c:141:9: warning: context imbalance in 'cfs_hash_rw_lock' - wrong count at exit include/linux/rwlock_api_smp.h:221:9: warning: context imbalance in 'cfs_hash_rw_unlock' - unexpected unlock Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5396 Reviewed-on: http://review.whamcloud.com/11295 Reviewed-by: John L. Hammond Reviewed-by: Patrick Farrell Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 3 +-- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 1 + drivers/staging/lustre/lustre/libcfs/libcfs_lock.c | 2 ++ drivers/staging/lustre/lustre/osc/osc_cache.c | 3 +++ drivers/staging/lustre/lustre/ptlrpc/client.c | 1 + 5 files changed, 8 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 c7b9ccb13f1c..176c79b95692 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -750,8 +750,7 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, static int kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) - __releases(conn->ibc_lock) - __acquires(conn->ibc_lock) + __must_hold(&conn->ibc_lock) { kib_msg_t *msg = tx->tx_msg; kib_peer_t *peer = conn->ibc_peer; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 477b385f15e0..a0955d21fec2 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -2336,6 +2336,7 @@ ksocknal_flush_stale_txs(ksock_peer_t *peer) static int ksocknal_send_keepalive_locked(ksock_peer_t *peer) + __must_hold(&ksocknal_data.ksnd_global_lock) { ksock_sched_t *sched; ksock_conn_t *conn; diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c index 15782d9e6aa9..32db78803d46 100644 --- a/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c +++ b/drivers/staging/lustre/lustre/libcfs/libcfs_lock.c @@ -90,6 +90,7 @@ EXPORT_SYMBOL(cfs_percpt_lock_alloc); */ void cfs_percpt_lock(struct cfs_percpt_lock *pcl, int index) + __acquires(pcl->pcl_locks) { int ncpt = cfs_cpt_number(pcl->pcl_cptab); int i; @@ -124,6 +125,7 @@ EXPORT_SYMBOL(cfs_percpt_lock); /** unlock a CPU partition */ void cfs_percpt_unlock(struct cfs_percpt_lock *pcl, int index) + __releases(pcl->pcl_locks) { int ncpt = cfs_cpt_number(pcl->pcl_cptab); int i; diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c index 2229419b7184..6b5f8d0d53df 100644 --- a/drivers/staging/lustre/lustre/osc/osc_cache.c +++ b/drivers/staging/lustre/lustre/osc/osc_cache.c @@ -1938,6 +1938,7 @@ static int get_write_extents(struct osc_object *obj, struct list_head *rpclist) static int osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc) + __must_hold(osc) { LIST_HEAD(rpclist); struct osc_extent *ext; @@ -2010,6 +2011,7 @@ osc_send_write_rpc(const struct lu_env *env, struct client_obd *cli, static int osc_send_read_rpc(const struct lu_env *env, struct client_obd *cli, struct osc_object *osc) + __must_hold(osc) { struct osc_extent *ext; struct osc_extent *next; @@ -2083,6 +2085,7 @@ static struct osc_object *osc_next_obj(struct client_obd *cli) /* called with the loi list lock held */ static void osc_check_rpcs(const struct lu_env *env, struct client_obd *cli) + __must_hold(&cli->cl_loi_list_lock) { struct osc_object *osc; int rc = 0; diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index efdda09507bf..8f3c26f1398f 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -353,6 +353,7 @@ static int unpack_reply(struct ptlrpc_request *req) * If anything goes wrong just ignore it - same as if it never happened */ static int ptlrpc_at_recv_early_reply(struct ptlrpc_request *req) + __must_hold(&req->rq_lock) { struct ptlrpc_request *early_req; time64_t olddl; -- cgit From 9581c2c44e73d7876d3836e3b09811493e65279e Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Wed, 23 Dec 2015 12:32:10 -0500 Subject: staging: lustre: add debugging ability for LFSCK Add the ability to debug LFSCK to libcfs. This is broken out of patch http://review.whamcloud.com/6321. Signed-off-by: Fan Yong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2914 Reviewed-on: http://review.whamcloud.com/6321 Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h | 2 +- drivers/staging/lustre/lustre/libcfs/debug.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h index a1787bb43483..98430e7108c1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h @@ -106,7 +106,7 @@ struct ptldebug_header { #define S_LOV 0x00020000 #define S_LQUOTA 0x00040000 #define S_OSD 0x00080000 -/* unused */ +#define S_LFSCK 0x00100000 /* unused */ /* unused */ #define S_LMV 0x00800000 /* b_new_cmd */ diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c index 0b38dad13546..6274558421a8 100644 --- a/drivers/staging/lustre/lustre/libcfs/debug.c +++ b/drivers/staging/lustre/lustre/libcfs/debug.c @@ -271,6 +271,8 @@ libcfs_debug_subsys2str(int subsys) return "lquota"; case S_OSD: return "osd"; + case S_LFSCK: + return "lfsck"; case S_LMV: return "lmv"; case S_SEC: -- cgit From 0d8be841081a90b7f73436668a42ebcecc5ca229 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 12:32:09 -0500 Subject: staging: lustre: Use kernel's strncasecmp and remove cfs_get_blocked_sigs Remove libcfs function cfs_strncasecmp() since the kernel already has its own strncasecmp(). Lastly remove from libcfs.h cfs_get_blocked_sigs() since this function no longer exist. Signed-off-by: James Simmons Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3963 Reviewed-on: http://review.whamcloud.com/13070 Reviewed-by: John L. Hammond Reviewed-by: Bob Glossman Reviewed-by: Patrick Farrell Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 1 - drivers/staging/lustre/include/linux/libcfs/libcfs_string.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 0d8a91ee5ffc..1574ae24f46c 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -90,7 +90,6 @@ void cfs_enter_debugger(void); * Defined by platform */ int unshare_fs_struct(void); -sigset_t cfs_get_blocked_sigs(void); sigset_t cfs_block_allsigs(void); sigset_t cfs_block_sigs(unsigned long sigs); sigset_t cfs_block_sigsinv(unsigned long sigs); diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h index d8d2e7dc212e..e02cde5aeca1 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h @@ -44,8 +44,6 @@ #define __LIBCFS_STRING_H__ /* libcfs_string.c */ -/* string comparison ignoring case */ -int cfs_strncasecmp(const char *s1, const char *s2, size_t n); /* Convert a text string to a bitmask */ int cfs_str2mask(const char *str, const char *(*bit2str)(int bit), int *oldmask, int minmask, int allmask); -- cgit From 8b88bcabca1e10d4e7e42f9ad7cefc2aed56d8b1 Mon Sep 17 00:00:00 2001 From: Fan Yong Date: Wed, 23 Dec 2015 12:32:12 -0500 Subject: staging: lustre: enum lu_object_header_flags comma style fix Cleanup the a style issues for the lu_object_header_flags enum by adding a comma for the last field. This is broken out of patch http://review.whamcloud.com/6321. Signed-off-by: Fan Yong Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-2914 Reviewed-on: http://review.whamcloud.com/6321 Reviewed-by: Alex Zhuravlev Reviewed-by: Andreas Dilger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lu_object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index 1d79341a495d..ee1dbb257d5d 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -488,7 +488,7 @@ enum lu_object_header_flags { /** * Mark this object has already been taken out of cache. */ - LU_OBJECT_UNHASHED = 1 + LU_OBJECT_UNHASHED = 1, }; enum lu_object_header_attr { -- cgit From 50a10043fd4c12c008bc607d30a72b59d2f2dee9 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:40 -0500 Subject: staging: lustre: kg_sem semaphore handling is incorrectly During the removal of the cfs wrappers the kg_sem semaphore was handled incorrectly. We need to take a write lock when writing data to the kkuc_groups. The libcfs_kkuc_group_foreach needs to only take a read lock. This makes use match the OpenSFS development branch. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index d8230aec9a2b..1a052ac8524d 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -186,7 +186,7 @@ int libcfs_kkuc_group_put(int group, void *payload) int rc = 0; int one_success = 0; - down_read(&kg_sem); + down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); @@ -198,7 +198,7 @@ int libcfs_kkuc_group_put(int group, void *payload) } } } - up_read(&kg_sem); + up_write(&kg_sem); /* don't return an error if the message has been delivered * at least to one agent */ @@ -230,12 +230,12 @@ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, if (kkuc_groups[group].next == NULL) return 0; - down_write(&kg_sem); + down_read(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp != NULL) rc = cb_func(reg->kr_data, cb_arg); } - up_write(&kg_sem); + up_read(&kg_sem); return rc; } -- cgit From 406fc91338d6848a1dda0e1851dffa5946817e7e Mon Sep 17 00:00:00 2001 From: Henri Doreau Date: Wed, 23 Dec 2015 16:24:41 -0500 Subject: staging: lustre: Prevent duplicate CT registrations Associate copytool registration to a given MDC import so that multiple mounts of the same filesystem do not lead to having the copytool registered multiple time. Signed-off-by: Henri Doreau Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-3882 Reviewed-on: http://review.whamcloud.com/7612 Reviewed-by: John L. Hammond Reviewed-by: Jinshan Xiong Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../include/linux/libcfs/libcfs_kernelcomm.h | 6 ++-- .../staging/lustre/lustre/include/lustre_export.h | 7 ++++ .../lustre/lustre/libcfs/kernel_user_comm.c | 15 +++++---- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 39 ++++++++++++++++------ drivers/staging/lustre/lustre/mdc/mdc_request.c | 22 +++++++----- 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h index 41f3d810aea4..3a89a3ba4553 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h @@ -77,7 +77,7 @@ enum kuc_generic_message_type { }; /* prototype for callback function on kuc groups */ -typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg); +typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); /* KUC Broadcast Groups. This determines which userspace process hears which * messages. Mutliple transports may be used within a group, or multiple @@ -92,8 +92,8 @@ typedef int (*libcfs_kkuc_cb_t)(__u32 data, void *cb_arg); int libcfs_kkuc_msg_put(struct file *fp, void *payload); int libcfs_kkuc_group_put(int group, void *payload); int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, - __u32 data); -int libcfs_kkuc_group_rem(int uid, int group); + void *data); +int libcfs_kkuc_group_rem(int uid, int group, void **pdata); int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, void *cb_arg); diff --git a/drivers/staging/lustre/lustre/include/lustre_export.h b/drivers/staging/lustre/lustre/include/lustre_export.h index 311e5aa9b0db..a030a98f5656 100644 --- a/drivers/staging/lustre/lustre/include/lustre_export.h +++ b/drivers/staging/lustre/lustre/include/lustre_export.h @@ -338,6 +338,13 @@ static inline bool imp_connect_disp_stripe(struct obd_import *imp) struct obd_export *class_conn2export(struct lustre_handle *conn); +#define KKUC_CT_DATA_MAGIC 0x092013cea +struct kkuc_ct_data { + __u32 kcd_magic; + struct obd_uuid kcd_uuid; + __u32 kcd_archive; +}; + /** @} export */ #endif /* __EXPORT_H */ diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c index 1a052ac8524d..3b4731aff9ed 100644 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c @@ -95,10 +95,10 @@ EXPORT_SYMBOL(libcfs_kkuc_msg_put); * group from any fs */ /** A single group registration has a uid and a file pointer */ struct kkuc_reg { - struct list_head kr_chain; - int kr_uid; + struct list_head kr_chain; + int kr_uid; struct file *kr_fp; - __u32 kr_data; + void *kr_data; }; static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; @@ -109,9 +109,10 @@ static DECLARE_RWSEM(kg_sem); * @param filp pipe to write into * @param uid identifier for this receiver * @param group group number + * @param data user data */ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, - __u32 data) + void *data) { struct kkuc_reg *reg; @@ -145,7 +146,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group) +int libcfs_kkuc_group_rem(int uid, int group, void **pdata) { struct kkuc_reg *reg, *next; @@ -171,6 +172,8 @@ int libcfs_kkuc_group_rem(int uid, int group) reg->kr_uid, reg->kr_fp, group); if (reg->kr_fp != NULL) fput(reg->kr_fp); + if (pdata) + *pdata = reg->kr_data; kfree(reg); } } @@ -213,7 +216,7 @@ EXPORT_SYMBOL(libcfs_kkuc_group_put); * Calls a callback function for each link of the given kuc group. * @param group the group to call the function on. * @param cb_func the function to be called. - * @param cb_arg iextra argument to be passed to the callback function. + * @param cb_arg extra argument to be passed to the callback function. */ int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, void *cb_arg) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index bbafe0a710d8..e2f181edf68f 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -794,7 +794,9 @@ static void lmv_hsm_req_build(struct lmv_obd *lmv, static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { - int i, rc = 0; + struct kkuc_ct_data *kcd = NULL; + int rc = 0; + __u32 i; /* unregister request (call from llapi_hsm_copytool_fini) */ for (i = 0; i < lmv->desc.ld_tgt_count; i++) { @@ -807,17 +809,21 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, * Unreached coordinators will get EPIPE on next requests * and will unregister automatically. */ - rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group); + rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group, (void **)&kcd); + if (kcd) + kfree(kcd); + return rc; } static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { - struct file *filp; - int i, j, err; - int rc = 0; - bool any_set = false; + struct file *filp; + __u32 i, j; + int err, rc = 0; + bool any_set = false; + struct kkuc_ct_data *kcd; /* All or nothing: try to register to all MDS. * In case of failure, unregister from previous MDS, @@ -854,12 +860,25 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, /* at least one registration done, with no failure */ filp = fget(lk->lk_wfd); - if (filp == NULL) { + if (!filp) return -EBADF; - } - rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, lk->lk_data); - if (rc != 0 && filp != NULL) + + kcd = kzalloc(sizeof(*kcd), GFP_NOFS); + if (!kcd) { fput(filp); + return -ENOMEM; + } + kcd->kcd_magic = KKUC_CT_DATA_MAGIC; + kcd->kcd_uuid = lmv->cluuid; + kcd->kcd_archive = lk->lk_data; + + rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, kcd); + if (rc) { + if (filp) + fput(filp); + kfree(kcd); + } + return rc; } diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 57e0fc1e8549..1936b491e59a 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2013,21 +2013,27 @@ static int mdc_hsm_copytool_send(int len, void *val) /** * callback function passed to kuc for re-registering each HSM copytool * running on MDC, after MDT shutdown/recovery. - * @param data archive id served by the copytool + * @param data copytool registration data * @param cb_arg callback argument (obd_import) */ -static int mdc_hsm_ct_reregister(__u32 data, void *cb_arg) +static int mdc_hsm_ct_reregister(void *data, void *cb_arg) { + struct kkuc_ct_data *kcd = data; struct obd_import *imp = (struct obd_import *)cb_arg; - __u32 archive = data; int rc; - CDEBUG(D_HA, "recover copytool registration to MDT (archive=%#x)\n", - archive); - rc = mdc_ioc_hsm_ct_register(imp, archive); + if (!kcd || kcd->kcd_magic != KKUC_CT_DATA_MAGIC) + return -EPROTO; + + if (!obd_uuid_equals(&kcd->kcd_uuid, &imp->imp_obd->obd_uuid)) + return 0; + + CDEBUG(D_HA, "%s: recover copytool registration to MDT (archive=%#x)\n", + imp->imp_obd->obd_name, kcd->kcd_archive); + rc = mdc_ioc_hsm_ct_register(imp, kcd->kcd_archive); /* ignore error if the copytool is already registered */ - return ((rc != 0) && (rc != -EEXIST)) ? rc : 0; + return (rc == -EEXIST) ? 0 : rc; } static int mdc_set_info_async(const struct lu_env *env, @@ -2369,7 +2375,7 @@ static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) case OBD_CLEANUP_EXPORTS: /* Failsafe, ok if racy */ if (obd->obd_type->typ_refcnt <= 1) - libcfs_kkuc_group_rem(0, KUC_GRP_HSM); + libcfs_kkuc_group_rem(0, KUC_GRP_HSM, NULL); obd_cleanup_client_import(obd); ptlrpc_lprocfs_unregister_obd(obd); -- cgit From db953dad0ceb8a25a4f6669edef1dd5c12d72f94 Mon Sep 17 00:00:00 2001 From: frank zago Date: Wed, 23 Dec 2015 16:24:42 -0500 Subject: staging: lustre: move kernel_user_comm.c from libcfs to lustre Move the kernel portion from libcfs to obdclass. This code is only used by lustre. This is broken out of the original patch 14270. The part covered by this change is as follows: The original code in kernel_user_comm.c is split into two parts: * obdclass/kernelcomm.c for the kernel part. filp_user_write() was moved there, and linux-fs.c deleted; * liblustreapi_kernelconn.c for the user part. The calls to CDEBUG have been removed, and calls to CERROR have been transformed to llapi_err_noerrno. The type lustre_kernelcomm has been removed and replace by struct lustre_kernelcomm. Various names and filenames have been harmonized to *kernelcomm*. Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14270 Reviewed-by: Nathan Rutman Reviewed-by: James Simmons 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/libcfs/Makefile | 5 +- .../lustre/lustre/libcfs/kernel_user_comm.c | 245 --------------------- drivers/staging/lustre/lustre/obdclass/Makefile | 10 +- .../staging/lustre/lustre/obdclass/kernelcomm.c | 245 +++++++++++++++++++++ 4 files changed, 252 insertions(+), 253 deletions(-) delete mode 100644 drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c create mode 100644 drivers/staging/lustre/lustre/obdclass/kernelcomm.c diff --git a/drivers/staging/lustre/lustre/libcfs/Makefile b/drivers/staging/lustre/lustre/libcfs/Makefile index 03d3f3d7b1f8..277c1235eb32 100644 --- a/drivers/staging/lustre/lustre/libcfs/Makefile +++ b/drivers/staging/lustre/lustre/libcfs/Makefile @@ -11,8 +11,7 @@ libcfs-linux-objs += linux-mem.o libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs)) libcfs-all-objs := debug.o fail.o module.o tracefile.o \ - libcfs_string.o hash.o kernel_user_comm.o \ - prng.o workitem.o libcfs_cpu.o \ - libcfs_mem.o libcfs_lock.o + libcfs_string.o hash.o prng.o workitem.o \ + libcfs_cpu.o libcfs_mem.o libcfs_lock.o libcfs-objs := $(libcfs-linux-objs) $(libcfs-all-objs) diff --git a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c b/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c deleted file mode 100644 index 3b4731aff9ed..000000000000 --- a/drivers/staging/lustre/lustre/libcfs/kernel_user_comm.c +++ /dev/null @@ -1,245 +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) 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * Author: Nathan Rutman - * - * Kernel <-> userspace communication routines. - * Using pipes for all arches. - */ - -#define DEBUG_SUBSYSTEM S_CLASS -#define D_KUC D_OTHER - -#include "../../include/linux/libcfs/libcfs.h" - -/* This is the kernel side (liblustre as well). */ - -/** - * libcfs_kkuc_msg_put - send an message from kernel to userspace - * @param fp to send the message to - * @param payload Payload data. First field of payload is always - * struct kuc_hdr - */ -int libcfs_kkuc_msg_put(struct file *filp, void *payload) -{ - struct kuc_hdr *kuch = (struct kuc_hdr *)payload; - ssize_t count = kuch->kuc_msglen; - loff_t offset = 0; - mm_segment_t fs; - int rc = -ENOSYS; - - if (filp == NULL || IS_ERR(filp)) - return -EBADF; - - if (kuch->kuc_magic != KUC_MAGIC) { - CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic); - return -ENOSYS; - } - - fs = get_fs(); - set_fs(KERNEL_DS); - while (count > 0) { - rc = vfs_write(filp, (void __force __user *)payload, - count, &offset); - if (rc < 0) - break; - count -= rc; - payload += rc; - rc = 0; - } - set_fs(fs); - - if (rc < 0) - CWARN("message send failed (%d)\n", rc); - else - CDEBUG(D_KUC, "Sent message rc=%d, fp=%p\n", rc, filp); - - return rc; -} -EXPORT_SYMBOL(libcfs_kkuc_msg_put); - -/* Broadcast groups are global across all mounted filesystems; - * i.e. registering for a group on 1 fs will get messages for that - * group from any fs */ -/** A single group registration has a uid and a file pointer */ -struct kkuc_reg { - struct list_head kr_chain; - int kr_uid; - struct file *kr_fp; - void *kr_data; -}; - -static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; -/* Protect message sending against remove and adds */ -static DECLARE_RWSEM(kg_sem); - -/** Add a receiver to a broadcast group - * @param filp pipe to write into - * @param uid identifier for this receiver - * @param group group number - * @param data user data - */ -int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, - void *data) -{ - struct kkuc_reg *reg; - - if (group > KUC_GRP_MAX) { - CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); - return -EINVAL; - } - - /* fput in group_rem */ - if (filp == NULL) - return -EBADF; - - /* freed in group_rem */ - reg = kmalloc(sizeof(*reg), 0); - if (reg == NULL) - return -ENOMEM; - - reg->kr_fp = filp; - reg->kr_uid = uid; - reg->kr_data = data; - - down_write(&kg_sem); - if (kkuc_groups[group].next == NULL) - INIT_LIST_HEAD(&kkuc_groups[group]); - list_add(®->kr_chain, &kkuc_groups[group]); - up_write(&kg_sem); - - CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group); - - return 0; -} -EXPORT_SYMBOL(libcfs_kkuc_group_add); - -int libcfs_kkuc_group_rem(int uid, int group, void **pdata) -{ - struct kkuc_reg *reg, *next; - - if (kkuc_groups[group].next == NULL) - return 0; - - if (uid == 0) { - /* Broadcast a shutdown message */ - struct kuc_hdr lh; - - lh.kuc_magic = KUC_MAGIC; - lh.kuc_transport = KUC_TRANSPORT_GENERIC; - lh.kuc_msgtype = KUC_MSG_SHUTDOWN; - lh.kuc_msglen = sizeof(lh); - libcfs_kkuc_group_put(group, &lh); - } - - down_write(&kg_sem); - list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { - if ((uid == 0) || (uid == reg->kr_uid)) { - list_del(®->kr_chain); - CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", - reg->kr_uid, reg->kr_fp, group); - if (reg->kr_fp != NULL) - fput(reg->kr_fp); - if (pdata) - *pdata = reg->kr_data; - kfree(reg); - } - } - up_write(&kg_sem); - - return 0; -} -EXPORT_SYMBOL(libcfs_kkuc_group_rem); - -int libcfs_kkuc_group_put(int group, void *payload) -{ - struct kkuc_reg *reg; - int rc = 0; - int one_success = 0; - - down_write(&kg_sem); - list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) { - rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - if (rc == 0) - one_success = 1; - else if (rc == -EPIPE) { - fput(reg->kr_fp); - reg->kr_fp = NULL; - } - } - } - up_write(&kg_sem); - - /* don't return an error if the message has been delivered - * at least to one agent */ - if (one_success) - rc = 0; - - return rc; -} -EXPORT_SYMBOL(libcfs_kkuc_group_put); - -/** - * Calls a callback function for each link of the given kuc group. - * @param group the group to call the function on. - * @param cb_func the function to be called. - * @param cb_arg extra argument to be passed to the callback function. - */ -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, - void *cb_arg) -{ - struct kkuc_reg *reg; - int rc = 0; - - if (group > KUC_GRP_MAX) { - CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); - return -EINVAL; - } - - /* no link for this group */ - if (kkuc_groups[group].next == NULL) - return 0; - - down_read(&kg_sem); - list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) - rc = cb_func(reg->kr_data, cb_arg); - } - up_read(&kg_sem); - - return rc; -} -EXPORT_SYMBOL(libcfs_kkuc_group_foreach); diff --git a/drivers/staging/lustre/lustre/obdclass/Makefile b/drivers/staging/lustre/lustre/obdclass/Makefile index acc685712ce9..c404eb3864ff 100644 --- a/drivers/staging/lustre/lustre/obdclass/Makefile +++ b/drivers/staging/lustre/lustre/obdclass/Makefile @@ -2,8 +2,8 @@ obj-$(CONFIG_LUSTRE_FS) += obdclass.o obdclass-y := linux/linux-module.o linux/linux-obdo.o linux/linux-sysctl.o \ llog.o llog_cat.o llog_obd.o llog_swab.o class_obd.o debug.o \ - genops.o uuid.o lprocfs_status.o \ - lustre_handles.o lustre_peer.o \ - statfs_pack.o obdo.o obd_config.o obd_mount.o \ - lu_object.o cl_object.o \ - cl_page.o cl_lock.o cl_io.o lu_ref.o acl.o lprocfs_counters.o + genops.o uuid.o lprocfs_status.o lprocfs_counters.o \ + lustre_handles.o lustre_peer.o statfs_pack.o \ + obdo.o obd_config.o obd_mount.o lu_object.o lu_ref.o \ + cl_object.o cl_page.o cl_lock.o cl_io.o \ + acl.o kernelcomm.o diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c new file mode 100644 index 000000000000..3b4731aff9ed --- /dev/null +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -0,0 +1,245 @@ +/* + * 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) 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2012, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * Author: Nathan Rutman + * + * Kernel <-> userspace communication routines. + * Using pipes for all arches. + */ + +#define DEBUG_SUBSYSTEM S_CLASS +#define D_KUC D_OTHER + +#include "../../include/linux/libcfs/libcfs.h" + +/* This is the kernel side (liblustre as well). */ + +/** + * libcfs_kkuc_msg_put - send an message from kernel to userspace + * @param fp to send the message to + * @param payload Payload data. First field of payload is always + * struct kuc_hdr + */ +int libcfs_kkuc_msg_put(struct file *filp, void *payload) +{ + struct kuc_hdr *kuch = (struct kuc_hdr *)payload; + ssize_t count = kuch->kuc_msglen; + loff_t offset = 0; + mm_segment_t fs; + int rc = -ENOSYS; + + if (filp == NULL || IS_ERR(filp)) + return -EBADF; + + if (kuch->kuc_magic != KUC_MAGIC) { + CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic); + return -ENOSYS; + } + + fs = get_fs(); + set_fs(KERNEL_DS); + while (count > 0) { + rc = vfs_write(filp, (void __force __user *)payload, + count, &offset); + if (rc < 0) + break; + count -= rc; + payload += rc; + rc = 0; + } + set_fs(fs); + + if (rc < 0) + CWARN("message send failed (%d)\n", rc); + else + CDEBUG(D_KUC, "Sent message rc=%d, fp=%p\n", rc, filp); + + return rc; +} +EXPORT_SYMBOL(libcfs_kkuc_msg_put); + +/* Broadcast groups are global across all mounted filesystems; + * i.e. registering for a group on 1 fs will get messages for that + * group from any fs */ +/** A single group registration has a uid and a file pointer */ +struct kkuc_reg { + struct list_head kr_chain; + int kr_uid; + struct file *kr_fp; + void *kr_data; +}; + +static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; +/* Protect message sending against remove and adds */ +static DECLARE_RWSEM(kg_sem); + +/** Add a receiver to a broadcast group + * @param filp pipe to write into + * @param uid identifier for this receiver + * @param group group number + * @param data user data + */ +int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, + void *data) +{ + struct kkuc_reg *reg; + + if (group > KUC_GRP_MAX) { + CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); + return -EINVAL; + } + + /* fput in group_rem */ + if (filp == NULL) + return -EBADF; + + /* freed in group_rem */ + reg = kmalloc(sizeof(*reg), 0); + if (reg == NULL) + return -ENOMEM; + + reg->kr_fp = filp; + reg->kr_uid = uid; + reg->kr_data = data; + + down_write(&kg_sem); + if (kkuc_groups[group].next == NULL) + INIT_LIST_HEAD(&kkuc_groups[group]); + list_add(®->kr_chain, &kkuc_groups[group]); + up_write(&kg_sem); + + CDEBUG(D_KUC, "Added uid=%d fp=%p to group %d\n", uid, filp, group); + + return 0; +} +EXPORT_SYMBOL(libcfs_kkuc_group_add); + +int libcfs_kkuc_group_rem(int uid, int group, void **pdata) +{ + struct kkuc_reg *reg, *next; + + if (kkuc_groups[group].next == NULL) + return 0; + + if (uid == 0) { + /* Broadcast a shutdown message */ + struct kuc_hdr lh; + + lh.kuc_magic = KUC_MAGIC; + lh.kuc_transport = KUC_TRANSPORT_GENERIC; + lh.kuc_msgtype = KUC_MSG_SHUTDOWN; + lh.kuc_msglen = sizeof(lh); + libcfs_kkuc_group_put(group, &lh); + } + + down_write(&kg_sem); + list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { + if ((uid == 0) || (uid == reg->kr_uid)) { + list_del(®->kr_chain); + CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", + reg->kr_uid, reg->kr_fp, group); + if (reg->kr_fp != NULL) + fput(reg->kr_fp); + if (pdata) + *pdata = reg->kr_data; + kfree(reg); + } + } + up_write(&kg_sem); + + return 0; +} +EXPORT_SYMBOL(libcfs_kkuc_group_rem); + +int libcfs_kkuc_group_put(int group, void *payload) +{ + struct kkuc_reg *reg; + int rc = 0; + int one_success = 0; + + down_write(&kg_sem); + list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { + if (reg->kr_fp != NULL) { + rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); + if (rc == 0) + one_success = 1; + else if (rc == -EPIPE) { + fput(reg->kr_fp); + reg->kr_fp = NULL; + } + } + } + up_write(&kg_sem); + + /* don't return an error if the message has been delivered + * at least to one agent */ + if (one_success) + rc = 0; + + return rc; +} +EXPORT_SYMBOL(libcfs_kkuc_group_put); + +/** + * Calls a callback function for each link of the given kuc group. + * @param group the group to call the function on. + * @param cb_func the function to be called. + * @param cb_arg extra argument to be passed to the callback function. + */ +int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, + void *cb_arg) +{ + struct kkuc_reg *reg; + int rc = 0; + + if (group > KUC_GRP_MAX) { + CDEBUG(D_WARNING, "Kernelcomm: bad group %d\n", group); + return -EINVAL; + } + + /* no link for this group */ + if (kkuc_groups[group].next == NULL) + return 0; + + down_read(&kg_sem); + list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { + if (reg->kr_fp != NULL) + rc = cb_func(reg->kr_data, cb_arg); + } + up_read(&kg_sem); + + return rc; +} +EXPORT_SYMBOL(libcfs_kkuc_group_foreach); -- cgit From e2780478fe011f80ef9d872e3b6941f946dcb6b2 Mon Sep 17 00:00:00 2001 From: frank zago Date: Wed, 23 Dec 2015 16:24:43 -0500 Subject: staging: lustre: split kernel comm between user and kernel Split the kernel comm header in libcfs into two new headers to handle both kernel space and user space for the lustre layer. This is broken out of the original patch 14270. The part covered by this change is as follows: The original libcfs_kernelcomm.h header is split into three parts: * lustre_kernelcomm.h, a new header for the kernel parts; * uapi_kernelcomm.h, a new header for the data structures shared between userspace and kernelspace; * lustreapi_internal.h receives the private liblustreapi prototypes. Various names and filenames have been harmonized to *kernelcomm*. The unused symbol KUC_FL_BLOCK has been removed. Signed-off-by: frank zago Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6245 Reviewed-on: http://review.whamcloud.com/14270 Reviewed-by: Nathan Rutman Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Reviewed-by: John L. Hammond Reviewed-by: Oleg Drokin Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/libcfs/libcfs.h | 1 - .../include/linux/libcfs/libcfs_kernelcomm.h | 118 --------------------- .../lustre/lustre/include/lustre_kernelcomm.h | 55 ++++++++++ .../lustre/lustre/include/uapi_kernelcomm.h | 92 ++++++++++++++++ drivers/staging/lustre/lustre/llite/dir.c | 1 + drivers/staging/lustre/lustre/lmv/lmv_obd.c | 1 + drivers/staging/lustre/lustre/mdc/mdc_request.c | 1 + drivers/staging/lustre/lustre/obdclass/genops.c | 1 + .../staging/lustre/lustre/obdclass/kernelcomm.c | 5 +- 9 files changed, 153 insertions(+), 122 deletions(-) delete mode 100644 drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h create mode 100644 drivers/staging/lustre/lustre/include/lustre_kernelcomm.h create mode 100644 drivers/staging/lustre/lustre/include/uapi_kernelcomm.h diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 1574ae24f46c..094eb0f27954 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -114,7 +114,6 @@ void cfs_get_random_bytes(void *buf, int size); #include "libcfs_prim.h" #include "libcfs_time.h" #include "libcfs_string.h" -#include "libcfs_kernelcomm.h" #include "libcfs_workitem.h" #include "libcfs_hash.h" #include "libcfs_fail.h" diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h deleted file mode 100644 index 3a89a3ba4553..000000000000 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_kernelcomm.h +++ /dev/null @@ -1,118 +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) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * Author: Nathan Rutman - * - * libcfs/include/libcfs/libcfs_kernelcomm.h - * - * Kernel <-> userspace communication routines. - * The definitions below are used in the kernel and userspace. - * - */ - -#ifndef __LIBCFS_KERNELCOMM_H__ -#define __LIBCFS_KERNELCOMM_H__ - -#ifndef __LIBCFS_LIBCFS_H__ -#error Do not #include this file directly. #include instead -#endif - -/* KUC message header. - * All current and future KUC messages should use this header. - * To avoid having to include Lustre headers from libcfs, define this here. - */ -struct kuc_hdr { - __u16 kuc_magic; - __u8 kuc_transport; /* Each new Lustre feature should use a different - transport */ - __u8 kuc_flags; - __u16 kuc_msgtype; /* Message type or opcode, transport-specific */ - __u16 kuc_msglen; /* Including header */ -} __aligned(sizeof(__u64)); - -#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) - -#define KUC_MAGIC 0x191C /*Lustre9etLinC */ -#define KUC_FL_BLOCK 0x01 /* Wait for send */ - -/* kuc_msgtype values are defined in each transport */ -enum kuc_transport_type { - KUC_TRANSPORT_GENERIC = 1, - KUC_TRANSPORT_HSM = 2, - KUC_TRANSPORT_CHANGELOG = 3, -}; - -enum kuc_generic_message_type { - KUC_MSG_SHUTDOWN = 1, -}; - -/* prototype for callback function on kuc groups */ -typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); - -/* KUC Broadcast Groups. This determines which userspace process hears which - * messages. Mutliple transports may be used within a group, or multiple - * groups may use the same transport. Broadcast - * groups need not be used if e.g. a UID is specified instead; - * use group 0 to signify unicast. - */ -#define KUC_GRP_HSM 0x02 -#define KUC_GRP_MAX KUC_GRP_HSM - -/* Kernel methods */ -int libcfs_kkuc_msg_put(struct file *fp, void *payload); -int libcfs_kkuc_group_put(int group, void *payload); -int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, - void *data); -int libcfs_kkuc_group_rem(int uid, int group, void **pdata); -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, - void *cb_arg); - -#define LK_FLG_STOP 0x01 - -/* kernelcomm control structure, passed from userspace to kernel */ -typedef struct lustre_kernelcomm { - __u32 lk_wfd; - __u32 lk_rfd; - __u32 lk_uid; - __u32 lk_group; - __u32 lk_data; - __u32 lk_flags; -} __packed lustre_kernelcomm; - -/* Userspace methods */ -int libcfs_ukuc_start(lustre_kernelcomm *l, int groups); -int libcfs_ukuc_stop(lustre_kernelcomm *l); -int libcfs_ukuc_msg_get(lustre_kernelcomm *l, char *buf, int maxsize, - int transport); - -#endif /* __LIBCFS_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h new file mode 100644 index 000000000000..9dd057cc56a5 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h @@ -0,0 +1,55 @@ +/* + * 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) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2013 Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * + * Author: Nathan Rutman + * + * Kernel <-> userspace communication routines. + * The definitions below are used in the kernel and userspace. + */ + +#ifndef __LUSTRE_KERNELCOMM_H__ +#define __LUSTRE_KERNELCOMM_H__ + +/* For declarations shared with userspace */ +#include "uapi_kernelcomm.h" + +/* prototype for callback function on kuc groups */ +typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); + +/* Kernel methods */ +int libcfs_kkuc_msg_put(struct file *fp, void *payload); +int libcfs_kkuc_group_put(int group, void *payload); +int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, + void *data); +int libcfs_kkuc_group_rem(int uid, int group, void **pdata); +int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, + void *cb_arg); + +#endif /* __LUSTRE_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h new file mode 100644 index 000000000000..5e0b8de687c1 --- /dev/null +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -0,0 +1,92 @@ +/* + * 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) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2013, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * + * Author: Nathan Rutman + * + * Kernel <-> userspace communication routines. + * The definitions below are used in the kernel and userspace. + */ + +#ifndef __UAPI_KERNELCOMM_H__ +#define __UAPI_KERNELCOMM_H__ + +#include + +/* KUC message header. + * All current and future KUC messages should use this header. + * To avoid having to include Lustre headers from libcfs, define this here. + */ +struct kuc_hdr { + __u16 kuc_magic; + __u8 kuc_transport; /* Each new Lustre feature should use a different + transport */ + __u8 kuc_flags; + __u16 kuc_msgtype; /* Message type or opcode, transport-specific */ + __u16 kuc_msglen; /* Including header */ +} __aligned(sizeof(__u64)); + +#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) + +#define KUC_MAGIC 0x191C /*Lustre9etLinC */ + +/* kuc_msgtype values are defined in each transport */ +enum kuc_transport_type { + KUC_TRANSPORT_GENERIC = 1, + KUC_TRANSPORT_HSM = 2, + KUC_TRANSPORT_CHANGELOG = 3, +}; + +enum kuc_generic_message_type { + KUC_MSG_SHUTDOWN = 1, +}; + +/* KUC Broadcast Groups. This determines which userspace process hears which + * messages. Mutliple transports may be used within a group, or multiple + * groups may use the same transport. Broadcast + * groups need not be used if e.g. a UID is specified instead; + * use group 0 to signify unicast. + */ +#define KUC_GRP_HSM 0x02 +#define KUC_GRP_MAX KUC_GRP_HSM + +#define LK_FLG_STOP 0x01 +#define LK_NOFD -1U + +/* kernelcomm control structure, passed from userspace to kernel */ +struct lustre_kernelcomm { + __u32 lk_wfd; + __u32 lk_rfd; + __u32 lk_uid; + __u32 lk_group; + __u32 lk_data; + __u32 lk_flags; +} __packed; + +#endif /* __UAPI_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 8982f7d1b374..2a5babe555e6 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -55,6 +55,7 @@ #include "../include/lustre_lite.h" #include "../include/lustre_dlm.h" #include "../include/lustre_fid.h" +#include "../include/lustre_kernelcomm.h" #include "llite_internal.h" /* diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index e2f181edf68f..30c73c2d3f51 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -53,6 +53,7 @@ #include "../include/lprocfs_status.h" #include "../include/lustre_lite.h" #include "../include/lustre_fid.h" +#include "../include/lustre_kernelcomm.h" #include "lmv_internal.h" static void lmv_activate_target(struct lmv_obd *lmv, diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 1936b491e59a..6923acef28bd 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -48,6 +48,7 @@ #include "../include/lprocfs_status.h" #include "../include/lustre_param.h" #include "../include/lustre_log.h" +#include "../include/lustre_kernelcomm.h" #include "mdc_internal.h" diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c index 228c44c37c4a..5665655fd6ee 100644 --- a/drivers/staging/lustre/lustre/obdclass/genops.c +++ b/drivers/staging/lustre/lustre/obdclass/genops.c @@ -42,6 +42,7 @@ #define DEBUG_SUBSYSTEM S_CLASS #include "../include/obd_class.h" #include "../include/lprocfs_status.h" +#include "../include/lustre_kernelcomm.h" spinlock_t obd_types_lock; diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 3b4731aff9ed..e3f5a3c40331 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -42,9 +42,8 @@ #define DEBUG_SUBSYSTEM S_CLASS #define D_KUC D_OTHER -#include "../../include/linux/libcfs/libcfs.h" - -/* This is the kernel side (liblustre as well). */ +#include "../include/obd_support.h" +#include "../include/lustre_kernelcomm.h" /** * libcfs_kkuc_msg_put - send an message from kernel to userspace -- cgit From 17328956b0a232c2b50e8e20a078542242759047 Mon Sep 17 00:00:00 2001 From: Hongchao Zhang Date: Wed, 23 Dec 2015 16:24:44 -0500 Subject: staging: lustre: embed kr_data into kkuc_reg In struct kkuc_reg, the "kr_data" is difficult to be freed outside of libcfs, then it's better to change it to be inline data instead of the data pointer. Signed-off-by: Hongchao Zhang Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-6485 Reviewed-on: http://review.whamcloud.com/14638 Reviewed-by: John L. Hammond Reviewed-by: James Simmons Reviewed-by: frank zago Reviewed-by: Robert Read Reviewed-by: Henri Doreau Reviewed-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/lustre/include/lustre_kernelcomm.h | 4 ++-- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 22 +++++++--------------- drivers/staging/lustre/lustre/mdc/mdc_request.c | 2 +- .../staging/lustre/lustre/obdclass/kernelcomm.c | 12 +++++------- 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h index 9dd057cc56a5..cfd415f7e49b 100644 --- a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h @@ -47,8 +47,8 @@ typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); int libcfs_kkuc_msg_put(struct file *fp, void *payload); int libcfs_kkuc_group_put(int group, void *payload); int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, - void *data); -int libcfs_kkuc_group_rem(int uid, int group, void **pdata); + void *data, size_t data_len); +int libcfs_kkuc_group_rem(int uid, int group); int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, void *cb_arg); diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 30c73c2d3f51..9ebfb39a8188 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -795,7 +795,6 @@ static void lmv_hsm_req_build(struct lmv_obd *lmv, static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, struct lustre_kernelcomm *lk, void *uarg) { - struct kkuc_ct_data *kcd = NULL; int rc = 0; __u32 i; @@ -810,9 +809,7 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, * Unreached coordinators will get EPIPE on next requests * and will unregister automatically. */ - rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group, (void **)&kcd); - if (kcd) - kfree(kcd); + rc = libcfs_kkuc_group_rem(lk->lk_uid, lk->lk_group); return rc; } @@ -824,7 +821,7 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, __u32 i, j; int err, rc = 0; bool any_set = false; - struct kkuc_ct_data *kcd; + struct kkuc_ct_data kcd = { 0 }; /* All or nothing: try to register to all MDS. * In case of failure, unregister from previous MDS, @@ -864,20 +861,15 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, if (!filp) return -EBADF; - kcd = kzalloc(sizeof(*kcd), GFP_NOFS); - if (!kcd) { - fput(filp); - return -ENOMEM; - } - kcd->kcd_magic = KKUC_CT_DATA_MAGIC; - kcd->kcd_uuid = lmv->cluuid; - kcd->kcd_archive = lk->lk_data; + kcd.kcd_magic = KKUC_CT_DATA_MAGIC; + kcd.kcd_uuid = lmv->cluuid; + kcd.kcd_archive = lk->lk_data; - rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, kcd); + rc = libcfs_kkuc_group_add(filp, lk->lk_uid, lk->lk_group, + &kcd, sizeof(kcd)); if (rc) { if (filp) fput(filp); - kfree(kcd); } return rc; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 6923acef28bd..3929f9129c8b 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -2376,7 +2376,7 @@ static int mdc_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage) case OBD_CLEANUP_EXPORTS: /* Failsafe, ok if racy */ if (obd->obd_type->typ_refcnt <= 1) - libcfs_kkuc_group_rem(0, KUC_GRP_HSM, NULL); + libcfs_kkuc_group_rem(0, KUC_GRP_HSM); obd_cleanup_client_import(obd); ptlrpc_lprocfs_unregister_obd(obd); diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index e3f5a3c40331..e29024655286 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -97,7 +97,7 @@ struct kkuc_reg { struct list_head kr_chain; int kr_uid; struct file *kr_fp; - void *kr_data; + char kr_data[0]; }; static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; @@ -111,7 +111,7 @@ static DECLARE_RWSEM(kg_sem); * @param data user data */ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, - void *data) + void *data, size_t data_len) { struct kkuc_reg *reg; @@ -125,13 +125,13 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, return -EBADF; /* freed in group_rem */ - reg = kmalloc(sizeof(*reg), 0); + reg = kmalloc(sizeof(*reg) + data_len, 0); if (reg == NULL) return -ENOMEM; reg->kr_fp = filp; reg->kr_uid = uid; - reg->kr_data = data; + memcpy(reg->kr_data, data, data_len); down_write(&kg_sem); if (kkuc_groups[group].next == NULL) @@ -145,7 +145,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group, void **pdata) +int libcfs_kkuc_group_rem(int uid, int group) { struct kkuc_reg *reg, *next; @@ -171,8 +171,6 @@ int libcfs_kkuc_group_rem(int uid, int group, void **pdata) reg->kr_uid, reg->kr_fp, group); if (reg->kr_fp != NULL) fput(reg->kr_fp); - if (pdata) - *pdata = reg->kr_data; kfree(reg); } } -- cgit From 16b376bbef5167783721d10fc633d8f2e698274c Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:45 -0500 Subject: staging: lustre: convert kernelcomm group to unsigned int The group variable was converted to an unsigned int in libcfs_kkuc_group_add() to avoid a potential overflow. The variable group is used in other kernelcomm functions so it makes sense to convert the rest of the group variables to unsigned int. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_kernelcomm.h | 6 +++--- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h index cfd415f7e49b..970610b6de89 100644 --- a/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/lustre_kernelcomm.h @@ -45,11 +45,11 @@ typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg); /* Kernel methods */ int libcfs_kkuc_msg_put(struct file *fp, void *payload); -int libcfs_kkuc_group_put(int group, void *payload); +int libcfs_kkuc_group_put(unsigned int group, void *payload); int libcfs_kkuc_group_add(struct file *fp, int uid, unsigned int group, void *data, size_t data_len); -int libcfs_kkuc_group_rem(int uid, int group); -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, +int libcfs_kkuc_group_rem(int uid, unsigned int group); +int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func, void *cb_arg); #endif /* __LUSTRE_KERNELCOMM_H__ */ diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index e29024655286..1081253eefef 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -145,7 +145,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } EXPORT_SYMBOL(libcfs_kkuc_group_add); -int libcfs_kkuc_group_rem(int uid, int group) +int libcfs_kkuc_group_rem(int uid, unsigned int group) { struct kkuc_reg *reg, *next; @@ -180,7 +180,7 @@ int libcfs_kkuc_group_rem(int uid, int group) } EXPORT_SYMBOL(libcfs_kkuc_group_rem); -int libcfs_kkuc_group_put(int group, void *payload) +int libcfs_kkuc_group_put(unsigned int group, void *payload) { struct kkuc_reg *reg; int rc = 0; @@ -215,7 +215,7 @@ EXPORT_SYMBOL(libcfs_kkuc_group_put); * @param cb_func the function to be called. * @param cb_arg extra argument to be passed to the callback function. */ -int libcfs_kkuc_group_foreach(int group, libcfs_kkuc_cb_t cb_func, +int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func, void *cb_arg) { struct kkuc_reg *reg; -- cgit From fb81e732440d08da9d7ec7f7ac189f8bdd51b8c6 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:46 -0500 Subject: staging: lustre: remove unnecessary NULL checks in kernel_comm.c Fix checkpatch.pl reports of NULL comparison in kernel_comm.c. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 1081253eefef..c9405e689862 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -59,7 +59,7 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) mm_segment_t fs; int rc = -ENOSYS; - if (filp == NULL || IS_ERR(filp)) + if (!filp || IS_ERR(filp)) return -EBADF; if (kuch->kuc_magic != KUC_MAGIC) { @@ -121,12 +121,12 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, } /* fput in group_rem */ - if (filp == NULL) + if (!filp) return -EBADF; /* freed in group_rem */ reg = kmalloc(sizeof(*reg) + data_len, 0); - if (reg == NULL) + if (!reg) return -ENOMEM; reg->kr_fp = filp; @@ -134,7 +134,7 @@ int libcfs_kkuc_group_add(struct file *filp, int uid, unsigned int group, memcpy(reg->kr_data, data, data_len); down_write(&kg_sem); - if (kkuc_groups[group].next == NULL) + if (!kkuc_groups[group].next) INIT_LIST_HEAD(&kkuc_groups[group]); list_add(®->kr_chain, &kkuc_groups[group]); up_write(&kg_sem); @@ -149,7 +149,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) { struct kkuc_reg *reg, *next; - if (kkuc_groups[group].next == NULL) + if (!kkuc_groups[group].next) return 0; if (uid == 0) { @@ -169,7 +169,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) list_del(®->kr_chain); CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", reg->kr_uid, reg->kr_fp, group); - if (reg->kr_fp != NULL) + if (reg->kr_fp) fput(reg->kr_fp); kfree(reg); } @@ -188,7 +188,7 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) down_write(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) { + if (reg->kr_fp) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); if (rc == 0) one_success = 1; @@ -227,12 +227,12 @@ int libcfs_kkuc_group_foreach(unsigned int group, libcfs_kkuc_cb_t cb_func, } /* no link for this group */ - if (kkuc_groups[group].next == NULL) + if (!kkuc_groups[group].next) return 0; down_read(&kg_sem); list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { - if (reg->kr_fp != NULL) + if (reg->kr_fp) rc = cb_func(reg->kr_data, cb_arg); } up_read(&kg_sem); -- cgit From 25c450ea43333a2c47d972467b87a722cba0bb4a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:47 -0500 Subject: staging: lustre: cleanup block comment style in kernel_comm code Fixup the comments to the linux kernel style for the source and headers related to the kernel_comm work. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/uapi_kernelcomm.h | 10 ++++++---- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 12 ++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h index 5e0b8de687c1..a8feab616f75 100644 --- a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -45,11 +45,13 @@ */ struct kuc_hdr { __u16 kuc_magic; - __u8 kuc_transport; /* Each new Lustre feature should use a different - transport */ + /* Each new Lustre feature should use a different transport */ + __u8 kuc_transport; __u8 kuc_flags; - __u16 kuc_msgtype; /* Message type or opcode, transport-specific */ - __u16 kuc_msglen; /* Including header */ + /* Message type or opcode, transport-specific */ + __u16 kuc_msgtype; + /* Including header */ + __u16 kuc_msglen; } __aligned(sizeof(__u64)); #define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index c9405e689862..eb5b0bede6ba 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -89,9 +89,11 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) } EXPORT_SYMBOL(libcfs_kkuc_msg_put); -/* Broadcast groups are global across all mounted filesystems; +/* + * Broadcast groups are global across all mounted filesystems; * i.e. registering for a group on 1 fs will get messages for that - * group from any fs */ + * group from any fs + */ /** A single group registration has a uid and a file pointer */ struct kkuc_reg { struct list_head kr_chain; @@ -200,8 +202,10 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) } up_write(&kg_sem); - /* don't return an error if the message has been delivered - * at least to one agent */ + /* + * don't return an error if the message has been delivered + * at least to one agent + */ if (one_success) rc = 0; -- cgit From 13c26b26066434b3b167e33a075c983a2e480395 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:48 -0500 Subject: staging: lustre: add space around '+' in kernel_comm code Add in missing space arouund '+' in the kernel_comm code. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/uapi_kernelcomm.h | 2 +- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h index a8feab616f75..5ace9f84422c 100644 --- a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -54,7 +54,7 @@ struct kuc_hdr { __u16 kuc_msglen; } __aligned(sizeof(__u64)); -#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr)+CR_MAXSIZE) +#define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr) + CR_MAXSIZE) #define KUC_MAGIC 0x191C /*Lustre9etLinC */ diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index eb5b0bede6ba..709b1ab80939 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -102,7 +102,7 @@ struct kkuc_reg { char kr_data[0]; }; -static struct list_head kkuc_groups[KUC_GRP_MAX+1] = {}; +static struct list_head kkuc_groups[KUC_GRP_MAX + 1] = {}; /* Protect message sending against remove and adds */ static DECLARE_RWSEM(kg_sem); -- cgit From a0d5e63e436629f41c1e8ea6aa0d506192afd75e Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:49 -0500 Subject: staging: lustre: use proper braces in libcfs_kkuc_group_put Add in missing braces for libcfs_kkuc_group_put();. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 709b1ab80939..46cb81ab3c5f 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -192,9 +192,9 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - if (rc == 0) + if (rc == 0) { one_success = 1; - else if (rc == -EPIPE) { + } else if (rc == -EPIPE) { fput(reg->kr_fp); reg->kr_fp = NULL; } -- cgit From 2bab480d1ca9b654eff316eba44fad2eac8884b4 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:50 -0500 Subject: staging: lustre: return proper error code for libcfs_kkuc_msg_put The functon libcfs_kkuc_msg_put() returns -ENOSYS which is not correct. Return -ENXIO instead if the kuc header is corrupt. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 46cb81ab3c5f..281cfd6c2bc7 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -57,14 +57,14 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) ssize_t count = kuch->kuc_msglen; loff_t offset = 0; mm_segment_t fs; - int rc = -ENOSYS; + int rc = -ENXIO; if (!filp || IS_ERR(filp)) return -EBADF; if (kuch->kuc_magic != KUC_MAGIC) { CERROR("KernelComm: bad magic %x\n", kuch->kuc_magic); - return -ENOSYS; + return rc; } fs = get_fs(); -- cgit From a5f533f593c82a3f7ed50c4c0c97078cc7a9487a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:51 -0500 Subject: staging: lustre: fix all conditional comparison to zero for kernelcomm.c Doing if (rc != 0) or if (rc == 0) is bad form. This patch corrects kernelcomm.c to behavior according to kernel coding standards. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 281cfd6c2bc7..285fee0ecaea 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -154,7 +154,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) if (!kkuc_groups[group].next) return 0; - if (uid == 0) { + if (!uid) { /* Broadcast a shutdown message */ struct kuc_hdr lh; @@ -167,7 +167,7 @@ int libcfs_kkuc_group_rem(int uid, unsigned int group) down_write(&kg_sem); list_for_each_entry_safe(reg, next, &kkuc_groups[group], kr_chain) { - if ((uid == 0) || (uid == reg->kr_uid)) { + if (!uid || (uid == reg->kr_uid)) { list_del(®->kr_chain); CDEBUG(D_KUC, "Removed uid=%d fp=%p from group %d\n", reg->kr_uid, reg->kr_fp, group); @@ -192,7 +192,7 @@ int libcfs_kkuc_group_put(unsigned int group, void *payload) list_for_each_entry(reg, &kkuc_groups[group], kr_chain) { if (reg->kr_fp) { rc = libcfs_kkuc_msg_put(reg->kr_fp, payload); - if (rc == 0) { + if (!rc) { one_success = 1; } else if (rc == -EPIPE) { fput(reg->kr_fp); -- cgit From 85de1f5516eb08812d4f5b445481fbde7aacd503 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Wed, 23 Dec 2015 16:24:52 -0500 Subject: staging: lustre: cleanup white space in kernel comm code Cleanup the last white space issues in the kernel comm code. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/uapi_kernelcomm.h | 10 +++++----- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h index 5ace9f84422c..5e998362e44b 100644 --- a/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h +++ b/drivers/staging/lustre/lustre/include/uapi_kernelcomm.h @@ -56,17 +56,17 @@ struct kuc_hdr { #define KUC_CHANGELOG_MSG_MAXSIZE (sizeof(struct kuc_hdr) + CR_MAXSIZE) -#define KUC_MAGIC 0x191C /*Lustre9etLinC */ +#define KUC_MAGIC 0x191C /*Lustre9etLinC */ /* kuc_msgtype values are defined in each transport */ enum kuc_transport_type { - KUC_TRANSPORT_GENERIC = 1, - KUC_TRANSPORT_HSM = 2, - KUC_TRANSPORT_CHANGELOG = 3, + KUC_TRANSPORT_GENERIC = 1, + KUC_TRANSPORT_HSM = 2, + KUC_TRANSPORT_CHANGELOG = 3, }; enum kuc_generic_message_type { - KUC_MSG_SHUTDOWN = 1, + KUC_MSG_SHUTDOWN = 1, }; /* KUC Broadcast Groups. This determines which userspace process hears which diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index 285fee0ecaea..be4867c5446c 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -185,7 +185,7 @@ EXPORT_SYMBOL(libcfs_kkuc_group_rem); int libcfs_kkuc_group_put(unsigned int group, void *payload) { struct kkuc_reg *reg; - int rc = 0; + int rc = 0; int one_success = 0; down_write(&kg_sem); -- cgit From b8947b399dbbce510183521d80f361df462e4383 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:49 -0500 Subject: drivers/staging/lustre: Silence warning about 'inline' Low-hanging fruit first: CC [M] drivers/staging/lustre/lustre/fid/fid_request.o In file included from drivers/staging/lustre/lustre/fid/../include/lustre_net.h:66:0, from drivers/staging/lustre/lustre/fid/../include/lustre_lib.h:64, from drivers/staging/lustre/lustre/fid/../include/obd.h:52, from drivers/staging/lustre/lustre/fid/fid_request.c:48: drivers/staging/lustre/lustre/fid/../include/lu_object.h:765:1: warning: 'inline' is not at beginning of declaration [-Wold-style-declaration] static const inline struct lu_device_operations * ^ So we just swap inline and const. 272 warnings gone. :) Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lu_object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/include/lu_object.h b/drivers/staging/lustre/lustre/include/lu_object.h index ee1dbb257d5d..0b22e5ee99ac 100644 --- a/drivers/staging/lustre/lustre/include/lu_object.h +++ b/drivers/staging/lustre/lustre/include/lu_object.h @@ -756,7 +756,7 @@ static inline const struct lu_fid *lu_object_fid(const struct lu_object *o) /** * return device operations vector for this object */ -static const inline struct lu_device_operations * +static inline const struct lu_device_operations * lu_object_ops(const struct lu_object *o) { return o->lo_dev->ld_ops; -- cgit From f65a0922f024d44a73fa113a833e55f4a5033597 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:50 -0500 Subject: drivers/staging/lustre: Fix set-but-unused whinge. drivers/staging/lustre/lustre/fid/lproc_fid.c: In function 'ldebugfs_fid_write_common': drivers/staging/lustre/lustre/fid/lproc_fid.c:67:6: warning: variable 'rc' set but not used [-Wunused-but-set-variable] int rc; We fix it by *using* the return code to help bulletproof it. It says it's test code - it should be *more* bulletproof than production, not less. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/fid/lproc_fid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/lustre/lustre/fid/lproc_fid.c b/drivers/staging/lustre/lustre/fid/lproc_fid.c index 39f2aa32e984..0320b6e83576 100644 --- a/drivers/staging/lustre/lustre/fid/lproc_fid.c +++ b/drivers/staging/lustre/lustre/fid/lproc_fid.c @@ -85,6 +85,8 @@ ldebugfs_fid_write_common(const char __user *buffer, size_t count, rc = sscanf(kernbuf, "[%llx - %llx]\n", (unsigned long long *)&tmp.lsr_start, (unsigned long long *)&tmp.lsr_end); + if (rc != 2) + return -EINVAL; if (!range_is_sane(&tmp) || range_is_zero(&tmp) || tmp.lsr_start < range->lsr_start || tmp.lsr_end > range->lsr_end) return -EINVAL; -- cgit From 7f6ab07293c8ee6a64783b01840189f894dc3f16 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:51 -0500 Subject: drivers/staging/lustre: Clean up another C warnining: set but not used drivers/staging/lustre/lustre/fid/../include/lustre_cfg.h: In function 'lustre_cfg_free': drivers/staging/lustre/lustre/fid/../include/lustre_cfg.h:253:6: warning: variable 'len' set but not used [-Wunused-but-set-variable] int len; Yep, we're just gonna call kfree, no need to calculate len. Bye-bye. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_cfg.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_cfg.h b/drivers/staging/lustre/lustre/include/lustre_cfg.h index eb6b292b7b25..d30d8b054c92 100644 --- a/drivers/staging/lustre/lustre/include/lustre_cfg.h +++ b/drivers/staging/lustre/lustre/include/lustre_cfg.h @@ -252,10 +252,6 @@ static inline struct lustre_cfg *lustre_cfg_new(int cmd, static inline void lustre_cfg_free(struct lustre_cfg *lcfg) { - int len; - - len = lustre_cfg_len(lcfg->lcfg_bufcount, lcfg->lcfg_buflens); - kfree(lcfg); return; } -- cgit From 5aec2e0791a5a76bec020b088a8b8a10afcfd522 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:52 -0500 Subject: drivers/staging/lustre: Fix another C compiler whine: set but not used CC [M] drivers/staging/lustre/lustre/libcfs/module.o drivers/staging/lustre/lustre/libcfs/module.c: In function 'lustre_insert_debugfs': drivers/staging/lustre/lustre/libcfs/module.c:670:17: warning: variable 'entry' set but not used [-Wunused-but-set-variable] struct dentry *entry; ^ Just ignore the dentry returned, and add a comment that we *know* we're not really leaking the dentry because something else will be able to reap it via recursion. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/module.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index 0067e5347884..af516a29c20e 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -511,8 +511,6 @@ static const struct file_operations lnet_debugfs_file_operations = { void lustre_insert_debugfs(struct ctl_table *table, const struct lnet_debugfs_symlink_def *symlinks) { - struct dentry *entry; - if (lnet_debugfs_root == NULL) lnet_debugfs_root = debugfs_create_dir("lnet", NULL); @@ -520,15 +518,17 @@ void lustre_insert_debugfs(struct ctl_table *table, if (IS_ERR_OR_NULL(lnet_debugfs_root)) return; + /* We don't save the dentry returned in next two calls, because + * we don't call debugfs_remove() but rather remove_recursive() + */ for (; table->procname; table++) - entry = debugfs_create_file(table->procname, table->mode, - lnet_debugfs_root, table, - &lnet_debugfs_file_operations); + debugfs_create_file(table->procname, table->mode, + lnet_debugfs_root, table, + &lnet_debugfs_file_operations); for (; symlinks && symlinks->name; symlinks++) - entry = debugfs_create_symlink(symlinks->name, - lnet_debugfs_root, - symlinks->target); + debugfs_create_symlink(symlinks->name, lnet_debugfs_root, + symlinks->target); } EXPORT_SYMBOL_GPL(lustre_insert_debugfs); -- cgit From bd6455de1a1af6b382b9ee93311397284c165c92 Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:53 -0500 Subject: drivers/staging/lustre: Nuke an unsigned >= 0 assert Writing asserts for almost-never-can-happen things can be valuable. Writing an assert that tests that an "unsigned int" hasn't gone negative isn't. And it generates an *ugly* message: drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ include/linux/compiler.h:137:45: note: in definition of macro 'unlikely' # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ^ drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF' LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ include/linux/compiler.h:137:53: note: in definition of macro 'unlikely' # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ^ drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF' LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ drivers/staging/lustre/lustre/llite/rw.c:763:20: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ include/linux/compiler.h:110:47: note: in definition of macro 'likely_notrace' #define likely_notrace(x) __builtin_expect(!!(x), 1) ^ include/linux/compiler.h:137:58: note: in expansion of macro '__branch_check__' # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) ^ drivers/staging/lustre/lustre/llite/../include/linux/../../../include/linux/libcfs/libcfs_private.h:58:6: note: in expansion of macro 'unlikely' if (unlikely(!(cond))) { \ ^ drivers/staging/lustre/lustre/llite/rw.c:763:2: note: in expansion of macro 'LASSERTF' LASSERTF(reserved >= 0, "reserved %lu\n", reserved); ^ Umm, thank you, GCC. We'll delete the problem line so we never see that spew again. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/rw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index f355474967d6..6b587d66d1b3 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -764,7 +764,6 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, ret = ll_read_ahead_pages(env, io, queue, ria, &reserved, mapping, &ra_end); - LASSERTF(reserved >= 0, "reserved %lu\n", reserved); if (reserved != 0) ll_ra_count_put(ll_i2sbi(inode), reserved); -- cgit From ad0d7799382b37e6afa910f27fa342af62d80ded Mon Sep 17 00:00:00 2001 From: Valdis Kletnieks Date: Tue, 22 Dec 2015 19:36:54 -0500 Subject: drivers/staging/lustre: Nuke another unsigned >= 0 assert Clean up another case of the compiler remininding the programmer they are an idiot: drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c:308:34: warning: comparison of unsigned expression >= 0 is always true [-Wtype-limits] LASSERT(page_pools.epp_waitqlen >= 0); Just lose the assert, and save a page of compiler spew. Signed-off-by: Valdis Kletnieks Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c index 6152c1b766c3..22621c74a66a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c +++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c @@ -304,7 +304,6 @@ static unsigned long enc_pools_cleanup(struct page ***pools, int npools) static inline void enc_pools_wakeup(void) { assert_spin_locked(&page_pools.epp_lock); - LASSERT(page_pools.epp_waitqlen >= 0); if (unlikely(page_pools.epp_waitqlen)) { LASSERT(waitqueue_active(&page_pools.epp_waitq)); -- cgit From a4113d61e53c6cd866f1e760648a41ff95c9b9ba Mon Sep 17 00:00:00 2001 From: Joshua Clayton Date: Sat, 26 Dec 2015 22:47:36 -0800 Subject: staging: lustre: fix lock imbalance nrs_resource_put_safe() might hold a lock one one struct while operating on the other. There are 2 levels of structures. Use nrs_policy_put(), which has locking baked in. sparse gives the following warning: drivers/staging/lustre//lustre/ptlrpc/nrs.c:498:39: warning: context imbalance in 'nrs_resource_put_safe' - different lock contexts for basic block Signed-off-by: Joshua Clayton Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/ptlrpc/nrs.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c index 7044e1ff6692..57acf8c45f9e 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c +++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c @@ -482,7 +482,6 @@ static void nrs_resource_get_safe(struct ptlrpc_nrs *nrs, static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp) { struct ptlrpc_nrs_policy *pols[NRS_RES_MAX]; - struct ptlrpc_nrs *nrs = NULL; int i; for (i = 0; i < NRS_RES_MAX; i++) { @@ -496,18 +495,9 @@ static void nrs_resource_put_safe(struct ptlrpc_nrs_resource **resp) } for (i = 0; i < NRS_RES_MAX; i++) { - if (pols[i] == NULL) - continue; - - if (nrs == NULL) { - nrs = pols[i]->pol_nrs; - spin_lock(&nrs->nrs_lock); - } - nrs_policy_put_locked(pols[i]); + if (pols[i]) + nrs_policy_put(pols[i]); } - - if (nrs != NULL) - spin_unlock(&nrs->nrs_lock); } /** -- cgit From 161106c5fa86cf76c16d5fe71abb8c2e836be842 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 1 Jan 2016 09:37:03 +0100 Subject: staging: lustre: obdecho: constify lu_device_operations and cl_device_operations structures These lu_device_operations and cl_device_operations structures are never modified, so declare them as const. Other structures of these types are already const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdecho/echo_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 7b53f7dd1797..f32f1e72d569 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -582,13 +582,13 @@ static struct lu_object *echo_object_alloc(const struct lu_env *env, return obj; } -static struct lu_device_operations echo_device_lu_ops = { +static const struct lu_device_operations echo_device_lu_ops = { .ldo_object_alloc = echo_object_alloc, }; /** @} echo_lu_dev_ops */ -static struct cl_device_operations echo_device_cl_ops = { +static const struct cl_device_operations echo_device_cl_ops = { }; /** \defgroup echo_init Setup and teardown -- cgit From 98aa7661788198dadf37f71286c4cc703b0c6684 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 1 Jan 2016 10:02:03 +0100 Subject: staging/lustre/llite: constify export_operations structures This export_operations structure is never modified, so declare it as const. Most other structures of this type are already const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/llite_nfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index 845e992ca5fc..e73024778808 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -796,7 +796,7 @@ char *ll_get_fsname(struct super_block *sb, char *buf, int buflen); void ll_open_cleanup(struct super_block *sb, struct ptlrpc_request *open_req); /* llite/llite_nfs.c */ -extern struct export_operations lustre_export_operations; +extern const struct export_operations lustre_export_operations; __u32 get_uuid2int(const char *name, int len); void get_uuid2fsid(const char *name, int len, __kernel_fsid_t *fsid); struct inode *search_inode_for_lustre(struct super_block *sb, diff --git a/drivers/staging/lustre/lustre/llite/llite_nfs.c b/drivers/staging/lustre/lustre/llite/llite_nfs.c index 18aab25f9cd9..9f64dd18f452 100644 --- a/drivers/staging/lustre/lustre/llite/llite_nfs.c +++ b/drivers/staging/lustre/lustre/llite/llite_nfs.c @@ -323,7 +323,7 @@ static struct dentry *ll_get_parent(struct dentry *dchild) return result; } -struct export_operations lustre_export_operations = { +const struct export_operations lustre_export_operations = { .get_parent = ll_get_parent, .encode_fh = ll_encode_fh, .get_name = ll_get_name, -- cgit From fccfde7d5d94327a991244124e01fa1daa9bb543 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:32 -0500 Subject: staging/lustre/lnet: Make lnet_ping static It's not used anywhere outside of api-ni.c anyway. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lib-lnet.h | 2 -- drivers/staging/lustre/lnet/lnet/api-ni.c | 7 +++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index b67a6607bb3b..40acddd728e6 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -662,8 +662,6 @@ void lnet_swap_pinginfo(lnet_ping_info_t *info); int lnet_ping_target_init(void); void lnet_ping_target_fini(void); -int lnet_ping(lnet_process_id_t id, int timeout_ms, - lnet_process_id_t *ids, int n_ids); int lnet_parse_ip2nets(char **networksp, char *ip2nets); int lnet_parse_routes(char *route_str, int *im_a_router); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 362282fa00bf..de453ceb8649 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -61,6 +61,9 @@ static int rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT; module_param(rnet_htable_size, int, 0444); MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table"); +static int lnet_ping(lnet_process_id_t id, int timeout_ms, + lnet_process_id_t *ids, int n_ids); + static char * lnet_get_routes(void) { @@ -1672,8 +1675,8 @@ lnet_ping_target_fini(void) cfs_restore_sigs(blocked); } -int -lnet_ping(lnet_process_id_t id, int timeout_ms, lnet_process_id_t *ids, int n_ids) +static int lnet_ping(lnet_process_id_t id, int timeout_ms, + lnet_process_id_t *ids, int n_ids) { lnet_handle_eq_t eqh; lnet_handle_md_t mdh; -- cgit From 71c36dd795b308df112da7d7f2f8b1a98fb6e7ed Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:33 -0500 Subject: staging/lustre/lnet: Get rid of IOC_LIBCFS_DEBUG_PEER hack IOC_LIBCFS_DEBUG_PEER was added back in the stone ages to print debug statistics on a peer when peer timeout happens. Redo it properly as a separate LNet API call, also get rid of "ioctl" forwarding into the underlying LNDs, since no current LNDs implement this function anymore. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- drivers/staging/lustre/include/linux/lnet/api.h | 1 + drivers/staging/lustre/lnet/lnet/api-ni.c | 38 ++++------------------ drivers/staging/lustre/lustre/ptlrpc/client.c | 2 +- 4 files changed, 10 insertions(+), 33 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 485ab2670918..7c5e5c805fe6 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -123,7 +123,7 @@ struct libcfs_ioctl_handler { #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_DEBUG_PEER _IOWR('e', 62, long) */ #define IOC_LIBCFS_LNETST _IOWR('e', 63, long) /* lnd ioctls */ #define IOC_LIBCFS_REGISTER_MYNID _IOWR('e', 70, long) diff --git a/drivers/staging/lustre/include/linux/lnet/api.h b/drivers/staging/lustre/include/linux/lnet/api.h index 75285fde15e8..fa5fad3582b3 100644 --- a/drivers/staging/lustre/include/linux/lnet/api.h +++ b/drivers/staging/lustre/include/linux/lnet/api.h @@ -197,6 +197,7 @@ int LNetGet(lnet_nid_t self, int LNetSetLazyPortal(int portal); int LNetClearLazyPortal(int portal); int LNetCtl(unsigned int cmd, void *arg); +void LNetDebugPeer(lnet_process_id_t id); /** @} lnet_misc */ diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index de453ceb8649..94ccef56c4bf 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1316,17 +1316,10 @@ LNetNIFini(void) EXPORT_SYMBOL(LNetNIFini); /** - * This is an ugly hack to export IOC_LIBCFS_DEBUG_PEER and - * IOC_LIBCFS_PORTALS_COMPATIBILITY commands to users, by tweaking the LNet - * internal ioctl handler. + * LNet ioctl handler. * * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it. * - * \param cmd IOC_LIBCFS_DEBUG_PEER to print debugging data about a peer. - * The data will be printed to system console. Don't use it excessively. - * \param arg A pointer to lnet_process_id_t, process ID of the peer. - * - * \return Always return 0 when called by users directly (i.e., not via ioctl). */ int LNetCtl(unsigned int cmd, void *arg) @@ -1396,29 +1389,6 @@ LNetCtl(unsigned int cmd, void *arg) data->ioc_count = rc; return 0; - case IOC_LIBCFS_DEBUG_PEER: { - /* CAVEAT EMPTOR: this one designed for calling directly; not - * via an ioctl */ - id = *((lnet_process_id_t *) arg); - - lnet_debug_peer(id.nid); - - ni = lnet_net2ni(LNET_NIDNET(id.nid)); - if (ni == NULL) { - CDEBUG(D_WARNING, "No NI for %s\n", libcfs_id2str(id)); - } else { - if (ni->ni_lnd->lnd_ctl == NULL) { - CDEBUG(D_WARNING, "No ctl for %s\n", - libcfs_id2str(id)); - } else { - (void)ni->ni_lnd->lnd_ctl(ni, cmd, arg); - } - - lnet_ni_decref(ni); - } - return 0; - } - default: ni = lnet_net2ni(data->ioc_net); if (ni == NULL) @@ -1436,6 +1406,12 @@ LNetCtl(unsigned int cmd, void *arg) } EXPORT_SYMBOL(LNetCtl); +void LNetDebugPeer(lnet_process_id_t id) +{ + lnet_debug_peer(id.nid); +} +EXPORT_SYMBOL(LNetDebugPeer); + /** * Retrieve the lnet_process_id_t ID of LNet interface at \a index. Note that * all interfaces share a same PID, as requested by LNetNIInit(). diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 8f3c26f1398f..1cc3c69a175a 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -1884,7 +1884,7 @@ int ptlrpc_expire_one_request(struct ptlrpc_request *req, int async_unlink) (s64)req->rq_sent, (s64)req->rq_real_sent); if (imp != NULL && obd_debug_peer_on_timeout) - LNetCtl(IOC_LIBCFS_DEBUG_PEER, &imp->imp_connection->c_peer); + LNetDebugPeer(imp->imp_connection->c_peer); ptlrpc_unregister_reply(req, async_unlink); ptlrpc_unregister_bulk(req, async_unlink); -- cgit From ee11f9223eeec882c3dfe2ca0af18feb53ff8ddf Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:34 -0500 Subject: staging/lustre/lnet: Get rid of IOC_LIBCFS_PORTALS_COMPATIBILITY ioctl This has been unused for ages and could be safely removed now. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 2 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 6 ------ drivers/staging/lustre/lustre/ptlrpc/events.c | 11 ----------- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 7c5e5c805fe6..3b16fcef1dad 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -118,7 +118,7 @@ struct libcfs_ioctl_handler { #define IOC_LIBCFS_GET_ROUTE _IOWR('e', 54, 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_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) diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 94ccef56c4bf..80b170ee5582 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1318,8 +1318,6 @@ EXPORT_SYMBOL(LNetNIFini); /** * LNet ioctl handler. * - * IOC_LIBCFS_PORTALS_COMPATIBILITY is now deprecated, don't use it. - * */ int LNetCtl(unsigned int cmd, void *arg) @@ -1360,10 +1358,6 @@ LNetCtl(unsigned int cmd, void *arg) return lnet_notify(NULL, data->ioc_nid, data->ioc_flags, jiffies - secs_passed * HZ); - case IOC_LIBCFS_PORTALS_COMPATIBILITY: - /* This can be removed once lustre stops calling it */ - return 0; - case IOC_LIBCFS_LNET_DIST: rc = LNetDist(data->ioc_nid, &data->ioc_nid, &data->ioc_u32[1]); if (rc < 0 && rc != -EHOSTUNREACH) diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c index 990156986986..07e76a2b1291 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/events.c +++ b/drivers/staging/lustre/lustre/ptlrpc/events.c @@ -438,14 +438,11 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid, __u32 best_order = 0; int count = 0; int rc = -ENOENT; - int portals_compatibility; int dist; __u32 order; lnet_nid_t dst_nid; lnet_nid_t src_nid; - portals_compatibility = LNetCtl(IOC_LIBCFS_PORTALS_COMPATIBILITY, NULL); - peer->pid = LUSTRE_SRV_LNET_PID; /* Choose the matching UUID that's closest */ @@ -466,14 +463,6 @@ int ptlrpc_uuid_to_peer(struct obd_uuid *uuid, best_dist = dist; best_order = order; - if (portals_compatibility > 1) { - /* Strong portals compatibility: Zero the nid's - * NET, so if I'm reading new config logs, or - * getting configured by (new) lconf I can - * still talk to old servers. */ - dst_nid = LNET_MKNID(0, LNET_NIDADDR(dst_nid)); - src_nid = LNET_MKNID(0, LNET_NIDADDR(src_nid)); - } peer->nid = dst_nid; *self = src_nid; rc = 0; -- cgit From 6973cd73af2068d029edae419515381df7bfd7e5 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:35 -0500 Subject: staging/lustre/obdecho: Remove unused ioctls Remove long unused ECHO_IOC_GET_STRIPE, ECHO_IOC_SET_STRIPE, ECHO_IOC_ENQUEUE and ECHO_IOC_CANCEL ioctls. Signed-off-by: John L. Hammond Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 8 +- .../staging/lustre/lustre/obdecho/echo_client.c | 163 --------------------- 2 files changed, 4 insertions(+), 167 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 428469fec534..7daf9543f32c 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -365,10 +365,10 @@ static inline void obd_ioctl_freedata(char *buf, int len) /* OBD_IOC_LLOG_CATINFO is deprecated */ #define OBD_IOC_LLOG_CATINFO _IOWR('f', 196, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) -#define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) +/* #define ECHO_IOC_GET_STRIPE _IOWR('f', 200, OBD_IOC_DATA_TYPE) */ +/* #define ECHO_IOC_SET_STRIPE _IOWR('f', 201, OBD_IOC_DATA_TYPE) */ +/* #define ECHO_IOC_ENQUEUE _IOWR('f', 202, OBD_IOC_DATA_TYPE) */ +/* #define ECHO_IOC_CANCEL _IOWR('f', 203, OBD_IOC_DATA_TYPE) */ #define OBD_IOC_GET_OBJ_VERSION _IOR('f', 210, OBD_IOC_DATA_TYPE) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index f32f1e72d569..ec8a26bd0835 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -162,9 +162,6 @@ struct echo_object_conf *cl2echo_conf(const struct cl_object_conf *c) static struct echo_object *cl_echo_object_find(struct echo_device *d, struct lov_stripe_md **lsm); static int cl_echo_object_put(struct echo_object *eco); -static int cl_echo_enqueue(struct echo_object *eco, u64 start, - u64 end, int mode, __u64 *cookie); -static int cl_echo_cancel(struct echo_device *d, __u64 cookie); static int cl_echo_object_brw(struct echo_object *eco, int rw, u64 offset, struct page **pages, int npages, int async); @@ -1076,36 +1073,6 @@ static int cl_echo_enqueue0(struct lu_env *env, struct echo_object *eco, return rc; } -static int cl_echo_enqueue(struct echo_object *eco, u64 start, u64 end, - int mode, __u64 *cookie) -{ - struct echo_thread_info *info; - struct lu_env *env; - struct cl_io *io; - int refcheck; - int result; - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - return PTR_ERR(env); - - info = echo_env_info(env); - io = &info->eti_io; - - io->ci_ignore_layout = 1; - result = cl_io_init(env, io, CIT_MISC, echo_obj2cl(eco)); - if (result < 0) - goto out; - LASSERT(result == 0); - - result = cl_echo_enqueue0(env, eco, start, end, mode, cookie, 0); - cl_io_fini(env, io); - -out: - cl_env_put(env, &refcheck); - return result; -} - static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed, __u64 cookie) { @@ -1137,22 +1104,6 @@ static int cl_echo_cancel0(struct lu_env *env, struct echo_device *ed, return 0; } -static int cl_echo_cancel(struct echo_device *ed, __u64 cookie) -{ - struct lu_env *env; - int refcheck; - int rc; - - env = cl_env_get(&refcheck); - if (IS_ERR(env)) - return PTR_ERR(env); - - rc = cl_echo_cancel0(env, ed, cookie); - - cl_env_put(env, &refcheck); - return rc; -} - static int cl_echo_async_brw(const struct lu_env *env, struct cl_io *io, enum cl_req_type unused, struct cl_2queue *queue) { @@ -1268,29 +1219,6 @@ out: static u64 last_object_id; -static int -echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob) -{ - struct lov_stripe_md *ulsm = _ulsm; - struct lov_oinfo **p; - int nob, i; - - nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]); - if (nob > ulsm_nob) - return -EINVAL; - - if (copy_to_user(ulsm, lsm, sizeof(*ulsm))) - return -EFAULT; - - for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) { - struct lov_oinfo __user *up; - if (get_user(up, ulsm->lsm_oinfo + i) || - copy_to_user(up, *p, sizeof(struct lov_oinfo))) - return -EFAULT; - } - return 0; -} - static int echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm, struct lov_stripe_md __user *ulsm, int ulsm_nob) @@ -1804,53 +1732,6 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw, return rc; } -static int -echo_client_enqueue(struct obd_export *exp, struct obdo *oa, - int mode, u64 offset, u64 nob) -{ - struct echo_device *ed = obd2echo_dev(exp->exp_obd); - struct lustre_handle *ulh = &oa->o_handle; - struct echo_object *eco; - u64 end; - int rc; - - if (ed->ed_next == NULL) - return -EOPNOTSUPP; - - if (!(mode == LCK_PR || mode == LCK_PW)) - return -EINVAL; - - if ((offset & (~CFS_PAGE_MASK)) != 0 || - (nob & (~CFS_PAGE_MASK)) != 0) - return -EINVAL; - - rc = echo_get_object(&eco, ed, oa); - if (rc != 0) - return rc; - - end = (nob == 0) ? ((u64) -1) : (offset + nob - 1); - rc = cl_echo_enqueue(eco, offset, end, mode, &ulh->cookie); - if (rc == 0) { - oa->o_valid |= OBD_MD_FLHANDLE; - CDEBUG(D_INFO, "Cookie is %#llx\n", ulh->cookie); - } - echo_put_object(eco); - return rc; -} - -static int -echo_client_cancel(struct obd_export *exp, struct obdo *oa) -{ - struct echo_device *ed = obd2echo_dev(exp->exp_obd); - __u64 cookie = oa->o_handle.cookie; - - if ((oa->o_valid & OBD_MD_FLHANDLE) == 0) - return -EINVAL; - - CDEBUG(D_INFO, "Cookie is %#llx\n", cookie); - return cl_echo_cancel(ed, cookie); -} - static int echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, void *karg, void *uarg) @@ -1961,50 +1842,6 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_client_brw_ioctl(env, rw, exp, data, &dummy_oti); goto out; - case ECHO_IOC_GET_STRIPE: - rc = echo_get_object(&eco, ed, oa); - if (rc == 0) { - rc = echo_copyout_lsm(eco->eo_lsm, data->ioc_pbuf1, - data->ioc_plen1); - echo_put_object(eco); - } - goto out; - - case ECHO_IOC_SET_STRIPE: - if (!capable(CFS_CAP_SYS_ADMIN)) { - rc = -EPERM; - goto out; - } - - if (data->ioc_pbuf1 == NULL) { /* unset */ - rc = echo_get_object(&eco, ed, oa); - if (rc == 0) { - eco->eo_deleted = 1; - echo_put_object(eco); - } - } else { - rc = echo_create_object(env, ed, 0, oa, - data->ioc_pbuf1, - data->ioc_plen1, &dummy_oti); - } - goto out; - - case ECHO_IOC_ENQUEUE: - if (!capable(CFS_CAP_SYS_ADMIN)) { - rc = -EPERM; - goto out; - } - - rc = echo_client_enqueue(exp, oa, - data->ioc_conn1, /* lock mode */ - data->ioc_offset, - data->ioc_count);/*extent*/ - goto out; - - case ECHO_IOC_CANCEL: - rc = echo_client_cancel(exp, oa); - goto out; - default: CERROR("echo_ioctl(): unrecognised ioctl %#x\n", cmd); rc = -ENOTTY; -- cgit From f833ea10c7bb87ac0c16d77ec0048b01e1fd996d Mon Sep 17 00:00:00 2001 From: "John L. Hammond" Date: Sun, 3 Jan 2016 12:05:36 -0500 Subject: staging/lustre/obdecho: remove userspace LSM handling In lustre/obdecho/echo_client.c, remove handling of lov_stripe_md passed from userspace (since userspace never passes it). Remove the LOV specific code (ed_next_islov) from the echo client (since it doesn't work). Remove echo_get_stripe_off_id() and all calls to it since the stripe count of the passed in lsm is always 0 and the funciton does nothing in this case. Remove the then unused lsm parameters of echo_client_page_debug_setup() and echo_client_page_debug_check(). In the OBD_IOC_GETATTR and OBD_IOC_SETATTR cases of echo_client_iocontrol() do not set the oi_md member of struct obd_info since only LOV OBD methods access it. Signed-off-by: John L. Hammond Reviewed-on: http://review.whamcloud.com/12446 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5814 Reviewed-by: Bobi Jam Reviewed-by: Andreas Dilger Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 1 - .../staging/lustre/lustre/obdecho/echo_client.c | 180 ++++----------------- 2 files changed, 31 insertions(+), 150 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index bcbe61301713..86897c2f6c68 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -375,7 +375,6 @@ struct echo_client_obd { spinlock_t ec_lock; struct list_head ec_objects; struct list_head ec_locks; - int ec_nstripes; __u64 ec_unique; }; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index ec8a26bd0835..5b76c222e2cf 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -60,7 +60,6 @@ struct echo_device { struct cl_site ed_site_myself; struct cl_site *ed_site; struct lu_device *ed_next; - int ed_next_islov; }; struct echo_object { @@ -767,14 +766,6 @@ static struct lu_device *echo_device_alloc(const struct lu_env *env, if (rc) goto out; - /* Tricky case, I have to determine the obd type since - * CLIO uses the different parameters to initialize - * objects for lov & osc. */ - if (strcmp(tgt_type_name, LUSTRE_LOV_NAME) == 0) - ed->ed_next_islov = 1; - else - LASSERT(strcmp(tgt_type_name, - LUSTRE_OSC_NAME) == 0); } else { LASSERT(strcmp(tgt_type_name, LUSTRE_OST_NAME) == 0); } @@ -960,20 +951,11 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, info = echo_env_info(env); conf = &info->eti_conf; if (d->ed_next) { - if (!d->ed_next_islov) { - struct lov_oinfo *oinfo = lsm->lsm_oinfo[0]; - - LASSERT(oinfo != NULL); - oinfo->loi_oi = lsm->lsm_oi; - conf->eoc_cl.u.coc_oinfo = oinfo; - } else { - struct lustre_md *md; + struct lov_oinfo *oinfo = lsm->lsm_oinfo[0]; - md = &info->eti_md; - memset(md, 0, sizeof(*md)); - md->lsm = lsm; - conf->eoc_cl.u.coc_md = md; - } + LASSERT(oinfo); + oinfo->loi_oi = lsm->lsm_oi; + conf->eoc_cl.u.coc_oinfo = oinfo; } conf->eoc_md = lsmp; @@ -1219,38 +1201,8 @@ out: static u64 last_object_id; -static int -echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm, - struct lov_stripe_md __user *ulsm, int ulsm_nob) -{ - struct echo_client_obd *ec = ed->ed_ec; - struct lov_oinfo **p; - int i; - - if (ulsm_nob < sizeof(*lsm)) - return -EINVAL; - - if (copy_from_user(lsm, ulsm, sizeof(*lsm))) - return -EFAULT; - - if (lsm->lsm_stripe_count > ec->ec_nstripes || - lsm->lsm_magic != LOV_MAGIC || - (lsm->lsm_stripe_size & (~CFS_PAGE_MASK)) != 0 || - ((__u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count > ~0UL)) - return -EINVAL; - - for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) { - struct lov_oinfo __user *up; - if (get_user(up, ulsm->lsm_oinfo + i) || - copy_from_user(*p, up, sizeof(struct lov_oinfo))) - return -EFAULT; - } - return 0; -} - static int echo_create_object(const struct lu_env *env, struct echo_device *ed, - int on_target, struct obdo *oa, void *ulsm, - int ulsm_nob, struct obd_trans_info *oti) + struct obdo *oa, struct obd_trans_info *oti) { struct echo_object *eco; struct echo_client_obd *ec = ed->ed_ec; @@ -1258,9 +1210,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, int rc; int created = 0; - if ((oa->o_valid & OBD_MD_FLID) == 0 && /* no obj id */ - (on_target || /* set_stripe */ - ec->ec_nstripes != 0)) { /* LOV */ + if ((oa->o_valid & OBD_MD_FLID) == 0) { /* no obj id */ CERROR("No valid oid\n"); return -EINVAL; } @@ -1271,32 +1221,7 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, goto failed; } - if (ulsm != NULL) { - int i, idx; - - rc = echo_copyin_lsm(ed, lsm, ulsm, ulsm_nob); - if (rc != 0) - goto failed; - - if (lsm->lsm_stripe_count == 0) - lsm->lsm_stripe_count = ec->ec_nstripes; - - if (lsm->lsm_stripe_size == 0) - lsm->lsm_stripe_size = PAGE_CACHE_SIZE; - - idx = cfs_rand(); - - /* setup stripes: indices + default ids if required */ - for (i = 0; i < lsm->lsm_stripe_count; i++) { - if (ostid_id(&lsm->lsm_oinfo[i]->loi_oi) == 0) - lsm->lsm_oinfo[i]->loi_oi = lsm->lsm_oi; - - lsm->lsm_oinfo[i]->loi_ost_idx = - (idx + i) % ec->ec_nstripes; - } - } - - /* setup object ID here for !on_target and LOV hint */ + /* setup object ID here */ if (oa->o_valid & OBD_MD_FLID) { LASSERT(oa->o_valid & OBD_MD_FLGROUP); lsm->lsm_oi = oa->o_oi; @@ -1305,18 +1230,16 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, if (ostid_id(&lsm->lsm_oi) == 0) ostid_set_id(&lsm->lsm_oi, ++last_object_id); - rc = 0; - if (on_target) { - /* Only echo objects are allowed to be created */ - LASSERT((oa->o_valid & OBD_MD_FLGROUP) && - (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO)); - rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); - if (rc != 0) { - CERROR("Cannot create objects: rc = %d\n", rc); - goto failed; - } - created = 1; + /* Only echo objects are allowed to be created */ + LASSERT((oa->o_valid & OBD_MD_FLGROUP) && + (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO)); + + rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); + if (rc != 0) { + CERROR("Cannot create objects: rc = %d\n", rc); + goto failed; } + created = 1; /* See what object ID we were given */ oa->o_oi = lsm->lsm_oi; @@ -1380,37 +1303,7 @@ static void echo_put_object(struct echo_object *eco) } static void -echo_get_stripe_off_id(struct lov_stripe_md *lsm, u64 *offp, u64 *idp) -{ - unsigned long stripe_count; - unsigned long stripe_size; - unsigned long width; - unsigned long woffset; - int stripe_index; - u64 offset; - - if (lsm->lsm_stripe_count <= 1) - return; - - offset = *offp; - stripe_size = lsm->lsm_stripe_size; - stripe_count = lsm->lsm_stripe_count; - - /* width = # bytes in all stripes */ - width = stripe_size * stripe_count; - - /* woffset = offset within a width; offset = whole number of widths */ - woffset = do_div(offset, width); - - stripe_index = woffset / stripe_size; - - *idp = ostid_id(&lsm->lsm_oinfo[stripe_index]->loi_oi); - *offp = offset * stripe_size + woffset % stripe_size; -} - -static void -echo_client_page_debug_setup(struct lov_stripe_md *lsm, - struct page *page, int rw, u64 id, +echo_client_page_debug_setup(struct page *page, int rw, u64 id, u64 offset, u64 count) { char *addr; @@ -1427,7 +1320,6 @@ echo_client_page_debug_setup(struct lov_stripe_md *lsm, if (rw == OBD_BRW_WRITE) { stripe_off = offset + delta; stripe_id = id; - echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id); } else { stripe_off = 0xdeadbeef00c0ffeeULL; stripe_id = 0xdeadbeef00c0ffeeULL; @@ -1439,8 +1331,7 @@ echo_client_page_debug_setup(struct lov_stripe_md *lsm, kunmap(page); } -static int echo_client_page_debug_check(struct lov_stripe_md *lsm, - struct page *page, u64 id, +static int echo_client_page_debug_check(struct page *page, u64 id, u64 offset, u64 count) { u64 stripe_off; @@ -1458,7 +1349,6 @@ static int echo_client_page_debug_check(struct lov_stripe_md *lsm, for (rc = delta = 0; delta < PAGE_CACHE_SIZE; delta += OBD_ECHO_BLOCK_SIZE) { stripe_off = offset + delta; stripe_id = id; - echo_get_stripe_off_id(lsm, &stripe_off, &stripe_id); rc2 = block_debug_check("test_brw", addr + delta, OBD_ECHO_BLOCK_SIZE, @@ -1478,7 +1368,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, u64 count, int async, struct obd_trans_info *oti) { - struct lov_stripe_md *lsm = eco->eo_lsm; u32 npages; struct brw_page *pga; struct brw_page *pgp; @@ -1497,8 +1386,6 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, gfp_mask = ((ostid_id(&oa->o_oi) & 2) == 0) ? GFP_KERNEL : GFP_HIGHUSER; LASSERT(rw == OBD_BRW_WRITE || rw == OBD_BRW_READ); - LASSERT(lsm != NULL); - LASSERT(ostid_id(&lsm->lsm_oi) == ostid_id(&oa->o_oi)); if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0) @@ -1537,7 +1424,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, pgp->flag = brw_flags; if (verify) - echo_client_page_debug_setup(lsm, pgp->pg, rw, + echo_client_page_debug_setup(pgp->pg, rw, ostid_id(&oa->o_oi), off, pgp->count); } @@ -1557,7 +1444,7 @@ static int echo_client_kbrw(struct echo_device *ed, int rw, struct obdo *oa, if (verify) { int vrc; - vrc = echo_client_page_debug_check(lsm, pgp->pg, + vrc = echo_client_page_debug_check(pgp->pg, ostid_id(&oa->o_oi), pgp->off, pgp->count); if (vrc != 0 && rc == 0) @@ -1577,7 +1464,6 @@ static int echo_client_prep_commit(const struct lu_env *env, u64 batch, struct obd_trans_info *oti, int async) { - struct lov_stripe_md *lsm = eco->eo_lsm; struct obd_ioobj ioo; struct niobuf_local *lnb; struct niobuf_remote *rnb; @@ -1585,8 +1471,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 || - (lsm != NULL && ostid_id(&lsm->lsm_oi) != ostid_id(&oa->o_oi))) + if (count <= 0 || (count & (~CFS_PAGE_MASK)) != 0) return -EINVAL; npages = batch >> PAGE_CACHE_SHIFT; @@ -1645,12 +1530,12 @@ static int echo_client_prep_commit(const struct lu_env *env, continue; if (rw == OBD_BRW_WRITE) - echo_client_page_debug_setup(lsm, page, rw, + echo_client_page_debug_setup(page, rw, ostid_id(&oa->o_oi), rnb[i].offset, rnb[i].len); else - echo_client_page_debug_check(lsm, page, + echo_client_page_debug_check(page, ostid_id(&oa->o_oi), rnb[i].offset, rnb[i].len); @@ -1780,8 +1665,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, goto out; } - rc = echo_create_object(env, ed, 1, oa, data->ioc_pbuf1, - data->ioc_plen1, &dummy_oti); + rc = echo_create_object(env, ed, oa, &dummy_oti); goto out; case OBD_IOC_DESTROY: @@ -1792,7 +1676,7 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - rc = obd_destroy(env, ec->ec_exp, oa, eco->eo_lsm, + rc = obd_destroy(env, ec->ec_exp, oa, NULL, &dummy_oti, NULL); if (rc == 0) eco->eo_deleted = 1; @@ -1803,10 +1687,10 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, case OBD_IOC_GETATTR: rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - struct obd_info oinfo = { }; + struct obd_info oinfo = { + .oi_oa = oa, + }; - oinfo.oi_md = eco->eo_lsm; - oinfo.oi_oa = oa; rc = obd_getattr(env, ec->ec_exp, &oinfo); echo_put_object(eco); } @@ -1820,10 +1704,9 @@ echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, rc = echo_get_object(&eco, ed, oa); if (rc == 0) { - struct obd_info oinfo = { }; - - oinfo.oi_oa = oa; - oinfo.oi_md = eco->eo_lsm; + struct obd_info oinfo = { + .oi_oa = oa, + }; rc = obd_setattr(env, ec->ec_exp, &oinfo, NULL); echo_put_object(eco); @@ -1888,7 +1771,6 @@ static int echo_client_setup(const struct lu_env *env, INIT_LIST_HEAD(&ec->ec_objects); INIT_LIST_HEAD(&ec->ec_locks); ec->ec_unique = 0; - ec->ec_nstripes = 0; ocd = kzalloc(sizeof(*ocd), GFP_NOFS); if (!ocd) { -- cgit From e2d52f7b3adb0e5b80a068a2b2628bc8c2e01c6d Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:37 -0500 Subject: staging/lustre: Add __user attributes to libcfs_ioctl_get/popdata args Just make clear which pointers are from userspace and which are not in libcfs_ioctl_getdata/libcfs_ioctl_popdata and their callers. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 4 ++-- drivers/staging/lustre/lustre/libcfs/linux/linux-module.c | 6 +++--- drivers/staging/lustre/lustre/libcfs/module.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 3b16fcef1dad..0c31bf9b8e8d 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -207,7 +207,7 @@ static inline int 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(char *buf, char *end, void *arg); -int libcfs_ioctl_popdata(void *arg, void *buf, int size); +int libcfs_ioctl_getdata(char *buf, char *end, void __user *arg); +int libcfs_ioctl_popdata(void __user *arg, void *buf, int size); #endif /* __LIBCFS_IOCTL_H__ */ diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index eccfe8bd57a2..c089b044ef2e 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -40,7 +40,7 @@ #define LNET_MINOR 240 -int libcfs_ioctl_getdata(char *buf, char *end, void *arg) +int libcfs_ioctl_getdata(char *buf, char *end, void __user *arg) { struct libcfs_ioctl_hdr *hdr; struct libcfs_ioctl_data *data; @@ -88,9 +88,9 @@ int libcfs_ioctl_getdata(char *buf, char *end, void *arg) return 0; } -int libcfs_ioctl_popdata(void *arg, void *data, int size) +int libcfs_ioctl_popdata(void __user *arg, void *data, int size) { - if (copy_to_user((char *)arg, data, size)) + if (copy_to_user(arg, data, size)) return -EFAULT; return 0; } diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index af516a29c20e..d5a047bd0180 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -116,7 +116,7 @@ int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand) EXPORT_SYMBOL(libcfs_deregister_ioctl); static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd, - void *arg, struct libcfs_ioctl_data *data) + void __user *arg, struct libcfs_ioctl_data *data) { int err = -EINVAL; @@ -157,7 +157,8 @@ static int libcfs_ioctl_int(struct cfs_psdev_file *pfile, unsigned long cmd, return err; } -static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg) +static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, + void __user *arg) { char *buf; struct libcfs_ioctl_data *data; -- cgit From 33ab3abce72e2a02a06e1927c0f2c7999e8b860e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:38 -0500 Subject: staging/lustre: Change ioctl user pointers in libcfs_ioctl_data Make them void __user * instead of char * (or char __user *), void * removes the necessity of explicit casts to proper type where people also need to remember __user qualifiers, so I think it works better here. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h index 0c31bf9b8e8d..05f2191e08fb 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -61,9 +61,9 @@ struct libcfs_ioctl_data { char *ioc_inlbuf2; __u32 ioc_plen1; /* buffers in userspace */ - char *ioc_pbuf1; + void __user *ioc_pbuf1; __u32 ioc_plen2; /* buffers in userspace */ - char *ioc_pbuf2; + void __user *ioc_pbuf2; char ioc_bulk[0]; }; -- cgit From 922cb32ca374fb729194d087c8f9aa17205d586e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:39 -0500 Subject: staging/lustre: Update user pointers in struct obd_ioctl_data Make them void __user * instead of char * (or char __user *), void * removes the necessity of explicit casts to proper type where people also need to remember __user qualifiers, so I think it works better here. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 7daf9543f32c..3d75a8292d5f 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -153,9 +153,9 @@ struct obd_ioctl_data { /* buffers the kernel will treat as user pointers */ __u32 ioc_plen1; - char *ioc_pbuf1; + void __user *ioc_pbuf1; __u32 ioc_plen2; - char *ioc_pbuf2; + void __user *ioc_pbuf2; /* inline buffers for various arguments */ __u32 ioc_inllen1; -- cgit From e3e8ff41c0ffe579ea48bd3250bc23abc4bd4b37 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:40 -0500 Subject: staging/lustre: Mark obd_ioctl_popdata/getdata argument as __user arg is a userspace pointer and marking it as such makes sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_lib.h | 4 ++-- drivers/staging/lustre/lustre/llite/dir.c | 4 ++-- drivers/staging/lustre/lustre/obdclass/class_obd.c | 14 ++++++++------ .../staging/lustre/lustre/obdclass/linux/linux-module.c | 8 ++++---- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_lib.h b/drivers/staging/lustre/lustre/include/lustre_lib.h index 3d75a8292d5f..cfccf7ca04c4 100644 --- a/drivers/staging/lustre/lustre/include/lustre_lib.h +++ b/drivers/staging/lustre/lustre/include/lustre_lib.h @@ -252,8 +252,8 @@ static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) #include "obd_support.h" /* function defined in lustre/obdclass//-module.c */ -int obd_ioctl_getdata(char **buf, int *len, void *arg); -int obd_ioctl_popdata(void *arg, void *data, int len); +int obd_ioctl_getdata(char **buf, int *len, void __user *arg); +int obd_ioctl_popdata(void __user *arg, void *data, int len); static inline void obd_ioctl_freedata(char *buf, int len) { diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 2a5babe555e6..eb2fc23574ca 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1279,7 +1279,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) char *filename; struct md_op_data *op_data; - rc = obd_ioctl_getdata(&buf, &len, (void *)arg); + rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); if (rc) return rc; data = (void *)buf; @@ -1321,7 +1321,7 @@ out_free: int len; int rc; - rc = obd_ioctl_getdata(&buf, &len, (void *)arg); + rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg); if (rc) return rc; diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index 0975e443057c..65cf46c8c86e 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -180,7 +180,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) } CDEBUG(D_IOCTL, "cmd = %x\n", cmd); - if (obd_ioctl_getdata(&buf, &len, (void *)arg)) { + if (obd_ioctl_getdata(&buf, &len, (void __user *)arg)) { CERROR("OBD ioctl: data error\n"); return -EINVAL; } @@ -227,7 +227,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) memcpy(data->ioc_bulk, BUILD_VERSION, strlen(BUILD_VERSION) + 1); - err = obd_ioctl_popdata((void *)arg, data, len); + err = obd_ioctl_popdata((void __user *)arg, data, len); if (err) err = -EFAULT; goto out; @@ -246,7 +246,8 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) goto out; } - err = obd_ioctl_popdata((void *)arg, data, sizeof(*data)); + err = obd_ioctl_popdata((void __user *)arg, data, + sizeof(*data)); if (err) err = -EFAULT; goto out; @@ -283,7 +284,8 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1, dev); - err = obd_ioctl_popdata((void *)arg, data, sizeof(*data)); + err = obd_ioctl_popdata((void __user *)arg, data, + sizeof(*data)); if (err) err = -EFAULT; goto out; @@ -330,7 +332,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) (int)index, status, obd->obd_type->typ_name, obd->obd_name, obd->obd_uuid.uuid, atomic_read(&obd->obd_refcount)); - err = obd_ioctl_popdata((void *)arg, data, len); + err = obd_ioctl_popdata((void __user *)arg, data, len); err = 0; goto out; @@ -388,7 +390,7 @@ int class_handle_ioctl(unsigned int cmd, unsigned long arg) if (err) goto out; - err = obd_ioctl_popdata((void *)arg, data, len); + err = obd_ioctl_popdata((void __user *)arg, data, len); if (err) err = -EFAULT; goto out; diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index a055cbb4f162..f8d3a639e85c 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -74,14 +74,14 @@ #include "../../include/lustre/lustre_build_version.h" /* buffer MUST be at least the size of obd_ioctl_hdr */ -int obd_ioctl_getdata(char **buf, int *len, void *arg) +int obd_ioctl_getdata(char **buf, int *len, void __user *arg) { struct obd_ioctl_hdr hdr; struct obd_ioctl_data *data; int err; int offset = 0; - if (copy_from_user(&hdr, (void *)arg, sizeof(hdr))) + if (copy_from_user(&hdr, arg, sizeof(hdr))) return -EFAULT; if (hdr.ioc_version != OBD_IOCTL_VERSION) { @@ -114,7 +114,7 @@ int obd_ioctl_getdata(char **buf, int *len, void *arg) *len = hdr.ioc_len; data = (struct obd_ioctl_data *)*buf; - if (copy_from_user(*buf, (void *)arg, hdr.ioc_len)) { + if (copy_from_user(*buf, arg, hdr.ioc_len)) { err = -EFAULT; goto free_buf; } @@ -156,7 +156,7 @@ free_buf: } EXPORT_SYMBOL(obd_ioctl_getdata); -int obd_ioctl_popdata(void *arg, void *data, int len) +int obd_ioctl_popdata(void __user *arg, void *data, int len) { int err; -- cgit From 4eb53dfd23281c6e358f26af56b3572bdcbfd43a Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:41 -0500 Subject: staging/lustre/lnet: Properly mark userspace pointer of lnet_ping() This also happens to silence sparce warnings about different address spaces. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/api-ni.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 80b170ee5582..d33fbdf99505 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -62,7 +62,7 @@ module_param(rnet_htable_size, int, 0444); MODULE_PARM_DESC(rnet_htable_size, "size of remote network hash table"); static int lnet_ping(lnet_process_id_t id, int timeout_ms, - lnet_process_id_t *ids, int n_ids); + lnet_process_id_t __user *ids, int n_ids); static char * lnet_get_routes(void) @@ -1376,7 +1376,7 @@ LNetCtl(unsigned int cmd, void *arg) id.nid = data->ioc_nid; id.pid = data->ioc_u32[0]; rc = lnet_ping(id, data->ioc_u32[1], /* timeout */ - (lnet_process_id_t *)data->ioc_pbuf1, + data->ioc_pbuf1, data->ioc_plen1/sizeof(lnet_process_id_t)); if (rc < 0) return rc; @@ -1646,7 +1646,7 @@ lnet_ping_target_fini(void) } static int lnet_ping(lnet_process_id_t id, int timeout_ms, - lnet_process_id_t *ids, int n_ids) + lnet_process_id_t __user *ids, int n_ids) { lnet_handle_eq_t eqh; lnet_handle_md_t mdh; -- cgit From 44164fc9922d4d5bd60de7a576ba5ebdeefe79a3 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:42 -0500 Subject: staging/lustre: Get rid of an ugly statfs hack in lov_iocontrol For some crazy reason ll_obd_statfs decided to decode async flag passed from userspace and then pass it via a userspace pointer argument to lov_iocontrol. This patch moves flags decoding to lov_iocontrol where it belongs. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 4 +--- drivers/staging/lustre/lustre/lov/lov_obd.c | 4 +++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b2fc5b3786ee..efff8307fb06 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2026,7 +2026,6 @@ int ll_obd_statfs(struct inode *inode, void *arg) char *buf = NULL; struct obd_ioctl_data *data = NULL; __u32 type; - __u32 flags; int len = 0, rc; if (!inode) { @@ -2069,8 +2068,7 @@ int ll_obd_statfs(struct inode *inode, void *arg) goto out_statfs; } - flags = (type & LL_STATFS_NODELAY) ? OBD_STATFS_NODELAY : 0; - rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, &flags); + rc = obd_iocontrol(IOC_OBD_STATFS, exp, len, buf, NULL); if (rc) goto out_statfs; out_statfs: diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 6c2bdfe9cdcf..1dde0b8fa9a6 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1420,7 +1420,9 @@ static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, (int) sizeof(struct obd_uuid)))) return -EFAULT; - flags = uarg ? *(__u32 *)uarg : 0; + memcpy(&flags, data->ioc_inlbuf1, sizeof(__u32)); + flags = flags & LL_STATFS_NODELAY ? OBD_STATFS_NODELAY : 0; + /* got statfs data */ rc = obd_statfs(NULL, lov->lov_tgts[index]->ltd_exp, &stat_buf, cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS), -- cgit From e09bee346e3f10a3739c4c9ae4286bd09cdf2631 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:43 -0500 Subject: staging/lustre: Properly mark obd_iocontrol argument as __user Also update all methods and calls everywhere. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/obd.h | 2 +- drivers/staging/lustre/lustre/include/obd_class.h | 2 +- drivers/staging/lustre/lustre/llite/dir.c | 6 ++++-- drivers/staging/lustre/lustre/llite/file.c | 6 +++--- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 2 +- drivers/staging/lustre/lustre/lov/lov_obd.c | 2 +- drivers/staging/lustre/lustre/mdc/mdc_request.c | 2 +- drivers/staging/lustre/lustre/obdecho/echo_client.c | 2 +- drivers/staging/lustre/lustre/osc/osc_request.c | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index 86897c2f6c68..f00d9a2e7afe 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -964,7 +964,7 @@ struct md_enqueue_info { struct obd_ops { struct module *owner; int (*iocontrol)(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg); + void *karg, void __user *uarg); int (*get_info)(const struct lu_env *env, struct obd_export *, __u32 keylen, void *key, __u32 *vallen, void *val, struct lov_stripe_md *lsm); diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h index 97d80397503c..4f631e6bf048 100644 --- a/drivers/staging/lustre/lustre/include/obd_class.h +++ b/drivers/staging/lustre/lustre/include/obd_class.h @@ -1155,7 +1155,7 @@ static inline int obd_adjust_kms(struct obd_export *exp, } static inline int obd_iocontrol(unsigned int cmd, struct obd_export *exp, - int len, void *karg, void *uarg) + int len, void *karg, void __user *uarg) { int rc; diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index eb2fc23574ca..5cfe8bb5fce2 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1724,7 +1724,8 @@ out_quotactl: return -EFAULT; return 0; case LL_IOC_GET_CONNECT_FLAGS: { - return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, (void *)arg); + return obd_iocontrol(cmd, sbi->ll_md_exp, 0, NULL, + (void __user *)arg); } case OBD_IOC_CHANGELOG_SEND: case OBD_IOC_CHANGELOG_CLEAR: @@ -1847,7 +1848,8 @@ out_quotactl: return rc; } default: - return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, (void *)arg); + return obd_iocontrol(cmd, sbi->ll_dt_exp, 0, NULL, + (void __user *)arg); } } diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 39e2ffd5f97f..c91b5b4111c9 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1518,7 +1518,7 @@ static int ll_lov_setstripe(struct inode *inode, struct file *file, ll_layout_refresh(inode, &gen); lsm = ccc_inode_lsm_get(inode); rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), - 0, lsm, (void *)arg); + 0, lsm, (void __user *)arg); ccc_inode_lsm_put(inode, lsm); } return rc; @@ -1532,7 +1532,7 @@ static int ll_lov_getstripe(struct inode *inode, unsigned long arg) lsm = ccc_inode_lsm_get(inode); if (lsm != NULL) rc = obd_iocontrol(LL_IOC_LOV_GETSTRIPE, ll_i2dtexp(inode), 0, - lsm, (void *)arg); + lsm, (void __user *)arg); ccc_inode_lsm_put(inode, lsm); return rc; } @@ -2497,7 +2497,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return err; return obd_iocontrol(cmd, ll_i2dtexp(inode), 0, NULL, - (void *)arg); + (void __user *)arg); } } } diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 9ebfb39a8188..59bdd580b249 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -876,7 +876,7 @@ static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, } static int lmv_iocontrol(unsigned int cmd, struct obd_export *exp, - int len, void *karg, void *uarg) + int len, void *karg, void __user *uarg) { struct obd_device *obddev = class_exp2obd(exp); struct lmv_obd *lmv = &obddev->u.lmv; diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c index 1dde0b8fa9a6..65077b7e235b 100644 --- a/drivers/staging/lustre/lustre/lov/lov_obd.c +++ b/drivers/staging/lustre/lustre/lov/lov_obd.c @@ -1385,7 +1385,7 @@ static int lov_statfs(const struct lu_env *env, struct obd_export *exp, } static int lov_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obddev = class_exp2obd(exp); struct lov_obd *lov = &obddev->u.lov; diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c index 3929f9129c8b..43481278096f 100644 --- a/drivers/staging/lustre/lustre/mdc/mdc_request.c +++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c @@ -1722,7 +1722,7 @@ static int mdc_ioc_swap_layouts(struct obd_export *exp, } static int mdc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obd = exp->exp_obd; struct obd_ioctl_data *data = karg; diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index 5b76c222e2cf..d3e398f70434 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1619,7 +1619,7 @@ static int echo_client_brw_ioctl(const struct lu_env *env, int rw, static int echo_client_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obd = exp->exp_obd; struct echo_device *ed = obd2echo_dev(obd); diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 7034f0a942c5..6eb678c00e7b 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2591,7 +2591,7 @@ static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump) } static int osc_iocontrol(unsigned int cmd, struct obd_export *exp, int len, - void *karg, void *uarg) + void *karg, void __user *uarg) { struct obd_device *obd = exp->exp_obd; struct obd_ioctl_data *data = karg; -- cgit From f2938c04b8f9b0223767ade931eeb63f3d7e0e68 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:44 -0500 Subject: staging/lustre: Properly mark argument to p_ioctl in cfs_psdev_ops as __user This also silents a sparse address space warning Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/libcfs/libcfs.h | 2 +- drivers/staging/lustre/lustre/libcfs/linux/linux-module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h index 094eb0f27954..dc9b88f2f977 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h @@ -77,7 +77,7 @@ struct cfs_psdev_ops { 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 *); + int (*p_ioctl)(struct cfs_psdev_file *, unsigned long, void __user *); }; /* diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c index c089b044ef2e..e5bc3d349d78 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c @@ -151,7 +151,7 @@ static long libcfs_ioctl(struct file *file, } if (libcfs_psdev_ops.p_ioctl != NULL) - rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void *)arg); + rc = libcfs_psdev_ops.p_ioctl(&pfile, cmd, (void __user *)arg); else rc = -EPERM; return rc; -- cgit From cadffe60eae0a798d5fd5368930684d7d6d0998e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:45 -0500 Subject: staging/lustre: Declare lprocfs_write_frac_u64_helper argument as __user The buffer that lprocfs_write_frac_u64_helper is working on is presumed to be a userspace one, so it's not suitable for use on kernel buffers. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lprocfs_status.h | 2 +- drivers/staging/lustre/lustre/obdclass/lprocfs_status.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h index 0ac8e0edcc48..fb13094d8b0b 100644 --- a/drivers/staging/lustre/lustre/include/lprocfs_status.h +++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h @@ -608,7 +608,7 @@ int lprocfs_write_helper(const char __user *buffer, unsigned long count, int *val); int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, __u64 *val); -int lprocfs_write_frac_u64_helper(const char *buffer, +int lprocfs_write_frac_u64_helper(const char __user *buffer, unsigned long count, __u64 *val, int mult); char *lprocfs_find_named_value(const char *buffer, const char *name, diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 51fe15f5d687..b65ad93eca4b 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -1319,8 +1319,8 @@ int lprocfs_write_u64_helper(const char __user *buffer, unsigned long count, } EXPORT_SYMBOL(lprocfs_write_u64_helper); -int lprocfs_write_frac_u64_helper(const char *buffer, unsigned long count, - __u64 *val, int mult) +int lprocfs_write_frac_u64_helper(const char __user *buffer, + unsigned long count, __u64 *val, int mult) { char kernbuf[22], *end, *pbuf; __u64 whole, frac = 0, units; -- cgit From 0dd48a43fd2591e4b48ae6fd6196779de49dcf51 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:46 -0500 Subject: staging/lustre/osc: Do not use lprocfs_write_helper in sysfs store methods sysfs store methods provide us with a kernel buffer already, but lprocfs_write_helper is expecting a user buffer. Replace lprocfs_write_helper with kstrto[u]int() calls instead in contention_seconds_store() and lockless_truncate_store() Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/lproc_osc.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/osc/lproc_osc.c b/drivers/staging/lustre/lustre/osc/lproc_osc.c index 1091536fc90d..b69ec0fa0203 100644 --- a/drivers/staging/lustre/lustre/osc/lproc_osc.c +++ b/drivers/staging/lustre/lustre/osc/lproc_osc.c @@ -480,9 +480,19 @@ static ssize_t contention_seconds_store(struct kobject *kobj, struct obd_device *obd = container_of(kobj, struct obd_device, obd_kobj); struct osc_device *od = obd2osc_dev(obd); + int rc; + int val; + + rc = kstrtoint(buffer, 10, &val); + if (rc) + return rc; + + if (val < 0) + return -EINVAL; + + od->od_contention_time = val; - return lprocfs_write_helper(buffer, count, &od->od_contention_time) ?: - count; + return count; } LUSTRE_RW_ATTR(contention_seconds); @@ -505,9 +515,16 @@ static ssize_t lockless_truncate_store(struct kobject *kobj, struct obd_device *obd = container_of(kobj, struct obd_device, obd_kobj); struct osc_device *od = obd2osc_dev(obd); + int rc; + unsigned int val; - return lprocfs_write_helper(buffer, count, &od->od_lockless_truncate) ?: - count; + rc = kstrtouint(buffer, 10, &val); + if (rc) + return rc; + + od->od_lockless_truncate = val; + + return count; } LUSTRE_RW_ATTR(lockless_truncate); -- cgit From 4c6243ec8437550019963335f252842a750cb6f6 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:47 -0500 Subject: staging/lustre/llite: Properly mark ll_obd_statfs argument as __user Also update all callers. This fixes a bunch of address space mismatch warnings from sparse. 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 | 2 +- drivers/staging/lustre/lustre/llite/llite_internal.h | 2 +- drivers/staging/lustre/lustre/llite/llite_lib.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5cfe8bb5fce2..5b41162c7b35 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1434,7 +1434,7 @@ free_lmv: case LL_IOC_LOV_SWAP_LAYOUTS: return -EPERM; case LL_IOC_OBD_STATFS: - return ll_obd_statfs(inode, (void *)arg); + return ll_obd_statfs(inode, (void __user *)arg); case LL_IOC_LOV_GETSTRIPE: case LL_IOC_MDC_GETINFO: case IOC_MDC_GETFILEINFO: diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index c91b5b4111c9..6652fdf2ca8a 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2278,7 +2278,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_GROUP_UNLOCK: return ll_put_grouplock(inode, file, arg); case IOC_OBD_STATFS: - return ll_obd_statfs(inode, (void *)arg); + return ll_obd_statfs(inode, (void __user *)arg); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h index e73024778808..29c325d5c4e6 100644 --- a/drivers/staging/lustre/lustre/llite/llite_internal.h +++ b/drivers/staging/lustre/lustre/llite/llite_internal.h @@ -782,7 +782,7 @@ int ll_show_options(struct seq_file *seq, struct dentry *dentry); void ll_dirty_page_discard_warn(struct page *page, int ioret); int ll_prep_inode(struct inode **inode, struct ptlrpc_request *req, struct super_block *, struct lookup_intent *); -int ll_obd_statfs(struct inode *inode, void *arg); +int ll_obd_statfs(struct inode *inode, void __user *arg); int ll_get_max_mdsize(struct ll_sb_info *sbi, int *max_mdsize); int ll_get_default_mdsize(struct ll_sb_info *sbi, int *default_mdsize); int ll_process_config(struct lustre_cfg *lcfg); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index efff8307fb06..68fa766adcbb 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -2019,7 +2019,7 @@ cleanup: return rc; } -int ll_obd_statfs(struct inode *inode, void *arg) +int ll_obd_statfs(struct inode *inode, void __user *arg) { struct ll_sb_info *sbi = NULL; struct obd_export *exp; -- cgit From 97514241423bfebf4a87395698c54d8c244eaf22 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:48 -0500 Subject: staging/lustre/llite: Fix improper userspace access in ll_fiemap Cannot use memcpy, but use copy_to/from_user instead Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 6652fdf2ca8a..9e50e9e19a28 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3033,19 +3033,26 @@ static int ll_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, fiemap->fm_extent_count = fieinfo->fi_extents_max; fiemap->fm_start = start; fiemap->fm_length = len; - if (extent_count > 0) - memcpy(&fiemap->fm_extents[0], fieinfo->fi_extents_start, - sizeof(struct ll_fiemap_extent)); + if (extent_count > 0 && + copy_from_user(&fiemap->fm_extents[0], fieinfo->fi_extents_start, + sizeof(struct ll_fiemap_extent)) != 0) { + rc = -EFAULT; + goto out; + } rc = ll_do_fiemap(inode, fiemap, num_bytes); fieinfo->fi_flags = fiemap->fm_flags; fieinfo->fi_extents_mapped = fiemap->fm_mapped_extents; - if (extent_count > 0) - memcpy(fieinfo->fi_extents_start, &fiemap->fm_extents[0], - fiemap->fm_mapped_extents * - sizeof(struct ll_fiemap_extent)); + if (extent_count > 0 && + copy_to_user(fieinfo->fi_extents_start, &fiemap->fm_extents[0], + fiemap->fm_mapped_extents * + sizeof(struct ll_fiemap_extent)) != 0) { + rc = -EFAULT; + goto out; + } +out: kvfree(fiemap); return rc; } -- cgit From 55f37f01f92163760970a4b866caf8cef2f57f12 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:49 -0500 Subject: staging/lustre: Declare lov_getstripe lump argument as __user This is a user pointer, so that makes sparse a lot happier. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_internal.h | 2 +- drivers/staging/lustre/lustre/lov/lov_pack.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 2d00bad58e35..f8e92fee02ce 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -197,7 +197,7 @@ int lov_packmd(struct obd_export *exp, struct lov_mds_md **lmm, int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, struct lov_mds_md *lmm, int lmm_bytes); int lov_getstripe(struct obd_export *exp, - struct lov_stripe_md *lsm, struct lov_user_md *lump); + struct lov_stripe_md *lsm, struct lov_user_md __user *lump); int lov_alloc_memmd(struct lov_stripe_md **lsmp, __u16 stripe_count, int pattern, int magic); int lov_free_memmd(struct lov_stripe_md **lsmp); diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 6b2d1007192b..a78211f64007 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -376,7 +376,7 @@ int lov_unpackmd(struct obd_export *exp, struct lov_stripe_md **lsmp, * lmm_magic must be LOV_USER_MAGIC. */ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, - struct lov_user_md *lump) + struct lov_user_md __user *lump) { /* * XXX huge struct allocated on stack. -- cgit From 7ac5db212d5cf77b84e9d3bd300056c217d6e49e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:50 -0500 Subject: staging/lustre/llite: Update llite_lib.c with proper __user attributes Casts for get/put_user and copy_to/from_user should have __user attribute for the userspace buffer address. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/llite_lib.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 68fa766adcbb..446e4b8d3b4e 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1744,14 +1744,14 @@ int ll_iocontrol(struct inode *inode, struct file *file, ptlrpc_req_finished(req); - return put_user(flags, (int *)arg); + return put_user(flags, (int __user *)arg); } case FSFILT_IOC_SETFLAGS: { struct lov_stripe_md *lsm; struct obd_info oinfo = { }; struct md_op_data *op_data; - if (get_user(flags, (int *)arg)) + if (get_user(flags, (int __user *)arg)) return -EFAULT; op_data = ll_prep_md_op_data(NULL, inode, NULL, NULL, 0, 0, @@ -2219,8 +2219,8 @@ int ll_get_obd_name(struct inode *inode, unsigned int cmd, unsigned long arg) if (!obd) return -ENOENT; - if (copy_to_user((void *)arg, obd->obd_name, - strlen(obd->obd_name) + 1)) + if (copy_to_user((void __user *)arg, obd->obd_name, + strlen(obd->obd_name) + 1)) return -EFAULT; return 0; -- cgit From ec2d71d0835decc8e5a358e7d8080a92eead4baa Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:51 -0500 Subject: staging/lustre/osc: Mark osc_getstripe user pointer argument as __user This shuts some sparse address space mismatch warnings Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_request.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index 6eb678c00e7b..3ae00fc3f996 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2534,7 +2534,8 @@ static int osc_statfs(const struct lu_env *env, struct obd_export *exp, * the maximum number of OST indices which will fit in the user buffer. * lmm_magic must be LOV_MAGIC (we only use 1 slot here). */ -static int osc_getstripe(struct lov_stripe_md *lsm, struct lov_user_md *lump) +static int osc_getstripe(struct lov_stripe_md *lsm, + struct lov_user_md __user *lump) { /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */ struct lov_user_md_v3 lum, *lumk; -- cgit From 6f9a3bd93f48127164e1599f0e1f9d4e16f9cb89 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:52 -0500 Subject: staging/lustre/lloop: Properly mark userspace pointers in lo/lloop_ioctl When casting unsigned long userspace pointer for use with userspace-accessing functions, need to use __user attribute to make sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/lloop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 871924b3f2e7..69c41afd1faa 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -636,7 +636,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, else fid_zero(&fid); - if (copy_to_user((struct lu_fid *)arg, &fid, sizeof(fid))) + if (copy_to_user((void __user *)arg, &fid, sizeof(fid))) err = -EFAULT; break; } @@ -708,7 +708,7 @@ static enum llioc_iter lloop_ioctl(struct inode *unused, struct file *file, dev = MKDEV(lloop_major, lo->lo_number); /* quit if the used pointer is writable */ - if (put_user((long)old_encode_dev(dev), (long *)arg)) { + if (put_user((long)old_encode_dev(dev), (long __user *)arg)) { err = -EFAULT; goto out; } -- cgit From 0f881d7b266eaa010c9cd6b621f74a876337c5a5 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:53 -0500 Subject: staging/lustre: Properly mark lmv_fid2path uarg argment as __user This makes sparse happy too. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 59bdd580b249..7a6fc5555ea1 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -663,7 +663,8 @@ out_local: return rc; } -static int lmv_fid2path(struct obd_export *exp, int len, void *karg, void *uarg) +static int lmv_fid2path(struct obd_export *exp, int len, void *karg, + void __user *uarg) { struct obd_device *obddev = class_exp2obd(exp); struct lmv_obd *lmv = &obddev->u.lmv; -- cgit From 11be8f6cdc8b0cdeb1d392dfb473f533ef435d0c Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:54 -0500 Subject: staging/lustre: Mark lmv_hsm_ct_register/unregister uarg as __user Since it is a userspace pointer, this makes things neater and sparse happier. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lmv/lmv_obd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 7a6fc5555ea1..733222cb1a1c 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -794,7 +794,8 @@ static void lmv_hsm_req_build(struct lmv_obd *lmv, } static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, - struct lustre_kernelcomm *lk, void *uarg) + struct lustre_kernelcomm *lk, + void __user *uarg) { int rc = 0; __u32 i; @@ -816,7 +817,7 @@ static int lmv_hsm_ct_unregister(struct lmv_obd *lmv, unsigned int cmd, int len, } static int lmv_hsm_ct_register(struct lmv_obd *lmv, unsigned int cmd, int len, - struct lustre_kernelcomm *lk, void *uarg) + struct lustre_kernelcomm *lk, void __user *uarg) { struct file *filp; __u32 i, j; -- cgit From 02f9c12e32605446f4ac48be0598b92f0b940764 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:55 -0500 Subject: staging/lustre/llite: Update all file.c user pointer casts to __user unsigned long user address must be casted with __user attribute to make sparse happy when used with userspace access functions. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 47 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 9e50e9e19a28..f31f75a446ec 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -1307,7 +1307,7 @@ static int ll_lov_recreate_obj(struct inode *inode, unsigned long arg) if (!capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&ucreat, (struct ll_recreate_obj *)arg, + if (copy_from_user(&ucreat, (struct ll_recreate_obj __user *)arg, sizeof(ucreat))) return -EFAULT; @@ -1325,7 +1325,7 @@ static int ll_lov_recreate_fid(struct inode *inode, unsigned long arg) if (!capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&fid, (struct lu_fid *)arg, sizeof(fid))) + if (copy_from_user(&fid, (struct lu_fid __user *)arg, sizeof(fid))) return -EFAULT; fid_to_ostid(&fid, &oi); @@ -1472,7 +1472,7 @@ static int ll_lov_setea(struct inode *inode, struct file *file, if (lump == NULL) return -ENOMEM; - if (copy_from_user(lump, (struct lov_user_md *)arg, lum_size)) { + if (copy_from_user(lump, (struct lov_user_md __user *)arg, lum_size)) { kvfree(lump); return -EFAULT; } @@ -1488,12 +1488,12 @@ static int ll_lov_setea(struct inode *inode, struct file *file, static int ll_lov_setstripe(struct inode *inode, struct file *file, unsigned long arg) { - struct lov_user_md_v3 lumv3; - struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg; - struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg; - int lum_size, rc; - int flags = FMODE_WRITE; + struct lov_user_md_v3 lumv3; + struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; + 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; /* first try with v1 which is smaller than v3 */ lum_size = sizeof(struct lov_user_md_v1); @@ -1826,7 +1826,7 @@ static int ll_ioctl_fiemap(struct inode *inode, unsigned long arg) ret_bytes += (fiemap_s->fm_mapped_extents * sizeof(struct ll_fiemap_extent)); - if (copy_to_user((void *)arg, fiemap_s, ret_bytes)) + if (copy_to_user((void __user *)arg, fiemap_s, ret_bytes)) rc = -EFAULT; error: @@ -2211,14 +2211,14 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) switch (cmd) { case LL_IOC_GETFLAGS: /* Get the current value of the file flags */ - return put_user(fd->fd_flags, (int *)arg); + return put_user(fd->fd_flags, (int __user *)arg); case LL_IOC_SETFLAGS: case LL_IOC_CLRFLAGS: /* Set or clear specific file flags */ /* XXX This probably needs checks to ensure the flags are * not abused, and to handle any flag side effects. */ - if (get_user(flags, (int *) arg)) + if (get_user(flags, (int __user *)arg)) return -EFAULT; if (cmd == LL_IOC_SETFLAGS) { @@ -2242,8 +2242,8 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct file *file2; struct lustre_swap_layouts lsl; - if (copy_from_user(&lsl, (char *)arg, - sizeof(struct lustre_swap_layouts))) + if (copy_from_user(&lsl, (char __user *)arg, + sizeof(struct lustre_swap_layouts))) return -EFAULT; if ((file->f_flags & O_ACCMODE) == 0) /* O_RDONLY */ @@ -2272,7 +2272,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ll_iocontrol(inode, file, cmd, arg); case FSFILT_IOC_GETVERSION_OLD: case FSFILT_IOC_GETVERSION: - return put_user(inode->i_generation, (int *)arg); + return put_user(inode->i_generation, (int __user *)arg); case LL_IOC_GROUP_LOCK: return ll_get_grouplock(inode, file, arg); case LL_IOC_GROUP_UNLOCK: @@ -2289,7 +2289,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_FLUSHCTX: return ll_flush_ctx(inode); case LL_IOC_PATH2FID: { - if (copy_to_user((void *)arg, ll_inode2fid(inode), + if (copy_to_user((void __user *)arg, ll_inode2fid(inode), sizeof(struct lu_fid))) return -EFAULT; @@ -2301,13 +2301,14 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct ioc_data_version idv; int rc; - if (copy_from_user(&idv, (char *)arg, sizeof(idv))) + 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)); - if (rc == 0 && copy_to_user((char *) arg, &idv, sizeof(idv))) + if (rc == 0 && copy_to_user((char __user *)arg, &idv, + sizeof(idv))) return -EFAULT; return rc; @@ -2320,7 +2321,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (mdtidx < 0) return mdtidx; - if (put_user((int)mdtidx, (int *)arg)) + if (put_user(mdtidx, (int __user *)arg)) return -EFAULT; return 0; @@ -2347,7 +2348,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), op_data, NULL); - if (copy_to_user((void *)arg, hus, sizeof(*hus))) + if (copy_to_user((void __user *)arg, hus, sizeof(*hus))) rc = -EFAULT; ll_finish_md_op_data(op_data); @@ -2358,7 +2359,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct hsm_state_set *hss; int rc; - hss = memdup_user((char *)arg, sizeof(*hss)); + hss = memdup_user((char __user *)arg, sizeof(*hss)); if (IS_ERR(hss)) return PTR_ERR(hss); @@ -2386,7 +2387,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) rc = obd_iocontrol(cmd, ll_i2mdexp(inode), sizeof(*op_data), op_data, NULL); - if (copy_to_user((char *)arg, hca, sizeof(*hca))) + if (copy_to_user((char __user *)arg, hca, sizeof(*hca))) rc = -EFAULT; ll_finish_md_op_data(op_data); @@ -2480,7 +2481,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case LL_IOC_HSM_IMPORT: { struct hsm_user_import *hui; - hui = memdup_user((void *)arg, sizeof(*hui)); + hui = memdup_user((void __user *)arg, sizeof(*hui)); if (IS_ERR(hui)) return PTR_ERR(hui); -- cgit From 61dad0ba9abbe97b80b2199c126e56b1598545eb Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:56 -0500 Subject: staging/lustre: Properly cast ll_fid2path argument to __user in ll_file_ioctl When calling ll_fid2path, it expects a userspace pointer. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index f31f75a446ec..132d19b62147 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -2296,7 +2296,7 @@ ll_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; } case OBD_IOC_FID2PATH: - return ll_fid2path(inode, (void *)arg); + return ll_fid2path(inode, (void __user *)arg); case LL_IOC_DATA_VERSION: { struct ioc_data_version idv; int rc; -- cgit From 7ec89fa54a37b3e8eb8ec5e5b64c845961762e22 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:57 -0500 Subject: staging/lustre: Properly cast ll_fid2path argument to __user in ll_dir_ioctl This makes sparse happier. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 5b41162c7b35..15b8e0a444fa 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1736,7 +1736,7 @@ out_quotactl: sizeof(struct ioc_changelog)); return rc; case OBD_IOC_FID2PATH: - return ll_fid2path(inode, (void *)arg); + return ll_fid2path(inode, (void __user *)arg); case LL_IOC_HSM_REQUEST: { struct hsm_user_request *hur; ssize_t totalsize; -- cgit From d47bb83b1bb778fb8429dc1f12a137039cee4e14 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:58 -0500 Subject: staging/lustre: Properly cast ll_getname argument to __user in ll_dir_ioctl This makes sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index 15b8e0a444fa..fc68e8b4c176 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1448,7 +1448,7 @@ free_lmv: if (cmd == IOC_MDC_GETFILEINFO || cmd == IOC_MDC_GETFILESTRIPE) { - filename = ll_getname((const char *)arg); + filename = ll_getname((const char __user *)arg); if (IS_ERR(filename)) return PTR_ERR(filename); -- cgit From af00f6c5ac2470b44cba595cbc17160e60356d08 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sun, 3 Jan 2016 12:05:59 -0500 Subject: staging/lustre/llite: Update ll_dir_ioctl pointer casts with __user When casting unsingned long userspace pointer from ioctl argument to a pointer suitable for use with userspace access functions, need to remember to add __user attribute, to make sparse happy. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dir.c | 69 ++++++++++++++++--------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c index fc68e8b4c176..36b10559154a 100644 --- a/drivers/staging/lustre/lustre/llite/dir.c +++ b/drivers/staging/lustre/lustre/llite/dir.c @@ -1253,7 +1253,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ll_iocontrol(inode, file, cmd, arg); case FSFILT_IOC_GETVERSION_OLD: case FSFILT_IOC_GETVERSION: - return put_user(inode->i_generation, (int *)arg); + return put_user(inode->i_generation, (int __user *)arg); /* We need to special case any other ioctls we want to handle, * to send them to the MDS/OST as appropriate and to properly * network encode the arg field. @@ -1267,7 +1267,7 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (mdtidx < 0) return mdtidx; - if (put_user((int)mdtidx, (int *)arg)) + if (put_user((int)mdtidx, (int __user *)arg)) return -EFAULT; return 0; @@ -1364,8 +1364,8 @@ lmv_out_free: case LL_IOC_LOV_SETSTRIPE: { struct lov_user_md_v3 lumv3; struct lov_user_md_v1 *lumv1 = (struct lov_user_md_v1 *)&lumv3; - struct lov_user_md_v1 *lumv1p = (struct lov_user_md_v1 *)arg; - struct lov_user_md_v3 *lumv3p = (struct lov_user_md_v3 *)arg; + struct lov_user_md_v1 __user *lumv1p = (void __user *)arg; + struct lov_user_md_v3 __user *lumv3p = (void __user *)arg; int set_default = 0; @@ -1390,7 +1390,7 @@ lmv_out_free: return rc; } case LL_IOC_LMV_GETSTRIPE: { - struct lmv_user_md *lump = (struct lmv_user_md *)arg; + struct lmv_user_md __user *lump = (void __user *)arg; struct lmv_user_md lum; struct lmv_user_md *tmp; int lum_size; @@ -1423,7 +1423,7 @@ lmv_out_free: tmp->lum_objects[0].lum_mds = mdtindex; memcpy(&tmp->lum_objects[0].lum_fid, ll_inode2fid(inode), sizeof(struct lu_fid)); - if (copy_to_user((void *)arg, tmp, lum_size)) { + if (copy_to_user((void __user *)arg, tmp, lum_size)) { rc = -EFAULT; goto free_lmv; } @@ -1440,7 +1440,7 @@ free_lmv: case IOC_MDC_GETFILEINFO: case IOC_MDC_GETFILESTRIPE: { struct ptlrpc_request *request = NULL; - struct lov_user_md *lump; + struct lov_user_md __user *lump; struct lov_mds_md *lmm = NULL; struct mdt_body *body; char *filename = NULL; @@ -1477,11 +1477,11 @@ free_lmv: if (cmd == IOC_MDC_GETFILESTRIPE || cmd == LL_IOC_LOV_GETSTRIPE) { - lump = (struct lov_user_md *)arg; + lump = (struct lov_user_md __user *)arg; } else { - struct lov_user_mds_data *lmdp; + struct lov_user_mds_data __user *lmdp; - lmdp = (struct lov_user_mds_data *)arg; + lmdp = (struct lov_user_mds_data __user *)arg; lump = &lmdp->lmd_lmm; } if (copy_to_user(lump, lmm, lmmsize)) { @@ -1493,7 +1493,7 @@ free_lmv: } skip_lmm: if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) { - struct lov_user_mds_data *lmdp; + struct lov_user_mds_data __user *lmdp; lstat_t st = { 0 }; st.st_dev = inode->i_sb->s_dev; @@ -1510,7 +1510,7 @@ skip_lmm: st.st_ctime = body->ctime; st.st_ino = inode->i_ino; - lmdp = (struct lov_user_mds_data *)arg; + lmdp = (struct lov_user_mds_data __user *)arg; if (copy_to_user(&lmdp->lmd_st, &st, sizeof(st))) { rc = -EFAULT; goto out_req; @@ -1524,14 +1524,14 @@ out_req: return rc; } case IOC_LOV_GETINFO: { - struct lov_user_mds_data *lumd; + struct lov_user_mds_data __user *lumd; struct lov_stripe_md *lsm; - struct lov_user_md *lum; + struct lov_user_md __user *lum; struct lov_mds_md *lmm; int lmmsize; lstat_t st; - lumd = (struct lov_user_mds_data *)arg; + lumd = (struct lov_user_mds_data __user *)arg; lum = &lumd->lmd_lmm; rc = ll_get_max_mdsize(sbi, &lmmsize); @@ -1637,8 +1637,8 @@ free_lmm: NULL); if (rc) { CDEBUG(D_QUOTA, "mdc ioctl %d failed: %d\n", cmd, rc); - if (copy_to_user((void *)arg, check, - sizeof(*check))) + if (copy_to_user((void __user *)arg, check, + sizeof(*check))) CDEBUG(D_QUOTA, "copy_to_user failed\n"); goto out_poll; } @@ -1647,8 +1647,8 @@ free_lmm: NULL); if (rc) { CDEBUG(D_QUOTA, "osc ioctl %d failed: %d\n", cmd, rc); - if (copy_to_user((void *)arg, check, - sizeof(*check))) + if (copy_to_user((void __user *)arg, check, + sizeof(*check))) CDEBUG(D_QUOTA, "copy_to_user failed\n"); goto out_poll; } @@ -1663,14 +1663,15 @@ out_poll: if (!qctl) return -ENOMEM; - if (copy_from_user(qctl, (void *)arg, sizeof(*qctl))) { + if (copy_from_user(qctl, (void __user *)arg, sizeof(*qctl))) { rc = -EFAULT; goto out_quotactl; } rc = quotactl_ioctl(sbi, qctl); - if (rc == 0 && copy_to_user((void *)arg, qctl, sizeof(*qctl))) + if (rc == 0 && copy_to_user((void __user *)arg, qctl, + sizeof(*qctl))) rc = -EFAULT; out_quotactl: @@ -1700,7 +1701,7 @@ out_quotactl: int count, vallen; struct obd_export *exp; - if (copy_from_user(&count, (int *)arg, sizeof(int))) + if (copy_from_user(&count, (int __user *)arg, sizeof(int))) return -EFAULT; /* get ost count when count is zero, get mdt count otherwise */ @@ -1713,14 +1714,14 @@ out_quotactl: return rc; } - if (copy_to_user((int *)arg, &count, sizeof(int))) + if (copy_to_user((int __user *)arg, &count, sizeof(int))) return -EFAULT; return 0; } case LL_IOC_PATH2FID: - if (copy_to_user((void *)arg, ll_inode2fid(inode), - sizeof(struct lu_fid))) + if (copy_to_user((void __user *)arg, ll_inode2fid(inode), + sizeof(struct lu_fid))) return -EFAULT; return 0; case LL_IOC_GET_CONNECT_FLAGS: { @@ -1732,7 +1733,7 @@ out_quotactl: if (!capable(CFS_CAP_SYS_ADMIN)) return -EPERM; - rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg, + rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg, sizeof(struct ioc_changelog)); return rc; case OBD_IOC_FID2PATH: @@ -1741,7 +1742,7 @@ out_quotactl: struct hsm_user_request *hur; ssize_t totalsize; - hur = memdup_user((void *)arg, sizeof(*hur)); + hur = memdup_user((void __user *)arg, sizeof(*hur)); if (IS_ERR(hur)) return PTR_ERR(hur); @@ -1760,7 +1761,7 @@ out_quotactl: return -ENOMEM; /* Copy the whole struct */ - if (copy_from_user(hur, (void *)arg, totalsize)) { + if (copy_from_user(hur, (void __user *)arg, totalsize)) { kvfree(hur); return -EFAULT; } @@ -1796,7 +1797,7 @@ out_quotactl: struct hsm_progress_kernel hpk; struct hsm_progress hp; - if (copy_from_user(&hp, (void *)arg, sizeof(hp))) + if (copy_from_user(&hp, (void __user *)arg, sizeof(hp))) return -EFAULT; hpk.hpk_fid = hp.hp_fid; @@ -1813,7 +1814,7 @@ out_quotactl: return rc; } case LL_IOC_HSM_CT_START: - rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void *)arg, + rc = copy_and_ioctl(cmd, sbi->ll_md_exp, (void __user *)arg, sizeof(struct lustre_kernelcomm)); return rc; @@ -1821,12 +1822,12 @@ out_quotactl: struct hsm_copy *copy; int rc; - copy = memdup_user((char *)arg, sizeof(*copy)); + copy = memdup_user((char __user *)arg, sizeof(*copy)); if (IS_ERR(copy)) return PTR_ERR(copy); rc = ll_ioc_copy_start(inode->i_sb, copy); - if (copy_to_user((char *)arg, copy, sizeof(*copy))) + if (copy_to_user((char __user *)arg, copy, sizeof(*copy))) rc = -EFAULT; kfree(copy); @@ -1836,12 +1837,12 @@ out_quotactl: struct hsm_copy *copy; int rc; - copy = memdup_user((char *)arg, sizeof(*copy)); + copy = memdup_user((char __user *)arg, sizeof(*copy)); if (IS_ERR(copy)) return PTR_ERR(copy); rc = ll_ioc_copy_end(inode->i_sb, copy); - if (copy_to_user((char *)arg, copy, sizeof(*copy))) + if (copy_to_user((char __user *)arg, copy, sizeof(*copy))) rc = -EFAULT; kfree(copy); -- cgit From 08816b2eb1ee4b41b52abc4b94b97cd2c5c15c10 Mon Sep 17 00:00:00 2001 From: Frank Zago Date: Sun, 3 Jan 2016 12:06:00 -0500 Subject: staging/lustre: Add __user annotations in lnetselftest code This fixes a bunch of sparse warnings. There is no code change. Signed-off-by: frank zago Reviewed-on: http://review.whamcloud.com/11819 Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-5396 Reviewed-by: James Simmons Reviewed-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lnetst.h | 104 ++++++++++----------- drivers/staging/lustre/lnet/selftest/conrpc.c | 4 +- drivers/staging/lustre/lnet/selftest/conrpc.h | 5 +- drivers/staging/lustre/lnet/selftest/console.c | 96 ++++++++++--------- drivers/staging/lustre/lnet/selftest/console.h | 56 +++++------ 5 files changed, 138 insertions(+), 127 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lnetst.h b/drivers/staging/lustre/include/linux/lnet/lnetst.h index fd1e0fd3696f..417044552d3f 100644 --- a/drivers/staging/lustre/include/linux/lnet/lnetst.h +++ b/drivers/staging/lustre/include/linux/lnet/lnetst.h @@ -245,20 +245,20 @@ typedef struct { int lstio_ses_force; /* IN: force create ? */ /** IN: session features */ unsigned lstio_ses_feats; - lst_sid_t *lstio_ses_idp; /* OUT: session id */ + lst_sid_t __user *lstio_ses_idp; /* OUT: session id */ int lstio_ses_nmlen; /* IN: name length */ - char *lstio_ses_namep; /* IN: session name */ + char __user *lstio_ses_namep; /* IN: session name */ } lstio_session_new_args_t; /* query current session */ typedef struct { - lst_sid_t *lstio_ses_idp; /* OUT: session id */ - int *lstio_ses_keyp; /* OUT: local key */ + lst_sid_t __user *lstio_ses_idp; /* OUT: session id */ + int __user *lstio_ses_keyp; /* OUT: local key */ /** OUT: session features */ - unsigned *lstio_ses_featp; - lstcon_ndlist_ent_t *lstio_ses_ndinfo; /* OUT: */ + unsigned __user *lstio_ses_featp; + lstcon_ndlist_ent_t __user *lstio_ses_ndinfo; /* OUT: */ int lstio_ses_nmlen; /* IN: name length */ - char *lstio_ses_namep; /* OUT: session name */ + char __user *lstio_ses_namep; /* OUT: session name */ } lstio_session_info_args_t; /* delete a session */ @@ -283,26 +283,26 @@ typedef struct { int lstio_dbg_timeout; /* IN: timeout of debug */ int lstio_dbg_nmlen; /* IN: len of name */ - char *lstio_dbg_namep; /* IN: name of + char __user *lstio_dbg_namep; /* IN: name of group|batch */ int lstio_dbg_count; /* IN: # of test nodes to debug */ - lnet_process_id_t *lstio_dbg_idsp; /* IN: id of test + lnet_process_id_t __user *lstio_dbg_idsp; /* IN: id of test nodes */ - struct list_head *lstio_dbg_resultp; /* OUT: list head of + struct list_head __user *lstio_dbg_resultp; /* OUT: list head of result buffer */ } lstio_debug_args_t; typedef struct { - int lstio_grp_key; /* IN: session key */ - int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + int lstio_grp_key; /* IN: session key */ + int lstio_grp_nmlen; /* IN: name length */ + char __user *lstio_grp_namep; /* IN: group name */ } lstio_group_add_args_t; typedef struct { - int lstio_grp_key; /* IN: session key */ - int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + int lstio_grp_key; /* IN: session key */ + int lstio_grp_nmlen; /* IN: name length */ + char __user *lstio_grp_namep; /* IN: group name */ } lstio_group_del_args_t; #define LST_GROUP_CLEAN 1 /* remove inactive nodes in the group */ @@ -315,22 +315,22 @@ typedef struct { int lstio_grp_opc; /* IN: OPC */ int lstio_grp_args; /* IN: arguments */ int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + char __user *lstio_grp_namep; /* IN: group name */ int lstio_grp_count; /* IN: # of nodes id */ - lnet_process_id_t *lstio_grp_idsp; /* IN: array of nodes */ - struct list_head *lstio_grp_resultp; /* OUT: list head of + lnet_process_id_t __user *lstio_grp_idsp; /* IN: array of nodes */ + struct list_head __user *lstio_grp_resultp; /* OUT: list head of result buffer */ } lstio_group_update_args_t; typedef struct { int lstio_grp_key; /* IN: session key */ int lstio_grp_nmlen; /* IN: name length */ - char *lstio_grp_namep; /* IN: group name */ + char __user *lstio_grp_namep; /* IN: group name */ int lstio_grp_count; /* IN: # of nodes */ /** OUT: session features */ - unsigned *lstio_grp_featp; - lnet_process_id_t *lstio_grp_idsp; /* IN: nodes */ - struct list_head *lstio_grp_resultp; /* OUT: list head of + unsigned __user *lstio_grp_featp; + lnet_process_id_t __user *lstio_grp_idsp; /* IN: nodes */ + struct list_head __user *lstio_grp_resultp; /* OUT: list head of result buffer */ } lstio_group_nodes_args_t; @@ -338,18 +338,18 @@ typedef struct { int lstio_grp_key; /* IN: session key */ int lstio_grp_idx; /* IN: group idx */ int lstio_grp_nmlen; /* IN: name len */ - char *lstio_grp_namep; /* OUT: name */ + char __user *lstio_grp_namep; /* OUT: name */ } lstio_group_list_args_t; typedef struct { int lstio_grp_key; /* IN: session key */ int lstio_grp_nmlen; /* IN: name len */ - char *lstio_grp_namep; /* IN: name */ - lstcon_ndlist_ent_t *lstio_grp_entp; /* OUT: description of + char __user *lstio_grp_namep; /* IN: name */ + lstcon_ndlist_ent_t __user *lstio_grp_entp; /* OUT: description of group */ - int *lstio_grp_idxp; /* IN/OUT: node index */ - int *lstio_grp_ndentp; /* IN/OUT: # of nodent */ - lstcon_node_ent_t *lstio_grp_dentsp; /* OUT: nodent array */ + int __user *lstio_grp_idxp; /* IN/OUT: node index */ + int __user *lstio_grp_ndentp; /* IN/OUT: # of nodent */ + lstcon_node_ent_t __user *lstio_grp_dentsp; /* OUT: nodent array */ } lstio_group_info_args_t; #define LST_DEFAULT_BATCH "batch" /* default batch name */ @@ -357,13 +357,13 @@ typedef struct { typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ + char __user *lstio_bat_namep; /* IN: batch name */ } lstio_batch_add_args_t; typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ + char __user *lstio_bat_namep; /* IN: batch name */ } lstio_batch_del_args_t; typedef struct { @@ -371,8 +371,8 @@ typedef struct { int lstio_bat_timeout; /* IN: timeout for the batch */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ - struct list_head *lstio_bat_resultp; /* OUT: list head of + char __user *lstio_bat_namep; /* IN: batch name */ + struct list_head __user *lstio_bat_resultp; /* OUT: list head of result buffer */ } lstio_batch_run_args_t; @@ -381,8 +381,8 @@ typedef struct { int lstio_bat_force; /* IN: abort unfinished test RPC */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ - struct list_head *lstio_bat_resultp; /* OUT: list head of + char __user *lstio_bat_namep; /* IN: batch name */ + struct list_head __user *lstio_bat_resultp; /* OUT: list head of result buffer */ } lstio_batch_stop_args_t; @@ -394,8 +394,8 @@ typedef struct { int lstio_bat_timeout; /* IN: timeout for waiting */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ - struct list_head *lstio_bat_resultp; /* OUT: list head of + char __user *lstio_bat_namep; /* IN: batch name */ + struct list_head __user *lstio_bat_resultp; /* OUT: list head of result buffer */ } lstio_batch_query_args_t; @@ -403,21 +403,21 @@ typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_idx; /* IN: index */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: batch name */ + char __user *lstio_bat_namep; /* IN: batch name */ } lstio_batch_list_args_t; typedef struct { int lstio_bat_key; /* IN: session key */ int lstio_bat_nmlen; /* IN: name length */ - char *lstio_bat_namep; /* IN: name */ + char __user *lstio_bat_namep; /* IN: name */ int lstio_bat_server; /* IN: query server or not */ int lstio_bat_testidx; /* IN: test index */ - lstcon_test_batch_ent_t *lstio_bat_entp; /* OUT: batch ent */ + lstcon_test_batch_ent_t __user *lstio_bat_entp; /* OUT: batch ent */ - int *lstio_bat_idxp; /* IN/OUT: index of node */ - int *lstio_bat_ndentp; /* IN/OUT: # of nodent */ - lstcon_node_ent_t *lstio_bat_dentsp; /* array of nodent */ + int __user *lstio_bat_idxp; /* IN/OUT: index of node */ + int __user *lstio_bat_ndentp; /* IN/OUT: # of nodent */ + lstcon_node_ent_t __user *lstio_bat_dentsp; /* array of nodent */ } lstio_batch_info_args_t; /* add stat in session */ @@ -427,10 +427,10 @@ typedef struct { stat request */ int lstio_sta_nmlen; /* IN: group name length */ - char *lstio_sta_namep; /* IN: group name */ + char __user *lstio_sta_namep; /* IN: group name */ int lstio_sta_count; /* IN: # of pid */ - lnet_process_id_t *lstio_sta_idsp; /* IN: pid */ - struct list_head *lstio_sta_resultp; /* OUT: list head of + lnet_process_id_t __user *lstio_sta_idsp; /* IN: pid */ + struct list_head __user *lstio_sta_resultp; /* OUT: list head of result buffer */ } lstio_stat_args_t; @@ -445,7 +445,7 @@ typedef enum { typedef struct { int lstio_tes_key; /* IN: session key */ int lstio_tes_bat_nmlen; /* IN: batch name len */ - char *lstio_tes_bat_name; /* IN: batch name */ + char __user *lstio_tes_bat_name; /* IN: batch name */ int lstio_tes_type; /* IN: test type */ int lstio_tes_oneside; /* IN: one sided test */ int lstio_tes_loop; /* IN: loop count */ @@ -457,20 +457,20 @@ typedef struct { destination groups */ int lstio_tes_sgrp_nmlen; /* IN: source group name length */ - char *lstio_tes_sgrp_name; /* IN: group name */ + char __user *lstio_tes_sgrp_name; /* IN: group name */ int lstio_tes_dgrp_nmlen; /* IN: destination group name length */ - char *lstio_tes_dgrp_name; /* IN: group name */ + char __user *lstio_tes_dgrp_name; /* IN: group name */ int lstio_tes_param_len; /* IN: param buffer len */ - void *lstio_tes_param; /* IN: parameter for specified + void __user *lstio_tes_param; /* IN: parameter for specified test: lstio_bulk_param_t, lstio_ping_param_t, ... more */ - int *lstio_tes_retp; /* OUT: private returned + int __user *lstio_tes_retp; /* OUT: private returned value */ - struct list_head *lstio_tes_resultp; /* OUT: list head of + struct list_head __user *lstio_tes_resultp;/* OUT: list head of result buffer */ } lstio_test_args_t; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 1066c70434b1..15a61ded6206 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -466,11 +466,11 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, - struct list_head *head_up, + struct list_head __user *head_up, lstcon_rpc_readent_func_t readent) { struct list_head tmp; - struct list_head *next; + struct list_head __user *next; lstcon_rpc_ent_t *ent; srpc_generic_reply_t *rep; lstcon_rpc_t *crpc; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h index 95c832ff7375..d2133bc76e93 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.h +++ b/drivers/staging/lustre/lnet/selftest/conrpc.h @@ -106,7 +106,8 @@ typedef 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 *, lstcon_rpc_ent_t *); +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); @@ -128,7 +129,7 @@ int lstcon_rpc_trans_ndlist(struct list_head *ndlist, void lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat); int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, - struct list_head *head_up, + 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); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 5619fc430e8d..366211e02ed8 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -363,7 +363,7 @@ lstcon_sesrpc_condition(int transop, lstcon_node_t *nd, void *arg) static int lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, - lstcon_rpc_ent_t *ent_up) + lstcon_rpc_ent_t __user *ent_up) { srpc_debug_reply_t *rep; @@ -392,8 +392,8 @@ lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, static int lstcon_group_nodes_add(lstcon_group_t *grp, - int count, lnet_process_id_t *ids_up, - unsigned *featp, struct list_head *result_up) + int count, lnet_process_id_t __user *ids_up, + unsigned *featp, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; @@ -459,8 +459,8 @@ lstcon_group_nodes_add(lstcon_group_t *grp, static int lstcon_group_nodes_remove(lstcon_group_t *grp, - int count, lnet_process_id_t *ids_up, - struct list_head *result_up) + int count, lnet_process_id_t __user *ids_up, + struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; @@ -537,8 +537,8 @@ lstcon_group_add(char *name) } int -lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up, - unsigned *featp, struct list_head *result_up) +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; int rc; @@ -641,8 +641,8 @@ lstcon_group_clean(char *name, int args) } int -lstcon_nodes_remove(char *name, int count, - lnet_process_id_t *ids_up, struct list_head *result_up) +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; int rc; @@ -671,7 +671,7 @@ lstcon_nodes_remove(char *name, int count, } int -lstcon_group_refresh(char *name, struct list_head *result_up) +lstcon_group_refresh(char *name, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_group_t *grp; @@ -713,7 +713,7 @@ lstcon_group_refresh(char *name, struct list_head *result_up) } int -lstcon_group_list(int index, int len, char *name_up) +lstcon_group_list(int index, int len, char __user *name_up) { lstcon_group_t *grp; @@ -732,7 +732,7 @@ lstcon_group_list(int index, int len, char *name_up) static int lstcon_nodes_getent(struct list_head *head, int *index_p, - int *count_p, lstcon_node_ent_t *dents_up) + int *count_p, lstcon_node_ent_t __user *dents_up) { lstcon_ndlink_t *ndl; lstcon_node_t *nd; @@ -771,8 +771,9 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, } int -lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, - int *index_p, int *count_p, lstcon_node_ent_t *dents_up) +lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, + int *index_p, int *count_p, + lstcon_node_ent_t __user *dents_up) { lstcon_ndlist_ent_t *gentp; lstcon_group_t *grp; @@ -892,7 +893,7 @@ lstcon_batch_add(char *name) } int -lstcon_batch_list(int index, int len, char *name_up) +lstcon_batch_list(int index, int len, char __user *name_up) { lstcon_batch_t *bat; @@ -910,9 +911,9 @@ lstcon_batch_list(int index, int len, char *name_up) } int -lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up, int server, - int testidx, int *index_p, int *ndent_p, - lstcon_node_ent_t *dents_up) +lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, + int server, int testidx, int *index_p, int *ndent_p, + lstcon_node_ent_t __user *dents_up) { lstcon_test_batch_ent_t *entp; struct list_head *clilst; @@ -1006,7 +1007,7 @@ lstcon_batrpc_condition(int transop, lstcon_node_t *nd, void *arg) static int lstcon_batch_op(lstcon_batch_t *bat, int transop, - struct list_head *result_up) + struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; int rc; @@ -1029,7 +1030,7 @@ lstcon_batch_op(lstcon_batch_t *bat, int transop, } int -lstcon_batch_run(char *name, int timeout, struct list_head *result_up) +lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up) { lstcon_batch_t *bat; int rc; @@ -1051,7 +1052,7 @@ lstcon_batch_run(char *name, int timeout, struct list_head *result_up) } int -lstcon_batch_stop(char *name, int force, struct list_head *result_up) +lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) { lstcon_batch_t *bat; int rc; @@ -1170,7 +1171,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 *result_up) +lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; lstcon_group_t *grp; @@ -1266,7 +1267,7 @@ lstcon_test_add(char *batch_name, int type, int loop, int concur, int dist, int span, char *src_name, char *dst_name, void *param, int paramlen, int *retp, - struct list_head *result_up) + struct list_head __user *result_up) { lstcon_test_t *test = NULL; int rc; @@ -1369,7 +1370,7 @@ lstcon_test_find(lstcon_batch_t *batch, int idx, lstcon_test_t **testpp) static int lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg, - lstcon_rpc_ent_t *ent_up) + lstcon_rpc_ent_t __user *ent_up) { srpc_batch_reply_t *rep = &msg->msg_body.bat_reply; @@ -1386,7 +1387,7 @@ lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg, int lstcon_test_batch_query(char *name, int testidx, int client, - int timeout, struct list_head *result_up) + int timeout, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; struct list_head *translist; @@ -1448,19 +1449,21 @@ lstcon_test_batch_query(char *name, int testidx, int client, static int lstcon_statrpc_readent(int transop, srpc_msg_t *msg, - lstcon_rpc_ent_t *ent_up) + lstcon_rpc_ent_t __user *ent_up) { srpc_stat_reply_t *rep = &msg->msg_body.stat_reply; - sfw_counters_t *sfwk_stat; - srpc_counters_t *srpc_stat; - lnet_counters_t *lnet_stat; + sfw_counters_t __user *sfwk_stat; + srpc_counters_t __user *srpc_stat; + lnet_counters_t __user *lnet_stat; if (rep->str_status != 0) return 0; - sfwk_stat = (sfw_counters_t *)&ent_up->rpe_payload[0]; - srpc_stat = (srpc_counters_t *)((char *)sfwk_stat + sizeof(*sfwk_stat)); - lnet_stat = (lnet_counters_t *)((char *)srpc_stat + sizeof(*srpc_stat)); + sfwk_stat = (sfw_counters_t __user *)&ent_up->rpe_payload[0]; + srpc_stat = (srpc_counters_t __user *) + ((char *)sfwk_stat + sizeof(*sfwk_stat)); + lnet_stat = (lnet_counters_t __user *) + ((char *)srpc_stat + sizeof(*srpc_stat)); if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) || copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) || @@ -1472,7 +1475,7 @@ lstcon_statrpc_readent(int transop, srpc_msg_t *msg, static int lstcon_ndlist_stat(struct list_head *ndlist, - int timeout, struct list_head *result_up) + int timeout, struct list_head __user *result_up) { struct list_head head; lstcon_rpc_trans_t *trans; @@ -1497,7 +1500,8 @@ lstcon_ndlist_stat(struct list_head *ndlist, } int -lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up) +lstcon_group_stat(char *grp_name, int timeout, + struct list_head __user *result_up) { lstcon_group_t *grp; int rc; @@ -1516,8 +1520,8 @@ lstcon_group_stat(char *grp_name, int timeout, struct list_head *result_up) } int -lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, - int timeout, struct list_head *result_up) +lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, + int timeout, struct list_head __user *result_up) { lstcon_ndlink_t *ndl; lstcon_group_t *tmp; @@ -1562,7 +1566,7 @@ lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, static int lstcon_debug_ndlist(struct list_head *ndlist, struct list_head *translist, - int timeout, struct list_head *result_up) + int timeout, struct list_head __user *result_up) { lstcon_rpc_trans_t *trans; int rc; @@ -1584,7 +1588,7 @@ lstcon_debug_ndlist(struct list_head *ndlist, } int -lstcon_session_debug(int timeout, struct list_head *result_up) +lstcon_session_debug(int timeout, struct list_head __user *result_up) { return lstcon_debug_ndlist(&console_session.ses_ndl_list, NULL, timeout, result_up); @@ -1592,7 +1596,7 @@ lstcon_session_debug(int timeout, struct list_head *result_up) int lstcon_batch_debug(int timeout, char *name, - int client, struct list_head *result_up) + int client, struct list_head __user *result_up) { lstcon_batch_t *bat; int rc; @@ -1610,7 +1614,7 @@ lstcon_batch_debug(int timeout, char *name, int lstcon_group_debug(int timeout, char *name, - struct list_head *result_up) + struct list_head __user *result_up) { lstcon_group_t *grp; int rc; @@ -1628,8 +1632,8 @@ lstcon_group_debug(int timeout, char *name, int lstcon_nodes_debug(int timeout, - int count, lnet_process_id_t *ids_up, - struct list_head *result_up) + int count, lnet_process_id_t __user *ids_up, + struct list_head __user *result_up) { lnet_process_id_t id; lstcon_ndlink_t *ndl; @@ -1693,7 +1697,7 @@ extern srpc_service_t lstcon_acceptor_service; int lstcon_session_new(char *name, int key, unsigned feats, - int timeout, int force, lst_sid_t *sid_up) + int timeout, int force, lst_sid_t __user *sid_up) { int rc = 0; int i; @@ -1758,8 +1762,10 @@ lstcon_session_new(char *name, int key, unsigned feats, } int -lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp, - lstcon_ndlist_ent_t *ndinfo_up, char *name_up, int len) +lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up, + unsigned __user *featp, + lstcon_ndlist_ent_t __user *ndinfo_up, + char __user *name_up, int len) { lstcon_ndlist_ent_t *entp; lstcon_ndlink_t *ndl; diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index 3f3286c0c7bf..f7ccaeb28be0 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -188,47 +188,51 @@ int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data); int lstcon_console_fini(void); int lstcon_session_match(lst_sid_t sid); int lstcon_session_new(char *name, int key, unsigned version, - int timeout, int flags, lst_sid_t *sid_up); -int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp, - lstcon_ndlist_ent_t *entp, char *name_up, int len); + int timeout, int flags, lst_sid_t __user *sid_up); +int lstcon_session_info(lst_sid_t __user *sid_up, int __user *key, + unsigned __user *verp, lstcon_ndlist_ent_t __user *entp, + char __user *name_up, int len); int lstcon_session_end(void); -int lstcon_session_debug(int timeout, struct list_head *result_up); +int lstcon_session_debug(int timeout, struct list_head __user *result_up); int lstcon_session_feats_check(unsigned feats); int lstcon_batch_debug(int timeout, char *name, - int client, struct list_head *result_up); + int client, struct list_head __user *result_up); int lstcon_group_debug(int timeout, char *name, - struct list_head *result_up); -int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t *nds_up, - struct list_head *result_up); + struct list_head __user *result_up); +int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t __user *nds_up, + struct list_head __user *result_up); int lstcon_group_add(char *name); int lstcon_group_del(char *name); int lstcon_group_clean(char *name, int args); -int lstcon_group_refresh(char *name, struct list_head *result_up); -int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up, - unsigned *featp, struct list_head *result_up); -int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up, - struct list_head *result_up); -int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up, - int *index_p, int *ndent_p, lstcon_node_ent_t *ndents_up); -int lstcon_group_list(int idx, int len, char *name_up); +int lstcon_group_refresh(char *name, struct list_head __user *result_up); +int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t __user *nds_up, + unsigned *featp, struct list_head __user *result_up); +int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t __user *nds_up, + struct list_head __user *result_up); +int lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gent_up, + int *index_p, int *ndent_p, + lstcon_node_ent_t __user *ndents_up); +int lstcon_group_list(int idx, int len, char __user *name_up); int lstcon_batch_add(char *name); -int lstcon_batch_run(char *name, int timeout, struct list_head *result_up); -int lstcon_batch_stop(char *name, int force, struct list_head *result_up); +int 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); int lstcon_test_batch_query(char *name, int testidx, int client, int timeout, - struct list_head *result_up); + struct list_head __user *result_up); int lstcon_batch_del(char *name); -int lstcon_batch_list(int idx, int namelen, char *name_up); -int lstcon_batch_info(char *name, lstcon_test_batch_ent_t *ent_up, +int lstcon_batch_list(int idx, int namelen, char __user *name_up); +int lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, int server, int testidx, int *index_p, - int *ndent_p, lstcon_node_ent_t *dents_up); + int *ndent_p, lstcon_node_ent_t __user *dents_up); int lstcon_group_stat(char *grp_name, int timeout, - struct list_head *result_up); -int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up, - int timeout, struct list_head *result_up); + struct list_head __user *result_up); +int lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, + int timeout, struct list_head __user *result_up); int lstcon_test_add(char *batch_name, int type, int loop, int concur, int dist, int span, char *src_name, char *dst_name, void *param, int paramlen, int *retp, - struct list_head *result_up); + struct list_head __user *result_up); #endif -- cgit From b0e7d960884abf9044c5c84c185bc6815f4b88e5 Mon Sep 17 00:00:00 2001 From: Parinay Kondekar Date: Tue, 5 Jan 2016 14:35:13 -0500 Subject: staging:lustre: remove obsolete comment in libcfs_ioctl.h The libcfs_ioctl.h header has a comment about a snapshot ioctl which has been removed for years. Lets remove the comment to avoid confusion. Broken out of patch 17492. 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 | 1 - 1 file changed, 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 05f2191e08fb..e4463ada0343 100644 --- a/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h +++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_ioctl.h @@ -102,7 +102,6 @@ struct libcfs_ioctl_handler { /* FIXME check conflict with lustre_lib.h */ #define LIBCFS_IOC_DEBUG_MASK _IOWR('f', 250, long) -/* ioctls for manipulating snapshots 30- */ #define IOC_LIBCFS_TYPE 'e' #define IOC_LIBCFS_MIN_NR 30 /* libcfs ioctls */ -- cgit From 62fcd58943654b0474f8d97309185dca1addd5a7 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 15 Jan 2016 11:32:11 +0530 Subject: Staging:lustre:lustre:obdclass:Remove return from void function This patch removes the return statement at the end of a void function as it is not necessary.This was found by checkpatch.pl . Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/llog_swab.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/llog_swab.c b/drivers/staging/lustre/lustre/obdclass/llog_swab.c index 3aa7393b20c3..8f57a8eb412c 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_swab.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_swab.c @@ -406,7 +406,5 @@ void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size) __swab64s(&marker->cm_createtime); __swab64s(&marker->cm_canceltime); } - - return; } EXPORT_SYMBOL(lustre_swab_cfg_marker); -- cgit From 9edece72e2cfb449a8c1a18275cb369861ab8fc8 Mon Sep 17 00:00:00 2001 From: Anjali Menon Date: Sat, 16 Jan 2016 15:30:50 +0530 Subject: staging: lustre: lustre: lov: Added space Added a spaces around '|' to fix the check detected by checkpatch.pl CHECK: spaces preferred around that '|' (ctx:VxV) Signed-off-by: Anjali Menon Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index 3733fdc88c8c..2c33cbce5940 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -334,7 +334,7 @@ static struct lov_device_emerg **lov_emerg_alloc(int nr) emerg[i] = em; cl_page_list_init(&em->emrg_page_list); em->emrg_env = cl_env_alloc(&em->emrg_refcheck, - LCT_REMEMBER|LCT_NOREF); + LCT_REMEMBER | LCT_NOREF); if (!IS_ERR(em->emrg_env)) em->emrg_env->le_ctx.lc_cookie = 0x2; else { -- cgit From 587cb02269c38dbd5d0f33e8ee08e5ca280b4b07 Mon Sep 17 00:00:00 2001 From: Sushuruth Sadagopan Date: Mon, 18 Jan 2016 02:09:23 -0500 Subject: staging: lustre: fix comment style Fix style of several comments. Signed-off-by: Sushuruth Sadagopan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/config.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 284a3c271bc6..74d644d7d729 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -217,12 +217,16 @@ lnet_parse_networks(struct list_head *nilist, char *networks) int niface; int rc; - /* NB we don't check interface conflicts here; it's the LNDs - * responsibility (if it cares at all) */ + /* + * NB we don't check interface conflicts here; it's the LNDs + * responsibility (if it cares at all) + */ if (square != NULL && (comma == NULL || square < comma)) { - /* i.e: o2ib0(ib0)[1,2], number between square - * brackets are CPTs this NI needs to be bond */ + /* + * i.e: o2ib0(ib0)[1,2], number between square + * brackets are CPTs this NI needs to be bond + */ if (bracket != NULL && bracket > square) { tmp = square; goto failed_syntax; @@ -609,8 +613,10 @@ lnet_parse_priority(char *str, unsigned int *priority, char **token) len = strlen(sep + 1); if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) { - /* Update the caller's token pointer so it treats the found - priority as the token to report in the error message. */ + /* + * Update the caller's token pointer so it treats the found + * priority as the token to report in the error message. + */ *token += sep - str + 1; return -1; } -- cgit From 197cb405b3ed1707ab4347b3ce8803fca7403939 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 21 Jan 2016 00:17:44 +0530 Subject: Staging:lustre:obdclass:linux:remove unnecessary braces Fixed 'braces {} are not necessary for single statement blocks' checkpatch.pl warning. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c index f8d3a639e85c..b0ee4db1e82b 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -144,9 +144,8 @@ int obd_ioctl_getdata(char **buf, int *len, void __user *arg) offset += cfs_size_round(data->ioc_inllen3); } - if (data->ioc_inllen4) { + if (data->ioc_inllen4) data->ioc_inlbuf4 = &data->ioc_bulk[0] + offset; - } return 0; @@ -250,9 +249,8 @@ static ssize_t health_show(struct kobject *kobj, struct attribute *attr, class_incref(obd, __func__, current); read_unlock(&obd_dev_lock); - if (obd_health_check(NULL, obd)) { + if (obd_health_check(NULL, obd)) healthy = false; - } class_decref(obd, __func__, current); read_lock(&obd_dev_lock); } -- cgit From 6ae07f1b38d18589fdeaa150b86252f02b2750fb Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 21 Jan 2016 00:17:45 +0530 Subject: Staging:lustre:obdclass:linux:simplify NULL comparison Remove explicit NULL comparision and replace it with a simpier form. Detected using checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/linux/linux-module.c | 6 +++--- 1 file changed, 3 insertions(+), 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 b0ee4db1e82b..1913f3e00ad5 100644 --- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c +++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c @@ -239,7 +239,7 @@ static ssize_t health_show(struct kobject *kobj, struct attribute *attr, struct obd_device *obd; obd = class_num2obd(i); - if (obd == NULL || !obd->obd_attached || !obd->obd_set_up) + if (!obd || !obd->obd_attached || !obd->obd_set_up) continue; LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); @@ -358,7 +358,7 @@ static int obd_device_list_seq_show(struct seq_file *p, void *v) struct obd_device *obd = class_num2obd((int)index); char *status; - if (obd == NULL) + if (!obd) return 0; LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC); @@ -422,7 +422,7 @@ int class_procfs_init(void) struct dentry *file; lustre_kobj = kobject_create_and_add("lustre", fs_kobj); - if (lustre_kobj == NULL) + if (!lustre_kobj) goto out; /* Create the files associated with this kobject */ -- cgit From 61382aa809e48dcd09109becf6b09715a8f492ac Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 23 Jan 2016 18:41:53 +0530 Subject: Staging:lustre:lustre:llite:Remove explicit NULL comparision Replaced explicit NULL comparision with its simplier form. Found using coccinelle: @replace_rule@ expression e; @@ -e == NULL + !e Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/dcache.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c index 3d6745e63fe3..bc179e5ac260 100644 --- a/drivers/staging/lustre/lustre/llite/dcache.c +++ b/drivers/staging/lustre/lustre/llite/dcache.c @@ -62,7 +62,7 @@ static void ll_release(struct dentry *de) LASSERT(de != NULL); lld = ll_d2d(de); - if (lld == NULL) /* NFS copies the de->d_op methods (bug 4655) */ + if (!lld) /* NFS copies the de->d_op methods (bug 4655) */ return; if (lld->lld_it) { @@ -131,7 +131,7 @@ static int find_cbdata(struct inode *inode) return rc; lsm = ccc_inode_lsm_get(inode); - if (lsm == NULL) + if (!lsm) return rc; rc = obd_find_cbdata(sbi->ll_dt_exp, lsm, return_if_equal, NULL); @@ -184,13 +184,13 @@ int ll_d_init(struct dentry *de) de, de, de->d_parent, d_inode(de), d_count(de)); - if (de->d_fsdata == NULL) { + if (!de->d_fsdata) { struct ll_dentry_data *lld; lld = kzalloc(sizeof(*lld), GFP_NOFS); if (likely(lld)) { spin_lock(&de->d_lock); - if (likely(de->d_fsdata == NULL)) { + if (likely(!de->d_fsdata)) { de->d_fsdata = lld; __d_lustre_invalidate(de); } else { @@ -328,7 +328,7 @@ static int ll_revalidate_dentry(struct dentry *dentry, if (lookup_flags & LOOKUP_RCU) return -ECHILD; - do_statahead_enter(dir, &dentry, d_inode(dentry) == NULL); + do_statahead_enter(dir, &dentry, !d_inode(dentry)); ll_statahead_mark(dir, dentry); return 1; } -- cgit From 364b72e5009fefd3d30e311465924e78ac07af14 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 29 Jan 2016 14:14:26 +0530 Subject: Staging:lustre:lclient:Remove unused function Discard the function ccc_vmpage_page_transient as it is not used anywhere in the kernel. Used grep to find occurences. Problem found using sparse. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lclient/lcommon_cl.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 34dde7dede74..4dfeb4e07d41 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -985,17 +985,6 @@ struct inode *ccc_object_inode(const struct cl_object *obj) return cl2ccc(obj)->cob_inode; } -/** - * Returns a pointer to cl_page associated with \a vmpage, without acquiring - * additional reference to the resulting page. This is an unsafe version of - * cl_vmpage_page() that can only be used under vmpage lock. - */ -struct cl_page *ccc_vmpage_page_transient(struct page *vmpage) -{ - KLASSERT(PageLocked(vmpage)); - return (struct cl_page *)vmpage->private; -} - /** * Initialize or update CLIO structures for regular files when new * meta-data arrives from the server. -- cgit From 1dd44dda6e7d1ca25765f7119d566c3669b6c909 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:48:57 +0900 Subject: staging: wilc1000: fix return type of wilc_add_pkt declaration This patch changes return type of wilc_add_pkt declaration from s32 to int. The return type of this function declaration and definition should be same as data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 8faac27002e9..be1536ada175 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -312,7 +312,7 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index); int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, u8 index, u8 mode, enum AUTHTYPE auth_type); -s32 wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen, +int wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen, const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, -- cgit From 961875ed9e7d88fc0e79d32c883775064cbb63fd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:48:58 +0900 Subject: staging: wilc1000: match argument name of wilc_add_ptk declaration Some arguments name of wilc_add_pkt declaration is different to those of this function definition. It is changed as same name of this function declaration and definition. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index be1536ada175..7e89776baa97 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -312,9 +312,9 @@ int wilc_add_wep_key_bss_sta(struct wilc_vif *vif, const u8 *key, u8 len, u8 index); int wilc_add_wep_key_bss_ap(struct wilc_vif *vif, const u8 *key, u8 len, u8 index, u8 mode, enum AUTHTYPE auth_type); -int wilc_add_ptk(struct wilc_vif *vif, const u8 *pu8Ptk, u8 u8PtkKeylen, - const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, - u8 mode, u8 u8Ciphermode, u8 u8Idx); +int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, + const u8 *mac_addr, const u8 *rx_mic, const u8 *tx_mic, + u8 mode, u8 cipher_mode, u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *pu32InactiveTime); s32 wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, -- cgit From a11486e48b24bb8c2fef218adfedafde65345d05 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:48:59 +0900 Subject: staging: wilc1000: fix return type of wilc_add_rx_gtk declaration This patch changes return type of wilc_add_rx_gtk declaration from s32 to int. The return type of this function declaration and definition should be same as data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7e89776baa97..02c1017156d5 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -317,7 +317,7 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, u8 mode, u8 cipher_mode, u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *pu32InactiveTime); -s32 wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, +int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode); -- cgit From 9676108e926a1432bb9dcfc8eef0de2243cadda4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:00 +0900 Subject: staging: wilc1000: match argument name of wilc_add_rx_gtk declaration Some argument name of wilc_add_rx_gtk declaration is different to those of this function definition. It is changed as same name of this function declaration and definition. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 02c1017156d5..6a5f3bd23055 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -317,10 +317,10 @@ int wilc_add_ptk(struct wilc_vif *vif, const u8 *ptk, u8 ptk_key_len, u8 mode, u8 cipher_mode, u8 index); s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, u32 *pu32InactiveTime); -int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *pu8RxGtk, u8 u8GtkKeylen, - u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC, - const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, - u8 u8Ciphermode); +int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, + u8 index, u32 key_rsc_len, const u8 *key_rsc, + const u8 *rx_mic, const u8 *tx_mic, u8 mode, + u8 cipher_mode); s32 wilc_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx); s32 wilc_set_pmkid_info(struct wilc_vif *vif, -- cgit From ad510dac485718de0c65fb27888aa6ef274bdaf9 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:01 +0900 Subject: staging: wilc1000: remove wilc_add_tx_gtk declaration This patch deletes wilc_add_tx_gtk declaration. It is not find wilc_add_tx_gtk definition in this driver. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6a5f3bd23055..a21ca3768124 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -321,8 +321,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 index, u32 key_rsc_len, const u8 *key_rsc, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode); -s32 wilc_add_tx_gtk(struct host_if_drv *hWFIDrv, u8 u8KeyLen, - u8 *pu8TxGtk, u8 u8KeyIdx); s32 wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pu8PmkidInfoArray); s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); -- cgit From 000b5625307dc34fdae9e6f004912a3f6b7195ae Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:02 +0900 Subject: staging: wilc1000: remove wilc_set_start_scan_req declaration This patch deletes wilc_set_start_scan_req declaration. It is not find wilc_set_start_scan_req definition in this driver. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a21ca3768124..1e3f38999821 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,6 @@ s32 wilc_set_pmkid_info(struct wilc_vif *vif, s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); -s32 wilc_set_start_scan_req(struct host_if_drv *hWFIDrv, u8 scanSource); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, -- cgit From 1ab587052b584647ec16e2e021f57cee988213b7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:03 +0900 Subject: staging: wilc1000: fix return type of wilc_set_pmkid_info This patch changes return type of wilc_set_pmkid_info from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8c7752034032..c976c1f202f6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3291,10 +3291,10 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, return result; } -s32 wilc_set_pmkid_info(struct wilc_vif *vif, +int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pu8PmkidInfoArray) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; u32 i; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 1e3f38999821..3dfdc048b7c2 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -321,7 +321,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 index, u32 key_rsc_len, const u8 *key_rsc, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode); -s32 wilc_set_pmkid_info(struct wilc_vif *vif, +int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pu8PmkidInfoArray); s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); -- cgit From 89dec13951e63f8d67ef32b3d6dd6ea782cd8c5b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:04 +0900 Subject: staging: wilc1000: replace u32 with int The data type of variable i changes u32 to int. It is used as array index to copy some data with memcpy function so that it is better to use data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c976c1f202f6..3ad4b0e09d88 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3297,7 +3297,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - u32 i; + int i; if (!hif_drv) { PRINT_ER("driver is null\n"); -- cgit From 16c0cba77369b25b790a4dee1a616ce6d69c92c6 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:05 +0900 Subject: staging: wilc1000: rename pu8PmkidInfoArray in wilc_set_pmkid_info This patch changes pu8PmkidInfoArray to pmkid to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3ad4b0e09d88..485318fcdb05 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3292,7 +3292,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, } int wilc_set_pmkid_info(struct wilc_vif *vif, - struct host_if_pmkid_attr *pu8PmkidInfoArray) + struct host_if_pmkid_attr *pmkid) { int result = 0; struct host_if_msg msg; @@ -3311,11 +3311,11 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, msg.body.key_info.action = ADDKEY; msg.vif = vif; - for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) { + for (i = 0; i < pmkid->numpmkid; i++) { memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].bssid, - &pu8PmkidInfoArray->pmkidlist[i].bssid, ETH_ALEN); + &pmkid->pmkidlist[i].bssid, ETH_ALEN); memcpy(msg.body.key_info.attr.pmkid.pmkidlist[i].pmkid, - &pu8PmkidInfoArray->pmkidlist[i].pmkid, PMKID_LEN); + &pmkid->pmkidlist[i].pmkid, PMKID_LEN); } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3dfdc048b7c2..675a4e13a3ba 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -322,7 +322,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, const u8 *rx_mic, const u8 *tx_mic, u8 mode, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, - struct host_if_pmkid_attr *pu8PmkidInfoArray); + struct host_if_pmkid_attr *pmkid); s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); -- cgit From dcb15a0810749865068784fae9f1e3d6c89240be Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:06 +0900 Subject: staging: wilc1000: fix return type of wilc_get_mac_address This patch changes return type of wilc_get_mac_address from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 485318fcdb05..affd1e656f7f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3325,9 +3325,9 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, return result; } -s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) { - s32 result = 0; + int result = 0; struct host_if_msg msg; memset(&msg, 0, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 675a4e13a3ba..6be4b14950cf 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -323,7 +323,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); -s32 wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, -- cgit From 1eabfe3fe7107feef75dbb2f4afa9aee7eb64960 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:07 +0900 Subject: staging: wilc1000: rename pu8MacAddress in wilc_get_mac_address This patch changes pu8MacAddress to mac_addr to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index affd1e656f7f..613c5a2d403b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3325,7 +3325,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, return result; } -int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) { int result = 0; struct host_if_msg msg; @@ -3333,7 +3333,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_GET_MAC_ADDRESS; - msg.body.get_mac_info.mac_addr = pu8MacAddress; + msg.body.get_mac_info.mac_addr = mac_addr; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6be4b14950cf..76f90cdaa496 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -323,7 +323,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, u8 cipher_mode); int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); -int wilc_get_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, -- cgit From 0b477624906983df8c0bd705020982c956db1e57 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:08 +0900 Subject: staging: wilc1000: fix return type of wilc_set_mac_address This patch changes return type of wilc_set_mac_address from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 613c5a2d403b..ed6f93289410 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3346,9 +3346,9 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) { - s32 result = 0; + int result = 0; struct host_if_msg msg; PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 76f90cdaa496..337965f96927 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -324,7 +324,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -s32 wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, -- cgit From f95f480c51125bbfa56ea2dc5383859dc43b0a15 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 22 Dec 2015 09:49:09 +0900 Subject: staging: wilc1000: rename pu8MacAddress in wilc_set_mac_address This patch changes pu8MacAddress to mac_addr to avoid camelcase. Signed-off-by: Chaehyun Lim 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 ed6f93289410..78d26ee016aa 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3346,16 +3346,16 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress) +int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) { int result = 0; struct host_if_msg msg; - PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]); + PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", mac_addr[0], mac_addr[1], mac_addr[2]); memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_SET_MAC_ADDRESS; - memcpy(msg.body.set_mac_info.mac_addr, pu8MacAddress, ETH_ALEN); + memcpy(msg.body.set_mac_info.mac_addr, mac_addr, ETH_ALEN); msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 337965f96927..13d253c6a5fd 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -324,7 +324,7 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_set_mac_address(struct wilc_vif *vif, u8 *pu8MacAddress); +int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, -- cgit From e663900aed9b90270e3452d500426ca0ae5762ed Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 24 Dec 2015 15:02:51 +0900 Subject: staging: wilc1000: fix always return 0 error This patch fixes a bug that return always 0 so it fails every time. Fixes: c1af9db78950 ("staging: wilc1000: call linux_sdio_init instead of io_init") Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index e961b5004902..464d27df829a 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -614,8 +614,6 @@ static int sdio_init(struct wilc *wilc) if (!wilc_sdio_init()) { dev_err(&func->dev, "Failed io init bus...\n"); return 0; - } else { - return 0; } /** -- cgit From 43d1ca528436bc3f629edd8b622b39fb1611d5f7 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 24 Dec 2015 15:02:52 +0900 Subject: staging: wilc1000: remove wilc_sdio_init wilc_sdio_init return always 1, which is needless. Remove it and it's related codes also. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 464d27df829a..caad876a8249 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -185,11 +185,6 @@ static void wilc_sdio_disable_interrupt(struct wilc *dev) dev_info(&func->dev, "wilc_sdio_disable_interrupt OUT\n"); } -static int wilc_sdio_init(void) -{ - return 1; -} - /******************************************** * * Function 0 @@ -611,11 +606,6 @@ static int sdio_init(struct wilc *wilc) g_sdio.irq_gpio = (wilc->dev_irq_num); - if (!wilc_sdio_init()) { - dev_err(&func->dev, "Failed io init bus...\n"); - return 0; - } - /** * function 0 csa enable **/ -- cgit From a045618e01ac486528f848841a3b31b9b7582c0c Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Tue, 22 Dec 2015 11:44:43 +0000 Subject: staging: wilc1000: replace numerical constant with predefined MACRO Replace the pre-defined macro signifying the ethernet protocol type defined in the kernel headers instead of the numerical constant Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 83af51bb83e8..0b62cc5df488 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -248,7 +248,7 @@ static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) eth_hdr_ptr = &buffer[0]; h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); - if (h_proto == 0x0800) { + if (h_proto == ETH_P_IP) { u8 *ip_hdr_ptr; u8 protocol; -- cgit From 30205892ecaa6a151e85bdd8e1bf9f7ee7a0fc17 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:19 +0900 Subject: staging: wilc1000: fix return type of wilc_flush_join_req This patch changes return type of wilc_flush_join_req from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78d26ee016aa..78d58e092d20 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3432,9 +3432,9 @@ s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, return result; } -s32 wilc_flush_join_req(struct wilc_vif *vif) +int wilc_flush_join_req(struct wilc_vif *vif) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 13d253c6a5fd..af8582456cd6 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -331,7 +331,7 @@ s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -s32 wilc_flush_join_req(struct wilc_vif *vif); +int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); -- cgit From 0a285b2770f022987233c98e9bb44af923df1306 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:20 +0900 Subject: staging: wilc1000: fix return type of wilc_set_join_req This patch changes return type of wilc_set_join_req from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 78d58e092d20..b24697baa159 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3365,13 +3365,13 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index af8582456cd6..eaf3a1002e79 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); -s32 wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, -- cgit From 16a537ca78d7d1a077eb53ccb2ba98eaa7132ae8 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:21 +0900 Subject: staging: wilc1000: rename pu8bssid in wilc_set_join_req This patch renames pu8bssid to bssid to remove pu8 prefix. There is no need to add this prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim 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 b24697baa159..bb4b61284ef2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3365,7 +3365,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, @@ -3397,9 +3397,9 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, msg.body.con_info.params = pJoinParams; msg.vif = vif; - if (pu8bssid) { + if (bssid) { msg.body.con_info.bssid = kmalloc(6, GFP_KERNEL); - memcpy(msg.body.con_info.bssid, pu8bssid, 6); + memcpy(msg.body.con_info.bssid, bssid, 6); } if (pu8ssid) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index eaf3a1002e79..0e40c8f96e00 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); -int wilc_set_join_req(struct wilc_vif *vif, u8 *pu8bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, -- cgit From f2cb5f3f1b47f3642cf9367d877d785973c0c267 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:22 +0900 Subject: staging: wilc1000: rename pu8ssid in wilc_set_join_req This patch renames pu8ssid to ssid to remove pu8 prefix. There is no need to add this prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim 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 bb4b61284ef2..a146d4fa2b3f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3365,7 +3365,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, @@ -3402,10 +3402,10 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, memcpy(msg.body.con_info.bssid, bssid, 6); } - if (pu8ssid) { + if (ssid) { msg.body.con_info.ssid_len = ssidLen; msg.body.con_info.ssid = kmalloc(ssidLen, GFP_KERNEL); - memcpy(msg.body.con_info.ssid, pu8ssid, ssidLen); + memcpy(msg.body.con_info.ssid, ssid, ssidLen); } if (pu8IEs) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 0e40c8f96e00..5d6f8079c7cc 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -326,7 +326,7 @@ int wilc_set_pmkid_info(struct wilc_vif *vif, int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); -int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *pu8ssid, +int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, -- cgit From dee39b1b1b0553903f7994a73660d254a195713c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:23 +0900 Subject: staging: wilc1000: rename ssidLen in wilc_set_join_req This patch renames ssidLen to ssid_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a146d4fa2b3f..4730b60fe373 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3366,7 +3366,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) @@ -3403,9 +3403,9 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, } if (ssid) { - msg.body.con_info.ssid_len = ssidLen; - msg.body.con_info.ssid = kmalloc(ssidLen, GFP_KERNEL); - memcpy(msg.body.con_info.ssid, ssid, ssidLen); + msg.body.con_info.ssid_len = ssid_len; + msg.body.con_info.ssid = kmalloc(ssid_len, GFP_KERNEL); + memcpy(msg.body.con_info.ssid, ssid, ssid_len); } if (pu8IEs) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5d6f8079c7cc..4c4674ba791b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -327,7 +327,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssidLen, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -- cgit From 88c9421ad21172f5ed9e53349e4713613c7798f7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:24 +0900 Subject: staging: wilc1000: rename pu8IEs in wilc_set_join_req This patch renames pu8IEs to ies to avoid camelcase. Signed-off-by: Chaehyun Lim 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 4730b60fe373..bf1597c92f4b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3366,7 +3366,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) @@ -3408,10 +3408,10 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, memcpy(msg.body.con_info.ssid, ssid, ssid_len); } - if (pu8IEs) { + if (ies) { msg.body.con_info.ies_len = IEsLen; msg.body.con_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.con_info.ies, pu8IEs, IEsLen); + memcpy(msg.body.con_info.ies, ies, IEsLen); } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4c4674ba791b..44929a61608e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -327,7 +327,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *pu8IEs, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t IEsLen, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -- cgit From 8c38d960a416b99b05a905b304582e688a707f1a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:25 +0900 Subject: staging: wilc1000: rename IEsLen in wilc_set_join_req This patch renames IEsLen to ies_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index bf1597c92f4b..4421babeea0e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3366,7 +3366,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) } int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *ies, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) @@ -3409,9 +3409,9 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, } if (ies) { - msg.body.con_info.ies_len = IEsLen; - msg.body.con_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.con_info.ies, ies, IEsLen); + msg.body.con_info.ies_len = ies_len; + msg.body.con_info.ies = kmalloc(ies_len, GFP_KERNEL); + memcpy(msg.body.con_info.ies, ies, ies_len); } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 44929a61608e..5edb178f6f1d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -327,7 +327,7 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, - size_t ssid_len, const u8 *ies, size_t IEsLen, + size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result pfConnectResult, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); -- cgit From 81c23a7ebca2a4b9f1b35e6c1d7894d951eb7f56 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:26 +0900 Subject: staging: wilc1000: rename pfConnectResult in wilc_set_join_req This patch renames pfConnectResult to connect_result to avoid camelcase. Signed-off-by: Chaehyun Lim 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 4421babeea0e..d691c95fd8bb 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3367,7 +3367,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result pfConnectResult, void *pvUserArg, + wilc_connect_result connect_result, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { @@ -3375,7 +3375,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv || !pfConnectResult) { + if (!hif_drv || !connect_result) { PRINT_ER("Driver is null\n"); return -EFAULT; } @@ -3392,7 +3392,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.security = u8security; msg.body.con_info.auth_type = tenuAuth_type; msg.body.con_info.ch = u8channel; - msg.body.con_info.result = pfConnectResult; + msg.body.con_info.result = connect_result; msg.body.con_info.arg = pvUserArg; msg.body.con_info.params = pJoinParams; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5edb178f6f1d..b42613255a34 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -328,7 +328,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result pfConnectResult, void *pvUserArg, + wilc_connect_result connect_result, void *pvUserArg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); -- cgit From 2ef29833e1c45948b48b5d4c77da70e3ccd90ab1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:27 +0900 Subject: staging: wilc1000: rename pvUserArg in wilc_set_join_req This patch renames pvUserArg to user_arg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d691c95fd8bb..11903593ad82 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3367,7 +3367,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result connect_result, void *pvUserArg, + wilc_connect_result connect_result, void *user_arg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { @@ -3393,7 +3393,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.auth_type = tenuAuth_type; msg.body.con_info.ch = u8channel; msg.body.con_info.result = connect_result; - msg.body.con_info.arg = pvUserArg; + msg.body.con_info.arg = user_arg; msg.body.con_info.params = pJoinParams; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b42613255a34..9e66d5eb229d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -328,7 +328,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, - wilc_connect_result connect_result, void *pvUserArg, + wilc_connect_result connect_result, void *user_arg, u8 u8security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); -- cgit From e0c54a883f816b7d9e72cf694329969178615687 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:28 +0900 Subject: staging: wilc1000: rename u8security in wilc_set_join_req This patch renames u8security to security to remove u8 prefix. There is no need to add prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 11903593ad82..64189faf3443 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3368,7 +3368,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 u8security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams) { int result = 0; @@ -3389,7 +3389,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.id = HOST_IF_MSG_CONNECT; - msg.body.con_info.security = u8security; + msg.body.con_info.security = security; msg.body.con_info.auth_type = tenuAuth_type; msg.body.con_info.ch = u8channel; msg.body.con_info.result = connect_result; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9e66d5eb229d..bb08e7fc7d6c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -329,7 +329,7 @@ int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 u8security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE tenuAuth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); -- cgit From 12a3b8bc26ae1f81297dfdb80775191d03deca1d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:29 +0900 Subject: staging: wilc1000: rename tenuAuth_type in wilc_set_join_req This patch renames tenuAuth_type to auth_type to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 64189faf3443..d3c595e57d2f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3368,7 +3368,7 @@ int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE auth_type, u8 u8channel, void *pJoinParams) { int result = 0; @@ -3390,7 +3390,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.id = HOST_IF_MSG_CONNECT; msg.body.con_info.security = security; - msg.body.con_info.auth_type = tenuAuth_type; + msg.body.con_info.auth_type = auth_type; msg.body.con_info.ch = u8channel; msg.body.con_info.result = connect_result; msg.body.con_info.arg = user_arg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index bb08e7fc7d6c..3d5fea7c671b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -329,7 +329,7 @@ int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, - u8 security, enum AUTHTYPE tenuAuth_type, + u8 security, enum AUTHTYPE auth_type, u8 u8channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); -- cgit From 0ea1ece02d7d7d6ba7f362d749700fc537dbf349 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:30 +0900 Subject: staging: wilc1000: rename u8channel in wilc_set_join_req This patch renames u8channel to channel to remove u8 prefix. There is no need to add prefix in order to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d3c595e57d2f..66abfa74153b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3369,7 +3369,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 u8channel, void *pJoinParams) + u8 channel, void *pJoinParams) { int result = 0; struct host_if_msg msg; @@ -3391,7 +3391,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.security = security; msg.body.con_info.auth_type = auth_type; - msg.body.con_info.ch = u8channel; + msg.body.con_info.ch = channel; msg.body.con_info.result = connect_result; msg.body.con_info.arg = user_arg; msg.body.con_info.params = pJoinParams; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3d5fea7c671b..b12c04fdf69c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -330,7 +330,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 u8channel, void *pJoinParams); + u8 channel, void *pJoinParams); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -- cgit From f382b376064fd513aa83f9ddc47920d2ac6abf59 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:31 +0900 Subject: staging: wilc1000: rename pJoinParams in wilc_set_join_req This patch renames pJoinParams to join_params to avoid camelcase. Signed-off-by: Chaehyun Lim 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 66abfa74153b..79f3d9f2e7cd 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3369,7 +3369,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 channel, void *pJoinParams) + u8 channel, void *join_params) { int result = 0; struct host_if_msg msg; @@ -3380,7 +3380,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return -EFAULT; } - if (!pJoinParams) { + if (!join_params) { PRINT_ER("Unable to Join - JoinParams is NULL\n"); return -EFAULT; } @@ -3394,7 +3394,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.body.con_info.ch = channel; msg.body.con_info.result = connect_result; msg.body.con_info.arg = user_arg; - msg.body.con_info.params = pJoinParams; + msg.body.con_info.params = join_params; msg.vif = vif; if (bssid) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b12c04fdf69c..698d1b6bc330 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -330,7 +330,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, - u8 channel, void *pJoinParams); + u8 channel, void *join_params); int wilc_flush_join_req(struct wilc_vif *vif); s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -- cgit From 11623136ef54ca945d64d3f8a1d1f3763ca13563 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:32 +0900 Subject: staging: wilc1000: use kmemdup instead of kmalloc and memcpy This patch changes kmalloc/memcpy to kmemdup. It is also added error checking to return -ENOMEM if kmemdup is failed. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 79f3d9f2e7cd..65189422432f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3398,20 +3398,23 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, msg.vif = vif; if (bssid) { - msg.body.con_info.bssid = kmalloc(6, GFP_KERNEL); - memcpy(msg.body.con_info.bssid, bssid, 6); + msg.body.con_info.bssid = kmemdup(bssid, 6, GFP_KERNEL); + if (!msg.body.con_info.bssid) + return -ENOMEM; } if (ssid) { msg.body.con_info.ssid_len = ssid_len; - msg.body.con_info.ssid = kmalloc(ssid_len, GFP_KERNEL); - memcpy(msg.body.con_info.ssid, ssid, ssid_len); + msg.body.con_info.ssid = kmemdup(ssid, ssid_len, GFP_KERNEL); + if (!msg.body.con_info.ssid) + return -ENOMEM; } if (ies) { msg.body.con_info.ies_len = ies_len; - msg.body.con_info.ies = kmalloc(ies_len, GFP_KERNEL); - memcpy(msg.body.con_info.ies, ies, ies_len); + msg.body.con_info.ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!msg.body.con_info.ies) + return -ENOMEM; } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; -- cgit From 5350251a9bba780fe1a92aebb71ecd7c37fa2e2f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:33 +0900 Subject: staging: wilc1000: fix return type of wilc_disconnect This patch changes return type of wilc_disconnect from s32 to int. The result variable gets return value from wilc_disconnect that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 65189422432f..5ddf78df8a8a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3461,9 +3461,9 @@ int wilc_flush_join_req(struct wilc_vif *vif) return result; } -s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode) +int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 698d1b6bc330..e8c556a0c4aa 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -332,7 +332,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, u8 security, enum AUTHTYPE auth_type, u8 channel, void *join_params); int wilc_flush_join_req(struct wilc_vif *vif); -s32 wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); +int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, -- cgit From 9f723fdeb84e5c4f061bba21348e280c3a73d58d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:34 +0900 Subject: staging: wilc1000: rename u16ReasonCode in wilc_disconnect This patch renames u16ReasonCode to reason_code to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5ddf78df8a8a..6e5bccc8bc3d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3461,7 +3461,7 @@ int wilc_flush_join_req(struct wilc_vif *vif) return result; } -int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode) +int wilc_disconnect(struct wilc_vif *vif, u16 reason_code) { int result = 0; struct host_if_msg msg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index e8c556a0c4aa..fa5d2925e47a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -332,7 +332,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, u8 security, enum AUTHTYPE auth_type, u8 channel, void *join_params); int wilc_flush_join_req(struct wilc_vif *vif); -int wilc_disconnect(struct wilc_vif *vif, u16 u16ReasonCode); +int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, -- cgit From a5f9943cc01e10a118c85845d8638b5f1331827e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:35 +0900 Subject: staging: wilc1000: remove wilc_free_join_params wilc_free_join_params call kfree. There is no need to use wrapper function, so use kfree directly. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 -------- drivers/staging/wilc1000/host_interface.h | 3 --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6e5bccc8bc3d..724b4bd75ac0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4609,14 +4609,6 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -void wilc_free_join_params(void *pJoinParams) -{ - if ((struct bss_param *)pJoinParams) - kfree((struct bss_param *)pJoinParams); - else - PRINT_ER("Unable to FREE null pointer\n"); -} - s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) { s32 result = 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index fa5d2925e47a..7ac85f27217e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,9 +365,6 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); - -void wilc_free_join_params(void *pJoinParams); - s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 53fb2d4bb0bd..be5704bfc382 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -196,7 +196,7 @@ static void clear_shadow_scan(void) last_scanned_shadow[last_scanned_cnt].pu8IEs = NULL; } - wilc_free_join_params(last_scanned_shadow[i].pJoinParams); + kfree(last_scanned_shadow[i].pJoinParams); last_scanned_shadow[i].pJoinParams = NULL; } last_scanned_cnt = 0; @@ -282,7 +282,7 @@ static void remove_network_from_shadow(unsigned long arg) kfree(last_scanned_shadow[i].pu8IEs); last_scanned_shadow[i].pu8IEs = NULL; - wilc_free_join_params(last_scanned_shadow[i].pJoinParams); + kfree(last_scanned_shadow[i].pJoinParams); for (j = i; (j < last_scanned_cnt - 1); j++) last_scanned_shadow[j] = last_scanned_shadow[j + 1]; @@ -376,7 +376,7 @@ static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, last_scanned_shadow[ap_index].u32TimeRcvdInScanCached = jiffies; last_scanned_shadow[ap_index].u8Found = 1; if (ap_found != -1) - wilc_free_join_params(last_scanned_shadow[ap_index].pJoinParams); + kfree(last_scanned_shadow[ap_index].pJoinParams); last_scanned_shadow[ap_index].pJoinParams = pJoinParams; } -- cgit From e16aed64cfbd15f358edc89f19e9da4a6fae4935 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:36 +0900 Subject: staging: wilc1000: fix return type of wilc_get_rssi This patch changes return type of wilc_get_rssi from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 724b4bd75ac0..c059e6d915eb 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3628,9 +3628,9 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, return result; } -s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) +int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7ac85f27217e..51ec72c01da7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -334,7 +334,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -s32 wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); +int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, -- cgit From 652bb5e888bca319c3d69e5473a0823a739592b5 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:37 +0900 Subject: staging: wilc1000: rename ps8Rssi in wilc_get_rssi This patch renames ps8Rssi to rssi_level to avoid camelcase. Signed-off-by: Chaehyun Lim 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 c059e6d915eb..e1e123b7d9a8 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3628,7 +3628,7 @@ s32 wilc_get_inactive_time(struct wilc_vif *vif, const u8 *mac, return result; } -int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) +int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) { int result = 0; struct host_if_msg msg; @@ -3646,12 +3646,12 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi) down(&hif_drv->sem_get_rssi); - if (!ps8Rssi) { + if (!rssi_level) { PRINT_ER("RSS pointer value is null"); return -EFAULT; } - *ps8Rssi = rssi; + *rssi_level = rssi; return result; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 51ec72c01da7..4506e0b66935 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -334,7 +334,7 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); -int wilc_get_rssi(struct wilc_vif *vif, s8 *ps8Rssi); +int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, -- cgit From cd163d32d1db882e01e7143be8ea7f7a6f61c108 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:38 +0900 Subject: staging: wilc1000: fix return type of wilc_get_statistics This patch changes return type of wilc_get_statistics from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e1e123b7d9a8..732ea9660d13 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3656,9 +3656,9 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return result; } -s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics) +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics) { - s32 result = 0; + int result = 0; struct host_if_msg msg; memset(&msg, 0, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4506e0b66935..c64dc13deae7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,7 +365,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -s32 wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); -- cgit From f70b25ff32baf75fc460210fa4ac75626a465396 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 24 Dec 2015 16:52:39 +0900 Subject: staging: wilc1000: rename pstrStatistics in wilc_get_statistics This patch renames pstrStatistics to stats to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 732ea9660d13..5113d3d5c5dc 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3656,14 +3656,14 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level) return result; } -int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics) +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) { int result = 0; struct host_if_msg msg; memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_GET_STATISTICS; - msg.body.data = (char *)pstrStatistics; + msg.body.data = (char *)stats; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c64dc13deae7..b8b235d72412 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,7 +365,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *pstrStatistics); +int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); -- cgit From de61db9e07e38f872541b02ee4f52965688d7e7b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:25 +0900 Subject: staging: wilc1000: fix return type of wilc_frame_register This patch changes return type of wilc_frame_register from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5113d3d5c5dc..d9e4e11f04d9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4123,9 +4123,9 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) return result; } -s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) +int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b8b235d72412..5ecc978dd6aa 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -362,7 +362,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); -s32 wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); +int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -- cgit From 2a8432ff3959ed483d3f55e968b746879676815d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:26 +0900 Subject: staging: wilc1000: rename u16FrameType in wilc_frame_register This patch renames u16FrameType to frame_type to avoid camelcase. Signed-off-by: Chaehyun Lim 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 d9e4e11f04d9..c3e59d8b18be 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4123,7 +4123,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) return result; } -int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg) { int result = 0; struct host_if_msg msg; @@ -4137,7 +4137,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_REGISTER_FRAME; - switch (u16FrameType) { + switch (frame_type) { case ACTION: PRINT_D(HOSTINF_DBG, "ACTION\n"); msg.body.reg_frame.reg_id = ACTION_FRM_IDX; @@ -4152,7 +4152,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg) PRINT_D(HOSTINF_DBG, "Not valid frame type\n"); break; } - msg.body.reg_frame.frame_type = u16FrameType; + msg.body.reg_frame.frame_type = frame_type; msg.body.reg_frame.reg = bReg; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5ecc978dd6aa..efb657bd3cef 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -362,7 +362,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); -int wilc_frame_register(struct wilc_vif *vif, u16 u16FrameType, bool bReg); +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -- cgit From 8859fc2898c5e6d40b29e4cbabdae4f4e2902f91 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:27 +0900 Subject: staging: wilc1000: rename bReg in wilc_frame_register This patch renames bReg to reg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c3e59d8b18be..9b72519713b9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4123,7 +4123,7 @@ s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) return result; } -int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg) +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) { int result = 0; struct host_if_msg msg; @@ -4153,7 +4153,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg) break; } msg.body.reg_frame.frame_type = frame_type; - msg.body.reg_frame.reg = bReg; + msg.body.reg_frame.reg = reg; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index efb657bd3cef..b43e0a1ff4e5 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -362,7 +362,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); -int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool bReg); +int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); -- cgit From 5ca581ef48d8e3188e580e0c246208c47ceb0ca7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:28 +0900 Subject: staging: wilc1000: fix return type of wilc_listen_state_expired This patch changes return type of wilc_listen_state_expired from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 9b72519713b9..4db211b2c9f3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4098,9 +4098,9 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, return result; } -s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) +int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b43e0a1ff4e5..fbc1ee1fccf4 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -361,7 +361,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); -s32 wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); +int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -- cgit From 6b0f7cdd893b480ed03ff60f1c122b1aa063205a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:29 +0900 Subject: staging: wilc1000: rename u32SessionID in wilc_listen_state_expired This patch renames u32SessionID to session_id to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4db211b2c9f3..3a9a967390f5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4098,7 +4098,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, return result; } -int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) +int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id) { int result = 0; struct host_if_msg msg; @@ -4114,7 +4114,7 @@ int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_LISTEN_TIMER_FIRED; msg.vif = vif; - msg.body.remain_on_ch.id = u32SessionID; + msg.body.remain_on_ch.id = session_id; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index fbc1ee1fccf4..47c664e15194 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -361,7 +361,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); -int wilc_listen_state_expired(struct wilc_vif *vif, u32 u32SessionID); +int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); -- cgit From 5d48f12c4c520e36833ab2c5189393113a65e2c6 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:30 +0900 Subject: staging: wilc1000: fix return type of wilc_set_power_mgmt This patch changes return type of wilc_set_power_mgmt from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3a9a967390f5..8b1e535d7830 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4393,9 +4393,9 @@ s32 wilc_edit_station(struct wilc_vif *vif, return result; } -s32 wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 47c664e15194..fb9c0ead48ea 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -351,7 +351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); -s32 wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout); s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); -- cgit From dbaa524e231630033a92d86521ececf4a0a1f019 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:31 +0900 Subject: staging: wilc1000: rename bIsEnabled in wilc_set_power_mgmt This patch renames bIsEnabled to enabled to avoid camelcase. Signed-off-by: Chaehyun Lim 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 8b1e535d7830..3ed8275c30ea 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4393,14 +4393,14 @@ s32 wilc_edit_station(struct wilc_vif *vif, return result; } -int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout) { int result = 0; struct host_if_msg msg; struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", bIsEnabled); + PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", enabled); if (!hif_drv) { PRINT_ER("driver is null\n"); @@ -4414,7 +4414,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout) msg.id = HOST_IF_MSG_POWER_MGMT; msg.vif = vif; - pstrPowerMgmtParam->enabled = bIsEnabled; + pstrPowerMgmtParam->enabled = enabled; pstrPowerMgmtParam->timeout = u32Timeout; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index fb9c0ead48ea..89765b89e429 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -351,7 +351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); -int wilc_set_power_mgmt(struct wilc_vif *vif, bool bIsEnabled, u32 u32Timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout); s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); -- cgit From ecd275000a8e1c80593255b327ab14989eb18c4c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:32 +0900 Subject: staging: wilc1000: rename u32Timeout in wilc_set_power_mgmt This patch renames u32Timeout to timeout to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3ed8275c30ea..dc1773deafe5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4393,7 +4393,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, return result; } -int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout) +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { int result = 0; struct host_if_msg msg; @@ -4415,7 +4415,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout) msg.vif = vif; pstrPowerMgmtParam->enabled = enabled; - pstrPowerMgmtParam->timeout = u32Timeout; + pstrPowerMgmtParam->timeout = timeout; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 89765b89e429..7b12425efeca 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -351,7 +351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); -int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 u32Timeout); +int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); -- cgit From 568640e4f1f00a0092559db6fbc760ae42a559ca Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:33 +0900 Subject: staging: wilc1000: rename pstrPowerMgmtParam in wilc_set_power_mgmt This patch renames pstrPowerMgmtParam to pwr_mgmt_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index dc1773deafe5..83ac21a3c8d6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4397,7 +4397,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) { int result = 0; struct host_if_msg msg; - struct power_mgmt_param *pstrPowerMgmtParam = &msg.body.pwr_mgmt_info; + struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", enabled); @@ -4414,8 +4414,8 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) msg.id = HOST_IF_MSG_POWER_MGMT; msg.vif = vif; - pstrPowerMgmtParam->enabled = enabled; - pstrPowerMgmtParam->timeout = timeout; + pwr_mgmt_info->enabled = enabled; + pwr_mgmt_info->timeout = timeout; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit From 14d9526f69d2b283e6326dce2c4c21e529a1e23c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:34 +0900 Subject: staging: wilc1000: fix return type of wilc_setup_multicast_filter This patch changes return type of wilc_setup_multicast_filter from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 83ac21a3c8d6..8e8e70ed2c82 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4423,10 +4423,10 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return result; } -s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct set_multicast *pstrMulticastFilterParam = &msg.body.multicast_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7b12425efeca..52032be6a81d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -352,7 +352,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); -s32 wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -- cgit From b80c0943022915b371911707adf619ccc6d3365d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:35 +0900 Subject: staging: wilc1000: rename bIsEnabled in wilc_setup_multicast_filter This patch renames bIsEnabled to enabled to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8e8e70ed2c82..a32e930e7c53 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4423,7 +4423,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return result; } -int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 u32count) { int result = 0; @@ -4443,7 +4443,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; msg.vif = vif; - pstrMulticastFilterParam->enabled = bIsEnabled; + pstrMulticastFilterParam->enabled = enabled; pstrMulticastFilterParam->cnt = u32count; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 52032be6a81d..9abdd3f49946 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -352,7 +352,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); -int wilc_setup_multicast_filter(struct wilc_vif *vif, bool bIsEnabled, +int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 u32count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -- cgit From 2dff2d4228f6c1b14dc7ea169c891783e63dc743 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:36 +0900 Subject: staging: wilc1000: rename u32count in wilc_setup_multicast_filter This patch renames u32count to count to remove u32 prefix. There is no need to use this prefix to show data type of this argument. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a32e930e7c53..489ab290af24 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4424,7 +4424,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) } int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, - u32 u32count) + u32 count) { int result = 0; struct host_if_msg msg; @@ -4444,7 +4444,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, msg.vif = vif; pstrMulticastFilterParam->enabled = enabled; - pstrMulticastFilterParam->cnt = u32count; + pstrMulticastFilterParam->cnt = count; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9abdd3f49946..5c271b180ca3 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -353,7 +353,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, - u32 u32count); + u32 count); s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, -- cgit From 40ecd38a6e1ab30ef4fe843ca9e77754cde41287 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:37 +0900 Subject: staging: wilc1000: rename pstrMulticastFilterParam in wilc_setup_multicast_filter This patch renames pstrMulticastFilterParam to multicast_filter_param to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 489ab290af24..aeb327158c58 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4428,7 +4428,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, { int result = 0; struct host_if_msg msg; - struct set_multicast *pstrMulticastFilterParam = &msg.body.multicast_info; + struct set_multicast *multicast_filter_param = &msg.body.multicast_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4443,8 +4443,8 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; msg.vif = vif; - pstrMulticastFilterParam->enabled = enabled; - pstrMulticastFilterParam->cnt = count; + multicast_filter_param->enabled = enabled; + multicast_filter_param->cnt = count; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit From 3d2a0bf719defc6087cf526af1e2ba98ae5e3bae Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:38 +0900 Subject: staging: wilc1000: fix return type of wilc_setup_ipaddress This patch changes return type of wilc_setup_ipaddress from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index aeb327158c58..dacadc91aca7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4638,9 +4638,9 @@ s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) return result; } -s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5c271b180ca3..d36a9f5c5ad3 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -354,7 +354,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); -s32 wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, -- cgit From 6964f086e5a8b72d7d911f322738a27621f8533d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:39 +0900 Subject: staging: wilc1000: rename u16ipadd in wilc_setup_ipaddress This patch renames u16ipadd to ip_addr to remove u16 prefix. There is no need to use prefix to show data type of this argument. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index dacadc91aca7..0d41657a4624 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4638,7 +4638,7 @@ s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) return result; } -int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { int result = 0; struct host_if_msg msg; @@ -4655,7 +4655,7 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) msg.id = HOST_IF_MSG_SET_IPADDRESS; - msg.body.ip_info.ip_addr = u16ipadd; + msg.body.ip_info.ip_addr = ip_addr; msg.vif = vif; msg.body.ip_info.idx = idx; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index d36a9f5c5ad3..f90a530e24e6 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -354,7 +354,7 @@ s32 wilc_edit_station(struct wilc_vif *vif, int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); -int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); +int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, -- cgit From 0fd6fa32988413fff37c9c38940737dc2831a11f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:40 +0900 Subject: staging: wilc1000: remove return statement This patch removes return statement that is always returned 0. wilc_setup_ipaddress can not run to the end due to return statement. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0d41657a4624..90fdbddaf9cd 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4644,8 +4644,6 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - return 0; - if (!hif_drv) { PRINT_ER("driver is null\n"); return -EFAULT; -- cgit From cb8f4e0e6d8bc1d37a50578bf0a84dd5567afa08 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:41 +0900 Subject: staging: wilc1000: fix return type of host_int_get_ipaddress This patch changes return type of host_int_get_ipaddress from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 90fdbddaf9cd..a203647eb27d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -362,7 +362,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static s32 host_int_get_ipaddress(struct wilc_vif *vif, +static int host_int_get_ipaddress(struct wilc_vif *vif, struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx); @@ -4664,11 +4664,11 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } -static s32 host_int_get_ipaddress(struct wilc_vif *vif, +static int host_int_get_ipaddress(struct wilc_vif *vif, struct host_if_drv *hif_drv, u8 *u16ipadd, u8 idx) { - s32 result = 0; + int result = 0; struct host_if_msg msg; if (!hif_drv) { -- cgit From f8813d3aa26993178cc4d62e58eb74427f272c66 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:42 +0900 Subject: staging: wilc1000: remove argument hif_drv in host_int_get_ipaddress This patch removes hif_drv argument of host_int_get_ipaddress. There is no need to pass hif_drv in this function because hif_drv is a member of vif. It is removed struct host_if_drv and use hif_drv of vif. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a203647eb27d..72115ae96de2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -362,16 +362,13 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, - struct host_if_drv *hif_drv, - u8 *u16ipadd, u8 idx); +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { s32 result = 0; struct wid wid; char firmware_ip_addr[4] = {0}; - struct host_if_drv *hif_drv = vif->hif_drv; if (ip_addr[0] < 192) ip_addr[0] = 0; @@ -389,7 +386,7 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - host_int_get_ipaddress(vif, hif_drv, firmware_ip_addr, idx); + host_int_get_ipaddress(vif, firmware_ip_addr, idx); if (result) { PRINT_ER("Failed to set IP address\n"); @@ -4664,12 +4661,11 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, - struct host_if_drv *hif_drv, - u8 *u16ipadd, u8 idx) +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) { int result = 0; struct host_if_msg msg; + struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { PRINT_ER("driver is null\n"); -- cgit From 3b4276d92f8d4f2a0999fb9ea76e98546895a1ba Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:43 +0900 Subject: staging: wilc1000: rename u16ipadd in host_int_get_ipaddress This patch renames u16ipadd to ip_addr to remove u16 prefix. There is no need to use this prefix to show data type of this argument. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 72115ae96de2..c8b4b320df31 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -362,7 +362,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx); +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { @@ -4661,7 +4661,7 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { int result = 0; struct host_if_msg msg; @@ -4676,7 +4676,7 @@ static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *u16ipadd, u8 idx) msg.id = HOST_IF_MSG_GET_IPADDRESS; - msg.body.ip_info.ip_addr = u16ipadd; + msg.body.ip_info.ip_addr = ip_addr; msg.vif = vif; msg.body.ip_info.idx = idx; -- cgit From 4ad878bee170cfa6722af26d39740a3c73614218 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 30 Dec 2015 21:15:44 +0900 Subject: staging: wilc1000: move static declaration of host_int_get_ipaddress This patch moves static function declaration to front part of host_interface.c file. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c8b4b320df31..5a97a9ddb4e3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -263,6 +263,7 @@ static struct wilc_vif *join_req_vif; #define FLUSHED_BYTE_POS 79 static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo); +static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); /* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as * special purpose in wilc device, so we add 1 to the index to starts from 1. @@ -362,8 +363,6 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, return result; } -static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); - static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { s32 result = 0; -- cgit From fb6e06806b31867e31e095303688cc5dd7503f4a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:33 +0900 Subject: staging: wilc1000: rename u32duration in struct remain_ch The patch renames u32duration to duration that is a member of struct remain_ch. The prefix u32 shows data type of its member, but there is no need to use u32 prefix to represent data type. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5a97a9ddb4e3..39fa5a3c6021 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -2558,7 +2558,7 @@ ERRORHANDLER: hif_drv->remain_on_ch_timer.data = (unsigned long)vif; mod_timer(&hif_drv->remain_on_ch_timer, jiffies + - msecs_to_jiffies(pstrHostIfRemainOnChan->u32duration)); + msecs_to_jiffies(pstrHostIfRemainOnChan->duration)); if (hif_drv->remain_on_ch.ready) hif_drv->remain_on_ch.ready(hif_drv->remain_on_ch.arg); @@ -4083,7 +4083,7 @@ s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, msg.body.remain_on_ch.expired = RemainOnChanExpired; msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; - msg.body.remain_on_ch.u32duration = u32duration; + msg.body.remain_on_ch.duration = u32duration; msg.body.remain_on_ch.id = u32SessionID; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f90a530e24e6..a2f428f1db18 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -240,7 +240,7 @@ struct ba_session_info { struct remain_ch { u16 ch; - u32 u32duration; + u32 duration; wilc_remain_on_chan_expired expired; wilc_remain_on_chan_ready ready; void *arg; -- cgit From 6d6bc4003b0a0930b8be8d69d5fc5ea4174577b7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:34 +0900 Subject: staging: wilc1000: fix return type of wilc_remain_on_channel This patch changes return type of wilc_remain_on_channel from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 39fa5a3c6021..30b4f3056433 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4061,13 +4061,13 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, return; } -s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a2f428f1db18..e28f46266cbe 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -356,7 +356,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -s32 wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, -- cgit From 6f7584be30f03f13704c7dd928f816110a2aa170 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:35 +0900 Subject: staging: wilc1000: rename u32SessionID in wilc_remain_on_channel This patch renames u32SessionID to session_id to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 30b4f3056433..6ea907e3b30c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4061,7 +4061,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, return; } -int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, @@ -4084,7 +4084,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; msg.body.remain_on_ch.duration = u32duration; - msg.body.remain_on_ch.id = u32SessionID; + msg.body.remain_on_ch.id = session_id; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index e28f46266cbe..c935e49d8f8f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -356,7 +356,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); -int wilc_remain_on_channel(struct wilc_vif *vif, u32 u32SessionID, +int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 u32duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, -- cgit From d44cd45ee1a8984c017f54a4d6afc484bbd152af Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:36 +0900 Subject: staging: wilc1000: rename u32duration in wilc_remain_on_channel This patch renames u32duration to duration to remove u32 prefix. There is no need u32 prefix to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6ea907e3b30c..116942df424a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4062,7 +4062,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, } int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, - u32 u32duration, u16 chan, + u32 duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg) @@ -4083,7 +4083,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.body.remain_on_ch.expired = RemainOnChanExpired; msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; - msg.body.remain_on_ch.duration = u32duration; + msg.body.remain_on_ch.duration = duration; msg.body.remain_on_ch.id = session_id; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c935e49d8f8f..4902cc8688a5 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -357,7 +357,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, - u32 u32duration, u16 chan, + u32 duration, u16 chan, wilc_remain_on_chan_expired RemainOnChanExpired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); -- cgit From 95bfdd58c07d6e1bec252b8f175c7934f75d4796 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:37 +0900 Subject: staging: wilc1000: rename RemainOnChanExpired in wilc_remain_on_channel This patch renames RemainOnChanExpired to expired to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 116942df424a..9265328325d3 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4063,7 +4063,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, - wilc_remain_on_chan_expired RemainOnChanExpired, + wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg) { @@ -4080,7 +4080,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.id = HOST_IF_MSG_REMAIN_ON_CHAN; msg.body.remain_on_ch.ch = chan; - msg.body.remain_on_ch.expired = RemainOnChanExpired; + msg.body.remain_on_ch.expired = expired; msg.body.remain_on_ch.ready = RemainOnChanReady; msg.body.remain_on_ch.arg = pvUserArg; msg.body.remain_on_ch.duration = duration; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4902cc8688a5..d2ca27eb3284 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -358,7 +358,7 @@ int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, - wilc_remain_on_chan_expired RemainOnChanExpired, + wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready RemainOnChanReady, void *pvUserArg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); -- cgit From 1aae9398e5756588df58880be67b7f318b6d21ce Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:38 +0900 Subject: staging: wilc1000: rename RemainOnChanReady in wilc_remain_on_channel This patch renames RemainOnChanReady to ready to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 9265328325d3..21d1e87e2db1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4064,7 +4064,7 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, - wilc_remain_on_chan_ready RemainOnChanReady, + wilc_remain_on_chan_ready ready, void *pvUserArg) { int result = 0; @@ -4081,7 +4081,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.id = HOST_IF_MSG_REMAIN_ON_CHAN; msg.body.remain_on_ch.ch = chan; msg.body.remain_on_ch.expired = expired; - msg.body.remain_on_ch.ready = RemainOnChanReady; + msg.body.remain_on_ch.ready = ready; msg.body.remain_on_ch.arg = pvUserArg; msg.body.remain_on_ch.duration = duration; msg.body.remain_on_ch.id = session_id; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index d2ca27eb3284..8a03055bcf5d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -359,7 +359,7 @@ s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, - wilc_remain_on_chan_ready RemainOnChanReady, + wilc_remain_on_chan_ready ready, void *pvUserArg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -- cgit From 482c43301d937dd5d3a565be856d8dda5b51a1dd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:39 +0900 Subject: staging: wilc1000: rename pvUserArg in wilc_remain_on_channel This patch renames pvUserArg to user_arg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 21d1e87e2db1..3636f7664b21 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4065,7 +4065,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready ready, - void *pvUserArg) + void *user_arg) { int result = 0; struct host_if_msg msg; @@ -4082,7 +4082,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, msg.body.remain_on_ch.ch = chan; msg.body.remain_on_ch.expired = expired; msg.body.remain_on_ch.ready = ready; - msg.body.remain_on_ch.arg = pvUserArg; + msg.body.remain_on_ch.arg = user_arg; msg.body.remain_on_ch.duration = duration; msg.body.remain_on_ch.id = session_id; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 8a03055bcf5d..4f741ff53f65 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -360,7 +360,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, wilc_remain_on_chan_ready ready, - void *pvUserArg); + void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); -- cgit From 2c2e461b1d0a0ee5374aded6056c2f1fbdcecdf7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:40 +0900 Subject: staging: wilc1000: fix return type of wilc_del_all_rx_ba_session This patch changes return type of wilc_del_all_rx_ba_session from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3636f7664b21..bf01e83c445d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4605,9 +4605,9 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct ba_session_info *pBASessionInfo = &msg.body.session_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4f741ff53f65..85064cd4c9c8 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -355,7 +355,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -s32 wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit From 73d41cce7769570857a1f223ab9faa7233f8e0bf Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:41 +0900 Subject: staging: wilc1000: rename pBSSID in wilc_del_all_rx_ba_session This patch renames pBSSID to bssid to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index bf01e83c445d..735e6f1dc25f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4605,7 +4605,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID) { int result = 0; struct host_if_msg msg; @@ -4621,7 +4621,7 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID) msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; - memcpy(pBASessionInfo->bssid, pBSSID, ETH_ALEN); + memcpy(pBASessionInfo->bssid, bssid, ETH_ALEN); pBASessionInfo->tid = TID; msg.vif = vif; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 85064cd4c9c8..5f7156e84f22 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -355,7 +355,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *pBSSID, char TID); +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit From d7954748de0e2368811ef68646d76184ed108f72 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:42 +0900 Subject: staging: wilc1000: rename TID in wilc_del_all_rx_ba_session This patch renames TID to tid to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 735e6f1dc25f..265c42beb0ba 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4605,7 +4605,7 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID) +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) { int result = 0; struct host_if_msg msg; @@ -4622,7 +4622,7 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID) msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; memcpy(pBASessionInfo->bssid, bssid, ETH_ALEN); - pBASessionInfo->tid = TID; + pBASessionInfo->tid = tid; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5f7156e84f22..6c8fe3a0ced8 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -355,7 +355,7 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char TID); +int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit From b91e6f33771ed5372bf379d5a33d2aae81842c50 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:43 +0900 Subject: staging: wilc1000: rename pBASessionInfo in wilc_del_all_rx_ba_session This patch renames pBASessionInfo to ba_session_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 265c42beb0ba..409d910a5ca7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4609,7 +4609,7 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) { int result = 0; struct host_if_msg msg; - struct ba_session_info *pBASessionInfo = &msg.body.session_info; + struct ba_session_info *ba_session_info = &msg.body.session_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4621,8 +4621,8 @@ int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; - memcpy(pBASessionInfo->bssid, bssid, ETH_ALEN); - pBASessionInfo->tid = tid; + memcpy(ba_session_info->bssid, bssid, ETH_ALEN); + ba_session_info->tid = tid; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit From 4208e6632138c9295820092d254016dd66b50e1c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:44 +0900 Subject: staging: wilc1000: fix return type of wilc_edit_station This patch changes return type of wilc_edit_station from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 409d910a5ca7..eb2d664cc038 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4350,10 +4350,10 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) return result; } -s32 wilc_edit_station(struct wilc_vif *vif, +int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6c8fe3a0ced8..f60bebb34477 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -349,7 +349,7 @@ int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); -s32 wilc_edit_station(struct wilc_vif *vif, +int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *pstrStaParams); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, -- cgit From 4c7abe191922f1f76c0f66e553fa307fb499160e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:45 +0900 Subject: staging: wilc1000: rename pstrStaParams in wilc_edit_station This patch renames pstrStaParams to sta_param to avoid camelcase. Signed-off-by: Chaehyun Lim 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 eb2d664cc038..de921fa0f19f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4351,7 +4351,7 @@ s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) } int wilc_edit_station(struct wilc_vif *vif, - struct add_sta_param *pstrStaParams) + struct add_sta_param *sta_param) { int result = 0; struct host_if_msg msg; @@ -4370,14 +4370,14 @@ int wilc_edit_station(struct wilc_vif *vif, msg.id = HOST_IF_MSG_EDIT_STATION; msg.vif = vif; - memcpy(pstrAddStationMsg, pstrStaParams, sizeof(struct add_sta_param)); + memcpy(pstrAddStationMsg, sta_param, sizeof(struct add_sta_param)); if (pstrAddStationMsg->rates_len > 0) { u8 *rates = kmalloc(pstrAddStationMsg->rates_len, GFP_KERNEL); if (!rates) return -ENOMEM; - memcpy(rates, pstrStaParams->rates, + memcpy(rates, sta_param->rates, pstrAddStationMsg->rates_len); pstrAddStationMsg->rates = rates; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f60bebb34477..abb626e92dbb 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -350,7 +350,7 @@ int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, - struct add_sta_param *pstrStaParams); + struct add_sta_param *sta_param); int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); -- cgit From 785c0712048afa9528a48970eec1863cf71d4ffc Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:46 +0900 Subject: staging: wilc1000: rename pstrAddStationMsg in wilc_edit_station This patch renames pstrAddStationMsg to add_sta_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index de921fa0f19f..2f94804e28a0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4355,7 +4355,7 @@ int wilc_edit_station(struct wilc_vif *vif, { int result = 0; struct host_if_msg msg; - struct add_sta_param *pstrAddStationMsg = &msg.body.add_sta_info; + struct add_sta_param *add_sta_info = &msg.body.add_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4370,16 +4370,16 @@ int wilc_edit_station(struct wilc_vif *vif, msg.id = HOST_IF_MSG_EDIT_STATION; msg.vif = vif; - memcpy(pstrAddStationMsg, sta_param, sizeof(struct add_sta_param)); - if (pstrAddStationMsg->rates_len > 0) { - u8 *rates = kmalloc(pstrAddStationMsg->rates_len, GFP_KERNEL); + memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); + if (add_sta_info->rates_len > 0) { + u8 *rates = kmalloc(add_sta_info->rates_len, GFP_KERNEL); if (!rates) return -ENOMEM; memcpy(rates, sta_param->rates, - pstrAddStationMsg->rates_len); - pstrAddStationMsg->rates = rates; + add_sta_info->rates_len); + add_sta_info->rates = rates; } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit From 1ae82d1ab0adf01fc3b049d375ccdf9c878085e0 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:47 +0900 Subject: staging: wilc1000: use kmemdup in wilc_edit_station This patch replaces kmalloc followed by memcpy with kmemdup. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2f94804e28a0..290c27aa0184 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4372,13 +4372,11 @@ int wilc_edit_station(struct wilc_vif *vif, memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); if (add_sta_info->rates_len > 0) { - u8 *rates = kmalloc(add_sta_info->rates_len, GFP_KERNEL); - + u8 *rates = kmemdup(sta_param->rates, + add_sta_info->rates_len, + GFP_KERNEL); if (!rates) return -ENOMEM; - - memcpy(rates, sta_param->rates, - add_sta_info->rates_len); add_sta_info->rates = rates; } -- cgit From e38d850f70a2a3a19d26c662bb2fc9c897e99e92 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:48 +0900 Subject: staging: wilc1000: remove rates variable in wilc_edit_station Instead of using rates variable, it is used as add_sta_info->rates directly. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 290c27aa0184..57d59dc77cba 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4372,12 +4372,11 @@ int wilc_edit_station(struct wilc_vif *vif, memcpy(add_sta_info, sta_param, sizeof(struct add_sta_param)); if (add_sta_info->rates_len > 0) { - u8 *rates = kmemdup(sta_param->rates, - add_sta_info->rates_len, - GFP_KERNEL); - if (!rates) + add_sta_info->rates = kmemdup(sta_param->rates, + add_sta_info->rates_len, + GFP_KERNEL); + if (!add_sta_info->rates) return -ENOMEM; - add_sta_info->rates = rates; } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit From 253eb92e40bb8a3a9e3f4f293354820bfd4bc049 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:49 +0900 Subject: staging: wilc1000: fix return type of wilc_del_allstation This patch changes return type of wilc_del_allstation from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 57d59dc77cba..3f410b2b4ee4 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4299,9 +4299,9 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) return result; } -s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) +int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct del_all_sta *pstrDelAllStationMsg = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index abb626e92dbb..6d424e73629e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -347,7 +347,7 @@ s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -s32 wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); +int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit From 2092374d7ec53b91c4921ce2d21cc0ad2382cb9f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:50 +0900 Subject: staging: wilc1000: rename pu8MacAddr in wilc_del_allstation This patch renames pu8MacAddr to mac_addr to avoid camelcase. Signed-off-by: Chaehyun Lim 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 3f410b2b4ee4..37a78a33d0ce 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4299,7 +4299,7 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) return result; } -int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) +int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) { int result = 0; struct host_if_msg msg; @@ -4322,8 +4322,8 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]) msg.vif = vif; for (i = 0; i < MAX_NUM_STA; i++) { - if (memcmp(pu8MacAddr[i], au8Zero_Buff, ETH_ALEN)) { - memcpy(pstrDelAllStationMsg->del_all_sta[i], pu8MacAddr[i], ETH_ALEN); + if (memcmp(mac_addr[i], au8Zero_Buff, ETH_ALEN)) { + memcpy(pstrDelAllStationMsg->del_all_sta[i], mac_addr[i], ETH_ALEN); PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", pstrDelAllStationMsg->del_all_sta[i][0], pstrDelAllStationMsg->del_all_sta[i][1], diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6d424e73629e..3c932e7a9b76 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -347,7 +347,7 @@ s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -int wilc_del_allstation(struct wilc_vif *vif, u8 pu8MacAddr[][ETH_ALEN]); +int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr); int wilc_edit_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit From 55d44a621dcb8eaadfffd28f74123f51d2e75eb2 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:51 +0900 Subject: staging: wilc1000: rename pstrDelAllStationMsg in wilc_del_allstation This patch renames pstrDelAllStationMsg to del_all_sta_info to avoid camelcase. 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 37a78a33d0ce..7686a521f548 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4303,7 +4303,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) { int result = 0; struct host_if_msg msg; - struct del_all_sta *pstrDelAllStationMsg = &msg.body.del_all_sta_info; + struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; u8 au8Zero_Buff[ETH_ALEN] = {0}; u32 i; @@ -4323,14 +4323,14 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) for (i = 0; i < MAX_NUM_STA; i++) { if (memcmp(mac_addr[i], au8Zero_Buff, ETH_ALEN)) { - memcpy(pstrDelAllStationMsg->del_all_sta[i], mac_addr[i], ETH_ALEN); + memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], ETH_ALEN); PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", - pstrDelAllStationMsg->del_all_sta[i][0], - pstrDelAllStationMsg->del_all_sta[i][1], - pstrDelAllStationMsg->del_all_sta[i][2], - pstrDelAllStationMsg->del_all_sta[i][3], - pstrDelAllStationMsg->del_all_sta[i][4], - pstrDelAllStationMsg->del_all_sta[i][5]); + del_all_sta_info->del_all_sta[i][0], + del_all_sta_info->del_all_sta[i][1], + del_all_sta_info->del_all_sta[i][2], + del_all_sta_info->del_all_sta[i][3], + del_all_sta_info->del_all_sta[i][4], + del_all_sta_info->del_all_sta[i][5]); u8AssocNumb++; } } @@ -4339,7 +4339,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) return result; } - pstrDelAllStationMsg->assoc_sta = u8AssocNumb; + del_all_sta_info->assoc_sta = u8AssocNumb; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit From 06e682b06e9823bba7a10dbb0a33d8c6a14ec78d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:52 +0900 Subject: staging: wilc1000: rename au8Zero_Buff in wilc_del_allstation This patch renames au8Zero_Buff to zero_addr to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7686a521f548..a3f120aebf04 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4305,7 +4305,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) struct host_if_msg msg; struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; - u8 au8Zero_Buff[ETH_ALEN] = {0}; + u8 zero_addr[ETH_ALEN] = {0}; u32 i; u8 u8AssocNumb = 0; @@ -4322,7 +4322,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) msg.vif = vif; for (i = 0; i < MAX_NUM_STA; i++) { - if (memcmp(mac_addr[i], au8Zero_Buff, ETH_ALEN)) { + if (memcmp(mac_addr[i], zero_addr, ETH_ALEN)) { memcpy(del_all_sta_info->del_all_sta[i], mac_addr[i], ETH_ALEN); PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", del_all_sta_info->del_all_sta[i][0], -- cgit From cc971eec560bdde8ff0dbc68ebeea3056892ba60 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:53 +0900 Subject: staging: wilc1000: use int instead of u32 The variable i is used as array index so that it is better to use data type of int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a3f120aebf04..c0f30a29cc9b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4306,7 +4306,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) struct del_all_sta *del_all_sta_info = &msg.body.del_all_sta_info; struct host_if_drv *hif_drv = vif->hif_drv; u8 zero_addr[ETH_ALEN] = {0}; - u32 i; + int i; u8 u8AssocNumb = 0; if (!hif_drv) { -- cgit From 9d6cec9f46eb993a158d6ad48f65aec419683795 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:54 +0900 Subject: staging: wilc1000: rename u8AssocNumb in wilc_del_allstation This patch renames u8AssocNumb to assoc_sta to avoid camelcase. 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 c0f30a29cc9b..0ff500d5b7ae 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4307,7 +4307,7 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) struct host_if_drv *hif_drv = vif->hif_drv; u8 zero_addr[ETH_ALEN] = {0}; int i; - u8 u8AssocNumb = 0; + u8 assoc_sta = 0; if (!hif_drv) { PRINT_ER("driver is null\n"); @@ -4331,15 +4331,15 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) del_all_sta_info->del_all_sta[i][3], del_all_sta_info->del_all_sta[i][4], del_all_sta_info->del_all_sta[i][5]); - u8AssocNumb++; + assoc_sta++; } } - if (!u8AssocNumb) { + if (!assoc_sta) { PRINT_D(CFG80211_DBG, "NO ASSOCIATED STAS\n"); return result; } - del_all_sta_info->assoc_sta = u8AssocNumb; + del_all_sta_info->assoc_sta = assoc_sta; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) -- cgit From 4d84dbed22cf4c9c0f98b72429499b1a59d63103 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:55 +0900 Subject: staging: wilc1000: fix return type of wilc_add_beacon This patch changes return type of wilc_add_beacon from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0ff500d5b7ae..8d935e4112c0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4159,10 +4159,10 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) return result; } -s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct beacon_attr *pstrSetBeaconParam = &msg.body.beacon_info; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3c932e7a9b76..272b69691849 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -343,7 +343,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); -s32 wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit From 8b1844bb20fe435f9bf4a86ea6572aec575a5659 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:56 +0900 Subject: staging: wilc1000: rename u32Interval in wilc_add_beacon This patch renames u32Interval to interval to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8d935e4112c0..615ae5916691 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4159,7 +4159,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) return result; } -int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; @@ -4178,7 +4178,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; - pstrSetBeaconParam->interval = u32Interval; + pstrSetBeaconParam->interval = interval; pstrSetBeaconParam->dtim_period = u32DTIMPeriod; pstrSetBeaconParam->head_len = u32HeadLen; pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 272b69691849..93a8abb47341 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -343,7 +343,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); -int wilc_add_beacon(struct wilc_vif *vif, u32 u32Interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit From 916935f5c8e313bdbecc6c7de60c5abb04e95986 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:57 +0900 Subject: staging: wilc1000: rename u32DTIMPeriod in wilc_add_beacon This patch renames u32DTIMPeriod to dtim_period to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 615ae5916691..9d9cf9126c4e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4159,7 +4159,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) return result; } -int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; @@ -4179,7 +4179,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; pstrSetBeaconParam->interval = interval; - pstrSetBeaconParam->dtim_period = u32DTIMPeriod; + pstrSetBeaconParam->dtim_period = dtim_period; pstrSetBeaconParam->head_len = u32HeadLen; pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL); if (!pstrSetBeaconParam->head) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 93a8abb47341..58b73d665292 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -343,7 +343,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); -int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 u32DTIMPeriod, +int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); -- cgit From 418990415fbf36bdafcb92a6313b56a2516b5f32 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:58 +0900 Subject: staging: wilc1000: rename u32HeadLen in wilc_add_beacon This patch renames u32HeadLen to head_len to avoid camelcase. Signed-off-by: Chaehyun Lim 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 9d9cf9126c4e..07674d2f5404 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) + u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; struct host_if_msg msg; @@ -4180,8 +4180,8 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, msg.vif = vif; pstrSetBeaconParam->interval = interval; pstrSetBeaconParam->dtim_period = dtim_period; - pstrSetBeaconParam->head_len = u32HeadLen; - pstrSetBeaconParam->head = kmemdup(pu8Head, u32HeadLen, GFP_KERNEL); + pstrSetBeaconParam->head_len = head_len; + pstrSetBeaconParam->head = kmemdup(pu8Head, head_len, GFP_KERNEL); if (!pstrSetBeaconParam->head) { result = -ENOMEM; goto ERRORHANDLER; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 58b73d665292..02750281fe0f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 u32HeadLen, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); + u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit From 55a76be054fb3826e691b2f9370ac4ac76bf9fdd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:35:59 +0900 Subject: staging: wilc1000: rename pu8Head in wilc_add_beacon This patch renames pu8Head to head to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 07674d2f5404..e35465e8fe4d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail) + u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail) { int result = 0; struct host_if_msg msg; @@ -4181,7 +4181,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, pstrSetBeaconParam->interval = interval; pstrSetBeaconParam->dtim_period = dtim_period; pstrSetBeaconParam->head_len = head_len; - pstrSetBeaconParam->head = kmemdup(pu8Head, head_len, GFP_KERNEL); + pstrSetBeaconParam->head = kmemdup(head, head_len, GFP_KERNEL); if (!pstrSetBeaconParam->head) { result = -ENOMEM; goto ERRORHANDLER; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 02750281fe0f..1c3f741ea48a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *pu8Head, u32 u32TailLen, u8 *pu8Tail); + u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit From 2df3585b12554f242816b21c4d6bd9f7e7f4c8cc Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:36:00 +0900 Subject: staging: wilc1000: rename u32TailLen in wilc_add_beacon This patch renames u32TailLen to tail_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e35465e8fe4d..c81c74916570 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail) + u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail) { int result = 0; struct host_if_msg msg; @@ -4186,10 +4186,10 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, result = -ENOMEM; goto ERRORHANDLER; } - pstrSetBeaconParam->tail_len = u32TailLen; + pstrSetBeaconParam->tail_len = tail_len; - if (u32TailLen > 0) { - pstrSetBeaconParam->tail = kmemdup(pu8Tail, u32TailLen, + if (tail_len > 0) { + pstrSetBeaconParam->tail = kmemdup(pu8Tail, tail_len, GFP_KERNEL); if (!pstrSetBeaconParam->tail) { result = -ENOMEM; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 1c3f741ea48a..7e4ea186b4a2 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 u32TailLen, u8 *pu8Tail); + u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit From 733d10312c9796a14da7be56a10e407ad4b9a0bf Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:36:01 +0900 Subject: staging: wilc1000: rename pu8Tail in wilc_add_beacon This patch renames pu8Tail to tail to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c81c74916570..8f8c58312c85 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4160,7 +4160,7 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) } int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail) + u32 head_len, u8 *head, u32 tail_len, u8 *tail) { int result = 0; struct host_if_msg msg; @@ -4189,7 +4189,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, pstrSetBeaconParam->tail_len = tail_len; if (tail_len > 0) { - pstrSetBeaconParam->tail = kmemdup(pu8Tail, tail_len, + pstrSetBeaconParam->tail = kmemdup(tail, tail_len, GFP_KERNEL); if (!pstrSetBeaconParam->tail) { result = -ENOMEM; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 7e4ea186b4a2..b61b4845e509 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -344,7 +344,7 @@ s32 wilc_hif_set_cfg(struct wilc_vif *vif, s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, - u32 head_len, u8 *head, u32 tail_len, u8 *pu8Tail); + u32 head_len, u8 *head, u32 tail_len, u8 *tail); int wilc_del_beacon(struct wilc_vif *vif); int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param); int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]); -- cgit From 75bf22c14c76c48241ca877737c59f8e049e0e60 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Sun, 3 Jan 2016 17:36:02 +0900 Subject: staging: wilc1000: rename pstrSetBeaconParam in wilc_add_beacon This patch renames pstrSetBeaconParam to beacon_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 8f8c58312c85..34d56cdd16c5 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4164,7 +4164,7 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, { int result = 0; struct host_if_msg msg; - struct beacon_attr *pstrSetBeaconParam = &msg.body.beacon_info; + struct beacon_attr *beacon_info = &msg.body.beacon_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv) { @@ -4178,25 +4178,24 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; - pstrSetBeaconParam->interval = interval; - pstrSetBeaconParam->dtim_period = dtim_period; - pstrSetBeaconParam->head_len = head_len; - pstrSetBeaconParam->head = kmemdup(head, head_len, GFP_KERNEL); - if (!pstrSetBeaconParam->head) { + beacon_info->interval = interval; + beacon_info->dtim_period = dtim_period; + beacon_info->head_len = head_len; + beacon_info->head = kmemdup(head, head_len, GFP_KERNEL); + if (!beacon_info->head) { result = -ENOMEM; goto ERRORHANDLER; } - pstrSetBeaconParam->tail_len = tail_len; + beacon_info->tail_len = tail_len; if (tail_len > 0) { - pstrSetBeaconParam->tail = kmemdup(tail, tail_len, - GFP_KERNEL); - if (!pstrSetBeaconParam->tail) { + beacon_info->tail = kmemdup(tail, tail_len, GFP_KERNEL); + if (!beacon_info->tail) { result = -ENOMEM; goto ERRORHANDLER; } } else { - pstrSetBeaconParam->tail = NULL; + beacon_info->tail = NULL; } result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); @@ -4205,9 +4204,9 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, ERRORHANDLER: if (result) { - kfree(pstrSetBeaconParam->head); + kfree(beacon_info->head); - kfree(pstrSetBeaconParam->tail); + kfree(beacon_info->tail); } return result; -- cgit From 1870394394734c596ec2ef4a3a853a03e128f0e2 Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Mon, 4 Jan 2016 20:33:50 +0000 Subject: staging: wilc1000: add missing __user attribute This removes a Sparse warning. Signed-off-by: Hugo Camboulive Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 27c653a0cdf9..291e6faa90e9 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -89,7 +89,7 @@ static ssize_t wilc_debug_region_read(struct file *file, char __user *userbuf, s return simple_read_from_buffer(userbuf, count, ppos, buf, res); } -static ssize_t wilc_debug_region_write(struct file *filp, const char *buf, size_t count, loff_t *ppos) +static ssize_t wilc_debug_region_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) { char buffer[128] = {}; int flag; -- cgit From d27afda304a502302b0baf4c21c7ba9451dbd992 Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Mon, 4 Jan 2016 22:02:23 +0000 Subject: staging: wilc1000: make some variables static terminated_handle is used only in host_interface.c wilc1000_spi_driver is exported by module_spi_driver() This fixes a few Sparse warnings. Signed-off-by: Hugo Camboulive Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 34d56cdd16c5..69946df84baf 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -225,7 +225,7 @@ struct join_bss_param { u8 start_time[4]; }; -struct host_if_drv *terminated_handle; +static struct host_if_drv *terminated_handle; bool wilc_optaining_ip; static u8 P2P_LISTEN_STATE; static struct task_struct *hif_thread_handler; diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 86de50c9f7f5..b9dc91de90e8 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -153,7 +153,7 @@ static const struct of_device_id wilc1000_of_match[] = { }; MODULE_DEVICE_TABLE(of, wilc1000_of_match); -struct spi_driver wilc1000_spi_driver = { +static struct spi_driver wilc1000_spi_driver = { .driver = { .name = MODALIAS, .of_match_table = wilc1000_of_match, -- cgit From 8c6492aa9065c33de127cbbcad8e84b828ce6f2e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:30 +0900 Subject: staging: wilc1000: rename pu8ssid in struct hidden_net_info This patch renames pu8ssid to ssid that is a member of struct hidden_net_info. There is no need to use pu8 prefix to show data type so just remove it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 69946df84baf..3ec40b1425d6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -842,7 +842,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; - memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen); + memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen); pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; } diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b61b4845e509..3b5740063939 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -186,7 +186,7 @@ struct rcvd_net_info { }; struct hidden_net_info { - u8 *pu8ssid; + u8 *ssid; u8 u8ssidlen; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index be5704bfc382..acd0c8d9b103 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -651,8 +651,8 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) for (i = 0; i < request->n_ssids; i++) { if (request->ssids[i].ssid && request->ssids[i].ssid_len != 0) { - strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); - memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); + strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); + memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); -- cgit From a2d4969bc9029235a85f48b4540105a0dbb6666d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:31 +0900 Subject: staging: wilc1000: rename u8ssidlen in struct hidden_net_info This patch renames u8ssidlen to ssid_len that is a member of hidden_net_info. There is no need to use u8 prefix to show data type so just rename it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3ec40b1425d6..21e0dcf1894b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -830,7 +830,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, strWIDList[u32WidsCount].type = WID_STR; for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) - valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen) + 1); + valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len) + 1); pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL); strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal; if (strWIDList[u32WidsCount].val) { @@ -841,9 +841,9 @@ static s32 Handle_Scan(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum); for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { - *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; - memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen); - pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].u8ssidlen; + *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; + memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len); + pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; } strWIDList[u32WidsCount].size = (s32)(valuesize + 1); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3b5740063939..42ab2ad97026 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -187,7 +187,7 @@ struct rcvd_net_info { struct hidden_net_info { u8 *ssid; - u8 u8ssidlen; + u8 ssid_len; }; struct hidden_network { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index acd0c8d9b103..56d736cd0714 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -653,7 +653,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) request->ssids[i].ssid_len != 0) { strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); - strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len; + strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid_len = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); strHiddenNetwork.u8ssidnum -= 1; -- cgit From 245a18654ffeb2e682200d0a0204b563762935be Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:32 +0900 Subject: staging: wilc1000: rename pstrHiddenNetworkInfo in struct hidden_network This patch renames pstrHiddenNetworkInfo to net_info to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 14 +++++++------- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 21e0dcf1894b..437cb41e8e44 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -830,7 +830,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, strWIDList[u32WidsCount].type = WID_STR; for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) - valuesize += ((pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len) + 1); + valuesize += ((pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len) + 1); pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL); strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal; if (strWIDList[u32WidsCount].val) { @@ -841,9 +841,9 @@ static s32 Handle_Scan(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum); for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { - *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; - memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid, pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len); - pu8Buffer += pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo[i].ssid_len; + *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; + memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len); + pu8Buffer += pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; } strWIDList[u32WidsCount].size = (s32)(valuesize + 1); @@ -912,8 +912,8 @@ ERRORHANDLER: kfree(pstrHostIFscanAttr->ies); pstrHostIFscanAttr->ies = NULL; - kfree(pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo); - pstrHostIFscanAttr->hidden_network.pstrHiddenNetworkInfo = NULL; + kfree(pstrHostIFscanAttr->hidden_network.net_info); + pstrHostIFscanAttr->hidden_network.net_info = NULL; kfree(pu8HdnNtwrksWidVal); @@ -3691,7 +3691,7 @@ s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, msg.id = HOST_IF_MSG_SCAN; if (pstrHiddenNetwork) { - msg.body.scan_info.hidden_network.pstrHiddenNetworkInfo = pstrHiddenNetwork->pstrHiddenNetworkInfo; + msg.body.scan_info.hidden_network.net_info = pstrHiddenNetwork->net_info; msg.body.scan_info.hidden_network.u8ssidnum = pstrHiddenNetwork->u8ssidnum; } else diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 42ab2ad97026..a0345e924963 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -191,7 +191,7 @@ struct hidden_net_info { }; struct hidden_network { - struct hidden_net_info *pstrHiddenNetworkInfo; + struct hidden_net_info *net_info; u8 u8ssidnum; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 56d736cd0714..f0dd38d23a1b 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -644,16 +644,16 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) PRINT_D(CFG80211_DBG, "Number of SSIDs %d\n", request->n_ssids); if (request->n_ssids >= 1) { - strHiddenNetwork.pstrHiddenNetworkInfo = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL); + strHiddenNetwork.net_info = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL); strHiddenNetwork.u8ssidnum = request->n_ssids; for (i = 0; i < request->n_ssids; i++) { if (request->ssids[i].ssid && request->ssids[i].ssid_len != 0) { - strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); - memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); - strHiddenNetwork.pstrHiddenNetworkInfo[i].ssid_len = request->ssids[i].ssid_len; + strHiddenNetwork.net_info[i].ssid = kmalloc(request->ssids[i].ssid_len, GFP_KERNEL); + memcpy(strHiddenNetwork.net_info[i].ssid, request->ssids[i].ssid, request->ssids[i].ssid_len); + strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); strHiddenNetwork.u8ssidnum -= 1; -- cgit From 40e05e86d5fcb3d652c49a2b0ad93573a7dca2b4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 13:26:33 +0900 Subject: staging: wilc1000: rename u8ssidnum in struct hidden_network This patch renames u8ssidnum to n_ssids that is a member of struct hidden_network. There is no need to use u8 prefix to show data type so just rename it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 10 +++++----- drivers/staging/wilc1000/host_interface.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 437cb41e8e44..b0de6e444a33 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -829,18 +829,18 @@ static s32 Handle_Scan(struct wilc_vif *vif, strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ; strWIDList[u32WidsCount].type = WID_STR; - for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) + for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) valuesize += ((pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len) + 1); pu8HdnNtwrksWidVal = kmalloc(valuesize + 1, GFP_KERNEL); strWIDList[u32WidsCount].val = pu8HdnNtwrksWidVal; if (strWIDList[u32WidsCount].val) { pu8Buffer = strWIDList[u32WidsCount].val; - *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.u8ssidnum; + *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.n_ssids; - PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.u8ssidnum); + PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.n_ssids); - for (i = 0; i < pstrHostIFscanAttr->hidden_network.u8ssidnum; i++) { + for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) { *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len); pu8Buffer += pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; @@ -3692,7 +3692,7 @@ s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, if (pstrHiddenNetwork) { msg.body.scan_info.hidden_network.net_info = pstrHiddenNetwork->net_info; - msg.body.scan_info.hidden_network.u8ssidnum = pstrHiddenNetwork->u8ssidnum; + msg.body.scan_info.hidden_network.n_ssids = pstrHiddenNetwork->n_ssids; } else PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a0345e924963..9cb08544fa35 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -192,7 +192,7 @@ struct hidden_net_info { struct hidden_network { struct hidden_net_info *net_info; - u8 u8ssidnum; + u8 n_ssids; }; struct user_scan_req { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index f0dd38d23a1b..792fdff4bca9 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -645,7 +645,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) if (request->n_ssids >= 1) { strHiddenNetwork.net_info = kmalloc(request->n_ssids * sizeof(struct hidden_network), GFP_KERNEL); - strHiddenNetwork.u8ssidnum = request->n_ssids; + strHiddenNetwork.n_ssids = request->n_ssids; for (i = 0; i < request->n_ssids; i++) { @@ -656,7 +656,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) strHiddenNetwork.net_info[i].ssid_len = request->ssids[i].ssid_len; } else { PRINT_D(CFG80211_DBG, "Received one NULL SSID\n"); - strHiddenNetwork.u8ssidnum -= 1; + strHiddenNetwork.n_ssids -= 1; } } PRINT_D(CFG80211_DBG, "Trigger Scan Request\n"); -- cgit From 03a5d8c0854c02a3c54ee09d9b784e82f0c1c9aa Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:45 +0900 Subject: staging: wilc1000: fix return type of wilc_scan This patch changes return type of wilc_scan from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index b0de6e444a33..c8a07cdb9141 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3672,12 +3672,12 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return result; } -s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 9cb08544fa35..2bf4ef0cda93 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -335,7 +335,7 @@ int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); -s32 wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); -- cgit From 3c2be65f28b9664e9f62c4dd4a9022b602174b29 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:46 +0900 Subject: staging: wilc1000: rename u8ScanSource in wilc_scan This patch renames u8ScanSource to scan_source to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c8a07cdb9141..ac00b17c6d3b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3672,7 +3672,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return result; } -int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) @@ -3698,7 +3698,7 @@ int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); msg.vif = vif; - msg.body.scan_info.src = u8ScanSource; + msg.body.scan_info.src = scan_source; msg.body.scan_info.type = u8ScanType; msg.body.scan_info.result = ScanResult; msg.body.scan_info.arg = pvUserArg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 2bf4ef0cda93..6ef594be0107 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -335,7 +335,7 @@ int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); -int wilc_scan(struct wilc_vif *vif, u8 u8ScanSource, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); -- cgit From c0734df9b3d51e190290a5674bebb9f888716f7c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:47 +0900 Subject: staging: wilc1000: rename u8ScanType in wilc_scan This patch renames u8ScanType to scan_type to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ac00b17c6d3b..6d96323f8589 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3672,7 +3672,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return result; } -int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) @@ -3699,7 +3699,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, msg.vif = vif; msg.body.scan_info.src = scan_source; - msg.body.scan_info.type = u8ScanType; + msg.body.scan_info.type = scan_type; msg.body.scan_info.result = ScanResult; msg.body.scan_info.arg = pvUserArg; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 6ef594be0107..0d7ed5549272 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -335,7 +335,7 @@ int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); -int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 u8ScanType, +int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); -- cgit From 5eb037e6d30aa59adbf72367ec76045a73d7a4e4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:48 +0900 Subject: staging: wilc1000: rename pu8ChnlFreqList in wilc_scan This patch renames pu8ChnlFreqList to ch_freq_list to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6d96323f8589..fcbfee609b70 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3673,7 +3673,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { @@ -3705,7 +3705,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.ch_list_len = u8ChnlListLen; msg.body.scan_info.ch_freq_list = kmalloc(u8ChnlListLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ch_freq_list, pu8ChnlFreqList, u8ChnlListLen); + memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, u8ChnlListLen); msg.body.scan_info.ies_len = IEsLen; msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 0d7ed5549272..863332e741d1 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -336,7 +336,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *pu8ChnlFreqList, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, -- cgit From 86163ec9902c3fffff5b047bcbb8e5d0de69f624 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:49 +0900 Subject: staging: wilc1000: rename u8ChnlListLen in wilc_scan This patch renames u8ChnlListLen to ch_list_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index fcbfee609b70..99455909c489 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3673,7 +3673,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { @@ -3703,9 +3703,9 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.result = ScanResult; msg.body.scan_info.arg = pvUserArg; - msg.body.scan_info.ch_list_len = u8ChnlListLen; - msg.body.scan_info.ch_freq_list = kmalloc(u8ChnlListLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, u8ChnlListLen); + msg.body.scan_info.ch_list_len = ch_list_len; + msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); + memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, ch_list_len); msg.body.scan_info.ies_len = IEsLen; msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 863332e741d1..c56c3f658a7b 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -336,7 +336,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 u8ChnlListLen, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, -- cgit From ce2d023ff5533bca864735229aea8a5538e48584 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:50 +0900 Subject: staging: wilc1000: rename pu8IEs in wilc_scan This patch renames pu8IEs to ies to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 99455909c489..6cd831069841 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3673,7 +3673,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) } int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { @@ -3709,7 +3709,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.ies_len = IEsLen; msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ies, pu8IEs, IEsLen); + memcpy(msg.body.scan_info.ies, ies, IEsLen); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c56c3f658a7b..5356492848c7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -336,7 +336,7 @@ int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, - u8 *ch_freq_list, u8 ch_list_len, const u8 *pu8IEs, + u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, -- cgit From 6ca31901d9db58ba68552ef7eec8a7125ad3f4f7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:51 +0900 Subject: staging: wilc1000: rename IEsLen in wilc_scan This patch renames IEsLen to ies_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6cd831069841..a3c13cb12b2f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3674,7 +3674,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { int result = 0; @@ -3707,9 +3707,9 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, ch_list_len); - msg.body.scan_info.ies_len = IEsLen; - msg.body.scan_info.ies = kmalloc(IEsLen, GFP_KERNEL); - memcpy(msg.body.scan_info.ies, ies, IEsLen); + msg.body.scan_info.ies_len = ies_len; + msg.body.scan_info.ies = kmalloc(ies_len, GFP_KERNEL); + memcpy(msg.body.scan_info.ies, ies, ies_len); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 5356492848c7..a782b9e54a6f 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t IEsLen, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -- cgit From c8fb0bf931decb8a78a51e275609c4573b4f728d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:52 +0900 Subject: staging: wilc1000: rename ScanResult in wilc_scan This patch renames ScanResult to scan_result to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a3c13cb12b2f..e475c775061e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3674,15 +3674,15 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, struct hidden_network *pstrHiddenNetwork) { int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; - if (!hif_drv || !ScanResult) { - PRINT_ER("hif_drv or ScanResult = NULL\n"); + if (!hif_drv || !scan_result) { + PRINT_ER("hif_drv or scan_result = NULL\n"); return -EFAULT; } @@ -3700,7 +3700,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.vif = vif; msg.body.scan_info.src = scan_source; msg.body.scan_info.type = scan_type; - msg.body.scan_info.result = ScanResult; + msg.body.scan_info.result = scan_result; msg.body.scan_info.arg = pvUserArg; msg.body.scan_info.ch_list_len = ch_list_len; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index a782b9e54a6f..aaaa5f7b729e 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result ScanResult, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -- cgit From 2c97f2d4ed34f77481836d4511fa9fbb072c258e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:53 +0900 Subject: staging: wilc1000: rename pvUserArg in wilc_scan This patch renames pvUserArg to user_arg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e475c775061e..56b58d3dd292 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3674,7 +3674,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *pstrHiddenNetwork) { int result = 0; @@ -3701,7 +3701,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.src = scan_source; msg.body.scan_info.type = scan_type; msg.body.scan_info.result = scan_result; - msg.body.scan_info.arg = pvUserArg; + msg.body.scan_info.arg = user_arg; msg.body.scan_info.ch_list_len = ch_list_len; msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index aaaa5f7b729e..1923a3093751 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, - size_t ies_len, wilc_scan_result scan_result, void *pvUserArg, + size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *pstrHiddenNetwork); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -- cgit From d317818bf4c1238c21efbe407e24727b50f324a1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:54 +0900 Subject: staging: wilc1000: rename pstrHiddenNetwork in wilc_scan This patch renames pstrHiddenNetwork to hidden_network to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 10 +++++----- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 56b58d3dd292..07fe5c84ce1c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3675,7 +3675,7 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, wilc_scan_result scan_result, void *user_arg, - struct hidden_network *pstrHiddenNetwork) + struct hidden_network *hidden_network) { int result = 0; struct host_if_msg msg; @@ -3690,12 +3690,12 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.id = HOST_IF_MSG_SCAN; - if (pstrHiddenNetwork) { - msg.body.scan_info.hidden_network.net_info = pstrHiddenNetwork->net_info; - msg.body.scan_info.hidden_network.n_ssids = pstrHiddenNetwork->n_ssids; + if (hidden_network) { + msg.body.scan_info.hidden_network.net_info = hidden_network->net_info; + msg.body.scan_info.hidden_network.n_ssids = hidden_network->n_ssids; } else - PRINT_D(HOSTINF_DBG, "pstrHiddenNetwork IS EQUAL TO NULL\n"); + PRINT_D(HOSTINF_DBG, "hidden_network IS EQUAL TO NULL\n"); msg.vif = vif; msg.body.scan_info.src = scan_source; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 1923a3093751..f8969774a23c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -338,7 +338,7 @@ int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, wilc_scan_result scan_result, void *user_arg, - struct hidden_network *pstrHiddenNetwork); + struct hidden_network *hidden_network); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); -- cgit From 1a271d996097367da1f35cf257da11f472fd39d2 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:55 +0900 Subject: staging: wilc1000: use kmemdup instead of kmalloc/memcpy This patch replaces kmalloc followed by memcpy with kmemdup. It is also added error checking to return -ENOMEM when kmemdup is failed. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 07fe5c84ce1c..3de0fad2fa1c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3704,12 +3704,16 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.body.scan_info.arg = user_arg; msg.body.scan_info.ch_list_len = ch_list_len; - msg.body.scan_info.ch_freq_list = kmalloc(ch_list_len, GFP_KERNEL); - memcpy(msg.body.scan_info.ch_freq_list, ch_freq_list, ch_list_len); + msg.body.scan_info.ch_freq_list = kmemdup(ch_freq_list, + ch_list_len, + GFP_KERNEL); + if (!msg.body.scan_info.ch_freq_list) + return -ENOMEM; msg.body.scan_info.ies_len = ies_len; - msg.body.scan_info.ies = kmalloc(ies_len, GFP_KERNEL); - memcpy(msg.body.scan_info.ies, ies, ies_len); + msg.body.scan_info.ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!msg.body.scan_info.ies) + return -ENOMEM; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { -- cgit From 3bff53a880b94df68e95b64b49929578af1b007a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:56 +0900 Subject: staging: wilc1000: rename phWFIDrv in wilc_init declaration The second argument name is different between wilc_init declaration and definition. This patch renames phWFIDrv to hif_drv_handler to match argument name. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f8969774a23c..b1ebd4d9df34 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -341,7 +341,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, struct hidden_network *hidden_network); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -s32 wilc_init(struct net_device *dev, struct host_if_drv **phWFIDrv); +s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail); -- cgit From 1e995c10791f83f606b94b73c0f89ac29aea4824 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 5 Jan 2016 23:06:57 +0900 Subject: staging: wilc1000: fix return type of wilc_init This patch changes return type of wilc_init from s32 to int. The error code as -ENOMEM or -EFAULT is returned in the wilc_init. It is better to use return type of int in this function, not s32. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 3de0fad2fa1c..5801d41ef988 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3779,9 +3779,9 @@ static void GetPeriodicRSSI(unsigned long arg) mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000)); } -s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) +int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) { - s32 result = 0; + int result = 0; struct host_if_drv *hif_drv; struct wilc_vif *vif; struct wilc *wilc; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b1ebd4d9df34..4c02e6bbed41 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -341,7 +341,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, struct hidden_network *hidden_network); s32 wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); -s32 wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); +int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail); -- cgit From ce7b516f3f9e11fe4ee06fad0d7e853bb6e8f160 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 13 Jan 2016 15:36:17 +0100 Subject: staging: wilc1000: remove extraneous variable Building wilc1000 with clang currently fails in the staging-next branch: drivers/staging/wilc1000/wilc_spi.c:123:34: warning: tentative definition of variable with internal linkage has incomplete non-array type 'const struct wilc1000_ops' [-Wtentative-definition-incomplete-type] static const struct wilc1000_ops wilc1000_spi_ops; The reason is that wilc1000_ops was left behind after a recent cleanup, and is completely unused and also uninitialized and const and has an incomplete type. Removing the variable is obviously correct, and gets rid of the warning. No idea why gcc does not complain about it though. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_spi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index b9dc91de90e8..1df07e7bea59 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -120,8 +120,6 @@ static u8 crc7(u8 crc, const u8 *buffer, u32 len) #define USE_SPI_DMA 0 -static const struct wilc1000_ops wilc1000_spi_ops; - static int wilc_bus_probe(struct spi_device *spi) { int ret, gpio; -- cgit From eec826439dbe1ad253bb7c4d54ed8777773ec630 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Wed, 20 Jan 2016 16:44:57 +0900 Subject: staging: wilc1000: remove redundant check in wilc_mq_recv At the beginning of wilc_mq_recv, it is checked if pHandle->bExiting is false or true. There is no need to check it again at the middle of this function. So just remove it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 098390cdf319..abc780c7686c 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -133,12 +133,6 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); down(&pHandle->hSem); - - if (pHandle->bExiting) { - PRINT_ER("pHandle fail\n"); - return -EFAULT; - } - spin_lock_irqsave(&pHandle->strCriticalSection, flags); pstrMessage = pHandle->pstrMessageList; -- cgit From d16791bfd52b628eb5759085f1a708c1843d10ef Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:31 +0900 Subject: staging: wilc1000: rename struct __Message_struct This patch renames typedef from struct __Message_struct and renames it to struct message. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index abc780c7686c..9b78fcd1291f 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -38,7 +38,7 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) } while (pHandle->pstrMessageList) { - Message *pstrMessge = pHandle->pstrMessageList->pstrNext; + struct message *pstrMessge = pHandle->pstrMessageList->pstrNext; kfree(pHandle->pstrMessageList); pHandle->pstrMessageList = pstrMessge; @@ -57,7 +57,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, const void *pvSendBuffer, u32 u32SendBufferSize) { unsigned long flags; - Message *pstrMessage = NULL; + struct message *pstrMessage = NULL; if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { PRINT_ER("pHandle or pvSendBuffer is null\n"); @@ -70,7 +70,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, } /* construct a new message */ - pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC); + pstrMessage = kmalloc(sizeof(struct message), GFP_ATOMIC); if (!pstrMessage) return -ENOMEM; @@ -89,7 +89,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, if (!pHandle->pstrMessageList) { pHandle->pstrMessageList = pstrMessage; } else { - Message *pstrTailMsg = pHandle->pstrMessageList; + struct message *pstrTailMsg = pHandle->pstrMessageList; while (pstrTailMsg->pstrNext) pstrTailMsg = pstrTailMsg->pstrNext; @@ -114,7 +114,7 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, void *pvRecvBuffer, u32 u32RecvBufferSize, u32 *pu32ReceivedLength) { - Message *pstrMessage; + struct message *pstrMessage; unsigned long flags; if ((!pHandle) || (u32RecvBufferSize == 0) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index d7e0328bacee..1a7c652df119 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -13,18 +13,18 @@ #include /* Message Queue type is a structure */ -typedef struct __Message_struct { +struct message { void *pvBuffer; u32 u32Length; - struct __Message_struct *pstrNext; -} Message; + struct message *pstrNext; +}; typedef struct __MessageQueue_struct { struct semaphore hSem; spinlock_t strCriticalSection; bool bExiting; u32 u32ReceiversCount; - Message *pstrMessageList; + struct message *pstrMessageList; } WILC_MsgQueueHandle; /*! -- cgit From 78d50f94f017b6e6becda2dce42462e473b23252 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:32 +0900 Subject: staging: wilc1000: rename pvBuffer in struct message This patch renames pvBuffer to buf to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 9b78fcd1291f..a4e612d51c67 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -76,9 +76,9 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, pstrMessage->u32Length = u32SendBufferSize; pstrMessage->pstrNext = NULL; - pstrMessage->pvBuffer = kmemdup(pvSendBuffer, u32SendBufferSize, - GFP_ATOMIC); - if (!pstrMessage->pvBuffer) { + pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, + GFP_ATOMIC); + if (!pstrMessage->buf) { kfree(pstrMessage); return -ENOMEM; } @@ -151,12 +151,12 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, /* consume the message */ pHandle->u32ReceiversCount--; - memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length); + memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->u32Length); *pu32ReceivedLength = pstrMessage->u32Length; pHandle->pstrMessageList = pstrMessage->pstrNext; - kfree(pstrMessage->pvBuffer); + kfree(pstrMessage->buf); kfree(pstrMessage); spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 1a7c652df119..848ed827a4b4 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -14,7 +14,7 @@ /* Message Queue type is a structure */ struct message { - void *pvBuffer; + void *buf; u32 u32Length; struct message *pstrNext; }; -- cgit From d3ff0580b9a7526f4292e2eca3a0f720d1c0f01b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:33 +0900 Subject: staging: wilc1000: rename u32Length in struct message This patch renames u32Length to len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index a4e612d51c67..0e66a649f638 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -74,7 +74,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, if (!pstrMessage) return -ENOMEM; - pstrMessage->u32Length = u32SendBufferSize; + pstrMessage->len = u32SendBufferSize; pstrMessage->pstrNext = NULL; pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, GFP_ATOMIC); @@ -142,7 +142,7 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, return -EFAULT; } /* check buffer size */ - if (u32RecvBufferSize < pstrMessage->u32Length) { + if (u32RecvBufferSize < pstrMessage->len) { spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); up(&pHandle->hSem); PRINT_ER("u32RecvBufferSize overflow\n"); @@ -151,8 +151,8 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, /* consume the message */ pHandle->u32ReceiversCount--; - memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->u32Length); - *pu32ReceivedLength = pstrMessage->u32Length; + memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); + *pu32ReceivedLength = pstrMessage->len; pHandle->pstrMessageList = pstrMessage->pstrNext; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 848ed827a4b4..b0ccd1de3765 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -15,7 +15,7 @@ /* Message Queue type is a structure */ struct message { void *buf; - u32 u32Length; + u32 len; struct message *pstrNext; }; -- cgit From 3356116124d8e868d5173afcfc86854994605e44 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:34 +0900 Subject: staging: wilc1000: rename pstrNext in struct message This patch renames pstrNext to next to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 12 ++++++------ drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 0e66a649f638..4d79a315662d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -38,7 +38,7 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) } while (pHandle->pstrMessageList) { - struct message *pstrMessge = pHandle->pstrMessageList->pstrNext; + struct message *pstrMessge = pHandle->pstrMessageList->next; kfree(pHandle->pstrMessageList); pHandle->pstrMessageList = pstrMessge; @@ -75,7 +75,7 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, return -ENOMEM; pstrMessage->len = u32SendBufferSize; - pstrMessage->pstrNext = NULL; + pstrMessage->next = NULL; pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, GFP_ATOMIC); if (!pstrMessage->buf) { @@ -91,10 +91,10 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, } else { struct message *pstrTailMsg = pHandle->pstrMessageList; - while (pstrTailMsg->pstrNext) - pstrTailMsg = pstrTailMsg->pstrNext; + while (pstrTailMsg->next) + pstrTailMsg = pstrTailMsg->next; - pstrTailMsg->pstrNext = pstrMessage; + pstrTailMsg->next = pstrMessage; } spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); @@ -154,7 +154,7 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; - pHandle->pstrMessageList = pstrMessage->pstrNext; + pHandle->pstrMessageList = pstrMessage->next; kfree(pstrMessage->buf); kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index b0ccd1de3765..ec503c356ee3 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -16,7 +16,7 @@ struct message { void *buf; u32 len; - struct message *pstrNext; + struct message *next; }; typedef struct __MessageQueue_struct { -- cgit From 5ba89554047425734caf59f4b744fc7c79c7b055 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:35 +0900 Subject: staging: wilc1000: rename struct WILC_MsgQueueHandle This patch removes typedef from struct WILC_MsgQueueHandle and renames it to struct message_queue. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_msgqueue.c | 14 +++++++------- drivers/staging/wilc1000/wilc_msgqueue.h | 18 +++++++++--------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5801d41ef988..79e8b7aa482b 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -229,7 +229,7 @@ static struct host_if_drv *terminated_handle; bool wilc_optaining_ip; static u8 P2P_LISTEN_STATE; static struct task_struct *hif_thread_handler; -static WILC_MsgQueueHandle hif_msg_q; +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; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 4d79a315662d..907bae19f494 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -11,7 +11,7 @@ * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_create(WILC_MsgQueueHandle *pHandle) +int wilc_mq_create(struct message_queue *pHandle) { spin_lock_init(&pHandle->strCriticalSection); sema_init(&pHandle->hSem, 0); @@ -27,7 +27,7 @@ int wilc_mq_create(WILC_MsgQueueHandle *pHandle) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) +int wilc_mq_destroy(struct message_queue *pHandle) { pHandle->bExiting = true; @@ -53,8 +53,8 @@ int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_send(WILC_MsgQueueHandle *pHandle, - const void *pvSendBuffer, u32 u32SendBufferSize) +int wilc_mq_send(struct message_queue *pHandle, + const void *pvSendBuffer, u32 u32SendBufferSize) { unsigned long flags; struct message *pstrMessage = NULL; @@ -110,9 +110,9 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, - void *pvRecvBuffer, u32 u32RecvBufferSize, - u32 *pu32ReceivedLength) +int wilc_mq_recv(struct message_queue *pHandle, + void *pvRecvBuffer, u32 u32RecvBufferSize, + u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index ec503c356ee3..111be463d335 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -19,13 +19,13 @@ struct message { struct message *next; }; -typedef struct __MessageQueue_struct { +struct message_queue { struct semaphore hSem; spinlock_t strCriticalSection; bool bExiting; u32 u32ReceiversCount; struct message *pstrMessageList; -} WILC_MsgQueueHandle; +}; /*! * @brief Creates a new Message queue @@ -40,7 +40,7 @@ typedef struct __MessageQueue_struct { * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_create(WILC_MsgQueueHandle *pHandle); +int wilc_mq_create(struct message_queue *pHandle); /*! * @brief Sends a message @@ -57,8 +57,8 @@ int wilc_mq_create(WILC_MsgQueueHandle *pHandle); * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_send(WILC_MsgQueueHandle *pHandle, - const void *pvSendBuffer, u32 u32SendBufferSize); +int wilc_mq_send(struct message_queue *pHandle, + const void *pvSendBuffer, u32 u32SendBufferSize); /*! * @brief Receives a message @@ -76,9 +76,9 @@ int wilc_mq_send(WILC_MsgQueueHandle *pHandle, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, - void *pvRecvBuffer, u32 u32RecvBufferSize, - u32 *pu32ReceivedLength); +int wilc_mq_recv(struct message_queue *pHandle, + void *pvRecvBuffer, u32 u32RecvBufferSize, + u32 *pu32ReceivedLength); /*! * @brief Destroys an existing Message queue @@ -89,6 +89,6 @@ int wilc_mq_recv(WILC_MsgQueueHandle *pHandle, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_destroy(WILC_MsgQueueHandle *pHandle); +int wilc_mq_destroy(struct message_queue *pHandle); #endif -- cgit From 9b849fd9ade195e4ca4b376f90184660e304dc51 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:36 +0900 Subject: staging: wilc1000: rename hSem in struct message_queue This patch renames hSem to sem to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 907bae19f494..b996c47af15d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -14,7 +14,7 @@ int wilc_mq_create(struct message_queue *pHandle) { spin_lock_init(&pHandle->strCriticalSection); - sema_init(&pHandle->hSem, 0); + sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; pHandle->u32ReceiversCount = 0; pHandle->bExiting = false; @@ -33,7 +33,7 @@ int wilc_mq_destroy(struct message_queue *pHandle) /* Release any waiting receiver thread. */ while (pHandle->u32ReceiversCount > 0) { - up(&pHandle->hSem); + up(&pHandle->sem); pHandle->u32ReceiversCount--; } @@ -99,7 +99,7 @@ int wilc_mq_send(struct message_queue *pHandle, spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); - up(&pHandle->hSem); + up(&pHandle->sem); return 0; } @@ -132,7 +132,7 @@ int wilc_mq_recv(struct message_queue *pHandle, pHandle->u32ReceiversCount++; spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); - down(&pHandle->hSem); + down(&pHandle->sem); spin_lock_irqsave(&pHandle->strCriticalSection, flags); pstrMessage = pHandle->pstrMessageList; @@ -144,7 +144,7 @@ int wilc_mq_recv(struct message_queue *pHandle, /* check buffer size */ if (u32RecvBufferSize < pstrMessage->len) { spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); - up(&pHandle->hSem); + up(&pHandle->sem); PRINT_ER("u32RecvBufferSize overflow\n"); return -EOVERFLOW; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 111be463d335..3ea40682cdf0 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -20,7 +20,7 @@ struct message { }; struct message_queue { - struct semaphore hSem; + struct semaphore sem; spinlock_t strCriticalSection; bool bExiting; u32 u32ReceiversCount; -- cgit From 3c09bb2e1eb0a4db3f297d2c70c0c1f553d7930e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:37 +0900 Subject: staging: wilc1000: rename strCriticalSection in struct message_queue This patch renames strCriticalSection to lock to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 18 +++++++++--------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index b996c47af15d..67bf147d7122 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -13,7 +13,7 @@ */ int wilc_mq_create(struct message_queue *pHandle) { - spin_lock_init(&pHandle->strCriticalSection); + spin_lock_init(&pHandle->lock); sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; pHandle->u32ReceiversCount = 0; @@ -83,7 +83,7 @@ int wilc_mq_send(struct message_queue *pHandle, return -ENOMEM; } - spin_lock_irqsave(&pHandle->strCriticalSection, flags); + spin_lock_irqsave(&pHandle->lock, flags); /* add it to the message queue */ if (!pHandle->pstrMessageList) { @@ -97,7 +97,7 @@ int wilc_mq_send(struct message_queue *pHandle, pstrTailMsg->next = pstrMessage; } - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); up(&pHandle->sem); @@ -128,22 +128,22 @@ int wilc_mq_recv(struct message_queue *pHandle, return -EFAULT; } - spin_lock_irqsave(&pHandle->strCriticalSection, flags); + spin_lock_irqsave(&pHandle->lock, flags); pHandle->u32ReceiversCount++; - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); down(&pHandle->sem); - spin_lock_irqsave(&pHandle->strCriticalSection, flags); + spin_lock_irqsave(&pHandle->lock, flags); pstrMessage = pHandle->pstrMessageList; if (!pstrMessage) { - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); PRINT_ER("pstrMessage is null\n"); return -EFAULT; } /* check buffer size */ if (u32RecvBufferSize < pstrMessage->len) { - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); up(&pHandle->sem); PRINT_ER("u32RecvBufferSize overflow\n"); return -EOVERFLOW; @@ -159,7 +159,7 @@ int wilc_mq_recv(struct message_queue *pHandle, kfree(pstrMessage->buf); kfree(pstrMessage); - spin_unlock_irqrestore(&pHandle->strCriticalSection, flags); + spin_unlock_irqrestore(&pHandle->lock, flags); return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 3ea40682cdf0..6cdebbf09c11 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -21,7 +21,7 @@ struct message { struct message_queue { struct semaphore sem; - spinlock_t strCriticalSection; + spinlock_t lock; bool bExiting; u32 u32ReceiversCount; struct message *pstrMessageList; -- cgit From c700cab3018cab34f510ba6e9fac5cbd6b030b1b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:38 +0900 Subject: staging: wilc1000: rename bExiting in struct message_queue This patch renames bExiting to exiting to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 67bf147d7122..47ba2564d931 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -17,7 +17,7 @@ int wilc_mq_create(struct message_queue *pHandle) sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; pHandle->u32ReceiversCount = 0; - pHandle->bExiting = false; + pHandle->exiting = false; return 0; } @@ -29,7 +29,7 @@ int wilc_mq_create(struct message_queue *pHandle) */ int wilc_mq_destroy(struct message_queue *pHandle) { - pHandle->bExiting = true; + pHandle->exiting = true; /* Release any waiting receiver thread. */ while (pHandle->u32ReceiversCount > 0) { @@ -64,7 +64,7 @@ int wilc_mq_send(struct message_queue *pHandle, return -EFAULT; } - if (pHandle->bExiting) { + if (pHandle->exiting) { PRINT_ER("pHandle fail\n"); return -EFAULT; } @@ -123,7 +123,7 @@ int wilc_mq_recv(struct message_queue *pHandle, return -EINVAL; } - if (pHandle->bExiting) { + if (pHandle->exiting) { PRINT_ER("pHandle fail\n"); return -EFAULT; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 6cdebbf09c11..2c21b3e5cd3f 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -22,7 +22,7 @@ struct message { struct message_queue { struct semaphore sem; spinlock_t lock; - bool bExiting; + bool exiting; u32 u32ReceiversCount; struct message *pstrMessageList; }; -- cgit From ec815ec5fd57e1ce016485336a68b8ab73316653 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:39 +0900 Subject: staging: wilc1000: rename u32ReceiversCount in struct message_queue This patch renames u32ReceiversCount to recv_count to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 10 +++++----- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 47ba2564d931..363e00389d22 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -16,7 +16,7 @@ int wilc_mq_create(struct message_queue *pHandle) spin_lock_init(&pHandle->lock); sema_init(&pHandle->sem, 0); pHandle->pstrMessageList = NULL; - pHandle->u32ReceiversCount = 0; + pHandle->recv_count = 0; pHandle->exiting = false; return 0; } @@ -32,9 +32,9 @@ int wilc_mq_destroy(struct message_queue *pHandle) pHandle->exiting = true; /* Release any waiting receiver thread. */ - while (pHandle->u32ReceiversCount > 0) { + while (pHandle->recv_count > 0) { up(&pHandle->sem); - pHandle->u32ReceiversCount--; + pHandle->recv_count--; } while (pHandle->pstrMessageList) { @@ -129,7 +129,7 @@ int wilc_mq_recv(struct message_queue *pHandle, } spin_lock_irqsave(&pHandle->lock, flags); - pHandle->u32ReceiversCount++; + pHandle->recv_count++; spin_unlock_irqrestore(&pHandle->lock, flags); down(&pHandle->sem); @@ -150,7 +150,7 @@ int wilc_mq_recv(struct message_queue *pHandle, } /* consume the message */ - pHandle->u32ReceiversCount--; + pHandle->recv_count--; memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 2c21b3e5cd3f..dcf54ea4a874 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -23,7 +23,7 @@ struct message_queue { struct semaphore sem; spinlock_t lock; bool exiting; - u32 u32ReceiversCount; + u32 recv_count; struct message *pstrMessageList; }; -- cgit From f9d26e21a874ce0799e5c0e54e0e6b473b3c0286 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:40 +0900 Subject: staging: wilc1000: rename pstrMessageList in struct message_queue This patch renames pstrMessageList to msg_list to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 20 ++++++++++---------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 363e00389d22..d13c9a76ab92 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -15,7 +15,7 @@ int wilc_mq_create(struct message_queue *pHandle) { spin_lock_init(&pHandle->lock); sema_init(&pHandle->sem, 0); - pHandle->pstrMessageList = NULL; + pHandle->msg_list = NULL; pHandle->recv_count = 0; pHandle->exiting = false; return 0; @@ -37,11 +37,11 @@ int wilc_mq_destroy(struct message_queue *pHandle) pHandle->recv_count--; } - while (pHandle->pstrMessageList) { - struct message *pstrMessge = pHandle->pstrMessageList->next; + while (pHandle->msg_list) { + struct message *pstrMessge = pHandle->msg_list->next; - kfree(pHandle->pstrMessageList); - pHandle->pstrMessageList = pstrMessge; + kfree(pHandle->msg_list); + pHandle->msg_list = pstrMessge; } return 0; @@ -86,10 +86,10 @@ int wilc_mq_send(struct message_queue *pHandle, spin_lock_irqsave(&pHandle->lock, flags); /* add it to the message queue */ - if (!pHandle->pstrMessageList) { - pHandle->pstrMessageList = pstrMessage; + if (!pHandle->msg_list) { + pHandle->msg_list = pstrMessage; } else { - struct message *pstrTailMsg = pHandle->pstrMessageList; + struct message *pstrTailMsg = pHandle->msg_list; while (pstrTailMsg->next) pstrTailMsg = pstrTailMsg->next; @@ -135,7 +135,7 @@ int wilc_mq_recv(struct message_queue *pHandle, down(&pHandle->sem); spin_lock_irqsave(&pHandle->lock, flags); - pstrMessage = pHandle->pstrMessageList; + pstrMessage = pHandle->msg_list; if (!pstrMessage) { spin_unlock_irqrestore(&pHandle->lock, flags); PRINT_ER("pstrMessage is null\n"); @@ -154,7 +154,7 @@ int wilc_mq_recv(struct message_queue *pHandle, memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; - pHandle->pstrMessageList = pstrMessage->next; + pHandle->msg_list = pstrMessage->next; kfree(pstrMessage->buf); kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index dcf54ea4a874..7e7ec06b132e 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -24,7 +24,7 @@ struct message_queue { spinlock_t lock; bool exiting; u32 recv_count; - struct message *pstrMessageList; + struct message *msg_list; }; /*! -- cgit From 2cc08b4f2645c3689b48c0b94245fc2ef93556c3 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:41 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_create This patch renames pHandle to mq to avoid camelcase Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 12 ++++++------ drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index d13c9a76ab92..453fa197738d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -11,13 +11,13 @@ * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_create(struct message_queue *pHandle) +int wilc_mq_create(struct message_queue *mq) { - spin_lock_init(&pHandle->lock); - sema_init(&pHandle->sem, 0); - pHandle->msg_list = NULL; - pHandle->recv_count = 0; - pHandle->exiting = false; + spin_lock_init(&mq->lock); + sema_init(&mq->sem, 0); + mq->msg_list = NULL; + mq->recv_count = 0; + mq->exiting = false; return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 7e7ec06b132e..bfd2347e5497 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -40,7 +40,7 @@ struct message_queue { * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_create(struct message_queue *pHandle); +int wilc_mq_create(struct message_queue *mq); /*! * @brief Sends a message -- cgit From d742f67ee129261ad37a88d8d0d7a36c81ace631 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:42 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_destroy This patch renames pHandle to mq to avoid camelcase Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 18 +++++++++--------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 453fa197738d..103fcfd9148a 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -27,21 +27,21 @@ int wilc_mq_create(struct message_queue *mq) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_destroy(struct message_queue *pHandle) +int wilc_mq_destroy(struct message_queue *mq) { - pHandle->exiting = true; + mq->exiting = true; /* Release any waiting receiver thread. */ - while (pHandle->recv_count > 0) { - up(&pHandle->sem); - pHandle->recv_count--; + while (mq->recv_count > 0) { + up(&mq->sem); + mq->recv_count--; } - while (pHandle->msg_list) { - struct message *pstrMessge = pHandle->msg_list->next; + while (mq->msg_list) { + struct message *pstrMessge = mq->msg_list->next; - kfree(pHandle->msg_list); - pHandle->msg_list = pstrMessge; + kfree(mq->msg_list); + mq->msg_list = pstrMessge; } return 0; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index bfd2347e5497..b91822e95ee9 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -89,6 +89,6 @@ int wilc_mq_recv(struct message_queue *pHandle, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_destroy(struct message_queue *pHandle); +int wilc_mq_destroy(struct message_queue *mq); #endif -- cgit From fca978b718628e5c9ddd0a94f7fdaf7040bea1c4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:43 +0900 Subject: staging: wilc1000: rename pstrMessge in wilc_mq_destroy This patch renames pstrMessge to msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 103fcfd9148a..a01420a9a729 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -38,10 +38,10 @@ int wilc_mq_destroy(struct message_queue *mq) } while (mq->msg_list) { - struct message *pstrMessge = mq->msg_list->next; + struct message *msg = mq->msg_list->next; kfree(mq->msg_list); - mq->msg_list = pstrMessge; + mq->msg_list = msg; } return 0; -- cgit From 5eb359756f3b881cd52d26f257cde95f162177ec Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:44 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_send This patch renames pHandle to mq to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 22 +++++++++++----------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index a01420a9a729..71ce1f585c3c 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -53,19 +53,19 @@ int wilc_mq_destroy(struct message_queue *mq) * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_send(struct message_queue *pHandle, +int wilc_mq_send(struct message_queue *mq, const void *pvSendBuffer, u32 u32SendBufferSize) { unsigned long flags; struct message *pstrMessage = NULL; - if ((!pHandle) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { - PRINT_ER("pHandle or pvSendBuffer is null\n"); + if ((!mq) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { + PRINT_ER("mq or pvSendBuffer is null\n"); return -EFAULT; } - if (pHandle->exiting) { - PRINT_ER("pHandle fail\n"); + if (mq->exiting) { + PRINT_ER("mq fail\n"); return -EFAULT; } @@ -83,13 +83,13 @@ int wilc_mq_send(struct message_queue *pHandle, return -ENOMEM; } - spin_lock_irqsave(&pHandle->lock, flags); + spin_lock_irqsave(&mq->lock, flags); /* add it to the message queue */ - if (!pHandle->msg_list) { - pHandle->msg_list = pstrMessage; + if (!mq->msg_list) { + mq->msg_list = pstrMessage; } else { - struct message *pstrTailMsg = pHandle->msg_list; + struct message *pstrTailMsg = mq->msg_list; while (pstrTailMsg->next) pstrTailMsg = pstrTailMsg->next; @@ -97,9 +97,9 @@ int wilc_mq_send(struct message_queue *pHandle, pstrTailMsg->next = pstrMessage; } - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_unlock_irqrestore(&mq->lock, flags); - up(&pHandle->sem); + up(&mq->sem); return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index b91822e95ee9..e6cdc10fb1da 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -57,7 +57,7 @@ int wilc_mq_create(struct message_queue *mq); * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_send(struct message_queue *pHandle, +int wilc_mq_send(struct message_queue *mq, const void *pvSendBuffer, u32 u32SendBufferSize); /*! -- cgit From 832f4fa5f10fed19f3fe20609a87d1fe09fc7d0e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:45 +0900 Subject: staging: wilc1000: rename pvSendBuffer in wilc_mq_send This patch renames pvSendBuffer to send_buf to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 71ce1f585c3c..5feb87c88e0d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -54,13 +54,13 @@ int wilc_mq_destroy(struct message_queue *mq) * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *pvSendBuffer, u32 u32SendBufferSize) + const void *send_buf, u32 u32SendBufferSize) { unsigned long flags; struct message *pstrMessage = NULL; - if ((!mq) || (u32SendBufferSize == 0) || (!pvSendBuffer)) { - PRINT_ER("mq or pvSendBuffer is null\n"); + if ((!mq) || (u32SendBufferSize == 0) || (!send_buf)) { + PRINT_ER("mq or send_buf is null\n"); return -EFAULT; } @@ -76,7 +76,7 @@ int wilc_mq_send(struct message_queue *mq, pstrMessage->len = u32SendBufferSize; pstrMessage->next = NULL; - pstrMessage->buf = kmemdup(pvSendBuffer, u32SendBufferSize, + pstrMessage->buf = kmemdup(send_buf, u32SendBufferSize, GFP_ATOMIC); if (!pstrMessage->buf) { kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index e6cdc10fb1da..3adee906c517 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -58,7 +58,7 @@ int wilc_mq_create(struct message_queue *mq); * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *pvSendBuffer, u32 u32SendBufferSize); + const void *send_buf, u32 u32SendBufferSize); /*! * @brief Receives a message -- cgit From 81e886e0b7d00c1e6c8bd820fb66a4144361020b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:46 +0900 Subject: staging: wilc1000: rename u32SendBufferSize in wilc_mq_send This patch renames u32SendBufferSize to send_buf_size to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 5feb87c88e0d..8e37cff02f9d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -54,12 +54,12 @@ int wilc_mq_destroy(struct message_queue *mq) * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *send_buf, u32 u32SendBufferSize) + const void *send_buf, u32 send_buf_size) { unsigned long flags; struct message *pstrMessage = NULL; - if ((!mq) || (u32SendBufferSize == 0) || (!send_buf)) { + if ((!mq) || (send_buf_size == 0) || (!send_buf)) { PRINT_ER("mq or send_buf is null\n"); return -EFAULT; } @@ -74,9 +74,9 @@ int wilc_mq_send(struct message_queue *mq, if (!pstrMessage) return -ENOMEM; - pstrMessage->len = u32SendBufferSize; + pstrMessage->len = send_buf_size; pstrMessage->next = NULL; - pstrMessage->buf = kmemdup(send_buf, u32SendBufferSize, + pstrMessage->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); if (!pstrMessage->buf) { kfree(pstrMessage); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 3adee906c517..70e1be11a700 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -58,7 +58,7 @@ int wilc_mq_create(struct message_queue *mq); * @version 1.0 */ int wilc_mq_send(struct message_queue *mq, - const void *send_buf, u32 u32SendBufferSize); + const void *send_buf, u32 send_buf_size); /*! * @brief Receives a message -- cgit From 669fd5077fede8af2aa6693280e38a37ef1efba1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:47 +0900 Subject: staging: wilc1000: rename pstrMessage in wilc_mq_send This patch renames pstrMessage to new_msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 8e37cff02f9d..9a80fe694822 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -57,7 +57,7 @@ int wilc_mq_send(struct message_queue *mq, const void *send_buf, u32 send_buf_size) { unsigned long flags; - struct message *pstrMessage = NULL; + struct message *new_msg = NULL; if ((!mq) || (send_buf_size == 0) || (!send_buf)) { PRINT_ER("mq or send_buf is null\n"); @@ -70,16 +70,15 @@ int wilc_mq_send(struct message_queue *mq, } /* construct a new message */ - pstrMessage = kmalloc(sizeof(struct message), GFP_ATOMIC); - if (!pstrMessage) + new_msg = kmalloc(sizeof(struct message), GFP_ATOMIC); + if (!new_msg) return -ENOMEM; - pstrMessage->len = send_buf_size; - pstrMessage->next = NULL; - pstrMessage->buf = kmemdup(send_buf, send_buf_size, - GFP_ATOMIC); - if (!pstrMessage->buf) { - kfree(pstrMessage); + new_msg->len = send_buf_size; + new_msg->next = NULL; + new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); + if (!new_msg->buf) { + kfree(new_msg); return -ENOMEM; } @@ -87,14 +86,14 @@ int wilc_mq_send(struct message_queue *mq, /* add it to the message queue */ if (!mq->msg_list) { - mq->msg_list = pstrMessage; + mq->msg_list = new_msg; } else { struct message *pstrTailMsg = mq->msg_list; while (pstrTailMsg->next) pstrTailMsg = pstrTailMsg->next; - pstrTailMsg->next = pstrMessage; + pstrTailMsg->next = new_msg; } spin_unlock_irqrestore(&mq->lock, flags); -- cgit From bd07b0076b465712804a5b01609dbe8fba9b9110 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:48 +0900 Subject: staging: wilc1000: rename pstrTailMsg in wilc_mq_send This patch renames pstrTailMsg to tail_msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 9a80fe694822..764723f99996 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -88,12 +88,12 @@ int wilc_mq_send(struct message_queue *mq, if (!mq->msg_list) { mq->msg_list = new_msg; } else { - struct message *pstrTailMsg = mq->msg_list; + struct message *tail_msg = mq->msg_list; - while (pstrTailMsg->next) - pstrTailMsg = pstrTailMsg->next; + while (tail_msg->next) + tail_msg = tail_msg->next; - pstrTailMsg->next = new_msg; + tail_msg->next = new_msg; } spin_unlock_irqrestore(&mq->lock, flags); -- cgit From dee1bf76d96783a902a9aa5804e6a108f283b2d1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:49 +0900 Subject: staging: wilc1000: fix return error code Three argument are checked at the beginning of wilc_mq_send whether they are valid arguments or not. It is correct to use return error code as -EINVAL, not -EFAULT. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 764723f99996..361ca8fbac31 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -61,7 +61,7 @@ int wilc_mq_send(struct message_queue *mq, if ((!mq) || (send_buf_size == 0) || (!send_buf)) { PRINT_ER("mq or send_buf is null\n"); - return -EFAULT; + return -EINVAL; } if (mq->exiting) { -- cgit From 24752783baae2cfdd061140a61797957963bf069 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:50 +0900 Subject: staging: wilc1000: rename pHandle in wilc_mq_recv This patch renames pHandle to mq to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 34 ++++++++++++++++---------------- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 361ca8fbac31..d2df1795facb 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -109,56 +109,56 @@ int wilc_mq_send(struct message_queue *mq, * @note copied from FLO glue implementatuion * @version 1.0 */ -int wilc_mq_recv(struct message_queue *pHandle, +int wilc_mq_recv(struct message_queue *mq, void *pvRecvBuffer, u32 u32RecvBufferSize, u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; - if ((!pHandle) || (u32RecvBufferSize == 0) + if ((!mq) || (u32RecvBufferSize == 0) || (!pvRecvBuffer) || (!pu32ReceivedLength)) { - PRINT_ER("pHandle or pvRecvBuffer is null\n"); + PRINT_ER("mq or pvRecvBuffer is null\n"); return -EINVAL; } - if (pHandle->exiting) { - PRINT_ER("pHandle fail\n"); + if (mq->exiting) { + PRINT_ER("mq fail\n"); return -EFAULT; } - spin_lock_irqsave(&pHandle->lock, flags); - pHandle->recv_count++; - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_lock_irqsave(&mq->lock, flags); + mq->recv_count++; + spin_unlock_irqrestore(&mq->lock, flags); - down(&pHandle->sem); - spin_lock_irqsave(&pHandle->lock, flags); + down(&mq->sem); + spin_lock_irqsave(&mq->lock, flags); - pstrMessage = pHandle->msg_list; + pstrMessage = mq->msg_list; if (!pstrMessage) { - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_unlock_irqrestore(&mq->lock, flags); PRINT_ER("pstrMessage is null\n"); return -EFAULT; } /* check buffer size */ if (u32RecvBufferSize < pstrMessage->len) { - spin_unlock_irqrestore(&pHandle->lock, flags); - up(&pHandle->sem); + spin_unlock_irqrestore(&mq->lock, flags); + up(&mq->sem); PRINT_ER("u32RecvBufferSize overflow\n"); return -EOVERFLOW; } /* consume the message */ - pHandle->recv_count--; + mq->recv_count--; memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; - pHandle->msg_list = pstrMessage->next; + mq->msg_list = pstrMessage->next; kfree(pstrMessage->buf); kfree(pstrMessage); - spin_unlock_irqrestore(&pHandle->lock, flags); + spin_unlock_irqrestore(&mq->lock, flags); return 0; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 70e1be11a700..0c1eead47b42 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -76,7 +76,7 @@ int wilc_mq_send(struct message_queue *mq, * @date 30 Aug 2010 * @version 1.0 */ -int wilc_mq_recv(struct message_queue *pHandle, +int wilc_mq_recv(struct message_queue *mq, void *pvRecvBuffer, u32 u32RecvBufferSize, u32 *pu32ReceivedLength); -- cgit From f034b01ea6236442c391c7d22623cd440d778de1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:51 +0900 Subject: staging: wilc1000: rename pvRecvBuffer in wilc_mq_recv This patch renames pvRecvBuffer to recv_buf to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index d2df1795facb..b836b2eac5cc 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -110,15 +110,15 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *pvRecvBuffer, u32 u32RecvBufferSize, + void *recv_buf, u32 u32RecvBufferSize, u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; if ((!mq) || (u32RecvBufferSize == 0) - || (!pvRecvBuffer) || (!pu32ReceivedLength)) { - PRINT_ER("mq or pvRecvBuffer is null\n"); + || (!recv_buf) || (!pu32ReceivedLength)) { + PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; } @@ -150,7 +150,7 @@ int wilc_mq_recv(struct message_queue *mq, /* consume the message */ mq->recv_count--; - memcpy(pvRecvBuffer, pstrMessage->buf, pstrMessage->len); + memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); *pu32ReceivedLength = pstrMessage->len; mq->msg_list = pstrMessage->next; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 0c1eead47b42..81b51dd88e6b 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -77,7 +77,7 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *pvRecvBuffer, u32 u32RecvBufferSize, + void *recv_buf, u32 u32RecvBufferSize, u32 *pu32ReceivedLength); /*! -- cgit From e8f2d1f19c6b18f2dbf2661311f4456850450a5f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:52 +0900 Subject: staging: wilc1000: rename u32RecvBufferSize in wilc_mq_recv This patch renames u32RecvBufferSize to recv_buf_size to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 8 ++++---- drivers/staging/wilc1000/wilc_msgqueue.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index b836b2eac5cc..c86bd7c6b72d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -110,13 +110,13 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 u32RecvBufferSize, + void *recv_buf, u32 recv_buf_size, u32 *pu32ReceivedLength) { struct message *pstrMessage; unsigned long flags; - if ((!mq) || (u32RecvBufferSize == 0) + if ((!mq) || (recv_buf_size == 0) || (!recv_buf) || (!pu32ReceivedLength)) { PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; @@ -141,10 +141,10 @@ int wilc_mq_recv(struct message_queue *mq, return -EFAULT; } /* check buffer size */ - if (u32RecvBufferSize < pstrMessage->len) { + if (recv_buf_size < pstrMessage->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); - PRINT_ER("u32RecvBufferSize overflow\n"); + PRINT_ER("recv_buf_size overflow\n"); return -EOVERFLOW; } diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 81b51dd88e6b..3804b3bf4f01 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -77,7 +77,7 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 u32RecvBufferSize, + void *recv_buf, u32 recv_buf_size, u32 *pu32ReceivedLength); /*! -- cgit From 62082cbe723299129948b35b15a18d2567cec651 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:53 +0900 Subject: staging: wilc1000: rename pu32ReceivedLength in wilc_mq_recv This patch renames pu32ReceivedLength to recv_len to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 7 +++---- drivers/staging/wilc1000/wilc_msgqueue.h | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index c86bd7c6b72d..5601de86656f 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -110,14 +110,13 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 recv_buf_size, - u32 *pu32ReceivedLength) + void *recv_buf, u32 recv_buf_size, u32 *recv_len) { struct message *pstrMessage; unsigned long flags; if ((!mq) || (recv_buf_size == 0) - || (!recv_buf) || (!pu32ReceivedLength)) { + || (!recv_buf) || (!recv_len)) { PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; } @@ -151,7 +150,7 @@ int wilc_mq_recv(struct message_queue *mq, /* consume the message */ mq->recv_count--; memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); - *pu32ReceivedLength = pstrMessage->len; + *recv_len = pstrMessage->len; mq->msg_list = pstrMessage->next; diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 3804b3bf4f01..4f79ead933ba 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -77,8 +77,7 @@ int wilc_mq_send(struct message_queue *mq, * @version 1.0 */ int wilc_mq_recv(struct message_queue *mq, - void *recv_buf, u32 recv_buf_size, - u32 *pu32ReceivedLength); + void *recv_buf, u32 recv_buf_size, u32 *recv_len); /*! * @brief Destroys an existing Message queue -- cgit From 5b8e7ba9fdb01323867d8df6b6758527f9b87b81 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:54 +0900 Subject: staging: wilc1000: rename pstrMessage in wilc_mq_recv This patch renames pstrMessage to msg to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 5601de86656f..71077157033c 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -112,7 +112,7 @@ int wilc_mq_send(struct message_queue *mq, int wilc_mq_recv(struct message_queue *mq, void *recv_buf, u32 recv_buf_size, u32 *recv_len) { - struct message *pstrMessage; + struct message *msg; unsigned long flags; if ((!mq) || (recv_buf_size == 0) @@ -133,14 +133,14 @@ int wilc_mq_recv(struct message_queue *mq, down(&mq->sem); spin_lock_irqsave(&mq->lock, flags); - pstrMessage = mq->msg_list; - if (!pstrMessage) { + msg = mq->msg_list; + if (!msg) { spin_unlock_irqrestore(&mq->lock, flags); - PRINT_ER("pstrMessage is null\n"); + PRINT_ER("msg is null\n"); return -EFAULT; } /* check buffer size */ - if (recv_buf_size < pstrMessage->len) { + if (recv_buf_size < msg->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); PRINT_ER("recv_buf_size overflow\n"); @@ -149,13 +149,13 @@ int wilc_mq_recv(struct message_queue *mq, /* consume the message */ mq->recv_count--; - memcpy(recv_buf, pstrMessage->buf, pstrMessage->len); - *recv_len = pstrMessage->len; + memcpy(recv_buf, msg->buf, msg->len); + *recv_len = msg->len; - mq->msg_list = pstrMessage->next; + mq->msg_list = msg->next; - kfree(pstrMessage->buf); - kfree(pstrMessage); + kfree(msg->buf); + kfree(msg); spin_unlock_irqrestore(&mq->lock, flags); -- cgit From 7adf4f312bb7e1f3bda90ed048d78a5a55099f10 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:55 +0900 Subject: staging: wilc1000: fix coding style of kmalloc usage This patch fixes coding style of kmalloc usage found by checkpatch. CHECK: Prefer kmalloc(sizeof(*new_msg)...) over kmalloc(sizeof(struct message)...) Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 71077157033c..c7a60f44db77 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -70,7 +70,7 @@ int wilc_mq_send(struct message_queue *mq, } /* construct a new message */ - new_msg = kmalloc(sizeof(struct message), GFP_ATOMIC); + new_msg = kmalloc(sizeof(*new_msg), GFP_ATOMIC); if (!new_msg) return -ENOMEM; -- cgit From 2c8e2dcb88bcd1c875e0d8f0581f18199073ec33 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:56 +0900 Subject: staging: wilc1000: fix logical continuations This patch fixes logical continuations found by checkpatch CHECK: Logical continuations should be on the previous line Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index c7a60f44db77..4493ca9adcce 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -115,8 +115,7 @@ int wilc_mq_recv(struct message_queue *mq, struct message *msg; unsigned long flags; - if ((!mq) || (recv_buf_size == 0) - || (!recv_buf) || (!recv_len)) { + if ((!mq) || (recv_buf_size == 0) || (!recv_buf) || (!recv_len)) { PRINT_ER("mq or recv_buf is null\n"); return -EINVAL; } -- cgit From 734fadce60a810beb9471d260e5e8af820d50b1d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 21 Jan 2016 20:30:57 +0900 Subject: staging: wilc1000: remove over-commenting There are over-commenting in wilc_msgqueue.h file. This comment is not explain exactly what codes do and make checkpatch warning about "line over 80 charcters". If necessary, comment will be added later with preferred coding style. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.h | 66 -------------------------------- 1 file changed, 66 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index 4f79ead933ba..ddd0984337ea 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -1,18 +1,8 @@ #ifndef __WILC_MSG_QUEUE_H__ #define __WILC_MSG_QUEUE_H__ -/*! - * @file wilc_msgqueue.h - * @brief Message Queue OS wrapper functionality - * @author syounan - * @sa wilc_oswrapper.h top level OS wrapper file - * @date 30 Aug 2010 - * @version 1.0 - */ - #include -/* Message Queue type is a structure */ struct message { void *buf; u32 len; @@ -27,67 +17,11 @@ struct message_queue { struct message *msg_list; }; -/*! - * @brief Creates a new Message queue - * @details Creates a new Message queue, if the feature - * CONFIG_WILC_MSG_QUEUE_IPC_NAME is enabled and pstrAttrs->pcName - * is not Null, then this message queue can be used for IPC with - * any other message queue having the same name in the system - * @param[in,out] pHandle handle to the message queue object - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_create(struct message_queue *mq); - -/*! - * @brief Sends a message - * @details Sends a message, this API will block until the message is - * actually sent or until it is timedout (as long as the feature - * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout - * is not set to WILC_OS_INFINITY), zero timeout is a valid value - * @param[in] pHandle handle to the message queue object - * @param[in] pvSendBuffer pointer to the data to send - * @param[in] u32SendBufferSize the size of the data to send - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_send(struct message_queue *mq, const void *send_buf, u32 send_buf_size); - -/*! - * @brief Receives a message - * @details Receives a message, this API will block until a message is - * received or until it is timedout (as long as the feature - * CONFIG_WILC_MSG_QUEUE_TIMEOUT is enabled and pstrAttrs->u32Timeout - * is not set to WILC_OS_INFINITY), zero timeout is a valid value - * @param[in] pHandle handle to the message queue object - * @param[out] pvRecvBuffer pointer to a buffer to fill with the received message - * @param[in] u32RecvBufferSize the size of the receive buffer - * @param[out] pu32ReceivedLength the length of received data - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_recv(struct message_queue *mq, void *recv_buf, u32 recv_buf_size, u32 *recv_len); - -/*! - * @brief Destroys an existing Message queue - * @param[in] pHandle handle to the message queue object - * @param[in] pstrAttrs Optional attributes, NULL for default - * @return Error code indicating success/failure - * @author syounan - * @date 30 Aug 2010 - * @version 1.0 - */ int wilc_mq_destroy(struct message_queue *mq); #endif -- cgit From 0c94df023602803fe4eaeb655510f5230b245beb Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:05 +0900 Subject: staging: wilc1000: fix bug when changing virtual interface This patch fixes a bug connection error when changing virtual interface to p2p. Variable quit needs to be set 0 when wilc is reinitialized again. Fixes : 67e2a07ed800 ("staging: wilc1000: move all of wilc_wlan_dev_t to struct wilc") Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 0b62cc5df488..07627b6ef8ec 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1588,6 +1588,8 @@ int wilc_wlan_init(struct net_device *dev) PRINT_D(INIT_DBG, "Initializing WILC_Wlan ...\n"); + wilc->quit = 0; + if (!wilc->hif_func->hif_init(wilc)) { ret = -EIO; goto _fail_; -- cgit From 33c64975e3ebb5ce2301005ab3602dbb2fdf1cd0 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:06 +0900 Subject: staging: wilc1000: remove define WILC_OPTIMIZE_SLEEP_INT Take the codes of WILC_OPTIMIZE_SLEEP_INT and remove codes inside ifndef. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 74 +----------------------------------- 1 file changed, 2 insertions(+), 72 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 07627b6ef8ec..e2ac0412014e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -3,9 +3,7 @@ #include "wilc_wfi_netdevice.h" #include "wilc_wlan_cfg.h" -#ifdef WILC_OPTIMIZE_SLEEP_INT static inline void chip_allow_sleep(struct wilc *wilc); -#endif static inline void chip_wakeup(struct wilc *wilc); static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ; @@ -29,21 +27,14 @@ static CHIP_PS_STATE_T chip_ps_state = CHIP_WAKEDUP; static inline void acquire_bus(struct wilc *wilc, BUS_ACQUIRE_T acquire) { mutex_lock(&wilc->hif_cs); - #ifndef WILC_OPTIMIZE_SLEEP_INT - if (chip_ps_state != CHIP_WAKEDUP) - #endif - { - if (acquire == ACQUIRE_AND_WAKEUP) - chip_wakeup(wilc); - } + if (acquire == ACQUIRE_AND_WAKEUP) + chip_wakeup(wilc); } static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release) { - #ifdef WILC_OPTIMIZE_SLEEP_INT if (release == RELEASE_ALLOW_SLEEP) chip_allow_sleep(wilc); - #endif mutex_unlock(&wilc->hif_cs); } @@ -524,8 +515,6 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) return NULL; } -#ifdef WILC_OPTIMIZE_SLEEP_INT - static inline void chip_allow_sleep(struct wilc *wilc) { u32 reg = 0; @@ -538,7 +527,6 @@ static inline void chip_allow_sleep(struct wilc *wilc) static inline void chip_wakeup(struct wilc *wilc) { u32 reg, clk_status_reg, trials = 0; - u32 sleep_time; if ((wilc->io_type & 0x1) == HIF_SPI) { do { @@ -597,66 +585,14 @@ static inline void chip_wakeup(struct wilc *wilc) } chip_ps_state = CHIP_WAKEDUP; } -#else -static inline void chip_wakeup(struct wilc *wilc) -{ - u32 reg, trials = 0; - - do { - if ((wilc->io_type & 0x1) == HIF_SPI) { - wilc->hif_func->hif_read_reg(wilc, 1, ®); - wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1)); - wilc->hif_func->hif_write_reg(wilc, 1, reg | BIT(1)); - wilc->hif_func->hif_write_reg(wilc, 1, reg & ~BIT(1)); - } else if ((wilc->io_type & 0x1) == HIF_SDIO) { - wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); - wilc->hif_func->hif_write_reg(wilc, 0xf0, - reg & ~BIT(0)); - wilc->hif_func->hif_write_reg(wilc, 0xf0, - reg | BIT(0)); - wilc->hif_func->hif_write_reg(wilc, 0xf0, - reg & ~BIT(0)); - } - - do { - mdelay(3); - - if ((wilc_get_chipid(wilc, true) == 0)) - wilc_debug(N_ERR, "Couldn't read chip id. Wake up failed\n"); - - } while ((wilc_get_chipid(wilc, true) == 0) && ((++trials % 3) == 0)); - - } while (wilc_get_chipid(wilc, true) == 0); - if (chip_ps_state == CHIP_SLEEPING_MANUAL) { - wilc->hif_func->hif_read_reg(wilc, 0x1C0C, ®); - reg &= ~BIT(0); - wilc->hif_func->hif_write_reg(wilc, 0x1C0C, reg); - - if (wilc_get_chipid(wilc, false) >= 0x1002b0) { - u32 val32; - - wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32); - val32 |= BIT(6); - wilc->hif_func->hif_write_reg(wilc, 0x1e1c, val32); - - wilc->hif_func->hif_read_reg(wilc, 0x1e9c, &val32); - val32 |= BIT(6); - wilc->hif_func->hif_write_reg(wilc, 0x1e9c, val32); - } - } - chip_ps_state = CHIP_WAKEDUP; -} -#endif void wilc_chip_sleep_manually(struct wilc *wilc) { if (chip_ps_state != CHIP_WAKEDUP) return; acquire_bus(wilc, ACQUIRE_ONLY); -#ifdef WILC_OPTIMIZE_SLEEP_INT chip_allow_sleep(wilc); -#endif wilc->hif_func->hif_write_reg(wilc, 0x10a8, 1); chip_ps_state = CHIP_SLEEPING_MANUAL; @@ -1041,9 +977,6 @@ static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) { wilc->hif_func->hif_clear_int_ext(wilc, SLEEP_INT_CLR); -#ifndef WILC_OPTIMIZE_SLEEP_INT - chip_ps_state = CHIP_SLEEPING_AUTO; -#endif } static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) @@ -1113,9 +1046,6 @@ void wilc_handle_isr(struct wilc *wilc) if (int_status & DATA_INT_EXT) { wilc_wlan_handle_isr_ext(wilc, int_status); - #ifndef WILC_OPTIMIZE_SLEEP_INT - chip_ps_state = CHIP_WAKEDUP; - #endif } if (int_status & SLEEP_INT_EXT) wilc_sleeptimer_isr_ext(wilc, int_status); -- cgit From fdc2ac1aafc62dfea1ae116f832ff1874104a0ee Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:07 +0900 Subject: staging: wilc1000: support suspend/resume functionality wilc supports suspend/resume functionality. Introduce new sleep and wakeup functions and remove old codes since that will be handled in the new functions. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 31 +++++++++++++++++++------------ drivers/staging/wilc1000/wilc_wlan.h | 4 +++- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index e2ac0412014e..d824606a248b 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -522,6 +522,7 @@ static inline void chip_allow_sleep(struct wilc *wilc) wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0)); + wilc->hif_func->hif_write_reg(wilc, 0xfa, 0); } static inline void chip_wakeup(struct wilc *wilc) @@ -543,6 +544,8 @@ static inline void chip_wakeup(struct wilc *wilc) } while (wilc_get_chipid(wilc, true) == 0); } else if ((wilc->io_type & 0x1) == HIF_SDIO) { + wilc->hif_func->hif_write_reg(wilc, 0xfa, 1); + udelay(200); wilc->hif_func->hif_read_reg(wilc, 0xf0, ®); do { wilc->hif_func->hif_write_reg(wilc, 0xf0, @@ -567,11 +570,7 @@ static inline void chip_wakeup(struct wilc *wilc) } if (chip_ps_state == CHIP_SLEEPING_MANUAL) { - wilc->hif_func->hif_read_reg(wilc, 0x1C0C, ®); - reg &= ~BIT(0); - wilc->hif_func->hif_write_reg(wilc, 0x1C0C, reg); - - if (wilc_get_chipid(wilc, false) >= 0x1002b0) { + if (wilc_get_chipid(wilc, false) < 0x1002b0) { u32 val32; wilc->hif_func->hif_read_reg(wilc, 0x1e1c, &val32); @@ -599,6 +598,20 @@ void wilc_chip_sleep_manually(struct wilc *wilc) release_bus(wilc, RELEASE_ONLY); } +void host_wakeup_notify(struct wilc *wilc) +{ + acquire_bus(wilc, ACQUIRE_ONLY); + wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1); + release_bus(wilc, RELEASE_ONLY); +} + +void host_sleep_notify(struct wilc *wilc) +{ + acquire_bus(wilc, ACQUIRE_ONLY); + wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1); + release_bus(wilc, RELEASE_ONLY); +} + int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) { int i, entries = 0; @@ -701,9 +714,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; } PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n"); - release_bus(wilc, RELEASE_ALLOW_SLEEP); - usleep_range(3000, 3000); - acquire_bus(wilc, ACQUIRE_AND_WAKEUP); } } while (!wilc->quit); @@ -736,9 +746,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; } else { release_bus(wilc, RELEASE_ALLOW_SLEEP); - usleep_range(3000, 3000); - acquire_bus(wilc, ACQUIRE_AND_WAKEUP); - PRINT_WRN(GENERIC_DBG, "Can't get VMM entery - reg = %2x\n", reg); } } while (--timeout); if (timeout <= 0) { @@ -1156,7 +1163,7 @@ int wilc_wlan_start(struct wilc *wilc) #ifdef WILC_EXT_PA_INV_TX_RX reg |= WILC_HAVE_EXT_PA_INV_TX_RX; #endif - + reg |= WILC_HAVE_USE_IRQ_AS_HOST_WAKE; reg |= WILC_HAVE_LEGACY_RF_SETTINGS; #ifdef XTAL_24 reg |= WILC_HAVE_XTAL_24; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 2edd7445f4a3..dd5abc52dfd9 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -106,6 +106,7 @@ #define WILC_HAVE_LEGACY_RF_SETTINGS BIT(5) #define WILC_HAVE_XTAL_24 BIT(6) #define WILC_HAVE_DISABLE_WILC_UART BIT(7) +#define WILC_HAVE_USE_IRQ_AS_HOST_WAKE BIT(8) /******************************************** * @@ -294,7 +295,8 @@ int wilc_mac_close(struct net_device *ndev); int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID); void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); - +void host_wakeup_notify(struct wilc *wilc); +void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; #endif -- cgit From 76855ba75fbc0787a5c0d32f991e54c81d2e5ad6 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:08 +0900 Subject: staging: wilc1000: add sdio resume/suspend This patch introduces sdio device suspend and resume functionality. sdio_reset function is added to reset sdio. Remove static inline keyword from chip_allow_sleep and chip_wakeup, and export symbols. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 72 +++++++++++++++++++++++++++ drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 + drivers/staging/wilc1000/wilc_wlan.c | 11 ++-- drivers/staging/wilc1000/wilc_wlan.h | 3 +- 4 files changed, 82 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index caad876a8249..f40a52730bc6 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -42,6 +42,7 @@ static wilc_sdio_t g_sdio; static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data); static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data); +static int sdio_init(struct wilc *wilc); static void wilc_sdio_interrupt(struct sdio_func *func) { @@ -142,11 +143,82 @@ static void linux_sdio_remove(struct sdio_func *func) wilc_netdev_cleanup(sdio_get_drvdata(func)); } +static int sdio_reset(struct wilc *wilc) +{ + sdio_cmd52_t cmd; + int ret; + struct sdio_func *func = dev_to_sdio_func(wilc->dev); + + cmd.read_write = 1; + cmd.function = 0; + cmd.raw = 0; + cmd.address = 0x6; + cmd.data = 0x8; + ret = wilc_sdio_cmd52(wilc, &cmd); + if (ret) { + dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n"); + return ret; + } + return 0; +} + +static int wilc_sdio_suspend(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct wilc *wilc = sdio_get_drvdata(func); + int ret; + + dev_info(dev, "sdio suspend\n"); + chip_wakeup(wilc); + + if (!wilc->suspend_event) { + wilc_chip_sleep_manually(wilc); + } else { + host_sleep_notify(wilc); + chip_allow_sleep(wilc); + } + + ret = sdio_reset(wilc); + if (ret) { + dev_err(&func->dev, "Fail reset sdio\n"); + return ret; + } + sdio_claim_host(func); + + return 0; +} + +static int wilc_sdio_resume(struct device *dev) +{ + struct sdio_func *func = dev_to_sdio_func(dev); + struct wilc *wilc = sdio_get_drvdata(func); + + dev_info(dev, "sdio resume\n"); + sdio_release_host(func); + chip_wakeup(wilc); + sdio_init(wilc); + + if (wilc->suspend_event) + host_wakeup_notify(wilc); + + chip_allow_sleep(wilc); + + return 0; +} + +static const struct dev_pm_ops wilc_sdio_pm_ops = { + .suspend = wilc_sdio_suspend, + .resume = wilc_sdio_resume, +}; + static struct sdio_driver wilc1000_sdio_driver = { .name = SDIO_MODALIAS, .id_table = wilc_sdio_ids, .probe = linux_sdio_probe, .remove = linux_sdio_remove, + .drv = { + .pm = &wilc_sdio_pm_ops, + } }; module_driver(wilc1000_sdio_driver, sdio_register_driver, diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 98ac8ed04a06..cd3d21d61bed 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -215,6 +215,7 @@ struct wilc { const struct firmware *firmware; struct device *dev; + bool suspend_event; }; struct WILC_WFI_mon_priv { diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index d824606a248b..74e20879f8ef 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -3,8 +3,6 @@ #include "wilc_wfi_netdevice.h" #include "wilc_wlan_cfg.h" -static inline void chip_allow_sleep(struct wilc *wilc); -static inline void chip_wakeup(struct wilc *wilc); static u32 dbgflag = N_INIT | N_ERR | N_INTR | N_TXQ | N_RXQ; /* FIXME: replace with dev_debug() */ @@ -515,7 +513,7 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) return NULL; } -static inline void chip_allow_sleep(struct wilc *wilc) +void chip_allow_sleep(struct wilc *wilc) { u32 reg = 0; @@ -524,8 +522,9 @@ static inline void chip_allow_sleep(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0xf0, reg & ~BIT(0)); wilc->hif_func->hif_write_reg(wilc, 0xfa, 0); } +EXPORT_SYMBOL_GPL(chip_allow_sleep); -static inline void chip_wakeup(struct wilc *wilc) +void chip_wakeup(struct wilc *wilc) { u32 reg, clk_status_reg, trials = 0; @@ -584,6 +583,7 @@ static inline void chip_wakeup(struct wilc *wilc) } chip_ps_state = CHIP_WAKEDUP; } +EXPORT_SYMBOL_GPL(chip_wakeup); void wilc_chip_sleep_manually(struct wilc *wilc) { @@ -597,6 +597,7 @@ void wilc_chip_sleep_manually(struct wilc *wilc) chip_ps_state = CHIP_SLEEPING_MANUAL; release_bus(wilc, RELEASE_ONLY); } +EXPORT_SYMBOL_GPL(wilc_chip_sleep_manually); void host_wakeup_notify(struct wilc *wilc) { @@ -604,6 +605,7 @@ void host_wakeup_notify(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0x10b0, 1); release_bus(wilc, RELEASE_ONLY); } +EXPORT_SYMBOL_GPL(host_wakeup_notify); void host_sleep_notify(struct wilc *wilc) { @@ -611,6 +613,7 @@ void host_sleep_notify(struct wilc *wilc) wilc->hif_func->hif_write_reg(wilc, 0x10ac, 1); release_bus(wilc, RELEASE_ONLY); } +EXPORT_SYMBOL_GPL(host_sleep_notify); int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) { diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index dd5abc52dfd9..53e56ff4d401 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -298,5 +298,6 @@ void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); void host_wakeup_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; - +void chip_allow_sleep(struct wilc *wilc); +void chip_wakeup(struct wilc *wilc); #endif -- cgit From 5397cbc231e20c8166709e696e70cff08d8ae503 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:09 +0900 Subject: staging: wilc1000: sdio_init: add resume argument Part of sdio init codes should not run when sdio init function is called on sdio resume so skip them. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 34 +++++++++++++++++++--------------- drivers/staging/wilc1000/wilc_spi.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 2 +- drivers/staging/wilc1000/wilc_wlan.h | 2 +- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index f40a52730bc6..7c20c8c9c2bc 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -42,7 +42,7 @@ static wilc_sdio_t g_sdio; static int sdio_write_reg(struct wilc *wilc, u32 addr, u32 data); static int sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data); -static int sdio_init(struct wilc *wilc); +static int sdio_init(struct wilc *wilc, bool resume); static void wilc_sdio_interrupt(struct sdio_func *func) { @@ -196,7 +196,7 @@ static int wilc_sdio_resume(struct device *dev) dev_info(dev, "sdio resume\n"); sdio_release_host(func); chip_wakeup(wilc); - sdio_init(wilc); + sdio_init(wilc, true); if (wilc->suspend_event) host_wakeup_notify(wilc); @@ -667,16 +667,17 @@ static int sdio_deinit(struct wilc *wilc) return 1; } -static int sdio_init(struct wilc *wilc) +static int sdio_init(struct wilc *wilc, bool resume) { struct sdio_func *func = dev_to_sdio_func(wilc->dev); sdio_cmd52_t cmd; int loop, ret; u32 chipid; - memset(&g_sdio, 0, sizeof(wilc_sdio_t)); - - g_sdio.irq_gpio = (wilc->dev_irq_num); + if (!resume) { + memset(&g_sdio, 0, sizeof(wilc_sdio_t)); + g_sdio.irq_gpio = (wilc->dev_irq_num); + } /** * function 0 csa enable @@ -766,16 +767,19 @@ static int sdio_init(struct wilc *wilc) /** * make sure can read back chip id correctly **/ - if (!sdio_read_reg(wilc, 0x1000, &chipid)) { - dev_err(&func->dev, "Fail cmd read chip id...\n"); - goto _fail_; + if (!resume) { + if (!sdio_read_reg(wilc, 0x1000, &chipid)) { + dev_err(&func->dev, "Fail cmd read chip id...\n"); + goto _fail_; + } + dev_err(&func->dev, "chipid (%08x)\n", chipid); + if ((chipid & 0xfff) > 0x2a0) + g_sdio.has_thrpt_enh3 = 1; + else + g_sdio.has_thrpt_enh3 = 0; + dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", + g_sdio.has_thrpt_enh3); } - dev_err(&func->dev, "chipid (%08x)\n", chipid); - if ((chipid & 0xfff) > 0x2a0) - g_sdio.has_thrpt_enh3 = 1; - else - g_sdio.has_thrpt_enh3 = 0; - dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3); return 1; diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c index 1df07e7bea59..29287122d1ca 100644 --- a/drivers/staging/wilc1000/wilc_spi.c +++ b/drivers/staging/wilc1000/wilc_spi.c @@ -850,7 +850,7 @@ static int _wilc_spi_deinit(struct wilc *wilc) return 1; } -static int wilc_spi_init(struct wilc *wilc) +static int wilc_spi_init(struct wilc *wilc, bool resume) { struct spi_device *spi = to_spi_device(wilc->dev); u32 reg; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 74e20879f8ef..36debb4d061c 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1530,7 +1530,7 @@ int wilc_wlan_init(struct net_device *dev) wilc->quit = 0; - if (!wilc->hif_func->hif_init(wilc)) { + if (!wilc->hif_func->hif_init(wilc, false)) { ret = -EIO; goto _fail_; } diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 53e56ff4d401..a1096edd6b63 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -227,7 +227,7 @@ struct rxq_entry_t { ********************************************/ struct wilc; struct wilc_hif_func { - int (*hif_init)(struct wilc *); + int (*hif_init)(struct wilc *, bool resume); int (*hif_deinit)(struct wilc *); int (*hif_read_reg)(struct wilc *, u32, u32 *); int (*hif_write_reg)(struct wilc *, u32, u32); -- cgit From 73584a40d7484f199a98893e97dcea8b2cbe4986 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:10 +0900 Subject: staging: wilc1000: add ops resuem/suspend/wakeup in cfg80211 This patch adds ops resume, suspend and set_wakeup in cfg80211. Together with previous patches, driver will support suspend/resume functionality. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 792fdff4bca9..0b6df6a95448 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -74,6 +74,10 @@ static const struct ieee80211_txrx_stypes } }; +static const struct wiphy_wowlan_support wowlan_support = { + .flags = WIPHY_WOWLAN_ANY +}; + #define WILC_WFI_DWELL_PASSIVE 100 #define WILC_WFI_DWELL_ACTIVE 40 @@ -2673,6 +2677,36 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) return 0; } +static int wilc_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + if (!wow && wilc_wlan_get_num_conn_ifcs(vif->wilc)) + vif->wilc->suspend_event = true; + else + vif->wilc->suspend_event = false; + + return 0; +} + +static int wilc_resume(struct wiphy *wiphy) +{ + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + netdev_info(vif->ndev, "cfg resume\n"); + return 0; +} + +static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled) +{ + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled); +} + static struct cfg80211_ops wilc_cfg80211_ops = { .set_monitor_channel = set_channel, .scan = scan, @@ -2708,6 +2742,10 @@ static struct cfg80211_ops wilc_cfg80211_ops = { .set_power_mgmt = set_power_mgmt, .set_cqm_rssi_config = set_cqm_rssi_config, + .suspend = wilc_suspend, + .resume = wilc_resume, + .set_wakeup = wilc_set_wakeup, + }; int WILC_WFI_update_stats(struct wiphy *wiphy, u32 pktlen, u8 changed) @@ -2792,6 +2830,7 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de sema_init(&(priv->SemHandleUpdateStats), 1); priv->wdev = wdev; wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; + wdev->wiphy->wowlan = &wowlan_support; wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS; PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids); -- cgit From 08037941d68497032f54a43c32ca20ccd5e2406b Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:11 +0900 Subject: staging: wilc1000: remove sleep and reduce close timeout sleep is not necessary during handling tx queue so remove it and also reduce close time to 5 sec since it is enough time to close. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 54fe9d74b780..236996fd8677 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -391,9 +391,6 @@ static int linux_wlan_txq_task(void *vp) } if (ret == WILC_TX_ERR_NO_BUF) { - do { - msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight); - } while (0); backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP; if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) backoff_weight = TX_BACKOFF_WEIGHT_MAX; @@ -1403,7 +1400,7 @@ void wilc_netdev_cleanup(struct wilc *wilc) release_firmware(wilc->firmware); if (wilc && (wilc->vif[0]->ndev || wilc->vif[1]->ndev)) { - wilc_lock_timeout(wilc, &close_exit_sync, 12 * 1000); + wilc_lock_timeout(wilc, &close_exit_sync, 5 * 1000); for (i = 0; i < NUM_CONCURRENT_IFC; i++) if (wilc->vif[i]->ndev) -- cgit From b8f6ca0b169dbf1d2800c3b7c618288aad91f039 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:12 +0900 Subject: staging: wilc1000: get address from wilc Get mac address from wilc device instead of using random mac address. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 236996fd8677..58837d7f1be2 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -511,20 +511,19 @@ static int wilc1000_firmware_download(struct net_device *dev) } static int linux_wlan_init_test_config(struct net_device *dev, - struct wilc *wilc) + struct wilc_vif *vif) { unsigned char c_val[64]; unsigned char mac_add[] = {0x00, 0x80, 0xC2, 0x5E, 0xa2, 0xff}; - + struct wilc *wilc = vif->wilc; struct wilc_priv *priv; struct host_if_drv *hif_drv; PRINT_D(TX_DBG, "Start configuring Firmware\n"); - get_random_bytes(&mac_add[5], 1); - get_random_bytes(&mac_add[4], 1); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; PRINT_D(INIT_DBG, "Host = %p\n", hif_drv); + wilc_get_mac_address(vif, mac_add); PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", mac_add[0], mac_add[1], mac_add[2], @@ -944,7 +943,7 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) Firmware_ver[size] = '\0'; PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver); } - ret = linux_wlan_init_test_config(dev, wl); + ret = linux_wlan_init_test_config(dev, vif); if (ret < 0) { PRINT_ER("Failed to configure firmware\n"); -- cgit From 14823bf2ea000c8762ec38ed7b67ee049a2b6fbf Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:13 +0900 Subject: staging: wilc1000: use unified firmware Use a unified firmware for all mode of operations which are station, ap and p2p. Two firmware are introduced for 1002 and 1003 chipset. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/Makefile | 5 ++--- drivers/staging/wilc1000/linux_wlan.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index 20a5cb9d4f4c..90c37606f202 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -1,8 +1,7 @@ obj-$(CONFIG_WILC1000) += wilc1000.o -ccflags-y += -DSTA_FIRMWARE=\"atmel/wilc1000_fw.bin\" \ - -DAP_FIRMWARE=\"atmel/wilc1000_ap_fw.bin\" \ - -DP2P_CONCURRENCY_FIRMWARE=\"atmel/wilc1000_p2p_fw.bin\" +ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \ + -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\" ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS #ccflags-y += -DTCP_ACK_FILTER diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 58837d7f1be2..006f75f7c675 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -416,21 +416,21 @@ int wilc_wlan_get_firmware(struct net_device *dev) { struct wilc_vif *vif; struct wilc *wilc; - int ret = 0; + int chip_id, ret = 0; const struct firmware *wilc_firmware; char *firmware; vif = netdev_priv(dev); wilc = vif->wilc; - if (vif->iftype == AP_MODE) { - firmware = AP_FIRMWARE; - } else if (vif->iftype == STATION_MODE) { - firmware = STA_FIRMWARE; - } else { - PRINT_D(INIT_DBG, "Get P2P_CONCURRENCY_FIRMWARE\n"); - firmware = P2P_CONCURRENCY_FIRMWARE; - } + chip_id = wilc_get_chipid(wilc, 0); + + if (chip_id < 0x1003a0) + firmware = FIRMWARE_1002; + else + firmware = FIRMWARE_1003; + + netdev_info(dev, "loading firmware %s\n", firmware); if (!vif) { PRINT_ER("vif is NULL\n"); -- cgit From e32737e9da8d870006fa34a4374391d103d87eb6 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:14 +0900 Subject: staging: wilc1000: remove wilc_set_machw_change_vir_if wilc_set_machw_change_vir_if is not used anymore since we use one unified firmware. Instead, wilc_set_operation_mode is called when wilc_mac_open to let the wilc use the proper firmware. Remove wilc_set_machw_change_vir_if and it's functions calls. In the later patch, mac index will be passed to wilc device. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 3 +-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 ----- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - drivers/staging/wilc1000/wilc_wlan.c | 32 ----------------------- 4 files changed, 1 insertion(+), 41 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 006f75f7c675..08d2cb2c00b8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1024,14 +1024,13 @@ int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_set_machw_change_vir_if(ndev, false); - wilc_get_mac_address(vif, mac_add); PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add); for (i = 0; i < wl->vif_num; i++) { if (ndev == wl->vif[i]->ndev) { memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); + wilc_set_operation_mode(vif, vif->iftype); break; } } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 0b6df6a95448..d2b7a8be484c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1274,7 +1274,6 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, kfree(g_key_gtk_params.seq); g_key_gtk_params.seq = NULL; - wilc_set_machw_change_vir_if(netdev, false); } if (key_index >= 0 && key_index <= 3) { @@ -2116,10 +2115,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, del_timer(&wilc_during_ip_timer); PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n"); - if (g_ptk_keys_saved && g_gtk_keys_saved) { - wilc_set_machw_change_vir_if(dev, true); - } - switch (type) { case NL80211_IFTYPE_STATION: wilc_connecting = 0; @@ -2261,7 +2256,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, } refresh_scan(priv, 1, true); - wilc_set_machw_change_vir_if(dev, false); if (wl->initialized) { for (i = 0; i < num_reg_frame; i++) { diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index cd3d21d61bed..0d851f863b91 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -235,7 +235,6 @@ int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio, const struct wilc_hif_func *ops); void wilc1000_wlan_deinit(struct net_device *dev); void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); -u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value); int wilc_wlan_get_firmware(struct net_device *dev); int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 36debb4d061c..5682581ebcc3 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1578,35 +1578,3 @@ _fail_: return ret; } - -u16 wilc_set_machw_change_vir_if(struct net_device *dev, bool value) -{ - u16 ret; - u32 reg; - struct wilc_vif *vif; - struct wilc *wilc; - - vif = netdev_priv(dev); - wilc = vif->wilc; - - mutex_lock(&wilc->hif_cs); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_CHANGING_VIR_IF, - ®); - if (!ret) - PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n"); - - if (value) - reg |= BIT(31); - else - reg &= ~BIT(31); - - ret = wilc->hif_func->hif_write_reg(wilc, WILC_CHANGING_VIR_IF, - reg); - - if (!ret) - PRINT_ER("Error while writing reg WILC_CHANGING_VIR_IF\n"); - - mutex_unlock(&wilc->hif_cs); - - return ret; -} -- cgit From ba615f1ef9cc8272ac8def632286c53524ce4f57 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:15 +0900 Subject: staging: wilc1000: set bssid with mode This patch add new argument mode to wilc_wlan_set_bssid and define mode in struct wilc_vif also. The mode is used by get_if_handler function to get proper netdevice for each mode. The get_if_handler is changed together. Remove invalid handle codes and add mode condition to get netdevice for the mode. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 26 +++++++++-------------- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 13 ++++++------ drivers/staging/wilc1000/wilc_wfi_netdevice.h | 3 ++- drivers/staging/wilc1000/wilc_wlan.h | 1 - 4 files changed, 19 insertions(+), 24 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 08d2cb2c00b8..2489ea30855c 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -288,26 +288,19 @@ static struct net_device *get_if_handler(struct wilc *wilc, u8 *mac_header) bssid = mac_header + 10; bssid1 = mac_header + 4; - for (i = 0; i < wilc->vif_num; i++) - if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN) || - !memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) - return wilc->vif[i]->ndev; - - PRINT_INFO(INIT_DBG, "Invalide handle\n"); - for (i = 0; i < 25; i++) - PRINT_D(INIT_DBG, "%02x ", mac_header[i]); - bssid = mac_header + 18; - bssid1 = mac_header + 12; - for (i = 0; i < wilc->vif_num; i++) - if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN) || - !memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) - return wilc->vif[i]->ndev; + for (i = 0; i < wilc->vif_num; i++) { + if (wilc->vif[i]->mode == STATION_MODE) + if (!memcmp(bssid, wilc->vif[i]->bssid, ETH_ALEN)) + return wilc->vif[i]->ndev; + if (wilc->vif[i]->mode == AP_MODE) + if (!memcmp(bssid1, wilc->vif[i]->bssid, ETH_ALEN)) + return wilc->vif[i]->ndev; + } - PRINT_INFO(INIT_DBG, "\n"); return NULL; } -int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid) +int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode) { int i = 0; int ret = -1; @@ -320,6 +313,7 @@ int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid) for (i = 0; i < wilc->vif_num; i++) if (wilc->vif[i]->ndev == wilc_netdev) { memcpy(wilc->vif[i]->bssid, bssid, 6); + wilc->vif[i]->mode = mode; ret = 0; break; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d2b7a8be484c..1b2eae59b51e 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -524,7 +524,8 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, if ((u8MacStatus == MAC_DISCONNECTED) && (pstrConnectInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE; - wilc_wlan_set_bssid(priv->dev, NullBssid); + wilc_wlan_set_bssid(priv->dev, NullBssid, + STATION_MODE); eth_zero_addr(wilc_connected_ssid); if (!pstrWFIDrv->p2p_connect) @@ -577,7 +578,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, p2p_recv_random = 0x00; wilc_ie = false; eth_zero_addr(priv->au8AssociatedBss); - wilc_wlan_set_bssid(priv->dev, NullBssid); + wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE); eth_zero_addr(wilc_connected_ssid); if (!pstrWFIDrv->p2p_connect) @@ -903,7 +904,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (!pstrWFIDrv->p2p_connect) wlan_channel = pstrNetworkInfo->u8channel; - wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid); + wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid, STATION_MODE); s32Error = wilc_set_join_req(vif, pstrNetworkInfo->au8bssid, sme->ssid, sme->ssid_len, sme->ie, sme->ie_len, @@ -937,7 +938,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; - wilc_wlan_set_bssid(priv->dev, NullBssid); + wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE); PRINT_D(CFG80211_DBG, "Disconnecting with reason code(%d)\n", reason_code); @@ -2400,7 +2401,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) PRINT_ER("Error in setting channel\n"); - wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr); + wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr, AP_MODE); s32Error = wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, @@ -2444,7 +2445,7 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) PRINT_D(HOSTAPD_DBG, "Deleting beacon\n"); - wilc_wlan_set_bssid(dev, NullBssid); + wilc_wlan_set_bssid(dev, NullBssid, AP_MODE); s32Error = wilc_del_beacon(vif); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 0d851f863b91..54e762ec815f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -160,6 +160,7 @@ struct wilc_vif { u8 bssid[ETH_ALEN]; struct host_if_drv *hif_drv; struct net_device *ndev; + u8 mode; }; struct wilc { @@ -236,6 +237,6 @@ int wilc_netdev_init(struct wilc **wilc, struct device *, int io_type, int gpio, void wilc1000_wlan_deinit(struct net_device *dev); void WILC_WFI_mgmt_rx(struct wilc *wilc, u8 *buff, u32 size); int wilc_wlan_get_firmware(struct net_device *dev); -int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid); +int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *bssid, u8 mode); #endif diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index a1096edd6b63..7f046531be01 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -293,7 +293,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *dev); int wilc_mac_open(struct net_device *ndev); int wilc_mac_close(struct net_device *ndev); -int wilc_wlan_set_bssid(struct net_device *wilc_netdev, u8 *pBSSID); void WILC_WFI_p2p_rx(struct net_device *dev, u8 *buff, u32 size); void host_wakeup_notify(struct wilc *wilc); void host_sleep_notify(struct wilc *wilc); -- cgit From ff35567923c7df4af03adec0a36871914b48bead Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:16 +0900 Subject: staging: wilc1000: set proper bssid address This patch changes index 0 to index of vif which is currently beging used because AP mode can run on any interface. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 1b2eae59b51e..7db96c7097c2 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2401,7 +2401,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) PRINT_ER("Error in setting channel\n"); - wilc_wlan_set_bssid(dev, wl->vif[0]->src_addr, AP_MODE); + wilc_wlan_set_bssid(dev, wl->vif[vif->u8IfIdx]->src_addr, AP_MODE); s32Error = wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, -- cgit From 86bff01b94bb0cd1a2cbcaae46c3677d60768c1a Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:17 +0900 Subject: staging: wilc1000: change_virtual_intf: change codes for unified firmware In previous patch, we use unified firmware on wilc, which means we do not need to download firmware again to change virtual interfaces. There are a lot of codes to change interface and they are needless now, so remove them except wilc_set_operation_mode function which change the mode and wilc_set_power_mgmt which control power save. There will be unused functions and they will be removed in later patch. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 220 ++-------------------- 1 file changed, 11 insertions(+), 209 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 7db96c7097c2..d282a871ddcb 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2098,9 +2098,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, { struct wilc_priv *priv; struct wilc_vif *vif; - u8 interface_type; - u16 TID = 0; - u8 i; struct wilc *wl; vif = netdev_priv(dev); @@ -2125,74 +2122,12 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, priv->wdev->iftype = type; vif->monitor_flag = 0; vif->iftype = STATION_MODE; + wilc_set_operation_mode(vif, STATION_MODE); memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN); - interface_type = vif->iftype; - vif->iftype = STATION_MODE; - - if (wl->initialized) { - wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, - TID); - wilc_wait_msg_queue_idle(); - - up(&wl->cfg_event); - - wilc1000_wlan_deinit(dev); - wilc1000_wlan_init(dev, vif); - wilc_initialized = 1; - vif->iftype = interface_type; - - wilc_set_wfi_drv_handler(vif, - wilc_get_vif_idx(wl->vif[0])); - wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr); - wilc_set_operation_mode(vif, STATION_MODE); - - if (g_wep_keys_saved) { - wilc_set_wep_default_keyid(wl->vif[0], - g_key_wep_params.key_idx); - wilc_add_wep_key_bss_sta(wl->vif[0], - g_key_wep_params.key, - g_key_wep_params.key_len, - g_key_wep_params.key_idx); - } - - wilc_flush_join_req(vif); - - if (g_ptk_keys_saved && g_gtk_keys_saved) { - PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0], - g_key_ptk_params.key[1], - g_key_ptk_params.key[2]); - PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0], - g_key_gtk_params.key[1], - g_key_gtk_params.key[2]); - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_ptk_key_params.key_idx, - g_add_ptk_key_params.pairwise, - g_add_ptk_key_params.mac_addr, - (struct key_params *)(&g_key_ptk_params)); - - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_gtk_key_params.key_idx, - g_add_gtk_key_params.pairwise, - g_add_gtk_key_params.mac_addr, - (struct key_params *)(&g_key_gtk_params)); - } - - if (wl->initialized) { - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } - } - wilc_enable_ps = true; - wilc_set_power_mgmt(vif, 1, 0); - } + wilc_enable_ps = true; + wilc_set_power_mgmt(vif, 1, 0); break; case NL80211_IFTYPE_P2P_CLIENT: @@ -2201,73 +2136,11 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_connecting = 0; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n"); - wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, TID); - dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; vif->monitor_flag = 0; - - PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); vif->iftype = CLIENT_MODE; - - - if (wl->initialized) { - wilc_wait_msg_queue_idle(); - - wilc1000_wlan_deinit(dev); - wilc1000_wlan_init(dev, vif); - wilc_initialized = 1; - - wilc_set_wfi_drv_handler(vif, - wilc_get_vif_idx(wl->vif[0])); - wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr); - wilc_set_operation_mode(vif, STATION_MODE); - - if (g_wep_keys_saved) { - wilc_set_wep_default_keyid(wl->vif[0], - g_key_wep_params.key_idx); - wilc_add_wep_key_bss_sta(wl->vif[0], - g_key_wep_params.key, - g_key_wep_params.key_len, - g_key_wep_params.key_idx); - } - - wilc_flush_join_req(vif); - - if (g_ptk_keys_saved && g_gtk_keys_saved) { - PRINT_D(CFG80211_DBG, "ptk %x %x %x\n", g_key_ptk_params.key[0], - g_key_ptk_params.key[1], - g_key_ptk_params.key[2]); - PRINT_D(CFG80211_DBG, "gtk %x %x %x\n", g_key_gtk_params.key[0], - g_key_gtk_params.key[1], - g_key_gtk_params.key[2]); - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_ptk_key_params.key_idx, - g_add_ptk_key_params.pairwise, - g_add_ptk_key_params.mac_addr, - (struct key_params *)(&g_key_ptk_params)); - - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_gtk_key_params.key_idx, - g_add_gtk_key_params.pairwise, - g_add_gtk_key_params.mac_addr, - (struct key_params *)(&g_key_gtk_params)); - } - - refresh_scan(priv, 1, true); - - if (wl->initialized) { - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } - } - } + wilc_set_operation_mode(vif, STATION_MODE); break; case NL80211_IFTYPE_AP: @@ -2276,23 +2149,11 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; vif->iftype = AP_MODE; - PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv); - - PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n"); - wilc_wlan_get_firmware(dev); - - if (wl->initialized) { - vif->iftype = AP_MODE; - wilc_mac_close(dev); - wilc_mac_open(dev); - - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } + + if (wl->initialized) { + wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); + wilc_set_operation_mode(vif, AP_MODE); + wilc_set_power_mgmt(vif, 0, 0); } break; @@ -2303,72 +2164,13 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(during_ip_time)); wilc_set_power_mgmt(vif, 0, 0); - wilc_del_all_rx_ba_session(vif, wl->vif[0]->bssid, TID); wilc_enable_ps = false; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n"); + + wilc_set_operation_mode(vif, AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; - - PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv); - - PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n"); - - vif->iftype = GO_MODE; - - wilc_wait_msg_queue_idle(); - wilc1000_wlan_deinit(dev); - wilc1000_wlan_init(dev, vif); - wilc_initialized = 1; - - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(wl->vif[0])); - wilc_set_mac_address(wl->vif[0], wl->vif[0]->src_addr); - wilc_set_operation_mode(vif, AP_MODE); - - if (g_wep_keys_saved) { - wilc_set_wep_default_keyid(wl->vif[0], - g_key_wep_params.key_idx); - wilc_add_wep_key_bss_sta(wl->vif[0], - g_key_wep_params.key, - g_key_wep_params.key_len, - g_key_wep_params.key_idx); - } - - wilc_flush_join_req(vif); - - if (g_ptk_keys_saved && g_gtk_keys_saved) { - PRINT_D(CFG80211_DBG, "ptk %x %x %x cipher %x\n", g_key_ptk_params.key[0], - g_key_ptk_params.key[1], - g_key_ptk_params.key[2], - g_key_ptk_params.cipher); - PRINT_D(CFG80211_DBG, "gtk %x %x %x cipher %x\n", g_key_gtk_params.key[0], - g_key_gtk_params.key[1], - g_key_gtk_params.key[2], - g_key_gtk_params.cipher); - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_ptk_key_params.key_idx, - g_add_ptk_key_params.pairwise, - g_add_ptk_key_params.mac_addr, - (struct key_params *)(&g_key_ptk_params)); - - add_key(wl->vif[0]->ndev->ieee80211_ptr->wiphy, - wl->vif[0]->ndev, - g_add_gtk_key_params.key_idx, - g_add_gtk_key_params.pairwise, - g_add_gtk_key_params.mac_addr, - (struct key_params *)(&g_key_gtk_params)); - } - - if (wl->initialized) { - for (i = 0; i < num_reg_frame; i++) { - PRINT_D(INIT_DBG, "Frame registering Type: %x - Reg: %d\n", vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - wilc_frame_register(vif, - vif->g_struct_frame_reg[i].frame_type, - vif->g_struct_frame_reg[i].reg); - } - } break; default: -- cgit From ee632309208c823419429d9a3b9702144a756431 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Mon, 25 Jan 2016 16:35:18 +0900 Subject: staging: wilc1000: call power save after changing mode host_int_set_power_mgmt should be called after changing operation mode to work properly. Move the function below host_int_set_operation_mode. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d282a871ddcb..4eede2b4e661 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2131,8 +2131,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_P2P_CLIENT: - wilc_enable_ps = false; - wilc_set_power_mgmt(vif, 0, 0); wilc_connecting = 0; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_P2P_CLIENT\n"); @@ -2141,6 +2139,9 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, vif->monitor_flag = 0; vif->iftype = CLIENT_MODE; wilc_set_operation_mode(vif, STATION_MODE); + + wilc_enable_ps = false; + wilc_set_power_mgmt(vif, 0, 0); break; case NL80211_IFTYPE_AP: @@ -2163,14 +2164,15 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_optaining_ip = true; mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(during_ip_time)); - wilc_set_power_mgmt(vif, 0, 0); - wilc_enable_ps = false; PRINT_D(HOSTAPD_DBG, "Interface type = NL80211_IFTYPE_GO\n"); wilc_set_operation_mode(vif, AP_MODE); dev->ieee80211_ptr->iftype = type; priv->wdev->iftype = type; vif->iftype = GO_MODE; + + wilc_enable_ps = false; + wilc_set_power_mgmt(vif, 0, 0); break; default: -- cgit From 4cf93d706fb9178cd9c8366c958b52a4ebca41f0 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Tue, 26 Jan 2016 18:50:00 +0900 Subject: staging: wilc1000: fix alignment for open parenthesis This patch fixes the check found by checkpatch.pl CHECK: Alignment should match open parenthesis Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 90 +++++++++++++++---------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 79e8b7aa482b..d77e2b2bea3d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -303,7 +303,7 @@ static s32 handle_set_channel(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting channel\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set channel\n"); @@ -350,7 +350,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, wid.size = sizeof(u32); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if ((hif_op_mode->mode) == IDLE_MODE) up(&hif_sema_driver); @@ -383,7 +383,7 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) wid.size = IP_ALEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); host_int_get_ipaddress(vif, firmware_ip_addr, idx); @@ -408,7 +408,7 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) wid.size = IP_ALEN; result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val); @@ -451,7 +451,7 @@ static s32 handle_set_mac_address(struct wilc_vif *vif, PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set mac address\n"); result = -EFAULT; @@ -473,7 +473,7 @@ static s32 handle_get_mac_address(struct wilc_vif *vif, wid.size = ETH_ALEN; result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get mac address\n"); @@ -939,7 +939,7 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, wid.size = sizeof(char); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set abort running scan\n"); @@ -1356,7 +1356,7 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send dissconect config packet\n"); @@ -1750,8 +1750,8 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[3].val = (s8 *)pu8keybuf; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 4, - wilc_get_vif_idx(vif)); + strWIDList, 4, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & ADDKEY) { PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); @@ -1772,8 +1772,8 @@ static int Handle_Key(struct wilc_vif *vif, wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & REMOVEKEY) { PRINT_D(HOSTINF_DBG, "Removing key\n"); @@ -1785,8 +1785,8 @@ static int Handle_Key(struct wilc_vif *vif, wid.size = 1; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); } else { wid.id = (u16)WID_KEY_ID; wid.type = WID_CHAR; @@ -1796,8 +1796,8 @@ static int Handle_Key(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting default key index\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); } up(&hif_drv->sem_test_key_block); break; @@ -1830,8 +1830,8 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[1].size = RX_MIC_KEY_MSG_LEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 2, - wilc_get_vif_idx(vif)); + strWIDList, 2, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); @@ -1862,8 +1862,8 @@ static int Handle_Key(struct wilc_vif *vif, wid.size = RX_MIC_KEY_MSG_LEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); @@ -1902,8 +1902,8 @@ _WPARxGtk_end_case_: strWIDList[1].size = PTK_KEY_MSG_LEN + 1; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 2, - wilc_get_vif_idx(vif)); + strWIDList, 2, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { @@ -1925,8 +1925,8 @@ _WPARxGtk_end_case_: wid.size = PTK_KEY_MSG_LEN; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - &wid, 1, - wilc_get_vif_idx(vif)); + &wid, 1, + wilc_get_vif_idx(vif)); kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); } @@ -1961,7 +1961,7 @@ _WPAPtk_end_case_: wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); kfree(pu8keybuf); break; @@ -1994,7 +1994,7 @@ static void Handle_Disconnect(struct wilc_vif *vif) eth_zero_addr(wilc_connected_ssid); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to send dissconect config packet\n"); @@ -2085,7 +2085,7 @@ static s32 Handle_GetChnl(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting channel value\n"); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get channel number\n"); @@ -2110,7 +2110,7 @@ static void Handle_GetRssi(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get RSSI value\n"); result = -EFAULT; @@ -2135,7 +2135,7 @@ static void Handle_GetLinkspeed(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get LINKSPEED value\n"); result = -EFAULT; @@ -2181,8 +2181,8 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, u32WidsCount++; result = wilc_send_config_pkt(vif->wilc, GET_CFG, strWIDList, - u32WidsCount, - wilc_get_vif_idx(vif)); + u32WidsCount, + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send scan paramters config packet\n"); @@ -2210,7 +2210,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, PRINT_D(CFG80211_DBG, "SETING STA inactive time\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to SET incative time\n"); @@ -2223,7 +2223,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wid.size = sizeof(u32); result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get incative time\n"); @@ -2311,7 +2311,7 @@ static void Handle_DelBeacon(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send delete beacon config packet\n"); } @@ -2384,7 +2384,7 @@ static void Handle_AddStation(struct wilc_vif *vif, pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to send add station config packet\n"); @@ -2426,7 +2426,7 @@ static void Handle_DelAllSta(struct wilc_vif *vif, } result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2458,7 +2458,7 @@ static void Handle_DelStation(struct wilc_vif *vif, memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2486,7 +2486,7 @@ static void Handle_EditStation(struct wilc_vif *vif, pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send edit station config packet\n"); @@ -2548,7 +2548,7 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, wid.val[1] = (s8)pstrHostIfRemainOnChan->ch; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to set remain on channel\n"); @@ -2596,7 +2596,7 @@ static int Handle_RegisterFrame(struct wilc_vif *vif, wid.size = sizeof(u16) + 2; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to frame register config packet\n"); result = -EINVAL; @@ -2631,7 +2631,7 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, wid.val[1] = FALSE_FRMWR_CHANNEL; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result != 0) { PRINT_ER("Failed to set remain on channel\n"); goto _done_; @@ -2689,7 +2689,7 @@ static void Handle_PowerManagement(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send power management config packet\n"); } @@ -2726,7 +2726,7 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif, ((strHostIfSetMulti->cnt) * ETH_ALEN)); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send setup multicast config packet\n"); @@ -2762,7 +2762,7 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, *ptr++ = 32; result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); @@ -3502,7 +3502,7 @@ static s32 host_int_get_assoc_res_info(struct wilc_vif *vif, wid.size = u32MaxAssocRespInfoLen; result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + wilc_get_vif_idx(vif)); if (result) { *pu32RcvdAssocRespInfoLen = 0; PRINT_ER("Failed to send association response config packet\n"); -- cgit From 0953a2e33b0fca7db82081f85eb7ed6b4b76a669 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Wed, 27 Jan 2016 11:50:25 +0900 Subject: staging: wilc1000: wilc_frmw_to_linux(): fixes null check Null checking wilc_netdev and skb->dev are already done in the begining of the function and they are just print printing error log, so delete them. Null checking wilc is needed before is used so add null ckeck before it is used. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 2489ea30855c..505b1233386c 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1322,6 +1322,9 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) struct net_device *wilc_netdev; struct wilc_vif *vif; + if (!wilc) + return; + wilc_netdev = get_if_handler(wilc, buff); if (!wilc_netdev) return; @@ -1338,14 +1341,8 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) PRINT_ER("Low memory - packet droped\n"); return; } - - if (!wilc || !wilc_netdev) - PRINT_ER("wilc_netdev in wilc is NULL"); skb->dev = wilc_netdev; - if (!skb->dev) - PRINT_ER("skb->dev is NULL\n"); - memcpy(skb_put(skb, frame_len), buff_to_send, frame_len); skb->protocol = eth_type_trans(skb, wilc_netdev); -- cgit From f05ab24945fcf66089a3c8276239ba50c121d7ab Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Wed, 27 Jan 2016 11:50:26 +0900 Subject: staging: wilc1000: fixes no space is necessary after a cast This patch fixes the check reported by checkpatch.pl for 'no space is necessary after a cast'. Signed-off-by: Leo Kim Signed-off-by: Glen Lee 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 505b1233386c..6b0800bd26ea 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1267,7 +1267,7 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) switch (cmd) { case SIOCSIWPRIV: { - struct iwreq *wrq = (struct iwreq *) req; + struct iwreq *wrq = (struct iwreq *)req; size = wrq->u.data.length; -- cgit From 40095ad9ecdc17b4f8cd7a4da67579ac64c26a95 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Wed, 27 Jan 2016 11:50:27 +0900 Subject: staging: wilc1000: fixes add spaces required around This patch fixes the checks reported by checkpatch.pl for spaces required around that '=' or '||' or '('. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 6b0800bd26ea..b368c2d9bf14 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -993,7 +993,7 @@ int wilc_mac_open(struct net_device *ndev) vif = netdev_priv(ndev); wl = vif->wilc; - if (!wl|| !wl->dev) { + if (!wl || !wl->dev) { netdev_err(ndev, "wilc1000: SPI device not ready\n"); return -ENODEV; } @@ -1054,7 +1054,7 @@ int wilc_mac_open(struct net_device *ndev) static struct net_device_stats *mac_stats(struct net_device *dev) { - struct wilc_vif *vif= netdev_priv(dev); + struct wilc_vif *vif = netdev_priv(dev); return &vif->netstats; } -- cgit From 43b36e42a55cf9cd669a1f29ef1db46c5ea37908 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:35 +0900 Subject: staging: wilc1000: coreconfigurator.c : remove over-commenting There are over-commenting in the coreconfigurator.c file and most of them are not helpful to explain what the code does and generate 80 ending line over warnings. So, all of comments are removed in this patch and the comments will later be added if necessary with the preferred Linux style. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 141 +--------------------------- 1 file changed, 1 insertion(+), 140 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 2d4d3f190c01..e6f50bac4b90 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -1,13 +1,3 @@ - -/*! - * @file coreconfigurator.c - * @brief - * @author - * @sa coreconfigurator.h - * @date 1 Mar 2012 - * @version 1.0 - */ - #include "coreconfigurator.h" #include "wilc_wlan_if.h" #include "wilc_wlan.h" @@ -16,7 +6,6 @@ #define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \ BEACON_INTERVAL_LEN + CAP_INFO_LEN) -/* Basic Frame Type Codes (2-bit) */ enum basic_frame_type { FRAME_TYPE_CONTROL = 0x04, FRAME_TYPE_DATA = 0x08, @@ -25,7 +14,6 @@ enum basic_frame_type { FRAME_TYPE_FORCE_32BIT = 0xFFFFFFFF }; -/* Frame Type and Subtype Codes (6-bit) */ enum sub_frame_type { ASSOC_REQ = 0x00, ASSOC_RSP = 0x10, @@ -65,7 +53,6 @@ enum sub_frame_type { FRAME_SUBTYPE_FORCE_32BIT = 0xFFFFFFFF }; -/* Element ID of various Information Elements */ enum info_element_id { ISSID = 0, /* Service Set Identifier */ ISUPRATES = 1, /* Supported Rates */ @@ -109,8 +96,6 @@ enum info_element_id { INFOELEM_ID_FORCE_32BIT = 0xFFFFFFFF }; -/* This function extracts the beacon period field from the beacon or probe */ -/* response frame. */ static inline u16 get_beacon_period(u8 *data) { u16 bcn_per; @@ -147,54 +132,36 @@ static inline u32 get_beacon_timestamp_hi(u8 *data) return time_stamp; } -/* This function extracts the 'frame type and sub type' bits from the MAC */ -/* header of the input frame. */ -/* Returns the value in the LSB of the returned value. */ static inline enum sub_frame_type get_sub_type(u8 *header) { return ((enum sub_frame_type)(header[0] & 0xFC)); } -/* This function extracts the 'to ds' bit from the MAC header of the input */ -/* frame. */ -/* Returns the value in the LSB of the returned value. */ static inline u8 get_to_ds(u8 *header) { return (header[1] & 0x01); } -/* This function extracts the 'from ds' bit from the MAC header of the input */ -/* frame. */ -/* Returns the value in the LSB of the returned value. */ static inline u8 get_from_ds(u8 *header) { return ((header[1] & 0x02) >> 1); } -/* This function extracts the MAC Address in 'address1' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ static inline void get_address1(u8 *pu8msa, u8 *addr) { memcpy(addr, pu8msa + 4, 6); } -/* This function extracts the MAC Address in 'address2' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ static inline void get_address2(u8 *pu8msa, u8 *addr) { memcpy(addr, pu8msa + 10, 6); } -/* This function extracts the MAC Address in 'address3' field of the MAC */ -/* header and updates the MAC Address in the allocated 'addr' variable. */ static inline void get_address3(u8 *pu8msa, u8 *addr) { memcpy(addr, pu8msa + 16, 6); } -/* This function extracts the BSSID from the incoming WLAN packet based on */ -/* the 'from ds' bit, and updates the MAC Address in the allocated 'addr' */ -/* variable. */ static inline void get_BSSID(u8 *data, u8 *bssid) { if (get_from_ds(data) == 1) @@ -205,7 +172,6 @@ static inline void get_BSSID(u8 *data, u8 *bssid) get_address3(data, bssid); } -/* This function extracts the SSID from a beacon/probe response frame */ static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) { u8 len = 0; @@ -217,8 +183,6 @@ static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) j = MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN + 2; - /* If the SSID length field is set wrongly to a value greater than the */ - /* allowed maximum SSID length limit, reset the length to 0 */ if (len >= MAX_SSID_LEN) len = 0; @@ -230,8 +194,6 @@ static inline void get_ssid(u8 *data, u8 *ssid, u8 *p_ssid_len) *p_ssid_len = len; } -/* This function extracts the capability info field from the beacon or probe */ -/* response frame. */ static inline u16 get_cap_info(u8 *data) { u16 cap_info = 0; @@ -240,8 +202,6 @@ static inline u16 get_cap_info(u8 *data) st = get_sub_type(data); - /* Location of the Capability field is different for Beacon and */ - /* Association frames. */ if ((st == BEACON) || (st == PROBE_RSP)) index += TIME_STAMP_LEN + BEACON_INTERVAL_LEN; @@ -251,8 +211,6 @@ static inline u16 get_cap_info(u8 *data) return cap_info; } -/* This function extracts the capability info field from the Association */ -/* response frame. */ static inline u16 get_assoc_resp_cap_info(u8 *data) { u16 cap_info; @@ -263,8 +221,6 @@ static inline u16 get_assoc_resp_cap_info(u8 *data) return cap_info; } -/* This function extracts the association status code from the incoming */ -/* association response frame and returns association status code */ static inline u16 get_asoc_status(u8 *data) { u16 asoc_status; @@ -275,8 +231,6 @@ static inline u16 get_asoc_status(u8 *data) return asoc_status; } -/* This function extracts association ID from the incoming association */ -/* response frame */ static inline u16 get_asoc_id(u8 *data) { u16 asoc_id; @@ -291,19 +245,8 @@ static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) { u16 u16index; - /*************************************************************************/ - /* Beacon Frame - Frame Body */ - /* --------------------------------------------------------------------- */ - /* |Timestamp |BeaconInt |CapInfo |SSID |SupRates |DSParSet |TIM elm | */ - /* --------------------------------------------------------------------- */ - /* |8 |2 |2 |2-34 |3-10 |3 |4-256 | */ - /* --------------------------------------------------------------------- */ - /* */ - /*************************************************************************/ - u16index = u16TagParamOffset; - /* Search for the TIM Element Field and return if the element is found */ while (u16index < (u16RxLen - FCS_LEN)) { if (pu8msa[u16index] == ITIM) return &pu8msa[u16index]; @@ -313,8 +256,6 @@ static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) return NULL; } -/* This function gets the current channel information from - * the 802.11n beacon/probe response frame */ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen) { u16 index; @@ -323,27 +264,12 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen) while (index < (u16RxLen - FCS_LEN)) { if (pu8msa[index] == IDSPARMS) return pu8msa[index + 2]; - /* Increment index by length information and header */ index += pu8msa[index + 1] + IE_HDR_LEN; } - /* Return current channel information from the MIB, if beacon/probe */ - /* response frame does not contain the DS parameter set IE */ - /* return (mget_CurrentChannel() + 1); */ - return 0; /* no MIB here */ + return 0; } -/** - * @brief parses the received 'N' message - * @details - * @param[in] pu8MsgBuffer The message to be parsed - * @param[out] ppstrNetworkInfo pointer to pointer to the structure containing the parsed Network Info - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) { tstrNetworkInfo *pstrNetworkInfo = NULL; @@ -357,28 +283,17 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo u8MsgType = pu8MsgBuffer[0]; - /* Check whether the received message type is 'N' */ if ('N' != u8MsgType) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } - /* Extract message ID */ u8MsgID = pu8MsgBuffer[1]; - - /* Extract message Length */ u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]); - - /* Extract WID ID */ u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]); - - /* Extract WID Length */ u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]); - - /* Assign a pointer to the WID value */ pu8WidVal = &pu8MsgBuffer[8]; - /* parse the WID value of the WID "WID_NEWORK_INFO" */ { u8 *pu8msa = NULL; u16 u16RxLen = 0; @@ -395,46 +310,30 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo pstrNetworkInfo->s8rssi = pu8WidVal[0]; - /* Assign a pointer to msa "Mac Header Start Address" */ pu8msa = &pu8WidVal[1]; u16RxLen = u16WidLen - 1; - - /* parse msa*/ - - /* Get the cap_info */ pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); - /* Get time-stamp [Low only 32 bit] */ pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); - /* Get full time-stamp [Low and High 64 bit] */ u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); - /* Get SSID */ get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen); - - /* Get BSSID */ get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); - /* - * Extract current channel information from - * the beacon/probe response frame - */ pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, u16RxLen + FCS_LEN); - /* Get beacon period */ u8index = MAC_HDR_LEN + TIME_STAMP_LEN; pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; - /* Get DTIM Period */ pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index); if (pu8TimElm) pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; @@ -456,16 +355,6 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo return 0; } -/** - * @brief Deallocates the parsed Network Info - * @details - * @param[in] pstrNetworkInfo Network Info to be deallocated - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) { s32 s32Error = 0; @@ -488,17 +377,6 @@ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) return s32Error; } -/** - * @brief parses the received Association Response frame - * @details - * @param[in] pu8Buffer The Association Response frame to be parsed - * @param[out] ppstrConnectRespInfo pointer to pointer to the structure containing the parsed Association Response Info - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 2 Apr 2012 - * @version 1.0 - */ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, tstrConnectRespInfo **ppstrConnectRespInfo) { @@ -512,20 +390,13 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, if (!pstrConnectRespInfo) return -ENOMEM; - /* u16AssocRespLen = pu8Buffer[0]; */ u16AssocRespLen = (u16)u32BufferLen; - /* get the status code */ pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer); if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - - /* get the capability */ pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer); - - /* get the Association ID */ pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer); - /* get the Information Elements */ pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); @@ -541,16 +412,6 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, return s32Error; } -/** - * @brief Deallocates the parsed Association Response Info - * @details - * @param[in] pstrNetworkInfo Network Info to be deallocated - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 2 Apr 2012 - * @version 1.0 - */ s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) { s32 s32Error = 0; -- cgit From e1a9db87a6cfa357c02cbcbaf9c351571b237c41 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:36 +0900 Subject: staging: wilc1000: renames u16RxLen variable This patch renames u16RxLen variable to rx_len to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index e6f50bac4b90..ed626b8fa9a0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -241,13 +241,13 @@ static inline u16 get_asoc_id(u8 *data) return asoc_id; } -static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) +static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 u16TagParamOffset) { u16 u16index; u16index = u16TagParamOffset; - while (u16index < (u16RxLen - FCS_LEN)) { + while (u16index < (rx_len - FCS_LEN)) { if (pu8msa[u16index] == ITIM) return &pu8msa[u16index]; u16index += (IE_HDR_LEN + pu8msa[u16index + 1]); @@ -256,12 +256,12 @@ static u8 *get_tim_elm(u8 *pu8msa, u16 u16RxLen, u16 u16TagParamOffset) return NULL; } -static u8 get_current_channel_802_11n(u8 *pu8msa, u16 u16RxLen) +static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) { u16 index; index = TAG_PARAM_OFFSET; - while (index < (u16RxLen - FCS_LEN)) { + while (index < (rx_len - FCS_LEN)) { if (pu8msa[index] == IDSPARMS) return pu8msa[index + 2]; index += pu8msa[index + 1] + IE_HDR_LEN; @@ -296,7 +296,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo { u8 *pu8msa = NULL; - u16 u16RxLen = 0; + u16 rx_len = 0; u8 *pu8TimElm = NULL; u8 *pu8IEs = NULL; u16 u16IEsLen = 0; @@ -312,7 +312,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo pu8msa = &pu8WidVal[1]; - u16RxLen = u16WidLen - 1; + rx_len = u16WidLen - 1; pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); @@ -326,7 +326,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, - u16RxLen + FCS_LEN); + rx_len + FCS_LEN); u8index = MAC_HDR_LEN + TIME_STAMP_LEN; @@ -334,11 +334,11 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; - pu8TimElm = get_tim_elm(pu8msa, u16RxLen + FCS_LEN, u8index); + pu8TimElm = get_tim_elm(pu8msa, rx_len + FCS_LEN, u8index); if (pu8TimElm) pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; - u16IEsLen = u16RxLen - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); + u16IEsLen = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (u16IEsLen > 0) { pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen, -- cgit From 6c25d7cbabb287956643775eabef1a1a2808dcaa Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:37 +0900 Subject: staging: wilc1000: renames u16TagParamOffset variable This patch renames u16TagParamOffset variable to tag_param_offset to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index ed626b8fa9a0..2f790f5a398c 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -241,11 +241,11 @@ static inline u16 get_asoc_id(u8 *data) return asoc_id; } -static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 u16TagParamOffset) +static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 tag_param_offset) { u16 u16index; - u16index = u16TagParamOffset; + u16index = tag_param_offset; while (u16index < (rx_len - FCS_LEN)) { if (pu8msa[u16index] == ITIM) -- cgit From c8a06381501c9b4d9750059967e78ffe6263e537 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 28 Jan 2016 16:13:38 +0900 Subject: staging: wilc1000: renames u16index variable This patch renames u16index variable to index to remove the prefix variable defined name. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 2f790f5a398c..49ae9b152654 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -243,14 +243,14 @@ static inline u16 get_asoc_id(u8 *data) static u8 *get_tim_elm(u8 *pu8msa, u16 rx_len, u16 tag_param_offset) { - u16 u16index; + u16 index; - u16index = tag_param_offset; + index = tag_param_offset; - while (u16index < (rx_len - FCS_LEN)) { - if (pu8msa[u16index] == ITIM) - return &pu8msa[u16index]; - u16index += (IE_HDR_LEN + pu8msa[u16index + 1]); + while (index < (rx_len - FCS_LEN)) { + if (pu8msa[index] == ITIM) + return &pu8msa[index]; + index += (IE_HDR_LEN + pu8msa[index + 1]); } return NULL; -- cgit From e9670aba93bce75cd6dc78010a8548da793ef1bb Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 29 Jan 2016 23:51:32 +0900 Subject: staging: wilc1000: wilc_msgqueue: use standard struct list_head This patch uses standard struct list_head in struct message and message_queue instead of custom linked list. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 32 ++++++++++++-------------------- drivers/staging/wilc1000/wilc_msgqueue.h | 5 +++-- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 4493ca9adcce..f57e4ec3c742 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -15,7 +15,7 @@ int wilc_mq_create(struct message_queue *mq) { spin_lock_init(&mq->lock); sema_init(&mq->sem, 0); - mq->msg_list = NULL; + INIT_LIST_HEAD(&mq->msg_list); mq->recv_count = 0; mq->exiting = false; return 0; @@ -29,6 +29,8 @@ int wilc_mq_create(struct message_queue *mq) */ int wilc_mq_destroy(struct message_queue *mq) { + struct message *msg; + mq->exiting = true; /* Release any waiting receiver thread. */ @@ -37,11 +39,10 @@ int wilc_mq_destroy(struct message_queue *mq) mq->recv_count--; } - while (mq->msg_list) { - struct message *msg = mq->msg_list->next; - - kfree(mq->msg_list); - mq->msg_list = msg; + while (!list_empty(&mq->msg_list)) { + msg = list_first_entry(&mq->msg_list, struct message, list); + list_del(&msg->list); + kfree(msg->buf); } return 0; @@ -75,7 +76,7 @@ int wilc_mq_send(struct message_queue *mq, return -ENOMEM; new_msg->len = send_buf_size; - new_msg->next = NULL; + INIT_LIST_HEAD(&new_msg->list); new_msg->buf = kmemdup(send_buf, send_buf_size, GFP_ATOMIC); if (!new_msg->buf) { kfree(new_msg); @@ -85,16 +86,7 @@ int wilc_mq_send(struct message_queue *mq, spin_lock_irqsave(&mq->lock, flags); /* add it to the message queue */ - if (!mq->msg_list) { - mq->msg_list = new_msg; - } else { - struct message *tail_msg = mq->msg_list; - - while (tail_msg->next) - tail_msg = tail_msg->next; - - tail_msg->next = new_msg; - } + list_add_tail(&new_msg->list, &mq->msg_list); spin_unlock_irqrestore(&mq->lock, flags); @@ -132,13 +124,13 @@ int wilc_mq_recv(struct message_queue *mq, down(&mq->sem); spin_lock_irqsave(&mq->lock, flags); - msg = mq->msg_list; - if (!msg) { + if (list_empty(&mq->msg_list)) { spin_unlock_irqrestore(&mq->lock, flags); PRINT_ER("msg is null\n"); return -EFAULT; } /* check buffer size */ + msg = list_first_entry(&mq->msg_list, struct message, list); if (recv_buf_size < msg->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); @@ -151,7 +143,7 @@ int wilc_mq_recv(struct message_queue *mq, memcpy(recv_buf, msg->buf, msg->len); *recv_len = msg->len; - mq->msg_list = msg->next; + list_del(&msg->list); kfree(msg->buf); kfree(msg); diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h index ddd0984337ea..846a4840e6e7 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.h +++ b/drivers/staging/wilc1000/wilc_msgqueue.h @@ -2,11 +2,12 @@ #define __WILC_MSG_QUEUE_H__ #include +#include struct message { void *buf; u32 len; - struct message *next; + struct list_head list; }; struct message_queue { @@ -14,7 +15,7 @@ struct message_queue { spinlock_t lock; bool exiting; u32 recv_count; - struct message *msg_list; + struct list_head msg_list; }; int wilc_mq_create(struct message_queue *mq); -- cgit From 8231dfc0879f8f0caecfcdc4b1ebae67cad6878d Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 29 Jan 2016 23:51:33 +0900 Subject: staging: wilc1000: wilc_msgqueue: release semaphore in error path It should be called up(&mq->sem) to release semaphore before returning error codes as -EFAULT when list is empty. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_msgqueue.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index f57e4ec3c742..5fe85eb40146 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -126,6 +126,7 @@ int wilc_mq_recv(struct message_queue *mq, if (list_empty(&mq->msg_list)) { spin_unlock_irqrestore(&mq->lock, flags); + up(&mq->sem); PRINT_ER("msg is null\n"); return -EFAULT; } -- cgit From d8c7d2b35d156e4faccfe2742b6c58492b60d065 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:37 +0900 Subject: staging: wilc1000: linux_mon: use __packed instead of __attribute__((packed)) This patch fixes the following checkpatch warning: WARNING: __packed is preferred over __attribute__((packed)) Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index e550027645b7..284dfb010f75 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -15,14 +15,14 @@ struct wilc_wfi_radiotap_hdr { struct ieee80211_radiotap_header hdr; u8 rate; -} __attribute__((packed)); +} __packed; struct wilc_wfi_radiotap_cb_hdr { struct ieee80211_radiotap_header hdr; u8 rate; u8 dump; u16 tx_flags; -} __attribute__((packed)); +} __packed; static struct net_device *wilc_wfi_mon; /* global monitor netdev */ -- cgit From 570549141aec0d21dc93f6d4cd115efe504d8a98 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:38 +0900 Subject: staging: wilc1000: linux_mon: remove blank lines after open brace '{' This patch remove blank lines after open brace found by checkpatch.pl CHECK: Blank lines aren't necessary after an open brace '{' Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 284dfb010f75..73c81134e9cb 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -71,7 +71,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) pkt_offset = GET_PKT_OFFSET(header); if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { - /* hostapd callback mgmt frame */ skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr)); @@ -103,7 +102,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) } } else { - skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr)); if (skb == NULL) { @@ -145,7 +143,6 @@ struct tx_complete_mon_data { static void mgmt_tx_complete(void *priv, int status) { - struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; u8 *buf = pv_data->buff; @@ -316,8 +313,6 @@ static const struct net_device_ops wilc_wfi_netdev_ops = { */ 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; -- cgit From c7843469a7c692a5d6e06ba393825b9bf55cd0f7 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:39 +0900 Subject: staging: wilc1000: linux_mon: remove blank line before a close brace '}' This patch removes blank lines before a close brace found by checkpatch.pl CHECK: Blank lines aren't necessary before a close brace '}' Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 73c81134e9cb..bd0b17e1e75d 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -119,7 +119,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) (1 << IEEE80211_RADIOTAP_RATE); /* | */ PRINT_INFO(HOSTAPD_DBG, "Presentflags %d\n", hdr->hdr.it_present); hdr->rate = 5; /* txrate->bitrate / 5; */ - } @@ -132,8 +131,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) memset(skb->cb, 0, sizeof(skb->cb)); netif_rx(skb); - - } struct tx_complete_mon_data { @@ -183,7 +180,6 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); return -EFAULT; - } mgmt_tx->size = len; @@ -325,7 +321,6 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi if (!wilc_wfi_mon) { PRINT_ER("failed to allocate memory\n"); return NULL; - } wilc_wfi_mon->type = ARPHRD_IEEE80211_RADIOTAP; @@ -379,5 +374,4 @@ int WILC_WFI_deinit_mon_interface(void) wilc_wfi_mon = NULL; } return 0; - } -- cgit From 24e33bd5d43568c55faf049ae653bfad41f8a472 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:40 +0900 Subject: staging: wilc1000: linux_mon: remove multiple blank lines This patch removes multiple blank lines found by checkpatch.pl CHECK: Please don't use multiple blank lines Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index bd0b17e1e75d..398fdea2ac6e 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -11,7 +11,6 @@ #include "wilc_wlan_if.h" #include "wilc_wlan.h" - struct wilc_wfi_radiotap_hdr { struct ieee80211_radiotap_header hdr; u8 rate; @@ -121,8 +120,6 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) hdr->rate = 5; /* txrate->bitrate / 5; */ } - - skb->dev = wilc_wfi_mon; skb_set_mac_header(skb, 0); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -143,8 +140,6 @@ static void mgmt_tx_complete(void *priv, int status) struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; u8 *buf = pv_data->buff; - - if (status == 1) { if (INFO || buf[0] == 0x10 || buf[0] == 0xb0) PRINT_INFO(HOSTAPD_DBG, "Packet sent successfully - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff); @@ -152,8 +147,6 @@ static void mgmt_tx_complete(void *priv, int status) PRINT_INFO(HOSTAPD_DBG, "Couldn't send packet - Size = %d - Address = %p.\n", pv_data->size, pv_data->buff); } - - /* incase of fully hosting mode, the freeing will be done in response to the cfg packet */ kfree(pv_data->buff); @@ -220,7 +213,6 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, return -EFAULT; } - rtap_len = ieee80211_get_radiotap_len(skb->data); if (skb->len < rtap_len) { PRINT_ER("Error in radiotap header\n"); @@ -273,8 +265,6 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, PRINT_INFO(HOSTAPD_DBG, "Skipping the radiotap header\n"); - - /* actual deliver of data is device-specific, and not shown here */ PRINT_INFO(HOSTAPD_DBG, "SKB netdevice name = %s\n", skb->dev->name); PRINT_INFO(HOSTAPD_DBG, "MONITOR real dev name = %s\n", mon_priv->real_ndev->name); -- cgit From a1436579493a26608318cf0b18f2eed31cd89dd0 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:41 +0900 Subject: staging: wilc1000: linux_mon: fix NULL comparison style This patch fixes NULL comparsion style found by checkpatch.pl CHECK: Comparison to NULL could be written "!wilc_wfi_mon" CHECK: Comparison to NULL could be written "!skb" CHECK: Comparison to NULL could be written "!skb" CHECK: Comparison to NULL could be written "!dev" CHECK: Comparison to NULL could be written "!mgmt_tx" CHECK: Comparison to NULL could be written "!mgmt_tx->buff" CHECK: Comparison to NULL could be written "!wilc_wfi_mon" CHECK: Comparison to NULL could be written "!mon_priv" CHECK: Comparison to NULL could be written "!priv" CHECK: Comparison to NULL could be written "wilc_wfi_mon" Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 398fdea2ac6e..7b9cc02c976b 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -54,7 +54,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) PRINT_INFO(HOSTAPD_DBG, "In monitor interface receive function\n"); - if (wilc_wfi_mon == NULL) + if (!wilc_wfi_mon) return; if (!netif_running(wilc_wfi_mon)) { @@ -73,7 +73,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) /* hostapd callback mgmt frame */ skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_cb_hdr)); - if (skb == NULL) { + if (!skb) { PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb"); return; } @@ -103,7 +103,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) } else { skb = dev_alloc_skb(size + sizeof(struct wilc_wfi_radiotap_hdr)); - if (skb == NULL) { + if (!skb) { PRINT_INFO(HOSTAPD_DBG, "Monitor if : No memory to allocate skb"); return; } @@ -156,20 +156,20 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) { struct tx_complete_mon_data *mgmt_tx = NULL; - if (dev == NULL) { + if (!dev) { PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n"); return -EFAULT; } netif_stop_queue(dev); mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC); - if (mgmt_tx == NULL) { + if (!mgmt_tx) { PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); return -EFAULT; } mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); - if (mgmt_tx->buff == NULL) { + if (!mgmt_tx->buff) { PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); return -EFAULT; @@ -203,12 +203,12 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, struct sk_buff *skb2; struct wilc_wfi_radiotap_cb_hdr *cb_hdr; - if (wilc_wfi_mon == NULL) + if (!wilc_wfi_mon) return -EFAULT; mon_priv = netdev_priv(wilc_wfi_mon); - if (mon_priv == NULL) { + if (!mon_priv) { PRINT_ER("Monitor interface private structure is NULL\n"); return -EFAULT; } @@ -324,7 +324,7 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi return NULL; } priv = netdev_priv(wilc_wfi_mon); - if (priv == NULL) { + if (!priv) { PRINT_ER("private structure is NULL\n"); return NULL; } @@ -347,7 +347,7 @@ int WILC_WFI_deinit_mon_interface(void) { bool rollback_lock = false; - if (wilc_wfi_mon != NULL) { + if (wilc_wfi_mon) { PRINT_D(HOSTAPD_DBG, "In Deinit monitor interface\n"); PRINT_D(HOSTAPD_DBG, "RTNL is being locked\n"); if (rtnl_is_locked()) { -- cgit From 382af7f2fdedb62bccdd887af4d43b736804d16f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:42 +0900 Subject: staging: wilc1000: linux_mon: remove space after a cast This patch removes space after a type cast found by checkpatch.pl CHECK: No space is necessary after a cast Signed-off-by: Chaehyun Lim 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 7b9cc02c976b..0c3dee36936f 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -80,7 +80,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) memcpy(skb_put(skb, size), buff, size); - cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb, sizeof(*cb_hdr)); + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb, sizeof(*cb_hdr)); memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ @@ -109,7 +109,7 @@ void WILC_WFI_monitor_rx(u8 *buff, u32 size) } memcpy(skb_put(skb, size), buff, size); - hdr = (struct wilc_wfi_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); + hdr = (struct wilc_wfi_radiotap_hdr *)skb_push(skb, sizeof(*hdr)); memset(hdr, 0, sizeof(struct wilc_wfi_radiotap_hdr)); hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ hdr->hdr.it_len = cpu_to_le16(sizeof(struct wilc_wfi_radiotap_hdr)); @@ -236,7 +236,7 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, memcpy(skb_put(skb2, skb->len), skb->data, skb->len); - cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *) skb_push(skb2, sizeof(*cb_hdr)); + cb_hdr = (struct wilc_wfi_radiotap_cb_hdr *)skb_push(skb2, sizeof(*cb_hdr)); memset(cb_hdr, 0, sizeof(struct wilc_wfi_radiotap_cb_hdr)); cb_hdr->hdr.it_version = 0; /* PKTHDR_RADIOTAP_VERSION; */ -- cgit From 964d8936dd3578c706214461e428167fb282a3e1 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:43 +0900 Subject: staging: wilc1000: linux_mon: insert blank line after a function This patch inserts a blank line afer function found by checkpatch.pl CHECK: Please use a blank line after function/struct/union/enum declarations Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 0c3dee36936f..53d0caf9d91e 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -152,6 +152,7 @@ static void mgmt_tx_complete(void *priv, int status) kfree(pv_data); } + static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) { struct tx_complete_mon_data *mgmt_tx = NULL; -- cgit From b4a53a621223d2e6f3f4012c7165f5ccaca41d9c Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:44 +0900 Subject: staging: wilc1000: linux_mon: add braces on all arms of if statement This patch adds braces on all arms of if statement found by checkpatch.pl CHECK: braces {} should be used on all arms of this statement Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 53d0caf9d91e..255383c6cf2b 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -278,8 +278,9 @@ static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb, if (!(memcmp(srcAdd, bssid, 6))) { mon_mgmt_tx(mon_priv->real_ndev, skb->data, skb->len); dev_kfree_skb(skb); - } else + } else { ret = wilc_mac_xmit(skb, mon_priv->real_ndev); + } return ret; } -- cgit From fa611271b4d681d02520c458c555e48ee11d61d4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:45 +0900 Subject: staging: wilc1000: linux_mon: fix coding style of kmalloc usage This patch fixes coding style of kmalloc usage found by checkpatch.pl CHECK: Prefer kmalloc(sizeof(*mgmt_tx)...) over kmalloc(sizeof(struct tx_complete_mon_data)...) Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 255383c6cf2b..a19755ebd72c 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -163,7 +163,7 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) } netif_stop_queue(dev); - mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC); + mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); if (!mgmt_tx) { PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); return -EFAULT; -- cgit From b026f6e8d607f40f9fcdc0bc9966db4bde4a1129 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:46 +0900 Subject: staging: wilc1000: linux_mon: fix error code of kmalloc This patch fixes error codes as -ENOMEM instead of using -EFAULT if kmalloc is failed. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index a19755ebd72c..1443a238a520 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -166,14 +166,14 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); if (!mgmt_tx) { PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); - return -EFAULT; + return -ENOMEM; } mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); if (!mgmt_tx->buff) { PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); - return -EFAULT; + return -ENOMEM; } mgmt_tx->size = len; -- cgit From e5349952de5b1138e6275529e4ec08c0ed33777f Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Mon, 1 Feb 2016 21:26:47 +0900 Subject: staging: wilc1000: linux_mon: remove debug message of kmalloc failure There is no need to print debug message when kmalloc is failed. This message is redundant. The code already show us that kmalloc is failed. The braces of first if statement is remove as well because if statement has a single statement. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index 1443a238a520..e9bb0ec5cbc6 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -164,14 +164,11 @@ static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len) netif_stop_queue(dev); mgmt_tx = kmalloc(sizeof(*mgmt_tx), GFP_ATOMIC); - if (!mgmt_tx) { - PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + if (!mgmt_tx) return -ENOMEM; - } mgmt_tx->buff = kmalloc(len, GFP_ATOMIC); if (!mgmt_tx->buff) { - PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); kfree(mgmt_tx); return -ENOMEM; } -- cgit From 04d5a21d62887b9bc5383fc68ab2756287da4532 Mon Sep 17 00:00:00 2001 From: Kiran Patil Date: Wed, 9 Dec 2015 15:50:23 -0800 Subject: i40e: Add mac_filter_element at the end of the list instead of HEAD Add MAC filter element to the end of the list in the given order, just to be tidy, and just in case there are ever any ordering issues in the future. Change-ID: Idc15276147593ea9393ac72c861f9c7905a791b4 Signed-off-by: Kiran Patil 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 8f3b53e0dc46..d078a6331365 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1368,7 +1368,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, f->changed = true; INIT_LIST_HEAD(&f->list); - list_add(&f->list, &vsi->mac_filter_list); + list_add_tail(&f->list, &vsi->mac_filter_list); } /* increment counter and add a new flag if needed */ -- cgit From 6e35c04cf633e55648acb9ccabff42aa37bd4044 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 9 Dec 2015 15:50:24 -0800 Subject: i40e/i40evf: Fix RSS rx-flow-hash configuration through ethtool This patch fixes the Hash PCTYPE enable for X722 since it supports a broader selection of PCTYPES for TCP and UDP. This patch also fixes a bug in XL710, X710, X722 support for RSS, as of now we cannot reduce the (4)tuple for RSS for TCP/IPv4/IPV6 or UDP/IPv4/IPv6 packets since this requires a product feature change that comes in a later release. A VF should never be allowed to change the tuples for RSS for any PCTYPE since that's a global setting for the device in case of i40e devices. Change-ID: I0ee7203c9b24813260f58f3220798bc9d9ac4a12 Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 14 +++----- drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 40 +++++----------------- 2 files changed, 12 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 29d5833e24a3..c8b9dcae630a 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2166,8 +2166,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case TCP_V4_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); break; @@ -2178,8 +2177,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case TCP_V6_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); break; @@ -2190,9 +2188,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case UDP_V4_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); @@ -2204,9 +2200,7 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case UDP_V6_FLOW: switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - break; + return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index a4c9feb589e7..8906785446ab 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -477,54 +477,30 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, switch (nfc->flow_type) { case TCP_V4_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - break; - default: + else return -EINVAL; - } break; case TCP_V6_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - break; - default: + else return -EINVAL; - } break; case UDP_V4_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); - break; - default: + } else { return -EINVAL; } break; case UDP_V6_FLOW: - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - hena &= ~(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | - BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); - break; - default: + } else { return -EINVAL; } break; -- cgit From 48b1804ee3cdad7bf115666eb35edf12a734710f Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Wed, 9 Dec 2015 15:50:25 -0800 Subject: i40e: Replace X722 mac check in ethtool get_settings 100M SGMII is only supported on X722. Replace the mac check with a feature flag check that is only set for the X722 device. Change-ID: I53452d9af6af8cd9dca8500215fbc6ce93418f52 Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 68f2204ec6f3..47f6c0a9c9fe 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -339,6 +339,7 @@ struct i40e_pf { #define I40E_FLAG_VEB_MODE_ENABLED BIT_ULL(40) #define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE BIT_ULL(41) #define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42) +#define I40E_FLAG_100M_SGMII_CAPABLE BIT_ULL(43) #define I40E_FLAG_PF_MAC BIT_ULL(50) /* tracks features that get auto disabled by errors */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index c8b9dcae630a..252a9dd941d4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -340,7 +340,7 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, SUPPORTED_1000baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) ecmd->advertising |= ADVERTISED_1000baseT_Full; - if (pf->hw.mac.type == I40E_MAC_X722) { + if (pf->flags & I40E_FLAG_100M_SGMII_CAPABLE) { ecmd->supported |= SUPPORTED_100baseT_Full; if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) -- cgit From 209dc4daf23f92b3e0bc6d602411506c4083e421 Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Dec 2015 15:50:27 -0800 Subject: i40evf: allow channel bonding of VFs In some modes, bonding would not enslave VF interfaces. This is due to bonding calling change_mtu and the immediately calling open. Because of the asynchronous nature of the admin queue mechanism, the VF returns -EBUSY to the open call, because it knows the previous operation hasn't finished yet. This causes bonding to fail with a less-than-useful error message. To fix this, remove the check for pending operations at the beginning of open. But this introduces a new bug where the driver will panic on a quick close/open cycle. To fix that, we add a new driver state, __I40EVF_DOWN_PENDING, that the driver enters when down is called. The driver finally transitions to a fully DOWN state when it receives confirmation from the PF driver that all the queues are disabled. This allows open to complete even if there is a pending mtu change, and bonding is finally happy. Change-ID: I06f4c7e435d5bacbfceaa7c3f209e0ff04be21cc Signed-off-by: Mitch Williams Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40evf/i40evf.h | 1 + drivers/net/ethernet/intel/i40evf/i40evf_main.c | 9 +++++---- drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c | 2 ++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h index be1b72b93888..9e15f68d9ddd 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf.h +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -173,6 +173,7 @@ enum i40evf_state_t { __I40EVF_RESETTING, /* in reset */ /* Below here, watchdog is running */ __I40EVF_DOWN, /* ready, can be opened */ + __I40EVF_DOWN_PENDING, /* descending, waiting for watchdog */ __I40EVF_TESTING, /* in ethtool self-test */ __I40EVF_RUNNING, /* opened, working */ }; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 94da913b151d..d1c4335114fc 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1032,7 +1032,7 @@ void i40evf_down(struct i40evf_adapter *adapter) struct net_device *netdev = adapter->netdev; struct i40evf_mac_filter *f; - if (adapter->state == __I40EVF_DOWN) + if (adapter->state <= __I40EVF_DOWN_PENDING) return; while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK, @@ -2142,7 +2142,8 @@ static int i40evf_open(struct net_device *netdev) dev_err(&adapter->pdev->dev, "Unable to open device due to PF driver failure.\n"); return -EIO; } - if (adapter->state != __I40EVF_DOWN || adapter->aq_required) + + if (adapter->state != __I40EVF_DOWN) return -EBUSY; /* allocate transmit descriptors */ @@ -2197,14 +2198,14 @@ static int i40evf_close(struct net_device *netdev) { struct i40evf_adapter *adapter = netdev_priv(netdev); - if (adapter->state <= __I40EVF_DOWN) + if (adapter->state <= __I40EVF_DOWN_PENDING) return 0; set_bit(__I40E_DOWN, &adapter->vsi.state); i40evf_down(adapter); - adapter->state = __I40EVF_DOWN; + adapter->state = __I40EVF_DOWN_PENDING; i40evf_free_traffic_irqs(adapter); return 0; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c index c1c526283757..d3739cc5b608 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c @@ -804,6 +804,8 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, case I40E_VIRTCHNL_OP_DISABLE_QUEUES: i40evf_free_all_tx_resources(adapter); i40evf_free_all_rx_resources(adapter); + if (adapter->state == __I40EVF_DOWN_PENDING) + adapter->state = __I40EVF_DOWN; break; case I40E_VIRTCHNL_OP_VERSION: case I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP: -- cgit From 406e734aa893fa5841e67de6d4f688ba70a82e4f Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Thu, 10 Dec 2015 11:38:49 -0800 Subject: i40e: define function capabilities in only one place The device capabilities were defined in two places, and neither had all the definitions. It really belongs with the AQ API definition, so this patch removes the other set of definitions and fills out the missing item. Change-ID: I273ba7d79a476cd11d2e0ca5825fec1716740de2 Signed-off-by: Shannon Nelson Acked-by: Jesse Brandeburg 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 | 85 +++++++--------------- .../net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 1 + 3 files changed, 30 insertions(+), 57 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index b22012a446a6..256ce6549f61 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -422,6 +422,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_LED 0x0061 #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_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 6a034ddac36a..4bdb08bb27d7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -2765,35 +2765,6 @@ i40e_aq_erase_nvm_exit: return status; } -#define I40E_DEV_FUNC_CAP_SWITCH_MODE 0x01 -#define I40E_DEV_FUNC_CAP_MGMT_MODE 0x02 -#define I40E_DEV_FUNC_CAP_NPAR 0x03 -#define I40E_DEV_FUNC_CAP_OS2BMC 0x04 -#define I40E_DEV_FUNC_CAP_VALID_FUNC 0x05 -#define I40E_DEV_FUNC_CAP_SRIOV_1_1 0x12 -#define I40E_DEV_FUNC_CAP_VF 0x13 -#define I40E_DEV_FUNC_CAP_VMDQ 0x14 -#define I40E_DEV_FUNC_CAP_802_1_QBG 0x15 -#define I40E_DEV_FUNC_CAP_802_1_QBH 0x16 -#define I40E_DEV_FUNC_CAP_VSI 0x17 -#define I40E_DEV_FUNC_CAP_DCB 0x18 -#define I40E_DEV_FUNC_CAP_FCOE 0x21 -#define I40E_DEV_FUNC_CAP_ISCSI 0x22 -#define I40E_DEV_FUNC_CAP_RSS 0x40 -#define I40E_DEV_FUNC_CAP_RX_QUEUES 0x41 -#define I40E_DEV_FUNC_CAP_TX_QUEUES 0x42 -#define I40E_DEV_FUNC_CAP_MSIX 0x43 -#define I40E_DEV_FUNC_CAP_MSIX_VF 0x44 -#define I40E_DEV_FUNC_CAP_FLOW_DIRECTOR 0x45 -#define I40E_DEV_FUNC_CAP_IEEE_1588 0x46 -#define I40E_DEV_FUNC_CAP_FLEX10 0xF1 -#define I40E_DEV_FUNC_CAP_CEM 0xF2 -#define I40E_DEV_FUNC_CAP_IWARP 0x51 -#define I40E_DEV_FUNC_CAP_LED 0x61 -#define I40E_DEV_FUNC_CAP_SDP 0x62 -#define I40E_DEV_FUNC_CAP_MDIO 0x63 -#define I40E_DEV_FUNC_CAP_WR_CSR_PROT 0x64 - /** * i40e_parse_discover_capabilities * @hw: pointer to the hw struct @@ -2832,79 +2803,79 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, major_rev = cap->major_rev; switch (id) { - case I40E_DEV_FUNC_CAP_SWITCH_MODE: + case I40E_AQ_CAP_ID_SWITCH_MODE: p->switch_mode = number; break; - case I40E_DEV_FUNC_CAP_MGMT_MODE: + case I40E_AQ_CAP_ID_MNG_MODE: p->management_mode = number; break; - case I40E_DEV_FUNC_CAP_NPAR: + case I40E_AQ_CAP_ID_NPAR_ACTIVE: p->npar_enable = number; break; - case I40E_DEV_FUNC_CAP_OS2BMC: + case I40E_AQ_CAP_ID_OS2BMC_CAP: p->os2bmc = number; break; - case I40E_DEV_FUNC_CAP_VALID_FUNC: + case I40E_AQ_CAP_ID_FUNCTIONS_VALID: p->valid_functions = number; break; - case I40E_DEV_FUNC_CAP_SRIOV_1_1: + case I40E_AQ_CAP_ID_SRIOV: if (number == 1) p->sr_iov_1_1 = true; break; - case I40E_DEV_FUNC_CAP_VF: + case I40E_AQ_CAP_ID_VF: p->num_vfs = number; p->vf_base_id = logical_id; break; - case I40E_DEV_FUNC_CAP_VMDQ: + case I40E_AQ_CAP_ID_VMDQ: if (number == 1) p->vmdq = true; break; - case I40E_DEV_FUNC_CAP_802_1_QBG: + case I40E_AQ_CAP_ID_8021QBG: if (number == 1) p->evb_802_1_qbg = true; break; - case I40E_DEV_FUNC_CAP_802_1_QBH: + case I40E_AQ_CAP_ID_8021QBR: if (number == 1) p->evb_802_1_qbh = true; break; - case I40E_DEV_FUNC_CAP_VSI: + case I40E_AQ_CAP_ID_VSI: p->num_vsis = number; break; - case I40E_DEV_FUNC_CAP_DCB: + case I40E_AQ_CAP_ID_DCB: if (number == 1) { p->dcb = true; p->enabled_tcmap = logical_id; p->maxtc = phys_id; } break; - case I40E_DEV_FUNC_CAP_FCOE: + case I40E_AQ_CAP_ID_FCOE: if (number == 1) p->fcoe = true; break; - case I40E_DEV_FUNC_CAP_ISCSI: + case I40E_AQ_CAP_ID_ISCSI: if (number == 1) p->iscsi = true; break; - case I40E_DEV_FUNC_CAP_RSS: + case I40E_AQ_CAP_ID_RSS: p->rss = true; p->rss_table_size = number; p->rss_table_entry_width = logical_id; break; - case I40E_DEV_FUNC_CAP_RX_QUEUES: + case I40E_AQ_CAP_ID_RXQ: p->num_rx_qp = number; p->base_queue = phys_id; break; - case I40E_DEV_FUNC_CAP_TX_QUEUES: + case I40E_AQ_CAP_ID_TXQ: p->num_tx_qp = number; p->base_queue = phys_id; break; - case I40E_DEV_FUNC_CAP_MSIX: + case I40E_AQ_CAP_ID_MSIX: p->num_msix_vectors = number; break; - case I40E_DEV_FUNC_CAP_MSIX_VF: + case I40E_AQ_CAP_ID_VF_MSIX: p->num_msix_vectors_vf = number; break; - case I40E_DEV_FUNC_CAP_FLEX10: + case I40E_AQ_CAP_ID_FLEX10: if (major_rev == 1) { if (number == 1) { p->flex10_enable = true; @@ -2920,38 +2891,38 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff, p->flex10_mode = logical_id; p->flex10_status = phys_id; break; - case I40E_DEV_FUNC_CAP_CEM: + case I40E_AQ_CAP_ID_CEM: if (number == 1) p->mgmt_cem = true; break; - case I40E_DEV_FUNC_CAP_IWARP: + case I40E_AQ_CAP_ID_IWARP: if (number == 1) p->iwarp = true; break; - case I40E_DEV_FUNC_CAP_LED: + case I40E_AQ_CAP_ID_LED: if (phys_id < I40E_HW_CAP_MAX_GPIO) p->led[phys_id] = true; break; - case I40E_DEV_FUNC_CAP_SDP: + case I40E_AQ_CAP_ID_SDP: if (phys_id < I40E_HW_CAP_MAX_GPIO) p->sdp[phys_id] = true; break; - case I40E_DEV_FUNC_CAP_MDIO: + case I40E_AQ_CAP_ID_MDIO: if (number == 1) { p->mdio_port_num = phys_id; p->mdio_port_mode = logical_id; } break; - case I40E_DEV_FUNC_CAP_IEEE_1588: + case I40E_AQ_CAP_ID_1588: if (number == 1) p->ieee_1588 = true; break; - case I40E_DEV_FUNC_CAP_FLOW_DIRECTOR: + case I40E_AQ_CAP_ID_FLOW_DIRECTOR: p->fd = true; p->fd_filters_guaranteed = number; p->fd_filters_best_effort = logical_id; break; - case I40E_DEV_FUNC_CAP_WR_CSR_PROT: + case I40E_AQ_CAP_ID_WSR_PROT: p->wr_csr_prot = (u64)number; p->wr_csr_prot |= (u64)logical_id << 32; break; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index f5b2b369dc7c..0d3bc3be0527 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -419,6 +419,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_LED 0x0061 #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_FLEX10 0x00F1 #define I40E_AQ_CAP_ID_CEM 0x00F2 -- cgit From 10311540fab76c7e5530bf5f0267a3d1b8d5818e Mon Sep 17 00:00:00 2001 From: Mitch Williams Date: Wed, 9 Dec 2015 15:50:30 -0800 Subject: i40evf: null out ring pointers on free Since we check these ring pointers to make sure we don't double-allocate or double-free the rings, we had better null them out after we free them. In very rare cases this can cause a panic if the driver is removed during reset recovery. Change-ID: Ib06eb4910a3058275c8f7ec5ef7f45baa4674f96 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 d1c4335114fc..81d958422ccf 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1122,7 +1122,9 @@ static void i40evf_free_queues(struct i40evf_adapter *adapter) if (!adapter->vsi_res) return; kfree(adapter->tx_rings); + adapter->tx_rings = NULL; kfree(adapter->rx_rings); + adapter->rx_rings = NULL; } /** -- cgit From 8eed76fa4885f1ed9f19f4d3a16dd24cebf09c19 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Wed, 9 Dec 2015 15:50:31 -0800 Subject: i40e: Cleanup the code with respect to restarting autoneg The restart-autoneg work around does not apply to X722. Added a flag to set it only for the right MAC and right FW version where the work around should be applied. Signed-off-by: Anjali Singhai Jain Change-ID: I942c3ff40cccd1e56f424b1da776b020fe3c9d2a 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 | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 47f6c0a9c9fe..53ed3bdd8363 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -340,6 +340,7 @@ struct i40e_pf { #define I40E_FLAG_GENEVE_OFFLOAD_CAPABLE BIT_ULL(41) #define I40E_FLAG_NO_PCI_LINK_CHECK BIT_ULL(42) #define I40E_FLAG_100M_SGMII_CAPABLE BIT_ULL(43) +#define I40E_FLAG_RESTART_AUTONEG BIT_ULL(44) #define I40E_FLAG_PF_MAC BIT_ULL(50) /* tracks features that get auto disabled by errors */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index d078a6331365..1a7022ca4750 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6889,8 +6889,7 @@ static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit) wr32(hw, I40E_REG_MSS, val); } - if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || - (pf->hw.aq.fw_maj_ver < 4)) { + if (pf->flags & I40E_FLAG_RESTART_AUTONEG) { msleep(75); ret = i40e_aq_set_link_restart_an(&pf->hw, true, NULL); if (ret) @@ -8367,6 +8366,12 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->hw.func_caps.fd_filters_best_effort; } + if (((pf->hw.mac.type == I40E_MAC_X710) || + (pf->hw.mac.type == I40E_MAC_XL710)) && + (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || + (pf->hw.aq.fw_maj_ver < 4))) + pf->flags |= I40E_FLAG_RESTART_AUTONEG; + if (pf->hw.func_caps.vmdq) { pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI; pf->flags |= I40E_FLAG_VMDQ_ENABLED; @@ -10904,8 +10909,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) wr32(hw, I40E_REG_MSS, val); } - if (((pf->hw.aq.fw_maj_ver == 4) && (pf->hw.aq.fw_min_ver < 33)) || - (pf->hw.aq.fw_maj_ver < 4)) { + if (pf->flags & I40E_FLAG_RESTART_AUTONEG) { msleep(75); err = i40e_aq_set_link_restart_an(&pf->hw, true, NULL); if (err) -- cgit From 5afdaaa0555257f3c42b141908567d40aca0e1d1 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Thu, 10 Dec 2015 11:38:50 -0800 Subject: i40e: update features with right offload Synchronize code bases and add SCTP offload support. Change-ID: I9f99071f7176225479026930c387bf681a47494e Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1a7022ca4750..486ae1604138 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8947,11 +8947,11 @@ 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_RXCSUM | - NETIF_F_GSO_UDP_TUNNEL | - NETIF_F_GSO_GRE | - NETIF_F_TSO; + netdev->hw_enc_features |= NETIF_F_IP_CSUM | + NETIF_F_GSO_UDP_TUNNEL | + NETIF_F_GSO_GRE | + NETIF_F_TSO | + 0; netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | -- cgit From 4f9e697ebbf40ba482ad0481da1e978440f2a53e Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Thu, 10 Dec 2015 11:38:51 -0800 Subject: i40e: bump version to 1.4.10 Bump. Change-ID: Ic9a495feb9ab0606f953c3848b0acf67169d3930 Signed-off-by: Catherine Sullivan 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 486ae1604138..c88583e112fa 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -51,7 +51,7 @@ static const char i40e_driver_string[] = #define DRV_VERSION_MAJOR 1 #define DRV_VERSION_MINOR 4 -#define DRV_VERSION_BUILD 8 +#define DRV_VERSION_BUILD 10 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." \ __stringify(DRV_VERSION_BUILD) DRV_KERN -- cgit From 35dae51de3e99db10f355642f5fc67719b93f558 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:03 -0800 Subject: i40e: add new device IDs for X722 Add the KX and QSFP device IDs for X722. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_common.c | 2 ++ drivers/net/ethernet/intel/i40e/i40e_devids.h | 2 ++ drivers/net/ethernet/intel/i40e/i40e_main.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 4bdb08bb27d7..3b03a3165ca7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -55,6 +55,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw) case I40E_DEV_ID_20G_KR2_A: hw->mac.type = I40E_MAC_XL710; break; + case I40E_DEV_ID_KX_X722: + case I40E_DEV_ID_QSFP_X722: case I40E_DEV_ID_SFP_X722: case I40E_DEV_ID_1G_BASE_T_X722: case I40E_DEV_ID_10G_BASE_T_X722: diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h index 448ef4c17efb..f7ce5c7c9003 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_devids.h +++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h @@ -41,6 +41,8 @@ #define I40E_DEV_ID_10G_BASE_T4 0x1589 #define I40E_DEV_ID_VF 0x154C #define I40E_DEV_ID_VF_HV 0x1571 +#define I40E_DEV_ID_KX_X722 0x37CE +#define I40E_DEV_ID_QSFP_X722 0x37CF #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 diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c88583e112fa..b3e671bb83ff 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -90,6 +90,8 @@ static const struct pci_device_id i40e_pci_tbl[] = { {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_10G_BASE_T4), 0}, {PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_KX_X722), 0}, + {PCI_VDEVICE(INTEL, I40E_DEV_ID_QSFP_X722), 0}, {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}, -- cgit From 95a73780921aecc5e66022e000fcf8aeecfb53cf Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:04 -0800 Subject: i40e: Extend ethtool RSS hooks for X722 This patch adds another way to access the RSS keys and lut using the AQ for X722 devices. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 53 ++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b3e671bb83ff..bd81a9770c5b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -7936,6 +7936,52 @@ static int i40e_vsi_config_rss(struct i40e_vsi *vsi) return ret; } +/** + * i40e_get_rss_aq - Get RSS keys and lut by using AQ commands + * @vsi: Pointer to vsi structure + * @seed: Buffter to store the hash keys + * @lut: Buffer to store the lookup table entries + * @lut_size: Size of buffer to store the lookup table entries + * + * Return 0 on success, negative on failure + */ +static int i40e_get_rss_aq(struct i40e_vsi *vsi, const u8 *seed, + u8 *lut, u16 lut_size) +{ + struct i40e_pf *pf = vsi->back; + struct i40e_hw *hw = &pf->hw; + int ret = 0; + + if (seed) { + ret = i40e_aq_get_rss_key(hw, vsi->id, + (struct i40e_aqc_get_set_rss_key_data *)seed); + if (ret) { + dev_info(&pf->pdev->dev, + "Cannot get RSS key, err %s aq_err %s\n", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, + pf->hw.aq.asq_last_status)); + return ret; + } + } + + if (lut) { + bool pf_lut = vsi->type == I40E_VSI_MAIN ? true : false; + + ret = i40e_aq_get_rss_lut(hw, vsi->id, pf_lut, lut, lut_size); + if (ret) { + dev_info(&pf->pdev->dev, + "Cannot get RSS lut, err %s aq_err %s\n", + i40e_stat_str(&pf->hw, ret), + i40e_aq_str(&pf->hw, + pf->hw.aq.asq_last_status)); + return ret; + } + } + + return ret; +} + /** * i40e_config_rss_reg - Configure RSS keys and lut by writing registers * @vsi: Pointer to vsi structure @@ -8038,7 +8084,12 @@ int i40e_config_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) */ int i40e_get_rss(struct i40e_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size) { - return i40e_get_rss_reg(vsi, seed, lut, lut_size); + struct i40e_pf *pf = vsi->back; + + if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) + return i40e_get_rss_aq(vsi, seed, lut, lut_size); + else + return i40e_get_rss_reg(vsi, seed, lut, lut_size); } /** -- cgit From 3d0da5b78262c1f86294419c7a70e4c837aca159 Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:05 -0800 Subject: i40e/i40evf: Fix for UDP/TCP RSS for X722 The PCTYPES for the X710 and X722 families are different. This patch makes adjustments for that. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 18 ++++++++++++++ drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 +++++ drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 29 +++++++++++++++++++--- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 +++--- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 252a9dd941d4..8a3f93ddbcc3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -2168,6 +2168,10 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); break; default: @@ -2179,6 +2183,10 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); break; default: @@ -2190,6 +2198,11 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + 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) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); break; @@ -2202,6 +2215,11 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) case 0: return -EINVAL; case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) + 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) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); break; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 63e62f9aec6e..86aacb9f4d44 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1213,6 +1213,12 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RSS_REG; } + if (pf->flags & I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE) { + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + vfres->vf_offload_flags |= + I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2; + } + if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING; diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c index 8906785446ab..bd1c2728bc5c 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c @@ -459,6 +459,7 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, struct ethtool_rxnfc *nfc) { 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); @@ -477,19 +478,34 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, switch (nfc->flow_type) { case TCP_V4_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP); - else + } else { return -EINVAL; + } break; case TCP_V6_FLOW: - if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) + if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2) + hena |= + BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK); + hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP); - else + } else { return -EINVAL; + } break; 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 |= + 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) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4)); } else { @@ -498,6 +514,11 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter, break; 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 |= + 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) | BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6)); } else { diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 81d958422ccf..798f0dedf14f 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -1456,7 +1456,11 @@ static int i40evf_init_rss(struct i40evf_adapter *adapter) int ret; /* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */ - hena = I40E_DEFAULT_RSS_HENA; + 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)); @@ -2507,8 +2511,6 @@ static void i40evf_init_task(struct work_struct *work) if (adapter->vf_res->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; - if (!RSS_AQ(adapter)) - i40evf_init_rss(adapter); err = i40evf_request_misc_irq(adapter); if (err) goto err_sw_init; -- cgit From f6d83d1376f496e6218080dd6eb663830672813f Mon Sep 17 00:00:00 2001 From: Anjali Singhai Jain Date: Tue, 22 Dec 2015 14:25:07 -0800 Subject: i40evf: add new write-back mode Add write-back on interrupt throttle rate timer expiration support for the i40evf driver, when running on X722 devices. Signed-off-by: Anjali Singhai Jain Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 6 ++++++ drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 16 ++++++++++++++++ drivers/net/ethernet/intel/i40evf/i40evf_main.c | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 86aacb9f4d44..659d78270fdb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -1222,6 +1222,12 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg) if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) 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) + vfres->vf_offload_flags |= + I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR; + } + vfres->num_vsis = num_vsis; vfres->num_queue_pairs = vf->num_queue_pairs; vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c index 7a00657dacda..7d663fb61927 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c @@ -252,6 +252,22 @@ static bool i40e_clean_tx_irq(struct i40e_ring *tx_ring, int budget) tx_ring->q_vector->tx.total_bytes += total_bytes; tx_ring->q_vector->tx.total_packets += total_packets; + if (tx_ring->flags & I40E_TXR_FLAGS_WB_ON_ITR) { + unsigned int j = 0; + /* check to see if there are < 4 descriptors + * waiting to be written back, then kick the hardware to force + * them to be written back in case we stay in NAPI. + * In this mode on X722 we do not enable Interrupt. + */ + j = i40evf_get_tx_pending(tx_ring); + + if (budget && + ((j / (WB_STRIDE + 1)) == 0) && (j > 0) && + !test_bit(__I40E_DOWN, &tx_ring->vsi->state) && + (I40E_DESC_UNUSED(tx_ring) != tx_ring->count)) + tx_ring->arm_wb = true; + } + netdev_tx_completed_queue(netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index), total_packets, total_bytes); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 798f0dedf14f..615ad0f1fdc4 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -2511,6 +2511,11 @@ static void i40evf_init_task(struct work_struct *work) if (adapter->vf_res->vf_offload_flags & I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; + + if (adapter->vf_res->vf_offload_flags & + I40E_VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) + adapter->flags |= I40EVF_FLAG_WB_ON_ITR_CAPABLE; + err = i40evf_request_misc_irq(adapter); if (err) goto err_sw_init; -- cgit From 2803b16c10ea7eec170c485388f5f26ae30e92fe Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 22 Dec 2015 14:25:08 -0800 Subject: i40e/i40evf: Use private workqueue As done per ixgbe, use a private workqueue to avoid blocking the system workqueue. This avoids some strange side effects when some other entity is depending on the system work queue. Change-ID: Ic8ba08f5b03696cf638b21afd25fbae7738d55ee Signed-off-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_main.c | 15 ++++++++++++++- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 +++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index bd81a9770c5b..3e482bcd5287 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -112,6 +112,8 @@ MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +static struct workqueue_struct *i40e_wq; + /** * i40e_allocate_dma_mem_d - OS specific memory alloc for shared code * @hw: pointer to the HW structure @@ -297,7 +299,7 @@ static void i40e_service_event_schedule(struct i40e_pf *pf) if (!test_bit(__I40E_DOWN, &pf->state) && !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) && !test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state)) - schedule_work(&pf->service_task); + queue_work(i40e_wq, &pf->service_task); } /** @@ -11470,6 +11472,16 @@ static int __init i40e_init_module(void) i40e_driver_string, i40e_driver_version_str); pr_info("%s: %s\n", i40e_driver_name, i40e_copyright); + /* we will see if single thread per module is enough for now, + * it can't be any worse than using the system workqueue which + * was already single threaded + */ + i40e_wq = create_singlethread_workqueue(i40e_driver_name); + if (!i40e_wq) { + pr_err("%s: Failed to create workqueue\n", i40e_driver_name); + return -ENOMEM; + } + i40e_dbg_init(); return pci_register_driver(&i40e_driver); } @@ -11484,6 +11496,7 @@ module_init(i40e_init_module); static void __exit i40e_exit_module(void) { pci_unregister_driver(&i40e_driver); + destroy_workqueue(i40e_wq); i40e_dbg_exit(); } module_exit(i40e_exit_module); diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c index 615ad0f1fdc4..66964eb6b7de 100644 --- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c +++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c @@ -69,6 +69,8 @@ MODULE_DESCRIPTION("Intel(R) XL710 X710 Virtual Function Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +static struct workqueue_struct *i40evf_wq; + /** * i40evf_allocate_dma_mem_d - OS specific memory alloc for shared code * @hw: pointer to the HW structure @@ -182,7 +184,7 @@ static void i40evf_tx_timeout(struct net_device *netdev) if (!(adapter->flags & (I40EVF_FLAG_RESET_PENDING | I40EVF_FLAG_RESET_NEEDED))) { adapter->flags |= I40EVF_FLAG_RESET_NEEDED; - schedule_work(&adapter->reset_task); + queue_work(i40evf_wq, &adapter->reset_task); } } @@ -2895,6 +2897,11 @@ static int __init i40evf_init_module(void) pr_info("%s\n", i40evf_copyright); + i40evf_wq = create_singlethread_workqueue(i40evf_driver_name); + if (!i40evf_wq) { + pr_err("%s: Failed to create workqueue\n", i40evf_driver_name); + return -ENOMEM; + } ret = pci_register_driver(&i40evf_driver); return ret; } @@ -2910,6 +2917,7 @@ module_init(i40evf_init_module); static void __exit i40evf_exit_module(void) { pci_unregister_driver(&i40evf_driver); + destroy_workqueue(i40evf_wq); } module_exit(i40evf_exit_module); -- cgit From 4ba40bcea7046a1fa9b57a8cb4bcb8776e86e7ed Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:09 -0800 Subject: i40e: add new proxy-wol bit for X722 Add the new proxy-wake-on-lan capability bit available with the new X722 device. Signed-off-by: Shannon Nelson Acked-by: Jesse Brandeburg Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 1 + drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 256ce6549f61..bff09957cdc0 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -402,6 +402,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 #define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 #define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 +#define I40E_AQ_CAP_ID_WOL_AND_PROXY 0x0008 #define I40E_AQ_CAP_ID_SRIOV 0x0012 #define I40E_AQ_CAP_ID_VF 0x0013 #define I40E_AQ_CAP_ID_VMDQ 0x0014 diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 0d3bc3be0527..365a7d6231a0 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -399,6 +399,7 @@ struct i40e_aqc_list_capabilities_element_resp { #define I40E_AQ_CAP_ID_OS2BMC_CAP 0x0004 #define I40E_AQ_CAP_ID_FUNCTIONS_VALID 0x0005 #define I40E_AQ_CAP_ID_ALTERNATE_RAM 0x0006 +#define I40E_AQ_CAP_ID_WOL_AND_PROXY 0x0008 #define I40E_AQ_CAP_ID_SRIOV 0x0012 #define I40E_AQ_CAP_ID_VF 0x0013 #define I40E_AQ_CAP_ID_VMDQ 0x0014 -- cgit From 6dfae3892473e91080accdb2da8476481393f769 Mon Sep 17 00:00:00 2001 From: Greg Bowers Date: Tue, 22 Dec 2015 14:25:10 -0800 Subject: i40e: Limit DCB FW version checks to X710/XL710 devices X710/XL710 devices require FW version checks to properly handle DCB configurations from the FW. Newer devices do not, so limit these checks to X710/XL710. Signed-off-by: Greg Bowers Acked-by: Shannon Nelson Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_dcb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c index 2691277c0055..582daa7ad776 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c +++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c @@ -814,13 +814,15 @@ i40e_status i40e_get_dcb_config(struct i40e_hw *hw) struct i40e_aqc_get_cee_dcb_cfg_resp cee_cfg; struct i40e_aqc_get_cee_dcb_cfg_v1_resp cee_v1_cfg; - /* If Firmware version < v4.33 IEEE only */ - if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || - (hw->aq.fw_maj_ver < 4)) + /* If Firmware version < v4.33 on X710/XL710, IEEE only */ + if ((hw->mac.type == I40E_MAC_XL710) && + (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) || + (hw->aq.fw_maj_ver < 4))) return i40e_get_ieee_dcb_config(hw); - /* If Firmware version == v4.33 use old CEE struct */ - if ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33)) { + /* If Firmware version == v4.33 on X710/XL710, use old CEE struct */ + if ((hw->mac.type == I40E_MAC_XL710) && + ((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver == 33))) { ret = i40e_aq_get_cee_dcb_config(hw, &cee_v1_cfg, sizeof(cee_v1_cfg), NULL); if (!ret) { -- cgit From 5394f02f0c0553f97bb4c5596a34c9a7333c032b Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:11 -0800 Subject: i40e: AQ Add Run PHY Activity struct Add the AQ opcode and struct definitions for the Run PHY Activity command Signed-off-by: Shannon Nelson Acked-by: Kevin Scott Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 13 +++++++++++++ drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index bff09957cdc0..9e340ca03440 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -220,6 +220,7 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_get_phy_wol_caps = 0x0621, i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_upload_ext_phy_fm = 0x0625, + i40e_aqc_opc_run_phy_activity = 0x0626, /* NVM commands */ i40e_aqc_opc_nvm_read = 0x0701, @@ -1825,6 +1826,18 @@ enum i40e_aq_phy_reg_type { I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; +/* Run PHY Activity (0x0626) */ +struct i40e_aqc_run_phy_activity { + __le16 activity_id; + u8 flags; + u8 reserved1; + __le32 control; + __le32 data; + u8 reserved2[4]; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); + /* NVM Read command (indirect 0x0701) * NVM Erase commands (direct 0x0702) * NVM Update commands (indirect 0x0703) diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 365a7d6231a0..51d83c634519 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -220,6 +220,7 @@ enum i40e_admin_queue_opc { i40e_aqc_opc_get_phy_wol_caps = 0x0621, i40e_aqc_opc_set_phy_debug = 0x0622, i40e_aqc_opc_upload_ext_phy_fm = 0x0625, + i40e_aqc_opc_run_phy_activity = 0x0626, /* NVM commands */ i40e_aqc_opc_nvm_read = 0x0701, @@ -1822,6 +1823,18 @@ enum i40e_aq_phy_reg_type { I40E_AQC_PHY_REG_EXERNAL_MODULE = 0x3 }; +/* Run PHY Activity (0x0626) */ +struct i40e_aqc_run_phy_activity { + __le16 activity_id; + u8 flags; + u8 reserved1; + __le32 control; + __le32 data; + u8 reserved2[4]; +}; + +I40E_CHECK_CMD_LENGTH(i40e_aqc_run_phy_activity); + /* NVM Read command (indirect 0x0701) * NVM Erase commands (direct 0x0702) * NVM Update commands (indirect 0x0703) -- cgit From 5926425368ba8f1b186d45d96020c288e3bb9b8d Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:12 -0800 Subject: i40e: AQ Geneve cloud tunnel type Fix the name of the new cloud tunnel type from the place-holder NGE name to the official Geneve. Also fix the spelling of the VXLAN type. Signed-off-by: Shannon Nelson Acked-by: Kevin Scott Signed-off-by: Jeff Kirsher Tested-by: Andrew Bowers --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 4 ++-- drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index 9e340ca03440..eab55eacb01c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1260,9 +1260,9 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { #define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 __le32 tenant_id; diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 51d83c634519..30b5a33aa424 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1257,9 +1257,9 @@ struct i40e_aqc_add_remove_cloud_filters_element_data { #define I40E_AQC_ADD_CLOUD_TNL_TYPE_SHIFT 9 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_MASK 0x1E00 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_XVLAN 0 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_VXLAN 0 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_NVGRE_OMAC 1 -#define I40E_AQC_ADD_CLOUD_TNL_TYPE_NGE 2 +#define I40E_AQC_ADD_CLOUD_TNL_TYPE_GENEVE 2 #define I40E_AQC_ADD_CLOUD_TNL_TYPE_IP 3 __le32 tenant_id; -- cgit From 5eb772f7ca86267565ef40c7b987c88405689b96 Mon Sep 17 00:00:00 2001 From: Shannon Nelson Date: Tue, 22 Dec 2015 14:25:13 -0800 Subject: i40e: AQ Add external power class to get link status Add the new External Device Power Ability field to the get_link_status data structure, using space from the reserved field at the end of the struct. Signed-off-by: Shannon Nelson Acked-by: Kevin Scott Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 7 ++++++- drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index eab55eacb01c..0e608d2a70d5 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1758,7 +1758,12 @@ struct i40e_aqc_get_link_status { u8 config; #define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_PACING_MASK 0x78 - u8 reserved[5]; + u8 external_power_ability; +#define I40E_AQ_LINK_POWER_CLASS_1 0x00 +#define I40E_AQ_LINK_POWER_CLASS_2 0x01 +#define I40E_AQ_LINK_POWER_CLASS_3 0x02 +#define I40E_AQ_LINK_POWER_CLASS_4 0x03 + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 30b5a33aa424..578b1780fb08 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1755,7 +1755,12 @@ struct i40e_aqc_get_link_status { u8 config; #define I40E_AQ_CONFIG_CRC_ENA 0x04 #define I40E_AQ_CONFIG_PACING_MASK 0x78 - u8 reserved[5]; + u8 external_power_ability; +#define I40E_AQ_LINK_POWER_CLASS_1 0x00 +#define I40E_AQ_LINK_POWER_CLASS_2 0x01 +#define I40E_AQ_LINK_POWER_CLASS_3 0x02 +#define I40E_AQ_LINK_POWER_CLASS_4 0x03 + u8 reserved[4]; }; I40E_CHECK_CMD_LENGTH(i40e_aqc_get_link_status); -- cgit From f8db54cc4df7b065b0028f8c919e2f47983f2043 Mon Sep 17 00:00:00 2001 From: Catherine Sullivan Date: Tue, 22 Dec 2015 14:25:14 -0800 Subject: i40e: add 100Mb ethtool reporting Add some missing reporting/advertisement of 100Mb capability for adapters that support it. Change-ID: I8b8523fbdc99517bec29d90c71b3744db11542ac Signed-off-by: Catherine Sullivan Tested-by: Andrew Bowers Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 4 ++++ drivers/net/ethernet/intel/i40e/i40e_main.c | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 8a3f93ddbcc3..45495911c5a4 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -411,6 +411,10 @@ static void i40e_get_settings_link_down(struct i40e_hw *hw, if (pf->hw.mac.type == I40E_MAC_X722) { ecmd->supported |= SUPPORTED_100baseT_Full; ecmd->advertising |= ADVERTISED_100baseT_Full; + if (pf->flags & I40E_FLAG_100M_SGMII_CAPABLE) { + ecmd->supported |= SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_100baseT_Full; + } } } if (phy_types & I40E_CAP_PHY_TYPE_XAUI || diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3e482bcd5287..320b0491abd9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8453,6 +8453,7 @@ static int i40e_sw_init(struct i40e_pf *pf) I40E_FLAG_OUTER_UDP_CSUM_CAPABLE | I40E_FLAG_WB_ON_ITR_CAPABLE | I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE | + I40E_FLAG_100M_SGMII_CAPABLE | I40E_FLAG_GENEVE_OFFLOAD_CAPABLE; } pf->eeprom_version = 0xDEAD; -- cgit From 07550df04712c88717d2ab6578bb36bbd4305e35 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 4 Feb 2016 12:30:56 +0200 Subject: spi: pxa2xx: Update comment in int_transfer_complete() The register writes here actually don't stop the SSP but clean and disable interrupts and set the receive FIFO inactivity timeout to zero. Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- 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 227e8bad19e6..9b9a528a9fbd 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -572,7 +572,7 @@ static void int_error_stop(struct driver_data *drv_data, const char* msg) static void int_transfer_complete(struct driver_data *drv_data) { - /* Stop SSP */ + /* Clear and disable interrupts */ write_SSSR_CS(drv_data, drv_data->clear_sr); reset_sccr1(drv_data); if (!pxa25x_ssp_comp(drv_data)) -- cgit From 7a8d44bc89e5cddcd5c0704a11a90484d36ba6ba Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 4 Feb 2016 12:30:57 +0200 Subject: spi: pxa2xx: Fix too early chipselect deassert There is a chance that chipselect is deasserted too early while the last clock cycle is still running. Protocol analyzers will see this as a failed last byte. This is more likely to occur with slow bitrates, for instance at 25 kbps. Reason for this is when using SPI mode 0 that both SPI host controller and SPI slave will drive the data lines at the falling edge of clock signal and sample at the rising edge. Receive FIFO gets the last bit now at the rising edge and code sees transfer to be finished either by the interrupt in PIO mode or by the DMA completion in DMA mode. The SSP Time Out register SSTO should take care of delaying the completion but it does not seems to have effect at least on Intel Skylake and Broxton even when using long enough values. Depending on timing code may get into point where chipselect is deasserted while the last clock cycle is still running at its second half cycle. Fix this by adding a wait loop in giveback() that waits until SSP becomes idle before deasserting the chipselect. Reported-by: Weifeng Voon Signed-off-by: Jarkko Nikula Signed-off-by: Mark Brown --- drivers/spi/spi-pxa2xx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 9b9a528a9fbd..ce66cf44bba5 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -496,6 +496,7 @@ static void giveback(struct driver_data *drv_data) { struct spi_transfer* last_transfer; struct spi_message *msg; + unsigned long timeout; msg = drv_data->cur_msg; drv_data->cur_msg = NULL; @@ -508,6 +509,12 @@ static void giveback(struct driver_data *drv_data) if (last_transfer->delay_usecs) udelay(last_transfer->delay_usecs); + /* Wait until SSP becomes idle before deasserting the CS */ + timeout = jiffies + msecs_to_jiffies(10); + while (pxa2xx_spi_read(drv_data, SSSR) & SSSR_BSY && + !time_after(jiffies, timeout)) + cpu_relax(); + /* Drop chip select UNLESS cs_change is true or we are returning * a message with an error, or next message is for another chip */ -- cgit From c29ebb64a553074dc52b6ad36cf0e573d6991c09 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 3 Feb 2016 17:29:41 -0200 Subject: [media] dvb_frontend: print DTV property dump also for SET_PROPERTY When debugging troubles with DTV properties get/set, it is important to be able to see not only the properties from get, but also the ones from set. So, improve the dumps to allow reporting both. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 03cc508b8c42..b1255b7c0b0e 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1162,18 +1162,24 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { _DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0), }; -static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp) +static void dtv_property_dump(struct dvb_frontend *fe, + bool is_set, + struct dtv_property *tvp) { int i; if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) { - dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n", - __func__, tvp->cmd); + dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n", + __func__, + is_set ? "SET" : "GET", + tvp->cmd); return; } - dev_dbg(fe->dvb->device, "%s: tvp.cmd = 0x%08x (%s)\n", __func__, - tvp->cmd, dtv_cmds[tvp->cmd].name); + dev_dbg(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x (%s)\n", __func__, + is_set ? "SET" : "GET", + tvp->cmd, + dtv_cmds[tvp->cmd].name); if (dtv_cmds[tvp->cmd].buffer) { dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n", @@ -1589,7 +1595,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe, return r; } - dtv_property_dump(fe, tvp); + dtv_property_dump(fe, false, tvp); return 0; } @@ -1830,6 +1836,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe, return r; } + dtv_property_dump(fe, true, tvp); + switch(tvp->cmd) { case DTV_CLEAR: /* -- cgit From 210bd104c6acd31c3c6b8b075b3f12d4a9f6b60d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 3 Feb 2016 13:34:00 -0200 Subject: [media] xc2028: unlock on error in xc2028_set_config() We have to unlock before returning -ENOMEM. Fixes: 8dfbcc4351a0 ('[media] xc2028: avoid use after free') Signed-off-by: Dan Carpenter Signed-off-by: Mauro Carvalho Chehab --- drivers/media/tuners/tuner-xc2028.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/tuners/tuner-xc2028.c b/drivers/media/tuners/tuner-xc2028.c index 082ff5608455..317ef63ee789 100644 --- a/drivers/media/tuners/tuner-xc2028.c +++ b/drivers/media/tuners/tuner-xc2028.c @@ -1407,8 +1407,10 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) memcpy(&priv->ctrl, p, sizeof(priv->ctrl)); if (p->fname) { priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL); - if (priv->ctrl.fname == NULL) - return -ENOMEM; + if (priv->ctrl.fname == NULL) { + rc = -ENOMEM; + goto unlock; + } } /* @@ -1440,6 +1442,7 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg) } else priv->state = XC2028_WAITING_FIRMWARE; } +unlock: mutex_unlock(&priv->lock); return rc; -- cgit From 2ea9a08d59b99fbb257bcd8c47e2cbc8be136f8c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 09:45:14 -0200 Subject: [media] dvb_frontend: add props argument to dtv_get_frontend() Instead of implicitly using the DTV cache properties at dtv_get_frontend(), pass it as an additional argument. This patch prepares to use a separate cache for G_PROPERTY, in order to avoid it to mangle with the DVB thread zigzag logic. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index b1255b7c0b0e..ca6d60f9d492 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -140,9 +140,12 @@ struct dvb_frontend_private { static void dvb_frontend_wakeup(struct dvb_frontend *fe); static int dtv_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c, struct dvb_frontend_parameters *p_out); -static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p); +static int +dtv_property_legacy_params_sync(struct dvb_frontend *fe, + const struct dtv_frontend_properties *c, + struct dvb_frontend_parameters *p); static bool has_get_frontend(struct dvb_frontend *fe) { @@ -202,6 +205,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, enum fe_status status) { struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_fe_events *events = &fepriv->events; struct dvb_frontend_event *e; int wp; @@ -209,7 +213,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, dev_dbg(fe->dvb->device, "%s:\n", __func__); if ((status & FE_HAS_LOCK) && has_get_frontend(fe)) - dtv_get_frontend(fe, &fepriv->parameters_out); + dtv_get_frontend(fe, c, &fepriv->parameters_out); mutex_lock(&events->mtx); @@ -687,6 +691,7 @@ static int dvb_enable_media_tuner(struct dvb_frontend *fe) static int dvb_frontend_thread(void *data) { struct dvb_frontend *fe = data; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; enum fe_status s; enum dvbfe_algo algo; @@ -807,7 +812,7 @@ restart: fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; fepriv->delay = HZ / 2; } - dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out); fe->ops.read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); /* update event list */ @@ -1274,11 +1279,11 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe, /* Ensure the cached values are set correctly in the frontend * legacy tuning structures, for the advanced tuning API. */ -static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) +static int +dtv_property_legacy_params_sync(struct dvb_frontend *fe, + const struct dtv_frontend_properties *c, + struct dvb_frontend_parameters *p) { - const struct dtv_frontend_properties *c = &fe->dtv_property_cache; - p->frequency = c->frequency; p->inversion = c->inversion; @@ -1350,6 +1355,7 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe, * If p_out is not null, it will update the DVBv3 params pointed by it. */ static int dtv_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c, struct dvb_frontend_parameters *p_out) { int r; @@ -1359,7 +1365,7 @@ static int dtv_get_frontend(struct dvb_frontend *fe, if (unlikely(r < 0)) return r; if (p_out) - dtv_property_legacy_params_sync(fe, p_out); + dtv_property_legacy_params_sync(fe, c, p_out); return 0; } @@ -2107,7 +2113,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, * is not idle. Otherwise, returns the cached content */ if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, NULL); + err = dtv_get_frontend(fe, c, NULL); if (err < 0) goto out; } @@ -2147,7 +2153,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe) * the user. FE_SET_FRONTEND triggers an initial frontend event * with status = 0, which copies output parameters to userspace. */ - dtv_property_legacy_params_sync(fe, &fepriv->parameters_out); + dtv_property_legacy_params_sync(fe, c, &fepriv->parameters_out); /* * Be sure that the bandwidth will be filled for all @@ -2518,7 +2524,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; case FE_GET_FRONTEND: - err = dtv_get_frontend(fe, parg); + err = dtv_get_frontend(fe, c, parg); break; case FE_SET_FRONTEND_TUNE_MODE: -- cgit From 089dfaf7f7f9b18e3dffb6d9ee8b37089025b952 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Sat, 30 Jan 2016 23:07:00 -0800 Subject: ASoC: fsl-asoc-card: Don't add DAPM routes for ASRC if it doesn't exist There are a pair of warnings when ASRC is absent in the DTB: fsl-asoc-card sound: ASoC: no source widget found for ASRC-Playback fsl-asoc-card sound: ASoC: Failed to add route ASRC-Playback -> direct -> CPU-Playback fsl-asoc-card sound: ASoC: no sink widget found for ASRC-Capture fsl-asoc-card sound: ASoC: Failed to add route CPU-Capture -> direct -> ASRC-Capture This is because the driver is still trying to add DAPM routes for ASRC even if it doesn't exist on that platform. The warnings are harmless but it might be annoying. So this patch drops the DAPM routes of ASRC when it's absent in the DAI link. Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 562b3bd22d9a..3d40797e3bcc 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -99,19 +99,26 @@ struct fsl_asoc_card_priv { /** * This dapm route map exsits for DPCM link only. * The other routes shall go through Device Tree. + * + * Note: keep all ASRC routes in the second half + * to drop them easily for non-ASRC cases. */ static const struct snd_soc_dapm_route audio_map[] = { - {"CPU-Playback", NULL, "ASRC-Playback"}, + /* 1st half -- Normal DAPM routes */ {"Playback", NULL, "CPU-Playback"}, - {"ASRC-Capture", NULL, "CPU-Capture"}, {"CPU-Capture", NULL, "Capture"}, + /* 2nd half -- ASRC DAPM routes */ + {"CPU-Playback", NULL, "ASRC-Playback"}, + {"ASRC-Capture", NULL, "CPU-Capture"}, }; static const struct snd_soc_dapm_route audio_map_ac97[] = { - {"AC97 Playback", NULL, "ASRC-Playback"}, + /* 1st half -- Normal DAPM routes */ {"Playback", NULL, "AC97 Playback"}, - {"ASRC-Capture", NULL, "AC97 Capture"}, {"AC97 Capture", NULL, "Capture"}, + /* 2nd half -- ASRC DAPM routes */ + {"AC97 Playback", NULL, "ASRC-Playback"}, + {"ASRC-Capture", NULL, "AC97 Capture"}, }; /* Add all possible widgets into here without being redundant */ @@ -593,6 +600,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->card.dapm_widgets = fsl_asoc_card_dapm_widgets; priv->card.num_dapm_widgets = ARRAY_SIZE(fsl_asoc_card_dapm_widgets); + /* Drop the second half of DAPM routes -- ASRC */ + if (!asrc_pdev) + priv->card.num_dapm_routes /= 2; + memcpy(priv->dai_link, fsl_asoc_card_dai, sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); -- cgit From 1f1e60c9cdd573be271130e44a23efed48e0578d Mon Sep 17 00:00:00 2001 From: Zidan Wang Date: Tue, 24 Nov 2015 10:18:27 +0800 Subject: ASoC: cs42xx8: fix the noise in the right dac channel with mono playback When playback mono wav with record in background, there will be some nosie in the right dac channel. It seems that the ADC data has been routed to the dac channel. The cs42888 have 8 dac channels, it's appropriate to mute the unused dac channels, and the noise will disappear. Steps to reproduce this issue: arecord -D hw:0,0 -f S16_LE -r 48000 -c 1 a.wav & aplay -Dhw:0,0 audio48k16M.wav Signed-off-by: Zidan Wang Signed-off-by: Mark Brown --- sound/soc/codecs/cs42xx8.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index d562e1b9a5d1..1179101b2b05 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -44,6 +44,7 @@ struct cs42xx8_priv { bool slave_mode; unsigned long sysclk; + u32 tx_channels; }; /* -127.5dB to 0dB with step of 0.5dB */ @@ -257,6 +258,9 @@ static int cs42xx8_hw_params(struct snd_pcm_substream *substream, u32 ratio = cs42xx8->sysclk / params_rate(params); u32 i, fm, val, mask; + if (tx) + cs42xx8->tx_channels = params_channels(params); + for (i = 0; i < ARRAY_SIZE(cs42xx8_ratios); i++) { if (cs42xx8_ratios[i].ratio == ratio) break; @@ -283,9 +287,11 @@ static int cs42xx8_digital_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; struct cs42xx8_priv *cs42xx8 = snd_soc_codec_get_drvdata(codec); + u8 dac_unmute = cs42xx8->tx_channels ? + ~((0x1 << cs42xx8->tx_channels) - 1) : 0; - regmap_update_bits(cs42xx8->regmap, CS42XX8_DACMUTE, - CS42XX8_DACMUTE_ALL, mute ? CS42XX8_DACMUTE_ALL : 0); + regmap_write(cs42xx8->regmap, CS42XX8_DACMUTE, + mute ? CS42XX8_DACMUTE_ALL : dac_unmute); return 0; } -- cgit From 5978531b296ab7e61abef43f2a1a2d9b92246de1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Feb 2016 17:16:32 -0300 Subject: perf build tests: Elide "-f Makefile" from make invokation Since this is the name that 'make' will look for if no explicit -f file is passed. This in turn makes the output of 'build-test' more compact: Before: $ perf stat make -C tools/perf build-test cd . && make FEATURE_DUMP_COPY=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP feature-dump make_no_libaudit_O: cd . && make -f Makefile O=/tmp/tmp.tHIa0Kkk2Y DESTDIR=/tmp/tmp.foK7rckkVi NO_LIBAUDIT=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP After: $ perf stat make -C tools/perf build-test make_no_libaudit_O: cd . && make O=/tmp/tmp.tHIa0Kkk2Y DESTDIR=/tmp/tmp.foK7rckkVi NO_LIBAUDIT=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-m440lb8dkfsywsyah0htif6t@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index cc72b67bde5e..0b70cf16a562 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -111,6 +111,9 @@ run := make_pure # disable features detection ifeq ($(MK),Makefile) run += make_clean_all +MAKE_F := $(MAKE) +else +MAKE_F := $(MAKE) -f $(MK) endif run += make_python_perf_so run += make_debug @@ -270,12 +273,12 @@ endif MAKEFLAGS := --no-print-directory -clean := @(cd $(PERF); make -s -f $(MK) $(O_OPT) clean >/dev/null) +clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null) $(run): $(call clean) @TMP_DEST=$$(mktemp -d); \ - cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \ + cmd="cd $(PERF) && $(MAKE_F) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \ printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1; \ echo " test: $(call test,$@)" >> $@ 2>&1; \ @@ -286,7 +289,7 @@ $(run_O): $(call clean) @TMP_O=$$(mktemp -d); \ TMP_DEST=$$(mktemp -d); \ - cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ + cmd="cd $(PERF) && $(MAKE_F) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 && \ echo " test: $(call test_O,$@)" >> $@ 2>&1; \ -- cgit From 3c7a152b0d1c81b9bac5ab922dc57168046668bf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Feb 2016 17:24:11 -0300 Subject: perf build tests: Move the feature related vars to the front of the make cmdline So that we do less visual searching on the 'make build-test' output to see the feature related variables: After: $ make -C tools/perf build-test make_no_newt_O: cd . && make NO_NEWT=1 FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP O=/tmp/tmp.dz55IX DESTDIR=/tmp/tmp.X29xxo make_tags_O: cd . && make tags FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP O=/tmp/tmp.6ecLh8 DESTDIR=/tmp/tmp.6vIla578Ho make_util_pmu_bison_o_O: cd . && make util/pmu-bison.o FEATURES_DUMP=/home/acme/git/linux/tools/perf/BUILD_TEST_FEATURE_DUMP O=/tmp/tmp.SVPM2G DESTDIR=/tmp/tmp.C0oAam Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-dx4krgzqa566v1pedrbrcchi@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/make | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 0b70cf16a562..12dcae7aa515 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -278,7 +278,7 @@ clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null) $(run): $(call clean) @TMP_DEST=$$(mktemp -d); \ - cmd="cd $(PERF) && $(MAKE_F) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \ + cmd="cd $(PERF) && $(MAKE_F) $($@) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST"; \ printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1; \ echo " test: $(call test,$@)" >> $@ 2>&1; \ @@ -289,7 +289,7 @@ $(run_O): $(call clean) @TMP_O=$$(mktemp -d); \ TMP_DEST=$$(mktemp -d); \ - cmd="cd $(PERF) && $(MAKE_F) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ + cmd="cd $(PERF) && $(MAKE_F) $($(patsubst %_O,%,$@)) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST"; \ printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 && \ echo " test: $(call test_O,$@)" >> $@ 2>&1; \ -- cgit From 67f43c009778ddaae812aae29731bb04c256165e Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:06 +0900 Subject: perf config: Document 'ui.show-headers' variable in man page This option controls display of column headers (like 'Overhead' and 'Symbol') in 'report' and 'top'. If this option is false, they are hidden. This option is only applied to TUI. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-2-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 74589c68558a..42787222ad15 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -296,6 +296,12 @@ hist.*:: and 'baz' to 50.00% for each, while 'absolute' would show their current overhead (33.33%). +ui.*:: + ui.show-headers:: + This option controls display of column headers (like 'Overhead' and 'Symbol') + in 'report' and 'top'. If this option is false, they are hidden. + This option is only applied to TUI. + SEE ALSO -------- linkperf:perf[1] -- cgit From 56c94dc56f9e4c1c09fbe26ad65715caa2259438 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:07 +0900 Subject: perf config: Document variables for 'call-graph' section in man page Explain 'call-graph' section and its variables: 'record-mode', 'dump-size', 'print-type', 'order', 'sort-key', 'threshold' and 'print-limit'. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-3-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 42787222ad15..42310ae7e636 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -302,6 +302,73 @@ ui.*:: in 'report' and 'top'. If this option is false, they are hidden. This option is only applied to TUI. +call-graph.*:: + When sub-commands 'top' and 'report' work with -g/—-children + there're options in control of call-graph. + + call-graph.record-mode:: + The record-mode can be 'fp' (frame pointer), 'dwarf' and 'lbr'. + The value of 'dwarf' is effective only if perf detect needed library + (libunwind or a recent version of libdw). + 'lbr' only work for cpus that support it. + + call-graph.dump-size:: + The size of stack to dump in order to do post-unwinding. Default is 8192 (byte). + When using dwarf into record-mode, the default size will be used if omitted. + + call-graph.print-type:: + The print-types can be graph (graph absolute), fractal (graph relative), + flat and folded. This option controls a way to show overhead for each callchain + entry. Suppose a following example. + + Overhead Symbols + ........ ....... + 40.00% foo + | + ---foo + | + |--50.00%--bar + | main + | + --50.00%--baz + main + + This output is a 'fractal' format. The 'foo' came from 'bar' and 'baz' exactly + half and half so 'fractal' shows 50.00% for each + (meaning that it assumes 100% total overhead of 'foo'). + + The 'graph' uses absolute overhead value of 'foo' as total so each of + 'bar' and 'baz' callchain will have 20.00% of overhead. + If 'flat' is used, single column and linear exposure of call chains. + 'folded' mean call chains are displayed in a line, separated by semicolons. + + call-graph.order:: + This option controls print order of callchains. The default is + 'callee' which means callee is printed at top and then followed by its + caller and so on. The 'caller' prints it in reverse order. + + If this option is not set and report.children or top.children is + set to true (or the equivalent command line option is given), + the default value of this option is changed to 'caller' for the + execution of 'perf report' or 'perf top'. Other commands will + still default to 'callee'. + + call-graph.sort-key:: + The callchains are merged if they contain same information. + The sort-key option determines a way to compare the callchains. + A value of 'sort-key' can be 'function' or 'address'. + The default is 'function'. + + call-graph.threshold:: + When there're many callchains it'd print tons of lines. So perf omits + small callchains under a certain overhead (threshold) and this option + control the threshold. Default is 0.5 (%). The overhead is calculated + by value depends on call-graph.print-type. + + call-graph.print-limit:: + This is a maximum number of lines of callchain printed for a single + histogram entry. Default is 0 which means no limitation. + SEE ALSO -------- linkperf:perf[1] -- cgit From 806cb95bb6cb25105b37d971d9916105898cb6fe Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:08 +0900 Subject: perf config: Document variables for 'report' section in man page Explain 'report' section's variables: 'percent-limit', 'queue-size' and 'children'. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-4-git-send-email-treeze.taeung@gmail.com [ Fix some grammar issues, add some more info ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 42310ae7e636..f38f46f67d74 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -369,6 +369,42 @@ call-graph.*:: This is a maximum number of lines of callchain printed for a single histogram entry. Default is 0 which means no limitation. +report.*:: + report.percent-limit:: + This one is mostly the same as call-graph.threshold but works for + histogram entries. Entries having an overhead lower than this + percentage will not be printed. Default is '0'. If percent-limit + is '10', only entries which have more than 10% of overhead will be + printed. + + report.queue-size:: + This option sets up the maximum allocation size of the internal + event queue for ordering events. Default is 0, meaning no limit. + + report.children:: + 'Children' means functions called from another function. + If this option is true, 'perf report' cumulates callchains of children + and show (accumulated) total overhead as well as 'Self' overhead. + Please refer to the 'perf report' manual. The default is 'true'. + + report.group:: + This option is to show event group information together. + Example output with this turned on, notice that there is one column + per event in the group, ref-cycles and cycles: + + # group: {ref-cycles,cycles} + # ======== + # + # Samples: 7K of event 'anon group { ref-cycles, cycles }' + # Event count (approx.): 6876107743 + # + # Overhead Command Shared Object Symbol + # ................ ....... ................. ................... + # + 99.84% 99.76% noploop noploop [.] main + 0.07% 0.00% noploop ld-2.15.so [.] strcmp + 0.03% 0.00% noploop [kernel.kallsyms] [k] timerqueue_del + SEE ALSO -------- linkperf:perf[1] -- cgit From 0b04c84087d3188c648628a6c73738314724c921 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:09 +0900 Subject: perf config: Document 'top.children' variable in man page Explain 'top.children' variable. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-5-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index f38f46f67d74..5e1db5ae53c4 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -405,6 +405,13 @@ report.*:: 0.07% 0.00% noploop ld-2.15.so [.] strcmp 0.03% 0.00% noploop [kernel.kallsyms] [k] timerqueue_del +top.*:: + top.children:: + Same as 'report.children'. So if it is enabled, the output of 'top' + command will have 'Children' overhead column as well as 'Self' overhead + column by default. + The default is 'true'. + SEE ALSO -------- linkperf:perf[1] -- cgit From 08b75b409e3799553a3536e628f1dba4c87d7c14 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:10 +0900 Subject: perf config: Document 'man.viewer' variable in man page Explain 'man.viewer' variable and how to add new man viewer tools. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-6-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 5e1db5ae53c4..fd3f048c9644 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -412,6 +412,15 @@ top.*:: column by default. The default is 'true'. +man.*:: + man.viewer:: + This option can assign a tool to view manual pages when 'help' + subcommand was invoked. Supported tools are 'man', 'woman' + (with emacs client) and 'konqueror'. Default is 'man'. + + New man viewer tool can be also added using 'man..cmd' + or use different path using 'man..path' config option. + SEE ALSO -------- linkperf:perf[1] -- cgit From ab2e08e8ba683f3e923a56b1e81b5c5e115bad0b Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:11 +0900 Subject: perf config: Document 'pager.' variables in man page Explain 'pager.' variables. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-7-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index fd3f048c9644..99aa72e5e9cf 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -421,6 +421,11 @@ man.*:: New man viewer tool can be also added using 'man..cmd' or use different path using 'man..path' config option. +pager.*:: + pager.:: + When the subcommand is run on stdio, determine whether it uses + pager or not based on this value. Default is 'unspecified'. + SEE ALSO -------- linkperf:perf[1] -- cgit From 57f0dafe6a41de6c9d81bc6c403349a261e10fc4 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:12 +0900 Subject: perf config: Document 'kmem.default' variable in man page Explain 'kmem.default' variable. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-8-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index 99aa72e5e9cf..fb1f4a984e63 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -426,6 +426,11 @@ pager.*:: When the subcommand is run on stdio, determine whether it uses pager or not based on this value. Default is 'unspecified'. +kmem.*:: + kmem.default:: + This option decides which allocator is to be analyzed if neither + '--slab' nor '--page' option is used. Default is 'slab'. + SEE ALSO -------- linkperf:perf[1] -- cgit From a9edec3ce211d776736b35b14b9bd2c0b5ed860b Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 4 Feb 2016 18:25:13 +0900 Subject: perf config: Document 'record.build-id' variable in man page Explain 'record.build-id' variable. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1454577913-16401-9-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index fb1f4a984e63..c7158bfb1649 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -431,6 +431,14 @@ kmem.*:: This option decides which allocator is to be analyzed if neither '--slab' nor '--page' option is used. Default is 'slab'. +record.*:: + record.build-id:: + This option can be 'cache', 'no-cache' or 'skip'. + 'cache' is to post-process data and save/update the binaries into + the build-id cache (in ~/.debug). This is the default. + But if this option is 'no-cache', it will not update the build-id cache. + 'skip' skips post-processing and does not update the cache. + SEE ALSO -------- linkperf:perf[1] -- cgit From e795421e40b39bf874c5ed9434365fb4a4b6c5d1 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jan 2016 16:24:15 +0100 Subject: cfq-iosched: Don't group_idle if cfqq has big thinktime There is no point in idling on a cfq group if the only cfq queue that is there has too big thinktime. Signed-off-by: Jan Kara Acked-by: Tejun Heo Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 1f9093e901da..0a6a70a9bca8 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2897,6 +2897,7 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq) static void cfq_arm_slice_timer(struct cfq_data *cfqd) { struct cfq_queue *cfqq = cfqd->active_queue; + struct cfq_rb_root *st = cfqq->service_tree; struct cfq_io_cq *cic; unsigned long sl, group_idle = 0; @@ -2947,8 +2948,13 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) return; } - /* There are other queues in the group, don't do group idle */ - if (group_idle && cfqq->cfqg->nr_cfqq > 1) + /* + * There are other queues in the group or this is the only group and + * it has too big thinktime, don't do group idle. + */ + if (group_idle && + (cfqq->cfqg->nr_cfqq > 1 || + cfq_io_thinktime_big(cfqd, &st->ttime, true))) return; cfq_mark_cfqq_wait_request(cfqq); -- cgit From 6c80731c75bd3289d35b89a21a4e317cbcb306e3 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jan 2016 16:24:16 +0100 Subject: cfq-iosched: Reorder checks in cfq_should_preempt() Move check for preemption by rt class up. There is no functional change but it makes arguing about conditions simpler since we can be sure both cfq queues are from the same ioprio class. Acked-by: Tejun Heo Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 0a6a70a9bca8..2544c219c00c 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3959,6 +3959,13 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, if (cfq_slice_used(cfqq)) return true; + /* + * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice. + */ + if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq)) + return true; + + WARN_ON_ONCE(cfqq->ioprio_class != new_cfqq->ioprio_class); /* Allow preemption only if we are idling on sync-noidle tree */ if (cfqd->serving_wl_type == SYNC_NOIDLE_WORKLOAD && cfqq_type(new_cfqq) == SYNC_NOIDLE_WORKLOAD && @@ -3973,12 +3980,6 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, if ((rq->cmd_flags & REQ_PRIO) && !cfqq->prio_pending) return true; - /* - * Allow an RT request to pre-empt an ongoing non-RT cfqq timeslice. - */ - if (cfq_class_rt(new_cfqq) && !cfq_class_rt(cfqq)) - return true; - /* An idle queue should not be idle now for some reason */ if (RB_EMPTY_ROOT(&cfqq->sort_list) && !cfq_should_idle(cfqd, cfqq)) return true; -- cgit From a257ae3e482e1cbd5fc573efeef5a73bffe09757 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jan 2016 16:24:17 +0100 Subject: cfq-iosched: Allow sync noidle workloads to preempt each other The original idea with preemption of sync noidle queues (introduced in commit 718eee0579b8 "cfq-iosched: fairness for sync no-idle queues") was that we service all sync noidle queues together, we don't idle on any of the queues individually and we idle only if there is no sync noidle queue to be served. This intention also matches the original test: if (cfqd->serving_type == SYNC_NOIDLE_WORKLOAD && new_cfqq->service_tree == cfqq->service_tree) return true; However since at that time cfqq->service_tree was not set for idling queues, this test was unreliable and was replaced in commit e4a229196a7c "cfq-iosched: fix no-idle preemption logic" by: if (cfqd->serving_type == SYNC_NOIDLE_WORKLOAD && cfqq_type(new_cfqq) == SYNC_NOIDLE_WORKLOAD && new_cfqq->service_tree->count == 1) return true; That was a reliable test but was actually doing something different - now we preempt sync noidle queue only if the new queue is the only one busy in the service tree. These days cfq queue is kept in service tree even if it is idling and thus the original check would be safe again. But since we actually check that cfq queues are in the same cgroup, of the same priority class and workload type (sync noidle), we know that new_cfqq is fine to preempt cfqq. So just remove the service tree check. Acked-by: Tejun Heo Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 1 - 1 file changed, 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 2544c219c00c..98569c2f373e 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3969,7 +3969,6 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, /* Allow preemption only if we are idling on sync-noidle tree */ if (cfqd->serving_wl_type == SYNC_NOIDLE_WORKLOAD && cfqq_type(new_cfqq) == SYNC_NOIDLE_WORKLOAD && - new_cfqq->service_tree->count == 2 && RB_EMPTY_ROOT(&cfqq->sort_list)) return true; -- cgit From 3984aa55204e2c3f423a70b013c44c64261788df Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 12 Jan 2016 16:24:19 +0100 Subject: cfq-iosched: Allow parent cgroup to preempt its child Currently we don't allow sync workload of one cgroup to preempt sync workload of any other cgroup. This is because we want to achieve service separation between cgroups. However in cases where cgroup preempting is ancestor of the current cgroup, there is no need of separation and idling introduces unnecessary overhead. This hurts for example the case when workload is isolated within a cgroup but journalling threads are in root cgroup. Simple way to demostrate the issue is using: dbench4 -c /usr/share/dbench4/client.txt -t 10 -D /mnt 1 on ext4 filesystem on plain SATA drive (mounted with barrier=0 to make difference more visible). When all processes are in the root cgroup, reported throughput is 153.132 MB/sec. When dbench process gets its own blkio cgroup, reported throughput drops to 26.1006 MB/sec. Fix the problem by making check in cfq_should_preempt() more benevolent and allow preemption by ancestor cgroup. This improves the throughput reported by dbench4 to 48.9106 MB/sec. Acked-by: Tejun Heo Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 98569c2f373e..e3c591dd8f19 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -632,6 +632,13 @@ static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg) return pblkg ? blkg_to_cfqg(pblkg) : NULL; } +static inline bool cfqg_is_descendant(struct cfq_group *cfqg, + struct cfq_group *ancestor) +{ + return cgroup_is_descendant(cfqg_to_blkg(cfqg)->blkcg->css.cgroup, + cfqg_to_blkg(ancestor)->blkcg->css.cgroup); +} + static inline void cfqg_get(struct cfq_group *cfqg) { return blkg_get(cfqg_to_blkg(cfqg)); @@ -758,6 +765,11 @@ static void cfqg_stats_xfer_dead(struct cfq_group *cfqg) #else /* CONFIG_CFQ_GROUP_IOSCHED */ static inline struct cfq_group *cfqg_parent(struct cfq_group *cfqg) { return NULL; } +static inline bool cfqg_is_descendant(struct cfq_group *cfqg, + struct cfq_group *ancestor) +{ + return true; +} static inline void cfqg_get(struct cfq_group *cfqg) { } static inline void cfqg_put(struct cfq_group *cfqg) { } @@ -3953,7 +3965,12 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, if (rq_is_sync(rq) && !cfq_cfqq_sync(cfqq)) return true; - if (new_cfqq->cfqg != cfqq->cfqg) + /* + * Treat ancestors of current cgroup the same way as current cgroup. + * For anybody else we disallow preemption to guarantee service + * fairness among cgroups. + */ + if (!cfqg_is_descendant(cfqq->cfqg, new_cfqq->cfqg)) return false; if (cfq_slice_used(cfqq)) -- cgit From 83a74ff8e63e39d8122ff17ac000064605884127 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 09:54:25 -0200 Subject: [media] siano: remove get_frontend stub There's nothing at siano's get_frontend() callback. So, remove it, as the core will handle it. Reviewed-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/siano/smsdvb-main.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index d31f468830cf..9148e14c9d07 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1015,12 +1015,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe) } } -/* Nothing to do here, as stats are automatically updated */ -static int smsdvb_get_frontend(struct dvb_frontend *fe) -{ - return 0; -} - static int smsdvb_init(struct dvb_frontend *fe) { struct smsdvb_client_t *client = @@ -1069,7 +1063,6 @@ static struct dvb_frontend_ops smsdvb_fe_ops = { .release = smsdvb_release, .set_frontend = smsdvb_set_frontend, - .get_frontend = smsdvb_get_frontend, .get_tune_settings = smsdvb_get_tune_settings, .read_status = smsdvb_read_status, -- cgit From 6f1bd426122da4a2d22570494bba9cf3dffbd753 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 10:01:05 -0200 Subject: [media] friio-fe: remove get_frontend() callback This driver doesn't support getting frontend information and it only works in automatic mode. So, let's remove get_frontend() and update the cache at set_frontend(). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/dvb-usb/friio-fe.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c index 8ec92fbeabad..979f05b4b87c 100644 --- a/drivers/media/usb/dvb-usb/friio-fe.c +++ b/drivers/media/usb/dvb-usb/friio-fe.c @@ -283,20 +283,6 @@ static int jdvbt90502_set_property(struct dvb_frontend *fe, return r; } -static int jdvbt90502_get_frontend(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *p = &fe->dtv_property_cache; - p->inversion = INVERSION_AUTO; - p->bandwidth_hz = 6000000; - p->code_rate_HP = FEC_AUTO; - p->code_rate_LP = FEC_AUTO; - p->modulation = QAM_64; - p->transmission_mode = TRANSMISSION_MODE_AUTO; - p->guard_interval = GUARD_INTERVAL_AUTO; - p->hierarchy = HIERARCHY_AUTO; - return 0; -} - static int jdvbt90502_set_frontend(struct dvb_frontend *fe) { struct dtv_frontend_properties *p = &fe->dtv_property_cache; @@ -312,8 +298,16 @@ static int jdvbt90502_set_frontend(struct dvb_frontend *fe) deb_fe("%s: Freq:%d\n", __func__, p->frequency); - /* for recovery from DTV_CLEAN */ - fe->dtv_property_cache.delivery_system = SYS_ISDBT; + /* This driver only works on auto mode */ + p->inversion = INVERSION_AUTO; + p->bandwidth_hz = 6000000; + p->code_rate_HP = FEC_AUTO; + p->code_rate_LP = FEC_AUTO; + p->modulation = QAM_64; + p->transmission_mode = TRANSMISSION_MODE_AUTO; + p->guard_interval = GUARD_INTERVAL_AUTO; + p->hierarchy = HIERARCHY_AUTO; + p->delivery_system = SYS_ISDBT; ret = jdvbt90502_pll_set_freq(state, p->frequency); if (ret) { @@ -466,7 +460,6 @@ static struct dvb_frontend_ops jdvbt90502_ops = { .set_property = jdvbt90502_set_property, .set_frontend = jdvbt90502_set_frontend, - .get_frontend = jdvbt90502_get_frontend, .read_status = jdvbt90502_read_status, .read_signal_strength = jdvbt90502_read_signal_strength, -- cgit From 0fa301d796ce7d78d12cf35440143e3f232f5663 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 10:37:37 -0200 Subject: [media] lgs8gxx: don't export get_frontend() callback This device doesn't really have a get_frontend(). All it does is to blindly set everything to auto mode. Remove the get_frontend(), as the code does that already, and put the frontend changes at set_frontend, where it belongs. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/lgs8gxx.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/media/dvb-frontends/lgs8gxx.c b/drivers/media/dvb-frontends/lgs8gxx.c index e2c191c8b196..919daeb96747 100644 --- a/drivers/media/dvb-frontends/lgs8gxx.c +++ b/drivers/media/dvb-frontends/lgs8gxx.c @@ -672,7 +672,7 @@ static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len) static int lgs8gxx_set_fe(struct dvb_frontend *fe) { - + struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct lgs8gxx_state *priv = fe->demodulator_priv; dprintk("%s\n", __func__); @@ -689,17 +689,7 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe) msleep(10); - return 0; -} - -static int lgs8gxx_get_fe(struct dvb_frontend *fe) -{ - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; - dprintk("%s\n", __func__); - /* TODO: get real readings from device */ - /* inversion status */ - fe_params->inversion = INVERSION_OFF; /* bandwidth */ fe_params->bandwidth_hz = 8000000; @@ -1016,7 +1006,6 @@ static struct dvb_frontend_ops lgs8gxx_ops = { .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, .set_frontend = lgs8gxx_set_fe, - .get_frontend = lgs8gxx_get_fe, .get_tune_settings = lgs8gxx_get_tune_settings, .read_status = lgs8gxx_read_status, -- cgit From a7497049841f04712ad525969e5eb4a42b5a1704 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 12:47:04 -0200 Subject: [media] mb86a20s: get rid of dummy get_frontend() This is not needed, as the core handles well if get_frontend() is not present. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-frontends/mb86a20s.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c index cfc005ee11d8..fb88dddaf3a3 100644 --- a/drivers/media/dvb-frontends/mb86a20s.c +++ b/drivers/media/dvb-frontends/mb86a20s.c @@ -2028,16 +2028,6 @@ static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe, return 0; } -static int mb86a20s_get_frontend_dummy(struct dvb_frontend *fe) -{ - /* - * get_frontend is now handled together with other stats - * retrival, when read_status() is called, as some statistics - * will depend on the layers detection. - */ - return 0; -}; - static int mb86a20s_tune(struct dvb_frontend *fe, bool re_tune, unsigned int mode_flags, @@ -2136,7 +2126,6 @@ static struct dvb_frontend_ops mb86a20s_ops = { .init = mb86a20s_initfe, .set_frontend = mb86a20s_set_frontend, - .get_frontend = mb86a20s_get_frontend_dummy, .read_status = mb86a20s_read_status_and_stats, .read_signal_strength = mb86a20s_read_signal_strength_from_cache, .tune = mb86a20s_tune, -- cgit From 7e3e68bcfd7713fb1470070c8fa0f108609dd76b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 12:58:30 -0200 Subject: [media] dvb_frontend: pass the props cache to get_frontend() as arg Instead of using the DTV properties cache directly, pass the get frontend data as an argument. For now, everything should remain the same, but the next patch will prevent get_frontend to affect the global cache. This is needed because several drivers don't care enough to only change the properties if locked. Due to that, calling G_PROPERTY before locking on those drivers will make them to never lock. Ok, those drivers are crap and should never be merged like that, but the core should not rely that the drivers would be doing the right thing. Reviewed-by: Michael Ira Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 2 +- drivers/media/dvb-core/dvb_frontend.h | 3 +- drivers/media/dvb-frontends/af9013.c | 4 +- drivers/media/dvb-frontends/af9033.c | 4 +- drivers/media/dvb-frontends/as102_fe.c | 4 +- drivers/media/dvb-frontends/atbm8830.c | 4 +- drivers/media/dvb-frontends/au8522_dig.c | 4 +- drivers/media/dvb-frontends/cx22700.c | 4 +- drivers/media/dvb-frontends/cx22702.c | 4 +- drivers/media/dvb-frontends/cx24110.c | 4 +- drivers/media/dvb-frontends/cx24117.c | 4 +- drivers/media/dvb-frontends/cx24120.c | 4 +- drivers/media/dvb-frontends/cx24123.c | 4 +- drivers/media/dvb-frontends/cxd2820r_c.c | 4 +- drivers/media/dvb-frontends/cxd2820r_core.c | 9 ++-- drivers/media/dvb-frontends/cxd2820r_priv.h | 9 ++-- drivers/media/dvb-frontends/cxd2820r_t.c | 4 +- drivers/media/dvb-frontends/cxd2820r_t2.c | 6 +-- drivers/media/dvb-frontends/cxd2841er.c | 4 +- drivers/media/dvb-frontends/dib3000mb.c | 9 ++-- drivers/media/dvb-frontends/dib3000mc.c | 6 +-- drivers/media/dvb-frontends/dib7000m.c | 6 +-- drivers/media/dvb-frontends/dib7000p.c | 6 +-- drivers/media/dvb-frontends/dib8000.c | 75 ++++++++++++++------------- drivers/media/dvb-frontends/dib9000.c | 23 ++++---- drivers/media/dvb-frontends/dvb_dummy_fe.c | 7 ++- drivers/media/dvb-frontends/hd29l2.c | 4 +- drivers/media/dvb-frontends/l64781.c | 4 +- drivers/media/dvb-frontends/lg2160.c | 62 +++++++++++----------- drivers/media/dvb-frontends/lgdt3305.c | 4 +- drivers/media/dvb-frontends/lgdt3306a.c | 4 +- drivers/media/dvb-frontends/lgdt330x.c | 5 +- drivers/media/dvb-frontends/lgs8gl5.c | 5 +- drivers/media/dvb-frontends/m88ds3103.c | 4 +- drivers/media/dvb-frontends/m88rs2000.c | 5 +- drivers/media/dvb-frontends/mt312.c | 4 +- drivers/media/dvb-frontends/mt352.c | 4 +- drivers/media/dvb-frontends/or51132.c | 4 +- drivers/media/dvb-frontends/rtl2830.c | 4 +- drivers/media/dvb-frontends/rtl2832.c | 4 +- drivers/media/dvb-frontends/s5h1409.c | 4 +- drivers/media/dvb-frontends/s5h1411.c | 4 +- drivers/media/dvb-frontends/s5h1420.c | 4 +- drivers/media/dvb-frontends/s921.c | 4 +- drivers/media/dvb-frontends/stb0899_drv.c | 4 +- drivers/media/dvb-frontends/stb6100.c | 2 +- drivers/media/dvb-frontends/stv0297.c | 4 +- drivers/media/dvb-frontends/stv0299.c | 4 +- drivers/media/dvb-frontends/stv0367.c | 8 +-- drivers/media/dvb-frontends/stv0900_core.c | 4 +- drivers/media/dvb-frontends/tc90522.c | 10 ++-- drivers/media/dvb-frontends/tda10021.c | 4 +- drivers/media/dvb-frontends/tda10023.c | 4 +- drivers/media/dvb-frontends/tda10048.c | 4 +- drivers/media/dvb-frontends/tda1004x.c | 4 +- drivers/media/dvb-frontends/tda10071.c | 4 +- drivers/media/dvb-frontends/tda10086.c | 4 +- drivers/media/dvb-frontends/tda8083.c | 4 +- drivers/media/dvb-frontends/ves1820.c | 4 +- drivers/media/dvb-frontends/ves1x93.c | 4 +- drivers/media/dvb-frontends/zl10353.c | 4 +- drivers/media/pci/bt8xx/dst.c | 4 +- drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c | 4 +- drivers/media/usb/dvb-usb/af9005-fe.c | 4 +- drivers/media/usb/dvb-usb/dtt200u-fe.c | 5 +- 65 files changed, 230 insertions(+), 213 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index ca6d60f9d492..d009478f16c4 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -1361,7 +1361,7 @@ static int dtv_get_frontend(struct dvb_frontend *fe, int r; if (fe->ops.get_frontend) { - r = fe->ops.get_frontend(fe); + r = fe->ops.get_frontend(fe, c); if (unlikely(r < 0)) return r; if (p_out) diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h index 458bcce20e38..9592573a0b41 100644 --- a/drivers/media/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb-core/dvb_frontend.h @@ -449,7 +449,8 @@ struct dvb_frontend_ops { int (*set_frontend)(struct dvb_frontend *fe); int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings); - int (*get_frontend)(struct dvb_frontend *fe); + int (*get_frontend)(struct dvb_frontend *fe, + struct dtv_frontend_properties *props); int (*read_status)(struct dvb_frontend *fe, enum fe_status *status); int (*read_ber)(struct dvb_frontend* fe, u32* ber); diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c index 41ab5defb798..8bcde336ffd7 100644 --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c @@ -866,9 +866,9 @@ err: return ret; } -static int af9013_get_frontend(struct dvb_frontend *fe) +static int af9013_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct af9013_state *state = fe->demodulator_priv; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c index 8b328d1ca8d3..efebe5ce2429 100644 --- a/drivers/media/dvb-frontends/af9033.c +++ b/drivers/media/dvb-frontends/af9033.c @@ -691,10 +691,10 @@ err: return ret; } -static int af9033_get_frontend(struct dvb_frontend *fe) +static int af9033_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct af9033_dev *dev = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[8]; diff --git a/drivers/media/dvb-frontends/as102_fe.c b/drivers/media/dvb-frontends/as102_fe.c index 544c5f65d19a..9412fcd1bddb 100644 --- a/drivers/media/dvb-frontends/as102_fe.c +++ b/drivers/media/dvb-frontends/as102_fe.c @@ -190,10 +190,10 @@ static int as102_fe_set_frontend(struct dvb_frontend *fe) return state->ops->set_tune(state->priv, &tune_args); } -static int as102_fe_get_frontend(struct dvb_frontend *fe) +static int as102_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct as102_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret = 0; struct as10x_tps tps = { 0 }; diff --git a/drivers/media/dvb-frontends/atbm8830.c b/drivers/media/dvb-frontends/atbm8830.c index 8fe552e293ed..47248b868e38 100644 --- a/drivers/media/dvb-frontends/atbm8830.c +++ b/drivers/media/dvb-frontends/atbm8830.c @@ -297,9 +297,9 @@ static int atbm8830_set_fe(struct dvb_frontend *fe) return 0; } -static int atbm8830_get_fe(struct dvb_frontend *fe) +static int atbm8830_get_fe(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; dprintk("%s\n", __func__); /* TODO: get real readings from device */ diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c index 6c1e97640f3f..e676b9461a59 100644 --- a/drivers/media/dvb-frontends/au8522_dig.c +++ b/drivers/media/dvb-frontends/au8522_dig.c @@ -816,9 +816,9 @@ static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber) return au8522_read_ucblocks(fe, ber); } -static int au8522_get_frontend(struct dvb_frontend *fe) +static int au8522_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct au8522_state *state = fe->demodulator_priv; c->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c index fd033cca6e11..5cad925609e0 100644 --- a/drivers/media/dvb-frontends/cx22700.c +++ b/drivers/media/dvb-frontends/cx22700.c @@ -345,9 +345,9 @@ static int cx22700_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx22700_get_frontend(struct dvb_frontend *fe) +static int cx22700_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx22700_state* state = fe->demodulator_priv; u8 reg09 = cx22700_readreg (state, 0x09); diff --git a/drivers/media/dvb-frontends/cx22702.c b/drivers/media/dvb-frontends/cx22702.c index d2d06dcd7683..c0e54c59cccf 100644 --- a/drivers/media/dvb-frontends/cx22702.c +++ b/drivers/media/dvb-frontends/cx22702.c @@ -562,9 +562,9 @@ static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int cx22702_get_frontend(struct dvb_frontend *fe) +static int cx22702_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx22702_state *state = fe->demodulator_priv; u8 reg0C = cx22702_readreg(state, 0x0C); diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c index cb36475e322b..6cb81ec12847 100644 --- a/drivers/media/dvb-frontends/cx24110.c +++ b/drivers/media/dvb-frontends/cx24110.c @@ -550,9 +550,9 @@ static int cx24110_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx24110_get_frontend(struct dvb_frontend *fe) +static int cx24110_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cx24110_state *state = fe->demodulator_priv; s32 afc; unsigned sclk; diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c index 5f77bc80a896..a3f7eb4e609d 100644 --- a/drivers/media/dvb-frontends/cx24117.c +++ b/drivers/media/dvb-frontends/cx24117.c @@ -1560,10 +1560,10 @@ static int cx24117_get_algo(struct dvb_frontend *fe) return DVBFE_ALGO_HW; } -static int cx24117_get_frontend(struct dvb_frontend *fe) +static int cx24117_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cx24117_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24117_cmd cmd; u8 reg, st, inv; int ret, idx; diff --git a/drivers/media/dvb-frontends/cx24120.c b/drivers/media/dvb-frontends/cx24120.c index 3b0ef52bb834..6ccbd86c9490 100644 --- a/drivers/media/dvb-frontends/cx24120.c +++ b/drivers/media/dvb-frontends/cx24120.c @@ -1502,9 +1502,9 @@ static int cx24120_sleep(struct dvb_frontend *fe) return 0; } -static int cx24120_get_frontend(struct dvb_frontend *fe) +static int cx24120_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct cx24120_state *state = fe->demodulator_priv; u8 freq1, freq2, freq3; diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c index 0fe7fb11124b..113b0949408a 100644 --- a/drivers/media/dvb-frontends/cx24123.c +++ b/drivers/media/dvb-frontends/cx24123.c @@ -945,9 +945,9 @@ static int cx24123_set_frontend(struct dvb_frontend *fe) return 0; } -static int cx24123_get_frontend(struct dvb_frontend *fe) +static int cx24123_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct cx24123_state *state = fe->demodulator_priv; dprintk("\n"); diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c index 42fad6aa3958..a674a6312c38 100644 --- a/drivers/media/dvb-frontends/cxd2820r_c.c +++ b/drivers/media/dvb-frontends/cxd2820r_c.c @@ -101,10 +101,10 @@ error: return ret; } -int cxd2820r_get_frontend_c(struct dvb_frontend *fe) +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c index ba4cb7557aa5..314d3b8c1080 100644 --- a/drivers/media/dvb-frontends/cxd2820r_core.c +++ b/drivers/media/dvb-frontends/cxd2820r_core.c @@ -313,7 +313,8 @@ static int cxd2820r_read_status(struct dvb_frontend *fe, enum fe_status *status) return ret; } -static int cxd2820r_get_frontend(struct dvb_frontend *fe) +static int cxd2820r_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { struct cxd2820r_priv *priv = fe->demodulator_priv; int ret; @@ -326,13 +327,13 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe) switch (fe->dtv_property_cache.delivery_system) { case SYS_DVBT: - ret = cxd2820r_get_frontend_t(fe); + ret = cxd2820r_get_frontend_t(fe, p); break; case SYS_DVBT2: - ret = cxd2820r_get_frontend_t2(fe); + ret = cxd2820r_get_frontend_t2(fe, p); break; case SYS_DVBC_ANNEX_A: - ret = cxd2820r_get_frontend_c(fe); + ret = cxd2820r_get_frontend_c(fe, p); break; default: ret = -EINVAL; diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h index a0d53f01a8bf..e31c48e53097 100644 --- a/drivers/media/dvb-frontends/cxd2820r_priv.h +++ b/drivers/media/dvb-frontends/cxd2820r_priv.h @@ -76,7 +76,8 @@ int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val); /* cxd2820r_c.c */ -int cxd2820r_get_frontend_c(struct dvb_frontend *fe); +int cxd2820r_get_frontend_c(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_c(struct dvb_frontend *fe); @@ -99,7 +100,8 @@ int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe, /* cxd2820r_t.c */ -int cxd2820r_get_frontend_t(struct dvb_frontend *fe); +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_t(struct dvb_frontend *fe); @@ -122,7 +124,8 @@ int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe, /* cxd2820r_t2.c */ -int cxd2820r_get_frontend_t2(struct dvb_frontend *fe); +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, + struct dtv_frontend_properties *p); int cxd2820r_set_frontend_t2(struct dvb_frontend *fe); diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c index 21abf1b4ed4d..75ce7d8ded00 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t.c +++ b/drivers/media/dvb-frontends/cxd2820r_t.c @@ -138,10 +138,10 @@ error: return ret; } -int cxd2820r_get_frontend_t(struct dvb_frontend *fe) +int cxd2820r_get_frontend_t(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c index 4e028b41c0d5..704475676234 100644 --- a/drivers/media/dvb-frontends/cxd2820r_t2.c +++ b/drivers/media/dvb-frontends/cxd2820r_t2.c @@ -23,8 +23,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe) { - struct cxd2820r_priv *priv = fe->demodulator_priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct cxd2820r_priv *priv = fe->demodulator_priv; int ret, i, bw_i; u32 if_freq, if_ctl; u64 num; @@ -169,10 +169,10 @@ error: } -int cxd2820r_get_frontend_t2(struct dvb_frontend *fe) +int cxd2820r_get_frontend_t2(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct cxd2820r_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[2]; diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index fdffb2f0ded8..900186ba8e62 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -2090,13 +2090,13 @@ static int cxd2841er_sleep_tc_to_active_c(struct cxd2841er_priv *priv, return 0; } -static int cxd2841er_get_frontend(struct dvb_frontend *fe) +static int cxd2841er_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { enum fe_status status = 0; u16 strength = 0, snr = 0; u32 errors = 0, ber = 0; struct cxd2841er_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; dev_dbg(&priv->i2c->dev, "%s()\n", __func__); if (priv->state == STATE_ACTIVE_S) diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 3ca300939f79..6821ecb53d63 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -112,7 +112,8 @@ static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ } }; -static int dib3000mb_get_frontend(struct dvb_frontend* fe); +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *c); static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) { @@ -359,7 +360,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count); if (search_state == 1) { - if (dib3000mb_get_frontend(fe) == 0) { + if (dib3000mb_get_frontend(fe, c) == 0) { deb_setf("reading tuning data from frontend succeeded.\n"); return dib3000mb_set_frontend(fe, 0); } @@ -450,9 +451,9 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode) return 0; } -static int dib3000mb_get_frontend(struct dvb_frontend* fe) +static int dib3000mb_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dib3000_state* state = fe->demodulator_priv; enum fe_code_rate *cr; u16 tps_val; diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index ac90ed3af37e..da0f1dc5aaf7 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -636,9 +636,9 @@ struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master); -static int dib3000mc_get_frontend(struct dvb_frontend* fe) +static int dib3000mc_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib3000mc_state *state = fe->demodulator_priv; u16 tps = dib3000mc_read_word(state,458); @@ -726,7 +726,7 @@ static int dib3000mc_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; // no channel found - dib3000mc_get_frontend(fe); + dib3000mc_get_frontend(fe, fep); } ret = dib3000mc_tune(fe); diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c index 8b21cccf3c3a..b3ddae8885ac 100644 --- a/drivers/media/dvb-frontends/dib7000m.c +++ b/drivers/media/dvb-frontends/dib7000m.c @@ -1151,9 +1151,9 @@ static int dib7000m_identify(struct dib7000m_state *state) } -static int dib7000m_get_frontend(struct dvb_frontend* fe) +static int dib7000m_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib7000m_state *state = fe->demodulator_priv; u16 tps = dib7000m_read_word(state,480); @@ -1246,7 +1246,7 @@ static int dib7000m_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; // no channel found - dib7000m_get_frontend(fe); + dib7000m_get_frontend(fe, fep); } ret = dib7000m_tune(fe); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 65ab79ed5e3e..b861d4437f2a 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -1405,9 +1405,9 @@ static int dib7000p_identify(struct dib7000p_state *st) return 0; } -static int dib7000p_get_frontend(struct dvb_frontend *fe) +static int dib7000p_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dib7000p_state *state = fe->demodulator_priv; u16 tps = dib7000p_read_word(state, 463); @@ -1540,7 +1540,7 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe) if (found == 0 || found == 1) return 0; - dib7000p_get_frontend(fe); + dib7000p_get_frontend(fe, fep); } ret = dib7000p_tune(fe); diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index 349d2f1f62ce..ddf9c44877a2 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -3382,14 +3382,15 @@ static int dib8000_sleep(struct dvb_frontend *fe) static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat); -static int dib8000_get_frontend(struct dvb_frontend *fe) +static int dib8000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct dib8000_state *state = fe->demodulator_priv; u16 i, val = 0; enum fe_status stat = 0; u8 index_frontend, sub_index_frontend; - fe->dtv_property_cache.bandwidth_hz = 6000000; + c->bandwidth_hz = 6000000; /* * If called to early, get_frontend makes dib8000_tune to either @@ -3406,7 +3407,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) if (stat&FE_HAS_SYNC) { dprintk("TMCC lock on the slave%i", index_frontend); /* synchronize the cache with the other frontends */ - state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); + state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { if (sub_index_frontend != index_frontend) { state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode; @@ -3426,57 +3427,57 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) } } - fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; + c->isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1; if (state->revision == 0x8090) val = dib8000_read_word(state, 572); else val = dib8000_read_word(state, 570); - fe->dtv_property_cache.inversion = (val & 0x40) >> 6; + c->inversion = (val & 0x40) >> 6; switch ((val & 0x30) >> 4) { case 1: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K; + c->transmission_mode = TRANSMISSION_MODE_2K; dprintk("dib8000_get_frontend: transmission mode 2K"); break; case 2: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K; + c->transmission_mode = TRANSMISSION_MODE_4K; dprintk("dib8000_get_frontend: transmission mode 4K"); break; case 3: default: - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K; + c->transmission_mode = TRANSMISSION_MODE_8K; dprintk("dib8000_get_frontend: transmission mode 8K"); break; } switch (val & 0x3) { case 0: - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32; + c->guard_interval = GUARD_INTERVAL_1_32; dprintk("dib8000_get_frontend: Guard Interval = 1/32 "); break; case 1: - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16; + c->guard_interval = GUARD_INTERVAL_1_16; dprintk("dib8000_get_frontend: Guard Interval = 1/16 "); break; case 2: dprintk("dib8000_get_frontend: Guard Interval = 1/8 "); - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8; + c->guard_interval = GUARD_INTERVAL_1_8; break; case 3: dprintk("dib8000_get_frontend: Guard Interval = 1/4 "); - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4; + c->guard_interval = GUARD_INTERVAL_1_4; break; } val = dib8000_read_word(state, 505); - fe->dtv_property_cache.isdbt_partial_reception = val & 1; - dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception); + c->isdbt_partial_reception = val & 1; + dprintk("dib8000_get_frontend: partial_reception = %d ", c->isdbt_partial_reception); for (i = 0; i < 3; i++) { int show; val = dib8000_read_word(state, 493 + i) & 0x0f; - fe->dtv_property_cache.layer[i].segment_count = val; + c->layer[i].segment_count = val; if (val == 0 || val > 13) show = 0; @@ -3485,41 +3486,41 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) if (show) dprintk("dib8000_get_frontend: Layer %d segments = %d ", - i, fe->dtv_property_cache.layer[i].segment_count); + i, c->layer[i].segment_count); val = dib8000_read_word(state, 499 + i) & 0x3; /* Interleaving can be 0, 1, 2 or 4 */ if (val == 3) val = 4; - fe->dtv_property_cache.layer[i].interleaving = val; + c->layer[i].interleaving = val; if (show) dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ", - i, fe->dtv_property_cache.layer[i].interleaving); + i, c->layer[i].interleaving); val = dib8000_read_word(state, 481 + i); switch (val & 0x7) { case 1: - fe->dtv_property_cache.layer[i].fec = FEC_1_2; + c->layer[i].fec = FEC_1_2; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i); break; case 2: - fe->dtv_property_cache.layer[i].fec = FEC_2_3; + c->layer[i].fec = FEC_2_3; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i); break; case 3: - fe->dtv_property_cache.layer[i].fec = FEC_3_4; + c->layer[i].fec = FEC_3_4; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i); break; case 5: - fe->dtv_property_cache.layer[i].fec = FEC_5_6; + c->layer[i].fec = FEC_5_6; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i); break; default: - fe->dtv_property_cache.layer[i].fec = FEC_7_8; + c->layer[i].fec = FEC_7_8; if (show) dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i); break; @@ -3528,23 +3529,23 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) val = dib8000_read_word(state, 487 + i); switch (val & 0x3) { case 0: - fe->dtv_property_cache.layer[i].modulation = DQPSK; + c->layer[i].modulation = DQPSK; if (show) dprintk("dib8000_get_frontend: Layer %d DQPSK ", i); break; case 1: - fe->dtv_property_cache.layer[i].modulation = QPSK; + c->layer[i].modulation = QPSK; if (show) dprintk("dib8000_get_frontend: Layer %d QPSK ", i); break; case 2: - fe->dtv_property_cache.layer[i].modulation = QAM_16; + c->layer[i].modulation = QAM_16; if (show) dprintk("dib8000_get_frontend: Layer %d QAM16 ", i); break; case 3: default: - fe->dtv_property_cache.layer[i].modulation = QAM_64; + c->layer[i].modulation = QAM_64; if (show) dprintk("dib8000_get_frontend: Layer %d QAM64 ", i); break; @@ -3553,16 +3554,16 @@ static int dib8000_get_frontend(struct dvb_frontend *fe) /* synchronize the cache with the other frontends */ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode; - state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; - state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; - state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; - state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception; + state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = c->isdbt_sb_mode; + state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; + state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; + state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; + state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = c->isdbt_partial_reception; for (i = 0; i < 3; i++) { - state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count; - state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving; - state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec; - state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation; + state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = c->layer[i].segment_count; + state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = c->layer[i].interleaving; + state->fe[index_frontend]->dtv_property_cache.layer[i].fec = c->layer[i].fec; + state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = c->layer[i].modulation; } } return 0; @@ -3671,7 +3672,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe) if (state->channel_parameters_set == 0) { /* searching */ if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) { dprintk("autosearch succeeded on fe%i", index_frontend); - dib8000_get_frontend(state->fe[index_frontend]); /* we read the channel parameters from the frontend which was successful */ + dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */ state->channel_parameters_set = 1; for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) { diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c index 91888a2f5301..bab8c5a980a2 100644 --- a/drivers/media/dvb-frontends/dib9000.c +++ b/drivers/media/dvb-frontends/dib9000.c @@ -1889,7 +1889,8 @@ static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_fron return 0; } -static int dib9000_get_frontend(struct dvb_frontend *fe) +static int dib9000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct dib9000_state *state = fe->demodulator_priv; u8 index_frontend, sub_index_frontend; @@ -1909,7 +1910,7 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) dprintk("TPS lock on the slave%i", index_frontend); /* synchronize the cache with the other frontends */ - state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]); + state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c); for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) { if (sub_index_frontend != index_frontend) { @@ -1943,14 +1944,14 @@ static int dib9000_get_frontend(struct dvb_frontend *fe) /* synchronize the cache with the other frontends */ for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) { - state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion; - state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode; - state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval; - state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation; - state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy; - state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP; - state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP; - state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff; + state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion; + state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode; + state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval; + state->fe[index_frontend]->dtv_property_cache.modulation = c->modulation; + state->fe[index_frontend]->dtv_property_cache.hierarchy = c->hierarchy; + state->fe[index_frontend]->dtv_property_cache.code_rate_HP = c->code_rate_HP; + state->fe[index_frontend]->dtv_property_cache.code_rate_LP = c->code_rate_LP; + state->fe[index_frontend]->dtv_property_cache.rolloff = c->rolloff; } ret = 0; @@ -2083,7 +2084,7 @@ static int dib9000_set_frontend(struct dvb_frontend *fe) /* synchronize all the channel cache */ state->get_frontend_internal = 1; - dib9000_get_frontend(state->fe[0]); + dib9000_get_frontend(state->fe[0], &state->fe[0]->dtv_property_cache); state->get_frontend_internal = 0; /* retune the other frontends with the found channel */ diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c index 14e996d45fac..e5bd8c62ad3a 100644 --- a/drivers/media/dvb-frontends/dvb_dummy_fe.c +++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c @@ -70,9 +70,12 @@ static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) } /* - * Only needed if it actually reads something from the hardware + * Should only be implemented if it actually reads something from the hardware. + * Also, it should check for the locks, in order to avoid report wrong data + * to userspace. */ -static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe) +static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { return 0; } diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c index 40e359f2d17d..1c7eb477e2cd 100644 --- a/drivers/media/dvb-frontends/hd29l2.c +++ b/drivers/media/dvb-frontends/hd29l2.c @@ -560,11 +560,11 @@ static int hd29l2_get_frontend_algo(struct dvb_frontend *fe) return DVBFE_ALGO_CUSTOM; } -static int hd29l2_get_frontend(struct dvb_frontend *fe) +static int hd29l2_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { int ret; struct hd29l2_priv *priv = fe->demodulator_priv; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; u8 buf[3]; u32 if_ctl; char *str_constellation, *str_code_rate, *str_constellation_code_rate, diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c index 0977871232a2..2f3d0519e19b 100644 --- a/drivers/media/dvb-frontends/l64781.c +++ b/drivers/media/dvb-frontends/l64781.c @@ -243,9 +243,9 @@ static int apply_frontend_param(struct dvb_frontend *fe) return 0; } -static int get_frontend(struct dvb_frontend *fe) +static int get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct l64781_state* state = fe->demodulator_priv; int tmp; diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c index 7880f71ccd8a..f51a3a0b3949 100644 --- a/drivers/media/dvb-frontends/lg2160.c +++ b/drivers/media/dvb-frontends/lg2160.c @@ -942,101 +942,102 @@ static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err) /* ------------------------------------------------------------------------ */ -static int lg216x_get_frontend(struct dvb_frontend *fe) +static int lg216x_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct lg216x_state *state = fe->demodulator_priv; int ret; lg_dbg("\n"); - fe->dtv_property_cache.modulation = VSB_8; - fe->dtv_property_cache.frequency = state->current_frequency; - fe->dtv_property_cache.delivery_system = SYS_ATSCMH; + c->modulation = VSB_8; + c->frequency = state->current_frequency; + c->delivery_system = SYS_ATSCMH; ret = lg216x_get_fic_version(state, - &fe->dtv_property_cache.atscmh_fic_ver); + &c->atscmh_fic_ver); if (lg_fail(ret)) goto fail; - if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) { - state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver; + if (state->fic_ver != c->atscmh_fic_ver) { + state->fic_ver = c->atscmh_fic_ver; #if 0 ret = lg2160_get_parade_id(state, - &fe->dtv_property_cache.atscmh_parade_id); + &c->atscmh_parade_id); if (lg_fail(ret)) goto fail; /* #else */ - fe->dtv_property_cache.atscmh_parade_id = state->parade_id; + c->atscmh_parade_id = state->parade_id; #endif ret = lg216x_get_nog(state, - &fe->dtv_property_cache.atscmh_nog); + &c->atscmh_nog); if (lg_fail(ret)) goto fail; ret = lg216x_get_tnog(state, - &fe->dtv_property_cache.atscmh_tnog); + &c->atscmh_tnog); if (lg_fail(ret)) goto fail; ret = lg216x_get_sgn(state, - &fe->dtv_property_cache.atscmh_sgn); + &c->atscmh_sgn); if (lg_fail(ret)) goto fail; ret = lg216x_get_prc(state, - &fe->dtv_property_cache.atscmh_prc); + &c->atscmh_prc); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_frame_mode(state, (enum atscmh_rs_frame_mode *) - &fe->dtv_property_cache.atscmh_rs_frame_mode); + &c->atscmh_rs_frame_mode); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_frame_ensemble(state, (enum atscmh_rs_frame_ensemble *) - &fe->dtv_property_cache.atscmh_rs_frame_ensemble); + &c->atscmh_rs_frame_ensemble); if (lg_fail(ret)) goto fail; ret = lg216x_get_rs_code_mode(state, (enum atscmh_rs_code_mode *) - &fe->dtv_property_cache.atscmh_rs_code_mode_pri, + &c->atscmh_rs_code_mode_pri, (enum atscmh_rs_code_mode *) - &fe->dtv_property_cache.atscmh_rs_code_mode_sec); + &c->atscmh_rs_code_mode_sec); if (lg_fail(ret)) goto fail; ret = lg216x_get_sccc_block_mode(state, (enum atscmh_sccc_block_mode *) - &fe->dtv_property_cache.atscmh_sccc_block_mode); + &c->atscmh_sccc_block_mode); if (lg_fail(ret)) goto fail; ret = lg216x_get_sccc_code_mode(state, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_a, + &c->atscmh_sccc_code_mode_a, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_b, + &c->atscmh_sccc_code_mode_b, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_c, + &c->atscmh_sccc_code_mode_c, (enum atscmh_sccc_code_mode *) - &fe->dtv_property_cache.atscmh_sccc_code_mode_d); + &c->atscmh_sccc_code_mode_d); if (lg_fail(ret)) goto fail; } #if 0 ret = lg216x_read_fic_err_count(state, - (u8 *)&fe->dtv_property_cache.atscmh_fic_err); + (u8 *)&c->atscmh_fic_err); if (lg_fail(ret)) goto fail; ret = lg216x_read_crc_err_count(state, - &fe->dtv_property_cache.atscmh_crc_err); + &c->atscmh_crc_err); if (lg_fail(ret)) goto fail; ret = lg216x_read_rs_err_count(state, - &fe->dtv_property_cache.atscmh_rs_err); + &c->atscmh_rs_err); if (lg_fail(ret)) goto fail; switch (state->cfg->lg_chip) { case LG2160: - if (((fe->dtv_property_cache.atscmh_rs_err >= 240) && - (fe->dtv_property_cache.atscmh_crc_err >= 240)) && + if (((c->atscmh_rs_err >= 240) && + (c->atscmh_crc_err >= 240)) && ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000)) ret = lg216x_soft_reset(state); break; @@ -1054,14 +1055,17 @@ fail: static int lg216x_get_property(struct dvb_frontend *fe, struct dtv_property *tvp) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + return (DTV_ATSCMH_FIC_VER == tvp->cmd) ? - lg216x_get_frontend(fe) : 0; + lg216x_get_frontend(fe, c) : 0; } static int lg2160_set_frontend(struct dvb_frontend *fe) { struct lg216x_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; lg_dbg("(%d)\n", fe->dtv_property_cache.frequency); @@ -1129,7 +1133,7 @@ static int lg2160_set_frontend(struct dvb_frontend *fe) ret = lg216x_enable_fic(state, 1); lg_fail(ret); - lg216x_get_frontend(fe); + lg216x_get_frontend(fe, c); fail: return ret; } diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c index 47121866163d..4503e8852fd1 100644 --- a/drivers/media/dvb-frontends/lgdt3305.c +++ b/drivers/media/dvb-frontends/lgdt3305.c @@ -812,9 +812,9 @@ fail: return ret; } -static int lgdt3305_get_frontend(struct dvb_frontend *fe) +static int lgdt3305_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgdt3305_state *state = fe->demodulator_priv; lg_dbg("\n"); diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index 721fbc07e9ee..179c26e5eb4e 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -1040,10 +1040,10 @@ fail: return ret; } -static int lgdt3306a_get_frontend(struct dvb_frontend *fe) +static int lgdt3306a_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { struct lgdt3306a_state *state = fe->demodulator_priv; - struct dtv_frontend_properties *p = &fe->dtv_property_cache; dbg_info("(%u, %d)\n", state->current_frequency, state->current_modulation); diff --git a/drivers/media/dvb-frontends/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c index cf3cc20510da..96bf254da21e 100644 --- a/drivers/media/dvb-frontends/lgdt330x.c +++ b/drivers/media/dvb-frontends/lgdt330x.c @@ -439,10 +439,11 @@ static int lgdt330x_set_parameters(struct dvb_frontend *fe) return 0; } -static int lgdt330x_get_frontend(struct dvb_frontend *fe) +static int lgdt330x_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgdt330x_state *state = fe->demodulator_priv; + p->frequency = state->current_frequency; return 0; } diff --git a/drivers/media/dvb-frontends/lgs8gl5.c b/drivers/media/dvb-frontends/lgs8gl5.c index 7bbb2c18c2dd..fbfd87b5b803 100644 --- a/drivers/media/dvb-frontends/lgs8gl5.c +++ b/drivers/media/dvb-frontends/lgs8gl5.c @@ -336,10 +336,11 @@ lgs8gl5_set_frontend(struct dvb_frontend *fe) static int -lgs8gl5_get_frontend(struct dvb_frontend *fe) +lgs8gl5_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct lgs8gl5_state *state = fe->demodulator_priv; + u8 inv = lgs8gl5_read_reg(state, REG_INVERSION); p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index ce73a5ec6036..76883600ec6f 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -791,11 +791,11 @@ err: return ret; } -static int m88ds3103_get_frontend(struct dvb_frontend *fe) +static int m88ds3103_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct m88ds3103_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c index 9b6f464c48bd..a09b12313a73 100644 --- a/drivers/media/dvb-frontends/m88rs2000.c +++ b/drivers/media/dvb-frontends/m88rs2000.c @@ -708,10 +708,11 @@ static int m88rs2000_set_frontend(struct dvb_frontend *fe) return 0; } -static int m88rs2000_get_frontend(struct dvb_frontend *fe) +static int m88rs2000_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct m88rs2000_state *state = fe->demodulator_priv; + c->fec_inner = state->fec_inner; c->frequency = state->tuner_frequency; c->symbol_rate = state->symbol_rate; diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c index c36e6764eead..fc08429c99b7 100644 --- a/drivers/media/dvb-frontends/mt312.c +++ b/drivers/media/dvb-frontends/mt312.c @@ -647,9 +647,9 @@ static int mt312_set_frontend(struct dvb_frontend *fe) return 0; } -static int mt312_get_frontend(struct dvb_frontend *fe) +static int mt312_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mt312_state *state = fe->demodulator_priv; int ret; diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c index 123bb2f8e4b6..c0bb6328956b 100644 --- a/drivers/media/dvb-frontends/mt352.c +++ b/drivers/media/dvb-frontends/mt352.c @@ -311,9 +311,9 @@ static int mt352_set_parameters(struct dvb_frontend *fe) return 0; } -static int mt352_get_parameters(struct dvb_frontend* fe) +static int mt352_get_parameters(struct dvb_frontend* fe, + struct dtv_frontend_properties *op) { - struct dtv_frontend_properties *op = &fe->dtv_property_cache; struct mt352_state* state = fe->demodulator_priv; u16 tps; u16 div; diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 35b1053b3640..a165af990672 100644 --- a/drivers/media/dvb-frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c @@ -375,9 +375,9 @@ static int or51132_set_parameters(struct dvb_frontend *fe) return 0; } -static int or51132_get_parameters(struct dvb_frontend* fe) +static int or51132_get_parameters(struct dvb_frontend* fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct or51132_state* state = fe->demodulator_priv; int status; int retry = 1; diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c index 74b771218033..3f96429af0e5 100644 --- a/drivers/media/dvb-frontends/rtl2830.c +++ b/drivers/media/dvb-frontends/rtl2830.c @@ -279,11 +279,11 @@ err: return ret; } -static int rtl2830_get_frontend(struct dvb_frontend *fe) +static int rtl2830_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct i2c_client *client = fe->demodulator_priv; struct rtl2830_dev *dev = i2c_get_clientdata(client); - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c index 10f2119935da..c2469fb42f12 100644 --- a/drivers/media/dvb-frontends/rtl2832.c +++ b/drivers/media/dvb-frontends/rtl2832.c @@ -575,11 +575,11 @@ err: return ret; } -static int rtl2832_get_frontend(struct dvb_frontend *fe) +static int rtl2832_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct rtl2832_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret; u8 buf[3]; diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c index 10964848a2f1..c68965ad97c0 100644 --- a/drivers/media/dvb-frontends/s5h1409.c +++ b/drivers/media/dvb-frontends/s5h1409.c @@ -925,9 +925,9 @@ static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber) return s5h1409_read_ucblocks(fe, ber); } -static int s5h1409_get_frontend(struct dvb_frontend *fe) +static int s5h1409_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1409_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index 9afc3f42290e..90f86e82b087 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -840,9 +840,9 @@ static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber) return s5h1411_read_ucblocks(fe, ber); } -static int s5h1411_get_frontend(struct dvb_frontend *fe) +static int s5h1411_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1411_state *state = fe->demodulator_priv; p->frequency = state->current_frequency; diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c index 9c22a4c70d87..d7d0b7d57ad7 100644 --- a/drivers/media/dvb-frontends/s5h1420.c +++ b/drivers/media/dvb-frontends/s5h1420.c @@ -756,9 +756,9 @@ static int s5h1420_set_frontend(struct dvb_frontend *fe) return 0; } -static int s5h1420_get_frontend(struct dvb_frontend* fe) +static int s5h1420_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s5h1420_state* state = fe->demodulator_priv; p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state); diff --git a/drivers/media/dvb-frontends/s921.c b/drivers/media/dvb-frontends/s921.c index d6a8fa63040b..b5e3d90eba5e 100644 --- a/drivers/media/dvb-frontends/s921.c +++ b/drivers/media/dvb-frontends/s921.c @@ -433,9 +433,9 @@ static int s921_set_frontend(struct dvb_frontend *fe) return 0; } -static int s921_get_frontend(struct dvb_frontend *fe) +static int s921_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct s921_state *state = fe->demodulator_priv; /* FIXME: Probably it is possible to get it from regs f1 and f2 */ diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c index 756650f154ab..3d171b0e00c2 100644 --- a/drivers/media/dvb-frontends/stb0899_drv.c +++ b/drivers/media/dvb-frontends/stb0899_drv.c @@ -1568,9 +1568,9 @@ static enum dvbfe_search stb0899_search(struct dvb_frontend *fe) return DVBFE_ALGO_SEARCH_ERROR; } -static int stb0899_get_frontend(struct dvb_frontend *fe) +static int stb0899_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stb0899_state *state = fe->demodulator_priv; struct stb0899_internal *internal = &state->internal; diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c index c978c801c7aa..b9c2511bf019 100644 --- a/drivers/media/dvb-frontends/stb6100.c +++ b/drivers/media/dvb-frontends/stb6100.c @@ -346,7 +346,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) if (fe->ops.get_frontend) { dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters"); - fe->ops.get_frontend(fe); + fe->ops.get_frontend(fe, p); } srate = p->symbol_rate; diff --git a/drivers/media/dvb-frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c index 75b4d8b25657..81b27b7c0c96 100644 --- a/drivers/media/dvb-frontends/stv0297.c +++ b/drivers/media/dvb-frontends/stv0297.c @@ -615,9 +615,9 @@ timeout: return 0; } -static int stv0297_get_frontend(struct dvb_frontend *fe) +static int stv0297_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0297_state *state = fe->demodulator_priv; int reg_00, reg_83; diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c index c43f36d32340..7927fa925f2f 100644 --- a/drivers/media/dvb-frontends/stv0299.c +++ b/drivers/media/dvb-frontends/stv0299.c @@ -602,9 +602,9 @@ static int stv0299_set_frontend(struct dvb_frontend *fe) return 0; } -static int stv0299_get_frontend(struct dvb_frontend *fe) +static int stv0299_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0299_state* state = fe->demodulator_priv; s32 derot_freq; int invval; diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index 44cb73f68af6..abc379aea713 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -1938,9 +1938,9 @@ static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int stv0367ter_get_frontend(struct dvb_frontend *fe) +static int stv0367ter_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367ter_state *ter_state = state->ter_state; enum stv0367_ter_mode mode; @@ -3146,9 +3146,9 @@ static int stv0367cab_set_frontend(struct dvb_frontend *fe) return 0; } -static int stv0367cab_get_frontend(struct dvb_frontend *fe) +static int stv0367cab_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0367_state *state = fe->demodulator_priv; struct stv0367cab_state *cab_state = state->cab_state; diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index fe31dd541955..28239b1fd954 100644 --- a/drivers/media/dvb-frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c @@ -1859,9 +1859,9 @@ static int stv0900_sleep(struct dvb_frontend *fe) return 0; } -static int stv0900_get_frontend(struct dvb_frontend *fe) +static int stv0900_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct stv0900_state *state = fe->demodulator_priv; struct stv0900_internal *intp = state->internal; enum fe_stv0900_demod_num demod = state->demod; diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c index 456cdc7fb1e7..31cd32532387 100644 --- a/drivers/media/dvb-frontends/tc90522.c +++ b/drivers/media/dvb-frontends/tc90522.c @@ -201,10 +201,10 @@ static const enum fe_code_rate fec_conv_sat[] = { FEC_2_3, /* for 8PSK. (trellis code) */ }; -static int tc90522s_get_frontend(struct dvb_frontend *fe) +static int tc90522s_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tc90522_state *state; - struct dtv_frontend_properties *c; struct dtv_fe_stats *stats; int ret, i; int layers; @@ -212,7 +212,6 @@ static int tc90522s_get_frontend(struct dvb_frontend *fe) u32 cndat; state = fe->demodulator_priv; - c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBS; c->symbol_rate = 28860000; @@ -337,10 +336,10 @@ static const enum fe_modulation mod_conv[] = { DQPSK, QPSK, QAM_16, QAM_64, 0, 0, 0, 0 }; -static int tc90522t_get_frontend(struct dvb_frontend *fe) +static int tc90522t_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tc90522_state *state; - struct dtv_frontend_properties *c; struct dtv_fe_stats *stats; int ret, i; int layers; @@ -348,7 +347,6 @@ static int tc90522t_get_frontend(struct dvb_frontend *fe) u32 cndat; state = fe->demodulator_priv; - c = &fe->dtv_property_cache; c->delivery_system = SYS_ISDBT; c->bandwidth_hz = 6000000; mode = 1; diff --git a/drivers/media/dvb-frontends/tda10021.c b/drivers/media/dvb-frontends/tda10021.c index a684424e665a..806c56691ca5 100644 --- a/drivers/media/dvb-frontends/tda10021.c +++ b/drivers/media/dvb-frontends/tda10021.c @@ -387,9 +387,9 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int tda10021_get_frontend(struct dvb_frontend *fe) +static int tda10021_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10021_state* state = fe->demodulator_priv; int sync; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/tda10023.c b/drivers/media/dvb-frontends/tda10023.c index 44a55656093f..3b8c7e499d0d 100644 --- a/drivers/media/dvb-frontends/tda10023.c +++ b/drivers/media/dvb-frontends/tda10023.c @@ -457,9 +457,9 @@ static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int tda10023_get_frontend(struct dvb_frontend *fe) +static int tda10023_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10023_state* state = fe->demodulator_priv; int sync,inv; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/tda10048.c b/drivers/media/dvb-frontends/tda10048.c index 8451086c563f..c2bf89d0b0b0 100644 --- a/drivers/media/dvb-frontends/tda10048.c +++ b/drivers/media/dvb-frontends/tda10048.c @@ -1028,9 +1028,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) return 0; } -static int tda10048_get_frontend(struct dvb_frontend *fe) +static int tda10048_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda10048_state *state = fe->demodulator_priv; dprintk(1, "%s()\n", __func__); diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c index 0e209b56c76c..3137a9ba3a32 100644 --- a/drivers/media/dvb-frontends/tda1004x.c +++ b/drivers/media/dvb-frontends/tda1004x.c @@ -899,9 +899,9 @@ static int tda1004x_set_fe(struct dvb_frontend *fe) return 0; } -static int tda1004x_get_fe(struct dvb_frontend *fe) +static int tda1004x_get_fe(struct dvb_frontend *fe, + struct dtv_frontend_properties *fe_params) { - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda1004x_state* state = fe->demodulator_priv; dprintk("%s\n", __func__); diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c index 119d47596ac8..37ebeef2bbd0 100644 --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c @@ -701,11 +701,11 @@ error: return ret; } -static int tda10071_get_frontend(struct dvb_frontend *fe) +static int tda10071_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { struct tda10071_dev *dev = fe->demodulator_priv; struct i2c_client *client = dev->client; - struct dtv_frontend_properties *c = &fe->dtv_property_cache; int ret, i; u8 buf[5], tmp; diff --git a/drivers/media/dvb-frontends/tda10086.c b/drivers/media/dvb-frontends/tda10086.c index 95a33e187f8e..31d0acb54fe8 100644 --- a/drivers/media/dvb-frontends/tda10086.c +++ b/drivers/media/dvb-frontends/tda10086.c @@ -459,9 +459,9 @@ static int tda10086_set_frontend(struct dvb_frontend *fe) return 0; } -static int tda10086_get_frontend(struct dvb_frontend *fe) +static int tda10086_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fe_params) { - struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; struct tda10086_state* state = fe->demodulator_priv; u8 val; int tmp; diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c index 796543fa2c8d..9072d6463094 100644 --- a/drivers/media/dvb-frontends/tda8083.c +++ b/drivers/media/dvb-frontends/tda8083.c @@ -342,9 +342,9 @@ static int tda8083_set_frontend(struct dvb_frontend *fe) return 0; } -static int tda8083_get_frontend(struct dvb_frontend *fe) +static int tda8083_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct tda8083_state* state = fe->demodulator_priv; /* FIXME: get symbolrate & frequency offset...*/ diff --git a/drivers/media/dvb-frontends/ves1820.c b/drivers/media/dvb-frontends/ves1820.c index aacfdda3e005..b09fe88c40f8 100644 --- a/drivers/media/dvb-frontends/ves1820.c +++ b/drivers/media/dvb-frontends/ves1820.c @@ -312,9 +312,9 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) return 0; } -static int ves1820_get_frontend(struct dvb_frontend *fe) +static int ves1820_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct ves1820_state* state = fe->demodulator_priv; int sync; s8 afc = 0; diff --git a/drivers/media/dvb-frontends/ves1x93.c b/drivers/media/dvb-frontends/ves1x93.c index 526952396422..ed113e216e14 100644 --- a/drivers/media/dvb-frontends/ves1x93.c +++ b/drivers/media/dvb-frontends/ves1x93.c @@ -406,9 +406,9 @@ static int ves1x93_set_frontend(struct dvb_frontend *fe) return 0; } -static int ves1x93_get_frontend(struct dvb_frontend *fe) +static int ves1x93_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct ves1x93_state* state = fe->demodulator_priv; int afc; diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c index ef9764a02d4c..1832c2f7695c 100644 --- a/drivers/media/dvb-frontends/zl10353.c +++ b/drivers/media/dvb-frontends/zl10353.c @@ -371,9 +371,9 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) return 0; } -static int zl10353_get_parameters(struct dvb_frontend *fe) +static int zl10353_get_parameters(struct dvb_frontend *fe, + struct dtv_frontend_properties *c) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct zl10353_state *state = fe->demodulator_priv; int s6, s9; u16 tps; diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c index 4a90eee5e3bb..35bc9b2287b4 100644 --- a/drivers/media/pci/bt8xx/dst.c +++ b/drivers/media/pci/bt8xx/dst.c @@ -1688,9 +1688,9 @@ static int dst_get_tuning_algo(struct dvb_frontend *fe) return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } -static int dst_get_frontend(struct dvb_frontend *fe) +static int dst_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct dst_state *state = fe->demodulator_priv; p->frequency = state->decode_freq; diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c index 84f6de6fa07d..047a32fe43ea 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c @@ -507,9 +507,9 @@ static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe, return 0; } -static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe) +static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *p) { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; struct mxl111sf_demod_state *state = fe->demodulator_priv; mxl_dbg("()"); diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c index ac97075d75f7..09db3d02bd82 100644 --- a/drivers/media/usb/dvb-usb/af9005-fe.c +++ b/drivers/media/usb/dvb-usb/af9005-fe.c @@ -1227,9 +1227,9 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe) return 0; } -static int af9005_fe_get_frontend(struct dvb_frontend *fe) +static int af9005_fe_get_frontend(struct dvb_frontend *fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct af9005_fe_state *state = fe->demodulator_priv; int ret; u8 temp; diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index 7e72a1bef76a..c09332bd99cb 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -140,10 +140,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe) return 0; } -static int dtt200u_fe_get_frontend(struct dvb_frontend* fe) +static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, + struct dtv_frontend_properties *fep) { - struct dtv_frontend_properties *fep = &fe->dtv_property_cache; struct dtt200u_fe_state *state = fe->demodulator_priv; + memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties)); return 0; } -- cgit From bb31d2381c730485be00a7da44c45416e9781709 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 4 Feb 2016 13:26:22 -0200 Subject: [media] dvb_frontend: Don't let drivers to trash data at cache GET_FRONTEND and G_PROPERTY can be called anytime, even when the tuner/demod is not fully locked. However, several parameters returned by those calls are available only after the demod get VITERBI lock. While several drivers do the right thing by checking the status before returning the parameter, some drivers simply blindly update the DTV properties cache without checking if the registers at the hardware contain valid values. Due to that, programs that call G_PROPERTY (or GET_FRONTEND) before having a tuner lock may interfere at the zigzag logic, as the DVB kthread calls the set_frontend() callback several times, to fine tune the frequency and to identify if the signal is inverted or not. While the drivers should be fixed to report the right status, we should prevent that such bugs would actually interfere at the device operation. So, let's use a separate var for userspace calls to get frontend. As we copy the content of the cache, this should not cause any troubles. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index d009478f16c4..4c35eb47472b 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -2087,6 +2087,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__); } else if (cmd == FE_GET_PROPERTY) { + struct dtv_frontend_properties getp = fe->dtv_property_cache; + dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num); dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props); @@ -2108,17 +2110,18 @@ static int dvb_frontend_ioctl_properties(struct file *file, } /* - * Fills the cache out struct with the cache contents, plus - * the data retrieved from get_frontend, if the frontend - * is not idle. Otherwise, returns the cached content + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. */ if (fepriv->state != FESTATE_IDLE) { - err = dtv_get_frontend(fe, c, NULL); + err = dtv_get_frontend(fe, &getp, NULL); if (err < 0) goto out; } for (i = 0; i < tvps->num; i++) { - err = dtv_property_process_get(fe, c, tvp + i, file); + err = dtv_property_process_get(fe, &getp, tvp + i, file); if (err < 0) goto out; (tvp + i)->result = err; @@ -2523,10 +2526,18 @@ static int dvb_frontend_ioctl_legacy(struct file *file, err = dvb_frontend_get_event (fe, parg, file->f_flags); break; - case FE_GET_FRONTEND: - err = dtv_get_frontend(fe, c, parg); - break; + case FE_GET_FRONTEND: { + struct dtv_frontend_properties getp = fe->dtv_property_cache; + /* + * Let's use our own copy of property cache, in order to + * avoid mangling with DTV zigzag logic, as drivers might + * return crap, if they don't check if the data is available + * before updating the properties cache. + */ + err = dtv_get_frontend(fe, &getp, parg); + break; + } case FE_SET_FRONTEND_TUNE_MODE: fepriv->tune_mode_flags = (unsigned long) parg; err = 0; -- cgit From 3e2751d9169563486c2bfe7382726f1315cb156b Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 4 Feb 2016 12:30:36 +0100 Subject: perf tools: Fix parallel build including 'clean' target Do not parallelize 'clean' with other targets, figure out if it is present and do it first, then the other targets. Noticed with: tools/perf> make -j24 clean all LD arch/libperf-in.o LD plugin_xen-in.o arch//libperf-in.o: file not recognized: File truncated make[3]: *** [arch/libperf-in.o] Error 1 make[2]: *** [arch] Error 2 make[2]: *** Waiting for unfinished jobs.... AR libapi.a Reported-and-Tested-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa Acked-by: Wang Nan Link: http://lkml.kernel.org/n/tip-kb0qs29zbz7hxn32mc5zbsoz@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 4b68f465195c..67837c6cdbd8 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -68,6 +68,20 @@ all tags TAGS: $(print_msg) $(make) +ifdef MAKECMDGOALS +has_clean := 0 +ifneq ($(filter clean,$(MAKECMDGOALS)),) + has_clean := 1 +endif # clean + +ifeq ($(has_clean),1) + rest := $(filter-out clean,$(MAKECMDGOALS)) + ifneq ($(rest),) +$(rest): clean + endif # rest +endif # has_clean +endif # MAKECMDGOALS + # # The clean target is not really parallel, don't print the jobs info: # -- cgit From be9e49911123516ef883836906269832aec37e01 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 3 Feb 2016 17:28:45 -0300 Subject: perf build tests: Do parallell builds with 'build-test' Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-jhmnf9g7y9ryqcjql00unk5y@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 67837c6cdbd8..32a64e619028 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -99,7 +99,7 @@ clean: # make -C tools/perf -f tests/make # build-test: - @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile --no-print-directory tarpkg out + @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory tarpkg out # # All other targets get passed through: -- cgit From 1586ba0c218b10cce1de57c45f599dd8831a2d12 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 4 Feb 2016 11:17:36 -0500 Subject: USB: EHCI: fix compiler warning introduced by commit 2a40f324541e Fix the following compiler warning (found by the kbuild test robot): drivers/usb/host/ehci-hcd.c:312:13: warning: 'unlink_empty_async_suspended' declared 'static' but never defined Commit 2a40f324541e ("USB: EHCI: fix regression during bus resume") protected the function definition with a "#ifdef CONFIG_PM" block, so now the declaration needs to be similarly protected. This patch moves it to a better location. Reported-by: kbuild test robot Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 1 - drivers/usb/host/ehci-hub.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a93d445b63a4..ae1b6e69eb96 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -309,7 +309,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci) static void end_iaa_cycle(struct ehci_hcd *ehci); static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); -static void unlink_empty_async_suspended(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 6333d3c2be9c..ffc90295a95f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -33,6 +33,8 @@ #ifdef CONFIG_PM +static void unlink_empty_async_suspended(struct ehci_hcd *ehci); + static int persist_enabled_on_companion(struct usb_device *udev, void *unused) { return !udev->maxchild && udev->persist_enabled && -- cgit From 3b0a6d1a1b3335fde9cbbc659568ed619b07d24a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 4 Feb 2016 14:02:45 -0600 Subject: PCI/AER: Rename pci_ops_aer to aer_inj_pci_ops Rename pci_ops_aer to aer_inj_pci_ops pci_read_aer() to aer_inj_read_config() pci_write_aer() to aer_inj_write_config() This is more conventional and more informative. No functional change. Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 20db790465dd..148a301a6b3c 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -181,8 +181,8 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where, return target; } -static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 *val) +static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) { u32 *sim; struct aer_error *err; @@ -212,8 +212,8 @@ out: return ops->read(bus, devfn, where, size, val); } -static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) +static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) { u32 *sim; struct aer_error *err; @@ -247,9 +247,9 @@ out: return ops->write(bus, devfn, where, size, val); } -static struct pci_ops pci_ops_aer = { - .read = pci_read_aer, - .write = pci_write_aer, +static struct pci_ops aer_inj_pci_ops = { + .read = aer_inj_read_config, + .write = aer_inj_write_config, }; static void pci_bus_ops_init(struct pci_bus_ops *bus_ops, @@ -270,9 +270,9 @@ static int pci_bus_set_aer_ops(struct pci_bus *bus) bus_ops = kmalloc(sizeof(*bus_ops), GFP_KERNEL); if (!bus_ops) return -ENOMEM; - ops = pci_bus_set_ops(bus, &pci_ops_aer); + ops = pci_bus_set_ops(bus, &aer_inj_pci_ops); spin_lock_irqsave(&inject_lock, flags); - if (ops == &pci_ops_aer) + if (ops == &aer_inj_pci_ops) goto out; pci_bus_ops_init(bus_ops, bus, ops); list_add(&bus_ops->list, &pci_bus_ops_list); -- cgit From 7e8fbdc628760857369af05636ed4ddc4fc8569b Mon Sep 17 00:00:00 2001 From: David Daney Date: Tue, 22 Dec 2015 13:44:51 -0800 Subject: PCI/AER: Restore pci_ops pointer while calling original pci_ops The aer_inject module intercepts config space accesses by replacing the bus->ops pointer. If it forwards accesses to the original pci_ops, and those original ops use bus->ops, they see the aer_pci_ops instead of their own pci_ops, which can cause a crash. For example, pci_generic_config_read() uses the bus->ops->map_bus pointer. If bus->ops is set to aer_pci_ops, which doesn't supply .map_bus, pci_generic_config_read() will dereference an invalid pointer and cause a crash. Temporarily restore the original bus->ops pointer while calling ops->read() or ops->write(). Callers of these functions already hold pci_lock, which prevents other users of bus->ops until we're finished. [bhelgaas: changelog] Signed-off-by: David Daney Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 148a301a6b3c..79a5e112711a 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -188,7 +188,9 @@ static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn, struct aer_error *err; unsigned long flags; struct pci_ops *ops; + struct pci_ops *my_ops; int domain; + int rv; spin_lock_irqsave(&inject_lock, flags); if (size != sizeof(u32)) @@ -208,8 +210,19 @@ static int aer_inj_read_config(struct pci_bus *bus, unsigned int devfn, } out: ops = __find_pci_bus_ops(bus); + /* + * pci_lock must already be held, so we can directly + * manipulate bus->ops. Many config access functions, + * including pci_generic_config_read() require the original + * bus->ops be installed to function, so temporarily put them + * back. + */ + my_ops = bus->ops; + bus->ops = ops; + rv = ops->read(bus, devfn, where, size, val); + bus->ops = my_ops; spin_unlock_irqrestore(&inject_lock, flags); - return ops->read(bus, devfn, where, size, val); + return rv; } static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, @@ -220,7 +233,9 @@ static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, unsigned long flags; int rw1cs; struct pci_ops *ops; + struct pci_ops *my_ops; int domain; + int rv; spin_lock_irqsave(&inject_lock, flags); if (size != sizeof(u32)) @@ -243,8 +258,19 @@ static int aer_inj_write_config(struct pci_bus *bus, unsigned int devfn, } out: ops = __find_pci_bus_ops(bus); + /* + * pci_lock must already be held, so we can directly + * manipulate bus->ops. Many config access functions, + * including pci_generic_config_write() require the original + * bus->ops be installed to function, so temporarily put them + * back. + */ + my_ops = bus->ops; + bus->ops = ops; + rv = ops->write(bus, devfn, where, size, val); + bus->ops = my_ops; spin_unlock_irqrestore(&inject_lock, flags); - return ops->write(bus, devfn, where, size, val); + return rv; } static struct pci_ops aer_inj_pci_ops = { -- cgit From 0e6053dc6e7a42c8ba9ce6e81adb3350c7df4bc8 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 22 Jan 2016 22:50:19 +0800 Subject: PCI/AER: Use list_first_entry_or_null() to simplify code Use list_first_entry_or_null() instead of list_empty() + list_entry() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 79a5e112711a..e2760a39a98a 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -124,16 +124,13 @@ static struct pci_ops *__find_pci_bus_ops(struct pci_bus *bus) static struct pci_bus_ops *pci_bus_ops_pop(void) { unsigned long flags; - struct pci_bus_ops *bus_ops = NULL; + struct pci_bus_ops *bus_ops; spin_lock_irqsave(&inject_lock, flags); - if (list_empty(&pci_bus_ops_list)) - bus_ops = NULL; - else { - struct list_head *lh = pci_bus_ops_list.next; - list_del(lh); - bus_ops = list_entry(lh, struct pci_bus_ops, list); - } + bus_ops = list_first_entry_or_null(&pci_bus_ops_list, + struct pci_bus_ops, list); + if (bus_ops) + list_del(&bus_ops->list); spin_unlock_irqrestore(&inject_lock, flags); return bus_ops; } -- cgit From b404bcfbf035413dcce539c8ba2c9986d220d8ed Mon Sep 17 00:00:00 2001 From: Manish Jaggi Date: Sat, 30 Jan 2016 01:33:58 +0530 Subject: PCI: Add ACS quirk for all Cavium devices Cavium devices matching this quirk do not perform peer-to-peer with other functions, allowing masking out these bits as if they were unimplemented in the ACS capability. Signed-off-by: Manish Jaggi Signed-off-by: Bjorn Helgaas Acked-by: Tirumalesh Chalamarla --- drivers/pci/quirks.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0575a1e026b4..85fa6a2a6dd2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3832,6 +3832,19 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags) #endif } +static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags) +{ + /* + * Cavium devices matching this quirk do not perform peer-to-peer + * with other functions, allowing masking out these bits as if they + * were unimplemented in the ACS capability. + */ + acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR | + PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT); + + return acs_flags ? 0 : 1; +} + /* * Many Intel PCH root ports do provide ACS-like features to disable peer * transactions and validate bus numbers in requests, but do not provide an @@ -3984,6 +3997,8 @@ static const struct pci_dev_acs_enabled { { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */ { 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */ + /* Cavium ThunderX */ + { PCI_VENDOR_ID_CAVIUM, PCI_ANY_ID, pci_quirk_cavium_acs }, { 0 } }; -- cgit From 7cdffeb534360609d57a39403ee951e08dcffbe7 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:37 -0300 Subject: rtc: max77686: Fix max77686_rtc_read_alarm() return value The function is always returning zero even in case of failures since the ret value was not propagated to the callers. Fix the error path. Reported-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Acked-by: Laxman Dewangan Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 7184a0eda793..6653c3d11b66 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -235,7 +235,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) out: mutex_unlock(&info->lock); - return 0; + return ret; } static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) -- cgit From 862f9453bd1494f10b059076a3c97c3b90d248aa Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:38 -0300 Subject: rtc: max77686: Use ARRAY_SIZE() instead of current array length It is better to use the ARRAY_SIZE() macro instead of the array length to avoid bugs if the array is later changed and the length not updated. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Acked-by: Laxman Dewangan Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 6653c3d11b66..d84a50c9f7f7 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -149,7 +149,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, RTC_NR_TIME); + MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); goto out; @@ -177,7 +177,7 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) mutex_lock(&info->lock); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, RTC_NR_TIME); + MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, ret); @@ -205,7 +205,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", __func__, __LINE__, ret); @@ -215,7 +215,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); alrm->enabled = 0; - for (i = 0; i < RTC_NR_TIME; i++) { + for (i = 0; i < ARRAY_SIZE(data); i++) { if (data[i] & ALARM_ENABLE_MASK) { alrm->enabled = 1; break; @@ -252,7 +252,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -261,11 +261,11 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); - for (i = 0; i < RTC_NR_TIME; i++) + for (i = 0; i < ARRAY_SIZE(data); i++) data[i] &= ~ALARM_ENABLE_MASK; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -291,7 +291,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -312,7 +312,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -341,7 +341,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, RTC_NR_TIME); + MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", @@ -406,7 +406,8 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) info->rtc_24hr_mode = 1; - ret = regmap_bulk_write(info->max77686->rtc_regmap, MAX77686_RTC_CONTROLM, data, 2); + ret = regmap_bulk_write(info->max77686->rtc_regmap, + MAX77686_RTC_CONTROLM, data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", __func__, ret); -- cgit From 5981804b83650de558c40769fb06f76fab31724e Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:39 -0300 Subject: rtc: max77686: Use usleep_range() instead of msleep() Documentation/timers/timers-howto.txt suggest to use usleep_range() instead of msleep() for small msec (1ms - 20ms) since msleep() will often sleep for 20ms for any value in that range. This is fine in this case since 16ms is the _minimum_ delay required by max77686 for an RTC update but by using usleep_range() instead of msleep(), the driver can support other RTC IP blocks with a shorter minimum delay (i.e: in the range of usecs instead of msecs). Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Tested-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d84a50c9f7f7..025a17a95da3 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -41,7 +41,7 @@ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) -#define MAX77686_RTC_UPDATE_DELAY 16 +#define MAX77686_RTC_UPDATE_DELAY 16000 enum { RTC_SEC = 0, @@ -130,7 +130,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, __func__, ret, data); else { /* Minimum 16ms delay required before RTC update. */ - msleep(MAX77686_RTC_UPDATE_DELAY); + usleep_range(MAX77686_RTC_UPDATE_DELAY, + MAX77686_RTC_UPDATE_DELAY * 2); } return ret; -- cgit From 01ea01b35120663a8ec727566e757ea6efdbd2d1 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:40 -0300 Subject: rtc: max77686: Use a driver data struct instead hard-coded values The driver has some hard-coded values such as the minimum delay needed before a RTC update or the mask used for the sec/min/hour/etc registers. Use a data structure that contains these values and pass as driver data using the platform device ID table for each device. This allows to make the driver's ops callbacks more generic so other RTC that are similar but don't have the same values can also be supported. Signed-off-by: Javier Martinez Canillas Acked-by: Laxman Dewangan Reviewed-by: Andi Shyti Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 025a17a95da3..8c4ca35029c3 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -41,8 +41,6 @@ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) -#define MAX77686_RTC_UPDATE_DELAY 16000 - enum { RTC_SEC = 0, RTC_MIN, @@ -54,6 +52,13 @@ enum { RTC_NR_TIME }; +struct max77686_rtc_driver_data { + /* Minimum usecs needed for a RTC update */ + unsigned long delay; + /* Mask used to read RTC registers value */ + u8 mask; +}; + struct max77686_rtc_info { struct device *dev; struct max77686_dev *max77686; @@ -63,6 +68,8 @@ struct max77686_rtc_info { struct regmap *regmap; + const struct max77686_rtc_driver_data *drv_data; + int virq; int rtc_24hr_mode; }; @@ -72,12 +79,19 @@ enum MAX77686_RTC_OP { MAX77686_RTC_READ, }; +static const struct max77686_rtc_driver_data max77686_drv_data = { + .delay = 16000, + .mask = 0x7f, +}; + static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, - int rtc_24hr_mode) + struct max77686_rtc_info *info) { - tm->tm_sec = data[RTC_SEC] & 0x7f; - tm->tm_min = data[RTC_MIN] & 0x7f; - if (rtc_24hr_mode) + u8 mask = info->drv_data->mask; + + tm->tm_sec = data[RTC_SEC] & mask; + tm->tm_min = data[RTC_MIN] & mask; + if (info->rtc_24hr_mode) tm->tm_hour = data[RTC_HOUR] & 0x1f; else { tm->tm_hour = data[RTC_HOUR] & 0x0f; @@ -86,10 +100,10 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, } /* Only a single bit is set in data[], so fls() would be equivalent */ - tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1; + tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1; tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; - tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; + tm->tm_year = (data[RTC_YEAR] & mask) + 100; tm->tm_yday = 0; tm->tm_isdst = 0; } @@ -117,6 +131,7 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, { int ret; unsigned int data; + unsigned long delay = info->drv_data->delay; if (op == MAX77686_RTC_WRITE) data = 1 << RTC_UDR_SHIFT; @@ -129,9 +144,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", __func__, ret, data); else { - /* Minimum 16ms delay required before RTC update. */ - usleep_range(MAX77686_RTC_UPDATE_DELAY, - MAX77686_RTC_UPDATE_DELAY * 2); + /* Minimum delay required before RTC update. */ + usleep_range(delay, delay * 2); } return ret; @@ -156,7 +170,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) goto out; } - max77686_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, tm, info); ret = rtc_valid_tm(tm); @@ -213,7 +227,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; } - max77686_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, &alrm->time, info); alrm->enabled = 0; for (i = 0; i < ARRAY_SIZE(data); i++) { @@ -260,7 +274,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) goto out; } - max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, &tm, info); for (i = 0; i < ARRAY_SIZE(data); i++) data[i] &= ~ALARM_ENABLE_MASK; @@ -299,7 +313,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) goto out; } - max77686_rtc_data_to_tm(data, &tm, info->rtc_24hr_mode); + max77686_rtc_data_to_tm(data, &tm, info); data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); @@ -307,7 +321,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; if (data[RTC_MONTH] & 0xf) data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); - if (data[RTC_YEAR] & 0x7f) + if (data[RTC_YEAR] & info->drv_data->mask) data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); if (data[RTC_DATE] & 0x1f) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); @@ -423,6 +437,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) { struct max77686_dev *max77686 = dev_get_drvdata(pdev->dev.parent); struct max77686_rtc_info *info; + const struct platform_device_id *id = platform_get_device_id(pdev); int ret; dev_info(&pdev->dev, "%s\n", __func__); @@ -436,6 +451,8 @@ static int max77686_rtc_probe(struct platform_device *pdev) info->dev = &pdev->dev; info->max77686 = max77686; info->rtc = max77686->rtc; + info->drv_data = (const struct max77686_rtc_driver_data *) + id->driver_data; platform_set_drvdata(pdev, info); @@ -510,7 +527,7 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops, max77686_rtc_suspend, max77686_rtc_resume); static const struct platform_device_id rtc_id[] = { - { "max77686-rtc", 0 }, + { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, }, {}, }; MODULE_DEVICE_TABLE(platform, rtc_id); -- cgit From 90a5698a86ba968e6fbe2e03cfab9ffc18a17186 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:41 -0300 Subject: rtc: max77686: Add an indirection level to access RTC registers The max77686 driver is generic enough that can be used for other Maxim RTC IP blocks but these might not have the same registers layout so instead of accessing the registers directly, add a map to translate offsets to the real registers addresses for each IP. Signed-off-by: Javier Martinez Canillas Acked-by: Laxman Dewangan Tested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 90 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 10 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 8c4ca35029c3..1f501b6fc314 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -57,6 +57,8 @@ struct max77686_rtc_driver_data { unsigned long delay; /* Mask used to read RTC registers value */ u8 mask; + /* Registers offset to I2C addresses map */ + const unsigned int *map; }; struct max77686_rtc_info { @@ -79,9 +81,69 @@ enum MAX77686_RTC_OP { MAX77686_RTC_READ, }; +/* These are not registers but just offsets that are mapped to addresses */ +enum max77686_rtc_reg_offset { + REG_RTC_CONTROLM = 0, + REG_RTC_CONTROL, + REG_RTC_UPDATE0, + REG_WTSR_SMPL_CNTL, + REG_RTC_SEC, + REG_RTC_MIN, + REG_RTC_HOUR, + REG_RTC_WEEKDAY, + REG_RTC_MONTH, + REG_RTC_YEAR, + REG_RTC_DATE, + REG_ALARM1_SEC, + REG_ALARM1_MIN, + REG_ALARM1_HOUR, + REG_ALARM1_WEEKDAY, + REG_ALARM1_MONTH, + REG_ALARM1_YEAR, + REG_ALARM1_DATE, + REG_ALARM2_SEC, + REG_ALARM2_MIN, + REG_ALARM2_HOUR, + REG_ALARM2_WEEKDAY, + REG_ALARM2_MONTH, + REG_ALARM2_YEAR, + REG_ALARM2_DATE, + REG_RTC_END, +}; + +/* Maps RTC registers offset to the MAX77686 register addresses */ +static const unsigned int max77686_map[REG_RTC_END] = { + [REG_RTC_CONTROLM] = MAX77686_RTC_CONTROLM, + [REG_RTC_CONTROL] = MAX77686_RTC_CONTROL, + [REG_RTC_UPDATE0] = MAX77686_RTC_UPDATE0, + [REG_WTSR_SMPL_CNTL] = MAX77686_WTSR_SMPL_CNTL, + [REG_RTC_SEC] = MAX77686_RTC_SEC, + [REG_RTC_MIN] = MAX77686_RTC_MIN, + [REG_RTC_HOUR] = MAX77686_RTC_HOUR, + [REG_RTC_WEEKDAY] = MAX77686_RTC_WEEKDAY, + [REG_RTC_MONTH] = MAX77686_RTC_MONTH, + [REG_RTC_YEAR] = MAX77686_RTC_YEAR, + [REG_RTC_DATE] = MAX77686_RTC_DATE, + [REG_ALARM1_SEC] = MAX77686_ALARM1_SEC, + [REG_ALARM1_MIN] = MAX77686_ALARM1_MIN, + [REG_ALARM1_HOUR] = MAX77686_ALARM1_HOUR, + [REG_ALARM1_WEEKDAY] = MAX77686_ALARM1_WEEKDAY, + [REG_ALARM1_MONTH] = MAX77686_ALARM1_MONTH, + [REG_ALARM1_YEAR] = MAX77686_ALARM1_YEAR, + [REG_ALARM1_DATE] = MAX77686_ALARM1_DATE, + [REG_ALARM2_SEC] = MAX77686_ALARM2_SEC, + [REG_ALARM2_MIN] = MAX77686_ALARM2_MIN, + [REG_ALARM2_HOUR] = MAX77686_ALARM2_HOUR, + [REG_ALARM2_WEEKDAY] = MAX77686_ALARM2_WEEKDAY, + [REG_ALARM2_MONTH] = MAX77686_ALARM2_MONTH, + [REG_ALARM2_YEAR] = MAX77686_ALARM2_YEAR, + [REG_ALARM2_DATE] = MAX77686_ALARM2_DATE, +}; + static const struct max77686_rtc_driver_data max77686_drv_data = { .delay = 16000, .mask = 0x7f, + .map = max77686_map, }; static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, @@ -139,7 +201,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, data = 1 << RTC_RBUDR_SHIFT; ret = regmap_update_bits(info->max77686->rtc_regmap, - MAX77686_RTC_UPDATE0, data, data); + info->drv_data->map[REG_RTC_UPDATE0], + data, data); if (ret < 0) dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", __func__, ret, data); @@ -164,7 +227,8 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_RTC_SEC], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); goto out; @@ -192,7 +256,8 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) mutex_lock(&info->lock); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_RTC_SEC, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_RTC_SEC], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, ret); @@ -211,6 +276,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) struct max77686_rtc_info *info = dev_get_drvdata(dev); u8 data[RTC_NR_TIME]; unsigned int val; + const unsigned int *map = info->drv_data->map; int i, ret; mutex_lock(&info->lock); @@ -220,7 +286,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", __func__, __LINE__, ret); @@ -258,6 +324,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) u8 data[RTC_NR_TIME]; int ret, i; struct rtc_time tm; + const unsigned int *map = info->drv_data->map; if (!mutex_is_locked(&info->lock)) dev_warn(info->dev, "%s: should have mutex locked\n", __func__); @@ -267,7 +334,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -280,7 +347,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) data[i] &= ~ALARM_ENABLE_MASK; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -297,6 +364,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) u8 data[RTC_NR_TIME]; int ret; struct rtc_time tm; + const unsigned int *map = info->drv_data->map; if (!mutex_is_locked(&info->lock)) dev_warn(info->dev, "%s: should have mutex locked\n", __func__); @@ -306,7 +374,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) goto out; ret = regmap_bulk_read(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); @@ -327,7 +395,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -356,7 +424,8 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) goto out; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_ALARM1_SEC, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_ALARM1_SEC], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", @@ -422,7 +491,8 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) info->rtc_24hr_mode = 1; ret = regmap_bulk_write(info->max77686->rtc_regmap, - MAX77686_RTC_CONTROLM, data, ARRAY_SIZE(data)); + info->drv_data->map[REG_RTC_CONTROLM], + data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", __func__, ret); -- cgit From f903129b86070befa996d7bdc53d0b82b1fa09d3 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:42 -0300 Subject: rtc: max77686: Add max77802 support The MAX77686 and MAX77802 RTC IP blocks are very similar with only these differences: 0) The RTC registers layout and addresses are different. 1) The MAX77686 use 1 bit of the sec/min/hour/etc registers as the alarm enable while MAX77802 has a separate register for that. 2) The MAX77686 RTCYEAR register valid values range is 0..99 while for MAX77802 is 0..199. 3) The MAX77686 has a separate I2C address for the RTC registers while the MAX77802 uses the same I2C address as the PMIC regs. 5) The minimum delay before a RTC update (16 msecs vs 200 usecs). There are separate drivers for MAX77686 and MAX77802 RTC IP blocks but the differences are not that big so the driver can be extended to support both instead of duplicating a lot of code in 2 drivers. Suggested-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Acked-by: Laxman Dewangan Tested-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Reviewed-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 196 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 156 insertions(+), 40 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 1f501b6fc314..a9a4ee0f0f41 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -1,5 +1,5 @@ /* - * RTC driver for Maxim MAX77686 + * RTC driver for Maxim MAX77686 and MAX77802 * * Copyright (C) 2012 Samsung Electronics Co.Ltd * @@ -41,6 +41,15 @@ #define ALARM_ENABLE_SHIFT 7 #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) +#define REG_RTC_NONE 0xdeadbeef + +/* + * MAX77802 has separate register (RTCAE1) for alarm enable instead + * using 1 bit from registers RTC{SEC,MIN,HOUR,DAY,MONTH,YEAR,DATE} + * as in done in MAX77686. + */ +#define MAX77802_ALARM_ENABLE_VALUE 0x77 + enum { RTC_SEC = 0, RTC_MIN, @@ -59,6 +68,10 @@ struct max77686_rtc_driver_data { u8 mask; /* Registers offset to I2C addresses map */ const unsigned int *map; + /* Has a separate alarm enable register? */ + bool alarm_enable_reg; + /* Has a separate I2C regmap for the RTC? */ + bool separate_i2c_addr; }; struct max77686_rtc_info { @@ -108,6 +121,7 @@ enum max77686_rtc_reg_offset { REG_ALARM2_MONTH, REG_ALARM2_YEAR, REG_ALARM2_DATE, + REG_RTC_AE1, REG_RTC_END, }; @@ -138,12 +152,52 @@ static const unsigned int max77686_map[REG_RTC_END] = { [REG_ALARM2_MONTH] = MAX77686_ALARM2_MONTH, [REG_ALARM2_YEAR] = MAX77686_ALARM2_YEAR, [REG_ALARM2_DATE] = MAX77686_ALARM2_DATE, + [REG_RTC_AE1] = REG_RTC_NONE, }; static const struct max77686_rtc_driver_data max77686_drv_data = { .delay = 16000, .mask = 0x7f, .map = max77686_map, + .alarm_enable_reg = false, + .separate_i2c_addr = true, +}; + +static const unsigned int max77802_map[REG_RTC_END] = { + [REG_RTC_CONTROLM] = MAX77802_RTC_CONTROLM, + [REG_RTC_CONTROL] = MAX77802_RTC_CONTROL, + [REG_RTC_UPDATE0] = MAX77802_RTC_UPDATE0, + [REG_WTSR_SMPL_CNTL] = MAX77802_WTSR_SMPL_CNTL, + [REG_RTC_SEC] = MAX77802_RTC_SEC, + [REG_RTC_MIN] = MAX77802_RTC_MIN, + [REG_RTC_HOUR] = MAX77802_RTC_HOUR, + [REG_RTC_WEEKDAY] = MAX77802_RTC_WEEKDAY, + [REG_RTC_MONTH] = MAX77802_RTC_MONTH, + [REG_RTC_YEAR] = MAX77802_RTC_YEAR, + [REG_RTC_DATE] = MAX77802_RTC_DATE, + [REG_ALARM1_SEC] = MAX77802_ALARM1_SEC, + [REG_ALARM1_MIN] = MAX77802_ALARM1_MIN, + [REG_ALARM1_HOUR] = MAX77802_ALARM1_HOUR, + [REG_ALARM1_WEEKDAY] = MAX77802_ALARM1_WEEKDAY, + [REG_ALARM1_MONTH] = MAX77802_ALARM1_MONTH, + [REG_ALARM1_YEAR] = MAX77802_ALARM1_YEAR, + [REG_ALARM1_DATE] = MAX77802_ALARM1_DATE, + [REG_ALARM2_SEC] = MAX77802_ALARM2_SEC, + [REG_ALARM2_MIN] = MAX77802_ALARM2_MIN, + [REG_ALARM2_HOUR] = MAX77802_ALARM2_HOUR, + [REG_ALARM2_WEEKDAY] = MAX77802_ALARM2_WEEKDAY, + [REG_ALARM2_MONTH] = MAX77802_ALARM2_MONTH, + [REG_ALARM2_YEAR] = MAX77802_ALARM2_YEAR, + [REG_ALARM2_DATE] = MAX77802_ALARM2_DATE, + [REG_RTC_AE1] = MAX77802_RTC_AE1, +}; + +static const struct max77686_rtc_driver_data max77802_drv_data = { + .delay = 200, + .mask = 0xff, + .map = max77802_map, + .alarm_enable_reg = true, + .separate_i2c_addr = false, }; static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, @@ -165,12 +219,20 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, tm->tm_wday = ffs(data[RTC_WEEKDAY] & mask) - 1; tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; - tm->tm_year = (data[RTC_YEAR] & mask) + 100; + tm->tm_year = data[RTC_YEAR] & mask; tm->tm_yday = 0; tm->tm_isdst = 0; + + /* + * MAX77686 uses 1 bit from sec/min/hour/etc RTC registers and the + * year values are just 0..99 so add 100 to support up to 2099. + */ + if (!info->drv_data->alarm_enable_reg) + tm->tm_year += 100; } -static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) +static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data, + struct max77686_rtc_info *info) { data[RTC_SEC] = tm->tm_sec; data[RTC_MIN] = tm->tm_min; @@ -178,6 +240,12 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) data[RTC_WEEKDAY] = 1 << tm->tm_wday; data[RTC_DATE] = tm->tm_mday; data[RTC_MONTH] = tm->tm_mon + 1; + + if (info->drv_data->alarm_enable_reg) { + data[RTC_YEAR] = tm->tm_year; + return 0; + } + data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { @@ -185,6 +253,7 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data) 1900 + tm->tm_year); return -EINVAL; } + return 0; } @@ -249,7 +318,7 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) u8 data[RTC_NR_TIME]; int ret; - ret = max77686_rtc_tm_to_data(tm, data); + ret = max77686_rtc_tm_to_data(tm, data, info); if (ret < 0) return ret; @@ -296,10 +365,31 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) max77686_rtc_data_to_tm(data, &alrm->time, info); alrm->enabled = 0; - for (i = 0; i < ARRAY_SIZE(data); i++) { - if (data[i] & ALARM_ENABLE_MASK) { + + if (info->drv_data->alarm_enable_reg) { + if (map[REG_RTC_AE1] == REG_RTC_NONE) { + ret = -EINVAL; + dev_err(info->dev, + "alarm enable register not set(%d)\n", ret); + goto out; + } + + ret = regmap_read(info->max77686->regmap, + map[REG_RTC_AE1], &val); + if (ret < 0) { + dev_err(info->dev, + "fail to read alarm enable(%d)\n", ret); + goto out; + } + + if (val) alrm->enabled = 1; - break; + } else { + for (i = 0; i < ARRAY_SIZE(data); i++) { + if (data[i] & ALARM_ENABLE_MASK) { + alrm->enabled = 1; + break; + } } } @@ -333,21 +423,35 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) if (ret < 0) goto out; - ret = regmap_bulk_read(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); - if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", + if (info->drv_data->alarm_enable_reg) { + if (map[REG_RTC_AE1] == REG_RTC_NONE) { + ret = -EINVAL; + dev_err(info->dev, + "alarm enable register not set(%d)\n", ret); + goto out; + } + + ret = regmap_write(info->max77686->regmap, map[REG_RTC_AE1], 0); + } else { + ret = regmap_bulk_read(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + if (ret < 0) { + dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); - goto out; - } + goto out; + } - max77686_rtc_data_to_tm(data, &tm, info); + max77686_rtc_data_to_tm(data, &tm, info); - for (i = 0; i < ARRAY_SIZE(data); i++) - data[i] &= ~ALARM_ENABLE_MASK; + for (i = 0; i < ARRAY_SIZE(data); i++) + data[i] &= ~ALARM_ENABLE_MASK; + + ret = regmap_bulk_write(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + } - ret = regmap_bulk_write(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -373,29 +477,37 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) if (ret < 0) goto out; - ret = regmap_bulk_read(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); - if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", + if (info->drv_data->alarm_enable_reg) { + ret = regmap_write(info->max77686->regmap, map[REG_RTC_AE1], + MAX77802_ALARM_ENABLE_VALUE); + } else { + ret = regmap_bulk_read(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + if (ret < 0) { + dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", __func__, ret); - goto out; - } - - max77686_rtc_data_to_tm(data, &tm, info); + goto out; + } - data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); - data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); - data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); - data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; - if (data[RTC_MONTH] & 0xf) - data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); - if (data[RTC_YEAR] & info->drv_data->mask) - data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); - if (data[RTC_DATE] & 0x1f) - data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); + max77686_rtc_data_to_tm(data, &tm, info); + + data[RTC_SEC] |= (1 << ALARM_ENABLE_SHIFT); + data[RTC_MIN] |= (1 << ALARM_ENABLE_SHIFT); + data[RTC_HOUR] |= (1 << ALARM_ENABLE_SHIFT); + data[RTC_WEEKDAY] &= ~ALARM_ENABLE_MASK; + if (data[RTC_MONTH] & 0xf) + data[RTC_MONTH] |= (1 << ALARM_ENABLE_SHIFT); + if (data[RTC_YEAR] & info->drv_data->mask) + data[RTC_YEAR] |= (1 << ALARM_ENABLE_SHIFT); + if (data[RTC_DATE] & 0x1f) + data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT); + + ret = regmap_bulk_write(info->max77686->rtc_regmap, + map[REG_ALARM1_SEC], data, + ARRAY_SIZE(data)); + } - ret = regmap_bulk_write(info->max77686->rtc_regmap, - map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", __func__, ret); @@ -413,7 +525,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) u8 data[RTC_NR_TIME]; int ret; - ret = max77686_rtc_tm_to_data(&alrm->time, data); + ret = max77686_rtc_tm_to_data(&alrm->time, data, info); if (ret < 0) return ret; @@ -524,6 +636,9 @@ static int max77686_rtc_probe(struct platform_device *pdev) info->drv_data = (const struct max77686_rtc_driver_data *) id->driver_data; + if (!info->drv_data->separate_i2c_addr) + info->max77686->rtc_regmap = info->max77686->regmap; + platform_set_drvdata(pdev, info); ret = max77686_rtc_init_reg(info); @@ -535,7 +650,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", + info->rtc_dev = devm_rtc_device_register(&pdev->dev, id->name, &max77686_rtc_ops, THIS_MODULE); if (IS_ERR(info->rtc_dev)) { @@ -598,6 +713,7 @@ static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops, static const struct platform_device_id rtc_id[] = { { "max77686-rtc", .driver_data = (kernel_ulong_t)&max77686_drv_data, }, + { "max77802-rtc", .driver_data = (kernel_ulong_t)&max77802_drv_data, }, {}, }; MODULE_DEVICE_TABLE(platform, rtc_id); -- cgit From 1e5813bded3c6702841549ac2533680f410aea43 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:43 -0300 Subject: rtc: max77686: Fix unsupported year message The max77686 RTC only supports a range of 99 years so instead of using year 1900 as the base, the year 2000 is used. This means that 1900 to 1999 are unsupported years. The driver was printing a warning for those values but was returning a error so for consistency, print an error message instead and don't say that a year 2000 is assumed, since the year is not set. Also, it is better to use dev_* log functions instead of pr_* to print information about the device in the kernel log in a standardized way. This also allows to remove the local pr_fmt() defined macro. Suggested-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Reviewed-by: Andi Shyti Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index a9a4ee0f0f41..bbb06dd2ee35 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -12,8 +12,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -249,7 +247,7 @@ static int max77686_rtc_tm_to_data(struct rtc_time *tm, u8 *data, data[RTC_YEAR] = tm->tm_year > 100 ? (tm->tm_year - 100) : 0; if (tm->tm_year < 100) { - pr_warn("RTC cannot handle the year %d. Assume it's 2000.\n", + dev_err(info->dev, "RTC cannot handle the year %d.\n", 1900 + tm->tm_year); return -EINVAL; } -- cgit From fb166ba1d7f0a662f7332f4ff660a0d6f4d76915 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 4 Feb 2016 09:26:35 +0900 Subject: rtc: max77686: Properly handle regmap_irq_get_virq() error code The regmap_irq_get_virq() can return 0 or -EINVAL in error conditions but driver checked only for value of 0. This could lead to a cast of -EINVAL to an unsigned int used as a interrupt number for devm_request_threaded_irq(). Although this is not yet fatal (devm_request_threaded_irq() will just fail with -EINVAL) but might be a misleading when diagnosing errors. Signed-off-by: Krzysztof Kozlowski Fixes: 6f1c1e71d933 ("mfd: max77686: Convert to use regmap_irq") Reviewed-by: Javier Martinez Canillas Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index bbb06dd2ee35..d2d1176a1f60 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -667,7 +667,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, MAX77686_RTCIRQ_RTCA1); - if (!info->virq) { + if (info->virq <= 0) { ret = -ENXIO; goto err_rtc; } -- cgit From cd0e7c1e54af2dd4d275177cb5dea0ced398e5ef Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Wed, 27 Jan 2016 00:36:44 -0300 Subject: rtc: Remove Maxim 77802 driver The max77686 RTC driver now supports the max77802 RTC as well so there's no need to have a separate driver anymore. Signed-off-by: Javier Martinez Canillas Reviewed-by: Krzysztof Kozlowski Acked-by: Laxman Dewangan Reviewed-by: Andi Shyti Tested-by: Krzysztof Kozlowski Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 10 - drivers/rtc/Makefile | 1 - drivers/rtc/rtc-max77802.c | 502 --------------------------------------------- 3 files changed, 513 deletions(-) delete mode 100644 drivers/rtc/rtc-max77802.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 376322f71fd5..ef456d3cf265 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -335,16 +335,6 @@ config RTC_DRV_RK808 This driver can also be built as a module. If so, the module will be called rk808-rtc. -config RTC_DRV_MAX77802 - tristate "Maxim 77802 RTC" - depends on MFD_MAX77686 - help - If you say yes here you will get support for the - RTC of Maxim MAX77802 PMIC. - - This driver can also be built as a module. If so, the module - will be called rtc-max77802. - config RTC_DRV_RS5C372 tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 62d61b26ca7e..ed4519efa3ca 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o -obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o diff --git a/drivers/rtc/rtc-max77802.c b/drivers/rtc/rtc-max77802.c deleted file mode 100644 index 82ffcc5a5345..000000000000 --- a/drivers/rtc/rtc-max77802.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * RTC driver for Maxim MAX77802 - * - * Copyright (C) 2013 Google, Inc - * - * Copyright (C) 2012 Samsung Electronics Co.Ltd - * - * based on rtc-max8997.c - * - * 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 -#include - -/* RTC Control Register */ -#define BCD_EN_SHIFT 0 -#define BCD_EN_MASK (1 << BCD_EN_SHIFT) -#define MODEL24_SHIFT 1 -#define MODEL24_MASK (1 << MODEL24_SHIFT) -/* RTC Update Register1 */ -#define RTC_UDR_SHIFT 0 -#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) -#define RTC_RBUDR_SHIFT 4 -#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) -/* RTC Hour register */ -#define HOUR_PM_SHIFT 6 -#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) -/* RTC Alarm Enable */ -#define ALARM_ENABLE_SHIFT 7 -#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) - -/* For the RTCAE1 register, we write this value to enable the alarm */ -#define ALARM_ENABLE_VALUE 0x77 - -#define MAX77802_RTC_UPDATE_DELAY_US 200 - -enum { - RTC_SEC = 0, - RTC_MIN, - RTC_HOUR, - RTC_WEEKDAY, - RTC_MONTH, - RTC_YEAR, - RTC_DATE, - RTC_NR_TIME -}; - -struct max77802_rtc_info { - struct device *dev; - struct max77686_dev *max77802; - struct i2c_client *rtc; - struct rtc_device *rtc_dev; - struct mutex lock; - - struct regmap *regmap; - - int virq; - int rtc_24hr_mode; -}; - -enum MAX77802_RTC_OP { - MAX77802_RTC_WRITE, - MAX77802_RTC_READ, -}; - -static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm, - int rtc_24hr_mode) -{ - tm->tm_sec = data[RTC_SEC] & 0xff; - tm->tm_min = data[RTC_MIN] & 0xff; - if (rtc_24hr_mode) - tm->tm_hour = data[RTC_HOUR] & 0x1f; - else { - tm->tm_hour = data[RTC_HOUR] & 0x0f; - if (data[RTC_HOUR] & HOUR_PM_MASK) - tm->tm_hour += 12; - } - - /* Only a single bit is set in data[], so fls() would be equivalent */ - tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1; - tm->tm_mday = data[RTC_DATE] & 0x1f; - tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; - - tm->tm_year = data[RTC_YEAR] & 0xff; - tm->tm_yday = 0; - tm->tm_isdst = 0; -} - -static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data) -{ - data[RTC_SEC] = tm->tm_sec; - data[RTC_MIN] = tm->tm_min; - data[RTC_HOUR] = tm->tm_hour; - data[RTC_WEEKDAY] = 1 << tm->tm_wday; - data[RTC_DATE] = tm->tm_mday; - data[RTC_MONTH] = tm->tm_mon + 1; - data[RTC_YEAR] = tm->tm_year; - - return 0; -} - -static int max77802_rtc_update(struct max77802_rtc_info *info, - enum MAX77802_RTC_OP op) -{ - int ret; - unsigned int data; - - if (op == MAX77802_RTC_WRITE) - data = 1 << RTC_UDR_SHIFT; - else - data = 1 << RTC_RBUDR_SHIFT; - - ret = regmap_update_bits(info->max77802->regmap, - MAX77802_RTC_UPDATE0, data, data); - if (ret < 0) - dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", - __func__, ret, data); - else { - /* Minimum delay required before RTC update. */ - usleep_range(MAX77802_RTC_UPDATE_DELAY_US, - MAX77802_RTC_UPDATE_DELAY_US * 2); - } - - return ret; -} - -static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - int ret; - - mutex_lock(&info->lock); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_bulk_read(info->max77802->regmap, - MAX77802_RTC_SEC, data, RTC_NR_TIME); - if (ret < 0) { - dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, - ret); - goto out; - } - - max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode); - - ret = rtc_valid_tm(tm); - -out: - mutex_unlock(&info->lock); - return ret; -} - -static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - int ret; - - ret = max77802_rtc_tm_to_data(tm, data); - if (ret < 0) - return ret; - - mutex_lock(&info->lock); - - ret = regmap_bulk_write(info->max77802->regmap, - MAX77802_RTC_SEC, data, RTC_NR_TIME); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, - ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); - -out: - mutex_unlock(&info->lock); - return ret; -} - -static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - unsigned int val; - int ret; - - mutex_lock(&info->lock); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_bulk_read(info->max77802->regmap, - MAX77802_ALARM1_SEC, data, RTC_NR_TIME); - if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", - __func__, __LINE__, ret); - goto out; - } - - max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode); - - alrm->enabled = 0; - ret = regmap_read(info->max77802->regmap, - MAX77802_RTC_AE1, &val); - if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n", - __func__, __LINE__, ret); - goto out; - } - if (val) - alrm->enabled = 1; - - alrm->pending = 0; - ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val); - if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n", - __func__, __LINE__, ret); - goto out; - } - - if (val & (1 << 2)) /* RTCA1 */ - alrm->pending = 1; - -out: - mutex_unlock(&info->lock); - return 0; -} - -static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info) -{ - int ret; - - if (!mutex_is_locked(&info->lock)) - dev_warn(info->dev, "%s: should have mutex locked\n", __func__); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_write(info->max77802->regmap, - MAX77802_RTC_AE1, 0); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); -out: - return ret; -} - -static int max77802_rtc_start_alarm(struct max77802_rtc_info *info) -{ - int ret; - - if (!mutex_is_locked(&info->lock)) - dev_warn(info->dev, "%s: should have mutex locked\n", - __func__); - - ret = max77802_rtc_update(info, MAX77802_RTC_READ); - if (ret < 0) - goto out; - - ret = regmap_write(info->max77802->regmap, - MAX77802_RTC_AE1, - ALARM_ENABLE_VALUE); - - if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", - __func__, ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); -out: - return ret; -} - -static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - u8 data[RTC_NR_TIME]; - int ret; - - ret = max77802_rtc_tm_to_data(&alrm->time, data); - if (ret < 0) - return ret; - - mutex_lock(&info->lock); - - ret = max77802_rtc_stop_alarm(info); - if (ret < 0) - goto out; - - ret = regmap_bulk_write(info->max77802->regmap, - MAX77802_ALARM1_SEC, data, RTC_NR_TIME); - - if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); - goto out; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); - if (ret < 0) - goto out; - - if (alrm->enabled) - ret = max77802_rtc_start_alarm(info); -out: - mutex_unlock(&info->lock); - return ret; -} - -static int max77802_rtc_alarm_irq_enable(struct device *dev, - unsigned int enabled) -{ - struct max77802_rtc_info *info = dev_get_drvdata(dev); - int ret; - - mutex_lock(&info->lock); - if (enabled) - ret = max77802_rtc_start_alarm(info); - else - ret = max77802_rtc_stop_alarm(info); - mutex_unlock(&info->lock); - - return ret; -} - -static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data) -{ - struct max77802_rtc_info *info = data; - - dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq); - - rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); - - return IRQ_HANDLED; -} - -static const struct rtc_class_ops max77802_rtc_ops = { - .read_time = max77802_rtc_read_time, - .set_time = max77802_rtc_set_time, - .read_alarm = max77802_rtc_read_alarm, - .set_alarm = max77802_rtc_set_alarm, - .alarm_irq_enable = max77802_rtc_alarm_irq_enable, -}; - -static int max77802_rtc_init_reg(struct max77802_rtc_info *info) -{ - u8 data[2]; - int ret; - - max77802_rtc_update(info, MAX77802_RTC_READ); - - /* Set RTC control register : Binary mode, 24hour mdoe */ - data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); - data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT); - - info->rtc_24hr_mode = 1; - - ret = regmap_bulk_write(info->max77802->regmap, - MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data)); - if (ret < 0) { - dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", - __func__, ret); - return ret; - } - - ret = max77802_rtc_update(info, MAX77802_RTC_WRITE); - return ret; -} - -static int max77802_rtc_probe(struct platform_device *pdev) -{ - struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent); - struct max77802_rtc_info *info; - int ret; - - dev_dbg(&pdev->dev, "%s\n", __func__); - - info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info), - GFP_KERNEL); - if (!info) - return -ENOMEM; - - mutex_init(&info->lock); - info->dev = &pdev->dev; - info->max77802 = max77802; - info->rtc = max77802->i2c; - - platform_set_drvdata(pdev, info); - - ret = max77802_rtc_init_reg(info); - - if (ret < 0) { - dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret); - return ret; - } - - device_init_wakeup(&pdev->dev, 1); - - info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc", - &max77802_rtc_ops, THIS_MODULE); - - if (IS_ERR(info->rtc_dev)) { - ret = PTR_ERR(info->rtc_dev); - dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); - if (ret == 0) - ret = -EINVAL; - return ret; - } - - if (!max77802->rtc_irq_data) { - dev_err(&pdev->dev, "No RTC regmap IRQ chip\n"); - return -EINVAL; - } - - info->virq = regmap_irq_get_virq(max77802->rtc_irq_data, - MAX77686_RTCIRQ_RTCA1); - - if (info->virq <= 0) { - dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n", - MAX77686_RTCIRQ_RTCA1); - return -EINVAL; - } - - ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL, - max77802_rtc_alarm_irq, 0, "rtc-alarm1", - info); - if (ret < 0) - dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n", - info->virq, ret); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int max77802_rtc_suspend(struct device *dev) -{ - if (device_may_wakeup(dev)) { - struct max77802_rtc_info *info = dev_get_drvdata(dev); - - return enable_irq_wake(info->virq); - } - - return 0; -} - -static int max77802_rtc_resume(struct device *dev) -{ - if (device_may_wakeup(dev)) { - struct max77802_rtc_info *info = dev_get_drvdata(dev); - - return disable_irq_wake(info->virq); - } - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops, - max77802_rtc_suspend, max77802_rtc_resume); - -static const struct platform_device_id rtc_id[] = { - { "max77802-rtc", 0 }, - {}, -}; -MODULE_DEVICE_TABLE(platform, rtc_id); - -static struct platform_driver max77802_rtc_driver = { - .driver = { - .name = "max77802-rtc", - .pm = &max77802_rtc_pm_ops, - }, - .probe = max77802_rtc_probe, - .id_table = rtc_id, -}; - -module_platform_driver(max77802_rtc_driver); - -MODULE_DESCRIPTION("Maxim MAX77802 RTC driver"); -MODULE_AUTHOR("Simon Glass "); -MODULE_LICENSE("GPL"); -- cgit From bf035f42344a3e790c2d37ed3ee9005311f98075 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Jan 2016 15:46:11 +0900 Subject: rtc: max77686: Cleanup and reduce dmesg output Cleanup of entire driver of its dmesg output: 1. Remove printing of the function name, because printing device name is sufficient. This also makes the dev_err()-like functions more compact and readable (not need of line break). 2. Lower from info to debug printing of each RTC interrupt (no need to make noise on each alarm). 3. Remove dev_info() at beginning of probe because a message is already always printed by either probe failure or from registering the RTC device as /dev/rtcX. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Javier Martinez Canillas Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-max77686.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d2d1176a1f60..0f2965d912ae 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -271,8 +271,8 @@ static int max77686_rtc_update(struct max77686_rtc_info *info, info->drv_data->map[REG_RTC_UPDATE0], data, data); if (ret < 0) - dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n", - __func__, ret, data); + dev_err(info->dev, "Fail to write update reg(ret=%d, data=0x%x)\n", + ret, data); else { /* Minimum delay required before RTC update. */ usleep_range(delay, delay * 2); @@ -297,7 +297,7 @@ static int max77686_rtc_read_time(struct device *dev, struct rtc_time *tm) info->drv_data->map[REG_RTC_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__, ret); + dev_err(info->dev, "Fail to read time reg(%d)\n", ret); goto out; } @@ -326,8 +326,7 @@ static int max77686_rtc_set_time(struct device *dev, struct rtc_time *tm) info->drv_data->map[REG_RTC_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__, - ret); + dev_err(info->dev, "Fail to write time reg(%d)\n", ret); goto out; } @@ -355,8 +354,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ret = regmap_bulk_read(info->max77686->rtc_regmap, map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n", - __func__, __LINE__, ret); + dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret); goto out; } @@ -394,8 +392,7 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->pending = 0; ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val); if (ret < 0) { - dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n", - __func__, __LINE__, ret); + dev_err(info->dev, "Fail to read status2 reg(%d)\n", ret); goto out; } @@ -435,8 +432,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret); goto out; } @@ -451,8 +447,7 @@ static int max77686_rtc_stop_alarm(struct max77686_rtc_info *info) } if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret); goto out; } @@ -483,8 +478,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) map[REG_ALARM1_SEC], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to read alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to read alarm reg(%d)\n", ret); goto out; } @@ -507,8 +501,7 @@ static int max77686_rtc_start_alarm(struct max77686_rtc_info *info) } if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret); goto out; } @@ -538,8 +531,7 @@ static int max77686_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to write alarm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write alarm reg(%d)\n", ret); goto out; } @@ -574,7 +566,7 @@ static irqreturn_t max77686_rtc_alarm_irq(int irq, void *data) { struct max77686_rtc_info *info = data; - dev_info(info->dev, "%s:irq(%d)\n", __func__, irq); + dev_dbg(info->dev, "RTC alarm IRQ: %d\n", irq); rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF); @@ -604,8 +596,7 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) info->drv_data->map[REG_RTC_CONTROLM], data, ARRAY_SIZE(data)); if (ret < 0) { - dev_err(info->dev, "%s: fail to write controlm reg(%d)\n", - __func__, ret); + dev_err(info->dev, "Fail to write controlm reg(%d)\n", ret); return ret; } @@ -620,8 +611,6 @@ static int max77686_rtc_probe(struct platform_device *pdev) const struct platform_device_id *id = platform_get_device_id(pdev); int ret; - dev_info(&pdev->dev, "%s\n", __func__); - info = devm_kzalloc(&pdev->dev, sizeof(struct max77686_rtc_info), GFP_KERNEL); if (!info) @@ -661,7 +650,7 @@ static int max77686_rtc_probe(struct platform_device *pdev) if (!max77686->rtc_irq_data) { ret = -EINVAL; - dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__); + dev_err(&pdev->dev, "No RTC regmap IRQ chip\n"); goto err_rtc; } -- cgit From 54dd1c4c2979d1ad127d0e615fdd0f5016a5d713 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Wed, 23 Dec 2015 20:54:33 +0800 Subject: rtc: ds1305: use to_spi_device and kobj_to_dev For better readability, use to_spi_device() and kobj_to_dev() instead of container_of(). Signed-off-by: Geliang Tang Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1305.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index f39691eea736..8e41c4613e51 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj, struct spi_transfer x[2]; int status; - spi = container_of(kobj, struct spi_device, dev.kobj); + spi = to_spi_device(kobj_to_dev(kobj)); addr = DS1305_NVRAM + off; msg_init(&m, x, &addr, count, NULL, buf); @@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj, struct spi_transfer x[2]; int status; - spi = container_of(kobj, struct spi_device, dev.kobj); + spi = to_spi_device(kobj_to_dev(kobj)); addr = (DS1305_WRITE | DS1305_NVRAM) + off; msg_init(&m, x, &addr, count, buf, NULL); -- cgit From aaa3cee5deffa28415a6e1852c5afae0f5d210e2 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Thu, 21 Jan 2016 13:24:21 +0100 Subject: rtc: rx8025: remove rv8803 id The rv8803 has its own driver that should be used. Remove its id from the rx8025 driver. Fixes: b1f9d790b59dc04f8813a49a92ddd8651770ffee Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rx8025.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index bd911bafb809..17341feadad1 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -65,7 +65,6 @@ static const struct i2c_device_id rx8025_id[] = { { "rx8025", 0 }, - { "rv8803", 1 }, { } }; MODULE_DEVICE_TABLE(i2c, rx8025_id); -- cgit From 04d3ba70a3c9c9ba593d3208531463c65f055526 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 17:04:46 +0100 Subject: rtc: mt6397: add IRQ domain dependency The mt6397 RTC driver can be built either when the MFD_MT6397 driver is enabled (which selects IRQ_DOMAIN), or when compile testing. The latter however fails without IRQ domains: drivers/rtc/rtc-mt6397.c: In function 'mtk_rtc_probe': drivers/rtc/rtc-mt6397.c:326:13: error: implicit declaration of function 'irq_create_mapping' [-Werror=implicit-function-declaration] rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start); This adds an explicit dependency for the COMPILE_TEST case. Signed-off-by: Arnd Bergmann Acked-by: Eddie Huang Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ef456d3cf265..27f6ac46c596 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1593,7 +1593,7 @@ config RTC_DRV_MOXART config RTC_DRV_MT6397 tristate "Mediatek Real Time Clock driver" - depends on MFD_MT6397 || COMPILE_TEST + depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) help This selects the Mediatek(R) RTC driver. RTC is part of Mediatek MT6397 PMIC. You should enable MT6397 PMIC MFD before select -- cgit From 8bc2a40730ec74271a0573a6882871308d069f5d Mon Sep 17 00:00:00 2001 From: Michael Lange Date: Thu, 21 Jan 2016 18:10:16 +0100 Subject: rtc: ds1307: add support for the DT property 'wakeup-source' For RTC chips with no IRQ directly connected to the SoC, the RTC chip can be forced as a wakeup source by stating that explicitly in the device's .dts file using the "wakeup-source" boolean property. This will guarantee the 'wakealarm' sysfs entry is available on the device, if supported by the RTC. With these changes to the driver rtc-ds1307 and the necessary entries in the .dts file, I get an working ds1337 RTC on the Witty Pi extension board by UUGear for the Raspberry Pi. An example for the entry in the .dts file: rtc: ds1337@68 { compatible = "dallas,ds1337"; reg = <0x68>; wakeup-source; If the "wakeup-source" property is set, do not request an IRQ. Set also UIE mode to unsupported, to get a working 'hwclock' binary. Signed-off-by: Michael Lange Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-ds1307.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index cf685f67b391..bfedeb543bfd 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -851,6 +851,7 @@ static int ds1307_probe(struct i2c_client *client, struct chip_desc *chip = &chips[id->driver_data]; struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); bool want_irq = false; + bool ds1307_can_wakeup_device = false; unsigned char *buf; struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); irq_handler_t irq_handler = ds1307_irq; @@ -898,6 +899,20 @@ static int ds1307_probe(struct i2c_client *client, ds1307->write_block_data = ds1307_write_block_data; } +#ifdef CONFIG_OF +/* + * For devices with no IRQ directly connected to the SoC, the RTC chip + * can be forced as a wakeup source by stating that explicitly in + * the device's .dts file using the "wakeup-source" boolean property. + * If the "wakeup-source" property is set, don't request an IRQ. + * This will guarantee the 'wakealarm' sysfs entry is available on the device, + * if supported by the RTC. + */ + if (of_property_read_bool(client->dev.of_node, "wakeup-source")) { + ds1307_can_wakeup_device = true; + } +#endif + switch (ds1307->type) { case ds_1337: case ds_1339: @@ -916,11 +931,13 @@ static int ds1307_probe(struct i2c_client *client, ds1307->regs[0] &= ~DS1337_BIT_nEOSC; /* - * Using IRQ? Disable the square wave and both alarms. + * Using IRQ or defined as wakeup-source? + * Disable the square wave and both alarms. * For some variants, be sure alarms can trigger when we're * running on Vbackup (BBSQI/BBSQW) */ - if (ds1307->client->irq > 0 && chip->alarm) { + if (chip->alarm && (ds1307->client->irq > 0 || + ds1307_can_wakeup_device)) { ds1307->regs[0] |= DS1337_BIT_INTCN | bbsqi_bitpos[ds1307->type]; ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); @@ -1135,6 +1152,14 @@ read_rtc: return PTR_ERR(ds1307->rtc); } + if (ds1307_can_wakeup_device) { + /* Disable request for an IRQ */ + want_irq = false; + dev_info(&client->dev, "'wakeup-source' is set, request for an IRQ is disabled!\n"); + /* We cannot support UIE mode if we do not have an IRQ line */ + ds1307->rtc->uie_unsupported = 1; + } + if (want_irq) { err = devm_request_threaded_irq(&client->dev, client->irq, NULL, irq_handler, -- cgit From 445c02076f1e60d2ee51503bf1288ef9f3bc8809 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 25 Jan 2016 00:22:16 +0900 Subject: rtc: ds1307: add temperature sensor support for ds3231 DS3231 has the temperature registers with a resolution of 0.25 degree celsius. This enables to get the value through hwmon. # cat /sys/class/i2c-adapter/i2c-2/2-0068/hwmon/hwmon0/temp1_input 21000 Signed-off-by: Akinobu Mita Acked-by: Guenter Roeck Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 9 +++++ drivers/rtc/rtc-ds1307.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 27f6ac46c596..d47ad96132bf 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -212,6 +212,15 @@ config RTC_DRV_DS1307 This driver can also be built as a module. If so, the module will be called rtc-ds1307. +config RTC_DRV_DS1307_HWMON + bool "HWMON support for rtc-ds1307" + depends on RTC_DRV_DS1307 && HWMON + depends on !(RTC_DRV_DS1307=y && HWMON=m) + default y + help + Say Y here if you want to expose temperature sensor data on + rtc-ds1307 (only DS3231) + config RTC_DRV_DS1374 tristate "Dallas/Maxim DS1374" help diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bfedeb543bfd..2462d5a53a53 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include /* * We can't determine type by probing, but if we expect pre-Linux code @@ -842,6 +844,90 @@ out: return; } +/*----------------------------------------------------------------------*/ + +#ifdef CONFIG_RTC_DRV_DS1307_HWMON + +/* + * Temperature sensor support for ds3231 devices. + */ + +#define DS3231_REG_TEMPERATURE 0x11 + +/* + * A user-initiated temperature conversion is not started by this function, + * so the temperature is updated once every 64 seconds. + */ +static int ds3231_hwmon_read_temp(struct device *dev, s16 *mC) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + u8 temp_buf[2]; + s16 temp; + int ret; + + ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE, + sizeof(temp_buf), temp_buf); + if (ret < 0) + return ret; + if (ret != sizeof(temp_buf)) + return -EIO; + + /* + * Temperature is represented as a 10-bit code with a resolution of + * 0.25 degree celsius and encoded in two's complement format. + */ + temp = (temp_buf[0] << 8) | temp_buf[1]; + temp >>= 6; + *mC = temp * 250; + + return 0; +} + +static ssize_t ds3231_hwmon_show_temp(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int ret; + s16 temp; + + ret = ds3231_hwmon_read_temp(dev, &temp); + if (ret) + return ret; + + return sprintf(buf, "%d\n", temp); +} +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp, + NULL, 0); + +static struct attribute *ds3231_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL, +}; +ATTRIBUTE_GROUPS(ds3231_hwmon); + +static void ds1307_hwmon_register(struct ds1307 *ds1307) +{ + struct device *dev; + + if (ds1307->type != ds_3231) + return; + + dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev, + ds1307->client->name, + ds1307, ds3231_hwmon_groups); + if (IS_ERR(dev)) { + dev_warn(&ds1307->client->dev, + "unable to register hwmon device %ld\n", PTR_ERR(dev)); + } +} + +#else + +static void ds1307_hwmon_register(struct ds1307 *ds1307) +{ +} + +#endif + static int ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1207,6 +1293,8 @@ read_rtc: } } + ds1307_hwmon_register(ds1307); + return 0; exit: -- cgit From 296d48568042360d0e2a6e6e91b0130acb5ca738 Mon Sep 17 00:00:00 2001 From: Mahesh Bandewar Date: Wed, 27 Jan 2016 23:33:28 -0800 Subject: ipvlan: inherit MTU from master device When we create IPvlan slave; we use ether_setup() and that sets up default MTU to 1500 while the master device may have lower / different MTU. Any subsequent changes to the masters' MTU are reflected into the slaves' MTU setting. However if those don't happen (most likely scenario), the slaves' MTU stays at 1500 which could be bad. This change adds code to inherit MTU from the master device instead of using the default value during the link initialization phase. Signed-off-by: Mahesh Bandewar CC: Eric Dumazet CC: Tim Hockins Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index f94392d07126..7a3b41468a55 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -468,6 +468,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev, ipvlan->dev = dev; ipvlan->port = port; ipvlan->sfeatures = IPVLAN_FEATURES; + ipvlan_adjust_mtu(ipvlan, phy_dev); INIT_LIST_HEAD(&ipvlan->addrs); /* TODO Probably put random address here to be presented to the -- cgit From de1df26b7cef702a32ae876ed45c1112f523df48 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Feb 2016 02:37:42 +0100 Subject: cpufreq: Clean up default and fallback governor setup The preprocessor magic used for setting the default cpufreq governor (and for using the performance governor as a fallback one for that matter) is really nasty, so replace it with __weak functions and overrides. Signed-off-by: Rafael J. Wysocki Acked-by: Saravana Kannan Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 37 +++++++++++++++++++--------------- drivers/cpufreq/cpufreq_conservative.c | 10 +++++---- drivers/cpufreq/cpufreq_ondemand.c | 36 ++++++++++++++++----------------- drivers/cpufreq/cpufreq_performance.c | 18 +++++++++++++---- drivers/cpufreq/cpufreq_powersave.c | 10 +++++---- drivers/cpufreq/cpufreq_userspace.c | 10 +++++---- include/linux/cpufreq.h | 25 ++--------------------- 7 files changed, 73 insertions(+), 73 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e979ec78b695..34b17447e0d1 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -959,6 +959,11 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy) return cpufreq_add_dev_symlink(policy); } +__weak struct cpufreq_governor *cpufreq_default_governor(void) +{ + return NULL; +} + static int cpufreq_init_policy(struct cpufreq_policy *policy) { struct cpufreq_governor *gov = NULL; @@ -968,11 +973,14 @@ static int cpufreq_init_policy(struct cpufreq_policy *policy) /* Update governor of new_policy to the governor used before hotplug */ gov = find_governor(policy->last_governor); - if (gov) + if (gov) { pr_debug("Restoring governor %s for cpu %d\n", policy->governor->name, policy->cpu); - else - gov = CPUFREQ_DEFAULT_GOVERNOR; + } else { + gov = cpufreq_default_governor(); + if (!gov) + return -ENODATA; + } new_policy.governor = gov; @@ -1920,21 +1928,16 @@ int cpufreq_driver_target(struct cpufreq_policy *policy, } EXPORT_SYMBOL_GPL(cpufreq_driver_target); +__weak struct cpufreq_governor *cpufreq_fallback_governor(void) +{ + return NULL; +} + static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { int ret; - /* Only must be defined when default governor is known to have latency - restrictions, like e.g. conservative or ondemand. - That this is the case is already ensured in Kconfig - */ -#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE - struct cpufreq_governor *gov = &cpufreq_gov_performance; -#else - struct cpufreq_governor *gov = NULL; -#endif - /* Don't start any governor operations if we are entering suspend */ if (cpufreq_suspended) return 0; @@ -1948,12 +1951,14 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, if (policy->governor->max_transition_latency && policy->cpuinfo.transition_latency > policy->governor->max_transition_latency) { - if (!gov) - return -EINVAL; - else { + struct cpufreq_governor *gov = cpufreq_fallback_governor(); + + if (gov) { pr_warn("%s governor failed, too long transition latency of HW, fallback to %s governor\n", policy->governor->name, gov->name); policy->governor = gov; + } else { + return -EINVAL; } } diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 606ad74abe6e..8504a70a4785 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -26,10 +26,7 @@ static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info); static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE -static -#endif -struct cpufreq_governor cpufreq_gov_conservative = { +static struct cpufreq_governor cpufreq_gov_conservative = { .name = "conservative", .governor = cs_cpufreq_governor_dbs, .max_transition_latency = TRANSITION_LATENCY_LIMIT, @@ -399,6 +396,11 @@ MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_conservative; +} + fs_initcall(cpufreq_gov_dbs_init); #else module_init(cpufreq_gov_dbs_init); diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index eae51070c034..929e193ac1c1 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -31,9 +31,7 @@ static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info); static struct od_ops od_ops; -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND static struct cpufreq_governor cpufreq_gov_ondemand; -#endif static unsigned int default_powersave_bias; @@ -554,6 +552,19 @@ static struct common_dbs_data od_dbs_cdata = { .mutex = __MUTEX_INITIALIZER(od_dbs_cdata.mutex), }; +static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + return cpufreq_governor_dbs(policy, &od_dbs_cdata, event); +} + +static struct cpufreq_governor cpufreq_gov_ondemand = { + .name = "ondemand", + .governor = od_cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + static void od_set_powersave_bias(unsigned int powersave_bias) { struct cpufreq_policy *policy; @@ -605,22 +616,6 @@ void od_unregister_powersave_bias_handler(void) } EXPORT_SYMBOL_GPL(od_unregister_powersave_bias_handler); -static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy, - unsigned int event) -{ - return cpufreq_governor_dbs(policy, &od_dbs_cdata, event); -} - -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND -static -#endif -struct cpufreq_governor cpufreq_gov_ondemand = { - .name = "ondemand", - .governor = od_cpufreq_governor_dbs, - .max_transition_latency = TRANSITION_LATENCY_LIMIT, - .owner = THIS_MODULE, -}; - static int __init cpufreq_gov_dbs_init(void) { return cpufreq_register_governor(&cpufreq_gov_ondemand); @@ -638,6 +633,11 @@ MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_ondemand; +} + fs_initcall(cpufreq_gov_dbs_init); #else module_init(cpufreq_gov_dbs_init); diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c index cf117deb39b1..af9f4b96f5a8 100644 --- a/drivers/cpufreq/cpufreq_performance.c +++ b/drivers/cpufreq/cpufreq_performance.c @@ -33,10 +33,7 @@ static int cpufreq_governor_performance(struct cpufreq_policy *policy, return 0; } -#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE -static -#endif -struct cpufreq_governor cpufreq_gov_performance = { +static struct cpufreq_governor cpufreq_gov_performance = { .name = "performance", .governor = cpufreq_governor_performance, .owner = THIS_MODULE, @@ -52,6 +49,19 @@ static void __exit cpufreq_gov_performance_exit(void) cpufreq_unregister_governor(&cpufreq_gov_performance); } +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_performance; +} +#endif +#ifndef CONFIG_CPU_FREQ_GOV_PERFORMANCE_MODULE +struct cpufreq_governor *cpufreq_fallback_governor(void) +{ + return &cpufreq_gov_performance; +} +#endif + MODULE_AUTHOR("Dominik Brodowski "); MODULE_DESCRIPTION("CPUfreq policy governor 'performance'"); MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index e3b874c235ea..b8b400232a74 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -33,10 +33,7 @@ static int cpufreq_governor_powersave(struct cpufreq_policy *policy, return 0; } -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE -static -#endif -struct cpufreq_governor cpufreq_gov_powersave = { +static struct cpufreq_governor cpufreq_gov_powersave = { .name = "powersave", .governor = cpufreq_governor_powersave, .owner = THIS_MODULE, @@ -57,6 +54,11 @@ MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'"); MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_powersave; +} + fs_initcall(cpufreq_gov_powersave_init); #else module_init(cpufreq_gov_powersave_init); diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 4dbf1db16aca..4d16f45ee1da 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -89,10 +89,7 @@ static int cpufreq_governor_userspace(struct cpufreq_policy *policy, return rc; } -#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE -static -#endif -struct cpufreq_governor cpufreq_gov_userspace = { +static struct cpufreq_governor cpufreq_gov_userspace = { .name = "userspace", .governor = cpufreq_governor_userspace, .store_setspeed = cpufreq_set, @@ -116,6 +113,11 @@ MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &cpufreq_gov_userspace; +} + fs_initcall(cpufreq_gov_userspace_init); #else module_init(cpufreq_gov_userspace_init); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 88a4215125bc..d0bf555b6bbf 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -464,29 +464,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); -/* CPUFREQ DEFAULT GOVERNOR */ -/* - * Performance governor is fallback governor if any other gov failed to auto - * load due latency restrictions - */ -#ifdef CONFIG_CPU_FREQ_GOV_PERFORMANCE -extern struct cpufreq_governor cpufreq_gov_performance; -#endif -#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_performance) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE) -extern struct cpufreq_governor cpufreq_gov_powersave; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_powersave) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) -extern struct cpufreq_governor cpufreq_gov_userspace; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_userspace) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND) -extern struct cpufreq_governor cpufreq_gov_ondemand; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand) -#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) -extern struct cpufreq_governor cpufreq_gov_conservative; -#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) -#endif +struct cpufreq_governor *cpufreq_default_governor(void); +struct cpufreq_governor *cpufreq_fallback_governor(void); /********************************************************************* * FREQUENCY TABLE HELPERS * -- cgit From 86622cb8c57abb05fe95bea3a068949c0ca79fc3 Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:37 +0530 Subject: cpufreq: powernv: Free 'chips' on module exit This will free the dynamically allocated memory of 'chips' on module exit. Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 547890fd9572..53f980bf9b77 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -612,6 +612,7 @@ static void __exit powernv_cpufreq_exit(void) unregister_reboot_notifier(&powernv_cpufreq_reboot_nb); opal_message_notifier_unregister(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb); + kfree(chips); cpufreq_unregister_driver(&powernv_cpufreq_driver); } module_exit(powernv_cpufreq_exit); -- cgit From 6d167a44e6c8da3316e037b788585fcf96112bea Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:38 +0530 Subject: cpufreq: powernv: Hot-plug safe the kworker thread In the kworker_thread powernv_cpufreq_work_fn(), we can end up sending an IPI to a cpu going offline. This is a rare corner case which is fixed using {get/put}_online_cpus(). Along with this fix, this patch adds changes to do oneshot cpumask_{clear/and} operation. Suggested-by: Shreyas B Prabhu Suggested-by: Gautham R Shenoy Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 53f980bf9b77..a271b0fbe8b9 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -423,18 +424,19 @@ void powernv_cpufreq_work_fn(struct work_struct *work) { struct chip *chip = container_of(work, struct chip, throttle); unsigned int cpu; - cpumask_var_t mask; + cpumask_t mask; - smp_call_function_any(&chip->mask, + get_online_cpus(); + cpumask_and(&mask, &chip->mask, cpu_online_mask); + smp_call_function_any(&mask, powernv_cpufreq_throttle_check, NULL, 0); if (!chip->restore) - return; + goto out; chip->restore = false; - cpumask_copy(mask, &chip->mask); - for_each_cpu_and(cpu, mask, cpu_online_mask) { - int index, tcpu; + for_each_cpu(cpu, &mask) { + int index; struct cpufreq_policy policy; cpufreq_get_policy(&policy, cpu); @@ -442,9 +444,10 @@ void powernv_cpufreq_work_fn(struct work_struct *work) policy.cur, CPUFREQ_RELATION_C, &index); powernv_cpufreq_target_index(&policy, index); - for_each_cpu(tcpu, policy.cpus) - cpumask_clear_cpu(tcpu, mask); + cpumask_andnot(&mask, &mask, policy.cpus); } +out: + put_online_cpus(); } static char throttle_reason[][30] = { -- cgit From 96c4726f01cdbf53acf74cf2394e287d74bf40a3 Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:39 +0530 Subject: cpufreq: powernv: Remove cpu_to_chip_id() from hot-path cpu_to_chip_id() does a DT walk through to find out the chip id by taking a contended device tree lock. This adds an unnecessary overhead in a hot path. So instead of calling cpu_to_chip_id() everytime cache the chip ids for all cores in the array 'core_to_chip_map' and use it in the hotpath. Reported-by: Anton Blanchard Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index a271b0fbe8b9..c670314053af 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -43,6 +43,7 @@ static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; static bool rebooting, throttled, occ_reset; +static unsigned int *core_to_chip_map; static struct chip { unsigned int id; @@ -313,13 +314,14 @@ static inline unsigned int get_nominal_index(void) static void powernv_cpufreq_throttle_check(void *data) { unsigned int cpu = smp_processor_id(); + unsigned int chip_id = core_to_chip_map[cpu_core_index_of_thread(cpu)]; unsigned long pmsr; int pmsr_pmax, i; pmsr = get_pmspr(SPRN_PMSR); for (i = 0; i < nr_chips; i++) - if (chips[i].id == cpu_to_chip_id(cpu)) + if (chips[i].id == chip_id) break; /* Check for Pmax Capping */ @@ -559,19 +561,29 @@ static int init_chip_info(void) unsigned int chip[256]; unsigned int cpu, i; unsigned int prev_chip_id = UINT_MAX; + cpumask_t cpu_mask; + int ret = -ENOMEM; - for_each_possible_cpu(cpu) { + core_to_chip_map = kcalloc(cpu_nr_cores(), sizeof(unsigned int), + GFP_KERNEL); + if (!core_to_chip_map) + goto out; + + cpumask_copy(&cpu_mask, cpu_possible_mask); + for_each_cpu(cpu, &cpu_mask) { unsigned int id = cpu_to_chip_id(cpu); if (prev_chip_id != id) { prev_chip_id = id; chip[nr_chips++] = id; } + core_to_chip_map[cpu_core_index_of_thread(cpu)] = id; + cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); } chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL); if (!chips) - return -ENOMEM; + goto free_chip_map; for (i = 0; i < nr_chips; i++) { chips[i].id = chip[i]; @@ -582,6 +594,10 @@ static int init_chip_info(void) } return 0; +free_chip_map: + kfree(core_to_chip_map); +out: + return ret; } static int __init powernv_cpufreq_init(void) @@ -616,6 +632,7 @@ static void __exit powernv_cpufreq_exit(void) opal_message_notifier_unregister(OPAL_MSG_OCC, &powernv_cpufreq_opal_nb); kfree(chips); + kfree(core_to_chip_map); cpufreq_unregister_driver(&powernv_cpufreq_driver); } module_exit(powernv_cpufreq_exit); -- cgit From 0306e481d479a58eff17c27adf213fbb5822946b Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:40 +0530 Subject: cpufreq: powernv/tracing: Add powernv_throttle tracepoint This patch adds the powernv_throttle tracepoint to trace the CPU frequency throttling event, which is used by the powernv-cpufreq driver in POWER8. Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Signed-off-by: Rafael J. Wysocki --- include/trace/events/power.h | 22 ++++++++++++++++++++++ kernel/trace/power-traces.c | 1 + 2 files changed, 23 insertions(+) diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 284244ebfe8d..19e50300ce7d 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -38,6 +38,28 @@ DEFINE_EVENT(cpu, cpu_idle, TP_ARGS(state, cpu_id) ); +TRACE_EVENT(powernv_throttle, + + TP_PROTO(int chip_id, const char *reason, int pmax), + + TP_ARGS(chip_id, reason, pmax), + + TP_STRUCT__entry( + __field(int, chip_id) + __string(reason, reason) + __field(int, pmax) + ), + + TP_fast_assign( + __entry->chip_id = chip_id; + __assign_str(reason, reason); + __entry->pmax = pmax; + ), + + TP_printk("Chip %d Pmax %d %s", __entry->chip_id, + __entry->pmax, __get_str(reason)) +); + TRACE_EVENT(pstate_sample, TP_PROTO(u32 core_busy, diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c index eb4220a132ec..81b87451c0ea 100644 --- a/kernel/trace/power-traces.c +++ b/kernel/trace/power-traces.c @@ -15,4 +15,5 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(suspend_resume); EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle); +EXPORT_TRACEPOINT_SYMBOL_GPL(powernv_throttle); -- cgit From c89f2682a39192433c296bf97b834fd2815a758b Mon Sep 17 00:00:00 2001 From: Shilpasri G Bhat Date: Wed, 3 Feb 2016 01:11:41 +0530 Subject: cpufreq: powernv: Replace pr_info with trace print for throttle event Currently we use printk message to notify the throttle event. But this can flood the console if the cpu is throttled frequently. So replace the printk with the tracepoint to notify the throttle event. And also events like throttle below nominal frequency and OCC_RESET are reduced to pr_warn/pr_warn_once as pointed by MFG to not mark them as critical messages. This patch adds 'throttle_reason' to struct chip to store the throttle reason. Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernv-cpufreq.c | 73 ++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index c670314053af..1bbc10a54c59 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -45,12 +46,22 @@ static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; static bool rebooting, throttled, occ_reset; static unsigned int *core_to_chip_map; +static const char * const throttle_reason[] = { + "No throttling", + "Power Cap", + "Processor Over Temperature", + "Power Supply Failure", + "Over Current", + "OCC Reset" +}; + static struct chip { unsigned int id; bool throttled; + bool restore; + u8 throttle_reason; cpumask_t mask; struct work_struct throttle; - bool restore; } *chips; static int nr_chips; @@ -331,17 +342,17 @@ static void powernv_cpufreq_throttle_check(void *data) goto next; chips[i].throttled = true; if (pmsr_pmax < powernv_pstate_info.nominal) - pr_crit("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", - cpu, chips[i].id, pmsr_pmax, - powernv_pstate_info.nominal); - else - pr_info("CPU %d on Chip %u has Pmax reduced below turbo frequency (%d < %d)\n", - cpu, chips[i].id, pmsr_pmax, - powernv_pstate_info.max); + pr_warn_once("CPU %d on Chip %u has Pmax reduced below nominal frequency (%d < %d)\n", + cpu, chips[i].id, pmsr_pmax, + powernv_pstate_info.nominal); + trace_powernv_throttle(chips[i].id, + throttle_reason[chips[i].throttle_reason], + pmsr_pmax); } else if (chips[i].throttled) { chips[i].throttled = false; - pr_info("CPU %d on Chip %u has Pmax restored to %d\n", cpu, - chips[i].id, pmsr_pmax); + trace_powernv_throttle(chips[i].id, + throttle_reason[chips[i].throttle_reason], + pmsr_pmax); } /* Check if Psafe_mode_active is set in PMSR. */ @@ -359,7 +370,7 @@ next: if (throttled) { pr_info("PMSR = %16lx\n", pmsr); - pr_crit("CPU Frequency could be throttled\n"); + pr_warn("CPU Frequency could be throttled\n"); } } @@ -452,15 +463,6 @@ out: put_online_cpus(); } -static char throttle_reason[][30] = { - "No throttling", - "Power Cap", - "Processor Over Temperature", - "Power Supply Failure", - "Over Current", - "OCC Reset" - }; - static int powernv_cpufreq_occ_msg(struct notifier_block *nb, unsigned long msg_type, void *_msg) { @@ -486,7 +488,7 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, */ if (!throttled) { throttled = true; - pr_crit("CPU frequency is throttled for duration\n"); + pr_warn("CPU frequency is throttled for duration\n"); } break; @@ -510,23 +512,18 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, return 0; } - if (omsg.throttle_status && + for (i = 0; i < nr_chips; i++) + if (chips[i].id == omsg.chip) + break; + + if (omsg.throttle_status >= 0 && omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS) - pr_info("OCC: Chip %u Pmax reduced due to %s\n", - (unsigned int)omsg.chip, - throttle_reason[omsg.throttle_status]); - else if (!omsg.throttle_status) - pr_info("OCC: Chip %u %s\n", (unsigned int)omsg.chip, - throttle_reason[omsg.throttle_status]); - else - return 0; + chips[i].throttle_reason = omsg.throttle_status; - for (i = 0; i < nr_chips; i++) - if (chips[i].id == omsg.chip) { - if (!omsg.throttle_status) - chips[i].restore = true; - schedule_work(&chips[i].throttle); - } + if (!omsg.throttle_status) + chips[i].restore = true; + + schedule_work(&chips[i].throttle); } return 0; } @@ -581,16 +578,14 @@ static int init_chip_info(void) cpumask_andnot(&cpu_mask, &cpu_mask, cpu_sibling_mask(cpu)); } - chips = kmalloc_array(nr_chips, sizeof(struct chip), GFP_KERNEL); + chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL); if (!chips) goto free_chip_map; for (i = 0; i < nr_chips; i++) { chips[i].id = chip[i]; - chips[i].throttled = false; cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); - chips[i].restore = false; } return 0; -- cgit From c4924e92442d7218bd725e47fa3988c73aae84c9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 4 Feb 2016 14:36:09 +0300 Subject: extcon: max77843: Use correct size for reading the interrupt register The info->status[] array has 3 elements. We are using size MAX77843_MUIC_IRQ_NUM (16) instead of MAX77843_MUIC_STATUS_NUM (3) as intended. Fixes: 135d9f7d135a ('extcon: max77843: Clear IRQ bits state before request IRQ') Signed-off-by: Dan Carpenter Reviewed-by: Jaewon Kim Reviewed-by: Krzysztof Kozlowski [cw00.choi: Modify the patch title] Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon-max77843.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c index 7bbc30097771..b188bd650efa 100644 --- a/drivers/extcon/extcon-max77843.c +++ b/drivers/extcon/extcon-max77843.c @@ -806,7 +806,7 @@ static int max77843_muic_probe(struct platform_device *pdev) /* Clear IRQ bits before request IRQs */ ret = regmap_bulk_read(max77843->regmap_muic, MAX77843_MUIC_REG_INT1, info->status, - MAX77843_MUIC_IRQ_NUM); + MAX77843_MUIC_STATUS_NUM); if (ret) { dev_err(&pdev->dev, "Failed to Clear IRQ bits\n"); goto err_muic_irq; -- cgit From b7aad8e2685b0aa58295bc4250c8476c9c7193eb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Dec 2015 09:55:45 +0900 Subject: extcon: palmas: Add the support for VBUS detection by using GPIO This patch support for VBUS detection by using GPIO pin. Signed-off-by: Felipe Balbi Signed-off-by: Chanwoo Choi Acked-by: Lee Jones --- drivers/extcon/extcon-palmas.c | 50 ++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/palmas.h | 3 +++ 2 files changed, 53 insertions(+) diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 93c30a885740..885ee95a6a7b 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -216,11 +216,23 @@ static int palmas_usb_probe(struct platform_device *pdev) return PTR_ERR(palmas_usb->id_gpiod); } + palmas_usb->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus", + GPIOD_IN); + if (IS_ERR(palmas_usb->vbus_gpiod)) { + dev_err(&pdev->dev, "failed to get vbus gpio\n"); + return PTR_ERR(palmas_usb->vbus_gpiod); + } + if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) { palmas_usb->enable_id_detection = false; palmas_usb->enable_gpio_id_detection = true; } + if (palmas_usb->enable_vbus_detection && palmas_usb->vbus_gpiod) { + palmas_usb->enable_vbus_detection = false; + palmas_usb->enable_gpio_vbus_detection = true; + } + if (palmas_usb->enable_gpio_id_detection) { u32 debounce; @@ -311,6 +323,40 @@ static int palmas_usb_probe(struct platform_device *pdev) palmas_usb->vbus_irq, status); return status; } + } else if (palmas_usb->enable_gpio_vbus_detection) { + /* remux GPIO_1 as VBUSDET */ + status = palmas_update_bits(palmas, + PALMAS_PU_PD_OD_BASE, + PALMAS_PRIMARY_SECONDARY_PAD1, + PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK, + (1 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)); + if (status < 0) { + dev_err(&pdev->dev, "can't remux GPIO1\n"); + return status; + } + + palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data, + PALMAS_VBUS_OTG_IRQ); + palmas_usb->gpio_vbus_irq = gpiod_to_irq(palmas_usb->vbus_gpiod); + if (palmas_usb->gpio_vbus_irq < 0) { + dev_err(&pdev->dev, "failed to get vbus irq\n"); + return palmas_usb->gpio_vbus_irq; + } + status = devm_request_threaded_irq(&pdev->dev, + palmas_usb->gpio_vbus_irq, + NULL, + palmas_vbus_irq_handler, + IRQF_TRIGGER_FALLING | + IRQF_TRIGGER_RISING | + IRQF_ONESHOT | + IRQF_EARLY_RESUME, + "palmas_usb_vbus", + palmas_usb); + if (status < 0) { + dev_err(&pdev->dev, + "failed to request handler for vbus irq\n"); + return status; + } } palmas_enable_irq(palmas_usb); @@ -337,6 +383,8 @@ static int palmas_usb_suspend(struct device *dev) if (device_may_wakeup(dev)) { if (palmas_usb->enable_vbus_detection) enable_irq_wake(palmas_usb->vbus_irq); + if (palmas_usb->enable_gpio_vbus_detection) + enable_irq_wake(palmas_usb->gpio_vbus_irq); if (palmas_usb->enable_id_detection) enable_irq_wake(palmas_usb->id_irq); if (palmas_usb->enable_gpio_id_detection) @@ -352,6 +400,8 @@ static int palmas_usb_resume(struct device *dev) if (device_may_wakeup(dev)) { if (palmas_usb->enable_vbus_detection) disable_irq_wake(palmas_usb->vbus_irq); + if (palmas_usb->enable_gpio_vbus_detection) + disable_irq_wake(palmas_usb->gpio_vbus_irq); if (palmas_usb->enable_id_detection) disable_irq_wake(palmas_usb->id_irq); if (palmas_usb->enable_gpio_id_detection) diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h index c800dbc42079..5c9a1d44c125 100644 --- a/include/linux/mfd/palmas.h +++ b/include/linux/mfd/palmas.h @@ -580,7 +580,9 @@ struct palmas_usb { int vbus_irq; int gpio_id_irq; + int gpio_vbus_irq; struct gpio_desc *id_gpiod; + struct gpio_desc *vbus_gpiod; unsigned long sw_debounce_jiffies; struct delayed_work wq_detectid; @@ -589,6 +591,7 @@ struct palmas_usb { bool enable_vbus_detection; bool enable_id_detection; bool enable_gpio_id_detection; + bool enable_gpio_vbus_detection; }; #define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator) -- cgit From 16b2329cc461fd15350d3cd3713a3b07a272d6ad Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Dec 2015 09:55:46 +0900 Subject: arm: boot: dts: beaglex15: Remove ID GPIO According to latest schematics [1], this board leaves ID pin floating. It's not connected to anything at all. So let's remove it. [1] https://github.com/beagleboard/beagleboard-x15/blob/master/BeagleBoard-X15_RevA2.pdf Signed-off-by: Felipe Balbi Signed-off-by: Chanwoo Choi Acked-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 36c0fa6c362a..8e6bce78a535 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -560,8 +560,6 @@ extcon_usb2: tps659038_usb { compatible = "ti,palmas-usb-vid"; ti,enable-vbus-detection; - ti,enable-id-detection; - id-gpios = <&gpio7 24 GPIO_ACTIVE_HIGH>; }; }; -- cgit From 0331966df0a288236bea6489420a35a0ca1e9043 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 30 Dec 2015 09:55:47 +0900 Subject: arm: boot: beaglex15: pass correct interrupt According to latest schematics [1], GPIO_1/VBUSDET on TPS659038 is tied to AM57x GPIO4_21. We can use that as a VBUS interrupt, instead of relying on PMIC's VBUS interrupts which don't seem to be firing on x15 at all. A follow up patch will add support for using this GPIO-based interrupt mechanism for notifying about VBUS. [1] https://github.com/beagleboard/beagleboard-x15/blob/master/BeagleBoard-X15_RevA2.pdf Signed-off-by: Felipe Balbi [cw00.choi: Use the 'vbus-gpio' property instead of 'interrupts-extended'] Signed-off-by: Chanwoo Choi Acked-by: Tony Lindgren --- arch/arm/boot/dts/am57xx-beagle-x15.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts index 8e6bce78a535..c37a5193f199 100644 --- a/arch/arm/boot/dts/am57xx-beagle-x15.dts +++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts @@ -560,6 +560,7 @@ extcon_usb2: tps659038_usb { compatible = "ti,palmas-usb-vid"; ti,enable-vbus-detection; + vbus-gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>; }; }; -- cgit From a6e4491c682a7b28574a62e6f311a0acec50b318 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 4 Feb 2016 09:38:00 -0500 Subject: sched/isolcpus: Output warning when the 'isolcpus=' kernel parameter is invalid The isolcpus= kernel boot parameter restricts userspace from scheduling on the specified CPUs. If a CPU is specified that is outside the range of 0 to nr_cpu_ids, cpulist_parse() will return -ERANGE, return an empty cpulist, and fail silently. This patch adds an error message to isolated_cpu_setup() to indicate to the user that something has gone awry, and returns 0 on error. Signed-off-by: Prarit Bhargava Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1454596680-10367-1-git-send-email-prarit@redhat.com [ Twiddled some details. ] Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9503d590e5ef..24fcdbf28b18 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6173,11 +6173,16 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu) /* Setup the mask of cpus configured for isolated domains */ static int __init isolated_cpu_setup(char *str) { + int ret; + alloc_bootmem_cpumask_var(&cpu_isolated_map); - cpulist_parse(str, cpu_isolated_map); + ret = cpulist_parse(str, cpu_isolated_map); + if (ret) { + pr_err("sched: Error, all isolcpus= values must be between 0 and %d\n", nr_cpu_ids); + return 0; + } return 1; } - __setup("isolcpus=", isolated_cpu_setup); struct s_data { -- cgit From 23272a6754b81ff6503e09c743bb4ceeeab39997 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 11:51:16 +0100 Subject: nbd: Remove signal usage As discussed on the mailing list, the usage of signals for timeout handling has a lot of potential issues. The nbd driver used for some time signals for timeouts. These signals where able to get the threads out of the blocking socket operations. This patch removes all signal usage and uses a socket shutdown instead. The socket descriptor itself is cleared later when the whole nbd device is closed. The tasks_lock is removed as we do not depend on this anymore. Instead a new lock for the socket is introduced so we can safely work with the socket in the timeout handler outside of the two main threads. Cc: Oleg Nesterov Cc: Christoph Hellwig Signed-off-by: Markus Pargmann Reviewed-by: Christoph Hellwig --- drivers/block/nbd.c | 126 ++++++++++++++++++++-------------------------------- 1 file changed, 48 insertions(+), 78 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index d61a04155d99..438f4dc549db 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -60,7 +60,8 @@ struct nbd_device { bool disconnect; /* a disconnect has been requested by user */ struct timer_list timeout_timer; - spinlock_t tasks_lock; + /* protects initialization and shutdown of the socket */ + spinlock_t sock_lock; struct task_struct *task_recv; struct task_struct *task_send; @@ -129,13 +130,20 @@ static void nbd_end_request(struct nbd_device *nbd, struct request *req) */ static void sock_shutdown(struct nbd_device *nbd) { - if (!nbd->sock) + spin_lock_irq(&nbd->sock_lock); + + if (!nbd->sock) { + spin_unlock_irq(&nbd->sock_lock); return; + } dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n"); kernel_sock_shutdown(nbd->sock, SHUT_RDWR); + sockfd_put(nbd->sock); nbd->sock = NULL; - del_timer_sync(&nbd->timeout_timer); + spin_unlock_irq(&nbd->sock_lock); + + del_timer(&nbd->timeout_timer); } static void nbd_xmit_timeout(unsigned long arg) @@ -148,17 +156,15 @@ static void nbd_xmit_timeout(unsigned long arg) nbd->disconnect = true; - spin_lock_irqsave(&nbd->tasks_lock, flags); + spin_lock_irqsave(&nbd->sock_lock, flags); - if (nbd->task_recv) - force_sig(SIGKILL, nbd->task_recv); - if (nbd->task_send) - force_sig(SIGKILL, nbd->task_send); + if (nbd->sock) + kernel_sock_shutdown(nbd->sock, SHUT_RDWR); - spin_unlock_irqrestore(&nbd->tasks_lock, flags); + spin_unlock_irqrestore(&nbd->sock_lock, flags); - dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n"); + dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n"); } /* @@ -171,7 +177,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, int result; struct msghdr msg; struct kvec iov; - sigset_t blocked, oldset; unsigned long pflags = current->flags; if (unlikely(!sock)) { @@ -181,11 +186,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, return -EINVAL; } - /* Allow interception of SIGKILL only - * Don't allow other signals to interrupt the transmission */ - siginitsetinv(&blocked, sigmask(SIGKILL)); - sigprocmask(SIG_SETMASK, &blocked, &oldset); - current->flags |= PF_MEMALLOC; do { sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC; @@ -212,7 +212,6 @@ static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size, buf += result; } while (size > 0); - sigprocmask(SIG_SETMASK, &oldset, NULL); tsk_restore_flags(current, pflags, PF_MEMALLOC); if (!send && nbd->xmit_timeout) @@ -406,23 +405,18 @@ static int nbd_thread_recv(struct nbd_device *nbd) { struct request *req; int ret; - unsigned long flags; BUG_ON(nbd->magic != NBD_MAGIC); sk_set_memalloc(nbd->sock->sk); - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_recv = current; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr); if (ret) { dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n"); - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_recv = NULL; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); return ret; } @@ -439,19 +433,7 @@ static int nbd_thread_recv(struct nbd_device *nbd) device_remove_file(disk_to_dev(nbd->disk), &pid_attr); - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_recv = NULL; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); - - if (signal_pending(current)) { - ret = kernel_dequeue_signal(NULL); - dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n", - task_pid_nr(current), current->comm, ret); - mutex_lock(&nbd->tx_lock); - sock_shutdown(nbd); - mutex_unlock(&nbd->tx_lock); - ret = -ETIMEDOUT; - } return ret; } @@ -544,11 +526,8 @@ static int nbd_thread_send(void *data) { struct nbd_device *nbd = data; struct request *req; - unsigned long flags; - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_send = current; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); set_user_nice(current, MIN_NICE); while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) { @@ -557,17 +536,6 @@ static int nbd_thread_send(void *data) kthread_should_stop() || !list_empty(&nbd->waiting_queue)); - if (signal_pending(current)) { - int ret = kernel_dequeue_signal(NULL); - - dev_warn(nbd_to_dev(nbd), "pid %d, %s, got signal %d\n", - task_pid_nr(current), current->comm, ret); - mutex_lock(&nbd->tx_lock); - sock_shutdown(nbd); - mutex_unlock(&nbd->tx_lock); - break; - } - /* extract request */ if (list_empty(&nbd->waiting_queue)) continue; @@ -582,13 +550,7 @@ static int nbd_thread_send(void *data) nbd_handle_req(nbd, req); } - spin_lock_irqsave(&nbd->tasks_lock, flags); nbd->task_send = NULL; - spin_unlock_irqrestore(&nbd->tasks_lock, flags); - - /* Clear maybe pending signals */ - if (signal_pending(current)) - kernel_dequeue_signal(NULL); return 0; } @@ -636,6 +598,25 @@ static void nbd_request_handler(struct request_queue *q) } } +static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock) +{ + int ret = 0; + + spin_lock_irq(&nbd->sock_lock); + + if (nbd->sock) { + ret = -EBUSY; + goto out; + } + + nbd->sock = sock; + +out: + spin_unlock_irq(&nbd->sock_lock); + + return ret; +} + static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); @@ -668,32 +649,26 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, return 0; } - case NBD_CLEAR_SOCK: { - struct socket *sock = nbd->sock; - nbd->sock = NULL; + case NBD_CLEAR_SOCK: + sock_shutdown(nbd); nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); BUG_ON(!list_empty(&nbd->waiting_queue)); kill_bdev(bdev); - if (sock) - sockfd_put(sock); return 0; - } case NBD_SET_SOCK: { - struct socket *sock; int err; - if (nbd->sock) - return -EBUSY; - sock = sockfd_lookup(arg, &err); - if (sock) { - nbd->sock = sock; - if (max_part > 0) - bdev->bd_invalidated = 1; - nbd->disconnect = false; /* we're connected now */ - return 0; - } - return -EINVAL; + struct socket *sock = sockfd_lookup(arg, &err); + + if (!sock) + return err; + + err = nbd_set_socket(nbd, sock); + if (!err && max_part) + bdev->bd_invalidated = 1; + + return err; } case NBD_SET_BLKSIZE: @@ -734,7 +709,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, case NBD_DO_IT: { struct task_struct *thread; - struct socket *sock; int error; if (nbd->task_recv) @@ -769,14 +743,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, mutex_lock(&nbd->tx_lock); sock_shutdown(nbd); - sock = nbd->sock; - nbd->sock = NULL; nbd_clear_que(nbd); kill_bdev(bdev); queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); set_device_ro(bdev, false); - if (sock) - sockfd_put(sock); nbd->flags = 0; nbd->bytesize = 0; bdev->bd_inode->i_size = 0; @@ -1042,7 +1012,7 @@ static int __init nbd_init(void) nbd_dev[i].magic = NBD_MAGIC; INIT_LIST_HEAD(&nbd_dev[i].waiting_queue); spin_lock_init(&nbd_dev[i].queue_lock); - spin_lock_init(&nbd_dev[i].tasks_lock); + spin_lock_init(&nbd_dev[i].sock_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); mutex_init(&nbd_dev[i].tx_lock); init_timer(&nbd_dev[i].timeout_timer); -- cgit From 1f7b5cf1be4351e60cf8ae7aab976503dd73c5f8 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 12:01:34 +0100 Subject: nbd: Timeouts are not user requested disconnects It may be useful to know in the client that a connection timed out. The current code returns success for a timeout. This patch reports the error code -ETIMEDOUT for a timeout. Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 438f4dc549db..2e14e51b5ea3 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -57,6 +57,7 @@ struct nbd_device { int blksize; loff_t bytesize; int xmit_timeout; + bool timedout; bool disconnect; /* a disconnect has been requested by user */ struct timer_list timeout_timer; @@ -154,10 +155,9 @@ static void nbd_xmit_timeout(unsigned long arg) if (list_empty(&nbd->queue_head)) return; - nbd->disconnect = true; - spin_lock_irqsave(&nbd->sock_lock, flags); + nbd->timedout = true; if (nbd->sock) kernel_sock_shutdown(nbd->sock, SHUT_RDWR); @@ -754,7 +754,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, if (max_part > 0) blkdev_reread_part(bdev); if (nbd->disconnect) /* user requested, ignore socket errors */ - return 0; + error = 0; + if (nbd->timedout) + error = -ETIMEDOUT; + return error; } -- cgit From 0e4f0f6f63d3416a9e529d99febfe98545427b81 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 12:04:51 +0100 Subject: nbd: Cleanup reset of nbd and bdev after a disconnect Group all variables that are reset after a disconnect into reset functions. This patch adds two of these functions, nbd_reset() and nbd_bdev_reset(). Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 2e14e51b5ea3..34a46c32c24f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -617,6 +617,30 @@ out: return ret; } +/* Reset all properties of an NBD device */ +static void nbd_reset(struct nbd_device *nbd) +{ + nbd->disconnect = false; + nbd->timedout = false; + nbd->blksize = 1024; + nbd->bytesize = 0; + set_capacity(nbd->disk, 0); + nbd->flags = 0; + nbd->xmit_timeout = 0; + queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); + del_timer_sync(&nbd->timeout_timer); +} + +static void nbd_bdev_reset(struct block_device *bdev) +{ + set_device_ro(bdev, false); + bdev->bd_inode->i_size = 0; + if (max_part > 0) { + blkdev_reread_part(bdev); + bdev->bd_invalidated = 1; + } +} + static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); @@ -745,19 +769,15 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, sock_shutdown(nbd); nbd_clear_que(nbd); kill_bdev(bdev); - queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); - set_device_ro(bdev, false); - nbd->flags = 0; - nbd->bytesize = 0; - bdev->bd_inode->i_size = 0; - set_capacity(nbd->disk, 0); - if (max_part > 0) - blkdev_reread_part(bdev); + nbd_bdev_reset(bdev); + if (nbd->disconnect) /* user requested, ignore socket errors */ error = 0; if (nbd->timedout) error = -ETIMEDOUT; + nbd_reset(nbd); + return error; } @@ -1023,14 +1043,12 @@ static int __init nbd_init(void) nbd_dev[i].timeout_timer.data = (unsigned long)&nbd_dev[i]; init_waitqueue_head(&nbd_dev[i].active_wq); init_waitqueue_head(&nbd_dev[i].waiting_wq); - nbd_dev[i].blksize = 1024; - nbd_dev[i].bytesize = 0; disk->major = NBD_MAJOR; disk->first_minor = i << part_shift; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; sprintf(disk->disk_name, "nbd%d", i); - set_capacity(disk, 0); + nbd_reset(&nbd_dev[i]); add_disk(disk); } -- cgit From d02cf53107792df373558851d6162dc4e4ceb95a Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Thu, 29 Oct 2015 12:06:15 +0100 Subject: nbd: Move flag parsing to a function nbd changes properties of the blockdevice depending on flags that were received. This patch moves this flag parsing into a separate function nbd_parse_flags(). Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 34a46c32c24f..b67500d5b338 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -641,6 +641,18 @@ static void nbd_bdev_reset(struct block_device *bdev) } } +static void nbd_parse_flags(struct nbd_device *nbd, struct block_device *bdev) +{ + if (nbd->flags & NBD_FLAG_READ_ONLY) + set_device_ro(bdev, true); + 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); + else + blk_queue_flush(nbd->disk->queue, 0); +} + static int nbd_dev_dbg_init(struct nbd_device *nbd); static void nbd_dev_dbg_close(struct nbd_device *nbd); @@ -742,15 +754,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, mutex_unlock(&nbd->tx_lock); - if (nbd->flags & NBD_FLAG_READ_ONLY) - set_device_ro(bdev, true); - 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); - else - blk_queue_flush(nbd->disk->queue, 0); + nbd_parse_flags(nbd, bdev); thread = kthread_run(nbd_thread_send, nbd, "%s", nbd_name(nbd)); -- cgit From da6ccaaa79caca4f38b540b651238f87215217a2 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Thu, 14 Jan 2016 13:42:32 -0500 Subject: nbd: ratelimit error msgs after socket close Make the "Attempted send on closed socket" error messages generated in nbd_request_handler() ratelimited. When the nbd socket is shutdown, the nbd_request_handler() function emits an error message for every request remaining in its queue. If the queue is large, this will spam a large amount of messages to the log. There's no need for a separate error message for each request, so this patch ratelimits it. In the specific case this was found, the system was virtual and the error messages were logged to the serial port, which overwhelmed it. Fixes: 4d48a542b427 ("nbd: fix I/O hang on disconnected nbds") Signed-off-by: Dan Streetman Signed-off-by: Markus Pargmann --- 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 b67500d5b338..4c5d94146aa3 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -580,8 +580,8 @@ static void nbd_request_handler(struct request_queue *q) req, req->cmd_type); if (unlikely(!nbd->sock)) { - dev_err(disk_to_dev(nbd->disk), - "Attempted send on closed socket\n"); + dev_err_ratelimited(disk_to_dev(nbd->disk), + "Attempted send on closed socket\n"); req->errors++; nbd_end_request(nbd, req); spin_lock_irq(q->queue_lock); -- cgit From 89fee59b504f86925894fcc9ba79d5c933842f93 Mon Sep 17 00:00:00 2001 From: Marcin Ślusarz Date: Tue, 19 Jan 2016 20:03:03 +0100 Subject: perf tools: handle spaces in file names obtained from /proc/pid/maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steam frequently puts game binaries in folders with spaces. Note: "(deleted)" markers are now treated as part of the file name. Signed-off-by: Marcin Ślusarz Acked-by: Namhyung Kim Fixes: 6064803313ba ("perf tools: Use sscanf for parsing /proc/pid/maps") Link: http://lkml.kernel.org/r/20160119190303.GA17579@marcin-Inspiron-7720 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 85155e91b61b..7bad5c3fa7b7 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -282,7 +282,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, strcpy(execname, ""); /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ - n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n", + n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %[^\n]\n", &event->mmap2.start, &event->mmap2.len, prot, &event->mmap2.pgoff, &event->mmap2.maj, &event->mmap2.min, -- cgit From e9c4bcdd349eb00f6c704450a063b3dcbea25864 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 30 Nov 2015 10:02:20 +0100 Subject: perf symbols: add Java demangling support Add Java function descriptor demangling support. Something bfd cannot do. Use the JAVA_DEMANGLE_NORET flag to avoid decoding the return type of functions. Signed-off-by: Stephane Eranian Cc: Adrian Hunter Cc: Andi Kleen Cc: Carl Love Cc: David Ahern Cc: Jiri Olsa Cc: John McCutchan Cc: Namhyung Kim Cc: Pawel Moll Cc: Peter Zijlstra Cc: Sonny Rao Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1448874143-7269-2-git-send-email-eranian@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/Build | 1 + tools/perf/util/demangle-java.c | 199 ++++++++++++++++++++++++++++++++++++++++ tools/perf/util/demangle-java.h | 10 ++ tools/perf/util/symbol-elf.c | 3 + 4 files changed, 213 insertions(+) create mode 100644 tools/perf/util/demangle-java.c create mode 100644 tools/perf/util/demangle-java.h diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 5eec53a3f4ac..edae107416b6 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -105,6 +105,7 @@ libperf-y += scripting-engines/ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o +libperf-y += demangle-java.o CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c new file mode 100644 index 000000000000..3e6062ab2cdd --- /dev/null +++ b/tools/perf/util/demangle-java.c @@ -0,0 +1,199 @@ +#include +#include +#include +#include "util.h" +#include "debug.h" +#include "symbol.h" + +#include "demangle-java.h" + +enum { + MODE_PREFIX = 0, + MODE_CLASS = 1, + MODE_FUNC = 2, + MODE_TYPE = 3, + MODE_CTYPE = 3, /* class arg */ +}; + +#define BASE_ENT(c, n) [c - 'A']=n +static const char *base_types['Z' - 'A' + 1] = { + BASE_ENT('B', "byte" ), + BASE_ENT('C', "char" ), + BASE_ENT('D', "double" ), + BASE_ENT('F', "float" ), + BASE_ENT('I', "int" ), + BASE_ENT('J', "long" ), + BASE_ENT('S', "short" ), + BASE_ENT('Z', "bool" ), +}; + +/* + * demangle Java symbol between str and end positions and stores + * up to maxlen characters into buf. The parser starts in mode. + * + * Use MODE_PREFIX to process entire prototype till end position + * Use MODE_TYPE to process return type if str starts on return type char + * + * Return: + * success: buf + * error : NULL + */ +static char * +__demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode) +{ + int rlen = 0; + int array = 0; + int narg = 0; + const char *q; + + if (!end) + end = str + strlen(str); + + for (q = str; q != end; q++) { + + if (rlen == (maxlen - 1)) + break; + + switch (*q) { + case 'L': + if (mode == MODE_PREFIX || mode == MODE_CTYPE) { + if (mode == MODE_CTYPE) { + if (narg) + rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); + narg++; + } + rlen += scnprintf(buf + rlen, maxlen - rlen, "class "); + if (mode == MODE_PREFIX) + mode = MODE_CLASS; + } else + buf[rlen++] = *q; + break; + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + if (mode == MODE_TYPE) { + if (narg) + rlen += scnprintf(buf + rlen, maxlen - rlen, ", "); + rlen += scnprintf(buf + rlen, maxlen - rlen, "%s", base_types[*q - 'A']); + while (array--) + rlen += scnprintf(buf + rlen, maxlen - rlen, "[]"); + array = 0; + narg++; + } else + buf[rlen++] = *q; + break; + case 'V': + if (mode == MODE_TYPE) { + rlen += scnprintf(buf + rlen, maxlen - rlen, "void"); + while (array--) + rlen += scnprintf(buf + rlen, maxlen - rlen, "[]"); + array = 0; + } else + buf[rlen++] = *q; + break; + case '[': + if (mode != MODE_TYPE) + goto error; + array++; + break; + case '(': + if (mode != MODE_FUNC) + goto error; + buf[rlen++] = *q; + mode = MODE_TYPE; + break; + case ')': + if (mode != MODE_TYPE) + goto error; + buf[rlen++] = *q; + narg = 0; + break; + case ';': + if (mode != MODE_CLASS && mode != MODE_CTYPE) + goto error; + /* safe because at least one other char to process */ + if (isalpha(*(q + 1))) + rlen += scnprintf(buf + rlen, maxlen - rlen, "."); + if (mode == MODE_CLASS) + mode = MODE_FUNC; + else if (mode == MODE_CTYPE) + mode = MODE_TYPE; + break; + case '/': + if (mode != MODE_CLASS && mode != MODE_CTYPE) + goto error; + rlen += scnprintf(buf + rlen, maxlen - rlen, "."); + break; + default : + buf[rlen++] = *q; + } + } + buf[rlen] = '\0'; + return buf; +error: + return NULL; +} + +/* + * Demangle Java function signature (openJDK, not GCJ) + * input: + * str: string to parse. String is not modified + * flags: comobination of JAVA_DEMANGLE_* flags to modify demangling + * return: + * if input can be demangled, then a newly allocated string is returned. + * if input cannot be demangled, then NULL is returned + * + * Note: caller is responsible for freeing demangled string + */ +char * +java_demangle_sym(const char *str, int flags) +{ + char *buf, *ptr; + char *p; + size_t len, l1 = 0; + + if (!str) + return NULL; + + /* find start of retunr type */ + p = strrchr(str, ')'); + if (!p) + return NULL; + + /* + * expansion factor estimated to 3x + */ + len = strlen(str) * 3 + 1; + buf = malloc(len); + if (!buf) + return NULL; + + buf[0] = '\0'; + if (!(flags & JAVA_DEMANGLE_NORET)) { + /* + * get return type first + */ + ptr = __demangle_java_sym(p + 1, NULL, buf, len, MODE_TYPE); + if (!ptr) + goto error; + + /* add space between return type and function prototype */ + l1 = strlen(buf); + buf[l1++] = ' '; + } + + /* process function up to return type */ + ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX); + if (!ptr) + goto error; + + return buf; +error: + free(buf); + return NULL; +} diff --git a/tools/perf/util/demangle-java.h b/tools/perf/util/demangle-java.h new file mode 100644 index 000000000000..a981c1f968fe --- /dev/null +++ b/tools/perf/util/demangle-java.h @@ -0,0 +1,10 @@ +#ifndef __PERF_DEMANGLE_JAVA +#define __PERF_DEMANGLE_JAVA 1 +/* + * demangle function flags + */ +#define JAVA_DEMANGLE_NORET 0x1 /* do not process return type */ + +char * java_demangle_sym(const char *str, int flags); + +#endif /* __PERF_DEMANGLE_JAVA */ diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 562b8ebeae5b..b1dd68f358fc 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -6,6 +6,7 @@ #include #include "symbol.h" +#include "demangle-java.h" #include "machine.h" #include "vdso.h" #include @@ -1077,6 +1078,8 @@ new_symbol: demangle_flags = DMGL_PARAMS | DMGL_ANSI; demangled = bfd_demangle(NULL, elf_name, demangle_flags); + if (demangled == NULL) + demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET); if (demangled != NULL) elf_name = demangled; } -- cgit From 8ee4646038e47d065d35703e3e343136c4cd42aa Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 30 Nov 2015 10:02:21 +0100 Subject: perf build: Add libcrypto feature detection Will be used to generate build-ids in the jitdump code. Signed-off-by: Stephane Eranian Cc: Adrian Hunter Cc: Andi Kleen Cc: Carl Love Cc: David Ahern Cc: Jiri Olsa Cc: John McCutchan Cc: Namhyung Kim Cc: Pawel Moll Cc: Peter Zijlstra Cc: Sonny Rao Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1448874143-7269-3-git-send-email-eranian@google.com [ tools/perf/Makefile.perf comment about NO_LIBCRYPTO and added it to tests/make ] 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-libcrypto.c | 17 +++++++++++++++++ tools/perf/Makefile.perf | 3 +++ tools/perf/config/Makefile | 11 +++++++++++ tools/perf/tests/make | 2 ++ 7 files changed, 44 insertions(+) create mode 100644 tools/build/feature/test-libcrypto.c diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 7bff2ea831cf..6b7707270aa3 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -46,6 +46,7 @@ FEATURE_TESTS_BASIC := \ libpython \ libpython-version \ libslang \ + libcrypto \ libunwind \ pthread-attr-setaffinity-np \ stackprotector-all \ @@ -87,6 +88,7 @@ FEATURE_DISPLAY ?= \ libperl \ libpython \ libslang \ + libcrypto \ libunwind \ libdw-dwarf-unwind \ zlib \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index bf8f0352264d..c5f4c417428d 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -23,6 +23,7 @@ FILES= \ test-libpython.bin \ test-libpython-version.bin \ test-libslang.bin \ + test-libcrypto.bin \ test-libunwind.bin \ test-libunwind-debug-frame.bin \ test-pthread-attr-setaffinity-np.bin \ @@ -105,6 +106,9 @@ $(OUTPUT)test-libaudit.bin: $(OUTPUT)test-libslang.bin: $(BUILD) -I/usr/include/slang -lslang +$(OUTPUT)test-libcrypto.bin: + $(BUILD) -lcrypto + $(OUTPUT)test-gtk2.bin: $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c index 81025cade45f..e499a36c1e4a 100644 --- a/tools/build/feature/test-all.c +++ b/tools/build/feature/test-all.c @@ -129,6 +129,10 @@ # include "test-bpf.c" #undef main +#define main main_test_libcrypto +# include "test-libcrypto.c" +#undef main + int main(int argc, char *argv[]) { main_test_libpython(); @@ -158,6 +162,7 @@ int main(int argc, char *argv[]) main_test_lzma(); main_test_get_cpuid(); main_test_bpf(); + main_test_libcrypto(); return 0; } diff --git a/tools/build/feature/test-libcrypto.c b/tools/build/feature/test-libcrypto.c new file mode 100644 index 000000000000..bd79dc7f28d3 --- /dev/null +++ b/tools/build/feature/test-libcrypto.c @@ -0,0 +1,17 @@ +#include +#include + +int main(void) +{ + MD5_CTX context; + unsigned char md[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; + unsigned char dat[] = "12345"; + + MD5_Init(&context); + MD5_Update(&context, &dat[0], sizeof(dat)); + MD5_Final(&md[0], &context); + + SHA1(&dat[0], sizeof(dat), &md[0]); + + return 0; +} diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 0ef3d97d7954..d404117810a7 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -58,6 +58,9 @@ include config/utilities.mak # # Define NO_LIBBIONIC if you do not want bionic support # +# Define NO_LIBCRYPTO if you do not want libcrypto (openssl) support +# used for generating build-ids for ELFs generated by jitdump. +# # Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support # for dwarf backtrace post unwind. # diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 0045a5ddd0ca..f7aeaf303f5a 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -404,6 +404,17 @@ ifndef NO_LIBAUDIT endif endif +ifndef NO_LIBCRYPTO + ifneq ($(feature-libcrypto), 1) + msg := $(warning No libcrypto.h found, disables jitted code injection, please install libssl-devel or libssl-dev); + NO_LIBCRYPTO := 1 + else + CFLAGS += -DHAVE_LIBCRYPTO_SUPPORT + EXTLIBS += -lcrypto + $(call detected,CONFIG_CRYPTO) + endif +endif + ifdef NO_NEWT NO_SLANG=1 endif diff --git a/tools/perf/tests/make b/tools/perf/tests/make index 12dcae7aa515..cac15d93aea6 100644 --- a/tools/perf/tests/make +++ b/tools/perf/tests/make @@ -80,6 +80,7 @@ make_no_libaudit := NO_LIBAUDIT=1 make_no_libbionic := NO_LIBBIONIC=1 make_no_auxtrace := NO_AUXTRACE=1 make_no_libbpf := NO_LIBBPF=1 +make_no_libcrypto := NO_LIBCRYPTO=1 make_tags := tags make_cscope := cscope make_help := help @@ -103,6 +104,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 +make_minimal += NO_LIBCRYPTO=1 # $(run) contains all available tests run := make_pure -- cgit From 921f3fadbc48c7c3799b415b895297cd476cf7f1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 22 Jan 2016 18:41:00 -0300 Subject: perf inject: Make sure mmap records are ordered when injecting build_ids To make sure the mmap records are ordered correctly and so that the correct especially due to jitted code mmaps. We cannot generate the buildid hit list and inject the jit mmaps (will come right after this patch) in at the same time for now. Signed-off-by: Stephane Eranian Cc: Adrian Hunter Cc: Andi Kleen Cc: Carl Love Cc: David Ahern Cc: Jiri Olsa Cc: John McCutchan Cc: Namhyung Kim Cc: Pawel Moll Cc: Peter Zijlstra Cc: Sonny Rao Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1448874143-7269-3-git-send-email-eranian@google.com [ Carved out from a larger patch ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 0022e02ed31a..6567baedd92a 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -755,6 +755,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) if (inject.session == NULL) return -1; + if (inject.build_ids) { + /* + * to make sure the mmap records are ordered correctly + * and so that the correct especially due to jitted code + * mmaps. We cannot generate the buildid hit list and + * inject the jit mmaps at the same time for now. + */ + inject.tool.ordered_events = true; + inject.tool.ordering_requires_timestamps = true; + } + ret = symbol__init(&inject.session->header.env); if (ret < 0) goto out_delete; -- cgit From 9b07e27f88b9cd785cdb23f9a2231c12521dda94 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 30 Nov 2015 10:02:21 +0100 Subject: perf inject: Add jitdump mmap injection support This patch adds a --jit/-j option to perf inject. This options injects MMAP records into the perf.data file to cover the jitted code mmaps. It also emits ELF images for each function in the jidump file. Those images are created where the jitdump file is. The MMAP records point to that location as well. Typical flow: $ perf record -k mono -- java -agentpath:libpjvmti.so java_class $ perf inject --jit -i perf.data -o perf.data.jitted $ perf report -i perf.data.jitted Note that jitdump.h support is not limited to Java, it works with any jitted environment modified to emit the jitdump file format, include those where code can be jitted multiple times and moved around. The jitdump.h format is adapted from the Oprofile project. The genelf.c (ELF binary generation) depends on MD5 hash encoding for the buildid. To enable this, libssl-dev must be installed. If not, then genelf.c defaults to using urandom to generate the buildid, which is not ideal. The Makefile auto-detects the presence on libssl-dev. This version mmaps the jitdump file to create a marker MMAP record in the perf.data file. The marker is used to detect jitdump and cause perf inject to inject the jitted mmaps and generate ELF images for jitted functions. In V8, the following fixes and changes were made among other things: - the jidump header format include a new flags field to be used to carry information about the configuration of the runtime agent. Contributed by: Adrian Hunter - Fix mmap pgoff: MMAP event pgoff must be the offset within the ELF file at which the code resides. Contributed by: Adrian Hunter - Fix ELF virtual addresses: perf tools expect the ELF virtual addresses of dynamic objects to match the file offset. Contributed by: Adrian Hunter - JIT MMAP injection does not obey finished_round semantics. JIT MMAP injection injects all MMAP events in one go, so it does not obey finished_round semantics, so drop the finished_round events from the output perf.data file. Contributed by: Adrian Hunter Signed-off-by: Stephane Eranian Cc: Adrian Hunter Cc: Andi Kleen Cc: Carl Love Cc: David Ahern Cc: Jiri Olsa Cc: John McCutchan Cc: Namhyung Kim Cc: Pawel Moll Cc: Peter Zijlstra Cc: Sonny Rao Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1448874143-7269-3-git-send-email-eranian@google.com [ Moved inject.build_ids ordering bits to a separate patch, fixed the NO_LIBELF=1 build ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-inject.txt | 7 + tools/perf/builtin-inject.c | 98 ++++- tools/perf/util/Build | 2 + tools/perf/util/genelf.c | 442 ++++++++++++++++++++ tools/perf/util/genelf.h | 63 +++ tools/perf/util/jit.h | 15 + tools/perf/util/jitdump.c | 670 +++++++++++++++++++++++++++++++ tools/perf/util/jitdump.h | 124 ++++++ 8 files changed, 1418 insertions(+), 3 deletions(-) create mode 100644 tools/perf/util/genelf.c create mode 100644 tools/perf/util/genelf.h create mode 100644 tools/perf/util/jit.h create mode 100644 tools/perf/util/jitdump.c create mode 100644 tools/perf/util/jitdump.h diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt index 0b1cedeef895..87b2588d1cbd 100644 --- a/tools/perf/Documentation/perf-inject.txt +++ b/tools/perf/Documentation/perf-inject.txt @@ -53,6 +53,13 @@ include::itrace.txt[] --strip:: Use with --itrace to strip out non-synthesized events. +-j:: +--jit:: + Process jitdump files by injecting the mmap records corresponding to jitted + functions. This option also generates the ELF images for each jitted function + found in the jitdumps files captured in the input perf.data file. Use this option + if you are monitoring environment using JIT runtimes, such as Java, DART or V8. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6567baedd92a..b38445f08c2f 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -17,6 +17,7 @@ #include "util/build-id.h" #include "util/data.h" #include "util/auxtrace.h" +#include "util/jit.h" #include @@ -29,6 +30,7 @@ struct perf_inject { bool sched_stat; bool have_auxtrace; bool strip; + bool jit_mode; const char *input_name; struct perf_data_file output; u64 bytes_written; @@ -71,6 +73,15 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool, return perf_event__repipe_synth(tool, event); } +#ifdef HAVE_LIBELF_SUPPORT +static int perf_event__drop_oe(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, + struct ordered_events *oe __maybe_unused) +{ + return 0; +} +#endif + static int perf_event__repipe_op2_synth(struct perf_tool *tool, union perf_event *event, struct perf_session *session @@ -234,6 +245,27 @@ static int perf_event__repipe_mmap(struct perf_tool *tool, return err; } +#ifdef HAVE_LIBELF_SUPPORT +static int perf_event__jit_repipe_mmap(struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct perf_inject *inject = container_of(tool, struct perf_inject, tool); + u64 n = 0; + + /* + * if jit marker, then inject jit mmaps and generate ELF images + */ + if (!jit_process(inject->session, &inject->output, machine, + event->mmap.filename, sample->pid, &n)) { + inject->bytes_written += n; + return 0; + } + return perf_event__repipe_mmap(tool, event, sample, machine); +} +#endif + static int perf_event__repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -247,6 +279,27 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool, return err; } +#ifdef HAVE_LIBELF_SUPPORT +static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, + union perf_event *event, + struct perf_sample *sample, + struct machine *machine) +{ + struct perf_inject *inject = container_of(tool, struct perf_inject, tool); + u64 n = 0; + + /* + * if jit marker, then inject jit mmaps and generate ELF images + */ + if (!jit_process(inject->session, &inject->output, machine, + event->mmap2.filename, sample->pid, &n)) { + inject->bytes_written += n; + return 0; + } + return perf_event__repipe_mmap2(tool, event, sample, machine); +} +#endif + static int perf_event__repipe_fork(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, @@ -664,6 +717,23 @@ static int __cmd_inject(struct perf_inject *inject) return ret; } +#ifdef HAVE_LIBELF_SUPPORT +static int +jit_validate_events(struct perf_session *session) +{ + struct perf_evsel *evsel; + + /* + * check that all events use CLOCK_MONOTONIC + */ + evlist__for_each(session->evlist, evsel) { + if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) + return -1; + } + return 0; +} +#endif + int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) { struct perf_inject inject = { @@ -703,7 +773,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) }; int ret; - const struct option options[] = { + struct option options[] = { OPT_BOOLEAN('b', "build-ids", &inject.build_ids, "Inject build-ids into the output stream"), OPT_STRING('i', "input", &inject.input_name, "file", @@ -713,6 +783,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), + OPT_BOOLEAN('j', "jit", &inject.jit_mode, "merge jitdump files into perf.data file"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show build ids, etc)"), OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", @@ -729,7 +800,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) "perf inject []", NULL }; - +#ifndef HAVE_LIBELF_SUPPORT + set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true); +#endif argc = parse_options(argc, argv, options, inject_usage, 0); /* @@ -765,7 +838,26 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } - +#ifdef HAVE_LIBELF_SUPPORT + if (inject.jit_mode) { + /* + * validate event is using the correct clockid + */ + if (jit_validate_events(inject.session)) { + fprintf(stderr, "error, jitted code must be sampled with perf record -k 1\n"); + return -1; + } + inject.tool.mmap2 = perf_event__jit_repipe_mmap2; + inject.tool.mmap = perf_event__jit_repipe_mmap; + inject.tool.ordered_events = true; + inject.tool.ordering_requires_timestamps = true; + /* + * JIT MMAP injection injects all MMAP events in one go, so it + * does not obey finished_round semantics. + */ + inject.tool.finished_round = perf_event__drop_oe; + } +#endif ret = symbol__init(&inject.session->header.env); if (ret < 0) goto out_delete; diff --git a/tools/perf/util/Build b/tools/perf/util/Build index edae107416b6..52a4a806ee2f 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -106,6 +106,8 @@ libperf-y += scripting-engines/ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o +libperf-$(CONFIG_LIBELF) += jitdump.o +libperf-$(CONFIG_LIBELF) += genelf.o CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c new file mode 100644 index 000000000000..145f8116ef56 --- /dev/null +++ b/tools/perf/util/genelf.c @@ -0,0 +1,442 @@ +/* + * genelf.c + * Copyright (C) 2014, Google, Inc + * + * Contributed by: + * Stephane Eranian + * + * Released under the GPL v2. (and only v2, not any later version) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "perf.h" +#include "genelf.h" +#include "../util/jitdump.h" + +#define JVMTI + +#define BUILD_ID_URANDOM /* different uuid for each run */ + +#ifdef HAVE_LIBCRYPTO + +#define BUILD_ID_MD5 +#undef BUILD_ID_SHA /* does not seem to work well when linked with Java */ +#undef BUILD_ID_URANDOM /* different uuid for each run */ + +#ifdef BUILD_ID_SHA +#include +#endif + +#ifdef BUILD_ID_MD5 +#include +#endif +#endif + + +typedef struct { + unsigned int namesz; /* Size of entry's owner string */ + unsigned int descsz; /* Size of the note descriptor */ + unsigned int type; /* Interpretation of the descriptor */ + char name[0]; /* Start of the name+desc data */ +} Elf_Note; + +struct options { + char *output; + int fd; +}; + +static char shd_string_table[] = { + 0, + '.', 't', 'e', 'x', 't', 0, /* 1 */ + '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /* 7 */ + '.', 's', 'y', 'm', 't', 'a', 'b', 0, /* 17 */ + '.', 's', 't', 'r', 't', 'a', 'b', 0, /* 25 */ + '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */ + '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */ + '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */ + '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */ +}; + +static struct buildid_note { + Elf_Note desc; /* descsz: size of build-id, must be multiple of 4 */ + char name[4]; /* GNU\0 */ + char build_id[20]; +} bnote; + +static Elf_Sym symtab[]={ + /* symbol 0 MUST be the undefined symbol */ + { .st_name = 0, /* index in sym_string table */ + .st_info = ELF_ST_TYPE(STT_NOTYPE), + .st_shndx = 0, /* for now */ + .st_value = 0x0, + .st_other = ELF_ST_VIS(STV_DEFAULT), + .st_size = 0, + }, + { .st_name = 1, /* index in sym_string table */ + .st_info = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC), + .st_shndx = 1, + .st_value = 0, /* for now */ + .st_other = ELF_ST_VIS(STV_DEFAULT), + .st_size = 0, /* for now */ + } +}; + +#ifdef BUILD_ID_URANDOM +static void +gen_build_id(struct buildid_note *note, + unsigned long load_addr __maybe_unused, + const void *code __maybe_unused, + size_t csize __maybe_unused) +{ + int fd; + size_t sz = sizeof(note->build_id); + ssize_t sret; + + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + err(1, "cannot access /dev/urandom for builid"); + + sret = read(fd, note->build_id, sz); + + close(fd); + + if (sret != (ssize_t)sz) + memset(note->build_id, 0, sz); +} +#endif + +#ifdef BUILD_ID_SHA +static void +gen_build_id(struct buildid_note *note, + unsigned long load_addr __maybe_unused, + const void *code, + size_t csize) +{ + if (sizeof(note->build_id) < SHA_DIGEST_LENGTH) + errx(1, "build_id too small for SHA1"); + + SHA1(code, csize, (unsigned char *)note->build_id); +} +#endif + +#ifdef BUILD_ID_MD5 +static void +gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize) +{ + MD5_CTX context; + + if (sizeof(note->build_id) < 16) + errx(1, "build_id too small for MD5"); + + MD5_Init(&context); + MD5_Update(&context, &load_addr, sizeof(load_addr)); + MD5_Update(&context, code, csize); + MD5_Final((unsigned char *)note->build_id, &context); +} +#endif + +/* + * fd: file descriptor open for writing for the output file + * load_addr: code load address (could be zero, just used for buildid) + * sym: function name (for native code - used as the symbol) + * code: the native code + * csize: the code size in bytes + */ +int +jit_write_elf(int fd, uint64_t load_addr, const char *sym, + const void *code, int csize) +{ + Elf *e; + Elf_Data *d; + Elf_Scn *scn; + Elf_Ehdr *ehdr; + Elf_Shdr *shdr; + char *strsym = NULL; + int symlen; + int retval = -1; + + if (elf_version(EV_CURRENT) == EV_NONE) { + warnx("ELF initialization failed"); + return -1; + } + + e = elf_begin(fd, ELF_C_WRITE, NULL); + if (!e) { + warnx("elf_begin failed"); + goto error; + } + + /* + * setup ELF header + */ + ehdr = elf_newehdr(e); + if (!ehdr) { + warnx("cannot get ehdr"); + goto error; + } + + ehdr->e_ident[EI_DATA] = GEN_ELF_ENDIAN; + ehdr->e_ident[EI_CLASS] = GEN_ELF_CLASS; + ehdr->e_machine = GEN_ELF_ARCH; + ehdr->e_type = ET_DYN; + ehdr->e_entry = GEN_ELF_TEXT_OFFSET; + ehdr->e_version = EV_CURRENT; + ehdr->e_shstrndx= 2; /* shdr index for section name */ + + /* + * setup text section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + goto error; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + goto error; + } + + d->d_align = 16; + d->d_off = 0LL; + d->d_buf = (void *)code; + d->d_type = ELF_T_BYTE; + d->d_size = csize; + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + goto error; + } + + shdr->sh_name = 1; + shdr->sh_type = SHT_PROGBITS; + shdr->sh_addr = GEN_ELF_TEXT_OFFSET; + shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC; + shdr->sh_entsize = 0; + + /* + * setup section headers string table + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + goto error; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + goto error; + } + + d->d_align = 1; + d->d_off = 0LL; + d->d_buf = shd_string_table; + d->d_type = ELF_T_BYTE; + d->d_size = sizeof(shd_string_table); + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + goto error; + } + + shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */ + shdr->sh_type = SHT_STRTAB; + shdr->sh_flags = 0; + shdr->sh_entsize = 0; + + /* + * setup symtab section + */ + symtab[1].st_size = csize; + symtab[1].st_value = GEN_ELF_TEXT_OFFSET; + + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + goto error; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + goto error; + } + + d->d_align = 8; + d->d_off = 0LL; + d->d_buf = symtab; + d->d_type = ELF_T_SYM; + d->d_size = sizeof(symtab); + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + goto error; + } + + shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */ + shdr->sh_type = SHT_SYMTAB; + shdr->sh_flags = 0; + shdr->sh_entsize = sizeof(Elf_Sym); + shdr->sh_link = 4; /* index of .strtab section */ + + /* + * setup symbols string table + * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry + */ + symlen = 2 + strlen(sym); + strsym = calloc(1, symlen); + if (!strsym) { + warnx("cannot allocate strsym"); + goto error; + } + strcpy(strsym + 1, sym); + + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + goto error; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + goto error; + } + + d->d_align = 1; + d->d_off = 0LL; + d->d_buf = strsym; + d->d_type = ELF_T_BYTE; + d->d_size = symlen; + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + goto error; + } + + shdr->sh_name = 25; /* offset in shd_string_table */ + shdr->sh_type = SHT_STRTAB; + shdr->sh_flags = 0; + shdr->sh_entsize = 0; + + /* + * setup build-id section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + goto error; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + goto error; + } + + /* + * build-id generation + */ + gen_build_id(&bnote, load_addr, code, csize); + bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */ + bnote.desc.descsz = sizeof(bnote.build_id); + bnote.desc.type = NT_GNU_BUILD_ID; + strcpy(bnote.name, "GNU"); + + d->d_align = 4; + d->d_off = 0LL; + d->d_buf = &bnote; + d->d_type = ELF_T_BYTE; + d->d_size = sizeof(bnote); + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + goto error; + } + + shdr->sh_name = 33; /* offset in shd_string_table */ + shdr->sh_type = SHT_NOTE; + shdr->sh_addr = 0x0; + shdr->sh_flags = SHF_ALLOC; + shdr->sh_size = sizeof(bnote); + shdr->sh_entsize = 0; + + if (elf_update(e, ELF_C_WRITE) < 0) { + warnx("elf_update 4 failed"); + goto error; + } + + retval = 0; +error: + (void)elf_end(e); + + free(strsym); + + + return retval; +} + +#ifndef JVMTI + +static unsigned char x86_code[] = { + 0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */ + 0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */ + 0xCD, 0x80 /* int $0x80 */ +}; + +static struct options options; + +int main(int argc, char **argv) +{ + int c, fd, ret; + + while ((c = getopt(argc, argv, "o:h")) != -1) { + switch (c) { + case 'o': + options.output = optarg; + break; + case 'h': + printf("Usage: genelf -o output_file [-h]\n"); + return 0; + default: + errx(1, "unknown option"); + } + } + + fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666); + if (fd == -1) + err(1, "cannot create file %s", options.output); + + ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code)); + close(fd); + + if (ret != 0) + unlink(options.output); + + return ret; +} +#endif diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h new file mode 100644 index 000000000000..d8e9ece13c8b --- /dev/null +++ b/tools/perf/util/genelf.h @@ -0,0 +1,63 @@ +#ifndef __GENELF_H__ +#define __GENELF_H__ + +/* genelf.c */ +extern int jit_write_elf(int fd, uint64_t code_addr, const char *sym, + const void *code, int csize); + +#if defined(__arm__) +#define GEN_ELF_ARCH EM_ARM +#define GEN_ELF_ENDIAN ELFDATA2LSB +#define GEN_ELF_CLASS ELFCLASS32 +#elif defined(__aarch64__) +#define GEN_ELF_ARCH EM_AARCH64 +#define GEN_ELF_ENDIAN ELFDATA2LSB +#define GEN_ELF_CLASS ELFCLASS64 +#elif defined(__x86_64__) +#define GEN_ELF_ARCH EM_X86_64 +#define GEN_ELF_ENDIAN ELFDATA2LSB +#define GEN_ELF_CLASS ELFCLASS64 +#elif defined(__i386__) +#define GEN_ELF_ARCH EM_386 +#define GEN_ELF_ENDIAN ELFDATA2LSB +#define GEN_ELF_CLASS ELFCLASS32 +#elif defined(__ppcle__) +#define GEN_ELF_ARCH EM_PPC +#define GEN_ELF_ENDIAN ELFDATA2LSB +#define GEN_ELF_CLASS ELFCLASS64 +#elif defined(__powerpc__) +#define GEN_ELF_ARCH EM_PPC64 +#define GEN_ELF_ENDIAN ELFDATA2MSB +#define GEN_ELF_CLASS ELFCLASS64 +#elif defined(__powerpcle__) +#define GEN_ELF_ARCH EM_PPC64 +#define GEN_ELF_ENDIAN ELFDATA2LSB +#define GEN_ELF_CLASS ELFCLASS64 +#else +#error "unsupported architecture" +#endif + +#if GEN_ELF_CLASS == ELFCLASS64 +#define elf_newehdr elf64_newehdr +#define elf_getshdr elf64_getshdr +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define ELF_ST_TYPE(a) ELF64_ST_TYPE(a) +#define ELF_ST_BIND(a) ELF64_ST_BIND(a) +#define ELF_ST_VIS(a) ELF64_ST_VISIBILITY(a) +#else +#define elf_newehdr elf32_newehdr +#define elf_getshdr elf32_getshdr +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define ELF_ST_TYPE(a) ELF32_ST_TYPE(a) +#define ELF_ST_BIND(a) ELF32_ST_BIND(a) +#define ELF_ST_VIS(a) ELF32_ST_VISIBILITY(a) +#endif + +/* The .text section is directly after the ELF header */ +#define GEN_ELF_TEXT_OFFSET sizeof(Elf_Ehdr) + +#endif diff --git a/tools/perf/util/jit.h b/tools/perf/util/jit.h new file mode 100644 index 000000000000..a1e99da0715a --- /dev/null +++ b/tools/perf/util/jit.h @@ -0,0 +1,15 @@ +#ifndef __JIT_H__ +#define __JIT_H__ + +#include + +extern int jit_process(struct perf_session *session, + struct perf_data_file *output, + struct machine *machine, + char *filename, + pid_t pid, + u64 *nbytes); + +extern int jit_inject_record(const char *filename); + +#endif /* __JIT_H__ */ diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c new file mode 100644 index 000000000000..9f7a01289efe --- /dev/null +++ b/tools/perf/util/jitdump.c @@ -0,0 +1,670 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "event.h" +#include "debug.h" +#include "evlist.h" +#include "symbol.h" +#include "strlist.h" +#include + +#include "session.h" +#include "jit.h" +#include "jitdump.h" +#include "genelf.h" +#include "../builtin.h" + +struct jit_buf_desc { + struct perf_data_file *output; + struct perf_session *session; + struct machine *machine; + union jr_entry *entry; + void *buf; + uint64_t sample_type; + size_t bufsize; + FILE *in; + bool needs_bswap; /* handles cross-endianess */ + void *debug_data; + size_t nr_debug_entries; + uint32_t code_load_count; + u64 bytes_written; + struct rb_root code_root; + char dir[PATH_MAX]; +}; + +struct debug_line_info { + unsigned long vma; + unsigned int lineno; + /* The filename format is unspecified, absolute path, relative etc. */ + char const filename[0]; +}; + +struct jit_tool { + struct perf_tool tool; + struct perf_data_file output; + struct perf_data_file input; + u64 bytes_written; +}; + +#define hmax(a, b) ((a) > (b) ? (a) : (b)) +#define get_jit_tool(t) (container_of(tool, struct jit_tool, tool)) + +static int +jit_emit_elf(char *filename, + const char *sym, + uint64_t code_addr, + const void *code, + int csize) +{ + int ret, fd; + + if (verbose > 0) + fprintf(stderr, "write ELF image %s\n", filename); + + fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); + if (fd == -1) { + pr_warning("cannot create jit ELF %s: %s\n", filename, strerror(errno)); + return -1; + } + + ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize); + + close(fd); + + if (ret) + unlink(filename); + + return ret; +} + +static void +jit_close(struct jit_buf_desc *jd) +{ + if (!(jd && jd->in)) + return; + funlockfile(jd->in); + fclose(jd->in); + jd->in = NULL; +} + +static int +jit_open(struct jit_buf_desc *jd, const char *name) +{ + struct jitheader header; + struct jr_prefix *prefix; + ssize_t bs, bsz = 0; + void *n, *buf = NULL; + int ret, retval = -1; + + jd->in = fopen(name, "r"); + if (!jd->in) + return -1; + + bsz = hmax(sizeof(header), sizeof(*prefix)); + + buf = malloc(bsz); + if (!buf) + goto error; + + /* + * protect from writer modifying the file while we are reading it + */ + flockfile(jd->in); + + ret = fread(buf, sizeof(header), 1, jd->in); + if (ret != 1) + goto error; + + memcpy(&header, buf, sizeof(header)); + + if (header.magic != JITHEADER_MAGIC) { + if (header.magic != JITHEADER_MAGIC_SW) + goto error; + jd->needs_bswap = true; + } + + if (jd->needs_bswap) { + header.version = bswap_32(header.version); + header.total_size = bswap_32(header.total_size); + header.pid = bswap_32(header.pid); + header.elf_mach = bswap_32(header.elf_mach); + header.timestamp = bswap_64(header.timestamp); + header.flags = bswap_64(header.flags); + } + + if (verbose > 2) + pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n", + header.version, + header.total_size, + (unsigned long long)header.timestamp, + header.pid, + header.elf_mach); + + if (header.flags & JITDUMP_FLAGS_RESERVED) { + pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", + (unsigned long long)header.flags & JITDUMP_FLAGS_RESERVED); + goto error; + } + + bs = header.total_size - sizeof(header); + + if (bs > bsz) { + n = realloc(buf, bs); + if (!n) + goto error; + bsz = bs; + buf = n; + /* read extra we do not know about */ + ret = fread(buf, bs - bsz, 1, jd->in); + if (ret != 1) + goto error; + } + /* + * keep dirname for generating files and mmap records + */ + strcpy(jd->dir, name); + dirname(jd->dir); + + return 0; +error: + funlockfile(jd->in); + fclose(jd->in); + return retval; +} + +static union jr_entry * +jit_get_next_entry(struct jit_buf_desc *jd) +{ + struct jr_prefix *prefix; + union jr_entry *jr; + void *addr; + size_t bs, size; + int id, ret; + + if (!(jd && jd->in)) + return NULL; + + if (jd->buf == NULL) { + size_t sz = getpagesize(); + if (sz < sizeof(*prefix)) + sz = sizeof(*prefix); + + jd->buf = malloc(sz); + if (jd->buf == NULL) + return NULL; + + jd->bufsize = sz; + } + + prefix = jd->buf; + + /* + * file is still locked at this point + */ + ret = fread(prefix, sizeof(*prefix), 1, jd->in); + if (ret != 1) + return NULL; + + if (jd->needs_bswap) { + prefix->id = bswap_32(prefix->id); + prefix->total_size = bswap_32(prefix->total_size); + prefix->timestamp = bswap_64(prefix->timestamp); + } + id = prefix->id; + size = prefix->total_size; + + bs = (size_t)size; + if (bs < sizeof(*prefix)) + return NULL; + + if (id >= JIT_CODE_MAX) { + pr_warning("next_entry: unknown prefix %d, skipping\n", id); + return NULL; + } + if (bs > jd->bufsize) { + void *n; + n = realloc(jd->buf, bs); + if (!n) + return NULL; + jd->buf = n; + jd->bufsize = bs; + } + + addr = ((void *)jd->buf) + sizeof(*prefix); + + ret = fread(addr, bs - sizeof(*prefix), 1, jd->in); + if (ret != 1) + return NULL; + + jr = (union jr_entry *)jd->buf; + + switch(id) { + case JIT_CODE_DEBUG_INFO: + if (jd->needs_bswap) { + uint64_t n; + jr->info.code_addr = bswap_64(jr->info.code_addr); + jr->info.nr_entry = bswap_64(jr->info.nr_entry); + for (n = 0 ; n < jr->info.nr_entry; n++) { + jr->info.entries[n].addr = bswap_64(jr->info.entries[n].addr); + jr->info.entries[n].lineno = bswap_32(jr->info.entries[n].lineno); + jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim); + } + } + break; + case JIT_CODE_CLOSE: + break; + case JIT_CODE_LOAD: + if (jd->needs_bswap) { + jr->load.pid = bswap_32(jr->load.pid); + jr->load.tid = bswap_32(jr->load.tid); + jr->load.vma = bswap_64(jr->load.vma); + jr->load.code_addr = bswap_64(jr->load.code_addr); + jr->load.code_size = bswap_64(jr->load.code_size); + jr->load.code_index= bswap_64(jr->load.code_index); + } + jd->code_load_count++; + break; + case JIT_CODE_MOVE: + if (jd->needs_bswap) { + jr->move.pid = bswap_32(jr->move.pid); + jr->move.tid = bswap_32(jr->move.tid); + jr->move.vma = bswap_64(jr->move.vma); + jr->move.old_code_addr = bswap_64(jr->move.old_code_addr); + jr->move.new_code_addr = bswap_64(jr->move.new_code_addr); + jr->move.code_size = bswap_64(jr->move.code_size); + jr->move.code_index = bswap_64(jr->move.code_index); + } + break; + case JIT_CODE_MAX: + default: + return NULL; + } + return jr; +} + +static int +jit_inject_event(struct jit_buf_desc *jd, union perf_event *event) +{ + ssize_t size; + + size = perf_data_file__write(jd->output, event, event->header.size); + if (size < 0) + return -1; + + jd->bytes_written += size; + return 0; +} + +static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) +{ + struct perf_sample sample; + union perf_event *event; + struct perf_tool *tool = jd->session->tool; + uint64_t code, addr; + uintptr_t uaddr; + char *filename; + struct stat st; + size_t size; + u16 idr_size; + const char *sym; + uint32_t count; + int ret, csize; + pid_t pid, tid; + struct { + u32 pid, tid; + u64 time; + } *id; + + pid = jr->load.pid; + tid = jr->load.tid; + csize = jr->load.code_size; + addr = jr->load.code_addr; + sym = (void *)((unsigned long)jr + sizeof(jr->load)); + code = (unsigned long)jr + jr->load.p.total_size - csize; + count = jr->load.code_index; + idr_size = jd->machine->id_hdr_size; + + event = calloc(1, sizeof(*event) + idr_size); + if (!event) + return -1; + + filename = event->mmap2.filename; + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%u.so", + jd->dir, + pid, + count); + + size++; /* for \0 */ + + size = PERF_ALIGN(size, sizeof(u64)); + uaddr = (uintptr_t)code; + ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize); + + if (jd->debug_data && jd->nr_debug_entries) { + free(jd->debug_data); + jd->debug_data = NULL; + jd->nr_debug_entries = 0; + } + + if (ret) { + free(event); + return -1; + } + if (stat(filename, &st)) + memset(&st, 0, sizeof(stat)); + + event->mmap2.header.type = PERF_RECORD_MMAP2; + event->mmap2.header.misc = PERF_RECORD_MISC_USER; + event->mmap2.header.size = (sizeof(event->mmap2) - + (sizeof(event->mmap2.filename) - size) + idr_size); + + event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; + event->mmap2.start = addr; + event->mmap2.len = csize; + event->mmap2.pid = pid; + event->mmap2.tid = tid; + event->mmap2.ino = st.st_ino; + event->mmap2.maj = major(st.st_dev); + event->mmap2.min = minor(st.st_dev); + event->mmap2.prot = st.st_mode; + event->mmap2.flags = MAP_SHARED; + event->mmap2.ino_generation = 1; + + id = (void *)((unsigned long)event + event->mmap.header.size - idr_size); + if (jd->sample_type & PERF_SAMPLE_TID) { + id->pid = pid; + id->tid = tid; + } + if (jd->sample_type & PERF_SAMPLE_TIME) + id->time = jr->load.p.timestamp; + + /* + * create pseudo sample to induce dso hit increment + * use first address as sample address + */ + memset(&sample, 0, sizeof(sample)); + sample.pid = pid; + sample.tid = tid; + sample.time = id->time; + sample.ip = addr; + + ret = perf_event__process_mmap2(tool, event, &sample, jd->machine); + if (ret) + return ret; + + ret = jit_inject_event(jd, event); + /* + * mark dso as use to generate buildid in the header + */ + if (!ret) + build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine); + + return ret; +} + +static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) +{ + struct perf_sample sample; + union perf_event *event; + struct perf_tool *tool = jd->session->tool; + char *filename; + size_t size; + struct stat st; + u16 idr_size; + int ret; + pid_t pid, tid; + struct { + u32 pid, tid; + u64 time; + } *id; + + pid = jr->move.pid; + tid = jr->move.tid; + idr_size = jd->machine->id_hdr_size; + + /* + * +16 to account for sample_id_all (hack) + */ + event = calloc(1, sizeof(*event) + 16); + if (!event) + return -1; + + filename = event->mmap2.filename; + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%"PRIu64, + jd->dir, + pid, + jr->move.code_index); + + size++; /* for \0 */ + + if (stat(filename, &st)) + memset(&st, 0, sizeof(stat)); + + size = PERF_ALIGN(size, sizeof(u64)); + + event->mmap2.header.type = PERF_RECORD_MMAP2; + event->mmap2.header.misc = PERF_RECORD_MISC_USER; + event->mmap2.header.size = (sizeof(event->mmap2) - + (sizeof(event->mmap2.filename) - size) + idr_size); + event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; + event->mmap2.start = jr->move.new_code_addr; + event->mmap2.len = jr->move.code_size; + event->mmap2.pid = pid; + event->mmap2.tid = tid; + event->mmap2.ino = st.st_ino; + event->mmap2.maj = major(st.st_dev); + event->mmap2.min = minor(st.st_dev); + event->mmap2.prot = st.st_mode; + event->mmap2.flags = MAP_SHARED; + event->mmap2.ino_generation = 1; + + id = (void *)((unsigned long)event + event->mmap.header.size - idr_size); + if (jd->sample_type & PERF_SAMPLE_TID) { + id->pid = pid; + id->tid = tid; + } + if (jd->sample_type & PERF_SAMPLE_TIME) + id->time = jr->load.p.timestamp; + + /* + * create pseudo sample to induce dso hit increment + * use first address as sample address + */ + memset(&sample, 0, sizeof(sample)); + sample.pid = pid; + sample.tid = tid; + sample.time = id->time; + sample.ip = jr->move.new_code_addr; + + ret = perf_event__process_mmap2(tool, event, &sample, jd->machine); + if (ret) + return ret; + + ret = jit_inject_event(jd, event); + if (!ret) + build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine); + + return ret; +} + +static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) +{ + void *data; + size_t sz; + + if (!(jd && jr)) + return -1; + + sz = jr->prefix.total_size - sizeof(jr->info); + data = malloc(sz); + if (!data) + return -1; + + memcpy(data, &jr->info.entries, sz); + + jd->debug_data = data; + + /* + * we must use nr_entry instead of size here because + * we cannot distinguish actual entry from padding otherwise + */ + jd->nr_debug_entries = jr->info.nr_entry; + + return 0; +} + +static int +jit_process_dump(struct jit_buf_desc *jd) +{ + union jr_entry *jr; + int ret; + + while ((jr = jit_get_next_entry(jd))) { + switch(jr->prefix.id) { + case JIT_CODE_LOAD: + ret = jit_repipe_code_load(jd, jr); + break; + case JIT_CODE_MOVE: + ret = jit_repipe_code_move(jd, jr); + break; + case JIT_CODE_DEBUG_INFO: + ret = jit_repipe_debug_info(jd, jr); + break; + default: + ret = 0; + continue; + } + } + return ret; +} + +static int +jit_inject(struct jit_buf_desc *jd, char *path) +{ + int ret; + + if (verbose > 0) + fprintf(stderr, "injecting: %s\n", path); + + ret = jit_open(jd, path); + if (ret) + return -1; + + ret = jit_process_dump(jd); + + jit_close(jd); + + if (verbose > 0) + fprintf(stderr, "injected: %s (%d)\n", path, ret); + + return 0; +} + +/* + * File must be with pattern .../jit-XXXX.dump + * where XXXX is the PID of the process which did the mmap() + * as captured in the RECORD_MMAP record + */ +static int +jit_detect(char *mmap_name, pid_t pid) + { + char *p; + char *end = NULL; + pid_t pid2; + + if (verbose > 2) + fprintf(stderr, "jit marker trying : %s\n", mmap_name); + /* + * get file name + */ + p = strrchr(mmap_name, '/'); + if (!p) + return -1; + + /* + * match prefix + */ + if (strncmp(p, "/jit-", 5)) + return -1; + + /* + * skip prefix + */ + p += 5; + + /* + * must be followed by a pid + */ + if (!isdigit(*p)) + return -1; + + pid2 = (int)strtol(p, &end, 10); + if (!end) + return -1; + + /* + * pid does not match mmap pid + * pid==0 in system-wide mode (synthesized) + */ + if (pid && pid2 != pid) + return -1; + /* + * validate suffix + */ + if (strcmp(end, ".dump")) + return -1; + + if (verbose > 0) + fprintf(stderr, "jit marker found: %s\n", mmap_name); + + return 0; +} + +int +jit_process(struct perf_session *session, + struct perf_data_file *output, + struct machine *machine, + char *filename, + pid_t pid, + u64 *nbytes) +{ + struct perf_evsel *first; + struct jit_buf_desc jd; + int ret; + + /* + * first, detect marker mmap (i.e., the jitdump mmap) + */ + if (jit_detect(filename, pid)) + return -1; + + memset(&jd, 0, sizeof(jd)); + + jd.session = session; + jd.output = output; + jd.machine = machine; + + /* + * track sample_type to compute id_all layout + * perf sets the same sample type to all events as of now + */ + first = perf_evlist__first(session->evlist); + jd.sample_type = first->attr.sample_type; + + *nbytes = 0; + + ret = jit_inject(&jd, filename); + if (!ret) + *nbytes = jd.bytes_written; + + return ret; +} diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h new file mode 100644 index 000000000000..b66c1f503d9e --- /dev/null +++ b/tools/perf/util/jitdump.h @@ -0,0 +1,124 @@ +/* + * jitdump.h: jitted code info encapsulation file format + * + * Adapted from OProfile GPLv2 support jidump.h: + * Copyright 2007 OProfile authors + * Jens Wilke + * Daniel Hansel + * Copyright IBM Corporation 2007 + */ +#ifndef JITDUMP_H +#define JITDUMP_H + +#include +#include +#include + +/* JiTD */ +#define JITHEADER_MAGIC 0x4A695444 +#define JITHEADER_MAGIC_SW 0x4454694A + +#define PADDING_8ALIGNED(x) ((((x) + 7) & 7) ^ 7) + +#define JITHEADER_VERSION 1 + +enum jitdump_flags_bits { + JITDUMP_FLAGS_MAX_BIT, +}; + +#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \ + (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0) + +struct jitheader { + uint32_t magic; /* characters "jItD" */ + uint32_t version; /* header version */ + uint32_t total_size; /* total size of header */ + uint32_t elf_mach; /* elf mach target */ + uint32_t pad1; /* reserved */ + uint32_t pid; /* JIT process id */ + uint64_t timestamp; /* timestamp */ + uint64_t flags; /* flags */ +}; + +enum jit_record_type { + JIT_CODE_LOAD = 0, + JIT_CODE_MOVE = 1, + JIT_CODE_DEBUG_INFO = 2, + JIT_CODE_CLOSE = 3, + + JIT_CODE_MAX, +}; + +/* record prefix (mandatory in each record) */ +struct jr_prefix { + uint32_t id; + uint32_t total_size; + uint64_t timestamp; +}; + +struct jr_code_load { + struct jr_prefix p; + + uint32_t pid; + uint32_t tid; + uint64_t vma; + uint64_t code_addr; + uint64_t code_size; + uint64_t code_index; +}; + +struct jr_code_close { + struct jr_prefix p; +}; + +struct jr_code_move { + struct jr_prefix p; + + uint32_t pid; + uint32_t tid; + uint64_t vma; + uint64_t old_code_addr; + uint64_t new_code_addr; + uint64_t code_size; + uint64_t code_index; +}; + +struct debug_entry { + uint64_t addr; + int lineno; /* source line number starting at 1 */ + int discrim; /* column discriminator, 0 is default */ + const char name[0]; /* null terminated filename, \xff\0 if same as previous entry */ +}; + +struct jr_code_debug_info { + struct jr_prefix p; + + uint64_t code_addr; + uint64_t nr_entry; + struct debug_entry entries[0]; +}; + +union jr_entry { + struct jr_code_debug_info info; + struct jr_code_close close; + struct jr_code_load load; + struct jr_code_move move; + struct jr_prefix prefix; +}; + +static inline struct debug_entry * +debug_entry_next(struct debug_entry *ent) +{ + void *a = ent + 1; + size_t l = strlen(ent->name) + 1; + return a + l; +} + +static inline char * +debug_entry_file(struct debug_entry *ent) +{ + void *a = ent + 1; + return a; +} + +#endif /* !JITDUMP_H */ -- cgit From d81221ff9406a3918084bfaed752894e82c5d44b Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Thu, 4 Feb 2016 16:29:01 +0000 Subject: ASoC: arizona: Add support for SNDRV_PCM_RATE_KNOT The Arizona CODECs support several rates that do not have simple defines in ALSA. This patch adds support for SNDRV_PCM_RATE_KNOT so that users can open stream at these rates. As part of this we should always set constraints in arizona_startup, currently we only set the constraints if we already have a clock to limit rates to that family of sample rates. This patch updates this to set a constraint of all rates supported by the chip if we do not already know which family of rates to limit to. Finally we also reduce the list of rates supported in the constraints to only include those that are supported on current parts. Signed-off-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.c | 62 ++++++++++++---------------------------------- sound/soc/codecs/arizona.h | 2 ++ sound/soc/codecs/cs47l24.c | 2 +- sound/soc/codecs/wm5102.c | 2 +- sound/soc/codecs/wm5110.c | 2 +- sound/soc/codecs/wm8997.c | 2 +- sound/soc/codecs/wm8998.c | 2 +- 7 files changed, 23 insertions(+), 51 deletions(-) diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 33143fe1de0b..a32cfb85f1ca 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -1398,29 +1398,6 @@ static const int arizona_48k_bclk_rates[] = { 24576000, }; -static const unsigned int arizona_48k_rates[] = { - 12000, - 24000, - 48000, - 96000, - 192000, - 384000, - 768000, - 4000, - 8000, - 16000, - 32000, - 64000, - 128000, - 256000, - 512000, -}; - -static const struct snd_pcm_hw_constraint_list arizona_48k_constraint = { - .count = ARRAY_SIZE(arizona_48k_rates), - .list = arizona_48k_rates, -}; - static const int arizona_44k1_bclk_rates[] = { -1, 44100, @@ -1443,22 +1420,7 @@ static const int arizona_44k1_bclk_rates[] = { 22579200, }; -static const unsigned int arizona_44k1_rates[] = { - 11025, - 22050, - 44100, - 88200, - 176400, - 352800, - 705600, -}; - -static const struct snd_pcm_hw_constraint_list arizona_44k1_constraint = { - .count = ARRAY_SIZE(arizona_44k1_rates), - .list = arizona_44k1_rates, -}; - -static int arizona_sr_vals[] = { +static const unsigned int arizona_sr_vals[] = { 0, 12000, 24000, @@ -1485,13 +1447,21 @@ static int arizona_sr_vals[] = { 512000, }; +#define ARIZONA_48K_RATE_MASK 0x0F003E +#define ARIZONA_44K1_RATE_MASK 0x003E00 +#define ARIZONA_RATE_MASK (ARIZONA_48K_RATE_MASK | ARIZONA_44K1_RATE_MASK) + +static const struct snd_pcm_hw_constraint_list arizona_constraint = { + .count = ARRAY_SIZE(arizona_sr_vals), + .list = arizona_sr_vals, +}; + static int arizona_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_codec *codec = dai->codec; struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona_dai_priv *dai_priv = &priv->dai[dai->id - 1]; - const struct snd_pcm_hw_constraint_list *constraint; unsigned int base_rate; if (!substream->runtime) @@ -1509,16 +1479,15 @@ static int arizona_startup(struct snd_pcm_substream *substream, } if (base_rate == 0) - return 0; - - if (base_rate % 8000) - constraint = &arizona_44k1_constraint; + dai_priv->constraint.mask = ARIZONA_RATE_MASK; + else if (base_rate % 8000) + dai_priv->constraint.mask = ARIZONA_44K1_RATE_MASK; else - constraint = &arizona_48k_constraint; + dai_priv->constraint.mask = ARIZONA_48K_RATE_MASK; return snd_pcm_hw_constraint_list(substream->runtime, 0, SNDRV_PCM_HW_PARAM_RATE, - constraint); + &dai_priv->constraint); } static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec, @@ -1911,6 +1880,7 @@ int arizona_init_dai(struct arizona_priv *priv, int id) struct arizona_dai_priv *dai_priv = &priv->dai[id]; dai_priv->clk = ARIZONA_CLK_SYSCLK; + dai_priv->constraint = arizona_constraint; return 0; } diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 0c64a5731513..1ea8e4ecf8d4 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -68,6 +68,8 @@ struct wm_adsp; struct arizona_dai_priv { int clk; + + struct snd_pcm_hw_constraint_list constraint; }; struct arizona_priv { diff --git a/sound/soc/codecs/cs47l24.c b/sound/soc/codecs/cs47l24.c index b8d3cd031d7d..576087bda330 100644 --- a/sound/soc/codecs/cs47l24.c +++ b/sound/soc/codecs/cs47l24.c @@ -923,7 +923,7 @@ static int cs47l24_set_fll(struct snd_soc_codec *codec, int fll_id, int source, } } -#define CS47L24_RATES SNDRV_PCM_RATE_8000_192000 +#define CS47L24_RATES SNDRV_PCM_RATE_KNOT #define CS47L24_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index aa1e96ab4bd2..a8b3e3f701f9 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -1738,7 +1738,7 @@ static int wm5102_set_fll(struct snd_soc_codec *codec, int fll_id, int source, } } -#define WM5102_RATES SNDRV_PCM_RATE_8000_192000 +#define WM5102_RATES SNDRV_PCM_RATE_KNOT #define WM5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 92b6a6a564df..aa47955b68af 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2024,7 +2024,7 @@ static int wm5110_set_fll(struct snd_soc_codec *codec, int fll_id, int source, } } -#define WM5110_RATES SNDRV_PCM_RATE_8000_192000 +#define WM5110_RATES SNDRV_PCM_RATE_KNOT #define WM5110_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index b4dba3a02aba..52d766efe14f 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -943,7 +943,7 @@ static int wm8997_set_fll(struct snd_soc_codec *codec, int fll_id, int source, } } -#define WM8997_RATES SNDRV_PCM_RATE_8000_192000 +#define WM8997_RATES SNDRV_PCM_RATE_KNOT #define WM8997_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 7719bc509e50..012396074a8a 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1170,7 +1170,7 @@ static const struct snd_soc_dapm_route wm8998_dapm_routes[] = { { "DRC1 Signal Activity", NULL, "DRC1R" }, }; -#define WM8998_RATES SNDRV_PCM_RATE_8000_192000 +#define WM8998_RATES SNDRV_PCM_RATE_KNOT #define WM8998_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) -- cgit From 27d6e7d1c96c9f51379e0feb972fec26029098bc Mon Sep 17 00:00:00 2001 From: Andreas Irestål Date: Thu, 4 Feb 2016 15:05:19 +0100 Subject: ASoC: adau17x1: Cache writes when core clock is disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some configurations, the dai registers get written before the bias level is changed in the codec driver. This leads to a situation where an initial write to the serial port register gets ignored, and future writes may as well, since regmap thinks that the codec already holds the value. More specifically, configuring the codec as i2s master would in fact result in the codec running as slave, a situation where no i2s clocks are generated and hence no data is transferred. This change makes sure that regmap only caches writes when the core clock is disabled, and syncs regmap whenever enabling the core clock again. Signed-off-by: Andreas Irestål Acked-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- sound/soc/codecs/adau1761.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 2f12477e539e..e7136b1956a3 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c @@ -456,13 +456,17 @@ static int adau1761_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: + regcache_cache_only(adau->regmap, false); regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, ADAU17X1_CLOCK_CONTROL_SYSCLK_EN); + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) + regcache_sync(adau->regmap); break; case SND_SOC_BIAS_OFF: regmap_update_bits(adau->regmap, ADAU17X1_CLOCK_CONTROL, ADAU17X1_CLOCK_CONTROL_SYSCLK_EN, 0); + regcache_cache_only(adau->regmap, true); break; } @@ -783,6 +787,10 @@ int adau1761_probe(struct device *dev, struct regmap *regmap, if (ret) return ret; + /* Enable cache only mode as we could miss writes before bias level + * reaches standby and the core clock is enabled */ + regcache_cache_only(regmap, true); + return snd_soc_register_codec(dev, &adau1761_codec_driver, dai_drv, 1); } EXPORT_SYMBOL_GPL(adau1761_probe); -- cgit From 436e056c4ba368f13a5709a5a4a7f26fc238a5a6 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 3 Feb 2016 13:18:20 +0000 Subject: ASoC: mxs-saif: check BUSY bit in hw_params() only if not mclk_in_use If something else, typically a codec, has enabled mclk, the BUSY bit may be set when hw_params() is called without this being an error. This check thus causes intermittent failures to configure the sound device when used in such a manner. Fix this by making the test conditional on !saif->mclk_in_use. Signed-off-by: Mans Rullgard Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index c866ade28ad0..cd04eb7ee753 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -408,7 +408,7 @@ static int mxs_saif_hw_params(struct snd_pcm_substream *substream, } stat = __raw_readl(saif->base + SAIF_STAT); - if (stat & BM_SAIF_STAT_BUSY) { + if (!saif->mclk_in_use && (stat & BM_SAIF_STAT_BUSY)) { dev_err(cpu_dai->dev, "error: busy\n"); return -EBUSY; } -- cgit From 57e756d30268a0373cce97165bd57331554f4bfd Mon Sep 17 00:00:00 2001 From: "Felipe F. Tonello" Date: Fri, 29 Jan 2016 11:01:00 +0000 Subject: ASoC: fsl-asoc-card: add cs4271 and cs4272 support add cs4271 and cs42727 support for fsl-asoc-card Signed-off-by: Felipe F. Tonello Acked-by: Nicolin Chen Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl-asoc-card.txt | 9 +++++++++ sound/soc/fsl/Kconfig | 4 ++-- sound/soc/fsl/fsl-asoc-card.c | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt index ce55c0a6f757..943b36d1b81b 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt @@ -24,6 +24,9 @@ The compatible list for this generic sound card currently: "fsl,imx-audio-cs42888" + "fsl,imx-audio-cs427x" + (compatible with CS4271 and CS4272) + "fsl,imx-audio-wm8962" (compatible with Documentation/devicetree/bindings/sound/imx-audio-wm8962.txt) @@ -61,6 +64,12 @@ Optional properties: - audio-asrc : The phandle of ASRC. It can be absent if there's no need to add ASRC support via DPCM. +Optional unless SSI is selected as a CPU DAI: + + - mux-int-port : The internal port of the i.MX audio muxer (AUDMUX) + + - mux-ext-port : The external port of the i.MX audio muxer + Example: sound-cs42888 { compatible = "fsl,imx-audio-cs42888"; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 14dfdee05fd5..35aabf9dc503 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -292,8 +292,8 @@ config SND_SOC_FSL_ASOC_CARD select SND_SOC_FSL_SSI help ALSA SoC Audio support with ASRC feature for Freescale SoCs that have - ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888 - and SGTL5000. + ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888, + CS4271, CS4272 and SGTL5000. Say Y if you want to add support for Freescale Generic ASoC Sound Card. endif # SND_IMX_SOC diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 3d40797e3bcc..dffd549a0e2a 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -28,6 +28,8 @@ #include "../codecs/wm8962.h" #include "../codecs/wm8960.h" +#define CS427x_SYSCLK_MCLK 0 + #define RX 0 #define TX 1 @@ -535,6 +537,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT; priv->cpu_priv.slot_width = 32; priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; + } else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) { + codec_dai_name = "cs4271-hifi"; + priv->codec_priv.mclk_id = CS427x_SYSCLK_MCLK; + priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; } else if (of_device_is_compatible(np, "fsl,imx-audio-sgtl5000")) { codec_dai_name = "sgtl5000"; priv->codec_priv.mclk_id = SGTL5000_SYSCLK; @@ -692,6 +698,7 @@ fail: static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-ac97", }, { .compatible = "fsl,imx-audio-cs42888", }, + { .compatible = "fsl,imx-audio-cs427x", }, { .compatible = "fsl,imx-audio-sgtl5000", }, { .compatible = "fsl,imx-audio-wm8962", }, { .compatible = "fsl,imx-audio-wm8960", }, -- cgit From 0c4b3c637ca5fe20fe513dbdee6f62166c97fed1 Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Thu, 4 Feb 2016 10:52:40 -0500 Subject: HID: multitouch: warn on sysfs group creation failure This adds a warning message stating that the sysfs group was not able to be created for the passed hid_device structure pointer with dev_warn. Signed-off-by: Nicholas Krause Reviewed-by: Benjamin Tissoires [jkosina@suse.cz: massaged changelog a bit] [jkosina@suse.cz: reformatted source] Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 296d4991560e..6adb788bbfca 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1133,6 +1133,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group); + if (ret) + dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n", + hdev->name); mt_set_maxcontacts(hdev); mt_set_input_mode(hdev); -- cgit From 59ee9c96dd5d1aa5f982d2849ed406af8d071134 Mon Sep 17 00:00:00 2001 From: Biao Huang Date: Wed, 3 Feb 2016 09:24:46 +0800 Subject: pinctrl: mediatek: Add gpio_request_enable support Implement the .gpio_request_enable() callbacks in struct pinmux_ops in mediatek pinctrl driver. Make sure that when gpio_request is called, GPIO on the pin is enabled. Signed-off-by: Biao Huang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c index 8cac73d9c382..b752f5aee6a4 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c @@ -43,6 +43,7 @@ #define MAX_GPIO_MODE_PER_REG 5 #define GPIO_MODE_BITS 3 +#define GPIO_MODE_PREFIX "GPIO" static const char * const mtk_gpio_functions[] = { "func0", "func1", "func2", "func3", @@ -733,12 +734,47 @@ static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev, return 0; } +static int mtk_pmx_find_gpio_mode(struct mtk_pinctrl *pctl, + unsigned offset) +{ + const struct mtk_desc_pin *pin = pctl->devdata->pins + offset; + const struct mtk_desc_function *func = pin->functions; + + while (func && func->name) { + if (!strncmp(func->name, GPIO_MODE_PREFIX, + sizeof(GPIO_MODE_PREFIX)-1)) + return func->muxval; + func++; + } + return -EINVAL; +} + +static int mtk_pmx_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + unsigned long muxval; + struct mtk_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + muxval = mtk_pmx_find_gpio_mode(pctl, offset); + + if (muxval < 0) { + dev_err(pctl->dev, "invalid gpio pin %d.\n", offset); + return -EINVAL; + } + + mtk_pmx_set_mode(pctldev, offset, muxval); + + return 0; +} + static const struct pinmux_ops mtk_pmx_ops = { .get_functions_count = mtk_pmx_get_funcs_cnt, .get_function_name = mtk_pmx_get_func_name, .get_function_groups = mtk_pmx_get_func_groups, .set_mux = mtk_pmx_set_mux, .gpio_set_direction = mtk_pmx_gpio_set_direction, + .gpio_request_enable = mtk_pmx_gpio_request_enable, }; static int mtk_gpio_direction_input(struct gpio_chip *chip, -- cgit From 9cd56ab89987f993a2774fe1793385bd23a7487c Mon Sep 17 00:00:00 2001 From: Julien Grossholtz Date: Wed, 13 Jan 2016 11:57:42 -0500 Subject: gpio: add bindings for TS-4800 gpio controller Device tree binding documentation for the TS-4800 GPIO controller. Signed-off-by: Julien Grossholtz [Point ngpios to gpio.txt] Signed-off-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-ts4800.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ts4800.txt diff --git a/Documentation/devicetree/bindings/gpio/gpio-ts4800.txt b/Documentation/devicetree/bindings/gpio/gpio-ts4800.txt new file mode 100644 index 000000000000..92ea9c8f6399 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-ts4800.txt @@ -0,0 +1,20 @@ +* TS-4800 FPGA's GPIO controller bindings + +Required properties: +- compatible: Must be "technologic,ts4800-gpio". +- #gpio-cells: Should be two. The first cell is the pin number. +- reg: Physical base address of the controller and length + of memory mapped region. + +Optional property: +- ngpios: See "gpio.txt" + +Example: + +gpio1: gpio { + compatible = "technologic,ts4800-gpio"; + reg = <0x10020 0x6>; + ngpios = <8>; + gpio-controller; + #gpio-cells = <2>; +}; -- cgit From 5041e791440a53930f06ce22deeb17a72e343ad0 Mon Sep 17 00:00:00 2001 From: Julien Grossholtz Date: Wed, 13 Jan 2016 11:57:43 -0500 Subject: gpio: add TS-4800 fpga GPIO support The TS-4800 GPIO driver provide support for the GPIOs available on the Technologic Sytems board FPGA. It allows to set direction and read/write states. It uses the generic gpio driver. Signed-off-by: Julien Grossholtz Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 ++++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-ts4800.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 drivers/gpio/gpio-ts4800.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 00f17673e7e0..77df86635480 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -382,6 +382,13 @@ config GPIO_TB10X select GENERIC_IRQ_CHIP select OF_GPIO +config GPIO_TS4800 + tristate "TS-4800 DIO blocks and compatibles" + depends on OF_GPIO + select GPIO_GENERIC + help + This driver support TS-4800 FPGA GPIO controllers. + config GPIO_TZ1090 bool "Toumaz Xenif TZ1090 GPIO support" depends on SOC_TZ1090 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index d4cc4f3d3674..2f5852daab0d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -99,6 +99,7 @@ obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o +obj-$(CONFIG_GPIO_TS4800) += gpio-ts4800.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c new file mode 100644 index 000000000000..c4908a45c523 --- /dev/null +++ b/drivers/gpio/gpio-ts4800.c @@ -0,0 +1,94 @@ +/* + * GPIO driver for the TS-4800 board + * + * Copyright (c) 2016 - Savoir-faire Linux + * + * 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 + +#define DEFAULT_PIN_NUMBER 16 +#define INPUT_REG_OFFSET 0x00 +#define OUTPUT_REG_OFFSET 0x02 +#define DIRECTION_REG_OFFSET 0x04 + +static int ts4800_gpio_probe(struct platform_device *pdev) +{ + struct device_node *node; + struct gpio_chip *chip; + struct resource *res; + void __iomem *base_addr; + int retval; + u32 ngpios; + + chip = devm_kzalloc(&pdev->dev, sizeof(struct gpio_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base_addr)) + return PTR_ERR(base_addr); + + node = pdev->dev.of_node; + if (!node) + return -EINVAL; + + retval = of_property_read_u32(node, "ngpios", &ngpios); + if (retval == -EINVAL) + ngpios = DEFAULT_PIN_NUMBER; + else if (retval) + return retval; + + retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET, + base_addr + OUTPUT_REG_OFFSET, NULL, + base_addr + DIRECTION_REG_OFFSET, NULL, + BGPIOF_BIG_ENDIAN & BGPIOF_BIG_ENDIAN_BYTE_ORDER); + if (retval) { + dev_err(&pdev->dev, "bgpio_init failed\n"); + return retval; + } + + chip->base = -1; + chip->label = dev_name(&pdev->dev); + chip->ngpio = ngpios; + + platform_set_drvdata(pdev, chip); + + return gpiochip_add_data(chip, NULL); +} + +static int ts4800_gpio_remove(struct platform_device *pdev) +{ + struct gpio_chip *chip = platform_get_drvdata(pdev); + + gpiochip_remove(chip); + + return 0; +} + +static const struct of_device_id ts4800_gpio_of_match[] = { + { .compatible = "technologic,ts4800-gpio", }, + {}, +}; + +static struct platform_driver ts4800_gpio_driver = { + .driver = { + .name = "ts4800-gpio", + .of_match_table = ts4800_gpio_of_match, + }, + .probe = ts4800_gpio_probe, + .remove = ts4800_gpio_remove, +}; + +module_platform_driver_probe(ts4800_gpio_driver, ts4800_gpio_probe); + +MODULE_AUTHOR("Julien Grossholtz "); +MODULE_DESCRIPTION("TS4800 FPGA GPIO driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 25cbac7716be6a8d5c57534645ca472d2e4be1fd Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 24 Jan 2016 00:30:08 +0900 Subject: pinctrl: tegra: move Tegra pinctrl drivers to sub-directory Tegra has several pinctrl drivers. Now it is reasonable enough to move them into drivers/pinctrl/tegra/. Signed-off-by: Masahiro Yamada Acked-by: Thierry Reding Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 32 +- drivers/pinctrl/Makefile | 8 +- drivers/pinctrl/pinctrl-tegra-xusb.c | 985 ----------- drivers/pinctrl/pinctrl-tegra.c | 747 --------- drivers/pinctrl/pinctrl-tegra.h | 194 --- drivers/pinctrl/pinctrl-tegra114.c | 1872 --------------------- drivers/pinctrl/pinctrl-tegra124.c | 2084 ----------------------- drivers/pinctrl/pinctrl-tegra20.c | 2252 ------------------------- drivers/pinctrl/pinctrl-tegra210.c | 1588 ------------------ drivers/pinctrl/pinctrl-tegra30.c | 2507 ---------------------------- drivers/pinctrl/tegra/Kconfig | 30 + drivers/pinctrl/tegra/Makefile | 7 + drivers/pinctrl/tegra/pinctrl-tegra-xusb.c | 985 +++++++++++ drivers/pinctrl/tegra/pinctrl-tegra.c | 747 +++++++++ drivers/pinctrl/tegra/pinctrl-tegra.h | 194 +++ drivers/pinctrl/tegra/pinctrl-tegra114.c | 1872 +++++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra124.c | 2084 +++++++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra20.c | 2252 +++++++++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra210.c | 1588 ++++++++++++++++++ drivers/pinctrl/tegra/pinctrl-tegra30.c | 2507 ++++++++++++++++++++++++++++ 20 files changed, 12268 insertions(+), 12267 deletions(-) delete mode 100644 drivers/pinctrl/pinctrl-tegra-xusb.c delete mode 100644 drivers/pinctrl/pinctrl-tegra.c delete mode 100644 drivers/pinctrl/pinctrl-tegra.h delete mode 100644 drivers/pinctrl/pinctrl-tegra114.c delete mode 100644 drivers/pinctrl/pinctrl-tegra124.c delete mode 100644 drivers/pinctrl/pinctrl-tegra20.c delete mode 100644 drivers/pinctrl/pinctrl-tegra210.c delete mode 100644 drivers/pinctrl/pinctrl-tegra30.c create mode 100644 drivers/pinctrl/tegra/Kconfig create mode 100644 drivers/pinctrl/tegra/Makefile create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra-xusb.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra.h create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra114.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra124.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra20.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra210.c create mode 100644 drivers/pinctrl/tegra/pinctrl-tegra30.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index f8405cdeb5fb..6ba67a619062 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -168,37 +168,6 @@ config PINCTRL_ST select PINCONF select GPIOLIB_IRQCHIP -config PINCTRL_TEGRA - bool - select PINMUX - select PINCONF - -config PINCTRL_TEGRA20 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA30 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA114 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA124 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA210 - bool - select PINCTRL_TEGRA - -config PINCTRL_TEGRA_XUSB - def_bool y if ARCH_TEGRA - select GENERIC_PHY - select PINCONF - select PINMUX - config PINCTRL_TZ1090 bool "Toumaz Xenif TZ1090 pin control driver" depends on SOC_TZ1090 @@ -259,6 +228,7 @@ source "drivers/pinctrl/sh-pfc/Kconfig" source "drivers/pinctrl/spear/Kconfig" source "drivers/pinctrl/stm32/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" +source "drivers/pinctrl/tegra/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/vt8500/Kconfig" source "drivers/pinctrl/mediatek/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index d25dcbd28dfa..e4e673e2a448 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -22,13 +22,7 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_SIRF) += sirf/ -obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o -obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o -obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o -obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o -obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o -obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o -obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o +obj-$(CONFIG_PINCTRL_TEGRA) += tegra/ obj-$(CONFIG_PINCTRL_TZ1090) += pinctrl-tz1090.o obj-$(CONFIG_PINCTRL_TZ1090_PDC) += pinctrl-tz1090-pdc.o obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c deleted file mode 100644 index bd3aa5a4fd6d..000000000000 --- a/drivers/pinctrl/pinctrl-tegra-xusb.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. - * - * 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 -#include -#include -#include - -#include - -#include "core.h" -#include "pinctrl-utils.h" - -#define XUSB_PADCTL_ELPG_PROGRAM 0x01c -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) -#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) - -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) - -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) -#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) - -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) -#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) - -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) -#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) - -struct tegra_xusb_padctl_function { - const char *name; - const char * const *groups; - unsigned int num_groups; -}; - -struct tegra_xusb_padctl_soc { - const struct pinctrl_pin_desc *pins; - unsigned int num_pins; - - const struct tegra_xusb_padctl_function *functions; - unsigned int num_functions; - - const struct tegra_xusb_padctl_lane *lanes; - unsigned int num_lanes; -}; - -struct tegra_xusb_padctl_lane { - const char *name; - - unsigned int offset; - unsigned int shift; - unsigned int mask; - unsigned int iddq; - - const unsigned int *funcs; - unsigned int num_funcs; -}; - -struct tegra_xusb_padctl { - struct device *dev; - void __iomem *regs; - struct mutex lock; - struct reset_control *rst; - - const struct tegra_xusb_padctl_soc *soc; - struct pinctrl_dev *pinctrl; - struct pinctrl_desc desc; - - struct phy_provider *provider; - struct phy *phys[2]; - - unsigned int enable; -}; - -static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, - unsigned long offset) -{ - writel(value, padctl->regs + offset); -} - -static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, - unsigned long offset) -{ - return readl(padctl->regs + offset); -} - -static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->num_pins; -} - -static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl, - unsigned int group) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->pins[group].name; -} - -static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl, - unsigned group, - const unsigned **pins, - unsigned *num_pins) -{ - /* - * For the tegra-xusb pad controller groups are synonomous - * with lanes/pins and there is always one lane/pin per group. - */ - *pins = &pinctrl->desc->pins[group].number; - *num_pins = 1; - - return 0; -} - -enum tegra_xusb_padctl_param { - TEGRA_XUSB_PADCTL_IDDQ, -}; - -static const struct tegra_xusb_padctl_property { - const char *name; - enum tegra_xusb_padctl_param param; -} properties[] = { - { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ }, -}; - -#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value)) -#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16) -#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff) - -static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl, - struct device_node *np, - struct pinctrl_map **maps, - unsigned int *reserved_maps, - unsigned int *num_maps) -{ - unsigned int i, reserve = 0, num_configs = 0; - unsigned long config, *configs = NULL; - const char *function, *group; - struct property *prop; - int err = 0; - u32 value; - - err = of_property_read_string(np, "nvidia,function", &function); - if (err < 0) { - if (err != -EINVAL) - return err; - - function = NULL; - } - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - err = of_property_read_u32(np, properties[i].name, &value); - if (err < 0) { - if (err == -EINVAL) - continue; - - goto out; - } - - config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value); - - err = pinctrl_utils_add_config(padctl->pinctrl, &configs, - &num_configs, config); - if (err < 0) - goto out; - } - - if (function) - reserve++; - - if (num_configs) - reserve++; - - err = of_property_count_strings(np, "nvidia,lanes"); - if (err < 0) - goto out; - - reserve *= err; - - err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps, - num_maps, reserve); - if (err < 0) - goto out; - - of_property_for_each_string(np, "nvidia,lanes", prop, group) { - if (function) { - err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps, - reserved_maps, num_maps, group, - function); - if (err < 0) - goto out; - } - - if (num_configs) { - err = pinctrl_utils_add_map_configs(padctl->pinctrl, - maps, reserved_maps, num_maps, group, - configs, num_configs, - PIN_MAP_TYPE_CONFIGS_GROUP); - if (err < 0) - goto out; - } - } - - err = 0; - -out: - kfree(configs); - return err; -} - -static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl, - struct device_node *parent, - struct pinctrl_map **maps, - unsigned int *num_maps) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - unsigned int reserved_maps = 0; - struct device_node *np; - int err; - - *num_maps = 0; - *maps = NULL; - - for_each_child_of_node(parent, np) { - err = tegra_xusb_padctl_parse_subnode(padctl, np, maps, - &reserved_maps, - num_maps); - if (err < 0) { - of_node_put(np); - return err; - } - } - - return 0; -} - -static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { - .get_groups_count = tegra_xusb_padctl_get_groups_count, - .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, -}; - -static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->num_functions; -} - -static const char * -tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl, - unsigned int function) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - return padctl->soc->functions[function].name; -} - -static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, - unsigned int function, - const char * const **groups, - unsigned * const num_groups) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - - *num_groups = padctl->soc->functions[function].num_groups; - *groups = padctl->soc->functions[function].groups; - - return 0; -} - -static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl, - unsigned int function, - unsigned int group) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - unsigned int i; - u32 value; - - lane = &padctl->soc->lanes[group]; - - for (i = 0; i < lane->num_funcs; i++) - if (lane->funcs[i] == function) - break; - - if (i >= lane->num_funcs) - return -EINVAL; - - value = padctl_readl(padctl, lane->offset); - value &= ~(lane->mask << lane->shift); - value |= i << lane->shift; - padctl_writel(padctl, value, lane->offset); - - return 0; -} - -static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { - .get_functions_count = tegra_xusb_padctl_get_functions_count, - .get_function_name = tegra_xusb_padctl_get_function_name, - .get_function_groups = tegra_xusb_padctl_get_function_groups, - .set_mux = tegra_xusb_padctl_pinmux_set, -}; - -static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, - unsigned int group, - unsigned long *config) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - enum tegra_xusb_padctl_param param; - u32 value; - - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config); - lane = &padctl->soc->lanes[group]; - - switch (param) { - case TEGRA_XUSB_PADCTL_IDDQ: - /* lanes with iddq == 0 don't support this parameter */ - if (lane->iddq == 0) - return -EINVAL; - - value = padctl_readl(padctl, lane->offset); - - if (value & BIT(lane->iddq)) - value = 0; - else - value = 1; - - *config = TEGRA_XUSB_PADCTL_PACK(param, value); - break; - - default: - dev_err(padctl->dev, "invalid configuration parameter: %04x\n", - param); - return -ENOTSUPP; - } - - return 0; -} - -static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl, - unsigned int group, - unsigned long *configs, - unsigned int num_configs) -{ - struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); - const struct tegra_xusb_padctl_lane *lane; - enum tegra_xusb_padctl_param param; - unsigned long value; - unsigned int i; - u32 regval; - - lane = &padctl->soc->lanes[group]; - - for (i = 0; i < num_configs; i++) { - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]); - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]); - - switch (param) { - case TEGRA_XUSB_PADCTL_IDDQ: - /* lanes with iddq == 0 don't support this parameter */ - if (lane->iddq == 0) - return -EINVAL; - - regval = padctl_readl(padctl, lane->offset); - - if (value) - regval &= ~BIT(lane->iddq); - else - regval |= BIT(lane->iddq); - - padctl_writel(padctl, regval, lane->offset); - break; - - default: - dev_err(padctl->dev, - "invalid configuration parameter: %04x\n", - param); - return -ENOTSUPP; - } - } - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static const char *strip_prefix(const char *s) -{ - const char *comma = strchr(s, ','); - if (!comma) - return s; - - return comma + 1; -} - -static void -tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl, - struct seq_file *s, - unsigned int group) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - unsigned long config, value; - int err; - - config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0); - - err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group, - &config); - if (err < 0) - continue; - - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); - - seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name), - value); - } -} - -static void -tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl, - struct seq_file *s, - unsigned long config) -{ - enum tegra_xusb_padctl_param param; - const char *name = "unknown"; - unsigned long value; - unsigned int i; - - param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config); - value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); - - for (i = 0; i < ARRAY_SIZE(properties); i++) { - if (properties[i].param == param) { - name = properties[i].name; - break; - } - } - - seq_printf(s, "%s=%lu", strip_prefix(name), value); -} -#endif - -static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { - .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get, - .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set, -#ifdef CONFIG_DEBUG_FS - .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show, - .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show, -#endif -}; - -static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) -{ - u32 value; - - mutex_lock(&padctl->lock); - - if (padctl->enable++ > 0) - goto out; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; -} - -static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) -{ - u32 value; - - mutex_lock(&padctl->lock); - - if (WARN_ON(padctl->enable == 0)) - goto out; - - if (--padctl->enable > 0) - goto out; - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - - usleep_range(100, 200); - - value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); - value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; - padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); - -out: - mutex_unlock(&padctl->lock); - return 0; -} - -static int tegra_xusb_phy_init(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - - return tegra_xusb_padctl_enable(padctl); -} - -static int tegra_xusb_phy_exit(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - - return tegra_xusb_padctl_disable(padctl); -} - -static int pcie_phy_power_on(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - unsigned long timeout; - int err = -ETIMEDOUT; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); - value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | - XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | - XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - timeout = jiffies + msecs_to_jiffies(50); - - while (time_before(jiffies, timeout)) { - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { - err = 0; - break; - } - - usleep_range(100, 200); - } - - return err; -} - -static int pcie_phy_power_off(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); - - return 0; -} - -static const struct phy_ops pcie_phy_ops = { - .init = tegra_xusb_phy_init, - .exit = tegra_xusb_phy_exit, - .power_on = pcie_phy_power_on, - .power_off = pcie_phy_power_off, - .owner = THIS_MODULE, -}; - -static int sata_phy_power_on(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - unsigned long timeout; - int err = -ETIMEDOUT; - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; - value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - timeout = jiffies + msecs_to_jiffies(50); - - while (time_before(jiffies, timeout)) { - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { - err = 0; - break; - } - - usleep_range(100, 200); - } - - return err; -} - -static int sata_phy_power_off(struct phy *phy) -{ - struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); - u32 value; - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; - value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); - - value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; - value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; - padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); - - return 0; -} - -static const struct phy_ops sata_phy_ops = { - .init = tegra_xusb_phy_init, - .exit = tegra_xusb_phy_exit, - .power_on = sata_phy_power_on, - .power_off = sata_phy_power_off, - .owner = THIS_MODULE, -}; - -static struct phy *tegra_xusb_padctl_xlate(struct device *dev, - struct of_phandle_args *args) -{ - struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); - unsigned int index = args->args[0]; - - if (args->args_count <= 0) - return ERR_PTR(-EINVAL); - - if (index >= ARRAY_SIZE(padctl->phys)) - return ERR_PTR(-EINVAL); - - return padctl->phys[index]; -} - -#define PIN_OTG_0 0 -#define PIN_OTG_1 1 -#define PIN_OTG_2 2 -#define PIN_ULPI_0 3 -#define PIN_HSIC_0 4 -#define PIN_HSIC_1 5 -#define PIN_PCIE_0 6 -#define PIN_PCIE_1 7 -#define PIN_PCIE_2 8 -#define PIN_PCIE_3 9 -#define PIN_PCIE_4 10 -#define PIN_SATA_0 11 - -static const struct pinctrl_pin_desc tegra124_pins[] = { - PINCTRL_PIN(PIN_OTG_0, "otg-0"), - PINCTRL_PIN(PIN_OTG_1, "otg-1"), - PINCTRL_PIN(PIN_OTG_2, "otg-2"), - PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"), - PINCTRL_PIN(PIN_HSIC_0, "hsic-0"), - PINCTRL_PIN(PIN_HSIC_1, "hsic-1"), - PINCTRL_PIN(PIN_PCIE_0, "pcie-0"), - PINCTRL_PIN(PIN_PCIE_1, "pcie-1"), - PINCTRL_PIN(PIN_PCIE_2, "pcie-2"), - PINCTRL_PIN(PIN_PCIE_3, "pcie-3"), - PINCTRL_PIN(PIN_PCIE_4, "pcie-4"), - PINCTRL_PIN(PIN_SATA_0, "sata-0"), -}; - -static const char * const tegra124_snps_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "ulpi-0", - "hsic-0", - "hsic-1", -}; - -static const char * const tegra124_xusb_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "ulpi-0", - "hsic-0", - "hsic-1", -}; - -static const char * const tegra124_uart_groups[] = { - "otg-0", - "otg-1", - "otg-2", -}; - -static const char * const tegra124_pcie_groups[] = { - "pcie-0", - "pcie-1", - "pcie-2", - "pcie-3", - "pcie-4", -}; - -static const char * const tegra124_usb3_groups[] = { - "pcie-0", - "pcie-1", - "sata-0", -}; - -static const char * const tegra124_sata_groups[] = { - "sata-0", -}; - -static const char * const tegra124_rsvd_groups[] = { - "otg-0", - "otg-1", - "otg-2", - "pcie-0", - "pcie-1", - "pcie-2", - "pcie-3", - "pcie-4", - "sata-0", -}; - -#define TEGRA124_FUNCTION(_name) \ - { \ - .name = #_name, \ - .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \ - .groups = tegra124_##_name##_groups, \ - } - -static struct tegra_xusb_padctl_function tegra124_functions[] = { - TEGRA124_FUNCTION(snps), - TEGRA124_FUNCTION(xusb), - TEGRA124_FUNCTION(uart), - TEGRA124_FUNCTION(pcie), - TEGRA124_FUNCTION(usb3), - TEGRA124_FUNCTION(sata), - TEGRA124_FUNCTION(rsvd), -}; - -enum tegra124_function { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, - TEGRA124_FUNC_UART, - TEGRA124_FUNC_PCIE, - TEGRA124_FUNC_USB3, - TEGRA124_FUNC_SATA, - TEGRA124_FUNC_RSVD, -}; - -static const unsigned int tegra124_otg_functions[] = { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, - TEGRA124_FUNC_UART, - TEGRA124_FUNC_RSVD, -}; - -static const unsigned int tegra124_usb_functions[] = { - TEGRA124_FUNC_SNPS, - TEGRA124_FUNC_XUSB, -}; - -static const unsigned int tegra124_pci_functions[] = { - TEGRA124_FUNC_PCIE, - TEGRA124_FUNC_USB3, - TEGRA124_FUNC_SATA, - TEGRA124_FUNC_RSVD, -}; - -#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \ - { \ - .name = _name, \ - .offset = _offset, \ - .shift = _shift, \ - .mask = _mask, \ - .iddq = _iddq, \ - .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \ - .funcs = tegra124_##_funcs##_functions, \ - } - -static const struct tegra_xusb_padctl_lane tegra124_lanes[] = { - TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg), - TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg), - TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg), - TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb), - TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb), - TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb), - TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci), - TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci), - TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci), - TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci), - TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci), - TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci), -}; - -static const struct tegra_xusb_padctl_soc tegra124_soc = { - .num_pins = ARRAY_SIZE(tegra124_pins), - .pins = tegra124_pins, - .num_functions = ARRAY_SIZE(tegra124_functions), - .functions = tegra124_functions, - .num_lanes = ARRAY_SIZE(tegra124_lanes), - .lanes = tegra124_lanes, -}; - -static const struct of_device_id tegra_xusb_padctl_of_match[] = { - { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc }, - { } -}; -MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); - -static int tegra_xusb_padctl_probe(struct platform_device *pdev) -{ - struct tegra_xusb_padctl *padctl; - const struct of_device_id *match; - struct resource *res; - struct phy *phy; - int err; - - padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL); - if (!padctl) - return -ENOMEM; - - platform_set_drvdata(pdev, padctl); - mutex_init(&padctl->lock); - padctl->dev = &pdev->dev; - - match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); - padctl->soc = match->data; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - padctl->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(padctl->regs)) - return PTR_ERR(padctl->regs); - - padctl->rst = devm_reset_control_get(&pdev->dev, NULL); - if (IS_ERR(padctl->rst)) - return PTR_ERR(padctl->rst); - - err = reset_control_deassert(padctl->rst); - if (err < 0) - return err; - - memset(&padctl->desc, 0, sizeof(padctl->desc)); - padctl->desc.name = dev_name(padctl->dev); - padctl->desc.pins = tegra124_pins; - padctl->desc.npins = ARRAY_SIZE(tegra124_pins); - padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops; - padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops; - padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; - padctl->desc.owner = THIS_MODULE; - - padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); - if (IS_ERR(padctl->pinctrl)) { - dev_err(&pdev->dev, "failed to register pincontrol\n"); - err = PTR_ERR(padctl->pinctrl); - goto reset; - } - - phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops); - if (IS_ERR(phy)) { - err = PTR_ERR(phy); - goto unregister; - } - - padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; - phy_set_drvdata(phy, padctl); - - phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops); - if (IS_ERR(phy)) { - err = PTR_ERR(phy); - goto unregister; - } - - padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; - phy_set_drvdata(phy, padctl); - - padctl->provider = devm_of_phy_provider_register(&pdev->dev, - tegra_xusb_padctl_xlate); - if (IS_ERR(padctl->provider)) { - err = PTR_ERR(padctl->provider); - dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); - goto unregister; - } - - return 0; - -unregister: - pinctrl_unregister(padctl->pinctrl); -reset: - reset_control_assert(padctl->rst); - return err; -} - -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); - - return err; -} - -static struct platform_driver tegra_xusb_padctl_driver = { - .driver = { - .name = "tegra-xusb-padctl", - .of_match_table = tegra_xusb_padctl_of_match, - }, - .probe = tegra_xusb_padctl_probe, - .remove = tegra_xusb_padctl_remove, -}; -module_platform_driver(tegra_xusb_padctl_driver); - -MODULE_AUTHOR("Thierry Reding "); -MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c deleted file mode 100644 index 9da4da219a07..000000000000 --- a/drivers/pinctrl/pinctrl-tegra.c +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Driver for the NVIDIA Tegra pinmux - * - * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. - * - * Derived from code: - * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010 NVIDIA Corporation - * Copyright (C) 2009-2011 ST-Ericsson AB - * - * 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 -#include -#include -#include -#include - -#include "core.h" -#include "pinctrl-tegra.h" -#include "pinctrl-utils.h" - -struct tegra_pmx { - struct device *dev; - struct pinctrl_dev *pctl; - - const struct tegra_pinctrl_soc_data *soc; - const char **group_pins; - - int nbanks; - void __iomem **regs; -}; - -static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg) -{ - return readl(pmx->regs[bank] + reg); -} - -static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg) -{ - writel(val, pmx->regs[bank] + reg); -} - -static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->ngroups; -} - -static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev, - unsigned group) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->groups[group].name; -} - -static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, - unsigned group, - const unsigned **pins, - unsigned *num_pins) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - *pins = pmx->soc->groups[group].pins; - *num_pins = pmx->soc->groups[group].npins; - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned offset) -{ - seq_printf(s, " %s", dev_name(pctldev->dev)); -} -#endif - -static const struct cfg_param { - const char *property; - enum tegra_pinconf_param param; -} cfg_params[] = { - {"nvidia,pull", TEGRA_PINCONF_PARAM_PULL}, - {"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE}, - {"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT}, - {"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN}, - {"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK}, - {"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET}, - {"nvidia,rcv-sel", TEGRA_PINCONF_PARAM_RCV_SEL}, - {"nvidia,io-hv", TEGRA_PINCONF_PARAM_RCV_SEL}, - {"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE}, - {"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT}, - {"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE}, - {"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH}, - {"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH}, - {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, - {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, - {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, -}; - -static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, - struct device_node *np, - struct pinctrl_map **map, - unsigned *reserved_maps, - unsigned *num_maps) -{ - struct device *dev = pctldev->dev; - int ret, i; - const char *function; - u32 val; - unsigned long config; - unsigned long *configs = NULL; - unsigned num_configs = 0; - unsigned reserve; - struct property *prop; - const char *group; - - ret = of_property_read_string(np, "nvidia,function", &function); - if (ret < 0) { - /* EINVAL=missing, which is fine since it's optional */ - if (ret != -EINVAL) - dev_err(dev, - "could not parse property nvidia,function\n"); - function = NULL; - } - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - ret = of_property_read_u32(np, cfg_params[i].property, &val); - if (!ret) { - config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); - ret = pinctrl_utils_add_config(pctldev, &configs, - &num_configs, config); - if (ret < 0) - goto exit; - /* EINVAL=missing, which is fine since it's optional */ - } else if (ret != -EINVAL) { - dev_err(dev, "could not parse property %s\n", - cfg_params[i].property); - } - } - - reserve = 0; - if (function != NULL) - reserve++; - if (num_configs) - reserve++; - ret = of_property_count_strings(np, "nvidia,pins"); - if (ret < 0) { - dev_err(dev, "could not parse property nvidia,pins\n"); - goto exit; - } - reserve *= ret; - - ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, - num_maps, reserve); - if (ret < 0) - goto exit; - - of_property_for_each_string(np, "nvidia,pins", prop, group) { - if (function) { - ret = pinctrl_utils_add_map_mux(pctldev, map, - reserved_maps, num_maps, group, - function); - if (ret < 0) - goto exit; - } - - if (num_configs) { - ret = pinctrl_utils_add_map_configs(pctldev, map, - reserved_maps, num_maps, group, - configs, num_configs, - PIN_MAP_TYPE_CONFIGS_GROUP); - if (ret < 0) - goto exit; - } - } - - ret = 0; - -exit: - kfree(configs); - return ret; -} - -static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, - struct device_node *np_config, - struct pinctrl_map **map, - unsigned *num_maps) -{ - unsigned reserved_maps; - struct device_node *np; - int ret; - - reserved_maps = 0; - *map = NULL; - *num_maps = 0; - - for_each_child_of_node(np_config, np) { - ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map, - &reserved_maps, num_maps); - if (ret < 0) { - pinctrl_utils_dt_free_map(pctldev, *map, - *num_maps); - of_node_put(np); - return ret; - } - } - - return 0; -} - -static const struct pinctrl_ops tegra_pinctrl_ops = { - .get_groups_count = tegra_pinctrl_get_groups_count, - .get_group_name = tegra_pinctrl_get_group_name, - .get_group_pins = tegra_pinctrl_get_group_pins, -#ifdef CONFIG_DEBUG_FS - .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, -}; - -static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->nfunctions; -} - -static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, - unsigned function) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - return pmx->soc->functions[function].name; -} - -static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, - unsigned function, - const char * const **groups, - unsigned * const num_groups) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - - *groups = pmx->soc->functions[function].groups; - *num_groups = pmx->soc->functions[function].ngroups; - - return 0; -} - -static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, - unsigned function, - unsigned group) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - const struct tegra_pingroup *g; - int i; - u32 val; - - g = &pmx->soc->groups[group]; - - if (WARN_ON(g->mux_reg < 0)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { - if (g->funcs[i] == function) - break; - } - if (WARN_ON(i == ARRAY_SIZE(g->funcs))) - return -EINVAL; - - val = pmx_readl(pmx, g->mux_bank, g->mux_reg); - val &= ~(0x3 << g->mux_bit); - val |= i << g->mux_bit; - pmx_writel(pmx, val, g->mux_bank, g->mux_reg); - - return 0; -} - -static const struct pinmux_ops tegra_pinmux_ops = { - .get_functions_count = tegra_pinctrl_get_funcs_count, - .get_function_name = tegra_pinctrl_get_func_name, - .get_function_groups = tegra_pinctrl_get_func_groups, - .set_mux = tegra_pinctrl_set_mux, -}; - -static int tegra_pinconf_reg(struct tegra_pmx *pmx, - const struct tegra_pingroup *g, - enum tegra_pinconf_param param, - bool report_err, - s8 *bank, s16 *reg, s8 *bit, s8 *width) -{ - switch (param) { - case TEGRA_PINCONF_PARAM_PULL: - *bank = g->pupd_bank; - *reg = g->pupd_reg; - *bit = g->pupd_bit; - *width = 2; - break; - case TEGRA_PINCONF_PARAM_TRISTATE: - *bank = g->tri_bank; - *reg = g->tri_reg; - *bit = g->tri_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_ENABLE_INPUT: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->einput_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_OPEN_DRAIN: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->odrain_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_LOCK: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->lock_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_IORESET: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->ioreset_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_RCV_SEL: - *bank = g->mux_bank; - *reg = g->mux_reg; - *bit = g->rcv_sel_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE: - if (pmx->soc->hsm_in_mux) { - *bank = g->mux_bank; - *reg = g->mux_reg; - } else { - *bank = g->drv_bank; - *reg = g->drv_reg; - } - *bit = g->hsm_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_SCHMITT: - if (pmx->soc->schmitt_in_mux) { - *bank = g->mux_bank; - *reg = g->mux_reg; - } else { - *bank = g->drv_bank; - *reg = g->drv_reg; - } - *bit = g->schmitt_bit; - *width = 1; - break; - case TEGRA_PINCONF_PARAM_LOW_POWER_MODE: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->lpmd_bit; - *width = 2; - break; - case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->drvdn_bit; - *width = g->drvdn_width; - break; - case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->drvup_bit; - *width = g->drvup_width; - break; - case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->slwf_bit; - *width = g->slwf_width; - break; - case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING: - *bank = g->drv_bank; - *reg = g->drv_reg; - *bit = g->slwr_bit; - *width = g->slwr_width; - break; - case TEGRA_PINCONF_PARAM_DRIVE_TYPE: - if (pmx->soc->drvtype_in_mux) { - *bank = g->mux_bank; - *reg = g->mux_reg; - } else { - *bank = g->drv_bank; - *reg = g->drv_reg; - } - *bit = g->drvtype_bit; - *width = 2; - break; - default: - dev_err(pmx->dev, "Invalid config param %04x\n", param); - return -ENOTSUPP; - } - - if (*reg < 0 || *bit > 31) { - if (report_err) { - const char *prop = "unknown"; - int i; - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - if (cfg_params[i].param == param) { - prop = cfg_params[i].property; - break; - } - } - - dev_err(pmx->dev, - "Config param %04x (%s) not supported on group %s\n", - param, prop, g->name); - } - return -ENOTSUPP; - } - - return 0; -} - -static int tegra_pinconf_get(struct pinctrl_dev *pctldev, - unsigned pin, unsigned long *config) -{ - dev_err(pctldev->dev, "pin_config_get op not supported\n"); - return -ENOTSUPP; -} - -static int tegra_pinconf_set(struct pinctrl_dev *pctldev, - unsigned pin, unsigned long *configs, - unsigned num_configs) -{ - dev_err(pctldev->dev, "pin_config_set op not supported\n"); - return -ENOTSUPP; -} - -static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev, - unsigned group, unsigned long *config) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config); - u16 arg; - const struct tegra_pingroup *g; - int ret; - s8 bank, bit, width; - s16 reg; - u32 val, mask; - - g = &pmx->soc->groups[group]; - - ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, - &width); - if (ret < 0) - return ret; - - val = pmx_readl(pmx, bank, reg); - mask = (1 << width) - 1; - arg = (val >> bit) & mask; - - *config = TEGRA_PINCONF_PACK(param, arg); - - return 0; -} - -static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, - unsigned group, unsigned long *configs, - unsigned num_configs) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - enum tegra_pinconf_param param; - u16 arg; - const struct tegra_pingroup *g; - int ret, i; - s8 bank, bit, width; - s16 reg; - u32 val, mask; - - g = &pmx->soc->groups[group]; - - for (i = 0; i < num_configs; i++) { - param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]); - arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]); - - ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, - &width); - if (ret < 0) - return ret; - - val = pmx_readl(pmx, bank, reg); - - /* LOCK can't be cleared */ - if (param == TEGRA_PINCONF_PARAM_LOCK) { - if ((val & BIT(bit)) && !arg) { - dev_err(pctldev->dev, "LOCK bit cannot be cleared\n"); - return -EINVAL; - } - } - - /* Special-case Boolean values; allow any non-zero as true */ - if (width == 1) - arg = !!arg; - - /* Range-check user-supplied value */ - mask = (1 << width) - 1; - if (arg & ~mask) { - dev_err(pctldev->dev, - "config %lx: %x too big for %d bit register\n", - configs[i], arg, width); - return -EINVAL; - } - - /* Update register */ - val &= ~(mask << bit); - val |= arg << bit; - pmx_writel(pmx, val, bank, reg); - } /* for each config */ - - return 0; -} - -#ifdef CONFIG_DEBUG_FS -static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, unsigned offset) -{ -} - -static const char *strip_prefix(const char *s) -{ - const char *comma = strchr(s, ','); - if (!comma) - return s; - - return comma + 1; -} - -static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, unsigned group) -{ - struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); - const struct tegra_pingroup *g; - int i, ret; - s8 bank, bit, width; - s16 reg; - u32 val; - - g = &pmx->soc->groups[group]; - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false, - &bank, ®, &bit, &width); - if (ret < 0) - continue; - - val = pmx_readl(pmx, bank, reg); - val >>= bit; - val &= (1 << width) - 1; - - seq_printf(s, "\n\t%s=%u", - strip_prefix(cfg_params[i].property), val); - } -} - -static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev, - struct seq_file *s, - unsigned long config) -{ - enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config); - u16 arg = TEGRA_PINCONF_UNPACK_ARG(config); - const char *pname = "unknown"; - int i; - - for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { - if (cfg_params[i].param == param) { - pname = cfg_params[i].property; - break; - } - } - - seq_printf(s, "%s=%d", strip_prefix(pname), arg); -} -#endif - -static const struct pinconf_ops tegra_pinconf_ops = { - .pin_config_get = tegra_pinconf_get, - .pin_config_set = tegra_pinconf_set, - .pin_config_group_get = tegra_pinconf_group_get, - .pin_config_group_set = tegra_pinconf_group_set, -#ifdef CONFIG_DEBUG_FS - .pin_config_dbg_show = tegra_pinconf_dbg_show, - .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show, - .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show, -#endif -}; - -static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = { - .name = "Tegra GPIOs", - .id = 0, - .base = 0, -}; - -static struct pinctrl_desc tegra_pinctrl_desc = { - .pctlops = &tegra_pinctrl_ops, - .pmxops = &tegra_pinmux_ops, - .confops = &tegra_pinconf_ops, - .owner = THIS_MODULE, -}; - -static bool gpio_node_has_range(void) -{ - struct device_node *np; - bool has_prop = false; - - np = of_find_compatible_node(NULL, NULL, "nvidia,tegra30-gpio"); - if (!np) - return has_prop; - - has_prop = of_find_property(np, "gpio-ranges", NULL); - - of_node_put(np); - - return has_prop; -} - -int tegra_pinctrl_probe(struct platform_device *pdev, - const struct tegra_pinctrl_soc_data *soc_data) -{ - struct tegra_pmx *pmx; - struct resource *res; - int i; - const char **group_pins; - int fn, gn, gfn; - - pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL); - if (!pmx) { - dev_err(&pdev->dev, "Can't alloc tegra_pmx\n"); - return -ENOMEM; - } - pmx->dev = &pdev->dev; - pmx->soc = soc_data; - - /* - * Each mux group will appear in 4 functions' list of groups. - * This over-allocates slightly, since not all groups are mux groups. - */ - pmx->group_pins = devm_kzalloc(&pdev->dev, - soc_data->ngroups * 4 * sizeof(*pmx->group_pins), - GFP_KERNEL); - if (!pmx->group_pins) - return -ENOMEM; - - group_pins = pmx->group_pins; - for (fn = 0; fn < soc_data->nfunctions; fn++) { - struct tegra_function *func = &soc_data->functions[fn]; - - func->groups = group_pins; - - for (gn = 0; gn < soc_data->ngroups; gn++) { - const struct tegra_pingroup *g = &soc_data->groups[gn]; - - if (g->mux_reg == -1) - continue; - - for (gfn = 0; gfn < 4; gfn++) - if (g->funcs[gfn] == fn) - break; - if (gfn == 4) - continue; - - BUG_ON(group_pins - pmx->group_pins >= - soc_data->ngroups * 4); - *group_pins++ = g->name; - func->ngroups++; - } - } - - tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios; - tegra_pinctrl_desc.name = dev_name(&pdev->dev); - tegra_pinctrl_desc.pins = pmx->soc->pins; - tegra_pinctrl_desc.npins = pmx->soc->npins; - - for (i = 0; ; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - if (!res) - break; - } - pmx->nbanks = i; - - pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs), - GFP_KERNEL); - if (!pmx->regs) { - dev_err(&pdev->dev, "Can't alloc regs pointer\n"); - return -ENOMEM; - } - - for (i = 0; i < pmx->nbanks; i++) { - res = platform_get_resource(pdev, IORESOURCE_MEM, i); - pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pmx->regs[i])) - return PTR_ERR(pmx->regs[i]); - } - - pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx); - if (IS_ERR(pmx->pctl)) { - dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); - return PTR_ERR(pmx->pctl); - } - - if (!gpio_node_has_range()) - pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); - - platform_set_drvdata(pdev, pmx); - - dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n"); - - 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/pinctrl-tegra.h b/drivers/pinctrl/pinctrl-tegra.h deleted file mode 100644 index 1615db7e3a4b..000000000000 --- a/drivers/pinctrl/pinctrl-tegra.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Driver for the NVIDIA Tegra pinmux - * - * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. - * - * 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. - */ - -#ifndef __PINMUX_TEGRA_H__ -#define __PINMUX_TEGRA_H__ - -enum tegra_pinconf_param { - /* argument: tegra_pinconf_pull */ - TEGRA_PINCONF_PARAM_PULL, - /* argument: tegra_pinconf_tristate */ - TEGRA_PINCONF_PARAM_TRISTATE, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_ENABLE_INPUT, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_OPEN_DRAIN, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_LOCK, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_IORESET, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_RCV_SEL, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_SCHMITT, - /* argument: Boolean */ - TEGRA_PINCONF_PARAM_LOW_POWER_MODE, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, - /* argument: Integer, range is HW-dependant */ - TEGRA_PINCONF_PARAM_DRIVE_TYPE, -}; - -enum tegra_pinconf_pull { - TEGRA_PINCONFIG_PULL_NONE, - TEGRA_PINCONFIG_PULL_DOWN, - TEGRA_PINCONFIG_PULL_UP, -}; - -enum tegra_pinconf_tristate { - TEGRA_PINCONFIG_DRIVEN, - TEGRA_PINCONFIG_TRISTATE, -}; - -#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) -#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) -#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) - -/** - * struct tegra_function - Tegra pinctrl mux function - * @name: The name of the function, exported to pinctrl core. - * @groups: An array of pin groups that may select this function. - * @ngroups: The number of entries in @groups. - */ -struct tegra_function { - const char *name; - const char **groups; - unsigned ngroups; -}; - -/** - * struct tegra_pingroup - Tegra pin group - * @name The name of the pin group. - * @pins An array of pin IDs included in this pin group. - * @npins The number of entries in @pins. - * @funcs The mux functions which can be muxed onto this group. - * @mux_reg: Mux register offset. - * This register contains the mux, einput, odrain, lock, - * ioreset, rcv_sel parameters. - * @mux_bank: Mux register bank. - * @mux_bit: Mux register bit. - * @pupd_reg: Pull-up/down register offset. - * @pupd_bank: Pull-up/down register bank. - * @pupd_bit: Pull-up/down register bit. - * @tri_reg: Tri-state register offset. - * @tri_bank: Tri-state register bank. - * @tri_bit: Tri-state register bit. - * @einput_bit: Enable-input register bit. - * @odrain_bit: Open-drain register bit. - * @lock_bit: Lock register bit. - * @ioreset_bit: IO reset register bit. - * @rcv_sel_bit: Receiver select bit. - * @drv_reg: Drive fields register offset. - * This register contains hsm, schmitt, lpmd, drvdn, - * drvup, slwr, slwf, and drvtype parameters. - * @drv_bank: Drive fields register bank. - * @hsm_bit: High Speed Mode register bit. - * @schmitt_bit: Scmitt register bit. - * @lpmd_bit: Low Power Mode register bit. - * @drvdn_bit: Drive Down register bit. - * @drvdn_width: Drive Down field width. - * @drvup_bit: Drive Up register bit. - * @drvup_width: Drive Up field width. - * @slwr_bit: Slew Rising register bit. - * @slwr_width: Slew Rising field width. - * @slwf_bit: Slew Falling register bit. - * @slwf_width: Slew Falling field width. - * @drvtype_bit: Drive type register bit. - * - * -1 in a *_reg field means that feature is unsupported for this group. - * *_bank and *_reg values are irrelevant when *_reg is -1. - * When *_reg is valid, *_bit may be -1 to indicate an unsupported feature. - * - * A representation of a group of pins (possibly just one pin) in the Tegra - * pin controller. Each group allows some parameter or parameters to be - * configured. The most common is mux function selection. Many others exist - * such as pull-up/down, tri-state, etc. Tegra's pin controller is complex; - * certain groups may only support configuring certain parameters, hence - * each parameter is optional. - */ -struct tegra_pingroup { - const char *name; - const unsigned *pins; - u8 npins; - u8 funcs[4]; - s16 mux_reg; - s16 pupd_reg; - s16 tri_reg; - s16 drv_reg; - u32 mux_bank:2; - u32 pupd_bank:2; - u32 tri_bank:2; - u32 drv_bank:2; - s32 mux_bit:6; - s32 pupd_bit:6; - s32 tri_bit:6; - s32 einput_bit:6; - s32 odrain_bit:6; - s32 lock_bit:6; - s32 ioreset_bit:6; - s32 rcv_sel_bit:6; - s32 hsm_bit:6; - s32 schmitt_bit:6; - s32 lpmd_bit:6; - s32 drvdn_bit:6; - s32 drvup_bit:6; - s32 slwr_bit:6; - s32 slwf_bit:6; - s32 drvtype_bit:6; - s32 drvdn_width:6; - s32 drvup_width:6; - s32 slwr_width:6; - s32 slwf_width:6; -}; - -/** - * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration - * @ngpios: The number of GPIO pins the pin controller HW affects. - * @pins: An array describing all pins the pin controller affects. - * All pins which are also GPIOs must be listed first within the - * array, and be numbered identically to the GPIO controller's - * numbering. - * @npins: The numbmer of entries in @pins. - * @functions: An array describing all mux functions the SoC supports. - * @nfunctions: The numbmer of entries in @functions. - * @groups: An array describing all pin groups the pin SoC supports. - * @ngroups: The numbmer of entries in @groups. - */ -struct tegra_pinctrl_soc_data { - unsigned ngpios; - const struct pinctrl_pin_desc *pins; - unsigned npins; - struct tegra_function *functions; - unsigned nfunctions; - const struct tegra_pingroup *groups; - unsigned ngroups; - bool hsm_in_mux; - bool schmitt_in_mux; - bool drvtype_in_mux; -}; - -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/pinctrl-tegra114.c b/drivers/pinctrl/pinctrl-tegra114.c deleted file mode 100644 index 05e49d5137ab..000000000000 --- a/drivers/pinctrl/pinctrl-tegra114.c +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra114 pinmux - * - * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. - * - * 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 "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) -#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) -#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) -#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) -#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) -#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) -#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) -#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) -#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) -#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) -#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) -#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) -#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) -#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) -#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) -#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) -#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) -#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) -#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) -#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) -#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) -#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) -#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) -#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) -#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) -#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) -#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) -#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) -#define TEGRA_PIN_GMI_DQS_P_PJ3 _GPIO(75) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) -#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) -#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) -#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) -#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) -#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) -#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) -#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) -#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) -#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) -#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) -#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) -#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) -#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) -#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) -#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) -#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) -#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) -#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) -#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) -#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) -#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) -#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) -#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) -#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) -#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) -#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) -#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) -#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) -#define TEGRA_PIN_PBB0 _GPIO(216) -#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) -#define TEGRA_PIN_PBB3 _GPIO(219) -#define TEGRA_PIN_PBB4 _GPIO(220) -#define TEGRA_PIN_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) -#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) -#define TEGRA_PIN_PCC1 _GPIO(225) -#define TEGRA_PIN_PCC2 _GPIO(226) -#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) -#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) -#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) -#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) -#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) -#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) -#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) -#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) -#define TEGRA_PIN_PWR_INT_N _PIN(2) -#define TEGRA_PIN_RESET_OUT_N _PIN(3) -#define TEGRA_PIN_OWR _PIN(4) -#define TEGRA_PIN_JTAG_RTCK _PIN(5) -#define TEGRA_PIN_CLK_32K_IN _PIN(6) -#define TEGRA_PIN_GMI_CLK_LB _PIN(7) - -static const struct pinctrl_pin_desc tegra114_pins[] = { - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), - PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), - PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), - PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), - PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), - PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), - PINCTRL_PIN(TEGRA_PIN_GMI_DQS_P_PJ3, "GMI_DQS_P PJ3"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), - PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), - PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), - PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), - PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), - PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), - PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), - PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), - PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), - PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), - PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), - PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), - PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), -}; - -static const unsigned clk_32k_out_pa0_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, -}; - -static const unsigned uart3_cts_n_pa1_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned dap2_fs_pa2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, -}; - -static const unsigned dap2_sclk_pa3_pins[] = { - TEGRA_PIN_DAP2_SCLK_PA3, -}; - -static const unsigned dap2_din_pa4_pins[] = { - TEGRA_PIN_DAP2_DIN_PA4, -}; - -static const unsigned dap2_dout_pa5_pins[] = { - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned sdmmc3_clk_pa6_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, -}; - -static const unsigned sdmmc3_cmd_pa7_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PA7, -}; - -static const unsigned gmi_a17_pb0_pins[] = { - TEGRA_PIN_GMI_A17_PB0, -}; - -static const unsigned gmi_a18_pb1_pins[] = { - TEGRA_PIN_GMI_A18_PB1, -}; - -static const unsigned sdmmc3_dat3_pb4_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PB4, -}; - -static const unsigned sdmmc3_dat2_pb5_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PB5, -}; - -static const unsigned sdmmc3_dat1_pb6_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PB6, -}; - -static const unsigned sdmmc3_dat0_pb7_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned uart3_rts_n_pc0_pins[] = { - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned uart2_txd_pc2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uart2_rxd_pc3_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, -}; - -static const unsigned gen1_i2c_scl_pc4_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, -}; - -static const unsigned gen1_i2c_sda_pc5_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned gmi_wp_n_pc7_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned gmi_ad0_pg0_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, -}; - -static const unsigned gmi_ad1_pg1_pins[] = { - TEGRA_PIN_GMI_AD1_PG1, -}; - -static const unsigned gmi_ad2_pg2_pins[] = { - TEGRA_PIN_GMI_AD2_PG2, -}; - -static const unsigned gmi_ad3_pg3_pins[] = { - TEGRA_PIN_GMI_AD3_PG3, -}; - -static const unsigned gmi_ad4_pg4_pins[] = { - TEGRA_PIN_GMI_AD4_PG4, -}; - -static const unsigned gmi_ad5_pg5_pins[] = { - TEGRA_PIN_GMI_AD5_PG5, -}; - -static const unsigned gmi_ad6_pg6_pins[] = { - TEGRA_PIN_GMI_AD6_PG6, -}; - -static const unsigned gmi_ad7_pg7_pins[] = { - TEGRA_PIN_GMI_AD7_PG7, -}; - -static const unsigned gmi_ad8_ph0_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, -}; - -static const unsigned gmi_ad9_ph1_pins[] = { - TEGRA_PIN_GMI_AD9_PH1, -}; - -static const unsigned gmi_ad10_ph2_pins[] = { - TEGRA_PIN_GMI_AD10_PH2, -}; - -static const unsigned gmi_ad11_ph3_pins[] = { - TEGRA_PIN_GMI_AD11_PH3, -}; - -static const unsigned gmi_ad12_ph4_pins[] = { - TEGRA_PIN_GMI_AD12_PH4, -}; - -static const unsigned gmi_ad13_ph5_pins[] = { - TEGRA_PIN_GMI_AD13_PH5, -}; - -static const unsigned gmi_ad14_ph6_pins[] = { - TEGRA_PIN_GMI_AD14_PH6, -}; - -static const unsigned gmi_ad15_ph7_pins[] = { - TEGRA_PIN_GMI_AD15_PH7, -}; - -static const unsigned gmi_wr_n_pi0_pins[] = { - TEGRA_PIN_GMI_WR_N_PI0, -}; - -static const unsigned gmi_oe_n_pi1_pins[] = { - TEGRA_PIN_GMI_OE_N_PI1, -}; - -static const unsigned gmi_cs6_n_pi3_pins[] = { - TEGRA_PIN_GMI_CS6_N_PI3, -}; - -static const unsigned gmi_rst_n_pi4_pins[] = { - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned gmi_iordy_pi5_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, -}; - -static const unsigned gmi_cs7_n_pi6_pins[] = { - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned gmi_wait_pi7_pins[] = { - TEGRA_PIN_GMI_WAIT_PI7, -}; - -static const unsigned gmi_cs0_n_pj0_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned gmi_cs1_n_pj2_pins[] = { - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned gmi_dqs_p_pj3_pins[] = { - TEGRA_PIN_GMI_DQS_P_PJ3, -}; - -static const unsigned uart2_cts_n_pj5_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned uart2_rts_n_pj6_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned gmi_a16_pj7_pins[] = { - TEGRA_PIN_GMI_A16_PJ7, -}; - -static const unsigned gmi_adv_n_pk0_pins[] = { - TEGRA_PIN_GMI_ADV_N_PK0, -}; - -static const unsigned gmi_clk_pk1_pins[] = { - TEGRA_PIN_GMI_CLK_PK1, -}; - -static const unsigned gmi_cs4_n_pk2_pins[] = { - TEGRA_PIN_GMI_CS4_N_PK2, -}; - -static const unsigned gmi_cs2_n_pk3_pins[] = { - TEGRA_PIN_GMI_CS2_N_PK3, -}; - -static const unsigned gmi_cs3_n_pk4_pins[] = { - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned spdif_out_pk5_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spdif_in_pk6_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned gmi_a19_pk7_pins[] = { - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned dap1_fs_pn0_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, -}; - -static const unsigned dap1_din_pn1_pins[] = { - TEGRA_PIN_DAP1_DIN_PN1, -}; - -static const unsigned dap1_dout_pn2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PN2, -}; - -static const unsigned dap1_sclk_pn3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned usb_vbus_en0_pn4_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PN4, -}; - -static const unsigned usb_vbus_en1_pn5_pins[] = { - TEGRA_PIN_USB_VBUS_EN1_PN5, -}; - -static const unsigned hdmi_int_pn7_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned ulpi_data7_po0_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned ulpi_data0_po1_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, -}; - -static const unsigned ulpi_data1_po2_pins[] = { - TEGRA_PIN_ULPI_DATA1_PO2, -}; - -static const unsigned ulpi_data2_po3_pins[] = { - TEGRA_PIN_ULPI_DATA2_PO3, -}; - -static const unsigned ulpi_data3_po4_pins[] = { - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned ulpi_data4_po5_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, -}; - -static const unsigned ulpi_data5_po6_pins[] = { - TEGRA_PIN_ULPI_DATA5_PO6, -}; - -static const unsigned ulpi_data6_po7_pins[] = { - TEGRA_PIN_ULPI_DATA6_PO7, -}; - -static const unsigned dap3_fs_pp0_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, -}; - -static const unsigned dap3_din_pp1_pins[] = { - TEGRA_PIN_DAP3_DIN_PP1, -}; - -static const unsigned dap3_dout_pp2_pins[] = { - TEGRA_PIN_DAP3_DOUT_PP2, -}; - -static const unsigned dap3_sclk_pp3_pins[] = { - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_fs_pp4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, -}; - -static const unsigned dap4_din_pp5_pins[] = { - TEGRA_PIN_DAP4_DIN_PP5, -}; - -static const unsigned dap4_dout_pp6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PP6, -}; - -static const unsigned dap4_sclk_pp7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned kb_col0_pq0_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, -}; - -static const unsigned kb_col1_pq1_pins[] = { - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kb_col2_pq2_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, -}; - -static const unsigned kb_col3_pq3_pins[] = { - TEGRA_PIN_KB_COL3_PQ3, -}; - -static const unsigned kb_col4_pq4_pins[] = { - TEGRA_PIN_KB_COL4_PQ4, -}; - -static const unsigned kb_col5_pq5_pins[] = { - TEGRA_PIN_KB_COL5_PQ5, -}; - -static const unsigned kb_col6_pq6_pins[] = { - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned kb_col7_pq7_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kb_row0_pr0_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, -}; - -static const unsigned kb_row1_pr1_pins[] = { - TEGRA_PIN_KB_ROW1_PR1, -}; - -static const unsigned kb_row2_pr2_pins[] = { - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kb_row3_pr3_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, -}; - -static const unsigned kb_row4_pr4_pins[] = { - TEGRA_PIN_KB_ROW4_PR4, -}; - -static const unsigned kb_row5_pr5_pins[] = { - TEGRA_PIN_KB_ROW5_PR5, -}; - -static const unsigned kb_row6_pr6_pins[] = { - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kb_row7_pr7_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned kb_row8_ps0_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, -}; - -static const unsigned kb_row9_ps1_pins[] = { - TEGRA_PIN_KB_ROW9_PS1, -}; - -static const unsigned kb_row10_ps2_pins[] = { - TEGRA_PIN_KB_ROW10_PS2, -}; - -static const unsigned gen2_i2c_scl_pt5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, -}; - -static const unsigned gen2_i2c_sda_pt6_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned sdmmc4_cmd_pt7_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned pu0_pins[] = { - TEGRA_PIN_PU0, -}; - -static const unsigned pu1_pins[] = { - TEGRA_PIN_PU1, -}; - -static const unsigned pu2_pins[] = { - TEGRA_PIN_PU2, -}; - -static const unsigned pu3_pins[] = { - TEGRA_PIN_PU3, -}; - -static const unsigned pu4_pins[] = { - TEGRA_PIN_PU4, -}; - -static const unsigned pu5_pins[] = { - TEGRA_PIN_PU5, -}; - -static const unsigned pu6_pins[] = { - TEGRA_PIN_PU6, -}; - -static const unsigned pv0_pins[] = { - TEGRA_PIN_PV0, -}; - -static const unsigned pv1_pins[] = { - TEGRA_PIN_PV1, -}; - -static const unsigned sdmmc3_cd_n_pv2_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, -}; - -static const unsigned sdmmc1_wp_n_pv3_pins[] = { - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned ddc_scl_pv4_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, -}; - -static const unsigned ddc_sda_pv5_pins[] = { - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned gpio_w2_aud_pw2_pins[] = { - TEGRA_PIN_GPIO_W2_AUD_PW2, -}; - -static const unsigned gpio_w3_aud_pw3_pins[] = { - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned clk1_out_pw4_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, -}; - -static const unsigned clk2_out_pw5_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, -}; - -static const unsigned uart3_txd_pw6_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned uart3_rxd_pw7_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned dvfs_pwm_px0_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, -}; - -static const unsigned gpio_x1_aud_px1_pins[] = { - TEGRA_PIN_GPIO_X1_AUD_PX1, -}; - -static const unsigned dvfs_clk_px2_pins[] = { - TEGRA_PIN_DVFS_CLK_PX2, -}; - -static const unsigned gpio_x3_aud_px3_pins[] = { - TEGRA_PIN_GPIO_X3_AUD_PX3, -}; - -static const unsigned gpio_x4_aud_px4_pins[] = { - TEGRA_PIN_GPIO_X4_AUD_PX4, -}; - -static const unsigned gpio_x5_aud_px5_pins[] = { - TEGRA_PIN_GPIO_X5_AUD_PX5, -}; - -static const unsigned gpio_x6_aud_px6_pins[] = { - TEGRA_PIN_GPIO_X6_AUD_PX6, -}; - -static const unsigned gpio_x7_aud_px7_pins[] = { - TEGRA_PIN_GPIO_X7_AUD_PX7, -}; - -static const unsigned ulpi_clk_py0_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, -}; - -static const unsigned ulpi_dir_py1_pins[] = { - TEGRA_PIN_ULPI_DIR_PY1, -}; - -static const unsigned ulpi_nxt_py2_pins[] = { - TEGRA_PIN_ULPI_NXT_PY2, -}; - -static const unsigned ulpi_stp_py3_pins[] = { - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned sdmmc1_dat3_py4_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, -}; - -static const unsigned sdmmc1_dat2_py5_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PY5, -}; - -static const unsigned sdmmc1_dat1_py6_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PY6, -}; - -static const unsigned sdmmc1_dat0_py7_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PY7, -}; - -static const unsigned sdmmc1_clk_pz0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PZ0, -}; - -static const unsigned sdmmc1_cmd_pz1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned sys_clk_req_pz5_pins[] = { - TEGRA_PIN_SYS_CLK_REQ_PZ5, -}; - -static const unsigned pwr_i2c_scl_pz6_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, -}; - -static const unsigned pwr_i2c_sda_pz7_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned sdmmc4_dat0_paa0_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, -}; - -static const unsigned sdmmc4_dat1_paa1_pins[] = { - TEGRA_PIN_SDMMC4_DAT1_PAA1, -}; - -static const unsigned sdmmc4_dat2_paa2_pins[] = { - TEGRA_PIN_SDMMC4_DAT2_PAA2, -}; - -static const unsigned sdmmc4_dat3_paa3_pins[] = { - TEGRA_PIN_SDMMC4_DAT3_PAA3, -}; - -static const unsigned sdmmc4_dat4_paa4_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, -}; - -static const unsigned sdmmc4_dat5_paa5_pins[] = { - TEGRA_PIN_SDMMC4_DAT5_PAA5, -}; - -static const unsigned sdmmc4_dat6_paa6_pins[] = { - TEGRA_PIN_SDMMC4_DAT6_PAA6, -}; - -static const unsigned sdmmc4_dat7_paa7_pins[] = { - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned pbb0_pins[] = { - TEGRA_PIN_PBB0, -}; - -static const unsigned cam_i2c_scl_pbb1_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB1, -}; - -static const unsigned cam_i2c_sda_pbb2_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PBB2, -}; - -static const unsigned pbb3_pins[] = { - TEGRA_PIN_PBB3, -}; - -static const unsigned pbb4_pins[] = { - TEGRA_PIN_PBB4, -}; - -static const unsigned pbb5_pins[] = { - TEGRA_PIN_PBB5, -}; - -static const unsigned pbb6_pins[] = { - TEGRA_PIN_PBB6, -}; - -static const unsigned pbb7_pins[] = { - TEGRA_PIN_PBB7, -}; - -static const unsigned cam_mclk_pcc0_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned pcc1_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned pcc2_pins[] = { - TEGRA_PIN_PCC2, -}; - -static const unsigned sdmmc4_clk_pcc4_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned clk2_req_pcc5_pins[] = { - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned clk3_out_pee0_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, -}; - -static const unsigned clk3_req_pee1_pins[] = { - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned clk1_req_pee2_pins[] = { - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned hdmi_cec_pee3_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, -}; - -static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned reset_out_n_pins[] = { - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned jtag_rtck_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned gmi_clk_lb_pins[] = { - TEGRA_PIN_GMI_CLK_LB, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_WR_N_PI0, - TEGRA_PIN_GMI_OE_N_PI1, - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_RST_N_PI4, - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_DQS_P_PJ3, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned drive_at3_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned drive_at4_pins[] = { - TEGRA_PIN_GMI_A17_PB0, - TEGRA_PIN_GMI_A18_PB1, - TEGRA_PIN_GMI_CS1_N_PJ2, - TEGRA_PIN_GMI_A16_PJ7, - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned drive_at5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, - TEGRA_PIN_CLK2_REQ_PCC5, - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, -}; - -static const unsigned drive_sdio3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, - TEGRA_PIN_SDMMC3_CMD_PA7, - TEGRA_PIN_SDMMC3_DAT3_PB4, - TEGRA_PIN_SDMMC3_DAT2_PB5, - TEGRA_PIN_SDMMC3_DAT1_PB6, - TEGRA_PIN_SDMMC3_DAT0_PB7, - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, - TEGRA_PIN_GPIO_X1_AUD_PX1, - TEGRA_PIN_DVFS_CLK_PX2, - TEGRA_PIN_GPIO_X3_AUD_PX3, - TEGRA_PIN_GPIO_X4_AUD_PX4, - TEGRA_PIN_GPIO_X5_AUD_PX5, - TEGRA_PIN_GPIO_X6_AUD_PX6, - TEGRA_PIN_GPIO_X7_AUD_PX7, - TEGRA_PIN_GPIO_W2_AUD_PW2, - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_CTS_N_PJ5, - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, - TEGRA_PIN_SDMMC1_DAT2_PY5, - TEGRA_PIN_SDMMC1_DAT1_PY6, - TEGRA_PIN_SDMMC1_DAT0_PY7, - TEGRA_PIN_SDMMC1_CLK_PZ0, - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, - TEGRA_PIN_SDMMC4_CMD_PT7, - TEGRA_PIN_SDMMC4_DAT0_PAA0, - TEGRA_PIN_SDMMC4_DAT1_PAA1, - TEGRA_PIN_SDMMC4_DAT2_PAA2, - TEGRA_PIN_SDMMC4_DAT3_PAA3, - TEGRA_PIN_SDMMC4_DAT4_PAA4, - TEGRA_PIN_SDMMC4_DAT5_PAA5, - TEGRA_PIN_SDMMC4_DAT6_PAA6, - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_PBB0, - TEGRA_PIN_CAM_I2C_SCL_PBB1, - TEGRA_PIN_CAM_I2C_SDA_PBB2, - TEGRA_PIN_PBB3, - TEGRA_PIN_PCC2, -}; - -static const unsigned drive_gmf_pins[] = { - TEGRA_PIN_PBB4, - TEGRA_PIN_PBB5, - TEGRA_PIN_PBB6, - TEGRA_PIN_PBB7, -}; - -static const unsigned drive_gmg_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned drive_gmh_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned drive_dev3_pins[] = { -}; - -static const unsigned drive_cec_pins[] = { -}; - -static const unsigned drive_at6_pins[] = { -}; - -static const unsigned drive_dap5_pins[] = { -}; - -static const unsigned drive_usb_vbus_en_pins[] = { -}; - -static const unsigned drive_ao3_pins[] = { -}; - -static const unsigned drive_hv0_pins[] = { -}; - -static const unsigned drive_sdio4_pins[] = { -}; - -static const unsigned drive_ao0_pins[] = { -}; - -enum tegra_mux { - TEGRA_MUX_BLINK, - TEGRA_MUX_CEC, - TEGRA_MUX_CLDVFS, - TEGRA_MUX_CLK, - TEGRA_MUX_CLK12, - TEGRA_MUX_CPU, - TEGRA_MUX_DAP, - TEGRA_MUX_DAP1, - TEGRA_MUX_DAP2, - TEGRA_MUX_DEV3, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYA_ALT, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DTV, - TEGRA_MUX_EMC_DLL, - TEGRA_MUX_EXTPERIPH1, - TEGRA_MUX_EXTPERIPH2, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_ALT, - TEGRA_MUX_HDA, - TEGRA_MUX_HSI, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2C4, - TEGRA_MUX_I2CPWR, - TEGRA_MUX_I2S0, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4, - TEGRA_MUX_IRDA, - TEGRA_MUX_KBC, - TEGRA_MUX_NAND, - TEGRA_MUX_NAND_ALT, - TEGRA_MUX_OWR, - TEGRA_MUX_PMI, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_PWRON, - TEGRA_MUX_RESET_OUT_N, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC2, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SDMMC4, - TEGRA_MUX_SOC, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SPI5, - TEGRA_MUX_SPI6, - TEGRA_MUX_SYSCLK, - TEGRA_MUX_TRACE, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_ULPI, - TEGRA_MUX_USB, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VI, - TEGRA_MUX_VI_ALT1, - TEGRA_MUX_VI_ALT3, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra114_functions[] = { - FUNCTION(blink), - FUNCTION(cec), - FUNCTION(cldvfs), - FUNCTION(clk), - FUNCTION(clk12), - FUNCTION(cpu), - FUNCTION(dap), - FUNCTION(dap1), - FUNCTION(dap2), - FUNCTION(dev3), - FUNCTION(displaya), - FUNCTION(displaya_alt), - FUNCTION(displayb), - FUNCTION(dtv), - FUNCTION(emc_dll), - FUNCTION(extperiph1), - FUNCTION(extperiph2), - FUNCTION(extperiph3), - FUNCTION(gmi), - FUNCTION(gmi_alt), - FUNCTION(hda), - FUNCTION(hsi), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2c4), - FUNCTION(i2cpwr), - FUNCTION(i2s0), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4), - FUNCTION(irda), - FUNCTION(kbc), - FUNCTION(nand), - FUNCTION(nand_alt), - FUNCTION(owr), - FUNCTION(pmi), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(pwron), - FUNCTION(reset_out_n), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sdmmc1), - FUNCTION(sdmmc2), - FUNCTION(sdmmc3), - FUNCTION(sdmmc4), - FUNCTION(soc), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(spi5), - FUNCTION(spi6), - FUNCTION(sysclk), - FUNCTION(trace), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(ulpi), - FUNCTION(usb), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vi), - FUNCTION(vi_alt1), - FUNCTION(vi_alt3), -}; - -#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 5, \ - .odrain_bit = PINGROUP_BIT_##od(6), \ - .lock_bit = 7, \ - .ioreset_bit = PINGROUP_BIT_##ior(8), \ - .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ - .drv_reg = -1, \ - } - -#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ - drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ - slwf_b, slwf_w, drvtype) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ - } - -static const struct tegra_pingroup tegra114_groups[] = { - /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ - PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), - PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), - PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), - PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), - PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), - PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), - PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), - PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), - PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), - PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), - PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), - PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), - PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), - PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), - PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3038, N, N, N), - PINGROUP(dap3_sclk_pp3, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x303c, N, N, N), - PINGROUP(pv0, USB, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), - PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), - PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), - PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), - PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), - PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), - PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), - PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), - PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), - PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), - PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), - PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), - PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), - PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), - PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), - PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, RSVD3, SPI4, 0x316c, N, N, N), - PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, RSVD3, SPI4, 0x3170, N, N, N), - PINGROUP(uart3_txd_pw6, UARTC, RSVD2, RSVD3, SPI4, 0x3174, N, N, N), - PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, RSVD3, SPI4, 0x3178, N, N, N), - PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, SPI4, 0x317c, N, N, N), - PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, DISPLAYA, 0x3180, N, N, N), - PINGROUP(pu0, OWR, UARTA, RSVD3, RSVD4, 0x3184, N, N, N), - PINGROUP(pu1, RSVD1, UARTA, RSVD3, RSVD4, 0x3188, N, N, N), - PINGROUP(pu2, RSVD1, UARTA, RSVD3, RSVD4, 0x318c, N, N, N), - PINGROUP(pu3, PWM0, UARTA, DISPLAYA, DISPLAYB, 0x3190, N, N, N), - PINGROUP(pu4, PWM1, UARTA, DISPLAYA, DISPLAYB, 0x3194, N, N, N), - PINGROUP(pu5, PWM2, UARTA, DISPLAYA, DISPLAYB, 0x3198, N, N, N), - PINGROUP(pu6, PWM3, UARTA, USB, DISPLAYB, 0x319c, N, N, N), - PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), - PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), - PINGROUP(dap4_fs_pp4, I2S3, RSVD2, DTV, RSVD4, 0x31a8, N, N, N), - PINGROUP(dap4_din_pp5, I2S3, RSVD2, RSVD3, RSVD4, 0x31ac, N, N, N), - PINGROUP(dap4_dout_pp6, I2S3, RSVD2, DTV, RSVD4, 0x31b0, N, N, N), - PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, RSVD3, RSVD4, 0x31b4, N, N, N), - PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), - PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), - PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N, N), - PINGROUP(gmi_iordy_pi5, SDMMC2, RSVD2, GMI, TRACE, 0x31c4, N, N, N), - PINGROUP(gmi_wait_pi7, SPI4, NAND, GMI, DTV, 0x31c8, N, N, N), - PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, TRACE, 0x31cc, N, N, N), - PINGROUP(gmi_clk_pk1, SDMMC2, NAND, GMI, TRACE, 0x31d0, N, N, N), - PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, USB, 0x31d4, N, N, N), - PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, SOC, 0x31d8, N, N, N), - PINGROUP(gmi_cs2_n_pk3, SDMMC2, NAND, GMI, TRACE, 0x31dc, N, N, N), - PINGROUP(gmi_cs3_n_pk4, SDMMC2, NAND, GMI, GMI_ALT, 0x31e0, N, N, N), - PINGROUP(gmi_cs4_n_pk2, USB, NAND, GMI, TRACE, 0x31e4, N, N, N), - PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SPI4, 0x31e8, N, N, N), - PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, SDMMC2, 0x31ec, N, N, N), - PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N, N), - PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N, N), - PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N, N), - PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N, N), - PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N, N), - PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, SPI4, 0x3204, N, N, N), - PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, SPI4, 0x3208, N, N, N), - PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, SPI4, 0x320c, N, N, N), - PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, DTV, 0x3210, N, N, N), - PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, CLDVFS, 0x3214, N, N, N), - PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, CLDVFS, 0x3218, N, N, N), - PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, USB, 0x321c, N, N, N), - PINGROUP(gmi_ad12_ph4, SDMMC2, NAND, GMI, RSVD4, 0x3220, N, N, N), - PINGROUP(gmi_ad13_ph5, SDMMC2, NAND, GMI, RSVD4, 0x3224, N, N, N), - PINGROUP(gmi_ad14_ph6, SDMMC2, NAND, GMI, DTV, 0x3228, N, N, N), - PINGROUP(gmi_ad15_ph7, SDMMC2, NAND, GMI, DTV, 0x322c, N, N, N), - PINGROUP(gmi_a16_pj7, UARTD, TRACE, GMI, GMI_ALT, 0x3230, N, N, N), - PINGROUP(gmi_a17_pb0, UARTD, RSVD2, GMI, TRACE, 0x3234, N, N, N), - PINGROUP(gmi_a18_pb1, UARTD, RSVD2, GMI, TRACE, 0x3238, N, N, N), - PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, TRACE, 0x323c, N, N, N), - PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, SPI4, 0x3240, N, N, N), - PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, SOC, 0x3244, N, N, N), - PINGROUP(gmi_dqs_p_pj3, SDMMC2, NAND, GMI, TRACE, 0x3248, N, N, N), - PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N, N), - PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), - PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), - PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), - PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), - PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), - PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), - PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), - PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), - PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), - PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, GMI, RSVD4, 0x3274, N, Y, N), - PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), - PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), - PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, RSVD4, 0x3284, N, N, N), - PINGROUP(pcc1, I2S4, RSVD2, RSVD3, RSVD4, 0x3288, N, N, N), - PINGROUP(pbb0, I2S4, VI, VI_ALT1, VI_ALT3, 0x328c, N, N, N), - PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, RSVD4, 0x3290, Y, N, N), - PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, RSVD4, 0x3294, Y, N, N), - PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, RSVD4, 0x3298, N, N, N), - PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, RSVD4, 0x329c, N, N, N), - PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, RSVD4, 0x32a0, N, N, N), - PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, RSVD4, 0x32a4, N, N, N), - PINGROUP(pbb7, I2S4, RSVD2, RSVD3, RSVD4, 0x32a8, N, N, N), - PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N, N), - PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), - PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), - PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), - PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), - PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), - PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), - PINGROUP(kb_row3_pr3, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32c8, N, N, N), - PINGROUP(kb_row4_pr4, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32cc, N, N, N), - PINGROUP(kb_row5_pr5, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32d0, N, N, N), - PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), - PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), - PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), - PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), - PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), - PINGROUP(kb_col0_pq0, KBC, USB, SPI2, EMC_DLL, 0x32fc, N, N, N), - PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, EMC_DLL, 0x3300, N, N, N), - PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), - PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), - PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), - PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC1, RSVD4, 0x3310, N, N, N), - PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, RSVD4, 0x3314, N, N, N), - PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, RSVD4, 0x3318, N, N, N), - PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), - PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N, N), - PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), - PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), - PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), - PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), - PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), - PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), - PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), - PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, RSVD4, 0x3340, N, N, N), - PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), - PINGROUP(clk1_req_pee2, DAP, DAP1, RSVD3, RSVD4, 0x3348, N, N, N), - PINGROUP(clk1_out_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), - PINGROUP(spdif_in_pk6, SPDIF, USB, RSVD3, RSVD4, 0x3350, N, N, N), - PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, RSVD4, 0x3354, N, N, N), - PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, RSVD4, 0x3358, N, N, N), - PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, RSVD4, 0x335c, N, N, N), - PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, RSVD4, 0x3360, N, N, N), - PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, RSVD4, 0x3364, N, N, N), - PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, RSVD3, RSVD4, 0x3368, N, N, N), - PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, RSVD3, RSVD4, 0x336c, N, N, N), - PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, RSVD3, RSVD4, 0x3370, N, N, N), - PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, RSVD3, RSVD4, 0x3374, N, N, N), - PINGROUP(gpio_x4_aud_px4, RSVD1, SPI1, SPI2, DAP2, 0x3378, N, N, N), - PINGROUP(gpio_x5_aud_px5, RSVD1, SPI1, SPI2, RSVD4, 0x337c, N, N, N), - PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, RSVD4, 0x3380, N, N, N), - PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), - PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), - PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), - PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), - PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), - PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), - PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), - PINGROUP(hdmi_cec_pee3, CEC, SDMMC3, RSVD3, SOC, 0x33e0, Y, N, N), - PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), - PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), - PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), - PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), - PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), - PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), - PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), - PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), - PINGROUP(gmi_clk_lb, SDMMC2, NAND, GMI, RSVD4, 0x3404, N, N, N), - PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), - - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ - DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at1, 0x870, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at2, 0x874, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at3, 0x878, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at4, 0x87c, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(ddc, 0x8fc, 2, 3, -1, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gma, 0x900, 2, 3, -1, 14, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, Y), - DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao3, 0x9a0, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(hv0, 0x9a4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(sdio4, 0x9a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao0, 0x9ac, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), -}; - -static const struct tegra_pinctrl_soc_data tegra114_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra114_pins, - .npins = ARRAY_SIZE(tegra114_pins), - .functions = tegra114_functions, - .nfunctions = ARRAY_SIZE(tegra114_functions), - .groups = tegra114_groups, - .ngroups = ARRAY_SIZE(tegra114_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra114_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra114_pinctrl); -} - -static const struct of_device_id tegra114_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra114-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra114_pinctrl_of_match); - -static struct platform_driver tegra114_pinctrl_driver = { - .driver = { - .name = "tegra114-pinctrl", - .of_match_table = tegra114_pinctrl_of_match, - }, - .probe = tegra114_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra114_pinctrl_driver); - -MODULE_AUTHOR("Pritesh Raithatha "); -MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra124.c b/drivers/pinctrl/pinctrl-tegra124.c deleted file mode 100644 index 7cd44c7c296d..000000000000 --- a/drivers/pinctrl/pinctrl-tegra124.c +++ /dev/null @@ -1,2084 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra124 pinmux - * - * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. - * - * 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 "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_PB0 _GPIO(8) -#define TEGRA_PIN_PB1 _GPIO(9) -#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_PC7 _GPIO(23) -#define TEGRA_PIN_PG0 _GPIO(48) -#define TEGRA_PIN_PG1 _GPIO(49) -#define TEGRA_PIN_PG2 _GPIO(50) -#define TEGRA_PIN_PG3 _GPIO(51) -#define TEGRA_PIN_PG4 _GPIO(52) -#define TEGRA_PIN_PG5 _GPIO(53) -#define TEGRA_PIN_PG6 _GPIO(54) -#define TEGRA_PIN_PG7 _GPIO(55) -#define TEGRA_PIN_PH0 _GPIO(56) -#define TEGRA_PIN_PH1 _GPIO(57) -#define TEGRA_PIN_PH2 _GPIO(58) -#define TEGRA_PIN_PH3 _GPIO(59) -#define TEGRA_PIN_PH4 _GPIO(60) -#define TEGRA_PIN_PH5 _GPIO(61) -#define TEGRA_PIN_PH6 _GPIO(62) -#define TEGRA_PIN_PH7 _GPIO(63) -#define TEGRA_PIN_PI0 _GPIO(64) -#define TEGRA_PIN_PI1 _GPIO(65) -#define TEGRA_PIN_PI2 _GPIO(66) -#define TEGRA_PIN_PI3 _GPIO(67) -#define TEGRA_PIN_PI4 _GPIO(68) -#define TEGRA_PIN_PI5 _GPIO(69) -#define TEGRA_PIN_PI6 _GPIO(70) -#define TEGRA_PIN_PI7 _GPIO(71) -#define TEGRA_PIN_PJ0 _GPIO(72) -#define TEGRA_PIN_PJ2 _GPIO(74) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_PJ7 _GPIO(79) -#define TEGRA_PIN_PK0 _GPIO(80) -#define TEGRA_PIN_PK1 _GPIO(81) -#define TEGRA_PIN_PK2 _GPIO(82) -#define TEGRA_PIN_PK3 _GPIO(83) -#define TEGRA_PIN_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_PK7 _GPIO(87) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) -#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) -#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) -#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) -#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) -#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) -#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) -#define TEGRA_PIN_KB_ROW16_PT0 _GPIO(152) -#define TEGRA_PIN_KB_ROW17_PT1 _GPIO(153) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) -#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) -#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) -#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) -#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) -#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) -#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) -#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) -#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) -#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) -#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) -#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) -#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) -#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) -#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) -#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) -#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) -#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) -#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) -#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) -#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) -#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) -#define TEGRA_PIN_PBB0 _GPIO(216) -#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) -#define TEGRA_PIN_PBB3 _GPIO(219) -#define TEGRA_PIN_PBB4 _GPIO(220) -#define TEGRA_PIN_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) -#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) -#define TEGRA_PIN_PCC1 _GPIO(225) -#define TEGRA_PIN_PCC2 _GPIO(226) -#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) -#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) -#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) -#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) -#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) -#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) -#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) -#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) -#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) -#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2 _GPIO(242) -#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) -#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) -#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) -#define TEGRA_PIN_DP_HPD_PFF0 _GPIO(248) -#define TEGRA_PIN_USB_VBUS_EN2_PFF1 _GPIO(249) -#define TEGRA_PIN_PFF2 _GPIO(250) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_PFF2 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) -#define TEGRA_PIN_PWR_INT_N _PIN(2) -#define TEGRA_PIN_GMI_CLK_LB _PIN(3) -#define TEGRA_PIN_RESET_OUT_N _PIN(4) -#define TEGRA_PIN_OWR _PIN(5) -#define TEGRA_PIN_CLK_32K_IN _PIN(6) -#define TEGRA_PIN_JTAG_RTCK _PIN(7) -#define TEGRA_PIN_DSI_B_CLK_P _PIN(8) -#define TEGRA_PIN_DSI_B_CLK_N _PIN(9) -#define TEGRA_PIN_DSI_B_D0_P _PIN(10) -#define TEGRA_PIN_DSI_B_D0_N _PIN(11) -#define TEGRA_PIN_DSI_B_D1_P _PIN(12) -#define TEGRA_PIN_DSI_B_D1_N _PIN(13) -#define TEGRA_PIN_DSI_B_D2_P _PIN(14) -#define TEGRA_PIN_DSI_B_D2_N _PIN(15) -#define TEGRA_PIN_DSI_B_D3_P _PIN(16) -#define TEGRA_PIN_DSI_B_D3_N _PIN(17) - -static const struct pinctrl_pin_desc tegra124_pins[] = { - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"), - PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"), - PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"), - PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"), - PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"), - PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"), - PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"), - PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"), - PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"), - PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"), - PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"), - PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"), - PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"), - PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"), - PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"), - PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"), - PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), - PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"), - PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"), - PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"), - PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"), - PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"), - PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"), - PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"), - PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"), - PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"), - PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"), - PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"), - PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), - PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), - PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), - PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), - PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW16 PT0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW17 PT1"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), - PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), - PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), - PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), - PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), - PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), - PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), - PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), - PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), - PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), - PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), - PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"), - PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), - PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), - PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"), - PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"), -}; - -static const unsigned clk_32k_out_pa0_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, -}; - -static const unsigned uart3_cts_n_pa1_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned dap2_fs_pa2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, -}; - -static const unsigned dap2_sclk_pa3_pins[] = { - TEGRA_PIN_DAP2_SCLK_PA3, -}; - -static const unsigned dap2_din_pa4_pins[] = { - TEGRA_PIN_DAP2_DIN_PA4, -}; - -static const unsigned dap2_dout_pa5_pins[] = { - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned sdmmc3_clk_pa6_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, -}; - -static const unsigned sdmmc3_cmd_pa7_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PA7, -}; - -static const unsigned pb0_pins[] = { - TEGRA_PIN_PB0, -}; - -static const unsigned pb1_pins[] = { - TEGRA_PIN_PB1, -}; - -static const unsigned sdmmc3_dat3_pb4_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PB4, -}; - -static const unsigned sdmmc3_dat2_pb5_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PB5, -}; - -static const unsigned sdmmc3_dat1_pb6_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PB6, -}; - -static const unsigned sdmmc3_dat0_pb7_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned uart3_rts_n_pc0_pins[] = { - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned uart2_txd_pc2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uart2_rxd_pc3_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, -}; - -static const unsigned gen1_i2c_scl_pc4_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, -}; - -static const unsigned gen1_i2c_sda_pc5_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned pc7_pins[] = { - TEGRA_PIN_PC7, -}; - -static const unsigned pg0_pins[] = { - TEGRA_PIN_PG0, -}; - -static const unsigned pg1_pins[] = { - TEGRA_PIN_PG1, -}; - -static const unsigned pg2_pins[] = { - TEGRA_PIN_PG2, -}; - -static const unsigned pg3_pins[] = { - TEGRA_PIN_PG3, -}; - -static const unsigned pg4_pins[] = { - TEGRA_PIN_PG4, -}; - -static const unsigned pg5_pins[] = { - TEGRA_PIN_PG5, -}; - -static const unsigned pg6_pins[] = { - TEGRA_PIN_PG6, -}; - -static const unsigned pg7_pins[] = { - TEGRA_PIN_PG7, -}; - -static const unsigned ph0_pins[] = { - TEGRA_PIN_PH0, -}; - -static const unsigned ph1_pins[] = { - TEGRA_PIN_PH1, -}; - -static const unsigned ph2_pins[] = { - TEGRA_PIN_PH2, -}; - -static const unsigned ph3_pins[] = { - TEGRA_PIN_PH3, -}; - -static const unsigned ph4_pins[] = { - TEGRA_PIN_PH4, -}; - -static const unsigned ph5_pins[] = { - TEGRA_PIN_PH5, -}; - -static const unsigned ph6_pins[] = { - TEGRA_PIN_PH6, -}; - -static const unsigned ph7_pins[] = { - TEGRA_PIN_PH7, -}; - -static const unsigned pi0_pins[] = { - TEGRA_PIN_PI0, -}; - -static const unsigned pi1_pins[] = { - TEGRA_PIN_PI1, -}; - -static const unsigned pi2_pins[] = { - TEGRA_PIN_PI2, -}; - -static const unsigned pi3_pins[] = { - TEGRA_PIN_PI3, -}; - -static const unsigned pi4_pins[] = { - TEGRA_PIN_PI4, -}; - -static const unsigned pi5_pins[] = { - TEGRA_PIN_PI5, -}; - -static const unsigned pi6_pins[] = { - TEGRA_PIN_PI6, -}; - -static const unsigned pi7_pins[] = { - TEGRA_PIN_PI7, -}; - -static const unsigned pj0_pins[] = { - TEGRA_PIN_PJ0, -}; - -static const unsigned pj2_pins[] = { - TEGRA_PIN_PJ2, -}; - -static const unsigned uart2_cts_n_pj5_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned uart2_rts_n_pj6_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned pj7_pins[] = { - TEGRA_PIN_PJ7, -}; - -static const unsigned pk0_pins[] = { - TEGRA_PIN_PK0, -}; - -static const unsigned pk1_pins[] = { - TEGRA_PIN_PK1, -}; - -static const unsigned pk2_pins[] = { - TEGRA_PIN_PK2, -}; - -static const unsigned pk3_pins[] = { - TEGRA_PIN_PK3, -}; - -static const unsigned pk4_pins[] = { - TEGRA_PIN_PK4, -}; - -static const unsigned spdif_out_pk5_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spdif_in_pk6_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned pk7_pins[] = { - TEGRA_PIN_PK7, -}; - -static const unsigned dap1_fs_pn0_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, -}; - -static const unsigned dap1_din_pn1_pins[] = { - TEGRA_PIN_DAP1_DIN_PN1, -}; - -static const unsigned dap1_dout_pn2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PN2, -}; - -static const unsigned dap1_sclk_pn3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned usb_vbus_en0_pn4_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PN4, -}; - -static const unsigned usb_vbus_en1_pn5_pins[] = { - TEGRA_PIN_USB_VBUS_EN1_PN5, -}; - -static const unsigned hdmi_int_pn7_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned ulpi_data7_po0_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned ulpi_data0_po1_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, -}; - -static const unsigned ulpi_data1_po2_pins[] = { - TEGRA_PIN_ULPI_DATA1_PO2, -}; - -static const unsigned ulpi_data2_po3_pins[] = { - TEGRA_PIN_ULPI_DATA2_PO3, -}; - -static const unsigned ulpi_data3_po4_pins[] = { - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned ulpi_data4_po5_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, -}; - -static const unsigned ulpi_data5_po6_pins[] = { - TEGRA_PIN_ULPI_DATA5_PO6, -}; - -static const unsigned ulpi_data6_po7_pins[] = { - TEGRA_PIN_ULPI_DATA6_PO7, -}; - -static const unsigned dap3_fs_pp0_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, -}; - -static const unsigned dap3_din_pp1_pins[] = { - TEGRA_PIN_DAP3_DIN_PP1, -}; - -static const unsigned dap3_dout_pp2_pins[] = { - TEGRA_PIN_DAP3_DOUT_PP2, -}; - -static const unsigned dap3_sclk_pp3_pins[] = { - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_fs_pp4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, -}; - -static const unsigned dap4_din_pp5_pins[] = { - TEGRA_PIN_DAP4_DIN_PP5, -}; - -static const unsigned dap4_dout_pp6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PP6, -}; - -static const unsigned dap4_sclk_pp7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned kb_col0_pq0_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, -}; - -static const unsigned kb_col1_pq1_pins[] = { - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kb_col2_pq2_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, -}; - -static const unsigned kb_col3_pq3_pins[] = { - TEGRA_PIN_KB_COL3_PQ3, -}; - -static const unsigned kb_col4_pq4_pins[] = { - TEGRA_PIN_KB_COL4_PQ4, -}; - -static const unsigned kb_col5_pq5_pins[] = { - TEGRA_PIN_KB_COL5_PQ5, -}; - -static const unsigned kb_col6_pq6_pins[] = { - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned kb_col7_pq7_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kb_row0_pr0_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, -}; - -static const unsigned kb_row1_pr1_pins[] = { - TEGRA_PIN_KB_ROW1_PR1, -}; - -static const unsigned kb_row2_pr2_pins[] = { - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kb_row3_pr3_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, -}; - -static const unsigned kb_row4_pr4_pins[] = { - TEGRA_PIN_KB_ROW4_PR4, -}; - -static const unsigned kb_row5_pr5_pins[] = { - TEGRA_PIN_KB_ROW5_PR5, -}; - -static const unsigned kb_row6_pr6_pins[] = { - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kb_row7_pr7_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned kb_row8_ps0_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, -}; - -static const unsigned kb_row9_ps1_pins[] = { - TEGRA_PIN_KB_ROW9_PS1, -}; - -static const unsigned kb_row10_ps2_pins[] = { - TEGRA_PIN_KB_ROW10_PS2, -}; - -static const unsigned kb_row11_ps3_pins[] = { - TEGRA_PIN_KB_ROW11_PS3, -}; - -static const unsigned kb_row12_ps4_pins[] = { - TEGRA_PIN_KB_ROW12_PS4, -}; - -static const unsigned kb_row13_ps5_pins[] = { - TEGRA_PIN_KB_ROW13_PS5, -}; - -static const unsigned kb_row14_ps6_pins[] = { - TEGRA_PIN_KB_ROW14_PS6, -}; - -static const unsigned kb_row15_ps7_pins[] = { - TEGRA_PIN_KB_ROW15_PS7, -}; - -static const unsigned kb_row16_pt0_pins[] = { - TEGRA_PIN_KB_ROW16_PT0, -}; - -static const unsigned kb_row17_pt1_pins[] = { - TEGRA_PIN_KB_ROW17_PT1, -}; - -static const unsigned gen2_i2c_scl_pt5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, -}; - -static const unsigned gen2_i2c_sda_pt6_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned sdmmc4_cmd_pt7_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned pu0_pins[] = { - TEGRA_PIN_PU0, -}; - -static const unsigned pu1_pins[] = { - TEGRA_PIN_PU1, -}; - -static const unsigned pu2_pins[] = { - TEGRA_PIN_PU2, -}; - -static const unsigned pu3_pins[] = { - TEGRA_PIN_PU3, -}; - -static const unsigned pu4_pins[] = { - TEGRA_PIN_PU4, -}; - -static const unsigned pu5_pins[] = { - TEGRA_PIN_PU5, -}; - -static const unsigned pu6_pins[] = { - TEGRA_PIN_PU6, -}; - -static const unsigned pv0_pins[] = { - TEGRA_PIN_PV0, -}; - -static const unsigned pv1_pins[] = { - TEGRA_PIN_PV1, -}; - -static const unsigned sdmmc3_cd_n_pv2_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, -}; - -static const unsigned sdmmc1_wp_n_pv3_pins[] = { - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned ddc_scl_pv4_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, -}; - -static const unsigned ddc_sda_pv5_pins[] = { - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned gpio_w2_aud_pw2_pins[] = { - TEGRA_PIN_GPIO_W2_AUD_PW2, -}; - -static const unsigned gpio_w3_aud_pw3_pins[] = { - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned dap_mclk1_pw4_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, -}; - -static const unsigned clk2_out_pw5_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, -}; - -static const unsigned uart3_txd_pw6_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned uart3_rxd_pw7_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned dvfs_pwm_px0_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, -}; - -static const unsigned gpio_x1_aud_px1_pins[] = { - TEGRA_PIN_GPIO_X1_AUD_PX1, -}; - -static const unsigned dvfs_clk_px2_pins[] = { - TEGRA_PIN_DVFS_CLK_PX2, -}; - -static const unsigned gpio_x3_aud_px3_pins[] = { - TEGRA_PIN_GPIO_X3_AUD_PX3, -}; - -static const unsigned gpio_x4_aud_px4_pins[] = { - TEGRA_PIN_GPIO_X4_AUD_PX4, -}; - -static const unsigned gpio_x5_aud_px5_pins[] = { - TEGRA_PIN_GPIO_X5_AUD_PX5, -}; - -static const unsigned gpio_x6_aud_px6_pins[] = { - TEGRA_PIN_GPIO_X6_AUD_PX6, -}; - -static const unsigned gpio_x7_aud_px7_pins[] = { - TEGRA_PIN_GPIO_X7_AUD_PX7, -}; - -static const unsigned ulpi_clk_py0_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, -}; - -static const unsigned ulpi_dir_py1_pins[] = { - TEGRA_PIN_ULPI_DIR_PY1, -}; - -static const unsigned ulpi_nxt_py2_pins[] = { - TEGRA_PIN_ULPI_NXT_PY2, -}; - -static const unsigned ulpi_stp_py3_pins[] = { - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned sdmmc1_dat3_py4_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, -}; - -static const unsigned sdmmc1_dat2_py5_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PY5, -}; - -static const unsigned sdmmc1_dat1_py6_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PY6, -}; - -static const unsigned sdmmc1_dat0_py7_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PY7, -}; - -static const unsigned sdmmc1_clk_pz0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PZ0, -}; - -static const unsigned sdmmc1_cmd_pz1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned pwr_i2c_scl_pz6_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, -}; - -static const unsigned pwr_i2c_sda_pz7_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned sdmmc4_dat0_paa0_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, -}; - -static const unsigned sdmmc4_dat1_paa1_pins[] = { - TEGRA_PIN_SDMMC4_DAT1_PAA1, -}; - -static const unsigned sdmmc4_dat2_paa2_pins[] = { - TEGRA_PIN_SDMMC4_DAT2_PAA2, -}; - -static const unsigned sdmmc4_dat3_paa3_pins[] = { - TEGRA_PIN_SDMMC4_DAT3_PAA3, -}; - -static const unsigned sdmmc4_dat4_paa4_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, -}; - -static const unsigned sdmmc4_dat5_paa5_pins[] = { - TEGRA_PIN_SDMMC4_DAT5_PAA5, -}; - -static const unsigned sdmmc4_dat6_paa6_pins[] = { - TEGRA_PIN_SDMMC4_DAT6_PAA6, -}; - -static const unsigned sdmmc4_dat7_paa7_pins[] = { - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned pbb0_pins[] = { - TEGRA_PIN_PBB0, -}; - -static const unsigned cam_i2c_scl_pbb1_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB1, -}; - -static const unsigned cam_i2c_sda_pbb2_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PBB2, -}; - -static const unsigned pbb3_pins[] = { - TEGRA_PIN_PBB3, -}; - -static const unsigned pbb4_pins[] = { - TEGRA_PIN_PBB4, -}; - -static const unsigned pbb5_pins[] = { - TEGRA_PIN_PBB5, -}; - -static const unsigned pbb6_pins[] = { - TEGRA_PIN_PBB6, -}; - -static const unsigned pbb7_pins[] = { - TEGRA_PIN_PBB7, -}; - -static const unsigned cam_mclk_pcc0_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned pcc1_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned pcc2_pins[] = { - TEGRA_PIN_PCC2, -}; - -static const unsigned sdmmc4_clk_pcc4_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned clk2_req_pcc5_pins[] = { - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned pex_l0_rst_n_pdd1_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PDD1, -}; - -static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, -}; - -static const unsigned pex_wake_n_pdd3_pins[] = { - TEGRA_PIN_PEX_WAKE_N_PDD3, -}; - -static const unsigned pex_l1_rst_n_pdd5_pins[] = { - TEGRA_PIN_PEX_L1_RST_N_PDD5, -}; - -static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, -}; - -static const unsigned clk3_out_pee0_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, -}; - -static const unsigned clk3_req_pee1_pins[] = { - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned dap_mclk1_req_pee2_pins[] = { - TEGRA_PIN_DAP_MCLK1_REQ_PEE2, -}; - -static const unsigned hdmi_cec_pee3_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, -}; - -static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned dp_hpd_pff0_pins[] = { - TEGRA_PIN_DP_HPD_PFF0, -}; - -static const unsigned usb_vbus_en2_pff1_pins[] = { - TEGRA_PIN_USB_VBUS_EN2_PFF1, -}; - -static const unsigned pff2_pins[] = { - TEGRA_PIN_PFF2, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned gmi_clk_lb_pins[] = { - TEGRA_PIN_GMI_CLK_LB, -}; - -static const unsigned reset_out_n_pins[] = { - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned jtag_rtck_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, - TEGRA_PIN_CLK_32K_IN, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, - TEGRA_PIN_KB_ROW16_PT0, - TEGRA_PIN_KB_ROW17_PT1, - TEGRA_PIN_SDMMC3_CD_N_PV2, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_PH0, - TEGRA_PIN_PH1, - TEGRA_PIN_PH2, - TEGRA_PIN_PH3, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_PG0, - TEGRA_PIN_PG1, - TEGRA_PIN_PG2, - TEGRA_PIN_PG3, - TEGRA_PIN_PG4, - TEGRA_PIN_PG5, - TEGRA_PIN_PG6, - TEGRA_PIN_PG7, - TEGRA_PIN_PI0, - TEGRA_PIN_PI1, - TEGRA_PIN_PI3, - TEGRA_PIN_PI4, - TEGRA_PIN_PI7, - TEGRA_PIN_PK0, - TEGRA_PIN_PK2, -}; - -static const unsigned drive_at3_pins[] = { - TEGRA_PIN_PC7, - TEGRA_PIN_PJ0, -}; - -static const unsigned drive_at4_pins[] = { - TEGRA_PIN_PB0, - TEGRA_PIN_PB1, - TEGRA_PIN_PJ0, - TEGRA_PIN_PJ7, - TEGRA_PIN_PK7, -}; - -static const unsigned drive_at5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, - TEGRA_PIN_DAP_MCLK1_REQ_PEE2, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, -}; - -static const unsigned drive_sdio3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, - TEGRA_PIN_SDMMC3_CMD_PA7, - TEGRA_PIN_SDMMC3_DAT3_PB4, - TEGRA_PIN_SDMMC3_DAT2_PB5, - TEGRA_PIN_SDMMC3_DAT1_PB6, - TEGRA_PIN_SDMMC3_DAT0_PB7, - TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, - TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_DVFS_PWM_PX0, - TEGRA_PIN_GPIO_X1_AUD_PX1, - TEGRA_PIN_DVFS_CLK_PX2, - TEGRA_PIN_GPIO_X3_AUD_PX3, - TEGRA_PIN_GPIO_X4_AUD_PX4, - TEGRA_PIN_GPIO_X5_AUD_PX5, - TEGRA_PIN_GPIO_X6_AUD_PX6, - TEGRA_PIN_GPIO_X7_AUD_PX7, - TEGRA_PIN_GPIO_W2_AUD_PW2, - TEGRA_PIN_GPIO_W3_AUD_PW3, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_CTS_N_PJ5, - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, - TEGRA_PIN_SDMMC1_DAT2_PY5, - TEGRA_PIN_SDMMC1_DAT1_PY6, - TEGRA_PIN_SDMMC1_DAT0_PY7, - TEGRA_PIN_SDMMC1_CLK_PZ0, - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, - TEGRA_PIN_SDMMC4_CMD_PT7, - TEGRA_PIN_SDMMC4_DAT0_PAA0, - TEGRA_PIN_SDMMC4_DAT1_PAA1, - TEGRA_PIN_SDMMC4_DAT2_PAA2, - TEGRA_PIN_SDMMC4_DAT3_PAA3, - TEGRA_PIN_SDMMC4_DAT4_PAA4, - TEGRA_PIN_SDMMC4_DAT5_PAA5, - TEGRA_PIN_SDMMC4_DAT6_PAA6, - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_PBB0, - TEGRA_PIN_CAM_I2C_SCL_PBB1, - TEGRA_PIN_CAM_I2C_SDA_PBB2, - TEGRA_PIN_PBB3, - TEGRA_PIN_PCC2, -}; - -static const unsigned drive_gmf_pins[] = { - TEGRA_PIN_PBB4, - TEGRA_PIN_PBB5, - TEGRA_PIN_PBB6, - TEGRA_PIN_PBB7, -}; - -static const unsigned drive_gmg_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned drive_gmh_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_SDMMC3_CD_N_PV2, - TEGRA_PIN_OWR, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned drive_gpv_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PDD1, - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, - TEGRA_PIN_PEX_WAKE_N_PDD3, - TEGRA_PIN_PEX_L1_RST_N_PDD5, - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, - TEGRA_PIN_USB_VBUS_EN2_PFF1, - TEGRA_PIN_PFF2, -}; - -static const unsigned drive_dev3_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned drive_cec_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned drive_at6_pins[] = { - TEGRA_PIN_PK1, - TEGRA_PIN_PK3, - TEGRA_PIN_PK4, - TEGRA_PIN_PI2, - TEGRA_PIN_PI5, - TEGRA_PIN_PI6, - TEGRA_PIN_PH4, - TEGRA_PIN_PH5, - TEGRA_PIN_PH6, - TEGRA_PIN_PH7, -}; - -static const unsigned drive_dap5_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, - TEGRA_PIN_SPDIF_OUT_PK5, - TEGRA_PIN_DP_HPD_PFF0, -}; - -static const unsigned drive_usb_vbus_en_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PN4, - TEGRA_PIN_USB_VBUS_EN1_PN5, -}; - -static const unsigned drive_ao3_pins[] = { - TEGRA_PIN_RESET_OUT_N, -}; - -static const unsigned drive_ao0_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned drive_hv0_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned drive_sdio4_pins[] = { - TEGRA_PIN_SDMMC1_WP_N_PV3, -}; - -static const unsigned drive_ao4_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned mipi_pad_ctrl_dsi_b_pins[] = { - TEGRA_PIN_DSI_B_CLK_P, - TEGRA_PIN_DSI_B_CLK_N, - TEGRA_PIN_DSI_B_D0_P, - TEGRA_PIN_DSI_B_D0_N, - TEGRA_PIN_DSI_B_D1_P, - TEGRA_PIN_DSI_B_D1_N, - TEGRA_PIN_DSI_B_D2_P, - TEGRA_PIN_DSI_B_D2_N, - TEGRA_PIN_DSI_B_D3_P, - TEGRA_PIN_DSI_B_D3_N, -}; - -enum tegra_mux { - TEGRA_MUX_BLINK, - TEGRA_MUX_CCLA, - TEGRA_MUX_CEC, - TEGRA_MUX_CLDVFS, - TEGRA_MUX_CLK, - TEGRA_MUX_CLK12, - TEGRA_MUX_CPU, - TEGRA_MUX_CSI, - TEGRA_MUX_DAP, - TEGRA_MUX_DAP1, - TEGRA_MUX_DAP2, - TEGRA_MUX_DEV3, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYA_ALT, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DP, - TEGRA_MUX_DSI_B, - TEGRA_MUX_DTV, - TEGRA_MUX_EXTPERIPH1, - TEGRA_MUX_EXTPERIPH2, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_ALT, - TEGRA_MUX_HDA, - TEGRA_MUX_HSI, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2C4, - TEGRA_MUX_I2CPWR, - TEGRA_MUX_I2S0, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4, - TEGRA_MUX_IRDA, - TEGRA_MUX_KBC, - TEGRA_MUX_OWR, - TEGRA_MUX_PE, - TEGRA_MUX_PE0, - TEGRA_MUX_PE1, - TEGRA_MUX_PMI, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_PWRON, - TEGRA_MUX_RESET_OUT_N, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SATA, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC2, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SDMMC4, - TEGRA_MUX_SOC, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SPI5, - TEGRA_MUX_SPI6, - TEGRA_MUX_SYS, - TEGRA_MUX_TMDS, - TEGRA_MUX_TRACE, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_ULPI, - TEGRA_MUX_USB, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VI, - TEGRA_MUX_VI_ALT1, - TEGRA_MUX_VI_ALT3, - TEGRA_MUX_VIMCLK2, - TEGRA_MUX_VIMCLK2_ALT, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra124_functions[] = { - FUNCTION(blink), - FUNCTION(ccla), - FUNCTION(cec), - FUNCTION(cldvfs), - FUNCTION(clk), - FUNCTION(clk12), - FUNCTION(cpu), - FUNCTION(csi), - FUNCTION(dap), - FUNCTION(dap1), - FUNCTION(dap2), - FUNCTION(dev3), - FUNCTION(displaya), - FUNCTION(displaya_alt), - FUNCTION(displayb), - FUNCTION(dp), - FUNCTION(dsi_b), - FUNCTION(dtv), - FUNCTION(extperiph1), - FUNCTION(extperiph2), - FUNCTION(extperiph3), - FUNCTION(gmi), - FUNCTION(gmi_alt), - FUNCTION(hda), - FUNCTION(hsi), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2c4), - FUNCTION(i2cpwr), - FUNCTION(i2s0), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4), - FUNCTION(irda), - FUNCTION(kbc), - FUNCTION(owr), - FUNCTION(pe), - FUNCTION(pe0), - FUNCTION(pe1), - FUNCTION(pmi), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(pwron), - FUNCTION(reset_out_n), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sata), - FUNCTION(sdmmc1), - FUNCTION(sdmmc2), - FUNCTION(sdmmc3), - FUNCTION(sdmmc4), - FUNCTION(soc), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(spi5), - FUNCTION(spi6), - FUNCTION(sys), - FUNCTION(tmds), - FUNCTION(trace), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(ulpi), - FUNCTION(usb), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vi), - FUNCTION(vi_alt1), - FUNCTION(vi_alt3), - FUNCTION(vimclk2), - FUNCTION(vimclk2_alt), -}; - -#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define MIPI_PAD_CTRL_PINGROUP_REG_A 0x820 /* bank 2 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) -#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r) ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 5, \ - .odrain_bit = PINGROUP_BIT_##od(6), \ - .lock_bit = 7, \ - .ioreset_bit = PINGROUP_BIT_##ior(8), \ - .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ - .drv_reg = -1, \ - } - -#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ - drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ - slwf_b, slwf_w, drvtype) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ - } - -#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1) \ - { \ - .name = "mipi_pad_ctrl_" #pg_name, \ - .pins = mipi_pad_ctrl_##pg_name##_pins, \ - .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_ ## f0, \ - TEGRA_MUX_ ## f1, \ - TEGRA_MUX_RSVD3, \ - TEGRA_MUX_RSVD4, \ - }, \ - .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r), \ - .mux_bank = 2, \ - .mux_bit = b, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = -1, \ - } - -static const struct tegra_pingroup tegra124_groups[] = { - /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ - PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), - PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), - PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), - PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), - PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), - PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), - PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), - PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), - PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), - PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), - PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), - PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), - PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), - PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), - PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, RSVD4, 0x3038, N, N, N), - PINGROUP(dap3_sclk_pp3, I2S2, SPI5, RSVD3, DISPLAYB, 0x303c, N, N, N), - PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), - PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), - PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), - PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), - PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), - PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), - PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), - PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), - PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), - PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), - PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), - PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), - PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), - PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), - PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), - PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N, N), - PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N, N), - PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, SPI4, 0x3174, N, N, N), - PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, SPI4, 0x3178, N, N, N), - PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, GMI, 0x317c, N, N, N), - PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, GMI, 0x3180, N, N, N), - PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N, N), - PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N, N), - PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N, N), - PINGROUP(pu3, PWM0, UARTA, GMI, DISPLAYB, 0x3190, N, N, N), - PINGROUP(pu4, PWM1, UARTA, GMI, DISPLAYB, 0x3194, N, N, N), - PINGROUP(pu5, PWM2, UARTA, GMI, DISPLAYB, 0x3198, N, N, N), - PINGROUP(pu6, PWM3, UARTA, RSVD3, GMI, 0x319c, N, N, N), - PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), - PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), - PINGROUP(dap4_fs_pp4, I2S3, GMI, DTV, RSVD4, 0x31a8, N, N, N), - PINGROUP(dap4_din_pp5, I2S3, GMI, RSVD3, RSVD4, 0x31ac, N, N, N), - PINGROUP(dap4_dout_pp6, I2S3, GMI, DTV, RSVD4, 0x31b0, N, N, N), - PINGROUP(dap4_sclk_pp7, I2S3, GMI, RSVD3, RSVD4, 0x31b4, N, N, N), - PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), - PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), - PINGROUP(pc7, RSVD1, RSVD2, GMI, GMI_ALT, 0x31c0, N, N, N), - PINGROUP(pi5, SDMMC2, RSVD2, GMI, RSVD4, 0x31c4, N, N, N), - PINGROUP(pi7, RSVD1, TRACE, GMI, DTV, 0x31c8, N, N, N), - PINGROUP(pk0, RSVD1, SDMMC3, GMI, SOC, 0x31cc, N, N, N), - PINGROUP(pk1, SDMMC2, TRACE, GMI, RSVD4, 0x31d0, N, N, N), - PINGROUP(pj0, RSVD1, RSVD2, GMI, USB, 0x31d4, N, N, N), - PINGROUP(pj2, RSVD1, RSVD2, GMI, SOC, 0x31d8, N, N, N), - PINGROUP(pk3, SDMMC2, TRACE, GMI, CCLA, 0x31dc, N, N, N), - PINGROUP(pk4, SDMMC2, RSVD2, GMI, GMI_ALT, 0x31e0, N, N, N), - PINGROUP(pk2, RSVD1, RSVD2, GMI, RSVD4, 0x31e4, N, N, N), - PINGROUP(pi3, RSVD1, RSVD2, GMI, SPI4, 0x31e8, N, N, N), - PINGROUP(pi6, RSVD1, RSVD2, GMI, SDMMC2, 0x31ec, N, N, N), - PINGROUP(pg0, RSVD1, RSVD2, GMI, RSVD4, 0x31f0, N, N, N), - PINGROUP(pg1, RSVD1, RSVD2, GMI, RSVD4, 0x31f4, N, N, N), - PINGROUP(pg2, RSVD1, TRACE, GMI, RSVD4, 0x31f8, N, N, N), - PINGROUP(pg3, RSVD1, TRACE, GMI, RSVD4, 0x31fc, N, N, N), - PINGROUP(pg4, RSVD1, TMDS, GMI, SPI4, 0x3200, N, N, N), - PINGROUP(pg5, RSVD1, RSVD2, GMI, SPI4, 0x3204, N, N, N), - PINGROUP(pg6, RSVD1, RSVD2, GMI, SPI4, 0x3208, N, N, N), - PINGROUP(pg7, RSVD1, RSVD2, GMI, SPI4, 0x320c, N, N, N), - PINGROUP(ph0, PWM0, TRACE, GMI, DTV, 0x3210, N, N, N), - PINGROUP(ph1, PWM1, TMDS, GMI, DISPLAYA, 0x3214, N, N, N), - PINGROUP(ph2, PWM2, TMDS, GMI, CLDVFS, 0x3218, N, N, N), - PINGROUP(ph3, PWM3, SPI4, GMI, CLDVFS, 0x321c, N, N, N), - PINGROUP(ph4, SDMMC2, RSVD2, GMI, RSVD4, 0x3220, N, N, N), - PINGROUP(ph5, SDMMC2, RSVD2, GMI, RSVD4, 0x3224, N, N, N), - PINGROUP(ph6, SDMMC2, TRACE, GMI, DTV, 0x3228, N, N, N), - PINGROUP(ph7, SDMMC2, TRACE, GMI, DTV, 0x322c, N, N, N), - PINGROUP(pj7, UARTD, RSVD2, GMI, GMI_ALT, 0x3230, N, N, N), - PINGROUP(pb0, UARTD, RSVD2, GMI, RSVD4, 0x3234, N, N, N), - PINGROUP(pb1, UARTD, RSVD2, GMI, RSVD4, 0x3238, N, N, N), - PINGROUP(pk7, UARTD, RSVD2, GMI, RSVD4, 0x323c, N, N, N), - PINGROUP(pi0, RSVD1, RSVD2, GMI, RSVD4, 0x3240, N, N, N), - PINGROUP(pi1, RSVD1, RSVD2, GMI, RSVD4, 0x3244, N, N, N), - PINGROUP(pi2, SDMMC2, TRACE, GMI, RSVD4, 0x3248, N, N, N), - PINGROUP(pi4, SPI4, TRACE, GMI, DISPLAYA, 0x324c, N, N, N), - PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), - PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), - PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), - PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), - PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), - PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), - PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), - PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), - PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), - PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, RSVD3, RSVD4, 0x3274, N, Y, N), - PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), - PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), - PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC2, 0x3284, N, N, N), - PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC2, 0x3288, N, N, N), - PINGROUP(pbb0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT, 0x328c, N, N, N), - PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC2, 0x3290, Y, N, N), - PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC2, 0x3294, Y, N, N), - PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC2, 0x3298, N, N, N), - PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC2, 0x329c, N, N, N), - PINGROUP(pbb5, VGP5, DISPLAYA, RSVD3, SDMMC2, 0x32a0, N, N, N), - PINGROUP(pbb6, I2S4, RSVD2, DISPLAYB, SDMMC2, 0x32a4, N, N, N), - PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC2, 0x32a8, N, N, N), - PINGROUP(pcc2, I2S4, RSVD2, SDMMC3, SDMMC2, 0x32ac, N, N, N), - PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), - PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), - PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), - PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), - PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), - PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), - PINGROUP(kb_row3_pr3, KBC, DISPLAYA, SYS, DISPLAYB, 0x32c8, N, N, N), - PINGROUP(kb_row4_pr4, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32cc, N, N, N), - PINGROUP(kb_row5_pr5, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32d0, N, N, N), - PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), - PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), - PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), - PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), - PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), - PINGROUP(kb_row11_ps3, KBC, RSVD2, RSVD3, IRDA, 0x32e8, N, N, N), - PINGROUP(kb_row12_ps4, KBC, RSVD2, RSVD3, IRDA, 0x32ec, N, N, N), - PINGROUP(kb_row13_ps5, KBC, RSVD2, SPI2, RSVD4, 0x32f0, N, N, N), - PINGROUP(kb_row14_ps6, KBC, RSVD2, SPI2, RSVD4, 0x32f4, N, N, N), - PINGROUP(kb_row15_ps7, KBC, SOC, RSVD3, RSVD4, 0x32f8, N, N, N), - PINGROUP(kb_col0_pq0, KBC, RSVD2, SPI2, RSVD4, 0x32fc, N, N, N), - PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, RSVD4, 0x3300, N, N, N), - PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), - PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), - PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), - PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC3, RSVD4, 0x3310, N, N, N), - PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, UARTD, 0x3314, N, N, N), - PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, UARTD, 0x3318, N, N, N), - PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), - PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), - PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), - PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), - PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), - PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), - PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), - PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), - PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SATA, 0x3340, N, N, N), - PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), - PINGROUP(dap_mclk1_req_pee2, DAP, DAP1, SATA, RSVD4, 0x3348, N, N, N), - PINGROUP(dap_mclk1_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), - PINGROUP(spdif_in_pk6, SPDIF, RSVD2, RSVD3, I2C3, 0x3350, N, N, N), - PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, I2C3, 0x3354, N, N, N), - PINGROUP(dap2_fs_pa2, I2S1, HDA, GMI, RSVD4, 0x3358, N, N, N), - PINGROUP(dap2_din_pa4, I2S1, HDA, GMI, RSVD4, 0x335c, N, N, N), - PINGROUP(dap2_dout_pa5, I2S1, HDA, GMI, RSVD4, 0x3360, N, N, N), - PINGROUP(dap2_sclk_pa3, I2S1, HDA, GMI, RSVD4, 0x3364, N, N, N), - PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, GMI, RSVD4, 0x3368, N, N, N), - PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, GMI, RSVD4, 0x336c, N, N, N), - PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, GMI, RSVD4, 0x3370, N, N, N), - PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, GMI, RSVD4, 0x3374, N, N, N), - PINGROUP(gpio_x4_aud_px4, GMI, SPI1, SPI2, DAP2, 0x3378, N, N, N), - PINGROUP(gpio_x5_aud_px5, GMI, SPI1, SPI2, RSVD4, 0x337c, N, N, N), - PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, GMI, 0x3380, N, N, N), - PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), - PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), - PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), - PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), - PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), - PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), - PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), - PINGROUP(pex_l0_rst_n_pdd1, PE0, RSVD2, RSVD3, RSVD4, 0x33bc, N, N, N), - PINGROUP(pex_l0_clkreq_n_pdd2, PE0, RSVD2, RSVD3, RSVD4, 0x33c0, N, N, N), - PINGROUP(pex_wake_n_pdd3, PE, RSVD2, RSVD3, RSVD4, 0x33c4, N, N, N), - PINGROUP(pex_l1_rst_n_pdd5, PE1, RSVD2, RSVD3, RSVD4, 0x33cc, N, N, N), - PINGROUP(pex_l1_clkreq_n_pdd6, PE1, RSVD2, RSVD3, RSVD4, 0x33d0, N, N, N), - PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N, N), - PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), - PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), - PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), - PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), - PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), - PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), - PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), - PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), - PINGROUP(gmi_clk_lb, SDMMC2, RSVD2, GMI, RSVD4, 0x3404, N, N, N), - PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), - PINGROUP(kb_row16_pt0, KBC, RSVD2, RSVD3, UARTC, 0x340c, N, N, N), - PINGROUP(kb_row17_pt1, KBC, RSVD2, RSVD3, UARTC, 0x3410, N, N, N), - PINGROUP(usb_vbus_en2_pff1, USB, RSVD2, RSVD3, RSVD4, 0x3414, Y, N, N), - PINGROUP(pff2, SATA, RSVD2, RSVD3, RSVD4, 0x3418, Y, N, N), - PINGROUP(dp_hpd_pff0, DP, RSVD2, RSVD3, RSVD4, 0x3430, N, N, N), - - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ - DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at1, 0x870, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at2, 0x874, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at3, 0x878, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), - DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gma, 0x900, 2, 3, 4, 14, 5, 20, 5, 28, 2, 30, 2, Y), - DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao3, 0x9a8, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(ao0, 0x9b0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(hv0, 0x9b4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), - DRV_PINGROUP(sdio4, 0x9c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), - DRV_PINGROUP(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), - - /* pg_name, r, b, f0, f1 */ - MIPI_PAD_CTRL_PINGROUP(dsi_b, 0x820, 1, CSI, DSI_B), -}; - -static const struct tegra_pinctrl_soc_data tegra124_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra124_pins, - .npins = ARRAY_SIZE(tegra124_pins), - .functions = tegra124_functions, - .nfunctions = ARRAY_SIZE(tegra124_functions), - .groups = tegra124_groups, - .ngroups = ARRAY_SIZE(tegra124_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra124_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra124_pinctrl); -} - -static const struct of_device_id tegra124_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra124-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match); - -static struct platform_driver tegra124_pinctrl_driver = { - .driver = { - .name = "tegra124-pinctrl", - .of_match_table = tegra124_pinctrl_of_match, - }, - .probe = tegra124_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra124_pinctrl_driver); - -MODULE_AUTHOR("Ashwini Ghuge "); -MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c deleted file mode 100644 index 4833db4433d9..000000000000 --- a/drivers/pinctrl/pinctrl-tegra20.c +++ /dev/null @@ -1,2252 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra20 pinmux - * - * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. - * - * Derived from code: - * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2010 NVIDIA 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 "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_VI_GP6_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDIO3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDIO3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_GMI_AD17_PB0 _GPIO(8) -#define TEGRA_PIN_GMI_AD18_PB1 _GPIO(9) -#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) -#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) -#define TEGRA_PIN_SDIO3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDIO3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDIO3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDIO3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) -#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) -#define TEGRA_PIN_SDIO3_DAT5_PD0 _GPIO(24) -#define TEGRA_PIN_SDIO3_DAT4_PD1 _GPIO(25) -#define TEGRA_PIN_VI_GP5_PD2 _GPIO(26) -#define TEGRA_PIN_SDIO3_DAT6_PD3 _GPIO(27) -#define TEGRA_PIN_SDIO3_DAT7_PD4 _GPIO(28) -#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) -#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) -#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) -#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) -#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) -#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) -#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) -#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) -#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) -#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) -#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) -#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) -#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) -#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) -#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) -#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) -#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) -#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) -#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) -#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) -#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) -#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) -#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) -#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) -#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) -#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) -#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) -#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) -#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) -#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) -#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) -#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) -#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) -#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) -#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) -#define TEGRA_PIN_GMI_HIOW_N_PI0 _GPIO(64) -#define TEGRA_PIN_GMI_HIOR_N_PI1 _GPIO(65) -#define TEGRA_PIN_GMI_CS5_N_PI2 _GPIO(66) -#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) -#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) -#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) -#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) -#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) -#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) -#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) -#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) -#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) -#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_GMI_AD16_PJ7 _GPIO(79) -#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) -#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) -#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) -#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) -#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_GMI_AD19_PK7 _GPIO(87) -#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) -#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) -#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) -#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) -#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) -#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) -#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) -#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) -#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) -#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) -#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) -#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) -#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) -#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) -#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) -#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) -#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) -#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) -#define TEGRA_PIN_HDMI_INT_N_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) -#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) -#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) -#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) -#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) -#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) -#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) -#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) -#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) -#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_GMI_DPD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_PV2 _GPIO(170) -#define TEGRA_PIN_PV3 _GPIO(171) -#define TEGRA_PIN_PV4 _GPIO(172) -#define TEGRA_PIN_PV5 _GPIO(173) -#define TEGRA_PIN_PV6 _GPIO(174) -#define TEGRA_PIN_LCD_DC1_PV7 _GPIO(175) -#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) -#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) -#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) -#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) -#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) -#define TEGRA_PIN_DAP_MCLK2_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) -#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) -#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) -#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) -#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) -#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) -#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) -#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDIO1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDIO1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDIO1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDIO1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDIO1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDIO1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) -#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) -#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) -#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_GMI_AD20_PAA0 _GPIO(208) -#define TEGRA_PIN_GMI_AD21_PAA1 _GPIO(209) -#define TEGRA_PIN_GMI_AD22_PAA2 _GPIO(210) -#define TEGRA_PIN_GMI_AD23_PAA3 _GPIO(211) -#define TEGRA_PIN_GMI_AD24_PAA4 _GPIO(212) -#define TEGRA_PIN_GMI_AD25_PAA5 _GPIO(213) -#define TEGRA_PIN_GMI_AD26_PAA6 _GPIO(214) -#define TEGRA_PIN_GMI_AD27_PAA7 _GPIO(215) -#define TEGRA_PIN_LED_BLINK_PBB0 _GPIO(216) -#define TEGRA_PIN_VI_GP0_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SCL_PBB2 _GPIO(218) -#define TEGRA_PIN_CAM_I2C_SDA_PBB3 _GPIO(219) -#define TEGRA_PIN_VI_GP3_PBB4 _GPIO(220) -#define TEGRA_PIN_VI_GP4_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_PBB7 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -#define TEGRA_PIN_CRT_HSYNC _PIN(30) -#define TEGRA_PIN_CRT_VSYNC _PIN(31) -#define TEGRA_PIN_DDC_SCL _PIN(32) -#define TEGRA_PIN_DDC_SDA _PIN(33) -#define TEGRA_PIN_OWC _PIN(34) -#define TEGRA_PIN_CORE_PWR_REQ _PIN(35) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(36) -#define TEGRA_PIN_PWR_INT_N _PIN(37) -#define TEGRA_PIN_CLK_32_K_IN _PIN(38) -#define TEGRA_PIN_DDR_COMP_PD _PIN(39) -#define TEGRA_PIN_DDR_COMP_PU _PIN(40) -#define TEGRA_PIN_DDR_A0 _PIN(41) -#define TEGRA_PIN_DDR_A1 _PIN(42) -#define TEGRA_PIN_DDR_A2 _PIN(43) -#define TEGRA_PIN_DDR_A3 _PIN(44) -#define TEGRA_PIN_DDR_A4 _PIN(45) -#define TEGRA_PIN_DDR_A5 _PIN(46) -#define TEGRA_PIN_DDR_A6 _PIN(47) -#define TEGRA_PIN_DDR_A7 _PIN(48) -#define TEGRA_PIN_DDR_A8 _PIN(49) -#define TEGRA_PIN_DDR_A9 _PIN(50) -#define TEGRA_PIN_DDR_A10 _PIN(51) -#define TEGRA_PIN_DDR_A11 _PIN(52) -#define TEGRA_PIN_DDR_A12 _PIN(53) -#define TEGRA_PIN_DDR_A13 _PIN(54) -#define TEGRA_PIN_DDR_A14 _PIN(55) -#define TEGRA_PIN_DDR_CAS_N _PIN(56) -#define TEGRA_PIN_DDR_BA0 _PIN(57) -#define TEGRA_PIN_DDR_BA1 _PIN(58) -#define TEGRA_PIN_DDR_BA2 _PIN(59) -#define TEGRA_PIN_DDR_DQS0P _PIN(60) -#define TEGRA_PIN_DDR_DQS0N _PIN(61) -#define TEGRA_PIN_DDR_DQS1P _PIN(62) -#define TEGRA_PIN_DDR_DQS1N _PIN(63) -#define TEGRA_PIN_DDR_DQS2P _PIN(64) -#define TEGRA_PIN_DDR_DQS2N _PIN(65) -#define TEGRA_PIN_DDR_DQS3P _PIN(66) -#define TEGRA_PIN_DDR_DQS3N _PIN(67) -#define TEGRA_PIN_DDR_CKE0 _PIN(68) -#define TEGRA_PIN_DDR_CKE1 _PIN(69) -#define TEGRA_PIN_DDR_CLK _PIN(70) -#define TEGRA_PIN_DDR_CLK_N _PIN(71) -#define TEGRA_PIN_DDR_DM0 _PIN(72) -#define TEGRA_PIN_DDR_DM1 _PIN(73) -#define TEGRA_PIN_DDR_DM2 _PIN(74) -#define TEGRA_PIN_DDR_DM3 _PIN(75) -#define TEGRA_PIN_DDR_ODT _PIN(76) -#define TEGRA_PIN_DDR_QUSE0 _PIN(77) -#define TEGRA_PIN_DDR_QUSE1 _PIN(78) -#define TEGRA_PIN_DDR_QUSE2 _PIN(79) -#define TEGRA_PIN_DDR_QUSE3 _PIN(80) -#define TEGRA_PIN_DDR_RAS_N _PIN(81) -#define TEGRA_PIN_DDR_WE_N _PIN(82) -#define TEGRA_PIN_DDR_DQ0 _PIN(83) -#define TEGRA_PIN_DDR_DQ1 _PIN(84) -#define TEGRA_PIN_DDR_DQ2 _PIN(85) -#define TEGRA_PIN_DDR_DQ3 _PIN(86) -#define TEGRA_PIN_DDR_DQ4 _PIN(87) -#define TEGRA_PIN_DDR_DQ5 _PIN(88) -#define TEGRA_PIN_DDR_DQ6 _PIN(89) -#define TEGRA_PIN_DDR_DQ7 _PIN(90) -#define TEGRA_PIN_DDR_DQ8 _PIN(91) -#define TEGRA_PIN_DDR_DQ9 _PIN(92) -#define TEGRA_PIN_DDR_DQ10 _PIN(93) -#define TEGRA_PIN_DDR_DQ11 _PIN(94) -#define TEGRA_PIN_DDR_DQ12 _PIN(95) -#define TEGRA_PIN_DDR_DQ13 _PIN(96) -#define TEGRA_PIN_DDR_DQ14 _PIN(97) -#define TEGRA_PIN_DDR_DQ15 _PIN(98) -#define TEGRA_PIN_DDR_DQ16 _PIN(99) -#define TEGRA_PIN_DDR_DQ17 _PIN(100) -#define TEGRA_PIN_DDR_DQ18 _PIN(101) -#define TEGRA_PIN_DDR_DQ19 _PIN(102) -#define TEGRA_PIN_DDR_DQ20 _PIN(103) -#define TEGRA_PIN_DDR_DQ21 _PIN(104) -#define TEGRA_PIN_DDR_DQ22 _PIN(105) -#define TEGRA_PIN_DDR_DQ23 _PIN(106) -#define TEGRA_PIN_DDR_DQ24 _PIN(107) -#define TEGRA_PIN_DDR_DQ25 _PIN(108) -#define TEGRA_PIN_DDR_DQ26 _PIN(109) -#define TEGRA_PIN_DDR_DQ27 _PIN(110) -#define TEGRA_PIN_DDR_DQ28 _PIN(111) -#define TEGRA_PIN_DDR_DQ29 _PIN(112) -#define TEGRA_PIN_DDR_DQ30 _PIN(113) -#define TEGRA_PIN_DDR_DQ31 _PIN(114) -#define TEGRA_PIN_DDR_CS0_N _PIN(115) -#define TEGRA_PIN_DDR_CS1_N _PIN(116) -#define TEGRA_PIN_SYS_RESET _PIN(117) -#define TEGRA_PIN_JTAG_TRST_N _PIN(118) -#define TEGRA_PIN_JTAG_TDO _PIN(119) -#define TEGRA_PIN_JTAG_TMS _PIN(120) -#define TEGRA_PIN_JTAG_TCK _PIN(121) -#define TEGRA_PIN_JTAG_TDI _PIN(122) -#define TEGRA_PIN_TEST_MODE_EN _PIN(123) - -static const struct pinctrl_pin_desc tegra20_pins[] = { - PINCTRL_PIN(TEGRA_PIN_VI_GP6_PA0, "VI_GP6 PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_CLK_PA6, "SDIO3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_CMD_PA7, "SDIO3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD17_PB0, "GMI_AD17 PB0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD18_PB1, "GMI_AD18 PB1"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), - PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT3_PB4, "SDIO3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT2_PB5, "SDIO3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT1_PB6, "SDIO3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT0_PB7, "SDIO3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT5_PD0, "SDIO3_DAT5 PD0"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT4_PD1, "SDIO3_DAT4 PD1"), - PINCTRL_PIN(TEGRA_PIN_VI_GP5_PD2, "VI_GP5 PD2"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT6_PD3, "SDIO3_DAT6 PD3"), - PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT7_PD4, "SDIO3_DAT7 PD4"), - PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), - PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), - PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), - PINCTRL_PIN(TEGRA_PIN_GMI_HIOW_N_PI0, "GMI_HIOW_N PI0"), - PINCTRL_PIN(TEGRA_PIN_GMI_HIOR_N_PI1, "GMI_HIOR_N PI1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS5_N_PI2, "GMI_CS5_N PI2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), - PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), - PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), - PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD16_PJ7, "GMI_AD16 PJ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD19_PK7, "GMI_AD19 PK7"), - PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), - PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), - PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), - PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), - PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), - PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), - PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), - PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_N_PN7, "HDMI_INT_N PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), - PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), - PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), - PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VD_D10 PT2"), - PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), - PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_GMI_DPD_PT7, "GMI_DPD PT7"), - /* PU0..6: GPIO only */ - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), - /* PV0..1: GPIO only */ - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - /* PV2..3: Balls are named after GPIO not function */ - PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), - PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), - /* PV4..6: GPIO only */ - PINCTRL_PIN(TEGRA_PIN_PV4, "PV4"), - PINCTRL_PIN(TEGRA_PIN_PV5, "PV5"), - PINCTRL_PIN(TEGRA_PIN_PV6, "PV6"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PV7, "LCD_DC1 PV7"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), - PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), - PINCTRL_PIN(TEGRA_PIN_DAP_MCLK2_PW5, "DAP_MCLK2 PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), - PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT3_PY4, "SDIO1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT2_PY5, "SDIO1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT1_PY6, "SDIO1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT0_PY7, "SDIO1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_CLK_PZ0, "SDIO1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDIO1_CMD_PZ1, "SDIO1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), - PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD20_PAA0, "GMI_AD20 PAA0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD21_PAA1, "GMI_AD21 PAA1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD22_PAA2, "GMI_AD22 PAA2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD23_PAA3, "GMI_AD23 PAA3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD24_PAA4, "GMI_AD24 PAA4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD25_PAA5, "GMI_AD25 PAA5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD26_PAA6, "GMI_AD26 PAA6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD27_PAA7, "GMI_AD27 PAA7"), - PINCTRL_PIN(TEGRA_PIN_LED_BLINK_PBB0, "LED_BLINK PBB0"), - PINCTRL_PIN(TEGRA_PIN_VI_GP0_PBB1, "VI_GP0 PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB2, "CAM_I2C_SCL PBB2"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB3, "CAM_I2C_SDA PBB3"), - PINCTRL_PIN(TEGRA_PIN_VI_GP3_PBB4, "VI_GP3 PBB4"), - PINCTRL_PIN(TEGRA_PIN_VI_GP4_PBB5, "VI_GP4 PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC, "CRT_HSYNC"), - PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC, "CRT_VSYNC"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL, "DDC_SCL"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA, "DDC_SDA"), - PINCTRL_PIN(TEGRA_PIN_OWC, "OWC"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_CLK_32_K_IN, "CLK_32_K_IN"), - PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PD, "DDR_COMP_PD"), - PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PU, "DDR_COMP_PU"), - PINCTRL_PIN(TEGRA_PIN_DDR_A0, "DDR_A0"), - PINCTRL_PIN(TEGRA_PIN_DDR_A1, "DDR_A1"), - PINCTRL_PIN(TEGRA_PIN_DDR_A2, "DDR_A2"), - PINCTRL_PIN(TEGRA_PIN_DDR_A3, "DDR_A3"), - PINCTRL_PIN(TEGRA_PIN_DDR_A4, "DDR_A4"), - PINCTRL_PIN(TEGRA_PIN_DDR_A5, "DDR_A5"), - PINCTRL_PIN(TEGRA_PIN_DDR_A6, "DDR_A6"), - PINCTRL_PIN(TEGRA_PIN_DDR_A7, "DDR_A7"), - PINCTRL_PIN(TEGRA_PIN_DDR_A8, "DDR_A8"), - PINCTRL_PIN(TEGRA_PIN_DDR_A9, "DDR_A9"), - PINCTRL_PIN(TEGRA_PIN_DDR_A10, "DDR_A10"), - PINCTRL_PIN(TEGRA_PIN_DDR_A11, "DDR_A11"), - PINCTRL_PIN(TEGRA_PIN_DDR_A12, "DDR_A12"), - PINCTRL_PIN(TEGRA_PIN_DDR_A13, "DDR_A13"), - PINCTRL_PIN(TEGRA_PIN_DDR_A14, "DDR_A14"), - PINCTRL_PIN(TEGRA_PIN_DDR_CAS_N, "DDR_CAS_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_BA0, "DDR_BA0"), - PINCTRL_PIN(TEGRA_PIN_DDR_BA1, "DDR_BA1"), - PINCTRL_PIN(TEGRA_PIN_DDR_BA2, "DDR_BA2"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS0P, "DDR_DQS0P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS0N, "DDR_DQS0N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS1P, "DDR_DQS1P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS1N, "DDR_DQS1N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS2P, "DDR_DQS2P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS2N, "DDR_DQS2N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS3P, "DDR_DQS3P"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQS3N, "DDR_DQS3N"), - PINCTRL_PIN(TEGRA_PIN_DDR_CKE0, "DDR_CKE0"), - PINCTRL_PIN(TEGRA_PIN_DDR_CKE1, "DDR_CKE1"), - PINCTRL_PIN(TEGRA_PIN_DDR_CLK, "DDR_CLK"), - PINCTRL_PIN(TEGRA_PIN_DDR_CLK_N, "DDR_CLK_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM0, "DDR_DM0"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM1, "DDR_DM1"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM2, "DDR_DM2"), - PINCTRL_PIN(TEGRA_PIN_DDR_DM3, "DDR_DM3"), - PINCTRL_PIN(TEGRA_PIN_DDR_ODT, "DDR_ODT"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE0, "DDR_QUSE0"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE1, "DDR_QUSE1"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE2, "DDR_QUSE2"), - PINCTRL_PIN(TEGRA_PIN_DDR_QUSE3, "DDR_QUSE3"), - PINCTRL_PIN(TEGRA_PIN_DDR_RAS_N, "DDR_RAS_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_WE_N, "DDR_WE_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ0, "DDR_DQ0"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ1, "DDR_DQ1"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ2, "DDR_DQ2"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ3, "DDR_DQ3"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ4, "DDR_DQ4"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ5, "DDR_DQ5"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ6, "DDR_DQ6"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ7, "DDR_DQ7"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ8, "DDR_DQ8"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ9, "DDR_DQ9"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ10, "DDR_DQ10"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ11, "DDR_DQ11"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ12, "DDR_DQ12"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ13, "DDR_DQ13"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ14, "DDR_DQ14"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ15, "DDR_DQ15"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ16, "DDR_DQ16"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ17, "DDR_DQ17"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ18, "DDR_DQ18"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ19, "DDR_DQ19"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ20, "DDR_DQ20"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ21, "DDR_DQ21"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ22, "DDR_DQ22"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ23, "DDR_DQ23"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ24, "DDR_DQ24"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ25, "DDR_DQ25"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ26, "DDR_DQ26"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ27, "DDR_DQ27"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ28, "DDR_DQ28"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ29, "DDR_DQ29"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ30, "DDR_DQ30"), - PINCTRL_PIN(TEGRA_PIN_DDR_DQ31, "DDR_DQ31"), - PINCTRL_PIN(TEGRA_PIN_DDR_CS0_N, "DDR_CS0_N"), - PINCTRL_PIN(TEGRA_PIN_DDR_CS1_N, "DDR_CS1_N"), - PINCTRL_PIN(TEGRA_PIN_SYS_RESET, "SYS_RESET"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), - PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), -}; - -static const unsigned ata_pins[] = { - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_CS7_N_PI6, - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned atb_pins[] = { - TEGRA_PIN_GMI_CS5_N_PI2, - TEGRA_PIN_GMI_DPD_PT7, -}; - -static const unsigned atc_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_CS3_N_PK4, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_HIOW_N_PI0, - TEGRA_PIN_GMI_HIOR_N_PI1, -}; - -static const unsigned atd_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, -}; - -static const unsigned ate_pins[] = { - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, -}; - -static const unsigned cdev1_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, -}; - -static const unsigned cdev2_pins[] = { - TEGRA_PIN_DAP_MCLK2_PW5, -}; - -static const unsigned crtp_pins[] = { - TEGRA_PIN_CRT_HSYNC, - TEGRA_PIN_CRT_VSYNC, -}; - -static const unsigned csus_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned ddc_pins[] = { - TEGRA_PIN_DDC_SCL, - TEGRA_PIN_DDC_SDA, -}; - -static const unsigned dta_pins[] = { - TEGRA_PIN_VI_D0_PT4, - TEGRA_PIN_VI_D1_PD5, -}; - -static const unsigned dtb_pins[] = { - TEGRA_PIN_VI_D10_PT2, - TEGRA_PIN_VI_D11_PT3, -}; - -static const unsigned dtc_pins[] = { - TEGRA_PIN_VI_HSYNC_PD7, - TEGRA_PIN_VI_VSYNC_PD6, -}; - -static const unsigned dtd_pins[] = { - TEGRA_PIN_VI_PCLK_PT0, - TEGRA_PIN_VI_D2_PL0, - TEGRA_PIN_VI_D3_PL1, - TEGRA_PIN_VI_D4_PL2, - TEGRA_PIN_VI_D5_PL3, - TEGRA_PIN_VI_D6_PL4, - TEGRA_PIN_VI_D7_PL5, - TEGRA_PIN_VI_D8_PL6, - TEGRA_PIN_VI_D9_PL7, -}; - -static const unsigned dte_pins[] = { - TEGRA_PIN_VI_GP0_PBB1, - TEGRA_PIN_VI_GP3_PBB4, - TEGRA_PIN_VI_GP4_PBB5, - TEGRA_PIN_VI_GP5_PD2, - TEGRA_PIN_VI_GP6_PA0, -}; - -static const unsigned dtf_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB2, - TEGRA_PIN_CAM_I2C_SDA_PBB3, -}; - -static const unsigned gma_pins[] = { - TEGRA_PIN_GMI_AD20_PAA0, - TEGRA_PIN_GMI_AD21_PAA1, - TEGRA_PIN_GMI_AD22_PAA2, - TEGRA_PIN_GMI_AD23_PAA3, -}; - -static const unsigned gmb_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned gmc_pins[] = { - TEGRA_PIN_GMI_AD16_PJ7, - TEGRA_PIN_GMI_AD17_PB0, - TEGRA_PIN_GMI_AD18_PB1, - TEGRA_PIN_GMI_AD19_PK7, -}; - -static const unsigned gmd_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned gme_pins[] = { - TEGRA_PIN_GMI_AD24_PAA4, - TEGRA_PIN_GMI_AD25_PAA5, - TEGRA_PIN_GMI_AD26_PAA6, - TEGRA_PIN_GMI_AD27_PAA7, -}; - -static const unsigned gpu_pins[] = { - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, -}; - -static const unsigned gpu7_pins[] = { - TEGRA_PIN_JTAG_RTCK_PU7, -}; - -static const unsigned gpv_pins[] = { - TEGRA_PIN_PV4, - TEGRA_PIN_PV5, - TEGRA_PIN_PV6, -}; - -static const unsigned hdint_pins[] = { - TEGRA_PIN_HDMI_INT_N_PN7, -}; - -static const unsigned i2cp_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned irrx_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned irtx_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned kbca_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kbcb_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, -}; - -static const unsigned kbcc_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kbcd_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kbce_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kbcf_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned lcsn_pins[] = { - TEGRA_PIN_LCD_CS0_N_PN4, -}; - -static const unsigned ld0_pins[] = { - TEGRA_PIN_LCD_D0_PE0, -}; - -static const unsigned ld1_pins[] = { - TEGRA_PIN_LCD_D1_PE1, -}; - -static const unsigned ld2_pins[] = { - TEGRA_PIN_LCD_D2_PE2, -}; - -static const unsigned ld3_pins[] = { - TEGRA_PIN_LCD_D3_PE3, -}; - -static const unsigned ld4_pins[] = { - TEGRA_PIN_LCD_D4_PE4, -}; - -static const unsigned ld5_pins[] = { - TEGRA_PIN_LCD_D5_PE5, -}; - -static const unsigned ld6_pins[] = { - TEGRA_PIN_LCD_D6_PE6, -}; - -static const unsigned ld7_pins[] = { - TEGRA_PIN_LCD_D7_PE7, -}; - -static const unsigned ld8_pins[] = { - TEGRA_PIN_LCD_D8_PF0, -}; - -static const unsigned ld9_pins[] = { - TEGRA_PIN_LCD_D9_PF1, -}; - -static const unsigned ld10_pins[] = { - TEGRA_PIN_LCD_D10_PF2, -}; - -static const unsigned ld11_pins[] = { - TEGRA_PIN_LCD_D11_PF3, -}; - -static const unsigned ld12_pins[] = { - TEGRA_PIN_LCD_D12_PF4, -}; - -static const unsigned ld13_pins[] = { - TEGRA_PIN_LCD_D13_PF5, -}; - -static const unsigned ld14_pins[] = { - TEGRA_PIN_LCD_D14_PF6, -}; - -static const unsigned ld15_pins[] = { - TEGRA_PIN_LCD_D15_PF7, -}; - -static const unsigned ld16_pins[] = { - TEGRA_PIN_LCD_D16_PM0, -}; - -static const unsigned ld17_pins[] = { - TEGRA_PIN_LCD_D17_PM1, -}; - -static const unsigned ldc_pins[] = { - TEGRA_PIN_LCD_DC0_PN6, -}; - -static const unsigned ldi_pins[] = { - TEGRA_PIN_LCD_D22_PM6, -}; - -static const unsigned lhp0_pins[] = { - TEGRA_PIN_LCD_D21_PM5, -}; - -static const unsigned lhp1_pins[] = { - TEGRA_PIN_LCD_D18_PM2, -}; - -static const unsigned lhp2_pins[] = { - TEGRA_PIN_LCD_D19_PM3, -}; - -static const unsigned lhs_pins[] = { - TEGRA_PIN_LCD_HSYNC_PJ3, -}; - -static const unsigned lm0_pins[] = { - TEGRA_PIN_LCD_CS1_N_PW0, -}; - -static const unsigned lm1_pins[] = { - TEGRA_PIN_LCD_M1_PW1, -}; - -static const unsigned lpp_pins[] = { - TEGRA_PIN_LCD_D23_PM7, -}; - -static const unsigned lpw0_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, -}; - -static const unsigned lpw1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, -}; - -static const unsigned lpw2_pins[] = { - TEGRA_PIN_LCD_PWR2_PC6, -}; - -static const unsigned lsc0_pins[] = { - TEGRA_PIN_LCD_PCLK_PB3, -}; - -static const unsigned lsc1_pins[] = { - TEGRA_PIN_LCD_WR_N_PZ3, -}; - -static const unsigned lsck_pins[] = { - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned lsda_pins[] = { - TEGRA_PIN_LCD_SDOUT_PN5, -}; - -static const unsigned lsdi_pins[] = { - TEGRA_PIN_LCD_SDIN_PZ2, -}; - -static const unsigned lspi_pins[] = { - TEGRA_PIN_LCD_DE_PJ1, -}; - -static const unsigned lvp0_pins[] = { - TEGRA_PIN_LCD_DC1_PV7, -}; - -static const unsigned lvp1_pins[] = { - TEGRA_PIN_LCD_D20_PM4, -}; - -static const unsigned lvs_pins[] = { - TEGRA_PIN_LCD_VSYNC_PJ4, -}; - -static const unsigned ls_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, - TEGRA_PIN_LCD_PWR1_PC1, - TEGRA_PIN_LCD_PWR2_PC6, - TEGRA_PIN_LCD_SDIN_PZ2, - TEGRA_PIN_LCD_SDOUT_PN5, - TEGRA_PIN_LCD_WR_N_PZ3, - TEGRA_PIN_LCD_CS0_N_PN4, - TEGRA_PIN_LCD_DC0_PN6, - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned lc_pins[] = { - TEGRA_PIN_LCD_PCLK_PB3, - TEGRA_PIN_LCD_DE_PJ1, - TEGRA_PIN_LCD_HSYNC_PJ3, - TEGRA_PIN_LCD_VSYNC_PJ4, - TEGRA_PIN_LCD_CS1_N_PW0, - TEGRA_PIN_LCD_M1_PW1, - TEGRA_PIN_LCD_DC1_PV7, - TEGRA_PIN_HDMI_INT_N_PN7, -}; - -static const unsigned ld17_0_pins[] = { - TEGRA_PIN_LCD_D0_PE0, - TEGRA_PIN_LCD_D1_PE1, - TEGRA_PIN_LCD_D2_PE2, - TEGRA_PIN_LCD_D3_PE3, - TEGRA_PIN_LCD_D4_PE4, - TEGRA_PIN_LCD_D5_PE5, - TEGRA_PIN_LCD_D6_PE6, - TEGRA_PIN_LCD_D7_PE7, - TEGRA_PIN_LCD_D8_PF0, - TEGRA_PIN_LCD_D9_PF1, - TEGRA_PIN_LCD_D10_PF2, - TEGRA_PIN_LCD_D11_PF3, - TEGRA_PIN_LCD_D12_PF4, - TEGRA_PIN_LCD_D13_PF5, - TEGRA_PIN_LCD_D14_PF6, - TEGRA_PIN_LCD_D15_PF7, - TEGRA_PIN_LCD_D16_PM0, - TEGRA_PIN_LCD_D17_PM1, -}; - -static const unsigned ld19_18_pins[] = { - TEGRA_PIN_LCD_D18_PM2, - TEGRA_PIN_LCD_D19_PM3, -}; - -static const unsigned ld21_20_pins[] = { - TEGRA_PIN_LCD_D20_PM4, - TEGRA_PIN_LCD_D21_PM5, -}; - -static const unsigned ld23_22_pins[] = { - TEGRA_PIN_LCD_D22_PM6, - TEGRA_PIN_LCD_D23_PM7, -}; - -static const unsigned owc_pins[] = { - TEGRA_PIN_OWC, -}; - -static const unsigned pmc_pins[] = { - TEGRA_PIN_LED_BLINK_PBB0, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned pta_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned rm_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned sdb_pins[] = { - TEGRA_PIN_SDIO3_CMD_PA7, -}; - -static const unsigned sdc_pins[] = { - TEGRA_PIN_SDIO3_DAT0_PB7, - TEGRA_PIN_SDIO3_DAT1_PB6, - TEGRA_PIN_SDIO3_DAT2_PB5, - TEGRA_PIN_SDIO3_DAT3_PB4, -}; - -static const unsigned sdd_pins[] = { - TEGRA_PIN_SDIO3_CLK_PA6, -}; - -static const unsigned sdio1_pins[] = { - TEGRA_PIN_SDIO1_CLK_PZ0, - TEGRA_PIN_SDIO1_CMD_PZ1, - TEGRA_PIN_SDIO1_DAT0_PY7, - TEGRA_PIN_SDIO1_DAT1_PY6, - TEGRA_PIN_SDIO1_DAT2_PY5, - TEGRA_PIN_SDIO1_DAT3_PY4, -}; - -static const unsigned slxa_pins[] = { - TEGRA_PIN_SDIO3_DAT4_PD1, -}; - -static const unsigned slxc_pins[] = { - TEGRA_PIN_SDIO3_DAT6_PD3, -}; - -static const unsigned slxd_pins[] = { - TEGRA_PIN_SDIO3_DAT7_PD4, -}; - -static const unsigned slxk_pins[] = { - TEGRA_PIN_SDIO3_DAT5_PD0, -}; - -static const unsigned spdi_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned spdo_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spia_pins[] = { - TEGRA_PIN_SPI2_MOSI_PX0, -}; - -static const unsigned spib_pins[] = { - TEGRA_PIN_SPI2_MISO_PX1, -}; - -static const unsigned spic_pins[] = { - TEGRA_PIN_SPI2_CS0_N_PX3, - TEGRA_PIN_SPI2_SCK_PX2, -}; - -static const unsigned spid_pins[] = { - TEGRA_PIN_SPI1_MOSI_PX4, -}; - -static const unsigned spie_pins[] = { - TEGRA_PIN_SPI1_CS0_N_PX6, - TEGRA_PIN_SPI1_SCK_PX5, -}; - -static const unsigned spif_pins[] = { - TEGRA_PIN_SPI1_MISO_PX7, -}; - -static const unsigned spig_pins[] = { - TEGRA_PIN_SPI2_CS1_N_PW2, -}; - -static const unsigned spih_pins[] = { - TEGRA_PIN_SPI2_CS2_N_PW3, -}; - -static const unsigned uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned uab_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned uac_pins[] = { - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, - TEGRA_PIN_PV2, - TEGRA_PIN_PV3, -}; - -static const unsigned ck32_pins[] = { - TEGRA_PIN_CLK_32_K_IN, -}; - -static const unsigned uad_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uca_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned ucb_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned ddrc_pins[] = { - TEGRA_PIN_DDR_COMP_PD, - TEGRA_PIN_DDR_COMP_PU, -}; - -static const unsigned pmca_pins[] = { - TEGRA_PIN_LED_BLINK_PBB0, -}; - -static const unsigned pmcb_pins[] = { - TEGRA_PIN_SYS_CLK_REQ_PZ5, -}; - -static const unsigned pmcc_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned pmcd_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pmce_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned xm2c_pins[] = { - TEGRA_PIN_DDR_A0, - TEGRA_PIN_DDR_A1, - TEGRA_PIN_DDR_A2, - TEGRA_PIN_DDR_A3, - TEGRA_PIN_DDR_A4, - TEGRA_PIN_DDR_A5, - TEGRA_PIN_DDR_A6, - TEGRA_PIN_DDR_A7, - TEGRA_PIN_DDR_A8, - TEGRA_PIN_DDR_A9, - TEGRA_PIN_DDR_A10, - TEGRA_PIN_DDR_A11, - TEGRA_PIN_DDR_A12, - TEGRA_PIN_DDR_A13, - TEGRA_PIN_DDR_A14, - TEGRA_PIN_DDR_CAS_N, - TEGRA_PIN_DDR_BA0, - TEGRA_PIN_DDR_BA1, - TEGRA_PIN_DDR_BA2, - TEGRA_PIN_DDR_DQS0P, - TEGRA_PIN_DDR_DQS0N, - TEGRA_PIN_DDR_DQS1P, - TEGRA_PIN_DDR_DQS1N, - TEGRA_PIN_DDR_DQS2P, - TEGRA_PIN_DDR_DQS2N, - TEGRA_PIN_DDR_DQS3P, - TEGRA_PIN_DDR_DQS3N, - TEGRA_PIN_DDR_CS0_N, - TEGRA_PIN_DDR_CS1_N, - TEGRA_PIN_DDR_CKE0, - TEGRA_PIN_DDR_CKE1, - TEGRA_PIN_DDR_CLK, - TEGRA_PIN_DDR_CLK_N, - TEGRA_PIN_DDR_DM0, - TEGRA_PIN_DDR_DM1, - TEGRA_PIN_DDR_DM2, - TEGRA_PIN_DDR_DM3, - TEGRA_PIN_DDR_ODT, - TEGRA_PIN_DDR_RAS_N, - TEGRA_PIN_DDR_WE_N, - TEGRA_PIN_DDR_QUSE0, - TEGRA_PIN_DDR_QUSE1, - TEGRA_PIN_DDR_QUSE2, - TEGRA_PIN_DDR_QUSE3, -}; - -static const unsigned xm2d_pins[] = { - TEGRA_PIN_DDR_DQ0, - TEGRA_PIN_DDR_DQ1, - TEGRA_PIN_DDR_DQ2, - TEGRA_PIN_DDR_DQ3, - TEGRA_PIN_DDR_DQ4, - TEGRA_PIN_DDR_DQ5, - TEGRA_PIN_DDR_DQ6, - TEGRA_PIN_DDR_DQ7, - TEGRA_PIN_DDR_DQ8, - TEGRA_PIN_DDR_DQ9, - TEGRA_PIN_DDR_DQ10, - TEGRA_PIN_DDR_DQ11, - TEGRA_PIN_DDR_DQ12, - TEGRA_PIN_DDR_DQ13, - TEGRA_PIN_DDR_DQ14, - TEGRA_PIN_DDR_DQ15, - TEGRA_PIN_DDR_DQ16, - TEGRA_PIN_DDR_DQ17, - TEGRA_PIN_DDR_DQ18, - TEGRA_PIN_DDR_DQ19, - TEGRA_PIN_DDR_DQ20, - TEGRA_PIN_DDR_DQ21, - TEGRA_PIN_DDR_DQ22, - TEGRA_PIN_DDR_DQ23, - TEGRA_PIN_DDR_DQ24, - TEGRA_PIN_DDR_DQ25, - TEGRA_PIN_DDR_DQ26, - TEGRA_PIN_DDR_DQ27, - TEGRA_PIN_DDR_DQ28, - TEGRA_PIN_DDR_DQ29, - TEGRA_PIN_DDR_DQ30, - TEGRA_PIN_DDR_DQ31, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_SYS_RESET, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_LED_BLINK_PBB0, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, - TEGRA_PIN_CLK_32_K_IN, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, - TEGRA_PIN_GMI_CS7_N_PI6, - TEGRA_PIN_GMI_DPD_PT7, - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_CS5_N_PI2, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_CS3_N_PK4, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_HIOW_N_PI0, - TEGRA_PIN_GMI_HIOR_N_PI1, - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_DAP_MCLK1_PW4, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_DAP_MCLK2_PW5, -}; - -static const unsigned drive_csus_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, - TEGRA_PIN_SPDIF_OUT_PK5, - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, - TEGRA_PIN_JTAG_RTCK_PU7, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_JTAG_TRST_N, - TEGRA_PIN_JTAG_TDO, - TEGRA_PIN_JTAG_TMS, - TEGRA_PIN_JTAG_TCK, - TEGRA_PIN_JTAG_TDI, - TEGRA_PIN_TEST_MODE_EN, -}; - -static const unsigned drive_lcd1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, - TEGRA_PIN_LCD_PWR2_PC6, - TEGRA_PIN_LCD_SDIN_PZ2, - TEGRA_PIN_LCD_SDOUT_PN5, - TEGRA_PIN_LCD_WR_N_PZ3, - TEGRA_PIN_LCD_CS0_N_PN4, - TEGRA_PIN_LCD_DC0_PN6, - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned drive_lcd2_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, - TEGRA_PIN_LCD_PCLK_PB3, - TEGRA_PIN_LCD_DE_PJ1, - TEGRA_PIN_LCD_HSYNC_PJ3, - TEGRA_PIN_LCD_VSYNC_PJ4, - TEGRA_PIN_LCD_D0_PE0, - TEGRA_PIN_LCD_D1_PE1, - TEGRA_PIN_LCD_D2_PE2, - TEGRA_PIN_LCD_D3_PE3, - TEGRA_PIN_LCD_D4_PE4, - TEGRA_PIN_LCD_D5_PE5, - TEGRA_PIN_LCD_D6_PE6, - TEGRA_PIN_LCD_D7_PE7, - TEGRA_PIN_LCD_D8_PF0, - TEGRA_PIN_LCD_D9_PF1, - TEGRA_PIN_LCD_D10_PF2, - TEGRA_PIN_LCD_D11_PF3, - TEGRA_PIN_LCD_D12_PF4, - TEGRA_PIN_LCD_D13_PF5, - TEGRA_PIN_LCD_D14_PF6, - TEGRA_PIN_LCD_D15_PF7, - TEGRA_PIN_LCD_D16_PM0, - TEGRA_PIN_LCD_D17_PM1, - TEGRA_PIN_LCD_D18_PM2, - TEGRA_PIN_LCD_D19_PM3, - TEGRA_PIN_LCD_D20_PM4, - TEGRA_PIN_LCD_D21_PM5, - TEGRA_PIN_LCD_D22_PM6, - TEGRA_PIN_LCD_D23_PM7, - TEGRA_PIN_LCD_CS1_N_PW0, - TEGRA_PIN_LCD_M1_PW1, - TEGRA_PIN_LCD_DC1_PV7, - TEGRA_PIN_HDMI_INT_N_PN7, -}; - -static const unsigned drive_sdmmc2_pins[] = { - TEGRA_PIN_SDIO3_DAT4_PD1, - TEGRA_PIN_SDIO3_DAT5_PD0, - TEGRA_PIN_SDIO3_DAT6_PD3, - TEGRA_PIN_SDIO3_DAT7_PD4, -}; - -static const unsigned drive_sdmmc3_pins[] = { - TEGRA_PIN_SDIO3_CLK_PA6, - TEGRA_PIN_SDIO3_CMD_PA7, - TEGRA_PIN_SDIO3_DAT0_PB7, - TEGRA_PIN_SDIO3_DAT1_PB6, - TEGRA_PIN_SDIO3_DAT2_PB5, - TEGRA_PIN_SDIO3_DAT3_PB4, - TEGRA_PIN_PV4, - TEGRA_PIN_PV5, - TEGRA_PIN_PV6, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_SPI2_MOSI_PX0, - TEGRA_PIN_SPI2_MISO_PX1, - TEGRA_PIN_SPI2_SCK_PX2, - TEGRA_PIN_SPI2_CS0_N_PX3, - TEGRA_PIN_SPI1_MOSI_PX4, - TEGRA_PIN_SPI1_SCK_PX5, - TEGRA_PIN_SPI1_CS0_N_PX6, - TEGRA_PIN_SPI1_MISO_PX7, - TEGRA_PIN_SPI2_CS1_N_PW2, - TEGRA_PIN_SPI2_CS2_N_PW3, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, - TEGRA_PIN_PV2, - TEGRA_PIN_PV3, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_RTS_N_PJ6, - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned drive_vi1_pins[] = { - TEGRA_PIN_VI_D0_PT4, - TEGRA_PIN_VI_D1_PD5, - TEGRA_PIN_VI_D2_PL0, - TEGRA_PIN_VI_D3_PL1, - TEGRA_PIN_VI_D4_PL2, - TEGRA_PIN_VI_D5_PL3, - TEGRA_PIN_VI_D6_PL4, - TEGRA_PIN_VI_D7_PL5, - TEGRA_PIN_VI_D8_PL6, - TEGRA_PIN_VI_D9_PL7, - TEGRA_PIN_VI_D10_PT2, - TEGRA_PIN_VI_D11_PT3, - TEGRA_PIN_VI_PCLK_PT0, - TEGRA_PIN_VI_VSYNC_PD6, - TEGRA_PIN_VI_HSYNC_PD7, -}; - -static const unsigned drive_vi2_pins[] = { - TEGRA_PIN_VI_GP0_PBB1, - TEGRA_PIN_CAM_I2C_SCL_PBB2, - TEGRA_PIN_CAM_I2C_SDA_PBB3, - TEGRA_PIN_VI_GP3_PBB4, - TEGRA_PIN_VI_GP4_PBB5, - TEGRA_PIN_VI_GP5_PD2, - TEGRA_PIN_VI_GP6_PA0, -}; - -static const unsigned drive_xm2a_pins[] = { - TEGRA_PIN_DDR_A0, - TEGRA_PIN_DDR_A1, - TEGRA_PIN_DDR_A2, - TEGRA_PIN_DDR_A3, - TEGRA_PIN_DDR_A4, - TEGRA_PIN_DDR_A5, - TEGRA_PIN_DDR_A6, - TEGRA_PIN_DDR_A7, - TEGRA_PIN_DDR_A8, - TEGRA_PIN_DDR_A9, - TEGRA_PIN_DDR_A10, - TEGRA_PIN_DDR_A11, - TEGRA_PIN_DDR_A12, - TEGRA_PIN_DDR_A13, - TEGRA_PIN_DDR_A14, - TEGRA_PIN_DDR_BA0, - TEGRA_PIN_DDR_BA1, - TEGRA_PIN_DDR_BA2, - TEGRA_PIN_DDR_CS0_N, - TEGRA_PIN_DDR_CS1_N, - TEGRA_PIN_DDR_ODT, - TEGRA_PIN_DDR_RAS_N, - TEGRA_PIN_DDR_CAS_N, - TEGRA_PIN_DDR_WE_N, - TEGRA_PIN_DDR_CKE0, - TEGRA_PIN_DDR_CKE1, -}; - -static const unsigned drive_xm2c_pins[] = { - TEGRA_PIN_DDR_DQS0P, - TEGRA_PIN_DDR_DQS0N, - TEGRA_PIN_DDR_DQS1P, - TEGRA_PIN_DDR_DQS1N, - TEGRA_PIN_DDR_DQS2P, - TEGRA_PIN_DDR_DQS2N, - TEGRA_PIN_DDR_DQS3P, - TEGRA_PIN_DDR_DQS3N, - TEGRA_PIN_DDR_QUSE0, - TEGRA_PIN_DDR_QUSE1, - TEGRA_PIN_DDR_QUSE2, - TEGRA_PIN_DDR_QUSE3, -}; - -static const unsigned drive_xm2d_pins[] = { - TEGRA_PIN_DDR_DQ0, - TEGRA_PIN_DDR_DQ1, - TEGRA_PIN_DDR_DQ2, - TEGRA_PIN_DDR_DQ3, - TEGRA_PIN_DDR_DQ4, - TEGRA_PIN_DDR_DQ5, - TEGRA_PIN_DDR_DQ6, - TEGRA_PIN_DDR_DQ7, - TEGRA_PIN_DDR_DQ8, - TEGRA_PIN_DDR_DQ9, - TEGRA_PIN_DDR_DQ10, - TEGRA_PIN_DDR_DQ11, - TEGRA_PIN_DDR_DQ12, - TEGRA_PIN_DDR_DQ13, - TEGRA_PIN_DDR_DQ14, - TEGRA_PIN_DDR_DQ15, - TEGRA_PIN_DDR_DQ16, - TEGRA_PIN_DDR_DQ17, - TEGRA_PIN_DDR_DQ18, - TEGRA_PIN_DDR_DQ19, - TEGRA_PIN_DDR_DQ20, - TEGRA_PIN_DDR_DQ21, - TEGRA_PIN_DDR_DQ22, - TEGRA_PIN_DDR_DQ23, - TEGRA_PIN_DDR_DQ24, - TEGRA_PIN_DDR_DQ25, - TEGRA_PIN_DDR_DQ26, - TEGRA_PIN_DDR_DQ27, - TEGRA_PIN_DDR_DQ28, - TEGRA_PIN_DDR_DQ29, - TEGRA_PIN_DDR_DQ30, - TEGRA_PIN_DDR_DQ31, - TEGRA_PIN_DDR_DM0, - TEGRA_PIN_DDR_DM1, - TEGRA_PIN_DDR_DM2, - TEGRA_PIN_DDR_DM3, -}; - -static const unsigned drive_xm2clk_pins[] = { - TEGRA_PIN_DDR_CLK, - TEGRA_PIN_DDR_CLK_N, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDIO1_CLK_PZ0, - TEGRA_PIN_SDIO1_CMD_PZ1, - TEGRA_PIN_SDIO1_DAT0_PY7, - TEGRA_PIN_SDIO1_DAT1_PY6, - TEGRA_PIN_SDIO1_DAT2_PY5, - TEGRA_PIN_SDIO1_DAT3_PY4, -}; - -static const unsigned drive_crt_pins[] = { - TEGRA_PIN_CRT_HSYNC, - TEGRA_PIN_CRT_VSYNC, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL, - TEGRA_PIN_DDC_SDA, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_GMI_AD20_PAA0, - TEGRA_PIN_GMI_AD21_PAA1, - TEGRA_PIN_GMI_AD22_PAA2, - TEGRA_PIN_GMI_AD23_PAA3, -}; - -static const unsigned drive_gmb_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned drive_gmc_pins[] = { - TEGRA_PIN_GMI_AD16_PJ7, - TEGRA_PIN_GMI_AD17_PB0, - TEGRA_PIN_GMI_AD18_PB1, - TEGRA_PIN_GMI_AD19_PK7, -}; - -static const unsigned drive_gmd_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_GMI_AD24_PAA4, - TEGRA_PIN_GMI_AD25_PAA5, - TEGRA_PIN_GMI_AD26_PAA6, - TEGRA_PIN_GMI_AD27_PAA7, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_OWC, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -enum tegra_mux { - TEGRA_MUX_AHB_CLK, - TEGRA_MUX_APB_CLK, - TEGRA_MUX_AUDIO_SYNC, - TEGRA_MUX_CRT, - TEGRA_MUX_DAP1, - TEGRA_MUX_DAP2, - TEGRA_MUX_DAP3, - TEGRA_MUX_DAP4, - TEGRA_MUX_DAP5, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_EMC_TEST0_DLL, - TEGRA_MUX_EMC_TEST1_DLL, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_INT, - TEGRA_MUX_HDMI, - TEGRA_MUX_I2CP, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_IDE, - TEGRA_MUX_IRDA, - TEGRA_MUX_KBC, - TEGRA_MUX_MIO, - TEGRA_MUX_MIPI_HS, - TEGRA_MUX_NAND, - TEGRA_MUX_OSC, - TEGRA_MUX_OWR, - TEGRA_MUX_PCIE, - TEGRA_MUX_PLLA_OUT, - TEGRA_MUX_PLLC_OUT1, - TEGRA_MUX_PLLM_OUT1, - TEGRA_MUX_PLLP_OUT2, - TEGRA_MUX_PLLP_OUT3, - TEGRA_MUX_PLLP_OUT4, - TEGRA_MUX_PWM, - TEGRA_MUX_PWR_INTR, - TEGRA_MUX_PWR_ON, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SDIO1, - TEGRA_MUX_SDIO2, - TEGRA_MUX_SDIO3, - TEGRA_MUX_SDIO4, - TEGRA_MUX_SFLASH, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI2_ALT, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_TRACE, - TEGRA_MUX_TWC, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_UARTE, - TEGRA_MUX_ULPI, - TEGRA_MUX_VI, - TEGRA_MUX_VI_SENSOR_CLK, - TEGRA_MUX_XIO, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra20_functions[] = { - FUNCTION(ahb_clk), - FUNCTION(apb_clk), - FUNCTION(audio_sync), - FUNCTION(crt), - FUNCTION(dap1), - FUNCTION(dap2), - FUNCTION(dap3), - FUNCTION(dap4), - FUNCTION(dap5), - FUNCTION(displaya), - FUNCTION(displayb), - FUNCTION(emc_test0_dll), - FUNCTION(emc_test1_dll), - FUNCTION(gmi), - FUNCTION(gmi_int), - FUNCTION(hdmi), - FUNCTION(i2cp), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(ide), - FUNCTION(irda), - FUNCTION(kbc), - FUNCTION(mio), - FUNCTION(mipi_hs), - FUNCTION(nand), - FUNCTION(osc), - FUNCTION(owr), - FUNCTION(pcie), - FUNCTION(plla_out), - FUNCTION(pllc_out1), - FUNCTION(pllm_out1), - FUNCTION(pllp_out2), - FUNCTION(pllp_out3), - FUNCTION(pllp_out4), - FUNCTION(pwm), - FUNCTION(pwr_intr), - FUNCTION(pwr_on), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sdio1), - FUNCTION(sdio2), - FUNCTION(sdio3), - FUNCTION(sdio4), - FUNCTION(sflash), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi2_alt), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(trace), - FUNCTION(twc), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(uarte), - FUNCTION(ulpi), - FUNCTION(vi), - FUNCTION(vi_sensor_clk), - FUNCTION(xio), -}; - -#define TRISTATE_REG_A 0x14 -#define PIN_MUX_CTL_REG_A 0x80 -#define PULLUPDOWN_REG_A 0xa0 -#define PINGROUP_REG_A 0x868 - -/* Pin group with mux control, and typically tri-state and pull-up/down too */ -#define MUX_PG(pg_name, f0, f1, f2, f3, \ - tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_ ## f0, \ - TEGRA_MUX_ ## f1, \ - TEGRA_MUX_ ## f2, \ - TEGRA_MUX_ ## f3, \ - }, \ - .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \ - .mux_bank = 1, \ - .mux_bit = mux_b, \ - .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ - .pupd_bank = 2, \ - .pupd_bit = pupd_b, \ - .tri_reg = ((tri_r) - TRISTATE_REG_A), \ - .tri_bank = 0, \ - .tri_bit = tri_b, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = -1, \ - } - -/* Pin groups with only pull up and pull down control */ -#define PULL_PG(pg_name, pupd_r, pupd_b) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ - .pupd_bank = 2, \ - .pupd_bit = pupd_b, \ - .drv_reg = -1, \ - } - -/* Pin groups for drive strength registers (configurable version) */ -#define DRV_PG_EXT(pg_name, r, hsm_b, schmitt_b, lpmd_b, \ - drvdn_b, drvup_b, \ - slwr_b, slwr_w, slwf_b, slwf_w) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 3, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = 5, \ - .drvup_bit = drvup_b, \ - .drvup_width = 5, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = -1, \ - } - -/* Pin groups for drive strength registers (simple version) */ -#define DRV_PG(pg_name, r) \ - DRV_PG_EXT(pg_name, r, 2, 3, 4, 12, 20, 28, 2, 30, 2) - -static const struct tegra_pingroup tegra20_groups[] = { - /* name, f0, f1, f2, f3, tri r/b, mux r/b, pupd r/b */ - MUX_PG(ata, IDE, NAND, GMI, RSVD4, 0x14, 0, 0x80, 24, 0xa0, 0), - MUX_PG(atb, IDE, NAND, GMI, SDIO4, 0x14, 1, 0x80, 16, 0xa0, 2), - MUX_PG(atc, IDE, NAND, GMI, SDIO4, 0x14, 2, 0x80, 22, 0xa0, 4), - MUX_PG(atd, IDE, NAND, GMI, SDIO4, 0x14, 3, 0x80, 20, 0xa0, 6), - MUX_PG(ate, IDE, NAND, GMI, RSVD4, 0x18, 25, 0x80, 12, 0xa0, 8), - MUX_PG(cdev1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, 0x14, 4, 0x88, 2, 0xa8, 0), - MUX_PG(cdev2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, 0x14, 5, 0x88, 4, 0xa8, 2), - MUX_PG(crtp, CRT, RSVD2, RSVD3, RSVD4, 0x20, 14, 0x98, 20, 0xa4, 24), - MUX_PG(csus, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, 0x14, 6, 0x88, 6, 0xac, 24), - MUX_PG(dap1, DAP1, RSVD2, GMI, SDIO2, 0x14, 7, 0x88, 20, 0xa0, 10), - MUX_PG(dap2, DAP2, TWC, RSVD3, GMI, 0x14, 8, 0x88, 22, 0xa0, 12), - MUX_PG(dap3, DAP3, RSVD2, RSVD3, RSVD4, 0x14, 9, 0x88, 24, 0xa0, 14), - MUX_PG(dap4, DAP4, RSVD2, GMI, RSVD4, 0x14, 10, 0x88, 26, 0xa0, 16), - MUX_PG(ddc, I2C2, RSVD2, RSVD3, RSVD4, 0x18, 31, 0x88, 0, 0xb0, 28), - MUX_PG(dta, RSVD1, SDIO2, VI, RSVD4, 0x14, 11, 0x84, 20, 0xa0, 18), - MUX_PG(dtb, RSVD1, RSVD2, VI, SPI1, 0x14, 12, 0x84, 22, 0xa0, 20), - MUX_PG(dtc, RSVD1, RSVD2, VI, RSVD4, 0x14, 13, 0x84, 26, 0xa0, 22), - MUX_PG(dtd, RSVD1, SDIO2, VI, RSVD4, 0x14, 14, 0x84, 28, 0xa0, 24), - MUX_PG(dte, RSVD1, RSVD2, VI, SPI1, 0x14, 15, 0x84, 30, 0xa0, 26), - MUX_PG(dtf, I2C3, RSVD2, VI, RSVD4, 0x20, 12, 0x98, 30, 0xa0, 28), - MUX_PG(gma, UARTE, SPI3, GMI, SDIO4, 0x14, 28, 0x84, 0, 0xb0, 20), - MUX_PG(gmb, IDE, NAND, GMI, GMI_INT, 0x18, 29, 0x88, 28, 0xb0, 22), - MUX_PG(gmc, UARTD, SPI4, GMI, SFLASH, 0x14, 29, 0x84, 2, 0xb0, 24), - MUX_PG(gmd, RSVD1, NAND, GMI, SFLASH, 0x18, 30, 0x88, 30, 0xb0, 26), - MUX_PG(gme, RSVD1, DAP5, GMI, SDIO4, 0x18, 0, 0x8c, 0, 0xa8, 24), - MUX_PG(gpu, PWM, UARTA, GMI, RSVD4, 0x14, 16, 0x8c, 4, 0xa4, 20), - MUX_PG(gpu7, RTCK, RSVD2, RSVD3, RSVD4, 0x20, 11, 0x98, 28, 0xa4, 6), - MUX_PG(gpv, PCIE, RSVD2, RSVD3, RSVD4, 0x14, 17, 0x8c, 2, 0xa0, 30), - MUX_PG(hdint, HDMI, RSVD2, RSVD3, RSVD4, 0x1c, 23, 0x84, 4, -1, -1), - MUX_PG(i2cp, I2CP, RSVD2, RSVD3, RSVD4, 0x14, 18, 0x88, 8, 0xa4, 2), - MUX_PG(irrx, UARTA, UARTB, GMI, SPI4, 0x14, 20, 0x88, 18, 0xa8, 22), - MUX_PG(irtx, UARTA, UARTB, GMI, SPI4, 0x14, 19, 0x88, 16, 0xa8, 20), - MUX_PG(kbca, KBC, NAND, SDIO2, EMC_TEST0_DLL, 0x14, 22, 0x88, 10, 0xa4, 8), - MUX_PG(kbcb, KBC, NAND, SDIO2, MIO, 0x14, 21, 0x88, 12, 0xa4, 10), - MUX_PG(kbcc, KBC, NAND, TRACE, EMC_TEST1_DLL, 0x18, 26, 0x88, 14, 0xa4, 12), - MUX_PG(kbcd, KBC, NAND, SDIO2, MIO, 0x20, 10, 0x98, 26, 0xa4, 14), - MUX_PG(kbce, KBC, NAND, OWR, RSVD4, 0x14, 26, 0x80, 28, 0xb0, 2), - MUX_PG(kbcf, KBC, NAND, TRACE, MIO, 0x14, 27, 0x80, 26, 0xb0, 0), - MUX_PG(lcsn, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 31, 0x90, 12, -1, -1), - MUX_PG(ld0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 0, 0x94, 0, -1, -1), - MUX_PG(ld1, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 1, 0x94, 2, -1, -1), - MUX_PG(ld2, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 2, 0x94, 4, -1, -1), - MUX_PG(ld3, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 3, 0x94, 6, -1, -1), - MUX_PG(ld4, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 4, 0x94, 8, -1, -1), - MUX_PG(ld5, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 5, 0x94, 10, -1, -1), - MUX_PG(ld6, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 6, 0x94, 12, -1, -1), - MUX_PG(ld7, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 7, 0x94, 14, -1, -1), - MUX_PG(ld8, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 8, 0x94, 16, -1, -1), - MUX_PG(ld9, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 9, 0x94, 18, -1, -1), - MUX_PG(ld10, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 10, 0x94, 20, -1, -1), - MUX_PG(ld11, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 11, 0x94, 22, -1, -1), - MUX_PG(ld12, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 12, 0x94, 24, -1, -1), - MUX_PG(ld13, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 13, 0x94, 26, -1, -1), - MUX_PG(ld14, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 14, 0x94, 28, -1, -1), - MUX_PG(ld15, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 15, 0x94, 30, -1, -1), - MUX_PG(ld16, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 16, 0x98, 0, -1, -1), - MUX_PG(ld17, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 17, 0x98, 2, -1, -1), - MUX_PG(ldc, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 30, 0x90, 14, -1, -1), - MUX_PG(ldi, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 6, 0x98, 16, -1, -1), - MUX_PG(lhp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 18, 0x98, 10, -1, -1), - MUX_PG(lhp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 19, 0x98, 4, -1, -1), - MUX_PG(lhp2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 20, 0x98, 6, -1, -1), - MUX_PG(lhs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x20, 7, 0x90, 22, -1, -1), - MUX_PG(lm0, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 24, 0x90, 26, -1, -1), - MUX_PG(lm1, DISPLAYA, DISPLAYB, RSVD3, CRT, 0x1c, 25, 0x90, 28, -1, -1), - MUX_PG(lpp, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 8, 0x98, 14, -1, -1), - MUX_PG(lpw0, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 3, 0x90, 0, -1, -1), - MUX_PG(lpw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 4, 0x90, 2, -1, -1), - MUX_PG(lpw2, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 5, 0x90, 4, -1, -1), - MUX_PG(lsc0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 27, 0x90, 18, -1, -1), - MUX_PG(lsc1, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 28, 0x90, 20, -1, -1), - MUX_PG(lsck, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 29, 0x90, 16, -1, -1), - MUX_PG(lsda, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 1, 0x90, 8, -1, -1), - MUX_PG(lsdi, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x20, 2, 0x90, 6, -1, -1), - MUX_PG(lspi, DISPLAYA, DISPLAYB, XIO, HDMI, 0x20, 0, 0x90, 10, -1, -1), - MUX_PG(lvp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 21, 0x90, 30, -1, -1), - MUX_PG(lvp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 22, 0x98, 8, -1, -1), - MUX_PG(lvs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 26, 0x90, 24, -1, -1), - MUX_PG(owc, OWR, RSVD2, RSVD3, RSVD4, 0x14, 31, 0x84, 8, 0xb0, 30), - MUX_PG(pmc, PWR_ON, PWR_INTR, RSVD3, RSVD4, 0x14, 23, 0x98, 18, -1, -1), - MUX_PG(pta, I2C2, HDMI, GMI, RSVD4, 0x14, 24, 0x98, 22, 0xa4, 4), - MUX_PG(rm, I2C1, RSVD2, RSVD3, RSVD4, 0x14, 25, 0x80, 14, 0xa4, 0), - MUX_PG(sdb, UARTA, PWM, SDIO3, SPI2, 0x20, 15, 0x8c, 10, -1, -1), - MUX_PG(sdc, PWM, TWC, SDIO3, SPI3, 0x18, 1, 0x8c, 12, 0xac, 28), - MUX_PG(sdd, UARTA, PWM, SDIO3, SPI3, 0x18, 2, 0x8c, 14, 0xac, 30), - MUX_PG(sdio1, SDIO1, RSVD2, UARTE, UARTA, 0x14, 30, 0x80, 30, 0xb0, 18), - MUX_PG(slxa, PCIE, SPI4, SDIO3, SPI2, 0x18, 3, 0x84, 6, 0xa4, 22), - MUX_PG(slxc, SPDIF, SPI4, SDIO3, SPI2, 0x18, 5, 0x84, 10, 0xa4, 26), - MUX_PG(slxd, SPDIF, SPI4, SDIO3, SPI2, 0x18, 6, 0x84, 12, 0xa4, 28), - MUX_PG(slxk, PCIE, SPI4, SDIO3, SPI2, 0x18, 7, 0x84, 14, 0xa4, 30), - MUX_PG(spdi, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 8, 0x8c, 8, 0xa4, 16), - MUX_PG(spdo, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 9, 0x8c, 6, 0xa4, 18), - MUX_PG(spia, SPI1, SPI2, SPI3, GMI, 0x18, 10, 0x8c, 30, 0xa8, 4), - MUX_PG(spib, SPI1, SPI2, SPI3, GMI, 0x18, 11, 0x8c, 28, 0xa8, 6), - MUX_PG(spic, SPI1, SPI2, SPI3, GMI, 0x18, 12, 0x8c, 26, 0xa8, 8), - MUX_PG(spid, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 13, 0x8c, 24, 0xa8, 10), - MUX_PG(spie, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 14, 0x8c, 22, 0xa8, 12), - MUX_PG(spif, SPI3, SPI1, SPI2, RSVD4, 0x18, 15, 0x8c, 20, 0xa8, 14), - MUX_PG(spig, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 16, 0x8c, 18, 0xa8, 16), - MUX_PG(spih, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 17, 0x8c, 16, 0xa8, 18), - MUX_PG(uaa, SPI3, MIPI_HS, UARTA, ULPI, 0x18, 18, 0x80, 0, 0xac, 0), - MUX_PG(uab, SPI2, MIPI_HS, UARTA, ULPI, 0x18, 19, 0x80, 2, 0xac, 2), - MUX_PG(uac, OWR, RSVD2, RSVD3, RSVD4, 0x18, 20, 0x80, 4, 0xac, 4), - MUX_PG(uad, IRDA, SPDIF, UARTA, SPI4, 0x18, 21, 0x80, 6, 0xac, 6), - MUX_PG(uca, UARTC, RSVD2, GMI, RSVD4, 0x18, 22, 0x84, 16, 0xac, 8), - MUX_PG(ucb, UARTC, PWM, GMI, RSVD4, 0x18, 23, 0x84, 18, 0xac, 10), - MUX_PG(uda, SPI1, RSVD2, UARTD, ULPI, 0x20, 13, 0x80, 8, 0xb0, 16), - /* pg_name, pupd_r/b */ - PULL_PG(ck32, 0xb0, 14), - PULL_PG(ddrc, 0xac, 26), - PULL_PG(pmca, 0xb0, 4), - PULL_PG(pmcb, 0xb0, 6), - PULL_PG(pmcc, 0xb0, 8), - PULL_PG(pmcd, 0xb0, 10), - PULL_PG(pmce, 0xb0, 12), - PULL_PG(xm2c, 0xa8, 30), - PULL_PG(xm2d, 0xa8, 28), - PULL_PG(ls, 0xac, 20), - PULL_PG(lc, 0xac, 22), - PULL_PG(ld17_0, 0xac, 12), - PULL_PG(ld19_18, 0xac, 14), - PULL_PG(ld21_20, 0xac, 16), - PULL_PG(ld23_22, 0xac, 18), - /* pg_name, r */ - DRV_PG(ao1, 0x868), - DRV_PG(ao2, 0x86c), - DRV_PG(at1, 0x870), - DRV_PG(at2, 0x874), - DRV_PG(cdev1, 0x878), - DRV_PG(cdev2, 0x87c), - DRV_PG(csus, 0x880), - DRV_PG(dap1, 0x884), - DRV_PG(dap2, 0x888), - DRV_PG(dap3, 0x88c), - DRV_PG(dap4, 0x890), - DRV_PG(dbg, 0x894), - DRV_PG(lcd1, 0x898), - DRV_PG(lcd2, 0x89c), - DRV_PG(sdmmc2, 0x8a0), - DRV_PG(sdmmc3, 0x8a4), - DRV_PG(spi, 0x8a8), - DRV_PG(uaa, 0x8ac), - DRV_PG(uab, 0x8b0), - DRV_PG(uart2, 0x8b4), - DRV_PG(uart3, 0x8b8), - DRV_PG(vi1, 0x8bc), - DRV_PG(vi2, 0x8c0), - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvup_b, slwr_b, slwr_w, slwf_b, slwf_w */ - DRV_PG_EXT(xm2a, 0x8c4, -1, -1, 4, 14, 19, 24, 4, 28, 4), - DRV_PG_EXT(xm2c, 0x8c8, -1, 3, -1, 14, 19, 24, 4, 28, 4), - DRV_PG_EXT(xm2d, 0x8cc, -1, 3, -1, 14, 19, 24, 4, 28, 4), - DRV_PG_EXT(xm2clk, 0x8d0, -1, -1, -1, 14, 19, 24, 4, 28, 4), - /* pg_name, r */ - DRV_PG(sdio1, 0x8e0), - DRV_PG(crt, 0x8ec), - DRV_PG(ddc, 0x8f0), - DRV_PG(gma, 0x8f4), - DRV_PG(gmb, 0x8f8), - DRV_PG(gmc, 0x8fc), - DRV_PG(gmd, 0x900), - DRV_PG(gme, 0x904), - DRV_PG(owr, 0x908), - DRV_PG(uda, 0x90c), -}; - -static const struct tegra_pinctrl_soc_data tegra20_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra20_pins, - .npins = ARRAY_SIZE(tegra20_pins), - .functions = tegra20_functions, - .nfunctions = ARRAY_SIZE(tegra20_functions), - .groups = tegra20_groups, - .ngroups = ARRAY_SIZE(tegra20_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra20_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra20_pinctrl); -} - -static const struct of_device_id tegra20_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra20-pinmux", }, - { }, -}; - -static struct platform_driver tegra20_pinctrl_driver = { - .driver = { - .name = "tegra20-pinctrl", - .of_match_table = tegra20_pinctrl_of_match, - }, - .probe = tegra20_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra20_pinctrl_driver); - -MODULE_AUTHOR("Stephen Warren "); -MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match); diff --git a/drivers/pinctrl/pinctrl-tegra210.c b/drivers/pinctrl/pinctrl-tegra210.c deleted file mode 100644 index 252b464901c0..000000000000 --- a/drivers/pinctrl/pinctrl-tegra210.c +++ /dev/null @@ -1,1588 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra210 pinmux - * - * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. - * - * 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 "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_PEX_L0_RST_N_PA0 _GPIO(0) -#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1 _GPIO(1) -#define TEGRA_PIN_PEX_WAKE_N_PA2 _GPIO(2) -#define TEGRA_PIN_PEX_L1_RST_N_PA3 _GPIO(3) -#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4 _GPIO(4) -#define TEGRA_PIN_SATA_LED_ACTIVE_PA5 _GPIO(5) -#define TEGRA_PIN_PA6 _GPIO(6) -#define TEGRA_PIN_DAP1_FS_PB0 _GPIO(8) -#define TEGRA_PIN_DAP1_DIN_PB1 _GPIO(9) -#define TEGRA_PIN_DAP1_DOUT_PB2 _GPIO(10) -#define TEGRA_PIN_DAP1_SCLK_PB3 _GPIO(11) -#define TEGRA_PIN_SPI2_MOSI_PB4 _GPIO(12) -#define TEGRA_PIN_SPI2_MISO_PB5 _GPIO(13) -#define TEGRA_PIN_SPI2_SCK_PB6 _GPIO(14) -#define TEGRA_PIN_SPI2_CS0_PB7 _GPIO(15) -#define TEGRA_PIN_SPI1_MOSI_PC0 _GPIO(16) -#define TEGRA_PIN_SPI1_MISO_PC1 _GPIO(17) -#define TEGRA_PIN_SPI1_SCK_PC2 _GPIO(18) -#define TEGRA_PIN_SPI1_CS0_PC3 _GPIO(19) -#define TEGRA_PIN_SPI1_CS1_PC4 _GPIO(20) -#define TEGRA_PIN_SPI4_SCK_PC5 _GPIO(21) -#define TEGRA_PIN_SPI4_CS0_PC6 _GPIO(22) -#define TEGRA_PIN_SPI4_MOSI_PC7 _GPIO(23) -#define TEGRA_PIN_SPI4_MISO_PD0 _GPIO(24) -#define TEGRA_PIN_UART3_TX_PD1 _GPIO(25) -#define TEGRA_PIN_UART3_RX_PD2 _GPIO(26) -#define TEGRA_PIN_UART3_RTS_PD3 _GPIO(27) -#define TEGRA_PIN_UART3_CTS_PD4 _GPIO(28) -#define TEGRA_PIN_DMIC1_CLK_PE0 _GPIO(32) -#define TEGRA_PIN_DMIC1_DAT_PE1 _GPIO(33) -#define TEGRA_PIN_DMIC2_CLK_PE2 _GPIO(34) -#define TEGRA_PIN_DMIC2_DAT_PE3 _GPIO(35) -#define TEGRA_PIN_DMIC3_CLK_PE4 _GPIO(36) -#define TEGRA_PIN_DMIC3_DAT_PE5 _GPIO(37) -#define TEGRA_PIN_PE6 _GPIO(38) -#define TEGRA_PIN_PE7 _GPIO(39) -#define TEGRA_PIN_GEN3_I2C_SCL_PF0 _GPIO(40) -#define TEGRA_PIN_GEN3_I2C_SDA_PF1 _GPIO(41) -#define TEGRA_PIN_UART2_TX_PG0 _GPIO(48) -#define TEGRA_PIN_UART2_RX_PG1 _GPIO(49) -#define TEGRA_PIN_UART2_RTS_PG2 _GPIO(50) -#define TEGRA_PIN_UART2_CTS_PG3 _GPIO(51) -#define TEGRA_PIN_WIFI_EN_PH0 _GPIO(56) -#define TEGRA_PIN_WIFI_RST_PH1 _GPIO(57) -#define TEGRA_PIN_WIFI_WAKE_AP_PH2 _GPIO(58) -#define TEGRA_PIN_AP_WAKE_BT_PH3 _GPIO(59) -#define TEGRA_PIN_BT_RST_PH4 _GPIO(60) -#define TEGRA_PIN_BT_WAKE_AP_PH5 _GPIO(61) -#define TEGRA_PIN_PH6 _GPIO(62) -#define TEGRA_PIN_AP_WAKE_NFC_PH7 _GPIO(63) -#define TEGRA_PIN_NFC_EN_PI0 _GPIO(64) -#define TEGRA_PIN_NFC_INT_PI1 _GPIO(65) -#define TEGRA_PIN_GPS_EN_PI2 _GPIO(66) -#define TEGRA_PIN_GPS_RST_PI3 _GPIO(67) -#define TEGRA_PIN_UART4_TX_PI4 _GPIO(68) -#define TEGRA_PIN_UART4_RX_PI5 _GPIO(69) -#define TEGRA_PIN_UART4_RTS_PI6 _GPIO(70) -#define TEGRA_PIN_UART4_CTS_PI7 _GPIO(71) -#define TEGRA_PIN_GEN1_I2C_SDA_PJ0 _GPIO(72) -#define TEGRA_PIN_GEN1_I2C_SCL_PJ1 _GPIO(73) -#define TEGRA_PIN_GEN2_I2C_SCL_PJ2 _GPIO(74) -#define TEGRA_PIN_GEN2_I2C_SDA_PJ3 _GPIO(75) -#define TEGRA_PIN_DAP4_FS_PJ4 _GPIO(76) -#define TEGRA_PIN_DAP4_DIN_PJ5 _GPIO(77) -#define TEGRA_PIN_DAP4_DOUT_PJ6 _GPIO(78) -#define TEGRA_PIN_DAP4_SCLK_PJ7 _GPIO(79) -#define TEGRA_PIN_PK0 _GPIO(80) -#define TEGRA_PIN_PK1 _GPIO(81) -#define TEGRA_PIN_PK2 _GPIO(82) -#define TEGRA_PIN_PK3 _GPIO(83) -#define TEGRA_PIN_PK4 _GPIO(84) -#define TEGRA_PIN_PK5 _GPIO(85) -#define TEGRA_PIN_PK6 _GPIO(86) -#define TEGRA_PIN_PK7 _GPIO(87) -#define TEGRA_PIN_PL0 _GPIO(88) -#define TEGRA_PIN_PL1 _GPIO(89) -#define TEGRA_PIN_SDMMC1_CLK_PM0 _GPIO(96) -#define TEGRA_PIN_SDMMC1_CMD_PM1 _GPIO(97) -#define TEGRA_PIN_SDMMC1_DAT3_PM2 _GPIO(98) -#define TEGRA_PIN_SDMMC1_DAT2_PM3 _GPIO(99) -#define TEGRA_PIN_SDMMC1_DAT1_PM4 _GPIO(100) -#define TEGRA_PIN_SDMMC1_DAT0_PM5 _GPIO(101) -#define TEGRA_PIN_SDMMC3_CLK_PP0 _GPIO(120) -#define TEGRA_PIN_SDMMC3_CMD_PP1 _GPIO(121) -#define TEGRA_PIN_SDMMC3_DAT3_PP2 _GPIO(122) -#define TEGRA_PIN_SDMMC3_DAT2_PP3 _GPIO(123) -#define TEGRA_PIN_SDMMC3_DAT1_PP4 _GPIO(124) -#define TEGRA_PIN_SDMMC3_DAT0_PP5 _GPIO(125) -#define TEGRA_PIN_CAM1_MCLK_PS0 _GPIO(144) -#define TEGRA_PIN_CAM2_MCLK_PS1 _GPIO(145) -#define TEGRA_PIN_CAM_I2C_SCL_PS2 _GPIO(146) -#define TEGRA_PIN_CAM_I2C_SDA_PS3 _GPIO(147) -#define TEGRA_PIN_CAM_RST_PS4 _GPIO(148) -#define TEGRA_PIN_CAM_AF_EN_PS5 _GPIO(149) -#define TEGRA_PIN_CAM_FLASH_EN_PS6 _GPIO(150) -#define TEGRA_PIN_CAM1_PWDN_PS7 _GPIO(151) -#define TEGRA_PIN_CAM2_PWDN_PT0 _GPIO(152) -#define TEGRA_PIN_CAM1_STROBE_PT1 _GPIO(153) -#define TEGRA_PIN_UART1_TX_PU0 _GPIO(160) -#define TEGRA_PIN_UART1_RX_PU1 _GPIO(161) -#define TEGRA_PIN_UART1_RTS_PU2 _GPIO(162) -#define TEGRA_PIN_UART1_CTS_PU3 _GPIO(163) -#define TEGRA_PIN_LCD_BL_PWM_PV0 _GPIO(168) -#define TEGRA_PIN_LCD_BL_EN_PV1 _GPIO(169) -#define TEGRA_PIN_LCD_RST_PV2 _GPIO(170) -#define TEGRA_PIN_LCD_GPIO1_PV3 _GPIO(171) -#define TEGRA_PIN_LCD_GPIO2_PV4 _GPIO(172) -#define TEGRA_PIN_AP_READY_PV5 _GPIO(173) -#define TEGRA_PIN_TOUCH_RST_PV6 _GPIO(174) -#define TEGRA_PIN_TOUCH_CLK_PV7 _GPIO(175) -#define TEGRA_PIN_MODEM_WAKE_AP_PX0 _GPIO(184) -#define TEGRA_PIN_TOUCH_INT_PX1 _GPIO(185) -#define TEGRA_PIN_MOTION_INT_PX2 _GPIO(186) -#define TEGRA_PIN_ALS_PROX_INT_PX3 _GPIO(187) -#define TEGRA_PIN_TEMP_ALERT_PX4 _GPIO(188) -#define TEGRA_PIN_BUTTON_POWER_ON_PX5 _GPIO(189) -#define TEGRA_PIN_BUTTON_VOL_UP_PX6 _GPIO(190) -#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7 _GPIO(191) -#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0 _GPIO(192) -#define TEGRA_PIN_BUTTON_HOME_PY1 _GPIO(193) -#define TEGRA_PIN_LCD_TE_PY2 _GPIO(194) -#define TEGRA_PIN_PWR_I2C_SCL_PY3 _GPIO(195) -#define TEGRA_PIN_PWR_I2C_SDA_PY4 _GPIO(196) -#define TEGRA_PIN_CLK_32K_OUT_PY5 _GPIO(197) -#define TEGRA_PIN_PZ0 _GPIO(200) -#define TEGRA_PIN_PZ1 _GPIO(201) -#define TEGRA_PIN_PZ2 _GPIO(202) -#define TEGRA_PIN_PZ3 _GPIO(203) -#define TEGRA_PIN_PZ4 _GPIO(204) -#define TEGRA_PIN_PZ5 _GPIO(205) -#define TEGRA_PIN_DAP2_FS_PAA0 _GPIO(208) -#define TEGRA_PIN_DAP2_SCLK_PAA1 _GPIO(209) -#define TEGRA_PIN_DAP2_DIN_PAA2 _GPIO(210) -#define TEGRA_PIN_DAP2_DOUT_PAA3 _GPIO(211) -#define TEGRA_PIN_AUD_MCLK_PBB0 _GPIO(216) -#define TEGRA_PIN_DVFS_PWM_PBB1 _GPIO(217) -#define TEGRA_PIN_DVFS_CLK_PBB2 _GPIO(218) -#define TEGRA_PIN_GPIO_X1_AUD_PBB3 _GPIO(219) -#define TEGRA_PIN_GPIO_X3_AUD_PBB4 _GPIO(220) -#define TEGRA_PIN_HDMI_CEC_PCC0 _GPIO(224) -#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1 _GPIO(225) -#define TEGRA_PIN_SPDIF_OUT_PCC2 _GPIO(226) -#define TEGRA_PIN_SPDIF_IN_PCC3 _GPIO(227) -#define TEGRA_PIN_USB_VBUS_EN0_PCC4 _GPIO(228) -#define TEGRA_PIN_USB_VBUS_EN1_PCC5 _GPIO(229) -#define TEGRA_PIN_DP_HPD0_PCC6 _GPIO(230) -#define TEGRA_PIN_PCC7 _GPIO(231) -#define TEGRA_PIN_SPI2_CS1_PDD0 _GPIO(232) -#define TEGRA_PIN_QSPI_SCK_PEE0 _GPIO(240) -#define TEGRA_PIN_QSPI_CS_N_PEE1 _GPIO(241) -#define TEGRA_PIN_QSPI_IO0_PEE2 _GPIO(242) -#define TEGRA_PIN_QSPI_IO1_PEE3 _GPIO(243) -#define TEGRA_PIN_QSPI_IO2_PEE4 _GPIO(244) -#define TEGRA_PIN_QSPI_IO3_PEE5 _GPIO(245) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_QSPI_IO3_PEE5 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) -#define TEGRA_PIN_PWR_INT_N _PIN(2) -#define TEGRA_PIN_CLK_32K_IN _PIN(3) -#define TEGRA_PIN_JTAG_RTCK _PIN(4) -#define TEGRA_PIN_BATT_BCL _PIN(5) -#define TEGRA_PIN_CLK_REQ _PIN(6) -#define TEGRA_PIN_SHUTDOWN _PIN(7) - -static const struct pinctrl_pin_desc tegra210_pins[] = { - PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"), - PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"), - PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"), - PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"), - PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"), - PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"), - PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"), - PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"), - PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"), - PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"), - PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"), - PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"), - PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"), - PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"), - PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"), - PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"), - PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"), - PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"), - PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"), - PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"), - PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"), - PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"), - PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"), - PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"), - PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"), - PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"), - PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"), - PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"), - PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"), - PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"), - PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), - PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"), - PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"), - PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"), - PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"), - PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"), - PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"), - PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"), - PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"), - PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"), - PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), - PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), - PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), - PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), - PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), - PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"), - PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"), - PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), - PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"), - PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"), - PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"), - PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"), - PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"), - PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"), - PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"), - PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"), - PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"), - PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"), - PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"), - PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"), - PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"), - PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"), - PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"), - PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"), - PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"), - PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"), - PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"), - PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"), - PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"), - PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"), - PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"), - PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"), - PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"), - PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"), - PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"), - PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"), - PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"), - PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"), - PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"), - PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"), - PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"), - PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"), - PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"), - PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"), - PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"), - PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"), - PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"), - PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"), - PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"), - PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"), - PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"), - PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"), - PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), - PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"), - PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"), - PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"), -}; - -static const unsigned pex_l0_rst_n_pa0_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PA0, -}; - -static const unsigned pex_l0_clkreq_n_pa1_pins[] = { - TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, -}; - -static const unsigned pex_wake_n_pa2_pins[] = { - TEGRA_PIN_PEX_WAKE_N_PA2, -}; - -static const unsigned pex_l1_rst_n_pa3_pins[] = { - TEGRA_PIN_PEX_L1_RST_N_PA3, -}; - -static const unsigned pex_l1_clkreq_n_pa4_pins[] = { - TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, -}; - -static const unsigned sata_led_active_pa5_pins[] = { - TEGRA_PIN_SATA_LED_ACTIVE_PA5, -}; - -static const unsigned pa6_pins[] = { - TEGRA_PIN_PA6, -}; - -static const unsigned dap1_fs_pb0_pins[] = { - TEGRA_PIN_DAP1_FS_PB0, -}; - -static const unsigned dap1_din_pb1_pins[] = { - TEGRA_PIN_DAP1_DIN_PB1, -}; - -static const unsigned dap1_dout_pb2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PB2, -}; - -static const unsigned dap1_sclk_pb3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PB3, -}; - -static const unsigned spi2_mosi_pb4_pins[] = { - TEGRA_PIN_SPI2_MOSI_PB4, -}; - -static const unsigned spi2_miso_pb5_pins[] = { - TEGRA_PIN_SPI2_MISO_PB5, -}; - -static const unsigned spi2_sck_pb6_pins[] = { - TEGRA_PIN_SPI2_SCK_PB6, -}; - -static const unsigned spi2_cs0_pb7_pins[] = { - TEGRA_PIN_SPI2_CS0_PB7, -}; - -static const unsigned spi1_mosi_pc0_pins[] = { - TEGRA_PIN_SPI1_MOSI_PC0, -}; - -static const unsigned spi1_miso_pc1_pins[] = { - TEGRA_PIN_SPI1_MISO_PC1, -}; - -static const unsigned spi1_sck_pc2_pins[] = { - TEGRA_PIN_SPI1_SCK_PC2, -}; - -static const unsigned spi1_cs0_pc3_pins[] = { - TEGRA_PIN_SPI1_CS0_PC3, -}; - -static const unsigned spi1_cs1_pc4_pins[] = { - TEGRA_PIN_SPI1_CS1_PC4, -}; - -static const unsigned spi4_sck_pc5_pins[] = { - TEGRA_PIN_SPI4_SCK_PC5, -}; - -static const unsigned spi4_cs0_pc6_pins[] = { - TEGRA_PIN_SPI4_CS0_PC6, -}; - -static const unsigned spi4_mosi_pc7_pins[] = { - TEGRA_PIN_SPI4_MOSI_PC7, -}; - -static const unsigned spi4_miso_pd0_pins[] = { - TEGRA_PIN_SPI4_MISO_PD0, -}; - -static const unsigned uart3_tx_pd1_pins[] = { - TEGRA_PIN_UART3_TX_PD1, -}; - -static const unsigned uart3_rx_pd2_pins[] = { - TEGRA_PIN_UART3_RX_PD2, -}; - -static const unsigned uart3_rts_pd3_pins[] = { - TEGRA_PIN_UART3_RTS_PD3, -}; - -static const unsigned uart3_cts_pd4_pins[] = { - TEGRA_PIN_UART3_CTS_PD4, -}; - -static const unsigned dmic1_clk_pe0_pins[] = { - TEGRA_PIN_DMIC1_CLK_PE0, -}; - -static const unsigned dmic1_dat_pe1_pins[] = { - TEGRA_PIN_DMIC1_DAT_PE1, -}; - -static const unsigned dmic2_clk_pe2_pins[] = { - TEGRA_PIN_DMIC2_CLK_PE2, -}; - -static const unsigned dmic2_dat_pe3_pins[] = { - TEGRA_PIN_DMIC2_DAT_PE3, -}; - -static const unsigned dmic3_clk_pe4_pins[] = { - TEGRA_PIN_DMIC3_CLK_PE4, -}; - -static const unsigned dmic3_dat_pe5_pins[] = { - TEGRA_PIN_DMIC3_DAT_PE5, -}; - -static const unsigned pe6_pins[] = { - TEGRA_PIN_PE6, -}; - -static const unsigned pe7_pins[] = { - TEGRA_PIN_PE7, -}; - -static const unsigned gen3_i2c_scl_pf0_pins[] = { - TEGRA_PIN_GEN3_I2C_SCL_PF0, -}; - -static const unsigned gen3_i2c_sda_pf1_pins[] = { - TEGRA_PIN_GEN3_I2C_SDA_PF1, -}; - -static const unsigned uart2_tx_pg0_pins[] = { - TEGRA_PIN_UART2_TX_PG0, -}; - -static const unsigned uart2_rx_pg1_pins[] = { - TEGRA_PIN_UART2_RX_PG1, -}; - -static const unsigned uart2_rts_pg2_pins[] = { - TEGRA_PIN_UART2_RTS_PG2, -}; - -static const unsigned uart2_cts_pg3_pins[] = { - TEGRA_PIN_UART2_CTS_PG3, -}; - -static const unsigned wifi_en_ph0_pins[] = { - TEGRA_PIN_WIFI_EN_PH0, -}; - -static const unsigned wifi_rst_ph1_pins[] = { - TEGRA_PIN_WIFI_RST_PH1, -}; - -static const unsigned wifi_wake_ap_ph2_pins[] = { - TEGRA_PIN_WIFI_WAKE_AP_PH2, -}; - -static const unsigned ap_wake_bt_ph3_pins[] = { - TEGRA_PIN_AP_WAKE_BT_PH3, -}; - -static const unsigned bt_rst_ph4_pins[] = { - TEGRA_PIN_BT_RST_PH4, -}; - -static const unsigned bt_wake_ap_ph5_pins[] = { - TEGRA_PIN_BT_WAKE_AP_PH5, -}; - -static const unsigned ph6_pins[] = { - TEGRA_PIN_PH6, -}; - -static const unsigned ap_wake_nfc_ph7_pins[] = { - TEGRA_PIN_AP_WAKE_NFC_PH7, -}; - -static const unsigned nfc_en_pi0_pins[] = { - TEGRA_PIN_NFC_EN_PI0, -}; - -static const unsigned nfc_int_pi1_pins[] = { - TEGRA_PIN_NFC_INT_PI1, -}; - -static const unsigned gps_en_pi2_pins[] = { - TEGRA_PIN_GPS_EN_PI2, -}; - -static const unsigned gps_rst_pi3_pins[] = { - TEGRA_PIN_GPS_RST_PI3, -}; - -static const unsigned uart4_tx_pi4_pins[] = { - TEGRA_PIN_UART4_TX_PI4, -}; - -static const unsigned uart4_rx_pi5_pins[] = { - TEGRA_PIN_UART4_RX_PI5, -}; - -static const unsigned uart4_rts_pi6_pins[] = { - TEGRA_PIN_UART4_RTS_PI6, -}; - -static const unsigned uart4_cts_pi7_pins[] = { - TEGRA_PIN_UART4_CTS_PI7, -}; - -static const unsigned gen1_i2c_sda_pj0_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PJ0, -}; - -static const unsigned gen1_i2c_scl_pj1_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PJ1, -}; - -static const unsigned gen2_i2c_scl_pj2_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PJ2, -}; - -static const unsigned gen2_i2c_sda_pj3_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PJ3, -}; - -static const unsigned dap4_fs_pj4_pins[] = { - TEGRA_PIN_DAP4_FS_PJ4, -}; - -static const unsigned dap4_din_pj5_pins[] = { - TEGRA_PIN_DAP4_DIN_PJ5, -}; - -static const unsigned dap4_dout_pj6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PJ6, -}; - -static const unsigned dap4_sclk_pj7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PJ7, -}; - -static const unsigned pk0_pins[] = { - TEGRA_PIN_PK0, -}; - -static const unsigned pk1_pins[] = { - TEGRA_PIN_PK1, -}; - -static const unsigned pk2_pins[] = { - TEGRA_PIN_PK2, -}; - -static const unsigned pk3_pins[] = { - TEGRA_PIN_PK3, -}; - -static const unsigned pk4_pins[] = { - TEGRA_PIN_PK4, -}; - -static const unsigned pk5_pins[] = { - TEGRA_PIN_PK5, -}; - -static const unsigned pk6_pins[] = { - TEGRA_PIN_PK6, -}; - -static const unsigned pk7_pins[] = { - TEGRA_PIN_PK7, -}; - -static const unsigned pl0_pins[] = { - TEGRA_PIN_PL0, -}; - -static const unsigned pl1_pins[] = { - TEGRA_PIN_PL1, -}; - -static const unsigned sdmmc1_clk_pm0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PM0, -}; - -static const unsigned sdmmc1_cmd_pm1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PM1, -}; - -static const unsigned sdmmc1_dat3_pm2_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PM2, -}; - -static const unsigned sdmmc1_dat2_pm3_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PM3, -}; - -static const unsigned sdmmc1_dat1_pm4_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PM4, -}; - -static const unsigned sdmmc1_dat0_pm5_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PM5, -}; - -static const unsigned sdmmc3_clk_pp0_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PP0, -}; - -static const unsigned sdmmc3_cmd_pp1_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PP1, -}; - -static const unsigned sdmmc3_dat3_pp2_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PP2, -}; - -static const unsigned sdmmc3_dat2_pp3_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PP3, -}; - -static const unsigned sdmmc3_dat1_pp4_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PP4, -}; - -static const unsigned sdmmc3_dat0_pp5_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PP5, -}; - -static const unsigned cam1_mclk_ps0_pins[] = { - TEGRA_PIN_CAM1_MCLK_PS0, -}; - -static const unsigned cam2_mclk_ps1_pins[] = { - TEGRA_PIN_CAM2_MCLK_PS1, -}; - -static const unsigned cam_i2c_scl_ps2_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PS2, -}; - -static const unsigned cam_i2c_sda_ps3_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PS3, -}; - -static const unsigned cam_rst_ps4_pins[] = { - TEGRA_PIN_CAM_RST_PS4, -}; - -static const unsigned cam_af_en_ps5_pins[] = { - TEGRA_PIN_CAM_AF_EN_PS5, -}; - -static const unsigned cam_flash_en_ps6_pins[] = { - TEGRA_PIN_CAM_FLASH_EN_PS6, -}; - -static const unsigned cam1_pwdn_ps7_pins[] = { - TEGRA_PIN_CAM1_PWDN_PS7, -}; - -static const unsigned cam2_pwdn_pt0_pins[] = { - TEGRA_PIN_CAM2_PWDN_PT0, -}; - -static const unsigned cam1_strobe_pt1_pins[] = { - TEGRA_PIN_CAM1_STROBE_PT1, -}; - -static const unsigned uart1_tx_pu0_pins[] = { - TEGRA_PIN_UART1_TX_PU0, -}; - -static const unsigned uart1_rx_pu1_pins[] = { - TEGRA_PIN_UART1_RX_PU1, -}; - -static const unsigned uart1_rts_pu2_pins[] = { - TEGRA_PIN_UART1_RTS_PU2, -}; - -static const unsigned uart1_cts_pu3_pins[] = { - TEGRA_PIN_UART1_CTS_PU3, -}; - -static const unsigned lcd_bl_pwm_pv0_pins[] = { - TEGRA_PIN_LCD_BL_PWM_PV0, -}; - -static const unsigned lcd_bl_en_pv1_pins[] = { - TEGRA_PIN_LCD_BL_EN_PV1, -}; - -static const unsigned lcd_rst_pv2_pins[] = { - TEGRA_PIN_LCD_RST_PV2, -}; - -static const unsigned lcd_gpio1_pv3_pins[] = { - TEGRA_PIN_LCD_GPIO1_PV3, -}; - -static const unsigned lcd_gpio2_pv4_pins[] = { - TEGRA_PIN_LCD_GPIO2_PV4, -}; - -static const unsigned ap_ready_pv5_pins[] = { - TEGRA_PIN_AP_READY_PV5, -}; - -static const unsigned touch_rst_pv6_pins[] = { - TEGRA_PIN_TOUCH_RST_PV6, -}; - -static const unsigned touch_clk_pv7_pins[] = { - TEGRA_PIN_TOUCH_CLK_PV7, -}; - -static const unsigned modem_wake_ap_px0_pins[] = { - TEGRA_PIN_MODEM_WAKE_AP_PX0, -}; - -static const unsigned touch_int_px1_pins[] = { - TEGRA_PIN_TOUCH_INT_PX1, -}; - -static const unsigned motion_int_px2_pins[] = { - TEGRA_PIN_MOTION_INT_PX2, -}; - -static const unsigned als_prox_int_px3_pins[] = { - TEGRA_PIN_ALS_PROX_INT_PX3, -}; - -static const unsigned temp_alert_px4_pins[] = { - TEGRA_PIN_TEMP_ALERT_PX4, -}; - -static const unsigned button_power_on_px5_pins[] = { - TEGRA_PIN_BUTTON_POWER_ON_PX5, -}; - -static const unsigned button_vol_up_px6_pins[] = { - TEGRA_PIN_BUTTON_VOL_UP_PX6, -}; - -static const unsigned button_vol_down_px7_pins[] = { - TEGRA_PIN_BUTTON_VOL_DOWN_PX7, -}; - -static const unsigned button_slide_sw_py0_pins[] = { - TEGRA_PIN_BUTTON_SLIDE_SW_PY0, -}; - -static const unsigned button_home_py1_pins[] = { - TEGRA_PIN_BUTTON_HOME_PY1, -}; - -static const unsigned lcd_te_py2_pins[] = { - TEGRA_PIN_LCD_TE_PY2, -}; - -static const unsigned pwr_i2c_scl_py3_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PY3, -}; - -static const unsigned pwr_i2c_sda_py4_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PY4, -}; - -static const unsigned clk_32k_out_py5_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PY5, -}; - -static const unsigned pz0_pins[] = { - TEGRA_PIN_PZ0, -}; - -static const unsigned pz1_pins[] = { - TEGRA_PIN_PZ1, -}; - -static const unsigned pz2_pins[] = { - TEGRA_PIN_PZ2, -}; - -static const unsigned pz3_pins[] = { - TEGRA_PIN_PZ3, -}; - -static const unsigned pz4_pins[] = { - TEGRA_PIN_PZ4, -}; - -static const unsigned pz5_pins[] = { - TEGRA_PIN_PZ5, -}; - -static const unsigned dap2_fs_paa0_pins[] = { - TEGRA_PIN_DAP2_FS_PAA0, -}; - -static const unsigned dap2_sclk_paa1_pins[] = { - TEGRA_PIN_DAP2_SCLK_PAA1, -}; - -static const unsigned dap2_din_paa2_pins[] = { - TEGRA_PIN_DAP2_DIN_PAA2, -}; - -static const unsigned dap2_dout_paa3_pins[] = { - TEGRA_PIN_DAP2_DOUT_PAA3, -}; - -static const unsigned aud_mclk_pbb0_pins[] = { - TEGRA_PIN_AUD_MCLK_PBB0, -}; - -static const unsigned dvfs_pwm_pbb1_pins[] = { - TEGRA_PIN_DVFS_PWM_PBB1, -}; - -static const unsigned dvfs_clk_pbb2_pins[] = { - TEGRA_PIN_DVFS_CLK_PBB2, -}; - -static const unsigned gpio_x1_aud_pbb3_pins[] = { - TEGRA_PIN_GPIO_X1_AUD_PBB3, -}; - -static const unsigned gpio_x3_aud_pbb4_pins[] = { - TEGRA_PIN_GPIO_X3_AUD_PBB4, -}; - -static const unsigned hdmi_cec_pcc0_pins[] = { - TEGRA_PIN_HDMI_CEC_PCC0, -}; - -static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = { - TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, -}; - -static const unsigned spdif_out_pcc2_pins[] = { - TEGRA_PIN_SPDIF_OUT_PCC2, -}; - -static const unsigned spdif_in_pcc3_pins[] = { - TEGRA_PIN_SPDIF_IN_PCC3, -}; - -static const unsigned usb_vbus_en0_pcc4_pins[] = { - TEGRA_PIN_USB_VBUS_EN0_PCC4, -}; - -static const unsigned usb_vbus_en1_pcc5_pins[] = { - TEGRA_PIN_USB_VBUS_EN1_PCC5, -}; - -static const unsigned dp_hpd0_pcc6_pins[] = { - TEGRA_PIN_DP_HPD0_PCC6, -}; - -static const unsigned pcc7_pins[] = { - TEGRA_PIN_PCC7, -}; - -static const unsigned spi2_cs1_pdd0_pins[] = { - TEGRA_PIN_SPI2_CS1_PDD0, -}; - -static const unsigned qspi_sck_pee0_pins[] = { - TEGRA_PIN_QSPI_SCK_PEE0, -}; - -static const unsigned qspi_cs_n_pee1_pins[] = { - TEGRA_PIN_QSPI_CS_N_PEE1, -}; - -static const unsigned qspi_io0_pee2_pins[] = { - TEGRA_PIN_QSPI_IO0_PEE2, -}; - -static const unsigned qspi_io1_pee3_pins[] = { - TEGRA_PIN_QSPI_IO1_PEE3, -}; - -static const unsigned qspi_io2_pee4_pins[] = { - TEGRA_PIN_QSPI_IO2_PEE4, -}; - -static const unsigned qspi_io3_pee5_pins[] = { - TEGRA_PIN_QSPI_IO3_PEE5, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned jtag_rtck_pins[] = { - TEGRA_PIN_JTAG_RTCK, -}; - -static const unsigned batt_bcl_pins[] = { - TEGRA_PIN_BATT_BCL, -}; - -static const unsigned clk_req_pins[] = { - TEGRA_PIN_CLK_REQ, -}; - -static const unsigned shutdown_pins[] = { - TEGRA_PIN_SHUTDOWN, -}; - -static const unsigned drive_pa6_pins[] = { - TEGRA_PIN_PA6, -}; - -static const unsigned drive_pcc7_pins[] = { - TEGRA_PIN_PCC7, -}; - -static const unsigned drive_pe6_pins[] = { - TEGRA_PIN_PE6, -}; - -static const unsigned drive_pe7_pins[] = { - TEGRA_PIN_PE7, -}; - -static const unsigned drive_ph6_pins[] = { - TEGRA_PIN_PH6, -}; - -static const unsigned drive_pk0_pins[] = { - TEGRA_PIN_PK0, -}; - -static const unsigned drive_pk1_pins[] = { - TEGRA_PIN_PK1, -}; - -static const unsigned drive_pk2_pins[] = { - TEGRA_PIN_PK2, -}; - -static const unsigned drive_pk3_pins[] = { - TEGRA_PIN_PK3, -}; - -static const unsigned drive_pk4_pins[] = { - TEGRA_PIN_PK4, -}; - -static const unsigned drive_pk5_pins[] = { - TEGRA_PIN_PK5, -}; - -static const unsigned drive_pk6_pins[] = { - TEGRA_PIN_PK6, -}; - -static const unsigned drive_pk7_pins[] = { - TEGRA_PIN_PK7, -}; - -static const unsigned drive_pl0_pins[] = { - TEGRA_PIN_PL0, -}; - -static const unsigned drive_pl1_pins[] = { - TEGRA_PIN_PL1, -}; - -static const unsigned drive_pz0_pins[] = { - TEGRA_PIN_PZ0, -}; - -static const unsigned drive_pz1_pins[] = { - TEGRA_PIN_PZ1, -}; - -static const unsigned drive_pz2_pins[] = { - TEGRA_PIN_PZ2, -}; - -static const unsigned drive_pz3_pins[] = { - TEGRA_PIN_PZ3, -}; - -static const unsigned drive_pz4_pins[] = { - TEGRA_PIN_PZ4, -}; - -static const unsigned drive_pz5_pins[] = { - TEGRA_PIN_PZ5, -}; - -static const unsigned drive_sdmmc1_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PM0, - TEGRA_PIN_SDMMC1_CMD_PM1, - TEGRA_PIN_SDMMC1_DAT3_PM2, - TEGRA_PIN_SDMMC1_DAT2_PM3, - TEGRA_PIN_SDMMC1_DAT1_PM4, - TEGRA_PIN_SDMMC1_DAT0_PM5, -}; - -static const unsigned drive_sdmmc2_pins[] = { -}; - -static const unsigned drive_sdmmc3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PP0, - TEGRA_PIN_SDMMC3_CMD_PP1, - TEGRA_PIN_SDMMC3_DAT3_PP2, - TEGRA_PIN_SDMMC3_DAT2_PP3, - TEGRA_PIN_SDMMC3_DAT1_PP4, - TEGRA_PIN_SDMMC3_DAT0_PP5, -}; - -static const unsigned drive_sdmmc4_pins[] = { -}; - -enum tegra_mux { - TEGRA_MUX_AUD, - TEGRA_MUX_BCL, - TEGRA_MUX_BLINK, - TEGRA_MUX_CCLA, - TEGRA_MUX_CEC, - TEGRA_MUX_CLDVFS, - TEGRA_MUX_CLK, - TEGRA_MUX_CORE, - TEGRA_MUX_CPU, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DMIC1, - TEGRA_MUX_DMIC2, - TEGRA_MUX_DMIC3, - TEGRA_MUX_DP, - TEGRA_MUX_DTV, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2CPMU, - TEGRA_MUX_I2CVI, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4A, - TEGRA_MUX_I2S4B, - TEGRA_MUX_I2S5A, - TEGRA_MUX_I2S5B, - TEGRA_MUX_IQC0, - TEGRA_MUX_IQC1, - TEGRA_MUX_JTAG, - TEGRA_MUX_PE, - TEGRA_MUX_PE0, - TEGRA_MUX_PE1, - TEGRA_MUX_PMI, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_QSPI, - TEGRA_MUX_RSVD0, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_SATA, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SHUTDOWN, - TEGRA_MUX_SOC, - TEGRA_MUX_SOR0, - TEGRA_MUX_SOR1, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SYS, - TEGRA_MUX_TOUCH, - TEGRA_MUX_UART, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_USB, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VIMCLK, - TEGRA_MUX_VIMCLK2, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra210_functions[] = { - FUNCTION(aud), - FUNCTION(bcl), - FUNCTION(blink), - FUNCTION(ccla), - FUNCTION(cec), - FUNCTION(cldvfs), - FUNCTION(clk), - FUNCTION(core), - FUNCTION(cpu), - FUNCTION(displaya), - FUNCTION(displayb), - FUNCTION(dmic1), - FUNCTION(dmic2), - FUNCTION(dmic3), - FUNCTION(dp), - FUNCTION(dtv), - FUNCTION(extperiph3), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2cpmu), - FUNCTION(i2cvi), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4a), - FUNCTION(i2s4b), - FUNCTION(i2s5a), - FUNCTION(i2s5b), - FUNCTION(iqc0), - FUNCTION(iqc1), - FUNCTION(jtag), - FUNCTION(pe), - FUNCTION(pe0), - FUNCTION(pe1), - FUNCTION(pmi), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(qspi), - FUNCTION(rsvd0), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(sata), - FUNCTION(sdmmc1), - FUNCTION(sdmmc3), - FUNCTION(shutdown), - FUNCTION(soc), - FUNCTION(sor0), - FUNCTION(sor1), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(sys), - FUNCTION(touch), - FUNCTION(uart), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(usb), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vimclk), - FUNCTION(vimclk2), -}; - -#define DRV_PINGROUP_REG_A 0x8d4 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, \ - rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, \ - slwr_w, slwf_b, slwf_w) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 6, \ - .odrain_bit = 11, \ - .lock_bit = 7, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10), \ - .hsm_bit = PINGROUP_BIT_##hsm(9), \ - .schmitt_bit = 12, \ - .drvtype_bit = PINGROUP_BIT_##drvtype(13), \ - .drv_reg = DRV_PINGROUP_REG(rdrv), \ - .drv_bank = 0, \ - .lpmd_bit = -1, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - } - -#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, \ - slwr_b, slwr_w, slwf_b, slwf_w) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = -1, \ - .schmitt_bit = -1, \ - .lpmd_bit = -1, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = -1, \ - } - -static const struct tegra_pingroup tegra210_groups[] = { - /* pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ - PINGROUP(sdmmc1_clk_pm0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3000, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_cmd_pm1, SDMMC1, SPI3, RSVD2, RSVD3, 0x3004, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat3_pm2, SDMMC1, SPI3, RSVD2, RSVD3, 0x3008, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat2_pm3, SDMMC1, SPI3, RSVD2, RSVD3, 0x300c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat1_pm4, SDMMC1, SPI3, RSVD2, RSVD3, 0x3010, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc1_dat0_pm5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3014, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_clk_pp0, SDMMC3, RSVD1, RSVD2, RSVD3, 0x301c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_cmd_pp1, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3020, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat0_pp5, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3024, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat1_pp4, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3028, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat2_pp3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x302c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(sdmmc3_dat3_pp2, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3030, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pex_l0_rst_n_pa0, PE0, RSVD1, RSVD2, RSVD3, 0x3038, N, N, Y, 0xa5c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_l0_clkreq_n_pa1, PE0, RSVD1, RSVD2, RSVD3, 0x303c, N, N, Y, 0xa58, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_wake_n_pa2, PE, RSVD1, RSVD2, RSVD3, 0x3040, N, N, Y, 0xa68, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_l1_rst_n_pa3, PE1, RSVD1, RSVD2, RSVD3, 0x3044, N, N, Y, 0xa64, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pex_l1_clkreq_n_pa4, PE1, RSVD1, RSVD2, RSVD3, 0x3048, N, N, Y, 0xa60, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(sata_led_active_pa5, SATA, RSVD1, RSVD2, RSVD3, 0x304c, N, N, N, 0xa94, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(spi1_mosi_pc0, SPI1, RSVD1, RSVD2, RSVD3, 0x3050, Y, Y, N, 0xae0, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_miso_pc1, SPI1, RSVD1, RSVD2, RSVD3, 0x3054, Y, Y, N, 0xadc, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_sck_pc2, SPI1, RSVD1, RSVD2, RSVD3, 0x3058, Y, Y, N, 0xae4, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_cs0_pc3, SPI1, RSVD1, RSVD2, RSVD3, 0x305c, Y, Y, N, 0xad4, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi1_cs1_pc4, SPI1, RSVD1, RSVD2, RSVD3, 0x3060, Y, Y, N, 0xad8, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_mosi_pb4, SPI2, DTV, RSVD2, RSVD3, 0x3064, Y, Y, N, 0xaf4, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_miso_pb5, SPI2, DTV, RSVD2, RSVD3, 0x3068, Y, Y, N, 0xaf0, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_sck_pb6, SPI2, DTV, RSVD2, RSVD3, 0x306c, Y, Y, N, 0xaf8, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_cs0_pb7, SPI2, DTV, RSVD2, RSVD3, 0x3070, Y, Y, N, 0xae8, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi2_cs1_pdd0, SPI2, RSVD1, RSVD2, RSVD3, 0x3074, Y, Y, N, 0xaec, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_mosi_pc7, SPI4, RSVD1, RSVD2, RSVD3, 0x3078, Y, Y, N, 0xb04, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_miso_pd0, SPI4, RSVD1, RSVD2, RSVD3, 0x307c, Y, Y, N, 0xb00, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_sck_pc5, SPI4, RSVD1, RSVD2, RSVD3, 0x3080, Y, Y, N, 0xb08, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(spi4_cs0_pc6, SPI4, RSVD1, RSVD2, RSVD3, 0x3084, Y, Y, N, 0xafc, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(qspi_sck_pee0, QSPI, RSVD1, RSVD2, RSVD3, 0x3088, Y, Y, N, 0xa90, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(qspi_cs_n_pee1, QSPI, RSVD1, RSVD2, RSVD3, 0x308c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io0_pee2, QSPI, RSVD1, RSVD2, RSVD3, 0x3090, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io1_pee3, QSPI, RSVD1, RSVD2, RSVD3, 0x3094, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io2_pee4, QSPI, RSVD1, RSVD2, RSVD3, 0x3098, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(qspi_io3_pee5, QSPI, RSVD1, RSVD2, RSVD3, 0x309c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(dmic1_clk_pe0, DMIC1, I2S3, RSVD2, RSVD3, 0x30a4, N, N, N, 0x984, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic1_dat_pe1, DMIC1, I2S3, RSVD2, RSVD3, 0x30a8, N, N, N, 0x988, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic2_clk_pe2, DMIC2, I2S3, RSVD2, RSVD3, 0x30ac, N, N, N, 0x98c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic2_dat_pe3, DMIC2, I2S3, RSVD2, RSVD3, 0x30b0, N, N, N, 0x990, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic3_clk_pe4, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b4, N, N, N, 0x994, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dmic3_dat_pe5, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b8, N, N, N, 0x998, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen1_i2c_scl_pj1, I2C1, RSVD1, RSVD2, RSVD3, 0x30bc, N, N, Y, 0x9a8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen1_i2c_sda_pj0, I2C1, RSVD1, RSVD2, RSVD3, 0x30c0, N, N, Y, 0x9ac, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen2_i2c_scl_pj2, I2C2, RSVD1, RSVD2, RSVD3, 0x30c4, N, N, Y, 0x9b0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen2_i2c_sda_pj3, I2C2, RSVD1, RSVD2, RSVD3, 0x30c8, N, N, Y, 0x9b4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen3_i2c_scl_pf0, I2C3, RSVD1, RSVD2, RSVD3, 0x30cc, N, N, Y, 0x9b8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gen3_i2c_sda_pf1, I2C3, RSVD1, RSVD2, RSVD3, 0x30d0, N, N, Y, 0x9bc, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_i2c_scl_ps2, I2C3, I2CVI, RSVD2, RSVD3, 0x30d4, N, N, Y, 0x934, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_i2c_sda_ps3, I2C3, I2CVI, RSVD2, RSVD3, 0x30d8, N, N, Y, 0x938, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pwr_i2c_scl_py3, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30dc, N, N, Y, 0xa6c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pwr_i2c_sda_py4, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30e0, N, N, Y, 0xa70, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_tx_pu0, UARTA, RSVD1, RSVD2, RSVD3, 0x30e4, N, N, N, 0xb28, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_rx_pu1, UARTA, RSVD1, RSVD2, RSVD3, 0x30e8, N, N, N, 0xb24, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_rts_pu2, UARTA, RSVD1, RSVD2, RSVD3, 0x30ec, N, N, N, 0xb20, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart1_cts_pu3, UARTA, RSVD1, RSVD2, RSVD3, 0x30f0, N, N, N, 0xb1c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_tx_pg0, UARTB, I2S4A, SPDIF, UART, 0x30f4, N, N, N, 0xb38, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_rx_pg1, UARTB, I2S4A, SPDIF, UART, 0x30f8, N, N, N, 0xb34, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_rts_pg2, UARTB, I2S4A, RSVD2, UART, 0x30fc, N, N, N, 0xb30, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart2_cts_pg3, UARTB, I2S4A, RSVD2, UART, 0x3100, N, N, N, 0xb2c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_tx_pd1, UARTC, SPI4, RSVD2, RSVD3, 0x3104, N, N, N, 0xb48, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_rx_pd2, UARTC, SPI4, RSVD2, RSVD3, 0x3108, N, N, N, 0xb44, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_rts_pd3, UARTC, SPI4, RSVD2, RSVD3, 0x310c, N, N, N, 0xb40, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart3_cts_pd4, UARTC, SPI4, RSVD2, RSVD3, 0x3110, N, N, N, 0xb3c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_tx_pi4, UARTD, UART, RSVD2, RSVD3, 0x3114, N, N, N, 0xb58, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_rx_pi5, UARTD, UART, RSVD2, RSVD3, 0x3118, N, N, N, 0xb54, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_rts_pi6, UARTD, UART, RSVD2, RSVD3, 0x311c, N, N, N, 0xb50, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(uart4_cts_pi7, UARTD, UART, RSVD2, RSVD3, 0x3120, N, N, N, 0xb4c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap1_fs_pb0, I2S1, RSVD1, RSVD2, RSVD3, 0x3124, Y, Y, N, 0x95c, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap1_din_pb1, I2S1, RSVD1, RSVD2, RSVD3, 0x3128, Y, Y, N, 0x954, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap1_dout_pb2, I2S1, RSVD1, RSVD2, RSVD3, 0x312c, Y, Y, N, 0x958, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap1_sclk_pb3, I2S1, RSVD1, RSVD2, RSVD3, 0x3130, Y, Y, N, 0x960, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_fs_paa0, I2S2, RSVD1, RSVD2, RSVD3, 0x3134, Y, Y, N, 0x96c, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_din_paa2, I2S2, RSVD1, RSVD2, RSVD3, 0x3138, Y, Y, N, 0x964, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_dout_paa3, I2S2, RSVD1, RSVD2, RSVD3, 0x313c, Y, Y, N, 0x968, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap2_sclk_paa1, I2S2, RSVD1, RSVD2, RSVD3, 0x3140, Y, Y, N, 0x970, -1, -1, -1, -1, 28, 2, 30, 2), - PINGROUP(dap4_fs_pj4, I2S4B, RSVD1, RSVD2, RSVD3, 0x3144, N, N, N, 0x97c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap4_din_pj5, I2S4B, RSVD1, RSVD2, RSVD3, 0x3148, N, N, N, 0x974, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap4_dout_pj6, I2S4B, RSVD1, RSVD2, RSVD3, 0x314c, N, N, N, 0x978, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dap4_sclk_pj7, I2S4B, RSVD1, RSVD2, RSVD3, 0x3150, N, N, N, 0x980, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam1_mclk_ps0, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3154, N, N, N, 0x918, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam2_mclk_ps1, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3158, N, N, N, 0x924, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(jtag_rtck, JTAG, RSVD1, RSVD2, RSVD3, 0x315c, N, N, N, 0xa2c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(clk_32k_in, CLK, RSVD1, RSVD2, RSVD3, 0x3160, N, N, N, 0x940, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(clk_32k_out_py5, SOC, BLINK, RSVD2, RSVD3, 0x3164, N, N, N, 0x944, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(batt_bcl, BCL, RSVD1, RSVD2, RSVD3, 0x3168, N, N, Y, 0x8f8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(clk_req, SYS, RSVD1, RSVD2, RSVD3, 0x316c, N, N, N, 0x948, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cpu_pwr_req, CPU, RSVD1, RSVD2, RSVD3, 0x3170, N, N, N, 0x950, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pwr_int_n, PMI, RSVD1, RSVD2, RSVD3, 0x3174, N, N, N, 0xa74, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(shutdown, SHUTDOWN, RSVD1, RSVD2, RSVD3, 0x3178, N, N, N, 0xac8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(core_pwr_req, CORE, RSVD1, RSVD2, RSVD3, 0x317c, N, N, N, 0x94c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(aud_mclk_pbb0, AUD, RSVD1, RSVD2, RSVD3, 0x3180, N, N, N, 0x8f4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dvfs_pwm_pbb1, RSVD0, CLDVFS, SPI3, RSVD3, 0x3184, N, N, N, 0x9a4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dvfs_clk_pbb2, RSVD0, CLDVFS, SPI3, RSVD3, 0x3188, N, N, N, 0x9a0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gpio_x1_aud_pbb3, RSVD0, RSVD1, SPI3, RSVD3, 0x318c, N, N, N, 0xa14, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gpio_x3_aud_pbb4, RSVD0, RSVD1, SPI3, RSVD3, 0x3190, N, N, N, 0xa18, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pcc7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3194, N, N, Y, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(hdmi_cec_pcc0, CEC, RSVD1, RSVD2, RSVD3, 0x3198, N, N, Y, 0xa24, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(hdmi_int_dp_hpd_pcc1, DP, RSVD1, RSVD2, RSVD3, 0x319c, N, N, Y, 0xa28, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(spdif_out_pcc2, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a0, N, N, N, 0xad0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(spdif_in_pcc3, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a4, N, N, N, 0xacc, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(usb_vbus_en0_pcc4, USB, RSVD1, RSVD2, RSVD3, 0x31a8, N, N, Y, 0xb5c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(usb_vbus_en1_pcc5, USB, RSVD1, RSVD2, RSVD3, 0x31ac, N, N, Y, 0xb60, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(dp_hpd0_pcc6, DP, RSVD1, RSVD2, RSVD3, 0x31b0, N, N, N, 0x99c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(wifi_en_ph0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b4, N, N, N, 0xb64, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(wifi_rst_ph1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b8, N, N, N, 0xb68, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(wifi_wake_ap_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31bc, N, N, N, 0xb6c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(ap_wake_bt_ph3, RSVD0, UARTB, SPDIF, RSVD3, 0x31c0, N, N, N, 0x8ec, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(bt_rst_ph4, RSVD0, UARTB, SPDIF, RSVD3, 0x31c4, N, N, N, 0x8fc, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(bt_wake_ap_ph5, RSVD0, RSVD1, RSVD2, RSVD3, 0x31c8, N, N, N, 0x900, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(ap_wake_nfc_ph7, RSVD0, RSVD1, RSVD2, RSVD3, 0x31cc, N, N, N, 0x8f0, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(nfc_en_pi0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d0, N, N, N, 0xa50, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(nfc_int_pi1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d4, N, N, N, 0xa54, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gps_en_pi2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d8, N, N, N, 0xa1c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(gps_rst_pi3, RSVD0, RSVD1, RSVD2, RSVD3, 0x31dc, N, N, N, 0xa20, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_rst_ps4, VGP1, RSVD1, RSVD2, RSVD3, 0x31e0, N, N, N, 0x93c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_af_en_ps5, VIMCLK, VGP2, RSVD2, RSVD3, 0x31e4, N, N, N, 0x92c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam_flash_en_ps6, VIMCLK, VGP3, RSVD2, RSVD3, 0x31e8, N, N, N, 0x930, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam1_pwdn_ps7, VGP4, RSVD1, RSVD2, RSVD3, 0x31ec, N, N, N, 0x91c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam2_pwdn_pt0, VGP5, RSVD1, RSVD2, RSVD3, 0x31f0, N, N, N, 0x928, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(cam1_strobe_pt1, VGP6, RSVD1, RSVD2, RSVD3, 0x31f4, N, N, N, 0x920, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_te_py2, DISPLAYA, RSVD1, RSVD2, RSVD3, 0x31f8, N, N, N, 0xa44, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_bl_pwm_pv0, DISPLAYA, PWM0, SOR0, RSVD3, 0x31fc, N, N, N, 0xa34, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_bl_en_pv1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3200, N, N, N, 0xa30, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_rst_pv2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3204, N, N, N, 0xa40, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_gpio1_pv3, DISPLAYB, RSVD1, RSVD2, RSVD3, 0x3208, N, N, N, 0xa38, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(lcd_gpio2_pv4, DISPLAYB, PWM1, RSVD2, SOR1, 0x320c, N, N, N, 0xa3c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(ap_ready_pv5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3210, N, N, N, 0x8e8, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(touch_rst_pv6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3214, N, N, N, 0xb18, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(touch_clk_pv7, TOUCH, RSVD1, RSVD2, RSVD3, 0x3218, N, N, N, 0xb10, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(modem_wake_ap_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0x321c, N, N, N, 0xa48, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(touch_int_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3220, N, N, N, 0xb14, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(motion_int_px2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3224, N, N, N, 0xa4c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(als_prox_int_px3, RSVD0, RSVD1, RSVD2, RSVD3, 0x3228, N, N, N, 0x8e4, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(temp_alert_px4, RSVD0, RSVD1, RSVD2, RSVD3, 0x322c, N, N, N, 0xb0c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_power_on_px5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3230, N, N, N, 0x908, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_vol_up_px6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3234, N, N, N, 0x914, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_vol_down_px7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3238, N, N, N, 0x910, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_slide_sw_py0, RSVD0, RSVD1, RSVD2, RSVD3, 0x323c, N, N, N, 0x90c, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(button_home_py1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3240, N, N, N, 0x904, 12, 5, 20, 5, -1, -1, -1, -1), - PINGROUP(pa6, SATA, RSVD1, RSVD2, RSVD3, 0x3244, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pe6, RSVD0, I2S5A, PWM2, RSVD3, 0x3248, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pe7, RSVD0, I2S5A, PWM3, RSVD3, 0x324c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(ph6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3250, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk0, IQC0, I2S5B, RSVD2, RSVD3, 0x3254, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk1, IQC0, I2S5B, RSVD2, RSVD3, 0x3258, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk2, IQC0, I2S5B, RSVD2, RSVD3, 0x325c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk3, IQC0, I2S5B, RSVD2, RSVD3, 0x3260, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk4, IQC1, RSVD1, RSVD2, RSVD3, 0x3264, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk5, IQC1, RSVD1, RSVD2, RSVD3, 0x3268, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk6, IQC1, RSVD1, RSVD2, RSVD3, 0x326c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pk7, IQC1, RSVD1, RSVD2, RSVD3, 0x3270, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pl0, RSVD0, RSVD1, RSVD2, RSVD3, 0x3274, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pl1, SOC, RSVD1, RSVD2, RSVD3, 0x3278, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz0, VIMCLK2, RSVD1, RSVD2, RSVD3, 0x327c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz1, VIMCLK2, SDMMC1, RSVD2, RSVD3, 0x3280, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz2, SDMMC3, CCLA, RSVD2, RSVD3, 0x3284, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3288, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x328c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - PINGROUP(pz5, SOC, RSVD1, RSVD2, RSVD3, 0x3290, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), - - /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ - DRV_PINGROUP(pa6, 0x9c0, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pcc7, 0x9c4, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pe6, 0x9c8, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pe7, 0x9cc, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(ph6, 0x9d0, 12, 5, 20, 5, -1, -1, -1, -1), - DRV_PINGROUP(pk0, 0x9d4, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk1, 0x9d8, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk2, 0x9dc, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk3, 0x9e0, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk4, 0x9e4, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk5, 0x9e8, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk6, 0x9ec, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pk7, 0x9f0, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pl0, 0x9f4, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pl1, 0x9f8, -1, -1, -1, -1, 28, 2, 30, 2), - DRV_PINGROUP(pz0, 0x9fc, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz1, 0xa00, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz2, 0xa04, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz3, 0xa08, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz4, 0xa0c, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(pz5, 0xa10, 12, 7, 20, 7, -1, -1, -1, -1), - DRV_PINGROUP(sdmmc1, 0xa98, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdmmc2, 0xa9c, 2, 6, 8, 6, 28, 2, 30, 2), - DRV_PINGROUP(sdmmc3, 0xab0, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdmmc4, 0xab4, 2, 6, 8, 6, 28, 2, 30, 2), -}; - -static const struct tegra_pinctrl_soc_data tegra210_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra210_pins, - .npins = ARRAY_SIZE(tegra210_pins), - .functions = tegra210_functions, - .nfunctions = ARRAY_SIZE(tegra210_functions), - .groups = tegra210_groups, - .ngroups = ARRAY_SIZE(tegra210_groups), - .hsm_in_mux = true, - .schmitt_in_mux = true, - .drvtype_in_mux = true, -}; - -static int tegra210_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra210_pinctrl); -} - -static const struct of_device_id tegra210_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra210-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match); - -static struct platform_driver tegra210_pinctrl_driver = { - .driver = { - .name = "tegra210-pinctrl", - .of_match_table = tegra210_pinctrl_of_match, - }, - .probe = tegra210_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra210_pinctrl_driver); - -MODULE_AUTHOR("NVIDIA"); -MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c deleted file mode 100644 index 47b2fd8bb2e9..000000000000 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ /dev/null @@ -1,2507 +0,0 @@ -/* - * Pinctrl data for the NVIDIA Tegra30 pinmux - * - * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. - * - * 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 "pinctrl-tegra.h" - -/* - * Most pins affected by the pinmux can also be GPIOs. Define these first. - * These must match how the GPIO driver names/numbers its pins. - */ -#define _GPIO(offset) (offset) - -#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) -#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) -#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) -#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) -#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) -#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) -#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) -#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) -#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) -#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) -#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) -#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) -#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) -#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) -#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) -#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) -#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) -#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) -#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) -#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) -#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) -#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) -#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) -#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) -#define TEGRA_PIN_SDMMC3_DAT5_PD0 _GPIO(24) -#define TEGRA_PIN_SDMMC3_DAT4_PD1 _GPIO(25) -#define TEGRA_PIN_LCD_DC1_PD2 _GPIO(26) -#define TEGRA_PIN_SDMMC3_DAT6_PD3 _GPIO(27) -#define TEGRA_PIN_SDMMC3_DAT7_PD4 _GPIO(28) -#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) -#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) -#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) -#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) -#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) -#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) -#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) -#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) -#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) -#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) -#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) -#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) -#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) -#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) -#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) -#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) -#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) -#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) -#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) -#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) -#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) -#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) -#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) -#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) -#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) -#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) -#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) -#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) -#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) -#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) -#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) -#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) -#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) -#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) -#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) -#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) -#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) -#define TEGRA_PIN_GMI_DQS_PI2 _GPIO(66) -#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) -#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) -#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) -#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) -#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) -#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) -#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) -#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) -#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) -#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) -#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) -#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) -#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) -#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) -#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) -#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) -#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) -#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) -#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) -#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) -#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) -#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) -#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) -#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) -#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) -#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) -#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) -#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) -#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) -#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) -#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) -#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) -#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) -#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) -#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) -#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) -#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) -#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) -#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) -#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) -#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) -#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) -#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) -#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) -#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) -#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) -#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) -#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) -#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) -#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) -#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) -#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) -#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) -#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) -#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) -#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) -#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) -#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) -#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) -#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) -#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) -#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) -#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) -#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) -#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) -#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) -#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) -#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) -#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) -#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) -#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) -#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) -#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) -#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) -#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) -#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) -#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) -#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) -#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) -#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) -#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) -#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) -#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) -#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) -#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) -#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) -#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) -#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) -#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) -#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) -#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) -#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) -#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) -#define TEGRA_PIN_PU0 _GPIO(160) -#define TEGRA_PIN_PU1 _GPIO(161) -#define TEGRA_PIN_PU2 _GPIO(162) -#define TEGRA_PIN_PU3 _GPIO(163) -#define TEGRA_PIN_PU4 _GPIO(164) -#define TEGRA_PIN_PU5 _GPIO(165) -#define TEGRA_PIN_PU6 _GPIO(166) -#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) -#define TEGRA_PIN_PV0 _GPIO(168) -#define TEGRA_PIN_PV1 _GPIO(169) -#define TEGRA_PIN_PV2 _GPIO(170) -#define TEGRA_PIN_PV3 _GPIO(171) -#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) -#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) -#define TEGRA_PIN_CRT_HSYNC_PV6 _GPIO(174) -#define TEGRA_PIN_CRT_VSYNC_PV7 _GPIO(175) -#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) -#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) -#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) -#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) -#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) -#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) -#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) -#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) -#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) -#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) -#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) -#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) -#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) -#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) -#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) -#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) -#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) -#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) -#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) -#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) -#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) -#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) -#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) -#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) -#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) -#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) -#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) -#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) -#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) -#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) -#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) -#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) -#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) -#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) -#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) -#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) -#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) -#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) -#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) -#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) -#define TEGRA_PIN_PBB0 _GPIO(216) -#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) -#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) -#define TEGRA_PIN_PBB3 _GPIO(219) -#define TEGRA_PIN_PBB4 _GPIO(220) -#define TEGRA_PIN_PBB5 _GPIO(221) -#define TEGRA_PIN_PBB6 _GPIO(222) -#define TEGRA_PIN_PBB7 _GPIO(223) -#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) -#define TEGRA_PIN_PCC1 _GPIO(225) -#define TEGRA_PIN_PCC2 _GPIO(226) -#define TEGRA_PIN_SDMMC4_RST_N_PCC3 _GPIO(227) -#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) -#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) -#define TEGRA_PIN_PEX_L2_RST_N_PCC6 _GPIO(230) -#define TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7 _GPIO(231) -#define TEGRA_PIN_PEX_L0_PRSNT_N_PDD0 _GPIO(232) -#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) -#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) -#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) -#define TEGRA_PIN_PEX_L1_PRSNT_N_PDD4 _GPIO(236) -#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) -#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) -#define TEGRA_PIN_PEX_L2_PRSNT_N_PDD7 _GPIO(239) -#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) -#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) -#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) -#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) -#define TEGRA_PIN_PEE4 _GPIO(244) -#define TEGRA_PIN_PEE5 _GPIO(245) -#define TEGRA_PIN_PEE6 _GPIO(246) -#define TEGRA_PIN_PEE7 _GPIO(247) - -/* All non-GPIO pins follow */ -#define NUM_GPIOS (TEGRA_PIN_PEE7 + 1) -#define _PIN(offset) (NUM_GPIOS + (offset)) - -/* Non-GPIO pins */ -#define TEGRA_PIN_CLK_32K_IN _PIN(0) -#define TEGRA_PIN_CORE_PWR_REQ _PIN(1) -#define TEGRA_PIN_CPU_PWR_REQ _PIN(2) -#define TEGRA_PIN_JTAG_TCK _PIN(3) -#define TEGRA_PIN_JTAG_TDI _PIN(4) -#define TEGRA_PIN_JTAG_TDO _PIN(5) -#define TEGRA_PIN_JTAG_TMS _PIN(6) -#define TEGRA_PIN_JTAG_TRST_N _PIN(7) -#define TEGRA_PIN_OWR _PIN(8) -#define TEGRA_PIN_PWR_INT_N _PIN(9) -#define TEGRA_PIN_SYS_RESET_N _PIN(10) -#define TEGRA_PIN_TEST_MODE_EN _PIN(11) - -static const struct pinctrl_pin_desc tegra30_pins[] = { - PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), - PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), - PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), - PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), - PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), - PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), - PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), - PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), - PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), - PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), - PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), - PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), - PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT5_PD0, "SDMMC3_DAT5 PD0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT4_PD1, "SDMMC3_DAT4 PD1"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PD2, "LCD_DC1 PD2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT6_PD3, "SDMMC3_DAT6 PD3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT7_PD4, "SDMMC3_DAT7 PD4"), - PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), - PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), - PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), - PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), - PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), - PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), - PINCTRL_PIN(TEGRA_PIN_GMI_DQS_PI2, "GMI_DQS PI2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), - PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), - PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), - PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), - PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), - PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), - PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), - PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), - PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), - PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), - PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), - PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), - PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), - PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), - PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), - PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), - PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), - PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), - PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), - PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), - PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), - PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), - PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), - PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), - PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), - PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), - PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), - PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), - PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), - PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), - PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), - PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), - PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), - PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), - PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), - PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), - PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), - PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), - PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), - PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), - PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), - PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), - PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), - PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), - PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), - PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), - PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), - PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), - PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), - PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), - PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VI_D10 PT2"), - PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), - PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), - PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), - PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), - PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), - PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), - PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), - PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), - PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), - PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), - PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), - PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), - PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), - PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), - PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), - PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), - PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), - PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC_PV6, "CRT_HSYNC PV6"), - PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC_PV7, "CRT_VSYNC PV7"), - PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), - PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), - PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), - PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), - PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), - PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), - PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), - PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), - PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), - PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), - PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), - PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), - PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), - PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), - PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), - PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), - PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), - PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), - PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), - PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), - PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), - PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), - PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), - PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), - PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), - PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), - PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), - PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), - PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), - PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_RST_N_PCC3, "SDMMC4_RST_N PCC3"), - PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), - PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PCC6, "PEX_L2_RST_N PCC6"), - PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, "PEX_L2_CLKREQ_N PCC7"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, "PEX_L0_PRSNT_N PDD0"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), - PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), - PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, "PEX_L1_PRSNT_N PDD4"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), - PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), - PINCTRL_PIN(TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, "PEX_L2_PRSNT_N PDD7"), - PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), - PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), - PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), - PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), - PINCTRL_PIN(TEGRA_PIN_PEE4, "PEE4"), - PINCTRL_PIN(TEGRA_PIN_PEE5, "PEE5"), - PINCTRL_PIN(TEGRA_PIN_PEE6, "PEE6"), - PINCTRL_PIN(TEGRA_PIN_PEE7, "PEE7"), - PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), - PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), - PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), - PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), - PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), - PINCTRL_PIN(TEGRA_PIN_SYS_RESET_N, "SYS_RESET_N"), - PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), -}; - -static const unsigned clk_32k_out_pa0_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, -}; - -static const unsigned uart3_cts_n_pa1_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, -}; - -static const unsigned dap2_fs_pa2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, -}; - -static const unsigned dap2_sclk_pa3_pins[] = { - TEGRA_PIN_DAP2_SCLK_PA3, -}; - -static const unsigned dap2_din_pa4_pins[] = { - TEGRA_PIN_DAP2_DIN_PA4, -}; - -static const unsigned dap2_dout_pa5_pins[] = { - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned sdmmc3_clk_pa6_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, -}; - -static const unsigned sdmmc3_cmd_pa7_pins[] = { - TEGRA_PIN_SDMMC3_CMD_PA7, -}; - -static const unsigned gmi_a17_pb0_pins[] = { - TEGRA_PIN_GMI_A17_PB0, -}; - -static const unsigned gmi_a18_pb1_pins[] = { - TEGRA_PIN_GMI_A18_PB1, -}; - -static const unsigned lcd_pwr0_pb2_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, -}; - -static const unsigned lcd_pclk_pb3_pins[] = { - TEGRA_PIN_LCD_PCLK_PB3, -}; - -static const unsigned sdmmc3_dat3_pb4_pins[] = { - TEGRA_PIN_SDMMC3_DAT3_PB4, -}; - -static const unsigned sdmmc3_dat2_pb5_pins[] = { - TEGRA_PIN_SDMMC3_DAT2_PB5, -}; - -static const unsigned sdmmc3_dat1_pb6_pins[] = { - TEGRA_PIN_SDMMC3_DAT1_PB6, -}; - -static const unsigned sdmmc3_dat0_pb7_pins[] = { - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned uart3_rts_n_pc0_pins[] = { - TEGRA_PIN_UART3_RTS_N_PC0, -}; - -static const unsigned lcd_pwr1_pc1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, -}; - -static const unsigned uart2_txd_pc2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, -}; - -static const unsigned uart2_rxd_pc3_pins[] = { - TEGRA_PIN_UART2_RXD_PC3, -}; - -static const unsigned gen1_i2c_scl_pc4_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, -}; - -static const unsigned gen1_i2c_sda_pc5_pins[] = { - TEGRA_PIN_GEN1_I2C_SDA_PC5, -}; - -static const unsigned lcd_pwr2_pc6_pins[] = { - TEGRA_PIN_LCD_PWR2_PC6, -}; - -static const unsigned gmi_wp_n_pc7_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, -}; - -static const unsigned sdmmc3_dat5_pd0_pins[] = { - TEGRA_PIN_SDMMC3_DAT5_PD0, -}; - -static const unsigned sdmmc3_dat4_pd1_pins[] = { - TEGRA_PIN_SDMMC3_DAT4_PD1, -}; - -static const unsigned lcd_dc1_pd2_pins[] = { - TEGRA_PIN_LCD_DC1_PD2, -}; - -static const unsigned sdmmc3_dat6_pd3_pins[] = { - TEGRA_PIN_SDMMC3_DAT6_PD3, -}; - -static const unsigned sdmmc3_dat7_pd4_pins[] = { - TEGRA_PIN_SDMMC3_DAT7_PD4, -}; - -static const unsigned vi_d1_pd5_pins[] = { - TEGRA_PIN_VI_D1_PD5, -}; - -static const unsigned vi_vsync_pd6_pins[] = { - TEGRA_PIN_VI_VSYNC_PD6, -}; - -static const unsigned vi_hsync_pd7_pins[] = { - TEGRA_PIN_VI_HSYNC_PD7, -}; - -static const unsigned lcd_d0_pe0_pins[] = { - TEGRA_PIN_LCD_D0_PE0, -}; - -static const unsigned lcd_d1_pe1_pins[] = { - TEGRA_PIN_LCD_D1_PE1, -}; - -static const unsigned lcd_d2_pe2_pins[] = { - TEGRA_PIN_LCD_D2_PE2, -}; - -static const unsigned lcd_d3_pe3_pins[] = { - TEGRA_PIN_LCD_D3_PE3, -}; - -static const unsigned lcd_d4_pe4_pins[] = { - TEGRA_PIN_LCD_D4_PE4, -}; - -static const unsigned lcd_d5_pe5_pins[] = { - TEGRA_PIN_LCD_D5_PE5, -}; - -static const unsigned lcd_d6_pe6_pins[] = { - TEGRA_PIN_LCD_D6_PE6, -}; - -static const unsigned lcd_d7_pe7_pins[] = { - TEGRA_PIN_LCD_D7_PE7, -}; - -static const unsigned lcd_d8_pf0_pins[] = { - TEGRA_PIN_LCD_D8_PF0, -}; - -static const unsigned lcd_d9_pf1_pins[] = { - TEGRA_PIN_LCD_D9_PF1, -}; - -static const unsigned lcd_d10_pf2_pins[] = { - TEGRA_PIN_LCD_D10_PF2, -}; - -static const unsigned lcd_d11_pf3_pins[] = { - TEGRA_PIN_LCD_D11_PF3, -}; - -static const unsigned lcd_d12_pf4_pins[] = { - TEGRA_PIN_LCD_D12_PF4, -}; - -static const unsigned lcd_d13_pf5_pins[] = { - TEGRA_PIN_LCD_D13_PF5, -}; - -static const unsigned lcd_d14_pf6_pins[] = { - TEGRA_PIN_LCD_D14_PF6, -}; - -static const unsigned lcd_d15_pf7_pins[] = { - TEGRA_PIN_LCD_D15_PF7, -}; - -static const unsigned gmi_ad0_pg0_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, -}; - -static const unsigned gmi_ad1_pg1_pins[] = { - TEGRA_PIN_GMI_AD1_PG1, -}; - -static const unsigned gmi_ad2_pg2_pins[] = { - TEGRA_PIN_GMI_AD2_PG2, -}; - -static const unsigned gmi_ad3_pg3_pins[] = { - TEGRA_PIN_GMI_AD3_PG3, -}; - -static const unsigned gmi_ad4_pg4_pins[] = { - TEGRA_PIN_GMI_AD4_PG4, -}; - -static const unsigned gmi_ad5_pg5_pins[] = { - TEGRA_PIN_GMI_AD5_PG5, -}; - -static const unsigned gmi_ad6_pg6_pins[] = { - TEGRA_PIN_GMI_AD6_PG6, -}; - -static const unsigned gmi_ad7_pg7_pins[] = { - TEGRA_PIN_GMI_AD7_PG7, -}; - -static const unsigned gmi_ad8_ph0_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, -}; - -static const unsigned gmi_ad9_ph1_pins[] = { - TEGRA_PIN_GMI_AD9_PH1, -}; - -static const unsigned gmi_ad10_ph2_pins[] = { - TEGRA_PIN_GMI_AD10_PH2, -}; - -static const unsigned gmi_ad11_ph3_pins[] = { - TEGRA_PIN_GMI_AD11_PH3, -}; - -static const unsigned gmi_ad12_ph4_pins[] = { - TEGRA_PIN_GMI_AD12_PH4, -}; - -static const unsigned gmi_ad13_ph5_pins[] = { - TEGRA_PIN_GMI_AD13_PH5, -}; - -static const unsigned gmi_ad14_ph6_pins[] = { - TEGRA_PIN_GMI_AD14_PH6, -}; - -static const unsigned gmi_ad15_ph7_pins[] = { - TEGRA_PIN_GMI_AD15_PH7, -}; - -static const unsigned gmi_wr_n_pi0_pins[] = { - TEGRA_PIN_GMI_WR_N_PI0, -}; - -static const unsigned gmi_oe_n_pi1_pins[] = { - TEGRA_PIN_GMI_OE_N_PI1, -}; - -static const unsigned gmi_dqs_pi2_pins[] = { - TEGRA_PIN_GMI_DQS_PI2, -}; - -static const unsigned gmi_cs6_n_pi3_pins[] = { - TEGRA_PIN_GMI_CS6_N_PI3, -}; - -static const unsigned gmi_rst_n_pi4_pins[] = { - TEGRA_PIN_GMI_RST_N_PI4, -}; - -static const unsigned gmi_iordy_pi5_pins[] = { - TEGRA_PIN_GMI_IORDY_PI5, -}; - -static const unsigned gmi_cs7_n_pi6_pins[] = { - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned gmi_wait_pi7_pins[] = { - TEGRA_PIN_GMI_WAIT_PI7, -}; - -static const unsigned gmi_cs0_n_pj0_pins[] = { - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned lcd_de_pj1_pins[] = { - TEGRA_PIN_LCD_DE_PJ1, -}; - -static const unsigned gmi_cs1_n_pj2_pins[] = { - TEGRA_PIN_GMI_CS1_N_PJ2, -}; - -static const unsigned lcd_hsync_pj3_pins[] = { - TEGRA_PIN_LCD_HSYNC_PJ3, -}; - -static const unsigned lcd_vsync_pj4_pins[] = { - TEGRA_PIN_LCD_VSYNC_PJ4, -}; - -static const unsigned uart2_cts_n_pj5_pins[] = { - TEGRA_PIN_UART2_CTS_N_PJ5, -}; - -static const unsigned uart2_rts_n_pj6_pins[] = { - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned gmi_a16_pj7_pins[] = { - TEGRA_PIN_GMI_A16_PJ7, -}; - -static const unsigned gmi_adv_n_pk0_pins[] = { - TEGRA_PIN_GMI_ADV_N_PK0, -}; - -static const unsigned gmi_clk_pk1_pins[] = { - TEGRA_PIN_GMI_CLK_PK1, -}; - -static const unsigned gmi_cs4_n_pk2_pins[] = { - TEGRA_PIN_GMI_CS4_N_PK2, -}; - -static const unsigned gmi_cs2_n_pk3_pins[] = { - TEGRA_PIN_GMI_CS2_N_PK3, -}; - -static const unsigned gmi_cs3_n_pk4_pins[] = { - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned spdif_out_pk5_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, -}; - -static const unsigned spdif_in_pk6_pins[] = { - TEGRA_PIN_SPDIF_IN_PK6, -}; - -static const unsigned gmi_a19_pk7_pins[] = { - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned vi_d2_pl0_pins[] = { - TEGRA_PIN_VI_D2_PL0, -}; - -static const unsigned vi_d3_pl1_pins[] = { - TEGRA_PIN_VI_D3_PL1, -}; - -static const unsigned vi_d4_pl2_pins[] = { - TEGRA_PIN_VI_D4_PL2, -}; - -static const unsigned vi_d5_pl3_pins[] = { - TEGRA_PIN_VI_D5_PL3, -}; - -static const unsigned vi_d6_pl4_pins[] = { - TEGRA_PIN_VI_D6_PL4, -}; - -static const unsigned vi_d7_pl5_pins[] = { - TEGRA_PIN_VI_D7_PL5, -}; - -static const unsigned vi_d8_pl6_pins[] = { - TEGRA_PIN_VI_D8_PL6, -}; - -static const unsigned vi_d9_pl7_pins[] = { - TEGRA_PIN_VI_D9_PL7, -}; - -static const unsigned lcd_d16_pm0_pins[] = { - TEGRA_PIN_LCD_D16_PM0, -}; - -static const unsigned lcd_d17_pm1_pins[] = { - TEGRA_PIN_LCD_D17_PM1, -}; - -static const unsigned lcd_d18_pm2_pins[] = { - TEGRA_PIN_LCD_D18_PM2, -}; - -static const unsigned lcd_d19_pm3_pins[] = { - TEGRA_PIN_LCD_D19_PM3, -}; - -static const unsigned lcd_d20_pm4_pins[] = { - TEGRA_PIN_LCD_D20_PM4, -}; - -static const unsigned lcd_d21_pm5_pins[] = { - TEGRA_PIN_LCD_D21_PM5, -}; - -static const unsigned lcd_d22_pm6_pins[] = { - TEGRA_PIN_LCD_D22_PM6, -}; - -static const unsigned lcd_d23_pm7_pins[] = { - TEGRA_PIN_LCD_D23_PM7, -}; - -static const unsigned dap1_fs_pn0_pins[] = { - TEGRA_PIN_DAP1_FS_PN0, -}; - -static const unsigned dap1_din_pn1_pins[] = { - TEGRA_PIN_DAP1_DIN_PN1, -}; - -static const unsigned dap1_dout_pn2_pins[] = { - TEGRA_PIN_DAP1_DOUT_PN2, -}; - -static const unsigned dap1_sclk_pn3_pins[] = { - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned lcd_cs0_n_pn4_pins[] = { - TEGRA_PIN_LCD_CS0_N_PN4, -}; - -static const unsigned lcd_sdout_pn5_pins[] = { - TEGRA_PIN_LCD_SDOUT_PN5, -}; - -static const unsigned lcd_dc0_pn6_pins[] = { - TEGRA_PIN_LCD_DC0_PN6, -}; - -static const unsigned hdmi_int_pn7_pins[] = { - TEGRA_PIN_HDMI_INT_PN7, -}; - -static const unsigned ulpi_data7_po0_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, -}; - -static const unsigned ulpi_data0_po1_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, -}; - -static const unsigned ulpi_data1_po2_pins[] = { - TEGRA_PIN_ULPI_DATA1_PO2, -}; - -static const unsigned ulpi_data2_po3_pins[] = { - TEGRA_PIN_ULPI_DATA2_PO3, -}; - -static const unsigned ulpi_data3_po4_pins[] = { - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned ulpi_data4_po5_pins[] = { - TEGRA_PIN_ULPI_DATA4_PO5, -}; - -static const unsigned ulpi_data5_po6_pins[] = { - TEGRA_PIN_ULPI_DATA5_PO6, -}; - -static const unsigned ulpi_data6_po7_pins[] = { - TEGRA_PIN_ULPI_DATA6_PO7, -}; - -static const unsigned dap3_fs_pp0_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, -}; - -static const unsigned dap3_din_pp1_pins[] = { - TEGRA_PIN_DAP3_DIN_PP1, -}; - -static const unsigned dap3_dout_pp2_pins[] = { - TEGRA_PIN_DAP3_DOUT_PP2, -}; - -static const unsigned dap3_sclk_pp3_pins[] = { - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned dap4_fs_pp4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, -}; - -static const unsigned dap4_din_pp5_pins[] = { - TEGRA_PIN_DAP4_DIN_PP5, -}; - -static const unsigned dap4_dout_pp6_pins[] = { - TEGRA_PIN_DAP4_DOUT_PP6, -}; - -static const unsigned dap4_sclk_pp7_pins[] = { - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned kb_col0_pq0_pins[] = { - TEGRA_PIN_KB_COL0_PQ0, -}; - -static const unsigned kb_col1_pq1_pins[] = { - TEGRA_PIN_KB_COL1_PQ1, -}; - -static const unsigned kb_col2_pq2_pins[] = { - TEGRA_PIN_KB_COL2_PQ2, -}; - -static const unsigned kb_col3_pq3_pins[] = { - TEGRA_PIN_KB_COL3_PQ3, -}; - -static const unsigned kb_col4_pq4_pins[] = { - TEGRA_PIN_KB_COL4_PQ4, -}; - -static const unsigned kb_col5_pq5_pins[] = { - TEGRA_PIN_KB_COL5_PQ5, -}; - -static const unsigned kb_col6_pq6_pins[] = { - TEGRA_PIN_KB_COL6_PQ6, -}; - -static const unsigned kb_col7_pq7_pins[] = { - TEGRA_PIN_KB_COL7_PQ7, -}; - -static const unsigned kb_row0_pr0_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, -}; - -static const unsigned kb_row1_pr1_pins[] = { - TEGRA_PIN_KB_ROW1_PR1, -}; - -static const unsigned kb_row2_pr2_pins[] = { - TEGRA_PIN_KB_ROW2_PR2, -}; - -static const unsigned kb_row3_pr3_pins[] = { - TEGRA_PIN_KB_ROW3_PR3, -}; - -static const unsigned kb_row4_pr4_pins[] = { - TEGRA_PIN_KB_ROW4_PR4, -}; - -static const unsigned kb_row5_pr5_pins[] = { - TEGRA_PIN_KB_ROW5_PR5, -}; - -static const unsigned kb_row6_pr6_pins[] = { - TEGRA_PIN_KB_ROW6_PR6, -}; - -static const unsigned kb_row7_pr7_pins[] = { - TEGRA_PIN_KB_ROW7_PR7, -}; - -static const unsigned kb_row8_ps0_pins[] = { - TEGRA_PIN_KB_ROW8_PS0, -}; - -static const unsigned kb_row9_ps1_pins[] = { - TEGRA_PIN_KB_ROW9_PS1, -}; - -static const unsigned kb_row10_ps2_pins[] = { - TEGRA_PIN_KB_ROW10_PS2, -}; - -static const unsigned kb_row11_ps3_pins[] = { - TEGRA_PIN_KB_ROW11_PS3, -}; - -static const unsigned kb_row12_ps4_pins[] = { - TEGRA_PIN_KB_ROW12_PS4, -}; - -static const unsigned kb_row13_ps5_pins[] = { - TEGRA_PIN_KB_ROW13_PS5, -}; - -static const unsigned kb_row14_ps6_pins[] = { - TEGRA_PIN_KB_ROW14_PS6, -}; - -static const unsigned kb_row15_ps7_pins[] = { - TEGRA_PIN_KB_ROW15_PS7, -}; - -static const unsigned vi_pclk_pt0_pins[] = { - TEGRA_PIN_VI_PCLK_PT0, -}; - -static const unsigned vi_mclk_pt1_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned vi_d10_pt2_pins[] = { - TEGRA_PIN_VI_D10_PT2, -}; - -static const unsigned vi_d11_pt3_pins[] = { - TEGRA_PIN_VI_D11_PT3, -}; - -static const unsigned vi_d0_pt4_pins[] = { - TEGRA_PIN_VI_D0_PT4, -}; - -static const unsigned gen2_i2c_scl_pt5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, -}; - -static const unsigned gen2_i2c_sda_pt6_pins[] = { - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned sdmmc4_cmd_pt7_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned pu0_pins[] = { - TEGRA_PIN_PU0, -}; - -static const unsigned pu1_pins[] = { - TEGRA_PIN_PU1, -}; - -static const unsigned pu2_pins[] = { - TEGRA_PIN_PU2, -}; - -static const unsigned pu3_pins[] = { - TEGRA_PIN_PU3, -}; - -static const unsigned pu4_pins[] = { - TEGRA_PIN_PU4, -}; - -static const unsigned pu5_pins[] = { - TEGRA_PIN_PU5, -}; - -static const unsigned pu6_pins[] = { - TEGRA_PIN_PU6, -}; - -static const unsigned jtag_rtck_pu7_pins[] = { - TEGRA_PIN_JTAG_RTCK_PU7, -}; - -static const unsigned pv0_pins[] = { - TEGRA_PIN_PV0, -}; - -static const unsigned pv1_pins[] = { - TEGRA_PIN_PV1, -}; - -static const unsigned pv2_pins[] = { - TEGRA_PIN_PV2, -}; - -static const unsigned pv3_pins[] = { - TEGRA_PIN_PV3, -}; - -static const unsigned ddc_scl_pv4_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, -}; - -static const unsigned ddc_sda_pv5_pins[] = { - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned crt_hsync_pv6_pins[] = { - TEGRA_PIN_CRT_HSYNC_PV6, -}; - -static const unsigned crt_vsync_pv7_pins[] = { - TEGRA_PIN_CRT_VSYNC_PV7, -}; - -static const unsigned lcd_cs1_n_pw0_pins[] = { - TEGRA_PIN_LCD_CS1_N_PW0, -}; - -static const unsigned lcd_m1_pw1_pins[] = { - TEGRA_PIN_LCD_M1_PW1, -}; - -static const unsigned spi2_cs1_n_pw2_pins[] = { - TEGRA_PIN_SPI2_CS1_N_PW2, -}; - -static const unsigned spi2_cs2_n_pw3_pins[] = { - TEGRA_PIN_SPI2_CS2_N_PW3, -}; - -static const unsigned clk1_out_pw4_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, -}; - -static const unsigned clk2_out_pw5_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, -}; - -static const unsigned uart3_txd_pw6_pins[] = { - TEGRA_PIN_UART3_TXD_PW6, -}; - -static const unsigned uart3_rxd_pw7_pins[] = { - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned spi2_mosi_px0_pins[] = { - TEGRA_PIN_SPI2_MOSI_PX0, -}; - -static const unsigned spi2_miso_px1_pins[] = { - TEGRA_PIN_SPI2_MISO_PX1, -}; - -static const unsigned spi2_sck_px2_pins[] = { - TEGRA_PIN_SPI2_SCK_PX2, -}; - -static const unsigned spi2_cs0_n_px3_pins[] = { - TEGRA_PIN_SPI2_CS0_N_PX3, -}; - -static const unsigned spi1_mosi_px4_pins[] = { - TEGRA_PIN_SPI1_MOSI_PX4, -}; - -static const unsigned spi1_sck_px5_pins[] = { - TEGRA_PIN_SPI1_SCK_PX5, -}; - -static const unsigned spi1_cs0_n_px6_pins[] = { - TEGRA_PIN_SPI1_CS0_N_PX6, -}; - -static const unsigned spi1_miso_px7_pins[] = { - TEGRA_PIN_SPI1_MISO_PX7, -}; - -static const unsigned ulpi_clk_py0_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, -}; - -static const unsigned ulpi_dir_py1_pins[] = { - TEGRA_PIN_ULPI_DIR_PY1, -}; - -static const unsigned ulpi_nxt_py2_pins[] = { - TEGRA_PIN_ULPI_NXT_PY2, -}; - -static const unsigned ulpi_stp_py3_pins[] = { - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned sdmmc1_dat3_py4_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, -}; - -static const unsigned sdmmc1_dat2_py5_pins[] = { - TEGRA_PIN_SDMMC1_DAT2_PY5, -}; - -static const unsigned sdmmc1_dat1_py6_pins[] = { - TEGRA_PIN_SDMMC1_DAT1_PY6, -}; - -static const unsigned sdmmc1_dat0_py7_pins[] = { - TEGRA_PIN_SDMMC1_DAT0_PY7, -}; - -static const unsigned sdmmc1_clk_pz0_pins[] = { - TEGRA_PIN_SDMMC1_CLK_PZ0, -}; - -static const unsigned sdmmc1_cmd_pz1_pins[] = { - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned lcd_sdin_pz2_pins[] = { - TEGRA_PIN_LCD_SDIN_PZ2, -}; - -static const unsigned lcd_wr_n_pz3_pins[] = { - TEGRA_PIN_LCD_WR_N_PZ3, -}; - -static const unsigned lcd_sck_pz4_pins[] = { - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned sys_clk_req_pz5_pins[] = { - TEGRA_PIN_SYS_CLK_REQ_PZ5, -}; - -static const unsigned pwr_i2c_scl_pz6_pins[] = { - TEGRA_PIN_PWR_I2C_SCL_PZ6, -}; - -static const unsigned pwr_i2c_sda_pz7_pins[] = { - TEGRA_PIN_PWR_I2C_SDA_PZ7, -}; - -static const unsigned sdmmc4_dat0_paa0_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, -}; - -static const unsigned sdmmc4_dat1_paa1_pins[] = { - TEGRA_PIN_SDMMC4_DAT1_PAA1, -}; - -static const unsigned sdmmc4_dat2_paa2_pins[] = { - TEGRA_PIN_SDMMC4_DAT2_PAA2, -}; - -static const unsigned sdmmc4_dat3_paa3_pins[] = { - TEGRA_PIN_SDMMC4_DAT3_PAA3, -}; - -static const unsigned sdmmc4_dat4_paa4_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, -}; - -static const unsigned sdmmc4_dat5_paa5_pins[] = { - TEGRA_PIN_SDMMC4_DAT5_PAA5, -}; - -static const unsigned sdmmc4_dat6_paa6_pins[] = { - TEGRA_PIN_SDMMC4_DAT6_PAA6, -}; - -static const unsigned sdmmc4_dat7_paa7_pins[] = { - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned pbb0_pins[] = { - TEGRA_PIN_PBB0, -}; - -static const unsigned cam_i2c_scl_pbb1_pins[] = { - TEGRA_PIN_CAM_I2C_SCL_PBB1, -}; - -static const unsigned cam_i2c_sda_pbb2_pins[] = { - TEGRA_PIN_CAM_I2C_SDA_PBB2, -}; - -static const unsigned pbb3_pins[] = { - TEGRA_PIN_PBB3, -}; - -static const unsigned pbb4_pins[] = { - TEGRA_PIN_PBB4, -}; - -static const unsigned pbb5_pins[] = { - TEGRA_PIN_PBB5, -}; - -static const unsigned pbb6_pins[] = { - TEGRA_PIN_PBB6, -}; - -static const unsigned pbb7_pins[] = { - TEGRA_PIN_PBB7, -}; - -static const unsigned cam_mclk_pcc0_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned pcc1_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned pcc2_pins[] = { - TEGRA_PIN_PCC2, -}; - -static const unsigned sdmmc4_rst_n_pcc3_pins[] = { - TEGRA_PIN_SDMMC4_RST_N_PCC3, -}; - -static const unsigned sdmmc4_clk_pcc4_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned clk2_req_pcc5_pins[] = { - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned pex_l2_rst_n_pcc6_pins[] = { - TEGRA_PIN_PEX_L2_RST_N_PCC6, -}; - -static const unsigned pex_l2_clkreq_n_pcc7_pins[] = { - TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, -}; - -static const unsigned pex_l0_prsnt_n_pdd0_pins[] = { - TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, -}; - -static const unsigned pex_l0_rst_n_pdd1_pins[] = { - TEGRA_PIN_PEX_L0_RST_N_PDD1, -}; - -static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, -}; - -static const unsigned pex_wake_n_pdd3_pins[] = { - TEGRA_PIN_PEX_WAKE_N_PDD3, -}; - -static const unsigned pex_l1_prsnt_n_pdd4_pins[] = { - TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, -}; - -static const unsigned pex_l1_rst_n_pdd5_pins[] = { - TEGRA_PIN_PEX_L1_RST_N_PDD5, -}; - -static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, -}; - -static const unsigned pex_l2_prsnt_n_pdd7_pins[] = { - TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, -}; - -static const unsigned clk3_out_pee0_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, -}; - -static const unsigned clk3_req_pee1_pins[] = { - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned clk1_req_pee2_pins[] = { - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned hdmi_cec_pee3_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned clk_32k_in_pins[] = { - TEGRA_PIN_CLK_32K_IN, -}; - -static const unsigned core_pwr_req_pins[] = { - TEGRA_PIN_CORE_PWR_REQ, -}; - -static const unsigned cpu_pwr_req_pins[] = { - TEGRA_PIN_CPU_PWR_REQ, -}; - -static const unsigned owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned pwr_int_n_pins[] = { - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned drive_ao1_pins[] = { - TEGRA_PIN_KB_ROW0_PR0, - TEGRA_PIN_KB_ROW1_PR1, - TEGRA_PIN_KB_ROW2_PR2, - TEGRA_PIN_KB_ROW3_PR3, - TEGRA_PIN_KB_ROW4_PR4, - TEGRA_PIN_KB_ROW5_PR5, - TEGRA_PIN_KB_ROW6_PR6, - TEGRA_PIN_KB_ROW7_PR7, - TEGRA_PIN_PWR_I2C_SCL_PZ6, - TEGRA_PIN_PWR_I2C_SDA_PZ7, - TEGRA_PIN_SYS_RESET_N, -}; - -static const unsigned drive_ao2_pins[] = { - TEGRA_PIN_CLK_32K_OUT_PA0, - TEGRA_PIN_KB_COL0_PQ0, - TEGRA_PIN_KB_COL1_PQ1, - TEGRA_PIN_KB_COL2_PQ2, - TEGRA_PIN_KB_COL3_PQ3, - TEGRA_PIN_KB_COL4_PQ4, - TEGRA_PIN_KB_COL5_PQ5, - TEGRA_PIN_KB_COL6_PQ6, - TEGRA_PIN_KB_COL7_PQ7, - TEGRA_PIN_KB_ROW8_PS0, - TEGRA_PIN_KB_ROW9_PS1, - TEGRA_PIN_KB_ROW10_PS2, - TEGRA_PIN_KB_ROW11_PS3, - TEGRA_PIN_KB_ROW12_PS4, - TEGRA_PIN_KB_ROW13_PS5, - TEGRA_PIN_KB_ROW14_PS6, - TEGRA_PIN_KB_ROW15_PS7, - TEGRA_PIN_SYS_CLK_REQ_PZ5, - TEGRA_PIN_CLK_32K_IN, - TEGRA_PIN_CORE_PWR_REQ, - TEGRA_PIN_CPU_PWR_REQ, - TEGRA_PIN_PWR_INT_N, -}; - -static const unsigned drive_at1_pins[] = { - TEGRA_PIN_GMI_AD8_PH0, - TEGRA_PIN_GMI_AD9_PH1, - TEGRA_PIN_GMI_AD10_PH2, - TEGRA_PIN_GMI_AD11_PH3, - TEGRA_PIN_GMI_AD12_PH4, - TEGRA_PIN_GMI_AD13_PH5, - TEGRA_PIN_GMI_AD14_PH6, - TEGRA_PIN_GMI_AD15_PH7, - TEGRA_PIN_GMI_IORDY_PI5, - TEGRA_PIN_GMI_CS7_N_PI6, -}; - -static const unsigned drive_at2_pins[] = { - TEGRA_PIN_GMI_AD0_PG0, - TEGRA_PIN_GMI_AD1_PG1, - TEGRA_PIN_GMI_AD2_PG2, - TEGRA_PIN_GMI_AD3_PG3, - TEGRA_PIN_GMI_AD4_PG4, - TEGRA_PIN_GMI_AD5_PG5, - TEGRA_PIN_GMI_AD6_PG6, - TEGRA_PIN_GMI_AD7_PG7, - TEGRA_PIN_GMI_WR_N_PI0, - TEGRA_PIN_GMI_OE_N_PI1, - TEGRA_PIN_GMI_DQS_PI2, - TEGRA_PIN_GMI_CS6_N_PI3, - TEGRA_PIN_GMI_RST_N_PI4, - TEGRA_PIN_GMI_WAIT_PI7, - TEGRA_PIN_GMI_ADV_N_PK0, - TEGRA_PIN_GMI_CLK_PK1, - TEGRA_PIN_GMI_CS4_N_PK2, - TEGRA_PIN_GMI_CS2_N_PK3, - TEGRA_PIN_GMI_CS3_N_PK4, -}; - -static const unsigned drive_at3_pins[] = { - TEGRA_PIN_GMI_WP_N_PC7, - TEGRA_PIN_GMI_CS0_N_PJ0, -}; - -static const unsigned drive_at4_pins[] = { - TEGRA_PIN_GMI_A17_PB0, - TEGRA_PIN_GMI_A18_PB1, - TEGRA_PIN_GMI_CS1_N_PJ2, - TEGRA_PIN_GMI_A16_PJ7, - TEGRA_PIN_GMI_A19_PK7, -}; - -static const unsigned drive_at5_pins[] = { - TEGRA_PIN_GEN2_I2C_SCL_PT5, - TEGRA_PIN_GEN2_I2C_SDA_PT6, -}; - -static const unsigned drive_cdev1_pins[] = { - TEGRA_PIN_CLK1_OUT_PW4, - TEGRA_PIN_CLK1_REQ_PEE2, -}; - -static const unsigned drive_cdev2_pins[] = { - TEGRA_PIN_CLK2_OUT_PW5, - TEGRA_PIN_CLK2_REQ_PCC5, -}; - -static const unsigned drive_cec_pins[] = { - TEGRA_PIN_HDMI_CEC_PEE3, -}; - -static const unsigned drive_crt_pins[] = { - TEGRA_PIN_CRT_HSYNC_PV6, - TEGRA_PIN_CRT_VSYNC_PV7, -}; - -static const unsigned drive_csus_pins[] = { - TEGRA_PIN_VI_MCLK_PT1, -}; - -static const unsigned drive_dap1_pins[] = { - TEGRA_PIN_SPDIF_OUT_PK5, - TEGRA_PIN_SPDIF_IN_PK6, - TEGRA_PIN_DAP1_FS_PN0, - TEGRA_PIN_DAP1_DIN_PN1, - TEGRA_PIN_DAP1_DOUT_PN2, - TEGRA_PIN_DAP1_SCLK_PN3, -}; - -static const unsigned drive_dap2_pins[] = { - TEGRA_PIN_DAP2_FS_PA2, - TEGRA_PIN_DAP2_SCLK_PA3, - TEGRA_PIN_DAP2_DIN_PA4, - TEGRA_PIN_DAP2_DOUT_PA5, -}; - -static const unsigned drive_dap3_pins[] = { - TEGRA_PIN_DAP3_FS_PP0, - TEGRA_PIN_DAP3_DIN_PP1, - TEGRA_PIN_DAP3_DOUT_PP2, - TEGRA_PIN_DAP3_SCLK_PP3, -}; - -static const unsigned drive_dap4_pins[] = { - TEGRA_PIN_DAP4_FS_PP4, - TEGRA_PIN_DAP4_DIN_PP5, - TEGRA_PIN_DAP4_DOUT_PP6, - TEGRA_PIN_DAP4_SCLK_PP7, -}; - -static const unsigned drive_dbg_pins[] = { - TEGRA_PIN_GEN1_I2C_SCL_PC4, - TEGRA_PIN_GEN1_I2C_SDA_PC5, - TEGRA_PIN_PU0, - TEGRA_PIN_PU1, - TEGRA_PIN_PU2, - TEGRA_PIN_PU3, - TEGRA_PIN_PU4, - TEGRA_PIN_PU5, - TEGRA_PIN_PU6, - TEGRA_PIN_JTAG_RTCK_PU7, - TEGRA_PIN_JTAG_TCK, - TEGRA_PIN_JTAG_TDI, - TEGRA_PIN_JTAG_TDO, - TEGRA_PIN_JTAG_TMS, - TEGRA_PIN_JTAG_TRST_N, - TEGRA_PIN_TEST_MODE_EN, -}; - -static const unsigned drive_ddc_pins[] = { - TEGRA_PIN_DDC_SCL_PV4, - TEGRA_PIN_DDC_SDA_PV5, -}; - -static const unsigned drive_dev3_pins[] = { - TEGRA_PIN_CLK3_OUT_PEE0, - TEGRA_PIN_CLK3_REQ_PEE1, -}; - -static const unsigned drive_gma_pins[] = { - TEGRA_PIN_SDMMC4_DAT0_PAA0, - TEGRA_PIN_SDMMC4_DAT1_PAA1, - TEGRA_PIN_SDMMC4_DAT2_PAA2, - TEGRA_PIN_SDMMC4_DAT3_PAA3, - TEGRA_PIN_SDMMC4_RST_N_PCC3, -}; - -static const unsigned drive_gmb_pins[] = { - TEGRA_PIN_SDMMC4_DAT4_PAA4, - TEGRA_PIN_SDMMC4_DAT5_PAA5, - TEGRA_PIN_SDMMC4_DAT6_PAA6, - TEGRA_PIN_SDMMC4_DAT7_PAA7, -}; - -static const unsigned drive_gmc_pins[] = { - TEGRA_PIN_SDMMC4_CLK_PCC4, -}; - -static const unsigned drive_gmd_pins[] = { - TEGRA_PIN_SDMMC4_CMD_PT7, -}; - -static const unsigned drive_gme_pins[] = { - TEGRA_PIN_PBB0, - TEGRA_PIN_CAM_I2C_SCL_PBB1, - TEGRA_PIN_CAM_I2C_SDA_PBB2, - TEGRA_PIN_PBB3, - TEGRA_PIN_PCC2, -}; - -static const unsigned drive_gmf_pins[] = { - TEGRA_PIN_PBB4, - TEGRA_PIN_PBB5, - TEGRA_PIN_PBB6, - TEGRA_PIN_PBB7, -}; - -static const unsigned drive_gmg_pins[] = { - TEGRA_PIN_CAM_MCLK_PCC0, -}; - -static const unsigned drive_gmh_pins[] = { - TEGRA_PIN_PCC1, -}; - -static const unsigned drive_gpv_pins[] = { - TEGRA_PIN_PEX_L2_RST_N_PCC6, - TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, - TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, - TEGRA_PIN_PEX_L0_RST_N_PDD1, - TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, - TEGRA_PIN_PEX_WAKE_N_PDD3, - TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, - TEGRA_PIN_PEX_L1_RST_N_PDD5, - TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, - TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, -}; - -static const unsigned drive_lcd1_pins[] = { - TEGRA_PIN_LCD_PWR1_PC1, - TEGRA_PIN_LCD_PWR2_PC6, - TEGRA_PIN_LCD_CS0_N_PN4, - TEGRA_PIN_LCD_SDOUT_PN5, - TEGRA_PIN_LCD_DC0_PN6, - TEGRA_PIN_LCD_SDIN_PZ2, - TEGRA_PIN_LCD_WR_N_PZ3, - TEGRA_PIN_LCD_SCK_PZ4, -}; - -static const unsigned drive_lcd2_pins[] = { - TEGRA_PIN_LCD_PWR0_PB2, - TEGRA_PIN_LCD_PCLK_PB3, - TEGRA_PIN_LCD_DC1_PD2, - TEGRA_PIN_LCD_D0_PE0, - TEGRA_PIN_LCD_D1_PE1, - TEGRA_PIN_LCD_D2_PE2, - TEGRA_PIN_LCD_D3_PE3, - TEGRA_PIN_LCD_D4_PE4, - TEGRA_PIN_LCD_D5_PE5, - TEGRA_PIN_LCD_D6_PE6, - TEGRA_PIN_LCD_D7_PE7, - TEGRA_PIN_LCD_D8_PF0, - TEGRA_PIN_LCD_D9_PF1, - TEGRA_PIN_LCD_D10_PF2, - TEGRA_PIN_LCD_D11_PF3, - TEGRA_PIN_LCD_D12_PF4, - TEGRA_PIN_LCD_D13_PF5, - TEGRA_PIN_LCD_D14_PF6, - TEGRA_PIN_LCD_D15_PF7, - TEGRA_PIN_LCD_DE_PJ1, - TEGRA_PIN_LCD_HSYNC_PJ3, - TEGRA_PIN_LCD_VSYNC_PJ4, - TEGRA_PIN_LCD_D16_PM0, - TEGRA_PIN_LCD_D17_PM1, - TEGRA_PIN_LCD_D18_PM2, - TEGRA_PIN_LCD_D19_PM3, - TEGRA_PIN_LCD_D20_PM4, - TEGRA_PIN_LCD_D21_PM5, - TEGRA_PIN_LCD_D22_PM6, - TEGRA_PIN_LCD_D23_PM7, - TEGRA_PIN_HDMI_INT_PN7, - TEGRA_PIN_LCD_CS1_N_PW0, - TEGRA_PIN_LCD_M1_PW1, -}; - -static const unsigned drive_owr_pins[] = { - TEGRA_PIN_OWR, -}; - -static const unsigned drive_sdio1_pins[] = { - TEGRA_PIN_SDMMC1_DAT3_PY4, - TEGRA_PIN_SDMMC1_DAT2_PY5, - TEGRA_PIN_SDMMC1_DAT1_PY6, - TEGRA_PIN_SDMMC1_DAT0_PY7, - TEGRA_PIN_SDMMC1_CLK_PZ0, - TEGRA_PIN_SDMMC1_CMD_PZ1, -}; - -static const unsigned drive_sdio2_pins[] = { - TEGRA_PIN_SDMMC3_DAT5_PD0, - TEGRA_PIN_SDMMC3_DAT4_PD1, - TEGRA_PIN_SDMMC3_DAT6_PD3, - TEGRA_PIN_SDMMC3_DAT7_PD4, -}; - -static const unsigned drive_sdio3_pins[] = { - TEGRA_PIN_SDMMC3_CLK_PA6, - TEGRA_PIN_SDMMC3_CMD_PA7, - TEGRA_PIN_SDMMC3_DAT3_PB4, - TEGRA_PIN_SDMMC3_DAT2_PB5, - TEGRA_PIN_SDMMC3_DAT1_PB6, - TEGRA_PIN_SDMMC3_DAT0_PB7, -}; - -static const unsigned drive_spi_pins[] = { - TEGRA_PIN_SPI2_CS1_N_PW2, - TEGRA_PIN_SPI2_CS2_N_PW3, - TEGRA_PIN_SPI2_MOSI_PX0, - TEGRA_PIN_SPI2_MISO_PX1, - TEGRA_PIN_SPI2_SCK_PX2, - TEGRA_PIN_SPI2_CS0_N_PX3, - TEGRA_PIN_SPI1_MOSI_PX4, - TEGRA_PIN_SPI1_SCK_PX5, - TEGRA_PIN_SPI1_CS0_N_PX6, - TEGRA_PIN_SPI1_MISO_PX7, -}; - -static const unsigned drive_uaa_pins[] = { - TEGRA_PIN_ULPI_DATA0_PO1, - TEGRA_PIN_ULPI_DATA1_PO2, - TEGRA_PIN_ULPI_DATA2_PO3, - TEGRA_PIN_ULPI_DATA3_PO4, -}; - -static const unsigned drive_uab_pins[] = { - TEGRA_PIN_ULPI_DATA7_PO0, - TEGRA_PIN_ULPI_DATA4_PO5, - TEGRA_PIN_ULPI_DATA5_PO6, - TEGRA_PIN_ULPI_DATA6_PO7, - TEGRA_PIN_PV0, - TEGRA_PIN_PV1, - TEGRA_PIN_PV2, - TEGRA_PIN_PV3, -}; - -static const unsigned drive_uart2_pins[] = { - TEGRA_PIN_UART2_TXD_PC2, - TEGRA_PIN_UART2_RXD_PC3, - TEGRA_PIN_UART2_CTS_N_PJ5, - TEGRA_PIN_UART2_RTS_N_PJ6, -}; - -static const unsigned drive_uart3_pins[] = { - TEGRA_PIN_UART3_CTS_N_PA1, - TEGRA_PIN_UART3_RTS_N_PC0, - TEGRA_PIN_UART3_TXD_PW6, - TEGRA_PIN_UART3_RXD_PW7, -}; - -static const unsigned drive_uda_pins[] = { - TEGRA_PIN_ULPI_CLK_PY0, - TEGRA_PIN_ULPI_DIR_PY1, - TEGRA_PIN_ULPI_NXT_PY2, - TEGRA_PIN_ULPI_STP_PY3, -}; - -static const unsigned drive_vi1_pins[] = { - TEGRA_PIN_VI_D1_PD5, - TEGRA_PIN_VI_VSYNC_PD6, - TEGRA_PIN_VI_HSYNC_PD7, - TEGRA_PIN_VI_D2_PL0, - TEGRA_PIN_VI_D3_PL1, - TEGRA_PIN_VI_D4_PL2, - TEGRA_PIN_VI_D5_PL3, - TEGRA_PIN_VI_D6_PL4, - TEGRA_PIN_VI_D7_PL5, - TEGRA_PIN_VI_D8_PL6, - TEGRA_PIN_VI_D9_PL7, - TEGRA_PIN_VI_PCLK_PT0, - TEGRA_PIN_VI_D10_PT2, - TEGRA_PIN_VI_D11_PT3, - TEGRA_PIN_VI_D0_PT4, -}; - -enum tegra_mux { - TEGRA_MUX_BLINK, - TEGRA_MUX_CEC, - TEGRA_MUX_CLK_12M_OUT, - TEGRA_MUX_CLK_32K_IN, - TEGRA_MUX_CORE_PWR_REQ, - TEGRA_MUX_CPU_PWR_REQ, - TEGRA_MUX_CRT, - TEGRA_MUX_DAP, - TEGRA_MUX_DDR, - TEGRA_MUX_DEV3, - TEGRA_MUX_DISPLAYA, - TEGRA_MUX_DISPLAYB, - TEGRA_MUX_DTV, - TEGRA_MUX_EXTPERIPH1, - TEGRA_MUX_EXTPERIPH2, - TEGRA_MUX_EXTPERIPH3, - TEGRA_MUX_GMI, - TEGRA_MUX_GMI_ALT, - TEGRA_MUX_HDA, - TEGRA_MUX_HDCP, - TEGRA_MUX_HDMI, - TEGRA_MUX_HSI, - TEGRA_MUX_I2C1, - TEGRA_MUX_I2C2, - TEGRA_MUX_I2C3, - TEGRA_MUX_I2C4, - TEGRA_MUX_I2CPWR, - TEGRA_MUX_I2S0, - TEGRA_MUX_I2S1, - TEGRA_MUX_I2S2, - TEGRA_MUX_I2S3, - TEGRA_MUX_I2S4, - TEGRA_MUX_INVALID, - TEGRA_MUX_KBC, - TEGRA_MUX_MIO, - TEGRA_MUX_NAND, - TEGRA_MUX_NAND_ALT, - TEGRA_MUX_OWR, - TEGRA_MUX_PCIE, - TEGRA_MUX_PWM0, - TEGRA_MUX_PWM1, - TEGRA_MUX_PWM2, - TEGRA_MUX_PWM3, - TEGRA_MUX_PWR_INT_N, - TEGRA_MUX_RSVD1, - TEGRA_MUX_RSVD2, - TEGRA_MUX_RSVD3, - TEGRA_MUX_RSVD4, - TEGRA_MUX_RTCK, - TEGRA_MUX_SATA, - TEGRA_MUX_SDMMC1, - TEGRA_MUX_SDMMC2, - TEGRA_MUX_SDMMC3, - TEGRA_MUX_SDMMC4, - TEGRA_MUX_SPDIF, - TEGRA_MUX_SPI1, - TEGRA_MUX_SPI2, - TEGRA_MUX_SPI2_ALT, - TEGRA_MUX_SPI3, - TEGRA_MUX_SPI4, - TEGRA_MUX_SPI5, - TEGRA_MUX_SPI6, - TEGRA_MUX_SYSCLK, - TEGRA_MUX_TEST, - TEGRA_MUX_TRACE, - TEGRA_MUX_UARTA, - TEGRA_MUX_UARTB, - TEGRA_MUX_UARTC, - TEGRA_MUX_UARTD, - TEGRA_MUX_UARTE, - TEGRA_MUX_ULPI, - TEGRA_MUX_VGP1, - TEGRA_MUX_VGP2, - TEGRA_MUX_VGP3, - TEGRA_MUX_VGP4, - TEGRA_MUX_VGP5, - TEGRA_MUX_VGP6, - TEGRA_MUX_VI, - TEGRA_MUX_VI_ALT1, - TEGRA_MUX_VI_ALT2, - TEGRA_MUX_VI_ALT3, -}; - -#define FUNCTION(fname) \ - { \ - .name = #fname, \ - } - -static struct tegra_function tegra30_functions[] = { - FUNCTION(blink), - FUNCTION(cec), - FUNCTION(clk_12m_out), - FUNCTION(clk_32k_in), - FUNCTION(core_pwr_req), - FUNCTION(cpu_pwr_req), - FUNCTION(crt), - FUNCTION(dap), - FUNCTION(ddr), - FUNCTION(dev3), - FUNCTION(displaya), - FUNCTION(displayb), - FUNCTION(dtv), - FUNCTION(extperiph1), - FUNCTION(extperiph2), - FUNCTION(extperiph3), - FUNCTION(gmi), - FUNCTION(gmi_alt), - FUNCTION(hda), - FUNCTION(hdcp), - FUNCTION(hdmi), - FUNCTION(hsi), - FUNCTION(i2c1), - FUNCTION(i2c2), - FUNCTION(i2c3), - FUNCTION(i2c4), - FUNCTION(i2cpwr), - FUNCTION(i2s0), - FUNCTION(i2s1), - FUNCTION(i2s2), - FUNCTION(i2s3), - FUNCTION(i2s4), - FUNCTION(invalid), - FUNCTION(kbc), - FUNCTION(mio), - FUNCTION(nand), - FUNCTION(nand_alt), - FUNCTION(owr), - FUNCTION(pcie), - FUNCTION(pwm0), - FUNCTION(pwm1), - FUNCTION(pwm2), - FUNCTION(pwm3), - FUNCTION(pwr_int_n), - FUNCTION(rsvd1), - FUNCTION(rsvd2), - FUNCTION(rsvd3), - FUNCTION(rsvd4), - FUNCTION(rtck), - FUNCTION(sata), - FUNCTION(sdmmc1), - FUNCTION(sdmmc2), - FUNCTION(sdmmc3), - FUNCTION(sdmmc4), - FUNCTION(spdif), - FUNCTION(spi1), - FUNCTION(spi2), - FUNCTION(spi2_alt), - FUNCTION(spi3), - FUNCTION(spi4), - FUNCTION(spi5), - FUNCTION(spi6), - FUNCTION(sysclk), - FUNCTION(test), - FUNCTION(trace), - FUNCTION(uarta), - FUNCTION(uartb), - FUNCTION(uartc), - FUNCTION(uartd), - FUNCTION(uarte), - FUNCTION(ulpi), - FUNCTION(vgp1), - FUNCTION(vgp2), - FUNCTION(vgp3), - FUNCTION(vgp4), - FUNCTION(vgp5), - FUNCTION(vgp6), - FUNCTION(vi), - FUNCTION(vi_alt1), - FUNCTION(vi_alt2), - FUNCTION(vi_alt3), -}; - -#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ -#define PINGROUP_REG_A 0x3000 /* bank 1 */ - -#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) -#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) - -#define PINGROUP_BIT_Y(b) (b) -#define PINGROUP_BIT_N(b) (-1) - -#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior) \ - { \ - .name = #pg_name, \ - .pins = pg_name##_pins, \ - .npins = ARRAY_SIZE(pg_name##_pins), \ - .funcs = { \ - TEGRA_MUX_##f0, \ - TEGRA_MUX_##f1, \ - TEGRA_MUX_##f2, \ - TEGRA_MUX_##f3, \ - }, \ - .mux_reg = PINGROUP_REG(r), \ - .mux_bank = 1, \ - .mux_bit = 0, \ - .pupd_reg = PINGROUP_REG(r), \ - .pupd_bank = 1, \ - .pupd_bit = 2, \ - .tri_reg = PINGROUP_REG(r), \ - .tri_bank = 1, \ - .tri_bit = 4, \ - .einput_bit = 5, \ - .odrain_bit = PINGROUP_BIT_##od(6), \ - .lock_bit = 7, \ - .ioreset_bit = PINGROUP_BIT_##ior(8), \ - .rcv_sel_bit = -1, \ - .drv_reg = -1, \ - } - -#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ - drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ - slwf_b, slwf_w) \ - { \ - .name = "drive_" #pg_name, \ - .pins = drive_##pg_name##_pins, \ - .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ - .mux_reg = -1, \ - .pupd_reg = -1, \ - .tri_reg = -1, \ - .einput_bit = -1, \ - .odrain_bit = -1, \ - .lock_bit = -1, \ - .ioreset_bit = -1, \ - .rcv_sel_bit = -1, \ - .drv_reg = DRV_PINGROUP_REG(r), \ - .drv_bank = 0, \ - .hsm_bit = hsm_b, \ - .schmitt_bit = schmitt_b, \ - .lpmd_bit = lpmd_b, \ - .drvdn_bit = drvdn_b, \ - .drvdn_width = drvdn_w, \ - .drvup_bit = drvup_b, \ - .drvup_width = drvup_w, \ - .slwr_bit = slwr_b, \ - .slwr_width = slwr_w, \ - .slwf_bit = slwf_b, \ - .slwf_width = slwf_w, \ - .drvtype_bit = -1, \ - } - -static const struct tegra_pingroup tegra30_groups[] = { - /* pg_name, f0, f1, f2, f3, r, od, ior */ - PINGROUP(clk_32k_out_pa0, BLINK, RSVD2, RSVD3, RSVD4, 0x331c, N, N), - PINGROUP(uart3_cts_n_pa1, UARTC, RSVD2, GMI, RSVD4, 0x317c, N, N), - PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, GMI, 0x3358, N, N), - PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, GMI, 0x3364, N, N), - PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, GMI, 0x335c, N, N), - PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, GMI, 0x3360, N, N), - PINGROUP(sdmmc3_clk_pa6, UARTA, PWM2, SDMMC3, SPI3, 0x3390, N, N), - PINGROUP(sdmmc3_cmd_pa7, UARTA, PWM3, SDMMC3, SPI2, 0x3394, N, N), - PINGROUP(gmi_a17_pb0, UARTD, SPI4, GMI, DTV, 0x3234, N, N), - PINGROUP(gmi_a18_pb1, UARTD, SPI4, GMI, DTV, 0x3238, N, N), - PINGROUP(lcd_pwr0_pb2, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3090, N, N), - PINGROUP(lcd_pclk_pb3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3094, N, N), - PINGROUP(sdmmc3_dat3_pb4, RSVD1, PWM0, SDMMC3, SPI3, 0x33a4, N, N), - PINGROUP(sdmmc3_dat2_pb5, RSVD1, PWM1, SDMMC3, SPI3, 0x33a0, N, N), - PINGROUP(sdmmc3_dat1_pb6, RSVD1, RSVD2, SDMMC3, SPI3, 0x339c, N, N), - PINGROUP(sdmmc3_dat0_pb7, RSVD1, RSVD2, SDMMC3, SPI3, 0x3398, N, N), - PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, GMI, RSVD4, 0x3180, N, N), - PINGROUP(lcd_pwr1_pc1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3070, N, N), - PINGROUP(uart2_txd_pc2, UARTB, SPDIF, UARTA, SPI4, 0x3168, N, N), - PINGROUP(uart2_rxd_pc3, UARTB, SPDIF, UARTA, SPI4, 0x3164, N, N), - PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N), - PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N), - PINGROUP(lcd_pwr2_pc6, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3074, N, N), - PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N), - PINGROUP(sdmmc3_dat5_pd0, PWM0, SPI4, SDMMC3, SPI2, 0x33ac, N, N), - PINGROUP(sdmmc3_dat4_pd1, PWM1, SPI4, SDMMC3, SPI2, 0x33a8, N, N), - PINGROUP(lcd_dc1_pd2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x310c, N, N), - PINGROUP(sdmmc3_dat6_pd3, SPDIF, SPI4, SDMMC3, SPI2, 0x33b0, N, N), - PINGROUP(sdmmc3_dat7_pd4, SPDIF, SPI4, SDMMC3, SPI2, 0x33b4, N, N), - PINGROUP(vi_d1_pd5, DDR, SDMMC2, VI, RSVD4, 0x3128, N, Y), - PINGROUP(vi_vsync_pd6, DDR, RSVD2, VI, RSVD4, 0x315c, N, Y), - PINGROUP(vi_hsync_pd7, DDR, RSVD2, VI, RSVD4, 0x3160, N, Y), - PINGROUP(lcd_d0_pe0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a4, N, N), - PINGROUP(lcd_d1_pe1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a8, N, N), - PINGROUP(lcd_d2_pe2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ac, N, N), - PINGROUP(lcd_d3_pe3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b0, N, N), - PINGROUP(lcd_d4_pe4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b4, N, N), - PINGROUP(lcd_d5_pe5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b8, N, N), - PINGROUP(lcd_d6_pe6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30bc, N, N), - PINGROUP(lcd_d7_pe7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c0, N, N), - PINGROUP(lcd_d8_pf0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c4, N, N), - PINGROUP(lcd_d9_pf1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c8, N, N), - PINGROUP(lcd_d10_pf2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30cc, N, N), - PINGROUP(lcd_d11_pf3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d0, N, N), - PINGROUP(lcd_d12_pf4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d4, N, N), - PINGROUP(lcd_d13_pf5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d8, N, N), - PINGROUP(lcd_d14_pf6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30dc, N, N), - PINGROUP(lcd_d15_pf7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e0, N, N), - PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N), - PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N), - PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N), - PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N), - PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N), - PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, RSVD4, 0x3204, N, N), - PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, RSVD4, 0x3208, N, N), - PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, RSVD4, 0x320c, N, N), - PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, RSVD4, 0x3210, N, N), - PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, RSVD4, 0x3214, N, N), - PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, RSVD4, 0x3218, N, N), - PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, RSVD4, 0x321c, N, N), - PINGROUP(gmi_ad12_ph4, RSVD1, NAND, GMI, RSVD4, 0x3220, N, N), - PINGROUP(gmi_ad13_ph5, RSVD1, NAND, GMI, RSVD4, 0x3224, N, N), - PINGROUP(gmi_ad14_ph6, RSVD1, NAND, GMI, RSVD4, 0x3228, N, N), - PINGROUP(gmi_ad15_ph7, RSVD1, NAND, GMI, RSVD4, 0x322c, N, N), - PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, RSVD4, 0x3240, N, N), - PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, RSVD4, 0x3244, N, N), - PINGROUP(gmi_dqs_pi2, RSVD1, NAND, GMI, RSVD4, 0x3248, N, N), - PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SATA, 0x31e8, N, N), - PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N), - PINGROUP(gmi_iordy_pi5, RSVD1, NAND, GMI, RSVD4, 0x31c4, N, N), - PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, GMI_ALT, 0x31ec, N, N), - PINGROUP(gmi_wait_pi7, RSVD1, NAND, GMI, RSVD4, 0x31c8, N, N), - PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, DTV, 0x31d4, N, N), - PINGROUP(lcd_de_pj1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3098, N, N), - PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, DTV, 0x31d8, N, N), - PINGROUP(lcd_hsync_pj3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x309c, N, N), - PINGROUP(lcd_vsync_pj4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a0, N, N), - PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N), - PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N), - PINGROUP(gmi_a16_pj7, UARTD, SPI4, GMI, GMI_ALT, 0x3230, N, N), - PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, RSVD4, 0x31cc, N, N), - PINGROUP(gmi_clk_pk1, RSVD1, NAND, GMI, RSVD4, 0x31d0, N, N), - PINGROUP(gmi_cs4_n_pk2, RSVD1, NAND, GMI, RSVD4, 0x31e4, N, N), - PINGROUP(gmi_cs2_n_pk3, RSVD1, NAND, GMI, RSVD4, 0x31dc, N, N), - PINGROUP(gmi_cs3_n_pk4, RSVD1, NAND, GMI, GMI_ALT, 0x31e0, N, N), - PINGROUP(spdif_out_pk5, SPDIF, RSVD2, I2C1, SDMMC2, 0x3354, N, N), - PINGROUP(spdif_in_pk6, SPDIF, HDA, I2C1, SDMMC2, 0x3350, N, N), - PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, RSVD4, 0x323c, N, N), - PINGROUP(vi_d2_pl0, DDR, SDMMC2, VI, RSVD4, 0x312c, N, Y), - PINGROUP(vi_d3_pl1, DDR, SDMMC2, VI, RSVD4, 0x3130, N, Y), - PINGROUP(vi_d4_pl2, DDR, SDMMC2, VI, RSVD4, 0x3134, N, Y), - PINGROUP(vi_d5_pl3, DDR, SDMMC2, VI, RSVD4, 0x3138, N, Y), - PINGROUP(vi_d6_pl4, DDR, SDMMC2, VI, RSVD4, 0x313c, N, Y), - PINGROUP(vi_d7_pl5, DDR, SDMMC2, VI, RSVD4, 0x3140, N, Y), - PINGROUP(vi_d8_pl6, DDR, SDMMC2, VI, RSVD4, 0x3144, N, Y), - PINGROUP(vi_d9_pl7, DDR, SDMMC2, VI, RSVD4, 0x3148, N, Y), - PINGROUP(lcd_d16_pm0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e4, N, N), - PINGROUP(lcd_d17_pm1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e8, N, N), - PINGROUP(lcd_d18_pm2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ec, N, N), - PINGROUP(lcd_d19_pm3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f0, N, N), - PINGROUP(lcd_d20_pm4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f4, N, N), - PINGROUP(lcd_d21_pm5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f8, N, N), - PINGROUP(lcd_d22_pm6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30fc, N, N), - PINGROUP(lcd_d23_pm7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3100, N, N), - PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, SDMMC2, 0x3338, N, N), - PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, SDMMC2, 0x333c, N, N), - PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SDMMC2, 0x3340, N, N), - PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, SDMMC2, 0x3344, N, N), - PINGROUP(lcd_cs0_n_pn4, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3084, N, N), - PINGROUP(lcd_sdout_pn5, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x307c, N, N), - PINGROUP(lcd_dc0_pn6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3088, N, N), - PINGROUP(hdmi_int_pn7, HDMI, RSVD2, RSVD3, RSVD4, 0x3110, N, N), - PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N), - PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N), - PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N), - PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N), - PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N), - PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N), - PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N), - PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N), - PINGROUP(dap3_fs_pp0, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3030, N, N), - PINGROUP(dap3_din_pp1, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3034, N, N), - PINGROUP(dap3_dout_pp2, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3038, N, N), - PINGROUP(dap3_sclk_pp3, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x303c, N, N), - PINGROUP(dap4_fs_pp4, I2S3, RSVD2, GMI, RSVD4, 0x31a8, N, N), - PINGROUP(dap4_din_pp5, I2S3, RSVD2, GMI, RSVD4, 0x31ac, N, N), - PINGROUP(dap4_dout_pp6, I2S3, RSVD2, GMI, RSVD4, 0x31b0, N, N), - PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, GMI, RSVD4, 0x31b4, N, N), - PINGROUP(kb_col0_pq0, KBC, NAND, TRACE, TEST, 0x32fc, N, N), - PINGROUP(kb_col1_pq1, KBC, NAND, TRACE, TEST, 0x3300, N, N), - PINGROUP(kb_col2_pq2, KBC, NAND, TRACE, RSVD4, 0x3304, N, N), - PINGROUP(kb_col3_pq3, KBC, NAND, TRACE, RSVD4, 0x3308, N, N), - PINGROUP(kb_col4_pq4, KBC, NAND, TRACE, RSVD4, 0x330c, N, N), - PINGROUP(kb_col5_pq5, KBC, NAND, TRACE, RSVD4, 0x3310, N, N), - PINGROUP(kb_col6_pq6, KBC, NAND, TRACE, MIO, 0x3314, N, N), - PINGROUP(kb_col7_pq7, KBC, NAND, TRACE, MIO, 0x3318, N, N), - PINGROUP(kb_row0_pr0, KBC, NAND, RSVD3, RSVD4, 0x32bc, N, N), - PINGROUP(kb_row1_pr1, KBC, NAND, RSVD3, RSVD4, 0x32c0, N, N), - PINGROUP(kb_row2_pr2, KBC, NAND, RSVD3, RSVD4, 0x32c4, N, N), - PINGROUP(kb_row3_pr3, KBC, NAND, RSVD3, INVALID, 0x32c8, N, N), - PINGROUP(kb_row4_pr4, KBC, NAND, TRACE, RSVD4, 0x32cc, N, N), - PINGROUP(kb_row5_pr5, KBC, NAND, TRACE, OWR, 0x32d0, N, N), - PINGROUP(kb_row6_pr6, KBC, NAND, SDMMC2, MIO, 0x32d4, N, N), - PINGROUP(kb_row7_pr7, KBC, NAND, SDMMC2, MIO, 0x32d8, N, N), - PINGROUP(kb_row8_ps0, KBC, NAND, SDMMC2, MIO, 0x32dc, N, N), - PINGROUP(kb_row9_ps1, KBC, NAND, SDMMC2, MIO, 0x32e0, N, N), - PINGROUP(kb_row10_ps2, KBC, NAND, SDMMC2, MIO, 0x32e4, N, N), - PINGROUP(kb_row11_ps3, KBC, NAND, SDMMC2, MIO, 0x32e8, N, N), - PINGROUP(kb_row12_ps4, KBC, NAND, SDMMC2, MIO, 0x32ec, N, N), - PINGROUP(kb_row13_ps5, KBC, NAND, SDMMC2, MIO, 0x32f0, N, N), - PINGROUP(kb_row14_ps6, KBC, NAND, SDMMC2, MIO, 0x32f4, N, N), - PINGROUP(kb_row15_ps7, KBC, NAND, SDMMC2, MIO, 0x32f8, N, N), - PINGROUP(vi_pclk_pt0, RSVD1, SDMMC2, VI, RSVD4, 0x3154, N, Y), - PINGROUP(vi_mclk_pt1, VI, VI_ALT1, VI_ALT2, VI_ALT3, 0x3158, N, Y), - PINGROUP(vi_d10_pt2, DDR, RSVD2, VI, RSVD4, 0x314c, N, Y), - PINGROUP(vi_d11_pt3, DDR, RSVD2, VI, RSVD4, 0x3150, N, Y), - PINGROUP(vi_d0_pt4, DDR, RSVD2, VI, RSVD4, 0x3124, N, Y), - PINGROUP(gen2_i2c_scl_pt5, I2C2, HDCP, GMI, RSVD4, 0x3250, Y, N), - PINGROUP(gen2_i2c_sda_pt6, I2C2, HDCP, GMI, RSVD4, 0x3254, Y, N), - PINGROUP(sdmmc4_cmd_pt7, I2C3, NAND, GMI, SDMMC4, 0x325c, N, Y), - PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N), - PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N), - PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N), - PINGROUP(pu3, PWM0, UARTA, GMI, RSVD4, 0x3190, N, N), - PINGROUP(pu4, PWM1, UARTA, GMI, RSVD4, 0x3194, N, N), - PINGROUP(pu5, PWM2, UARTA, GMI, RSVD4, 0x3198, N, N), - PINGROUP(pu6, PWM3, UARTA, GMI, RSVD4, 0x319c, N, N), - PINGROUP(jtag_rtck_pu7, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N), - PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N), - PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N), - PINGROUP(pv2, OWR, RSVD2, RSVD3, RSVD4, 0x3060, N, N), - PINGROUP(pv3, CLK_12M_OUT, RSVD2, RSVD3, RSVD4, 0x3064, N, N), - PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N), - PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N), - PINGROUP(crt_hsync_pv6, CRT, RSVD2, RSVD3, RSVD4, 0x311c, N, N), - PINGROUP(crt_vsync_pv7, CRT, RSVD2, RSVD3, RSVD4, 0x3120, N, N), - PINGROUP(lcd_cs1_n_pw0, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3104, N, N), - PINGROUP(lcd_m1_pw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3108, N, N), - PINGROUP(spi2_cs1_n_pw2, SPI3, SPI2, SPI2_ALT, I2C1, 0x3388, N, N), - PINGROUP(spi2_cs2_n_pw3, SPI3, SPI2, SPI2_ALT, I2C1, 0x338c, N, N), - PINGROUP(clk1_out_pw4, EXTPERIPH1, RSVD2, RSVD3, RSVD4, 0x334c, N, N), - PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N), - PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, RSVD4, 0x3174, N, N), - PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, RSVD4, 0x3178, N, N), - PINGROUP(spi2_mosi_px0, SPI6, SPI2, SPI3, GMI, 0x3368, N, N), - PINGROUP(spi2_miso_px1, SPI6, SPI2, SPI3, GMI, 0x336c, N, N), - PINGROUP(spi2_sck_px2, SPI6, SPI2, SPI3, GMI, 0x3374, N, N), - PINGROUP(spi2_cs0_n_px3, SPI6, SPI2, SPI3, GMI, 0x3370, N, N), - PINGROUP(spi1_mosi_px4, SPI2, SPI1, SPI2_ALT, GMI, 0x3378, N, N), - PINGROUP(spi1_sck_px5, SPI2, SPI1, SPI2_ALT, GMI, 0x337c, N, N), - PINGROUP(spi1_cs0_n_px6, SPI2, SPI1, SPI2_ALT, GMI, 0x3380, N, N), - PINGROUP(spi1_miso_px7, SPI3, SPI1, SPI2_ALT, RSVD4, 0x3384, N, N), - PINGROUP(ulpi_clk_py0, SPI1, RSVD2, UARTD, ULPI, 0x3020, N, N), - PINGROUP(ulpi_dir_py1, SPI1, RSVD2, UARTD, ULPI, 0x3024, N, N), - PINGROUP(ulpi_nxt_py2, SPI1, RSVD2, UARTD, ULPI, 0x3028, N, N), - PINGROUP(ulpi_stp_py3, SPI1, RSVD2, UARTD, ULPI, 0x302c, N, N), - PINGROUP(sdmmc1_dat3_py4, SDMMC1, RSVD2, UARTE, UARTA, 0x3050, N, N), - PINGROUP(sdmmc1_dat2_py5, SDMMC1, RSVD2, UARTE, UARTA, 0x3054, N, N), - PINGROUP(sdmmc1_dat1_py6, SDMMC1, RSVD2, UARTE, UARTA, 0x3058, N, N), - PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, UARTE, UARTA, 0x305c, N, N), - PINGROUP(sdmmc1_clk_pz0, SDMMC1, RSVD2, RSVD3, UARTA, 0x3048, N, N), - PINGROUP(sdmmc1_cmd_pz1, SDMMC1, RSVD2, RSVD3, UARTA, 0x304c, N, N), - PINGROUP(lcd_sdin_pz2, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3078, N, N), - PINGROUP(lcd_wr_n_pz3, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3080, N, N), - PINGROUP(lcd_sck_pz4, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x308c, N, N), - PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N), - PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N), - PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N), - PINGROUP(sdmmc4_dat0_paa0, UARTE, SPI3, GMI, SDMMC4, 0x3260, N, Y), - PINGROUP(sdmmc4_dat1_paa1, UARTE, SPI3, GMI, SDMMC4, 0x3264, N, Y), - PINGROUP(sdmmc4_dat2_paa2, UARTE, SPI3, GMI, SDMMC4, 0x3268, N, Y), - PINGROUP(sdmmc4_dat3_paa3, UARTE, SPI3, GMI, SDMMC4, 0x326c, N, Y), - PINGROUP(sdmmc4_dat4_paa4, I2C3, I2S4, GMI, SDMMC4, 0x3270, N, Y), - PINGROUP(sdmmc4_dat5_paa5, VGP3, I2S4, GMI, SDMMC4, 0x3274, N, Y), - PINGROUP(sdmmc4_dat6_paa6, VGP4, I2S4, GMI, SDMMC4, 0x3278, N, Y), - PINGROUP(sdmmc4_dat7_paa7, VGP5, I2S4, GMI, SDMMC4, 0x327c, N, Y), - PINGROUP(pbb0, I2S4, RSVD2, RSVD3, SDMMC4, 0x328c, N, N), - PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC4, 0x3290, Y, N), - PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC4, 0x3294, Y, N), - PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC4, 0x3298, N, N), - PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC4, 0x329c, N, N), - PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, SDMMC4, 0x32a0, N, N), - PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, SDMMC4, 0x32a4, N, N), - PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC4, 0x32a8, N, N), - PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC4, 0x3284, N, N), - PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC4, 0x3288, N, N), - PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N), - PINGROUP(sdmmc4_rst_n_pcc3, VGP6, RSVD2, RSVD3, SDMMC4, 0x3280, N, Y), - PINGROUP(sdmmc4_clk_pcc4, INVALID, NAND, GMI, SDMMC4, 0x3258, N, Y), - PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N), - PINGROUP(pex_l2_rst_n_pcc6, PCIE, HDA, RSVD3, RSVD4, 0x33d8, N, N), - PINGROUP(pex_l2_clkreq_n_pcc7, PCIE, HDA, RSVD3, RSVD4, 0x33dc, N, N), - PINGROUP(pex_l0_prsnt_n_pdd0, PCIE, HDA, RSVD3, RSVD4, 0x33b8, N, N), - PINGROUP(pex_l0_rst_n_pdd1, PCIE, HDA, RSVD3, RSVD4, 0x33bc, N, N), - PINGROUP(pex_l0_clkreq_n_pdd2, PCIE, HDA, RSVD3, RSVD4, 0x33c0, N, N), - PINGROUP(pex_wake_n_pdd3, PCIE, HDA, RSVD3, RSVD4, 0x33c4, N, N), - PINGROUP(pex_l1_prsnt_n_pdd4, PCIE, HDA, RSVD3, RSVD4, 0x33c8, N, N), - PINGROUP(pex_l1_rst_n_pdd5, PCIE, HDA, RSVD3, RSVD4, 0x33cc, N, N), - PINGROUP(pex_l1_clkreq_n_pdd6, PCIE, HDA, RSVD3, RSVD4, 0x33d0, N, N), - PINGROUP(pex_l2_prsnt_n_pdd7, PCIE, HDA, RSVD3, RSVD4, 0x33d4, N, N), - PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N), - PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N), - PINGROUP(clk1_req_pee2, DAP, HDA, RSVD3, RSVD4, 0x3348, N, N), - PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N), - PINGROUP(clk_32k_in, CLK_32K_IN, RSVD2, RSVD3, RSVD4, 0x3330, N, N), - PINGROUP(core_pwr_req, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3324, N, N), - PINGROUP(cpu_pwr_req, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3328, N, N), - PINGROUP(owr, OWR, CEC, RSVD3, RSVD4, 0x3334, N, N), - PINGROUP(pwr_int_n, PWR_INT_N, RSVD2, RSVD3, RSVD4, 0x332c, N, N), - /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ - DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(at1, 0x870, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), - DRV_PINGROUP(at2, 0x874, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), - DRV_PINGROUP(at3, 0x878, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(crt, 0x8f8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(csus, 0x88c, -1, -1, -1, 12, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(gma, 0x900, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gmb, 0x904, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gmc, 0x908, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gmd, 0x90c, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), - DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), - DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(lcd1, 0x8a4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(lcd2, 0x8a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdio2, 0x8ac, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), - DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), - DRV_PINGROUP(vi1, 0x8c8, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), -}; - -static const struct tegra_pinctrl_soc_data tegra30_pinctrl = { - .ngpios = NUM_GPIOS, - .pins = tegra30_pins, - .npins = ARRAY_SIZE(tegra30_pins), - .functions = tegra30_functions, - .nfunctions = ARRAY_SIZE(tegra30_functions), - .groups = tegra30_groups, - .ngroups = ARRAY_SIZE(tegra30_groups), - .hsm_in_mux = false, - .schmitt_in_mux = false, - .drvtype_in_mux = false, -}; - -static int tegra30_pinctrl_probe(struct platform_device *pdev) -{ - return tegra_pinctrl_probe(pdev, &tegra30_pinctrl); -} - -static const struct of_device_id tegra30_pinctrl_of_match[] = { - { .compatible = "nvidia,tegra30-pinmux", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match); - -static struct platform_driver tegra30_pinctrl_driver = { - .driver = { - .name = "tegra30-pinctrl", - .of_match_table = tegra30_pinctrl_of_match, - }, - .probe = tegra30_pinctrl_probe, - .remove = tegra_pinctrl_remove, -}; -module_platform_driver(tegra30_pinctrl_driver); - -MODULE_AUTHOR("Stephen Warren "); -MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig new file mode 100644 index 000000000000..24e20cc08d5b --- /dev/null +++ b/drivers/pinctrl/tegra/Kconfig @@ -0,0 +1,30 @@ +config PINCTRL_TEGRA + bool + select PINMUX + select PINCONF + +config PINCTRL_TEGRA20 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA30 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA114 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA124 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA210 + bool + select PINCTRL_TEGRA + +config PINCTRL_TEGRA_XUSB + def_bool y if ARCH_TEGRA + select GENERIC_PHY + select PINCONF + select PINMUX diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile new file mode 100644 index 000000000000..a927379b6794 --- /dev/null +++ b/drivers/pinctrl/tegra/Makefile @@ -0,0 +1,7 @@ +obj-y += pinctrl-tegra.o +obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o +obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o +obj-$(CONFIG_PINCTRL_TEGRA114) += pinctrl-tegra114.o +obj-$(CONFIG_PINCTRL_TEGRA124) += pinctrl-tegra124.o +obj-$(CONFIG_PINCTRL_TEGRA210) += pinctrl-tegra210.o +obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o diff --git a/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c new file mode 100644 index 000000000000..2f06029c9405 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra-xusb.c @@ -0,0 +1,985 @@ +/* + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. + * + * 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 +#include +#include +#include + +#include + +#include "../core.h" +#include "../pinctrl-utils.h" + +#define XUSB_PADCTL_ELPG_PROGRAM 0x01c +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26) +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25) +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24) + +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1) + +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5) +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4) + +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1) +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0) + +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148 +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1) +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0) + +struct tegra_xusb_padctl_function { + const char *name; + const char * const *groups; + unsigned int num_groups; +}; + +struct tegra_xusb_padctl_soc { + const struct pinctrl_pin_desc *pins; + unsigned int num_pins; + + const struct tegra_xusb_padctl_function *functions; + unsigned int num_functions; + + const struct tegra_xusb_padctl_lane *lanes; + unsigned int num_lanes; +}; + +struct tegra_xusb_padctl_lane { + const char *name; + + unsigned int offset; + unsigned int shift; + unsigned int mask; + unsigned int iddq; + + const unsigned int *funcs; + unsigned int num_funcs; +}; + +struct tegra_xusb_padctl { + struct device *dev; + void __iomem *regs; + struct mutex lock; + struct reset_control *rst; + + const struct tegra_xusb_padctl_soc *soc; + struct pinctrl_dev *pinctrl; + struct pinctrl_desc desc; + + struct phy_provider *provider; + struct phy *phys[2]; + + unsigned int enable; +}; + +static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value, + unsigned long offset) +{ + writel(value, padctl->regs + offset); +} + +static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl, + unsigned long offset) +{ + return readl(padctl->regs + offset); +} + +static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->num_pins; +} + +static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl, + unsigned int group) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->pins[group].name; +} + +static int tegra_xusb_padctl_get_group_pins(struct pinctrl_dev *pinctrl, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + /* + * For the tegra-xusb pad controller groups are synonomous + * with lanes/pins and there is always one lane/pin per group. + */ + *pins = &pinctrl->desc->pins[group].number; + *num_pins = 1; + + return 0; +} + +enum tegra_xusb_padctl_param { + TEGRA_XUSB_PADCTL_IDDQ, +}; + +static const struct tegra_xusb_padctl_property { + const char *name; + enum tegra_xusb_padctl_param param; +} properties[] = { + { "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ }, +}; + +#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value)) +#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16) +#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff) + +static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl, + struct device_node *np, + struct pinctrl_map **maps, + unsigned int *reserved_maps, + unsigned int *num_maps) +{ + unsigned int i, reserve = 0, num_configs = 0; + unsigned long config, *configs = NULL; + const char *function, *group; + struct property *prop; + int err = 0; + u32 value; + + err = of_property_read_string(np, "nvidia,function", &function); + if (err < 0) { + if (err != -EINVAL) + return err; + + function = NULL; + } + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + err = of_property_read_u32(np, properties[i].name, &value); + if (err < 0) { + if (err == -EINVAL) + continue; + + goto out; + } + + config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value); + + err = pinctrl_utils_add_config(padctl->pinctrl, &configs, + &num_configs, config); + if (err < 0) + goto out; + } + + if (function) + reserve++; + + if (num_configs) + reserve++; + + err = of_property_count_strings(np, "nvidia,lanes"); + if (err < 0) + goto out; + + reserve *= err; + + err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps, + num_maps, reserve); + if (err < 0) + goto out; + + of_property_for_each_string(np, "nvidia,lanes", prop, group) { + if (function) { + err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps, + reserved_maps, num_maps, group, + function); + if (err < 0) + goto out; + } + + if (num_configs) { + err = pinctrl_utils_add_map_configs(padctl->pinctrl, + maps, reserved_maps, num_maps, group, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (err < 0) + goto out; + } + } + + err = 0; + +out: + kfree(configs); + return err; +} + +static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl, + struct device_node *parent, + struct pinctrl_map **maps, + unsigned int *num_maps) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + unsigned int reserved_maps = 0; + struct device_node *np; + int err; + + *num_maps = 0; + *maps = NULL; + + for_each_child_of_node(parent, np) { + err = tegra_xusb_padctl_parse_subnode(padctl, np, maps, + &reserved_maps, + num_maps); + if (err < 0) { + of_node_put(np); + return err; + } + } + + return 0; +} + +static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = { + .get_groups_count = tegra_xusb_padctl_get_groups_count, + .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, +}; + +static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->num_functions; +} + +static const char * +tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl, + unsigned int function) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + return padctl->soc->functions[function].name; +} + +static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl, + unsigned int function, + const char * const **groups, + unsigned * const num_groups) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + + *num_groups = padctl->soc->functions[function].num_groups; + *groups = padctl->soc->functions[function].groups; + + return 0; +} + +static int tegra_xusb_padctl_pinmux_set(struct pinctrl_dev *pinctrl, + unsigned int function, + unsigned int group) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + const struct tegra_xusb_padctl_lane *lane; + unsigned int i; + u32 value; + + lane = &padctl->soc->lanes[group]; + + for (i = 0; i < lane->num_funcs; i++) + if (lane->funcs[i] == function) + break; + + if (i >= lane->num_funcs) + return -EINVAL; + + value = padctl_readl(padctl, lane->offset); + value &= ~(lane->mask << lane->shift); + value |= i << lane->shift; + padctl_writel(padctl, value, lane->offset); + + return 0; +} + +static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = { + .get_functions_count = tegra_xusb_padctl_get_functions_count, + .get_function_name = tegra_xusb_padctl_get_function_name, + .get_function_groups = tegra_xusb_padctl_get_function_groups, + .set_mux = tegra_xusb_padctl_pinmux_set, +}; + +static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl, + unsigned int group, + unsigned long *config) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + const struct tegra_xusb_padctl_lane *lane; + enum tegra_xusb_padctl_param param; + u32 value; + + param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config); + lane = &padctl->soc->lanes[group]; + + switch (param) { + case TEGRA_XUSB_PADCTL_IDDQ: + /* lanes with iddq == 0 don't support this parameter */ + if (lane->iddq == 0) + return -EINVAL; + + value = padctl_readl(padctl, lane->offset); + + if (value & BIT(lane->iddq)) + value = 0; + else + value = 1; + + *config = TEGRA_XUSB_PADCTL_PACK(param, value); + break; + + default: + dev_err(padctl->dev, "invalid configuration parameter: %04x\n", + param); + return -ENOTSUPP; + } + + return 0; +} + +static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl, + unsigned int group, + unsigned long *configs, + unsigned int num_configs) +{ + struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl); + const struct tegra_xusb_padctl_lane *lane; + enum tegra_xusb_padctl_param param; + unsigned long value; + unsigned int i; + u32 regval; + + lane = &padctl->soc->lanes[group]; + + for (i = 0; i < num_configs; i++) { + param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]); + value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]); + + switch (param) { + case TEGRA_XUSB_PADCTL_IDDQ: + /* lanes with iddq == 0 don't support this parameter */ + if (lane->iddq == 0) + return -EINVAL; + + regval = padctl_readl(padctl, lane->offset); + + if (value) + regval &= ~BIT(lane->iddq); + else + regval |= BIT(lane->iddq); + + padctl_writel(padctl, regval, lane->offset); + break; + + default: + dev_err(padctl->dev, + "invalid configuration parameter: %04x\n", + param); + return -ENOTSUPP; + } + } + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static const char *strip_prefix(const char *s) +{ + const char *comma = strchr(s, ','); + if (!comma) + return s; + + return comma + 1; +} + +static void +tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl, + struct seq_file *s, + unsigned int group) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + unsigned long config, value; + int err; + + config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0); + + err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group, + &config); + if (err < 0) + continue; + + value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); + + seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name), + value); + } +} + +static void +tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl, + struct seq_file *s, + unsigned long config) +{ + enum tegra_xusb_padctl_param param; + const char *name = "unknown"; + unsigned long value; + unsigned int i; + + param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config); + value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config); + + for (i = 0; i < ARRAY_SIZE(properties); i++) { + if (properties[i].param == param) { + name = properties[i].name; + break; + } + } + + seq_printf(s, "%s=%lu", strip_prefix(name), value); +} +#endif + +static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = { + .pin_config_group_get = tegra_xusb_padctl_pinconf_group_get, + .pin_config_group_set = tegra_xusb_padctl_pinconf_group_set, +#ifdef CONFIG_DEBUG_FS + .pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show, + .pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show, +#endif +}; + +static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl) +{ + u32 value; + + mutex_lock(&padctl->lock); + + if (padctl->enable++ > 0) + goto out; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + +out: + mutex_unlock(&padctl->lock); + return 0; +} + +static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl) +{ + u32 value; + + mutex_lock(&padctl->lock); + + if (WARN_ON(padctl->enable == 0)) + goto out; + + if (--padctl->enable > 0) + goto out; + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + + usleep_range(100, 200); + + value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM); + value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN; + padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM); + +out: + mutex_unlock(&padctl->lock); + return 0; +} + +static int tegra_xusb_phy_init(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + + return tegra_xusb_padctl_enable(padctl); +} + +static int tegra_xusb_phy_exit(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + + return tegra_xusb_padctl_disable(padctl); +} + +static int pcie_phy_power_on(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + unsigned long timeout; + int err = -ETIMEDOUT; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); + value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN | + XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN | + XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + + timeout = jiffies + msecs_to_jiffies(50); + + while (time_before(jiffies, timeout)) { + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) { + err = 0; + break; + } + + usleep_range(100, 200); + } + + return err; +} + +static int pcie_phy_power_off(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1); + + return 0; +} + +static const struct phy_ops pcie_phy_ops = { + .init = tegra_xusb_phy_init, + .exit = tegra_xusb_phy_exit, + .power_on = pcie_phy_power_on, + .power_off = pcie_phy_power_off, + .owner = THIS_MODULE, +}; + +static int sata_phy_power_on(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + unsigned long timeout; + int err = -ETIMEDOUT; + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; + value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + timeout = jiffies + msecs_to_jiffies(50); + + while (time_before(jiffies, timeout)) { + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) { + err = 0; + break; + } + + usleep_range(100, 200); + } + + return err; +} + +static int sata_phy_power_off(struct phy *phy) +{ + struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy); + u32 value; + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD; + value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1); + + value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD; + value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ; + padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1); + + return 0; +} + +static const struct phy_ops sata_phy_ops = { + .init = tegra_xusb_phy_init, + .exit = tegra_xusb_phy_exit, + .power_on = sata_phy_power_on, + .power_off = sata_phy_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *tegra_xusb_padctl_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev); + unsigned int index = args->args[0]; + + if (args->args_count <= 0) + return ERR_PTR(-EINVAL); + + if (index >= ARRAY_SIZE(padctl->phys)) + return ERR_PTR(-EINVAL); + + return padctl->phys[index]; +} + +#define PIN_OTG_0 0 +#define PIN_OTG_1 1 +#define PIN_OTG_2 2 +#define PIN_ULPI_0 3 +#define PIN_HSIC_0 4 +#define PIN_HSIC_1 5 +#define PIN_PCIE_0 6 +#define PIN_PCIE_1 7 +#define PIN_PCIE_2 8 +#define PIN_PCIE_3 9 +#define PIN_PCIE_4 10 +#define PIN_SATA_0 11 + +static const struct pinctrl_pin_desc tegra124_pins[] = { + PINCTRL_PIN(PIN_OTG_0, "otg-0"), + PINCTRL_PIN(PIN_OTG_1, "otg-1"), + PINCTRL_PIN(PIN_OTG_2, "otg-2"), + PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"), + PINCTRL_PIN(PIN_HSIC_0, "hsic-0"), + PINCTRL_PIN(PIN_HSIC_1, "hsic-1"), + PINCTRL_PIN(PIN_PCIE_0, "pcie-0"), + PINCTRL_PIN(PIN_PCIE_1, "pcie-1"), + PINCTRL_PIN(PIN_PCIE_2, "pcie-2"), + PINCTRL_PIN(PIN_PCIE_3, "pcie-3"), + PINCTRL_PIN(PIN_PCIE_4, "pcie-4"), + PINCTRL_PIN(PIN_SATA_0, "sata-0"), +}; + +static const char * const tegra124_snps_groups[] = { + "otg-0", + "otg-1", + "otg-2", + "ulpi-0", + "hsic-0", + "hsic-1", +}; + +static const char * const tegra124_xusb_groups[] = { + "otg-0", + "otg-1", + "otg-2", + "ulpi-0", + "hsic-0", + "hsic-1", +}; + +static const char * const tegra124_uart_groups[] = { + "otg-0", + "otg-1", + "otg-2", +}; + +static const char * const tegra124_pcie_groups[] = { + "pcie-0", + "pcie-1", + "pcie-2", + "pcie-3", + "pcie-4", +}; + +static const char * const tegra124_usb3_groups[] = { + "pcie-0", + "pcie-1", + "sata-0", +}; + +static const char * const tegra124_sata_groups[] = { + "sata-0", +}; + +static const char * const tegra124_rsvd_groups[] = { + "otg-0", + "otg-1", + "otg-2", + "pcie-0", + "pcie-1", + "pcie-2", + "pcie-3", + "pcie-4", + "sata-0", +}; + +#define TEGRA124_FUNCTION(_name) \ + { \ + .name = #_name, \ + .num_groups = ARRAY_SIZE(tegra124_##_name##_groups), \ + .groups = tegra124_##_name##_groups, \ + } + +static struct tegra_xusb_padctl_function tegra124_functions[] = { + TEGRA124_FUNCTION(snps), + TEGRA124_FUNCTION(xusb), + TEGRA124_FUNCTION(uart), + TEGRA124_FUNCTION(pcie), + TEGRA124_FUNCTION(usb3), + TEGRA124_FUNCTION(sata), + TEGRA124_FUNCTION(rsvd), +}; + +enum tegra124_function { + TEGRA124_FUNC_SNPS, + TEGRA124_FUNC_XUSB, + TEGRA124_FUNC_UART, + TEGRA124_FUNC_PCIE, + TEGRA124_FUNC_USB3, + TEGRA124_FUNC_SATA, + TEGRA124_FUNC_RSVD, +}; + +static const unsigned int tegra124_otg_functions[] = { + TEGRA124_FUNC_SNPS, + TEGRA124_FUNC_XUSB, + TEGRA124_FUNC_UART, + TEGRA124_FUNC_RSVD, +}; + +static const unsigned int tegra124_usb_functions[] = { + TEGRA124_FUNC_SNPS, + TEGRA124_FUNC_XUSB, +}; + +static const unsigned int tegra124_pci_functions[] = { + TEGRA124_FUNC_PCIE, + TEGRA124_FUNC_USB3, + TEGRA124_FUNC_SATA, + TEGRA124_FUNC_RSVD, +}; + +#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs) \ + { \ + .name = _name, \ + .offset = _offset, \ + .shift = _shift, \ + .mask = _mask, \ + .iddq = _iddq, \ + .num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions), \ + .funcs = tegra124_##_funcs##_functions, \ + } + +static const struct tegra_xusb_padctl_lane tegra124_lanes[] = { + TEGRA124_LANE("otg-0", 0x004, 0, 0x3, 0, otg), + TEGRA124_LANE("otg-1", 0x004, 2, 0x3, 0, otg), + TEGRA124_LANE("otg-2", 0x004, 4, 0x3, 0, otg), + TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb), + TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb), + TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb), + TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci), + TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci), + TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci), + TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci), + TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci), + TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci), +}; + +static const struct tegra_xusb_padctl_soc tegra124_soc = { + .num_pins = ARRAY_SIZE(tegra124_pins), + .pins = tegra124_pins, + .num_functions = ARRAY_SIZE(tegra124_functions), + .functions = tegra124_functions, + .num_lanes = ARRAY_SIZE(tegra124_lanes), + .lanes = tegra124_lanes, +}; + +static const struct of_device_id tegra_xusb_padctl_of_match[] = { + { .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc }, + { } +}; +MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match); + +static int tegra_xusb_padctl_probe(struct platform_device *pdev) +{ + struct tegra_xusb_padctl *padctl; + const struct of_device_id *match; + struct resource *res; + struct phy *phy; + int err; + + padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL); + if (!padctl) + return -ENOMEM; + + platform_set_drvdata(pdev, padctl); + mutex_init(&padctl->lock); + padctl->dev = &pdev->dev; + + match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node); + padctl->soc = match->data; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + padctl->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(padctl->regs)) + return PTR_ERR(padctl->regs); + + padctl->rst = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(padctl->rst)) + return PTR_ERR(padctl->rst); + + err = reset_control_deassert(padctl->rst); + if (err < 0) + return err; + + memset(&padctl->desc, 0, sizeof(padctl->desc)); + padctl->desc.name = dev_name(padctl->dev); + padctl->desc.pins = tegra124_pins; + padctl->desc.npins = ARRAY_SIZE(tegra124_pins); + padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops; + padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops; + padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops; + padctl->desc.owner = THIS_MODULE; + + padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl); + if (IS_ERR(padctl->pinctrl)) { + dev_err(&pdev->dev, "failed to register pincontrol\n"); + err = PTR_ERR(padctl->pinctrl); + goto reset; + } + + phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops); + if (IS_ERR(phy)) { + err = PTR_ERR(phy); + goto unregister; + } + + padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy; + phy_set_drvdata(phy, padctl); + + phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops); + if (IS_ERR(phy)) { + err = PTR_ERR(phy); + goto unregister; + } + + padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy; + phy_set_drvdata(phy, padctl); + + padctl->provider = devm_of_phy_provider_register(&pdev->dev, + tegra_xusb_padctl_xlate); + if (IS_ERR(padctl->provider)) { + err = PTR_ERR(padctl->provider); + dev_err(&pdev->dev, "failed to register PHYs: %d\n", err); + goto unregister; + } + + return 0; + +unregister: + pinctrl_unregister(padctl->pinctrl); +reset: + reset_control_assert(padctl->rst); + return err; +} + +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); + + return err; +} + +static struct platform_driver tegra_xusb_padctl_driver = { + .driver = { + .name = "tegra-xusb-padctl", + .of_match_table = tegra_xusb_padctl_of_match, + }, + .probe = tegra_xusb_padctl_probe, + .remove = tegra_xusb_padctl_remove, +}; +module_platform_driver(tegra_xusb_padctl_driver); + +MODULE_AUTHOR("Thierry Reding "); +MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c new file mode 100644 index 000000000000..49388822c0e9 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -0,0 +1,747 @@ +/* + * Driver for the NVIDIA Tegra pinmux + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * + * Derived from code: + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010 NVIDIA Corporation + * Copyright (C) 2009-2011 ST-Ericsson AB + * + * 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 +#include +#include +#include +#include + +#include "../core.h" +#include "../pinctrl-utils.h" +#include "pinctrl-tegra.h" + +struct tegra_pmx { + struct device *dev; + struct pinctrl_dev *pctl; + + const struct tegra_pinctrl_soc_data *soc; + const char **group_pins; + + int nbanks; + void __iomem **regs; +}; + +static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg) +{ + return readl(pmx->regs[bank] + reg); +} + +static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg) +{ + writel(val, pmx->regs[bank] + reg); +} + +static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->ngroups; +} + +static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->groups[group].name; +} + +static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + *pins = pmx->soc->groups[group].pins; + *num_pins = pmx->soc->groups[group].npins; + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned offset) +{ + seq_printf(s, " %s", dev_name(pctldev->dev)); +} +#endif + +static const struct cfg_param { + const char *property; + enum tegra_pinconf_param param; +} cfg_params[] = { + {"nvidia,pull", TEGRA_PINCONF_PARAM_PULL}, + {"nvidia,tristate", TEGRA_PINCONF_PARAM_TRISTATE}, + {"nvidia,enable-input", TEGRA_PINCONF_PARAM_ENABLE_INPUT}, + {"nvidia,open-drain", TEGRA_PINCONF_PARAM_OPEN_DRAIN}, + {"nvidia,lock", TEGRA_PINCONF_PARAM_LOCK}, + {"nvidia,io-reset", TEGRA_PINCONF_PARAM_IORESET}, + {"nvidia,rcv-sel", TEGRA_PINCONF_PARAM_RCV_SEL}, + {"nvidia,io-hv", TEGRA_PINCONF_PARAM_RCV_SEL}, + {"nvidia,high-speed-mode", TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE}, + {"nvidia,schmitt", TEGRA_PINCONF_PARAM_SCHMITT}, + {"nvidia,low-power-mode", TEGRA_PINCONF_PARAM_LOW_POWER_MODE}, + {"nvidia,pull-down-strength", TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH}, + {"nvidia,pull-up-strength", TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH}, + {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, + {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, + {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, +}; + +static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, + struct pinctrl_map **map, + unsigned *reserved_maps, + unsigned *num_maps) +{ + struct device *dev = pctldev->dev; + int ret, i; + const char *function; + u32 val; + unsigned long config; + unsigned long *configs = NULL; + unsigned num_configs = 0; + unsigned reserve; + struct property *prop; + const char *group; + + ret = of_property_read_string(np, "nvidia,function", &function); + if (ret < 0) { + /* EINVAL=missing, which is fine since it's optional */ + if (ret != -EINVAL) + dev_err(dev, + "could not parse property nvidia,function\n"); + function = NULL; + } + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + ret = of_property_read_u32(np, cfg_params[i].property, &val); + if (!ret) { + config = TEGRA_PINCONF_PACK(cfg_params[i].param, val); + ret = pinctrl_utils_add_config(pctldev, &configs, + &num_configs, config); + if (ret < 0) + goto exit; + /* EINVAL=missing, which is fine since it's optional */ + } else if (ret != -EINVAL) { + dev_err(dev, "could not parse property %s\n", + cfg_params[i].property); + } + } + + reserve = 0; + if (function != NULL) + reserve++; + if (num_configs) + reserve++; + ret = of_property_count_strings(np, "nvidia,pins"); + if (ret < 0) { + dev_err(dev, "could not parse property nvidia,pins\n"); + goto exit; + } + reserve *= ret; + + ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, + num_maps, reserve); + if (ret < 0) + goto exit; + + of_property_for_each_string(np, "nvidia,pins", prop, group) { + if (function) { + ret = pinctrl_utils_add_map_mux(pctldev, map, + reserved_maps, num_maps, group, + function); + if (ret < 0) + goto exit; + } + + if (num_configs) { + ret = pinctrl_utils_add_map_configs(pctldev, map, + reserved_maps, num_maps, group, + configs, num_configs, + PIN_MAP_TYPE_CONFIGS_GROUP); + if (ret < 0) + goto exit; + } + } + + ret = 0; + +exit: + kfree(configs); + return ret; +} + +static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np_config, + struct pinctrl_map **map, + unsigned *num_maps) +{ + unsigned reserved_maps; + struct device_node *np; + int ret; + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + for_each_child_of_node(np_config, np) { + ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); + if (ret < 0) { + pinctrl_utils_dt_free_map(pctldev, *map, + *num_maps); + of_node_put(np); + return ret; + } + } + + return 0; +} + +static const struct pinctrl_ops tegra_pinctrl_ops = { + .get_groups_count = tegra_pinctrl_get_groups_count, + .get_group_name = tegra_pinctrl_get_group_name, + .get_group_pins = tegra_pinctrl_get_group_pins, +#ifdef CONFIG_DEBUG_FS + .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, +}; + +static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->nfunctions; +} + +static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev, + unsigned function) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + return pmx->soc->functions[function].name; +} + +static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, + unsigned function, + const char * const **groups, + unsigned * const num_groups) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + + *groups = pmx->soc->functions[function].groups; + *num_groups = pmx->soc->functions[function].ngroups; + + return 0; +} + +static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev, + unsigned function, + unsigned group) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *g; + int i; + u32 val; + + g = &pmx->soc->groups[group]; + + if (WARN_ON(g->mux_reg < 0)) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(g->funcs); i++) { + if (g->funcs[i] == function) + break; + } + if (WARN_ON(i == ARRAY_SIZE(g->funcs))) + return -EINVAL; + + val = pmx_readl(pmx, g->mux_bank, g->mux_reg); + val &= ~(0x3 << g->mux_bit); + val |= i << g->mux_bit; + pmx_writel(pmx, val, g->mux_bank, g->mux_reg); + + return 0; +} + +static const struct pinmux_ops tegra_pinmux_ops = { + .get_functions_count = tegra_pinctrl_get_funcs_count, + .get_function_name = tegra_pinctrl_get_func_name, + .get_function_groups = tegra_pinctrl_get_func_groups, + .set_mux = tegra_pinctrl_set_mux, +}; + +static int tegra_pinconf_reg(struct tegra_pmx *pmx, + const struct tegra_pingroup *g, + enum tegra_pinconf_param param, + bool report_err, + s8 *bank, s16 *reg, s8 *bit, s8 *width) +{ + switch (param) { + case TEGRA_PINCONF_PARAM_PULL: + *bank = g->pupd_bank; + *reg = g->pupd_reg; + *bit = g->pupd_bit; + *width = 2; + break; + case TEGRA_PINCONF_PARAM_TRISTATE: + *bank = g->tri_bank; + *reg = g->tri_reg; + *bit = g->tri_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_ENABLE_INPUT: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->einput_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_OPEN_DRAIN: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->odrain_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_LOCK: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->lock_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_IORESET: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->ioreset_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_RCV_SEL: + *bank = g->mux_bank; + *reg = g->mux_reg; + *bit = g->rcv_sel_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE: + if (pmx->soc->hsm_in_mux) { + *bank = g->mux_bank; + *reg = g->mux_reg; + } else { + *bank = g->drv_bank; + *reg = g->drv_reg; + } + *bit = g->hsm_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_SCHMITT: + if (pmx->soc->schmitt_in_mux) { + *bank = g->mux_bank; + *reg = g->mux_reg; + } else { + *bank = g->drv_bank; + *reg = g->drv_reg; + } + *bit = g->schmitt_bit; + *width = 1; + break; + case TEGRA_PINCONF_PARAM_LOW_POWER_MODE: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->lpmd_bit; + *width = 2; + break; + case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->drvdn_bit; + *width = g->drvdn_width; + break; + case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->drvup_bit; + *width = g->drvup_width; + break; + case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->slwf_bit; + *width = g->slwf_width; + break; + case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING: + *bank = g->drv_bank; + *reg = g->drv_reg; + *bit = g->slwr_bit; + *width = g->slwr_width; + break; + case TEGRA_PINCONF_PARAM_DRIVE_TYPE: + if (pmx->soc->drvtype_in_mux) { + *bank = g->mux_bank; + *reg = g->mux_reg; + } else { + *bank = g->drv_bank; + *reg = g->drv_reg; + } + *bit = g->drvtype_bit; + *width = 2; + break; + default: + dev_err(pmx->dev, "Invalid config param %04x\n", param); + return -ENOTSUPP; + } + + if (*reg < 0 || *bit > 31) { + if (report_err) { + const char *prop = "unknown"; + int i; + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + if (cfg_params[i].param == param) { + prop = cfg_params[i].property; + break; + } + } + + dev_err(pmx->dev, + "Config param %04x (%s) not supported on group %s\n", + param, prop, g->name); + } + return -ENOTSUPP; + } + + return 0; +} + +static int tegra_pinconf_get(struct pinctrl_dev *pctldev, + unsigned pin, unsigned long *config) +{ + dev_err(pctldev->dev, "pin_config_get op not supported\n"); + return -ENOTSUPP; +} + +static int tegra_pinconf_set(struct pinctrl_dev *pctldev, + unsigned pin, unsigned long *configs, + unsigned num_configs) +{ + dev_err(pctldev->dev, "pin_config_set op not supported\n"); + return -ENOTSUPP; +} + +static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev, + unsigned group, unsigned long *config) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config); + u16 arg; + const struct tegra_pingroup *g; + int ret; + s8 bank, bit, width; + s16 reg; + u32 val, mask; + + g = &pmx->soc->groups[group]; + + ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, + &width); + if (ret < 0) + return ret; + + val = pmx_readl(pmx, bank, reg); + mask = (1 << width) - 1; + arg = (val >> bit) & mask; + + *config = TEGRA_PINCONF_PACK(param, arg); + + return 0; +} + +static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned group, unsigned long *configs, + unsigned num_configs) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + enum tegra_pinconf_param param; + u16 arg; + const struct tegra_pingroup *g; + int ret, i; + s8 bank, bit, width; + s16 reg; + u32 val, mask; + + g = &pmx->soc->groups[group]; + + for (i = 0; i < num_configs; i++) { + param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]); + arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]); + + ret = tegra_pinconf_reg(pmx, g, param, true, &bank, ®, &bit, + &width); + if (ret < 0) + return ret; + + val = pmx_readl(pmx, bank, reg); + + /* LOCK can't be cleared */ + if (param == TEGRA_PINCONF_PARAM_LOCK) { + if ((val & BIT(bit)) && !arg) { + dev_err(pctldev->dev, "LOCK bit cannot be cleared\n"); + return -EINVAL; + } + } + + /* Special-case Boolean values; allow any non-zero as true */ + if (width == 1) + arg = !!arg; + + /* Range-check user-supplied value */ + mask = (1 << width) - 1; + if (arg & ~mask) { + dev_err(pctldev->dev, + "config %lx: %x too big for %d bit register\n", + configs[i], arg, width); + return -EINVAL; + } + + /* Update register */ + val &= ~(mask << bit); + val |= arg << bit; + pmx_writel(pmx, val, bank, reg); + } /* for each config */ + + return 0; +} + +#ifdef CONFIG_DEBUG_FS +static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned offset) +{ +} + +static const char *strip_prefix(const char *s) +{ + const char *comma = strchr(s, ','); + if (!comma) + return s; + + return comma + 1; +} + +static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned group) +{ + struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); + const struct tegra_pingroup *g; + int i, ret; + s8 bank, bit, width; + s16 reg; + u32 val; + + g = &pmx->soc->groups[group]; + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false, + &bank, ®, &bit, &width); + if (ret < 0) + continue; + + val = pmx_readl(pmx, bank, reg); + val >>= bit; + val &= (1 << width) - 1; + + seq_printf(s, "\n\t%s=%u", + strip_prefix(cfg_params[i].property), val); + } +} + +static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned long config) +{ + enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config); + u16 arg = TEGRA_PINCONF_UNPACK_ARG(config); + const char *pname = "unknown"; + int i; + + for (i = 0; i < ARRAY_SIZE(cfg_params); i++) { + if (cfg_params[i].param == param) { + pname = cfg_params[i].property; + break; + } + } + + seq_printf(s, "%s=%d", strip_prefix(pname), arg); +} +#endif + +static const struct pinconf_ops tegra_pinconf_ops = { + .pin_config_get = tegra_pinconf_get, + .pin_config_set = tegra_pinconf_set, + .pin_config_group_get = tegra_pinconf_group_get, + .pin_config_group_set = tegra_pinconf_group_set, +#ifdef CONFIG_DEBUG_FS + .pin_config_dbg_show = tegra_pinconf_dbg_show, + .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show, + .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show, +#endif +}; + +static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = { + .name = "Tegra GPIOs", + .id = 0, + .base = 0, +}; + +static struct pinctrl_desc tegra_pinctrl_desc = { + .pctlops = &tegra_pinctrl_ops, + .pmxops = &tegra_pinmux_ops, + .confops = &tegra_pinconf_ops, + .owner = THIS_MODULE, +}; + +static bool gpio_node_has_range(void) +{ + struct device_node *np; + bool has_prop = false; + + np = of_find_compatible_node(NULL, NULL, "nvidia,tegra30-gpio"); + if (!np) + return has_prop; + + has_prop = of_find_property(np, "gpio-ranges", NULL); + + of_node_put(np); + + return has_prop; +} + +int tegra_pinctrl_probe(struct platform_device *pdev, + const struct tegra_pinctrl_soc_data *soc_data) +{ + struct tegra_pmx *pmx; + struct resource *res; + int i; + const char **group_pins; + int fn, gn, gfn; + + pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL); + if (!pmx) { + dev_err(&pdev->dev, "Can't alloc tegra_pmx\n"); + return -ENOMEM; + } + pmx->dev = &pdev->dev; + pmx->soc = soc_data; + + /* + * Each mux group will appear in 4 functions' list of groups. + * This over-allocates slightly, since not all groups are mux groups. + */ + pmx->group_pins = devm_kzalloc(&pdev->dev, + soc_data->ngroups * 4 * sizeof(*pmx->group_pins), + GFP_KERNEL); + if (!pmx->group_pins) + return -ENOMEM; + + group_pins = pmx->group_pins; + for (fn = 0; fn < soc_data->nfunctions; fn++) { + struct tegra_function *func = &soc_data->functions[fn]; + + func->groups = group_pins; + + for (gn = 0; gn < soc_data->ngroups; gn++) { + const struct tegra_pingroup *g = &soc_data->groups[gn]; + + if (g->mux_reg == -1) + continue; + + for (gfn = 0; gfn < 4; gfn++) + if (g->funcs[gfn] == fn) + break; + if (gfn == 4) + continue; + + BUG_ON(group_pins - pmx->group_pins >= + soc_data->ngroups * 4); + *group_pins++ = g->name; + func->ngroups++; + } + } + + tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios; + tegra_pinctrl_desc.name = dev_name(&pdev->dev); + tegra_pinctrl_desc.pins = pmx->soc->pins; + tegra_pinctrl_desc.npins = pmx->soc->npins; + + for (i = 0; ; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + break; + } + pmx->nbanks = i; + + pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs), + GFP_KERNEL); + if (!pmx->regs) { + dev_err(&pdev->dev, "Can't alloc regs pointer\n"); + return -ENOMEM; + } + + for (i = 0; i < pmx->nbanks; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pmx->regs[i])) + return PTR_ERR(pmx->regs[i]); + } + + pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx); + if (IS_ERR(pmx->pctl)) { + dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); + return PTR_ERR(pmx->pctl); + } + + if (!gpio_node_has_range()) + pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range); + + platform_set_drvdata(pdev, pmx); + + dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n"); + + 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 new file mode 100644 index 000000000000..1615db7e3a4b --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra.h @@ -0,0 +1,194 @@ +/* + * Driver for the NVIDIA Tegra pinmux + * + * Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. + * + * 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. + */ + +#ifndef __PINMUX_TEGRA_H__ +#define __PINMUX_TEGRA_H__ + +enum tegra_pinconf_param { + /* argument: tegra_pinconf_pull */ + TEGRA_PINCONF_PARAM_PULL, + /* argument: tegra_pinconf_tristate */ + TEGRA_PINCONF_PARAM_TRISTATE, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_ENABLE_INPUT, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_OPEN_DRAIN, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_LOCK, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_IORESET, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_RCV_SEL, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_SCHMITT, + /* argument: Boolean */ + TEGRA_PINCONF_PARAM_LOW_POWER_MODE, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, + /* argument: Integer, range is HW-dependant */ + TEGRA_PINCONF_PARAM_DRIVE_TYPE, +}; + +enum tegra_pinconf_pull { + TEGRA_PINCONFIG_PULL_NONE, + TEGRA_PINCONFIG_PULL_DOWN, + TEGRA_PINCONFIG_PULL_UP, +}; + +enum tegra_pinconf_tristate { + TEGRA_PINCONFIG_DRIVEN, + TEGRA_PINCONFIG_TRISTATE, +}; + +#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_)) +#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) +#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) + +/** + * struct tegra_function - Tegra pinctrl mux function + * @name: The name of the function, exported to pinctrl core. + * @groups: An array of pin groups that may select this function. + * @ngroups: The number of entries in @groups. + */ +struct tegra_function { + const char *name; + const char **groups; + unsigned ngroups; +}; + +/** + * struct tegra_pingroup - Tegra pin group + * @name The name of the pin group. + * @pins An array of pin IDs included in this pin group. + * @npins The number of entries in @pins. + * @funcs The mux functions which can be muxed onto this group. + * @mux_reg: Mux register offset. + * This register contains the mux, einput, odrain, lock, + * ioreset, rcv_sel parameters. + * @mux_bank: Mux register bank. + * @mux_bit: Mux register bit. + * @pupd_reg: Pull-up/down register offset. + * @pupd_bank: Pull-up/down register bank. + * @pupd_bit: Pull-up/down register bit. + * @tri_reg: Tri-state register offset. + * @tri_bank: Tri-state register bank. + * @tri_bit: Tri-state register bit. + * @einput_bit: Enable-input register bit. + * @odrain_bit: Open-drain register bit. + * @lock_bit: Lock register bit. + * @ioreset_bit: IO reset register bit. + * @rcv_sel_bit: Receiver select bit. + * @drv_reg: Drive fields register offset. + * This register contains hsm, schmitt, lpmd, drvdn, + * drvup, slwr, slwf, and drvtype parameters. + * @drv_bank: Drive fields register bank. + * @hsm_bit: High Speed Mode register bit. + * @schmitt_bit: Scmitt register bit. + * @lpmd_bit: Low Power Mode register bit. + * @drvdn_bit: Drive Down register bit. + * @drvdn_width: Drive Down field width. + * @drvup_bit: Drive Up register bit. + * @drvup_width: Drive Up field width. + * @slwr_bit: Slew Rising register bit. + * @slwr_width: Slew Rising field width. + * @slwf_bit: Slew Falling register bit. + * @slwf_width: Slew Falling field width. + * @drvtype_bit: Drive type register bit. + * + * -1 in a *_reg field means that feature is unsupported for this group. + * *_bank and *_reg values are irrelevant when *_reg is -1. + * When *_reg is valid, *_bit may be -1 to indicate an unsupported feature. + * + * A representation of a group of pins (possibly just one pin) in the Tegra + * pin controller. Each group allows some parameter or parameters to be + * configured. The most common is mux function selection. Many others exist + * such as pull-up/down, tri-state, etc. Tegra's pin controller is complex; + * certain groups may only support configuring certain parameters, hence + * each parameter is optional. + */ +struct tegra_pingroup { + const char *name; + const unsigned *pins; + u8 npins; + u8 funcs[4]; + s16 mux_reg; + s16 pupd_reg; + s16 tri_reg; + s16 drv_reg; + u32 mux_bank:2; + u32 pupd_bank:2; + u32 tri_bank:2; + u32 drv_bank:2; + s32 mux_bit:6; + s32 pupd_bit:6; + s32 tri_bit:6; + s32 einput_bit:6; + s32 odrain_bit:6; + s32 lock_bit:6; + s32 ioreset_bit:6; + s32 rcv_sel_bit:6; + s32 hsm_bit:6; + s32 schmitt_bit:6; + s32 lpmd_bit:6; + s32 drvdn_bit:6; + s32 drvup_bit:6; + s32 slwr_bit:6; + s32 slwf_bit:6; + s32 drvtype_bit:6; + s32 drvdn_width:6; + s32 drvup_width:6; + s32 slwr_width:6; + s32 slwf_width:6; +}; + +/** + * struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration + * @ngpios: The number of GPIO pins the pin controller HW affects. + * @pins: An array describing all pins the pin controller affects. + * All pins which are also GPIOs must be listed first within the + * array, and be numbered identically to the GPIO controller's + * numbering. + * @npins: The numbmer of entries in @pins. + * @functions: An array describing all mux functions the SoC supports. + * @nfunctions: The numbmer of entries in @functions. + * @groups: An array describing all pin groups the pin SoC supports. + * @ngroups: The numbmer of entries in @groups. + */ +struct tegra_pinctrl_soc_data { + unsigned ngpios; + const struct pinctrl_pin_desc *pins; + unsigned npins; + struct tegra_function *functions; + unsigned nfunctions; + const struct tegra_pingroup *groups; + unsigned ngroups; + bool hsm_in_mux; + bool schmitt_in_mux; + bool drvtype_in_mux; +}; + +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 new file mode 100644 index 000000000000..05e49d5137ab --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra114.c @@ -0,0 +1,1872 @@ +/* + * Pinctrl data for the NVIDIA Tegra114 pinmux + * + * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * + * 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 "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) +#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) +#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) +#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) +#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) +#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) +#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) +#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) +#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) +#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) +#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) +#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) +#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) +#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) +#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) +#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) +#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) +#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) +#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) +#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) +#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) +#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) +#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) +#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) +#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) +#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) +#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) +#define TEGRA_PIN_GMI_DQS_P_PJ3 _GPIO(75) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) +#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) +#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) +#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) +#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) +#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) +#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) +#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) +#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) +#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) +#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) +#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) +#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) +#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) +#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) +#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) +#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) +#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_RESET_OUT_N _PIN(3) +#define TEGRA_PIN_OWR _PIN(4) +#define TEGRA_PIN_JTAG_RTCK _PIN(5) +#define TEGRA_PIN_CLK_32K_IN _PIN(6) +#define TEGRA_PIN_GMI_CLK_LB _PIN(7) + +static const struct pinctrl_pin_desc tegra114_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), + PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), + PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), + PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), + PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), + PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), + PINCTRL_PIN(TEGRA_PIN_GMI_DQS_P_PJ3, "GMI_DQS_P PJ3"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), + PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned gmi_a17_pb0_pins[] = { + TEGRA_PIN_GMI_A17_PB0, +}; + +static const unsigned gmi_a18_pb1_pins[] = { + TEGRA_PIN_GMI_A18_PB1, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned gmi_wp_n_pc7_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned gmi_ad0_pg0_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, +}; + +static const unsigned gmi_ad1_pg1_pins[] = { + TEGRA_PIN_GMI_AD1_PG1, +}; + +static const unsigned gmi_ad2_pg2_pins[] = { + TEGRA_PIN_GMI_AD2_PG2, +}; + +static const unsigned gmi_ad3_pg3_pins[] = { + TEGRA_PIN_GMI_AD3_PG3, +}; + +static const unsigned gmi_ad4_pg4_pins[] = { + TEGRA_PIN_GMI_AD4_PG4, +}; + +static const unsigned gmi_ad5_pg5_pins[] = { + TEGRA_PIN_GMI_AD5_PG5, +}; + +static const unsigned gmi_ad6_pg6_pins[] = { + TEGRA_PIN_GMI_AD6_PG6, +}; + +static const unsigned gmi_ad7_pg7_pins[] = { + TEGRA_PIN_GMI_AD7_PG7, +}; + +static const unsigned gmi_ad8_ph0_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, +}; + +static const unsigned gmi_ad9_ph1_pins[] = { + TEGRA_PIN_GMI_AD9_PH1, +}; + +static const unsigned gmi_ad10_ph2_pins[] = { + TEGRA_PIN_GMI_AD10_PH2, +}; + +static const unsigned gmi_ad11_ph3_pins[] = { + TEGRA_PIN_GMI_AD11_PH3, +}; + +static const unsigned gmi_ad12_ph4_pins[] = { + TEGRA_PIN_GMI_AD12_PH4, +}; + +static const unsigned gmi_ad13_ph5_pins[] = { + TEGRA_PIN_GMI_AD13_PH5, +}; + +static const unsigned gmi_ad14_ph6_pins[] = { + TEGRA_PIN_GMI_AD14_PH6, +}; + +static const unsigned gmi_ad15_ph7_pins[] = { + TEGRA_PIN_GMI_AD15_PH7, +}; + +static const unsigned gmi_wr_n_pi0_pins[] = { + TEGRA_PIN_GMI_WR_N_PI0, +}; + +static const unsigned gmi_oe_n_pi1_pins[] = { + TEGRA_PIN_GMI_OE_N_PI1, +}; + +static const unsigned gmi_cs6_n_pi3_pins[] = { + TEGRA_PIN_GMI_CS6_N_PI3, +}; + +static const unsigned gmi_rst_n_pi4_pins[] = { + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned gmi_iordy_pi5_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, +}; + +static const unsigned gmi_cs7_n_pi6_pins[] = { + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned gmi_wait_pi7_pins[] = { + TEGRA_PIN_GMI_WAIT_PI7, +}; + +static const unsigned gmi_cs0_n_pj0_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned gmi_cs1_n_pj2_pins[] = { + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned gmi_dqs_p_pj3_pins[] = { + TEGRA_PIN_GMI_DQS_P_PJ3, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned gmi_a16_pj7_pins[] = { + TEGRA_PIN_GMI_A16_PJ7, +}; + +static const unsigned gmi_adv_n_pk0_pins[] = { + TEGRA_PIN_GMI_ADV_N_PK0, +}; + +static const unsigned gmi_clk_pk1_pins[] = { + TEGRA_PIN_GMI_CLK_PK1, +}; + +static const unsigned gmi_cs4_n_pk2_pins[] = { + TEGRA_PIN_GMI_CS4_N_PK2, +}; + +static const unsigned gmi_cs2_n_pk3_pins[] = { + TEGRA_PIN_GMI_CS2_N_PK3, +}; + +static const unsigned gmi_cs3_n_pk4_pins[] = { + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned gmi_a19_pk7_pins[] = { + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned usb_vbus_en0_pn4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, +}; + +static const unsigned usb_vbus_en1_pn5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned sdmmc3_cd_n_pv2_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned sdmmc1_wp_n_pv3_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned gpio_w2_aud_pw2_pins[] = { + TEGRA_PIN_GPIO_W2_AUD_PW2, +}; + +static const unsigned gpio_w3_aud_pw3_pins[] = { + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned clk1_out_pw4_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned dvfs_pwm_px0_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, +}; + +static const unsigned gpio_x1_aud_px1_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PX1, +}; + +static const unsigned dvfs_clk_px2_pins[] = { + TEGRA_PIN_DVFS_CLK_PX2, +}; + +static const unsigned gpio_x3_aud_px3_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PX3, +}; + +static const unsigned gpio_x4_aud_px4_pins[] = { + TEGRA_PIN_GPIO_X4_AUD_PX4, +}; + +static const unsigned gpio_x5_aud_px5_pins[] = { + TEGRA_PIN_GPIO_X5_AUD_PX5, +}; + +static const unsigned gpio_x6_aud_px6_pins[] = { + TEGRA_PIN_GPIO_X6_AUD_PX6, +}; + +static const unsigned gpio_x7_aud_px7_pins[] = { + TEGRA_PIN_GPIO_X7_AUD_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned sys_clk_req_pz5_pins[] = { + TEGRA_PIN_SYS_CLK_REQ_PZ5, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned clk1_req_pee2_pins[] = { + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, +}; + +static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned reset_out_n_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned gmi_clk_lb_pins[] = { + TEGRA_PIN_GMI_CLK_LB, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_WR_N_PI0, + TEGRA_PIN_GMI_OE_N_PI1, + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_RST_N_PI4, + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_DQS_P_PJ3, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_GMI_A17_PB0, + TEGRA_PIN_GMI_A18_PB1, + TEGRA_PIN_GMI_CS1_N_PJ2, + TEGRA_PIN_GMI_A16_PJ7, + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, + TEGRA_PIN_GPIO_X1_AUD_PX1, + TEGRA_PIN_DVFS_CLK_PX2, + TEGRA_PIN_GPIO_X3_AUD_PX3, + TEGRA_PIN_GPIO_X4_AUD_PX4, + TEGRA_PIN_GPIO_X5_AUD_PX5, + TEGRA_PIN_GPIO_X6_AUD_PX6, + TEGRA_PIN_GPIO_X7_AUD_PX7, + TEGRA_PIN_GPIO_W2_AUD_PW2, + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, + TEGRA_PIN_SDMMC4_CMD_PT7, + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_dev3_pins[] = { +}; + +static const unsigned drive_cec_pins[] = { +}; + +static const unsigned drive_at6_pins[] = { +}; + +static const unsigned drive_dap5_pins[] = { +}; + +static const unsigned drive_usb_vbus_en_pins[] = { +}; + +static const unsigned drive_ao3_pins[] = { +}; + +static const unsigned drive_hv0_pins[] = { +}; + +static const unsigned drive_sdio4_pins[] = { +}; + +static const unsigned drive_ao0_pins[] = { +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK, + TEGRA_MUX_CLK12, + TEGRA_MUX_CPU, + TEGRA_MUX_DAP, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYA_ALT, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DTV, + TEGRA_MUX_EMC_DLL, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_NAND, + TEGRA_MUX_NAND_ALT, + TEGRA_MUX_OWR, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWRON, + TEGRA_MUX_RESET_OUT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SOC, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_SYSCLK, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_ULPI, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT3, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra114_functions[] = { + FUNCTION(blink), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk), + FUNCTION(clk12), + FUNCTION(cpu), + FUNCTION(dap), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displaya_alt), + FUNCTION(displayb), + FUNCTION(dtv), + FUNCTION(emc_dll), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(nand), + FUNCTION(nand_alt), + FUNCTION(owr), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwron), + FUNCTION(reset_out_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(soc), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(sysclk), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(ulpi), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt3), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 5, \ + .odrain_bit = PINGROUP_BIT_##od(6), \ + .lock_bit = 7, \ + .ioreset_bit = PINGROUP_BIT_##ior(8), \ + .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ + .drv_reg = -1, \ + } + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ + drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ + slwf_b, slwf_w, drvtype) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ + } + +static const struct tegra_pingroup tegra114_groups[] = { + /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), + PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), + PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), + PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), + PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), + PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), + PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3038, N, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x303c, N, N, N), + PINGROUP(pv0, USB, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), + PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), + PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), + PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, RSVD3, SPI4, 0x316c, N, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, RSVD3, SPI4, 0x3170, N, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, RSVD3, SPI4, 0x3174, N, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, RSVD3, SPI4, 0x3178, N, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, SPI4, 0x317c, N, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, DISPLAYA, 0x3180, N, N, N), + PINGROUP(pu0, OWR, UARTA, RSVD3, RSVD4, 0x3184, N, N, N), + PINGROUP(pu1, RSVD1, UARTA, RSVD3, RSVD4, 0x3188, N, N, N), + PINGROUP(pu2, RSVD1, UARTA, RSVD3, RSVD4, 0x318c, N, N, N), + PINGROUP(pu3, PWM0, UARTA, DISPLAYA, DISPLAYB, 0x3190, N, N, N), + PINGROUP(pu4, PWM1, UARTA, DISPLAYA, DISPLAYB, 0x3194, N, N, N), + PINGROUP(pu5, PWM2, UARTA, DISPLAYA, DISPLAYB, 0x3198, N, N, N), + PINGROUP(pu6, PWM3, UARTA, USB, DISPLAYB, 0x319c, N, N, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), + PINGROUP(dap4_fs_pp4, I2S3, RSVD2, DTV, RSVD4, 0x31a8, N, N, N), + PINGROUP(dap4_din_pp5, I2S3, RSVD2, RSVD3, RSVD4, 0x31ac, N, N, N), + PINGROUP(dap4_dout_pp6, I2S3, RSVD2, DTV, RSVD4, 0x31b0, N, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, RSVD3, RSVD4, 0x31b4, N, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), + PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N, N), + PINGROUP(gmi_iordy_pi5, SDMMC2, RSVD2, GMI, TRACE, 0x31c4, N, N, N), + PINGROUP(gmi_wait_pi7, SPI4, NAND, GMI, DTV, 0x31c8, N, N, N), + PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, TRACE, 0x31cc, N, N, N), + PINGROUP(gmi_clk_pk1, SDMMC2, NAND, GMI, TRACE, 0x31d0, N, N, N), + PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, USB, 0x31d4, N, N, N), + PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, SOC, 0x31d8, N, N, N), + PINGROUP(gmi_cs2_n_pk3, SDMMC2, NAND, GMI, TRACE, 0x31dc, N, N, N), + PINGROUP(gmi_cs3_n_pk4, SDMMC2, NAND, GMI, GMI_ALT, 0x31e0, N, N, N), + PINGROUP(gmi_cs4_n_pk2, USB, NAND, GMI, TRACE, 0x31e4, N, N, N), + PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SPI4, 0x31e8, N, N, N), + PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, SDMMC2, 0x31ec, N, N, N), + PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N, N), + PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N, N), + PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N, N), + PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N, N), + PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N, N), + PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, SPI4, 0x3204, N, N, N), + PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, SPI4, 0x3208, N, N, N), + PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, SPI4, 0x320c, N, N, N), + PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, DTV, 0x3210, N, N, N), + PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, CLDVFS, 0x3214, N, N, N), + PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, CLDVFS, 0x3218, N, N, N), + PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, USB, 0x321c, N, N, N), + PINGROUP(gmi_ad12_ph4, SDMMC2, NAND, GMI, RSVD4, 0x3220, N, N, N), + PINGROUP(gmi_ad13_ph5, SDMMC2, NAND, GMI, RSVD4, 0x3224, N, N, N), + PINGROUP(gmi_ad14_ph6, SDMMC2, NAND, GMI, DTV, 0x3228, N, N, N), + PINGROUP(gmi_ad15_ph7, SDMMC2, NAND, GMI, DTV, 0x322c, N, N, N), + PINGROUP(gmi_a16_pj7, UARTD, TRACE, GMI, GMI_ALT, 0x3230, N, N, N), + PINGROUP(gmi_a17_pb0, UARTD, RSVD2, GMI, TRACE, 0x3234, N, N, N), + PINGROUP(gmi_a18_pb1, UARTD, RSVD2, GMI, TRACE, 0x3238, N, N, N), + PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, TRACE, 0x323c, N, N, N), + PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, SPI4, 0x3240, N, N, N), + PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, SOC, 0x3244, N, N, N), + PINGROUP(gmi_dqs_p_pj3, SDMMC2, NAND, GMI, TRACE, 0x3248, N, N, N), + PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N, N), + PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), + PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), + PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), + PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), + PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), + PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), + PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), + PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), + PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, GMI, RSVD4, 0x3274, N, Y, N), + PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), + PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, RSVD4, 0x3284, N, N, N), + PINGROUP(pcc1, I2S4, RSVD2, RSVD3, RSVD4, 0x3288, N, N, N), + PINGROUP(pbb0, I2S4, VI, VI_ALT1, VI_ALT3, 0x328c, N, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, RSVD4, 0x3290, Y, N, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, RSVD4, 0x3294, Y, N, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, RSVD4, 0x3298, N, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, RSVD4, 0x329c, N, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, RSVD4, 0x32a0, N, N, N), + PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, RSVD4, 0x32a4, N, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, RSVD4, 0x32a8, N, N, N), + PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N, N), + PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), + PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), + PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), + PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), + PINGROUP(kb_row3_pr3, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32c8, N, N, N), + PINGROUP(kb_row4_pr4, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32cc, N, N, N), + PINGROUP(kb_row5_pr5, KBC, DISPLAYA, SPI2, DISPLAYB, 0x32d0, N, N, N), + PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), + PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), + PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), + PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), + PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), + PINGROUP(kb_col0_pq0, KBC, USB, SPI2, EMC_DLL, 0x32fc, N, N, N), + PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, EMC_DLL, 0x3300, N, N, N), + PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), + PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), + PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), + PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC1, RSVD4, 0x3310, N, N, N), + PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, RSVD4, 0x3314, N, N, N), + PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, RSVD4, 0x3318, N, N, N), + PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), + PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N, N), + PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), + PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), + PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), + PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), + PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, RSVD4, 0x3340, N, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), + PINGROUP(clk1_req_pee2, DAP, DAP1, RSVD3, RSVD4, 0x3348, N, N, N), + PINGROUP(clk1_out_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), + PINGROUP(spdif_in_pk6, SPDIF, USB, RSVD3, RSVD4, 0x3350, N, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, RSVD4, 0x3354, N, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, RSVD4, 0x3358, N, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, RSVD4, 0x335c, N, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, RSVD4, 0x3360, N, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, RSVD4, 0x3364, N, N, N), + PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, RSVD3, RSVD4, 0x3368, N, N, N), + PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, RSVD3, RSVD4, 0x336c, N, N, N), + PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, RSVD3, RSVD4, 0x3370, N, N, N), + PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, RSVD3, RSVD4, 0x3374, N, N, N), + PINGROUP(gpio_x4_aud_px4, RSVD1, SPI1, SPI2, DAP2, 0x3378, N, N, N), + PINGROUP(gpio_x5_aud_px5, RSVD1, SPI1, SPI2, RSVD4, 0x337c, N, N, N), + PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, RSVD4, 0x3380, N, N, N), + PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), + PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), + PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), + PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), + PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), + PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), + PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), + PINGROUP(hdmi_cec_pee3, CEC, SDMMC3, RSVD3, SOC, 0x33e0, Y, N, N), + PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), + PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), + PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), + PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), + PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), + PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), + PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), + PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), + PINGROUP(gmi_clk_lb, SDMMC2, NAND, GMI, RSVD4, 0x3404, N, N, N), + PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), + + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at1, 0x870, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at2, 0x874, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at3, 0x878, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at4, 0x87c, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, -1, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gma, 0x900, 2, 3, -1, 14, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, Y), + DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao3, 0x9a0, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(hv0, 0x9a4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(sdio4, 0x9a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao0, 0x9ac, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), +}; + +static const struct tegra_pinctrl_soc_data tegra114_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra114_pins, + .npins = ARRAY_SIZE(tegra114_pins), + .functions = tegra114_functions, + .nfunctions = ARRAY_SIZE(tegra114_functions), + .groups = tegra114_groups, + .ngroups = ARRAY_SIZE(tegra114_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra114_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra114_pinctrl); +} + +static const struct of_device_id tegra114_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra114-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra114_pinctrl_of_match); + +static struct platform_driver tegra114_pinctrl_driver = { + .driver = { + .name = "tegra114-pinctrl", + .of_match_table = tegra114_pinctrl_of_match, + }, + .probe = tegra114_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra114_pinctrl_driver); + +MODULE_AUTHOR("Pritesh Raithatha "); +MODULE_DESCRIPTION("NVIDIA Tegra114 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra124.c b/drivers/pinctrl/tegra/pinctrl-tegra124.c new file mode 100644 index 000000000000..7cd44c7c296d --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra124.c @@ -0,0 +1,2084 @@ +/* + * Pinctrl data for the NVIDIA Tegra124 pinmux + * + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. + * + * 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 "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_PB0 _GPIO(8) +#define TEGRA_PIN_PB1 _GPIO(9) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_PC7 _GPIO(23) +#define TEGRA_PIN_PG0 _GPIO(48) +#define TEGRA_PIN_PG1 _GPIO(49) +#define TEGRA_PIN_PG2 _GPIO(50) +#define TEGRA_PIN_PG3 _GPIO(51) +#define TEGRA_PIN_PG4 _GPIO(52) +#define TEGRA_PIN_PG5 _GPIO(53) +#define TEGRA_PIN_PG6 _GPIO(54) +#define TEGRA_PIN_PG7 _GPIO(55) +#define TEGRA_PIN_PH0 _GPIO(56) +#define TEGRA_PIN_PH1 _GPIO(57) +#define TEGRA_PIN_PH2 _GPIO(58) +#define TEGRA_PIN_PH3 _GPIO(59) +#define TEGRA_PIN_PH4 _GPIO(60) +#define TEGRA_PIN_PH5 _GPIO(61) +#define TEGRA_PIN_PH6 _GPIO(62) +#define TEGRA_PIN_PH7 _GPIO(63) +#define TEGRA_PIN_PI0 _GPIO(64) +#define TEGRA_PIN_PI1 _GPIO(65) +#define TEGRA_PIN_PI2 _GPIO(66) +#define TEGRA_PIN_PI3 _GPIO(67) +#define TEGRA_PIN_PI4 _GPIO(68) +#define TEGRA_PIN_PI5 _GPIO(69) +#define TEGRA_PIN_PI6 _GPIO(70) +#define TEGRA_PIN_PI7 _GPIO(71) +#define TEGRA_PIN_PJ0 _GPIO(72) +#define TEGRA_PIN_PJ2 _GPIO(74) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_PJ7 _GPIO(79) +#define TEGRA_PIN_PK0 _GPIO(80) +#define TEGRA_PIN_PK1 _GPIO(81) +#define TEGRA_PIN_PK2 _GPIO(82) +#define TEGRA_PIN_PK3 _GPIO(83) +#define TEGRA_PIN_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_PK7 _GPIO(87) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_USB_VBUS_EN0_PN4 _GPIO(108) +#define TEGRA_PIN_USB_VBUS_EN1_PN5 _GPIO(109) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_KB_ROW16_PT0 _GPIO(152) +#define TEGRA_PIN_KB_ROW17_PT1 _GPIO(153) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_SDMMC3_CD_N_PV2 _GPIO(170) +#define TEGRA_PIN_SDMMC1_WP_N_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_GPIO_W2_AUD_PW2 _GPIO(178) +#define TEGRA_PIN_GPIO_W3_AUD_PW3 _GPIO(179) +#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_DVFS_PWM_PX0 _GPIO(184) +#define TEGRA_PIN_GPIO_X1_AUD_PX1 _GPIO(185) +#define TEGRA_PIN_DVFS_CLK_PX2 _GPIO(186) +#define TEGRA_PIN_GPIO_X3_AUD_PX3 _GPIO(187) +#define TEGRA_PIN_GPIO_X4_AUD_PX4 _GPIO(188) +#define TEGRA_PIN_GPIO_X5_AUD_PX5 _GPIO(189) +#define TEGRA_PIN_GPIO_X6_AUD_PX6 _GPIO(190) +#define TEGRA_PIN_GPIO_X7_AUD_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) +#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) +#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_DAP_MCLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4 _GPIO(244) +#define TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5 _GPIO(245) +#define TEGRA_PIN_DP_HPD_PFF0 _GPIO(248) +#define TEGRA_PIN_USB_VBUS_EN2_PFF1 _GPIO(249) +#define TEGRA_PIN_PFF2 _GPIO(250) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PFF2 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_GMI_CLK_LB _PIN(3) +#define TEGRA_PIN_RESET_OUT_N _PIN(4) +#define TEGRA_PIN_OWR _PIN(5) +#define TEGRA_PIN_CLK_32K_IN _PIN(6) +#define TEGRA_PIN_JTAG_RTCK _PIN(7) +#define TEGRA_PIN_DSI_B_CLK_P _PIN(8) +#define TEGRA_PIN_DSI_B_CLK_N _PIN(9) +#define TEGRA_PIN_DSI_B_D0_P _PIN(10) +#define TEGRA_PIN_DSI_B_D0_N _PIN(11) +#define TEGRA_PIN_DSI_B_D1_P _PIN(12) +#define TEGRA_PIN_DSI_B_D1_N _PIN(13) +#define TEGRA_PIN_DSI_B_D2_P _PIN(14) +#define TEGRA_PIN_DSI_B_D2_N _PIN(15) +#define TEGRA_PIN_DSI_B_D3_P _PIN(16) +#define TEGRA_PIN_DSI_B_D3_N _PIN(17) + +static const struct pinctrl_pin_desc tegra124_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_PB0, "PB0"), + PINCTRL_PIN(TEGRA_PIN_PB1, "PB1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_PC7, "PC7"), + PINCTRL_PIN(TEGRA_PIN_PG0, "PG0"), + PINCTRL_PIN(TEGRA_PIN_PG1, "PG1"), + PINCTRL_PIN(TEGRA_PIN_PG2, "PG2"), + PINCTRL_PIN(TEGRA_PIN_PG3, "PG3"), + PINCTRL_PIN(TEGRA_PIN_PG4, "PG4"), + PINCTRL_PIN(TEGRA_PIN_PG5, "PG5"), + PINCTRL_PIN(TEGRA_PIN_PG6, "PG6"), + PINCTRL_PIN(TEGRA_PIN_PG7, "PG7"), + PINCTRL_PIN(TEGRA_PIN_PH0, "PH0"), + PINCTRL_PIN(TEGRA_PIN_PH1, "PH1"), + PINCTRL_PIN(TEGRA_PIN_PH2, "PH2"), + PINCTRL_PIN(TEGRA_PIN_PH3, "PH3"), + PINCTRL_PIN(TEGRA_PIN_PH4, "PH4"), + PINCTRL_PIN(TEGRA_PIN_PH5, "PH5"), + PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), + PINCTRL_PIN(TEGRA_PIN_PH7, "PH7"), + PINCTRL_PIN(TEGRA_PIN_PI0, "PI0"), + PINCTRL_PIN(TEGRA_PIN_PI1, "PI1"), + PINCTRL_PIN(TEGRA_PIN_PI2, "PI2"), + PINCTRL_PIN(TEGRA_PIN_PI3, "PI3"), + PINCTRL_PIN(TEGRA_PIN_PI4, "PI4"), + PINCTRL_PIN(TEGRA_PIN_PI5, "PI5"), + PINCTRL_PIN(TEGRA_PIN_PI6, "PI6"), + PINCTRL_PIN(TEGRA_PIN_PI7, "PI7"), + PINCTRL_PIN(TEGRA_PIN_PJ0, "PJ0"), + PINCTRL_PIN(TEGRA_PIN_PJ2, "PJ2"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_PJ7, "PJ7"), + PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), + PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), + PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), + PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), + PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PN4, "USB_VBUS_EN0 PN4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PN5, "USB_VBUS_EN1 PN5"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW16_PT0, "KB_ROW16 PT0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW17_PT1, "KB_ROW17 PT1"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CD_N_PV2, "SDMMC3_CD_N PV2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_WP_N_PV3, "SDMMC1_WP_N PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W2_AUD_PW2, "GPIO_W2_AUD PW2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_W3_AUD_PW3, "GPIO_W3_AUD PW3"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PX0, "DVFS_PWM PX0"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PX1, "GPIO_X1_AUD PX1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PX2, "DVFS_CLK PX2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PX3, "GPIO_X3_AUD PX3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X4_AUD_PX4, "GPIO_X4_AUD PX4"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X5_AUD_PX5, "GPIO_X5_AUD PX5"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X6_AUD_PX6, "GPIO_X6_AUD PX6"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X7_AUD_PX7, "GPIO_X7_AUD PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_REQ_PEE2, "DAP_MCLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, "SDMMC3_CLK_LB_OUT PEE4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, "SDMMC3_CLK_LB_IN PEE5"), + PINCTRL_PIN(TEGRA_PIN_DP_HPD_PFF0, "DP_HPD PFF0"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN2_PFF1, "USB_VBUS_EN2 PFF1"), + PINCTRL_PIN(TEGRA_PIN_PFF2, "PFF2"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_LB, "GMI_CLK_LB"), + PINCTRL_PIN(TEGRA_PIN_RESET_OUT_N, "RESET_OUT_N"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_P, "DSI_B_CLK_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_CLK_N, "DSI_B_CLK_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_P, "DSI_B_D0_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D0_N, "DSI_B_D0_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_P, "DSI_B_D1_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D1_N, "DSI_B_D1_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_P, "DSI_B_D2_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D2_N, "DSI_B_D2_N"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_P, "DSI_B_D3_P"), + PINCTRL_PIN(TEGRA_PIN_DSI_B_D3_N, "DSI_B_D3_N"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned pb0_pins[] = { + TEGRA_PIN_PB0, +}; + +static const unsigned pb1_pins[] = { + TEGRA_PIN_PB1, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned pc7_pins[] = { + TEGRA_PIN_PC7, +}; + +static const unsigned pg0_pins[] = { + TEGRA_PIN_PG0, +}; + +static const unsigned pg1_pins[] = { + TEGRA_PIN_PG1, +}; + +static const unsigned pg2_pins[] = { + TEGRA_PIN_PG2, +}; + +static const unsigned pg3_pins[] = { + TEGRA_PIN_PG3, +}; + +static const unsigned pg4_pins[] = { + TEGRA_PIN_PG4, +}; + +static const unsigned pg5_pins[] = { + TEGRA_PIN_PG5, +}; + +static const unsigned pg6_pins[] = { + TEGRA_PIN_PG6, +}; + +static const unsigned pg7_pins[] = { + TEGRA_PIN_PG7, +}; + +static const unsigned ph0_pins[] = { + TEGRA_PIN_PH0, +}; + +static const unsigned ph1_pins[] = { + TEGRA_PIN_PH1, +}; + +static const unsigned ph2_pins[] = { + TEGRA_PIN_PH2, +}; + +static const unsigned ph3_pins[] = { + TEGRA_PIN_PH3, +}; + +static const unsigned ph4_pins[] = { + TEGRA_PIN_PH4, +}; + +static const unsigned ph5_pins[] = { + TEGRA_PIN_PH5, +}; + +static const unsigned ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned ph7_pins[] = { + TEGRA_PIN_PH7, +}; + +static const unsigned pi0_pins[] = { + TEGRA_PIN_PI0, +}; + +static const unsigned pi1_pins[] = { + TEGRA_PIN_PI1, +}; + +static const unsigned pi2_pins[] = { + TEGRA_PIN_PI2, +}; + +static const unsigned pi3_pins[] = { + TEGRA_PIN_PI3, +}; + +static const unsigned pi4_pins[] = { + TEGRA_PIN_PI4, +}; + +static const unsigned pi5_pins[] = { + TEGRA_PIN_PI5, +}; + +static const unsigned pi6_pins[] = { + TEGRA_PIN_PI6, +}; + +static const unsigned pi7_pins[] = { + TEGRA_PIN_PI7, +}; + +static const unsigned pj0_pins[] = { + TEGRA_PIN_PJ0, +}; + +static const unsigned pj2_pins[] = { + TEGRA_PIN_PJ2, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned pj7_pins[] = { + TEGRA_PIN_PJ7, +}; + +static const unsigned pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned usb_vbus_en0_pn4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, +}; + +static const unsigned usb_vbus_en1_pn5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned kb_row11_ps3_pins[] = { + TEGRA_PIN_KB_ROW11_PS3, +}; + +static const unsigned kb_row12_ps4_pins[] = { + TEGRA_PIN_KB_ROW12_PS4, +}; + +static const unsigned kb_row13_ps5_pins[] = { + TEGRA_PIN_KB_ROW13_PS5, +}; + +static const unsigned kb_row14_ps6_pins[] = { + TEGRA_PIN_KB_ROW14_PS6, +}; + +static const unsigned kb_row15_ps7_pins[] = { + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned kb_row16_pt0_pins[] = { + TEGRA_PIN_KB_ROW16_PT0, +}; + +static const unsigned kb_row17_pt1_pins[] = { + TEGRA_PIN_KB_ROW17_PT1, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned sdmmc3_cd_n_pv2_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, +}; + +static const unsigned sdmmc1_wp_n_pv3_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned gpio_w2_aud_pw2_pins[] = { + TEGRA_PIN_GPIO_W2_AUD_PW2, +}; + +static const unsigned gpio_w3_aud_pw3_pins[] = { + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned dap_mclk1_pw4_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned dvfs_pwm_px0_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, +}; + +static const unsigned gpio_x1_aud_px1_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PX1, +}; + +static const unsigned dvfs_clk_px2_pins[] = { + TEGRA_PIN_DVFS_CLK_PX2, +}; + +static const unsigned gpio_x3_aud_px3_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PX3, +}; + +static const unsigned gpio_x4_aud_px4_pins[] = { + TEGRA_PIN_GPIO_X4_AUD_PX4, +}; + +static const unsigned gpio_x5_aud_px5_pins[] = { + TEGRA_PIN_GPIO_X5_AUD_PX5, +}; + +static const unsigned gpio_x6_aud_px6_pins[] = { + TEGRA_PIN_GPIO_X6_AUD_PX6, +}; + +static const unsigned gpio_x7_aud_px7_pins[] = { + TEGRA_PIN_GPIO_X7_AUD_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned pex_l0_rst_n_pdd1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, +}; + +static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, +}; + +static const unsigned pex_wake_n_pdd3_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PDD3, +}; + +static const unsigned pex_l1_rst_n_pdd5_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PDD5, +}; + +static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned dap_mclk1_req_pee2_pins[] = { + TEGRA_PIN_DAP_MCLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned sdmmc3_clk_lb_out_pee4_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, +}; + +static const unsigned sdmmc3_clk_lb_in_pee5_pins[] = { + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned dp_hpd_pff0_pins[] = { + TEGRA_PIN_DP_HPD_PFF0, +}; + +static const unsigned usb_vbus_en2_pff1_pins[] = { + TEGRA_PIN_USB_VBUS_EN2_PFF1, +}; + +static const unsigned pff2_pins[] = { + TEGRA_PIN_PFF2, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned gmi_clk_lb_pins[] = { + TEGRA_PIN_GMI_CLK_LB, +}; + +static const unsigned reset_out_n_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_CLK_32K_IN, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_KB_ROW16_PT0, + TEGRA_PIN_KB_ROW17_PT1, + TEGRA_PIN_SDMMC3_CD_N_PV2, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_PH0, + TEGRA_PIN_PH1, + TEGRA_PIN_PH2, + TEGRA_PIN_PH3, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_PG0, + TEGRA_PIN_PG1, + TEGRA_PIN_PG2, + TEGRA_PIN_PG3, + TEGRA_PIN_PG4, + TEGRA_PIN_PG5, + TEGRA_PIN_PG6, + TEGRA_PIN_PG7, + TEGRA_PIN_PI0, + TEGRA_PIN_PI1, + TEGRA_PIN_PI3, + TEGRA_PIN_PI4, + TEGRA_PIN_PI7, + TEGRA_PIN_PK0, + TEGRA_PIN_PK2, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_PC7, + TEGRA_PIN_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_PB0, + TEGRA_PIN_PB1, + TEGRA_PIN_PJ0, + TEGRA_PIN_PJ7, + TEGRA_PIN_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, + TEGRA_PIN_DAP_MCLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, + TEGRA_PIN_SDMMC3_CLK_LB_OUT_PEE4, + TEGRA_PIN_SDMMC3_CLK_LB_IN_PEE5, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_DVFS_PWM_PX0, + TEGRA_PIN_GPIO_X1_AUD_PX1, + TEGRA_PIN_DVFS_CLK_PX2, + TEGRA_PIN_GPIO_X3_AUD_PX3, + TEGRA_PIN_GPIO_X4_AUD_PX4, + TEGRA_PIN_GPIO_X5_AUD_PX5, + TEGRA_PIN_GPIO_X6_AUD_PX6, + TEGRA_PIN_GPIO_X7_AUD_PX7, + TEGRA_PIN_GPIO_W2_AUD_PW2, + TEGRA_PIN_GPIO_W3_AUD_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, + TEGRA_PIN_SDMMC4_CMD_PT7, + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_SDMMC3_CD_N_PV2, + TEGRA_PIN_OWR, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_gpv_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, + TEGRA_PIN_PEX_WAKE_N_PDD3, + TEGRA_PIN_PEX_L1_RST_N_PDD5, + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, + TEGRA_PIN_USB_VBUS_EN2_PFF1, + TEGRA_PIN_PFF2, +}; + +static const unsigned drive_dev3_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned drive_cec_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned drive_at6_pins[] = { + TEGRA_PIN_PK1, + TEGRA_PIN_PK3, + TEGRA_PIN_PK4, + TEGRA_PIN_PI2, + TEGRA_PIN_PI5, + TEGRA_PIN_PI6, + TEGRA_PIN_PH4, + TEGRA_PIN_PH5, + TEGRA_PIN_PH6, + TEGRA_PIN_PH7, +}; + +static const unsigned drive_dap5_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_DP_HPD_PFF0, +}; + +static const unsigned drive_usb_vbus_en_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PN4, + TEGRA_PIN_USB_VBUS_EN1_PN5, +}; + +static const unsigned drive_ao3_pins[] = { + TEGRA_PIN_RESET_OUT_N, +}; + +static const unsigned drive_ao0_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned drive_hv0_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned drive_sdio4_pins[] = { + TEGRA_PIN_SDMMC1_WP_N_PV3, +}; + +static const unsigned drive_ao4_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned mipi_pad_ctrl_dsi_b_pins[] = { + TEGRA_PIN_DSI_B_CLK_P, + TEGRA_PIN_DSI_B_CLK_N, + TEGRA_PIN_DSI_B_D0_P, + TEGRA_PIN_DSI_B_D0_N, + TEGRA_PIN_DSI_B_D1_P, + TEGRA_PIN_DSI_B_D1_N, + TEGRA_PIN_DSI_B_D2_P, + TEGRA_PIN_DSI_B_D2_N, + TEGRA_PIN_DSI_B_D3_P, + TEGRA_PIN_DSI_B_D3_N, +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CCLA, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK, + TEGRA_MUX_CLK12, + TEGRA_MUX_CPU, + TEGRA_MUX_CSI, + TEGRA_MUX_DAP, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYA_ALT, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DP, + TEGRA_MUX_DSI_B, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_OWR, + TEGRA_MUX_PE, + TEGRA_MUX_PE0, + TEGRA_MUX_PE1, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWRON, + TEGRA_MUX_RESET_OUT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SATA, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SOC, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_SYS, + TEGRA_MUX_TMDS, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_ULPI, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT3, + TEGRA_MUX_VIMCLK2, + TEGRA_MUX_VIMCLK2_ALT, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra124_functions[] = { + FUNCTION(blink), + FUNCTION(ccla), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk), + FUNCTION(clk12), + FUNCTION(cpu), + FUNCTION(csi), + FUNCTION(dap), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displaya_alt), + FUNCTION(displayb), + FUNCTION(dp), + FUNCTION(dsi_b), + FUNCTION(dtv), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(owr), + FUNCTION(pe), + FUNCTION(pe0), + FUNCTION(pe1), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwron), + FUNCTION(reset_out_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sata), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(soc), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(sys), + FUNCTION(tmds), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(ulpi), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt3), + FUNCTION(vimclk2), + FUNCTION(vimclk2_alt), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ +#define MIPI_PAD_CTRL_PINGROUP_REG_A 0x820 /* bank 2 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) +#define MIPI_PAD_CTRL_PINGROUP_REG_Y(r) ((r) - MIPI_PAD_CTRL_PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 5, \ + .odrain_bit = PINGROUP_BIT_##od(6), \ + .lock_bit = 7, \ + .ioreset_bit = PINGROUP_BIT_##ior(8), \ + .rcv_sel_bit = PINGROUP_BIT_##rcv_sel(9), \ + .drv_reg = -1, \ + } + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ + drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ + slwf_b, slwf_w, drvtype) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = PINGROUP_BIT_##drvtype(6), \ + } + +#define MIPI_PAD_CTRL_PINGROUP(pg_name, r, b, f0, f1) \ + { \ + .name = "mipi_pad_ctrl_" #pg_name, \ + .pins = mipi_pad_ctrl_##pg_name##_pins, \ + .npins = ARRAY_SIZE(mipi_pad_ctrl_##pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_ ## f0, \ + TEGRA_MUX_ ## f1, \ + TEGRA_MUX_RSVD3, \ + TEGRA_MUX_RSVD4, \ + }, \ + .mux_reg = MIPI_PAD_CTRL_PINGROUP_REG_Y(r), \ + .mux_bank = 2, \ + .mux_bit = b, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + +static const struct tegra_pingroup tegra124_groups[] = { + /* pg_name, f0, f1, f2, f3, r, od, ior, rcv_sel */ + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N, N), + PINGROUP(ulpi_clk_py0, SPI1, SPI5, UARTD, ULPI, 0x3020, N, N, N), + PINGROUP(ulpi_dir_py1, SPI1, SPI5, UARTD, ULPI, 0x3024, N, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, SPI5, UARTD, ULPI, 0x3028, N, N, N), + PINGROUP(ulpi_stp_py3, SPI1, SPI5, UARTD, ULPI, 0x302c, N, N, N), + PINGROUP(dap3_fs_pp0, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3030, N, N, N), + PINGROUP(dap3_din_pp1, I2S2, SPI5, DISPLAYA, DISPLAYB, 0x3034, N, N, N), + PINGROUP(dap3_dout_pp2, I2S2, SPI5, DISPLAYA, RSVD4, 0x3038, N, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, SPI5, RSVD3, DISPLAYB, 0x303c, N, N, N), + PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, CLK12, RSVD3, RSVD4, 0x3048, N, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, SPDIF, SPI4, UARTA, 0x304c, N, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, SPDIF, SPI4, UARTA, 0x3050, N, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, PWM0, SPI4, UARTA, 0x3054, N, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, PWM1, SPI4, UARTA, 0x3058, N, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, SPI4, UARTA, 0x305c, N, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N, N), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N, N), + PINGROUP(hdmi_int_pn7, RSVD1, RSVD2, RSVD3, RSVD4, 0x3110, N, N, Y), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N, Y), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N, Y), + PINGROUP(uart2_rxd_pc3, IRDA, SPDIF, UARTA, SPI4, 0x3164, N, N, N), + PINGROUP(uart2_txd_pc2, IRDA, SPDIF, UARTA, SPI4, 0x3168, N, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, SPI4, 0x3174, N, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, SPI4, 0x3178, N, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, SDMMC1, DTV, GMI, 0x317c, N, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, DTV, GMI, 0x3180, N, N, N), + PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N, N), + PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N, N), + PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N, N), + PINGROUP(pu3, PWM0, UARTA, GMI, DISPLAYB, 0x3190, N, N, N), + PINGROUP(pu4, PWM1, UARTA, GMI, DISPLAYB, 0x3194, N, N, N), + PINGROUP(pu5, PWM2, UARTA, GMI, DISPLAYB, 0x3198, N, N, N), + PINGROUP(pu6, PWM3, UARTA, RSVD3, GMI, 0x319c, N, N, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N, N), + PINGROUP(dap4_fs_pp4, I2S3, GMI, DTV, RSVD4, 0x31a8, N, N, N), + PINGROUP(dap4_din_pp5, I2S3, GMI, RSVD3, RSVD4, 0x31ac, N, N, N), + PINGROUP(dap4_dout_pp6, I2S3, GMI, DTV, RSVD4, 0x31b0, N, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, GMI, RSVD3, RSVD4, 0x31b4, N, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N, N), + PINGROUP(pc7, RSVD1, RSVD2, GMI, GMI_ALT, 0x31c0, N, N, N), + PINGROUP(pi5, SDMMC2, RSVD2, GMI, RSVD4, 0x31c4, N, N, N), + PINGROUP(pi7, RSVD1, TRACE, GMI, DTV, 0x31c8, N, N, N), + PINGROUP(pk0, RSVD1, SDMMC3, GMI, SOC, 0x31cc, N, N, N), + PINGROUP(pk1, SDMMC2, TRACE, GMI, RSVD4, 0x31d0, N, N, N), + PINGROUP(pj0, RSVD1, RSVD2, GMI, USB, 0x31d4, N, N, N), + PINGROUP(pj2, RSVD1, RSVD2, GMI, SOC, 0x31d8, N, N, N), + PINGROUP(pk3, SDMMC2, TRACE, GMI, CCLA, 0x31dc, N, N, N), + PINGROUP(pk4, SDMMC2, RSVD2, GMI, GMI_ALT, 0x31e0, N, N, N), + PINGROUP(pk2, RSVD1, RSVD2, GMI, RSVD4, 0x31e4, N, N, N), + PINGROUP(pi3, RSVD1, RSVD2, GMI, SPI4, 0x31e8, N, N, N), + PINGROUP(pi6, RSVD1, RSVD2, GMI, SDMMC2, 0x31ec, N, N, N), + PINGROUP(pg0, RSVD1, RSVD2, GMI, RSVD4, 0x31f0, N, N, N), + PINGROUP(pg1, RSVD1, RSVD2, GMI, RSVD4, 0x31f4, N, N, N), + PINGROUP(pg2, RSVD1, TRACE, GMI, RSVD4, 0x31f8, N, N, N), + PINGROUP(pg3, RSVD1, TRACE, GMI, RSVD4, 0x31fc, N, N, N), + PINGROUP(pg4, RSVD1, TMDS, GMI, SPI4, 0x3200, N, N, N), + PINGROUP(pg5, RSVD1, RSVD2, GMI, SPI4, 0x3204, N, N, N), + PINGROUP(pg6, RSVD1, RSVD2, GMI, SPI4, 0x3208, N, N, N), + PINGROUP(pg7, RSVD1, RSVD2, GMI, SPI4, 0x320c, N, N, N), + PINGROUP(ph0, PWM0, TRACE, GMI, DTV, 0x3210, N, N, N), + PINGROUP(ph1, PWM1, TMDS, GMI, DISPLAYA, 0x3214, N, N, N), + PINGROUP(ph2, PWM2, TMDS, GMI, CLDVFS, 0x3218, N, N, N), + PINGROUP(ph3, PWM3, SPI4, GMI, CLDVFS, 0x321c, N, N, N), + PINGROUP(ph4, SDMMC2, RSVD2, GMI, RSVD4, 0x3220, N, N, N), + PINGROUP(ph5, SDMMC2, RSVD2, GMI, RSVD4, 0x3224, N, N, N), + PINGROUP(ph6, SDMMC2, TRACE, GMI, DTV, 0x3228, N, N, N), + PINGROUP(ph7, SDMMC2, TRACE, GMI, DTV, 0x322c, N, N, N), + PINGROUP(pj7, UARTD, RSVD2, GMI, GMI_ALT, 0x3230, N, N, N), + PINGROUP(pb0, UARTD, RSVD2, GMI, RSVD4, 0x3234, N, N, N), + PINGROUP(pb1, UARTD, RSVD2, GMI, RSVD4, 0x3238, N, N, N), + PINGROUP(pk7, UARTD, RSVD2, GMI, RSVD4, 0x323c, N, N, N), + PINGROUP(pi0, RSVD1, RSVD2, GMI, RSVD4, 0x3240, N, N, N), + PINGROUP(pi1, RSVD1, RSVD2, GMI, RSVD4, 0x3244, N, N, N), + PINGROUP(pi2, SDMMC2, TRACE, GMI, RSVD4, 0x3248, N, N, N), + PINGROUP(pi4, SPI4, TRACE, GMI, DISPLAYA, 0x324c, N, N, N), + PINGROUP(gen2_i2c_scl_pt5, I2C2, RSVD2, GMI, RSVD4, 0x3250, Y, N, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, RSVD2, GMI, RSVD4, 0x3254, Y, N, N), + PINGROUP(sdmmc4_clk_pcc4, SDMMC4, RSVD2, GMI, RSVD4, 0x3258, N, Y, N), + PINGROUP(sdmmc4_cmd_pt7, SDMMC4, RSVD2, GMI, RSVD4, 0x325c, N, Y, N), + PINGROUP(sdmmc4_dat0_paa0, SDMMC4, SPI3, GMI, RSVD4, 0x3260, N, Y, N), + PINGROUP(sdmmc4_dat1_paa1, SDMMC4, SPI3, GMI, RSVD4, 0x3264, N, Y, N), + PINGROUP(sdmmc4_dat2_paa2, SDMMC4, SPI3, GMI, RSVD4, 0x3268, N, Y, N), + PINGROUP(sdmmc4_dat3_paa3, SDMMC4, SPI3, GMI, RSVD4, 0x326c, N, Y, N), + PINGROUP(sdmmc4_dat4_paa4, SDMMC4, SPI3, GMI, RSVD4, 0x3270, N, Y, N), + PINGROUP(sdmmc4_dat5_paa5, SDMMC4, SPI3, RSVD3, RSVD4, 0x3274, N, Y, N), + PINGROUP(sdmmc4_dat6_paa6, SDMMC4, SPI3, GMI, RSVD4, 0x3278, N, Y, N), + PINGROUP(sdmmc4_dat7_paa7, SDMMC4, RSVD2, GMI, RSVD4, 0x327c, N, Y, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC2, 0x3284, N, N, N), + PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC2, 0x3288, N, N, N), + PINGROUP(pbb0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT, 0x328c, N, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC2, 0x3290, Y, N, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC2, 0x3294, Y, N, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC2, 0x3298, N, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC2, 0x329c, N, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, RSVD3, SDMMC2, 0x32a0, N, N, N), + PINGROUP(pbb6, I2S4, RSVD2, DISPLAYB, SDMMC2, 0x32a4, N, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC2, 0x32a8, N, N, N), + PINGROUP(pcc2, I2S4, RSVD2, SDMMC3, SDMMC2, 0x32ac, N, N, N), + PINGROUP(jtag_rtck, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N, N), + PINGROUP(kb_row0_pr0, KBC, RSVD2, RSVD3, RSVD4, 0x32bc, N, N, N), + PINGROUP(kb_row1_pr1, KBC, RSVD2, RSVD3, RSVD4, 0x32c0, N, N, N), + PINGROUP(kb_row2_pr2, KBC, RSVD2, RSVD3, RSVD4, 0x32c4, N, N, N), + PINGROUP(kb_row3_pr3, KBC, DISPLAYA, SYS, DISPLAYB, 0x32c8, N, N, N), + PINGROUP(kb_row4_pr4, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32cc, N, N, N), + PINGROUP(kb_row5_pr5, KBC, DISPLAYA, RSVD3, DISPLAYB, 0x32d0, N, N, N), + PINGROUP(kb_row6_pr6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB, 0x32d4, N, N, N), + PINGROUP(kb_row7_pr7, KBC, RSVD2, CLDVFS, UARTA, 0x32d8, N, N, N), + PINGROUP(kb_row8_ps0, KBC, RSVD2, CLDVFS, UARTA, 0x32dc, N, N, N), + PINGROUP(kb_row9_ps1, KBC, RSVD2, RSVD3, UARTA, 0x32e0, N, N, N), + PINGROUP(kb_row10_ps2, KBC, RSVD2, RSVD3, UARTA, 0x32e4, N, N, N), + PINGROUP(kb_row11_ps3, KBC, RSVD2, RSVD3, IRDA, 0x32e8, N, N, N), + PINGROUP(kb_row12_ps4, KBC, RSVD2, RSVD3, IRDA, 0x32ec, N, N, N), + PINGROUP(kb_row13_ps5, KBC, RSVD2, SPI2, RSVD4, 0x32f0, N, N, N), + PINGROUP(kb_row14_ps6, KBC, RSVD2, SPI2, RSVD4, 0x32f4, N, N, N), + PINGROUP(kb_row15_ps7, KBC, SOC, RSVD3, RSVD4, 0x32f8, N, N, N), + PINGROUP(kb_col0_pq0, KBC, RSVD2, SPI2, RSVD4, 0x32fc, N, N, N), + PINGROUP(kb_col1_pq1, KBC, RSVD2, SPI2, RSVD4, 0x3300, N, N, N), + PINGROUP(kb_col2_pq2, KBC, RSVD2, SPI2, RSVD4, 0x3304, N, N, N), + PINGROUP(kb_col3_pq3, KBC, DISPLAYA, PWM2, UARTA, 0x3308, N, N, N), + PINGROUP(kb_col4_pq4, KBC, OWR, SDMMC3, UARTA, 0x330c, N, N, N), + PINGROUP(kb_col5_pq5, KBC, RSVD2, SDMMC3, RSVD4, 0x3310, N, N, N), + PINGROUP(kb_col6_pq6, KBC, RSVD2, SPI2, UARTD, 0x3314, N, N, N), + PINGROUP(kb_col7_pq7, KBC, RSVD2, SPI2, UARTD, 0x3318, N, N, N), + PINGROUP(clk_32k_out_pa0, BLINK, SOC, RSVD3, RSVD4, 0x331c, N, N, N), + PINGROUP(core_pwr_req, PWRON, RSVD2, RSVD3, RSVD4, 0x3324, N, N, N), + PINGROUP(cpu_pwr_req, CPU, RSVD2, RSVD3, RSVD4, 0x3328, N, N, N), + PINGROUP(pwr_int_n, PMI, RSVD2, RSVD3, RSVD4, 0x332c, N, N, N), + PINGROUP(clk_32k_in, CLK, RSVD2, RSVD3, RSVD4, 0x3330, N, N, N), + PINGROUP(owr, OWR, RSVD2, RSVD3, RSVD4, 0x3334, N, N, Y), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, RSVD4, 0x3338, N, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, RSVD4, 0x333c, N, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SATA, 0x3340, N, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, RSVD4, 0x3344, N, N, N), + PINGROUP(dap_mclk1_req_pee2, DAP, DAP1, SATA, RSVD4, 0x3348, N, N, N), + PINGROUP(dap_mclk1_pw4, EXTPERIPH1, DAP2, RSVD3, RSVD4, 0x334c, N, N, N), + PINGROUP(spdif_in_pk6, SPDIF, RSVD2, RSVD3, I2C3, 0x3350, N, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, RSVD3, I2C3, 0x3354, N, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, GMI, RSVD4, 0x3358, N, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, GMI, RSVD4, 0x335c, N, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, GMI, RSVD4, 0x3360, N, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, GMI, RSVD4, 0x3364, N, N, N), + PINGROUP(dvfs_pwm_px0, SPI6, CLDVFS, GMI, RSVD4, 0x3368, N, N, N), + PINGROUP(gpio_x1_aud_px1, SPI6, RSVD2, GMI, RSVD4, 0x336c, N, N, N), + PINGROUP(gpio_x3_aud_px3, SPI6, SPI1, GMI, RSVD4, 0x3370, N, N, N), + PINGROUP(dvfs_clk_px2, SPI6, CLDVFS, GMI, RSVD4, 0x3374, N, N, N), + PINGROUP(gpio_x4_aud_px4, GMI, SPI1, SPI2, DAP2, 0x3378, N, N, N), + PINGROUP(gpio_x5_aud_px5, GMI, SPI1, SPI2, RSVD4, 0x337c, N, N, N), + PINGROUP(gpio_x6_aud_px6, SPI6, SPI1, SPI2, GMI, 0x3380, N, N, N), + PINGROUP(gpio_x7_aud_px7, RSVD1, SPI1, SPI2, RSVD4, 0x3384, N, N, N), + PINGROUP(sdmmc3_clk_pa6, SDMMC3, RSVD2, RSVD3, SPI3, 0x3390, N, N, N), + PINGROUP(sdmmc3_cmd_pa7, SDMMC3, PWM3, UARTA, SPI3, 0x3394, N, N, N), + PINGROUP(sdmmc3_dat0_pb7, SDMMC3, RSVD2, RSVD3, SPI3, 0x3398, N, N, N), + PINGROUP(sdmmc3_dat1_pb6, SDMMC3, PWM2, UARTA, SPI3, 0x339c, N, N, N), + PINGROUP(sdmmc3_dat2_pb5, SDMMC3, PWM1, DISPLAYA, SPI3, 0x33a0, N, N, N), + PINGROUP(sdmmc3_dat3_pb4, SDMMC3, PWM0, DISPLAYB, SPI3, 0x33a4, N, N, N), + PINGROUP(pex_l0_rst_n_pdd1, PE0, RSVD2, RSVD3, RSVD4, 0x33bc, N, N, N), + PINGROUP(pex_l0_clkreq_n_pdd2, PE0, RSVD2, RSVD3, RSVD4, 0x33c0, N, N, N), + PINGROUP(pex_wake_n_pdd3, PE, RSVD2, RSVD3, RSVD4, 0x33c4, N, N, N), + PINGROUP(pex_l1_rst_n_pdd5, PE1, RSVD2, RSVD3, RSVD4, 0x33cc, N, N, N), + PINGROUP(pex_l1_clkreq_n_pdd6, PE1, RSVD2, RSVD3, RSVD4, 0x33d0, N, N, N), + PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N, N), + PINGROUP(sdmmc1_wp_n_pv3, SDMMC1, CLK12, SPI4, UARTA, 0x33e4, N, N, N), + PINGROUP(sdmmc3_cd_n_pv2, SDMMC3, OWR, RSVD3, RSVD4, 0x33e8, N, N, N), + PINGROUP(gpio_w2_aud_pw2, SPI6, RSVD2, SPI2, I2C1, 0x33ec, N, N, N), + PINGROUP(gpio_w3_aud_pw3, SPI6, SPI1, SPI2, I2C1, 0x33f0, N, N, N), + PINGROUP(usb_vbus_en0_pn4, USB, RSVD2, RSVD3, RSVD4, 0x33f4, Y, N, N), + PINGROUP(usb_vbus_en1_pn5, USB, RSVD2, RSVD3, RSVD4, 0x33f8, Y, N, N), + PINGROUP(sdmmc3_clk_lb_in_pee5, SDMMC3, RSVD2, RSVD3, RSVD4, 0x33fc, N, N, N), + PINGROUP(sdmmc3_clk_lb_out_pee4, SDMMC3, RSVD2, RSVD3, RSVD4, 0x3400, N, N, N), + PINGROUP(gmi_clk_lb, SDMMC2, RSVD2, GMI, RSVD4, 0x3404, N, N, N), + PINGROUP(reset_out_n, RSVD1, RSVD2, RSVD3, RESET_OUT_N, 0x3408, N, N, N), + PINGROUP(kb_row16_pt0, KBC, RSVD2, RSVD3, UARTC, 0x340c, N, N, N), + PINGROUP(kb_row17_pt1, KBC, RSVD2, RSVD3, UARTC, 0x3410, N, N, N), + PINGROUP(usb_vbus_en2_pff1, USB, RSVD2, RSVD3, RSVD4, 0x3414, Y, N, N), + PINGROUP(pff2, SATA, RSVD2, RSVD3, RSVD4, 0x3418, Y, N, N), + PINGROUP(dp_hpd_pff0, DP, RSVD2, RSVD3, RSVD4, 0x3430, N, N, N), + + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w, drvtype */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at1, 0x870, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at2, 0x874, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at3, 0x878, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2, N), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gma, 0x900, 2, 3, 4, 14, 5, 20, 5, 28, 2, 30, 2, Y), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(at6, 0x994, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + DRV_PINGROUP(dap5, 0x998, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(usb_vbus_en, 0x99c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao3, 0x9a8, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(ao0, 0x9b0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(hv0, 0x9b4, 2, 3, 4, 12, 5, -1, -1, 28, 2, -1, -1, N), + DRV_PINGROUP(sdio4, 0x9c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2, N), + DRV_PINGROUP(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2, Y), + + /* pg_name, r, b, f0, f1 */ + MIPI_PAD_CTRL_PINGROUP(dsi_b, 0x820, 1, CSI, DSI_B), +}; + +static const struct tegra_pinctrl_soc_data tegra124_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra124_pins, + .npins = ARRAY_SIZE(tegra124_pins), + .functions = tegra124_functions, + .nfunctions = ARRAY_SIZE(tegra124_functions), + .groups = tegra124_groups, + .ngroups = ARRAY_SIZE(tegra124_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra124_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra124_pinctrl); +} + +static const struct of_device_id tegra124_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra124-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra124_pinctrl_of_match); + +static struct platform_driver tegra124_pinctrl_driver = { + .driver = { + .name = "tegra124-pinctrl", + .of_match_table = tegra124_pinctrl_of_match, + }, + .probe = tegra124_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra124_pinctrl_driver); + +MODULE_AUTHOR("Ashwini Ghuge "); +MODULE_DESCRIPTION("NVIDIA Tegra124 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c new file mode 100644 index 000000000000..4833db4433d9 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -0,0 +1,2252 @@ +/* + * Pinctrl data for the NVIDIA Tegra20 pinmux + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * + * Derived from code: + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010 NVIDIA 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 "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_VI_GP6_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDIO3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDIO3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_GMI_AD17_PB0 _GPIO(8) +#define TEGRA_PIN_GMI_AD18_PB1 _GPIO(9) +#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) +#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) +#define TEGRA_PIN_SDIO3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDIO3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDIO3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDIO3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) +#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) +#define TEGRA_PIN_SDIO3_DAT5_PD0 _GPIO(24) +#define TEGRA_PIN_SDIO3_DAT4_PD1 _GPIO(25) +#define TEGRA_PIN_VI_GP5_PD2 _GPIO(26) +#define TEGRA_PIN_SDIO3_DAT6_PD3 _GPIO(27) +#define TEGRA_PIN_SDIO3_DAT7_PD4 _GPIO(28) +#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) +#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) +#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) +#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) +#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) +#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) +#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) +#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) +#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) +#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) +#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) +#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) +#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) +#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) +#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) +#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) +#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) +#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) +#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) +#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) +#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) +#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) +#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) +#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) +#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) +#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) +#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) +#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) +#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) +#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) +#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) +#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) +#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) +#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) +#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) +#define TEGRA_PIN_GMI_HIOW_N_PI0 _GPIO(64) +#define TEGRA_PIN_GMI_HIOR_N_PI1 _GPIO(65) +#define TEGRA_PIN_GMI_CS5_N_PI2 _GPIO(66) +#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) +#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) +#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) +#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) +#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) +#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) +#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) +#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) +#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) +#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_GMI_AD16_PJ7 _GPIO(79) +#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) +#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) +#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) +#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) +#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_GMI_AD19_PK7 _GPIO(87) +#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) +#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) +#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) +#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) +#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) +#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) +#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) +#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) +#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) +#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) +#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) +#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) +#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) +#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) +#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) +#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) +#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) +#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) +#define TEGRA_PIN_HDMI_INT_N_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) +#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) +#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) +#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) +#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_GMI_DPD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_PV2 _GPIO(170) +#define TEGRA_PIN_PV3 _GPIO(171) +#define TEGRA_PIN_PV4 _GPIO(172) +#define TEGRA_PIN_PV5 _GPIO(173) +#define TEGRA_PIN_PV6 _GPIO(174) +#define TEGRA_PIN_LCD_DC1_PV7 _GPIO(175) +#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) +#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) +#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) +#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) +#define TEGRA_PIN_DAP_MCLK1_PW4 _GPIO(180) +#define TEGRA_PIN_DAP_MCLK2_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) +#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) +#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) +#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) +#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) +#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) +#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) +#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDIO1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDIO1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDIO1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDIO1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDIO1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDIO1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) +#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) +#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) +#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_GMI_AD20_PAA0 _GPIO(208) +#define TEGRA_PIN_GMI_AD21_PAA1 _GPIO(209) +#define TEGRA_PIN_GMI_AD22_PAA2 _GPIO(210) +#define TEGRA_PIN_GMI_AD23_PAA3 _GPIO(211) +#define TEGRA_PIN_GMI_AD24_PAA4 _GPIO(212) +#define TEGRA_PIN_GMI_AD25_PAA5 _GPIO(213) +#define TEGRA_PIN_GMI_AD26_PAA6 _GPIO(214) +#define TEGRA_PIN_GMI_AD27_PAA7 _GPIO(215) +#define TEGRA_PIN_LED_BLINK_PBB0 _GPIO(216) +#define TEGRA_PIN_VI_GP0_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SCL_PBB2 _GPIO(218) +#define TEGRA_PIN_CAM_I2C_SDA_PBB3 _GPIO(219) +#define TEGRA_PIN_VI_GP3_PBB4 _GPIO(220) +#define TEGRA_PIN_VI_GP4_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PBB7 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +#define TEGRA_PIN_CRT_HSYNC _PIN(30) +#define TEGRA_PIN_CRT_VSYNC _PIN(31) +#define TEGRA_PIN_DDC_SCL _PIN(32) +#define TEGRA_PIN_DDC_SDA _PIN(33) +#define TEGRA_PIN_OWC _PIN(34) +#define TEGRA_PIN_CORE_PWR_REQ _PIN(35) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(36) +#define TEGRA_PIN_PWR_INT_N _PIN(37) +#define TEGRA_PIN_CLK_32_K_IN _PIN(38) +#define TEGRA_PIN_DDR_COMP_PD _PIN(39) +#define TEGRA_PIN_DDR_COMP_PU _PIN(40) +#define TEGRA_PIN_DDR_A0 _PIN(41) +#define TEGRA_PIN_DDR_A1 _PIN(42) +#define TEGRA_PIN_DDR_A2 _PIN(43) +#define TEGRA_PIN_DDR_A3 _PIN(44) +#define TEGRA_PIN_DDR_A4 _PIN(45) +#define TEGRA_PIN_DDR_A5 _PIN(46) +#define TEGRA_PIN_DDR_A6 _PIN(47) +#define TEGRA_PIN_DDR_A7 _PIN(48) +#define TEGRA_PIN_DDR_A8 _PIN(49) +#define TEGRA_PIN_DDR_A9 _PIN(50) +#define TEGRA_PIN_DDR_A10 _PIN(51) +#define TEGRA_PIN_DDR_A11 _PIN(52) +#define TEGRA_PIN_DDR_A12 _PIN(53) +#define TEGRA_PIN_DDR_A13 _PIN(54) +#define TEGRA_PIN_DDR_A14 _PIN(55) +#define TEGRA_PIN_DDR_CAS_N _PIN(56) +#define TEGRA_PIN_DDR_BA0 _PIN(57) +#define TEGRA_PIN_DDR_BA1 _PIN(58) +#define TEGRA_PIN_DDR_BA2 _PIN(59) +#define TEGRA_PIN_DDR_DQS0P _PIN(60) +#define TEGRA_PIN_DDR_DQS0N _PIN(61) +#define TEGRA_PIN_DDR_DQS1P _PIN(62) +#define TEGRA_PIN_DDR_DQS1N _PIN(63) +#define TEGRA_PIN_DDR_DQS2P _PIN(64) +#define TEGRA_PIN_DDR_DQS2N _PIN(65) +#define TEGRA_PIN_DDR_DQS3P _PIN(66) +#define TEGRA_PIN_DDR_DQS3N _PIN(67) +#define TEGRA_PIN_DDR_CKE0 _PIN(68) +#define TEGRA_PIN_DDR_CKE1 _PIN(69) +#define TEGRA_PIN_DDR_CLK _PIN(70) +#define TEGRA_PIN_DDR_CLK_N _PIN(71) +#define TEGRA_PIN_DDR_DM0 _PIN(72) +#define TEGRA_PIN_DDR_DM1 _PIN(73) +#define TEGRA_PIN_DDR_DM2 _PIN(74) +#define TEGRA_PIN_DDR_DM3 _PIN(75) +#define TEGRA_PIN_DDR_ODT _PIN(76) +#define TEGRA_PIN_DDR_QUSE0 _PIN(77) +#define TEGRA_PIN_DDR_QUSE1 _PIN(78) +#define TEGRA_PIN_DDR_QUSE2 _PIN(79) +#define TEGRA_PIN_DDR_QUSE3 _PIN(80) +#define TEGRA_PIN_DDR_RAS_N _PIN(81) +#define TEGRA_PIN_DDR_WE_N _PIN(82) +#define TEGRA_PIN_DDR_DQ0 _PIN(83) +#define TEGRA_PIN_DDR_DQ1 _PIN(84) +#define TEGRA_PIN_DDR_DQ2 _PIN(85) +#define TEGRA_PIN_DDR_DQ3 _PIN(86) +#define TEGRA_PIN_DDR_DQ4 _PIN(87) +#define TEGRA_PIN_DDR_DQ5 _PIN(88) +#define TEGRA_PIN_DDR_DQ6 _PIN(89) +#define TEGRA_PIN_DDR_DQ7 _PIN(90) +#define TEGRA_PIN_DDR_DQ8 _PIN(91) +#define TEGRA_PIN_DDR_DQ9 _PIN(92) +#define TEGRA_PIN_DDR_DQ10 _PIN(93) +#define TEGRA_PIN_DDR_DQ11 _PIN(94) +#define TEGRA_PIN_DDR_DQ12 _PIN(95) +#define TEGRA_PIN_DDR_DQ13 _PIN(96) +#define TEGRA_PIN_DDR_DQ14 _PIN(97) +#define TEGRA_PIN_DDR_DQ15 _PIN(98) +#define TEGRA_PIN_DDR_DQ16 _PIN(99) +#define TEGRA_PIN_DDR_DQ17 _PIN(100) +#define TEGRA_PIN_DDR_DQ18 _PIN(101) +#define TEGRA_PIN_DDR_DQ19 _PIN(102) +#define TEGRA_PIN_DDR_DQ20 _PIN(103) +#define TEGRA_PIN_DDR_DQ21 _PIN(104) +#define TEGRA_PIN_DDR_DQ22 _PIN(105) +#define TEGRA_PIN_DDR_DQ23 _PIN(106) +#define TEGRA_PIN_DDR_DQ24 _PIN(107) +#define TEGRA_PIN_DDR_DQ25 _PIN(108) +#define TEGRA_PIN_DDR_DQ26 _PIN(109) +#define TEGRA_PIN_DDR_DQ27 _PIN(110) +#define TEGRA_PIN_DDR_DQ28 _PIN(111) +#define TEGRA_PIN_DDR_DQ29 _PIN(112) +#define TEGRA_PIN_DDR_DQ30 _PIN(113) +#define TEGRA_PIN_DDR_DQ31 _PIN(114) +#define TEGRA_PIN_DDR_CS0_N _PIN(115) +#define TEGRA_PIN_DDR_CS1_N _PIN(116) +#define TEGRA_PIN_SYS_RESET _PIN(117) +#define TEGRA_PIN_JTAG_TRST_N _PIN(118) +#define TEGRA_PIN_JTAG_TDO _PIN(119) +#define TEGRA_PIN_JTAG_TMS _PIN(120) +#define TEGRA_PIN_JTAG_TCK _PIN(121) +#define TEGRA_PIN_JTAG_TDI _PIN(122) +#define TEGRA_PIN_TEST_MODE_EN _PIN(123) + +static const struct pinctrl_pin_desc tegra20_pins[] = { + PINCTRL_PIN(TEGRA_PIN_VI_GP6_PA0, "VI_GP6 PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_CLK_PA6, "SDIO3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_CMD_PA7, "SDIO3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD17_PB0, "GMI_AD17 PB0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD18_PB1, "GMI_AD18 PB1"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), + PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT3_PB4, "SDIO3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT2_PB5, "SDIO3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT1_PB6, "SDIO3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT0_PB7, "SDIO3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT5_PD0, "SDIO3_DAT5 PD0"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT4_PD1, "SDIO3_DAT4 PD1"), + PINCTRL_PIN(TEGRA_PIN_VI_GP5_PD2, "VI_GP5 PD2"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT6_PD3, "SDIO3_DAT6 PD3"), + PINCTRL_PIN(TEGRA_PIN_SDIO3_DAT7_PD4, "SDIO3_DAT7 PD4"), + PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), + PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), + PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), + PINCTRL_PIN(TEGRA_PIN_GMI_HIOW_N_PI0, "GMI_HIOW_N PI0"), + PINCTRL_PIN(TEGRA_PIN_GMI_HIOR_N_PI1, "GMI_HIOR_N PI1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS5_N_PI2, "GMI_CS5_N PI2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), + PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), + PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), + PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD16_PJ7, "GMI_AD16 PJ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD19_PK7, "GMI_AD19 PK7"), + PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), + PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), + PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), + PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), + PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), + PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), + PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), + PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_N_PN7, "HDMI_INT_N PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), + PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), + PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), + PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VD_D10 PT2"), + PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), + PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_GMI_DPD_PT7, "GMI_DPD PT7"), + /* PU0..6: GPIO only */ + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), + /* PV0..1: GPIO only */ + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + /* PV2..3: Balls are named after GPIO not function */ + PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), + PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), + /* PV4..6: GPIO only */ + PINCTRL_PIN(TEGRA_PIN_PV4, "PV4"), + PINCTRL_PIN(TEGRA_PIN_PV5, "PV5"), + PINCTRL_PIN(TEGRA_PIN_PV6, "PV6"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PV7, "LCD_DC1 PV7"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), + PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK1_PW4, "DAP_MCLK1 PW4"), + PINCTRL_PIN(TEGRA_PIN_DAP_MCLK2_PW5, "DAP_MCLK2 PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT3_PY4, "SDIO1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT2_PY5, "SDIO1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT1_PY6, "SDIO1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_DAT0_PY7, "SDIO1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_CLK_PZ0, "SDIO1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDIO1_CMD_PZ1, "SDIO1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), + PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD20_PAA0, "GMI_AD20 PAA0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD21_PAA1, "GMI_AD21 PAA1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD22_PAA2, "GMI_AD22 PAA2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD23_PAA3, "GMI_AD23 PAA3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD24_PAA4, "GMI_AD24 PAA4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD25_PAA5, "GMI_AD25 PAA5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD26_PAA6, "GMI_AD26 PAA6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD27_PAA7, "GMI_AD27 PAA7"), + PINCTRL_PIN(TEGRA_PIN_LED_BLINK_PBB0, "LED_BLINK PBB0"), + PINCTRL_PIN(TEGRA_PIN_VI_GP0_PBB1, "VI_GP0 PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB2, "CAM_I2C_SCL PBB2"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB3, "CAM_I2C_SDA PBB3"), + PINCTRL_PIN(TEGRA_PIN_VI_GP3_PBB4, "VI_GP3 PBB4"), + PINCTRL_PIN(TEGRA_PIN_VI_GP4_PBB5, "VI_GP4 PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC, "CRT_HSYNC"), + PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC, "CRT_VSYNC"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL, "DDC_SCL"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA, "DDC_SDA"), + PINCTRL_PIN(TEGRA_PIN_OWC, "OWC"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_CLK_32_K_IN, "CLK_32_K_IN"), + PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PD, "DDR_COMP_PD"), + PINCTRL_PIN(TEGRA_PIN_DDR_COMP_PU, "DDR_COMP_PU"), + PINCTRL_PIN(TEGRA_PIN_DDR_A0, "DDR_A0"), + PINCTRL_PIN(TEGRA_PIN_DDR_A1, "DDR_A1"), + PINCTRL_PIN(TEGRA_PIN_DDR_A2, "DDR_A2"), + PINCTRL_PIN(TEGRA_PIN_DDR_A3, "DDR_A3"), + PINCTRL_PIN(TEGRA_PIN_DDR_A4, "DDR_A4"), + PINCTRL_PIN(TEGRA_PIN_DDR_A5, "DDR_A5"), + PINCTRL_PIN(TEGRA_PIN_DDR_A6, "DDR_A6"), + PINCTRL_PIN(TEGRA_PIN_DDR_A7, "DDR_A7"), + PINCTRL_PIN(TEGRA_PIN_DDR_A8, "DDR_A8"), + PINCTRL_PIN(TEGRA_PIN_DDR_A9, "DDR_A9"), + PINCTRL_PIN(TEGRA_PIN_DDR_A10, "DDR_A10"), + PINCTRL_PIN(TEGRA_PIN_DDR_A11, "DDR_A11"), + PINCTRL_PIN(TEGRA_PIN_DDR_A12, "DDR_A12"), + PINCTRL_PIN(TEGRA_PIN_DDR_A13, "DDR_A13"), + PINCTRL_PIN(TEGRA_PIN_DDR_A14, "DDR_A14"), + PINCTRL_PIN(TEGRA_PIN_DDR_CAS_N, "DDR_CAS_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_BA0, "DDR_BA0"), + PINCTRL_PIN(TEGRA_PIN_DDR_BA1, "DDR_BA1"), + PINCTRL_PIN(TEGRA_PIN_DDR_BA2, "DDR_BA2"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS0P, "DDR_DQS0P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS0N, "DDR_DQS0N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS1P, "DDR_DQS1P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS1N, "DDR_DQS1N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS2P, "DDR_DQS2P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS2N, "DDR_DQS2N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS3P, "DDR_DQS3P"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQS3N, "DDR_DQS3N"), + PINCTRL_PIN(TEGRA_PIN_DDR_CKE0, "DDR_CKE0"), + PINCTRL_PIN(TEGRA_PIN_DDR_CKE1, "DDR_CKE1"), + PINCTRL_PIN(TEGRA_PIN_DDR_CLK, "DDR_CLK"), + PINCTRL_PIN(TEGRA_PIN_DDR_CLK_N, "DDR_CLK_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM0, "DDR_DM0"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM1, "DDR_DM1"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM2, "DDR_DM2"), + PINCTRL_PIN(TEGRA_PIN_DDR_DM3, "DDR_DM3"), + PINCTRL_PIN(TEGRA_PIN_DDR_ODT, "DDR_ODT"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE0, "DDR_QUSE0"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE1, "DDR_QUSE1"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE2, "DDR_QUSE2"), + PINCTRL_PIN(TEGRA_PIN_DDR_QUSE3, "DDR_QUSE3"), + PINCTRL_PIN(TEGRA_PIN_DDR_RAS_N, "DDR_RAS_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_WE_N, "DDR_WE_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ0, "DDR_DQ0"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ1, "DDR_DQ1"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ2, "DDR_DQ2"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ3, "DDR_DQ3"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ4, "DDR_DQ4"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ5, "DDR_DQ5"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ6, "DDR_DQ6"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ7, "DDR_DQ7"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ8, "DDR_DQ8"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ9, "DDR_DQ9"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ10, "DDR_DQ10"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ11, "DDR_DQ11"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ12, "DDR_DQ12"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ13, "DDR_DQ13"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ14, "DDR_DQ14"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ15, "DDR_DQ15"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ16, "DDR_DQ16"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ17, "DDR_DQ17"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ18, "DDR_DQ18"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ19, "DDR_DQ19"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ20, "DDR_DQ20"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ21, "DDR_DQ21"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ22, "DDR_DQ22"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ23, "DDR_DQ23"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ24, "DDR_DQ24"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ25, "DDR_DQ25"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ26, "DDR_DQ26"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ27, "DDR_DQ27"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ28, "DDR_DQ28"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ29, "DDR_DQ29"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ30, "DDR_DQ30"), + PINCTRL_PIN(TEGRA_PIN_DDR_DQ31, "DDR_DQ31"), + PINCTRL_PIN(TEGRA_PIN_DDR_CS0_N, "DDR_CS0_N"), + PINCTRL_PIN(TEGRA_PIN_DDR_CS1_N, "DDR_CS1_N"), + PINCTRL_PIN(TEGRA_PIN_SYS_RESET, "SYS_RESET"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), + PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), +}; + +static const unsigned ata_pins[] = { + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_CS7_N_PI6, + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned atb_pins[] = { + TEGRA_PIN_GMI_CS5_N_PI2, + TEGRA_PIN_GMI_DPD_PT7, +}; + +static const unsigned atc_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_CS3_N_PK4, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_HIOW_N_PI0, + TEGRA_PIN_GMI_HIOR_N_PI1, +}; + +static const unsigned atd_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, +}; + +static const unsigned ate_pins[] = { + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, +}; + +static const unsigned cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned cdev2_pins[] = { + TEGRA_PIN_DAP_MCLK2_PW5, +}; + +static const unsigned crtp_pins[] = { + TEGRA_PIN_CRT_HSYNC, + TEGRA_PIN_CRT_VSYNC, +}; + +static const unsigned csus_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned ddc_pins[] = { + TEGRA_PIN_DDC_SCL, + TEGRA_PIN_DDC_SDA, +}; + +static const unsigned dta_pins[] = { + TEGRA_PIN_VI_D0_PT4, + TEGRA_PIN_VI_D1_PD5, +}; + +static const unsigned dtb_pins[] = { + TEGRA_PIN_VI_D10_PT2, + TEGRA_PIN_VI_D11_PT3, +}; + +static const unsigned dtc_pins[] = { + TEGRA_PIN_VI_HSYNC_PD7, + TEGRA_PIN_VI_VSYNC_PD6, +}; + +static const unsigned dtd_pins[] = { + TEGRA_PIN_VI_PCLK_PT0, + TEGRA_PIN_VI_D2_PL0, + TEGRA_PIN_VI_D3_PL1, + TEGRA_PIN_VI_D4_PL2, + TEGRA_PIN_VI_D5_PL3, + TEGRA_PIN_VI_D6_PL4, + TEGRA_PIN_VI_D7_PL5, + TEGRA_PIN_VI_D8_PL6, + TEGRA_PIN_VI_D9_PL7, +}; + +static const unsigned dte_pins[] = { + TEGRA_PIN_VI_GP0_PBB1, + TEGRA_PIN_VI_GP3_PBB4, + TEGRA_PIN_VI_GP4_PBB5, + TEGRA_PIN_VI_GP5_PD2, + TEGRA_PIN_VI_GP6_PA0, +}; + +static const unsigned dtf_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB2, + TEGRA_PIN_CAM_I2C_SDA_PBB3, +}; + +static const unsigned gma_pins[] = { + TEGRA_PIN_GMI_AD20_PAA0, + TEGRA_PIN_GMI_AD21_PAA1, + TEGRA_PIN_GMI_AD22_PAA2, + TEGRA_PIN_GMI_AD23_PAA3, +}; + +static const unsigned gmb_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned gmc_pins[] = { + TEGRA_PIN_GMI_AD16_PJ7, + TEGRA_PIN_GMI_AD17_PB0, + TEGRA_PIN_GMI_AD18_PB1, + TEGRA_PIN_GMI_AD19_PK7, +}; + +static const unsigned gmd_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned gme_pins[] = { + TEGRA_PIN_GMI_AD24_PAA4, + TEGRA_PIN_GMI_AD25_PAA5, + TEGRA_PIN_GMI_AD26_PAA6, + TEGRA_PIN_GMI_AD27_PAA7, +}; + +static const unsigned gpu_pins[] = { + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, +}; + +static const unsigned gpu7_pins[] = { + TEGRA_PIN_JTAG_RTCK_PU7, +}; + +static const unsigned gpv_pins[] = { + TEGRA_PIN_PV4, + TEGRA_PIN_PV5, + TEGRA_PIN_PV6, +}; + +static const unsigned hdint_pins[] = { + TEGRA_PIN_HDMI_INT_N_PN7, +}; + +static const unsigned i2cp_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned irrx_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned irtx_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned kbca_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kbcb_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned kbcc_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kbcd_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kbce_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kbcf_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned lcsn_pins[] = { + TEGRA_PIN_LCD_CS0_N_PN4, +}; + +static const unsigned ld0_pins[] = { + TEGRA_PIN_LCD_D0_PE0, +}; + +static const unsigned ld1_pins[] = { + TEGRA_PIN_LCD_D1_PE1, +}; + +static const unsigned ld2_pins[] = { + TEGRA_PIN_LCD_D2_PE2, +}; + +static const unsigned ld3_pins[] = { + TEGRA_PIN_LCD_D3_PE3, +}; + +static const unsigned ld4_pins[] = { + TEGRA_PIN_LCD_D4_PE4, +}; + +static const unsigned ld5_pins[] = { + TEGRA_PIN_LCD_D5_PE5, +}; + +static const unsigned ld6_pins[] = { + TEGRA_PIN_LCD_D6_PE6, +}; + +static const unsigned ld7_pins[] = { + TEGRA_PIN_LCD_D7_PE7, +}; + +static const unsigned ld8_pins[] = { + TEGRA_PIN_LCD_D8_PF0, +}; + +static const unsigned ld9_pins[] = { + TEGRA_PIN_LCD_D9_PF1, +}; + +static const unsigned ld10_pins[] = { + TEGRA_PIN_LCD_D10_PF2, +}; + +static const unsigned ld11_pins[] = { + TEGRA_PIN_LCD_D11_PF3, +}; + +static const unsigned ld12_pins[] = { + TEGRA_PIN_LCD_D12_PF4, +}; + +static const unsigned ld13_pins[] = { + TEGRA_PIN_LCD_D13_PF5, +}; + +static const unsigned ld14_pins[] = { + TEGRA_PIN_LCD_D14_PF6, +}; + +static const unsigned ld15_pins[] = { + TEGRA_PIN_LCD_D15_PF7, +}; + +static const unsigned ld16_pins[] = { + TEGRA_PIN_LCD_D16_PM0, +}; + +static const unsigned ld17_pins[] = { + TEGRA_PIN_LCD_D17_PM1, +}; + +static const unsigned ldc_pins[] = { + TEGRA_PIN_LCD_DC0_PN6, +}; + +static const unsigned ldi_pins[] = { + TEGRA_PIN_LCD_D22_PM6, +}; + +static const unsigned lhp0_pins[] = { + TEGRA_PIN_LCD_D21_PM5, +}; + +static const unsigned lhp1_pins[] = { + TEGRA_PIN_LCD_D18_PM2, +}; + +static const unsigned lhp2_pins[] = { + TEGRA_PIN_LCD_D19_PM3, +}; + +static const unsigned lhs_pins[] = { + TEGRA_PIN_LCD_HSYNC_PJ3, +}; + +static const unsigned lm0_pins[] = { + TEGRA_PIN_LCD_CS1_N_PW0, +}; + +static const unsigned lm1_pins[] = { + TEGRA_PIN_LCD_M1_PW1, +}; + +static const unsigned lpp_pins[] = { + TEGRA_PIN_LCD_D23_PM7, +}; + +static const unsigned lpw0_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, +}; + +static const unsigned lpw1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, +}; + +static const unsigned lpw2_pins[] = { + TEGRA_PIN_LCD_PWR2_PC6, +}; + +static const unsigned lsc0_pins[] = { + TEGRA_PIN_LCD_PCLK_PB3, +}; + +static const unsigned lsc1_pins[] = { + TEGRA_PIN_LCD_WR_N_PZ3, +}; + +static const unsigned lsck_pins[] = { + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned lsda_pins[] = { + TEGRA_PIN_LCD_SDOUT_PN5, +}; + +static const unsigned lsdi_pins[] = { + TEGRA_PIN_LCD_SDIN_PZ2, +}; + +static const unsigned lspi_pins[] = { + TEGRA_PIN_LCD_DE_PJ1, +}; + +static const unsigned lvp0_pins[] = { + TEGRA_PIN_LCD_DC1_PV7, +}; + +static const unsigned lvp1_pins[] = { + TEGRA_PIN_LCD_D20_PM4, +}; + +static const unsigned lvs_pins[] = { + TEGRA_PIN_LCD_VSYNC_PJ4, +}; + +static const unsigned ls_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, + TEGRA_PIN_LCD_PWR1_PC1, + TEGRA_PIN_LCD_PWR2_PC6, + TEGRA_PIN_LCD_SDIN_PZ2, + TEGRA_PIN_LCD_SDOUT_PN5, + TEGRA_PIN_LCD_WR_N_PZ3, + TEGRA_PIN_LCD_CS0_N_PN4, + TEGRA_PIN_LCD_DC0_PN6, + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned lc_pins[] = { + TEGRA_PIN_LCD_PCLK_PB3, + TEGRA_PIN_LCD_DE_PJ1, + TEGRA_PIN_LCD_HSYNC_PJ3, + TEGRA_PIN_LCD_VSYNC_PJ4, + TEGRA_PIN_LCD_CS1_N_PW0, + TEGRA_PIN_LCD_M1_PW1, + TEGRA_PIN_LCD_DC1_PV7, + TEGRA_PIN_HDMI_INT_N_PN7, +}; + +static const unsigned ld17_0_pins[] = { + TEGRA_PIN_LCD_D0_PE0, + TEGRA_PIN_LCD_D1_PE1, + TEGRA_PIN_LCD_D2_PE2, + TEGRA_PIN_LCD_D3_PE3, + TEGRA_PIN_LCD_D4_PE4, + TEGRA_PIN_LCD_D5_PE5, + TEGRA_PIN_LCD_D6_PE6, + TEGRA_PIN_LCD_D7_PE7, + TEGRA_PIN_LCD_D8_PF0, + TEGRA_PIN_LCD_D9_PF1, + TEGRA_PIN_LCD_D10_PF2, + TEGRA_PIN_LCD_D11_PF3, + TEGRA_PIN_LCD_D12_PF4, + TEGRA_PIN_LCD_D13_PF5, + TEGRA_PIN_LCD_D14_PF6, + TEGRA_PIN_LCD_D15_PF7, + TEGRA_PIN_LCD_D16_PM0, + TEGRA_PIN_LCD_D17_PM1, +}; + +static const unsigned ld19_18_pins[] = { + TEGRA_PIN_LCD_D18_PM2, + TEGRA_PIN_LCD_D19_PM3, +}; + +static const unsigned ld21_20_pins[] = { + TEGRA_PIN_LCD_D20_PM4, + TEGRA_PIN_LCD_D21_PM5, +}; + +static const unsigned ld23_22_pins[] = { + TEGRA_PIN_LCD_D22_PM6, + TEGRA_PIN_LCD_D23_PM7, +}; + +static const unsigned owc_pins[] = { + TEGRA_PIN_OWC, +}; + +static const unsigned pmc_pins[] = { + TEGRA_PIN_LED_BLINK_PBB0, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned pta_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned rm_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned sdb_pins[] = { + TEGRA_PIN_SDIO3_CMD_PA7, +}; + +static const unsigned sdc_pins[] = { + TEGRA_PIN_SDIO3_DAT0_PB7, + TEGRA_PIN_SDIO3_DAT1_PB6, + TEGRA_PIN_SDIO3_DAT2_PB5, + TEGRA_PIN_SDIO3_DAT3_PB4, +}; + +static const unsigned sdd_pins[] = { + TEGRA_PIN_SDIO3_CLK_PA6, +}; + +static const unsigned sdio1_pins[] = { + TEGRA_PIN_SDIO1_CLK_PZ0, + TEGRA_PIN_SDIO1_CMD_PZ1, + TEGRA_PIN_SDIO1_DAT0_PY7, + TEGRA_PIN_SDIO1_DAT1_PY6, + TEGRA_PIN_SDIO1_DAT2_PY5, + TEGRA_PIN_SDIO1_DAT3_PY4, +}; + +static const unsigned slxa_pins[] = { + TEGRA_PIN_SDIO3_DAT4_PD1, +}; + +static const unsigned slxc_pins[] = { + TEGRA_PIN_SDIO3_DAT6_PD3, +}; + +static const unsigned slxd_pins[] = { + TEGRA_PIN_SDIO3_DAT7_PD4, +}; + +static const unsigned slxk_pins[] = { + TEGRA_PIN_SDIO3_DAT5_PD0, +}; + +static const unsigned spdi_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned spdo_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spia_pins[] = { + TEGRA_PIN_SPI2_MOSI_PX0, +}; + +static const unsigned spib_pins[] = { + TEGRA_PIN_SPI2_MISO_PX1, +}; + +static const unsigned spic_pins[] = { + TEGRA_PIN_SPI2_CS0_N_PX3, + TEGRA_PIN_SPI2_SCK_PX2, +}; + +static const unsigned spid_pins[] = { + TEGRA_PIN_SPI1_MOSI_PX4, +}; + +static const unsigned spie_pins[] = { + TEGRA_PIN_SPI1_CS0_N_PX6, + TEGRA_PIN_SPI1_SCK_PX5, +}; + +static const unsigned spif_pins[] = { + TEGRA_PIN_SPI1_MISO_PX7, +}; + +static const unsigned spig_pins[] = { + TEGRA_PIN_SPI2_CS1_N_PW2, +}; + +static const unsigned spih_pins[] = { + TEGRA_PIN_SPI2_CS2_N_PW3, +}; + +static const unsigned uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned uab_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned uac_pins[] = { + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, + TEGRA_PIN_PV2, + TEGRA_PIN_PV3, +}; + +static const unsigned ck32_pins[] = { + TEGRA_PIN_CLK_32_K_IN, +}; + +static const unsigned uad_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uca_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned ucb_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned ddrc_pins[] = { + TEGRA_PIN_DDR_COMP_PD, + TEGRA_PIN_DDR_COMP_PU, +}; + +static const unsigned pmca_pins[] = { + TEGRA_PIN_LED_BLINK_PBB0, +}; + +static const unsigned pmcb_pins[] = { + TEGRA_PIN_SYS_CLK_REQ_PZ5, +}; + +static const unsigned pmcc_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned pmcd_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pmce_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned xm2c_pins[] = { + TEGRA_PIN_DDR_A0, + TEGRA_PIN_DDR_A1, + TEGRA_PIN_DDR_A2, + TEGRA_PIN_DDR_A3, + TEGRA_PIN_DDR_A4, + TEGRA_PIN_DDR_A5, + TEGRA_PIN_DDR_A6, + TEGRA_PIN_DDR_A7, + TEGRA_PIN_DDR_A8, + TEGRA_PIN_DDR_A9, + TEGRA_PIN_DDR_A10, + TEGRA_PIN_DDR_A11, + TEGRA_PIN_DDR_A12, + TEGRA_PIN_DDR_A13, + TEGRA_PIN_DDR_A14, + TEGRA_PIN_DDR_CAS_N, + TEGRA_PIN_DDR_BA0, + TEGRA_PIN_DDR_BA1, + TEGRA_PIN_DDR_BA2, + TEGRA_PIN_DDR_DQS0P, + TEGRA_PIN_DDR_DQS0N, + TEGRA_PIN_DDR_DQS1P, + TEGRA_PIN_DDR_DQS1N, + TEGRA_PIN_DDR_DQS2P, + TEGRA_PIN_DDR_DQS2N, + TEGRA_PIN_DDR_DQS3P, + TEGRA_PIN_DDR_DQS3N, + TEGRA_PIN_DDR_CS0_N, + TEGRA_PIN_DDR_CS1_N, + TEGRA_PIN_DDR_CKE0, + TEGRA_PIN_DDR_CKE1, + TEGRA_PIN_DDR_CLK, + TEGRA_PIN_DDR_CLK_N, + TEGRA_PIN_DDR_DM0, + TEGRA_PIN_DDR_DM1, + TEGRA_PIN_DDR_DM2, + TEGRA_PIN_DDR_DM3, + TEGRA_PIN_DDR_ODT, + TEGRA_PIN_DDR_RAS_N, + TEGRA_PIN_DDR_WE_N, + TEGRA_PIN_DDR_QUSE0, + TEGRA_PIN_DDR_QUSE1, + TEGRA_PIN_DDR_QUSE2, + TEGRA_PIN_DDR_QUSE3, +}; + +static const unsigned xm2d_pins[] = { + TEGRA_PIN_DDR_DQ0, + TEGRA_PIN_DDR_DQ1, + TEGRA_PIN_DDR_DQ2, + TEGRA_PIN_DDR_DQ3, + TEGRA_PIN_DDR_DQ4, + TEGRA_PIN_DDR_DQ5, + TEGRA_PIN_DDR_DQ6, + TEGRA_PIN_DDR_DQ7, + TEGRA_PIN_DDR_DQ8, + TEGRA_PIN_DDR_DQ9, + TEGRA_PIN_DDR_DQ10, + TEGRA_PIN_DDR_DQ11, + TEGRA_PIN_DDR_DQ12, + TEGRA_PIN_DDR_DQ13, + TEGRA_PIN_DDR_DQ14, + TEGRA_PIN_DDR_DQ15, + TEGRA_PIN_DDR_DQ16, + TEGRA_PIN_DDR_DQ17, + TEGRA_PIN_DDR_DQ18, + TEGRA_PIN_DDR_DQ19, + TEGRA_PIN_DDR_DQ20, + TEGRA_PIN_DDR_DQ21, + TEGRA_PIN_DDR_DQ22, + TEGRA_PIN_DDR_DQ23, + TEGRA_PIN_DDR_DQ24, + TEGRA_PIN_DDR_DQ25, + TEGRA_PIN_DDR_DQ26, + TEGRA_PIN_DDR_DQ27, + TEGRA_PIN_DDR_DQ28, + TEGRA_PIN_DDR_DQ29, + TEGRA_PIN_DDR_DQ30, + TEGRA_PIN_DDR_DQ31, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_SYS_RESET, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_LED_BLINK_PBB0, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, + TEGRA_PIN_CLK_32_K_IN, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, + TEGRA_PIN_GMI_CS7_N_PI6, + TEGRA_PIN_GMI_DPD_PT7, + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_CS5_N_PI2, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_CS3_N_PK4, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_HIOW_N_PI0, + TEGRA_PIN_GMI_HIOR_N_PI1, + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_DAP_MCLK1_PW4, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_DAP_MCLK2_PW5, +}; + +static const unsigned drive_csus_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, + TEGRA_PIN_JTAG_RTCK_PU7, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_JTAG_TRST_N, + TEGRA_PIN_JTAG_TDO, + TEGRA_PIN_JTAG_TMS, + TEGRA_PIN_JTAG_TCK, + TEGRA_PIN_JTAG_TDI, + TEGRA_PIN_TEST_MODE_EN, +}; + +static const unsigned drive_lcd1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, + TEGRA_PIN_LCD_PWR2_PC6, + TEGRA_PIN_LCD_SDIN_PZ2, + TEGRA_PIN_LCD_SDOUT_PN5, + TEGRA_PIN_LCD_WR_N_PZ3, + TEGRA_PIN_LCD_CS0_N_PN4, + TEGRA_PIN_LCD_DC0_PN6, + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned drive_lcd2_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, + TEGRA_PIN_LCD_PCLK_PB3, + TEGRA_PIN_LCD_DE_PJ1, + TEGRA_PIN_LCD_HSYNC_PJ3, + TEGRA_PIN_LCD_VSYNC_PJ4, + TEGRA_PIN_LCD_D0_PE0, + TEGRA_PIN_LCD_D1_PE1, + TEGRA_PIN_LCD_D2_PE2, + TEGRA_PIN_LCD_D3_PE3, + TEGRA_PIN_LCD_D4_PE4, + TEGRA_PIN_LCD_D5_PE5, + TEGRA_PIN_LCD_D6_PE6, + TEGRA_PIN_LCD_D7_PE7, + TEGRA_PIN_LCD_D8_PF0, + TEGRA_PIN_LCD_D9_PF1, + TEGRA_PIN_LCD_D10_PF2, + TEGRA_PIN_LCD_D11_PF3, + TEGRA_PIN_LCD_D12_PF4, + TEGRA_PIN_LCD_D13_PF5, + TEGRA_PIN_LCD_D14_PF6, + TEGRA_PIN_LCD_D15_PF7, + TEGRA_PIN_LCD_D16_PM0, + TEGRA_PIN_LCD_D17_PM1, + TEGRA_PIN_LCD_D18_PM2, + TEGRA_PIN_LCD_D19_PM3, + TEGRA_PIN_LCD_D20_PM4, + TEGRA_PIN_LCD_D21_PM5, + TEGRA_PIN_LCD_D22_PM6, + TEGRA_PIN_LCD_D23_PM7, + TEGRA_PIN_LCD_CS1_N_PW0, + TEGRA_PIN_LCD_M1_PW1, + TEGRA_PIN_LCD_DC1_PV7, + TEGRA_PIN_HDMI_INT_N_PN7, +}; + +static const unsigned drive_sdmmc2_pins[] = { + TEGRA_PIN_SDIO3_DAT4_PD1, + TEGRA_PIN_SDIO3_DAT5_PD0, + TEGRA_PIN_SDIO3_DAT6_PD3, + TEGRA_PIN_SDIO3_DAT7_PD4, +}; + +static const unsigned drive_sdmmc3_pins[] = { + TEGRA_PIN_SDIO3_CLK_PA6, + TEGRA_PIN_SDIO3_CMD_PA7, + TEGRA_PIN_SDIO3_DAT0_PB7, + TEGRA_PIN_SDIO3_DAT1_PB6, + TEGRA_PIN_SDIO3_DAT2_PB5, + TEGRA_PIN_SDIO3_DAT3_PB4, + TEGRA_PIN_PV4, + TEGRA_PIN_PV5, + TEGRA_PIN_PV6, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_SPI2_MOSI_PX0, + TEGRA_PIN_SPI2_MISO_PX1, + TEGRA_PIN_SPI2_SCK_PX2, + TEGRA_PIN_SPI2_CS0_N_PX3, + TEGRA_PIN_SPI1_MOSI_PX4, + TEGRA_PIN_SPI1_SCK_PX5, + TEGRA_PIN_SPI1_CS0_N_PX6, + TEGRA_PIN_SPI1_MISO_PX7, + TEGRA_PIN_SPI2_CS1_N_PW2, + TEGRA_PIN_SPI2_CS2_N_PW3, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, + TEGRA_PIN_PV2, + TEGRA_PIN_PV3, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_RTS_N_PJ6, + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned drive_vi1_pins[] = { + TEGRA_PIN_VI_D0_PT4, + TEGRA_PIN_VI_D1_PD5, + TEGRA_PIN_VI_D2_PL0, + TEGRA_PIN_VI_D3_PL1, + TEGRA_PIN_VI_D4_PL2, + TEGRA_PIN_VI_D5_PL3, + TEGRA_PIN_VI_D6_PL4, + TEGRA_PIN_VI_D7_PL5, + TEGRA_PIN_VI_D8_PL6, + TEGRA_PIN_VI_D9_PL7, + TEGRA_PIN_VI_D10_PT2, + TEGRA_PIN_VI_D11_PT3, + TEGRA_PIN_VI_PCLK_PT0, + TEGRA_PIN_VI_VSYNC_PD6, + TEGRA_PIN_VI_HSYNC_PD7, +}; + +static const unsigned drive_vi2_pins[] = { + TEGRA_PIN_VI_GP0_PBB1, + TEGRA_PIN_CAM_I2C_SCL_PBB2, + TEGRA_PIN_CAM_I2C_SDA_PBB3, + TEGRA_PIN_VI_GP3_PBB4, + TEGRA_PIN_VI_GP4_PBB5, + TEGRA_PIN_VI_GP5_PD2, + TEGRA_PIN_VI_GP6_PA0, +}; + +static const unsigned drive_xm2a_pins[] = { + TEGRA_PIN_DDR_A0, + TEGRA_PIN_DDR_A1, + TEGRA_PIN_DDR_A2, + TEGRA_PIN_DDR_A3, + TEGRA_PIN_DDR_A4, + TEGRA_PIN_DDR_A5, + TEGRA_PIN_DDR_A6, + TEGRA_PIN_DDR_A7, + TEGRA_PIN_DDR_A8, + TEGRA_PIN_DDR_A9, + TEGRA_PIN_DDR_A10, + TEGRA_PIN_DDR_A11, + TEGRA_PIN_DDR_A12, + TEGRA_PIN_DDR_A13, + TEGRA_PIN_DDR_A14, + TEGRA_PIN_DDR_BA0, + TEGRA_PIN_DDR_BA1, + TEGRA_PIN_DDR_BA2, + TEGRA_PIN_DDR_CS0_N, + TEGRA_PIN_DDR_CS1_N, + TEGRA_PIN_DDR_ODT, + TEGRA_PIN_DDR_RAS_N, + TEGRA_PIN_DDR_CAS_N, + TEGRA_PIN_DDR_WE_N, + TEGRA_PIN_DDR_CKE0, + TEGRA_PIN_DDR_CKE1, +}; + +static const unsigned drive_xm2c_pins[] = { + TEGRA_PIN_DDR_DQS0P, + TEGRA_PIN_DDR_DQS0N, + TEGRA_PIN_DDR_DQS1P, + TEGRA_PIN_DDR_DQS1N, + TEGRA_PIN_DDR_DQS2P, + TEGRA_PIN_DDR_DQS2N, + TEGRA_PIN_DDR_DQS3P, + TEGRA_PIN_DDR_DQS3N, + TEGRA_PIN_DDR_QUSE0, + TEGRA_PIN_DDR_QUSE1, + TEGRA_PIN_DDR_QUSE2, + TEGRA_PIN_DDR_QUSE3, +}; + +static const unsigned drive_xm2d_pins[] = { + TEGRA_PIN_DDR_DQ0, + TEGRA_PIN_DDR_DQ1, + TEGRA_PIN_DDR_DQ2, + TEGRA_PIN_DDR_DQ3, + TEGRA_PIN_DDR_DQ4, + TEGRA_PIN_DDR_DQ5, + TEGRA_PIN_DDR_DQ6, + TEGRA_PIN_DDR_DQ7, + TEGRA_PIN_DDR_DQ8, + TEGRA_PIN_DDR_DQ9, + TEGRA_PIN_DDR_DQ10, + TEGRA_PIN_DDR_DQ11, + TEGRA_PIN_DDR_DQ12, + TEGRA_PIN_DDR_DQ13, + TEGRA_PIN_DDR_DQ14, + TEGRA_PIN_DDR_DQ15, + TEGRA_PIN_DDR_DQ16, + TEGRA_PIN_DDR_DQ17, + TEGRA_PIN_DDR_DQ18, + TEGRA_PIN_DDR_DQ19, + TEGRA_PIN_DDR_DQ20, + TEGRA_PIN_DDR_DQ21, + TEGRA_PIN_DDR_DQ22, + TEGRA_PIN_DDR_DQ23, + TEGRA_PIN_DDR_DQ24, + TEGRA_PIN_DDR_DQ25, + TEGRA_PIN_DDR_DQ26, + TEGRA_PIN_DDR_DQ27, + TEGRA_PIN_DDR_DQ28, + TEGRA_PIN_DDR_DQ29, + TEGRA_PIN_DDR_DQ30, + TEGRA_PIN_DDR_DQ31, + TEGRA_PIN_DDR_DM0, + TEGRA_PIN_DDR_DM1, + TEGRA_PIN_DDR_DM2, + TEGRA_PIN_DDR_DM3, +}; + +static const unsigned drive_xm2clk_pins[] = { + TEGRA_PIN_DDR_CLK, + TEGRA_PIN_DDR_CLK_N, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDIO1_CLK_PZ0, + TEGRA_PIN_SDIO1_CMD_PZ1, + TEGRA_PIN_SDIO1_DAT0_PY7, + TEGRA_PIN_SDIO1_DAT1_PY6, + TEGRA_PIN_SDIO1_DAT2_PY5, + TEGRA_PIN_SDIO1_DAT3_PY4, +}; + +static const unsigned drive_crt_pins[] = { + TEGRA_PIN_CRT_HSYNC, + TEGRA_PIN_CRT_VSYNC, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL, + TEGRA_PIN_DDC_SDA, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_GMI_AD20_PAA0, + TEGRA_PIN_GMI_AD21_PAA1, + TEGRA_PIN_GMI_AD22_PAA2, + TEGRA_PIN_GMI_AD23_PAA3, +}; + +static const unsigned drive_gmb_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned drive_gmc_pins[] = { + TEGRA_PIN_GMI_AD16_PJ7, + TEGRA_PIN_GMI_AD17_PB0, + TEGRA_PIN_GMI_AD18_PB1, + TEGRA_PIN_GMI_AD19_PK7, +}; + +static const unsigned drive_gmd_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_GMI_AD24_PAA4, + TEGRA_PIN_GMI_AD25_PAA5, + TEGRA_PIN_GMI_AD26_PAA6, + TEGRA_PIN_GMI_AD27_PAA7, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_OWC, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +enum tegra_mux { + TEGRA_MUX_AHB_CLK, + TEGRA_MUX_APB_CLK, + TEGRA_MUX_AUDIO_SYNC, + TEGRA_MUX_CRT, + TEGRA_MUX_DAP1, + TEGRA_MUX_DAP2, + TEGRA_MUX_DAP3, + TEGRA_MUX_DAP4, + TEGRA_MUX_DAP5, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_EMC_TEST0_DLL, + TEGRA_MUX_EMC_TEST1_DLL, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_INT, + TEGRA_MUX_HDMI, + TEGRA_MUX_I2CP, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_IDE, + TEGRA_MUX_IRDA, + TEGRA_MUX_KBC, + TEGRA_MUX_MIO, + TEGRA_MUX_MIPI_HS, + TEGRA_MUX_NAND, + TEGRA_MUX_OSC, + TEGRA_MUX_OWR, + TEGRA_MUX_PCIE, + TEGRA_MUX_PLLA_OUT, + TEGRA_MUX_PLLC_OUT1, + TEGRA_MUX_PLLM_OUT1, + TEGRA_MUX_PLLP_OUT2, + TEGRA_MUX_PLLP_OUT3, + TEGRA_MUX_PLLP_OUT4, + TEGRA_MUX_PWM, + TEGRA_MUX_PWR_INTR, + TEGRA_MUX_PWR_ON, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SDIO1, + TEGRA_MUX_SDIO2, + TEGRA_MUX_SDIO3, + TEGRA_MUX_SDIO4, + TEGRA_MUX_SFLASH, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI2_ALT, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_TRACE, + TEGRA_MUX_TWC, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_UARTE, + TEGRA_MUX_ULPI, + TEGRA_MUX_VI, + TEGRA_MUX_VI_SENSOR_CLK, + TEGRA_MUX_XIO, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra20_functions[] = { + FUNCTION(ahb_clk), + FUNCTION(apb_clk), + FUNCTION(audio_sync), + FUNCTION(crt), + FUNCTION(dap1), + FUNCTION(dap2), + FUNCTION(dap3), + FUNCTION(dap4), + FUNCTION(dap5), + FUNCTION(displaya), + FUNCTION(displayb), + FUNCTION(emc_test0_dll), + FUNCTION(emc_test1_dll), + FUNCTION(gmi), + FUNCTION(gmi_int), + FUNCTION(hdmi), + FUNCTION(i2cp), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(ide), + FUNCTION(irda), + FUNCTION(kbc), + FUNCTION(mio), + FUNCTION(mipi_hs), + FUNCTION(nand), + FUNCTION(osc), + FUNCTION(owr), + FUNCTION(pcie), + FUNCTION(plla_out), + FUNCTION(pllc_out1), + FUNCTION(pllm_out1), + FUNCTION(pllp_out2), + FUNCTION(pllp_out3), + FUNCTION(pllp_out4), + FUNCTION(pwm), + FUNCTION(pwr_intr), + FUNCTION(pwr_on), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sdio1), + FUNCTION(sdio2), + FUNCTION(sdio3), + FUNCTION(sdio4), + FUNCTION(sflash), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi2_alt), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(trace), + FUNCTION(twc), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(uarte), + FUNCTION(ulpi), + FUNCTION(vi), + FUNCTION(vi_sensor_clk), + FUNCTION(xio), +}; + +#define TRISTATE_REG_A 0x14 +#define PIN_MUX_CTL_REG_A 0x80 +#define PULLUPDOWN_REG_A 0xa0 +#define PINGROUP_REG_A 0x868 + +/* Pin group with mux control, and typically tri-state and pull-up/down too */ +#define MUX_PG(pg_name, f0, f1, f2, f3, \ + tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_ ## f0, \ + TEGRA_MUX_ ## f1, \ + TEGRA_MUX_ ## f2, \ + TEGRA_MUX_ ## f3, \ + }, \ + .mux_reg = ((mux_r) - PIN_MUX_CTL_REG_A), \ + .mux_bank = 1, \ + .mux_bit = mux_b, \ + .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ + .pupd_bank = 2, \ + .pupd_bit = pupd_b, \ + .tri_reg = ((tri_r) - TRISTATE_REG_A), \ + .tri_bank = 0, \ + .tri_bit = tri_b, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + +/* Pin groups with only pull up and pull down control */ +#define PULL_PG(pg_name, pupd_r, pupd_b) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = ((pupd_r) - PULLUPDOWN_REG_A), \ + .pupd_bank = 2, \ + .pupd_bit = pupd_b, \ + .drv_reg = -1, \ + } + +/* Pin groups for drive strength registers (configurable version) */ +#define DRV_PG_EXT(pg_name, r, hsm_b, schmitt_b, lpmd_b, \ + drvdn_b, drvup_b, \ + slwr_b, slwr_w, slwf_b, slwf_w) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .drv_reg = ((r) - PINGROUP_REG_A), \ + .drv_bank = 3, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = 5, \ + .drvup_bit = drvup_b, \ + .drvup_width = 5, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = -1, \ + } + +/* Pin groups for drive strength registers (simple version) */ +#define DRV_PG(pg_name, r) \ + DRV_PG_EXT(pg_name, r, 2, 3, 4, 12, 20, 28, 2, 30, 2) + +static const struct tegra_pingroup tegra20_groups[] = { + /* name, f0, f1, f2, f3, tri r/b, mux r/b, pupd r/b */ + MUX_PG(ata, IDE, NAND, GMI, RSVD4, 0x14, 0, 0x80, 24, 0xa0, 0), + MUX_PG(atb, IDE, NAND, GMI, SDIO4, 0x14, 1, 0x80, 16, 0xa0, 2), + MUX_PG(atc, IDE, NAND, GMI, SDIO4, 0x14, 2, 0x80, 22, 0xa0, 4), + MUX_PG(atd, IDE, NAND, GMI, SDIO4, 0x14, 3, 0x80, 20, 0xa0, 6), + MUX_PG(ate, IDE, NAND, GMI, RSVD4, 0x18, 25, 0x80, 12, 0xa0, 8), + MUX_PG(cdev1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, 0x14, 4, 0x88, 2, 0xa8, 0), + MUX_PG(cdev2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, 0x14, 5, 0x88, 4, 0xa8, 2), + MUX_PG(crtp, CRT, RSVD2, RSVD3, RSVD4, 0x20, 14, 0x98, 20, 0xa4, 24), + MUX_PG(csus, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, 0x14, 6, 0x88, 6, 0xac, 24), + MUX_PG(dap1, DAP1, RSVD2, GMI, SDIO2, 0x14, 7, 0x88, 20, 0xa0, 10), + MUX_PG(dap2, DAP2, TWC, RSVD3, GMI, 0x14, 8, 0x88, 22, 0xa0, 12), + MUX_PG(dap3, DAP3, RSVD2, RSVD3, RSVD4, 0x14, 9, 0x88, 24, 0xa0, 14), + MUX_PG(dap4, DAP4, RSVD2, GMI, RSVD4, 0x14, 10, 0x88, 26, 0xa0, 16), + MUX_PG(ddc, I2C2, RSVD2, RSVD3, RSVD4, 0x18, 31, 0x88, 0, 0xb0, 28), + MUX_PG(dta, RSVD1, SDIO2, VI, RSVD4, 0x14, 11, 0x84, 20, 0xa0, 18), + MUX_PG(dtb, RSVD1, RSVD2, VI, SPI1, 0x14, 12, 0x84, 22, 0xa0, 20), + MUX_PG(dtc, RSVD1, RSVD2, VI, RSVD4, 0x14, 13, 0x84, 26, 0xa0, 22), + MUX_PG(dtd, RSVD1, SDIO2, VI, RSVD4, 0x14, 14, 0x84, 28, 0xa0, 24), + MUX_PG(dte, RSVD1, RSVD2, VI, SPI1, 0x14, 15, 0x84, 30, 0xa0, 26), + MUX_PG(dtf, I2C3, RSVD2, VI, RSVD4, 0x20, 12, 0x98, 30, 0xa0, 28), + MUX_PG(gma, UARTE, SPI3, GMI, SDIO4, 0x14, 28, 0x84, 0, 0xb0, 20), + MUX_PG(gmb, IDE, NAND, GMI, GMI_INT, 0x18, 29, 0x88, 28, 0xb0, 22), + MUX_PG(gmc, UARTD, SPI4, GMI, SFLASH, 0x14, 29, 0x84, 2, 0xb0, 24), + MUX_PG(gmd, RSVD1, NAND, GMI, SFLASH, 0x18, 30, 0x88, 30, 0xb0, 26), + MUX_PG(gme, RSVD1, DAP5, GMI, SDIO4, 0x18, 0, 0x8c, 0, 0xa8, 24), + MUX_PG(gpu, PWM, UARTA, GMI, RSVD4, 0x14, 16, 0x8c, 4, 0xa4, 20), + MUX_PG(gpu7, RTCK, RSVD2, RSVD3, RSVD4, 0x20, 11, 0x98, 28, 0xa4, 6), + MUX_PG(gpv, PCIE, RSVD2, RSVD3, RSVD4, 0x14, 17, 0x8c, 2, 0xa0, 30), + MUX_PG(hdint, HDMI, RSVD2, RSVD3, RSVD4, 0x1c, 23, 0x84, 4, -1, -1), + MUX_PG(i2cp, I2CP, RSVD2, RSVD3, RSVD4, 0x14, 18, 0x88, 8, 0xa4, 2), + MUX_PG(irrx, UARTA, UARTB, GMI, SPI4, 0x14, 20, 0x88, 18, 0xa8, 22), + MUX_PG(irtx, UARTA, UARTB, GMI, SPI4, 0x14, 19, 0x88, 16, 0xa8, 20), + MUX_PG(kbca, KBC, NAND, SDIO2, EMC_TEST0_DLL, 0x14, 22, 0x88, 10, 0xa4, 8), + MUX_PG(kbcb, KBC, NAND, SDIO2, MIO, 0x14, 21, 0x88, 12, 0xa4, 10), + MUX_PG(kbcc, KBC, NAND, TRACE, EMC_TEST1_DLL, 0x18, 26, 0x88, 14, 0xa4, 12), + MUX_PG(kbcd, KBC, NAND, SDIO2, MIO, 0x20, 10, 0x98, 26, 0xa4, 14), + MUX_PG(kbce, KBC, NAND, OWR, RSVD4, 0x14, 26, 0x80, 28, 0xb0, 2), + MUX_PG(kbcf, KBC, NAND, TRACE, MIO, 0x14, 27, 0x80, 26, 0xb0, 0), + MUX_PG(lcsn, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 31, 0x90, 12, -1, -1), + MUX_PG(ld0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 0, 0x94, 0, -1, -1), + MUX_PG(ld1, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 1, 0x94, 2, -1, -1), + MUX_PG(ld2, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 2, 0x94, 4, -1, -1), + MUX_PG(ld3, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 3, 0x94, 6, -1, -1), + MUX_PG(ld4, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 4, 0x94, 8, -1, -1), + MUX_PG(ld5, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 5, 0x94, 10, -1, -1), + MUX_PG(ld6, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 6, 0x94, 12, -1, -1), + MUX_PG(ld7, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 7, 0x94, 14, -1, -1), + MUX_PG(ld8, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 8, 0x94, 16, -1, -1), + MUX_PG(ld9, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 9, 0x94, 18, -1, -1), + MUX_PG(ld10, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 10, 0x94, 20, -1, -1), + MUX_PG(ld11, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 11, 0x94, 22, -1, -1), + MUX_PG(ld12, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 12, 0x94, 24, -1, -1), + MUX_PG(ld13, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 13, 0x94, 26, -1, -1), + MUX_PG(ld14, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 14, 0x94, 28, -1, -1), + MUX_PG(ld15, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 15, 0x94, 30, -1, -1), + MUX_PG(ld16, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 16, 0x98, 0, -1, -1), + MUX_PG(ld17, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 17, 0x98, 2, -1, -1), + MUX_PG(ldc, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 30, 0x90, 14, -1, -1), + MUX_PG(ldi, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 6, 0x98, 16, -1, -1), + MUX_PG(lhp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 18, 0x98, 10, -1, -1), + MUX_PG(lhp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 19, 0x98, 4, -1, -1), + MUX_PG(lhp2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 20, 0x98, 6, -1, -1), + MUX_PG(lhs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x20, 7, 0x90, 22, -1, -1), + MUX_PG(lm0, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x1c, 24, 0x90, 26, -1, -1), + MUX_PG(lm1, DISPLAYA, DISPLAYB, RSVD3, CRT, 0x1c, 25, 0x90, 28, -1, -1), + MUX_PG(lpp, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 8, 0x98, 14, -1, -1), + MUX_PG(lpw0, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 3, 0x90, 0, -1, -1), + MUX_PG(lpw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x20, 4, 0x90, 2, -1, -1), + MUX_PG(lpw2, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 5, 0x90, 4, -1, -1), + MUX_PG(lsc0, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 27, 0x90, 18, -1, -1), + MUX_PG(lsc1, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 28, 0x90, 20, -1, -1), + MUX_PG(lsck, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x1c, 29, 0x90, 16, -1, -1), + MUX_PG(lsda, DISPLAYA, DISPLAYB, SPI3, HDMI, 0x20, 1, 0x90, 8, -1, -1), + MUX_PG(lsdi, DISPLAYA, DISPLAYB, SPI3, RSVD4, 0x20, 2, 0x90, 6, -1, -1), + MUX_PG(lspi, DISPLAYA, DISPLAYB, XIO, HDMI, 0x20, 0, 0x90, 10, -1, -1), + MUX_PG(lvp0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 21, 0x90, 30, -1, -1), + MUX_PG(lvp1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x1c, 22, 0x98, 8, -1, -1), + MUX_PG(lvs, DISPLAYA, DISPLAYB, XIO, RSVD4, 0x1c, 26, 0x90, 24, -1, -1), + MUX_PG(owc, OWR, RSVD2, RSVD3, RSVD4, 0x14, 31, 0x84, 8, 0xb0, 30), + MUX_PG(pmc, PWR_ON, PWR_INTR, RSVD3, RSVD4, 0x14, 23, 0x98, 18, -1, -1), + MUX_PG(pta, I2C2, HDMI, GMI, RSVD4, 0x14, 24, 0x98, 22, 0xa4, 4), + MUX_PG(rm, I2C1, RSVD2, RSVD3, RSVD4, 0x14, 25, 0x80, 14, 0xa4, 0), + MUX_PG(sdb, UARTA, PWM, SDIO3, SPI2, 0x20, 15, 0x8c, 10, -1, -1), + MUX_PG(sdc, PWM, TWC, SDIO3, SPI3, 0x18, 1, 0x8c, 12, 0xac, 28), + MUX_PG(sdd, UARTA, PWM, SDIO3, SPI3, 0x18, 2, 0x8c, 14, 0xac, 30), + MUX_PG(sdio1, SDIO1, RSVD2, UARTE, UARTA, 0x14, 30, 0x80, 30, 0xb0, 18), + MUX_PG(slxa, PCIE, SPI4, SDIO3, SPI2, 0x18, 3, 0x84, 6, 0xa4, 22), + MUX_PG(slxc, SPDIF, SPI4, SDIO3, SPI2, 0x18, 5, 0x84, 10, 0xa4, 26), + MUX_PG(slxd, SPDIF, SPI4, SDIO3, SPI2, 0x18, 6, 0x84, 12, 0xa4, 28), + MUX_PG(slxk, PCIE, SPI4, SDIO3, SPI2, 0x18, 7, 0x84, 14, 0xa4, 30), + MUX_PG(spdi, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 8, 0x8c, 8, 0xa4, 16), + MUX_PG(spdo, SPDIF, RSVD2, I2C1, SDIO2, 0x18, 9, 0x8c, 6, 0xa4, 18), + MUX_PG(spia, SPI1, SPI2, SPI3, GMI, 0x18, 10, 0x8c, 30, 0xa8, 4), + MUX_PG(spib, SPI1, SPI2, SPI3, GMI, 0x18, 11, 0x8c, 28, 0xa8, 6), + MUX_PG(spic, SPI1, SPI2, SPI3, GMI, 0x18, 12, 0x8c, 26, 0xa8, 8), + MUX_PG(spid, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 13, 0x8c, 24, 0xa8, 10), + MUX_PG(spie, SPI2, SPI1, SPI2_ALT, GMI, 0x18, 14, 0x8c, 22, 0xa8, 12), + MUX_PG(spif, SPI3, SPI1, SPI2, RSVD4, 0x18, 15, 0x8c, 20, 0xa8, 14), + MUX_PG(spig, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 16, 0x8c, 18, 0xa8, 16), + MUX_PG(spih, SPI3, SPI2, SPI2_ALT, I2C1, 0x18, 17, 0x8c, 16, 0xa8, 18), + MUX_PG(uaa, SPI3, MIPI_HS, UARTA, ULPI, 0x18, 18, 0x80, 0, 0xac, 0), + MUX_PG(uab, SPI2, MIPI_HS, UARTA, ULPI, 0x18, 19, 0x80, 2, 0xac, 2), + MUX_PG(uac, OWR, RSVD2, RSVD3, RSVD4, 0x18, 20, 0x80, 4, 0xac, 4), + MUX_PG(uad, IRDA, SPDIF, UARTA, SPI4, 0x18, 21, 0x80, 6, 0xac, 6), + MUX_PG(uca, UARTC, RSVD2, GMI, RSVD4, 0x18, 22, 0x84, 16, 0xac, 8), + MUX_PG(ucb, UARTC, PWM, GMI, RSVD4, 0x18, 23, 0x84, 18, 0xac, 10), + MUX_PG(uda, SPI1, RSVD2, UARTD, ULPI, 0x20, 13, 0x80, 8, 0xb0, 16), + /* pg_name, pupd_r/b */ + PULL_PG(ck32, 0xb0, 14), + PULL_PG(ddrc, 0xac, 26), + PULL_PG(pmca, 0xb0, 4), + PULL_PG(pmcb, 0xb0, 6), + PULL_PG(pmcc, 0xb0, 8), + PULL_PG(pmcd, 0xb0, 10), + PULL_PG(pmce, 0xb0, 12), + PULL_PG(xm2c, 0xa8, 30), + PULL_PG(xm2d, 0xa8, 28), + PULL_PG(ls, 0xac, 20), + PULL_PG(lc, 0xac, 22), + PULL_PG(ld17_0, 0xac, 12), + PULL_PG(ld19_18, 0xac, 14), + PULL_PG(ld21_20, 0xac, 16), + PULL_PG(ld23_22, 0xac, 18), + /* pg_name, r */ + DRV_PG(ao1, 0x868), + DRV_PG(ao2, 0x86c), + DRV_PG(at1, 0x870), + DRV_PG(at2, 0x874), + DRV_PG(cdev1, 0x878), + DRV_PG(cdev2, 0x87c), + DRV_PG(csus, 0x880), + DRV_PG(dap1, 0x884), + DRV_PG(dap2, 0x888), + DRV_PG(dap3, 0x88c), + DRV_PG(dap4, 0x890), + DRV_PG(dbg, 0x894), + DRV_PG(lcd1, 0x898), + DRV_PG(lcd2, 0x89c), + DRV_PG(sdmmc2, 0x8a0), + DRV_PG(sdmmc3, 0x8a4), + DRV_PG(spi, 0x8a8), + DRV_PG(uaa, 0x8ac), + DRV_PG(uab, 0x8b0), + DRV_PG(uart2, 0x8b4), + DRV_PG(uart3, 0x8b8), + DRV_PG(vi1, 0x8bc), + DRV_PG(vi2, 0x8c0), + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvup_b, slwr_b, slwr_w, slwf_b, slwf_w */ + DRV_PG_EXT(xm2a, 0x8c4, -1, -1, 4, 14, 19, 24, 4, 28, 4), + DRV_PG_EXT(xm2c, 0x8c8, -1, 3, -1, 14, 19, 24, 4, 28, 4), + DRV_PG_EXT(xm2d, 0x8cc, -1, 3, -1, 14, 19, 24, 4, 28, 4), + DRV_PG_EXT(xm2clk, 0x8d0, -1, -1, -1, 14, 19, 24, 4, 28, 4), + /* pg_name, r */ + DRV_PG(sdio1, 0x8e0), + DRV_PG(crt, 0x8ec), + DRV_PG(ddc, 0x8f0), + DRV_PG(gma, 0x8f4), + DRV_PG(gmb, 0x8f8), + DRV_PG(gmc, 0x8fc), + DRV_PG(gmd, 0x900), + DRV_PG(gme, 0x904), + DRV_PG(owr, 0x908), + DRV_PG(uda, 0x90c), +}; + +static const struct tegra_pinctrl_soc_data tegra20_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra20_pins, + .npins = ARRAY_SIZE(tegra20_pins), + .functions = tegra20_functions, + .nfunctions = ARRAY_SIZE(tegra20_functions), + .groups = tegra20_groups, + .ngroups = ARRAY_SIZE(tegra20_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra20_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra20_pinctrl); +} + +static const struct of_device_id tegra20_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra20-pinmux", }, + { }, +}; + +static struct platform_driver tegra20_pinctrl_driver = { + .driver = { + .name = "tegra20-pinctrl", + .of_match_table = tegra20_pinctrl_of_match, + }, + .probe = tegra20_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra20_pinctrl_driver); + +MODULE_AUTHOR("Stephen Warren "); +MODULE_DESCRIPTION("NVIDIA Tegra20 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, tegra20_pinctrl_of_match); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra210.c b/drivers/pinctrl/tegra/pinctrl-tegra210.c new file mode 100644 index 000000000000..252b464901c0 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra210.c @@ -0,0 +1,1588 @@ +/* + * Pinctrl data for the NVIDIA Tegra210 pinmux + * + * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. + * + * 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 "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_PEX_L0_RST_N_PA0 _GPIO(0) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PA1 _GPIO(1) +#define TEGRA_PIN_PEX_WAKE_N_PA2 _GPIO(2) +#define TEGRA_PIN_PEX_L1_RST_N_PA3 _GPIO(3) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PA4 _GPIO(4) +#define TEGRA_PIN_SATA_LED_ACTIVE_PA5 _GPIO(5) +#define TEGRA_PIN_PA6 _GPIO(6) +#define TEGRA_PIN_DAP1_FS_PB0 _GPIO(8) +#define TEGRA_PIN_DAP1_DIN_PB1 _GPIO(9) +#define TEGRA_PIN_DAP1_DOUT_PB2 _GPIO(10) +#define TEGRA_PIN_DAP1_SCLK_PB3 _GPIO(11) +#define TEGRA_PIN_SPI2_MOSI_PB4 _GPIO(12) +#define TEGRA_PIN_SPI2_MISO_PB5 _GPIO(13) +#define TEGRA_PIN_SPI2_SCK_PB6 _GPIO(14) +#define TEGRA_PIN_SPI2_CS0_PB7 _GPIO(15) +#define TEGRA_PIN_SPI1_MOSI_PC0 _GPIO(16) +#define TEGRA_PIN_SPI1_MISO_PC1 _GPIO(17) +#define TEGRA_PIN_SPI1_SCK_PC2 _GPIO(18) +#define TEGRA_PIN_SPI1_CS0_PC3 _GPIO(19) +#define TEGRA_PIN_SPI1_CS1_PC4 _GPIO(20) +#define TEGRA_PIN_SPI4_SCK_PC5 _GPIO(21) +#define TEGRA_PIN_SPI4_CS0_PC6 _GPIO(22) +#define TEGRA_PIN_SPI4_MOSI_PC7 _GPIO(23) +#define TEGRA_PIN_SPI4_MISO_PD0 _GPIO(24) +#define TEGRA_PIN_UART3_TX_PD1 _GPIO(25) +#define TEGRA_PIN_UART3_RX_PD2 _GPIO(26) +#define TEGRA_PIN_UART3_RTS_PD3 _GPIO(27) +#define TEGRA_PIN_UART3_CTS_PD4 _GPIO(28) +#define TEGRA_PIN_DMIC1_CLK_PE0 _GPIO(32) +#define TEGRA_PIN_DMIC1_DAT_PE1 _GPIO(33) +#define TEGRA_PIN_DMIC2_CLK_PE2 _GPIO(34) +#define TEGRA_PIN_DMIC2_DAT_PE3 _GPIO(35) +#define TEGRA_PIN_DMIC3_CLK_PE4 _GPIO(36) +#define TEGRA_PIN_DMIC3_DAT_PE5 _GPIO(37) +#define TEGRA_PIN_PE6 _GPIO(38) +#define TEGRA_PIN_PE7 _GPIO(39) +#define TEGRA_PIN_GEN3_I2C_SCL_PF0 _GPIO(40) +#define TEGRA_PIN_GEN3_I2C_SDA_PF1 _GPIO(41) +#define TEGRA_PIN_UART2_TX_PG0 _GPIO(48) +#define TEGRA_PIN_UART2_RX_PG1 _GPIO(49) +#define TEGRA_PIN_UART2_RTS_PG2 _GPIO(50) +#define TEGRA_PIN_UART2_CTS_PG3 _GPIO(51) +#define TEGRA_PIN_WIFI_EN_PH0 _GPIO(56) +#define TEGRA_PIN_WIFI_RST_PH1 _GPIO(57) +#define TEGRA_PIN_WIFI_WAKE_AP_PH2 _GPIO(58) +#define TEGRA_PIN_AP_WAKE_BT_PH3 _GPIO(59) +#define TEGRA_PIN_BT_RST_PH4 _GPIO(60) +#define TEGRA_PIN_BT_WAKE_AP_PH5 _GPIO(61) +#define TEGRA_PIN_PH6 _GPIO(62) +#define TEGRA_PIN_AP_WAKE_NFC_PH7 _GPIO(63) +#define TEGRA_PIN_NFC_EN_PI0 _GPIO(64) +#define TEGRA_PIN_NFC_INT_PI1 _GPIO(65) +#define TEGRA_PIN_GPS_EN_PI2 _GPIO(66) +#define TEGRA_PIN_GPS_RST_PI3 _GPIO(67) +#define TEGRA_PIN_UART4_TX_PI4 _GPIO(68) +#define TEGRA_PIN_UART4_RX_PI5 _GPIO(69) +#define TEGRA_PIN_UART4_RTS_PI6 _GPIO(70) +#define TEGRA_PIN_UART4_CTS_PI7 _GPIO(71) +#define TEGRA_PIN_GEN1_I2C_SDA_PJ0 _GPIO(72) +#define TEGRA_PIN_GEN1_I2C_SCL_PJ1 _GPIO(73) +#define TEGRA_PIN_GEN2_I2C_SCL_PJ2 _GPIO(74) +#define TEGRA_PIN_GEN2_I2C_SDA_PJ3 _GPIO(75) +#define TEGRA_PIN_DAP4_FS_PJ4 _GPIO(76) +#define TEGRA_PIN_DAP4_DIN_PJ5 _GPIO(77) +#define TEGRA_PIN_DAP4_DOUT_PJ6 _GPIO(78) +#define TEGRA_PIN_DAP4_SCLK_PJ7 _GPIO(79) +#define TEGRA_PIN_PK0 _GPIO(80) +#define TEGRA_PIN_PK1 _GPIO(81) +#define TEGRA_PIN_PK2 _GPIO(82) +#define TEGRA_PIN_PK3 _GPIO(83) +#define TEGRA_PIN_PK4 _GPIO(84) +#define TEGRA_PIN_PK5 _GPIO(85) +#define TEGRA_PIN_PK6 _GPIO(86) +#define TEGRA_PIN_PK7 _GPIO(87) +#define TEGRA_PIN_PL0 _GPIO(88) +#define TEGRA_PIN_PL1 _GPIO(89) +#define TEGRA_PIN_SDMMC1_CLK_PM0 _GPIO(96) +#define TEGRA_PIN_SDMMC1_CMD_PM1 _GPIO(97) +#define TEGRA_PIN_SDMMC1_DAT3_PM2 _GPIO(98) +#define TEGRA_PIN_SDMMC1_DAT2_PM3 _GPIO(99) +#define TEGRA_PIN_SDMMC1_DAT1_PM4 _GPIO(100) +#define TEGRA_PIN_SDMMC1_DAT0_PM5 _GPIO(101) +#define TEGRA_PIN_SDMMC3_CLK_PP0 _GPIO(120) +#define TEGRA_PIN_SDMMC3_CMD_PP1 _GPIO(121) +#define TEGRA_PIN_SDMMC3_DAT3_PP2 _GPIO(122) +#define TEGRA_PIN_SDMMC3_DAT2_PP3 _GPIO(123) +#define TEGRA_PIN_SDMMC3_DAT1_PP4 _GPIO(124) +#define TEGRA_PIN_SDMMC3_DAT0_PP5 _GPIO(125) +#define TEGRA_PIN_CAM1_MCLK_PS0 _GPIO(144) +#define TEGRA_PIN_CAM2_MCLK_PS1 _GPIO(145) +#define TEGRA_PIN_CAM_I2C_SCL_PS2 _GPIO(146) +#define TEGRA_PIN_CAM_I2C_SDA_PS3 _GPIO(147) +#define TEGRA_PIN_CAM_RST_PS4 _GPIO(148) +#define TEGRA_PIN_CAM_AF_EN_PS5 _GPIO(149) +#define TEGRA_PIN_CAM_FLASH_EN_PS6 _GPIO(150) +#define TEGRA_PIN_CAM1_PWDN_PS7 _GPIO(151) +#define TEGRA_PIN_CAM2_PWDN_PT0 _GPIO(152) +#define TEGRA_PIN_CAM1_STROBE_PT1 _GPIO(153) +#define TEGRA_PIN_UART1_TX_PU0 _GPIO(160) +#define TEGRA_PIN_UART1_RX_PU1 _GPIO(161) +#define TEGRA_PIN_UART1_RTS_PU2 _GPIO(162) +#define TEGRA_PIN_UART1_CTS_PU3 _GPIO(163) +#define TEGRA_PIN_LCD_BL_PWM_PV0 _GPIO(168) +#define TEGRA_PIN_LCD_BL_EN_PV1 _GPIO(169) +#define TEGRA_PIN_LCD_RST_PV2 _GPIO(170) +#define TEGRA_PIN_LCD_GPIO1_PV3 _GPIO(171) +#define TEGRA_PIN_LCD_GPIO2_PV4 _GPIO(172) +#define TEGRA_PIN_AP_READY_PV5 _GPIO(173) +#define TEGRA_PIN_TOUCH_RST_PV6 _GPIO(174) +#define TEGRA_PIN_TOUCH_CLK_PV7 _GPIO(175) +#define TEGRA_PIN_MODEM_WAKE_AP_PX0 _GPIO(184) +#define TEGRA_PIN_TOUCH_INT_PX1 _GPIO(185) +#define TEGRA_PIN_MOTION_INT_PX2 _GPIO(186) +#define TEGRA_PIN_ALS_PROX_INT_PX3 _GPIO(187) +#define TEGRA_PIN_TEMP_ALERT_PX4 _GPIO(188) +#define TEGRA_PIN_BUTTON_POWER_ON_PX5 _GPIO(189) +#define TEGRA_PIN_BUTTON_VOL_UP_PX6 _GPIO(190) +#define TEGRA_PIN_BUTTON_VOL_DOWN_PX7 _GPIO(191) +#define TEGRA_PIN_BUTTON_SLIDE_SW_PY0 _GPIO(192) +#define TEGRA_PIN_BUTTON_HOME_PY1 _GPIO(193) +#define TEGRA_PIN_LCD_TE_PY2 _GPIO(194) +#define TEGRA_PIN_PWR_I2C_SCL_PY3 _GPIO(195) +#define TEGRA_PIN_PWR_I2C_SDA_PY4 _GPIO(196) +#define TEGRA_PIN_CLK_32K_OUT_PY5 _GPIO(197) +#define TEGRA_PIN_PZ0 _GPIO(200) +#define TEGRA_PIN_PZ1 _GPIO(201) +#define TEGRA_PIN_PZ2 _GPIO(202) +#define TEGRA_PIN_PZ3 _GPIO(203) +#define TEGRA_PIN_PZ4 _GPIO(204) +#define TEGRA_PIN_PZ5 _GPIO(205) +#define TEGRA_PIN_DAP2_FS_PAA0 _GPIO(208) +#define TEGRA_PIN_DAP2_SCLK_PAA1 _GPIO(209) +#define TEGRA_PIN_DAP2_DIN_PAA2 _GPIO(210) +#define TEGRA_PIN_DAP2_DOUT_PAA3 _GPIO(211) +#define TEGRA_PIN_AUD_MCLK_PBB0 _GPIO(216) +#define TEGRA_PIN_DVFS_PWM_PBB1 _GPIO(217) +#define TEGRA_PIN_DVFS_CLK_PBB2 _GPIO(218) +#define TEGRA_PIN_GPIO_X1_AUD_PBB3 _GPIO(219) +#define TEGRA_PIN_GPIO_X3_AUD_PBB4 _GPIO(220) +#define TEGRA_PIN_HDMI_CEC_PCC0 _GPIO(224) +#define TEGRA_PIN_HDMI_INT_DP_HPD_PCC1 _GPIO(225) +#define TEGRA_PIN_SPDIF_OUT_PCC2 _GPIO(226) +#define TEGRA_PIN_SPDIF_IN_PCC3 _GPIO(227) +#define TEGRA_PIN_USB_VBUS_EN0_PCC4 _GPIO(228) +#define TEGRA_PIN_USB_VBUS_EN1_PCC5 _GPIO(229) +#define TEGRA_PIN_DP_HPD0_PCC6 _GPIO(230) +#define TEGRA_PIN_PCC7 _GPIO(231) +#define TEGRA_PIN_SPI2_CS1_PDD0 _GPIO(232) +#define TEGRA_PIN_QSPI_SCK_PEE0 _GPIO(240) +#define TEGRA_PIN_QSPI_CS_N_PEE1 _GPIO(241) +#define TEGRA_PIN_QSPI_IO0_PEE2 _GPIO(242) +#define TEGRA_PIN_QSPI_IO1_PEE3 _GPIO(243) +#define TEGRA_PIN_QSPI_IO2_PEE4 _GPIO(244) +#define TEGRA_PIN_QSPI_IO3_PEE5 _GPIO(245) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_QSPI_IO3_PEE5 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CORE_PWR_REQ _PIN(0) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(1) +#define TEGRA_PIN_PWR_INT_N _PIN(2) +#define TEGRA_PIN_CLK_32K_IN _PIN(3) +#define TEGRA_PIN_JTAG_RTCK _PIN(4) +#define TEGRA_PIN_BATT_BCL _PIN(5) +#define TEGRA_PIN_CLK_REQ _PIN(6) +#define TEGRA_PIN_SHUTDOWN _PIN(7) + +static const struct pinctrl_pin_desc tegra210_pins[] = { + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PA0, "PEX_L0_RST_N PA0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, "PEX_L0_CLKREQ_N PA1"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PA2, "PEX_WAKE_N PA2"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PA3, "PEX_L1_RST_N PA3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, "PEX_L1_CLKREQ_N PA4"), + PINCTRL_PIN(TEGRA_PIN_SATA_LED_ACTIVE_PA5, "SATA_LED_ACTIVE PA5"), + PINCTRL_PIN(TEGRA_PIN_PA6, "PA6"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PB0, "DAP1_FS PB0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PB1, "DAP1_DIN PB1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PB2, "DAP1_DOUT PB2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PB3, "DAP1_SCLK PB3"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PB4, "SPI2_MOSI PB4"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PB5, "SPI2_MISO PB5"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PB6, "SPI2_SCK PB6"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_PB7, "SPI2_CS0 PB7"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PC0, "SPI1_MOSI PC0"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PC1, "SPI1_MISO PC1"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PC2, "SPI1_SCK PC2"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_PC3, "SPI1_CS0 PC3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS1_PC4, "SPI1_CS1 PC4"), + PINCTRL_PIN(TEGRA_PIN_SPI4_SCK_PC5, "SPI4_SCK PC5"), + PINCTRL_PIN(TEGRA_PIN_SPI4_CS0_PC6, "SPI4_CS0 PC6"), + PINCTRL_PIN(TEGRA_PIN_SPI4_MOSI_PC7, "SPI4_MOSI PC7"), + PINCTRL_PIN(TEGRA_PIN_SPI4_MISO_PD0, "SPI4_MISO PD0"), + PINCTRL_PIN(TEGRA_PIN_UART3_TX_PD1, "UART3_TX PD1"), + PINCTRL_PIN(TEGRA_PIN_UART3_RX_PD2, "UART3_RX PD2"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_PD3, "UART3_RTS PD3"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_PD4, "UART3_CTS PD4"), + PINCTRL_PIN(TEGRA_PIN_DMIC1_CLK_PE0, "DMIC1_CLK PE0"), + PINCTRL_PIN(TEGRA_PIN_DMIC1_DAT_PE1, "DMIC1_DAT PE1"), + PINCTRL_PIN(TEGRA_PIN_DMIC2_CLK_PE2, "DMIC2_CLK PE2"), + PINCTRL_PIN(TEGRA_PIN_DMIC2_DAT_PE3, "DMIC2_DAT PE3"), + PINCTRL_PIN(TEGRA_PIN_DMIC3_CLK_PE4, "DMIC3_CLK PE4"), + PINCTRL_PIN(TEGRA_PIN_DMIC3_DAT_PE5, "DMIC3_DAT PE5"), + PINCTRL_PIN(TEGRA_PIN_PE6, "PE6"), + PINCTRL_PIN(TEGRA_PIN_PE7, "PE7"), + PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SCL_PF0, "GEN3_I2C_SCL PF0"), + PINCTRL_PIN(TEGRA_PIN_GEN3_I2C_SDA_PF1, "GEN3_I2C_SDA PF1"), + PINCTRL_PIN(TEGRA_PIN_UART2_TX_PG0, "UART2_TX PG0"), + PINCTRL_PIN(TEGRA_PIN_UART2_RX_PG1, "UART2_RX PG1"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_PG2, "UART2_RTS PG2"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_PG3, "UART2_CTS PG3"), + PINCTRL_PIN(TEGRA_PIN_WIFI_EN_PH0, "WIFI_EN PH0"), + PINCTRL_PIN(TEGRA_PIN_WIFI_RST_PH1, "WIFI_RST PH1"), + PINCTRL_PIN(TEGRA_PIN_WIFI_WAKE_AP_PH2, "WIFI_WAKE_AP PH2"), + PINCTRL_PIN(TEGRA_PIN_AP_WAKE_BT_PH3, "AP_WAKE_BT PH3"), + PINCTRL_PIN(TEGRA_PIN_BT_RST_PH4, "BT_RST PH4"), + PINCTRL_PIN(TEGRA_PIN_BT_WAKE_AP_PH5, "BT_WAKE_AP PH5"), + PINCTRL_PIN(TEGRA_PIN_PH6, "PH6"), + PINCTRL_PIN(TEGRA_PIN_AP_WAKE_NFC_PH7, "AP_WAKE_NFC PH7"), + PINCTRL_PIN(TEGRA_PIN_NFC_EN_PI0, "NFC_EN PI0"), + PINCTRL_PIN(TEGRA_PIN_NFC_INT_PI1, "NFC_INT PI1"), + PINCTRL_PIN(TEGRA_PIN_GPS_EN_PI2, "GPS_EN PI2"), + PINCTRL_PIN(TEGRA_PIN_GPS_RST_PI3, "GPS_RST PI3"), + PINCTRL_PIN(TEGRA_PIN_UART4_TX_PI4, "UART4_TX PI4"), + PINCTRL_PIN(TEGRA_PIN_UART4_RX_PI5, "UART4_RX PI5"), + PINCTRL_PIN(TEGRA_PIN_UART4_RTS_PI6, "UART4_RTS PI6"), + PINCTRL_PIN(TEGRA_PIN_UART4_CTS_PI7, "UART4_CTS PI7"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PJ0, "GEN1_I2C_SDA PJ0"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PJ1, "GEN1_I2C_SCL PJ1"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PJ2, "GEN2_I2C_SCL PJ2"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PJ3, "GEN2_I2C_SDA PJ3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PJ4, "DAP4_FS PJ4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PJ5, "DAP4_DIN PJ5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PJ6, "DAP4_DOUT PJ6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PJ7, "DAP4_SCLK PJ7"), + PINCTRL_PIN(TEGRA_PIN_PK0, "PK0"), + PINCTRL_PIN(TEGRA_PIN_PK1, "PK1"), + PINCTRL_PIN(TEGRA_PIN_PK2, "PK2"), + PINCTRL_PIN(TEGRA_PIN_PK3, "PK3"), + PINCTRL_PIN(TEGRA_PIN_PK4, "PK4"), + PINCTRL_PIN(TEGRA_PIN_PK5, "PK5"), + PINCTRL_PIN(TEGRA_PIN_PK6, "PK6"), + PINCTRL_PIN(TEGRA_PIN_PK7, "PK7"), + PINCTRL_PIN(TEGRA_PIN_PL0, "PL0"), + PINCTRL_PIN(TEGRA_PIN_PL1, "PL1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PM0, "SDMMC1_CLK PM0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PM1, "SDMMC1_CMD PM1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PM2, "SDMMC1_DAT3 PM2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PM3, "SDMMC1_DAT2 PM3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PM4, "SDMMC1_DAT1 PM4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PM5, "SDMMC1_DAT0 PM5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PP0, "SDMMC3_CLK PP0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PP1, "SDMMC3_CMD PP1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PP2, "SDMMC3_DAT3 PP2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PP3, "SDMMC3_DAT2 PP3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PP4, "SDMMC3_DAT1 PP4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PP5, "SDMMC3_DAT0 PP5"), + PINCTRL_PIN(TEGRA_PIN_CAM1_MCLK_PS0, "CAM1_MCLK PS0"), + PINCTRL_PIN(TEGRA_PIN_CAM2_MCLK_PS1, "CAM2_MCLK PS1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PS2, "CAM_I2C_SCL PS2"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PS3, "CAM_I2C_SDA PS3"), + PINCTRL_PIN(TEGRA_PIN_CAM_RST_PS4, "CAM_RST PS4"), + PINCTRL_PIN(TEGRA_PIN_CAM_AF_EN_PS5, "CAM_AF_EN PS5"), + PINCTRL_PIN(TEGRA_PIN_CAM_FLASH_EN_PS6, "CAM_FLASH_EN PS6"), + PINCTRL_PIN(TEGRA_PIN_CAM1_PWDN_PS7, "CAM1_PWDN PS7"), + PINCTRL_PIN(TEGRA_PIN_CAM2_PWDN_PT0, "CAM2_PWDN PT0"), + PINCTRL_PIN(TEGRA_PIN_CAM1_STROBE_PT1, "CAM1_STROBE PT1"), + PINCTRL_PIN(TEGRA_PIN_UART1_TX_PU0, "UART1_TX PU0"), + PINCTRL_PIN(TEGRA_PIN_UART1_RX_PU1, "UART1_RX PU1"), + PINCTRL_PIN(TEGRA_PIN_UART1_RTS_PU2, "UART1_RTS PU2"), + PINCTRL_PIN(TEGRA_PIN_UART1_CTS_PU3, "UART1_CTS PU3"), + PINCTRL_PIN(TEGRA_PIN_LCD_BL_PWM_PV0, "LCD_BL_PWM PV0"), + PINCTRL_PIN(TEGRA_PIN_LCD_BL_EN_PV1, "LCD_BL_EN PV1"), + PINCTRL_PIN(TEGRA_PIN_LCD_RST_PV2, "LCD_RST PV2"), + PINCTRL_PIN(TEGRA_PIN_LCD_GPIO1_PV3, "LCD_GPIO1 PV3"), + PINCTRL_PIN(TEGRA_PIN_LCD_GPIO2_PV4, "LCD_GPIO2 PV4"), + PINCTRL_PIN(TEGRA_PIN_AP_READY_PV5, "AP_READY PV5"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_RST_PV6, "TOUCH_RST PV6"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_CLK_PV7, "TOUCH_CLK PV7"), + PINCTRL_PIN(TEGRA_PIN_MODEM_WAKE_AP_PX0, "MODEM_WAKE_AP PX0"), + PINCTRL_PIN(TEGRA_PIN_TOUCH_INT_PX1, "TOUCH_INT PX1"), + PINCTRL_PIN(TEGRA_PIN_MOTION_INT_PX2, "MOTION_INT PX2"), + PINCTRL_PIN(TEGRA_PIN_ALS_PROX_INT_PX3, "ALS_PROX_INT PX3"), + PINCTRL_PIN(TEGRA_PIN_TEMP_ALERT_PX4, "TEMP_ALERT PX4"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_POWER_ON_PX5, "BUTTON_POWER_ON PX5"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_UP_PX6, "BUTTON_VOL_UP PX6"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_VOL_DOWN_PX7, "BUTTON_VOL_DOWN PX7"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_SLIDE_SW_PY0, "BUTTON_SLIDE_SW PY0"), + PINCTRL_PIN(TEGRA_PIN_BUTTON_HOME_PY1, "BUTTON_HOME PY1"), + PINCTRL_PIN(TEGRA_PIN_LCD_TE_PY2, "LCD_TE PY2"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PY3, "PWR_I2C_SCL PY3"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PY4, "PWR_I2C_SDA PY4"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PY5, "CLK_32K_OUT PY5"), + PINCTRL_PIN(TEGRA_PIN_PZ0, "PZ0"), + PINCTRL_PIN(TEGRA_PIN_PZ1, "PZ1"), + PINCTRL_PIN(TEGRA_PIN_PZ2, "PZ2"), + PINCTRL_PIN(TEGRA_PIN_PZ3, "PZ3"), + PINCTRL_PIN(TEGRA_PIN_PZ4, "PZ4"), + PINCTRL_PIN(TEGRA_PIN_PZ5, "PZ5"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PAA0, "DAP2_FS PAA0"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PAA1, "DAP2_SCLK PAA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PAA2, "DAP2_DIN PAA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PAA3, "DAP2_DOUT PAA3"), + PINCTRL_PIN(TEGRA_PIN_AUD_MCLK_PBB0, "AUD_MCLK PBB0"), + PINCTRL_PIN(TEGRA_PIN_DVFS_PWM_PBB1, "DVFS_PWM PBB1"), + PINCTRL_PIN(TEGRA_PIN_DVFS_CLK_PBB2, "DVFS_CLK PBB2"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X1_AUD_PBB3, "GPIO_X1_AUD PBB3"), + PINCTRL_PIN(TEGRA_PIN_GPIO_X3_AUD_PBB4, "GPIO_X3_AUD PBB4"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PCC0, "HDMI_CEC PCC0"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, "HDMI_INT_DP_HPD PCC1"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PCC2, "SPDIF_OUT PCC2"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PCC3, "SPDIF_IN PCC3"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN0_PCC4, "USB_VBUS_EN0 PCC4"), + PINCTRL_PIN(TEGRA_PIN_USB_VBUS_EN1_PCC5, "USB_VBUS_EN1 PCC5"), + PINCTRL_PIN(TEGRA_PIN_DP_HPD0_PCC6, "DP_HPD0 PCC6"), + PINCTRL_PIN(TEGRA_PIN_PCC7, "PCC7"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_PDD0, "SPI2_CS1 PDD0"), + PINCTRL_PIN(TEGRA_PIN_QSPI_SCK_PEE0, "QSPI_SCK PEE0"), + PINCTRL_PIN(TEGRA_PIN_QSPI_CS_N_PEE1, "QSPI_CS_N PEE1"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO0_PEE2, "QSPI_IO0 PEE2"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO1_PEE3, "QSPI_IO1 PEE3"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO2_PEE4, "QSPI_IO2 PEE4"), + PINCTRL_PIN(TEGRA_PIN_QSPI_IO3_PEE5, "QSPI_IO3 PEE5"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK, "JTAG_RTCK"), + PINCTRL_PIN(TEGRA_PIN_BATT_BCL, "BATT_BCL"), + PINCTRL_PIN(TEGRA_PIN_CLK_REQ, "CLK_REQ"), + PINCTRL_PIN(TEGRA_PIN_SHUTDOWN, "SHUTDOWN"), +}; + +static const unsigned pex_l0_rst_n_pa0_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PA0, +}; + +static const unsigned pex_l0_clkreq_n_pa1_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PA1, +}; + +static const unsigned pex_wake_n_pa2_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PA2, +}; + +static const unsigned pex_l1_rst_n_pa3_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PA3, +}; + +static const unsigned pex_l1_clkreq_n_pa4_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PA4, +}; + +static const unsigned sata_led_active_pa5_pins[] = { + TEGRA_PIN_SATA_LED_ACTIVE_PA5, +}; + +static const unsigned pa6_pins[] = { + TEGRA_PIN_PA6, +}; + +static const unsigned dap1_fs_pb0_pins[] = { + TEGRA_PIN_DAP1_FS_PB0, +}; + +static const unsigned dap1_din_pb1_pins[] = { + TEGRA_PIN_DAP1_DIN_PB1, +}; + +static const unsigned dap1_dout_pb2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PB2, +}; + +static const unsigned dap1_sclk_pb3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PB3, +}; + +static const unsigned spi2_mosi_pb4_pins[] = { + TEGRA_PIN_SPI2_MOSI_PB4, +}; + +static const unsigned spi2_miso_pb5_pins[] = { + TEGRA_PIN_SPI2_MISO_PB5, +}; + +static const unsigned spi2_sck_pb6_pins[] = { + TEGRA_PIN_SPI2_SCK_PB6, +}; + +static const unsigned spi2_cs0_pb7_pins[] = { + TEGRA_PIN_SPI2_CS0_PB7, +}; + +static const unsigned spi1_mosi_pc0_pins[] = { + TEGRA_PIN_SPI1_MOSI_PC0, +}; + +static const unsigned spi1_miso_pc1_pins[] = { + TEGRA_PIN_SPI1_MISO_PC1, +}; + +static const unsigned spi1_sck_pc2_pins[] = { + TEGRA_PIN_SPI1_SCK_PC2, +}; + +static const unsigned spi1_cs0_pc3_pins[] = { + TEGRA_PIN_SPI1_CS0_PC3, +}; + +static const unsigned spi1_cs1_pc4_pins[] = { + TEGRA_PIN_SPI1_CS1_PC4, +}; + +static const unsigned spi4_sck_pc5_pins[] = { + TEGRA_PIN_SPI4_SCK_PC5, +}; + +static const unsigned spi4_cs0_pc6_pins[] = { + TEGRA_PIN_SPI4_CS0_PC6, +}; + +static const unsigned spi4_mosi_pc7_pins[] = { + TEGRA_PIN_SPI4_MOSI_PC7, +}; + +static const unsigned spi4_miso_pd0_pins[] = { + TEGRA_PIN_SPI4_MISO_PD0, +}; + +static const unsigned uart3_tx_pd1_pins[] = { + TEGRA_PIN_UART3_TX_PD1, +}; + +static const unsigned uart3_rx_pd2_pins[] = { + TEGRA_PIN_UART3_RX_PD2, +}; + +static const unsigned uart3_rts_pd3_pins[] = { + TEGRA_PIN_UART3_RTS_PD3, +}; + +static const unsigned uart3_cts_pd4_pins[] = { + TEGRA_PIN_UART3_CTS_PD4, +}; + +static const unsigned dmic1_clk_pe0_pins[] = { + TEGRA_PIN_DMIC1_CLK_PE0, +}; + +static const unsigned dmic1_dat_pe1_pins[] = { + TEGRA_PIN_DMIC1_DAT_PE1, +}; + +static const unsigned dmic2_clk_pe2_pins[] = { + TEGRA_PIN_DMIC2_CLK_PE2, +}; + +static const unsigned dmic2_dat_pe3_pins[] = { + TEGRA_PIN_DMIC2_DAT_PE3, +}; + +static const unsigned dmic3_clk_pe4_pins[] = { + TEGRA_PIN_DMIC3_CLK_PE4, +}; + +static const unsigned dmic3_dat_pe5_pins[] = { + TEGRA_PIN_DMIC3_DAT_PE5, +}; + +static const unsigned pe6_pins[] = { + TEGRA_PIN_PE6, +}; + +static const unsigned pe7_pins[] = { + TEGRA_PIN_PE7, +}; + +static const unsigned gen3_i2c_scl_pf0_pins[] = { + TEGRA_PIN_GEN3_I2C_SCL_PF0, +}; + +static const unsigned gen3_i2c_sda_pf1_pins[] = { + TEGRA_PIN_GEN3_I2C_SDA_PF1, +}; + +static const unsigned uart2_tx_pg0_pins[] = { + TEGRA_PIN_UART2_TX_PG0, +}; + +static const unsigned uart2_rx_pg1_pins[] = { + TEGRA_PIN_UART2_RX_PG1, +}; + +static const unsigned uart2_rts_pg2_pins[] = { + TEGRA_PIN_UART2_RTS_PG2, +}; + +static const unsigned uart2_cts_pg3_pins[] = { + TEGRA_PIN_UART2_CTS_PG3, +}; + +static const unsigned wifi_en_ph0_pins[] = { + TEGRA_PIN_WIFI_EN_PH0, +}; + +static const unsigned wifi_rst_ph1_pins[] = { + TEGRA_PIN_WIFI_RST_PH1, +}; + +static const unsigned wifi_wake_ap_ph2_pins[] = { + TEGRA_PIN_WIFI_WAKE_AP_PH2, +}; + +static const unsigned ap_wake_bt_ph3_pins[] = { + TEGRA_PIN_AP_WAKE_BT_PH3, +}; + +static const unsigned bt_rst_ph4_pins[] = { + TEGRA_PIN_BT_RST_PH4, +}; + +static const unsigned bt_wake_ap_ph5_pins[] = { + TEGRA_PIN_BT_WAKE_AP_PH5, +}; + +static const unsigned ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned ap_wake_nfc_ph7_pins[] = { + TEGRA_PIN_AP_WAKE_NFC_PH7, +}; + +static const unsigned nfc_en_pi0_pins[] = { + TEGRA_PIN_NFC_EN_PI0, +}; + +static const unsigned nfc_int_pi1_pins[] = { + TEGRA_PIN_NFC_INT_PI1, +}; + +static const unsigned gps_en_pi2_pins[] = { + TEGRA_PIN_GPS_EN_PI2, +}; + +static const unsigned gps_rst_pi3_pins[] = { + TEGRA_PIN_GPS_RST_PI3, +}; + +static const unsigned uart4_tx_pi4_pins[] = { + TEGRA_PIN_UART4_TX_PI4, +}; + +static const unsigned uart4_rx_pi5_pins[] = { + TEGRA_PIN_UART4_RX_PI5, +}; + +static const unsigned uart4_rts_pi6_pins[] = { + TEGRA_PIN_UART4_RTS_PI6, +}; + +static const unsigned uart4_cts_pi7_pins[] = { + TEGRA_PIN_UART4_CTS_PI7, +}; + +static const unsigned gen1_i2c_sda_pj0_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PJ0, +}; + +static const unsigned gen1_i2c_scl_pj1_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PJ1, +}; + +static const unsigned gen2_i2c_scl_pj2_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PJ2, +}; + +static const unsigned gen2_i2c_sda_pj3_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PJ3, +}; + +static const unsigned dap4_fs_pj4_pins[] = { + TEGRA_PIN_DAP4_FS_PJ4, +}; + +static const unsigned dap4_din_pj5_pins[] = { + TEGRA_PIN_DAP4_DIN_PJ5, +}; + +static const unsigned dap4_dout_pj6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PJ6, +}; + +static const unsigned dap4_sclk_pj7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PJ7, +}; + +static const unsigned pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned pk5_pins[] = { + TEGRA_PIN_PK5, +}; + +static const unsigned pk6_pins[] = { + TEGRA_PIN_PK6, +}; + +static const unsigned pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned pl0_pins[] = { + TEGRA_PIN_PL0, +}; + +static const unsigned pl1_pins[] = { + TEGRA_PIN_PL1, +}; + +static const unsigned sdmmc1_clk_pm0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PM0, +}; + +static const unsigned sdmmc1_cmd_pm1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PM1, +}; + +static const unsigned sdmmc1_dat3_pm2_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PM2, +}; + +static const unsigned sdmmc1_dat2_pm3_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PM3, +}; + +static const unsigned sdmmc1_dat1_pm4_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PM4, +}; + +static const unsigned sdmmc1_dat0_pm5_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PM5, +}; + +static const unsigned sdmmc3_clk_pp0_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PP0, +}; + +static const unsigned sdmmc3_cmd_pp1_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PP1, +}; + +static const unsigned sdmmc3_dat3_pp2_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PP2, +}; + +static const unsigned sdmmc3_dat2_pp3_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PP3, +}; + +static const unsigned sdmmc3_dat1_pp4_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PP4, +}; + +static const unsigned sdmmc3_dat0_pp5_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PP5, +}; + +static const unsigned cam1_mclk_ps0_pins[] = { + TEGRA_PIN_CAM1_MCLK_PS0, +}; + +static const unsigned cam2_mclk_ps1_pins[] = { + TEGRA_PIN_CAM2_MCLK_PS1, +}; + +static const unsigned cam_i2c_scl_ps2_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PS2, +}; + +static const unsigned cam_i2c_sda_ps3_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PS3, +}; + +static const unsigned cam_rst_ps4_pins[] = { + TEGRA_PIN_CAM_RST_PS4, +}; + +static const unsigned cam_af_en_ps5_pins[] = { + TEGRA_PIN_CAM_AF_EN_PS5, +}; + +static const unsigned cam_flash_en_ps6_pins[] = { + TEGRA_PIN_CAM_FLASH_EN_PS6, +}; + +static const unsigned cam1_pwdn_ps7_pins[] = { + TEGRA_PIN_CAM1_PWDN_PS7, +}; + +static const unsigned cam2_pwdn_pt0_pins[] = { + TEGRA_PIN_CAM2_PWDN_PT0, +}; + +static const unsigned cam1_strobe_pt1_pins[] = { + TEGRA_PIN_CAM1_STROBE_PT1, +}; + +static const unsigned uart1_tx_pu0_pins[] = { + TEGRA_PIN_UART1_TX_PU0, +}; + +static const unsigned uart1_rx_pu1_pins[] = { + TEGRA_PIN_UART1_RX_PU1, +}; + +static const unsigned uart1_rts_pu2_pins[] = { + TEGRA_PIN_UART1_RTS_PU2, +}; + +static const unsigned uart1_cts_pu3_pins[] = { + TEGRA_PIN_UART1_CTS_PU3, +}; + +static const unsigned lcd_bl_pwm_pv0_pins[] = { + TEGRA_PIN_LCD_BL_PWM_PV0, +}; + +static const unsigned lcd_bl_en_pv1_pins[] = { + TEGRA_PIN_LCD_BL_EN_PV1, +}; + +static const unsigned lcd_rst_pv2_pins[] = { + TEGRA_PIN_LCD_RST_PV2, +}; + +static const unsigned lcd_gpio1_pv3_pins[] = { + TEGRA_PIN_LCD_GPIO1_PV3, +}; + +static const unsigned lcd_gpio2_pv4_pins[] = { + TEGRA_PIN_LCD_GPIO2_PV4, +}; + +static const unsigned ap_ready_pv5_pins[] = { + TEGRA_PIN_AP_READY_PV5, +}; + +static const unsigned touch_rst_pv6_pins[] = { + TEGRA_PIN_TOUCH_RST_PV6, +}; + +static const unsigned touch_clk_pv7_pins[] = { + TEGRA_PIN_TOUCH_CLK_PV7, +}; + +static const unsigned modem_wake_ap_px0_pins[] = { + TEGRA_PIN_MODEM_WAKE_AP_PX0, +}; + +static const unsigned touch_int_px1_pins[] = { + TEGRA_PIN_TOUCH_INT_PX1, +}; + +static const unsigned motion_int_px2_pins[] = { + TEGRA_PIN_MOTION_INT_PX2, +}; + +static const unsigned als_prox_int_px3_pins[] = { + TEGRA_PIN_ALS_PROX_INT_PX3, +}; + +static const unsigned temp_alert_px4_pins[] = { + TEGRA_PIN_TEMP_ALERT_PX4, +}; + +static const unsigned button_power_on_px5_pins[] = { + TEGRA_PIN_BUTTON_POWER_ON_PX5, +}; + +static const unsigned button_vol_up_px6_pins[] = { + TEGRA_PIN_BUTTON_VOL_UP_PX6, +}; + +static const unsigned button_vol_down_px7_pins[] = { + TEGRA_PIN_BUTTON_VOL_DOWN_PX7, +}; + +static const unsigned button_slide_sw_py0_pins[] = { + TEGRA_PIN_BUTTON_SLIDE_SW_PY0, +}; + +static const unsigned button_home_py1_pins[] = { + TEGRA_PIN_BUTTON_HOME_PY1, +}; + +static const unsigned lcd_te_py2_pins[] = { + TEGRA_PIN_LCD_TE_PY2, +}; + +static const unsigned pwr_i2c_scl_py3_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PY3, +}; + +static const unsigned pwr_i2c_sda_py4_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PY4, +}; + +static const unsigned clk_32k_out_py5_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PY5, +}; + +static const unsigned pz0_pins[] = { + TEGRA_PIN_PZ0, +}; + +static const unsigned pz1_pins[] = { + TEGRA_PIN_PZ1, +}; + +static const unsigned pz2_pins[] = { + TEGRA_PIN_PZ2, +}; + +static const unsigned pz3_pins[] = { + TEGRA_PIN_PZ3, +}; + +static const unsigned pz4_pins[] = { + TEGRA_PIN_PZ4, +}; + +static const unsigned pz5_pins[] = { + TEGRA_PIN_PZ5, +}; + +static const unsigned dap2_fs_paa0_pins[] = { + TEGRA_PIN_DAP2_FS_PAA0, +}; + +static const unsigned dap2_sclk_paa1_pins[] = { + TEGRA_PIN_DAP2_SCLK_PAA1, +}; + +static const unsigned dap2_din_paa2_pins[] = { + TEGRA_PIN_DAP2_DIN_PAA2, +}; + +static const unsigned dap2_dout_paa3_pins[] = { + TEGRA_PIN_DAP2_DOUT_PAA3, +}; + +static const unsigned aud_mclk_pbb0_pins[] = { + TEGRA_PIN_AUD_MCLK_PBB0, +}; + +static const unsigned dvfs_pwm_pbb1_pins[] = { + TEGRA_PIN_DVFS_PWM_PBB1, +}; + +static const unsigned dvfs_clk_pbb2_pins[] = { + TEGRA_PIN_DVFS_CLK_PBB2, +}; + +static const unsigned gpio_x1_aud_pbb3_pins[] = { + TEGRA_PIN_GPIO_X1_AUD_PBB3, +}; + +static const unsigned gpio_x3_aud_pbb4_pins[] = { + TEGRA_PIN_GPIO_X3_AUD_PBB4, +}; + +static const unsigned hdmi_cec_pcc0_pins[] = { + TEGRA_PIN_HDMI_CEC_PCC0, +}; + +static const unsigned hdmi_int_dp_hpd_pcc1_pins[] = { + TEGRA_PIN_HDMI_INT_DP_HPD_PCC1, +}; + +static const unsigned spdif_out_pcc2_pins[] = { + TEGRA_PIN_SPDIF_OUT_PCC2, +}; + +static const unsigned spdif_in_pcc3_pins[] = { + TEGRA_PIN_SPDIF_IN_PCC3, +}; + +static const unsigned usb_vbus_en0_pcc4_pins[] = { + TEGRA_PIN_USB_VBUS_EN0_PCC4, +}; + +static const unsigned usb_vbus_en1_pcc5_pins[] = { + TEGRA_PIN_USB_VBUS_EN1_PCC5, +}; + +static const unsigned dp_hpd0_pcc6_pins[] = { + TEGRA_PIN_DP_HPD0_PCC6, +}; + +static const unsigned pcc7_pins[] = { + TEGRA_PIN_PCC7, +}; + +static const unsigned spi2_cs1_pdd0_pins[] = { + TEGRA_PIN_SPI2_CS1_PDD0, +}; + +static const unsigned qspi_sck_pee0_pins[] = { + TEGRA_PIN_QSPI_SCK_PEE0, +}; + +static const unsigned qspi_cs_n_pee1_pins[] = { + TEGRA_PIN_QSPI_CS_N_PEE1, +}; + +static const unsigned qspi_io0_pee2_pins[] = { + TEGRA_PIN_QSPI_IO0_PEE2, +}; + +static const unsigned qspi_io1_pee3_pins[] = { + TEGRA_PIN_QSPI_IO1_PEE3, +}; + +static const unsigned qspi_io2_pee4_pins[] = { + TEGRA_PIN_QSPI_IO2_PEE4, +}; + +static const unsigned qspi_io3_pee5_pins[] = { + TEGRA_PIN_QSPI_IO3_PEE5, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned jtag_rtck_pins[] = { + TEGRA_PIN_JTAG_RTCK, +}; + +static const unsigned batt_bcl_pins[] = { + TEGRA_PIN_BATT_BCL, +}; + +static const unsigned clk_req_pins[] = { + TEGRA_PIN_CLK_REQ, +}; + +static const unsigned shutdown_pins[] = { + TEGRA_PIN_SHUTDOWN, +}; + +static const unsigned drive_pa6_pins[] = { + TEGRA_PIN_PA6, +}; + +static const unsigned drive_pcc7_pins[] = { + TEGRA_PIN_PCC7, +}; + +static const unsigned drive_pe6_pins[] = { + TEGRA_PIN_PE6, +}; + +static const unsigned drive_pe7_pins[] = { + TEGRA_PIN_PE7, +}; + +static const unsigned drive_ph6_pins[] = { + TEGRA_PIN_PH6, +}; + +static const unsigned drive_pk0_pins[] = { + TEGRA_PIN_PK0, +}; + +static const unsigned drive_pk1_pins[] = { + TEGRA_PIN_PK1, +}; + +static const unsigned drive_pk2_pins[] = { + TEGRA_PIN_PK2, +}; + +static const unsigned drive_pk3_pins[] = { + TEGRA_PIN_PK3, +}; + +static const unsigned drive_pk4_pins[] = { + TEGRA_PIN_PK4, +}; + +static const unsigned drive_pk5_pins[] = { + TEGRA_PIN_PK5, +}; + +static const unsigned drive_pk6_pins[] = { + TEGRA_PIN_PK6, +}; + +static const unsigned drive_pk7_pins[] = { + TEGRA_PIN_PK7, +}; + +static const unsigned drive_pl0_pins[] = { + TEGRA_PIN_PL0, +}; + +static const unsigned drive_pl1_pins[] = { + TEGRA_PIN_PL1, +}; + +static const unsigned drive_pz0_pins[] = { + TEGRA_PIN_PZ0, +}; + +static const unsigned drive_pz1_pins[] = { + TEGRA_PIN_PZ1, +}; + +static const unsigned drive_pz2_pins[] = { + TEGRA_PIN_PZ2, +}; + +static const unsigned drive_pz3_pins[] = { + TEGRA_PIN_PZ3, +}; + +static const unsigned drive_pz4_pins[] = { + TEGRA_PIN_PZ4, +}; + +static const unsigned drive_pz5_pins[] = { + TEGRA_PIN_PZ5, +}; + +static const unsigned drive_sdmmc1_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PM0, + TEGRA_PIN_SDMMC1_CMD_PM1, + TEGRA_PIN_SDMMC1_DAT3_PM2, + TEGRA_PIN_SDMMC1_DAT2_PM3, + TEGRA_PIN_SDMMC1_DAT1_PM4, + TEGRA_PIN_SDMMC1_DAT0_PM5, +}; + +static const unsigned drive_sdmmc2_pins[] = { +}; + +static const unsigned drive_sdmmc3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PP0, + TEGRA_PIN_SDMMC3_CMD_PP1, + TEGRA_PIN_SDMMC3_DAT3_PP2, + TEGRA_PIN_SDMMC3_DAT2_PP3, + TEGRA_PIN_SDMMC3_DAT1_PP4, + TEGRA_PIN_SDMMC3_DAT0_PP5, +}; + +static const unsigned drive_sdmmc4_pins[] = { +}; + +enum tegra_mux { + TEGRA_MUX_AUD, + TEGRA_MUX_BCL, + TEGRA_MUX_BLINK, + TEGRA_MUX_CCLA, + TEGRA_MUX_CEC, + TEGRA_MUX_CLDVFS, + TEGRA_MUX_CLK, + TEGRA_MUX_CORE, + TEGRA_MUX_CPU, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DMIC1, + TEGRA_MUX_DMIC2, + TEGRA_MUX_DMIC3, + TEGRA_MUX_DP, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2CPMU, + TEGRA_MUX_I2CVI, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4A, + TEGRA_MUX_I2S4B, + TEGRA_MUX_I2S5A, + TEGRA_MUX_I2S5B, + TEGRA_MUX_IQC0, + TEGRA_MUX_IQC1, + TEGRA_MUX_JTAG, + TEGRA_MUX_PE, + TEGRA_MUX_PE0, + TEGRA_MUX_PE1, + TEGRA_MUX_PMI, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_QSPI, + TEGRA_MUX_RSVD0, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_SATA, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SHUTDOWN, + TEGRA_MUX_SOC, + TEGRA_MUX_SOR0, + TEGRA_MUX_SOR1, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SYS, + TEGRA_MUX_TOUCH, + TEGRA_MUX_UART, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_USB, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VIMCLK, + TEGRA_MUX_VIMCLK2, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra210_functions[] = { + FUNCTION(aud), + FUNCTION(bcl), + FUNCTION(blink), + FUNCTION(ccla), + FUNCTION(cec), + FUNCTION(cldvfs), + FUNCTION(clk), + FUNCTION(core), + FUNCTION(cpu), + FUNCTION(displaya), + FUNCTION(displayb), + FUNCTION(dmic1), + FUNCTION(dmic2), + FUNCTION(dmic3), + FUNCTION(dp), + FUNCTION(dtv), + FUNCTION(extperiph3), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2cpmu), + FUNCTION(i2cvi), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4a), + FUNCTION(i2s4b), + FUNCTION(i2s5a), + FUNCTION(i2s5b), + FUNCTION(iqc0), + FUNCTION(iqc1), + FUNCTION(jtag), + FUNCTION(pe), + FUNCTION(pe0), + FUNCTION(pe1), + FUNCTION(pmi), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(qspi), + FUNCTION(rsvd0), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(sata), + FUNCTION(sdmmc1), + FUNCTION(sdmmc3), + FUNCTION(shutdown), + FUNCTION(soc), + FUNCTION(sor0), + FUNCTION(sor1), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(sys), + FUNCTION(touch), + FUNCTION(uart), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(usb), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vimclk), + FUNCTION(vimclk2), +}; + +#define DRV_PINGROUP_REG_A 0x8d4 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, \ + rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, \ + slwr_w, slwf_b, slwf_w) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 6, \ + .odrain_bit = 11, \ + .lock_bit = 7, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = PINGROUP_BIT_##e_io_hv(10), \ + .hsm_bit = PINGROUP_BIT_##hsm(9), \ + .schmitt_bit = 12, \ + .drvtype_bit = PINGROUP_BIT_##drvtype(13), \ + .drv_reg = DRV_PINGROUP_REG(rdrv), \ + .drv_bank = 0, \ + .lpmd_bit = -1, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + } + +#define DRV_PINGROUP(pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, \ + slwr_b, slwr_w, slwf_b, slwf_w) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = -1, \ + .schmitt_bit = -1, \ + .lpmd_bit = -1, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = -1, \ + } + +static const struct tegra_pingroup tegra210_groups[] = { + /* pg_name, f0, f1, f2, f3, r, hsm, drvtype, e_io_hv, rdrv, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ + PINGROUP(sdmmc1_clk_pm0, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3000, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_cmd_pm1, SDMMC1, SPI3, RSVD2, RSVD3, 0x3004, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat3_pm2, SDMMC1, SPI3, RSVD2, RSVD3, 0x3008, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat2_pm3, SDMMC1, SPI3, RSVD2, RSVD3, 0x300c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat1_pm4, SDMMC1, SPI3, RSVD2, RSVD3, 0x3010, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc1_dat0_pm5, SDMMC1, RSVD1, RSVD2, RSVD3, 0x3014, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_clk_pp0, SDMMC3, RSVD1, RSVD2, RSVD3, 0x301c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_cmd_pp1, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3020, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat0_pp5, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3024, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat1_pp4, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3028, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat2_pp3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x302c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(sdmmc3_dat3_pp2, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3030, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pex_l0_rst_n_pa0, PE0, RSVD1, RSVD2, RSVD3, 0x3038, N, N, Y, 0xa5c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_l0_clkreq_n_pa1, PE0, RSVD1, RSVD2, RSVD3, 0x303c, N, N, Y, 0xa58, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_wake_n_pa2, PE, RSVD1, RSVD2, RSVD3, 0x3040, N, N, Y, 0xa68, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_l1_rst_n_pa3, PE1, RSVD1, RSVD2, RSVD3, 0x3044, N, N, Y, 0xa64, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pex_l1_clkreq_n_pa4, PE1, RSVD1, RSVD2, RSVD3, 0x3048, N, N, Y, 0xa60, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(sata_led_active_pa5, SATA, RSVD1, RSVD2, RSVD3, 0x304c, N, N, N, 0xa94, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(spi1_mosi_pc0, SPI1, RSVD1, RSVD2, RSVD3, 0x3050, Y, Y, N, 0xae0, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_miso_pc1, SPI1, RSVD1, RSVD2, RSVD3, 0x3054, Y, Y, N, 0xadc, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_sck_pc2, SPI1, RSVD1, RSVD2, RSVD3, 0x3058, Y, Y, N, 0xae4, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_cs0_pc3, SPI1, RSVD1, RSVD2, RSVD3, 0x305c, Y, Y, N, 0xad4, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi1_cs1_pc4, SPI1, RSVD1, RSVD2, RSVD3, 0x3060, Y, Y, N, 0xad8, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_mosi_pb4, SPI2, DTV, RSVD2, RSVD3, 0x3064, Y, Y, N, 0xaf4, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_miso_pb5, SPI2, DTV, RSVD2, RSVD3, 0x3068, Y, Y, N, 0xaf0, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_sck_pb6, SPI2, DTV, RSVD2, RSVD3, 0x306c, Y, Y, N, 0xaf8, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_cs0_pb7, SPI2, DTV, RSVD2, RSVD3, 0x3070, Y, Y, N, 0xae8, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi2_cs1_pdd0, SPI2, RSVD1, RSVD2, RSVD3, 0x3074, Y, Y, N, 0xaec, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_mosi_pc7, SPI4, RSVD1, RSVD2, RSVD3, 0x3078, Y, Y, N, 0xb04, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_miso_pd0, SPI4, RSVD1, RSVD2, RSVD3, 0x307c, Y, Y, N, 0xb00, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_sck_pc5, SPI4, RSVD1, RSVD2, RSVD3, 0x3080, Y, Y, N, 0xb08, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(spi4_cs0_pc6, SPI4, RSVD1, RSVD2, RSVD3, 0x3084, Y, Y, N, 0xafc, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(qspi_sck_pee0, QSPI, RSVD1, RSVD2, RSVD3, 0x3088, Y, Y, N, 0xa90, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(qspi_cs_n_pee1, QSPI, RSVD1, RSVD2, RSVD3, 0x308c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io0_pee2, QSPI, RSVD1, RSVD2, RSVD3, 0x3090, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io1_pee3, QSPI, RSVD1, RSVD2, RSVD3, 0x3094, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io2_pee4, QSPI, RSVD1, RSVD2, RSVD3, 0x3098, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(qspi_io3_pee5, QSPI, RSVD1, RSVD2, RSVD3, 0x309c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(dmic1_clk_pe0, DMIC1, I2S3, RSVD2, RSVD3, 0x30a4, N, N, N, 0x984, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic1_dat_pe1, DMIC1, I2S3, RSVD2, RSVD3, 0x30a8, N, N, N, 0x988, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic2_clk_pe2, DMIC2, I2S3, RSVD2, RSVD3, 0x30ac, N, N, N, 0x98c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic2_dat_pe3, DMIC2, I2S3, RSVD2, RSVD3, 0x30b0, N, N, N, 0x990, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic3_clk_pe4, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b4, N, N, N, 0x994, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dmic3_dat_pe5, DMIC3, I2S5A, RSVD2, RSVD3, 0x30b8, N, N, N, 0x998, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen1_i2c_scl_pj1, I2C1, RSVD1, RSVD2, RSVD3, 0x30bc, N, N, Y, 0x9a8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen1_i2c_sda_pj0, I2C1, RSVD1, RSVD2, RSVD3, 0x30c0, N, N, Y, 0x9ac, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen2_i2c_scl_pj2, I2C2, RSVD1, RSVD2, RSVD3, 0x30c4, N, N, Y, 0x9b0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen2_i2c_sda_pj3, I2C2, RSVD1, RSVD2, RSVD3, 0x30c8, N, N, Y, 0x9b4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen3_i2c_scl_pf0, I2C3, RSVD1, RSVD2, RSVD3, 0x30cc, N, N, Y, 0x9b8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gen3_i2c_sda_pf1, I2C3, RSVD1, RSVD2, RSVD3, 0x30d0, N, N, Y, 0x9bc, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_i2c_scl_ps2, I2C3, I2CVI, RSVD2, RSVD3, 0x30d4, N, N, Y, 0x934, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_i2c_sda_ps3, I2C3, I2CVI, RSVD2, RSVD3, 0x30d8, N, N, Y, 0x938, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pwr_i2c_scl_py3, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30dc, N, N, Y, 0xa6c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pwr_i2c_sda_py4, I2CPMU, RSVD1, RSVD2, RSVD3, 0x30e0, N, N, Y, 0xa70, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_tx_pu0, UARTA, RSVD1, RSVD2, RSVD3, 0x30e4, N, N, N, 0xb28, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_rx_pu1, UARTA, RSVD1, RSVD2, RSVD3, 0x30e8, N, N, N, 0xb24, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_rts_pu2, UARTA, RSVD1, RSVD2, RSVD3, 0x30ec, N, N, N, 0xb20, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart1_cts_pu3, UARTA, RSVD1, RSVD2, RSVD3, 0x30f0, N, N, N, 0xb1c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_tx_pg0, UARTB, I2S4A, SPDIF, UART, 0x30f4, N, N, N, 0xb38, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_rx_pg1, UARTB, I2S4A, SPDIF, UART, 0x30f8, N, N, N, 0xb34, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_rts_pg2, UARTB, I2S4A, RSVD2, UART, 0x30fc, N, N, N, 0xb30, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart2_cts_pg3, UARTB, I2S4A, RSVD2, UART, 0x3100, N, N, N, 0xb2c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_tx_pd1, UARTC, SPI4, RSVD2, RSVD3, 0x3104, N, N, N, 0xb48, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_rx_pd2, UARTC, SPI4, RSVD2, RSVD3, 0x3108, N, N, N, 0xb44, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_rts_pd3, UARTC, SPI4, RSVD2, RSVD3, 0x310c, N, N, N, 0xb40, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart3_cts_pd4, UARTC, SPI4, RSVD2, RSVD3, 0x3110, N, N, N, 0xb3c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_tx_pi4, UARTD, UART, RSVD2, RSVD3, 0x3114, N, N, N, 0xb58, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_rx_pi5, UARTD, UART, RSVD2, RSVD3, 0x3118, N, N, N, 0xb54, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_rts_pi6, UARTD, UART, RSVD2, RSVD3, 0x311c, N, N, N, 0xb50, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(uart4_cts_pi7, UARTD, UART, RSVD2, RSVD3, 0x3120, N, N, N, 0xb4c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap1_fs_pb0, I2S1, RSVD1, RSVD2, RSVD3, 0x3124, Y, Y, N, 0x95c, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap1_din_pb1, I2S1, RSVD1, RSVD2, RSVD3, 0x3128, Y, Y, N, 0x954, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap1_dout_pb2, I2S1, RSVD1, RSVD2, RSVD3, 0x312c, Y, Y, N, 0x958, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap1_sclk_pb3, I2S1, RSVD1, RSVD2, RSVD3, 0x3130, Y, Y, N, 0x960, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_fs_paa0, I2S2, RSVD1, RSVD2, RSVD3, 0x3134, Y, Y, N, 0x96c, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_din_paa2, I2S2, RSVD1, RSVD2, RSVD3, 0x3138, Y, Y, N, 0x964, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_dout_paa3, I2S2, RSVD1, RSVD2, RSVD3, 0x313c, Y, Y, N, 0x968, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap2_sclk_paa1, I2S2, RSVD1, RSVD2, RSVD3, 0x3140, Y, Y, N, 0x970, -1, -1, -1, -1, 28, 2, 30, 2), + PINGROUP(dap4_fs_pj4, I2S4B, RSVD1, RSVD2, RSVD3, 0x3144, N, N, N, 0x97c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap4_din_pj5, I2S4B, RSVD1, RSVD2, RSVD3, 0x3148, N, N, N, 0x974, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap4_dout_pj6, I2S4B, RSVD1, RSVD2, RSVD3, 0x314c, N, N, N, 0x978, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dap4_sclk_pj7, I2S4B, RSVD1, RSVD2, RSVD3, 0x3150, N, N, N, 0x980, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam1_mclk_ps0, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3154, N, N, N, 0x918, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam2_mclk_ps1, EXTPERIPH3, RSVD1, RSVD2, RSVD3, 0x3158, N, N, N, 0x924, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(jtag_rtck, JTAG, RSVD1, RSVD2, RSVD3, 0x315c, N, N, N, 0xa2c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(clk_32k_in, CLK, RSVD1, RSVD2, RSVD3, 0x3160, N, N, N, 0x940, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(clk_32k_out_py5, SOC, BLINK, RSVD2, RSVD3, 0x3164, N, N, N, 0x944, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(batt_bcl, BCL, RSVD1, RSVD2, RSVD3, 0x3168, N, N, Y, 0x8f8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(clk_req, SYS, RSVD1, RSVD2, RSVD3, 0x316c, N, N, N, 0x948, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cpu_pwr_req, CPU, RSVD1, RSVD2, RSVD3, 0x3170, N, N, N, 0x950, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pwr_int_n, PMI, RSVD1, RSVD2, RSVD3, 0x3174, N, N, N, 0xa74, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(shutdown, SHUTDOWN, RSVD1, RSVD2, RSVD3, 0x3178, N, N, N, 0xac8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(core_pwr_req, CORE, RSVD1, RSVD2, RSVD3, 0x317c, N, N, N, 0x94c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(aud_mclk_pbb0, AUD, RSVD1, RSVD2, RSVD3, 0x3180, N, N, N, 0x8f4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dvfs_pwm_pbb1, RSVD0, CLDVFS, SPI3, RSVD3, 0x3184, N, N, N, 0x9a4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dvfs_clk_pbb2, RSVD0, CLDVFS, SPI3, RSVD3, 0x3188, N, N, N, 0x9a0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gpio_x1_aud_pbb3, RSVD0, RSVD1, SPI3, RSVD3, 0x318c, N, N, N, 0xa14, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gpio_x3_aud_pbb4, RSVD0, RSVD1, SPI3, RSVD3, 0x3190, N, N, N, 0xa18, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pcc7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3194, N, N, Y, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(hdmi_cec_pcc0, CEC, RSVD1, RSVD2, RSVD3, 0x3198, N, N, Y, 0xa24, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(hdmi_int_dp_hpd_pcc1, DP, RSVD1, RSVD2, RSVD3, 0x319c, N, N, Y, 0xa28, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(spdif_out_pcc2, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a0, N, N, N, 0xad0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(spdif_in_pcc3, SPDIF, RSVD1, RSVD2, RSVD3, 0x31a4, N, N, N, 0xacc, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(usb_vbus_en0_pcc4, USB, RSVD1, RSVD2, RSVD3, 0x31a8, N, N, Y, 0xb5c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(usb_vbus_en1_pcc5, USB, RSVD1, RSVD2, RSVD3, 0x31ac, N, N, Y, 0xb60, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(dp_hpd0_pcc6, DP, RSVD1, RSVD2, RSVD3, 0x31b0, N, N, N, 0x99c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(wifi_en_ph0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b4, N, N, N, 0xb64, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(wifi_rst_ph1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31b8, N, N, N, 0xb68, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(wifi_wake_ap_ph2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31bc, N, N, N, 0xb6c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(ap_wake_bt_ph3, RSVD0, UARTB, SPDIF, RSVD3, 0x31c0, N, N, N, 0x8ec, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(bt_rst_ph4, RSVD0, UARTB, SPDIF, RSVD3, 0x31c4, N, N, N, 0x8fc, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(bt_wake_ap_ph5, RSVD0, RSVD1, RSVD2, RSVD3, 0x31c8, N, N, N, 0x900, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(ap_wake_nfc_ph7, RSVD0, RSVD1, RSVD2, RSVD3, 0x31cc, N, N, N, 0x8f0, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(nfc_en_pi0, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d0, N, N, N, 0xa50, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(nfc_int_pi1, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d4, N, N, N, 0xa54, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gps_en_pi2, RSVD0, RSVD1, RSVD2, RSVD3, 0x31d8, N, N, N, 0xa1c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(gps_rst_pi3, RSVD0, RSVD1, RSVD2, RSVD3, 0x31dc, N, N, N, 0xa20, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_rst_ps4, VGP1, RSVD1, RSVD2, RSVD3, 0x31e0, N, N, N, 0x93c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_af_en_ps5, VIMCLK, VGP2, RSVD2, RSVD3, 0x31e4, N, N, N, 0x92c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam_flash_en_ps6, VIMCLK, VGP3, RSVD2, RSVD3, 0x31e8, N, N, N, 0x930, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam1_pwdn_ps7, VGP4, RSVD1, RSVD2, RSVD3, 0x31ec, N, N, N, 0x91c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam2_pwdn_pt0, VGP5, RSVD1, RSVD2, RSVD3, 0x31f0, N, N, N, 0x928, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(cam1_strobe_pt1, VGP6, RSVD1, RSVD2, RSVD3, 0x31f4, N, N, N, 0x920, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_te_py2, DISPLAYA, RSVD1, RSVD2, RSVD3, 0x31f8, N, N, N, 0xa44, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_bl_pwm_pv0, DISPLAYA, PWM0, SOR0, RSVD3, 0x31fc, N, N, N, 0xa34, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_bl_en_pv1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3200, N, N, N, 0xa30, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_rst_pv2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3204, N, N, N, 0xa40, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_gpio1_pv3, DISPLAYB, RSVD1, RSVD2, RSVD3, 0x3208, N, N, N, 0xa38, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(lcd_gpio2_pv4, DISPLAYB, PWM1, RSVD2, SOR1, 0x320c, N, N, N, 0xa3c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(ap_ready_pv5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3210, N, N, N, 0x8e8, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(touch_rst_pv6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3214, N, N, N, 0xb18, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(touch_clk_pv7, TOUCH, RSVD1, RSVD2, RSVD3, 0x3218, N, N, N, 0xb10, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(modem_wake_ap_px0, RSVD0, RSVD1, RSVD2, RSVD3, 0x321c, N, N, N, 0xa48, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(touch_int_px1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3220, N, N, N, 0xb14, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(motion_int_px2, RSVD0, RSVD1, RSVD2, RSVD3, 0x3224, N, N, N, 0xa4c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(als_prox_int_px3, RSVD0, RSVD1, RSVD2, RSVD3, 0x3228, N, N, N, 0x8e4, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(temp_alert_px4, RSVD0, RSVD1, RSVD2, RSVD3, 0x322c, N, N, N, 0xb0c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_power_on_px5, RSVD0, RSVD1, RSVD2, RSVD3, 0x3230, N, N, N, 0x908, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_vol_up_px6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3234, N, N, N, 0x914, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_vol_down_px7, RSVD0, RSVD1, RSVD2, RSVD3, 0x3238, N, N, N, 0x910, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_slide_sw_py0, RSVD0, RSVD1, RSVD2, RSVD3, 0x323c, N, N, N, 0x90c, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(button_home_py1, RSVD0, RSVD1, RSVD2, RSVD3, 0x3240, N, N, N, 0x904, 12, 5, 20, 5, -1, -1, -1, -1), + PINGROUP(pa6, SATA, RSVD1, RSVD2, RSVD3, 0x3244, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pe6, RSVD0, I2S5A, PWM2, RSVD3, 0x3248, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pe7, RSVD0, I2S5A, PWM3, RSVD3, 0x324c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(ph6, RSVD0, RSVD1, RSVD2, RSVD3, 0x3250, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk0, IQC0, I2S5B, RSVD2, RSVD3, 0x3254, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk1, IQC0, I2S5B, RSVD2, RSVD3, 0x3258, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk2, IQC0, I2S5B, RSVD2, RSVD3, 0x325c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk3, IQC0, I2S5B, RSVD2, RSVD3, 0x3260, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk4, IQC1, RSVD1, RSVD2, RSVD3, 0x3264, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk5, IQC1, RSVD1, RSVD2, RSVD3, 0x3268, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk6, IQC1, RSVD1, RSVD2, RSVD3, 0x326c, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pk7, IQC1, RSVD1, RSVD2, RSVD3, 0x3270, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pl0, RSVD0, RSVD1, RSVD2, RSVD3, 0x3274, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pl1, SOC, RSVD1, RSVD2, RSVD3, 0x3278, Y, Y, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz0, VIMCLK2, RSVD1, RSVD2, RSVD3, 0x327c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz1, VIMCLK2, SDMMC1, RSVD2, RSVD3, 0x3280, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz2, SDMMC3, CCLA, RSVD2, RSVD3, 0x3284, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz3, SDMMC3, RSVD1, RSVD2, RSVD3, 0x3288, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz4, SDMMC1, RSVD1, RSVD2, RSVD3, 0x328c, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + PINGROUP(pz5, SOC, RSVD1, RSVD2, RSVD3, 0x3290, N, N, N, -1, -1, -1, -1, -1, -1, -1, -1, -1), + + /* pg_name, r, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ + DRV_PINGROUP(pa6, 0x9c0, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pcc7, 0x9c4, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pe6, 0x9c8, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pe7, 0x9cc, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(ph6, 0x9d0, 12, 5, 20, 5, -1, -1, -1, -1), + DRV_PINGROUP(pk0, 0x9d4, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk1, 0x9d8, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk2, 0x9dc, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk3, 0x9e0, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk4, 0x9e4, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk5, 0x9e8, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk6, 0x9ec, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pk7, 0x9f0, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pl0, 0x9f4, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pl1, 0x9f8, -1, -1, -1, -1, 28, 2, 30, 2), + DRV_PINGROUP(pz0, 0x9fc, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz1, 0xa00, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz2, 0xa04, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz3, 0xa08, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz4, 0xa0c, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(pz5, 0xa10, 12, 7, 20, 7, -1, -1, -1, -1), + DRV_PINGROUP(sdmmc1, 0xa98, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdmmc2, 0xa9c, 2, 6, 8, 6, 28, 2, 30, 2), + DRV_PINGROUP(sdmmc3, 0xab0, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdmmc4, 0xab4, 2, 6, 8, 6, 28, 2, 30, 2), +}; + +static const struct tegra_pinctrl_soc_data tegra210_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra210_pins, + .npins = ARRAY_SIZE(tegra210_pins), + .functions = tegra210_functions, + .nfunctions = ARRAY_SIZE(tegra210_functions), + .groups = tegra210_groups, + .ngroups = ARRAY_SIZE(tegra210_groups), + .hsm_in_mux = true, + .schmitt_in_mux = true, + .drvtype_in_mux = true, +}; + +static int tegra210_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra210_pinctrl); +} + +static const struct of_device_id tegra210_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra210-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra210_pinctrl_of_match); + +static struct platform_driver tegra210_pinctrl_driver = { + .driver = { + .name = "tegra210-pinctrl", + .of_match_table = tegra210_pinctrl_of_match, + }, + .probe = tegra210_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra210_pinctrl_driver); + +MODULE_AUTHOR("NVIDIA"); +MODULE_DESCRIPTION("NVIDIA Tegra210 pinctrl driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/tegra/pinctrl-tegra30.c b/drivers/pinctrl/tegra/pinctrl-tegra30.c new file mode 100644 index 000000000000..47b2fd8bb2e9 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra30.c @@ -0,0 +1,2507 @@ +/* + * Pinctrl data for the NVIDIA Tegra30 pinmux + * + * Copyright (c) 2011-2012, NVIDIA CORPORATION. All rights reserved. + * + * 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 "pinctrl-tegra.h" + +/* + * Most pins affected by the pinmux can also be GPIOs. Define these first. + * These must match how the GPIO driver names/numbers its pins. + */ +#define _GPIO(offset) (offset) + +#define TEGRA_PIN_CLK_32K_OUT_PA0 _GPIO(0) +#define TEGRA_PIN_UART3_CTS_N_PA1 _GPIO(1) +#define TEGRA_PIN_DAP2_FS_PA2 _GPIO(2) +#define TEGRA_PIN_DAP2_SCLK_PA3 _GPIO(3) +#define TEGRA_PIN_DAP2_DIN_PA4 _GPIO(4) +#define TEGRA_PIN_DAP2_DOUT_PA5 _GPIO(5) +#define TEGRA_PIN_SDMMC3_CLK_PA6 _GPIO(6) +#define TEGRA_PIN_SDMMC3_CMD_PA7 _GPIO(7) +#define TEGRA_PIN_GMI_A17_PB0 _GPIO(8) +#define TEGRA_PIN_GMI_A18_PB1 _GPIO(9) +#define TEGRA_PIN_LCD_PWR0_PB2 _GPIO(10) +#define TEGRA_PIN_LCD_PCLK_PB3 _GPIO(11) +#define TEGRA_PIN_SDMMC3_DAT3_PB4 _GPIO(12) +#define TEGRA_PIN_SDMMC3_DAT2_PB5 _GPIO(13) +#define TEGRA_PIN_SDMMC3_DAT1_PB6 _GPIO(14) +#define TEGRA_PIN_SDMMC3_DAT0_PB7 _GPIO(15) +#define TEGRA_PIN_UART3_RTS_N_PC0 _GPIO(16) +#define TEGRA_PIN_LCD_PWR1_PC1 _GPIO(17) +#define TEGRA_PIN_UART2_TXD_PC2 _GPIO(18) +#define TEGRA_PIN_UART2_RXD_PC3 _GPIO(19) +#define TEGRA_PIN_GEN1_I2C_SCL_PC4 _GPIO(20) +#define TEGRA_PIN_GEN1_I2C_SDA_PC5 _GPIO(21) +#define TEGRA_PIN_LCD_PWR2_PC6 _GPIO(22) +#define TEGRA_PIN_GMI_WP_N_PC7 _GPIO(23) +#define TEGRA_PIN_SDMMC3_DAT5_PD0 _GPIO(24) +#define TEGRA_PIN_SDMMC3_DAT4_PD1 _GPIO(25) +#define TEGRA_PIN_LCD_DC1_PD2 _GPIO(26) +#define TEGRA_PIN_SDMMC3_DAT6_PD3 _GPIO(27) +#define TEGRA_PIN_SDMMC3_DAT7_PD4 _GPIO(28) +#define TEGRA_PIN_VI_D1_PD5 _GPIO(29) +#define TEGRA_PIN_VI_VSYNC_PD6 _GPIO(30) +#define TEGRA_PIN_VI_HSYNC_PD7 _GPIO(31) +#define TEGRA_PIN_LCD_D0_PE0 _GPIO(32) +#define TEGRA_PIN_LCD_D1_PE1 _GPIO(33) +#define TEGRA_PIN_LCD_D2_PE2 _GPIO(34) +#define TEGRA_PIN_LCD_D3_PE3 _GPIO(35) +#define TEGRA_PIN_LCD_D4_PE4 _GPIO(36) +#define TEGRA_PIN_LCD_D5_PE5 _GPIO(37) +#define TEGRA_PIN_LCD_D6_PE6 _GPIO(38) +#define TEGRA_PIN_LCD_D7_PE7 _GPIO(39) +#define TEGRA_PIN_LCD_D8_PF0 _GPIO(40) +#define TEGRA_PIN_LCD_D9_PF1 _GPIO(41) +#define TEGRA_PIN_LCD_D10_PF2 _GPIO(42) +#define TEGRA_PIN_LCD_D11_PF3 _GPIO(43) +#define TEGRA_PIN_LCD_D12_PF4 _GPIO(44) +#define TEGRA_PIN_LCD_D13_PF5 _GPIO(45) +#define TEGRA_PIN_LCD_D14_PF6 _GPIO(46) +#define TEGRA_PIN_LCD_D15_PF7 _GPIO(47) +#define TEGRA_PIN_GMI_AD0_PG0 _GPIO(48) +#define TEGRA_PIN_GMI_AD1_PG1 _GPIO(49) +#define TEGRA_PIN_GMI_AD2_PG2 _GPIO(50) +#define TEGRA_PIN_GMI_AD3_PG3 _GPIO(51) +#define TEGRA_PIN_GMI_AD4_PG4 _GPIO(52) +#define TEGRA_PIN_GMI_AD5_PG5 _GPIO(53) +#define TEGRA_PIN_GMI_AD6_PG6 _GPIO(54) +#define TEGRA_PIN_GMI_AD7_PG7 _GPIO(55) +#define TEGRA_PIN_GMI_AD8_PH0 _GPIO(56) +#define TEGRA_PIN_GMI_AD9_PH1 _GPIO(57) +#define TEGRA_PIN_GMI_AD10_PH2 _GPIO(58) +#define TEGRA_PIN_GMI_AD11_PH3 _GPIO(59) +#define TEGRA_PIN_GMI_AD12_PH4 _GPIO(60) +#define TEGRA_PIN_GMI_AD13_PH5 _GPIO(61) +#define TEGRA_PIN_GMI_AD14_PH6 _GPIO(62) +#define TEGRA_PIN_GMI_AD15_PH7 _GPIO(63) +#define TEGRA_PIN_GMI_WR_N_PI0 _GPIO(64) +#define TEGRA_PIN_GMI_OE_N_PI1 _GPIO(65) +#define TEGRA_PIN_GMI_DQS_PI2 _GPIO(66) +#define TEGRA_PIN_GMI_CS6_N_PI3 _GPIO(67) +#define TEGRA_PIN_GMI_RST_N_PI4 _GPIO(68) +#define TEGRA_PIN_GMI_IORDY_PI5 _GPIO(69) +#define TEGRA_PIN_GMI_CS7_N_PI6 _GPIO(70) +#define TEGRA_PIN_GMI_WAIT_PI7 _GPIO(71) +#define TEGRA_PIN_GMI_CS0_N_PJ0 _GPIO(72) +#define TEGRA_PIN_LCD_DE_PJ1 _GPIO(73) +#define TEGRA_PIN_GMI_CS1_N_PJ2 _GPIO(74) +#define TEGRA_PIN_LCD_HSYNC_PJ3 _GPIO(75) +#define TEGRA_PIN_LCD_VSYNC_PJ4 _GPIO(76) +#define TEGRA_PIN_UART2_CTS_N_PJ5 _GPIO(77) +#define TEGRA_PIN_UART2_RTS_N_PJ6 _GPIO(78) +#define TEGRA_PIN_GMI_A16_PJ7 _GPIO(79) +#define TEGRA_PIN_GMI_ADV_N_PK0 _GPIO(80) +#define TEGRA_PIN_GMI_CLK_PK1 _GPIO(81) +#define TEGRA_PIN_GMI_CS4_N_PK2 _GPIO(82) +#define TEGRA_PIN_GMI_CS2_N_PK3 _GPIO(83) +#define TEGRA_PIN_GMI_CS3_N_PK4 _GPIO(84) +#define TEGRA_PIN_SPDIF_OUT_PK5 _GPIO(85) +#define TEGRA_PIN_SPDIF_IN_PK6 _GPIO(86) +#define TEGRA_PIN_GMI_A19_PK7 _GPIO(87) +#define TEGRA_PIN_VI_D2_PL0 _GPIO(88) +#define TEGRA_PIN_VI_D3_PL1 _GPIO(89) +#define TEGRA_PIN_VI_D4_PL2 _GPIO(90) +#define TEGRA_PIN_VI_D5_PL3 _GPIO(91) +#define TEGRA_PIN_VI_D6_PL4 _GPIO(92) +#define TEGRA_PIN_VI_D7_PL5 _GPIO(93) +#define TEGRA_PIN_VI_D8_PL6 _GPIO(94) +#define TEGRA_PIN_VI_D9_PL7 _GPIO(95) +#define TEGRA_PIN_LCD_D16_PM0 _GPIO(96) +#define TEGRA_PIN_LCD_D17_PM1 _GPIO(97) +#define TEGRA_PIN_LCD_D18_PM2 _GPIO(98) +#define TEGRA_PIN_LCD_D19_PM3 _GPIO(99) +#define TEGRA_PIN_LCD_D20_PM4 _GPIO(100) +#define TEGRA_PIN_LCD_D21_PM5 _GPIO(101) +#define TEGRA_PIN_LCD_D22_PM6 _GPIO(102) +#define TEGRA_PIN_LCD_D23_PM7 _GPIO(103) +#define TEGRA_PIN_DAP1_FS_PN0 _GPIO(104) +#define TEGRA_PIN_DAP1_DIN_PN1 _GPIO(105) +#define TEGRA_PIN_DAP1_DOUT_PN2 _GPIO(106) +#define TEGRA_PIN_DAP1_SCLK_PN3 _GPIO(107) +#define TEGRA_PIN_LCD_CS0_N_PN4 _GPIO(108) +#define TEGRA_PIN_LCD_SDOUT_PN5 _GPIO(109) +#define TEGRA_PIN_LCD_DC0_PN6 _GPIO(110) +#define TEGRA_PIN_HDMI_INT_PN7 _GPIO(111) +#define TEGRA_PIN_ULPI_DATA7_PO0 _GPIO(112) +#define TEGRA_PIN_ULPI_DATA0_PO1 _GPIO(113) +#define TEGRA_PIN_ULPI_DATA1_PO2 _GPIO(114) +#define TEGRA_PIN_ULPI_DATA2_PO3 _GPIO(115) +#define TEGRA_PIN_ULPI_DATA3_PO4 _GPIO(116) +#define TEGRA_PIN_ULPI_DATA4_PO5 _GPIO(117) +#define TEGRA_PIN_ULPI_DATA5_PO6 _GPIO(118) +#define TEGRA_PIN_ULPI_DATA6_PO7 _GPIO(119) +#define TEGRA_PIN_DAP3_FS_PP0 _GPIO(120) +#define TEGRA_PIN_DAP3_DIN_PP1 _GPIO(121) +#define TEGRA_PIN_DAP3_DOUT_PP2 _GPIO(122) +#define TEGRA_PIN_DAP3_SCLK_PP3 _GPIO(123) +#define TEGRA_PIN_DAP4_FS_PP4 _GPIO(124) +#define TEGRA_PIN_DAP4_DIN_PP5 _GPIO(125) +#define TEGRA_PIN_DAP4_DOUT_PP6 _GPIO(126) +#define TEGRA_PIN_DAP4_SCLK_PP7 _GPIO(127) +#define TEGRA_PIN_KB_COL0_PQ0 _GPIO(128) +#define TEGRA_PIN_KB_COL1_PQ1 _GPIO(129) +#define TEGRA_PIN_KB_COL2_PQ2 _GPIO(130) +#define TEGRA_PIN_KB_COL3_PQ3 _GPIO(131) +#define TEGRA_PIN_KB_COL4_PQ4 _GPIO(132) +#define TEGRA_PIN_KB_COL5_PQ5 _GPIO(133) +#define TEGRA_PIN_KB_COL6_PQ6 _GPIO(134) +#define TEGRA_PIN_KB_COL7_PQ7 _GPIO(135) +#define TEGRA_PIN_KB_ROW0_PR0 _GPIO(136) +#define TEGRA_PIN_KB_ROW1_PR1 _GPIO(137) +#define TEGRA_PIN_KB_ROW2_PR2 _GPIO(138) +#define TEGRA_PIN_KB_ROW3_PR3 _GPIO(139) +#define TEGRA_PIN_KB_ROW4_PR4 _GPIO(140) +#define TEGRA_PIN_KB_ROW5_PR5 _GPIO(141) +#define TEGRA_PIN_KB_ROW6_PR6 _GPIO(142) +#define TEGRA_PIN_KB_ROW7_PR7 _GPIO(143) +#define TEGRA_PIN_KB_ROW8_PS0 _GPIO(144) +#define TEGRA_PIN_KB_ROW9_PS1 _GPIO(145) +#define TEGRA_PIN_KB_ROW10_PS2 _GPIO(146) +#define TEGRA_PIN_KB_ROW11_PS3 _GPIO(147) +#define TEGRA_PIN_KB_ROW12_PS4 _GPIO(148) +#define TEGRA_PIN_KB_ROW13_PS5 _GPIO(149) +#define TEGRA_PIN_KB_ROW14_PS6 _GPIO(150) +#define TEGRA_PIN_KB_ROW15_PS7 _GPIO(151) +#define TEGRA_PIN_VI_PCLK_PT0 _GPIO(152) +#define TEGRA_PIN_VI_MCLK_PT1 _GPIO(153) +#define TEGRA_PIN_VI_D10_PT2 _GPIO(154) +#define TEGRA_PIN_VI_D11_PT3 _GPIO(155) +#define TEGRA_PIN_VI_D0_PT4 _GPIO(156) +#define TEGRA_PIN_GEN2_I2C_SCL_PT5 _GPIO(157) +#define TEGRA_PIN_GEN2_I2C_SDA_PT6 _GPIO(158) +#define TEGRA_PIN_SDMMC4_CMD_PT7 _GPIO(159) +#define TEGRA_PIN_PU0 _GPIO(160) +#define TEGRA_PIN_PU1 _GPIO(161) +#define TEGRA_PIN_PU2 _GPIO(162) +#define TEGRA_PIN_PU3 _GPIO(163) +#define TEGRA_PIN_PU4 _GPIO(164) +#define TEGRA_PIN_PU5 _GPIO(165) +#define TEGRA_PIN_PU6 _GPIO(166) +#define TEGRA_PIN_JTAG_RTCK_PU7 _GPIO(167) +#define TEGRA_PIN_PV0 _GPIO(168) +#define TEGRA_PIN_PV1 _GPIO(169) +#define TEGRA_PIN_PV2 _GPIO(170) +#define TEGRA_PIN_PV3 _GPIO(171) +#define TEGRA_PIN_DDC_SCL_PV4 _GPIO(172) +#define TEGRA_PIN_DDC_SDA_PV5 _GPIO(173) +#define TEGRA_PIN_CRT_HSYNC_PV6 _GPIO(174) +#define TEGRA_PIN_CRT_VSYNC_PV7 _GPIO(175) +#define TEGRA_PIN_LCD_CS1_N_PW0 _GPIO(176) +#define TEGRA_PIN_LCD_M1_PW1 _GPIO(177) +#define TEGRA_PIN_SPI2_CS1_N_PW2 _GPIO(178) +#define TEGRA_PIN_SPI2_CS2_N_PW3 _GPIO(179) +#define TEGRA_PIN_CLK1_OUT_PW4 _GPIO(180) +#define TEGRA_PIN_CLK2_OUT_PW5 _GPIO(181) +#define TEGRA_PIN_UART3_TXD_PW6 _GPIO(182) +#define TEGRA_PIN_UART3_RXD_PW7 _GPIO(183) +#define TEGRA_PIN_SPI2_MOSI_PX0 _GPIO(184) +#define TEGRA_PIN_SPI2_MISO_PX1 _GPIO(185) +#define TEGRA_PIN_SPI2_SCK_PX2 _GPIO(186) +#define TEGRA_PIN_SPI2_CS0_N_PX3 _GPIO(187) +#define TEGRA_PIN_SPI1_MOSI_PX4 _GPIO(188) +#define TEGRA_PIN_SPI1_SCK_PX5 _GPIO(189) +#define TEGRA_PIN_SPI1_CS0_N_PX6 _GPIO(190) +#define TEGRA_PIN_SPI1_MISO_PX7 _GPIO(191) +#define TEGRA_PIN_ULPI_CLK_PY0 _GPIO(192) +#define TEGRA_PIN_ULPI_DIR_PY1 _GPIO(193) +#define TEGRA_PIN_ULPI_NXT_PY2 _GPIO(194) +#define TEGRA_PIN_ULPI_STP_PY3 _GPIO(195) +#define TEGRA_PIN_SDMMC1_DAT3_PY4 _GPIO(196) +#define TEGRA_PIN_SDMMC1_DAT2_PY5 _GPIO(197) +#define TEGRA_PIN_SDMMC1_DAT1_PY6 _GPIO(198) +#define TEGRA_PIN_SDMMC1_DAT0_PY7 _GPIO(199) +#define TEGRA_PIN_SDMMC1_CLK_PZ0 _GPIO(200) +#define TEGRA_PIN_SDMMC1_CMD_PZ1 _GPIO(201) +#define TEGRA_PIN_LCD_SDIN_PZ2 _GPIO(202) +#define TEGRA_PIN_LCD_WR_N_PZ3 _GPIO(203) +#define TEGRA_PIN_LCD_SCK_PZ4 _GPIO(204) +#define TEGRA_PIN_SYS_CLK_REQ_PZ5 _GPIO(205) +#define TEGRA_PIN_PWR_I2C_SCL_PZ6 _GPIO(206) +#define TEGRA_PIN_PWR_I2C_SDA_PZ7 _GPIO(207) +#define TEGRA_PIN_SDMMC4_DAT0_PAA0 _GPIO(208) +#define TEGRA_PIN_SDMMC4_DAT1_PAA1 _GPIO(209) +#define TEGRA_PIN_SDMMC4_DAT2_PAA2 _GPIO(210) +#define TEGRA_PIN_SDMMC4_DAT3_PAA3 _GPIO(211) +#define TEGRA_PIN_SDMMC4_DAT4_PAA4 _GPIO(212) +#define TEGRA_PIN_SDMMC4_DAT5_PAA5 _GPIO(213) +#define TEGRA_PIN_SDMMC4_DAT6_PAA6 _GPIO(214) +#define TEGRA_PIN_SDMMC4_DAT7_PAA7 _GPIO(215) +#define TEGRA_PIN_PBB0 _GPIO(216) +#define TEGRA_PIN_CAM_I2C_SCL_PBB1 _GPIO(217) +#define TEGRA_PIN_CAM_I2C_SDA_PBB2 _GPIO(218) +#define TEGRA_PIN_PBB3 _GPIO(219) +#define TEGRA_PIN_PBB4 _GPIO(220) +#define TEGRA_PIN_PBB5 _GPIO(221) +#define TEGRA_PIN_PBB6 _GPIO(222) +#define TEGRA_PIN_PBB7 _GPIO(223) +#define TEGRA_PIN_CAM_MCLK_PCC0 _GPIO(224) +#define TEGRA_PIN_PCC1 _GPIO(225) +#define TEGRA_PIN_PCC2 _GPIO(226) +#define TEGRA_PIN_SDMMC4_RST_N_PCC3 _GPIO(227) +#define TEGRA_PIN_SDMMC4_CLK_PCC4 _GPIO(228) +#define TEGRA_PIN_CLK2_REQ_PCC5 _GPIO(229) +#define TEGRA_PIN_PEX_L2_RST_N_PCC6 _GPIO(230) +#define TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7 _GPIO(231) +#define TEGRA_PIN_PEX_L0_PRSNT_N_PDD0 _GPIO(232) +#define TEGRA_PIN_PEX_L0_RST_N_PDD1 _GPIO(233) +#define TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2 _GPIO(234) +#define TEGRA_PIN_PEX_WAKE_N_PDD3 _GPIO(235) +#define TEGRA_PIN_PEX_L1_PRSNT_N_PDD4 _GPIO(236) +#define TEGRA_PIN_PEX_L1_RST_N_PDD5 _GPIO(237) +#define TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6 _GPIO(238) +#define TEGRA_PIN_PEX_L2_PRSNT_N_PDD7 _GPIO(239) +#define TEGRA_PIN_CLK3_OUT_PEE0 _GPIO(240) +#define TEGRA_PIN_CLK3_REQ_PEE1 _GPIO(241) +#define TEGRA_PIN_CLK1_REQ_PEE2 _GPIO(242) +#define TEGRA_PIN_HDMI_CEC_PEE3 _GPIO(243) +#define TEGRA_PIN_PEE4 _GPIO(244) +#define TEGRA_PIN_PEE5 _GPIO(245) +#define TEGRA_PIN_PEE6 _GPIO(246) +#define TEGRA_PIN_PEE7 _GPIO(247) + +/* All non-GPIO pins follow */ +#define NUM_GPIOS (TEGRA_PIN_PEE7 + 1) +#define _PIN(offset) (NUM_GPIOS + (offset)) + +/* Non-GPIO pins */ +#define TEGRA_PIN_CLK_32K_IN _PIN(0) +#define TEGRA_PIN_CORE_PWR_REQ _PIN(1) +#define TEGRA_PIN_CPU_PWR_REQ _PIN(2) +#define TEGRA_PIN_JTAG_TCK _PIN(3) +#define TEGRA_PIN_JTAG_TDI _PIN(4) +#define TEGRA_PIN_JTAG_TDO _PIN(5) +#define TEGRA_PIN_JTAG_TMS _PIN(6) +#define TEGRA_PIN_JTAG_TRST_N _PIN(7) +#define TEGRA_PIN_OWR _PIN(8) +#define TEGRA_PIN_PWR_INT_N _PIN(9) +#define TEGRA_PIN_SYS_RESET_N _PIN(10) +#define TEGRA_PIN_TEST_MODE_EN _PIN(11) + +static const struct pinctrl_pin_desc tegra30_pins[] = { + PINCTRL_PIN(TEGRA_PIN_CLK_32K_OUT_PA0, "CLK_32K_OUT PA0"), + PINCTRL_PIN(TEGRA_PIN_UART3_CTS_N_PA1, "UART3_CTS_N PA1"), + PINCTRL_PIN(TEGRA_PIN_DAP2_FS_PA2, "DAP2_FS PA2"), + PINCTRL_PIN(TEGRA_PIN_DAP2_SCLK_PA3, "DAP2_SCLK PA3"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DIN_PA4, "DAP2_DIN PA4"), + PINCTRL_PIN(TEGRA_PIN_DAP2_DOUT_PA5, "DAP2_DOUT PA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CLK_PA6, "SDMMC3_CLK PA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_CMD_PA7, "SDMMC3_CMD PA7"), + PINCTRL_PIN(TEGRA_PIN_GMI_A17_PB0, "GMI_A17 PB0"), + PINCTRL_PIN(TEGRA_PIN_GMI_A18_PB1, "GMI_A18 PB1"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR0_PB2, "LCD_PWR0 PB2"), + PINCTRL_PIN(TEGRA_PIN_LCD_PCLK_PB3, "LCD_PCLK PB3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT3_PB4, "SDMMC3_DAT3 PB4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT2_PB5, "SDMMC3_DAT2 PB5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT1_PB6, "SDMMC3_DAT1 PB6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT0_PB7, "SDMMC3_DAT0 PB7"), + PINCTRL_PIN(TEGRA_PIN_UART3_RTS_N_PC0, "UART3_RTS_N PC0"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR1_PC1, "LCD_PWR1 PC1"), + PINCTRL_PIN(TEGRA_PIN_UART2_TXD_PC2, "UART2_TXD PC2"), + PINCTRL_PIN(TEGRA_PIN_UART2_RXD_PC3, "UART2_RXD PC3"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SCL_PC4, "GEN1_I2C_SCL PC4"), + PINCTRL_PIN(TEGRA_PIN_GEN1_I2C_SDA_PC5, "GEN1_I2C_SDA PC5"), + PINCTRL_PIN(TEGRA_PIN_LCD_PWR2_PC6, "LCD_PWR2 PC6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WP_N_PC7, "GMI_WP_N PC7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT5_PD0, "SDMMC3_DAT5 PD0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT4_PD1, "SDMMC3_DAT4 PD1"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC1_PD2, "LCD_DC1 PD2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT6_PD3, "SDMMC3_DAT6 PD3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC3_DAT7_PD4, "SDMMC3_DAT7 PD4"), + PINCTRL_PIN(TEGRA_PIN_VI_D1_PD5, "VI_D1 PD5"), + PINCTRL_PIN(TEGRA_PIN_VI_VSYNC_PD6, "VI_VSYNC PD6"), + PINCTRL_PIN(TEGRA_PIN_VI_HSYNC_PD7, "VI_HSYNC PD7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D0_PE0, "LCD_D0 PE0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D1_PE1, "LCD_D1 PE1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D2_PE2, "LCD_D2 PE2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D3_PE3, "LCD_D3 PE3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D4_PE4, "LCD_D4 PE4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D5_PE5, "LCD_D5 PE5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D6_PE6, "LCD_D6 PE6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D7_PE7, "LCD_D7 PE7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D8_PF0, "LCD_D8 PF0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D9_PF1, "LCD_D9 PF1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D10_PF2, "LCD_D10 PF2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D11_PF3, "LCD_D11 PF3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D12_PF4, "LCD_D12 PF4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D13_PF5, "LCD_D13 PF5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D14_PF6, "LCD_D14 PF6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D15_PF7, "LCD_D15 PF7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD0_PG0, "GMI_AD0 PG0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD1_PG1, "GMI_AD1 PG1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD2_PG2, "GMI_AD2 PG2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD3_PG3, "GMI_AD3 PG3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD4_PG4, "GMI_AD4 PG4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD5_PG5, "GMI_AD5 PG5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD6_PG6, "GMI_AD6 PG6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD7_PG7, "GMI_AD7 PG7"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD8_PH0, "GMI_AD8 PH0"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD9_PH1, "GMI_AD9 PH1"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD10_PH2, "GMI_AD10 PH2"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD11_PH3, "GMI_AD11 PH3"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD12_PH4, "GMI_AD12 PH4"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD13_PH5, "GMI_AD13 PH5"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD14_PH6, "GMI_AD14 PH6"), + PINCTRL_PIN(TEGRA_PIN_GMI_AD15_PH7, "GMI_AD15 PH7"), + PINCTRL_PIN(TEGRA_PIN_GMI_WR_N_PI0, "GMI_WR_N PI0"), + PINCTRL_PIN(TEGRA_PIN_GMI_OE_N_PI1, "GMI_OE_N PI1"), + PINCTRL_PIN(TEGRA_PIN_GMI_DQS_PI2, "GMI_DQS PI2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS6_N_PI3, "GMI_CS6_N PI3"), + PINCTRL_PIN(TEGRA_PIN_GMI_RST_N_PI4, "GMI_RST_N PI4"), + PINCTRL_PIN(TEGRA_PIN_GMI_IORDY_PI5, "GMI_IORDY PI5"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS7_N_PI6, "GMI_CS7_N PI6"), + PINCTRL_PIN(TEGRA_PIN_GMI_WAIT_PI7, "GMI_WAIT PI7"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS0_N_PJ0, "GMI_CS0_N PJ0"), + PINCTRL_PIN(TEGRA_PIN_LCD_DE_PJ1, "LCD_DE PJ1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS1_N_PJ2, "GMI_CS1_N PJ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_HSYNC_PJ3, "LCD_HSYNC PJ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_VSYNC_PJ4, "LCD_VSYNC PJ4"), + PINCTRL_PIN(TEGRA_PIN_UART2_CTS_N_PJ5, "UART2_CTS_N PJ5"), + PINCTRL_PIN(TEGRA_PIN_UART2_RTS_N_PJ6, "UART2_RTS_N PJ6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A16_PJ7, "GMI_A16 PJ7"), + PINCTRL_PIN(TEGRA_PIN_GMI_ADV_N_PK0, "GMI_ADV_N PK0"), + PINCTRL_PIN(TEGRA_PIN_GMI_CLK_PK1, "GMI_CLK PK1"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS4_N_PK2, "GMI_CS4_N PK2"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS2_N_PK3, "GMI_CS2_N PK3"), + PINCTRL_PIN(TEGRA_PIN_GMI_CS3_N_PK4, "GMI_CS3_N PK4"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_OUT_PK5, "SPDIF_OUT PK5"), + PINCTRL_PIN(TEGRA_PIN_SPDIF_IN_PK6, "SPDIF_IN PK6"), + PINCTRL_PIN(TEGRA_PIN_GMI_A19_PK7, "GMI_A19 PK7"), + PINCTRL_PIN(TEGRA_PIN_VI_D2_PL0, "VI_D2 PL0"), + PINCTRL_PIN(TEGRA_PIN_VI_D3_PL1, "VI_D3 PL1"), + PINCTRL_PIN(TEGRA_PIN_VI_D4_PL2, "VI_D4 PL2"), + PINCTRL_PIN(TEGRA_PIN_VI_D5_PL3, "VI_D5 PL3"), + PINCTRL_PIN(TEGRA_PIN_VI_D6_PL4, "VI_D6 PL4"), + PINCTRL_PIN(TEGRA_PIN_VI_D7_PL5, "VI_D7 PL5"), + PINCTRL_PIN(TEGRA_PIN_VI_D8_PL6, "VI_D8 PL6"), + PINCTRL_PIN(TEGRA_PIN_VI_D9_PL7, "VI_D9 PL7"), + PINCTRL_PIN(TEGRA_PIN_LCD_D16_PM0, "LCD_D16 PM0"), + PINCTRL_PIN(TEGRA_PIN_LCD_D17_PM1, "LCD_D17 PM1"), + PINCTRL_PIN(TEGRA_PIN_LCD_D18_PM2, "LCD_D18 PM2"), + PINCTRL_PIN(TEGRA_PIN_LCD_D19_PM3, "LCD_D19 PM3"), + PINCTRL_PIN(TEGRA_PIN_LCD_D20_PM4, "LCD_D20 PM4"), + PINCTRL_PIN(TEGRA_PIN_LCD_D21_PM5, "LCD_D21 PM5"), + PINCTRL_PIN(TEGRA_PIN_LCD_D22_PM6, "LCD_D22 PM6"), + PINCTRL_PIN(TEGRA_PIN_LCD_D23_PM7, "LCD_D23 PM7"), + PINCTRL_PIN(TEGRA_PIN_DAP1_FS_PN0, "DAP1_FS PN0"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DIN_PN1, "DAP1_DIN PN1"), + PINCTRL_PIN(TEGRA_PIN_DAP1_DOUT_PN2, "DAP1_DOUT PN2"), + PINCTRL_PIN(TEGRA_PIN_DAP1_SCLK_PN3, "DAP1_SCLK PN3"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS0_N_PN4, "LCD_CS0_N PN4"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDOUT_PN5, "LCD_SDOUT PN5"), + PINCTRL_PIN(TEGRA_PIN_LCD_DC0_PN6, "LCD_DC0 PN6"), + PINCTRL_PIN(TEGRA_PIN_HDMI_INT_PN7, "HDMI_INT PN7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA7_PO0, "ULPI_DATA7 PO0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA0_PO1, "ULPI_DATA0 PO1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA1_PO2, "ULPI_DATA1 PO2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA2_PO3, "ULPI_DATA2 PO3"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA3_PO4, "ULPI_DATA3 PO4"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA4_PO5, "ULPI_DATA4 PO5"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA5_PO6, "ULPI_DATA5 PO6"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DATA6_PO7, "ULPI_DATA6 PO7"), + PINCTRL_PIN(TEGRA_PIN_DAP3_FS_PP0, "DAP3_FS PP0"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DIN_PP1, "DAP3_DIN PP1"), + PINCTRL_PIN(TEGRA_PIN_DAP3_DOUT_PP2, "DAP3_DOUT PP2"), + PINCTRL_PIN(TEGRA_PIN_DAP3_SCLK_PP3, "DAP3_SCLK PP3"), + PINCTRL_PIN(TEGRA_PIN_DAP4_FS_PP4, "DAP4_FS PP4"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DIN_PP5, "DAP4_DIN PP5"), + PINCTRL_PIN(TEGRA_PIN_DAP4_DOUT_PP6, "DAP4_DOUT PP6"), + PINCTRL_PIN(TEGRA_PIN_DAP4_SCLK_PP7, "DAP4_SCLK PP7"), + PINCTRL_PIN(TEGRA_PIN_KB_COL0_PQ0, "KB_COL0 PQ0"), + PINCTRL_PIN(TEGRA_PIN_KB_COL1_PQ1, "KB_COL1 PQ1"), + PINCTRL_PIN(TEGRA_PIN_KB_COL2_PQ2, "KB_COL2 PQ2"), + PINCTRL_PIN(TEGRA_PIN_KB_COL3_PQ3, "KB_COL3 PQ3"), + PINCTRL_PIN(TEGRA_PIN_KB_COL4_PQ4, "KB_COL4 PQ4"), + PINCTRL_PIN(TEGRA_PIN_KB_COL5_PQ5, "KB_COL5 PQ5"), + PINCTRL_PIN(TEGRA_PIN_KB_COL6_PQ6, "KB_COL6 PQ6"), + PINCTRL_PIN(TEGRA_PIN_KB_COL7_PQ7, "KB_COL7 PQ7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW0_PR0, "KB_ROW0 PR0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW1_PR1, "KB_ROW1 PR1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW2_PR2, "KB_ROW2 PR2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW3_PR3, "KB_ROW3 PR3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW4_PR4, "KB_ROW4 PR4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW5_PR5, "KB_ROW5 PR5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW6_PR6, "KB_ROW6 PR6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW7_PR7, "KB_ROW7 PR7"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW8_PS0, "KB_ROW8 PS0"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW9_PS1, "KB_ROW9 PS1"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW10_PS2, "KB_ROW10 PS2"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW11_PS3, "KB_ROW11 PS3"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW12_PS4, "KB_ROW12 PS4"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW13_PS5, "KB_ROW13 PS5"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW14_PS6, "KB_ROW14 PS6"), + PINCTRL_PIN(TEGRA_PIN_KB_ROW15_PS7, "KB_ROW15 PS7"), + PINCTRL_PIN(TEGRA_PIN_VI_PCLK_PT0, "VI_PCLK PT0"), + PINCTRL_PIN(TEGRA_PIN_VI_MCLK_PT1, "VI_MCLK PT1"), + PINCTRL_PIN(TEGRA_PIN_VI_D10_PT2, "VI_D10 PT2"), + PINCTRL_PIN(TEGRA_PIN_VI_D11_PT3, "VI_D11 PT3"), + PINCTRL_PIN(TEGRA_PIN_VI_D0_PT4, "VI_D0 PT4"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SCL_PT5, "GEN2_I2C_SCL PT5"), + PINCTRL_PIN(TEGRA_PIN_GEN2_I2C_SDA_PT6, "GEN2_I2C_SDA PT6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CMD_PT7, "SDMMC4_CMD PT7"), + PINCTRL_PIN(TEGRA_PIN_PU0, "PU0"), + PINCTRL_PIN(TEGRA_PIN_PU1, "PU1"), + PINCTRL_PIN(TEGRA_PIN_PU2, "PU2"), + PINCTRL_PIN(TEGRA_PIN_PU3, "PU3"), + PINCTRL_PIN(TEGRA_PIN_PU4, "PU4"), + PINCTRL_PIN(TEGRA_PIN_PU5, "PU5"), + PINCTRL_PIN(TEGRA_PIN_PU6, "PU6"), + PINCTRL_PIN(TEGRA_PIN_JTAG_RTCK_PU7, "JTAG_RTCK PU7"), + PINCTRL_PIN(TEGRA_PIN_PV0, "PV0"), + PINCTRL_PIN(TEGRA_PIN_PV1, "PV1"), + PINCTRL_PIN(TEGRA_PIN_PV2, "PV2"), + PINCTRL_PIN(TEGRA_PIN_PV3, "PV3"), + PINCTRL_PIN(TEGRA_PIN_DDC_SCL_PV4, "DDC_SCL PV4"), + PINCTRL_PIN(TEGRA_PIN_DDC_SDA_PV5, "DDC_SDA PV5"), + PINCTRL_PIN(TEGRA_PIN_CRT_HSYNC_PV6, "CRT_HSYNC PV6"), + PINCTRL_PIN(TEGRA_PIN_CRT_VSYNC_PV7, "CRT_VSYNC PV7"), + PINCTRL_PIN(TEGRA_PIN_LCD_CS1_N_PW0, "LCD_CS1_N PW0"), + PINCTRL_PIN(TEGRA_PIN_LCD_M1_PW1, "LCD_M1 PW1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS1_N_PW2, "SPI2_CS1_N PW2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS2_N_PW3, "SPI2_CS2_N PW3"), + PINCTRL_PIN(TEGRA_PIN_CLK1_OUT_PW4, "CLK1_OUT PW4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_OUT_PW5, "CLK2_OUT PW5"), + PINCTRL_PIN(TEGRA_PIN_UART3_TXD_PW6, "UART3_TXD PW6"), + PINCTRL_PIN(TEGRA_PIN_UART3_RXD_PW7, "UART3_RXD PW7"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MOSI_PX0, "SPI2_MOSI PX0"), + PINCTRL_PIN(TEGRA_PIN_SPI2_MISO_PX1, "SPI2_MISO PX1"), + PINCTRL_PIN(TEGRA_PIN_SPI2_SCK_PX2, "SPI2_SCK PX2"), + PINCTRL_PIN(TEGRA_PIN_SPI2_CS0_N_PX3, "SPI2_CS0_N PX3"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MOSI_PX4, "SPI1_MOSI PX4"), + PINCTRL_PIN(TEGRA_PIN_SPI1_SCK_PX5, "SPI1_SCK PX5"), + PINCTRL_PIN(TEGRA_PIN_SPI1_CS0_N_PX6, "SPI1_CS0_N PX6"), + PINCTRL_PIN(TEGRA_PIN_SPI1_MISO_PX7, "SPI1_MISO PX7"), + PINCTRL_PIN(TEGRA_PIN_ULPI_CLK_PY0, "ULPI_CLK PY0"), + PINCTRL_PIN(TEGRA_PIN_ULPI_DIR_PY1, "ULPI_DIR PY1"), + PINCTRL_PIN(TEGRA_PIN_ULPI_NXT_PY2, "ULPI_NXT PY2"), + PINCTRL_PIN(TEGRA_PIN_ULPI_STP_PY3, "ULPI_STP PY3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT3_PY4, "SDMMC1_DAT3 PY4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT2_PY5, "SDMMC1_DAT2 PY5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT1_PY6, "SDMMC1_DAT1 PY6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_DAT0_PY7, "SDMMC1_DAT0 PY7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CLK_PZ0, "SDMMC1_CLK PZ0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC1_CMD_PZ1, "SDMMC1_CMD PZ1"), + PINCTRL_PIN(TEGRA_PIN_LCD_SDIN_PZ2, "LCD_SDIN PZ2"), + PINCTRL_PIN(TEGRA_PIN_LCD_WR_N_PZ3, "LCD_WR_N PZ3"), + PINCTRL_PIN(TEGRA_PIN_LCD_SCK_PZ4, "LCD_SCK PZ4"), + PINCTRL_PIN(TEGRA_PIN_SYS_CLK_REQ_PZ5, "SYS_CLK_REQ PZ5"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SCL_PZ6, "PWR_I2C_SCL PZ6"), + PINCTRL_PIN(TEGRA_PIN_PWR_I2C_SDA_PZ7, "PWR_I2C_SDA PZ7"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT0_PAA0, "SDMMC4_DAT0 PAA0"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT1_PAA1, "SDMMC4_DAT1 PAA1"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT2_PAA2, "SDMMC4_DAT2 PAA2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT3_PAA3, "SDMMC4_DAT3 PAA3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT4_PAA4, "SDMMC4_DAT4 PAA4"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT5_PAA5, "SDMMC4_DAT5 PAA5"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT6_PAA6, "SDMMC4_DAT6 PAA6"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_DAT7_PAA7, "SDMMC4_DAT7 PAA7"), + PINCTRL_PIN(TEGRA_PIN_PBB0, "PBB0"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SCL_PBB1, "CAM_I2C_SCL PBB1"), + PINCTRL_PIN(TEGRA_PIN_CAM_I2C_SDA_PBB2, "CAM_I2C_SDA PBB2"), + PINCTRL_PIN(TEGRA_PIN_PBB3, "PBB3"), + PINCTRL_PIN(TEGRA_PIN_PBB4, "PBB4"), + PINCTRL_PIN(TEGRA_PIN_PBB5, "PBB5"), + PINCTRL_PIN(TEGRA_PIN_PBB6, "PBB6"), + PINCTRL_PIN(TEGRA_PIN_PBB7, "PBB7"), + PINCTRL_PIN(TEGRA_PIN_CAM_MCLK_PCC0, "CAM_MCLK PCC0"), + PINCTRL_PIN(TEGRA_PIN_PCC1, "PCC1"), + PINCTRL_PIN(TEGRA_PIN_PCC2, "PCC2"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_RST_N_PCC3, "SDMMC4_RST_N PCC3"), + PINCTRL_PIN(TEGRA_PIN_SDMMC4_CLK_PCC4, "SDMMC4_CLK PCC4"), + PINCTRL_PIN(TEGRA_PIN_CLK2_REQ_PCC5, "CLK2_REQ PCC5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_RST_N_PCC6, "PEX_L2_RST_N PCC6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, "PEX_L2_CLKREQ_N PCC7"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, "PEX_L0_PRSNT_N PDD0"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_RST_N_PDD1, "PEX_L0_RST_N PDD1"), + PINCTRL_PIN(TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, "PEX_L0_CLKREQ_N PDD2"), + PINCTRL_PIN(TEGRA_PIN_PEX_WAKE_N_PDD3, "PEX_WAKE_N PDD3"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, "PEX_L1_PRSNT_N PDD4"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_RST_N_PDD5, "PEX_L1_RST_N PDD5"), + PINCTRL_PIN(TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, "PEX_L1_CLKREQ_N PDD6"), + PINCTRL_PIN(TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, "PEX_L2_PRSNT_N PDD7"), + PINCTRL_PIN(TEGRA_PIN_CLK3_OUT_PEE0, "CLK3_OUT PEE0"), + PINCTRL_PIN(TEGRA_PIN_CLK3_REQ_PEE1, "CLK3_REQ PEE1"), + PINCTRL_PIN(TEGRA_PIN_CLK1_REQ_PEE2, "CLK1_REQ PEE2"), + PINCTRL_PIN(TEGRA_PIN_HDMI_CEC_PEE3, "HDMI_CEC PEE3"), + PINCTRL_PIN(TEGRA_PIN_PEE4, "PEE4"), + PINCTRL_PIN(TEGRA_PIN_PEE5, "PEE5"), + PINCTRL_PIN(TEGRA_PIN_PEE6, "PEE6"), + PINCTRL_PIN(TEGRA_PIN_PEE7, "PEE7"), + PINCTRL_PIN(TEGRA_PIN_CLK_32K_IN, "CLK_32K_IN"), + PINCTRL_PIN(TEGRA_PIN_CORE_PWR_REQ, "CORE_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_CPU_PWR_REQ, "CPU_PWR_REQ"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TCK, "JTAG_TCK"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDI, "JTAG_TDI"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TDO, "JTAG_TDO"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TMS, "JTAG_TMS"), + PINCTRL_PIN(TEGRA_PIN_JTAG_TRST_N, "JTAG_TRST_N"), + PINCTRL_PIN(TEGRA_PIN_OWR, "OWR"), + PINCTRL_PIN(TEGRA_PIN_PWR_INT_N, "PWR_INT_N"), + PINCTRL_PIN(TEGRA_PIN_SYS_RESET_N, "SYS_RESET_N"), + PINCTRL_PIN(TEGRA_PIN_TEST_MODE_EN, "TEST_MODE_EN"), +}; + +static const unsigned clk_32k_out_pa0_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, +}; + +static const unsigned uart3_cts_n_pa1_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, +}; + +static const unsigned dap2_fs_pa2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, +}; + +static const unsigned dap2_sclk_pa3_pins[] = { + TEGRA_PIN_DAP2_SCLK_PA3, +}; + +static const unsigned dap2_din_pa4_pins[] = { + TEGRA_PIN_DAP2_DIN_PA4, +}; + +static const unsigned dap2_dout_pa5_pins[] = { + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned sdmmc3_clk_pa6_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, +}; + +static const unsigned sdmmc3_cmd_pa7_pins[] = { + TEGRA_PIN_SDMMC3_CMD_PA7, +}; + +static const unsigned gmi_a17_pb0_pins[] = { + TEGRA_PIN_GMI_A17_PB0, +}; + +static const unsigned gmi_a18_pb1_pins[] = { + TEGRA_PIN_GMI_A18_PB1, +}; + +static const unsigned lcd_pwr0_pb2_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, +}; + +static const unsigned lcd_pclk_pb3_pins[] = { + TEGRA_PIN_LCD_PCLK_PB3, +}; + +static const unsigned sdmmc3_dat3_pb4_pins[] = { + TEGRA_PIN_SDMMC3_DAT3_PB4, +}; + +static const unsigned sdmmc3_dat2_pb5_pins[] = { + TEGRA_PIN_SDMMC3_DAT2_PB5, +}; + +static const unsigned sdmmc3_dat1_pb6_pins[] = { + TEGRA_PIN_SDMMC3_DAT1_PB6, +}; + +static const unsigned sdmmc3_dat0_pb7_pins[] = { + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned uart3_rts_n_pc0_pins[] = { + TEGRA_PIN_UART3_RTS_N_PC0, +}; + +static const unsigned lcd_pwr1_pc1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, +}; + +static const unsigned uart2_txd_pc2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, +}; + +static const unsigned uart2_rxd_pc3_pins[] = { + TEGRA_PIN_UART2_RXD_PC3, +}; + +static const unsigned gen1_i2c_scl_pc4_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, +}; + +static const unsigned gen1_i2c_sda_pc5_pins[] = { + TEGRA_PIN_GEN1_I2C_SDA_PC5, +}; + +static const unsigned lcd_pwr2_pc6_pins[] = { + TEGRA_PIN_LCD_PWR2_PC6, +}; + +static const unsigned gmi_wp_n_pc7_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, +}; + +static const unsigned sdmmc3_dat5_pd0_pins[] = { + TEGRA_PIN_SDMMC3_DAT5_PD0, +}; + +static const unsigned sdmmc3_dat4_pd1_pins[] = { + TEGRA_PIN_SDMMC3_DAT4_PD1, +}; + +static const unsigned lcd_dc1_pd2_pins[] = { + TEGRA_PIN_LCD_DC1_PD2, +}; + +static const unsigned sdmmc3_dat6_pd3_pins[] = { + TEGRA_PIN_SDMMC3_DAT6_PD3, +}; + +static const unsigned sdmmc3_dat7_pd4_pins[] = { + TEGRA_PIN_SDMMC3_DAT7_PD4, +}; + +static const unsigned vi_d1_pd5_pins[] = { + TEGRA_PIN_VI_D1_PD5, +}; + +static const unsigned vi_vsync_pd6_pins[] = { + TEGRA_PIN_VI_VSYNC_PD6, +}; + +static const unsigned vi_hsync_pd7_pins[] = { + TEGRA_PIN_VI_HSYNC_PD7, +}; + +static const unsigned lcd_d0_pe0_pins[] = { + TEGRA_PIN_LCD_D0_PE0, +}; + +static const unsigned lcd_d1_pe1_pins[] = { + TEGRA_PIN_LCD_D1_PE1, +}; + +static const unsigned lcd_d2_pe2_pins[] = { + TEGRA_PIN_LCD_D2_PE2, +}; + +static const unsigned lcd_d3_pe3_pins[] = { + TEGRA_PIN_LCD_D3_PE3, +}; + +static const unsigned lcd_d4_pe4_pins[] = { + TEGRA_PIN_LCD_D4_PE4, +}; + +static const unsigned lcd_d5_pe5_pins[] = { + TEGRA_PIN_LCD_D5_PE5, +}; + +static const unsigned lcd_d6_pe6_pins[] = { + TEGRA_PIN_LCD_D6_PE6, +}; + +static const unsigned lcd_d7_pe7_pins[] = { + TEGRA_PIN_LCD_D7_PE7, +}; + +static const unsigned lcd_d8_pf0_pins[] = { + TEGRA_PIN_LCD_D8_PF0, +}; + +static const unsigned lcd_d9_pf1_pins[] = { + TEGRA_PIN_LCD_D9_PF1, +}; + +static const unsigned lcd_d10_pf2_pins[] = { + TEGRA_PIN_LCD_D10_PF2, +}; + +static const unsigned lcd_d11_pf3_pins[] = { + TEGRA_PIN_LCD_D11_PF3, +}; + +static const unsigned lcd_d12_pf4_pins[] = { + TEGRA_PIN_LCD_D12_PF4, +}; + +static const unsigned lcd_d13_pf5_pins[] = { + TEGRA_PIN_LCD_D13_PF5, +}; + +static const unsigned lcd_d14_pf6_pins[] = { + TEGRA_PIN_LCD_D14_PF6, +}; + +static const unsigned lcd_d15_pf7_pins[] = { + TEGRA_PIN_LCD_D15_PF7, +}; + +static const unsigned gmi_ad0_pg0_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, +}; + +static const unsigned gmi_ad1_pg1_pins[] = { + TEGRA_PIN_GMI_AD1_PG1, +}; + +static const unsigned gmi_ad2_pg2_pins[] = { + TEGRA_PIN_GMI_AD2_PG2, +}; + +static const unsigned gmi_ad3_pg3_pins[] = { + TEGRA_PIN_GMI_AD3_PG3, +}; + +static const unsigned gmi_ad4_pg4_pins[] = { + TEGRA_PIN_GMI_AD4_PG4, +}; + +static const unsigned gmi_ad5_pg5_pins[] = { + TEGRA_PIN_GMI_AD5_PG5, +}; + +static const unsigned gmi_ad6_pg6_pins[] = { + TEGRA_PIN_GMI_AD6_PG6, +}; + +static const unsigned gmi_ad7_pg7_pins[] = { + TEGRA_PIN_GMI_AD7_PG7, +}; + +static const unsigned gmi_ad8_ph0_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, +}; + +static const unsigned gmi_ad9_ph1_pins[] = { + TEGRA_PIN_GMI_AD9_PH1, +}; + +static const unsigned gmi_ad10_ph2_pins[] = { + TEGRA_PIN_GMI_AD10_PH2, +}; + +static const unsigned gmi_ad11_ph3_pins[] = { + TEGRA_PIN_GMI_AD11_PH3, +}; + +static const unsigned gmi_ad12_ph4_pins[] = { + TEGRA_PIN_GMI_AD12_PH4, +}; + +static const unsigned gmi_ad13_ph5_pins[] = { + TEGRA_PIN_GMI_AD13_PH5, +}; + +static const unsigned gmi_ad14_ph6_pins[] = { + TEGRA_PIN_GMI_AD14_PH6, +}; + +static const unsigned gmi_ad15_ph7_pins[] = { + TEGRA_PIN_GMI_AD15_PH7, +}; + +static const unsigned gmi_wr_n_pi0_pins[] = { + TEGRA_PIN_GMI_WR_N_PI0, +}; + +static const unsigned gmi_oe_n_pi1_pins[] = { + TEGRA_PIN_GMI_OE_N_PI1, +}; + +static const unsigned gmi_dqs_pi2_pins[] = { + TEGRA_PIN_GMI_DQS_PI2, +}; + +static const unsigned gmi_cs6_n_pi3_pins[] = { + TEGRA_PIN_GMI_CS6_N_PI3, +}; + +static const unsigned gmi_rst_n_pi4_pins[] = { + TEGRA_PIN_GMI_RST_N_PI4, +}; + +static const unsigned gmi_iordy_pi5_pins[] = { + TEGRA_PIN_GMI_IORDY_PI5, +}; + +static const unsigned gmi_cs7_n_pi6_pins[] = { + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned gmi_wait_pi7_pins[] = { + TEGRA_PIN_GMI_WAIT_PI7, +}; + +static const unsigned gmi_cs0_n_pj0_pins[] = { + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned lcd_de_pj1_pins[] = { + TEGRA_PIN_LCD_DE_PJ1, +}; + +static const unsigned gmi_cs1_n_pj2_pins[] = { + TEGRA_PIN_GMI_CS1_N_PJ2, +}; + +static const unsigned lcd_hsync_pj3_pins[] = { + TEGRA_PIN_LCD_HSYNC_PJ3, +}; + +static const unsigned lcd_vsync_pj4_pins[] = { + TEGRA_PIN_LCD_VSYNC_PJ4, +}; + +static const unsigned uart2_cts_n_pj5_pins[] = { + TEGRA_PIN_UART2_CTS_N_PJ5, +}; + +static const unsigned uart2_rts_n_pj6_pins[] = { + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned gmi_a16_pj7_pins[] = { + TEGRA_PIN_GMI_A16_PJ7, +}; + +static const unsigned gmi_adv_n_pk0_pins[] = { + TEGRA_PIN_GMI_ADV_N_PK0, +}; + +static const unsigned gmi_clk_pk1_pins[] = { + TEGRA_PIN_GMI_CLK_PK1, +}; + +static const unsigned gmi_cs4_n_pk2_pins[] = { + TEGRA_PIN_GMI_CS4_N_PK2, +}; + +static const unsigned gmi_cs2_n_pk3_pins[] = { + TEGRA_PIN_GMI_CS2_N_PK3, +}; + +static const unsigned gmi_cs3_n_pk4_pins[] = { + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned spdif_out_pk5_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, +}; + +static const unsigned spdif_in_pk6_pins[] = { + TEGRA_PIN_SPDIF_IN_PK6, +}; + +static const unsigned gmi_a19_pk7_pins[] = { + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned vi_d2_pl0_pins[] = { + TEGRA_PIN_VI_D2_PL0, +}; + +static const unsigned vi_d3_pl1_pins[] = { + TEGRA_PIN_VI_D3_PL1, +}; + +static const unsigned vi_d4_pl2_pins[] = { + TEGRA_PIN_VI_D4_PL2, +}; + +static const unsigned vi_d5_pl3_pins[] = { + TEGRA_PIN_VI_D5_PL3, +}; + +static const unsigned vi_d6_pl4_pins[] = { + TEGRA_PIN_VI_D6_PL4, +}; + +static const unsigned vi_d7_pl5_pins[] = { + TEGRA_PIN_VI_D7_PL5, +}; + +static const unsigned vi_d8_pl6_pins[] = { + TEGRA_PIN_VI_D8_PL6, +}; + +static const unsigned vi_d9_pl7_pins[] = { + TEGRA_PIN_VI_D9_PL7, +}; + +static const unsigned lcd_d16_pm0_pins[] = { + TEGRA_PIN_LCD_D16_PM0, +}; + +static const unsigned lcd_d17_pm1_pins[] = { + TEGRA_PIN_LCD_D17_PM1, +}; + +static const unsigned lcd_d18_pm2_pins[] = { + TEGRA_PIN_LCD_D18_PM2, +}; + +static const unsigned lcd_d19_pm3_pins[] = { + TEGRA_PIN_LCD_D19_PM3, +}; + +static const unsigned lcd_d20_pm4_pins[] = { + TEGRA_PIN_LCD_D20_PM4, +}; + +static const unsigned lcd_d21_pm5_pins[] = { + TEGRA_PIN_LCD_D21_PM5, +}; + +static const unsigned lcd_d22_pm6_pins[] = { + TEGRA_PIN_LCD_D22_PM6, +}; + +static const unsigned lcd_d23_pm7_pins[] = { + TEGRA_PIN_LCD_D23_PM7, +}; + +static const unsigned dap1_fs_pn0_pins[] = { + TEGRA_PIN_DAP1_FS_PN0, +}; + +static const unsigned dap1_din_pn1_pins[] = { + TEGRA_PIN_DAP1_DIN_PN1, +}; + +static const unsigned dap1_dout_pn2_pins[] = { + TEGRA_PIN_DAP1_DOUT_PN2, +}; + +static const unsigned dap1_sclk_pn3_pins[] = { + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned lcd_cs0_n_pn4_pins[] = { + TEGRA_PIN_LCD_CS0_N_PN4, +}; + +static const unsigned lcd_sdout_pn5_pins[] = { + TEGRA_PIN_LCD_SDOUT_PN5, +}; + +static const unsigned lcd_dc0_pn6_pins[] = { + TEGRA_PIN_LCD_DC0_PN6, +}; + +static const unsigned hdmi_int_pn7_pins[] = { + TEGRA_PIN_HDMI_INT_PN7, +}; + +static const unsigned ulpi_data7_po0_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, +}; + +static const unsigned ulpi_data0_po1_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, +}; + +static const unsigned ulpi_data1_po2_pins[] = { + TEGRA_PIN_ULPI_DATA1_PO2, +}; + +static const unsigned ulpi_data2_po3_pins[] = { + TEGRA_PIN_ULPI_DATA2_PO3, +}; + +static const unsigned ulpi_data3_po4_pins[] = { + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned ulpi_data4_po5_pins[] = { + TEGRA_PIN_ULPI_DATA4_PO5, +}; + +static const unsigned ulpi_data5_po6_pins[] = { + TEGRA_PIN_ULPI_DATA5_PO6, +}; + +static const unsigned ulpi_data6_po7_pins[] = { + TEGRA_PIN_ULPI_DATA6_PO7, +}; + +static const unsigned dap3_fs_pp0_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, +}; + +static const unsigned dap3_din_pp1_pins[] = { + TEGRA_PIN_DAP3_DIN_PP1, +}; + +static const unsigned dap3_dout_pp2_pins[] = { + TEGRA_PIN_DAP3_DOUT_PP2, +}; + +static const unsigned dap3_sclk_pp3_pins[] = { + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned dap4_fs_pp4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, +}; + +static const unsigned dap4_din_pp5_pins[] = { + TEGRA_PIN_DAP4_DIN_PP5, +}; + +static const unsigned dap4_dout_pp6_pins[] = { + TEGRA_PIN_DAP4_DOUT_PP6, +}; + +static const unsigned dap4_sclk_pp7_pins[] = { + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned kb_col0_pq0_pins[] = { + TEGRA_PIN_KB_COL0_PQ0, +}; + +static const unsigned kb_col1_pq1_pins[] = { + TEGRA_PIN_KB_COL1_PQ1, +}; + +static const unsigned kb_col2_pq2_pins[] = { + TEGRA_PIN_KB_COL2_PQ2, +}; + +static const unsigned kb_col3_pq3_pins[] = { + TEGRA_PIN_KB_COL3_PQ3, +}; + +static const unsigned kb_col4_pq4_pins[] = { + TEGRA_PIN_KB_COL4_PQ4, +}; + +static const unsigned kb_col5_pq5_pins[] = { + TEGRA_PIN_KB_COL5_PQ5, +}; + +static const unsigned kb_col6_pq6_pins[] = { + TEGRA_PIN_KB_COL6_PQ6, +}; + +static const unsigned kb_col7_pq7_pins[] = { + TEGRA_PIN_KB_COL7_PQ7, +}; + +static const unsigned kb_row0_pr0_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, +}; + +static const unsigned kb_row1_pr1_pins[] = { + TEGRA_PIN_KB_ROW1_PR1, +}; + +static const unsigned kb_row2_pr2_pins[] = { + TEGRA_PIN_KB_ROW2_PR2, +}; + +static const unsigned kb_row3_pr3_pins[] = { + TEGRA_PIN_KB_ROW3_PR3, +}; + +static const unsigned kb_row4_pr4_pins[] = { + TEGRA_PIN_KB_ROW4_PR4, +}; + +static const unsigned kb_row5_pr5_pins[] = { + TEGRA_PIN_KB_ROW5_PR5, +}; + +static const unsigned kb_row6_pr6_pins[] = { + TEGRA_PIN_KB_ROW6_PR6, +}; + +static const unsigned kb_row7_pr7_pins[] = { + TEGRA_PIN_KB_ROW7_PR7, +}; + +static const unsigned kb_row8_ps0_pins[] = { + TEGRA_PIN_KB_ROW8_PS0, +}; + +static const unsigned kb_row9_ps1_pins[] = { + TEGRA_PIN_KB_ROW9_PS1, +}; + +static const unsigned kb_row10_ps2_pins[] = { + TEGRA_PIN_KB_ROW10_PS2, +}; + +static const unsigned kb_row11_ps3_pins[] = { + TEGRA_PIN_KB_ROW11_PS3, +}; + +static const unsigned kb_row12_ps4_pins[] = { + TEGRA_PIN_KB_ROW12_PS4, +}; + +static const unsigned kb_row13_ps5_pins[] = { + TEGRA_PIN_KB_ROW13_PS5, +}; + +static const unsigned kb_row14_ps6_pins[] = { + TEGRA_PIN_KB_ROW14_PS6, +}; + +static const unsigned kb_row15_ps7_pins[] = { + TEGRA_PIN_KB_ROW15_PS7, +}; + +static const unsigned vi_pclk_pt0_pins[] = { + TEGRA_PIN_VI_PCLK_PT0, +}; + +static const unsigned vi_mclk_pt1_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned vi_d10_pt2_pins[] = { + TEGRA_PIN_VI_D10_PT2, +}; + +static const unsigned vi_d11_pt3_pins[] = { + TEGRA_PIN_VI_D11_PT3, +}; + +static const unsigned vi_d0_pt4_pins[] = { + TEGRA_PIN_VI_D0_PT4, +}; + +static const unsigned gen2_i2c_scl_pt5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, +}; + +static const unsigned gen2_i2c_sda_pt6_pins[] = { + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned sdmmc4_cmd_pt7_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned pu0_pins[] = { + TEGRA_PIN_PU0, +}; + +static const unsigned pu1_pins[] = { + TEGRA_PIN_PU1, +}; + +static const unsigned pu2_pins[] = { + TEGRA_PIN_PU2, +}; + +static const unsigned pu3_pins[] = { + TEGRA_PIN_PU3, +}; + +static const unsigned pu4_pins[] = { + TEGRA_PIN_PU4, +}; + +static const unsigned pu5_pins[] = { + TEGRA_PIN_PU5, +}; + +static const unsigned pu6_pins[] = { + TEGRA_PIN_PU6, +}; + +static const unsigned jtag_rtck_pu7_pins[] = { + TEGRA_PIN_JTAG_RTCK_PU7, +}; + +static const unsigned pv0_pins[] = { + TEGRA_PIN_PV0, +}; + +static const unsigned pv1_pins[] = { + TEGRA_PIN_PV1, +}; + +static const unsigned pv2_pins[] = { + TEGRA_PIN_PV2, +}; + +static const unsigned pv3_pins[] = { + TEGRA_PIN_PV3, +}; + +static const unsigned ddc_scl_pv4_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, +}; + +static const unsigned ddc_sda_pv5_pins[] = { + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned crt_hsync_pv6_pins[] = { + TEGRA_PIN_CRT_HSYNC_PV6, +}; + +static const unsigned crt_vsync_pv7_pins[] = { + TEGRA_PIN_CRT_VSYNC_PV7, +}; + +static const unsigned lcd_cs1_n_pw0_pins[] = { + TEGRA_PIN_LCD_CS1_N_PW0, +}; + +static const unsigned lcd_m1_pw1_pins[] = { + TEGRA_PIN_LCD_M1_PW1, +}; + +static const unsigned spi2_cs1_n_pw2_pins[] = { + TEGRA_PIN_SPI2_CS1_N_PW2, +}; + +static const unsigned spi2_cs2_n_pw3_pins[] = { + TEGRA_PIN_SPI2_CS2_N_PW3, +}; + +static const unsigned clk1_out_pw4_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, +}; + +static const unsigned clk2_out_pw5_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, +}; + +static const unsigned uart3_txd_pw6_pins[] = { + TEGRA_PIN_UART3_TXD_PW6, +}; + +static const unsigned uart3_rxd_pw7_pins[] = { + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned spi2_mosi_px0_pins[] = { + TEGRA_PIN_SPI2_MOSI_PX0, +}; + +static const unsigned spi2_miso_px1_pins[] = { + TEGRA_PIN_SPI2_MISO_PX1, +}; + +static const unsigned spi2_sck_px2_pins[] = { + TEGRA_PIN_SPI2_SCK_PX2, +}; + +static const unsigned spi2_cs0_n_px3_pins[] = { + TEGRA_PIN_SPI2_CS0_N_PX3, +}; + +static const unsigned spi1_mosi_px4_pins[] = { + TEGRA_PIN_SPI1_MOSI_PX4, +}; + +static const unsigned spi1_sck_px5_pins[] = { + TEGRA_PIN_SPI1_SCK_PX5, +}; + +static const unsigned spi1_cs0_n_px6_pins[] = { + TEGRA_PIN_SPI1_CS0_N_PX6, +}; + +static const unsigned spi1_miso_px7_pins[] = { + TEGRA_PIN_SPI1_MISO_PX7, +}; + +static const unsigned ulpi_clk_py0_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, +}; + +static const unsigned ulpi_dir_py1_pins[] = { + TEGRA_PIN_ULPI_DIR_PY1, +}; + +static const unsigned ulpi_nxt_py2_pins[] = { + TEGRA_PIN_ULPI_NXT_PY2, +}; + +static const unsigned ulpi_stp_py3_pins[] = { + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned sdmmc1_dat3_py4_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, +}; + +static const unsigned sdmmc1_dat2_py5_pins[] = { + TEGRA_PIN_SDMMC1_DAT2_PY5, +}; + +static const unsigned sdmmc1_dat1_py6_pins[] = { + TEGRA_PIN_SDMMC1_DAT1_PY6, +}; + +static const unsigned sdmmc1_dat0_py7_pins[] = { + TEGRA_PIN_SDMMC1_DAT0_PY7, +}; + +static const unsigned sdmmc1_clk_pz0_pins[] = { + TEGRA_PIN_SDMMC1_CLK_PZ0, +}; + +static const unsigned sdmmc1_cmd_pz1_pins[] = { + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned lcd_sdin_pz2_pins[] = { + TEGRA_PIN_LCD_SDIN_PZ2, +}; + +static const unsigned lcd_wr_n_pz3_pins[] = { + TEGRA_PIN_LCD_WR_N_PZ3, +}; + +static const unsigned lcd_sck_pz4_pins[] = { + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned sys_clk_req_pz5_pins[] = { + TEGRA_PIN_SYS_CLK_REQ_PZ5, +}; + +static const unsigned pwr_i2c_scl_pz6_pins[] = { + TEGRA_PIN_PWR_I2C_SCL_PZ6, +}; + +static const unsigned pwr_i2c_sda_pz7_pins[] = { + TEGRA_PIN_PWR_I2C_SDA_PZ7, +}; + +static const unsigned sdmmc4_dat0_paa0_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, +}; + +static const unsigned sdmmc4_dat1_paa1_pins[] = { + TEGRA_PIN_SDMMC4_DAT1_PAA1, +}; + +static const unsigned sdmmc4_dat2_paa2_pins[] = { + TEGRA_PIN_SDMMC4_DAT2_PAA2, +}; + +static const unsigned sdmmc4_dat3_paa3_pins[] = { + TEGRA_PIN_SDMMC4_DAT3_PAA3, +}; + +static const unsigned sdmmc4_dat4_paa4_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, +}; + +static const unsigned sdmmc4_dat5_paa5_pins[] = { + TEGRA_PIN_SDMMC4_DAT5_PAA5, +}; + +static const unsigned sdmmc4_dat6_paa6_pins[] = { + TEGRA_PIN_SDMMC4_DAT6_PAA6, +}; + +static const unsigned sdmmc4_dat7_paa7_pins[] = { + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned pbb0_pins[] = { + TEGRA_PIN_PBB0, +}; + +static const unsigned cam_i2c_scl_pbb1_pins[] = { + TEGRA_PIN_CAM_I2C_SCL_PBB1, +}; + +static const unsigned cam_i2c_sda_pbb2_pins[] = { + TEGRA_PIN_CAM_I2C_SDA_PBB2, +}; + +static const unsigned pbb3_pins[] = { + TEGRA_PIN_PBB3, +}; + +static const unsigned pbb4_pins[] = { + TEGRA_PIN_PBB4, +}; + +static const unsigned pbb5_pins[] = { + TEGRA_PIN_PBB5, +}; + +static const unsigned pbb6_pins[] = { + TEGRA_PIN_PBB6, +}; + +static const unsigned pbb7_pins[] = { + TEGRA_PIN_PBB7, +}; + +static const unsigned cam_mclk_pcc0_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned pcc1_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned pcc2_pins[] = { + TEGRA_PIN_PCC2, +}; + +static const unsigned sdmmc4_rst_n_pcc3_pins[] = { + TEGRA_PIN_SDMMC4_RST_N_PCC3, +}; + +static const unsigned sdmmc4_clk_pcc4_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned clk2_req_pcc5_pins[] = { + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned pex_l2_rst_n_pcc6_pins[] = { + TEGRA_PIN_PEX_L2_RST_N_PCC6, +}; + +static const unsigned pex_l2_clkreq_n_pcc7_pins[] = { + TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, +}; + +static const unsigned pex_l0_prsnt_n_pdd0_pins[] = { + TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, +}; + +static const unsigned pex_l0_rst_n_pdd1_pins[] = { + TEGRA_PIN_PEX_L0_RST_N_PDD1, +}; + +static const unsigned pex_l0_clkreq_n_pdd2_pins[] = { + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, +}; + +static const unsigned pex_wake_n_pdd3_pins[] = { + TEGRA_PIN_PEX_WAKE_N_PDD3, +}; + +static const unsigned pex_l1_prsnt_n_pdd4_pins[] = { + TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, +}; + +static const unsigned pex_l1_rst_n_pdd5_pins[] = { + TEGRA_PIN_PEX_L1_RST_N_PDD5, +}; + +static const unsigned pex_l1_clkreq_n_pdd6_pins[] = { + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, +}; + +static const unsigned pex_l2_prsnt_n_pdd7_pins[] = { + TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, +}; + +static const unsigned clk3_out_pee0_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, +}; + +static const unsigned clk3_req_pee1_pins[] = { + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned clk1_req_pee2_pins[] = { + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned hdmi_cec_pee3_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned clk_32k_in_pins[] = { + TEGRA_PIN_CLK_32K_IN, +}; + +static const unsigned core_pwr_req_pins[] = { + TEGRA_PIN_CORE_PWR_REQ, +}; + +static const unsigned cpu_pwr_req_pins[] = { + TEGRA_PIN_CPU_PWR_REQ, +}; + +static const unsigned owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned pwr_int_n_pins[] = { + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_ao1_pins[] = { + TEGRA_PIN_KB_ROW0_PR0, + TEGRA_PIN_KB_ROW1_PR1, + TEGRA_PIN_KB_ROW2_PR2, + TEGRA_PIN_KB_ROW3_PR3, + TEGRA_PIN_KB_ROW4_PR4, + TEGRA_PIN_KB_ROW5_PR5, + TEGRA_PIN_KB_ROW6_PR6, + TEGRA_PIN_KB_ROW7_PR7, + TEGRA_PIN_PWR_I2C_SCL_PZ6, + TEGRA_PIN_PWR_I2C_SDA_PZ7, + TEGRA_PIN_SYS_RESET_N, +}; + +static const unsigned drive_ao2_pins[] = { + TEGRA_PIN_CLK_32K_OUT_PA0, + TEGRA_PIN_KB_COL0_PQ0, + TEGRA_PIN_KB_COL1_PQ1, + TEGRA_PIN_KB_COL2_PQ2, + TEGRA_PIN_KB_COL3_PQ3, + TEGRA_PIN_KB_COL4_PQ4, + TEGRA_PIN_KB_COL5_PQ5, + TEGRA_PIN_KB_COL6_PQ6, + TEGRA_PIN_KB_COL7_PQ7, + TEGRA_PIN_KB_ROW8_PS0, + TEGRA_PIN_KB_ROW9_PS1, + TEGRA_PIN_KB_ROW10_PS2, + TEGRA_PIN_KB_ROW11_PS3, + TEGRA_PIN_KB_ROW12_PS4, + TEGRA_PIN_KB_ROW13_PS5, + TEGRA_PIN_KB_ROW14_PS6, + TEGRA_PIN_KB_ROW15_PS7, + TEGRA_PIN_SYS_CLK_REQ_PZ5, + TEGRA_PIN_CLK_32K_IN, + TEGRA_PIN_CORE_PWR_REQ, + TEGRA_PIN_CPU_PWR_REQ, + TEGRA_PIN_PWR_INT_N, +}; + +static const unsigned drive_at1_pins[] = { + TEGRA_PIN_GMI_AD8_PH0, + TEGRA_PIN_GMI_AD9_PH1, + TEGRA_PIN_GMI_AD10_PH2, + TEGRA_PIN_GMI_AD11_PH3, + TEGRA_PIN_GMI_AD12_PH4, + TEGRA_PIN_GMI_AD13_PH5, + TEGRA_PIN_GMI_AD14_PH6, + TEGRA_PIN_GMI_AD15_PH7, + TEGRA_PIN_GMI_IORDY_PI5, + TEGRA_PIN_GMI_CS7_N_PI6, +}; + +static const unsigned drive_at2_pins[] = { + TEGRA_PIN_GMI_AD0_PG0, + TEGRA_PIN_GMI_AD1_PG1, + TEGRA_PIN_GMI_AD2_PG2, + TEGRA_PIN_GMI_AD3_PG3, + TEGRA_PIN_GMI_AD4_PG4, + TEGRA_PIN_GMI_AD5_PG5, + TEGRA_PIN_GMI_AD6_PG6, + TEGRA_PIN_GMI_AD7_PG7, + TEGRA_PIN_GMI_WR_N_PI0, + TEGRA_PIN_GMI_OE_N_PI1, + TEGRA_PIN_GMI_DQS_PI2, + TEGRA_PIN_GMI_CS6_N_PI3, + TEGRA_PIN_GMI_RST_N_PI4, + TEGRA_PIN_GMI_WAIT_PI7, + TEGRA_PIN_GMI_ADV_N_PK0, + TEGRA_PIN_GMI_CLK_PK1, + TEGRA_PIN_GMI_CS4_N_PK2, + TEGRA_PIN_GMI_CS2_N_PK3, + TEGRA_PIN_GMI_CS3_N_PK4, +}; + +static const unsigned drive_at3_pins[] = { + TEGRA_PIN_GMI_WP_N_PC7, + TEGRA_PIN_GMI_CS0_N_PJ0, +}; + +static const unsigned drive_at4_pins[] = { + TEGRA_PIN_GMI_A17_PB0, + TEGRA_PIN_GMI_A18_PB1, + TEGRA_PIN_GMI_CS1_N_PJ2, + TEGRA_PIN_GMI_A16_PJ7, + TEGRA_PIN_GMI_A19_PK7, +}; + +static const unsigned drive_at5_pins[] = { + TEGRA_PIN_GEN2_I2C_SCL_PT5, + TEGRA_PIN_GEN2_I2C_SDA_PT6, +}; + +static const unsigned drive_cdev1_pins[] = { + TEGRA_PIN_CLK1_OUT_PW4, + TEGRA_PIN_CLK1_REQ_PEE2, +}; + +static const unsigned drive_cdev2_pins[] = { + TEGRA_PIN_CLK2_OUT_PW5, + TEGRA_PIN_CLK2_REQ_PCC5, +}; + +static const unsigned drive_cec_pins[] = { + TEGRA_PIN_HDMI_CEC_PEE3, +}; + +static const unsigned drive_crt_pins[] = { + TEGRA_PIN_CRT_HSYNC_PV6, + TEGRA_PIN_CRT_VSYNC_PV7, +}; + +static const unsigned drive_csus_pins[] = { + TEGRA_PIN_VI_MCLK_PT1, +}; + +static const unsigned drive_dap1_pins[] = { + TEGRA_PIN_SPDIF_OUT_PK5, + TEGRA_PIN_SPDIF_IN_PK6, + TEGRA_PIN_DAP1_FS_PN0, + TEGRA_PIN_DAP1_DIN_PN1, + TEGRA_PIN_DAP1_DOUT_PN2, + TEGRA_PIN_DAP1_SCLK_PN3, +}; + +static const unsigned drive_dap2_pins[] = { + TEGRA_PIN_DAP2_FS_PA2, + TEGRA_PIN_DAP2_SCLK_PA3, + TEGRA_PIN_DAP2_DIN_PA4, + TEGRA_PIN_DAP2_DOUT_PA5, +}; + +static const unsigned drive_dap3_pins[] = { + TEGRA_PIN_DAP3_FS_PP0, + TEGRA_PIN_DAP3_DIN_PP1, + TEGRA_PIN_DAP3_DOUT_PP2, + TEGRA_PIN_DAP3_SCLK_PP3, +}; + +static const unsigned drive_dap4_pins[] = { + TEGRA_PIN_DAP4_FS_PP4, + TEGRA_PIN_DAP4_DIN_PP5, + TEGRA_PIN_DAP4_DOUT_PP6, + TEGRA_PIN_DAP4_SCLK_PP7, +}; + +static const unsigned drive_dbg_pins[] = { + TEGRA_PIN_GEN1_I2C_SCL_PC4, + TEGRA_PIN_GEN1_I2C_SDA_PC5, + TEGRA_PIN_PU0, + TEGRA_PIN_PU1, + TEGRA_PIN_PU2, + TEGRA_PIN_PU3, + TEGRA_PIN_PU4, + TEGRA_PIN_PU5, + TEGRA_PIN_PU6, + TEGRA_PIN_JTAG_RTCK_PU7, + TEGRA_PIN_JTAG_TCK, + TEGRA_PIN_JTAG_TDI, + TEGRA_PIN_JTAG_TDO, + TEGRA_PIN_JTAG_TMS, + TEGRA_PIN_JTAG_TRST_N, + TEGRA_PIN_TEST_MODE_EN, +}; + +static const unsigned drive_ddc_pins[] = { + TEGRA_PIN_DDC_SCL_PV4, + TEGRA_PIN_DDC_SDA_PV5, +}; + +static const unsigned drive_dev3_pins[] = { + TEGRA_PIN_CLK3_OUT_PEE0, + TEGRA_PIN_CLK3_REQ_PEE1, +}; + +static const unsigned drive_gma_pins[] = { + TEGRA_PIN_SDMMC4_DAT0_PAA0, + TEGRA_PIN_SDMMC4_DAT1_PAA1, + TEGRA_PIN_SDMMC4_DAT2_PAA2, + TEGRA_PIN_SDMMC4_DAT3_PAA3, + TEGRA_PIN_SDMMC4_RST_N_PCC3, +}; + +static const unsigned drive_gmb_pins[] = { + TEGRA_PIN_SDMMC4_DAT4_PAA4, + TEGRA_PIN_SDMMC4_DAT5_PAA5, + TEGRA_PIN_SDMMC4_DAT6_PAA6, + TEGRA_PIN_SDMMC4_DAT7_PAA7, +}; + +static const unsigned drive_gmc_pins[] = { + TEGRA_PIN_SDMMC4_CLK_PCC4, +}; + +static const unsigned drive_gmd_pins[] = { + TEGRA_PIN_SDMMC4_CMD_PT7, +}; + +static const unsigned drive_gme_pins[] = { + TEGRA_PIN_PBB0, + TEGRA_PIN_CAM_I2C_SCL_PBB1, + TEGRA_PIN_CAM_I2C_SDA_PBB2, + TEGRA_PIN_PBB3, + TEGRA_PIN_PCC2, +}; + +static const unsigned drive_gmf_pins[] = { + TEGRA_PIN_PBB4, + TEGRA_PIN_PBB5, + TEGRA_PIN_PBB6, + TEGRA_PIN_PBB7, +}; + +static const unsigned drive_gmg_pins[] = { + TEGRA_PIN_CAM_MCLK_PCC0, +}; + +static const unsigned drive_gmh_pins[] = { + TEGRA_PIN_PCC1, +}; + +static const unsigned drive_gpv_pins[] = { + TEGRA_PIN_PEX_L2_RST_N_PCC6, + TEGRA_PIN_PEX_L2_CLKREQ_N_PCC7, + TEGRA_PIN_PEX_L0_PRSNT_N_PDD0, + TEGRA_PIN_PEX_L0_RST_N_PDD1, + TEGRA_PIN_PEX_L0_CLKREQ_N_PDD2, + TEGRA_PIN_PEX_WAKE_N_PDD3, + TEGRA_PIN_PEX_L1_PRSNT_N_PDD4, + TEGRA_PIN_PEX_L1_RST_N_PDD5, + TEGRA_PIN_PEX_L1_CLKREQ_N_PDD6, + TEGRA_PIN_PEX_L2_PRSNT_N_PDD7, +}; + +static const unsigned drive_lcd1_pins[] = { + TEGRA_PIN_LCD_PWR1_PC1, + TEGRA_PIN_LCD_PWR2_PC6, + TEGRA_PIN_LCD_CS0_N_PN4, + TEGRA_PIN_LCD_SDOUT_PN5, + TEGRA_PIN_LCD_DC0_PN6, + TEGRA_PIN_LCD_SDIN_PZ2, + TEGRA_PIN_LCD_WR_N_PZ3, + TEGRA_PIN_LCD_SCK_PZ4, +}; + +static const unsigned drive_lcd2_pins[] = { + TEGRA_PIN_LCD_PWR0_PB2, + TEGRA_PIN_LCD_PCLK_PB3, + TEGRA_PIN_LCD_DC1_PD2, + TEGRA_PIN_LCD_D0_PE0, + TEGRA_PIN_LCD_D1_PE1, + TEGRA_PIN_LCD_D2_PE2, + TEGRA_PIN_LCD_D3_PE3, + TEGRA_PIN_LCD_D4_PE4, + TEGRA_PIN_LCD_D5_PE5, + TEGRA_PIN_LCD_D6_PE6, + TEGRA_PIN_LCD_D7_PE7, + TEGRA_PIN_LCD_D8_PF0, + TEGRA_PIN_LCD_D9_PF1, + TEGRA_PIN_LCD_D10_PF2, + TEGRA_PIN_LCD_D11_PF3, + TEGRA_PIN_LCD_D12_PF4, + TEGRA_PIN_LCD_D13_PF5, + TEGRA_PIN_LCD_D14_PF6, + TEGRA_PIN_LCD_D15_PF7, + TEGRA_PIN_LCD_DE_PJ1, + TEGRA_PIN_LCD_HSYNC_PJ3, + TEGRA_PIN_LCD_VSYNC_PJ4, + TEGRA_PIN_LCD_D16_PM0, + TEGRA_PIN_LCD_D17_PM1, + TEGRA_PIN_LCD_D18_PM2, + TEGRA_PIN_LCD_D19_PM3, + TEGRA_PIN_LCD_D20_PM4, + TEGRA_PIN_LCD_D21_PM5, + TEGRA_PIN_LCD_D22_PM6, + TEGRA_PIN_LCD_D23_PM7, + TEGRA_PIN_HDMI_INT_PN7, + TEGRA_PIN_LCD_CS1_N_PW0, + TEGRA_PIN_LCD_M1_PW1, +}; + +static const unsigned drive_owr_pins[] = { + TEGRA_PIN_OWR, +}; + +static const unsigned drive_sdio1_pins[] = { + TEGRA_PIN_SDMMC1_DAT3_PY4, + TEGRA_PIN_SDMMC1_DAT2_PY5, + TEGRA_PIN_SDMMC1_DAT1_PY6, + TEGRA_PIN_SDMMC1_DAT0_PY7, + TEGRA_PIN_SDMMC1_CLK_PZ0, + TEGRA_PIN_SDMMC1_CMD_PZ1, +}; + +static const unsigned drive_sdio2_pins[] = { + TEGRA_PIN_SDMMC3_DAT5_PD0, + TEGRA_PIN_SDMMC3_DAT4_PD1, + TEGRA_PIN_SDMMC3_DAT6_PD3, + TEGRA_PIN_SDMMC3_DAT7_PD4, +}; + +static const unsigned drive_sdio3_pins[] = { + TEGRA_PIN_SDMMC3_CLK_PA6, + TEGRA_PIN_SDMMC3_CMD_PA7, + TEGRA_PIN_SDMMC3_DAT3_PB4, + TEGRA_PIN_SDMMC3_DAT2_PB5, + TEGRA_PIN_SDMMC3_DAT1_PB6, + TEGRA_PIN_SDMMC3_DAT0_PB7, +}; + +static const unsigned drive_spi_pins[] = { + TEGRA_PIN_SPI2_CS1_N_PW2, + TEGRA_PIN_SPI2_CS2_N_PW3, + TEGRA_PIN_SPI2_MOSI_PX0, + TEGRA_PIN_SPI2_MISO_PX1, + TEGRA_PIN_SPI2_SCK_PX2, + TEGRA_PIN_SPI2_CS0_N_PX3, + TEGRA_PIN_SPI1_MOSI_PX4, + TEGRA_PIN_SPI1_SCK_PX5, + TEGRA_PIN_SPI1_CS0_N_PX6, + TEGRA_PIN_SPI1_MISO_PX7, +}; + +static const unsigned drive_uaa_pins[] = { + TEGRA_PIN_ULPI_DATA0_PO1, + TEGRA_PIN_ULPI_DATA1_PO2, + TEGRA_PIN_ULPI_DATA2_PO3, + TEGRA_PIN_ULPI_DATA3_PO4, +}; + +static const unsigned drive_uab_pins[] = { + TEGRA_PIN_ULPI_DATA7_PO0, + TEGRA_PIN_ULPI_DATA4_PO5, + TEGRA_PIN_ULPI_DATA5_PO6, + TEGRA_PIN_ULPI_DATA6_PO7, + TEGRA_PIN_PV0, + TEGRA_PIN_PV1, + TEGRA_PIN_PV2, + TEGRA_PIN_PV3, +}; + +static const unsigned drive_uart2_pins[] = { + TEGRA_PIN_UART2_TXD_PC2, + TEGRA_PIN_UART2_RXD_PC3, + TEGRA_PIN_UART2_CTS_N_PJ5, + TEGRA_PIN_UART2_RTS_N_PJ6, +}; + +static const unsigned drive_uart3_pins[] = { + TEGRA_PIN_UART3_CTS_N_PA1, + TEGRA_PIN_UART3_RTS_N_PC0, + TEGRA_PIN_UART3_TXD_PW6, + TEGRA_PIN_UART3_RXD_PW7, +}; + +static const unsigned drive_uda_pins[] = { + TEGRA_PIN_ULPI_CLK_PY0, + TEGRA_PIN_ULPI_DIR_PY1, + TEGRA_PIN_ULPI_NXT_PY2, + TEGRA_PIN_ULPI_STP_PY3, +}; + +static const unsigned drive_vi1_pins[] = { + TEGRA_PIN_VI_D1_PD5, + TEGRA_PIN_VI_VSYNC_PD6, + TEGRA_PIN_VI_HSYNC_PD7, + TEGRA_PIN_VI_D2_PL0, + TEGRA_PIN_VI_D3_PL1, + TEGRA_PIN_VI_D4_PL2, + TEGRA_PIN_VI_D5_PL3, + TEGRA_PIN_VI_D6_PL4, + TEGRA_PIN_VI_D7_PL5, + TEGRA_PIN_VI_D8_PL6, + TEGRA_PIN_VI_D9_PL7, + TEGRA_PIN_VI_PCLK_PT0, + TEGRA_PIN_VI_D10_PT2, + TEGRA_PIN_VI_D11_PT3, + TEGRA_PIN_VI_D0_PT4, +}; + +enum tegra_mux { + TEGRA_MUX_BLINK, + TEGRA_MUX_CEC, + TEGRA_MUX_CLK_12M_OUT, + TEGRA_MUX_CLK_32K_IN, + TEGRA_MUX_CORE_PWR_REQ, + TEGRA_MUX_CPU_PWR_REQ, + TEGRA_MUX_CRT, + TEGRA_MUX_DAP, + TEGRA_MUX_DDR, + TEGRA_MUX_DEV3, + TEGRA_MUX_DISPLAYA, + TEGRA_MUX_DISPLAYB, + TEGRA_MUX_DTV, + TEGRA_MUX_EXTPERIPH1, + TEGRA_MUX_EXTPERIPH2, + TEGRA_MUX_EXTPERIPH3, + TEGRA_MUX_GMI, + TEGRA_MUX_GMI_ALT, + TEGRA_MUX_HDA, + TEGRA_MUX_HDCP, + TEGRA_MUX_HDMI, + TEGRA_MUX_HSI, + TEGRA_MUX_I2C1, + TEGRA_MUX_I2C2, + TEGRA_MUX_I2C3, + TEGRA_MUX_I2C4, + TEGRA_MUX_I2CPWR, + TEGRA_MUX_I2S0, + TEGRA_MUX_I2S1, + TEGRA_MUX_I2S2, + TEGRA_MUX_I2S3, + TEGRA_MUX_I2S4, + TEGRA_MUX_INVALID, + TEGRA_MUX_KBC, + TEGRA_MUX_MIO, + TEGRA_MUX_NAND, + TEGRA_MUX_NAND_ALT, + TEGRA_MUX_OWR, + TEGRA_MUX_PCIE, + TEGRA_MUX_PWM0, + TEGRA_MUX_PWM1, + TEGRA_MUX_PWM2, + TEGRA_MUX_PWM3, + TEGRA_MUX_PWR_INT_N, + TEGRA_MUX_RSVD1, + TEGRA_MUX_RSVD2, + TEGRA_MUX_RSVD3, + TEGRA_MUX_RSVD4, + TEGRA_MUX_RTCK, + TEGRA_MUX_SATA, + TEGRA_MUX_SDMMC1, + TEGRA_MUX_SDMMC2, + TEGRA_MUX_SDMMC3, + TEGRA_MUX_SDMMC4, + TEGRA_MUX_SPDIF, + TEGRA_MUX_SPI1, + TEGRA_MUX_SPI2, + TEGRA_MUX_SPI2_ALT, + TEGRA_MUX_SPI3, + TEGRA_MUX_SPI4, + TEGRA_MUX_SPI5, + TEGRA_MUX_SPI6, + TEGRA_MUX_SYSCLK, + TEGRA_MUX_TEST, + TEGRA_MUX_TRACE, + TEGRA_MUX_UARTA, + TEGRA_MUX_UARTB, + TEGRA_MUX_UARTC, + TEGRA_MUX_UARTD, + TEGRA_MUX_UARTE, + TEGRA_MUX_ULPI, + TEGRA_MUX_VGP1, + TEGRA_MUX_VGP2, + TEGRA_MUX_VGP3, + TEGRA_MUX_VGP4, + TEGRA_MUX_VGP5, + TEGRA_MUX_VGP6, + TEGRA_MUX_VI, + TEGRA_MUX_VI_ALT1, + TEGRA_MUX_VI_ALT2, + TEGRA_MUX_VI_ALT3, +}; + +#define FUNCTION(fname) \ + { \ + .name = #fname, \ + } + +static struct tegra_function tegra30_functions[] = { + FUNCTION(blink), + FUNCTION(cec), + FUNCTION(clk_12m_out), + FUNCTION(clk_32k_in), + FUNCTION(core_pwr_req), + FUNCTION(cpu_pwr_req), + FUNCTION(crt), + FUNCTION(dap), + FUNCTION(ddr), + FUNCTION(dev3), + FUNCTION(displaya), + FUNCTION(displayb), + FUNCTION(dtv), + FUNCTION(extperiph1), + FUNCTION(extperiph2), + FUNCTION(extperiph3), + FUNCTION(gmi), + FUNCTION(gmi_alt), + FUNCTION(hda), + FUNCTION(hdcp), + FUNCTION(hdmi), + FUNCTION(hsi), + FUNCTION(i2c1), + FUNCTION(i2c2), + FUNCTION(i2c3), + FUNCTION(i2c4), + FUNCTION(i2cpwr), + FUNCTION(i2s0), + FUNCTION(i2s1), + FUNCTION(i2s2), + FUNCTION(i2s3), + FUNCTION(i2s4), + FUNCTION(invalid), + FUNCTION(kbc), + FUNCTION(mio), + FUNCTION(nand), + FUNCTION(nand_alt), + FUNCTION(owr), + FUNCTION(pcie), + FUNCTION(pwm0), + FUNCTION(pwm1), + FUNCTION(pwm2), + FUNCTION(pwm3), + FUNCTION(pwr_int_n), + FUNCTION(rsvd1), + FUNCTION(rsvd2), + FUNCTION(rsvd3), + FUNCTION(rsvd4), + FUNCTION(rtck), + FUNCTION(sata), + FUNCTION(sdmmc1), + FUNCTION(sdmmc2), + FUNCTION(sdmmc3), + FUNCTION(sdmmc4), + FUNCTION(spdif), + FUNCTION(spi1), + FUNCTION(spi2), + FUNCTION(spi2_alt), + FUNCTION(spi3), + FUNCTION(spi4), + FUNCTION(spi5), + FUNCTION(spi6), + FUNCTION(sysclk), + FUNCTION(test), + FUNCTION(trace), + FUNCTION(uarta), + FUNCTION(uartb), + FUNCTION(uartc), + FUNCTION(uartd), + FUNCTION(uarte), + FUNCTION(ulpi), + FUNCTION(vgp1), + FUNCTION(vgp2), + FUNCTION(vgp3), + FUNCTION(vgp4), + FUNCTION(vgp5), + FUNCTION(vgp6), + FUNCTION(vi), + FUNCTION(vi_alt1), + FUNCTION(vi_alt2), + FUNCTION(vi_alt3), +}; + +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ + +#define DRV_PINGROUP_REG(r) ((r) - DRV_PINGROUP_REG_A) +#define PINGROUP_REG(r) ((r) - PINGROUP_REG_A) + +#define PINGROUP_BIT_Y(b) (b) +#define PINGROUP_BIT_N(b) (-1) + +#define PINGROUP(pg_name, f0, f1, f2, f3, r, od, ior) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .funcs = { \ + TEGRA_MUX_##f0, \ + TEGRA_MUX_##f1, \ + TEGRA_MUX_##f2, \ + TEGRA_MUX_##f3, \ + }, \ + .mux_reg = PINGROUP_REG(r), \ + .mux_bank = 1, \ + .mux_bit = 0, \ + .pupd_reg = PINGROUP_REG(r), \ + .pupd_bank = 1, \ + .pupd_bit = 2, \ + .tri_reg = PINGROUP_REG(r), \ + .tri_bank = 1, \ + .tri_bit = 4, \ + .einput_bit = 5, \ + .odrain_bit = PINGROUP_BIT_##od(6), \ + .lock_bit = 7, \ + .ioreset_bit = PINGROUP_BIT_##ior(8), \ + .rcv_sel_bit = -1, \ + .drv_reg = -1, \ + } + +#define DRV_PINGROUP(pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, \ + drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, \ + slwf_b, slwf_w) \ + { \ + .name = "drive_" #pg_name, \ + .pins = drive_##pg_name##_pins, \ + .npins = ARRAY_SIZE(drive_##pg_name##_pins), \ + .mux_reg = -1, \ + .pupd_reg = -1, \ + .tri_reg = -1, \ + .einput_bit = -1, \ + .odrain_bit = -1, \ + .lock_bit = -1, \ + .ioreset_bit = -1, \ + .rcv_sel_bit = -1, \ + .drv_reg = DRV_PINGROUP_REG(r), \ + .drv_bank = 0, \ + .hsm_bit = hsm_b, \ + .schmitt_bit = schmitt_b, \ + .lpmd_bit = lpmd_b, \ + .drvdn_bit = drvdn_b, \ + .drvdn_width = drvdn_w, \ + .drvup_bit = drvup_b, \ + .drvup_width = drvup_w, \ + .slwr_bit = slwr_b, \ + .slwr_width = slwr_w, \ + .slwf_bit = slwf_b, \ + .slwf_width = slwf_w, \ + .drvtype_bit = -1, \ + } + +static const struct tegra_pingroup tegra30_groups[] = { + /* pg_name, f0, f1, f2, f3, r, od, ior */ + PINGROUP(clk_32k_out_pa0, BLINK, RSVD2, RSVD3, RSVD4, 0x331c, N, N), + PINGROUP(uart3_cts_n_pa1, UARTC, RSVD2, GMI, RSVD4, 0x317c, N, N), + PINGROUP(dap2_fs_pa2, I2S1, HDA, RSVD3, GMI, 0x3358, N, N), + PINGROUP(dap2_sclk_pa3, I2S1, HDA, RSVD3, GMI, 0x3364, N, N), + PINGROUP(dap2_din_pa4, I2S1, HDA, RSVD3, GMI, 0x335c, N, N), + PINGROUP(dap2_dout_pa5, I2S1, HDA, RSVD3, GMI, 0x3360, N, N), + PINGROUP(sdmmc3_clk_pa6, UARTA, PWM2, SDMMC3, SPI3, 0x3390, N, N), + PINGROUP(sdmmc3_cmd_pa7, UARTA, PWM3, SDMMC3, SPI2, 0x3394, N, N), + PINGROUP(gmi_a17_pb0, UARTD, SPI4, GMI, DTV, 0x3234, N, N), + PINGROUP(gmi_a18_pb1, UARTD, SPI4, GMI, DTV, 0x3238, N, N), + PINGROUP(lcd_pwr0_pb2, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3090, N, N), + PINGROUP(lcd_pclk_pb3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3094, N, N), + PINGROUP(sdmmc3_dat3_pb4, RSVD1, PWM0, SDMMC3, SPI3, 0x33a4, N, N), + PINGROUP(sdmmc3_dat2_pb5, RSVD1, PWM1, SDMMC3, SPI3, 0x33a0, N, N), + PINGROUP(sdmmc3_dat1_pb6, RSVD1, RSVD2, SDMMC3, SPI3, 0x339c, N, N), + PINGROUP(sdmmc3_dat0_pb7, RSVD1, RSVD2, SDMMC3, SPI3, 0x3398, N, N), + PINGROUP(uart3_rts_n_pc0, UARTC, PWM0, GMI, RSVD4, 0x3180, N, N), + PINGROUP(lcd_pwr1_pc1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3070, N, N), + PINGROUP(uart2_txd_pc2, UARTB, SPDIF, UARTA, SPI4, 0x3168, N, N), + PINGROUP(uart2_rxd_pc3, UARTB, SPDIF, UARTA, SPI4, 0x3164, N, N), + PINGROUP(gen1_i2c_scl_pc4, I2C1, RSVD2, RSVD3, RSVD4, 0x31a4, Y, N), + PINGROUP(gen1_i2c_sda_pc5, I2C1, RSVD2, RSVD3, RSVD4, 0x31a0, Y, N), + PINGROUP(lcd_pwr2_pc6, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3074, N, N), + PINGROUP(gmi_wp_n_pc7, RSVD1, NAND, GMI, GMI_ALT, 0x31c0, N, N), + PINGROUP(sdmmc3_dat5_pd0, PWM0, SPI4, SDMMC3, SPI2, 0x33ac, N, N), + PINGROUP(sdmmc3_dat4_pd1, PWM1, SPI4, SDMMC3, SPI2, 0x33a8, N, N), + PINGROUP(lcd_dc1_pd2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x310c, N, N), + PINGROUP(sdmmc3_dat6_pd3, SPDIF, SPI4, SDMMC3, SPI2, 0x33b0, N, N), + PINGROUP(sdmmc3_dat7_pd4, SPDIF, SPI4, SDMMC3, SPI2, 0x33b4, N, N), + PINGROUP(vi_d1_pd5, DDR, SDMMC2, VI, RSVD4, 0x3128, N, Y), + PINGROUP(vi_vsync_pd6, DDR, RSVD2, VI, RSVD4, 0x315c, N, Y), + PINGROUP(vi_hsync_pd7, DDR, RSVD2, VI, RSVD4, 0x3160, N, Y), + PINGROUP(lcd_d0_pe0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a4, N, N), + PINGROUP(lcd_d1_pe1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a8, N, N), + PINGROUP(lcd_d2_pe2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ac, N, N), + PINGROUP(lcd_d3_pe3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b0, N, N), + PINGROUP(lcd_d4_pe4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b4, N, N), + PINGROUP(lcd_d5_pe5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30b8, N, N), + PINGROUP(lcd_d6_pe6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30bc, N, N), + PINGROUP(lcd_d7_pe7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c0, N, N), + PINGROUP(lcd_d8_pf0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c4, N, N), + PINGROUP(lcd_d9_pf1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30c8, N, N), + PINGROUP(lcd_d10_pf2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30cc, N, N), + PINGROUP(lcd_d11_pf3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d0, N, N), + PINGROUP(lcd_d12_pf4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d4, N, N), + PINGROUP(lcd_d13_pf5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30d8, N, N), + PINGROUP(lcd_d14_pf6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30dc, N, N), + PINGROUP(lcd_d15_pf7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e0, N, N), + PINGROUP(gmi_ad0_pg0, RSVD1, NAND, GMI, RSVD4, 0x31f0, N, N), + PINGROUP(gmi_ad1_pg1, RSVD1, NAND, GMI, RSVD4, 0x31f4, N, N), + PINGROUP(gmi_ad2_pg2, RSVD1, NAND, GMI, RSVD4, 0x31f8, N, N), + PINGROUP(gmi_ad3_pg3, RSVD1, NAND, GMI, RSVD4, 0x31fc, N, N), + PINGROUP(gmi_ad4_pg4, RSVD1, NAND, GMI, RSVD4, 0x3200, N, N), + PINGROUP(gmi_ad5_pg5, RSVD1, NAND, GMI, RSVD4, 0x3204, N, N), + PINGROUP(gmi_ad6_pg6, RSVD1, NAND, GMI, RSVD4, 0x3208, N, N), + PINGROUP(gmi_ad7_pg7, RSVD1, NAND, GMI, RSVD4, 0x320c, N, N), + PINGROUP(gmi_ad8_ph0, PWM0, NAND, GMI, RSVD4, 0x3210, N, N), + PINGROUP(gmi_ad9_ph1, PWM1, NAND, GMI, RSVD4, 0x3214, N, N), + PINGROUP(gmi_ad10_ph2, PWM2, NAND, GMI, RSVD4, 0x3218, N, N), + PINGROUP(gmi_ad11_ph3, PWM3, NAND, GMI, RSVD4, 0x321c, N, N), + PINGROUP(gmi_ad12_ph4, RSVD1, NAND, GMI, RSVD4, 0x3220, N, N), + PINGROUP(gmi_ad13_ph5, RSVD1, NAND, GMI, RSVD4, 0x3224, N, N), + PINGROUP(gmi_ad14_ph6, RSVD1, NAND, GMI, RSVD4, 0x3228, N, N), + PINGROUP(gmi_ad15_ph7, RSVD1, NAND, GMI, RSVD4, 0x322c, N, N), + PINGROUP(gmi_wr_n_pi0, RSVD1, NAND, GMI, RSVD4, 0x3240, N, N), + PINGROUP(gmi_oe_n_pi1, RSVD1, NAND, GMI, RSVD4, 0x3244, N, N), + PINGROUP(gmi_dqs_pi2, RSVD1, NAND, GMI, RSVD4, 0x3248, N, N), + PINGROUP(gmi_cs6_n_pi3, NAND, NAND_ALT, GMI, SATA, 0x31e8, N, N), + PINGROUP(gmi_rst_n_pi4, NAND, NAND_ALT, GMI, RSVD4, 0x324c, N, N), + PINGROUP(gmi_iordy_pi5, RSVD1, NAND, GMI, RSVD4, 0x31c4, N, N), + PINGROUP(gmi_cs7_n_pi6, NAND, NAND_ALT, GMI, GMI_ALT, 0x31ec, N, N), + PINGROUP(gmi_wait_pi7, RSVD1, NAND, GMI, RSVD4, 0x31c8, N, N), + PINGROUP(gmi_cs0_n_pj0, RSVD1, NAND, GMI, DTV, 0x31d4, N, N), + PINGROUP(lcd_de_pj1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3098, N, N), + PINGROUP(gmi_cs1_n_pj2, RSVD1, NAND, GMI, DTV, 0x31d8, N, N), + PINGROUP(lcd_hsync_pj3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x309c, N, N), + PINGROUP(lcd_vsync_pj4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30a0, N, N), + PINGROUP(uart2_cts_n_pj5, UARTA, UARTB, GMI, SPI4, 0x3170, N, N), + PINGROUP(uart2_rts_n_pj6, UARTA, UARTB, GMI, SPI4, 0x316c, N, N), + PINGROUP(gmi_a16_pj7, UARTD, SPI4, GMI, GMI_ALT, 0x3230, N, N), + PINGROUP(gmi_adv_n_pk0, RSVD1, NAND, GMI, RSVD4, 0x31cc, N, N), + PINGROUP(gmi_clk_pk1, RSVD1, NAND, GMI, RSVD4, 0x31d0, N, N), + PINGROUP(gmi_cs4_n_pk2, RSVD1, NAND, GMI, RSVD4, 0x31e4, N, N), + PINGROUP(gmi_cs2_n_pk3, RSVD1, NAND, GMI, RSVD4, 0x31dc, N, N), + PINGROUP(gmi_cs3_n_pk4, RSVD1, NAND, GMI, GMI_ALT, 0x31e0, N, N), + PINGROUP(spdif_out_pk5, SPDIF, RSVD2, I2C1, SDMMC2, 0x3354, N, N), + PINGROUP(spdif_in_pk6, SPDIF, HDA, I2C1, SDMMC2, 0x3350, N, N), + PINGROUP(gmi_a19_pk7, UARTD, SPI4, GMI, RSVD4, 0x323c, N, N), + PINGROUP(vi_d2_pl0, DDR, SDMMC2, VI, RSVD4, 0x312c, N, Y), + PINGROUP(vi_d3_pl1, DDR, SDMMC2, VI, RSVD4, 0x3130, N, Y), + PINGROUP(vi_d4_pl2, DDR, SDMMC2, VI, RSVD4, 0x3134, N, Y), + PINGROUP(vi_d5_pl3, DDR, SDMMC2, VI, RSVD4, 0x3138, N, Y), + PINGROUP(vi_d6_pl4, DDR, SDMMC2, VI, RSVD4, 0x313c, N, Y), + PINGROUP(vi_d7_pl5, DDR, SDMMC2, VI, RSVD4, 0x3140, N, Y), + PINGROUP(vi_d8_pl6, DDR, SDMMC2, VI, RSVD4, 0x3144, N, Y), + PINGROUP(vi_d9_pl7, DDR, SDMMC2, VI, RSVD4, 0x3148, N, Y), + PINGROUP(lcd_d16_pm0, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e4, N, N), + PINGROUP(lcd_d17_pm1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30e8, N, N), + PINGROUP(lcd_d18_pm2, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30ec, N, N), + PINGROUP(lcd_d19_pm3, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f0, N, N), + PINGROUP(lcd_d20_pm4, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f4, N, N), + PINGROUP(lcd_d21_pm5, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30f8, N, N), + PINGROUP(lcd_d22_pm6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x30fc, N, N), + PINGROUP(lcd_d23_pm7, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3100, N, N), + PINGROUP(dap1_fs_pn0, I2S0, HDA, GMI, SDMMC2, 0x3338, N, N), + PINGROUP(dap1_din_pn1, I2S0, HDA, GMI, SDMMC2, 0x333c, N, N), + PINGROUP(dap1_dout_pn2, I2S0, HDA, GMI, SDMMC2, 0x3340, N, N), + PINGROUP(dap1_sclk_pn3, I2S0, HDA, GMI, SDMMC2, 0x3344, N, N), + PINGROUP(lcd_cs0_n_pn4, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3084, N, N), + PINGROUP(lcd_sdout_pn5, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x307c, N, N), + PINGROUP(lcd_dc0_pn6, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3088, N, N), + PINGROUP(hdmi_int_pn7, HDMI, RSVD2, RSVD3, RSVD4, 0x3110, N, N), + PINGROUP(ulpi_data7_po0, SPI2, HSI, UARTA, ULPI, 0x301c, N, N), + PINGROUP(ulpi_data0_po1, SPI3, HSI, UARTA, ULPI, 0x3000, N, N), + PINGROUP(ulpi_data1_po2, SPI3, HSI, UARTA, ULPI, 0x3004, N, N), + PINGROUP(ulpi_data2_po3, SPI3, HSI, UARTA, ULPI, 0x3008, N, N), + PINGROUP(ulpi_data3_po4, SPI3, HSI, UARTA, ULPI, 0x300c, N, N), + PINGROUP(ulpi_data4_po5, SPI2, HSI, UARTA, ULPI, 0x3010, N, N), + PINGROUP(ulpi_data5_po6, SPI2, HSI, UARTA, ULPI, 0x3014, N, N), + PINGROUP(ulpi_data6_po7, SPI2, HSI, UARTA, ULPI, 0x3018, N, N), + PINGROUP(dap3_fs_pp0, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3030, N, N), + PINGROUP(dap3_din_pp1, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3034, N, N), + PINGROUP(dap3_dout_pp2, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x3038, N, N), + PINGROUP(dap3_sclk_pp3, I2S2, RSVD2, DISPLAYA, DISPLAYB, 0x303c, N, N), + PINGROUP(dap4_fs_pp4, I2S3, RSVD2, GMI, RSVD4, 0x31a8, N, N), + PINGROUP(dap4_din_pp5, I2S3, RSVD2, GMI, RSVD4, 0x31ac, N, N), + PINGROUP(dap4_dout_pp6, I2S3, RSVD2, GMI, RSVD4, 0x31b0, N, N), + PINGROUP(dap4_sclk_pp7, I2S3, RSVD2, GMI, RSVD4, 0x31b4, N, N), + PINGROUP(kb_col0_pq0, KBC, NAND, TRACE, TEST, 0x32fc, N, N), + PINGROUP(kb_col1_pq1, KBC, NAND, TRACE, TEST, 0x3300, N, N), + PINGROUP(kb_col2_pq2, KBC, NAND, TRACE, RSVD4, 0x3304, N, N), + PINGROUP(kb_col3_pq3, KBC, NAND, TRACE, RSVD4, 0x3308, N, N), + PINGROUP(kb_col4_pq4, KBC, NAND, TRACE, RSVD4, 0x330c, N, N), + PINGROUP(kb_col5_pq5, KBC, NAND, TRACE, RSVD4, 0x3310, N, N), + PINGROUP(kb_col6_pq6, KBC, NAND, TRACE, MIO, 0x3314, N, N), + PINGROUP(kb_col7_pq7, KBC, NAND, TRACE, MIO, 0x3318, N, N), + PINGROUP(kb_row0_pr0, KBC, NAND, RSVD3, RSVD4, 0x32bc, N, N), + PINGROUP(kb_row1_pr1, KBC, NAND, RSVD3, RSVD4, 0x32c0, N, N), + PINGROUP(kb_row2_pr2, KBC, NAND, RSVD3, RSVD4, 0x32c4, N, N), + PINGROUP(kb_row3_pr3, KBC, NAND, RSVD3, INVALID, 0x32c8, N, N), + PINGROUP(kb_row4_pr4, KBC, NAND, TRACE, RSVD4, 0x32cc, N, N), + PINGROUP(kb_row5_pr5, KBC, NAND, TRACE, OWR, 0x32d0, N, N), + PINGROUP(kb_row6_pr6, KBC, NAND, SDMMC2, MIO, 0x32d4, N, N), + PINGROUP(kb_row7_pr7, KBC, NAND, SDMMC2, MIO, 0x32d8, N, N), + PINGROUP(kb_row8_ps0, KBC, NAND, SDMMC2, MIO, 0x32dc, N, N), + PINGROUP(kb_row9_ps1, KBC, NAND, SDMMC2, MIO, 0x32e0, N, N), + PINGROUP(kb_row10_ps2, KBC, NAND, SDMMC2, MIO, 0x32e4, N, N), + PINGROUP(kb_row11_ps3, KBC, NAND, SDMMC2, MIO, 0x32e8, N, N), + PINGROUP(kb_row12_ps4, KBC, NAND, SDMMC2, MIO, 0x32ec, N, N), + PINGROUP(kb_row13_ps5, KBC, NAND, SDMMC2, MIO, 0x32f0, N, N), + PINGROUP(kb_row14_ps6, KBC, NAND, SDMMC2, MIO, 0x32f4, N, N), + PINGROUP(kb_row15_ps7, KBC, NAND, SDMMC2, MIO, 0x32f8, N, N), + PINGROUP(vi_pclk_pt0, RSVD1, SDMMC2, VI, RSVD4, 0x3154, N, Y), + PINGROUP(vi_mclk_pt1, VI, VI_ALT1, VI_ALT2, VI_ALT3, 0x3158, N, Y), + PINGROUP(vi_d10_pt2, DDR, RSVD2, VI, RSVD4, 0x314c, N, Y), + PINGROUP(vi_d11_pt3, DDR, RSVD2, VI, RSVD4, 0x3150, N, Y), + PINGROUP(vi_d0_pt4, DDR, RSVD2, VI, RSVD4, 0x3124, N, Y), + PINGROUP(gen2_i2c_scl_pt5, I2C2, HDCP, GMI, RSVD4, 0x3250, Y, N), + PINGROUP(gen2_i2c_sda_pt6, I2C2, HDCP, GMI, RSVD4, 0x3254, Y, N), + PINGROUP(sdmmc4_cmd_pt7, I2C3, NAND, GMI, SDMMC4, 0x325c, N, Y), + PINGROUP(pu0, OWR, UARTA, GMI, RSVD4, 0x3184, N, N), + PINGROUP(pu1, RSVD1, UARTA, GMI, RSVD4, 0x3188, N, N), + PINGROUP(pu2, RSVD1, UARTA, GMI, RSVD4, 0x318c, N, N), + PINGROUP(pu3, PWM0, UARTA, GMI, RSVD4, 0x3190, N, N), + PINGROUP(pu4, PWM1, UARTA, GMI, RSVD4, 0x3194, N, N), + PINGROUP(pu5, PWM2, UARTA, GMI, RSVD4, 0x3198, N, N), + PINGROUP(pu6, PWM3, UARTA, GMI, RSVD4, 0x319c, N, N), + PINGROUP(jtag_rtck_pu7, RTCK, RSVD2, RSVD3, RSVD4, 0x32b0, N, N), + PINGROUP(pv0, RSVD1, RSVD2, RSVD3, RSVD4, 0x3040, N, N), + PINGROUP(pv1, RSVD1, RSVD2, RSVD3, RSVD4, 0x3044, N, N), + PINGROUP(pv2, OWR, RSVD2, RSVD3, RSVD4, 0x3060, N, N), + PINGROUP(pv3, CLK_12M_OUT, RSVD2, RSVD3, RSVD4, 0x3064, N, N), + PINGROUP(ddc_scl_pv4, I2C4, RSVD2, RSVD3, RSVD4, 0x3114, N, N), + PINGROUP(ddc_sda_pv5, I2C4, RSVD2, RSVD3, RSVD4, 0x3118, N, N), + PINGROUP(crt_hsync_pv6, CRT, RSVD2, RSVD3, RSVD4, 0x311c, N, N), + PINGROUP(crt_vsync_pv7, CRT, RSVD2, RSVD3, RSVD4, 0x3120, N, N), + PINGROUP(lcd_cs1_n_pw0, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3104, N, N), + PINGROUP(lcd_m1_pw1, DISPLAYA, DISPLAYB, RSVD3, RSVD4, 0x3108, N, N), + PINGROUP(spi2_cs1_n_pw2, SPI3, SPI2, SPI2_ALT, I2C1, 0x3388, N, N), + PINGROUP(spi2_cs2_n_pw3, SPI3, SPI2, SPI2_ALT, I2C1, 0x338c, N, N), + PINGROUP(clk1_out_pw4, EXTPERIPH1, RSVD2, RSVD3, RSVD4, 0x334c, N, N), + PINGROUP(clk2_out_pw5, EXTPERIPH2, RSVD2, RSVD3, RSVD4, 0x3068, N, N), + PINGROUP(uart3_txd_pw6, UARTC, RSVD2, GMI, RSVD4, 0x3174, N, N), + PINGROUP(uart3_rxd_pw7, UARTC, RSVD2, GMI, RSVD4, 0x3178, N, N), + PINGROUP(spi2_mosi_px0, SPI6, SPI2, SPI3, GMI, 0x3368, N, N), + PINGROUP(spi2_miso_px1, SPI6, SPI2, SPI3, GMI, 0x336c, N, N), + PINGROUP(spi2_sck_px2, SPI6, SPI2, SPI3, GMI, 0x3374, N, N), + PINGROUP(spi2_cs0_n_px3, SPI6, SPI2, SPI3, GMI, 0x3370, N, N), + PINGROUP(spi1_mosi_px4, SPI2, SPI1, SPI2_ALT, GMI, 0x3378, N, N), + PINGROUP(spi1_sck_px5, SPI2, SPI1, SPI2_ALT, GMI, 0x337c, N, N), + PINGROUP(spi1_cs0_n_px6, SPI2, SPI1, SPI2_ALT, GMI, 0x3380, N, N), + PINGROUP(spi1_miso_px7, SPI3, SPI1, SPI2_ALT, RSVD4, 0x3384, N, N), + PINGROUP(ulpi_clk_py0, SPI1, RSVD2, UARTD, ULPI, 0x3020, N, N), + PINGROUP(ulpi_dir_py1, SPI1, RSVD2, UARTD, ULPI, 0x3024, N, N), + PINGROUP(ulpi_nxt_py2, SPI1, RSVD2, UARTD, ULPI, 0x3028, N, N), + PINGROUP(ulpi_stp_py3, SPI1, RSVD2, UARTD, ULPI, 0x302c, N, N), + PINGROUP(sdmmc1_dat3_py4, SDMMC1, RSVD2, UARTE, UARTA, 0x3050, N, N), + PINGROUP(sdmmc1_dat2_py5, SDMMC1, RSVD2, UARTE, UARTA, 0x3054, N, N), + PINGROUP(sdmmc1_dat1_py6, SDMMC1, RSVD2, UARTE, UARTA, 0x3058, N, N), + PINGROUP(sdmmc1_dat0_py7, SDMMC1, RSVD2, UARTE, UARTA, 0x305c, N, N), + PINGROUP(sdmmc1_clk_pz0, SDMMC1, RSVD2, RSVD3, UARTA, 0x3048, N, N), + PINGROUP(sdmmc1_cmd_pz1, SDMMC1, RSVD2, RSVD3, UARTA, 0x304c, N, N), + PINGROUP(lcd_sdin_pz2, DISPLAYA, DISPLAYB, SPI5, RSVD4, 0x3078, N, N), + PINGROUP(lcd_wr_n_pz3, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x3080, N, N), + PINGROUP(lcd_sck_pz4, DISPLAYA, DISPLAYB, SPI5, HDCP, 0x308c, N, N), + PINGROUP(sys_clk_req_pz5, SYSCLK, RSVD2, RSVD3, RSVD4, 0x3320, N, N), + PINGROUP(pwr_i2c_scl_pz6, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b4, Y, N), + PINGROUP(pwr_i2c_sda_pz7, I2CPWR, RSVD2, RSVD3, RSVD4, 0x32b8, Y, N), + PINGROUP(sdmmc4_dat0_paa0, UARTE, SPI3, GMI, SDMMC4, 0x3260, N, Y), + PINGROUP(sdmmc4_dat1_paa1, UARTE, SPI3, GMI, SDMMC4, 0x3264, N, Y), + PINGROUP(sdmmc4_dat2_paa2, UARTE, SPI3, GMI, SDMMC4, 0x3268, N, Y), + PINGROUP(sdmmc4_dat3_paa3, UARTE, SPI3, GMI, SDMMC4, 0x326c, N, Y), + PINGROUP(sdmmc4_dat4_paa4, I2C3, I2S4, GMI, SDMMC4, 0x3270, N, Y), + PINGROUP(sdmmc4_dat5_paa5, VGP3, I2S4, GMI, SDMMC4, 0x3274, N, Y), + PINGROUP(sdmmc4_dat6_paa6, VGP4, I2S4, GMI, SDMMC4, 0x3278, N, Y), + PINGROUP(sdmmc4_dat7_paa7, VGP5, I2S4, GMI, SDMMC4, 0x327c, N, Y), + PINGROUP(pbb0, I2S4, RSVD2, RSVD3, SDMMC4, 0x328c, N, N), + PINGROUP(cam_i2c_scl_pbb1, VGP1, I2C3, RSVD3, SDMMC4, 0x3290, Y, N), + PINGROUP(cam_i2c_sda_pbb2, VGP2, I2C3, RSVD3, SDMMC4, 0x3294, Y, N), + PINGROUP(pbb3, VGP3, DISPLAYA, DISPLAYB, SDMMC4, 0x3298, N, N), + PINGROUP(pbb4, VGP4, DISPLAYA, DISPLAYB, SDMMC4, 0x329c, N, N), + PINGROUP(pbb5, VGP5, DISPLAYA, DISPLAYB, SDMMC4, 0x32a0, N, N), + PINGROUP(pbb6, VGP6, DISPLAYA, DISPLAYB, SDMMC4, 0x32a4, N, N), + PINGROUP(pbb7, I2S4, RSVD2, RSVD3, SDMMC4, 0x32a8, N, N), + PINGROUP(cam_mclk_pcc0, VI, VI_ALT1, VI_ALT3, SDMMC4, 0x3284, N, N), + PINGROUP(pcc1, I2S4, RSVD2, RSVD3, SDMMC4, 0x3288, N, N), + PINGROUP(pcc2, I2S4, RSVD2, RSVD3, RSVD4, 0x32ac, N, N), + PINGROUP(sdmmc4_rst_n_pcc3, VGP6, RSVD2, RSVD3, SDMMC4, 0x3280, N, Y), + PINGROUP(sdmmc4_clk_pcc4, INVALID, NAND, GMI, SDMMC4, 0x3258, N, Y), + PINGROUP(clk2_req_pcc5, DAP, RSVD2, RSVD3, RSVD4, 0x306c, N, N), + PINGROUP(pex_l2_rst_n_pcc6, PCIE, HDA, RSVD3, RSVD4, 0x33d8, N, N), + PINGROUP(pex_l2_clkreq_n_pcc7, PCIE, HDA, RSVD3, RSVD4, 0x33dc, N, N), + PINGROUP(pex_l0_prsnt_n_pdd0, PCIE, HDA, RSVD3, RSVD4, 0x33b8, N, N), + PINGROUP(pex_l0_rst_n_pdd1, PCIE, HDA, RSVD3, RSVD4, 0x33bc, N, N), + PINGROUP(pex_l0_clkreq_n_pdd2, PCIE, HDA, RSVD3, RSVD4, 0x33c0, N, N), + PINGROUP(pex_wake_n_pdd3, PCIE, HDA, RSVD3, RSVD4, 0x33c4, N, N), + PINGROUP(pex_l1_prsnt_n_pdd4, PCIE, HDA, RSVD3, RSVD4, 0x33c8, N, N), + PINGROUP(pex_l1_rst_n_pdd5, PCIE, HDA, RSVD3, RSVD4, 0x33cc, N, N), + PINGROUP(pex_l1_clkreq_n_pdd6, PCIE, HDA, RSVD3, RSVD4, 0x33d0, N, N), + PINGROUP(pex_l2_prsnt_n_pdd7, PCIE, HDA, RSVD3, RSVD4, 0x33d4, N, N), + PINGROUP(clk3_out_pee0, EXTPERIPH3, RSVD2, RSVD3, RSVD4, 0x31b8, N, N), + PINGROUP(clk3_req_pee1, DEV3, RSVD2, RSVD3, RSVD4, 0x31bc, N, N), + PINGROUP(clk1_req_pee2, DAP, HDA, RSVD3, RSVD4, 0x3348, N, N), + PINGROUP(hdmi_cec_pee3, CEC, RSVD2, RSVD3, RSVD4, 0x33e0, Y, N), + PINGROUP(clk_32k_in, CLK_32K_IN, RSVD2, RSVD3, RSVD4, 0x3330, N, N), + PINGROUP(core_pwr_req, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3324, N, N), + PINGROUP(cpu_pwr_req, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4, 0x3328, N, N), + PINGROUP(owr, OWR, CEC, RSVD3, RSVD4, 0x3334, N, N), + PINGROUP(pwr_int_n, PWR_INT_N, RSVD2, RSVD3, RSVD4, 0x332c, N, N), + /* pg_name, r, hsm_b, schmitt_b, lpmd_b, drvdn_b, drvdn_w, drvup_b, drvup_w, slwr_b, slwr_w, slwf_b, slwf_w */ + DRV_PINGROUP(ao1, 0x868, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(ao2, 0x86c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(at1, 0x870, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), + DRV_PINGROUP(at2, 0x874, 2, 3, 4, 14, 5, 19, 5, 24, 2, 28, 2), + DRV_PINGROUP(at3, 0x878, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(at4, 0x87c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(at5, 0x880, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(cdev1, 0x884, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(cdev2, 0x888, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(cec, 0x938, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(crt, 0x8f8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(csus, 0x88c, -1, -1, -1, 12, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(dap1, 0x890, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dap2, 0x894, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dap3, 0x898, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dap4, 0x89c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dbg, 0x8a0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(ddc, 0x8fc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(dev3, 0x92c, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(gma, 0x900, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gmb, 0x904, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gmc, 0x908, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gmd, 0x90c, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), + DRV_PINGROUP(gme, 0x910, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gmf, 0x914, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gmg, 0x918, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gmh, 0x91c, 2, 3, 4, 14, 5, 19, 5, 28, 2, 30, 2), + DRV_PINGROUP(gpv, 0x928, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(lcd1, 0x8a4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(lcd2, 0x8a8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(owr, 0x920, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(sdio1, 0x8ec, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdio2, 0x8ac, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(sdio3, 0x8b0, 2, 3, -1, 12, 7, 20, 7, 28, 2, 30, 2), + DRV_PINGROUP(spi, 0x8b4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uaa, 0x8b8, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uab, 0x8bc, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uart2, 0x8c0, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uart3, 0x8c4, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(uda, 0x924, 2, 3, 4, 12, 5, 20, 5, 28, 2, 30, 2), + DRV_PINGROUP(vi1, 0x8c8, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), +}; + +static const struct tegra_pinctrl_soc_data tegra30_pinctrl = { + .ngpios = NUM_GPIOS, + .pins = tegra30_pins, + .npins = ARRAY_SIZE(tegra30_pins), + .functions = tegra30_functions, + .nfunctions = ARRAY_SIZE(tegra30_functions), + .groups = tegra30_groups, + .ngroups = ARRAY_SIZE(tegra30_groups), + .hsm_in_mux = false, + .schmitt_in_mux = false, + .drvtype_in_mux = false, +}; + +static int tegra30_pinctrl_probe(struct platform_device *pdev) +{ + return tegra_pinctrl_probe(pdev, &tegra30_pinctrl); +} + +static const struct of_device_id tegra30_pinctrl_of_match[] = { + { .compatible = "nvidia,tegra30-pinmux", }, + { }, +}; +MODULE_DEVICE_TABLE(of, tegra30_pinctrl_of_match); + +static struct platform_driver tegra30_pinctrl_driver = { + .driver = { + .name = "tegra30-pinctrl", + .of_match_table = tegra30_pinctrl_of_match, + }, + .probe = tegra30_pinctrl_probe, + .remove = tegra_pinctrl_remove, +}; +module_platform_driver(tegra30_pinctrl_driver); + +MODULE_AUTHOR("Stephen Warren "); +MODULE_DESCRIPTION("NVIDIA Tegra30 pinctrl driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 209045adc2bbdb2b315fa5539cec54d01cd3e7db Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 30 Nov 2015 10:02:22 +0100 Subject: perf tools: add JVMTI agent library This is a standalone JVMTI library to help profile Java jitted code with perf record/perf report. The library is not installed or compiled automatically by perf Makefile. It is not used directly by perf. It is arch agnostic and has been tested on X86 and ARM. It needs to be used with a Java runtime, such as OpenJDK, as follows: $ java -agentpath:libjvmti.so ....... See the "Committer Notes" below on how to build it. When used this way, java will generate a jitdump binary file in $HOME/.debug/java/jit/java-jit-* This binary dump file contains information to help symbolize and annotate jitted code. The jitdump information must be injected into the perf.data file using: $ perf inject --jit -i perf.data -o perf.data.jitted This injects the MMAP records to cover the jitted code and also generates one ELF image for each jitted function. The ELF images are created in the same subdir as the jitdump file. The MMAP records point there too. Then, to visualize the function or asm profile, simply use the regular perf commands: $ perf report -i perf.data.jitted or $ perf annotate -i perf.data.jitted JVMTI agent code adapted from the OProfile's opagent code. This version of the JVMTI agent is using the CLOCK_MONOTONIC as the time source to timestamp jit samples. To correlate with perf_events samples, it needs to run on kernel 4.0.0-rc5+ or later with the following commit from Peter Zijlstra: 34f439278cef ("perf: Add per event clockid support") With this patch recording jitted code is done as follows: $ perf record -k mono -- java -agentpath:libjvmti.so ....... -------------------------------------------------------------------------- Committer Notes: Extended testing instructions: $ cd tools/perf/jvmti/ $ dnf install java-devel $ make Then, create some simple java stuff to record some samples: $ cat hello.java public class hello { public static void main(String[] args) { System.out.println("Hello, World"); } } $ javac hello.java $ java hello Hello, World $ And then record it using this jvmti thing: $ perf record -k mono java -agentpath:/home/acme/git/linux/tools/perf/jvmti/libjvmti.so hello java: jvmti: jitdump in /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jit-1908.dump Hello, World [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.030 MB perf.data (268 samples) ] $ Now lets insert the PERF_RECORD_MMAP2 records to point jitted mmaps to files created by the agent: $ perf inject --jit -i perf.data -o perf.data.jitted And finally see that it did its job: $ perf report -D -i perf.data.jitted | grep PERF_RECORD_MMAP2 | tail -5 79197149129422 0xfe10 [0xa0]: PERF_RECORD_MMAP2 1908/1923: [0x7f172428bd60(0x80) @ 0x40 fd:02 1840554 1]: --xs /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-283.so 79197149235701 0xfeb0 [0xa0]: PERF_RECORD_MMAP2 1908/1923: [0x7f172428ba60(0x180) @ 0x40 fd:02 1840555 1]: --xs /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-284.so 79197149250558 0xff50 [0xa0]: PERF_RECORD_MMAP2 1908/1923: [0x7f172428b860(0x180) @ 0x40 fd:02 1840556 1]: --xs /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-285.so 79197149714746 0xfff0 [0xa0]: PERF_RECORD_MMAP2 1908/1923: [0x7f172428b660(0x180) @ 0x40 fd:02 1840557 1]: --xs /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-286.so 79197149806558 0x10090 [0xa0]: PERF_RECORD_MMAP2 1908/1923: [0x7f172428b460(0x180) @ 0x40 fd:02 1840558 1]: --xs /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-287.so $ So: $ perf report -D -i perf.data | grep PERF_RECORD_MMAP2 | wc -l Failed to open /tmp/perf-1908.map, continuing without symbols 21 $ perf report -D -i perf.data.jitted | grep PERF_RECORD_MMAP2 | wc -l 307 $ echo $((307 - 21)) 286 $ 286 extra PERF_RECORD_MMAP2 records. All for thise tiny, with just one function, ELF files: $ file /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-9.so /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-9.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), corrupted program header size, BuildID[sha1]=ae54a2ebc3ecf0ba547bfc8cabdea1519df5203f, not stripped $ readelf -sw /home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-9.so Symbol table '.symtab' contains 2 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000040 9 FUNC LOCAL DEFAULT 1 atomic_cmpxchg_long $ Inserted into the build-id cache: $ ls -la ~/.debug/.build-id/ae/54a2ebc3ecf0ba547bfc8cabdea1519df5203f lrwxrwxrwx. 1 acme acme 111 Feb 5 11:30 /home/acme/.debug/.build-id/ae/54a2ebc3ecf0ba547bfc8cabdea1519df5203f -> ../../home/acme/.debug/jit/java-jit-20160205.XXWIEDls/jitted-1908-9.so/ae54a2ebc3ecf0ba547bfc8cabdea1519df5203f Note: check why 'file' reports that 'corrupted program header size'. With a stupid java hog to do some profiling: $ cat hog.java public class hog { private static double do_something_else(int i) { double total = 0; while (i > 0) { total += Math.log(i--); } return total; } private static double do_something(int i) { double total = 0; while (i > 0) { total += Math.sqrt(i--) + do_something_else(i / 100); } return total; } public static void main(String[] args) { System.out.println(String.format("%s=%f & %f", args[0], do_something(Integer.parseInt(args[0])), do_something_else(Integer.parseInt(args[1])))); } } $ javac hog.java $ perf record -F 10000 -g -k mono java -agentpath:/home/acme/git/linux/tools/perf/jvmti/libjvmti.so hog 100000 2345000 java: jvmti: jitdump in /home/acme/.debug/jit/java-jit-20160205.XX4sqd14/jit-8670.dump 100000=291561592.669602 & 32050989.778714 [ perf record: Woken up 6 times to write data ] [ perf record: Captured and wrote 1.536 MB perf.data (12538 samples) ] $ perf inject --jit -i perf.data -o perf.data.jitted Looking at the 'perf report' TUI, at one expanded callchain leading to the jitted code: $ perf report --no-children -i perf.data.jitted Samples: 12K of event 'cycles:pp', Event count (approx.): 3829569932 Overhead Comm Shared Object Symbol - 93.38% java jitted-8670-291.so [.] class hog.do_something_else(int) class hog.do_something_else(int) - Interpreter - 75.86% call_stub JavaCalls::call_helper jni_invoke_static jni_CallStaticVoidMethod JavaMain start_thread - 17.52% JavaCalls::call_helper jni_invoke_static jni_CallStaticVoidMethod JavaMain start_thread Signed-off-by: Stephane Eranian Tested-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Andi Kleen Cc: Carl Love Cc: David Ahern Cc: Jiri Olsa Cc: John McCutchan Cc: Namhyung Kim Cc: Pawel Moll Cc: Peter Zijlstra Cc: Sonny Rao Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1448874143-7269-4-git-send-email-eranian@google.com [ Made it build on fedora23, added some build/usage instructions ] [ Check if filename != NULL in compiled_method_load_cb, fixing segfault ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/jvmti/Makefile | 76 +++++++ tools/perf/jvmti/jvmti_agent.c | 465 +++++++++++++++++++++++++++++++++++++++++ tools/perf/jvmti/jvmti_agent.h | 29 +++ tools/perf/jvmti/libjvmti.c | 208 ++++++++++++++++++ 4 files changed, 778 insertions(+) create mode 100644 tools/perf/jvmti/Makefile create mode 100644 tools/perf/jvmti/jvmti_agent.c create mode 100644 tools/perf/jvmti/jvmti_agent.h create mode 100644 tools/perf/jvmti/libjvmti.c diff --git a/tools/perf/jvmti/Makefile b/tools/perf/jvmti/Makefile new file mode 100644 index 000000000000..5968f8332a28 --- /dev/null +++ b/tools/perf/jvmti/Makefile @@ -0,0 +1,76 @@ +ARCH=$(shell uname -m) + +ifeq ($(ARCH), x86_64) +JARCH=amd64 +endif +ifeq ($(ARCH), armv7l) +JARCH=armhf +endif +ifeq ($(ARCH), armv6l) +JARCH=armhf +endif +ifeq ($(ARCH), aarch64) +JARCH=aarch64 +endif +ifeq ($(ARCH), ppc64) +JARCH=powerpc +endif +ifeq ($(ARCH), ppc64le) +JARCH=powerpc +endif + +DESTDIR=/usr/local + +VERSION=1 +REVISION=0 +AGE=0 + +LN=ln -sf +RM=rm + +SLIBJVMTI=libjvmti.so.$(VERSION).$(REVISION).$(AGE) +VLIBJVMTI=libjvmti.so.$(VERSION) +SLDFLAGS=-shared -Wl,-soname -Wl,$(VLIBJVMTI) +SOLIBEXT=so + +# The following works at least on fedora 23, you may need the next +# line for other distros. +JDIR=$(shell alternatives --display java | tail -1 | cut -d' ' -f 5 | sed 's%/jre/bin/java.%%g') +#JDIR=$(shell /usr/sbin/update-java-alternatives -l | head -1 | cut -d ' ' -f 3) +# -lrt required in 32-bit mode for clock_gettime() +LIBS=-lelf -lrt +INCDIR=-I $(JDIR)/include -I $(JDIR)/include/linux + +TARGETS=$(SLIBJVMTI) + +SRCS=libjvmti.c jvmti_agent.c +OBJS=$(SRCS:.c=.o) +SOBJS=$(OBJS:.o=.lo) +OPT=-O2 -g -Werror -Wall + +CFLAGS=$(INCDIR) $(OPT) + +all: $(TARGETS) + +.c.o: + $(CC) $(CFLAGS) -c $*.c +.c.lo: + $(CC) -fPIC -DPIC $(CFLAGS) -c $*.c -o $*.lo + +$(OBJS) $(SOBJS): Makefile jvmti_agent.h ../util/jitdump.h + +$(SLIBJVMTI): $(SOBJS) + $(CC) $(CFLAGS) $(SLDFLAGS) -o $@ $(SOBJS) $(LIBS) + $(LN) $@ libjvmti.$(SOLIBEXT) + +clean: + $(RM) -f *.o *.so.* *.so *.lo + +install: + -mkdir -p $(DESTDIR)/lib + install -m 755 $(SLIBJVMTI) $(DESTDIR)/lib/ + (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) $(VLIBJVMTI)) + (cd $(DESTDIR)/lib; $(LN) $(SLIBJVMTI) libjvmti.$(SOLIBEXT)) + ldconfig + +.SUFFIXES: .c .S .o .lo diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c new file mode 100644 index 000000000000..cbab139de5a4 --- /dev/null +++ b/tools/perf/jvmti/jvmti_agent.c @@ -0,0 +1,465 @@ +/* + * jvmti_agent.c: JVMTI agent interface + * + * Adapted from the Oprofile code in opagent.c: + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright 2007 OProfile authors + * Jens Wilke + * Daniel Hansel + * Copyright IBM Corporation 2007 + */ +#include +#include /* for mkdir() */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for gettid() */ +#include + +#include "jvmti_agent.h" +#include "../util/jitdump.h" + +#define JIT_LANG "java" + +static char jit_path[PATH_MAX]; +static void *marker_addr; + +/* + * padding buffer + */ +static const char pad_bytes[7]; + +static inline pid_t gettid(void) +{ + return (pid_t)syscall(__NR_gettid); +} + +static int get_e_machine(struct jitheader *hdr) +{ + ssize_t sret; + char id[16]; + int fd, ret = -1; + int m = -1; + struct { + uint16_t e_type; + uint16_t e_machine; + } info; + + fd = open("/proc/self/exe", O_RDONLY); + if (fd == -1) + return -1; + + sret = read(fd, id, sizeof(id)); + if (sret != sizeof(id)) + goto error; + + /* check ELF signature */ + if (id[0] != 0x7f || id[1] != 'E' || id[2] != 'L' || id[3] != 'F') + goto error; + + sret = read(fd, &info, sizeof(info)); + if (sret != sizeof(info)) + goto error; + + m = info.e_machine; + if (m < 0) + m = 0; /* ELF EM_NONE */ + + hdr->elf_mach = m; + ret = 0; +error: + close(fd); + return ret; +} + +#define NSEC_PER_SEC 1000000000 +static int perf_clk_id = CLOCK_MONOTONIC; + +static inline uint64_t +timespec_to_ns(const struct timespec *ts) +{ + return ((uint64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; +} + +static inline uint64_t +perf_get_timestamp(void) +{ + struct timespec ts; + int ret; + + ret = clock_gettime(perf_clk_id, &ts); + if (ret) + return 0; + + return timespec_to_ns(&ts); +} + +static int +debug_cache_init(void) +{ + char str[32]; + char *base, *p; + struct tm tm; + time_t t; + int ret; + + time(&t); + localtime_r(&t, &tm); + + base = getenv("JITDUMPDIR"); + if (!base) + base = getenv("HOME"); + if (!base) + base = "."; + + strftime(str, sizeof(str), JIT_LANG"-jit-%Y%m%d", &tm); + + snprintf(jit_path, PATH_MAX - 1, "%s/.debug/", base); + + ret = mkdir(jit_path, 0755); + if (ret == -1) { + if (errno != EEXIST) { + warn("jvmti: cannot create jit cache dir %s", jit_path); + return -1; + } + } + + snprintf(jit_path, PATH_MAX - 1, "%s/.debug/jit", base); + ret = mkdir(jit_path, 0755); + if (ret == -1) { + if (errno != EEXIST) { + warn("cannot create jit cache dir %s", jit_path); + return -1; + } + } + + snprintf(jit_path, PATH_MAX - 1, "%s/.debug/jit/%s.XXXXXXXX", base, str); + + p = mkdtemp(jit_path); + if (p != jit_path) { + warn("cannot create jit cache dir %s", jit_path); + return -1; + } + + return 0; +} + +static int +perf_open_marker_file(int fd) +{ + long pgsz; + + pgsz = sysconf(_SC_PAGESIZE); + if (pgsz == -1) + return -1; + + /* + * we mmap the jitdump to create an MMAP RECORD in perf.data file. + * The mmap is captured either live (perf record running when we mmap) + * or in deferred mode, via /proc/PID/maps + * the MMAP record is used as a marker of a jitdump file for more meta + * data info about the jitted code. Perf report/annotate detect this + * special filename and process the jitdump file. + * + * mapping must be PROT_EXEC to ensure it is captured by perf record + * even when not using -d option + */ + marker_addr = mmap(NULL, pgsz, PROT_READ|PROT_EXEC, MAP_PRIVATE, fd, 0); + return (marker_addr == MAP_FAILED) ? -1 : 0; +} + +static void +perf_close_marker_file(void) +{ + long pgsz; + + if (!marker_addr) + return; + + pgsz = sysconf(_SC_PAGESIZE); + if (pgsz == -1) + return; + + munmap(marker_addr, pgsz); +} + +void *jvmti_open(void) +{ + int pad_cnt; + char dump_path[PATH_MAX]; + struct jitheader header; + int fd; + FILE *fp; + + /* + * check if clockid is supported + */ + if (!perf_get_timestamp()) + warnx("jvmti: kernel does not support %d clock id", perf_clk_id); + + memset(&header, 0, sizeof(header)); + + debug_cache_init(); + + /* + * jitdump file name + */ + snprintf(dump_path, PATH_MAX, "%s/jit-%i.dump", jit_path, getpid()); + + fd = open(dump_path, O_CREAT|O_TRUNC|O_RDWR, 0666); + if (fd == -1) + return NULL; + + /* + * create perf.data maker for the jitdump file + */ + if (perf_open_marker_file(fd)) { + warnx("jvmti: failed to create marker file"); + return NULL; + } + + fp = fdopen(fd, "w+"); + if (!fp) { + warn("jvmti: cannot create %s", dump_path); + close(fd); + goto error; + } + + warnx("jvmti: jitdump in %s", dump_path); + + if (get_e_machine(&header)) { + warn("get_e_machine failed\n"); + goto error; + } + + header.magic = JITHEADER_MAGIC; + header.version = JITHEADER_VERSION; + header.total_size = sizeof(header); + header.pid = getpid(); + + /* calculate amount of padding '\0' */ + pad_cnt = PADDING_8ALIGNED(header.total_size); + header.total_size += pad_cnt; + + header.timestamp = perf_get_timestamp(); + + if (!fwrite(&header, sizeof(header), 1, fp)) { + warn("jvmti: cannot write dumpfile header"); + goto error; + } + + /* write padding '\0' if necessary */ + if (pad_cnt && !fwrite(pad_bytes, pad_cnt, 1, fp)) { + warn("jvmti: cannot write dumpfile header padding"); + goto error; + } + + return fp; +error: + fclose(fp); + return NULL; +} + +int +jvmti_close(void *agent) +{ + struct jr_code_close rec; + FILE *fp = agent; + + if (!fp) { + warnx("jvmti: incalid fd in close_agent"); + return -1; + } + + rec.p.id = JIT_CODE_CLOSE; + rec.p.total_size = sizeof(rec); + + rec.p.timestamp = perf_get_timestamp(); + + if (!fwrite(&rec, sizeof(rec), 1, fp)) + return -1; + + fclose(fp); + + fp = NULL; + + perf_close_marker_file(); + + return 0; +} + +int +jvmti_write_code(void *agent, char const *sym, + uint64_t vma, void const *code, unsigned int const size) +{ + static int code_generation = 1; + struct jr_code_load rec; + size_t sym_len; + size_t padding_count; + FILE *fp = agent; + int ret = -1; + + /* don't care about 0 length function, no samples */ + if (size == 0) + return 0; + + if (!fp) { + warnx("jvmti: invalid fd in write_native_code"); + return -1; + } + + sym_len = strlen(sym) + 1; + + rec.p.id = JIT_CODE_LOAD; + rec.p.total_size = sizeof(rec) + sym_len; + padding_count = PADDING_8ALIGNED(rec.p.total_size); + rec.p. total_size += padding_count; + rec.p.timestamp = perf_get_timestamp(); + + rec.code_size = size; + rec.vma = vma; + rec.code_addr = vma; + rec.pid = getpid(); + rec.tid = gettid(); + + if (code) + rec.p.total_size += size; + + /* + * If JVM is multi-threaded, nultiple concurrent calls to agent + * may be possible, so protect file writes + */ + flockfile(fp); + + /* + * get code index inside lock to avoid race condition + */ + rec.code_index = code_generation++; + + ret = fwrite_unlocked(&rec, sizeof(rec), 1, fp); + fwrite_unlocked(sym, sym_len, 1, fp); + + if (padding_count) + fwrite_unlocked(pad_bytes, padding_count, 1, fp); + + if (code) + fwrite_unlocked(code, size, 1, fp); + + funlockfile(fp); + + ret = 0; + + return ret; +} + +int +jvmti_write_debug_info(void *agent, uint64_t code, const char *file, + jvmtiAddrLocationMap const *map, + jvmtiLineNumberEntry *li, jint num) +{ + static const char *prev_str = "\xff"; + struct jr_code_debug_info rec; + size_t sret, len, size, flen; + size_t padding_count; + FILE *fp = agent; + int i; + + /* + * no entry to write + */ + if (!num) + return 0; + + if (!fp) { + warnx("jvmti: invalid fd in write_debug_info"); + return -1; + } + + flen = strlen(file) + 1; + + rec.p.id = JIT_CODE_DEBUG_INFO; + size = sizeof(rec); + rec.p.timestamp = perf_get_timestamp(); + rec.code_addr = (uint64_t)(uintptr_t)code; + rec.nr_entry = num; + + /* + * on disk source line info layout: + * uint64_t : addr + * int : line number + * file[] : source file name + * padding : pad to multiple of 8 bytes + */ + size += num * (sizeof(uint64_t) + sizeof(int)); + size += flen + (num - 1) * 2; + /* + * pad to 8 bytes + */ + padding_count = PADDING_8ALIGNED(size); + + rec.p.total_size = size + padding_count; + + /* + * If JVM is multi-threaded, nultiple concurrent calls to agent + * may be possible, so protect file writes + */ + flockfile(fp); + + sret = fwrite_unlocked(&rec, sizeof(rec), 1, fp); + if (sret != 1) + goto error; + + for (i = 0; i < num; i++) { + uint64_t addr; + + addr = (uint64_t)map[i].start_address; + len = sizeof(addr); + sret = fwrite_unlocked(&addr, len, 1, fp); + if (sret != 1) + goto error; + + len = sizeof(int); + sret = fwrite_unlocked(&li[i].line_number, len, 1, fp); + if (sret != 1) + goto error; + + if (i == 0) { + sret = fwrite_unlocked(file, flen, 1, fp); + } else { + sret = fwrite_unlocked(prev_str, 2, 1, fp); + } + if (sret != 1) + goto error; + + } + if (padding_count) + sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp); + if (sret != 1) + goto error; + + funlockfile(fp); + return 0; +error: + funlockfile(fp); + return -1; +} diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h new file mode 100644 index 000000000000..8251a1c5ee3f --- /dev/null +++ b/tools/perf/jvmti/jvmti_agent.h @@ -0,0 +1,29 @@ +#ifndef __JVMTI_AGENT_H__ +#define __JVMTI_AGENT_H__ + +#include +#include +#include + +#define __unused __attribute__((unused)) + +#if defined(__cplusplus) +extern "C" { +#endif + +void *jvmti_open(void); +int jvmti_close(void *agent); +int jvmti_write_code(void *agent, char const *symbol_name, + uint64_t vma, void const *code, + const unsigned int code_size); +int jvmti_write_debug_info(void *agent, + uint64_t code, + const char *file, + jvmtiAddrLocationMap const *map, + jvmtiLineNumberEntry *tab, jint nr); + +#if defined(__cplusplus) +} + +#endif +#endif /* __JVMTI_H__ */ diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c new file mode 100644 index 000000000000..92ffbe4ff160 --- /dev/null +++ b/tools/perf/jvmti/libjvmti.c @@ -0,0 +1,208 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "jvmti_agent.h" + +static int has_line_numbers; +void *jvmti_agent; + +static void JNICALL +compiled_method_load_cb(jvmtiEnv *jvmti, + jmethodID method, + jint code_size, + void const *code_addr, + jint map_length, + jvmtiAddrLocationMap const *map, + void const *compile_info __unused) +{ + jvmtiLineNumberEntry *tab = NULL; + jclass decl_class; + char *class_sign = NULL; + char *func_name = NULL; + char *func_sign = NULL; + char *file_name= NULL; + char fn[PATH_MAX]; + uint64_t addr = (uint64_t)(uintptr_t)code_addr; + jvmtiError ret; + jint nr_lines = 0; + size_t len; + + ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, + &decl_class); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: cannot get declaring class"); + return; + } + + if (has_line_numbers && map && map_length) { + + ret = (*jvmti)->GetLineNumberTable(jvmti, method, &nr_lines, &tab); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: cannot get line table for method"); + } else { + ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: cannot get source filename ret=%d", ret); + nr_lines = 0; + } + } + } + + ret = (*jvmti)->GetClassSignature(jvmti, decl_class, + &class_sign, NULL); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: getclassignature failed"); + goto error; + } + + ret = (*jvmti)->GetMethodName(jvmti, method, &func_name, + &func_sign, NULL); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: failed getmethodname"); + goto error; + } + + /* + * Assume path name is class hierarchy, this is a common practice with Java programs + */ + if (*class_sign == 'L') { + int j, i = 0; + char *p = strrchr(class_sign, '/'); + if (p) { + /* drop the 'L' prefix and copy up to the final '/' */ + for (i = 0; i < (p - class_sign); i++) + fn[i] = class_sign[i+1]; + } + /* + * append file name, we use loops and not string ops to avoid modifying + * class_sign which is used later for the symbol name + */ + for (j = 0; i < (PATH_MAX - 1) && file_name && j < strlen(file_name); j++, i++) + fn[i] = file_name[j]; + fn[i] = '\0'; + } else { + /* fallback case */ + strcpy(fn, file_name); + } + /* + * write source line info record if we have it + */ + if (jvmti_write_debug_info(jvmti_agent, addr, fn, map, tab, nr_lines)) + warnx("jvmti: write_debug_info() failed"); + + len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2; + { + char str[len]; + snprintf(str, len, "%s%s%s", class_sign, func_name, func_sign); + if (jvmti_write_code(jvmti_agent, str, addr, code_addr, code_size)) + warnx("jvmti: write_code() failed"); + } +error: + (*jvmti)->Deallocate(jvmti, (unsigned char *)func_name); + (*jvmti)->Deallocate(jvmti, (unsigned char *)func_sign); + (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); + (*jvmti)->Deallocate(jvmti, (unsigned char *)tab); + (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); +} + +static void JNICALL +code_generated_cb(jvmtiEnv *jvmti, + char const *name, + void const *code_addr, + jint code_size) +{ + uint64_t addr = (uint64_t)(unsigned long)code_addr; + int ret; + + ret = jvmti_write_code(jvmti_agent, name, addr, code_addr, code_size); + if (ret) + warnx("jvmti: write_code() failed for code_generated"); +} + +JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __unused) +{ + jvmtiEventCallbacks cb; + jvmtiCapabilities caps1; + jvmtiJlocationFormat format; + jvmtiEnv *jvmti = NULL; + jint ret; + + jvmti_agent = jvmti_open(); + if (!jvmti_agent) { + warnx("jvmti: open_agent failed"); + return -1; + } + + /* + * Request a JVMTI interface version 1 environment + */ + ret = (*jvm)->GetEnv(jvm, (void *)&jvmti, JVMTI_VERSION_1); + if (ret != JNI_OK) { + warnx("jvmti: jvmti version 1 not supported"); + return -1; + } + + /* + * acquire method_load capability, we require it + * request line numbers (optional) + */ + memset(&caps1, 0, sizeof(caps1)); + caps1.can_generate_compiled_method_load_events = 1; + + ret = (*jvmti)->AddCapabilities(jvmti, &caps1); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: acquire compiled_method capability failed"); + return -1; + } + ret = (*jvmti)->GetJLocationFormat(jvmti, &format); + if (ret == JVMTI_ERROR_NONE && format == JVMTI_JLOCATION_JVMBCI) { + memset(&caps1, 0, sizeof(caps1)); + caps1.can_get_line_numbers = 1; + caps1.can_get_source_file_name = 1; + ret = (*jvmti)->AddCapabilities(jvmti, &caps1); + if (ret == JVMTI_ERROR_NONE) + has_line_numbers = 1; + } + + memset(&cb, 0, sizeof(cb)); + + cb.CompiledMethodLoad = compiled_method_load_cb; + cb.DynamicCodeGenerated = code_generated_cb; + + ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb)); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: cannot set event callbacks"); + return -1; + } + + ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: setnotification failed for method_load"); + return -1; + } + + ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: setnotification failed on code_generated"); + return -1; + } + return 0; +} + +JNIEXPORT void JNICALL +Agent_OnUnload(JavaVM *jvm __unused) +{ + int ret; + + ret = jvmti_close(jvmti_agent); + if (ret) + errx(1, "Error: op_close_agent()"); +} -- cgit From 598b7c6919c7bbcc1243009721a01bc12275ff3e Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 30 Nov 2015 10:02:23 +0100 Subject: perf jit: add source line info support This patch adds source line information support to perf for jitted code. The source line info must be emitted by the runtime, such as JVMTI. Perf injects extract the source line info from the jitdump file and adds the corresponding .debug_lines section in the ELF image generated for each jitted function. The source line enables matching any address in the profile with a source file and line number. The improvement is visible in perf annotate with the source code displayed alongside the assembly code. The dwarf code leverages the support from OProfile which is also released under GPLv2. Copyright 2007 OProfile authors. Signed-off-by: Stephane Eranian Cc: Adrian Hunter Cc: Andi Kleen Cc: Carl Love Cc: David Ahern Cc: Jiri Olsa Cc: John McCutchan Cc: Namhyung Kim Cc: Pawel Moll Cc: Peter Zijlstra Cc: Sonny Rao Cc: Sukadev Bhattiprolu Link: http://lkml.kernel.org/r/1448874143-7269-5-git-send-email-eranian@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/jvmti/jvmti_agent.c | 32 +-- tools/perf/jvmti/jvmti_agent.h | 11 +- tools/perf/jvmti/libjvmti.c | 122 ++++++++- tools/perf/util/Build | 3 + tools/perf/util/genelf.c | 15 +- tools/perf/util/genelf.h | 6 +- tools/perf/util/genelf_debug.c | 610 +++++++++++++++++++++++++++++++++++++++++ tools/perf/util/jitdump.c | 8 +- 8 files changed, 768 insertions(+), 39 deletions(-) create mode 100644 tools/perf/util/genelf_debug.c diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c index cbab139de5a4..6461e02ab940 100644 --- a/tools/perf/jvmti/jvmti_agent.c +++ b/tools/perf/jvmti/jvmti_agent.c @@ -374,20 +374,20 @@ jvmti_write_code(void *agent, char const *sym, int jvmti_write_debug_info(void *agent, uint64_t code, const char *file, - jvmtiAddrLocationMap const *map, - jvmtiLineNumberEntry *li, jint num) + jvmti_line_info_t *li, int nr_lines) { - static const char *prev_str = "\xff"; struct jr_code_debug_info rec; size_t sret, len, size, flen; size_t padding_count; + uint64_t addr; + const char *fn = file; FILE *fp = agent; int i; /* * no entry to write */ - if (!num) + if (!nr_lines) return 0; if (!fp) { @@ -401,17 +401,18 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, size = sizeof(rec); rec.p.timestamp = perf_get_timestamp(); rec.code_addr = (uint64_t)(uintptr_t)code; - rec.nr_entry = num; + rec.nr_entry = nr_lines; /* * on disk source line info layout: * uint64_t : addr * int : line number + * int : column discriminator * file[] : source file name * padding : pad to multiple of 8 bytes */ - size += num * (sizeof(uint64_t) + sizeof(int)); - size += flen + (num - 1) * 2; + size += nr_lines * sizeof(struct debug_entry); + size += flen * nr_lines; /* * pad to 8 bytes */ @@ -429,28 +430,27 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file, if (sret != 1) goto error; - for (i = 0; i < num; i++) { - uint64_t addr; + for (i = 0; i < nr_lines; i++) { - addr = (uint64_t)map[i].start_address; + addr = (uint64_t)li[i].pc; len = sizeof(addr); sret = fwrite_unlocked(&addr, len, 1, fp); if (sret != 1) goto error; - len = sizeof(int); + len = sizeof(li[0].line_number); sret = fwrite_unlocked(&li[i].line_number, len, 1, fp); if (sret != 1) goto error; - if (i == 0) { - sret = fwrite_unlocked(file, flen, 1, fp); - } else { - sret = fwrite_unlocked(prev_str, 2, 1, fp); - } + len = sizeof(li[0].discrim); + sret = fwrite_unlocked(&li[i].discrim, len, 1, fp); if (sret != 1) goto error; + sret = fwrite_unlocked(fn, flen, 1, fp); + if (sret != 1) + goto error; } if (padding_count) sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp); diff --git a/tools/perf/jvmti/jvmti_agent.h b/tools/perf/jvmti/jvmti_agent.h index 8251a1c5ee3f..bedf5d0ba9ff 100644 --- a/tools/perf/jvmti/jvmti_agent.h +++ b/tools/perf/jvmti/jvmti_agent.h @@ -11,16 +11,23 @@ extern "C" { #endif +typedef struct { + unsigned long pc; + int line_number; + int discrim; /* discriminator -- 0 for now */ +} jvmti_line_info_t; + void *jvmti_open(void); int jvmti_close(void *agent); int jvmti_write_code(void *agent, char const *symbol_name, uint64_t vma, void const *code, const unsigned int code_size); + int jvmti_write_debug_info(void *agent, uint64_t code, const char *file, - jvmtiAddrLocationMap const *map, - jvmtiLineNumberEntry *tab, jint nr); + jvmti_line_info_t *li, + int nr_lines); #if defined(__cplusplus) } diff --git a/tools/perf/jvmti/libjvmti.c b/tools/perf/jvmti/libjvmti.c index 92ffbe4ff160..ac12e4b91a92 100644 --- a/tools/perf/jvmti/libjvmti.c +++ b/tools/perf/jvmti/libjvmti.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "jvmti_agent.h" @@ -11,6 +12,100 @@ static int has_line_numbers; void *jvmti_agent; +static jvmtiError +do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, + jvmti_line_info_t *tab, jint *nr) +{ + jint i, lines = 0; + jint nr_lines = 0; + jvmtiLineNumberEntry *loc_tab = NULL; + jvmtiError ret; + + ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab); + if (ret != JVMTI_ERROR_NONE) + return ret; + + for (i = 0; i < nr_lines; i++) { + if (loc_tab[i].start_location < bci) { + tab[lines].pc = (unsigned long)pc; + tab[lines].line_number = loc_tab[i].line_number; + tab[lines].discrim = 0; /* not yet used */ + lines++; + } else { + break; + } + } + (*jvmti)->Deallocate(jvmti, (unsigned char *)loc_tab); + *nr = lines; + return JVMTI_ERROR_NONE; +} + +static jvmtiError +get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **tab, int *nr_lines) +{ + const jvmtiCompiledMethodLoadRecordHeader *hdr; + jvmtiCompiledMethodLoadInlineRecord *rec; + jvmtiLineNumberEntry *lne = NULL; + PCStackInfo *c; + jint nr, ret; + int nr_total = 0; + int i, lines_total = 0; + + if (!(tab && nr_lines)) + return JVMTI_ERROR_NULL_POINTER; + + /* + * Phase 1 -- get the number of lines necessary + */ + for (hdr = compile_info; hdr != NULL; hdr = hdr->next) { + if (hdr->kind == JVMTI_CMLR_INLINE_INFO) { + rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr; + for (i = 0; i < rec->numpcs; i++) { + c = rec->pcinfo + i; + nr = 0; + /* + * unfortunately, need a tab to get the number of lines! + */ + ret = (*jvmti)->GetLineNumberTable(jvmti, c->methods[0], &nr, &lne); + if (ret == JVMTI_ERROR_NONE) { + /* free what was allocated for nothing */ + (*jvmti)->Deallocate(jvmti, (unsigned char *)lne); + nr_total += (int)nr; + } + } + } + } + + if (nr_total == 0) + return JVMTI_ERROR_NOT_FOUND; + + /* + * Phase 2 -- allocate big enough line table + */ + *tab = malloc(nr_total * sizeof(**tab)); + if (!*tab) + return JVMTI_ERROR_OUT_OF_MEMORY; + + for (hdr = compile_info; hdr != NULL; hdr = hdr->next) { + if (hdr->kind == JVMTI_CMLR_INLINE_INFO) { + rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr; + for (i = 0; i < rec->numpcs; i++) { + c = rec->pcinfo + i; + nr = 0; + ret = do_get_line_numbers(jvmti, c->pc, + c->methods[0], + c->bcis[0], + *tab + lines_total, + &nr); + if (ret == JVMTI_ERROR_NONE) + lines_total += nr; + } + } + } + *nr_lines = lines_total; + return JVMTI_ERROR_NONE; +} + static void JNICALL compiled_method_load_cb(jvmtiEnv *jvmti, jmethodID method, @@ -18,9 +113,9 @@ compiled_method_load_cb(jvmtiEnv *jvmti, void const *code_addr, jint map_length, jvmtiAddrLocationMap const *map, - void const *compile_info __unused) + const void *compile_info) { - jvmtiLineNumberEntry *tab = NULL; + jvmti_line_info_t *line_tab = NULL; jclass decl_class; char *class_sign = NULL; char *func_name = NULL; @@ -29,7 +124,7 @@ compiled_method_load_cb(jvmtiEnv *jvmti, char fn[PATH_MAX]; uint64_t addr = (uint64_t)(uintptr_t)code_addr; jvmtiError ret; - jint nr_lines = 0; + int nr_lines = 0; /* in line_tab[] */ size_t len; ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, @@ -40,19 +135,19 @@ compiled_method_load_cb(jvmtiEnv *jvmti, } if (has_line_numbers && map && map_length) { - - ret = (*jvmti)->GetLineNumberTable(jvmti, method, &nr_lines, &tab); + ret = get_line_numbers(jvmti, compile_info, &line_tab, &nr_lines); if (ret != JVMTI_ERROR_NONE) { warnx("jvmti: cannot get line table for method"); - } else { - ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); - if (ret != JVMTI_ERROR_NONE) { - warnx("jvmti: cannot get source filename ret=%d", ret); - nr_lines = 0; - } + nr_lines = 0; } } + ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); + if (ret != JVMTI_ERROR_NONE) { + warnx("jvmti: cannot get source filename ret=%d", ret); + goto error; + } + ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL); if (ret != JVMTI_ERROR_NONE) { @@ -92,13 +187,14 @@ compiled_method_load_cb(jvmtiEnv *jvmti, /* * write source line info record if we have it */ - if (jvmti_write_debug_info(jvmti_agent, addr, fn, map, tab, nr_lines)) + if (jvmti_write_debug_info(jvmti_agent, addr, fn, line_tab, nr_lines)) warnx("jvmti: write_debug_info() failed"); len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2; { char str[len]; snprintf(str, len, "%s%s%s", class_sign, func_name, func_sign); + if (jvmti_write_code(jvmti_agent, str, addr, code_addr, code_size)) warnx("jvmti: write_code() failed"); } @@ -106,8 +202,8 @@ error: (*jvmti)->Deallocate(jvmti, (unsigned char *)func_name); (*jvmti)->Deallocate(jvmti, (unsigned char *)func_sign); (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); - (*jvmti)->Deallocate(jvmti, (unsigned char *)tab); (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); + free(line_tab); } static void JNICALL diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 52a4a806ee2f..a34752d28488 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -108,8 +108,11 @@ libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o +libperf-$(CONFIG_LIBELF) += genelf_debug.o CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" +# avoid compiler warnings in 32-bit mode +CFLAGS_genelf_debug.o += -Wno-packed $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c $(call rule_mkdir) diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c index 145f8116ef56..c1ef805c6a8f 100644 --- a/tools/perf/util/genelf.c +++ b/tools/perf/util/genelf.c @@ -156,7 +156,8 @@ gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *cod */ int jit_write_elf(int fd, uint64_t load_addr, const char *sym, - const void *code, int csize) + const void *code, int csize, + void *debug, int nr_debug_entries) { Elf *e; Elf_Data *d; @@ -385,9 +386,15 @@ jit_write_elf(int fd, uint64_t load_addr, const char *sym, shdr->sh_size = sizeof(bnote); shdr->sh_entsize = 0; - if (elf_update(e, ELF_C_WRITE) < 0) { - warnx("elf_update 4 failed"); - goto error; + if (debug && nr_debug_entries) { + retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries); + if (retval) + goto error; + } else { + if (elf_update(e, ELF_C_WRITE) < 0) { + warnx("elf_update 4 failed"); + goto error; + } } retval = 0; diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h index d8e9ece13c8b..45bf9c6d3257 100644 --- a/tools/perf/util/genelf.h +++ b/tools/perf/util/genelf.h @@ -3,7 +3,11 @@ /* genelf.c */ extern int jit_write_elf(int fd, uint64_t code_addr, const char *sym, - const void *code, int csize); + const void *code, int csize, + void *debug, int nr_debug_entries); +/* genelf_debug.c */ +extern int jit_add_debug_info(Elf *e, uint64_t code_addr, + void *debug, int nr_debug_entries); #if defined(__arm__) #define GEN_ELF_ARCH EM_ARM diff --git a/tools/perf/util/genelf_debug.c b/tools/perf/util/genelf_debug.c new file mode 100644 index 000000000000..5980f7d256b1 --- /dev/null +++ b/tools/perf/util/genelf_debug.c @@ -0,0 +1,610 @@ +/* + * genelf_debug.c + * Copyright (C) 2015, Google, Inc + * + * Contributed by: + * Stephane Eranian + * + * Released under the GPL v2. + * + * based on GPLv2 source code from Oprofile + * @remark Copyright 2007 OProfile authors + * @author Philippe Elie + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "perf.h" +#include "genelf.h" +#include "../util/jitdump.h" + +#define BUFFER_EXT_DFL_SIZE (4 * 1024) + +typedef uint32_t uword; +typedef uint16_t uhalf; +typedef int32_t sword; +typedef int16_t shalf; +typedef uint8_t ubyte; +typedef int8_t sbyte; + +struct buffer_ext { + size_t cur_pos; + size_t max_sz; + void *data; +}; + +static void +buffer_ext_dump(struct buffer_ext *be, const char *msg) +{ + size_t i; + warnx("DUMP for %s", msg); + for (i = 0 ; i < be->cur_pos; i++) + warnx("%4zu 0x%02x", i, (((char *)be->data)[i]) & 0xff); +} + +static inline int +buffer_ext_add(struct buffer_ext *be, void *addr, size_t sz) +{ + void *tmp; + size_t be_sz = be->max_sz; + +retry: + if ((be->cur_pos + sz) < be_sz) { + memcpy(be->data + be->cur_pos, addr, sz); + be->cur_pos += sz; + return 0; + } + + if (!be_sz) + be_sz = BUFFER_EXT_DFL_SIZE; + else + be_sz <<= 1; + + tmp = realloc(be->data, be_sz); + if (!tmp) + return -1; + + be->data = tmp; + be->max_sz = be_sz; + + goto retry; +} + +static void +buffer_ext_init(struct buffer_ext *be) +{ + be->data = NULL; + be->cur_pos = 0; + be->max_sz = 0; +} + +static inline size_t +buffer_ext_size(struct buffer_ext *be) +{ + return be->cur_pos; +} + +static inline void * +buffer_ext_addr(struct buffer_ext *be) +{ + return be->data; +} + +struct debug_line_header { + // Not counting this field + uword total_length; + // version number (2 currently) + uhalf version; + // relative offset from next field to + // program statement + uword prolog_length; + ubyte minimum_instruction_length; + ubyte default_is_stmt; + // line_base - see DWARF 2 specs + sbyte line_base; + // line_range - see DWARF 2 specs + ubyte line_range; + // number of opcode + 1 + ubyte opcode_base; + /* follow the array of opcode args nr: ubytes [nr_opcode_base] */ + /* follow the search directories index, zero terminated string + * terminated by an empty string. + */ + /* follow an array of { filename, LEB128, LEB128, LEB128 }, first is + * the directory index entry, 0 means current directory, then mtime + * and filesize, last entry is followed by en empty string. + */ + /* follow the first program statement */ +} __attribute__((packed)); + +/* DWARF 2 spec talk only about one possible compilation unit header while + * binutils can handle two flavours of dwarf 2, 32 and 64 bits, this is not + * related to the used arch, an ELF 32 can hold more than 4 Go of debug + * information. For now we handle only DWARF 2 32 bits comp unit. It'll only + * become a problem if we generate more than 4GB of debug information. + */ +struct compilation_unit_header { + uword total_length; + uhalf version; + uword debug_abbrev_offset; + ubyte pointer_size; +} __attribute__((packed)); + +#define DW_LNS_num_opcode (DW_LNS_set_isa + 1) + +/* field filled at run time are marked with -1 */ +static struct debug_line_header const default_debug_line_header = { + .total_length = -1, + .version = 2, + .prolog_length = -1, + .minimum_instruction_length = 1, /* could be better when min instruction size != 1 */ + .default_is_stmt = 1, /* we don't take care about basic block */ + .line_base = -5, /* sensible value for line base ... */ + .line_range = -14, /* ... and line range are guessed statically */ + .opcode_base = DW_LNS_num_opcode +}; + +static ubyte standard_opcode_length[] = +{ + 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 +}; +#if 0 +{ + [DW_LNS_advance_pc] = 1, + [DW_LNS_advance_line] = 1, + [DW_LNS_set_file] = 1, + [DW_LNS_set_column] = 1, + [DW_LNS_fixed_advance_pc] = 1, + [DW_LNS_set_isa] = 1, +}; +#endif + +/* field filled at run time are marked with -1 */ +static struct compilation_unit_header default_comp_unit_header = { + .total_length = -1, + .version = 2, + .debug_abbrev_offset = 0, /* we reuse the same abbrev entries for all comp unit */ + .pointer_size = sizeof(void *) +}; + +static void emit_uword(struct buffer_ext *be, uword data) +{ + buffer_ext_add(be, &data, sizeof(uword)); +} + +static void emit_string(struct buffer_ext *be, const char *s) +{ + buffer_ext_add(be, (void *)s, strlen(s) + 1); +} + +static void emit_unsigned_LEB128(struct buffer_ext *be, + unsigned long data) +{ + do { + ubyte cur = data & 0x7F; + data >>= 7; + if (data) + cur |= 0x80; + buffer_ext_add(be, &cur, 1); + } while (data); +} + +static void emit_signed_LEB128(struct buffer_ext *be, long data) +{ + int more = 1; + int negative = data < 0; + int size = sizeof(long) * CHAR_BIT; + while (more) { + ubyte cur = data & 0x7F; + data >>= 7; + if (negative) + data |= - (1 << (size - 7)); + if ((data == 0 && !(cur & 0x40)) || + (data == -1l && (cur & 0x40))) + more = 0; + else + cur |= 0x80; + buffer_ext_add(be, &cur, 1); + } +} + +static void emit_extended_opcode(struct buffer_ext *be, ubyte opcode, + void *data, size_t data_len) +{ + buffer_ext_add(be, (char *)"", 1); + + emit_unsigned_LEB128(be, data_len + 1); + + buffer_ext_add(be, &opcode, 1); + buffer_ext_add(be, data, data_len); +} + +static void emit_opcode(struct buffer_ext *be, ubyte opcode) +{ + buffer_ext_add(be, &opcode, 1); +} + +static void emit_opcode_signed(struct buffer_ext *be, + ubyte opcode, long data) +{ + buffer_ext_add(be, &opcode, 1); + emit_signed_LEB128(be, data); +} + +static void emit_opcode_unsigned(struct buffer_ext *be, ubyte opcode, + unsigned long data) +{ + buffer_ext_add(be, &opcode, 1); + emit_unsigned_LEB128(be, data); +} + +static void emit_advance_pc(struct buffer_ext *be, unsigned long delta_pc) +{ + emit_opcode_unsigned(be, DW_LNS_advance_pc, delta_pc); +} + +static void emit_advance_lineno(struct buffer_ext *be, long delta_lineno) +{ + emit_opcode_signed(be, DW_LNS_advance_line, delta_lineno); +} + +static void emit_lne_end_of_sequence(struct buffer_ext *be) +{ + emit_extended_opcode(be, DW_LNE_end_sequence, NULL, 0); +} + +static void emit_set_file(struct buffer_ext *be, unsigned long idx) +{ + emit_opcode_unsigned(be, DW_LNS_set_file, idx); +} + +static void emit_lne_define_filename(struct buffer_ext *be, + const char *filename) +{ + buffer_ext_add(be, (void *)"", 1); + + /* LNE field, strlen(filename) + zero termination, 3 bytes for: the dir entry, timestamp, filesize */ + emit_unsigned_LEB128(be, strlen(filename) + 5); + emit_opcode(be, DW_LNE_define_file); + emit_string(be, filename); + /* directory index 0=do not know */ + emit_unsigned_LEB128(be, 0); + /* last modification date on file 0=do not know */ + emit_unsigned_LEB128(be, 0); + /* filesize 0=do not know */ + emit_unsigned_LEB128(be, 0); +} + +static void emit_lne_set_address(struct buffer_ext *be, + void *address) +{ + emit_extended_opcode(be, DW_LNE_set_address, &address, sizeof(unsigned long)); +} + +static ubyte get_special_opcode(struct debug_entry *ent, + unsigned int last_line, + unsigned long last_vma) +{ + unsigned int temp; + unsigned long delta_addr; + + /* + * delta from line_base + */ + temp = (ent->lineno - last_line) - default_debug_line_header.line_base; + + if (temp >= default_debug_line_header.line_range) + return 0; + + /* + * delta of addresses + */ + delta_addr = (ent->addr - last_vma) / default_debug_line_header.minimum_instruction_length; + + /* This is not sufficient to ensure opcode will be in [0-256] but + * sufficient to ensure when summing with the delta lineno we will + * not overflow the unsigned long opcode */ + + if (delta_addr <= 256 / default_debug_line_header.line_range) { + unsigned long opcode = temp + + (delta_addr * default_debug_line_header.line_range) + + default_debug_line_header.opcode_base; + + return opcode <= 255 ? opcode : 0; + } + return 0; +} + +static void emit_lineno_info(struct buffer_ext *be, + struct debug_entry *ent, size_t nr_entry, + unsigned long code_addr) +{ + size_t i; + + /* + * Machine state at start of a statement program + * address = 0 + * file = 1 + * line = 1 + * column = 0 + * is_stmt = default_is_stmt as given in the debug_line_header + * basic block = 0 + * end sequence = 0 + */ + + /* start state of the state machine we take care of */ + unsigned long last_vma = code_addr; + char const *cur_filename = NULL; + unsigned long cur_file_idx = 0; + int last_line = 1; + + emit_lne_set_address(be, (void *)code_addr); + + for (i = 0; i < nr_entry; i++, ent = debug_entry_next(ent)) { + int need_copy = 0; + ubyte special_opcode; + + /* + * check if filename changed, if so add it + */ + if (!cur_filename || strcmp(cur_filename, ent->name)) { + emit_lne_define_filename(be, ent->name); + cur_filename = ent->name; + emit_set_file(be, ++cur_file_idx); + need_copy = 1; + } + + special_opcode = get_special_opcode(ent, last_line, last_vma); + if (special_opcode != 0) { + last_line = ent->lineno; + last_vma = ent->addr; + emit_opcode(be, special_opcode); + } else { + /* + * lines differ, emit line delta + */ + if (last_line != ent->lineno) { + emit_advance_lineno(be, ent->lineno - last_line); + last_line = ent->lineno; + need_copy = 1; + } + /* + * addresses differ, emit address delta + */ + if (last_vma != ent->addr) { + emit_advance_pc(be, ent->addr - last_vma); + last_vma = ent->addr; + need_copy = 1; + } + /* + * add new row to matrix + */ + if (need_copy) + emit_opcode(be, DW_LNS_copy); + } + } +} + +static void add_debug_line(struct buffer_ext *be, + struct debug_entry *ent, size_t nr_entry, + unsigned long code_addr) +{ + struct debug_line_header * dbg_header; + size_t old_size; + + old_size = buffer_ext_size(be); + + buffer_ext_add(be, (void *)&default_debug_line_header, + sizeof(default_debug_line_header)); + + buffer_ext_add(be, &standard_opcode_length, sizeof(standard_opcode_length)); + + // empty directory entry + buffer_ext_add(be, (void *)"", 1); + + // empty filename directory + buffer_ext_add(be, (void *)"", 1); + + dbg_header = buffer_ext_addr(be) + old_size; + dbg_header->prolog_length = (buffer_ext_size(be) - old_size) - + offsetof(struct debug_line_header, minimum_instruction_length); + + emit_lineno_info(be, ent, nr_entry, code_addr); + + emit_lne_end_of_sequence(be); + + dbg_header = buffer_ext_addr(be) + old_size; + dbg_header->total_length = (buffer_ext_size(be) - old_size) - + offsetof(struct debug_line_header, version); +} + +static void +add_debug_abbrev(struct buffer_ext *be) +{ + emit_unsigned_LEB128(be, 1); + emit_unsigned_LEB128(be, DW_TAG_compile_unit); + emit_unsigned_LEB128(be, DW_CHILDREN_yes); + emit_unsigned_LEB128(be, DW_AT_stmt_list); + emit_unsigned_LEB128(be, DW_FORM_data4); + emit_unsigned_LEB128(be, 0); + emit_unsigned_LEB128(be, 0); + emit_unsigned_LEB128(be, 0); +} + +static void +add_compilation_unit(struct buffer_ext *be, + size_t offset_debug_line) +{ + struct compilation_unit_header *comp_unit_header; + size_t old_size = buffer_ext_size(be); + + buffer_ext_add(be, &default_comp_unit_header, + sizeof(default_comp_unit_header)); + + emit_unsigned_LEB128(be, 1); + emit_uword(be, offset_debug_line); + + comp_unit_header = buffer_ext_addr(be) + old_size; + comp_unit_header->total_length = (buffer_ext_size(be) - old_size) - + offsetof(struct compilation_unit_header, version); +} + +static int +jit_process_debug_info(uint64_t code_addr, + void *debug, int nr_debug_entries, + struct buffer_ext *dl, + struct buffer_ext *da, + struct buffer_ext *di) +{ + struct debug_entry *ent = debug; + int i; + + for (i = 0; i < nr_debug_entries; i++) { + ent->addr = ent->addr - code_addr; + ent = debug_entry_next(ent); + } + add_compilation_unit(di, buffer_ext_size(dl)); + add_debug_line(dl, debug, nr_debug_entries, 0); + add_debug_abbrev(da); + if (0) buffer_ext_dump(da, "abbrev"); + + return 0; +} + +int +jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries) +{ + Elf_Data *d; + Elf_Scn *scn; + Elf_Shdr *shdr; + struct buffer_ext dl, di, da; + int ret; + + buffer_ext_init(&dl); + buffer_ext_init(&di); + buffer_ext_init(&da); + + ret = jit_process_debug_info(code_addr, debug, nr_debug_entries, &dl, &da, &di); + if (ret) + return -1; + /* + * setup .debug_line section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + return -1; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + return -1; + } + + d->d_align = 1; + d->d_off = 0LL; + d->d_buf = buffer_ext_addr(&dl); + d->d_type = ELF_T_BYTE; + d->d_size = buffer_ext_size(&dl); + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + return -1; + } + + shdr->sh_name = 52; /* .debug_line */ + shdr->sh_type = SHT_PROGBITS; + shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */ + shdr->sh_flags = 0; + shdr->sh_entsize = 0; + + /* + * setup .debug_info section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + return -1; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + return -1; + } + + d->d_align = 1; + d->d_off = 0LL; + d->d_buf = buffer_ext_addr(&di); + d->d_type = ELF_T_BYTE; + d->d_size = buffer_ext_size(&di); + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + return -1; + } + + shdr->sh_name = 64; /* .debug_info */ + shdr->sh_type = SHT_PROGBITS; + shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */ + shdr->sh_flags = 0; + shdr->sh_entsize = 0; + + /* + * setup .debug_abbrev section + */ + scn = elf_newscn(e); + if (!scn) { + warnx("cannot create section"); + return -1; + } + + d = elf_newdata(scn); + if (!d) { + warnx("cannot get new data"); + return -1; + } + + d->d_align = 1; + d->d_off = 0LL; + d->d_buf = buffer_ext_addr(&da); + d->d_type = ELF_T_BYTE; + d->d_size = buffer_ext_size(&da); + d->d_version = EV_CURRENT; + + shdr = elf_getshdr(scn); + if (!shdr) { + warnx("cannot get section header"); + return -1; + } + + shdr->sh_name = 76; /* .debug_info */ + shdr->sh_type = SHT_PROGBITS; + shdr->sh_addr = 0; /* must be zero or == sh_offset -> dynamic object */ + shdr->sh_flags = 0; + shdr->sh_entsize = 0; + + /* + * now we update the ELF image with all the sections + */ + if (elf_update(e, ELF_C_WRITE) < 0) { + warnx("elf_update debug failed"); + return -1; + } + return 0; +} diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 9f7a01289efe..99fa5eee9fe0 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -63,7 +63,9 @@ jit_emit_elf(char *filename, const char *sym, uint64_t code_addr, const void *code, - int csize) + int csize, + void *debug, + int nr_debug_entries) { int ret, fd; @@ -76,7 +78,7 @@ jit_emit_elf(char *filename, return -1; } - ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize); + ret = jit_write_elf(fd, code_addr, sym, (const void *)code, csize, debug, nr_debug_entries); close(fd); @@ -347,7 +349,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) size = PERF_ALIGN(size, sizeof(u64)); uaddr = (uintptr_t)code; - ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize); + ret = jit_emit_elf(filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries); if (jd->debug_data && jd->nr_debug_entries) { free(jd->debug_data); -- cgit From a3ff9582369e71439ad2bf40e70474b9f1b85c55 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Feb 2016 16:46:26 +0200 Subject: spi: dw-mid: switch to new dmaengine_terminate_* API Convert dmaengine_terminate_all() calls to synchronous versions. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-dw-mid.c b/drivers/spi/spi-dw-mid.c index 9185f6c08459..e31971f91475 100644 --- a/drivers/spi/spi-dw-mid.c +++ b/drivers/spi/spi-dw-mid.c @@ -89,10 +89,10 @@ static void mid_spi_dma_exit(struct dw_spi *dws) if (!dws->dma_inited) return; - dmaengine_terminate_all(dws->txchan); + dmaengine_terminate_sync(dws->txchan); dma_release_channel(dws->txchan); - dmaengine_terminate_all(dws->rxchan); + dmaengine_terminate_sync(dws->rxchan); dma_release_channel(dws->rxchan); } -- cgit From 2f6fdefb3503ff0600b5435c0c9ce43cb50d3f1a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Feb 2016 16:54:10 +0200 Subject: spi: dw-mmio: remove message which is handled by core devm_ioremap_resource() validates its parameters and issues an error message if needed. Signed-off-by: Andy Shevchenko Signed-off-by: Mark Brown --- drivers/spi/spi-dw-mmio.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index a6d7029a85ac..447497e9124c 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -47,11 +47,6 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) /* Get basic io resource and map it */ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -EINVAL; - } - dws->regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(dws->regs)) { dev_err(&pdev->dev, "SPI region map failed\n"); -- cgit From 2ec3b6287b12a7131c28cd9408b368cd451bdc48 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 4 Feb 2016 17:13:29 +0100 Subject: spi: axi: Add bindings documentation for Analog Devices axi-spi-engine Add the devicetree bindings documentation for the Analog Devices axi-spi-engine SPI master peripheral. This is a soft-peripheral used in FPGAs. The external interfaces of the peripheral are: * A memory mapped register map which is used to configure the peripheral. * One interrupt. * Two clocks, one for the memory mapped register interface and one for the SPI bus. * A SPI master interface to which the slave devices are connected. These interfaces are described by the devicetree bindings accordingly. Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/adi,axi-spi-engine.txt | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt diff --git a/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt b/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt new file mode 100644 index 000000000000..8a18d71e6879 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.txt @@ -0,0 +1,31 @@ +Analog Devices AXI SPI Engine controller Device Tree Bindings + +Required properties: +- compatible : Must be "adi,axi-spi-engine-1.00.a"" +- reg : Physical base address and size of the register map. +- interrupts : Property with a value describing the interrupt + number. +- clock-names : List of input clock names - "s_axi_aclk", "spi_clk" +- clocks : Clock phandles and specifiers (See clock bindings for + details on clock-names and clocks). +- #address-cells : Must be <1> +- #size-cells : Must be <0> + +Optional subnodes: + Subnodes are use to represent the SPI slave devices connected to the SPI + master. They follow the generic SPI bindings as outlined in spi-bus.txt. + +Example: + + spi@@44a00000 { + compatible = "adi,axi-spi-engine-1.00.a"; + reg = <0x44a00000 0x1000>; + interrupts = <0 56 4>; + clocks = <&clkc 15 &clkc 15>; + clock-names = "s_axi_aclk", "spi_clk"; + + #address-cells = <1>; + #size-cells = <0>; + + /* SPI devices */ + }; -- cgit From b1353d1c1d4555b7c40066fa2cacc7da266e9904 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 4 Feb 2016 17:13:30 +0100 Subject: spi: Add Analog Devices AXI SPI Engine controller support This patch adds support for the AXI SPI Engine controller which is a FPGA soft-peripheral which is used in some of Analog Devices' reference designs. The AXI SPI Engine controller is part of the SPI Engine framework[1] and allows memory mapped access to the SPI Engine control bus. This allows it to be used as a general purpose software driven SPI controller. The SPI Engine in addition offers some optional advanced acceleration and offloading capabilities, which are not part of this patch though and will be introduced separately. At the core of the SPI Engine framework is a small sort of co-processor that accepts a command stream and turns the commands into low-level SPI transactions. Communication is done through three memory mapped FIFOs in the register map of the AXI SPI Engine peripheral. One FIFO for the command stream and one each for transmit and receive data. The driver translates a spi_message in a command stream and writes it to the peripheral which executes it asynchronously. This allows it to perform very precise timings which are required for some SPI slave devices to achieve maximum performance (e.g. analog-to-digital and digital-to-analog converters). The execution flow is synchronized to the host system by a special synchronize instruction which generates a interrupt. [1] https://wiki.analog.com/resources/fpga/peripherals/spi_engine Signed-off-by: Lars-Peter Clausen Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/spi-axi-spi-engine.c | 591 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 600 insertions(+) create mode 100644 drivers/spi/spi-axi-spi-engine.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 7caf18cb3e5e..d84adceb9b89 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -83,6 +83,14 @@ config SPI_AU1550 If you say yes to this option, support will be included for the PSC SPI controller found on Au1550, Au1200 and Au1300 series. +config SPI_AXI_SPI_ENGINE + tristate "Analog Devices AXI SPI Engine controller" + depends on HAS_IOMEM + help + This enables support for the Analog Devices AXI SPI Engine SPI controller. + It is part of the SPI Engine framework that is used in some Analog Devices + reference designs for FPGAs. + config SPI_BCM2835 tristate "BCM2835 SPI controller" depends on GPIOLIB diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 8991ffce6e12..7ad880684a85 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o +obj-$(CONFIG_SPI_AXI_SPI_ENGINE) += spi-axi-spi-engine.o obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM2835AUX) += spi-bcm2835aux.o obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c new file mode 100644 index 000000000000..c968ab210a51 --- /dev/null +++ b/drivers/spi/spi-axi-spi-engine.c @@ -0,0 +1,591 @@ +/* + * SPI-Engine SPI controller driver + * Copyright 2015 Analog Devices Inc. + * Author: Lars-Peter Clausen + * + * Licensed under the GPL-2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) +#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) +#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) + +#define SPI_ENGINE_REG_VERSION 0x00 + +#define SPI_ENGINE_REG_RESET 0x40 + +#define SPI_ENGINE_REG_INT_ENABLE 0x80 +#define SPI_ENGINE_REG_INT_PENDING 0x84 +#define SPI_ENGINE_REG_INT_SOURCE 0x88 + +#define SPI_ENGINE_REG_SYNC_ID 0xc0 + +#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xd0 +#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xd4 +#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xd8 + +#define SPI_ENGINE_REG_CMD_FIFO 0xe0 +#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xe4 +#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xe8 +#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xec + +#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) +#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) +#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) +#define SPI_ENGINE_INT_SYNC BIT(3) + +#define SPI_ENGINE_CONFIG_CPHA BIT(0) +#define SPI_ENGINE_CONFIG_CPOL BIT(1) +#define SPI_ENGINE_CONFIG_3WIRE BIT(2) + +#define SPI_ENGINE_INST_TRANSFER 0x0 +#define SPI_ENGINE_INST_ASSERT 0x1 +#define SPI_ENGINE_INST_WRITE 0x2 +#define SPI_ENGINE_INST_MISC 0x3 + +#define SPI_ENGINE_CMD_REG_CLK_DIV 0x0 +#define SPI_ENGINE_CMD_REG_CONFIG 0x1 + +#define SPI_ENGINE_MISC_SYNC 0x0 +#define SPI_ENGINE_MISC_SLEEP 0x1 + +#define SPI_ENGINE_TRANSFER_WRITE 0x1 +#define SPI_ENGINE_TRANSFER_READ 0x2 + +#define SPI_ENGINE_CMD(inst, arg1, arg2) \ + (((inst) << 12) | ((arg1) << 8) | (arg2)) + +#define SPI_ENGINE_CMD_TRANSFER(flags, n) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, (flags), (n)) +#define SPI_ENGINE_CMD_ASSERT(delay, cs) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, (delay), (cs)) +#define SPI_ENGINE_CMD_WRITE(reg, val) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_WRITE, (reg), (val)) +#define SPI_ENGINE_CMD_SLEEP(delay) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SLEEP, (delay)) +#define SPI_ENGINE_CMD_SYNC(id) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, SPI_ENGINE_MISC_SYNC, (id)) + +struct spi_engine_program { + unsigned int length; + uint16_t instructions[]; +}; + +struct spi_engine { + struct clk *clk; + struct clk *ref_clk; + + spinlock_t lock; + + void __iomem *base; + + struct spi_message *msg; + struct spi_engine_program *p; + unsigned cmd_length; + const uint16_t *cmd_buf; + + struct spi_transfer *tx_xfer; + unsigned int tx_length; + const uint8_t *tx_buf; + + struct spi_transfer *rx_xfer; + unsigned int rx_length; + uint8_t *rx_buf; + + unsigned int sync_id; + unsigned int completed_id; + + unsigned int int_enable; +}; + +static void spi_engine_program_add_cmd(struct spi_engine_program *p, + bool dry, uint16_t cmd) +{ + if (!dry) + p->instructions[p->length] = cmd; + p->length++; +} + +static unsigned int spi_engine_get_config(struct spi_device *spi) +{ + unsigned int config = 0; + + if (spi->mode & SPI_CPOL) + config |= SPI_ENGINE_CONFIG_CPOL; + if (spi->mode & SPI_CPHA) + config |= SPI_ENGINE_CONFIG_CPHA; + if (spi->mode & SPI_3WIRE) + config |= SPI_ENGINE_CONFIG_3WIRE; + + return config; +} + +static unsigned int spi_engine_get_clk_div(struct spi_engine *spi_engine, + struct spi_device *spi, struct spi_transfer *xfer) +{ + unsigned int clk_div; + + clk_div = DIV_ROUND_UP(clk_get_rate(spi_engine->ref_clk), + xfer->speed_hz * 2); + if (clk_div > 255) + clk_div = 255; + else if (clk_div > 0) + clk_div -= 1; + + return clk_div; +} + +static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, + struct spi_transfer *xfer) +{ + unsigned int len = xfer->len; + + while (len) { + unsigned int n = min(len, 256U); + unsigned int flags = 0; + + if (xfer->tx_buf) + flags |= SPI_ENGINE_TRANSFER_WRITE; + if (xfer->rx_buf) + flags |= SPI_ENGINE_TRANSFER_READ; + + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_TRANSFER(flags, n - 1)); + len -= n; + } +} + +static void spi_engine_gen_sleep(struct spi_engine_program *p, bool dry, + struct spi_engine *spi_engine, unsigned int clk_div, unsigned int delay) +{ + unsigned int spi_clk = clk_get_rate(spi_engine->ref_clk); + unsigned int t; + + if (delay == 0) + return; + + t = DIV_ROUND_UP(delay * spi_clk, (clk_div + 1) * 2); + while (t) { + unsigned int n = min(t, 256U); + + spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_SLEEP(n - 1)); + t -= n; + } +} + +static void spi_engine_gen_cs(struct spi_engine_program *p, bool dry, + struct spi_device *spi, bool assert) +{ + unsigned int mask = 0xff; + + if (assert) + mask ^= BIT(spi->chip_select); + + spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_ASSERT(1, mask)); +} + +static int spi_engine_compile_message(struct spi_engine *spi_engine, + struct spi_message *msg, bool dry, struct spi_engine_program *p) +{ + struct spi_device *spi = msg->spi; + struct spi_transfer *xfer; + int clk_div, new_clk_div; + bool cs_change = true; + + clk_div = -1; + + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG, + spi_engine_get_config(spi))); + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + new_clk_div = spi_engine_get_clk_div(spi_engine, spi, xfer); + if (new_clk_div != clk_div) { + clk_div = new_clk_div; + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CLK_DIV, + clk_div)); + } + + if (cs_change) + spi_engine_gen_cs(p, dry, spi, true); + + spi_engine_gen_xfer(p, dry, xfer); + spi_engine_gen_sleep(p, dry, spi_engine, clk_div, + xfer->delay_usecs); + + cs_change = xfer->cs_change; + if (list_is_last(&xfer->transfer_list, &msg->transfers)) + cs_change = !cs_change; + + if (cs_change) + spi_engine_gen_cs(p, dry, spi, false); + } + + return 0; +} + +static void spi_engine_xfer_next(struct spi_engine *spi_engine, + struct spi_transfer **_xfer) +{ + struct spi_message *msg = spi_engine->msg; + struct spi_transfer *xfer = *_xfer; + + if (!xfer) { + xfer = list_first_entry(&msg->transfers, + struct spi_transfer, transfer_list); + } else if (list_is_last(&xfer->transfer_list, &msg->transfers)) { + xfer = NULL; + } else { + xfer = list_next_entry(xfer, transfer_list); + } + + *_xfer = xfer; +} + +static void spi_engine_tx_next(struct spi_engine *spi_engine) +{ + struct spi_transfer *xfer = spi_engine->tx_xfer; + + do { + spi_engine_xfer_next(spi_engine, &xfer); + } while (xfer && !xfer->tx_buf); + + spi_engine->tx_xfer = xfer; + if (xfer) { + spi_engine->tx_length = xfer->len; + spi_engine->tx_buf = xfer->tx_buf; + } else { + spi_engine->tx_buf = NULL; + } +} + +static void spi_engine_rx_next(struct spi_engine *spi_engine) +{ + struct spi_transfer *xfer = spi_engine->rx_xfer; + + do { + spi_engine_xfer_next(spi_engine, &xfer); + } while (xfer && !xfer->rx_buf); + + spi_engine->rx_xfer = xfer; + if (xfer) { + spi_engine->rx_length = xfer->len; + spi_engine->rx_buf = xfer->rx_buf; + } else { + spi_engine->rx_buf = NULL; + } +} + +static bool spi_engine_write_cmd_fifo(struct spi_engine *spi_engine) +{ + void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_CMD_FIFO; + unsigned int n, m, i; + const uint16_t *buf; + + n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_CMD_FIFO_ROOM); + while (n && spi_engine->cmd_length) { + m = min(n, spi_engine->cmd_length); + buf = spi_engine->cmd_buf; + for (i = 0; i < m; i++) + writel_relaxed(buf[i], addr); + spi_engine->cmd_buf += m; + spi_engine->cmd_length -= m; + n -= m; + } + + return spi_engine->cmd_length != 0; +} + +static bool spi_engine_write_tx_fifo(struct spi_engine *spi_engine) +{ + void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDO_DATA_FIFO; + unsigned int n, m, i; + const uint8_t *buf; + + n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDO_FIFO_ROOM); + while (n && spi_engine->tx_length) { + m = min(n, spi_engine->tx_length); + buf = spi_engine->tx_buf; + for (i = 0; i < m; i++) + writel_relaxed(buf[i], addr); + spi_engine->tx_buf += m; + spi_engine->tx_length -= m; + n -= m; + if (spi_engine->tx_length == 0) + spi_engine_tx_next(spi_engine); + } + + return spi_engine->tx_length != 0; +} + +static bool spi_engine_read_rx_fifo(struct spi_engine *spi_engine) +{ + void __iomem *addr = spi_engine->base + SPI_ENGINE_REG_SDI_DATA_FIFO; + unsigned int n, m, i; + uint8_t *buf; + + n = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_SDI_FIFO_LEVEL); + while (n && spi_engine->rx_length) { + m = min(n, spi_engine->rx_length); + buf = spi_engine->rx_buf; + for (i = 0; i < m; i++) + buf[i] = readl_relaxed(addr); + spi_engine->rx_buf += m; + spi_engine->rx_length -= m; + n -= m; + if (spi_engine->rx_length == 0) + spi_engine_rx_next(spi_engine); + } + + return spi_engine->rx_length != 0; +} + +static irqreturn_t spi_engine_irq(int irq, void *devid) +{ + struct spi_master *master = devid; + struct spi_engine *spi_engine = spi_master_get_devdata(master); + unsigned int disable_int = 0; + unsigned int pending; + + pending = readl_relaxed(spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + + if (pending & SPI_ENGINE_INT_SYNC) { + writel_relaxed(SPI_ENGINE_INT_SYNC, + spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + spi_engine->completed_id = readl_relaxed( + spi_engine->base + SPI_ENGINE_REG_SYNC_ID); + } + + spin_lock(&spi_engine->lock); + + if (pending & SPI_ENGINE_INT_CMD_ALMOST_EMPTY) { + if (!spi_engine_write_cmd_fifo(spi_engine)) + disable_int |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY; + } + + if (pending & SPI_ENGINE_INT_SDO_ALMOST_EMPTY) { + if (!spi_engine_write_tx_fifo(spi_engine)) + disable_int |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY; + } + + if (pending & (SPI_ENGINE_INT_SDI_ALMOST_FULL | SPI_ENGINE_INT_SYNC)) { + if (!spi_engine_read_rx_fifo(spi_engine)) + disable_int |= SPI_ENGINE_INT_SDI_ALMOST_FULL; + } + + if (pending & SPI_ENGINE_INT_SYNC) { + if (spi_engine->msg && + spi_engine->completed_id == spi_engine->sync_id) { + struct spi_message *msg = spi_engine->msg; + + kfree(spi_engine->p); + msg->status = 0; + msg->actual_length = msg->frame_length; + spi_engine->msg = NULL; + spi_finalize_current_message(master); + disable_int |= SPI_ENGINE_INT_SYNC; + } + } + + if (disable_int) { + spi_engine->int_enable &= ~disable_int; + writel_relaxed(spi_engine->int_enable, + spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + } + + spin_unlock(&spi_engine->lock); + + return IRQ_HANDLED; +} + +static int spi_engine_transfer_one_message(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_engine_program p_dry, *p; + struct spi_engine *spi_engine = spi_master_get_devdata(master); + unsigned int int_enable = 0; + unsigned long flags; + size_t size; + + p_dry.length = 0; + spi_engine_compile_message(spi_engine, msg, true, &p_dry); + + size = sizeof(*p->instructions) * (p_dry.length + 1); + p = kzalloc(sizeof(*p) + size, GFP_KERNEL); + if (!p) + return -ENOMEM; + spi_engine_compile_message(spi_engine, msg, false, p); + + spin_lock_irqsave(&spi_engine->lock, flags); + spi_engine->sync_id = (spi_engine->sync_id + 1) & 0xff; + spi_engine_program_add_cmd(p, false, + SPI_ENGINE_CMD_SYNC(spi_engine->sync_id)); + + spi_engine->msg = msg; + spi_engine->p = p; + + spi_engine->cmd_buf = p->instructions; + spi_engine->cmd_length = p->length; + if (spi_engine_write_cmd_fifo(spi_engine)) + int_enable |= SPI_ENGINE_INT_CMD_ALMOST_EMPTY; + + spi_engine_tx_next(spi_engine); + if (spi_engine_write_tx_fifo(spi_engine)) + int_enable |= SPI_ENGINE_INT_SDO_ALMOST_EMPTY; + + spi_engine_rx_next(spi_engine); + if (spi_engine->rx_length != 0) + int_enable |= SPI_ENGINE_INT_SDI_ALMOST_FULL; + + int_enable |= SPI_ENGINE_INT_SYNC; + + writel_relaxed(int_enable, + spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + spi_engine->int_enable = int_enable; + spin_unlock_irqrestore(&spi_engine->lock, flags); + + return 0; +} + +static int spi_engine_probe(struct platform_device *pdev) +{ + struct spi_engine *spi_engine; + struct spi_master *master; + unsigned int version; + struct resource *res; + int irq; + int ret; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + return -ENXIO; + + spi_engine = devm_kzalloc(&pdev->dev, sizeof(*spi_engine), GFP_KERNEL); + if (!spi_engine) + return -ENOMEM; + + master = spi_alloc_master(&pdev->dev, 0); + if (!master) + return -ENOMEM; + + spi_master_set_devdata(master, spi_engine); + + spin_lock_init(&spi_engine->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + spi_engine->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(spi_engine->base)) { + ret = PTR_ERR(spi_engine->base); + goto err_put_master; + } + + version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION); + if (SPI_ENGINE_VERSION_MAJOR(version) != 1) { + dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n", + SPI_ENGINE_VERSION_MAJOR(version), + SPI_ENGINE_VERSION_MINOR(version), + SPI_ENGINE_VERSION_PATCH(version)); + return -ENODEV; + } + + spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); + if (IS_ERR(spi_engine->clk)) { + ret = PTR_ERR(spi_engine->clk); + goto err_put_master; + } + + spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk"); + if (IS_ERR(spi_engine->ref_clk)) { + ret = PTR_ERR(spi_engine->ref_clk); + goto err_put_master; + } + + ret = clk_prepare_enable(spi_engine->clk); + if (ret) + goto err_put_master; + + ret = clk_prepare_enable(spi_engine->ref_clk); + if (ret) + goto err_clk_disable; + + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET); + writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + + ret = request_irq(irq, spi_engine_irq, 0, pdev->name, master); + 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); + master->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; + master->transfer_one_message = spi_engine_transfer_one_message; + master->num_chipselect = 8; + + ret = spi_register_master(master); + if (ret) + goto err_free_irq; + + platform_set_drvdata(pdev, master); + + return 0; +err_free_irq: + free_irq(irq, master); +err_ref_clk_disable: + clk_disable_unprepare(spi_engine->ref_clk); +err_clk_disable: + clk_disable_unprepare(spi_engine->clk); +err_put_master: + spi_master_put(master); + return ret; +} + +static int spi_engine_remove(struct platform_device *pdev) +{ + struct spi_master *master = platform_get_drvdata(pdev); + struct spi_engine *spi_engine = spi_master_get_devdata(master); + int irq = platform_get_irq(pdev, 0); + + spi_unregister_master(master); + + free_irq(irq, master); + + writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); + writel_relaxed(0x01, spi_engine->base + SPI_ENGINE_REG_RESET); + + clk_disable_unprepare(spi_engine->ref_clk); + clk_disable_unprepare(spi_engine->clk); + + return 0; +} + +static const struct of_device_id spi_engine_match_table[] = { + { .compatible = "adi,axi-spi-engine-1.00.a" }, + { }, +}; + +static struct platform_driver spi_engine_driver = { + .probe = spi_engine_probe, + .remove = spi_engine_remove, + .driver = { + .name = "spi-engine", + .of_match_table = spi_engine_match_table, + }, +}; +module_platform_driver(spi_engine_driver); + +MODULE_AUTHOR("Lars-Peter Clausen "); +MODULE_DESCRIPTION("Analog Devices SPI engine peripheral driver"); +MODULE_LICENSE("GPL"); -- cgit From 38c09961048b853afd9429c9b57685a1511bc857 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Fri, 5 Feb 2016 12:33:30 +0800 Subject: regulator: act8945a: add regulator driver for ACT8945A This patch adds new regulator driver to support ACT8945A MFD chip's regulators. The ACT8945A has three step-down DC/DC converters and four low-dropout regulators. Signed-off-by: Wenyou Yang Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 ++ drivers/regulator/Makefile | 1 + drivers/regulator/act8945a-regulator.c | 165 +++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/regulator/act8945a-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8155e80dd3f8..74a6354eaefa 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -78,6 +78,15 @@ config REGULATOR_ACT8865 This driver controls a active-semi act8865 voltage output regulator via I2C bus. +config REGULATOR_ACT8945A + tristate "Active-semi ACT8945A voltage regulator" + depends on MFD_ACT8945A + help + This driver controls a active-semi ACT8945A voltage regulator + via I2C bus. The ACT8945A features three step-down DC/DC converters + and four low-dropout linear regulators, along with a ActivePath + battery charger. + config REGULATOR_AD5398 tristate "Analog Devices AD5398/AD5821 regulators" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 980b1943fa81..348cfd727350 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o obj-$(CONFIG_REGULATOR_ACT8865) += act8865-regulator.o +obj-$(CONFIG_REGULATOR_ACT8945A) += act8945a-regulator.o obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c new file mode 100644 index 000000000000..441864b9fece --- /dev/null +++ b/drivers/regulator/act8945a-regulator.c @@ -0,0 +1,165 @@ +/* + * Voltage regulation driver for active-semi ACT8945A PMIC + * + * Copyright (C) 2015 Atmel Corporation + * + * Author: Wenyou Yang + * + * 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 + +/** + * ACT8945A Global Register Map. + */ +#define ACT8945A_SYS_MODE 0x00 +#define ACT8945A_SYS_CTRL 0x01 +#define ACT8945A_DCDC1_VSET1 0x20 +#define ACT8945A_DCDC1_VSET2 0x21 +#define ACT8945A_DCDC1_CTRL 0x22 +#define ACT8945A_DCDC2_VSET1 0x30 +#define ACT8945A_DCDC2_VSET2 0x31 +#define ACT8945A_DCDC2_CTRL 0x32 +#define ACT8945A_DCDC3_VSET1 0x40 +#define ACT8945A_DCDC3_VSET2 0x41 +#define ACT8945A_DCDC3_CTRL 0x42 +#define ACT8945A_LDO1_VSET 0x50 +#define ACT8945A_LDO1_CTRL 0x51 +#define ACT8945A_LDO2_VSET 0x54 +#define ACT8945A_LDO2_CTRL 0x55 +#define ACT8945A_LDO3_VSET 0x60 +#define ACT8945A_LDO3_CTRL 0x61 +#define ACT8945A_LDO4_VSET 0x64 +#define ACT8945A_LDO4_CTRL 0x65 + +/** + * Field Definitions. + */ +#define ACT8945A_ENA 0x80 /* ON - [7] */ +#define ACT8945A_VSEL_MASK 0x3F /* VSET - [5:0] */ + +/** + * ACT8945A Voltage Number + */ +#define ACT8945A_VOLTAGE_NUM 64 + +enum { + ACT8945A_ID_DCDC1, + ACT8945A_ID_DCDC2, + ACT8945A_ID_DCDC3, + ACT8945A_ID_LDO1, + ACT8945A_ID_LDO2, + ACT8945A_ID_LDO3, + ACT8945A_ID_LDO4, + ACT8945A_REG_NUM, +}; + +static const struct regulator_linear_range act8945a_voltage_ranges[] = { + REGULATOR_LINEAR_RANGE(600000, 0, 23, 25000), + REGULATOR_LINEAR_RANGE(1200000, 24, 47, 50000), + REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000), +}; + +static struct regulator_ops act8945a_ops = { + .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, +}; + +#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \ + [_family##_ID_##_id] = { \ + .name = _name, \ + .supply_name = _supply, \ + .of_match = of_match_ptr("REG_"#_id), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = _family##_ID_##_id, \ + .type = REGULATOR_VOLTAGE, \ + .ops = &act8945a_ops, \ + .n_voltages = ACT8945A_VOLTAGE_NUM, \ + .linear_ranges = act8945a_voltage_ranges, \ + .n_linear_ranges = ARRAY_SIZE(act8945a_voltage_ranges), \ + .vsel_reg = _family##_##_id##_##_vsel_reg, \ + .vsel_mask = ACT8945A_VSEL_MASK, \ + .enable_reg = _family##_##_id##_CTRL, \ + .enable_mask = ACT8945A_ENA, \ + .owner = THIS_MODULE, \ + } + +static const struct regulator_desc act8945a_regulators[] = { + ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET1, "vp1"), + ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET1, "vp2"), + ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET1, "vp3"), + ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"), + ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"), + ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"), + ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"), +}; + +static const struct regulator_desc act8945a_alt_regulators[] = { + ACT89xx_REG("DCDC_REG1", ACT8945A, DCDC1, VSET2, "vp1"), + ACT89xx_REG("DCDC_REG2", ACT8945A, DCDC2, VSET2, "vp2"), + ACT89xx_REG("DCDC_REG3", ACT8945A, DCDC3, VSET2, "vp3"), + ACT89xx_REG("LDO_REG1", ACT8945A, LDO1, VSET, "inl45"), + ACT89xx_REG("LDO_REG2", ACT8945A, LDO2, VSET, "inl45"), + ACT89xx_REG("LDO_REG3", ACT8945A, LDO3, VSET, "inl67"), + ACT89xx_REG("LDO_REG4", ACT8945A, LDO4, VSET, "inl67"), +}; + +static int act8945a_pmic_probe(struct platform_device *pdev) +{ + struct regulator_config config = { }; + const struct regulator_desc *regulators; + struct regulator_dev *rdev; + int i, num_regulators; + bool voltage_select; + + voltage_select = of_property_read_bool(pdev->dev.parent->of_node, + "active-semi,vsel-high"); + + if (voltage_select) { + regulators = act8945a_alt_regulators; + num_regulators = ARRAY_SIZE(act8945a_alt_regulators); + } else { + regulators = act8945a_regulators; + num_regulators = ARRAY_SIZE(act8945a_regulators); + } + + config.dev = &pdev->dev; + config.dev->of_node = pdev->dev.parent->of_node; + for (i = 0; i < num_regulators; i++) { + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, + "failed to register %s regulator\n", + regulators[i].name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static struct platform_driver act8945a_pmic_driver = { + .driver = { + .name = "act8945a-regulator", + }, + .probe = act8945a_pmic_probe, +}; +module_platform_driver(act8945a_pmic_driver); + +MODULE_DESCRIPTION("Active-semi ACT8945A voltage regulator driver"); +MODULE_AUTHOR("Wenyou Yang "); +MODULE_LICENSE("GPL"); -- cgit From a3408b7ba0efa41a944db8b0f92bbe88b7d2783b Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Fri, 5 Feb 2016 12:33:31 +0800 Subject: regulator: add documentation for ACT8945A's regulator DT bindings This patch adds documentation for the DT bindings of the regulator subdevice of ACT8945A MFD. Signed-off-by: Wenyou Yang Acked-by: Rob Herring Signed-off-by: Mark Brown --- .../bindings/regulator/act8945a-regulator.txt | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/act8945a-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/act8945a-regulator.txt b/Documentation/devicetree/bindings/regulator/act8945a-regulator.txt new file mode 100644 index 000000000000..5c80a7779552 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/act8945a-regulator.txt @@ -0,0 +1,80 @@ +Device-Tree bindings for regulators of Active-semi ACT8945A Multi-Function Device + +Required properties: + - compatible: "active-semi,act8945a", please refer to ../mfd/act8945a.txt. + +Optional properties: +- active-semi,vsel-high: Indicates if the VSEL pin is set to logic-high. + If this property is missing, assume the VSEL pin is set to logic-low. + +Optional input supply properties: + - vp1-supply: The input supply for REG_DCDC1 + - vp2-supply: The input supply for REG_DCDC2 + - vp3-supply: The input supply for REG_DCDC3 + - inl45-supply: The input supply for REG_LDO1 and REG_LDO2 + - inl67-supply: The input supply for REG_LDO3 and REG_LDO4 + +Any standard regulator properties can be used to configure the single regulator. + +The valid names for regulators are: + REG_DCDC1, REG_DCDC2, REG_DCDC3, REG_LDO1, REG_LDO2, REG_LDO3, REG_LDO4. + +Example: + pmic@5b { + compatible = "active-semi,act8945a"; + reg = <0x5b>; + status = "okay"; + + active-semi,vsel-high; + + regulators { + vdd_1v35_reg: REG_DCDC1 { + regulator-name = "VDD_1V35"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + }; + + vdd_1v2_reg: REG_DCDC2 { + regulator-name = "VDD_1V2"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1300000>; + regulator-always-on; + }; + + vdd_3v3_reg: REG_DCDC3 { + regulator-name = "VDD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd_fuse_reg: REG_LDO1 { + regulator-name = "VDD_FUSE"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + vdd_3v3_lp_reg: REG_LDO2 { + regulator-name = "VDD_3V3_LP"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd_led_reg: REG_LDO3 { + regulator-name = "VDD_LED"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdd_sdhc_1v8_reg: REG_LDO4 { + regulator-name = "VDD_SDHC_1V8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + }; + }; -- cgit From 3bdff244a2bcbde37ec33bf3cdde4638049c6c38 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 15 Jan 2016 16:13:10 +0800 Subject: ALSA: pcm: Add snd_pcm_rate_range_to_bits() This helper function can convert a given sample rate range to SNDRV_PCM_RATE_xxx bits. Signed-off-by: Mengdong Lin Acked-by: Takashi Iwai Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/pcm.h | 2 ++ sound/core/pcm_misc.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b0be09279943..af1fb37c6b26 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -1093,6 +1093,8 @@ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, unsigned int rates_b); +unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min, + unsigned int rate_max); /** * snd_pcm_set_runtime_buffer - Set the PCM runtime buffer diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index ebe8444de6c6..53dc37357bca 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c @@ -565,3 +565,33 @@ unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, return rates_a & rates_b; } EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect); + +/** + * snd_pcm_rate_range_to_bits - converts rate range to SNDRV_PCM_RATE_xxx bit + * @rate_min: the minimum sample rate + * @rate_max: the maximum sample rate + * + * This function has an implicit assumption: the rates in the given range have + * only the pre-defined rates like 44100 or 16000. + * + * Return: The SNDRV_PCM_RATE_xxx flag that corresponds to the given rate range, + * or SNDRV_PCM_RATE_KNOT for an unknown range. + */ +unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min, + unsigned int rate_max) +{ + unsigned int rates = 0; + int i; + + for (i = 0; i < snd_pcm_known_rates.count; i++) { + if (snd_pcm_known_rates.list[i] >= rate_min + && snd_pcm_known_rates.list[i] <= rate_max) + rates |= 1 << i; + } + + if (!rates) + rates = SNDRV_PCM_RATE_KNOT; + + return rates; +} +EXPORT_SYMBOL_GPL(snd_pcm_rate_range_to_bits); -- cgit From 690f44badf2f44b8ec09098118b74f789f95e2c8 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 5 Feb 2016 19:42:18 +0100 Subject: regulator: lp872x: Remove warning about invalid DVS GPIO Some devices don't hook the DVS pin to a GPIO but to ground or VCC. In those cases, it is not a problem to have no DVS GPIO provided, as the current code will already switch to software-only DVS selection: When the DVS GPIO is invalid, lp872x_init_dvs jumps to the set_default_dvs_mode label, which instructs the chip not to use the DVS pin at all and do it all in software instead (by clearing the LP8720_EXT_DVS_M bit in the LP872X_GENERAL_CFG register). That is reflected later in the code, when setting the bucks (the DVS pin only applies to the bucks) by checking for the LP8720_EXT_DVS_M bit on the LP872X_GENERAL_CFG register (in lp872x_select_buck_vout_addr) to decide whether to use software or hardware DVS selection. Thus, there is no need to print a warning when the DVS GPIO is invalid. Signed-off-by: Paul Kocialkowski Signed-off-by: Mark Brown --- drivers/regulator/lp872x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 19d758486553..21c49d871aba 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -738,10 +738,8 @@ static int lp872x_init_dvs(struct lp872x *lp) goto set_default_dvs_mode; gpio = dvs->gpio; - if (!gpio_is_valid(gpio)) { - dev_warn(lp->dev, "invalid gpio: %d\n", gpio); + if (!gpio_is_valid(gpio)) goto set_default_dvs_mode; - } pinstate = dvs->init_state; ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS"); -- cgit From 7e6213f4345c3798b7fb7af41d221e2fd77ec6a6 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 5 Feb 2016 19:42:19 +0100 Subject: regulator: lp872x: Add enable GPIO pin support LP872x regulators are made active via the EN pin, which might be hooked to a GPIO. This adds support for driving the GPIO high when the driver is in use. Signed-off-by: Paul Kocialkowski Signed-off-by: Mark Brown --- .../devicetree/bindings/regulator/lp872x.txt | 1 + drivers/regulator/lp872x.c | 34 ++++++++++++++++++++++ include/linux/regulator/lp872x.h | 5 ++++ 3 files changed, 40 insertions(+) diff --git a/Documentation/devicetree/bindings/regulator/lp872x.txt b/Documentation/devicetree/bindings/regulator/lp872x.txt index 78183182dad9..ca58a68ffdf1 100644 --- a/Documentation/devicetree/bindings/regulator/lp872x.txt +++ b/Documentation/devicetree/bindings/regulator/lp872x.txt @@ -28,6 +28,7 @@ Optional properties: - ti,dvs-gpio: GPIO specifier for external DVS pin control of LP872x devices. - ti,dvs-vsel: DVS selector. 0 = SEL_V1, 1 = SEL_V2. - ti,dvs-state: initial DVS pin state. 0 = DVS_LOW, 1 = DVS_HIGH. + - enable-gpios: GPIO specifier for EN pin control of LP872x devices. Sub nodes for regulator_init_data LP8720 has maximum 6 nodes. (child name: ldo1 ~ 5 and buck) diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 21c49d871aba..38992112fd6e 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -757,6 +758,33 @@ set_default_dvs_mode: default_dvs_mode[lp->chipid]); } +static int lp872x_hw_enable(struct lp872x *lp) +{ + int ret, gpio; + + if (!lp->pdata) + return -EINVAL; + + gpio = lp->pdata->enable_gpio; + if (!gpio_is_valid(gpio)) + return 0; + + /* Always set enable GPIO high. */ + ret = devm_gpio_request_one(lp->dev, gpio, GPIOF_OUT_INIT_HIGH, "LP872X EN"); + if (ret) { + dev_err(lp->dev, "gpio request err: %d\n", ret); + return ret; + } + + /* Each chip has a different enable delay. */ + if (lp->chipid == LP8720) + usleep_range(LP8720_ENABLE_DELAY, 1.5 * LP8720_ENABLE_DELAY); + else + usleep_range(LP8725_ENABLE_DELAY, 1.5 * LP8725_ENABLE_DELAY); + + return 0; +} + static int lp872x_config(struct lp872x *lp) { struct lp872x_platform_data *pdata = lp->pdata; @@ -875,6 +903,8 @@ static struct lp872x_platform_data of_property_read_u8(np, "ti,dvs-state", &dvs_state); pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW; + pdata->enable_gpio = of_get_named_gpio(np, "enable-gpios", 0); + if (of_get_child_count(np) == 0) goto out; @@ -948,6 +978,10 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id) lp->chipid = id->driver_data; i2c_set_clientdata(cl, lp); + ret = lp872x_hw_enable(lp); + if (ret) + return ret; + ret = lp872x_config(lp); if (ret) return ret; diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h index 132e05c46661..6029279f4eed 100644 --- a/include/linux/regulator/lp872x.h +++ b/include/linux/regulator/lp872x.h @@ -18,6 +18,9 @@ #define LP872X_MAX_REGULATORS 9 +#define LP8720_ENABLE_DELAY 200 +#define LP8725_ENABLE_DELAY 30000 + enum lp872x_regulator_id { LP8720_ID_BASE, LP8720_ID_LDO1 = LP8720_ID_BASE, @@ -79,12 +82,14 @@ struct lp872x_regulator_data { * @update_config : if LP872X_GENERAL_CFG register is updated, set true * @regulator_data : platform regulator id and init data * @dvs : dvs data for buck voltage control + * @enable_gpio : gpio pin number for enable control */ struct lp872x_platform_data { u8 general_config; bool update_config; struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS]; struct lp872x_dvs *dvs; + int enable_gpio; }; #endif -- cgit From 3487c65659088c8205d8ab726b45469912271bbd Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Fri, 29 Jan 2016 11:29:31 +0000 Subject: PCI: rcar: Remove PCI_PROBE_ONLY handling The PCIe rcar host driver is not used in system configurations requiring the PCI_PROBE_ONLY flag to be set to prevent resources assignment, therefore the driver code handling the flag can be removed from the kernel. Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas Acked-by: Simon Horman Cc: Arnd Bergmann Cc: Phil Edworthy --- drivers/pci/host/pcie-rcar.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index 4edb5181f4e2..35092188039b 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -390,9 +390,7 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie) rcar_pcie_setup(&res, pcie); - /* Do not reassign resources if probe only */ - if (!pci_has_flag(PCI_PROBE_ONLY)) - pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); if (IS_ENABLED(CONFIG_PCI_MSI)) bus = pci_scan_root_bus_msi(pcie->dev, pcie->root_bus_nr, @@ -408,13 +406,11 @@ static int rcar_pcie_enable(struct rcar_pcie *pcie) pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); - if (!pci_has_flag(PCI_PROBE_ONLY)) { - pci_bus_size_bridges(bus); - pci_bus_assign_resources(bus); + pci_bus_size_bridges(bus); + pci_bus_assign_resources(bus); - list_for_each_entry(child, &bus->children, node) - pcie_bus_configure_settings(child); - } + list_for_each_entry(child, &bus->children, node) + pcie_bus_configure_settings(child); pci_bus_add_devices(bus); -- cgit From dbae40b76abef2f8a7e7bf1701f77df9e73def48 Mon Sep 17 00:00:00 2001 From: Yang Shi Date: Wed, 27 Jan 2016 09:32:05 -0800 Subject: PCI: layerscape: Add "fsl,ls2085a-pcie" compatible ID The Layerscape PCI host driver must recognize ls2085a compatible when using firmware with ls2085a compatible property, otherwise the PCI bus won't be detected even though ls2085a compatible is included by the dts. Signed-off-by: Yang Shi Signed-off-by: Bjorn Helgaas --- drivers/pci/host/pci-layerscape.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c index 3923bed93c7e..c40d8b2ce330 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/host/pci-layerscape.c @@ -203,6 +203,7 @@ static const struct of_device_id ls_pcie_of_match[] = { { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, + { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata }, { }, }; MODULE_DEVICE_TABLE(of, ls_pcie_of_match); -- cgit From ab1a187bba5c4e5ed8aa6e7bb7dcd7cd7e065aef Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 27 Jan 2016 07:35:07 -0600 Subject: PCI: Check device_attach() return value always Previously we checked the device_attach() return value only when CONFIG_BUG=y. That caused this warning in builds where CONFIG_BUG is not set: drivers/pci/bus.c:237:6: warning: variable 'retval' set but not used [-Wunused-but-set-variable] Check the return value of device_attach() always and clean up after failure. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/pci/bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 89b3befc7155..f2187d491475 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -291,7 +291,12 @@ void pci_bus_add_device(struct pci_dev *dev) dev->match_driver = true; retval = device_attach(&dev->dev); - WARN_ON(retval < 0); + if (retval < 0) { + dev_warn(&dev->dev, "device attach failed (%d)\n", retval); + pci_proc_detach_device(dev); + pci_remove_sysfs_dev_files(dev); + return; + } dev->is_added = 1; } -- cgit From 4e48fe4148698ffd3935800f4967362e80a7ae92 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:12 -0600 Subject: PCI/PME: Remove redundant port lookup We've already looked up srv->port a few lines earlier, and there's no need to do it again. Remove the redundant lookup. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki suspend_level = PME_SUSPEND_WAKEUP; } if (!wakeup || ret) { - struct pci_dev *port = srv->port; - pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port); data->suspend_level = PME_SUSPEND_NOIRQ; -- cgit From 41ccebaecef50e56f822791a52b7bd9e9608e5e6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:19 -0600 Subject: PCI/PME: Restructure pcie_pme_suspend() to prevent compiler warning Previously we had this: if (wakeup) ret = enable_irq_wake(...); if (!wakeup || ret) ... "ret" is only evaluated when "wakeup" is true, and it is always initialized in that case, but gcc isn't smart enough to figure that out and warns: drivers/pci/pcie/pme.c:414:14: warning: 'ret' may be used uninitialized in this function [-Wmaybe-uninitialized] Restructure the code slightly to make it easier for gcc (and maybe for humans as well). Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki port; - bool wakeup; + bool wakeup, wake_irq_enabled = false; int ret; if (device_may_wakeup(&port->dev)) { @@ -409,9 +409,12 @@ static int pcie_pme_suspend(struct pcie_device *srv) spin_lock_irq(&data->lock); if (wakeup) { ret = enable_irq_wake(srv->irq); - data->suspend_level = PME_SUSPEND_WAKEUP; + if (ret == 0) { + data->suspend_level = PME_SUSPEND_WAKEUP; + wake_irq_enabled = true; + } } - if (!wakeup || ret) { + if (!wake_irq_enabled) { pcie_pme_interrupt_enable(port, false); pcie_clear_root_pme_status(port); data->suspend_level = PME_SUSPEND_NOIRQ; -- cgit From 5bbe029ff7bc8ff82ef31d3480d68c95642a3c7a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:47 -0600 Subject: PCI: Move pci_set_flags() from asm-generic/pci-bridge.h to linux/pci.h The PCI flag management constants and functions were previously declared in include/asm-generic/pci-bridge.h. But they are not specific to bridges, and arches did not include pci-bridge.h consistently. Move the following interfaces and related constants to include/linux/pci.h and remove pci-bridge.h: pci_set_flags() pci_add_flags() pci_clear_flags() pci_has_flag() This fixes these warnings when building for some arches: drivers/pci/host/pcie-designware.c:562:20: error: 'PCI_PROBE_ONLY' undeclared (first use in this function) drivers/pci/host/pcie-designware.c:562:7: error: implicit declaration of function 'pci_has_flag' [-Werror=implicit-function-declaration] Signed-off-by: Bjorn Helgaas --- drivers/pci/probe.c | 7 +++++ include/asm-generic/pci-bridge.h | 65 ---------------------------------------- include/linux/pci.h | 22 ++++++++++++++ 3 files changed, 29 insertions(+), 65 deletions(-) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 6d7ab9bb0d5a..ead1ac1dc1e3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1803,6 +1803,13 @@ static int only_one_child(struct pci_bus *bus) return 0; if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT) return 1; + + /* + * PCIe downstream ports are bridges that normally lead to only a + * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all + * possible devices, not just device 0. See PCIe spec r3.0, + * sec 7.3.1. + */ if (parent->has_secondary_link && !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS)) return 1; diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h index 20db2e5a0a69..1b1d82f66d57 100644 --- a/include/asm-generic/pci-bridge.h +++ b/include/asm-generic/pci-bridge.h @@ -6,69 +6,4 @@ */ #ifndef _ASM_GENERIC_PCI_BRIDGE_H #define _ASM_GENERIC_PCI_BRIDGE_H - -#ifdef __KERNEL__ - -enum { - /* Force re-assigning all resources (ignore firmware - * setup completely) - */ - PCI_REASSIGN_ALL_RSRC = 0x00000001, - - /* Re-assign all bus numbers */ - PCI_REASSIGN_ALL_BUS = 0x00000002, - - /* Do not try to assign, just use existing setup */ - PCI_PROBE_ONLY = 0x00000004, - - /* Don't bother with ISA alignment unless the bridge has - * ISA forwarding enabled - */ - PCI_CAN_SKIP_ISA_ALIGN = 0x00000008, - - /* Enable domain numbers in /proc */ - PCI_ENABLE_PROC_DOMAINS = 0x00000010, - /* ... except for domain 0 */ - PCI_COMPAT_DOMAIN_0 = 0x00000020, - - /* PCIe downstream ports are bridges that normally lead to only a - * device 0, but if this is set, we scan all possible devices, not - * just device 0. - */ - PCI_SCAN_ALL_PCIE_DEVS = 0x00000040, -}; - -#ifdef CONFIG_PCI -extern unsigned int pci_flags; - -static inline void pci_set_flags(int flags) -{ - pci_flags = flags; -} - -static inline void pci_add_flags(int flags) -{ - pci_flags |= flags; -} - -static inline void pci_clear_flags(int flags) -{ - pci_flags &= ~flags; -} - -static inline int pci_has_flag(int flag) -{ - return pci_flags & flag; -} -#else -static inline void pci_set_flags(int flags) { } -static inline void pci_add_flags(int flags) { } -static inline void pci_clear_flags(int flags) { } -static inline int pci_has_flag(int flag) -{ - return 0; -} -#endif /* CONFIG_PCI */ - -#endif /* __KERNEL__ */ #endif /* _ASM_GENERIC_PCI_BRIDGE_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 27df4a6585da..3d371c150753 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -746,9 +746,26 @@ struct pci_driver { .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0 +enum { + PCI_REASSIGN_ALL_RSRC = 0x00000001, /* ignore firmware setup */ + PCI_REASSIGN_ALL_BUS = 0x00000002, /* reassign all bus numbers */ + PCI_PROBE_ONLY = 0x00000004, /* use existing setup */ + PCI_CAN_SKIP_ISA_ALIGN = 0x00000008, /* don't do ISA alignment */ + PCI_ENABLE_PROC_DOMAINS = 0x00000010, /* enable domains in /proc */ + PCI_COMPAT_DOMAIN_0 = 0x00000020, /* ... except domain 0 */ + PCI_SCAN_ALL_PCIE_DEVS = 0x00000040, /* scan all, not just dev 0 */ +}; + /* these external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI +extern unsigned int pci_flags; + +static inline void pci_set_flags(int flags) { pci_flags = flags; } +static inline void pci_add_flags(int flags) { pci_flags |= flags; } +static inline void pci_clear_flags(int flags) { pci_flags &= ~flags; } +static inline int pci_has_flag(int flag) { return pci_flags & flag; } + void pcie_bus_configure_settings(struct pci_bus *bus); enum pcie_bus_config_types { @@ -1405,6 +1422,11 @@ void pci_register_set_vga_state(arch_set_vga_state_t func); #else /* CONFIG_PCI is not enabled */ +static inline void pci_set_flags(int flags) { } +static inline void pci_add_flags(int flags) { } +static inline void pci_clear_flags(int flags) { } +static inline int pci_has_flag(int flag) { return 0; } + /* * If the system does not have PCI, clearly these return errors. Define * these as simple inline functions to avoid hair in drivers. -- cgit From 5bd28338d681dcbde2c4bee4ebea0c4e0dfcd9e4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:57:54 -0600 Subject: PCI: Remove includes of empty asm-generic/pci-bridge.h include/asm-generic/pci-bridge.h is now empty, so remove every #include of it. Signed-off-by: Bjorn Helgaas Acked-by: Will Deacon (arm64) --- arch/alpha/include/asm/pci.h | 1 - arch/arm/include/asm/pci.h | 3 --- arch/arm64/include/asm/pci.h | 1 - arch/mips/include/asm/pci.h | 1 - arch/powerpc/include/asm/pci-bridge.h | 1 - arch/unicore32/include/asm/pci.h | 2 -- arch/x86/pci/common.c | 1 - drivers/of/of_pci.c | 1 - drivers/pci/pci.c | 1 - drivers/pci/probe.c | 1 - drivers/pci/setup-bus.c | 1 - 11 files changed, 14 deletions(-) diff --git a/arch/alpha/include/asm/pci.h b/arch/alpha/include/asm/pci.h index 98f2eeee8f68..75d8865d763d 100644 --- a/arch/alpha/include/asm/pci.h +++ b/arch/alpha/include/asm/pci.h @@ -7,7 +7,6 @@ #include #include #include -#include /* * The following structure is used to manage multiple PCI busses. diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index a5635444ca41..d7de19a77d51 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -3,8 +3,6 @@ #ifdef __KERNEL__ #include -#include - #include /* for pci_sys_data */ extern unsigned long pcibios_min_io; @@ -41,5 +39,4 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) } #endif /* __KERNEL__ */ - #endif diff --git a/arch/arm64/include/asm/pci.h b/arch/arm64/include/asm/pci.h index b008a72f8bc0..f75b04e8d732 100644 --- a/arch/arm64/include/asm/pci.h +++ b/arch/arm64/include/asm/pci.h @@ -7,7 +7,6 @@ #include #include -#include #include #define PCIBIOS_MIN_IO 0x1000 diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 98c31e5d9579..108d19376bb1 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -102,7 +102,6 @@ static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, #include #include #include -#include struct pci_dev; diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index 54843ca5fa2b..78968c1ff931 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -10,7 +10,6 @@ #include #include #include -#include struct device_node; diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h index 38b3f3785c3c..eb9dccecb338 100644 --- a/arch/unicore32/include/asm/pci.h +++ b/arch/unicore32/include/asm/pci.h @@ -14,7 +14,6 @@ #ifdef __KERNEL__ #include -#include #include #include /* for PCIBIOS_MIN_* */ @@ -23,5 +22,4 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); #endif /* __KERNEL__ */ - #endif diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 2879efc73a96..b4a9f23d77d9 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c index b1449f71601c..13f4fed38048 100644 --- a/drivers/of/of_pci.c +++ b/drivers/of/of_pci.c @@ -5,7 +5,6 @@ #include #include #include -#include static inline int __of_pci_pci_compare(struct device_node *node, unsigned int data) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 602eb4223510..64c0a1215f84 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include "pci.h" diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ead1ac1dc1e3..5eb378fbe849 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "pci.h" #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 7796d0a5befa..55641a39a3e9 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "pci.h" unsigned int pci_flags; -- cgit From 234234c2e12e1b302beefbd11e9c5b26f9234cb1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:58:02 -0600 Subject: ARM64: PCI: Remove generated include of asm-generic/pci-bridge.h arm64 generates asm/pci-bridge.h, which merely includes the now-empty asm-generic/pci-bridge.h. Stop generating asm/pci-bridge.h, and stop including it. Signed-off-by: Bjorn Helgaas Acked-by: Will Deacon --- arch/arm64/include/asm/Kbuild | 3 --- arch/arm64/kernel/pci.c | 2 -- 2 files changed, 5 deletions(-) diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index 70fd9ffb58cf..cff532a6744e 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -1,5 +1,3 @@ - - generic-y += bug.h generic-y += bugs.h generic-y += checksum.h @@ -31,7 +29,6 @@ generic-y += msgbuf.h generic-y += msi.h generic-y += mutex.h generic-y += pci.h -generic-y += pci-bridge.h generic-y += poll.h generic-y += preempt.h generic-y += resource.h diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c index b3d098bd34aa..c72de668e1d4 100644 --- a/arch/arm64/kernel/pci.c +++ b/arch/arm64/kernel/pci.c @@ -19,8 +19,6 @@ #include #include -#include - /* * Called after each bus is probed, but before its children are examined */ -- cgit From b6b83f7fdae7cae5260b907510619a47bd29cd70 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:58:07 -0600 Subject: PCI: Remove empty asm-generic/pci-bridge.h include/asm-generic/pci-bridge.h is empty, and nobody includes it, so remove it. Signed-off-by: Bjorn Helgaas --- include/asm-generic/pci-bridge.h | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 include/asm-generic/pci-bridge.h diff --git a/include/asm-generic/pci-bridge.h b/include/asm-generic/pci-bridge.h deleted file mode 100644 index 1b1d82f66d57..000000000000 --- a/include/asm-generic/pci-bridge.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 _ASM_GENERIC_PCI_BRIDGE_H -#define _ASM_GENERIC_PCI_BRIDGE_H -#endif /* _ASM_GENERIC_PCI_BRIDGE_H */ -- cgit From 952bbcb0781bd1341f6a9f5c96fc32737392c04a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 5 Feb 2016 14:58:12 -0600 Subject: PCI: Remove includes of asm/pci-bridge.h Drivers should include asm/pci-bridge.h only when they need the arch- specific things provided there. Outside of the arch/ directories, the only drivers that actually need things provided by asm/pci-bridge.h are the powerpc RPA hotplug drivers in drivers/pci/hotplug/rpa*. Remove the includes of asm/pci-bridge.h from the other drivers, adding an include of linux/pci.h if necessary. Signed-off-by: Bjorn Helgaas --- drivers/ata/pata_macio.c | 2 +- drivers/char/agp/uninorth-agp.c | 1 - drivers/gpu/drm/radeon/radeon_combios.c | 1 - drivers/ide/pdc202xx_new.c | 1 - drivers/ide/pmac.c | 1 - drivers/macintosh/macio_asic.c | 1 - drivers/misc/cxl/pci.c | 1 - drivers/net/ethernet/sun/sungem.c | 1 - drivers/net/ethernet/toshiba/spider_net.c | 1 - drivers/scsi/mac53c94.c | 2 +- drivers/scsi/mesh.c | 2 +- drivers/usb/core/hcd-pci.c | 1 - drivers/video/fbdev/aty/aty128fb.c | 1 - drivers/video/fbdev/aty/radeon_base.c | 1 - drivers/video/fbdev/imsttfb.c | 1 - drivers/video/fbdev/matrox/matroxfb_base.h | 1 - drivers/video/fbdev/offb.c | 4 ---- sound/ppc/pmac.c | 1 - 18 files changed, 3 insertions(+), 21 deletions(-) diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index e3d4b059fcd1..e347e7acd8ed 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 05755441250c..fdced547ad59 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include "agp.h" diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index a9b01bcf7d0a..432480ff9d22 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -34,7 +34,6 @@ #include #include #include -#include #endif /* CONFIG_PPC_PMAC */ /* from radeon_legacy_encoder.c */ diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c index 9ad014a7afc7..b33646be699c 100644 --- a/drivers/ide/pdc202xx_new.c +++ b/drivers/ide/pdc202xx_new.c @@ -28,7 +28,6 @@ #ifdef CONFIG_PPC_PMAC #include -#include #endif #define DRV_NAME "pdc202xx_new" diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 96a345248224..7f0434f7e486 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 4f12c6f01fe7..b6819f0fc608 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -31,7 +31,6 @@ #include #include #include -#include #undef DEBUG diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 4c1903f781fc..a21403238a4a 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c @@ -19,7 +19,6 @@ #include #include #include -#include /* for struct pci_controller */ #include #include diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index e23a642357e7..2437227712dc 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -51,7 +51,6 @@ #endif #ifdef CONFIG_PPC_PMAC -#include #include #include #include diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index 3c54a2cae5df..67610270d171 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include "spider_net.h" diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c index 141226631429..a6682c508c4c 100644 --- a/drivers/scsi/mac53c94.c +++ b/drivers/scsi/mac53c94.c @@ -18,11 +18,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 555367f00228..1753e42826dd 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 9eb1cff28bd4..c3640f8a8fb3 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -28,7 +28,6 @@ #ifdef CONFIG_PPC_PMAC #include #include -#include #include #endif diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index c42ce2fdfd44..0a4626886b00 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -68,7 +68,6 @@ #include #include #include -#include #include "../macmodes.h" #endif diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index ce0b1d05a388..218339a4edaa 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -76,7 +76,6 @@ #ifdef CONFIG_PPC -#include #include "../macmodes.h" #ifdef CONFIG_BOOTX_TEXT diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index 9b167f7ef6c6..4363c64d74e8 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -33,7 +33,6 @@ #if defined(CONFIG_PPC) #include #include -#include #include "macmodes.h" #endif diff --git a/drivers/video/fbdev/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h index 09b02cd1eb0e..7a90ea2c4613 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.h +++ b/drivers/video/fbdev/matrox/matroxfb_base.h @@ -47,7 +47,6 @@ #if defined(CONFIG_PPC_PMAC) #include -#include #include "../macmodes.h" #endif diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index 43a0a52fc527..fb60a8f0cc94 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -28,10 +28,6 @@ #include #include -#ifdef CONFIG_PPC64 -#include -#endif - #ifdef CONFIG_PPC32 #include #endif diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 0095a80a997f..a5843fc5ff20 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -34,7 +34,6 @@ #include "pmac.h" #include #include -#include /* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */ -- cgit From 1300568ac129a83f321fdb74e397942f583c8321 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 5 Feb 2016 23:47:13 +0100 Subject: pinctrl: stm32: fix compile error and modernize - Fix the dev->parent assignment compile error - Use gpiochip_get_data() to get the data pointer for the banks Cc: Maxime Coquelin Cc: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index d25d4a064bad..9a08222ecb72 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -6,7 +6,7 @@ * Heavily based on Mediatek's pinctrl driver */ #include -#include +#include #include #include #include @@ -46,9 +46,6 @@ #define gpio_range_to_bank(chip) \ container_of(chip, struct stm32_gpio_bank, range) -#define gpio_chip_to_bank(chip) \ - container_of(chip, struct stm32_gpio_bank, gpio_chip) - static const char * const stm32_gpio_functions[] = { "gpio", "af0", "af1", "af2", "af3", "af4", @@ -144,7 +141,7 @@ static void stm32_gpio_free(struct gpio_chip *chip, unsigned offset) static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); int ret; clk_enable(bank->clk); @@ -158,7 +155,7 @@ static int stm32_gpio_get(struct gpio_chip *chip, unsigned offset) static void stm32_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); __stm32_gpio_set(bank, offset, value); } @@ -171,7 +168,7 @@ static int stm32_gpio_direction_input(struct gpio_chip *chip, unsigned offset) static int stm32_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { - struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); + struct stm32_gpio_bank *bank = gpiochip_get_data(chip); __stm32_gpio_set(bank, offset, value); pinctrl_gpio_direction_output(chip->base + offset); @@ -689,7 +686,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; bank->gpio_chip.ngpio = npins; bank->gpio_chip.of_node = np; - bank->gpio_chip.dev = dev; + bank->gpio_chip.parent = dev; spin_lock_init(&bank->lock); of_property_read_string(np, "st,bank-name", &range->name); @@ -699,7 +696,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, range->pin_base = range->base = range->id * STM32_GPIO_PINS_PER_BANK; range->npins = bank->gpio_chip.ngpio; range->gc = &bank->gpio_chip; - err = gpiochip_add(&bank->gpio_chip); + err = gpiochip_add_data(&bank->gpio_chip, bank); if (err) { dev_err(dev, "Failed to add gpiochip(%d)!\n", bank_nr); return err; -- cgit From ad2db351e77d3022f61934406fbefce1616b6f76 Mon Sep 17 00:00:00 2001 From: Joshua Henderson Date: Mon, 1 Feb 2016 15:48:29 -0700 Subject: pinctrl: Add DT bindings for PIC32 pin control and GPIO Document the devicetree bindings for PINCTRL and GPIO found on Microchip PIC32 class devices. Signed-off-by: Joshua Henderson Cc: Ralf Baechle Acked-by: Rob Herring Cc: Linus Walleij Signed-off-by: Linus Walleij --- .../bindings/gpio/microchip,pic32-gpio.txt | 49 ++++++++++++++++++ .../bindings/pinctrl/microchip,pic32-pinctrl.txt | 60 ++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt create mode 100644 Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt diff --git a/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt b/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt new file mode 100644 index 000000000000..ef3752889496 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/microchip,pic32-gpio.txt @@ -0,0 +1,49 @@ +* Microchip PIC32 GPIO devices (PIO). + +Required properties: + - compatible: "microchip,pic32mzda-gpio" + - reg: Base address and length for the device. + - interrupts: The port interrupt shared by all pins. + - gpio-controller: Marks the port as GPIO controller. + - #gpio-cells: Two. The first cell is the pin number and + the second cell is used to specify the gpio polarity as defined in + defined in : + 0 = GPIO_ACTIVE_HIGH + 1 = GPIO_ACTIVE_LOW + 2 = GPIO_OPEN_DRAIN + - interrupt-controller: Marks the device node as an interrupt controller. + - #interrupt-cells: Two. The first cell is the GPIO number and second cell + is used to specify the trigger type as defined in + : + IRQ_TYPE_EDGE_RISING + IRQ_TYPE_EDGE_FALLING + IRQ_TYPE_EDGE_BOTH + - clocks: Clock specifier (see clock bindings for details). + - microchip,gpio-bank: Specifies which bank a controller owns. + - gpio-ranges: Interaction with the PINCTRL subsystem. + +Example: + +/* PORTA */ +gpio0: gpio0@1f860000 { + compatible = "microchip,pic32mzda-gpio"; + reg = <0x1f860000 0x100>; + interrupts = <118 IRQ_TYPE_LEVEL_HIGH>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&PBCLK4>; + microchip,gpio-bank = <0>; + gpio-ranges = <&pic32_pinctrl 0 0 16>; +}; + +keys { + ... + + button@sw1 { + label = "ESC"; + linux,code = <1>; + gpios = <&gpio0 12 0>; + }; +}; diff --git a/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt new file mode 100644 index 000000000000..4b5efa51bec7 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/microchip,pic32-pinctrl.txt @@ -0,0 +1,60 @@ +* Microchip PIC32 Pin Controller + +Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and +../interrupt-controller/interrupts.txt for generic information regarding +pin controller, GPIO, and interrupt bindings. + +PIC32 'pin configuration node' is a node of a group of pins which can be +used for a specific device or function. This node represents configuraions of +pins, optional function, and optional mux related configuration. + +Required properties for pin controller node: + - compatible: "microchip,pic32mada-pinctrl" + - reg: Address range of the pinctrl registers. + - clocks: Clock specifier (see clock bindings for details) + +Required properties for pin configuration sub-nodes: + - pins: List of pins to which the configuration applies. + +Optional properties for pin configuration sub-nodes: +---------------------------------------------------- + - function: Mux function for the specified pins. + - bias-pull-up: Enable weak pull-up. + - bias-pull-down: Enable weak pull-down. + - input-enable: Set the pin as an input. + - output-low: Set the pin as an output level low. + - output-high: Set the pin as an output level high. + - microchip,digital: Enable digital I/O. + - microchip,analog: Enable analog I/O. + +Example: + +pic32_pinctrl: pinctrl@1f801400{ + #address-cells = <1>; + #size-cells = <1>; + compatible = "microchip,pic32mzda-pinctrl"; + reg = <0x1f801400 0x400>; + clocks = <&PBCLK1>; + + pinctrl_uart2: pinctrl_uart2 { + uart2-tx { + pins = "G9"; + function = "U2TX"; + microchip,digital; + output-low; + }; + uart2-rx { + pins = "B0"; + function = "U2RX"; + microchip,digital; + input-enable; + }; + }; +}; + +uart2: serial@1f822200 { + compatible = "microchip,pic32mzda-uart"; + reg = <0x1f822200 0x50>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; +}; -- cgit From 2ba384e6c3810733e14e183dedc3406f402a686f Mon Sep 17 00:00:00 2001 From: Joshua Henderson Date: Mon, 1 Feb 2016 15:48:30 -0700 Subject: pinctrl: pinctrl-pic32: Add PIC32 pin control driver Add a driver for the pin controller present on the Microchip PIC32 including the specific variant PIC32MZDA. This driver provides pinmux and pinconfig operations as well as GPIO and IRQ chips for the GPIO banks. Signed-off-by: Joshua Henderson Cc: Ralf Baechle Cc: Linus Walleij Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 17 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pic32.c | 2312 +++++++++++++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-pic32.h | 141 +++ 4 files changed, 2471 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pic32.c create mode 100644 drivers/pinctrl/pinctrl-pic32.h diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 6ba67a619062..a4c07394e313 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -207,6 +207,23 @@ config PINCTRL_PALMAS open drain configuration for the Palmas series devices like TPS65913, TPS80036 etc. +config PINCTRL_PIC32 + bool "Microchip PIC32 pin controller driver" + depends on OF + depends on MACH_PIC32 + select PINMUX + select GENERIC_PINCONF + select GPIOLIB_IRQCHIP + select OF_GPIO + help + This is the pin controller and gpio driver for Microchip PIC32 + microcontrollers. This option is selected automatically when specific + machine and arch are selected to build. + +config PINCTRL_PIC32MZDA + def_bool y if PIC32MZDA + select PINCTRL_PIC32 + config PINCTRL_ZYNQ bool "Pinctrl driver for Xilinx Zynq" depends on ARCH_ZYNQ diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index e4e673e2a448..8adc235e1a96 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_MESON) += meson/ obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o +obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o diff --git a/drivers/pinctrl/pinctrl-pic32.c b/drivers/pinctrl/pinctrl-pic32.c new file mode 100644 index 000000000000..0b07d4bdab95 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pic32.c @@ -0,0 +1,2312 @@ +/* + * PIC32 pinctrl driver + * + * Joshua Henderson, + * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. + * + * 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 + +#include "pinctrl-utils.h" +#include "pinctrl-pic32.h" + +#define PINS_PER_BANK 16 + +#define PIC32_CNCON_EDGE 11 +#define PIC32_CNCON_ON 15 + +#define PIN_CONFIG_MICROCHIP_DIGITAL (PIN_CONFIG_END + 1) +#define PIN_CONFIG_MICROCHIP_ANALOG (PIN_CONFIG_END + 2) + +static const struct pinconf_generic_params pic32_mpp_bindings[] = { + {"microchip,digital", PIN_CONFIG_MICROCHIP_DIGITAL, 0}, + {"microchip,analog", PIN_CONFIG_MICROCHIP_ANALOG, 0}, +}; + +#define GPIO_BANK_START(bank) ((bank) * PINS_PER_BANK) + +struct pic32_function { + const char *name; + const char * const *groups; + unsigned int ngroups; +}; + +struct pic32_pin_group { + const char *name; + unsigned int pin; + struct pic32_desc_function *functions; +}; + +struct pic32_desc_function { + const char *name; + u32 muxreg; + u32 muxval; +}; + +struct pic32_gpio_bank { + void __iomem *reg_base; + struct gpio_chip gpio_chip; + struct irq_chip irq_chip; + struct clk *clk; +}; + +struct pic32_pinctrl { + void __iomem *reg_base; + struct device *dev; + struct pinctrl_dev *pctldev; + const struct pinctrl_pin_desc *pins; + unsigned int npins; + const struct pic32_function *functions; + unsigned int nfunctions; + const struct pic32_pin_group *groups; + unsigned int ngroups; + struct pic32_gpio_bank *gpio_banks; + unsigned int nbanks; + struct clk *clk; +}; + +static const struct pinctrl_pin_desc pic32_pins[] = { + PINCTRL_PIN(0, "A0"), + PINCTRL_PIN(1, "A1"), + PINCTRL_PIN(2, "A2"), + PINCTRL_PIN(3, "A3"), + PINCTRL_PIN(4, "A4"), + PINCTRL_PIN(5, "A5"), + PINCTRL_PIN(6, "A6"), + PINCTRL_PIN(7, "A7"), + PINCTRL_PIN(8, "A8"), + PINCTRL_PIN(9, "A9"), + PINCTRL_PIN(10, "A10"), + PINCTRL_PIN(11, "A11"), + PINCTRL_PIN(12, "A12"), + PINCTRL_PIN(13, "A13"), + PINCTRL_PIN(14, "A14"), + PINCTRL_PIN(15, "A15"), + PINCTRL_PIN(16, "B0"), + PINCTRL_PIN(17, "B1"), + PINCTRL_PIN(18, "B2"), + PINCTRL_PIN(19, "B3"), + PINCTRL_PIN(20, "B4"), + PINCTRL_PIN(21, "B5"), + PINCTRL_PIN(22, "B6"), + PINCTRL_PIN(23, "B7"), + PINCTRL_PIN(24, "B8"), + PINCTRL_PIN(25, "B9"), + PINCTRL_PIN(26, "B10"), + PINCTRL_PIN(27, "B11"), + PINCTRL_PIN(28, "B12"), + PINCTRL_PIN(29, "B13"), + PINCTRL_PIN(30, "B14"), + PINCTRL_PIN(31, "B15"), + PINCTRL_PIN(33, "C1"), + PINCTRL_PIN(34, "C2"), + PINCTRL_PIN(35, "C3"), + PINCTRL_PIN(36, "C4"), + PINCTRL_PIN(44, "C12"), + PINCTRL_PIN(45, "C13"), + PINCTRL_PIN(46, "C14"), + PINCTRL_PIN(47, "C15"), + PINCTRL_PIN(48, "D0"), + PINCTRL_PIN(49, "D1"), + PINCTRL_PIN(50, "D2"), + PINCTRL_PIN(51, "D3"), + PINCTRL_PIN(52, "D4"), + PINCTRL_PIN(53, "D5"), + PINCTRL_PIN(54, "D6"), + PINCTRL_PIN(55, "D7"), + PINCTRL_PIN(57, "D9"), + PINCTRL_PIN(58, "D10"), + PINCTRL_PIN(59, "D11"), + PINCTRL_PIN(60, "D12"), + PINCTRL_PIN(61, "D13"), + PINCTRL_PIN(62, "D14"), + PINCTRL_PIN(63, "D15"), + PINCTRL_PIN(64, "E0"), + PINCTRL_PIN(65, "E1"), + PINCTRL_PIN(66, "E2"), + PINCTRL_PIN(67, "E3"), + PINCTRL_PIN(68, "E4"), + PINCTRL_PIN(69, "E5"), + PINCTRL_PIN(70, "E6"), + PINCTRL_PIN(71, "E7"), + PINCTRL_PIN(72, "E8"), + PINCTRL_PIN(73, "E9"), + PINCTRL_PIN(80, "F0"), + PINCTRL_PIN(81, "F1"), + PINCTRL_PIN(82, "F2"), + PINCTRL_PIN(83, "F3"), + PINCTRL_PIN(84, "F4"), + PINCTRL_PIN(85, "F5"), + PINCTRL_PIN(88, "F8"), + PINCTRL_PIN(92, "F12"), + PINCTRL_PIN(93, "F13"), + PINCTRL_PIN(96, "G0"), + PINCTRL_PIN(97, "G1"), + PINCTRL_PIN(102, "G6"), + PINCTRL_PIN(103, "G7"), + PINCTRL_PIN(104, "G8"), + PINCTRL_PIN(105, "G9"), + PINCTRL_PIN(108, "G12"), + PINCTRL_PIN(109, "G13"), + PINCTRL_PIN(110, "G14"), + PINCTRL_PIN(111, "G15"), + PINCTRL_PIN(112, "H0"), + PINCTRL_PIN(113, "H1"), + PINCTRL_PIN(114, "H2"), + PINCTRL_PIN(115, "H3"), + PINCTRL_PIN(116, "H4"), + PINCTRL_PIN(117, "H5"), + PINCTRL_PIN(118, "H6"), + PINCTRL_PIN(119, "H7"), + PINCTRL_PIN(120, "H8"), + PINCTRL_PIN(121, "H9"), + PINCTRL_PIN(122, "H10"), + PINCTRL_PIN(123, "H11"), + PINCTRL_PIN(124, "H12"), + PINCTRL_PIN(125, "H13"), + PINCTRL_PIN(126, "H14"), + PINCTRL_PIN(127, "H15"), + PINCTRL_PIN(128, "J0"), + PINCTRL_PIN(129, "J1"), + PINCTRL_PIN(130, "J2"), + PINCTRL_PIN(131, "J3"), + PINCTRL_PIN(132, "J4"), + PINCTRL_PIN(133, "J5"), + PINCTRL_PIN(134, "J6"), + PINCTRL_PIN(135, "J7"), + PINCTRL_PIN(136, "J8"), + PINCTRL_PIN(137, "J9"), + PINCTRL_PIN(138, "J10"), + PINCTRL_PIN(139, "J11"), + PINCTRL_PIN(140, "J12"), + PINCTRL_PIN(141, "J13"), + PINCTRL_PIN(142, "J14"), + PINCTRL_PIN(143, "J15"), + PINCTRL_PIN(144, "K0"), + PINCTRL_PIN(145, "K1"), + PINCTRL_PIN(146, "K2"), + PINCTRL_PIN(147, "K3"), + PINCTRL_PIN(148, "K4"), + PINCTRL_PIN(149, "K5"), + PINCTRL_PIN(150, "K6"), + PINCTRL_PIN(151, "K7"), +}; + +static const char * const pic32_input0_group[] = { + "D2", "G8", "F4", "F1", "B9", "B10", "C14", "B5", + "C1", "D14", "G1", "A14", "D6", +}; + +static const char * const pic32_input1_group[] = { + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "G0", "A15", "D7", +}; + +static const char * const pic32_input2_group[] = { + "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7", + "F12", "D12", "F8", "C3", "E9", +}; + +static const char * const pic32_input3_group[] = { + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "F2", "C2", "E8", +}; + +static const char * const pic32_output0_group[] = { + "D2", "G8", "F4", "D10", "F1", "B9", "B10", "C14", + "B5", "C1", "D14", "G1", "A14", "D6", +}; + +static const char * const pic32_output0_1_group[] = { + "D2", "G8", "F4", "D10", "F1", "B9", "B10", "C14", + "B5", "C1", "D14", "G1", "A14", "D6", + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "D15", "G0", "A15", "D7", +}; + +static const char *const pic32_output1_group[] = { + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "D15", "G0", "A15", "D7", +}; + +static const char *const pic32_output1_3_group[] = { + "D3", "G7", "F5", "D11", "F0", "B1", "E5", "C13", + "B3", "C4", "D15", "G0", "A15", "D7", + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "C2", "E8", "F2", +}; + +static const char * const pic32_output2_group[] = { + "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7", + "F12", "D12", "F8", "C3", "E9", +}; + +static const char * const pic32_output2_3_group[] = { + "D9", "G6", "B8", "B15", "D4", "B0", "E3", "B7", + "F12", "D12", "F8", "C3", "E9", + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "C2", "E8", "F2", +}; + +static const char * const pic32_output3_group[] = { + "G9", "B14", "D0", "B6", "D5", "B2", "F3", "F13", + "C2", "E8", "F2", +}; + +#define FUNCTION(_name, _gr) \ + { \ + .name = #_name, \ + .groups = pic32_##_gr##_group, \ + .ngroups = ARRAY_SIZE(pic32_##_gr##_group), \ + } + +static const struct pic32_function pic32_functions[] = { + FUNCTION(INT3, input0), + FUNCTION(T2CK, input0), + FUNCTION(T6CK, input0), + FUNCTION(IC3, input0), + FUNCTION(IC7, input0), + FUNCTION(U1RX, input0), + FUNCTION(U2CTS, input0), + FUNCTION(U5RX, input0), + FUNCTION(U6CTS, input0), + FUNCTION(SDI1, input0), + FUNCTION(SDI3, input0), + FUNCTION(SDI5, input0), + FUNCTION(SS6IN, input0), + FUNCTION(REFCLKI1, input0), + FUNCTION(INT4, input1), + FUNCTION(T5CK, input1), + FUNCTION(T7CK, input1), + FUNCTION(IC4, input1), + FUNCTION(IC8, input1), + FUNCTION(U3RX, input1), + FUNCTION(U4CTS, input1), + FUNCTION(SDI2, input1), + FUNCTION(SDI4, input1), + FUNCTION(C1RX, input1), + FUNCTION(REFCLKI4, input1), + FUNCTION(INT2, input2), + FUNCTION(T3CK, input2), + FUNCTION(T8CK, input2), + FUNCTION(IC2, input2), + FUNCTION(IC5, input2), + FUNCTION(IC9, input2), + FUNCTION(U1CTS, input2), + FUNCTION(U2RX, input2), + FUNCTION(U5CTS, input2), + FUNCTION(SS1IN, input2), + FUNCTION(SS3IN, input2), + FUNCTION(SS4IN, input2), + FUNCTION(SS5IN, input2), + FUNCTION(C2RX, input2), + FUNCTION(INT1, input3), + FUNCTION(T4CK, input3), + FUNCTION(T9CK, input3), + FUNCTION(IC1, input3), + FUNCTION(IC6, input3), + FUNCTION(U3CTS, input3), + FUNCTION(U4RX, input3), + FUNCTION(U6RX, input3), + FUNCTION(SS2IN, input3), + FUNCTION(SDI6, input3), + FUNCTION(OCFA, input3), + FUNCTION(REFCLKI3, input3), + FUNCTION(U3TX, output0), + FUNCTION(U4RTS, output0), + FUNCTION(SDO1, output0_1), + FUNCTION(SDO2, output0_1), + FUNCTION(SDO3, output0_1), + FUNCTION(SDO5, output0_1), + FUNCTION(SS6OUT, output0), + FUNCTION(OC3, output0), + FUNCTION(OC6, output0), + FUNCTION(REFCLKO4, output0), + FUNCTION(C2OUT, output0), + FUNCTION(C1TX, output0), + FUNCTION(U1TX, output1), + FUNCTION(U2RTS, output1), + FUNCTION(U5TX, output1), + FUNCTION(U6RTS, output1), + FUNCTION(SDO4, output1_3), + FUNCTION(OC4, output1), + FUNCTION(OC7, output1), + FUNCTION(REFCLKO1, output1), + FUNCTION(U3RTS, output2), + FUNCTION(U4TX, output2), + FUNCTION(U6TX, output2_3), + FUNCTION(SS1OUT, output2), + FUNCTION(SS3OUT, output2), + FUNCTION(SS4OUT, output2), + FUNCTION(SS5OUT, output2), + FUNCTION(SDO6, output2_3), + FUNCTION(OC5, output2), + FUNCTION(OC8, output2), + FUNCTION(C1OUT, output2), + FUNCTION(REFCLKO3, output2), + FUNCTION(U1RTS, output3), + FUNCTION(U2TX, output3), + FUNCTION(U5RTS, output3), + FUNCTION(SS2OUT, output3), + FUNCTION(OC2, output3), + FUNCTION(OC1, output3), + FUNCTION(OC9, output3), + FUNCTION(C2TX, output3), +}; + +#define PIC32_PINCTRL_GROUP(_pin, _name, ...) \ + { \ + .name = #_name, \ + .pin = _pin, \ + .functions = (struct pic32_desc_function[]){ \ + __VA_ARGS__, { } }, \ + } + +#define PIC32_PINCTRL_FUNCTION(_name, _muxreg, _muxval) \ + { \ + .name = #_name, \ + .muxreg = _muxreg, \ + .muxval = _muxval, \ + } + +static const struct pic32_pin_group pic32_groups[] = { + PIC32_PINCTRL_GROUP(14, A14, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 13), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 13), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 13), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 13), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 13), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 13), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 13), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 13), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 13), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 13), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 13), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 13), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 13), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 13), + PIC32_PINCTRL_FUNCTION(U3TX, RPA14R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPA14R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPA14R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPA14R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPA14R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPA14R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPA14R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPA14R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPA14R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPA14R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPA14R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPA14R, 15)), + PIC32_PINCTRL_GROUP(15, A15, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 13), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 13), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 13), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 13), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 13), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 13), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 13), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 13), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 13), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 13), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 13), + PIC32_PINCTRL_FUNCTION(U1TX, RPA15R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPA15R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPA15R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPA15R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPA15R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPA15R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPA15R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPA15R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPA15R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPA15R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPA15R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPA15R, 15)), + PIC32_PINCTRL_GROUP(16, B0, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 5), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 5), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 5), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 5), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 5), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 5), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 5), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 5), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 5), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 5), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 5), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 5), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 5), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 5), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB0R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB0R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB0R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB0R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB0R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB0R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB0R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB0R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB0R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB0R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB0R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB0R, 15)), + PIC32_PINCTRL_GROUP(17, B1, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 5), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 5), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 5), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 5), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 5), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 5), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 5), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 5), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 5), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 5), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 5), + PIC32_PINCTRL_FUNCTION(U1TX, RPB1R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPB1R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPB1R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPB1R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPB1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB1R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPB1R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPB1R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPB1R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPB1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPB1R, 15)), + PIC32_PINCTRL_GROUP(18, B2, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 7), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 7), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 7), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 7), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 7), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 7), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 7), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 7), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 7), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 7), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 7), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 7), + PIC32_PINCTRL_FUNCTION(U1RTS, RPB2R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPB2R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPB2R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPB2R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPB2R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPB2R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPB2R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPB2R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPB2R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPB2R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPB2R, 15)), + PIC32_PINCTRL_GROUP(19, B3, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 8), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 8), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 8), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 8), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 8), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 8), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 8), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 8), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 8), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 8), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 8), + PIC32_PINCTRL_FUNCTION(U1TX, RPB3R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPB3R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPB3R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPB3R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPB3R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB3R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB3R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPB3R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPB3R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPB3R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPB3R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPB3R, 15)), + PIC32_PINCTRL_GROUP(21, B5, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 8), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 8), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 8), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 8), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 8), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 8), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 8), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 8), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 8), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 8), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 8), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 8), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 8), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 8), + PIC32_PINCTRL_FUNCTION(U3TX, RPB5R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPB5R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPB5R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB5R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB5R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPB5R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPB5R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPB5R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPB5R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB5R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPB5R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPB5R, 15)), + PIC32_PINCTRL_GROUP(22, B6, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 4), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 4), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 4), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 4), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 4), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 4), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 4), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 4), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 4), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 4), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 4), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 4), + PIC32_PINCTRL_FUNCTION(U1RTS, RPB6R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPB6R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPB6R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPB6R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPB6R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPB6R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPB6R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPB6R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPB6R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPB6R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPB6R, 15)), + PIC32_PINCTRL_GROUP(23, B7, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 7), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 7), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 7), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 7), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 7), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 7), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 7), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 7), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 7), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 7), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 7), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 7), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 7), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 7), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB7R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB7R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB7R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB7R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB7R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB7R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB7R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB7R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB7R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB7R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB7R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB7R, 15)), + PIC32_PINCTRL_GROUP(24, B8, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 2), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 2), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 2), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 2), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 2), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 2), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 2), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 2), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 2), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 2), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 2), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 2), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 2), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 2), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB8R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB8R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB8R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB8R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB8R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB8R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB8R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB8R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB8R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB8R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB8R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB8R, 15)), + PIC32_PINCTRL_GROUP(25, B9, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 5), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 5), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 5), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 5), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 5), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 5), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 5), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 5), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 5), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 5), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 5), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 5), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 5), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 5), + PIC32_PINCTRL_FUNCTION(U3TX, RPB9R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPB9R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPB9R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB9R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB9R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPB9R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPB9R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPB9R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPB9R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB9R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPB9R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPB9R, 15)), + PIC32_PINCTRL_GROUP(26, B10, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 6), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 6), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 6), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 6), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 6), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 6), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 6), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 6), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 6), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 6), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 6), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 6), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 6), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 6), + PIC32_PINCTRL_FUNCTION(U3TX, RPB10R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPB10R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPB10R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPB10R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPB10R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPB10R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPB10R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPB10R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPB10R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPB10R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPB10R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPB10R, 15)), + PIC32_PINCTRL_GROUP(30, B14, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 2), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 2), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 2), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 2), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 2), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 2), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 2), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 2), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 2), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 2), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 2), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 2), + PIC32_PINCTRL_FUNCTION(U1RTS, RPB14R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPB14R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPB14R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPB14R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPB14R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPB14R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPB14R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPB14R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPB14R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPB14R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPB14R, 15)), + PIC32_PINCTRL_GROUP(31, B15, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 3), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 3), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 3), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 3), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 3), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 3), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 3), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 3), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 3), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 3), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 3), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 3), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 3), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 3), + PIC32_PINCTRL_FUNCTION(U3RTS, RPB15R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPB15R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPB15R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPB15R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPB15R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPB15R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPB15R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPB15R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPB15R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPB15R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPB15R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPB15R, 15)), + PIC32_PINCTRL_GROUP(33, C1, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 10), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 10), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 10), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 10), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 10), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 10), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 10), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 10), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 10), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 10), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 10), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 10), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 10), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 10), + PIC32_PINCTRL_FUNCTION(U3TX, RPC1R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPC1R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPC1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC1R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPC1R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPC1R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPC1R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPC1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPC1R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPC1R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPC1R, 15)), + PIC32_PINCTRL_GROUP(34, C2, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 12), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 12), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 12), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 12), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 12), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 12), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 12), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 12), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 12), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 12), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 12), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 12), + PIC32_PINCTRL_FUNCTION(U1RTS, RPC2R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPC2R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPC2R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPC2R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPC2R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPC2R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPC2R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPC2R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPC2R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPC2R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPC2R, 15)), + PIC32_PINCTRL_GROUP(35, C3, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 12), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 12), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 12), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 12), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 12), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 12), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 12), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 12), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 12), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 12), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 12), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 12), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 12), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 12), + PIC32_PINCTRL_FUNCTION(U3RTS, RPC3R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPC3R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPC3R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPC3R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPC3R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPC3R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPC3R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPC3R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPC3R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPC3R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPC3R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPC3R, 15)), + PIC32_PINCTRL_GROUP(36, C4, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 10), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 10), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 10), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 10), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 10), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 10), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 10), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 10), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 10), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 10), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 10), + PIC32_PINCTRL_FUNCTION(U1TX, RPC4R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPC4R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPC4R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPC4R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPC4R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC4R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC4R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPC4R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPC4R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPC4R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPC4R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPC4R, 15)), + PIC32_PINCTRL_GROUP(45, C13, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 7), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 7), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 7), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 7), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 7), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 7), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 7), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 7), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 7), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 7), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 7), + PIC32_PINCTRL_FUNCTION(U1TX, RPC13R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPC13R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPC13R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPC13R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPC13R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC13R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC13R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPC13R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPC13R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPC13R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPC13R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPC13R, 15)), + PIC32_PINCTRL_GROUP(46, C14, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 7), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 7), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 7), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 7), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 7), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 7), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 7), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 7), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 7), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 7), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 7), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 7), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 7), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 7), + PIC32_PINCTRL_FUNCTION(U3TX, RPC14R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPC14R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPC14R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPC14R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPC14R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPC14R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPC14R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPC14R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPC14R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPC14R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPC14R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPC14R, 15)), + PIC32_PINCTRL_GROUP(48, D0, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 3), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 3), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 3), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 3), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 3), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 3), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 3), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 3), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 3), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 3), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 3), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 3), + PIC32_PINCTRL_FUNCTION(U1RTS, RPD0R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPD0R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPD0R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPD0R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPD0R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPD0R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPD0R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPD0R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPD0R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPD0R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPD0R, 15)), + PIC32_PINCTRL_GROUP(50, D2, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 0), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 0), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 0), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 0), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 0), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 0), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 0), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 0), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 0), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 0), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 0), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 0), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 0), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 0), + PIC32_PINCTRL_FUNCTION(U3TX, RPD2R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD2R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD2R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD2R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD2R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD2R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD2R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD2R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD2R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD2R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD2R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD2R, 15)), + PIC32_PINCTRL_GROUP(51, D3, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 0), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 0), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 0), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 0), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 0), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 0), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 0), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 0), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 0), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 0), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 0), + PIC32_PINCTRL_FUNCTION(U1TX, RPD3R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD3R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD3R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD3R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD3R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD3R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD3R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD3R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD3R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD3R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD3R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD3R, 15)), + PIC32_PINCTRL_GROUP(52, D4, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 4), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 4), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 4), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 4), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 4), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 4), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 4), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 4), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 4), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 4), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 4), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 4), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 4), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 4), + PIC32_PINCTRL_FUNCTION(U3RTS, RPD4R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPD4R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPD4R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPD4R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPD4R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPD4R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPD4R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPD4R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPD4R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPD4R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPD4R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD4R, 15)), + PIC32_PINCTRL_GROUP(53, D5, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 6), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 6), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 6), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 6), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 6), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 6), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 6), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 6), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 6), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 6), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 6), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 6), + PIC32_PINCTRL_FUNCTION(U1RTS, RPD5R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPD5R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPD5R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPD5R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPD5R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPD5R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPD5R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPD5R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPD5R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPD5R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPD5R, 15)), + PIC32_PINCTRL_GROUP(54, D6, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 14), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 14), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 14), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 14), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 14), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 14), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 14), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 14), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 14), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 14), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 14), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 14), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 14), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 14), + PIC32_PINCTRL_FUNCTION(U3TX, RPD6R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD6R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD6R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD6R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD6R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD6R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD6R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD6R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD6R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD6R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD6R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD6R, 15)), + PIC32_PINCTRL_GROUP(55, D7, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 14), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 14), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 14), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 14), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 14), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 14), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 14), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 14), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 14), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 14), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 14), + PIC32_PINCTRL_FUNCTION(U1TX, RPD7R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD7R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD7R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD7R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD7R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD7R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD7R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD7R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD7R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD7R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD7R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD7R, 15)), + PIC32_PINCTRL_GROUP(57, D9, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 0), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 0), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 0), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 0), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 0), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 0), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 0), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 0), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 0), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 0), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 0), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 0), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 0), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 0), + PIC32_PINCTRL_FUNCTION(U3RTS, RPD9R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPD9R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPD9R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPD9R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPD9R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPD9R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPD9R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPD9R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPD9R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPD9R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPD9R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD9R, 15)), + PIC32_PINCTRL_GROUP(58, D10, + PIC32_PINCTRL_FUNCTION(U3TX, RPD10R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD10R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD10R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD10R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD10R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD10R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD10R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD10R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD10R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD10R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD10R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD10R, 15)), + PIC32_PINCTRL_GROUP(59, D11, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 3), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 3), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 3), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 3), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 3), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 3), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 3), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 3), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 3), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 3), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 3), + PIC32_PINCTRL_FUNCTION(U1TX, RPD11R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD11R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD11R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD11R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD11R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD11R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD11R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD11R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD11R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD11R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD11R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD11R, 15)), + PIC32_PINCTRL_GROUP(60, D12, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 10), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 10), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 10), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 10), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 10), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 10), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 10), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 10), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 10), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 10), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 10), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 10), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 10), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 10), + PIC32_PINCTRL_FUNCTION(U3RTS, RPD12R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPD12R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPD12R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPD12R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPD12R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPD12R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPD12R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPD12R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPD12R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPD12R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPD12R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPD12R, 15)), + PIC32_PINCTRL_GROUP(62, D14, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 11), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 11), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 11), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 11), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 11), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 11), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 11), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 11), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 11), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 11), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 11), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 11), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 11), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 11), + PIC32_PINCTRL_FUNCTION(U3TX, RPD14R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPD14R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPD14R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD14R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD14R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPD14R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPD14R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPD14R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPD14R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPD14R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPD14R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPD14R, 15)), + PIC32_PINCTRL_GROUP(63, D15, + PIC32_PINCTRL_FUNCTION(U1TX, RPD15R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPD15R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPD15R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPD15R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPD15R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPD15R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPD15R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPD15R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPD15R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPD15R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPD15R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPD15R, 15)), + PIC32_PINCTRL_GROUP(67, E3, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 6), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 6), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 6), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 6), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 6), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 6), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 6), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 6), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 6), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 6), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 6), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 6), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 6), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 6), + PIC32_PINCTRL_FUNCTION(U3RTS, RPE3R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPE3R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPE3R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPE3R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPE3R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPE3R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPE3R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPE3R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPE3R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPE3R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPE3R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPE3R, 15)), + PIC32_PINCTRL_GROUP(69, E5, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 6), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 6), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 6), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 6), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 6), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 6), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 6), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 6), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 6), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 6), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 6), + PIC32_PINCTRL_FUNCTION(U1TX, RPE5R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPE5R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPE5R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPE5R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPE5R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPE5R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPE5R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPE5R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPE5R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPE5R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPE5R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPE5R, 15)), + PIC32_PINCTRL_GROUP(72, E8, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 13), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 13), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 13), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 13), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 13), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 13), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 13), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 13), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 13), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 13), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 13), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 13), + PIC32_PINCTRL_FUNCTION(U1RTS, RPE8R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPE8R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPE8R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPE8R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPE8R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPE8R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPE8R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPE8R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPE8R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPE8R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPE8R, 15)), + PIC32_PINCTRL_GROUP(73, E9, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 13), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 13), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 13), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 13), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 13), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 13), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 13), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 13), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 13), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 13), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 13), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 13), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 13), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 13), + PIC32_PINCTRL_FUNCTION(U3RTS, RPE9R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPE9R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPE9R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPE9R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPE9R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPE9R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPE9R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPE9R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPE9R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPE9R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPE9R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPE9R, 15)), + PIC32_PINCTRL_GROUP(80, F0, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 4), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 4), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 4), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 4), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 4), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 4), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 4), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 4), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 4), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 4), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 4), + PIC32_PINCTRL_FUNCTION(U1TX, RPF0R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPF0R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPF0R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPF0R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPF0R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF0R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF0R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPF0R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPF0R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPF0R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPF0R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPF0R, 15)), + PIC32_PINCTRL_GROUP(81, F1, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 4), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 4), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 4), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 4), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 4), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 4), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 4), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 4), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 4), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 4), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 4), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 4), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 4), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 4), + PIC32_PINCTRL_FUNCTION(U3TX, RPF1R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPF1R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPF1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF1R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPF1R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPF1R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPF1R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPF1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPF1R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPF1R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPF1R, 15)), + PIC32_PINCTRL_GROUP(82, F2, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 11), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 11), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 11), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 11), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 11), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 11), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 11), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 11), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 11), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 11), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 11), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 11), + PIC32_PINCTRL_FUNCTION(U1RTS, RPF2R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPF2R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPF2R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPF2R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPF2R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPF2R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPF2R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPF2R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPF2R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPF2R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPF2R, 15)), + PIC32_PINCTRL_GROUP(83, F3, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 8), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 8), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 8), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 8), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 8), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 8), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 8), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 8), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 8), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 8), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 8), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 8), + PIC32_PINCTRL_FUNCTION(U1RTS, RPF3R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPF3R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPF3R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPF3R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPF3R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPF3R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPF3R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPF3R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPF3R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPF3R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPF3R, 15)), + PIC32_PINCTRL_GROUP(84, F4, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 2), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 2), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 2), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 2), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 2), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 2), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 2), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 2), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 2), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 2), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 2), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 2), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 2), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 2), + PIC32_PINCTRL_FUNCTION(U3TX, RPF4R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPF4R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPF4R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF4R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF4R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPF4R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPF4R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPF4R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPF4R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPF4R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPF4R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPF4R, 15)), + PIC32_PINCTRL_GROUP(85, F5, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 2), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 2), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 2), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 2), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 2), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 2), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 2), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 2), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 2), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 2), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 2), + PIC32_PINCTRL_FUNCTION(U1TX, RPF5R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPF5R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPF5R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPF5R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPF5R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPF5R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPF5R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPF5R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPF5R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPF5R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPF5R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPF5R, 15)), + PIC32_PINCTRL_GROUP(88, F8, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 11), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 11), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 11), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 11), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 11), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 11), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 11), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 11), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 11), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 11), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 11), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 11), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 11), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 11), + PIC32_PINCTRL_FUNCTION(U3RTS, RPF8R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPF8R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPF8R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPF8R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPF8R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPF8R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPF8R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPF8R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPF8R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPF8R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPF8R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPF8R, 15)), + PIC32_PINCTRL_GROUP(92, F12, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 9), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 9), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 9), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 9), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 9), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 9), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 9), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 9), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 9), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 9), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 9), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 9), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 9), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 9), + PIC32_PINCTRL_FUNCTION(U3RTS, RPF12R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPF12R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPF12R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPF12R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPF12R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPF12R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPF12R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPF12R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPF12R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPF12R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPF12R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPF12R, 15)), + PIC32_PINCTRL_GROUP(93, F13, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 9), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 9), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 9), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 9), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 9), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 9), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 9), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 9), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 9), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 9), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 9), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 9), + PIC32_PINCTRL_FUNCTION(U1RTS, RPF13R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPF13R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPF13R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPF13R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPF13R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPF13R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPF13R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPF13R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPF13R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPF13R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPF13R, 15)), + PIC32_PINCTRL_GROUP(96, G0, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 12), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 12), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 12), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 12), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 12), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 12), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 12), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 12), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 12), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 12), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 12), + PIC32_PINCTRL_FUNCTION(U1TX, RPG0R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPG0R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPG0R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPG0R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPG0R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG0R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG0R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPG0R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPG0R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPG0R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPG0R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPG0R, 15)), + PIC32_PINCTRL_GROUP(97, G1, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 12), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 12), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 12), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 12), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 12), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 12), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 12), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 12), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 12), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 12), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 12), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 12), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 12), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 12), + PIC32_PINCTRL_FUNCTION(U3TX, RPG1R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPG1R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPG1R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG1R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG1R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPG1R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPG1R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPG1R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPG1R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPG1R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPG1R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPG1R, 15)), + PIC32_PINCTRL_GROUP(102, G6, + PIC32_PINCTRL_FUNCTION(INT2, INT2R, 1), + PIC32_PINCTRL_FUNCTION(T3CK, T3CKR, 1), + PIC32_PINCTRL_FUNCTION(T8CK, T8CKR, 1), + PIC32_PINCTRL_FUNCTION(IC2, IC2R, 1), + PIC32_PINCTRL_FUNCTION(IC5, IC5R, 1), + PIC32_PINCTRL_FUNCTION(IC9, IC9R, 1), + PIC32_PINCTRL_FUNCTION(U1CTS, U1CTSR, 1), + PIC32_PINCTRL_FUNCTION(U2RX, U2RXR, 1), + PIC32_PINCTRL_FUNCTION(U5CTS, U5CTSR, 1), + PIC32_PINCTRL_FUNCTION(SS1IN, SS1INR, 1), + PIC32_PINCTRL_FUNCTION(SS3IN, SS3INR, 1), + PIC32_PINCTRL_FUNCTION(SS4IN, SS4INR, 1), + PIC32_PINCTRL_FUNCTION(SS5IN, SS5INR, 1), + PIC32_PINCTRL_FUNCTION(C2RX, C2RXR, 1), + PIC32_PINCTRL_FUNCTION(U3RTS, RPG6R, 1), + PIC32_PINCTRL_FUNCTION(U4TX, RPG6R, 2), + PIC32_PINCTRL_FUNCTION(U6TX, RPG6R, 4), + PIC32_PINCTRL_FUNCTION(SS1OUT, RPG6R, 5), + PIC32_PINCTRL_FUNCTION(SS3OUT, RPG6R, 7), + PIC32_PINCTRL_FUNCTION(SS4OUT, RPG6R, 8), + PIC32_PINCTRL_FUNCTION(SS5OUT, RPG6R, 9), + PIC32_PINCTRL_FUNCTION(SDO6, RPG6R, 10), + PIC32_PINCTRL_FUNCTION(OC5, RPG6R, 11), + PIC32_PINCTRL_FUNCTION(OC8, RPG6R, 12), + PIC32_PINCTRL_FUNCTION(C1OUT, RPG6R, 14), + PIC32_PINCTRL_FUNCTION(REFCLKO3, RPG6R, 15)), + PIC32_PINCTRL_GROUP(103, G7, + PIC32_PINCTRL_FUNCTION(INT4, INT4R, 1), + PIC32_PINCTRL_FUNCTION(T5CK, T5CKR, 1), + PIC32_PINCTRL_FUNCTION(T7CK, T7CKR, 1), + PIC32_PINCTRL_FUNCTION(IC4, IC4R, 1), + PIC32_PINCTRL_FUNCTION(IC8, IC8R, 1), + PIC32_PINCTRL_FUNCTION(U3RX, U3RXR, 1), + PIC32_PINCTRL_FUNCTION(U4CTS, U4CTSR, 1), + PIC32_PINCTRL_FUNCTION(SDI2, SDI2R, 1), + PIC32_PINCTRL_FUNCTION(SDI4, SDI4R, 1), + PIC32_PINCTRL_FUNCTION(C1RX, C1RXR, 1), + PIC32_PINCTRL_FUNCTION(REFCLKI4, REFCLKI4R, 1), + PIC32_PINCTRL_FUNCTION(U1TX, RPG7R, 1), + PIC32_PINCTRL_FUNCTION(U2RTS, RPG7R, 2), + PIC32_PINCTRL_FUNCTION(U5TX, RPG7R, 3), + PIC32_PINCTRL_FUNCTION(U6RTS, RPG7R, 4), + PIC32_PINCTRL_FUNCTION(SDO1, RPG7R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG7R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG7R, 7), + PIC32_PINCTRL_FUNCTION(SDO4, RPG7R, 8), + PIC32_PINCTRL_FUNCTION(SDO5, RPG7R, 9), + PIC32_PINCTRL_FUNCTION(OC4, RPG7R, 11), + PIC32_PINCTRL_FUNCTION(OC7, RPG7R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO1, RPG7R, 15)), + PIC32_PINCTRL_GROUP(104, G8, + PIC32_PINCTRL_FUNCTION(INT3, INT3R, 1), + PIC32_PINCTRL_FUNCTION(T2CK, T2CKR, 1), + PIC32_PINCTRL_FUNCTION(T6CK, T6CKR, 1), + PIC32_PINCTRL_FUNCTION(IC3, IC3R, 1), + PIC32_PINCTRL_FUNCTION(IC7, IC7R, 1), + PIC32_PINCTRL_FUNCTION(U1RX, U1RXR, 1), + PIC32_PINCTRL_FUNCTION(U2CTS, U2CTSR, 1), + PIC32_PINCTRL_FUNCTION(U5RX, U5RXR, 1), + PIC32_PINCTRL_FUNCTION(U6CTS, U6CTSR, 1), + PIC32_PINCTRL_FUNCTION(SDI1, SDI1R, 1), + PIC32_PINCTRL_FUNCTION(SDI3, SDI3R, 1), + PIC32_PINCTRL_FUNCTION(SDI5, SDI5R, 1), + PIC32_PINCTRL_FUNCTION(SS6IN, SS6INR, 1), + PIC32_PINCTRL_FUNCTION(REFCLKI1, REFCLKI1R, 1), + PIC32_PINCTRL_FUNCTION(U3TX, RPG8R, 1), + PIC32_PINCTRL_FUNCTION(U4RTS, RPG8R, 2), + PIC32_PINCTRL_FUNCTION(SDO1, RPG8R, 5), + PIC32_PINCTRL_FUNCTION(SDO2, RPG8R, 6), + PIC32_PINCTRL_FUNCTION(SDO3, RPG8R, 7), + PIC32_PINCTRL_FUNCTION(SDO5, RPG8R, 9), + PIC32_PINCTRL_FUNCTION(SS6OUT, RPG8R, 10), + PIC32_PINCTRL_FUNCTION(OC3, RPG8R, 11), + PIC32_PINCTRL_FUNCTION(OC6, RPG8R, 12), + PIC32_PINCTRL_FUNCTION(REFCLKO4, RPG8R, 13), + PIC32_PINCTRL_FUNCTION(C2OUT, RPG8R, 14), + PIC32_PINCTRL_FUNCTION(C1TX, RPG8R, 15)), + PIC32_PINCTRL_GROUP(105, G9, + PIC32_PINCTRL_FUNCTION(INT1, INT1R, 1), + PIC32_PINCTRL_FUNCTION(T4CK, T4CKR, 1), + PIC32_PINCTRL_FUNCTION(T9CK, T9CKR, 1), + PIC32_PINCTRL_FUNCTION(IC1, IC1R, 1), + PIC32_PINCTRL_FUNCTION(IC6, IC6R, 1), + PIC32_PINCTRL_FUNCTION(U3CTS, U3CTSR, 1), + PIC32_PINCTRL_FUNCTION(U4RX, U4RXR, 1), + PIC32_PINCTRL_FUNCTION(U6RX, U6RXR, 1), + PIC32_PINCTRL_FUNCTION(SS2IN, SS2INR, 1), + PIC32_PINCTRL_FUNCTION(SDI6, SDI6R, 1), + PIC32_PINCTRL_FUNCTION(OCFA, OCFAR, 1), + PIC32_PINCTRL_FUNCTION(REFCLKI3, REFCLKI3R, 1), + PIC32_PINCTRL_FUNCTION(U1RTS, RPG9R, 1), + PIC32_PINCTRL_FUNCTION(U2TX, RPG9R, 2), + PIC32_PINCTRL_FUNCTION(U5RTS, RPG9R, 3), + PIC32_PINCTRL_FUNCTION(U6TX, RPG9R, 4), + PIC32_PINCTRL_FUNCTION(SS2OUT, RPG9R, 6), + PIC32_PINCTRL_FUNCTION(SDO4, RPG9R, 8), + PIC32_PINCTRL_FUNCTION(SDO6, RPG9R, 10), + PIC32_PINCTRL_FUNCTION(OC2, RPG9R, 11), + PIC32_PINCTRL_FUNCTION(OC1, RPG9R, 12), + PIC32_PINCTRL_FUNCTION(OC9, RPG9R, 13), + PIC32_PINCTRL_FUNCTION(C2TX, RPG9R, 15)), +}; + +static inline struct pic32_gpio_bank *irqd_to_bank(struct irq_data *d) +{ + return gpiochip_get_data(irq_data_get_irq_chip_data(d)); +} + +static inline struct pic32_gpio_bank *pctl_to_bank(struct pic32_pinctrl *pctl, + unsigned pin) +{ + return &pctl->gpio_banks[pin / PINS_PER_BANK]; +} + +static int pic32_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->ngroups; +} + +static const char *pic32_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned group) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->groups[group].name; +} + +static int pic32_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned group, + const unsigned **pins, + unsigned *num_pins) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *pins = &pctl->groups[group].pin; + *num_pins = 1; + + return 0; +} + +static const struct pinctrl_ops pic32_pinctrl_ops = { + .get_groups_count = pic32_pinctrl_get_groups_count, + .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, +}; + +static int pic32_pinmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->nfunctions; +} + +static const char * +pic32_pinmux_get_function_name(struct pinctrl_dev *pctldev, unsigned func) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + return pctl->functions[func].name; +} + +static int pic32_pinmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned func, + const char * const **groups, + unsigned * const num_groups) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pctl->functions[func].groups; + *num_groups = pctl->functions[func].ngroups; + + return 0; +} + +static int pic32_pinmux_enable(struct pinctrl_dev *pctldev, + unsigned func, unsigned group) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + const struct pic32_pin_group *pg = &pctl->groups[group]; + const struct pic32_function *pf = &pctl->functions[func]; + const char *fname = pf->name; + struct pic32_desc_function *functions = pg->functions; + + while (functions->name) { + if (!strcmp(functions->name, fname)) { + dev_dbg(pctl->dev, + "setting function %s reg 0x%x = %d\n", + fname, functions->muxreg, functions->muxval); + + writel(functions->muxval, pctl->reg_base + functions->muxreg); + + return 0; + } + + functions++; + } + + dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func); + + return -EINVAL; +} + +static int pic32_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pic32_gpio_bank *bank = gpiochip_get_data(range->gc); + u32 mask = BIT(offset - bank->gpio_chip.base); + + dev_dbg(pctl->dev, "requesting gpio %d in bank %d with mask 0x%x\n", + offset, bank->gpio_chip.base, mask); + + writel(mask, bank->reg_base + PIC32_CLR(ANSEL_REG)); + + return 0; +} + +static int pic32_gpio_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + u32 mask = BIT(offset); + + writel(mask, bank->reg_base + PIC32_SET(TRIS_REG)); + + return 0; +} + +static int pic32_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + + return !!(readl(bank->reg_base + PORT_REG) & BIT(offset)); +} + +static void pic32_gpio_set(struct gpio_chip *chip, unsigned offset, + int value) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + u32 mask = BIT(offset); + + if (value) + writel(mask, bank->reg_base + PIC32_SET(PORT_REG)); + else + writel(mask, bank->reg_base + PIC32_CLR(PORT_REG)); +} + +static int pic32_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + u32 mask = BIT(offset); + + pic32_gpio_set(chip, offset, value); + writel(mask, bank->reg_base + PIC32_CLR(TRIS_REG)); + + return 0; +} + +static int pic32_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned offset, bool input) +{ + struct gpio_chip *chip = range->gc; + + if (input) + pic32_gpio_direction_input(chip, offset); + else + pic32_gpio_direction_output(chip, offset, 0); + + return 0; +} + +static const struct pinmux_ops pic32_pinmux_ops = { + .get_functions_count = pic32_pinmux_get_functions_count, + .get_function_name = pic32_pinmux_get_function_name, + .get_function_groups = pic32_pinmux_get_function_groups, + .set_mux = pic32_pinmux_enable, + .gpio_request_enable = pic32_gpio_request_enable, + .gpio_set_direction = pic32_gpio_set_direction, +}; + +static int pic32_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pic32_gpio_bank *bank = pctl_to_bank(pctl, pin); + unsigned param = pinconf_to_config_param(*config); + u32 mask = BIT(pin - bank->gpio_chip.base); + u32 arg; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + arg = !!(readl(bank->reg_base + CNPU_REG) & mask); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = !!(readl(bank->reg_base + CNPD_REG) & mask); + break; + case PIN_CONFIG_MICROCHIP_DIGITAL: + arg = !(readl(bank->reg_base + ANSEL_REG) & mask); + break; + case PIN_CONFIG_MICROCHIP_ANALOG: + arg = !!(readl(bank->reg_base + ANSEL_REG) & mask); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + arg = !!(readl(bank->reg_base + ODCU_REG) & mask); + break; + case PIN_CONFIG_INPUT_ENABLE: + arg = !!(readl(bank->reg_base + TRIS_REG) & mask); + break; + case PIN_CONFIG_OUTPUT: + arg = !(readl(bank->reg_base + TRIS_REG) & mask); + break; + default: + dev_err(pctl->dev, "Property %u not supported\n", param); + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int pic32_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, unsigned num_configs) +{ + struct pic32_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct pic32_gpio_bank *bank = pctl_to_bank(pctl, pin); + unsigned param; + u32 arg; + unsigned int i; + u32 offset = pin - bank->gpio_chip.base; + u32 mask = BIT(offset); + + dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n", + pin, bank->gpio_chip.base, mask); + + 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_PULL_UP: + dev_dbg(pctl->dev, " pullup\n"); + writel(mask, bank->reg_base +PIC32_SET(CNPU_REG)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + dev_dbg(pctl->dev, " pulldown\n"); + writel(mask, bank->reg_base + PIC32_SET(CNPD_REG)); + break; + case PIN_CONFIG_MICROCHIP_DIGITAL: + dev_dbg(pctl->dev, " digital\n"); + writel(mask, bank->reg_base + PIC32_CLR(ANSEL_REG)); + break; + case PIN_CONFIG_MICROCHIP_ANALOG: + dev_dbg(pctl->dev, " analog\n"); + writel(mask, bank->reg_base + PIC32_SET(ANSEL_REG)); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + dev_dbg(pctl->dev, " opendrain\n"); + writel(mask, bank->reg_base + PIC32_SET(ODCU_REG)); + break; + case PIN_CONFIG_INPUT_ENABLE: + pic32_gpio_direction_input(&bank->gpio_chip, offset); + break; + case PIN_CONFIG_OUTPUT: + pic32_gpio_direction_output(&bank->gpio_chip, + offset, arg); + break; + default: + dev_err(pctl->dev, "Property %u not supported\n", + param); + return -ENOTSUPP; + } + } + + return 0; +} + +static const struct pinconf_ops pic32_pinconf_ops = { + .pin_config_get = pic32_pinconf_get, + .pin_config_set = pic32_pinconf_set, + .is_generic = true, +}; + +static struct pinctrl_desc pic32_pinctrl_desc = { + .name = "pic32-pinctrl", + .pctlops = &pic32_pinctrl_ops, + .pmxops = &pic32_pinmux_ops, + .confops = &pic32_pinconf_ops, + .owner = THIS_MODULE, +}; + +static int pic32_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(chip); + + return !!(readl(bank->reg_base + TRIS_REG) & BIT(offset)); +} + +static void pic32_gpio_irq_ack(struct irq_data *data) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + + writel(0, bank->reg_base + CNF_REG); +} + +static void pic32_gpio_irq_mask(struct irq_data *data) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + + writel(BIT(PIC32_CNCON_ON), bank->reg_base + PIC32_CLR(CNCON_REG)); +} + +static void pic32_gpio_irq_unmask(struct irq_data *data) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + + writel(BIT(PIC32_CNCON_ON), bank->reg_base + PIC32_SET(CNCON_REG)); +} + +static unsigned int pic32_gpio_irq_startup(struct irq_data *data) +{ + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + + pic32_gpio_direction_input(chip, data->hwirq); + pic32_gpio_irq_unmask(data); + + return 0; +} + +static int pic32_gpio_irq_set_type(struct irq_data *data, unsigned int type) +{ + struct pic32_gpio_bank *bank = irqd_to_bank(data); + u32 mask = BIT(data->hwirq); + + switch (type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_EDGE_RISING: + /* enable RISE */ + writel(mask, bank->reg_base + PIC32_SET(CNEN_REG)); + /* disable FALL */ + writel(mask, bank->reg_base + PIC32_CLR(CNNE_REG)); + /* enable EDGE */ + writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG)); + break; + case IRQ_TYPE_EDGE_FALLING: + /* disable RISE */ + writel(mask, bank->reg_base + PIC32_CLR(CNEN_REG)); + /* enable FALL */ + writel(mask, bank->reg_base + PIC32_SET(CNNE_REG)); + /* enable EDGE */ + writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG)); + break; + case IRQ_TYPE_EDGE_BOTH: + /* enable RISE */ + writel(mask, bank->reg_base + PIC32_SET(CNEN_REG)); + /* enable FALL */ + writel(mask, bank->reg_base + PIC32_SET(CNNE_REG)); + /* enable EDGE */ + writel(BIT(PIC32_CNCON_EDGE), bank->reg_base + PIC32_SET(CNCON_REG)); + break; + default: + return -EINVAL; + } + + irq_set_handler_locked(data, handle_edge_irq); + + return 0; +} + +static u32 pic32_gpio_get_pending(struct gpio_chip *gc, unsigned long status) +{ + struct pic32_gpio_bank *bank = gpiochip_get_data(gc); + u32 pending = 0; + u32 cnen_rise, cnne_fall; + u32 pin; + + cnen_rise = readl(bank->reg_base + CNEN_REG); + cnne_fall = readl(bank->reg_base + CNNE_REG); + + for_each_set_bit(pin, &status, BITS_PER_LONG) { + u32 mask = BIT(pin); + + if ((mask & cnen_rise) || (mask && cnne_fall)) + pending |= mask; + } + + return pending; +} + +static void pic32_gpio_irq_handler(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct pic32_gpio_bank *bank = gpiochip_get_data(gc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long pending; + unsigned int pin; + u32 stat; + + chained_irq_enter(chip, desc); + + stat = readl(bank->reg_base + CNF_REG); + pending = pic32_gpio_get_pending(gc, stat); + + for_each_set_bit(pin, &pending, BITS_PER_LONG) + generic_handle_irq(irq_linear_revmap(gc->irqdomain, pin)); + + chained_irq_exit(chip, desc); +} + +#define GPIO_BANK(_bank, _npins) \ + { \ + .gpio_chip = { \ + .label = "GPIO" #_bank, \ + .request = gpiochip_generic_request, \ + .free = gpiochip_generic_free, \ + .get_direction = pic32_gpio_get_direction, \ + .direction_input = pic32_gpio_direction_input, \ + .direction_output = pic32_gpio_direction_output, \ + .get = pic32_gpio_get, \ + .set = pic32_gpio_set, \ + .ngpio = _npins, \ + .base = GPIO_BANK_START(_bank), \ + .owner = THIS_MODULE, \ + .can_sleep = 0, \ + }, \ + .irq_chip = { \ + .name = "GPIO" #_bank, \ + .irq_startup = pic32_gpio_irq_startup, \ + .irq_ack = pic32_gpio_irq_ack, \ + .irq_mask = pic32_gpio_irq_mask, \ + .irq_unmask = pic32_gpio_irq_unmask, \ + .irq_set_type = pic32_gpio_irq_set_type, \ + }, \ + } + +static struct pic32_gpio_bank pic32_gpio_banks[] = { + GPIO_BANK(0, PINS_PER_BANK), + GPIO_BANK(1, PINS_PER_BANK), + GPIO_BANK(2, PINS_PER_BANK), + GPIO_BANK(3, PINS_PER_BANK), + GPIO_BANK(4, PINS_PER_BANK), + GPIO_BANK(5, PINS_PER_BANK), + GPIO_BANK(6, PINS_PER_BANK), + GPIO_BANK(7, PINS_PER_BANK), + GPIO_BANK(8, PINS_PER_BANK), + GPIO_BANK(9, PINS_PER_BANK), +}; + +static int pic32_pinctrl_probe(struct platform_device *pdev) +{ + struct pic32_pinctrl *pctl; + struct resource *res; + int ret; + + pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL); + if (!pctl) + return -ENOMEM; + pctl->dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, pctl); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pctl->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pctl->reg_base)) + return PTR_ERR(pctl->reg_base); + + pctl->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pctl->clk)) { + ret = PTR_ERR(pctl->clk); + dev_err(&pdev->dev, "clk get failed\n"); + return ret; + } + + ret = clk_prepare_enable(pctl->clk); + if (ret) { + dev_err(&pdev->dev, "clk enable failed\n"); + return ret; + } + + pctl->pins = pic32_pins; + pctl->npins = ARRAY_SIZE(pic32_pins); + pctl->functions = pic32_functions; + pctl->nfunctions = ARRAY_SIZE(pic32_functions); + pctl->groups = pic32_groups; + pctl->ngroups = ARRAY_SIZE(pic32_groups); + pctl->gpio_banks = pic32_gpio_banks; + pctl->nbanks = ARRAY_SIZE(pic32_gpio_banks); + + pic32_pinctrl_desc.pins = pctl->pins; + pic32_pinctrl_desc.npins = pctl->npins; + 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); + if (IS_ERR(pctl->pctldev)) { + dev_err(&pdev->dev, "Failed to register pinctrl device\n"); + return PTR_ERR(pctl->pctldev); + } + + return 0; +} + +static int pic32_gpio_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct pic32_gpio_bank *bank; + u32 id; + int irq, ret; + struct resource *res; + + if (of_property_read_u32(np, "microchip,gpio-bank", &id)) { + dev_err(&pdev->dev, "microchip,gpio-bank property not found\n"); + return -EINVAL; + } + + if (id >= ARRAY_SIZE(pic32_gpio_banks)) { + dev_err(&pdev->dev, "invalid microchip,gpio-bank property\n"); + return -EINVAL; + } + + bank = &pic32_gpio_banks[id]; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + bank->reg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(bank->reg_base)) + return PTR_ERR(bank->reg_base); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "irq get failed\n"); + return irq; + } + + bank->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(bank->clk)) { + ret = PTR_ERR(bank->clk); + dev_err(&pdev->dev, "clk get failed\n"); + return ret; + } + + ret = clk_prepare_enable(bank->clk); + if (ret) { + dev_err(&pdev->dev, "clk enable failed\n"); + return ret; + } + + bank->gpio_chip.parent = &pdev->dev; + bank->gpio_chip.of_node = np; + ret = gpiochip_add_data(&bank->gpio_chip, bank); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to add GPIO chip %u: %d\n", + id, ret); + return ret; + } + + ret = gpiochip_irqchip_add(&bank->gpio_chip, &bank->irq_chip, + 0, handle_level_irq, IRQ_TYPE_NONE); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to add IRQ chip %u: %d\n", + id, ret); + gpiochip_remove(&bank->gpio_chip); + return ret; + } + + gpiochip_set_chained_irqchip(&bank->gpio_chip, &bank->irq_chip, + irq, pic32_gpio_irq_handler); + + return 0; +} + +static const struct of_device_id pic32_pinctrl_of_match[] = { + { .compatible = "microchip,pic32mzda-pinctrl", }, + { }, +}; + +static struct platform_driver pic32_pinctrl_driver = { + .driver = { + .name = "pic32-pinctrl", + .of_match_table = pic32_pinctrl_of_match, + .suppress_bind_attrs = true, + }, + .probe = pic32_pinctrl_probe, +}; + +static const struct of_device_id pic32_gpio_of_match[] = { + { .compatible = "microchip,pic32mzda-gpio", }, + { }, +}; + +static struct platform_driver pic32_gpio_driver = { + .driver = { + .name = "pic32-gpio", + .of_match_table = pic32_gpio_of_match, + .suppress_bind_attrs = true, + }, + .probe = pic32_gpio_probe, +}; + +static int __init pic32_gpio_register(void) +{ + return platform_driver_register(&pic32_gpio_driver); +} +arch_initcall(pic32_gpio_register); + +static int __init pic32_pinctrl_register(void) +{ + return platform_driver_register(&pic32_pinctrl_driver); +} +arch_initcall(pic32_pinctrl_register); diff --git a/drivers/pinctrl/pinctrl-pic32.h b/drivers/pinctrl/pinctrl-pic32.h new file mode 100644 index 000000000000..12826267dc96 --- /dev/null +++ b/drivers/pinctrl/pinctrl-pic32.h @@ -0,0 +1,141 @@ +/* + * PIC32 pinctrl driver + * + * Joshua Henderson, + * Copyright (C) 2015 Microchip Technology Inc. All rights reserved. + * + * 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. + */ +#ifndef PINCTRL_PINCTRL_PIC32_H +#define PINCTRL_PINCTRL_PIC32_H + +/* PORT Registers */ +#define ANSEL_REG 0x00 +#define TRIS_REG 0x10 +#define PORT_REG 0x20 +#define LAT_REG 0x30 +#define ODCU_REG 0x40 +#define CNPU_REG 0x50 +#define CNPD_REG 0x60 +#define CNCON_REG 0x70 +#define CNEN_REG 0x80 +#define CNSTAT_REG 0x90 +#define CNNE_REG 0xA0 +#define CNF_REG 0xB0 + +/* Input PPS Registers */ +#define INT1R 0x04 +#define INT2R 0x08 +#define INT3R 0x0C +#define INT4R 0x10 +#define T2CKR 0x18 +#define T3CKR 0x1C +#define T4CKR 0x20 +#define T5CKR 0x24 +#define T6CKR 0x28 +#define T7CKR 0x2C +#define T8CKR 0x30 +#define T9CKR 0x34 +#define IC1R 0x38 +#define IC2R 0x3C +#define IC3R 0x40 +#define IC4R 0x44 +#define IC5R 0x48 +#define IC6R 0x4C +#define IC7R 0x50 +#define IC8R 0x54 +#define IC9R 0x58 +#define OCFAR 0x60 +#define U1RXR 0x68 +#define U1CTSR 0x6C +#define U2RXR 0x70 +#define U2CTSR 0x74 +#define U3RXR 0x78 +#define U3CTSR 0x7C +#define U4RXR 0x80 +#define U4CTSR 0x84 +#define U5RXR 0x88 +#define U5CTSR 0x8C +#define U6RXR 0x90 +#define U6CTSR 0x94 +#define SDI1R 0x9C +#define SS1INR 0xA0 +#define SDI2R 0xA8 +#define SS2INR 0xAC +#define SDI3R 0xB4 +#define SS3INR 0xB8 +#define SDI4R 0xC0 +#define SS4INR 0xC4 +#define SDI5R 0xCC +#define SS5INR 0xD0 +#define SDI6R 0xD8 +#define SS6INR 0xDC +#define C1RXR 0xE0 +#define C2RXR 0xE4 +#define REFCLKI1R 0xE8 +#define REFCLKI3R 0xF0 +#define REFCLKI4R 0xF4 + +/* Output PPS Registers */ +#define RPA14R 0x138 +#define RPA15R 0x13C +#define RPB0R 0x140 +#define RPB1R 0x144 +#define RPB2R 0x148 +#define RPB3R 0x14C +#define RPB5R 0x154 +#define RPB6R 0x158 +#define RPB7R 0x15C +#define RPB8R 0x160 +#define RPB9R 0x164 +#define RPB10R 0x168 +#define RPB14R 0x178 +#define RPB15R 0x17C +#define RPC1R 0x184 +#define RPC2R 0x188 +#define RPC3R 0x18C +#define RPC4R 0x190 +#define RPC13R 0x1B4 +#define RPC14R 0x1B8 +#define RPD0R 0x1C0 +#define RPD1R 0x1C4 +#define RPD2R 0x1C8 +#define RPD3R 0x1CC +#define RPD4R 0x1D0 +#define RPD5R 0x1D4 +#define RPD6R 0x1D8 +#define RPD7R 0x1DC +#define RPD9R 0x1E4 +#define RPD10R 0x1E8 +#define RPD11R 0x1EC +#define RPD12R 0x1F0 +#define RPD14R 0x1F8 +#define RPD15R 0x1FC +#define RPE3R 0x20C +#define RPE5R 0x214 +#define RPE8R 0x220 +#define RPE9R 0x224 +#define RPF0R 0x240 +#define RPF1R 0x244 +#define RPF2R 0x248 +#define RPF3R 0x24C +#define RPF4R 0x250 +#define RPF5R 0x254 +#define RPF8R 0x260 +#define RPF12R 0x270 +#define RPF13R 0x274 +#define RPG0R 0x280 +#define RPG1R 0x284 +#define RPG6R 0x298 +#define RPG7R 0x29C +#define RPG8R 0x2A0 +#define RPG9R 0x2A4 + +#endif /* PINCTRL_PINCTRL_PIC32_H */ -- cgit From 0660511c0beeccdc240479f29d5ecd8362115be3 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:49 +0800 Subject: crypto: tcrypt - Use ahash This patch removes the last user of the obsolete crypto_hash interface, tcrypt, by simply switching it over to ahash. In fact it already has all the code there so it's just a matter of calling the ahash speed test code with the right mask. Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 239 ++++---------------------------------------------------- 1 file changed, 15 insertions(+), 224 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 270bc4b82bd9..579dce071463 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -554,164 +554,6 @@ out: crypto_free_blkcipher(tfm); } -static int test_hash_jiffies_digest(struct hash_desc *desc, - struct scatterlist *sg, int blen, - char *out, int secs) -{ - unsigned long start, end; - int bcount; - int ret; - - for (start = jiffies, end = start + secs * HZ, bcount = 0; - time_before(jiffies, end); bcount++) { - ret = crypto_hash_digest(desc, sg, blen, out); - if (ret) - return ret; - } - - printk("%6u opers/sec, %9lu bytes/sec\n", - bcount / secs, ((long)bcount * blen) / secs); - - return 0; -} - -static int test_hash_jiffies(struct hash_desc *desc, struct scatterlist *sg, - int blen, int plen, char *out, int secs) -{ - unsigned long start, end; - int bcount, pcount; - int ret; - - if (plen == blen) - return test_hash_jiffies_digest(desc, sg, blen, out, secs); - - for (start = jiffies, end = start + secs * HZ, bcount = 0; - time_before(jiffies, end); bcount++) { - ret = crypto_hash_init(desc); - if (ret) - return ret; - for (pcount = 0; pcount < blen; pcount += plen) { - ret = crypto_hash_update(desc, sg, plen); - if (ret) - return ret; - } - /* we assume there is enough space in 'out' for the result */ - ret = crypto_hash_final(desc, out); - if (ret) - return ret; - } - - printk("%6u opers/sec, %9lu bytes/sec\n", - bcount / secs, ((long)bcount * blen) / secs); - - return 0; -} - -static int test_hash_cycles_digest(struct hash_desc *desc, - struct scatterlist *sg, int blen, char *out) -{ - unsigned long cycles = 0; - int i; - int ret; - - local_irq_disable(); - - /* Warm-up run. */ - for (i = 0; i < 4; i++) { - ret = crypto_hash_digest(desc, sg, blen, out); - if (ret) - goto out; - } - - /* The real thing. */ - for (i = 0; i < 8; i++) { - cycles_t start, end; - - start = get_cycles(); - - ret = crypto_hash_digest(desc, sg, blen, out); - if (ret) - goto out; - - end = get_cycles(); - - cycles += end - start; - } - -out: - local_irq_enable(); - - if (ret) - return ret; - - printk("%6lu cycles/operation, %4lu cycles/byte\n", - cycles / 8, cycles / (8 * blen)); - - return 0; -} - -static int test_hash_cycles(struct hash_desc *desc, struct scatterlist *sg, - int blen, int plen, char *out) -{ - unsigned long cycles = 0; - int i, pcount; - int ret; - - if (plen == blen) - return test_hash_cycles_digest(desc, sg, blen, out); - - local_irq_disable(); - - /* Warm-up run. */ - for (i = 0; i < 4; i++) { - ret = crypto_hash_init(desc); - if (ret) - goto out; - for (pcount = 0; pcount < blen; pcount += plen) { - ret = crypto_hash_update(desc, sg, plen); - if (ret) - goto out; - } - ret = crypto_hash_final(desc, out); - if (ret) - goto out; - } - - /* The real thing. */ - for (i = 0; i < 8; i++) { - cycles_t start, end; - - start = get_cycles(); - - ret = crypto_hash_init(desc); - if (ret) - goto out; - for (pcount = 0; pcount < blen; pcount += plen) { - ret = crypto_hash_update(desc, sg, plen); - if (ret) - goto out; - } - ret = crypto_hash_final(desc, out); - if (ret) - goto out; - - end = get_cycles(); - - cycles += end - start; - } - -out: - local_irq_enable(); - - if (ret) - return ret; - - printk("%6lu cycles/operation, %4lu cycles/byte\n", - cycles / 8, cycles / (8 * blen)); - - return 0; -} - static void test_hash_sg_init(struct scatterlist *sg) { int i; @@ -723,69 +565,6 @@ static void test_hash_sg_init(struct scatterlist *sg) } } -static void test_hash_speed(const char *algo, unsigned int secs, - struct hash_speed *speed) -{ - struct scatterlist sg[TVMEMSIZE]; - struct crypto_hash *tfm; - struct hash_desc desc; - static char output[1024]; - int i; - int ret; - - tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC); - - if (IS_ERR(tfm)) { - printk(KERN_ERR "failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); - return; - } - - printk(KERN_INFO "\ntesting speed of %s (%s)\n", algo, - get_driver_name(crypto_hash, tfm)); - - desc.tfm = tfm; - desc.flags = 0; - - if (crypto_hash_digestsize(tfm) > sizeof(output)) { - printk(KERN_ERR "digestsize(%u) > outputbuffer(%zu)\n", - crypto_hash_digestsize(tfm), sizeof(output)); - goto out; - } - - test_hash_sg_init(sg); - for (i = 0; speed[i].blen != 0; i++) { - if (speed[i].blen > TVMEMSIZE * PAGE_SIZE) { - printk(KERN_ERR - "template (%u) too big for tvmem (%lu)\n", - speed[i].blen, TVMEMSIZE * PAGE_SIZE); - goto out; - } - - if (speed[i].klen) - crypto_hash_setkey(tfm, tvmem[0], speed[i].klen); - - printk(KERN_INFO "test%3u " - "(%5u byte blocks,%5u bytes per update,%4u updates): ", - i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); - - if (secs) - ret = test_hash_jiffies(&desc, sg, speed[i].blen, - speed[i].plen, output, secs); - else - ret = test_hash_cycles(&desc, sg, speed[i].blen, - speed[i].plen, output); - - if (ret) { - printk(KERN_ERR "hashing failed ret=%d\n", ret); - break; - } - } - -out: - crypto_free_hash(tfm); -} - static inline int do_one_ahash_op(struct ahash_request *req, int ret) { if (ret == -EINPROGRESS || ret == -EBUSY) { @@ -945,8 +724,8 @@ out: return 0; } -static void test_ahash_speed(const char *algo, unsigned int secs, - struct hash_speed *speed) +static void test_ahash_speed_common(const char *algo, unsigned int secs, + struct hash_speed *speed, unsigned mask) { struct scatterlist sg[TVMEMSIZE]; struct tcrypt_result tresult; @@ -955,7 +734,7 @@ static void test_ahash_speed(const char *algo, unsigned int secs, char *output; int i, ret; - tfm = crypto_alloc_ahash(algo, 0, 0); + tfm = crypto_alloc_ahash(algo, 0, mask); if (IS_ERR(tfm)) { pr_err("failed to load transform for %s: %ld\n", algo, PTR_ERR(tfm)); @@ -1021,6 +800,18 @@ out: crypto_free_ahash(tfm); } +static void test_ahash_speed(const char *algo, unsigned int secs, + struct hash_speed *speed) +{ + return test_ahash_speed_common(algo, secs, speed, 0); +} + +static void test_hash_speed(const char *algo, unsigned int secs, + struct hash_speed *speed) +{ + return test_ahash_speed_common(algo, secs, speed, CRYPTO_ALG_ASYNC); +} + static inline int do_one_acipher_op(struct ablkcipher_request *req, int ret) { if (ret == -EINPROGRESS || ret == -EBUSY) { -- cgit From 8bc618d6a2e05f8f4d26d46b63d19ddfdcba7869 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:50 +0800 Subject: crypto: doc - Use ahash This patch replaces the crypto_hash example in api-intro.txt with crypto_ahash. Signed-off-by: Herbert Xu --- Documentation/crypto/api-intro.txt | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt index 8b49302712a8..beda682e8d77 100644 --- a/Documentation/crypto/api-intro.txt +++ b/Documentation/crypto/api-intro.txt @@ -49,28 +49,33 @@ under development. Here's an example of how to use the API: - #include + #include #include #include struct scatterlist sg[2]; char result[128]; - struct crypto_hash *tfm; - struct hash_desc desc; + struct crypto_ahash *tfm; + struct ahash_request *req; - tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC); if (IS_ERR(tfm)) fail(); /* ... set up the scatterlists ... */ - desc.tfm = tfm; - desc.flags = 0; - - if (crypto_hash_digest(&desc, sg, 2, result)) + req = ahash_request_alloc(tfm, GFP_ATOMIC); + if (!req) fail(); + + ahash_request_set_callback(req, 0, NULL, NULL); + ahash_request_set_crypt(req, sg, result, 2); - crypto_free_hash(tfm); + if (crypto_ahash_digest(req)) + fail(); + + ahash_request_free(req); + crypto_free_ahash(tfm); Many real examples are available in the regression test module (tcrypt.c). -- cgit From 92b3cad3af31250a2b26d586f91c9962d626a7ed Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:51 +0800 Subject: crypto: skcipher - Fix driver name helper The helper crypto_skcipher_driver_name was returning the alg name and not the driver name. Signed-off-by: Herbert Xu --- include/crypto/skcipher.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h index 5bb70565b13a..905490c1da89 100644 --- a/include/crypto/skcipher.h +++ b/include/crypto/skcipher.h @@ -234,7 +234,7 @@ static inline int crypto_has_skcipher(const char *alg_name, u32 type, static inline const char *crypto_skcipher_driver_name( struct crypto_skcipher *tfm) { - return crypto_tfm_alg_name(crypto_skcipher_tfm(tfm)); + return crypto_tfm_alg_driver_name(crypto_skcipher_tfm(tfm)); } /** -- cgit From d12481bc58fba89427565f8592e88446ec084a24 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:52 +0800 Subject: crypto: hash - Add helpers to return alg and driver names This patch adds helpers to retrieve the alg name and driver name of crypto_shash and crypto_ahash objects. Signed-off-by: Herbert Xu --- include/crypto/hash.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/crypto/hash.h b/include/crypto/hash.h index f855efaa2f8c..1969f1416658 100644 --- a/include/crypto/hash.h +++ b/include/crypto/hash.h @@ -272,6 +272,16 @@ static inline void crypto_free_ahash(struct crypto_ahash *tfm) */ int crypto_has_ahash(const char *alg_name, u32 type, u32 mask); +static inline const char *crypto_ahash_alg_name(struct crypto_ahash *tfm) +{ + return crypto_tfm_alg_name(crypto_ahash_tfm(tfm)); +} + +static inline const char *crypto_ahash_driver_name(struct crypto_ahash *tfm) +{ + return crypto_tfm_alg_driver_name(crypto_ahash_tfm(tfm)); +} + static inline unsigned int crypto_ahash_alignmask( struct crypto_ahash *tfm) { @@ -676,6 +686,16 @@ static inline void crypto_free_shash(struct crypto_shash *tfm) crypto_destroy_tfm(tfm, crypto_shash_tfm(tfm)); } +static inline const char *crypto_shash_alg_name(struct crypto_shash *tfm) +{ + return crypto_tfm_alg_name(crypto_shash_tfm(tfm)); +} + +static inline const char *crypto_shash_driver_name(struct crypto_shash *tfm) +{ + return crypto_tfm_alg_driver_name(crypto_shash_tfm(tfm)); +} + static inline unsigned int crypto_shash_alignmask( struct crypto_shash *tfm) { -- cgit From 6dae10001e84253992142c7343fdae16a13f3d73 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:53 +0800 Subject: staging: lustre: Use ahash This patch replaces uses of the long obsolete hash interface with ahash. Signed-off-by: Herbert Xu Acked-by: Greg Kroah-Hartman --- .../lustre/lustre/libcfs/linux/linux-crypto.c | 92 ++++++++++++---------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c index 079d50ebfa3a..94c01aad844b 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c @@ -27,7 +27,7 @@ * Copyright (c) 2012, Intel Corporation. */ -#include +#include #include #include "../../../include/linux/libcfs/libcfs.h" #include "linux-crypto.h" @@ -38,9 +38,11 @@ static int cfs_crypto_hash_speeds[CFS_HASH_ALG_MAX]; static int cfs_crypto_hash_alloc(unsigned char alg_id, const struct cfs_crypto_hash_type **type, - struct hash_desc *desc, unsigned char *key, + struct ahash_request **req, + unsigned char *key, unsigned int key_len) { + struct crypto_ahash *tfm; int err = 0; *type = cfs_crypto_hash_type(alg_id); @@ -50,18 +52,23 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, alg_id, CFS_HASH_ALG_MAX); return -EINVAL; } - desc->tfm = crypto_alloc_hash((*type)->cht_name, 0, 0); + tfm = crypto_alloc_ahash((*type)->cht_name, 0, CRYPTO_ALG_ASYNC); - if (desc->tfm == NULL) - return -EINVAL; - - if (IS_ERR(desc->tfm)) { + if (IS_ERR(tfm)) { CDEBUG(D_INFO, "Failed to alloc crypto hash %s\n", (*type)->cht_name); - return PTR_ERR(desc->tfm); + return PTR_ERR(tfm); } - desc->flags = 0; + *req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!*req) { + CDEBUG(D_INFO, "Failed to alloc ahash_request for %s\n", + (*type)->cht_name); + crypto_free_ahash(tfm); + return -ENOMEM; + } + + ahash_request_set_callback(*req, 0, NULL, NULL); /** Shash have different logic for initialization then digest * shash: crypto_hash_setkey, crypto_hash_init @@ -70,23 +77,27 @@ static int cfs_crypto_hash_alloc(unsigned char alg_id, * cfs_crypto_hash_alloc. */ if (key != NULL) - err = crypto_hash_setkey(desc->tfm, key, key_len); + err = crypto_ahash_setkey(tfm, key, key_len); else if ((*type)->cht_key != 0) - err = crypto_hash_setkey(desc->tfm, + err = crypto_ahash_setkey(tfm, (unsigned char *)&((*type)->cht_key), (*type)->cht_size); if (err != 0) { - crypto_free_hash(desc->tfm); + crypto_free_ahash(tfm); return err; } CDEBUG(D_INFO, "Using crypto hash: %s (%s) speed %d MB/s\n", - (crypto_hash_tfm(desc->tfm))->__crt_alg->cra_name, - (crypto_hash_tfm(desc->tfm))->__crt_alg->cra_driver_name, + crypto_ahash_alg_name(tfm), crypto_ahash_driver_name(tfm), cfs_crypto_hash_speeds[alg_id]); - return crypto_hash_init(desc); + err = crypto_ahash_init(*req); + if (err) { + ahash_request_free(*req); + crypto_free_ahash(tfm); + } + return err; } int cfs_crypto_hash_digest(unsigned char alg_id, @@ -95,27 +106,29 @@ int cfs_crypto_hash_digest(unsigned char alg_id, unsigned char *hash, unsigned int *hash_len) { struct scatterlist sl; - struct hash_desc hdesc; + struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; if (buf == NULL || buf_len == 0 || hash_len == NULL) return -EINVAL; - err = cfs_crypto_hash_alloc(alg_id, &type, &hdesc, key, key_len); + err = cfs_crypto_hash_alloc(alg_id, &type, &req, key, key_len); if (err != 0) return err; if (hash == NULL || *hash_len < type->cht_size) { *hash_len = type->cht_size; - crypto_free_hash(hdesc.tfm); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return -ENOSPC; } sg_init_one(&sl, buf, buf_len); - hdesc.flags = 0; - err = crypto_hash_digest(&hdesc, &sl, sl.length, hash); - crypto_free_hash(hdesc.tfm); + ahash_request_set_crypt(req, &sl, hash, sl.length); + err = crypto_ahash_digest(req); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return err; } @@ -125,22 +138,15 @@ struct cfs_crypto_hash_desc * cfs_crypto_hash_init(unsigned char alg_id, unsigned char *key, unsigned int key_len) { - - struct hash_desc *hdesc; + struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; - hdesc = kmalloc(sizeof(*hdesc), 0); - if (hdesc == NULL) - return ERR_PTR(-ENOMEM); + err = cfs_crypto_hash_alloc(alg_id, &type, &req, key, key_len); - err = cfs_crypto_hash_alloc(alg_id, &type, hdesc, key, key_len); - - if (err) { - kfree(hdesc); + if (err) return ERR_PTR(err); - } - return (struct cfs_crypto_hash_desc *)hdesc; + return (struct cfs_crypto_hash_desc *)req; } EXPORT_SYMBOL(cfs_crypto_hash_init); @@ -148,23 +154,27 @@ int cfs_crypto_hash_update_page(struct cfs_crypto_hash_desc *hdesc, struct page *page, unsigned int offset, unsigned int len) { + struct ahash_request *req = (void *)hdesc; struct scatterlist sl; sg_init_table(&sl, 1); sg_set_page(&sl, page, len, offset & ~CFS_PAGE_MASK); - return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length); + ahash_request_set_crypt(req, &sl, NULL, sl.length); + return crypto_ahash_update(req); } EXPORT_SYMBOL(cfs_crypto_hash_update_page); int cfs_crypto_hash_update(struct cfs_crypto_hash_desc *hdesc, const void *buf, unsigned int buf_len) { + struct ahash_request *req = (void *)hdesc; struct scatterlist sl; sg_init_one(&sl, buf, buf_len); - return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length); + ahash_request_set_crypt(req, &sl, NULL, sl.length); + return crypto_ahash_update(req); } EXPORT_SYMBOL(cfs_crypto_hash_update); @@ -173,25 +183,27 @@ int cfs_crypto_hash_final(struct cfs_crypto_hash_desc *hdesc, unsigned char *hash, unsigned int *hash_len) { int err; - int size = crypto_hash_digestsize(((struct hash_desc *)hdesc)->tfm); + struct ahash_request *req = (void *)hdesc; + int size = crypto_ahash_digestsize(crypto_ahash_reqtfm(req)); if (hash_len == NULL) { - crypto_free_hash(((struct hash_desc *)hdesc)->tfm); - kfree(hdesc); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return 0; } if (hash == NULL || *hash_len < size) { *hash_len = size; return -ENOSPC; } - err = crypto_hash_final((struct hash_desc *) hdesc, hash); + ahash_request_set_crypt(req, NULL, hash, 0); + err = crypto_ahash_final(req); if (err < 0) { /* May be caller can fix error */ return err; } - crypto_free_hash(((struct hash_desc *)hdesc)->tfm); - kfree(hdesc); + crypto_free_ahash(crypto_ahash_reqtfm(req)); + ahash_request_free(req); return err; } EXPORT_SYMBOL(cfs_crypto_hash_final); -- cgit From 896545098777564212b9e91af4c973f094649aa7 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Mon, 1 Feb 2016 21:36:54 +0800 Subject: crypto: hash - Remove crypto_hash interface This patch removes all traces of the crypto_hash interface, now that everyone has switched over to shash or ahash. Signed-off-by: Herbert Xu --- Documentation/DocBook/crypto-API.tmpl | 13 -- crypto/ahash.c | 18 --- crypto/shash.c | 147 -------------------- include/crypto/algapi.h | 18 --- include/crypto/internal/hash.h | 3 - include/linux/crypto.h | 251 ---------------------------------- 6 files changed, 450 deletions(-) diff --git a/Documentation/DocBook/crypto-API.tmpl b/Documentation/DocBook/crypto-API.tmpl index 07df23ea06e4..866ff082272b 100644 --- a/Documentation/DocBook/crypto-API.tmpl +++ b/Documentation/DocBook/crypto-API.tmpl @@ -1761,19 +1761,6 @@ read(opfd, out, outlen); !Finclude/linux/crypto.h crypto_cipher_setkey !Finclude/linux/crypto.h crypto_cipher_encrypt_one !Finclude/linux/crypto.h crypto_cipher_decrypt_one - - Synchronous Message Digest API -!Pinclude/linux/crypto.h Synchronous Message Digest API -!Finclude/linux/crypto.h crypto_alloc_hash -!Finclude/linux/crypto.h crypto_free_hash -!Finclude/linux/crypto.h crypto_has_hash -!Finclude/linux/crypto.h crypto_hash_blocksize -!Finclude/linux/crypto.h crypto_hash_digestsize -!Finclude/linux/crypto.h crypto_hash_init -!Finclude/linux/crypto.h crypto_hash_update -!Finclude/linux/crypto.h crypto_hash_final -!Finclude/linux/crypto.h crypto_hash_digest -!Finclude/linux/crypto.h crypto_hash_setkey Message Digest Algorithm Definitions !Pinclude/crypto/hash.h Message Digest Algorithm Definitions diff --git a/crypto/ahash.c b/crypto/ahash.c index 8b08a59221a6..5fc1f172963d 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -166,24 +166,6 @@ int crypto_ahash_walk_first(struct ahash_request *req, } EXPORT_SYMBOL_GPL(crypto_ahash_walk_first); -int crypto_hash_walk_first_compat(struct hash_desc *hdesc, - struct crypto_hash_walk *walk, - struct scatterlist *sg, unsigned int len) -{ - walk->total = len; - - if (!walk->total) { - walk->entrylen = 0; - return 0; - } - - walk->alignmask = crypto_hash_alignmask(hdesc->tfm); - walk->sg = sg; - walk->flags = hdesc->flags & CRYPTO_TFM_REQ_MASK; - - return hash_walk_new_entry(walk); -} - static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { diff --git a/crypto/shash.c b/crypto/shash.c index 88a27de79848..472bc141f50d 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -369,151 +369,6 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm) return 0; } -static int shash_compat_setkey(struct crypto_hash *tfm, const u8 *key, - unsigned int keylen) -{ - struct shash_desc **descp = crypto_hash_ctx(tfm); - struct shash_desc *desc = *descp; - - return crypto_shash_setkey(desc->tfm, key, keylen); -} - -static int shash_compat_init(struct hash_desc *hdesc) -{ - struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); - struct shash_desc *desc = *descp; - - desc->flags = hdesc->flags; - - return crypto_shash_init(desc); -} - -static int shash_compat_update(struct hash_desc *hdesc, struct scatterlist *sg, - unsigned int len) -{ - struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); - struct shash_desc *desc = *descp; - struct crypto_hash_walk walk; - int nbytes; - - for (nbytes = crypto_hash_walk_first_compat(hdesc, &walk, sg, len); - nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) - nbytes = crypto_shash_update(desc, walk.data, nbytes); - - return nbytes; -} - -static int shash_compat_final(struct hash_desc *hdesc, u8 *out) -{ - struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); - - return crypto_shash_final(*descp, out); -} - -static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg, - unsigned int nbytes, u8 *out) -{ - unsigned int offset = sg->offset; - int err; - - if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { - struct shash_desc **descp = crypto_hash_ctx(hdesc->tfm); - struct shash_desc *desc = *descp; - void *data; - - desc->flags = hdesc->flags; - - data = kmap_atomic(sg_page(sg)); - err = crypto_shash_digest(desc, data + offset, nbytes, out); - kunmap_atomic(data); - crypto_yield(desc->flags); - goto out; - } - - err = shash_compat_init(hdesc); - if (err) - goto out; - - err = shash_compat_update(hdesc, sg, nbytes); - if (err) - goto out; - - err = shash_compat_final(hdesc, out); - -out: - return err; -} - -static void crypto_exit_shash_ops_compat(struct crypto_tfm *tfm) -{ - struct shash_desc **descp = crypto_tfm_ctx(tfm); - struct shash_desc *desc = *descp; - - crypto_free_shash(desc->tfm); - kzfree(desc); -} - -static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm) -{ - struct hash_tfm *crt = &tfm->crt_hash; - struct crypto_alg *calg = tfm->__crt_alg; - struct shash_alg *alg = __crypto_shash_alg(calg); - struct shash_desc **descp = crypto_tfm_ctx(tfm); - struct crypto_shash *shash; - struct shash_desc *desc; - - if (!crypto_mod_get(calg)) - return -EAGAIN; - - shash = crypto_create_tfm(calg, &crypto_shash_type); - if (IS_ERR(shash)) { - crypto_mod_put(calg); - return PTR_ERR(shash); - } - - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(shash), - GFP_KERNEL); - if (!desc) { - crypto_free_shash(shash); - return -ENOMEM; - } - - *descp = desc; - desc->tfm = shash; - tfm->exit = crypto_exit_shash_ops_compat; - - crt->init = shash_compat_init; - crt->update = shash_compat_update; - crt->final = shash_compat_final; - crt->digest = shash_compat_digest; - crt->setkey = shash_compat_setkey; - - crt->digestsize = alg->digestsize; - - return 0; -} - -static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) -{ - switch (mask & CRYPTO_ALG_TYPE_MASK) { - case CRYPTO_ALG_TYPE_HASH_MASK: - return crypto_init_shash_ops_compat(tfm); - } - - return -EINVAL; -} - -static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, - u32 mask) -{ - switch (mask & CRYPTO_ALG_TYPE_MASK) { - case CRYPTO_ALG_TYPE_HASH_MASK: - return sizeof(struct shash_desc *); - } - - return 0; -} - static int crypto_shash_init_tfm(struct crypto_tfm *tfm) { struct crypto_shash *hash = __crypto_shash_cast(tfm); @@ -560,9 +415,7 @@ static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg) } static const struct crypto_type crypto_shash_type = { - .ctxsize = crypto_shash_ctxsize, .extsize = crypto_alg_extsize, - .init = crypto_init_shash_ops, .init_tfm = crypto_shash_init_tfm, #ifdef CONFIG_PROC_FS .show = crypto_shash_show, diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index b09d43f612e1..eeafd21afb44 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -349,24 +349,6 @@ static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm) return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher; } -static inline struct crypto_hash *crypto_spawn_hash(struct crypto_spawn *spawn) -{ - u32 type = CRYPTO_ALG_TYPE_HASH; - u32 mask = CRYPTO_ALG_TYPE_HASH_MASK; - - return __crypto_hash_cast(crypto_spawn_tfm(spawn, type, mask)); -} - -static inline void *crypto_hash_ctx(struct crypto_hash *tfm) -{ - return crypto_tfm_ctx(&tfm->base); -} - -static inline void *crypto_hash_ctx_aligned(struct crypto_hash *tfm) -{ - return crypto_tfm_ctx_aligned(&tfm->base); -} - static inline void blkcipher_walk_init(struct blkcipher_walk *walk, struct scatterlist *dst, struct scatterlist *src, diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index 3b4af1d7c7e9..49dae16f8929 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -57,9 +57,6 @@ int crypto_hash_walk_first(struct ahash_request *req, struct crypto_hash_walk *walk); int crypto_ahash_walk_first(struct ahash_request *req, struct crypto_hash_walk *walk); -int crypto_hash_walk_first_compat(struct hash_desc *hdesc, - struct crypto_hash_walk *walk, - struct scatterlist *sg, unsigned int len); static inline int crypto_ahash_walk_done(struct crypto_hash_walk *walk, int err) diff --git a/include/linux/crypto.h b/include/linux/crypto.h index ab2a745d85f3..99c94899ad0f 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -136,7 +136,6 @@ struct scatterlist; struct crypto_ablkcipher; struct crypto_async_request; struct crypto_blkcipher; -struct crypto_hash; struct crypto_tfm; struct crypto_type; struct skcipher_givcrypt_request; @@ -186,11 +185,6 @@ struct cipher_desc { void *info; }; -struct hash_desc { - struct crypto_hash *tfm; - u32 flags; -}; - /** * DOC: Block Cipher Algorithm Definitions * @@ -518,18 +512,6 @@ struct cipher_tfm { void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); }; -struct hash_tfm { - int (*init)(struct hash_desc *desc); - int (*update)(struct hash_desc *desc, - struct scatterlist *sg, unsigned int nsg); - int (*final)(struct hash_desc *desc, u8 *out); - int (*digest)(struct hash_desc *desc, struct scatterlist *sg, - unsigned int nsg, u8 *out); - int (*setkey)(struct crypto_hash *tfm, const u8 *key, - unsigned int keylen); - unsigned int digestsize; -}; - struct compress_tfm { int (*cot_compress)(struct crypto_tfm *tfm, const u8 *src, unsigned int slen, @@ -542,7 +524,6 @@ struct compress_tfm { #define crt_ablkcipher crt_u.ablkcipher #define crt_blkcipher crt_u.blkcipher #define crt_cipher crt_u.cipher -#define crt_hash crt_u.hash #define crt_compress crt_u.compress struct crypto_tfm { @@ -553,7 +534,6 @@ struct crypto_tfm { struct ablkcipher_tfm ablkcipher; struct blkcipher_tfm blkcipher; struct cipher_tfm cipher; - struct hash_tfm hash; struct compress_tfm compress; } crt_u; @@ -580,10 +560,6 @@ struct crypto_comp { struct crypto_tfm base; }; -struct crypto_hash { - struct crypto_tfm base; -}; - enum { CRYPTOA_UNSPEC, CRYPTOA_ALG, @@ -1576,233 +1552,6 @@ static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, dst, src); } -/** - * DOC: Synchronous Message Digest API - * - * The synchronous message digest API is used with the ciphers of type - * CRYPTO_ALG_TYPE_HASH (listed as type "hash" in /proc/crypto) - */ - -static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm) -{ - return (struct crypto_hash *)tfm; -} - -static inline struct crypto_hash *crypto_hash_cast(struct crypto_tfm *tfm) -{ - BUG_ON((crypto_tfm_alg_type(tfm) ^ CRYPTO_ALG_TYPE_HASH) & - CRYPTO_ALG_TYPE_HASH_MASK); - return __crypto_hash_cast(tfm); -} - -/** - * crypto_alloc_hash() - allocate synchronous message digest handle - * @alg_name: is the cra_name / name or cra_driver_name / driver name of the - * message digest cipher - * @type: specifies the type of the cipher - * @mask: specifies the mask for the cipher - * - * Allocate a cipher handle for a message digest. The returned struct - * crypto_hash is the cipher handle that is required for any subsequent - * API invocation for that message digest. - * - * Return: allocated cipher handle in case of success; IS_ERR() is true in case - * of an error, PTR_ERR() returns the error code. - */ -static inline struct crypto_hash *crypto_alloc_hash(const char *alg_name, - u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - mask &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_HASH; - mask |= CRYPTO_ALG_TYPE_HASH_MASK; - - return __crypto_hash_cast(crypto_alloc_base(alg_name, type, mask)); -} - -static inline struct crypto_tfm *crypto_hash_tfm(struct crypto_hash *tfm) -{ - return &tfm->base; -} - -/** - * crypto_free_hash() - zeroize and free message digest handle - * @tfm: cipher handle to be freed - */ -static inline void crypto_free_hash(struct crypto_hash *tfm) -{ - crypto_free_tfm(crypto_hash_tfm(tfm)); -} - -/** - * crypto_has_hash() - Search for the availability of a message digest - * @alg_name: is the cra_name / name or cra_driver_name / driver name of the - * message digest cipher - * @type: specifies the type of the cipher - * @mask: specifies the mask for the cipher - * - * Return: true when the message digest cipher is known to the kernel crypto - * API; false otherwise - */ -static inline int crypto_has_hash(const char *alg_name, u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - mask &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_HASH; - mask |= CRYPTO_ALG_TYPE_HASH_MASK; - - return crypto_has_alg(alg_name, type, mask); -} - -static inline struct hash_tfm *crypto_hash_crt(struct crypto_hash *tfm) -{ - return &crypto_hash_tfm(tfm)->crt_hash; -} - -/** - * crypto_hash_blocksize() - obtain block size for message digest - * @tfm: cipher handle - * - * The block size for the message digest cipher referenced with the cipher - * handle is returned. - * - * Return: block size of cipher - */ -static inline unsigned int crypto_hash_blocksize(struct crypto_hash *tfm) -{ - return crypto_tfm_alg_blocksize(crypto_hash_tfm(tfm)); -} - -static inline unsigned int crypto_hash_alignmask(struct crypto_hash *tfm) -{ - return crypto_tfm_alg_alignmask(crypto_hash_tfm(tfm)); -} - -/** - * crypto_hash_digestsize() - obtain message digest size - * @tfm: cipher handle - * - * The size for the message digest created by the message digest cipher - * referenced with the cipher handle is returned. - * - * Return: message digest size - */ -static inline unsigned int crypto_hash_digestsize(struct crypto_hash *tfm) -{ - return crypto_hash_crt(tfm)->digestsize; -} - -static inline u32 crypto_hash_get_flags(struct crypto_hash *tfm) -{ - return crypto_tfm_get_flags(crypto_hash_tfm(tfm)); -} - -static inline void crypto_hash_set_flags(struct crypto_hash *tfm, u32 flags) -{ - crypto_tfm_set_flags(crypto_hash_tfm(tfm), flags); -} - -static inline void crypto_hash_clear_flags(struct crypto_hash *tfm, u32 flags) -{ - crypto_tfm_clear_flags(crypto_hash_tfm(tfm), flags); -} - -/** - * crypto_hash_init() - (re)initialize message digest handle - * @desc: cipher request handle that to be filled by caller -- - * desc.tfm is filled with the hash cipher handle; - * desc.flags is filled with either CRYPTO_TFM_REQ_MAY_SLEEP or 0. - * - * The call (re-)initializes the message digest referenced by the hash cipher - * request handle. Any potentially existing state created by previous - * operations is discarded. - * - * Return: 0 if the message digest initialization was successful; < 0 if an - * error occurred - */ -static inline int crypto_hash_init(struct hash_desc *desc) -{ - return crypto_hash_crt(desc->tfm)->init(desc); -} - -/** - * crypto_hash_update() - add data to message digest for processing - * @desc: cipher request handle - * @sg: scatter / gather list pointing to the data to be added to the message - * digest - * @nbytes: number of bytes to be processed from @sg - * - * Updates the message digest state of the cipher handle pointed to by the - * hash cipher request handle with the input data pointed to by the - * scatter/gather list. - * - * Return: 0 if the message digest update was successful; < 0 if an error - * occurred - */ -static inline int crypto_hash_update(struct hash_desc *desc, - struct scatterlist *sg, - unsigned int nbytes) -{ - return crypto_hash_crt(desc->tfm)->update(desc, sg, nbytes); -} - -/** - * crypto_hash_final() - calculate message digest - * @desc: cipher request handle - * @out: message digest output buffer -- The caller must ensure that the out - * buffer has a sufficient size (e.g. by using the crypto_hash_digestsize - * function). - * - * Finalize the message digest operation and create the message digest - * based on all data added to the cipher handle. The message digest is placed - * into the output buffer. - * - * Return: 0 if the message digest creation was successful; < 0 if an error - * occurred - */ -static inline int crypto_hash_final(struct hash_desc *desc, u8 *out) -{ - return crypto_hash_crt(desc->tfm)->final(desc, out); -} - -/** - * crypto_hash_digest() - calculate message digest for a buffer - * @desc: see crypto_hash_final() - * @sg: see crypto_hash_update() - * @nbytes: see crypto_hash_update() - * @out: see crypto_hash_final() - * - * This function is a "short-hand" for the function calls of crypto_hash_init, - * crypto_hash_update and crypto_hash_final. The parameters have the same - * meaning as discussed for those separate three functions. - * - * Return: 0 if the message digest creation was successful; < 0 if an error - * occurred - */ -static inline int crypto_hash_digest(struct hash_desc *desc, - struct scatterlist *sg, - unsigned int nbytes, u8 *out) -{ - return crypto_hash_crt(desc->tfm)->digest(desc, sg, nbytes, out); -} - -/** - * crypto_hash_setkey() - set key for message digest - * @hash: cipher handle - * @key: buffer holding the key - * @keylen: length of the key in bytes - * - * The caller provided key is set for the message digest cipher. The cipher - * handle must point to a keyed hash in order for this function to succeed. - * - * Return: 0 if the setting of the key was successful; < 0 if an error occurred - */ -static inline int crypto_hash_setkey(struct crypto_hash *hash, - const u8 *key, unsigned int keylen) -{ - return crypto_hash_crt(hash)->setkey(hash, key, keylen); -} - static inline struct crypto_comp *__crypto_comp_cast(struct crypto_tfm *tfm) { return (struct crypto_comp *)tfm; -- cgit From f823ab93c518f49c94453bfa9f5c2de6129c9fc6 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 1 Feb 2016 17:39:21 +0000 Subject: crypto: sunxi-ss - prevent compilation on 64-bit The driver for the sunxi-ss crypto engine is not entirely 64-bit safe, compilation on arm64 spits some warnings. The proper fix was deemed to involved [1], so since 64-bit SoCs won't have this IP block we just disable this driver for 64-bit. [1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2016-January/399988.html (and the reply) Signed-off-by: Andre Przywara Acked-by: Corentin LABBE Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 0a6e0b72284b..fed3ffbec4c1 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -488,7 +488,7 @@ config CRYPTO_DEV_IMGTEC_HASH config CRYPTO_DEV_SUN4I_SS tristate "Support for Allwinner Security System cryptographic accelerator" - depends on ARCH_SUNXI + depends on ARCH_SUNXI && !64BIT select CRYPTO_MD5 select CRYPTO_SHA1 select CRYPTO_AES -- cgit From 53a0bd7144224ba26b326a16e9eaf8bd7f433220 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Mon, 1 Feb 2016 11:17:30 -0800 Subject: crypto: aead - move aead_request_cast helper to aead.h Move the helper function to common header for everybody to use. changes in v2: - move the helper to crypto/internal/aead.h instead of crypto/aead.h Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- drivers/crypto/atmel-aes.c | 6 ------ include/crypto/internal/aead.h | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 6dd3317ca365..949af89cdac3 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -369,12 +369,6 @@ static inline size_t atmel_aes_padlen(size_t len, size_t block_size) return len ? block_size - len : 0; } -static inline struct aead_request * -aead_request_cast(struct crypto_async_request *req) -{ - return container_of(req, struct aead_request, base); -} - static struct atmel_aes_dev *atmel_aes_find_dev(struct atmel_aes_base_ctx *ctx) { struct atmel_aes_dev *aes_dd = NULL; diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h index 5554cdd8d6c1..da3864991d4c 100644 --- a/include/crypto/internal/aead.h +++ b/include/crypto/internal/aead.h @@ -80,6 +80,12 @@ static inline u32 aead_request_flags(struct aead_request *req) return req->base.flags; } +static inline struct aead_request *aead_request_cast( + struct crypto_async_request *req) +{ + return container_of(req, struct aead_request, base); +} + static inline void crypto_set_aead_spawn( struct crypto_aead_spawn *spawn, struct crypto_instance *inst) { -- cgit From fd09967b830c9ed60f53f318ee67907803065c9c Mon Sep 17 00:00:00 2001 From: "Wang, Rui Y" Date: Tue, 2 Feb 2016 21:56:45 +0800 Subject: crypto: sha-mb - Fix load failure On Monday, February 1, 2016 4:18 PM, Herbert Xu wrote: > > On Wed, Jan 27, 2016 at 05:08:35PM +0800, Rui Wang wrote: >> >> +static int sha1_mb_async_import(struct ahash_request *req, const void >> +*in) { >> + struct ahash_request *mcryptd_req = ahash_request_ctx(req); >> + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); >> + struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); >> + struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; >> + struct crypto_shash *child = mcryptd_ahash_child(mcryptd_tfm); >> + struct mcryptd_hash_request_ctx *rctx; >> + struct shash_desc *desc; >> + int err; >> + >> + memcpy(mcryptd_req, req, sizeof(*req)); >> + ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); >> + rctx = ahash_request_ctx(mcryptd_req); >> + desc = &rctx->desc; >> + desc->tfm = child; >> + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; >> + >> + err = crypto_shash_init(desc); >> + if (err) >> + return err; > > What is this desc for? Hi Herbert, Yeah I just realized that the call to crypto_shash_init() isn't necessary here. What it does is overwritten by crypto_ahash_import(). But this desc still needs to be initialized here because it's newly allocated by ahash_request_alloc(). We eventually calls the shash version of import() which needs desc as an argument. The real context to be imported is then derived from shash_desc_ctx(desc). desc is a sub-field of struct mcryptd_hash_request_ctx, which is again a sub-field of the bigger blob allocated by ahash_request_alloc(). The entire blob's size is set in sha1_mb_async_init_tfm(). So a better version is as follows: (just removed the call to crypto_shash_init()) >From 4bcb73adbef99aada94c49f352063619aa24d43d Mon Sep 17 00:00:00 2001 From: Rui Wang Date: Mon, 14 Dec 2015 17:22:13 +0800 Subject: [PATCH v2 1/4] crypto x86/sha1_mb: Fix load failure modprobe sha1_mb fails with the following message: modprobe: ERROR: could not insert 'sha1_mb': No such device It is because it needs to set its statesize and implement its import() and export() interface. v2: remove redundant call to crypto_shash_init() Signed-off-by: Rui Wang Signed-off-by: Herbert Xu --- arch/x86/crypto/sha-mb/sha1_mb.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/x86/crypto/sha-mb/sha1_mb.c b/arch/x86/crypto/sha-mb/sha1_mb.c index a841e9765bd6..a8a0224fa0f8 100644 --- a/arch/x86/crypto/sha-mb/sha1_mb.c +++ b/arch/x86/crypto/sha-mb/sha1_mb.c @@ -762,6 +762,38 @@ static int sha1_mb_async_digest(struct ahash_request *req) return crypto_ahash_digest(mcryptd_req); } +static int sha1_mb_async_export(struct ahash_request *req, void *out) +{ + struct ahash_request *mcryptd_req = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); + struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; + + memcpy(mcryptd_req, req, sizeof(*req)); + ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); + return crypto_ahash_export(mcryptd_req, out); +} + +static int sha1_mb_async_import(struct ahash_request *req, const void *in) +{ + struct ahash_request *mcryptd_req = ahash_request_ctx(req); + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); + struct sha1_mb_ctx *ctx = crypto_ahash_ctx(tfm); + struct mcryptd_ahash *mcryptd_tfm = ctx->mcryptd_tfm; + struct crypto_shash *child = mcryptd_ahash_child(mcryptd_tfm); + struct mcryptd_hash_request_ctx *rctx; + struct shash_desc *desc; + + memcpy(mcryptd_req, req, sizeof(*req)); + ahash_request_set_tfm(mcryptd_req, &mcryptd_tfm->base); + rctx = ahash_request_ctx(mcryptd_req); + desc = &rctx->desc; + desc->tfm = child; + desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; + + return crypto_ahash_import(mcryptd_req, in); +} + static int sha1_mb_async_init_tfm(struct crypto_tfm *tfm) { struct mcryptd_ahash *mcryptd_tfm; @@ -796,8 +828,11 @@ static struct ahash_alg sha1_mb_async_alg = { .final = sha1_mb_async_final, .finup = sha1_mb_async_finup, .digest = sha1_mb_async_digest, + .export = sha1_mb_async_export, + .import = sha1_mb_async_import, .halg = { .digestsize = SHA1_DIGEST_SIZE, + .statesize = sizeof(struct sha1_hash_ctx), .base = { .cra_name = "sha1", .cra_driver_name = "sha1_mb", -- cgit From b31dde2a5cb1bf764282abf934266b7193c2bc7c Mon Sep 17 00:00:00 2001 From: Tom Lendacky Date: Tue, 2 Feb 2016 11:38:21 -0600 Subject: crypto: ccp - Don't assume export/import areas are aligned Use a local variable for the exported and imported state so that alignment is not an issue. On export, set a local variable from the request context and then memcpy the contents of the local variable to the export memory area. On import, memcpy the import memory area into a local variable and then use the local variable to set the request context. Cc: # 3.14.x- Signed-off-by: Tom Lendacky Signed-off-by: Herbert Xu --- drivers/crypto/ccp/ccp-crypto-aes-cmac.c | 26 ++++++++++++++--------- drivers/crypto/ccp/ccp-crypto-sha.c | 36 +++++++++++++++++++------------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c index 6a2d836eb2d9..d095452b8828 100644 --- a/drivers/crypto/ccp/ccp-crypto-aes-cmac.c +++ b/drivers/crypto/ccp/ccp-crypto-aes-cmac.c @@ -223,12 +223,15 @@ static int ccp_aes_cmac_digest(struct ahash_request *req) static int ccp_aes_cmac_export(struct ahash_request *req, void *out) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_aes_cmac_exp_ctx *state = out; + struct ccp_aes_cmac_exp_ctx state; - state->null_msg = rctx->null_msg; - memcpy(state->iv, rctx->iv, sizeof(state->iv)); - state->buf_count = rctx->buf_count; - memcpy(state->buf, rctx->buf, sizeof(state->buf)); + state.null_msg = rctx->null_msg; + memcpy(state.iv, rctx->iv, sizeof(state.iv)); + state.buf_count = rctx->buf_count; + memcpy(state.buf, rctx->buf, sizeof(state.buf)); + + /* 'out' may not be aligned so memcpy from local variable */ + memcpy(out, &state, sizeof(state)); return 0; } @@ -236,12 +239,15 @@ static int ccp_aes_cmac_export(struct ahash_request *req, void *out) static int ccp_aes_cmac_import(struct ahash_request *req, const void *in) { struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_aes_cmac_exp_ctx *state = in; + struct ccp_aes_cmac_exp_ctx state; + + /* 'in' may not be aligned so memcpy to local variable */ + memcpy(&state, in, sizeof(state)); - rctx->null_msg = state->null_msg; - memcpy(rctx->iv, state->iv, sizeof(rctx->iv)); - rctx->buf_count = state->buf_count; - memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); + rctx->null_msg = state.null_msg; + memcpy(rctx->iv, state.iv, sizeof(rctx->iv)); + rctx->buf_count = state.buf_count; + memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); return 0; } diff --git a/drivers/crypto/ccp/ccp-crypto-sha.c b/drivers/crypto/ccp/ccp-crypto-sha.c index a67128a7af23..7002c6b283e5 100644 --- a/drivers/crypto/ccp/ccp-crypto-sha.c +++ b/drivers/crypto/ccp/ccp-crypto-sha.c @@ -210,14 +210,17 @@ static int ccp_sha_digest(struct ahash_request *req) static int ccp_sha_export(struct ahash_request *req, void *out) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - struct ccp_sha_exp_ctx *state = out; + struct ccp_sha_exp_ctx state; - state->type = rctx->type; - state->msg_bits = rctx->msg_bits; - state->first = rctx->first; - memcpy(state->ctx, rctx->ctx, sizeof(state->ctx)); - state->buf_count = rctx->buf_count; - memcpy(state->buf, rctx->buf, sizeof(state->buf)); + state.type = rctx->type; + state.msg_bits = rctx->msg_bits; + state.first = rctx->first; + memcpy(state.ctx, rctx->ctx, sizeof(state.ctx)); + state.buf_count = rctx->buf_count; + memcpy(state.buf, rctx->buf, sizeof(state.buf)); + + /* 'out' may not be aligned so memcpy from local variable */ + memcpy(out, &state, sizeof(state)); return 0; } @@ -225,14 +228,17 @@ static int ccp_sha_export(struct ahash_request *req, void *out) static int ccp_sha_import(struct ahash_request *req, const void *in) { struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req); - const struct ccp_sha_exp_ctx *state = in; - - rctx->type = state->type; - rctx->msg_bits = state->msg_bits; - rctx->first = state->first; - memcpy(rctx->ctx, state->ctx, sizeof(rctx->ctx)); - rctx->buf_count = state->buf_count; - memcpy(rctx->buf, state->buf, sizeof(rctx->buf)); + struct ccp_sha_exp_ctx state; + + /* 'in' may not be aligned so memcpy to local variable */ + memcpy(&state, in, sizeof(state)); + + rctx->type = state.type; + rctx->msg_bits = state.msg_bits; + rctx->first = state.first; + memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx)); + rctx->buf_count = state.buf_count; + memcpy(rctx->buf, state.buf, sizeof(rctx->buf)); return 0; } -- cgit From 57f96bbab9d9fa89e79c30866e50aea61ffa7938 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 2 Feb 2016 10:08:53 -0800 Subject: crypto: asymmetric_keys - convert public key and digsig asym to the akcipher api This patch converts the module verification code to the new akcipher API. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/Kconfig | 2 +- crypto/asymmetric_keys/Makefile | 7 +- crypto/asymmetric_keys/pkcs7_parser.c | 12 +- crypto/asymmetric_keys/pkcs7_trust.c | 2 +- crypto/asymmetric_keys/pkcs7_verify.c | 2 +- crypto/asymmetric_keys/public_key.c | 64 +++------ crypto/asymmetric_keys/public_key.h | 36 ----- crypto/asymmetric_keys/rsa.c | 213 +++++++++++------------------- crypto/asymmetric_keys/x509_cert_parser.c | 37 +----- crypto/asymmetric_keys/x509_public_key.c | 17 +-- crypto/asymmetric_keys/x509_rsakey.asn1 | 4 - include/crypto/public_key.h | 34 ++--- 12 files changed, 134 insertions(+), 296 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key.h delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1 diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 4870f28403f5..905d745c2f85 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -22,7 +22,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config PUBLIC_KEY_ALGO_RSA tristate "RSA public-key algorithm" - select MPILIB + select CRYPTO_RSA help This option enables support for the RSA algorithm (PKCS#1, RFC3447). diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index cd1406f9b14a..b78a194ea014 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -16,21 +16,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o x509_key_parser-y := \ x509-asn1.o \ x509_akid-asn1.o \ - x509_rsakey-asn1.o \ x509_cert_parser.o \ x509_public_key.o $(obj)/x509_cert_parser.o: \ $(obj)/x509-asn1.h \ - $(obj)/x509_akid-asn1.h \ - $(obj)/x509_rsakey-asn1.h + $(obj)/x509_akid-asn1.h + $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h $(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h -$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h clean-files += x509-asn1.c x509-asn1.h clean-files += x509_akid-asn1.c x509_akid-asn1.h -clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h # # PKCS#7 message handling diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index 8f3056cd0399..3ef62dac9771 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -15,7 +15,7 @@ #include #include #include -#include "public_key.h" +#include #include "pkcs7_parser.h" #include "pkcs7-asn1.h" @@ -44,7 +44,7 @@ struct pkcs7_parse_context { static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) { if (sinfo) { - mpi_free(sinfo->sig.mpi[0]); + kfree(sinfo->sig.s); kfree(sinfo->sig.digest); kfree(sinfo->signing_cert_id); kfree(sinfo); @@ -614,16 +614,14 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen, const void *value, size_t vlen) { struct pkcs7_parse_context *ctx = context; - MPI mpi; BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA); - mpi = mpi_read_raw_data(value, vlen); - if (!mpi) + ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL); + if (!ctx->sinfo->sig.s) return -ENOMEM; - ctx->sinfo->sig.mpi[0] = mpi; - ctx->sinfo->sig.nr_mpi = 1; + ctx->sinfo->sig.s_size = vlen; return 0; } diff --git a/crypto/asymmetric_keys/pkcs7_trust.c b/crypto/asymmetric_keys/pkcs7_trust.c index 90d6d47965b0..3bbdcc79a3d3 100644 --- a/crypto/asymmetric_keys/pkcs7_trust.c +++ b/crypto/asymmetric_keys/pkcs7_trust.c @@ -17,7 +17,7 @@ #include #include #include -#include "public_key.h" +#include #include "pkcs7_parser.h" /** diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index 325575caf6b4..f5db1378c096 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -16,7 +16,7 @@ #include #include #include -#include "public_key.h" +#include #include "pkcs7_parser.h" /* diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 6db4c01c6503..b383629b9e62 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -18,24 +18,16 @@ #include #include #include -#include "public_key.h" +#include MODULE_LICENSE("GPL"); const char *const pkey_algo_name[PKEY_ALGO__LAST] = { - [PKEY_ALGO_DSA] = "DSA", - [PKEY_ALGO_RSA] = "RSA", + [PKEY_ALGO_DSA] = "dsa", + [PKEY_ALGO_RSA] = "rsa", }; EXPORT_SYMBOL_GPL(pkey_algo_name); -const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = { -#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \ - defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE) - [PKEY_ALGO_RSA] = &RSA_public_key_algorithm, -#endif -}; -EXPORT_SYMBOL_GPL(pkey_algo); - const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { [PKEY_ID_PGP] = "PGP", [PKEY_ID_X509] = "X509", @@ -43,6 +35,12 @@ const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { }; EXPORT_SYMBOL_GPL(pkey_id_type_name); +static int (*alg_verify[PKEY_ALGO__LAST])(const struct public_key *pkey, + const struct public_key_signature *sig) = { + NULL, + rsa_verify_signature +}; + /* * Provide a part of a description of the key for /proc/keys. */ @@ -53,7 +51,8 @@ static void public_key_describe(const struct key *asymmetric_key, if (key) seq_printf(m, "%s.%s", - pkey_id_type_name[key->id_type], key->algo->name); + pkey_id_type_name[key->id_type], + pkey_algo_name[key->pkey_algo]); } /* @@ -62,50 +61,31 @@ static void public_key_describe(const struct key *asymmetric_key, void public_key_destroy(void *payload) { struct public_key *key = payload; - int i; - if (key) { - for (i = 0; i < ARRAY_SIZE(key->mpi); i++) - mpi_free(key->mpi[i]); - kfree(key); - } + if (key) + kfree(key->key); + kfree(key); } EXPORT_SYMBOL_GPL(public_key_destroy); /* * Verify a signature using a public key. */ -int public_key_verify_signature(const struct public_key *pk, +int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { - const struct public_key_algorithm *algo; - - BUG_ON(!pk); - BUG_ON(!pk->mpi[0]); - BUG_ON(!pk->mpi[1]); + BUG_ON(!pkey); BUG_ON(!sig); BUG_ON(!sig->digest); - BUG_ON(!sig->mpi[0]); - - algo = pk->algo; - if (!algo) { - if (pk->pkey_algo >= PKEY_ALGO__LAST) - return -ENOPKG; - algo = pkey_algo[pk->pkey_algo]; - if (!algo) - return -ENOPKG; - } + BUG_ON(!sig->s); - if (!algo->verify_signature) - return -ENOTSUPP; + if (pkey->pkey_algo >= PKEY_ALGO__LAST) + return -ENOPKG; - if (sig->nr_mpi != algo->n_sig_mpi) { - pr_debug("Signature has %u MPI not %u\n", - sig->nr_mpi, algo->n_sig_mpi); - return -EINVAL; - } + if (!alg_verify[pkey->pkey_algo]) + return -ENOPKG; - return algo->verify_signature(pk, sig); + return alg_verify[pkey->pkey_algo](pkey, sig); } EXPORT_SYMBOL_GPL(public_key_verify_signature); diff --git a/crypto/asymmetric_keys/public_key.h b/crypto/asymmetric_keys/public_key.h deleted file mode 100644 index 5c37a22a0637..000000000000 --- a/crypto/asymmetric_keys/public_key.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Public key algorithm internals - * - * See Documentation/crypto/asymmetric-keys.txt - * - * 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. - */ - -#include - -extern struct asymmetric_key_subtype public_key_subtype; - -/* - * Public key algorithm definition. - */ -struct public_key_algorithm { - const char *name; - u8 n_pub_mpi; /* Number of MPIs in public key */ - u8 n_sec_mpi; /* Number of MPIs in secret key */ - u8 n_sig_mpi; /* Number of MPIs in a signature */ - int (*verify_signature)(const struct public_key *key, - const struct public_key_signature *sig); -}; - -extern const struct public_key_algorithm RSA_public_key_algorithm; - -/* - * public_key.c - */ -extern int public_key_verify_signature(const struct public_key *pk, - const struct public_key_signature *sig); diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c index 508b57b77474..8b08ffcdb809 100644 --- a/crypto/asymmetric_keys/rsa.c +++ b/crypto/asymmetric_keys/rsa.c @@ -11,10 +11,10 @@ #define pr_fmt(fmt) "RSA: "fmt #include -#include #include +#include +#include #include -#include "public_key.h" MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("RSA Public Key Algorithm"); @@ -84,72 +84,10 @@ static const struct { #undef _ }; -/* - * RSAVP1() function [RFC3447 sec 5.2.2] - */ -static int RSAVP1(const struct public_key *key, MPI s, MPI *_m) -{ - MPI m; - int ret; - - /* (1) Validate 0 <= s < n */ - if (mpi_cmp_ui(s, 0) < 0) { - kleave(" = -EBADMSG [s < 0]"); - return -EBADMSG; - } - if (mpi_cmp(s, key->rsa.n) >= 0) { - kleave(" = -EBADMSG [s >= n]"); - return -EBADMSG; - } - - m = mpi_alloc(0); - if (!m) - return -ENOMEM; - - /* (2) m = s^e mod n */ - ret = mpi_powm(m, s, key->rsa.e, key->rsa.n); - if (ret < 0) { - mpi_free(m); - return ret; - } - - *_m = m; - return 0; -} - -/* - * Integer to Octet String conversion [RFC3447 sec 4.1] - */ -static int RSA_I2OSP(MPI x, size_t xLen, u8 **pX) -{ - unsigned X_size, x_size; - int X_sign; - u8 *X; - - /* Make sure the string is the right length. The number should begin - * with { 0x00, 0x01, ... } so we have to account for 15 leading zero - * bits not being reported by MPI. - */ - x_size = mpi_get_nbits(x); - pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8); - if (x_size != xLen * 8 - 15) - return -ERANGE; - - X = mpi_get_buffer(x, &X_size, &X_sign); - if (!X) - return -ENOMEM; - if (X_sign < 0) { - kfree(X); - return -EBADMSG; - } - if (X_size != xLen - 1) { - kfree(X); - return -EBADMSG; - } - - *pX = X; - return 0; -} +struct rsa_completion { + struct completion completion; + int err; +}; /* * Perform the RSA signature verification. @@ -160,7 +98,7 @@ static int RSA_I2OSP(MPI x, size_t xLen, u8 **pX) * @asn1_template: The DigestInfo ASN.1 template * @asn1_size: Size of asm1_template[] */ -static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, +static int rsa_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, const u8 *asn1_template, size_t asn1_size) { unsigned PS_end, T_offset, i; @@ -169,10 +107,10 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, if (k < 2 + 1 + asn1_size + hash_size) return -EBADMSG; - - /* Decode the EMSA-PKCS1-v1_5 */ - if (EM[1] != 0x01) { - kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]); + /* Decode the EMSA-PKCS1-v1_5 + * note: leading zeros are stirpped by the RSA implementation */ + if (EM[0] != 0x01) { + kleave(" = -EBADMSG [EM[0] == %02u]", EM[0]); return -EBADMSG; } @@ -183,7 +121,7 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, return -EBADMSG; } - for (i = 2; i < PS_end; i++) { + for (i = 1; i < PS_end; i++) { if (EM[i] != 0xff) { kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); return -EBADMSG; @@ -204,75 +142,82 @@ static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, return 0; } -/* - * Perform the verification step [RFC3447 sec 8.2.2]. - */ -static int RSA_verify_signature(const struct public_key *key, - const struct public_key_signature *sig) +static void public_key_verify_done(struct crypto_async_request *req, int err) { - size_t tsize; - int ret; + struct rsa_completion *compl = req->data; - /* Variables as per RFC3447 sec 8.2.2 */ - const u8 *H = sig->digest; - u8 *EM = NULL; - MPI m = NULL; - size_t k; + if (err == -EINPROGRESS) + return; - kenter(""); - - if (!RSA_ASN1_templates[sig->pkey_hash_algo].data) - return -ENOTSUPP; - - /* (1) Check the signature size against the public key modulus size */ - k = mpi_get_nbits(key->rsa.n); - tsize = mpi_get_nbits(sig->rsa.s); + compl->err = err; + complete(&compl->completion); +} - /* According to RFC 4880 sec 3.2, length of MPI is computed starting - * from most significant bit. So the RFC 3447 sec 8.2.2 size check - * must be relaxed to conform with shorter signatures - so we fail here - * only if signature length is longer than modulus size. - */ - pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize); - if (k < tsize) { - ret = -EBADMSG; - goto error; +int rsa_verify_signature(const struct public_key *pkey, + const struct public_key_signature *sig) +{ + struct crypto_akcipher *tfm; + struct akcipher_request *req; + struct rsa_completion compl; + struct scatterlist sig_sg, sg_out; + void *outbuf = NULL; + unsigned int outlen = 0; + int ret = -ENOMEM; + + tfm = crypto_alloc_akcipher("rsa", 0, 0); + if (IS_ERR(tfm)) + goto error_out; + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + goto error_free_tfm; + + ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen); + if (ret) + goto error_free_req; + + ret = -EINVAL; + outlen = crypto_akcipher_maxsize(tfm); + if (!outlen) + goto error_free_req; + + /* initlialzie out buf */ + ret = -ENOMEM; + outbuf = kmalloc(outlen, GFP_KERNEL); + if (!outbuf) + goto error_free_req; + + sg_init_one(&sig_sg, sig->s, sig->s_size); + sg_init_one(&sg_out, outbuf, outlen); + akcipher_request_set_crypt(req, &sig_sg, &sg_out, sig->s_size, outlen); + init_completion(&compl.completion); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + public_key_verify_done, &compl); + + ret = crypto_akcipher_verify(req); + if (ret == -EINPROGRESS) { + wait_for_completion(&compl.completion); + ret = compl.err; } - /* Round up and convert to octets */ - k = (k + 7) / 8; + if (ret) + goto error_free_req; - /* (2b) Apply the RSAVP1 verification primitive to the public key */ - ret = RSAVP1(key, sig->rsa.s, &m); - if (ret < 0) - goto error; - - /* (2c) Convert the message representative (m) to an encoded message - * (EM) of length k octets. - * - * NOTE! The leading zero byte is suppressed by MPI, so we pass a - * pointer to the _preceding_ byte to RSA_verify()! + /* + * Output from the operation is an encoded message (EM) of + * length k octets. */ - ret = RSA_I2OSP(m, k, &EM); - if (ret < 0) - goto error; - - ret = RSA_verify(H, EM - 1, k, sig->digest_size, + outlen = req->dst_len; + ret = rsa_verify(sig->digest, outbuf, outlen, sig->digest_size, RSA_ASN1_templates[sig->pkey_hash_algo].data, RSA_ASN1_templates[sig->pkey_hash_algo].size); - -error: - kfree(EM); - mpi_free(m); - kleave(" = %d", ret); +error_free_req: + akcipher_request_free(req); +error_free_tfm: + crypto_free_akcipher(tfm); +error_out: + kfree(outbuf); return ret; } - -const struct public_key_algorithm RSA_public_key_algorithm = { - .name = "RSA", - .n_pub_mpi = 2, - .n_sec_mpi = 3, - .n_sig_mpi = 1, - .verify_signature = RSA_verify_signature, -}; -EXPORT_SYMBOL_GPL(RSA_public_key_algorithm); +EXPORT_SYMBOL_GPL(rsa_verify_signature); diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 021d39c0ba75..7502029e3385 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -15,11 +15,10 @@ #include #include #include -#include "public_key.h" +#include #include "x509_parser.h" #include "x509-asn1.h" #include "x509_akid-asn1.h" -#include "x509_rsakey-asn1.h" struct x509_parse_context { struct x509_certificate *cert; /* Certificate being constructed */ @@ -56,7 +55,7 @@ void x509_free_certificate(struct x509_certificate *cert) kfree(cert->akid_id); kfree(cert->akid_skid); kfree(cert->sig.digest); - mpi_free(cert->sig.rsa.s); + kfree(cert->sig.s); kfree(cert); } } @@ -103,12 +102,12 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) } } - /* Decode the public key */ - ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, - ctx->key, ctx->key_size); - if (ret < 0) + cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); + if (!cert->pub->key) goto error_decode; + cert->pub->keylen = ctx->key_size; + /* Generate cert issuer + serial number key ID */ kid = asymmetric_key_generate_id(cert->raw_serial, cert->raw_serial_size, @@ -124,6 +123,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) return cert; error_decode: + kfree(cert->pub->key); kfree(ctx); error_no_ctx: x509_free_certificate(cert); @@ -404,29 +404,6 @@ int x509_extract_key_data(void *context, size_t hdrlen, return 0; } -/* - * Extract a RSA public key value - */ -int rsa_extract_mpi(void *context, size_t hdrlen, - unsigned char tag, - const void *value, size_t vlen) -{ - struct x509_parse_context *ctx = context; - MPI mpi; - - if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) { - pr_err("Too many public key MPIs in certificate\n"); - return -EBADMSG; - } - - mpi = mpi_read_raw_data(value, vlen); - if (!mpi) - return -ENOMEM; - - ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi; - return 0; -} - /* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ #define SEQ_TAG_KEYID (ASN1_CONT << 6) diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 9e9e5a6a9ed6..7092d5cbb5d3 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -13,15 +13,11 @@ #include #include #include -#include -#include -#include #include #include #include #include #include "asymmetric_keys.h" -#include "public_key.h" #include "x509_parser.h" static bool use_builtin_keys; @@ -167,13 +163,15 @@ int x509_get_sig_params(struct x509_certificate *cert) if (cert->unsupported_crypto) return -ENOPKG; - if (cert->sig.rsa.s) + if (cert->sig.s) return 0; - cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); - if (!cert->sig.rsa.s) + cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size, + GFP_KERNEL); + if (!cert->sig.s) return -ENOMEM; - cert->sig.nr_mpi = 1; + + cert->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. @@ -296,8 +294,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || cert->sig.pkey_algo >= PKEY_ALGO__LAST || cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || - !pkey_algo[cert->pub->pkey_algo] || - !pkey_algo[cert->sig.pkey_algo] || !hash_algo_name[cert->sig.pkey_hash_algo]) { ret = -ENOPKG; goto error_free_cert; @@ -309,7 +305,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pkey_algo_name[cert->sig.pkey_algo], hash_algo_name[cert->sig.pkey_hash_algo]); - cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; cert->pub->id_type = PKEY_ID_X509; /* Check the signature on the key if it appears to be self-signed */ diff --git a/crypto/asymmetric_keys/x509_rsakey.asn1 b/crypto/asymmetric_keys/x509_rsakey.asn1 deleted file mode 100644 index 4ec7cc6532c1..000000000000 --- a/crypto/asymmetric_keys/x509_rsakey.asn1 +++ /dev/null @@ -1,4 +0,0 @@ -RSAPublicKey ::= SEQUENCE { - modulus INTEGER ({ rsa_extract_mpi }), -- n - publicExponent INTEGER ({ rsa_extract_mpi }) -- e - } diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index cc2516df0efa..50ac8759d7ee 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -24,7 +24,6 @@ enum pkey_algo { }; extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; -extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST]; /* asymmetric key implementation supports only up to SHA224 */ #define PKEY_HASH__LAST (HASH_ALGO_SHA224 + 1) @@ -59,31 +58,10 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; * part. */ struct public_key { - const struct public_key_algorithm *algo; - u8 capabilities; -#define PKEY_CAN_ENCRYPT 0x01 -#define PKEY_CAN_DECRYPT 0x02 -#define PKEY_CAN_SIGN 0x04 -#define PKEY_CAN_VERIFY 0x08 + void *key; + u32 keylen; enum pkey_algo pkey_algo : 8; enum pkey_id_type id_type : 8; - union { - MPI mpi[5]; - struct { - MPI p; /* DSA prime */ - MPI q; /* DSA group order */ - MPI g; /* DSA group generator */ - MPI y; /* DSA public-key value = g^x mod p */ - MPI x; /* DSA secret exponent (if present) */ - } dsa; - struct { - MPI n; /* RSA public modulus */ - MPI e; /* RSA public encryption exponent */ - MPI d; /* RSA secret encryption exponent (if present) */ - MPI p; /* RSA secret prime (if present) */ - MPI q; /* RSA secret prime (if present) */ - } rsa; - }; }; extern void public_key_destroy(void *payload); @@ -92,6 +70,8 @@ extern void public_key_destroy(void *payload); * Public key cryptography signature data */ struct public_key_signature { + u8 *s; /* Signature */ + u32 s_size; /* Number of bytes in signature */ u8 *digest; u8 digest_size; /* Number of bytes in digest */ u8 nr_mpi; /* Occupancy of mpi[] */ @@ -109,6 +89,7 @@ struct public_key_signature { }; }; +extern struct asymmetric_key_subtype public_key_subtype; struct key; extern int verify_signature(const struct key *key, const struct public_key_signature *sig); @@ -119,4 +100,9 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring, const struct asymmetric_key_id *skid, bool partial); +int public_key_verify_signature(const struct public_key *pkey, + const struct public_key_signature *sig); + +int rsa_verify_signature(const struct public_key *pkey, + const struct public_key_signature *sig); #endif /* _LINUX_PUBLIC_KEY_H */ -- cgit From 42bbaabb12e687e9dcfa6cbb92567094cfbde7c2 Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 2 Feb 2016 10:08:58 -0800 Subject: integrity: convert digsig to akcipher api Convert asymmetric_verify to akcipher api. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- security/integrity/Kconfig | 1 + security/integrity/digsig_asymmetric.c | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 21d756832b75..5533a011b58e 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig @@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS select ASYMMETRIC_KEY_TYPE select ASYMMETRIC_PUBLIC_KEY_SUBTYPE select PUBLIC_KEY_ALGO_RSA + select CRYPTO_RSA select X509_CERTIFICATE_PARSER help This option enables digital signature verification using diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 5ade2a7517a6..2fa3bc681a1b 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -106,13 +106,9 @@ int asymmetric_verify(struct key *keyring, const char *sig, pks.pkey_hash_algo = hdr->hash_algo; pks.digest = (u8 *)data; pks.digest_size = datalen; - pks.nr_mpi = 1; - pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); - - if (pks.rsa.s) - ret = verify_signature(key, &pks); - - mpi_free(pks.rsa.s); + pks.s = hdr->sig; + pks.s_size = siglen; + ret = verify_signature(key, &pks); key_put(key); pr_debug("%s() = %d\n", __func__, ret); return ret; -- cgit From 1e0a6e1747b760b95b05ede659c8a6e5eb9b8acb Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 2 Feb 2016 10:09:03 -0800 Subject: crypto: public_key - remove MPIs from public_key_signature struct After digsig_asymmetric.c is converted the MPIs can be now safely removed from the public_key_signature structure. Signed-off-by: Tadeusz Struk Signed-off-by: Herbert Xu --- include/crypto/public_key.h | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 50ac8759d7ee..a1693ed77be6 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -14,7 +14,6 @@ #ifndef _LINUX_PUBLIC_KEY_H #define _LINUX_PUBLIC_KEY_H -#include #include enum pkey_algo { @@ -73,20 +72,9 @@ struct public_key_signature { u8 *s; /* Signature */ u32 s_size; /* Number of bytes in signature */ u8 *digest; - u8 digest_size; /* Number of bytes in digest */ - u8 nr_mpi; /* Occupancy of mpi[] */ + u8 digest_size; /* Number of bytes in digest */ enum pkey_algo pkey_algo : 8; enum hash_algo pkey_hash_algo : 8; - union { - MPI mpi[2]; - struct { - MPI s; /* m^d mod n */ - } rsa; - struct { - MPI r; - MPI s; - } dsa; - }; }; extern struct asymmetric_key_subtype public_key_subtype; -- cgit From 018ba95c71c0b0ef7abc8d584bf556ffd1f5b230 Mon Sep 17 00:00:00 2001 From: "Wang, Rui Y" Date: Wed, 3 Feb 2016 18:26:57 +0800 Subject: crypto: testmgr - Add a test case for import()/export() Modify __test_hash() so that hash import/export can be tested from within the kernel. The test is unconditionally done when a struct hash_testvec has its .np > 1. v3: make the test unconditional v2: Leverage template[i].np as suggested by Tim Chen Signed-off-by: Rui Wang Signed-off-by: Herbert Xu --- crypto/testmgr.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index cbd78c954844..cde6a2983937 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -190,6 +190,61 @@ static int wait_async_op(struct tcrypt_result *tr, int ret) return ret; } +static int ahash_partial_update(struct ahash_request **preq, + struct crypto_ahash *tfm, struct hash_testvec *template, + void *hash_buff, int k, int temp, struct scatterlist *sg, + const char *algo, char *result, struct tcrypt_result *tresult) +{ + char *state; + struct ahash_request *req; + int statesize, ret = -EINVAL; + + req = *preq; + statesize = crypto_ahash_statesize( + crypto_ahash_reqtfm(req)); + state = kmalloc(statesize, GFP_KERNEL); + if (!state) { + pr_err("alt: hash: Failed to alloc state for %s\n", algo); + goto out_nostate; + } + ret = crypto_ahash_export(req, state); + if (ret) { + pr_err("alt: hash: Failed to export() for %s\n", algo); + goto out; + } + ahash_request_free(req); + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) { + pr_err("alg: hash: Failed to alloc request for %s\n", algo); + goto out_noreq; + } + ahash_request_set_callback(req, + CRYPTO_TFM_REQ_MAY_BACKLOG, + tcrypt_complete, tresult); + + memcpy(hash_buff, template->plaintext + temp, + template->tap[k]); + sg_init_one(&sg[0], hash_buff, template->tap[k]); + ahash_request_set_crypt(req, sg, result, template->tap[k]); + ret = crypto_ahash_import(req, state); + if (ret) { + pr_err("alg: hash: Failed to import() for %s\n", algo); + goto out; + } + ret = wait_async_op(tresult, crypto_ahash_update(req)); + if (ret) + goto out; + *preq = req; + ret = 0; + goto out_noreq; +out: + ahash_request_free(req); +out_noreq: + kfree(state); +out_nostate: + return ret; +} + static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, unsigned int tcount, bool use_digest, const int align_offset) @@ -377,6 +432,84 @@ static int __test_hash(struct crypto_ahash *tfm, struct hash_testvec *template, } } + /* partial update exercise */ + j = 0; + for (i = 0; i < tcount; i++) { + /* alignment tests are only done with continuous buffers */ + if (align_offset != 0) + break; + + if (template[i].np < 2) + continue; + + j++; + memset(result, 0, MAX_DIGEST_SIZE); + + ret = -EINVAL; + hash_buff = xbuf[0]; + memcpy(hash_buff, template[i].plaintext, + template[i].tap[0]); + sg_init_one(&sg[0], hash_buff, template[i].tap[0]); + + if (template[i].ksize) { + crypto_ahash_clear_flags(tfm, ~0); + if (template[i].ksize > MAX_KEYLEN) { + pr_err("alg: hash: setkey failed on test %d for %s: key size %d > %d\n", + j, algo, template[i].ksize, MAX_KEYLEN); + ret = -EINVAL; + goto out; + } + memcpy(key, template[i].key, template[i].ksize); + ret = crypto_ahash_setkey(tfm, key, template[i].ksize); + if (ret) { + pr_err("alg: hash: setkey failed on test %d for %s: ret=%d\n", + j, algo, -ret); + goto out; + } + } + + ahash_request_set_crypt(req, sg, result, template[i].tap[0]); + ret = wait_async_op(&tresult, crypto_ahash_init(req)); + if (ret) { + pr_err("alt: hash: init failed on test %d for %s: ret=%d\n", + j, algo, -ret); + goto out; + } + ret = wait_async_op(&tresult, crypto_ahash_update(req)); + if (ret) { + pr_err("alt: hash: update failed on test %d for %s: ret=%d\n", + j, algo, -ret); + goto out; + } + + temp = template[i].tap[0]; + for (k = 1; k < template[i].np; k++) { + ret = ahash_partial_update(&req, tfm, &template[i], + hash_buff, k, temp, &sg[0], algo, result, + &tresult); + if (ret) { + pr_err("hash: partial update failed on test %d for %s: ret=%d\n", + j, algo, -ret); + goto out_noreq; + } + temp += template[i].tap[k]; + } + ret = wait_async_op(&tresult, crypto_ahash_final(req)); + if (ret) { + pr_err("alt: hash: final failed on test %d for %s: ret=%d\n", + j, algo, -ret); + goto out; + } + if (memcmp(result, template[i].digest, + crypto_ahash_digestsize(tfm))) { + pr_err("alg: hash: Partial Test %d failed for %s\n", + j, algo); + hexdump(result, crypto_ahash_digestsize(tfm)); + ret = -EINVAL; + goto out; + } + } + ret = 0; out: -- cgit From 6e56201857fabf0249204704e2a15e6f61d5a05c Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Feb 2016 10:46:50 -0200 Subject: crypto: sahara - remove unneeded mutex in the exported state As pointed out by Herbert Xu we should not include the mutex in the exported state, so let's just get rid of it. Signed-off-by: Fabio Estevam Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 6c4f91c5e6b3..7e8147df6e0d 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -182,7 +182,6 @@ struct sahara_sha_reqctx { u8 buf[SAHARA_MAX_SHA_BLOCK_SIZE]; u8 rembuf[SAHARA_MAX_SHA_BLOCK_SIZE]; u8 context[SHA256_DIGEST_SIZE + 4]; - struct mutex mutex; unsigned int mode; unsigned int digest_size; unsigned int context_size; @@ -1096,7 +1095,6 @@ static int sahara_sha_enqueue(struct ahash_request *req, int last) if (!req->nbytes && !last) return 0; - mutex_lock(&rctx->mutex); rctx->last = last; if (!rctx->active) { @@ -1109,7 +1107,6 @@ static int sahara_sha_enqueue(struct ahash_request *req, int last) mutex_unlock(&dev->queue_mutex); wake_up_process(dev->kthread); - mutex_unlock(&rctx->mutex); return ret; } @@ -1137,8 +1134,6 @@ static int sahara_sha_init(struct ahash_request *req) rctx->context_size = rctx->digest_size + 4; rctx->active = 0; - mutex_init(&rctx->mutex); - return 0; } -- cgit From bceab44eed7f37110136860cb2992fbd6702588d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Feb 2016 10:46:51 -0200 Subject: crypto: sahara - avoid needlessly saving and restoring sahara_ctx Based on commit 434b421241f2d0 ("crypto: caam - avoid needlessly saving and restoring caam_hash_ctx") from Russell King. When exporting and importing the hash state, we will only export and import into hashes which share the same struct crypto_ahash pointer. (See hash_accept->af_alg_accept->hash_accept_parent.) This means that saving the sahara_ctx structure on export, and restoring it on import is a waste of resources. So, remove this code. Signed-off-by: Fabio Estevam Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 7e8147df6e0d..9db09b643a44 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1162,26 +1162,18 @@ static int sahara_sha_digest(struct ahash_request *req) static int sahara_sha_export(struct ahash_request *req, void *out) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); - struct sahara_ctx *ctx = crypto_ahash_ctx(ahash); struct sahara_sha_reqctx *rctx = ahash_request_ctx(req); - memcpy(out, ctx, sizeof(struct sahara_ctx)); - memcpy(out + sizeof(struct sahara_sha_reqctx), rctx, - sizeof(struct sahara_sha_reqctx)); + memcpy(out, rctx, sizeof(struct sahara_sha_reqctx)); return 0; } static int sahara_sha_import(struct ahash_request *req, const void *in) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); - struct sahara_ctx *ctx = crypto_ahash_ctx(ahash); struct sahara_sha_reqctx *rctx = ahash_request_ctx(req); - memcpy(ctx, in, sizeof(struct sahara_ctx)); - memcpy(rctx, in + sizeof(struct sahara_sha_reqctx), - sizeof(struct sahara_sha_reqctx)); + memcpy(rctx, in, sizeof(struct sahara_sha_reqctx)); return 0; } -- cgit From d42cf2f1901e4fafb133d5fb680fc7138b9ba393 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Wed, 3 Feb 2016 10:46:52 -0200 Subject: crypto: sahara - fill the statesize field Currently the sahara driver fails to probe: sahara: probe of 63ff8000.crypto failed with error -22 This happens since commit 8996eafdcbad ("crypto: ahash - ensure statesize is non-zero"), which requires statesize to be filled. Pass the statesize members for sha1 and sha256, so we can probe the driver successfully again. Signed-off-by: Fabio Estevam Signed-off-by: Herbert Xu --- drivers/crypto/sahara.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 9db09b643a44..c3f3d89e4831 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -1259,6 +1259,7 @@ static struct ahash_alg sha_v3_algs[] = { .export = sahara_sha_export, .import = sahara_sha_import, .halg.digestsize = SHA1_DIGEST_SIZE, + .halg.statesize = sizeof(struct sahara_sha_reqctx), .halg.base = { .cra_name = "sha1", .cra_driver_name = "sahara-sha1", @@ -1286,6 +1287,7 @@ static struct ahash_alg sha_v4_algs[] = { .export = sahara_sha_export, .import = sahara_sha_import, .halg.digestsize = SHA256_DIGEST_SIZE, + .halg.statesize = sizeof(struct sahara_sha_reqctx), .halg.base = { .cra_name = "sha256", .cra_driver_name = "sahara-sha256", -- cgit From abfa7f4357e3640fdee87dfc276fd0f379fb5ae6 Mon Sep 17 00:00:00 2001 From: Jerome Marchand Date: Wed, 3 Feb 2016 13:58:12 +0100 Subject: crypto: testmgr - fix out of bound read in __test_aead() __test_aead() reads MAX_IVLEN bytes from template[i].iv, but the actual length of the initialisation vector can be shorter. The length of the IV is already calculated earlier in the function. Let's just reuses that. Also the IV length is currently calculated several time for no reason. Let's fix that too. This fix an out-of-bound error detected by KASan. Signed-off-by: Jerome Marchand Signed-off-by: Herbert Xu --- crypto/testmgr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index cde6a2983937..54681838da6c 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -613,6 +613,8 @@ static int __test_aead(struct crypto_aead *tfm, int enc, aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, tcrypt_complete, &result); + iv_len = crypto_aead_ivsize(tfm); + for (i = 0, j = 0; i < tcount; i++) { if (template[i].np) continue; @@ -633,7 +635,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc, memcpy(input, template[i].input, template[i].ilen); memcpy(assoc, template[i].assoc, template[i].alen); - iv_len = crypto_aead_ivsize(tfm); if (template[i].iv) memcpy(iv, template[i].iv, iv_len); else @@ -742,7 +743,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc, j++; if (template[i].iv) - memcpy(iv, template[i].iv, MAX_IVLEN); + memcpy(iv, template[i].iv, iv_len); else memset(iv, 0, MAX_IVLEN); -- cgit From ed1afac9145c4517a2c84f93e04a35046ea206e3 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Fri, 5 Feb 2016 14:23:33 +0100 Subject: crypto: testmgr - mark more algorithms as FIPS compliant Some more authenc() wrapped algorithms are FIPS compliant, tag them as such. Signed-off-by: Marcus Meissner Acked-by: Stephan Mueller Signed-off-by: Herbert Xu --- crypto/testmgr.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 54681838da6c..93f3527962ec 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -2058,6 +2058,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha1),cbc(des3_ede))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2103,6 +2104,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha224),cbc(des3_ede))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2116,6 +2118,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha256),cbc(aes))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2142,6 +2145,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha256),cbc(des3_ede))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2168,6 +2172,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha384),cbc(des3_ede))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = { .enc = { @@ -2180,6 +2185,7 @@ static const struct alg_test_desc alg_test_descs[] = { } }, { .alg = "authenc(hmac(sha512),cbc(aes))", + .fips_allowed = 1, .test = alg_test_aead, .suite = { .aead = { @@ -2207,6 +2213,7 @@ static const struct alg_test_desc alg_test_descs[] = { }, { .alg = "authenc(hmac(sha512),cbc(des3_ede))", .test = alg_test_aead, + .fips_allowed = 1, .suite = { .aead = { .enc = { -- cgit From d01332f1acacc0cb43a61f4244dd2b846d4cd585 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 1 Feb 2016 08:19:56 +0100 Subject: tipc: fix link attribute propagation bug Changing certain link attributes (link tolerance and link priority) from the TIPC management tool is supposed to automatically take effect at both endpoints of the affected link. Currently the media address is not instantiated for the link and is used uninstantiated when crafting protocol messages designated for the peer endpoint. This means that changing a link property currently results in the property being changed on the local machine but the protocol message designated for the peer gets lost. Resulting in property discrepancy between the endpoints. In this patch we resolve this by using the media address from the link entry and using the bearer transmit function to send it. Hence, we can now eliminate the redundant function tipc_link_prot_xmit() and the redundant field tipc_link::media_addr. Fixes: 2af5ae372a4b (tipc: clean up unused code and structures) Reviewed-by: Jon Maloy Reported-by: Jason Hu Signed-off-by: Richard Alpe Signed-off-by: David S. Miller --- net/tipc/link.c | 31 ++++++------------------------- net/tipc/link.h | 6 ++++-- net/tipc/node.c | 9 ++++++--- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/net/tipc/link.c b/net/tipc/link.c index 0c2944fb9ae0..f15635391576 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -123,7 +123,6 @@ struct tipc_stats { struct tipc_link { u32 addr; char name[TIPC_MAX_LINK_NAME]; - struct tipc_media_addr *media_addr; struct net *net; /* Management and link supervision data */ @@ -1261,26 +1260,6 @@ drop: return rc; } -/* - * Send protocol message to the other endpoint. - */ -static void tipc_link_proto_xmit(struct tipc_link *l, u32 msg_typ, - int probe_msg, u32 gap, u32 tolerance, - u32 priority) -{ - struct sk_buff *skb = NULL; - struct sk_buff_head xmitq; - - __skb_queue_head_init(&xmitq); - tipc_link_build_proto_msg(l, msg_typ, probe_msg, gap, - tolerance, priority, &xmitq); - skb = __skb_dequeue(&xmitq); - if (!skb) - return; - tipc_bearer_xmit_skb(l->net, l->bearer_id, skb, l->media_addr); - l->rcv_unacked = 0; -} - static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe, u16 rcvgap, int tolerance, int priority, struct sk_buff_head *xmitq) @@ -2021,16 +2000,18 @@ msg_full: return -EMSGSIZE; } -void tipc_link_set_tolerance(struct tipc_link *l, u32 tol) +void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, + struct sk_buff_head *xmitq) { l->tolerance = tol; - tipc_link_proto_xmit(l, STATE_MSG, 0, 0, tol, 0); + tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, tol, 0, xmitq); } -void tipc_link_set_prio(struct tipc_link *l, u32 prio) +void tipc_link_set_prio(struct tipc_link *l, u32 prio, + struct sk_buff_head *xmitq) { l->priority = prio; - tipc_link_proto_xmit(l, STATE_MSG, 0, 0, 0, prio); + tipc_link_build_proto_msg(l, STATE_MSG, 0, 0, 0, prio, xmitq); } void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit) diff --git a/net/tipc/link.h b/net/tipc/link.h index b2ae0f4276af..b4ee9d6e181d 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h @@ -112,8 +112,10 @@ char tipc_link_plane(struct tipc_link *l); int tipc_link_prio(struct tipc_link *l); int tipc_link_window(struct tipc_link *l); unsigned long tipc_link_tolerance(struct tipc_link *l); -void tipc_link_set_tolerance(struct tipc_link *l, u32 tol); -void tipc_link_set_prio(struct tipc_link *l, u32 prio); +void tipc_link_set_tolerance(struct tipc_link *l, u32 tol, + struct sk_buff_head *xmitq); +void tipc_link_set_prio(struct tipc_link *l, u32 prio, + struct sk_buff_head *xmitq); void tipc_link_set_abort_limit(struct tipc_link *l, u32 limit); void tipc_link_set_queue_limits(struct tipc_link *l, u32 window); int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg, diff --git a/net/tipc/node.c b/net/tipc/node.c index fa97d9649a28..f8a8255a7182 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1637,9 +1637,12 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) char *name; struct tipc_link *link; struct tipc_node *node; + struct sk_buff_head xmitq; struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1]; struct net *net = sock_net(skb->sk); + __skb_queue_head_init(&xmitq); + if (!info->attrs[TIPC_NLA_LINK]) return -EINVAL; @@ -1683,13 +1686,13 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) u32 tol; tol = nla_get_u32(props[TIPC_NLA_PROP_TOL]); - tipc_link_set_tolerance(link, tol); + tipc_link_set_tolerance(link, tol, &xmitq); } if (props[TIPC_NLA_PROP_PRIO]) { u32 prio; prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); - tipc_link_set_prio(link, prio); + tipc_link_set_prio(link, prio, &xmitq); } if (props[TIPC_NLA_PROP_WIN]) { u32 win; @@ -1701,7 +1704,7 @@ int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info) out: tipc_node_read_unlock(node); - + tipc_bearer_xmit(net, bearer_id, &xmitq, &node->links[bearer_id].maddr); return res; } -- cgit From 817298102b0bc936b08dfcc5fbcc2213157050f2 Mon Sep 17 00:00:00 2001 From: Richard Alpe Date: Mon, 1 Feb 2016 08:19:57 +0100 Subject: tipc: fix link priority propagation Currently link priority changes isn't handled for active links. In this patch we resolve this by changing our priority if the peer passes a valid priority in a state message. Reviewed-by: Jon Maloy Signed-off-by: Richard Alpe Signed-off-by: David S. Miller --- net/tipc/link.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/tipc/link.c b/net/tipc/link.c index f15635391576..6f4a6d9b0149 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1458,6 +1458,12 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb, if (in_range(peers_tol, TIPC_MIN_LINK_TOL, TIPC_MAX_LINK_TOL)) l->tolerance = peers_tol; + if (peers_prio && in_range(peers_prio, TIPC_MIN_LINK_PRI, + TIPC_MAX_LINK_PRI)) { + l->priority = peers_prio; + rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); + } + l->silent_intv_cnt = 0; l->stats.recv_states++; if (msg_probe(hdr)) -- cgit From 9256645af09807bc52fa8b2e66ecd28ab25318c4 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 1 Feb 2016 18:51:04 -0500 Subject: net/core: relax BUILD_BUG_ON in netdev_stats_to_stats64 The netdev_stats_to_stats64 function copies the deprecated net_device_stats format stats into rtnl_link_stats64 for legacy support purposes, but with the BUILD_BUG_ON as it was, it wasn't possible to extend rtnl_link_stats64 without also extending net_device_stats. Relax the BUILD_BUG_ON to only require that rtnl_link_stats64 is larger, and zero out all the stat counters that aren't present in net_device_stats. CC: Eric Dumazet CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- net/core/dev.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 8cba3d852f25..65863e512227 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7253,24 +7253,31 @@ void netdev_run_todo(void) } } -/* Convert net_device_stats to rtnl_link_stats64. They have the same - * fields in the same order, with only the type differing. +/* Convert net_device_stats to rtnl_link_stats64. rtnl_link_stats64 has + * all the same fields in the same order as net_device_stats, with only + * the type differing, but rtnl_link_stats64 may have additional fields + * at the end for newer counters. */ void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, const struct net_device_stats *netdev_stats) { #if BITS_PER_LONG == 64 - BUILD_BUG_ON(sizeof(*stats64) != sizeof(*netdev_stats)); + BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats)); memcpy(stats64, netdev_stats, sizeof(*stats64)); + /* zero out counters that only exist in rtnl_link_stats64 */ + memset((char *)stats64 + sizeof(*netdev_stats), 0, + sizeof(*stats64) - sizeof(*netdev_stats)); #else - size_t i, n = sizeof(*stats64) / sizeof(u64); + size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long); const unsigned long *src = (const unsigned long *)netdev_stats; u64 *dst = (u64 *)stats64; - BUILD_BUG_ON(sizeof(*netdev_stats) / sizeof(unsigned long) != - sizeof(*stats64) / sizeof(u64)); + BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64)); for (i = 0; i < n; i++) dst[i] = src[i]; + /* zero out counters that only exist in rtnl_link_stats64 */ + memset((char *)stats64 + n * sizeof(u64), 0, + sizeof(*stats64) - n * sizeof(u64)); #endif } EXPORT_SYMBOL(netdev_stats_to_stats64); -- cgit From 6e7333d315a768170a59ac771297ee0551bdddbf Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 1 Feb 2016 18:51:05 -0500 Subject: net: add rx_nohandler stat counter This adds an rx_nohandler stat counter, along with a sysfs statistics node, and copies the counter out via netlink as well. CC: "David S. Miller" CC: Eric Dumazet CC: Jiri Pirko CC: Daniel Borkmann CC: Tom Herbert CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 +++ include/uapi/linux/if_link.h | 4 ++++ net/core/dev.c | 6 +++++- net/core/net-sysfs.c | 2 ++ net/core/rtnetlink.c | 2 ++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 289c2314d766..78a20cec2a0a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1397,6 +1397,8 @@ enum netdev_priv_flags { * do not use this in drivers * @tx_dropped: Dropped packets by core network, * do not use this in drivers + * @rx_nohandler: nohandler dropped packets by core network on + * inactive devices, do not use this in drivers * * @wireless_handlers: List of functions to handle Wireless Extensions, * instead of ioctl, @@ -1611,6 +1613,7 @@ struct net_device { atomic_long_t rx_dropped; atomic_long_t tx_dropped; + atomic_long_t rx_nohandler; #ifdef CONFIG_WIRELESS_EXT const struct iw_handler_def * wireless_handlers; diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index a30b78090594..d3e90b91e07e 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -35,6 +35,8 @@ struct rtnl_link_stats { /* for cslip etc */ __u32 rx_compressed; __u32 tx_compressed; + + __u32 rx_nohandler; /* dropped, no handler found */ }; /* The main device statistics structure */ @@ -68,6 +70,8 @@ struct rtnl_link_stats64 { /* for cslip etc */ __u64 rx_compressed; __u64 tx_compressed; + + __u64 rx_nohandler; /* dropped, no handler found */ }; /* The struct should be in sync with struct ifmap */ diff --git a/net/core/dev.c b/net/core/dev.c index 65863e512227..f1284835b8c9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4154,7 +4154,10 @@ ncls: ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } else { drop: - atomic_long_inc(&skb->dev->rx_dropped); + if (!deliver_exact) + atomic_long_inc(&skb->dev->rx_dropped); + else + atomic_long_inc(&skb->dev->rx_nohandler); kfree_skb(skb); /* Jamal, now you will not able to escape explaining * me how you were going to use this. :-) @@ -7307,6 +7310,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, } storage->rx_dropped += atomic_long_read(&dev->rx_dropped); storage->tx_dropped += atomic_long_read(&dev->tx_dropped); + storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler); return storage; } EXPORT_SYMBOL(dev_get_stats); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index b6c8a6629b39..da7dbc237a5f 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -574,6 +574,7 @@ NETSTAT_ENTRY(tx_heartbeat_errors); NETSTAT_ENTRY(tx_window_errors); NETSTAT_ENTRY(rx_compressed); NETSTAT_ENTRY(tx_compressed); +NETSTAT_ENTRY(rx_nohandler); static struct attribute *netstat_attrs[] = { &dev_attr_rx_packets.attr, @@ -599,6 +600,7 @@ static struct attribute *netstat_attrs[] = { &dev_attr_tx_window_errors.attr, &dev_attr_rx_compressed.attr, &dev_attr_tx_compressed.attr, + &dev_attr_rx_nohandler.attr, NULL }; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d735e854f916..20d71358c143 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -804,6 +804,8 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, a->rx_compressed = b->rx_compressed; a->tx_compressed = b->tx_compressed; + + a->rx_nohandler = b->rx_nohandler; } static void copy_rtnl_link_stats64(void *v, const struct rtnl_link_stats64 *b) -- cgit From bb63daf9efb4f2bcb657d7179a53bd808f978dc9 Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 1 Feb 2016 18:51:06 -0500 Subject: team: track sum of rx_nohandler for all slaves CC: Jiri Pirko CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/team/team.c | 10 +++++++--- include/linux/if_team.h | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 718ceeab4dbc..00558e139584 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -758,6 +758,8 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb) u64_stats_update_end(&pcpu_stats->syncp); skb->dev = team->dev; + } else if (res == RX_HANDLER_EXACT) { + this_cpu_inc(team->pcpu_stats->rx_nohandler); } else { this_cpu_inc(team->pcpu_stats->rx_dropped); } @@ -1807,7 +1809,7 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) struct team *team = netdev_priv(dev); struct team_pcpu_stats *p; u64 rx_packets, rx_bytes, rx_multicast, tx_packets, tx_bytes; - u32 rx_dropped = 0, tx_dropped = 0; + u32 rx_dropped = 0, tx_dropped = 0, rx_nohandler = 0; unsigned int start; int i; @@ -1828,14 +1830,16 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) stats->tx_packets += tx_packets; stats->tx_bytes += tx_bytes; /* - * rx_dropped & tx_dropped are u32, updated - * without syncp protection. + * rx_dropped, tx_dropped & rx_nohandler are u32, + * updated without syncp protection. */ rx_dropped += p->rx_dropped; tx_dropped += p->tx_dropped; + rx_nohandler += p->rx_nohandler; } stats->rx_dropped = rx_dropped; stats->tx_dropped = tx_dropped; + stats->rx_nohandler = rx_nohandler; return stats; } diff --git a/include/linux/if_team.h b/include/linux/if_team.h index b84e49c3a738..174f43f43aff 100644 --- a/include/linux/if_team.h +++ b/include/linux/if_team.h @@ -24,6 +24,7 @@ struct team_pcpu_stats { struct u64_stats_sync syncp; u32 rx_dropped; u32 tx_dropped; + u32 rx_nohandler; }; struct team; -- cgit From f344b0d940d2da88c23b864f818da43081ce300f Mon Sep 17 00:00:00 2001 From: Jarod Wilson Date: Mon, 1 Feb 2016 18:51:07 -0500 Subject: bond: track sum of rx_nohandler for all slaves Sample output with this set applied for an active-backup bond: $ cat /sys/devices/virtual/net/bond0/lower_p7p1/statistics/rx_nohandler 16568 $ cat /sys/devices/virtual/net/bond0/lower_p5p2/statistics/rx_nohandler 16583 $ cat /sys/devices/virtual/net/bond0/statistics/rx_nohandler 33151 CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek CC: netdev@vger.kernel.org Signed-off-by: Jarod Wilson Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 56b560558884..6587929b040a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3309,6 +3309,7 @@ static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev, stats->rx_bytes += sstats->rx_bytes - pstats->rx_bytes; stats->rx_errors += sstats->rx_errors - pstats->rx_errors; stats->rx_dropped += sstats->rx_dropped - pstats->rx_dropped; + stats->rx_nohandler += sstats->rx_nohandler - pstats->rx_nohandler; stats->tx_packets += sstats->tx_packets - pstats->tx_packets;; stats->tx_bytes += sstats->tx_bytes - pstats->tx_bytes; -- cgit From 61d2bcae99f66a640b3dd9632180209143fb5512 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 1 Feb 2016 21:03:07 -0800 Subject: tcp: fastopen: accept data/FIN present in SYNACK message RFC 7413 (TCP Fast Open) 4.2.2 states that the SYNACK message MAY include data and/or FIN This patch adds support for the client side : If we receive a SYNACK with payload or FIN, queue the skb instead of ignoring it. Since we already support the same for SYN, we refactor the existing code and reuse it. Note we need to clone the skb, so this operation might fail under memory pressure. Sara Dickinson pointed out FreeBSD server Fast Open implementation was planned to generate such SYNACK in the future. The server side might be implemented on linux later. Reported-by: Sara Dickinson Signed-off-by: Eric Dumazet Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller --- include/net/tcp.h | 1 + net/ipv4/tcp_fastopen.c | 64 ++++++++++++++++++++++++++----------------------- net/ipv4/tcp_input.c | 3 +++ 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index f6f8f032c73e..27f4c733116d 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1437,6 +1437,7 @@ void tcp_free_fastopen_req(struct tcp_sock *tp); extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; int tcp_fastopen_reset_cipher(void *key, unsigned int len); +void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb); struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct tcp_fastopen_cookie *foc, diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 55be6ac70cff..467d3e985411 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -124,6 +124,35 @@ static bool tcp_fastopen_cookie_gen(struct request_sock *req, return false; } + +/* If an incoming SYN or SYNACK frame contains a payload and/or FIN, + * queue this additional data / FIN. + */ +void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb) +{ + struct tcp_sock *tp = tcp_sk(sk); + + if (TCP_SKB_CB(skb)->end_seq == tp->rcv_nxt) + return; + + skb = skb_clone(skb, GFP_ATOMIC); + if (!skb) + return; + + skb_dst_drop(skb); + __skb_pull(skb, tcp_hdrlen(skb)); + skb_set_owner_r(skb, sk); + + tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; + __skb_queue_tail(&sk->sk_receive_queue, skb); + tp->syn_data_acked = 1; + + /* u64_stats_update_begin(&tp->syncp) not needed here, + * as we certainly are not changing upper 32bit value (0) + */ + tp->bytes_received = skb->len; +} + static struct sock *tcp_fastopen_create_child(struct sock *sk, struct sk_buff *skb, struct dst_entry *dst, @@ -132,7 +161,6 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk, struct tcp_sock *tp; struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; struct sock *child; - u32 end_seq; bool own_req; req->num_retrans = 0; @@ -178,35 +206,11 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk, tcp_init_metrics(child); tcp_init_buffer_space(child); - /* Queue the data carried in the SYN packet. - * We used to play tricky games with skb_get(). - * With lockless listener, it is a dead end. - * Do not think about it. - * - * XXX (TFO) - we honor a zero-payload TFO request for now, - * (any reason not to?) but no need to queue the skb since - * there is no data. How about SYN+FIN? - */ - end_seq = TCP_SKB_CB(skb)->end_seq; - if (end_seq != TCP_SKB_CB(skb)->seq + 1) { - struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); - - if (likely(skb2)) { - skb_dst_drop(skb2); - __skb_pull(skb2, tcp_hdrlen(skb)); - skb_set_owner_r(skb2, child); - __skb_queue_tail(&child->sk_receive_queue, skb2); - tp->syn_data_acked = 1; - - /* u64_stats_update_begin(&tp->syncp) not needed here, - * as we certainly are not changing upper 32bit value (0) - */ - tp->bytes_received = end_seq - TCP_SKB_CB(skb)->seq - 1; - } else { - end_seq = TCP_SKB_CB(skb)->seq + 1; - } - } - tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = end_seq; + tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1; + + tcp_fastopen_add_skb(child, skb); + + tcp_rsk(req)->rcv_nxt = tp->rcv_nxt; /* tcp_conn_request() is sending the SYNACK, * and queues the child into listener accept queue. */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1c2a73406261..4add3eb40e58 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5509,6 +5509,9 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, tp->syn_data_acked = tp->syn_data; if (tp->syn_data_acked) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); + + tcp_fastopen_add_skb(sk, synack); + return false; } -- cgit From 9d691539eea2d977e3eb86766c389a19a9c13146 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 1 Feb 2016 21:03:08 -0800 Subject: tcp: do not enqueue skb with SYN flag If we remove the SYN flag from the skbs that tcp_fastopen_add_skb() places in socket receive queue, then we can remove the test that tcp_recvmsg() has to perform in fast path. All we have to do is to adjust SEQ in the slow path. For the moment, we place an unlikely() and output a message if we find an skb having SYN flag set. Goal would be to get rid of the test completely. Signed-off-by: Eric Dumazet Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 8 ++++++-- net/ipv4/tcp_fastopen.c | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 19746b3fcbbe..c5075779e017 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1466,8 +1466,10 @@ static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { offset = seq - TCP_SKB_CB(skb)->seq; - if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN) + if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) { + pr_err_once("%s: found a SYN, please report !\n", __func__); offset--; + } if (offset < skb->len || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)) { *off = offset; return skb; @@ -1657,8 +1659,10 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, break; offset = *seq - TCP_SKB_CB(skb)->seq; - if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN) + if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) { + pr_err_once("%s: found a SYN, please report !\n", __func__); offset--; + } if (offset < skb->len) goto found_ok_skb; if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 467d3e985411..6a6e11e54bae 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -143,6 +143,9 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb) __skb_pull(skb, tcp_hdrlen(skb)); skb_set_owner_r(skb, sk); + TCP_SKB_CB(skb)->seq++; + TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN; + tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; __skb_queue_tail(&sk->sk_receive_queue, skb); tp->syn_data_acked = 1; -- cgit From ba905f5e2f63d86ed4cfbd3d9096fb28d156f1ee Mon Sep 17 00:00:00 2001 From: Kim Jones Date: Tue, 2 Feb 2016 03:51:16 +0000 Subject: ethtool: Declare netdev_rss_key as __read_mostly. netdev_rss_key is written to once and thereafter is read by drivers when they are initialising. The fact that it is mostly read and not written to makes it a candidate for a __read_mostly declaration. Signed-off-by: Kim Jones Signed-off-by: Alan Carey Acked-by: Rami Rosen Signed-off-by: David S. Miller --- include/linux/netdevice.h | 2 +- net/core/ethtool.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 78a20cec2a0a..219f53c30cb3 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3744,7 +3744,7 @@ void netdev_lower_state_changed(struct net_device *lower_dev, /* RSS keys are 40 or 52 bytes long */ #define NETDEV_RSS_KEY_LEN 52 -extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN]; +extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; void netdev_rss_key_fill(void *buffer, size_t len); int dev_get_nest_level(struct net_device *dev, diff --git a/net/core/ethtool.c b/net/core/ethtool.c index daf04709dd3c..453c803f1c87 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -632,7 +632,7 @@ static int ethtool_copy_validate_indir(u32 *indir, void __user *useraddr, return 0; } -u8 netdev_rss_key[NETDEV_RSS_KEY_LEN]; +u8 netdev_rss_key[NETDEV_RSS_KEY_LEN] __read_mostly; void netdev_rss_key_fill(void *buffer, size_t len) { -- cgit From 824bd0ce6c7c43a9e1e210abf124958e54d88342 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 1 Feb 2016 22:39:53 -0800 Subject: bpf: introduce BPF_MAP_TYPE_PERCPU_HASH map Introduce BPF_MAP_TYPE_PERCPU_HASH map type which is used to do accurate counters without need to use BPF_XADD instruction which turned out to be too costly for high-performance network monitoring. In the typical use case the 'key' is the flow tuple or other long living object that sees a lot of events per second. bpf_map_lookup_elem() returns per-cpu area. Example: struct { u32 packets; u32 bytes; } * ptr = bpf_map_lookup_elem(&map, &key); /* ptr points to this_cpu area of the value, so the following * increments will not collide with other cpus */ ptr->packets ++; ptr->bytes += skb->len; bpf_update_elem() atomically creates a new element where all per-cpu values are zero initialized and this_cpu value is populated with given 'value'. Note that non-per-cpu hash map always allocates new element and then deletes old after rcu grace period to maintain atomicity of update. Per-cpu hash map updates element values in-place. Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/uapi/linux/bpf.h | 1 + kernel/bpf/hashtab.c | 275 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 229 insertions(+), 47 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index aa6f8571de13..43ae40c8763e 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -81,6 +81,7 @@ enum bpf_map_type { BPF_MAP_TYPE_ARRAY, BPF_MAP_TYPE_PROG_ARRAY, BPF_MAP_TYPE_PERF_EVENT_ARRAY, + BPF_MAP_TYPE_PERCPU_HASH, }; enum bpf_prog_type { diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index c5b30fd8a315..2be5f6e8bb04 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -31,21 +31,27 @@ struct bpf_htab { struct htab_elem { struct hlist_node hash_node; struct rcu_head rcu; - u32 hash; + union { + u32 hash; + u32 key_size; + }; char key[0] __aligned(8); }; /* Called from syscall */ static struct bpf_map *htab_map_alloc(union bpf_attr *attr) { + bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_HASH; struct bpf_htab *htab; int err, i; + u64 cost; htab = kzalloc(sizeof(*htab), GFP_USER); if (!htab) return ERR_PTR(-ENOMEM); /* mandatory map attributes */ + htab->map.map_type = attr->map_type; htab->map.key_size = attr->key_size; htab->map.value_size = attr->value_size; htab->map.max_entries = attr->max_entries; @@ -77,24 +83,34 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr) */ goto free_htab; + if (percpu && round_up(htab->map.value_size, 8) > PCPU_MIN_UNIT_SIZE) + /* make sure the size for pcpu_alloc() is reasonable */ + goto free_htab; + htab->elem_size = sizeof(struct htab_elem) + - round_up(htab->map.key_size, 8) + - htab->map.value_size; + round_up(htab->map.key_size, 8); + if (percpu) + htab->elem_size += sizeof(void *); + else + htab->elem_size += htab->map.value_size; /* prevent zero size kmalloc and check for u32 overflow */ if (htab->n_buckets == 0 || htab->n_buckets > U32_MAX / sizeof(struct bucket)) goto free_htab; - if ((u64) htab->n_buckets * sizeof(struct bucket) + - (u64) htab->elem_size * htab->map.max_entries >= - U32_MAX - PAGE_SIZE) + cost = (u64) htab->n_buckets * sizeof(struct bucket) + + (u64) htab->elem_size * htab->map.max_entries; + + if (percpu) + cost += (u64) round_up(htab->map.value_size, 8) * + num_possible_cpus() * htab->map.max_entries; + + if (cost >= U32_MAX - PAGE_SIZE) /* make sure page count doesn't overflow */ goto free_htab; - htab->map.pages = round_up(htab->n_buckets * sizeof(struct bucket) + - htab->elem_size * htab->map.max_entries, - PAGE_SIZE) >> PAGE_SHIFT; + htab->map.pages = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT; err = -ENOMEM; htab->buckets = kmalloc_array(htab->n_buckets, sizeof(struct bucket), @@ -148,7 +164,7 @@ static struct htab_elem *lookup_elem_raw(struct hlist_head *head, u32 hash, } /* Called from syscall or from eBPF program */ -static void *htab_map_lookup_elem(struct bpf_map *map, void *key) +static void *__htab_map_lookup_elem(struct bpf_map *map, void *key) { struct bpf_htab *htab = container_of(map, struct bpf_htab, map); struct hlist_head *head; @@ -166,6 +182,13 @@ static void *htab_map_lookup_elem(struct bpf_map *map, void *key) l = lookup_elem_raw(head, hash, key, key_size); + return l; +} + +static void *htab_map_lookup_elem(struct bpf_map *map, void *key) +{ + struct htab_elem *l = __htab_map_lookup_elem(map, key); + if (l) return l->key + round_up(map->key_size, 8); @@ -230,65 +253,139 @@ find_first_elem: return -ENOENT; } + +static inline void htab_elem_set_ptr(struct htab_elem *l, u32 key_size, + void __percpu *pptr) +{ + *(void __percpu **)(l->key + key_size) = pptr; +} + +static inline void __percpu *htab_elem_get_ptr(struct htab_elem *l, u32 key_size) +{ + return *(void __percpu **)(l->key + key_size); +} + +static void htab_percpu_elem_free(struct htab_elem *l) +{ + free_percpu(htab_elem_get_ptr(l, l->key_size)); + kfree(l); +} + +static void htab_percpu_elem_free_rcu(struct rcu_head *head) +{ + struct htab_elem *l = container_of(head, struct htab_elem, rcu); + + htab_percpu_elem_free(l); +} + +static void free_htab_elem(struct htab_elem *l, bool percpu, u32 key_size) +{ + if (percpu) { + l->key_size = key_size; + call_rcu(&l->rcu, htab_percpu_elem_free_rcu); + } else { + kfree_rcu(l, rcu); + } +} + +static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, + void *value, u32 key_size, u32 hash, + bool percpu) +{ + u32 size = htab->map.value_size; + struct htab_elem *l_new; + void __percpu *pptr; + + l_new = kmalloc(htab->elem_size, GFP_ATOMIC | __GFP_NOWARN); + if (!l_new) + return NULL; + + memcpy(l_new->key, key, key_size); + if (percpu) { + /* round up value_size to 8 bytes */ + size = round_up(size, 8); + + /* alloc_percpu zero-fills */ + pptr = __alloc_percpu_gfp(size, 8, GFP_ATOMIC | __GFP_NOWARN); + if (!pptr) { + kfree(l_new); + return NULL; + } + + /* copy true value_size bytes */ + memcpy(this_cpu_ptr(pptr), value, htab->map.value_size); + htab_elem_set_ptr(l_new, key_size, pptr); + } else { + memcpy(l_new->key + round_up(key_size, 8), value, size); + } + + l_new->hash = hash; + return l_new; +} + +static int check_flags(struct bpf_htab *htab, struct htab_elem *l_old, + u64 map_flags) +{ + if (!l_old && unlikely(atomic_read(&htab->count) >= htab->map.max_entries)) + /* if elem with this 'key' doesn't exist and we've reached + * max_entries limit, fail insertion of new elem + */ + return -E2BIG; + + if (l_old && map_flags == BPF_NOEXIST) + /* elem already exists */ + return -EEXIST; + + if (!l_old && map_flags == BPF_EXIST) + /* elem doesn't exist, cannot update it */ + return -ENOENT; + + return 0; +} + /* Called from syscall or from eBPF program */ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, u64 map_flags) { struct bpf_htab *htab = container_of(map, struct bpf_htab, map); - struct htab_elem *l_new, *l_old; + struct htab_elem *l_new = NULL, *l_old; struct hlist_head *head; - struct bucket *b; unsigned long flags; - u32 key_size; + struct bucket *b; + u32 key_size, hash; int ret; - if (map_flags > BPF_EXIST) + if (unlikely(map_flags > BPF_EXIST)) /* unknown flags */ return -EINVAL; WARN_ON_ONCE(!rcu_read_lock_held()); - /* allocate new element outside of lock */ - l_new = kmalloc(htab->elem_size, GFP_ATOMIC | __GFP_NOWARN); - if (!l_new) - return -ENOMEM; - key_size = map->key_size; - memcpy(l_new->key, key, key_size); - memcpy(l_new->key + round_up(key_size, 8), value, map->value_size); + hash = htab_map_hash(key, key_size); + + /* allocate new element outside of the lock, since + * we're most likley going to insert it + */ + l_new = alloc_htab_elem(htab, key, value, key_size, hash, false); + if (!l_new) + return -ENOMEM; - l_new->hash = htab_map_hash(l_new->key, key_size); - b = __select_bucket(htab, l_new->hash); + b = __select_bucket(htab, hash); head = &b->head; /* bpf_map_update_elem() can be called in_irq() */ raw_spin_lock_irqsave(&b->lock, flags); - l_old = lookup_elem_raw(head, l_new->hash, key, key_size); + l_old = lookup_elem_raw(head, hash, key, key_size); - if (!l_old && unlikely(atomic_read(&htab->count) >= map->max_entries)) { - /* if elem with this 'key' doesn't exist and we've reached - * max_entries limit, fail insertion of new elem - */ - ret = -E2BIG; + ret = check_flags(htab, l_old, map_flags); + if (ret) goto err; - } - if (l_old && map_flags == BPF_NOEXIST) { - /* elem already exists */ - ret = -EEXIST; - goto err; - } - - if (!l_old && map_flags == BPF_EXIST) { - /* elem doesn't exist, cannot update it */ - ret = -ENOENT; - goto err; - } - - /* add new element to the head of the list, so that concurrent - * search will find it before old elem + /* add new element to the head of the list, so that + * concurrent search will find it before old elem */ hlist_add_head_rcu(&l_new->hash_node, head); if (l_old) { @@ -298,7 +395,6 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, atomic_inc(&htab->count); } raw_spin_unlock_irqrestore(&b->lock, flags); - return 0; err: raw_spin_unlock_irqrestore(&b->lock, flags); @@ -306,10 +402,64 @@ err: return ret; } +static int htab_percpu_map_update_elem(struct bpf_map *map, void *key, + void *value, u64 map_flags) +{ + struct bpf_htab *htab = container_of(map, struct bpf_htab, map); + struct htab_elem *l_new = NULL, *l_old; + struct hlist_head *head; + unsigned long flags; + struct bucket *b; + u32 key_size, hash; + int ret; + + if (unlikely(map_flags > BPF_EXIST)) + /* unknown flags */ + return -EINVAL; + + WARN_ON_ONCE(!rcu_read_lock_held()); + + key_size = map->key_size; + + hash = htab_map_hash(key, key_size); + + b = __select_bucket(htab, hash); + head = &b->head; + + /* bpf_map_update_elem() can be called in_irq() */ + raw_spin_lock_irqsave(&b->lock, flags); + + l_old = lookup_elem_raw(head, hash, key, key_size); + + ret = check_flags(htab, l_old, map_flags); + if (ret) + goto err; + + if (l_old) { + /* per-cpu hash map can update value in-place */ + memcpy(this_cpu_ptr(htab_elem_get_ptr(l_old, key_size)), + value, htab->map.value_size); + } else { + l_new = alloc_htab_elem(htab, key, value, key_size, + hash, true); + if (!l_new) { + ret = -ENOMEM; + goto err; + } + hlist_add_head_rcu(&l_new->hash_node, head); + atomic_inc(&htab->count); + } + ret = 0; +err: + raw_spin_unlock_irqrestore(&b->lock, flags); + return ret; +} + /* Called from syscall or from eBPF program */ static int htab_map_delete_elem(struct bpf_map *map, void *key) { struct bpf_htab *htab = container_of(map, struct bpf_htab, map); + bool percpu = map->map_type == BPF_MAP_TYPE_PERCPU_HASH; struct hlist_head *head; struct bucket *b; struct htab_elem *l; @@ -332,7 +482,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key) if (l) { hlist_del_rcu(&l->hash_node); atomic_dec(&htab->count); - kfree_rcu(l, rcu); + free_htab_elem(l, percpu, key_size); ret = 0; } @@ -352,7 +502,12 @@ static void delete_all_elements(struct bpf_htab *htab) hlist_for_each_entry_safe(l, n, head, hash_node) { hlist_del_rcu(&l->hash_node); atomic_dec(&htab->count); - kfree(l); + if (htab->map.map_type == BPF_MAP_TYPE_PERCPU_HASH) { + l->key_size = htab->map.key_size; + htab_percpu_elem_free(l); + } else { + kfree(l); + } } } } @@ -391,9 +546,35 @@ static struct bpf_map_type_list htab_type __read_mostly = { .type = BPF_MAP_TYPE_HASH, }; +/* Called from eBPF program */ +static void *htab_percpu_map_lookup_elem(struct bpf_map *map, void *key) +{ + struct htab_elem *l = __htab_map_lookup_elem(map, key); + + if (l) + return this_cpu_ptr(htab_elem_get_ptr(l, map->key_size)); + else + return NULL; +} + +static const struct bpf_map_ops htab_percpu_ops = { + .map_alloc = htab_map_alloc, + .map_free = htab_map_free, + .map_get_next_key = htab_map_get_next_key, + .map_lookup_elem = htab_percpu_map_lookup_elem, + .map_update_elem = htab_percpu_map_update_elem, + .map_delete_elem = htab_map_delete_elem, +}; + +static struct bpf_map_type_list htab_percpu_type __read_mostly = { + .ops = &htab_percpu_ops, + .type = BPF_MAP_TYPE_PERCPU_HASH, +}; + static int __init register_htab_map(void) { bpf_register_map_type(&htab_type); + bpf_register_map_type(&htab_percpu_type); return 0; } late_initcall(register_htab_map); -- cgit From a10423b87a7eae75da79ce80a8d9475047a674ee Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 1 Feb 2016 22:39:54 -0800 Subject: bpf: introduce BPF_MAP_TYPE_PERCPU_ARRAY map Primary use case is a histogram array of latency where bpf program computes the latency of block requests or other events and stores histogram of latency into array of 64 elements. All cpus are constantly running, so normal increment is not accurate, bpf_xadd causes cache ping-pong and this per-cpu approach allows fastest collision-free counters. Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/bpf.h | 1 + include/uapi/linux/bpf.h | 1 + kernel/bpf/arraymap.c | 102 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 83d1926c61e4..141fb0d45731 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -151,6 +151,7 @@ struct bpf_array { union { char value[0] __aligned(8); void *ptrs[0] __aligned(8); + void __percpu *pptrs[0] __aligned(8); }; }; #define MAX_TAIL_CALL_CNT 32 diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 43ae40c8763e..2ee0fde1bf96 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -82,6 +82,7 @@ enum bpf_map_type { BPF_MAP_TYPE_PROG_ARRAY, BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_MAP_TYPE_PERCPU_HASH, + BPF_MAP_TYPE_PERCPU_ARRAY, }; enum bpf_prog_type { diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 89ebbc4d1164..b9bf1d7949ca 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -17,11 +17,39 @@ #include #include +static void bpf_array_free_percpu(struct bpf_array *array) +{ + int i; + + for (i = 0; i < array->map.max_entries; i++) + free_percpu(array->pptrs[i]); +} + +static int bpf_array_alloc_percpu(struct bpf_array *array) +{ + void __percpu *ptr; + int i; + + for (i = 0; i < array->map.max_entries; i++) { + ptr = __alloc_percpu_gfp(array->elem_size, 8, + GFP_USER | __GFP_NOWARN); + if (!ptr) { + bpf_array_free_percpu(array); + return -ENOMEM; + } + array->pptrs[i] = ptr; + } + + return 0; +} + /* Called from syscall */ static struct bpf_map *array_map_alloc(union bpf_attr *attr) { + bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY; struct bpf_array *array; - u32 elem_size, array_size; + u64 array_size; + u32 elem_size; /* check sanity of attributes */ if (attr->max_entries == 0 || attr->key_size != 4 || @@ -36,12 +64,16 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) elem_size = round_up(attr->value_size, 8); - /* check round_up into zero and u32 overflow */ - if (elem_size == 0 || - attr->max_entries > (U32_MAX - PAGE_SIZE - sizeof(*array)) / elem_size) + array_size = sizeof(*array); + if (percpu) + array_size += (u64) attr->max_entries * sizeof(void *); + else + array_size += (u64) attr->max_entries * elem_size; + + /* make sure there is no u32 overflow later in round_up() */ + if (array_size >= U32_MAX - PAGE_SIZE) return ERR_PTR(-ENOMEM); - array_size = sizeof(*array) + attr->max_entries * elem_size; /* allocate all map elements and zero-initialize them */ array = kzalloc(array_size, GFP_USER | __GFP_NOWARN); @@ -52,12 +84,25 @@ static struct bpf_map *array_map_alloc(union bpf_attr *attr) } /* copy mandatory map attributes */ + array->map.map_type = attr->map_type; array->map.key_size = attr->key_size; array->map.value_size = attr->value_size; array->map.max_entries = attr->max_entries; - array->map.pages = round_up(array_size, PAGE_SIZE) >> PAGE_SHIFT; array->elem_size = elem_size; + if (!percpu) + goto out; + + array_size += (u64) attr->max_entries * elem_size * num_possible_cpus(); + + if (array_size >= U32_MAX - PAGE_SIZE || + elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) { + kvfree(array); + return ERR_PTR(-ENOMEM); + } +out: + array->map.pages = round_up(array_size, PAGE_SIZE) >> PAGE_SHIFT; + return &array->map; } @@ -67,12 +112,24 @@ static void *array_map_lookup_elem(struct bpf_map *map, void *key) struct bpf_array *array = container_of(map, struct bpf_array, map); u32 index = *(u32 *)key; - if (index >= array->map.max_entries) + if (unlikely(index >= array->map.max_entries)) return NULL; return array->value + array->elem_size * index; } +/* Called from eBPF program */ +static void *percpu_array_map_lookup_elem(struct bpf_map *map, void *key) +{ + struct bpf_array *array = container_of(map, struct bpf_array, map); + u32 index = *(u32 *)key; + + if (unlikely(index >= array->map.max_entries)) + return NULL; + + return this_cpu_ptr(array->pptrs[index]); +} + /* Called from syscall */ static int array_map_get_next_key(struct bpf_map *map, void *key, void *next_key) { @@ -99,19 +156,24 @@ static int array_map_update_elem(struct bpf_map *map, void *key, void *value, struct bpf_array *array = container_of(map, struct bpf_array, map); u32 index = *(u32 *)key; - if (map_flags > BPF_EXIST) + if (unlikely(map_flags > BPF_EXIST)) /* unknown flags */ return -EINVAL; - if (index >= array->map.max_entries) + if (unlikely(index >= array->map.max_entries)) /* all elements were pre-allocated, cannot insert a new one */ return -E2BIG; - if (map_flags == BPF_NOEXIST) + if (unlikely(map_flags == BPF_NOEXIST)) /* all elements already exist */ return -EEXIST; - memcpy(array->value + array->elem_size * index, value, map->value_size); + if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) + memcpy(this_cpu_ptr(array->pptrs[index]), + value, map->value_size); + else + memcpy(array->value + array->elem_size * index, + value, map->value_size); return 0; } @@ -133,6 +195,9 @@ static void array_map_free(struct bpf_map *map) */ synchronize_rcu(); + if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) + bpf_array_free_percpu(array); + kvfree(array); } @@ -150,9 +215,24 @@ static struct bpf_map_type_list array_type __read_mostly = { .type = BPF_MAP_TYPE_ARRAY, }; +static const struct bpf_map_ops percpu_array_ops = { + .map_alloc = array_map_alloc, + .map_free = array_map_free, + .map_get_next_key = array_map_get_next_key, + .map_lookup_elem = percpu_array_map_lookup_elem, + .map_update_elem = array_map_update_elem, + .map_delete_elem = array_map_delete_elem, +}; + +static struct bpf_map_type_list percpu_array_type __read_mostly = { + .ops = &percpu_array_ops, + .type = BPF_MAP_TYPE_PERCPU_ARRAY, +}; + static int __init register_array_map(void) { bpf_register_map_type(&array_type); + bpf_register_map_type(&percpu_array_type); return 0; } late_initcall(register_array_map); -- cgit From 15a07b33814d14ca817887dbea8530728dc0fbe4 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 1 Feb 2016 22:39:55 -0800 Subject: bpf: add lookup/update support for per-cpu hash and array maps The functions bpf_map_lookup_elem(map, key, value) and bpf_map_update_elem(map, key, value, flags) need to get/set values from all-cpus for per-cpu hash and array maps, so that user space can aggregate/update them as necessary. Example of single counter aggregation in user space: unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); long values[nr_cpus]; long value = 0; bpf_lookup_elem(fd, key, values); for (i = 0; i < nr_cpus; i++) value += values[i]; The user space must provide round_up(value_size, 8) * nr_cpus array to get/set values, since kernel will use 'long' copy of per-cpu values to try to copy good counters atomically. It's a best-effort, since bpf programs and user space are racing to access the same memory. Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- include/linux/bpf.h | 23 ++++++++++++++ kernel/bpf/arraymap.c | 64 +++++++++++++++++++++++++++++++++++++++ kernel/bpf/hashtab.c | 83 +++++++++++++++++++++++++++++++++++++++++++++------ kernel/bpf/syscall.c | 57 ++++++++++++++++++++++++----------- 4 files changed, 201 insertions(+), 26 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 141fb0d45731..90ee6ab24bc5 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -183,6 +183,29 @@ int bpf_prog_new_fd(struct bpf_prog *prog); int bpf_obj_pin_user(u32 ufd, const char __user *pathname); int bpf_obj_get_user(const char __user *pathname); +int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value); +int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value); +int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value, + u64 flags); +int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value, + u64 flags); + +/* memcpy that is used with 8-byte aligned pointers, power-of-8 size and + * forced to use 'long' read/writes to try to atomically copy long counters. + * Best-effort only. No barriers here, since it _will_ race with concurrent + * updates from BPF programs. Called from bpf syscall and mostly used with + * size 8 or 16 bytes, so ask compiler to inline it. + */ +static inline void bpf_long_memcpy(void *dst, const void *src, u32 size) +{ + const long *lsrc = src; + long *ldst = dst; + + size /= sizeof(long); + while (size--) + *ldst++ = *lsrc++; +} + /* verify correctness of eBPF program */ int bpf_check(struct bpf_prog **fp, union bpf_attr *attr); #else diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index b9bf1d7949ca..bd3bdf2486a7 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -130,6 +130,32 @@ static void *percpu_array_map_lookup_elem(struct bpf_map *map, void *key) return this_cpu_ptr(array->pptrs[index]); } +int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value) +{ + struct bpf_array *array = container_of(map, struct bpf_array, map); + u32 index = *(u32 *)key; + void __percpu *pptr; + int cpu, off = 0; + u32 size; + + if (unlikely(index >= array->map.max_entries)) + return -ENOENT; + + /* per_cpu areas are zero-filled and bpf programs can only + * access 'value_size' of them, so copying rounded areas + * will not leak any kernel data + */ + size = round_up(map->value_size, 8); + rcu_read_lock(); + pptr = array->pptrs[index]; + for_each_possible_cpu(cpu) { + bpf_long_memcpy(value + off, per_cpu_ptr(pptr, cpu), size); + off += size; + } + rcu_read_unlock(); + return 0; +} + /* Called from syscall */ static int array_map_get_next_key(struct bpf_map *map, void *key, void *next_key) { @@ -177,6 +203,44 @@ static int array_map_update_elem(struct bpf_map *map, void *key, void *value, return 0; } +int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value, + u64 map_flags) +{ + struct bpf_array *array = container_of(map, struct bpf_array, map); + u32 index = *(u32 *)key; + void __percpu *pptr; + int cpu, off = 0; + u32 size; + + if (unlikely(map_flags > BPF_EXIST)) + /* unknown flags */ + return -EINVAL; + + if (unlikely(index >= array->map.max_entries)) + /* all elements were pre-allocated, cannot insert a new one */ + return -E2BIG; + + if (unlikely(map_flags == BPF_NOEXIST)) + /* all elements already exist */ + return -EEXIST; + + /* the user space will provide round_up(value_size, 8) bytes that + * will be copied into per-cpu area. bpf programs can only access + * value_size of it. During lookup the same extra bytes will be + * returned or zeros which were zero-filled by percpu_alloc, + * so no kernel data leaks possible + */ + size = round_up(map->value_size, 8); + rcu_read_lock(); + pptr = array->pptrs[index]; + for_each_possible_cpu(cpu) { + bpf_long_memcpy(per_cpu_ptr(pptr, cpu), value + off, size); + off += size; + } + rcu_read_unlock(); + return 0; +} + /* Called from syscall or from eBPF program */ static int array_map_delete_elem(struct bpf_map *map, void *key) { diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 2be5f6e8bb04..fd5db8fe9360 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -290,7 +290,7 @@ static void free_htab_elem(struct htab_elem *l, bool percpu, u32 key_size) static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, void *value, u32 key_size, u32 hash, - bool percpu) + bool percpu, bool onallcpus) { u32 size = htab->map.value_size; struct htab_elem *l_new; @@ -312,8 +312,18 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key, return NULL; } - /* copy true value_size bytes */ - memcpy(this_cpu_ptr(pptr), value, htab->map.value_size); + if (!onallcpus) { + /* copy true value_size bytes */ + memcpy(this_cpu_ptr(pptr), value, htab->map.value_size); + } else { + int off = 0, cpu; + + for_each_possible_cpu(cpu) { + bpf_long_memcpy(per_cpu_ptr(pptr, cpu), + value + off, size); + off += size; + } + } htab_elem_set_ptr(l_new, key_size, pptr); } else { memcpy(l_new->key + round_up(key_size, 8), value, size); @@ -368,7 +378,7 @@ static int htab_map_update_elem(struct bpf_map *map, void *key, void *value, /* allocate new element outside of the lock, since * we're most likley going to insert it */ - l_new = alloc_htab_elem(htab, key, value, key_size, hash, false); + l_new = alloc_htab_elem(htab, key, value, key_size, hash, false, false); if (!l_new) return -ENOMEM; @@ -402,8 +412,9 @@ err: return ret; } -static int htab_percpu_map_update_elem(struct bpf_map *map, void *key, - void *value, u64 map_flags) +static int __htab_percpu_map_update_elem(struct bpf_map *map, void *key, + void *value, u64 map_flags, + bool onallcpus) { struct bpf_htab *htab = container_of(map, struct bpf_htab, map); struct htab_elem *l_new = NULL, *l_old; @@ -436,12 +447,25 @@ static int htab_percpu_map_update_elem(struct bpf_map *map, void *key, goto err; if (l_old) { + void __percpu *pptr = htab_elem_get_ptr(l_old, key_size); + u32 size = htab->map.value_size; + /* per-cpu hash map can update value in-place */ - memcpy(this_cpu_ptr(htab_elem_get_ptr(l_old, key_size)), - value, htab->map.value_size); + if (!onallcpus) { + memcpy(this_cpu_ptr(pptr), value, size); + } else { + int off = 0, cpu; + + size = round_up(size, 8); + for_each_possible_cpu(cpu) { + bpf_long_memcpy(per_cpu_ptr(pptr, cpu), + value + off, size); + off += size; + } + } } else { l_new = alloc_htab_elem(htab, key, value, key_size, - hash, true); + hash, true, onallcpus); if (!l_new) { ret = -ENOMEM; goto err; @@ -455,6 +479,12 @@ err: return ret; } +static int htab_percpu_map_update_elem(struct bpf_map *map, void *key, + void *value, u64 map_flags) +{ + return __htab_percpu_map_update_elem(map, key, value, map_flags, false); +} + /* Called from syscall or from eBPF program */ static int htab_map_delete_elem(struct bpf_map *map, void *key) { @@ -557,6 +587,41 @@ static void *htab_percpu_map_lookup_elem(struct bpf_map *map, void *key) return NULL; } +int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value) +{ + struct htab_elem *l; + void __percpu *pptr; + int ret = -ENOENT; + int cpu, off = 0; + u32 size; + + /* per_cpu areas are zero-filled and bpf programs can only + * access 'value_size' of them, so copying rounded areas + * will not leak any kernel data + */ + size = round_up(map->value_size, 8); + rcu_read_lock(); + l = __htab_map_lookup_elem(map, key); + if (!l) + goto out; + pptr = htab_elem_get_ptr(l, map->key_size); + for_each_possible_cpu(cpu) { + bpf_long_memcpy(value + off, + per_cpu_ptr(pptr, cpu), size); + off += size; + } + ret = 0; +out: + rcu_read_unlock(); + return ret; +} + +int bpf_percpu_hash_update(struct bpf_map *map, void *key, void *value, + u64 map_flags) +{ + return __htab_percpu_map_update_elem(map, key, value, map_flags, true); +} + static const struct bpf_map_ops htab_percpu_ops = { .map_alloc = htab_map_alloc, .map_free = htab_map_free, diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 637397059f76..c95a753c2007 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -239,6 +239,7 @@ static int map_lookup_elem(union bpf_attr *attr) int ufd = attr->map_fd; struct bpf_map *map; void *key, *value, *ptr; + u32 value_size; struct fd f; int err; @@ -259,23 +260,35 @@ static int map_lookup_elem(union bpf_attr *attr) if (copy_from_user(key, ukey, map->key_size) != 0) goto free_key; + if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || + map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) + value_size = round_up(map->value_size, 8) * num_possible_cpus(); + else + value_size = map->value_size; + err = -ENOMEM; - value = kmalloc(map->value_size, GFP_USER | __GFP_NOWARN); + value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); if (!value) goto free_key; - rcu_read_lock(); - ptr = map->ops->map_lookup_elem(map, key); - if (ptr) - memcpy(value, ptr, map->value_size); - rcu_read_unlock(); + if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) { + err = bpf_percpu_hash_copy(map, key, value); + } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { + err = bpf_percpu_array_copy(map, key, value); + } else { + rcu_read_lock(); + ptr = map->ops->map_lookup_elem(map, key); + if (ptr) + memcpy(value, ptr, value_size); + rcu_read_unlock(); + err = ptr ? 0 : -ENOENT; + } - err = -ENOENT; - if (!ptr) + if (err) goto free_value; err = -EFAULT; - if (copy_to_user(uvalue, value, map->value_size) != 0) + if (copy_to_user(uvalue, value, value_size) != 0) goto free_value; err = 0; @@ -298,6 +311,7 @@ static int map_update_elem(union bpf_attr *attr) int ufd = attr->map_fd; struct bpf_map *map; void *key, *value; + u32 value_size; struct fd f; int err; @@ -318,21 +332,30 @@ static int map_update_elem(union bpf_attr *attr) if (copy_from_user(key, ukey, map->key_size) != 0) goto free_key; + if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || + map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) + value_size = round_up(map->value_size, 8) * num_possible_cpus(); + else + value_size = map->value_size; + err = -ENOMEM; - value = kmalloc(map->value_size, GFP_USER | __GFP_NOWARN); + value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); if (!value) goto free_key; err = -EFAULT; - if (copy_from_user(value, uvalue, map->value_size) != 0) + if (copy_from_user(value, uvalue, value_size) != 0) goto free_value; - /* eBPF program that use maps are running under rcu_read_lock(), - * therefore all map accessors rely on this fact, so do the same here - */ - rcu_read_lock(); - err = map->ops->map_update_elem(map, key, value, attr->flags); - rcu_read_unlock(); + if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH) { + err = bpf_percpu_hash_update(map, key, value, attr->flags); + } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) { + err = bpf_percpu_array_update(map, key, value, attr->flags); + } else { + rcu_read_lock(); + err = map->ops->map_update_elem(map, key, value, attr->flags); + rcu_read_unlock(); + } free_value: kfree(value); -- cgit From e15596717948c95587a0b15363030283c126c23a Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Mon, 1 Feb 2016 22:39:56 -0800 Subject: samples/bpf: unit test for BPF_MAP_TYPE_PERCPU_HASH A sanity test for BPF_MAP_TYPE_PERCPU_HASH. Signed-off-by: Martin KaFai Lau Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/test_maps.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c index 6299ee95cd11..5f5fe5332148 100644 --- a/samples/bpf/test_maps.c +++ b/samples/bpf/test_maps.c @@ -89,6 +89,100 @@ static void test_hashmap_sanity(int i, void *data) close(map_fd); } +/* sanity tests for percpu map API */ +static void test_percpu_hashmap_sanity(int task, void *data) +{ + long long key, next_key; + int expected_key_mask = 0; + unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + long long value[nr_cpus]; + int map_fd, i; + + map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key), + sizeof(value[0]), 2); + if (map_fd < 0) { + printf("failed to create hashmap '%s'\n", strerror(errno)); + exit(1); + } + + for (i = 0; i < nr_cpus; i++) + value[i] = i + 100; + key = 1; + /* insert key=1 element */ + assert(!(expected_key_mask & key)); + assert(bpf_update_elem(map_fd, &key, value, BPF_ANY) == 0); + expected_key_mask |= key; + + /* BPF_NOEXIST means: add new element if it doesn't exist */ + assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 && + /* key=1 already exists */ + errno == EEXIST); + + /* -1 is an invalid flag */ + assert(bpf_update_elem(map_fd, &key, value, -1) == -1 && + errno == EINVAL); + + /* check that key=1 can be found. value could be 0 if the lookup + * was run from a different cpu. + */ + value[0] = 1; + assert(bpf_lookup_elem(map_fd, &key, value) == 0 && value[0] == 100); + + key = 2; + /* check that key=2 is not found */ + assert(bpf_lookup_elem(map_fd, &key, value) == -1 && errno == ENOENT); + + /* BPF_EXIST means: update existing element */ + assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == -1 && + /* key=2 is not there */ + errno == ENOENT); + + /* insert key=2 element */ + assert(!(expected_key_mask & key)); + assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == 0); + expected_key_mask |= key; + + /* key=1 and key=2 were inserted, check that key=0 cannot be inserted + * due to max_entries limit + */ + key = 0; + assert(bpf_update_elem(map_fd, &key, value, BPF_NOEXIST) == -1 && + errno == E2BIG); + + /* check that key = 0 doesn't exist */ + assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT); + + /* iterate over two elements */ + while (!bpf_get_next_key(map_fd, &key, &next_key)) { + assert((expected_key_mask & next_key) == next_key); + expected_key_mask &= ~next_key; + + assert(bpf_lookup_elem(map_fd, &next_key, value) == 0); + for (i = 0; i < nr_cpus; i++) + assert(value[i] == i + 100); + + key = next_key; + } + assert(errno == ENOENT); + + /* Update with BPF_EXIST */ + key = 1; + assert(bpf_update_elem(map_fd, &key, value, BPF_EXIST) == 0); + + /* delete both elements */ + key = 1; + assert(bpf_delete_elem(map_fd, &key) == 0); + key = 2; + assert(bpf_delete_elem(map_fd, &key) == 0); + assert(bpf_delete_elem(map_fd, &key) == -1 && errno == ENOENT); + + key = 0; + /* check that map is empty */ + assert(bpf_get_next_key(map_fd, &key, &next_key) == -1 && + errno == ENOENT); + close(map_fd); +} + static void test_arraymap_sanity(int i, void *data) { int key, next_key, map_fd; @@ -209,6 +303,7 @@ static void run_parallel(int tasks, void (*fn)(int i, void *data), void *data) static void test_map_stress(void) { run_parallel(100, test_hashmap_sanity, NULL); + run_parallel(100, test_percpu_hashmap_sanity, NULL); run_parallel(100, test_arraymap_sanity, NULL); } @@ -282,6 +377,7 @@ static void test_map_parallel(void) int main(void) { test_hashmap_sanity(0, NULL); + test_percpu_hashmap_sanity(0, NULL); test_arraymap_sanity(0, NULL); test_map_large(); test_map_parallel(); -- cgit From df570f577231407d929bdc6f59ae2f53e0028e8a Mon Sep 17 00:00:00 2001 From: "tom.leiming@gmail.com" Date: Mon, 1 Feb 2016 22:39:57 -0800 Subject: samples/bpf: unit test for BPF_MAP_TYPE_PERCPU_ARRAY A sanity test for BPF_MAP_TYPE_PERCPU_ARRAY Signed-off-by: Ming Lei Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/test_maps.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/samples/bpf/test_maps.c b/samples/bpf/test_maps.c index 5f5fe5332148..ad466ed33093 100644 --- a/samples/bpf/test_maps.c +++ b/samples/bpf/test_maps.c @@ -236,6 +236,94 @@ static void test_arraymap_sanity(int i, void *data) close(map_fd); } +static void test_percpu_arraymap_many_keys(void) +{ + unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + unsigned nr_keys = 20000; + long values[nr_cpus]; + int key, map_fd, i; + + map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), + sizeof(values[0]), nr_keys); + if (map_fd < 0) { + printf("failed to create per-cpu arraymap '%s'\n", + strerror(errno)); + exit(1); + } + + for (i = 0; i < nr_cpus; i++) + values[i] = i + 10; + + for (key = 0; key < nr_keys; key++) + assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0); + + for (key = 0; key < nr_keys; key++) { + for (i = 0; i < nr_cpus; i++) + values[i] = 0; + assert(bpf_lookup_elem(map_fd, &key, values) == 0); + for (i = 0; i < nr_cpus; i++) + assert(values[i] == i + 10); + } + + close(map_fd); +} + +static void test_percpu_arraymap_sanity(int i, void *data) +{ + unsigned nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + long values[nr_cpus]; + int key, next_key, map_fd; + + map_fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key), + sizeof(values[0]), 2); + if (map_fd < 0) { + printf("failed to create arraymap '%s'\n", strerror(errno)); + exit(1); + } + + for (i = 0; i < nr_cpus; i++) + values[i] = i + 100; + + key = 1; + /* insert key=1 element */ + assert(bpf_update_elem(map_fd, &key, values, BPF_ANY) == 0); + + values[0] = 0; + assert(bpf_update_elem(map_fd, &key, values, BPF_NOEXIST) == -1 && + errno == EEXIST); + + /* check that key=1 can be found */ + assert(bpf_lookup_elem(map_fd, &key, values) == 0 && values[0] == 100); + + key = 0; + /* check that key=0 is also found and zero initialized */ + assert(bpf_lookup_elem(map_fd, &key, values) == 0 && + values[0] == 0 && values[nr_cpus - 1] == 0); + + + /* check that key=2 cannot be inserted due to max_entries limit */ + key = 2; + assert(bpf_update_elem(map_fd, &key, values, BPF_EXIST) == -1 && + errno == E2BIG); + + /* check that key = 2 doesn't exist */ + assert(bpf_lookup_elem(map_fd, &key, values) == -1 && errno == ENOENT); + + /* iterate over two elements */ + assert(bpf_get_next_key(map_fd, &key, &next_key) == 0 && + next_key == 0); + assert(bpf_get_next_key(map_fd, &next_key, &next_key) == 0 && + next_key == 1); + assert(bpf_get_next_key(map_fd, &next_key, &next_key) == -1 && + errno == ENOENT); + + /* delete shouldn't succeed */ + key = 1; + assert(bpf_delete_elem(map_fd, &key) == -1 && errno == EINVAL); + + close(map_fd); +} + #define MAP_SIZE (32 * 1024) static void test_map_large(void) { @@ -305,6 +393,7 @@ static void test_map_stress(void) run_parallel(100, test_hashmap_sanity, NULL); run_parallel(100, test_percpu_hashmap_sanity, NULL); run_parallel(100, test_arraymap_sanity, NULL); + run_parallel(100, test_percpu_arraymap_sanity, NULL); } #define TASKS 1024 @@ -379,6 +468,9 @@ int main(void) test_hashmap_sanity(0, NULL); test_percpu_hashmap_sanity(0, NULL); test_arraymap_sanity(0, NULL); + test_percpu_arraymap_sanity(0, NULL); + test_percpu_arraymap_many_keys(); + test_map_large(); test_map_parallel(); test_map_stress(); -- cgit From 3059303f59cf90a84e7fdef154ff0b215bcfaa97 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 1 Feb 2016 22:39:58 -0800 Subject: samples/bpf: update tracex[23] examples to use per-cpu maps Signed-off-by: Alexei Starovoitov Signed-off-by: David S. Miller --- samples/bpf/tracex2_kern.c | 2 +- samples/bpf/tracex2_user.c | 7 ++++++- samples/bpf/tracex3_kern.c | 8 ++++---- samples/bpf/tracex3_user.c | 21 ++++++++++++++------- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c index b32367cfbff4..09c1adc27d42 100644 --- a/samples/bpf/tracex2_kern.c +++ b/samples/bpf/tracex2_kern.c @@ -70,7 +70,7 @@ struct hist_key { }; struct bpf_map_def SEC("maps") my_hist_map = { - .type = BPF_MAP_TYPE_HASH, + .type = BPF_MAP_TYPE_PERCPU_HASH, .key_size = sizeof(struct hist_key), .value_size = sizeof(long), .max_entries = 1024, diff --git a/samples/bpf/tracex2_user.c b/samples/bpf/tracex2_user.c index cd0241c1447a..ab5b19e68acf 100644 --- a/samples/bpf/tracex2_user.c +++ b/samples/bpf/tracex2_user.c @@ -37,6 +37,8 @@ struct hist_key { static void print_hist_for_pid(int fd, void *task) { struct hist_key key = {}, next_key; + unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + long values[nr_cpus]; char starstr[MAX_STARS]; long value; long data[MAX_INDEX] = {}; @@ -49,7 +51,10 @@ static void print_hist_for_pid(int fd, void *task) key = next_key; continue; } - bpf_lookup_elem(fd, &next_key, &value); + bpf_lookup_elem(fd, &next_key, values); + value = 0; + for (i = 0; i < nr_cpus; i++) + value += values[i]; ind = next_key.index; data[ind] = value; if (value && ind > max_ind) diff --git a/samples/bpf/tracex3_kern.c b/samples/bpf/tracex3_kern.c index bf337fbb0947..9974c3d7c18b 100644 --- a/samples/bpf/tracex3_kern.c +++ b/samples/bpf/tracex3_kern.c @@ -20,7 +20,7 @@ struct bpf_map_def SEC("maps") my_map = { /* kprobe is NOT a stable ABI. If kernel internals change this bpf+kprobe * example will no longer be meaningful */ -SEC("kprobe/blk_mq_start_request") +SEC("kprobe/blk_start_request") int bpf_prog1(struct pt_regs *ctx) { long rq = PT_REGS_PARM1(ctx); @@ -42,13 +42,13 @@ static unsigned int log2l(unsigned long long n) #define SLOTS 100 struct bpf_map_def SEC("maps") lat_map = { - .type = BPF_MAP_TYPE_ARRAY, + .type = BPF_MAP_TYPE_PERCPU_ARRAY, .key_size = sizeof(u32), .value_size = sizeof(u64), .max_entries = SLOTS, }; -SEC("kprobe/blk_update_request") +SEC("kprobe/blk_account_io_completion") int bpf_prog2(struct pt_regs *ctx) { long rq = PT_REGS_PARM1(ctx); @@ -81,7 +81,7 @@ int bpf_prog2(struct pt_regs *ctx) value = bpf_map_lookup_elem(&lat_map, &index); if (value) - __sync_fetch_and_add((long *)value, 1); + *value += 1; return 0; } diff --git a/samples/bpf/tracex3_user.c b/samples/bpf/tracex3_user.c index 0aaa933ab938..48716f7f0d8b 100644 --- a/samples/bpf/tracex3_user.c +++ b/samples/bpf/tracex3_user.c @@ -20,11 +20,13 @@ static void clear_stats(int fd) { + unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); + __u64 values[nr_cpus]; __u32 key; - __u64 value = 0; + memset(values, 0, sizeof(values)); for (key = 0; key < SLOTS; key++) - bpf_update_elem(fd, &key, &value, BPF_ANY); + bpf_update_elem(fd, &key, values, BPF_ANY); } const char *color[] = { @@ -75,15 +77,20 @@ static void print_banner(void) static void print_hist(int fd) { - __u32 key; - __u64 value; - __u64 cnt[SLOTS]; - __u64 max_cnt = 0; + unsigned int nr_cpus = sysconf(_SC_NPROCESSORS_CONF); __u64 total_events = 0; + long values[nr_cpus]; + __u64 max_cnt = 0; + __u64 cnt[SLOTS]; + __u64 value; + __u32 key; + int i; for (key = 0; key < SLOTS; key++) { + bpf_lookup_elem(fd, &key, values); value = 0; - bpf_lookup_elem(fd, &key, &value); + for (i = 0; i < nr_cpus; i++) + value += values[i]; cnt[key] = value; total_events += value; if (value > max_cnt) -- cgit From 387b75f8b31437792e8334390fdf5cf060d1e3da Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 2 Feb 2016 07:47:14 +0100 Subject: bgmac: add helper checking for BCM4707 / BCM53018 chip id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Chipsets with BCM4707 / BCM53018 ID require special handling at a few places in the code. It's likely there will be more IDs to check in the future. To simplify it add this trivial helper. Signed-off-by: Rafał Miłecki Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bgmac.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 06f6cffdfaf5..230f8e6209e5 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -26,6 +26,17 @@ static const struct bcma_device_id bgmac_bcma_tbl[] = { }; MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); +static inline bool bgmac_is_bcm4707_family(struct bgmac *bgmac) +{ + switch (bgmac->core->bus->chipinfo.id) { + case BCMA_CHIP_ID_BCM4707: + case BCMA_CHIP_ID_BCM53018: + return true; + default: + return false; + } +} + static bool bgmac_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, int timeout) { @@ -987,11 +998,9 @@ static void bgmac_mac_speed(struct bgmac *bgmac) static void bgmac_miiconfig(struct bgmac *bgmac) { struct bcma_device *core = bgmac->core; - struct bcma_chipinfo *ci = &core->bus->chipinfo; u8 imode; - if (ci->id == BCMA_CHIP_ID_BCM4707 || - ci->id == BCMA_CHIP_ID_BCM53018) { + if (bgmac_is_bcm4707_family(bgmac)) { bcma_awrite32(core, BCMA_IOCTL, bcma_aread32(core, BCMA_IOCTL) | 0x40 | BGMAC_BCMA_IOCTL_SW_CLKEN); @@ -1055,9 +1064,7 @@ static void bgmac_chip_reset(struct bgmac *bgmac) } /* Request Misc PLL for corerev > 2 */ - if (core->id.rev > 2 && - ci->id != BCMA_CHIP_ID_BCM4707 && - ci->id != BCMA_CHIP_ID_BCM53018) { + if (core->id.rev > 2 && !bgmac_is_bcm4707_family(bgmac)) { bgmac_set(bgmac, BCMA_CLKCTLST, BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ); bgmac_wait_value(bgmac->core, BCMA_CLKCTLST, @@ -1193,8 +1200,7 @@ static void bgmac_enable(struct bgmac *bgmac) break; } - if (ci->id != BCMA_CHIP_ID_BCM4707 && - ci->id != BCMA_CHIP_ID_BCM53018) { + if (!bgmac_is_bcm4707_family(bgmac)) { rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL); rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK; bp_clk = bcma_pmu_get_bus_clock(&bgmac->core->bus->drv_cc) / @@ -1472,14 +1478,12 @@ static int bgmac_fixed_phy_register(struct bgmac *bgmac) static int bgmac_mii_register(struct bgmac *bgmac) { - struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo; struct mii_bus *mii_bus; struct phy_device *phy_dev; char bus_id[MII_BUS_ID_SIZE + 3]; int err = 0; - if (ci->id == BCMA_CHIP_ID_BCM4707 || - ci->id == BCMA_CHIP_ID_BCM53018) + if (bgmac_is_bcm4707_family(bgmac)) return bgmac_fixed_phy_register(bgmac); mii_bus = mdiobus_alloc(); @@ -1539,7 +1543,6 @@ static void bgmac_mii_unregister(struct bgmac *bgmac) /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */ static int bgmac_probe(struct bcma_device *core) { - struct bcma_chipinfo *ci = &core->bus->chipinfo; struct net_device *net_dev; struct bgmac *bgmac; struct ssb_sprom *sprom = &core->bus->sprom; @@ -1620,8 +1623,7 @@ static int bgmac_probe(struct bcma_device *core) bgmac_chip_reset(bgmac); /* For Northstar, we have to take all GMAC core out of reset */ - if (ci->id == BCMA_CHIP_ID_BCM4707 || - ci->id == BCMA_CHIP_ID_BCM53018) { + if (bgmac_is_bcm4707_family(bgmac)) { struct bcma_device *ns_core; int ns_gmac; -- cgit From c6140a299bdf2425d092383fafaaf2a4a3745989 Mon Sep 17 00:00:00 2001 From: Zhang Shengju Date: Tue, 2 Feb 2016 08:32:55 +0000 Subject: bonding: add slave device name for debug netdev_dbg() will add bond device name, it will be helpful if we print slave device name. Signed-off-by: Zhang Shengju Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6587929b040a..7c9eb6704a7d 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -618,8 +618,8 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active, static void bond_set_dev_addr(struct net_device *bond_dev, struct net_device *slave_dev) { - netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", - bond_dev, slave_dev, slave_dev->addr_len); + netdev_dbg(bond_dev, "bond_dev=%p slave_dev=%p slave_dev->name=%s slave_dev->addr_len=%d\n", + bond_dev, slave_dev, slave_dev->name, slave_dev->addr_len); memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); bond_dev->addr_assign_type = NET_ADDR_STOLEN; call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); -- cgit From 4f61d4ef7088581997ad95ad37db2d8a459844e4 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:08 +0100 Subject: tipc: remove incorrect check for subscription timeout value Until now, during subscription creation we set sub->timeout by converting the timeout request value in milliseconds to jiffies. This is followed by setting the timeout value in the timer if sub->timeout != TIPC_WAIT_FOREVER. For a subscription create request with a timeout value of TIPC_WAIT_FOREVER, msecs_to_jiffies(TIPC_WAIT_FOREVER) returns MAX_JIFFY_OFFSET (0xfffffffe). This is not equal to TIPC_WAIT_FOREVER (0xffffffff). In this commit, we remove this check. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 69ee2eeef968..7e61a907d860 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -270,8 +270,7 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, memcpy(&sub->evt.s, s, sizeof(*s)); atomic_inc(&tn->subscription_count); setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); - if (sub->timeout != TIPC_WAIT_FOREVER) - sub->timeout += jiffies; + sub->timeout += jiffies; if (!mod_timer(&sub->timer, sub->timeout)) tipc_subscrb_get(subscriber); *sub_p = sub; -- cgit From 3086523149ef4c15f5e75bb2ed9f43a8f3f95015 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:09 +0100 Subject: tipc: remove filter and timeout elements from struct tipc_subscription Until now, struct tipc_subscription has duplicate timeout and filter attributes present: 1. directly as members of struct tipc_subscription 2. in struct tipc_subscr, which is contained in struct tipc_event In this commit, we remove the references to these elements as members of struct tipc_subscription and replace them with elements from struct tipc_subscr. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 15 ++++++++------- net/tipc/subscr.h | 5 ----- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7e61a907d860..cef0b6b967d3 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -110,7 +110,8 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, { if (!tipc_subscrp_check_overlap(sub, found_lower, found_upper)) return; - if (!must && !(sub->filter & TIPC_SUB_PORTS)) + if (!must && + !(htohl(sub->evt.s.filter, sub->swap) & TIPC_SUB_PORTS)) return; tipc_subscrp_send_event(sub, found_lower, found_upper, event, port_ref, @@ -222,6 +223,7 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_subscription *sub; + u32 timeout, filter; int swap; /* Determine subscriber's endianness */ @@ -253,10 +255,8 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, sub->seq.type = htohl(s->seq.type, swap); sub->seq.lower = htohl(s->seq.lower, swap); sub->seq.upper = htohl(s->seq.upper, swap); - sub->timeout = msecs_to_jiffies(htohl(s->timeout, swap)); - sub->filter = htohl(s->filter, swap); - if ((!(sub->filter & TIPC_SUB_PORTS) == - !(sub->filter & TIPC_SUB_SERVICE)) || + filter = htohl(s->filter, swap); + if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) || (sub->seq.lower > sub->seq.upper)) { pr_warn("Subscription rejected, illegal request\n"); kfree(sub); @@ -265,13 +265,14 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, spin_lock_bh(&subscriber->lock); list_add(&sub->subscrp_list, &subscriber->subscrp_list); spin_unlock_bh(&subscriber->lock); + sub->subscriber = subscriber; sub->swap = swap; memcpy(&sub->evt.s, s, sizeof(*s)); atomic_inc(&tn->subscription_count); setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); - sub->timeout += jiffies; - if (!mod_timer(&sub->timer, sub->timeout)) + timeout = htohl(sub->evt.s.timeout, swap); + if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) tipc_subscrb_get(subscriber); *sub_p = sub; return 0; diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 92ee18cc5fe6..9e69dbf05626 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -50,12 +50,9 @@ struct tipc_subscriber; * @subscriber: pointer to its subscriber * @seq: name sequence associated with subscription * @net: point to network namespace - * @timeout: duration of subscription (in ms) - * @filter: event filtering to be done for subscription * @timer: timer governing subscription duration (optional) * @nameseq_list: adjacent subscriptions in name sequence's subscription list * @subscrp_list: adjacent subscriptions in subscriber's subscription list - * @server_ref: object reference of server port associated with subscription * @swap: indicates if subscriber uses opposite endianness in its messages * @evt: template for events generated by subscription */ @@ -63,8 +60,6 @@ struct tipc_subscription { struct tipc_subscriber *subscriber; struct tipc_name_seq seq; struct net *net; - unsigned long timeout; - u32 filter; struct timer_list timer; struct list_head nameseq_list; struct list_head subscrp_list; -- cgit From a4273c73ebf06515eab6b5a84817a175ad8acdc4 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:10 +0100 Subject: tipc: remove struct tipc_name_seq from struct tipc_subscription Until now, struct tipc_subscriber has duplicate fields for type, upper and lower (as member of struct tipc_name_seq) at: 1. as member seq in struct tipc_subscription 2. as member seq in struct tipc_subscr, which is contained in struct tipc_event The former structure contains the type, upper and lower values in network byte order and the later contains the intact copy of the request. The struct tipc_subscription contains a field swap to determine if request needs network byte order conversion. Thus by using swap, we can convert the request when required instead of duplicating it. In this commit, 1. we remove the references to these elements as members of struct tipc_subscription and replace them with elements from struct tipc_subscr. 2. provide new functions to convert the user request into network byte order. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/name_table.c | 14 ++++++++++---- net/tipc/subscr.c | 33 +++++++++++++++++++++++---------- net/tipc/subscr.h | 6 ++++-- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 91fce70291a8..777b979b8463 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c @@ -418,6 +418,9 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, struct tipc_subscription *s) { struct sub_seq *sseq = nseq->sseqs; + struct tipc_name_seq ns; + + tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns); list_add(&s->nameseq_list, &nseq->subscriptions); @@ -425,7 +428,7 @@ static void tipc_nameseq_subscribe(struct name_seq *nseq, return; while (sseq != &nseq->sseqs[nseq->first_free]) { - if (tipc_subscrp_check_overlap(s, sseq->lower, sseq->upper)) { + if (tipc_subscrp_check_overlap(&ns, sseq->lower, sseq->upper)) { struct publication *crs; struct name_info *info = sseq->info; int must_report = 1; @@ -722,9 +725,10 @@ int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower, u32 ref, void tipc_nametbl_subscribe(struct tipc_subscription *s) { struct tipc_net *tn = net_generic(s->net, tipc_net_id); - u32 type = s->seq.type; + u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap); int index = hash(type); struct name_seq *seq; + struct tipc_name_seq ns; spin_lock_bh(&tn->nametbl_lock); seq = nametbl_find_seq(s->net, type); @@ -735,8 +739,9 @@ void tipc_nametbl_subscribe(struct tipc_subscription *s) tipc_nameseq_subscribe(seq, s); spin_unlock_bh(&seq->lock); } else { + tipc_subscrp_convert_seq(&s->evt.s.seq, s->swap, &ns); pr_warn("Failed to create subscription for {%u,%u,%u}\n", - s->seq.type, s->seq.lower, s->seq.upper); + ns.type, ns.lower, ns.upper); } spin_unlock_bh(&tn->nametbl_lock); } @@ -748,9 +753,10 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s) { struct tipc_net *tn = net_generic(s->net, tipc_net_id); struct name_seq *seq; + u32 type = tipc_subscrp_convert_seq_type(s->evt.s.seq.type, s->swap); spin_lock_bh(&tn->nametbl_lock); - seq = nametbl_find_seq(s->net, s->seq.type); + seq = nametbl_find_seq(s->net, type); if (seq != NULL) { spin_lock_bh(&seq->lock); list_del_init(&s->nameseq_list); diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index cef0b6b967d3..5f3100e964cf 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -92,23 +92,39 @@ static void tipc_subscrp_send_event(struct tipc_subscription *sub, * * Returns 1 if there is overlap, otherwise 0. */ -int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower, +int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower, u32 found_upper) { - if (found_lower < sub->seq.lower) - found_lower = sub->seq.lower; - if (found_upper > sub->seq.upper) - found_upper = sub->seq.upper; + if (found_lower < seq->lower) + found_lower = seq->lower; + if (found_upper > seq->upper) + found_upper = seq->upper; if (found_lower > found_upper) return 0; return 1; } +u32 tipc_subscrp_convert_seq_type(u32 type, int swap) +{ + return htohl(type, swap); +} + +void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, + struct tipc_name_seq *out) +{ + out->type = htohl(in->type, swap); + out->lower = htohl(in->lower, swap); + out->upper = htohl(in->upper, swap); +} + void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, u32 found_upper, u32 event, u32 port_ref, u32 node, int must) { - if (!tipc_subscrp_check_overlap(sub, found_lower, found_upper)) + struct tipc_name_seq seq; + + tipc_subscrp_convert_seq(&sub->evt.s.seq, sub->swap, &seq); + if (!tipc_subscrp_check_overlap(&seq, found_lower, found_upper)) return; if (!must && !(htohl(sub->evt.s.filter, sub->swap) & TIPC_SUB_PORTS)) @@ -252,12 +268,9 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, /* Initialize subscription object */ sub->net = net; - sub->seq.type = htohl(s->seq.type, swap); - sub->seq.lower = htohl(s->seq.lower, swap); - sub->seq.upper = htohl(s->seq.upper, swap); filter = htohl(s->filter, swap); if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) || - (sub->seq.lower > sub->seq.upper)) { + (htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) { pr_warn("Subscription rejected, illegal request\n"); kfree(sub); return -EINVAL; diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 9e69dbf05626..be60103082c9 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -58,7 +58,6 @@ struct tipc_subscriber; */ struct tipc_subscription { struct tipc_subscriber *subscriber; - struct tipc_name_seq seq; struct net *net; struct timer_list timer; struct list_head nameseq_list; @@ -67,11 +66,14 @@ struct tipc_subscription { struct tipc_event evt; }; -int tipc_subscrp_check_overlap(struct tipc_subscription *sub, u32 found_lower, +int tipc_subscrp_check_overlap(struct tipc_name_seq *seq, u32 found_lower, u32 found_upper); void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower, u32 found_upper, u32 event, u32 port_ref, u32 node, int must); +void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, + struct tipc_name_seq *out); +u32 tipc_subscrp_convert_seq_type(u32 type, int swap); int tipc_topsrv_start(struct net *net); void tipc_topsrv_stop(struct net *net); -- cgit From 7c13c6224123a6424bd3bc60ef982759754501e9 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:11 +0100 Subject: tipc: introduce tipc_subscrb_subscribe() routine In this commit, we split tipc_subscrp_create() into two: 1. tipc_subscrp_create() creates a subscription 2. A new function tipc_subscrp_subscribe() adds the subscription to the subscriber subscription list, activates the subscription timer and subscribes to the nametable updates. In future commits, the purpose of tipc_subscrb_rcv_cb() will be to either subscribe or cancel a subscription. There is no functional change in this commit. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 54 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 5f3100e964cf..022a2f21be04 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -233,13 +233,13 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s, spin_unlock_bh(&subscriber->lock); } -static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, - struct tipc_subscriber *subscriber, - struct tipc_subscription **sub_p) +static struct tipc_subscription *tipc_subscrp_create(struct net *net, + struct tipc_subscr *s, + struct tipc_subscriber *subscriber) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_subscription *sub; - u32 timeout, filter; + u32 filter; int swap; /* Determine subscriber's endianness */ @@ -249,21 +249,21 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); tipc_subscrp_cancel(s, subscriber); - return 0; + return NULL; } /* Refuse subscription if global limit exceeded */ if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { pr_warn("Subscription rejected, limit reached (%u)\n", TIPC_MAX_SUBSCRIPTIONS); - return -EINVAL; + return NULL; } /* Allocate subscription object */ sub = kmalloc(sizeof(*sub), GFP_ATOMIC); if (!sub) { pr_warn("Subscription rejected, no memory\n"); - return -ENOMEM; + return NULL; } /* Initialize subscription object */ @@ -273,22 +273,36 @@ static int tipc_subscrp_create(struct net *net, struct tipc_subscr *s, (htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) { pr_warn("Subscription rejected, illegal request\n"); kfree(sub); - return -EINVAL; + return NULL; } - spin_lock_bh(&subscriber->lock); - list_add(&sub->subscrp_list, &subscriber->subscrp_list); - spin_unlock_bh(&subscriber->lock); - sub->subscriber = subscriber; sub->swap = swap; memcpy(&sub->evt.s, s, sizeof(*s)); atomic_inc(&tn->subscription_count); setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); - timeout = htohl(sub->evt.s.timeout, swap); + return sub; +} + +static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, + struct tipc_subscriber *subscriber) +{ + struct tipc_net *tn = net_generic(net, tipc_net_id); + struct tipc_subscription *sub = NULL; + u32 timeout; + + sub = tipc_subscrp_create(net, s, subscriber); + if (!sub) + return tipc_conn_terminate(tn->topsrv, subscriber->conid); + + spin_lock_bh(&subscriber->lock); + list_add(&sub->subscrp_list, &subscriber->subscrp_list); + spin_unlock_bh(&subscriber->lock); + + sub->subscriber = subscriber; + timeout = htohl(sub->evt.s.timeout, sub->swap); if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) tipc_subscrb_get(subscriber); - *sub_p = sub; - return 0; + tipc_nametbl_subscribe(sub); } /* Handle one termination request for the subscriber */ @@ -302,14 +316,8 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, struct sockaddr_tipc *addr, void *usr_data, void *buf, size_t len) { - struct tipc_subscriber *subscrb = usr_data; - struct tipc_subscription *sub = NULL; - struct tipc_net *tn = net_generic(net, tipc_net_id); - - if (tipc_subscrp_create(net, (struct tipc_subscr *)buf, subscrb, &sub)) - return tipc_conn_terminate(tn->topsrv, subscrb->conid); - - tipc_nametbl_subscribe(sub); + tipc_subscrp_subscribe(net, (struct tipc_subscr *)buf, + (struct tipc_subscriber *)usr_data); } /* Handle one request to establish a new subscriber */ -- cgit From c8beccc67c833db4a01c621cbc6eb0a577286806 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:12 +0100 Subject: tipc: fix connection abort during subscription cancellation In 'commit 7fe8097cef5f ("tipc: fix nullpointer bug when subscribing to events")', we terminate the connection if the subscription creation fails. In the same commit, the subscription creation result was based on the value of subscription pointer (set in the function) instead of the return code. Unfortunately, the same function also handles subscription cancellation request. For a subscription cancellation request, the subscription pointer cannot be set. Thus the connection is terminated during cancellation request. In this commit, we move the subcription cancel check outside of tipc_subscrp_create(). Hence, - tipc_subscrp_create() will create a subscripton - tipc_subscrb_rcv_cb() will subscribe or cancel a subscription. Fixes: 'commit 7fe8097cef5f ("tipc: fix nullpointer bug when subscribing to events")' Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 022a2f21be04..531227208ae2 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -235,22 +235,11 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s, static struct tipc_subscription *tipc_subscrp_create(struct net *net, struct tipc_subscr *s, - struct tipc_subscriber *subscriber) + int swap) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_subscription *sub; - u32 filter; - int swap; - - /* Determine subscriber's endianness */ - swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); - - /* Detect & process a subscription cancellation request */ - if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { - s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); - tipc_subscrp_cancel(s, subscriber); - return NULL; - } + u32 filter = htohl(s->filter, swap); /* Refuse subscription if global limit exceeded */ if (atomic_read(&tn->subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { @@ -268,7 +257,6 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, /* Initialize subscription object */ sub->net = net; - filter = htohl(s->filter, swap); if (((filter & TIPC_SUB_PORTS) && (filter & TIPC_SUB_SERVICE)) || (htohl(s->seq.lower, swap) > htohl(s->seq.upper, swap))) { pr_warn("Subscription rejected, illegal request\n"); @@ -284,13 +272,13 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, } static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, - struct tipc_subscriber *subscriber) + struct tipc_subscriber *subscriber, int swap) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_subscription *sub = NULL; u32 timeout; - sub = tipc_subscrp_create(net, s, subscriber); + sub = tipc_subscrp_create(net, s, swap); if (!sub) return tipc_conn_terminate(tn->topsrv, subscriber->conid); @@ -299,7 +287,7 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, spin_unlock_bh(&subscriber->lock); sub->subscriber = subscriber; - timeout = htohl(sub->evt.s.timeout, sub->swap); + timeout = htohl(sub->evt.s.timeout, swap); if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) tipc_subscrb_get(subscriber); tipc_nametbl_subscribe(sub); @@ -316,8 +304,20 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, struct sockaddr_tipc *addr, void *usr_data, void *buf, size_t len) { - tipc_subscrp_subscribe(net, (struct tipc_subscr *)buf, - (struct tipc_subscriber *)usr_data); + struct tipc_subscriber *subscriber = usr_data; + struct tipc_subscr *s = (struct tipc_subscr *)buf; + int swap; + + /* Determine subscriber's endianness */ + swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); + + /* Detect & process a subscription cancellation request */ + if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { + s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); + return tipc_subscrp_cancel(s, subscriber); + } + + tipc_subscrp_subscribe(net, s, subscriber, swap); } /* Handle one request to establish a new subscriber */ -- cgit From cb01c7c8701a35866479753fe78d04bd9826dd1b Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:13 +0100 Subject: tipc: fix connection abort when receiving invalid cancel request Until now, the subscribers endianness for a subscription create/cancel request is determined as: swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)) The checks are performed only for port/service subscriptions. The swap calculation is incorrect if the filter in the subscription cancellation request is set to TIPC_SUB_CANCEL (it's a malformed cancel request, as the corresponding subscription create filter is missing). Thus, the check if the request is for cancellation fails and the request is treated as a subscription create request. The subscription creation fails as the request is illegal, which terminates this connection. In this commit we determine the endianness by including TIPC_SUB_CANCEL, which will set swap correctly and the request is processed as a cancellation request. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 531227208ae2..24d2c8128bac 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -309,7 +309,8 @@ static void tipc_subscrb_rcv_cb(struct net *net, int conid, int swap; /* Determine subscriber's endianness */ - swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); + swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE | + TIPC_SUB_CANCEL)); /* Detect & process a subscription cancellation request */ if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { -- cgit From d4091899c9bbfd6695449c6b09517ceb45bb379d Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:14 +0100 Subject: tipc: hold subscriber->lock for tipc_nametbl_subscribe() Until now, while creating a subscription the subscriber lock protects only the subscribers subscription list and not the nametable. The call to tipc_nametbl_subscribe() is outside the lock. However, at subscription timeout and cancel both the subscribers subscription list and the nametable are protected by the subscriber lock. This asymmetric locking mechanism leads to the following problem: In a SMP system, the timer can be fire on another core before the create request is complete. When the timer thread calls tipc_nametbl_unsubscribe() before create thread calls tipc_nametbl_subscribe(), we get a nullptr exception. This can be simulated by creating subscription with timeout=0 and sometimes the timeout occurs before the create request is complete. The following is the oops: [57.569661] BUG: unable to handle kernel NULL pointer dereference at (null) [57.577498] IP: [] tipc_nametbl_unsubscribe+0x8a/0x120 [tipc] [57.584820] PGD 0 [57.586834] Oops: 0002 [#1] SMP [57.685506] CPU: 14 PID: 10077 Comm: kworker/u40:1 Tainted: P OENX 3.12.48-52.27.1. 9688.1.PTF-default #1 [57.703637] Workqueue: tipc_rcv tipc_recv_work [tipc] [57.708697] task: ffff88064c7f00c0 ti: ffff880629ef4000 task.ti: ffff880629ef4000 [57.716181] RIP: 0010:[] [] tipc_nametbl_unsubscribe+0x8a/ 0x120 [tipc] [...] [57.812327] Call Trace: [57.814806] [] tipc_subscrp_delete+0x37/0x90 [tipc] [57.821357] [] tipc_subscrp_timeout+0x3f/0x70 [tipc] [57.827982] [] call_timer_fn+0x31/0x100 [57.833490] [] run_timer_softirq+0x1f9/0x2b0 [57.839414] [] __do_softirq+0xe5/0x230 [57.844827] [] call_softirq+0x1c/0x30 [57.850150] [] do_softirq+0x55/0x90 [57.855285] [] irq_exit+0x95/0xa0 [57.860290] [] smp_apic_timer_interrupt+0x45/0x60 [57.866644] [] apic_timer_interrupt+0x6d/0x80 [57.872686] [] tipc_subscrb_rcv_cb+0x2a5/0x3f0 [tipc] [57.879425] [] tipc_receive_from_sock+0x9f/0x100 [tipc] [57.886324] [] tipc_recv_work+0x26/0x60 [tipc] [57.892463] [] process_one_work+0x172/0x420 [57.898309] [] worker_thread+0x11a/0x3c0 [57.903871] [] kthread+0xb4/0xc0 [57.908751] [] ret_from_fork+0x58/0x90 In this commit, we do the following at subscription creation: 1. set the subscription's subscriber pointer before performing tipc_nametbl_subscribe(), as this value is required further in the call chain ex: by tipc_subscrp_send_event(). 2. move tipc_nametbl_subscribe() under the scope of subscriber lock Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 24d2c8128bac..e4ebbc161e42 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -284,13 +284,13 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, spin_lock_bh(&subscriber->lock); list_add(&sub->subscrp_list, &subscriber->subscrp_list); + sub->subscriber = subscriber; + tipc_nametbl_subscribe(sub); spin_unlock_bh(&subscriber->lock); - sub->subscriber = subscriber; timeout = htohl(sub->evt.s.timeout, swap); if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) tipc_subscrb_get(subscriber); - tipc_nametbl_subscribe(sub); } /* Handle one termination request for the subscriber */ -- cgit From f3ad288c56d21e3b8ec77e13ab9aa06dbbfa3577 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:15 +0100 Subject: tipc: protect tipc_subscrb_get() with subscriber spin lock Until now, during subscription creation the mod_time() & tipc_subscrb_get() are called after releasing the subscriber spin lock. In a SMP system when performing a subscription creation, if the subscription timeout occurs simultaneously (the timer is scheduled to run on another CPU) then the timer thread might decrement the subscribers refcount before the create thread increments the refcount. This can be simulated by creating subscription with timeout=0 and sometimes the timeout occurs before the create request is complete. This leads to the following message: [30.702949] BUG: spinlock bad magic on CPU#1, kworker/u8:3/87 [30.703834] general protection fault: 0000 [#1] SMP [30.704826] CPU: 1 PID: 87 Comm: kworker/u8:3 Not tainted 4.4.0-rc8+ #18 [30.704826] Workqueue: tipc_rcv tipc_recv_work [tipc] [30.704826] task: ffff88003f878600 ti: ffff88003fae0000 task.ti: ffff88003fae0000 [30.704826] RIP: 0010:[] [] spin_dump+0x5c/0xe0 [...] [30.704826] Call Trace: [30.704826] [] spin_bug+0x26/0x30 [30.704826] [] do_raw_spin_lock+0xe5/0x120 [30.704826] [] _raw_spin_lock_bh+0x19/0x20 [30.704826] [] tipc_subscrb_rcv_cb+0x1d0/0x330 [tipc] [30.704826] [] tipc_receive_from_sock+0xc1/0x150 [tipc] [30.704826] [] tipc_recv_work+0x3f/0x80 [tipc] [30.704826] [] process_one_work+0x149/0x3c0 [30.704826] [] worker_thread+0x66/0x460 [30.704826] [] ? process_one_work+0x3c0/0x3c0 [30.704826] [] ? process_one_work+0x3c0/0x3c0 [30.704826] [] kthread+0xed/0x110 [30.704826] [] ? kthread_create_on_node+0x190/0x190 [30.704826] [] ret_from_fork+0x3f/0x70 In this commit, 1. we remove the check for the return code for mod_timer() 2. we protect tipc_subscrb_get() using the subscriber spin lock. We increment the subscriber's refcount as soon as we add the subscription to subscriber's subscription list. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index e4ebbc161e42..7d226ecb0490 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -284,13 +284,13 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, spin_lock_bh(&subscriber->lock); list_add(&sub->subscrp_list, &subscriber->subscrp_list); + tipc_subscrb_get(subscriber); sub->subscriber = subscriber; tipc_nametbl_subscribe(sub); spin_unlock_bh(&subscriber->lock); timeout = htohl(sub->evt.s.timeout, swap); - if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) - tipc_subscrb_get(subscriber); + mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); } /* Handle one termination request for the subscriber */ -- cgit From ae245557f87fffe2e1c39ba07524024e650e822b Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:16 +0100 Subject: tipc: donot create timers if subscription timeout = TIPC_WAIT_FOREVER Until now, we create timers even for the subscription requests with timeout = TIPC_WAIT_FOREVER. This can be improved by avoiding timer creation when the timeout is set to TIPC_WAIT_FOREVER. In this commit, we introduce a check to creates timers only when timeout != TIPC_WAIT_FOREVER. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 7d226ecb0490..22963cafd5ed 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -188,12 +188,14 @@ static struct tipc_subscriber *tipc_subscrb_create(int conid) static void tipc_subscrb_delete(struct tipc_subscriber *subscriber) { struct tipc_subscription *sub, *temp; + u32 timeout; spin_lock_bh(&subscriber->lock); /* Destroy any existing subscriptions for subscriber */ list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, subscrp_list) { - if (del_timer(&sub->timer)) { + timeout = htohl(sub->evt.s.timeout, sub->swap); + if ((timeout == TIPC_WAIT_FOREVER) || del_timer(&sub->timer)) { tipc_subscrp_delete(sub); tipc_subscrb_put(subscriber); } @@ -217,13 +219,16 @@ static void tipc_subscrp_cancel(struct tipc_subscr *s, struct tipc_subscriber *subscriber) { struct tipc_subscription *sub, *temp; + u32 timeout; spin_lock_bh(&subscriber->lock); /* Find first matching subscription, exit if not found */ list_for_each_entry_safe(sub, temp, &subscriber->subscrp_list, subscrp_list) { if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { - if (del_timer(&sub->timer)) { + timeout = htohl(sub->evt.s.timeout, sub->swap); + if ((timeout == TIPC_WAIT_FOREVER) || + del_timer(&sub->timer)) { tipc_subscrp_delete(sub); tipc_subscrb_put(subscriber); } @@ -267,7 +272,6 @@ static struct tipc_subscription *tipc_subscrp_create(struct net *net, sub->swap = swap; memcpy(&sub->evt.s, s, sizeof(*s)); atomic_inc(&tn->subscription_count); - setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); return sub; } @@ -290,6 +294,10 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, spin_unlock_bh(&subscriber->lock); timeout = htohl(sub->evt.s.timeout, swap); + if (timeout == TIPC_WAIT_FOREVER) + return; + + setup_timer(&sub->timer, tipc_subscrp_timeout, (unsigned long)sub); mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); } -- cgit From 06c8581f85e99bbf69723f76ad2a40fa8a8c8cdd Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:17 +0100 Subject: tipc: use alloc_ordered_workqueue() instead of WQ_UNBOUND w/ max_active = 1 Until now, tipc_rcv and tipc_send workqueues in server are allocated with parameters WQ_UNBOUND & max_active = 1. This parameters passed to this function makes it equivalent to alloc_ordered_workqueue(). The later form is more explicit and can inherit future ordered_workqueue changes. In this commit we replace alloc_workqueue() with more readable alloc_ordered_workqueue(). Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tipc/server.c b/net/tipc/server.c index 922e04a43396..2446bfbaa309 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c @@ -571,13 +571,13 @@ static void tipc_work_stop(struct tipc_server *s) static int tipc_work_start(struct tipc_server *s) { - s->rcv_wq = alloc_workqueue("tipc_rcv", WQ_UNBOUND, 1); + s->rcv_wq = alloc_ordered_workqueue("tipc_rcv", 0); if (!s->rcv_wq) { pr_err("can't start tipc receive workqueue\n"); return -ENOMEM; } - s->send_wq = alloc_workqueue("tipc_send", WQ_UNBOUND, 1); + s->send_wq = alloc_ordered_workqueue("tipc_send", 0); if (!s->send_wq) { pr_err("can't start tipc send workqueue\n"); destroy_workqueue(s->rcv_wq); -- cgit From c89e2e2a0dafde7fb64dfb441a37e93a54cbb844 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 5 Feb 2016 11:32:34 +0100 Subject: staging:iio:ad7606: Consolidate channel specs By slightly reordering the channels in the channel spec array we can reuse the same array for all variant of the chip. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7606_core.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 2c9d8b7de9f5..263f981da967 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -250,7 +250,8 @@ static const struct attribute_group ad7606_attribute_group_range = { }, \ } -static const struct iio_chan_spec ad7606_8_channels[] = { +static const struct iio_chan_spec ad7606_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(8), AD7606_CHANNEL(0), AD7606_CHANNEL(1), AD7606_CHANNEL(2), @@ -259,25 +260,6 @@ static const struct iio_chan_spec ad7606_8_channels[] = { AD7606_CHANNEL(5), AD7606_CHANNEL(6), AD7606_CHANNEL(7), - IIO_CHAN_SOFT_TIMESTAMP(8), -}; - -static const struct iio_chan_spec ad7606_6_channels[] = { - AD7606_CHANNEL(0), - AD7606_CHANNEL(1), - AD7606_CHANNEL(2), - AD7606_CHANNEL(3), - AD7606_CHANNEL(4), - AD7606_CHANNEL(5), - IIO_CHAN_SOFT_TIMESTAMP(6), -}; - -static const struct iio_chan_spec ad7606_4_channels[] = { - AD7606_CHANNEL(0), - AD7606_CHANNEL(1), - AD7606_CHANNEL(2), - AD7606_CHANNEL(3), - IIO_CHAN_SOFT_TIMESTAMP(4), }; static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { @@ -287,20 +269,20 @@ static const struct ad7606_chip_info ad7606_chip_info_tbl[] = { [ID_AD7606_8] = { .name = "ad7606", .int_vref_mv = 2500, - .channels = ad7606_8_channels, - .num_channels = 8, + .channels = ad7606_channels, + .num_channels = 9, }, [ID_AD7606_6] = { .name = "ad7606-6", .int_vref_mv = 2500, - .channels = ad7606_6_channels, - .num_channels = 6, + .channels = ad7606_channels, + .num_channels = 7, }, [ID_AD7606_4] = { .name = "ad7606-4", .int_vref_mv = 2500, - .channels = ad7606_4_channels, - .num_channels = 4, + .channels = ad7606_channels, + .num_channels = 5, }, }; -- cgit From 1b3b36b044939b438c4463e8bde8cd644ba82032 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 16 Jan 2016 00:48:32 +0100 Subject: bcma: support identifying MX25L25635F serial flash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's a Macronix 32 MiB flash found on board with BCM47189 SoC. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon_sflash.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 7e11ef4cb7db..04d706ca5f43 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c @@ -38,6 +38,7 @@ static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { { "M25P32", 0x15, 0x10000, 64, }, { "M25P64", 0x16, 0x10000, 128, }, { "M25FL128", 0x17, 0x10000, 256, }, + { "MX25L25635F", 0x18, 0x10000, 512, }, { NULL }, }; -- cgit From 7267bcda332e2782e21a559f3b1b859a35b4062d Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 16 Jan 2016 00:48:52 +0100 Subject: bcma: identify bus cores (devices) found on BCM47189 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add missing defines and print proper names. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/scan.c | 3 +++ include/linux/bcma/bcma.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index df806b9c5490..5ee731132365 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -98,6 +98,9 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { { BCMA_CORE_SHIM, "SHIM" }, { BCMA_CORE_PCIE2, "PCIe Gen2" }, { BCMA_CORE_ARM_CR4, "ARM CR4" }, + { BCMA_CORE_GCI, "GCI" }, + { BCMA_CORE_CMEM, "CNDS DDR2/3 memory controller" }, + { BCMA_CORE_ARM_CA7, "ARM CA7" }, { BCMA_CORE_DEFAULT, "Default" }, }; diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 3feb1b2d75d8..991ebb4c2015 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -151,6 +151,8 @@ struct bcma_host_ops { #define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */ #define BCMA_CORE_USB30_DEV 0x83D #define BCMA_CORE_ARM_CR4 0x83E +#define BCMA_CORE_GCI 0x840 +#define BCMA_CORE_CMEM 0x846 /* CNDS DDR2/3 memory controller */ #define BCMA_CORE_ARM_CA7 0x847 #define BCMA_CORE_SYS_MEM 0x849 #define BCMA_CORE_DEFAULT 0xFFF -- cgit From 0c06f5d43e1f969bae3fa7832a94af46c75db9a7 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 16 Jan 2016 00:48:53 +0100 Subject: bcma: support chipsets with PMU and GCI cores (devices) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both cores are another exceptions. They are not accessed in a standard way and to they don't need or have wrapping addresses. This fixes bus scanning after finding such core. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/scan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 5ee731132365..4a2d1b235fb5 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -318,6 +318,8 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr, switch (core->id.id) { case BCMA_CORE_4706_MAC_GBIT_COMMON: case BCMA_CORE_NS_CHIPCOMMON_B: + case BCMA_CORE_PMU: + case BCMA_CORE_GCI: /* Not used yet: case BCMA_CORE_OOB_ROUTER: */ break; default: -- cgit From 67edf354faaf93156646e741483b2313bc756c0f Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Jan 2016 08:45:25 +0100 Subject: bcma: use _PMU_ in all names of PMU registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PMU (Power Management Unit) seems to be a separated piece of hardware, just accessed using ChipCommon core registers. In recent Broadcom chipsets PMU is not bounded to CC but available as separated core. To make code cleaner & easier to review (for a correct R/W access) use clearer names. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon_pmu.c | 46 ++++++++++++++--------------- drivers/net/wireless/broadcom/b43/main.c | 8 ++--- include/linux/bcma/bcma_driver_chipcommon.h | 12 ++++---- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index fe0d48cb1778..472f39dc5a38 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -15,44 +15,44 @@ u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); - return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + return bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_cc_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set); + bcma_cc_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); + bcma_cc_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set); + bcma_cc_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); + bcma_cc_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); + bcma_cc_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); @@ -472,8 +472,8 @@ u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) @@ -497,20 +497,20 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; /* RMW only the P1 divider */ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL0 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); + tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); /* RMW only the int feedback divider */ - bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL2 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA); + tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; - bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp); + bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); tmp = BCMA_CC_PMU_CTL_PLL_UPD; break; diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c index ec013fbd6a81..c279211e49f9 100644 --- a/drivers/net/wireless/broadcom/b43/main.c +++ b/drivers/net/wireless/broadcom/b43/main.c @@ -1215,10 +1215,10 @@ void b43_wireless_core_phy_pll_reset(struct b43_wldev *dev) case B43_BUS_BCMA: bcma_cc = &dev->dev->bdev->bus->drv_cc; - bcma_cc_write32(bcma_cc, BCMA_CC_CHIPCTL_ADDR, 0); - bcma_cc_mask32(bcma_cc, BCMA_CC_CHIPCTL_DATA, ~0x4); - bcma_cc_set32(bcma_cc, BCMA_CC_CHIPCTL_DATA, 0x4); - bcma_cc_mask32(bcma_cc, BCMA_CC_CHIPCTL_DATA, ~0x4); + bcma_cc_write32(bcma_cc, BCMA_CC_PMU_CHIPCTL_ADDR, 0); + bcma_cc_mask32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, ~0x4); + bcma_cc_set32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, 0x4); + bcma_cc_mask32(bcma_cc, BCMA_CC_PMU_CHIPCTL_DATA, ~0x4); break; #endif #ifdef CONFIG_B43_SSB diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index db51a6ffb7d6..96d8d56f240f 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -351,12 +351,12 @@ #define BCMA_CC_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ #define BCMA_CC_PMU_RES_REQT 0x0644 /* PMU res req timer */ #define BCMA_CC_PMU_RES_REQM 0x0648 /* PMU res req mask */ -#define BCMA_CC_CHIPCTL_ADDR 0x0650 -#define BCMA_CC_CHIPCTL_DATA 0x0654 -#define BCMA_CC_REGCTL_ADDR 0x0658 -#define BCMA_CC_REGCTL_DATA 0x065C -#define BCMA_CC_PLLCTL_ADDR 0x0660 -#define BCMA_CC_PLLCTL_DATA 0x0664 +#define BCMA_CC_PMU_CHIPCTL_ADDR 0x0650 +#define BCMA_CC_PMU_CHIPCTL_DATA 0x0654 +#define BCMA_CC_PMU_REGCTL_ADDR 0x0658 +#define BCMA_CC_PMU_REGCTL_DATA 0x065C +#define BCMA_CC_PMU_PLLCTL_ADDR 0x0660 +#define BCMA_CC_PMU_PLLCTL_DATA 0x0664 #define BCMA_CC_PMU_STRAPOPT 0x0668 /* (corerev >= 28) */ #define BCMA_CC_PMU_XTAL_FREQ 0x066C /* (pmurev >= 10) */ #define BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK 0x00001FFF -- cgit From b3c47afbf54d86daa0473895e8ca9e8b663f5c1a Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 19 Jan 2016 08:45:26 +0100 Subject: bcma: support PMU present as separated bus core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On recent Broadcom chipsets PMU is present as separated core and it can't be accessed using ChipCommon anymore as it fails with e.g.: [ 0.000577] Unhandled fault: external abort on non-linefetch (0x1008) at 0xf1000604 Solve it by using a new (PMU) core pointer set to ChipCommon or PMU depending on the hardware capabilities. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon.c | 2 +- drivers/bcma/driver_chipcommon_pmu.c | 94 ++++++++++++++++------------- include/linux/bcma/bcma_driver_chipcommon.h | 19 ++++++ 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index b7c8a8d4e6d1..36ee221e298f 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -185,7 +185,7 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) ticks = 2; else if (ticks > maxt) ticks = maxt; - bcma_cc_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); + bcma_pmu_write32(cc, BCMA_CC_PMU_WATCHDOG, ticks); } else { struct bcma_bus *bus = cc->core->bus; diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 472f39dc5a38..f1eb4d3e1d57 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -15,44 +15,44 @@ u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); - return bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + return bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_read); void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_write); void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_ADDR); + bcma_pmu_maskset32(cc, BCMA_CC_PMU_PLLCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset); void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); + bcma_pmu_write32(cc, BCMA_CC_PMU_CHIPCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_CHIPCTL_ADDR); + bcma_pmu_maskset32(cc, BCMA_CC_PMU_CHIPCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset); void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask, u32 set) { - bcma_cc_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); - bcma_cc_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); - bcma_cc_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); + bcma_pmu_write32(cc, BCMA_CC_PMU_REGCTL_ADDR, offset); + bcma_pmu_read32(cc, BCMA_CC_PMU_REGCTL_ADDR); + bcma_pmu_maskset32(cc, BCMA_CC_PMU_REGCTL_DATA, mask, set); } EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset); @@ -60,18 +60,18 @@ static u32 bcma_pmu_xtalfreq(struct bcma_drv_cc *cc) { u32 ilp_ctl, alp_hz; - if (!(bcma_cc_read32(cc, BCMA_CC_PMU_STAT) & + if (!(bcma_pmu_read32(cc, BCMA_CC_PMU_STAT) & BCMA_CC_PMU_STAT_EXT_LPO_AVAIL)) return 0; - bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, - BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); + bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, + BIT(BCMA_CC_PMU_XTAL_FREQ_MEASURE_SHIFT)); usleep_range(1000, 2000); - ilp_ctl = bcma_cc_read32(cc, BCMA_CC_PMU_XTAL_FREQ); + ilp_ctl = bcma_pmu_read32(cc, BCMA_CC_PMU_XTAL_FREQ); ilp_ctl &= BCMA_CC_PMU_XTAL_FREQ_ILPCTL_MASK; - bcma_cc_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); + bcma_pmu_write32(cc, BCMA_CC_PMU_XTAL_FREQ, 0); alp_hz = ilp_ctl * 32768 / 4; return (alp_hz + 50000) / 100000 * 100; @@ -127,8 +127,8 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) mask = (u32)~(BCMA_RES_4314_HT_AVAIL | BCMA_RES_4314_MACPHY_CLK_AVAIL); - bcma_cc_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); - bcma_cc_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); + bcma_pmu_mask32(cc, BCMA_CC_PMU_MINRES_MSK, mask); + bcma_pmu_mask32(cc, BCMA_CC_PMU_MAXRES_MSK, mask); bcma_wait_value(cc->core, BCMA_CLKCTLST, BCMA_CLKCTLST_HAVEHT, 0, 20000); break; @@ -140,7 +140,7 @@ static void bcma_pmu2_pll_init0(struct bcma_drv_cc *cc, u32 xtalfreq) /* Flush */ if (cc->pmu.rev >= 2) - bcma_cc_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, BCMA_CC_PMU_CTL_PLL_UPD); /* TODO: Do we need to update OTP? */ } @@ -195,9 +195,9 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) /* Set the resource masks. */ if (min_msk) - bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); + bcma_pmu_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); if (max_msk) - bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); + bcma_pmu_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); /* * Add some delay; allow resources to come up and settle. @@ -269,23 +269,33 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) void bcma_pmu_early_init(struct bcma_drv_cc *cc) { + struct bcma_bus *bus = cc->core->bus; u32 pmucap; - pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); + if (cc->core->id.rev >= 35 && + cc->capabilities_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { + cc->pmu.core = bcma_find_core(bus, BCMA_CORE_PMU); + if (!cc->pmu.core) + bcma_warn(bus, "Couldn't find expected PMU core"); + } + if (!cc->pmu.core) + cc->pmu.core = cc->core; + + pmucap = bcma_pmu_read32(cc, BCMA_CC_PMU_CAP); cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); - bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", - cc->pmu.rev, pmucap); + bcma_debug(bus, "Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, + pmucap); } void bcma_pmu_init(struct bcma_drv_cc *cc) { if (cc->pmu.rev == 1) - bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, - ~BCMA_CC_PMU_CTL_NOILPONW); + bcma_pmu_mask32(cc, BCMA_CC_PMU_CTL, + ~BCMA_CC_PMU_CTL_NOILPONW); else - bcma_cc_set32(cc, BCMA_CC_PMU_CTL, - BCMA_CC_PMU_CTL_NOILPONW); + bcma_pmu_set32(cc, BCMA_CC_PMU_CTL, + BCMA_CC_PMU_CTL_NOILPONW); bcma_pmu_pll_init(cc); bcma_pmu_resources_init(cc); @@ -472,8 +482,8 @@ u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc) static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value) { - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, offset); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, value); } void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) @@ -497,20 +507,20 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0; /* RMW only the P1 divider */ - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL0 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); + tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK)); tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT); - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); /* RMW only the int feedback divider */ - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_ADDR, BCMA_CC_PMU_PLL_CTL2 + phypll_offset); - tmp = bcma_cc_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); + tmp = bcma_pmu_read32(cc, BCMA_CC_PMU_PLLCTL_DATA); tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK); tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT; - bcma_cc_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); + bcma_pmu_write32(cc, BCMA_CC_PMU_PLLCTL_DATA, tmp); tmp = BCMA_CC_PMU_CTL_PLL_UPD; break; @@ -646,7 +656,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) break; } - tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL); - bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp); + tmp |= bcma_pmu_read32(cc, BCMA_CC_PMU_CTL); + bcma_pmu_write32(cc, BCMA_CC_PMU_CTL, tmp); } EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate); diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 96d8d56f240f..700d0c6f7480 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -217,6 +217,11 @@ #define BCMA_CC_CLKDIV_JTAG_SHIFT 8 #define BCMA_CC_CLKDIV_UART 0x000000FF #define BCMA_CC_CAP_EXT 0x00AC /* Capabilities */ +#define BCMA_CC_CAP_EXT_SECI_PRESENT 0x00000001 +#define BCMA_CC_CAP_EXT_GSIO_PRESENT 0x00000002 +#define BCMA_CC_CAP_EXT_GCI_PRESENT 0x00000004 +#define BCMA_CC_CAP_EXT_SECI_PUART_PRESENT 0x00000008 /* UART present */ +#define BCMA_CC_CAP_EXT_AOB_PRESENT 0x00000040 #define BCMA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */ #define BCMA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */ #define BCMA_CC_SLOWCLKCTL 0x00B8 /* 6 <= Rev <= 9 only */ @@ -566,6 +571,7 @@ * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ struct bcma_chipcommon_pmu { + struct bcma_device *core; /* Can be separated core or just ChipCommon one */ u8 rev; /* PMU revision */ u32 crystalfreq; /* The active crystal frequency (in kHz) */ }; @@ -660,6 +666,19 @@ struct bcma_drv_cc_b { #define bcma_cc_maskset32(cc, offset, mask, set) \ bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) +/* PMU registers access */ +#define bcma_pmu_read32(cc, offset) \ + bcma_read32((cc)->pmu.core, offset) +#define bcma_pmu_write32(cc, offset, val) \ + bcma_write32((cc)->pmu.core, offset, val) + +#define bcma_pmu_mask32(cc, offset, mask) \ + bcma_pmu_write32(cc, offset, bcma_pmu_read32(cc, offset) & (mask)) +#define bcma_pmu_set32(cc, offset, set) \ + bcma_pmu_write32(cc, offset, bcma_pmu_read32(cc, offset) | (set)) +#define bcma_pmu_maskset32(cc, offset, mask, set) \ + bcma_pmu_write32(cc, offset, (bcma_pmu_read32(cc, offset) & (mask)) | (set)) + extern u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks); extern u32 bcma_chipco_get_alp_clock(struct bcma_drv_cc *cc); -- cgit From 36e8072ebeb1981074c7ec1b63bae3ecc3295b4b Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Wed, 20 Jan 2016 16:46:04 +0100 Subject: brcmfmac: fix setting primary channel for 80 MHz width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First of all it changes the way we calculate primary channel offset. If we use e.g. 80 MHz channel with primary frequency 5180 MHz (which means center frequency is 5210 MHz) it makes sense to calculate primary offset as -30 MHz. Then it fixes values we compare primary_offset with. We were comparing offset in MHz against -2 or 2 which was resulting in picking a wrong primary channel. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 23 ++++++++++------------ 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 7b01e4ddb315..d00c5c1d58bf 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -247,7 +247,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n", ch->chan->center_freq, ch->center_freq1, ch->width); ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1); - primary_offset = ch->center_freq1 - ch->chan->center_freq; + primary_offset = ch->chan->center_freq - ch->center_freq1; switch (ch->width) { case NL80211_CHAN_WIDTH_20: case NL80211_CHAN_WIDTH_20_NOHT: @@ -256,24 +256,21 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, break; case NL80211_CHAN_WIDTH_40: ch_inf.bw = BRCMU_CHAN_BW_40; - if (primary_offset < 0) + if (primary_offset > 0) ch_inf.sb = BRCMU_CHAN_SB_U; else ch_inf.sb = BRCMU_CHAN_SB_L; break; case NL80211_CHAN_WIDTH_80: ch_inf.bw = BRCMU_CHAN_BW_80; - if (primary_offset < 0) { - if (primary_offset < -CH_10MHZ_APART) - ch_inf.sb = BRCMU_CHAN_SB_UU; - else - ch_inf.sb = BRCMU_CHAN_SB_UL; - } else { - if (primary_offset > CH_10MHZ_APART) - ch_inf.sb = BRCMU_CHAN_SB_LL; - else - ch_inf.sb = BRCMU_CHAN_SB_LU; - } + if (primary_offset == -30) + ch_inf.sb = BRCMU_CHAN_SB_LL; + else if (primary_offset == -10) + ch_inf.sb = BRCMU_CHAN_SB_LU; + else if (primary_offset == 10) + ch_inf.sb = BRCMU_CHAN_SB_UL; + else + ch_inf.sb = BRCMU_CHAN_SB_UU; break; case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: -- cgit From 4c81acab3816c6941900c2abdb412df6cf34bc74 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Fri, 22 Jan 2016 18:02:54 +0100 Subject: bcma: init serial console directly from ChipCommon code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UART is connected to and controlled over ChipCommon core. It doesn't have much to do with MIPS core (where we initialize it currently) except just existing on embedded systemms. There isn't point of such cross-core initialization (and we needed #ifdef anyway) so just handle it in ChipCommon. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/bcma_private.h | 1 - drivers/bcma/driver_chipcommon.c | 13 ++++++++++--- drivers/bcma/driver_mips.c | 3 --- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 38f156745d53..7e4ddfb076d3 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -48,7 +48,6 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); #ifdef CONFIG_BCMA_DRIVER_MIPS -void bcma_chipco_serial_init(struct bcma_drv_cc *cc); extern struct platform_device bcma_pflash_dev; #endif /* CONFIG_BCMA_DRIVER_MIPS */ diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index 36ee221e298f..bdb73d97da63 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -15,6 +15,8 @@ #include #include +static void bcma_chipco_serial_init(struct bcma_drv_cc *cc); + static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, u32 mask, u32 value) { @@ -115,6 +117,8 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc) void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) { + struct bcma_bus *bus = cc->core->bus; + if (cc->early_setup_done) return; @@ -129,6 +133,9 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) if (cc->capabilities & BCMA_CC_CAP_PMU) bcma_pmu_early_init(cc); + if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC) + bcma_chipco_serial_init(cc); + cc->early_setup_done = true; } @@ -314,9 +321,9 @@ u32 bcma_chipco_gpio_pulldown(struct bcma_drv_cc *cc, u32 mask, u32 value) return res; } -#ifdef CONFIG_BCMA_DRIVER_MIPS -void bcma_chipco_serial_init(struct bcma_drv_cc *cc) +static void bcma_chipco_serial_init(struct bcma_drv_cc *cc) { +#if IS_BUILTIN(CONFIG_BCM47XX) unsigned int irq; u32 baud_base; u32 i; @@ -358,5 +365,5 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc) ports[i].baud_base = baud_base; ports[i].reg_shift = 0; } +#endif /* CONFIG_BCM47XX */ } -#endif /* CONFIG_BCMA_DRIVER_MIPS */ diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index 24424f3fef96..a40a203314db 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c @@ -337,12 +337,9 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { - struct bcma_bus *bus = mcore->core->bus; - if (mcore->early_setup_done) return; - bcma_chipco_serial_init(&bus->drv_cc); bcma_core_mips_flash_detect(mcore); mcore->early_setup_done = true; -- cgit From 61dba73cdbba8ec5c01b31beaf9e2debc2d2f273 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 24 Jan 2016 16:37:33 +0100 Subject: bcma: add support for BCM47094 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's another SoC with 32 GPIOs and simplified watchdog handling. It was tested on D-Link DIR-885L. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/driver_chipcommon.c | 1 + drivers/bcma/driver_gpio.c | 1 + include/linux/bcma/bcma.h | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index bdb73d97da63..b0f44a2937b9 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c @@ -197,6 +197,7 @@ u32 bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) struct bcma_bus *bus = cc->core->bus; if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4707 && + bus->chipinfo.id != BCMA_CHIP_ID_BCM47094 && bus->chipinfo.id != BCMA_CHIP_ID_BCM53018) bcma_core_set_clockmode(cc->core, ticks ? BCMA_CLKMODE_FAST : BCMA_CLKMODE_DYNAMIC); diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 504899a72966..77b0738fbe1b 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -197,6 +197,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) case BCMA_CHIP_ID_BCM4707: case BCMA_CHIP_ID_BCM5357: case BCMA_CHIP_ID_BCM53572: + case BCMA_CHIP_ID_BCM47094: chip->ngpio = 32; break; default: diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 991ebb4c2015..0367c63f5960 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -201,6 +201,7 @@ struct bcma_host_ops { #define BCMA_PKG_ID_BCM4707 1 #define BCMA_PKG_ID_BCM4708 2 #define BCMA_PKG_ID_BCM4709 0 +#define BCMA_CHIP_ID_BCM47094 53030 #define BCMA_CHIP_ID_BCM53018 53018 /* Board types (on PCI usually equals to the subsystem dev id) */ -- cgit From 515b399c9a204da70d54916d23c1748ff7083fb8 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:02:09 +0100 Subject: bcma: claim only 14e4:4365 PCI Dell card with SoftMAC BCM43142 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems 14e4:4365 pattern is too generic as there are two devices: 1) 14e4:4365 1028:0016 with SoftMAC BCM43142 chipset 2) 14e4:4365 14e4:4365 with FullMAC BCM4366 chipset The later one was found in D-Link DIR-885L router and we want to let brcmfmac handle it. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/bcma/host_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 0856189c065f..cae5385cf499 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -294,7 +294,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) }, -- cgit From a4f4abd037c1f8c6a834c95a46a2514d4b350888 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:01 +0100 Subject: brcmfmac: analyze descriptors of current component only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far we were looking for address descriptors without a check for crossing current component border. In case of dealing with unsupported descriptor or descriptor missing at all the code would incorrectly get data from another component. Consider this binary-described component from BCM4366 EROM: 4bf83b01 TAG==CI CID==0x83b 20080201 TAG==CI PORTS==0+1 WRAPPERS==0+1 18400035 TAG==ADDR SZ_SZD TYPE_SLAVE 00050000 18107085 TAG==ADDR SZ_4K TYPE_SWRAP Driver was assigning invalid base address to this core: brcmfmac: [6 ] core 0x83b:32 base 0x18109000 wrap 0x18107000 which came from totally different component defined in EROM: 43b36701 TAG==CI CID==0x367 00000201 TAG==CI PORTS==0+1 WRAPPERS==0+0 18109005 TAG==ADDR SZ_4K TYPE_SLAVE This change will also allow us to support components without wrapper address in the future. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 82e4382eb177..e434e2a52098 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -803,7 +803,14 @@ static int brcmf_chip_dmp_get_regaddr(struct brcmf_chip_priv *ci, u32 *eromaddr, *eromaddr -= 4; return -EFAULT; } - } while (desc != DMP_DESC_ADDRESS); + } while (desc != DMP_DESC_ADDRESS && + desc != DMP_DESC_COMPONENT); + + /* stop if we crossed current component border */ + if (desc == DMP_DESC_COMPONENT) { + *eromaddr -= 4; + return 0; + } /* skip upper 32-bit address descriptor */ if (val & DMP_DESC_ADDRSIZE_GT32) -- cgit From 44977b81823f4801d45d61fb9b278b4483923ae1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:02 +0100 Subject: brcmfmac: allow storing PMU core without wrapper address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separated PMU core can be found in new devices and should be used for accessing PMU registers (which were routed through ChipCommon so far). This core is one of exceptions that doesn't have or need wrapper address to be still safely accessible. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index e434e2a52098..55952d43dfb5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -883,7 +883,8 @@ int brcmf_chip_dmp_erom_scan(struct brcmf_chip_priv *ci) rev = (val & DMP_COMP_REVISION) >> DMP_COMP_REVISION_S; /* need core with ports */ - if (nmw + nsw == 0) + if (nmw + nsw == 0 && + id != BCMA_CORE_PMU) continue; /* try to obtain register address info */ -- cgit From 9befe9195a17856f8bf5ede7a5c067bd0a281be6 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:03 +0100 Subject: brcmfmac: read extended capabilities of ChipCommon core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an extra bitfield with info about some present hardware. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 3 +++ drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 55952d43dfb5..f4a4d00cb4a2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1025,6 +1025,9 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) /* get chipcommon capabilites */ pub->cc_caps = chip->ops->read32(chip->ctx, CORE_CC_REG(base, capabilities)); + pub->cc_caps_ext = chip->ops->read32(chip->ctx, + CORE_CC_REG(base, + capabilities_ext)); /* get pmu caps & rev */ if (pub->cc_caps & CC_CAP_PMU) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index f6b5feea23d2..cb9145f1786a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -27,6 +27,7 @@ * @chip: chip identifier. * @chiprev: chip revision. * @cc_caps: chipcommon core capabilities. + * @cc_caps_ext: chipcommon core extended capabilities. * @pmucaps: PMU capabilities. * @pmurev: PMU revision. * @rambase: RAM base address (only applicable for ARM CR4 chips). @@ -38,6 +39,7 @@ struct brcmf_chip { u32 chip; u32 chiprev; u32 cc_caps; + u32 cc_caps_ext; u32 pmucaps; u32 pmurev; u32 rambase; -- cgit From e2b397f18cc6423c2dad87f9a633add762d869dd Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:04 +0100 Subject: brcmfmac: access PMU registers using standalone PMU core if available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On recent Broadcom chipsets PMU is present as separated core and it can't be accessed using ChipCommon anymore as it fails with e.g.: [ 18.198412] Unhandled fault: imprecise external abort (0x1406) at 0xb6da200f Add a new helper function that will return a proper core that should be used for accessing PMU registers. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 30 ++++++++++++++++++---- .../wireless/broadcom/brcm80211/brcmfmac/chip.h | 1 + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 9 +++---- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index f4a4d00cb4a2..0e8f2a079907 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1014,6 +1014,7 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) { struct brcmf_chip *pub; struct brcmf_core_priv *cc; + struct brcmf_core *pmu; u32 base; u32 val; int ret = 0; @@ -1030,9 +1031,10 @@ static int brcmf_chip_setup(struct brcmf_chip_priv *chip) capabilities_ext)); /* get pmu caps & rev */ + pmu = brcmf_chip_get_pmu(pub); /* after reading cc_caps_ext */ if (pub->cc_caps & CC_CAP_PMU) { val = chip->ops->read32(chip->ctx, - CORE_CC_REG(base, pmucapabilities)); + CORE_CC_REG(pmu->base, pmucapabilities)); pub->pmurev = val & PCAP_REV_MASK; pub->pmucaps = val; } @@ -1131,6 +1133,23 @@ struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *pub) return &cc->pub; } +struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub) +{ + struct brcmf_core *cc = brcmf_chip_get_chipcommon(pub); + struct brcmf_core *pmu; + + /* See if there is separated PMU core available */ + if (cc->rev >= 35 && + pub->cc_caps_ext & BCMA_CC_CAP_EXT_AOB_PRESENT) { + pmu = brcmf_chip_get_core(pub, BCMA_CORE_PMU); + if (pmu) + return pmu; + } + + /* Fallback to ChipCommon core for older hardware */ + return cc; +} + bool brcmf_chip_iscoreup(struct brcmf_core *pub) { struct brcmf_core_priv *core; @@ -1301,6 +1320,7 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) { u32 base, addr, reg, pmu_cc3_mask = ~0; struct brcmf_chip_priv *chip; + struct brcmf_core *pmu = brcmf_chip_get_pmu(pub); brcmf_dbg(TRACE, "Enter\n"); @@ -1320,9 +1340,9 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) case BRCM_CC_4335_CHIP_ID: case BRCM_CC_4339_CHIP_ID: /* read PMU chipcontrol register 3 */ - addr = CORE_CC_REG(base, chipcontrol_addr); + addr = CORE_CC_REG(pmu->base, chipcontrol_addr); chip->ops->write32(chip->ctx, addr, 3); - addr = CORE_CC_REG(base, chipcontrol_data); + addr = CORE_CC_REG(pmu->base, chipcontrol_data); reg = chip->ops->read32(chip->ctx, addr); return (reg & pmu_cc3_mask) != 0; case BRCM_CC_43430_CHIP_ID: @@ -1330,12 +1350,12 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) reg = chip->ops->read32(chip->ctx, addr); return reg != 0; default: - addr = CORE_CC_REG(base, pmucapabilities_ext); + addr = CORE_CC_REG(pmu->base, pmucapabilities_ext); reg = chip->ops->read32(chip->ctx, addr); if ((reg & PCAPEXT_SR_SUPPORTED_MASK) == 0) return false; - addr = CORE_CC_REG(base, retention_ctl); + addr = CORE_CC_REG(pmu->base, retention_ctl); reg = chip->ops->read32(chip->ctx, addr); return (reg & (PMU_RCTL_MACPHY_DISABLE_MASK | PMU_RCTL_LOGIC_DISABLE_MASK)) == 0; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index cb9145f1786a..dd0ec3eba6a9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -85,6 +85,7 @@ struct brcmf_chip *brcmf_chip_attach(void *ctx, void brcmf_chip_detach(struct brcmf_chip *chip); struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid); struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip); +struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub); bool brcmf_chip_iscoreup(struct brcmf_core *core); void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index dd6614332836..80b5d4784645 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3615,7 +3615,6 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, const struct sdiod_drive_str *str_tab = NULL; u32 str_mask; u32 str_shift; - u32 base; u32 i; u32 drivestrength_sel = 0; u32 cc_data_temp; @@ -3658,14 +3657,15 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, } if (str_tab != NULL) { + struct brcmf_core *pmu = brcmf_chip_get_pmu(ci); + for (i = 0; str_tab[i].strength != 0; i++) { if (drivestrength >= str_tab[i].strength) { drivestrength_sel = str_tab[i].sel; break; } } - base = brcmf_chip_get_chipcommon(ci)->base; - addr = CORE_CC_REG(base, chipcontrol_addr); + addr = CORE_CC_REG(pmu->base, chipcontrol_addr); brcmf_sdiod_regwl(sdiodev, addr, 1, NULL); cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL); cc_data_temp &= ~str_mask; @@ -3835,8 +3835,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus) goto fail; /* set PMUControl so a backplane reset does PMU state reload */ - reg_addr = CORE_CC_REG(brcmf_chip_get_chipcommon(bus->ci)->base, - pmucontrol); + reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol); reg_val = brcmf_sdiod_regrl(bus->sdiodev, reg_addr, &err); if (err) goto fail; -- cgit From f66ab2a7da8ffd78ba26048f8108577ba73a1828 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Tue, 26 Jan 2016 17:57:05 +0100 Subject: brcmfmac: add support for 14e4:4365 PCI ID with BCM4366 chipset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Broadcom ARM routers BCM4366 cards are available with 14e4:4365 ID. Unfortunately this ID was already used by Broadcom for cards with BCM43142, a totally different chipset requiring SoftMAC driver. To avoid a conflict between brcmfmac and bcma use more specific ID entry with subvendor and subdevice specified. Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 0480b70e3eb8..d5f9ef470447 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1951,6 +1951,9 @@ static const struct dev_pm_ops brcmf_pciedrvr_pm = { #define BRCMF_PCIE_DEVICE(dev_id) { BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\ PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } +#define BRCMF_PCIE_DEVICE_SUB(dev_id, subvend, subdev) { \ + BRCM_PCIE_VENDOR_ID_BROADCOM, dev_id,\ + subvend, subdev, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4350_DEVICE_ID), @@ -1966,6 +1969,7 @@ static struct pci_device_id brcmf_pcie_devid_table[] = { BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4365_5G_DEVICE_ID), + BRCMF_PCIE_DEVICE_SUB(0x4365, BRCM_PCIE_VENDOR_ID_BROADCOM, 0x4365), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), -- cgit From d1e61b86a2b1b99e5dcd4d41aa23d033b83542a1 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sun, 31 Jan 2016 12:14:34 +0100 Subject: brcmfmac: treat NULL character in NVRAM as separator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Platform NVRAM (stored on a flash partition) has entries separated by a NULL (\0) char. Our parsing code switches from VALUE state to IDLE whenever it meets a NULL (\0). When that happens our IDLE handler should simply consume it and analyze whatever is placed ahead. This fixes harmless warnings spamming debugging output: [ 155.165624] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=20: ignoring invalid character [ 155.180806] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=44: ignoring invalid character [ 155.195971] brcmfmac: brcmf_nvram_handle_idle warning: ln=1:col=63: ignoring invalid character Signed-off-by: Rafał Miłecki Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 1365c12b78fc..7269056d0044 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -93,7 +93,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp) c = nvp->data[nvp->pos]; if (c == '\n') return COMMENT; - if (is_whitespace(c)) + if (is_whitespace(c) || c == '\0') goto proceed; if (c == '#') return COMMENT; -- cgit From 97f1a17109272b9f060cbd6d1d5be41528643000 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Mon, 25 Jan 2016 11:47:29 +0100 Subject: brcmfmac: sdio: Increase the default timeouts a bit On a Radxa Rock2 board with a Ampak AP6335 (Broadcom 4339 core) it seems the card responds very quickly most of the time, unfortunately during initialisation it sometimes seems to take just a bit over 2 seconds to respond. This results intialization failing with message like: brcmf_c_preinit_dcmds: Retreiving cur_etheraddr failed, -52 brcmf_bus_start: failed: -52 brcmf_sdio_firmware_callback: dongle is not responding Increasing the timeout to allow for a bit more headroom allows the card to initialize reliably. A quick search online after diagnosing/fixing this showed that Google has a similar patch in their ChromeOS tree, so this doesn't seem specific to the board I'm using. Signed-off-by: Sjoerd Simons Reviewed-by: Julian Calaby Acked-by: Arend van Spriel Reviewed-by: Douglas Anderson Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 80b5d4784645..6776e45b2958 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -45,8 +45,8 @@ #include "chip.h" #include "firmware.h" -#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2000) -#define CTL_DONE_TIMEOUT msecs_to_jiffies(2000) +#define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) +#define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) #ifdef DEBUG -- cgit From 48dc5fb3ba53b20418de8514700f63d88c5de3a3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 28 Jan 2016 22:58:28 +0100 Subject: hostap: avoid uninitialized variable use in hfa384x_get_rid The driver reads a value from hfa384x_from_bap(), which may fail, and then assigns the value to a local variable. gcc detects that in in the failure case, the 'rlen' variable now contains uninitialized data: In file included from ../drivers/net/wireless/intersil/hostap/hostap_pci.c:220:0: drivers/net/wireless/intersil/hostap/hostap_hw.c: In function 'hfa384x_get_rid': drivers/net/wireless/intersil/hostap/hostap_hw.c:842:5: warning: 'rec' may be used uninitialized in this function [-Wmaybe-uninitialized] if (le16_to_cpu(rec.len) == 0) { This restructures the function as suggested by Russell King, to make it more readable and get more reliable error handling, by handling each failure mode using a goto. Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo --- drivers/net/wireless/intersil/hostap/hostap_hw.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intersil/hostap/hostap_hw.c b/drivers/net/wireless/intersil/hostap/hostap_hw.c index 6df3ee561d52..515aa3f993f3 100644 --- a/drivers/net/wireless/intersil/hostap/hostap_hw.c +++ b/drivers/net/wireless/intersil/hostap/hostap_hw.c @@ -836,25 +836,30 @@ static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len, spin_lock_bh(&local->baplock); res = hfa384x_setup_bap(dev, BAP0, rid, 0); - if (!res) - res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); + if (res) + goto unlock; + + res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); + if (res) + goto unlock; if (le16_to_cpu(rec.len) == 0) { /* RID not available */ res = -ENODATA; + goto unlock; } rlen = (le16_to_cpu(rec.len) - 1) * 2; - if (!res && exact_len && rlen != len) { + if (exact_len && rlen != len) { printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: " "rid=0x%04x, len=%d (expected %d)\n", dev->name, rid, rlen, len); res = -ENODATA; } - if (!res) - res = hfa384x_from_bap(dev, BAP0, buf, len); + res = hfa384x_from_bap(dev, BAP0, buf, len); +unlock: spin_unlock_bh(&local->baplock); mutex_unlock(&local->rid_bap_mtx); -- cgit From 44ca509cb9769f27ad8f7d662910e31329eed46f Mon Sep 17 00:00:00 2001 From: Nachiket Kukade Date: Sun, 31 Jan 2016 23:44:46 -0800 Subject: mwifiex: fix bandwidth display problem Instead of using HT info from beacon IEs, use HT info from association response frame to update bandwidth in cfg80211_get_channel handler. Signed-off-by: Nachiket Kukade Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 4 ++-- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- drivers/net/wireless/marvell/mwifiex/join.c | 15 +++++++++++++++ drivers/net/wireless/marvell/mwifiex/main.h | 2 ++ drivers/net/wireless/marvell/mwifiex/sta_event.c | 3 +++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 84615533986c..f2dce81ba36e 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -3793,8 +3793,8 @@ static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, freq = ieee80211_channel_to_frequency(curr_bss->channel, band); chan = ieee80211_get_channel(wiphy, freq); - if (curr_bss->bcn_ht_oper) { - second_chan_offset = curr_bss->bcn_ht_oper->ht_param & + if (priv->ht_param_present) { + second_chan_offset = priv->assoc_resp_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; chan_type = mwifiex_sec_chan_offset_to_chan_type (second_chan_offset); diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 4af916817bcd..c134cf865291 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1063,7 +1063,7 @@ struct ieee_types_assoc_rsp { __le16 cap_info_bitmap; __le16 status_code; __le16 a_id; - u8 ie_buffer[1]; + u8 ie_buffer[0]; } __packed; struct host_cmd_ds_802_11_associate_rsp { diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c index cc09a81dbf6a..62211fca91b7 100644 --- a/drivers/net/wireless/marvell/mwifiex/join.c +++ b/drivers/net/wireless/marvell/mwifiex/join.c @@ -644,6 +644,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc; bool enable_data = true; u16 cap_info, status_code, aid; + const u8 *ie_ptr; + struct ieee80211_ht_operation *assoc_resp_ht_oper; assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; @@ -733,6 +735,19 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, = ((bss_desc->wmm_ie.qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); + /* Store the bandwidth information from assoc response */ + ie_ptr = cfg80211_find_ie(WLAN_EID_HT_OPERATION, assoc_rsp->ie_buffer, + priv->assoc_rsp_size + - sizeof(struct ieee_types_assoc_rsp)); + if (ie_ptr) { + assoc_resp_ht_oper = (struct ieee80211_ht_operation *)(ie_ptr + + sizeof(struct ieee_types_header)); + priv->assoc_resp_ht_param = assoc_resp_ht_oper->ht_param; + priv->ht_param_present = true; + } else { + priv->ht_param_present = false; + } + mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: curr_pkt_filter is %#x\n", priv->curr_pkt_filter); diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index c755be54cc83..89a1576d0a4b 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -674,6 +674,8 @@ struct mwifiex_private { struct mwifiex_ds_mem_rw mem_rw; struct sk_buff_head bypass_txq; struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX]; + u8 assoc_resp_ht_param; + bool ht_param_present; }; diff --git a/drivers/net/wireless/marvell/mwifiex/sta_event.c b/drivers/net/wireless/marvell/mwifiex/sta_event.c index fd8061c73091..070bce401151 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_event.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_event.c @@ -92,6 +92,9 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) priv->is_data_rate_auto = true; priv->data_rate = 0; + priv->assoc_resp_ht_param = 0; + priv->ht_param_present = false; + if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data) mwifiex_hist_data_reset(priv); -- cgit From efdf0e393e76aa18e9c2ec0ca9b3a71ad410994b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Feb 2016 13:00:05 +0300 Subject: mwifiex: fix a reversed condition The NULL test here is reversed. Fixes: 7d7f07d8c5d3 ('mwifiex: add wowlan net-detect support') Signed-off-by: Dan Carpenter Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index fc8d8ca67453..489f7a911a83 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -2196,7 +2196,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, pmatch = adapter->nd_info->matches[idx]; - if (!pmatch) { + if (pmatch) { memset(pmatch, 0, sizeof(*pmatch)); if (chan_band_tlv) { pmatch->n_channels = 1; -- cgit From 0a7701b4defcebc7ce461355e6d9478df313b084 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:51 +0100 Subject: libertas: fix pointer bugs for PS_MODE commands struct cmd_ds_802_11_ps_mode contains the command header and a pointer to it was initialized with data points to the body which leads to mis-interpretation of the cmd_ds_802_11_ps_mode.action member. cmd[0] contains the header, &cmd[1] points beyond that. cmdnode->cmdbuf is a pointer to the command buffer This piece of code was unused since power saving was not enabled. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cmd.c | 4 ++-- drivers/net/wireless/marvell/libertas/cmdresp.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index 0387a5b380c8..40467d646270 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -957,7 +957,7 @@ static void lbs_queue_cmd(struct lbs_private *priv, /* Exit_PS command needs to be queued in the header always. */ if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { - struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf; + struct cmd_ds_802_11_ps_mode *psm = (void *)cmdnode->cmdbuf; if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) { if (priv->psstate != PS_STATE_FULL_POWER) @@ -1387,7 +1387,7 @@ int lbs_execute_next_command(struct lbs_private *priv) * PS command. Ignore it if it is not Exit_PS. * otherwise send it down immediately. */ - struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1]; + struct cmd_ds_802_11_ps_mode *psm = (void *)cmd; lbs_deb_host( "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", diff --git a/drivers/net/wireless/marvell/libertas/cmdresp.c b/drivers/net/wireless/marvell/libertas/cmdresp.c index e5442e8956f7..701125f9b060 100644 --- a/drivers/net/wireless/marvell/libertas/cmdresp.c +++ b/drivers/net/wireless/marvell/libertas/cmdresp.c @@ -123,7 +123,10 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) priv->cmd_timed_out = 0; if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) { - struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1]; + /* struct cmd_ds_802_11_ps_mode also contains + * the header + */ + struct cmd_ds_802_11_ps_mode *psmode = (void *)resp; u16 action = le16_to_cpu(psmode->action); lbs_deb_host( -- cgit From fae4f9f78ab11937bc45b0f3625efe2e35aed510 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:52 +0100 Subject: libertas: check whether bus can do more than polling If a sdio host does not support sdio irqs, polling is used instead. That has an impact on performance. Some functionality should not be enabled then. This add a variable in libertas_priv to indicate that. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/dev.h | 1 + drivers/net/wireless/marvell/libertas/if_sdio.c | 2 +- drivers/net/wireless/marvell/libertas/if_usb.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas/dev.h b/drivers/net/wireless/marvell/libertas/dev.h index 6bd1608992b0..edf710bc5e77 100644 --- a/drivers/net/wireless/marvell/libertas/dev.h +++ b/drivers/net/wireless/marvell/libertas/dev.h @@ -99,6 +99,7 @@ struct lbs_private { /* Hardware access */ void *card; bool iface_running; + u8 is_polling; /* host has to poll the card irq */ u8 fw_ready; u8 surpriseremoved; u8 setup_fw_on_resume; diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 68fd3a9779bd..13eae9ff8c35 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1267,7 +1267,7 @@ static int if_sdio_probe(struct sdio_func *func, priv->reset_card = if_sdio_reset_card; priv->power_save = if_sdio_power_save; priv->power_restore = if_sdio_power_restore; - + priv->is_polling = !(func->card->host->caps & MMC_CAP_SDIO_IRQ); ret = if_sdio_power_on(card); if (ret) goto err_activate_card; diff --git a/drivers/net/wireless/marvell/libertas/if_usb.c b/drivers/net/wireless/marvell/libertas/if_usb.c index dff08a2896a3..aba0c9995b14 100644 --- a/drivers/net/wireless/marvell/libertas/if_usb.c +++ b/drivers/net/wireless/marvell/libertas/if_usb.c @@ -267,6 +267,7 @@ static int if_usb_probe(struct usb_interface *intf, priv->enter_deep_sleep = NULL; priv->exit_deep_sleep = NULL; priv->reset_deep_sleep_wakeup = NULL; + priv->is_polling = false; #ifdef CONFIG_OLPC if (machine_is_olpc()) priv->reset_card = if_usb_reset_olpc_card; -- cgit From 57954b94cad77c3253beca805cf493861c7d92b5 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:53 +0100 Subject: libertas: do not confirm sleep if commands are pending If the main thread gets one PS AWAKE event and one PS SLEEP event in one iteration over event_fifo there will never be checks for commands to be processed, since psstate will always be PS_STATE_SLEEP or PS_STATE_PRE_SLEEP Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cmdresp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/libertas/cmdresp.c b/drivers/net/wireless/marvell/libertas/cmdresp.c index 701125f9b060..c95bf6dc9522 100644 --- a/drivers/net/wireless/marvell/libertas/cmdresp.c +++ b/drivers/net/wireless/marvell/libertas/cmdresp.c @@ -257,6 +257,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event) "EVENT: in FULL POWER mode, ignoring PS_SLEEP\n"); break; } + if (!list_empty(&priv->cmdpendingq)) { + lbs_deb_cmd("EVENT: commands in queue, do not sleep\n"); + break; + } priv->psstate = PS_STATE_PRE_SLEEP; lbs_ps_confirm_sleep(priv); -- cgit From fada24a5477073dd8fa84baf25ead204dc1dcb18 Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:54 +0100 Subject: libertas: go back to ps mode without commands pending Removes the old todo block and checks only whether ieee powersave mode is requested. We still have to check for being connected as this powersave mode includes logic for regularly waking up and checking for packets which only makes sense when connected. For not being connected, another mode is needed. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cmd.c | 36 ++++------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c index 40467d646270..4ddd0e5a6b85 100644 --- a/drivers/net/wireless/marvell/libertas/cmd.c +++ b/drivers/net/wireless/marvell/libertas/cmd.c @@ -1428,40 +1428,14 @@ int lbs_execute_next_command(struct lbs_private *priv) * check if in power save mode, if yes, put the device back * to PS mode */ -#ifdef TODO - /* - * This was the old code for libertas+wext. Someone that - * understands this beast should re-code it in a sane way. - * - * I actually don't understand why this is related to WPA - * and to connection status, shouldn't powering should be - * independ of such things? - */ if ((priv->psmode != LBS802_11POWERMODECAM) && (priv->psstate == PS_STATE_FULL_POWER) && - ((priv->connect_status == LBS_CONNECTED) || - lbs_mesh_connected(priv))) { - if (priv->secinfo.WPAenabled || - priv->secinfo.WPA2enabled) { - /* check for valid WPA group keys */ - if (priv->wpa_mcast_key.len || - priv->wpa_unicast_key.len) { - lbs_deb_host( - "EXEC_NEXT_CMD: WPA enabled and GTK_SET" - " go back to PS_SLEEP"); - lbs_set_ps_mode(priv, - PS_MODE_ACTION_ENTER_PS, - false); - } - } else { - lbs_deb_host( - "EXEC_NEXT_CMD: cmdpendingq empty, " - "go back to PS_SLEEP"); - lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, - false); - } + (priv->connect_status == LBS_CONNECTED)) { + lbs_deb_host( + "EXEC_NEXT_CMD: cmdpendingq empty, go back to PS_SLEEP"); + lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, + false); } -#endif } ret = 0; -- cgit From 0b8802dc5f59a4517e4130dc3606eb973760928a Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:55 +0100 Subject: libertas: fix ps-mode related removal problems When the device is remove e.g. because of going to suspend mode with powersaving enabled, lbs_remove_card tries to exit powersaving state even when already woken up. That command is not processed properly in that situation, since the command processing queue is already stopped, so it waits forever for the command being processed, so disable it. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/libertas/main.c b/drivers/net/wireless/marvell/libertas/main.c index 8079560f4965..b35b8bcce24c 100644 --- a/drivers/net/wireless/marvell/libertas/main.c +++ b/drivers/net/wireless/marvell/libertas/main.c @@ -1060,7 +1060,12 @@ void lbs_remove_card(struct lbs_private *priv) if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { priv->psmode = LBS802_11POWERMODECAM; - lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); + /* no need to wakeup if already woken up, + * on suspend, this exit ps command is not processed + * the driver hangs + */ + if (priv->psstate != PS_STATE_FULL_POWER) + lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true); } if (priv->is_deep_sleep) { -- cgit From 143e49458424b80fd004963b6ba88ed583ea62da Mon Sep 17 00:00:00 2001 From: Andreas Kemnade Date: Sat, 30 Jan 2016 18:01:56 +0100 Subject: libertas: add an cfg80211 interface for powersaving This patch adds an interface for handling commands like iwconfig wlanX power on/off. Such an interface formerly existed when the driver used wext. While performance with sdio in polling mode without using powersave mode is quite bad, powersaving mode is unusable, so do not enable it under such conditions. Signed-off-by: Andreas Kemnade Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/libertas/cfg.c | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c index 86955c416b30..2eea76a340b7 100644 --- a/drivers/net/wireless/marvell/libertas/cfg.c +++ b/drivers/net/wireless/marvell/libertas/cfg.c @@ -2039,6 +2039,43 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +int lbs_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout) +{ + struct lbs_private *priv = wiphy_priv(wiphy); + + if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { + if (!enabled) + return 0; + else + return -EINVAL; + } + /* firmware does not work well with too long latency with power saving + * enabled, so do not enable it if there is only polling, no + * interrupts (like in some sdio hosts which can only + * poll for sdio irqs) + */ + if (priv->is_polling) { + if (!enabled) + return 0; + else + return -EINVAL; + } + if (!enabled) { + priv->psmode = LBS802_11POWERMODECAM; + if (priv->psstate != PS_STATE_FULL_POWER) + lbs_set_ps_mode(priv, + PS_MODE_ACTION_EXIT_PS, + true); + return 0; + } + if (priv->psmode != LBS802_11POWERMODECAM) + return 0; + priv->psmode = LBS802_11POWERMODEMAX_PSP; + if (priv->connect_status == LBS_CONNECTED) + lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS, true); + return 0; +} /* * Initialization @@ -2057,6 +2094,7 @@ static struct cfg80211_ops lbs_cfg80211_ops = { .change_virtual_intf = lbs_change_intf, .join_ibss = lbs_join_ibss, .leave_ibss = lbs_leave_ibss, + .set_power_mgmt = lbs_set_power_mgmt, }; -- cgit From 478375cedcc0ae5b4cadd29ee5f74c3a5cb5d2ad Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 5 Feb 2016 09:23:32 +0530 Subject: Staging:iio:Remove exceptional & on function name In this file,function names are otherwise used as pointers without &. Found using coccinelle. // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // Signed-off-by: Bhumika Goyal Signed-off-by: Jonathan Cameron --- 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 10c43dda0f5a..d1218d896725 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -558,7 +558,7 @@ out: } static const struct iio_info ad5933_info = { - .read_raw = &ad5933_read_raw, + .read_raw = ad5933_read_raw, .attrs = &ad5933_attribute_group, .driver_module = THIS_MODULE, }; @@ -616,9 +616,9 @@ static int ad5933_ring_postdisable(struct iio_dev *indio_dev) } static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = { - .preenable = &ad5933_ring_preenable, - .postenable = &ad5933_ring_postenable, - .postdisable = &ad5933_ring_postdisable, + .preenable = ad5933_ring_preenable, + .postenable = ad5933_ring_postenable, + .postdisable = ad5933_ring_postdisable, }; static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) -- cgit From 1ad1ce9b669095bfe94c32ecd19f2a426837eb93 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Feb 2016 18:50:37 +0200 Subject: iio: pressure: ms5611: Add IIO_CHAN_INFO_SCALE to mask This allows data exported via buffer interface to be converted to standard units in userspace. Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/ms5611_core.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 2f3d9b4aca4e..6cf0e55380aa 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -201,6 +201,18 @@ static int ms5611_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_TEMP: + *val = 10; + return IIO_VAL_INT; + case IIO_PRESSURE: + *val = 0; + *val2 = 1000; + return IIO_VAL_INT_PLUS_MICRO; + default: + return -EINVAL; + } } return -EINVAL; @@ -218,11 +230,13 @@ static struct ms5611_chip_info chip_info_tbl[] = { static const struct iio_chan_spec ms5611_channels[] = { { .type = IIO_PRESSURE, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_SCALE), }, { .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | + BIT(IIO_CHAN_INFO_SCALE), } }; -- cgit From 713bbb4efb9dcda2e96c8338db1f21c68f2d822a Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 3 Feb 2016 18:50:38 +0200 Subject: iio: pressure: ms5611: Add triggered buffer support This will be used together with an external trigger (e.g hrtimer based software trigger). Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/pressure/Kconfig | 1 + drivers/iio/pressure/ms5611.h | 1 + drivers/iio/pressure/ms5611_core.c | 74 ++++++++++++++++++++++++++++++++++++-- drivers/iio/pressure/ms5611_i2c.c | 7 ++++ drivers/iio/pressure/ms5611_spi.c | 8 +++++ 5 files changed, 89 insertions(+), 2 deletions(-) diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index cf03a43545a1..f15f66d6f527 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig @@ -69,6 +69,7 @@ config MPL3115 config MS5611 tristate "Measurement Specialties MS5611 pressure sensor driver" + select IIO_TRIGGERED_BUFFER help Say Y here to build support for the Measurement Specialties MS5611, MS5607 pressure and temperature sensors. diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h index 23b93c797dba..2d70dd6e14b0 100644 --- a/drivers/iio/pressure/ms5611.h +++ b/drivers/iio/pressure/ms5611.h @@ -52,5 +52,6 @@ struct ms5611_state { }; int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type); +int ms5611_remove(struct iio_dev *indio_dev); #endif /* _MS5611_H */ diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c index 6cf0e55380aa..c7885f0c819f 100644 --- a/drivers/iio/pressure/ms5611_core.c +++ b/drivers/iio/pressure/ms5611_core.c @@ -17,6 +17,9 @@ #include #include +#include +#include +#include #include "ms5611.h" static bool ms5611_prom_is_valid(u16 *prom, size_t len) @@ -173,6 +176,28 @@ static int ms5611_reset(struct iio_dev *indio_dev) return 0; } +static irqreturn_t ms5611_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ms5611_state *st = iio_priv(indio_dev); + s32 buf[4]; /* s32 (pressure) + s32 (temp) + 2 * s32 (timestamp) */ + int ret; + + mutex_lock(&st->lock); + ret = ms5611_read_temp_and_pressure(indio_dev, &buf[1], &buf[0]); + mutex_unlock(&st->lock); + if (ret < 0) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); + +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + static int ms5611_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) @@ -218,6 +243,8 @@ static int ms5611_read_raw(struct iio_dev *indio_dev, return -EINVAL; } +static const unsigned long ms5611_scan_masks[] = {0x3, 0}; + static struct ms5611_chip_info chip_info_tbl[] = { [MS5611] = { .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate, @@ -232,12 +259,27 @@ static const struct iio_chan_spec ms5611_channels[] = { .type = IIO_PRESSURE, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = 0, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, }, { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) | BIT(IIO_CHAN_INFO_SCALE), - } + .scan_index = 1, + .scan_type = { + .sign = 's', + .realbits = 32, + .storagebits = 32, + .endianness = IIO_CPU, + }, + }, + IIO_CHAN_SOFT_TIMESTAMP(2), }; static const struct iio_info ms5611_info = { @@ -269,15 +311,43 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type) indio_dev->channels = ms5611_channels; indio_dev->num_channels = ARRAY_SIZE(ms5611_channels); indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->available_scan_masks = ms5611_scan_masks; ret = ms5611_init(indio_dev); if (ret < 0) return ret; - return devm_iio_device_register(dev, indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ms5611_trigger_handler, NULL); + if (ret < 0) { + dev_err(dev, "iio triggered buffer setup failed\n"); + return ret; + } + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(dev, "unable to register iio device\n"); + goto err_buffer_cleanup; + } + + return 0; + +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; } EXPORT_SYMBOL(ms5611_probe); +int ms5611_remove(struct iio_dev *indio_dev) +{ + iio_device_unregister(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); + + return 0; +} +EXPORT_SYMBOL(ms5611_remove); + MODULE_AUTHOR("Tomasz Duszynski "); MODULE_DESCRIPTION("MS5611 core driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c index 245797d1ecf0..42706a89c6ee 100644 --- a/drivers/iio/pressure/ms5611_i2c.c +++ b/drivers/iio/pressure/ms5611_i2c.c @@ -99,6 +99,7 @@ static int ms5611_i2c_probe(struct i2c_client *client, return -ENOMEM; st = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); st->reset = ms5611_i2c_reset; st->read_prom_word = ms5611_i2c_read_prom_word; st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure; @@ -107,6 +108,11 @@ static int ms5611_i2c_probe(struct i2c_client *client, return ms5611_probe(indio_dev, &client->dev, id->driver_data); } +static int ms5611_i2c_remove(struct i2c_client *client) +{ + return ms5611_remove(i2c_get_clientdata(client)); +} + static const struct i2c_device_id ms5611_id[] = { { "ms5611", MS5611 }, { "ms5607", MS5607 }, @@ -120,6 +126,7 @@ static struct i2c_driver ms5611_driver = { }, .id_table = ms5611_id, .probe = ms5611_i2c_probe, + .remove = ms5611_i2c_remove, }; module_i2c_driver(ms5611_driver); diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index aaa0c4ba91a7..c4bf4e8f7c5c 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -90,6 +90,8 @@ static int ms5611_spi_probe(struct spi_device *spi) if (!indio_dev) return -ENOMEM; + spi_set_drvdata(spi, indio_dev); + spi->mode = SPI_MODE_0; spi->max_speed_hz = 20000000; spi->bits_per_word = 8; @@ -107,6 +109,11 @@ static int ms5611_spi_probe(struct spi_device *spi) spi_get_device_id(spi)->driver_data); } +static int ms5611_spi_remove(struct spi_device *spi) +{ + return ms5611_remove(spi_get_drvdata(spi)); +} + static const struct spi_device_id ms5611_id[] = { { "ms5611", MS5611 }, { "ms5607", MS5607 }, @@ -120,6 +127,7 @@ static struct spi_driver ms5611_driver = { }, .id_table = ms5611_id, .probe = ms5611_spi_probe, + .remove = ms5611_spi_remove, }; module_spi_driver(ms5611_driver); -- cgit From 182b49058e036573ccea37619d90fcaddc983536 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 2 Feb 2016 16:27:24 +0100 Subject: iio: Add helper function for calculating scan index storage size We have the same code for computing the scan index storage size in bytes all over the place. Factor this out into helper functions. Signed-off-by: Lars-Peter Clausen Acked-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/industrialio-buffer.c | 59 +++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 139ae916225f..b976332d45d3 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -512,33 +512,41 @@ static ssize_t iio_buffer_show_enable(struct device *dev, return sprintf(buf, "%d\n", iio_buffer_is_active(indio_dev->buffer)); } +static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, + unsigned int scan_index) +{ + const struct iio_chan_spec *ch; + unsigned int bytes; + + ch = iio_find_channel_from_si(indio_dev, scan_index); + bytes = ch->scan_type.storagebits / 8; + if (ch->scan_type.repeat > 1) + bytes *= ch->scan_type.repeat; + return bytes; +} + +static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) +{ + return iio_storage_bytes_for_si(indio_dev, + indio_dev->scan_index_timestamp); +} + static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const unsigned long *mask, bool timestamp) { - const struct iio_chan_spec *ch; unsigned bytes = 0; int length, i; /* How much space will the demuxed element take? */ for_each_set_bit(i, mask, indio_dev->masklength) { - ch = iio_find_channel_from_si(indio_dev, i); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_si(indio_dev, i); bytes = ALIGN(bytes, length); bytes += length; } + if (timestamp) { - ch = iio_find_channel_from_si(indio_dev, - indio_dev->scan_index_timestamp); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_timestamp(indio_dev); bytes = ALIGN(bytes, length); bytes += length; } @@ -1288,7 +1296,6 @@ static int iio_buffer_add_demux(struct iio_buffer *buffer, static int iio_buffer_update_demux(struct iio_dev *indio_dev, struct iio_buffer *buffer) { - const struct iio_chan_spec *ch; int ret, in_ind = -1, out_ind, length; unsigned in_loc = 0, out_loc = 0; struct iio_demux_table *p = NULL; @@ -1315,21 +1322,11 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, in_ind = find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, in_ind + 1); - ch = iio_find_channel_from_si(indio_dev, in_ind); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_si(indio_dev, in_ind); /* Make sure we are aligned */ in_loc = roundup(in_loc, length) + length; } - ch = iio_find_channel_from_si(indio_dev, in_ind); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_si(indio_dev, in_ind); out_loc = roundup(out_loc, length); in_loc = roundup(in_loc, length); ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); @@ -1340,13 +1337,7 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, } /* Relies on scan_timestamp being last */ if (buffer->scan_timestamp) { - ch = iio_find_channel_from_si(indio_dev, - indio_dev->scan_index_timestamp); - if (ch->scan_type.repeat > 1) - length = ch->scan_type.storagebits / 8 * - ch->scan_type.repeat; - else - length = ch->scan_type.storagebits / 8; + length = iio_storage_bytes_for_timestamp(indio_dev); out_loc = roundup(out_loc, length); in_loc = roundup(in_loc, length); ret = iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); -- cgit From 3b31b783add21b47bc0314ddf33c9af9247a1d65 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 2 Feb 2016 15:36:39 +0100 Subject: iio: chemical: select IRQ_WORK for ATLAS ph sensor The newly added atlas-ph-sensor driver uses irq_work_queue, which may not always be enabled: ERROR: "irq_work_queue" [drivers/iio/chemical/atlas-ph-sensor.ko] undefined! This adds a 'select' statement to Kconfig to ensure it's there when we need it. Signed-off-by: Arnd Bergmann Fixes: 27dec00ecf2d ("iio: chemical: add Atlas pH-SM sensor support") Reviewed-by: Matt Ranostay Signed-off-by: Jonathan Cameron --- drivers/iio/chemical/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig index ce7cd1370f74..f73290f84c90 100644 --- a/drivers/iio/chemical/Kconfig +++ b/drivers/iio/chemical/Kconfig @@ -10,6 +10,7 @@ config ATLAS_PH_SENSOR select REGMAP_I2C select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select IRQ_WORK help Say Y here to build I2C interface support for the Atlas Scientific OEM pH-SM sensor. -- cgit From b8cc27ca4cce107460fca33acad3f96a8c26e015 Mon Sep 17 00:00:00 2001 From: "Gujulan Elango, Hari Prasath (H.)" Date: Tue, 2 Feb 2016 12:56:32 +0000 Subject: staging: iio: replace clk_get() with devm_clk_get() This patch replaces the clk_get() with devm_clk_get().Accordingly,modified the error paths,rename error labels and removed clk_put() in probe() & remove functions. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/spear_adc.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/staging/iio/adc/spear_adc.c b/drivers/staging/iio/adc/spear_adc.c index 712cae0e8608..f2c006572783 100644 --- a/drivers/staging/iio/adc/spear_adc.c +++ b/drivers/staging/iio/adc/spear_adc.c @@ -288,7 +288,7 @@ static int spear_adc_probe(struct platform_device *pdev) st->adc_base_spear3xx = (struct adc_regs_spear3xx __iomem *)st->adc_base_spear6xx; - st->clk = clk_get(dev, NULL); + st->clk = devm_clk_get(dev, NULL); if (IS_ERR(st->clk)) { dev_err(dev, "failed getting clock\n"); goto errout1; @@ -297,28 +297,28 @@ static int spear_adc_probe(struct platform_device *pdev) ret = clk_prepare_enable(st->clk); if (ret) { dev_err(dev, "failed enabling clock\n"); - goto errout2; + goto errout1; } irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_err(dev, "failed getting interrupt resource\n"); ret = -EINVAL; - goto errout3; + goto errout2; } ret = devm_request_irq(dev, irq, spear_adc_isr, 0, SPEAR_ADC_MOD_NAME, st); if (ret < 0) { dev_err(dev, "failed requesting interrupt\n"); - goto errout3; + goto errout2; } if (of_property_read_u32(np, "sampling-frequency", &st->sampling_freq)) { dev_err(dev, "sampling-frequency missing in DT\n"); ret = -EINVAL; - goto errout3; + goto errout2; } /* @@ -348,16 +348,14 @@ static int spear_adc_probe(struct platform_device *pdev) ret = iio_device_register(indio_dev); if (ret) - goto errout3; + goto errout2; dev_info(dev, "SPEAR ADC driver loaded, IRQ %d\n", irq); return 0; -errout3: - clk_disable_unprepare(st->clk); errout2: - clk_put(st->clk); + clk_disable_unprepare(st->clk); errout1: iounmap(st->adc_base_spear6xx); return ret; @@ -370,7 +368,6 @@ static int spear_adc_remove(struct platform_device *pdev) iio_device_unregister(indio_dev); clk_disable_unprepare(st->clk); - clk_put(st->clk); iounmap(st->adc_base_spear6xx); return 0; -- cgit From 380f6ff5495e8008775078e62e748c7e8f099270 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 2 Feb 2016 11:50:43 -0600 Subject: Documentation: afe4404: Add DT bindings for the AFE4404 heart monitor Add the TI afe4404 heart monitor DT bindings documentation. Create health directory created under iio. Signed-off-by: Andrew F. Davis Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/health/afe4404.txt | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/health/afe4404.txt diff --git a/Documentation/devicetree/bindings/iio/health/afe4404.txt b/Documentation/devicetree/bindings/iio/health/afe4404.txt new file mode 100644 index 000000000000..de69f203edfa --- /dev/null +++ b/Documentation/devicetree/bindings/iio/health/afe4404.txt @@ -0,0 +1,30 @@ +Texas Instruments AFE4404 Heart rate and Pulse Oximeter + +Required properties: + - compatible : Should be "ti,afe4404". + - reg : I2C address of the device. + - tx-supply : Regulator supply to transmitting LEDs. + - interrupt-parent : Phandle to he parent interrupt controller. + - interrupts : The interrupt line the device ADC_RDY pin is + connected to. For details refer to, + ../interrupt-controller/interrupts.txt. + +Optional properties: + - reset-gpios : GPIO used to reset the device. + For details refer to, ../gpio/gpio.txt. + +Example: + +&i2c2 { + heart_mon@58 { + compatible = "ti,afe4404"; + reg = <0x58>; + + tx-supply = <&vbat>; + + interrupt-parent = <&gpio1>; + interrupts = <28 IRQ_TYPE_EDGE_RISING>; + + reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + }; +}; -- cgit From 87aec56e27efac98b7a0abe93258687716bf0b1e Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 2 Feb 2016 11:50:44 -0600 Subject: iio: health: Add driver for the TI AFE4404 heart monitor Add driver for the TI AFE4404 heart rate monitor and pulse oximeter. This device detects reflected LED light fluctuations and presents an ADC value to the user space for further signal processing. Datasheet: http://www.ti.com/product/AFE4404/datasheet Signed-off-by: Andrew F. Davis Signed-off-by: Jonathan Cameron --- .../ABI/testing/sysfs-bus-iio-health-afe440x | 54 ++ drivers/iio/health/Kconfig | 19 +- drivers/iio/health/Makefile | 1 + drivers/iio/health/afe4404.c | 679 +++++++++++++++++++++ drivers/iio/health/afe440x.h | 191 ++++++ 5 files changed, 943 insertions(+), 1 deletion(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-health-afe440x create mode 100644 drivers/iio/health/afe4404.c create mode 100644 drivers/iio/health/afe440x.h diff --git a/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x b/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x new file mode 100644 index 000000000000..3740f253d406 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-health-afe440x @@ -0,0 +1,54 @@ +What: /sys/bus/iio/devices/iio:deviceX/tia_resistanceY + /sys/bus/iio/devices/iio:deviceX/tia_capacitanceY +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get and set the resistance and the capacitance settings for the + Transimpedance Amplifier. Y is 1 for Rf1 and Cf1, Y is 2 for + Rf2 and Cf2 values. + +What: /sys/bus/iio/devices/iio:deviceX/tia_separate_en +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Enable or disable separate settings for the TransImpedance + Amplifier above, when disabled both values are set by the + first channel. + +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_raw + /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY_ambient_raw +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get measured values from the ADC for these stages. Y is the + specific LED number. The values are expressed in 24-bit twos + complement. + +What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ledY-ledY_ambient_raw +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get differential values from the ADC for these stages. Y is the + specific LED number. The values are expressed in 24-bit twos + complement for the specified LEDs. + +What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_offset + /sys/bus/iio/devices/iio:deviceX/out_current_ledY_ambient_offset +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get and set the offset cancellation DAC setting for these + stages. The values are expressed in 5-bit sign-magnitude. + +What: /sys/bus/iio/devices/iio:deviceX/out_current_ledY_raw +Date: December 2015 +KernelVersion: +Contact: Andrew F. Davis +Description: + Get and set the LED current for the specified LED. Y is the + specific LED number. diff --git a/drivers/iio/health/Kconfig b/drivers/iio/health/Kconfig index a647679da805..632a14b7dd6f 100644 --- a/drivers/iio/health/Kconfig +++ b/drivers/iio/health/Kconfig @@ -3,7 +3,22 @@ # # When adding new entries keep the list in alphabetical order -menu "Health sensors" +menu "Health Sensors" + +menu "Heart Rate Monitors" + +config AFE4404 + tristate "TI AFE4404 heart rate and pulse oximeter sensor" + depends on I2C + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes to choose the Texas Instruments AFE4404 + heart rate monitor and low-cost pulse oximeter. + + To compile this driver as a module, choose M here: the + module will be called afe4404. config MAX30100 tristate "MAX30100 heart rate and pulse oximeter sensor" @@ -19,3 +34,5 @@ config MAX30100 module will be called max30100. endmenu + +endmenu diff --git a/drivers/iio/health/Makefile b/drivers/iio/health/Makefile index 7c475d7faad8..b37c0d5e07b8 100644 --- a/drivers/iio/health/Makefile +++ b/drivers/iio/health/Makefile @@ -4,4 +4,5 @@ # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AFE4404) += afe4404.o obj-$(CONFIG_MAX30100) += max30100.o diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c new file mode 100644 index 000000000000..0759268f37e0 --- /dev/null +++ b/drivers/iio/health/afe4404.c @@ -0,0 +1,679 @@ +/* + * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 + +#include "afe440x.h" + +#define AFE4404_DRIVER_NAME "afe4404" + +/* AFE4404 registers */ +#define AFE4404_TIA_GAIN_SEP 0x20 +#define AFE4404_TIA_GAIN 0x21 +#define AFE4404_PROG_TG_STC 0x34 +#define AFE4404_PROG_TG_ENDC 0x35 +#define AFE4404_LED3LEDSTC 0x36 +#define AFE4404_LED3LEDENDC 0x37 +#define AFE4404_CLKDIV_PRF 0x39 +#define AFE4404_OFFDAC 0x3a +#define AFE4404_DEC 0x3d +#define AFE4404_AVG_LED2_ALED2VAL 0x3f +#define AFE4404_AVG_LED1_ALED1VAL 0x40 + +/* AFE4404 GAIN register fields */ +#define AFE4404_TIA_GAIN_RES_MASK GENMASK(2, 0) +#define AFE4404_TIA_GAIN_RES_SHIFT 0 +#define AFE4404_TIA_GAIN_CAP_MASK GENMASK(5, 3) +#define AFE4404_TIA_GAIN_CAP_SHIFT 3 + +/* AFE4404 LEDCNTRL register fields */ +#define AFE4404_LEDCNTRL_ILED1_MASK GENMASK(5, 0) +#define AFE4404_LEDCNTRL_ILED1_SHIFT 0 +#define AFE4404_LEDCNTRL_ILED2_MASK GENMASK(11, 6) +#define AFE4404_LEDCNTRL_ILED2_SHIFT 6 +#define AFE4404_LEDCNTRL_ILED3_MASK GENMASK(17, 12) +#define AFE4404_LEDCNTRL_ILED3_SHIFT 12 + +/* AFE4404 CONTROL2 register fields */ +#define AFE440X_CONTROL2_ILED_2X_MASK BIT(17) +#define AFE440X_CONTROL2_ILED_2X_SHIFT 17 + +/* AFE4404 CONTROL3 register fields */ +#define AFE440X_CONTROL3_OSC_ENABLE BIT(9) + +/* AFE4404 OFFDAC register current fields */ +#define AFE4404_OFFDAC_CURR_LED1_MASK GENMASK(9, 5) +#define AFE4404_OFFDAC_CURR_LED1_SHIFT 5 +#define AFE4404_OFFDAC_CURR_LED2_MASK GENMASK(19, 15) +#define AFE4404_OFFDAC_CURR_LED2_SHIFT 15 +#define AFE4404_OFFDAC_CURR_LED3_MASK GENMASK(4, 0) +#define AFE4404_OFFDAC_CURR_LED3_SHIFT 0 +#define AFE4404_OFFDAC_CURR_ALED1_MASK GENMASK(14, 10) +#define AFE4404_OFFDAC_CURR_ALED1_SHIFT 10 +#define AFE4404_OFFDAC_CURR_ALED2_MASK GENMASK(4, 0) +#define AFE4404_OFFDAC_CURR_ALED2_SHIFT 0 + +/* AFE4404 NULL fields */ +#define NULL_MASK 0 +#define NULL_SHIFT 0 + +/* AFE4404 TIA_GAIN_CAP values */ +#define AFE4404_TIA_GAIN_CAP_5_P 0x0 +#define AFE4404_TIA_GAIN_CAP_2_5_P 0x1 +#define AFE4404_TIA_GAIN_CAP_10_P 0x2 +#define AFE4404_TIA_GAIN_CAP_7_5_P 0x3 +#define AFE4404_TIA_GAIN_CAP_20_P 0x4 +#define AFE4404_TIA_GAIN_CAP_17_5_P 0x5 +#define AFE4404_TIA_GAIN_CAP_25_P 0x6 +#define AFE4404_TIA_GAIN_CAP_22_5_P 0x7 + +/* AFE4404 TIA_GAIN_RES values */ +#define AFE4404_TIA_GAIN_RES_500_K 0x0 +#define AFE4404_TIA_GAIN_RES_250_K 0x1 +#define AFE4404_TIA_GAIN_RES_100_K 0x2 +#define AFE4404_TIA_GAIN_RES_50_K 0x3 +#define AFE4404_TIA_GAIN_RES_25_K 0x4 +#define AFE4404_TIA_GAIN_RES_10_K 0x5 +#define AFE4404_TIA_GAIN_RES_1_M 0x6 +#define AFE4404_TIA_GAIN_RES_2_M 0x7 + +/** + * struct afe4404_data + * @dev - Device structure + * @regmap - Register map of the device + * @regulator - Pointer to the regulator for the IC + * @trig - IIO trigger for this device + * @irq - ADC_RDY line interrupt number + */ +struct afe4404_data { + struct device *dev; + struct regmap *regmap; + struct regulator *regulator; + struct iio_trigger *trig; + int irq; +}; + +enum afe4404_chan_id { + LED1, + ALED1, + LED2, + ALED2, + LED3, + LED1_ALED1, + LED2_ALED2, + ILED1, + ILED2, + ILED3, +}; + +static const struct afe440x_reg_info afe4404_reg_info[] = { + [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED1), + [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED1), + [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED2), + [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED2), + [LED3] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), + [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), + [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), + [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED1), + [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED2), + [ILED3] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED3), +}; + +static const struct iio_chan_spec afe4404_channels[] = { + /* ADC values */ + AFE440X_INTENSITY_CHAN(LED1, "led1", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED2, "led2", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED3, "led3", BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), + /* LED current */ + AFE440X_CURRENT_CHAN(ILED1, "led1"), + AFE440X_CURRENT_CHAN(ILED2, "led2"), + AFE440X_CURRENT_CHAN(ILED3, "led3"), +}; + +static const struct afe440x_val_table afe4404_res_table[] = { + { .integer = 500000, .fract = 0 }, + { .integer = 250000, .fract = 0 }, + { .integer = 100000, .fract = 0 }, + { .integer = 50000, .fract = 0 }, + { .integer = 25000, .fract = 0 }, + { .integer = 10000, .fract = 0 }, + { .integer = 1000000, .fract = 0 }, + { .integer = 2000000, .fract = 0 }, +}; +AFE440X_TABLE_ATTR(tia_resistance_available, afe4404_res_table); + +static const struct afe440x_val_table afe4404_cap_table[] = { + { .integer = 0, .fract = 5000 }, + { .integer = 0, .fract = 2500 }, + { .integer = 0, .fract = 10000 }, + { .integer = 0, .fract = 7500 }, + { .integer = 0, .fract = 20000 }, + { .integer = 0, .fract = 17500 }, + { .integer = 0, .fract = 25000 }, + { .integer = 0, .fract = 22500 }, +}; +AFE440X_TABLE_ATTR(tia_capacitance_available, afe4404_cap_table); + +static ssize_t afe440x_show_register(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + unsigned int reg_val, type; + int vals[2]; + int ret, val_len; + + ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); + if (ret) + return ret; + + reg_val &= afe440x_attr->mask; + reg_val >>= afe440x_attr->shift; + + switch (afe440x_attr->type) { + case SIMPLE: + type = IIO_VAL_INT; + val_len = 1; + vals[0] = reg_val; + break; + case RESISTANCE: + case CAPACITANCE: + type = IIO_VAL_INT_PLUS_MICRO; + val_len = 2; + if (reg_val < afe440x_attr->table_size) { + vals[0] = afe440x_attr->val_table[reg_val].integer; + vals[1] = afe440x_attr->val_table[reg_val].fract; + break; + } + return -EINVAL; + default: + return -EINVAL; + } + + return iio_format_value(buf, type, val_len, vals); +} + +static ssize_t afe440x_store_register(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + int val, integer, fract, ret; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + switch (afe440x_attr->type) { + case SIMPLE: + val = integer; + break; + case RESISTANCE: + case CAPACITANCE: + for (val = 0; val < afe440x_attr->table_size; val++) + if (afe440x_attr->val_table[val].integer == integer && + afe440x_attr->val_table[val].fract == fract) + break; + if (val == afe440x_attr->table_size) + return -EINVAL; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, + afe440x_attr->mask, + (val << afe440x_attr->shift)); + if (ret) + return ret; + + return count; +} + +static AFE440X_ATTR(tia_separate_en, AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); + +static AFE440X_ATTR(tia_resistance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); +static AFE440X_ATTR(tia_capacitance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); + +static AFE440X_ATTR(tia_resistance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); +static AFE440X_ATTR(tia_capacitance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); + +static struct attribute *afe440x_attributes[] = { + &afe440x_attr_tia_separate_en.dev_attr.attr, + &afe440x_attr_tia_resistance1.dev_attr.attr, + &afe440x_attr_tia_capacitance1.dev_attr.attr, + &afe440x_attr_tia_resistance2.dev_attr.attr, + &afe440x_attr_tia_capacitance2.dev_attr.attr, + &dev_attr_tia_resistance_available.attr, + &dev_attr_tia_capacitance_available.attr, + NULL +}; + +static const struct attribute_group afe440x_attribute_group = { + .attrs = afe440x_attributes +}; + +static int afe4404_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct afe4404_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; + int ret; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(afe->regmap, reg_info.reg, val); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + ret = regmap_read(afe->regmap, reg_info.offreg, + val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(afe->regmap, reg_info.reg, val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 800000; + return IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + + return -EINVAL; +} + +static int afe4404_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct afe4404_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + return regmap_update_bits(afe->regmap, + reg_info.offreg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + return regmap_update_bits(afe->regmap, + reg_info.reg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info afe4404_iio_info = { + .attrs = &afe440x_attribute_group, + .read_raw = afe4404_read_raw, + .write_raw = afe4404_write_raw, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t afe4404_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct afe4404_data *afe = iio_priv(indio_dev); + int ret, bit, i = 0; + s32 buffer[10]; + + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = regmap_read(afe->regmap, afe4404_reg_info[bit].reg, + &buffer[i++]); + if (ret) + goto err; + } + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_trigger_ops afe4404_trigger_ops = { + .owner = THIS_MODULE, +}; + +/* Default timings from data-sheet */ +#define AFE4404_TIMING_PAIRS \ + { AFE440X_PRPCOUNT, 39999 }, \ + { AFE440X_LED2LEDSTC, 0 }, \ + { AFE440X_LED2LEDENDC, 398 }, \ + { AFE440X_LED2STC, 80 }, \ + { AFE440X_LED2ENDC, 398 }, \ + { AFE440X_ADCRSTSTCT0, 5600 }, \ + { AFE440X_ADCRSTENDCT0, 5606 }, \ + { AFE440X_LED2CONVST, 5607 }, \ + { AFE440X_LED2CONVEND, 6066 }, \ + { AFE4404_LED3LEDSTC, 400 }, \ + { AFE4404_LED3LEDENDC, 798 }, \ + { AFE440X_ALED2STC, 480 }, \ + { AFE440X_ALED2ENDC, 798 }, \ + { AFE440X_ADCRSTSTCT1, 6068 }, \ + { AFE440X_ADCRSTENDCT1, 6074 }, \ + { AFE440X_ALED2CONVST, 6075 }, \ + { AFE440X_ALED2CONVEND, 6534 }, \ + { AFE440X_LED1LEDSTC, 800 }, \ + { AFE440X_LED1LEDENDC, 1198 }, \ + { AFE440X_LED1STC, 880 }, \ + { AFE440X_LED1ENDC, 1198 }, \ + { AFE440X_ADCRSTSTCT2, 6536 }, \ + { AFE440X_ADCRSTENDCT2, 6542 }, \ + { AFE440X_LED1CONVST, 6543 }, \ + { AFE440X_LED1CONVEND, 7003 }, \ + { AFE440X_ALED1STC, 1280 }, \ + { AFE440X_ALED1ENDC, 1598 }, \ + { AFE440X_ADCRSTSTCT3, 7005 }, \ + { AFE440X_ADCRSTENDCT3, 7011 }, \ + { AFE440X_ALED1CONVST, 7012 }, \ + { AFE440X_ALED1CONVEND, 7471 }, \ + { AFE440X_PDNCYCLESTC, 7671 }, \ + { AFE440X_PDNCYCLEENDC, 39199 } + +static const struct reg_sequence afe4404_reg_sequences[] = { + AFE4404_TIMING_PAIRS, + { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, + { AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES_50_K }, + { AFE440X_LEDCNTRL, (0xf << AFE4404_LEDCNTRL_ILED1_SHIFT) | + (0x3 << AFE4404_LEDCNTRL_ILED2_SHIFT) | + (0x3 << AFE4404_LEDCNTRL_ILED3_SHIFT) }, + { AFE440X_CONTROL2, AFE440X_CONTROL3_OSC_ENABLE }, +}; + +static const struct regmap_range afe4404_yes_ranges[] = { + regmap_reg_range(AFE440X_LED2VAL, AFE440X_LED1_ALED1VAL), + regmap_reg_range(AFE4404_AVG_LED2_ALED2VAL, AFE4404_AVG_LED1_ALED1VAL), +}; + +static const struct regmap_access_table afe4404_volatile_table = { + .yes_ranges = afe4404_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(afe4404_yes_ranges), +}; + +static const struct regmap_config afe4404_regmap_config = { + .reg_bits = 8, + .val_bits = 24, + + .max_register = AFE4404_AVG_LED1_ALED1VAL, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &afe4404_volatile_table, +}; + +#ifdef CONFIG_OF +static const struct of_device_id afe4404_of_match[] = { + { .compatible = "ti,afe4404", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, afe4404_of_match); +#endif + +static int afe4404_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, + AFE440X_CONTROL2_PDN_AFE); + if (ret) + return ret; + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static int afe4404_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, 0); + if (ret) + return ret; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(afe4404_pm_ops, afe4404_suspend, afe4404_resume); + +static int afe4404_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct afe4404_data *afe; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*afe)); + if (!indio_dev) + return -ENOMEM; + + afe = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + + afe->dev = &client->dev; + afe->irq = client->irq; + + afe->regmap = devm_regmap_init_i2c(client, &afe4404_regmap_config); + if (IS_ERR(afe->regmap)) { + dev_err(afe->dev, "Unable to allocate register map\n"); + return PTR_ERR(afe->regmap); + } + + afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); + if (IS_ERR(afe->regulator)) { + dev_err(afe->dev, "Unable to get regulator\n"); + return PTR_ERR(afe->regulator); + } + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_write(afe->regmap, AFE440X_CONTROL0, + AFE440X_CONTROL0_SW_RESET); + if (ret) { + dev_err(afe->dev, "Unable to reset device\n"); + goto disable_reg; + } + + ret = regmap_multi_reg_write(afe->regmap, afe4404_reg_sequences, + ARRAY_SIZE(afe4404_reg_sequences)); + if (ret) { + dev_err(afe->dev, "Unable to set register defaults\n"); + goto disable_reg; + } + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = afe->dev; + indio_dev->channels = afe4404_channels; + indio_dev->num_channels = ARRAY_SIZE(afe4404_channels); + indio_dev->name = AFE4404_DRIVER_NAME; + indio_dev->info = &afe4404_iio_info; + + if (afe->irq > 0) { + afe->trig = devm_iio_trigger_alloc(afe->dev, + "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!afe->trig) { + dev_err(afe->dev, "Unable to allocate IIO trigger\n"); + ret = -ENOMEM; + goto disable_reg; + } + + iio_trigger_set_drvdata(afe->trig, indio_dev); + + afe->trig->ops = &afe4404_trigger_ops; + afe->trig->dev.parent = afe->dev; + + ret = iio_trigger_register(afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to register IIO trigger\n"); + goto disable_reg; + } + + ret = devm_request_threaded_irq(afe->dev, afe->irq, + iio_trigger_generic_data_rdy_poll, + NULL, IRQF_ONESHOT, + AFE4404_DRIVER_NAME, + afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to request IRQ\n"); + goto disable_reg; + } + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + afe4404_trigger_handler, NULL); + if (ret) { + dev_err(afe->dev, "Unable to setup buffer\n"); + goto unregister_trigger; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(afe->dev, "Unable to register IIO device\n"); + goto unregister_triggered_buffer; + } + + return 0; + +unregister_triggered_buffer: + iio_triggered_buffer_cleanup(indio_dev); +unregister_trigger: + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); +disable_reg: + regulator_disable(afe->regulator); + + return ret; +} + +static int afe4404_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct afe4404_data *afe = iio_priv(indio_dev); + int ret; + + iio_device_unregister(indio_dev); + + iio_triggered_buffer_cleanup(indio_dev); + + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static const struct i2c_device_id afe4404_ids[] = { + { "afe4404", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, afe4404_ids); + +static struct i2c_driver afe4404_i2c_driver = { + .driver = { + .name = AFE4404_DRIVER_NAME, + .of_match_table = of_match_ptr(afe4404_of_match), + .pm = &afe4404_pm_ops, + }, + .probe = afe4404_probe, + .remove = afe4404_remove, + .id_table = afe4404_ids, +}; +module_i2c_driver(afe4404_i2c_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TI AFE4404 Heart Rate and Pulse Oximeter"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/health/afe440x.h b/drivers/iio/health/afe440x.h new file mode 100644 index 000000000000..c671ab78a23a --- /dev/null +++ b/drivers/iio/health/afe440x.h @@ -0,0 +1,191 @@ +/* + * AFE440X Heart Rate Monitors and Low-Cost Pulse Oximeters + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 _AFE440X_H +#define _AFE440X_H + +/* AFE440X registers */ +#define AFE440X_CONTROL0 0x00 +#define AFE440X_LED2STC 0x01 +#define AFE440X_LED2ENDC 0x02 +#define AFE440X_LED1LEDSTC 0x03 +#define AFE440X_LED1LEDENDC 0x04 +#define AFE440X_ALED2STC 0x05 +#define AFE440X_ALED2ENDC 0x06 +#define AFE440X_LED1STC 0x07 +#define AFE440X_LED1ENDC 0x08 +#define AFE440X_LED2LEDSTC 0x09 +#define AFE440X_LED2LEDENDC 0x0a +#define AFE440X_ALED1STC 0x0b +#define AFE440X_ALED1ENDC 0x0c +#define AFE440X_LED2CONVST 0x0d +#define AFE440X_LED2CONVEND 0x0e +#define AFE440X_ALED2CONVST 0x0f +#define AFE440X_ALED2CONVEND 0x10 +#define AFE440X_LED1CONVST 0x11 +#define AFE440X_LED1CONVEND 0x12 +#define AFE440X_ALED1CONVST 0x13 +#define AFE440X_ALED1CONVEND 0x14 +#define AFE440X_ADCRSTSTCT0 0x15 +#define AFE440X_ADCRSTENDCT0 0x16 +#define AFE440X_ADCRSTSTCT1 0x17 +#define AFE440X_ADCRSTENDCT1 0x18 +#define AFE440X_ADCRSTSTCT2 0x19 +#define AFE440X_ADCRSTENDCT2 0x1a +#define AFE440X_ADCRSTSTCT3 0x1b +#define AFE440X_ADCRSTENDCT3 0x1c +#define AFE440X_PRPCOUNT 0x1d +#define AFE440X_CONTROL1 0x1e +#define AFE440X_LEDCNTRL 0x22 +#define AFE440X_CONTROL2 0x23 +#define AFE440X_ALARM 0x29 +#define AFE440X_LED2VAL 0x2a +#define AFE440X_ALED2VAL 0x2b +#define AFE440X_LED1VAL 0x2c +#define AFE440X_ALED1VAL 0x2d +#define AFE440X_LED2_ALED2VAL 0x2e +#define AFE440X_LED1_ALED1VAL 0x2f +#define AFE440X_CONTROL3 0x31 +#define AFE440X_PDNCYCLESTC 0x32 +#define AFE440X_PDNCYCLEENDC 0x33 + +/* CONTROL0 register fields */ +#define AFE440X_CONTROL0_REG_READ BIT(0) +#define AFE440X_CONTROL0_TM_COUNT_RST BIT(1) +#define AFE440X_CONTROL0_SW_RESET BIT(3) + +/* CONTROL1 register fields */ +#define AFE440X_CONTROL1_TIMEREN BIT(8) + +/* TIAGAIN register fields */ +#define AFE440X_TIAGAIN_ENSEPGAIN_MASK BIT(15) +#define AFE440X_TIAGAIN_ENSEPGAIN_SHIFT 15 + +/* CONTROL2 register fields */ +#define AFE440X_CONTROL2_PDN_AFE BIT(0) +#define AFE440X_CONTROL2_PDN_RX BIT(1) +#define AFE440X_CONTROL2_DYNAMIC4 BIT(3) +#define AFE440X_CONTROL2_DYNAMIC3 BIT(4) +#define AFE440X_CONTROL2_DYNAMIC2 BIT(14) +#define AFE440X_CONTROL2_DYNAMIC1 BIT(20) + +/* CONTROL3 register fields */ +#define AFE440X_CONTROL3_CLKDIV GENMASK(2, 0) + +/* CONTROL0 values */ +#define AFE440X_CONTROL0_WRITE 0x0 +#define AFE440X_CONTROL0_READ 0x1 + +struct afe440x_reg_info { + unsigned int reg; + unsigned int offreg; + unsigned int shift; + unsigned int mask; +}; + +#define AFE440X_REG_INFO(_reg, _offreg, _sm) \ + { \ + .reg = _reg, \ + .offreg = _offreg, \ + .shift = _sm ## _SHIFT, \ + .mask = _sm ## _MASK, \ + } + +#define AFE440X_INTENSITY_CHAN(_index, _name, _mask) \ + { \ + .type = IIO_INTENSITY, \ + .channel = _index, \ + .address = _index, \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 24, \ + .storagebits = 32, \ + .endianness = IIO_CPU, \ + }, \ + .extend_name = _name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + _mask, \ + } + +#define AFE440X_CURRENT_CHAN(_index, _name) \ + { \ + .type = IIO_CURRENT, \ + .channel = _index, \ + .address = _index, \ + .scan_index = _index, \ + .extend_name = _name, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .output = true, \ + } + +enum afe440x_reg_type { + SIMPLE, + RESISTANCE, + CAPACITANCE, +}; + +struct afe440x_val_table { + int integer; + int fract; +}; + +#define AFE440X_TABLE_ATTR(_name, _table) \ +static ssize_t _name ## _show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + ssize_t len = 0; \ + int i; \ + \ + for (i = 0; i < ARRAY_SIZE(_table); i++) \ + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06u ", \ + _table[i].integer, \ + _table[i].fract); \ + \ + buf[len - 1] = '\n'; \ + \ + return len; \ +} \ +static DEVICE_ATTR_RO(_name) + +struct afe440x_attr { + struct device_attribute dev_attr; + unsigned int reg; + unsigned int shift; + unsigned int mask; + enum afe440x_reg_type type; + const struct afe440x_val_table *val_table; + unsigned int table_size; +}; + +#define to_afe440x_attr(_dev_attr) \ + container_of(_dev_attr, struct afe440x_attr, dev_attr) + +#define AFE440X_ATTR(_name, _reg, _field, _type, _table, _size) \ + struct afe440x_attr afe440x_attr_##_name = { \ + .dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \ + afe440x_show_register, \ + afe440x_store_register), \ + .reg = _reg, \ + .shift = _field ## _SHIFT, \ + .mask = _field ## _MASK, \ + .type = _type, \ + .val_table = _table, \ + .table_size = _size, \ + } + +#endif /* _AFE440X_H */ -- cgit From 535e58f17a765ecbd651913233f210b383676504 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Tue, 2 Feb 2016 11:50:45 -0600 Subject: Documentation: afe4403: Add DT bindings for the AFE4403 heart monitor Add the TI AFE4403 heart monitor DT bindings documentation. Signed-off-by: Andrew F. Davis Signed-off-by: Jonathan Cameron --- .../devicetree/bindings/iio/health/afe4403.txt | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/health/afe4403.txt diff --git a/Documentation/devicetree/bindings/iio/health/afe4403.txt b/Documentation/devicetree/bindings/iio/health/afe4403.txt new file mode 100644 index 000000000000..2fffd70336ba --- /dev/null +++ b/Documentation/devicetree/bindings/iio/health/afe4403.txt @@ -0,0 +1,34 @@ +Texas Instruments AFE4403 Heart rate and Pulse Oximeter + +Required properties: + - compatible : Should be "ti,afe4403". + - reg : SPI chip select address of device. + - tx-supply : Regulator supply to transmitting LEDs. + - interrupt-parent : Phandle to he parent interrupt controller. + - interrupts : The interrupt line the device ADC_RDY pin is + connected to. For details refer to, + ../../interrupt-controller/interrupts.txt. + +Optional properties: + - reset-gpios : GPIO used to reset the device. + For details refer to, ../../gpio/gpio.txt. + +For other required and optional properties of SPI slave nodes +please refer to ../../spi/spi-bus.txt. + +Example: + +&spi0 { + heart_mon@0 { + compatible = "ti,afe4403"; + reg = <0>; + spi-max-frequency = <10000000>; + + tx-supply = <&vbat>; + + interrupt-parent = <&gpio1>; + interrupts = <28 IRQ_TYPE_EDGE_RISING>; + + reset-gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + }; +}; -- cgit From e3e17b773bfe45462b7f3fae20c550025975cb13 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 6 Feb 2016 11:16:28 -0800 Subject: tcp: fastopen: call tcp_fin() if FIN present in SYNACK When we acknowledge a FIN, it is not enough to ack the sequence number and queue the skb into receive queue. We also have to call tcp_fin() to properly update socket state and send proper poll() notifications. It seems we also had the problem if we received a SYN packet with the FIN flag set, but it does not seem an urgent issue, as no known implementation can do that. Fixes: 61d2bcae99f6 ("tcp: fastopen: accept data/FIN present in SYNACK message") Signed-off-by: Eric Dumazet Cc: Yuchung Cheng Cc: Neal Cardwell Signed-off-by: David S. Miller --- include/net/tcp.h | 1 + net/ipv4/tcp_fastopen.c | 3 +++ net/ipv4/tcp_input.c | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 27f4c733116d..479d535609fd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -568,6 +568,7 @@ void tcp_rearm_rto(struct sock *sk); void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req); void tcp_reset(struct sock *sk); void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb); +void tcp_fin(struct sock *sk); /* tcp_timer.c */ void tcp_init_xmit_timers(struct sock *); diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 6a6e11e54bae..fdb286ddba04 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c @@ -154,6 +154,9 @@ void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb) * as we certainly are not changing upper 32bit value (0) */ tp->bytes_received = skb->len; + + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) + tcp_fin(sk); } static struct sock *tcp_fastopen_create_child(struct sock *sk, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4add3eb40e58..8194a250a01e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3995,7 +3995,7 @@ void tcp_reset(struct sock *sk) * * If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT. */ -static void tcp_fin(struct sock *sk) +void tcp_fin(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); -- cgit From eec96d1e2d318bc734728111cfe3b203b58943b9 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sat, 6 Feb 2016 13:35:21 -0600 Subject: iio: health: Add driver for the TI AFE4403 heart monitor Add driver for the TI AFE4403 heart rate monitor and pulse oximeter. This device detects reflected LED light fluctuations and presents an ADC value to the user space for further signal processing. Data sheet located here: http://www.ti.com/product/AFE4403/datasheet Signed-off-by: Andrew F. Davis Signed-off-by: Jonathan Cameron --- drivers/iio/health/Kconfig | 12 + drivers/iio/health/Makefile | 1 + drivers/iio/health/afe4403.c | 708 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 721 insertions(+) create mode 100644 drivers/iio/health/afe4403.c diff --git a/drivers/iio/health/Kconfig b/drivers/iio/health/Kconfig index 632a14b7dd6f..f0c19779ac27 100644 --- a/drivers/iio/health/Kconfig +++ b/drivers/iio/health/Kconfig @@ -7,6 +7,18 @@ menu "Health Sensors" menu "Heart Rate Monitors" +config AFE4403 + tristate "TI AFE4403 Heart Rate Monitor" + depends on SPI_MASTER + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes to choose the Texas Instruments AFE4403 + heart rate monitor and low-cost pulse oximeter. + + To compile this driver as a module, choose M here: the + module will be called afe4403. + config AFE4404 tristate "TI AFE4404 heart rate and pulse oximeter sensor" depends on I2C diff --git a/drivers/iio/health/Makefile b/drivers/iio/health/Makefile index b37c0d5e07b8..9955a2ae8df1 100644 --- a/drivers/iio/health/Makefile +++ b/drivers/iio/health/Makefile @@ -4,5 +4,6 @@ # When adding new entries keep the list in alphabetical order +obj-$(CONFIG_AFE4403) += afe4403.o obj-$(CONFIG_AFE4404) += afe4404.o obj-$(CONFIG_MAX30100) += max30100.o diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c new file mode 100644 index 000000000000..91c046e40d2f --- /dev/null +++ b/drivers/iio/health/afe4403.c @@ -0,0 +1,708 @@ +/* + * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 + +#include "afe440x.h" + +#define AFE4403_DRIVER_NAME "afe4403" + +/* AFE4403 Registers */ +#define AFE4403_TIAGAIN 0x20 +#define AFE4403_TIA_AMB_GAIN 0x21 + +/* AFE4403 GAIN register fields */ +#define AFE4403_TIAGAIN_RES_MASK GENMASK(2, 0) +#define AFE4403_TIAGAIN_RES_SHIFT 0 +#define AFE4403_TIAGAIN_CAP_MASK GENMASK(7, 3) +#define AFE4403_TIAGAIN_CAP_SHIFT 3 + +/* AFE4403 LEDCNTRL register fields */ +#define AFE440X_LEDCNTRL_LED1_MASK GENMASK(15, 8) +#define AFE440X_LEDCNTRL_LED1_SHIFT 8 +#define AFE440X_LEDCNTRL_LED2_MASK GENMASK(7, 0) +#define AFE440X_LEDCNTRL_LED2_SHIFT 0 +#define AFE440X_LEDCNTRL_LED_RANGE_MASK GENMASK(17, 16) +#define AFE440X_LEDCNTRL_LED_RANGE_SHIFT 16 + +/* AFE4403 CONTROL2 register fields */ +#define AFE440X_CONTROL2_PWR_DWN_TX BIT(2) +#define AFE440X_CONTROL2_EN_SLOW_DIAG BIT(8) +#define AFE440X_CONTROL2_DIAG_OUT_TRI BIT(10) +#define AFE440X_CONTROL2_TX_BRDG_MOD BIT(11) +#define AFE440X_CONTROL2_TX_REF_MASK GENMASK(18, 17) +#define AFE440X_CONTROL2_TX_REF_SHIFT 17 + +/* AFE4404 NULL fields */ +#define NULL_MASK 0 +#define NULL_SHIFT 0 + +/* AFE4403 LEDCNTRL values */ +#define AFE440X_LEDCNTRL_RANGE_TX_HALF 0x1 +#define AFE440X_LEDCNTRL_RANGE_TX_FULL 0x2 +#define AFE440X_LEDCNTRL_RANGE_TX_OFF 0x3 + +/* AFE4403 CONTROL2 values */ +#define AFE440X_CONTROL2_TX_REF_025 0x0 +#define AFE440X_CONTROL2_TX_REF_050 0x1 +#define AFE440X_CONTROL2_TX_REF_100 0x2 +#define AFE440X_CONTROL2_TX_REF_075 0x3 + +/* AFE4403 CONTROL3 values */ +#define AFE440X_CONTROL3_CLK_DIV_2 0x0 +#define AFE440X_CONTROL3_CLK_DIV_4 0x2 +#define AFE440X_CONTROL3_CLK_DIV_6 0x3 +#define AFE440X_CONTROL3_CLK_DIV_8 0x4 +#define AFE440X_CONTROL3_CLK_DIV_12 0x5 +#define AFE440X_CONTROL3_CLK_DIV_1 0x7 + +/* AFE4403 TIAGAIN_CAP values */ +#define AFE4403_TIAGAIN_CAP_5_P 0x0 +#define AFE4403_TIAGAIN_CAP_10_P 0x1 +#define AFE4403_TIAGAIN_CAP_20_P 0x2 +#define AFE4403_TIAGAIN_CAP_30_P 0x3 +#define AFE4403_TIAGAIN_CAP_55_P 0x8 +#define AFE4403_TIAGAIN_CAP_155_P 0x10 + +/* AFE4403 TIAGAIN_RES values */ +#define AFE4403_TIAGAIN_RES_500_K 0x0 +#define AFE4403_TIAGAIN_RES_250_K 0x1 +#define AFE4403_TIAGAIN_RES_100_K 0x2 +#define AFE4403_TIAGAIN_RES_50_K 0x3 +#define AFE4403_TIAGAIN_RES_25_K 0x4 +#define AFE4403_TIAGAIN_RES_10_K 0x5 +#define AFE4403_TIAGAIN_RES_1_M 0x6 +#define AFE4403_TIAGAIN_RES_NONE 0x7 + +/** + * struct afe4403_data + * @dev - Device structure + * @spi - SPI device handle + * @regmap - Register map of the device + * @regulator - Pointer to the regulator for the IC + * @trig - IIO trigger for this device + * @irq - ADC_RDY line interrupt number + */ +struct afe4403_data { + struct device *dev; + struct spi_device *spi; + struct regmap *regmap; + struct regulator *regulator; + struct iio_trigger *trig; + int irq; +}; + +enum afe4403_chan_id { + LED1, + ALED1, + LED2, + ALED2, + LED1_ALED1, + LED2_ALED2, + ILED1, + ILED2, +}; + +static const struct afe440x_reg_info afe4403_reg_info[] = { + [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, 0, NULL), + [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, 0, NULL), + [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, 0, NULL), + [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), + [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), + [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), + [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED1), + [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED2), +}; + +static const struct iio_chan_spec afe4403_channels[] = { + /* ADC values */ + AFE440X_INTENSITY_CHAN(LED1, "led1", 0), + AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2, "led2", 0), + AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", 0), + AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), + /* LED current */ + AFE440X_CURRENT_CHAN(ILED1, "led1"), + AFE440X_CURRENT_CHAN(ILED2, "led2"), +}; + +static const struct afe440x_val_table afe4403_res_table[] = { + { 500000 }, { 250000 }, { 100000 }, { 50000 }, + { 25000 }, { 10000 }, { 1000000 }, { 0 }, +}; +AFE440X_TABLE_ATTR(tia_resistance_available, afe4403_res_table); + +static const struct afe440x_val_table afe4403_cap_table[] = { + { 0, 5000 }, { 0, 10000 }, { 0, 20000 }, { 0, 25000 }, + { 0, 30000 }, { 0, 35000 }, { 0, 45000 }, { 0, 50000 }, + { 0, 55000 }, { 0, 60000 }, { 0, 70000 }, { 0, 75000 }, + { 0, 80000 }, { 0, 85000 }, { 0, 95000 }, { 0, 100000 }, + { 0, 155000 }, { 0, 160000 }, { 0, 170000 }, { 0, 175000 }, + { 0, 180000 }, { 0, 185000 }, { 0, 195000 }, { 0, 200000 }, + { 0, 205000 }, { 0, 210000 }, { 0, 220000 }, { 0, 225000 }, + { 0, 230000 }, { 0, 235000 }, { 0, 245000 }, { 0, 250000 }, +}; +AFE440X_TABLE_ATTR(tia_capacitance_available, afe4403_cap_table); + +static ssize_t afe440x_show_register(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + unsigned int reg_val, type; + int vals[2]; + int ret, val_len; + + ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); + if (ret) + return ret; + + reg_val &= afe440x_attr->mask; + reg_val >>= afe440x_attr->shift; + + switch (afe440x_attr->type) { + case SIMPLE: + type = IIO_VAL_INT; + val_len = 1; + vals[0] = reg_val; + break; + case RESISTANCE: + case CAPACITANCE: + type = IIO_VAL_INT_PLUS_MICRO; + val_len = 2; + if (reg_val < afe440x_attr->table_size) { + vals[0] = afe440x_attr->val_table[reg_val].integer; + vals[1] = afe440x_attr->val_table[reg_val].fract; + break; + } + return -EINVAL; + default: + return -EINVAL; + } + + return iio_format_value(buf, type, val_len, vals); +} + +static ssize_t afe440x_store_register(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); + int val, integer, fract, ret; + + ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract); + if (ret) + return ret; + + switch (afe440x_attr->type) { + case SIMPLE: + val = integer; + break; + case RESISTANCE: + case CAPACITANCE: + for (val = 0; val < afe440x_attr->table_size; val++) + if (afe440x_attr->val_table[val].integer == integer && + afe440x_attr->val_table[val].fract == fract) + break; + if (val == afe440x_attr->table_size) + return -EINVAL; + break; + default: + return -EINVAL; + } + + ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, + afe440x_attr->mask, + (val << afe440x_attr->shift)); + if (ret) + return ret; + + return count; +} + +static AFE440X_ATTR(tia_separate_en, AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); + +static AFE440X_ATTR(tia_resistance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); +static AFE440X_ATTR(tia_capacitance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_CAP, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); + +static AFE440X_ATTR(tia_resistance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); +static AFE440X_ATTR(tia_capacitance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); + +static struct attribute *afe440x_attributes[] = { + &afe440x_attr_tia_separate_en.dev_attr.attr, + &afe440x_attr_tia_resistance1.dev_attr.attr, + &afe440x_attr_tia_capacitance1.dev_attr.attr, + &afe440x_attr_tia_resistance2.dev_attr.attr, + &afe440x_attr_tia_capacitance2.dev_attr.attr, + &dev_attr_tia_resistance_available.attr, + &dev_attr_tia_capacitance_available.attr, + NULL +}; + +static const struct attribute_group afe440x_attribute_group = { + .attrs = afe440x_attributes +}; + +static int afe4403_read(struct afe4403_data *afe, unsigned int reg, u32 *val) +{ + u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ}; + u8 rx[3]; + int ret; + + /* Enable reading from the device */ + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + return ret; + + ret = spi_write_then_read(afe->spi, ®, 1, rx, 3); + if (ret) + return ret; + + *val = (rx[0] << 16) | + (rx[1] << 8) | + (rx[2]); + + /* Disable reading from the device */ + tx[3] = AFE440X_CONTROL0_WRITE; + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + return ret; + + return 0; +} + +static int afe4403_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct afe4403_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; + int ret; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = afe4403_read(afe, reg_info.reg, val); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_CHAN_INFO_OFFSET: + ret = regmap_read(afe->regmap, reg_info.offreg, + val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = regmap_read(afe->regmap, reg_info.reg, val); + if (ret) + return ret; + *val &= reg_info.mask; + *val >>= reg_info.shift; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 0; + *val2 = 800000; + return IIO_VAL_INT_PLUS_MICRO; + } + break; + default: + break; + } + + return -EINVAL; +} + +static int afe4403_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct afe4403_data *afe = iio_priv(indio_dev); + const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; + + switch (chan->type) { + case IIO_INTENSITY: + switch (mask) { + case IIO_CHAN_INFO_OFFSET: + return regmap_update_bits(afe->regmap, + reg_info.offreg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + case IIO_CURRENT: + switch (mask) { + case IIO_CHAN_INFO_RAW: + return regmap_update_bits(afe->regmap, + reg_info.reg, + reg_info.mask, + (val << reg_info.shift)); + } + break; + default: + break; + } + + return -EINVAL; +} + +static const struct iio_info afe4403_iio_info = { + .attrs = &afe440x_attribute_group, + .read_raw = afe4403_read_raw, + .write_raw = afe4403_write_raw, + .driver_module = THIS_MODULE, +}; + +static irqreturn_t afe4403_trigger_handler(int irq, void *private) +{ + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct afe4403_data *afe = iio_priv(indio_dev); + int ret, bit, i = 0; + s32 buffer[8]; + u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ}; + u8 rx[3]; + + /* Enable reading from the device */ + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + goto err; + + for_each_set_bit(bit, indio_dev->active_scan_mask, + indio_dev->masklength) { + ret = spi_write_then_read(afe->spi, + &afe4403_reg_info[bit].reg, 1, + rx, 3); + if (ret) + goto err; + + buffer[i++] = (rx[0] << 16) | + (rx[1] << 8) | + (rx[2]); + } + + /* Disable reading from the device */ + tx[3] = AFE440X_CONTROL0_WRITE; + ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0); + if (ret) + goto err; + + iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_trigger_ops afe4403_trigger_ops = { + .owner = THIS_MODULE, +}; + +#define AFE4403_TIMING_PAIRS \ + { AFE440X_LED2STC, 0x000050 }, \ + { AFE440X_LED2ENDC, 0x0003e7 }, \ + { AFE440X_LED1LEDSTC, 0x0007d0 }, \ + { AFE440X_LED1LEDENDC, 0x000bb7 }, \ + { AFE440X_ALED2STC, 0x000438 }, \ + { AFE440X_ALED2ENDC, 0x0007cf }, \ + { AFE440X_LED1STC, 0x000820 }, \ + { AFE440X_LED1ENDC, 0x000bb7 }, \ + { AFE440X_LED2LEDSTC, 0x000000 }, \ + { AFE440X_LED2LEDENDC, 0x0003e7 }, \ + { AFE440X_ALED1STC, 0x000c08 }, \ + { AFE440X_ALED1ENDC, 0x000f9f }, \ + { AFE440X_LED2CONVST, 0x0003ef }, \ + { AFE440X_LED2CONVEND, 0x0007cf }, \ + { AFE440X_ALED2CONVST, 0x0007d7 }, \ + { AFE440X_ALED2CONVEND, 0x000bb7 }, \ + { AFE440X_LED1CONVST, 0x000bbf }, \ + { AFE440X_LED1CONVEND, 0x009c3f }, \ + { AFE440X_ALED1CONVST, 0x000fa7 }, \ + { AFE440X_ALED1CONVEND, 0x001387 }, \ + { AFE440X_ADCRSTSTCT0, 0x0003e8 }, \ + { AFE440X_ADCRSTENDCT0, 0x0003eb }, \ + { AFE440X_ADCRSTSTCT1, 0x0007d0 }, \ + { AFE440X_ADCRSTENDCT1, 0x0007d3 }, \ + { AFE440X_ADCRSTSTCT2, 0x000bb8 }, \ + { AFE440X_ADCRSTENDCT2, 0x000bbb }, \ + { AFE440X_ADCRSTSTCT3, 0x000fa0 }, \ + { AFE440X_ADCRSTENDCT3, 0x000fa3 }, \ + { AFE440X_PRPCOUNT, 0x009c3f }, \ + { AFE440X_PDNCYCLESTC, 0x001518 }, \ + { AFE440X_PDNCYCLEENDC, 0x00991f } + +static const struct reg_sequence afe4403_reg_sequences[] = { + AFE4403_TIMING_PAIRS, + { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN | 0x000007}, + { AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES_1_M }, + { AFE440X_LEDCNTRL, (0x14 << AFE440X_LEDCNTRL_LED1_SHIFT) | + (0x14 << AFE440X_LEDCNTRL_LED2_SHIFT) }, + { AFE440X_CONTROL2, AFE440X_CONTROL2_TX_REF_050 << + AFE440X_CONTROL2_TX_REF_SHIFT }, +}; + +static const struct regmap_range afe4403_yes_ranges[] = { + regmap_reg_range(AFE440X_LED2VAL, AFE440X_LED1_ALED1VAL), +}; + +static const struct regmap_access_table afe4403_volatile_table = { + .yes_ranges = afe4403_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(afe4403_yes_ranges), +}; + +static const struct regmap_config afe4403_regmap_config = { + .reg_bits = 8, + .val_bits = 24, + + .max_register = AFE440X_PDNCYCLEENDC, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &afe4403_volatile_table, +}; + +#ifdef CONFIG_OF +static const struct of_device_id afe4403_of_match[] = { + { .compatible = "ti,afe4403", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, afe4403_of_match); +#endif + +static int afe4403_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, + AFE440X_CONTROL2_PDN_AFE); + if (ret) + return ret; + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static int afe4403_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_update_bits(afe->regmap, AFE440X_CONTROL2, + AFE440X_CONTROL2_PDN_AFE, 0); + if (ret) + return ret; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(afe4403_pm_ops, afe4403_suspend, afe4403_resume); + +static int afe4403_probe(struct spi_device *spi) +{ + struct iio_dev *indio_dev; + struct afe4403_data *afe; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*afe)); + if (!indio_dev) + return -ENOMEM; + + afe = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + + afe->dev = &spi->dev; + afe->spi = spi; + afe->irq = spi->irq; + + afe->regmap = devm_regmap_init_spi(spi, &afe4403_regmap_config); + if (IS_ERR(afe->regmap)) { + dev_err(afe->dev, "Unable to allocate register map\n"); + return PTR_ERR(afe->regmap); + } + + afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); + if (IS_ERR(afe->regulator)) { + dev_err(afe->dev, "Unable to get regulator\n"); + return PTR_ERR(afe->regulator); + } + ret = regulator_enable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to enable regulator\n"); + return ret; + } + + ret = regmap_write(afe->regmap, AFE440X_CONTROL0, + AFE440X_CONTROL0_SW_RESET); + if (ret) { + dev_err(afe->dev, "Unable to reset device\n"); + goto err_disable_reg; + } + + ret = regmap_multi_reg_write(afe->regmap, afe4403_reg_sequences, + ARRAY_SIZE(afe4403_reg_sequences)); + if (ret) { + dev_err(afe->dev, "Unable to set register defaults\n"); + goto err_disable_reg; + } + + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->dev.parent = afe->dev; + indio_dev->channels = afe4403_channels; + indio_dev->num_channels = ARRAY_SIZE(afe4403_channels); + indio_dev->name = AFE4403_DRIVER_NAME; + indio_dev->info = &afe4403_iio_info; + + if (afe->irq > 0) { + afe->trig = devm_iio_trigger_alloc(afe->dev, + "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!afe->trig) { + dev_err(afe->dev, "Unable to allocate IIO trigger\n"); + ret = -ENOMEM; + goto err_disable_reg; + } + + iio_trigger_set_drvdata(afe->trig, indio_dev); + + afe->trig->ops = &afe4403_trigger_ops; + afe->trig->dev.parent = afe->dev; + + ret = iio_trigger_register(afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to register IIO trigger\n"); + goto err_disable_reg; + } + + ret = devm_request_threaded_irq(afe->dev, afe->irq, + iio_trigger_generic_data_rdy_poll, + NULL, IRQF_ONESHOT, + AFE4403_DRIVER_NAME, + afe->trig); + if (ret) { + dev_err(afe->dev, "Unable to request IRQ\n"); + goto err_trig; + } + } + + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + afe4403_trigger_handler, NULL); + if (ret) { + dev_err(afe->dev, "Unable to setup buffer\n"); + goto err_trig; + } + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(afe->dev, "Unable to register IIO device\n"); + goto err_buff; + } + + return 0; + +err_buff: + iio_triggered_buffer_cleanup(indio_dev); +err_trig: + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); +err_disable_reg: + regulator_disable(afe->regulator); + + return ret; +} + +static int afe4403_remove(struct spi_device *spi) +{ + struct iio_dev *indio_dev = spi_get_drvdata(spi); + struct afe4403_data *afe = iio_priv(indio_dev); + int ret; + + iio_device_unregister(indio_dev); + + iio_triggered_buffer_cleanup(indio_dev); + + if (afe->irq > 0) + iio_trigger_unregister(afe->trig); + + ret = regulator_disable(afe->regulator); + if (ret) { + dev_err(afe->dev, "Unable to disable regulator\n"); + return ret; + } + + return 0; +} + +static const struct spi_device_id afe4403_ids[] = { + { "afe4403", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, afe4403_ids); + +static struct spi_driver afe4403_spi_driver = { + .driver = { + .name = AFE4403_DRIVER_NAME, + .of_match_table = of_match_ptr(afe4403_of_match), + .pm = &afe4403_pm_ops, + }, + .probe = afe4403_probe, + .remove = afe4403_remove, + .id_table = afe4403_ids, +}; +module_spi_driver(afe4403_spi_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TI AFE4403 Heart Rate and Pulse Oximeter"); +MODULE_LICENSE("GPL v2"); -- cgit From c8e9b92d2957a1d49abc7b81ba3f89ad530d617b Mon Sep 17 00:00:00 2001 From: Kevin Wern Date: Sat, 16 Jan 2016 13:44:41 -0800 Subject: staging/slicoss: Use ethtool_ops instead of module_param. ethtool_ops has attributes in sub struct ethtool_coalesce that correspond to the parameters intagg_delay and dynamic_intagg. It is preferable to set these properties with ethtool rather than module_param, so create these attributes in adapter and set them using ethtool_coalesce's rx_coalesce_usecs and rx_use_adaptive_coalesce. (Outlined in TODO file) Signed-off-by: Kevin Wern Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slic.h | 2 ++ drivers/staging/slicoss/slicoss.c | 41 +++++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h index c95b3abad646..cc0afeeb68c1 100644 --- a/drivers/staging/slicoss/slic.h +++ b/drivers/staging/slicoss/slic.h @@ -478,6 +478,8 @@ struct adapter { u32 max_isr_xmits; u32 rcv_interrupt_yields; u32 intagg_period; + u32 intagg_delay; + u32 dynamic_intagg; struct inicpm_state *inicpm_info; void *pinicpm_info; struct slic_ifevents if_events; diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index b23a2d1f61a2..c490b7166a8d 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -102,8 +102,7 @@ static char *slic_banner = "Alacritech SLIC Technology(tm) Server and Storage Ac static char *slic_proc_version = "2.0.351 2006/07/14 12:26:00"; static struct base_driver slic_global = { {}, 0, 0, 0, 1, NULL, NULL }; -static int intagg_delay = 100; -static u32 dynamic_intagg; +#define DEFAULT_INTAGG_DELAY 100 static unsigned int rcv_count; #define DRV_NAME "slicoss" @@ -119,17 +118,14 @@ MODULE_AUTHOR(DRV_AUTHOR); MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_LICENSE("Dual BSD/GPL"); -module_param(dynamic_intagg, int, 0); -MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting"); -module_param(intagg_delay, int, 0); -MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay"); - static const struct pci_device_id slic_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) }, { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) }, { 0 } }; +static struct ethtool_ops slic_ethtool_ops; + MODULE_DEVICE_TABLE(pci, slic_pci_tbl); static inline void slic_reg32_write(void __iomem *reg, u32 value, bool flush) @@ -2860,7 +2856,7 @@ static int slic_card_init(struct sliccard *card, struct adapter *adapter) if (slic_global.dynamic_intagg) slic_intagg_set(adapter, 0); else - slic_intagg_set(adapter, intagg_delay); + slic_intagg_set(adapter, adapter->intagg_delay); /* * Initialize ping status to "ok" @@ -2881,6 +2877,26 @@ card_init_err: return status; } +static int slic_get_coalesce(struct net_device *dev, + struct ethtool_coalesce *coalesce) +{ + struct adapter *adapter = netdev_priv(dev); + + adapter->intagg_delay = coalesce->rx_coalesce_usecs; + adapter->dynamic_intagg = coalesce->use_adaptive_rx_coalesce; + return 0; +} + +static int slic_set_coalesce(struct net_device *dev, + struct ethtool_coalesce *coalesce) +{ + struct adapter *adapter = netdev_priv(dev); + + coalesce->rx_coalesce_usecs = adapter->intagg_delay; + coalesce->use_adaptive_rx_coalesce = adapter->dynamic_intagg; + return 0; +} + static void slic_init_driver(void) { if (slic_first_init) { @@ -3069,8 +3085,6 @@ static int slic_entry_probe(struct pci_dev *pcidev, struct sliccard *card = NULL; int pci_using_dac = 0; - slic_global.dynamic_intagg = dynamic_intagg; - err = pci_enable_device(pcidev); if (err) @@ -3112,12 +3126,14 @@ static int slic_entry_probe(struct pci_dev *pcidev, goto err_out_exit_slic_probe; } + netdev->ethtool_ops = &slic_ethtool_ops; SET_NETDEV_DEV(netdev, &pcidev->dev); pci_set_drvdata(pcidev, netdev); adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pcidev = pcidev; + slic_global.dynamic_intagg = adapter->dynamic_intagg; if (pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -3204,5 +3220,10 @@ static void __exit slic_module_cleanup(void) pci_unregister_driver(&slic_driver); } +static struct ethtool_ops slic_ethtool_ops = { + .get_coalesce = slic_get_coalesce, + .set_coalesce = slic_set_coalesce +}; + module_init(slic_module_init); module_exit(slic_module_cleanup); -- cgit From a4b5d606b957c6a58e991de63fe999492de1ab92 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 3 Feb 2016 23:35:23 +0100 Subject: usb: core: rename mutex usb_bus_list_lock to usb_bus_idr_lock Now that usb_bus_list has been removed and switched to idr rename the related mutex accordingly. Signed-off-by: Heiner Kallweit Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 6 +++--- drivers/usb/core/hcd.c | 30 +++++++++++++++--------------- drivers/usb/core/hub.c | 4 ++-- drivers/usb/mon/mon_main.c | 4 ++-- include/linux/usb/hcd.h | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 6118a04f0b84..ef04b50e6bbb 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -620,7 +620,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); /* print devices for all busses */ idr_for_each_entry(&usb_bus_idr, bus, id) { /* recurse through all children of the root hub */ @@ -631,12 +631,12 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, bus->root_hub, bus, 0, 0, 0); usb_unlock_device(bus->root_hub); if (ret < 0) { - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return ret; } total_written += ret; } - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return total_written; } diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index cf3eb22dbeb4..0b8a91004737 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -97,8 +97,8 @@ EXPORT_SYMBOL_GPL (usb_bus_idr); #define USB_MAXBUS 64 /* used when updating list of hcds */ -DEFINE_MUTEX(usb_bus_list_lock); /* exported only for usbfs */ -EXPORT_SYMBOL_GPL (usb_bus_list_lock); +DEFINE_MUTEX(usb_bus_idr_lock); /* exported only for usbfs */ +EXPORT_SYMBOL_GPL (usb_bus_idr_lock); /* used for controlling access to virtual root hubs */ static DEFINE_SPINLOCK(hcd_root_hub_lock); @@ -1014,14 +1014,14 @@ static int usb_register_bus(struct usb_bus *bus) int result = -E2BIG; int busnum; - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); busnum = idr_alloc(&usb_bus_idr, bus, 1, USB_MAXBUS, GFP_KERNEL); if (busnum < 0) { pr_err("%s: failed to get bus number\n", usbcore_name); goto error_find_busnum; } bus->busnum = busnum; - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); usb_notify_add_bus(bus); @@ -1030,7 +1030,7 @@ static int usb_register_bus(struct usb_bus *bus) return 0; error_find_busnum: - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return result; } @@ -1051,9 +1051,9 @@ static void usb_deregister_bus (struct usb_bus *bus) * controller code, as well as having it call this when cleaning * itself up */ - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); idr_remove(&usb_bus_idr, bus->busnum); - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); usb_notify_remove_bus(bus); } @@ -1083,12 +1083,12 @@ static int register_root_hub(struct usb_hcd *hcd) set_bit (devnum, usb_dev->bus->devmap.devicemap); usb_set_device_state(usb_dev, USB_STATE_ADDRESS); - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); dev_dbg (parent_dev, "can't read %s device descriptor %d\n", dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; @@ -1099,7 +1099,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (!retval) { usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); } else if (usb_dev->speed >= USB_SPEED_SUPER) { - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); return retval; @@ -1119,7 +1119,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return retval; } @@ -2885,9 +2885,9 @@ error_create_attr_group: #ifdef CONFIG_PM cancel_work_sync(&hcd->wakeup_work); #endif - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); usb_disconnect(&rhdev); /* Sets rhdev to NULL */ - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); err_register_root_hub: hcd->rh_pollable = 0; clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); @@ -2954,9 +2954,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) cancel_work_sync(&hcd->wakeup_work); #endif - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); usb_disconnect(&rhdev); /* Sets rhdev to NULL */ - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); /* * tasklet_kill() isn't needed here because: diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f912fe6bbc0b..3d46d03a785b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2145,7 +2145,7 @@ static void hub_disconnect_children(struct usb_device *udev) * Something got disconnected. Get rid of it and all of its children. * * If *pdev is a normal device then the parent hub must already be locked. - * If *pdev is a root hub then the caller must hold the usb_bus_list_lock, + * If *pdev is a root hub then the caller must hold the usb_bus_idr_lock, * which protects the set of root hubs as well as the list of buses. * * Only hub drivers (including virtual root hub drivers for host @@ -2443,7 +2443,7 @@ static void set_usb_port_removable(struct usb_device *udev) * enumerated. The device descriptor is available, but not descriptors * for any device configuration. The caller must have locked either * the parent hub (if udev is a normal device) or else the - * usb_bus_list_lock (if udev is a root hub). The parent's pointer to + * usb_bus_idr_lock (if udev is a root hub). The parent's pointer to * udev has already been installed, but udev is not yet visible through * sysfs or other filesystem code. * diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 9b87efb0e50d..33ff49c4cea4 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c @@ -365,11 +365,11 @@ static int __init mon_init(void) } // MOD_INC_USE_COUNT(which_module?); - mutex_lock(&usb_bus_list_lock); + mutex_lock(&usb_bus_idr_lock); idr_for_each_entry(&usb_bus_idr, ubus, id) mon_bus_init(ubus); usb_register_notify(&mon_nb); - mutex_unlock(&usb_bus_list_lock); + mutex_unlock(&usb_bus_idr_lock); return 0; err_reg: diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index c293dd044599..b98f831dcda3 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -632,7 +632,7 @@ extern void usb_set_device_state(struct usb_device *udev, /* exported only within usbcore */ extern struct idr usb_bus_idr; -extern struct mutex usb_bus_list_lock; +extern struct mutex usb_bus_idr_lock; extern wait_queue_head_t usb_kill_urb_queue; -- cgit From b1249ab513017efdff646b26b46b5399bd91773b Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 3 Feb 2016 23:36:33 +0100 Subject: usb: r8a66597: add locking to r8a66597_check_detect_child Use mutex usb_bus_idr_lock to protect idr_find. Signed-off-by: Heiner Kallweit Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 1ef887361ac0..bfa7fa3d2eea 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2099,11 +2099,13 @@ static void r8a66597_check_detect_child(struct r8a66597 *r8a66597, memset(now_map, 0, sizeof(now_map)); + mutex_lock(&usb_bus_idr_lock); bus = idr_find(&usb_bus_idr, hcd->self.busnum); if (bus && bus->root_hub) { collect_usb_address_map(bus->root_hub, now_map); update_usb_address_map(r8a66597, bus->root_hub, now_map); } + mutex_unlock(&usb_bus_idr_lock); } static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf) -- cgit From abb4f8addf1d55f3a63ac84e3d9f609f97e5b9a0 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 5 Feb 2016 15:26:54 +0530 Subject: staging: wilc1000: fix build failure allmodconfig build of alpha, m68k, m32r, tilepro has failed with the error: drivers/staging/wilc1000/wilc_wfi_cfgoperations.c: In function 'wilc_create_wiphy': drivers/staging/wilc1000/wilc_wfi_cfgoperations.c:2632:13: error: 'struct wiphy' has no member named 'wowlan' Looking at other drivers wowlan can be only used when CONFIG_PM is defined. Fixes: 73584a40d748 ("staging: wilc1000: add ops resuem/suspend/wakeup in cfg80211") Cc: Glen Lee Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 4eede2b4e661..28a6ffa6d907 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2629,7 +2629,9 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de sema_init(&(priv->SemHandleUpdateStats), 1); priv->wdev = wdev; wdev->wiphy->max_scan_ssids = MAX_NUM_PROBED_SSID; +#ifdef CONFIG_PM wdev->wiphy->wowlan = &wowlan_support; +#endif wdev->wiphy->max_num_pmkids = WILC_MAX_NUM_PMKIDS; PRINT_INFO(CFG80211_DBG, "Max number of PMKIDs = %d\n", wdev->wiphy->max_num_pmkids); -- cgit From 2bcfdc23c6a418b441a1d17f237e9ea347e2fb1f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 7 Jan 2016 14:46:34 +0200 Subject: mei: bus: remove redundant uuid string in debug messages Remove uuid from the debug messages in bus-fixup.c as this is already part of the device name. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus-fixup.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 020de5919c21..b2d2a6ea576c 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -48,8 +48,7 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO; */ static void number_of_connections(struct mei_cl_device *cldev) { - dev_dbg(&cldev->dev, "running hook %s on %pUl\n", - __func__, mei_me_cl_uuid(cldev->me_cl)); + dev_dbg(&cldev->dev, "running hook %s\n", __func__); if (cldev->me_cl->props.max_number_of_connections > 1) cldev->do_match = 0; @@ -62,8 +61,8 @@ static void number_of_connections(struct mei_cl_device *cldev) */ static void blacklist(struct mei_cl_device *cldev) { - dev_dbg(&cldev->dev, "running hook %s on %pUl\n", - __func__, mei_me_cl_uuid(cldev->me_cl)); + dev_dbg(&cldev->dev, "running hook %s\n", __func__); + cldev->do_match = 0; } @@ -208,8 +207,7 @@ static void mei_nfc(struct mei_cl_device *cldev) bus = cldev->bus; - dev_dbg(bus->dev, "running hook %s: %pUl match=%d\n", - __func__, mei_me_cl_uuid(cldev->me_cl), cldev->do_match); + dev_dbg(&cldev->dev, "running hook %s\n", __func__); mutex_lock(&bus->device_lock); /* we need to connect to INFO GUID */ -- cgit From 13cf988562b0c7f06e0016bea2b5304358397702 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 7 Jan 2016 14:46:36 +0200 Subject: mei: prevent queuing new flow control credit. The MEI FW can receive only one flow control for read. Currently the driver only checks if a flow control credit was already sent and read is pending in the rd_pending queue, but it also has to check if flow control credit already queued in the write control queue to prevent sending more than one flow control credits. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index a6c87c713193..72e32615acd9 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1421,6 +1421,25 @@ out: return 0; } +/** + * mei_cl_is_read_fc_cb - check if read cb is waiting for flow control + * for given host client + * + * @cl: host client + * + * Return: true, if found at least one cb. + */ +static bool mei_cl_is_read_fc_cb(struct mei_cl *cl) +{ + struct mei_device *dev = cl->dev; + struct mei_cl_cb *cb; + + list_for_each_entry(cb, &dev->ctrl_wr_list.list, list) + if (cb->fop_type == MEI_FOP_READ && cb->cl == cl) + return true; + return false; +} + /** * mei_cl_read_start - the start read client message function. * @@ -1445,7 +1464,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp) return -ENODEV; /* HW currently supports only one pending read */ - if (!list_empty(&cl->rd_pending)) + if (!list_empty(&cl->rd_pending) || mei_cl_is_read_fc_cb(cl)) return -EBUSY; if (!mei_me_cl_is_active(cl->me_cl)) { -- cgit From 8b2458f413c429e4c5c4799e02ec2820396aaac4 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Thu, 7 Jan 2016 14:46:37 +0200 Subject: mei: always copy the read buffer if data is ready Copy completed callback content to the user space if we have such callback ready in the beginning of the read. Simplify offset processing logic as byproduct. This is a refinement for: commit 139aacf757fc ("mei: fix read after read scenario") Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/main.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 677d0362f334..36ca15234344 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -159,27 +159,22 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, goto out; } + if (ubuf == NULL) { + rets = -EMSGSIZE; + goto out; + } + if (cl == &dev->iamthif_cl) { rets = mei_amthif_read(dev, file, ubuf, length, offset); goto out; } cb = mei_cl_read_cb(cl, file); - if (cb) { - /* read what left */ - if (cb->buf_idx > *offset) - goto copy_buffer; - /* offset is beyond buf_idx we have no more data return 0 */ - if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { - rets = 0; - goto free; - } - /* Offset needs to be cleaned for contiguous reads*/ - if (cb->buf_idx == 0 && *offset > 0) - *offset = 0; - } else if (*offset > 0) { + if (cb) + goto copy_buffer; + + if (*offset > 0) *offset = 0; - } err = mei_cl_read_start(cl, length, file); if (err && err != -EBUSY) { @@ -231,10 +226,10 @@ copy_buffer: goto free; } - cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld\n", - cb->buf.size, cb->buf_idx); - if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) { - rets = -EMSGSIZE; + cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld offset = %lld\n", + cb->buf.size, cb->buf_idx, *offset); + if (*offset >= cb->buf_idx) { + rets = 0; goto free; } @@ -255,6 +250,7 @@ copy_buffer: free: mei_io_cb_free(cb); + *offset = 0; out: cl_dbg(dev, cl, "end mei read rets = %d\n", rets); -- cgit From b86d1bd8d1a0f67f12b62e5ee724514f19dc6bf8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 7 Jan 2016 14:46:39 +0200 Subject: mei: drop nfc leftovers from the mei driver We left few function prototypes in the header file after moving nfc logic to bus. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/mei_dev.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 4250555d5e72..b54d9d9cacea 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -649,17 +649,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, struct mei_cl_cb *complete_list); int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); -/* - * NFC functions - */ -int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -void mei_nfc_host_exit(struct mei_device *dev); - -/* - * NFC Client UUID - */ -extern const uuid_le mei_nfc_guid; - int mei_wd_send(struct mei_device *dev); int mei_wd_stop(struct mei_device *dev); int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -- cgit From 8477614d9f7c5ce0e871e1aa200d9060a6b8749e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:38 -0800 Subject: of: earlycon: of_setup_earlycon() requires CONFIG_OF_EARLY_FLATTREE DT earlycon is only supported for CONFIG_OF_EARLY_FLATTREE=y; exclude of_setup_earlycon() if not defined. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 3f2423690d01..54419a210dc3 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -204,6 +204,8 @@ static int __init param_setup_earlycon(char *buf) } early_param("earlycon", param_setup_earlycon); +#ifdef CONFIG_OF_EARLY_FLATTREE + int __init of_setup_earlycon(unsigned long addr, int (*setup)(struct earlycon_device *, const char *)) { @@ -227,3 +229,5 @@ int __init of_setup_earlycon(unsigned long addr, register_console(early_console_dev.con); return 0; } + +#endif /* CONFIG_OF_EARLY_FLATTREE */ -- cgit From 2eaa790989e03900298ad24f77f1086dbbc1aebd Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:39 -0800 Subject: earlycon: Use common framework for earlycon declarations Use a single common table of struct earlycon_id for both command line and devicetree. Re-define OF_EARLYCON_DECLARE() macro to instance a unique earlycon declaration (the declaration is only guaranteed to be unique within a compilation unit; separate compilation units must still use unique earlycon names). The semantics of OF_EARLYCON_DECLARE() is different; it declares an earlycon which can matched either on the command line or by devicetree. EARLYCON_DECLARE() is semantically unchanged; it declares an earlycon which is matched by command line only. Remove redundant instances of EARLYCON_DECLARE(). This enables all earlycons to properly initialize struct console with the appropriate name and index, which improves diagnostics and enables direct earlycon-to-console handoff. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 14 +++++++------- drivers/tty/serial/amba-pl011.c | 1 - drivers/tty/serial/arc_uart.c | 1 - drivers/tty/serial/earlycon.c | 10 +--------- drivers/tty/serial/msm_serial.c | 2 -- drivers/tty/serial/samsung.c | 6 ------ drivers/tty/serial/sprd_serial.c | 2 -- include/asm-generic/vmlinux.lds.h | 6 ++---- include/linux/serial_core.h | 22 +++++++++++++--------- 9 files changed, 23 insertions(+), 41 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 655f79db7899..168611867611 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -796,14 +796,13 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) #endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_SERIAL_EARLYCON -extern struct of_device_id __earlycon_of_table[]; static int __init early_init_dt_scan_chosen_serial(void) { int offset; const char *p; int l; - const struct of_device_id *match = __earlycon_of_table; + const struct earlycon_id *match; const void *fdt = initial_boot_params; offset = fdt_path_offset(fdt, "/chosen"); @@ -826,19 +825,20 @@ static int __init early_init_dt_scan_chosen_serial(void) if (offset < 0) return -ENODEV; - while (match->compatible[0]) { + for (match = __earlycon_table; match < __earlycon_table_end; match++) { u64 addr; - if (fdt_node_check_compatible(fdt, offset, match->compatible)) { - match++; + if (!match->compatible[0]) + continue; + + if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - } addr = fdt_translate_address(fdt, offset); if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match->data); + of_setup_earlycon(addr, match->setup); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index c0da0ccbbcf5..de846027ba47 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2327,7 +2327,6 @@ static int __init pl011_early_console_setup(struct earlycon_device *device, device->con->write = pl011_early_write; return 0; } -EARLYCON_DECLARE(pl011, pl011_early_console_setup); OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup); #else diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 03ebe401fff7..3a1de5c87cb4 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -576,7 +576,6 @@ static int __init arc_early_console_setup(struct earlycon_device *dev, dev->con->write = arc_early_serial_write; return 0; } -EARLYCON_DECLARE(arc_uart, arc_early_console_setup); OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup); #endif /* CONFIG_SERIAL_ARC_CONSOLE */ diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 54419a210dc3..d50b70053418 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -19,7 +19,6 @@ #include #include #include -#include #ifdef CONFIG_FIX_EARLYCON_MEM #include @@ -37,13 +36,6 @@ static struct earlycon_device early_console_dev = { .con = &early_con, }; -extern struct earlycon_id __earlycon_table[]; -static const struct earlycon_id __earlycon_table_sentinel - __used __section(__earlycon_table_end); - -static const struct of_device_id __earlycon_of_table_sentinel - __used __section(__earlycon_of_table_end); - static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) { void __iomem *base; @@ -166,7 +158,7 @@ int __init setup_earlycon(char *buf) if (early_con.flags & CON_ENABLED) return -EALREADY; - for (match = __earlycon_table; match->name[0]; match++) { + for (match = __earlycon_table; match < __earlycon_table_end; match++) { size_t len = strlen(match->name); if (strncmp(buf, match->name, len)) diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index dcde955475dc..96d3ce8dc2dc 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -1478,7 +1478,6 @@ msm_serial_early_console_setup(struct earlycon_device *device, const char *opt) device->con->write = msm_serial_early_write; return 0; } -EARLYCON_DECLARE(msm_serial, msm_serial_early_console_setup); OF_EARLYCON_DECLARE(msm_serial, "qcom,msm-uart", msm_serial_early_console_setup); @@ -1500,7 +1499,6 @@ msm_serial_early_console_setup_dm(struct earlycon_device *device, device->con->write = msm_serial_early_write_dm; return 0; } -EARLYCON_DECLARE(msm_serial_dm, msm_serial_early_console_setup_dm); OF_EARLYCON_DECLARE(msm_serial_dm, "qcom,msm-uartdm", msm_serial_early_console_setup_dm); diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index d72cd736bdc6..fd9c47f2f29f 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c @@ -2451,7 +2451,6 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device, } OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart", s3c2410_early_console_setup); -EARLYCON_DECLARE(s3c2410, s3c2410_early_console_setup); /* S3C2412, S3C2440, S3C64xx */ static struct samsung_early_console_data s3c2440_early_console_data = { @@ -2470,9 +2469,6 @@ OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart", s3c2440_early_console_setup); OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart", s3c2440_early_console_setup); -EARLYCON_DECLARE(s3c2412, s3c2440_early_console_setup); -EARLYCON_DECLARE(s3c2440, s3c2440_early_console_setup); -EARLYCON_DECLARE(s3c6400, s3c2440_early_console_setup); /* S5PV210, EXYNOS */ static struct samsung_early_console_data s5pv210_early_console_data = { @@ -2489,8 +2485,6 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart", s5pv210_early_console_setup); OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart", s5pv210_early_console_setup); -EARLYCON_DECLARE(s5pv210, s5pv210_early_console_setup); -EARLYCON_DECLARE(exynos4210, s5pv210_early_console_setup); #endif MODULE_ALIAS("platform:samsung-uart"); diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index ef26c4a60be4..18971063f95f 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -624,8 +624,6 @@ static int __init sprd_early_console_setup( device->con->write = sprd_early_write; return 0; } - -EARLYCON_DECLARE(sprd_serial, sprd_early_console_setup); OF_EARLYCON_DECLARE(sprd_serial, "sprd,sc9836-uart", sprd_early_console_setup); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index c4bd0e2c173c..e9a81a6a109f 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -157,7 +157,7 @@ #define EARLYCON_TABLE() STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__earlycon_table) = .; \ *(__earlycon_table) \ - *(__earlycon_table_end) + VMLINUX_SYMBOL(__earlycon_table_end) = .; #else #define EARLYCON_TABLE() #endif @@ -179,7 +179,6 @@ #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem) #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) #define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method) -#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon) #ifdef CONFIG_ACPI #define ACPI_PROBE_TABLE(name) \ @@ -526,8 +525,7 @@ IRQCHIP_OF_MATCH_TABLE() \ ACPI_PROBE_TABLE(irqchip) \ ACPI_PROBE_TABLE(clksrc) \ - EARLYCON_TABLE() \ - EARLYCON_OF_TABLES() + EARLYCON_TABLE() #define INIT_TEXT \ *(.init.text) \ diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index e03d6ba5e5b4..25e05147f379 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -342,22 +342,26 @@ struct earlycon_device { struct earlycon_id { char name[16]; + char compatible[128]; int (*setup)(struct earlycon_device *, const char *options); } __aligned(32); +extern const struct earlycon_id __earlycon_table[]; +extern const struct earlycon_id __earlycon_table_end[]; + +#define OF_EARLYCON_DECLARE(_name, compat, fn) \ + static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \ + __used __section(__earlycon_table) \ + = { .name = __stringify(_name), \ + .compatible = compat, \ + .setup = fn } + +#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) + extern int setup_earlycon(char *buf); extern int of_setup_earlycon(unsigned long addr, int (*setup)(struct earlycon_device *, const char *)); -#define EARLYCON_DECLARE(_name, func) \ - static const struct earlycon_id __earlycon_##_name \ - __used __section(__earlycon_table) \ - = { .name = __stringify(_name), \ - .setup = func } - -#define OF_EARLYCON_DECLARE(name, compat, fn) \ - _OF_DECLARE(earlycon, name, compat, fn, void *) - struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr, -- cgit From cda64e68240265752c6db22a75f28707dfaf6563 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:40 -0800 Subject: serial: earlycon: Fixup earlycon console name and index Properly initialize the struct console 'name' and 'index' fields for the registering earlycon. For earlycons w/o trailing numerals, the index is set to 0; otherwise, the index is set to the value of the trailing numeral. For example, the 'exynos4210' earlycon name == "exynos" and index == 4210. Earlycons with embedded numerals will have all non-trailing numerals as part of the name; for example, the 's3c2412' earlycon name == "s3c" and index == 2412. This ackward scheme was initially added for the uart8250 earlycon; adopt this scheme for the other earlycon "drivers". Introduce earlycon_init() which performs the string scanning and initializes the name and index fields; encapsulate the other console field initializations within. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index d50b70053418..90b064faa1c4 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -27,9 +27,9 @@ #include static struct console early_con = { - .name = "uart", /* 8250 console switch requires this name */ + .name = "uart", /* fixed up at earlycon registration */ .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1, + .index = 0, }; static struct earlycon_device early_console_dev = { @@ -53,6 +53,25 @@ static void __iomem * __init earlycon_map(unsigned long paddr, size_t size) return base; } +static void __init earlycon_init(struct earlycon_device *device, + const char *name) +{ + struct console *earlycon = device->con; + const char *s; + size_t len; + + /* scan backwards from end of string for first non-numeral */ + for (s = name + strlen(name); + s > name && s[-1] >= '0' && s[-1] <= '9'; + s--) + ; + if (*s) + earlycon->index = simple_strtoul(s, NULL, 10); + len = s - name; + strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name))); + earlycon->data = &early_console_dev; +} + static int __init parse_options(struct earlycon_device *device, char *options) { struct uart_port *port = &device->port; @@ -119,7 +138,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match) if (port->mapbase) port->membase = earlycon_map(port->mapbase, 64); - early_console_dev.con->data = &early_console_dev; + earlycon_init(&early_console_dev, match->name); err = match->setup(&early_console_dev, buf); if (err < 0) return err; -- cgit From 05d961320ba624c98b16d72b32f947307674b341 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:41 -0800 Subject: of: earlycon: Fixup earlycon console name and index Use the console name embedded in the OF earlycon table by the OF_EARLYCON_DECLARE() macro to initialize the struct console 'name' and 'index' fields. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 2 +- drivers/tty/serial/earlycon.c | 6 +++--- include/linux/serial_core.h | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 168611867611..ec1459517de6 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -838,7 +838,7 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match->setup); + of_setup_earlycon(addr, match); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 90b064faa1c4..47e54deb944b 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -218,7 +218,7 @@ early_param("earlycon", param_setup_earlycon); #ifdef CONFIG_OF_EARLY_FLATTREE int __init of_setup_earlycon(unsigned long addr, - int (*setup)(struct earlycon_device *, const char *)) + const struct earlycon_id *match) { int err; struct uart_port *port = &early_console_dev.port; @@ -229,8 +229,8 @@ int __init of_setup_earlycon(unsigned long addr, port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); - early_console_dev.con->data = &early_console_dev; - err = setup(&early_console_dev, NULL); + earlycon_init(&early_console_dev, match->name); + err = match->setup(&early_console_dev, NULL); if (err < 0) return err; if (!early_console_dev.con->write) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 25e05147f379..63fdb55e4c9d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -359,8 +359,7 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, - int (*setup)(struct earlycon_device *, const char *)); +extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match); struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); -- cgit From 4d118c9a866590850dad8689262a95345d2c6e09 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:42 -0800 Subject: of: earlycon: Add options string handling Pass-through any options string in the 'stdout-path' property to the earlycon "driver" setup. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 11 ++++++----- drivers/tty/serial/earlycon.c | 9 +++++++-- include/linux/serial_core.h | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index ec1459517de6..cfd3b35e8d81 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -800,7 +800,7 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) static int __init early_init_dt_scan_chosen_serial(void) { int offset; - const char *p; + const char *p, *q, *options = NULL; int l; const struct earlycon_id *match; const void *fdt = initial_boot_params; @@ -817,11 +817,12 @@ static int __init early_init_dt_scan_chosen_serial(void) if (!p || !l) return -ENOENT; - /* Remove console options if present */ - l = strchrnul(p, ':') - p; + q = strchrnul(p, ':'); + if (*q != '\0') + options = q + 1; /* Get the node specified by stdout-path */ - offset = fdt_path_offset_namelen(fdt, p, l); + offset = fdt_path_offset_namelen(fdt, p, q - p); if (offset < 0) return -ENODEV; @@ -838,7 +839,7 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match); + of_setup_earlycon(addr, match, options); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 47e54deb944b..7509ee34de28 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -218,7 +218,8 @@ early_param("earlycon", param_setup_earlycon); #ifdef CONFIG_OF_EARLY_FLATTREE int __init of_setup_earlycon(unsigned long addr, - const struct earlycon_id *match) + const struct earlycon_id *match, + const char *options) { int err; struct uart_port *port = &early_console_dev.port; @@ -229,8 +230,12 @@ int __init of_setup_earlycon(unsigned long addr, port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); + if (options) { + strlcpy(early_console_dev.options, options, + sizeof(early_console_dev.options)); + } earlycon_init(&early_console_dev, match->name); - err = match->setup(&early_console_dev, NULL); + err = match->setup(&early_console_dev, options); if (err < 0) return err; if (!early_console_dev.con->write) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 63fdb55e4c9d..62a4df05eaca 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -359,7 +359,8 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match); +extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, + const char *options); struct uart_port *uart_get_console(struct uart_port *ports, int nr, struct console *c); -- cgit From 088da2a17619cf0113b62a76ad38c6a14470ffa6 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:43 -0800 Subject: of: earlycon: Initialize port fields from DT properties Read the optional "reg-offset", "reg-shift", "reg-io-width" and endianness properties and initialize the respective struct uart_port field if found. NB: These bindings are common to several drivers and the values merely indicate the default value; the registering earlycon setup() method can simply override the values if required. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 2 +- drivers/tty/serial/earlycon.c | 31 +++++++++++++++++++++++++++++++ include/linux/serial_core.h | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index cfd3b35e8d81..e8fd54a30802 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -839,7 +839,7 @@ static int __init early_init_dt_scan_chosen_serial(void) if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match, options); + of_setup_earlycon(addr, match, offset, options); return 0; } return -ENODEV; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 7509ee34de28..7089667bde93 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_FIX_EARLYCON_MEM #include @@ -219,10 +220,13 @@ early_param("earlycon", param_setup_earlycon); int __init of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, + unsigned long node, const char *options) { int err; struct uart_port *port = &early_console_dev.port; + const __be32 *val; + bool big_endian; spin_lock_init(&port->lock); port->iotype = UPIO_MEM; @@ -230,6 +234,33 @@ int __init of_setup_earlycon(unsigned long addr, port->uartclk = BASE_BAUD * 16; port->membase = earlycon_map(addr, SZ_4K); + val = of_get_flat_dt_prop(node, "reg-offset", NULL); + if (val) + port->mapbase += be32_to_cpu(*val); + val = of_get_flat_dt_prop(node, "reg-shift", NULL); + if (val) + port->regshift = be32_to_cpu(*val); + big_endian = of_get_flat_dt_prop(node, "big-endian", NULL) != NULL || + (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && + of_get_flat_dt_prop(node, "native-endian", NULL) != NULL); + val = of_get_flat_dt_prop(node, "reg-io-width", NULL); + if (val) { + switch (be32_to_cpu(*val)) { + case 1: + port->iotype = UPIO_MEM; + break; + case 2: + port->iotype = UPIO_MEM16; + break; + case 4: + port->iotype = (big_endian) ? UPIO_MEM32BE : UPIO_MEM32; + break; + default: + pr_warn("[%s] unsupported reg-io-width\n", match->name); + return -EINVAL; + } + } + if (options) { strlcpy(early_console_dev.options, options, sizeof(early_console_dev.options)); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 62a4df05eaca..6d1bed821181 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -360,6 +360,7 @@ extern const struct earlycon_id __earlycon_table_end[]; extern int setup_earlycon(char *buf); extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, + unsigned long node, const char *options); struct uart_port *uart_get_console(struct uart_port *ports, int nr, -- cgit From c90fe9c0394b068ceca16f66e9f35bcd8d948295 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:44 -0800 Subject: of: earlycon: Move address translation to of_setup_earlycon() Cleanup the early DT/earlycon separation; remove the 'addr' parameter from of_setup_earlycon() and get the uart phys addr directly with a new wrapper function, of_flat_dt_translate_addr(). Limit fdt_translate_address() to file scope. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 8 +------- drivers/of/fdt_address.c | 11 ++++++++++- drivers/tty/serial/earlycon.c | 12 +++++++++--- include/linux/of_fdt.h | 2 +- include/linux/serial_core.h | 2 +- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index e8fd54a30802..918809e6f913 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -827,19 +827,13 @@ static int __init early_init_dt_scan_chosen_serial(void) return -ENODEV; for (match = __earlycon_table; match < __earlycon_table_end; match++) { - u64 addr; - if (!match->compatible[0]) continue; if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - addr = fdt_translate_address(fdt, offset); - if (addr == OF_BAD_ADDR) - return -ENXIO; - - of_setup_earlycon(addr, match, offset, options); + of_setup_earlycon(match, offset, options); return 0; } return -ENODEV; diff --git a/drivers/of/fdt_address.c b/drivers/of/fdt_address.c index 8d3dc6fbdb7a..dca8f9b93745 100644 --- a/drivers/of/fdt_address.c +++ b/drivers/of/fdt_address.c @@ -161,7 +161,7 @@ static int __init fdt_translate_one(const void *blob, int parent, * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things */ -u64 __init fdt_translate_address(const void *blob, int node_offset) +static u64 __init fdt_translate_address(const void *blob, int node_offset) { int parent, len; const struct of_bus *bus, *pbus; @@ -239,3 +239,12 @@ u64 __init fdt_translate_address(const void *blob, int node_offset) bail: return result; } + +/** + * of_flat_dt_translate_address - translate DT addr into CPU phys addr + * @node: node in the flat blob + */ +u64 __init of_flat_dt_translate_address(unsigned long node) +{ + return fdt_translate_address(initial_boot_params, node); +} diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 7089667bde93..baee9ad59af7 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #ifdef CONFIG_FIX_EARLYCON_MEM @@ -218,8 +219,7 @@ early_param("earlycon", param_setup_earlycon); #ifdef CONFIG_OF_EARLY_FLATTREE -int __init of_setup_earlycon(unsigned long addr, - const struct earlycon_id *match, +int __init of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options) { @@ -227,12 +227,18 @@ int __init of_setup_earlycon(unsigned long addr, struct uart_port *port = &early_console_dev.port; const __be32 *val; bool big_endian; + u64 addr; spin_lock_init(&port->lock); port->iotype = UPIO_MEM; + addr = of_flat_dt_translate_address(node); + if (addr == OF_BAD_ADDR) { + pr_warn("[%s] bad address\n", match->name); + return -ENXIO; + } port->mapbase = addr; port->uartclk = BASE_BAUD * 16; - port->membase = earlycon_map(addr, SZ_4K); + port->membase = earlycon_map(port->mapbase, SZ_4K); val = of_get_flat_dt_prop(node, "reg-offset", NULL); if (val) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index df9ef3801812..2fbe8682a66f 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -88,7 +88,7 @@ extern void unflatten_device_tree(void); extern void unflatten_and_copy_device_tree(void); extern void early_init_devtree(void *); extern void early_get_first_memblock_info(void *, phys_addr_t *); -extern u64 fdt_translate_address(const void *blob, int node_offset); +extern u64 of_flat_dt_translate_address(unsigned long node); extern void of_fdt_limit_memory(int limit); #else /* CONFIG_OF_FLATTREE */ static inline void early_init_fdt_scan_reserved_mem(void) {} diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 6d1bed821181..cbfcf38e220d 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -359,7 +359,7 @@ extern const struct earlycon_id __earlycon_table_end[]; #define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn) extern int setup_earlycon(char *buf); -extern int of_setup_earlycon(unsigned long addr, const struct earlycon_id *match, +extern int of_setup_earlycon(const struct earlycon_id *match, unsigned long node, const char *options); -- cgit From 8e7737393c2fb410ce189c4659498722ef5745f0 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:45 -0800 Subject: serial: earlycon: Common log banner for command line and DT Refactor the command line earlycon banner into earlycon_init() so both earlycon startup methods output an info banner. Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index baee9ad59af7..36b79f1828ab 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -59,6 +59,7 @@ static void __init earlycon_init(struct earlycon_device *device, const char *name) { struct console *earlycon = device->con; + struct uart_port *port = &device->port; const char *s; size_t len; @@ -72,6 +73,19 @@ static void __init earlycon_init(struct earlycon_device *device, len = s - name; strlcpy(earlycon->name, name, min(len + 1, sizeof(earlycon->name))); earlycon->data = &early_console_dev; + + if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || + port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) + pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", + (port->iotype == UPIO_MEM) ? "" : + (port->iotype == UPIO_MEM16) ? "16" : + (port->iotype == UPIO_MEM32) ? "32" : "32be", + (unsigned long long)port->mapbase, + device->options); + else + pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", + port->iobase, + device->options); } static int __init parse_options(struct earlycon_device *device, char *options) @@ -110,19 +124,6 @@ static int __init parse_options(struct earlycon_device *device, char *options) strlcpy(device->options, options, length); } - if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || - port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) - pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", - (port->iotype == UPIO_MEM) ? "" : - (port->iotype == UPIO_MEM16) ? "16" : - (port->iotype == UPIO_MEM32) ? "32" : "32be", - (unsigned long long)port->mapbase, - device->options); - else - pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", - port->iobase, - device->options); - return 0; } -- cgit From b969398490d940a98cec0aefcafb9877dc122182 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:46 -0800 Subject: serial: earlycon: Show the earlycon "driver" in banner Output the earlycon "driver" from the just-parsed console 'name' and 'index' fields. NB: ->mapbase is a resource_size_t so use %pa format specifier Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/earlycon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 36b79f1828ab..067783f0523c 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -76,16 +76,16 @@ static void __init earlycon_init(struct earlycon_device *device, if (port->iotype == UPIO_MEM || port->iotype == UPIO_MEM16 || port->iotype == UPIO_MEM32 || port->iotype == UPIO_MEM32BE) - pr_info("Early serial console at MMIO%s 0x%llx (options '%s')\n", + pr_info("%s%d at MMIO%s %pa (options '%s')\n", + earlycon->name, earlycon->index, (port->iotype == UPIO_MEM) ? "" : (port->iotype == UPIO_MEM16) ? "16" : (port->iotype == UPIO_MEM32) ? "32" : "32be", - (unsigned long long)port->mapbase, - device->options); + &port->mapbase, device->options); else - pr_info("Early serial console at I/O port 0x%lx (options '%s')\n", - port->iobase, - device->options); + pr_info("%s%d at I/O port 0x%lx (options '%s')\n", + earlycon->name, earlycon->index, + port->iobase, device->options); } static int __init parse_options(struct earlycon_device *device, char *options) -- cgit From dc6b576b283e7bdff552af9c0ce66e121c6b4887 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:47 -0800 Subject: serial: 8250_early: Use port->regshift earlycon initializes struct uart_port::regshift to the correct value for UPIO_MEM32 already. Use the port field rather than hard-coded value. This enables broader support for various i/o access methods in 8250 earlycon (eg., omap8250 earlycon). Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_early.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index af62131af21e..180143ce77ce 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -39,15 +39,17 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offset) { + offset <<= port->regshift; + switch (port->iotype) { case UPIO_MEM: return readb(port->membase + offset); case UPIO_MEM16: - return readw(port->membase + (offset << 1)); + return readw(port->membase + offset); case UPIO_MEM32: - return readl(port->membase + (offset << 2)); + return readl(port->membase + offset); case UPIO_MEM32BE: - return ioread32be(port->membase + (offset << 2)); + return ioread32be(port->membase + offset); case UPIO_PORT: return inb(port->iobase + offset); default: @@ -57,18 +59,20 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse static void __init serial8250_early_out(struct uart_port *port, int offset, int value) { + offset <<= port->regshift; + switch (port->iotype) { case UPIO_MEM: writeb(value, port->membase + offset); break; case UPIO_MEM16: - writew(value, port->membase + (offset << 1)); + writew(value, port->membase + offset); break; case UPIO_MEM32: - writel(value, port->membase + (offset << 2)); + writel(value, port->membase + offset); break; case UPIO_MEM32BE: - iowrite32be(value, port->membase + (offset << 2)); + iowrite32be(value, port->membase + offset); break; case UPIO_PORT: outb(value, port->iobase + offset); -- cgit From 0fcc286f6a952d6ec40f74f26fd9cd5d63c25f9e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:48 -0800 Subject: of: earlycon: Log more helpful message if stdout-path node not found Earlycon may fail to initialize for a variety of reasons, most of which log the default early param message. If the stdout-path node is not found, log the path which was not found (and suppress the default early param message). Acked-by: Rob Herring Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/of/fdt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 918809e6f913..e2295b2c9836 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -820,11 +820,14 @@ static int __init early_init_dt_scan_chosen_serial(void) q = strchrnul(p, ':'); if (*q != '\0') options = q + 1; + l = q - p; /* Get the node specified by stdout-path */ - offset = fdt_path_offset_namelen(fdt, p, q - p); - if (offset < 0) - return -ENODEV; + offset = fdt_path_offset_namelen(fdt, p, l); + if (offset < 0) { + pr_warn("earlycon: stdout-path %.*s not found\n", l, p); + return 0; + } for (match = __earlycon_table; match < __earlycon_table_end; match++) { if (!match->compatible[0]) -- cgit From 75d611bf01737d8456093804377e5cb0a60a9038 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 16 Jan 2016 15:23:49 -0800 Subject: serial: 8250_omap: Add omap8250 earlycon Add DT earlycon for 8250_omap driver. This boot console is included for kernels built with CONFIG_SERIAL_EARLYCON=y, CONFIG_OF=y, CONFIG_SERIAL_8250_OMAP=y, and CONFIG_OF_EARLY_FLATTREE=y. This boot console is enabled with the command line option "earlycon" (without "=...") when the DT 'stdout-path' property matches a compatible uart. For example, / { chosen { stdout-path = "serial0:115200"; }; .... aliases { serial0 = &uart0; }; .... ocp : ocp { uart0 : serial@44e09000 { compatible = "ti,omap3-uart"; } }; }; Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_early.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 180143ce77ce..3b3dbdc1b73e 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -149,3 +149,24 @@ EARLYCON_DECLARE(uart8250, early_serial8250_setup); EARLYCON_DECLARE(uart, early_serial8250_setup); OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup); OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); + +#ifdef CONFIG_SERIAL_8250_OMAP + +static int __init early_omap8250_setup(struct earlycon_device *device, + const char *options) +{ + struct uart_port *port = &device->port; + + if (!(device->port.membase || device->port.iobase)) + return -ENODEV; + + port->regshift = 2; + device->con->write = early_serial8250_write; + return 0; +} + +OF_EARLYCON_DECLARE(omap8250, "ti,omap2-uart", early_omap8250_setup); +OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup); +OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup); + +#endif -- cgit From fdd9b8655933c3eb3154fe1ed351c17b654258bd Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Fri, 8 Jan 2016 00:49:21 +0200 Subject: mei: wd: drop the watchdog code from the core mei driver Instead of integrating the iAMT watchdog in the mei core driver we will create a watchdog device on the mei client bus and create a driver for it. This patch removes the watchdog code from the mei core driver. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/Kconfig | 6 +- drivers/misc/mei/Makefile | 1 - drivers/misc/mei/client.c | 12 +- drivers/misc/mei/client.h | 4 - drivers/misc/mei/init.c | 10 +- drivers/misc/mei/interrupt.c | 15 -- drivers/misc/mei/mei_dev.h | 61 +------ drivers/misc/mei/wd.c | 391 ------------------------------------------- 8 files changed, 9 insertions(+), 491 deletions(-) delete mode 100644 drivers/misc/mei/wd.c diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig index d23384dde73b..c49e1d2269af 100644 --- a/drivers/misc/mei/Kconfig +++ b/drivers/misc/mei/Kconfig @@ -1,6 +1,6 @@ config INTEL_MEI tristate "Intel Management Engine Interface" - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI help The Intel Management Engine (Intel ME) provides Manageability, Security and Media services for system containing Intel chipsets. @@ -12,7 +12,7 @@ config INTEL_MEI config INTEL_MEI_ME tristate "ME Enabled Intel Chipsets" select INTEL_MEI - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI help MEI support for ME Enabled Intel chipsets. @@ -37,7 +37,7 @@ config INTEL_MEI_ME config INTEL_MEI_TXE tristate "Intel Trusted Execution Environment with ME Interface" select INTEL_MEI - depends on X86 && PCI && WATCHDOG_CORE + depends on X86 && PCI help MEI Support for Trusted Execution Environment device on Intel SoCs diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index 01447ca21c26..59e6b0aede34 100644 --- a/drivers/misc/mei/Makefile +++ b/drivers/misc/mei/Makefile @@ -9,7 +9,6 @@ mei-objs += interrupt.o mei-objs += client.o mei-objs += main.o mei-objs += amthif.o -mei-objs += wd.o mei-objs += bus.o mei-objs += bus-fixup.o mei-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 72e32615acd9..e069fcaed7aa 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -648,7 +648,7 @@ int mei_cl_unlink(struct mei_cl *cl) if (!cl) return 0; - /* wd and amthif might not be initialized */ + /* amthif might not be initialized */ if (!cl->dev) return 0; @@ -679,17 +679,11 @@ void mei_host_client_init(struct work_struct *work) mutex_lock(&dev->device_lock); - me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid); if (me_cl) mei_amthif_host_init(dev, me_cl); mei_me_cl_put(me_cl); - me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid); - if (me_cl) - mei_wd_host_init(dev, me_cl); - mei_me_cl_put(me_cl); - dev->dev_state = MEI_DEV_ENABLED; dev->reset_count = 0; mutex_unlock(&dev->device_lock); @@ -1153,7 +1147,7 @@ err: * * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. */ -int mei_cl_flow_ctrl_creds(struct mei_cl *cl) +static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) { int rets; @@ -1186,7 +1180,7 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl) * 0 on success * -EINVAL when ctrl credits are <= 0 */ -int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) +static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) { if (WARN_ON(!cl || !cl->me_cl)) return -EINVAL; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 04e1aa39243f..2e90a25f896e 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -18,7 +18,6 @@ #define _MEI_CLIENT_H_ #include -#include #include #include @@ -120,9 +119,6 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, enum mei_cb_file_ops type, struct file *fp); int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); -int mei_cl_flow_ctrl_creds(struct mei_cl *cl); - -int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); /* * MEI input output function prototype */ diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 3edafc8d3ad4..46a4302e5524 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -156,8 +156,7 @@ int mei_reset(struct mei_device *dev) mei_cl_all_wakeup(dev); /* remove entry if already in list */ - dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n"); - mei_cl_unlink(&dev->wd_cl); + dev_dbg(dev->dev, "remove iamthif from the file list.\n"); mei_cl_unlink(&dev->iamthif_cl); mei_amthif_reset_params(dev); } @@ -165,7 +164,6 @@ int mei_reset(struct mei_device *dev) mei_hbm_reset(dev); dev->rd_msg_hdr = 0; - dev->wd_pending = false; if (ret) { dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); @@ -335,16 +333,12 @@ void mei_stop(struct mei_device *dev) mutex_lock(&dev->device_lock); - mei_wd_stop(dev); - dev->dev_state = MEI_DEV_POWER_DOWN; mei_reset(dev); /* move device to disabled state unconditionally */ dev->dev_state = MEI_DEV_DISABLED; mutex_unlock(&dev->device_lock); - - mei_watchdog_unregister(dev); } EXPORT_SYMBOL_GPL(mei_stop); @@ -394,7 +388,6 @@ void mei_device_init(struct mei_device *dev, init_waitqueue_head(&dev->wait_hw_ready); init_waitqueue_head(&dev->wait_pg); init_waitqueue_head(&dev->wait_hbm_start); - init_waitqueue_head(&dev->wait_stop_wd); dev->dev_state = MEI_DEV_INITIALIZING; dev->reset_count = 0; @@ -407,7 +400,6 @@ void mei_device_init(struct mei_device *dev, INIT_WORK(&dev->init_work, mei_host_client_init); INIT_WORK(&dev->reset_work, mei_reset_work); - INIT_LIST_HEAD(&dev->wd_cl.link); INIT_LIST_HEAD(&dev->iamthif_cl.link); mei_io_list_init(&dev->amthif_cmd_list); mei_io_list_init(&dev->amthif_rd_complete_list); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 64b568a0268d..6340dee33052 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -360,21 +360,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) list_move_tail(&cb->list, &cmpl_list->list); } - if (dev->wd_state == MEI_WD_STOPPING) { - dev->wd_state = MEI_WD_IDLE; - wake_up(&dev->wait_stop_wd); - } - - if (mei_cl_is_connected(&dev->wd_cl)) { - if (dev->wd_pending && - mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { - ret = mei_wd_send(dev); - if (ret) - return ret; - dev->wd_pending = false; - } - } - /* complete control write list CB */ dev_dbg(dev->dev, "complete control write list cb.\n"); list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) { diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index b54d9d9cacea..da613268480c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -18,7 +18,7 @@ #define _MEI_DEV_H_ #include -#include +#include #include #include #include @@ -26,33 +26,13 @@ #include "hw.h" #include "hbm.h" -/* - * watch dog definition - */ -#define MEI_WD_HDR_SIZE 4 -#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE -#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) - -#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ -#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ -#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ - -#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ - -#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) - -#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) - /* * AMTHI Client UUID */ extern const uuid_le mei_amthif_guid; -/* - * Watchdog Client UUID - */ -extern const uuid_le mei_wd_guid; +#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) /* * Number of Maximum MEI Clients @@ -78,7 +58,6 @@ extern const uuid_le mei_wd_guid; */ #define MEI_HOST_CLIENT_ID_ANY (-1) #define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ -#define MEI_WD_HOST_CLIENT_ID 1 #define MEI_IAMTHIF_HOST_CLIENT_ID 2 @@ -123,12 +102,6 @@ enum mei_file_transaction_states { MEI_READ_COMPLETE }; -enum mei_wd_states { - MEI_WD_IDLE, - MEI_WD_RUNNING, - MEI_WD_STOPPING, -}; - /** * enum mei_cb_file_ops - file operation associated with the callback * @MEI_FOP_READ: read @@ -404,7 +377,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @wait_hw_ready : wait queue for receive HW ready message form FW * @wait_pg : wait queue for receive PG message from FW * @wait_hbm_start : wait queue for receive HBM start message from FW - * @wait_stop_wd : wait queue for receive WD stop message from FW * * @reset_count : number of consecutive resets * @dev_state : device state @@ -435,12 +407,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * * @allow_fixed_address: allow user space to connect a fixed client * - * @wd_cl : watchdog client - * @wd_state : watchdog client state - * @wd_pending : watchdog command is pending - * @wd_timeout : watchdog expiration timeout - * @wd_data : watchdog message buffer - * * @amthif_cmd_list : amthif list for cmd waiting * @amthif_rd_complete_list : amthif list for reading completed cmd data * @iamthif_file_object : file for current amthif operation @@ -486,7 +452,6 @@ struct mei_device { wait_queue_head_t wait_hw_ready; wait_queue_head_t wait_pg; wait_queue_head_t wait_hbm_start; - wait_queue_head_t wait_stop_wd; /* * mei device states @@ -531,13 +496,6 @@ struct mei_device { bool allow_fixed_address; - struct mei_cl wd_cl; - enum mei_wd_states wd_state; - bool wd_pending; - u16 wd_timeout; - unsigned char wd_data[MEI_WD_START_MSG_SIZE]; - - /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ @@ -649,21 +607,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, struct mei_cl_cb *complete_list); int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); -int mei_wd_send(struct mei_device *dev); -int mei_wd_stop(struct mei_device *dev); -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); -/* - * mei_watchdog_register - Registering watchdog interface - * once we got connection to the WD Client - * @dev: mei device - */ -int mei_watchdog_register(struct mei_device *dev); -/* - * mei_watchdog_unregister - Unregistering watchdog interface - * @dev: mei device - */ -void mei_watchdog_unregister(struct mei_device *dev); - /* * Register Access Function */ diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c deleted file mode 100644 index b346638833b0..000000000000 --- a/drivers/misc/mei/wd.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * - * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2012, 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 - -#include "mei_dev.h" -#include "hbm.h" -#include "client.h" - -static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; -static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; - -/* - * AMT Watchdog Device - */ -#define INTEL_AMT_WATCHDOG_ID "INTCAMT" - -/* UUIDs for AMT F/W clients */ -const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, - 0x9D, 0xA9, 0x15, 0x14, 0xCB, - 0x32, 0xAB); - -static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) -{ - dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); - memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); -} - -/** - * mei_wd_host_init - connect to the watchdog client - * - * @dev: the device structure - * @me_cl: me client - * - * Return: -ENOTTY if wd client cannot be found - * -EIO if write has failed - * 0 on success - */ -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) -{ - struct mei_cl *cl = &dev->wd_cl; - int ret; - - mei_cl_init(cl, dev); - - dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; - dev->wd_state = MEI_WD_IDLE; - - ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); - if (ret < 0) { - dev_info(dev->dev, "wd: failed link client\n"); - return ret; - } - - ret = mei_cl_connect(cl, me_cl, NULL); - if (ret) { - dev_err(dev->dev, "wd: failed to connect = %d\n", ret); - mei_cl_unlink(cl); - return ret; - } - - ret = mei_watchdog_register(dev); - if (ret) { - mei_cl_disconnect(cl); - mei_cl_unlink(cl); - } - return ret; -} - -/** - * mei_wd_send - sends watch dog message to fw. - * - * @dev: the device structure - * - * Return: 0 if success, - * -EIO when message send fails - * -EINVAL when invalid message is to be sent - * -ENODEV on flow control failure - */ -int mei_wd_send(struct mei_device *dev) -{ - struct mei_cl *cl = &dev->wd_cl; - struct mei_msg_hdr hdr; - int ret; - - hdr.host_addr = cl->host_client_id; - hdr.me_addr = mei_cl_me_id(cl); - hdr.msg_complete = 1; - hdr.reserved = 0; - hdr.internal = 0; - - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) - hdr.length = MEI_WD_START_MSG_SIZE; - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) - hdr.length = MEI_WD_STOP_MSG_SIZE; - else { - dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); - return -EINVAL; - } - - ret = mei_write_message(dev, &hdr, dev->wd_data); - if (ret) { - dev_err(dev->dev, "wd: write message failed\n"); - return ret; - } - - ret = mei_cl_flow_ctrl_reduce(cl); - if (ret) { - dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); - return ret; - } - - return 0; -} - -/** - * mei_wd_stop - sends watchdog stop message to fw. - * - * @dev: the device structure - * - * Return: 0 if success - * on error: - * -EIO when message send fails - * -EINVAL when invalid message is to be sent - * -ETIME on message timeout - */ -int mei_wd_stop(struct mei_device *dev) -{ - struct mei_cl *cl = &dev->wd_cl; - int ret; - - if (!mei_cl_is_connected(cl) || - dev->wd_state != MEI_WD_RUNNING) - return 0; - - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); - - dev->wd_state = MEI_WD_STOPPING; - - ret = mei_cl_flow_ctrl_creds(cl); - if (ret < 0) - goto err; - - if (ret && mei_hbuf_acquire(dev)) { - ret = mei_wd_send(dev); - if (ret) - goto err; - dev->wd_pending = false; - } else { - dev->wd_pending = true; - } - - mutex_unlock(&dev->device_lock); - - ret = wait_event_timeout(dev->wait_stop_wd, - dev->wd_state == MEI_WD_IDLE, - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); - mutex_lock(&dev->device_lock); - if (dev->wd_state != MEI_WD_IDLE) { - /* timeout */ - ret = -ETIME; - dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); - goto err; - } - dev_dbg(dev->dev, "wd: stop completed after %u msec\n", - MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); - return 0; -err: - return ret; -} - -/** - * mei_wd_ops_start - wd start command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_start(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - struct mei_cl *cl; - int err = -ENODEV; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - cl = &dev->wd_cl; - - mutex_lock(&dev->device_lock); - - if (dev->dev_state != MEI_DEV_ENABLED) { - dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", - mei_dev_state_str(dev->dev_state)); - goto end_unlock; - } - - if (!mei_cl_is_connected(cl)) { - cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); - goto end_unlock; - } - - mei_wd_set_start_timeout(dev, dev->wd_timeout); - - err = 0; -end_unlock: - mutex_unlock(&dev->device_lock); - return err; -} - -/** - * mei_wd_ops_stop - wd stop command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_stop(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - mutex_lock(&dev->device_lock); - mei_wd_stop(dev); - mutex_unlock(&dev->device_lock); - - return 0; -} - -/** - * mei_wd_ops_ping - wd ping command from the watchdog core. - * - * @wd_dev: watchdog device struct - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_ping(struct watchdog_device *wd_dev) -{ - struct mei_device *dev; - struct mei_cl *cl; - int ret; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - cl = &dev->wd_cl; - - mutex_lock(&dev->device_lock); - - if (!mei_cl_is_connected(cl)) { - cl_err(dev, cl, "wd: not connected.\n"); - ret = -ENODEV; - goto end; - } - - dev->wd_state = MEI_WD_RUNNING; - - ret = mei_cl_flow_ctrl_creds(cl); - if (ret < 0) - goto end; - - /* Check if we can send the ping to HW*/ - if (ret && mei_hbuf_acquire(dev)) { - dev_dbg(dev->dev, "wd: sending ping\n"); - - ret = mei_wd_send(dev); - if (ret) - goto end; - dev->wd_pending = false; - } else { - dev->wd_pending = true; - } - -end: - mutex_unlock(&dev->device_lock); - return ret; -} - -/** - * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. - * - * @wd_dev: watchdog device struct - * @timeout: timeout value to set - * - * Return: 0 if success, negative errno code for failure - */ -static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, - unsigned int timeout) -{ - struct mei_device *dev; - - dev = watchdog_get_drvdata(wd_dev); - if (!dev) - return -ENODEV; - - /* Check Timeout value */ - if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) - return -EINVAL; - - mutex_lock(&dev->device_lock); - - dev->wd_timeout = timeout; - wd_dev->timeout = timeout; - mei_wd_set_start_timeout(dev, dev->wd_timeout); - - mutex_unlock(&dev->device_lock); - - return 0; -} - -/* - * Watchdog Device structs - */ -static const struct watchdog_ops wd_ops = { - .owner = THIS_MODULE, - .start = mei_wd_ops_start, - .stop = mei_wd_ops_stop, - .ping = mei_wd_ops_ping, - .set_timeout = mei_wd_ops_set_timeout, -}; -static const struct watchdog_info wd_info = { - .identity = INTEL_AMT_WATCHDOG_ID, - .options = WDIOF_KEEPALIVEPING | - WDIOF_SETTIMEOUT | - WDIOF_ALARMONLY, -}; - -static struct watchdog_device amt_wd_dev = { - .info = &wd_info, - .ops = &wd_ops, - .timeout = MEI_WD_DEFAULT_TIMEOUT, - .min_timeout = MEI_WD_MIN_TIMEOUT, - .max_timeout = MEI_WD_MAX_TIMEOUT, -}; - - -int mei_watchdog_register(struct mei_device *dev) -{ - - int ret; - - amt_wd_dev.parent = dev->dev; - /* unlock to perserve correct locking order */ - mutex_unlock(&dev->device_lock); - ret = watchdog_register_device(&amt_wd_dev); - mutex_lock(&dev->device_lock); - if (ret) { - dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", - ret); - return ret; - } - - dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); - watchdog_set_drvdata(&amt_wd_dev, dev); - return 0; -} - -void mei_watchdog_unregister(struct mei_device *dev) -{ - if (watchdog_get_drvdata(&amt_wd_dev) == NULL) - return; - - watchdog_set_drvdata(&amt_wd_dev, NULL); - watchdog_unregister_device(&amt_wd_dev); -} - -- cgit From 222818c3d84c1f3190767f5f09f2b9b9a0e0ca7f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 8 Jan 2016 00:49:22 +0200 Subject: watchdog: mei_wdt: implement MEI iAMT watchdog driver Create a driver with the generic watchdog interface for the MEI iAMT watchdog device. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/mei/mei.txt | 12 +- MAINTAINERS | 1 + drivers/watchdog/Kconfig | 15 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/mei_wdt.c | 404 +++++++++++++++++++++++++++++++++ 5 files changed, 427 insertions(+), 6 deletions(-) create mode 100644 drivers/watchdog/mei_wdt.c diff --git a/Documentation/misc-devices/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt index 91c1fa34f48b..2b80a0cd621f 100644 --- a/Documentation/misc-devices/mei/mei.txt +++ b/Documentation/misc-devices/mei/mei.txt @@ -231,15 +231,15 @@ IT knows when a platform crashes even when there is a hard failure on the host. The Intel AMT Watchdog is composed of two parts: 1) Firmware feature - receives the heartbeats and sends an event when the heartbeats stop. - 2) Intel MEI driver - connects to the watchdog feature, configures the - watchdog and sends the heartbeats. + 2) Intel MEI iAMT watchdog driver - connects to the watchdog feature, + configures the watchdog and sends the heartbeats. -The Intel MEI driver uses the kernel watchdog API to configure the Intel AMT -Watchdog and to send heartbeats to it. The default timeout of the +The Intel iAMT watchdog MEI driver uses the kernel watchdog API to configure +the Intel AMT Watchdog and to send heartbeats to it. The default timeout of the watchdog is 120 seconds. -If the Intel AMT Watchdog feature does not exist (i.e. the connection failed), -the Intel MEI driver will disable the sending of heartbeats. +If the Intel AMT is not enabled in the firmware then the watchdog client won't enumerate +on the me client bus and watchdog devices won't be exposed. Supported Chipsets diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..d63b3c773c7d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5751,6 +5751,7 @@ S: Supported F: include/uapi/linux/mei.h F: include/linux/mei_cl_bus.h F: drivers/misc/mei/* +F: drivers/watchdog/mei_wdt.c F: Documentation/misc-devices/mei/* INTEL MIC DRIVERS (mic) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 4f0e7be0da34..57f872122b16 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1212,6 +1212,21 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. +config INTEL_MEI_WDT + tristate "Intel MEI iAMT Watchdog" + depends on INTEL_MEI && X86 + select WATCHDOG_CORE + ---help--- + A device driver for the Intel MEI iAMT watchdog. + + The Intel AMT Watchdog is an OS Health (Hang/Crash) watchdog. + Whenever the OS hangs or crashes, iAMT will send an event + to any subscriber to this event. The watchdog doesn't reset the + the platform. + + To compile this driver as a module, choose M here: + the module will be called mei_wdt. + # M32R Architecture # M68K Architecture diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f566753256ab..efc4f788e0f2 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -126,6 +126,7 @@ obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o obj-$(CONFIG_INTEL_MID_WATCHDOG) += intel-mid_wdt.o +obj-$(CONFIG_INTEL_MEI_WDT) += mei_wdt.o # M32R Architecture diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c new file mode 100644 index 000000000000..32e3e1d55ef3 --- /dev/null +++ b/drivers/watchdog/mei_wdt.c @@ -0,0 +1,404 @@ +/* + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 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. + */ + +#include +#include +#include +#include + +#include +#include + +/* + * iAMT Watchdog Device + */ +#define INTEL_AMT_WATCHDOG_ID "iamt_wdt" + +#define MEI_WDT_DEFAULT_TIMEOUT 120 /* seconds */ +#define MEI_WDT_MIN_TIMEOUT 120 /* seconds */ +#define MEI_WDT_MAX_TIMEOUT 65535 /* seconds */ + +/* Commands */ +#define MEI_MANAGEMENT_CONTROL 0x02 + +/* MEI Management Control version number */ +#define MEI_MC_VERSION_NUMBER 0x10 + +/* Sub Commands */ +#define MEI_MC_START_WD_TIMER_REQ 0x13 +#define MEI_MC_STOP_WD_TIMER_REQ 0x14 + +/** + * enum mei_wdt_state - internal watchdog state + * + * @MEI_WDT_IDLE: wd is idle and not opened + * @MEI_WDT_START: wd was opened, start was called + * @MEI_WDT_RUNNING: wd is expecting keep alive pings + * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE + */ +enum mei_wdt_state { + MEI_WDT_IDLE, + MEI_WDT_START, + MEI_WDT_RUNNING, + MEI_WDT_STOPPING, +}; + +/** + * struct mei_wdt - mei watchdog driver + * @wdd: watchdog device + * + * @cldev: mei watchdog client device + * @state: watchdog internal state + * @timeout: watchdog current timeout + */ +struct mei_wdt { + struct watchdog_device wdd; + + struct mei_cl_device *cldev; + enum mei_wdt_state state; + u16 timeout; +}; + +/* + * struct mei_mc_hdr - Management Control Command Header + * + * @command: Management Control (0x2) + * @bytecount: Number of bytes in the message beyond this byte + * @subcommand: Management Control Subcommand + * @versionnumber: Management Control Version (0x10) + */ +struct mei_mc_hdr { + u8 command; + u8 bytecount; + u8 subcommand; + u8 versionnumber; +}; + +/** + * struct mei_wdt_start_request watchdog start/ping + * + * @hdr: Management Control Command Header + * @timeout: timeout value + * @reserved: reserved (legacy) + */ +struct mei_wdt_start_request { + struct mei_mc_hdr hdr; + u16 timeout; + u8 reserved[17]; +} __packed; + +/** + * struct mei_wdt_stop_request - watchdog stop + * + * @hdr: Management Control Command Header + */ +struct mei_wdt_stop_request { + struct mei_mc_hdr hdr; +} __packed; + +/** + * mei_wdt_ping - send wd start/ping command + * + * @wdt: mei watchdog device + * + * Return: 0 on success, + * negative errno code on failure + */ +static int mei_wdt_ping(struct mei_wdt *wdt) +{ + struct mei_wdt_start_request req; + const size_t req_len = sizeof(req); + int ret; + + memset(&req, 0, req_len); + req.hdr.command = MEI_MANAGEMENT_CONTROL; + req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); + req.hdr.subcommand = MEI_MC_START_WD_TIMER_REQ; + req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; + req.timeout = wdt->timeout; + + ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); + if (ret < 0) + return ret; + + return 0; +} + +/** + * mei_wdt_stop - send wd stop command + * + * @wdt: mei watchdog device + * + * Return: 0 on success, + * negative errno code on failure + */ +static int mei_wdt_stop(struct mei_wdt *wdt) +{ + struct mei_wdt_stop_request req; + const size_t req_len = sizeof(req); + int ret; + + memset(&req, 0, req_len); + req.hdr.command = MEI_MANAGEMENT_CONTROL; + req.hdr.bytecount = req_len - offsetof(struct mei_mc_hdr, subcommand); + req.hdr.subcommand = MEI_MC_STOP_WD_TIMER_REQ; + req.hdr.versionnumber = MEI_MC_VERSION_NUMBER; + + ret = mei_cldev_send(wdt->cldev, (u8 *)&req, req_len); + if (ret < 0) + return ret; + + return 0; +} + +/** + * mei_wdt_ops_start - wd start command from the watchdog core. + * + * @wdd: watchdog device + * + * Return: 0 on success or -ENODEV; + */ +static int mei_wdt_ops_start(struct watchdog_device *wdd) +{ + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + + wdt->state = MEI_WDT_START; + wdd->timeout = wdt->timeout; + return 0; +} + +/** + * mei_wdt_ops_stop - wd stop command from the watchdog core. + * + * @wdd: watchdog device + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wdt_ops_stop(struct watchdog_device *wdd) +{ + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + int ret; + + if (wdt->state != MEI_WDT_RUNNING) + return 0; + + wdt->state = MEI_WDT_STOPPING; + + ret = mei_wdt_stop(wdt); + if (ret) + return ret; + + wdt->state = MEI_WDT_IDLE; + + return 0; +} + +/** + * mei_wdt_ops_ping - wd ping command from the watchdog core. + * + * @wdd: watchdog device + * + * Return: 0 if success, negative errno code on failure + */ +static int mei_wdt_ops_ping(struct watchdog_device *wdd) +{ + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + int ret; + + if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) + return 0; + + ret = mei_wdt_ping(wdt); + if (ret) + return ret; + + wdt->state = MEI_WDT_RUNNING; + + return 0; +} + +/** + * mei_wdt_ops_set_timeout - wd set timeout command from the watchdog core. + * + * @wdd: watchdog device + * @timeout: timeout value to set + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wdt_ops_set_timeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + + struct mei_wdt *wdt = watchdog_get_drvdata(wdd); + + /* valid value is already checked by the caller */ + wdt->timeout = timeout; + wdd->timeout = timeout; + + return 0; +} + +static const struct watchdog_ops wd_ops = { + .owner = THIS_MODULE, + .start = mei_wdt_ops_start, + .stop = mei_wdt_ops_stop, + .ping = mei_wdt_ops_ping, + .set_timeout = mei_wdt_ops_set_timeout, +}; + +/* not const as the firmware_version field need to be retrieved */ +static struct watchdog_info wd_info = { + .identity = INTEL_AMT_WATCHDOG_ID, + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_ALARMONLY, +}; + +/** + * mei_wdt_unregister - unregister from the watchdog subsystem + * + * @wdt: mei watchdog device + */ +static void mei_wdt_unregister(struct mei_wdt *wdt) +{ + watchdog_unregister_device(&wdt->wdd); + watchdog_set_drvdata(&wdt->wdd, NULL); +} + +/** + * mei_wdt_register - register with the watchdog subsystem + * + * @wdt: mei watchdog device + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wdt_register(struct mei_wdt *wdt) +{ + struct device *dev; + int ret; + + if (!wdt || !wdt->cldev) + return -EINVAL; + + dev = &wdt->cldev->dev; + + wdt->wdd.info = &wd_info; + wdt->wdd.ops = &wd_ops; + wdt->wdd.parent = dev; + wdt->wdd.timeout = MEI_WDT_DEFAULT_TIMEOUT; + wdt->wdd.min_timeout = MEI_WDT_MIN_TIMEOUT; + wdt->wdd.max_timeout = MEI_WDT_MAX_TIMEOUT; + + watchdog_set_drvdata(&wdt->wdd, wdt); + ret = watchdog_register_device(&wdt->wdd); + if (ret) { + dev_err(dev, "unable to register watchdog device = %d.\n", ret); + watchdog_set_drvdata(&wdt->wdd, NULL); + } + + return ret; +} + +static int mei_wdt_probe(struct mei_cl_device *cldev, + const struct mei_cl_device_id *id) +{ + struct mei_wdt *wdt; + int ret; + + wdt = kzalloc(sizeof(struct mei_wdt), GFP_KERNEL); + if (!wdt) + return -ENOMEM; + + wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; + wdt->state = MEI_WDT_IDLE; + wdt->cldev = cldev; + mei_cldev_set_drvdata(cldev, wdt); + + ret = mei_cldev_enable(cldev); + if (ret < 0) { + dev_err(&cldev->dev, "Could not enable cl device\n"); + goto err_out; + } + + wd_info.firmware_version = mei_cldev_ver(cldev); + + ret = mei_wdt_register(wdt); + if (ret) + goto err_disable; + + return 0; + +err_disable: + mei_cldev_disable(cldev); + +err_out: + kfree(wdt); + + return ret; +} + +static int mei_wdt_remove(struct mei_cl_device *cldev) +{ + struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + + mei_wdt_unregister(wdt); + + mei_cldev_disable(cldev); + + kfree(wdt); + + return 0; +} + +#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ + 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) + +static struct mei_cl_device_id mei_wdt_tbl[] = { + { .uuid = MEI_UUID_WD, .version = 0x1}, + /* required last entry */ + { } +}; +MODULE_DEVICE_TABLE(mei, mei_wdt_tbl); + +static struct mei_cl_driver mei_wdt_driver = { + .id_table = mei_wdt_tbl, + .name = KBUILD_MODNAME, + + .probe = mei_wdt_probe, + .remove = mei_wdt_remove, +}; + +static int __init mei_wdt_init(void) +{ + int ret; + + ret = mei_cldev_driver_register(&mei_wdt_driver); + if (ret) { + pr_err(KBUILD_MODNAME ": module registration failed\n"); + return ret; + } + return 0; +} + +static void __exit mei_wdt_exit(void) +{ + mei_cldev_driver_unregister(&mei_wdt_driver); +} + +module_init(mei_wdt_init); +module_exit(mei_wdt_exit); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Device driver for Intel MEI iAMT watchdog"); -- cgit From c9cf20ee45602a7a5512b7fbbef5672382790555 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 8 Jan 2016 00:49:23 +0200 Subject: watchdog: mei_wdt: add status debugfs entry Add entry for displaying current watchdog internal state cat /mei_wdt/state IDLE|START|RUNNING|STOPPING Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 32e3e1d55ef3..e7e3f144f2b0 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -54,6 +55,24 @@ enum mei_wdt_state { MEI_WDT_STOPPING, }; +#if IS_ENABLED(CONFIG_DEBUG_FS) +static const char *mei_wdt_state_str(enum mei_wdt_state state) +{ + switch (state) { + case MEI_WDT_IDLE: + return "IDLE"; + case MEI_WDT_START: + return "START"; + case MEI_WDT_RUNNING: + return "RUNNING"; + case MEI_WDT_STOPPING: + return "STOPPING"; + default: + return "unknown"; + } +} +#endif /* CONFIG_DEBUG_FS */ + /** * struct mei_wdt - mei watchdog driver * @wdd: watchdog device @@ -61,6 +80,8 @@ enum mei_wdt_state { * @cldev: mei watchdog client device * @state: watchdog internal state * @timeout: watchdog current timeout + * + * @dbgfs_dir: debugfs dir entry */ struct mei_wdt { struct watchdog_device wdd; @@ -68,6 +89,10 @@ struct mei_wdt { struct mei_cl_device *cldev; enum mei_wdt_state state; u16 timeout; + +#if IS_ENABLED(CONFIG_DEBUG_FS) + struct dentry *dbgfs_dir; +#endif /* CONFIG_DEBUG_FS */ }; /* @@ -310,6 +335,63 @@ static int mei_wdt_register(struct mei_wdt *wdt) return ret; } +#if IS_ENABLED(CONFIG_DEBUG_FS) + +static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct mei_wdt *wdt = file->private_data; + const size_t bufsz = 32; + char buf[bufsz]; + ssize_t pos; + + pos = scnprintf(buf, bufsz, "state: %s\n", + mei_wdt_state_str(wdt->state)); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); +} + +static const struct file_operations dbgfs_fops_state = { + .open = simple_open, + .read = mei_dbgfs_read_state, + .llseek = generic_file_llseek, +}; + +static void dbgfs_unregister(struct mei_wdt *wdt) +{ + debugfs_remove_recursive(wdt->dbgfs_dir); + wdt->dbgfs_dir = NULL; +} + +static int dbgfs_register(struct mei_wdt *wdt) +{ + struct dentry *dir, *f; + + dir = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!dir) + return -ENOMEM; + + wdt->dbgfs_dir = dir; + f = debugfs_create_file("state", S_IRUSR, dir, wdt, &dbgfs_fops_state); + if (!f) + goto err; + + return 0; +err: + dbgfs_unregister(wdt); + return -ENODEV; +} + +#else + +static inline void dbgfs_unregister(struct mei_wdt *wdt) {} + +static inline int dbgfs_register(struct mei_wdt *wdt) +{ + return 0; +} +#endif /* CONFIG_DEBUG_FS */ + static int mei_wdt_probe(struct mei_cl_device *cldev, const struct mei_cl_device_id *id) { @@ -337,6 +419,9 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, if (ret) goto err_disable; + if (dbgfs_register(wdt)) + dev_warn(&cldev->dev, "cannot register debugfs\n"); + return 0; err_disable: @@ -356,6 +441,8 @@ static int mei_wdt_remove(struct mei_cl_device *cldev) mei_cldev_disable(cldev); + dbgfs_unregister(wdt); + kfree(wdt); return 0; -- cgit From e97cdb303c04bfe60283094bdced68a0d363bd5d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 8 Jan 2016 00:49:24 +0200 Subject: mei: bus: whitelist the watchdog client The iAMT WD client has to be whitelisted sice it has two connections and is filtered out by number_of_connections fixup. Also the API has changed for BDW and SKL but firmware haven't updated the protocol version. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus-fixup.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index b2d2a6ea576c..b87323f4bb14 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -35,6 +35,9 @@ static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO; #define MEI_UUID_NFC_HCI UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, \ 0x94, 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c) +#define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \ + 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) + #define MEI_UUID_ANY NULL_UUID_LE /** @@ -66,6 +69,31 @@ static void blacklist(struct mei_cl_device *cldev) cldev->do_match = 0; } +/** + * mei_wd - wd client on the bus, change protocol version + * as the API has changed. + * + * @cldev: me clients device + */ +#if IS_ENABLED(CONFIG_INTEL_MEI_ME) +#include +#include "hw-me-regs.h" +static void mei_wd(struct mei_cl_device *cldev) +{ + struct pci_dev *pdev = to_pci_dev(cldev->dev.parent); + + dev_dbg(&cldev->dev, "running hook %s\n", __func__); + if (pdev->device == MEI_DEV_ID_WPT_LP || + pdev->device == MEI_DEV_ID_SPT || + pdev->device == MEI_DEV_ID_SPT_H) + cldev->me_cl->props.protocol_version = 0x2; + + cldev->do_match = 1; +} +#else +static inline void mei_wd(struct mei_cl_device *cldev) {} +#endif /* CONFIG_INTEL_MEI_ME */ + struct mei_nfc_cmd { u8 command; u8 status; @@ -280,6 +308,7 @@ static struct mei_fixup { MEI_FIXUP(MEI_UUID_ANY, number_of_connections), MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist), MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc), + MEI_FIXUP(MEI_UUID_WD, mei_wd), }; /** -- cgit From 1fba6a594cfd1ea0f1fc8a97e22f43def1505d74 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:49:32 +0100 Subject: TTY: serial/mpsc, stop leaking mappings When mpsc_routing_base, sdma_intr_base, mpsc_base, sdma_base, and brg_base are mapped, they are never unmapped. The condition in the free paths is always 'if (!XXX_base) { unmap }'. Fix it by inverting the condition. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index cadfd1cfae2b..363772992acc 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -1870,12 +1870,12 @@ static int mpsc_shared_map_regs(struct platform_device *pd) static void mpsc_shared_unmap_regs(void) { - if (!mpsc_shared_regs.mpsc_routing_base) { + if (mpsc_shared_regs.mpsc_routing_base) { iounmap(mpsc_shared_regs.mpsc_routing_base); release_mem_region(mpsc_shared_regs.mpsc_routing_base_p, MPSC_ROUTING_REG_BLOCK_SIZE); } - if (!mpsc_shared_regs.sdma_intr_base) { + if (mpsc_shared_regs.sdma_intr_base) { iounmap(mpsc_shared_regs.sdma_intr_base); release_mem_region(mpsc_shared_regs.sdma_intr_base_p, MPSC_SDMA_INTR_REG_BLOCK_SIZE); @@ -2011,15 +2011,15 @@ err: static void mpsc_drv_unmap_regs(struct mpsc_port_info *pi) { - if (!pi->mpsc_base) { + if (pi->mpsc_base) { iounmap(pi->mpsc_base); release_mem_region(pi->mpsc_base_p, MPSC_REG_BLOCK_SIZE); } - if (!pi->sdma_base) { + if (pi->sdma_base) { iounmap(pi->sdma_base); release_mem_region(pi->sdma_base_p, MPSC_SDMA_REG_BLOCK_SIZE); } - if (!pi->brg_base) { + if (pi->brg_base) { iounmap(pi->brg_base); release_mem_region(pi->brg_base_p, MPSC_BRG_REG_BLOCK_SIZE); } -- cgit From bca1481ec4a0014271b7c220f41d7a790654dfbb Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:49:33 +0100 Subject: TTY: serial/mpsc, clean up init/remove functions There is a chain of up to 4 nested ifs in init and remove functions. Instead, make the code linear and use goto's to handle failures. Remove unneeded cast from mpsc_release_port by referencing pi->port directly. And finally, use dev_dbg instead of pr_debug given we have dev->dev node. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 163 ++++++++++++++++++++++------------------------ 1 file changed, 79 insertions(+), 84 deletions(-) diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index 363772992acc..44a23113f469 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -1891,44 +1891,39 @@ static void mpsc_shared_unmap_regs(void) static int mpsc_shared_drv_probe(struct platform_device *dev) { struct mpsc_shared_pdata *pdata; - int rc = -ENODEV; - - if (dev->id == 0) { - rc = mpsc_shared_map_regs(dev); - if (!rc) { - pdata = (struct mpsc_shared_pdata *) - dev_get_platdata(&dev->dev); - - mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; - mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; - mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val; - mpsc_shared_regs.SDMA_INTR_CAUSE_m = - pdata->intr_cause_val; - mpsc_shared_regs.SDMA_INTR_MASK_m = - pdata->intr_mask_val; - - rc = 0; - } - } + int rc; - return rc; + if (dev->id != 0) + return -ENODEV; + + rc = mpsc_shared_map_regs(dev); + if (rc) + return rc; + + pdata = dev_get_platdata(&dev->dev); + + mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val; + mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val; + mpsc_shared_regs.MPSC_TCRR_m= pdata->tcrr_val; + mpsc_shared_regs.SDMA_INTR_CAUSE_m = pdata->intr_cause_val; + mpsc_shared_regs.SDMA_INTR_MASK_m = pdata->intr_mask_val; + + return 0; } static int mpsc_shared_drv_remove(struct platform_device *dev) { - int rc = -ENODEV; + if (dev->id != 0) + return -ENODEV; - if (dev->id == 0) { - mpsc_shared_unmap_regs(); - mpsc_shared_regs.MPSC_MRR_m = 0; - mpsc_shared_regs.MPSC_RCRR_m = 0; - mpsc_shared_regs.MPSC_TCRR_m = 0; - mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0; - mpsc_shared_regs.SDMA_INTR_MASK_m = 0; - rc = 0; - } + mpsc_shared_unmap_regs(); + mpsc_shared_regs.MPSC_MRR_m = 0; + mpsc_shared_regs.MPSC_RCRR_m = 0; + mpsc_shared_regs.MPSC_TCRR_m = 0; + mpsc_shared_regs.SDMA_INTR_CAUSE_m = 0; + mpsc_shared_regs.SDMA_INTR_MASK_m = 0; - return rc; + return 0; } static struct platform_driver mpsc_shared_driver = { @@ -1979,10 +1974,6 @@ static int mpsc_drv_map_regs(struct mpsc_port_info *pi, pi->sdma_base_p = r->start; } else { mpsc_resource_err("SDMA base"); - if (pi->mpsc_base) { - iounmap(pi->mpsc_base); - pi->mpsc_base = NULL; - } goto err; } @@ -1993,19 +1984,19 @@ static int mpsc_drv_map_regs(struct mpsc_port_info *pi, pi->brg_base_p = r->start; } else { mpsc_resource_err("BRG base"); - if (pi->mpsc_base) { - iounmap(pi->mpsc_base); - pi->mpsc_base = NULL; - } - if (pi->sdma_base) { - iounmap(pi->sdma_base); - pi->sdma_base = NULL; - } goto err; } return 0; err: + if (pi->sdma_base) { + iounmap(pi->sdma_base); + pi->sdma_base = NULL; + } + if (pi->mpsc_base) { + iounmap(pi->mpsc_base); + pi->mpsc_base = NULL; + } return -ENOMEM; } @@ -2073,36 +2064,37 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi, static int mpsc_drv_probe(struct platform_device *dev) { - struct mpsc_port_info *pi; - int rc = -ENODEV; - - pr_debug("mpsc_drv_probe: Adding MPSC %d\n", dev->id); - - if (dev->id < MPSC_NUM_CTLRS) { - pi = &mpsc_ports[dev->id]; - - rc = mpsc_drv_map_regs(pi, dev); - if (!rc) { - mpsc_drv_get_platform_data(pi, dev, dev->id); - pi->port.dev = &dev->dev; - - rc = mpsc_make_ready(pi); - if (!rc) { - spin_lock_init(&pi->tx_lock); - rc = uart_add_one_port(&mpsc_reg, &pi->port); - if (!rc) { - rc = 0; - } else { - mpsc_release_port((struct uart_port *) - pi); - mpsc_drv_unmap_regs(pi); - } - } else { - mpsc_drv_unmap_regs(pi); - } - } - } + struct mpsc_port_info *pi; + int rc; + + dev_dbg(&dev->dev, "mpsc_drv_probe: Adding MPSC %d\n", dev->id); + + if (dev->id >= MPSC_NUM_CTLRS) + return -ENODEV; + + pi = &mpsc_ports[dev->id]; + + rc = mpsc_drv_map_regs(pi, dev); + if (rc) + return rc; + mpsc_drv_get_platform_data(pi, dev, dev->id); + pi->port.dev = &dev->dev; + + rc = mpsc_make_ready(pi); + if (rc) + goto err_unmap; + + spin_lock_init(&pi->tx_lock); + rc = uart_add_one_port(&mpsc_reg, &pi->port); + if (rc) + goto err_relport; + + return 0; +err_relport: + mpsc_release_port(&pi->port); +err_unmap: + mpsc_drv_unmap_regs(pi); return rc; } @@ -2124,19 +2116,22 @@ static int __init mpsc_drv_init(void) memset(&mpsc_shared_regs, 0, sizeof(mpsc_shared_regs)); rc = uart_register_driver(&mpsc_reg); - if (!rc) { - rc = platform_driver_register(&mpsc_shared_driver); - if (!rc) { - rc = platform_driver_register(&mpsc_driver); - if (rc) { - platform_driver_unregister(&mpsc_shared_driver); - uart_unregister_driver(&mpsc_reg); - } - } else { - uart_unregister_driver(&mpsc_reg); - } - } + if (rc) + return rc; + + rc = platform_driver_register(&mpsc_shared_driver); + if (rc) + goto err_unreg_uart; + rc = platform_driver_register(&mpsc_driver); + if (rc) + goto err_unreg_plat; + + return 0; +err_unreg_plat: + platform_driver_unregister(&mpsc_shared_driver); +err_unreg_uart: + uart_unregister_driver(&mpsc_reg); return rc; } device_initcall(mpsc_drv_init); -- cgit From 6f3689fb5940d0679bcc50bcb47dbb0deae9d5e7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:49:34 +0100 Subject: TTY: serial/mpsc, remove unused fields c_iflag and c_cflag are set, but unused. Remove. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpsc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/tty/serial/mpsc.c b/drivers/tty/serial/mpsc.c index 44a23113f469..4a3021bcc859 100644 --- a/drivers/tty/serial/mpsc.c +++ b/drivers/tty/serial/mpsc.c @@ -137,8 +137,6 @@ struct mpsc_port_info { /* Internal driver state for this ctlr */ u8 ready; u8 rcv_data; - tcflag_t c_iflag; /* save termios->c_iflag */ - tcflag_t c_cflag; /* save termios->c_cflag */ /* Info passed in from platform */ u8 mirror_regs; /* Need to mirror regs? */ @@ -1407,9 +1405,6 @@ static void mpsc_set_termios(struct uart_port *port, struct ktermios *termios, ulong flags; u32 chr_bits, stop_bits, par; - pi->c_iflag = termios->c_iflag; - pi->c_cflag = termios->c_cflag; - switch (termios->c_cflag & CSIZE) { case CS5: chr_bits = MPSC_MPCR_CL_5; -- cgit From aa3188d017d14e8eddc375ef2cc26fefb0b1ecf6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:52:48 +0100 Subject: TTY: 8250_pnp, constify tables Make modem_names and base static const. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 658b392d1170..e813a874c26f 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -380,16 +380,16 @@ static const struct pnp_device_id pnp_dev_table[] = { MODULE_DEVICE_TABLE(pnp, pnp_dev_table); -static char *modem_names[] = { +static const char *modem_names[] = { "MODEM", "Modem", "modem", "FAX", "Fax", "fax", "56K", "56k", "K56", "33.6", "28.8", "14.4", "33,600", "28,800", "14,400", "33.600", "28.800", "14.400", "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL }; -static int check_name(char *name) +static int check_name(const char *name) { - char **tmp; + const char **tmp; for (tmp = modem_names; *tmp; tmp++) if (strstr(name, *tmp)) @@ -400,7 +400,7 @@ static int check_name(char *name) static int check_resources(struct pnp_dev *dev) { - resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; + static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; int i; for (i = 0; i < ARRAY_SIZE(base); i++) { -- cgit From 1497f2ce16700b773744b4ec1c12f1acaeafb5ae Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:52:49 +0100 Subject: TTY: 8250_pnp, make checks bool Since check_name and check_resources return only 0/1, switch them to bool/true/false. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index e813a874c26f..f6332de4e3e3 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -387,28 +387,28 @@ static const char *modem_names[] = { "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL }; -static int check_name(const char *name) +static bool check_name(const char *name) { const char **tmp; for (tmp = modem_names; *tmp; tmp++) if (strstr(name, *tmp)) - return 1; + return true; - return 0; + return false; } -static int check_resources(struct pnp_dev *dev) +static bool check_resources(struct pnp_dev *dev) { static const resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(base); i++) { if (pnp_possible_config(dev, IORESOURCE_IO, base[i], 8)) - return 1; + return true; } - return 0; + return false; } /* -- cgit From e57c25367e56feca96f8959775503cf7747a7dbd Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:52:50 +0100 Subject: TTY: xtensa/iss/console, remove unused _INLINE_ definition This is a remnant from the dark age. Nobody uses the macro now, so remove. Signed-off-by: Jiri Slaby Cc: Chris Zankel Cc: Max Filippov Cc: Signed-off-by: Greg Kroah-Hartman --- arch/xtensa/platforms/iss/console.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 70cb408bc20d..c54505dcf4db 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c @@ -28,10 +28,6 @@ #include #include -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - #define SERIAL_MAX_NUM_LINES 1 #define SERIAL_TIMER_VALUE (HZ / 10) -- cgit From d4dbe374f430156738d34e4572c58f387d558e83 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:06 +0100 Subject: TTY: serial/m32r_sio, disband m32r_sio.h The only needed information from the header is struct old_serial_port. Move it to m32r_sio.c, make it const and anonymous. And kill the rest from the header as it is dead stuff. Given m32r_sio_suspend_port and m32r_sio_resume_port are local to m32r_sio.c and unused, kill them from .c too. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 37 +++++++++----------------------- drivers/tty/serial/m32r_sio.h | 49 ------------------------------------------- 2 files changed, 10 insertions(+), 76 deletions(-) delete mode 100644 drivers/tty/serial/m32r_sio.h diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 0eeb64f2499c..3c76ffc2d10a 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -47,7 +47,6 @@ #define BAUD_RATE 115200 #include -#include "m32r_sio.h" #include "m32r_sio_reg.h" /* @@ -98,7 +97,16 @@ #endif /* !CONFIG_PLAT_USRV */ -static struct old_serial_port old_serial_port[] = { +static const struct { + unsigned int uart; + unsigned int baud_base; + unsigned int port; + unsigned int irq; + unsigned int flags; + unsigned char io_type; + unsigned char __iomem *iomem_base; + unsigned short iomem_reg_shift; +} old_serial_port[] = { SERIAL_PORT_DFNS }; @@ -1112,28 +1120,6 @@ static struct uart_driver m32r_sio_reg = { .cons = M32R_SIO_CONSOLE, }; -/** - * m32r_sio_suspend_port - suspend one serial port - * @line: serial line number - * - * Suspend one serial port. - */ -void m32r_sio_suspend_port(int line) -{ - uart_suspend_port(&m32r_sio_reg, &m32r_sio_ports[line].port); -} - -/** - * m32r_sio_resume_port - resume one serial port - * @line: serial line number - * - * Resume one serial port. - */ -void m32r_sio_resume_port(int line) -{ - uart_resume_port(&m32r_sio_reg, &m32r_sio_ports[line].port); -} - static int __init m32r_sio_init(void) { int ret, i; @@ -1163,8 +1149,5 @@ static void __exit m32r_sio_exit(void) module_init(m32r_sio_init); module_exit(m32r_sio_exit); -EXPORT_SYMBOL(m32r_sio_suspend_port); -EXPORT_SYMBOL(m32r_sio_resume_port); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic M32R SIO serial driver"); diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/m32r_sio.h deleted file mode 100644 index 8129824496c6..000000000000 --- a/drivers/tty/serial/m32r_sio.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * m32r_sio.h - * - * Driver for M32R serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * Based on drivers/serial/8250.h. - * - * Copyright (C) 2001 Russell King. - * Copyright (C) 2004 Hirokazu Takata - * - * 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 - -struct m32r_sio_probe { - struct module *owner; - int (*pci_init_one)(struct pci_dev *dev); - void (*pci_remove_one)(struct pci_dev *dev); - void (*pnp_init)(void); -}; - -int m32r_sio_register_probe(struct m32r_sio_probe *probe); -void m32r_sio_unregister_probe(struct m32r_sio_probe *probe); -void m32r_sio_get_irq_map(unsigned int *map); -void m32r_sio_suspend_port(int line); -void m32r_sio_resume_port(int line); - -struct old_serial_port { - unsigned int uart; - unsigned int baud_base; - unsigned int port; - unsigned int irq; - unsigned int flags; - unsigned char io_type; - unsigned char __iomem *iomem_base; - unsigned short iomem_reg_shift; -}; - -#define _INLINE_ inline - -#define PROBE_RSA (1 << 0) -#define PROBE_ANY (~0) - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) -- cgit From c8e7d143d519724b3bf5b86615eca2962b77a826 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:07 +0100 Subject: TTY: serial/m32r_sio, simplify old_serial_port The only variables in old_serial_port are port and irq. So make old_serial_port contain only those two and move the initialization of the rest to the place where old_serial_port is actually read. Also get rid of SERIAL_PORT_DFNS. It is ugly and having the initializer where it belongs makes more sense. Finally, use already defined UART_NR in the loop. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 57 ++++++++++++------------------------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 3c76ffc2d10a..835b5697a455 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -66,48 +66,22 @@ #define PASS_LIMIT 256 -#define BASE_BAUD 115200 - /* Standard COM flags */ #define STD_COM_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST) -/* - * SERIAL_PORT_DFNS tells us about built-in ports that have no - * standard enumeration mechanism. Platforms that can find all - * serial ports via mechanisms like ACPI or PCI need not supply it. - */ -#if defined(CONFIG_PLAT_USRV) - -#define SERIAL_PORT_DFNS \ - /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0x3F8, PLD_IRQ_UART0, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, PLD_IRQ_UART1, STD_COM_FLAGS }, /* ttyS1 */ - -#else /* !CONFIG_PLAT_USRV */ - -#if defined(CONFIG_SERIAL_M32R_PLDSIO) -#define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV, \ - STD_COM_FLAGS }, /* ttyS0 */ -#else -#define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, M32R_SIO_OFFSET, M32R_IRQ_SIO0_R, \ - STD_COM_FLAGS }, /* ttyS0 */ -#endif - -#endif /* !CONFIG_PLAT_USRV */ - static const struct { - unsigned int uart; - unsigned int baud_base; unsigned int port; unsigned int irq; - unsigned int flags; - unsigned char io_type; - unsigned char __iomem *iomem_base; - unsigned short iomem_reg_shift; } old_serial_port[] = { - SERIAL_PORT_DFNS +#if defined(CONFIG_PLAT_USRV) + /* PORT IRQ FLAGS */ + { 0x3F8, PLD_IRQ_UART0 }, /* ttyS0 */ + { 0x2F8, PLD_IRQ_UART1 }, /* ttyS1 */ +#elif defined(CONFIG_SERIAL_M32R_PLDSIO) + { ((unsigned long)PLD_ESIO0CR), PLD_IRQ_SIO0_RCV }, /* ttyS0 */ +#else + { M32R_SIO_OFFSET, M32R_IRQ_SIO0_R }, /* ttyS0 */ +#endif }; #define UART_NR ARRAY_SIZE(old_serial_port) @@ -959,15 +933,14 @@ static void __init m32r_sio_init_ports(void) return; first = 0; - for (i = 0, up = m32r_sio_ports; i < ARRAY_SIZE(old_serial_port); - i++, up++) { + for (i = 0, up = m32r_sio_ports; i < UART_NR; i++, up++) { up->port.iobase = old_serial_port[i].port; up->port.irq = irq_canonicalize(old_serial_port[i].irq); - up->port.uartclk = old_serial_port[i].baud_base * 16; - up->port.flags = old_serial_port[i].flags; - up->port.membase = old_serial_port[i].iomem_base; - up->port.iotype = old_serial_port[i].io_type; - up->port.regshift = old_serial_port[i].iomem_reg_shift; + up->port.uartclk = BAUD_RATE * 16; + up->port.flags = STD_COM_FLAGS; + up->port.membase = 0; + up->port.iotype = 0; + up->port.regshift = 0; up->port.ops = &m32r_sio_pops; } } -- cgit From ad245aa2750212a8daae44d6dc2f3d34b94d74c6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:08 +0100 Subject: TTY: serial/m32r_sio, remove debug macros DEBUG_AUTOCONF is unused. Switch DEBUG_INTR to pr_debug. This is only enabled with DEBUG or dynamic debug when explicitly asked for. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 835b5697a455..6b1303505667 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -49,21 +49,6 @@ #include #include "m32r_sio_reg.h" -/* - * Debugging. - */ -#if 0 -#define DEBUG_AUTOCONF(fmt...) printk(fmt) -#else -#define DEBUG_AUTOCONF(fmt...) do { } while (0) -#endif - -#if 0 -#define DEBUG_INTR(fmt...) printk(fmt) -#else -#define DEBUG_INTR(fmt...) do { } while (0) -#endif - #define PASS_LIMIT 256 /* Standard COM flags */ @@ -334,7 +319,7 @@ static void receive_chars(struct uart_sio_port *up, int *status) } if (*status & UART_LSR_BI) { - DEBUG_INTR("handling break...."); + pr_debug("handling break....\n"); flag = TTY_BREAK; } else if (*status & UART_LSR_PE) flag = TTY_PARITY; @@ -395,7 +380,7 @@ static void transmit_chars(struct uart_sio_port *up) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(&up->port); - DEBUG_INTR("THRE..."); + pr_debug("THRE...\n"); if (uart_circ_empty(xmit)) m32r_sio_stop_tx(&up->port); @@ -407,7 +392,7 @@ static void transmit_chars(struct uart_sio_port *up) static inline void m32r_sio_handle_port(struct uart_sio_port *up, unsigned int status) { - DEBUG_INTR("status = %x...", status); + pr_debug("status = %x...\n", status); if (status & 0x04) receive_chars(up, &status); @@ -435,7 +420,7 @@ static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) struct list_head *l, *end = NULL; int pass_counter = 0; - DEBUG_INTR("m32r_sio_interrupt(%d)...", irq); + pr_debug("m32r_sio_interrupt(%d)...\n", irq); #ifdef CONFIG_SERIAL_M32R_PLDSIO // if (irq == PLD_IRQ_SIO0_SND) @@ -475,7 +460,7 @@ static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) spin_unlock(&i->lock); - DEBUG_INTR("end.\n"); + pr_debug("end.\n"); return IRQ_HANDLED; } -- cgit From b85e5ed5621b3a19f1ca20b30fd64803aa3d5ff8 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 12 Jan 2016 10:59:09 +0100 Subject: TTY: serial/m32r_sio, remove unused members struct uart_sio_port has a lots of unused members. Some of them are set to some constant but never read. Remove all those. This includes removal of uart_ops->pm handler as we never handle pm (pm was never set). Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/m32r_sio.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 6b1303505667..68765f7c2645 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c @@ -75,19 +75,7 @@ struct uart_sio_port { struct uart_port port; struct timer_list timer; /* "no irq" timer */ struct list_head list; /* ports on this IRQ */ - unsigned short rev; - unsigned char acr; unsigned char ier; - unsigned char lcr; - unsigned char mcr_mask; /* mask of user bits */ - unsigned char mcr_force; /* mask of forced bits */ - unsigned char lsr_break_flag; - - /* - * We provide a per-port pm hook. - */ - void (*pm)(struct uart_port *port, - unsigned int state, unsigned int old); }; struct irq_info { @@ -312,12 +300,6 @@ static void receive_chars(struct uart_sio_port *up, int *status) */ *status &= up->port.read_status_mask; - if (up->port.line == up->port.cons->index) { - /* Recover the break flag from console xmit */ - *status |= up->lsr_break_flag; - up->lsr_break_flag = 0; - } - if (*status & UART_LSR_BI) { pr_debug("handling break....\n"); flag = TTY_BREAK; @@ -749,20 +731,9 @@ static void m32r_sio_set_termios(struct uart_port *port, serial_out(up, UART_IER, up->ier); - up->lcr = cval; /* Save LCR */ spin_unlock_irqrestore(&up->port.lock, flags); } -static void m32r_sio_pm(struct uart_port *port, unsigned int state, - unsigned int oldstate) -{ - struct uart_sio_port *up = - container_of(port, struct uart_sio_port, port); - - if (up->pm) - up->pm(port, state, oldstate); -} - /* * Resource handling. This is complicated by the fact that resources * depend on the port type. Maybe we should be claiming the standard @@ -899,7 +870,6 @@ static struct uart_ops m32r_sio_pops = { .startup = m32r_sio_startup, .shutdown = m32r_sio_shutdown, .set_termios = m32r_sio_set_termios, - .pm = m32r_sio_pm, .release_port = m32r_sio_release_port, .request_port = m32r_sio_request_port, .config_port = m32r_sio_config_port, @@ -944,9 +914,6 @@ static void __init m32r_sio_register_ports(struct uart_driver *drv) init_timer(&up->timer); up->timer.function = m32r_sio_timeout; - up->mcr_mask = ~0; - up->mcr_force = 0; - uart_add_one_port(drv, &up->port); } } -- cgit From a07a70bcb72e4a766c8d3173986a773cef842d30 Mon Sep 17 00:00:00 2001 From: "Matwey V. Kornilov" Date: Mon, 1 Feb 2016 21:09:20 +0300 Subject: tty: Move serial8250_stop_rx() in front of serial8250_start_tx() Software RS485 emultaion is to be added in the following commit. serial8250_start_tx() will need to refer serial8250_stop_rx(). Move serial8250_stop_rx() in front of serial8250_start_tx() in order to avoid function forward declaration. Signed-off-by: Matwey V. Kornilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 0bd3c6baa300..04681e5745de 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1304,6 +1304,19 @@ static void autoconfig_irq(struct uart_8250_port *up) port->irq = (irq > 0) ? irq : 0; } +static void serial8250_stop_rx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + serial8250_rpm_get(up); + + up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); + up->port.read_status_mask &= ~UART_LSR_DR; + serial_port_out(port, UART_IER, up->ier); + + serial8250_rpm_put(up); +} + static inline void __stop_tx(struct uart_8250_port *p) { if (p->ier & UART_IER_THRI) { @@ -1371,19 +1384,6 @@ static void serial8250_unthrottle(struct uart_port *port) port->unthrottle(port); } -static void serial8250_stop_rx(struct uart_port *port) -{ - struct uart_8250_port *up = up_to_u8250p(port); - - serial8250_rpm_get(up); - - up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); - up->port.read_status_mask &= ~UART_LSR_DR; - serial_port_out(port, UART_IER, up->ier); - - serial8250_rpm_put(up); -} - static void serial8250_disable_ms(struct uart_port *port) { struct uart_8250_port *up = -- cgit From e490c9144cfaa8e2242c1e5d5187230928f27417 Mon Sep 17 00:00:00 2001 From: "Matwey V. Kornilov" Date: Mon, 1 Feb 2016 21:09:21 +0300 Subject: tty: Add software emulated RS485 support for 8250 Implementation of software emulation of RS485 direction handling is based on omap_serial driver. Before and after transmission RTS is set to the appropriate value. Note that before calling serial8250_em485_init() the caller has to ensure that UART will interrupt when shift register empty. Otherwise, emultaion cannot be used. Both serial8250_em485_init() and serial8250_em485_destroy() are idempotent functions. Signed-off-by: Matwey V. Kornilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 2 + drivers/tty/serial/8250/8250_port.c | 223 +++++++++++++++++++++++++++++++++++- include/linux/serial_8250.h | 8 ++ 3 files changed, 229 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index d54dcd87c67e..ce587c03efc3 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -117,6 +117,8 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value) struct uart_8250_port *serial8250_get_port(int line); void serial8250_rpm_get(struct uart_8250_port *p); void serial8250_rpm_put(struct uart_8250_port *p); +int serial8250_em485_init(struct uart_8250_port *p); +void serial8250_em485_destroy(struct uart_8250_port *p); #if defined(__alpha__) && !defined(CONFIG_PCI) /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 04681e5745de..01a85a7e7427 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -522,6 +523,20 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) } } +static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) +{ + unsigned char mcr = serial_in(p, UART_MCR); + + if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial_out(p, UART_MCR, mcr); +} + +static void serial8250_em485_handle_start_tx(unsigned long arg); +static void serial8250_em485_handle_stop_tx(unsigned long arg); + void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) { serial8250_clear_fifos(p); @@ -546,6 +561,73 @@ void serial8250_rpm_put(struct uart_8250_port *p) } EXPORT_SYMBOL_GPL(serial8250_rpm_put); +/** + * serial8250_em485_init() - put uart_8250_port into rs485 emulating + * @p: uart_8250_port port instance + * + * The function is used to start rs485 software emulating on the + * &struct uart_8250_port* @p. Namely, RTS is switched before/after + * transmission. The function is idempotent, so it is safe to call it + * multiple times. + * + * The caller MUST enable interrupt on empty shift register before + * calling serial8250_em485_init(). This interrupt is not a part of + * 8250 standard, but implementation defined. + * + * The function is supposed to be called from .rs485_config callback + * or from any other callback protected with p->port.lock spinlock. + * + * See also serial8250_em485_destroy() + * + * Return 0 - success, -errno - otherwise + */ +int serial8250_em485_init(struct uart_8250_port *p) +{ + if (p->em485 != NULL) + return 0; + + p->em485 = kmalloc(sizeof(struct uart_8250_em485), GFP_KERNEL); + if (p->em485 == NULL) + return -ENOMEM; + + setup_timer(&p->em485->stop_tx_timer, + serial8250_em485_handle_stop_tx, (unsigned long)p); + setup_timer(&p->em485->start_tx_timer, + serial8250_em485_handle_start_tx, (unsigned long)p); + p->em485->active_timer = NULL; + + serial8250_em485_rts_after_send(p); + + return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_init); + +/** + * serial8250_em485_destroy() - put uart_8250_port into normal state + * @p: uart_8250_port port instance + * + * The function is used to stop rs485 software emulating on the + * &struct uart_8250_port* @p. The function is idempotent, so it is safe to + * call it multiple times. + * + * The function is supposed to be called from .rs485_config callback + * or from any other callback protected with p->port.lock spinlock. + * + * See also serial8250_em485_init() + */ +void serial8250_em485_destroy(struct uart_8250_port *p) +{ + if (p->em485 == NULL) + return; + + del_timer(&p->em485->start_tx_timer); + del_timer(&p->em485->stop_tx_timer); + + kfree(p->em485); + p->em485 = NULL; +} +EXPORT_SYMBOL_GPL(serial8250_em485_destroy); + /* * These two wrappers ensure that enable_runtime_pm_tx() can be called more than * once and disable_runtime_pm_tx() will still disable RPM because the fifo is @@ -1317,7 +1399,56 @@ static void serial8250_stop_rx(struct uart_port *port) serial8250_rpm_put(up); } -static inline void __stop_tx(struct uart_8250_port *p) +static void __do_stop_tx_rs485(struct uart_8250_port *p) +{ + if (!p->em485) + return; + + serial8250_em485_rts_after_send(p); + /* + * Empty the RX FIFO, we are not interested in anything + * received during the half-duplex transmission. + */ + if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) + serial8250_clear_fifos(p); +} + +static void serial8250_em485_handle_stop_tx(unsigned long arg) +{ + struct uart_8250_port *p = (struct uart_8250_port *)arg; + struct uart_8250_em485 *em485 = p->em485; + unsigned long flags; + + spin_lock_irqsave(&p->port.lock, flags); + if (em485 && + em485->active_timer == &em485->stop_tx_timer) { + __do_stop_tx_rs485(p); + em485->active_timer = NULL; + } + spin_unlock_irqrestore(&p->port.lock, flags); +} + +static void __stop_tx_rs485(struct uart_8250_port *p) +{ + struct uart_8250_em485 *em485 = p->em485; + + if (!em485) + return; + + /* + * __do_stop_tx_rs485 is going to set RTS according to config + * AND flush RX FIFO if required. + */ + if (p->port.rs485.delay_rts_after_send > 0) { + em485->active_timer = &em485->stop_tx_timer; + mod_timer(&em485->stop_tx_timer, jiffies + + p->port.rs485.delay_rts_after_send * HZ / 1000); + } else { + __do_stop_tx_rs485(p); + } +} + +static inline void __do_stop_tx(struct uart_8250_port *p) { if (p->ier & UART_IER_THRI) { p->ier &= ~UART_IER_THRI; @@ -1326,6 +1457,28 @@ static inline void __stop_tx(struct uart_8250_port *p) } } +static inline void __stop_tx(struct uart_8250_port *p) +{ + struct uart_8250_em485 *em485 = p->em485; + + if (em485) { + unsigned char lsr = serial_in(p, UART_LSR); + /* + * To provide required timeing and allow FIFO transfer, + * __stop_tx_rs485 must be called only when both FIFO and + * shift register are empty. It is for device driver to enable + * interrupt on TEMT. + */ + if ((lsr & BOTH_EMPTY) != BOTH_EMPTY) + return; + + del_timer(&em485->start_tx_timer); + em485->active_timer = NULL; + } + __do_stop_tx(p); + __stop_tx_rs485(p); +} + static void serial8250_stop_tx(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); @@ -1343,12 +1496,10 @@ static void serial8250_stop_tx(struct uart_port *port) serial8250_rpm_put(up); } -static void serial8250_start_tx(struct uart_port *port) +static inline void __start_tx(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); - serial8250_rpm_get_tx(up); - if (up->dma && !up->dma->tx_dma(up)) return; @@ -1374,6 +1525,70 @@ static void serial8250_start_tx(struct uart_port *port) } } +static inline void start_tx_rs485(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + unsigned char mcr; + + if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) + serial8250_stop_rx(&up->port); + + del_timer(&em485->stop_tx_timer); + em485->active_timer = NULL; + + mcr = serial_in(up, UART_MCR); + if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != + !!(mcr & UART_MCR_RTS)) { + if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) + mcr |= UART_MCR_RTS; + else + mcr &= ~UART_MCR_RTS; + serial_out(up, UART_MCR, mcr); + + if (up->port.rs485.delay_rts_before_send > 0) { + em485->active_timer = &em485->start_tx_timer; + mod_timer(&em485->start_tx_timer, jiffies + + up->port.rs485.delay_rts_before_send * HZ / 1000); + return; + } + } + + __start_tx(port); +} + +static void serial8250_em485_handle_start_tx(unsigned long arg) +{ + struct uart_8250_port *p = (struct uart_8250_port *)arg; + struct uart_8250_em485 *em485 = p->em485; + unsigned long flags; + + spin_lock_irqsave(&p->port.lock, flags); + if (em485 && + em485->active_timer == &em485->start_tx_timer) { + __start_tx(&p->port); + em485->active_timer = NULL; + } + spin_unlock_irqrestore(&p->port.lock, flags); +} + +static void serial8250_start_tx(struct uart_port *port) +{ + struct uart_8250_port *up = up_to_u8250p(port); + struct uart_8250_em485 *em485 = up->em485; + + serial8250_rpm_get_tx(up); + + if (em485 && + em485->active_timer == &em485->start_tx_timer) + return; + + if (em485) + start_tx_rs485(port); + else + __start_tx(port); +} + static void serial8250_throttle(struct uart_port *port) { port->throttle(port); diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index faa0e0370ce7..434879759725 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -76,6 +76,12 @@ struct uart_8250_ops { void (*release_irq)(struct uart_8250_port *); }; +struct uart_8250_em485 { + struct timer_list start_tx_timer; /* "rs485 start tx" timer */ + struct timer_list stop_tx_timer; /* "rs485 stop tx" timer */ + struct timer_list *active_timer; /* pointer to active timer */ +}; + /* * This should be used by drivers which want to register * their own 8250 ports without registering their own @@ -122,6 +128,8 @@ struct uart_8250_port { /* 8250 specific callbacks */ int (*dl_read)(struct uart_8250_port *); void (*dl_write)(struct uart_8250_port *, int); + + struct uart_8250_em485 *em485; }; static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up) -- cgit From 344cee2470ff70801c95c62ab2762da0834c8c6c Mon Sep 17 00:00:00 2001 From: "Matwey V. Kornilov" Date: Mon, 1 Feb 2016 21:09:22 +0300 Subject: tty: 8250_omap: Use software emulated RS485 direction control Use software emulated RS485 direction control to provide RS485 API existed in omap_serial driver. Note that 8250_omap issues interrupt on shift register empty which is single prerequesite for using software emulated RS485. Signed-off-by: Matwey V. Kornilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_omap.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index a2c0734c76e2..d710985a2e4f 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -697,6 +697,36 @@ static void omap_8250_throttle(struct uart_port *port) pm_runtime_put_autosuspend(port->dev); } +static int omap_8250_rs485_config(struct uart_port *port, + struct serial_rs485 *rs485) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + /* Clamp the delays to [0, 100ms] */ + rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); + rs485->delay_rts_after_send = min(rs485->delay_rts_after_send, 100U); + + port->rs485 = *rs485; + + /* + * Both serial8250_em485_init and serial8250_em485_destroy + * are idempotent + */ + if (rs485->flags & SER_RS485_ENABLED) { + int ret = serial8250_em485_init(up); + + if (ret) { + rs485->flags &= ~SER_RS485_ENABLED; + port->rs485.flags &= ~SER_RS485_ENABLED; + } + return ret; + } + + serial8250_em485_destroy(up); + + return 0; +} + static void omap_8250_unthrottle(struct uart_port *port) { unsigned long flags; @@ -1146,6 +1176,7 @@ static int omap8250_probe(struct platform_device *pdev) up.port.shutdown = omap_8250_shutdown; up.port.throttle = omap_8250_throttle; up.port.unthrottle = omap_8250_unthrottle; + up.port.rs485_config = omap_8250_rs485_config; if (pdev->dev.of_node) { const struct of_device_id *id; -- cgit From cdcea058e51008479545f29201b4fa577c59733c Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:25 +0200 Subject: serial: 8250_dw: Avoid serial_outx code duplicate with new dw8250_check_lcr() With the help of Heikki we take common code that makes sure LCR write wasn't ignored and put it in new function called dw8250_check_lcr(). This function serves 3 serial_out routines: dw8250_serial_out(), dw8250_serial_out32(), and dw8250_serial_outq(). This patch only brings better code reuse. Signed-off-by: Noam Camus Cc: Heikki Krogerus Cc: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 91 ++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 49 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index a5d319e4aae6..ffe5e0cb1f05 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -95,25 +95,43 @@ static void dw8250_force_idle(struct uart_port *p) (void)p->serial_in(p, UART_RX); } -static void dw8250_serial_out(struct uart_port *p, int offset, int value) +static void dw8250_check_lcr(struct uart_port *p, int value) { - writeb(value, p->membase + (offset << p->regshift)); + void __iomem *offset = p->membase + (UART_LCR << p->regshift); + int tries = 1000; /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writeb(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ + while (tries--) { + unsigned int lcr = p->serial_in(p, UART_LCR); + + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) + return; + + dw8250_force_idle(p); + +#ifdef CONFIG_64BIT + __raw_writeq(value & 0xff, offset); +#else + if (p->iotype == UPIO_MEM32) + writel(value, offset); + else + writeb(value, offset); +#endif } + /* + * FIXME: this deadlocks if port->lock is already held + * dev_err(p->dev, "Couldn't set LCR to %d\n", value); + */ +} + +static void dw8250_serial_out(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; + + writeb(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in(struct uart_port *p, int offset) @@ -135,49 +153,26 @@ static unsigned int dw8250_serial_inq(struct uart_port *p, int offset) static void dw8250_serial_outq(struct uart_port *p, int offset, int value) { + struct dw8250_data *d = p->private_data; + value &= 0xff; __raw_writeq(value, p->membase + (offset << p->regshift)); /* Read back to ensure register write ordering. */ __raw_readq(p->membase + (UART_LCR << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - __raw_writeq(value & 0xff, - p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } #endif /* CONFIG_64BIT */ static void dw8250_serial_out32(struct uart_port *p, int offset, int value) { + struct dw8250_data *d = p->private_data; + writel(value, p->membase + (offset << p->regshift)); - /* Make sure LCR write wasn't ignored */ - if (offset == UART_LCR) { - int tries = 1000; - while (tries--) { - unsigned int lcr = p->serial_in(p, UART_LCR); - if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) - return; - dw8250_force_idle(p); - writel(value, p->membase + (UART_LCR << p->regshift)); - } - /* - * FIXME: this deadlocks if port->lock is already held - * dev_err(p->dev, "Couldn't set LCR to %d\n", value); - */ - } + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); } static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) @@ -463,10 +458,8 @@ static int dw8250_probe(struct platform_device *pdev) dw8250_quirks(p, data); /* If the Busy Functionality is not implemented, don't handle it */ - if (data->uart_16550_compatible) { - p->serial_out = NULL; + if (data->uart_16550_compatible) p->handle_irq = NULL; - } if (!data->skip_autocfg) dw8250_setup_port(p); -- cgit From 4625090187768bc776d69dfaa6a1f79b1125debe Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:26 +0200 Subject: serial: 8250_dw: Add support for big-endian MMIO accesses Add support for UPIO_MEM32BE in addition to UPIO_MEM32. For big endian we use 2 new accessors similar to little endian, called dw8250_serial_out32be() and dw8250_serial_in32be(). Signed-off-by: Noam Camus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index ffe5e0cb1f05..92c4a9bc2e6d 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -182,6 +182,24 @@ static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) return dw8250_modify_msr(p, offset, value); } +static void dw8250_serial_out32be(struct uart_port *p, int offset, int value) +{ + struct dw8250_data *d = p->private_data; + + iowrite32be(value, p->membase + (offset << p->regshift)); + + if (offset == UART_LCR && !d->uart_16550_compatible) + dw8250_check_lcr(p, value); +} + +static unsigned int dw8250_serial_in32be(struct uart_port *p, int offset) +{ + unsigned int value = ioread32be(p->membase + (offset << p->regshift)); + + return dw8250_modify_msr(p, offset, value); +} + + static int dw8250_handle_irq(struct uart_port *p) { struct dw8250_data *d = p->private_data; @@ -276,6 +294,11 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) data->skip_autocfg = true; } #endif + if (of_device_is_big_endian(p->dev->of_node)) { + p->iotype = UPIO_MEM32BE; + p->serial_in = dw8250_serial_in32be; + p->serial_out = dw8250_serial_out32be; + } } else if (has_acpi_companion(p->dev)) { p->iotype = UPIO_MEM32; p->regshift = 2; -- cgit From 5a43140cc4a59eda4549cc3b74989efa77973158 Mon Sep 17 00:00:00 2001 From: Noam Camus Date: Sat, 12 Dec 2015 19:18:27 +0200 Subject: serial: 8250_dw: Do not use readl/writel before checking port iotype Direct call to readl()/writel() is checked against iotype and in case of UPIO_MEM32BE we use ioread32be()/iowrite32be() instead of them. Signed-off-by: Noam Camus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 92c4a9bc2e6d..30810acf7f96 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -114,6 +114,8 @@ static void dw8250_check_lcr(struct uart_port *p, int value) #else if (p->iotype == UPIO_MEM32) writel(value, offset); + else if (p->iotype == UPIO_MEM32BE) + iowrite32be(value, offset); else writeb(value, offset); #endif @@ -327,14 +329,20 @@ static void dw8250_setup_port(struct uart_port *p) * If the Component Version Register returns zero, we know that * ADDITIONAL_FEATURES are not enabled. No need to go any further. */ - reg = readl(p->membase + DW_UART_UCV); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_UCV); + else + reg = readl(p->membase + DW_UART_UCV); if (!reg) return; dev_dbg(p->dev, "Designware UART version %c.%c%c\n", (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff); - reg = readl(p->membase + DW_UART_CPR); + if (p->iotype == UPIO_MEM32BE) + reg = ioread32be(p->membase + DW_UART_CPR); + else + reg = readl(p->membase + DW_UART_CPR); if (!reg) return; -- cgit From cc74bd1d218053cefc6323721512808d36a1bfb1 Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Tue, 15 Dec 2015 01:45:16 +0200 Subject: tty: serial: constify psc_ops structs Constifies psc_ops structures in tty's serial port driver since they are not modified after their initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mpc52xx_uart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index 8c3e51314470..3970d6a9aaca 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c @@ -346,7 +346,7 @@ static irqreturn_t mpc52xx_psc_handle_irq(struct uart_port *port) return mpc5xxx_uart_process_int(port); } -static struct psc_ops mpc52xx_psc_ops = { +static const struct psc_ops mpc52xx_psc_ops = { .fifo_init = mpc52xx_psc_fifo_init, .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, @@ -376,7 +376,7 @@ static struct psc_ops mpc52xx_psc_ops = { .get_mr1 = mpc52xx_psc_get_mr1, }; -static struct psc_ops mpc5200b_psc_ops = { +static const struct psc_ops mpc5200b_psc_ops = { .fifo_init = mpc52xx_psc_fifo_init, .raw_rx_rdy = mpc52xx_psc_raw_rx_rdy, .raw_tx_rdy = mpc52xx_psc_raw_tx_rdy, @@ -969,7 +969,7 @@ static u8 mpc5125_psc_get_mr1(struct uart_port *port) return in_8(&PSC_5125(port)->mr1); } -static struct psc_ops mpc5125_psc_ops = { +static const struct psc_ops mpc5125_psc_ops = { .fifo_init = mpc5125_psc_fifo_init, .raw_rx_rdy = mpc5125_psc_raw_rx_rdy, .raw_tx_rdy = mpc5125_psc_raw_tx_rdy, @@ -1004,7 +1004,7 @@ static struct psc_ops mpc5125_psc_ops = { .get_mr1 = mpc5125_psc_get_mr1, }; -static struct psc_ops mpc512x_psc_ops = { +static const struct psc_ops mpc512x_psc_ops = { .fifo_init = mpc512x_psc_fifo_init, .raw_rx_rdy = mpc512x_psc_raw_rx_rdy, .raw_tx_rdy = mpc512x_psc_raw_tx_rdy, -- cgit From aaa68c50b28c903a2fa53aad3d5fd17e8cc7f492 Mon Sep 17 00:00:00 2001 From: Frederik Völkel Date: Fri, 18 Dec 2015 12:28:23 +0100 Subject: serial: Remove 68328 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's old, messy and mostly unmaintained. Remove it as suggested by Peter Hurley and Alan. Signed-off-by: Frederik Völkel Signed-off-by: Lukas Braun Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/68328serial.c | 1309 -------------------------------------- drivers/tty/serial/Kconfig | 11 - drivers/tty/serial/Makefile | 1 - 3 files changed, 1321 deletions(-) delete mode 100644 drivers/tty/serial/68328serial.c diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c deleted file mode 100644 index 9587ed1242fe..000000000000 --- a/drivers/tty/serial/68328serial.c +++ /dev/null @@ -1,1309 +0,0 @@ -/* 68328serial.c: Serial port driver for 68328 microcontroller - * - * Copyright (C) 1995 David S. Miller - * Copyright (C) 1998 Kenneth Albanowski - * Copyright (C) 1998, 1999 D. Jeff Dionne - * Copyright (C) 1999 Vladimir Gurevich - * Copyright (C) 2002-2003 David McCullough - * Copyright (C) 2002 Greg Ungerer - * - * VZ Support/Fixes Evan Stawnyczy - * Multiple UART support Daniel Potts - * Power management support Daniel Potts - * VZ Second Serial Port enable Phil Wilshire - * 2.4/2.5 port David McCullough - */ - -#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 - -/* (es) */ -/* note: perhaps we can murge these files, so that you can just - * define 1 of them, and they can sort that out for themselves - */ -#if defined(CONFIG_M68EZ328) -#include -#else -#if defined(CONFIG_M68VZ328) -#include -#else -#include -#endif /* CONFIG_M68VZ328 */ -#endif /* CONFIG_M68EZ328 */ - -/* Turn off usage of real serial interrupt code, to "support" Copilot */ -#ifdef CONFIG_XCOPILOT_BUGS -#undef USE_INTS -#else -#define USE_INTS -#endif - -/* - * I believe this is the optimal setting that reduces the number of interrupts. - * At high speeds the output might become a little "bursted" (use USTCNT_TXHE - * if that bothers you), but in most cases it will not, since we try to - * transmit characters every time rs_interrupt is called. Thus, quite often - * you'll see that a receive interrupt occures before the transmit one. - * -- Vladimir Gurevich - */ -#define USTCNT_TX_INTR_MASK (USTCNT_TXEE) - -/* - * 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special - * "Old data interrupt" which occures whenever the data stay in the FIFO - * longer than 30 bits time. This allows us to use FIFO without compromising - * latency. '328 does not have this feature and without the real 328-based - * board I would assume that RXRE is the safest setting. - * - * For EZ328 I use RXHE (Half empty) interrupt to reduce the number of - * interrupts. RXFE (receive queue full) causes the system to lose data - * at least at 115200 baud - * - * If your board is busy doing other stuff, you might consider to use - * RXRE (data ready intrrupt) instead. - * - * The other option is to make these INTR masks run-time configurable, so - * that people can dynamically adapt them according to the current usage. - * -- Vladimir Gurevich - */ - -/* (es) */ -#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328) -#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN) -#elif defined(CONFIG_M68328) -#define USTCNT_RX_INTR_MASK (USTCNT_RXRE) -#else -#error Please, define the Rx interrupt events for your CPU -#endif -/* (/es) */ - -/* - * This is our internal structure for each serial port's state. - */ -struct m68k_serial { - struct tty_port tport; - char is_cons; /* Is this our console. */ - int magic; - int baud_base; - int port; - int irq; - int type; /* UART type */ - int custom_divisor; - int x_char; /* xon/xoff character */ - int line; - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; -}; - -#define SERIAL_MAGIC 0x5301 - -/* - * Define the number of ports supported and their irqs. - */ -#define NR_PORTS 1 - -static struct m68k_serial m68k_soft[NR_PORTS]; - -static unsigned int uart_irqs[NR_PORTS] = { UART_IRQ_NUM }; - -/* multiple ports are contiguous in memory */ -m68328_uart *uart_addr = (m68328_uart *)USTCNT_ADDR; - -struct tty_driver *serial_driver; - -static void change_speed(struct m68k_serial *info, struct tty_struct *tty); - -/* - * Setup for console. Argument comes from the boot command line. - */ - -/* note: this is messy, but it works, again, perhaps defined somewhere else?*/ -#ifdef CONFIG_M68VZ328 -#define CONSOLE_BAUD_RATE 19200 -#define DEFAULT_CBAUD B19200 -#endif - - -#ifndef CONSOLE_BAUD_RATE -#define CONSOLE_BAUD_RATE 9600 -#define DEFAULT_CBAUD B9600 -#endif - - -static int m68328_console_initted; -static int m68328_console_baud = CONSOLE_BAUD_RATE; -static int m68328_console_cbaud = DEFAULT_CBAUD; - - -static inline int serial_paranoia_check(struct m68k_serial *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct %s in %s\n"; - static const char *badinfo = - "Warning: null m68k_serial for %s in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* - * This is used to figure out the divisor speeds and the timeouts - */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 0 }; - -/* Utility routines */ -static inline int get_baud(struct m68k_serial *ss) -{ - unsigned long result = 115200; - unsigned short int baud = uart_addr[ss->line].ubaud; - if (GET_FIELD(baud, UBAUD_PRESCALER) == 0x38) result = 38400; - result >>= GET_FIELD(baud, UBAUD_DIVIDE); - - return result; -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - - local_irq_save(flags); - uart->ustcnt &= ~USTCNT_TXEN; - local_irq_restore(flags); -} - -static int rs_put_char(char ch) -{ - unsigned long flags; - int loops = 0; - - local_irq_save(flags); - - while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) { - loops++; - udelay(5); - } - - UTX_TXDATA = ch; - udelay(5); - local_irq_restore(flags); - return 1; -} - -static void rs_start(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - - local_irq_save(flags); - if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) { -#ifdef USE_INTS - uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; -#else - uart->ustcnt |= USTCNT_TXEN; -#endif - } - local_irq_restore(flags); -} - -static void receive_chars(struct m68k_serial *info, unsigned short rx) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned char ch, flag; - - /* - * This do { } while() loop will get ALL chars out of Rx FIFO - */ -#ifndef CONFIG_XCOPILOT_BUGS - do { -#endif - ch = GET_FIELD(rx, URX_RXDATA); - - if (info->is_cons) { - if (URX_BREAK & rx) { /* whee, break received */ - return; -#ifdef CONFIG_MAGIC_SYSRQ - } else if (ch == 0x10) { /* ^P */ - show_state(); - show_free_areas(0); - show_buffers(); -/* show_net_buffers(); */ - return; - } else if (ch == 0x12) { /* ^R */ - emergency_restart(); - return; -#endif /* CONFIG_MAGIC_SYSRQ */ - } - } - - flag = TTY_NORMAL; - - if (rx & URX_PARITY_ERROR) - flag = TTY_PARITY; - else if (rx & URX_OVRUN) - flag = TTY_OVERRUN; - else if (rx & URX_FRAME_ERROR) - flag = TTY_FRAME; - - tty_insert_flip_char(&info->tport, ch, flag); -#ifndef CONFIG_XCOPILOT_BUGS - } while ((rx = uart->urx.w) & URX_DATA_READY); -#endif - - tty_schedule_flip(&info->tport); -} - -static void transmit_chars(struct m68k_serial *info, struct tty_struct *tty) -{ - m68328_uart *uart = &uart_addr[info->line]; - - if (info->x_char) { - /* Send next char */ - uart->utx.b.txdata = info->x_char; - info->x_char = 0; - goto clear_and_return; - } - - if ((info->xmit_cnt <= 0) || !tty || tty->stopped) { - /* That's peculiar... TX ints off */ - uart->ustcnt &= ~USTCNT_TX_INTR_MASK; - goto clear_and_return; - } - - /* Send char */ - uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - - if (info->xmit_cnt <= 0) { - /* All done for now... TX ints off */ - uart->ustcnt &= ~USTCNT_TX_INTR_MASK; - goto clear_and_return; - } - -clear_and_return: - /* Clear interrupt (should be auto)*/ - return; -} - -/* - * This is the serial driver's generic interrupt routine - */ -irqreturn_t rs_interrupt(int irq, void *dev_id) -{ - struct m68k_serial *info = dev_id; - struct tty_struct *tty = tty_port_tty_get(&info->tport); - m68328_uart *uart; - unsigned short rx; - unsigned short tx; - - uart = &uart_addr[info->line]; - rx = uart->urx.w; - -#ifdef USE_INTS - tx = uart->utx.w; - - if (rx & URX_DATA_READY) - receive_chars(info, rx); - if (tx & UTX_TX_AVAIL) - transmit_chars(info, tty); -#else - receive_chars(info, rx); -#endif - tty_kref_put(tty); - - return IRQ_HANDLED; -} - -static int startup(struct m68k_serial *info, struct tty_struct *tty) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (info->tport.flags & ASYNC_INITIALIZED) - return 0; - - if (!info->xmit_buf) { - info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL); - if (!info->xmit_buf) - return -ENOMEM; - } - - local_irq_save(flags); - - /* - * Clear the FIFO buffers and disable them - * (they will be reenabled in change_speed()) - */ - - uart->ustcnt = USTCNT_UEN; - uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_TXEN; - (void)uart->urx.w; - - /* - * Finally, enable sequencing and interrupts - */ -#ifdef USE_INTS - uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | - USTCNT_RX_INTR_MASK | USTCNT_TX_INTR_MASK; -#else - uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK; -#endif - - if (tty) - clear_bit(TTY_IO_ERROR, &tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* - * and set the speed of the serial port - */ - - change_speed(info, tty); - - info->tport.flags |= ASYNC_INITIALIZED; - local_irq_restore(flags); - return 0; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct m68k_serial *info, struct tty_struct *tty) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - uart->ustcnt = 0; /* All off! */ - if (!(info->tport.flags & ASYNC_INITIALIZED)) - return; - - local_irq_save(flags); - - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = 0; - } - - if (tty) - set_bit(TTY_IO_ERROR, &tty->flags); - - info->tport.flags &= ~ASYNC_INITIALIZED; - local_irq_restore(flags); -} - -struct { - int divisor, prescale; -} -#ifndef CONFIG_M68VZ328 - hw_baud_table[18] = { - {0, 0}, /* 0 */ - {0, 0}, /* 50 */ - {0, 0}, /* 75 */ - {0, 0}, /* 110 */ - {0, 0}, /* 134 */ - {0, 0}, /* 150 */ - {0, 0}, /* 200 */ - {7, 0x26}, /* 300 */ - {6, 0x26}, /* 600 */ - {5, 0x26}, /* 1200 */ - {0, 0}, /* 1800 */ - {4, 0x26}, /* 2400 */ - {3, 0x26}, /* 4800 */ - {2, 0x26}, /* 9600 */ - {1, 0x26}, /* 19200 */ - {0, 0x26}, /* 38400 */ - {1, 0x38}, /* 57600 */ - {0, 0x38}, /* 115200 */ -}; -#else - hw_baud_table[18] = { - {0, 0}, /* 0 */ - {0, 0}, /* 50 */ - {0, 0}, /* 75 */ - {0, 0}, /* 110 */ - {0, 0}, /* 134 */ - {0, 0}, /* 150 */ - {0, 0}, /* 200 */ - {0, 0}, /* 300 */ - {7, 0x26}, /* 600 */ - {6, 0x26}, /* 1200 */ - {0, 0}, /* 1800 */ - {5, 0x26}, /* 2400 */ - {4, 0x26}, /* 4800 */ - {3, 0x26}, /* 9600 */ - {2, 0x26}, /* 19200 */ - {1, 0x26}, /* 38400 */ - {0, 0x26}, /* 57600 */ - {1, 0x38}, /* 115200 */ -}; -#endif -/* rate = 1036800 / ((65 - prescale) * (1<line]; - unsigned short port; - unsigned short ustcnt; - unsigned cflag; - int i; - - cflag = tty->termios.c_cflag; - port = info->port; - if (!port) - return; - - ustcnt = uart->ustcnt; - uart->ustcnt = ustcnt & ~USTCNT_TXEN; - - i = cflag & CBAUD; - if (i & CBAUDEX) { - i = (i & ~CBAUDEX) + B38400; - } - - uart->ubaud = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) | - PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale); - - ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7); - - if ((cflag & CSIZE) == CS8) - ustcnt |= USTCNT_8_7; - - if (cflag & CSTOPB) - ustcnt |= USTCNT_STOP; - - if (cflag & PARENB) - ustcnt |= USTCNT_PARITYEN; - if (cflag & PARODD) - ustcnt |= USTCNT_ODD_EVEN; - -#ifdef CONFIG_SERIAL_68328_RTS_CTS - if (cflag & CRTSCTS) { - uart->utx.w &= ~UTX_NOCTS; - } else { - uart->utx.w |= UTX_NOCTS; - } -#endif - - ustcnt |= USTCNT_TXEN; - - uart->ustcnt = ustcnt; - return; -} - -/* - * Fair output driver allows a process to speak. - */ -static void rs_fair_output(void) -{ - int left; /* Output no more than that */ - unsigned long flags; - struct m68k_serial *info = &m68k_soft[0]; - char c; - - if (info == NULL) return; - if (info->xmit_buf == NULL) return; - - local_irq_save(flags); - left = info->xmit_cnt; - while (left != 0) { - c = info->xmit_buf[info->xmit_tail]; - info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - local_irq_restore(flags); - - rs_put_char(c); - - local_irq_save(flags); - left = min(info->xmit_cnt, left-1); - } - - /* Last character is being transmitted now (hopefully). */ - udelay(5); - - local_irq_restore(flags); - return; -} - -/* - * m68k_console_print is registered for printk. - */ -void console_print_68328(const char *p) -{ - char c; - - while ((c = *(p++)) != 0) { - if (c == '\n') - rs_put_char('\r'); - rs_put_char(c); - } - - /* Comment this if you want to have a strict interrupt-driven output */ - rs_fair_output(); - - return; -} - -static void rs_set_ldisc(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_set_ldisc")) - return; - - info->is_cons = (tty->termios.c_line == N_TTY); - - printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off"); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; -#ifndef USE_INTS - for (;;) { -#endif - - /* Enable transmitter */ - local_irq_save(flags); - - if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) { - local_irq_restore(flags); - return; - } - -#ifdef USE_INTS - uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; -#else - uart->ustcnt |= USTCNT_TXEN; -#endif - -#ifdef USE_INTS - if (uart->utx.w & UTX_TX_AVAIL) { -#else - if (1) { -#endif - /* Send char */ - uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - -#ifndef USE_INTS - while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); - } -#endif - local_irq_restore(flags); -} - -extern void console_printn(const char *b, int count); - -static int rs_write(struct tty_struct *tty, - const unsigned char *buf, int count) -{ - int c, total = 0; - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - - if (!tty || !info->xmit_buf) - return 0; - - local_save_flags(flags); - while (1) { - local_irq_disable(); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - local_irq_restore(flags); - - if (c <= 0) - break; - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - - local_irq_disable(); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); - buf += c; - count -= c; - total += c; - } - - if (info->xmit_cnt && !tty->stopped) { - /* Enable transmitter */ - local_irq_disable(); -#ifndef USE_INTS - while (info->xmit_cnt) { -#endif - - uart->ustcnt |= USTCNT_TXEN; -#ifdef USE_INTS - uart->ustcnt |= USTCNT_TX_INTR_MASK; -#else - while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); -#endif - if (uart->utx.w & UTX_TX_AVAIL) { - uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt--; - } - -#ifndef USE_INTS - } -#endif - local_irq_restore(flags); - } - - return total; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - int ret; - - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; - return info->xmit_cnt; -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; - local_irq_save(flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - local_irq_restore(flags); - tty_wakeup(tty); -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); - - /* Turn off RTS line (do this atomic) */ -} - -static void rs_unthrottle(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } - - /* Assert RTS line (do this atomic) */ -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct m68k_serial *info, - struct serial_struct *retinfo) -{ - struct serial_struct tmp; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = info->port; - tmp.irq = info->irq; - tmp.flags = info->tport.flags; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->tport.close_delay; - tmp.closing_wait = info->tport.closing_wait; - tmp.custom_divisor = info->custom_divisor; - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - - return 0; -} - -static int set_serial_info(struct m68k_serial *info, struct tty_struct *tty, - struct serial_struct *new_info) -{ - struct tty_port *port = &info->tport; - struct serial_struct new_serial; - struct m68k_serial old_info; - int retval = 0; - - if (!new_info) - return -EFAULT; - if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) - return -EFAULT; - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.baud_base != info->baud_base) || - (new_serial.type != info->type) || - (new_serial.close_delay != port->close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (port->flags & ~ASYNC_USR_MASK))) - return -EPERM; - port->flags = ((port->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - if (port->count > 1) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud_base = new_serial.baud_base; - port->flags = ((port->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->type = new_serial.type; - port->close_delay = new_serial.close_delay; - port->closing_wait = new_serial.closing_wait; - -check_and_exit: - retval = startup(info, tty); - return retval; -} - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct m68k_serial *info, unsigned int *value) -{ -#ifdef CONFIG_SERIAL_68328_RTS_CTS - m68328_uart *uart = &uart_addr[info->line]; -#endif - unsigned char status; - unsigned long flags; - - local_irq_save(flags); -#ifdef CONFIG_SERIAL_68328_RTS_CTS - status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0; -#else - status = 0; -#endif - local_irq_restore(flags); - return put_user(status, value); -} - -/* - * This routine sends a break character out the serial port. - */ -static void send_break(struct m68k_serial *info, unsigned int duration) -{ - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - if (!info->port) - return; - local_irq_save(flags); -#ifdef USE_INTS - uart->utx.w |= UTX_SEND_BREAK; - msleep_interruptible(duration); - uart->utx.w &= ~UTX_SEND_BREAK; -#endif - local_irq_restore(flags); -} - -static int rs_ioctl(struct tty_struct *tty, - unsigned int cmd, unsigned long arg) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - int retval; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - send_break(info, 250); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - send_break(info, arg ? arg*(100) : 250); - return 0; - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, tty, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - case TIOCSERGSTRUCT: - if (copy_to_user((struct m68k_serial *) arg, - info, sizeof(struct m68k_serial))) - return -EFAULT; - return 0; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - change_speed(info, tty); - - if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) - rs_start(tty); -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * S structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file *filp) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - struct tty_port *port = &info->tport; - m68328_uart *uart = &uart_addr[info->line]; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_close")) - return; - - local_irq_save(flags); - - if (tty_hung_up_p(filp)) { - local_irq_restore(flags); - return; - } - - if ((tty->count == 1) && (port->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("rs_close: bad serial port count; tty->count is 1, " - "port->count is %d\n", port->count); - port->count = 1; - } - if (--port->count < 0) { - printk("rs_close: bad serial port count for ttyS%d: %d\n", - info->line, port->count); - port->count = 0; - } - if (port->count) { - local_irq_restore(flags); - return; - } - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, port->closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - - uart->ustcnt &= ~USTCNT_RXEN; - uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK); - - shutdown(info, tty); - rs_flush_buffer(tty); - - tty_ldisc_flush(tty); - tty->closing = 0; - tty_port_tty_set(&info->tport, NULL); - - if (port->blocked_open) { - if (port->close_delay) - msleep_interruptible(jiffies_to_msecs(port->close_delay)); - wake_up_interruptible(&port->open_wait); - } - port->flags &= ~ASYNC_NORMAL_ACTIVE; - local_irq_restore(flags); -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void rs_hangup(struct tty_struct *tty) -{ - struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_hangup")) - return; - - rs_flush_buffer(tty); - shutdown(info, tty); - info->tport.count = 0; - info->tport.flags &= ~ASYNC_NORMAL_ACTIVE; - tty_port_tty_set(&info->tport, NULL); - wake_up_interruptible(&info->tport.open_wait); -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its S structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -int rs_open(struct tty_struct *tty, struct file *filp) -{ - struct m68k_serial *info; - int retval; - - info = &m68k_soft[tty->index]; - - if (serial_paranoia_check(info, tty->name, "rs_open")) - return -ENODEV; - - info->tport.count++; - tty->driver_data = info; - tty_port_tty_set(&info->tport, tty); - - /* - * Start up serial port - */ - retval = startup(info, tty); - if (retval) - return retval; - - return tty_port_block_til_ready(&info->tport, tty, filp); -} - -/* Finally, routines used to initialize the serial driver. */ - -static void show_serial_version(void) -{ - printk("MC68328 serial driver version 1.00\n"); -} - -static const struct tty_operations rs_ops = { - .open = rs_open, - .close = rs_close, - .write = rs_write, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = rs_hangup, - .set_ldisc = rs_set_ldisc, -}; - -static const struct tty_port_operations rs_port_ops = { -}; - -/* rs_init inits the driver */ -static int __init -rs68328_init(void) -{ - unsigned long flags; - int i; - struct m68k_serial *info; - - serial_driver = alloc_tty_driver(NR_PORTS); - if (!serial_driver) - return -ENOMEM; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - /* SPARC: Not all of this is exactly right for us. */ - - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - m68328_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &rs_ops); - - local_irq_save(flags); - - for (i = 0; i < NR_PORTS; i++) { - - info = &m68k_soft[i]; - tty_port_init(&info->tport); - info->tport.ops = &rs_port_ops; - info->magic = SERIAL_MAGIC; - info->port = (int) &uart_addr[i]; - info->irq = uart_irqs[i]; - info->custom_divisor = 16; - info->x_char = 0; - info->line = i; - info->is_cons = 1; /* Means shortcuts work */ - - printk("%s%d at 0x%08x (irq = %d)", serial_driver->name, info->line, - info->port, info->irq); - printk(" is a builtin MC68328 UART\n"); - -#ifdef CONFIG_M68VZ328 - if (i > 0) - PJSEL &= 0xCF; /* PSW enable second port output */ -#endif - - if (request_irq(uart_irqs[i], - rs_interrupt, - 0, - "M68328_UART", info)) - panic("Unable to attach 68328 serial interrupt\n"); - - tty_port_link_device(&info->tport, serial_driver, i); - } - local_irq_restore(flags); - - if (tty_register_driver(serial_driver)) { - put_tty_driver(serial_driver); - for (i = 0; i < NR_PORTS; i++) - tty_port_destroy(&m68k_soft[i].tport); - printk(KERN_ERR "Couldn't register serial driver\n"); - return -ENOMEM; - } - - return 0; -} - -module_init(rs68328_init); - - - -static void m68328_set_baud(void) -{ - unsigned short ustcnt; - int i; - - ustcnt = USTCNT; - USTCNT = ustcnt & ~USTCNT_TXEN; - -again: - for (i = 0; i < ARRAY_SIZE(baud_table); i++) - if (baud_table[i] == m68328_console_baud) - break; - if (i >= ARRAY_SIZE(baud_table)) { - m68328_console_baud = 9600; - goto again; - } - - UBAUD = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) | - PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale); - ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7); - ustcnt |= USTCNT_8_7; - ustcnt |= USTCNT_TXEN; - USTCNT = ustcnt; - m68328_console_initted = 1; - return; -} - - -int m68328_console_setup(struct console *cp, char *arg) -{ - int i, n = CONSOLE_BAUD_RATE; - - if (!cp) - return(-1); - - if (arg) - n = simple_strtoul(arg, NULL, 0); - - for (i = 0; i < ARRAY_SIZE(baud_table); i++) - if (baud_table[i] == n) - break; - if (i < ARRAY_SIZE(baud_table)) { - m68328_console_baud = n; - m68328_console_cbaud = 0; - if (i > 15) { - m68328_console_cbaud |= CBAUDEX; - i -= 15; - } - m68328_console_cbaud |= i; - } - - m68328_set_baud(); /* make sure baud rate changes */ - return 0; -} - - -static struct tty_driver *m68328_console_device(struct console *c, int *index) -{ - *index = c->index; - return serial_driver; -} - - -void m68328_console_write (struct console *co, const char *str, - unsigned int count) -{ - if (!m68328_console_initted) - m68328_set_baud(); - while (count--) { - if (*str == '\n') - rs_put_char('\r'); - rs_put_char(*str++); - } -} - - -static struct console m68328_driver = { - .name = "ttyS", - .write = m68328_console_write, - .device = m68328_console_device, - .setup = m68328_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - - -static int __init m68328_console_init(void) -{ - register_console(&m68328_driver); - return 0; -} - -console_initcall(m68328_console_init); diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 39721ec4f415..e5c9250426a8 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -793,17 +793,6 @@ config SERIAL_CORE_CONSOLE config CONSOLE_POLL bool -config SERIAL_68328 - bool "68328 serial support" - depends on M68328 || M68EZ328 || M68VZ328 - help - This driver supports the built-in serial port of the Motorola 68328 - (standard, EZ and VZ varieties). - -config SERIAL_68328_RTS_CTS - bool "Support RTS/CTS on 68328 serial port" - depends on SERIAL_68328 - config SERIAL_MCF bool "Coldfire serial support" depends on COLDFIRE diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index b391c9b31960..ceba33c4ebb4 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -34,7 +34,6 @@ obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX310X) += max310x.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_MUX) += mux.o -obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o -- cgit From 0b41ce991052022c030fd868e03877700220b090 Mon Sep 17 00:00:00 2001 From: Sebastian Frias Date: Fri, 18 Dec 2015 17:40:05 +0100 Subject: 8250: use callbacks to access UART_DLL/UART_DLM Some UART HW has a single register combining UART_DLL/UART_DLM (this was probably forgotten in the change that introduced the callbacks, commit b32b19b8ffc05cbd3bf91c65e205f6a912ca15d9) Fixes: b32b19b8ffc0 ("[SERIAL] 8250: set divisor register correctly ...") Signed-off-by: Sebastian Frias Reviewed-by: Peter Hurley Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_port.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 01a85a7e7427..c2b650aeb792 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -813,22 +813,16 @@ static int size_fifo(struct uart_8250_port *up) */ static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p) { - unsigned char old_dll, old_dlm, old_lcr; - unsigned int id; + unsigned char old_lcr; + unsigned int id, old_dl; old_lcr = serial_in(p, UART_LCR); serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A); + old_dl = serial_dl_read(p); + serial_dl_write(p, 0); + id = serial_dl_read(p); + serial_dl_write(p, old_dl); - old_dll = serial_in(p, UART_DLL); - old_dlm = serial_in(p, UART_DLM); - - serial_out(p, UART_DLL, 0); - serial_out(p, UART_DLM, 0); - - id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8; - - serial_out(p, UART_DLL, old_dll); - serial_out(p, UART_DLM, old_dlm); serial_out(p, UART_LCR, old_lcr); return id; -- cgit From 4b769371fef7e5ad2ec9d7a677bb7001a0c5b213 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Jan 2016 11:26:14 +0100 Subject: serial: atmel: trivial: clean the IP version decoding code No functional change is associated with this patch. A driver property depends on the Atmel serial IP revision. This property is the way the rx timeout is handled: by an hardware or software timer. So, change this property name and setup code so that it's easier to understand and more future proof as the distinction of USART vs. UART is blurrier on newer SoCs. Variable names and debug comments are also adapted to make this code more obvious. Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 1c0884d8ef32..a429cfef0286 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -159,8 +159,8 @@ struct atmel_uart_port { u32 rts_high; u32 rts_low; bool ms_irq_enabled; - bool is_usart; /* usart or uart */ - struct timer_list uart_timer; /* uart timer */ + bool has_hw_timer; + struct timer_list uart_timer; bool suspended; unsigned int pending; @@ -1710,19 +1710,19 @@ static void atmel_get_ip_name(struct uart_port *port) struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int name = atmel_uart_readl(port, ATMEL_US_NAME); u32 version; - int usart, uart; - /* usart and uart ascii */ - usart = 0x55534152; - uart = 0x44424755; + u32 usart, dbgu_uart; + /* ASCII decoding for IP version */ + usart = 0x55534152; /* USAR(T) */ + dbgu_uart = 0x44424755; /* DBGU */ - atmel_port->is_usart = false; + atmel_port->has_hw_timer = false; if (name == usart) { - dev_dbg(port->dev, "This is usart\n"); - atmel_port->is_usart = true; - } else if (name == uart) { - dev_dbg(port->dev, "This is uart\n"); - atmel_port->is_usart = false; + dev_dbg(port->dev, "Usart with hw timer\n"); + atmel_port->has_hw_timer = true; + } else if (name == dbgu_uart) { + dev_dbg(port->dev, "Dbgu or uart without hw timer\n"); + atmel_port->has_hw_timer = false; } else { /* fallback for older SoCs: use version field */ version = atmel_uart_readl(port, ATMEL_US_VERSION); @@ -1730,12 +1730,12 @@ static void atmel_get_ip_name(struct uart_port *port) case 0x302: case 0x10213: dev_dbg(port->dev, "This version is usart\n"); - atmel_port->is_usart = true; + atmel_port->has_hw_timer = true; break; case 0x203: case 0x10202: dev_dbg(port->dev, "This version is uart\n"); - atmel_port->is_usart = false; + atmel_port->has_hw_timer = false; break; default: dev_err(port->dev, "Not supported ip name nor version, set to uart\n"); @@ -1835,7 +1835,7 @@ static int atmel_startup(struct uart_port *port) if (atmel_use_pdc_rx(port)) { /* set UART timeout */ - if (!atmel_port->is_usart) { + if (!atmel_port->has_hw_timer) { mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port)); /* set USART timeout */ @@ -1850,7 +1850,7 @@ static int atmel_startup(struct uart_port *port) atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN); } else if (atmel_use_dma_rx(port)) { /* set UART timeout */ - if (!atmel_port->is_usart) { + if (!atmel_port->has_hw_timer) { mod_timer(&atmel_port->uart_timer, jiffies + uart_poll_timeout(port)); /* set USART timeout */ -- cgit From 1d673fb971d4411e92991ca17ff2b54ce19af3a4 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 26 Jan 2016 11:26:15 +0100 Subject: serial: atmel: add support for new UART version Starting with sama5d2, the new UART revision has an hardware timer. So, add it to the IP detection code and set the "has_hw_timer" property for it. Signed-off-by: Nicolas Ferre Reported-by: David Mosberger Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a429cfef0286..ede011828727 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1710,15 +1710,16 @@ static void atmel_get_ip_name(struct uart_port *port) struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); int name = atmel_uart_readl(port, ATMEL_US_NAME); u32 version; - u32 usart, dbgu_uart; + u32 usart, dbgu_uart, new_uart; /* ASCII decoding for IP version */ usart = 0x55534152; /* USAR(T) */ dbgu_uart = 0x44424755; /* DBGU */ + new_uart = 0x55415254; /* UART */ atmel_port->has_hw_timer = false; - if (name == usart) { - dev_dbg(port->dev, "Usart with hw timer\n"); + if (name == usart || name == new_uart) { + dev_dbg(port->dev, "Usart or uart with hw timer\n"); atmel_port->has_hw_timer = true; } else if (name == dbgu_uart) { dev_dbg(port->dev, "Dbgu or uart without hw timer\n"); -- cgit From b78cd1691404ca26ea7ede3d899b8bd2482da745 Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 26 Jan 2016 12:34:49 +0100 Subject: serial: atmel: Use atmel_port consistently In all functions other than atmel_serial_probe_fifos, atmel_serial_probe, and atmel_console_init, the name "port" is used to refer to an instance of struct uart_port. In many of these functions, "atmel_port" is used to refer to an instance of struct atmel_uart_port. We make the use of the name "port" consistent by making atmel_serial_probe_fifos, atmel_serial_probe, and atmel_console_init use "atmel_port" to refer to an instance of struct atmel_uart_port instead of the previous name of "port". Signed-off-by: Jaeden Amero Signed-off-by: Kyle Roeschley Acked-by: Karthik Manamcheri [nicolas.ferre@atmel.com: fix typo in variable, adapt to newer kernel] Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 95 ++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index ede011828727..b30c93f80899 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -2479,13 +2479,13 @@ static int __init atmel_console_init(void) struct atmel_uart_data *pdata = dev_get_platdata(&atmel_default_console_device->dev); int id = pdata->num; - struct atmel_uart_port *port = &atmel_ports[id]; + struct atmel_uart_port *atmel_port = &atmel_ports[id]; - port->backup_imr = 0; - port->uart.line = id; + atmel_port->backup_imr = 0; + atmel_port->uart.line = id; add_preferred_console(ATMEL_DEVICENAME, id, NULL); - ret = atmel_init_port(port, atmel_default_console_device); + ret = atmel_init_port(atmel_port, atmel_default_console_device); if (ret) return ret; register_console(&atmel_console); @@ -2600,23 +2600,23 @@ static int atmel_serial_resume(struct platform_device *pdev) #define atmel_serial_resume NULL #endif -static void atmel_serial_probe_fifos(struct atmel_uart_port *port, +static void atmel_serial_probe_fifos(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { - port->fifo_size = 0; - port->rts_low = 0; - port->rts_high = 0; + atmel_port->fifo_size = 0; + atmel_port->rts_low = 0; + atmel_port->rts_high = 0; if (of_property_read_u32(pdev->dev.of_node, "atmel,fifo-size", - &port->fifo_size)) + &atmel_port->fifo_size)) return; - if (!port->fifo_size) + if (!atmel_port->fifo_size) return; - if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) { - port->fifo_size = 0; + if (atmel_port->fifo_size < ATMEL_MIN_FIFO_SIZE) { + atmel_port->fifo_size = 0; dev_err(&pdev->dev, "Invalid FIFO size\n"); return; } @@ -2629,22 +2629,22 @@ static void atmel_serial_probe_fifos(struct atmel_uart_port *port, * Threshold to a reasonably high value respecting this 16 data * empirical rule when possible. */ - port->rts_high = max_t(int, port->fifo_size >> 1, - port->fifo_size - ATMEL_RTS_HIGH_OFFSET); - port->rts_low = max_t(int, port->fifo_size >> 2, - port->fifo_size - ATMEL_RTS_LOW_OFFSET); + atmel_port->rts_high = max_t(int, atmel_port->fifo_size >> 1, + atmel_port->fifo_size - ATMEL_RTS_HIGH_OFFSET); + atmel_port->rts_low = max_t(int, atmel_port->fifo_size >> 2, + atmel_port->fifo_size - ATMEL_RTS_LOW_OFFSET); dev_info(&pdev->dev, "Using FIFO (%u data)\n", - port->fifo_size); + atmel_port->fifo_size); dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n", - port->rts_high); + atmel_port->rts_high); dev_dbg(&pdev->dev, "RTS Low Threshold : %2u data\n", - port->rts_low); + atmel_port->rts_low); } static int atmel_serial_probe(struct platform_device *pdev) { - struct atmel_uart_port *port; + struct atmel_uart_port *atmel_port; struct device_node *np = pdev->dev.of_node; struct atmel_uart_data *pdata = dev_get_platdata(&pdev->dev); void *data; @@ -2675,87 +2675,88 @@ static int atmel_serial_probe(struct platform_device *pdev) goto err; } - port = &atmel_ports[ret]; - port->backup_imr = 0; - port->uart.line = ret; - atmel_serial_probe_fifos(port, pdev); + atmel_port = &atmel_ports[ret]; + atmel_port->backup_imr = 0; + atmel_port->uart.line = ret; + atmel_serial_probe_fifos(atmel_port, pdev); - spin_lock_init(&port->lock_suspended); + spin_lock_init(&atmel_port->lock_suspended); - ret = atmel_init_port(port, pdev); + ret = atmel_init_port(atmel_port, pdev); if (ret) goto err_clear_bit; - port->gpios = mctrl_gpio_init(&port->uart, 0); - if (IS_ERR(port->gpios)) { - ret = PTR_ERR(port->gpios); + atmel_port->gpios = mctrl_gpio_init(&atmel_port->uart, 0); + if (IS_ERR(atmel_port->gpios)) { + ret = PTR_ERR(atmel_port->gpios); goto err_clear_bit; } - if (!atmel_use_pdc_rx(&port->uart)) { + if (!atmel_use_pdc_rx(&atmel_port->uart)) { ret = -ENOMEM; data = kmalloc(sizeof(struct atmel_uart_char) * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL); if (!data) goto err_alloc_ring; - port->rx_ring.buf = data; + atmel_port->rx_ring.buf = data; } - rs485_enabled = port->uart.rs485.flags & SER_RS485_ENABLED; + rs485_enabled = atmel_port->uart.rs485.flags & SER_RS485_ENABLED; - ret = uart_add_one_port(&atmel_uart, &port->uart); + ret = uart_add_one_port(&atmel_uart, &atmel_port->uart); if (ret) goto err_add_port; #ifdef CONFIG_SERIAL_ATMEL_CONSOLE - if (atmel_is_console_port(&port->uart) + if (atmel_is_console_port(&atmel_port->uart) && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { /* * The serial core enabled the clock for us, so undo * the clk_prepare_enable() in atmel_console_setup() */ - clk_disable_unprepare(port->clk); + clk_disable_unprepare(atmel_port->clk); } #endif device_init_wakeup(&pdev->dev, 1); - platform_set_drvdata(pdev, port); + platform_set_drvdata(pdev, atmel_port); /* * The peripheral clock has been disabled by atmel_init_port(): * enable it before accessing I/O registers */ - clk_prepare_enable(port->clk); + clk_prepare_enable(atmel_port->clk); if (rs485_enabled) { - atmel_uart_writel(&port->uart, ATMEL_US_MR, + atmel_uart_writel(&atmel_port->uart, ATMEL_US_MR, ATMEL_US_USMODE_NORMAL); - atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN); + atmel_uart_writel(&atmel_port->uart, ATMEL_US_CR, + ATMEL_US_RTSEN); } /* * Get port name of usart or uart */ - atmel_get_ip_name(&port->uart); + atmel_get_ip_name(&atmel_port->uart); /* * The peripheral clock can now safely be disabled till the port * is used */ - clk_disable_unprepare(port->clk); + clk_disable_unprepare(atmel_port->clk); return 0; err_add_port: - kfree(port->rx_ring.buf); - port->rx_ring.buf = NULL; + kfree(atmel_port->rx_ring.buf); + atmel_port->rx_ring.buf = NULL; err_alloc_ring: - if (!atmel_is_console_port(&port->uart)) { - clk_put(port->clk); - port->clk = NULL; + if (!atmel_is_console_port(&atmel_port->uart)) { + clk_put(atmel_port->clk); + atmel_port->clk = NULL; } err_clear_bit: - clear_bit(port->uart.line, atmel_ports_in_use); + clear_bit(atmel_port->uart.line, atmel_ports_in_use); err: return ret; } -- cgit From b7ed5161f17a39ed09fd799a919b5f6de688251d Mon Sep 17 00:00:00 2001 From: Wills Wang Date: Sun, 20 Dec 2015 12:55:23 +0800 Subject: sc16is7xx: fix incorrect register bits macro In datasheet, Modem Status Register MSR[4-7] reflect the modem pins CTS/DSR/RI/CD signal state. Signed-off-by: Wills Wang Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 13f8d5f70272..311e7bc07a24 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -196,14 +196,14 @@ * or (IO6) * - only on 75x/76x */ -#define SC16IS7XX_MSR_CTS_BIT (1 << 0) /* CTS */ -#define SC16IS7XX_MSR_DSR_BIT (1 << 1) /* DSR (IO4) +#define SC16IS7XX_MSR_CTS_BIT (1 << 4) /* CTS */ +#define SC16IS7XX_MSR_DSR_BIT (1 << 5) /* DSR (IO4) * - only on 75x/76x */ -#define SC16IS7XX_MSR_RI_BIT (1 << 2) /* RI (IO7) +#define SC16IS7XX_MSR_RI_BIT (1 << 6) /* RI (IO7) * - only on 75x/76x */ -#define SC16IS7XX_MSR_CD_BIT (1 << 3) /* CD (IO6) +#define SC16IS7XX_MSR_CD_BIT (1 << 7) /* CD (IO6) * - only on 75x/76x */ #define SC16IS7XX_MSR_DELTA_MASK 0x0F /* Any of the delta bits! */ @@ -240,7 +240,7 @@ /* IOControl register bits (Only 750/760) */ #define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */ -#define SC16IS7XX_IOCONTROL_GPIO_BIT (1 << 1) /* Enable GPIO[7:4] */ +#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */ #define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */ /* EFCR register bits */ @@ -687,7 +687,7 @@ static void sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno) case SC16IS7XX_IIR_CTSRTS_SRC: msr = sc16is7xx_port_read(port, SC16IS7XX_MSR_REG); uart_handle_cts_change(port, - !!(msr & SC16IS7XX_MSR_CTS_BIT)); + !!(msr & SC16IS7XX_MSR_DCTS_BIT)); break; case SC16IS7XX_IIR_THRI_SRC: sc16is7xx_handle_tx(port); -- cgit From 2f2fd0894991a04bf3581104d5ea3a8dc9a4f01f Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Fri, 15 Jan 2016 14:32:20 -0600 Subject: serial: amba-pl011: use cpu_relax when polling registers Busy loops that poll on a register should call cpu_relax(). On some architectures, it can lower CPU power consumption or yield to a hyperthreaded twin processor. It also serves as a compiler barrier, so it can replace barrier() calls. Signed-off-by: Timur Tabi Reviewed-by: Dave Martin Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index de846027ba47..618763b2539a 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1167,7 +1167,7 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap) /* Disable RX and TX DMA */ while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) - barrier(); + cpu_relax(); spin_lock_irq(&uap->port.lock); uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE); @@ -1611,7 +1611,7 @@ static void pl011_put_poll_char(struct uart_port *port, container_of(port, struct uart_amba_port, port); while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) - barrier(); + cpu_relax(); pl011_write(ch, uap, REG_DR); } @@ -2150,7 +2150,7 @@ static void pl011_console_putchar(struct uart_port *port, int ch) container_of(port, struct uart_amba_port, port); while (pl011_read(uap, REG_FR) & UART01x_FR_TXFF) - barrier(); + cpu_relax(); pl011_write(ch, uap, REG_DR); } @@ -2158,7 +2158,7 @@ static void pl011_console_write(struct console *co, const char *s, unsigned int count) { struct uart_amba_port *uap = amba_ports[co->index]; - unsigned int status, old_cr = 0, new_cr; + unsigned int old_cr = 0, new_cr; unsigned long flags; int locked = 1; @@ -2188,9 +2188,8 @@ pl011_console_write(struct console *co, const char *s, unsigned int count) * Finally, wait for transmitter to become empty * and restore the TCR */ - do { - status = pl011_read(uap, REG_FR); - } while (status & UART01x_FR_BUSY); + while (pl011_read(uap, REG_FR) & UART01x_FR_BUSY) + cpu_relax(); if (!uap->vendor->always_enabled) pl011_write(old_cr, uap, REG_CR); @@ -2302,13 +2301,13 @@ static struct console amba_console = { static void pl011_putc(struct uart_port *port, int c) { while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF) - ; + cpu_relax(); if (port->iotype == UPIO_MEM32) writel(c, port->membase + UART01x_DR); else writeb(c, port->membase + UART01x_DR); while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY) - ; + cpu_relax(); } static void pl011_early_write(struct console *con, const char *s, unsigned n) -- cgit From ff52a9a0c3c64ae33fe65b94733df3a1a6ce1a70 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 20 Jan 2016 11:40:03 +0100 Subject: serial: amba-pl011: mark vendor_zte as __maybe_unused The pl011 driver has gone back and forth on the definition of the ZTE specific variation of the hardware definitions, but the current state is that the vendor definition is left in place yet unused: drivers/tty/serial/amba-pl011.c:190:27: warning: 'vendor_zte' defined but not used [-Wunused-variable] I don't know what the plan forward is to get this code to work, but the current behavior is a bit annoying as we get a warning whenever we build this driver. This patch does not help us to make it work, but at least shuts up the warning. Signed-off-by: Arnd Bergmann Fixes: 7ec758718920 ("tty: amba-pl011: add support for ZTE UART (EXPERIMENTAL)") Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 618763b2539a..500232ad38f3 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -187,7 +187,7 @@ static const u16 pl011_zte_offsets[REG_ARRAY_SIZE] = { [REG_DMACR] = ZX_UART011_DMACR, }; -static struct vendor_data vendor_zte = { +static struct vendor_data vendor_zte __maybe_unused = { .reg_offset = pl011_zte_offsets, .access_32b = true, .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8, -- cgit From 30c6c352ce4796f8c9815452db84c78805bbbe10 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sun, 27 Dec 2015 22:29:42 +0800 Subject: serial: 8250_pci: use to_pci_dev() Use to_pci_dev() instead of open-coding it. Signed-off-by: Geliang Tang Reviewed-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index e71ec78fc11e..90025e4f3452 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1541,10 +1541,9 @@ pci_brcm_trumanage_setup(struct serial_private *priv, static int pci_fintek_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { + struct pci_dev *pci_dev = to_pci_dev(port->dev); u8 setting; u8 *index = (u8 *) port->private_data; - struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev, - dev); pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting); -- cgit From 8178a89eb89e025868992aff32ab78503ec5fa1e Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 22 Dec 2015 08:57:06 -0700 Subject: serial/8250_pci: simplify Pericom handling Considering that pci_pericom_setup(()'s only difference to pci_default_setup() is the setting of the uartclk field, and taking into account that this field already gets taken care of by having the base_baud field filled in the pci_boards[] entries, there's no need for both the function and the quirks table entry. Signed-off-by: Jan Beulich Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 90025e4f3452..da501c1390db 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1334,29 +1334,6 @@ static int pci_default_setup(struct serial_private *priv, return setup_port(priv, port, bar, offset, board->reg_shift); } -static int pci_pericom_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) -{ - unsigned int bar, offset = board->first_offset, maxnr; - - bar = FL_GET_BASE(board->flags); - if (board->flags & FL_BASE_BARS) - bar += idx; - else - offset += idx * board->uart_offset; - - maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> - (board->reg_shift + 3); - - if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) - return 1; - - port->port.uartclk = 14745600; - - return setup_port(priv, port, bar, offset, board->reg_shift); -} - static int ce4100_serial_setup(struct serial_private *priv, const struct pciserial_board *board, @@ -2243,16 +2220,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_default_setup, .exit = pci_plx9050_exit, }, - /* - * Pericom - */ - { - .vendor = PCI_VENDOR_ID_PERICOM, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_pericom_setup, - }, /* * PLX */ -- cgit From 0b0cced19ab15c9ebbfbc6c4c0d932863e18fbe5 Mon Sep 17 00:00:00 2001 From: Yoshinori Sato Date: Thu, 24 Dec 2015 11:24:48 +0100 Subject: serial: sh-sci: Add CONFIG_SERIAL_EARLYCON support "earlyprintk" is architecture specific option. General "earlycon" option support is much better. Signed-off-by: Yoshinori Sato [uli: preserve other SCSCR bits when asserting RE and TE] Signed-off-by: Ulrich Hecht [geert: rewording, #ifdef rework] Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 6 ++++ drivers/tty/serial/sh-sci.c | 77 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index e5c9250426a8..54b6f2c15f72 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -745,6 +745,12 @@ config SERIAL_SH_SCI_CONSOLE depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE +config SERIAL_SH_SCI_EARLYCON + bool "Support for early console on SuperH SCI(F)" + depends on SERIAL_SH_SCI=y + select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON + config SERIAL_SH_SCI_DMA bool "DMA support" depends on SERIAL_SH_SCI && DMA_ENGINE diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 4646a9f531ad..ec08f1bff753 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -637,7 +637,8 @@ static void sci_clear_SCxSR(struct uart_port *port, unsigned int mask) } } -#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) +#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \ + defined(CONFIG_SERIAL_SH_SCI_EARLYCON) #ifdef CONFIG_CONSOLE_POLL static int sci_poll_get_char(struct uart_port *port) @@ -678,7 +679,8 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) serial_port_out(port, SCxTDR, c); sci_clear_SCxSR(port, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); } -#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ +#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE || + CONFIG_SERIAL_SH_SCI_EARLYCON */ static void sci_init_pins(struct uart_port *port, unsigned int cflag) { @@ -2632,7 +2634,8 @@ static void sci_cleanup_single(struct sci_port *port) pm_runtime_disable(port->port.dev); } -#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE +#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || \ + defined(CONFIG_SERIAL_SH_SCI_EARLYCON) static void serial_console_putchar(struct uart_port *port, int ch) { sci_poll_put_char(port, ch); @@ -2652,9 +2655,12 @@ static void serial_console_write(struct console *co, const char *s, int locked = 1; local_irq_save(flags); +#if defined(SUPPORT_SYSRQ) if (port->sysrq) locked = 0; - else if (oops_in_progress) + else +#endif + if (oops_in_progress) locked = spin_trylock(&port->lock); else spin_lock(&port->lock); @@ -2764,7 +2770,7 @@ static inline int sci_probe_earlyprintk(struct platform_device *pdev) #define SCI_CONSOLE NULL -#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ +#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE || CONFIG_SERIAL_SH_SCI_EARLYCON */ static const char banner[] __initconst = "SuperH (H)SCI(F) driver initialized"; @@ -2998,6 +3004,67 @@ static void __exit sci_exit(void) early_platform_init_buffer("earlyprintk", &sci_driver, early_serial_buf, ARRAY_SIZE(early_serial_buf)); #endif +#ifdef CONFIG_SERIAL_SH_SCI_EARLYCON +static struct __init plat_sci_port port_cfg; + +static int __init early_console_setup(struct earlycon_device *device, + int type) +{ + if (!device->port.membase) + return -ENODEV; + + device->port.serial_in = sci_serial_in; + device->port.serial_out = sci_serial_out; + device->port.type = type; + memcpy(&sci_ports[0].port, &device->port, sizeof(struct uart_port)); + sci_ports[0].cfg = &port_cfg; + sci_ports[0].cfg->type = type; + sci_probe_regmap(sci_ports[0].cfg); + port_cfg.scscr = sci_serial_in(&sci_ports[0].port, SCSCR) | + SCSCR_RE | SCSCR_TE; + sci_serial_out(&sci_ports[0].port, SCSCR, port_cfg.scscr); + + device->con->write = serial_console_write; + return 0; +} +static int __init sci_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCI); +} +static int __init scif_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCIF); +} +static int __init scifa_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCIFA); +} +static int __init scifb_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_SCIFB); +} +static int __init hscif_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + return early_console_setup(device, PORT_HSCIF); +} + +EARLYCON_DECLARE(sci, sci_early_console_setup); +OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup); +EARLYCON_DECLARE(scif, scif_early_console_setup); +OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup); +EARLYCON_DECLARE(scifa, scifa_early_console_setup); +OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup); +EARLYCON_DECLARE(scifb, scifb_early_console_setup); +OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup); +EARLYCON_DECLARE(hscif, hscif_early_console_setup); +OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup); +#endif /* CONFIG_SERIAL_SH_SCI_EARLYCON */ + module_init(sci_init); module_exit(sci_exit); -- cgit From e3538c37ee383228cb9f89fb9312c417f5eb3bfc Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:49 -0800 Subject: tty: xuartps: Beautify read-modify writes Non-functional, formatting changes to ease reading the code. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Reviewed-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 009e0dbc12d2..50d4082d2354 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -515,12 +515,14 @@ static void cdns_uart_start_tx(struct uart_port *port) if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port)) return; - status = readl(port->membase + CDNS_UART_CR_OFFSET); - /* Set the TX enable bit and clear the TX disable bit to enable the + /* + * Set the TX enable bit and clear the TX disable bit to enable the * transmitter. */ - writel((status & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN, - port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR_OFFSET); + status &= ~CDNS_UART_CR_TX_DIS; + status |= CDNS_UART_CR_TX_EN; + writel(status, port->membase + CDNS_UART_CR_OFFSET); while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { @@ -1123,8 +1125,9 @@ static void cdns_uart_console_write(struct console *co, const char *s, * clear the TX disable bit to enable the transmitter. */ ctrl = readl(port->membase + CDNS_UART_CR_OFFSET); - writel((ctrl & ~CDNS_UART_CR_TX_DIS) | CDNS_UART_CR_TX_EN, - port->membase + CDNS_UART_CR_OFFSET); + ctrl &= ~CDNS_UART_CR_TX_DIS; + ctrl |= CDNS_UART_CR_TX_EN; + writel(ctrl, port->membase + CDNS_UART_CR_OFFSET); uart_console_write(port, s, count, cdns_uart_console_putchar); cdns_uart_console_wait_tx(port); -- cgit From f0f54a806b2df97485519a7c4ebc45feed08a306 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:50 -0800 Subject: tty: xuartps: Use spinlock to serialize HW access Instead of disabling the IRQ, use the spin lock to serialize accesses to the HW. This protects the driver from interference of non-IRQ callbacks with each other and makes the driver more consistent in its serialization method. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 50d4082d2354..2c98c357d9a0 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -945,12 +945,10 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) #ifdef CONFIG_CONSOLE_POLL static int cdns_uart_poll_get_char(struct uart_port *port) { - u32 imr; int c; + unsigned long flags; - /* Disable all interrupts */ - imr = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(imr, port->membase + CDNS_UART_IDR_OFFSET); + spin_lock_irqsave(&port->lock, flags); /* Check if FIFO is empty */ if (readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY) @@ -959,19 +957,16 @@ static int cdns_uart_poll_get_char(struct uart_port *port) c = (unsigned char) readl( port->membase + CDNS_UART_FIFO_OFFSET); - /* Enable interrupts */ - writel(imr, port->membase + CDNS_UART_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); return c; } static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) { - u32 imr; + unsigned long flags; - /* Disable all interrupts */ - imr = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(imr, port->membase + CDNS_UART_IDR_OFFSET); + spin_lock_irqsave(&port->lock, flags); /* Wait until FIFO is empty */ while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & @@ -986,8 +981,7 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) CDNS_UART_SR_TXEMPTY)) cpu_relax(); - /* Enable interrupts */ - writel(imr, port->membase + CDNS_UART_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); return; } -- cgit From ea8dd8e585761c2811d0566938983868d89976a8 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:51 -0800 Subject: tty: xuartps: Don't consider circular buffer when enabling transmitter Restarting the transmitter even if the circ buffer is empty may be necessary to push out remaining data when the port is restarted after being stopped. Cc: Peter Hurley Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 2c98c357d9a0..6a7cd4e057ae 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -512,7 +512,7 @@ static void cdns_uart_start_tx(struct uart_port *port) { unsigned int status, numbytes = port->fifosize; - if (uart_circ_empty(&port->state->xmit) || uart_tx_stopped(port)) + if (uart_tx_stopped(port)) return; /* @@ -524,6 +524,9 @@ static void cdns_uart_start_tx(struct uart_port *port) status |= CDNS_UART_CR_TX_EN; writel(status, port->membase + CDNS_UART_CR_OFFSET); + if (uart_circ_empty(&port->state->xmit)) + return; + while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { /* Break if no more data available in the UART buffer */ -- cgit From aea8f3ddcf5de21188b737345fc2f62526350874 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:52 -0800 Subject: tty: xuartps: Clear interrupt status register in shutdown When shutting down the UART, clear the interrupt status register. Bits in the ISR are cleared by writing them as '1'. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Reviewed-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 6a7cd4e057ae..ef114d7a0623 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -828,6 +828,7 @@ static void cdns_uart_shutdown(struct uart_port *port) /* Disable interrupts */ status = readl(port->membase + CDNS_UART_IMR_OFFSET); writel(status, port->membase + CDNS_UART_IDR_OFFSET); + writel(0xffffffff, port->membase + CDNS_UART_ISR_OFFSET); /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, -- cgit From 6e14f7c1f2c2e8d783b4bc50e7ac31b468910698 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:53 -0800 Subject: tty: xuartps: Improve startup function The startup function is supposed to initialize the UART for receiving. Hence, don't enable the TX part. Also, protect HW accesses with the port lock. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ef114d7a0623..6ffd3bbe3e18 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -758,6 +758,7 @@ static void cdns_uart_set_termios(struct uart_port *port, */ static int cdns_uart_startup(struct uart_port *port) { + unsigned long flags; unsigned int retval = 0, status = 0; retval = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, @@ -765,6 +766,8 @@ static int cdns_uart_startup(struct uart_port *port) if (retval) return retval; + spin_lock_irqsave(&port->lock, flags); + /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, port->membase + CDNS_UART_CR_OFFSET); @@ -775,15 +778,14 @@ static int cdns_uart_startup(struct uart_port *port) writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST, port->membase + CDNS_UART_CR_OFFSET); - status = readl(port->membase + CDNS_UART_CR_OFFSET); - - /* Clear the RX disable and TX disable bits and then set the TX enable - * bit and RX enable bit to enable the transmitter and receiver. + /* + * Clear the RX disable bit and then set the RX enable bit to enable + * the receiver. */ - writel((status & ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS)) - | (CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN | - CDNS_UART_CR_STOPBRK), - port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR_OFFSET); + status &= CDNS_UART_CR_RX_DIS; + status |= CDNS_UART_CR_RX_EN; + writel(status, port->membase + CDNS_UART_CR_OFFSET); /* Set the Mode Register with normal mode,8 data bits,1 stop bit, * no parity. @@ -814,6 +816,8 @@ static int cdns_uart_startup(struct uart_port *port) CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); + return retval; } -- cgit From 4c0b92ed9ebab389cdefd56efe81f8c3d8d458d5 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:54 -0800 Subject: tty: xuartps: Keep lock for whole ISR The RX path in the interrupt handler released a lock unnecessarily. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 6ffd3bbe3e18..ab3995d00973 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -265,9 +265,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, data, status); } - spin_unlock(&port->lock); tty_flip_buffer_push(&port->state->port); - spin_lock(&port->lock); } /* Dispatch an appropriate handler */ -- cgit From a19eda0f49e5b19c403c5fe33e1e2f46e7b02082 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:55 -0800 Subject: tty: xuartps: Acquire port lock for shutdown Shutting down the UART port can happen while console operations are in progress. Holding the port lock serializes these operations and avoids the UART HW to be disabled in the middle of console prints. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ab3995d00973..f3ac69387b0a 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -826,6 +826,9 @@ static int cdns_uart_startup(struct uart_port *port) static void cdns_uart_shutdown(struct uart_port *port) { int status; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); /* Disable interrupts */ status = readl(port->membase + CDNS_UART_IMR_OFFSET); @@ -835,6 +838,9 @@ static void cdns_uart_shutdown(struct uart_port *port) /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, port->membase + CDNS_UART_CR_OFFSET); + + spin_unlock_irqrestore(&port->lock, flags); + free_irq(port->irq, port); } -- cgit From 5ede4a5cde278af46aacecca25470943b8c5a086 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Sat, 26 Dec 2015 02:43:56 -0800 Subject: tty: xuartps: Move RX path into helper function Move RX-related IRQ handling into a helper function. Fixes a problem where every char received after a parity or frame error in the current isr will also be tagged as a parity or frame error. Signed-off-by: Soren Brinkmann Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 50 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index f3ac69387b0a..db9e23eaf300 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -172,28 +172,8 @@ struct cdns_uart { #define to_cdns_uart(_nb) container_of(_nb, struct cdns_uart, \ clk_rate_change_nb); -/** - * cdns_uart_isr - Interrupt handler - * @irq: Irq number - * @dev_id: Id of the port - * - * Return: IRQHANDLED - */ -static irqreturn_t cdns_uart_isr(int irq, void *dev_id) +static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) { - struct uart_port *port = (struct uart_port *)dev_id; - unsigned long flags; - unsigned int isrstatus, numbytes; - unsigned int data; - char status = TTY_NORMAL; - - spin_lock_irqsave(&port->lock, flags); - - /* Read the interrupt status register to determine which - * interrupt(s) is/are active. - */ - isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); - /* * There is no hardware break detection, so we interpret framing * error with all-zeros data as a break sequence. Most of the time, @@ -223,6 +203,9 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) /* Receive Timeout Interrupt */ while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY)) { + u32 data; + char status = TTY_NORMAL; + data = readl(port->membase + CDNS_UART_FIFO_OFFSET); /* Non-NULL byte after BREAK is garbage (99%) */ @@ -263,10 +246,33 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) } uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, - data, status); + data, status); } tty_flip_buffer_push(&port->state->port); } +} + +/** + * cdns_uart_isr - Interrupt handler + * @irq: Irq number + * @dev_id: Id of the port + * + * Return: IRQHANDLED + */ +static irqreturn_t cdns_uart_isr(int irq, void *dev_id) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned long flags; + unsigned int isrstatus, numbytes; + + spin_lock_irqsave(&port->lock, flags); + + /* Read the interrupt status register to determine which + * interrupt(s) is/are active. + */ + isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); + + cdns_uart_handle_rx(port, isrstatus); /* Dispatch an appropriate handler */ if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { -- cgit From 55861d11c5c804f053411b6e5505d19f561e46a3 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:36 -0800 Subject: tty: xuartps: Move request_irq to after setting up the HW Request_irq() should be _after_ h/w programming, otherwise an interrupt could be triggered and in-progress before the h/w has been setup. Reported-by: Peter Hurley Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index db9e23eaf300..5da1c51e9e40 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -762,13 +762,9 @@ static void cdns_uart_set_termios(struct uart_port *port, */ static int cdns_uart_startup(struct uart_port *port) { + int ret; unsigned long flags; - unsigned int retval = 0, status = 0; - - retval = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, - (void *)port); - if (retval) - return retval; + unsigned int status = 0; spin_lock_irqsave(&port->lock, flags); @@ -814,15 +810,22 @@ static int cdns_uart_startup(struct uart_port *port) writel(readl(port->membase + CDNS_UART_ISR_OFFSET), port->membase + CDNS_UART_ISR_OFFSET); + spin_unlock_irqrestore(&port->lock, flags); + + ret = request_irq(port->irq, cdns_uart_isr, 0, CDNS_UART_NAME, port); + if (ret) { + dev_err(port->dev, "request_irq '%d' failed with %d\n", + port->irq, ret); + return ret; + } + /* Set the Interrupt Registers with desired interrupts */ writel(CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER_OFFSET); - spin_unlock_irqrestore(&port->lock, flags); - - return retval; + return 0; } /** -- cgit From 373e882f9ecfb383fcd3d8878b2eb20e17d45792 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:37 -0800 Subject: tty: xuartps: Refactor IRQ handling The system could deadlock handling RX IRQs when RX-related IRQ conditions became true while the receiver was disabled. To avoid this, enable/disable the RX/TX IRQs together with the receiver/transmitter. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 5da1c51e9e40..a0039cbcf812 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -126,6 +126,10 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); #define CDNS_UART_IXR_RXEMPTY 0x00000002 /* RX FIFO empty interrupt. */ #define CDNS_UART_IXR_MASK 0x00001FFF /* Valid bit mask */ +#define CDNS_UART_RX_IRQS (CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | \ + CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_RXTRIG | \ + CDNS_UART_IXR_TOUT) + /* Goes in read_status_mask for break detection as the HW doesn't do it*/ #define CDNS_UART_IXR_BRK 0x80000000 @@ -272,7 +276,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) */ isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); - cdns_uart_handle_rx(port, isrstatus); + if (isrstatus & CDNS_UART_RX_IRQS) + cdns_uart_handle_rx(port, isrstatus); /* Dispatch an appropriate handler */ if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { @@ -580,9 +585,12 @@ static void cdns_uart_stop_rx(struct uart_port *port) { unsigned int regval; + /* Disable RX IRQs */ + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IDR_OFFSET); + + /* Disable the receiver */ regval = readl(port->membase + CDNS_UART_CR_OFFSET); regval |= CDNS_UART_CR_RX_DIS; - /* Disable the receiver */ writel(regval, port->membase + CDNS_UART_CR_OFFSET); } @@ -820,10 +828,7 @@ static int cdns_uart_startup(struct uart_port *port) } /* Set the Interrupt Registers with desired interrupts */ - writel(CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_PARITY | - CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN | - CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_TOUT, - port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER_OFFSET); return 0; } -- cgit From 354fb1a7d7e54a79d042f0a92dbd484bd3e900e6 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:38 -0800 Subject: tty: xuartps: Cleanup: Reformat if-else Convert an if-else into the more common early return on error, reducing the indent level of the happy path. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 124 ++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index a0039cbcf812..8014dd3c6d55 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -202,58 +202,55 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) isrstatus &= port->read_status_mask; isrstatus &= ~port->ignore_status_mask; - if ((isrstatus & CDNS_UART_IXR_TOUT) || - (isrstatus & CDNS_UART_IXR_RXTRIG)) { - /* Receive Timeout Interrupt */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_RXEMPTY)) { - u32 data; - char status = TTY_NORMAL; - - data = readl(port->membase + CDNS_UART_FIFO_OFFSET); - - /* Non-NULL byte after BREAK is garbage (99%) */ - if (data && (port->read_status_mask & - CDNS_UART_IXR_BRK)) { - port->read_status_mask &= ~CDNS_UART_IXR_BRK; - port->icount.brk++; - if (uart_handle_break(port)) - continue; - } + if (!(isrstatus & (CDNS_UART_IXR_TOUT | CDNS_UART_IXR_RXTRIG))) + return; + + while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + CDNS_UART_SR_RXEMPTY)) { + u32 data; + char status = TTY_NORMAL; + + data = readl(port->membase + CDNS_UART_FIFO_OFFSET); + + /* Non-NULL byte after BREAK is garbage (99%) */ + if (data && (port->read_status_mask & CDNS_UART_IXR_BRK)) { + port->read_status_mask &= ~CDNS_UART_IXR_BRK; + port->icount.brk++; + if (uart_handle_break(port)) + continue; + } #ifdef SUPPORT_SYSRQ - /* - * uart_handle_sysrq_char() doesn't work if - * spinlocked, for some reason - */ - if (port->sysrq) { - spin_unlock(&port->lock); - if (uart_handle_sysrq_char(port, - (unsigned char)data)) { - spin_lock(&port->lock); - continue; - } + /* + * uart_handle_sysrq_char() doesn't work if + * spinlocked, for some reason + */ + if (port->sysrq) { + spin_unlock(&port->lock); + if (uart_handle_sysrq_char(port, data)) { spin_lock(&port->lock); + continue; } + spin_lock(&port->lock); + } #endif - port->icount.rx++; - - if (isrstatus & CDNS_UART_IXR_PARITY) { - port->icount.parity++; - status = TTY_PARITY; - } else if (isrstatus & CDNS_UART_IXR_FRAMING) { - port->icount.frame++; - status = TTY_FRAME; - } else if (isrstatus & CDNS_UART_IXR_OVERRUN) { - port->icount.overrun++; - } + port->icount.rx++; - uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, - data, status); + if (isrstatus & CDNS_UART_IXR_PARITY) { + port->icount.parity++; + status = TTY_PARITY; + } else if (isrstatus & CDNS_UART_IXR_FRAMING) { + port->icount.frame++; + status = TTY_FRAME; + } else if (isrstatus & CDNS_UART_IXR_OVERRUN) { + port->icount.overrun++; } - tty_flip_buffer_push(&port->state->port); + + uart_insert_char(port, isrstatus, CDNS_UART_IXR_OVERRUN, + data, status); } + tty_flip_buffer_push(&port->state->port); } /** @@ -1429,27 +1426,30 @@ static int cdns_uart_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Cannot get uart_port structure\n"); rc = -ENODEV; goto err_out_notif_unreg; - } else { - /* Register the port. - * This function also registers this device with the tty layer - * and triggers invocation of the config_port() entry point. - */ - port->mapbase = res->start; - port->irq = irq; - port->dev = &pdev->dev; - port->uartclk = clk_get_rate(cdns_uart_data->uartclk); - port->private_data = cdns_uart_data; - cdns_uart_data->port = port; - platform_set_drvdata(pdev, port); - rc = uart_add_one_port(&cdns_uart_uart_driver, port); - if (rc) { - dev_err(&pdev->dev, - "uart_add_one_port() failed; err=%i\n", rc); - goto err_out_notif_unreg; - } - return 0; } + /* + * Register the port. + * This function also registers this device with the tty layer + * and triggers invocation of the config_port() entry point. + */ + port->mapbase = res->start; + port->irq = irq; + port->dev = &pdev->dev; + port->uartclk = clk_get_rate(cdns_uart_data->uartclk); + port->private_data = cdns_uart_data; + cdns_uart_data->port = port; + platform_set_drvdata(pdev, port); + + rc = uart_add_one_port(&cdns_uart_uart_driver, port); + if (rc) { + dev_err(&pdev->dev, + "uart_add_one_port() failed; err=%i\n", rc); + goto err_out_notif_unreg; + } + + return 0; + err_out_notif_unreg: #ifdef CONFIG_COMMON_CLK clk_notifier_unregister(cdns_uart_data->uartclk, -- cgit From 74ea66d4ca061a3cd4c0e924e51b60e924644852 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:39 -0800 Subject: tty: xuartps: Improve sysrq handling Handling magic sysrq included dropping a lock to avoid a deadlock that happened when cdns_uart_console_write tried to acquire a lock in the from the sysrq code path. By making the acquisition of the lock in cdns_uart_console_write depending on port->sysrq, cdns_uart_handle_rx can be simplified to simply call uart_handle_sysrq. Suggested-by: Peter Hurley Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 8014dd3c6d55..0eecba88298f 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -220,20 +220,8 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) continue; } -#ifdef SUPPORT_SYSRQ - /* - * uart_handle_sysrq_char() doesn't work if - * spinlocked, for some reason - */ - if (port->sysrq) { - spin_unlock(&port->lock); - if (uart_handle_sysrq_char(port, data)) { - spin_lock(&port->lock); - continue; - } - spin_lock(&port->lock); - } -#endif + if (uart_handle_sysrq_char(port, data)) + continue; port->icount.rx++; @@ -1128,7 +1116,9 @@ static void cdns_uart_console_write(struct console *co, const char *s, unsigned int imr, ctrl; int locked = 1; - if (oops_in_progress) + if (port->sysrq) + locked = 0; + else if (oops_in_progress) locked = spin_trylock_irqsave(&port->lock, flags); else spin_lock_irqsave(&port->lock, flags); -- cgit From a8df6a51600a93ce3d13eebbdf81f45bf719cb15 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:40 -0800 Subject: tty: xuartps: Remove '_OFFSET' suffix from #defines Remove the _OFFSET suffix from all register defines which makes code a little easier to read and avoids a few line breaks. Suggested-by: Peter Hurley Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 221 ++++++++++++++++++------------------- 1 file changed, 106 insertions(+), 115 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 0eecba88298f..3ff6e3c2347c 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -50,24 +50,24 @@ module_param(rx_timeout, uint, S_IRUGO); MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255"); /* Register offsets for the UART. */ -#define CDNS_UART_CR_OFFSET 0x00 /* Control Register */ -#define CDNS_UART_MR_OFFSET 0x04 /* Mode Register */ -#define CDNS_UART_IER_OFFSET 0x08 /* Interrupt Enable */ -#define CDNS_UART_IDR_OFFSET 0x0C /* Interrupt Disable */ -#define CDNS_UART_IMR_OFFSET 0x10 /* Interrupt Mask */ -#define CDNS_UART_ISR_OFFSET 0x14 /* Interrupt Status */ -#define CDNS_UART_BAUDGEN_OFFSET 0x18 /* Baud Rate Generator */ -#define CDNS_UART_RXTOUT_OFFSET 0x1C /* RX Timeout */ -#define CDNS_UART_RXWM_OFFSET 0x20 /* RX FIFO Trigger Level */ -#define CDNS_UART_MODEMCR_OFFSET 0x24 /* Modem Control */ -#define CDNS_UART_MODEMSR_OFFSET 0x28 /* Modem Status */ -#define CDNS_UART_SR_OFFSET 0x2C /* Channel Status */ -#define CDNS_UART_FIFO_OFFSET 0x30 /* FIFO */ -#define CDNS_UART_BAUDDIV_OFFSET 0x34 /* Baud Rate Divider */ -#define CDNS_UART_FLOWDEL_OFFSET 0x38 /* Flow Delay */ -#define CDNS_UART_IRRX_PWIDTH_OFFSET 0x3C /* IR Min Received Pulse Width */ -#define CDNS_UART_IRTX_PWIDTH_OFFSET 0x40 /* IR Transmitted pulse Width */ -#define CDNS_UART_TXWM_OFFSET 0x44 /* TX FIFO Trigger Level */ +#define CDNS_UART_CR 0x00 /* Control Register */ +#define CDNS_UART_MR 0x04 /* Mode Register */ +#define CDNS_UART_IER 0x08 /* Interrupt Enable */ +#define CDNS_UART_IDR 0x0C /* Interrupt Disable */ +#define CDNS_UART_IMR 0x10 /* Interrupt Mask */ +#define CDNS_UART_ISR 0x14 /* Interrupt Status */ +#define CDNS_UART_BAUDGEN 0x18 /* Baud Rate Generator */ +#define CDNS_UART_RXTOUT 0x1C /* RX Timeout */ +#define CDNS_UART_RXWM 0x20 /* RX FIFO Trigger Level */ +#define CDNS_UART_MODEMCR 0x24 /* Modem Control */ +#define CDNS_UART_MODEMSR 0x28 /* Modem Status */ +#define CDNS_UART_SR 0x2C /* Channel Status */ +#define CDNS_UART_FIFO 0x30 /* FIFO */ +#define CDNS_UART_BAUDDIV 0x34 /* Baud Rate Divider */ +#define CDNS_UART_FLOWDEL 0x38 /* Flow Delay */ +#define CDNS_UART_IRRX_PWIDTH 0x3C /* IR Min Received Pulse Width */ +#define CDNS_UART_IRTX_PWIDTH 0x40 /* IR Transmitted pulse Width */ +#define CDNS_UART_TXWM 0x44 /* TX FIFO Trigger Level */ /* Control Register Bit Definitions */ #define CDNS_UART_CR_STOPBRK 0x00000100 /* Stop TX break */ @@ -184,15 +184,14 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) * there's another non-zero byte at the end of the sequence. */ if (isrstatus & CDNS_UART_IXR_FRAMING) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) { - if (!readl(port->membase + CDNS_UART_FIFO_OFFSET)) { + if (!readl(port->membase + CDNS_UART_FIFO)) { port->read_status_mask |= CDNS_UART_IXR_BRK; isrstatus &= ~CDNS_UART_IXR_FRAMING; } } - writel(CDNS_UART_IXR_FRAMING, - port->membase + CDNS_UART_ISR_OFFSET); + writel(CDNS_UART_IXR_FRAMING, port->membase + CDNS_UART_ISR); } /* drop byte with parity error if IGNPAR specified */ @@ -205,12 +204,11 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) if (!(isrstatus & (CDNS_UART_IXR_TOUT | CDNS_UART_IXR_RXTRIG))) return; - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_RXEMPTY)) { + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) { u32 data; char status = TTY_NORMAL; - data = readl(port->membase + CDNS_UART_FIFO_OFFSET); + data = readl(port->membase + CDNS_UART_FIFO); /* Non-NULL byte after BREAK is garbage (99%) */ if (data && (port->read_status_mask & CDNS_UART_IXR_BRK)) { @@ -259,7 +257,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) /* Read the interrupt status register to determine which * interrupt(s) is/are active. */ - isrstatus = readl(port->membase + CDNS_UART_ISR_OFFSET); + isrstatus = readl(port->membase + CDNS_UART_ISR); if (isrstatus & CDNS_UART_RX_IRQS) cdns_uart_handle_rx(port, isrstatus); @@ -268,7 +266,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { if (uart_circ_empty(&port->state->xmit)) { writel(CDNS_UART_IXR_TXEMPTY, - port->membase + CDNS_UART_IDR_OFFSET); + port->membase + CDNS_UART_IDR); } else { numbytes = port->fifosize; /* Break if no more data available in the UART buffer */ @@ -281,7 +279,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) */ writel(port->state->xmit.buf[ port->state->xmit.tail], - port->membase + CDNS_UART_FIFO_OFFSET); + port->membase + CDNS_UART_FIFO); port->icount.tx++; @@ -299,7 +297,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) } } - writel(isrstatus, port->membase + CDNS_UART_ISR_OFFSET); + writel(isrstatus, port->membase + CDNS_UART_ISR); /* be sure to release the lock and tty before leaving */ spin_unlock_irqrestore(&port->lock, flags); @@ -389,14 +387,14 @@ static unsigned int cdns_uart_set_baud_rate(struct uart_port *port, &div8); /* Write new divisors to hardware */ - mreg = readl(port->membase + CDNS_UART_MR_OFFSET); + mreg = readl(port->membase + CDNS_UART_MR); if (div8) mreg |= CDNS_UART_MR_CLKSEL; else mreg &= ~CDNS_UART_MR_CLKSEL; - writel(mreg, port->membase + CDNS_UART_MR_OFFSET); - writel(cd, port->membase + CDNS_UART_BAUDGEN_OFFSET); - writel(bdiv, port->membase + CDNS_UART_BAUDDIV_OFFSET); + writel(mreg, port->membase + CDNS_UART_MR); + writel(cd, port->membase + CDNS_UART_BAUDGEN); + writel(bdiv, port->membase + CDNS_UART_BAUDDIV); cdns_uart->baud = baud; return calc_baud; @@ -443,9 +441,9 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, spin_lock_irqsave(&cdns_uart->port->lock, flags); /* Disable the TX and RX to set baud rate */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&cdns_uart->port->lock, flags); @@ -470,11 +468,11 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, spin_lock_irqsave(&cdns_uart->port->lock, flags); /* Set TX/RX Reset */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); - while (readl(port->membase + CDNS_UART_CR_OFFSET) & + while (readl(port->membase + CDNS_UART_CR) & (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) cpu_relax(); @@ -483,11 +481,11 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, * enable bit and RX enable bit to enable the transmitter and * receiver. */ - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&cdns_uart->port->lock, flags); @@ -513,15 +511,15 @@ static void cdns_uart_start_tx(struct uart_port *port) * Set the TX enable bit and clear the TX disable bit to enable the * transmitter. */ - status = readl(port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR); status &= ~CDNS_UART_CR_TX_DIS; status |= CDNS_UART_CR_TX_EN; - writel(status, port->membase + CDNS_UART_CR_OFFSET); + writel(status, port->membase + CDNS_UART_CR); if (uart_circ_empty(&port->state->xmit)) return; - while (numbytes-- && ((readl(port->membase + CDNS_UART_SR_OFFSET) & + while (numbytes-- && ((readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { /* Break if no more data available in the UART buffer */ if (uart_circ_empty(&port->state->xmit)) @@ -531,7 +529,7 @@ static void cdns_uart_start_tx(struct uart_port *port) * write it to the cdns_uart's TX_FIFO register. */ writel(port->state->xmit.buf[port->state->xmit.tail], - port->membase + CDNS_UART_FIFO_OFFSET); + port->membase + CDNS_UART_FIFO); port->icount.tx++; /* Adjust the tail of the UART buffer and wrap @@ -540,9 +538,9 @@ static void cdns_uart_start_tx(struct uart_port *port) port->state->xmit.tail = (port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1); } - writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR_OFFSET); + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); /* Enable the TX Empty interrupt */ - writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) uart_write_wakeup(port); @@ -556,10 +554,10 @@ static void cdns_uart_stop_tx(struct uart_port *port) { unsigned int regval; - regval = readl(port->membase + CDNS_UART_CR_OFFSET); + regval = readl(port->membase + CDNS_UART_CR); regval |= CDNS_UART_CR_TX_DIS; /* Disable the transmitter */ - writel(regval, port->membase + CDNS_UART_CR_OFFSET); + writel(regval, port->membase + CDNS_UART_CR); } /** @@ -571,12 +569,12 @@ static void cdns_uart_stop_rx(struct uart_port *port) unsigned int regval; /* Disable RX IRQs */ - writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IDR_OFFSET); + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IDR); /* Disable the receiver */ - regval = readl(port->membase + CDNS_UART_CR_OFFSET); + regval = readl(port->membase + CDNS_UART_CR); regval |= CDNS_UART_CR_RX_DIS; - writel(regval, port->membase + CDNS_UART_CR_OFFSET); + writel(regval, port->membase + CDNS_UART_CR); } /** @@ -589,7 +587,7 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port) { unsigned int status; - status = readl(port->membase + CDNS_UART_SR_OFFSET) & + status = readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY; return status ? TIOCSER_TEMT : 0; } @@ -607,15 +605,15 @@ static void cdns_uart_break_ctl(struct uart_port *port, int ctl) spin_lock_irqsave(&port->lock, flags); - status = readl(port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR); if (ctl == -1) writel(CDNS_UART_CR_STARTBRK | status, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); else { if ((status & CDNS_UART_CR_STOPBRK) == 0) writel(CDNS_UART_CR_STOPBRK | status, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); } spin_unlock_irqrestore(&port->lock, flags); } @@ -638,18 +636,18 @@ static void cdns_uart_set_termios(struct uart_port *port, spin_lock_irqsave(&port->lock, flags); /* Wait for the transmit FIFO to empty before making changes */ - if (!(readl(port->membase + CDNS_UART_CR_OFFSET) & + if (!(readl(port->membase + CDNS_UART_CR) & CDNS_UART_CR_TX_DIS)) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) { cpu_relax(); } } /* Disable the TX and RX to set baud rate */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); /* * Min baud rate = 6bps and Max Baud Rate is 10Mbps for 100Mhz clk @@ -668,20 +666,20 @@ static void cdns_uart_set_termios(struct uart_port *port, uart_update_timeout(port, termios->c_cflag, baud); /* Set TX/RX Reset */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); /* * Clear the RX disable and TX disable bits and then set the TX enable * bit and RX enable bit to enable the transmitter and receiver. */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); port->read_status_mask = CDNS_UART_IXR_TXEMPTY | CDNS_UART_IXR_RXTRIG | CDNS_UART_IXR_OVERRUN | CDNS_UART_IXR_TOUT; @@ -701,7 +699,7 @@ static void cdns_uart_set_termios(struct uart_port *port, CDNS_UART_IXR_TOUT | CDNS_UART_IXR_PARITY | CDNS_UART_IXR_FRAMING | CDNS_UART_IXR_OVERRUN; - mode_reg = readl(port->membase + CDNS_UART_MR_OFFSET); + mode_reg = readl(port->membase + CDNS_UART_MR); /* Handling Data Size */ switch (termios->c_cflag & CSIZE) { @@ -742,7 +740,7 @@ static void cdns_uart_set_termios(struct uart_port *port, cval |= CDNS_UART_MR_PARITY_NONE; } cval |= mode_reg & 1; - writel(cval, port->membase + CDNS_UART_MR_OFFSET); + writel(cval, port->membase + CDNS_UART_MR); spin_unlock_irqrestore(&port->lock, flags); } @@ -763,45 +761,45 @@ static int cdns_uart_startup(struct uart_port *port) /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); /* Set the Control Register with TX/RX Enable, TX/RX Reset, * no break chars. */ writel(CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); /* * Clear the RX disable bit and then set the RX enable bit to enable * the receiver. */ - status = readl(port->membase + CDNS_UART_CR_OFFSET); + status = readl(port->membase + CDNS_UART_CR); status &= CDNS_UART_CR_RX_DIS; status |= CDNS_UART_CR_RX_EN; - writel(status, port->membase + CDNS_UART_CR_OFFSET); + writel(status, port->membase + CDNS_UART_CR); /* Set the Mode Register with normal mode,8 data bits,1 stop bit, * no parity. */ writel(CDNS_UART_MR_CHMODE_NORM | CDNS_UART_MR_STOPMODE_1_BIT | CDNS_UART_MR_PARITY_NONE | CDNS_UART_MR_CHARLEN_8_BIT, - port->membase + CDNS_UART_MR_OFFSET); + port->membase + CDNS_UART_MR); /* * Set the RX FIFO Trigger level to use most of the FIFO, but it * can be tuned with a module parameter */ - writel(rx_trigger_level, port->membase + CDNS_UART_RXWM_OFFSET); + writel(rx_trigger_level, port->membase + CDNS_UART_RXWM); /* * Receive Timeout register is enabled but it * can be tuned with a module parameter */ - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); /* Clear out any pending interrupts before enabling them */ - writel(readl(port->membase + CDNS_UART_ISR_OFFSET), - port->membase + CDNS_UART_ISR_OFFSET); + writel(readl(port->membase + CDNS_UART_ISR), + port->membase + CDNS_UART_ISR); spin_unlock_irqrestore(&port->lock, flags); @@ -813,7 +811,7 @@ static int cdns_uart_startup(struct uart_port *port) } /* Set the Interrupt Registers with desired interrupts */ - writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_RX_IRQS, port->membase + CDNS_UART_IER); return 0; } @@ -830,13 +828,13 @@ static void cdns_uart_shutdown(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); /* Disable interrupts */ - status = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(status, port->membase + CDNS_UART_IDR_OFFSET); - writel(0xffffffff, port->membase + CDNS_UART_ISR_OFFSET); + status = readl(port->membase + CDNS_UART_IMR); + writel(status, port->membase + CDNS_UART_IDR); + writel(0xffffffff, port->membase + CDNS_UART_ISR); /* Disable the TX and RX */ writel(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS, - port->membase + CDNS_UART_CR_OFFSET); + port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&port->lock, flags); @@ -941,7 +939,7 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) { u32 val; - val = readl(port->membase + CDNS_UART_MODEMCR_OFFSET); + val = readl(port->membase + CDNS_UART_MODEMCR); val &= ~(CDNS_UART_MODEMCR_RTS | CDNS_UART_MODEMCR_DTR); @@ -950,7 +948,7 @@ static void cdns_uart_set_mctrl(struct uart_port *port, unsigned int mctrl) if (mctrl & TIOCM_DTR) val |= CDNS_UART_MODEMCR_DTR; - writel(val, port->membase + CDNS_UART_MODEMCR_OFFSET); + writel(val, port->membase + CDNS_UART_MODEMCR); } #ifdef CONFIG_CONSOLE_POLL @@ -962,11 +960,10 @@ static int cdns_uart_poll_get_char(struct uart_port *port) spin_lock_irqsave(&port->lock, flags); /* Check if FIFO is empty */ - if (readl(port->membase + CDNS_UART_SR_OFFSET) & CDNS_UART_SR_RXEMPTY) + if (readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY) c = NO_POLL_CHAR; else /* Read a character */ - c = (unsigned char) readl( - port->membase + CDNS_UART_FIFO_OFFSET); + c = (unsigned char) readl(port->membase + CDNS_UART_FIFO); spin_unlock_irqrestore(&port->lock, flags); @@ -980,16 +977,14 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c) spin_lock_irqsave(&port->lock, flags); /* Wait until FIFO is empty */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_TXEMPTY)) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) cpu_relax(); /* Write a character */ - writel(c, port->membase + CDNS_UART_FIFO_OFFSET); + writel(c, port->membase + CDNS_UART_FIFO); /* Wait until FIFO is empty */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_TXEMPTY)) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) cpu_relax(); spin_unlock_irqrestore(&port->lock, flags); @@ -1066,8 +1061,7 @@ static struct uart_port *cdns_uart_get_port(int id) */ static void cdns_uart_console_wait_tx(struct uart_port *port) { - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & - CDNS_UART_SR_TXEMPTY)) + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXEMPTY)) barrier(); } @@ -1079,7 +1073,7 @@ static void cdns_uart_console_wait_tx(struct uart_port *port) static void cdns_uart_console_putchar(struct uart_port *port, int ch) { cdns_uart_console_wait_tx(port); - writel(ch, port->membase + CDNS_UART_FIFO_OFFSET); + writel(ch, port->membase + CDNS_UART_FIFO); } static void __init cdns_early_write(struct console *con, const char *s, @@ -1124,25 +1118,25 @@ static void cdns_uart_console_write(struct console *co, const char *s, spin_lock_irqsave(&port->lock, flags); /* save and disable interrupt */ - imr = readl(port->membase + CDNS_UART_IMR_OFFSET); - writel(imr, port->membase + CDNS_UART_IDR_OFFSET); + imr = readl(port->membase + CDNS_UART_IMR); + writel(imr, port->membase + CDNS_UART_IDR); /* * Make sure that the tx part is enabled. Set the TX enable bit and * clear the TX disable bit to enable the transmitter. */ - ctrl = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl = readl(port->membase + CDNS_UART_CR); ctrl &= ~CDNS_UART_CR_TX_DIS; ctrl |= CDNS_UART_CR_TX_EN; - writel(ctrl, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl, port->membase + CDNS_UART_CR); uart_console_write(port, s, count, cdns_uart_console_putchar); cdns_uart_console_wait_tx(port); - writel(ctrl, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl, port->membase + CDNS_UART_CR); /* restore interrupt state */ - writel(imr, port->membase + CDNS_UART_IER_OFFSET); + writel(imr, port->membase + CDNS_UART_IER); if (locked) spin_unlock_irqrestore(&port->lock, flags); @@ -1254,14 +1248,13 @@ static int cdns_uart_suspend(struct device *device) spin_lock_irqsave(&port->lock, flags); /* Empty the receive FIFO 1st before making changes */ - while (!(readl(port->membase + CDNS_UART_SR_OFFSET) & + while (!(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_RXEMPTY)) - readl(port->membase + CDNS_UART_FIFO_OFFSET); + readl(port->membase + CDNS_UART_FIFO); /* set RX trigger level to 1 */ - writel(1, port->membase + CDNS_UART_RXWM_OFFSET); + writel(1, port->membase + CDNS_UART_RXWM); /* disable RX timeout interrups */ - writel(CDNS_UART_IXR_TOUT, - port->membase + CDNS_UART_IDR_OFFSET); + writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IDR); spin_unlock_irqrestore(&port->lock, flags); } @@ -1300,30 +1293,28 @@ static int cdns_uart_resume(struct device *device) spin_lock_irqsave(&port->lock, flags); /* Set TX/RX Reset */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg |= CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); - while (readl(port->membase + CDNS_UART_CR_OFFSET) & + writel(ctrl_reg, port->membase + CDNS_UART_CR); + while (readl(port->membase + CDNS_UART_CR) & (CDNS_UART_CR_TXRST | CDNS_UART_CR_RXRST)) cpu_relax(); /* restore rx timeout value */ - writel(rx_timeout, port->membase + CDNS_UART_RXTOUT_OFFSET); + writel(rx_timeout, port->membase + CDNS_UART_RXTOUT); /* Enable Tx/Rx */ - ctrl_reg = readl(port->membase + CDNS_UART_CR_OFFSET); + ctrl_reg = readl(port->membase + CDNS_UART_CR); ctrl_reg &= ~(CDNS_UART_CR_TX_DIS | CDNS_UART_CR_RX_DIS); ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN; - writel(ctrl_reg, port->membase + CDNS_UART_CR_OFFSET); + writel(ctrl_reg, port->membase + CDNS_UART_CR); spin_unlock_irqrestore(&port->lock, flags); } else { spin_lock_irqsave(&port->lock, flags); /* restore original rx trigger level */ - writel(rx_trigger_level, - port->membase + CDNS_UART_RXWM_OFFSET); + writel(rx_trigger_level, port->membase + CDNS_UART_RXWM); /* enable RX timeout interrupt */ - writel(CDNS_UART_IXR_TOUT, - port->membase + CDNS_UART_IER_OFFSET); + writel(CDNS_UART_IXR_TOUT, port->membase + CDNS_UART_IER); spin_unlock_irqrestore(&port->lock, flags); } -- cgit From 07986580d0ad14433021b709c6c005e2757c5a68 Mon Sep 17 00:00:00 2001 From: Soren Brinkmann Date: Mon, 11 Jan 2016 17:41:41 -0800 Subject: tty: xuartps: Consolidate TX handling start_tx and the ISR used largely identical code to transmit data. Consolidate that in one place. Signed-off-by: Soren Brinkmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/xilinx_uartps.c | 97 ++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 57 deletions(-) diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 3ff6e3c2347c..131a3117fbbb 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -239,6 +239,41 @@ static void cdns_uart_handle_rx(struct uart_port *port, unsigned int isrstatus) tty_flip_buffer_push(&port->state->port); } +static void cdns_uart_handle_tx(struct uart_port *port) +{ + unsigned int numbytes; + + if (uart_circ_empty(&port->state->xmit)) { + writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IDR); + return; + } + + numbytes = port->fifosize; + while (numbytes && !uart_circ_empty(&port->state->xmit) && + !(readl(port->membase + CDNS_UART_SR) & CDNS_UART_SR_TXFULL)) { + /* + * Get the data from the UART circular buffer + * and write it to the cdns_uart's TX_FIFO + * register. + */ + writel(port->state->xmit.buf[port->state->xmit.tail], + port->membase + CDNS_UART_FIFO); + port->icount.tx++; + + /* + * Adjust the tail of the UART buffer and wrap + * the buffer if it reaches limit. + */ + port->state->xmit.tail = + (port->state->xmit.tail + 1) & (UART_XMIT_SIZE - 1); + + numbytes--; + } + + if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + /** * cdns_uart_isr - Interrupt handler * @irq: Irq number @@ -250,7 +285,7 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) { struct uart_port *port = (struct uart_port *)dev_id; unsigned long flags; - unsigned int isrstatus, numbytes; + unsigned int isrstatus; spin_lock_irqsave(&port->lock, flags); @@ -262,40 +297,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) if (isrstatus & CDNS_UART_RX_IRQS) cdns_uart_handle_rx(port, isrstatus); - /* Dispatch an appropriate handler */ - if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) { - if (uart_circ_empty(&port->state->xmit)) { - writel(CDNS_UART_IXR_TXEMPTY, - port->membase + CDNS_UART_IDR); - } else { - numbytes = port->fifosize; - /* Break if no more data available in the UART buffer */ - while (numbytes--) { - if (uart_circ_empty(&port->state->xmit)) - break; - /* Get the data from the UART circular buffer - * and write it to the cdns_uart's TX_FIFO - * register. - */ - writel(port->state->xmit.buf[ - port->state->xmit.tail], - port->membase + CDNS_UART_FIFO); - - port->icount.tx++; - - /* Adjust the tail of the UART buffer and wrap - * the buffer if it reaches limit. - */ - port->state->xmit.tail = - (port->state->xmit.tail + 1) & - (UART_XMIT_SIZE - 1); - } - - if (uart_circ_chars_pending( - &port->state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); - } - } + if ((isrstatus & CDNS_UART_IXR_TXEMPTY) == CDNS_UART_IXR_TXEMPTY) + cdns_uart_handle_tx(port); writel(isrstatus, port->membase + CDNS_UART_ISR); @@ -502,7 +505,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, */ static void cdns_uart_start_tx(struct uart_port *port) { - unsigned int status, numbytes = port->fifosize; + unsigned int status; if (uart_tx_stopped(port)) return; @@ -519,31 +522,11 @@ static void cdns_uart_start_tx(struct uart_port *port) if (uart_circ_empty(&port->state->xmit)) return; - while (numbytes-- && ((readl(port->membase + CDNS_UART_SR) & - CDNS_UART_SR_TXFULL)) != CDNS_UART_SR_TXFULL) { - /* Break if no more data available in the UART buffer */ - if (uart_circ_empty(&port->state->xmit)) - break; - - /* Get the data from the UART circular buffer and - * write it to the cdns_uart's TX_FIFO register. - */ - writel(port->state->xmit.buf[port->state->xmit.tail], - port->membase + CDNS_UART_FIFO); - port->icount.tx++; + cdns_uart_handle_tx(port); - /* Adjust the tail of the UART buffer and wrap - * the buffer if it reaches limit. - */ - port->state->xmit.tail = (port->state->xmit.tail + 1) & - (UART_XMIT_SIZE - 1); - } writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_ISR); /* Enable the TX Empty interrupt */ writel(CDNS_UART_IXR_TXEMPTY, port->membase + CDNS_UART_IER); - - if (uart_circ_chars_pending(&port->state->xmit) < WAKEUP_CHARS) - uart_write_wakeup(port); } /** -- cgit From 29add68d16474b7e8e3eadd94da4e909533b99d2 Mon Sep 17 00:00:00 2001 From: Martin Fuzzey Date: Tue, 5 Jan 2016 16:53:31 +0100 Subject: serial: imx: Fix suspend / resume. When a non console i.MX UART is enabled in the device tree, system suspend fails due to an unprepared clock: [ 638.794563] PM: Syncing filesystems ... done. [ 638.878902] Freezing user space processes ... (elapsed 0.002 seconds) done. [ 638.888454] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. [ 638.996697] PM: suspend of devices complete after 97.200 msecs [ 639.002611] PM: suspend devices took 0.100 seconds [ 639.013020] PM: late suspend of devices complete after 2.288 msecs [ 639.021486] ------------[ cut here ]------------ [ 639.026147] WARNING: CPU: 0 PID: 488 at drivers/clk/clk.c:732 clk_core_enable+0xc0/0x12c() [ 639.034413] Modules linked in: [ 639.037490] CPU: 0 PID: 488 Comm: system_server Tainted: G W 4.4.0-rc5-pknbsp-svn2214-atag-v4.4-rc5-121-gebfd9cb #1304 [ 639.049312] Hardware name: Freescale i.MX53 (Device Tree Support) [ 639.055444] [] (unwind_backtrace) from [] (show_stack+0x20/0x24) [ 639.063199] [] (show_stack) from [] (dump_stack+0x20/0x28) [ 639.070442] [] (dump_stack) from [] (warn_slowpath_common+0x88/0xc0) [ 639.078541] [] (warn_slowpath_common) from [] (warn_slowpath_null+0x2c/0x34) [ 639.087332] [] (warn_slowpath_null) from [] (clk_core_enable+0xc0/0x12c) [ 639.095777] [] (clk_core_enable) from [] (clk_enable+0x2c/0x40) [ 639.103441] [] (clk_enable) from [] (imx_serial_port_suspend_noirq+0x20/0xe0) [ 639.112336] [] (imx_serial_port_suspend_noirq) from [] (dpm_run_callback+0x68/0x16c) [ 639.121825] [] (dpm_run_callback) from [] (__device_suspend_noirq+0xf4/0x22c) [ 639.130705] [] (__device_suspend_noirq) from [] (dpm_suspend_noirq+0x148/0x30c) [ 639.139764] [] (dpm_suspend_noirq) from [] (suspend_devices_and_enter+0x2e8/0x6a4) [ 639.149078] [] (suspend_devices_and_enter) from [] (pm_suspend+0x310/0x4b8) [ 639.157782] [] (pm_suspend) from [] (state_store+0x7c/0xcc) [ 639.165099] [] (state_store) from [] (kobj_attr_store+0x1c/0x28) [ 639.172858] [] (kobj_attr_store) from [] (sysfs_kf_write+0x54/0x58) [ 639.180871] [] (sysfs_kf_write) from [] (kernfs_fop_write+0x100/0x1c8) [ 639.189152] [] (kernfs_fop_write) from [] (__vfs_write+0x3c/0xe8) [ 639.196991] [] (__vfs_write) from [] (vfs_write+0xa4/0x160) [ 639.204307] [] (vfs_write) from [] (SyS_write+0x4c/0x98) [ 639.211363] [] (SyS_write) from [] (ret_fast_syscall+0x0/0x3c) This does not happen for the common case of a single UART used as a console (since imx_console_setup() already does a prepare) Signed-off-by: Martin Fuzzey Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/imx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 9362f54c816c..231e7d5caf6c 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2166,7 +2166,8 @@ static int imx_serial_port_suspend(struct device *dev) uart_suspend_port(&imx_reg, &sport->port); - return 0; + /* Needed to enable clock in suspend_noirq */ + return clk_prepare(sport->clk_ipg); } static int imx_serial_port_resume(struct device *dev) @@ -2179,6 +2180,8 @@ static int imx_serial_port_resume(struct device *dev) uart_resume_port(&imx_reg, &sport->port); + clk_unprepare(sport->clk_ipg); + return 0; } -- cgit From 95ee05c7adb0b5b7d55cc991b015a62efba21ba5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:18 +0100 Subject: serial: sh-sci: Add more Serial Mode Register documentation Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/sh-sci.h | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index ec08f1bff753..65f717395086 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2064,7 +2064,7 @@ static void sci_reset(struct uart_port *port) static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - unsigned int baud, smr_val = 0, scr_val = 0, i; + unsigned int baud, smr_val = SCSMR_ASYNC, scr_val = 0, i; unsigned int brr = 255, cks = 0, srr = 15, dl = 0, sccks = 0; unsigned int brr1 = 255, cks1 = 0, srr1 = 15, dl1 = 0; struct sci_port *s = to_sci_port(port); diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index fb1760250421..7a4fa185b93e 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -35,12 +35,27 @@ enum { /* SCSMR (Serial Mode Register) */ +#define SCSMR_C_A BIT(7) /* Communication Mode */ +#define SCSMR_CSYNC BIT(7) /* - Clocked synchronous mode */ +#define SCSMR_ASYNC 0 /* - Asynchronous mode */ #define SCSMR_CHR BIT(6) /* 7-bit Character Length */ #define SCSMR_PE BIT(5) /* Parity Enable */ #define SCSMR_ODD BIT(4) /* Odd Parity */ #define SCSMR_STOP BIT(3) /* Stop Bit Length */ #define SCSMR_CKS 0x0003 /* Clock Select */ +/* Serial Mode Register, SCIFA/SCIFB only bits */ +#define SCSMR_CKEDG BIT(12) /* Transmit/Receive Clock Edge Select */ +#define SCSMR_SRC_MASK 0x0700 /* Sampling Control */ +#define SCSMR_SRC_16 0x0000 /* Sampling rate 1/16 */ +#define SCSMR_SRC_5 0x0100 /* Sampling rate 1/5 */ +#define SCSMR_SRC_7 0x0200 /* Sampling rate 1/7 */ +#define SCSMR_SRC_11 0x0300 /* Sampling rate 1/11 */ +#define SCSMR_SRC_13 0x0400 /* Sampling rate 1/13 */ +#define SCSMR_SRC_17 0x0500 /* Sampling rate 1/17 */ +#define SCSMR_SRC_19 0x0600 /* Sampling rate 1/19 */ +#define SCSMR_SRC_27 0x0700 /* Sampling rate 1/27 */ + /* Serial Control Register, SCIFA/SCIFB only bits */ #define SCSCR_TDRQE BIT(15) /* Tx Data Transfer Request Enable */ #define SCSCR_RDRQE BIT(14) /* Rx Data Transfer Request Enable */ -- cgit From 3a964abe1ef1cfbe82d0ae832d70c7750d673728 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:19 +0100 Subject: serial: sh-sci: Preserve SCIFA/SCIFB bit rate config for serial console SCIFA and SCIFB have additional bit rate config bits in the Serial Mode Register. Don't touch them when using the port as a serial console, as we rely on the boot loader to have configured the serial port config. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 65f717395086..b175f8f565d8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2202,7 +2202,8 @@ done: } else { /* Don't touch the bit rate configuration */ scr_val = s->cfg->scscr & (SCSCR_CKE1 | SCSCR_CKE0); - smr_val |= serial_port_in(port, SCSMR) & SCSMR_CKS; + smr_val |= serial_port_in(port, SCSMR) & + (SCSMR_CKEDG | SCSMR_SRC_MASK | SCSMR_CKS); dev_dbg(port->dev, "SCR 0x%x SMR 0x%x\n", scr_val, smr_val); serial_port_out(port, SCSCR, scr_val); serial_port_out(port, SCSMR, smr_val); -- cgit From 7b5c0c08f5e895fb92c1d1d5f905c68eca1df5c0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:20 +0100 Subject: serial: sh-sci: Use premultiplier to handle half sampling rate On SCIx variants different from HSCIF, the bit rate is equal to the sampling clock rate divided by half the sampling rate. Currently this is handled by dividing the sampling rate by two, which was OK as it was always even. Replace halving the sampling rate by premultiplying the base clock frequency by 2, to accommodate odd sampling rates on SCIFA/SCIFB later. Replace the shift value in the BRG divider calculation by a premultiplication of the base clock frequency too, for consistency. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index b175f8f565d8..70f005f37de0 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1907,9 +1907,11 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, unsigned int min_sr, max_sr, sr; int err, min_err = INT_MAX; + if (s->port.type != PORT_HSCIF) + freq *= 2; if (s->sampling_rate) { /* SCI(F) has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate / 2; + min_sr = max_sr = s->sampling_rate; } else { /* HSCIF has a variable 1/(8..32) sampling rate */ min_sr = 8; @@ -1940,9 +1942,11 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps, unsigned int min_sr, max_sr, sr, dl; int err, min_err = INT_MAX; + if (s->port.type != PORT_HSCIF) + freq *= 2; if (s->sampling_rate) { /* SCIF has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate / 2; + min_sr = max_sr = s->sampling_rate; } else { /* HSCIF has a variable 1/(8..32) sampling rate */ min_sr = 8; @@ -1975,18 +1979,18 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, unsigned int *cks) { - unsigned int min_sr, max_sr, shift, sr, br, prediv, scrate, c; + unsigned int min_sr, max_sr, sr, br, prediv, scrate, c; unsigned long freq = s->clk_rates[SCI_FCK]; int err, min_err = INT_MAX; + if (s->port.type != PORT_HSCIF) + freq *= 2; if (s->sampling_rate) { min_sr = max_sr = s->sampling_rate; - shift = 0; } else { /* HSCIF has a variable sample rate */ min_sr = 8; max_sr = 32; - shift = 1; } /* @@ -2007,7 +2011,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, for (sr = max_sr; sr >= min_sr; sr--) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ - prediv = sr * (1 << (2 * c + shift)); + prediv = sr * (1 << (2 * c + 1)); /* * We need to calculate: -- cgit From 69eee8e9c876eb412282a3b45d998e989d3a8e93 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:21 +0100 Subject: serial: sh-sci: Use a bitmask to indicate supported sampling rates Replace the single sampling rate and special handling for HSCIF's variable sampling rates by a bitmask and a custom iterator. This prepares for the advent of SCIFA/SCIFB's sparse variable sampling rates. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 66 +++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 70f005f37de0..dbf488b9ae27 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -84,6 +84,18 @@ enum SCI_CLKS { SCI_NUM_CLKS }; +/* Bit x set means sampling rate x + 1 is supported */ +#define SCI_SR(x) BIT((x) - 1) +#define SCI_SR_RANGE(x, y) GENMASK((y) - 1, (x) - 1) + +#define min_sr(_port) ffs((_port)->sampling_rate_mask) +#define max_sr(_port) fls((_port)->sampling_rate_mask) + +/* Iterate over all supported sampling rates, from high to low */ +#define for_each_sr(_sr, _port) \ + for ((_sr) = max_sr(_port); (_sr) >= min_sr(_port); (_sr)--) \ + if ((_port)->sampling_rate_mask & SCI_SR((_sr))) + struct sci_port { struct uart_port port; @@ -93,7 +105,7 @@ struct sci_port { unsigned int overrun_mask; unsigned int error_mask; unsigned int error_clear; - unsigned int sampling_rate; + unsigned int sampling_rate_mask; resource_size_t reg_size; /* Break timer */ @@ -1904,21 +1916,13 @@ static int sci_sck_calc(struct sci_port *s, unsigned int bps, unsigned int *srr) { unsigned long freq = s->clk_rates[SCI_SCK]; - unsigned int min_sr, max_sr, sr; int err, min_err = INT_MAX; + unsigned int sr; if (s->port.type != PORT_HSCIF) freq *= 2; - if (s->sampling_rate) { - /* SCI(F) has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate; - } else { - /* HSCIF has a variable 1/(8..32) sampling rate */ - min_sr = 8; - max_sr = 32; - } - for (sr = max_sr; sr >= min_sr; sr--) { + for_each_sr(sr, s) { err = DIV_ROUND_CLOSEST(freq, sr) - bps; if (abs(err) >= abs(min_err)) continue; @@ -1939,21 +1943,13 @@ static int sci_brg_calc(struct sci_port *s, unsigned int bps, unsigned long freq, unsigned int *dlr, unsigned int *srr) { - unsigned int min_sr, max_sr, sr, dl; int err, min_err = INT_MAX; + unsigned int sr, dl; if (s->port.type != PORT_HSCIF) freq *= 2; - if (s->sampling_rate) { - /* SCIF has a fixed sampling rate */ - min_sr = max_sr = s->sampling_rate; - } else { - /* HSCIF has a variable 1/(8..32) sampling rate */ - min_sr = 8; - max_sr = 32; - } - for (sr = max_sr; sr >= min_sr; sr--) { + for_each_sr(sr, s) { dl = DIV_ROUND_CLOSEST(freq, sr * bps); dl = clamp(dl, 1U, 65535U); @@ -1979,19 +1975,12 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, unsigned int *brr, unsigned int *srr, unsigned int *cks) { - unsigned int min_sr, max_sr, sr, br, prediv, scrate, c; unsigned long freq = s->clk_rates[SCI_FCK]; + unsigned int sr, br, prediv, scrate, c; int err, min_err = INT_MAX; if (s->port.type != PORT_HSCIF) freq *= 2; - if (s->sampling_rate) { - min_sr = max_sr = s->sampling_rate; - } else { - /* HSCIF has a variable sample rate */ - min_sr = 8; - max_sr = 32; - } /* * Find the combination of sample rate and clock select with the @@ -2008,7 +1997,7 @@ static int sci_scbrr_calc(struct sci_port *s, unsigned int bps, * (|D - 0.5| / N * (1 + F))| * NOTE: Usually, treat D for 0.5, F is 0 by this calculation. */ - for (sr = max_sr; sr >= min_sr; sr--) { + for_each_sr(sr, s) { for (c = 0; c <= 3; c++) { /* integerized formulas from HSCIF documentation */ prediv = sr * (1 << (2 * c + 1)); @@ -2102,8 +2091,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, for (i = 0; i < SCI_NUM_CLKS; i++) max_freq = max(max_freq, s->clk_rates[i]); - baud = uart_get_baud_rate(port, termios, old, 0, - max_freq / max(s->sampling_rate, 8U)); + baud = uart_get_baud_rate(port, termios, old, 0, max_freq / min_sr(s)); if (!baud) goto done; @@ -2535,37 +2523,37 @@ static int sci_init_single(struct platform_device *dev, port->fifosize = 256; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate = 16; + sci_port->sampling_rate_mask = SCI_SR(16); break; case PORT_HSCIF: port->fifosize = 128; sci_port->overrun_reg = SCLSR; sci_port->overrun_mask = SCLSR_ORER; - sci_port->sampling_rate = 0; + sci_port->sampling_rate_mask = SCI_SR_RANGE(8, 32); break; case PORT_SCIFA: port->fifosize = 64; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate = 16; + sci_port->sampling_rate_mask = SCI_SR(16); break; case PORT_SCIF: port->fifosize = 16; if (p->regtype == SCIx_SH7705_SCIF_REGTYPE) { sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate = 16; + sci_port->sampling_rate_mask = SCI_SR(16); } else { sci_port->overrun_reg = SCLSR; sci_port->overrun_mask = SCLSR_ORER; - sci_port->sampling_rate = 32; + sci_port->sampling_rate_mask = SCI_SR(32); } break; default: port->fifosize = 1; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCI_ORER; - sci_port->sampling_rate = 32; + sci_port->sampling_rate_mask = SCI_SR(32); break; } @@ -2574,7 +2562,7 @@ static int sci_init_single(struct platform_device *dev, * data override the sampling rate for now. */ if (p->sampling_rate) - sci_port->sampling_rate = p->sampling_rate; + sci_port->sampling_rate_mask = SCI_SR(p->sampling_rate); if (!early) { ret = sci_init_clocks(sci_port, &dev->dev); -- cgit From 92a0574867f3329ca285b51adcf09ed3ee42e7a0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 4 Jan 2016 14:45:22 +0100 Subject: serial: sh-sci: Add support for SCIFA/SCIFB variable sampling rates Add support for sparse variable sampling rates on SCIFA and SCIFB. According to the datasheet, sampling rate 1/5 needs a small quirk to avoid corrupting the first byte received. This increases the range and accuracy of supported baud rates. E.g. on r8a7791/koelsch: - Supports now 134, 150, and standard 500000-4000000 bps, - Perfect match for 134, 150, 500000, 1000000, 2000000, and 4000000 bps, - Accuracy has increased for most standard bps values. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sh-sci.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index dbf488b9ae27..4678d8f2dd7d 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -88,6 +88,10 @@ enum SCI_CLKS { #define SCI_SR(x) BIT((x) - 1) #define SCI_SR_RANGE(x, y) GENMASK((y) - 1, (x) - 1) +#define SCI_SR_SCIFAB SCI_SR(5) | SCI_SR(7) | SCI_SR(11) | \ + SCI_SR(13) | SCI_SR(16) | SCI_SR(17) | \ + SCI_SR(19) | SCI_SR(27) + #define min_sr(_port) ffs((_port)->sampling_rate_mask) #define max_sr(_port) fls((_port)->sampling_rate_mask) @@ -2179,6 +2183,17 @@ done: uart_update_timeout(port, termios->c_cflag, baud); if (best_clk >= 0) { + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) + switch (srr + 1) { + case 5: smr_val |= SCSMR_SRC_5; break; + case 7: smr_val |= SCSMR_SRC_7; break; + case 11: smr_val |= SCSMR_SRC_11; break; + case 13: smr_val |= SCSMR_SRC_13; break; + case 16: smr_val |= SCSMR_SRC_16; break; + case 17: smr_val |= SCSMR_SRC_17; break; + case 19: smr_val |= SCSMR_SRC_19; break; + case 27: smr_val |= SCSMR_SRC_27; break; + } smr_val |= cks; dev_dbg(port->dev, "SCR 0x%x SMR 0x%x BRR %u CKS 0x%x DL %u SRR %u\n", @@ -2227,6 +2242,16 @@ done: scr_val |= s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0); dev_dbg(port->dev, "SCSCR 0x%x\n", scr_val); serial_port_out(port, SCSCR, scr_val); + if ((srr + 1 == 5) && + (port->type == PORT_SCIFA || port->type == PORT_SCIFB)) { + /* + * In asynchronous mode, when the sampling rate is 1/5, first + * received data may become invalid on some SCIFA and SCIFB. + * To avoid this problem wait more than 1 serial data time (1 + * bit time x serial data number) after setting SCSCR.RE = 1. + */ + udelay(DIV_ROUND_UP(10 * 1000000, baud)); + } #ifdef CONFIG_SERIAL_SH_SCI_DMA /* @@ -2523,7 +2548,7 @@ static int sci_init_single(struct platform_device *dev, port->fifosize = 256; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR(16); + sci_port->sampling_rate_mask = SCI_SR_SCIFAB; break; case PORT_HSCIF: port->fifosize = 128; @@ -2535,7 +2560,7 @@ static int sci_init_single(struct platform_device *dev, port->fifosize = 64; sci_port->overrun_reg = SCxSR; sci_port->overrun_mask = SCIFA_ORER; - sci_port->sampling_rate_mask = SCI_SR(16); + sci_port->sampling_rate_mask = SCI_SR_SCIFAB; break; case PORT_SCIF: port->fifosize = 16; -- cgit From ba47f97a18f2f9c517131fcdaceb3b5a4811dc19 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 4 Jan 2016 15:54:46 +0800 Subject: serial: core: remove baud_rates when serial console setup Currently, when tring to set up a serial console with a higher baud rate, it would fallback to 921600. Tested-by: Jianqun Xu Signed-off-by: Jeffy Chen Reviewed-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 85829f8568e7..a126a603b083 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1875,26 +1875,6 @@ uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) } EXPORT_SYMBOL_GPL(uart_parse_options); -struct baud_rates { - unsigned int rate; - unsigned int cflag; -}; - -static const struct baud_rates baud_rates[] = { - { 921600, B921600 }, - { 460800, B460800 }, - { 230400, B230400 }, - { 115200, B115200 }, - { 57600, B57600 }, - { 38400, B38400 }, - { 19200, B19200 }, - { 9600, B9600 }, - { 4800, B4800 }, - { 2400, B2400 }, - { 1200, B1200 }, - { 0, B38400 } -}; - /** * uart_set_options - setup the serial console parameters * @port: pointer to the serial ports uart_port structure @@ -1910,7 +1890,6 @@ uart_set_options(struct uart_port *port, struct console *co, { struct ktermios termios; static struct ktermios dummy; - int i; /* * Ensure that the serial console lock is initialised @@ -1925,16 +1904,8 @@ uart_set_options(struct uart_port *port, struct console *co, memset(&termios, 0, sizeof(struct ktermios)); - termios.c_cflag = CREAD | HUPCL | CLOCAL; - - /* - * Construct a cflag setting. - */ - for (i = 0; baud_rates[i].rate; i++) - if (baud_rates[i].rate <= baud) - break; - - termios.c_cflag |= baud_rates[i].cflag; + termios.c_cflag |= CREAD | HUPCL | CLOCAL; + tty_termios_encode_baud_rate(&termios, baud, baud); if (bits == 7) termios.c_cflag |= CS7; -- cgit From 020641768a5c27620977b03e6f3aed1e9c0c9a45 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Mon, 11 Jan 2016 10:39:20 +0900 Subject: serial: sh-sci: Add device tree support for r8a7792 Simply document new compat strings. There appears to be no need for a driver updates. Signed-off-by: Simon Horman Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/renesas,sci-serial.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt index 401b1b33c2c4..528c3b90f23c 100644 --- a/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt +++ b/Documentation/devicetree/bindings/serial/renesas,sci-serial.txt @@ -19,6 +19,8 @@ Required properties: - "renesas,scifa-r8a7791" for R8A7791 (R-Car M2-W) SCIFA compatible UART. - "renesas,scifb-r8a7791" for R8A7791 (R-Car M2-W) SCIFB compatible UART. - "renesas,hscif-r8a7791" for R8A7791 (R-Car M2-W) HSCIF compatible UART. + - "renesas,scif-r8a7792" for R8A7792 (R-Car V2H) SCIF compatible UART. + - "renesas,hscif-r8a7792" for R8A7792 (R-Car V2H) HSCIF compatible UART. - "renesas,scif-r8a7793" for R8A7793 (R-Car M2-N) SCIF compatible UART. - "renesas,scifa-r8a7793" for R8A7793 (R-Car M2-N) SCIFA compatible UART. - "renesas,scifb-r8a7793" for R8A7793 (R-Car M2-N) SCIFB compatible UART. -- cgit From cafe1ac6402395eb990c936204ff0760af963633 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 7 Jan 2016 13:28:32 -0500 Subject: drivers/tty: make serial 8250_ingenic.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/serial/8250/Kconfig:config SERIAL_8250_INGENIC drivers/tty/serial/8250/Kconfig: bool "Support for Ingenic SoC serial ports" ...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. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. 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: Greg Kroah-Hartman Cc: Jiri Slaby Cc: Matt Redfearn Cc: Masahiro Yamada Cc: Paul Burton Cc: Peter Hurley Cc: linux-serial@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_ingenic.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index d6e1ec9b4fde..47824887b63f 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -4,6 +4,8 @@ * * Ingenic SoC UART support * + * Author: Paul Burton + * * 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 @@ -18,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -297,16 +299,6 @@ out: return err; } -static int ingenic_uart_remove(struct platform_device *pdev) -{ - struct ingenic_uart_data *data = platform_get_drvdata(pdev); - - serial8250_unregister_port(data->line); - clk_disable_unprepare(data->clk_module); - clk_disable_unprepare(data->clk_baud); - return 0; -} - static const struct ingenic_uart_config jz4740_uart_config = { .tx_loadsz = 8, .fifosize = 16, @@ -329,19 +321,13 @@ static const struct of_device_id of_match[] = { { .compatible = "ingenic,jz4780-uart", .data = &jz4780_uart_config }, { /* sentinel */ } }; -MODULE_DEVICE_TABLE(of, of_match); static struct platform_driver ingenic_uart_platform_driver = { .driver = { - .name = "ingenic-uart", - .of_match_table = of_match, + .name = "ingenic-uart", + .of_match_table = of_match, + .suppress_bind_attrs = true, }, .probe = ingenic_uart_probe, - .remove = ingenic_uart_remove, }; - -module_platform_driver(ingenic_uart_platform_driver); - -MODULE_AUTHOR("Paul Burton"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Ingenic SoC UART driver"); +builtin_platform_driver(ingenic_uart_platform_driver); -- cgit From 7cdcc29e4919dc31f494eaf05e46005c28efe832 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 8 Jan 2016 15:34:05 -0500 Subject: serial-uartlite: add earlycon support Microblaze currently uses the old earlyprintk system, rather than the unified earlycon support, to show boot messages on uartlite. Add earlycon support so that other archs using uartlite can benefit from it. The new code in uartlite.c is copied almost verbatim from arch/microblaze/kernel/early_printk.c. Signed-off-by: Rich Felker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 1 + drivers/tty/serial/uartlite.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 54b6f2c15f72..bdbe1c533c6a 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -610,6 +610,7 @@ config SERIAL_UARTLITE_CONSOLE bool "Support for console on Xilinx uartlite serial port" depends on SERIAL_UARTLITE=y select SERIAL_CORE_CONSOLE + select SERIAL_EARLYCON help Say Y here if you wish to use a Xilinx uartlite as the system console (the system console is the device which receives all kernel diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index b1c6bd3d483f..c249aee887d2 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -519,6 +519,47 @@ static int __init ulite_console_init(void) console_initcall(ulite_console_init); +static void early_uartlite_putc(struct uart_port *port, int c) +{ + /* + * Limit how many times we'll spin waiting for TX FIFO status. + * This will prevent lockups if the base address is incorrectly + * set, or any other issue on the UARTLITE. + * This limit is pretty arbitrary, unless we are at about 10 baud + * we'll never timeout on a working UART. + */ + + unsigned retries = 1000000; + /* read status bit - 0x8 offset */ + while (--retries && (readl(port->membase + 8) & (1 << 3))) + ; + + /* Only attempt the iowrite if we didn't timeout */ + /* write to TX_FIFO - 0x4 offset */ + if (retries) + writel(c & 0xff, port->membase + 4); +} + +static void early_uartlite_write(struct console *console, + const char *s, unsigned n) +{ + struct earlycon_device *device = console->data; + uart_console_write(&device->port, s, n, early_uartlite_putc); +} + +static int __init early_uartlite_setup(struct earlycon_device *device, + const char *options) +{ + if (!device->port.membase) + return -ENODEV; + + device->con->write = early_uartlite_write; + return 0; +} +EARLYCON_DECLARE(uartlite, early_uartlite_setup); +OF_EARLYCON_DECLARE(uartlite_b, "xlnx,opb-uartlite-1.00.b", early_uartlite_setup); +OF_EARLYCON_DECLARE(uartlite_a, "xlnx,xps-uartlite-1.00.a", early_uartlite_setup); + #endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */ static struct uart_driver ulite_uart_driver = { -- cgit From 9e370d2c9f59a63dda0ced3ecd1b55498d97c449 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 8 Jan 2016 15:33:50 -0500 Subject: serial-uartlite: fix missing locking in isr The uartlite driver suffers from missing/duplicate/corrupted character data when the interrupt handler runs concurrently with access to the device from another cpu. Take the port spinlock to exclude concurrent access. Signed-off-by: Rich Felker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/uartlite.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index c249aee887d2..ee2e8efdea4a 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -194,7 +194,9 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) { struct uart_port *port = dev_id; int busy, n = 0; + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); do { int stat = uart_in32(ULITE_STATUS, port); busy = ulite_receive(port, stat); @@ -202,6 +204,8 @@ static irqreturn_t ulite_isr(int irq, void *dev_id) n++; } while (busy); + spin_unlock_irqrestore(&port->lock, flags); + /* work done? */ if (n > 1) { tty_flip_buffer_push(&port->state->port); -- cgit From ac2b335e7149e7dd0c8dcbb2b158a17b78c480a1 Mon Sep 17 00:00:00 2001 From: Paul Mcquade Date: Sat, 17 Oct 2015 21:04:39 +0100 Subject: net: wireless: rt2x00: Fixed Spacing issues Removed empty spaces before/after parenthesis Signed-off-by: Paul McQuade Acked-by: Helmut Schaa Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt61pci.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.h b/drivers/net/wireless/ralink/rt2x00/rt61pci.h index 1442075a8382..ab8641547a1f 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.h +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.h @@ -138,14 +138,14 @@ #define PAIRWISE_TA_TABLE_BASE 0x1a00 #define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) + (SHARED_KEY_TABLE_BASE + \ + ((__idx) * sizeof(struct hw_key_entry))) #define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) + (PAIRWISE_KEY_TABLE_BASE + \ + ((__idx) * sizeof(struct hw_key_entry))) #define PAIRWISE_TA_ENTRY(__idx) \ - ( PAIRWISE_TA_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_pairwise_ta_entry)) ) + (PAIRWISE_TA_TABLE_BASE + \ + ((__idx) * sizeof(struct hw_pairwise_ta_entry))) struct hw_key_entry { u8 key[16]; @@ -180,7 +180,7 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE3 0x2f00 #define HW_BEACON_OFFSET(__index) \ - ( HW_BEACON_BASE0 + (__index * 0x0100) ) + (HW_BEACON_BASE0 + (__index * 0x0100)) /* * HOST-MCU shared memory. @@ -1287,9 +1287,9 @@ struct hw_pairwise_ta_entry { /* * DMA descriptor defines. */ -#define TXD_DESC_SIZE ( 16 * sizeof(__le32) ) -#define TXINFO_SIZE ( 6 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 16 * sizeof(__le32) ) +#define TXD_DESC_SIZE (16 * sizeof(__le32)) +#define TXINFO_SIZE (6 * sizeof(__le32)) +#define RXD_DESC_SIZE (16 * sizeof(__le32)) /* * TX descriptor format for TX, PRIO and Beacon Ring. -- cgit From b2cc2dd8ebb885ad1b2ee4c5d35b40d98db211fa Mon Sep 17 00:00:00 2001 From: Paul Mcquade Date: Sat, 17 Oct 2015 22:06:43 +0100 Subject: net: wireless: rt2x00: Space issue Removed empty spaces before/after parenthesis Signed-off-by: Paul McQuade Acked-by: Helmut Schaa Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 3282ddb766f4..8c679f2d668d 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -107,7 +107,7 @@ * amount of bytes needed to move the data. */ #define ALIGN_SIZE(__skb, __header) \ - ( ((unsigned long)((__skb)->data + (__header))) & 3 ) + (((unsigned long)((__skb)->data + (__header))) & 3) /* * Constants for extra TX headroom for alignment purposes. @@ -128,14 +128,14 @@ #define SLOT_TIME 20 #define SHORT_SLOT_TIME 9 #define SIFS 10 -#define PIFS ( SIFS + SLOT_TIME ) -#define SHORT_PIFS ( SIFS + SHORT_SLOT_TIME ) -#define DIFS ( PIFS + SLOT_TIME ) -#define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME ) -#define EIFS ( SIFS + DIFS + \ - GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) -#define SHORT_EIFS ( SIFS + SHORT_DIFS + \ - GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) +#define PIFS (SIFS + SLOT_TIME) +#define SHORT_PIFS (SIFS + SHORT_SLOT_TIME) +#define DIFS (PIFS + SLOT_TIME) +#define SHORT_DIFS (SHORT_PIFS + SHORT_SLOT_TIME) +#define EIFS (SIFS + DIFS + \ + GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10)) +#define SHORT_EIFS (SIFS + SHORT_DIFS + \ + GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10)) enum rt2x00_chip_intf { RT2X00_CHIP_INTF_PCI, -- cgit From 5b451715e94d43fdb8f3cca67d1ec72184f294f9 Mon Sep 17 00:00:00 2001 From: Paul Mcquade Date: Sat, 17 Oct 2015 22:11:23 +0100 Subject: net: wireless: rt2x00: Space Required Space needed before open parenthesis Signed-off-by: Paul McQuade Acked-by: Helmut Schaa Signed-off-by: Kalle Valo --- drivers/net/wireless/ralink/rt2x00/rt2x00debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c index 90fdb02b55e7..25ee3cb8e982 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c @@ -629,7 +629,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, data += sprintf(data, "register\tbase\twords\twordsize\n"); #define RT2X00DEBUGFS_SPRINTF_REGISTER(__name) \ { \ - if(debug->__name.read) \ + if (debug->__name.read) \ data += sprintf(data, __stringify(__name) \ "\t%d\t%d\t%d\n", \ debug->__name.word_base, \ @@ -699,7 +699,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) #define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ ({ \ - if(debug->__name.read) { \ + if (debug->__name.read) { \ (__intf)->__name##_off_entry = \ debugfs_create_u32(__stringify(__name) "_offset", \ S_IRUSR | S_IWUSR, \ -- cgit From 1349ba02bf72caafa36a2d6878cdba340d65b2ac Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 21 Jan 2016 09:46:12 +0100 Subject: ARM: OMAP: serial: Rename DRIVER_NAME DRIVER_NAME is too generic to be used in a driver-specific platform data file. Use a name specific to the driver instead, to avoid collisions. Signed-off-by: Jean Delvare Acked-by: Tony Lindgren Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- arch/arm/mach-omap2/serial.c | 2 +- drivers/tty/serial/omap-serial.c | 2 +- include/linux/platform_data/serial-omap.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index f164c6b32ce2..8e072de89fed 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -252,7 +252,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata, info = omap_serial_default_info; oh = uart->oh; - name = DRIVER_NAME; + name = OMAP_SERIAL_DRIVER_NAME; omap_up.dma_enabled = info->dma_enabled; omap_up.uartclk = OMAP24XX_BASE_BAUD * 16; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index b645f9228ed7..1401dc9cde35 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1866,7 +1866,7 @@ static struct platform_driver serial_omap_driver = { .probe = serial_omap_probe, .remove = serial_omap_remove, .driver = { - .name = DRIVER_NAME, + .name = OMAP_SERIAL_DRIVER_NAME, .pm = &serial_omap_dev_pm_ops, .of_match_table = of_match_ptr(omap_serial_of_match), }, diff --git a/include/linux/platform_data/serial-omap.h b/include/linux/platform_data/serial-omap.h index d09275f3cde3..2ba2c34ca3d3 100644 --- a/include/linux/platform_data/serial-omap.h +++ b/include/linux/platform_data/serial-omap.h @@ -21,7 +21,7 @@ #include #include -#define DRIVER_NAME "omap_uart" +#define OMAP_SERIAL_DRIVER_NAME "omap_uart" /* * Use tty device name as ttyO, [O -> OMAP] -- cgit From 434ba16e86640104faf241eaf34bc4bbea9733a4 Mon Sep 17 00:00:00 2001 From: Wang Dongsheng Date: Thu, 21 Jan 2016 15:59:53 +0800 Subject: serial: 8250: of: Enable suspend/resume for 8250_of driver Suspend/resume functions should work for 8250_of driver. Signed-off-by: Wang Dongsheng Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_of.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 33021c1f7d55..c7ed3d2bc8b2 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -335,6 +335,7 @@ static struct platform_driver of_platform_serial_driver = { .driver = { .name = "of_serial", .of_match_table = of_platform_serial_table, + .pm = &of_serial_pm_ops, }, .probe = of_platform_serial_probe, .remove = of_platform_serial_remove, -- cgit From 45d7e9a51c995b4732eeecc121f40798e2220bea Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sun, 17 Jan 2016 12:15:29 +0000 Subject: dt/bindings: serial: bcm2835: add binding documentation for bcm2835-aux-uart Add binding documentation for the bcm2835-aux-uart driver. Signed-off-by: Martin Sperl Acked-by: Rob Herring Acked-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- .../bindings/serial/brcm,bcm2835-aux-uart.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Documentation/devicetree/bindings/serial/brcm,bcm2835-aux-uart.txt diff --git a/Documentation/devicetree/bindings/serial/brcm,bcm2835-aux-uart.txt b/Documentation/devicetree/bindings/serial/brcm,bcm2835-aux-uart.txt new file mode 100644 index 000000000000..b5cc6297cd1b --- /dev/null +++ b/Documentation/devicetree/bindings/serial/brcm,bcm2835-aux-uart.txt @@ -0,0 +1,18 @@ +* BCM2835 AUXILIAR UART + +Required properties: + +- compatible: "brcm,bcm2835-aux-uart" +- reg: The base address of the UART register bank. +- interrupts: A single interrupt specifier. +- clocks: Clock driving the hardware; used to figure out the baud rate + divisor. + +Example: + + uart1: serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <1 29>; + clocks = <&aux BCM2835_AUX_CLOCK_UART>; + }; -- cgit From bdc5f300958062a766518b81d5378f837149d5c1 Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Sun, 17 Jan 2016 12:15:30 +0000 Subject: serial: bcm2835: add driver for bcm2835-aux-uart The bcm2835 SOC contains an auxiliary uart, which is very close to the ns16550 with some differences. The big difference is that the uart HW is not using an internal divider of 16 but 8, which results in an effictive baud-rate being twice the requested baud-rate. This driver handles this device correctly and handles the difference in the HW divider by scaling up the clock by a factor of 2. The approach to write a separate (wrapper) driver instead of using a multiplying clock and "ns16550" as compatibility in the device-tree has been recommended by Stephen Warren. Signed-off-by: Martin Sperl Acked-by: Eric Anholt Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm2835aux.c | 146 ++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 24 +++++ drivers/tty/serial/8250/Makefile | 1 + 3 files changed, 171 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_bcm2835aux.c diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c new file mode 100644 index 000000000000..ecf89f13a13b --- /dev/null +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -0,0 +1,146 @@ +/* + * Serial port driver for BCM2835AUX UART + * + * Copyright (C) 2016 Martin Sperl + * + * Based on 8250_lpc18xx.c: + * Copyright (C) 2015 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. + * + */ + +#include +#include +#include +#include +#include + +#include "8250.h" + +struct bcm2835aux_data { + struct uart_8250_port uart; + struct clk *clk; + int line; +}; + +static int bcm2835aux_serial_probe(struct platform_device *pdev) +{ + struct bcm2835aux_data *data; + struct resource *res; + int ret; + + /* allocate the custom structure */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + /* initialize data */ + spin_lock_init(&data->uart.port.lock); + data->uart.capabilities = UART_CAP_FIFO; + data->uart.port.dev = &pdev->dev; + data->uart.port.regshift = 2; + data->uart.port.type = PORT_16550; + data->uart.port.iotype = UPIO_MEM; + data->uart.port.fifosize = 8; + data->uart.port.flags = UPF_SHARE_IRQ | + UPF_FIXED_PORT | + UPF_FIXED_TYPE | + UPF_SKIP_TEST; + + /* get the clock - this also enables the HW */ + data->clk = devm_clk_get(&pdev->dev, NULL); + ret = PTR_ERR_OR_ZERO(data->clk); + if (ret) { + dev_err(&pdev->dev, "could not get clk: %d\n", ret); + return ret; + } + + /* get the interrupt */ + data->uart.port.irq = platform_get_irq(pdev, 0); + if (data->uart.port.irq < 0) { + dev_err(&pdev->dev, "irq not found - %i", + data->uart.port.irq); + return data->uart.port.irq; + } + + /* map the main registers */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "memory resource not found"); + return -EINVAL; + } + data->uart.port.membase = devm_ioremap_resource(&pdev->dev, res); + ret = PTR_ERR_OR_ZERO(data->uart.port.membase); + if (ret) + return ret; + + /* Check for a fixed line number */ + ret = of_alias_get_id(pdev->dev.of_node, "serial"); + if (ret >= 0) + data->uart.port.line = ret; + + /* enable the clock as a last step */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "unable to enable uart clock - %d\n", + ret); + return ret; + } + + /* the HW-clock divider for bcm2835aux is 8, + * but 8250 expects a divider of 16, + * so we have to multiply the actual clock by 2 + * to get identical baudrates. + */ + data->uart.port.uartclk = clk_get_rate(data->clk) * 2; + + /* register the port */ + ret = serial8250_register_8250_port(&data->uart); + if (ret < 0) { + dev_err(&pdev->dev, "unable to register 8250 port - %d\n", + ret); + goto dis_clk; + } + data->line = ret; + + platform_set_drvdata(pdev, data); + + return 0; + +dis_clk: + clk_disable_unprepare(data->clk); + return ret; +} + +static int bcm2835aux_serial_remove(struct platform_device *pdev) +{ + struct bcm2835aux_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->uart.port.line); + clk_disable_unprepare(data->clk); + + return 0; +} + +static const struct of_device_id bcm2835aux_serial_match[] = { + { .compatible = "brcm,bcm2835-aux-uart" }, + { }, +}; +MODULE_DEVICE_TABLE(of, bcm2835aux_serial_match); + +static struct platform_driver bcm2835aux_serial_driver = { + .driver = { + .name = "bcm2835-aux-uart", + .of_match_table = bcm2835aux_serial_match, + }, + .probe = bcm2835aux_serial_probe, + .remove = bcm2835aux_serial_remove, +}; +module_platform_driver(bcm2835aux_serial_driver); + +MODULE_DESCRIPTION("BCM2835 auxiliar UART driver"); +MODULE_AUTHOR("Martin Sperl "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index b03cb5175113..67ad6b0d595b 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -272,6 +272,30 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_BCM2835AUX + tristate "BCM2835 auxiliar mini UART support" + depends on ARCH_BCM2835 || COMPILE_TEST + depends on SERIAL_8250 && SERIAL_8250_SHARE_IRQ + help + Support for the BCM2835 auxiliar mini UART. + + Features and limitations of the UART are + Registers are similar to 16650 registers, + set bits in the control registers that are unsupported + are ignored and read back as 0 + 7/8 bit operation with 1 start and 1 stop bit + 8 symbols deep fifo for rx and tx + SW controlled RTS and SW readable CTS + Clock rate derived from system clock + Uses 8 times oversampling (compared to 16 times for 16650) + Missing break detection (but break generation) + Missing framing error detection + Missing parity bit + Missing receive time-out interrupt + Missing DCD, DSR, DTR and RI signals + + If unsure, say N. + config SERIAL_8250_FSL bool depends on SERIAL_8250_CONSOLE diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index b9b9bca5b6c3..5c1869fdfd4c 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o +obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o -- cgit From fff21fac75ccebacd29fc16b56a46a124359917a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sat, 30 Jan 2016 09:11:46 +0000 Subject: serial: zs: Fix a transmit lockup in console output Transmit interrupts are disabled and the transmit buffer drained in the course of console output so that polled transmission is possible. That however causes a lost transmit interrupt as the TxIP bit in RR3 is only set on a transmit buffer full-to-empty transition and then iff transmit interrupts are enabled at the same time. Consequently if console output disturbs a regular transmission in progress, the TxIP bit is never set again and the transmission locks up waiting for a transmit interrupt. Fix the problem by restarting transmission manually rather than waiting for a transmit interrupt that will never happen. Signed-off-by: Maciej W. Rozycki Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/zs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index 2b65bb7ffb8a..eeefd76a30da 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c @@ -1181,6 +1181,10 @@ static void zs_console_write(struct console *co, const char *s, if (txint & TxINT_ENAB) { zport->regs[1] |= TxINT_ENAB; write_zsreg(zport, R1, zport->regs[1]); + + /* Resume any transmission as the TxIP bit won't be set. */ + if (!zport->tx_stopped) + zs_raw_transmit_chars(zport); } spin_unlock_irqrestore(&scc->zlock, flags); } -- cgit From 6970cd446c25a4634f03c1adf0c12c010235bf3e Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:02 -0800 Subject: mwifiex: display right transmit packet delay drv_pkt_delay_max should be assigned non-zero value, so that packet delay can be accumulate in the right way. Signed-off-by: Xinming Hu Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/main.h | 1 + drivers/net/wireless/marvell/mwifiex/wmm.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 89a1576d0a4b..0433977c4e2f 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -298,6 +298,7 @@ struct mwifiex_tid_tbl { #define WMM_HIGHEST_PRIORITY 7 #define HIGH_PRIO_TID 7 #define LOW_PRIO_TID 0 +#define MWIFIEX_WMM_DRV_DELAY_MAX 510 struct mwifiex_wmm_desc { struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index 499e5a741c62..0eb246502e1d 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -438,6 +438,7 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) mwifiex_set_ba_params(priv); mwifiex_reset_11n_rx_seq_num(priv); + priv->wmm.drv_pkt_delay_max = MWIFIEX_WMM_DRV_DELAY_MAX; atomic_set(&priv->wmm.tx_pkts_queued, 0); atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } -- cgit From af05148392f50490c662dccee6c502d9fcba33e2 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:03 -0800 Subject: mwifiex: process pcie io memory read failure case It is observed that ioread32 may fail to read pcie register in certain scenarios, this patch handles these cases. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 918e04954afe..b9fe1813cc4f 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -323,6 +323,8 @@ static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) struct pcie_service_card *card = adapter->card; *data = ioread32(card->pci_mmap1 + reg); + if (*data == 0xffffffff) + return 0xffffffff; return 0; } -- cgit From 0172404d79ec37e2c7d9dc90f6876dc314dc0fe5 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:04 -0800 Subject: mwifiex: skip firmware dump when read_regs() fails If we are not able to read registers or PCIe memory, it means PCIe device is in bad state. We will skip firmware dump in this case. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index b9fe1813cc4f..a18d944c2f31 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2366,9 +2366,13 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) { int ret, tries; u8 ctrl_data; + u32 fw_status; struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) + return RDWR_STATUS_FAILURE; + ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY); if (ret) { mwifiex_dbg(adapter, ERROR, -- cgit From 9a86232213b9498e0c0721fc508f760e7a089e59 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:05 -0800 Subject: mwifiex: keep original structure in decl header file memory_type_mapping strucuture did not refer to other mwifiex specific strture. A better software design method would keep it in decl header file, which does not include other mwifiex header file. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/decl.h | 21 +++++++++++++++++++++ drivers/net/wireless/marvell/mwifiex/main.h | 20 -------------------- drivers/net/wireless/marvell/mwifiex/pcie.h | 1 + 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index d9c15cd36f12..c744a7030866 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -270,4 +270,25 @@ struct mwifiex_11h_intf_state { bool is_11h_enabled; bool is_11h_active; } __packed; + +#define MWIFIEX_FW_DUMP_IDX 0xff +#define MWIFIEX_DRV_INFO_IDX 20 +#define FW_DUMP_MAX_NAME_LEN 8 +#define FW_DUMP_HOST_READY 0xEE +#define FW_DUMP_DONE 0xFF +#define FW_DUMP_READ_DONE 0xFE + +struct memory_type_mapping { + u8 mem_name[FW_DUMP_MAX_NAME_LEN]; + u8 *mem_ptr; + u32 mem_size; + u8 done_flag; +}; + +enum rdwr_status { + RDWR_STATUS_SUCCESS = 0, + RDWR_STATUS_FAILURE = 1, + RDWR_STATUS_DONE = 2 +}; + #endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h index 0433977c4e2f..aea7aee46cf7 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.h +++ b/drivers/net/wireless/marvell/mwifiex/main.h @@ -489,26 +489,6 @@ struct mwifiex_roc_cfg { struct ieee80211_channel chan; }; -#define MWIFIEX_FW_DUMP_IDX 0xff -#define MWIFIEX_DRV_INFO_IDX 20 -#define FW_DUMP_MAX_NAME_LEN 8 -#define FW_DUMP_HOST_READY 0xEE -#define FW_DUMP_DONE 0xFF -#define FW_DUMP_READ_DONE 0xFE - -struct memory_type_mapping { - u8 mem_name[FW_DUMP_MAX_NAME_LEN]; - u8 *mem_ptr; - u32 mem_size; - u8 done_flag; -}; - -enum rdwr_status { - RDWR_STATUS_SUCCESS = 0, - RDWR_STATUS_FAILURE = 1, - RDWR_STATUS_DONE = 2 -}; - enum mwifiex_iface_work_flags { MWIFIEX_IFACE_WORK_DEVICE_DUMP, MWIFIEX_IFACE_WORK_CARD_RESET, diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 9700ac355e55..8f190c44cb76 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -26,6 +26,7 @@ #include #include +#include "decl.h" #include "main.h" #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" -- cgit From 50632092dfda712dec2232d6ddf75e803c397c70 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:06 -0800 Subject: mwifiex: use an extensible framework for firmware dump solution This patch apply an extensible firmware dump framework, so that other chipset can be easily added as needed. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 35 ++++++++++++----------------- drivers/net/wireless/marvell/mwifiex/pcie.h | 19 ++++++++++++++++ 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index a18d944c2f31..c94d31e1b525 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -37,17 +37,6 @@ static struct mwifiex_if_ops pcie_ops; static struct semaphore add_remove_card_sem; -static struct memory_type_mapping mem_type_mapping_tbl[] = { - {"ITCM", NULL, 0, 0xF0}, - {"DTCM", NULL, 0, 0xF1}, - {"SQRAM", NULL, 0, 0xF2}, - {"IRAM", NULL, 0, 0xF3}, - {"APU", NULL, 0, 0xF4}, - {"CIU", NULL, 0, 0xF5}, - {"ICU", NULL, 0, 0xF6}, - {"MAC", NULL, 0, 0xF7}, -}; - static int mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, size_t size, int flags) @@ -206,6 +195,8 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, card->pcie.blksz_fw_dl = data->blksz_fw_dl; card->pcie.tx_buf_size = data->tx_buf_size; card->pcie.can_dump_fw = data->can_dump_fw; + card->pcie.mem_type_mapping_tbl = data->mem_type_mapping_tbl; + card->pcie.num_mem_types = data->num_mem_types; card->pcie.can_ext_scan = data->can_ext_scan; } @@ -2373,7 +2364,8 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) return RDWR_STATUS_FAILURE; - ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY); + ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, + reg->fw_dump_host_ready); if (ret) { mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); @@ -2386,11 +2378,11 @@ mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) return RDWR_STATUS_SUCCESS; if (doneflag && ctrl_data == doneflag) return RDWR_STATUS_DONE; - if (ctrl_data != FW_DUMP_HOST_READY) { + if (ctrl_data != reg->fw_dump_host_ready) { mwifiex_dbg(adapter, WARN, "The ctrl reg was changed, re-try again!\n"); ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, - FW_DUMP_HOST_READY); + reg->fw_dump_host_ready); if (ret) { mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); @@ -2418,8 +2410,9 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) if (!card->pcie.can_dump_fw) return; - for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; + for (idx = 0; idx < adapter->num_mem_types; idx++) { + struct memory_type_mapping *entry = + &adapter->mem_type_mapping_tbl[idx]; if (entry->mem_ptr) { vfree(entry->mem_ptr); @@ -2440,8 +2433,8 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) /* Read the length of every memory which will dump */ for (idx = 0; idx < dump_num; idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; - + struct memory_type_mapping *entry = + &adapter->mem_type_mapping_tbl[idx]; stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); if (stat == RDWR_STATUS_FAILURE) return; @@ -2457,7 +2450,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) if (memory_size == 0) { mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n"); ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl, - FW_DUMP_READ_DONE); + creg->fw_dump_read_done); if (ret) { mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); return; @@ -2762,8 +2755,8 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) return -1; adapter->tx_buf_size = card->pcie.tx_buf_size; - adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; - adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); + 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; diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 8f190c44cb76..8bc4390f0e20 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -136,6 +136,8 @@ struct mwifiex_pcie_card_reg { u16 fw_dump_ctrl; u16 fw_dump_start; u16 fw_dump_end; + u8 fw_dump_host_ready; + u8 fw_dump_read_done; u8 msix_support; }; @@ -203,6 +205,8 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { .fw_dump_ctrl = 0xcf4, .fw_dump_start = 0xcf8, .fw_dump_end = 0xcff, + .fw_dump_host_ready = 0xee, + .fw_dump_read_done = 0xfe, .msix_support = 0, }; @@ -238,12 +242,25 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { .msix_support = 1, }; +static struct memory_type_mapping mem_type_mapping_tbl_w8897[] = { + {"ITCM", NULL, 0, 0xF0}, + {"DTCM", NULL, 0, 0xF1}, + {"SQRAM", NULL, 0, 0xF2}, + {"IRAM", NULL, 0, 0xF3}, + {"APU", NULL, 0, 0xF4}, + {"CIU", NULL, 0, 0xF5}, + {"ICU", NULL, 0, 0xF6}, + {"MAC", NULL, 0, 0xF7}, +}; + struct mwifiex_pcie_device { const char *firmware; const struct mwifiex_pcie_card_reg *reg; u16 blksz_fw_dl; u16 tx_buf_size; bool can_dump_fw; + struct memory_type_mapping *mem_type_mapping_tbl; + u8 num_mem_types; bool can_ext_scan; }; @@ -262,6 +279,8 @@ static const struct mwifiex_pcie_device mwifiex_pcie8897 = { .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, .can_dump_fw = true, + .mem_type_mapping_tbl = mem_type_mapping_tbl_w8897, + .num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl_w8897), .can_ext_scan = true, }; -- cgit From 56486026c282983c390b264493a4619d997b86f1 Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:07 -0800 Subject: mwifiex: dynamically increase preallocated firmware dump memory size This patch increase firmware dump memory 4K each time, until meet the demand. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/decl.h | 2 ++ drivers/net/wireless/marvell/mwifiex/pcie.c | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index c744a7030866..a184f9fdfbcb 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -122,6 +122,8 @@ #define BLOCK_NUMBER_OFFSET 15 #define SDIO_HEADER_OFFSET 28 +#define MWIFIEX_SIZE_4K 0x4000 + enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_UAP = 1, diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index c94d31e1b525..a62a09b028e5 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2402,7 +2402,8 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; unsigned int reg, reg_start, reg_end; - u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; + u8 *dbg_ptr, *end_ptr, *tmp_ptr, dump_num; + u8 idx, i, read_reg, doneflag = 0; enum rdwr_status stat; u32 memory_size; int ret; @@ -2485,11 +2486,21 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) mwifiex_read_reg_byte(adapter, reg, dbg_ptr); if (dbg_ptr < end_ptr) { dbg_ptr++; - } else { - mwifiex_dbg(adapter, ERROR, - "Allocated buf not enough\n"); - return; + continue; } + mwifiex_dbg(adapter, ERROR, + "pre-allocated buf not enough\n"); + tmp_ptr = + vzalloc(memory_size + MWIFIEX_SIZE_4K); + if (!tmp_ptr) + return; + memcpy(tmp_ptr, entry->mem_ptr, memory_size); + vfree(entry->mem_ptr); + entry->mem_ptr = tmp_ptr; + tmp_ptr = NULL; + dbg_ptr = entry->mem_ptr + memory_size; + memory_size += MWIFIEX_SIZE_4K; + end_ptr = entry->mem_ptr + memory_size; } if (stat != RDWR_STATUS_DONE) -- cgit From 03f0f7cdebeb0872076817ff835ea812a62b37c6 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Tue, 2 Feb 2016 22:05:08 -0800 Subject: mwifiex: increase the priority of firmware dump message Firmware dump operation takes few seconds. Hence it's important to notify user in dmesg that firmware dump has started or completed. Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/pcie.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index a62a09b028e5..14fe31671475 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2422,7 +2422,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) entry->mem_size = 0; } - mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n"); + mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n"); /* Read the number of the memories which will dump */ stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); @@ -2512,7 +2512,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) break; } while (true); } - mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n"); + mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n"); } static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter) -- cgit From 11e70824e75f2cfbad9ae066ca5b29e1c361f19e Mon Sep 17 00:00:00 2001 From: Xinming Hu Date: Tue, 2 Feb 2016 22:05:09 -0800 Subject: mwifiex: firmware dump support for w8997 chipset Current firmware dump solution support w8897 chipset, this patch extend the exist framework with support for w8997 chipset. Trigger firmware dump using, cat /sys/kernel/debug/mwifiex/mlan0/device_dump, data can be obtain by cat /sys/class/devcoredump/devcd*/data > data.txt after that. Signed-off-by: Xinming Hu Signed-off-by: Cathy Luo Signed-off-by: Amitkumar Karwar Signed-off-by: Kalle Valo --- drivers/net/wireless/marvell/mwifiex/decl.h | 1 + drivers/net/wireless/marvell/mwifiex/pcie.c | 30 +++++++++++++++++++---------- drivers/net/wireless/marvell/mwifiex/pcie.h | 13 ++++++++++++- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h index a184f9fdfbcb..bec300b9c2ea 100644 --- a/drivers/net/wireless/marvell/mwifiex/decl.h +++ b/drivers/net/wireless/marvell/mwifiex/decl.h @@ -274,6 +274,7 @@ struct mwifiex_11h_intf_state { } __packed; #define MWIFIEX_FW_DUMP_IDX 0xff +#define MWIFIEX_FW_DUMP_MAX_MEMSIZE 0x160000 #define MWIFIEX_DRV_INFO_IDX 20 #define FW_DUMP_MAX_NAME_LEN 8 #define FW_DUMP_HOST_READY 0xEE diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 14fe31671475..cc072142411a 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -2402,7 +2402,7 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) struct pcie_service_card *card = adapter->card; const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; unsigned int reg, reg_start, reg_end; - u8 *dbg_ptr, *end_ptr, *tmp_ptr, dump_num; + u8 *dbg_ptr, *end_ptr, *tmp_ptr, fw_dump_num, dump_num; u8 idx, i, read_reg, doneflag = 0; enum rdwr_status stat; u32 memory_size; @@ -2430,22 +2430,32 @@ static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) return; reg = creg->fw_dump_start; - mwifiex_read_reg_byte(adapter, reg, &dump_num); + mwifiex_read_reg_byte(adapter, reg, &fw_dump_num); + + /* W8997 chipset firmware dump will be restore in single region*/ + if (fw_dump_num == 0) + dump_num = 1; + else + dump_num = fw_dump_num; /* Read the length of every memory which will dump */ for (idx = 0; idx < dump_num; idx++) { struct memory_type_mapping *entry = &adapter->mem_type_mapping_tbl[idx]; - stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - return; - memory_size = 0; - reg = creg->fw_dump_start; - for (i = 0; i < 4; i++) { - mwifiex_read_reg_byte(adapter, reg, &read_reg); - memory_size |= (read_reg << (i * 8)); + if (fw_dump_num != 0) { + stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); + if (stat == RDWR_STATUS_FAILURE) + return; + + reg = creg->fw_dump_start; + for (i = 0; i < 4; i++) { + mwifiex_read_reg_byte(adapter, reg, &read_reg); + memory_size |= (read_reg << (i * 8)); reg++; + } + } else { + memory_size = MWIFIEX_FW_DUMP_MAX_MEMSIZE; } if (memory_size == 0) { diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index 8bc4390f0e20..29e58ce877e3 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -239,6 +239,11 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, .pfu_enabled = 1, .sleep_cookie = 0, + .fw_dump_ctrl = 0xcf4, + .fw_dump_start = 0xcf8, + .fw_dump_end = 0xcff, + .fw_dump_host_ready = 0xcc, + .fw_dump_read_done = 0xdd, .msix_support = 1, }; @@ -253,6 +258,10 @@ static struct memory_type_mapping mem_type_mapping_tbl_w8897[] = { {"MAC", NULL, 0, 0xF7}, }; +static struct memory_type_mapping mem_type_mapping_tbl_w8997[] = { + {"DUMP", NULL, 0, 0xDD}, +}; + struct mwifiex_pcie_device { const char *firmware; const struct mwifiex_pcie_card_reg *reg; @@ -289,7 +298,9 @@ static const struct mwifiex_pcie_device mwifiex_pcie8997 = { .reg = &mwifiex_reg_8997, .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, - .can_dump_fw = false, + .can_dump_fw = true, + .mem_type_mapping_tbl = mem_type_mapping_tbl_w8997, + .num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl_w8997), .can_ext_scan = true, }; -- cgit From 1a33e342cf35e53c08d76f2f891e48c014a5f34e Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:10 +0100 Subject: tty: serial: 8250: Fix whitespace errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes whitespace errors reported by checkpatch to increase readability. Main focus is on missing spaces after commas in function headers and macros (like foo,bar edited to foo, bar). Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_acorn.c | 2 +- drivers/tty/serial/8250/8250_hub6.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 8 +++-- drivers/tty/serial/8250/8250_port.c | 2 ++ drivers/tty/serial/8250/serial_cs.c | 60 ++++++++++++++++++------------------ 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c index 549aa07c0d27..402dfdd4940e 100644 --- a/drivers/tty/serial/8250/8250_acorn.c +++ b/drivers/tty/serial/8250/8250_acorn.c @@ -70,7 +70,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) uart.port.regshift = 2; uart.port.dev = &ec->dev; - for (i = 0; i < info->num_ports; i ++) { + for (i = 0; i < info->num_ports; i++) { uart.port.membase = info->vaddr + type->offset[i]; uart.port.mapbase = bus_addr + type->offset[i]; diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c index a5c778e83de0..27124e21eb96 100644 --- a/drivers/tty/serial/8250/8250_hub6.c +++ b/drivers/tty/serial/8250/8250_hub6.c @@ -10,7 +10,7 @@ #include #include -#define HUB6(card,port) \ +#define HUB6(card, port) \ { \ .iobase = 0x302, \ .irq = 3, \ diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index da501c1390db..3529302e5689 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1198,8 +1198,9 @@ static int pci_quatech_has_qmcr(struct uart_8250_port *port) static int pci_quatech_test(struct uart_8250_port *port) { - u8 reg; - u8 qopr = pci_quatech_rqopr(port); + u8 reg, qopr; + + qopr = pci_quatech_rqopr(port); pci_quatech_wqopr(port, qopr & QPCR_TEST_FOR1); reg = pci_quatech_rqopr(port) & 0xC0; if (reg != QPCR_TEST_GET1) @@ -1286,6 +1287,7 @@ static int pci_quatech_init(struct pci_dev *dev) unsigned long base = pci_resource_start(dev, 0); if (base) { u32 tmp; + outl(inl(base + 0x38) | 0x00002000, base + 0x38); tmp = inl(base + 0x3c); outl(tmp | 0x01000000, base + 0x3c); @@ -4487,7 +4489,7 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, - PCI_ANY_ID , PCI_ANY_ID, 0, 0, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_8_1152000 }, /* diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index c2b650aeb792..58aa5a126bc2 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1503,6 +1503,7 @@ static inline void __start_tx(struct uart_port *port) if (up->bugs & UART_BUG_TXEN) { unsigned char lsr; + lsr = serial_in(up, UART_LSR); up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; if (lsr & UART_LSR_THRE) @@ -1963,6 +1964,7 @@ static void wait_for_xmitr(struct uart_8250_port *up, int bits) /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { unsigned int tmout; + for (tmout = 1000000; tmout; tmout--) { unsigned int msr = serial_in(up, UART_MSR); up->msr_saved_flags |= msr & MSR_SAVE_FLAGS; diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 4d180c9423ef..6d7a801a78be 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -28,7 +28,7 @@ and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL. - + ======================================================================*/ #include @@ -257,7 +257,7 @@ static const struct serial_quirk quirks[] = { }; -static int serial_config(struct pcmcia_device * link); +static int serial_config(struct pcmcia_device *link); static void serial_remove(struct pcmcia_device *link) @@ -309,7 +309,7 @@ static int serial_probe(struct pcmcia_device *link) dev_dbg(&link->dev, "serial_attach()\n"); /* Create new serial device */ - info = kzalloc(sizeof (*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; info->p_dev = link; @@ -339,7 +339,7 @@ static void serial_detach(struct pcmcia_device *link) /*====================================================================*/ -static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, +static int setup_serial(struct pcmcia_device *handle, struct serial_info *info, unsigned int iobase, int irq) { struct uart_8250_port uart; @@ -600,7 +600,7 @@ static int serial_check_for_multi(struct pcmcia_device *p_dev, void *priv_data) } -static int serial_config(struct pcmcia_device * link) +static int serial_config(struct pcmcia_device *link) { struct serial_info *info = link->priv; int i; @@ -701,7 +701,7 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_PROD_ID12(1, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), PCMCIA_PFC_DEVICE_PROD_ID12(1, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), - PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), + PCMCIA_PFC_DEVICE_PROD_ID12(1, "NEC", "PK-UG-J001", 0x18df0ba0, 0x831b1064), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9), PCMCIA_PFC_DEVICE_PROD_ID12(1, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed), PCMCIA_PFC_DEVICE_PROD_ID12(1, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), @@ -797,30 +797,30 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3), - PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676), - PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), - PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), - PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232", 0x19ca78af, 0xb6bc0235), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.", "SERIAL CARD: CF232", 0x63f2e0bd, 0xb9e175d3), + PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.", "SERIAL CARD: CF232-5", 0x63f2e0bd, 0xfce33442), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF232", 0x3beb8cf2, 0x171e7190), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF232-5", 0x3beb8cf2, 0x20da4262), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF428", 0x3beb8cf2, 0xea5dd57d), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: CF500", 0x3beb8cf2, 0xd77255fa), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: IC232", 0x3beb8cf2, 0x6a709903), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: SL232", 0x3beb8cf2, 0x18430676), + PCMCIA_DEVICE_PROD_ID12("Elan", "Serial Port: XL232", 0x3beb8cf2, 0x6f933767), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: CF332", 0x3beb8cf2, 0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL332", 0x3beb8cf2, 0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL385", 0x3beb8cf2, 0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(0, "Elan", "Serial+Parallel Port: SP230", 0x3beb8cf2, 0xdb9e58bc), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: CF332", 0x3beb8cf2, 0x16dc1ba7), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL332", 0x3beb8cf2, 0x19816c41), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL385", 0x3beb8cf2, 0x64112029), + PCMCIA_MFC_DEVICE_PROD_ID12(1, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(2, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), + PCMCIA_MFC_DEVICE_PROD_ID12(3, "Elan", "Serial Port: SL432", 0x3beb8cf2, 0x1cce7ac4), PCMCIA_DEVICE_MANF_CARD(0x0279, 0x950b), /* too generic */ /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ -- cgit From 6d7c157fc706c173b720f0bae58e7a88ccfbeb9f Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:11 +0100 Subject: tty: serial: 8250: Replace spaces with tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Indentation is changed to match the correct format of using tabs instead of spaces wherever possible. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 12 ++++++------ drivers/tty/serial/8250/8250_port.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 3529302e5689..4186eb136f02 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -721,7 +721,7 @@ static int pci_ni8430_init(struct pci_dev *dev) */ pcibios_resource_to_bus(dev->bus, ®ion, &dev->resource[bar]); device_window = ((region.start + MITE_IOWBSR1_WIN_OFFSET) & 0xffffff00) - | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE; + | MITE_IOWBSR1_WENAB | MITE_IOWBSR1_WSIZE; writel(device_window, p + MITE_IOWBSR1); /* Set window access to go to RAMSEL IO address space */ @@ -1744,7 +1744,7 @@ xr17v35x_has_slave(struct serial_private *priv) const int dev_id = priv->dev->device; return ((dev_id == PCI_DEVICE_ID_EXAR_XR17V4358) || - (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358)); + (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358)); } static int @@ -1844,8 +1844,8 @@ pci_fastcom335_setup(struct serial_private *priv, static int pci_wch_ch353_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { port->port.flags |= UPF_FIXED_TYPE; port->port.type = PORT_16550A; @@ -1854,8 +1854,8 @@ pci_wch_ch353_setup(struct serial_private *priv, static int pci_wch_ch38x_setup(struct serial_private *priv, - const struct pciserial_board *board, - struct uart_8250_port *port, int idx) + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) { port->port.flags |= UPF_FIXED_TYPE; port->port.type = PORT_16850; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 58aa5a126bc2..a35abc19fc18 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -53,7 +53,7 @@ #define DEBUG_AUTOCONF(fmt...) do { } while (0) #endif -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* * Here we define the default xmit fifo size used for each type of UART. @@ -2487,7 +2487,7 @@ serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios, void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) + struct ktermios *old) { struct uart_8250_port *up = up_to_u8250p(port); unsigned char cval; -- cgit From f7941f508d1eabdd1046eef4182d6052d853f09c Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:12 +0100 Subject: tty: serial: 8250: Fix braces after struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a checkpatch warning by moving an opening curly brace to its correct position. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_hp300.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 2891958cd842..5e1b464b9e3b 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -24,8 +24,7 @@ #endif #ifdef CONFIG_HPAPCI -struct hp300_port -{ +struct hp300_port { struct hp300_port *next; /* next port */ int line; /* line (tty) number */ }; -- cgit From 740dc2defc476e58f7b6f3f6265d196b1b744c25 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:13 +0100 Subject: tty: serial: 8250: Fix multiline comment style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkpatch outputs some warnings about incorrect comment style, which is fixed by this patch. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_ingenic.c | 12 ++++++++---- drivers/tty/serial/8250/8250_pnp.c | 14 ++++++++------ drivers/tty/serial/8250/8250_port.c | 32 +++++++++++++++++--------------- drivers/tty/serial/8250/serial_cs.c | 26 +++++++++++++++++--------- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c index 47824887b63f..b4e1d39805b2 100644 --- a/drivers/tty/serial/8250/8250_ingenic.c +++ b/drivers/tty/serial/8250/8250_ingenic.c @@ -156,14 +156,18 @@ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value) break; case UART_IER: - /* Enable receive timeout interrupt with the - * receive line status interrupt */ + /* + * Enable receive timeout interrupt with the receive line + * status interrupt. + */ value |= (value & 0x4) << 2; break; case UART_MCR: - /* If we have enabled modem status IRQs we should enable modem - * mode. */ + /* + * If we have enabled modem status IRQs we should enable + * modem mode. + */ ier = p->serial_in(p, UART_IER); if (ier & UART_IER_MSI) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index f6332de4e3e3..38000d6225c3 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -357,8 +357,8 @@ static const struct pnp_device_id pnp_dev_table[] = { /* Fujitsu Wacom 1FGT Tablet PC device */ { "FUJ02E9", 0 }, /* - * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 in - * disguise) + * LG C1 EXPRESS DUAL (C1-PB11A3) touch screen (actually a FUJ02E6 + * in disguise). */ { "LTS0001", 0 }, /* Rockwell's (PORALiNK) 33600 INT PNP */ @@ -367,12 +367,14 @@ static const struct pnp_device_id pnp_dev_table[] = { { "PNPCXXX", UNKNOWN_DEV }, /* More unknown PnP modems */ { "PNPDXXX", UNKNOWN_DEV }, - /* Winbond CIR port, should not be probed. We should keep track - of it to prevent the legacy serial driver from probing it */ + /* + * Winbond CIR port, should not be probed. We should keep track of + * it to prevent the legacy serial driver from probing it. + */ { "WEC1022", CIR_PORT }, /* - * SMSC IrCC SIR/FIR port, should not be probed by serial driver - * as well so its own driver can bind to it. + * SMSC IrCC SIR/FIR port, should not be probed by serial driver as + * well so its own driver can bind to it. */ { "SMCF010", CIR_PORT }, { "", 0 } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a35abc19fc18..01246b8f8ca3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -251,9 +251,11 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE, }, -/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement -workaround of errata A-008006 which states that tx_loadsz should be -configured less than Maximum supported fifo bytes */ + /* + * tx_loadsz is set to 63-bytes instead of 64-bytes to implement + * workaround of errata A-008006 which states that tx_loadsz should + * be configured less than Maximum supported fifo bytes. + */ [PORT_16550A_FSL64] = { .name = "16550A_FSL64", .fifo_size = 64, @@ -2198,23 +2200,23 @@ int serial8250_do_startup(struct uart_port *port) serial8250_set_mctrl(port, port->mctrl); - /* Serial over Lan (SoL) hack: - Intel 8257x Gigabit ethernet chips have a - 16550 emulation, to be used for Serial Over Lan. - Those chips take a longer time than a normal - serial device to signalize that a transmission - data was queued. Due to that, the above test generally - fails. One solution would be to delay the reading of - iir. However, this is not reliable, since the timeout - is variable. So, let's just don't test if we receive - TX irq. This way, we'll never enable UART_BUG_TXEN. + /* + * Serial over Lan (SoL) hack: + * Intel 8257x Gigabit ethernet chips have a 16550 emulation, to be + * used for Serial Over Lan. Those chips take a longer time than a + * normal serial device to signalize that a transmission data was + * queued. Due to that, the above test generally fails. One solution + * would be to delay the reading of iir. However, this is not + * reliable, since the timeout is variable. So, let's just don't + * test if we receive TX irq. This way, we'll never enable + * UART_BUG_TXEN. */ if (up->port.flags & UPF_NO_TXEN_TEST) goto dont_test_tx_en; /* - * Do a quick test to see if we receive an - * interrupt when we enable the TX irq. + * Do a quick test to see if we receive an interrupt when we enable + * the TX irq. */ serial_port_out(port, UART_IER, UART_IER_THRI); lsr = serial_port_in(port, UART_LSR); diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 6d7a801a78be..2b7309d2e6f7 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -441,16 +441,20 @@ static int simple_config(struct pcmcia_device *link) struct serial_info *info = link->priv; int i = -ENODEV, try; - /* First pass: look for a config entry that looks normal. - * Two tries: without IO aliases, then with aliases */ + /* + * First pass: look for a config entry that looks normal. + * Two tries: without IO aliases, then with aliases. + */ link->config_flags |= CONF_AUTO_SET_VPP; for (try = 0; try < 4; try++) if (!pcmcia_loop_config(link, simple_config_check, &try)) goto found_port; - /* Second pass: try to find an entry that isn't picky about - its base address, then try to grab any standard serial port - address, and finally try to get any free port. */ + /* + * Second pass: try to find an entry that isn't picky about + * its base address, then try to grab any standard serial port + * address, and finally try to get any free port. + */ if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL)) goto found_port; @@ -480,8 +484,10 @@ static int multi_config_check(struct pcmcia_device *p_dev, void *priv_data) if (p_dev->resource[1]->end) return -EINVAL; - /* The quad port cards have bad CIS's, so just look for a - window larger than 8 ports and assume it will be right */ + /* + * The quad port cards have bad CIS's, so just look for a + * window larger than 8 ports and assume it will be right. + */ if (p_dev->resource[0]->end <= 8) return -EINVAL; @@ -623,8 +629,10 @@ static int serial_config(struct pcmcia_device *link) break; } - /* Another check for dual-serial cards: look for either serial or - multifunction cards that ask for appropriate IO port ranges */ + /* + * Another check for dual-serial cards: look for either serial or + * multifunction cards that ask for appropriate IO port ranges. + */ if ((info->multi == 0) && (link->has_func_id) && (link->socket->pcmcia_pfc == 0) && -- cgit From c2f5fde143b47136dc8f8b7a2ce65d9bf6286c12 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:14 +0100 Subject: tty: serial: 8250: Remove else after return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes checkpatch warnings about unnecessary else blocks after return statements. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4186eb136f02..123319738a89 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -805,10 +805,10 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) pi = (c & 0xff); - if (pi == 2) { + if (pi == 2) return 1; - } else if ((pi == 0) && - (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { + + if ((pi == 0) && (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { /* two possibilities: 0x30ps encodes number of parallel and * serial ports, or 0x1000 indicates *something*. This is not * immediately obvious, since the 2s1p+4s configuration seems @@ -816,12 +816,12 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) * advertising the same function 3 as the 4s+2s1p config. */ sub_serports = dev->subsystem_device & 0xf; - if (sub_serports > 0) { + if (sub_serports > 0) return sub_serports; - } else { - dev_err(&dev->dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); - return 0; - } + + dev_err(&dev->dev, + "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); + return 0; } moan_device("unknown NetMos/Mostech program interface", dev); -- cgit From b34f9fafea371a28d7007d7d003396f655c8f60d Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:15 +0100 Subject: tty: serial: 8250: Move EXPORT_SYMBOL to function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch moves EXPORT_SYMBOL macros directly after the definition of the corresponding symbol to remove checkpatch warnings. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 8031e428894f..3d9623824b0b 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -768,6 +768,7 @@ void serial8250_suspend_port(int line) uart_suspend_port(&serial8250_reg, port); } +EXPORT_SYMBOL(serial8250_suspend_port); /** * serial8250_resume_port - resume one serial port @@ -793,6 +794,7 @@ void serial8250_resume_port(int line) } uart_resume_port(&serial8250_reg, port); } +EXPORT_SYMBOL(serial8250_resume_port); /* * Register a set of serial devices attached to a platform device. The @@ -1172,9 +1174,6 @@ static void __exit serial8250_exit(void) module_init(serial8250_init); module_exit(serial8250_exit); -EXPORT_SYMBOL(serial8250_suspend_port); -EXPORT_SYMBOL(serial8250_resume_port); - MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); -- cgit From 207c28b1c6b5216247317b1222baa777ee87e632 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:16 +0100 Subject: tty: serial: 8250: Fix line continuation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed checkpatch warning about an unnecessary line continuation in a multi-line variable assignment. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Reviewed-by: Peter Hurley Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_hp300.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index 5e1b464b9e3b..cf566bbf8531 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -248,8 +248,8 @@ static int __init hp300_8250_init(void) /* Memory mapped I/O */ uart.port.iotype = UPIO_MEM; - uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ \ - | UPF_BOOT_AUTOCONF; + uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ + | UPF_BOOT_AUTOCONF; /* XXX - no interrupt support yet */ uart.port.irq = 0; uart.port.uartclk = HPAPCI_BAUD_BASE * 16; -- cgit From 149a44cc98cfd776b9c17fe10fb8eca12cd5212a Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:17 +0100 Subject: tty: serial: 8250: Add parentheses to macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a checkpatch warning caused by missing parentheses in the definition of a macro. Furthermore redundant parentheses are removed in an assignment. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 3d9623824b0b..9947d382cf97 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -691,7 +691,7 @@ static int __init univ8250_console_init(void) } console_initcall(univ8250_console_init); -#define SERIAL8250_CONSOLE &univ8250_console +#define SERIAL8250_CONSOLE (&univ8250_console) #else #define SERIAL8250_CONSOLE NULL #endif diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 123319738a89..ec8a63573fd2 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -803,7 +803,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev) unsigned int pi; unsigned short sub_serports; - pi = (c & 0xff); + pi = c & 0xff; if (pi == 2) return 1; -- cgit From 90ad7c442f6e32fa74f2d5e6fd28ace110b5025a Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:18 +0100 Subject: tty: serial: 8250: Fix multi-line strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged user-visible multi-line strings into a single line according to the Linux Kernel Coding Style, which allows user-visible strings to exceed the maximum line length of 80 characters. The main reason for this is to facilitate grepping for these strings. However, some strings were ignored in this patch, because the use of format specifiers breaks the ability to grep anyway. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 3 +-- drivers/tty/serial/8250/serial_cs.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 9947d382cf97..323679cd93d7 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1178,8 +1178,7 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver"); module_param(share_irqs, uint, 0644); -MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices" - " (unsafe)"); +MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)"); module_param(nr_uarts, uint, 0644); MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")"); diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index 2b7309d2e6f7..933c2688dd7e 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -533,8 +533,8 @@ static int multi_config(struct pcmcia_device *link) info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky, &base2)) { - dev_warn(&link->dev, "no usable port range " - "found, giving up\n"); + dev_warn(&link->dev, + "no usable port range found, giving up\n"); return -ENODEV; } } -- cgit From 9f59fbf0f22f79e11cf74fc19581726e3f118d57 Mon Sep 17 00:00:00 2001 From: Phillip Raffeck Date: Thu, 14 Jan 2016 16:08:19 +0100 Subject: tty: serial: 8250: Suitably replace printk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch replaces printk by the corresponding variant of dev_* in order to fix checkpatch warnings. If no suitable device pointer is present, the corresponding pr_* variant is used. Signed-off-by: Phillip Raffeck Signed-off-by: Anton Würfel Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 5 ++--- drivers/tty/serial/8250/8250_gsc.c | 7 ++++--- drivers/tty/serial/8250/8250_hp300.c | 20 +++++++++++--------- drivers/tty/serial/8250/8250_port.c | 3 +-- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 323679cd93d7..77752216de0e 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1099,9 +1099,8 @@ static int __init serial8250_init(void) serial8250_isa_init_ports(); - printk(KERN_INFO "Serial: 8250/16550 driver, " - "%d ports, IRQ sharing %sabled\n", nr_uarts, - share_irqs ? "en" : "dis"); + pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %sabled\n", + nr_uarts, share_irqs ? "en" : "dis"); #ifdef CONFIG_SPARC ret = sunserial_register_minors(&serial8250_reg, UART_NR); diff --git a/drivers/tty/serial/8250/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c index 2e3ea1a70d7b..b1e6ae9f1ff9 100644 --- a/drivers/tty/serial/8250/8250_gsc.c +++ b/drivers/tty/serial/8250/8250_gsc.c @@ -42,7 +42,7 @@ static int __init serial_init_chip(struct parisc_device *dev) * the user what they're missing. */ if (parisc_parent(dev)->id.hw_type != HPHW_IOA) - printk(KERN_INFO + dev_info(&dev->dev, "Serial: device 0x%llx not configured.\n" "Enable support for Wax, Lasi, Asp or Dino.\n", (unsigned long long)dev->hpa.start); @@ -66,8 +66,9 @@ static int __init serial_init_chip(struct parisc_device *dev) err = serial8250_register_8250_port(&uart); if (err < 0) { - printk(KERN_WARNING - "serial8250_register_8250_port returned error %d\n", err); + dev_warn(&dev->dev, + "serial8250_register_8250_port returned error %d\n", + err); iounmap(uart.port.membase); return err; } diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c index cf566bbf8531..38166db2b824 100644 --- a/drivers/tty/serial/8250/8250_hp300.c +++ b/drivers/tty/serial/8250/8250_hp300.c @@ -110,7 +110,7 @@ int __init hp300_setup_serial_console(void) /* Check for APCI console */ if (scode == 256) { #ifdef CONFIG_HPAPCI - printk(KERN_INFO "Serial console is HP APCI 1\n"); + pr_info("Serial console is HP APCI 1\n"); port.uartclk = HPAPCI_BAUD_BASE * 16; port.mapbase = (FRODO_BASE + FRODO_APCI_OFFSET(1)); @@ -118,7 +118,7 @@ int __init hp300_setup_serial_console(void) port.regshift = 2; add_preferred_console("ttyS", port.line, "9600n8"); #else - printk(KERN_WARNING "Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n"); + pr_warn("Serial console is APCI but support is disabled (CONFIG_HPAPCI)!\n"); return 0; #endif } else { @@ -127,7 +127,7 @@ int __init hp300_setup_serial_console(void) if (!pa) return 0; - printk(KERN_INFO "Serial console is HP DCA at select code %d\n", scode); + pr_info("Serial console is HP DCA at select code %d\n", scode); port.uartclk = HPDCA_BAUD_BASE * 16; port.mapbase = (pa + UART_OFFSET); @@ -141,13 +141,13 @@ int __init hp300_setup_serial_console(void) if (DIO_ID(pa + DIO_VIRADDRBASE) & 0x80) add_preferred_console("ttyS", port.line, "9600n8"); #else - printk(KERN_WARNING "Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n"); + pr_warn("Serial console is DCA but support is disabled (CONFIG_HPDCA)!\n"); return 0; #endif } if (early_serial_setup(&port) < 0) - printk(KERN_WARNING "hp300_setup_serial_console(): early_serial_setup() failed.\n"); + pr_warn("%s: early_serial_setup() failed.\n", __func__); return 0; } #endif /* CONFIG_SERIAL_8250_CONSOLE */ @@ -179,8 +179,9 @@ static int hpdca_init_one(struct dio_dev *d, line = serial8250_register_8250_port(&uart); if (line < 0) { - printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d" - " irq %d failed\n", d->scode, uart.port.irq); + dev_notice(&d->dev, + "8250_hp300: register_serial() DCA scode %d irq %d failed\n", + d->scode, uart.port.irq); return -ENOMEM; } @@ -260,8 +261,9 @@ static int __init hp300_8250_init(void) line = serial8250_register_8250_port(&uart); if (line < 0) { - printk(KERN_NOTICE "8250_hp300: register_serial() APCI" - " %d irq %d failed\n", i, uart.port.irq); + dev_notice(uart.port.dev, + "8250_hp300: register_serial() APCI %d irq %d failed\n", + i, uart.port.irq); kfree(port); continue; } diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 01246b8f8ca3..dbf08076093c 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1316,8 +1316,7 @@ static void autoconfig(struct uart_8250_port *up) out_lock: spin_unlock_irqrestore(&port->lock, flags); if (up->capabilities != old_capabilities) { - printk(KERN_WARNING - "ttyS%d: detected caps %08x should be %08x\n", + pr_warn("ttyS%d: detected caps %08x should be %08x\n", serial_index(port), old_capabilities, up->capabilities); } -- cgit From 952773b52b5ef8d6ea4ecbe37424b53d4f0c4704 Mon Sep 17 00:00:00 2001 From: Phillip Raffeck Date: Thu, 14 Jan 2016 16:08:20 +0100 Subject: tty: serial: 8250: Remove SERIAL_DEBUG_PNP macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes the macro SERIAL_DEBUG_PNP, which is used to enable debugging at compile time. As SERIAL_DEBUG_PNP is an orphan, the corresponding #ifdef is removed. To keep the ability to enable debugging at compile time, the call to printk(KERN_DEBUG ...) is replaced by a corresponding call to dev_dbg(), which is configurable via CONFIG_DYNAMIC_DEBUG. Signed-off-by: Phillip Raffeck Signed-off-by: Anton Würfel Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 38000d6225c3..cad40ff8d641 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -464,11 +464,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) } else return -ENODEV; -#ifdef SERIAL_DEBUG_PNP - printk(KERN_DEBUG - "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", - uart.port.iobase, uart.port.mapbase, uart.port.irq, uart.port.iotype); -#endif + dev_dbg(&dev->dev, + "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", + uart.port.iobase, uart.port.mapbase, + uart.port.irq, uart.port.iotype); + if (flags & CIR_PORT) { uart.port.flags |= UPF_FIXED_PORT | UPF_FIXED_TYPE; uart.port.type = PORT_8250_CIR; -- cgit From 9faef1cb33d4cc17ae4e85de67aa242eebb64102 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:21 +0100 Subject: tty: serial: 8250: Correct conversion specifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes compiler warnings about wrong conversion specifiers used in a debug output in 8250_pnp.c. The precise warning is: drivers/tty/serial/8250/8250_pnp.c: In function ‘serial_pnp_probe’: include/linux/dynamic_debug.h:64:16: warning: format ‘%x’ expects argument of [...] drivers/tty/serial/8250/8250_pnp.c:467:2: note: in expansion of macro ‘dev_dbg’ dev_dbg(&dev->dev, ^ include/linux/dynamic_debug.h:64:16: warning: format ‘%lx’ expects argument of [...] drivers/tty/serial/8250/8250_pnp.c:467:2: note: in expansion of macro ‘dev_dbg’ dev_dbg(&dev->dev, ^ Those warnings never got triggered, because the command was nested in an #ifdef, which is removed by a patch of this series. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pnp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index cad40ff8d641..e6bd21967c27 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -465,8 +465,8 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) return -ENODEV; dev_dbg(&dev->dev, - "Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n", - uart.port.iobase, uart.port.mapbase, + "Setup PNP port: port %lx, mem %pa, irq %d, type %d\n", + uart.port.iobase, &uart.port.mapbase, uart.port.irq, uart.port.iotype); if (flags & CIR_PORT) { -- cgit From 829b0000242e3d2729972a034209afdd2b004456 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:22 +0100 Subject: tty: serial: 8250: Merge duplicate conditions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch refactors a switch case statement by merging an if condition in the default case into an identical condition right after the switch statement. This comes with a slight change in behaviour: If pci_netmos_9900_numports returns 0, an additional warning is printed. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index ec8a63573fd2..4b1c241e6f75 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -850,13 +850,13 @@ static int pci_netmos_init(struct pci_dev *dev) break; default: - if (num_serial == 0 ) { - moan_device("unknown NetMos/Mostech device", dev); - } + break; } - if (num_serial == 0) + if (num_serial == 0) { + moan_device("unknown NetMos/Mostech device", dev); return -ENODEV; + } return num_serial; } -- cgit From b3d67936bf1926ae53e969fb4bab4516cdaa9333 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:23 +0100 Subject: tty: serial: 8250: Fix indentation warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checkpatch complains about incorrect indentation of switch/case statements. This patch fixes the corresponding warnings. Additionally some indentation is changed to match the correct format specified in the Linux Kernel Coding Style. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 16 ++++++++-------- drivers/tty/serial/8250/8250_pnp.c | 4 ++-- drivers/tty/serial/8250/8250_port.c | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 4b1c241e6f75..1e7beaa20be5 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -842,15 +842,15 @@ static int pci_netmos_init(struct pci_dev *dev) return 0; switch (dev->device) { /* FALLTHROUGH on all */ - case PCI_DEVICE_ID_NETMOS_9904: - case PCI_DEVICE_ID_NETMOS_9912: - case PCI_DEVICE_ID_NETMOS_9922: - case PCI_DEVICE_ID_NETMOS_9900: - num_serial = pci_netmos_9900_numports(dev); - break; + case PCI_DEVICE_ID_NETMOS_9904: + case PCI_DEVICE_ID_NETMOS_9912: + case PCI_DEVICE_ID_NETMOS_9922: + case PCI_DEVICE_ID_NETMOS_9900: + num_serial = pci_netmos_9900_numports(dev); + break; - default: - break; + default: + break; } if (num_serial == 0) { diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index e6bd21967c27..34f05ed78b68 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c @@ -427,8 +427,8 @@ static bool check_resources(struct pnp_dev *dev) static int serial_pnp_guess_board(struct pnp_dev *dev) { if (!(check_name(pnp_dev_name(dev)) || - (dev->card && check_name(dev->card->name)))) - return -ENODEV; + (dev->card && check_name(dev->card->name)))) + return -ENODEV; if (check_resources(dev)) return 0; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index dbf08076093c..e376cfaf8ab7 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2469,9 +2469,9 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud, serial_port_out(port, 0x2, quot_frac); } -static unsigned int -serial8250_get_baud_rate(struct uart_port *port, struct ktermios *termios, - struct ktermios *old) +static unsigned int serial8250_get_baud_rate(struct uart_port *port, + struct ktermios *termios, + struct ktermios *old) { unsigned int tolerance = port->uartclk / 100; -- cgit From b3bd666807d98d8ea53e578307979f6424175612 Mon Sep 17 00:00:00 2001 From: Anton Wuerfel Date: Thu, 14 Jan 2016 16:08:24 +0100 Subject: tty: serial: 8250: Add generic port init macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes redundant 8250 port initialization macros and replaces them by a single generic base-macro, which is specialized as needed. Signed-off-by: Anton Würfel Signed-off-by: Phillip Raffeck Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Cc: linux-kernel@i4.cs.fau.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250.h | 12 ++++++++ drivers/tty/serial/8250/8250_accent.c | 13 ++------- drivers/tty/serial/8250/8250_boca.c | 41 ++++++++++++---------------- drivers/tty/serial/8250/8250_exar_st16c554.c | 17 ++++-------- drivers/tty/serial/8250/8250_fourport.c | 28 ++++++++----------- 5 files changed, 49 insertions(+), 62 deletions(-) diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index ce587c03efc3..047a7ba6796a 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -92,6 +92,18 @@ struct serial8250_config { #define SERIAL8250_SHARE_IRQS 0 #endif +#define SERIAL8250_PORT_FLAGS(_base, _irq, _flags) \ + { \ + .iobase = _base, \ + .irq = _irq, \ + .uartclk = 1843200, \ + .iotype = UPIO_PORT, \ + .flags = UPF_BOOT_AUTOCONF | (_flags), \ + } + +#define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0) + + static inline int serial_in(struct uart_8250_port *up, int offset) { return up->port.serial_in(&up->port, offset); diff --git a/drivers/tty/serial/8250/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c index 34b51c651192..522aeae05192 100644 --- a/drivers/tty/serial/8250/8250_accent.c +++ b/drivers/tty/serial/8250/8250_accent.c @@ -10,18 +10,11 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port accent_data[] = { - PORT(0x330, 4), - PORT(0x338, 4), + SERIAL8250_PORT(0x330, 4), + SERIAL8250_PORT(0x338, 4), { }, }; diff --git a/drivers/tty/serial/8250/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c index d125dc107985..a63b5998e383 100644 --- a/drivers/tty/serial/8250/8250_boca.c +++ b/drivers/tty/serial/8250/8250_boca.c @@ -10,32 +10,25 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port boca_data[] = { - PORT(0x100, 12), - PORT(0x108, 12), - PORT(0x110, 12), - PORT(0x118, 12), - PORT(0x120, 12), - PORT(0x128, 12), - PORT(0x130, 12), - PORT(0x138, 12), - PORT(0x140, 12), - PORT(0x148, 12), - PORT(0x150, 12), - PORT(0x158, 12), - PORT(0x160, 12), - PORT(0x168, 12), - PORT(0x170, 12), - PORT(0x178, 12), + SERIAL8250_PORT(0x100, 12), + SERIAL8250_PORT(0x108, 12), + SERIAL8250_PORT(0x110, 12), + SERIAL8250_PORT(0x118, 12), + SERIAL8250_PORT(0x120, 12), + SERIAL8250_PORT(0x128, 12), + SERIAL8250_PORT(0x130, 12), + SERIAL8250_PORT(0x138, 12), + SERIAL8250_PORT(0x140, 12), + SERIAL8250_PORT(0x148, 12), + SERIAL8250_PORT(0x150, 12), + SERIAL8250_PORT(0x158, 12), + SERIAL8250_PORT(0x160, 12), + SERIAL8250_PORT(0x168, 12), + SERIAL8250_PORT(0x170, 12), + SERIAL8250_PORT(0x178, 12), { }, }; diff --git a/drivers/tty/serial/8250/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c index bf53aabf9b5e..3a7cb8262bb9 100644 --- a/drivers/tty/serial/8250/8250_exar_st16c554.c +++ b/drivers/tty/serial/8250/8250_exar_st16c554.c @@ -13,20 +13,13 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF, \ - } +#include "8250.h" static struct plat_serial8250_port exar_data[] = { - PORT(0x100, 5), - PORT(0x108, 5), - PORT(0x110, 5), - PORT(0x118, 5), + SERIAL8250_PORT(0x100, 5), + SERIAL8250_PORT(0x108, 5), + SERIAL8250_PORT(0x110, 5), + SERIAL8250_PORT(0x118, 5), { }, }; diff --git a/drivers/tty/serial/8250/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c index be1582609626..4045180a8cfc 100644 --- a/drivers/tty/serial/8250/8250_fourport.c +++ b/drivers/tty/serial/8250/8250_fourport.c @@ -10,24 +10,20 @@ #include #include -#define PORT(_base,_irq) \ - { \ - .iobase = _base, \ - .irq = _irq, \ - .uartclk = 1843200, \ - .iotype = UPIO_PORT, \ - .flags = UPF_BOOT_AUTOCONF | UPF_FOURPORT, \ - } +#include "8250.h" + +#define SERIAL8250_FOURPORT(_base, _irq) \ + SERIAL8250_PORT_FLAGS(_base, _irq, UPF_FOURPORT) static struct plat_serial8250_port fourport_data[] = { - PORT(0x1a0, 9), - PORT(0x1a8, 9), - PORT(0x1b0, 9), - PORT(0x1b8, 9), - PORT(0x2a0, 5), - PORT(0x2a8, 5), - PORT(0x2b0, 5), - PORT(0x2b8, 5), + SERIAL8250_FOURPORT(0x1a0, 9), + SERIAL8250_FOURPORT(0x1a8, 9), + SERIAL8250_FOURPORT(0x1b0, 9), + SERIAL8250_FOURPORT(0x1b8, 9), + SERIAL8250_FOURPORT(0x2a0, 5), + SERIAL8250_FOURPORT(0x2a8, 5), + SERIAL8250_FOURPORT(0x2b0, 5), + SERIAL8250_FOURPORT(0x2b8, 5), { }, }; -- cgit From e3c5fc4d47ad2a52924d72e9945e00ec6dd2997b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 18 Oct 2015 18:21:14 -0400 Subject: drivers/tty: make hvc/hvc_vio.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/hvc/Kconfig:config HVC_CONSOLE drivers/tty/hvc/Kconfig: bool "pSeries Hypervisor Virtual Console 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_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. We don't replace module.h with init.h since the file already has that. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: Michael Ellerman Cc: Anton Blanchard Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_vio.c | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c index f575a9b5ede7..b05dc5086627 100644 --- a/drivers/tty/hvc/hvc_vio.c +++ b/drivers/tty/hvc/hvc_vio.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include @@ -61,7 +60,6 @@ static struct vio_device_id hvc_driver_table[] = { #endif { "", "" } }; -MODULE_DEVICE_TABLE(vio, hvc_driver_table); typedef enum hv_protocol { HV_PROTOCOL_RAW, @@ -363,26 +361,13 @@ static int hvc_vio_probe(struct vio_dev *vdev, return 0; } -static int hvc_vio_remove(struct vio_dev *vdev) -{ - struct hvc_struct *hp = dev_get_drvdata(&vdev->dev); - int rc, termno; - - termno = hp->vtermno; - rc = hvc_remove(hp); - if (rc == 0) { - if (hvterm_privs[termno] != &hvterm_priv0) - kfree(hvterm_privs[termno]); - hvterm_privs[termno] = NULL; - } - return rc; -} - static struct vio_driver hvc_vio_driver = { .id_table = hvc_driver_table, .probe = hvc_vio_probe, - .remove = hvc_vio_remove, .name = hvc_driver_name, + .driver = { + .suppress_bind_attrs = true, + }, }; static int __init hvc_vio_init(void) @@ -394,13 +379,7 @@ static int __init hvc_vio_init(void) return rc; } -module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ - -static void __exit hvc_vio_exit(void) -{ - vio_unregister_driver(&hvc_vio_driver); -} -module_exit(hvc_vio_exit); +device_initcall(hvc_vio_init); /* after drivers/tty/hvc/hvc_console.c */ void __init hvc_vio_init_early(void) { -- cgit From fc7f47bf1d0a45304809c42405f82eecfc04fd29 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sun, 18 Oct 2015 18:21:15 -0400 Subject: drivers/tty: make ehv_bytechan.c explicitly non-modular The Kconfig currently controlling compilation of this code is: drivers/tty/Kconfig:config PPC_EPAPR_HV_BYTECHAN drivers/tty/Kconfig: bool "ePAPR hypervisor byte channel driver" ...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. We explicitly disallow a driver unbind, since that doesn't have a sensible use case anyway, and it allows us to drop the ".remove" code for non-modular drivers. 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: Greg Kroah-Hartman Cc: Jiri Slaby Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/tty/ehv_bytechan.c | 40 +++------------------------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 342b36b9ad35..7ac9bcdf1e61 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -23,7 +23,6 @@ * byte channel used for the console is designated as the default tty. */ -#include #include #include #include @@ -719,19 +718,6 @@ error: return ret; } -static int ehv_bc_tty_remove(struct platform_device *pdev) -{ - struct ehv_bc_data *bc = dev_get_drvdata(&pdev->dev); - - tty_unregister_device(ehv_bc_driver, bc - bcs); - - tty_port_destroy(&bc->port); - irq_dispose_mapping(bc->tx_irq); - irq_dispose_mapping(bc->rx_irq); - - return 0; -} - static const struct of_device_id ehv_bc_tty_of_ids[] = { { .compatible = "epapr,hv-byte-channel" }, {} @@ -741,15 +727,15 @@ static struct platform_driver ehv_bc_tty_driver = { .driver = { .name = "ehv-bc", .of_match_table = ehv_bc_tty_of_ids, + .suppress_bind_attrs = true, }, .probe = ehv_bc_tty_probe, - .remove = ehv_bc_tty_remove, }; /** * ehv_bc_init - ePAPR hypervisor byte channel driver initialization * - * This function is called when this module is loaded. + * This function is called when this driver is loaded. */ static int __init ehv_bc_init(void) { @@ -814,24 +800,4 @@ error: return ret; } - - -/** - * ehv_bc_exit - ePAPR hypervisor byte channel driver termination - * - * This function is called when this driver is unloaded. - */ -static void __exit ehv_bc_exit(void) -{ - platform_driver_unregister(&ehv_bc_tty_driver); - tty_unregister_driver(ehv_bc_driver); - put_tty_driver(ehv_bc_driver); - kfree(bcs); -} - -module_init(ehv_bc_init); -module_exit(ehv_bc_exit); - -MODULE_AUTHOR("Timur Tabi "); -MODULE_DESCRIPTION("ePAPR hypervisor byte channel driver"); -MODULE_LICENSE("GPL v2"); +device_initcall(ehv_bc_init); -- cgit From 1051937d465665e3360ea7d9a3d2adfd86f47dd4 Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Wed, 28 Oct 2015 11:56:44 +0530 Subject: tty/vt/keyboard: use memdup_user to simplify code use memdup_user rather than duplicating implementation. found by coccinelle Signed-off-by: Saurabh Sengar Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/keyboard.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 6f0336fff501..f973bfce5d08 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1706,16 +1706,12 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm) return -EINVAL; if (ct) { - dia = kmalloc(sizeof(struct kbdiacr) * ct, - GFP_KERNEL); - if (!dia) - return -ENOMEM; - if (copy_from_user(dia, a->kbdiacr, - sizeof(struct kbdiacr) * ct)) { - kfree(dia); - return -EFAULT; - } + dia = memdup_user(a->kbdiacr, + sizeof(struct kbdiacr) * ct); + if (IS_ERR(dia)) + return PTR_ERR(dia); + } spin_lock_irqsave(&kbd_event_lock, flags); -- cgit From b1209983d2c012be8d253ed118f9281ed9f46af6 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 24 Oct 2015 02:27:43 +0300 Subject: tty: synclinkmp: do not ignore errors in probe() synclinkmp_init_one() ignores all errors and does not release all resources if something fails. The patch adds returned code to device_init() and add_device() and proper error handling. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/synclinkmp.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index 4b314b63a2ed..90da0c712262 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c @@ -549,8 +549,8 @@ static int tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); static int set_break(struct tty_struct *tty, int break_state); -static void add_device(SLMP_INFO *info); -static void device_init(int adapter_num, struct pci_dev *pdev); +static int add_device(SLMP_INFO *info); +static int device_init(int adapter_num, struct pci_dev *pdev); static int claim_resources(SLMP_INFO *info); static void release_resources(SLMP_INFO *info); @@ -3688,7 +3688,7 @@ static void release_resources(SLMP_INFO *info) /* Add the specified device instance data structure to the * global linked list of devices and increment the device count. */ -static void add_device(SLMP_INFO *info) +static int add_device(SLMP_INFO *info) { info->next_device = NULL; info->line = synclinkmp_device_count; @@ -3726,7 +3726,9 @@ static void add_device(SLMP_INFO *info) info->max_frame_size ); #if SYNCLINK_GENERIC_HDLC - hdlcdev_init(info); + return hdlcdev_init(info); +#else + return 0; #endif } @@ -3815,10 +3817,10 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) return info; } -static void device_init(int adapter_num, struct pci_dev *pdev) +static int device_init(int adapter_num, struct pci_dev *pdev) { SLMP_INFO *port_array[SCA_MAX_PORTS]; - int port; + int port, rc; /* allocate device instances for up to SCA_MAX_PORTS devices */ for ( port = 0; port < SCA_MAX_PORTS; ++port ) { @@ -3828,14 +3830,16 @@ static void device_init(int adapter_num, struct pci_dev *pdev) tty_port_destroy(&port_array[port]->port); kfree(port_array[port]); } - return; + return -ENOMEM; } } /* give copy of port_array to all ports and add to device list */ for ( port = 0; port < SCA_MAX_PORTS; ++port ) { memcpy(port_array[port]->port_array,port_array,sizeof(port_array)); - add_device( port_array[port] ); + rc = add_device( port_array[port] ); + if (rc) + goto err_add; spin_lock_init(&port_array[port]->lock); } @@ -3855,21 +3859,30 @@ static void device_init(int adapter_num, struct pci_dev *pdev) alloc_dma_bufs(port_array[port]); } - if ( request_irq(port_array[0]->irq_level, + rc = request_irq(port_array[0]->irq_level, synclinkmp_interrupt, port_array[0]->irq_flags, port_array[0]->device_name, - port_array[0]) < 0 ) { + port_array[0]); + if ( rc ) { printk( "%s(%d):%s Can't request interrupt, IRQ=%d\n", __FILE__,__LINE__, port_array[0]->device_name, port_array[0]->irq_level ); + goto err_irq; } - else { - port_array[0]->irq_requested = true; - adapter_test(port_array[0]); - } + port_array[0]->irq_requested = true; + adapter_test(port_array[0]); } + return 0; +err_irq: + release_resources( port_array[0] ); +err_add: + for ( port = 0; port < SCA_MAX_PORTS; ++port ) { + tty_port_destroy(&port_array[port]->port); + kfree(port_array[port]); + } + return rc; } static const struct tty_operations ops = { @@ -5584,8 +5597,7 @@ static int synclinkmp_init_one (struct pci_dev *dev, printk("error enabling pci device %p\n", dev); return -EIO; } - device_init( ++synclinkmp_adapter_count, dev ); - return 0; + return device_init( ++synclinkmp_adapter_count, dev ); } static void synclinkmp_remove_one (struct pci_dev *dev) -- cgit From e9b736d88af1a143530565929390cadf036dc799 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 26 Nov 2015 19:28:26 +0100 Subject: TTY: n_hdlc, fix lockdep false positive The class of 4 n_hdls buf locks is the same because a single function n_hdlc_buf_list_init is used to init all the locks. But since flush_tx_queue takes n_hdlc->tx_buf_list.spinlock and then calls n_hdlc_buf_put which takes n_hdlc->tx_free_buf_list.spinlock, lockdep emits a warning: ============================================= [ INFO: possible recursive locking detected ] 4.3.0-25.g91e30a7-default #1 Not tainted --------------------------------------------- a.out/1248 is trying to acquire lock: (&(&list->spinlock)->rlock){......}, at: [] n_hdlc_buf_put+0x20/0x60 [n_hdlc] but task is already holding lock: (&(&list->spinlock)->rlock){......}, at: [] n_hdlc_tty_ioctl+0x127/0x1d0 [n_hdlc] other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(&(&list->spinlock)->rlock); lock(&(&list->spinlock)->rlock); *** DEADLOCK *** May be due to missing lock nesting notation 2 locks held by a.out/1248: #0: (&tty->ldisc_sem){++++++}, at: [] tty_ldisc_ref_wait+0x20/0x50 #1: (&(&list->spinlock)->rlock){......}, at: [] n_hdlc_tty_ioctl+0x127/0x1d0 [n_hdlc] ... Call Trace: ... [] _raw_spin_lock_irqsave+0x50/0x70 [] n_hdlc_buf_put+0x20/0x60 [n_hdlc] [] n_hdlc_tty_ioctl+0x144/0x1d0 [n_hdlc] [] tty_ioctl+0x3f1/0xe40 ... Fix it by initializing the spin_locks separately. This removes also reduntand memset of a freshly kzallocated space. Signed-off-by: Jiri Slaby Reported-by: Dmitry Vyukov Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_hdlc.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index bbc4ce66c2c1..bcaba17688f6 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -159,7 +159,6 @@ struct n_hdlc { /* * HDLC buffer list manipulation functions */ -static void n_hdlc_buf_list_init(struct n_hdlc_buf_list *list); static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, struct n_hdlc_buf *buf); static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list); @@ -853,10 +852,10 @@ static struct n_hdlc *n_hdlc_alloc(void) if (!n_hdlc) return NULL; - n_hdlc_buf_list_init(&n_hdlc->rx_free_buf_list); - n_hdlc_buf_list_init(&n_hdlc->tx_free_buf_list); - n_hdlc_buf_list_init(&n_hdlc->rx_buf_list); - n_hdlc_buf_list_init(&n_hdlc->tx_buf_list); + spin_lock_init(&n_hdlc->rx_free_buf_list.spinlock); + spin_lock_init(&n_hdlc->tx_free_buf_list.spinlock); + spin_lock_init(&n_hdlc->rx_buf_list.spinlock); + spin_lock_init(&n_hdlc->tx_buf_list.spinlock); /* allocate free rx buffer list */ for(i=0;ispinlock); -} /* end of n_hdlc_buf_list_init() */ - /** * n_hdlc_buf_put - add specified HDLC buffer to tail of specified list * @list - pointer to buffer list -- cgit From 401879c57f01cbf2da204ad2e8db910525c6dbea Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Jan 2016 17:48:45 -0800 Subject: net: irda: Fix use-after-free in irtty_open() The N_IRDA line discipline may access the previous line discipline's closed and already-fre private data on open [1]. The tty->disc_data field _never_ refers to valid data on entry to the line discipline's open() method. Rather, the ldisc is expected to initialize that field for its own use for the lifetime of the instance (ie. from open() to close() only). [1] ================================================================== BUG: KASAN: use-after-free in irtty_open+0x422/0x550 at addr ffff8800331dd068 Read of size 4 by task a.out/13960 ============================================================================= BUG kmalloc-512 (Tainted: G B ): kasan: bad access detected ----------------------------------------------------------------------------- ... Call Trace: [] __asan_report_load4_noabort+0x3e/0x40 mm/kasan/report.c:279 [] irtty_open+0x422/0x550 drivers/net/irda/irtty-sir.c:436 [] tty_ldisc_open.isra.2+0x60/0xa0 drivers/tty/tty_ldisc.c:447 [] tty_set_ldisc+0x1a0/0x940 drivers/tty/tty_ldisc.c:567 [< inline >] tiocsetd drivers/tty/tty_io.c:2650 [] tty_ioctl+0xace/0x1fd0 drivers/tty/tty_io.c:2883 [< inline >] vfs_ioctl fs/ioctl.c:43 [] do_vfs_ioctl+0x57c/0xe60 fs/ioctl.c:607 [< inline >] SYSC_ioctl fs/ioctl.c:622 [] SyS_ioctl+0x74/0x80 fs/ioctl.c:613 [] entry_SYSCALL_64_fastpath+0x16/0x7a Reported-and-tested-by: Dmitry Vyukov Cc: Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/irtty-sir.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 696852eb23c3..7a3f990c1935 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -430,16 +430,6 @@ static int irtty_open(struct tty_struct *tty) /* Module stuff handled via irda_ldisc.owner - Jean II */ - /* First make sure we're not already connected. */ - if (tty->disc_data != NULL) { - priv = tty->disc_data; - if (priv && priv->magic == IRTTY_MAGIC) { - ret = -EEXIST; - goto out; - } - tty->disc_data = NULL; /* ### */ - } - /* stop the underlying driver */ irtty_stop_receiver(tty, TRUE); if (tty->ops->stop) -- cgit From 9b95d95d5eba5a077283423616b4ec3329d6ab00 Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Tue, 15 Dec 2015 01:50:19 +0200 Subject: char: constify tty_port_operations structs Constifies tty_port_operations structure in the char driver since it is not modified after its initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Acked-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/char/ttyprintk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index a15ce4ef39cd..b098d2d0b7c4 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -171,7 +171,7 @@ static const struct tty_operations ttyprintk_ops = { .ioctl = tpk_ioctl, }; -static struct tty_port_operations null_ops = { }; +static const struct tty_port_operations null_ops = { }; static struct tty_driver *ttyprintk_driver; -- cgit From 04b757dfd26cee24bc62ed815cd87efbf10ef2fc Mon Sep 17 00:00:00 2001 From: Aya Mahfouz Date: Tue, 15 Dec 2015 01:53:36 +0200 Subject: tty: constify tty_port_operations structs Constifies tty_port_operations structures in the tty driver since they are not modified after their initialization. Detected and found using Coccinelle. Suggested-by: Julia Lawall Signed-off-by: Aya Mahfouz Signed-off-by: Greg Kroah-Hartman --- drivers/tty/goldfish.c | 2 +- drivers/tty/mxser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c index 0f82c0b146f6..752232c77503 100644 --- a/drivers/tty/goldfish.c +++ b/drivers/tty/goldfish.c @@ -162,7 +162,7 @@ static int goldfish_tty_console_setup(struct console *co, char *options) return 0; } -static struct tty_port_operations goldfish_port_ops = { +static const struct tty_port_operations goldfish_port_ops = { .activate = goldfish_tty_activate, .shutdown = goldfish_tty_shutdown }; diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 9a0791e523b5..2f12bb9f4336 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -2336,7 +2336,7 @@ static const struct tty_operations mxser_ops = { .get_icount = mxser_get_icount, }; -static struct tty_port_operations mxser_port_ops = { +static const struct tty_port_operations mxser_port_ops = { .carrier_raised = mxser_carrier_raised, .dtr_rts = mxser_dtr_rts, .activate = mxser_activate, -- cgit From a4f642a8a3c2838ad09fe8313d45db46600e1478 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 22:54:56 +0100 Subject: tty: nozomi: avoid a harmless gcc warning The nozomi wireless data driver has its own helper function to transfer data from a FIFO, doing an extra byte swap on big-endian architectures, presumably to bring the data back into byte-serial order after readw() or readl() perform their implicit byteswap. This helper function is used in the receive_data() function to first read the length into a 32-bit variable, which causes a compile-time warning: drivers/tty/nozomi.c: In function 'receive_data': drivers/tty/nozomi.c:857:9: warning: 'size' may be used uninitialized in this function [-Wmaybe-uninitialized] The problem is that gcc is unsure whether the data was actually read or not. We know that it is at this point, so we can replace it with a single readl() to shut up that warning. I am leaving the byteswap in there, to preserve the existing behavior, even though this seems fishy: Reading the length of the data into a cpu-endian variable should normally not use a second byteswap on big-endian systems, unless the hardware is aware of the CPU endianess. There appears to be a lot more confusion about endianess in this driver, so it probably has not worked on big-endian systems in a long time, if ever, and I have no way to test it. It's well possible that this driver has not been used by anyone in a while, the last patch that looks like it was tested on the hardware is from 2008. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/nozomi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index 80f9de907563..5cc80b80c82b 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -823,7 +823,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); int i, ret; - read_mem32((u32 *) &size, addr, 4); + size = __le32_to_cpu(readl(addr)); /* DBG1( "%d bytes port: %d", size, index); */ if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { -- cgit From 05ead49691d245f67bdd1b30cab5d9af522ac884 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 22:54:57 +0100 Subject: tty: cyclades: cyz_interrupt is only used for PCI When CONFIG_PCI is not set, enabling CONFIG_CYZ_INTR has no practical effect other than generating a warning about an unused function: drivers/tty/cyclades.c:1184:20: warning: 'cyz_interrupt' defined but not used [-Wunused-function] static irqreturn_t cyz_interrupt(int irq, void *dev_id) This adds a dependency to avoid that warning. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index c01f45095877..82c4d2e45319 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -226,7 +226,7 @@ config CYCLADES config CYZ_INTR bool "Cyclades-Z interrupt mode operation" - depends on CYCLADES + depends on CYCLADES && PCI help The Cyclades-Z family of multiport cards allows 2 (two) driver op modes: polling and interrupt. In polling mode, the driver will check -- cgit From e36ae3439936e13c33f5841c7c2c1a9875acbb6d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 22:54:58 +0100 Subject: tty: hvc_xen: hide xen_console_remove when unused xencons_disconnect_backend() is only called from xen_console_remove(), which is conditionally compiled, so we get a harmless warning when CONFIG_HVC_XEN_FRONTEND is unset: hvc/hvc_xen.c:350:12: error: 'xen_console_remove' defined but not used [-Werror=unused-function] This moves the function down into the same #ifdef section to silence the warning. Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/tty/hvc/hvc_xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index fa816b7193b6..11725422dacb 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -323,6 +323,7 @@ void xen_console_resume(void) } } +#ifdef CONFIG_HVC_XEN_FRONTEND static void xencons_disconnect_backend(struct xencons_info *info) { if (info->irq > 0) @@ -363,7 +364,6 @@ static int xen_console_remove(struct xencons_info *info) return 0; } -#ifdef CONFIG_HVC_XEN_FRONTEND static int xencons_remove(struct xenbus_device *dev) { return xen_console_remove(dev_get_drvdata(&dev->dev)); -- cgit From e882f7158f102ef148a2d96eb4cb50cc88830c87 Mon Sep 17 00:00:00 2001 From: Melchior FRANZ Date: Sun, 1 Nov 2015 19:48:18 +0100 Subject: tty: vt: initialize softcursor_original correctly add_softcursor() stores the contents of the text buffer position in this variable before drawing the softcursor, whereas hide_softcursor() writes the value back. A value of -1 means that no cursor has been drawn and therefore no character is to be restored. softcursor_original, however, is only implicitly initialized with 0. Therefore, when hide_softcursor is called for the first time (console_init -> con_init -> redraw_screen -> hide_cursor), it wrongly writes 0x0000 in the top left corner of the text buffer. Normally, this is just as black as the rest of the screen (vc_video_erase_char) and can't be seen, but it appears as a black cursor rectangle on non-black backgrounds e.g. with boot option "vt.global_cursor_default=0 vt.color=0xf0". softcursor_original needs to be initialized with -1. Signed-off-by: Melchior FRANZ Signed-off-by: Greg Kroah-Hartman --- drivers/tty/vt/vt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index bd51bdd0a7bf..3e3c7575e92d 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -568,7 +568,7 @@ static void delete_char(struct vc_data *vc, unsigned int nr) vc->vc_cols - vc->vc_x); } -static int softcursor_original; +static int softcursor_original = -1; static void add_softcursor(struct vc_data *vc) { -- cgit From 0e715d6fbd2a4a1dcd215d6d51091346e6a3d3fa Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:11 +0100 Subject: vxlan: cleanup types include/net/vxlan.h is a kernel header, no need to prefix fixed size types with double underscore. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- include/net/vxlan.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 0fb86442544b..5c64250619c5 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -30,15 +30,15 @@ * [0] https://tools.ietf.org/html/draft-smith-vxlan-group-policy */ struct vxlanhdr_gbp { - __u8 vx_flags; + u8 vx_flags; #ifdef __LITTLE_ENDIAN_BITFIELD - __u8 reserved_flags1:3, + u8 reserved_flags1:3, policy_applied:1, reserved_flags2:2, dont_learn:1, reserved_flags3:1; #elif defined(__BIG_ENDIAN_BITFIELD) - __u8 reserved_flags1:1, + u8 reserved_flags1:1, dont_learn:1, reserved_flags2:2, policy_applied:1, @@ -138,10 +138,10 @@ struct vxlan_config { int remote_ifindex; int mtu; __be16 dst_port; - __u16 port_min; - __u16 port_max; - __u8 tos; - __u8 ttl; + u16 port_min; + u16 port_max; + u8 tos; + u8 ttl; u32 flags; unsigned long age_interval; unsigned int addrmax; -- cgit From 427bc465bf9fcdab749f6997ff7a4eecaef4ca40 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:12 +0100 Subject: vxlan: remove duplicated macros VNI_HASH_BITS and VNI_HASH_SIZE are defined twice. Remove the extra definitions. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- include/net/vxlan.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 5c64250619c5..234bf1ef2737 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -9,9 +9,6 @@ #include #include -#define VNI_HASH_BITS 10 -#define VNI_HASH_SIZE (1< Date: Tue, 2 Feb 2016 18:09:13 +0100 Subject: vxlan: restructure vxlan.h definitions RCO and GBP are VXLAN extensions, not specified in RFC 7348. Because of that, they need to be explicitly enabled when creating vxlan interface. By default, those extensions are not used and plain VXLAN header is sent and received. Reflect this in vxlan.h: first, the plain VXLAN header is defined. Following it, RCO is documented and defined, and likewise for GBP. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- include/net/vxlan.h | 104 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 234bf1ef2737..25bd919c9ef0 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -9,14 +9,71 @@ #include #include +/* VXLAN protocol (RFC 7348) header: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |R|R|R|R|I|R|R|R| Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | VXLAN Network Identifier (VNI) | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * I = VXLAN Network Identifier (VNI) present. + */ +struct vxlanhdr { + __be32 vx_flags; + __be32 vx_vni; +}; + +/* VXLAN header flags. */ +#define VXLAN_HF_VNI BIT(27) + +#define VXLAN_N_VID (1u << 24) +#define VXLAN_VID_MASK (VXLAN_N_VID - 1) +#define VXLAN_VNI_MASK (VXLAN_VID_MASK << 8) +#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) + +#define VNI_HASH_BITS 10 +#define VNI_HASH_SIZE (1<mark mapping @@ -59,44 +119,6 @@ struct vxlanhdr_gbp { #define VXLAN_GBP_POLICY_APPLIED (BIT(3) << 16) #define VXLAN_GBP_ID_MASK (0xFFFF) -/* VXLAN protocol header: - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |G|R|R|R|I|R|R|C| Reserved | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | VXLAN Network Identifier (VNI) | Reserved | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * G = 1 Group Policy (VXLAN-GBP) - * I = 1 VXLAN Network Identifier (VNI) present - * C = 1 Remote checksum offload (RCO) - */ -struct vxlanhdr { - __be32 vx_flags; - __be32 vx_vni; -}; - -/* VXLAN header flags. */ -#define VXLAN_HF_RCO BIT(21) -#define VXLAN_HF_VNI BIT(27) -#define VXLAN_HF_GBP BIT(31) - -/* Remote checksum offload header option */ -#define VXLAN_RCO_MASK 0x7f /* Last byte of vni field */ -#define VXLAN_RCO_UDP 0x80 /* Indicate UDP RCO (TCP when not set *) */ -#define VXLAN_RCO_SHIFT 1 /* Left shift of start */ -#define VXLAN_RCO_SHIFT_MASK ((1 << VXLAN_RCO_SHIFT) - 1) -#define VXLAN_MAX_REMCSUM_START (VXLAN_RCO_MASK << VXLAN_RCO_SHIFT) - -#define VXLAN_N_VID (1u << 24) -#define VXLAN_VID_MASK (VXLAN_N_VID - 1) -#define VXLAN_VNI_MASK (VXLAN_VID_MASK << 8) -#define VXLAN_HLEN (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) - -#define VNI_HASH_BITS 10 -#define VNI_HASH_SIZE (1< Date: Tue, 2 Feb 2016 18:09:14 +0100 Subject: vxlan: consolidate output route calculation The code for output route lookup is duplicated for ndo_start_xmit and ndo_fill_metadata_dst. Move it to a common function. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 77 +++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 65439188c582..d0f7723fd776 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1847,6 +1847,27 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk return 0; } +static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, + struct sk_buff *skb, int oif, u8 tos, + __be32 daddr, __be32 *saddr) +{ + struct rtable *rt = NULL; + struct flowi4 fl4; + + memset(&fl4, 0, sizeof(fl4)); + fl4.flowi4_oif = oif; + fl4.flowi4_tos = RT_TOS(tos); + fl4.flowi4_mark = skb->mark; + fl4.flowi4_proto = IPPROTO_UDP; + fl4.daddr = daddr; + fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr; + + rt = ip_route_output_key(vxlan->net, &fl4); + if (!IS_ERR(rt)) + *saddr = fl4.saddr; + return rt; +} + #if IS_ENABLED(CONFIG_IPV6) static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan, struct sk_buff *skb, int oif, @@ -1928,7 +1949,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct sock *sk; struct rtable *rt = NULL; const struct iphdr *old_iph; - struct flowi4 fl4; union vxlan_addr *dst; union vxlan_addr remote_ip; struct vxlan_metadata _md; @@ -1995,6 +2015,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, } if (dst->sa.sa_family == AF_INET) { + __be32 saddr; + if (!vxlan->vn4_sock) goto drop; sk = vxlan->vn4_sock->sock->sk; @@ -2009,15 +2031,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, flags &= ~VXLAN_F_UDP_CSUM; } - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0; - fl4.flowi4_tos = RT_TOS(tos); - fl4.flowi4_mark = skb->mark; - fl4.flowi4_proto = IPPROTO_UDP; - fl4.daddr = dst->sin.sin_addr.s_addr; - fl4.saddr = vxlan->cfg.saddr.sin.sin_addr.s_addr; - - rt = ip_route_output_key(vxlan->net, &fl4); + rt = vxlan_get_route(vxlan, skb, + rdst ? rdst->remote_ifindex : 0, tos, + dst->sin.sin_addr.s_addr, &saddr); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to %pI4\n", &dst->sin.sin_addr.s_addr); @@ -2049,7 +2065,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - err = vxlan_xmit_skb(rt, sk, skb, fl4.saddr, + err = vxlan_xmit_skb(rt, sk, skb, saddr, dst->sin.sin_addr.s_addr, tos, ttl, df, src_port, dst_port, htonl(vni << 8), md, !net_eq(vxlan->net, dev_net(vxlan->dev)), @@ -2390,31 +2406,6 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb, - struct ip_tunnel_info *info, - __be16 sport, __be16 dport) -{ - struct vxlan_dev *vxlan = netdev_priv(dev); - struct rtable *rt; - struct flowi4 fl4; - - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_tos = RT_TOS(info->key.tos); - fl4.flowi4_mark = skb->mark; - fl4.flowi4_proto = IPPROTO_UDP; - fl4.daddr = info->key.u.ipv4.dst; - - rt = ip_route_output_key(vxlan->net, &fl4); - if (IS_ERR(rt)) - return PTR_ERR(rt); - ip_rt_put(rt); - - info->key.u.ipv4.src = fl4.saddr; - info->key.tp_src = sport; - info->key.tp_dst = dport; - return 0; -} - static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { struct vxlan_dev *vxlan = netdev_priv(dev); @@ -2426,9 +2417,16 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) dport = info->key.tp_dst ? : vxlan->cfg.dst_port; if (ip_tunnel_info_af(info) == AF_INET) { + struct rtable *rt; + if (!vxlan->vn4_sock) return -EINVAL; - return egress_ipv4_tun_info(dev, skb, info, sport, dport); + rt = vxlan_get_route(vxlan, skb, 0, info->key.tos, + info->key.u.ipv4.dst, + &info->key.u.ipv4.src); + if (IS_ERR(rt)) + return PTR_ERR(rt); + ip_rt_put(rt); } else { #if IS_ENABLED(CONFIG_IPV6) struct dst_entry *ndst; @@ -2441,13 +2439,12 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) if (IS_ERR(ndst)) return PTR_ERR(ndst); dst_release(ndst); - - info->key.tp_src = sport; - info->key.tp_dst = dport; #else /* !CONFIG_IPV6 */ return -EPFNOSUPPORT; #endif } + info->key.tp_src = sport; + info->key.tp_dst = dport; return 0; } -- cgit From b4ed5cad24c1072033efbffa680c84c9ba19c798 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:15 +0100 Subject: vxlan: consolidate csum flag handling The flag for tx checksumming for tunneling over IPv4 and IPv6 is different. Decide whether to do tx checksumming in vxlan_xmit_one and pass it on as a separate flag. This will allow for tx path consolidation in the next patch. Unfortunately, gcc is not clever enough to see that udp_sum is always initialized and gives an uninitialized variable warning. Set it to false to silence the warning. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d0f7723fd776..fe3fd4808f4d 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1690,12 +1690,13 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, struct net_device *dev, struct in6_addr *saddr, struct in6_addr *daddr, __u8 prio, __u8 ttl, __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags) + struct vxlan_metadata *md, bool xnet, u32 vxflags, + bool udp_sum) { struct vxlanhdr *vxh; int min_headroom; int err; - bool udp_sum = !(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX); + bool nocheck = !udp_sum; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; u16 hdrlen = sizeof(struct vxlanhdr); @@ -1763,8 +1764,7 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, skb_set_inner_protocol(skb, htons(ETH_P_TEB)); udp_tunnel6_xmit_skb(dst, sk, skb, dev, saddr, daddr, prio, - ttl, src_port, dst_port, - !!(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX)); + ttl, src_port, dst_port, nocheck); return 0; err: dst_release(dst); @@ -1775,12 +1775,13 @@ err: static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags) + struct vxlan_metadata *md, bool xnet, u32 vxflags, + bool udp_sum) { struct vxlanhdr *vxh; int min_headroom; int err; - bool udp_sum = !!(vxflags & VXLAN_F_UDP_CSUM); + bool nocheck = !udp_sum; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; u16 hdrlen = sizeof(struct vxlanhdr); @@ -1842,8 +1843,7 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk skb_set_inner_protocol(skb, htons(ETH_P_TEB)); udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df, - src_port, dst_port, xnet, - !(vxflags & VXLAN_F_UDP_CSUM)); + src_port, dst_port, xnet, nocheck); return 0; } @@ -1959,6 +1959,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, __u8 tos, ttl; int err; u32 flags = vxlan->flags; + bool udp_sum = false; info = skb_tunnel_info(skb); @@ -2007,6 +2008,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (info) { ttl = info->key.ttl; tos = info->key.tos; + udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); if (info->options_len) md = ip_tunnel_info_opts(info); @@ -2024,11 +2026,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, if (info) { if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) df = htons(IP_DF); - - if (info->key.tun_flags & TUNNEL_CSUM) - flags |= VXLAN_F_UDP_CSUM; - else - flags &= ~VXLAN_F_UDP_CSUM; + } else { + udp_sum = !!(flags & VXLAN_F_UDP_CSUM); } rt = vxlan_get_route(vxlan, skb, @@ -2069,7 +2068,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, dst->sin.sin_addr.s_addr, tos, ttl, df, src_port, dst_port, htonl(vni << 8), md, !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags); + flags, udp_sum); if (err < 0) { /* skb is already freed. */ skb = NULL; @@ -2119,18 +2118,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, return; } - if (info) { - if (info->key.tun_flags & TUNNEL_CSUM) - flags &= ~VXLAN_F_UDP_ZERO_CSUM6_TX; - else - flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; - } + if (!info) + udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); ttl = ttl ? : ip6_dst_hoplimit(ndst); err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr, 0, ttl, src_port, dst_port, htonl(vni << 8), md, !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags); + flags, udp_sum); #endif } -- cgit From f491e56dba511d318f52efa4c226471bf5943e88 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Tue, 2 Feb 2016 18:09:16 +0100 Subject: vxlan: consolidate vxlan_xmit_skb and vxlan6_xmit_skb There's a lot of code duplication. Factor out the duplicate code to a new function shared between IPv4 and IPv6 xmit path. Signed-off-by: Jiri Benc Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 137 ++++++++++------------------------------------------ 1 file changed, 26 insertions(+), 111 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index fe3fd4808f4d..65f52472a52c 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1684,19 +1684,14 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags, gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK); } -#if IS_ENABLED(CONFIG_IPV6) -static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, - struct sk_buff *skb, - struct net_device *dev, struct in6_addr *saddr, - struct in6_addr *daddr, __u8 prio, __u8 ttl, - __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags, +static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, + int iphdr_len, __be32 vni, + struct vxlan_metadata *md, u32 vxflags, bool udp_sum) { struct vxlanhdr *vxh; int min_headroom; int err; - bool nocheck = !udp_sum; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; u16 hdrlen = sizeof(struct vxlanhdr); @@ -1713,93 +1708,8 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk, } } - skb_scrub_packet(skb, xnet); - min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len - + VXLAN_HLEN + sizeof(struct ipv6hdr) - + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); - - /* Need space for new headers (invalidates iph ptr) */ - err = skb_cow_head(skb, min_headroom); - if (unlikely(err)) { - kfree_skb(skb); - goto err; - } - - skb = vlan_hwaccel_push_inside(skb); - if (WARN_ON(!skb)) { - err = -ENOMEM; - goto err; - } - - skb = iptunnel_handle_offloads(skb, udp_sum, type); - if (IS_ERR(skb)) { - err = -EINVAL; - goto err; - } - - vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); - vxh->vx_flags = htonl(VXLAN_HF_VNI); - vxh->vx_vni = vni; - - if (type & SKB_GSO_TUNNEL_REMCSUM) { - u32 data = (skb_checksum_start_offset(skb) - hdrlen) >> - VXLAN_RCO_SHIFT; - - if (skb->csum_offset == offsetof(struct udphdr, check)) - data |= VXLAN_RCO_UDP; - - vxh->vx_vni |= htonl(data); - vxh->vx_flags |= htonl(VXLAN_HF_RCO); - - if (!skb_is_gso(skb)) { - skb->ip_summed = CHECKSUM_NONE; - skb->encapsulation = 0; - } - } - - if (vxflags & VXLAN_F_GBP) - vxlan_build_gbp_hdr(vxh, vxflags, md); - - skb_set_inner_protocol(skb, htons(ETH_P_TEB)); - - udp_tunnel6_xmit_skb(dst, sk, skb, dev, saddr, daddr, prio, - ttl, src_port, dst_port, nocheck); - return 0; -err: - dst_release(dst); - return err; -} -#endif - -static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, - __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df, - __be16 src_port, __be16 dst_port, __be32 vni, - struct vxlan_metadata *md, bool xnet, u32 vxflags, - bool udp_sum) -{ - struct vxlanhdr *vxh; - int min_headroom; - int err; - bool nocheck = !udp_sum; - int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; - u16 hdrlen = sizeof(struct vxlanhdr); - - if ((vxflags & VXLAN_F_REMCSUM_TX) && - skb->ip_summed == CHECKSUM_PARTIAL) { - int csum_start = skb_checksum_start_offset(skb); - - if (csum_start <= VXLAN_MAX_REMCSUM_START && - !(csum_start & VXLAN_RCO_SHIFT_MASK) && - (skb->csum_offset == offsetof(struct udphdr, check) || - skb->csum_offset == offsetof(struct tcphdr, check))) { - udp_sum = false; - type |= SKB_GSO_TUNNEL_REMCSUM; - } - } - - min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len - + VXLAN_HLEN + sizeof(struct iphdr) + + VXLAN_HLEN + iphdr_len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); /* Need space for new headers (invalidates iph ptr) */ @@ -1841,9 +1751,6 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk vxlan_build_gbp_hdr(vxh, vxflags, md); skb_set_inner_protocol(skb, htons(ETH_P_TEB)); - - udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df, - src_port, dst_port, xnet, nocheck); return 0; } @@ -1960,6 +1867,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, int err; u32 flags = vxlan->flags; bool udp_sum = false; + bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); info = skb_tunnel_info(skb); @@ -2064,16 +1972,14 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); - err = vxlan_xmit_skb(rt, sk, skb, saddr, - dst->sin.sin_addr.s_addr, tos, ttl, df, - src_port, dst_port, htonl(vni << 8), md, - !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags, udp_sum); - if (err < 0) { - /* skb is already freed. */ - skb = NULL; - goto rt_tx_error; - } + err = vxlan_build_skb(skb, &rt->dst, sizeof(struct iphdr), + htonl(vni << 8), md, flags, udp_sum); + if (err < 0) + goto xmit_tx_error; + + udp_tunnel_xmit_skb(rt, sk, skb, saddr, + dst->sin.sin_addr.s_addr, tos, ttl, df, + src_port, dst_port, xnet, !udp_sum); #if IS_ENABLED(CONFIG_IPV6) } else { struct dst_entry *ndst; @@ -2122,10 +2028,16 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); ttl = ttl ? : ip6_dst_hoplimit(ndst); - err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr, - 0, ttl, src_port, dst_port, htonl(vni << 8), md, - !net_eq(vxlan->net, dev_net(vxlan->dev)), - flags, udp_sum); + skb_scrub_packet(skb, xnet); + err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), + htonl(vni << 8), md, flags, udp_sum); + if (err < 0) { + dst_release(ndst); + return; + } + udp_tunnel6_xmit_skb(ndst, sk, skb, dev, + &saddr, &dst->sin6.sin6_addr, + 0, ttl, src_port, dst_port, !udp_sum); #endif } @@ -2135,6 +2047,9 @@ drop: dev->stats.tx_dropped++; goto tx_free; +xmit_tx_error: + /* skb is already freed. */ + skb = NULL; rt_tx_error: ip_rt_put(rt); tx_error: -- cgit From a5a773a54e59538d03fd1a20facd7214c030b1d3 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 3 Feb 2016 09:49:16 +0530 Subject: be2net: return error status from be_set_phys_id() be_set_phys_id() returns 0 to ethtool when the command fails in the FW. This patch fixes the set_phys_id() to return -EIO in case the FW cmd fails. Signed-off-by: Suresh Reddy Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_ethtool.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index a19ac441336f..2ff691636dac 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -720,29 +720,32 @@ static int be_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { struct be_adapter *adapter = netdev_priv(netdev); + int status = 0; switch (state) { case ETHTOOL_ID_ACTIVE: - be_cmd_get_beacon_state(adapter, adapter->hba_port_num, - &adapter->beacon_state); - return 1; /* cycle on/off once per second */ + status = be_cmd_get_beacon_state(adapter, adapter->hba_port_num, + &adapter->beacon_state); + if (status) + return be_cmd_status(status); + return 1; /* cycle on/off once per second */ case ETHTOOL_ID_ON: - be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - BEACON_STATE_ENABLED); + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, + 0, 0, BEACON_STATE_ENABLED); break; case ETHTOOL_ID_OFF: - be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - BEACON_STATE_DISABLED); + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, + 0, 0, BEACON_STATE_DISABLED); break; case ETHTOOL_ID_INACTIVE: - be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0, - adapter->beacon_state); + status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, + 0, 0, adapter->beacon_state); } - return 0; + return be_cmd_status(status); } static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump) -- cgit From fa5c867d4df275a2c11a455043848574e80a8b32 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 3 Feb 2016 09:49:17 +0530 Subject: be2net: check for INSUFFICIENT_PRIVILEGES error The driver currently logs the message "VF is not privileged to issue opcode" by checking only the base_status field for UNAUTHORIZED_REQUEST. Add check to look for INSUFFICIENT_PRIVILEGES in the additional status field also as not all cmds fail with that base status. Signed-off-by: Suresh Reddy Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 3 ++- drivers/net/ethernet/emulex/benet/be_cmds.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index b63d8ad2e115..3b665f16d2aa 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -236,7 +236,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, if (base_status != MCC_STATUS_SUCCESS && !be_skip_err_log(opcode, base_status, addl_status)) { - if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { + if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST || + addl_status == MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES) { dev_warn(&adapter->pdev->dev, "VF is not privileged to issue opcode %d-%d\n", opcode, subsystem); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 241819b36ca7..f260ef3329a1 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -68,7 +68,8 @@ enum mcc_addl_status { MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a, MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab, MCC_ADDL_STATUS_INVALID_SIGNATURE = 0x56, - MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57 + MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57, + MCC_ADDL_STATUS_INSUFFICIENT_PRIVILEGES = 0x60 }; #define CQE_BASE_STATUS_MASK 0xFFFF -- cgit From 41dcdfbd0944a3ef08224a8c9ba3b2fdeae0dd86 Mon Sep 17 00:00:00 2001 From: Sriharsha Basavapatna Date: Wed, 3 Feb 2016 09:49:18 +0530 Subject: be2net: Fix be_vlan_rem_vid() to check vlan id being removed The driver decrements its vlan count without checking if it is really present in its list. This results in an invalid vlan count and impacts subsequent vlan add/rem ops. The function be_vlan_rem_vid() should be updated to fix this. Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index f99de3657ce3..09e6f2cdfc90 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1463,6 +1463,9 @@ static int be_vlan_rem_vid(struct net_device *netdev, __be16 proto, u16 vid) if (lancer_chip(adapter) && vid == 0) return 0; + if (!test_bit(vid, adapter->vids)) + return 0; + clear_bit(vid, adapter->vids); adapter->vlans_added--; -- cgit From ee9ad2802449c0a6811a74af2ce30500895d137b Mon Sep 17 00:00:00 2001 From: Sriharsha Basavapatna Date: Wed, 3 Feb 2016 09:49:19 +0530 Subject: be2net: SRIOV Queue distribution should factor in EQ-count of VFs The SRIOV resource distribution logic for RX/TX queue counts is not optimal when a small number of VFs are enabled. It does not take into account the VF's EQ count while computing the queue counts. Because of this, the VF gets a large number of queues, though it doesn't have sufficient EQs, resulting in wasted queue resources. And the PF gets a smaller share of queues though it has more EQs. Fix this by capping the VF queue count at its EQ count. Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 4 ++++ drivers/net/ethernet/emulex/benet/be_main.c | 15 ++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index cf837831304b..de88c30bc029 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -89,6 +89,10 @@ #define BE3_MAX_TX_QS 16 #define BE3_MAX_EVT_QS 16 #define BE3_SRIOV_MAX_EVT_QS 8 +#define SH_VF_MAX_NIC_EQS 3 /* Skyhawk VFs can have a max of 4 EQs + * and at least 1 is granted to either + * SURF/DPDK + */ #define MAX_RSS_IFACES 15 #define MAX_RX_QS 32 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 09e6f2cdfc90..62f6fbb8b0f1 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3792,18 +3792,15 @@ static u16 be_calculate_vf_qs(struct be_adapter *adapter, u16 num_vfs) struct be_resources res = adapter->pool_res; u16 num_vf_qs = 1; - /* Distribute the queue resources equally among the PF and it's VFs + /* Distribute the queue resources among the PF and it's VFs * Do not distribute queue resources in multi-channel configuration. */ if (num_vfs && !be_is_mc(adapter)) { - /* If number of VFs requested is 8 less than max supported, - * assign 8 queue pairs to the PF and divide the remaining - * resources evenly among the VFs - */ - if (num_vfs < (be_max_vfs(adapter) - 8)) - num_vf_qs = (res.max_rss_qs - 8) / num_vfs; - else - num_vf_qs = res.max_rss_qs / num_vfs; + /* Divide the qpairs evenly among the VFs and the PF, capped + * at VF-EQ-count. Any remainder qpairs belong to the PF. + */ + num_vf_qs = min(SH_VF_MAX_NIC_EQS, + res.max_rss_qs / (num_vfs + 1)); /* Skyhawk-R chip supports only MAX_RSS_IFACES RSS capable * interfaces per port. Provide RSS on VFs, only if number -- cgit From 2e365b1b80aa98655a5582dbb9bf6cf8c0ff268c Mon Sep 17 00:00:00 2001 From: Somnath Kotur Date: Wed, 3 Feb 2016 09:49:20 +0530 Subject: be2net: Don't run ethtool self-tests for VFs The CMD_SUBSYSTEM_LOWLEVEL cmds need DEV_CFG Privilege to run which VFs don't have by default. Self-tests need to be issued only for PFs. Signed-off-by: Somnath Kotur Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 3b665f16d2aa..7d51d4733890 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -65,7 +65,22 @@ static struct be_cmd_priv_map cmd_priv_map[] = { CMD_SUBSYSTEM_COMMON, BE_PRIV_LNKMGMT | BE_PRIV_VHADM | BE_PRIV_DEVCFG | BE_PRIV_DEVSEC - } + }, + { + OPCODE_LOWLEVEL_HOST_DDR_DMA, + CMD_SUBSYSTEM_LOWLEVEL, + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_LOWLEVEL_LOOPBACK_TEST, + CMD_SUBSYSTEM_LOWLEVEL, + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, + CMD_SUBSYSTEM_LOWLEVEL, + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, }; static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, u8 subsystem) @@ -3169,6 +3184,10 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, struct be_cmd_req_set_lmode *req; int status; + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_SET_LOOPBACK_MODE, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -3214,6 +3233,10 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, struct be_cmd_resp_loopback_test *resp; int status; + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_LOOPBACK_TEST, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -3260,6 +3283,10 @@ int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern, int status; int i, j = 0; + if (!be_cmd_allowed(adapter, OPCODE_LOWLEVEL_HOST_DDR_DMA, + CMD_SUBSYSTEM_LOWLEVEL)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); -- cgit From 1babbad46f4aba1c242e43e27c5b36a62311b2d4 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Wed, 3 Feb 2016 09:49:21 +0530 Subject: be2net: Fix Lancer error recovery After error is detected, wait for adapter to move to ready state before destroying queues and cleanup of other resources. Also skip performing any cleanup for non-Lancer chips and move debug messages to correct routine. Signed-off-by: Padmanabh Ratnakar Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 51 +++++++++++++++++++---------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 62f6fbb8b0f1..6eb3aba832fc 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4859,21 +4859,27 @@ static int be_resume(struct be_adapter *adapter) static int be_err_recover(struct be_adapter *adapter) { - struct device *dev = &adapter->pdev->dev; int status; + /* Error recovery is supported only Lancer as of now */ + if (!lancer_chip(adapter)) + return -EIO; + + /* Wait for adapter to reach quiescent state before + * destroying queues + */ + status = be_fw_wait_ready(adapter); + if (status) + goto err; + + be_cleanup(adapter); + status = be_resume(adapter); if (status) goto err; - dev_info(dev, "Adapter recovery successful\n"); return 0; err: - if (be_physfn(adapter)) - dev_err(dev, "Adapter recovery failed\n"); - else - dev_err(dev, "Re-trying adapter recovery\n"); - return status; } @@ -4882,21 +4888,32 @@ static void be_err_detection_task(struct work_struct *work) struct be_adapter *adapter = container_of(work, struct be_adapter, be_err_detection_work.work); - int status = 0; + struct device *dev = &adapter->pdev->dev; + int recovery_status; be_detect_error(adapter); - if (be_check_error(adapter, BE_ERROR_HW)) { - be_cleanup(adapter); - - /* As of now error recovery support is in Lancer only */ - if (lancer_chip(adapter)) - status = be_err_recover(adapter); + if (be_check_error(adapter, BE_ERROR_HW)) + recovery_status = be_err_recover(adapter); + else + goto reschedule_task; + + if (!recovery_status) { + dev_info(dev, "Adapter recovery successful\n"); + goto reschedule_task; + } else if (be_virtfn(adapter)) { + /* For VFs, check if PF have allocated resources + * every second. + */ + dev_err(dev, "Re-trying adapter recovery\n"); + goto reschedule_task; + } else { + dev_err(dev, "Adapter recovery failed\n"); } - /* Always attempt recovery on VFs */ - if (!status || be_virtfn(adapter)) - be_schedule_err_detection(adapter); + return; +reschedule_task: + be_schedule_err_detection(adapter); } static void be_log_sfp_info(struct be_adapter *adapter) -- cgit From 972f37b424e65f9ef1ce143b8658d9ed50db9f42 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Wed, 3 Feb 2016 09:49:22 +0530 Subject: be2net: Add retry in case of error recovery failure Retry error recovery MAX_ERR_RECOVERY_RETRY_COUNT times in case of failure during error recovery. Signed-off-by: Padmanabh Ratnakar Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 5 +++++ drivers/net/ethernet/emulex/benet/be_main.c | 23 +++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index de88c30bc029..515e206589cc 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -397,6 +397,10 @@ enum vf_state { #define BE_UC_PMAC_COUNT 30 #define BE_VF_UC_PMAC_COUNT 2 +#define MAX_ERR_RECOVERY_RETRY_COUNT 3 +#define ERR_DETECTION_DELAY 1000 +#define ERR_RECOVERY_RETRY_DELAY 30000 + /* Ethtool set_dump flags */ #define LANCER_INITIATE_FW_DUMP 0x1 #define LANCER_DELETE_FW_DUMP 0x2 @@ -534,6 +538,7 @@ struct be_adapter { u16 work_counter; struct delayed_work be_err_detection_work; + u8 recovery_retries; u8 err_flags; u32 flags; u32 cmd_privileges; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 6eb3aba832fc..d5286d3c9356 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4265,10 +4265,10 @@ static void be_schedule_worker(struct be_adapter *adapter) adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; } -static void be_schedule_err_detection(struct be_adapter *adapter) +static void be_schedule_err_detection(struct be_adapter *adapter, u32 delay) { schedule_delayed_work(&adapter->be_err_detection_work, - msecs_to_jiffies(1000)); + msecs_to_jiffies(delay)); adapter->flags |= BE_FLAGS_ERR_DETECTION_SCHEDULED; } @@ -4890,6 +4890,7 @@ static void be_err_detection_task(struct work_struct *work) be_err_detection_work.work); struct device *dev = &adapter->pdev->dev; int recovery_status; + int delay = ERR_DETECTION_DELAY; be_detect_error(adapter); @@ -4899,6 +4900,7 @@ static void be_err_detection_task(struct work_struct *work) goto reschedule_task; if (!recovery_status) { + adapter->recovery_retries = 0; dev_info(dev, "Adapter recovery successful\n"); goto reschedule_task; } else if (be_virtfn(adapter)) { @@ -4907,13 +4909,22 @@ static void be_err_detection_task(struct work_struct *work) */ dev_err(dev, "Re-trying adapter recovery\n"); goto reschedule_task; + } else if (adapter->recovery_retries++ < + MAX_ERR_RECOVERY_RETRY_COUNT) { + /* In case of another error during recovery, it takes 30 sec + * for adapter to come out of error. Retry error recovery after + * this time interval. + */ + dev_err(&adapter->pdev->dev, "Re-trying adapter recovery\n"); + delay = ERR_RECOVERY_RETRY_DELAY; + goto reschedule_task; } else { dev_err(dev, "Adapter recovery failed\n"); } return; reschedule_task: - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, delay); } static void be_log_sfp_info(struct be_adapter *adapter) @@ -5309,7 +5320,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) be_roce_dev_add(adapter); - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); /* On Die temperature not supported for VF. */ if (be_physfn(adapter) && IS_ENABLED(CONFIG_BE2NET_HWMON)) { @@ -5376,7 +5387,7 @@ static int be_pci_resume(struct pci_dev *pdev) if (status) return status; - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); if (adapter->wol_en) be_setup_wol(adapter, false); @@ -5476,7 +5487,7 @@ static void be_eeh_resume(struct pci_dev *pdev) if (status) goto err; - be_schedule_err_detection(adapter); + be_schedule_err_detection(adapter, ERR_DETECTION_DELAY); return; err: dev_err(&adapter->pdev->dev, "EEH resume failed\n"); -- cgit From 3c0d49aaa67e1990f4c081892e9bb69070853919 Mon Sep 17 00:00:00 2001 From: Padmanabh Ratnakar Date: Wed, 3 Feb 2016 09:49:23 +0530 Subject: be2net: Fix interval calculation in interrupt moderation Interrupt moderation parameters need to be recalculated only after a time interval of 1 ms. Interval calculation is wrong when there is a rollover of jiffies. Using recommended way of interval calculation using jiffies to fix this. Signed-off-by: Padmanabh Ratnakar Signed-off-by: Sriharsha Basavapatna Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index d5286d3c9356..9c1fc9dcea25 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -1917,8 +1917,7 @@ static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo) if (!aic->enable) return 0; - if (time_before_eq(now, aic->jiffies) || - jiffies_to_msecs(now - aic->jiffies) < 1) + if (jiffies_to_msecs(now - aic->jiffies) < 1) eqd = aic->prev_eqd; else eqd = be_get_new_eqd(eqo); -- cgit From 22fae97d863679994b951799dd4bbe7afd95897b Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Tue, 2 Feb 2016 11:55:05 +0000 Subject: xen-netback: implement dynamic multicast control My recent patch to the Xen Project documents a protocol for 'dynamic multicast control' in netif.h. This extends the previous multicast control protocol to not require a shared ring reconnection to turn the feature off. Instead the backend watches the "request-multicast-control" key in xenstore and turns the feature off if the key value is written to zero. This patch adds support for dynamic multicast control in xen-netback. Signed-off-by: Paul Durrant Cc: Ian Campbell Cc: Wei Liu Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/xenbus.c | 89 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 0333ab0fd926..112825200d41 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -251,6 +251,7 @@ struct xenvif { unsigned int stalled_queues; struct xenbus_watch credit_watch; + struct xenbus_watch mcast_ctrl_watch; spinlock_t lock; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 56ebd8267386..39a303de20dd 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -327,7 +327,7 @@ static int netback_probe(struct xenbus_device *dev, goto abort_transaction; } - /* We support multicast-control. */ + /* We support dynamic multicast-control. */ err = xenbus_printf(xbt, dev->nodename, "feature-multicast-control", "%d", 1); if (err) { @@ -335,6 +335,14 @@ static int netback_probe(struct xenbus_device *dev, goto abort_transaction; } + err = xenbus_printf(xbt, dev->nodename, + "feature-dynamic-multicast-control", + "%d", 1); + if (err) { + message = "writing feature-dynamic-multicast-control"; + goto abort_transaction; + } + err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); @@ -683,7 +691,8 @@ static void xen_net_rate_changed(struct xenbus_watch *watch, } } -static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) +static int xen_register_credit_watch(struct xenbus_device *dev, + struct xenvif *vif) { int err = 0; char *node; @@ -708,7 +717,7 @@ static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) return err; } -static void xen_unregister_watchers(struct xenvif *vif) +static void xen_unregister_credit_watch(struct xenvif *vif) { if (vif->credit_watch.node) { unregister_xenbus_watch(&vif->credit_watch); @@ -717,6 +726,75 @@ static void xen_unregister_watchers(struct xenvif *vif) } } +static void xen_mcast_ctrl_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + struct xenvif *vif = container_of(watch, struct xenvif, + mcast_ctrl_watch); + struct xenbus_device *dev = xenvif_to_xenbus_device(vif); + int val; + + if (xenbus_scanf(XBT_NIL, dev->otherend, + "request-multicast-control", "%d", &val) < 0) + val = 0; + vif->multicast_control = !!val; +} + +static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev, + struct xenvif *vif) +{ + int err = 0; + char *node; + unsigned maxlen = strlen(dev->otherend) + + sizeof("/request-multicast-control"); + + if (vif->mcast_ctrl_watch.node) { + pr_err_ratelimited("Watch is already registered\n"); + return -EADDRINUSE; + } + + node = kmalloc(maxlen, GFP_KERNEL); + if (!node) { + pr_err("Failed to allocate memory for watch\n"); + return -ENOMEM; + } + snprintf(node, maxlen, "%s/request-multicast-control", + dev->otherend); + vif->mcast_ctrl_watch.node = node; + vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed; + err = register_xenbus_watch(&vif->mcast_ctrl_watch); + if (err) { + pr_err("Failed to set watcher %s\n", + vif->mcast_ctrl_watch.node); + kfree(node); + vif->mcast_ctrl_watch.node = NULL; + vif->mcast_ctrl_watch.callback = NULL; + } + return err; +} + +static void xen_unregister_mcast_ctrl_watch(struct xenvif *vif) +{ + if (vif->mcast_ctrl_watch.node) { + unregister_xenbus_watch(&vif->mcast_ctrl_watch); + kfree(vif->mcast_ctrl_watch.node); + vif->mcast_ctrl_watch.node = NULL; + } +} + +static void xen_register_watchers(struct xenbus_device *dev, + struct xenvif *vif) +{ + xen_register_credit_watch(dev, vif); + xen_register_mcast_ctrl_watch(dev, vif); +} + +static void xen_unregister_watchers(struct xenvif *vif) +{ + xen_unregister_mcast_ctrl_watch(vif); + xen_unregister_credit_watch(vif); +} + static void unregister_hotplug_status_watch(struct backend_info *be) { if (be->have_hotplug_status_watch) { @@ -1030,11 +1108,6 @@ static int read_xenbus_vif_flags(struct backend_info *be) val = 0; vif->ipv6_csum = !!val; - if (xenbus_scanf(XBT_NIL, dev->otherend, "request-multicast-control", - "%d", &val) < 0) - val = 0; - vif->multicast_control = !!val; - return 0; } -- cgit From 67eb03318bc5fe170ae832423fda7a23b0d801cf Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Feb 2016 07:43:45 -0800 Subject: net: Add support for fill_slave_info to VRF device Allows userspace to have direct access to VRF table association versus looking up master device and its table. Signed-off-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 21 +++++++++++++++++++++ include/uapi/linux/if_link.h | 8 ++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 66addb7a7911..76e1fc9d8748 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -877,6 +877,24 @@ static int vrf_fillinfo(struct sk_buff *skb, return nla_put_u32(skb, IFLA_VRF_TABLE, vrf->tb_id); } +static size_t vrf_get_slave_size(const struct net_device *bond_dev, + const struct net_device *slave_dev) +{ + return nla_total_size(sizeof(u32)); /* IFLA_VRF_PORT_TABLE */ +} + +static int vrf_fill_slave_info(struct sk_buff *skb, + const struct net_device *vrf_dev, + const struct net_device *slave_dev) +{ + struct net_vrf *vrf = netdev_priv(vrf_dev); + + if (nla_put_u32(skb, IFLA_VRF_PORT_TABLE, vrf->tb_id)) + return -EMSGSIZE; + + return 0; +} + static const struct nla_policy vrf_nl_policy[IFLA_VRF_MAX + 1] = { [IFLA_VRF_TABLE] = { .type = NLA_U32 }, }; @@ -890,6 +908,9 @@ static struct rtnl_link_ops vrf_link_ops __read_mostly = { .validate = vrf_validate, .fill_info = vrf_fillinfo, + .get_slave_size = vrf_get_slave_size, + .fill_slave_info = vrf_fill_slave_info, + .newlink = vrf_newlink, .dellink = vrf_dellink, .setup = vrf_setup, diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index d3e90b91e07e..d452cea59020 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -405,6 +405,14 @@ enum { #define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) +enum { + IFLA_VRF_PORT_UNSPEC, + IFLA_VRF_PORT_TABLE, + __IFLA_VRF_PORT_MAX +}; + +#define IFLA_VRF_PORT_MAX (__IFLA_VRF_PORT_MAX - 1) + /* IPVLAN section */ enum { IFLA_IPVLAN_UNSPEC, -- cgit From 3575dbf2cbbc8e598f17ec441aed526dbea0e1bd Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 2 Feb 2016 18:17:54 +0100 Subject: net: drop write-only stack variable Remove a write-only stack variable from unix_attach_fds(). This is a left-over from the security fix in: commit 712f4aad406bb1ed67f3f98d04c044191f0ff593 Author: willy tarreau Date: Sun Jan 10 07:54:56 2016 +0100 unix: properly account for FDs passed over unix sockets Signed-off-by: David Herrmann Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/unix/af_unix.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 49d5093eb055..b3745557fc89 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1534,7 +1534,6 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) { int i; unsigned char max_level = 0; - int unix_sock_count = 0; if (too_many_unix_fds(current)) return -ETOOMANYREFS; @@ -1542,11 +1541,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) for (i = scm->fp->count - 1; i >= 0; i--) { struct sock *sk = unix_get_socket(scm->fp->fp[i]); - if (sk) { - unix_sock_count++; + if (sk) max_level = max(max_level, unix_sk(sk)->recursion_level); - } } if (unlikely(max_level > MAX_RECURSION_LEVEL)) return -ETOOMANYREFS; -- cgit From e662ca40de846e0a2be6326a7c4668326ddb194c Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 2 Feb 2016 10:33:04 -0800 Subject: tcp: retransmit after recovery processing and congestion control The retransmission and F-RTO transmission currently happen inside recovery state processing (tcp_fastretrans_alert) but before congestion control. This refactoring moves the logic after both s.t. we can determine how much to send (cwnd) before deciding what to send. Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 58 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8194a250a01e..84a4ab9c05d1 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -126,6 +126,10 @@ int sysctl_tcp_invalid_ratelimit __read_mostly = HZ/2; #define TCP_REMNANT (TCP_FLAG_FIN|TCP_FLAG_URG|TCP_FLAG_SYN|TCP_FLAG_PSH) #define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH)) +#define REXMIT_NONE 0 /* no loss recovery to do */ +#define REXMIT_LOST 1 /* retransmit packets marked lost */ +#define REXMIT_NEW 2 /* FRTO-style transmit of unsent/new packets */ + /* Adapt the MSS value used to make delayed ack decision to the * real world. */ @@ -2662,7 +2666,8 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) /* Process an ACK in CA_Loss state. Move to CA_Open if lost data are * recovered or spurious. Otherwise retransmits more on partial ACKs. */ -static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) +static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack, + int *rexmit) { struct tcp_sock *tp = tcp_sk(sk); bool recovered = !before(tp->snd_una, tp->high_seq); @@ -2684,10 +2689,15 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) tp->frto = 0; /* Step 3.a. loss was real */ } else if (flag & FLAG_SND_UNA_ADVANCED && !recovered) { tp->high_seq = tp->snd_nxt; - __tcp_push_pending_frames(sk, tcp_current_mss(sk), - TCP_NAGLE_OFF); - if (after(tp->snd_nxt, tp->high_seq)) - return; /* Step 2.b */ + /* Step 2.b. Try send new data (but deferred until cwnd + * is updated in tcp_ack()). Otherwise fall back to + * the conventional recovery. + */ + if (tcp_send_head(sk) && + after(tcp_wnd_end(tp), tp->snd_nxt)) { + *rexmit = REXMIT_NEW; + return; + } tp->frto = 0; } } @@ -2706,7 +2716,7 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) else if (flag & FLAG_SND_UNA_ADVANCED) tcp_reset_reno_sack(tp); } - tcp_xmit_retransmit_queue(sk); + *rexmit = REXMIT_LOST; } /* Undo during fast recovery after partial ACK. */ @@ -2756,7 +2766,7 @@ static bool tcp_try_undo_partial(struct sock *sk, const int acked, */ static void tcp_fastretrans_alert(struct sock *sk, const int acked, const int prior_unsacked, - bool is_dupack, int flag) + bool is_dupack, int flag, int *rexmit) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); @@ -2831,7 +2841,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, } break; case TCP_CA_Loss: - tcp_process_loss(sk, flag, is_dupack); + tcp_process_loss(sk, flag, is_dupack, rexmit); if (icsk->icsk_ca_state != TCP_CA_Open && !(flag & FLAG_LOST_RETRANS)) return; @@ -2871,7 +2881,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, if (do_lost) tcp_update_scoreboard(sk, fast_rexmit); tcp_cwnd_reduction(sk, prior_unsacked, fast_rexmit, flag); - tcp_xmit_retransmit_queue(sk); + *rexmit = REXMIT_LOST; } /* Kathleen Nichols' algorithm for tracking the minimum value of @@ -3506,6 +3516,27 @@ static inline void tcp_in_ack_event(struct sock *sk, u32 flags) icsk->icsk_ca_ops->in_ack_event(sk, flags); } +/* Congestion control has updated the cwnd already. So if we're in + * loss recovery then now we do any new sends (for FRTO) or + * retransmits (for CA_Loss or CA_recovery) that make sense. + */ +static void tcp_xmit_recovery(struct sock *sk, int rexmit) +{ + struct tcp_sock *tp = tcp_sk(sk); + + if (rexmit == REXMIT_NONE) + return; + + if (unlikely(rexmit == 2)) { + __tcp_push_pending_frames(sk, tcp_current_mss(sk), + TCP_NAGLE_OFF); + if (after(tp->snd_nxt, tp->high_seq)) + return; + tp->frto = 0; + } + tcp_xmit_retransmit_queue(sk); +} + /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) { @@ -3520,6 +3551,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets = tp->packets_out; const int prior_unsacked = tp->packets_out - tp->sacked_out; int acked = 0; /* Number of packets newly acked */ + int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */ sack_state.first_sackt.v64 = 0; @@ -3616,7 +3648,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (tcp_ack_is_dubious(sk, flag)) { is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); tcp_fastretrans_alert(sk, acked, prior_unsacked, - is_dupack, flag); + is_dupack, flag, &rexmit); } if (tp->tlp_high_seq) tcp_process_tlp_ack(sk, ack, flag); @@ -3634,13 +3666,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (icsk->icsk_pending == ICSK_TIME_RETRANS) tcp_schedule_loss_probe(sk); tcp_update_pacing_rate(sk); + tcp_xmit_recovery(sk, rexmit); return 1; no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) tcp_fastretrans_alert(sk, acked, prior_unsacked, - is_dupack, flag); + is_dupack, flag, &rexmit); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than * it needs to be for normal retransmission. @@ -3664,7 +3697,8 @@ old_ack: flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, &sack_state); tcp_fastretrans_alert(sk, acked, prior_unsacked, - is_dupack, flag); + is_dupack, flag, &rexmit); + tcp_xmit_recovery(sk, rexmit); } SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt); -- cgit From 31ba0c10723e9eba378f96de1d1a9426129949e1 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 2 Feb 2016 10:33:05 -0800 Subject: tcp: move cwnd reduction after recovery state procesing Currently the cwnd is reduced and increased in various different places. The reduction happens in various places in the recovery state processing (tcp_fastretrans_alert) while the increase happens afterward. A better sequence is to identify lost packets and update the congestion control state (icsk_ca_state) first. Then base on the new state, up/down the cwnd in one central place. It's more clear to reason cwnd changes. Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 60 ++++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 84a4ab9c05d1..dc810df53e90 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2471,14 +2471,12 @@ static void tcp_init_cwnd_reduction(struct sock *sk) tcp_ecn_queue_cwr(tp); } -static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, - int fast_rexmit, int flag) +static void tcp_cwnd_reduction(struct sock *sk, int newly_acked_sacked, + int flag) { struct tcp_sock *tp = tcp_sk(sk); int sndcnt = 0; int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp); - int newly_acked_sacked = prior_unsacked - - (tp->packets_out - tp->sacked_out); if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd)) return; @@ -2496,7 +2494,8 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked, } else { sndcnt = min(delta, newly_acked_sacked); } - sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0)); + /* Force a fast retransmit upon entering fast recovery */ + sndcnt = max(sndcnt, (tp->prr_out ? 0 : 1)); tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt; } @@ -2541,7 +2540,7 @@ static void tcp_try_keep_open(struct sock *sk) } } -static void tcp_try_to_open(struct sock *sk, int flag, const int prior_unsacked) +static void tcp_try_to_open(struct sock *sk, int flag) { struct tcp_sock *tp = tcp_sk(sk); @@ -2555,8 +2554,6 @@ static void tcp_try_to_open(struct sock *sk, int flag, const int prior_unsacked) if (inet_csk(sk)->icsk_ca_state != TCP_CA_CWR) { tcp_try_keep_open(sk); - } else { - tcp_cwnd_reduction(sk, prior_unsacked, 0, flag); } } @@ -2720,8 +2717,7 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack, } /* Undo during fast recovery after partial ACK. */ -static bool tcp_try_undo_partial(struct sock *sk, const int acked, - const int prior_unsacked, int flag) +static bool tcp_try_undo_partial(struct sock *sk, const int acked) { struct tcp_sock *tp = tcp_sk(sk); @@ -2736,10 +2732,8 @@ static bool tcp_try_undo_partial(struct sock *sk, const int acked, * can undo. Otherwise we clock out new packets but do not * mark more packets lost or retransmit more. */ - if (tp->retrans_out) { - tcp_cwnd_reduction(sk, prior_unsacked, 0, flag); + if (tp->retrans_out) return true; - } if (!tcp_any_retrans_done(sk)) tp->retrans_stamp = 0; @@ -2758,21 +2752,21 @@ static bool tcp_try_undo_partial(struct sock *sk, const int acked, * taking into account both packets sitting in receiver's buffer and * packets lost by network. * - * Besides that it does CWND reduction, when packet loss is detected - * and changes state of machine. + * Besides that it updates the congestion state when packet loss or ECN + * is detected. But it does not reduce the cwnd, it is done by the + * congestion control later. * * It does _not_ decide what to send, it is made in function * tcp_xmit_retransmit_queue(). */ static void tcp_fastretrans_alert(struct sock *sk, const int acked, - const int prior_unsacked, - bool is_dupack, int flag, int *rexmit) + bool is_dupack, int *ack_flag, int *rexmit) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); + int fast_rexmit = 0, flag = *ack_flag; bool do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); - int fast_rexmit = 0; if (WARN_ON(!tp->packets_out && tp->sacked_out)) tp->sacked_out = 0; @@ -2819,8 +2813,10 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, /* Use RACK to detect loss */ if (sysctl_tcp_recovery & TCP_RACK_LOST_RETRANS && - tcp_rack_mark_lost(sk)) + tcp_rack_mark_lost(sk)) { flag |= FLAG_LOST_RETRANS; + *ack_flag |= FLAG_LOST_RETRANS; + } /* E. Process state. */ switch (icsk->icsk_ca_state) { @@ -2829,7 +2825,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, if (tcp_is_reno(tp) && is_dupack) tcp_add_reno_sack(sk); } else { - if (tcp_try_undo_partial(sk, acked, prior_unsacked, flag)) + if (tcp_try_undo_partial(sk, acked)) return; /* Partial ACK arrived. Force fast retransmit. */ do_lost = tcp_is_reno(tp) || @@ -2858,7 +2854,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, tcp_try_undo_dsack(sk); if (!tcp_time_to_recover(sk, flag)) { - tcp_try_to_open(sk, flag, prior_unsacked); + tcp_try_to_open(sk, flag); return; } @@ -2880,7 +2876,6 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, if (do_lost) tcp_update_scoreboard(sk, fast_rexmit); - tcp_cwnd_reduction(sk, prior_unsacked, fast_rexmit, flag); *rexmit = REXMIT_LOST; } @@ -3306,9 +3301,6 @@ static inline bool tcp_ack_is_dubious(const struct sock *sk, const int flag) /* Decide wheather to run the increase function of congestion control. */ static inline bool tcp_may_raise_cwnd(const struct sock *sk, const int flag) { - if (tcp_in_cwnd_reduction(sk)) - return false; - /* If reordering is high then always grow cwnd whenever data is * delivered regardless of its ordering. Otherwise stay conservative * and only grow cwnd on in-order delivery (RFC5681). A stretched ACK w/ @@ -3551,6 +3543,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets = tp->packets_out; const int prior_unsacked = tp->packets_out - tp->sacked_out; int acked = 0; /* Number of packets newly acked */ + int acked_sacked; /* Number of packets newly acked or sacked */ int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */ sack_state.first_sackt.v64 = 0; @@ -3647,15 +3640,20 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (tcp_ack_is_dubious(sk, flag)) { is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); - tcp_fastretrans_alert(sk, acked, prior_unsacked, - is_dupack, flag, &rexmit); + tcp_fastretrans_alert(sk, acked, is_dupack, &flag, &rexmit); } if (tp->tlp_high_seq) tcp_process_tlp_ack(sk, ack, flag); + acked_sacked = prior_unsacked - (tp->packets_out - tp->sacked_out); /* Advance cwnd if state allows */ - if (tcp_may_raise_cwnd(sk, flag)) + if (tcp_in_cwnd_reduction(sk)) { + /* Reduce cwnd if state mandates */ + tcp_cwnd_reduction(sk, acked_sacked, flag); + } else if (tcp_may_raise_cwnd(sk, flag)) { + /* Advance cwnd if state allows */ tcp_cong_avoid(sk, ack, acked); + } if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { struct dst_entry *dst = __sk_dst_get(sk); @@ -3672,8 +3670,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) - tcp_fastretrans_alert(sk, acked, prior_unsacked, - is_dupack, flag, &rexmit); + tcp_fastretrans_alert(sk, acked, is_dupack, &flag, &rexmit); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than * it needs to be for normal retransmission. @@ -3696,8 +3693,7 @@ old_ack: if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, &sack_state); - tcp_fastretrans_alert(sk, acked, prior_unsacked, - is_dupack, flag, &rexmit); + tcp_fastretrans_alert(sk, acked, is_dupack, &flag, &rexmit); tcp_xmit_recovery(sk, rexmit); } -- cgit From ddf1af6fa00e772fdb67a7d22cb83fac2b8968a8 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 2 Feb 2016 10:33:06 -0800 Subject: tcp: new delivery accounting This patch changes the accounting of how many packets are newly acked or sacked when the sender receives an ACK. The current approach basically computes newly_acked_sacked = (prior_packets - prior_sacked) - (tp->packets_out - tp->sacked_out) where prior_packets and prior_sacked out are snapshot at the beginning of the ACK processing. The new approach tracks the delivery information via a new TCP state variable "delivered" which monotically increases as new packets are delivered in order or out-of-order. The reason for this change is that the current approach is brittle that produces negative or inaccurate estimate. 1) For non-SACK connections, an ACK that advances the SND.UNA could reset the DUPACK counters (tp->sacked_out) in tcp_process_loss() or tcp_fastretrans_alert(). This inflates the inflight suddenly and causes under-estimate or even negative estimate. Here is a real example: before after (processing ACK) packets_out 75 73 sacked_out 23 0 ca state Loss Open The old approach computes (75-23) - (73 - 0) = -21 delivered while the new approach computes 1 delivered since it considers the 2nd-24th packets are delivered OOO. 2) MSS change would re-count packets_out and sacked_out so the estimate is in-accurate and can even become negative. E.g., the inflight is doubled when MSS is halved. 3) Spurious retransmission signaled by DSACK is not accounted The new approach is simpler and more robust. For SACK connections, tp->delivered increments as packets are being acked or sacked in SACK and ACK processing. For non-sack connections, it's done in tcp_remove_reno_sacks() and tcp_add_reno_sack(). When an ACK advances the SND.UNA, tp->delivered is incremented by the number of packets ACKed (less the current number of DUPACKs received plus one packet hole). Upon receiving a DUPACK, tp->delivered is incremented assuming one out-of-order packet is delivered. Upon receiving a DSACK, tp->delivered is incremtened assuming one retransmission is delivered in tcp_sacktag_write_queue(). Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/tcp.h | 1 + net/ipv4/tcp_input.c | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index b386361ba3e8..d909feeeaea2 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -256,6 +256,7 @@ struct tcp_sock { u32 prr_delivered; /* Number of newly delivered packets to * receiver in Recovery. */ u32 prr_out; /* Total number of pkts sent during Recovery. */ + u32 delivered; /* Total data packets delivered incl. rexmits */ u32 rcv_wnd; /* Current receiver window */ u32 write_seq; /* Tail(+1) of data held in tcp send buffer */ diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index dc810df53e90..2d690b3f0a7b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1214,6 +1214,7 @@ static u8 tcp_sacktag_one(struct sock *sk, sacked |= TCPCB_SACKED_ACKED; state->flag |= FLAG_DATA_SACKED; tp->sacked_out += pcount; + tp->delivered += pcount; /* Out-of-order packets delivered */ fack_count += pcount; @@ -1825,8 +1826,12 @@ static void tcp_check_reno_reordering(struct sock *sk, const int addend) static void tcp_add_reno_sack(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + u32 prior_sacked = tp->sacked_out; + tp->sacked_out++; tcp_check_reno_reordering(sk, 0); + if (tp->sacked_out > prior_sacked) + tp->delivered++; /* Some out-of-order packet is delivered */ tcp_verify_left_out(tp); } @@ -1838,6 +1843,7 @@ static void tcp_remove_reno_sacks(struct sock *sk, int acked) if (acked > 0) { /* One ACK acked hole. The rest eat duplicate ACKs. */ + tp->delivered += max_t(int, acked - tp->sacked_out, 1); if (acked - 1 >= tp->sacked_out) tp->sacked_out = 0; else @@ -3156,10 +3162,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, flag |= FLAG_ORIG_SACK_ACKED; } - if (sacked & TCPCB_SACKED_ACKED) + if (sacked & TCPCB_SACKED_ACKED) { tp->sacked_out -= acked_pcount; - else if (tcp_is_sack(tp) && !tcp_skb_spurious_retrans(tp, skb)) - tcp_rack_advance(tp, &skb->skb_mstamp, sacked); + } else if (tcp_is_sack(tp)) { + tp->delivered += acked_pcount; + if (!tcp_skb_spurious_retrans(tp, skb)) + tcp_rack_advance(tp, &skb->skb_mstamp, sacked); + } if (sacked & TCPCB_LOST) tp->lost_out -= acked_pcount; @@ -3541,9 +3550,9 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) bool is_dupack = false; u32 prior_fackets; int prior_packets = tp->packets_out; - const int prior_unsacked = tp->packets_out - tp->sacked_out; + u32 prior_delivered = tp->delivered; int acked = 0; /* Number of packets newly acked */ - int acked_sacked; /* Number of packets newly acked or sacked */ + u32 acked_sacked; /* Number of packets newly acked or sacked */ int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */ sack_state.first_sackt.v64 = 0; @@ -3645,7 +3654,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (tp->tlp_high_seq) tcp_process_tlp_ack(sk, ack, flag); - acked_sacked = prior_unsacked - (tp->packets_out - tp->sacked_out); + acked_sacked = tp->delivered - prior_delivered; /* Advance cwnd if state allows */ if (tcp_in_cwnd_reduction(sk)) { /* Reduce cwnd if state mandates */ -- cgit From 3ebd88710584d494b670e54b2c339e3be290956c Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 2 Feb 2016 10:33:07 -0800 Subject: tcp: refactor pkts acked accounting A small refactoring that gets number of packets cumulatively acked from tcp_clean_rtx_queue() directly. Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2d690b3f0a7b..40824b380ef8 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3104,7 +3104,7 @@ static void tcp_ack_tstamp(struct sock *sk, struct sk_buff *skb, * arrived at the other end. */ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, - u32 prior_snd_una, + u32 prior_snd_una, int *acked, struct tcp_sacktag_state *sack) { const struct inet_connection_sock *icsk = inet_csk(sk); @@ -3277,6 +3277,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, } } #endif + *acked = pkts_acked; return flag; } @@ -3642,10 +3643,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) goto no_queue; /* See if we can take anything off of the retransmit queue. */ - acked = tp->packets_out; - flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, + flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, &acked, &sack_state); - acked -= tp->packets_out; if (tcp_ack_is_dubious(sk, flag)) { is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); -- cgit From 2d14a4def4fc87cb2d2712f7841b45189d75e301 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 2 Feb 2016 10:33:08 -0800 Subject: tcp: make congestion control more robust against reordering This change enables congestion control to update cwnd based on not only packet cumulatively acked but also packets delivered out-of-order. This makes congestion control robust against packet reordering because it may raise cwnd as long as packets are being delivered once reordering has been detected (i.e., it only cares the amount of packets delivered, not the ordering among them). Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 40824b380ef8..d598ff408cb9 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3660,7 +3660,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_cwnd_reduction(sk, acked_sacked, flag); } else if (tcp_may_raise_cwnd(sk, flag)) { /* Advance cwnd if state allows */ - tcp_cong_avoid(sk, ack, acked); + tcp_cong_avoid(sk, ack, acked_sacked); } if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { -- cgit From d452e6caf8367cc70cf940c24a6a6cc2d521d3c1 Mon Sep 17 00:00:00 2001 From: Yuchung Cheng Date: Tue, 2 Feb 2016 10:33:09 -0800 Subject: tcp: tcp_cong_control helper Refactor and consolidate cwnd and rate updates into a new function tcp_cong_control(). Signed-off-by: Yuchung Cheng Signed-off-by: Neal Cardwell Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d598ff408cb9..596c1cb6759a 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3323,6 +3323,24 @@ static inline bool tcp_may_raise_cwnd(const struct sock *sk, const int flag) return flag & FLAG_DATA_ACKED; } +/* The "ultimate" congestion control function that aims to replace the rigid + * cwnd increase and decrease control (tcp_cong_avoid,tcp_*cwnd_reduction). + * It's called toward the end of processing an ACK with precise rate + * information. All transmission or retransmission are delayed afterwards. + */ +static void tcp_cong_control(struct sock *sk, u32 ack, u32 acked_sacked, + int flag) +{ + if (tcp_in_cwnd_reduction(sk)) { + /* Reduce cwnd if state mandates */ + tcp_cwnd_reduction(sk, acked_sacked, flag); + } else if (tcp_may_raise_cwnd(sk, flag)) { + /* Advance cwnd if state allows */ + tcp_cong_avoid(sk, ack, acked_sacked); + } + tcp_update_pacing_rate(sk); +} + /* Check that window update is acceptable. * The function assumes that snd_una<=ack<=snd_next. */ @@ -3553,7 +3571,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets = tp->packets_out; u32 prior_delivered = tp->delivered; int acked = 0; /* Number of packets newly acked */ - u32 acked_sacked; /* Number of packets newly acked or sacked */ int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */ sack_state.first_sackt.v64 = 0; @@ -3653,16 +3670,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (tp->tlp_high_seq) tcp_process_tlp_ack(sk, ack, flag); - acked_sacked = tp->delivered - prior_delivered; - /* Advance cwnd if state allows */ - if (tcp_in_cwnd_reduction(sk)) { - /* Reduce cwnd if state mandates */ - tcp_cwnd_reduction(sk, acked_sacked, flag); - } else if (tcp_may_raise_cwnd(sk, flag)) { - /* Advance cwnd if state allows */ - tcp_cong_avoid(sk, ack, acked_sacked); - } - if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) { struct dst_entry *dst = __sk_dst_get(sk); if (dst) @@ -3671,7 +3678,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (icsk->icsk_pending == ICSK_TIME_RETRANS) tcp_schedule_loss_probe(sk); - tcp_update_pacing_rate(sk); + tcp_cong_control(sk, ack, tp->delivered - prior_delivered, flag); tcp_xmit_recovery(sk, rexmit); return 1; -- cgit From 46fcc6ef9d39eb7b1becaa5ef5cba64d230f7c3f Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Tue, 2 Feb 2016 10:41:55 -0800 Subject: sunvnet: Add support for perf LDC event tracing Add perf event macros for support of tracing and instrumentation of LDC state machine Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- include/trace/events/sunvnet.h | 139 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 include/trace/events/sunvnet.h diff --git a/include/trace/events/sunvnet.h b/include/trace/events/sunvnet.h new file mode 100644 index 000000000000..eb080b267e55 --- /dev/null +++ b/include/trace/events/sunvnet.h @@ -0,0 +1,139 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM sunvnet + +#if !defined(_TRACE_SUNVNET_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_SUNVNET_H + +#include + +TRACE_EVENT(vnet_rx_one, + + TP_PROTO(int lsid, int rsid, int index, int needs_ack), + + TP_ARGS(lsid, rsid, index, needs_ack), + + TP_STRUCT__entry( + __field(int, lsid) + __field(int, rsid) + __field(int, index) + __field(int, needs_ack) + ), + + TP_fast_assign( + __entry->lsid = lsid; + __entry->rsid = rsid; + __entry->index = index; + __entry->needs_ack = needs_ack; + ), + + TP_printk("(%x:%x) walk_rx_one index %d; needs_ack %d", + __entry->lsid, __entry->rsid, + __entry->index, __entry->needs_ack) +); + +DECLARE_EVENT_CLASS(vnet_tx_stopped_ack_template, + + TP_PROTO(int lsid, int rsid, int ack_end, int npkts), + + TP_ARGS(lsid, rsid, ack_end, npkts), + + TP_STRUCT__entry( + __field(int, lsid) + __field(int, rsid) + __field(int, ack_end) + __field(int, npkts) + ), + + TP_fast_assign( + __entry->lsid = lsid; + __entry->rsid = rsid; + __entry->ack_end = ack_end; + __entry->npkts = npkts; + ), + + TP_printk("(%x:%x) stopped ack for %d; npkts %d", + __entry->lsid, __entry->rsid, + __entry->ack_end, __entry->npkts) +); +DEFINE_EVENT(vnet_tx_stopped_ack_template, vnet_tx_send_stopped_ack, + TP_PROTO(int lsid, int rsid, int ack_end, int npkts), + TP_ARGS(lsid, rsid, ack_end, npkts)); +DEFINE_EVENT(vnet_tx_stopped_ack_template, vnet_tx_defer_stopped_ack, + TP_PROTO(int lsid, int rsid, int ack_end, int npkts), + TP_ARGS(lsid, rsid, ack_end, npkts)); +DEFINE_EVENT(vnet_tx_stopped_ack_template, vnet_tx_pending_stopped_ack, + TP_PROTO(int lsid, int rsid, int ack_end, int npkts), + TP_ARGS(lsid, rsid, ack_end, npkts)); + +TRACE_EVENT(vnet_rx_stopped_ack, + + TP_PROTO(int lsid, int rsid, int end), + + TP_ARGS(lsid, rsid, end), + + TP_STRUCT__entry( + __field(int, lsid) + __field(int, rsid) + __field(int, end) + ), + + TP_fast_assign( + __entry->lsid = lsid; + __entry->rsid = rsid; + __entry->end = end; + ), + + TP_printk("(%x:%x) stopped ack for index %d", + __entry->lsid, __entry->rsid, __entry->end) +); + +TRACE_EVENT(vnet_tx_trigger, + + TP_PROTO(int lsid, int rsid, int start, int err), + + TP_ARGS(lsid, rsid, start, err), + + TP_STRUCT__entry( + __field(int, lsid) + __field(int, rsid) + __field(int, start) + __field(int, err) + ), + + TP_fast_assign( + __entry->lsid = lsid; + __entry->rsid = rsid; + __entry->start = start; + __entry->err = err; + ), + + TP_printk("(%x:%x) Tx trigger for %d sent with err %d %s", + __entry->lsid, __entry->rsid, __entry->start, + __entry->err, __entry->err > 0 ? "(ok)" : " ") +); + +TRACE_EVENT(vnet_skip_tx_trigger, + + TP_PROTO(int lsid, int rsid, int last), + + TP_ARGS(lsid, rsid, last), + + TP_STRUCT__entry( + __field(int, lsid) + __field(int, rsid) + __field(int, last) + ), + + TP_fast_assign( + __entry->lsid = lsid; + __entry->rsid = rsid; + __entry->last = last; + ), + + TP_printk("(%x:%x) Skip Tx trigger. Last trigger sent was %d", + __entry->lsid, __entry->rsid, __entry->last) +); +#endif /* _TRACE_SOCK_H */ + +/* This part must be outside protection */ +#include -- cgit From 365a10289fccbf769ad8b172c30716fac50fa278 Mon Sep 17 00:00:00 2001 From: Sowmini Varadhan Date: Tue, 2 Feb 2016 10:41:56 -0800 Subject: sunvnet: perf tracepoint invocations to trace LDC state machine Use sunvnet perf trace macros to monitor LDC message exchange state. Signed-off-by: Sowmini Varadhan Signed-off-by: David S. Miller --- drivers/net/ethernet/sun/sunvnet.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 23fa29877f5b..942a95db2061 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -17,6 +17,8 @@ #include #include #include +#define CREATE_TRACE_POINTS +#include #if IS_ENABLED(CONFIG_IPV6) #include @@ -540,6 +542,8 @@ static int vnet_walk_rx_one(struct vnet_port *port, err = vnet_rx_one(port, desc); if (err == -ECONNRESET) return err; + trace_vnet_rx_one(port->vio._local_sid, port->vio._peer_sid, + index, desc->hdr.ack); desc->hdr.state = VIO_DESC_DONE; err = put_rx_desc(port, dr, desc, index); if (err < 0) @@ -587,9 +591,15 @@ static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr, ack_start = ack_end = vio_dring_prev(dr, start); if (send_ack) { port->napi_resume = false; + trace_vnet_tx_send_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, + ack_end, *npkts); return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED); } else { + trace_vnet_tx_defer_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, + ack_end, *npkts); port->napi_resume = true; port->napi_stop_idx = ack_end; return 1; @@ -663,6 +673,8 @@ static int vnet_ack(struct vnet_port *port, void *msgbuf) /* sync for race conditions with vnet_start_xmit() and tell xmit it * is time to send a trigger. */ + trace_vnet_rx_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, end); dr->cons = vio_dring_next(dr, end); desc = vio_dring_entry(dr, dr->cons); if (desc->hdr.state == VIO_DESC_READY && !port->start_cons) { @@ -886,6 +898,9 @@ static int __vnet_tx_trigger(struct vnet_port *port, u32 start) int retries = 0; if (port->stop_rx) { + trace_vnet_tx_pending_stopped_ack(port->vio._local_sid, + port->vio._peer_sid, + port->stop_rx_idx, -1); err = vnet_send_ack(port, &port->vio.drings[VIO_DRIVER_RX_RING], port->stop_rx_idx, -1, @@ -908,6 +923,8 @@ static int __vnet_tx_trigger(struct vnet_port *port, u32 start) if (retries++ > VNET_MAX_RETRIES) break; } while (err == -EAGAIN); + trace_vnet_tx_trigger(port->vio._local_sid, + port->vio._peer_sid, start, err); return err; } @@ -1414,8 +1431,11 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) * producer to consumer announcement that work is available to the * consumer */ - if (!port->start_cons) - goto ldc_start_done; /* previous trigger suffices */ + if (!port->start_cons) { /* previous trigger suffices */ + trace_vnet_skip_tx_trigger(port->vio._local_sid, + port->vio._peer_sid, dr->cons); + goto ldc_start_done; + } err = __vnet_tx_trigger(port, dr->cons); if (unlikely(err < 0)) { -- cgit From 103a8ad1fa3b261c78dfc842cb315defe9d40be0 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 3 Feb 2016 04:04:36 +0100 Subject: ethtool: add speed/duplex validation functions Add functions which check if the speed/duplex are defined. Signed-off-by: Nikolay Aleksandrov Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 57fa39005e79..b2e180181629 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -1319,11 +1319,45 @@ enum ethtool_sfeatures_retval_bits { #define SPEED_UNKNOWN -1 +static inline int ethtool_validate_speed(__u32 speed) +{ + switch (speed) { + case SPEED_10: + case SPEED_100: + case SPEED_1000: + case SPEED_2500: + case SPEED_5000: + case SPEED_10000: + case SPEED_20000: + case SPEED_25000: + case SPEED_40000: + case SPEED_50000: + case SPEED_56000: + case SPEED_100000: + case SPEED_UNKNOWN: + return 1; + } + + return 0; +} + /* Duplex, half or full. */ #define DUPLEX_HALF 0x00 #define DUPLEX_FULL 0x01 #define DUPLEX_UNKNOWN 0xff +static inline int ethtool_validate_duplex(__u8 duplex) +{ + switch (duplex) { + case DUPLEX_HALF: + case DUPLEX_FULL: + case DUPLEX_UNKNOWN: + return 1; + } + + return 0; +} + /* Which connector port. */ #define PORT_TP 0x00 #define PORT_AUI 0x01 -- cgit From 16032be56c1f66770da15cb94f0eb366c37aff6e Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Wed, 3 Feb 2016 04:04:37 +0100 Subject: virtio_net: add ethtool support for set and get of settings This patch allows the user to set and retrieve speed and duplex of the virtio_net device via ethtool. Having this functionality is very helpful for simulating different environments and also enables the virtio_net device to participate in operations where proper speed and duplex are required (e.g. currently bonding lacp mode requires full duplex). Custom speed and duplex are not allowed, the user-supplied settings are validated before applying. Example: $ ethtool eth1 Settings for eth1: ... Speed: Unknown! Duplex: Unknown! (255) $ ethtool -s eth1 speed 1000 duplex full $ ethtool eth1 Settings for eth1: ... Speed: 1000Mb/s Duplex: Full Based on a patch by Roopa Prabhu. Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 767ab11a6e9f..c9fd52a8e6ec 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -146,6 +146,10 @@ struct virtnet_info { virtio_net_ctrl_ack ctrl_status; u8 ctrl_promisc; u8 ctrl_allmulti; + + /* Ethtool settings */ + u8 duplex; + u32 speed; }; struct padded_vnet_hdr { @@ -1376,6 +1380,58 @@ static void virtnet_get_channels(struct net_device *dev, channels->other_count = 0; } +/* Check if the user is trying to change anything besides speed/duplex */ +static bool virtnet_validate_ethtool_cmd(const struct ethtool_cmd *cmd) +{ + struct ethtool_cmd diff1 = *cmd; + struct ethtool_cmd diff2 = {}; + + /* advertising and cmd are usually set, ignore port because we set it */ + ethtool_cmd_speed_set(&diff1, 0); + diff1.advertising = 0; + diff1.duplex = 0; + diff1.port = 0; + diff1.cmd = 0; + + return !memcmp(&diff1, &diff2, sizeof(diff1)); +} + +static int virtnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct virtnet_info *vi = netdev_priv(dev); + u32 speed; + + speed = ethtool_cmd_speed(cmd); + /* don't allow custom speed and duplex */ + if (!ethtool_validate_speed(speed) || + !ethtool_validate_duplex(cmd->duplex) || + !virtnet_validate_ethtool_cmd(cmd)) + return -EINVAL; + vi->speed = speed; + vi->duplex = cmd->duplex; + + return 0; +} + +static int virtnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct virtnet_info *vi = netdev_priv(dev); + + ethtool_cmd_speed_set(cmd, vi->speed); + cmd->duplex = vi->duplex; + cmd->port = PORT_OTHER; + + return 0; +} + +static void virtnet_init_settings(struct net_device *dev) +{ + struct virtnet_info *vi = netdev_priv(dev); + + vi->speed = SPEED_UNKNOWN; + vi->duplex = DUPLEX_UNKNOWN; +} + static const struct ethtool_ops virtnet_ethtool_ops = { .get_drvinfo = virtnet_get_drvinfo, .get_link = ethtool_op_get_link, @@ -1383,6 +1439,8 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .set_channels = virtnet_set_channels, .get_channels = virtnet_get_channels, .get_ts_info = ethtool_op_get_ts_info, + .get_settings = virtnet_get_settings, + .set_settings = virtnet_set_settings, }; #define MIN_MTU 68 @@ -1855,6 +1913,8 @@ static int virtnet_probe(struct virtio_device *vdev) netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs); netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs); + virtnet_init_settings(dev); + err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); -- cgit From 6fa251663069e05daadd1666cbf3b658bf840ea4 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:49 +0200 Subject: ipv4: Namespaceify tcp syn retries sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 ++ include/net/tcp.h | 1 - net/ipv4/sysctl_net_ipv4.c | 18 +++++++++--------- net/ipv4/tcp.c | 3 ++- net/ipv4/tcp_ipv4.c | 2 ++ net/ipv4/tcp_timer.c | 4 ++-- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 2b7907a35568..b7b5bd64df35 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -98,6 +98,8 @@ struct netns_ipv4 { int sysctl_tcp_keepalive_probes; int sysctl_tcp_keepalive_intvl; + int sysctl_tcp_syn_retries; + struct ping_group_range ping_group_range; atomic_t dev_addr_genid; diff --git a/include/net/tcp.h b/include/net/tcp.h index 479d535609fd..825485c7cc1a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -240,7 +240,6 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_fin_timeout; -extern int sysctl_tcp_syn_retries; extern int sysctl_tcp_synack_retries; extern int sysctl_tcp_retries1; extern int sysctl_tcp_retries2; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 4d367b4139a3..ae9dd8823134 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -291,15 +291,6 @@ static struct ctl_table ipv4_table[] = { .extra1 = &ip_ttl_min, .extra2 = &ip_ttl_max, }, - { - .procname = "tcp_syn_retries", - .data = &sysctl_tcp_syn_retries, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &tcp_syn_retries_min, - .extra2 = &tcp_syn_retries_max - }, { .procname = "tcp_synack_retries", .data = &sysctl_tcp_synack_retries, @@ -960,6 +951,15 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, + { + .procname = "tcp_syn_retries", + .data = &init_net.ipv4.sysctl_tcp_syn_retries, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &tcp_syn_retries_min, + .extra2 = &tcp_syn_retries_max + }, { } }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c5075779e017..3dbb3637bb4b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2731,6 +2731,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); int val, len; if (get_user(len, optlen)) @@ -2765,7 +2766,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, val = keepalive_probes(tp); break; case TCP_SYNCNT: - val = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; + val = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; break; case TCP_LINGER2: val = tp->linger2; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index a4d523709ab3..f7464852aaa1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2388,6 +2388,8 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES; net->ipv4.sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL; + net->ipv4.sysctl_tcp_syn_retries = TCP_SYN_RETRIES; + return 0; fail: tcp_sk_exit(net); diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index a4730a28b220..c5d51f530c65 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -22,7 +22,6 @@ #include #include -int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES; int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES; int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; @@ -157,6 +156,7 @@ static int tcp_write_timeout(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); int retry_until; bool do_reset, syn_set = false; @@ -169,7 +169,7 @@ static int tcp_write_timeout(struct sock *sk) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVEFAIL); } - retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; + retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; syn_set = true; } else { if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0, 0)) { -- cgit From 7c083ecb3ba4583a625d5ff9655d1a819e374493 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:50 +0200 Subject: ipv4: Namespaceify tcp synack retries sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + include/net/tcp.h | 1 - net/ipv4/inet_connection_sock.c | 7 ++----- net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_timer.c | 3 +-- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index b7b5bd64df35..9e83084ab8c1 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -99,6 +99,7 @@ struct netns_ipv4 { int sysctl_tcp_keepalive_intvl; int sysctl_tcp_syn_retries; + int sysctl_tcp_synack_retries; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index 825485c7cc1a..05659e860039 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -240,7 +240,6 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_fin_timeout; -extern int sysctl_tcp_synack_retries; extern int sysctl_tcp_retries1; extern int sysctl_tcp_retries2; extern int sysctl_tcp_orphan_retries; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 46b9c887bede..9b17c1792dce 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -482,10 +482,6 @@ EXPORT_SYMBOL_GPL(inet_csk_route_child_sock); #define AF_INET_FAMILY(fam) true #endif -/* Only thing we need from tcp.h */ -extern int sysctl_tcp_synack_retries; - - /* Decide when to expire the request and when to resend SYN-ACK */ static inline void syn_ack_recalc(struct request_sock *req, const int thresh, const int max_retries, @@ -557,6 +553,7 @@ static void reqsk_timer_handler(unsigned long data) { struct request_sock *req = (struct request_sock *)data; struct sock *sk_listener = req->rsk_listener; + struct net *net = sock_net(sk_listener); struct inet_connection_sock *icsk = inet_csk(sk_listener); struct request_sock_queue *queue = &icsk->icsk_accept_queue; int qlen, expire = 0, resend = 0; @@ -566,7 +563,7 @@ static void reqsk_timer_handler(unsigned long data) if (sk_state_load(sk_listener) != TCP_LISTEN) goto drop; - max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; + max_retries = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_synack_retries; thresh = max_retries; /* Normally all the openreqs are young and become mature * (i.e. converted to established socket) for first timeout. diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index ae9dd8823134..bb682e36d8b7 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -291,13 +291,6 @@ static struct ctl_table ipv4_table[] = { .extra1 = &ip_ttl_min, .extra2 = &ip_ttl_max, }, - { - .procname = "tcp_synack_retries", - .data = &sysctl_tcp_synack_retries, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { .procname = "tcp_max_orphans", .data = &sysctl_tcp_max_orphans, @@ -960,6 +953,13 @@ static struct ctl_table ipv4_net_table[] = { .extra1 = &tcp_syn_retries_min, .extra2 = &tcp_syn_retries_max }, + { + .procname = "tcp_synack_retries", + .data = &init_net.ipv4.sysctl_tcp_synack_retries, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { } }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f7464852aaa1..3146279695b9 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2389,6 +2389,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL; net->ipv4.sysctl_tcp_syn_retries = TCP_SYN_RETRIES; + net->ipv4.sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; return 0; fail: diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index c5d51f530c65..ca25fdf0c525 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -22,7 +22,6 @@ #include #include -int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES; int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; int sysctl_tcp_orphan_retries __read_mostly; @@ -332,7 +331,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); int max_retries = icsk->icsk_syn_retries ? : - sysctl_tcp_synack_retries + 1; /* add one more retry for fastopen */ + sock_net(sk)->ipv4.sysctl_tcp_synack_retries + 1; /* add one more retry for fastopen */ struct request_sock *req; req = tcp_sk(sk)->fastopen_rsk; -- cgit From 12ed8244ed8b31b023ea6d2851fd8b15f2999e9b Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:51 +0200 Subject: ipv4: Namespaceify tcp syncookies sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 ++ include/net/tcp.h | 1 - net/ipv4/syncookies.c | 4 +--- net/ipv4/sysctl_net_ipv4.c | 18 +++++++++--------- net/ipv4/tcp_input.c | 10 ++++++---- net/ipv4/tcp_ipv4.c | 3 ++- net/ipv4/tcp_minisocks.c | 3 --- net/ipv6/syncookies.c | 2 +- 8 files changed, 21 insertions(+), 22 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 9e83084ab8c1..ac000fccdf0f 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -101,6 +101,8 @@ struct netns_ipv4 { int sysctl_tcp_syn_retries; int sysctl_tcp_synack_retries; + int sysctl_tcp_syncookies; + struct ping_group_range ping_group_range; atomic_t dev_addr_genid; diff --git a/include/net/tcp.h b/include/net/tcp.h index 05659e860039..1fb23b70d237 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -243,7 +243,6 @@ extern int sysctl_tcp_fin_timeout; extern int sysctl_tcp_retries1; extern int sysctl_tcp_retries2; extern int sysctl_tcp_orphan_retries; -extern int sysctl_tcp_syncookies; extern int sysctl_tcp_fastopen; extern int sysctl_tcp_retrans_collapse; extern int sysctl_tcp_stdurg; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 643a86c49020..ba0dcffada3b 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -19,8 +19,6 @@ #include #include -extern int sysctl_tcp_syncookies; - static u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS] __read_mostly; #define COOKIEBITS 24 /* Upper bits store count */ @@ -307,7 +305,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) __u8 rcv_wscale; struct flowi4 fl4; - if (!sysctl_tcp_syncookies || !th->ack || th->rst) + if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) goto out; if (tcp_synq_no_recent_overflow(sk)) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index bb682e36d8b7..d80142570a8d 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -341,15 +341,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, -#ifdef CONFIG_SYN_COOKIES - { - .procname = "tcp_syncookies", - .data = &sysctl_tcp_syncookies, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, -#endif { .procname = "tcp_fastopen", .data = &sysctl_tcp_fastopen, @@ -960,6 +951,15 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, +#ifdef CONFIG_SYN_COOKIES + { + .procname = "tcp_syncookies", + .data = &init_net.ipv4.sysctl_tcp_syncookies, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, +#endif { } }; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 596c1cb6759a..b17aba42a368 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -6163,9 +6163,10 @@ static bool tcp_syn_flood_action(const struct sock *sk, struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; const char *msg = "Dropping request"; bool want_cookie = false; + struct net *net = sock_net(sk); #ifdef CONFIG_SYN_COOKIES - if (sysctl_tcp_syncookies) { + if (net->ipv4.sysctl_tcp_syncookies) { msg = "Sending cookies"; want_cookie = true; NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES); @@ -6174,7 +6175,7 @@ static bool tcp_syn_flood_action(const struct sock *sk, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP); if (!queue->synflood_warned && - sysctl_tcp_syncookies != 2 && + net->ipv4.sysctl_tcp_syncookies != 2 && xchg(&queue->synflood_warned, 1) == 0) pr_info("%s: Possible SYN flooding on port %d. %s. Check SNMP counters.\n", proto, ntohs(tcp_hdr(skb)->dest), msg); @@ -6207,6 +6208,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, __u32 isn = TCP_SKB_CB(skb)->tcp_tw_isn; struct tcp_options_received tmp_opt; struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); struct sock *fastopen_sk = NULL; struct dst_entry *dst = NULL; struct request_sock *req; @@ -6217,7 +6219,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, * limitations, they conserve resources and peer is * evidently real one. */ - if ((sysctl_tcp_syncookies == 2 || + if ((net->ipv4.sysctl_tcp_syncookies == 2 || inet_csk_reqsk_queue_is_full(sk)) && !isn) { want_cookie = tcp_syn_flood_action(sk, skb, rsk_ops->slab_name); if (!want_cookie) @@ -6283,7 +6285,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, } } /* Kill the following clause, if you dislike this way. */ - else if (!sysctl_tcp_syncookies && + else if (!net->ipv4.sysctl_tcp_syncookies && (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < (sysctl_max_syn_backlog >> 2)) && !tcp_peer_is_proven(req, dst, false, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3146279695b9..98313d10a2e0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -860,7 +860,6 @@ static void tcp_v4_reqsk_destructor(struct request_sock *req) kfree(inet_rsk(req)->opt); } - #ifdef CONFIG_TCP_MD5SIG /* * RFC2385 MD5 checksumming requires a mapping of @@ -2391,6 +2390,8 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_syn_retries = TCP_SYN_RETRIES; net->ipv4.sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; + net->ipv4.sysctl_tcp_syncookies = 0; + return 0; fail: tcp_sk_exit(net); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 75632a925824..fadd8b978951 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -27,9 +27,6 @@ #include #include -int sysctl_tcp_syncookies __read_mostly = 1; -EXPORT_SYMBOL(sysctl_tcp_syncookies); - int sysctl_tcp_abort_on_overflow __read_mostly; struct inet_timewait_death_row tcp_death_row = { diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 2906ef20795e..0e393ff7f5d0 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -148,7 +148,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) struct dst_entry *dst; __u8 rcv_wscale; - if (!sysctl_tcp_syncookies || !th->ack || th->rst) + if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst) goto out; if (tcp_synq_no_recent_overflow(sk)) -- cgit From 1043e25ff96a1efc7bd34d11f5f32203a28a3bd7 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:52 +0200 Subject: ipv4: Namespaceify tcp reordering sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 2 +- include/net/tcp.h | 4 +++- net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_input.c | 12 ++++++------ net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/tcp_metrics.c | 3 ++- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index ac000fccdf0f..eb4cd0a3c296 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -100,8 +100,8 @@ struct netns_ipv4 { int sysctl_tcp_syn_retries; int sysctl_tcp_synack_retries; - int sysctl_tcp_syncookies; + int sysctl_tcp_reordering; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index 1fb23b70d237..7e9a147cabae 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -961,9 +961,11 @@ static inline void tcp_enable_fack(struct tcp_sock *tp) */ static inline void tcp_enable_early_retrans(struct tcp_sock *tp) { + struct net *net = sock_net((struct sock *)tp); + tp->do_early_retrans = sysctl_tcp_early_retrans && sysctl_tcp_early_retrans < 4 && !sysctl_tcp_thin_dupack && - sysctl_tcp_reordering == 3; + net->ipv4.sysctl_tcp_reordering == 3; } static inline void tcp_disable_early_retrans(struct tcp_sock *tp) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index d80142570a8d..7cd20570588f 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -455,13 +455,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec, }, - { - .procname = "tcp_reordering", - .data = &sysctl_tcp_reordering, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { .procname = "tcp_max_reordering", .data = &sysctl_tcp_max_reordering, @@ -960,6 +953,13 @@ static struct ctl_table ipv4_net_table[] = { .proc_handler = proc_dointvec }, #endif + { + .procname = "tcp_reordering", + .data = &init_net.ipv4.sysctl_tcp_reordering, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { } }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 3dbb3637bb4b..f4db6b04cdb4 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -406,7 +406,7 @@ void tcp_init_sock(struct sock *sk) tp->mss_cache = TCP_MSS_DEFAULT; u64_stats_init(&tp->syncp); - tp->reordering = sysctl_tcp_reordering; + tp->reordering = sock_net(sk)->ipv4.sysctl_tcp_reordering; tcp_enable_early_retrans(tp); tcp_assign_congestion_control(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b17aba42a368..5ee6fe0d152d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -80,9 +80,7 @@ int sysctl_tcp_timestamps __read_mostly = 1; int sysctl_tcp_window_scaling __read_mostly = 1; int sysctl_tcp_sack __read_mostly = 1; int sysctl_tcp_fack __read_mostly = 1; -int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH; int sysctl_tcp_max_reordering __read_mostly = 300; -EXPORT_SYMBOL(sysctl_tcp_reordering); int sysctl_tcp_dsack __read_mostly = 1; int sysctl_tcp_app_win __read_mostly = 31; int sysctl_tcp_adv_win_scale __read_mostly = 1; @@ -1883,6 +1881,7 @@ void tcp_enter_loss(struct sock *sk) { const struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); struct sk_buff *skb; bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery; bool is_reneg; /* is receiver reneging on SACKs? */ @@ -1933,9 +1932,9 @@ void tcp_enter_loss(struct sock *sk) * suggests that the degree of reordering is over-estimated. */ if (icsk->icsk_ca_state <= TCP_CA_Disorder && - tp->sacked_out >= sysctl_tcp_reordering) + tp->sacked_out >= net->ipv4.sysctl_tcp_reordering) tp->reordering = min_t(unsigned int, tp->reordering, - sysctl_tcp_reordering); + net->ipv4.sysctl_tcp_reordering); tcp_set_ca_state(sk, TCP_CA_Loss); tp->high_seq = tp->snd_nxt; tcp_ecn_queue_cwr(tp); @@ -2119,6 +2118,7 @@ static bool tcp_time_to_recover(struct sock *sk, int flag) { struct tcp_sock *tp = tcp_sk(sk); __u32 packets_out; + int tcp_reordering = sock_net(sk)->ipv4.sysctl_tcp_reordering; /* Trick#1: The loss is proven. */ if (tp->lost_out) @@ -2133,7 +2133,7 @@ static bool tcp_time_to_recover(struct sock *sk, int flag) */ packets_out = tp->packets_out; if (packets_out <= tp->reordering && - tp->sacked_out >= max_t(__u32, packets_out/2, sysctl_tcp_reordering) && + tp->sacked_out >= max_t(__u32, packets_out/2, tcp_reordering) && !tcp_may_send_now(sk)) { /* We have nothing to send. This connection is limited * either by receiver window or by application. @@ -3317,7 +3317,7 @@ static inline bool tcp_may_raise_cwnd(const struct sock *sk, const int flag) * new SACK or ECE mark may first advance cwnd here and later reduce * cwnd in tcp_fastretrans_alert() based on more states. */ - if (tcp_sk(sk)->reordering > sysctl_tcp_reordering) + if (tcp_sk(sk)->reordering > sock_net(sk)->ipv4.sysctl_tcp_reordering) return flag & FLAG_FORWARD_PROGRESS; return flag & FLAG_DATA_ACKED; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 98313d10a2e0..10dfc8b5c0f8 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2389,8 +2389,8 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_syn_retries = TCP_SYN_RETRIES; net->ipv4.sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; - net->ipv4.sysctl_tcp_syncookies = 0; + net->ipv4.sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH; return 0; fail: diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index c8cbc2b4b792..c26241f3057b 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -369,6 +369,7 @@ void tcp_update_metrics(struct sock *sk) const struct inet_connection_sock *icsk = inet_csk(sk); struct dst_entry *dst = __sk_dst_get(sk); struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); struct tcp_metrics_block *tm; unsigned long rtt; u32 val; @@ -473,7 +474,7 @@ void tcp_update_metrics(struct sock *sk) if (!tcp_metric_locked(tm, TCP_METRIC_REORDERING)) { val = tcp_metric_get(tm, TCP_METRIC_REORDERING); if (val < tp->reordering && - tp->reordering != sysctl_tcp_reordering) + tp->reordering != net->ipv4.sysctl_tcp_reordering) tcp_metric_set(tm, TCP_METRIC_REORDERING, tp->reordering); } -- cgit From ae5c3f406cffe15ffd2aa544961b7cd027468d46 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:53 +0200 Subject: ipv4: Namespaceify tcp_retries1 sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + include/net/tcp.h | 1 - net/ipv4/sysctl_net_ipv4.c | 16 ++++++++-------- net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_timer.c | 8 ++++---- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index eb4cd0a3c296..dee6ba647461 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -102,6 +102,7 @@ struct netns_ipv4 { int sysctl_tcp_synack_retries; int sysctl_tcp_syncookies; int sysctl_tcp_reordering; + int sysctl_tcp_retries1; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index 7e9a147cabae..da96b9af3e5f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -240,7 +240,6 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_fin_timeout; -extern int sysctl_tcp_retries1; extern int sysctl_tcp_retries2; extern int sysctl_tcp_orphan_retries; extern int sysctl_tcp_fastopen; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 7cd20570588f..52853c6dc929 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -319,14 +319,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "tcp_retries1", - .data = &sysctl_tcp_retries1, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra2 = &tcp_retr1_max - }, { .procname = "tcp_retries2", .data = &sysctl_tcp_retries2, @@ -960,6 +952,14 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_retries1", + .data = &init_net.ipv4.sysctl_tcp_retries1, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra2 = &tcp_retr1_max + }, { } }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 10dfc8b5c0f8..57fe3c6bfb30 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2391,6 +2391,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; net->ipv4.sysctl_tcp_syncookies = 0; net->ipv4.sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH; + net->ipv4.sysctl_tcp_retries1 = TCP_RETR1; return 0; fail: diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index ca25fdf0c525..6694e33149b9 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -22,7 +22,6 @@ #include #include -int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; int sysctl_tcp_orphan_retries __read_mostly; int sysctl_tcp_thin_linear_timeouts __read_mostly; @@ -171,7 +170,7 @@ static int tcp_write_timeout(struct sock *sk) retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries; syn_set = true; } else { - if (retransmits_timed_out(sk, sysctl_tcp_retries1, 0, 0)) { + if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1, 0, 0)) { /* Some middle-boxes may black-hole Fast Open _after_ * the handshake. Therefore we conservatively disable * Fast Open on this path on recurring timeouts with @@ -180,7 +179,7 @@ static int tcp_write_timeout(struct sock *sk) if (tp->syn_data_acked && tp->bytes_acked <= tp->rx_opt.mss_clamp) { tcp_fastopen_cache_set(sk, 0, NULL, true, 0); - if (icsk->icsk_retransmits == sysctl_tcp_retries1) + if (icsk->icsk_retransmits == net->ipv4.sysctl_tcp_retries1) NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVEFAIL); } @@ -359,6 +358,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk) void tcp_retransmit_timer(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); struct inet_connection_sock *icsk = inet_csk(sk); if (tp->fastopen_rsk) { @@ -489,7 +489,7 @@ out_reset_timer: icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX); } inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, icsk->icsk_rto, TCP_RTO_MAX); - if (retransmits_timed_out(sk, sysctl_tcp_retries1 + 1, 0, 0)) + if (retransmits_timed_out(sk, net->ipv4.sysctl_tcp_retries1 + 1, 0, 0)) __sk_dst_reset(sk); out:; -- cgit From c6214a97c86c660de4f7ddb8eed925192e646161 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:54 +0200 Subject: ipv4: Namespaceify tcp_retries2 sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + include/net/tcp.h | 1 - net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_output.c | 3 ++- net/ipv4/tcp_timer.c | 5 ++--- 6 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index dee6ba647461..d92c8e5d0fbc 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -103,6 +103,7 @@ struct netns_ipv4 { int sysctl_tcp_syncookies; int sysctl_tcp_reordering; int sysctl_tcp_retries1; + int sysctl_tcp_retries2; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index da96b9af3e5f..a786cfa6301b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -240,7 +240,6 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_fin_timeout; -extern int sysctl_tcp_retries2; extern int sysctl_tcp_orphan_retries; extern int sysctl_tcp_fastopen; extern int sysctl_tcp_retrans_collapse; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 52853c6dc929..8e339d43619c 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -319,13 +319,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "tcp_retries2", - .data = &sysctl_tcp_retries2, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { .procname = "tcp_fin_timeout", .data = &sysctl_tcp_fin_timeout, @@ -960,6 +953,13 @@ static struct ctl_table ipv4_net_table[] = { .proc_handler = proc_dointvec_minmax, .extra2 = &tcp_retr1_max }, + { + .procname = "tcp_retries2", + .data = &init_net.ipv4.sysctl_tcp_retries2, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { } }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 57fe3c6bfb30..0710e6108a5e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2392,6 +2392,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_syncookies = 0; net->ipv4.sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH; net->ipv4.sysctl_tcp_retries1 = TCP_RETR1; + net->ipv4.sysctl_tcp_retries2 = TCP_RETR2; return 0; fail: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index fda379cd600d..7beb3f688b7a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -3476,6 +3476,7 @@ void tcp_send_probe0(struct sock *sk) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); + struct net *net = sock_net(sk); unsigned long probe_max; int err; @@ -3489,7 +3490,7 @@ void tcp_send_probe0(struct sock *sk) } if (err <= 0) { - if (icsk->icsk_backoff < sysctl_tcp_retries2) + if (icsk->icsk_backoff < net->ipv4.sysctl_tcp_retries2) icsk->icsk_backoff++; icsk->icsk_probes_out++; probe_max = TCP_RTO_MAX; diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6694e33149b9..09f4e0297e56 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -22,7 +22,6 @@ #include #include -int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; int sysctl_tcp_orphan_retries __read_mostly; int sysctl_tcp_thin_linear_timeouts __read_mostly; @@ -189,7 +188,7 @@ static int tcp_write_timeout(struct sock *sk) dst_negative_advice(sk); } - retry_until = sysctl_tcp_retries2; + retry_until = net->ipv4.sysctl_tcp_retries2; if (sock_flag(sk, SOCK_DEAD)) { const bool alive = icsk->icsk_rto < TCP_RTO_MAX; @@ -303,7 +302,7 @@ static void tcp_probe_timer(struct sock *sk) (s32)(tcp_time_stamp - start_ts) > icsk->icsk_user_timeout) goto abort; - max_probes = sysctl_tcp_retries2; + max_probes = sock_net(sk)->ipv4.sysctl_tcp_retries2; if (sock_flag(sk, SOCK_DEAD)) { const bool alive = inet_csk_rto_backoff(icsk, TCP_RTO_MAX) < TCP_RTO_MAX; -- cgit From c402d9beffb6141ab2e4d2ad8be71128803a28ca Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:55 +0200 Subject: ipv4: Namespaceify tcp_orphan_retries sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + include/net/tcp.h | 1 - net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_timer.c | 3 +-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index d92c8e5d0fbc..080230321985 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -104,6 +104,7 @@ struct netns_ipv4 { int sysctl_tcp_reordering; int sysctl_tcp_retries1; int sysctl_tcp_retries2; + int sysctl_tcp_orphan_retries; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index a786cfa6301b..71f840b89c76 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -240,7 +240,6 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_fin_timeout; -extern int sysctl_tcp_orphan_retries; extern int sysctl_tcp_fastopen; extern int sysctl_tcp_retrans_collapse; extern int sysctl_tcp_stdurg; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 8e339d43619c..b7af6336985f 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -419,13 +419,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, - { - .procname = "tcp_orphan_retries", - .data = &sysctl_tcp_orphan_retries, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { .procname = "tcp_fack", .data = &sysctl_tcp_fack, @@ -960,6 +953,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_orphan_retries", + .data = &init_net.ipv4.sysctl_tcp_orphan_retries, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { } }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0710e6108a5e..1240dd62eee1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2393,6 +2393,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH; net->ipv4.sysctl_tcp_retries1 = TCP_RETR1; net->ipv4.sysctl_tcp_retries2 = TCP_RETR2; + net->ipv4.sysctl_tcp_orphan_retries = 0; return 0; fail: diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 09f4e0297e56..49bc474f8e35 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -22,7 +22,6 @@ #include #include -int sysctl_tcp_orphan_retries __read_mostly; int sysctl_tcp_thin_linear_timeouts __read_mostly; static void tcp_write_err(struct sock *sk) @@ -78,7 +77,7 @@ static int tcp_out_of_resources(struct sock *sk, bool do_reset) /* Calculate maximal number or retries on an orphaned socket. */ static int tcp_orphan_retries(struct sock *sk, bool alive) { - int retries = sysctl_tcp_orphan_retries; /* May be zero. */ + int retries = sock_net(sk)->ipv4.sysctl_tcp_orphan_retries; /* May be zero. */ /* We know from an ICMP that something is wrong. */ if (sk->sk_err_soft && !alive) -- cgit From 1e579caa18b96f9eb18f4f5416658cd15f37c062 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:56 +0200 Subject: ipv4: Namespaceify tcp_fin_timeout sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + include/net/tcp.h | 3 +-- net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp.c | 7 +++---- net/ipv4/tcp_ipv4.c | 1 + 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 080230321985..de5ff4385e84 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -105,6 +105,7 @@ struct netns_ipv4 { int sysctl_tcp_retries1; int sysctl_tcp_retries2; int sysctl_tcp_orphan_retries; + int sysctl_tcp_fin_timeout; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index 71f840b89c76..3f160c2e6960 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -239,7 +239,6 @@ extern struct inet_timewait_death_row tcp_death_row; extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; -extern int sysctl_tcp_fin_timeout; extern int sysctl_tcp_fastopen; extern int sysctl_tcp_retrans_collapse; extern int sysctl_tcp_stdurg; @@ -1249,7 +1248,7 @@ static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp) static inline int tcp_fin_time(const struct sock *sk) { - int fin_timeout = tcp_sk(sk)->linger2 ? : sysctl_tcp_fin_timeout; + int fin_timeout = tcp_sk(sk)->linger2 ? : sock_net(sk)->ipv4.sysctl_tcp_fin_timeout; const int rto = inet_csk(sk)->icsk_rto; if (fin_timeout < (rto << 2) - (rto >> 1)) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index b7af6336985f..8bd335a2cba8 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -319,13 +319,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "tcp_fin_timeout", - .data = &sysctl_tcp_fin_timeout, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, { .procname = "tcp_fastopen", .data = &sysctl_tcp_fastopen, @@ -960,6 +953,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_fin_timeout", + .data = &init_net.ipv4.sysctl_tcp_fin_timeout, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_jiffies, + }, { } }; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f4db6b04cdb4..014f18e2f7b3 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -282,8 +282,6 @@ #include #include -int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; - int sysctl_tcp_min_tso_segs __read_mostly = 2; int sysctl_tcp_autocorking __read_mostly = 1; @@ -2330,6 +2328,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); + struct net *net = sock_net(sk); int val; int err = 0; @@ -2526,7 +2525,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, case TCP_LINGER2: if (val < 0) tp->linger2 = -1; - else if (val > sysctl_tcp_fin_timeout / HZ) + else if (val > net->ipv4.sysctl_tcp_fin_timeout / HZ) tp->linger2 = 0; else tp->linger2 = val * HZ; @@ -2771,7 +2770,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, case TCP_LINGER2: val = tp->linger2; if (val >= 0) - val = (val ? : sysctl_tcp_fin_timeout) / HZ; + val = (val ? : net->ipv4.sysctl_tcp_fin_timeout) / HZ; break; case TCP_DEFER_ACCEPT: val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1240dd62eee1..36c83c28d9c9 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2394,6 +2394,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_retries1 = TCP_RETR1; net->ipv4.sysctl_tcp_retries2 = TCP_RETR2; net->ipv4.sysctl_tcp_orphan_retries = 0; + net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT; return 0; fail: -- cgit From 4979f2d9f7262b9b180bc83de8d70f7a7721c085 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Feb 2016 09:46:57 +0200 Subject: ipv4: Namespaceify tcp_notsent_lowat sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/net/netns/ipv4.h | 1 + include/net/tcp.h | 4 ++-- net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp_ipv4.c | 1 + net/ipv4/tcp_output.c | 3 --- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index de5ff4385e84..4d6ec3f6fafe 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -106,6 +106,7 @@ struct netns_ipv4 { int sysctl_tcp_retries2; int sysctl_tcp_orphan_retries; int sysctl_tcp_fin_timeout; + unsigned int sysctl_tcp_notsent_lowat; struct ping_group_range ping_group_range; diff --git a/include/net/tcp.h b/include/net/tcp.h index 3f160c2e6960..9b2cb0c8d876 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -267,7 +267,6 @@ extern int sysctl_tcp_thin_dupack; extern int sysctl_tcp_early_retrans; extern int sysctl_tcp_limit_output_bytes; extern int sysctl_tcp_challenge_ack_limit; -extern unsigned int sysctl_tcp_notsent_lowat; extern int sysctl_tcp_min_tso_segs; extern int sysctl_tcp_min_rtt_wlen; extern int sysctl_tcp_autocorking; @@ -1682,7 +1681,8 @@ void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr); static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp) { - return tp->notsent_lowat ?: sysctl_tcp_notsent_lowat; + struct net *net = sock_net((struct sock *)tp); + return tp->notsent_lowat ?: net->ipv4.sysctl_tcp_notsent_lowat; } static inline bool tcp_stream_memory_free(const struct sock *sk) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 8bd335a2cba8..44bb59824267 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -455,13 +455,6 @@ static struct ctl_table ipv4_table[] = { .proc_handler = proc_dointvec_minmax, .extra1 = &one, }, - { - .procname = "tcp_notsent_lowat", - .data = &sysctl_tcp_notsent_lowat, - .maxlen = sizeof(sysctl_tcp_notsent_lowat), - .mode = 0644, - .proc_handler = proc_dointvec, - }, { .procname = "tcp_rmem", .data = &sysctl_tcp_rmem, @@ -960,6 +953,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec_jiffies, }, + { + .procname = "tcp_notsent_lowat", + .data = &init_net.ipv4.sysctl_tcp_notsent_lowat, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec, + }, { } }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 36c83c28d9c9..11ae706f53a1 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2395,6 +2395,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_retries2 = TCP_RETR2; net->ipv4.sysctl_tcp_orphan_retries = 0; net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT; + net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX; return 0; fail: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7beb3f688b7a..7d2c7a400456 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -62,9 +62,6 @@ int sysctl_tcp_tso_win_divisor __read_mostly = 3; /* By default, RFC2861 behavior. */ int sysctl_tcp_slow_start_after_idle __read_mostly = 1; -unsigned int sysctl_tcp_notsent_lowat __read_mostly = UINT_MAX; -EXPORT_SYMBOL(sysctl_tcp_notsent_lowat); - static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, int push_one, gfp_t gfp); -- cgit From 7a23f80eaae9c6b5175cd7a96634a91ed9928aff Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:48 +0200 Subject: watchdog: mei_wdt: register wd device only if required For Intel Broadwell and newer platforms, the ME device can inform the host whether the watchdog functionality is activated or not. If the watchdog functionality is not activated then the watchdog interface can be not registered and eliminate unnecessary pings and hence lower the power consumption by avoiding waking up the device. The feature can be deactivated also without reboot in that case the watchdog device should be unregistered at runtime. The information regarding the deactivation is reported in the ping response command. In runtime case the unregistration has to be run from a worker so that the ping initiated by the watchdog core completes. Otherwise the flow will deadlock on watchdog core mutex which both ping and unregistration acquire. Reviewed-by: Guenter Roeck Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 200 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 191 insertions(+), 9 deletions(-) diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index e7e3f144f2b0..9addf8902f74 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -38,27 +39,35 @@ /* Sub Commands */ #define MEI_MC_START_WD_TIMER_REQ 0x13 +#define MEI_MC_START_WD_TIMER_RES 0x83 +#define MEI_WDT_STATUS_SUCCESS 0 +#define MEI_WDT_WDSTATE_NOT_REQUIRED 0x1 #define MEI_MC_STOP_WD_TIMER_REQ 0x14 /** * enum mei_wdt_state - internal watchdog state * + * @MEI_WDT_PROBE: wd in probing stage * @MEI_WDT_IDLE: wd is idle and not opened * @MEI_WDT_START: wd was opened, start was called * @MEI_WDT_RUNNING: wd is expecting keep alive pings * @MEI_WDT_STOPPING: wd is stopping and will move to IDLE + * @MEI_WDT_NOT_REQUIRED: wd device is not required */ enum mei_wdt_state { + MEI_WDT_PROBE, MEI_WDT_IDLE, MEI_WDT_START, MEI_WDT_RUNNING, MEI_WDT_STOPPING, + MEI_WDT_NOT_REQUIRED, }; -#if IS_ENABLED(CONFIG_DEBUG_FS) static const char *mei_wdt_state_str(enum mei_wdt_state state) { switch (state) { + case MEI_WDT_PROBE: + return "PROBE"; case MEI_WDT_IDLE: return "IDLE"; case MEI_WDT_START: @@ -67,11 +76,12 @@ static const char *mei_wdt_state_str(enum mei_wdt_state state) return "RUNNING"; case MEI_WDT_STOPPING: return "STOPPING"; + case MEI_WDT_NOT_REQUIRED: + return "NOT_REQUIRED"; default: return "unknown"; } } -#endif /* CONFIG_DEBUG_FS */ /** * struct mei_wdt - mei watchdog driver @@ -79,6 +89,10 @@ static const char *mei_wdt_state_str(enum mei_wdt_state state) * * @cldev: mei watchdog client device * @state: watchdog internal state + * @resp_required: ping required response + * @response: ping response completion + * @unregister: unregister worker + * @reg_lock: watchdog device registration lock * @timeout: watchdog current timeout * * @dbgfs_dir: debugfs dir entry @@ -88,6 +102,10 @@ struct mei_wdt { struct mei_cl_device *cldev; enum mei_wdt_state state; + bool resp_required; + struct completion response; + struct work_struct unregister; + struct mutex reg_lock; u16 timeout; #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -123,6 +141,19 @@ struct mei_wdt_start_request { u8 reserved[17]; } __packed; +/** + * struct mei_wdt_start_response watchdog start/ping response + * + * @hdr: Management Control Command Header + * @status: operation status + * @wdstate: watchdog status bit mask + */ +struct mei_wdt_start_response { + struct mei_mc_hdr hdr; + u8 status; + u8 wdstate; +} __packed; + /** * struct mei_wdt_stop_request - watchdog stop * @@ -244,13 +275,18 @@ static int mei_wdt_ops_ping(struct watchdog_device *wdd) if (wdt->state != MEI_WDT_START && wdt->state != MEI_WDT_RUNNING) return 0; + if (wdt->resp_required) + init_completion(&wdt->response); + + wdt->state = MEI_WDT_RUNNING; ret = mei_wdt_ping(wdt); if (ret) return ret; - wdt->state = MEI_WDT_RUNNING; + if (wdt->resp_required) + ret = wait_for_completion_killable(&wdt->response); - return 0; + return ret; } /** @@ -290,6 +326,19 @@ static struct watchdog_info wd_info = { WDIOF_ALARMONLY, }; +/** + * __mei_wdt_is_registered - check if wdt is registered + * + * @wdt: mei watchdog device + * + * Return: true if the wdt is registered with the watchdog subsystem + * Locking: should be called under wdt->reg_lock + */ +static inline bool __mei_wdt_is_registered(struct mei_wdt *wdt) +{ + return !!watchdog_get_drvdata(&wdt->wdd); +} + /** * mei_wdt_unregister - unregister from the watchdog subsystem * @@ -297,8 +346,15 @@ static struct watchdog_info wd_info = { */ static void mei_wdt_unregister(struct mei_wdt *wdt) { - watchdog_unregister_device(&wdt->wdd); - watchdog_set_drvdata(&wdt->wdd, NULL); + mutex_lock(&wdt->reg_lock); + + if (__mei_wdt_is_registered(wdt)) { + watchdog_unregister_device(&wdt->wdd); + watchdog_set_drvdata(&wdt->wdd, NULL); + memset(&wdt->wdd, 0, sizeof(wdt->wdd)); + } + + mutex_unlock(&wdt->reg_lock); } /** @@ -318,6 +374,13 @@ static int mei_wdt_register(struct mei_wdt *wdt) dev = &wdt->cldev->dev; + mutex_lock(&wdt->reg_lock); + + if (__mei_wdt_is_registered(wdt)) { + ret = 0; + goto out; + } + wdt->wdd.info = &wd_info; wdt->wdd.ops = &wd_ops; wdt->wdd.parent = dev; @@ -332,9 +395,106 @@ static int mei_wdt_register(struct mei_wdt *wdt) watchdog_set_drvdata(&wdt->wdd, NULL); } + wdt->state = MEI_WDT_IDLE; + +out: + mutex_unlock(&wdt->reg_lock); return ret; } +static void mei_wdt_unregister_work(struct work_struct *work) +{ + struct mei_wdt *wdt = container_of(work, struct mei_wdt, unregister); + + mei_wdt_unregister(wdt); +} + +/** + * mei_wdt_event_rx - callback for data receive + * + * @cldev: bus device + */ +static void mei_wdt_event_rx(struct mei_cl_device *cldev) +{ + struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + struct mei_wdt_start_response res; + const size_t res_len = sizeof(res); + int ret; + + ret = mei_cldev_recv(wdt->cldev, (u8 *)&res, res_len); + if (ret < 0) { + dev_err(&cldev->dev, "failure in recv %d\n", ret); + return; + } + + /* Empty response can be sent on stop */ + if (ret == 0) + return; + + if (ret < sizeof(struct mei_mc_hdr)) { + dev_err(&cldev->dev, "recv small data %d\n", ret); + return; + } + + if (res.hdr.command != MEI_MANAGEMENT_CONTROL || + res.hdr.versionnumber != MEI_MC_VERSION_NUMBER) { + dev_err(&cldev->dev, "wrong command received\n"); + return; + } + + if (res.hdr.subcommand != MEI_MC_START_WD_TIMER_RES) { + dev_warn(&cldev->dev, "unsupported command %d :%s[%d]\n", + res.hdr.subcommand, + mei_wdt_state_str(wdt->state), + wdt->state); + return; + } + + /* Run the unregistration in a worker as this can be + * run only after ping completion, otherwise the flow will + * deadlock on watchdog core mutex. + */ + if (wdt->state == MEI_WDT_RUNNING) { + if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) { + wdt->state = MEI_WDT_NOT_REQUIRED; + schedule_work(&wdt->unregister); + } + goto out; + } + + if (wdt->state == MEI_WDT_PROBE) { + if (res.wdstate & MEI_WDT_WDSTATE_NOT_REQUIRED) { + wdt->state = MEI_WDT_NOT_REQUIRED; + } else { + /* stop the watchdog and register watchdog device */ + mei_wdt_stop(wdt); + mei_wdt_register(wdt); + } + return; + } + + dev_warn(&cldev->dev, "not in correct state %s[%d]\n", + mei_wdt_state_str(wdt->state), wdt->state); + +out: + if (!completion_done(&wdt->response)) + complete(&wdt->response); +} + +/** + * mei_wdt_event - callback for event receive + * + * @cldev: bus device + * @events: event mask + * @context: callback context + */ +static void mei_wdt_event(struct mei_cl_device *cldev, + u32 events, void *context) +{ + if (events & BIT(MEI_CL_EVENT_RX)) + mei_wdt_event_rx(cldev); +} + #if IS_ENABLED(CONFIG_DEBUG_FS) static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, @@ -403,8 +563,13 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, return -ENOMEM; wdt->timeout = MEI_WDT_DEFAULT_TIMEOUT; - wdt->state = MEI_WDT_IDLE; + wdt->state = MEI_WDT_PROBE; wdt->cldev = cldev; + wdt->resp_required = mei_cldev_ver(cldev) > 0x1; + mutex_init(&wdt->reg_lock); + init_completion(&wdt->response); + INIT_WORK(&wdt->unregister, mei_wdt_unregister_work); + mei_cldev_set_drvdata(cldev, wdt); ret = mei_cldev_enable(cldev); @@ -413,9 +578,20 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, goto err_out; } + ret = mei_cldev_register_event_cb(wdt->cldev, BIT(MEI_CL_EVENT_RX), + mei_wdt_event, NULL); + if (ret) { + dev_err(&cldev->dev, "Could not register event ret=%d\n", ret); + goto err_disable; + } + wd_info.firmware_version = mei_cldev_ver(cldev); - ret = mei_wdt_register(wdt); + if (wdt->resp_required) + ret = mei_wdt_ping(wdt); + else + ret = mei_wdt_register(wdt); + if (ret) goto err_disable; @@ -437,6 +613,12 @@ static int mei_wdt_remove(struct mei_cl_device *cldev) { struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + /* Free the caller in case of fw initiated or unexpected reset */ + if (!completion_done(&wdt->response)) + complete(&wdt->response); + + cancel_work_sync(&wdt->unregister); + mei_wdt_unregister(wdt); mei_cldev_disable(cldev); @@ -452,7 +634,7 @@ static int mei_wdt_remove(struct mei_cl_device *cldev) 0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB) static struct mei_cl_device_id mei_wdt_tbl[] = { - { .uuid = MEI_UUID_WD, .version = 0x1}, + { .uuid = MEI_UUID_WD, .version = MEI_CL_VERSION_ANY }, /* required last entry */ { } }; -- cgit From ad1cd720b18330599a9cabaf970095b74c9c3355 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:49 +0200 Subject: watchdog: mei_wdt: add activation debugfs entry Add entry for displaying whether the device has activated or deactivated watchdog fw application. cat /mei_wdt/activation activated | deactivated Reviewed-by: Guenter Roeck Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 9addf8902f74..b93474ec34a1 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -497,6 +497,28 @@ static void mei_wdt_event(struct mei_cl_device *cldev, #if IS_ENABLED(CONFIG_DEBUG_FS) +static ssize_t mei_dbgfs_read_activation(struct file *file, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct mei_wdt *wdt = file->private_data; + const size_t bufsz = 32; + char buf[32]; + ssize_t pos; + + mutex_lock(&wdt->reg_lock); + pos = scnprintf(buf, bufsz, "%s\n", + __mei_wdt_is_registered(wdt) ? "activated" : "deactivated"); + mutex_unlock(&wdt->reg_lock); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, pos); +} + +static const struct file_operations dbgfs_fops_activation = { + .open = simple_open, + .read = mei_dbgfs_read_activation, + .llseek = generic_file_llseek, +}; + static ssize_t mei_dbgfs_read_state(struct file *file, char __user *ubuf, size_t cnt, loff_t *ppos) { @@ -536,6 +558,11 @@ static int dbgfs_register(struct mei_wdt *wdt) if (!f) goto err; + f = debugfs_create_file("activation", S_IRUSR, + dir, wdt, &dbgfs_fops_activation); + if (!f) + goto err; + return 0; err: dbgfs_unregister(wdt); -- cgit From 3a20a5c339cce042e53557be067e121e4e984adf Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:50 +0200 Subject: watchdog: mei_wdt: re-register device on event For Intel SKL platform the ME device can inform the host via asynchronous notification that the watchdog feature was activated on the device. The activation doesn't require reboot. In that case the driver registers the watchdog device with the kernel. Reviewed-by: Guenter Roeck Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/watchdog/mei_wdt.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index b93474ec34a1..630bd189f167 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -481,6 +481,21 @@ out: complete(&wdt->response); } +/* + * mei_wdt_notify_event - callback for event notification + * + * @cldev: bus device + */ +static void mei_wdt_notify_event(struct mei_cl_device *cldev) +{ + struct mei_wdt *wdt = mei_cldev_get_drvdata(cldev); + + if (wdt->state != MEI_WDT_NOT_REQUIRED) + return; + + mei_wdt_register(wdt); +} + /** * mei_wdt_event - callback for event receive * @@ -493,6 +508,9 @@ static void mei_wdt_event(struct mei_cl_device *cldev, { if (events & BIT(MEI_CL_EVENT_RX)) mei_wdt_event_rx(cldev); + + if (events & BIT(MEI_CL_EVENT_NOTIF)) + mei_wdt_notify_event(cldev); } #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -605,9 +623,15 @@ static int mei_wdt_probe(struct mei_cl_device *cldev, goto err_out; } - ret = mei_cldev_register_event_cb(wdt->cldev, BIT(MEI_CL_EVENT_RX), + ret = mei_cldev_register_event_cb(wdt->cldev, + BIT(MEI_CL_EVENT_RX) | + BIT(MEI_CL_EVENT_NOTIF), mei_wdt_event, NULL); - if (ret) { + + /* on legacy devices notification is not supported + * this doesn't fail the registration for RX event + */ + if (ret && ret != -EOPNOTSUPP) { dev_err(&cldev->dev, "Could not register event ret=%d\n", ret); goto err_disable; } -- cgit From a96c548291719ae40da1b3c52493f40a63d3dd84 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 22:46:51 +0200 Subject: mei: trace pci configuration space io Use tracing events also for reading and writing pci configuration space /tracing/events/mei/mei_pci_reg_{read,write} Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me.c | 10 ++++++++-- drivers/misc/mei/hw-txe.c | 10 ++++++++-- drivers/misc/mei/mei-trace.c | 2 ++ drivers/misc/mei/mei-trace.h | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 25b1997a62cb..e2fb44cc5c37 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -189,8 +189,11 @@ static int mei_me_fw_status(struct mei_device *dev, fw_status->count = fw_src->count; for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) { - ret = pci_read_config_dword(pdev, - fw_src->status[i], &fw_status->status[i]); + ret = pci_read_config_dword(pdev, fw_src->status[i], + &fw_status->status[i]); + trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HSF_X", + fw_src->status[i], + fw_status->status[i]); if (ret) return ret; } @@ -215,6 +218,7 @@ static void mei_me_hw_config(struct mei_device *dev) reg = 0; pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg); hw->d0i3_supported = ((reg & PCI_CFG_HFS_1_D0I3_MSK) == PCI_CFG_HFS_1_D0I3_MSK); @@ -1248,6 +1252,7 @@ static bool mei_me_fw_type_nm(struct pci_dev *pdev) u32 reg; pci_read_config_dword(pdev, PCI_CFG_HFS_2, ®); + trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_2", PCI_CFG_HFS_2, reg); /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */ return (reg & 0x600) == 0x200; } @@ -1260,6 +1265,7 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev) u32 reg; /* Read ME FW Status check for SPS Firmware */ pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + trace_mei_pci_cfg_read(&pdev->dev, "PCI_CFG_HFS_1", PCI_CFG_HFS_1, reg); /* if bits [19:16] = 15, running SPS Firmware */ return (reg & 0xf0000) == 0xf0000; } diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index bae680c648ff..4a6c1b85f11e 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c @@ -28,6 +28,9 @@ #include "client.h" #include "hbm.h" +#include "mei-trace.h" + + /** * mei_txe_reg_read - Reads 32bit data from the txe device * @@ -640,8 +643,11 @@ static int mei_txe_fw_status(struct mei_device *dev, fw_status->count = fw_src->count; for (i = 0; i < fw_src->count && i < MEI_FW_STATUS_MAX; i++) { - ret = pci_read_config_dword(pdev, - fw_src->status[i], &fw_status->status[i]); + ret = pci_read_config_dword(pdev, fw_src->status[i], + &fw_status->status[i]); + trace_mei_pci_cfg_read(dev->dev, "PCI_CFG_HSF_X", + fw_src->status[i], + fw_status->status[i]); if (ret) return ret; } diff --git a/drivers/misc/mei/mei-trace.c b/drivers/misc/mei/mei-trace.c index 388efb519138..e19e6acb191b 100644 --- a/drivers/misc/mei/mei-trace.c +++ b/drivers/misc/mei/mei-trace.c @@ -22,4 +22,6 @@ EXPORT_TRACEPOINT_SYMBOL(mei_reg_read); EXPORT_TRACEPOINT_SYMBOL(mei_reg_write); +EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_read); +EXPORT_TRACEPOINT_SYMBOL(mei_pci_cfg_write); #endif /* __CHECKER__ */ diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h index 47e1bc6551d4..86e5068837c1 100644 --- a/drivers/misc/mei/mei-trace.h +++ b/drivers/misc/mei/mei-trace.h @@ -64,6 +64,44 @@ TRACE_EVENT(mei_reg_write, __get_str(dev), __entry->reg, __entry->offs, __entry->val) ); +TRACE_EVENT(mei_pci_cfg_read, + TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val), + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) + __field(const char *, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)) + __entry->reg = reg; + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] pci cfg read %s:[%#x] = %#x", + __get_str(dev), __entry->reg, __entry->offs, __entry->val) +); + +TRACE_EVENT(mei_pci_cfg_write, + TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val), + TP_ARGS(dev, reg, offs, val), + TP_STRUCT__entry( + __string(dev, dev_name(dev)) + __field(const char *, reg) + __field(u32, offs) + __field(u32, val) + ), + TP_fast_assign( + __assign_str(dev, dev_name(dev)) + __entry->reg = reg; + __entry->offs = offs; + __entry->val = val; + ), + TP_printk("[%s] pci cfg write %s[%#x] = %#x)", + __get_str(dev), __entry->reg, __entry->offs, __entry->val) +); + #endif /* _MEI_TRACE_H_ */ /* This part must be outside protection */ -- cgit From 98cb4ab09e772d791b7150c38574a024b9801b47 Mon Sep 17 00:00:00 2001 From: Jakob Østergaard Jensen Date: Sun, 7 Feb 2016 12:36:12 +0100 Subject: tty: serial: jsm_tty: fixed redundant variable issue. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable "len" gets assigned once and it's value copied to "n", which is then used for the rest of the function. This patch fixes the unnecessary variable reassignment by using "len" throughout the function instead. Signed-off-by: Jakob Østergaard Jensen Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/jsm/jsm_tty.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 00cac10ae75a..c5ddfe542451 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -529,7 +529,6 @@ void jsm_input(struct jsm_channel *ch) int data_len; unsigned long lock_flags; int len = 0; - int n = 0; int s = 0; int i = 0; @@ -597,16 +596,15 @@ void jsm_input(struct jsm_channel *ch) jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n"); len = tty_buffer_request_room(port, data_len); - n = len; /* - * n now contains the most amount of data we can copy, + * len now contains the most amount of data we can copy, * bounded either by the flip buffer size or the amount * of data the card actually has pending... */ - while (n) { + while (len) { s = ((head >= tail) ? head : RQUEUESIZE) - tail; - s = min(s, n); + s = min(s, len); if (s <= 0) break; @@ -637,7 +635,7 @@ void jsm_input(struct jsm_channel *ch) tty_insert_flip_string(port, ch->ch_rqueue + tail, s); } tail += s; - n -= s; + len -= s; /* Flip queue if needed */ tail &= rmask; } -- cgit From 26900254827878c4f98c0d169f8ba290099b1ef3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:17 +0200 Subject: mei: debugfs: adjust active clients print buffer In case of many active host clients clients (41 and more) 1K buffer is not enough for full information print. Calculate buffer size according to real clients number. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index a138d8a27ab5..9f5410b98688 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -50,6 +50,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf, } pos += scnprintf(buf + pos, bufsz - pos, HDR); +#undef HDR /* if the driver is not enabled the list won't be consistent */ if (dev->dev_state != MEI_DEV_ENABLED) @@ -90,23 +91,37 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf, { struct mei_device *dev = fp->private_data; struct mei_cl *cl; - const size_t bufsz = 1024; + size_t bufsz = 1; char *buf; int i = 0; int pos = 0; int ret; +#define HDR " |me|host|state|rd|wr|\n" + if (!dev) return -ENODEV; + mutex_lock(&dev->device_lock); + + /* + * if the driver is not enabled the list won't be consistent, + * we output empty table + */ + if (dev->dev_state == MEI_DEV_ENABLED) + list_for_each_entry(cl, &dev->file_list, link) + bufsz++; + + bufsz *= sizeof(HDR) + 1; + buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) + if (!buf) { + mutex_unlock(&dev->device_lock); return -ENOMEM; + } - pos += scnprintf(buf + pos, bufsz - pos, - " |me|host|state|rd|wr|\n"); - - mutex_lock(&dev->device_lock); + pos += scnprintf(buf + pos, bufsz - pos, HDR); +#undef HDR /* if the driver is not enabled the list won't be consistent */ if (dev->dev_state != MEI_DEV_ENABLED) @@ -115,7 +130,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf, list_for_each_entry(cl, &dev->file_list, link) { pos += scnprintf(buf + pos, bufsz - pos, - "%2d|%2d|%4d|%5d|%2d|%2d|\n", + "%3d|%2d|%4d|%5d|%2d|%2d|\n", i, mei_cl_me_id(cl), cl->host_client_id, cl->state, !list_empty(&cl->rd_completed), cl->writing_state); i++; -- cgit From 439a74b3373dab4214b4191d50dfb1d78be5b18e Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:18 +0200 Subject: mei: debugfs: allow hbm features list dump in earlier stages HBM features list is ready while sending enumerate request and enumerating clients, output it to debugfs in these states too. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index 9f5410b98688..6bdd75424fe8 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -165,7 +165,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, pos += scnprintf(buf + pos, bufsz - pos, "hbm: %s\n", mei_hbm_state_str(dev->hbm_state)); - if (dev->hbm_state == MEI_HBM_STARTED) { + if (dev->hbm_state >= MEI_HBM_ENUM_CLIENTS && + dev->hbm_state <= MEI_HBM_STARTED) { pos += scnprintf(buf + pos, bufsz - pos, "hbm features:\n"); pos += scnprintf(buf + pos, bufsz - pos, "\tPG: %01d\n", dev->hbm_f_pg_supported); -- cgit From f862b6b24f0ffd954633a55f39251a6873b664ca Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:19 +0200 Subject: mei: fix possible integer overflow issue There is a possible integer overflow following by a buffer overflow when accumulating messages coming from the FW to compose a full payload. Occurrence of wrap around has to be prevented for next message size calculation. For unsigned integer the addition overflow has occurred when the result is smaller than one of the arguments. To simplify the fix, the types of buf.size and buf_idx are set to the same width, namely size_t also to be aligned with the type of length parameter in file read/write ops. Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 5 ++--- drivers/misc/mei/client.c | 2 +- drivers/misc/mei/interrupt.c | 21 ++++++++++++++++----- drivers/misc/mei/main.c | 5 +++-- drivers/misc/mei/mei_dev.h | 4 ++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index cd0403f09267..b753df98b476 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -195,9 +195,8 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, * remove message from deletion list */ - dev_dbg(dev->dev, "amthif cb->buf size - %d\n", - cb->buf.size); - dev_dbg(dev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx); + dev_dbg(dev->dev, "amthif cb->buf.size - %zd cb->buf_idx - %zd\n", + cb->buf.size, cb->buf_idx); /* length is being truncated to PAGE_SIZE, however, * the buf_idx may point beyond */ diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index e069fcaed7aa..738f3d703323 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1569,7 +1569,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, return 0; } - cl_dbg(dev, cl, "buf: size = %d idx = %lu\n", + cl_dbg(dev, cl, "buf: size = %zd idx = %zd\n", cb->buf.size, cb->buf_idx); rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx); diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 6340dee33052..b8aa047ec258 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -104,6 +104,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; unsigned char *buffer = NULL; + size_t buf_sz; cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list); if (!cb) { @@ -124,11 +125,21 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, goto out; } - if (cb->buf.size < mei_hdr->length + cb->buf_idx) { - cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n", + buf_sz = mei_hdr->length + cb->buf_idx; + /* catch for integer overflow */ + if (buf_sz < cb->buf_idx) { + cl_err(dev, cl, "message is too big len %d idx %ld\n", + mei_hdr->length, cb->buf_idx); + + list_move_tail(&cb->list, &complete_list->list); + cb->status = -EMSGSIZE; + goto out; + } + + if (cb->buf.size < buf_sz) { + cl_dbg(dev, cl, "message overflow. size %zd len %d idx %zd\n", cb->buf.size, mei_hdr->length, cb->buf_idx); - buffer = krealloc(cb->buf.data, mei_hdr->length + cb->buf_idx, - GFP_KERNEL); + buffer = krealloc(cb->buf.data, buf_sz, GFP_KERNEL); if (!buffer) { cb->status = -ENOMEM; @@ -136,7 +147,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, goto out; } cb->buf.data = buffer; - cb->buf.size = mei_hdr->length + cb->buf_idx; + cb->buf.size = buf_sz; } buffer = cb->buf.data + cb->buf_idx; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 36ca15234344..47dc6d9ae655 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -226,7 +226,7 @@ copy_buffer: goto free; } - cl_dbg(dev, cl, "buf.size = %d buf.idx = %ld offset = %lld\n", + cl_dbg(dev, cl, "buf.size = %zd buf.idx = %zd offset = %lld\n", cb->buf.size, cb->buf_idx, *offset); if (*offset >= cb->buf_idx) { rets = 0; @@ -245,7 +245,8 @@ copy_buffer: rets = length; *offset += length; - if ((unsigned long)*offset < cb->buf_idx) + /* not all data was read, keep the cb */ + if (*offset < cb->buf_idx) goto out; free: diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index da613268480c..9b793f87b7d4 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -126,7 +126,7 @@ enum mei_cb_file_ops { * Intel MEI message data struct */ struct mei_msg_data { - u32 size; + size_t size; unsigned char *data; }; @@ -190,7 +190,7 @@ struct mei_cl_cb { struct mei_cl *cl; enum mei_cb_file_ops fop_type; struct mei_msg_data buf; - unsigned long buf_idx; + size_t buf_idx; unsigned long read_time; struct file *file_object; int status; -- cgit From 1f7e489a285c8b1aca9a7b66a55bbc95eb031721 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:20 +0200 Subject: mei: call stop on failed char device register If registering of character device failed stop the device properly. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 4 +++- drivers/misc/mei/pci-txe.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 75fc9c688df8..996344f6c32d 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -210,7 +210,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = mei_register(dev, &pdev->dev); if (err) - goto release_irq; + goto stop; pci_set_drvdata(pdev, dev); @@ -231,6 +231,8 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +stop: + mei_stop(dev); release_irq: mei_cancel_work(dev); mei_disable_interrupts(dev); diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index 71f8a7475717..30cc30683c07 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -154,7 +154,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err = mei_register(dev, &pdev->dev); if (err) - goto release_irq; + goto stop; pci_set_drvdata(pdev, dev); @@ -170,6 +170,8 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; +stop: + mei_stop(dev); release_irq: mei_cancel_work(dev); -- cgit From 5ba0bf476c792b91543da77e0bdec311b0eaa8f7 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:21 +0200 Subject: mei: amthif: don't copy from an empty buffer If empty message come from FW (buf_idx == 0) then the current code will still try to copy data from not filled buffer to the user-space, instead the code should behave the same as when end of a message has been reached, clean resources and return 0 Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index b753df98b476..c3f514027c80 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -185,7 +185,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, /* if the whole message will fit remove it from the list */ if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) list_del_init(&cb->list); - else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { + else if (cb->buf_idx <= *offset) { /* end of the message has been reached */ list_del_init(&cb->list); rets = 0; -- cgit From d0df8dfb8582f50053bde6a771262571daedf5d0 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:22 +0200 Subject: mei: amthif: don't drop read packets on timeout Since the driver now uses a list for storing read packets instead of single variable a pending read is no longer blocking other connections. A pending read will be discarded up the file closure. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 27 --------------------------- drivers/misc/mei/hw.h | 1 - drivers/misc/mei/interrupt.c | 32 -------------------------------- drivers/misc/mei/main.c | 16 ---------------- drivers/misc/mei/mei_dev.h | 4 ---- 5 files changed, 80 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index c3f514027c80..5da1654bc209 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -50,7 +50,6 @@ void mei_amthif_reset_params(struct mei_device *dev) dev->iamthif_current_cb = NULL; dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; dev->iamthif_stall_timer = 0; dev->iamthif_open_count = 0; } @@ -124,18 +123,10 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, int mei_amthif_read(struct mei_device *dev, struct file *file, char __user *ubuf, size_t length, loff_t *offset) { - struct mei_cl *cl = file->private_data; struct mei_cl_cb *cb; - unsigned long timeout; int rets; int wait_ret; - /* Only possible if we are in timeout */ - if (!cl) { - dev_err(dev->dev, "bad file ext.\n"); - return -ETIME; - } - dev_dbg(dev->dev, "checking amthif data\n"); cb = mei_amthif_find_read_list_entry(dev, file); @@ -168,20 +159,6 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, } dev_dbg(dev->dev, "Got amthif data\n"); - dev->iamthif_timer = 0; - - timeout = cb->read_time + - mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); - dev_dbg(dev->dev, "amthif timeout = %lud\n", - timeout); - - if (time_after(jiffies, timeout)) { - dev_dbg(dev->dev, "amthif Time out\n"); - /* 15 sec for the message has expired */ - list_del_init(&cb->list); - rets = -ETIME; - goto free; - } /* if the whole message will fit remove it from the list */ if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) list_del_init(&cb->list); @@ -303,7 +280,6 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; dev->iamthif_file_object = NULL; dev_dbg(dev->dev, "complete amthif cmd_list cb.\n"); @@ -462,9 +438,6 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) dev->iamthif_stall_timer = 0; list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); dev_dbg(dev->dev, "amthif read completed\n"); - dev->iamthif_timer = jiffies; - dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", - dev->iamthif_timer); } else { mei_amthif_run_next_cmd(dev); } diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 4cebde85924f..4c5d6cfd79b4 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -29,7 +29,6 @@ #define MEI_CLIENTS_INIT_TIMEOUT 15 /* HPS: Clients Enumeration Timeout */ #define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */ -#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */ #define MEI_PGI_TIMEOUT 1 /* PG Isolation time response 1 sec */ #define MEI_D0I3_TIMEOUT 5 /* D0i3 set/unset max response time */ diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index b8aa047ec258..78978193d19b 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -156,7 +156,6 @@ int mei_cl_irq_read_msg(struct mei_cl *cl, cb->buf_idx += mei_hdr->length; if (mei_hdr->msg_complete) { - cb->read_time = jiffies; cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx); list_move_tail(&cb->list, &complete_list->list); } else { @@ -458,7 +457,6 @@ static void mei_connect_timeout(struct mei_cl *cl) */ void mei_timer(struct work_struct *work) { - unsigned long timeout; struct mei_cl *cl; struct mei_device *dev = container_of(work, @@ -504,7 +502,6 @@ void mei_timer(struct work_struct *work) mei_reset(dev); dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_timer = 0; mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; @@ -514,35 +511,6 @@ void mei_timer(struct work_struct *work) } } - if (dev->iamthif_timer) { - - timeout = dev->iamthif_timer + - mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); - - dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", - dev->iamthif_timer); - dev_dbg(dev->dev, "timeout = %ld\n", timeout); - dev_dbg(dev->dev, "jiffies = %ld\n", jiffies); - if (time_after(jiffies, timeout)) { - /* - * User didn't read the AMTHI data on time (15sec) - * freeing AMTHI for other requests - */ - - dev_dbg(dev->dev, "freeing AMTHI for other requests\n"); - - mei_io_list_flush(&dev->amthif_rd_complete_list, - &dev->iamthif_cl); - mei_io_cb_free(dev->iamthif_current_cb); - dev->iamthif_current_cb = NULL; - - dev->iamthif_file_object->private_data = NULL; - dev->iamthif_file_object = NULL; - dev->iamthif_timer = 0; - mei_amthif_run_next_cmd(dev); - - } - } out: if (dev->dev_state != MEI_DEV_DISABLED) schedule_delayed_work(&dev->timer_work, 2 * HZ); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 47dc6d9ae655..5f2b63460d88 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -274,7 +274,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, struct mei_cl *cl = file->private_data; struct mei_cl_cb *write_cb = NULL; struct mei_device *dev; - unsigned long timeout = 0; int rets; if (WARN_ON(!cl || !cl->dev)) @@ -310,21 +309,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, goto out; } - if (cl == &dev->iamthif_cl) { - write_cb = mei_amthif_find_read_list_entry(dev, file); - - if (write_cb) { - timeout = write_cb->read_time + - mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); - - if (time_after(jiffies, timeout)) { - *offset = 0; - mei_io_cb_free(write_cb); - write_cb = NULL; - } - } - } - *offset = 0; write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); if (!write_cb) { diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 9b793f87b7d4..4d0e066703ef 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -179,7 +179,6 @@ struct mei_cl; * @fop_type: file operation type * @buf: buffer for data associated with the callback * @buf_idx: last read index - * @read_time: last read operation time stamp (iamthif) * @file_object: pointer to file structure * @status: io status of the cb * @internal: communication between driver and FW flag @@ -191,7 +190,6 @@ struct mei_cl_cb { enum mei_cb_file_ops fop_type; struct mei_msg_data buf; size_t buf_idx; - unsigned long read_time; struct file *file_object; int status; u32 internal:1; @@ -413,7 +411,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @iamthif_cl : amthif host client * @iamthif_current_cb : amthif current operation callback * @iamthif_open_count : number of opened amthif connections - * @iamthif_timer : time stamp of current amthif command completion * @iamthif_stall_timer : timer to detect amthif hang * @iamthif_state : amthif processor state * @iamthif_canceled : current amthif command is canceled @@ -504,7 +501,6 @@ struct mei_device { struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; - unsigned long iamthif_timer; u32 iamthif_stall_timer; enum iamthif_states iamthif_state; bool iamthif_canceled; -- cgit From f23e2cc4bb1d8bbbe02dcd3539ed531a3f40277c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:23 +0200 Subject: mei: constify struct file pointer The struct file file pointer is used as an opaque handle to for a connected client, for this part the pointer should be immutable and should be set to count. Reviewed-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 6 +++--- drivers/misc/mei/client.c | 12 +++++++----- drivers/misc/mei/client.h | 12 +++++++----- drivers/misc/mei/main.c | 4 ++-- drivers/misc/mei/mei_dev.h | 6 +++--- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 5da1654bc209..16cceedeed97 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -93,7 +93,7 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) * Return: returned a list entry on success, NULL on failure. */ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - struct file *file) + const struct file *file) { struct mei_cl_cb *cb; @@ -205,7 +205,7 @@ out: * * Return: 0 on success, <0 on failure. */ -static int mei_amthif_read_start(struct mei_cl *cl, struct file *file) +static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) { struct mei_device *dev = cl->dev; struct mei_cl_cb *cb; @@ -495,7 +495,7 @@ static bool mei_clear_list(struct mei_device *dev, * * Return: true if callback removed from the list, false otherwise */ -static bool mei_clear_lists(struct mei_device *dev, struct file *file) +static bool mei_clear_lists(struct mei_device *dev, const struct file *file) { bool removed = false; diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 738f3d703323..4c23caee04ab 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -359,7 +359,7 @@ void mei_io_cb_free(struct mei_cl_cb *cb) * Return: mei_cl_cb pointer or NULL; */ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, - struct file *fp) + const struct file *fp) { struct mei_cl_cb *cb; @@ -455,7 +455,8 @@ int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length) * Return: cb on success and NULL on failure */ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, - enum mei_cb_file_ops type, struct file *fp) + enum mei_cb_file_ops type, + const struct file *fp) { struct mei_cl_cb *cb; @@ -1028,7 +1029,7 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, * Return: 0 on success, <0 on failure. */ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, - struct file *file) + const struct file *file) { struct mei_device *dev; struct mei_cl_cb *cb; @@ -1277,7 +1278,8 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, * * Return: 0 on such and error otherwise. */ -int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request) +int mei_cl_notify_request(struct mei_cl *cl, + const struct file *file, u8 request) { struct mei_device *dev; struct mei_cl_cb *cb; @@ -1443,7 +1445,7 @@ static bool mei_cl_is_read_fc_cb(struct mei_cl *cl) * * Return: 0 on success, <0 on failure. */ -int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp) +int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp) { struct mei_device *dev; struct mei_cl_cb *cb; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 2e90a25f896e..fdc43279368f 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -83,7 +83,7 @@ static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl) * MEI IO Functions */ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, - struct file *fp); + const struct file *fp); void mei_io_cb_free(struct mei_cl_cb *priv_cb); int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length); @@ -116,7 +116,8 @@ struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp); void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp); struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, - enum mei_cb_file_ops type, struct file *fp); + enum mei_cb_file_ops type, + const struct file *fp); int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); /* @@ -213,10 +214,10 @@ void mei_cl_set_disconnected(struct mei_cl *cl); int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl, - struct file *file); + const struct file *file); int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); -int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp); +int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp); int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr, struct mei_cl_cb *cmpl_list); int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking); @@ -229,7 +230,8 @@ void mei_host_client_init(struct work_struct *work); u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop); enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request); -int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request); +int mei_cl_notify_request(struct mei_cl *cl, + const struct file *file, u8 request); int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 5f2b63460d88..03741c456ee4 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -435,7 +435,7 @@ end: * * Return: 0 on success , <0 on error */ -static int mei_ioctl_client_notify_request(struct file *file, u32 request) +static int mei_ioctl_client_notify_request(const struct file *file, u32 request) { struct mei_cl *cl = file->private_data; @@ -450,7 +450,7 @@ static int mei_ioctl_client_notify_request(struct file *file, u32 request) * * Return: 0 on success , <0 on error */ -static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get) +static int mei_ioctl_client_notify_get(const struct file *file, u32 *notify_get) { struct mei_cl *cl = file->private_data; bool notify_ev; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 4d0e066703ef..947e0a70577a 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -190,7 +190,7 @@ struct mei_cl_cb { enum mei_cb_file_ops fop_type; struct mei_msg_data buf; size_t buf_idx; - struct file *file_object; + const struct file *file_object; int status; u32 internal:1; u32 completed:1; @@ -497,7 +497,7 @@ struct mei_device { struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ struct mei_cl_cb amthif_rd_complete_list; - struct file *iamthif_file_object; + const struct file *iamthif_file_object; struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; @@ -590,7 +590,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev, int mei_amthif_release(struct mei_device *dev, struct file *file); struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - struct file *file); + const struct file *file); int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_amthif_run_next_cmd(struct mei_device *dev); -- cgit From 62e8e6ad60975df491d886efaa7fe0aa832947fb Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:24 +0200 Subject: mei: rename variable names 'file_object' to fp The driver uses three names file, fp, and file_object for struct file type. To improve code clarity and adjust to my taste rename file_object to more common and shorter fp. Reviewed-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 20 ++++++++++---------- drivers/misc/mei/client.c | 8 ++++---- drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/mei_dev.h | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 16cceedeed97..647edc68884f 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -98,7 +98,7 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, struct mei_cl_cb *cb; list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) - if (cb->file_object == file) + if (cb->fp == file) return cb; return NULL; } @@ -224,7 +224,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, const struct file *file) list_add_tail(&cb->list, &dev->ctrl_wr_list.list); dev->iamthif_state = MEI_IAMTHIF_READING; - dev->iamthif_file_object = cb->file_object; + dev->iamthif_fp = cb->fp; dev->iamthif_current_cb = cb; return 0; @@ -253,7 +253,7 @@ static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) dev->iamthif_state = MEI_IAMTHIF_WRITING; dev->iamthif_current_cb = cb; - dev->iamthif_file_object = cb->file_object; + dev->iamthif_fp = cb->fp; dev->iamthif_canceled = false; ret = mei_cl_write(cl, cb, false); @@ -261,7 +261,7 @@ static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb) return ret; if (cb->completed) - cb->status = mei_amthif_read_start(cl, cb->file_object); + cb->status = mei_amthif_read_start(cl, cb->fp); return 0; } @@ -280,7 +280,7 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) dev->iamthif_canceled = false; dev->iamthif_state = MEI_IAMTHIF_IDLE; - dev->iamthif_file_object = NULL; + dev->iamthif_fp = NULL; dev_dbg(dev->dev, "complete amthif cmd_list cb.\n"); @@ -338,7 +338,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev, poll_wait(file, &dev->iamthif_cl.wait, wait); if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && - dev->iamthif_file_object == file) { + dev->iamthif_fp == file) { mask |= POLLIN | POLLRDNORM; mei_amthif_run_next_cmd(dev); @@ -368,7 +368,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, return ret; if (cb->completed) - cb->status = mei_amthif_read_start(cl, cb->file_object); + cb->status = mei_amthif_read_start(cl, cb->fp); return 0; } @@ -469,7 +469,7 @@ static bool mei_clear_list(struct mei_device *dev, /* list all list member */ list_for_each_entry_safe(cb, next, mei_cb_list, list) { /* check if list member associated with a file */ - if (file == cb->file_object) { + if (file == cb->fp) { /* check if cb equal to current iamthif cb */ if (dev->iamthif_current_cb == cb) { dev->iamthif_current_cb = NULL; @@ -518,7 +518,7 @@ static bool mei_clear_lists(struct mei_device *dev, const struct file *file) /* check if iamthif_current_cb not NULL */ if (dev->iamthif_current_cb && !removed) { /* check file and iamthif current cb association */ - if (dev->iamthif_current_cb->file_object == file) { + if (dev->iamthif_current_cb->fp == file) { /* remove cb */ mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; @@ -541,7 +541,7 @@ int mei_amthif_release(struct mei_device *dev, struct file *file) if (dev->iamthif_open_count > 0) dev->iamthif_open_count--; - if (dev->iamthif_file_object == file && + if (dev->iamthif_fp == file && dev->iamthif_state != MEI_IAMTHIF_IDLE) { dev_dbg(dev->dev, "amthif canceled iamthif state %d\n", diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 4c23caee04ab..c57ac25ce8db 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -368,7 +368,7 @@ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type, return NULL; INIT_LIST_HEAD(&cb->list); - cb->file_object = fp; + cb->fp = fp; cb->cl = cl; cb->buf_idx = 0; cb->fop_type = type; @@ -486,7 +486,7 @@ struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp) struct mei_cl_cb *cb; list_for_each_entry(cb, &cl->rd_completed, list) - if (!fp || fp == cb->file_object) + if (!fp || fp == cb->fp) return cb; return NULL; @@ -504,12 +504,12 @@ void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp) struct mei_cl_cb *cb, *next; list_for_each_entry_safe(cb, next, &cl->rd_completed, list) - if (!fp || fp == cb->file_object) + if (!fp || fp == cb->fp) mei_io_cb_free(cb); list_for_each_entry_safe(cb, next, &cl->rd_pending, list) - if (!fp || fp == cb->file_object) + if (!fp || fp == cb->fp) mei_io_cb_free(cb); } diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 78978193d19b..37c8f0e14387 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -506,7 +506,7 @@ void mei_timer(struct work_struct *work) mei_io_cb_free(dev->iamthif_current_cb); dev->iamthif_current_cb = NULL; - dev->iamthif_file_object = NULL; + dev->iamthif_fp = NULL; mei_amthif_run_next_cmd(dev); } } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 947e0a70577a..3acbbb49d08c 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -179,7 +179,7 @@ struct mei_cl; * @fop_type: file operation type * @buf: buffer for data associated with the callback * @buf_idx: last read index - * @file_object: pointer to file structure + * @fp: pointer to file structure * @status: io status of the cb * @internal: communication between driver and FW flag * @completed: the transfer or reception has completed @@ -190,7 +190,7 @@ struct mei_cl_cb { enum mei_cb_file_ops fop_type; struct mei_msg_data buf; size_t buf_idx; - const struct file *file_object; + const struct file *fp; int status; u32 internal:1; u32 completed:1; @@ -407,7 +407,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * * @amthif_cmd_list : amthif list for cmd waiting * @amthif_rd_complete_list : amthif list for reading completed cmd data - * @iamthif_file_object : file for current amthif operation + * @iamthif_fp : file for current amthif operation * @iamthif_cl : amthif host client * @iamthif_current_cb : amthif current operation callback * @iamthif_open_count : number of opened amthif connections @@ -497,7 +497,7 @@ struct mei_device { struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ struct mei_cl_cb amthif_rd_complete_list; - const struct file *iamthif_file_object; + const struct file *iamthif_fp; struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; long iamthif_open_count; -- cgit From 5cf8b2a9be0abec35f675bc719ca6eba9e559b1d Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:25 +0200 Subject: mei: amthif: allow only one request at a time A next amthif write can be executed only after the previous one has completed. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 647edc68884f..4383a9ad9208 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -315,6 +315,14 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) dev = cl->dev; list_add_tail(&cb->list, &dev->amthif_cmd_list.list); + + /* + * The previous request is still in processing, queue this one. + */ + if (dev->iamthif_state > MEI_IAMTHIF_IDLE && + dev->iamthif_state < MEI_IAMTHIF_READ_COMPLETE) + return 0; + return mei_amthif_run_next_cmd(dev); } -- cgit From 9abd8b31292497530085156b41746e2a1cd9c934 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:26 +0200 Subject: mei: amthif: replace amthif_rd_complete_list with rd_completed Now when we have per client rd_completed list we can remove the amthif specific amthif_rd_complete_list. In addition in the function mei_amthif_read do not loop over the rd_completed list like the original code as the code path is unlocked. Reviewed-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 39 +++++++++++---------------------------- drivers/misc/mei/client.c | 1 - drivers/misc/mei/init.c | 1 - drivers/misc/mei/interrupt.c | 2 +- drivers/misc/mei/mei_dev.h | 7 +------ 5 files changed, 13 insertions(+), 37 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 4383a9ad9208..058dd6917805 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -84,26 +84,6 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) return ret; } -/** - * mei_amthif_find_read_list_entry - finds a amthilist entry for current file - * - * @dev: the device structure - * @file: pointer to file object - * - * Return: returned a list entry on success, NULL on failure. - */ -struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - const struct file *file) -{ - struct mei_cl_cb *cb; - - list_for_each_entry(cb, &dev->amthif_rd_complete_list.list, list) - if (cb->fp == file) - return cb; - return NULL; -} - - /** * mei_amthif_read - read data from AMTHIF client * @@ -123,12 +103,13 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, int mei_amthif_read(struct mei_device *dev, struct file *file, char __user *ubuf, size_t length, loff_t *offset) { + struct mei_cl *cl = file->private_data; struct mei_cl_cb *cb; int rets; int wait_ret; dev_dbg(dev->dev, "checking amthif data\n"); - cb = mei_amthif_find_read_list_entry(dev, file); + cb = mei_cl_read_cb(cl, file); /* Check for if we can block or not*/ if (cb == NULL && file->f_flags & O_NONBLOCK) @@ -141,7 +122,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, mutex_unlock(&dev->device_lock); wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, - (cb = mei_amthif_find_read_list_entry(dev, file))); + !list_empty(&cl->rd_completed)); /* Locking again the Mutex */ mutex_lock(&dev->device_lock); @@ -149,7 +130,7 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, if (wait_ret) return -ERESTARTSYS; - dev_dbg(dev->dev, "woke up from sleep\n"); + cb = mei_cl_read_cb(cl, file); } if (cb->status) { @@ -420,11 +401,12 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, /** * mei_amthif_complete - complete amthif callback. * - * @dev: the device structure. + * @cl: host client * @cb: callback block. */ -void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) +void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) { + struct mei_device *dev = cl->dev; if (cb->fop_type == MEI_FOP_WRITE) { if (!cb->status) { @@ -436,7 +418,7 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) * in case of error enqueue the write cb to complete read list * so it can be propagated to the reader */ - list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); + list_add_tail(&cb->list, &cl->rd_completed); wake_up_interruptible(&dev->iamthif_cl.wait); return; } @@ -444,7 +426,7 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) if (!dev->iamthif_canceled) { dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; dev->iamthif_stall_timer = 0; - list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); + list_add_tail(&cb->list, &cl->rd_completed); dev_dbg(dev->dev, "amthif read completed\n"); } else { mei_amthif_run_next_cmd(dev); @@ -506,10 +488,11 @@ static bool mei_clear_list(struct mei_device *dev, static bool mei_clear_lists(struct mei_device *dev, const struct file *file) { bool removed = false; + struct mei_cl *cl = &dev->iamthif_cl; /* remove callbacks associated with a file */ mei_clear_list(dev, file, &dev->amthif_cmd_list.list); - if (mei_clear_list(dev, file, &dev->amthif_rd_complete_list.list)) + if (mei_clear_list(dev, file, &cl->rd_completed)) removed = true; mei_clear_list(dev, file, &dev->ctrl_rd_list.list); diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index c57ac25ce8db..32991684563b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -536,7 +536,6 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp) mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); - mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); mei_cl_read_cb_flush(cl, fp); diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 46a4302e5524..a1d978a82806 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -402,7 +402,6 @@ void mei_device_init(struct mei_device *dev, INIT_LIST_HEAD(&dev->iamthif_cl.link); mei_io_list_init(&dev->amthif_cmd_list); - mei_io_list_init(&dev->amthif_rd_complete_list); bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); dev->open_handle_count = 0; diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 37c8f0e14387..72806ef6efdd 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -48,7 +48,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list) dev_dbg(dev->dev, "completing call back.\n"); if (cl == &dev->iamthif_cl) - mei_amthif_complete(dev, cb); + mei_amthif_complete(cl, cb); else mei_cl_complete(cl, cb); } diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 3acbbb49d08c..81901967911d 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -406,7 +406,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @allow_fixed_address: allow user space to connect a fixed client * * @amthif_cmd_list : amthif list for cmd waiting - * @amthif_rd_complete_list : amthif list for reading completed cmd data * @iamthif_fp : file for current amthif operation * @iamthif_cl : amthif host client * @iamthif_current_cb : amthif current operation callback @@ -496,7 +495,6 @@ struct mei_device { /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; /* driver managed amthif list for reading completed amthif cmd data */ - struct mei_cl_cb amthif_rd_complete_list; const struct file *iamthif_fp; struct mei_cl iamthif_cl; struct mei_cl_cb *iamthif_current_cb; @@ -589,15 +587,12 @@ unsigned int mei_amthif_poll(struct mei_device *dev, int mei_amthif_release(struct mei_device *dev, struct file *file); -struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, - const struct file *file); - int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_amthif_run_next_cmd(struct mei_device *dev); int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); -void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); +void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb); int mei_amthif_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr, struct mei_cl_cb *complete_list); -- cgit From 77b007b1b50ef728be8252cbdf3f7e7e45b29bc5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:27 +0200 Subject: mei: amthif: drop parameter validation from mei_amthif_write Remove duplicated parameter validation from mei_amthif_write functions, The parameter check is already performed by the caller function mei_write Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 058dd6917805..911b663a8fdb 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -285,15 +285,7 @@ int mei_amthif_run_next_cmd(struct mei_device *dev) int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb) { - struct mei_device *dev; - - if (WARN_ON(!cl || !cl->dev)) - return -ENODEV; - - if (WARN_ON(!cb)) - return -EINVAL; - - dev = cl->dev; + struct mei_device *dev = cl->dev; list_add_tail(&cb->list, &dev->amthif_cmd_list.list); -- cgit From 4bddf56fc93c6ad7a451f15a69e3d89d49db0747 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:28 +0200 Subject: mei: amthif: use rx_wait queue also for amthif client Switch using cl->rx_wait wait queue also for amthif, there is nothing special about amthif in that matter in Rx flow. The cl->wait is reserved for hbm flows and asynchronous events Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 911b663a8fdb..b98eac389782 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -121,8 +121,8 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, /* unlock the Mutex */ mutex_unlock(&dev->device_lock); - wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, - !list_empty(&cl->rd_completed)); + wait_ret = wait_event_interruptible(cl->rx_wait, + !list_empty(&cl->rd_completed)); /* Locking again the Mutex */ mutex_lock(&dev->device_lock); @@ -316,7 +316,7 @@ unsigned int mei_amthif_poll(struct mei_device *dev, { unsigned int mask = 0; - poll_wait(file, &dev->iamthif_cl.wait, wait); + poll_wait(file, &dev->iamthif_cl.rx_wait, wait); if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && dev->iamthif_fp == file) { @@ -411,7 +411,7 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) * so it can be propagated to the reader */ list_add_tail(&cb->list, &cl->rd_completed); - wake_up_interruptible(&dev->iamthif_cl.wait); + wake_up_interruptible(&cl->rx_wait); return; } @@ -425,7 +425,7 @@ void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb) } dev_dbg(dev->dev, "completing amthif call back.\n"); - wake_up_interruptible(&dev->iamthif_cl.wait); + wake_up_interruptible(&cl->rx_wait); } /** -- cgit From b74d883138911b110cf8f5b7b94790e16bb56795 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:29 +0200 Subject: mei: amthif: interrupt reader on link reset In case of link reset all waiting readers should be interrupted. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index b98eac389782..ca2efc3602df 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -122,7 +122,8 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, mutex_unlock(&dev->device_lock); wait_ret = wait_event_interruptible(cl->rx_wait, - !list_empty(&cl->rd_completed)); + !list_empty(&cl->rd_completed) || + !mei_cl_is_connected(cl)); /* Locking again the Mutex */ mutex_lock(&dev->device_lock); @@ -130,6 +131,11 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, if (wait_ret) return -ERESTARTSYS; + if (!mei_cl_is_connected(cl)) { + rets = -EBUSY; + goto out; + } + cb = mei_cl_read_cb(cl, file); } -- cgit From a1f9ae2bd264e3aed95aacd0102bd22a0422b8d1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:30 +0200 Subject: mei: bus: fix RX event scheduling In this particular case this more correct and safer to check if the RX event is set in the event mask rather than query waitqueue_active Since the check is already performed in the mei_cl_bus_rx_event function, it is just required to check for its return value. Second, since we don't have exclusive waiter wake_up_interruptible_all is not used correctly here. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 13 +++++++++---- drivers/misc/mei/client.c | 6 ++---- drivers/misc/mei/mei_dev.h | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 0b05aa938799..a40d8e24ecda 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -252,23 +252,28 @@ void mei_cl_bus_notify_event(struct mei_cl *cl) } /** - * mei_cl_bus_rx_event - schedule rx evenet + * mei_cl_bus_rx_event - schedule rx event * * @cl: host client + * + * Return: true if event was scheduled + * false if the client is not waiting for event */ -void mei_cl_bus_rx_event(struct mei_cl *cl) +bool mei_cl_bus_rx_event(struct mei_cl *cl) { struct mei_cl_device *cldev = cl->cldev; if (!cldev || !cldev->event_cb) - return; + return false; if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX))) - return; + return false; set_bit(MEI_CL_EVENT_RX, &cldev->events); schedule_work(&cldev->event_work); + + return true; } /** diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 32991684563b..574f7394fb2b 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1735,10 +1735,8 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb) case MEI_FOP_READ: list_add_tail(&cb->list, &cl->rd_completed); - if (waitqueue_active(&cl->rx_wait)) - wake_up_interruptible_all(&cl->rx_wait); - else - mei_cl_bus_rx_event(cl); + if (!mei_cl_bus_rx_event(cl)) + wake_up_interruptible(&cl->rx_wait); break; case MEI_FOP_CONNECT: diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 81901967911d..be97b8f2a883 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -316,7 +316,7 @@ void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking); ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); -void mei_cl_bus_rx_event(struct mei_cl *cl); +bool mei_cl_bus_rx_event(struct mei_cl *cl); void mei_cl_bus_notify_event(struct mei_cl *cl); void mei_cl_bus_remove_devices(struct mei_device *bus); int mei_cl_bus_init(void); -- cgit From 850f8940a6a38563ff401073fd845414ab49c5ed Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 7 Feb 2016 23:35:31 +0200 Subject: mei: bus: fix notification event delivery Call wake_up cl->ev_wait only in case there is no bus client registered to the event notification. Second, since we don't have exclusive waiter wake_up_interruptible_all is not used correctly here. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 13 +++++++++---- drivers/misc/mei/client.c | 4 ++-- drivers/misc/mei/mei_dev.h | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index a40d8e24ecda..990f4f65c35e 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -230,25 +230,30 @@ static void mei_cl_bus_event_work(struct work_struct *work) * mei_cl_bus_notify_event - schedule notify cb on bus client * * @cl: host client + * + * Return: true if event was scheduled + * false if the client is not waiting for event */ -void mei_cl_bus_notify_event(struct mei_cl *cl) +bool mei_cl_bus_notify_event(struct mei_cl *cl) { struct mei_cl_device *cldev = cl->cldev; if (!cldev || !cldev->event_cb) - return; + return false; if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF))) - return; + return false; if (!cl->notify_ev) - return; + return false; set_bit(MEI_CL_EVENT_NOTIF, &cldev->events); schedule_work(&cldev->event_work); cl->notify_ev = false; + + return true; } /** diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 574f7394fb2b..3fd070a698ce 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1363,12 +1363,12 @@ void mei_cl_notify(struct mei_cl *cl) cl_dbg(dev, cl, "notify event"); cl->notify_ev = true; - wake_up_interruptible_all(&cl->ev_wait); + if (!mei_cl_bus_notify_event(cl)) + wake_up_interruptible(&cl->ev_wait); if (cl->ev_async) kill_fasync(&cl->ev_async, SIGIO, POLL_PRI); - mei_cl_bus_notify_event(cl); } /** diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index be97b8f2a883..70c4da015401 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -317,7 +317,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking); ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); bool mei_cl_bus_rx_event(struct mei_cl *cl); -void mei_cl_bus_notify_event(struct mei_cl *cl); +bool mei_cl_bus_notify_event(struct mei_cl *cl); void mei_cl_bus_remove_devices(struct mei_device *bus); int mei_cl_bus_init(void); void mei_cl_bus_exit(void); -- cgit From 15c13dfcad883a1e76b714480fb27be96247fd82 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:32 +0200 Subject: mei: bus: check if the device is enabled before data transfer The bus data transfer interface was missing the check if the device is in enabled state, this may lead to stack corruption during link reset. Cc: #4.0 Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 990f4f65c35e..83b084558ee5 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -53,6 +53,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } + if (!mei_cl_is_connected(cl)) { rets = -ENODEV; goto out; @@ -109,6 +114,10 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) bus = cl->dev; mutex_lock(&bus->device_lock); + if (bus->dev_state != MEI_DEV_ENABLED) { + rets = -ENODEV; + goto out; + } cb = mei_cl_read_cb(cl, NULL); if (cb) -- cgit From e8466b336adc20bacb597670e0a89e695626e000 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:33 +0200 Subject: mei: drop superfluous closing bracket from write traces Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/mei-trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h index 86e5068837c1..7d2d5d4a1624 100644 --- a/drivers/misc/mei/mei-trace.h +++ b/drivers/misc/mei/mei-trace.h @@ -60,7 +60,7 @@ TRACE_EVENT(mei_reg_write, __entry->offs = offs; __entry->val = val; ), - TP_printk("[%s] write %s[%#x] = %#x)", + TP_printk("[%s] write %s[%#x] = %#x", __get_str(dev), __entry->reg, __entry->offs, __entry->val) ); @@ -98,7 +98,7 @@ TRACE_EVENT(mei_pci_cfg_write, __entry->offs = offs; __entry->val = val; ), - TP_printk("[%s] pci cfg write %s[%#x] = %#x)", + TP_printk("[%s] pci cfg write %s[%#x] = %#x", __get_str(dev), __entry->reg, __entry->offs, __entry->val) ); -- cgit From 0faf6a3bbae74ca08c2ecc09e5f6d350ad54c1ab Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:34 +0200 Subject: mei: wake blocked write on link reset In case of link reset all blocked writes should be interrupted. Note, that currently blocking write is used only through bus layer. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 3fd070a698ce..5ddc690752c2 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1691,7 +1691,8 @@ out: mutex_unlock(&dev->device_lock); rets = wait_event_interruptible(cl->tx_wait, - cl->writing_state == MEI_WRITE_COMPLETE); + cl->writing_state == MEI_WRITE_COMPLETE || + (!mei_cl_is_connected(cl))); mutex_lock(&dev->device_lock); /* wait_event_interruptible returns -ERESTARTSYS */ if (rets) { @@ -1699,6 +1700,10 @@ out: rets = -EINTR; goto err; } + if (cl->writing_state != MEI_WRITE_COMPLETE) { + rets = -EFAULT; + goto err; + } } rets = size; -- cgit From a4307fe45aa9be03d5d7194b317a40b0d0558bee Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:35 +0200 Subject: mei: clean write queues and wake waiters on disconnect Clean write and write_waiting queues in disconnect. Requests in those queues are stale and processing will lead to fat warnings. In multi thread operations on disconnect and in FW disconnect case - write/read/event waiters should end wait and return error. Wake all waiters for disconnecting client to achieve that. Drop wake all and write queue clean on reset, as now we waking all waiters and cleaning write queues on disconnect. No need to do it twice. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 71 ++++++++++++++++++++--------------------------- drivers/misc/mei/client.h | 2 -- drivers/misc/mei/init.c | 5 ---- 3 files changed, 30 insertions(+), 48 deletions(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 5ddc690752c2..3a9c656f1425 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -719,6 +719,33 @@ bool mei_hbuf_acquire(struct mei_device *dev) return true; } +/** + * mei_cl_wake_all - wake up readers, writers and event waiters so + * they can be interrupted + * + * @cl: host client + */ +static void mei_cl_wake_all(struct mei_cl *cl) +{ + struct mei_device *dev = cl->dev; + + /* synchronized under device mutex */ + if (waitqueue_active(&cl->rx_wait)) { + cl_dbg(dev, cl, "Waking up reading client!\n"); + wake_up_interruptible(&cl->rx_wait); + } + /* synchronized under device mutex */ + if (waitqueue_active(&cl->tx_wait)) { + cl_dbg(dev, cl, "Waking up writing client!\n"); + wake_up_interruptible(&cl->tx_wait); + } + /* synchronized under device mutex */ + if (waitqueue_active(&cl->ev_wait)) { + cl_dbg(dev, cl, "Waking up waiting for event clients!\n"); + wake_up_interruptible(&cl->ev_wait); + } +} + /** * mei_cl_set_disconnected - set disconnected state and clear * associated states and resources @@ -734,8 +761,11 @@ void mei_cl_set_disconnected(struct mei_cl *cl) return; cl->state = MEI_FILE_DISCONNECTED; + mei_io_list_free(&dev->write_list, cl); + mei_io_list_free(&dev->write_waiting_list, cl); mei_io_list_flush(&dev->ctrl_rd_list, cl); mei_io_list_flush(&dev->ctrl_wr_list, cl); + mei_cl_wake_all(cl); cl->mei_flow_ctrl_creds = 0; cl->timer_count = 0; @@ -1770,44 +1800,3 @@ void mei_cl_all_disconnect(struct mei_device *dev) list_for_each_entry(cl, &dev->file_list, link) mei_cl_set_disconnected(cl); } - - -/** - * mei_cl_all_wakeup - wake up all readers and writers they can be interrupted - * - * @dev: mei device - */ -void mei_cl_all_wakeup(struct mei_device *dev) -{ - struct mei_cl *cl; - - list_for_each_entry(cl, &dev->file_list, link) { - if (waitqueue_active(&cl->rx_wait)) { - cl_dbg(dev, cl, "Waking up reading client!\n"); - wake_up_interruptible(&cl->rx_wait); - } - if (waitqueue_active(&cl->tx_wait)) { - cl_dbg(dev, cl, "Waking up writing client!\n"); - wake_up_interruptible(&cl->tx_wait); - } - - /* synchronized under device mutex */ - if (waitqueue_active(&cl->ev_wait)) { - cl_dbg(dev, cl, "Waking up waiting for event clients!\n"); - wake_up_interruptible(&cl->ev_wait); - } - } -} - -/** - * mei_cl_all_write_clear - clear all pending writes - * - * @dev: mei device - */ -void mei_cl_all_write_clear(struct mei_device *dev) -{ - mei_io_list_free(&dev->write_list, NULL); - mei_io_list_free(&dev->write_waiting_list, NULL); -} - - diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index fdc43279368f..9925cf1a91ef 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -238,8 +238,6 @@ int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); void mei_cl_notify(struct mei_cl *cl); void mei_cl_all_disconnect(struct mei_device *dev); -void mei_cl_all_wakeup(struct mei_device *dev); -void mei_cl_all_write_clear(struct mei_device *dev); #define MEI_CL_FMT "cl:host=%02d me=%02d " #define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl) diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index a1d978a82806..cfcb46da13f1 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -148,13 +148,8 @@ int mei_reset(struct mei_device *dev) state != MEI_DEV_POWER_UP) { /* remove all waiting requests */ - mei_cl_all_write_clear(dev); - mei_cl_all_disconnect(dev); - /* wake up all readers and writers so they can be interrupted */ - mei_cl_all_wakeup(dev); - /* remove entry if already in list */ dev_dbg(dev->dev, "remove iamthif from the file list.\n"); mei_cl_unlink(&dev->iamthif_cl); -- cgit From 603c53e42adf5f2d29ffdd1ff1edda0c27e400df Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:36 +0200 Subject: mei: discard replies from unconnected fixed address clients A fixed address client in the FW doesn't have a notion of connection and can send message after the file associated with it was already closed. Silently discard such messages. Add inline helpers to detect whether a message is hbm or intended for a fixed address client Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 72806ef6efdd..06b744a503a3 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -239,6 +239,16 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb, return 0; } +static inline bool hdr_is_hbm(struct mei_msg_hdr *mei_hdr) +{ + return mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0; +} + +static inline bool hdr_is_fixed(struct mei_msg_hdr *mei_hdr) +{ + return mei_hdr->host_addr == 0 && mei_hdr->me_addr != 0; +} + /** * mei_irq_read_handler - bottom half read routine after ISR to * handle the read processing. @@ -280,7 +290,7 @@ int mei_irq_read_handler(struct mei_device *dev, } /* HBM message */ - if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) { + if (hdr_is_hbm(mei_hdr)) { ret = mei_hbm_dispatch(dev, mei_hdr); if (ret) { dev_dbg(dev->dev, "mei_hbm_dispatch failed ret = %d\n", @@ -300,6 +310,14 @@ int mei_irq_read_handler(struct mei_device *dev, /* if no recipient cl was found we assume corrupted header */ if (&cl->link == &dev->file_list) { + /* A message for not connected fixed address clients + * should be silently discarded + */ + if (hdr_is_fixed(mei_hdr)) { + mei_irq_discard_msg(dev, mei_hdr); + ret = 0; + goto reset_slots; + } dev_err(dev->dev, "no destination client found 0x%08X\n", dev->rd_msg_hdr); ret = -EBADMSG; -- cgit From 06ee536bcb15ca12868289467762130fa0a426f3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:37 +0200 Subject: mei: fill file pointer in read cb for fixed address client The read callback created from a flow control request for a fixed address client have NULL in the file pointer. Fill the file pointer using a data from a write callback. This allows us to drop workaround introduced in: commit eeabfcf5a92a ("mei: connection to fixed address clients from user-space") Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 11 +- drivers/misc/mei/main.c | 5 - drivers/misc/mei/wd.c | 391 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 397 insertions(+), 10 deletions(-) create mode 100644 drivers/misc/mei/wd.c diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 3a9c656f1425..a27ae2deecb4 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1173,11 +1173,12 @@ err: /** * mei_cl_flow_ctrl_creds - checks flow_control credits for cl. * - * @cl: private data of the file object + * @cl: host client + * @fp: the file pointer associated with the pointer * * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. */ -static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) +static int mei_cl_flow_ctrl_creds(struct mei_cl *cl, const struct file *fp) { int rets; @@ -1188,7 +1189,7 @@ static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) return 1; if (mei_cl_is_fixed_address(cl)) { - rets = mei_cl_read_start(cl, mei_cl_mtu(cl), NULL); + rets = mei_cl_read_start(cl, mei_cl_mtu(cl), fp); if (rets && rets != -EBUSY) return rets; return 1; @@ -1568,7 +1569,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, first_chunk = cb->buf_idx == 0; - rets = first_chunk ? mei_cl_flow_ctrl_creds(cl) : 1; + rets = first_chunk ? mei_cl_flow_ctrl_creds(cl, cb->fp) : 1; if (rets < 0) return rets; @@ -1674,7 +1675,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) mei_hdr.msg_complete = 0; mei_hdr.internal = cb->internal; - rets = mei_cl_flow_ctrl_creds(cl); + rets = mei_cl_flow_ctrl_creds(cl, cb->fp); if (rets < 0) goto err; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 03741c456ee4..f1fdd65e9678 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -209,11 +209,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, cb = mei_cl_read_cb(cl, file); if (!cb) { - if (mei_cl_is_fixed_address(cl) && dev->allow_fixed_address) { - cb = mei_cl_read_cb(cl, NULL); - if (cb) - goto copy_buffer; - } rets = 0; goto out; } diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c new file mode 100644 index 000000000000..7d9b4ee42f65 --- /dev/null +++ b/drivers/misc/mei/wd.c @@ -0,0 +1,391 @@ +/* + * + * Intel Management Engine Interface (Intel MEI) Linux driver + * Copyright (c) 2003-2012, 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 + +#include "mei_dev.h" +#include "hbm.h" +#include "client.h" + +static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; +static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; + +/* + * AMT Watchdog Device + */ +#define INTEL_AMT_WATCHDOG_ID "INTCAMT" + +/* UUIDs for AMT F/W clients */ +const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, + 0x9D, 0xA9, 0x15, 0x14, 0xCB, + 0x32, 0xAB); + +static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) +{ + dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); + memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); + memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); +} + +/** + * mei_wd_host_init - connect to the watchdog client + * + * @dev: the device structure + * @me_cl: me client + * + * Return: -ENOTTY if wd client cannot be found + * -EIO if write has failed + * 0 on success + */ +int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) +{ + struct mei_cl *cl = &dev->wd_cl; + int ret; + + mei_cl_init(cl, dev); + + dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; + dev->wd_state = MEI_WD_IDLE; + + ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); + if (ret < 0) { + dev_info(dev->dev, "wd: failed link client\n"); + return ret; + } + + ret = mei_cl_connect(cl, me_cl, NULL); + if (ret) { + dev_err(dev->dev, "wd: failed to connect = %d\n", ret); + mei_cl_unlink(cl); + return ret; + } + + ret = mei_watchdog_register(dev); + if (ret) { + mei_cl_disconnect(cl); + mei_cl_unlink(cl); + } + return ret; +} + +/** + * mei_wd_send - sends watch dog message to fw. + * + * @dev: the device structure + * + * Return: 0 if success, + * -EIO when message send fails + * -EINVAL when invalid message is to be sent + * -ENODEV on flow control failure + */ +int mei_wd_send(struct mei_device *dev) +{ + struct mei_cl *cl = &dev->wd_cl; + struct mei_msg_hdr hdr; + int ret; + + hdr.host_addr = cl->host_client_id; + hdr.me_addr = mei_cl_me_id(cl); + hdr.msg_complete = 1; + hdr.reserved = 0; + hdr.internal = 0; + + if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) + hdr.length = MEI_WD_START_MSG_SIZE; + else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) + hdr.length = MEI_WD_STOP_MSG_SIZE; + else { + dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); + return -EINVAL; + } + + ret = mei_write_message(dev, &hdr, dev->wd_data); + if (ret) { + dev_err(dev->dev, "wd: write message failed\n"); + return ret; + } + + ret = mei_cl_flow_ctrl_reduce(cl); + if (ret) { + dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); + return ret; + } + + return 0; +} + +/** + * mei_wd_stop - sends watchdog stop message to fw. + * + * @dev: the device structure + * + * Return: 0 if success + * on error: + * -EIO when message send fails + * -EINVAL when invalid message is to be sent + * -ETIME on message timeout + */ +int mei_wd_stop(struct mei_device *dev) +{ + struct mei_cl *cl = &dev->wd_cl; + int ret; + + if (!mei_cl_is_connected(cl) || + dev->wd_state != MEI_WD_RUNNING) + return 0; + + memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); + + dev->wd_state = MEI_WD_STOPPING; + + ret = mei_cl_flow_ctrl_creds(cl, NULL); + if (ret < 0) + goto err; + + if (ret && mei_hbuf_acquire(dev)) { + ret = mei_wd_send(dev); + if (ret) + goto err; + dev->wd_pending = false; + } else { + dev->wd_pending = true; + } + + mutex_unlock(&dev->device_lock); + + ret = wait_event_timeout(dev->wait_stop_wd, + dev->wd_state == MEI_WD_IDLE, + msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); + mutex_lock(&dev->device_lock); + if (dev->wd_state != MEI_WD_IDLE) { + /* timeout */ + ret = -ETIME; + dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); + goto err; + } + dev_dbg(dev->dev, "wd: stop completed after %u msec\n", + MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); + return 0; +err: + return ret; +} + +/** + * mei_wd_ops_start - wd start command from the watchdog core. + * + * @wd_dev: watchdog device struct + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_start(struct watchdog_device *wd_dev) +{ + struct mei_device *dev; + struct mei_cl *cl; + int err = -ENODEV; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + cl = &dev->wd_cl; + + mutex_lock(&dev->device_lock); + + if (dev->dev_state != MEI_DEV_ENABLED) { + dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", + mei_dev_state_str(dev->dev_state)); + goto end_unlock; + } + + if (!mei_cl_is_connected(cl)) { + cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); + goto end_unlock; + } + + mei_wd_set_start_timeout(dev, dev->wd_timeout); + + err = 0; +end_unlock: + mutex_unlock(&dev->device_lock); + return err; +} + +/** + * mei_wd_ops_stop - wd stop command from the watchdog core. + * + * @wd_dev: watchdog device struct + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_stop(struct watchdog_device *wd_dev) +{ + struct mei_device *dev; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + mutex_lock(&dev->device_lock); + mei_wd_stop(dev); + mutex_unlock(&dev->device_lock); + + return 0; +} + +/** + * mei_wd_ops_ping - wd ping command from the watchdog core. + * + * @wd_dev: watchdog device struct + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_ping(struct watchdog_device *wd_dev) +{ + struct mei_device *dev; + struct mei_cl *cl; + int ret; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + cl = &dev->wd_cl; + + mutex_lock(&dev->device_lock); + + if (!mei_cl_is_connected(cl)) { + cl_err(dev, cl, "wd: not connected.\n"); + ret = -ENODEV; + goto end; + } + + dev->wd_state = MEI_WD_RUNNING; + + ret = mei_cl_flow_ctrl_creds(cl, NULL); + if (ret < 0) + goto end; + + /* Check if we can send the ping to HW*/ + if (ret && mei_hbuf_acquire(dev)) { + dev_dbg(dev->dev, "wd: sending ping\n"); + + ret = mei_wd_send(dev); + if (ret) + goto end; + dev->wd_pending = false; + } else { + dev->wd_pending = true; + } + +end: + mutex_unlock(&dev->device_lock); + return ret; +} + +/** + * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. + * + * @wd_dev: watchdog device struct + * @timeout: timeout value to set + * + * Return: 0 if success, negative errno code for failure + */ +static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, + unsigned int timeout) +{ + struct mei_device *dev; + + dev = watchdog_get_drvdata(wd_dev); + if (!dev) + return -ENODEV; + + /* Check Timeout value */ + if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) + return -EINVAL; + + mutex_lock(&dev->device_lock); + + dev->wd_timeout = timeout; + wd_dev->timeout = timeout; + mei_wd_set_start_timeout(dev, dev->wd_timeout); + + mutex_unlock(&dev->device_lock); + + return 0; +} + +/* + * Watchdog Device structs + */ +static const struct watchdog_ops wd_ops = { + .owner = THIS_MODULE, + .start = mei_wd_ops_start, + .stop = mei_wd_ops_stop, + .ping = mei_wd_ops_ping, + .set_timeout = mei_wd_ops_set_timeout, +}; +static const struct watchdog_info wd_info = { + .identity = INTEL_AMT_WATCHDOG_ID, + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_ALARMONLY, +}; + +static struct watchdog_device amt_wd_dev = { + .info = &wd_info, + .ops = &wd_ops, + .timeout = MEI_WD_DEFAULT_TIMEOUT, + .min_timeout = MEI_WD_MIN_TIMEOUT, + .max_timeout = MEI_WD_MAX_TIMEOUT, +}; + + +int mei_watchdog_register(struct mei_device *dev) +{ + + int ret; + + amt_wd_dev.parent = dev->dev; + /* unlock to perserve correct locking order */ + mutex_unlock(&dev->device_lock); + ret = watchdog_register_device(&amt_wd_dev); + mutex_lock(&dev->device_lock); + if (ret) { + dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", + ret); + return ret; + } + + dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); + watchdog_set_drvdata(&amt_wd_dev, dev); + return 0; +} + +void mei_watchdog_unregister(struct mei_device *dev) +{ + if (watchdog_get_drvdata(&amt_wd_dev) == NULL) + return; + + watchdog_set_drvdata(&amt_wd_dev, NULL); + watchdog_unregister_device(&amt_wd_dev); +} + -- cgit From f4e06246183f187d1327fdba18a797eb091a7d03 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:38 +0200 Subject: mei: fixed address clients for the new platforms Enable by default connection to fixed address clients from user-space for skylake and newer platform. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 31 +++++++++++++++++++++++++++++-- drivers/misc/mei/hbm.c | 4 ++++ drivers/misc/mei/hw.h | 6 ++++++ drivers/misc/mei/main.c | 18 ++++++++++++++---- drivers/misc/mei/mei_dev.h | 4 ++++ 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index 6bdd75424fe8..8ad406315741 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -176,6 +176,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, dev->hbm_f_dot_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tEV: %01d\n", dev->hbm_f_ev_supported); + pos += scnprintf(buf + pos, bufsz - pos, "\tFA: %01d\n", + dev->hbm_f_fa_supported); } pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n", @@ -191,6 +193,30 @@ static const struct file_operations mei_dbgfs_fops_devstate = { .llseek = generic_file_llseek, }; +static ssize_t mei_dbgfs_write_allow_fa(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct mei_device *dev; + int ret; + + dev = container_of(file->private_data, + struct mei_device, allow_fixed_address); + + ret = debugfs_write_file_bool(file, user_buf, count, ppos); + if (ret < 0) + return ret; + dev->override_fixed_address = true; + return ret; +} + +static const struct file_operations mei_dbgfs_fops_allow_fa = { + .open = simple_open, + .read = debugfs_read_file_bool, + .write = mei_dbgfs_write_allow_fa, + .llseek = generic_file_llseek, +}; + /** * mei_dbgfs_deregister - Remove the debugfs files and directories * @@ -240,8 +266,9 @@ int mei_dbgfs_register(struct mei_device *dev, const char *name) dev_err(dev->dev, "devstate: registration failed\n"); goto err; } - f = debugfs_create_bool("allow_fixed_address", S_IRUSR | S_IWUSR, dir, - &dev->allow_fixed_address); + f = debugfs_create_file("allow_fixed_address", S_IRUSR | S_IWUSR, dir, + &dev->allow_fixed_address, + &mei_dbgfs_fops_allow_fa); if (!f) { dev_err(dev->dev, "allow_fixed_address: registration failed\n"); goto err; diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index e7b7aad0999b..3915b8e8d0f1 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -979,6 +979,10 @@ static void mei_hbm_config_features(struct mei_device *dev) /* Notification Event Support */ if (dev->version.major_version >= HBM_MAJOR_VERSION_EV) dev->hbm_f_ev_supported = 1; + + /* Fixed Address Client Support */ + if (dev->version.major_version >= HBM_MAJOR_VERSION_FA) + dev->hbm_f_fa_supported = 1; } /** diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 4c5d6cfd79b4..459ad596df66 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -64,6 +64,12 @@ #define HBM_MINOR_VERSION_EV 0 #define HBM_MAJOR_VERSION_EV 2 +/* + * MEI version with fixed address client support + */ +#define HBM_MINOR_VERSION_FA 0 +#define HBM_MAJOR_VERSION_FA 2 + /* Host bus message command opcode */ #define MEI_HBM_CMD_OP_MSK 0x7f /* Host bus message command RESPONSE */ diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index f1fdd65e9678..58fa2c83ee39 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -369,12 +369,22 @@ static int mei_ioctl_connect_client(struct file *file, /* find ME client we're trying to connect to */ me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid); - if (!me_cl || - (me_cl->props.fixed_address && !dev->allow_fixed_address)) { + if (!me_cl) { dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n", &data->in_client_uuid); - mei_me_cl_put(me_cl); - return -ENOTTY; + rets = -ENOTTY; + goto end; + } + + if (me_cl->props.fixed_address) { + bool forbidden = dev->override_fixed_address ? + !dev->allow_fixed_address : !dev->hbm_f_fa_supported; + if (forbidden) { + dev_dbg(dev->dev, "Connection forbidden to FW Client UUID = %pUl\n", + &data->in_client_uuid); + rets = -ENOTTY; + goto end; + } } dev_dbg(dev->dev, "Connect to FW Client ID = %d\n", diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 70c4da015401..6d97f3335e22 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -396,6 +396,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @hbm_f_dc_supported : hbm feature dynamic clients * @hbm_f_dot_supported : hbm feature disconnect on timeout * @hbm_f_ev_supported : hbm feature event notification + * @hbm_f_fa_supported : hbm feature fixed address client * * @me_clients_rwsem: rw lock over me_clients list * @me_clients : list of FW clients @@ -404,6 +405,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @me_client_index : last FW client index in enumeration * * @allow_fixed_address: allow user space to connect a fixed client + * @override_fixed_address: force allow fixed address behavior * * @amthif_cmd_list : amthif list for cmd waiting * @iamthif_fp : file for current amthif operation @@ -483,6 +485,7 @@ struct mei_device { unsigned int hbm_f_dc_supported:1; unsigned int hbm_f_dot_supported:1; unsigned int hbm_f_ev_supported:1; + unsigned int hbm_f_fa_supported:1; struct rw_semaphore me_clients_rwsem; struct list_head me_clients; @@ -491,6 +494,7 @@ struct mei_device { unsigned long me_client_index; bool allow_fixed_address; + bool override_fixed_address; /* amthif list for cmd waiting */ struct mei_cl_cb amthif_cmd_list; -- cgit From 6938c1923f8ac6eb6d1c99b924d3e377201143ed Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:39 +0200 Subject: mei: hbm: warn about fw-initiated disconnect The FW can initiate client disconnection only because an error condition, hence it make sense to bump the debug message to the warning level to have an entery in the log. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.h | 3 +++ drivers/misc/mei/hbm.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 9925cf1a91ef..be6929620d61 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -245,6 +245,9 @@ void mei_cl_all_disconnect(struct mei_device *dev); #define cl_dbg(dev, cl, format, arg...) \ dev_dbg((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) +#define cl_warn(dev, cl, format, arg...) \ + dev_warn((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) + #define cl_err(dev, cl, format, arg...) \ dev_err((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg) diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 3915b8e8d0f1..a2f32b0eb649 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -866,7 +866,7 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev, cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req); if (cl) { - cl_dbg(dev, cl, "fw disconnect request received\n"); + cl_warn(dev, cl, "fw disconnect request received\n"); cl->state = MEI_FILE_DISCONNECTING; cl->timer_count = 0; -- cgit From 7851e008703e2f7073802e560293213e93dcdde6 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:40 +0200 Subject: mei: drop reserved host client ids The reserved host clients can be obsoleted now, a portion of the platforms is shipped without iAMT enabled, where the reservation is not relevant and for platforms with iAMT dynamic allocation is sufficient. Dropping reserved ids makes enumeration more flexible and generic Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 2 +- drivers/misc/mei/bus-fixup.c | 2 +- drivers/misc/mei/bus.c | 2 +- drivers/misc/mei/client.c | 15 +++++---------- drivers/misc/mei/client.h | 4 ++-- drivers/misc/mei/main.c | 2 +- drivers/misc/mei/mei_dev.h | 8 -------- 7 files changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index ca2efc3602df..de194ef573ee 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -71,7 +71,7 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) mei_cl_init(cl, dev); - ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID); + ret = mei_cl_link(cl); if (ret < 0) { dev_err(dev->dev, "amthif: failed cl_link %d\n", ret); return ret; diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index b87323f4bb14..e9e6ea3ab73c 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -239,7 +239,7 @@ static void mei_nfc(struct mei_cl_device *cldev) mutex_lock(&bus->device_lock); /* we need to connect to INFO GUID */ - cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY); + cl = mei_cl_alloc_linked(bus); if (IS_ERR(cl)) { ret = PTR_ERR(cl); cl = NULL; diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 83b084558ee5..bc18e5519da6 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -417,7 +417,7 @@ int mei_cldev_enable(struct mei_cl_device *cldev) if (!cl) { mutex_lock(&bus->device_lock); - cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY); + cl = mei_cl_alloc_linked(bus); mutex_unlock(&bus->device_lock); if (IS_ERR(cl)) return PTR_ERR(cl); diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index a27ae2deecb4..2890669b81f9 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -587,27 +587,23 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev) * mei_cl_link - allocate host id in the host map * * @cl: host client - * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one * * Return: 0 on success * -EINVAL on incorrect values * -EMFILE if open count exceeded. */ -int mei_cl_link(struct mei_cl *cl, int id) +int mei_cl_link(struct mei_cl *cl) { struct mei_device *dev; long open_handle_count; + int id; if (WARN_ON(!cl || !cl->dev)) return -EINVAL; dev = cl->dev; - /* If Id is not assigned get one*/ - if (id == MEI_HOST_CLIENT_ID_ANY) - id = find_first_zero_bit(dev->host_clients_map, - MEI_CLIENTS_MAX); - + id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); if (id >= MEI_CLIENTS_MAX) { dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX); return -EMFILE; @@ -1143,11 +1139,10 @@ nortpm: * mei_cl_alloc_linked - allocate and link host client * * @dev: the device structure - * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one * * Return: cl on success ERR_PTR on failure */ -struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id) +struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev) { struct mei_cl *cl; int ret; @@ -1158,7 +1153,7 @@ struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id) goto err; } - ret = mei_cl_link(cl, id); + ret = mei_cl_link(cl); if (ret) goto err; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index be6929620d61..a912ea686d97 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -107,10 +107,10 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev); void mei_cl_init(struct mei_cl *cl, struct mei_device *dev); -int mei_cl_link(struct mei_cl *cl, int id); +int mei_cl_link(struct mei_cl *cl); int mei_cl_unlink(struct mei_cl *cl); -struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id); +struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev); struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 58fa2c83ee39..17970163eacc 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -65,7 +65,7 @@ static int mei_open(struct inode *inode, struct file *file) goto err_unlock; } - cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY); + cl = mei_cl_alloc_linked(dev); if (IS_ERR(cl)) { err = PTR_ERR(cl); goto err_unlock; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 6d97f3335e22..320ddae5ee1e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -53,14 +53,6 @@ extern const uuid_le mei_amthif_guid; */ #define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1) -/* - * Internal Clients Number - */ -#define MEI_HOST_CLIENT_ID_ANY (-1) -#define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ -#define MEI_IAMTHIF_HOST_CLIENT_ID 2 - - /* File state */ enum file_state { MEI_FILE_INITIALIZING = 0, -- cgit From a816a00ece63d16ade7e9c0ca8b5a7e4c5ea2453 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:41 +0200 Subject: mei: bus: run rescan on me_clients list change Since clients can be now added and removed during runtime we need to run bus rescan whenever me_clients list is modified. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 8 ++++++++ drivers/misc/mei/hbm.c | 8 +++++++- drivers/misc/mei/init.c | 2 ++ drivers/misc/mei/mei_dev.h | 3 +++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index bc18e5519da6..951d32265040 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -977,6 +977,14 @@ void mei_cl_bus_rescan(struct mei_device *bus) dev_dbg(bus->dev, "rescan end"); } +void mei_cl_bus_rescan_work(struct work_struct *work) +{ + struct mei_device *bus = + container_of(work, struct mei_device, bus_rescan_work); + + mei_cl_bus_rescan(bus); +} + int __mei_cldev_driver_register(struct mei_cl_driver *cldrv, struct module *owner) { diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index a2f32b0eb649..0c9310ad6136 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -401,6 +401,9 @@ static int mei_hbm_fw_add_cl_req(struct mei_device *dev, if (ret) status = !MEI_HBMS_SUCCESS; + if (dev->dev_state == MEI_DEV_ENABLED) + schedule_work(&dev->bus_rescan_work); + return mei_hbm_add_cl_resp(dev, req->me_addr, status); } @@ -789,8 +792,11 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl, cl->state = MEI_FILE_CONNECTED; else { cl->state = MEI_FILE_DISCONNECT_REPLY; - if (rs->status == MEI_CL_CONN_NOT_FOUND) + if (rs->status == MEI_CL_CONN_NOT_FOUND) { mei_me_cl_del(dev, cl->me_cl); + if (dev->dev_state == MEI_DEV_ENABLED) + schedule_work(&dev->bus_rescan_work); + } } cl->status = mei_cl_conn_status_to_errno(rs->status); } diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index cfcb46da13f1..52fde2b498ef 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -93,6 +93,7 @@ void mei_cancel_work(struct mei_device *dev) { cancel_work_sync(&dev->init_work); cancel_work_sync(&dev->reset_work); + cancel_work_sync(&dev->bus_rescan_work); cancel_delayed_work(&dev->timer_work); } @@ -394,6 +395,7 @@ void mei_device_init(struct mei_device *dev, INIT_DELAYED_WORK(&dev->timer_work, mei_timer); INIT_WORK(&dev->init_work, mei_host_client_init); INIT_WORK(&dev->reset_work, mei_reset_work); + INIT_WORK(&dev->bus_rescan_work, mei_cl_bus_rescan_work); INIT_LIST_HEAD(&dev->iamthif_cl.link); mei_io_list_init(&dev->amthif_cmd_list); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 320ddae5ee1e..c31adb8a0cff 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -304,6 +304,7 @@ struct mei_hw_ops { /* MEI bus API*/ void mei_cl_bus_rescan(struct mei_device *bus); +void mei_cl_bus_rescan_work(struct work_struct *work); void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking); @@ -410,6 +411,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * * @init_work : work item for the device init * @reset_work : work item for the device reset + * @bus_rescan_work : work item for the bus rescan * * @device_list : mei client bus list * @cl_bus_lock : client bus list lock @@ -501,6 +503,7 @@ struct mei_device { struct work_struct init_work; struct work_struct reset_work; + struct work_struct bus_rescan_work; /* List of bus devices */ struct list_head device_list; -- cgit From 27f476ea98ed495839662db4e3a76357bbeb1bb3 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:42 +0200 Subject: mei: hbm: send immediate reply flag in enum request Signal the FW that it can send an HBM enumeration answer immediately, without waiting for FW initialization completion, meaning before all the FW clients are ready and registered. Organize enumeration response options to enum as a byproduct. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/debugfs.c | 2 ++ drivers/misc/mei/hbm.c | 8 +++++++- drivers/misc/mei/hw.h | 25 +++++++++++++++++++++---- drivers/misc/mei/mei_dev.h | 2 ++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c index 8ad406315741..c6c051b52f55 100644 --- a/drivers/misc/mei/debugfs.c +++ b/drivers/misc/mei/debugfs.c @@ -172,6 +172,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf, dev->hbm_f_pg_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tDC: %01d\n", dev->hbm_f_dc_supported); + pos += scnprintf(buf + pos, bufsz - pos, "\tIE: %01d\n", + dev->hbm_f_ie_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tDOT: %01d\n", dev->hbm_f_dot_supported); pos += scnprintf(buf + pos, bufsz - pos, "\tEV: %01d\n", diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 0c9310ad6136..d2798d5b0a9d 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -301,7 +301,10 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev) enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data; memset(enum_req, 0, len); enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; - enum_req->allow_add = dev->hbm_f_dc_supported; + enum_req->flags |= dev->hbm_f_dc_supported ? + MEI_HBM_ENUM_F_ALLOW_ADD : 0; + enum_req->flags |= dev->hbm_f_ie_supported ? + MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0; ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data); if (ret) { @@ -978,6 +981,9 @@ static void mei_hbm_config_features(struct mei_device *dev) if (dev->version.major_version >= HBM_MAJOR_VERSION_DC) dev->hbm_f_dc_supported = 1; + if (dev->version.major_version >= HBM_MAJOR_VERSION_IE) + dev->hbm_f_ie_supported = 1; + /* disconnect on connect timeout instead of link reset */ if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT) dev->hbm_f_dot_supported = 1; diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h index 459ad596df66..9daf3f9aed25 100644 --- a/drivers/misc/mei/hw.h +++ b/drivers/misc/mei/hw.h @@ -52,6 +52,12 @@ #define HBM_MINOR_VERSION_DC 0 #define HBM_MAJOR_VERSION_DC 2 +/* + * MEI version with immediate reply to enum request support + */ +#define HBM_MINOR_VERSION_IE 0 +#define HBM_MAJOR_VERSION_IE 2 + /* * MEI version with disconnect on connection timeout support */ @@ -246,15 +252,26 @@ struct hbm_me_stop_request { } __packed; /** - * struct hbm_host_enum_request - enumeration request from host to fw + * enum hbm_host_enum_flags - enumeration request flags (HBM version >= 2.0) * - * @hbm_cmd: bus message command header - * @allow_add: allow dynamic clients add HBM version >= 2.0 + * @MEI_HBM_ENUM_F_ALLOW_ADD: allow dynamic clients add + * @MEI_HBM_ENUM_F_IMMEDIATE_ENUM: allow FW to send answer immediately + */ +enum hbm_host_enum_flags { + MEI_HBM_ENUM_F_ALLOW_ADD = BIT(0), + MEI_HBM_ENUM_F_IMMEDIATE_ENUM = BIT(1), +}; + +/** + * struct hbm_host_enum_request - enumeration request from host to fw + * + * @hbm_cmd : bus message command header + * @flags : request flags * @reserved: reserved */ struct hbm_host_enum_request { u8 hbm_cmd; - u8 allow_add; + u8 flags; u8 reserved[2]; } __packed; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index c31adb8a0cff..2b9160e506d7 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -390,6 +390,7 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @hbm_f_dot_supported : hbm feature disconnect on timeout * @hbm_f_ev_supported : hbm feature event notification * @hbm_f_fa_supported : hbm feature fixed address client + * @hbm_f_ie_supported : hbm feature immediate reply to enum request * * @me_clients_rwsem: rw lock over me_clients list * @me_clients : list of FW clients @@ -480,6 +481,7 @@ struct mei_device { unsigned int hbm_f_dot_supported:1; unsigned int hbm_f_ev_supported:1; unsigned int hbm_f_fa_supported:1; + unsigned int hbm_f_ie_supported:1; struct rw_semaphore me_clients_rwsem; struct list_head me_clients; -- cgit From 025fb792bac33632c19fe12265ba1f6108921300 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Sun, 7 Feb 2016 23:35:43 +0200 Subject: mei: split amthif client init from end of clients enumeration The amthif FW client can appear after the end of client enumeration. Amthif host client initialization is done now at FW client discovery time. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 5 +++-- drivers/misc/mei/bus.c | 8 ++++++++ drivers/misc/mei/client.c | 17 ++--------------- drivers/misc/mei/client.h | 2 +- drivers/misc/mei/hbm.c | 2 +- drivers/misc/mei/init.c | 2 -- drivers/misc/mei/mei_dev.h | 2 -- 7 files changed, 15 insertions(+), 23 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index de194ef573ee..04525ada9eda 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -67,6 +67,9 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) struct mei_cl *cl = &dev->iamthif_cl; int ret; + if (mei_cl_is_connected(cl)) + return 0; + dev->iamthif_state = MEI_IAMTHIF_IDLE; mei_cl_init(cl, dev); @@ -79,8 +82,6 @@ int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl) ret = mei_cl_connect(cl, me_cl, NULL); - dev->iamthif_state = MEI_IAMTHIF_IDLE; - return ret; } diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 951d32265040..f4cf43b47c7a 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -981,6 +981,14 @@ void mei_cl_bus_rescan_work(struct work_struct *work) { struct mei_device *bus = container_of(work, struct mei_device, bus_rescan_work); + struct mei_me_client *me_cl; + + mutex_lock(&bus->device_lock); + me_cl = mei_me_cl_by_uuid(bus, &mei_amthif_guid); + if (me_cl) + mei_amthif_host_init(bus, me_cl); + mei_me_cl_put(me_cl); + mutex_unlock(&bus->device_lock); mei_cl_bus_rescan(bus); } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 2890669b81f9..af6816bc268f 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -666,25 +666,12 @@ int mei_cl_unlink(struct mei_cl *cl) return 0; } - -void mei_host_client_init(struct work_struct *work) +void mei_host_client_init(struct mei_device *dev) { - struct mei_device *dev = - container_of(work, struct mei_device, init_work); - struct mei_me_client *me_cl; - - mutex_lock(&dev->device_lock); - - me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid); - if (me_cl) - mei_amthif_host_init(dev, me_cl); - mei_me_cl_put(me_cl); - dev->dev_state = MEI_DEV_ENABLED; dev->reset_count = 0; - mutex_unlock(&dev->device_lock); - mei_cl_bus_rescan(dev); + schedule_work(&dev->bus_rescan_work); pm_runtime_mark_last_busy(dev->dev); dev_dbg(dev->dev, "rpm: autosuspend\n"); diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index a912ea686d97..0d7a3a1fef78 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -226,7 +226,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb); -void mei_host_client_init(struct work_struct *work); +void mei_host_client_init(struct mei_device *dev); u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop); enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request); diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index d2798d5b0a9d..5e305d2605f3 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -549,7 +549,7 @@ static int mei_hbm_prop_req(struct mei_device *dev) /* We got all client properties */ if (next_client_index == MEI_CLIENTS_MAX) { dev->hbm_state = MEI_HBM_STARTED; - schedule_work(&dev->init_work); + mei_host_client_init(dev); return 0; } diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 52fde2b498ef..f7c8dfdb6a12 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c @@ -91,7 +91,6 @@ EXPORT_SYMBOL_GPL(mei_fw_status2str); */ void mei_cancel_work(struct mei_device *dev) { - cancel_work_sync(&dev->init_work); cancel_work_sync(&dev->reset_work); cancel_work_sync(&dev->bus_rescan_work); @@ -393,7 +392,6 @@ void mei_device_init(struct mei_device *dev, mei_io_list_init(&dev->ctrl_rd_list); INIT_DELAYED_WORK(&dev->timer_work, mei_timer); - INIT_WORK(&dev->init_work, mei_host_client_init); INIT_WORK(&dev->reset_work, mei_reset_work); INIT_WORK(&dev->bus_rescan_work, mei_cl_bus_rescan_work); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 2b9160e506d7..db78e6d99456 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -410,7 +410,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); * @iamthif_state : amthif processor state * @iamthif_canceled : current amthif command is canceled * - * @init_work : work item for the device init * @reset_work : work item for the device reset * @bus_rescan_work : work item for the bus rescan * @@ -503,7 +502,6 @@ struct mei_device { enum iamthif_states iamthif_state; bool iamthif_canceled; - struct work_struct init_work; struct work_struct reset_work; struct work_struct bus_rescan_work; -- cgit From 49a76d7040b466dd92f198ded4aba3cd3569d48f Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sat, 6 Feb 2016 02:01:50 -0500 Subject: staging/lustre/libcfs: Properly handle debugfs read- and write-only files It turns out that unlike procfs, debugfs does not really enforce permissions for root (similar to regular filesystems), so we need to ensure we are not providing ->write() method to read-only files and ->read() method for write-only files at registration. This fixes a couple of crashes on unexpected access. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/libcfs/module.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c index d5a047bd0180..611607ab92db 100644 --- a/drivers/staging/lustre/lustre/libcfs/module.c +++ b/drivers/staging/lustre/lustre/libcfs/module.c @@ -502,13 +502,36 @@ static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf, return error; } -static const struct file_operations lnet_debugfs_file_operations = { +static const struct file_operations lnet_debugfs_file_operations_rw = { .open = simple_open, .read = lnet_debugfs_read, .write = lnet_debugfs_write, .llseek = default_llseek, }; +static const struct file_operations lnet_debugfs_file_operations_ro = { + .open = simple_open, + .read = lnet_debugfs_read, + .llseek = default_llseek, +}; + +static const struct file_operations lnet_debugfs_file_operations_wo = { + .open = simple_open, + .write = lnet_debugfs_write, + .llseek = default_llseek, +}; + +static const struct file_operations *lnet_debugfs_fops_select(umode_t mode) +{ + if (!(mode & S_IWUGO)) + return &lnet_debugfs_file_operations_ro; + + if (!(mode & S_IRUGO)) + return &lnet_debugfs_file_operations_wo; + + return &lnet_debugfs_file_operations_rw; +} + void lustre_insert_debugfs(struct ctl_table *table, const struct lnet_debugfs_symlink_def *symlinks) { @@ -525,7 +548,7 @@ void lustre_insert_debugfs(struct ctl_table *table, for (; table->procname; table++) debugfs_create_file(table->procname, table->mode, lnet_debugfs_root, table, - &lnet_debugfs_file_operations); + lnet_debugfs_fops_select(table->mode)); for (; symlinks && symlinks->name; symlinks++) debugfs_create_symlink(symlinks->name, lnet_debugfs_root, -- cgit From da33f1dd9f69c5a5d23e1254906b027af3362e36 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sat, 6 Feb 2016 02:01:51 -0500 Subject: staging/lustre/obdclass: export debugfs functionality for GPL only. Turns out we mistakenly export some pretty-wide-reaching debugfs functions as EXPORT_SYMBOL instead of EXPORT_SYMBOL_GPL as we should, so this patch rectifies the situation. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lustre/obdclass/lprocfs_status.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index b65ad93eca4b..9a1434d89d57 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -261,7 +261,7 @@ struct dentry *ldebugfs_add_simple(struct dentry *root, } return entry; } -EXPORT_SYMBOL(ldebugfs_add_simple); +EXPORT_SYMBOL_GPL(ldebugfs_add_simple); static struct file_operations lprocfs_generic_fops = { }; @@ -294,14 +294,14 @@ int ldebugfs_add_vars(struct dentry *parent, } return 0; } -EXPORT_SYMBOL(ldebugfs_add_vars); +EXPORT_SYMBOL_GPL(ldebugfs_add_vars); void ldebugfs_remove(struct dentry **entryp) { debugfs_remove_recursive(*entryp); *entryp = NULL; } -EXPORT_SYMBOL(ldebugfs_remove); +EXPORT_SYMBOL_GPL(ldebugfs_remove); struct dentry *ldebugfs_register(const char *name, struct dentry *parent, @@ -327,7 +327,7 @@ struct dentry *ldebugfs_register(const char *name, out: return entry; } -EXPORT_SYMBOL(ldebugfs_register); +EXPORT_SYMBOL_GPL(ldebugfs_register); /* Generic callbacks */ int lprocfs_rd_uint(struct seq_file *m, void *data) @@ -942,7 +942,7 @@ int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list, return rc; } -EXPORT_SYMBOL(lprocfs_obd_setup); +EXPORT_SYMBOL_GPL(lprocfs_obd_setup); int lprocfs_obd_cleanup(struct obd_device *obd) { @@ -957,7 +957,7 @@ int lprocfs_obd_cleanup(struct obd_device *obd) return 0; } -EXPORT_SYMBOL(lprocfs_obd_cleanup); +EXPORT_SYMBOL_GPL(lprocfs_obd_cleanup); int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid) { @@ -1219,7 +1219,7 @@ int ldebugfs_register_stats(struct dentry *parent, const char *name, return 0; } -EXPORT_SYMBOL(ldebugfs_register_stats); +EXPORT_SYMBOL_GPL(ldebugfs_register_stats); void lprocfs_counter_init(struct lprocfs_stats *stats, int index, unsigned conf, const char *name, const char *units) @@ -1446,7 +1446,7 @@ int ldebugfs_seq_create(struct dentry *parent, return 0; } -EXPORT_SYMBOL(ldebugfs_seq_create); +EXPORT_SYMBOL_GPL(ldebugfs_seq_create); int ldebugfs_obd_seq_create(struct obd_device *dev, const char *name, @@ -1457,7 +1457,7 @@ int ldebugfs_obd_seq_create(struct obd_device *dev, return ldebugfs_seq_create(dev->obd_debugfs_entry, name, mode, seq_fops, data); } -EXPORT_SYMBOL(ldebugfs_obd_seq_create); +EXPORT_SYMBOL_GPL(ldebugfs_obd_seq_create); void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value) { -- cgit From deaf7e1cc65f3562cb47acf3650c64834afaa434 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Sat, 6 Feb 2016 02:12:12 -0500 Subject: staging/lustre/lnet: Don't call roundup_pow_of_two on zero in LNetEQAlloc roundup_pow_of_two return when called on a zero argument is undefined, so don't call it like that. This fixes a problem introduced by commit 322489d9d551 ("staging/lustre: Use roundup_pow_of_two() in LNetEQAlloc()") since 0 is a valid count parameter for LNetEQAlloc. Also manifesting itself as an annoying kernel warning: LNet: 3486:0:(lib-eq.c:85:LNetEQAlloc()) EQ callback is guaranteed to get every event, do you still want to set eqcount 1 for polling event which will have locking overhead? Please contact with developer to confirm Signed-off-by: Oleg Drokin CC: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/lib-eq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index 64f94a690081..bfbc3136fd3b 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -79,7 +79,8 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, * overflow, they don't skip entries, so the queue has the same * apparent capacity at all times */ - count = roundup_pow_of_two(count); + if (count) + count = roundup_pow_of_two(count); if (callback != LNET_EQ_HANDLER_NONE && count != 0) CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count); -- cgit From f6ab21b546ae2020e16f353a7a3a4c7327887de9 Mon Sep 17 00:00:00 2001 From: CHANG FU CHIAO Date: Sat, 6 Feb 2016 13:57:48 +0800 Subject: staging: lustre: add static declaration this function is only referenced within the file Signed-off-by: CHANG FU CHIAO Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/osc/osc_page.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index 2439d804fe75..8943f0a065b9 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -434,8 +434,8 @@ static void osc_page_delete(const struct lu_env *env, osc_lru_del(osc_cli(obj), opg, true); } -void osc_page_clip(const struct lu_env *env, const struct cl_page_slice *slice, - int from, int to) +static void osc_page_clip(const struct lu_env *env, + const struct cl_page_slice *slice, int from, int to) { struct osc_page *opg = cl2osc_page(slice); struct osc_async_page *oap = &opg->ops_oap; -- cgit From b330686595279de880d174f9f3d4a6c615adff0d Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:18 +0900 Subject: staging: wilc1000: wilc_set_wfi_drv_handler: add mac index Firmware supports sta/ap concurrency so mac index will be passed to wilc. Remove wilc_set_wfi_drv_handler in scan and connect functions, and call the function in ndo_open which is wilc_mac_open. WID_SET_DRV_HANDLER value has been changed as well. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 11 ++++++----- drivers/staging/wilc1000/host_interface.h | 3 ++- drivers/staging/wilc1000/linux_wlan.c | 19 +++++++++++++++++++ drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 ++---- drivers/staging/wilc1000/wilc_wlan_if.h | 2 +- 5 files changed, 30 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d77e2b2bea3d..7c75d0e1ef5a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -320,9 +320,9 @@ static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, struct wid wid; wid.id = (u16)WID_SET_DRV_HANDLER; - wid.type = WID_INT; - wid.val = (s8 *)&hif_drv_handler->handler; - wid.size = sizeof(u32); + wid.type = WID_STR; + wid.val = (s8 *)hif_drv_handler; + wid.size = sizeof(*hif_drv_handler); result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, hif_drv_handler->handler); @@ -3557,7 +3557,7 @@ int wilc_wait_msg_queue_idle(void) return result; } -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index) +int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx) { int result = 0; struct host_if_msg msg; @@ -3565,6 +3565,7 @@ int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index) memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_SET_WFIDRV_HANDLER; msg.body.drv.handler = index; + msg.body.drv.mac_idx = mac_idx; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); @@ -3909,7 +3910,7 @@ s32 wilc_deinit(struct wilc_vif *vif) del_timer_sync(&hif_drv->remain_on_ch_timer); - wilc_set_wfi_drv_handler(vif, 0); + wilc_set_wfi_drv_handler(vif, 0, 0); down(&hif_sema_driver); if (hif_drv->usr_scan_req.scan_result) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 4c02e6bbed41..b828791bb81a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -217,6 +217,7 @@ struct user_conn_req { struct drv_handler { u32 handler; + u8 mac_idx; }; struct op_mode { @@ -363,7 +364,7 @@ int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, void *user_arg); int wilc_listen_state_expired(struct wilc_vif *vif, u32 session_id); int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg); -int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index); +int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx); int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index b368c2d9bf14..2fafcc47b59d 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1024,6 +1024,25 @@ int wilc_mac_open(struct net_device *ndev) for (i = 0; i < wl->vif_num; i++) { if (ndev == wl->vif[i]->ndev) { memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); + if (vif->iftype == AP_MODE) { + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + 0); + } else if (!wilc_wlan_get_num_conn_ifcs(wilc)) { + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + wilc->open_ifcs); + } else { + if (memcmp(wilc->vif[i ^ 1]->bssid, + wilc->vif[i ^ 1]->src_addr, 6)) + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + 0); + else + wilc_set_wfi_drv_handler(vif, + wilc_get_vif_idx(vif), + 1); + } wilc_set_operation_mode(vif, vif->iftype); break; } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 28a6ffa6d907..6ebe07e80acd 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -633,7 +633,6 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) priv->u32RcvdChCount = 0; - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); reset_shadow_found(); priv->bCfgScanning = true; @@ -714,8 +713,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, vif = netdev_priv(priv->dev); pstrWFIDrv = (struct host_if_drv *)(priv->hWILCWFIDrv); - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); - PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv); if (!(strncmp(sme->ssid, "DIRECT-", 7))) { PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n"); @@ -2152,7 +2149,8 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, vif->iftype = AP_MODE; if (wl->initialized) { - wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif)); + wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), + 0); wilc_set_operation_mode(vif, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); } diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 618903caff54..d306ec1a8529 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -832,7 +832,6 @@ typedef enum { /* Custom Integer WID list */ WID_GET_INACTIVE_TIME = 0x2084, - WID_SET_DRV_HANDLER = 0X2085, WID_SET_OPERATION_MODE = 0X2086, /* EMAC String WID list */ WID_SSID = 0x3000, @@ -865,6 +864,7 @@ typedef enum { WID_MODEL_NAME = 0x3027, /*Added for CAPI tool */ WID_MODEL_NUM = 0x3028, /*Added for CAPI tool */ WID_DEVICE_NAME = 0x3029, /*Added for CAPI tool */ + WID_SET_DRV_HANDLER = 0x3030, /* NMAC String WID list */ WID_11N_P_ACTION_REQ = 0x3080, -- cgit From ef54719cabca2b65a84fa07065c55e332467b9d1 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:19 +0900 Subject: staging: wilc1000: remove unused functions This patch removes unused following functions. wilc_del_all_rx_ba_session wilc_flush_join_req wilc_wait_msg_queue_idle wilc_set_mac_address Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 92 ------------------------------- drivers/staging/wilc1000/host_interface.h | 4 -- 2 files changed, 96 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7c75d0e1ef5a..1dc6af045c86 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3342,25 +3342,6 @@ int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr) return result; } -int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr) -{ - int result = 0; - struct host_if_msg msg; - - PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", mac_addr[0], mac_addr[1], mac_addr[2]); - - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_SET_MAC_ADDRESS; - memcpy(msg.body.set_mac_info.mac_addr, mac_addr, ETH_ALEN); - msg.vif = vif; - - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) - PRINT_ER("Failed to send message queue: Set mac address\n"); - - return result; -} - int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, @@ -3431,32 +3412,6 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, return result; } -int wilc_flush_join_req(struct wilc_vif *vif) -{ - int result = 0; - struct host_if_msg msg; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!join_req) - return -EFAULT; - - if (!hif_drv) { - PRINT_ER("Driver is null\n"); - return -EFAULT; - } - - msg.id = HOST_IF_MSG_FLUSH_CONNECT; - msg.vif = vif; - - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) { - PRINT_ER("Failed to send message queue: Flush join request\n"); - return -EFAULT; - } - - return result; -} - int wilc_disconnect(struct wilc_vif *vif, u16 reason_code) { int result = 0; @@ -3539,24 +3494,6 @@ int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel) return 0; } -int wilc_wait_msg_queue_idle(void) -{ - int result = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); - msg.id = HOST_IF_MSG_Q_IDLE; - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) { - PRINT_ER("wilc mq send fail\n"); - result = -EINVAL; - } - - down(&hif_sema_wait_response); - - return result; -} - int wilc_set_wfi_drv_handler(struct wilc_vif *vif, int index, u8 mac_idx) { int result = 0; @@ -4606,35 +4543,6 @@ static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) return (void *)pNewJoinBssParam; } -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid) -{ - int result = 0; - struct host_if_msg msg; - struct ba_session_info *ba_session_info = &msg.body.session_info; - struct host_if_drv *hif_drv = vif->hif_drv; - - if (!hif_drv) { - PRINT_ER("driver is null\n"); - return -EFAULT; - } - - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS; - - memcpy(ba_session_info->bssid, bssid, ETH_ALEN); - ba_session_info->tid = tid; - msg.vif = vif; - - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) - PRINT_ER("wilc_mq_send fail\n"); - - down(&hif_sema_wait_response); - - return result; -} - int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) { int result = 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index b828791bb81a..3302a5bb1c6a 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -325,14 +325,11 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len, int wilc_set_pmkid_info(struct wilc_vif *vif, struct host_if_pmkid_attr *pmkid); int wilc_get_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_set_mac_address(struct wilc_vif *vif, u8 *mac_addr); -int wilc_wait_msg_queue_idle(void); int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, size_t ssid_len, const u8 *ies, size_t ies_len, wilc_connect_result connect_result, void *user_arg, u8 security, enum AUTHTYPE auth_type, u8 channel, void *join_params); -int wilc_flush_join_req(struct wilc_vif *vif); int wilc_disconnect(struct wilc_vif *vif, u16 reason_code); int wilc_set_mac_chnl_num(struct wilc_vif *vif, u8 channel); int wilc_get_rssi(struct wilc_vif *vif, s8 *rssi_level); @@ -356,7 +353,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout); int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, u32 count); int wilc_setup_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); -int wilc_del_all_rx_ba_session(struct wilc_vif *vif, char *bssid, char tid); int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, u32 duration, u16 chan, wilc_remain_on_chan_expired expired, -- cgit From ff9d65abc8561d67313cd310dc15d2f496282a92 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:20 +0900 Subject: staging: wilc1000: ignore power save If two interfaces are connected and it is required to enable power save then ignore the request. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 1dc6af045c86..7e1b5a097249 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4341,6 +4341,9 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) return -EFAULT; } + if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) + return 0; + PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n"); memset(&msg, 0, sizeof(struct host_if_msg)); -- cgit From 430e640d6d24cf0c9ff035536fd9daa8f2cc879d Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:21 +0900 Subject: staging: wilc1000: handle connecting error If connection fails, wilc1000_connecting needs to be set false also and return immediately because goto lable 'done' doesn't do anything. Remove lable 'done' as well. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 6ebe07e80acd..744b77120b86 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -757,8 +757,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_D(CFG80211_DBG, "No Scan results yet\n"); else PRINT_D(CFG80211_DBG, "Required bss not in scan results: Error(%d)\n", s32Error); - - goto done; + wilc_connecting = 0; + return s32Error; } priv->WILC_WFI_wep_default = 0; @@ -845,8 +845,8 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, } else { s32Error = -ENOTSUPP; PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); - - goto done; + wilc_connecting = 0; + return s32Error; } } @@ -912,11 +912,10 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) { PRINT_ER("wilc_set_join_req(): Error(%d)\n", s32Error); s32Error = -ENOENT; - goto done; + wilc_connecting = 0; + return s32Error; } -done: - return s32Error; } -- cgit From c6866cc4be96e8c50aad53375f9becacb433a5a1 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:22 +0900 Subject: staging: wilc1000: tcp_process: fix a build warning This patch fixes build warning "flags is used uninitialized" when TCP_ACK_FILTER is defined. Fixes: 562ed3f1f78a ("staging/wilc1000: pass struct wilc to most linux_wlan.c functions") Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 5682581ebcc3..25cf32559be4 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -234,6 +234,7 @@ static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) vif = netdev_priv(dev); wilc = vif->wilc; + spin_lock_irqsave(&wilc->txq_spinlock, flags); eth_hdr_ptr = &buffer[0]; h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12])); -- cgit From e9576e96cc601b6ffd5af4895407cc44c3bdef8a Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:23 +0900 Subject: staging: wilc1000: remove define TCP_ACK_FILTER This patch removes define TCP_ACK_FILTER and use it's feature codes. Add argument wilc to wilc_wlan_txq_remove because compile error happens. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/Makefile | 1 - drivers/staging/wilc1000/wilc_wlan.c | 22 ++-------------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile index 90c37606f202..acc3f3e8481b 100644 --- a/drivers/staging/wilc1000/Makefile +++ b/drivers/staging/wilc1000/Makefile @@ -4,7 +4,6 @@ ccflags-y += -DFIRMWARE_1002=\"atmel/wilc1002_firmware.bin\" \ -DFIRMWARE_1003=\"atmel/wilc1003_firmware.bin\" ccflags-y += -I$(src)/ -DWILC_ASIC_A0 -DWILC_DEBUGFS -#ccflags-y += -DTCP_ACK_FILTER wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \ wilc_msgqueue.o \ diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 25cf32559be4..94420161eb5d 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -36,8 +36,7 @@ static inline void release_bus(struct wilc *wilc, BUS_RELEASE_T release) mutex_unlock(&wilc->hif_cs); } -#ifdef TCP_ACK_FILTER -static void wilc_wlan_txq_remove(struct txq_entry_t *tqe) +static void wilc_wlan_txq_remove(struct wilc *wilc, struct txq_entry_t *tqe) { if (tqe == wilc->txq_head) { @@ -54,7 +53,6 @@ static void wilc_wlan_txq_remove(struct txq_entry_t *tqe) } wilc->txq_entries -= 1; } -#endif static struct txq_entry_t * wilc_wlan_txq_remove_from_head(struct net_device *dev) @@ -146,7 +144,6 @@ static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) return 0; } -#ifdef TCP_ACK_FILTER struct ack_session_info; struct ack_session_info { u32 seq_num; @@ -308,7 +305,7 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) pending_acks_info[i].ack_num); tqe = pending_acks_info[i].txqe; if (tqe) { - wilc_wlan_txq_remove(tqe); + wilc_wlan_txq_remove(wilc, tqe); tqe->status = 1; if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, @@ -335,7 +332,6 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) return 1; } -#endif static bool enabled = false; @@ -344,12 +340,10 @@ void wilc_enable_tcp_ack_filter(bool value) enabled = value; } -#ifdef TCP_ACK_FILTER static bool is_tcp_ack_filter_enabled(void) { return enabled; } -#endif static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_size) { @@ -373,9 +367,7 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_s tqe->buffer_size = buffer_size; tqe->tx_complete_func = NULL; tqe->priv = NULL; -#ifdef TCP_ACK_FILTER tqe->tcp_pending_ack_idx = NOT_TCP_ACK; -#endif PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); if (wilc_wlan_txq_add_to_head(wilc, tqe)) @@ -406,11 +398,9 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->priv = priv; PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); -#ifdef TCP_ACK_FILTER tqe->tcp_pending_ack_idx = NOT_TCP_ACK; if (is_tcp_ack_filter_enabled()) tcp_process(dev, tqe); -#endif wilc_wlan_txq_add_to_tail(dev, tqe); return wilc->txq_entries; } @@ -436,9 +426,7 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->buffer_size = buffer_size; tqe->tx_complete_func = func; tqe->priv = priv; -#ifdef TCP_ACK_FILTER tqe->tcp_pending_ack_idx = NOT_TCP_ACK; -#endif PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); wilc_wlan_txq_add_to_tail(dev, tqe); return 1; @@ -643,9 +631,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, CFG_PKTS_TIMEOUT); -#ifdef TCP_ACK_FILTER wilc_wlan_txq_filter_dup_tcp_ack(dev); -#endif PRINT_D(TX_DBG, "Getting the head of the TxQ\n"); tqe = wilc_wlan_txq_get_first(wilc); i = 0; @@ -829,10 +815,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, tqe->status); - #ifdef TCP_ACK_FILTER if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK) pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL; - #endif kfree(tqe); } else { break; @@ -1564,9 +1548,7 @@ int wilc_wlan_init(struct net_device *dev) ret = -EIO; goto _fail_; } -#ifdef TCP_ACK_FILTER init_tcp_tracking(); -#endif return 1; -- cgit From 4fd6229147e5c58ecf51d7f07ee5247846d0338d Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:24 +0900 Subject: staging: wilc1000: increase link speed This patch increases throughput by enabling tcp ack filter base on checking statistics and also handling tcp session. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 31 +++++++++++++-------------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 ++ drivers/staging/wilc1000/wilc_wlan.c | 27 ++++++++++++++--------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7e1b5a097249..4bbf38c05940 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -57,6 +57,9 @@ #define BLOCK_ACK_REQ_SIZE 0x14 #define FALSE_FRMWR_CHANNEL 100 +#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54 +#define DEFAULT_LINK_SPEED 72 + struct cfg_param_attr { struct cfg_param_val cfg_attr_info; }; @@ -2187,7 +2190,14 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, if (result) PRINT_ER("Failed to send scan paramters config packet\n"); - up(&hif_sema_wait_response); + if (pstrStatistics->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH && + pstrStatistics->link_speed != DEFAULT_LINK_SPEED) + wilc_enable_tcp_ack_filter(true); + else if (pstrStatistics->link_speed != DEFAULT_LINK_SPEED) + wilc_enable_tcp_ack_filter(false); + + if (pstrStatistics != &vif->wilc->dummy_statistics) + up(&hif_sema_wait_response); return 0; } @@ -3606,7 +3616,8 @@ int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats) return -EFAULT; } - down(&hif_sema_wait_response); + if (stats != &vif->wilc->dummy_statistics) + down(&hif_sema_wait_response); return result; } @@ -3698,21 +3709,9 @@ static void GetPeriodicRSSI(unsigned long arg) return; } - if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) { - s32 result = 0; - struct host_if_msg msg; - - memset(&msg, 0, sizeof(struct host_if_msg)); - - msg.id = HOST_IF_MSG_GET_RSSI; - msg.vif = vif; + if (vif->hif_drv->hif_state == HOST_IF_CONNECTED) + wilc_get_statistics(vif, &vif->wilc->dummy_statistics); - result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); - if (result) { - PRINT_ER("Failed to send get host channel param's message queue "); - return; - } - } periodic_rssi.data = (unsigned long)vif; mod_timer(&periodic_rssi, jiffies + msecs_to_jiffies(5000)); } diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 54e762ec815f..9f8c79e3d195 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -217,6 +217,8 @@ struct wilc { struct device *dev; bool suspend_event; + + struct rf_info dummy_statistics; }; struct WILC_WFI_mon_priv { diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 94420161eb5d..04d4c92e3948 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -178,19 +178,21 @@ static inline int init_tcp_tracking(void) static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq) { - ack_session_info[tcp_session].seq_num = seq; - ack_session_info[tcp_session].bigger_ack_num = 0; - ack_session_info[tcp_session].src_port = src_prt; - ack_session_info[tcp_session].dst_port = dst_prt; - tcp_session++; - + if (tcp_session < 2 * MAX_TCP_SESSION) { + ack_session_info[tcp_session].seq_num = seq; + ack_session_info[tcp_session].bigger_ack_num = 0; + ack_session_info[tcp_session].src_port = src_prt; + ack_session_info[tcp_session].dst_port = dst_prt; + tcp_session++; + } PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq); return 0; } static inline int update_tcp_session(u32 index, u32 ack) { - if (ack > ack_session_info[index].bigger_ack_num) + if (index < 2 * MAX_TCP_SESSION && + ack > ack_session_info[index].bigger_ack_num) ack_session_info[index].bigger_ack_num = ack; return 0; } @@ -198,7 +200,7 @@ static inline int update_tcp_session(u32 index, u32 ack) static inline int add_tcp_pending_ack(u32 ack, u32 session_index, struct txq_entry_t *txqe) { - if (pending_acks < MAX_PENDING_ACKS) { + if (pending_base + pending_acks < MAX_PENDING_ACKS) { pending_acks_info[pending_base + pending_acks].ack_num = ack; pending_acks_info[pending_base + pending_acks].txqe = txqe; pending_acks_info[pending_base + pending_acks].session_index = session_index; @@ -265,7 +267,8 @@ static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) (u32)tcp_hdr_ptr[11]; for (i = 0; i < tcp_session; i++) { - if (ack_session_info[i].seq_num == seq_no) { + if (i < 2 * MAX_TCP_SESSION && + ack_session_info[i].seq_num == seq_no) { update_tcp_session(i, ack_no); break; } @@ -298,6 +301,9 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags); for (i = pending_base; i < (pending_base + pending_acks); i++) { + if (i >= MAX_PENDING_ACKS || + pending_acks_info[i].session_index >= 2 * MAX_TCP_SESSION) + break; if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) { struct txq_entry_t *tqe; @@ -815,7 +821,8 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (tqe->tx_complete_func) tqe->tx_complete_func(tqe->priv, tqe->status); - if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK) + if (tqe->tcp_pending_ack_idx != NOT_TCP_ACK && + tqe->tcp_pending_ack_idx < MAX_PENDING_ACKS) pending_acks_info[tqe->tcp_pending_ack_idx].txqe = NULL; kfree(tqe); } else { -- cgit From cba352a4c10afd609946f6d15bfe82e2a6c421a7 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:25 +0900 Subject: staging: wilc1000: disable power save when AP mode This patch disables power save mode in case of AP mode. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 744b77120b86..e9db04958030 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2203,6 +2203,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, PRINT_ER("Error in setting channel\n"); wilc_wlan_set_bssid(dev, wl->vif[vif->u8IfIdx]->src_addr, AP_MODE); + wilc_set_power_mgmt(vif, 0, 0); s32Error = wilc_add_beacon(vif, settings->beacon_interval, settings->dtim_period, beacon->head_len, -- cgit From 783d07c1bf8b8e6364aa2e90c83addb8001817e1 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:26 +0900 Subject: staging: wilc1000: fix bug on p2p connection In case of action frame, size -7 is correct, but in this case, size should be used as it is. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index e9db04958030..4038f7db1b35 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1728,7 +1728,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) } } - cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0); + cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size, 0); } } -- cgit From 70418790437753faa9a6d7d5c567820e47838e85 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:27 +0900 Subject: staging: wilc1000: add ops tx power in cfg80211 This patch implements set_tx_power and get_tx_power of cfg80211_ops. In addition, Id of HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS is changed with 37. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 88 ++++++++++++++++++++++- drivers/staging/wilc1000/host_interface.h | 2 + drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 35 +++++++++ drivers/staging/wilc1000/wilc_wlan_if.h | 1 + 4 files changed, 125 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4bbf38c05940..4b1d92cb50d0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -46,7 +46,9 @@ #define HOST_IF_MSG_DEL_BA_SESSION 34 #define HOST_IF_MSG_Q_IDLE 35 #define HOST_IF_MSG_DEL_ALL_STA 36 -#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 34 +#define HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS 37 +#define HOST_IF_MSG_SET_TX_POWER 38 +#define HOST_IF_MSG_GET_TX_POWER 39 #define HOST_IF_MSG_EXIT 100 #define HOST_IF_SCAN_TIMEOUT 4000 @@ -166,6 +168,10 @@ struct sta_inactive_t { u8 mac[6]; }; +struct tx_power { + u8 tx_pwr; +}; + union message_body { struct scan_attr scan_info; struct connect_attr con_info; @@ -191,6 +197,7 @@ union message_body { struct reg_frame reg_frame; char *data; struct del_all_sta del_all_sta_info; + struct tx_power tx_power; }; struct host_if_msg { @@ -2783,6 +2790,40 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, return result; } +static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr) +{ + int ret; + struct wid wid; + + wid.id = (u16)WID_TX_POWER; + wid.type = WID_CHAR; + wid.val = &tx_pwr; + wid.size = sizeof(char); + + ret = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (ret) + netdev_err(vif->ndev, "Failed to set TX PWR\n"); +} + +static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) +{ + s32 ret = 0; + struct wid wid; + + wid.id = (u16)WID_TX_POWER; + wid.type = WID_CHAR; + wid.val = (s8 *)tx_pwr; + wid.size = sizeof(char); + + ret = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); + if (ret) + netdev_err(vif->ndev, "Failed to get TX PWR\n"); + + up(&hif_sema_wait_response); +} + static int hostIFthread(void *pvArg) { u32 u32Ret; @@ -2986,6 +3027,13 @@ static int hostIFthread(void *pvArg) Handle_DelAllSta(msg.vif, &msg.body.del_all_sta_info); break; + case HOST_IF_MSG_SET_TX_POWER: + handle_set_tx_pwr(msg.vif, msg.body.tx_power.tx_pwr); + break; + + case HOST_IF_MSG_GET_TX_POWER: + handle_get_tx_pwr(msg.vif, &msg.body.tx_power.tx_pwr); + break; default: PRINT_ER("[Host Interface] undefined Received Msg ID\n"); break; @@ -4596,3 +4644,41 @@ static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return result; } + +int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power) +{ + int ret = 0; + struct host_if_msg msg; + + memset(&msg, 0, sizeof(struct host_if_msg)); + + msg.id = HOST_IF_MSG_SET_TX_POWER; + msg.body.tx_power.tx_pwr = tx_power; + msg.vif = vif; + + ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); + if (ret) + netdev_err(vif->ndev, "wilc_mq_send fail\n"); + + return ret; +} + +int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power) +{ + int ret = 0; + struct host_if_msg msg; + + memset(&msg, 0, sizeof(struct host_if_msg)); + + msg.id = HOST_IF_MSG_GET_TX_POWER; + msg.vif = vif; + + ret = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); + if (ret) + netdev_err(vif->ndev, "Failed to get TX PWR\n"); + + down(&hif_sema_wait_response); + *tx_power = msg.body.tx_power.tx_pwr; + + return ret; +} diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 3302a5bb1c6a..69c36a7449c7 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -365,6 +365,8 @@ int wilc_set_operation_mode(struct wilc_vif *vif, u32 mode); int wilc_get_statistics(struct wilc_vif *vif, struct rf_info *stats); void wilc_resolve_disconnect_aberration(struct wilc_vif *vif); int wilc_get_vif_idx(struct wilc_vif *vif); +int wilc_set_tx_power(struct wilc_vif *vif, u8 tx_power); +int wilc_get_tx_power(struct wilc_vif *vif, u8 *tx_power); extern bool wilc_optaining_ip; extern u8 wilc_connected_ssid[6]; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 4038f7db1b35..14e1f14256d2 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2504,6 +2504,39 @@ static void wilc_set_wakeup(struct wiphy *wiphy, bool enabled) netdev_info(vif->ndev, "cfg set wake up = %d\n", enabled); } +static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + int ret; + s32 tx_power = MBM_TO_DBM(mbm); + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + if (tx_power < 0) + tx_power = 0; + else if (tx_power > 18) + tx_power = 18; + ret = wilc_set_tx_power(vif, tx_power); + if (ret) + netdev_err(vif->ndev, "Failed to set tx power\n"); + + return ret; +} + +static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm) +{ + int ret; + struct wilc_priv *priv = wiphy_priv(wiphy); + struct wilc_vif *vif = netdev_priv(priv->dev); + + ret = wilc_get_tx_power(vif, (u8 *)dbm); + if (ret) + netdev_err(vif->ndev, "Failed to get tx power\n"); + + return ret; +} + static struct cfg80211_ops wilc_cfg80211_ops = { .set_monitor_channel = set_channel, .scan = scan, @@ -2542,6 +2575,8 @@ static struct cfg80211_ops wilc_cfg80211_ops = { .suspend = wilc_suspend, .resume = wilc_resume, .set_wakeup = wilc_set_wakeup, + .set_tx_power = set_tx_power, + .get_tx_power = get_tx_power, }; diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index d306ec1a8529..c446af60dfe8 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -761,6 +761,7 @@ typedef enum { WID_DEL_BEACON = 0x00CA, WID_LOGTerminal_Switch = 0x00CD, + WID_TX_POWER = 0x00CE, /* EMAC Short WID list */ /* RTS Threshold */ /* -- cgit From ec4504832655e8ebc246d3f96efba4b1ea82ecbe Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:28 +0900 Subject: staging: wilc1000: fix WEP security bug Station cannot connect to soft AP mode wilc when it is configured for WEP security. This patch fixes it by setting the key index within the key value and change the last else condition with DEFAULTKEY action case, and also do not use WILC_WFI_wep_default index to set wep key id. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 27 +++++++++++------------ drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 9 +------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 4b1d92cb50d0..67bcf889287e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1737,14 +1737,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[1].size = sizeof(char); strWIDList[1].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.auth_type; - strWIDList[2].id = (u16)WID_KEY_ID; - strWIDList[2].type = WID_CHAR; - - strWIDList[2].val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index; - strWIDList[2].size = sizeof(char); - - pu8keybuf = kmemdup(pstrHostIFkeyAttr->attr.wep.key, - pstrHostIFkeyAttr->attr.wep.key_len, + pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL); if (pu8keybuf == NULL) { @@ -1752,15 +1745,21 @@ static int Handle_Key(struct wilc_vif *vif, return -ENOMEM; } + pu8keybuf[0] = pstrHostIFkeyAttr->attr.wep.index; + pu8keybuf[1] = pstrHostIFkeyAttr->attr.wep.key_len; + + memcpy(&pu8keybuf[2], pstrHostIFkeyAttr->attr.wep.key, + pstrHostIFkeyAttr->attr.wep.key_len); + kfree(pstrHostIFkeyAttr->attr.wep.key); - strWIDList[3].id = (u16)WID_WEP_KEY_VALUE; - strWIDList[3].type = WID_STR; - strWIDList[3].size = pstrHostIFkeyAttr->attr.wep.key_len; - strWIDList[3].val = (s8 *)pu8keybuf; + strWIDList[2].id = (u16)WID_WEP_KEY_VALUE; + strWIDList[2].type = WID_STR; + strWIDList[2].size = pstrHostIFkeyAttr->attr.wep.key_len + 2; + strWIDList[2].val = (s8 *)pu8keybuf; result = wilc_send_config_pkt(vif->wilc, SET_CFG, - strWIDList, 4, + strWIDList, 3, wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & ADDKEY) { @@ -1797,7 +1796,7 @@ static int Handle_Key(struct wilc_vif *vif, result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - } else { + } else if (pstrHostIFkeyAttr->action & DEFAULTKEY) { wid.id = (u16)WID_KEY_ID; wid.type = WID_CHAR; wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 14e1f14256d2..fb940ed4d0ef 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -761,7 +761,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, return s32Error; } - priv->WILC_WFI_wep_default = 0; memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key)); memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len)); @@ -788,7 +787,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, for (i = 0; i < sme->key_len; i++) PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]); } - priv->WILC_WFI_wep_default = sme->key_idx; priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); @@ -806,7 +804,6 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, pcgroup_encrypt_val = "WEP104"; pccipher_group = "WLAN_CIPHER_SUITE_WEP104"; - priv->WILC_WFI_wep_default = sme->key_idx; priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); @@ -986,7 +983,6 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: if (priv->wdev->iftype == NL80211_IFTYPE_AP) { - priv->WILC_WFI_wep_default = key_index; priv->WILC_WFI_wep_key_len[key_index] = params->key_len; memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); @@ -1009,7 +1005,6 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, break; } if (memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) { - priv->WILC_WFI_wep_default = key_index; priv->WILC_WFI_wep_key_len[key_index] = params->key_len; memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len); @@ -1336,9 +1331,7 @@ static int set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 ke PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index); - if (key_index != priv->WILC_WFI_wep_default) { - wilc_set_wep_default_keyid(vif, key_index); - } + wilc_set_wep_default_keyid(vif, key_index); return 0; } diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 9f8c79e3d195..07eda4db1dcd 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -124,7 +124,6 @@ struct wilc_priv { struct host_if_drv *hWILCWFIDrv; struct host_if_pmkid_attr pmkid_list; struct WILC_WFI_stats netstats; - u8 WILC_WFI_wep_default; u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104]; u8 WILC_WFI_wep_key_len[4]; /* The real interface that the monitor is on */ -- cgit From 32cee9993c8bccfcf1626b1b192e4ed611a0fcfb Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:29 +0900 Subject: staging: wilc1000: get mac address after setting drv handler This patch moves wilc_get_mac_address and address memcpy function after calling wilc_set_wif_drv_handler to get selected mac address. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 2fafcc47b59d..9de57aeb50d4 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1018,12 +1018,8 @@ int wilc_mac_open(struct net_device *ndev) return ret; } - wilc_get_mac_address(vif, mac_add); - PRINT_D(INIT_DBG, "Mac address: %pM\n", mac_add); - for (i = 0; i < wl->vif_num; i++) { if (ndev == wl->vif[i]->ndev) { - memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); if (vif->iftype == AP_MODE) { wilc_set_wfi_drv_handler(vif, wilc_get_vif_idx(vif), @@ -1044,6 +1040,11 @@ int wilc_mac_open(struct net_device *ndev) 1); } wilc_set_operation_mode(vif, vif->iftype); + + wilc_get_mac_address(vif, mac_add); + netdev_dbg(ndev, "Mac address: %pM\n", mac_add); + memcpy(wl->vif[i]->src_addr, mac_add, ETH_ALEN); + break; } } -- cgit From ef7e012fdc8b5c1d129429cf0cd68ddb0ccc6599 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:30 +0900 Subject: staging: wilc1000: move wilc_send_config_pkt to wilc_wlan.c This patch moves the function wilc_send_config_pkt to wilc_wlan.c which handles transport since the purpose of the function is sending/getting of config information. coreconfiguator.[ch] will be rename with frame.[ch] later. The print codes of the function is removed also and they will be implemented with netdev_xx print format later. struct wid need to be moved to wilc_wlan_if.h which defines configure informations. Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 59 ----------------------------- drivers/staging/wilc1000/coreconfigurator.h | 9 ----- drivers/staging/wilc1000/wilc_wlan.c | 39 +++++++++++++++++++ drivers/staging/wilc1000/wilc_wlan.h | 2 + drivers/staging/wilc1000/wilc_wlan_if.h | 7 ++++ 5 files changed, 48 insertions(+), 68 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 49ae9b152654..6f17e2b66673 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -433,62 +433,3 @@ s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) return s32Error; } - -/** - * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs - * using driver config layer - * - * @details - * @param[in] pstrWIDs WIDs to be sent in the configuration packet - * @param[in] u32WIDsCount number of WIDs to be sent in the configuration packet - * @param[out] pu8RxResp The received Packet Response - * @param[out] ps32RxRespLen Length of the received Packet Response - * @return Error code indicating success/failure - * @note - * @author mabubakr - * @date 1 Mar 2012 - * @version 1.0 - */ -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, - u32 count, u32 drv) -{ - s32 counter = 0, ret = 0; - - if (mode == GET_CFG) { - for (counter = 0; counter < count; counter++) { - PRINT_INFO(CORECONFIG_DBG, "Sending CFG packet [%d][%d]\n", !counter, - (counter == count - 1)); - if (!wilc_wlan_cfg_get(wilc, !counter, - wids[counter].id, - (counter == count - 1), - drv)) { - ret = -ETIMEDOUT; - printk("[Sendconfigpkt]Get Timed out\n"); - break; - } - } - counter = 0; - for (counter = 0; counter < count; counter++) { - wids[counter].size = wilc_wlan_cfg_get_val( - wids[counter].id, - wids[counter].val, - wids[counter].size); - } - } else if (mode == SET_CFG) { - for (counter = 0; counter < count; counter++) { - PRINT_D(CORECONFIG_DBG, "Sending config SET PACKET WID:%x\n", wids[counter].id); - if (!wilc_wlan_cfg_set(wilc, !counter, - wids[counter].id, - wids[counter].val, - wids[counter].size, - (counter == count - 1), - drv)) { - ret = -ETIMEDOUT; - printk("[Sendconfigpkt]Set Timed out\n"); - break; - } - } - } - - return ret; -} diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index fc43d04ca1da..ee107ac915e0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -70,13 +70,6 @@ typedef enum { CONNECT_STS_FORCE_16_BIT = 0xFFFF } tenuConnectSts; -struct wid { - u16 id; - enum wid_type type; - s32 size; - s8 *val; -}; - typedef struct { u8 u8Full; u8 u8Index; @@ -127,8 +120,6 @@ typedef struct { size_t ie_len; } tstrDisconnectNotifInfo; -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, - u32 count, u32 drv); s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 04d4c92e3948..265ddfe3a924 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1439,6 +1439,45 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) return ret; } +s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, + u32 count, u32 drv) +{ + s32 counter = 0, ret = 0; + + if (mode == GET_CFG) { + for (counter = 0; counter < count; counter++) { + if (!wilc_wlan_cfg_get(wilc, !counter, + wids[counter].id, + (counter == count - 1), + drv)) { + ret = -ETIMEDOUT; + break; + } + } + counter = 0; + for (counter = 0; counter < count; counter++) { + wids[counter].size = wilc_wlan_cfg_get_val( + wids[counter].id, + wids[counter].val, + wids[counter].size); + } + } else if (mode == SET_CFG) { + for (counter = 0; counter < count; counter++) { + if (!wilc_wlan_cfg_set(wilc, !counter, + wids[counter].id, + wids[counter].val, + wids[counter].size, + (counter == count - 1), + drv)) { + ret = -ETIMEDOUT; + break; + } + } + } + + return ret; +} + static u32 init_chip(struct net_device *dev) { u32 chipid; diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 7f046531be01..3ebaf0e3e6bd 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -299,4 +299,6 @@ void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; void chip_allow_sleep(struct wilc *wilc); void chip_wakeup(struct wilc *wilc); +s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, + u32 count, u32 drv); #endif diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index c446af60dfe8..455a98fb9b20 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -300,6 +300,13 @@ enum wid_type { WID_TYPE_FORCE_32BIT = 0xFFFFFFFF }; +struct wid { + u16 id; + enum wid_type type; + s32 size; + s8 *val; +}; + typedef enum { WID_NIL = 0xffff, -- cgit From 79df6a490bb0d6d71e97441d4cd3d10d986d5cb3 Mon Sep 17 00:00:00 2001 From: Glen Lee Date: Thu, 4 Feb 2016 18:15:31 +0900 Subject: staging: wilc1000: pass vif to wilc_send_config_pkt This patch passes vif instead of wilc to wilc_send_config_pkt and it's related functions as well, because we need vif which is currently being used and vif has wilc as well. Change custom print with netdev_xxx format if there are custom print inside the functions we have changed. Function parameter of following functions are modified to vif. wilc_send_config_pkt wilc_wlan_cfg_set wilc_wlan_cfg_get wilc_wlan_cfg_commit wilc_wlan_txq_add_cfg_pkt wilc_wlan_txq_add_to_head Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 94 +++++++++++++++---------------- drivers/staging/wilc1000/linux_wlan.c | 88 ++++++++++++++--------------- drivers/staging/wilc1000/wilc_wlan.c | 57 +++++++++++-------- drivers/staging/wilc1000/wilc_wlan.h | 7 ++- 4 files changed, 128 insertions(+), 118 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 67bcf889287e..6f583a4224a6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -312,7 +312,7 @@ static s32 handle_set_channel(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting channel\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -334,7 +334,7 @@ static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, wid.val = (s8 *)hif_drv_handler; wid.size = sizeof(*hif_drv_handler); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, hif_drv_handler->handler); if (!hif_drv_handler->handler) @@ -359,7 +359,7 @@ static s32 handle_set_operation_mode(struct wilc_vif *vif, wid.val = (s8 *)&hif_op_mode->mode; wid.size = sizeof(u32); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if ((hif_op_mode->mode) == IDLE_MODE) @@ -392,7 +392,7 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) wid.val = (u8 *)ip_addr; wid.size = IP_ALEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); host_int_get_ipaddress(vif, firmware_ip_addr, idx); @@ -417,7 +417,7 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) wid.val = kmalloc(IP_ALEN, GFP_KERNEL); wid.size = IP_ALEN; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val); @@ -460,7 +460,7 @@ static s32 handle_set_mac_address(struct wilc_vif *vif, wid.size = ETH_ALEN; PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to set mac address\n"); @@ -482,7 +482,7 @@ static s32 handle_get_mac_address(struct wilc_vif *vif, wid.val = get_mac_addr->mac_addr; wid.size = ETH_ALEN; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -778,7 +778,7 @@ static s32 handle_cfg_param(struct wilc_vif *vif, wid_cnt++; } - result = wilc_send_config_pkt(vif->wilc, SET_CFG, wid_list, + result = wilc_send_config_pkt(vif, SET_CFG, wid_list, wid_cnt, wilc_get_vif_idx(vif)); if (result) @@ -902,7 +902,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, else if (hif_drv->hif_state == HOST_IF_IDLE) scan_while_connected = false; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(vif)); @@ -948,7 +948,7 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, wid.val = (s8 *)&u8abort_running_scan; wid.size = sizeof(char); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -1204,7 +1204,7 @@ static s32 Handle_Connect(struct wilc_vif *vif, PRINT_D(GENERIC_DBG, "save bssid = %pM\n", wilc_connected_ssid); } - result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(vif)); if (result) { @@ -1302,7 +1302,7 @@ static s32 Handle_FlushConnect(struct wilc_vif *vif) u32WidsCount++; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(join_req_vif)); if (result) { @@ -1365,7 +1365,7 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send dissconect config packet\n"); @@ -1758,7 +1758,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[2].size = pstrHostIFkeyAttr->attr.wep.key_len + 2; strWIDList[2].val = (s8 *)pu8keybuf; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, 3, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1780,7 +1780,7 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = (s8 *)pu8keybuf; wid.size = pstrHostIFkeyAttr->attr.wep.key_len + 2; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1793,7 +1793,7 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = s8idxarray; wid.size = 1; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); } else if (pstrHostIFkeyAttr->action & DEFAULTKEY) { @@ -1804,7 +1804,7 @@ static int Handle_Key(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Setting default key index\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); } @@ -1838,7 +1838,7 @@ static int Handle_Key(struct wilc_vif *vif, strWIDList[1].val = (s8 *)pu8keybuf; strWIDList[1].size = RX_MIC_KEY_MSG_LEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, 2, wilc_get_vif_idx(vif)); @@ -1870,7 +1870,7 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = (s8 *)pu8keybuf; wid.size = RX_MIC_KEY_MSG_LEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1910,7 +1910,7 @@ _WPARxGtk_end_case_: strWIDList[1].val = (s8 *)pu8keybuf; strWIDList[1].size = PTK_KEY_MSG_LEN + 1; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, 2, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1933,7 +1933,7 @@ _WPARxGtk_end_case_: wid.val = (s8 *)pu8keybuf; wid.size = PTK_KEY_MSG_LEN; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -1969,7 +1969,7 @@ _WPAPtk_end_case_: wid.val = (s8 *)pu8keybuf; wid.size = (pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); kfree(pu8keybuf); @@ -2002,7 +2002,7 @@ static void Handle_Disconnect(struct wilc_vif *vif) eth_zero_addr(wilc_connected_ssid); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2093,7 +2093,7 @@ static s32 Handle_GetChnl(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting channel value\n"); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2118,7 +2118,7 @@ static void Handle_GetRssi(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get RSSI value\n"); @@ -2143,7 +2143,7 @@ static void Handle_GetLinkspeed(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to get LINKSPEED value\n"); @@ -2189,7 +2189,7 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, strWIDList[u32WidsCount].val = (s8 *)&pstrStatistics->tx_fail_cnt; u32WidsCount++; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, strWIDList, + result = wilc_send_config_pkt(vif, GET_CFG, strWIDList, u32WidsCount, wilc_get_vif_idx(vif)); @@ -2225,7 +2225,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, PRINT_D(CFG80211_DBG, "SETING STA inactive time\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2238,7 +2238,7 @@ static s32 Handle_Get_InActiveTime(struct wilc_vif *vif, wid.val = (s8 *)&inactive_time; wid.size = sizeof(u32); - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2297,8 +2297,8 @@ static void Handle_AddBeacon(struct wilc_vif *vif, memcpy(pu8CurrByte, pstrSetBeaconParam->tail, pstrSetBeaconParam->tail_len); pu8CurrByte += pstrSetBeaconParam->tail_len; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add beacon config packet\n"); @@ -2326,7 +2326,7 @@ static void Handle_DelBeacon(struct wilc_vif *vif) PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send delete beacon config packet\n"); @@ -2399,7 +2399,7 @@ static void Handle_AddStation(struct wilc_vif *vif, pu8CurrByte = wid.val; pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to send add station config packet\n"); @@ -2441,7 +2441,7 @@ static void Handle_DelAllSta(struct wilc_vif *vif, pu8CurrByte += ETH_ALEN; } - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2473,7 +2473,7 @@ static void Handle_DelStation(struct wilc_vif *vif, memcpy(pu8CurrByte, pstrDelStaParam->mac_addr, ETH_ALEN); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send add station config packet\n"); @@ -2501,7 +2501,7 @@ static void Handle_EditStation(struct wilc_vif *vif, pu8CurrByte = wid.val; pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send edit station config packet\n"); @@ -2563,7 +2563,7 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, wid.val[0] = u8remain_on_chan_flag; wid.val[1] = (s8)pstrHostIfRemainOnChan->ch; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result != 0) PRINT_ER("Failed to set remain on channel\n"); @@ -2611,7 +2611,7 @@ static int Handle_RegisterFrame(struct wilc_vif *vif, wid.size = sizeof(u16) + 2; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { PRINT_ER("Failed to frame register config packet\n"); @@ -2646,7 +2646,7 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, wid.val[0] = u8remain_on_chan_flag; wid.val[1] = FALSE_FRMWR_CHANNEL; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result != 0) { PRINT_ER("Failed to set remain on channel\n"); @@ -2704,7 +2704,7 @@ static void Handle_PowerManagement(struct wilc_vif *vif, PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send power management config packet\n"); @@ -2741,7 +2741,7 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif, memcpy(pu8CurrByte, wilc_multicast_mac_addr_list, ((strHostIfSetMulti->cnt) * ETH_ALEN)); - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_ER("Failed to send setup multicast config packet\n"); @@ -2777,7 +2777,7 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, *ptr++ = 0; *ptr++ = 32; - result = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); @@ -2799,8 +2799,8 @@ static void handle_set_tx_pwr(struct wilc_vif *vif, u8 tx_pwr) wid.val = &tx_pwr; wid.size = sizeof(char); - ret = wilc_send_config_pkt(vif->wilc, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (ret) netdev_err(vif->ndev, "Failed to set TX PWR\n"); } @@ -2815,8 +2815,8 @@ static void handle_get_tx_pwr(struct wilc_vif *vif, u8 *tx_pwr) wid.val = (s8 *)tx_pwr; wid.size = sizeof(char); - ret = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + ret = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); if (ret) netdev_err(vif->ndev, "Failed to get TX PWR\n"); @@ -3513,7 +3513,7 @@ static s32 host_int_get_assoc_res_info(struct wilc_vif *vif, wid.val = pu8AssocRespInfo; wid.size = u32MaxAssocRespInfoLen; - result = wilc_send_config_pkt(vif->wilc, GET_CFG, &wid, 1, + result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { *pu32RcvdAssocRespInfoLen = 0; diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 9de57aeb50d4..a3b4939048d8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -526,86 +526,86 @@ static int linux_wlan_init_test_config(struct net_device *dev, *(int *)c_val = 1; - if (!wilc_wlan_cfg_set(wilc, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 1, WID_SET_DRV_HANDLER, c_val, 4, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_PC_TEST_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = INFRASTRUCTURE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_BSS_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_BSS_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = RATE_AUTO; - if (!wilc_wlan_cfg_set(wilc, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = G_MIXED_11B_2_MODE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11G_OPERATING_MODE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11G_OPERATING_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_CURRENT_CHANNEL, c_val, 1, 0, 0)) goto _fail_; c_val[0] = G_SHORT_PREAMBLE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_PREAMBLE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_PREAMBLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = AUTO_PROT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_PROT_MECH, c_val, 1, 0, 0)) goto _fail_; c_val[0] = ACTIVE_SCAN; - if (!wilc_wlan_cfg_set(wilc, 0, WID_SCAN_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_SCAN_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = SITE_SURVEY_OFF; - if (!wilc_wlan_cfg_set(wilc, 0, WID_SITE_SURVEY, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_SITE_SURVEY, c_val, 1, 0, 0)) goto _fail_; *((int *)c_val) = 0xffff; - if (!wilc_wlan_cfg_set(wilc, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_RTS_THRESHOLD, c_val, 2, 0, 0)) goto _fail_; *((int *)c_val) = 2346; - if (!wilc_wlan_cfg_set(wilc, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_FRAG_THRESHOLD, c_val, 2, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_BCAST_SSID, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_BCAST_SSID, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_QOS_ENABLE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_QOS_ENABLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = NO_POWERSAVE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_POWER_MANAGEMENT, c_val, 1, 0, 0)) goto _fail_; c_val[0] = NO_SECURITY; /* NO_ENCRYPT, 0x79 */ - if (!wilc_wlan_cfg_set(wilc, 0, WID_11I_MODE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11I_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = OPEN_SYSTEM; - if (!wilc_wlan_cfg_set(wilc, 0, WID_AUTH_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_AUTH_TYPE, c_val, 1, 0, 0)) goto _fail_; strcpy(c_val, "123456790abcdef1234567890"); - if (!wilc_wlan_cfg_set(wilc, 0, WID_WEP_KEY_VALUE, c_val, + if (!wilc_wlan_cfg_set(vif, 0, WID_WEP_KEY_VALUE, c_val, (strlen(c_val) + 1), 0, 0)) goto _fail_; strcpy(c_val, "12345678"); - if (!wilc_wlan_cfg_set(wilc, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11I_PSK, c_val, (strlen(c_val)), 0, 0)) goto _fail_; strcpy(c_val, "password"); - if (!wilc_wlan_cfg_set(wilc, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1), + if (!wilc_wlan_cfg_set(vif, 0, WID_1X_KEY, c_val, (strlen(c_val) + 1), 0, 0)) goto _fail_; @@ -613,106 +613,106 @@ static int linux_wlan_init_test_config(struct net_device *dev, c_val[1] = 168; c_val[2] = 1; c_val[3] = 112; - if (!wilc_wlan_cfg_set(wilc, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_1X_SERV_ADDR, c_val, 4, 0, 0)) goto _fail_; c_val[0] = 3; - if (!wilc_wlan_cfg_set(wilc, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_LISTEN_INTERVAL, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 3; - if (!wilc_wlan_cfg_set(wilc, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_DTIM_PERIOD, c_val, 1, 0, 0)) goto _fail_; c_val[0] = NORMAL_ACK; - if (!wilc_wlan_cfg_set(wilc, 0, WID_ACK_POLICY, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_ACK_POLICY, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, + if (!wilc_wlan_cfg_set(vif, 0, WID_USER_CONTROL_ON_TX_POWER, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 48; - if (!wilc_wlan_cfg_set(wilc, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11A, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 28; - if (!wilc_wlan_cfg_set(wilc, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_TX_POWER_LEVEL_11B, c_val, 1, 0, 0)) goto _fail_; *((int *)c_val) = 100; - if (!wilc_wlan_cfg_set(wilc, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_BEACON_INTERVAL, c_val, 2, 0, 0)) goto _fail_; c_val[0] = REKEY_DISABLE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_POLICY, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_POLICY, c_val, 1, 0, 0)) goto _fail_; *((int *)c_val) = 84600; - if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PERIOD, c_val, 4, 0, 0)) goto _fail_; *((int *)c_val) = 500; - if (!wilc_wlan_cfg_set(wilc, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_REKEY_PACKET_COUNT, c_val, 4, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_SHORT_SLOT_ALLOWED, c_val, 1, 0, 0)) goto _fail_; c_val[0] = G_SELF_CTS_PROT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ERP_PROT_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_ENABLE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_ENABLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = HT_MIXED_MODE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_OPERATING_MODE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OPERATING_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_TXOP_PROT_DISABLE, c_val, 1, 0, 0)) goto _fail_; memcpy(c_val, mac_add, 6); - if (!wilc_wlan_cfg_set(wilc, 0, WID_MAC_ADDR, c_val, 6, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_MAC_ADDR, c_val, 6, 0, 0)) goto _fail_; c_val[0] = DETECT_PROTECT_REPORT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_OBSS_NONHT_DETECTION, c_val, 1, 0, 0)) goto _fail_; c_val[0] = RTS_CTS_NONHT_PROT; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_HT_PROT_TYPE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 0; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_RIFS_PROT_ENABLE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = MIMO_MODE; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0)) + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_SMPS_MODE, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 7; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_CURRENT_TX_MCS, c_val, 1, 0, 0)) goto _fail_; c_val[0] = 1; - if (!wilc_wlan_cfg_set(wilc, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, + if (!wilc_wlan_cfg_set(vif, 0, WID_11N_IMMEDIATE_BA_ENABLED, c_val, 1, 1, 1)) goto _fail_; @@ -927,7 +927,7 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) goto _fail_irq_enable_; } - if (wilc_wlan_cfg_get(wl, 1, WID_FIRMWARE_VERSION, 1, 0)) { + if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; char Firmware_ver[20]; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 265ddfe3a924..392ef162772f 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -113,9 +113,11 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, up(&wilc->txq_event); } -static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) +static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, struct txq_entry_t *tqe) { unsigned long flags; + struct wilc *wilc = vif->wilc; + if (wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, CFG_PKTS_TIMEOUT)) return -1; @@ -134,12 +136,12 @@ static int wilc_wlan_txq_add_to_head(struct wilc *wilc, struct txq_entry_t *tqe) wilc->txq_head = tqe; } wilc->txq_entries += 1; - PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", wilc->txq_entries); + netdev_dbg(vif->ndev, "Number of entries in TxQ = %d\n", wilc->txq_entries); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); up(&wilc->txq_add_to_head_cs); up(&wilc->txq_event); - PRINT_D(TX_DBG, "Wake up the txq_handler\n"); + netdev_dbg(vif->ndev, "Wake up the txq_handler\n"); return 0; } @@ -351,20 +353,22 @@ static bool is_tcp_ack_filter_enabled(void) return enabled; } -static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_size) +static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, + u32 buffer_size) { struct txq_entry_t *tqe; + struct wilc *wilc = vif->wilc; - PRINT_D(TX_DBG, "Adding config packet ...\n"); + netdev_dbg(vif->ndev, "Adding config packet ...\n"); if (wilc->quit) { - PRINT_D(TX_DBG, "Return due to clear function\n"); + netdev_dbg(vif->ndev, "Return due to clear function\n"); up(&wilc->cfg_event); return 0; } tqe = kmalloc(sizeof(*tqe), GFP_ATOMIC); if (!tqe) { - PRINT_ER("Failed to allocate memory\n"); + netdev_err(vif->ndev, "Failed to allocate memory\n"); return 0; } @@ -374,9 +378,9 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc *wilc, u8 *buffer, u32 buffer_s tqe->tx_complete_func = NULL; tqe->priv = NULL; tqe->tcp_pending_ack_idx = NOT_TCP_ACK; - PRINT_D(TX_DBG, "Adding the config packet at the Queue tail\n"); + netdev_dbg(vif->ndev, "Adding the config packet at the Queue tail\n"); - if (wilc_wlan_txq_add_to_head(wilc, tqe)) + if (wilc_wlan_txq_add_to_head(vif, tqe)) return 0; return 1; } @@ -1326,8 +1330,10 @@ void wilc_wlan_cleanup(struct net_device *dev) wilc->hif_func->hif_deinit(NULL); } -static int wilc_wlan_cfg_commit(struct wilc *wilc, int type, u32 drv_handler) +static int wilc_wlan_cfg_commit(struct wilc_vif *vif, int type, + u32 drv_handler) { + struct wilc *wilc = vif->wilc; struct wilc_cfg_frame *cfg = &wilc->cfg_frame; int total_len = wilc->cfg_frame_offset + 4 + DRIVER_HANDLER_SIZE; int seq_no = wilc->cfg_seq_no % 256; @@ -1346,17 +1352,18 @@ static int wilc_wlan_cfg_commit(struct wilc *wilc, int type, u32 drv_handler) cfg->wid_header[7] = (u8)(driver_handler >> 24); wilc->cfg_seq_no = seq_no; - if (!wilc_wlan_txq_add_cfg_pkt(wilc, &cfg->wid_header[0], total_len)) + if (!wilc_wlan_txq_add_cfg_pkt(vif, &cfg->wid_header[0], total_len)) return -1; return 0; } -int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, +int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler) { u32 offset; int ret_size; + struct wilc *wilc = vif->wilc; if (wilc->cfg_frame_in_use) return 0; @@ -1371,17 +1378,18 @@ int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, wilc->cfg_frame_offset = offset; if (commit) { - PRINT_D(TX_DBG, "[WILC]PACKET Commit with sequence number %d\n", - wilc->cfg_seq_no); - PRINT_D(RX_DBG, "Processing cfg_set()\n"); + netdev_dbg(vif->ndev, + "[WILC]PACKET Commit with sequence number %d\n", + wilc->cfg_seq_no); + netdev_dbg(vif->ndev, "Processing cfg_set()\n"); wilc->cfg_frame_in_use = 1; - if (wilc_wlan_cfg_commit(wilc, WILC_CFG_SET, drv_handler)) + if (wilc_wlan_cfg_commit(vif, WILC_CFG_SET, drv_handler)) ret_size = 0; if (wilc_lock_timeout(wilc, &wilc->cfg_event, CFG_PKTS_TIMEOUT)) { - PRINT_D(TX_DBG, "Set Timed Out\n"); + netdev_dbg(vif->ndev, "Set Timed Out\n"); ret_size = 0; } wilc->cfg_frame_in_use = 0; @@ -1392,11 +1400,12 @@ int wilc_wlan_cfg_set(struct wilc *wilc, int start, u32 wid, u8 *buffer, return ret_size; } -int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit, +int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, u32 drv_handler) { u32 offset; int ret_size; + struct wilc *wilc = vif->wilc; if (wilc->cfg_frame_in_use) return 0; @@ -1413,15 +1422,15 @@ int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit, if (commit) { wilc->cfg_frame_in_use = 1; - if (wilc_wlan_cfg_commit(wilc, WILC_CFG_QUERY, drv_handler)) + if (wilc_wlan_cfg_commit(vif, WILC_CFG_QUERY, drv_handler)) ret_size = 0; if (wilc_lock_timeout(wilc, &wilc->cfg_event, CFG_PKTS_TIMEOUT)) { - PRINT_D(TX_DBG, "Get Timed Out\n"); + netdev_dbg(vif->ndev, "Get Timed Out\n"); ret_size = 0; } - PRINT_D(GENERIC_DBG, "[WILC]Get Response received\n"); + netdev_dbg(vif->ndev, "[WILC]Get Response received\n"); wilc->cfg_frame_in_use = 0; wilc->cfg_frame_offset = 0; wilc->cfg_seq_no += 1; @@ -1439,14 +1448,14 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) return ret; } -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, +s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv) { s32 counter = 0, ret = 0; if (mode == GET_CFG) { for (counter = 0; counter < count; counter++) { - if (!wilc_wlan_cfg_get(wilc, !counter, + if (!wilc_wlan_cfg_get(vif, !counter, wids[counter].id, (counter == count - 1), drv)) { @@ -1463,7 +1472,7 @@ s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, } } else if (mode == SET_CFG) { for (counter = 0; counter < count; counter++) { - if (!wilc_wlan_cfg_set(wilc, !counter, + if (!wilc_wlan_cfg_set(vif, !counter, wids[counter].id, wids[counter].val, wids[counter].size, diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index 3ebaf0e3e6bd..e913ae7abef7 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -268,6 +268,7 @@ struct wilc_cfg_rsp { }; struct wilc; +struct wilc_vif; int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); int wilc_wlan_start(struct wilc *); @@ -277,9 +278,9 @@ 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 *wilc, int start, u32 wid, u8 *buffer, +int wilc_wlan_cfg_set(struct wilc_vif *vif, int start, u32 wid, u8 *buffer, u32 buffer_size, int commit, u32 drv_handler); -int wilc_wlan_cfg_get(struct wilc *wilc, int start, u32 wid, int commit, +int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 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, @@ -299,6 +300,6 @@ void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; void chip_allow_sleep(struct wilc *wilc); void chip_wakeup(struct wilc *wilc); -s32 wilc_send_config_pkt(struct wilc *wilc, u8 mode, struct wid *wids, +s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv); #endif -- cgit From 48b28df99c302cd0e84b099c7333f921fb09ff35 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:32 +0900 Subject: staging: wilc1000: rename hWILCWFIDrv of wilc_priv structure This patch renames hWILCWFIDrv pointer variable of wilc_priv structure to hif_drv to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 8 ++++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 22 ++++++++++++---------- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index a3b4939048d8..06c79dd0bdd8 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -89,7 +89,7 @@ static int dev_state_ev_handler(struct notifier_block *this, unsigned long event PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); return NOTIFY_DONE; } - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; vif = netdev_priv(dev); if (!vif || !hif_drv) { PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); @@ -515,7 +515,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, PRINT_D(TX_DBG, "Start configuring Firmware\n"); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; PRINT_D(INIT_DBG, "Host = %p\n", hif_drv); wilc_get_mac_address(vif, mac_add); @@ -1089,7 +1089,7 @@ static void wilc_set_multicast_list(struct net_device *dev) priv = wiphy_priv(dev->ieee80211_ptr->wiphy); vif = netdev_priv(dev); - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; if (!dev) return; @@ -1228,7 +1228,7 @@ int wilc_mac_close(struct net_device *ndev) return 0; } - hif_drv = (struct host_if_drv *)priv->hWILCWFIDrv; + hif_drv = (struct host_if_drv *)priv->hif_drv; PRINT_D(GENERIC_DBG, "Mac close\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index fb940ed4d0ef..b8fd6956d4c5 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -512,7 +512,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, dev = priv->dev; vif = netdev_priv(dev); wl = vif->wilc; - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; if (enuConnDisconnEvent == CONN_DISCONN_EVENT_CONN_RESP) { u16 u16ConnectStatus; @@ -711,9 +711,11 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, wilc_connecting = 1; priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - pstrWFIDrv = (struct host_if_drv *)(priv->hWILCWFIDrv); + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; - PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv); + PRINT_D(CFG80211_DBG, + "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", + sme->ssid, dev, priv->hif_drv); if (!(strncmp(sme->ssid, "DIRECT-", 7))) { PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n"); pstrWFIDrv->p2p_connect = 1; @@ -928,7 +930,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; wilc_wlan_set_bssid(priv->dev, NullBssid, STATION_MODE); @@ -1276,7 +1278,7 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev, wilc_remove_wep_key(vif, key_index); } else { PRINT_D(CFG80211_DBG, "Removing all installed keys\n"); - wilc_remove_key(priv->hWILCWFIDrv, mac_addr); + wilc_remove_key(priv->hif_drv, mac_addr); } return 0; @@ -1632,7 +1634,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) s32 s32Freq; priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET); @@ -1844,7 +1846,7 @@ static int mgmt_tx(struct wiphy *wiphy, vif = netdev_priv(wdev->netdev); priv = wiphy_priv(wiphy); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; *cookie = (unsigned long)buf; priv->u64tx_cookie = *cookie; @@ -1970,7 +1972,7 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, struct host_if_drv *pstrWFIDrv; priv = wiphy_priv(wiphy); - pstrWFIDrv = (struct host_if_drv *)priv->hWILCWFIDrv; + pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies); @@ -2070,7 +2072,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - if (!priv->hWILCWFIDrv) { + if (!priv->hif_drv) { PRINT_ER("Driver is NULL\n"); return -EIO; } @@ -2715,7 +2717,7 @@ int wilc_init_host_int(struct net_device *net) priv->bInP2PlistenState = false; sema_init(&(priv->hSemScanReq), 1); - s32Error = wilc_init(net, &priv->hWILCWFIDrv); + s32Error = wilc_init(net, &priv->hif_drv); if (s32Error) PRINT_ER("Error while initializing hostinterface\n"); diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 07eda4db1dcd..64fcb777cc2d 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -121,7 +121,7 @@ struct wilc_priv { spinlock_t lock; struct net_device *dev; struct napi_struct napi; - struct host_if_drv *hWILCWFIDrv; + struct host_if_drv *hif_drv; struct host_if_pmkid_attr pmkid_list; struct WILC_WFI_stats netstats; u8 WILC_WFI_wep_key[4][WLAN_KEY_LEN_WEP104]; -- cgit From fa8b23c6f25dae2b83882feb1aadceece69d9cdf Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:33 +0900 Subject: staging: wilc1000: fixes missing a blank line after declarations This patch fixes the warnings reported by checkpatch.pl for Missing a blank line after declarations. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 06c79dd0bdd8..5992478015a2 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -853,6 +853,7 @@ static void wlan_deinitialize_threads(struct net_device *dev) { struct wilc_vif *vif; struct wilc *wl; + vif = netdev_priv(dev); wl = vif->wilc; @@ -1472,6 +1473,7 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, { struct wireless_dev *wdev; + wdev = wilc_create_wiphy(ndev, dev); if (dev) -- cgit From 5b9f526e79f347faa2fd3f9e09b226da63b95c7f Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:34 +0900 Subject: staging: wilc1000: rename pBssid of tx_complete_data structure This patch renames pBssid variable of tx_complete_data structure to bssid to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 2 +- drivers/staging/wilc1000/wilc_wlan_if.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 5992478015a2..f5f787ef90c0 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1193,7 +1193,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n"); vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; - tx_data->pBssid = wilc->vif[vif->u8IfIdx]->bssid; + tx_data->bssid = wilc->vif[vif->u8IfIdx]->bssid; queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data, tx_data->buff, tx_data->size, linux_wlan_tx_complete); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 392ef162772f..ebf38a578694 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -809,7 +809,7 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) if (tqe->type == WILC_CFG_PKT) { buffer_offset = ETH_CONFIG_PKT_HDR_OFFSET; } else if (tqe->type == WILC_NET_PKT) { - char *bssid = ((struct tx_complete_data *)(tqe->priv))->pBssid; + char *bssid = ((struct tx_complete_data *)(tqe->priv))->bssid; buffer_offset = ETH_ETHERNET_HDR_OFFSET; memcpy(&txb[offset + 4], bssid, 6); diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 455a98fb9b20..294552dda7b5 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -82,7 +82,7 @@ typedef struct { struct tx_complete_data { int size; void *buff; - u8 *pBssid; + u8 *bssid; struct sk_buff *skb; }; -- cgit From 885cabccf9e834b4208873a7168f6fef7d0c0104 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:35 +0900 Subject: staging: wilc1000: remove warnings line over 80 characters This patch removes the warnings reported by checkpatch.pl for line over 80 characters. Signed-off-by: Leo Kim Signed-off-by: Glen Lee 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 f5f787ef90c0..1446b194c4ef 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -25,7 +25,8 @@ #include -static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr); +static int dev_state_ev_handler(struct notifier_block *this, + unsigned long event, void *ptr); static struct notifier_block g_dev_notifier = { .notifier_call = dev_state_ev_handler @@ -57,7 +58,8 @@ static const struct net_device_ops wilc_netdev_ops = { }; -static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr) +static int dev_state_ev_handler(struct notifier_block *this, + unsigned long event, void *ptr) { struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr; struct wilc_priv *priv; -- cgit From 1408603c95133c38b950498205c4d9d012a7086a Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:36 +0900 Subject: staging: wilc1000: removes unnecessary debug logs This patch removes unnecessary debug logs. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 154 ++++++---------------------------- 1 file changed, 24 insertions(+), 130 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 1446b194c4ef..13c6cb2b676f 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -70,47 +70,32 @@ static int dev_state_ev_handler(struct notifier_block *this, u8 null_ip[4] = {0}; char wlan_dev_name[5] = "wlan0"; - if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) { - PRINT_D(GENERIC_DBG, "dev_iface = NULL\n"); + if (!dev_iface || !dev_iface->ifa_dev || !dev_iface->ifa_dev->dev) return NOTIFY_DONE; - } if (memcmp(dev_iface->ifa_label, "wlan0", 5) && - memcmp(dev_iface->ifa_label, "p2p0", 4)) { - PRINT_D(GENERIC_DBG, "Interface is neither WLAN0 nor P2P0\n"); + memcmp(dev_iface->ifa_label, "p2p0", 4)) return NOTIFY_DONE; - } dev = (struct net_device *)dev_iface->ifa_dev->dev; - if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) { - PRINT_D(GENERIC_DBG, "No Wireless registerd\n"); + if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy) return NOTIFY_DONE; - } + priv = wiphy_priv(dev->ieee80211_ptr->wiphy); - if (!priv) { - PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); + if (!priv) return NOTIFY_DONE; - } + hif_drv = (struct host_if_drv *)priv->hif_drv; vif = netdev_priv(dev); - if (!vif || !hif_drv) { - PRINT_D(GENERIC_DBG, "No Wireless Priv\n"); + if (!vif || !hif_drv) return NOTIFY_DONE; - } - - PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler +++\n"); switch (event) { case NETDEV_UP: - PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_UP %p\n", dev); - - PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n"); - if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) { hif_drv->IFC_UP = 1; wilc_optaining_ip = false; del_timer(&wilc_during_ip_timer); - PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n"); } if (wilc_enable_ps) @@ -127,9 +112,6 @@ static int dev_state_ev_handler(struct notifier_block *this, break; case NETDEV_DOWN: - PRINT_D(GENERIC_DBG, "dev_state_ev_handler event=NETDEV_DOWN %p\n", dev); - - PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Released ===============\n\n"); if (vif->iftype == STATION_MODE || vif->iftype == CLIENT_MODE) { hif_drv->IFC_UP = 0; wilc_optaining_ip = false; @@ -152,9 +134,6 @@ static int dev_state_ev_handler(struct notifier_block *this, break; default: - PRINT_INFO(GENERIC_DBG, "dev_state_ev_handler event=default\n"); - PRINT_INFO(GENERIC_DBG, "[%s] unknown dev event: %lu\n", dev_iface->ifa_label, event); - break; } @@ -169,7 +148,6 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INT_DBG, "Interrupt received UH\n"); if (wilc->close) { PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n"); @@ -191,7 +169,6 @@ static irqreturn_t isr_bh_routine(int irq, void *userdata) return IRQ_HANDLED; } - PRINT_D(INT_DBG, "Interrupt received BH\n"); wilc_handle_isr(wilc); return IRQ_HANDLED; @@ -255,12 +232,9 @@ int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout) /* FIXME: replace with mutex_lock or wait_for_completion */ int error = -1; - PRINT_D(LOCK_DBG, "Locking %p\n", vp); if (vp) error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout)); - else - PRINT_ER("Failed, mutex is NULL\n"); return error; } @@ -358,28 +332,21 @@ static int linux_wlan_txq_task(void *vp) up(&wl->txq_thread_started); while (1) { - PRINT_D(TX_DBG, "txq_task Taking a nap :)\n"); down(&wl->txq_event); - PRINT_D(TX_DBG, "txq_task Who waked me up :$\n"); if (wl->close) { up(&wl->txq_thread_started); while (!kthread_should_stop()) schedule(); - - PRINT_D(TX_DBG, "TX thread stopped\n"); break; } - PRINT_D(TX_DBG, "txq_task handle the sending packet and let me go to sleep.\n"); #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) { - PRINT_D(TX_DBG, "Waking up queue\n"); - if (netif_queue_stopped(wl->vif[0]->ndev)) netif_wake_queue(wl->vif[0]->ndev); if (netif_queue_stopped(wl->vif[1]->ndev)) @@ -428,15 +395,11 @@ int wilc_wlan_get_firmware(struct net_device *dev) netdev_info(dev, "loading firmware %s\n", firmware); - if (!vif) { - PRINT_ER("vif is NULL\n"); + if (!vif) goto _fail_; - } - if (!(&vif->ndev->dev)) { - PRINT_ER("&vif->ndev->dev is NULL\n"); + if (!(&vif->ndev->dev)) goto _fail_; - } if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) { PRINT_ER("%s - firmare not available\n", firmware); @@ -459,20 +422,13 @@ static int linux_wlan_start_firmware(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INIT_DBG, "Starting Firmware ...\n"); ret = wilc_wlan_start(wilc); - if (ret < 0) { - PRINT_ER("Failed to start Firmware\n"); + if (ret < 0) return ret; - } - PRINT_D(INIT_DBG, "Waiting for Firmware to get ready ...\n"); ret = wilc_lock_timeout(wilc, &wilc->sync_event, 5000); - if (ret) { - PRINT_D(INIT_DBG, "Firmware start timed out"); + if (ret) return ret; - } - PRINT_D(INIT_DBG, "Firmware successfully started\n"); return 0; } @@ -490,14 +446,12 @@ static int wilc1000_firmware_download(struct net_device *dev) PRINT_ER("Firmware buffer is NULL\n"); return -ENOBUFS; } - PRINT_D(INIT_DBG, "Downloading Firmware ...\n"); + ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data, wilc->firmware->size); if (ret < 0) return ret; - PRINT_D(INIT_DBG, "Freeing FW buffer ...\n"); - PRINT_D(INIT_DBG, "Releasing firmware\n"); release_firmware(wilc->firmware); wilc->firmware = NULL; @@ -740,7 +694,6 @@ void wilc1000_wlan_deinit(struct net_device *dev) if (wl->initialized) { netdev_info(dev, "Deinitializing wilc1000...\n"); - PRINT_D(INIT_DBG, "Disabling IRQ\n"); if (!wl->dev_irq_num && wl->hif_func->disable_interrupt) { mutex_lock(&wl->hif_cs); @@ -750,29 +703,19 @@ void wilc1000_wlan_deinit(struct net_device *dev) if (&wl->txq_event) up(&wl->txq_event); - PRINT_D(INIT_DBG, "Deinitializing Threads\n"); wlan_deinitialize_threads(dev); - - PRINT_D(INIT_DBG, "Deinitializing IRQ\n"); deinit_irq(dev); wilc_wlan_stop(wl); - - PRINT_D(INIT_DBG, "Deinitializing WILC Wlan\n"); 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) { - - PRINT_D(INIT_DBG, "Disabling IRQ 2\n"); - mutex_lock(&wl->hif_cs); wl->hif_func->disable_interrupt(wl); mutex_unlock(&wl->hif_cs); } #endif - - PRINT_D(INIT_DBG, "Deinitializing Locks\n"); wlan_deinit_locks(dev); wl->initialized = false; @@ -792,8 +735,6 @@ static int wlan_init_locks(struct net_device *dev) vif = netdev_priv(dev); wl = vif->wilc; - PRINT_D(INIT_DBG, "Initializing Locks ...\n"); - mutex_init(&wl->hif_cs); mutex_init(&wl->rxq_cs); @@ -818,8 +759,6 @@ static int wlan_deinit_locks(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INIT_DBG, "De-Initializing Locks\n"); - if (&wilc->hif_cs) mutex_destroy(&wilc->hif_cs); @@ -837,8 +776,6 @@ static int wlan_initialize_threads(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(INIT_DBG, "Initializing Threads ...\n"); - PRINT_D(INIT_DBG, "Creating kthread for transmission\n"); wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev, "K_TXQ_TASK"); if (!wilc->txq_thread) { @@ -860,7 +797,6 @@ static void wlan_deinitialize_threads(struct net_device *dev) wl = vif->wilc; wl->close = 1; - PRINT_D(INIT_DBG, "Deinitializing Threads\n"); if (&wl->txq_event) up(&wl->txq_event); @@ -884,20 +820,17 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) ret = wilc_wlan_init(dev); if (ret < 0) { - PRINT_ER("Initializing WILC_Wlan FAILED\n"); ret = -EIO; goto _fail_locks_; } if (wl->gpio >= 0 && init_irq(dev)) { - PRINT_ER("couldn't initialize IRQ\n"); ret = -EIO; goto _fail_locks_; } ret = wlan_initialize_threads(dev); if (ret < 0) { - PRINT_ER("Initializing Threads FAILED\n"); ret = -EIO; goto _fail_wilc_wlan_; } @@ -905,27 +838,23 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) if (!wl->dev_irq_num && wl->hif_func->enable_interrupt && wl->hif_func->enable_interrupt(wl)) { - PRINT_ER("couldn't initialize IRQ\n"); ret = -EIO; goto _fail_irq_init_; } if (wilc_wlan_get_firmware(dev)) { - PRINT_ER("Can't get firmware\n"); ret = -EIO; goto _fail_irq_enable_; } ret = wilc1000_firmware_download(dev); if (ret < 0) { - PRINT_ER("Failed to download firmware\n"); ret = -EIO; goto _fail_irq_enable_; } ret = linux_wlan_start_firmware(dev); if (ret < 0) { - PRINT_ER("Failed to start firmware\n"); ret = -EIO; goto _fail_irq_enable_; } @@ -1007,16 +936,11 @@ int wilc_mac_open(struct net_device *ndev) PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev); ret = wilc_init_host_int(ndev); - if (ret < 0) { - PRINT_ER("Failed to initialize host interface\n"); - + if (ret < 0) return ret; - } - PRINT_D(INIT_DBG, "*** re-init ***\n"); ret = wilc1000_wlan_init(ndev, vif); if (ret < 0) { - PRINT_ER("Failed to initialize wilc1000\n"); wilc_deinit_host_int(ndev); return ret; } @@ -1097,23 +1021,16 @@ static void wilc_set_multicast_list(struct net_device *dev) if (!dev) return; - PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", - dev->mc.count); - - if (dev->flags & IFF_PROMISC) { - PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n"); + if (dev->flags & IFF_PROMISC) return; - } if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) { - PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n"); wilc_setup_multicast_filter(vif, false, 0); return; } if ((dev->mc.count) == 0) { - PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n"); wilc_setup_multicast_filter(vif, true, 0); return; } @@ -1160,8 +1077,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) vif = netdev_priv(ndev); wilc = vif->wilc; - PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n"); - if (skb->dev != ndev) { PRINT_ER("Packet not destined to this device\n"); return 0; @@ -1169,7 +1084,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC); if (!tx_data) { - PRINT_ER("Failed to allocate memory for tx_data structure\n"); dev_kfree_skb(skb); netif_wake_queue(ndev); return 0; @@ -1191,8 +1105,6 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", udp_buf[248], udp_buf[249], udp_buf[250]); - PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb); - PRINT_D(TX_DBG, "Adding tx packet to TX Queue\n"); vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; tx_data->bssid = wilc->vif[vif->u8IfIdx]->bssid; @@ -1218,39 +1130,29 @@ int wilc_mac_close(struct net_device *ndev) vif = netdev_priv(ndev); if (!vif || !vif->ndev || !vif->ndev->ieee80211_ptr || - !vif->ndev->ieee80211_ptr->wiphy) { - PRINT_ER("vif = NULL\n"); + !vif->ndev->ieee80211_ptr->wiphy) return 0; - } priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); wl = vif->wilc; - if (!priv) { - PRINT_ER("priv = NULL\n"); + if (!priv) return 0; - } hif_drv = (struct host_if_drv *)priv->hif_drv; PRINT_D(GENERIC_DBG, "Mac close\n"); - if (!wl) { - PRINT_ER("wl = NULL\n"); + if (!wl) return 0; - } - if (!hif_drv) { - PRINT_ER("hif_drv = NULL\n"); + if (!hif_drv) return 0; - } - if ((wl->open_ifcs) > 0) { + if ((wl->open_ifcs) > 0) wl->open_ifcs--; - } else { - PRINT_ER("ERROR: MAC close called while number of opened interfaces is zero\n"); + else return 0; - } if (vif->ndev) { netif_stop_queue(vif->ndev); @@ -1303,8 +1205,6 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) if (strncasecmp(buff, "RSSI", length) == 0) { priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); ret = wilc_get_rssi(vif, &rssi); - if (ret) - PRINT_ER("Failed to send get rssi param's message queue "); PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi); rssi += 5; @@ -1360,10 +1260,9 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) buff_to_send = buff; skb = dev_alloc_skb(frame_len); - if (!skb) { - PRINT_ER("Low memory - packet droped\n"); + if (!skb) return; - } + skb->dev = wilc_netdev; memcpy(skb_put(skb, frame_len), buff_to_send, frame_len); @@ -1453,10 +1352,8 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, for (i = 0; i < NUM_CONCURRENT_IFC; i++) { ndev = alloc_etherdev(sizeof(struct wilc_vif)); - if (!ndev) { - PRINT_ER("Failed to allocate ethernet dev\n"); + if (!ndev) return -1; - } vif = netdev_priv(ndev); memset(vif, 0, sizeof(struct wilc_vif)); @@ -1495,11 +1392,8 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, vif->netstats.tx_bytes = 0; } - if (register_netdev(ndev)) { - PRINT_ER("Device couldn't be registered - %s\n", - ndev->name); + if (register_netdev(ndev)) return -1; - } vif->iftype = STATION_MODE; vif->mac_opened = 0; -- cgit From 5ac2442732c32aae692e11f45f7bfcfe238e4631 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:37 +0900 Subject: staging: wilc1000: replaces PRINT_XXX with netdev_xxx This patches replaces PRINT_XXX with netdev_xxx. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 109 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 13c6cb2b676f..c16cc4031cfb 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -101,12 +101,12 @@ static int dev_state_ev_handler(struct notifier_block *this, if (wilc_enable_ps) wilc_set_power_mgmt(vif, 1, 0); - PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label); + netdev_dbg(dev, "[%s] Up IP\n", dev_iface->ifa_label); ip_addr_buf = (char *)&dev_iface->ifa_address; - PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", - ip_addr_buf[0], ip_addr_buf[1], - ip_addr_buf[2], ip_addr_buf[3]); + netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); break; @@ -122,12 +122,12 @@ static int dev_state_ev_handler(struct notifier_block *this, wilc_resolve_disconnect_aberration(vif); - PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label); + netdev_dbg(dev, "[%s] Down IP\n", dev_iface->ifa_label); ip_addr_buf = null_ip; - PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", - ip_addr_buf[0], ip_addr_buf[1], - ip_addr_buf[2], ip_addr_buf[3]); + netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); @@ -150,7 +150,7 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) wilc = vif->wilc; if (wilc->close) { - PRINT_ER("Driver is CLOSING: Can't handle UH interrupt\n"); + netdev_err(dev, "Can't handle UH interrupt\n"); return IRQ_HANDLED; } return IRQ_WAKE_THREAD; @@ -160,12 +160,13 @@ static irqreturn_t isr_bh_routine(int irq, void *userdata) { struct wilc_vif *vif; struct wilc *wilc; + struct net_device *dev = (struct net_device *)userdata; vif = netdev_priv(userdata); wilc = vif->wilc; if (wilc->close) { - PRINT_ER("Driver is CLOSING: Can't handle BH interrupt\n"); + netdev_err(dev, "Can't handle BH interrupt\n"); return IRQ_HANDLED; } @@ -188,7 +189,7 @@ static int init_irq(struct net_device *dev) wl->dev_irq_num = gpio_to_irq(wl->gpio); } else { ret = -1; - PRINT_ER("could not obtain gpio for WILC_INTR\n"); + netdev_err(dev, "could not obtain gpio for WILC_INTR\n"); } if (ret != -1 && request_threaded_irq(wl->dev_irq_num, @@ -196,12 +197,13 @@ static int init_irq(struct net_device *dev) isr_bh_routine, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "WILC_IRQ", dev) < 0) { - PRINT_ER("Failed to request IRQ for GPIO: %d\n", wl->gpio); + netdev_err(dev, "Failed to request IRQ GPIO: %d\n", wl->gpio); gpio_free(wl->gpio); ret = -1; } else { - PRINT_D(INIT_DBG, "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n", - wl->dev_irq_num, wl->gpio); + netdev_dbg(dev, + "IRQ request succeeded IRQ-NUM= %d on GPIO: %d\n", + wl->dev_irq_num, wl->gpio); } return ret; @@ -402,7 +404,7 @@ int wilc_wlan_get_firmware(struct net_device *dev) goto _fail_; if (request_firmware(&wilc_firmware, firmware, wilc->dev) != 0) { - PRINT_ER("%s - firmare not available\n", firmware); + netdev_err(dev, "%s - firmare not available\n", firmware); ret = -1; goto _fail_; } @@ -443,7 +445,7 @@ static int wilc1000_firmware_download(struct net_device *dev) wilc = vif->wilc; if (!wilc->firmware) { - PRINT_ER("Firmware buffer is NULL\n"); + netdev_err(dev, "Firmware buffer is NULL\n"); return -ENOBUFS; } @@ -455,7 +457,7 @@ static int wilc1000_firmware_download(struct net_device *dev) release_firmware(wilc->firmware); wilc->firmware = NULL; - PRINT_D(INIT_DBG, "Download Succeeded\n"); + netdev_dbg(dev, "Download Succeeded\n"); return 0; } @@ -469,15 +471,13 @@ static int linux_wlan_init_test_config(struct net_device *dev, struct wilc_priv *priv; struct host_if_drv *hif_drv; - PRINT_D(TX_DBG, "Start configuring Firmware\n"); + netdev_dbg(dev, "Start configuring Firmware\n"); priv = wiphy_priv(dev->ieee80211_ptr->wiphy); hif_drv = (struct host_if_drv *)priv->hif_drv; - PRINT_D(INIT_DBG, "Host = %p\n", hif_drv); + netdev_dbg(dev, "Host = %p\n", hif_drv); wilc_get_mac_address(vif, mac_add); - PRINT_D(INIT_DBG, "MAC address is : %02x-%02x-%02x-%02x-%02x-%02x\n", - mac_add[0], mac_add[1], mac_add[2], - mac_add[3], mac_add[4], mac_add[5]); + netdev_dbg(dev, "MAC address is : %pM\n", mac_add); wilc_get_chipid(wilc, 0); *(int *)c_val = 1; @@ -720,10 +720,9 @@ void wilc1000_wlan_deinit(struct net_device *dev) wl->initialized = false; - PRINT_D(INIT_DBG, "wilc1000 deinitialization Done\n"); - + netdev_dbg(dev, "wilc1000 deinitialization Done\n"); } else { - PRINT_D(INIT_DBG, "wilc1000 is not initialized\n"); + netdev_dbg(dev, "wilc1000 is not initialized\n"); } } @@ -779,7 +778,7 @@ static int wlan_initialize_threads(struct net_device *dev) wilc->txq_thread = kthread_run(linux_wlan_txq_task, (void *)dev, "K_TXQ_TASK"); if (!wilc->txq_thread) { - PRINT_ER("couldn't create TXQ thread\n"); + netdev_err(dev, "couldn't create TXQ thread\n"); wilc->close = 0; return -ENOBUFS; } @@ -861,18 +860,18 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif) if (wilc_wlan_cfg_get(vif, 1, WID_FIRMWARE_VERSION, 1, 0)) { int size; - char Firmware_ver[20]; + char firmware_ver[20]; - size = wilc_wlan_cfg_get_val( - WID_FIRMWARE_VERSION, - Firmware_ver, sizeof(Firmware_ver)); - Firmware_ver[size] = '\0'; - PRINT_D(INIT_DBG, "***** Firmware Ver = %s *******\n", Firmware_ver); + size = wilc_wlan_cfg_get_val(WID_FIRMWARE_VERSION, + firmware_ver, + sizeof(firmware_ver)); + firmware_ver[size] = '\0'; + netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver); } ret = linux_wlan_init_test_config(dev, vif); if (ret < 0) { - PRINT_ER("Failed to configure firmware\n"); + netdev_err(dev, "Failed to configure firmware\n"); ret = -EIO; goto _fail_fw_start_; } @@ -896,9 +895,9 @@ _fail_wilc_wlan_: wilc_wlan_cleanup(dev); _fail_locks_: wlan_deinit_locks(dev); - PRINT_ER("WLAN Iinitialization FAILED\n"); + netdev_err(dev, "WLAN Iinitialization FAILED\n"); } else { - PRINT_D(INIT_DBG, "wilc1000 already initialized\n"); + netdev_dbg(dev, "wilc1000 already initialized\n"); } return ret; } @@ -933,7 +932,7 @@ int wilc_mac_open(struct net_device *ndev) vif = netdev_priv(ndev); wilc = vif->wilc; priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); - PRINT_D(INIT_DBG, "MAC OPEN[%p]\n", ndev); + netdev_dbg(ndev, "MAC OPEN[%p]\n", ndev); ret = wilc_init_host_int(ndev); if (ret < 0) @@ -979,7 +978,7 @@ int wilc_mac_open(struct net_device *ndev) memcpy(ndev->dev_addr, wl->vif[i]->src_addr, ETH_ALEN); if (!is_valid_ether_addr(ndev->dev_addr)) { - PRINT_ER("Error: Wrong MAC address\n"); + netdev_err(ndev, "Wrong MAC address\n"); wilc_deinit_host_int(ndev); wilc1000_wlan_deinit(ndev); return -EINVAL; @@ -1037,13 +1036,13 @@ static void wilc_set_multicast_list(struct net_device *dev) netdev_for_each_mc_addr(ha, dev) { memcpy(wilc_multicast_mac_addr_list[i], ha->addr, ETH_ALEN); - PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i, - wilc_multicast_mac_addr_list[i][0], - wilc_multicast_mac_addr_list[i][1], - wilc_multicast_mac_addr_list[i][2], - wilc_multicast_mac_addr_list[i][3], - wilc_multicast_mac_addr_list[i][4], - wilc_multicast_mac_addr_list[i][5]); + netdev_dbg(dev, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i, + wilc_multicast_mac_addr_list[i][0], + wilc_multicast_mac_addr_list[i][1], + wilc_multicast_mac_addr_list[i][2], + wilc_multicast_mac_addr_list[i][3], + wilc_multicast_mac_addr_list[i][4], + wilc_multicast_mac_addr_list[i][5]); i++; } @@ -1078,7 +1077,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) wilc = vif->wilc; if (skb->dev != ndev) { - PRINT_ER("Packet not destined to this device\n"); + netdev_err(ndev, "Packet not destined to this device\n"); return 0; } @@ -1095,15 +1094,15 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) eth_h = (struct ethhdr *)(skb->data); if (eth_h->h_proto == 0x8e88) - PRINT_D(INIT_DBG, "EAPOL transmitted\n"); + netdev_dbg(ndev, "EAPOL transmitted\n"); ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); udp_buf = (char *)ih + sizeof(struct iphdr); if ((udp_buf[1] == 68 && udp_buf[3] == 67) || (udp_buf[1] == 67 && udp_buf[3] == 68)) - PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", - udp_buf[248], udp_buf[249], udp_buf[250]); + netdev_dbg(ndev, "DHCP Message transmitted, type:%x %x %x\n", + udp_buf[248], udp_buf[249], udp_buf[250]); vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; @@ -1141,7 +1140,7 @@ int wilc_mac_close(struct net_device *ndev) hif_drv = (struct host_if_drv *)priv->hif_drv; - PRINT_D(GENERIC_DBG, "Mac close\n"); + netdev_dbg(ndev, "Mac close\n"); if (!wl) return 0; @@ -1161,7 +1160,7 @@ int wilc_mac_close(struct net_device *ndev) } if (wl->open_ifcs == 0) { - PRINT_D(GENERIC_DBG, "Deinitializing wilc1000\n"); + netdev_dbg(ndev, "Deinitializing wilc1000\n"); wl->close = 1; wilc1000_wlan_deinit(ndev); WILC_WFI_deinit_mon_interface(); @@ -1205,14 +1204,14 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) if (strncasecmp(buff, "RSSI", length) == 0) { priv = wiphy_priv(vif->ndev->ieee80211_ptr->wiphy); ret = wilc_get_rssi(vif, &rssi); - PRINT_INFO(GENERIC_DBG, "RSSI :%d\n", rssi); + netdev_info(ndev, "RSSI :%d\n", rssi); rssi += 5; snprintf(buff, size, "rssi %d", rssi); if (copy_to_user(wrq->u.data.pointer, buff, size)) { - PRINT_ER("%s: failed to copy data to user buffer\n", __func__); + netdev_err(ndev, "failed to copy\n"); ret = -EFAULT; goto done; } @@ -1223,7 +1222,7 @@ static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd) default: { - PRINT_INFO(GENERIC_DBG, "Command - %d - has been received\n", cmd); + netdev_info(ndev, "Command - %d - has been received\n", cmd); ret = -EOPNOTSUPP; goto done; } @@ -1272,7 +1271,7 @@ void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset) vif->netstats.rx_bytes += frame_len; skb->ip_summed = CHECKSUM_UNNECESSARY; stats = netif_rx(skb); - PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats); + netdev_dbg(wilc_netdev, "netif_rx ret value is: %d\n", stats); } } @@ -1379,7 +1378,7 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, SET_NETDEV_DEV(ndev, dev); if (!wdev) { - PRINT_ER("Can't register WILC Wiphy\n"); + netdev_err(ndev, "Can't register WILC Wiphy\n"); return -1; } -- cgit From b6ba7e899f90597072afef9960b58697b7841257 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:38 +0900 Subject: staging: wilc1000: removes void function return This patch removes the warning reported by checkpatch.pl for void function return statements are not generally useful. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index c16cc4031cfb..5c87105c034a 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1047,8 +1047,6 @@ static void wilc_set_multicast_list(struct net_device *dev) } wilc_setup_multicast_filter(vif, true, (dev->mc.count)); - - return; } static void linux_wlan_tx_complete(void *priv, int status) -- cgit From 6750140dfc6a6331e4cf98f1fa3cc440cac42fc0 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:39 +0900 Subject: staging: wilc1000: renames u8IfIdx of wilc_vif structure This patch renames u8IfIdx variable of wilc_vif structure to idx to avoid camelcase. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/linux_wlan.c | 8 ++++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6f583a4224a6..2022deb113c0 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -281,7 +281,7 @@ static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); */ int wilc_get_vif_idx(struct wilc_vif *vif) { - return vif->u8IfIdx + 1; + return vif->idx + 1; } /* We need to minus 1 from idx which is from wilc device to get real index diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 5c87105c034a..9ca335367b86 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -107,7 +107,7 @@ static int dev_state_ev_handler(struct notifier_block *this, netdev_dbg(dev, "IP add=%d:%d:%d:%d\n", ip_addr_buf[0], ip_addr_buf[1], ip_addr_buf[2], ip_addr_buf[3]); - wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); + wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx); break; @@ -129,7 +129,7 @@ static int dev_state_ev_handler(struct notifier_block *this, ip_addr_buf[0], ip_addr_buf[1], ip_addr_buf[2], ip_addr_buf[3]); - wilc_setup_ipaddress(vif, ip_addr_buf, vif->u8IfIdx); + wilc_setup_ipaddress(vif, ip_addr_buf, vif->idx); break; @@ -1104,7 +1104,7 @@ int wilc_mac_xmit(struct sk_buff *skb, struct net_device *ndev) vif->netstats.tx_packets++; vif->netstats.tx_bytes += tx_data->size; - tx_data->bssid = wilc->vif[vif->u8IfIdx]->bssid; + tx_data->bssid = wilc->vif[vif->idx]->bssid; queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data, tx_data->buff, tx_data->size, linux_wlan_tx_complete); @@ -1360,7 +1360,7 @@ int wilc_netdev_init(struct wilc **wilc, struct device *dev, int io_type, else strcpy(ndev->name, "p2p%d"); - vif->u8IfIdx = wl->vif_num; + vif->idx = wl->vif_num; vif->wilc = *wilc; wl->vif[i] = vif; wl->vif[wl->vif_num]->ndev = ndev; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index b8fd6956d4c5..cc50225ca844 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -2197,7 +2197,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, if (s32Error != 0) PRINT_ER("Error in setting channel\n"); - wilc_wlan_set_bssid(dev, wl->vif[vif->u8IfIdx]->src_addr, AP_MODE); + wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); s32Error = wilc_add_beacon(vif, settings->beacon_interval, diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 64fcb777cc2d..07a4ff10bb65 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -148,7 +148,7 @@ typedef struct { } struct_frame_reg; struct wilc_vif { - u8 u8IfIdx; + u8 idx; u8 iftype; int monitor_flag; int mac_opened; -- cgit From bc4b5b3cf7506fbd21dc42d46c53288fcda6632f Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:40 +0900 Subject: staging: wilc1000: fixes variable dereferenced before check This patch fixes the warning reported by smatch. - wilc_wlan_get_firmware() warn: variable dereferenced before check 'vif' - wilc_set_multicast_list() warn: variable dereferenced before check 'dev' Just delete them and no need add null check since they are net_device from ndo_set_rx_mode of net_device_ops and vif of netdev_priv. Signed-off-by: Leo Kim Signed-off-by: Glen Lee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 9ca335367b86..22a2f98cc2fe 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -397,9 +397,6 @@ int wilc_wlan_get_firmware(struct net_device *dev) netdev_info(dev, "loading firmware %s\n", firmware); - if (!vif) - goto _fail_; - if (!(&vif->ndev->dev)) goto _fail_; @@ -1017,9 +1014,6 @@ static void wilc_set_multicast_list(struct net_device *dev) vif = netdev_priv(dev); hif_drv = (struct host_if_drv *)priv->hif_drv; - if (!dev) - return; - if (dev->flags & IFF_PROMISC) return; -- cgit From cdd610644be7b096c5bece4b7a1be07da5fe491c Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:41 +0900 Subject: staging: wilc1000: wilc_parse_network_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pu8MsgBuffer to msg_buffer - ppstrNetworkInfo to ret_network_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 16 ++++++++-------- drivers/staging/wilc1000/coreconfigurator.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 6f17e2b66673..43f0a295fe55 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -270,7 +270,7 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) return 0; } -s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo) +s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) { tstrNetworkInfo *pstrNetworkInfo = NULL; u8 u8MsgType = 0; @@ -281,18 +281,18 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo u16 u16WidLen = 0; u8 *pu8WidVal = NULL; - u8MsgType = pu8MsgBuffer[0]; + u8MsgType = msg_buffer[0]; if ('N' != u8MsgType) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } - u8MsgID = pu8MsgBuffer[1]; - u16MsgLen = MAKE_WORD16(pu8MsgBuffer[2], pu8MsgBuffer[3]); - u16WidID = MAKE_WORD16(pu8MsgBuffer[4], pu8MsgBuffer[5]); - u16WidLen = MAKE_WORD16(pu8MsgBuffer[6], pu8MsgBuffer[7]); - pu8WidVal = &pu8MsgBuffer[8]; + u8MsgID = msg_buffer[1]; + u16MsgLen = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); + u16WidID = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); + u16WidLen = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); + pu8WidVal = &msg_buffer[8]; { u8 *pu8msa = NULL; @@ -350,7 +350,7 @@ s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo } - *ppstrNetworkInfo = pstrNetworkInfo; + *ret_network_info = pstrNetworkInfo; return 0; } diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index ee107ac915e0..aec0779596be 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -120,7 +120,7 @@ typedef struct { size_t ie_len; } tstrDisconnectNotifInfo; -s32 wilc_parse_network_info(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo); +s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, -- cgit From 5fd5e1e15c5e1ad04e891e15cd32d0ca3f212970 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:42 +0900 Subject: staging: wilc1000: wilc_parse_network_info(): renames local variables This patch renames to avoid camelcase, changes follow are: - pstrNetworkInfo to network_info - u8MsgType to msg_type - u8MsgID to msg_id - u16MsgLen to msg_len - u16WidID to wid_id - u16WidLen to wid_len - pu8WidVal to wid_val Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 67 ++++++++++++++--------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 43f0a295fe55..24afeb894b13 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -272,27 +272,27 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) { - tstrNetworkInfo *pstrNetworkInfo = NULL; - u8 u8MsgType = 0; - u8 u8MsgID = 0; - u16 u16MsgLen = 0; + tstrNetworkInfo *network_info = NULL; + u8 msg_type = 0; + u8 msg_id = 0; + u16 msg_len = 0; - u16 u16WidID = (u16)WID_NIL; - u16 u16WidLen = 0; - u8 *pu8WidVal = NULL; + u16 wid_id = (u16)WID_NIL; + u16 wid_len = 0; + u8 *wid_val = NULL; - u8MsgType = msg_buffer[0]; + msg_type = msg_buffer[0]; - if ('N' != u8MsgType) { + if ('N' != msg_type) { PRINT_ER("Received Message format incorrect.\n"); return -EFAULT; } - u8MsgID = msg_buffer[1]; - u16MsgLen = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); - u16WidID = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); - u16WidLen = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); - pu8WidVal = &msg_buffer[8]; + msg_id = msg_buffer[1]; + msg_len = MAKE_WORD16(msg_buffer[2], msg_buffer[3]); + wid_id = MAKE_WORD16(msg_buffer[4], msg_buffer[5]); + wid_len = MAKE_WORD16(msg_buffer[6], msg_buffer[7]); + wid_val = &msg_buffer[8]; { u8 *pu8msa = NULL; @@ -304,53 +304,52 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) u32 u32Tsf_Lo; u32 u32Tsf_Hi; - pstrNetworkInfo = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); - if (!pstrNetworkInfo) + network_info = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); + if (!network_info) return -ENOMEM; - pstrNetworkInfo->s8rssi = pu8WidVal[0]; + network_info->s8rssi = wid_val[0]; - pu8msa = &pu8WidVal[1]; + pu8msa = &wid_val[1]; - rx_len = u16WidLen - 1; - pstrNetworkInfo->u16CapInfo = get_cap_info(pu8msa); - pstrNetworkInfo->u32Tsf = get_beacon_timestamp_lo(pu8msa); - PRINT_D(CORECONFIG_DBG, "TSF :%x\n", pstrNetworkInfo->u32Tsf); + rx_len = wid_len - 1; + network_info->u16CapInfo = get_cap_info(pu8msa); + network_info->u32Tsf = get_beacon_timestamp_lo(pu8msa); + PRINT_D(CORECONFIG_DBG, "TSF :%x\n", network_info->u32Tsf); u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); - pstrNetworkInfo->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); + network_info->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); - get_ssid(pu8msa, pstrNetworkInfo->au8ssid, &pstrNetworkInfo->u8SsidLen); - get_BSSID(pu8msa, pstrNetworkInfo->au8bssid); + get_ssid(pu8msa, network_info->au8ssid, &network_info->u8SsidLen); + get_BSSID(pu8msa, network_info->au8bssid); - pstrNetworkInfo->u8channel = get_current_channel_802_11n(pu8msa, + network_info->u8channel = get_current_channel_802_11n(pu8msa, rx_len + FCS_LEN); u8index = MAC_HDR_LEN + TIME_STAMP_LEN; - pstrNetworkInfo->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); + network_info->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; pu8TimElm = get_tim_elm(pu8msa, rx_len + FCS_LEN, u8index); if (pu8TimElm) - pstrNetworkInfo->u8DtimPeriod = pu8TimElm[3]; + network_info->u8DtimPeriod = pu8TimElm[3]; pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; u16IEsLen = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (u16IEsLen > 0) { - pstrNetworkInfo->pu8IEs = kmemdup(pu8IEs, u16IEsLen, - GFP_KERNEL); - if (!pstrNetworkInfo->pu8IEs) + network_info->pu8IEs = kmemdup(pu8IEs, u16IEsLen, + GFP_KERNEL); + if (!network_info->pu8IEs) return -ENOMEM; } - pstrNetworkInfo->u16IEsLen = u16IEsLen; - + network_info->u16IEsLen = u16IEsLen; } - *ret_network_info = pstrNetworkInfo; + *ret_network_info = network_info; return 0; } -- cgit From e509681d195e6ebd6a16407ab3898e151194ee30 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:43 +0900 Subject: staging: wilc1000: wilc_parse_network_info(): renames local inner variables This patch renames to avoid camelcase, changes follow are: - pu8TimElm to tim_elm - pu8IEs to ies - u16IEsLen to ies_len - u32Tsf_Lo to tsf_lo - u32Tsf_Hi to tsf_hi And, remove the prefix variable defined name, below are: - u8index to index - pu8msa to msa Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 24afeb894b13..2a4e324397fb 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -295,14 +295,14 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) wid_val = &msg_buffer[8]; { - u8 *pu8msa = NULL; + u8 *msa = NULL; u16 rx_len = 0; - u8 *pu8TimElm = NULL; - u8 *pu8IEs = NULL; - u16 u16IEsLen = 0; - u8 u8index = 0; - u32 u32Tsf_Lo; - u32 u32Tsf_Hi; + u8 *tim_elm = NULL; + u8 *ies = NULL; + u16 ies_len = 0; + u8 index = 0; + u32 tsf_lo; + u32 tsf_hi; network_info = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); if (!network_info) @@ -310,43 +310,43 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) network_info->s8rssi = wid_val[0]; - pu8msa = &wid_val[1]; + msa = &wid_val[1]; rx_len = wid_len - 1; - network_info->u16CapInfo = get_cap_info(pu8msa); - network_info->u32Tsf = get_beacon_timestamp_lo(pu8msa); + network_info->u16CapInfo = get_cap_info(msa); + network_info->u32Tsf = get_beacon_timestamp_lo(msa); PRINT_D(CORECONFIG_DBG, "TSF :%x\n", network_info->u32Tsf); - u32Tsf_Lo = get_beacon_timestamp_lo(pu8msa); - u32Tsf_Hi = get_beacon_timestamp_hi(pu8msa); + tsf_lo = get_beacon_timestamp_lo(msa); + tsf_hi = get_beacon_timestamp_hi(msa); - network_info->u64Tsf = u32Tsf_Lo | ((u64)u32Tsf_Hi << 32); + network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); - get_ssid(pu8msa, network_info->au8ssid, &network_info->u8SsidLen); - get_BSSID(pu8msa, network_info->au8bssid); + get_ssid(msa, network_info->au8ssid, &network_info->u8SsidLen); + get_BSSID(msa, network_info->au8bssid); - network_info->u8channel = get_current_channel_802_11n(pu8msa, + network_info->u8channel = get_current_channel_802_11n(msa, rx_len + FCS_LEN); - u8index = MAC_HDR_LEN + TIME_STAMP_LEN; + index = MAC_HDR_LEN + TIME_STAMP_LEN; - network_info->u16BeaconPeriod = get_beacon_period(pu8msa + u8index); + network_info->u16BeaconPeriod = get_beacon_period(msa + index); - u8index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; + index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; - pu8TimElm = get_tim_elm(pu8msa, rx_len + FCS_LEN, u8index); - if (pu8TimElm) - network_info->u8DtimPeriod = pu8TimElm[3]; - pu8IEs = &pu8msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; - u16IEsLen = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); + tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); + if (tim_elm) + network_info->u8DtimPeriod = tim_elm[3]; + ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; + ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); - if (u16IEsLen > 0) { - network_info->pu8IEs = kmemdup(pu8IEs, u16IEsLen, + if (ies_len > 0) { + network_info->pu8IEs = kmemdup(ies, ies_len, GFP_KERNEL); if (!network_info->pu8IEs) return -ENOMEM; } - network_info->u16IEsLen = u16IEsLen; + network_info->u16IEsLen = ies_len; } *ret_network_info = network_info; -- cgit From 66d77cb5bbfc3b99ea5c4ac1978b577c322cbbae Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:44 +0900 Subject: staging: wilc1000: rename variable s32Error This patch renames variable s32Error to result to avoid CamelCase naming convention. Also, remove the unused variable s32Error and replace with direct return. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 2a4e324397fb..88e5661d31ba 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -356,30 +356,29 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) { - s32 s32Error = 0; + s32 result = 0; if (pstrNetworkInfo) { if (pstrNetworkInfo->pu8IEs) { kfree(pstrNetworkInfo->pu8IEs); pstrNetworkInfo->pu8IEs = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } kfree(pstrNetworkInfo); pstrNetworkInfo = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } - return s32Error; + return result; } s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, tstrConnectRespInfo **ppstrConnectRespInfo) { - s32 s32Error = 0; tstrConnectRespInfo *pstrConnectRespInfo = NULL; u16 u16AssocRespLen = 0; u8 *pu8IEs = NULL; @@ -408,27 +407,27 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, *ppstrConnectRespInfo = pstrConnectRespInfo; - return s32Error; + return 0; } s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) { - s32 s32Error = 0; + s32 result = 0; if (pstrConnectRespInfo) { if (pstrConnectRespInfo->pu8RespIEs) { kfree(pstrConnectRespInfo->pu8RespIEs); pstrConnectRespInfo->pu8RespIEs = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } kfree(pstrConnectRespInfo); pstrConnectRespInfo = NULL; } else { - s32Error = -EFAULT; + result = -EFAULT; } - return s32Error; + return result; } -- cgit From 946a9ddb43706c6f55600c4b2725a7b19f0777d8 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:45 +0900 Subject: staging: wilc1000: wilc_parse_assoc_resp_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pu8Buffer to buffer - u32BufferLen to buffer_len - ppstrConnectRespInfo to ret_connect_resp_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 16 ++++++++-------- drivers/staging/wilc1000/coreconfigurator.h | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 88e5661d31ba..48c8573535de 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -376,8 +376,8 @@ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) return result; } -s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, - tstrConnectRespInfo **ppstrConnectRespInfo) +s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, + tstrConnectRespInfo **ret_connect_resp_info) { tstrConnectRespInfo *pstrConnectRespInfo = NULL; u16 u16AssocRespLen = 0; @@ -388,14 +388,14 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, if (!pstrConnectRespInfo) return -ENOMEM; - u16AssocRespLen = (u16)u32BufferLen; + u16AssocRespLen = (u16)buffer_len; - pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(pu8Buffer); + pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(buffer); if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(pu8Buffer); - pstrConnectRespInfo->u16AssocID = get_asoc_id(pu8Buffer); + pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(buffer); + pstrConnectRespInfo->u16AssocID = get_asoc_id(buffer); - pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; + pu8IEs = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL); @@ -405,7 +405,7 @@ s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, pstrConnectRespInfo->u16RespIEsLen = u16IEsLen; } - *ppstrConnectRespInfo = pstrConnectRespInfo; + *ret_connect_resp_info = pstrConnectRespInfo; return 0; } diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index aec0779596be..6a2c323413ad 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -122,9 +122,8 @@ typedef struct { s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); - -s32 wilc_parse_assoc_resp_info(u8 *pu8Buffer, u32 u32BufferLen, - tstrConnectRespInfo **ppstrConnectRespInfo); +s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, + tstrConnectRespInfo **ret_connect_resp_info); s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); -- cgit From ebd7a9b037ec8383cf6e9941bc2efb4520232042 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:46 +0900 Subject: staging: wilc1000: wilc_parse_assoc_resp_info(): renames local variables This patch renames to avoid camelcase, changes follow are: - pstrConnectRespInfo to connect_resp_info - u16AssocRespLen to assoc_resp_len - pu8IEs to ies - u16IEsLen to ies_len Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 48c8573535de..c0be33d0564e 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -379,33 +379,33 @@ s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info) { - tstrConnectRespInfo *pstrConnectRespInfo = NULL; - u16 u16AssocRespLen = 0; - u8 *pu8IEs = NULL; - u16 u16IEsLen = 0; + tstrConnectRespInfo *connect_resp_info = NULL; + u16 assoc_resp_len = 0; + u8 *ies = NULL; + u16 ies_len = 0; - pstrConnectRespInfo = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL); - if (!pstrConnectRespInfo) + connect_resp_info = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL); + if (!connect_resp_info) return -ENOMEM; - u16AssocRespLen = (u16)buffer_len; + assoc_resp_len = (u16)buffer_len; - pstrConnectRespInfo->u16ConnectStatus = get_asoc_status(buffer); - if (pstrConnectRespInfo->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - pstrConnectRespInfo->u16capability = get_assoc_resp_cap_info(buffer); - pstrConnectRespInfo->u16AssocID = get_asoc_id(buffer); + connect_resp_info->u16ConnectStatus = get_asoc_status(buffer); + if (connect_resp_info->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { + connect_resp_info->u16capability = get_assoc_resp_cap_info(buffer); + connect_resp_info->u16AssocID = get_asoc_id(buffer); - pu8IEs = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; - u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); + ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; + ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); - pstrConnectRespInfo->pu8RespIEs = kmemdup(pu8IEs, u16IEsLen, GFP_KERNEL); - if (!pstrConnectRespInfo->pu8RespIEs) + connect_resp_info->pu8RespIEs = kmemdup(ies, ies_len, GFP_KERNEL); + if (!connect_resp_info->pu8RespIEs) return -ENOMEM; - pstrConnectRespInfo->u16RespIEsLen = u16IEsLen; + connect_resp_info->u16RespIEsLen = ies_len; } - *ret_connect_resp_info = pstrConnectRespInfo; + *ret_connect_resp_info = connect_resp_info; return 0; } -- cgit From 9f4970edc5487018ceaf28ab32bd428ff9a9d1ee Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:47 +0900 Subject: staging: wilc1000: wilc_dealloc_assoc_resp_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pstrConnectRespInfo to connect_resp_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 14 +++++++------- drivers/staging/wilc1000/coreconfigurator.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c0be33d0564e..c78da2c746ac 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -410,20 +410,20 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, return 0; } -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo) +s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info) { s32 result = 0; - if (pstrConnectRespInfo) { - if (pstrConnectRespInfo->pu8RespIEs) { - kfree(pstrConnectRespInfo->pu8RespIEs); - pstrConnectRespInfo->pu8RespIEs = NULL; + if (connect_resp_info) { + if (connect_resp_info->pu8RespIEs) { + kfree(connect_resp_info->pu8RespIEs); + connect_resp_info->pu8RespIEs = NULL; } else { result = -EFAULT; } - kfree(pstrConnectRespInfo); - pstrConnectRespInfo = NULL; + kfree(connect_resp_info); + connect_resp_info = NULL; } else { result = -EFAULT; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 6a2c323413ad..ec810b57de98 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -124,7 +124,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *pstrConnectRespInfo); +s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer, -- cgit From c1725aab7cd874e03214504568beb44cffb1e092 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:48 +0900 Subject: staging: wilc1000: wilc_dealloc_network_info(): renames function variables This patch renames to avoid camelcase, changes follow are: - pstrNetworkInfo to network_info Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 14 +++++++------- drivers/staging/wilc1000/coreconfigurator.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c78da2c746ac..a0b80bf8e009 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -354,20 +354,20 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) return 0; } -s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo) +s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info) { s32 result = 0; - if (pstrNetworkInfo) { - if (pstrNetworkInfo->pu8IEs) { - kfree(pstrNetworkInfo->pu8IEs); - pstrNetworkInfo->pu8IEs = NULL; + if (network_info) { + if (network_info->pu8IEs) { + kfree(network_info->pu8IEs); + network_info->pu8IEs = NULL; } else { result = -EFAULT; } - kfree(pstrNetworkInfo); - pstrNetworkInfo = NULL; + kfree(network_info); + network_info = NULL; } else { result = -EFAULT; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index ec810b57de98..d801e58be8e6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -121,7 +121,7 @@ typedef struct { } tstrDisconnectNotifInfo; s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); -s32 wilc_dealloc_network_info(tstrNetworkInfo *pstrNetworkInfo); +s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); -- cgit From 4d38a56b3c5e1cefc863757a839483de40e10f35 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:49 +0900 Subject: staging: wilc1000: fix warnings for line over 80 characters This patch fixes warnings reported by checkpatch.pl for line over 80 characters Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 33 ++++++++++++++++++++------------- drivers/staging/wilc1000/wilc_wlan.h | 3 ++- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index ebf38a578694..a6f4e15adef9 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -113,7 +113,8 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, up(&wilc->txq_event); } -static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, struct txq_entry_t *tqe) +static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, + struct txq_entry_t *tqe) { unsigned long flags; struct wilc *wilc = vif->wilc; @@ -695,8 +696,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) acquire_bus(wilc, ACQUIRE_AND_WAKEUP); counter = 0; do { - ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, - ®); + ret = wilc->hif_func->hif_read_reg(wilc, + WILC_HOST_TX_CTRL, + ®); if (!ret) { wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n"); break; @@ -728,8 +730,9 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; } - ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, - 0x2); + ret = wilc->hif_func->hif_write_reg(wilc, + WILC_HOST_VMM_CTL, + 0x2); if (!ret) { wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n"); break; @@ -1063,7 +1066,8 @@ void wilc_handle_isr(struct wilc *wilc) } EXPORT_SYMBOL_GPL(wilc_handle_isr); -int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size) +int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, + u32 buffer_size) { u32 offset; u32 addr, size, size2, blksz; @@ -1096,8 +1100,8 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_ size2 = blksz; memcpy(dma_buffer, &buffer[offset], size2); - ret = wilc->hif_func->hif_block_tx(wilc, addr, dma_buffer, - size2); + ret = wilc->hif_func->hif_block_tx(wilc, addr, + dma_buffer, size2); if (!ret) break; @@ -1233,7 +1237,8 @@ int wilc_wlan_stop(struct wilc *wilc) } do { - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); + ret = wilc->hif_func->hif_read_reg(wilc, + WILC_GLB_RESET_0, ®); if (!ret) { PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); @@ -1246,14 +1251,16 @@ int wilc_wlan_stop(struct wilc *wilc) PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", timeout); reg &= ~BIT(10); - ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, - reg); + ret = wilc->hif_func->hif_write_reg(wilc, + WILC_GLB_RESET_0, + reg); timeout--; } else { PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", timeout); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, - ®); + ret = wilc->hif_func->hif_read_reg(wilc, + WILC_GLB_RESET_0, + ®); if (!ret) { PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index e913ae7abef7..d362fa8512cf 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -270,7 +270,8 @@ struct wilc_cfg_rsp { struct wilc; struct wilc_vif; -int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, u32 buffer_size); +int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, + u32 buffer_size); int wilc_wlan_start(struct wilc *); int wilc_wlan_stop(struct wilc *); int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, -- cgit From 133b22d694c7a4753145eb41029d9dec9db84590 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:50 +0900 Subject: staging: wilc1000: remove useless log message This patch remove useless log message in wilc_wlan.c file Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 128 ++++++----------------------------- 1 file changed, 22 insertions(+), 106 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index a6f4e15adef9..400d311d587b 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -104,12 +104,9 @@ static void wilc_wlan_txq_add_to_tail(struct net_device *dev, wilc->txq_tail = tqe; } wilc->txq_entries += 1; - PRINT_D(TX_DBG, "Number of entries in TxQ = %d\n", wilc->txq_entries); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); - PRINT_D(TX_DBG, "Wake the txq_handling\n"); - up(&wilc->txq_event); } @@ -137,12 +134,10 @@ static int wilc_wlan_txq_add_to_head(struct wilc_vif *vif, wilc->txq_head = tqe; } wilc->txq_entries += 1; - netdev_dbg(vif->ndev, "Number of entries in TxQ = %d\n", wilc->txq_entries); spin_unlock_irqrestore(&wilc->txq_spinlock, flags); up(&wilc->txq_add_to_head_cs); up(&wilc->txq_event); - netdev_dbg(vif->ndev, "Wake up the txq_handler\n"); return 0; } @@ -188,7 +183,6 @@ static inline int add_tcp_session(u32 src_prt, u32 dst_prt, u32 seq) ack_session_info[tcp_session].dst_port = dst_prt; tcp_session++; } - PRINT_D(TCP_ENH, "TCP Session %d to Ack %d\n", tcp_session, seq); return 0; } @@ -310,8 +304,6 @@ static int wilc_wlan_txq_filter_dup_tcp_ack(struct net_device *dev) if (pending_acks_info[i].ack_num < ack_session_info[pending_acks_info[i].session_index].bigger_ack_num) { struct txq_entry_t *tqe; - PRINT_D(TCP_ENH, "DROP ACK: %u\n", - pending_acks_info[i].ack_num); tqe = pending_acks_info[i].txqe; if (tqe) { wilc_wlan_txq_remove(wilc, tqe); @@ -379,7 +371,6 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer, tqe->tx_complete_func = NULL; tqe->priv = NULL; tqe->tcp_pending_ack_idx = NOT_TCP_ACK; - netdev_dbg(vif->ndev, "Adding the config packet at the Queue tail\n"); if (wilc_wlan_txq_add_to_head(vif, tqe)) return 0; @@ -408,7 +399,6 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->tx_complete_func = func; tqe->priv = priv; - PRINT_D(TX_DBG, "Adding mgmt packet at the Queue tail\n"); tqe->tcp_pending_ack_idx = NOT_TCP_ACK; if (is_tcp_ack_filter_enabled()) tcp_process(dev, tqe); @@ -438,7 +428,6 @@ int wilc_wlan_txq_add_mgmt_pkt(struct net_device *dev, void *priv, u8 *buffer, tqe->tx_complete_func = func; tqe->priv = priv; tqe->tcp_pending_ack_idx = NOT_TCP_ACK; - PRINT_D(TX_DBG, "Adding Network packet at the Queue tail\n"); wilc_wlan_txq_add_to_tail(dev, tqe); return 1; } @@ -478,18 +467,15 @@ static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) mutex_lock(&wilc->rxq_cs); if (!wilc->rxq_head) { - PRINT_D(RX_DBG, "Add to Queue head\n"); rqe->next = NULL; wilc->rxq_head = rqe; wilc->rxq_tail = rqe; } else { - PRINT_D(RX_DBG, "Add to Queue tail\n"); wilc->rxq_tail->next = rqe; rqe->next = NULL; wilc->rxq_tail = rqe; } wilc->rxq_entries += 1; - PRINT_D(RX_DBG, "Number of queue entries: %d\n", wilc->rxq_entries); mutex_unlock(&wilc->rxq_cs); return wilc->rxq_entries; } @@ -497,7 +483,6 @@ static int wilc_wlan_rxq_add(struct wilc *wilc, struct rxq_entry_t *rqe) static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) { - PRINT_D(RX_DBG, "Getting rxQ element\n"); if (wilc->rxq_head) { struct rxq_entry_t *rqe; @@ -505,11 +490,9 @@ static struct rxq_entry_t *wilc_wlan_rxq_remove(struct wilc *wilc) rqe = wilc->rxq_head; wilc->rxq_head = wilc->rxq_head->next; wilc->rxq_entries -= 1; - PRINT_D(RX_DBG, "RXQ entries decreased\n"); mutex_unlock(&wilc->rxq_cs); return rqe; } - PRINT_D(RX_DBG, "Nothing to get from Q\n"); return NULL; } @@ -643,7 +626,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) wilc_lock_timeout(wilc, &wilc->txq_add_to_head_cs, CFG_PKTS_TIMEOUT); wilc_wlan_txq_filter_dup_tcp_ack(dev); - PRINT_D(TX_DBG, "Getting the head of the TxQ\n"); tqe = wilc_wlan_txq_get_first(wilc); i = 0; sum = 0; @@ -659,27 +641,20 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) vmm_sz = HOST_HDR_OFFSET; vmm_sz += tqe->buffer_size; - PRINT_D(TX_DBG, "VMM Size before alignment = %d\n", vmm_sz); + if (vmm_sz & 0x3) vmm_sz = (vmm_sz + 4) & ~0x3; if ((sum + vmm_sz) > LINUX_TX_SIZE) break; - PRINT_D(TX_DBG, "VMM Size AFTER alignment = %d\n", vmm_sz); vmm_table[i] = vmm_sz / 4; - PRINT_D(TX_DBG, "VMMTable entry size = %d\n", - vmm_table[i]); - - if (tqe->type == WILC_CFG_PKT) { + if (tqe->type == WILC_CFG_PKT) vmm_table[i] |= BIT(10); - PRINT_D(TX_DBG, "VMMTable entry changed for CFG packet = %d\n", vmm_table[i]); - } vmm_table[i] = cpu_to_le32(vmm_table[i]); i++; sum += vmm_sz; - PRINT_D(TX_DBG, "sum = %d\n", sum); tqe = wilc_wlan_txq_get_next(wilc, tqe); } else { break; @@ -699,23 +674,18 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't read reg vmm_tbl_entry..\n"); + if (!ret) break; - } if ((reg & 0x1) == 0) { - PRINT_D(TX_DBG, "Writing VMM table ... with Size = %d\n", ((i + 1) * 4)); break; } else { counter++; if (counter > 200) { counter = 0; - PRINT_D(TX_DBG, "Looping in tx ctrl , forcce quit\n"); ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, 0); break; } - PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n"); } } while (!wilc->quit); @@ -725,25 +695,19 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) timeout = 200; do { ret = wilc->hif_func->hif_block_tx(wilc, WILC_VMM_TBL_RX_SHADOW_BASE, (u8 *)vmm_table, ((i + 1) * 4)); - if (!ret) { - wilc_debug(N_ERR, "ERR block TX of VMM table.\n"); + if (!ret) break; - } ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_VMM_CTL, 0x2); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't write reg host_vmm_ctl..\n"); + if (!ret) break; - } do { ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_VMM_CTL, ®); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't read reg host_vmm_ctl..\n"); + if (!ret) break; - } if ((reg >> 2) & 0x1) { entries = ((reg >> 3) & 0x3f); break; @@ -763,16 +727,12 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]); ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't read reg WILC_HOST_TX_CTRL..\n"); + if (!ret) break; - } reg &= ~BIT(0); ret = wilc->hif_func->hif_write_reg(wilc, WILC_HOST_TX_CTRL, reg); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't write reg WILC_HOST_TX_CTRL..\n"); + if (!ret) break; - } break; } else { break; @@ -840,16 +800,12 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) acquire_bus(wilc, ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_clear_int_ext(wilc, ENABLE_TX_VMM); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't start tx VMM ...\n"); + if (!ret) goto _end_; - } ret = wilc->hif_func->hif_block_tx_ext(wilc, 0, txb, offset); - if (!ret) { - wilc_debug(N_ERR, "[wilc txq]: fail can't block tx ext...\n"); + if (!ret) goto _end_; - } _end_: @@ -875,19 +831,15 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) do { if (wilc->quit) { - PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n"); up(&wilc->cfg_event); break; } rqe = wilc_wlan_rxq_remove(wilc); - if (!rqe) { - PRINT_D(RX_DBG, "nothing in the queue - exit 1st do-while\n"); + if (!rqe) break; - } + buffer = rqe->buffer; size = rqe->buffer_size; - PRINT_D(RX_DBG, "rxQ entery Size = %d - Address = %p\n", - size, buffer); offset = 0; do { @@ -906,10 +858,8 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) tp_len = (header >> 11) & 0x7ff; pkt_len = header & 0x7ff; - if (pkt_len == 0 || tp_len == 0) { - wilc_debug(N_RXQ, "[wilc rxq]: data corrupt, packet len or tp_len is 0 [%d][%d]\n", pkt_len, tp_len); + if (pkt_len == 0 || tp_len == 0) break; - } #define IS_MANAGMEMENT 0x100 #define IS_MANAGMEMENT_CALLBACK 0x080 @@ -935,7 +885,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) wilc_wlan_cfg_indicate_rx(wilc, &buffer[pkt_offset + offset], pkt_len, &rsp); if (rsp.type == WILC_CFG_RSP) { - PRINT_D(RX_DBG, "wilc->cfg_seq_no = %d - rsp.seq_no = %d\n", wilc->cfg_seq_no, rsp.seq_no); if (wilc->cfg_seq_no == rsp.seq_no) up(&wilc->cfg_event); } else if (rsp.type == WILC_CFG_RSP_STATUS) { @@ -977,10 +926,8 @@ static void wilc_pllupdate_isr_ext(struct wilc *wilc, u32 int_stats) else mdelay(WILC_PLL_TO_SPI); - while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) { - PRINT_D(TX_DBG, "PLL update retrying\n"); + while (!(ISWILC1000(wilc_get_chipid(wilc, true)) && --trials)) mdelay(1); - } } static void wilc_sleeptimer_isr_ext(struct wilc *wilc, u32 int_stats1) @@ -1000,9 +947,6 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) size = ((int_status & 0x7fff) << 2); while (!size && retries < 10) { - u32 time = 0; - - wilc_debug(N_ERR, "RX Size equal zero ... Trying to read it again for %d time\n", time++); wilc->hif_func->hif_read_size(wilc, &size); size = ((size & 0x7fff) << 2); retries++; @@ -1012,21 +956,17 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) if (LINUX_RX_SIZE - offset < size) offset = 0; - if (wilc->rx_buffer) { + if (wilc->rx_buffer) buffer = &wilc->rx_buffer[offset]; - } else { - wilc_debug(N_ERR, "[wilc isr]: fail Rx Buffer is NULL...drop the packets (%d)\n", size); + else goto _end_; - } wilc->hif_func->hif_clear_int_ext(wilc, DATA_INT_CLR | ENABLE_RX_VMM); ret = wilc->hif_func->hif_block_rx_ext(wilc, 0, buffer, size); - if (!ret) { - wilc_debug(N_ERR, "[wilc isr]: fail block rx...\n"); + if (!ret) goto _end_; - } _end_: if (ret) { offset += size; @@ -1079,12 +1019,9 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, dma_buffer = kmalloc(blksz, GFP_KERNEL); if (!dma_buffer) { ret = -EIO; - PRINT_ER("Can't allocate buffer for firmware download IO error\n "); goto _fail_1; } - PRINT_D(INIT_DBG, "Downloading firmware size = %d ...\n", buffer_size); - offset = 0; do { memcpy(&addr, &buffer[offset], 4); @@ -1113,7 +1050,6 @@ int wilc_wlan_firmware_download(struct wilc *wilc, const u8 *buffer, if (!ret) { ret = -EIO; - PRINT_ER("Can't download firmware IO error\n "); goto _fail_; } PRINT_D(INIT_DBG, "Offset = %d\n", offset); @@ -1143,7 +1079,6 @@ int wilc_wlan_start(struct wilc *wilc) acquire_bus(wilc, ACQUIRE_ONLY); ret = wilc->hif_func->hif_write_reg(wilc, WILC_VMM_CORE_CFG, reg); if (!ret) { - wilc_debug(N_ERR, "[wilc start]: fail write reg vmm_core_cfg...\n"); release_bus(wilc, RELEASE_ONLY); ret = -EIO; return ret; @@ -1177,7 +1112,6 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_1, reg); if (!ret) { - wilc_debug(N_ERR, "[wilc start]: fail write WILC_GP_REG_1 ...\n"); release_bus(wilc, RELEASE_ONLY); ret = -EIO; return ret; @@ -1187,7 +1121,6 @@ int wilc_wlan_start(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, 0x1000, &chipid); if (!ret) { - wilc_debug(N_ERR, "[wilc start]: fail read reg 0x1000 ...\n"); release_bus(wilc, RELEASE_ONLY); ret = -EIO; return ret; @@ -1223,7 +1156,6 @@ int wilc_wlan_stop(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (!ret) { - PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } @@ -1231,7 +1163,6 @@ int wilc_wlan_stop(struct wilc *wilc) reg &= ~BIT(10); ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); if (!ret) { - PRINT_ER("Error while writing reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } @@ -1240,34 +1171,24 @@ int wilc_wlan_stop(struct wilc *wilc) ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (!ret) { - PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } - PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", - reg, timeout); if ((reg & BIT(10))) { - PRINT_D(GENERIC_DBG, "Bit 10 not reset : Retry %d\n", - timeout); reg &= ~BIT(10); ret = wilc->hif_func->hif_write_reg(wilc, WILC_GLB_RESET_0, reg); timeout--; } else { - PRINT_D(GENERIC_DBG, "Bit 10 reset after : Retry %d\n", - timeout); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); if (!ret) { - PRINT_ER("Error while reading reg\n"); release_bus(wilc, RELEASE_ALLOW_SLEEP); return ret; } - PRINT_D(GENERIC_DBG, "Read RESET Reg %x : Retry%d\n", - reg, timeout); break; } @@ -1322,17 +1243,14 @@ void wilc_wlan_cleanup(struct net_device *dev) acquire_bus(wilc, ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GP_REG_0, ®); - if (!ret) { - PRINT_ER("Error while reading reg\n"); + if (!ret) release_bus(wilc, RELEASE_ALLOW_SLEEP); - } - PRINT_ER("Writing ABORT reg\n"); + ret = wilc->hif_func->hif_write_reg(wilc, WILC_GP_REG_0, (reg | ABORT_INT)); - if (!ret) { - PRINT_ER("Error while writing reg\n"); + if (!ret) release_bus(wilc, RELEASE_ALLOW_SLEEP); - } + release_bus(wilc, RELEASE_ALLOW_SLEEP); wilc->hif_func->hif_deinit(NULL); } @@ -1437,7 +1355,6 @@ int wilc_wlan_cfg_get(struct wilc_vif *vif, int start, u32 wid, int commit, netdev_dbg(vif->ndev, "Get Timed Out\n"); ret_size = 0; } - netdev_dbg(vif->ndev, "[WILC]Get Response received\n"); wilc->cfg_frame_in_use = 0; wilc->cfg_frame_offset = 0; wilc->cfg_seq_no += 1; @@ -1589,7 +1506,6 @@ int wilc_wlan_init(struct net_device *dev) if (!wilc->tx_buffer) wilc->tx_buffer = kmalloc(LINUX_TX_SIZE, GFP_KERNEL); - PRINT_D(TX_DBG, "wilc->tx_buffer = %p\n", wilc->tx_buffer); if (!wilc->tx_buffer) { ret = -ENOBUFS; @@ -1599,7 +1515,7 @@ int wilc_wlan_init(struct net_device *dev) if (!wilc->rx_buffer) wilc->rx_buffer = kmalloc(LINUX_RX_SIZE, GFP_KERNEL); - PRINT_D(TX_DBG, "wilc->rx_buffer =%p\n", wilc->rx_buffer); + if (!wilc->rx_buffer) { ret = -ENOBUFS; PRINT_ER("Can't allocate Rx Buffer"); -- cgit From b2a45eae9ff3538f39cd4cee6569d0a53be54595 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:51 +0900 Subject: staging: wilc1000: remove useless function This patch remove useless function remove_TCP_related in wilc_wlan.c file Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 400d311d587b..8618e27ac80e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -206,15 +206,6 @@ static inline int add_tcp_pending_ack(u32 ack, u32 session_index, } return 0; } -static inline int remove_TCP_related(struct wilc *wilc) -{ - unsigned long flags; - - spin_lock_irqsave(&wilc->txq_spinlock, flags); - - spin_unlock_irqrestore(&wilc->txq_spinlock, flags); - return 0; -} static inline int tcp_process(struct net_device *dev, struct txq_entry_t *tqe) { -- cgit From f06b9baf8716972a6a65f6eff470b918a9c67254 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:52 +0900 Subject: staging: wilc1000: remove unnecessary braces This patch remove warnings reported by checkpatch.pl for unnecessary braces Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 8618e27ac80e..e2c84dbba014 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -984,15 +984,15 @@ void wilc_handle_isr(struct wilc *wilc) if (int_status & PLL_INT_EXT) wilc_pllupdate_isr_ext(wilc, int_status); - if (int_status & DATA_INT_EXT) { + if (int_status & DATA_INT_EXT) wilc_wlan_handle_isr_ext(wilc, int_status); - } + if (int_status & SLEEP_INT_EXT) wilc_sleeptimer_isr_ext(wilc, int_status); - if (!(int_status & (ALL_INT_EXT))) { + if (!(int_status & (ALL_INT_EXT))) wilc_unknown_isr_ext(wilc); - } + release_bus(wilc, RELEASE_ALLOW_SLEEP); } EXPORT_SYMBOL_GPL(wilc_handle_isr); -- cgit From 20f4e712d1a9c2efce20d5345cc1a4bf7070852b Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:53 +0900 Subject: staging: wilc1000: remove warnings missing a blank line after declarations This patch remove warnings reported by checkpatch.pl for missing a blank line after declarations Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index e2c84dbba014..dc2632286756 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1143,6 +1143,7 @@ int wilc_wlan_stop(struct wilc *wilc) u32 reg = 0; int ret; u8 timeout = 10; + acquire_bus(wilc, ACQUIRE_AND_WAKEUP); ret = wilc->hif_func->hif_read_reg(wilc, WILC_GLB_RESET_0, ®); -- cgit From 65c3f000133ae375f34772d5e59f8aee28fbac9a Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:15:54 +0900 Subject: staging: wilc1000: Optimize code of wilc_get_chipid function This patch optimize code of wilc_get_chipid function. u8 type changed to boolean type and removed unnecessary if statement. Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 4 ++-- drivers/staging/wilc1000/wilc_wlan.c | 19 +++++++------------ drivers/staging/wilc1000/wilc_wlan_if.h | 2 +- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 22a2f98cc2fe..9e5dea4b24c5 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -388,7 +388,7 @@ int wilc_wlan_get_firmware(struct net_device *dev) vif = netdev_priv(dev); wilc = vif->wilc; - chip_id = wilc_get_chipid(wilc, 0); + chip_id = wilc_get_chipid(wilc, false); if (chip_id < 0x1003a0) firmware = FIRMWARE_1002; @@ -475,7 +475,7 @@ static int linux_wlan_init_test_config(struct net_device *dev, wilc_get_mac_address(vif, mac_add); netdev_dbg(dev, "MAC address is : %pM\n", mac_add); - wilc_get_chipid(wilc, 0); + wilc_get_chipid(wilc, false); *(int *)c_val = 1; diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index dc2632286756..46087e29fc15 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1441,36 +1441,31 @@ static u32 init_chip(struct net_device *dev) return ret; } -u32 wilc_get_chipid(struct wilc *wilc, u8 update) +u32 wilc_get_chipid(struct wilc *wilc, bool update) { static u32 chipid; u32 tempchipid = 0; - u32 rfrevid; + u32 rfrevid = 0; - if (chipid == 0 || update != 0) { + if (chipid == 0 || update) { wilc->hif_func->hif_read_reg(wilc, 0x1000, &tempchipid); wilc->hif_func->hif_read_reg(wilc, 0x13f4, &rfrevid); if (!ISWILC1000(tempchipid)) { chipid = 0; - goto _fail_; + return chipid; } if (tempchipid == 0x1002a0) { - if (rfrevid == 0x1) { - } else { + if (rfrevid != 0x1) tempchipid = 0x1002a1; - } } else if (tempchipid == 0x1002b0) { - if (rfrevid == 3) { - } else if (rfrevid == 4) { + if (rfrevid == 0x4) tempchipid = 0x1002b1; - } else { + else if (rfrevid != 0x3) tempchipid = 0x1002b2; - } } chipid = tempchipid; } -_fail_: return chipid; } diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h index 294552dda7b5..269c56ea147b 100644 --- a/drivers/staging/wilc1000/wilc_wlan_if.h +++ b/drivers/staging/wilc1000/wilc_wlan_if.h @@ -921,6 +921,6 @@ struct wilc; int wilc_wlan_init(struct net_device *dev); void wilc_bus_set_max_speed(void); void wilc_bus_set_default_speed(void); -u32 wilc_get_chipid(struct wilc *wilc, u8 update); +u32 wilc_get_chipid(struct wilc *wilc, bool update); #endif -- cgit From 06fb9336acdc388d186e943319d6a211dab06300 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:55 +0900 Subject: staging: wilc1000: wilc_wfi_cfgoperations.c: replaces PRINT_ER with netdev_err This patches replaces PRINT_ER with netdev_err. Removes unnecessary debug logs as well. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 86 ++++++++--------------- 1 file changed, 31 insertions(+), 55 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index cc50225ca844..d8cf6b490e72 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -405,10 +405,8 @@ static void CfgScanResult(enum scan_event scan_event, if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && (((s32)network_info->s8rssi * 100) < 0 || - ((s32)network_info->s8rssi * 100) > 100)) { - PRINT_ER("wiphy signal type fial\n"); + ((s32)network_info->s8rssi * 100) > 100)) return; - } if (network_info) { s32Freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ); @@ -436,10 +434,6 @@ static void CfgScanResult(enum scan_event scan_event, (size_t)network_info->u16IEsLen, (((s32)network_info->s8rssi) * 100), GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } - - - } else { - PRINT_ER("Discovered networks exceeded the max limit\n"); } } else { u32 i; @@ -531,7 +525,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, if (!pstrWFIDrv->p2p_connect) wlan_channel = INVALID_CHANNEL; - PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus); + netdev_err(dev, "Unspecified failure\n"); } if (u16ConnectStatus == WLAN_STATUS_SUCCESS) { @@ -572,8 +566,6 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, u16ConnectStatus, GFP_KERNEL); } else if (enuConnDisconnEvent == CONN_DISCONN_EVENT_DISCONN_NOTIF) { wilc_optaining_ip = false; - PRINT_ER("Received MAC_DISCONNECTED from firmware with reason %d on dev [%p]\n", - pstrDisconnectNotifInfo->u16reason, priv->dev); p2p_local_random = 0x01; p2p_recv_random = 0x00; wilc_ie = false; @@ -612,7 +604,7 @@ static int set_channel(struct wiphy *wiphy, result = wilc_set_mac_chnl_num(vif, channelnum); if (result != 0) - PRINT_ER("Error in setting channel %d\n", channelnum); + netdev_err(priv->dev, "Error in setting channel\n"); return result; } @@ -680,8 +672,7 @@ static int scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) (void *)priv, NULL); } } else { - PRINT_ER("Requested num of scanned channels is greater than the max, supported" - " channels\n"); + netdev_err(priv->dev, "Requested scanned channels over\n"); } if (s32Error != 0) { @@ -843,7 +834,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, } else { s32Error = -ENOTSUPP; - PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); + netdev_err(dev, "Not supported cipher\n"); wilc_connecting = 0; return s32Error; } @@ -909,7 +900,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, pstrNetworkInfo->u8channel, pstrNetworkInfo->pJoinParams); if (s32Error != 0) { - PRINT_ER("wilc_set_join_req(): Error(%d)\n", s32Error); + netdev_err(dev, "wilc_set_join_req(): Error\n"); s32Error = -ENOENT; wilc_connecting = 0; return s32Error; @@ -944,7 +935,7 @@ static int disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_co s32Error = wilc_disconnect(vif, reason_code); if (s32Error != 0) { - PRINT_ER("Error in disconnecting: Error(%d)\n", s32Error); + netdev_err(priv->dev, "Error in disconnecting\n"); s32Error = -EINVAL; } @@ -1211,7 +1202,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, break; default: - PRINT_ER("Not supported cipher: Error(%d)\n", s32Error); + netdev_err(netdev, "Not supported cipher\n"); s32Error = -ENOTSUPP; } @@ -1362,7 +1353,7 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev, } if (associatedsta == -1) { - PRINT_ER("Station required is not associated\n"); + netdev_err(dev, "sta required is not associated\n"); return -ENOENT; } @@ -1449,8 +1440,7 @@ static int set_wiphy_params(struct wiphy *wiphy, u32 changed) PRINT_D(CFG80211_DBG, "Setting CFG params in the host interface\n"); s32Error = wilc_hif_set_cfg(vif, &pstrCfgParamVal); if (s32Error) - PRINT_ER("Error in setting WIPHY PARAMS\n"); - + netdev_err(priv->dev, "Error in setting WIPHY PARAMS\n"); return s32Error; } @@ -1485,7 +1475,7 @@ static int set_pmksa(struct wiphy *wiphy, struct net_device *netdev, if (!(flag == PMKID_FOUND)) priv->pmkid_list.numpmkid++; } else { - PRINT_ER("Invalid PMKID index\n"); + netdev_err(netdev, "Invalid PMKID index\n"); s32Error = -EINVAL; } @@ -1854,16 +1844,14 @@ static int mgmt_tx(struct wiphy *wiphy, if (ieee80211_is_mgmt(mgmt->frame_control)) { mgmt_tx = kmalloc(sizeof(struct p2p_mgmt_data), GFP_KERNEL); - if (!mgmt_tx) { - PRINT_ER("Failed to allocate memory for mgmt_tx structure\n"); + if (!mgmt_tx) return -EFAULT; - } + mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL); - if (!mgmt_tx->buff) { - PRINT_ER("Failed to allocate memory for mgmt_tx buff\n"); + if (!mgmt_tx->buff) kfree(mgmt_tx); return -EFAULT; - } + memcpy(mgmt_tx->buff, buf, len); mgmt_tx->size = len; @@ -2072,10 +2060,8 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - if (!priv->hif_drv) { - PRINT_ER("Driver is NULL\n"); + if (!priv->hif_drv) return -EIO; - } if (wilc_enable_ps) wilc_set_power_mgmt(vif, enabled, timeout); @@ -2168,7 +2154,7 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; default: - PRINT_ER("Unknown interface type= %d\n", type); + netdev_err(dev, "Unknown interface type= %d\n", type); return -EINVAL; } @@ -2195,7 +2181,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev, s32Error = set_channel(wiphy, &settings->chandef); if (s32Error != 0) - PRINT_ER("Error in setting channel\n"); + netdev_err(dev, "Error in setting channel\n"); wilc_wlan_set_bssid(dev, wl->vif[vif->idx]->src_addr, AP_MODE); wilc_set_power_mgmt(vif, 0, 0); @@ -2247,7 +2233,7 @@ static int stop_ap(struct wiphy *wiphy, struct net_device *dev) s32Error = wilc_del_beacon(vif); if (s32Error) - PRINT_ER("Host delete beacon fail\n"); + netdev_err(dev, "Host delete beacon fail\n"); return s32Error; } @@ -2317,7 +2303,7 @@ static int add_station(struct wiphy *wiphy, struct net_device *dev, s32Error = wilc_add_station(vif, &strStaParams); if (s32Error) - PRINT_ER("Host add station fail\n"); + netdev_err(dev, "Host add station fail\n"); } return s32Error; @@ -2352,7 +2338,7 @@ static int del_station(struct wiphy *wiphy, struct net_device *dev, s32Error = wilc_del_station(vif, mac); if (s32Error) - PRINT_ER("Host delete station fail\n"); + netdev_err(dev, "Host delete station fail\n"); } return s32Error; } @@ -2424,7 +2410,7 @@ static int change_station(struct wiphy *wiphy, struct net_device *dev, s32Error = wilc_edit_station(vif, &strStaParams); if (s32Error) - PRINT_ER("Host edit station fail\n"); + netdev_err(dev, "Host edit station fail\n"); } return s32Error; } @@ -2457,8 +2443,7 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n"); vif = netdev_priv(priv->wdev->netdev); vif->monitor_flag = 1; - } else - PRINT_ER("Error in initializing monitor interface\n "); + } } return priv->wdev; } @@ -2612,16 +2597,12 @@ static struct wireless_dev *WILC_WFI_CfgAlloc(void) PRINT_D(CFG80211_DBG, "Allocating wireless device\n"); wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - PRINT_ER("Cannot allocate wireless device\n"); + if (!wdev) goto _fail_; - } wdev->wiphy = wiphy_new(&wilc_cfg80211_ops, sizeof(struct wilc_priv)); - if (!wdev->wiphy) { - PRINT_ER("Cannot allocate wiphy\n"); + if (!wdev->wiphy) goto _fail_mem_; - } WILC_WFI_band_2ghz.ht_cap.ht_supported = 1; WILC_WFI_band_2ghz.ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); @@ -2649,7 +2630,7 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de wdev = WILC_WFI_CfgAlloc(); if (!wdev) { - PRINT_ER("CfgAlloc Failed\n"); + netdev_err(net, "wiphy new allocate failed\n"); return NULL; } @@ -2684,11 +2665,10 @@ struct wireless_dev *wilc_create_wiphy(struct net_device *net, struct device *de set_wiphy_dev(wdev->wiphy, dev); s32Error = wiphy_register(wdev->wiphy); - if (s32Error) { - PRINT_ER("Cannot register wiphy device\n"); - } else { + if (s32Error) + netdev_err(net, "Cannot register wiphy device\n"); + else PRINT_D(CFG80211_DBG, "Successful Registering\n"); - } priv->dev = net; return wdev; @@ -2707,10 +2687,6 @@ int wilc_init_host_int(struct net_device *net) setup_timer(&wilc_during_ip_timer, clear_duringIP, 0); } op_ifcs++; - if (s32Error < 0) { - PRINT_ER("Failed to creat refresh Timer\n"); - return s32Error; - } priv->gbAutoRateAdjusted = false; @@ -2719,7 +2695,7 @@ int wilc_init_host_int(struct net_device *net) sema_init(&(priv->hSemScanReq), 1); s32Error = wilc_init(net, &priv->hif_drv); if (s32Error) - PRINT_ER("Error while initializing hostinterface\n"); + netdev_err(net, "Error while initializing hostinterface\n"); return s32Error; } @@ -2748,7 +2724,7 @@ int wilc_deinit_host_int(struct net_device *net) } if (s32Error) - PRINT_ER("Error while deintializing host interface\n"); + netdev_err(net, "Error while deintializing host interface\n"); return s32Error; } -- cgit From e078ed73669c73306adc9e62de5da055fded290b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:15:56 +0900 Subject: staging: wilc1000: wilc_msgqueue.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_msgqueue.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c index 5fe85eb40146..780ddd3aa05d 100644 --- a/drivers/staging/wilc1000/wilc_msgqueue.c +++ b/drivers/staging/wilc1000/wilc_msgqueue.c @@ -60,15 +60,11 @@ int wilc_mq_send(struct message_queue *mq, unsigned long flags; struct message *new_msg = NULL; - if ((!mq) || (send_buf_size == 0) || (!send_buf)) { - PRINT_ER("mq or send_buf is null\n"); + if (!mq || (send_buf_size == 0) || !send_buf) return -EINVAL; - } - if (mq->exiting) { - PRINT_ER("mq fail\n"); + if (mq->exiting) return -EFAULT; - } /* construct a new message */ new_msg = kmalloc(sizeof(*new_msg), GFP_ATOMIC); @@ -107,15 +103,11 @@ int wilc_mq_recv(struct message_queue *mq, struct message *msg; unsigned long flags; - if ((!mq) || (recv_buf_size == 0) || (!recv_buf) || (!recv_len)) { - PRINT_ER("mq or recv_buf is null\n"); + if (!mq || (recv_buf_size == 0) || !recv_buf || !recv_len) return -EINVAL; - } - if (mq->exiting) { - PRINT_ER("mq fail\n"); + if (mq->exiting) return -EFAULT; - } spin_lock_irqsave(&mq->lock, flags); mq->recv_count++; @@ -127,7 +119,6 @@ int wilc_mq_recv(struct message_queue *mq, if (list_empty(&mq->msg_list)) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); - PRINT_ER("msg is null\n"); return -EFAULT; } /* check buffer size */ @@ -135,7 +126,6 @@ int wilc_mq_recv(struct message_queue *mq, if (recv_buf_size < msg->len) { spin_unlock_irqrestore(&mq->lock, flags); up(&mq->sem); - PRINT_ER("recv_buf_size overflow\n"); return -EOVERFLOW; } -- cgit From 368949a7c08b0698e56dbe53c9b960b93b4edea9 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:03 +0900 Subject: staging: wilc1000: remove unused log message using the CORECONFIG_DBG tag This patch remove unused log messages using the CORECONFIG_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 1 - drivers/staging/wilc1000/linux_wlan_common.h | 2 -- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 20 +------------------- 4 files changed, 2 insertions(+), 23 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index a0b80bf8e009..11e3ce078bad 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -315,7 +315,6 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) rx_len = wid_len - 1; network_info->u16CapInfo = get_cap_info(msa); network_info->u32Tsf = get_beacon_timestamp_lo(msa); - PRINT_D(CORECONFIG_DBG, "TSF :%x\n", network_info->u32Tsf); tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 5d40f05124c1..5e1d3ad5bed0 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -6,7 +6,6 @@ enum debug_region { Hostapd_debug, Hostinf_debug, CFG80211_debug, - Coreconfig_debug, Interrupt_debug, TX_debug, RX_debug, @@ -24,7 +23,6 @@ enum debug_region { #define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) #define HOSTINF_DBG (1 << Hostinf_debug) -#define CORECONFIG_DBG (1 << Coreconfig_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) #define TX_DBG (1 << TX_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 291e6faa90e9..c7e07758ad7e 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CORECONFIG_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d8cf6b490e72..7a5d81953839 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -192,7 +192,6 @@ static void clear_shadow_scan(void) if (op_ifcs == 0) { del_timer_sync(&hAgingTimer); - PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n"); for (i = 0; i < last_scanned_cnt; i++) { if (last_scanned_shadow[last_scanned_cnt].pu8IEs) { @@ -424,8 +423,6 @@ static void CfgScanResult(enum scan_event scan_event, PRINT_D(CFG80211_DBG, "Network %s found\n", network_info->au8ssid); priv->u32RcvdChCount++; - if (!join_params) - PRINT_INFO(CORECONFIG_DBG, ">> Something really bad happened\n"); add_network_to_shadow(network_info, priv, join_params); if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { @@ -762,24 +759,14 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_INFO(CFG80211_DBG, "sme->crypto.n_ciphers_pairwise=%d\n", sme->crypto.n_ciphers_pairwise); - if (INFO) { - for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) - PRINT_D(CORECONFIG_DBG, "sme->crypto.ciphers_pairwise[%d]=%x\n", i, sme->crypto.ciphers_pairwise[i]); - } - if (sme->crypto.cipher_group != NO_ENCRYPT) { pcwpa_version = "Default"; - PRINT_D(CORECONFIG_DBG, ">> sme->crypto.wpa_versions: %x\n", sme->crypto.wpa_versions); if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) { u8security = ENCRYPT_ENABLED | WEP; pcgroup_encrypt_val = "WEP40"; pccipher_group = "WLAN_CIPHER_SUITE_WEP40"; PRINT_INFO(CFG80211_DBG, "WEP Default Key Idx = %d\n", sme->key_idx); - if (INFO) { - for (i = 0; i < sme->key_len; i++) - PRINT_D(CORECONFIG_DBG, "WEP Key Value[%d] = %d\n", i, sme->key[i]); - } priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len; memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len); @@ -1386,9 +1373,6 @@ static int get_station(struct wiphy *wiphy, struct net_device *dev, wilc_enable_tcp_ack_filter(true); else if (strStatistics.link_speed != DEFAULT_LINK_SPEED) wilc_enable_tcp_ack_filter(false); - - PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets, - sinfo->tx_failed, sinfo->txrate.legacy); } return 0; } @@ -2718,10 +2702,8 @@ int wilc_deinit_host_int(struct net_device *net) s32Error = wilc_deinit(vif); clear_shadow_scan(); - if (op_ifcs == 0) { - PRINT_D(CORECONFIG_DBG, "destroy during ip\n"); + if (op_ifcs == 0) del_timer_sync(&wilc_during_ip_timer); - } if (s32Error) netdev_err(net, "Error while deintializing host interface\n"); -- cgit From c4f97526a029fc6c57baf6c2de349ec41fce0e12 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:04 +0900 Subject: staging: wilc1000: remove unused log message using the HOSTINF_DBG tag This patch remove unused log message using the HOSTINF_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 198 +--------------------- drivers/staging/wilc1000/linux_wlan_common.h | 2 - drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 - 4 files changed, 10 insertions(+), 194 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2022deb113c0..6e0a4267a8ec 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -310,8 +310,6 @@ static s32 handle_set_channel(struct wilc_vif *vif, wid.val = (char *)&hif_set_ch->set_ch; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Setting channel\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -382,9 +380,6 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) if (ip_addr[0] < 192) ip_addr[0] = 0; - PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %pI4\n", - idx, ip_addr); - memcpy(set_ip[idx], ip_addr, IP_ALEN); wid.id = (u16)WID_IP_ADDRESS; @@ -402,8 +397,6 @@ static s32 handle_set_ip_address(struct wilc_vif *vif, u8 *ip_addr, u8 idx) return -EINVAL; } - PRINT_INFO(HOSTINF_DBG, "IP address set\n"); - return result; } @@ -420,8 +413,6 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - PRINT_INFO(HOSTINF_DBG, "%pI4\n", wid.val); - memcpy(get_ip[idx], wid.val, IP_ALEN); kfree(wid.val); @@ -434,10 +425,6 @@ static s32 handle_get_ip_address(struct wilc_vif *vif, u8 idx) return -EINVAL; } - PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d\n", idx); - PRINT_INFO(HOSTINF_DBG, "%pI4\n", get_ip[idx]); - PRINT_INFO(HOSTINF_DBG, "\n"); - return result; } @@ -504,8 +491,6 @@ static s32 handle_cfg_param(struct wilc_vif *vif, down(&hif_drv->sem_cfg_values); - PRINT_D(HOSTINF_DBG, "Setting CFG params\n"); - if (cfg_param_attr->cfg_attr_info.flag & BSS_TYPE) { if (cfg_param_attr->cfg_attr_info.bss_type < 6) { wid_list[wid_cnt].id = WID_BSS_TYPE; @@ -810,9 +795,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, u8 *pu8HdnNtwrksWidVal = NULL; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "Setting SCAN params\n"); - PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", hif_drv->hif_state); - hif_drv->usr_scan_req.scan_result = pstrHostIFscanAttr->result; hif_drv->usr_scan_req.arg = pstrHostIFscanAttr->arg; @@ -832,8 +814,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, goto ERRORHANDLER; } - PRINT_D(HOSTINF_DBG, "Setting SCAN params\n"); - hif_drv->usr_scan_req.rcvd_ch_cnt = 0; strWIDList[u32WidsCount].id = (u16)WID_SSID_PROBE_REQ; @@ -848,8 +828,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.n_ssids; - PRINT_D(HOSTINF_DBG, "In Handle_ProbeRequest number of ssid %d\n", pstrHostIFscanAttr->hidden_network.n_ssids); - for (i = 0; i < pstrHostIFscanAttr->hidden_network.n_ssids; i++) { *pu8Buffer++ = pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len; memcpy(pu8Buffer, pstrHostIFscanAttr->hidden_network.net_info[i].ssid, pstrHostIFscanAttr->hidden_network.net_info[i].ssid_len); @@ -908,8 +886,6 @@ static s32 Handle_Scan(struct wilc_vif *vif, if (result) PRINT_ER("Failed to send scan paramters config packet\n"); - else - PRINT_D(HOSTINF_DBG, "Successfully sent SCAN params config packet\n"); ERRORHANDLER: if (result) { @@ -938,8 +914,6 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, struct wid wid; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "in Handle_ScanDone()\n"); - if (enuEvent == SCAN_EVENT_ABORTED) { PRINT_D(GENERIC_DBG, "Abort running scan\n"); u8abort_running_scan = 1; @@ -990,8 +964,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, return result; } - PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n"); - ptstrJoinBssParam = (struct join_bss_param *)pstrHostIFconnectAttr->params; if (!ptstrJoinBssParam) { PRINT_ER("Required BSSID not found\n"); @@ -1067,8 +1039,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) mode_11i = hif_drv->usr_conn_req.u8security; - PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", hif_drv->usr_conn_req.u8security); - strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE; strWIDList[u32WidsCount].type = WID_CHAR; strWIDList[u32WidsCount].size = sizeof(char); @@ -1078,11 +1048,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) auth_type = (u8)hif_drv->usr_conn_req.auth_type; - PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", - hif_drv->usr_conn_req.auth_type); - PRINT_D(HOSTINF_DBG, "Connecting to network of SSID %s on channel %d\n", - hif_drv->usr_conn_req.pu8ssid, pstrHostIFconnectAttr->ch); - strWIDList[u32WidsCount].id = (u16)WID_JOIN_REQ_EXTENDED; strWIDList[u32WidsCount].type = WID_STR; strWIDList[u32WidsCount].size = 112; @@ -1114,7 +1079,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, } *(pu8CurrByte++) = (ptstrJoinBssParam->cap_info) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->cap_info) >> 8) & 0xFF; - PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8))); if (pstrHostIFconnectAttr->bssid) memcpy(pu8CurrByte, pstrHostIFconnectAttr->bssid, 6); @@ -1126,26 +1090,20 @@ static s32 Handle_Connect(struct wilc_vif *vif, *(pu8CurrByte++) = (ptstrJoinBssParam->beacon_period) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->beacon_period) >> 8) & 0xFF; - PRINT_D(HOSTINF_DBG, "* Beacon Period %d*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8))); *(pu8CurrByte++) = ptstrJoinBssParam->dtim_period; - PRINT_D(HOSTINF_DBG, "* DTIM Period %d*\n", (*(pu8CurrByte - 1))); memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1); pu8CurrByte += (MAX_RATES_SUPPORTED + 1); *(pu8CurrByte++) = ptstrJoinBssParam->wmm_cap; - PRINT_D(HOSTINF_DBG, "* wmm cap%d*\n", (*(pu8CurrByte - 1))); *(pu8CurrByte++) = ptstrJoinBssParam->uapsd_cap; *(pu8CurrByte++) = ptstrJoinBssParam->ht_capable; hif_drv->usr_conn_req.ht_capable = ptstrJoinBssParam->ht_capable; *(pu8CurrByte++) = ptstrJoinBssParam->rsn_found; - PRINT_D(HOSTINF_DBG, "* rsn found %d*\n", *(pu8CurrByte - 1)); *(pu8CurrByte++) = ptstrJoinBssParam->rsn_grp_policy; - PRINT_D(HOSTINF_DBG, "* rsn group policy %0x*\n", (*(pu8CurrByte - 1))); *(pu8CurrByte++) = ptstrJoinBssParam->mode_802_11i; - PRINT_D(HOSTINF_DBG, "* mode_802_11i %d*\n", (*(pu8CurrByte - 1))); memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy)); pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy); @@ -1160,8 +1118,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, *(pu8CurrByte++) = ptstrJoinBssParam->noa_enabled; if (ptstrJoinBssParam->noa_enabled) { - PRINT_D(HOSTINF_DBG, "NOA present\n"); - *(pu8CurrByte++) = (ptstrJoinBssParam->tsf) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 8) & 0xFF; *(pu8CurrByte++) = ((ptstrJoinBssParam->tsf) >> 16) & 0xFF; @@ -1183,8 +1139,7 @@ static s32 Handle_Connect(struct wilc_vif *vif, memcpy(pu8CurrByte, ptstrJoinBssParam->start_time, sizeof(ptstrJoinBssParam->start_time)); pu8CurrByte += sizeof(ptstrJoinBssParam->start_time); - } else - PRINT_D(HOSTINF_DBG, "NOA not present\n"); + } pu8CurrByte = strWIDList[u32WidsCount].val; u32WidsCount++; @@ -1194,8 +1149,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, join_req_vif = vif; } - PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n"); - if (pstrHostIFconnectAttr->bssid) { memcpy(wilc_connected_ssid, pstrHostIFconnectAttr->bssid, ETH_ALEN); @@ -1222,8 +1175,6 @@ ERRORHANDLER: del_timer(&hif_drv->connect_timer); - PRINT_D(HOSTINF_DBG, "could not start wilc_connecting to the required network\n"); - memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (pstrHostIFconnectAttr->result) { @@ -1252,7 +1203,6 @@ ERRORHANDLER: } } - PRINT_D(HOSTINF_DBG, "Deallocating connection parameters\n"); kfree(pstrHostIFconnectAttr->bssid); pstrHostIFconnectAttr->bssid = NULL; @@ -1363,8 +1313,6 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) wid.val = (s8 *)&u16DummyReasonCode; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) @@ -1405,10 +1353,8 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, struct host_if_drv *hif_drv = vif->hif_drv; bNewNtwrkFound = true; - PRINT_INFO(HOSTINF_DBG, "Handling received network info\n"); if (hif_drv->usr_scan_req.scan_result) { - PRINT_D(HOSTINF_DBG, "State: Scanning, parsing network information received\n"); wilc_parse_network_info(pstrRcvdNetworkInfo->buffer, &pstrNetworkInfo); if ((!pstrNetworkInfo) || (!hif_drv->usr_scan_req.scan_result)) { @@ -1423,7 +1369,6 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { if (pstrNetworkInfo->s8rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { - PRINT_D(HOSTINF_DBG, "Network previously discovered\n"); goto done; } else { hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->s8rssi; @@ -1435,8 +1380,6 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, } if (bNewNtwrkFound) { - PRINT_D(HOSTINF_DBG, "New network found\n"); - if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->s8rssi; @@ -1454,8 +1397,6 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, hif_drv->usr_scan_req.arg, pJoinParams); } - } else { - PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit\n"); } } else { pstrNetworkInfo->bNewNetwork = false; @@ -1528,13 +1469,10 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, u8MacStatus = pstrRcvdGnrlAsyncInfo->buffer[7]; u8MacStatusReasonCode = pstrRcvdGnrlAsyncInfo->buffer[8]; u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9]; - PRINT_INFO(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Info = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { u32 u32RcvdAssocRespInfoLen = 0; tstrConnectRespInfo *pstrConnectRespInfo = NULL; - PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo); - memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (u8MacStatus == MAC_CONNECTED) { @@ -1545,10 +1483,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, MAX_ASSOC_RESP_FRAME_SIZE, &u32RcvdAssocRespInfoLen); - PRINT_INFO(HOSTINF_DBG, "Received association response with length = %d\n", u32RcvdAssocRespInfoLen); - if (u32RcvdAssocRespInfoLen != 0) { - PRINT_D(HOSTINF_DBG, "Parsing association response\n"); s32Err = wilc_parse_assoc_resp_info(rcv_assoc_resp, u32RcvdAssocRespInfoLen, &pstrConnectRespInfo); if (s32Err) { @@ -1557,7 +1492,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus; if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - PRINT_INFO(HOSTINF_DBG, "Association response received : Successful connection status\n"); if (pstrConnectRespInfo->pu8RespIEs) { strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen; strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->u16RespIEsLen, GFP_KERNEL); @@ -1584,7 +1518,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, } if (hif_drv->usr_conn_req.pu8bssid) { - PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n"); memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.pu8bssid, 6); if ((u8MacStatus == MAC_CONNECTED) && @@ -1613,7 +1546,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { wilc_set_power_mgmt(vif, 0, 0); - PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n"); hif_drv->hif_state = HOST_IF_CONNECTED; PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n"); @@ -1621,7 +1553,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(10000)); } else { - PRINT_D(HOSTINF_DBG, "MAC status : %d and Connect Status : %d\n", u8MacStatus, strConnectInfo.u16ConnectStatus); hif_drv->hif_state = HOST_IF_IDLE; scan_while_connected = false; } @@ -1641,12 +1572,9 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, hif_drv->usr_conn_req.ies = NULL; } else if ((u8MacStatus == MAC_DISCONNECTED) && (hif_drv->hif_state == HOST_IF_CONNECTED)) { - PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n"); - memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo)); if (hif_drv->usr_scan_req.scan_result) { - PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n"); del_timer(&hif_drv->scan_timer); Handle_ScanDone(vif, SCAN_EVENT_ABORTED); } @@ -1694,9 +1622,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, } else if ((u8MacStatus == MAC_DISCONNECTED) && (hif_drv->usr_scan_req.scan_result)) { - PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW while scanning\n"); - PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >>\n\n"); - del_timer(&hif_drv->scan_timer); if (hif_drv->usr_scan_req.scan_result) Handle_ScanDone(vif, SCAN_EVENT_ABORTED); @@ -1725,8 +1650,6 @@ static int Handle_Key(struct wilc_vif *vif, case WEP: if (pstrHostIFkeyAttr->action & ADDKEY_AP) { - PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); - PRINT_D(GENERIC_DBG, "ID Hostint is %d\n", pstrHostIFkeyAttr->attr.wep.index); strWIDList[0].id = (u16)WID_11I_MODE; strWIDList[0].type = WID_CHAR; strWIDList[0].size = sizeof(char); @@ -1763,7 +1686,6 @@ static int Handle_Key(struct wilc_vif *vif, wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & ADDKEY) { - PRINT_D(HOSTINF_DBG, "Handling WEP key\n"); pu8keybuf = kmalloc(pstrHostIFkeyAttr->attr.wep.key_len + 2, GFP_KERNEL); if (!pu8keybuf) { PRINT_ER("No buffer to send Key\n"); @@ -1785,7 +1707,6 @@ static int Handle_Key(struct wilc_vif *vif, wilc_get_vif_idx(vif)); kfree(pu8keybuf); } else if (pstrHostIFkeyAttr->action & REMOVEKEY) { - PRINT_D(HOSTINF_DBG, "Removing key\n"); wid.id = (u16)WID_REMOVE_WEP_KEY; wid.type = WID_STR; @@ -1802,8 +1723,6 @@ static int Handle_Key(struct wilc_vif *vif, wid.val = (s8 *)&pstrHostIFkeyAttr->attr.wep.index; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Setting default key index\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -1845,8 +1764,6 @@ static int Handle_Key(struct wilc_vif *vif, kfree(pu8keybuf); up(&hif_drv->sem_test_key_block); } else if (pstrHostIFkeyAttr->action & ADDKEY) { - PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n"); - pu8keybuf = kzalloc(RX_MIC_KEY_MSG_LEN, GFP_KERNEL); if (pu8keybuf == NULL) { PRINT_ER("No buffer to send RxGTK Key\n"); @@ -1948,9 +1865,6 @@ _WPAPtk_end_case_: break; case PMKSA: - - PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n"); - pu8keybuf = kmalloc((pstrHostIFkeyAttr->attr.pmkid.numpmkid * PMKSA_KEY_LEN) + 1, GFP_KERNEL); if (!pu8keybuf) { PRINT_ER("No buffer to send PMKSA Key\n"); @@ -1995,8 +1909,6 @@ static void Handle_Disconnect(struct wilc_vif *vif) wid.val = (s8 *)&u16DummyReasonCode; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Sending disconnect request\n"); - wilc_optaining_ip = false; wilc_set_power_mgmt(vif, 0, 0); @@ -2026,10 +1938,8 @@ static void Handle_Disconnect(struct wilc_vif *vif) } if (hif_drv->usr_conn_req.conn_result) { - if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n"); + if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) del_timer(&hif_drv->connect_timer); - } hif_drv->usr_conn_req.conn_result(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL, @@ -2074,10 +1984,8 @@ void wilc_resolve_disconnect_aberration(struct wilc_vif *vif) if (!vif->hif_drv) return; if ((vif->hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) || - (vif->hif_drv->hif_state == HOST_IF_CONNECTING)) { - PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n"); + (vif->hif_drv->hif_state == HOST_IF_CONNECTING)) wilc_disconnect(vif, 1); - } } static s32 Handle_GetChnl(struct wilc_vif *vif) @@ -2091,8 +1999,6 @@ static s32 Handle_GetChnl(struct wilc_vif *vif) wid.val = (s8 *)&ch_no; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Getting channel value\n"); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -2116,8 +2022,6 @@ static void Handle_GetRssi(struct wilc_vif *vif) wid.val = &rssi; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Getting RSSI value\n"); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2141,8 +2045,6 @@ static void Handle_GetLinkspeed(struct wilc_vif *vif) wid.val = &link_speed; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Getting LINKSPEED value\n"); - result = wilc_send_config_pkt(vif, GET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) { @@ -2260,8 +2162,6 @@ static void Handle_AddBeacon(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Adding BEACON\n"); - wid.id = (u16)WID_ADD_BEACON; wid.type = WID_BIN; wid.size = pstrSetBeaconParam->head_len + pstrSetBeaconParam->tail_len + 16; @@ -2324,8 +2224,6 @@ static void Handle_DelBeacon(struct wilc_vif *vif) pu8CurrByte = wid.val; - PRINT_D(HOSTINF_DBG, "Deleting BEACON\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) @@ -2339,7 +2237,6 @@ static u32 WILC_HostIf_PackStaParam(u8 *pu8Buffer, pu8CurrByte = pu8Buffer; - PRINT_D(HOSTINF_DBG, "Packing STA params\n"); memcpy(pu8CurrByte, pstrStationParam->bssid, ETH_ALEN); pu8CurrByte += ETH_ALEN; @@ -2387,7 +2284,6 @@ static void Handle_AddStation(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Handling add station\n"); wid.id = (u16)WID_ADD_STA; wid.type = WID_BIN; wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len; @@ -2422,8 +2318,6 @@ static void Handle_DelAllSta(struct wilc_vif *vif, wid.type = WID_STR; wid.size = (pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1; - PRINT_D(HOSTINF_DBG, "Handling delete station\n"); - wid.val = kmalloc((pstrDelAllStaParam->assoc_sta * ETH_ALEN) + 1, GFP_KERNEL); if (!wid.val) goto ERRORHANDLER; @@ -2463,8 +2357,6 @@ static void Handle_DelStation(struct wilc_vif *vif, wid.type = WID_BIN; wid.size = ETH_ALEN; - PRINT_D(HOSTINF_DBG, "Handling delete station\n"); - wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) goto ERRORHANDLER; @@ -2493,7 +2385,6 @@ static void Handle_EditStation(struct wilc_vif *vif, wid.type = WID_BIN; wid.size = WILC_ADD_STA_LENGTH + pstrStationParam->rates_len; - PRINT_D(HOSTINF_DBG, "Handling edit station\n"); wid.val = kmalloc(wid.size, GFP_KERNEL); if (!wid.val) goto ERRORHANDLER; @@ -2547,9 +2438,6 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, goto ERRORHANDLER; } - PRINT_D(HOSTINF_DBG, "Setting channel :%d\n", - pstrHostIfRemainOnChan->ch); - u8remain_on_chan_flag = true; wid.id = (u16)WID_REMAIN_ON_CHAN; wid.type = WID_STR; @@ -2593,10 +2481,6 @@ static int Handle_RegisterFrame(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Handling frame register : %d FrameType: %d\n", - pstrHostIfRegisterFrame->reg, - pstrHostIfRegisterFrame->frame_type); - wid.id = (u16)WID_REGISTER_FRAME; wid.type = WID_STR; wid.val = kmalloc(sizeof(u16) + 2, GFP_KERNEL); @@ -2629,8 +2513,6 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, s32 result = 0; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "CANCEL REMAIN ON CHAN\n"); - if (P2P_LISTEN_STATE) { u8remain_on_chan_flag = false; wid.id = (u16)WID_REMAIN_ON_CHAN; @@ -2698,12 +2580,10 @@ static void Handle_PowerManagement(struct wilc_vif *vif, s8PowerMode = MIN_FAST_PS; else s8PowerMode = NO_POWERSAVE; - PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode); + wid.val = &s8PowerMode; wid.size = sizeof(char); - PRINT_D(HOSTINF_DBG, "Handling Power Management\n"); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); if (result) @@ -2717,8 +2597,6 @@ static void Handle_SetMulticastFilter(struct wilc_vif *vif, struct wid wid; u8 *pu8CurrByte; - PRINT_D(HOSTINF_DBG, "Setup Multicast Filter\n"); - wid.id = (u16)WID_SETUP_MULTICAST_FILTER; wid.type = WID_BIN; wid.size = sizeof(struct set_multicast) + ((strHostIfSetMulti->cnt) * ETH_ALEN); @@ -2779,8 +2657,6 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - if (result) - PRINT_D(HOSTINF_DBG, "Couldn't delete BA Session\n"); kfree(wid.val); @@ -2849,7 +2725,6 @@ static int hostIFthread(void *pvArg) if (msg.id == HOST_IF_MSG_CONNECT && vif->hif_drv->usr_scan_req.scan_result) { - PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n"); wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); usleep_range(2 * 1000, 2 * 1000); continue; @@ -2899,7 +2774,6 @@ static int hostIFthread(void *pvArg) case HOST_IF_MSG_RCVD_SCAN_COMPLETE: del_timer(&vif->hif_drv->scan_timer); - PRINT_D(HOSTINF_DBG, "scan completed successfully\n"); if (!wilc_wlan_get_num_conn_ifcs(wilc)) wilc_chip_sleep_manually(wilc); @@ -2954,13 +2828,11 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_SCAN_TIMER_FIRED: - PRINT_D(HOSTINF_DBG, "Scan Timeout\n"); Handle_ScanDone(msg.vif, SCAN_EVENT_ABORTED); break; case HOST_IF_MSG_CONNECT_TIMER_FIRED: - PRINT_D(HOSTINF_DBG, "Connect Timeout\n"); Handle_ConnectTimeout(msg.vif); break; @@ -2978,14 +2850,12 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_SET_IPADDRESS: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n"); handle_set_ip_address(vif, msg.body.ip_info.ip_addr, msg.body.ip_info.idx); break; case HOST_IF_MSG_GET_IPADDRESS: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_IPADDRESS\n"); handle_get_ip_address(vif, msg.body.ip_info.idx); break; @@ -3000,12 +2870,10 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_REMAIN_ON_CHAN: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REMAIN_ON_CHAN\n"); Handle_RemainOnChan(msg.vif, &msg.body.remain_on_ch); break; case HOST_IF_MSG_REGISTER_FRAME: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_REGISTER_FRAME\n"); Handle_RegisterFrame(msg.vif, &msg.body.reg_frame); break; @@ -3014,7 +2882,6 @@ static int hostIFthread(void *pvArg) break; case HOST_IF_MSG_SET_MULTICAST_FILTER: - PRINT_D(HOSTINF_DBG, "HOST_IF_MSG_SET_MULTICAST_FILTER\n"); Handle_SetMulticastFilter(msg.vif, &msg.body.multicast_info); break; @@ -3039,7 +2906,6 @@ static int hostIFthread(void *pvArg) } } - PRINT_D(HOSTINF_DBG, "Releasing thread exit semaphore\n"); up(&hif_sema_thread); return 0; } @@ -3689,9 +3555,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, if (hidden_network) { msg.body.scan_info.hidden_network.net_info = hidden_network->net_info; msg.body.scan_info.hidden_network.n_ssids = hidden_network->n_ssids; - - } else - PRINT_D(HOSTINF_DBG, "hidden_network IS EQUAL TO NULL\n"); + } msg.vif = vif; msg.body.scan_info.src = scan_source; @@ -3717,7 +3581,6 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, return -EINVAL; } - PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n"); hif_drv->scan_timer.data = (unsigned long)vif; mod_timer(&hif_drv->scan_timer, jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT)); @@ -3774,8 +3637,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) vif = netdev_priv(dev); wilc = vif->wilc; - PRINT_D(HOSTINF_DBG, "Initializing host interface for client %d\n", clients_count + 1); - scan_while_connected = false; sema_init(&hif_sema_wait_response, 0); @@ -3794,7 +3655,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) wilc_optaining_ip = false; - PRINT_D(HOSTINF_DBG, "Global handle pointer value=%p\n", hif_drv); if (clients_count == 0) { sema_init(&hif_sema_thread, 0); sema_init(&hif_sema_driver, 0); @@ -3808,8 +3668,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) sema_init(&hif_drv->sem_get_chnl, 0); sema_init(&hif_drv->sem_inactive_time, 0); - PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count); - if (clients_count == 0) { result = wilc_mq_create(&hif_msg_q); @@ -3847,13 +3705,6 @@ int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler) hif_drv->p2p_timeout = 0; - PRINT_INFO(HOSTINF_DBG, "Initialization values, Site survey value: %d\n Scan source: %d\n Active scan time: %d\n Passive scan time: %d\nCurrent tx Rate = %d\n", - hif_drv->cfg_values.site_survey_enabled, - hif_drv->cfg_values.scan_source, - hif_drv->cfg_values.active_scan_time, - hif_drv->cfg_values.passive_scan_time, - hif_drv->cfg_values.curr_tx_rate); - up(&hif_drv->sem_cfg_values); clients_count++; @@ -3880,17 +3731,10 @@ s32 wilc_deinit(struct wilc_vif *vif) down(&hif_sema_deinit); terminated_handle = hif_drv; - PRINT_D(HOSTINF_DBG, "De-initializing host interface for client %d\n", clients_count); - - if (del_timer_sync(&hif_drv->scan_timer)) - PRINT_D(HOSTINF_DBG, ">> Scan timer is active\n"); - - if (del_timer_sync(&hif_drv->connect_timer)) - PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n"); - - if (del_timer_sync(&periodic_rssi)) - PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n"); + del_timer_sync(&hif_drv->scan_timer); + del_timer_sync(&hif_drv->connect_timer); + del_timer_sync(&periodic_rssi); del_timer_sync(&hif_drv->remain_on_ch_timer); wilc_set_wfi_drv_handler(vif, 0, 0); @@ -3909,9 +3753,7 @@ s32 wilc_deinit(struct wilc_vif *vif) memset(&msg, 0, sizeof(struct host_if_msg)); if (clients_count == 1) { - if (del_timer_sync(&periodic_rssi)) - PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n"); - + del_timer_sync(&periodic_rssi); msg.id = HOST_IF_MSG_EXIT; msg.vif = vif; @@ -3985,10 +3827,8 @@ void wilc_gnrl_async_info_received(struct wilc *wilc, u8 *pu8Buffer, } hif_drv = vif->hif_drv; - PRINT_D(HOSTINF_DBG, "General asynchronous info packet received\n"); if (!hif_drv || hif_drv == terminated_handle) { - PRINT_D(HOSTINF_DBG, "Wifi driver handler is equal to NULL\n"); up(&hif_sema_deinit); return; } @@ -4123,17 +3963,14 @@ int wilc_frame_register(struct wilc_vif *vif, u16 frame_type, bool reg) msg.id = HOST_IF_MSG_REGISTER_FRAME; switch (frame_type) { case ACTION: - PRINT_D(HOSTINF_DBG, "ACTION\n"); msg.body.reg_frame.reg_id = ACTION_FRM_IDX; break; case PROBE_REQ: - PRINT_D(HOSTINF_DBG, "PROBE REQ\n"); msg.body.reg_frame.reg_id = PROBE_REQ_IDX; break; default: - PRINT_D(HOSTINF_DBG, "Not valid frame type\n"); break; } msg.body.reg_frame.frame_type = frame_type; @@ -4162,8 +3999,6 @@ int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n"); - msg.id = HOST_IF_MSG_ADD_BEACON; msg.vif = vif; beacon_info->interval = interval; @@ -4213,7 +4048,6 @@ int wilc_del_beacon(struct wilc_vif *vif) msg.id = HOST_IF_MSG_DEL_BEACON; msg.vif = vif; - PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n"); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) @@ -4236,8 +4070,6 @@ int wilc_add_station(struct wilc_vif *vif, struct add_sta_param *sta_param) memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n"); - msg.id = HOST_IF_MSG_ADD_STATION; msg.vif = vif; @@ -4270,8 +4102,6 @@ int wilc_del_station(struct wilc_vif *vif, const u8 *mac_addr) memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n"); - msg.id = HOST_IF_MSG_DEL_STATION; msg.vif = vif; @@ -4303,8 +4133,6 @@ int wilc_del_allstation(struct wilc_vif *vif, u8 mac_addr[][ETH_ALEN]) memset(&msg, 0, sizeof(struct host_if_msg)); - PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n"); - msg.id = HOST_IF_MSG_DEL_ALL_STA; msg.vif = vif; @@ -4350,8 +4178,6 @@ int wilc_edit_station(struct wilc_vif *vif, return -EFAULT; } - PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n"); - memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_EDIT_STATION; @@ -4380,8 +4206,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) struct power_mgmt_param *pwr_mgmt_info = &msg.body.pwr_mgmt_info; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", enabled); - if (!hif_drv) { PRINT_ER("driver is null\n"); return -EFAULT; @@ -4390,8 +4214,6 @@ int wilc_set_power_mgmt(struct wilc_vif *vif, bool enabled, u32 timeout) if (wilc_wlan_get_num_conn_ifcs(vif->wilc) == 2 && enabled) return 0; - PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n"); - memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_POWER_MGMT; @@ -4419,8 +4241,6 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, return -EFAULT; } - PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n"); - memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_SET_MULTICAST_FILTER; diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 5e1d3ad5bed0..5374f36bff62 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -4,7 +4,6 @@ enum debug_region { Generic_debug = 0, Hostapd_debug, - Hostinf_debug, CFG80211_debug, Interrupt_debug, TX_debug, @@ -22,7 +21,6 @@ enum debug_region { #define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) -#define HOSTINF_DBG (1 << Hostinf_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) #define TX_DBG (1 << TX_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index c7e07758ad7e..4b38c377be79 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | HOSTINF_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 7a5d81953839..a40b310072be 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1716,8 +1716,6 @@ static void WILC_WFI_RemainOnChannelReady(void *pUserVoid) priv = (struct wilc_priv *)pUserVoid; - PRINT_D(HOSTINF_DBG, "Remain on channel ready\n"); - priv->bInP2PlistenState = true; cfg80211_ready_on_channel(priv->wdev, -- cgit From a41047962ac0530bb275bfb656fbc1e348fad23a Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:05 +0900 Subject: staging: wilc1000: remove unused log message using the TX_DBG tag This patch remove unused log message using the TX_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 4 ---- drivers/staging/wilc1000/linux_wlan_common.h | 2 -- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 9 +++------ 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 9e5dea4b24c5..202be15b615f 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -1047,10 +1047,6 @@ static void linux_wlan_tx_complete(void *priv, int status) { struct tx_complete_data *pv_data = (struct tx_complete_data *)priv; - if (status == 1) - PRINT_D(TX_DBG, "Packet sent successfully - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); - else - PRINT_D(TX_DBG, "Couldn't send packet - Size = %d - Address = %p - SKB = %p\n", pv_data->size, pv_data->buff, pv_data->skb); dev_kfree_skb(pv_data->skb); kfree(pv_data); } diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 5374f36bff62..617bc5325cd2 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -6,7 +6,6 @@ enum debug_region { Hostapd_debug, CFG80211_debug, Interrupt_debug, - TX_debug, RX_debug, Lock_debug, Tcp_enhance, @@ -23,7 +22,6 @@ enum debug_region { #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) -#define TX_DBG (1 << TX_debug) #define RX_DBG (1 << RX_debug) #define LOCK_DBG (1 << Lock_debug) #define TCP_ENH (1 << Tcp_enhance) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 4b38c377be79..a3d274bd0820 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | TX_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 46087e29fc15..dd0c051fedca 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -652,13 +652,11 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) } } while (1); - if (i == 0) { - PRINT_D(TX_DBG, "Nothing in TX-Q\n"); + if (i == 0) break; - } else { - PRINT_D(TX_DBG, "Mark the last entry in VMM table - number of previous entries = %d\n", i); + else vmm_table[i] = 0x0; - } + acquire_bus(wilc, ACQUIRE_AND_WAKEUP); counter = 0; do { @@ -807,7 +805,6 @@ _end_: up(&wilc->txq_add_to_head_cs); wilc->txq_exit = 1; - PRINT_D(TX_DBG, "THREAD: Exiting txq\n"); *txq_count = wilc->txq_entries; return ret; } -- cgit From d9fb23d72f3f1f4e2209134ab4c9b40d72b21a20 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:06 +0900 Subject: staging: wilc1000: removes function 'wilc_dealloc_network_info()' This patch removes function 'wilc_dealloc_network_info()'. Does not need this function which only free memory. Therefore, this function is removed and changed directly with kfree. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 22 ---------------------- drivers/staging/wilc1000/coreconfigurator.h | 1 - drivers/staging/wilc1000/host_interface.c | 4 ++-- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 11e3ce078bad..81dd22e9c5f6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -353,28 +353,6 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) return 0; } -s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info) -{ - s32 result = 0; - - if (network_info) { - if (network_info->pu8IEs) { - kfree(network_info->pu8IEs); - network_info->pu8IEs = NULL; - } else { - result = -EFAULT; - } - - kfree(network_info); - network_info = NULL; - - } else { - result = -EFAULT; - } - - return result; -} - s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info) { diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index d801e58be8e6..23775e4e0f37 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -121,7 +121,6 @@ typedef struct { } tstrDisconnectNotifInfo; s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); -s32 wilc_dealloc_network_info(tstrNetworkInfo *network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 6e0a4267a8ec..2a1d7e952494 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1410,8 +1410,8 @@ done: pstrRcvdNetworkInfo->buffer = NULL; if (pstrNetworkInfo) { - wilc_dealloc_network_info(pstrNetworkInfo); - pstrNetworkInfo = NULL; + kfree(pstrNetworkInfo->pu8IEs); + kfree(pstrNetworkInfo); } return result; -- cgit From 5f79c2aebf87a1cbe84a728916ecb77287eaa715 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:07 +0900 Subject: staging: wilc1000: removes function 'wilc_dealloc_assoc_resp_info()' This patch removes function wilc_dealloc_assoc_resp_info()'. Does not need this function which only free memory. Therefore, this function is removed and changed directly with kfree. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 22 ---------------------- drivers/staging/wilc1000/coreconfigurator.h | 1 - drivers/staging/wilc1000/host_interface.c | 4 ++-- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 81dd22e9c5f6..c86278de8c41 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -386,25 +386,3 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, return 0; } - -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info) -{ - s32 result = 0; - - if (connect_resp_info) { - if (connect_resp_info->pu8RespIEs) { - kfree(connect_resp_info->pu8RespIEs); - connect_resp_info->pu8RespIEs = NULL; - } else { - result = -EFAULT; - } - - kfree(connect_resp_info); - connect_resp_info = NULL; - - } else { - result = -EFAULT; - } - - return result; -} diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 23775e4e0f37..d42f47c8e61d 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -123,7 +123,6 @@ typedef struct { s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, tstrConnectRespInfo **ret_connect_resp_info); -s32 wilc_dealloc_assoc_resp_info(tstrConnectRespInfo *connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer, diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2a1d7e952494..30b93d0b7d80 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1501,8 +1501,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, } if (pstrConnectRespInfo) { - wilc_dealloc_assoc_resp_info(pstrConnectRespInfo); - pstrConnectRespInfo = NULL; + kfree(pstrConnectRespInfo->pu8RespIEs); + kfree(pstrConnectRespInfo); } } } -- cgit From 40d96e1d7600b094faeee43cd3de71df0b1ddc52 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:08 +0900 Subject: staging: wilc1000: remove typedef from tstrConnectRespInfo This patch removes typedef from the struct tstrConnectRespInfo and renames it to connect_resp_info. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 6 +++--- drivers/staging/wilc1000/coreconfigurator.h | 6 +++--- drivers/staging/wilc1000/host_interface.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c86278de8c41..c456a324fddc 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -354,14 +354,14 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) } s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, - tstrConnectRespInfo **ret_connect_resp_info) + struct connect_resp_info **ret_connect_resp_info) { - tstrConnectRespInfo *connect_resp_info = NULL; + struct connect_resp_info *connect_resp_info = NULL; u16 assoc_resp_len = 0; u8 *ies = NULL; u16 ies_len = 0; - connect_resp_info = kzalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL); + connect_resp_info = kzalloc(sizeof(*connect_resp_info), GFP_KERNEL); if (!connect_resp_info) return -ENOMEM; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index d42f47c8e61d..611486bec32d 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -97,13 +97,13 @@ typedef struct { u64 u64Tsf; } tstrNetworkInfo; -typedef struct { +struct connect_resp_info { u16 u16capability; u16 u16ConnectStatus; u16 u16AssocID; u8 *pu8RespIEs; u16 u16RespIEsLen; -} tstrConnectRespInfo; +}; typedef struct { u8 au8bssid[6]; @@ -122,7 +122,7 @@ typedef struct { s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, - tstrConnectRespInfo **ret_connect_resp_info); + struct connect_resp_info **ret_connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, u32 u32Length); void wilc_network_info_received(struct wilc *wilc, u8 *pu8Buffer, diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 30b93d0b7d80..513b1f016177 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1471,7 +1471,7 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, u8MacStatusAdditionalInfo = pstrRcvdGnrlAsyncInfo->buffer[9]; if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { u32 u32RcvdAssocRespInfoLen = 0; - tstrConnectRespInfo *pstrConnectRespInfo = NULL; + struct connect_resp_info *pstrConnectRespInfo = NULL; memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); -- cgit From ba7b6ff52a153ce94def3466e9eb23c7bb9888d5 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:09 +0900 Subject: staging: wilc1000: renames struct connect_resp_info variables This patch renames to avoid camelcase and remove prefix names, changes follow are: - u16capability to capability - u16ConnectStatus to status - u16AssocID to assoc_id - pu8RespIEs to ies - u16RespIEsLen to ies_len Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 14 +++++++------- drivers/staging/wilc1000/coreconfigurator.h | 10 +++++----- drivers/staging/wilc1000/host_interface.c | 14 +++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index c456a324fddc..e9f6262bb0a6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -367,19 +367,19 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, assoc_resp_len = (u16)buffer_len; - connect_resp_info->u16ConnectStatus = get_asoc_status(buffer); - if (connect_resp_info->u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - connect_resp_info->u16capability = get_assoc_resp_cap_info(buffer); - connect_resp_info->u16AssocID = get_asoc_id(buffer); + connect_resp_info->status = get_asoc_status(buffer); + if (connect_resp_info->status == SUCCESSFUL_STATUSCODE) { + connect_resp_info->capability = get_assoc_resp_cap_info(buffer); + connect_resp_info->assoc_id = get_asoc_id(buffer); ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); - connect_resp_info->pu8RespIEs = kmemdup(ies, ies_len, GFP_KERNEL); - if (!connect_resp_info->pu8RespIEs) + connect_resp_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!connect_resp_info->ies) return -ENOMEM; - connect_resp_info->u16RespIEsLen = ies_len; + connect_resp_info->ies_len = ies_len; } *ret_connect_resp_info = connect_resp_info; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 611486bec32d..aa9aee68e064 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -98,11 +98,11 @@ typedef struct { } tstrNetworkInfo; struct connect_resp_info { - u16 u16capability; - u16 u16ConnectStatus; - u16 u16AssocID; - u8 *pu8RespIEs; - u16 u16RespIEsLen; + u16 capability; + u16 status; + u16 assoc_id; + u8 *ies; + u16 ies_len; }; typedef struct { diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 513b1f016177..992008b14704 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1489,19 +1489,19 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, if (s32Err) { PRINT_ER("wilc_parse_assoc_resp_info() returned error %d\n", s32Err); } else { - strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus; + strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->status; if (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE) { - if (pstrConnectRespInfo->pu8RespIEs) { - strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen; - strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->u16RespIEsLen, GFP_KERNEL); - memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs, - pstrConnectRespInfo->u16RespIEsLen); + if (pstrConnectRespInfo->ies) { + strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->ies_len; + strConnectInfo.pu8RespIEs = kmalloc(pstrConnectRespInfo->ies_len, GFP_KERNEL); + memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->ies, + pstrConnectRespInfo->ies_len); } } if (pstrConnectRespInfo) { - kfree(pstrConnectRespInfo->pu8RespIEs); + kfree(pstrConnectRespInfo->ies); kfree(pstrConnectRespInfo); } } -- cgit From 6b5180a0845e3deb7ed70271ca8ac313b05b5d04 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:10 +0900 Subject: staging: wilc1000: remove typedef from pstrNetworkInfo This patch removes typedef from the struct pstrNetworkInfo and renames it to network_info. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 7 ++++--- drivers/staging/wilc1000/coreconfigurator.h | 7 ++++--- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/host_interface.h | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 14 +++++++------- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index e9f6262bb0a6..0d0a4ec9a073 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -270,9 +270,10 @@ static u8 get_current_channel_802_11n(u8 *pu8msa, u16 rx_len) return 0; } -s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) +s32 wilc_parse_network_info(u8 *msg_buffer, + struct network_info **ret_network_info) { - tstrNetworkInfo *network_info = NULL; + struct network_info *network_info = NULL; u8 msg_type = 0; u8 msg_id = 0; u16 msg_len = 0; @@ -304,7 +305,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info) u32 tsf_lo; u32 tsf_hi; - network_info = kzalloc(sizeof(tstrNetworkInfo), GFP_KERNEL); + network_info = kzalloc(sizeof(*network_info), GFP_KERNEL); if (!network_info) return -ENOMEM; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index aa9aee68e064..214b43b85c5c 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -76,7 +76,7 @@ typedef struct { s8 as8RSSI[NUM_RSSI]; } tstrRSSI; -typedef struct { +struct network_info { s8 s8rssi; u16 u16CapInfo; u8 au8ssid[MAX_SSID_LEN]; @@ -95,7 +95,7 @@ typedef struct { void *pJoinParams; tstrRSSI strRssi; u64 u64Tsf; -} tstrNetworkInfo; +}; struct connect_resp_info { u16 capability; @@ -120,7 +120,8 @@ typedef struct { size_t ie_len; } tstrDisconnectNotifInfo; -s32 wilc_parse_network_info(u8 *msg_buffer, tstrNetworkInfo **ret_network_info); +s32 wilc_parse_network_info(u8 *msg_buffer, + struct network_info **ret_network_info); s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, struct connect_resp_info **ret_connect_resp_info); void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 992008b14704..c0b4f7bf3a82 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -272,7 +272,7 @@ static struct wilc_vif *join_req_vif; #define FLUSHED_JOIN_REQ 1 #define FLUSHED_BYTE_POS 79 -static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo); +static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo); static int host_int_get_ipaddress(struct wilc_vif *vif, u8 *ip_addr, u8 idx); /* The u8IfIdx starts from 0 to NUM_CONCURRENT_IFC -1, but 0 index used as @@ -1348,7 +1348,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, u32 i; bool bNewNtwrkFound; s32 result = 0; - tstrNetworkInfo *pstrNetworkInfo = NULL; + struct network_info *pstrNetworkInfo = NULL; void *pJoinParams = NULL; struct host_if_drv *hif_drv = vif->hif_drv; @@ -4255,7 +4255,7 @@ int wilc_setup_multicast_filter(struct wilc_vif *vif, bool enabled, return result; } -static void *host_int_ParseJoinBssParam(tstrNetworkInfo *ptstrNetworkInfo) +static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) { struct join_bss_param *pNewJoinBssParam = NULL; u8 *pu8IEs; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 69c36a7449c7..c73a5c389297 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -168,8 +168,8 @@ enum KEY_TYPE { PMKSA, }; -typedef void (*wilc_scan_result)(enum scan_event, tstrNetworkInfo *, - void *, void *); +typedef void (*wilc_scan_result)(enum scan_event, struct network_info *, + void *, void *); typedef void (*wilc_connect_result)(enum conn_event, tstrConnectInfo *, diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index a40b310072be..b6a50c6b94c7 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -93,7 +93,7 @@ static const struct wiphy_wowlan_support wowlan_support = { extern int wilc_mac_open(struct net_device *ndev); extern int wilc_mac_close(struct net_device *ndev); -static tstrNetworkInfo last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; +static struct network_info last_scanned_shadow[MAX_NUM_SCANNED_NETWORKS_SHADOW]; static u32 last_scanned_cnt; struct timer_list wilc_during_ip_timer; static struct timer_list hAgingTimer; @@ -206,7 +206,7 @@ static void clear_shadow_scan(void) } } -static u32 get_rssi_avg(tstrNetworkInfo *network_info) +static u32 get_rssi_avg(struct network_info *network_info) { u8 i; int rssi_v = 0; @@ -231,7 +231,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) wiphy = priv->dev->ieee80211_ptr->wiphy; for (i = 0; i < last_scanned_cnt; i++) { - tstrNetworkInfo *network_info; + struct network_info *network_info; network_info = &last_scanned_shadow[i]; @@ -310,7 +310,7 @@ static void clear_duringIP(unsigned long arg) wilc_optaining_ip = false; } -static int is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, +static int is_network_in_shadow(struct network_info *pstrNetworkInfo, void *user_void) { int state = -1; @@ -333,7 +333,7 @@ static int is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, return state; } -static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, +static void add_network_to_shadow(struct network_info *pstrNetworkInfo, void *user_void, void *pJoinParams) { int ap_found = is_network_in_shadow(pstrNetworkInfo, user_void); @@ -384,7 +384,7 @@ static void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, } static void CfgScanResult(enum scan_event scan_event, - tstrNetworkInfo *network_info, + struct network_info *network_info, void *user_void, void *join_params) { @@ -693,7 +693,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, struct wilc_priv *priv; struct host_if_drv *pstrWFIDrv; - tstrNetworkInfo *pstrNetworkInfo = NULL; + struct network_info *pstrNetworkInfo = NULL; struct wilc_vif *vif; wilc_connecting = 1; -- cgit From 5c23a291450f763e2d45264141617b8c3967c7e7 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:11 +0900 Subject: staging: wilc1000: renames s8rssi of connect_resp_info structure This patch renames s8rssi variable to rssi. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 6 +++--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 0d0a4ec9a073..1e8c56bd73d9 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -309,7 +309,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, if (!network_info) return -ENOMEM; - network_info->s8rssi = wid_val[0]; + network_info->rssi = wid_val[0]; msa = &wid_val[1]; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 214b43b85c5c..e386e85030d9 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -77,7 +77,7 @@ typedef struct { } tstrRSSI; struct network_info { - s8 s8rssi; + s8 rssi; u16 u16CapInfo; u8 au8ssid[MAX_SSID_LEN]; u8 u8SsidLen; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c0b4f7bf3a82..f40b5a7ea8a2 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1368,10 +1368,10 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, (pstrNetworkInfo->au8bssid)) { if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) { - if (pstrNetworkInfo->s8rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { + if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { goto done; } else { - hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->s8rssi; + hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->rssi; bNewNtwrkFound = false; break; } @@ -1381,7 +1381,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, if (bNewNtwrkFound) { if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { - hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->s8rssi; + hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi; if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid && pstrNetworkInfo->au8bssid) { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index b6a50c6b94c7..277d82af2e0f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -351,13 +351,13 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, ap_index = ap_found; } rssi_index = last_scanned_shadow[ap_index].strRssi.u8Index; - last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->s8rssi; + last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi; if (rssi_index == NUM_RSSI) { rssi_index = 0; last_scanned_shadow[ap_index].strRssi.u8Full = 1; } last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; - last_scanned_shadow[ap_index].s8rssi = pstrNetworkInfo->s8rssi; + last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo; last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; memcpy(last_scanned_shadow[ap_index].au8ssid, @@ -403,8 +403,8 @@ static void CfgScanResult(enum scan_event scan_event, return; if (wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC && - (((s32)network_info->s8rssi * 100) < 0 || - ((s32)network_info->s8rssi * 100) > 100)) + (((s32)network_info->rssi * 100) < 0 || + ((s32)network_info->rssi * 100) > 100)) return; if (network_info) { @@ -415,7 +415,7 @@ static void CfgScanResult(enum scan_event scan_event, return; PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," - "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->s8rssi) * 100), + "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->rssi) * 100), network_info->u16CapInfo, network_info->u16BeaconPeriod); if (network_info->bNewNetwork) { @@ -428,7 +428,7 @@ static void CfgScanResult(enum scan_event scan_event, if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo, network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, (((s32)network_info->s8rssi) * 100), GFP_KERNEL); + (size_t)network_info->u16IEsLen, (((s32)network_info->rssi) * 100), GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } } @@ -439,7 +439,7 @@ static void CfgScanResult(enum scan_event scan_event, if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) { PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].au8ssid); - last_scanned_shadow[i].s8rssi = network_info->s8rssi; + last_scanned_shadow[i].rssi = network_info->rssi; last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; break; } -- cgit From fa5e2d159fb19f42dc598079ccdd7c385345ac4b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:12 +0900 Subject: staging: wilc1000: renames u16CapInfo of connect_resp_info structure This patch renames u16CapInfo variable to cap_info. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 42 +++++++++++++++++------ 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 1e8c56bd73d9..6c40d36922f6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -314,7 +314,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, msa = &wid_val[1]; rx_len = wid_len - 1; - network_info->u16CapInfo = get_cap_info(msa); + network_info->cap_info = get_cap_info(msa); network_info->u32Tsf = get_beacon_timestamp_lo(msa); tsf_lo = get_beacon_timestamp_lo(msa); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index e386e85030d9..ace50d86d7c6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -78,7 +78,7 @@ typedef struct { struct network_info { s8 rssi; - u16 u16CapInfo; + u16 cap_info; u8 au8ssid[MAX_SSID_LEN]; u8 u8SsidLen; u8 au8bssid[6]; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index f40b5a7ea8a2..d56a33c20ddd 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4277,7 +4277,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) if (pNewJoinBssParam) { pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; - pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo; + pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 277d82af2e0f..76768f291f50 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -246,9 +246,17 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) rssi = get_rssi_avg(network_info); if (memcmp("DIRECT-", network_info->au8ssid, 7) || direct_scan) { - bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo, - network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL); + bss = cfg80211_inform_bss(wiphy, + channel, + CFG80211_BSS_FTYPE_UNKNOWN, + network_info->au8bssid, + network_info->u64Tsf, + network_info->cap_info, + network_info->u16BeaconPeriod, + (const u8 *)network_info->pu8IEs, + (size_t)network_info->u16IEsLen, + (s32)rssi * 100, + GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } } @@ -358,7 +366,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, } last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; - last_scanned_shadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo; + last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; memcpy(last_scanned_shadow[ap_index].au8ssid, pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen); @@ -414,9 +422,15 @@ static void CfgScanResult(enum scan_event scan_event, if (!channel) return; - PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d," - "BeaconPeriod: %d\n", channel->center_freq, (((s32)network_info->rssi) * 100), - network_info->u16CapInfo, network_info->u16BeaconPeriod); + PRINT_INFO(CFG80211_DBG, "Network Info::" + "CHANNEL Frequency: %d," + "RSSI: %d," + "Capability Info: %d," + "Beacon Period: %d\n", + channel->center_freq, + (s32)network_info->rssi * 100, + network_info->cap_info, + network_info->u16BeaconPeriod); if (network_info->bNewNetwork) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { @@ -426,9 +440,17 @@ static void CfgScanResult(enum scan_event scan_event, add_network_to_shadow(network_info, priv, join_params); if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { - bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->au8bssid, network_info->u64Tsf, network_info->u16CapInfo, - network_info->u16BeaconPeriod, (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, (((s32)network_info->rssi) * 100), GFP_KERNEL); + bss = cfg80211_inform_bss(wiphy, + channel, + CFG80211_BSS_FTYPE_UNKNOWN, + network_info->au8bssid, + network_info->u64Tsf, + network_info->cap_info, + network_info->u16BeaconPeriod, + (const u8 *)network_info->pu8IEs, + (size_t)network_info->u16IEsLen, + (s32)network_info->rssi * 100, + GFP_KERNEL); cfg80211_put_bss(wiphy, bss); } } -- cgit From 2a3ff58a8a519d58ea0d0c1d3802203345140e98 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:13 +0900 Subject: staging: wilc1000: renames au8ssid of connect_resp_info structure This patch renames au8ssid variable to ssid. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 3 ++- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 19 +++++++++++-------- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 6c40d36922f6..4dd7c8a9e993 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -322,7 +322,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); - get_ssid(msa, network_info->au8ssid, &network_info->u8SsidLen); + get_ssid(msa, network_info->ssid, &network_info->u8SsidLen); get_BSSID(msa, network_info->au8bssid); network_info->u8channel = get_current_channel_802_11n(msa, diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index ace50d86d7c6..781a65ff369f 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -79,7 +79,7 @@ typedef struct { struct network_info { s8 rssi; u16 cap_info; - u8 au8ssid[MAX_SSID_LEN]; + u8 ssid[MAX_SSID_LEN]; u8 u8SsidLen; u8 au8bssid[6]; u16 u16BeaconPeriod; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index d56a33c20ddd..c31f0b5b021a 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4279,7 +4279,8 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); - memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1); + memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, + ptstrNetworkInfo->u8SsidLen + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen; memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 76768f291f50..1caeff4e25c2 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -244,7 +244,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) channel = ieee80211_get_channel(wiphy, freq); rssi = get_rssi_avg(network_info); - if (memcmp("DIRECT-", network_info->au8ssid, 7) || + if (memcmp("DIRECT-", network_info->ssid, 7) || direct_scan) { bss = cfg80211_inform_bss(wiphy, channel, @@ -288,7 +288,8 @@ static void remove_network_from_shadow(unsigned long arg) for (i = 0; i < last_scanned_cnt; i++) { if (time_after(now, last_scanned_shadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) { - PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", last_scanned_shadow[i].au8ssid); + PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n", + last_scanned_shadow[i].ssid); kfree(last_scanned_shadow[i].pu8IEs); last_scanned_shadow[i].pu8IEs = NULL; @@ -368,8 +369,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; - memcpy(last_scanned_shadow[ap_index].au8ssid, - pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen); + memcpy(last_scanned_shadow[ap_index].ssid, + pstrNetworkInfo->ssid, pstrNetworkInfo->u8SsidLen); memcpy(last_scanned_shadow[ap_index].au8bssid, pstrNetworkInfo->au8bssid, ETH_ALEN); last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; @@ -434,12 +435,14 @@ static void CfgScanResult(enum scan_event scan_event, if (network_info->bNewNetwork) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { - PRINT_D(CFG80211_DBG, "Network %s found\n", network_info->au8ssid); + PRINT_D(CFG80211_DBG, + "Network %s found\n", + network_info->ssid); priv->u32RcvdChCount++; add_network_to_shadow(network_info, priv, join_params); - if (!(memcmp("DIRECT-", network_info->au8ssid, 7))) { + if (!(memcmp("DIRECT-", network_info->ssid, 7))) { bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, @@ -459,7 +462,7 @@ static void CfgScanResult(enum scan_event scan_event, for (i = 0; i < priv->u32RcvdChCount; i++) { if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) { - PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].au8ssid); + PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid); last_scanned_shadow[i].rssi = network_info->rssi; last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; @@ -736,7 +739,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, for (i = 0; i < last_scanned_cnt; i++) { if ((sme->ssid_len == last_scanned_shadow[i].u8SsidLen) && - memcmp(last_scanned_shadow[i].au8ssid, + memcmp(last_scanned_shadow[i].ssid, sme->ssid, sme->ssid_len) == 0) { PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid); -- cgit From a36e89e9bbda9e802dce432dffa2daceeca3cc74 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:14 +0900 Subject: staging: wilc1000: renames u8SsidLen of connect_resp_info structure This patch renames u8SsidLen variable to ssid_len. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 4dd7c8a9e993..273fad92e502 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -322,7 +322,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); - get_ssid(msa, network_info->ssid, &network_info->u8SsidLen); + get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->au8bssid); network_info->u8channel = get_current_channel_802_11n(msa, diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 781a65ff369f..39f3691918c8 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -80,7 +80,7 @@ struct network_info { s8 rssi; u16 cap_info; u8 ssid[MAX_SSID_LEN]; - u8 u8SsidLen; + u8 ssid_len; u8 au8bssid[6]; u16 u16BeaconPeriod; u8 u8DtimPeriod; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c31f0b5b021a..f9a8a447c716 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4280,8 +4280,8 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, - ptstrNetworkInfo->u8SsidLen + 1); - pNewJoinBssParam->ssid_len = ptstrNetworkInfo->u8SsidLen; + ptstrNetworkInfo->ssid_len + 1); + pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len; memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3); memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 1caeff4e25c2..b5a97fd9e8c1 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -368,9 +368,9 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; - last_scanned_shadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen; + last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len; memcpy(last_scanned_shadow[ap_index].ssid, - pstrNetworkInfo->ssid, pstrNetworkInfo->u8SsidLen); + pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len); memcpy(last_scanned_shadow[ap_index].au8bssid, pstrNetworkInfo->au8bssid, ETH_ALEN); last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; @@ -738,7 +738,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type); for (i = 0; i < last_scanned_cnt; i++) { - if ((sme->ssid_len == last_scanned_shadow[i].u8SsidLen) && + if ((sme->ssid_len == last_scanned_shadow[i].ssid_len) && memcmp(last_scanned_shadow[i].ssid, sme->ssid, sme->ssid_len) == 0) { -- cgit From 38d3bb787824355ea23010e38860888664626f02 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:15 +0900 Subject: staging: wilc1000: renames au8bssid of connect_resp_info structure This patch renames au8bssid variable to bssid. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 10 +++---- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 34 ++++++++++++----------- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 273fad92e502..4a825765f988 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -323,7 +323,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); get_ssid(msa, network_info->ssid, &network_info->ssid_len); - get_BSSID(msa, network_info->au8bssid); + get_BSSID(msa, network_info->bssid); network_info->u8channel = get_current_channel_802_11n(msa, rx_len + FCS_LEN); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 39f3691918c8..5404162c5960 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -81,7 +81,7 @@ struct network_info { u16 cap_info; u8 ssid[MAX_SSID_LEN]; u8 ssid_len; - u8 au8bssid[6]; + u8 bssid[6]; u16 u16BeaconPeriod; u8 u8DtimPeriod; u8 u8channel; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index f9a8a447c716..2534c9ac72b1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1365,9 +1365,9 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, for (i = 0; i < hif_drv->usr_scan_req.rcvd_ch_cnt; i++) { if ((hif_drv->usr_scan_req.net_info[i].au8bssid) && - (pstrNetworkInfo->au8bssid)) { + (pstrNetworkInfo->bssid)) { if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, - pstrNetworkInfo->au8bssid, 6) == 0) { + pstrNetworkInfo->bssid, 6) == 0) { if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { goto done; } else { @@ -1384,9 +1384,9 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi; if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid && - pstrNetworkInfo->au8bssid) { + pstrNetworkInfo->bssid) { memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid, - pstrNetworkInfo->au8bssid, 6); + pstrNetworkInfo->bssid, 6); hif_drv->usr_scan_req.rcvd_ch_cnt++; @@ -4278,7 +4278,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; - memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6); + memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, ptstrNetworkInfo->ssid_len + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index b5a97fd9e8c1..40287b5593b5 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -249,7 +249,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, - network_info->au8bssid, + network_info->bssid, network_info->u64Tsf, network_info->cap_info, network_info->u16BeaconPeriod, @@ -332,8 +332,8 @@ static int is_network_in_shadow(struct network_info *pstrNetworkInfo, state = -1; } else { for (i = 0; i < last_scanned_cnt; i++) { - if (memcmp(last_scanned_shadow[i].au8bssid, - pstrNetworkInfo->au8bssid, 6) == 0) { + if (memcmp(last_scanned_shadow[i].bssid, + pstrNetworkInfo->bssid, 6) == 0) { state = i; break; } @@ -371,8 +371,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len; memcpy(last_scanned_shadow[ap_index].ssid, pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len); - memcpy(last_scanned_shadow[ap_index].au8bssid, - pstrNetworkInfo->au8bssid, ETH_ALEN); + memcpy(last_scanned_shadow[ap_index].bssid, + pstrNetworkInfo->bssid, ETH_ALEN); last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; @@ -446,7 +446,7 @@ static void CfgScanResult(enum scan_event scan_event, bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, - network_info->au8bssid, + network_info->bssid, network_info->u64Tsf, network_info->cap_info, network_info->u16BeaconPeriod, @@ -461,7 +461,7 @@ static void CfgScanResult(enum scan_event scan_event, u32 i; for (i = 0; i < priv->u32RcvdChCount; i++) { - if (memcmp(last_scanned_shadow[i].au8bssid, network_info->au8bssid, 6) == 0) { + if (memcmp(last_scanned_shadow[i].bssid, network_info->bssid, 6) == 0) { PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid); last_scanned_shadow[i].rssi = network_info->rssi; @@ -560,8 +560,9 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, for (i = 0; i < last_scanned_cnt; i++) { - if (memcmp(last_scanned_shadow[i].au8bssid, - pstrConnectInfo->au8bssid, ETH_ALEN) == 0) { + if (memcmp(last_scanned_shadow[i].bssid, + pstrConnectInfo->au8bssid, + ETH_ALEN) == 0) { unsigned long now = jiffies; if (time_after(now, @@ -747,7 +748,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, PRINT_INFO(CFG80211_DBG, "BSSID is not passed from the user\n"); break; } else { - if (memcmp(last_scanned_shadow[i].au8bssid, + if (memcmp(last_scanned_shadow[i].bssid, sme->bssid, ETH_ALEN) == 0) { PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n"); @@ -762,10 +763,11 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, pstrNetworkInfo = &last_scanned_shadow[i]; - PRINT_INFO(CFG80211_DBG, "network BSSID to be associated: %x%x%x%x%x%x\n", - pstrNetworkInfo->au8bssid[0], pstrNetworkInfo->au8bssid[1], - pstrNetworkInfo->au8bssid[2], pstrNetworkInfo->au8bssid[3], - pstrNetworkInfo->au8bssid[4], pstrNetworkInfo->au8bssid[5]); + PRINT_INFO(CFG80211_DBG, "network BSSID to be associated:" + "%x%x%x%x%x%x\n", + pstrNetworkInfo->bssid[0], pstrNetworkInfo->bssid[1], + pstrNetworkInfo->bssid[2], pstrNetworkInfo->bssid[3], + pstrNetworkInfo->bssid[4], pstrNetworkInfo->bssid[5]); } else { s32Error = -ENOENT; if (last_scanned_cnt == 0) @@ -903,9 +905,9 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, if (!pstrWFIDrv->p2p_connect) wlan_channel = pstrNetworkInfo->u8channel; - wilc_wlan_set_bssid(dev, pstrNetworkInfo->au8bssid, STATION_MODE); + wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE); - s32Error = wilc_set_join_req(vif, pstrNetworkInfo->au8bssid, sme->ssid, + s32Error = wilc_set_join_req(vif, pstrNetworkInfo->bssid, sme->ssid, sme->ssid_len, sme->ie, sme->ie_len, CfgConnectResult, (void *)priv, u8security, tenuAuth_type, -- cgit From 4b313e915b0cf1f25e4857d8933bfc25d2ce8410 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:16 +0900 Subject: staging: wilc1000: renames u16BeaconPeriod of connect_resp_info structure This patch renames u16BeaconPeriod variable to beacon_period. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 4a825765f988..b4f7ec3c59a5 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -330,7 +330,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, index = MAC_HDR_LEN + TIME_STAMP_LEN; - network_info->u16BeaconPeriod = get_beacon_period(msa + index); + network_info->beacon_period = get_beacon_period(msa + index); index += BEACON_INTERVAL_LEN + CAP_INFO_LEN; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 5404162c5960..2fbffe83d354 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -82,7 +82,7 @@ struct network_info { u8 ssid[MAX_SSID_LEN]; u8 ssid_len; u8 bssid[6]; - u16 u16BeaconPeriod; + u16 beacon_period; u8 u8DtimPeriod; u8 u8channel; unsigned long u32TimeRcvdInScanCached; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2534c9ac72b1..0ba248b2c216 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4276,7 +4276,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); if (pNewJoinBssParam) { pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; - pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod; + pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 40287b5593b5..0938b2dd3d2f 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -252,7 +252,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) network_info->bssid, network_info->u64Tsf, network_info->cap_info, - network_info->u16BeaconPeriod, + network_info->beacon_period, (const u8 *)network_info->pu8IEs, (size_t)network_info->u16IEsLen, (s32)rssi * 100, @@ -373,7 +373,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, pstrNetworkInfo->ssid, pstrNetworkInfo->ssid_len); memcpy(last_scanned_shadow[ap_index].bssid, pstrNetworkInfo->bssid, ETH_ALEN); - last_scanned_shadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod; + last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; @@ -431,7 +431,7 @@ static void CfgScanResult(enum scan_event scan_event, channel->center_freq, (s32)network_info->rssi * 100, network_info->cap_info, - network_info->u16BeaconPeriod); + network_info->beacon_period); if (network_info->bNewNetwork) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { @@ -449,7 +449,7 @@ static void CfgScanResult(enum scan_event scan_event, network_info->bssid, network_info->u64Tsf, network_info->cap_info, - network_info->u16BeaconPeriod, + network_info->beacon_period, (const u8 *)network_info->pu8IEs, (size_t)network_info->u16IEsLen, (s32)network_info->rssi * 100, -- cgit From df340fdf014c1f57a1e297b10307cb2e437a2bcd Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:17 +0900 Subject: staging: wilc1000: renames u8DtimPeriod of connect_resp_info structure This patch renames u8DtimPeriod variable to dtim_period. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index b4f7ec3c59a5..ce3bc29f51fa 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -336,7 +336,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); if (tim_elm) - network_info->u8DtimPeriod = tim_elm[3]; + network_info->dtim_period = tim_elm[3]; ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 2fbffe83d354..bbc4b0e583fe 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -83,7 +83,7 @@ struct network_info { u8 ssid_len; u8 bssid[6]; u16 beacon_period; - u8 u8DtimPeriod; + u8 dtim_period; u8 u8channel; unsigned long u32TimeRcvdInScanCached; unsigned long u32TimeRcvdInScan; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 0ba248b2c216..df331971c4b1 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4275,7 +4275,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); if (pNewJoinBssParam) { - pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod; + pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 0938b2dd3d2f..233b03d191f6 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -374,7 +374,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, memcpy(last_scanned_shadow[ap_index].bssid, pstrNetworkInfo->bssid, ETH_ALEN); last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; - last_scanned_shadow[ap_index].u8DtimPeriod = pstrNetworkInfo->u8DtimPeriod; + last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; -- cgit From 405a8c786442a5e493bfa1c44a18cb4902500e2e Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:18 +0900 Subject: staging: wilc1000: renames u8channel of connect_resp_info structure This patch renames u8channel variable to ch. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index ce3bc29f51fa..6c748aaf8d8e 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -325,7 +325,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->bssid); - network_info->u8channel = get_current_channel_802_11n(msa, + network_info->ch = get_current_channel_802_11n(msa, rx_len + FCS_LEN); index = MAC_HDR_LEN + TIME_STAMP_LEN; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index bbc4b0e583fe..2f030a939e98 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -84,7 +84,7 @@ struct network_info { u8 bssid[6]; u16 beacon_period; u8 dtim_period; - u8 u8channel; + u8 ch; unsigned long u32TimeRcvdInScanCached; unsigned long u32TimeRcvdInScan; bool bNewNetwork; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 233b03d191f6..73323157d6cd 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -240,7 +240,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->u8channel, IEEE80211_BAND_2GHZ); + freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, freq); rssi = get_rssi_avg(network_info); @@ -375,7 +375,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, pstrNetworkInfo->bssid, ETH_ALEN); last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; - last_scanned_shadow[ap_index].u8channel = pstrNetworkInfo->u8channel; + last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch; last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; if (ap_found != -1) @@ -417,7 +417,7 @@ static void CfgScanResult(enum scan_event scan_event, return; if (network_info) { - s32Freq = ieee80211_channel_to_frequency((s32)network_info->u8channel, IEEE80211_BAND_2GHZ); + s32Freq = ieee80211_channel_to_frequency((s32)network_info->ch, IEEE80211_BAND_2GHZ); channel = ieee80211_get_channel(wiphy, s32Freq); if (!channel) @@ -895,15 +895,15 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, } - PRINT_INFO(CFG80211_DBG, "Required Channel = %d\n", pstrNetworkInfo->u8channel); + PRINT_INFO(CFG80211_DBG, "Required Ch = %d\n", pstrNetworkInfo->ch); PRINT_INFO(CFG80211_DBG, "Group encryption value = %s\n Cipher Group = %s\n WPA version = %s\n", pcgroup_encrypt_val, pccipher_group, pcwpa_version); - curr_channel = pstrNetworkInfo->u8channel; + curr_channel = pstrNetworkInfo->ch; if (!pstrWFIDrv->p2p_connect) - wlan_channel = pstrNetworkInfo->u8channel; + wlan_channel = pstrNetworkInfo->ch; wilc_wlan_set_bssid(dev, pstrNetworkInfo->bssid, STATION_MODE); @@ -911,7 +911,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, sme->ssid_len, sme->ie, sme->ie_len, CfgConnectResult, (void *)priv, u8security, tenuAuth_type, - pstrNetworkInfo->u8channel, + pstrNetworkInfo->ch, pstrNetworkInfo->pJoinParams); if (s32Error != 0) { netdev_err(dev, "wilc_set_join_req(): Error\n"); -- cgit From 264d70f4dece6a3b146194b96780c1eb6f268600 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:19 +0900 Subject: staging: wilc1000: renames struct connect_resp_info variables This patch renames to avoid camelcase changes follow are: - u32TimeRcvdInScanCached to time_scan_cached - u32TimeRcvdInScan to time_scan Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 2f030a939e98..0e10c7502eeb 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -85,8 +85,8 @@ struct network_info { u16 beacon_period; u8 dtim_period; u8 ch; - unsigned long u32TimeRcvdInScanCached; - unsigned long u32TimeRcvdInScan; + unsigned long time_scan_cached; + unsigned long time_scan; bool bNewNetwork; u8 u8Found; u32 u32Tsf; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 73323157d6cd..d7b4a2dab2bf 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -277,7 +277,7 @@ static void update_scan_time(void) int i; for (i = 0; i < last_scanned_cnt; i++) - last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; + last_scanned_shadow[i].time_scan = jiffies; } static void remove_network_from_shadow(unsigned long arg) @@ -287,7 +287,8 @@ static void remove_network_from_shadow(unsigned long arg) for (i = 0; i < last_scanned_cnt; i++) { - if (time_after(now, last_scanned_shadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) { + if (time_after(now, last_scanned_shadow[i].time_scan + + (unsigned long)(SCAN_RESULT_EXPIRE))) { PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n", last_scanned_shadow[i].ssid); @@ -384,8 +385,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL); memcpy(last_scanned_shadow[ap_index].pu8IEs, pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); - last_scanned_shadow[ap_index].u32TimeRcvdInScan = jiffies; - last_scanned_shadow[ap_index].u32TimeRcvdInScanCached = jiffies; + last_scanned_shadow[ap_index].time_scan = jiffies; + last_scanned_shadow[ap_index].time_scan_cached = jiffies; last_scanned_shadow[ap_index].u8Found = 1; if (ap_found != -1) kfree(last_scanned_shadow[ap_index].pJoinParams); @@ -465,7 +466,7 @@ static void CfgScanResult(enum scan_event scan_event, PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", last_scanned_shadow[i].ssid); last_scanned_shadow[i].rssi = network_info->rssi; - last_scanned_shadow[i].u32TimeRcvdInScan = jiffies; + last_scanned_shadow[i].time_scan = jiffies; break; } } @@ -566,9 +567,9 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, unsigned long now = jiffies; if (time_after(now, - last_scanned_shadow[i].u32TimeRcvdInScanCached + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) { + last_scanned_shadow[i].time_scan_cached + + (unsigned long)(nl80211_SCAN_RESULT_EXPIRE - (1 * HZ)))) bNeedScanRefresh = true; - } break; } -- cgit From d40207637a62dab0f0607e066aaea99eb6257afa Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:20 +0900 Subject: staging: wilc1000: renames bNewNetwork of connect_resp_info structure This patch renames bNewNetwork variable to new_network. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 0e10c7502eeb..fd3b5d400d93 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -87,7 +87,7 @@ struct network_info { u8 ch; unsigned long time_scan_cached; unsigned long time_scan; - bool bNewNetwork; + bool new_network; u8 u8Found; u32 u32Tsf; u8 *pu8IEs; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index df331971c4b1..c0171f987844 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1390,7 +1390,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, hif_drv->usr_scan_req.rcvd_ch_cnt++; - pstrNetworkInfo->bNewNetwork = true; + pstrNetworkInfo->new_network = true; pJoinParams = host_int_ParseJoinBssParam(pstrNetworkInfo); hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo, @@ -1399,7 +1399,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, } } } else { - pstrNetworkInfo->bNewNetwork = false; + pstrNetworkInfo->new_network = false; hif_drv->usr_scan_req.scan_result(SCAN_EVENT_NETWORK_FOUND, pstrNetworkInfo, hif_drv->usr_scan_req.arg, NULL); } diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d7b4a2dab2bf..5d29f761ad9b 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -434,7 +434,7 @@ static void CfgScanResult(enum scan_event scan_event, network_info->cap_info, network_info->beacon_period); - if (network_info->bNewNetwork) { + if (network_info->new_network) { if (priv->u32RcvdChCount < MAX_NUM_SCANNED_NETWORKS) { PRINT_D(CFG80211_DBG, "Network %s found\n", -- cgit From a35d6e2ded29f790ce03bf4296463a6ce12520a6 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:21 +0900 Subject: staging: wilc1000: renames u8Found of connect_resp_info structure This patch renames u8Found variable to found. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index fd3b5d400d93..27c35d7867d0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -88,7 +88,7 @@ struct network_info { unsigned long time_scan_cached; unsigned long time_scan; bool new_network; - u8 u8Found; + u8 found; u32 u32Tsf; u8 *pu8IEs; u16 u16IEsLen; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 5d29f761ad9b..c856f4f21bbc 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -235,7 +235,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) network_info = &last_scanned_shadow[i]; - if (!network_info->u8Found || all) { + if (!network_info->found || all) { s32 freq; struct ieee80211_channel *channel; @@ -269,7 +269,7 @@ static void reset_shadow_found(void) int i; for (i = 0; i < last_scanned_cnt; i++) - last_scanned_shadow[i].u8Found = 0; + last_scanned_shadow[i].found = 0; } static void update_scan_time(void) @@ -387,7 +387,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); last_scanned_shadow[ap_index].time_scan = jiffies; last_scanned_shadow[ap_index].time_scan_cached = jiffies; - last_scanned_shadow[ap_index].u8Found = 1; + last_scanned_shadow[ap_index].found = 1; if (ap_found != -1) kfree(last_scanned_shadow[ap_index].pJoinParams); last_scanned_shadow[ap_index].pJoinParams = pJoinParams; -- cgit From afb706539b1d61f9d4fa82fa4cd759ad2b9b848a Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:22 +0900 Subject: staging: wilc1000: renames u32Tsf of connect_resp_info structure This patch renames u32Tsf variable to tsf_lo. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/host_interface.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 6c748aaf8d8e..3e1e1f52a5b0 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -315,7 +315,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, rx_len = wid_len - 1; network_info->cap_info = get_cap_info(msa); - network_info->u32Tsf = get_beacon_timestamp_lo(msa); + network_info->tsf_lo = get_beacon_timestamp_lo(msa); tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 27c35d7867d0..07a2ef0543e8 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -89,7 +89,7 @@ struct network_info { unsigned long time_scan; bool new_network; u8 found; - u32 u32Tsf; + u32 tsf_lo; u8 *pu8IEs; u16 u16IEsLen; void *pJoinParams; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c0171f987844..fa6ee92de054 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -4330,7 +4330,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) (pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) { u16 u16P2P_count; - pNewJoinBssParam->tsf = ptstrNetworkInfo->u32Tsf; + pNewJoinBssParam->tsf = ptstrNetworkInfo->tsf_lo; pNewJoinBssParam->noa_enabled = 1; pNewJoinBssParam->idx = pu8IEs[index + 9]; -- cgit From 390b6db00d8c9333fad997f2f31367df6d34b4ff Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:23 +0900 Subject: staging: wilc1000: renames struct connect_resp_info variables This patch renames to avoid camelcase changes follow are: - pu8IEs to ies - u16IEsLen to ies_len Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 7 +++--- drivers/staging/wilc1000/coreconfigurator.h | 4 +-- drivers/staging/wilc1000/host_interface.c | 6 ++--- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 30 +++++++++++------------ 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index 3e1e1f52a5b0..cbca6a0f7bc6 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -341,12 +341,11 @@ s32 wilc_parse_network_info(u8 *msg_buffer, ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (ies_len > 0) { - network_info->pu8IEs = kmemdup(ies, ies_len, - GFP_KERNEL); - if (!network_info->pu8IEs) + network_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!network_info->ies) return -ENOMEM; } - network_info->u16IEsLen = ies_len; + network_info->ies_len = ies_len; } *ret_network_info = network_info; diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 07a2ef0543e8..3dca84018a72 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -90,8 +90,8 @@ struct network_info { bool new_network; u8 found; u32 tsf_lo; - u8 *pu8IEs; - u16 u16IEsLen; + u8 *ies; + u16 ies_len; void *pJoinParams; tstrRSSI strRssi; u64 u64Tsf; diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index fa6ee92de054..781063dc9868 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1410,7 +1410,7 @@ done: pstrRcvdNetworkInfo->buffer = NULL; if (pstrNetworkInfo) { - kfree(pstrNetworkInfo->pu8IEs); + kfree(pstrNetworkInfo->ies); kfree(pstrNetworkInfo); } @@ -4270,8 +4270,8 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) u8 authTotalCount = 0; u8 i, j; - pu8IEs = ptstrNetworkInfo->pu8IEs; - u16IEsLen = ptstrNetworkInfo->u16IEsLen; + pu8IEs = ptstrNetworkInfo->ies; + u16IEsLen = ptstrNetworkInfo->ies_len; pNewJoinBssParam = kzalloc(sizeof(struct join_bss_param), GFP_KERNEL); if (pNewJoinBssParam) { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index c856f4f21bbc..d150f4692a37 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -194,9 +194,9 @@ static void clear_shadow_scan(void) del_timer_sync(&hAgingTimer); for (i = 0; i < last_scanned_cnt; i++) { - if (last_scanned_shadow[last_scanned_cnt].pu8IEs) { - kfree(last_scanned_shadow[i].pu8IEs); - last_scanned_shadow[last_scanned_cnt].pu8IEs = NULL; + if (last_scanned_shadow[last_scanned_cnt].ies) { + kfree(last_scanned_shadow[i].ies); + last_scanned_shadow[last_scanned_cnt].ies = NULL; } kfree(last_scanned_shadow[i].pJoinParams); @@ -253,8 +253,8 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) network_info->u64Tsf, network_info->cap_info, network_info->beacon_period, - (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, + (const u8 *)network_info->ies, + (size_t)network_info->ies_len, (s32)rssi * 100, GFP_KERNEL); cfg80211_put_bss(wiphy, bss); @@ -292,8 +292,8 @@ static void remove_network_from_shadow(unsigned long arg) PRINT_D(CFG80211_DBG, "Network expired ScanShadow:%s\n", last_scanned_shadow[i].ssid); - kfree(last_scanned_shadow[i].pu8IEs); - last_scanned_shadow[i].pu8IEs = NULL; + kfree(last_scanned_shadow[i].ies); + last_scanned_shadow[i].ies = NULL; kfree(last_scanned_shadow[i].pJoinParams); @@ -377,14 +377,14 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].beacon_period = pstrNetworkInfo->beacon_period; last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch; - last_scanned_shadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen; + last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len; last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; if (ap_found != -1) - kfree(last_scanned_shadow[ap_index].pu8IEs); - last_scanned_shadow[ap_index].pu8IEs = - kmalloc(pstrNetworkInfo->u16IEsLen, GFP_KERNEL); - memcpy(last_scanned_shadow[ap_index].pu8IEs, - pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen); + kfree(last_scanned_shadow[ap_index].ies); + last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len, + GFP_KERNEL); + memcpy(last_scanned_shadow[ap_index].ies, + pstrNetworkInfo->ies, pstrNetworkInfo->ies_len); last_scanned_shadow[ap_index].time_scan = jiffies; last_scanned_shadow[ap_index].time_scan_cached = jiffies; last_scanned_shadow[ap_index].found = 1; @@ -451,8 +451,8 @@ static void CfgScanResult(enum scan_event scan_event, network_info->u64Tsf, network_info->cap_info, network_info->beacon_period, - (const u8 *)network_info->pu8IEs, - (size_t)network_info->u16IEsLen, + (const u8 *)network_info->ies, + (size_t)network_info->ies_len, (s32)network_info->rssi * 100, GFP_KERNEL); cfg80211_put_bss(wiphy, bss); -- cgit From cb64de7c362103847fa30ac720edcab8b92650b1 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:24 +0900 Subject: staging: wilc1000: renames pJoinParams of connect_resp_info structure This patch renames pJoinParams variable to join_params. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 3dca84018a72..f154e39c47a2 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -92,7 +92,7 @@ struct network_info { u32 tsf_lo; u8 *ies; u16 ies_len; - void *pJoinParams; + void *join_params; tstrRSSI strRssi; u64 u64Tsf; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index d150f4692a37..15f334af026c 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -199,8 +199,8 @@ static void clear_shadow_scan(void) last_scanned_shadow[last_scanned_cnt].ies = NULL; } - kfree(last_scanned_shadow[i].pJoinParams); - last_scanned_shadow[i].pJoinParams = NULL; + kfree(last_scanned_shadow[i].join_params); + last_scanned_shadow[i].join_params = NULL; } last_scanned_cnt = 0; } @@ -295,7 +295,7 @@ static void remove_network_from_shadow(unsigned long arg) kfree(last_scanned_shadow[i].ies); last_scanned_shadow[i].ies = NULL; - kfree(last_scanned_shadow[i].pJoinParams); + kfree(last_scanned_shadow[i].join_params); for (j = i; (j < last_scanned_cnt - 1); j++) last_scanned_shadow[j] = last_scanned_shadow[j + 1]; @@ -389,8 +389,8 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].time_scan_cached = jiffies; last_scanned_shadow[ap_index].found = 1; if (ap_found != -1) - kfree(last_scanned_shadow[ap_index].pJoinParams); - last_scanned_shadow[ap_index].pJoinParams = pJoinParams; + kfree(last_scanned_shadow[ap_index].join_params); + last_scanned_shadow[ap_index].join_params = pJoinParams; } static void CfgScanResult(enum scan_event scan_event, @@ -913,7 +913,7 @@ static int connect(struct wiphy *wiphy, struct net_device *dev, CfgConnectResult, (void *)priv, u8security, tenuAuth_type, pstrNetworkInfo->ch, - pstrNetworkInfo->pJoinParams); + pstrNetworkInfo->join_params); if (s32Error != 0) { netdev_err(dev, "wilc_set_join_req(): Error\n"); s32Error = -ENOENT; -- cgit From f2050a189680a6b26c38d96958917721cc2f82a4 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:25 +0900 Subject: staging: wilc1000: renames strRssi of connect_resp_info structure This patch renames strRssi variable to str_rssi. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index f154e39c47a2..18c785b0769b 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -93,7 +93,7 @@ struct network_info { u8 *ies; u16 ies_len; void *join_params; - tstrRSSI strRssi; + tstrRSSI str_rssi; u64 u64Tsf; }; diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 15f334af026c..30b163402e05 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -210,10 +210,11 @@ static u32 get_rssi_avg(struct network_info *network_info) { u8 i; int rssi_v = 0; - u8 num_rssi = (network_info->strRssi.u8Full) ? NUM_RSSI : (network_info->strRssi.u8Index); + u8 num_rssi = (network_info->str_rssi.u8Full) ? + NUM_RSSI : (network_info->str_rssi.u8Index); for (i = 0; i < num_rssi; i++) - rssi_v += network_info->strRssi.as8RSSI[i]; + rssi_v += network_info->str_rssi.as8RSSI[i]; rssi_v /= num_rssi; return rssi_v; @@ -360,13 +361,13 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, } else { ap_index = ap_found; } - rssi_index = last_scanned_shadow[ap_index].strRssi.u8Index; - last_scanned_shadow[ap_index].strRssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi; + rssi_index = last_scanned_shadow[ap_index].str_rssi.u8Index; + last_scanned_shadow[ap_index].str_rssi.as8RSSI[rssi_index++] = pstrNetworkInfo->rssi; if (rssi_index == NUM_RSSI) { rssi_index = 0; - last_scanned_shadow[ap_index].strRssi.u8Full = 1; + last_scanned_shadow[ap_index].str_rssi.u8Full = 1; } - last_scanned_shadow[ap_index].strRssi.u8Index = rssi_index; + last_scanned_shadow[ap_index].str_rssi.u8Index = rssi_index; last_scanned_shadow[ap_index].rssi = pstrNetworkInfo->rssi; last_scanned_shadow[ap_index].cap_info = pstrNetworkInfo->cap_info; last_scanned_shadow[ap_index].ssid_len = pstrNetworkInfo->ssid_len; -- cgit From 17d2f2b36f0b7cb309124ef714cb97e792c9a94b Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:26 +0900 Subject: staging: wilc1000: renames u64Tsf of connect_resp_info structure This patch renames u64Tsf variable to tsf_hi. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 2 +- drivers/staging/wilc1000/coreconfigurator.h | 2 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index cbca6a0f7bc6..d481719a97db 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -320,7 +320,7 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tsf_lo = get_beacon_timestamp_lo(msa); tsf_hi = get_beacon_timestamp_hi(msa); - network_info->u64Tsf = tsf_lo | ((u64)tsf_hi << 32); + network_info->tsf_hi = tsf_lo | ((u64)tsf_hi << 32); get_ssid(msa, network_info->ssid, &network_info->ssid_len); get_BSSID(msa, network_info->bssid); diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h index 18c785b0769b..748199d4439a 100644 --- a/drivers/staging/wilc1000/coreconfigurator.h +++ b/drivers/staging/wilc1000/coreconfigurator.h @@ -94,7 +94,7 @@ struct network_info { u16 ies_len; void *join_params; tstrRSSI str_rssi; - u64 u64Tsf; + u64 tsf_hi; }; struct connect_resp_info { diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 30b163402e05..35c39c66af4d 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -251,7 +251,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->bssid, - network_info->u64Tsf, + network_info->tsf_hi, network_info->cap_info, network_info->beacon_period, (const u8 *)network_info->ies, @@ -379,7 +379,7 @@ static void add_network_to_shadow(struct network_info *pstrNetworkInfo, last_scanned_shadow[ap_index].dtim_period = pstrNetworkInfo->dtim_period; last_scanned_shadow[ap_index].ch = pstrNetworkInfo->ch; last_scanned_shadow[ap_index].ies_len = pstrNetworkInfo->ies_len; - last_scanned_shadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf; + last_scanned_shadow[ap_index].tsf_hi = pstrNetworkInfo->tsf_hi; if (ap_found != -1) kfree(last_scanned_shadow[ap_index].ies); last_scanned_shadow[ap_index].ies = kmalloc(pstrNetworkInfo->ies_len, @@ -449,7 +449,7 @@ static void CfgScanResult(enum scan_event scan_event, channel, CFG80211_BSS_FTYPE_UNKNOWN, network_info->bssid, - network_info->u64Tsf, + network_info->tsf_hi, network_info->cap_info, network_info->beacon_period, (const u8 *)network_info->ies, -- cgit From 5b3b744a4cb2613dc792c74421a0846c7223fb39 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:27 +0900 Subject: staging: wilc1000: remove unnecessary wilc_rx_complete function This patch remove unnecessary wilc_rx_complete function because this function only print unused log message. remove unused has_packet variable nomore. Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 5 ----- drivers/staging/wilc1000/wilc_wfi_netdevice.h | 1 - drivers/staging/wilc1000/wilc_wlan.c | 7 +------ 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index 202be15b615f..e702020b8e9d 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -372,11 +372,6 @@ static int linux_wlan_txq_task(void *vp) return 0; } -void wilc_rx_complete(struct wilc *nic) -{ - PRINT_D(RX_DBG, "RX completed\n"); -} - int wilc_wlan_get_firmware(struct net_device *dev) { struct wilc_vif *vif; diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h index 07a4ff10bb65..3077f5d416c7 100644 --- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h +++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h @@ -228,7 +228,6 @@ int wilc1000_wlan_init(struct net_device *dev, struct wilc_vif *vif); void wilc_frmw_to_linux(struct wilc *wilc, u8 *buff, u32 size, u32 pkt_offset); void wilc_mac_indicate(struct wilc *wilc, int flag); -void wilc_rx_complete(struct wilc *wilc); void wilc_dbg(u8 *buff); int wilc_lock_timeout(struct wilc *wilc, void *, u32 timeout); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index dd0c051fedca..98527f6f0394 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -811,7 +811,7 @@ _end_: static void wilc_wlan_handle_rxq(struct wilc *wilc) { - int offset = 0, size, has_packet = 0; + int offset = 0, size; u8 *buffer; struct rxq_entry_t *rqe; @@ -866,7 +866,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) &buffer[offset], pkt_len, pkt_offset); - has_packet = 1; } } else { struct wilc_cfg_rsp rsp; @@ -888,10 +887,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) break; } while (1); kfree(rqe); - - if (has_packet) - wilc_rx_complete(wilc); - } while (1); wilc->rxq_exit = 1; -- cgit From eef2679b090ef149e93919aa0dde3432485e8d7e Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:28 +0900 Subject: staging: wilc1000: remove unused log message using the RX_DBG tag This patch remove unused log message using the RX_DBG tag Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan_common.h | 2 -- drivers/staging/wilc1000/wilc_debugfs.c | 2 +- drivers/staging/wilc1000/wilc_wlan.c | 5 ----- drivers/staging/wilc1000/wilc_wlan_cfg.c | 5 ----- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 617bc5325cd2..63d0ec523129 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -6,7 +6,6 @@ enum debug_region { Hostapd_debug, CFG80211_debug, Interrupt_debug, - RX_debug, Lock_debug, Tcp_enhance, Spin_debug, @@ -22,7 +21,6 @@ enum debug_region { #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INT_DBG (1 << Interrupt_debug) -#define RX_DBG (1 << RX_debug) #define LOCK_DBG (1 << Lock_debug) #define TCP_ENH (1 << Tcp_enhance) #define SPIN_DEBUG (1 << Spin_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index a3d274bd0820..9c85bdd502f7 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,7 +24,7 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | RX_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 98527f6f0394..46e66475dbc8 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -835,11 +835,8 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) u32 pkt_len, pkt_offset, tp_len; int is_cfg_packet; - PRINT_D(RX_DBG, "In the 2nd do-while\n"); memcpy(&header, &buffer[offset], 4); header = cpu_to_le32(header); - PRINT_D(RX_DBG, "Header = %04x - Offset = %d\n", - header, offset); is_cfg_packet = (header >> 31) & 0x1; pkt_offset = (header >> 22) & 0x1ff; @@ -890,7 +887,6 @@ static void wilc_wlan_handle_rxq(struct wilc *wilc) } while (1); wilc->rxq_exit = 1; - PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n"); } static void wilc_unknown_isr_ext(struct wilc *wilc) @@ -958,7 +954,6 @@ _end_: if (rqe) { rqe->buffer = buffer; rqe->buffer_size = size; - PRINT_D(RX_DBG, "rxq entery Size= %d - Address = %p\n", rqe->buffer_size, rqe->buffer); wilc_wlan_rxq_add(wilc, rqe); } } diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index b72c77bb35f1..3b3065b4d734 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -522,7 +522,6 @@ int wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, rsp->type = wilc_wlan_parse_info_frame(frame, size); rsp->seq_no = msg_id; /*call host interface info parse as well*/ - PRINT_INFO(RX_DBG, "Info message received\n"); wilc_gnrl_async_info_received(wilc, frame - 4, size + 4); break; @@ -532,14 +531,10 @@ int wilc_wlan_cfg_indicate_rx(struct wilc *wilc, u8 *frame, int size, break; case 'S': - PRINT_INFO(RX_DBG, "Scan Notification Received\n"); wilc_scan_complete_received(wilc, frame - 4, size + 4); break; default: - PRINT_INFO(RX_DBG, "Receive unknown message type[%d-%d-%d-%d-%d-%d-%d-%d]\n", - frame[0], frame[1], frame[2], frame[3], frame[4], - frame[5], frame[6], frame[7]); rsp->type = 0; rsp->seq_no = msg_id; ret = 0; -- cgit From c9f75c3071a469a0a4cac0c5d32c47873bca9bf5 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:29 +0900 Subject: staging: wilc1000: remove unused debug tag This patch remove unused debug tag INT_DBG, LOCK_DBG, BUS_DBG, MEM_DBG and FIRM_DBG Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan_common.h | 15 --------------- drivers/staging/wilc1000/wilc_debugfs.c | 5 +++-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 63d0ec523129..758633e73488 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -5,29 +5,14 @@ enum debug_region { Generic_debug = 0, Hostapd_debug, CFG80211_debug, - Interrupt_debug, - Lock_debug, - Tcp_enhance, - Spin_debug, - Init_debug, - Bus_debug, - Mem_debug, - Firmware_debug, COMP = 0xFFFFFFFF, }; #define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) -#define INT_DBG (1 << Interrupt_debug) -#define LOCK_DBG (1 << Lock_debug) -#define TCP_ENH (1 << Tcp_enhance) -#define SPIN_DEBUG (1 << Spin_debug) #define INIT_DBG (1 << Init_debug) -#define BUS_DBG (1 << Bus_debug) -#define MEM_DBG (1 << Mem_debug) -#define FIRM_DBG (1 << Firmware_debug) #if defined (WILC_DEBUGFS) extern atomic_t WILC_REGION; diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 9c85bdd502f7..8d088249ea44 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,9 +24,10 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INT_DBG | LOCK_DBG | INIT_DBG | BUS_DBG | MEM_DBG) +#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INIT_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) -atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | FIRM_DBG | HOSTAPD_DBG); +atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | + HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); EXPORT_SYMBOL_GPL(WILC_DEBUG_LEVEL); -- cgit From e3f16965c9d47318f598163ac2d9788b80114219 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 4 Feb 2016 18:24:30 +0900 Subject: staging: wilc1000: remove unnecessary log message using GENERIC_DBG tag This patch remove unnecessary log message using GENERIC_DBG tag. Needed log messages has changed netdev_dbg from PRINT_D. And removes variables that were used to log message. Signed-off-by: Chris Park Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 42 +------------ drivers/staging/wilc1000/linux_wlan.c | 2 - drivers/staging/wilc1000/linux_wlan_common.h | 4 +- drivers/staging/wilc1000/wilc_debugfs.c | 6 +- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 76 +++-------------------- drivers/staging/wilc1000/wilc_wlan.c | 2 - drivers/staging/wilc1000/wilc_wlan_cfg.c | 11 +--- 7 files changed, 18 insertions(+), 125 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 781063dc9868..abb20fb22963 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -445,7 +445,6 @@ static s32 handle_set_mac_address(struct wilc_vif *vif, wid.type = WID_STR; wid.val = mac_buf; wid.size = ETH_ALEN; - PRINT_D(GENERIC_DBG, "mac addr = :%pM\n", wid.val); result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); @@ -800,15 +799,12 @@ static s32 Handle_Scan(struct wilc_vif *vif, if ((hif_drv->hif_state >= HOST_IF_SCANNING) && (hif_drv->hif_state < HOST_IF_CONNECTED)) { - PRINT_D(GENERIC_DBG, "Don't scan already in [%d] state\n", - hif_drv->hif_state); PRINT_ER("Already scan\n"); result = -EBUSY; goto ERRORHANDLER; } if (wilc_optaining_ip || wilc_connecting) { - PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n"); PRINT_ER("Don't do obss scan\n"); result = -EBUSY; goto ERRORHANDLER; @@ -915,7 +911,6 @@ static s32 Handle_ScanDone(struct wilc_vif *vif, struct host_if_drv *hif_drv = vif->hif_drv; if (enuEvent == SCAN_EVENT_ABORTED) { - PRINT_D(GENERIC_DBG, "Abort running scan\n"); u8abort_running_scan = 1; wid.id = (u16)WID_ABORT_RUNNING_SCAN; wid.type = WID_CHAR; @@ -956,8 +951,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, struct join_bss_param *ptstrJoinBssParam; struct host_if_drv *hif_drv = vif->hif_drv; - PRINT_D(GENERIC_DBG, "Handling connect request\n"); - if (memcmp(pstrHostIFconnectAttr->bssid, wilc_connected_ssid, ETH_ALEN) == 0) { result = 0; PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n"); @@ -1149,13 +1142,9 @@ static s32 Handle_Connect(struct wilc_vif *vif, join_req_vif = vif; } - if (pstrHostIFconnectAttr->bssid) { + if (pstrHostIFconnectAttr->bssid) memcpy(wilc_connected_ssid, pstrHostIFconnectAttr->bssid, ETH_ALEN); - PRINT_D(GENERIC_DBG, "save Bssid = %pM\n", - pstrHostIFconnectAttr->bssid); - PRINT_D(GENERIC_DBG, "save bssid = %pM\n", wilc_connected_ssid); - } result = wilc_send_config_pkt(vif, SET_CFG, strWIDList, u32WidsCount, @@ -1165,7 +1154,6 @@ static s32 Handle_Connect(struct wilc_vif *vif, result = -EFAULT; goto ERRORHANDLER; } else { - PRINT_D(GENERIC_DBG, "set HOST_IF_WAITING_CONN_RESP\n"); hif_drv->hif_state = HOST_IF_WAITING_CONN_RESP; } @@ -1443,8 +1431,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, PRINT_ER("Driver handler is NULL\n"); return -ENODEV; } - PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n", - hif_drv->hif_state, pstrRcvdGnrlAsyncInfo->buffer[7]); if ((hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) || (hif_drv->hif_state == HOST_IF_CONNECTED) || @@ -1548,7 +1534,6 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, hif_drv->hif_state = HOST_IF_CONNECTED; - PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n"); wilc_optaining_ip = true; mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(10000)); @@ -2421,19 +2406,16 @@ static int Handle_RemainOnChan(struct wilc_vif *vif, } if (hif_drv->usr_scan_req.scan_result) { - PRINT_INFO(GENERIC_DBG, "Required to remain on chan while scanning return\n"); hif_drv->remain_on_ch_pending = 1; result = -EBUSY; goto ERRORHANDLER; } if (hif_drv->hif_state == HOST_IF_WAITING_CONN_RESP) { - PRINT_INFO(GENERIC_DBG, "Required to remain on chan while connecting return\n"); result = -EBUSY; goto ERRORHANDLER; } if (wilc_optaining_ip || wilc_connecting) { - PRINT_D(GENERIC_DBG, "[handle_scan]: Don't do obss scan until IP adresss is obtained\n"); result = -EBUSY; goto ERRORHANDLER; } @@ -2541,7 +2523,7 @@ static u32 Handle_ListenStateExpired(struct wilc_vif *vif, } P2P_LISTEN_STATE = 0; } else { - PRINT_D(GENERIC_DBG, "Not in listen state\n"); + netdev_dbg(vif->ndev, "Not in listen state\n"); result = -EFAULT; } @@ -2635,12 +2617,6 @@ static s32 Handle_DelAllRxBASessions(struct wilc_vif *vif, struct wid wid; char *ptr = NULL; - PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n", - strHostIfBASessionInfo->bssid[0], - strHostIfBASessionInfo->bssid[1], - strHostIfBASessionInfo->bssid[2], - strHostIfBASessionInfo->tid); - wid.id = (u16)WID_DEL_ALL_RX_BA; wid.type = WID_STR; wid.val = kmalloc(BLOCK_ACK_REQ_SIZE, GFP_KERNEL); @@ -2711,13 +2687,10 @@ static int hostIFthread(void *pvArg) while (1) { wilc_mq_recv(&hif_msg_q, &msg, sizeof(struct host_if_msg), &u32Ret); vif = msg.vif; - if (msg.id == HOST_IF_MSG_EXIT) { - PRINT_D(GENERIC_DBG, "THREAD: Exiting HostIfThread\n"); + if (msg.id == HOST_IF_MSG_EXIT) break; - } if ((!wilc_initialized)) { - PRINT_D(GENERIC_DBG, "--WAIT--"); usleep_range(200 * 1000, 200 * 1000); wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); continue; @@ -3318,9 +3291,6 @@ int wilc_set_join_req(struct wilc_vif *vif, u8 *bssid, const u8 *ssid, } if (hif_drv->hif_state < HOST_IF_CONNECTING) hif_drv->hif_state = HOST_IF_CONNECTING; - else - PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' : %d\n", - hif_drv->hif_state); result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); if (result) { @@ -3870,8 +3840,6 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, return; hif_drv = vif->hif_drv; - PRINT_D(GENERIC_DBG, "Scan notification received %p\n", hif_drv); - if (!hif_drv || hif_drv == terminated_handle) return; @@ -4341,10 +4309,6 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->opp_enabled = 0; } - PRINT_D(GENERIC_DBG, "P2P Dump\n"); - for (i = 0; i < pu8IEs[index + 7]; i++) - PRINT_D(GENERIC_DBG, " %x\n", pu8IEs[index + 9 + i]); - pNewJoinBssParam->cnt = pu8IEs[index + 11]; u16P2P_count = index + 12; diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index e702020b8e9d..c11830f71f38 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -253,8 +253,6 @@ void wilc_mac_indicate(struct wilc *wilc, int flag) } else { wilc->mac_status = status; } - } else if (flag == WILC_MAC_INDICATE_SCAN) { - PRINT_D(GENERIC_DBG, "Scanning ...\n"); } } diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 758633e73488..44573e2ea0ee 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -2,14 +2,12 @@ #define LINUX_WLAN_COMMON_H enum debug_region { - Generic_debug = 0, - Hostapd_debug, + Hostapd_debug = 0, CFG80211_debug, Init_debug, COMP = 0xFFFFFFFF, }; -#define GENERIC_DBG (1 << Generic_debug) #define HOSTAPD_DBG (1 << Hostapd_debug) #define CFG80211_DBG (1 << CFG80211_debug) #define INIT_DBG (1 << Init_debug) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 8d088249ea44..c5c8cc905630 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -24,9 +24,9 @@ static struct dentry *wilc_dir; * -------------------------------------------------------------------------------- */ -#define DBG_REGION_ALL (GENERIC_DBG | HOSTAPD_DBG | CFG80211_DBG | INIT_DBG) +#define DBG_REGION_ALL (HOSTAPD_DBG | CFG80211_DBG | INIT_DBG) #define DBG_LEVEL_ALL (DEBUG | INFO | WRN | ERR) -atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | GENERIC_DBG | CFG80211_DBG | +atomic_t WILC_REGION = ATOMIC_INIT(INIT_DBG | CFG80211_DBG | HOSTAPD_DBG); EXPORT_SYMBOL_GPL(WILC_REGION); atomic_t WILC_DEBUG_LEVEL = ATOMIC_INIT(ERR); @@ -136,7 +136,7 @@ struct wilc_debugfs_info_t { static struct wilc_debugfs_info_t debugfs_info[] = { { "wilc_debug_level", 0666, (DEBUG | ERR), FOPS(NULL, wilc_debug_level_read, wilc_debug_level_write, NULL), }, - { "wilc_debug_region", 0666, (INIT_DBG | GENERIC_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), }, + { "wilc_debug_region", 0666, (INIT_DBG | CFG80211_DBG), FOPS(NULL, wilc_debug_region_read, wilc_debug_region_write, NULL), }, }; static int __init wilc_debugfs_init(void) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 35c39c66af4d..bf264d3657be 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -317,7 +317,6 @@ static void remove_network_from_shadow(unsigned long arg) static void clear_duringIP(unsigned long arg) { - PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n"); wilc_optaining_ip = false; } @@ -1567,7 +1566,6 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) } if (wlan_channel != INVALID_CHANNEL) { if (channel_list_attr_index) { - PRINT_D(GENERIC_DBG, "Modify channel list attribute\n"); 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++) { @@ -1579,7 +1577,6 @@ static void WILC_WFI_CfgParseRxAction(u8 *buf, u32 len) } if (op_channel_attr_index) { - PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n"); buf[op_channel_attr_index + 6] = 0x51; buf[op_channel_attr_index + 7] = wlan_channel; } @@ -1609,7 +1606,6 @@ static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftyp } if (wlan_channel != INVALID_CHANNEL && bOperChan) { if (channel_list_attr_index) { - PRINT_D(GENERIC_DBG, "Modify channel list attribute\n"); 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++) { @@ -1621,7 +1617,6 @@ static void WILC_WFI_CfgParseTxAction(u8 *buf, u32 len, bool bOperChan, u8 iftyp } if (op_channel_attr_index) { - PRINT_D(GENERIC_DBG, "Modify operating channel attribute\n"); buf[op_channel_attr_index + 6] = 0x51; buf[op_channel_attr_index + 7] = wlan_channel; } @@ -1645,41 +1640,29 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) if (pkt_offset & IS_MANAGMEMENT_CALLBACK) { if (buff[FRAME_TYPE_ID] == IEEE80211_STYPE_PROBE_RESP) { - PRINT_D(GENERIC_DBG, "Probe response ACK\n"); cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); return; } else { - if (pkt_offset & IS_MGMT_STATUS_SUCCES) { - PRINT_D(GENERIC_DBG, "Success Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID], - buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]); + if (pkt_offset & IS_MGMT_STATUS_SUCCES) cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, true, GFP_KERNEL); - } else { - PRINT_D(GENERIC_DBG, "Fail Ack - Action frame category: %x Action Subtype: %d Dialog T: %x OR %x\n", buff[ACTION_CAT_ID], buff[ACTION_SUBTYPE_ID], - buff[ACTION_SUBTYPE_ID + 1], buff[P2P_PUB_ACTION_SUBTYPE + 1]); + else cfg80211_mgmt_tx_status(priv->wdev, priv->u64tx_cookie, buff, size, false, GFP_KERNEL); - } return; } } else { - PRINT_D(GENERIC_DBG, "Rx Frame Type:%x\n", buff[FRAME_TYPE_ID]); - s32Freq = ieee80211_channel_to_frequency(curr_channel, IEEE80211_BAND_2GHZ); if (ieee80211_is_action(buff[FRAME_TYPE_ID])) { - PRINT_D(GENERIC_DBG, "Rx Action Frame Type: %x %x\n", buff[ACTION_SUBTYPE_ID], buff[P2P_PUB_ACTION_SUBTYPE]); - if (priv->bCfgScanning && time_after_eq(jiffies, (unsigned long)pstrWFIDrv->p2p_timeout)) { - PRINT_D(GENERIC_DBG, "Receiving action frames from wrong channels\n"); + netdev_dbg(dev, "Receiving action wrong ch\n"); return; } if (buff[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { switch (buff[ACTION_SUBTYPE_ID]) { case GAS_INTIAL_REQ: - PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buff[ACTION_SUBTYPE_ID]); break; case GAS_INTIAL_RSP: - PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buff[ACTION_SUBTYPE_ID]); break; case PUBLIC_ACT_VENDORSPEC: @@ -1690,7 +1673,6 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) if (!memcmp(p2p_vendor_spec, &buff[i], 6)) { p2p_recv_random = buff[i + 6]; wilc_ie = true; - PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", p2p_recv_random); break; } } @@ -1707,20 +1689,19 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) } } } else { - PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); + netdev_dbg(dev, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); } } if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP) && (wilc_ie)) { - PRINT_D(GENERIC_DBG, "Sending P2P to host without extra elemnt\n"); cfg80211_rx_mgmt(priv->wdev, s32Freq, 0, buff, size - 7, 0); return; } break; default: - PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]); + netdev_dbg(dev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buff[ACTION_SUBTYPE_ID]); break; } } @@ -1761,17 +1742,12 @@ static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID) priv = (struct wilc_priv *)pUserVoid; if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) { - PRINT_D(GENERIC_DBG, "Remain on channel expired\n"); - priv->bInP2PlistenState = false; cfg80211_remain_on_channel_expired(priv->wdev, priv->strRemainOnChanParams.u64ListenCookie, priv->strRemainOnChanParams.pstrListenChan, GFP_KERNEL); - } else { - PRINT_D(GENERIC_DBG, "Received ID 0x%x Expected ID 0x%x (No match)\n", u32SessionID - , priv->strRemainOnChanParams.u32ListenSessionID); } } @@ -1787,11 +1763,8 @@ static int remain_on_channel(struct wiphy *wiphy, priv = wiphy_priv(wiphy); vif = netdev_priv(priv->dev); - PRINT_D(GENERIC_DBG, "Remaining on channel %d\n", chan->hw_value); - - if (wdev->iftype == NL80211_IFTYPE_AP) { - PRINT_D(GENERIC_DBG, "Required remain-on-channel while in AP mode"); + netdev_dbg(vif->ndev, "Required while in AP mode\n"); return s32Error; } @@ -1868,34 +1841,22 @@ static int mgmt_tx(struct wiphy *wiphy, if (ieee80211_is_probe_resp(mgmt->frame_control)) { - PRINT_D(GENERIC_DBG, "TX: Probe Response\n"); - PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value); wilc_set_mac_chnl_num(vif, chan->hw_value); curr_channel = chan->hw_value; } else if (ieee80211_is_action(mgmt->frame_control)) { - PRINT_D(GENERIC_DBG, "ACTION FRAME:%x\n", (u16)mgmt->frame_control); - - if (buf[ACTION_CAT_ID] == PUB_ACTION_ATTR_ID) { if (buf[ACTION_SUBTYPE_ID] != PUBLIC_ACT_VENDORSPEC || buf[P2P_PUB_ACTION_SUBTYPE] != GO_NEG_CONF) { - PRINT_D(GENERIC_DBG, "Setting channel: %d\n", chan->hw_value); wilc_set_mac_chnl_num(vif, chan->hw_value); curr_channel = chan->hw_value; } switch (buf[ACTION_SUBTYPE_ID]) { case GAS_INTIAL_REQ: - { - PRINT_D(GENERIC_DBG, "GAS INITIAL REQ %x\n", buf[ACTION_SUBTYPE_ID]); break; - } case GAS_INTIAL_RSP: - { - PRINT_D(GENERIC_DBG, "GAS INITIAL RSP %x\n", buf[ACTION_SUBTYPE_ID]); break; - } case PUBLIC_ACT_VENDORSPEC: { @@ -1910,8 +1871,6 @@ static int mgmt_tx(struct wiphy *wiphy, if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) { if (p2p_local_random > p2p_recv_random) { - PRINT_D(GENERIC_DBG, "LOCAL WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); - for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) { if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(p2p_oui, &buf[i + 2], 4))) { if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP) @@ -1927,13 +1886,11 @@ static int mgmt_tx(struct wiphy *wiphy, mgmt_tx->buff[len + sizeof(p2p_vendor_spec)] = p2p_local_random; mgmt_tx->size = buf_len; } - } else { - PRINT_D(GENERIC_DBG, "PEER WILL BE GO LocaRand=%02x RecvRand %02x\n", p2p_local_random, p2p_recv_random); } } } else { - PRINT_D(GENERIC_DBG, "Not a P2P public action frame\n"); + netdev_dbg(vif->ndev, "Not a P2P public action frame\n"); } break; @@ -1941,24 +1898,18 @@ static int mgmt_tx(struct wiphy *wiphy, default: { - PRINT_D(GENERIC_DBG, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]); + netdev_dbg(vif->ndev, "NOT HANDLED PUBLIC ACTION FRAME TYPE:%x\n", buf[ACTION_SUBTYPE_ID]); break; } } } - PRINT_D(GENERIC_DBG, "TX: ACTION FRAME Type:%x : Chan:%d\n", buf[ACTION_SUBTYPE_ID], chan->hw_value); pstrWFIDrv->p2p_timeout = (jiffies + msecs_to_jiffies(wait)); - - PRINT_D(GENERIC_DBG, "Current Jiffies: %lu Timeout:%llu\n", - jiffies, pstrWFIDrv->p2p_timeout); } wilc_wlan_txq_add_mgmt_pkt(wdev->netdev, mgmt_tx, mgmt_tx->buff, mgmt_tx->size, WILC_WFI_mgmt_tx_complete); - } else { - PRINT_D(GENERIC_DBG, "This function transmits only management frames\n"); } return 0; } @@ -1972,9 +1923,6 @@ static int mgmt_tx_cancel_wait(struct wiphy *wiphy, priv = wiphy_priv(wiphy); pstrWFIDrv = (struct host_if_drv *)priv->hif_drv; - - - PRINT_D(GENERIC_DBG, "Tx Cancel wait :%lu\n", jiffies); pstrWFIDrv->p2p_timeout = jiffies; if (!priv->bInP2PlistenState) { @@ -2001,7 +1949,6 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, if (!frame_type) return; - PRINT_D(GENERIC_DBG, "Frame registering Frame Type: %x: Boolean: %d\n", frame_type, reg); switch (frame_type) { case PROBE_REQ: { @@ -2023,10 +1970,8 @@ void wilc_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, } } - if (!wl->initialized) { - PRINT_D(GENERIC_DBG, "Return since mac is closed\n"); + if (!wl->initialized) return; - } wilc_frame_register(vif, frame_type, reg); } @@ -2099,7 +2044,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, wilc_ie = false; wilc_optaining_ip = false; del_timer(&wilc_during_ip_timer); - PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n"); switch (type) { case NL80211_IFTYPE_STATION: @@ -2148,8 +2092,6 @@ static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, break; case NL80211_IFTYPE_P2P_GO: - PRINT_D(GENERIC_DBG, "start duringIP timer\n"); - wilc_optaining_ip = true; mod_timer(&wilc_during_ip_timer, jiffies + msecs_to_jiffies(during_ip_time)); diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 46e66475dbc8..98b21d492720 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -713,8 +713,6 @@ int wilc_wlan_handle_txq(struct net_device *dev, u32 *txq_count) break; if (entries == 0) { - PRINT_WRN(GENERIC_DBG, "[wilc txq]: no more buffer in the chip (reg: %08x), retry later [[ %d, %x ]]\n", reg, i, vmm_table[i - 1]); - ret = wilc->hif_func->hif_read_reg(wilc, WILC_HOST_TX_CTRL, ®); if (!ret) break; diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c index 3b3065b4d734..2bb684a3e23b 100644 --- a/drivers/staging/wilc1000/wilc_wlan_cfg.c +++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c @@ -270,13 +270,12 @@ static int wilc_wlan_cfg_set_bin(u8 *frame, u32 offset, u16 id, u8 *b, u32 size) static void wilc_wlan_parse_response_frame(u8 *info, int size) { u32 wid, len = 0, i = 0; - static int seq; while (size > 0) { i = 0; wid = info[0] | (info[1] << 8); wid = cpu_to_le32(wid); - PRINT_INFO(GENERIC_DBG, "Processing response for %d seq %d\n", wid, seq++); + switch ((wid >> 12) & 0x7) { case WID_CHAR: do { @@ -329,10 +328,6 @@ static void wilc_wlan_parse_response_frame(u8 *info, int size) if (wid == WID_SITE_SURVEY_RESULTS) { static int toggle; - PRINT_INFO(GENERIC_DBG, "Site survey results received[%d]\n", - size); - - PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]toggle[%d]\n", size, toggle); i += toggle; toggle ^= 1; } @@ -361,7 +356,7 @@ static int wilc_wlan_parse_info_frame(u8 *info, int size) wid = info[0] | (info[1] << 8); len = info[2]; - PRINT_INFO(GENERIC_DBG, "Status Len = %d Id= %d\n", len, wid); + if ((len == 1) && (wid == WID_STATUS)) { pd->mac_status = info[3]; type = WILC_CFG_RSP_STATUS; @@ -475,8 +470,6 @@ int wilc_wlan_cfg_get_wid_value(u16 wid, u8 *buffer, u32 buffer_size) if (g_cfg_str[i].id == WID_SITE_SURVEY_RESULTS) { static int toggle; - PRINT_INFO(GENERIC_DBG, "Site survey results value[%d]\n", - size); i += toggle; toggle ^= 1; -- cgit From e0990c159f658db3fb6e32b76c449d33e718ed24 Mon Sep 17 00:00:00 2001 From: Leo Kim Date: Thu, 4 Feb 2016 18:24:31 +0900 Subject: staging: wilc1000: remove warnings line over 80 characters This patch removes the warnings reported by checkpatch.pl for line over 80 characters. Signed-off-by: Leo Kim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/coreconfigurator.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c index d481719a97db..3a7658617014 100644 --- a/drivers/staging/wilc1000/coreconfigurator.c +++ b/drivers/staging/wilc1000/coreconfigurator.c @@ -4,7 +4,7 @@ #include #include #define TAG_PARAM_OFFSET (MAC_HDR_LEN + TIME_STAMP_LEN + \ - BEACON_INTERVAL_LEN + CAP_INFO_LEN) + BEACON_INTERVAL_LEN + CAP_INFO_LEN) enum basic_frame_type { FRAME_TYPE_CONTROL = 0x04, @@ -337,8 +337,10 @@ s32 wilc_parse_network_info(u8 *msg_buffer, tim_elm = get_tim_elm(msa, rx_len + FCS_LEN, index); if (tim_elm) network_info->dtim_period = tim_elm[3]; - ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN]; - ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + CAP_INFO_LEN); + ies = &msa[MAC_HDR_LEN + TIME_STAMP_LEN + BEACON_INTERVAL_LEN + + CAP_INFO_LEN]; + ies_len = rx_len - (MAC_HDR_LEN + TIME_STAMP_LEN + + BEACON_INTERVAL_LEN + CAP_INFO_LEN); if (ies_len > 0) { network_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); @@ -373,7 +375,8 @@ s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len, connect_resp_info->assoc_id = get_asoc_id(buffer); ies = &buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN]; - ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN); + ies_len = assoc_resp_len - (CAP_INFO_LEN + STATUS_CODE_LEN + + AID_LEN); connect_resp_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); if (!connect_resp_info->ies) -- cgit From 4168da71875c8aca823a78fa33f5481efa7dc36e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:11 +0900 Subject: staging: wilc1000: fix return type of wilc_hif_set_cfg This patch changes return type of wilc_hif_set_cfg from s32 to int. The result variable gets return value from wilc_mq_send that has data type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index abb20fb22963..e20621d29ea6 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3558,10 +3558,10 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, return result; } -s32 wilc_hif_set_cfg(struct wilc_vif *vif, +int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index c73a5c389297..395b68169363 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -337,7 +337,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, u8 *ch_freq_list, u8 ch_list_len, const u8 *ies, size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *hidden_network); -s32 wilc_hif_set_cfg(struct wilc_vif *vif, +int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *pstrCfgParamVal); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); -- cgit From 483ab2aa00c0570084abec6147d5165fcffd1ac4 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:12 +0900 Subject: staging: wilc1000: rename pstrCfgParamVal in wilc_hif_set_cfg This patch renames pstrCfgParamVal to cfg_param to avoid camelcase. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e20621d29ea6..2c64659b1aa7 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3559,7 +3559,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, } int wilc_hif_set_cfg(struct wilc_vif *vif, - struct cfg_param_val *pstrCfgParamVal) + struct cfg_param_val *cfg_param) { int result = 0; struct host_if_msg msg; @@ -3572,7 +3572,7 @@ int wilc_hif_set_cfg(struct wilc_vif *vif, memset(&msg, 0, sizeof(struct host_if_msg)); msg.id = HOST_IF_MSG_CFG_PARAMS; - msg.body.cfg_info.cfg_attr_info = *pstrCfgParamVal; + msg.body.cfg_info.cfg_attr_info = *cfg_param; msg.vif = vif; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 395b68169363..f08f115fb3dd 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -338,7 +338,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, size_t ies_len, wilc_scan_result scan_result, void *user_arg, struct hidden_network *hidden_network); int wilc_hif_set_cfg(struct wilc_vif *vif, - struct cfg_param_val *pstrCfgParamVal); + struct cfg_param_val *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); s32 wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, -- cgit From 127a27c3fbe01b8b35e658b0b6f655be43290f95 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:13 +0900 Subject: staging: wilc1000: fix return type of wilc_deinit This patch changes return type of wilc_deinit from s32 to int. The result variable gets return value from wilc_mq_send that has return type of int. It should be changed return type of this function as well as data type of result variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 2c64659b1aa7..ef7c90ff3af9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3687,9 +3687,9 @@ _fail_: return result; } -s32 wilc_deinit(struct wilc_vif *vif) +int wilc_deinit(struct wilc_vif *vif) { - s32 result = 0; + int result = 0; struct host_if_msg msg; struct host_if_drv *hif_drv = vif->hif_drv; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index f08f115fb3dd..bfa4a41264f1 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -340,7 +340,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, int wilc_hif_set_cfg(struct wilc_vif *vif, struct cfg_param_val *cfg_param); int wilc_init(struct net_device *dev, struct host_if_drv **hif_drv_handler); -s32 wilc_deinit(struct wilc_vif *vif); +int wilc_deinit(struct wilc_vif *vif); int wilc_add_beacon(struct wilc_vif *vif, u32 interval, u32 dtim_period, u32 head_len, u8 *head, u32 tail_len, u8 *tail); int wilc_del_beacon(struct wilc_vif *vif); -- cgit From 8eb62f3f6d8e58ec1b0eedee73ddd371a80a1bd3 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 5 Feb 2016 10:35:14 +0900 Subject: staging: wilc1000: fix return error code of wilc_deinit It should be returned error code as -EFAULT instead of 0 when hif_drv is NULL. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ef7c90ff3af9..c42286a7bab9 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3695,7 +3695,7 @@ int wilc_deinit(struct wilc_vif *vif) if (!hif_drv) { PRINT_ER("hif_drv = NULL\n"); - return 0; + return -EFAULT; } down(&hif_sema_deinit); -- cgit From 6bb871b61e48fbfca36989a15da4fd599395c598 Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 7 Dec 2015 10:58:37 -0500 Subject: staging: unisys: fix parenthesis in toolaction_show() Fix the only fixable parenthesis alignment issue in visorchipset.c. The rest are unworkable because of the length of the symbol names used. Signed-off-by: Benjamin Romer 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 07594f43853d..b29832657c7b 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -537,8 +537,8 @@ static ssize_t toolaction_show(struct device *dev, u8 tool_action; visorchannel_read(controlvm_channel, - offsetof(struct spar_controlvm_channel_protocol, - tool_action), &tool_action, sizeof(u8)); + offsetof(struct spar_controlvm_channel_protocol, + tool_action), &tool_action, sizeof(u8)); return scnprintf(buf, PAGE_SIZE, "%u\n", tool_action); } -- cgit From 61dd330a284b7164eda3549ea3ec1bb53598a21e Mon Sep 17 00:00:00 2001 From: David Kershner Date: Fri, 15 Jan 2016 11:19:05 -0500 Subject: staging: unisys: Only process up to budget amount of responses >From napi documentation you should only process the amount your budget allows, if you go over it just wait for the next napi poll to continue. Signed-off-by: David Kershner Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 05194707278a..2d51299825cf 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -36,6 +36,7 @@ * = 163840 bytes */ #define MAX_BUF 163840 +#define NAPI_WEIGHT 64 static int visornic_probe(struct visor_device *dev); static void visornic_remove(struct visor_device *dev); @@ -1613,14 +1614,12 @@ drain_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata) */ static void service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, - int *rx_work_done) + int *rx_work_done, int budget) { unsigned long flags; struct net_device *netdev; - /* TODO: CLIENT ACQUIRE -- Don't really need this at the - * moment */ - for (;;) { + while (*rx_work_done < budget) { if (!visorchannel_signalremove(devdata->dev->visorchannel, IOCHAN_FROM_IOPART, cmdrsp)) @@ -1709,7 +1708,7 @@ static int visornic_poll(struct napi_struct *napi, int budget) int rx_count = 0; send_rcv_posts_if_needed(devdata); - service_resp_queue(devdata->cmdrsp, devdata, &rx_count); + service_resp_queue(devdata->cmdrsp, devdata, &rx_count, budget); /* * If there aren't any more packets to receive @@ -1893,6 +1892,16 @@ static int visornic_probe(struct visor_device *dev) goto cleanup_napi_add; } + /* Let's start our threads to get responses */ + netif_napi_add(netdev, &devdata->napi, visornic_poll, NAPI_WEIGHT); + + /* + * Note: Interupts have to be enable before the while + * loop below because the napi routine is responsible for + * setting enab_dis_acked + */ + visorbus_enable_channel_interrupts(dev); + err = register_netdev(netdev); if (err) { dev_err(&dev->device, -- cgit From 2c7e1d4e4b1dd8f843f2acce1ba879bef9b78f22 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Wed, 9 Dec 2015 20:57:05 +0530 Subject: staging: unisys: visorchipset.c fixed spacing around operator This patch fixes checkpatch.pl warning for visorchipset.c CHECK: spaces preferred around that '*' (ctx:VxV) +#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) Signed-off-by: Bhaktipriya Shridhar 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 b29832657c7b..95a923e2b201 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -43,7 +43,7 @@ #define POLLJIFFIES_CONTROLVMCHANNEL_FAST 1 #define POLLJIFFIES_CONTROLVMCHANNEL_SLOW 100 -#define MAX_CONTROLVM_PAYLOAD_BYTES (1024*128) +#define MAX_CONTROLVM_PAYLOAD_BYTES (1024 * 128) #define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 -- cgit From 58e1e5425f0dea78dcd9ae56c0330fa4ada6c792 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 8 Dec 2015 13:07:01 -0800 Subject: Staging: unisys: fix potential format string leak Since "name" is always used directly, force "%s" for the kthread format string to avoid any potential format string leaks. Signed-off-by: Kees Cook Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorhba/visorhba_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index d5178b44ba8c..202bfabfec6c 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -167,7 +167,7 @@ static int visor_thread_start(struct visor_thread_info *thrinfo, { /* used to stop the thread */ init_completion(&thrinfo->has_stopped); - thrinfo->task = kthread_run(threadfn, thrcontext, name); + thrinfo->task = kthread_run(threadfn, thrcontext, "%s", name); if (IS_ERR(thrinfo->task)) { thrinfo->id = 0; return PTR_ERR(thrinfo->task); -- cgit From 3025ee74cc56f76b04b264777888cdccb673104c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 7 Jan 2016 12:34:13 +0300 Subject: staging: unisys: remove some dead code queue_delayed_work() returns bool, not negative error codes. It returns false if the work has already been queued or true otherwise. Since we don't care about that, we can just remove the test. Signed-off-by: Dan Carpenter Signed-off-by: Benjamin Romer Acked-by: Don Zickus Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 95a923e2b201..f4c37dab9999 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -2310,13 +2310,8 @@ visorchipset_init(struct acpi_device *acpi_device) } most_recent_message_jiffies = jiffies; poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; - rc = queue_delayed_work(periodic_controlvm_workqueue, - &periodic_controlvm_work, poll_jiffies); - if (rc < 0) { - POSTCODE_LINUX_2(QUEUE_DELAYED_WORK_PC, - DIAG_SEVERITY_ERR); - goto cleanup; - } + queue_delayed_work(periodic_controlvm_workqueue, + &periodic_controlvm_work, poll_jiffies); visorchipset_platform_device.dev.devt = major_dev; if (platform_device_register(&visorchipset_platform_device) < 0) { -- cgit From 9305b0fe0985eb2d277df29f3a962828b00dd7cc Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Mon, 25 Jan 2016 20:22:16 +0000 Subject: staging: unisys: visornic: remove useless memset alloc_etherdev() calls alloc_netdev_mqs(), which already uses kzalloc/vzalloc. This clears a sparse warning : drivers/staging/unisys/visornic/visornic_main.c:1366:15: warning: memset with byte count of 1460112 Signed-off-by: Hugo Camboulive Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 2d51299825cf..9b3eb95ed183 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1364,7 +1364,6 @@ devdata_initialize(struct visornic_devdata *devdata, struct visor_device *dev) { if (!devdata) return NULL; - memset(devdata, '\0', sizeof(struct visornic_devdata)); devdata->dev = dev; devdata->incarnation_id = get_jiffies_64(); return devdata; -- cgit From a191176441cdb4e34e3b84d76bf3ee6f3756954e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:42 +0100 Subject: staging: most: remove unnecessary keep_mbo variable The MBO pointer stacked_mbo and the boolean variable keep_mbo are always changed together and therefore provide the same information. This patch removes keep_mbo and uses stacked_mbo instead. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index dc3fb25b52aa..6f70ed715064 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -39,7 +39,6 @@ struct aim_channel { struct most_channel_config *cfg; unsigned int channel_id; dev_t devno; - bool keep_mbo; unsigned int mbo_offs; struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); @@ -136,7 +135,7 @@ static int aim_close(struct inode *inode, struct file *filp) while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) most_put_mbo(mbo); - if (channel->keep_mbo) + if (channel->stacked_mbo) most_put_mbo(channel->stacked_mbo); ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); atomic_dec(&channel->access_ref); @@ -227,9 +226,8 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct mbo *mbo; struct aim_channel *channel = filp->private_data; - if (channel->keep_mbo) { + if (channel->stacked_mbo) { mbo = channel->stacked_mbo; - channel->keep_mbo = false; goto start_copy; } while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) { @@ -249,9 +247,6 @@ start_copy: return -EIO; } - if (count < mbo->processed_length) - channel->keep_mbo = true; - proc_len = min((int)count, (int)(mbo->processed_length - channel->mbo_offs)); @@ -261,12 +256,13 @@ start_copy: retval = not_copied ? proc_len - not_copied : proc_len; - if (channel->keep_mbo) { + if (count < mbo->processed_length) { channel->mbo_offs = retval; channel->stacked_mbo = mbo; } else { most_put_mbo(mbo); channel->mbo_offs = 0; + channel->stacked_mbo = NULL; } mutex_unlock(&channel->io_mutex); return retval; -- cgit From f9f24870d84d4c77cbb330df1e1112fd97a9e12c Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:43 +0100 Subject: staging: most: rename variables This patch renames some variables for better readability. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 6f70ed715064..bff891fc0a5d 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -221,8 +221,8 @@ error: static ssize_t aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { - ssize_t retval; - size_t not_copied, proc_len; + ssize_t copied; + size_t to_copy, not_copied; struct mbo *mbo; struct aim_channel *channel = filp->private_data; @@ -247,17 +247,17 @@ start_copy: return -EIO; } - proc_len = min((int)count, - (int)(mbo->processed_length - channel->mbo_offs)); + to_copy = min((int)count, + (int)(mbo->processed_length - channel->mbo_offs)); not_copied = copy_to_user(buf, mbo->virt_address + channel->mbo_offs, - proc_len); + to_copy); - retval = not_copied ? proc_len - not_copied : proc_len; + copied = not_copied ? to_copy - not_copied : to_copy; if (count < mbo->processed_length) { - channel->mbo_offs = retval; + channel->mbo_offs = copied; channel->stacked_mbo = mbo; } else { most_put_mbo(mbo); @@ -265,7 +265,7 @@ start_copy: channel->stacked_mbo = NULL; } mutex_unlock(&channel->io_mutex); - return retval; + return copied; } static inline bool __must_check IS_ERR_OR_FALSE(int x) -- cgit From 4aa575a91e637ab1c5e89c91bb59e91e518cb5f6 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:44 +0100 Subject: staging: most: simplify expression This patch replaces the ternary ?-operator with a way simpler subtraction. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index bff891fc0a5d..b29307820eda 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -254,7 +254,7 @@ start_copy: mbo->virt_address + channel->mbo_offs, to_copy); - copied = not_copied ? to_copy - not_copied : to_copy; + copied = to_copy - not_copied; if (count < mbo->processed_length) { channel->mbo_offs = copied; -- cgit From 06e7ecf287e7d2414c381d5312d6c81e79a7520d Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:45 +0100 Subject: staging: most: unify types This patch unifies variable types to get less castings. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index b29307820eda..4bf0322a99eb 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -39,7 +39,7 @@ struct aim_channel { struct most_channel_config *cfg; unsigned int channel_id; dev_t devno; - unsigned int mbo_offs; + size_t mbo_offs; struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); atomic_t access_ref; @@ -221,8 +221,7 @@ error: static ssize_t aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { - ssize_t copied; - size_t to_copy, not_copied; + size_t to_copy, not_copied, copied; struct mbo *mbo; struct aim_channel *channel = filp->private_data; @@ -247,8 +246,7 @@ start_copy: return -EIO; } - to_copy = min((int)count, - (int)(mbo->processed_length - channel->mbo_offs)); + to_copy = min(count, (size_t)mbo->processed_length - channel->mbo_offs); not_copied = copy_to_user(buf, mbo->virt_address + channel->mbo_offs, -- cgit From e6d6cbe303c5cfa581842ce4ba4899ba313931ab Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:46 +0100 Subject: staging: most: use min_t This patch replaces min with min_t. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 4bf0322a99eb..6ee4eb2177bd 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -246,7 +246,9 @@ start_copy: return -EIO; } - to_copy = min(count, (size_t)mbo->processed_length - channel->mbo_offs); + to_copy = min_t(size_t, + count, + mbo->processed_length - channel->mbo_offs); not_copied = copy_to_user(buf, mbo->virt_address + channel->mbo_offs, -- cgit From 8a742f785bbda4a60288325e42953515c2320b50 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:47 +0100 Subject: staging: most: fix mbo leak This patch fixes a potential MBO leak in case function aim_read() exits right after the MBO has been fetched from kfifo and before it has been saved to the variable stacked_mbo. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 6ee4eb2177bd..86194ce51472 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -237,6 +237,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) (!channel->dev)))) return -ERESTARTSYS; } + channel->stacked_mbo = mbo; start_copy: /* make sure we don't submit to gone devices */ @@ -258,7 +259,6 @@ start_copy: if (count < mbo->processed_length) { channel->mbo_offs = copied; - channel->stacked_mbo = mbo; } else { most_put_mbo(mbo); channel->mbo_offs = 0; -- cgit From 9e2f2c4fb93a12e20f6bd82e1b9bf3df36236198 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:48 +0100 Subject: staging: most: fix tracking of MBO offset This patch increments mbo_offs by the number of bytes that have been copied and resets it in case a complete mbo has been transferred to user buffer. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 86194ce51472..0141293b4bf5 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -257,9 +257,8 @@ start_copy: copied = to_copy - not_copied; - if (count < mbo->processed_length) { - channel->mbo_offs = copied; - } else { + channel->mbo_offs += copied; + if (channel->mbo_offs >= mbo->processed_length) { most_put_mbo(mbo); channel->mbo_offs = 0; channel->stacked_mbo = NULL; -- cgit From 560dca25cd038ae932c8f2d42bf991968faf258a Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:49 +0100 Subject: staging: most: use readl and writel functions This patch makes use of functions readl and writel instead of the __raw_* variants. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_hdm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 327d738c7194..48ce7ab1bb03 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -140,7 +140,7 @@ bool dim2_sysfs_get_state_cb(void) */ u32 dimcb_io_read(u32 *ptr32) { - return __raw_readl(ptr32); + return readl(ptr32); } /** @@ -150,7 +150,7 @@ u32 dimcb_io_read(u32 *ptr32) */ void dimcb_io_write(u32 *ptr32, u32 value) { - __raw_writel(value, ptr32); + writel(value, ptr32); } /** -- cgit From 9ce039a08add9c4212539d303134b579064a2be5 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:50 +0100 Subject: staging: most: remove function destroy_most_c_obj This patch removes the function destroy_most_c_obj and executes its code within function destroy_most_inst_obj. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 38 +++++++++++++----------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index ed1ed25b6d1d..8be6cdcf4008 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -551,29 +551,6 @@ create_most_c_obj(const char *name, struct kobject *parent) return c; } -/** - * destroy_most_c_obj - channel release function - * @c: pointer to channel object - * - * This decrements the reference counter of the channel object. - * If the reference count turns zero, its release function is called. - */ -static void destroy_most_c_obj(struct most_c_obj *c) -{ - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; - - mutex_lock(&deregister_mutex); - flush_trash_fifo(c); - flush_channel_fifos(c); - mutex_unlock(&deregister_mutex); - kobject_put(&c->kobj); -} - /* ___ ___ * ___I N S T A N C E___ */ @@ -766,7 +743,20 @@ static void destroy_most_inst_obj(struct most_inst_obj *inst) * reference count of the inst->kobj */ list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - destroy_most_c_obj(c); + if (c->aim0.ptr) + c->aim0.ptr->disconnect_channel(c->iface, + c->channel_id); + if (c->aim1.ptr) + c->aim1.ptr->disconnect_channel(c->iface, + c->channel_id); + c->aim0.ptr = NULL; + c->aim1.ptr = NULL; + + mutex_lock(&deregister_mutex); + flush_trash_fifo(c); + flush_channel_fifos(c); + mutex_unlock(&deregister_mutex); + kobject_put(&c->kobj); } kobject_put(&inst->kobj); } -- cgit From b7382d44a530cd8c1bc156ddc123e3f09ae68746 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:51 +0100 Subject: staging: most: add missing call to ida_simple_remove This patch adds two missing calls to function ida_simpel_remove. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 8be6cdcf4008..995987d352a8 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1752,6 +1752,7 @@ struct kobject *most_register_interface(struct most_interface *iface) inst = create_most_inst_obj(name); if (!inst) { pr_info("Failed to allocate interface instance\n"); + ida_simple_remove(&mdev_id, id); return ERR_PTR(-ENOMEM); } @@ -1808,6 +1809,7 @@ struct kobject *most_register_interface(struct most_interface *iface) free_instance: pr_info("Failed allocate channel(s)\n"); list_del(&inst->list); + ida_simple_remove(&mdev_id, id); destroy_most_inst_obj(inst); return ERR_PTR(-ENOMEM); } -- cgit From 44fe57818b8038ece1d6089c5075a5c73ad7e18a Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:52 +0100 Subject: staging: most: move call to disconnect_channel callback This patch invokes AIM's disconnect_channel callback before the corresponding pointers are re-initialized to NULL. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 995987d352a8..d5ef61df1f9b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1046,12 +1046,12 @@ static ssize_t store_remove_link(struct most_aim_obj *aim_obj, if (IS_ERR(c)) return -ENODEV; + if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) + return -EIO; if (c->aim0.ptr == aim_obj->driver) c->aim0.ptr = NULL; if (c->aim1.ptr == aim_obj->driver) c->aim1.ptr = NULL; - if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id)) - return -EIO; return len; } -- cgit From 42e252a65d3bbd36106b3e243cb1e11136cecdf4 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:53 +0100 Subject: staging: most: move initialization of pointer This patch makes function store_add_link initialize the pointer to an AIM right before the channel is probed. It is needed, the AIM may already call most_start_channel while probe_channel is still running. At this point the pointer to the AIM must not be NULL. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index d5ef61df1f9b..21c550ccfe78 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -996,11 +996,14 @@ static ssize_t store_add_link(struct most_aim_obj *aim_obj, else return -ENOSPC; + *aim_ptr = aim_obj->driver; ret = aim_obj->driver->probe_channel(c->iface, c->channel_id, &c->cfg, &c->kobj, mdev_devnod); - if (ret) + if (ret) { + *aim_ptr = NULL; return ret; - *aim_ptr = aim_obj->driver; + } + return len; } -- cgit From 245dc23d2368beada77d9bc26f3292fa34931655 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:54 +0100 Subject: staging: most: move mutex This patch removes mutex from code that doesn't need any locking. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 21c550ccfe78..ae1b5778b24b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1830,15 +1830,14 @@ void most_deregister_interface(struct most_interface *iface) struct most_inst_obj *i = iface->priv; struct most_c_obj *c; - mutex_lock(&deregister_mutex); if (unlikely(!i)) { pr_info("Bad Interface\n"); - mutex_unlock(&deregister_mutex); return; } pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, iface->description); + mutex_lock(&deregister_mutex); atomic_set(&i->tainted, 1); mutex_unlock(&deregister_mutex); -- cgit From a0fceb1fb853585dcc7419944eb0ca385bdc497e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:55 +0100 Subject: staging: most: move channel disconnect to function most_deregister_interface This patch moves the code that disconnects linked channels. It is needed to have cleaning things up done right. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index ae1b5778b24b..782747a50477 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -738,20 +738,7 @@ static void destroy_most_inst_obj(struct most_inst_obj *inst) { struct most_c_obj *c, *tmp; - /* need to destroy channels first, since - * each channel incremented the - * reference count of the inst->kobj - */ list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - if (c->aim0.ptr) - c->aim0.ptr->disconnect_channel(c->iface, - c->channel_id); - if (c->aim1.ptr) - c->aim1.ptr->disconnect_channel(c->iface, - c->channel_id); - c->aim0.ptr = NULL; - c->aim1.ptr = NULL; - mutex_lock(&deregister_mutex); flush_trash_fifo(c); flush_channel_fifos(c); @@ -1837,6 +1824,17 @@ void most_deregister_interface(struct most_interface *iface) pr_info("deregistering MOST device %s (%s)\n", i->kobj.name, iface->description); + list_for_each_entry(c, &i->channel_list, list) { + if (c->aim0.ptr) + c->aim0.ptr->disconnect_channel(c->iface, + c->channel_id); + if (c->aim1.ptr) + c->aim1.ptr->disconnect_channel(c->iface, + c->channel_id); + c->aim0.ptr = NULL; + c->aim1.ptr = NULL; + } + mutex_lock(&deregister_mutex); atomic_set(&i->tainted, 1); mutex_unlock(&deregister_mutex); -- cgit From 6ed90e3622d1b3eff2433cc0c31fdcfc3cd2a23f Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:56 +0100 Subject: staging: most: remove tainted flag This patch removes the atomic tainted flag. It is needed to get rid of logical overhead. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 782747a50477..58e288b74b1b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -74,7 +74,6 @@ struct most_c_obj { struct most_inst_obj { int dev_id; - atomic_t tainted; struct most_interface *iface; struct list_head channel_list; struct most_c_obj *channel[MAX_CHANNELS]; @@ -1299,18 +1298,10 @@ _exit: */ int most_submit_mbo(struct mbo *mbo) { - struct most_c_obj *c; - struct most_inst_obj *i; - if (unlikely((!mbo) || (!mbo->context))) { pr_err("Bad MBO or missing channel reference\n"); return -EINVAL; } - c = mbo->context; - i = c->inst; - - if (unlikely(atomic_read(&i->tainted))) - return -ENODEV; nq_hdm_mbo(mbo); return 0; @@ -1436,17 +1427,8 @@ EXPORT_SYMBOL_GPL(most_get_mbo); */ void most_put_mbo(struct mbo *mbo) { - struct most_c_obj *c; - struct most_inst_obj *i; - - c = mbo->context; - i = c->inst; + struct most_c_obj *c = mbo->context; - if (unlikely(atomic_read(&i->tainted))) { - mbo->status = MBO_E_CLOSE; - trash_mbo(mbo); - return; - } if (c->cfg.direction == MOST_CH_TX) { arm_mbo(mbo); return; @@ -1602,14 +1584,6 @@ int most_stop_channel(struct most_interface *iface, int id, c->hdm_enqueue_task = NULL; mutex_unlock(&c->stop_task_mutex); - mutex_lock(&deregister_mutex); - if (atomic_read(&c->inst->tainted)) { - mutex_unlock(&deregister_mutex); - mutex_unlock(&c->start_mutex); - return -ENODEV; - } - mutex_unlock(&deregister_mutex); - if (iface->mod && modref) { module_put(iface->mod); modref--; @@ -1750,7 +1724,6 @@ struct kobject *most_register_interface(struct most_interface *iface) INIT_LIST_HEAD(&inst->channel_list); inst->iface = iface; inst->dev_id = id; - atomic_set(&inst->tainted, 0); list_add_tail(&inst->list, &instance_list); for (i = 0; i < iface->num_channels; i++) { @@ -1835,10 +1808,6 @@ void most_deregister_interface(struct most_interface *iface) c->aim1.ptr = NULL; } - mutex_lock(&deregister_mutex); - atomic_set(&i->tainted, 1); - mutex_unlock(&deregister_mutex); - while (modref) { if (iface->mod && modref) module_put(iface->mod); -- cgit From 9cda3007ab9c87d3977fc84e7db73e021ba048ac Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:57 +0100 Subject: staging: most: remove reference counter This patch removes the unnecessary reference conter mod_ref. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 58e288b74b1b..daae42d0238c 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -35,7 +35,6 @@ static struct class *most_class; static struct device *class_glue_dir; static struct ida mdev_id; -static int modref; static int dummy_num_buffers; struct most_c_aim_obj { @@ -1508,7 +1507,6 @@ int most_start_channel(struct most_interface *iface, int id, mutex_unlock(&c->start_mutex); return -ENOLCK; } - modref++; c->cfg.extra_len = 0; if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) { @@ -1550,7 +1548,6 @@ out: error: module_put(iface->mod); - modref--; mutex_unlock(&c->start_mutex); return ret; } @@ -1584,10 +1581,8 @@ int most_stop_channel(struct most_interface *iface, int id, c->hdm_enqueue_task = NULL; mutex_unlock(&c->stop_task_mutex); - if (iface->mod && modref) { + if (iface->mod) module_put(iface->mod); - modref--; - } c->is_poisoned = true; if (c->iface->poison_channel(c->iface, c->channel_id)) { @@ -1808,12 +1803,6 @@ void most_deregister_interface(struct most_interface *iface) c->aim1.ptr = NULL; } - while (modref) { - if (iface->mod && modref) - module_put(iface->mod); - modref--; - } - list_for_each_entry(c, &i->channel_list, list) { if (c->aim0.refs + c->aim1.refs <= 0) continue; -- cgit From b522e61fb6329b68e6da8f237f21fc83a1d8ace2 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:58 +0100 Subject: staging: most: remove code to destroy channel This patch removes unnecessary code to destroy channel objects. It is needed, because function most_stop_channel, which is indirectly triggered by function most_deregister_interface, already destroys the channels. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index daae42d0238c..31ea3a5e485e 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1803,19 +1803,6 @@ void most_deregister_interface(struct most_interface *iface) c->aim1.ptr = NULL; } - list_for_each_entry(c, &i->channel_list, list) { - if (c->aim0.refs + c->aim1.refs <= 0) - continue; - - mutex_lock(&c->stop_task_mutex); - if (c->hdm_enqueue_task) - kthread_stop(c->hdm_enqueue_task); - c->hdm_enqueue_task = NULL; - mutex_unlock(&c->stop_task_mutex); - - if (iface->poison_channel(iface, c->channel_id)) - pr_err("Can't poison channel %d\n", c->channel_id); - } ida_simple_remove(&mdev_id, i->dev_id); list_del(&i->list); destroy_most_inst_obj(i); -- cgit From 61f6bfcbaee6b49f3147ba5a3fd8d9803272b433 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:52:59 +0100 Subject: staging: most: remove redundant mutexes This patch removes the mutexes stop_task_mutex and deregister mutex, since they can safely be left out. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 31ea3a5e485e..b085f0ac5b8c 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -65,7 +65,6 @@ struct most_c_obj { struct most_c_aim_obj aim1; struct list_head trash_fifo; struct task_struct *hdm_enqueue_task; - struct mutex stop_task_mutex; wait_queue_head_t hdm_fifo_wq; }; @@ -93,8 +92,6 @@ struct most_inst_obj { _mbo; \ }) -static struct mutex deregister_mutex; - /* ___ ___ * ___C H A N N E L___ */ @@ -737,10 +734,8 @@ static void destroy_most_inst_obj(struct most_inst_obj *inst) struct most_c_obj *c, *tmp; list_for_each_entry_safe(c, tmp, &inst->channel_list, list) { - mutex_lock(&deregister_mutex); flush_trash_fifo(c); flush_channel_fifos(c); - mutex_unlock(&deregister_mutex); kobject_put(&c->kobj); } kobject_put(&inst->kobj); @@ -1575,11 +1570,9 @@ int most_stop_channel(struct most_interface *iface, int id, if (c->aim0.refs + c->aim1.refs >= 2) goto out; - mutex_lock(&c->stop_task_mutex); if (c->hdm_enqueue_task) kthread_stop(c->hdm_enqueue_task); c->hdm_enqueue_task = NULL; - mutex_unlock(&c->stop_task_mutex); if (iface->mod) module_put(iface->mod); @@ -1757,7 +1750,6 @@ struct kobject *most_register_interface(struct most_interface *iface) init_completion(&c->cleanup); atomic_set(&c->mbo_ref, 0); mutex_init(&c->start_mutex); - mutex_init(&c->stop_task_mutex); list_add_tail(&c->list, &inst->channel_list); } pr_info("registered new MOST device mdev%d (%s)\n", @@ -1853,7 +1845,6 @@ static int __init most_init(void) pr_info("init()\n"); INIT_LIST_HEAD(&instance_list); INIT_LIST_HEAD(&aim_list); - mutex_init(&deregister_mutex); ida_init(&mdev_id); if (bus_register(&most_bus)) { -- cgit From 0ccaa6de8edb0053efd4dcc49e8f053bf5ff7595 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:00 +0100 Subject: staging: most: remove redundant call to wake_up_interruptible This patch prevents the cdev module from rousing the channel wait queue in case the channel is about to be closed. It is safe to do so, because the application can not be waiting within read or write and at the same time be calling close. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 0141293b4bf5..fd2ac898628e 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -127,7 +127,6 @@ static int aim_close(struct inode *inode, struct file *filp) kfifo_free(&channel->fifo); list_del(&channel->list); ida_simple_remove(&minor_id, MINOR(channel->devno)); - wake_up_interruptible(&channel->wq); kfree(channel); return 0; } @@ -139,7 +138,6 @@ static int aim_close(struct inode *inode, struct file *filp) most_put_mbo(channel->stacked_mbo); ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); atomic_dec(&channel->access_ref); - wake_up_interruptible(&channel->wq); return ret; } -- cgit From 5f858a61a8b4f5fec7b3c0618646ed6f7bfcd3a7 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:01 +0100 Subject: staging: most: encapsulate shared code This patch encapsulates shared code. It therefore creates the new functions stop_channel and destroy_cdev. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 55 +++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index fd2ac898628e..533e2900ad63 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -69,6 +69,30 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id) return channel; } +static void stop_channel(struct aim_channel *c) +{ + struct mbo *mbo; + + while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) + most_put_mbo(mbo); + if (c->stacked_mbo) + most_put_mbo(c->stacked_mbo); + most_stop_channel(c->iface, c->channel_id, &cdev_aim); +} + +static void destroy_cdev(struct aim_channel *c) +{ + unsigned long flags; + + device_destroy(aim_class, c->devno); + cdev_del(&c->cdev); + kfifo_free(&c->fifo); + spin_lock_irqsave(&ch_list_lock, flags); + list_del(&c->list); + spin_unlock_irqrestore(&ch_list_lock, flags); + ida_simple_remove(&minor_id, MINOR(c->devno)); +} + /** * aim_open - implements the syscall to open the device * @inode: inode pointer @@ -114,31 +138,21 @@ static int aim_open(struct inode *inode, struct file *filp) */ static int aim_close(struct inode *inode, struct file *filp) { - int ret; - struct mbo *mbo; struct aim_channel *channel = to_channel(inode->i_cdev); mutex_lock(&channel->io_mutex); if (!channel->dev) { mutex_unlock(&channel->io_mutex); atomic_dec(&channel->access_ref); - device_destroy(aim_class, channel->devno); - cdev_del(&channel->cdev); - kfifo_free(&channel->fifo); - list_del(&channel->list); - ida_simple_remove(&minor_id, MINOR(channel->devno)); + destroy_cdev(channel); kfree(channel); return 0; } mutex_unlock(&channel->io_mutex); - while (kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1)) - most_put_mbo(mbo); - if (channel->stacked_mbo) - most_put_mbo(channel->stacked_mbo); - ret = most_stop_channel(channel->iface, channel->channel_id, &cdev_aim); + stop_channel(channel); atomic_dec(&channel->access_ref); - return ret; + return 0; } /** @@ -310,7 +324,6 @@ static const struct file_operations channel_fops = { static int aim_disconnect_channel(struct most_interface *iface, int channel_id) { struct aim_channel *channel; - unsigned long flags; if (!iface) { pr_info("Bad interface pointer\n"); @@ -326,13 +339,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) mutex_unlock(&channel->io_mutex); if (atomic_read(&channel->access_ref)) { - device_destroy(aim_class, channel->devno); - cdev_del(&channel->cdev); - kfifo_free(&channel->fifo); - ida_simple_remove(&minor_id, MINOR(channel->devno)); - spin_lock_irqsave(&ch_list_lock, flags); - list_del(&channel->list); - spin_unlock_irqrestore(&ch_list_lock, flags); + destroy_cdev(channel); kfree(channel); } else { wake_up_interruptible(&channel->wq); @@ -526,11 +533,7 @@ static void __exit mod_exit(void) most_deregister_aim(&cdev_aim); list_for_each_entry_safe(channel, tmp, &channel_list, list) { - device_destroy(aim_class, channel->devno); - cdev_del(&channel->cdev); - kfifo_free(&channel->fifo); - list_del(&channel->list); - ida_simple_remove(&minor_id, MINOR(channel->devno)); + destroy_cdev(channel); kfree(channel); } class_destroy(aim_class); -- cgit From cdc293d58945527f36b13771822be69277c21bd6 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 12 Jan 2016 14:00:03 +0100 Subject: staging: most: fix retrieval of buffer availability This patch fixes the function channel_has_mbo that delivers the false information in case two AIMs are using the same tx channel. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 12 ++++++------ drivers/staging/most/mostcore/core.c | 7 ++++++- drivers/staging/most/mostcore/mostcore.h | 3 ++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 533e2900ad63..c4bbf7d296e8 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -50,6 +50,11 @@ struct aim_channel { static struct list_head channel_list; static spinlock_t ch_list_lock; +static inline bool ch_has_mbo(struct aim_channel *c) +{ + return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; +} + static struct aim_channel *get_channel(struct most_interface *iface, int id) { struct aim_channel *channel, *tmp; @@ -279,11 +284,6 @@ start_copy: return copied; } -static inline bool __must_check IS_ERR_OR_FALSE(int x) -{ - return x <= 0; -} - static unsigned int aim_poll(struct file *filp, poll_table *wait) { struct aim_channel *c = filp->private_data; @@ -295,7 +295,7 @@ static unsigned int aim_poll(struct file *filp, poll_table *wait) if (!kfifo_is_empty(&c->fifo)) mask |= POLLIN | POLLRDNORM; } else { - if (!IS_ERR_OR_FALSE(channel_has_mbo(c->iface, c->channel_id))) + if (ch_has_mbo(c)) mask |= POLLOUT | POLLWRNORM; } return mask; diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index b085f0ac5b8c..09a5a1a1138e 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1352,7 +1352,7 @@ most_c_obj *get_channel_by_iface(struct most_interface *iface, int id) return i->channel[id]; } -int channel_has_mbo(struct most_interface *iface, int id) +int channel_has_mbo(struct most_interface *iface, int id, struct most_aim *aim) { struct most_c_obj *c = get_channel_by_iface(iface, id); unsigned long flags; @@ -1361,6 +1361,11 @@ int channel_has_mbo(struct most_interface *iface, int id) if (unlikely(!c)) return -EINVAL; + if (c->aim0.refs && c->aim1.refs && + ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || + (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) + return 0; + spin_lock_irqsave(&c->fifo_lock, flags); empty = list_empty(&c->fifo); spin_unlock_irqrestore(&c->fifo_lock, flags); diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h index bda3850d5435..60e018e499ef 100644 --- a/drivers/staging/most/mostcore/mostcore.h +++ b/drivers/staging/most/mostcore/mostcore.h @@ -310,7 +310,8 @@ int most_deregister_aim(struct most_aim *aim); struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx, struct most_aim *); void most_put_mbo(struct mbo *mbo); -int channel_has_mbo(struct most_interface *iface, int channel_idx); +int channel_has_mbo(struct most_interface *iface, int channel_idx, + struct most_aim *aim); int most_start_channel(struct most_interface *iface, int channel_idx, struct most_aim *); int most_stop_channel(struct most_interface *iface, int channel_idx, -- cgit From d8b082e6c625cba59ecfb80e4506c8f30bed24ea Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:03 +0100 Subject: staging: most: rename variable channel This patch renames the variable 'channel' to 'c'. This is needed to have the code look more homogeneous and to prevent format violations. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 216 +++++++++++++++++------------------ 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index c4bbf7d296e8..50651395a0ae 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -57,13 +57,13 @@ static inline bool ch_has_mbo(struct aim_channel *c) static struct aim_channel *get_channel(struct most_interface *iface, int id) { - struct aim_channel *channel, *tmp; + struct aim_channel *c, *tmp; unsigned long flags; int found_channel = 0; spin_lock_irqsave(&ch_list_lock, flags); - list_for_each_entry_safe(channel, tmp, &channel_list, list) { - if ((channel->iface == iface) && (channel->channel_id == id)) { + list_for_each_entry_safe(c, tmp, &channel_list, list) { + if ((c->iface == iface) && (c->channel_id == id)) { found_channel = 1; break; } @@ -71,7 +71,7 @@ static struct aim_channel *get_channel(struct most_interface *iface, int id) spin_unlock_irqrestore(&ch_list_lock, flags); if (!found_channel) return NULL; - return channel; + return c; } static void stop_channel(struct aim_channel *c) @@ -108,29 +108,29 @@ static void destroy_cdev(struct aim_channel *c) */ static int aim_open(struct inode *inode, struct file *filp) { - struct aim_channel *channel; + struct aim_channel *c; int ret; - channel = to_channel(inode->i_cdev); - filp->private_data = channel; + c = to_channel(inode->i_cdev); + filp->private_data = c; - if (((channel->cfg->direction == MOST_CH_RX) && + if (((c->cfg->direction == MOST_CH_RX) && ((filp->f_flags & O_ACCMODE) != O_RDONLY)) || - ((channel->cfg->direction == MOST_CH_TX) && + ((c->cfg->direction == MOST_CH_TX) && ((filp->f_flags & O_ACCMODE) != O_WRONLY))) { pr_info("WARN: Access flags mismatch\n"); return -EACCES; } - if (!atomic_inc_and_test(&channel->access_ref)) { + if (!atomic_inc_and_test(&c->access_ref)) { pr_info("WARN: Device is busy\n"); - atomic_dec(&channel->access_ref); + atomic_dec(&c->access_ref); return -EBUSY; } - ret = most_start_channel(channel->iface, channel->channel_id, + ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); if (ret) - atomic_dec(&channel->access_ref); + atomic_dec(&c->access_ref); return ret; } @@ -143,20 +143,20 @@ static int aim_open(struct inode *inode, struct file *filp) */ static int aim_close(struct inode *inode, struct file *filp) { - struct aim_channel *channel = to_channel(inode->i_cdev); - - mutex_lock(&channel->io_mutex); - if (!channel->dev) { - mutex_unlock(&channel->io_mutex); - atomic_dec(&channel->access_ref); - destroy_cdev(channel); - kfree(channel); + struct aim_channel *c = to_channel(inode->i_cdev); + + mutex_lock(&c->io_mutex); + if (!c->dev) { + mutex_unlock(&c->io_mutex); + atomic_dec(&c->access_ref); + destroy_cdev(c); + kfree(c); return 0; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); - stop_channel(channel); - atomic_dec(&channel->access_ref); + stop_channel(c); + atomic_dec(&c->access_ref); return 0; } @@ -175,38 +175,38 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, size_t max_len = 0; ssize_t retval; struct mbo *mbo; - struct aim_channel *channel = filp->private_data; + struct aim_channel *c = filp->private_data; - mutex_lock(&channel->io_mutex); - if (unlikely(!channel->dev)) { - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); return -EPIPE; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); - mbo = most_get_mbo(channel->iface, channel->channel_id, &cdev_aim); + mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); if (!mbo) { if ((filp->f_flags & O_NONBLOCK)) return -EAGAIN; if (wait_event_interruptible( - channel->wq, - (mbo = most_get_mbo(channel->iface, - channel->channel_id, + c->wq, + (mbo = most_get_mbo(c->iface, + c->channel_id, &cdev_aim)) || - (!channel->dev))) + (!c->dev))) return -ERESTARTSYS; } - mutex_lock(&channel->io_mutex); - if (unlikely(!channel->dev)) { - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); err = -EPIPE; goto error; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); - max_len = channel->cfg->buffer_size; + max_len = c->cfg->buffer_size; actual_len = min(count, max_len); mbo->buffer_length = actual_len; @@ -240,47 +240,47 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) { size_t to_copy, not_copied, copied; struct mbo *mbo; - struct aim_channel *channel = filp->private_data; + struct aim_channel *c = filp->private_data; - if (channel->stacked_mbo) { - mbo = channel->stacked_mbo; + if (c->stacked_mbo) { + mbo = c->stacked_mbo; goto start_copy; } - while ((!kfifo_out(&channel->fifo, &mbo, 1)) && (channel->dev)) { + while ((!kfifo_out(&c->fifo, &mbo, 1)) && (c->dev)) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; - if (wait_event_interruptible(channel->wq, - (!kfifo_is_empty(&channel->fifo) || - (!channel->dev)))) + if (wait_event_interruptible(c->wq, + (!kfifo_is_empty(&c->fifo) || + (!c->dev)))) return -ERESTARTSYS; } - channel->stacked_mbo = mbo; + c->stacked_mbo = mbo; start_copy: /* make sure we don't submit to gone devices */ - mutex_lock(&channel->io_mutex); - if (unlikely(!channel->dev)) { - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + if (unlikely(!c->dev)) { + mutex_unlock(&c->io_mutex); return -EIO; } to_copy = min_t(size_t, count, - mbo->processed_length - channel->mbo_offs); + mbo->processed_length - c->mbo_offs); not_copied = copy_to_user(buf, - mbo->virt_address + channel->mbo_offs, + mbo->virt_address + c->mbo_offs, to_copy); copied = to_copy - not_copied; - channel->mbo_offs += copied; - if (channel->mbo_offs >= mbo->processed_length) { + c->mbo_offs += copied; + if (c->mbo_offs >= mbo->processed_length) { most_put_mbo(mbo); - channel->mbo_offs = 0; - channel->stacked_mbo = NULL; + c->mbo_offs = 0; + c->stacked_mbo = NULL; } - mutex_unlock(&channel->io_mutex); + mutex_unlock(&c->io_mutex); return copied; } @@ -323,26 +323,26 @@ static const struct file_operations channel_fops = { */ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) { - struct aim_channel *channel; + struct aim_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); return -EINVAL; } - channel = get_channel(iface, channel_id); - if (!channel) + c = get_channel(iface, channel_id); + if (!c) return -ENXIO; - mutex_lock(&channel->io_mutex); - channel->dev = NULL; - mutex_unlock(&channel->io_mutex); + mutex_lock(&c->io_mutex); + c->dev = NULL; + mutex_unlock(&c->io_mutex); - if (atomic_read(&channel->access_ref)) { - destroy_cdev(channel); - kfree(channel); + if (atomic_read(&c->access_ref)) { + destroy_cdev(c); + kfree(c); } else { - wake_up_interruptible(&channel->wq); + wake_up_interruptible(&c->wq); } return 0; } @@ -356,21 +356,21 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) */ static int aim_rx_completion(struct mbo *mbo) { - struct aim_channel *channel; + struct aim_channel *c; if (!mbo) return -EINVAL; - channel = get_channel(mbo->ifp, mbo->hdm_channel_id); - if (!channel) + c = get_channel(mbo->ifp, mbo->hdm_channel_id); + if (!c) return -ENXIO; - kfifo_in(&channel->fifo, &mbo, 1); + kfifo_in(&c->fifo, &mbo, 1); #ifdef DEBUG_MESG - if (kfifo_is_full(&channel->fifo)) + if (kfifo_is_full(&c->fifo)) pr_info("WARN: Fifo is full\n"); #endif - wake_up_interruptible(&channel->wq); + wake_up_interruptible(&c->wq); return 0; } @@ -383,7 +383,7 @@ static int aim_rx_completion(struct mbo *mbo) */ static int aim_tx_completion(struct most_interface *iface, int channel_id) { - struct aim_channel *channel; + struct aim_channel *c; if (!iface) { pr_info("Bad interface pointer\n"); @@ -394,10 +394,10 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) return -EINVAL; } - channel = get_channel(iface, channel_id); - if (!channel) + c = get_channel(iface, channel_id); + if (!c) return -ENXIO; - wake_up_interruptible(&channel->wq); + wake_up_interruptible(&c->wq); return 0; } @@ -419,7 +419,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, struct most_channel_config *cfg, struct kobject *parent, char *name) { - struct aim_channel *channel; + struct aim_channel *c; unsigned long cl_flags; int retval; int current_minor; @@ -428,60 +428,60 @@ static int aim_probe(struct most_interface *iface, int channel_id, pr_info("Probing AIM with bad arguments"); return -EINVAL; } - channel = get_channel(iface, channel_id); - if (channel) + c = get_channel(iface, channel_id); + if (c) return -EEXIST; current_minor = ida_simple_get(&minor_id, 0, 0, GFP_KERNEL); if (current_minor < 0) return current_minor; - channel = kzalloc(sizeof(*channel), GFP_KERNEL); - if (!channel) { + c = kzalloc(sizeof(*c), GFP_KERNEL); + if (!c) { retval = -ENOMEM; goto error_alloc_channel; } - channel->devno = MKDEV(major, current_minor); - cdev_init(&channel->cdev, &channel_fops); - channel->cdev.owner = THIS_MODULE; - cdev_add(&channel->cdev, channel->devno, 1); - channel->iface = iface; - channel->cfg = cfg; - channel->channel_id = channel_id; - channel->mbo_offs = 0; - atomic_set(&channel->access_ref, -1); - INIT_KFIFO(channel->fifo); - retval = kfifo_alloc(&channel->fifo, cfg->num_buffers, GFP_KERNEL); + c->devno = MKDEV(major, current_minor); + cdev_init(&c->cdev, &channel_fops); + c->cdev.owner = THIS_MODULE; + cdev_add(&c->cdev, c->devno, 1); + c->iface = iface; + c->cfg = cfg; + c->channel_id = channel_id; + c->mbo_offs = 0; + atomic_set(&c->access_ref, -1); + INIT_KFIFO(c->fifo); + retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); if (retval) { pr_info("failed to alloc channel kfifo"); goto error_alloc_kfifo; } - init_waitqueue_head(&channel->wq); - mutex_init(&channel->io_mutex); + init_waitqueue_head(&c->wq); + mutex_init(&c->io_mutex); spin_lock_irqsave(&ch_list_lock, cl_flags); - list_add_tail(&channel->list, &channel_list); + list_add_tail(&c->list, &channel_list); spin_unlock_irqrestore(&ch_list_lock, cl_flags); - channel->dev = device_create(aim_class, + c->dev = device_create(aim_class, NULL, - channel->devno, + c->devno, NULL, "%s", name); - retval = IS_ERR(channel->dev); + retval = IS_ERR(c->dev); if (retval) { pr_info("failed to create new device node %s\n", name); goto error_create_device; } - kobject_uevent(&channel->dev->kobj, KOBJ_ADD); + kobject_uevent(&c->dev->kobj, KOBJ_ADD); return 0; error_create_device: - kfifo_free(&channel->fifo); - list_del(&channel->list); + kfifo_free(&c->fifo); + list_del(&c->list); error_alloc_kfifo: - cdev_del(&channel->cdev); - kfree(channel); + cdev_del(&c->cdev); + kfree(c); error_alloc_channel: ida_simple_remove(&minor_id, current_minor); return retval; @@ -526,15 +526,15 @@ free_cdev: static void __exit mod_exit(void) { - struct aim_channel *channel, *tmp; + struct aim_channel *c, *tmp; pr_info("exit module\n"); most_deregister_aim(&cdev_aim); - list_for_each_entry_safe(channel, tmp, &channel_list, list) { - destroy_cdev(channel); - kfree(channel); + list_for_each_entry_safe(c, tmp, &channel_list, list) { + destroy_cdev(c); + kfree(c); } class_destroy(aim_class); unregister_chrdev_region(aim_devno, 1); -- cgit From fa96b8ed9cc562827b27181de7285c8fba54f395 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:04 +0100 Subject: staging: most: fix race conditions This patch fixes race conditions that might emerge from functions aim_open, aim_close, aim_read, aim_write and aim_disconnect_channel within module cdev. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 89 ++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 50651395a0ae..ade7808e9d1c 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -32,6 +32,7 @@ static struct most_aim cdev_aim; struct aim_channel { wait_queue_head_t wq; + spinlock_t unlink; /* synchronization lock to unlink channels */ struct cdev cdev; struct device *dev; struct mutex io_mutex; @@ -55,6 +56,12 @@ static inline bool ch_has_mbo(struct aim_channel *c) return channel_has_mbo(c->iface, c->channel_id, &cdev_aim) > 0; } +static inline bool ch_get_mbo(struct aim_channel *c, struct mbo **mbo) +{ + *mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); + return *mbo; +} + static struct aim_channel *get_channel(struct most_interface *iface, int id) { struct aim_channel *c, *tmp; @@ -82,6 +89,7 @@ static void stop_channel(struct aim_channel *c) most_put_mbo(mbo); if (c->stacked_mbo) most_put_mbo(c->stacked_mbo); + c->stacked_mbo = NULL; most_stop_channel(c->iface, c->channel_id, &cdev_aim); } @@ -121,16 +129,25 @@ static int aim_open(struct inode *inode, struct file *filp) pr_info("WARN: Access flags mismatch\n"); return -EACCES; } + + mutex_lock(&c->io_mutex); + if (!c->dev) { + pr_info("WARN: Device is destroyed\n"); + mutex_unlock(&c->io_mutex); + return -EBUSY; + } + if (!atomic_inc_and_test(&c->access_ref)) { pr_info("WARN: Device is busy\n"); atomic_dec(&c->access_ref); + mutex_unlock(&c->io_mutex); return -EBUSY; } - ret = most_start_channel(c->iface, c->channel_id, - &cdev_aim); + ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); if (ret) atomic_dec(&c->access_ref); + mutex_unlock(&c->io_mutex); return ret; } @@ -146,17 +163,17 @@ static int aim_close(struct inode *inode, struct file *filp) struct aim_channel *c = to_channel(inode->i_cdev); mutex_lock(&c->io_mutex); - if (!c->dev) { + spin_lock(&c->unlink); + atomic_dec(&c->access_ref); + spin_unlock(&c->unlink); + if (c->dev) { + stop_channel(c); mutex_unlock(&c->io_mutex); - atomic_dec(&c->access_ref); + } else { destroy_cdev(c); + mutex_unlock(&c->io_mutex); kfree(c); - return 0; } - mutex_unlock(&c->io_mutex); - - stop_channel(c); - atomic_dec(&c->access_ref); return 0; } @@ -171,40 +188,27 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { int ret, err; - size_t actual_len = 0; - size_t max_len = 0; + size_t actual_len; + size_t max_len; ssize_t retval; - struct mbo *mbo; + struct mbo *mbo = NULL; struct aim_channel *c = filp->private_data; mutex_lock(&c->io_mutex); - if (unlikely(!c->dev)) { + while (c->dev && !ch_get_mbo(c, &mbo)) { mutex_unlock(&c->io_mutex); - return -EPIPE; - } - mutex_unlock(&c->io_mutex); - - mbo = most_get_mbo(c->iface, c->channel_id, &cdev_aim); - if (!mbo) { if ((filp->f_flags & O_NONBLOCK)) return -EAGAIN; - if (wait_event_interruptible( - c->wq, - (mbo = most_get_mbo(c->iface, - c->channel_id, - &cdev_aim)) || - (!c->dev))) + if (wait_event_interruptible(c->wq, ch_has_mbo(c) || !c->dev)) return -ERESTARTSYS; + mutex_lock(&c->io_mutex); } - mutex_lock(&c->io_mutex); if (unlikely(!c->dev)) { - mutex_unlock(&c->io_mutex); err = -EPIPE; goto error; } - mutex_unlock(&c->io_mutex); max_len = c->cfg->buffer_size; actual_len = min(count, max_len); @@ -222,9 +226,12 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, err = ret; goto error; } + mutex_unlock(&c->io_mutex); return actual_len - retval; error: - most_put_mbo(mbo); + if (mbo) + most_put_mbo(mbo); + mutex_unlock(&c->io_mutex); return err; } @@ -242,23 +249,25 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct mbo *mbo; struct aim_channel *c = filp->private_data; + mutex_lock(&c->io_mutex); if (c->stacked_mbo) { mbo = c->stacked_mbo; goto start_copy; } while ((!kfifo_out(&c->fifo, &mbo, 1)) && (c->dev)) { + mutex_unlock(&c->io_mutex); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; if (wait_event_interruptible(c->wq, (!kfifo_is_empty(&c->fifo) || (!c->dev)))) return -ERESTARTSYS; + mutex_lock(&c->io_mutex); } c->stacked_mbo = mbo; start_copy: /* make sure we don't submit to gone devices */ - mutex_lock(&c->io_mutex); if (unlikely(!c->dev)) { mutex_unlock(&c->io_mutex); return -EIO; @@ -335,14 +344,17 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) return -ENXIO; mutex_lock(&c->io_mutex); + spin_lock(&c->unlink); c->dev = NULL; - mutex_unlock(&c->io_mutex); - - if (atomic_read(&c->access_ref)) { + spin_unlock(&c->unlink); + if (!atomic_read(&c->access_ref)) { + stop_channel(c); + wake_up_interruptible(&c->wq); + mutex_unlock(&c->io_mutex); + } else { destroy_cdev(c); + mutex_unlock(&c->io_mutex); kfree(c); - } else { - wake_up_interruptible(&c->wq); } return 0; } @@ -365,7 +377,13 @@ static int aim_rx_completion(struct mbo *mbo) if (!c) return -ENXIO; + spin_lock(&c->unlink); + if (atomic_read(&c->access_ref) || !c->dev) { + spin_unlock(&c->unlink); + return -EFAULT; + } kfifo_in(&c->fifo, &mbo, 1); + spin_unlock(&c->unlink); #ifdef DEBUG_MESG if (kfifo_is_full(&c->fifo)) pr_info("WARN: Fifo is full\n"); @@ -451,6 +469,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->channel_id = channel_id; c->mbo_offs = 0; atomic_set(&c->access_ref, -1); + spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); if (retval) { -- cgit From b3c9f3c56c41cbebe7804b48ba8e6e484509c2c0 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:05 +0100 Subject: staging: most: change type of access_ref This patch changes the type of the access reference from atomit_t to int. It is needed, because the reference variable is secured by synchronization locks and does not need to be atomic anymore. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index ade7808e9d1c..d9c3f561c7a7 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -43,7 +43,7 @@ struct aim_channel { size_t mbo_offs; struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); - atomic_t access_ref; + int access_ref; struct list_head list; }; @@ -137,16 +137,15 @@ static int aim_open(struct inode *inode, struct file *filp) return -EBUSY; } - if (!atomic_inc_and_test(&c->access_ref)) { + if (c->access_ref) { pr_info("WARN: Device is busy\n"); - atomic_dec(&c->access_ref); mutex_unlock(&c->io_mutex); return -EBUSY; } ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); - if (ret) - atomic_dec(&c->access_ref); + if (!ret) + c->access_ref = 1; mutex_unlock(&c->io_mutex); return ret; } @@ -164,7 +163,7 @@ static int aim_close(struct inode *inode, struct file *filp) mutex_lock(&c->io_mutex); spin_lock(&c->unlink); - atomic_dec(&c->access_ref); + c->access_ref = 0; spin_unlock(&c->unlink); if (c->dev) { stop_channel(c); @@ -347,7 +346,7 @@ static int aim_disconnect_channel(struct most_interface *iface, int channel_id) spin_lock(&c->unlink); c->dev = NULL; spin_unlock(&c->unlink); - if (!atomic_read(&c->access_ref)) { + if (c->access_ref) { stop_channel(c); wake_up_interruptible(&c->wq); mutex_unlock(&c->io_mutex); @@ -378,7 +377,7 @@ static int aim_rx_completion(struct mbo *mbo) return -ENXIO; spin_lock(&c->unlink); - if (atomic_read(&c->access_ref) || !c->dev) { + if (!c->access_ref || !c->dev) { spin_unlock(&c->unlink); return -EFAULT; } @@ -468,7 +467,7 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->cfg = cfg; c->channel_id = channel_id; c->mbo_offs = 0; - atomic_set(&c->access_ref, -1); + c->access_ref = 0; spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); retval = kfifo_alloc(&c->fifo, cfg->num_buffers, GFP_KERNEL); -- cgit From f45b0fba43f415f69982df743dfa9b5d1b57785e Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:06 +0100 Subject: staging: most: remove stacked_mbo This patch makes use of kfifo_peek and kfifo_skip, which renders the variable stacked_mbo useless. It is therefore removed. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index d9c3f561c7a7..0ee2f085848f 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -41,7 +41,6 @@ struct aim_channel { unsigned int channel_id; dev_t devno; size_t mbo_offs; - struct mbo *stacked_mbo; DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *)); int access_ref; struct list_head list; @@ -87,9 +86,6 @@ static void stop_channel(struct aim_channel *c) while (kfifo_out((struct kfifo *)&c->fifo, &mbo, 1)) most_put_mbo(mbo); - if (c->stacked_mbo) - most_put_mbo(c->stacked_mbo); - c->stacked_mbo = NULL; most_stop_channel(c->iface, c->channel_id, &cdev_aim); } @@ -143,6 +139,7 @@ static int aim_open(struct inode *inode, struct file *filp) return -EBUSY; } + c->mbo_offs = 0; ret = most_start_channel(c->iface, c->channel_id, &cdev_aim); if (!ret) c->access_ref = 1; @@ -249,11 +246,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) struct aim_channel *c = filp->private_data; mutex_lock(&c->io_mutex); - if (c->stacked_mbo) { - mbo = c->stacked_mbo; - goto start_copy; - } - while ((!kfifo_out(&c->fifo, &mbo, 1)) && (c->dev)) { + while (c->dev && !kfifo_peek(&c->fifo, &mbo)) { mutex_unlock(&c->io_mutex); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; @@ -263,9 +256,7 @@ aim_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) return -ERESTARTSYS; mutex_lock(&c->io_mutex); } - c->stacked_mbo = mbo; -start_copy: /* make sure we don't submit to gone devices */ if (unlikely(!c->dev)) { mutex_unlock(&c->io_mutex); @@ -284,9 +275,9 @@ start_copy: c->mbo_offs += copied; if (c->mbo_offs >= mbo->processed_length) { + kfifo_skip(&c->fifo); most_put_mbo(mbo); c->mbo_offs = 0; - c->stacked_mbo = NULL; } mutex_unlock(&c->io_mutex); return copied; @@ -466,7 +457,6 @@ static int aim_probe(struct most_interface *iface, int channel_id, c->iface = iface; c->cfg = cfg; c->channel_id = channel_id; - c->mbo_offs = 0; c->access_ref = 0; spin_lock_init(&c->unlink); INIT_KFIFO(c->fifo); -- cgit From 5adf5dc5682fa7968370a8bea773d98f1beeeddc Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:07 +0100 Subject: staging: most: rearrange function aim_write This patch straightens and rearranges the code of function aim_write() of module aim-cdev. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 0ee2f085848f..c3f32716168b 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -183,10 +183,9 @@ static int aim_close(struct inode *inode, struct file *filp) static ssize_t aim_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) { - int ret, err; + int ret; size_t actual_len; size_t max_len; - ssize_t retval; struct mbo *mbo = NULL; struct aim_channel *c = filp->private_data; @@ -202,33 +201,30 @@ static ssize_t aim_write(struct file *filp, const char __user *buf, } if (unlikely(!c->dev)) { - err = -EPIPE; - goto error; + ret = -EPIPE; + goto unlock; } max_len = c->cfg->buffer_size; actual_len = min(count, max_len); mbo->buffer_length = actual_len; - retval = copy_from_user(mbo->virt_address, buf, mbo->buffer_length); - if (retval) { - err = -EIO; - goto error; + if (copy_from_user(mbo->virt_address, buf, mbo->buffer_length)) { + ret = -EFAULT; + goto put_mbo; } ret = most_submit_mbo(mbo); - if (ret) { - pr_info("submitting MBO to core failed\n"); - err = ret; - goto error; - } + if (ret) + goto put_mbo; + mutex_unlock(&c->io_mutex); - return actual_len - retval; -error: - if (mbo) - most_put_mbo(mbo); + return actual_len; +put_mbo: + most_put_mbo(mbo); +unlock: mutex_unlock(&c->io_mutex); - return err; + return ret; } /** -- cgit From 1c55d30b1da6bd4f3b0dbd64e660fad44b8958d8 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:08 +0100 Subject: staging: most: add statistics for dropped packets This patch adds a counter for dropped packets. It needed for statistical analysis. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-network/networking.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c index 3c7beb03871d..2f42de44d051 100644 --- a/drivers/staging/most/aim-network/networking.c +++ b/drivers/staging/most/aim-network/networking.c @@ -431,6 +431,7 @@ static int aim_rx_data(struct mbo *mbo) u32 len = mbo->processed_length; struct sk_buff *skb; struct net_device *dev; + unsigned int skb_len; nd = get_net_dev_context(mbo->ifp); if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id) @@ -482,9 +483,13 @@ static int aim_rx_data(struct mbo *mbo) memcpy(skb_put(skb, len), buf, len); skb->protocol = eth_type_trans(skb, dev); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - netif_rx(skb); + skb_len = skb->len; + if (netif_rx(skb) == NET_RX_SUCCESS) { + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb_len; + } else { + dev->stats.rx_dropped++; + } out: most_put_mbo(mbo); -- cgit From 0833ac7db0034b64669ea3fc3dc36d7c9e7905b8 Mon Sep 17 00:00:00 2001 From: Christian Gromm Date: Tue, 22 Dec 2015 10:53:09 +0100 Subject: staging: most: remove 2nd forward declaration of struct most_aim This patch removes the second forwared declaration of struct most_aim. Signed-off-by: Christian Gromm Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index c3f32716168b..3a2dbf1490c6 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -405,8 +405,6 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id) return 0; } -static struct most_aim cdev_aim; - /** * aim_probe - probe function of the driver module * @iface: pointer to interface instance -- cgit From 17ac98ac7339bdf867633d788e1bde32349012f2 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Sun, 22 Nov 2015 22:30:54 +0530 Subject: staging: most: fix error comparison device_create() returns ERR_PTR on error, it does not return NULL. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index 09a5a1a1138e..e4797fdb10dd 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1869,7 +1869,7 @@ static int __init most_init(void) class_glue_dir = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (!class_glue_dir) + if (IS_ERR(class_glue_dir)) goto exit_driver; most_aim_kset = -- cgit From e7f2b70fd3a98951e4f09b7c7a084b268c924ad8 Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Mon, 28 Dec 2015 08:55:37 +0000 Subject: staging: most: replace multiple if..else with table lookup Replace multiple if..else if..statements with simple table lookup in two functions. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 41 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index e4797fdb10dd..ab4c32d78d9f 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -79,6 +79,14 @@ struct most_inst_obj { struct list_head list; }; +static const struct { + int most_ch_data_type; + char *name; +} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" }, + { MOST_CH_ASYNC, "async\n" }, + { MOST_CH_SYNC, "sync\n" }, + { MOST_CH_ISOC_AVP, "isoc_avp\n"} }; + #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) /** @@ -409,14 +417,12 @@ static ssize_t show_set_datatype(struct most_c_obj *c, struct most_c_attr *attr, char *buf) { - if (c->cfg.data_type & MOST_CH_CONTROL) - return snprintf(buf, PAGE_SIZE, "control\n"); - else if (c->cfg.data_type & MOST_CH_ASYNC) - return snprintf(buf, PAGE_SIZE, "async\n"); - else if (c->cfg.data_type & MOST_CH_SYNC) - return snprintf(buf, PAGE_SIZE, "sync\n"); - else if (c->cfg.data_type & MOST_CH_ISOC_AVP) - return snprintf(buf, PAGE_SIZE, "isoc_avp\n"); + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) + return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); + } return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -425,15 +431,16 @@ static ssize_t store_set_datatype(struct most_c_obj *c, const char *buf, size_t count) { - if (!strcmp(buf, "control\n")) { - c->cfg.data_type = MOST_CH_CONTROL; - } else if (!strcmp(buf, "async\n")) { - c->cfg.data_type = MOST_CH_ASYNC; - } else if (!strcmp(buf, "sync\n")) { - c->cfg.data_type = MOST_CH_SYNC; - } else if (!strcmp(buf, "isoc_avp\n")) { - c->cfg.data_type = MOST_CH_ISOC_AVP; - } else { + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (!strcmp(buf, ch_data_type[i].name)) { + c->cfg.data_type = ch_data_type[i].most_ch_data_type; + break; + } + } + + if (i == ARRAY_SIZE(ch_data_type)) { pr_info("WARN: invalid attribute settings\n"); return -EINVAL; } -- cgit From 092c78f24a89c0ef837cc905fb40f67db39ba257 Mon Sep 17 00:00:00 2001 From: Hugo Camboulive Date: Sat, 2 Jan 2016 22:33:26 +0000 Subject: staging: most: add __iomem for io_base and registers This removes a few Sparse warnings. Signed-off-by: Hugo Camboulive Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/hdm-dim2/dim2_hal.c | 4 ++-- drivers/staging/most/hdm-dim2/dim2_hal.h | 7 ++++--- drivers/staging/most/hdm-dim2/dim2_hdm.c | 6 +++--- drivers/staging/most/hdm-dim2/dim2_hdm.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c index 172257596f1f..3c524506ee22 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.c +++ b/drivers/staging/most/hdm-dim2/dim2_hal.c @@ -84,7 +84,7 @@ static inline bool dim_on_error(u8 error_id, const char *error_message) struct lld_global_vars_t { bool dim_is_initialized; bool mcm_is_initialized; - struct dim2_regs *dim2; /* DIM2 core base address */ + struct dim2_regs __iomem *dim2; /* DIM2 core base address */ u32 dbr_map[DBR_MAP_SIZE]; }; @@ -650,7 +650,7 @@ static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number) /* -------------------------------------------------------------------------- */ /* API */ -u8 dim_startup(void *dim_base_address, u32 mlb_clock) +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock) { g.dim_is_initialized = false; diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h index 48cdd9c8cde1..fc73d4f97734 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hal.h +++ b/drivers/staging/most/hdm-dim2/dim2_hal.h @@ -16,6 +16,7 @@ #define _DIM2_HAL_H #include +#include "dim2_reg.h" #ifdef __cplusplus extern "C" { @@ -65,7 +66,7 @@ struct dim_channel { u16 done_sw_buffers_number; /*< Done software buffers number. */ }; -u8 dim_startup(void *dim_base_address, u32 mlb_clock); +u8 dim_startup(struct dim2_regs __iomem *dim_base_address, u32 mlb_clock); void dim_shutdown(void); @@ -103,9 +104,9 @@ bool dim_enqueue_buffer(struct dim_channel *ch, u32 buffer_addr, bool dim_detach_buffers(struct dim_channel *ch, u16 buffers_number); -u32 dimcb_io_read(u32 *ptr32); +u32 dimcb_io_read(u32 __iomem *ptr32); -void dimcb_io_write(u32 *ptr32, u32 value); +void dimcb_io_write(u32 __iomem *ptr32, u32 value); void dimcb_on_error(u8 error_id, const char *error_message); diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c index 48ce7ab1bb03..6296aa5b6d8e 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.c +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c @@ -99,7 +99,7 @@ struct dim2_hdm { struct most_channel_capability capabilities[DMA_CHANNELS]; struct most_interface most_iface; char name[16 + sizeof "dim2-"]; - void *io_base; + void __iomem *io_base; unsigned int irq_ahb0; int clk_speed; struct task_struct *netinfo_task; @@ -138,7 +138,7 @@ bool dim2_sysfs_get_state_cb(void) * dimcb_io_read - callback from HAL to read an I/O register * @ptr32: register address */ -u32 dimcb_io_read(u32 *ptr32) +u32 dimcb_io_read(u32 __iomem *ptr32) { return readl(ptr32); } @@ -148,7 +148,7 @@ u32 dimcb_io_read(u32 *ptr32) * @ptr32: register address * @value: value to write */ -void dimcb_io_write(u32 *ptr32, u32 value) +void dimcb_io_write(u32 __iomem *ptr32, u32 value) { writel(value, ptr32); } diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h index 1c94e3355fcc..4050e7c764ed 100644 --- a/drivers/staging/most/hdm-dim2/dim2_hdm.h +++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h @@ -18,7 +18,7 @@ struct device; /* platform dependent data for dim2 interface */ struct dim2_platform_data { - int (*init)(struct dim2_platform_data *pd, void *io_base, + int (*init)(struct dim2_platform_data *pd, void __iomem *io_base, int clk_speed); void (*destroy)(struct dim2_platform_data *pd); void *priv; -- cgit From 18e77054de741ef3ed2a2489bc9bf82a318b2d5e Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Fri, 29 Jan 2016 22:07:30 -0800 Subject: staging: ashmem: Avoid deadlock with mmap/shrink Both ashmem_mmap and ashmem_shrink take the ashmem_lock. It may be possible for ashmem_mmap to invoke ashmem_shrink: -000|mutex_lock(lock = 0x0) -001|ashmem_shrink(?, sc = 0x0) <--- try to take ashmem_mutex again -002|shrink_slab(shrink = 0xDA5F1CC0, nr_pages_scanned = 0, lru_pages -002|= -002|124) -003|try_to_free_pages(zonelist = 0x0, ?, ?, ?) -004|__alloc_pages_nodemask(gfp_mask = 21200, order = 1, zonelist = -004|0xC11D0940, -005|new_slab(s = 0xE4841E80, ?, node = -1) -006|__slab_alloc.isra.43.constprop.50(s = 0xE4841E80, gfpflags = -006|2148925462, ad -007|kmem_cache_alloc(s = 0xE4841E80, gfpflags = 208) -008|shmem_alloc_inode(?) -009|alloc_inode(sb = 0xE480E800) -010|new_inode_pseudo(?) -011|new_inode(?) -012|shmem_get_inode(sb = 0xE480E800, dir = 0x0, ?, dev = 0, flags = -012|187) -013|shmem_file_setup(?, ?, flags = 187) -014|ashmem_mmap(?, vma = 0xC5D64210) <---- Acquire ashmem_mutex -015|mmap_region(file = 0xDF8E2C00, addr = 1772974080, len = 233472, -015|flags = 57, -016|sys_mmap_pgoff(addr = 0, len = 230400, prot = 3, flags = 1, fd = -016|157, pgoff -017|ret_fast_syscall(asm) -->|exception -018|NUR:0x40097508(asm) ---|end of frame Avoid this deadlock by using mutex_trylock in ashmem_shrink; if the mutex is already held, do not attempt to shrink. Cc: Greg KH Cc: Android Kernel Team Reported-by: Matt Wagantall Reported-by: Syed Rameez Mustafa Reported-by: Osvaldo Banuelos Reported-by: Subbaraman Narayanamurthy Signed-off-by: Laura Abbott [jstultz: Minor commit message tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ashmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 5bb1283d19cd..8ae130827c56 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -441,7 +441,9 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) if (!(sc->gfp_mask & __GFP_FS)) return SHRINK_STOP; - mutex_lock(&ashmem_mutex); + if (!mutex_trylock(&ashmem_mutex)) + return -1; + list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) { loff_t start = range->pgstart * PAGE_SIZE; loff_t end = (range->pgend + 1) * PAGE_SIZE; -- cgit From 90a2f171383b5ae43b33ab4d9d566b9765622ac7 Mon Sep 17 00:00:00 2001 From: Rom Lemarchand Date: Fri, 29 Jan 2016 22:07:31 -0800 Subject: staging: ashmem: Add missing include Include into ashmem.h to ensure referenced types are defined Cc: Android Kernel Team Cc: Greg KH Signed-off-by: Rom Lemarchand [jstultz: Minor commit message tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/uapi/ashmem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/android/uapi/ashmem.h b/drivers/staging/android/uapi/ashmem.h index ba4743c71d6b..13df42d200b7 100644 --- a/drivers/staging/android/uapi/ashmem.h +++ b/drivers/staging/android/uapi/ashmem.h @@ -13,6 +13,7 @@ #define _UAPI_LINUX_ASHMEM_H #include +#include #define ASHMEM_NAME_LEN 256 -- cgit From cc635da2e2e04efe32bbabc4e390c497d593c97d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 29 Jan 2016 22:07:33 -0800 Subject: staging: lowmemorykiller: Make default lowmemorykiller debug message useful lowmemorykiller debug messages are inscrutable and mostly useful for debugging the lowmemorykiller, not explaining why a process was killed. Make the messages more useful by prefixing them with "lowmemorykiller: " and explaining in more readable terms what was killed, who it was killed for, and why it was killed. The messages now look like: [ 76.997631] lowmemorykiller: Killing 'droid.gallery3d' (2172), adj 1000, [ 76.997635] to free 27436kB on behalf of 'kswapd0' (29) because [ 76.997638] cache 122624kB is below limit 122880kB for oom_score_adj 1000 [ 76.997641] Free memory is -53356kB above reserved A negative number for free memory above reserved means some of the reserved memory has been used and is being regenerated by kswapd, which is likely what called the shrinkers. Cc: Android Kernel Team Cc: Greg KH Signed-off-by: Colin Cross [jstultz: Minor checkpatch tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/lowmemorykiller.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index 8b5a4a82d8b8..4b8a56cda6ca 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -84,6 +84,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) int tasksize; int i; short min_score_adj = OOM_SCORE_ADJ_MAX + 1; + int minfree = 0; int selected_tasksize = 0; short selected_oom_score_adj; int array_size = ARRAY_SIZE(lowmem_adj); @@ -97,8 +98,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (lowmem_minfree_size < array_size) array_size = lowmem_minfree_size; for (i = 0; i < array_size; i++) { - if (other_free < lowmem_minfree[i] && - other_file < lowmem_minfree[i]) { + minfree = lowmem_minfree[i]; + if (other_free < minfree && other_file < minfree) { min_score_adj = lowmem_adj[i]; break; } @@ -153,8 +154,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) selected = p; selected_tasksize = tasksize; selected_oom_score_adj = oom_score_adj; - lowmem_print(2, "select %d (%s), adj %hd, size %d, to kill\n", - p->pid, p->comm, oom_score_adj, tasksize); + lowmem_print(2, "select '%s' (%d), adj %hd, size %d, to kill\n", + p->comm, p->pid, oom_score_adj, tasksize); } if (selected) { task_lock(selected); @@ -167,9 +168,18 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) if (selected->mm) mark_oom_victim(selected); task_unlock(selected); - lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n", - selected->pid, selected->comm, - selected_oom_score_adj, selected_tasksize); + lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" + " to free %ldkB on behalf of '%s' (%d) because\n" + " cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" + " Free memory is %ldkB above reserved\n", + selected->comm, selected->pid, + selected_oom_score_adj, + selected_tasksize * (long)(PAGE_SIZE / 1024), + current->comm, current->pid, + other_file * (long)(PAGE_SIZE / 1024), + minfree * (long)(PAGE_SIZE / 1024), + min_score_adj, + other_free * (long)(PAGE_SIZE / 1024)); lowmem_deathpending_timeout = jiffies + HZ; rem += selected_tasksize; } -- cgit From 1328d8efef17d5e16bd6e9cfe59130a833674534 Mon Sep 17 00:00:00 2001 From: Rajmal Menariya Date: Fri, 29 Jan 2016 22:07:35 -0800 Subject: staging: ion: Set minimum carveout heap allocation order to PAGE_SHIFT In carveout heap, change minimum allocation order from 12 to PAGE_SHIFT. After this change each bit in bitmap (genalloc - General purpose special memory pool) represents one page size memory. Cc: sprd-ind-kernel-group@googlegroups.com Cc: sanjeev.yadav@spreadtrum.com Cc: Colin Cross Cc: Android Kernel Team Cc: Greg KH Cc: Sumit Semwal Signed-off-by: Rajmal Menariya [jstultz: Reworked commit message] Signed-off-by: John Stultz Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_carveout_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c index 9156d8238c97..e702ce6461fc 100644 --- a/drivers/staging/android/ion/ion_carveout_heap.c +++ b/drivers/staging/android/ion/ion_carveout_heap.c @@ -167,7 +167,7 @@ struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data) if (!carveout_heap) return ERR_PTR(-ENOMEM); - carveout_heap->pool = gen_pool_create(12, -1); + carveout_heap->pool = gen_pool_create(PAGE_SHIFT, -1); if (!carveout_heap->pool) { kfree(carveout_heap); return ERR_PTR(-ENOMEM); -- cgit From cd572182bd3d82e270d273b241f29d40b4213111 Mon Sep 17 00:00:00 2001 From: Bopamo Osaisai Date: Fri, 8 Jan 2016 09:15:31 -0800 Subject: Staging: android: Fix brace coding style warning in sync_debug.c This is a patch to the sync_debug.c file that rectifies a brace warning that was found with the checkpatch.pl tool Signed-off-by: Bopamo Osaisai Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync_debug.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index f45d13cdd42b..02a1649a1bd9 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -158,9 +158,8 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) seq_printf(s, "[%p] %s: %s\n", fence, fence->name, sync_status_str(atomic_read(&fence->status))); - for (i = 0; i < fence->num_fences; ++i) { + for (i = 0; i < fence->num_fences; ++i) sync_print_pt(s, fence->cbs[i].sync_pt, true); - } spin_lock_irqsave(&fence->wq.lock, flags); list_for_each_entry(pos, &fence->wq.task_list, task_list) { -- cgit From 2ef230531ee171a475fc3ddad5516dd7e09a8a77 Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Fri, 15 Jan 2016 10:38:19 +0800 Subject: staging: ion : Donnot wakeup kswapd in ion system alloc Since ion alloc can be called by userspace,eg gralloc. When it is called frequently, the efficiency of kswapd is to low. And the reclaimed memory is too lower. In this way, the kswapd can use to much cpu resources. With 3.5GB DMA Zone and 0.5 Normal Zone. pgsteal_kswapd_dma 9364140 pgsteal_kswapd_normal 7071043 pgscan_kswapd_dma 10428250 pgscan_kswapd_normal 37840094 With this change the reclaim ratio has greatly improved 18.9% -> 72.5% Signed-off-by: Chen Feng Signed-off-by: Lu bing Reviewed-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_system_heap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index d4c3e5512dd5..b69dfc706440 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -27,7 +27,7 @@ #include "ion_priv.h" static gfp_t high_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN | - __GFP_NORETRY) & ~__GFP_DIRECT_RECLAIM; + __GFP_NORETRY) & ~__GFP_RECLAIM; static gfp_t low_order_gfp_flags = (GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN); static const unsigned int orders[] = {8, 4, 0}; static const int num_orders = ARRAY_SIZE(orders); -- cgit From 70bc916b2c80913753fb188d4daee50a64d21ba0 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Thu, 21 Jan 2016 11:57:47 +0000 Subject: staging: android: ion: Set the length of the DMA sg entries in buffer ion_buffer_create() will allocate a buffer and then create a DMA mapping for it, but it forgot to set the length of the page entries. Signed-off-by: Liviu Dudau Signed-off-by: Jon Medhurst Acked-by: Laura Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index e237e9f3312d..df560216d702 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -251,8 +251,10 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap, * memory coming from the heaps is ready for dma, ie if it has a * cached mapping that mapping has been invalidated */ - for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) + for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) { sg_dma_address(sg) = sg_phys(sg); + sg_dma_len(sg) = sg->length; + } mutex_lock(&dev->buffer_lock); ion_buffer_add(dev, buffer); mutex_unlock(&dev->buffer_lock); -- cgit From a906d6931f3ccaf7de805643190765ddd7378e27 Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Mon, 1 Feb 2016 14:04:02 +0800 Subject: android: binder: Sanity check at binder ioctl Sanity check at binder ioctl function, Only allow the shared mm_struct to use the same binder-object to do binder operate. And add proc->vma_vm_mm = current->mm at the open function. The libbinder do ioctl before mmap called. V2: Fix compile error for error commit V3: Change the condition to proc->vma_vm_mm Signed-off-by: Chen Feng Signed-off-by: Wei Dong Signed-off-by: Junmin Zhao Reviewed-by: Zhuangluan Su Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a39e85f9efa9..f080a8b7659b 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2737,6 +2737,10 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /*pr_info("binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/ + if (unlikely(current->mm != proc->vma_vm_mm)) { + pr_err("current mm mismatch proc mm\n"); + return -EINVAL; + } trace_binder_ioctl(cmd, arg); ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); @@ -2951,6 +2955,7 @@ static int binder_open(struct inode *nodp, struct file *filp) return -ENOMEM; get_task_struct(current); proc->tsk = current; + proc->vma_vm_mm = current->mm; INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); -- cgit From 9b32381ca50f5268edae8eac009a74b55df608d2 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:14 -0200 Subject: staging/android: fix sync framework documentation Updates comments about functions and structures. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.h | 45 ++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index afa0752275a7..7a4d8209bb0b 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -110,15 +110,9 @@ struct sync_timeline { /** * struct sync_pt - sync point - * @fence: base fence class + * @base: base fence class * @child_list: membership in sync_timeline.child_list_head * @active_list: membership in sync_timeline.active_list_head - * @signaled_list: membership in temporary signaled_list on stack - * @fence: sync_fence to which the sync_pt belongs - * @pt_list: membership in sync_fence.pt_list_head - * @status: 1: signaled, 0:active, <0: error - * @timestamp: time which sync_pt status transitioned from active to - * signaled or error. */ struct sync_pt { struct fence base; @@ -144,12 +138,11 @@ struct sync_fence_cb { * @file: file representing this fence * @kref: reference count on fence. * @name: name of sync_fence. Useful for debugging - * @pt_list_head: list of sync_pts in the fence. immutable once fence - * is created - * @status: 0: signaled, >0:active, <0: error - * - * @wq: wait queue for fence signaling * @sync_fence_list: membership in global fence list + * @num_fences number of sync_pts in the fence + * @wq: wait queue for fence signaling + * @status: 0: signaled, >0:active, <0: error + * @cbs: sync_pts callback information */ struct sync_fence { struct file *file; @@ -172,9 +165,8 @@ typedef void (*sync_callback_t)(struct sync_fence *fence, /** * struct sync_fence_waiter - metadata for asynchronous waiter on a fence - * @waiter_list: membership in sync_fence.waiter_list_head + * @work: wait_queue for the fence waiter * @callback: function pointer to call when fence signals - * @callback_data: pointer to pass to @callback */ struct sync_fence_waiter { wait_queue_t work; @@ -200,7 +192,8 @@ static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, * * Creates a new sync_timeline which will use the implementation specified by * @ops. @size bytes will be allocated allowing for implementation specific - * data to be kept after the generic sync_timeline struct. + * data to be kept after the generic sync_timeline struct. Returns the + * sync_timeline object or NULL in case of error. */ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, int size, const char *name); @@ -231,7 +224,8 @@ void sync_timeline_signal(struct sync_timeline *obj); * * Creates a new sync_pt as a child of @parent. @size bytes will be * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. + * the generic sync_timeline struct. Returns the sync_pt object or + * NULL in case of error. */ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); @@ -275,7 +269,8 @@ struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt); * @b: fence b * * Creates a new fence which contains copies of all the sync_pts in both - * @a and @b. @a and @b remain valid, independent fences. + * @a and @b. @a and @b remain valid, independent fences. Returns the + * new merged fence or NULL in case of error. */ struct sync_fence *sync_fence_merge(const char *name, struct sync_fence *a, struct sync_fence *b); @@ -285,7 +280,7 @@ struct sync_fence *sync_fence_merge(const char *name, * @fd: fd referencing a fence * * Ensures @fd references a valid fence, increments the refcount of the backing - * file, and returns the fence. + * file, and returns the fence. Returns the fence or NULL in case of error. */ struct sync_fence *sync_fence_fdget(int fd); @@ -313,10 +308,10 @@ void sync_fence_install(struct sync_fence *fence, int fd); * @fence: fence to wait on * @waiter: waiter callback struck * - * Returns 1 if @fence has already signaled. - * * Registers a callback to be called when @fence signals or has an error. * @waiter should be initialized with sync_fence_waiter_init(). + * + * Returns 1 if @fence has already signaled, 0 if not or <0 if error. */ int sync_fence_wait_async(struct sync_fence *fence, struct sync_fence_waiter *waiter); @@ -326,11 +321,11 @@ int sync_fence_wait_async(struct sync_fence *fence, * @fence: fence to wait on * @waiter: waiter callback struck * - * returns 0 if waiter was removed from fence's async waiter list. - * returns -ENOENT if waiter was not found on fence's async waiter list. - * * Cancels a previously registered async wait. Will fail gracefully if * @waiter was never registered or if @fence has already signaled @waiter. + * + * Returns 0 if waiter was removed from fence's async waiter list. + * Returns -ENOENT if waiter was not found on fence's async waiter list. */ int sync_fence_cancel_async(struct sync_fence *fence, struct sync_fence_waiter *waiter); @@ -341,7 +336,9 @@ int sync_fence_cancel_async(struct sync_fence *fence, * @tiemout: timeout in ms * * Wait for @fence to be signaled or have an error. Waits indefinitely - * if @timeout < 0 + * if @timeout < 0. + * + * Returns 0 if fence signaled, > 0 if it is still active and <0 on error */ int sync_fence_wait(struct sync_fence *fence, long timeout); -- cgit From 3179dd927a9338e01ed0261e0bba080b6b8bdbaa Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:15 -0200 Subject: staging/android: sync: remove interfaces that are not used These interfaces are not used nor have plans to be used in the near future so remove them for a cleaner solution before de-staging the sync framework. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 56 ------------------------------------ drivers/staging/android/sync.h | 50 -------------------------------- drivers/staging/android/sync_debug.c | 15 ---------- 3 files changed, 121 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index ed43796b5b58..7a84f8853a8e 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -317,62 +317,6 @@ struct sync_fence *sync_fence_merge(const char *name, } EXPORT_SYMBOL(sync_fence_merge); -int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, - int wake_flags, void *key) -{ - struct sync_fence_waiter *wait; - - wait = container_of(curr, struct sync_fence_waiter, work); - list_del_init(&wait->work.task_list); - - wait->callback(wait->work.private, wait); - return 1; -} - -int sync_fence_wait_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter) -{ - int err = atomic_read(&fence->status); - unsigned long flags; - - if (err < 0) - return err; - - if (!err) - return 1; - - init_waitqueue_func_entry(&waiter->work, sync_fence_wake_up_wq); - waiter->work.private = fence; - - spin_lock_irqsave(&fence->wq.lock, flags); - err = atomic_read(&fence->status); - if (err > 0) - __add_wait_queue_tail(&fence->wq, &waiter->work); - spin_unlock_irqrestore(&fence->wq.lock, flags); - - if (err < 0) - return err; - - return !err; -} -EXPORT_SYMBOL(sync_fence_wait_async); - -int sync_fence_cancel_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&fence->wq.lock, flags); - if (!list_empty(&waiter->work.task_list)) - list_del_init(&waiter->work.task_list); - else - ret = -ENOENT; - spin_unlock_irqrestore(&fence->wq.lock, flags); - return ret; -} -EXPORT_SYMBOL(sync_fence_cancel_async); - int sync_fence_wait(struct sync_fence *fence, long timeout) { long ret; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 7a4d8209bb0b..e0865b94c8f7 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -159,27 +159,6 @@ struct sync_fence { struct sync_fence_cb cbs[]; }; -struct sync_fence_waiter; -typedef void (*sync_callback_t)(struct sync_fence *fence, - struct sync_fence_waiter *waiter); - -/** - * struct sync_fence_waiter - metadata for asynchronous waiter on a fence - * @work: wait_queue for the fence waiter - * @callback: function pointer to call when fence signals - */ -struct sync_fence_waiter { - wait_queue_t work; - sync_callback_t callback; -}; - -static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, - sync_callback_t callback) -{ - INIT_LIST_HEAD(&waiter->work.task_list); - waiter->callback = callback; -} - /* * API for sync_timeline implementers */ @@ -303,33 +282,6 @@ void sync_fence_put(struct sync_fence *fence); */ void sync_fence_install(struct sync_fence *fence, int fd); -/** - * sync_fence_wait_async() - registers and async wait on the fence - * @fence: fence to wait on - * @waiter: waiter callback struck - * - * Registers a callback to be called when @fence signals or has an error. - * @waiter should be initialized with sync_fence_waiter_init(). - * - * Returns 1 if @fence has already signaled, 0 if not or <0 if error. - */ -int sync_fence_wait_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter); - -/** - * sync_fence_cancel_async() - cancels an async wait - * @fence: fence to wait on - * @waiter: waiter callback struck - * - * Cancels a previously registered async wait. Will fail gracefully if - * @waiter was never registered or if @fence has already signaled @waiter. - * - * Returns 0 if waiter was removed from fence's async waiter list. - * Returns -ENOENT if waiter was not found on fence's async waiter list. - */ -int sync_fence_cancel_async(struct sync_fence *fence, - struct sync_fence_waiter *waiter); - /** * sync_fence_wait() - wait on fence * @fence: fence to wait on @@ -357,7 +309,5 @@ void sync_dump(void); # define sync_fence_debug_remove(fence) # define sync_dump() #endif -int sync_fence_wake_up_wq(wait_queue_t *curr, unsigned mode, - int wake_flags, void *key); #endif /* _LINUX_SYNC_H */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 02a1649a1bd9..c7ee98f3b851 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -151,8 +151,6 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) { - wait_queue_t *pos; - unsigned long flags; int i; seq_printf(s, "[%p] %s: %s\n", fence, fence->name, @@ -160,19 +158,6 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) for (i = 0; i < fence->num_fences; ++i) sync_print_pt(s, fence->cbs[i].sync_pt, true); - - spin_lock_irqsave(&fence->wq.lock, flags); - list_for_each_entry(pos, &fence->wq.task_list, task_list) { - struct sync_fence_waiter *waiter; - - if (pos->func != &sync_fence_wake_up_wq) - continue; - - waiter = container_of(pos, struct sync_fence_waiter, work); - - seq_printf(s, "waiter %pF\n", waiter->callback); - } - spin_unlock_irqrestore(&fence->wq.lock, flags); } static int sync_debugfs_show(struct seq_file *s, void *unused) -- cgit From 27e3917ab996cfcf68d0261006bd3d116e969402 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:16 -0200 Subject: staging/android: remove not used sync_timeline ops .dup and .compare are not used by the sync framework, so remove them from sw_sync. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 29 +---------------------------- drivers/staging/android/sync.c | 6 ------ drivers/staging/android/sync.h | 19 ------------------- 3 files changed, 1 insertion(+), 53 deletions(-) diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index c4ff1679ebbc..566dcdc7e236 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -25,14 +25,6 @@ #include "sw_sync.h" -static int sw_sync_cmp(u32 a, u32 b) -{ - if (a == b) - return 0; - - return ((s32)a - (s32)b) < 0 ? -1 : 1; -} - struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) { struct sw_sync_pt *pt; @@ -46,30 +38,13 @@ struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) } EXPORT_SYMBOL(sw_sync_pt_create); -static struct sync_pt *sw_sync_pt_dup(struct sync_pt *sync_pt) -{ - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; - struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); - - return (struct sync_pt *)sw_sync_pt_create(obj, pt->value); -} - static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt) { struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; struct sw_sync_timeline *obj = (struct sw_sync_timeline *)sync_pt_parent(sync_pt); - return sw_sync_cmp(obj->value, pt->value) >= 0; -} - -static int sw_sync_pt_compare(struct sync_pt *a, struct sync_pt *b) -{ - struct sw_sync_pt *pt_a = (struct sw_sync_pt *)a; - struct sw_sync_pt *pt_b = (struct sw_sync_pt *)b; - - return sw_sync_cmp(pt_a->value, pt_b->value); + return (pt->value > obj->value) ? 0 : 1; } static int sw_sync_fill_driver_data(struct sync_pt *sync_pt, @@ -103,9 +78,7 @@ static void sw_sync_pt_value_str(struct sync_pt *sync_pt, static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", - .dup = sw_sync_pt_dup, .has_signaled = sw_sync_pt_has_signaled, - .compare = sw_sync_pt_compare, .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, .pt_value_str = sw_sync_pt_value_str, diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 7a84f8853a8e..f4d9bcddb6f8 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -68,9 +68,6 @@ static void sync_timeline_free(struct kref *kref) sync_timeline_debug_remove(obj); - if (obj->ops->release_obj) - obj->ops->release_obj(obj); - kfree(obj); } @@ -383,9 +380,6 @@ static void android_fence_release(struct fence *fence) list_del(&pt->active_list); spin_unlock_irqrestore(fence->lock, flags); - if (parent->ops->free_pt) - parent->ops->free_pt(pt); - sync_timeline_put(parent); fence_free(&pt->base); } diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index e0865b94c8f7..b47058fbe8af 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -30,17 +30,10 @@ struct sync_fence; /** * struct sync_timeline_ops - sync object implementation ops * @driver_name: name of the implementation - * @dup: duplicate a sync_pt * @has_signaled: returns: * 1 if pt has signaled * 0 if pt has not signaled * <0 on error - * @compare: returns: - * 1 if b will signal before a - * 0 if a and b will signal at the same time - * -1 if a will signal before b - * @free_pt: called before sync_pt is freed - * @release_obj: called before sync_timeline is freed * @fill_driver_data: write implementation specific driver data to data. * should return an error if there is not enough room * as specified by size. This information is returned @@ -51,21 +44,9 @@ struct sync_fence; struct sync_timeline_ops { const char *driver_name; - /* required */ - struct sync_pt * (*dup)(struct sync_pt *pt); - /* required */ int (*has_signaled)(struct sync_pt *pt); - /* required */ - int (*compare)(struct sync_pt *a, struct sync_pt *b); - - /* optional */ - void (*free_pt)(struct sync_pt *sync_pt); - - /* optional */ - void (*release_obj)(struct sync_timeline *sync_timeline); - /* optional */ int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); -- cgit From 8a0044846115e74552b671a7073cffeec14b9316 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:17 -0200 Subject: staging/android: create a 'sync' dir for debugfs information Creates the 'sync' dir on debugfs root dir and move the 'sync' file to sync/info. This is the preparation to add more debug info and control. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync_debug.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index c7ee98f3b851..4dc6e03d6487 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -30,6 +31,8 @@ #ifdef CONFIG_DEBUG_FS +static struct dentry *dbgfs; + static LIST_HEAD(sync_timeline_list_head); static DEFINE_SPINLOCK(sync_timeline_list_lock); static LIST_HEAD(sync_fence_list_head); @@ -192,13 +195,13 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) return 0; } -static int sync_debugfs_open(struct inode *inode, struct file *file) +static int sync_info_debugfs_open(struct inode *inode, struct file *file) { return single_open(file, sync_debugfs_show, inode->i_private); } -static const struct file_operations sync_debugfs_fops = { - .open = sync_debugfs_open, +static const struct file_operations sync_info_debugfs_fops = { + .open = sync_info_debugfs_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, @@ -206,11 +209,21 @@ static const struct file_operations sync_debugfs_fops = { static __init int sync_debugfs_init(void) { - debugfs_create_file("sync", S_IRUGO, NULL, NULL, &sync_debugfs_fops); + dbgfs = debugfs_create_dir("sync", NULL); + + debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops); + return 0; } late_initcall(sync_debugfs_init); +static __exit void sync_debugfs_exit(void) +{ + if (dbgfs) + debugfs_remove_recursive(dbgfs); +} +module_exit(sync_debugfs_exit); + #define DUMP_CHUNK 256 static char sync_dump_buf[64 * 1024]; void sync_dump(void) -- cgit From a44eb74cd413fa62733d7df89942eabaf26176eb Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:18 -0200 Subject: staging/android: move SW_SYNC_USER to a debugfs file This remove CONFIG_SW_SYNC_USER and instead compile the sw_sync file into debugpfs under /sync/sw_sync. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/Kconfig | 9 --- drivers/staging/android/sw_sync.c | 129 ----------------------------------- drivers/staging/android/sync_debug.c | 118 +++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 139 deletions(-) diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 42b15126aa06..bd90d2002afb 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -57,15 +57,6 @@ config SW_SYNC synchronization. Useful when there is no hardware primitive backing the synchronization. -config SW_SYNC_USER - bool "Userspace API for SW_SYNC" - default n - depends on SW_SYNC - ---help--- - Provides a user space API to the sw sync object. - *WARNING* improper use of this can result in deadlocking kernel - drivers from userspace. - source "drivers/staging/android/ion/Kconfig" endif # if ANDROID diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 566dcdc7e236..f491dbce5696 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -102,132 +102,3 @@ void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc) sync_timeline_signal(&obj->obj); } EXPORT_SYMBOL(sw_sync_timeline_inc); - -#ifdef CONFIG_SW_SYNC_USER -/* *WARNING* - * - * improper use of this can result in deadlocking kernel drivers from userspace. - */ - -/* opening sw_sync create a new sync obj */ -static int sw_sync_open(struct inode *inode, struct file *file) -{ - struct sw_sync_timeline *obj; - char task_comm[TASK_COMM_LEN]; - - get_task_comm(task_comm, current); - - obj = sw_sync_timeline_create(task_comm); - if (!obj) - return -ENOMEM; - - file->private_data = obj; - - return 0; -} - -static int sw_sync_release(struct inode *inode, struct file *file) -{ - struct sw_sync_timeline *obj = file->private_data; - - sync_timeline_destroy(&obj->obj); - return 0; -} - -static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, - unsigned long arg) -{ - int fd = get_unused_fd_flags(O_CLOEXEC); - int err; - struct sync_pt *pt; - struct sync_fence *fence; - struct sw_sync_create_fence_data data; - - if (fd < 0) - return fd; - - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { - err = -EFAULT; - goto err; - } - - pt = sw_sync_pt_create(obj, data.value); - if (!pt) { - err = -ENOMEM; - goto err; - } - - data.name[sizeof(data.name) - 1] = '\0'; - fence = sync_fence_create(data.name, pt); - if (!fence) { - sync_pt_free(pt); - err = -ENOMEM; - goto err; - } - - data.fence = fd; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - sync_fence_put(fence); - err = -EFAULT; - goto err; - } - - sync_fence_install(fence, fd); - - return 0; - -err: - put_unused_fd(fd); - return err; -} - -static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg) -{ - u32 value; - - if (copy_from_user(&value, (void __user *)arg, sizeof(value))) - return -EFAULT; - - sw_sync_timeline_inc(obj, value); - - return 0; -} - -static long sw_sync_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct sw_sync_timeline *obj = file->private_data; - - switch (cmd) { - case SW_SYNC_IOC_CREATE_FENCE: - return sw_sync_ioctl_create_fence(obj, arg); - - case SW_SYNC_IOC_INC: - return sw_sync_ioctl_inc(obj, arg); - - default: - return -ENOTTY; - } -} - -static const struct file_operations sw_sync_fops = { - .owner = THIS_MODULE, - .open = sw_sync_open, - .release = sw_sync_release, - .unlocked_ioctl = sw_sync_ioctl, - .compat_ioctl = sw_sync_ioctl, -}; - -static struct miscdevice sw_sync_dev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "sw_sync", - .fops = &sw_sync_fops, -}; - -static int __init sw_sync_device_init(void) -{ - return misc_register(&sw_sync_dev); -} -device_initcall(sw_sync_device_init); - -#endif /* CONFIG_SW_SYNC_USER */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 4dc6e03d6487..33dec4219e99 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -27,7 +27,7 @@ #include #include #include -#include "sync.h" +#include "sw_sync.h" #ifdef CONFIG_DEBUG_FS @@ -207,11 +207,127 @@ static const struct file_operations sync_info_debugfs_fops = { .release = single_release, }; +/* + * *WARNING* + * + * improper use of this can result in deadlocking kernel drivers from userspace. + */ + +/* opening sw_sync create a new sync obj */ +static int sw_sync_debugfs_open(struct inode *inode, struct file *file) +{ + struct sw_sync_timeline *obj; + char task_comm[TASK_COMM_LEN]; + + get_task_comm(task_comm, current); + + obj = sw_sync_timeline_create(task_comm); + if (!obj) + return -ENOMEM; + + file->private_data = obj; + + return 0; +} + +static int sw_sync_debugfs_release(struct inode *inode, struct file *file) +{ + struct sw_sync_timeline *obj = file->private_data; + + sync_timeline_destroy(&obj->obj); + return 0; +} + +static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, + unsigned long arg) +{ + int fd = get_unused_fd_flags(O_CLOEXEC); + int err; + struct sync_pt *pt; + struct sync_fence *fence; + struct sw_sync_create_fence_data data; + + if (fd < 0) + return fd; + + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + err = -EFAULT; + goto err; + } + + pt = sw_sync_pt_create(obj, data.value); + if (!pt) { + err = -ENOMEM; + goto err; + } + + data.name[sizeof(data.name) - 1] = '\0'; + fence = sync_fence_create(data.name, pt); + if (!fence) { + sync_pt_free(pt); + err = -ENOMEM; + goto err; + } + + data.fence = fd; + if (copy_to_user((void __user *)arg, &data, sizeof(data))) { + sync_fence_put(fence); + err = -EFAULT; + goto err; + } + + sync_fence_install(fence, fd); + + return 0; + +err: + put_unused_fd(fd); + return err; +} + +static long sw_sync_ioctl_inc(struct sw_sync_timeline *obj, unsigned long arg) +{ + u32 value; + + if (copy_from_user(&value, (void __user *)arg, sizeof(value))) + return -EFAULT; + + sw_sync_timeline_inc(obj, value); + + return 0; +} + +static long sw_sync_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct sw_sync_timeline *obj = file->private_data; + + switch (cmd) { + case SW_SYNC_IOC_CREATE_FENCE: + return sw_sync_ioctl_create_fence(obj, arg); + + case SW_SYNC_IOC_INC: + return sw_sync_ioctl_inc(obj, arg); + + default: + return -ENOTTY; + } +} + +static const struct file_operations sw_sync_debugfs_fops = { + .open = sw_sync_debugfs_open, + .release = sw_sync_debugfs_release, + .unlocked_ioctl = sw_sync_ioctl, + .compat_ioctl = sw_sync_ioctl, +}; + static __init int sync_debugfs_init(void) { dbgfs = debugfs_create_dir("sync", NULL); debugfs_create_file("info", 0444, dbgfs, NULL, &sync_info_debugfs_fops); + debugfs_create_file("sw_sync", 0644, dbgfs, NULL, + &sw_sync_debugfs_fops); return 0; } -- cgit From d7fdb0ae9d115fa14ff3a5382c8a62de41c7786a Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:19 -0200 Subject: staging/android: rename sync_fence to sync_file sync_file has a more close meaning to what a sync_fence really, a struct that represent a file that can be used by userspace to get information on a fence, or wait for it to be signaled. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 254 ++++++++++++++++++----------------- drivers/staging/android/sync.h | 98 +++++++------- drivers/staging/android/sync_debug.c | 59 ++++---- drivers/staging/android/trace/sync.h | 10 +- drivers/staging/android/uapi/sync.h | 14 +- 5 files changed, 221 insertions(+), 214 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index f4d9bcddb6f8..8cccdf94ce77 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -32,7 +32,7 @@ #include "trace/sync.h" static const struct fence_ops android_fence_ops; -static const struct file_operations sync_fence_fops; +static const struct file_operations sync_file_fops; struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, int size, const char *name) @@ -147,80 +147,81 @@ void sync_pt_free(struct sync_pt *pt) } EXPORT_SYMBOL(sync_pt_free); -static struct sync_fence *sync_fence_alloc(int size, const char *name) +static struct sync_file *sync_file_alloc(int size, const char *name) { - struct sync_fence *fence; + struct sync_file *sync_file; - fence = kzalloc(size, GFP_KERNEL); - if (!fence) + sync_file = kzalloc(size, GFP_KERNEL); + if (!sync_file) return NULL; - fence->file = anon_inode_getfile("sync_fence", &sync_fence_fops, - fence, 0); - if (IS_ERR(fence->file)) + sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops, + sync_file, 0); + if (IS_ERR(sync_file->file)) goto err; - kref_init(&fence->kref); - strlcpy(fence->name, name, sizeof(fence->name)); + kref_init(&sync_file->kref); + strlcpy(sync_file->name, name, sizeof(sync_file->name)); - init_waitqueue_head(&fence->wq); + init_waitqueue_head(&sync_file->wq); - return fence; + return sync_file; err: - kfree(fence); + kfree(sync_file); return NULL; } static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) { - struct sync_fence_cb *check; - struct sync_fence *fence; + struct sync_file_cb *check; + struct sync_file *sync_file; - check = container_of(cb, struct sync_fence_cb, cb); - fence = check->fence; + check = container_of(cb, struct sync_file_cb, cb); + sync_file = check->sync_file; - if (atomic_dec_and_test(&fence->status)) - wake_up_all(&fence->wq); + if (atomic_dec_and_test(&sync_file->status)) + wake_up_all(&sync_file->wq); } /* TODO: implement a create which takes more that one sync_pt */ -struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt) +struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) { - struct sync_fence *fence; + struct sync_file *sync_file; - fence = sync_fence_alloc(offsetof(struct sync_fence, cbs[1]), name); - if (!fence) + sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1]), + name); + if (!sync_file) return NULL; - fence->num_fences = 1; - atomic_set(&fence->status, 1); + sync_file->num_fences = 1; + atomic_set(&sync_file->status, 1); - fence->cbs[0].sync_pt = pt; - fence->cbs[0].fence = fence; - if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func)) - atomic_dec(&fence->status); + sync_file->cbs[0].sync_pt = pt; + sync_file->cbs[0].sync_file = sync_file; + if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) + atomic_dec(&sync_file->status); - sync_fence_debug_add(fence); + sync_file_debug_add(sync_file); - return fence; + return sync_file; } -EXPORT_SYMBOL(sync_fence_create_dma); +EXPORT_SYMBOL(sync_file_create_dma); -struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt) +struct sync_file *sync_file_create(const char *name, struct sync_pt *pt) { - return sync_fence_create_dma(name, &pt->base); + return sync_file_create_dma(name, &pt->base); } -EXPORT_SYMBOL(sync_fence_create); +EXPORT_SYMBOL(sync_file_create); -struct sync_fence *sync_fence_fdget(int fd) +struct sync_file *sync_file_fdget(int fd) { struct file *file = fget(fd); if (!file) return NULL; - if (file->f_op != &sync_fence_fops) + if (file->f_op != &sync_file_fops) goto err; return file->private_data; @@ -229,70 +230,71 @@ err: fput(file); return NULL; } -EXPORT_SYMBOL(sync_fence_fdget); +EXPORT_SYMBOL(sync_file_fdget); -void sync_fence_put(struct sync_fence *fence) +void sync_file_put(struct sync_file *sync_file) { - fput(fence->file); + fput(sync_file->file); } -EXPORT_SYMBOL(sync_fence_put); +EXPORT_SYMBOL(sync_file_put); -void sync_fence_install(struct sync_fence *fence, int fd) +void sync_file_install(struct sync_file *sync_file, int fd) { - fd_install(fd, fence->file); + fd_install(fd, sync_file->file); } -EXPORT_SYMBOL(sync_fence_install); +EXPORT_SYMBOL(sync_file_install); -static void sync_fence_add_pt(struct sync_fence *fence, - int *i, struct fence *pt) +static void sync_file_add_pt(struct sync_file *sync_file, int *i, + struct fence *pt) { - fence->cbs[*i].sync_pt = pt; - fence->cbs[*i].fence = fence; + sync_file->cbs[*i].sync_pt = pt; + sync_file->cbs[*i].sync_file = sync_file; - if (!fence_add_callback(pt, &fence->cbs[*i].cb, fence_check_cb_func)) { + if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, + fence_check_cb_func)) { fence_get(pt); (*i)++; } } -struct sync_fence *sync_fence_merge(const char *name, - struct sync_fence *a, struct sync_fence *b) +struct sync_file *sync_file_merge(const char *name, + struct sync_file *a, struct sync_file *b) { int num_fences = a->num_fences + b->num_fences; - struct sync_fence *fence; + struct sync_file *sync_file; int i, i_a, i_b; - unsigned long size = offsetof(struct sync_fence, cbs[num_fences]); + unsigned long size = offsetof(struct sync_file, cbs[num_fences]); - fence = sync_fence_alloc(size, name); - if (!fence) + sync_file = sync_file_alloc(size, name); + if (!sync_file) return NULL; - atomic_set(&fence->status, num_fences); + atomic_set(&sync_file->status, num_fences); /* - * Assume sync_fence a and b are both ordered and have no + * Assume sync_file a and b are both ordered and have no * duplicates with the same context. * - * If a sync_fence can only be created with sync_fence_merge - * and sync_fence_create, this is a reasonable assumption. + * If a sync_file can only be created with sync_file_merge + * and sync_file_create, this is a reasonable assumption. */ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { struct fence *pt_a = a->cbs[i_a].sync_pt; struct fence *pt_b = b->cbs[i_b].sync_pt; if (pt_a->context < pt_b->context) { - sync_fence_add_pt(fence, &i, pt_a); + sync_file_add_pt(sync_file, &i, pt_a); i_a++; } else if (pt_a->context > pt_b->context) { - sync_fence_add_pt(fence, &i, pt_b); + sync_file_add_pt(sync_file, &i, pt_b); i_b++; } else { if (pt_a->seqno - pt_b->seqno <= INT_MAX) - sync_fence_add_pt(fence, &i, pt_a); + sync_file_add_pt(sync_file, &i, pt_a); else - sync_fence_add_pt(fence, &i, pt_b); + sync_file_add_pt(sync_file, &i, pt_b); i_a++; i_b++; @@ -300,21 +302,21 @@ struct sync_fence *sync_fence_merge(const char *name, } for (; i_a < a->num_fences; i_a++) - sync_fence_add_pt(fence, &i, a->cbs[i_a].sync_pt); + sync_file_add_pt(sync_file, &i, a->cbs[i_a].sync_pt); for (; i_b < b->num_fences; i_b++) - sync_fence_add_pt(fence, &i, b->cbs[i_b].sync_pt); + sync_file_add_pt(sync_file, &i, b->cbs[i_b].sync_pt); if (num_fences > i) - atomic_sub(num_fences - i, &fence->status); - fence->num_fences = i; + atomic_sub(num_fences - i, &sync_file->status); + sync_file->num_fences = i; - sync_fence_debug_add(fence); - return fence; + sync_file_debug_add(sync_file); + return sync_file; } -EXPORT_SYMBOL(sync_fence_merge); +EXPORT_SYMBOL(sync_file_merge); -int sync_fence_wait(struct sync_fence *fence, long timeout) +int sync_file_wait(struct sync_file *sync_file, long timeout) { long ret; int i; @@ -324,33 +326,33 @@ int sync_fence_wait(struct sync_fence *fence, long timeout) else timeout = msecs_to_jiffies(timeout); - trace_sync_wait(fence, 1); - for (i = 0; i < fence->num_fences; ++i) - trace_sync_pt(fence->cbs[i].sync_pt); - ret = wait_event_interruptible_timeout(fence->wq, - atomic_read(&fence->status) <= 0, + trace_sync_wait(sync_file, 1); + for (i = 0; i < sync_file->num_fences; ++i) + trace_sync_pt(sync_file->cbs[i].sync_pt); + ret = wait_event_interruptible_timeout(sync_file->wq, + atomic_read(&sync_file->status) <= 0, timeout); - trace_sync_wait(fence, 0); + trace_sync_wait(sync_file, 0); if (ret < 0) { return ret; } else if (ret == 0) { if (timeout) { - pr_info("fence timeout on [%p] after %dms\n", fence, - jiffies_to_msecs(timeout)); + pr_info("sync_file timeout on [%p] after %dms\n", + sync_file, jiffies_to_msecs(timeout)); sync_dump(); } return -ETIME; } - ret = atomic_read(&fence->status); + ret = atomic_read(&sync_file->status); if (ret) { - pr_info("fence error %ld on [%p]\n", ret, fence); + pr_info("sync_file error %ld on [%p]\n", ret, sync_file); sync_dump(); } return ret; } -EXPORT_SYMBOL(sync_fence_wait); +EXPORT_SYMBOL(sync_file_wait); static const char *android_fence_get_driver_name(struct fence *fence) { @@ -459,37 +461,39 @@ static const struct fence_ops android_fence_ops = { .timeline_value_str = android_fence_timeline_value_str, }; -static void sync_fence_free(struct kref *kref) +static void sync_file_free(struct kref *kref) { - struct sync_fence *fence = container_of(kref, struct sync_fence, kref); + struct sync_file *sync_file = container_of(kref, struct sync_file, + kref); int i; - for (i = 0; i < fence->num_fences; ++i) { - fence_remove_callback(fence->cbs[i].sync_pt, &fence->cbs[i].cb); - fence_put(fence->cbs[i].sync_pt); + for (i = 0; i < sync_file->num_fences; ++i) { + fence_remove_callback(sync_file->cbs[i].sync_pt, + &sync_file->cbs[i].cb); + fence_put(sync_file->cbs[i].sync_pt); } - kfree(fence); + kfree(sync_file); } -static int sync_fence_release(struct inode *inode, struct file *file) +static int sync_file_release(struct inode *inode, struct file *file) { - struct sync_fence *fence = file->private_data; + struct sync_file *sync_file = file->private_data; - sync_fence_debug_remove(fence); + sync_file_debug_remove(sync_file); - kref_put(&fence->kref, sync_fence_free); + kref_put(&sync_file->kref, sync_file_free); return 0; } -static unsigned int sync_fence_poll(struct file *file, poll_table *wait) +static unsigned int sync_file_poll(struct file *file, poll_table *wait) { - struct sync_fence *fence = file->private_data; + struct sync_file *sync_file = file->private_data; int status; - poll_wait(file, &fence->wq, wait); + poll_wait(file, &sync_file->wq, wait); - status = atomic_read(&fence->status); + status = atomic_read(&sync_file->status); if (!status) return POLLIN; @@ -498,21 +502,23 @@ static unsigned int sync_fence_poll(struct file *file, poll_table *wait) return 0; } -static long sync_fence_ioctl_wait(struct sync_fence *fence, unsigned long arg) +static long sync_file_ioctl_wait(struct sync_file *sync_file, + unsigned long arg) { __s32 value; if (copy_from_user(&value, (void __user *)arg, sizeof(value))) return -EFAULT; - return sync_fence_wait(fence, value); + return sync_file_wait(sync_file, value); } -static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) +static long sync_file_ioctl_merge(struct sync_file *sync_file, + unsigned long arg) { int fd = get_unused_fd_flags(O_CLOEXEC); int err; - struct sync_fence *fence2, *fence3; + struct sync_file *fence2, *fence3; struct sync_merge_data data; if (fd < 0) @@ -523,14 +529,14 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) goto err_put_fd; } - fence2 = sync_fence_fdget(data.fd2); + fence2 = sync_file_fdget(data.fd2); if (!fence2) { err = -ENOENT; goto err_put_fd; } data.name[sizeof(data.name) - 1] = '\0'; - fence3 = sync_fence_merge(data.name, fence, fence2); + fence3 = sync_file_merge(data.name, sync_file, fence2); if (!fence3) { err = -ENOMEM; goto err_put_fence2; @@ -542,15 +548,15 @@ static long sync_fence_ioctl_merge(struct sync_fence *fence, unsigned long arg) goto err_put_fence3; } - sync_fence_install(fence3, fd); - sync_fence_put(fence2); + sync_file_install(fence3, fd); + sync_file_put(fence2); return 0; err_put_fence3: - sync_fence_put(fence3); + sync_file_put(fence3); err_put_fence2: - sync_fence_put(fence2); + sync_file_put(fence2); err_put_fd: put_unused_fd(fd); @@ -589,10 +595,10 @@ static int sync_fill_pt_info(struct fence *fence, void *data, int size) return info->len; } -static long sync_fence_ioctl_fence_info(struct sync_fence *fence, +static long sync_file_ioctl_fence_info(struct sync_file *sync_file, unsigned long arg) { - struct sync_fence_info_data *data; + struct sync_file_info_data *data; __u32 size; __u32 len = 0; int ret, i; @@ -600,7 +606,7 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, if (copy_from_user(&size, (void __user *)arg, sizeof(size))) return -EFAULT; - if (size < sizeof(struct sync_fence_info_data)) + if (size < sizeof(struct sync_file_info_data)) return -EINVAL; if (size > 4096) @@ -610,15 +616,15 @@ static long sync_fence_ioctl_fence_info(struct sync_fence *fence, if (!data) return -ENOMEM; - strlcpy(data->name, fence->name, sizeof(data->name)); - data->status = atomic_read(&fence->status); + strlcpy(data->name, sync_file->name, sizeof(data->name)); + data->status = atomic_read(&sync_file->status); if (data->status >= 0) data->status = !data->status; - len = sizeof(struct sync_fence_info_data); + len = sizeof(struct sync_file_info_data); - for (i = 0; i < fence->num_fences; ++i) { - struct fence *pt = fence->cbs[i].sync_pt; + for (i = 0; i < sync_file->num_fences; ++i) { + struct fence *pt = sync_file->cbs[i].sync_pt; ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); @@ -641,30 +647,30 @@ out: return ret; } -static long sync_fence_ioctl(struct file *file, unsigned int cmd, +static long sync_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct sync_fence *fence = file->private_data; + struct sync_file *sync_file = file->private_data; switch (cmd) { case SYNC_IOC_WAIT: - return sync_fence_ioctl_wait(fence, arg); + return sync_file_ioctl_wait(sync_file, arg); case SYNC_IOC_MERGE: - return sync_fence_ioctl_merge(fence, arg); + return sync_file_ioctl_merge(sync_file, arg); case SYNC_IOC_FENCE_INFO: - return sync_fence_ioctl_fence_info(fence, arg); + return sync_file_ioctl_fence_info(sync_file, arg); default: return -ENOTTY; } } -static const struct file_operations sync_fence_fops = { - .release = sync_fence_release, - .poll = sync_fence_poll, - .unlocked_ioctl = sync_fence_ioctl, - .compat_ioctl = sync_fence_ioctl, +static const struct file_operations sync_file_fops = { + .release = sync_file_release, + .poll = sync_file_poll, + .unlocked_ioctl = sync_file_ioctl, + .compat_ioctl = sync_file_ioctl, }; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index b47058fbe8af..bec62c37ec7c 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -25,7 +25,7 @@ struct sync_timeline; struct sync_pt; -struct sync_fence; +struct sync_file; /** * struct sync_timeline_ops - sync object implementation ops @@ -108,36 +108,36 @@ static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) child_list_lock); } -struct sync_fence_cb { +struct sync_file_cb { struct fence_cb cb; struct fence *sync_pt; - struct sync_fence *fence; + struct sync_file *sync_file; }; /** - * struct sync_fence - sync fence + * struct sync_file - sync file to export to the userspace * @file: file representing this fence * @kref: reference count on fence. - * @name: name of sync_fence. Useful for debugging - * @sync_fence_list: membership in global fence list + * @name: name of sync_file. Useful for debugging + * @sync_file_list: membership in global file list * @num_fences number of sync_pts in the fence * @wq: wait queue for fence signaling * @status: 0: signaled, >0:active, <0: error * @cbs: sync_pts callback information */ -struct sync_fence { +struct sync_file { struct file *file; struct kref kref; char name[32]; #ifdef CONFIG_DEBUG_FS - struct list_head sync_fence_list; + struct list_head sync_file_list; #endif int num_fences; wait_queue_head_t wq; atomic_t status; - struct sync_fence_cb cbs[]; + struct sync_file_cb cbs[]; }; /* @@ -199,95 +199,95 @@ struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); void sync_pt_free(struct sync_pt *pt); /** - * sync_fence_create() - creates a sync fence - * @name: name of fence to create - * @pt: sync_pt to add to the fence + * sync_file_create() - creates a sync file + * @name: name of file to create + * @pt: sync_pt to add to the file * - * Creates a fence containg @pt. Once this is called, the fence takes + * Creates a sync_file containg @pt. Once this is called, the sync_file takes * ownership of @pt. */ -struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt); +struct sync_file *sync_file_create(const char *name, struct sync_pt *pt); /** - * sync_fence_create_dma() - creates a sync fence from dma-fence - * @name: name of fence to create - * @pt: dma-fence to add to the fence + * sync_file_create_dma() - creates a sync file from dma-fence + * @name: name of file to create + * @pt: dma-fence to add to the file * - * Creates a fence containg @pt. Once this is called, the fence takes + * Creates a sync_file containg @pt. Once this is called, the fence takes * ownership of @pt. */ -struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt); +struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); /* - * API for sync_fence consumers + * API for sync_file consumers */ /** - * sync_fence_merge() - merge two fences + * sync_file_merge() - merge two sync_files * @name: name of new fence - * @a: fence a - * @b: fence b + * @a: sync_file a + * @b: sync_file b * - * Creates a new fence which contains copies of all the sync_pts in both - * @a and @b. @a and @b remain valid, independent fences. Returns the - * new merged fence or NULL in case of error. + * Creates a new sync_file which contains copies of all the sync_pts in both + * @a and @b. @a and @b remain valid, independent sync_file. Returns the + * new merged sync_file or NULL in case of error. */ -struct sync_fence *sync_fence_merge(const char *name, - struct sync_fence *a, struct sync_fence *b); +struct sync_file *sync_file_merge(const char *name, + struct sync_file *a, struct sync_file *b); /** - * sync_fence_fdget() - get a fence from an fd + * sync_file_fdget() - get a sync_file from an fd * @fd: fd referencing a fence * - * Ensures @fd references a valid fence, increments the refcount of the backing - * file, and returns the fence. Returns the fence or NULL in case of error. + * Ensures @fd references a valid sync_file, increments the refcount of the + * backing file. Returns the sync_file or NULL in case of error. */ -struct sync_fence *sync_fence_fdget(int fd); +struct sync_file *sync_file_fdget(int fd); /** - * sync_fence_put() - puts a reference of a sync fence - * @fence: fence to put + * sync_file_put() - puts a reference of a sync_file + * @sync_file: sync_file to put * - * Puts a reference on @fence. If this is the last reference, the fence and - * all it's sync_pts will be freed + * Puts a reference on @sync_fence. If this is the last reference, the + * sync_fil and all it's sync_pts will be freed */ -void sync_fence_put(struct sync_fence *fence); +void sync_file_put(struct sync_file *sync_file); /** - * sync_fence_install() - installs a fence into a file descriptor - * @fence: fence to install + * sync_file_install() - installs a sync_file into a file descriptor + * @sync_file: sync_file to install * @fd: file descriptor in which to install the fence * - * Installs @fence into @fd. @fd's should be acquired through + * Installs @sync_file into @fd. @fd's should be acquired through * get_unused_fd_flags(O_CLOEXEC). */ -void sync_fence_install(struct sync_fence *fence, int fd); +void sync_file_install(struct sync_file *sync_file, int fd); /** - * sync_fence_wait() - wait on fence - * @fence: fence to wait on + * sync_file_wait() - wait on sync file + * @sync_file: file to wait on * @tiemout: timeout in ms * - * Wait for @fence to be signaled or have an error. Waits indefinitely + * Wait for @sync_file to be signaled or have an error. Waits indefinitely * if @timeout < 0. * * Returns 0 if fence signaled, > 0 if it is still active and <0 on error */ -int sync_fence_wait(struct sync_fence *fence, long timeout); +int sync_file_wait(struct sync_file *sync_file, long timeout); #ifdef CONFIG_DEBUG_FS void sync_timeline_debug_add(struct sync_timeline *obj); void sync_timeline_debug_remove(struct sync_timeline *obj); -void sync_fence_debug_add(struct sync_fence *fence); -void sync_fence_debug_remove(struct sync_fence *fence); +void sync_file_debug_add(struct sync_file *fence); +void sync_file_debug_remove(struct sync_file *fence); void sync_dump(void); #else # define sync_timeline_debug_add(obj) # define sync_timeline_debug_remove(obj) -# define sync_fence_debug_add(fence) -# define sync_fence_debug_remove(fence) +# define sync_file_debug_add(fence) +# define sync_file_debug_remove(fence) # define sync_dump() #endif diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 33dec4219e99..f1880240973d 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -35,8 +35,8 @@ static struct dentry *dbgfs; static LIST_HEAD(sync_timeline_list_head); static DEFINE_SPINLOCK(sync_timeline_list_lock); -static LIST_HEAD(sync_fence_list_head); -static DEFINE_SPINLOCK(sync_fence_list_lock); +static LIST_HEAD(sync_file_list_head); +static DEFINE_SPINLOCK(sync_file_list_lock); void sync_timeline_debug_add(struct sync_timeline *obj) { @@ -56,22 +56,22 @@ void sync_timeline_debug_remove(struct sync_timeline *obj) spin_unlock_irqrestore(&sync_timeline_list_lock, flags); } -void sync_fence_debug_add(struct sync_fence *fence) +void sync_file_debug_add(struct sync_file *sync_file) { unsigned long flags; - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_add_tail(&fence->sync_fence_list, &sync_fence_list_head); - spin_unlock_irqrestore(&sync_fence_list_lock, flags); + spin_lock_irqsave(&sync_file_list_lock, flags); + list_add_tail(&sync_file->sync_file_list, &sync_file_list_head); + spin_unlock_irqrestore(&sync_file_list_lock, flags); } -void sync_fence_debug_remove(struct sync_fence *fence) +void sync_file_debug_remove(struct sync_file *sync_file) { unsigned long flags; - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_del(&fence->sync_fence_list); - spin_unlock_irqrestore(&sync_fence_list_lock, flags); + spin_lock_irqsave(&sync_file_list_lock, flags); + list_del(&sync_file->sync_file_list); + spin_unlock_irqrestore(&sync_file_list_lock, flags); } static const char *sync_status_str(int status) @@ -152,17 +152,18 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) spin_unlock_irqrestore(&obj->child_list_lock, flags); } -static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) -{ +static void sync_print_sync_file(struct seq_file *s, + struct sync_file *sync_file) + { int i; - seq_printf(s, "[%p] %s: %s\n", fence, fence->name, - sync_status_str(atomic_read(&fence->status))); - - for (i = 0; i < fence->num_fences; ++i) - sync_print_pt(s, fence->cbs[i].sync_pt, true); -} + seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, + sync_status_str(atomic_read(&sync_file->status))); + for (i = 0; i < sync_file->num_fences; ++i) + sync_print_pt(s, sync_file->cbs[i].sync_pt, true); + } + static int sync_debugfs_show(struct seq_file *s, void *unused) { unsigned long flags; @@ -183,15 +184,15 @@ static int sync_debugfs_show(struct seq_file *s, void *unused) seq_puts(s, "fences:\n--------------\n"); - spin_lock_irqsave(&sync_fence_list_lock, flags); - list_for_each(pos, &sync_fence_list_head) { - struct sync_fence *fence = - container_of(pos, struct sync_fence, sync_fence_list); + spin_lock_irqsave(&sync_file_list_lock, flags); + list_for_each(pos, &sync_file_list_head) { + struct sync_file *sync_file = + container_of(pos, struct sync_file, sync_file_list); - sync_print_fence(s, fence); + sync_print_sync_file(s, sync_file); seq_puts(s, "\n"); } - spin_unlock_irqrestore(&sync_fence_list_lock, flags); + spin_unlock_irqrestore(&sync_file_list_lock, flags); return 0; } @@ -244,7 +245,7 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, int fd = get_unused_fd_flags(O_CLOEXEC); int err; struct sync_pt *pt; - struct sync_fence *fence; + struct sync_file *sync_file; struct sw_sync_create_fence_data data; if (fd < 0) @@ -262,8 +263,8 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, } data.name[sizeof(data.name) - 1] = '\0'; - fence = sync_fence_create(data.name, pt); - if (!fence) { + sync_file = sync_file_create(data.name, pt); + if (!sync_file) { sync_pt_free(pt); err = -ENOMEM; goto err; @@ -271,12 +272,12 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, data.fence = fd; if (copy_to_user((void __user *)arg, &data, sizeof(data))) { - sync_fence_put(fence); + sync_file_put(sync_file); err = -EFAULT; goto err; } - sync_fence_install(fence, fd); + sync_file_install(sync_file, fd); return 0; diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 77edb977a7bf..80f5da4f2aa5 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -33,19 +33,19 @@ TRACE_EVENT(sync_timeline, ); TRACE_EVENT(sync_wait, - TP_PROTO(struct sync_fence *fence, int begin), + TP_PROTO(struct sync_file *sync_file, int begin), - TP_ARGS(fence, begin), + TP_ARGS(sync_file, begin), TP_STRUCT__entry( - __string(name, fence->name) + __string(name, sync_file->name) __field(s32, status) __field(u32, begin) ), TP_fast_assign( - __assign_str(name, fence->name); - __entry->status = atomic_read(&fence->status); + __assign_str(name, sync_file->name); + __entry->status = atomic_read(&sync_file->status); __entry->begin = begin; ), diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index e964c751f6b8..73deb6907ce1 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -46,15 +46,15 @@ struct sync_pt_info { }; /** - * struct sync_fence_info_data - data returned from fence info ioctl + * struct sync_file_info_data - data returned from fence info ioctl * @len: ioctl caller writes the size of the buffer its passing in. - * ioctl returns length of sync_fence_data returned to userspace - * including pt_info. + * ioctl returns length of sync_file_info_data returned to + * userspace including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error * @pt_info: a sync_pt_info struct for every sync_pt in the fence */ -struct sync_fence_info_data { +struct sync_file_info_data { __u32 len; char name[32]; __s32 status; @@ -83,15 +83,15 @@ struct sync_fence_info_data { /** * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence * - * Takes a struct sync_fence_info_data with extra space allocated for pt_info. + * Takes a struct sync_file_info_data with extra space allocated for pt_info. * Caller should write the size of the buffer into len. On return, len is - * updated to reflect the total size of the sync_fence_info_data including + * updated to reflect the total size of the sync_file_info_data including * pt_info. * * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. * To iterate over the sync_pt_infos, use the sync_pt_info.len field. */ #define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\ - struct sync_fence_info_data) + struct sync_file_info_data) #endif /* _UAPI_LINUX_SYNC_H */ -- cgit From c88b26dd8eda48758967c87b4ef89ae8e35f1e71 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:20 -0200 Subject: staging/android: rename 'sync_pt' to 'fence' in struct sync_fence_cb 'sync_pt' is actually declared as struct fence so to make the name means its type we rename it to 'fence'. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 20 ++++++++++---------- drivers/staging/android/sync.h | 2 +- drivers/staging/android/sync_debug.c | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 8cccdf94ce77..22b1d9b03fd6 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -197,7 +197,7 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) sync_file->num_fences = 1; atomic_set(&sync_file->status, 1); - sync_file->cbs[0].sync_pt = pt; + sync_file->cbs[0].fence = pt; sync_file->cbs[0].sync_file = sync_file; if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) atomic_dec(&sync_file->status); @@ -247,7 +247,7 @@ EXPORT_SYMBOL(sync_file_install); static void sync_file_add_pt(struct sync_file *sync_file, int *i, struct fence *pt) { - sync_file->cbs[*i].sync_pt = pt; + sync_file->cbs[*i].fence = pt; sync_file->cbs[*i].sync_file = sync_file; if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, @@ -279,8 +279,8 @@ struct sync_file *sync_file_merge(const char *name, * and sync_file_create, this is a reasonable assumption. */ for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { - struct fence *pt_a = a->cbs[i_a].sync_pt; - struct fence *pt_b = b->cbs[i_b].sync_pt; + struct fence *pt_a = a->cbs[i_a].fence; + struct fence *pt_b = b->cbs[i_b].fence; if (pt_a->context < pt_b->context) { sync_file_add_pt(sync_file, &i, pt_a); @@ -302,10 +302,10 @@ struct sync_file *sync_file_merge(const char *name, } for (; i_a < a->num_fences; i_a++) - sync_file_add_pt(sync_file, &i, a->cbs[i_a].sync_pt); + sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence); for (; i_b < b->num_fences; i_b++) - sync_file_add_pt(sync_file, &i, b->cbs[i_b].sync_pt); + sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence); if (num_fences > i) atomic_sub(num_fences - i, &sync_file->status); @@ -328,7 +328,7 @@ int sync_file_wait(struct sync_file *sync_file, long timeout) trace_sync_wait(sync_file, 1); for (i = 0; i < sync_file->num_fences; ++i) - trace_sync_pt(sync_file->cbs[i].sync_pt); + trace_sync_pt(sync_file->cbs[i].fence); ret = wait_event_interruptible_timeout(sync_file->wq, atomic_read(&sync_file->status) <= 0, timeout); @@ -468,9 +468,9 @@ static void sync_file_free(struct kref *kref) int i; for (i = 0; i < sync_file->num_fences; ++i) { - fence_remove_callback(sync_file->cbs[i].sync_pt, + fence_remove_callback(sync_file->cbs[i].fence, &sync_file->cbs[i].cb); - fence_put(sync_file->cbs[i].sync_pt); + fence_put(sync_file->cbs[i].fence); } kfree(sync_file); @@ -624,7 +624,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len = sizeof(struct sync_file_info_data); for (i = 0; i < sync_file->num_fences; ++i) { - struct fence *pt = sync_file->cbs[i].sync_pt; + struct fence *pt = sync_file->cbs[i].fence; ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index bec62c37ec7c..a18d1e3365fb 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -110,7 +110,7 @@ static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) struct sync_file_cb { struct fence_cb cb; - struct fence *sync_pt; + struct fence *fence; struct sync_file *sync_file; }; diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index f1880240973d..85ae98a63a1e 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -161,7 +161,7 @@ static void sync_print_sync_file(struct seq_file *s, sync_status_str(atomic_read(&sync_file->status))); for (i = 0; i < sync_file->num_fences; ++i) - sync_print_pt(s, sync_file->cbs[i].sync_pt, true); + sync_print_pt(s, sync_file->cbs[i].fence, true); } static int sync_debugfs_show(struct seq_file *s, void *unused) -- cgit From b55b54b5db330e36cd465adb3fbe274ffb1061d3 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:21 -0200 Subject: staging/android: remove struct sync_pt struct sync_pt was just wrapping around struct fence and creating an extra abstraction layer. The only two members of struct sync_pt, child_list and active_list, were moved to struct fence in an earlier commit. After removing those two members struct sync_pt is nothing more than struct fence, so remove it all and use struct fence directly. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 23 ++++---- drivers/staging/android/sw_sync.h | 8 +-- drivers/staging/android/sync.c | 101 +++++++++++++++-------------------- drivers/staging/android/sync.h | 63 +++++++--------------- drivers/staging/android/sync_debug.c | 49 ++++++++--------- drivers/staging/android/trace/sync.h | 14 ++--- include/linux/fence.h | 2 + 7 files changed, 113 insertions(+), 147 deletions(-) diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index f491dbce5696..3bee959b41d8 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -25,7 +25,7 @@ #include "sw_sync.h" -struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) +struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) { struct sw_sync_pt *pt; @@ -34,23 +34,23 @@ struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value) pt->value = value; - return (struct sync_pt *)pt; + return (struct fence *)pt; } EXPORT_SYMBOL(sw_sync_pt_create); -static int sw_sync_pt_has_signaled(struct sync_pt *sync_pt) +static int sw_sync_fence_has_signaled(struct fence *fence) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; struct sw_sync_timeline *obj = - (struct sw_sync_timeline *)sync_pt_parent(sync_pt); + (struct sw_sync_timeline *)fence_parent(fence); return (pt->value > obj->value) ? 0 : 1; } -static int sw_sync_fill_driver_data(struct sync_pt *sync_pt, +static int sw_sync_fill_driver_data(struct fence *fence, void *data, int size) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; if (size < sizeof(pt->value)) return -ENOMEM; @@ -68,20 +68,19 @@ static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline, snprintf(str, size, "%d", timeline->value); } -static void sw_sync_pt_value_str(struct sync_pt *sync_pt, - char *str, int size) +static void sw_sync_fence_value_str(struct fence *fence, char *str, int size) { - struct sw_sync_pt *pt = (struct sw_sync_pt *)sync_pt; + struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; snprintf(str, size, "%d", pt->value); } static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", - .has_signaled = sw_sync_pt_has_signaled, + .has_signaled = sw_sync_fence_has_signaled, .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, - .pt_value_str = sw_sync_pt_value_str, + .fence_value_str = sw_sync_fence_value_str, }; struct sw_sync_timeline *sw_sync_timeline_create(const char *name) diff --git a/drivers/staging/android/sw_sync.h b/drivers/staging/android/sw_sync.h index c87ae9ebf267..e18667bfb0ca 100644 --- a/drivers/staging/android/sw_sync.h +++ b/drivers/staging/android/sw_sync.h @@ -29,7 +29,7 @@ struct sw_sync_timeline { }; struct sw_sync_pt { - struct sync_pt pt; + struct fence pt; u32 value; }; @@ -38,7 +38,7 @@ struct sw_sync_pt { struct sw_sync_timeline *sw_sync_timeline_create(const char *name); void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc); -struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); +struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, u32 value); #else static inline struct sw_sync_timeline *sw_sync_timeline_create(const char *name) { @@ -49,8 +49,8 @@ static inline void sw_sync_timeline_inc(struct sw_sync_timeline *obj, u32 inc) { } -static inline struct sync_pt *sw_sync_pt_create(struct sw_sync_timeline *obj, - u32 value) +static inline struct fence *sw_sync_pt_create(struct sw_sync_timeline *obj, + u32 value) { return NULL; } diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 22b1d9b03fd6..3c2c8d07df62 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -102,51 +102,45 @@ void sync_timeline_signal(struct sync_timeline *obj) { unsigned long flags; LIST_HEAD(signaled_pts); - struct sync_pt *pt, *next; + struct fence *fence, *next; trace_sync_timeline(obj); spin_lock_irqsave(&obj->child_list_lock, flags); - list_for_each_entry_safe(pt, next, &obj->active_list_head, + list_for_each_entry_safe(fence, next, &obj->active_list_head, active_list) { - if (fence_is_signaled_locked(&pt->base)) - list_del_init(&pt->active_list); + if (fence_is_signaled_locked(fence)) + list_del_init(&fence->active_list); } spin_unlock_irqrestore(&obj->child_list_lock, flags); } EXPORT_SYMBOL(sync_timeline_signal); -struct sync_pt *sync_pt_create(struct sync_timeline *obj, int size) +struct fence *sync_pt_create(struct sync_timeline *obj, int size) { unsigned long flags; - struct sync_pt *pt; + struct fence *fence; - if (size < sizeof(struct sync_pt)) + if (size < sizeof(*fence)) return NULL; - pt = kzalloc(size, GFP_KERNEL); - if (!pt) + fence = kzalloc(size, GFP_KERNEL); + if (!fence) return NULL; spin_lock_irqsave(&obj->child_list_lock, flags); sync_timeline_get(obj); - fence_init(&pt->base, &android_fence_ops, &obj->child_list_lock, + fence_init(fence, &android_fence_ops, &obj->child_list_lock, obj->context, ++obj->value); - list_add_tail(&pt->child_list, &obj->child_list_head); - INIT_LIST_HEAD(&pt->active_list); + list_add_tail(&fence->child_list, &obj->child_list_head); + INIT_LIST_HEAD(&fence->active_list); spin_unlock_irqrestore(&obj->child_list_lock, flags); - return pt; + return fence; } EXPORT_SYMBOL(sync_pt_create); -void sync_pt_free(struct sync_pt *pt) -{ - fence_put(&pt->base); -} -EXPORT_SYMBOL(sync_pt_free); - static struct sync_file *sync_file_alloc(int size, const char *name) { struct sync_file *sync_file; @@ -184,8 +178,8 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) wake_up_all(&sync_file->wq); } -/* TODO: implement a create which takes more that one sync_pt */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) +/* TODO: implement a create which takes more that one fence */ +struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) { struct sync_file *sync_file; @@ -197,9 +191,10 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) sync_file->num_fences = 1; atomic_set(&sync_file->status, 1); - sync_file->cbs[0].fence = pt; + sync_file->cbs[0].fence = fence; sync_file->cbs[0].sync_file = sync_file; - if (fence_add_callback(pt, &sync_file->cbs[0].cb, fence_check_cb_func)) + if (fence_add_callback(fence, &sync_file->cbs[0].cb, + fence_check_cb_func)) atomic_dec(&sync_file->status); sync_file_debug_add(sync_file); @@ -208,9 +203,9 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt) } EXPORT_SYMBOL(sync_file_create_dma); -struct sync_file *sync_file_create(const char *name, struct sync_pt *pt) +struct sync_file *sync_file_create(const char *name, struct fence *fence) { - return sync_file_create_dma(name, &pt->base); + return sync_file_create_dma(name, fence); } EXPORT_SYMBOL(sync_file_create); @@ -245,14 +240,14 @@ void sync_file_install(struct sync_file *sync_file, int fd) EXPORT_SYMBOL(sync_file_install); static void sync_file_add_pt(struct sync_file *sync_file, int *i, - struct fence *pt) + struct fence *fence) { - sync_file->cbs[*i].fence = pt; + sync_file->cbs[*i].fence = fence; sync_file->cbs[*i].sync_file = sync_file; - if (!fence_add_callback(pt, &sync_file->cbs[*i].cb, + if (!fence_add_callback(fence, &sync_file->cbs[*i].cb, fence_check_cb_func)) { - fence_get(pt); + fence_get(fence); (*i)++; } } @@ -328,7 +323,7 @@ int sync_file_wait(struct sync_file *sync_file, long timeout) trace_sync_wait(sync_file, 1); for (i = 0; i < sync_file->num_fences; ++i) - trace_sync_pt(sync_file->cbs[i].fence); + trace_fence(sync_file->cbs[i].fence); ret = wait_event_interruptible_timeout(sync_file->wq, atomic_read(&sync_file->status) <= 0, timeout); @@ -356,43 +351,39 @@ EXPORT_SYMBOL(sync_file_wait); static const char *android_fence_get_driver_name(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); return parent->ops->driver_name; } static const char *android_fence_get_timeline_name(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); return parent->name; } static void android_fence_release(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); unsigned long flags; spin_lock_irqsave(fence->lock, flags); - list_del(&pt->child_list); - if (WARN_ON_ONCE(!list_empty(&pt->active_list))) - list_del(&pt->active_list); + list_del(&fence->child_list); + if (WARN_ON_ONCE(!list_empty(&fence->active_list))) + list_del(&fence->active_list); spin_unlock_irqrestore(fence->lock, flags); sync_timeline_put(parent); - fence_free(&pt->base); + fence_free(fence); } static bool android_fence_signaled(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); int ret; - ret = parent->ops->has_signaled(pt); + ret = parent->ops->has_signaled(fence); if (ret < 0) fence->status = ret; return ret; @@ -400,46 +391,42 @@ static bool android_fence_signaled(struct fence *fence) static bool android_fence_enable_signaling(struct fence *fence) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (android_fence_signaled(fence)) return false; - list_add_tail(&pt->active_list, &parent->active_list_head); + list_add_tail(&fence->active_list, &parent->active_list_head); return true; } static int android_fence_fill_driver_data(struct fence *fence, void *data, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (!parent->ops->fill_driver_data) return 0; - return parent->ops->fill_driver_data(pt, data, size); + return parent->ops->fill_driver_data(fence, data, size); } static void android_fence_value_str(struct fence *fence, char *str, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); - if (!parent->ops->pt_value_str) { + if (!parent->ops->fence_value_str) { if (size) *str = 0; return; } - parent->ops->pt_value_str(pt, str, size); + parent->ops->fence_value_str(fence, str, size); } static void android_fence_timeline_value_str(struct fence *fence, char *str, int size) { - struct sync_pt *pt = container_of(fence, struct sync_pt, base); - struct sync_timeline *parent = sync_pt_parent(pt); + struct sync_timeline *parent = fence_parent(fence); if (!parent->ops->timeline_value_str) { if (size) @@ -624,9 +611,9 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len = sizeof(struct sync_file_info_data); for (i = 0; i < sync_file->num_fences; ++i) { - struct fence *pt = sync_file->cbs[i].fence; + struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_pt_info(pt, (u8 *)data + len, size - len); + ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len); if (ret < 0) goto out; diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index a18d1e3365fb..8cdac1a12e4f 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -24,7 +24,6 @@ #include "uapi/sync.h" struct sync_timeline; -struct sync_pt; struct sync_file; /** @@ -39,23 +38,23 @@ struct sync_file; * as specified by size. This information is returned * to userspace by SYNC_IOC_FENCE_INFO. * @timeline_value_str: fill str with the value of the sync_timeline's counter - * @pt_value_str: fill str with the value of the sync_pt + * @fence_value_str: fill str with the value of the fence */ struct sync_timeline_ops { const char *driver_name; /* required */ - int (*has_signaled)(struct sync_pt *pt); + int (*has_signaled)(struct fence *fence); /* optional */ - int (*fill_driver_data)(struct sync_pt *syncpt, void *data, int size); + int (*fill_driver_data)(struct fence *fence, void *data, int size); /* optional */ void (*timeline_value_str)(struct sync_timeline *timeline, char *str, int size); /* optional */ - void (*pt_value_str)(struct sync_pt *pt, char *str, int size); + void (*fence_value_str)(struct fence *fence, char *str, int size); }; /** @@ -66,7 +65,7 @@ struct sync_timeline_ops { * @destroyed: set when sync_timeline is destroyed * @child_list_head: list of children sync_pts for this sync_timeline * @child_list_lock: lock protecting @child_list_head, destroyed, and - * sync_pt.status + * fence.status * @active_list_head: list of active (unsignaled/errored) sync_pts * @sync_timeline_list: membership in global sync_timeline_list */ @@ -89,22 +88,9 @@ struct sync_timeline { #endif }; -/** - * struct sync_pt - sync point - * @base: base fence class - * @child_list: membership in sync_timeline.child_list_head - * @active_list: membership in sync_timeline.active_list_head - */ -struct sync_pt { - struct fence base; - - struct list_head child_list; - struct list_head active_list; -}; - -static inline struct sync_timeline *sync_pt_parent(struct sync_pt *pt) +static inline struct sync_timeline *fence_parent(struct fence *fence) { - return container_of(pt->base.lock, struct sync_timeline, + return container_of(fence->lock, struct sync_timeline, child_list_lock); } @@ -164,7 +150,7 @@ struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, * * A sync implementation should call this when the @obj is going away * (i.e. module unload.) @obj won't actually be freed until all its children - * sync_pts are freed. + * fences are freed. */ void sync_timeline_destroy(struct sync_timeline *obj); @@ -172,41 +158,32 @@ void sync_timeline_destroy(struct sync_timeline *obj); * sync_timeline_signal() - signal a status change on a sync_timeline * @obj: sync_timeline to signal * - * A sync implementation should call this any time one of it's sync_pts + * A sync implementation should call this any time one of it's fences * has signaled or has an error condition. */ void sync_timeline_signal(struct sync_timeline *obj); /** * sync_pt_create() - creates a sync pt - * @parent: sync_pt's parent sync_timeline + * @parent: fence's parent sync_timeline * @size: size to allocate for this pt * - * Creates a new sync_pt as a child of @parent. @size bytes will be + * Creates a new fence as a child of @parent. @size bytes will be * allocated allowing for implementation specific data to be kept after - * the generic sync_timeline struct. Returns the sync_pt object or + * the generic sync_timeline struct. Returns the fence object or * NULL in case of error. */ -struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); +struct fence *sync_pt_create(struct sync_timeline *parent, int size); /** - * sync_pt_free() - frees a sync pt - * @pt: sync_pt to free + * sync_fence_create() - creates a sync fence + * @name: name of fence to create + * @fence: fence to add to the sync_fence * - * This should only be called on sync_pts which have been created but - * not added to a fence. - */ -void sync_pt_free(struct sync_pt *pt); - -/** - * sync_file_create() - creates a sync file - * @name: name of file to create - * @pt: sync_pt to add to the file - * - * Creates a sync_file containg @pt. Once this is called, the sync_file takes - * ownership of @pt. + * Creates a sync_file containg @fence. Once this is called, the sync_file + * takes ownership of @fence. */ -struct sync_file *sync_file_create(const char *name, struct sync_pt *pt); +struct sync_file *sync_file_create(const char *name, struct fence *fence); /** * sync_file_create_dma() - creates a sync file from dma-fence @@ -228,7 +205,7 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); * @a: sync_file a * @b: sync_file b * - * Creates a new sync_file which contains copies of all the sync_pts in both + * Creates a new sync_file which contains copies of all the fences in both * @a and @b. @a and @b remain valid, independent sync_file. Returns the * new merged sync_file or NULL in case of error. */ diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 85ae98a63a1e..fd13f1e885e5 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -85,39 +85,40 @@ static const char *sync_status_str(int status) return "error"; } -static void sync_print_pt(struct seq_file *s, struct fence *pt, bool fence) +static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show) { int status = 1; + struct sync_timeline *parent = fence_parent(fence); - if (fence_is_signaled_locked(pt)) - status = pt->status; + if (fence_is_signaled_locked(fence)) + status = fence->status; - seq_printf(s, " %s%spt %s", - fence && pt->ops->get_timeline_name ? - pt->ops->get_timeline_name(pt) : "", - fence ? "_" : "", + seq_printf(s, " %s%sfence %s", + show ? parent->name : "", + show ? "_" : "", sync_status_str(status)); if (status <= 0) { struct timespec64 ts64 = - ktime_to_timespec64(pt->timestamp); + ktime_to_timespec64(fence->timestamp); seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec); } - if ((!fence || pt->ops->timeline_value_str) && - pt->ops->fence_value_str) { + if ((!fence || fence->ops->timeline_value_str) && + fence->ops->fence_value_str) { char value[64]; bool success; - pt->ops->fence_value_str(pt, value, sizeof(value)); + fence->ops->fence_value_str(fence, value, sizeof(value)); success = strlen(value); if (success) seq_printf(s, ": %s", value); if (success && fence) { - pt->ops->timeline_value_str(pt, value, sizeof(value)); + fence->ops->timeline_value_str(fence, value, + sizeof(value)); if (strlen(value)) seq_printf(s, " / %s", value); @@ -145,25 +146,25 @@ static void sync_print_obj(struct seq_file *s, struct sync_timeline *obj) spin_lock_irqsave(&obj->child_list_lock, flags); list_for_each(pos, &obj->child_list_head) { - struct sync_pt *pt = - container_of(pos, struct sync_pt, child_list); - sync_print_pt(s, &pt->base, false); + struct fence *fence = + container_of(pos, struct fence, child_list); + sync_print_fence(s, fence, false); } spin_unlock_irqrestore(&obj->child_list_lock, flags); } static void sync_print_sync_file(struct seq_file *s, struct sync_file *sync_file) - { +{ int i; seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, sync_status_str(atomic_read(&sync_file->status))); for (i = 0; i < sync_file->num_fences; ++i) - sync_print_pt(s, sync_file->cbs[i].fence, true); - } - + sync_print_fence(s, sync_file->cbs[i].fence, true); +} + static int sync_debugfs_show(struct seq_file *s, void *unused) { unsigned long flags; @@ -244,7 +245,7 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, { int fd = get_unused_fd_flags(O_CLOEXEC); int err; - struct sync_pt *pt; + struct fence *fence; struct sync_file *sync_file; struct sw_sync_create_fence_data data; @@ -256,16 +257,16 @@ static long sw_sync_ioctl_create_fence(struct sw_sync_timeline *obj, goto err; } - pt = sw_sync_pt_create(obj, data.value); - if (!pt) { + fence = sw_sync_pt_create(obj, data.value); + if (!fence) { err = -ENOMEM; goto err; } data.name[sizeof(data.name) - 1] = '\0'; - sync_file = sync_file_create(data.name, pt); + sync_file = sync_file_create(data.name, fence); if (!sync_file) { - sync_pt_free(pt); + fence_put(fence); err = -ENOMEM; goto err; } diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 80f5da4f2aa5..87c60e9f584e 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -53,20 +53,20 @@ TRACE_EVENT(sync_wait, __get_str(name), __entry->status) ); -TRACE_EVENT(sync_pt, - TP_PROTO(struct fence *pt), +TRACE_EVENT(fence, + TP_PROTO(struct fence *fence), - TP_ARGS(pt), + TP_ARGS(fence), TP_STRUCT__entry( - __string(timeline, pt->ops->get_timeline_name(pt)) + __string(timeline, fence->ops->get_timeline_name(fence)) __array(char, value, 32) ), TP_fast_assign( - __assign_str(timeline, pt->ops->get_timeline_name(pt)); - if (pt->ops->fence_value_str) { - pt->ops->fence_value_str(pt, __entry->value, + __assign_str(timeline, fence->ops->get_timeline_name(fence)); + if (fence->ops->fence_value_str) { + fence->ops->fence_value_str(fence, __entry->value, sizeof(__entry->value)); } else { __entry->value[0] = '\0'; diff --git a/include/linux/fence.h b/include/linux/fence.h index bb522011383b..605bd88246a6 100644 --- a/include/linux/fence.h +++ b/include/linux/fence.h @@ -79,6 +79,8 @@ struct fence { unsigned long flags; ktime_t timestamp; int status; + struct list_head child_list; + struct list_head active_list; }; enum fence_flag_bits { -- cgit From e6a0cb4819d082b60ce47e432bfcac16fdf93767 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:22 -0200 Subject: staging/android: remove unused var from sync_timeline_signal() signaled_pts is not used in this function. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 3c2c8d07df62..9ec55ef16eb1 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -101,7 +101,6 @@ EXPORT_SYMBOL(sync_timeline_destroy); void sync_timeline_signal(struct sync_timeline *obj) { unsigned long flags; - LIST_HEAD(signaled_pts); struct fence *fence, *next; trace_sync_timeline(obj); -- cgit From 84288db5ca3fdac8d5a4bc730cc0b20144ddaa46 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:23 -0200 Subject: staging/android: remove pointless sync_timeline_signal at destroy phase All changes to timeline value come through the user via sync_timeline_signal() calls. When sync_timeline_destroy() is called no changes on timeline->value happens hence call sync_timeline_signal() with no increment is pointless. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 9ec55ef16eb1..b9f167ffdff5 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -90,10 +90,6 @@ void sync_timeline_destroy(struct sync_timeline *obj) */ smp_wmb(); - /* - * signal any children that their parent is going away. - */ - sync_timeline_signal(obj); sync_timeline_put(obj); } EXPORT_SYMBOL(sync_timeline_destroy); -- cgit From d52ef2cef99cc200d828f39d1584e4b190fc2442 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Thu, 21 Jan 2016 10:49:24 -0200 Subject: staging/android: remove sync_fence_create_dma() With the removal of struct sync_pt sync_fence_create_dma() now takes the same arguments as sync_fence_create() so let's keep only sync_fence_create(). Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 8 +------- drivers/staging/android/sync.h | 10 ---------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index b9f167ffdff5..5fa4779a1956 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -174,7 +174,7 @@ static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) } /* TODO: implement a create which takes more that one fence */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) +struct sync_file *sync_file_create(const char *name, struct fence *fence) { struct sync_file *sync_file; @@ -196,12 +196,6 @@ struct sync_file *sync_file_create_dma(const char *name, struct fence *fence) return sync_file; } -EXPORT_SYMBOL(sync_file_create_dma); - -struct sync_file *sync_file_create(const char *name, struct fence *fence) -{ - return sync_file_create_dma(name, fence); -} EXPORT_SYMBOL(sync_file_create); struct sync_file *sync_file_fdget(int fd) diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 8cdac1a12e4f..8980b5580fb3 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -185,16 +185,6 @@ struct fence *sync_pt_create(struct sync_timeline *parent, int size); */ struct sync_file *sync_file_create(const char *name, struct fence *fence); -/** - * sync_file_create_dma() - creates a sync file from dma-fence - * @name: name of file to create - * @pt: dma-fence to add to the file - * - * Creates a sync_file containg @pt. Once this is called, the fence takes - * ownership of @pt. - */ -struct sync_file *sync_file_create_dma(const char *name, struct fence *pt); - /* * API for sync_file consumers */ -- cgit From 8fb78ad6e55d8456de9202279b8463f26b012088 Mon Sep 17 00:00:00 2001 From: Ben Marsh Date: Mon, 1 Feb 2016 14:12:32 +0100 Subject: Staging: Android: memory allocation style change in ion_page_pool.c This is a patch to ion_page_pool.c that changes a memory allocation style issue as found by checkpatch.pl. Signed-off-by: Ben Marsh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion_page_pool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c index fd7e23e0c06e..1fe80165a462 100644 --- a/drivers/staging/android/ion/ion_page_pool.c +++ b/drivers/staging/android/ion/ion_page_pool.c @@ -149,8 +149,8 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask, struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order) { - struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool), - GFP_KERNEL); + struct ion_page_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) return NULL; pool->high_count = 0; -- cgit From 84013bb4651e568d543f4cd3fa65c7931943da73 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:30 -0200 Subject: staging/android: remove SYNC_WAIT ioctl This ioctl is replicating the work of poll() syscall so let's take the opportunity that this is still on staging tree and remove the duplication and force new users to use the poll() standard interface. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 52 ------------------------------------ drivers/staging/android/sync.h | 13 --------- drivers/staging/android/trace/sync.h | 44 ------------------------------ drivers/staging/android/uapi/sync.h | 7 ----- 4 files changed, 116 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 5fa4779a1956..381209a9dc2d 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -300,44 +300,6 @@ struct sync_file *sync_file_merge(const char *name, } EXPORT_SYMBOL(sync_file_merge); -int sync_file_wait(struct sync_file *sync_file, long timeout) -{ - long ret; - int i; - - if (timeout < 0) - timeout = MAX_SCHEDULE_TIMEOUT; - else - timeout = msecs_to_jiffies(timeout); - - trace_sync_wait(sync_file, 1); - for (i = 0; i < sync_file->num_fences; ++i) - trace_fence(sync_file->cbs[i].fence); - ret = wait_event_interruptible_timeout(sync_file->wq, - atomic_read(&sync_file->status) <= 0, - timeout); - trace_sync_wait(sync_file, 0); - - if (ret < 0) { - return ret; - } else if (ret == 0) { - if (timeout) { - pr_info("sync_file timeout on [%p] after %dms\n", - sync_file, jiffies_to_msecs(timeout)); - sync_dump(); - } - return -ETIME; - } - - ret = atomic_read(&sync_file->status); - if (ret) { - pr_info("sync_file error %ld on [%p]\n", ret, sync_file); - sync_dump(); - } - return ret; -} -EXPORT_SYMBOL(sync_file_wait); - static const char *android_fence_get_driver_name(struct fence *fence) { struct sync_timeline *parent = fence_parent(fence); @@ -478,17 +440,6 @@ static unsigned int sync_file_poll(struct file *file, poll_table *wait) return 0; } -static long sync_file_ioctl_wait(struct sync_file *sync_file, - unsigned long arg) -{ - __s32 value; - - if (copy_from_user(&value, (void __user *)arg, sizeof(value))) - return -EFAULT; - - return sync_file_wait(sync_file, value); -} - static long sync_file_ioctl_merge(struct sync_file *sync_file, unsigned long arg) { @@ -629,9 +580,6 @@ static long sync_file_ioctl(struct file *file, unsigned int cmd, struct sync_file *sync_file = file->private_data; switch (cmd) { - case SYNC_IOC_WAIT: - return sync_file_ioctl_wait(sync_file, arg); - case SYNC_IOC_MERGE: return sync_file_ioctl_merge(sync_file, arg); diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 8980b5580fb3..af1af998949c 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include "uapi/sync.h" @@ -230,18 +229,6 @@ void sync_file_put(struct sync_file *sync_file); */ void sync_file_install(struct sync_file *sync_file, int fd); -/** - * sync_file_wait() - wait on sync file - * @sync_file: file to wait on - * @tiemout: timeout in ms - * - * Wait for @sync_file to be signaled or have an error. Waits indefinitely - * if @timeout < 0. - * - * Returns 0 if fence signaled, > 0 if it is still active and <0 on error - */ -int sync_file_wait(struct sync_file *sync_file, long timeout); - #ifdef CONFIG_DEBUG_FS void sync_timeline_debug_add(struct sync_timeline *obj); diff --git a/drivers/staging/android/trace/sync.h b/drivers/staging/android/trace/sync.h index 87c60e9f584e..a0f80f41677e 100644 --- a/drivers/staging/android/trace/sync.h +++ b/drivers/staging/android/trace/sync.h @@ -32,50 +32,6 @@ TRACE_EVENT(sync_timeline, TP_printk("name=%s value=%s", __get_str(name), __entry->value) ); -TRACE_EVENT(sync_wait, - TP_PROTO(struct sync_file *sync_file, int begin), - - TP_ARGS(sync_file, begin), - - TP_STRUCT__entry( - __string(name, sync_file->name) - __field(s32, status) - __field(u32, begin) - ), - - TP_fast_assign( - __assign_str(name, sync_file->name); - __entry->status = atomic_read(&sync_file->status); - __entry->begin = begin; - ), - - TP_printk("%s name=%s state=%d", __entry->begin ? "begin" : "end", - __get_str(name), __entry->status) -); - -TRACE_EVENT(fence, - TP_PROTO(struct fence *fence), - - TP_ARGS(fence), - - TP_STRUCT__entry( - __string(timeline, fence->ops->get_timeline_name(fence)) - __array(char, value, 32) - ), - - TP_fast_assign( - __assign_str(timeline, fence->ops->get_timeline_name(fence)); - if (fence->ops->fence_value_str) { - fence->ops->fence_value_str(fence, __entry->value, - sizeof(__entry->value)); - } else { - __entry->value[0] = '\0'; - } - ), - - TP_printk("name=%s value=%s", __get_str(timeline), __entry->value) -); - #endif /* if !defined(_TRACE_SYNC_H) || defined(TRACE_HEADER_MULTI_READ) */ /* This part must be outside protection */ diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 73deb6907ce1..6c88c8080d1e 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -64,13 +64,6 @@ struct sync_file_info_data { #define SYNC_IOC_MAGIC '>' -/** - * DOC: SYNC_IOC_WAIT - wait for a fence to signal - * - * pass timeout in milliseconds. Waits indefinitely timeout < 0. - */ -#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32) - /** * DOC: SYNC_IOC_MERGE - merge two fences * -- cgit From e1786348e4e5442e82b4b35f8ade6f4d0f434e18 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:31 -0200 Subject: staging/android: rename sync_pt_info to sync_fence_info As struct sync_pt doesn't exist anymore it is a good idea remove any reference to it in the sync_framework. sync_pts were replaced directly by fences and here we rename it to sync_fence_info to let the fence namespace clean. v2: rename fence_info to sync_fence_info (Maarten) Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 10 +++++----- drivers/staging/android/uapi/sync.h | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 381209a9dc2d..f6ffb109b483 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -490,15 +490,15 @@ err_put_fd: return err; } -static int sync_fill_pt_info(struct fence *fence, void *data, int size) +static int sync_fill_fence_info(struct fence *fence, void *data, int size) { - struct sync_pt_info *info = data; + struct sync_fence_info *info = data; int ret; - if (size < sizeof(struct sync_pt_info)) + if (size < sizeof(*info)) return -ENOMEM; - info->len = sizeof(struct sync_pt_info); + info->len = sizeof(*info); if (fence->ops->fill_driver_data) { ret = fence->ops->fill_driver_data(fence, info->driver_data, @@ -553,7 +553,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, for (i = 0; i < sync_file->num_fences; ++i) { struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_pt_info(fence, (u8 *)data + len, size - len); + ret = sync_fill_fence_info(fence, (u8 *)data + len, size - len); if (ret < 0) goto out; diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 6c88c8080d1e..9a0c3cd2ced0 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -27,15 +27,15 @@ struct sync_merge_data { }; /** - * struct sync_pt_info - detailed sync_pt information - * @len: length of sync_pt_info including any driver_data + * struct sync_fence_info - detailed fence information + * @len: length of sync_fence_info including any driver_data * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent - * @status: status of the sync_pt 0:active 1:signaled <0:error + * @status: status of the fence 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds * @driver_data: any driver dependent data */ -struct sync_pt_info { +struct sync_fence_info { __u32 len; char obj_name[32]; char driver_name[32]; @@ -52,14 +52,14 @@ struct sync_pt_info { * userspace including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error - * @pt_info: a sync_pt_info struct for every sync_pt in the fence + * @sync_fence_info: array of sync_fence_info for every fence in the sync_file */ struct sync_file_info_data { __u32 len; char name[32]; __s32 status; - __u8 pt_info[0]; + __u8 sync_fence_info[0]; }; #define SYNC_IOC_MAGIC '>' -- cgit From b5b24ac57af99b6b580eb52118167702e442da02 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:32 -0200 Subject: staging/android: rename sync_file_info_data to sync_file_info info_data is a bit redundant, let's keep it as only sync_file_info. It is also smaller. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 26 +++++++++++++------------- drivers/staging/android/uapi/sync.h | 9 ++++----- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index f6ffb109b483..85a0e87b9119 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -525,7 +525,7 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) static long sync_file_ioctl_fence_info(struct sync_file *sync_file, unsigned long arg) { - struct sync_file_info_data *data; + struct sync_file_info *info; __u32 size; __u32 len = 0; int ret, i; @@ -533,27 +533,27 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (copy_from_user(&size, (void __user *)arg, sizeof(size))) return -EFAULT; - if (size < sizeof(struct sync_file_info_data)) + if (size < sizeof(struct sync_file_info)) return -EINVAL; if (size > 4096) size = 4096; - data = kzalloc(size, GFP_KERNEL); - if (!data) + info = kzalloc(size, GFP_KERNEL); + if (!info) return -ENOMEM; - strlcpy(data->name, sync_file->name, sizeof(data->name)); - data->status = atomic_read(&sync_file->status); - if (data->status >= 0) - data->status = !data->status; + strlcpy(info->name, sync_file->name, sizeof(info->name)); + info->status = atomic_read(&sync_file->status); + if (info->status >= 0) + info->status = !info->status; - len = sizeof(struct sync_file_info_data); + len = sizeof(struct sync_file_info); for (i = 0; i < sync_file->num_fences; ++i) { struct fence *fence = sync_file->cbs[i].fence; - ret = sync_fill_fence_info(fence, (u8 *)data + len, size - len); + ret = sync_fill_fence_info(fence, (u8 *)info + len, size - len); if (ret < 0) goto out; @@ -561,15 +561,15 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, len += ret; } - data->len = len; + info->len = len; - if (copy_to_user((void __user *)arg, data, len)) + if (copy_to_user((void __user *)arg, info, len)) ret = -EFAULT; else ret = 0; out: - kfree(data); + kfree(info); return ret; } diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 9a0c3cd2ced0..fcc0b3c5b6da 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -46,15 +46,15 @@ struct sync_fence_info { }; /** - * struct sync_file_info_data - data returned from fence info ioctl + * struct sync_file_info - data returned from fence info ioctl * @len: ioctl caller writes the size of the buffer its passing in. - * ioctl returns length of sync_file_info_data returned to + * ioctl returns length of sync_file_info returned to * userspace including pt_info. * @name: name of fence * @status: status of fence. 1: signaled 0:active <0:error * @sync_fence_info: array of sync_fence_info for every fence in the sync_file */ -struct sync_file_info_data { +struct sync_file_info { __u32 len; char name[32]; __s32 status; @@ -84,7 +84,6 @@ struct sync_file_info_data { * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. * To iterate over the sync_pt_infos, use the sync_pt_info.len field. */ -#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\ - struct sync_file_info_data) +#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_file_info) #endif /* _UAPI_LINUX_SYNC_H */ -- cgit From c7434b8436f9fb79855f0a52e4e9665becb77aea Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:33 -0200 Subject: staging/android: remove driver_data from struct sync_fence_info It is unclear in what situations driver_data should be used thus better do not upstream it for now. If a need arises in the future a discussion can be started to re-add it. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sw_sync.c | 14 -------------- drivers/staging/android/sync.c | 21 --------------------- drivers/staging/android/sync.h | 7 ------- drivers/staging/android/uapi/sync.h | 5 +---- 4 files changed, 1 insertion(+), 46 deletions(-) diff --git a/drivers/staging/android/sw_sync.c b/drivers/staging/android/sw_sync.c index 3bee959b41d8..af39ff58fa33 100644 --- a/drivers/staging/android/sw_sync.c +++ b/drivers/staging/android/sw_sync.c @@ -47,19 +47,6 @@ static int sw_sync_fence_has_signaled(struct fence *fence) return (pt->value > obj->value) ? 0 : 1; } -static int sw_sync_fill_driver_data(struct fence *fence, - void *data, int size) -{ - struct sw_sync_pt *pt = (struct sw_sync_pt *)fence; - - if (size < sizeof(pt->value)) - return -ENOMEM; - - memcpy(data, &pt->value, sizeof(pt->value)); - - return sizeof(pt->value); -} - static void sw_sync_timeline_value_str(struct sync_timeline *sync_timeline, char *str, int size) { @@ -78,7 +65,6 @@ static void sw_sync_fence_value_str(struct fence *fence, char *str, int size) static struct sync_timeline_ops sw_sync_timeline_ops = { .driver_name = "sw_sync", .has_signaled = sw_sync_fence_has_signaled, - .fill_driver_data = sw_sync_fill_driver_data, .timeline_value_str = sw_sync_timeline_value_str, .fence_value_str = sw_sync_fence_value_str, }; diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 85a0e87b9119..d527878c7488 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -351,16 +351,6 @@ static bool android_fence_enable_signaling(struct fence *fence) return true; } -static int android_fence_fill_driver_data(struct fence *fence, - void *data, int size) -{ - struct sync_timeline *parent = fence_parent(fence); - - if (!parent->ops->fill_driver_data) - return 0; - return parent->ops->fill_driver_data(fence, data, size); -} - static void android_fence_value_str(struct fence *fence, char *str, int size) { @@ -394,7 +384,6 @@ static const struct fence_ops android_fence_ops = { .signaled = android_fence_signaled, .wait = fence_default_wait, .release = android_fence_release, - .fill_driver_data = android_fence_fill_driver_data, .fence_value_str = android_fence_value_str, .timeline_value_str = android_fence_timeline_value_str, }; @@ -493,22 +482,12 @@ err_put_fd: static int sync_fill_fence_info(struct fence *fence, void *data, int size) { struct sync_fence_info *info = data; - int ret; if (size < sizeof(*info)) return -ENOMEM; info->len = sizeof(*info); - if (fence->ops->fill_driver_data) { - ret = fence->ops->fill_driver_data(fence, info->driver_data, - size - sizeof(*info)); - if (ret < 0) - return ret; - - info->len += ret; - } - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); strlcpy(info->driver_name, fence->ops->get_driver_name(fence), diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index af1af998949c..d2a173433a7d 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -32,10 +32,6 @@ struct sync_file; * 1 if pt has signaled * 0 if pt has not signaled * <0 on error - * @fill_driver_data: write implementation specific driver data to data. - * should return an error if there is not enough room - * as specified by size. This information is returned - * to userspace by SYNC_IOC_FENCE_INFO. * @timeline_value_str: fill str with the value of the sync_timeline's counter * @fence_value_str: fill str with the value of the fence */ @@ -45,9 +41,6 @@ struct sync_timeline_ops { /* required */ int (*has_signaled)(struct fence *fence); - /* optional */ - int (*fill_driver_data)(struct fence *fence, void *data, int size); - /* optional */ void (*timeline_value_str)(struct sync_timeline *timeline, char *str, int size); diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index fcc0b3c5b6da..4d8cf0062f04 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -28,12 +28,11 @@ struct sync_merge_data { /** * struct sync_fence_info - detailed fence information - * @len: length of sync_fence_info including any driver_data + * @len: length of sync_fence_info * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent * @status: status of the fence 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds - * @driver_data: any driver dependent data */ struct sync_fence_info { __u32 len; @@ -41,8 +40,6 @@ struct sync_fence_info { char driver_name[32]; __s32 status; __u64 timestamp_ns; - - __u8 driver_data[0]; }; /** -- cgit From 323de43f79c5055af71c2db44f34e060ac15e1df Mon Sep 17 00:00:00 2001 From: Gustavo Padovan Date: Wed, 3 Feb 2016 11:25:34 -0200 Subject: staging/android: remove len field from struct sync_fence_info After removing driver_data struct sync_fence_info has now a fixed size, thus it doesn't need any field to tell its size, it is already known. Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync.c | 4 +--- drivers/staging/android/uapi/sync.h | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index d527878c7488..2ab0c208088d 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -486,8 +486,6 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) if (size < sizeof(*info)) return -ENOMEM; - info->len = sizeof(*info); - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); strlcpy(info->driver_name, fence->ops->get_driver_name(fence), @@ -498,7 +496,7 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) info->status = 0; info->timestamp_ns = ktime_to_ns(fence->timestamp); - return info->len; + return sizeof(*info); } static long sync_file_ioctl_fence_info(struct sync_file *sync_file, diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 4d8cf0062f04..a0cf357e598d 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -28,14 +28,12 @@ struct sync_merge_data { /** * struct sync_fence_info - detailed fence information - * @len: length of sync_fence_info * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent * @status: status of the fence 0:active 1:signaled <0:error * @timestamp_ns: timestamp of status change in nanoseconds */ struct sync_fence_info { - __u32 len; char obj_name[32]; char driver_name[32]; __s32 status; -- cgit From 9f90381b3ec8ad5056348642333f0220c95def27 Mon Sep 17 00:00:00 2001 From: Rohit kumar Date: Tue, 12 Jan 2016 09:31:46 +0530 Subject: staging/ion: Add support to get ion handle from dma buf Currently we can only import dma buf fd's to get ion_handle. Adding support to import dma buf handles to support kernel specific use cases. An example use case is in linux platforms such as Tizen, in which DRM-GEM is used for buffer management for graphics. It has gem_handle corresponding to a buffer and uses gem_name for sharing the buffer with other processes. However,it also uses dma_buf fd for 3d operations. For wayland, there are multiple calls for gem_handle to dma_buf fd conversion. So, we store dma_buf associated with buffer. But, there is no api for getting ion_handle from dma_buf. This patch exposes api to retrieve the ion handle from dma_buf for similar use cases. With this patch, we can integrate ION within DRM-GEM for buffer management and dma_buf sharing. Signed-off-by: Rohit kumar Reviewed-by: Laura Abbott Reviewed-by: Sumit Semwal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 26 ++++++++++++++++++-------- drivers/staging/android/ion/ion.h | 20 ++++++++++++++++---- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index df560216d702..d6698483e152 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1153,22 +1153,18 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_share_dma_buf_fd); -struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) +struct ion_handle *ion_import_dma_buf(struct ion_client *client, + struct dma_buf *dmabuf) { - struct dma_buf *dmabuf; struct ion_buffer *buffer; struct ion_handle *handle; int ret; - dmabuf = dma_buf_get(fd); - if (IS_ERR(dmabuf)) - return ERR_CAST(dmabuf); /* if this memory came from ion */ if (dmabuf->ops != &dma_buf_ops) { pr_err("%s: can not import dmabuf from another exporter\n", __func__); - dma_buf_put(dmabuf); return ERR_PTR(-EINVAL); } buffer = dmabuf->priv; @@ -1196,11 +1192,25 @@ struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd) } end: - dma_buf_put(dmabuf); return handle; } EXPORT_SYMBOL(ion_import_dma_buf); +struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd) +{ + struct dma_buf *dmabuf; + struct ion_handle *handle; + + dmabuf = dma_buf_get(fd); + if (IS_ERR(dmabuf)) + return ERR_CAST(dmabuf); + + handle = ion_import_dma_buf(client, dmabuf); + dma_buf_put(dmabuf); + return handle; +} +EXPORT_SYMBOL(ion_import_dma_buf_fd); + static int ion_sync_for_device(struct ion_client *client, int fd) { struct dma_buf *dmabuf; @@ -1308,7 +1318,7 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct ion_handle *handle; - handle = ion_import_dma_buf(client, data.fd.fd); + handle = ion_import_dma_buf_fd(client, data.fd.fd); if (IS_ERR(handle)) ret = PTR_ERR(handle); else diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h index b860c5f579f5..a1331fc169a1 100644 --- a/drivers/staging/android/ion/ion.h +++ b/drivers/staging/android/ion/ion.h @@ -192,14 +192,26 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client, int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle); /** - * ion_import_dma_buf() - given an dma-buf fd from the ion exporter get handle + * ion_import_dma_buf() - get ion_handle from dma-buf + * @client: the client + * @dmabuf: the dma-buf + * + * Get the ion_buffer associated with the dma-buf and return the ion_handle. + * If no ion_handle exists for this buffer, return newly created ion_handle. + * If dma-buf from another exporter is passed, return ERR_PTR(-EINVAL) + */ +struct ion_handle *ion_import_dma_buf(struct ion_client *client, + struct dma_buf *dmabuf); + +/** + * ion_import_dma_buf_fd() - given a dma-buf fd from the ion exporter get handle * @client: the client * @fd: the dma-buf fd * - * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf, - * import that fd and return a handle representing it. If a dma-buf from + * Given an dma-buf fd that was allocated through ion via ion_share_dma_buf_fd, + * import that fd and return a handle representing it. If a dma-buf from * another exporter is passed in this function will return ERR_PTR(-EINVAL) */ -struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd); +struct ion_handle *ion_import_dma_buf_fd(struct ion_client *client, int fd); #endif /* _LINUX_ION_H */ -- cgit From 948c4db4ee10d85fe78ed3755dcaeb85cd37a148 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 26 Jan 2016 17:39:06 +0800 Subject: ion:synchronize debugfs callback and ion_client_destroy There are race condition B/T ion_client_destroy and debugfs callbacks. Let's use a mutex to synchronize them. Signed-off-by: Neil Zhang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/ion/ion.c | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index d6698483e152..7ff2a7ec871f 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -677,6 +677,34 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle) } EXPORT_SYMBOL(ion_unmap_kernel); +static struct mutex debugfs_mutex; +static struct rb_root *ion_root_client; +static int is_client_alive(struct ion_client *client) +{ + struct rb_node *node; + struct ion_client *tmp; + struct ion_device *dev; + + node = ion_root_client->rb_node; + dev = container_of(ion_root_client, struct ion_device, clients); + + down_read(&dev->lock); + while (node) { + tmp = rb_entry(node, struct ion_client, node); + if (client < tmp) { + node = node->rb_left; + } else if (client > tmp) { + node = node->rb_right; + } else { + up_read(&dev->lock); + return 1; + } + } + + up_read(&dev->lock); + return 0; +} + static int ion_debug_client_show(struct seq_file *s, void *unused) { struct ion_client *client = s->private; @@ -685,6 +713,14 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) const char *names[ION_NUM_HEAP_IDS] = {NULL}; int i; + mutex_lock(&debugfs_mutex); + if (!is_client_alive(client)) { + seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n", + client); + mutex_unlock(&debugfs_mutex); + return 0; + } + mutex_lock(&client->lock); for (n = rb_first(&client->handles); n; n = rb_next(n)) { struct ion_handle *handle = rb_entry(n, struct ion_handle, @@ -696,6 +732,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused) sizes[id] += handle->buffer->size; } mutex_unlock(&client->lock); + mutex_unlock(&debugfs_mutex); seq_printf(s, "%16.16s: %16.16s\n", "heap_name", "size_in_bytes"); for (i = 0; i < ION_NUM_HEAP_IDS; i++) { @@ -832,6 +869,7 @@ void ion_client_destroy(struct ion_client *client) struct rb_node *n; pr_debug("%s: %d\n", __func__, __LINE__); + mutex_lock(&debugfs_mutex); while ((n = rb_first(&client->handles))) { struct ion_handle *handle = rb_entry(n, struct ion_handle, node); @@ -850,6 +888,7 @@ void ion_client_destroy(struct ion_client *client) kfree(client->display_name); kfree(client->name); kfree(client); + mutex_unlock(&debugfs_mutex); } EXPORT_SYMBOL(ion_client_destroy); @@ -1415,6 +1454,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size"); seq_puts(s, "----------------------------------------------------\n"); + mutex_lock(&debugfs_mutex); for (n = rb_first(&dev->clients); n; n = rb_next(n)) { struct ion_client *client = rb_entry(n, struct ion_client, node); @@ -1433,6 +1473,8 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused) client->pid, size); } } + mutex_unlock(&debugfs_mutex); + seq_puts(s, "----------------------------------------------------\n"); seq_puts(s, "orphaned allocations (info is from last known client):\n"); mutex_lock(&dev->buffer_lock); @@ -1617,6 +1659,8 @@ debugfs_done: init_rwsem(&idev->lock); plist_head_init(&idev->heaps); idev->clients = RB_ROOT; + ion_root_client = &idev->clients; + mutex_init(&debugfs_mutex); return idev; } EXPORT_SYMBOL(ion_device_create); -- cgit From b0e302b40873c0418aacaad2aa455bf867c9d1a2 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 1 Feb 2016 11:33:00 +0100 Subject: staging: goldfish: use div64_s64 instead of do_div The goldfish nand driver divides a signed 64-bit number (loff_t) in multiple places using the do_div() function. This has always been unreliable but now produces a compiler warning (since 4.5-rc1): goldfish/goldfish_nand.c: In function 'goldfish_nand_erase': goldfish/goldfish_nand.c:107:91: error: comparison of distinct pointer types lacks a cast [-Werror] goldfish/goldfish_nand.c: In function 'goldfish_nand_read_oob': goldfish/goldfish_nand.c:145:91: error: comparison of distinct pointer types lacks a cast [-Werror] This changes the code to the equivalent div_s64{,_rem} that works correctly for negative numbers (which we should never get here). The warning has shown up on ARM allmodconfig builds after the goldfish bus driver has become visible on ARM. Signed-off-by: Arnd Bergmann Fixes: bd2f348db503 ("goldfish: refactor goldfish platform configs") Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_nand.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/staging/goldfish/goldfish_nand.c b/drivers/staging/goldfish/goldfish_nand.c index f223b3a5a428..76d60eed1490 100644 --- a/drivers/staging/goldfish/goldfish_nand.c +++ b/drivers/staging/goldfish/goldfish_nand.c @@ -100,11 +100,11 @@ static int goldfish_nand_erase(struct mtd_info *mtd, struct erase_info *instr) { loff_t ofs = instr->addr; u32 len = instr->len; - u32 rem; + s32 rem; if (ofs + len > mtd->size) goto invalid_arg; - rem = do_div(ofs, mtd->writesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= (mtd->writesize + mtd->oobsize); @@ -133,7 +133,7 @@ invalid_arg: static int goldfish_nand_read_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops) { - u32 rem; + s32 rem; if (ofs + ops->len > mtd->size) goto invalid_arg; @@ -142,7 +142,7 @@ static int goldfish_nand_read_oob(struct mtd_info *mtd, loff_t ofs, if (ops->ooblen + ops->ooboffs > mtd->oobsize) goto invalid_arg; - rem = do_div(ofs, mtd->writesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= (mtd->writesize + mtd->oobsize); @@ -165,7 +165,7 @@ invalid_arg: static int goldfish_nand_write_oob(struct mtd_info *mtd, loff_t ofs, struct mtd_oob_ops *ops) { - u32 rem; + s32 rem; if (ofs + ops->len > mtd->size) goto invalid_arg; @@ -174,7 +174,7 @@ static int goldfish_nand_write_oob(struct mtd_info *mtd, loff_t ofs, if (ops->ooblen + ops->ooboffs > mtd->oobsize) goto invalid_arg; - rem = do_div(ofs, mtd->writesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= (mtd->writesize + mtd->oobsize); @@ -197,12 +197,12 @@ invalid_arg: static int goldfish_nand_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - u32 rem; + s32 rem; if (from + len > mtd->size) goto invalid_arg; - rem = do_div(from, mtd->writesize); + from = div_s64_rem(from, mtd->writesize, &rem); if (rem) goto invalid_arg; from *= (mtd->writesize + mtd->oobsize); @@ -219,12 +219,12 @@ invalid_arg: static int goldfish_nand_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - u32 rem; + s32 rem; if (to + len > mtd->size) goto invalid_arg; - rem = do_div(to, mtd->writesize); + to = div_s64_rem(to, mtd->writesize, &rem); if (rem) goto invalid_arg; to *= (mtd->writesize + mtd->oobsize); @@ -240,12 +240,12 @@ invalid_arg: static int goldfish_nand_block_isbad(struct mtd_info *mtd, loff_t ofs) { - u32 rem; + s32 rem; if (ofs >= mtd->size) goto invalid_arg; - rem = do_div(ofs, mtd->erasesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= mtd->erasesize / mtd->writesize; @@ -261,12 +261,12 @@ invalid_arg: static int goldfish_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - u32 rem; + s32 rem; if (ofs >= mtd->size) goto invalid_arg; - rem = do_div(ofs, mtd->erasesize); + ofs = div_s64_rem(ofs, mtd->writesize, &rem); if (rem) goto invalid_arg; ofs *= mtd->erasesize / mtd->writesize; @@ -321,7 +321,7 @@ static int goldfish_nand_init_device(struct platform_device *pdev, mtd->oobavail = mtd->oobsize; mtd->erasesize = readl(base + NAND_DEV_ERASE_SIZE) / (mtd->writesize + mtd->oobsize) * mtd->writesize; - do_div(mtd->size, mtd->writesize + mtd->oobsize); + mtd->size = div_s64(mtd->size, mtd->writesize + mtd->oobsize); mtd->size *= mtd->writesize; dev_dbg(&pdev->dev, "goldfish nand dev%d: size %llx, page %d, extra %d, erase %d\n", -- cgit From 2ce601b033376905d585e0825d5499616a22b565 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 09:38:21 +0100 Subject: staging: goldfish: (coding style) Add spaces around the "+" to conform to checkpatch Added a space around the "+" at: "reg_base+addr2" to clear up a checkpatch check. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index b0927e49d0a8..f1e18386e34d 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -63,7 +63,7 @@ struct goldfish_audio { #define AUDIO_READ(data, addr) (readl(data->reg_base + addr)) #define AUDIO_WRITE(data, addr, x) (writel(x, data->reg_base + addr)) #define AUDIO_WRITE64(data, addr, addr2, x) \ - (gf_write_dma_addr((x), data->reg_base + addr, data->reg_base+addr2)) + (gf_write_dma_addr((x), data->reg_base + addr, data->reg_base + addr2)) /* * temporary variable used between goldfish_audio_probe() and -- cgit From 269ad6e018146dafb70c9a40e546f73752d44db2 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Thu, 19 Nov 2015 09:47:24 +0100 Subject: staging: goldfish: (coding style) Rewrite comparisons to NULL as "!data->reg_base" Rewrite comparisons to NULL "data->reg_base == NULL" as "!data->reg_base" to conform to checkpatch. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index f1e18386e34d..364fdcdd3a06 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -280,12 +280,12 @@ static int goldfish_audio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { + if (!r) { dev_err(&pdev->dev, "platform_get_resource failed\n"); return -ENODEV; } data->reg_base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); - if (data->reg_base == NULL) + if (!data->reg_base) return -ENOMEM; data->irq = platform_get_irq(pdev, 0); @@ -295,7 +295,7 @@ static int goldfish_audio_probe(struct platform_device *pdev) } data->buffer_virt = dmam_alloc_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, &buf_addr, GFP_KERNEL); - if (data->buffer_virt == NULL) { + if (!data->buffer_virt) { dev_err(&pdev->dev, "allocate buffer failed\n"); return -ENOMEM; } -- cgit From 65dc15079604b6a96194513f36425b9df6629c79 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Mon, 11 Jan 2016 21:34:28 +0530 Subject: staging: comedi: dt2801: Prefer using the BIT macro As suggested by checkpatch.pl, this patch replaces bit shifting on 1 with the BIT(x) macro. Signed-off-by: Bhaktipriya Shridhar Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/dt2801.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c index 80e38dedd359..6c7b4d27c27c 100644 --- a/drivers/staging/comedi/drivers/dt2801.c +++ b/drivers/staging/comedi/drivers/dt2801.c @@ -68,17 +68,17 @@ Configuration options: /* Command modifiers (only used with read/write), EXTTRIG can be used with some other commands. */ -#define DT_MOD_DMA (1<<4) -#define DT_MOD_CONT (1<<5) -#define DT_MOD_EXTCLK (1<<6) -#define DT_MOD_EXTTRIG (1<<7) +#define DT_MOD_DMA BIT(4) +#define DT_MOD_CONT BIT(5) +#define DT_MOD_EXTCLK BIT(6) +#define DT_MOD_EXTTRIG BIT(7) /* Bits in status register */ -#define DT_S_DATA_OUT_READY (1<<0) -#define DT_S_DATA_IN_FULL (1<<1) -#define DT_S_READY (1<<2) -#define DT_S_COMMAND (1<<3) -#define DT_S_COMPOSITE_ERROR (1<<7) +#define DT_S_DATA_OUT_READY BIT(0) +#define DT_S_DATA_IN_FULL BIT(1) +#define DT_S_READY BIT(2) +#define DT_S_COMMAND BIT(3) +#define DT_S_COMPOSITE_ERROR BIT(7) /* registers */ #define DT2801_DATA 0 -- cgit From d4631301225a44d36b98ce39a2e3d6e00f59d8fb Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Mon, 11 Jan 2016 23:29:33 -0700 Subject: staging: comedi: ni_pcimio: Adds PXI-6251 to supported boards Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_pcimio.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 30a5a75d1fe7..231e37d6b7c6 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -26,7 +26,8 @@ Devices: [National Instruments] PCI-MIO-16XE-50 (ni_pcimio), PXI-6040E, PCI-6030E, PCI-6031E, PCI-6032E, PCI-6033E, PCI-6071E, PCI-6023E, PCI-6024E, PCI-6025E, PXI-6025E, PCI-6034E, PCI-6035E, PCI-6052E, PCI-6110, PCI-6111, PCI-6220, PCI-6221, PCI-6224, PXI-6224, - PCI-6225, PXI-6225, PCI-6229, PCI-6250, PCI-6251, PCIe-6251, PXIe-6251, + PCI-6225, PXI-6225, PCI-6229, PCI-6250, + PCI-6251, PXI-6251, PCIe-6251, PXIe-6251, PCI-6254, PCI-6259, PCIe-6259, PCI-6280, PCI-6281, PXI-6281, PCI-6284, PCI-6289, PCI-6711, PXI-6711, PCI-6713, PXI-6713, @@ -193,6 +194,7 @@ enum ni_pcimio_boardid { BOARD_PCI6229, BOARD_PCI6250, BOARD_PCI6251, + BOARD_PXI6251, BOARD_PCIE6251, BOARD_PXIE6251, BOARD_PCI6254, @@ -811,6 +813,21 @@ static const struct ni_board_struct ni_boards[] = { .ao_speed = 350, .caldac = { caldac_none }, }, + [BOARD_PXI6251] = { + .name = "pxi-6251", + .n_adchan = 16, + .ai_maxdata = 0xffff, + .ai_fifo_depth = 4095, + .gainlkup = ai_gain_628x, + .ai_speed = 800, + .n_aochan = 2, + .ao_maxdata = 0xffff, + .ao_fifo_depth = 8191, + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_speed = 350, + .caldac = { caldac_none }, + }, [BOARD_PCIE6251] = { .name = "pcie-6251", .n_adchan = 16, @@ -1290,6 +1307,7 @@ static const struct pci_device_id ni_pcimio_pci_table[] = { { PCI_VDEVICE(NI, 0x71bc), BOARD_PCI6221_37PIN }, { PCI_VDEVICE(NI, 0x717d), BOARD_PCIE6251 }, { PCI_VDEVICE(NI, 0x72e8), BOARD_PXIE6251 }, + { PCI_VDEVICE(NI, 0x70ad), BOARD_PXI6251 }, { 0 } }; MODULE_DEVICE_TABLE(pci, ni_pcimio_pci_table); -- cgit From 1fd24a4702d2af0ea4d5845126cf57d4d1796216 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Tue, 12 Jan 2016 10:33:18 -0700 Subject: staging: comedi: ni_tiocmd: change mistaken use of start_src for start_arg This fixes a bug in function ni_tio_input_inttrig(). The trigger number should be compared to cmd->start_arg, not cmd->start_src. Fixes: 6a760394d7eb ("staging: comedi: ni_tiocmd: clarify the cmd->start_arg validation and use") Cc: # 3.17+ Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_tiocmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_tiocmd.c b/drivers/staging/comedi/drivers/ni_tiocmd.c index 437f723bb34d..823e47910004 100644 --- a/drivers/staging/comedi/drivers/ni_tiocmd.c +++ b/drivers/staging/comedi/drivers/ni_tiocmd.c @@ -92,7 +92,7 @@ static int ni_tio_input_inttrig(struct comedi_device *dev, unsigned long flags; int ret = 0; - if (trig_num != cmd->start_src) + if (trig_num != cmd->start_arg) return -EINVAL; spin_lock_irqsave(&counter->lock, flags); -- cgit From f08a28e65cbdf80b4b4da7e423c45ee7c3ef35ac Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Tue, 12 Jan 2016 11:05:10 -0700 Subject: staging: comedi: ni_mio_common: use CR_CHAN more consistently Generally, the CR_CHAN macro is/should be used to access the relevant bits for channel identification in cmd->*_arg when the corresponding cmd->*_src==TRIG_EXT, including cmd->convert_arg in this case. This patch does not fix a bug per se, as NISTC_AI_MODE1_CONVERT_SRC() already masks the value sufficiently, but using CR_CHAN() here makes the code clearer as it avoids passing some irrelevant bits to NISTC_AI_MODE1_CONVERT_SRC() in the first place. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 5e8130a7d670..1978d65636fd 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2428,7 +2428,8 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); break; case TRIG_EXT: - mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg); + mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + + CR_CHAN(cmd->convert_arg)); if ((cmd->convert_arg & CR_INVERT) == 0) mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY; ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); -- cgit From 5b293beb2ef0c45cd3c0e00ce67930b5d3471c13 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:24 -0700 Subject: staging: comedi: mite: enable continuous regeneration of finite samples This change enables the mite DMA controller to only transfer the amount of data needed by a command. By default, the old behavior of transferring the entire comedi DMA data buffer is still in effect. These changes allow a command to only transmit a limited portion of that data buffer as needed. This patch begins to reinterprets stop_arg when stop_src == TRIG_NONE to allow the user to specify the length of the buffer that should be repeated. The intent is to allow a user to have a specific buffer repeated as-is indefinitely. The contents of the DMA buffer can be left static or changed by the user via mmap access to the DMA buffer. If the contents are changed by the user, additional munging is not performed by the driver and only a single call to comedi_mark_buffer_written should be done. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/mite.c | 72 ++++++++++++++++++++++++++++++----- drivers/staging/comedi/drivers/mite.h | 3 ++ 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/drivers/staging/comedi/drivers/mite.c b/drivers/staging/comedi/drivers/mite.c index fa7ae2c04556..8f24702c3380 100644 --- a/drivers/staging/comedi/drivers/mite.c +++ b/drivers/staging/comedi/drivers/mite.c @@ -297,7 +297,6 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, { struct comedi_async *async = s->async; unsigned int n_links; - int i; if (ring->descriptors) { dma_free_coherent(ring->hw_dev, @@ -326,17 +325,58 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, } ring->n_links = n_links; - for (i = 0; i < n_links; i++) { + return mite_init_ring_descriptors(ring, s, n_links << PAGE_SHIFT); +} +EXPORT_SYMBOL_GPL(mite_buf_change); + +/* + * initializes the ring buffer descriptors to provide correct DMA transfer links + * to the exact amount of memory required. When the ring buffer is allocated in + * mite_buf_change, the default is to initialize the ring to refer to the entire + * DMA data buffer. A command may call this function later to re-initialize and + * shorten the amount of memory that will be transferred. + */ +int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring, + struct comedi_subdevice *s, + unsigned int nbytes) +{ + struct comedi_async *async = s->async; + unsigned int n_full_links = nbytes >> PAGE_SHIFT; + unsigned int remainder = nbytes % PAGE_SIZE; + int i; + + dev_dbg(s->device->class_dev, + "mite: init ring buffer to %u bytes\n", nbytes); + + if ((n_full_links + (remainder > 0 ? 1 : 0)) > ring->n_links) { + dev_err(s->device->class_dev, + "mite: ring buffer too small for requested init\n"); + return -ENOMEM; + } + + /* We set the descriptors for all full links. */ + for (i = 0; i < n_full_links; ++i) { ring->descriptors[i].count = cpu_to_le32(PAGE_SIZE); ring->descriptors[i].addr = cpu_to_le32(async->buf_map->page_list[i].dma_addr); ring->descriptors[i].next = - cpu_to_le32(ring->descriptors_dma_addr + (i + - 1) * - sizeof(struct mite_dma_descriptor)); + cpu_to_le32(ring->descriptors_dma_addr + + (i + 1) * sizeof(struct mite_dma_descriptor)); } - ring->descriptors[n_links - 1].next = - cpu_to_le32(ring->descriptors_dma_addr); + + /* the last link is either a remainder or was a full link. */ + if (remainder > 0) { + /* set the lesser count for the remainder link */ + ring->descriptors[i].count = cpu_to_le32(remainder); + ring->descriptors[i].addr = + cpu_to_le32(async->buf_map->page_list[i].dma_addr); + /* increment i so that assignment below refs last link */ + ++i; + } + + /* Assign the last link->next to point back to the head of the list. */ + ring->descriptors[i - 1].next = cpu_to_le32(ring->descriptors_dma_addr); + /* * barrier is meant to insure that all the writes to the dma descriptors * have completed before the dma controller is commanded to read them @@ -344,7 +384,7 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, smp_wmb(); return 0; } -EXPORT_SYMBOL_GPL(mite_buf_change); +EXPORT_SYMBOL_GPL(mite_init_ring_descriptors); void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits) @@ -552,6 +592,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, unsigned int old_alloc_count = async->buf_read_alloc_count; u32 nbytes_ub, nbytes_lb; int count; + bool finite_regen = (cmd->stop_src == TRIG_NONE && stop_count != 0); /* read alloc as much as we can */ comedi_buf_read_alloc(s, async->prealloc_bufsz); @@ -561,11 +602,24 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, nbytes_ub = mite_bytes_read_from_memory_ub(mite_chan); if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_ub - stop_count) > 0) nbytes_ub = stop_count; - if ((int)(nbytes_ub - old_alloc_count) > 0) { + + if ((!finite_regen || stop_count > old_alloc_count) && + ((int)(nbytes_ub - old_alloc_count) > 0)) { dev_warn(s->device->class_dev, "mite: DMA underrun\n"); async->events |= COMEDI_CB_OVERFLOW; return -1; } + + if (finite_regen) { + /* + * This is a special case where we continuously output a finite + * buffer. In this case, we do not free any of the memory, + * hence we expect that old_alloc_count will reach a maximum of + * stop_count bytes. + */ + return 0; + } + count = nbytes_lb - async->buf_read_count; if (count <= 0) return 0; diff --git a/drivers/staging/comedi/drivers/mite.h b/drivers/staging/comedi/drivers/mite.h index c32d4e4ddccc..87534b07ec81 100644 --- a/drivers/staging/comedi/drivers/mite.h +++ b/drivers/staging/comedi/drivers/mite.h @@ -110,6 +110,9 @@ void mite_prep_dma(struct mite_channel *mite_chan, unsigned int num_device_bits, unsigned int num_memory_bits); int mite_buf_change(struct mite_dma_descriptor_ring *ring, struct comedi_subdevice *s); +int mite_init_ring_descriptors(struct mite_dma_descriptor_ring *ring, + struct comedi_subdevice *s, + unsigned int nbytes); enum mite_registers { /* -- cgit From 5c93736c208d89c7832624b8f3a2ce616473ab65 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:25 -0700 Subject: staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_reset This patch implements ni_ao_reset much more closely organized like NI MHDDK examples and DAQ-STC pseudo-code. Adds comments with some more specific references to the DAQ-STC. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 70 +++++++++++++++++--------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1978d65636fd..7d2091d8b72b 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3215,48 +3215,70 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) { + /* See 3.6.1.2 "Resetting", of DAQ-STC Technical Reference Manual */ + + /* + * In the following, the "--sync" comments are meant to denote + * asynchronous boundaries for setting the registers as described in the + * DAQ-STC mostly in the order also described in the DAQ-STC. + */ + struct ni_private *devpriv = dev->private; ni_release_ao_mite_channel(dev); + /* --sync (reset AO) */ + if (devpriv->is_m_series) + /* following example in mhddk for m-series */ + ni_stc_writew(dev, NISTC_RESET_AO, NISTC_RESET_REG); + + /*--sync (start config) */ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + + /*--sync (Disarm) */ ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); - ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); - ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); - ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); - ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL | - NISTC_AO_PERSONAL_UPDATE_PW | - NISTC_AO_PERSONAL_TMRDACWR_PW, - NISTC_AO_PERSONAL_REG); - ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG); - ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG); - devpriv->ao_cmd1 = 0; - ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); - devpriv->ao_cmd2 = 0; - ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); + + /* + * --sync + * (clear bunch of registers--mseries mhddk examples do not include + * this) + */ + devpriv->ao_cmd1 = 0; + devpriv->ao_cmd2 = 0; devpriv->ao_mode1 = 0; - ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); devpriv->ao_mode2 = 0; - ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); if (devpriv->is_m_series) devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE; else devpriv->ao_mode3 = 0; - ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); devpriv->ao_trigger_select = 0; - ni_stc_writew(dev, devpriv->ao_trigger_select, - NISTC_AO_TRIG_SEL_REG); - if (devpriv->is_6xxx) { - unsigned immediate_bits = 0; - unsigned i; - for (i = 0; i < s->n_chan; ++i) - immediate_bits |= 1 << i; - ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG); + ni_stc_writew(dev, 0, NISTC_AO_PERSONAL_REG); + ni_stc_writew(dev, 0, NISTC_AO_CMD1_REG); + ni_stc_writew(dev, 0, NISTC_AO_CMD2_REG); + ni_stc_writew(dev, 0, NISTC_AO_MODE1_REG); + ni_stc_writew(dev, 0, NISTC_AO_MODE2_REG); + ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG); + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); + ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG); + ni_stc_writew(dev, 0, NISTC_AO_TRIG_SEL_REG); + + /*--sync (disable interrupts) */ + ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); + + /*--sync (ack) */ + ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); + ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); + + /*--not in DAQ-STC. which doc? */ + if (devpriv->is_6xxx) { + ni_ao_win_outw(dev, (1u << s->n_chan) - 1u, + NI671X_AO_IMMEDIATE_REG); ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, NI611X_AO_MISC_REG); } ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); + /*--end */ return 0; } -- cgit From d2a6c32a2209ac79cb52b56e46ec37fdc1df6ce1 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:26 -0700 Subject: staging: comedi: ni_mio_common: make more bits in ao_cmd1 reg be stateful Bits NISTC_AO_CMD1_DAC0_UPDATE_MODE and NISTC_AO_CMD1_DAC1_UPDATE_MODE are now saved in the local copy of the AO_CMD1 register. This is more appropriate than prior methods of setting these bits specifically _both_ in the ni_ao_cmd configuration function _and_ the ni_ao_inttrig trigger function. With this patch, the bits are only specifically called out now in the ni_ao_cmd configuration function. In the ni_ao_inttrig trigger function, only the UI_ARM, UC_ARM, BC_ARM bits of the ao_cmd1 register are specifically called out. Each of these bits is a strobe bit, while the DAC[0-1]_UPDATE_MODE bits are simple write bits. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 7d2091d8b72b..9df20d922d32 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2903,8 +2903,6 @@ static int ni_ao_inttrig(struct comedi_device *dev, ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM | NISTC_AO_CMD1_UC_ARM | NISTC_AO_CMD1_BC_ARM | - NISTC_AO_CMD1_DAC1_UPDATE_MODE | - NISTC_AO_CMD1_DAC0_UPDATE_MODE | devpriv->ao_cmd1, NISTC_AO_CMD1_REG); @@ -3081,9 +3079,11 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE | - NISTC_AO_CMD1_DAC0_UPDATE_MODE, - NISTC_AO_CMD1_REG); + /* Configure DAQ-STC for Timed update mode */ + devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | + NISTC_AO_CMD1_DAC0_UPDATE_MODE; + /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ + ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); -- cgit From 080e6795cba316663a5eb4f49500937eca4f32cd Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:27 -0700 Subject: staging: comedi: ni_mio_common: Cleans up/clarifies ni_ao_cmd This patch implements ni_ao_cmd much more closely organized like NI MHDDK examples and DAQ-STC pseudo-code. Adds comments with some more specific references to the DAQ-STC. For stop_src==TRIG_NONE (continuous output mode of entire buffer), the count for the UC counter was corrected to represent the maximum count possible (0xffffff). Prior behavior for stop_src=TRIG_NONE did not actually follow the DAQ-STC. Furthermore, stop_src==TRIG_NONE now correctly uses code specialized for either m-series or e-series devices. It should be noted that stop_src==TRIG_NONE does _not_ with this patch (or with prior behavior in ni_mio_common) actually implement true continuous output. Rather, the output is simply configured to operate as a single buffer output, but where the buffer is as large as is possible with NI-STC hardware. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 443 ++++++++++++++++++------- 1 file changed, 318 insertions(+), 125 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 9df20d922d32..8f0fe3a26c73 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2912,42 +2912,68 @@ static int ni_ao_inttrig(struct comedi_device *dev, return 0; } -static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +/* + * begin ni_ao_cmd. + * Organized similar to NI-STC and MHDDK examples. + * ni_ao_cmd is broken out into configuration sub-routines for clarity. + */ + +static void ni_ao_cmd_personalize(struct comedi_device *dev, + const struct comedi_cmd *cmd) { const struct ni_board_struct *board = dev->board_ptr; - struct ni_private *devpriv = dev->private; - const struct comedi_cmd *cmd = &s->async->cmd; - int bits; - int i; - unsigned trigvar; - unsigned val; - - if (dev->irq == 0) { - dev_err(dev->class_dev, "cannot run command without an irq\n"); - return -EIO; - } + unsigned bits; ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); + bits = + /* fast CPU interface--only eseries */ + /* ((slow CPU interface) ? 0 : AO_Fast_CPU) | */ + NISTC_AO_PERSONAL_BC_SRC_SEL | + 0 /* (use_original_pulse ? 0 : NISTC_AO_PERSONAL_UPDATE_TIMEBASE) */ | + /* + * FIXME: start setting following bit when appropriate. Need to + * determine whether board is E4 or E1. + * FROM MHHDK: + * if board is E4 or E1 + * Set bit "NISTC_AO_PERSONAL_UPDATE_PW" to 0 + * else + * set it to 1 + */ + NISTC_AO_PERSONAL_UPDATE_PW | + /* FIXME: when should we set following bit to zero? */ + NISTC_AO_PERSONAL_TMRDACWR_PW | + (board->ao_fifo_depth ? + NISTC_AO_PERSONAL_FIFO_ENA : NISTC_AO_PERSONAL_DMA_PIO_CTRL) + ; +#if 0 + /* + * FIXME: + * add something like ".has_individual_dacs = 0" to ni_board_struct + * since, as F Hess pointed out, not all in m series have singles. not + * sure if e-series all have duals... + */ - if (devpriv->is_6xxx) { - ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, - NI611X_AO_MISC_REG); + /* + * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit for + * 6281, verified with bus analyzer. + */ + if (devpriv->is_m_series) + bits |= NISTC_AO_PERSONAL_NUM_DAC; +#endif + ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); - bits = 0; - for (i = 0; i < cmd->chanlist_len; i++) { - int chan; + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} - chan = CR_CHAN(cmd->chanlist[i]); - bits |= 1 << chan; - ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG); - } - ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG); - } +static void ni_ao_cmd_set_trigger(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; - ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + /* sync */ if (cmd->stop_src == TRIG_NONE) { devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS; devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE; @@ -2957,179 +2983,346 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); - val = devpriv->ao_trigger_select; - switch (cmd->start_src) { - case TRIG_INT: - case TRIG_NOW: - val &= ~(NISTC_AO_TRIG_START1_POLARITY | - NISTC_AO_TRIG_START1_SEL_MASK); - val |= NISTC_AO_TRIG_START1_EDGE | - NISTC_AO_TRIG_START1_SYNC; - break; - case TRIG_EXT: - val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1); - if (cmd->start_arg & CR_INVERT) { - /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ - val |= NISTC_AO_TRIG_START1_POLARITY; - } - if (cmd->start_arg & CR_EDGE) { - /* 0=edge detection disabled, 1=enabled */ - val |= NISTC_AO_TRIG_START1_EDGE; + { + unsigned int trigsel = devpriv->ao_trigger_select; + + switch (cmd->start_src) { + case TRIG_INT: + case TRIG_NOW: + trigsel &= ~(NISTC_AO_TRIG_START1_POLARITY | + NISTC_AO_TRIG_START1_SEL_MASK); + trigsel |= NISTC_AO_TRIG_START1_EDGE | + NISTC_AO_TRIG_START1_SYNC; + break; + case TRIG_EXT: + trigsel = NISTC_AO_TRIG_START1_SEL( + CR_CHAN(cmd->start_arg) + 1); + if (cmd->start_arg & CR_INVERT) + /* + * 0=active high, 1=active low. + * see daq-stc 3-24 (p186) + */ + trigsel |= NISTC_AO_TRIG_START1_POLARITY; + if (cmd->start_arg & CR_EDGE) + /* 0=edge detection disabled, 1=enabled */ + trigsel |= NISTC_AO_TRIG_START1_EDGE; + break; + default: + BUG(); + break; } + + devpriv->ao_trigger_select = trigsel; ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG); - break; - default: - BUG(); - break; } - devpriv->ao_trigger_select = val; - ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG); + /* AO_Delayed_START1 = 0, we do not support delayed start...yet */ + /* sync */ + /* select DA_START1 as PFI6/AO_START1 when configured as an output */ devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN; ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_counters(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; + /* Not supporting 'waveform staging' or 'local buffer with pauses' */ + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + /* + * This relies on ao_mode1/(Trigger_Once | Continuous) being set in + * set_trigger above. It is unclear whether we really need to re-write + * this register with these values. The mhddk examples for e-series + * show writing this in both places, but the examples for m-series show + * a single write in the set_counters function (here). + */ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + + /* sync (upload number of buffer iterations -1) */ + /* indicate that we want to use BC_Load_A_Register as the source */ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - if (cmd->stop_src == TRIG_NONE) - ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG); - else - ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); + + /* + * if the BC_TC interrupt is still issued in spite of UC, BC, UI + * ignoring BC_TC, then we will need to find a way to ignore that + * interrupt in continuous mode. + */ + ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); /* iter once */ + + /* sync (issue command to load number of buffer iterations -1) */ ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG); + + /* sync (upload number of updates in buffer) */ + /* indicate that we want to use UC_Load_A_Register as the source */ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - switch (cmd->stop_src) { - case TRIG_COUNT: + + { + /* + * Current behavior is to configure the maximum update count + * possible when continuous output mode is requested. + */ + unsigned int stop_arg = cmd->stop_src == TRIG_COUNT ? + (cmd->stop_arg & 0xffffff) : 0xffffff; + if (devpriv->is_m_series) { - /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ - ni_stc_writel(dev, cmd->stop_arg - 1, - NISTC_AO_UC_LOADA_REG); + /* + * this is how the NI example code does it for m-series + * boards, verified correct with 6259 + */ + ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG); + + /* sync (issue cmd to load number of updates in MISB) */ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); } else { - ni_stc_writel(dev, cmd->stop_arg, - NISTC_AO_UC_LOADA_REG); + ni_stc_writel(dev, stop_arg, NISTC_AO_UC_LOADA_REG); + + /* sync (issue cmd to load number of updates in MISB) */ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, cmd->stop_arg - 1, - NISTC_AO_UC_LOADA_REG); + + /* + * sync (upload number of updates-1 in MISB) + * --eseries only? + */ + ni_stc_writel(dev, stop_arg - 1, NISTC_AO_UC_LOADA_REG); } - break; - case TRIG_NONE: - ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); - break; - default: - ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG); } - devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK | - NISTC_AO_MODE1_UI_SRC_MASK | - NISTC_AO_MODE1_UPDATE_SRC_POLARITY | - NISTC_AO_MODE1_UI_SRC_POLARITY); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_update(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + + /* + * zero out these bit fields to be set below. Does an ao-reset do this + * automatically? + */ + devpriv->ao_mode1 &= ~( + NISTC_AO_MODE1_UI_SRC_MASK | + NISTC_AO_MODE1_UI_SRC_POLARITY | + NISTC_AO_MODE1_UPDATE_SRC_MASK | + NISTC_AO_MODE1_UPDATE_SRC_POLARITY + ); + switch (cmd->scan_begin_src) { case TRIG_TIMER: - devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; - trigvar = - ni_ns_to_timer(dev, cmd->scan_begin_arg, - CMDF_ROUND_NEAREST); - ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); - ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); - ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG); + devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; + + /* + * NOTE: there are several other ways of configuring internal + * updates, but we'll only support one for now: using + * AO_IN_TIMEBASE, w/o waveform staging, w/o a delay between + * START1 and first update, and also w/o local buffer mode w/ + * pauses. + */ + + /* + * This is already done above: + * devpriv->ao_mode1 &= ~( + * // set UPDATE_Source to UI_TC: + * NISTC_AO_MODE1_UPDATE_SRC_MASK | + * // set UPDATE_Source_Polarity to rising (required?) + * NISTC_AO_MODE1_UPDATE_SRC_POLARITY | + * // set UI_Source to AO_IN_TIMEBASE1: + * NISTC_AO_MODE1_UI_SRC_MASK | + * // set UI_Source_Polarity to rising (required?) + * NISTC_AO_MODE1_UI_SRC_POLARITY + * ); + */ + + /* + * TODO: use ao_ui_clock_source to allow all possible signals + * to be routed to UI_Source_Select. See tSTC.h for + * eseries/ni67xx and tMSeries.h for mseries. + */ + + { + unsigned trigvar = ni_ns_to_timer(dev, + cmd->scan_begin_arg, + CMDF_ROUND_NEAREST); + + /* + * Wait N TB3 ticks after the start trigger before + * clocking(N must be >=2). + */ + /* following line: 2-1 per STC */ + ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); + ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, + NISTC_AO_CMD1_REG); + /* following line: N-1 per STC */ + ni_stc_writel(dev, trigvar - 1, NISTC_AO_UI_LOADA_REG); + } break; case TRIG_EXT: - devpriv->ao_mode1 |= - NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg); + /* FIXME: assert scan_begin_arg != 0, ret failure otherwise */ + devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; + devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC( + CR_CHAN(cmd->scan_begin_arg)); if (cmd->scan_begin_arg & CR_INVERT) devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY; - devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; break; default: BUG(); break; } + ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) | NISTC_AO_MODE2_UI_INIT_LOAD_SRC); ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); + /* Configure DAQ-STC for Timed update mode */ + devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | + NISTC_AO_CMD1_DAC0_UPDATE_MODE; + /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ + ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_channels(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + struct ni_private *devpriv = dev->private; + const struct comedi_cmd *cmd = &s->async->cmd; + unsigned bits = 0; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + + if (devpriv->is_6xxx) { + unsigned int i; + + bits = 0; + for (i = 0; i < cmd->chanlist_len; ++i) { + int chan = CR_CHAN(cmd->chanlist[i]); + + bits |= 1 << chan; + ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG); + } + ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG); + } + + ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); + if (cmd->scan_end_arg > 1) { devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN; - ni_stc_writew(dev, - NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) | - NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ, - NISTC_AO_OUT_CTRL_REG); - } else { - unsigned bits; + bits = NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) + | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; + } else { devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN; bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; - if (devpriv->is_m_series || devpriv->is_6xxx) { + if (devpriv->is_m_series | devpriv->is_6xxx) bits |= NISTC_AO_OUT_CTRL_CHANS(0); - } else { - bits |= - NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0])); - } - ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG); + else + bits |= NISTC_AO_OUT_CTRL_CHANS( + CR_CHAN(cmd->chanlist[0])); } + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); + ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG); - /* Configure DAQ-STC for Timed update mode */ - devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | - NISTC_AO_CMD1_DAC0_UPDATE_MODE; - /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ - ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev, + const struct comedi_cmd *cmd) +{ + struct ni_private *devpriv = dev->private; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); + /* + * Since we are not supporting waveform staging, we ignore these errors: + * NISTC_AO_MODE3_STOP_ON_BC_TC_ERR, + * NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR + */ + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); +} + +static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev) +{ + struct ni_private *devpriv = dev->private; + + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK; #ifdef PCIDMA devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F; #else devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF; #endif + /* NOTE: this is where use_onboard_memory=True would be implemented */ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); - bits = NISTC_AO_PERSONAL_BC_SRC_SEL | - NISTC_AO_PERSONAL_UPDATE_PW | - NISTC_AO_PERSONAL_TMRDACWR_PW; - if (board->ao_fifo_depth) - bits |= NISTC_AO_PERSONAL_FIFO_ENA; - else - bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL; -#if 0 - /* - * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit - * for 6281, verified with bus analyzer. - */ - if (devpriv->is_m_series) - bits |= NISTC_AO_PERSONAL_NUM_DAC; -#endif - ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); - /* enable sending of ao dma requests */ + /* enable sending of ao fifo requests (dma request) */ ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG); ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); - if (cmd->stop_src == TRIG_COUNT) { - ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC, - NISTC_INTB_ACK_REG); + /* we are not supporting boards with virtual fifos */ +} + +static void ni_ao_cmd_set_interrupts(struct comedi_device *dev, + struct comedi_subdevice *s) +{ + if (s->async->cmd.stop_src == TRIG_COUNT) ni_set_bits(dev, NISTC_INTB_ENA_REG, NISTC_INTB_ENA_AO_BC_TC, 1); - } s->async->inttrig = ni_ao_inttrig; +} +static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +{ + struct ni_private *devpriv = dev->private; + const struct comedi_cmd *cmd = &s->async->cmd; + + if (dev->irq == 0) { + dev_err(dev->class_dev, "cannot run command without an irq"); + return -EIO; + } + + /* ni_ao_reset should have already been done */ + ni_ao_cmd_personalize(dev, cmd); + /* clearing fifo and preload happens elsewhere */ + + ni_ao_cmd_set_trigger(dev, cmd); + ni_ao_cmd_set_counters(dev, cmd); + ni_ao_cmd_set_update(dev, cmd); + ni_ao_cmd_set_channels(dev, s); + ni_ao_cmd_set_stop_conditions(dev, cmd); + ni_ao_cmd_set_fifo_mode(dev); + ni_ao_cmd_set_interrupts(dev, s); + + /* + * arm(ing) and star(ting) happen in ni_ao_inttrig, which _must_ be + * called for ao commands since 1) TRIG_NOW is not supported and 2) DMA + * must be setup and initially written to before arm/start happen. + */ return 0; } +/* end ni_ao_cmd */ + static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { -- cgit From 6aab7fee7a24395db1b556a5e5cf30aa2627c2be Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:28 -0700 Subject: staging: comedi: ni_mio_common: adds finite regeneration to AO output This patch implements for analog output the reinterpretation of stop_arg when stop_src == TRIG_NONE to allow the user to specify the length of the buffer that should be repeated. The intent is to allow a user to have a specific buffer repeated as-is indefinitely. The contents of the DMA buffer can be left static or changed by the user via mmap access to the DMA buffer. If the contents are changed by the user, additional munging is not performed by the driver and only a single call to comedi_mark_buffer_written should be done. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 61 +++++++++++++++++++------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 8f0fe3a26c73..1a22c79c2817 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1500,7 +1500,8 @@ static void handle_b_interrupt(struct comedi_device *dev, s->async->events |= COMEDI_CB_OVERFLOW; } - if (b_status & NISTC_AO_STATUS1_BC_TC) + if (s->async->cmd.stop_src != TRIG_NONE && + b_status & NISTC_AO_STATUS1_BC_TC) s->async->events |= COMEDI_CB_EOA; #ifndef PCIDMA @@ -2073,6 +2074,37 @@ static unsigned ni_timer_to_ns(const struct comedi_device *dev, int timer) return devpriv->clock_ns * (timer + 1); } +static void ni_cmd_set_mite_transfer(struct mite_dma_descriptor_ring *ring, + struct comedi_subdevice *sdev, + const struct comedi_cmd *cmd, + unsigned int max_count) { +#ifdef PCIDMA + unsigned int nbytes = max_count; + + if (cmd->stop_arg > 0 && cmd->stop_arg < max_count) + nbytes = cmd->stop_arg; + nbytes *= comedi_bytes_per_scan(sdev); + + if (nbytes > sdev->async->prealloc_bufsz) { + if (cmd->stop_arg > 0) + dev_err(sdev->device->class_dev, + "ni_cmd_set_mite_transfer: tried exact data transfer limits greater than buffer size\n"); + + /* + * we can only transfer up to the size of the buffer. In this + * case, the user is expected to continue to write into the + * comedi buffer (already implemented as a ring buffer). + */ + nbytes = sdev->async->prealloc_bufsz; + } + + mite_init_ring_descriptors(ring, sdev, nbytes); +#else + dev_err(sdev->device->class_dev, + "ni_cmd_set_mite_transfer: exact data transfer limits not implemented yet without DMA\n"); +#endif +} + static unsigned ni_min_ai_scan_period_ns(struct comedi_device *dev, unsigned num_channels) { @@ -3062,12 +3094,16 @@ static void ni_ao_cmd_set_counters(struct comedi_device *dev, devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); + /* + * if a user specifies '0', this automatically assumes the entire 24bit + * address space is available for the (multiple iterations of single + * buffer) MISB. Otherwise, stop_arg specifies the MISB length that + * will be used, regardless of whether we are in continuous mode or not. + * In continuous mode, the output will just iterate indefinitely over + * the MISB. + */ { - /* - * Current behavior is to configure the maximum update count - * possible when continuous output mode is requested. - */ - unsigned int stop_arg = cmd->stop_src == TRIG_COUNT ? + unsigned int stop_arg = cmd->stop_arg > 0 ? (cmd->stop_arg & 0xffffff) : 0xffffff; if (devpriv->is_m_series) { @@ -3311,6 +3347,7 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ni_ao_cmd_set_channels(dev, s); ni_ao_cmd_set_stop_conditions(dev, cmd); ni_ao_cmd_set_fifo_mode(dev); + ni_cmd_set_mite_transfer(devpriv->ao_mite_ring, s, cmd, 0x00ffffff); ni_ao_cmd_set_interrupts(dev, s); /* @@ -3381,11 +3418,7 @@ static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - - if (cmd->stop_src == TRIG_COUNT) - err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff); - else /* TRIG_NONE */ - err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); + err |= comedi_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff); if (err) return 3; @@ -5240,7 +5273,6 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) unsigned long flags; #ifdef PCIDMA struct ni_private *devpriv = dev->private; - struct mite_struct *mite = devpriv->mite; #endif if (!dev->attached) @@ -5252,8 +5284,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG); b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); #ifdef PCIDMA - if (mite) { - struct ni_private *devpriv = dev->private; + if (devpriv->mite) { unsigned long flags_too; spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too); @@ -5269,7 +5300,7 @@ static irqreturn_t ni_E_interrupt(int irq, void *d) ao_mite_status = mite_get_status(devpriv->ao_mite_chan); if (ao_mite_status & CHSR_LINKC) writel(CHOR_CLRLC, - mite->mite_io_addr + + devpriv->mite->mite_io_addr + MITE_CHOR(devpriv-> ao_mite_chan->channel)); } -- cgit From f164cbf98fa8692ecbe1f870c50522985d34d1c2 Mon Sep 17 00:00:00 2001 From: "Spencer E. Olson" Date: Wed, 27 Jan 2016 14:28:29 -0700 Subject: staging: comedi: ni_mio_common: add finite regeneration to dio output This patch continues the implementation of reinterpreting stop_arg when stop_src == TRIG_NONE for national instruments cdio output on e/m-series devices. This is part of a series of patches that allow a user to have a specific buffer repeated as-is indefinitely. The contents of the DMA buffer can be left static or changed by the user via mmap access to the DMA buffer. If the contents are changed by the user, additional munging is not performed by the driver and only a single call to comedi_mark_buffer_written should be done. The original behavior is preserved when stop_arg == 0, as would be the prior use case. As opposed to analog output, this patch is relatively simple. First, the digital output capabilities are much more limited/simple as compared to the analog output device on NI e/m-series hardware, and second, this patch relies on changes made with the earlier patch to accomplish limiting the DMA buffer transfer. Signed-off-by: Spencer E. Olson Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 1a22c79c2817..929389b52572 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3630,7 +3630,9 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); - err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); + err |= comedi_check_trigger_arg_max(&cmd->stop_arg, + s->async->prealloc_bufsz / + comedi_bytes_per_scan(s)); if (err) return 3; @@ -3707,6 +3709,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev, static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { + struct ni_private *devpriv = dev->private; const struct comedi_cmd *cmd = &s->async->cmd; unsigned cdo_mode_bits; int retval; @@ -3731,6 +3734,10 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) if (retval < 0) return retval; + ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd, + s->async->prealloc_bufsz / + comedi_bytes_per_scan(s)); + s->async->inttrig = ni_cdo_inttrig; return 0; -- cgit From b9491eab37e224b82d12c723e55c5b3b49396773 Mon Sep 17 00:00:00 2001 From: "Pablo G. Gallardo" Date: Thu, 4 Feb 2016 21:43:13 -0200 Subject: STAGING: COMEDI: Remove unnecessary typecast of c90 int constant This patch removes unnecessary typecast of c90 int constant. Signed-off-by: Pablo G. Gallardo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 83bd309d011b..f0d1b15f3c5a 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -516,7 +516,7 @@ struct comedi_bufinfo { #define UNIT_mA 1 #define UNIT_none 2 -#define COMEDI_MIN_SPEED ((unsigned int)0xffffffff) +#define COMEDI_MIN_SPEED 0xffffffffu /**********************************************************/ /* everything after this line is ALPHA */ -- cgit From 0e05c0273587677160c30effff2ac12b090791a0 Mon Sep 17 00:00:00 2001 From: "Pablo G. Gallardo" Date: Thu, 4 Feb 2016 21:43:14 -0200 Subject: STAGING: COMEDI: Wrap line over 80 characters This patch wraps lines over 80 characters. Signed-off-by: Pablo G. Gallardo Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_pcmcia.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/comedi/comedi_pcmcia.h b/drivers/staging/comedi/comedi_pcmcia.h index 5d3db2b9b4a1..5a572c200a8b 100644 --- a/drivers/staging/comedi/comedi_pcmcia.h +++ b/drivers/staging/comedi/comedi_pcmcia.h @@ -39,7 +39,8 @@ void comedi_pcmcia_driver_unregister(struct comedi_driver *, struct pcmcia_driver *); /** - * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver + * module_comedi_pcmcia_driver() - Helper macro for registering a comedi + * PCMCIA driver * @__comedi_driver: comedi_driver struct * @__pcmcia_driver: pcmcia_driver struct * -- cgit From e223da96bf16bee7f6c4c3aed1ade44a48aff0d3 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Mon, 16 Nov 2015 19:58:49 -0500 Subject: staging: drop kbuild workaround dummy module from top dir This is essentially a revert of 86f69fe9c069dd8608d238581eea259caa1dfc99 ("Staging: workaround build system bug"), but to call it a revert would imply it was wrong -- rather it seems more like it is just no longer required anymore. It doesn't list the full details of the failing use case, but the most obvious would appear to be a "make allnoconfig" that subsequently had set just CONFIG_STAGING=y in the .config file, to give: paul@builder:~/git/linux-head$ grep STAGING ../staging-allno/.config CONFIG_STAGING=y # CONFIG_STAGING_MEDIA is not set # CONFIG_STAGING_BOARD is not set paul@builder:~/git/linux-head$ After building this .config (on ARM, just to be different), we see that built-in.o is created, and the final vmlinux links OK: paul@builder:~/git/linux-head$ ls -l ../staging-allno/drivers/staging/built-in.o -rw-rw-r-- 1 paul paul 257 Nov 16 18:06 ../staging-allno/drivers/staging/built-in.o paul@builder:~/git/linux-head$ file ../staging-allno/drivers/staging/built-in.o ../staging-allno/drivers/staging/built-in.o: ELF 32-bit LSB relocatable, ARM, version 1, not stripped paul@builder:~/git/linux-head$ nm ../staging-allno/drivers/staging/built-in.o nm: ../staging-allno/drivers/staging/built-in.o: no symbols paul@builder:~/git/linux-head$ ls -l ../staging-allno/vmlinux -rwxrwxr-x 1 paul paul 1236326 Nov 16 18:07 ../staging-allno/vmlinux paul@builder:~/git/linux-head$ I also tested an "allmodconfig" and did not see any problems there either. Switching back to x86-64 and testing several things there didn't show any issues either. So it appears we do not need to carry the workaround in tree any longer. Cc: linux-kbuild@vger.kernel.org Signed-off-by: Paul Gortmaker Acked-by: Michal Marek Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Makefile | 3 --- drivers/staging/staging.c | 19 ------------------- 2 files changed, 22 deletions(-) delete mode 100644 drivers/staging/staging.c diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index dbab17e9d45c..b3920c224013 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -1,8 +1,5 @@ # Makefile for staging directory -# fix for build system bug... -obj-$(CONFIG_STAGING) += staging.o - obj-y += media/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ diff --git a/drivers/staging/staging.c b/drivers/staging/staging.c deleted file mode 100644 index 233e589c0932..000000000000 --- a/drivers/staging/staging.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include -#include - -static int __init staging_init(void) -{ - return 0; -} - -static void __exit staging_exit(void) -{ -} - -module_init(staging_init); -module_exit(staging_exit); - -MODULE_AUTHOR("Greg Kroah-Hartman"); -MODULE_DESCRIPTION("Staging Core"); -MODULE_LICENSE("GPL"); -- cgit From 14d88ec50ea668cc20efb622a13c664f056aee97 Mon Sep 17 00:00:00 2001 From: Dean Luick Date: Mon, 21 Dec 2015 20:31:53 -0500 Subject: staging/rdma/hfi1: set Gen3 half-swing for integrated devices Correctly set half-swing for integrated devices. A0 needs all fields set for CcePcieCtrl. B0 and later only need a few fields set. Reviewed-by: Stuart Summers Signed-off-by: Dean Luick Signed-off-by: Ira Weiny Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/chip_registers.h | 11 ++++ drivers/staging/rdma/hfi1/pcie.c | 82 ++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rdma/hfi1/chip_registers.h b/drivers/staging/rdma/hfi1/chip_registers.h index 701e9e1012a6..014d7a609ea0 100644 --- a/drivers/staging/rdma/hfi1/chip_registers.h +++ b/drivers/staging/rdma/hfi1/chip_registers.h @@ -551,6 +551,17 @@ #define CCE_MSIX_TABLE_UPPER (CCE + 0x000000100008) #define CCE_MSIX_TABLE_UPPER_RESETCSR 0x0000000100000000ull #define CCE_MSIX_VEC_CLR_WITHOUT_INT (CCE + 0x000000110400) +#define CCE_PCIE_CTRL (CCE + 0x0000000000C0) +#define CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_MASK 0x3ull +#define CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_SHIFT 0 +#define CCE_PCIE_CTRL_PCIE_LANE_DELAY_MASK 0xFull +#define CCE_PCIE_CTRL_PCIE_LANE_DELAY_SHIFT 2 +#define CCE_PCIE_CTRL_XMT_MARGIN_OVERWRITE_ENABLE_SHIFT 8 +#define CCE_PCIE_CTRL_XMT_MARGIN_SHIFT 9 +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_MASK 0x1ull +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_SHIFT 12 +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_MASK 0x7ull +#define CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_SHIFT 13 #define CCE_REVISION (CCE + 0x000000000000) #define CCE_REVISION2 (CCE + 0x000000000008) #define CCE_REVISION2_HFI_ID_MASK 0x1ull diff --git a/drivers/staging/rdma/hfi1/pcie.c b/drivers/staging/rdma/hfi1/pcie.c index 8317b07d722a..9917faff823c 100644 --- a/drivers/staging/rdma/hfi1/pcie.c +++ b/drivers/staging/rdma/hfi1/pcie.c @@ -866,6 +866,83 @@ static void arm_gasket_logic(struct hfi1_devdata *dd) read_csr(dd, ASIC_PCIE_SD_HOST_CMD); } +/* + * CCE_PCIE_CTRL long name helpers + * We redefine these shorter macros to use in the code while leaving + * chip_registers.h to be autogenerated from the hardware spec. + */ +#define LANE_BUNDLE_MASK CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_MASK +#define LANE_BUNDLE_SHIFT CCE_PCIE_CTRL_PCIE_LANE_BUNDLE_SHIFT +#define LANE_DELAY_MASK CCE_PCIE_CTRL_PCIE_LANE_DELAY_MASK +#define LANE_DELAY_SHIFT CCE_PCIE_CTRL_PCIE_LANE_DELAY_SHIFT +#define MARGIN_OVERWRITE_ENABLE_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_OVERWRITE_ENABLE_SHIFT +#define MARGIN_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_SHIFT +#define MARGIN_G1_G2_OVERWRITE_MASK CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_MASK +#define MARGIN_G1_G2_OVERWRITE_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_OVERWRITE_ENABLE_SHIFT +#define MARGIN_GEN1_GEN2_MASK CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_MASK +#define MARGIN_GEN1_GEN2_SHIFT CCE_PCIE_CTRL_XMT_MARGIN_GEN1_GEN2_SHIFT + + /* + * Write xmt_margin for full-swing (WFR-B) or half-swing (WFR-C). + */ +static void write_xmt_margin(struct hfi1_devdata *dd, const char *fname) +{ + u64 pcie_ctrl; + u64 xmt_margin; + u64 xmt_margin_oe; + u64 lane_delay; + u64 lane_bundle; + + pcie_ctrl = read_csr(dd, CCE_PCIE_CTRL); + + /* + * For Discrete, use full-swing. + * - PCIe TX defaults to full-swing. + * Leave this register as default. + * For Integrated, use half-swing + * - Copy xmt_margin and xmt_margin_oe + * from Gen1/Gen2 to Gen3. + */ + if (dd->pcidev->device == PCI_DEVICE_ID_INTEL1) { /* integrated */ + /* extract initial fields */ + xmt_margin = (pcie_ctrl >> MARGIN_GEN1_GEN2_SHIFT) + & MARGIN_GEN1_GEN2_MASK; + xmt_margin_oe = (pcie_ctrl >> MARGIN_G1_G2_OVERWRITE_SHIFT) + & MARGIN_G1_G2_OVERWRITE_MASK; + lane_delay = (pcie_ctrl >> LANE_DELAY_SHIFT) & LANE_DELAY_MASK; + lane_bundle = (pcie_ctrl >> LANE_BUNDLE_SHIFT) + & LANE_BUNDLE_MASK; + + /* + * For A0, EFUSE values are not set. Override with the + * correct values. + */ + if (is_ax(dd)) { + /* + * xmt_margin and OverwiteEnabel should be the + * same for Gen1/Gen2 and Gen3 + */ + xmt_margin = 0x5; + xmt_margin_oe = 0x1; + lane_delay = 0xF; /* Delay 240ns. */ + lane_bundle = 0x0; /* Set to 1 lane. */ + } + + /* overwrite existing values */ + pcie_ctrl = (xmt_margin << MARGIN_GEN1_GEN2_SHIFT) + | (xmt_margin_oe << MARGIN_G1_G2_OVERWRITE_SHIFT) + | (xmt_margin << MARGIN_SHIFT) + | (xmt_margin_oe << MARGIN_OVERWRITE_ENABLE_SHIFT) + | (lane_delay << LANE_DELAY_SHIFT) + | (lane_bundle << LANE_BUNDLE_SHIFT); + + write_csr(dd, CCE_PCIE_CTRL, pcie_ctrl); + } + + dd_dev_dbg(dd, "%s: program XMT margin, CcePcieCtrl 0x%llx\n", + fname, pcie_ctrl); +} + /* * Do all the steps needed to transition the PCIe link to Gen3 speed. */ @@ -1064,11 +1141,8 @@ retry: /* * step 5d: program XMT margin - * Right now, leave the default alone. To change, do a - * read-modify-write of: - * CcePcieCtrl.XmtMargin - * CcePcieCtrl.XmitMarginOverwriteEnable */ + write_xmt_margin(dd, __func__); /* step 5e: disable active state power management (ASPM) */ dd_dev_info(dd, "%s: clearing ASPM\n", __func__); -- cgit From 568dcc883abcbb5ef7daf8ddcfea1b533324b4a6 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Mon, 21 Dec 2015 20:31:52 -0500 Subject: staging/rdma/hfi1: add dd_dev_dbg To be used in future patches add dd_dev_dbg. dd_* functions properly decode the hfi1_devdata structure used throughout the driver Signed-off-by: Ira Weiny Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/hfi.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/staging/rdma/hfi1/hfi.h b/drivers/staging/rdma/hfi1/hfi.h index 2611bb2e764d..f14ed1e4001b 100644 --- a/drivers/staging/rdma/hfi1/hfi.h +++ b/drivers/staging/rdma/hfi1/hfi.h @@ -1794,6 +1794,10 @@ static inline u64 hfi1_pkt_base_sdma_integrity(struct hfi1_devdata *dd) dev_info(&(dd)->pcidev->dev, "%s: " fmt, \ get_unit_name((dd)->unit), ##__VA_ARGS__) +#define dd_dev_dbg(dd, fmt, ...) \ + dev_dbg(&(dd)->pcidev->dev, "%s: " fmt, \ + get_unit_name((dd)->unit), ##__VA_ARGS__) + #define hfi1_dev_porterr(dd, port, fmt, ...) \ dev_err(&(dd)->pcidev->dev, "%s: IB%u:%u " fmt, \ get_unit_name((dd)->unit), (dd)->unit, (port), \ -- cgit From 480fd015ec5c9109c55e39057f3df60278851432 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 23 Dec 2015 21:42:57 +0100 Subject: staging: rdma: hfi1: diag: constify hfi1_filter_array structure The hfi1_filter_array structure is never modified, so declare it as const. Done with the help of Coccinelle. Signed-off-by: Julia Lawall Acked-by: Mike Marciniszyn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/diag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rdma/hfi1/diag.c b/drivers/staging/rdma/hfi1/diag.c index 0c8831705664..e41159fe6889 100644 --- a/drivers/staging/rdma/hfi1/diag.c +++ b/drivers/staging/rdma/hfi1/diag.c @@ -257,7 +257,7 @@ static int hfi1_filter_ib_service_level(void *ibhdr, void *packet_data, static int hfi1_filter_ib_pkey(void *ibhdr, void *packet_data, void *value); static int hfi1_filter_direction(void *ibhdr, void *packet_data, void *value); -static struct hfi1_filter_array hfi1_filters[] = { +static const struct hfi1_filter_array hfi1_filters[] = { { hfi1_filter_lid }, { hfi1_filter_dlid }, { hfi1_filter_mad_mgmt_class }, -- cgit From 80e4898e82e39618397d66ef5cc49529555c17ce Mon Sep 17 00:00:00 2001 From: Edward Mascarenhas Date: Mon, 21 Dec 2015 21:57:44 -0500 Subject: staging/rdma/hfi1: Clean up comments Clean up comments by deleting numbering and terms internal to Intel. The information on the actual bugs is not deleted. Reviewed-by: Mike Marciniszyn Signed-off-by: Edward Mascarenhas Signed-off-by: Jubin John Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/chip.c | 1 - drivers/staging/rdma/hfi1/driver.c | 2 +- drivers/staging/rdma/hfi1/hfi.h | 4 ++-- drivers/staging/rdma/hfi1/pcie.c | 2 +- drivers/staging/rdma/hfi1/ud.c | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rdma/hfi1/chip.c b/drivers/staging/rdma/hfi1/chip.c index bbe5ad85cec0..02ba78ff5ca0 100644 --- a/drivers/staging/rdma/hfi1/chip.c +++ b/drivers/staging/rdma/hfi1/chip.c @@ -13537,7 +13537,6 @@ int hfi1_set_ctxt_jkey(struct hfi1_devdata *dd, unsigned ctxt, u16 jkey) write_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_JOB_KEY, reg); /* * Enable send-side J_KEY integrity check, unless this is A0 h/w - * (due to A0 erratum). */ if (!is_ax(dd)) { reg = read_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_ENABLE); diff --git a/drivers/staging/rdma/hfi1/driver.c b/drivers/staging/rdma/hfi1/driver.c index 8485de1fce08..321852060213 100644 --- a/drivers/staging/rdma/hfi1/driver.c +++ b/drivers/staging/rdma/hfi1/driver.c @@ -368,7 +368,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd, if (opcode == IB_OPCODE_CNP) { /* * Only in pre-B0 h/w is the CNP_OPCODE handled - * via this code path (errata 291394). + * via this code path. */ struct hfi1_qp *qp = NULL; u32 lqpn, rqpn; diff --git a/drivers/staging/rdma/hfi1/hfi.h b/drivers/staging/rdma/hfi1/hfi.h index f14ed1e4001b..d4826a9ab8d3 100644 --- a/drivers/staging/rdma/hfi1/hfi.h +++ b/drivers/staging/rdma/hfi1/hfi.h @@ -1730,7 +1730,7 @@ static inline u64 hfi1_pkt_default_send_ctxt_mask(struct hfi1_devdata *dd, base_sc_integrity |= HFI1_PKT_KERNEL_SC_INTEGRITY; if (is_ax(dd)) - /* turn off send-side job key checks - A0 erratum */ + /* turn off send-side job key checks - A0 */ return base_sc_integrity & ~SEND_CTXT_CHECK_ENABLE_CHECK_JOB_KEY_SMASK; return base_sc_integrity; @@ -1757,7 +1757,7 @@ static inline u64 hfi1_pkt_base_sdma_integrity(struct hfi1_devdata *dd) | SEND_DMA_CHECK_ENABLE_CHECK_ENABLE_SMASK; if (is_ax(dd)) - /* turn off send-side job key checks - A0 erratum */ + /* turn off send-side job key checks - A0 */ return base_sdma_integrity & ~SEND_DMA_CHECK_ENABLE_CHECK_JOB_KEY_SMASK; return base_sdma_integrity; diff --git a/drivers/staging/rdma/hfi1/pcie.c b/drivers/staging/rdma/hfi1/pcie.c index 9917faff823c..b2f553d86042 100644 --- a/drivers/staging/rdma/hfi1/pcie.c +++ b/drivers/staging/rdma/hfi1/pcie.c @@ -1063,7 +1063,7 @@ retry: * PcieCfgRegPl100 - Gen3 Control * * turn off PcieCfgRegPl100.Gen3ZRxDcNonCompl - * turn on PcieCfgRegPl100.EqEieosCnt (erratum) + * turn on PcieCfgRegPl100.EqEieosCnt * Everything else zero. */ reg32 = PCIE_CFG_REG_PL100_EQ_EIEOS_CNT_SMASK; diff --git a/drivers/staging/rdma/hfi1/ud.c b/drivers/staging/rdma/hfi1/ud.c index bd1b402c1e14..25e6053c38db 100644 --- a/drivers/staging/rdma/hfi1/ud.c +++ b/drivers/staging/rdma/hfi1/ud.c @@ -671,7 +671,7 @@ void hfi1_ud_rcv(struct hfi1_packet *packet) if (unlikely(bth1 & HFI1_BECN_SMASK)) { /* * In pre-B0 h/w the CNP_OPCODE is handled via an - * error path (errata 291394). + * error path. */ struct hfi1_pportdata *ppd = ppd_from_ibp(ibp); u32 lqpn = be32_to_cpu(ohdr->bth[1]) & HFI1_QPN_MASK; -- cgit From d9d3e025c0f68a1ec99ee13209d31d2a766ac56f Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Mon, 21 Dec 2015 21:57:45 -0500 Subject: staging/rdma/hfi1: Fix Xmit Wait calculation Total XMIT wait needs to sum the xmit wait values of all the VLs not just those requested in the query. Also, make the algorithm used for both PortStatus and PortDataCounters the same. Reviewed-by: Arthur Kepner Reviewed-by: Breyer, Scott J Signed-off-by: Ira Weiny Signed-off-by: Jubin John Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/mad.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/staging/rdma/hfi1/mad.c b/drivers/staging/rdma/hfi1/mad.c index 4f5dbd14b5de..bee1c0e5c2e3 100644 --- a/drivers/staging/rdma/hfi1/mad.c +++ b/drivers/staging/rdma/hfi1/mad.c @@ -2279,17 +2279,23 @@ static void a0_portstatus(struct hfi1_pportdata *ppd, { if (!is_bx(ppd->dd)) { unsigned long vl; - u64 max_vl_xmit_wait = 0, tmp; + u64 sum_vl_xmit_wait = 0; u32 vl_all_mask = VL_MASK_ALL; for_each_set_bit(vl, (unsigned long *)&(vl_all_mask), 8 * sizeof(vl_all_mask)) { - tmp = read_port_cntr(ppd, C_TX_WAIT_VL, - idx_from_vl(vl)); - if (tmp > max_vl_xmit_wait) - max_vl_xmit_wait = tmp; + u64 tmp = sum_vl_xmit_wait + + read_port_cntr(ppd, C_TX_WAIT_VL, + idx_from_vl(vl)); + if (tmp < sum_vl_xmit_wait) { + /* we wrapped */ + sum_vl_xmit_wait = (u64)~0; + break; + } + sum_vl_xmit_wait = tmp; } - rsp->port_xmit_wait = cpu_to_be64(max_vl_xmit_wait); + if (be64_to_cpu(rsp->port_xmit_wait) > sum_vl_xmit_wait) + rsp->port_xmit_wait = cpu_to_be64(sum_vl_xmit_wait); } } @@ -2491,18 +2497,19 @@ static u64 get_error_counter_summary(struct ib_device *ibdev, u8 port, return error_counter_summary; } -static void a0_datacounters(struct hfi1_devdata *dd, struct _port_dctrs *rsp, +static void a0_datacounters(struct hfi1_pportdata *ppd, struct _port_dctrs *rsp, u32 vl_select_mask) { - if (!is_bx(dd)) { + if (!is_bx(ppd->dd)) { unsigned long vl; - int vfi = 0; u64 sum_vl_xmit_wait = 0; + u32 vl_all_mask = VL_MASK_ALL; - for_each_set_bit(vl, (unsigned long *)&(vl_select_mask), - 8 * sizeof(vl_select_mask)) { + for_each_set_bit(vl, (unsigned long *)&(vl_all_mask), + 8 * sizeof(vl_all_mask)) { u64 tmp = sum_vl_xmit_wait + - be64_to_cpu(rsp->vls[vfi++].port_vl_xmit_wait); + read_port_cntr(ppd, C_TX_WAIT_VL, + idx_from_vl(vl)); if (tmp < sum_vl_xmit_wait) { /* we wrapped */ sum_vl_xmit_wait = (u64) ~0; @@ -2665,7 +2672,7 @@ static int pma_get_opa_datacounters(struct opa_pma_mad *pmp, vfi++; } - a0_datacounters(dd, rsp, vl_select_mask); + a0_datacounters(ppd, rsp, vl_select_mask); if (resp_len) *resp_len += response_data_size; -- cgit From 0fbc7c505680ca6efe2486afb34866602781c980 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:49 +0200 Subject: staging: sm750fb: disable PCI device if lynxfb_pci_probe fails In case of error during lynxfb_pci_probe, the function returned without calling pci_disable_device. Fix it by adding pci_disable_device on the error cleanup path. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c78421b5b0e7..c80b11c387ad 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1132,6 +1132,7 @@ err_info0_alloc: err_map: kfree(sm750_dev); err_share: + pci_disable_device(pdev); err_enable: return -ENODEV; } -- cgit From baf24530a48c991144aaf82007d4f5e21eb47aa8 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:50 +0200 Subject: staging: sm750fb: lynxfb_pci_probe: return actual errors The lynxfb_pci_probe always returned -ENODEV in case of error. Modify it so that actual error code will be propogated to the caller. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c80b11c387ad..7eb386881964 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1006,18 +1006,17 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, struct fb_info *info[] = {NULL, NULL}; struct sm750_dev *sm750_dev = NULL; int fbidx; + int err; /* enable device */ - if (pci_enable_device(pdev)) { - pr_err("can not enable device.\n"); - goto err_enable; - } + err = pci_enable_device(pdev); + if (err) + return err; + err = -ENOMEM; sm750_dev = kzalloc(sizeof(*sm750_dev), GFP_KERNEL); - if (!sm750_dev) { - pr_err("Could not allocate memory for share.\n"); - goto err_share; - } + if (!sm750_dev) + goto disable_pci; sm750_dev->fbinfo[0] = sm750_dev->fbinfo[1] = NULL; sm750_dev->devid = pdev->device; @@ -1051,10 +1050,9 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750fb_setup(sm750_dev, g_settings); /* call chip specific mmap routine */ - if (hw_sm750_map(sm750_dev, pdev)) { - pr_err("Memory map failed\n"); - goto err_map; - } + err = hw_sm750_map(sm750_dev, pdev); + if (err) + goto free_sm750_dev; if (!sm750_dev->mtrr_off) sm750_dev->mtrr.vram = arch_phys_wc_add(sm750_dev->vidmem_start, @@ -1073,6 +1071,7 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, /* allocate frame buffer info structor according to g_dualview */ fbidx = 0; ALLOC_FB: + err = -ENOMEM; info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev); if (!info[fbidx]) { pr_err("Could not allocate framebuffer #%d.\n", fbidx); @@ -1082,7 +1081,6 @@ ALLOC_FB: goto err_info1_alloc; } else { struct lynxfb_par *par; - int errno; pr_info("framebuffer #%d alloc okay\n", fbidx); sm750_dev->fbinfo[fbidx] = info[fbidx]; @@ -1100,11 +1098,11 @@ ALLOC_FB: /* register frame buffer */ pr_info("Ready to register framebuffer #%d.\n", fbidx); - errno = register_framebuffer(info[fbidx]); - if (errno < 0) { + err = register_framebuffer(info[fbidx]); + if (err < 0) { pr_err("Failed to register fb_info #%d. err %d\n", fbidx, - errno); + err); if (fbidx == 0) goto err_register0; else @@ -1129,12 +1127,11 @@ err_register0: err_info0_set: framebuffer_release(info[0]); err_info0_alloc: -err_map: +free_sm750_dev: kfree(sm750_dev); -err_share: +disable_pci: pci_disable_device(pdev); -err_enable: - return -ENODEV; + return err; } static void lynxfb_pci_remove(struct pci_dev *pdev) -- cgit From 473baa2df6833c53c74f13eb812de5c57287ffd4 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:51 +0200 Subject: staging: sm750fb: lynxfb_pci_remove: remove unused variable The par variable in lynxfb_pci_remove is only assigned a value and never used afterwards. Remove it. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 7eb386881964..6ed4478ed65a 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1138,7 +1138,6 @@ static void lynxfb_pci_remove(struct pci_dev *pdev) { struct fb_info *info; struct sm750_dev *sm750_dev; - struct lynxfb_par *par; int cnt; cnt = 2; @@ -1148,7 +1147,6 @@ static void lynxfb_pci_remove(struct pci_dev *pdev) info = sm750_dev->fbinfo[cnt]; if (!info) continue; - par = info->par; unregister_framebuffer(info); /* release frame buffer */ -- cgit From a3f92cc94c6126d243d1cfc4f198e101f89bd46b Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:52 +0200 Subject: staging: sm750fb: replace dual member of sm750_dev with fb_count Will be used in futher refactoring of driver _probe and _remove methods. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 24 +++++++++++++----------- drivers/staging/sm750fb/sm750.h | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 6ed4478ed65a..1b3ab04d8f06 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -189,7 +189,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info, * If not use spin_lock,system will die if user load driver * and immediately unload driver frequently (dual) */ - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_lock(&sm750_dev->slock); sm750_dev->accel.de_fillrect(&sm750_dev->accel, @@ -197,7 +197,7 @@ static void lynxfb_ops_fillrect(struct fb_info *info, region->dx, region->dy, region->width, region->height, color, rop); - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_unlock(&sm750_dev->slock); } @@ -223,7 +223,7 @@ static void lynxfb_ops_copyarea(struct fb_info *info, * If not use spin_lock, system will die if user load driver * and immediately unload driver frequently (dual) */ - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_lock(&sm750_dev->slock); sm750_dev->accel.de_copyarea(&sm750_dev->accel, @@ -231,7 +231,7 @@ static void lynxfb_ops_copyarea(struct fb_info *info, base, pitch, Bpp, region->dx, region->dy, region->width, region->height, HW_ROP2_COPY); - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_unlock(&sm750_dev->slock); } @@ -272,7 +272,7 @@ static void lynxfb_ops_imageblit(struct fb_info *info, * If not use spin_lock, system will die if user load driver * and immediately unload driver frequently (dual) */ - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_lock(&sm750_dev->slock); sm750_dev->accel.de_imageblit(&sm750_dev->accel, @@ -281,7 +281,7 @@ static void lynxfb_ops_imageblit(struct fb_info *info, image->dx, image->dy, image->width, image->height, fgcol, bgcol, HW_ROP2_COPY); - if (sm750_dev->dual) + if (sm750_dev->fb_count > 1) spin_unlock(&sm750_dev->slock); } @@ -650,8 +650,10 @@ static int sm750fb_set_drv(struct lynxfb_par *par) output = &par->output; crtc = &par->crtc; - crtc->vidmem_size = (sm750_dev->dual) ? sm750_dev->vidmem_size >> 1 : - sm750_dev->vidmem_size; + crtc->vidmem_size = sm750_dev->vidmem_size; + if (sm750_dev->fb_count > 1) + crtc->vidmem_size >>= 1; + /* setup crtc and output member */ sm750_dev->hwCursor = g_hwcursor; @@ -981,7 +983,7 @@ static void sm750fb_setup(struct sm750_dev *sm750_dev, char *src) NO_PARAM: if (sm750_dev->revid != SM750LE_REVISION_ID) { - if (sm750_dev->dual) { + if (sm750_dev->fb_count > 1) { if (swap) sm750_dev->dataflow = sm750_dual_swap; else @@ -1027,7 +1029,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->mtrr_off = g_nomtrr; sm750_dev->mtrr.vram = 0; sm750_dev->accel_off = g_noaccel; - sm750_dev->dual = g_dualview; spin_lock_init(&sm750_dev->slock); if (!sm750_dev->accel_off) { @@ -1113,7 +1114,8 @@ ALLOC_FB: /* no dual view by far */ fbidx++; - if (sm750_dev->dual && fbidx < 2) + sm750_dev->fb_count++; + if (g_dualview && fbidx < 2) goto ALLOC_FB; return 0; diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index b0a93cdc7292..fddffac6930f 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -79,7 +79,7 @@ struct sm750_dev { struct fb_info *fbinfo[2]; struct lynx_accel accel; int accel_off; - int dual; + int fb_count; int mtrr_off; struct{ int vram; -- cgit From 9324f9193bc3ba7a07e70ac6e01b3257fb17f390 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:53 +0200 Subject: staging: sm750fb: introduce sm750fb_frambuffer_release Use a function to unregister framebuffer info and release its resources. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 1b3ab04d8f06..88a640507d7f 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1002,6 +1002,18 @@ NO_PARAM: } } +static void sm750fb_frambuffer_release(struct sm750_dev *sm750_dev) +{ + struct fb_info *fb_info; + + while (sm750_dev->fb_count) { + fb_info = sm750_dev->fbinfo[sm750_dev->fb_count - 1]; + unregister_framebuffer(fb_info); + framebuffer_release(fb_info); + sm750_dev->fb_count--; + } +} + static int lynxfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1138,22 +1150,11 @@ disable_pci: static void lynxfb_pci_remove(struct pci_dev *pdev) { - struct fb_info *info; struct sm750_dev *sm750_dev; - int cnt; - cnt = 2; sm750_dev = pci_get_drvdata(pdev); - while (cnt-- > 0) { - info = sm750_dev->fbinfo[cnt]; - if (!info) - continue; - - unregister_framebuffer(info); - /* release frame buffer */ - framebuffer_release(info); - } + sm750fb_frambuffer_release(sm750_dev); arch_phys_wc_del(sm750_dev->mtrr.vram); iounmap(sm750_dev->pvReg); -- cgit From a50bc32d325831f2365333298c2808adac18a219 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:54 +0200 Subject: staging: sm750fb: introduce sm750fb_frambuffer_alloc Split framebuffer allocation and registration into a dedicated function to simplify lynxfb_pci_probe Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 98 +++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 88a640507d7f..c33c7ffb8557 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1014,11 +1014,43 @@ static void sm750fb_frambuffer_release(struct sm750_dev *sm750_dev) } } +static int sm750fb_frambuffer_alloc(struct sm750_dev *sm750_dev, int fbidx) +{ + struct fb_info *fb_info; + struct lynxfb_par *par; + int err; + + fb_info = framebuffer_alloc(sizeof(struct lynxfb_par), + &sm750_dev->pdev->dev); + if (!fb_info) + return -ENOMEM; + + sm750_dev->fbinfo[fbidx] = fb_info; + par = fb_info->par; + par->dev = sm750_dev; + + err = lynxfb_set_fbinfo(fb_info, fbidx); + if (err) + goto release_fb; + + err = register_framebuffer(fb_info); + if (err < 0) + goto release_fb; + + sm750_dev->fb_count++; + + return 0; + +release_fb: + framebuffer_release(fb_info); + return err; +} + static int lynxfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct fb_info *info[] = {NULL, NULL}; struct sm750_dev *sm750_dev = NULL; + int max_fb; int fbidx; int err; @@ -1081,66 +1113,18 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, /* call chipInit routine */ hw_sm750_inithw(sm750_dev, pdev); - /* allocate frame buffer info structor according to g_dualview */ - fbidx = 0; -ALLOC_FB: - err = -ENOMEM; - info[fbidx] = framebuffer_alloc(sizeof(struct lynxfb_par), &pdev->dev); - if (!info[fbidx]) { - pr_err("Could not allocate framebuffer #%d.\n", fbidx); - if (fbidx == 0) - goto err_info0_alloc; - else - goto err_info1_alloc; - } else { - struct lynxfb_par *par; - - pr_info("framebuffer #%d alloc okay\n", fbidx); - sm750_dev->fbinfo[fbidx] = info[fbidx]; - par = info[fbidx]->par; - par->dev = sm750_dev; - - /* set fb_info structure */ - if (lynxfb_set_fbinfo(info[fbidx], fbidx)) { - pr_err("Failed to initial fb_info #%d.\n", fbidx); - if (fbidx == 0) - goto err_info0_set; - else - goto err_info1_set; - } - - /* register frame buffer */ - pr_info("Ready to register framebuffer #%d.\n", fbidx); - err = register_framebuffer(info[fbidx]); - if (err < 0) { - pr_err("Failed to register fb_info #%d. err %d\n", - fbidx, - err); - if (fbidx == 0) - goto err_register0; - else - goto err_register1; - } - pr_info("Accomplished register framebuffer #%d.\n", fbidx); + /* allocate frame buffer info structures according to g_dualview */ + max_fb = g_dualview ? 2 : 1; + for (fbidx = 0; fbidx < max_fb; fbidx++) { + err = sm750fb_frambuffer_alloc(sm750_dev, fbidx); + if (err) + goto release_fb; } - /* no dual view by far */ - fbidx++; - sm750_dev->fb_count++; - if (g_dualview && fbidx < 2) - goto ALLOC_FB; - return 0; -err_register1: -err_info1_set: - framebuffer_release(info[1]); -err_info1_alloc: - unregister_framebuffer(info[0]); -err_register0: -err_info0_set: - framebuffer_release(info[0]); -err_info0_alloc: +release_fb: + sm750fb_frambuffer_release(sm750_dev); free_sm750_dev: kfree(sm750_dev); disable_pci: -- cgit From 61da1a12d80f02c42a5f8d8865da94751e077735 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 19:59:55 +0200 Subject: staging: sm750fb: lynxfb_pci_probe: remove some pr_info Several pr_info statements in lynxfb_pci_probe seem like debug leftovers and may be removed. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index c33c7ffb8557..2ae2a522136f 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -1067,8 +1067,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->fbinfo[0] = sm750_dev->fbinfo[1] = NULL; sm750_dev->devid = pdev->device; sm750_dev->revid = pdev->revision; - - pr_info("share->revid = %02x\n", sm750_dev->revid); sm750_dev->pdev = pdev; sm750_dev->mtrr_off = g_nomtrr; sm750_dev->mtrr.vram = 0; @@ -1086,9 +1084,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, sm750_dev->accel.de_fillrect = hw_fillrect; sm750_dev->accel.de_copyarea = hw_copyarea; sm750_dev->accel.de_imageblit = hw_imageblit; - pr_info("enable 2d acceleration\n"); - } else { - pr_info("disable 2d acceleration\n"); } /* call chip specific setup routine */ @@ -1105,9 +1100,6 @@ static int lynxfb_pci_probe(struct pci_dev *pdev, memset_io(sm750_dev->pvMem, 0, sm750_dev->vidmem_size); - pr_info("sm%3x mmio address = %p\n", sm750_dev->devid, - sm750_dev->pvReg); - pci_set_drvdata(pdev, sm750_dev); /* call chipInit routine */ -- cgit From 9eced7438d864c33e6de781bb47f0f21a784c8c5 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:14 +0200 Subject: staging: sm750fb: hw_sm750(le)_deWait: rename dwVal to val Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_hw.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 41822c6c0380..f9908d942c63 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -495,11 +495,11 @@ int hw_sm750le_deWait(void) int i = 0x10000000; while (i--) { - unsigned int dwVal = PEEK32(DE_STATE2); + unsigned int val = PEEK32(DE_STATE2); - if ((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && - (FIELD_GET(dwVal, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) && - (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) { + if ((FIELD_GET(val, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && + (FIELD_GET(val, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) && + (FIELD_GET(val, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) { return 0; } } @@ -513,11 +513,11 @@ int hw_sm750_deWait(void) int i = 0x10000000; while (i--) { - unsigned int dwVal = PEEK32(SYSTEM_CTRL); + unsigned int val = PEEK32(SYSTEM_CTRL); - if ((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && - (FIELD_GET(dwVal, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) && - (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) { + if ((FIELD_GET(val, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && + (FIELD_GET(val, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) && + (FIELD_GET(val, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) { return 0; } } -- cgit From c808d6ce4a2a2d923fbf29e054ff08c0141703c0 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:15 +0200 Subject: staging: sm750fb: use BIT macro for DE_STATE1 single-bit field Replace complex definition of DE_STATE1 field and usage of FIELD_SET with BIT() macro and open-coded register value modifications Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 4 +--- drivers/staging/sm750fb/sm750_hw.c | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 16a01c25442c..7bbe53a12808 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -3,9 +3,7 @@ /* New register for SM750LE */ #define DE_STATE1 0x100054 -#define DE_STATE1_DE_ABORT 0:0 -#define DE_STATE1_DE_ABORT_OFF 0 -#define DE_STATE1_DE_ABORT_ON 1 +#define DE_STATE1_DE_ABORT BIT(0) #define DE_STATE2 0x100058 #define DE_STATE2_DE_FIFO 3:3 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index f9908d942c63..5754af5b9ddf 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -468,11 +468,11 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) if (getChipType() == SM750LE) { reg = PEEK32(DE_STATE1); - reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON); + reg |= DE_STATE1_DE_ABORT; POKE32(DE_STATE1, reg); reg = PEEK32(DE_STATE1); - reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF); + reg &= ~DE_STATE1_DE_ABORT; POKE32(DE_STATE1, reg); } else { -- cgit From ae6061dbfcb2f49cd717fb235b5d0633e99f2596 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:16 +0200 Subject: staging: sm750fb: use BIT macro for DE_STATE2 single-bit fields Replace complex definition of DE_STATE1 fields and usage of FIELD_GET with BIT() macro and open-coded register value modifications Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 12 +++--------- drivers/staging/sm750fb/sm750_hw.c | 8 ++++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 7bbe53a12808..db13bdf6a1dc 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -6,15 +6,9 @@ #define DE_STATE1_DE_ABORT BIT(0) #define DE_STATE2 0x100058 -#define DE_STATE2_DE_FIFO 3:3 -#define DE_STATE2_DE_FIFO_NOTEMPTY 0 -#define DE_STATE2_DE_FIFO_EMPTY 1 -#define DE_STATE2_DE_STATUS 2:2 -#define DE_STATE2_DE_STATUS_IDLE 0 -#define DE_STATE2_DE_STATUS_BUSY 1 -#define DE_STATE2_DE_MEM_FIFO 1:1 -#define DE_STATE2_DE_MEM_FIFO_NOTEMPTY 0 -#define DE_STATE2_DE_MEM_FIFO_EMPTY 1 +#define DE_STATE2_DE_FIFO_EMPTY BIT(3) +#define DE_STATE2_DE_STATUS_BUSY BIT(2) +#define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1) #define DE_STATE2_DE_RESERVED 0:0 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 5754af5b9ddf..425bec886078 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -493,15 +493,15 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) int hw_sm750le_deWait(void) { int i = 0x10000000; + unsigned int mask = DE_STATE2_DE_STATUS_BUSY | DE_STATE2_DE_FIFO_EMPTY | + DE_STATE2_DE_MEM_FIFO_EMPTY; while (i--) { unsigned int val = PEEK32(DE_STATE2); - if ((FIELD_GET(val, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) && - (FIELD_GET(val, DE_STATE2, DE_FIFO) == DE_STATE2_DE_FIFO_EMPTY) && - (FIELD_GET(val, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) { + if ((val & mask) == + (DE_STATE2_DE_FIFO_EMPTY | DE_STATE2_DE_MEM_FIFO_EMPTY)) return 0; - } } /* timeout error */ return -1; -- cgit From 1c3ad306884300a07822e91ac8e8dd8650c863a1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:17 +0200 Subject: staging: sm750fb: remove unused DE_STATE2_DE_RESERVED Definition of reserved fields in a register is not interesting Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index db13bdf6a1dc..38ebe95338db 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -9,9 +9,6 @@ #define DE_STATE2_DE_FIFO_EMPTY BIT(3) #define DE_STATE2_DE_STATUS_BUSY BIT(2) #define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1) -#define DE_STATE2_DE_RESERVED 0:0 - - #define SYSTEM_CTRL 0x000000 #define SYSTEM_CTRL_DPMS 31:30 -- cgit From 410c756d41ef57fd0252de652c635f247cc16474 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:18 +0200 Subject: staging: sm750fb: use BIT macro for SYSTEM_CTRL single-bit fields Replace complex definition of SYSTEM_CTRL fields and usage of FIELD_GET/SET with BIT() macro and open-coded register value modifications Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 24 ++++------ drivers/staging/sm750fb/ddk750_reg.h | 76 ++++++++------------------------ drivers/staging/sm750fb/sm750_hw.c | 15 ++++--- 3 files changed, 35 insertions(+), 80 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 84f6e8b8c0e2..1a29ae037ee3 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -136,17 +136,13 @@ static void waitNextVerticalSync(int ctrl, int delay) while (delay-- > 0) { /* Wait for end of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - PANEL_VSYNC); - } while (status == SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); /* Wait for start of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - PANEL_VSYNC); - } while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); } } else { @@ -163,17 +159,13 @@ static void waitNextVerticalSync(int ctrl, int delay) while (delay-- > 0) { /* Wait for end of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - CRT_VSYNC); - } while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE); /* Wait for start of vsync. */ do { - status = FIELD_GET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - CRT_VSYNC); - } while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE); + status = PEEK32(SYSTEM_CTRL); + } while (!(status & SYSTEM_CTRL_PANEL_VSYNC_ACTIVE)); } } } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 38ebe95338db..351a1dc67900 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -16,68 +16,30 @@ #define SYSTEM_CTRL_DPMS_VPHN 1 #define SYSTEM_CTRL_DPMS_VNHP 2 #define SYSTEM_CTRL_DPMS_VNHN 3 -#define SYSTEM_CTRL_PCI_BURST 29:29 -#define SYSTEM_CTRL_PCI_BURST_OFF 0 -#define SYSTEM_CTRL_PCI_BURST_ON 1 -#define SYSTEM_CTRL_PCI_MASTER 25:25 -#define SYSTEM_CTRL_PCI_MASTER_OFF 0 -#define SYSTEM_CTRL_PCI_MASTER_ON 1 -#define SYSTEM_CTRL_LATENCY_TIMER 24:24 -#define SYSTEM_CTRL_LATENCY_TIMER_ON 0 -#define SYSTEM_CTRL_LATENCY_TIMER_OFF 1 -#define SYSTEM_CTRL_DE_FIFO 23:23 -#define SYSTEM_CTRL_DE_FIFO_NOTEMPTY 0 -#define SYSTEM_CTRL_DE_FIFO_EMPTY 1 -#define SYSTEM_CTRL_DE_STATUS 22:22 -#define SYSTEM_CTRL_DE_STATUS_IDLE 0 -#define SYSTEM_CTRL_DE_STATUS_BUSY 1 -#define SYSTEM_CTRL_DE_MEM_FIFO 21:21 -#define SYSTEM_CTRL_DE_MEM_FIFO_NOTEMPTY 0 -#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY 1 -#define SYSTEM_CTRL_CSC_STATUS 20:20 -#define SYSTEM_CTRL_CSC_STATUS_IDLE 0 -#define SYSTEM_CTRL_CSC_STATUS_BUSY 1 -#define SYSTEM_CTRL_CRT_VSYNC 19:19 -#define SYSTEM_CTRL_CRT_VSYNC_INACTIVE 0 -#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE 1 -#define SYSTEM_CTRL_PANEL_VSYNC 18:18 -#define SYSTEM_CTRL_PANEL_VSYNC_INACTIVE 0 -#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE 1 -#define SYSTEM_CTRL_CURRENT_BUFFER 17:17 -#define SYSTEM_CTRL_CURRENT_BUFFER_NORMAL 0 -#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING 1 -#define SYSTEM_CTRL_DMA_STATUS 16:16 -#define SYSTEM_CTRL_DMA_STATUS_IDLE 0 -#define SYSTEM_CTRL_DMA_STATUS_BUSY 1 -#define SYSTEM_CTRL_PCI_BURST_READ 15:15 -#define SYSTEM_CTRL_PCI_BURST_READ_OFF 0 -#define SYSTEM_CTRL_PCI_BURST_READ_ON 1 -#define SYSTEM_CTRL_DE_ABORT 13:13 -#define SYSTEM_CTRL_DE_ABORT_OFF 0 -#define SYSTEM_CTRL_DE_ABORT_ON 1 -#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK 11:11 -#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_OFF 0 -#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK_ON 1 -#define SYSTEM_CTRL_PCI_RETRY 7:7 -#define SYSTEM_CTRL_PCI_RETRY_ON 0 -#define SYSTEM_CTRL_PCI_RETRY_OFF 1 +#define SYSTEM_CTRL_PCI_BURST BIT(29) +#define SYSTEM_CTRL_PCI_MASTER BIT(25) +#define SYSTEM_CTRL_LATENCY_TIMER_OFF BIT(24) +#define SYSTEM_CTRL_DE_FIFO_EMPTY BIT(23) +#define SYSTEM_CTRL_DE_STATUS_BUSY BIT(22) +#define SYSTEM_CTRL_DE_MEM_FIFO_EMPTY BIT(21) +#define SYSTEM_CTRL_CSC_STATUS_BUSY BIT(20) +#define SYSTEM_CTRL_CRT_VSYNC_ACTIVE BIT(19) +#define SYSTEM_CTRL_PANEL_VSYNC_ACTIVE BIT(18) +#define SYSTEM_CTRL_CURRENT_BUFFER_FLIP_PENDING BIT(17) +#define SYSTEM_CTRL_DMA_STATUS_BUSY BIT(16) +#define SYSTEM_CTRL_PCI_BURST_READ BIT(15) +#define SYSTEM_CTRL_DE_ABORT BIT(13) +#define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK BIT(11) +#define SYSTEM_CTRL_PCI_RETRY_OFF BIT(7) #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE 5:4 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 0 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 1 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 2 #define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 3 -#define SYSTEM_CTRL_CRT_TRISTATE 3:3 -#define SYSTEM_CTRL_CRT_TRISTATE_OFF 0 -#define SYSTEM_CTRL_CRT_TRISTATE_ON 1 -#define SYSTEM_CTRL_PCIMEM_TRISTATE 2:2 -#define SYSTEM_CTRL_PCIMEM_TRISTATE_OFF 0 -#define SYSTEM_CTRL_PCIMEM_TRISTATE_ON 1 -#define SYSTEM_CTRL_LOCALMEM_TRISTATE 1:1 -#define SYSTEM_CTRL_LOCALMEM_TRISTATE_OFF 0 -#define SYSTEM_CTRL_LOCALMEM_TRISTATE_ON 1 -#define SYSTEM_CTRL_PANEL_TRISTATE 0:0 -#define SYSTEM_CTRL_PANEL_TRISTATE_OFF 0 -#define SYSTEM_CTRL_PANEL_TRISTATE_ON 1 +#define SYSTEM_CTRL_CRT_TRISTATE BIT(3) +#define SYSTEM_CTRL_PCIMEM_TRISTATE BIT(2) +#define SYSTEM_CTRL_LOCALMEM_TRISTATE BIT(1) +#define SYSTEM_CTRL_PANEL_TRISTATE BIT(0) #define MISC_CTRL 0x000004 #define MISC_CTRL_DRAM_RERESH_COUNT 27:27 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 425bec886078..59adeb669644 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -108,7 +108,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* for sm718,open pci burst */ if (sm750_dev->devid == 0x718) { POKE32(SYSTEM_CTRL, - FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON)); + PEEK32(SYSTEM_CTRL) | SYSTEM_CTRL_PCI_BURST); } if (getChipType() != SM750LE) { @@ -478,11 +478,11 @@ void hw_sm750_initAccel(struct sm750_dev *sm750_dev) } else { /* engine reset */ reg = PEEK32(SYSTEM_CTRL); - reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON); + reg |= SYSTEM_CTRL_DE_ABORT; POKE32(SYSTEM_CTRL, reg); reg = PEEK32(SYSTEM_CTRL); - reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, OFF); + reg &= ~SYSTEM_CTRL_DE_ABORT; POKE32(SYSTEM_CTRL, reg); } @@ -511,15 +511,16 @@ int hw_sm750le_deWait(void) int hw_sm750_deWait(void) { int i = 0x10000000; + unsigned int mask = SYSTEM_CTRL_DE_STATUS_BUSY | + SYSTEM_CTRL_DE_FIFO_EMPTY | + SYSTEM_CTRL_DE_MEM_FIFO_EMPTY; while (i--) { unsigned int val = PEEK32(SYSTEM_CTRL); - if ((FIELD_GET(val, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) && - (FIELD_GET(val, SYSTEM_CTRL, DE_FIFO) == SYSTEM_CTRL_DE_FIFO_EMPTY) && - (FIELD_GET(val, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) { + if ((val & mask) == + (SYSTEM_CTRL_DE_FIFO_EMPTY | SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) return 0; - } } /* timeout error */ return -1; -- cgit From a8856ff88ee8b6026782c70f71f0c95c45c57992 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:19 +0200 Subject: staging: sm750fb: change definition of SYSTEM_CTRL multi-bit fields Use more straight-forward definitions for multi-bit fields of SYSTEM_CTRL register and replace FIELD_GET/SET for these fields with open-coded implementation. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 20 ++++++++++---------- drivers/staging/sm750fb/sm750_hw.c | 18 +++++++++--------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 667e4f822544..1c5001c0a44e 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -12,7 +12,7 @@ void ddk750_setDPMS(DPMS_t state) DPMS, state)); } else { value = PEEK32(SYSTEM_CTRL); - value = FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state); + value = (value & ~SYSTEM_CTRL_DPMS_MASK) | state; POKE32(SYSTEM_CTRL, value); } } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 351a1dc67900..75a20e70ebc3 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -11,11 +11,11 @@ #define DE_STATE2_DE_MEM_FIFO_EMPTY BIT(1) #define SYSTEM_CTRL 0x000000 -#define SYSTEM_CTRL_DPMS 31:30 -#define SYSTEM_CTRL_DPMS_VPHP 0 -#define SYSTEM_CTRL_DPMS_VPHN 1 -#define SYSTEM_CTRL_DPMS_VNHP 2 -#define SYSTEM_CTRL_DPMS_VNHN 3 +#define SYSTEM_CTRL_DPMS_MASK (0x3 << 30) +#define SYSTEM_CTRL_DPMS_VPHP (0x0 << 30) +#define SYSTEM_CTRL_DPMS_VPHN (0x1 << 30) +#define SYSTEM_CTRL_DPMS_VNHP (0x2 << 30) +#define SYSTEM_CTRL_DPMS_VNHN (0x3 << 30) #define SYSTEM_CTRL_PCI_BURST BIT(29) #define SYSTEM_CTRL_PCI_MASTER BIT(25) #define SYSTEM_CTRL_LATENCY_TIMER_OFF BIT(24) @@ -31,11 +31,11 @@ #define SYSTEM_CTRL_DE_ABORT BIT(13) #define SYSTEM_CTRL_PCI_SUBSYS_ID_LOCK BIT(11) #define SYSTEM_CTRL_PCI_RETRY_OFF BIT(7) -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE 5:4 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 0 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 1 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 2 -#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 3 +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_MASK (0x3 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_1 (0x0 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_2 (0x1 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_4 (0x2 << 4) +#define SYSTEM_CTRL_PCI_SLAVE_BURST_READ_SIZE_8 (0x3 << 4) #define SYSTEM_CTRL_CRT_TRISTATE BIT(3) #define SYSTEM_CTRL_PCIMEM_TRISTATE BIT(2) #define SYSTEM_CTRL_LOCALMEM_TRISTATE BIT(1) diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 59adeb669644..357ee5654d4d 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -112,6 +112,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) } if (getChipType() != SM750LE) { + unsigned int val; /* does user need CRT ?*/ if (sm750_dev->nocrt) { POKE32(MISC_CTRL, @@ -119,20 +120,18 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) MISC_CTRL, DAC_POWER, OFF)); /* shut off dpms */ - POKE32(SYSTEM_CTRL, - FIELD_SET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - DPMS, VNHN)); + val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; + val |= SYSTEM_CTRL_DPMS_VPHN; + POKE32(SYSTEM_CTRL, val); } else { POKE32(MISC_CTRL, FIELD_SET(PEEK32(MISC_CTRL), MISC_CTRL, DAC_POWER, ON)); /* turn on dpms */ - POKE32(SYSTEM_CTRL, - FIELD_SET(PEEK32(SYSTEM_CTRL), - SYSTEM_CTRL, - DPMS, VPHP)); + val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; + val |= SYSTEM_CTRL_DPMS_VPHP; + POKE32(SYSTEM_CTRL, val); } switch (sm750_dev->pnltype) { @@ -448,8 +447,9 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) } if (output->paths & sm750_crt) { + unsigned int val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; - POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms)); + POKE32(SYSTEM_CTRL, val | dpms); POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb)); } -- cgit From 8bc728cf0125ad1e420b2097b28488c23dc0cab2 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:20 +0200 Subject: staging: sm750fb: ddk750_initHw: rename ulReg to reg Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 52 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 0331d34458ae..905c1a86fd80 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -197,24 +197,24 @@ unsigned int ddk750_getVMSize(void) int ddk750_initHw(initchip_param_t *pInitParam) { - unsigned int ulReg; + unsigned int reg; if (pInitParam->powerMode != 0) pInitParam->powerMode = 0; setPowerMode(pInitParam->powerMode); /* Enable display power gate & LOCALMEM power gate*/ - ulReg = PEEK32(CURRENT_GATE); - ulReg = FIELD_SET(ulReg, CURRENT_GATE, DISPLAY, ON); - ulReg = FIELD_SET(ulReg, CURRENT_GATE, LOCALMEM, ON); - setCurrentGate(ulReg); + reg = PEEK32(CURRENT_GATE); + reg = FIELD_SET(reg, CURRENT_GATE, DISPLAY, ON); + reg = FIELD_SET(reg, CURRENT_GATE, LOCALMEM, ON); + setCurrentGate(reg); if (getChipType() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ - ulReg = PEEK32(VGA_CONFIGURATION); - ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, PLL, PANEL); - ulReg = FIELD_SET(ulReg, VGA_CONFIGURATION, MODE, GRAPHIC); - POKE32(VGA_CONFIGURATION, ulReg); + reg = PEEK32(VGA_CONFIGURATION); + reg = FIELD_SET(reg, VGA_CONFIGURATION, PLL, PANEL); + reg = FIELD_SET(reg, VGA_CONFIGURATION, MODE, GRAPHIC); + POKE32(VGA_CONFIGURATION, reg); } else { #if defined(__i386__) || defined(__x86_64__) /* set graphic mode via IO method */ @@ -238,36 +238,36 @@ int ddk750_initHw(initchip_param_t *pInitParam) The memory should be resetted after changing the MXCLK. */ if (pInitParam->resetMemory == 1) { - ulReg = PEEK32(MISC_CTRL); - ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, RESET); - POKE32(MISC_CTRL, ulReg); + reg = PEEK32(MISC_CTRL); + reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, RESET); + POKE32(MISC_CTRL, reg); - ulReg = FIELD_SET(ulReg, MISC_CTRL, LOCALMEM_RESET, NORMAL); - POKE32(MISC_CTRL, ulReg); + reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, NORMAL); + POKE32(MISC_CTRL, reg); } if (pInitParam->setAllEngOff == 1) { enable2DEngine(0); /* Disable Overlay, if a former application left it on */ - ulReg = PEEK32(VIDEO_DISPLAY_CTRL); - ulReg = FIELD_SET(ulReg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(VIDEO_DISPLAY_CTRL, ulReg); + reg = PEEK32(VIDEO_DISPLAY_CTRL); + reg = FIELD_SET(reg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); + POKE32(VIDEO_DISPLAY_CTRL, reg); /* Disable video alpha, if a former application left it on */ - ulReg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); - ulReg = FIELD_SET(ulReg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(VIDEO_ALPHA_DISPLAY_CTRL, ulReg); + reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); + reg = FIELD_SET(reg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); + POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg); /* Disable alpha plane, if a former application left it on */ - ulReg = PEEK32(ALPHA_DISPLAY_CTRL); - ulReg = FIELD_SET(ulReg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(ALPHA_DISPLAY_CTRL, ulReg); + reg = PEEK32(ALPHA_DISPLAY_CTRL); + reg = FIELD_SET(reg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); + POKE32(ALPHA_DISPLAY_CTRL, reg); /* Disable DMA Channel, if a former application left it on */ - ulReg = PEEK32(DMA_ABORT_INTERRUPT); - ulReg = FIELD_SET(ulReg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); - POKE32(DMA_ABORT_INTERRUPT, ulReg); + reg = PEEK32(DMA_ABORT_INTERRUPT); + reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); + POKE32(DMA_ABORT_INTERRUPT, reg); /* Disable DMA Power, if a former application left it on */ enableDMA(0); -- cgit From 5372350be30abf9f84e676d1f28260d3a3b5e629 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:21 +0200 Subject: staging: sm750fb: use BIT macro for MISC_CTRL single-bit fields Replace complex definition of MISC_CTRL register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 4 +- drivers/staging/sm750fb/ddk750_power.h | 11 ++---- drivers/staging/sm750fb/ddk750_reg.h | 68 +++++++++------------------------- drivers/staging/sm750fb/sm750_hw.c | 8 +--- 4 files changed, 25 insertions(+), 66 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 905c1a86fd80..08b490578b06 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -239,10 +239,10 @@ int ddk750_initHw(initchip_param_t *pInitParam) */ if (pInitParam->resetMemory == 1) { reg = PEEK32(MISC_CTRL); - reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, RESET); + reg &= ~MISC_CTRL_LOCALMEM_RESET; POKE32(MISC_CTRL, reg); - reg = FIELD_SET(reg, MISC_CTRL, LOCALMEM_RESET, NORMAL); + reg |= MISC_CTRL_LOCALMEM_RESET; POKE32(MISC_CTRL, reg); } diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h index 6e804d990cff..5963691f9a68 100644 --- a/drivers/staging/sm750fb/ddk750_power.h +++ b/drivers/staging/sm750fb/ddk750_power.h @@ -9,13 +9,10 @@ typedef enum _DPMS_t { } DPMS_t; -#define setDAC(off) \ - { \ - POKE32(MISC_CTRL, FIELD_VALUE(PEEK32(MISC_CTRL), \ - MISC_CTRL, \ - DAC_POWER, \ - off)); \ - } +#define setDAC(off) { \ + POKE32(MISC_CTRL, \ + (PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF) | (off)); \ +} void ddk750_setDPMS(DPMS_t); diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 75a20e70ebc3..6fef904f3de1 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -42,26 +42,16 @@ #define SYSTEM_CTRL_PANEL_TRISTATE BIT(0) #define MISC_CTRL 0x000004 -#define MISC_CTRL_DRAM_RERESH_COUNT 27:27 -#define MISC_CTRL_DRAM_RERESH_COUNT_1ROW 0 -#define MISC_CTRL_DRAM_RERESH_COUNT_3ROW 1 +#define MISC_CTRL_DRAM_RERESH_COUNT BIT(27) #define MISC_CTRL_DRAM_REFRESH_TIME 26:25 #define MISC_CTRL_DRAM_REFRESH_TIME_8 0 #define MISC_CTRL_DRAM_REFRESH_TIME_16 1 #define MISC_CTRL_DRAM_REFRESH_TIME_32 2 #define MISC_CTRL_DRAM_REFRESH_TIME_64 3 -#define MISC_CTRL_INT_OUTPUT 24:24 -#define MISC_CTRL_INT_OUTPUT_NORMAL 0 -#define MISC_CTRL_INT_OUTPUT_INVERT 1 -#define MISC_CTRL_PLL_CLK_COUNT 23:23 -#define MISC_CTRL_PLL_CLK_COUNT_OFF 0 -#define MISC_CTRL_PLL_CLK_COUNT_ON 1 -#define MISC_CTRL_DAC_POWER 20:20 -#define MISC_CTRL_DAC_POWER_ON 0 -#define MISC_CTRL_DAC_POWER_OFF 1 -#define MISC_CTRL_CLK_SELECT 16:16 -#define MISC_CTRL_CLK_SELECT_OSC 0 -#define MISC_CTRL_CLK_SELECT_TESTCLK 1 +#define MISC_CTRL_INT_OUTPUT_INVERT BIT(24) +#define MISC_CTRL_PLL_CLK_COUNT BIT(23) +#define MISC_CTRL_DAC_POWER_OFF BIT(20) +#define MISC_CTRL_CLK_SELECT_TESTCLK BIT(16) #define MISC_CTRL_DRAM_COLUMN_SIZE 15:14 #define MISC_CTRL_DRAM_COLUMN_SIZE_256 0 #define MISC_CTRL_DRAM_COLUMN_SIZE_512 1 @@ -71,42 +61,18 @@ #define MISC_CTRL_LOCALMEM_SIZE_16M 0 #define MISC_CTRL_LOCALMEM_SIZE_32M 1 #define MISC_CTRL_LOCALMEM_SIZE_64M 2 -#define MISC_CTRL_DRAM_TWTR 11:11 -#define MISC_CTRL_DRAM_TWTR_2CLK 0 -#define MISC_CTRL_DRAM_TWTR_1CLK 1 -#define MISC_CTRL_DRAM_TWR 10:10 -#define MISC_CTRL_DRAM_TWR_3CLK 0 -#define MISC_CTRL_DRAM_TWR_2CLK 1 -#define MISC_CTRL_DRAM_TRP 9:9 -#define MISC_CTRL_DRAM_TRP_3CLK 0 -#define MISC_CTRL_DRAM_TRP_4CLK 1 -#define MISC_CTRL_DRAM_TRFC 8:8 -#define MISC_CTRL_DRAM_TRFC_12CLK 0 -#define MISC_CTRL_DRAM_TRFC_14CLK 1 -#define MISC_CTRL_DRAM_TRAS 7:7 -#define MISC_CTRL_DRAM_TRAS_7CLK 0 -#define MISC_CTRL_DRAM_TRAS_8CLK 1 -#define MISC_CTRL_LOCALMEM_RESET 6:6 -#define MISC_CTRL_LOCALMEM_RESET_RESET 0 -#define MISC_CTRL_LOCALMEM_RESET_NORMAL 1 -#define MISC_CTRL_LOCALMEM_STATE 5:5 -#define MISC_CTRL_LOCALMEM_STATE_ACTIVE 0 -#define MISC_CTRL_LOCALMEM_STATE_INACTIVE 1 -#define MISC_CTRL_CPU_CAS_LATENCY 4:4 -#define MISC_CTRL_CPU_CAS_LATENCY_2CLK 0 -#define MISC_CTRL_CPU_CAS_LATENCY_3CLK 1 -#define MISC_CTRL_DLL 3:3 -#define MISC_CTRL_DLL_ON 0 -#define MISC_CTRL_DLL_OFF 1 -#define MISC_CTRL_DRAM_OUTPUT 2:2 -#define MISC_CTRL_DRAM_OUTPUT_LOW 0 -#define MISC_CTRL_DRAM_OUTPUT_HIGH 1 -#define MISC_CTRL_LOCALMEM_BUS_SIZE 1:1 -#define MISC_CTRL_LOCALMEM_BUS_SIZE_32 0 -#define MISC_CTRL_LOCALMEM_BUS_SIZE_64 1 -#define MISC_CTRL_EMBEDDED_LOCALMEM 0:0 -#define MISC_CTRL_EMBEDDED_LOCALMEM_ON 0 -#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF 1 +#define MISC_CTRL_DRAM_TWTR BIT(11) +#define MISC_CTRL_DRAM_TWR BIT(10) +#define MISC_CTRL_DRAM_TRP BIT(9) +#define MISC_CTRL_DRAM_TRFC BIT(8) +#define MISC_CTRL_DRAM_TRAS BIT(7) +#define MISC_CTRL_LOCALMEM_RESET BIT(6) +#define MISC_CTRL_LOCALMEM_STATE_INACTIVE BIT(5) +#define MISC_CTRL_CPU_CAS_LATENCY BIT(4) +#define MISC_CTRL_DLL_OFF BIT(3) +#define MISC_CTRL_DRAM_OUTPUT_HIGH BIT(2) +#define MISC_CTRL_LOCALMEM_BUS_SIZE BIT(1) +#define MISC_CTRL_EMBEDDED_LOCALMEM_OFF BIT(0) #define GPIO_MUX 0x000008 #define GPIO_MUX_31 31:31 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 357ee5654d4d..b33ec076f3f5 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -116,18 +116,14 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* does user need CRT ?*/ if (sm750_dev->nocrt) { POKE32(MISC_CTRL, - FIELD_SET(PEEK32(MISC_CTRL), - MISC_CTRL, - DAC_POWER, OFF)); + PEEK32(MISC_CTRL) | MISC_CTRL_DAC_POWER_OFF); /* shut off dpms */ val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; val |= SYSTEM_CTRL_DPMS_VPHN; POKE32(SYSTEM_CTRL, val); } else { POKE32(MISC_CTRL, - FIELD_SET(PEEK32(MISC_CTRL), - MISC_CTRL, - DAC_POWER, ON)); + PEEK32(MISC_CTRL) & ~MISC_CTRL_DAC_POWER_OFF); /* turn on dpms */ val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; val |= SYSTEM_CTRL_DPMS_VPHP; -- cgit From 9a357143bcddcbba4e57839694240ad44714279d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:22 +0200 Subject: staging: sm750fb: ddk750_sii164: fix defines for i2c{Read, Write}reg For case when USE_HW_I2C is not defined, i2c{Read,Write}reg was wrongly defined to use old function names. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_sii164.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c index 241b77b927ee..9fd6afb009c2 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.c +++ b/drivers/staging/sm750fb/ddk750_sii164.c @@ -14,8 +14,8 @@ #define i2cWriteReg sm750_hw_i2c_write_reg #define i2cReadReg sm750_hw_i2c_read_reg #else - #define i2cWriteReg swI2CWriteReg - #define i2cReadReg swI2CReadReg + #define i2cWriteReg sm750_sw_i2c_write_reg + #define i2cReadReg sm750_sw_i2c_read_reg #endif /* SII164 Vendor and Device ID */ -- cgit From 2a5149e0a20f451c0c39e4fc90511f13615e80c9 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:23 +0200 Subject: staging: sm750fb: use BIT macro for GPIO_MUX single-bit fields Replace complex definition of GPIO_MUX register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_hwi2c.c | 7 +- drivers/staging/sm750fb/ddk750_reg.h | 128 +++++++++------------------------ 2 files changed, 35 insertions(+), 100 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 7be2111284f4..b824681e55a7 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -17,8 +17,7 @@ unsigned char bus_speed_mode /* Enable GPIO 30 & 31 as IIC clock & data */ value = PEEK32(GPIO_MUX); - value = FIELD_SET(value, GPIO_MUX, 30, I2C) | - FIELD_SET(0, GPIO_MUX, 31, I2C); + value |= (GPIO_MUX_30 | GPIO_MUX_31); POKE32(GPIO_MUX, value); /* Enable Hardware I2C power. @@ -52,8 +51,8 @@ void sm750_hw_i2c_close(void) /* Set GPIO 30 & 31 back as GPIO pins */ value = PEEK32(GPIO_MUX); - value = FIELD_SET(value, GPIO_MUX, 30, GPIO); - value = FIELD_SET(value, GPIO_MUX, 31, GPIO); + value &= ~GPIO_MUX_30; + value &= ~GPIO_MUX_31; POKE32(GPIO_MUX, value); } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 6fef904f3de1..6df50769746e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -75,102 +75,38 @@ #define MISC_CTRL_EMBEDDED_LOCALMEM_OFF BIT(0) #define GPIO_MUX 0x000008 -#define GPIO_MUX_31 31:31 -#define GPIO_MUX_31_GPIO 0 -#define GPIO_MUX_31_I2C 1 -#define GPIO_MUX_30 30:30 -#define GPIO_MUX_30_GPIO 0 -#define GPIO_MUX_30_I2C 1 -#define GPIO_MUX_29 29:29 -#define GPIO_MUX_29_GPIO 0 -#define GPIO_MUX_29_SSP1 1 -#define GPIO_MUX_28 28:28 -#define GPIO_MUX_28_GPIO 0 -#define GPIO_MUX_28_SSP1 1 -#define GPIO_MUX_27 27:27 -#define GPIO_MUX_27_GPIO 0 -#define GPIO_MUX_27_SSP1 1 -#define GPIO_MUX_26 26:26 -#define GPIO_MUX_26_GPIO 0 -#define GPIO_MUX_26_SSP1 1 -#define GPIO_MUX_25 25:25 -#define GPIO_MUX_25_GPIO 0 -#define GPIO_MUX_25_SSP1 1 -#define GPIO_MUX_24 24:24 -#define GPIO_MUX_24_GPIO 0 -#define GPIO_MUX_24_SSP0 1 -#define GPIO_MUX_23 23:23 -#define GPIO_MUX_23_GPIO 0 -#define GPIO_MUX_23_SSP0 1 -#define GPIO_MUX_22 22:22 -#define GPIO_MUX_22_GPIO 0 -#define GPIO_MUX_22_SSP0 1 -#define GPIO_MUX_21 21:21 -#define GPIO_MUX_21_GPIO 0 -#define GPIO_MUX_21_SSP0 1 -#define GPIO_MUX_20 20:20 -#define GPIO_MUX_20_GPIO 0 -#define GPIO_MUX_20_SSP0 1 -#define GPIO_MUX_19 19:19 -#define GPIO_MUX_19_GPIO 0 -#define GPIO_MUX_19_PWM 1 -#define GPIO_MUX_18 18:18 -#define GPIO_MUX_18_GPIO 0 -#define GPIO_MUX_18_PWM 1 -#define GPIO_MUX_17 17:17 -#define GPIO_MUX_17_GPIO 0 -#define GPIO_MUX_17_PWM 1 -#define GPIO_MUX_16 16:16 -#define GPIO_MUX_16_GPIO_ZVPORT 0 -#define GPIO_MUX_16_TEST_DATA 1 -#define GPIO_MUX_15 15:15 -#define GPIO_MUX_15_GPIO_ZVPORT 0 -#define GPIO_MUX_15_TEST_DATA 1 -#define GPIO_MUX_14 14:14 -#define GPIO_MUX_14_GPIO_ZVPORT 0 -#define GPIO_MUX_14_TEST_DATA 1 -#define GPIO_MUX_13 13:13 -#define GPIO_MUX_13_GPIO_ZVPORT 0 -#define GPIO_MUX_13_TEST_DATA 1 -#define GPIO_MUX_12 12:12 -#define GPIO_MUX_12_GPIO_ZVPORT 0 -#define GPIO_MUX_12_TEST_DATA 1 -#define GPIO_MUX_11 11:11 -#define GPIO_MUX_11_GPIO_ZVPORT 0 -#define GPIO_MUX_11_TEST_DATA 1 -#define GPIO_MUX_10 10:10 -#define GPIO_MUX_10_GPIO_ZVPORT 0 -#define GPIO_MUX_10_TEST_DATA 1 -#define GPIO_MUX_9 9:9 -#define GPIO_MUX_9_GPIO_ZVPORT 0 -#define GPIO_MUX_9_TEST_DATA 1 -#define GPIO_MUX_8 8:8 -#define GPIO_MUX_8_GPIO_ZVPORT 0 -#define GPIO_MUX_8_TEST_DATA 1 -#define GPIO_MUX_7 7:7 -#define GPIO_MUX_7_GPIO_ZVPORT 0 -#define GPIO_MUX_7_TEST_DATA 1 -#define GPIO_MUX_6 6:6 -#define GPIO_MUX_6_GPIO_ZVPORT 0 -#define GPIO_MUX_6_TEST_DATA 1 -#define GPIO_MUX_5 5:5 -#define GPIO_MUX_5_GPIO_ZVPORT 0 -#define GPIO_MUX_5_TEST_DATA 1 -#define GPIO_MUX_4 4:4 -#define GPIO_MUX_4_GPIO_ZVPORT 0 -#define GPIO_MUX_4_TEST_DATA 1 -#define GPIO_MUX_3 3:3 -#define GPIO_MUX_3_GPIO_ZVPORT 0 -#define GPIO_MUX_3_TEST_DATA 1 -#define GPIO_MUX_2 2:2 -#define GPIO_MUX_2_GPIO_ZVPORT 0 -#define GPIO_MUX_2_TEST_DATA 1 -#define GPIO_MUX_1 1:1 -#define GPIO_MUX_1_GPIO_ZVPORT 0 -#define GPIO_MUX_1_TEST_DATA 1 -#define GPIO_MUX_0 0:0 -#define GPIO_MUX_0_GPIO_ZVPORT 0 -#define GPIO_MUX_0_TEST_DATA 1 +#define GPIO_MUX_31 BIT(31) +#define GPIO_MUX_30 BIT(30) +#define GPIO_MUX_29 BIT(29) +#define GPIO_MUX_28 BIT(28) +#define GPIO_MUX_27 BIT(27) +#define GPIO_MUX_26 BIT(26) +#define GPIO_MUX_25 BIT(25) +#define GPIO_MUX_24 BIT(24) +#define GPIO_MUX_23 BIT(23) +#define GPIO_MUX_22 BIT(22) +#define GPIO_MUX_21 BIT(21) +#define GPIO_MUX_20 BIT(20) +#define GPIO_MUX_19 BIT(19) +#define GPIO_MUX_18 BIT(18) +#define GPIO_MUX_17 BIT(17) +#define GPIO_MUX_16 BIT(16) +#define GPIO_MUX_15 BIT(15) +#define GPIO_MUX_14 BIT(14) +#define GPIO_MUX_13 BIT(13) +#define GPIO_MUX_12 BIT(12) +#define GPIO_MUX_11 BIT(11) +#define GPIO_MUX_10 BIT(10) +#define GPIO_MUX_9 BIT(9) +#define GPIO_MUX_8 BIT(8) +#define GPIO_MUX_7 BIT(7) +#define GPIO_MUX_6 BIT(6) +#define GPIO_MUX_5 BIT(5) +#define GPIO_MUX_4 BIT(4) +#define GPIO_MUX_3 BIT(3) +#define GPIO_MUX_2 BIT(2) +#define GPIO_MUX_1 BIT(1) +#define GPIO_MUX_0 BIT(0) #define LOCALMEM_ARBITRATION 0x00000C #define LOCALMEM_ARBITRATION_ROTATE 28:28 -- cgit From 5538d5c8bd1681dbf6e5684de24acffa69e2bf9f Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:24 +0200 Subject: staging: sm750fb: change definition of MISC_CTRL multi-bit fields Use more straight-forward definitions for multi-bit fields of MISC_CTRL register and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 08b490578b06..36c2e50ef661 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -178,7 +178,7 @@ unsigned int ddk750_getVMSize(void) POKE32(MODE0_GATE, reg); /* get frame buffer size from GPIO */ - reg = FIELD_GET(PEEK32(MISC_CTRL), MISC_CTRL, LOCALMEM_SIZE); + reg = PEEK32(MISC_CTRL) & MISC_CTRL_LOCALMEM_SIZE_MASK; switch (reg) { case MISC_CTRL_LOCALMEM_SIZE_8M: data = SZ_8M; break; /* 8 Mega byte */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 6df50769746e..72eaf1920bd0 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -43,24 +43,24 @@ #define MISC_CTRL 0x000004 #define MISC_CTRL_DRAM_RERESH_COUNT BIT(27) -#define MISC_CTRL_DRAM_REFRESH_TIME 26:25 -#define MISC_CTRL_DRAM_REFRESH_TIME_8 0 -#define MISC_CTRL_DRAM_REFRESH_TIME_16 1 -#define MISC_CTRL_DRAM_REFRESH_TIME_32 2 -#define MISC_CTRL_DRAM_REFRESH_TIME_64 3 +#define MISC_CTRL_DRAM_REFRESH_TIME_MASK (0x3 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_8 (0x0 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_16 (0x1 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_32 (0x2 << 25) +#define MISC_CTRL_DRAM_REFRESH_TIME_64 (0x3 << 25) #define MISC_CTRL_INT_OUTPUT_INVERT BIT(24) #define MISC_CTRL_PLL_CLK_COUNT BIT(23) #define MISC_CTRL_DAC_POWER_OFF BIT(20) #define MISC_CTRL_CLK_SELECT_TESTCLK BIT(16) -#define MISC_CTRL_DRAM_COLUMN_SIZE 15:14 -#define MISC_CTRL_DRAM_COLUMN_SIZE_256 0 -#define MISC_CTRL_DRAM_COLUMN_SIZE_512 1 -#define MISC_CTRL_DRAM_COLUMN_SIZE_1024 2 -#define MISC_CTRL_LOCALMEM_SIZE 13:12 -#define MISC_CTRL_LOCALMEM_SIZE_8M 3 -#define MISC_CTRL_LOCALMEM_SIZE_16M 0 -#define MISC_CTRL_LOCALMEM_SIZE_32M 1 -#define MISC_CTRL_LOCALMEM_SIZE_64M 2 +#define MISC_CTRL_DRAM_COLUMN_SIZE_MASK (0x3 << 14) +#define MISC_CTRL_DRAM_COLUMN_SIZE_256 (0x0 << 14) +#define MISC_CTRL_DRAM_COLUMN_SIZE_512 (0x1 << 14) +#define MISC_CTRL_DRAM_COLUMN_SIZE_1024 (0x2 << 14) +#define MISC_CTRL_LOCALMEM_SIZE_MASK (0x3 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_8M (0x3 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_16M (0x0 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_32M (0x1 << 12) +#define MISC_CTRL_LOCALMEM_SIZE_64M (0x2 << 12) #define MISC_CTRL_DRAM_TWTR BIT(11) #define MISC_CTRL_DRAM_TWR BIT(10) #define MISC_CTRL_DRAM_TRP BIT(9) -- cgit From 90946e5293af9ff1253bc038e2afa4aa0844b75a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:25 +0200 Subject: staging: sm750fb: use BIT macro for CURRENT_GATE single-bit fields Replace complex definition of CURRENT_GATE register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 3 +-- drivers/staging/sm750fb/ddk750_power.c | 18 +++++++------- drivers/staging/sm750fb/ddk750_reg.h | 44 +++++++++------------------------- 3 files changed, 20 insertions(+), 45 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 36c2e50ef661..b11231ca1894 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -205,8 +205,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) /* Enable display power gate & LOCALMEM power gate*/ reg = PEEK32(CURRENT_GATE); - reg = FIELD_SET(reg, CURRENT_GATE, DISPLAY, ON); - reg = FIELD_SET(reg, CURRENT_GATE, LOCALMEM, ON); + reg |= (CURRENT_GATE_DISPLAY | CURRENT_GATE_LOCALMEM); setCurrentGate(reg); if (getChipType() != SM750LE) { diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 1c5001c0a44e..417702548f0f 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -112,11 +112,9 @@ void enable2DEngine(unsigned int enable) gate = PEEK32(CURRENT_GATE); if (enable) { - gate = FIELD_SET(gate, CURRENT_GATE, DE, ON); - gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON); + gate |= (CURRENT_GATE_DE | CURRENT_GATE_CSC); } else { - gate = FIELD_SET(gate, CURRENT_GATE, DE, OFF); - gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF); + gate &= ~(CURRENT_GATE_DE | CURRENT_GATE_CSC); } setCurrentGate(gate); @@ -129,9 +127,9 @@ void enableDMA(unsigned int enable) /* Enable DMA Gate */ gate = PEEK32(CURRENT_GATE); if (enable) - gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON); + gate |= CURRENT_GATE_DMA; else - gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF); + gate &= ~CURRENT_GATE_DMA; setCurrentGate(gate); } @@ -146,9 +144,9 @@ void enableGPIO(unsigned int enable) /* Enable GPIO Gate */ gate = PEEK32(CURRENT_GATE); if (enable) - gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON); + gate |= CURRENT_GATE_GPIO; else - gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF); + gate &= ~CURRENT_GATE_GPIO; setCurrentGate(gate); } @@ -163,9 +161,9 @@ void enableI2C(unsigned int enable) /* Enable I2C Gate */ gate = PEEK32(CURRENT_GATE); if (enable) - gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON); + gate |= CURRENT_GATE_I2C; else - gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF); + gate &= ~CURRENT_GATE_I2C; setCurrentGate(gate); } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 72eaf1920bd0..e3ca8326f96f 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -415,39 +415,17 @@ #define CURRENT_GATE_M2XCLK_DIV_3 2 #define CURRENT_GATE_M2XCLK_DIV_4 3 #endif -#define CURRENT_GATE_VGA 10:10 -#define CURRENT_GATE_VGA_OFF 0 -#define CURRENT_GATE_VGA_ON 1 -#define CURRENT_GATE_PWM 9:9 -#define CURRENT_GATE_PWM_OFF 0 -#define CURRENT_GATE_PWM_ON 1 -#define CURRENT_GATE_I2C 8:8 -#define CURRENT_GATE_I2C_OFF 0 -#define CURRENT_GATE_I2C_ON 1 -#define CURRENT_GATE_SSP 7:7 -#define CURRENT_GATE_SSP_OFF 0 -#define CURRENT_GATE_SSP_ON 1 -#define CURRENT_GATE_GPIO 6:6 -#define CURRENT_GATE_GPIO_OFF 0 -#define CURRENT_GATE_GPIO_ON 1 -#define CURRENT_GATE_ZVPORT 5:5 -#define CURRENT_GATE_ZVPORT_OFF 0 -#define CURRENT_GATE_ZVPORT_ON 1 -#define CURRENT_GATE_CSC 4:4 -#define CURRENT_GATE_CSC_OFF 0 -#define CURRENT_GATE_CSC_ON 1 -#define CURRENT_GATE_DE 3:3 -#define CURRENT_GATE_DE_OFF 0 -#define CURRENT_GATE_DE_ON 1 -#define CURRENT_GATE_DISPLAY 2:2 -#define CURRENT_GATE_DISPLAY_OFF 0 -#define CURRENT_GATE_DISPLAY_ON 1 -#define CURRENT_GATE_LOCALMEM 1:1 -#define CURRENT_GATE_LOCALMEM_OFF 0 -#define CURRENT_GATE_LOCALMEM_ON 1 -#define CURRENT_GATE_DMA 0:0 -#define CURRENT_GATE_DMA_OFF 0 -#define CURRENT_GATE_DMA_ON 1 +#define CURRENT_GATE_VGA BIT(10) +#define CURRENT_GATE_PWM BIT(9) +#define CURRENT_GATE_I2C BIT(8) +#define CURRENT_GATE_SSP BIT(7) +#define CURRENT_GATE_GPIO BIT(6) +#define CURRENT_GATE_ZVPORT BIT(5) +#define CURRENT_GATE_CSC BIT(4) +#define CURRENT_GATE_DE BIT(3) +#define CURRENT_GATE_DISPLAY BIT(2) +#define CURRENT_GATE_LOCALMEM BIT(1) +#define CURRENT_GATE_DMA BIT(0) #define MODE0_GATE 0x000044 #define MODE0_GATE_MCLK 15:14 -- cgit From 19aa211387d195ff77699895d017688954402e6a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:26 +0200 Subject: staging: sm750fb: set{Memory, Master}Clock: rename ulReg to reg Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index b11231ca1894..37c52a3f2d81 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -79,7 +79,7 @@ static void setChipClock(unsigned int frequency) static void setMemoryClock(unsigned int frequency) { - unsigned int ulReg, divisor; + unsigned int reg, divisor; /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ if (getChipType() == SM750LE) @@ -95,24 +95,24 @@ static void setMemoryClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - ulReg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE); switch (divisor) { default: case 1: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_1); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_1); break; case 2: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_2); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_2); break; case 3: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_3); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_3); break; case 4: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, M2XCLK, DIV_4); + reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_4); break; } - setCurrentGate(ulReg); + setCurrentGate(reg); } } @@ -126,7 +126,7 @@ static void setMemoryClock(unsigned int frequency) */ static void setMasterClock(unsigned int frequency) { - unsigned int ulReg, divisor; + unsigned int reg, divisor; /* Cheok_0509: For SM750LE, the memory clock is fixed. Nothing to set. */ if (getChipType() == SM750LE) @@ -142,24 +142,24 @@ static void setMasterClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - ulReg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE); switch (divisor) { default: case 3: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_3); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_3); break; case 4: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_4); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_4); break; case 6: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_6); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_6); break; case 8: - ulReg = FIELD_SET(ulReg, CURRENT_GATE, MCLK, DIV_8); + reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_8); break; } - setCurrentGate(ulReg); + setCurrentGate(reg); } } -- cgit From 6e8aa4a1362f893ffd592a8d738d637d01d57261 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:27 +0200 Subject: staging: sm750fb: change definition of CURRENT_GATE multi-bit fields Use more straight-forward definitions for multi-bit fields of CURRENT_GATE register and use open-coded implementation for register manipulation. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 20 +++++++++---------- drivers/staging/sm750fb/ddk750_reg.h | 36 +++++++++++++++++------------------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 37c52a3f2d81..1cf9d9a189e0 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -95,20 +95,20 @@ static void setMemoryClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - reg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_M2XCLK_MASK; switch (divisor) { default: case 1: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_1); + reg |= CURRENT_GATE_M2XCLK_DIV_1; break; case 2: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_2); + reg |= CURRENT_GATE_M2XCLK_DIV_2; break; case 3: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_3); + reg |= CURRENT_GATE_M2XCLK_DIV_3; break; case 4: - reg = FIELD_SET(reg, CURRENT_GATE, M2XCLK, DIV_4); + reg |= CURRENT_GATE_M2XCLK_DIV_4; break; } @@ -142,20 +142,20 @@ static void setMasterClock(unsigned int frequency) divisor = roundedDiv(get_mxclk_freq(), frequency); /* Set the corresponding divisor in the register. */ - reg = PEEK32(CURRENT_GATE); + reg = PEEK32(CURRENT_GATE) & ~CURRENT_GATE_MCLK_MASK; switch (divisor) { default: case 3: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_3); + reg |= CURRENT_GATE_MCLK_DIV_3; break; case 4: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_4); + reg |= CURRENT_GATE_MCLK_DIV_4; break; case 6: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_6); + reg |= CURRENT_GATE_MCLK_DIV_6; break; case 8: - reg = FIELD_SET(reg, CURRENT_GATE, MCLK, DIV_8); + reg |= CURRENT_GATE_MCLK_DIV_8; break; } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index e3ca8326f96f..b4149cadc07d 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -391,29 +391,29 @@ #define INT_MASK_VGA_VSYNC_ENABLE 1 #define CURRENT_GATE 0x000040 -#define CURRENT_GATE_MCLK 15:14 +#define CURRENT_GATE_MCLK_MASK (0x3 << 14) #ifdef VALIDATION_CHIP - #define CURRENT_GATE_MCLK_112MHZ 0 - #define CURRENT_GATE_MCLK_84MHZ 1 - #define CURRENT_GATE_MCLK_56MHZ 2 - #define CURRENT_GATE_MCLK_42MHZ 3 + #define CURRENT_GATE_MCLK_112MHZ (0x0 << 14) + #define CURRENT_GATE_MCLK_84MHZ (0x1 << 14) + #define CURRENT_GATE_MCLK_56MHZ (0x2 << 14) + #define CURRENT_GATE_MCLK_42MHZ (0x3 << 14) #else - #define CURRENT_GATE_MCLK_DIV_3 0 - #define CURRENT_GATE_MCLK_DIV_4 1 - #define CURRENT_GATE_MCLK_DIV_6 2 - #define CURRENT_GATE_MCLK_DIV_8 3 + #define CURRENT_GATE_MCLK_DIV_3 (0x0 << 14) + #define CURRENT_GATE_MCLK_DIV_4 (0x1 << 14) + #define CURRENT_GATE_MCLK_DIV_6 (0x2 << 14) + #define CURRENT_GATE_MCLK_DIV_8 (0x3 << 14) #endif -#define CURRENT_GATE_M2XCLK 13:12 +#define CURRENT_GATE_M2XCLK_MASK (0x3 << 12) #ifdef VALIDATION_CHIP - #define CURRENT_GATE_M2XCLK_336MHZ 0 - #define CURRENT_GATE_M2XCLK_168MHZ 1 - #define CURRENT_GATE_M2XCLK_112MHZ 2 - #define CURRENT_GATE_M2XCLK_84MHZ 3 + #define CURRENT_GATE_M2XCLK_336MHZ (0x0 << 12) + #define CURRENT_GATE_M2XCLK_168MHZ (0x1 << 12) + #define CURRENT_GATE_M2XCLK_112MHZ (0x2 << 12) + #define CURRENT_GATE_M2XCLK_84MHZ (0x3 << 12) #else - #define CURRENT_GATE_M2XCLK_DIV_1 0 - #define CURRENT_GATE_M2XCLK_DIV_2 1 - #define CURRENT_GATE_M2XCLK_DIV_3 2 - #define CURRENT_GATE_M2XCLK_DIV_4 3 + #define CURRENT_GATE_M2XCLK_DIV_1 (0x0 << 12) + #define CURRENT_GATE_M2XCLK_DIV_2 (0x1 << 12) + #define CURRENT_GATE_M2XCLK_DIV_3 (0x2 << 12) + #define CURRENT_GATE_M2XCLK_DIV_4 (0x3 << 12) #endif #define CURRENT_GATE_VGA BIT(10) #define CURRENT_GATE_PWM BIT(9) -- cgit From 05e9d9ea4474a082b5abe753bab72d43aaf0592d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:28 +0200 Subject: staging: sm750fb: use BIT macro for MODE0_GATE single-bit fields Replace complex definition of MODE0_GATE register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 44 +++++++++-------------------------- 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 1cf9d9a189e0..a9a8884bbcfd 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -174,7 +174,7 @@ unsigned int ddk750_getVMSize(void) /* for 750,always use power mode0*/ reg = PEEK32(MODE0_GATE); - reg = FIELD_SET(reg, MODE0_GATE, GPIO, ON); + reg |= MODE0_GATE_GPIO; POKE32(MODE0_GATE, reg); /* get frame buffer size from GPIO */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index b4149cadc07d..70b1567fba23 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -438,39 +438,17 @@ #define MODE0_GATE_M2XCLK_168MHZ 1 #define MODE0_GATE_M2XCLK_112MHZ 2 #define MODE0_GATE_M2XCLK_84MHZ 3 -#define MODE0_GATE_VGA 10:10 -#define MODE0_GATE_VGA_OFF 0 -#define MODE0_GATE_VGA_ON 1 -#define MODE0_GATE_PWM 9:9 -#define MODE0_GATE_PWM_OFF 0 -#define MODE0_GATE_PWM_ON 1 -#define MODE0_GATE_I2C 8:8 -#define MODE0_GATE_I2C_OFF 0 -#define MODE0_GATE_I2C_ON 1 -#define MODE0_GATE_SSP 7:7 -#define MODE0_GATE_SSP_OFF 0 -#define MODE0_GATE_SSP_ON 1 -#define MODE0_GATE_GPIO 6:6 -#define MODE0_GATE_GPIO_OFF 0 -#define MODE0_GATE_GPIO_ON 1 -#define MODE0_GATE_ZVPORT 5:5 -#define MODE0_GATE_ZVPORT_OFF 0 -#define MODE0_GATE_ZVPORT_ON 1 -#define MODE0_GATE_CSC 4:4 -#define MODE0_GATE_CSC_OFF 0 -#define MODE0_GATE_CSC_ON 1 -#define MODE0_GATE_DE 3:3 -#define MODE0_GATE_DE_OFF 0 -#define MODE0_GATE_DE_ON 1 -#define MODE0_GATE_DISPLAY 2:2 -#define MODE0_GATE_DISPLAY_OFF 0 -#define MODE0_GATE_DISPLAY_ON 1 -#define MODE0_GATE_LOCALMEM 1:1 -#define MODE0_GATE_LOCALMEM_OFF 0 -#define MODE0_GATE_LOCALMEM_ON 1 -#define MODE0_GATE_DMA 0:0 -#define MODE0_GATE_DMA_OFF 0 -#define MODE0_GATE_DMA_ON 1 +#define MODE0_GATE_VGA BIT(10) +#define MODE0_GATE_PWM BIT(9) +#define MODE0_GATE_I2C BIT(8) +#define MODE0_GATE_SSP BIT(7) +#define MODE0_GATE_GPIO BIT(6) +#define MODE0_GATE_ZVPORT BIT(5) +#define MODE0_GATE_CSC BIT(4) +#define MODE0_GATE_DE BIT(3) +#define MODE0_GATE_DISPLAY BIT(2) +#define MODE0_GATE_LOCALMEM BIT(1) +#define MODE0_GATE_DMA BIT(0) #define MODE1_GATE 0x000048 #define MODE1_GATE_MCLK 15:14 -- cgit From a941245109ff133f715af9a9b9a55be09e89dda1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:29 +0200 Subject: staging: sm750fb: change definition of MODE0_GATE multi-bit fields Use more straight-forward definitions for multi-bit fields of MODE0_GATE register. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 70b1567fba23..d97859a0fa7b 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -428,16 +428,16 @@ #define CURRENT_GATE_DMA BIT(0) #define MODE0_GATE 0x000044 -#define MODE0_GATE_MCLK 15:14 -#define MODE0_GATE_MCLK_112MHZ 0 -#define MODE0_GATE_MCLK_84MHZ 1 -#define MODE0_GATE_MCLK_56MHZ 2 -#define MODE0_GATE_MCLK_42MHZ 3 -#define MODE0_GATE_M2XCLK 13:12 -#define MODE0_GATE_M2XCLK_336MHZ 0 -#define MODE0_GATE_M2XCLK_168MHZ 1 -#define MODE0_GATE_M2XCLK_112MHZ 2 -#define MODE0_GATE_M2XCLK_84MHZ 3 +#define MODE0_GATE_MCLK_MASK (0x3 << 14) +#define MODE0_GATE_MCLK_112MHZ (0x0 << 14) +#define MODE0_GATE_MCLK_84MHZ (0x1 << 14) +#define MODE0_GATE_MCLK_56MHZ (0x2 << 14) +#define MODE0_GATE_MCLK_42MHZ (0x3 << 14) +#define MODE0_GATE_M2XCLK_MASK (0x3 << 12) +#define MODE0_GATE_M2XCLK_336MHZ (0x0 << 12) +#define MODE0_GATE_M2XCLK_168MHZ (0x1 << 12) +#define MODE0_GATE_M2XCLK_112MHZ (0x2 << 12) +#define MODE0_GATE_M2XCLK_84MHZ (0x3 << 12) #define MODE0_GATE_VGA BIT(10) #define MODE0_GATE_PWM BIT(9) #define MODE0_GATE_I2C BIT(8) -- cgit From 776980cf0f8cd3c8e5863ec92bccb8e670e3efa1 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:30 +0200 Subject: staging: sm750fb: use BIT macro for POWER_MODE_CTRL single-bit fields Replace complex definition of POWER_MODE_CTRL register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 10 ++++------ drivers/staging/sm750fb/ddk750_reg.h | 12 +++--------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 417702548f0f..4959482cbeb5 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -60,17 +60,15 @@ void setPowerMode(unsigned int powerMode) /* Set up other fields in Power Control Register */ if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) { - control_value = + control_value &= ~POWER_MODE_CTRL_OSC_INPUT; #ifdef VALIDATION_CHIP - FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, OFF) | + control_value &= ~POWER_MODE_CTRL_336CLK; #endif - FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, OFF); } else { - control_value = + control_value |= POWER_MODE_CTRL_OSC_INPUT; #ifdef VALIDATION_CHIP - FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, ON) | + control_value |= POWER_MODE_CTRL_336CLK; #endif - FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, ON); } /* Program new power mode. */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index d97859a0fa7b..bc49b44c611d 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -497,16 +497,10 @@ #define POWER_MODE_CTRL 0x00004C #ifdef VALIDATION_CHIP - #define POWER_MODE_CTRL_336CLK 4:4 - #define POWER_MODE_CTRL_336CLK_OFF 0 - #define POWER_MODE_CTRL_336CLK_ON 1 + #define POWER_MODE_CTRL_336CLK BIT(4) #endif -#define POWER_MODE_CTRL_OSC_INPUT 3:3 -#define POWER_MODE_CTRL_OSC_INPUT_OFF 0 -#define POWER_MODE_CTRL_OSC_INPUT_ON 1 -#define POWER_MODE_CTRL_ACPI 2:2 -#define POWER_MODE_CTRL_ACPI_OFF 0 -#define POWER_MODE_CTRL_ACPI_ON 1 +#define POWER_MODE_CTRL_OSC_INPUT BIT(3) +#define POWER_MODE_CTRL_ACPI BIT(2) #define POWER_MODE_CTRL_MODE 1:0 #define POWER_MODE_CTRL_MODE_MODE0 0 #define POWER_MODE_CTRL_MODE_MODE1 1 -- cgit From f41b17fc3f124729e0778f64ba2039f4b71b0fc6 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Jan 2016 20:04:31 +0200 Subject: staging: sm750fb: change definition of POWER_MODE_CTRL multi-bit field Use more straight-forward definitions for multi-bit field of POWER_MODE_CTRL register and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 13 +++++-------- drivers/staging/sm750fb/ddk750_reg.h | 8 ++++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index 4959482cbeb5..c85dfc509b04 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -21,7 +21,7 @@ static unsigned int getPowerMode(void) { if (getChipType() == SM750LE) return 0; - return FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE); + return PEEK32(POWER_MODE_CTRL) & POWER_MODE_CTRL_MODE_MASK; } @@ -33,25 +33,22 @@ void setPowerMode(unsigned int powerMode) { unsigned int control_value = 0; - control_value = PEEK32(POWER_MODE_CTRL); + control_value = PEEK32(POWER_MODE_CTRL) & ~POWER_MODE_CTRL_MODE_MASK; if (getChipType() == SM750LE) return; switch (powerMode) { case POWER_MODE_CTRL_MODE_MODE0: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, - MODE0); + control_value |= POWER_MODE_CTRL_MODE_MODE0; break; case POWER_MODE_CTRL_MODE_MODE1: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, - MODE1); + control_value |= POWER_MODE_CTRL_MODE_MODE1; break; case POWER_MODE_CTRL_MODE_SLEEP: - control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, - SLEEP); + control_value |= POWER_MODE_CTRL_MODE_SLEEP; break; default: diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index bc49b44c611d..a90b56f55f1e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -501,10 +501,10 @@ #endif #define POWER_MODE_CTRL_OSC_INPUT BIT(3) #define POWER_MODE_CTRL_ACPI BIT(2) -#define POWER_MODE_CTRL_MODE 1:0 -#define POWER_MODE_CTRL_MODE_MODE0 0 -#define POWER_MODE_CTRL_MODE_MODE1 1 -#define POWER_MODE_CTRL_MODE_SLEEP 2 +#define POWER_MODE_CTRL_MODE_MASK (0x3 << 0) +#define POWER_MODE_CTRL_MODE_MODE0 (0x0 << 0) +#define POWER_MODE_CTRL_MODE_MODE1 (0x1 << 0) +#define POWER_MODE_CTRL_MODE_SLEEP (0x2 << 0) #define PCI_MASTER_BASE 0x000050 #define PCI_MASTER_BASE_ADDRESS 7:0 -- cgit From 04c73f28967423f2b68f80df1149cf5d2e85c1f5 Mon Sep 17 00:00:00 2001 From: Othmar Pasteka Date: Sun, 8 Nov 2015 11:58:51 +0100 Subject: staging: sm750fb: fix style for if clause Fix for checkpatch.pl complaints: ERROR: that open brace { should be on the previous line CHECK: spaces preferred around that '+' (ctx:VxV) Signed-off-by: Othmar Pasteka Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_cursor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c index 3b7ce9275f51..0a41585535a6 100644 --- a/drivers/staging/sm750fb/sm750_cursor.c +++ b/drivers/staging/sm750fb/sm750_cursor.c @@ -143,8 +143,7 @@ void hw_cursor_setData(struct lynx_cursor *cursor, iowrite16(data, pbuffer); /* assume pitch is 1,2,4,8,...*/ - if ((i+1) % pitch == 0) - { + if ((i + 1) % pitch == 0) { /* need a return */ pstart += offset; pbuffer = pstart; -- cgit From fe7185908a4e981ae484043806a4f24d6cf09e91 Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Wed, 25 Nov 2015 22:56:30 +0100 Subject: drivers:staging:sm750fb Fix all space preferred around messages This fixes all messages from checkpatch.pl about space preferred Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_mode.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index fa35926680ab..0fd34fa93a41 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -30,8 +30,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0)); POKE32(CRT_AUTO_CENTERING_BR, - FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y-1) - | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x-1)); + FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, BOTTOM, y - 1) + | FIELD_VALUE(0, CRT_AUTO_CENTERING_BR, RIGHT, x - 1)); /* Assume common fields in dispControl have been properly set before calling this function. @@ -101,9 +101,9 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)| - FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)| - FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE)| + ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | + FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | + FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE); @@ -116,7 +116,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) & FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING) & FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE); - POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg); + POKE32(CRT_DISPLAY_CTRL, ulTmpValue | ulReg); } } else if (pll->clockType == PRIMARY_PLL) { @@ -140,15 +140,15 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity)| - FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity)| - FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity)| - FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE)| + ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | + FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | + FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity) | + FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE); ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE)| + FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) @@ -167,13 +167,13 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) * next vertical sync to turn on/off the plane. */ - POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg); + POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg); - while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) { + while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue | ulReg)) { cnt++; if (cnt > 1000) break; - POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg); + POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg); } } else { ret = -1; -- cgit From fbb8c963573926bceb5c59e2a7d74e5ce7669e78 Mon Sep 17 00:00:00 2001 From: Matej Vasek Date: Mon, 25 Jan 2016 16:02:33 +0100 Subject: staging: sm750fb, fix typos The code contained typos like "structur", "fointers", etc. Fix that. No code change, only comments. Signed-off-by: Matej Vasek Cc: Sudip Mukherjee Cc: Teddy Wang Cc: Greg Kroah-Hartman Cc: Cc: Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_hwi2c.c | 4 ++-- drivers/staging/sm750fb/ddk750_mode.c | 2 +- drivers/staging/sm750fb/ddk750_sii164.h | 5 ++++- drivers/staging/sm750fb/sm750.c | 2 +- drivers/staging/sm750fb/sm750.h | 2 +- drivers/staging/sm750fb/sm750_accel.c | 4 ++-- drivers/staging/sm750fb/sm750_accel.h | 2 +- drivers/staging/sm750fb/sm750_hw.c | 2 +- 8 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index b824681e55a7..40253bd8cf2a 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -127,7 +127,7 @@ static unsigned int hw_i2c_write_data( if (hw_i2c_wait_tx_done() != 0) break; - /* Substract length */ + /* Subtract length */ length -= (count + 1); /* Total byte written */ @@ -194,7 +194,7 @@ static unsigned int hw_i2c_read_data( for (i = 0; i <= count; i++) *buf++ = PEEK32(I2C_DATA0 + i); - /* Substract length by 16 */ + /* Subtract length by 16 */ length -= (count + 1); /* Number of bytes read. */ diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 0fd34fa93a41..d0e3935654ff 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -42,7 +42,7 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK); /* Set bit 29:27 of display control register for the right clock */ - /* Note that SM750LE only need to supported 7 resoluitons. */ + /* Note that SM750LE only need to supported 7 resolutions. */ if (x == 800 && y == 600) dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41); else if (x == 1024 && y == 768) diff --git a/drivers/staging/sm750fb/ddk750_sii164.h b/drivers/staging/sm750fb/ddk750_sii164.h index f2610c90eeb4..664ad089f753 100644 --- a/drivers/staging/sm750fb/ddk750_sii164.h +++ b/drivers/staging/sm750fb/ddk750_sii164.h @@ -39,7 +39,10 @@ unsigned char sii164IsConnected(void); unsigned char sii164CheckInterrupt(void); void sii164ClearInterrupt(void); #endif -/* below register definination is used for Silicon Image SiI164 DVI controller chip */ +/* + * below register definition is used for + * Silicon Image SiI164 DVI controller chip + */ /* * Vendor ID registers */ diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 2ae2a522136f..c9d4871cd62d 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -319,7 +319,7 @@ static int lynxfb_ops_set_par(struct fb_info *info) var = &info->var; fix = &info->fix; - /* fix structur is not so FIX ... */ + /* fix structure is not so FIX ... */ line_length = var->xres_virtual * var->bits_per_pixel / 8; line_length = ALIGN(line_length, crtc->line_pad); fix->line_length = line_length; diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h index fddffac6930f..8e70ce0d6da4 100644 --- a/drivers/staging/sm750fb/sm750.h +++ b/drivers/staging/sm750fb/sm750.h @@ -53,7 +53,7 @@ struct lynx_accel { /* base virtual address of de data port */ volatile unsigned char __iomem *dpPortBase; - /* function fointers */ + /* function pointers */ void (*de_init)(struct lynx_accel *); int (*de_wait)(void);/* see if hardware ready to work */ diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index 43e59725920c..e150680a8cd1 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -53,7 +53,7 @@ void hw_de_init(struct lynx_accel *accel) FIELD_CLEAR(DE_STRETCH_FORMAT, ADDRESSING)& FIELD_CLEAR(DE_STRETCH_FORMAT, SOURCE_HEIGHT); - /* DE_STRETCH bpp format need be initilized in setMode routine */ + /* DE_STRETCH bpp format need be initialized in setMode routine */ write_dpr(accel, DE_STRETCH_FORMAT, (read_dpr(accel, DE_STRETCH_FORMAT) & clr) | reg); /* disable clipping and transparent */ @@ -305,7 +305,7 @@ int hw_imageblit(struct lynx_accel *accel, u32 dx, u32 dy, /* Starting coordinate of destination surface */ u32 width, - u32 height, /* width and height of rectange in pixel value */ + u32 height, /* width and height of rectangle in pixel value */ u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */ u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */ u32 rop2) /* ROP value */ diff --git a/drivers/staging/sm750fb/sm750_accel.h b/drivers/staging/sm750fb/sm750_accel.h index f252e47d5ee9..1ec66d28f456 100644 --- a/drivers/staging/sm750fb/sm750_accel.h +++ b/drivers/staging/sm750fb/sm750_accel.h @@ -268,7 +268,7 @@ int hw_imageblit(struct lynx_accel *accel, u32 dx, u32 dy, /* Starting coordinate of destination surface */ u32 width, - u32 height, /* width and height of rectange in pixel value */ + u32 height, /* width and height of rectangle in pixel value */ u32 fColor, /* Foreground color (corresponding to a 1 in the monochrome data */ u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */ u32 rop2); diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index b33ec076f3f5..c0c2f1c4de82 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -142,7 +142,7 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) break; } } else { - /* for 750LE ,no DVI chip initilization makes Monitor no signal */ + /* for 750LE ,no DVI chip initialization makes Monitor no signal */ /* Set up GPIO for software I2C to program DVI chip in the Xilinx SP605 board, in order to have video signal. */ -- cgit From 8891bcac17da0a7233a46266c57cf9934d39f919 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:00 +0100 Subject: staging: rtl8188eu: add spaces around binary '*' Fix checkpatch issue: CHECK: spaces preferred around that '*' (ctx:VxV) Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_efuse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 2320fb11af24..169bb693b75f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -500,8 +500,8 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (offset > max_section) return false; - memset((void *)data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); - memset((void *)tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); + memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ /* Skip dummy parts to prevent unexpected data read from Efuse. */ -- cgit From d0beccb04e9670d97ef91c1141bfad8f41801183 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:01 +0100 Subject: staging: rtl8188eu: don't cast to void* when calling memset() The first argument to memset() is (void *), the explicit typecasts are not needed. They just make code less readable. Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ap.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_efuse.c | 8 ++++---- drivers/staging/rtl8188eu/core/rtw_security.c | 28 +++++++++++++-------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index e5d29fe9d446..79d326ae18fe 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -569,7 +569,7 @@ static void update_bmc_sta(struct adapter *padapter) psta->ieee8021x_blocked = 0; - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); + memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats)); /* prepare for add_RATid */ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->SupportedRates); @@ -692,7 +692,7 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) /* todo: init other variables */ - memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); + memset(&psta->sta_stats, 0, sizeof(struct stainfo_stats)); spin_lock_bh(&psta->lock); psta->state |= _FW_LINKED; diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c index 169bb693b75f..fd8cf472e8dc 100644 --- a/drivers/staging/rtl8188eu/core/rtw_efuse.c +++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c @@ -394,7 +394,7 @@ u8 Efuse_WordEnableDataWrite(struct adapter *pAdapter, u16 efuse_addr, u8 word_e u8 badworden = 0x0F; u8 tmpdata[8]; - memset((void *)tmpdata, 0xff, PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, PGPKT_DATA_SIZE); if (!(word_en & BIT(0))) { tmpaddr = start_addr; @@ -500,8 +500,8 @@ int Efuse_PgPacketRead(struct adapter *pAdapter, u8 offset, u8 *data) if (offset > max_section) return false; - memset((void *)data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); - memset((void *)tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset(data, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, sizeof(u8) * PGPKT_DATA_SIZE); /* Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */ /* Skip dummy parts to prevent unexpected data read from Efuse. */ @@ -572,7 +572,7 @@ static bool hal_EfuseFixHeaderProcess(struct adapter *pAdapter, u8 efuseType, st u16 efuse_addr = *pAddr; u32 PgWriteSuccess = 0; - memset((void *)originaldata, 0xff, 8); + memset(originaldata, 0xff, 8); if (Efuse_PgPacketRead(pAdapter, pFixPkt->offset, originaldata)) { /* check if data exist */ diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c index 22839d57dc8c..b781ccf45bc0 100644 --- a/drivers/staging/rtl8188eu/core/rtw_security.c +++ b/drivers/staging/rtl8188eu/core/rtw_security.c @@ -1081,13 +1081,13 @@ static int aes_cipher(u8 *key, uint hdrlen, u8 *pframe, uint plen) frsubtype >>= 4; - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); + memset(mic_iv, 0, 16); + memset(mic_header1, 0, 16); + memset(mic_header2, 0, 16); + memset(ctr_preload, 0, 16); + memset(chain_buffer, 0, 16); + memset(aes_out, 0, 16); + memset(padded_buffer, 0, 16); if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) a4_exists = 0; @@ -1279,13 +1279,13 @@ static int aes_decipher(u8 *key, uint hdrlen, uint frsubtype = GetFrameSubType(pframe); frsubtype >>= 4; - memset((void *)mic_iv, 0, 16); - memset((void *)mic_header1, 0, 16); - memset((void *)mic_header2, 0, 16); - memset((void *)ctr_preload, 0, 16); - memset((void *)chain_buffer, 0, 16); - memset((void *)aes_out, 0, 16); - memset((void *)padded_buffer, 0, 16); + memset(mic_iv, 0, 16); + memset(mic_header1, 0, 16); + memset(mic_header2, 0, 16); + memset(ctr_preload, 0, 16); + memset(chain_buffer, 0, 16); + memset(aes_out, 0, 16); + memset(padded_buffer, 0, 16); /* start to decrypt the payload */ -- cgit From 329862549c0f2b8df352b3f23fef0fe1760ffbc5 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:02 +0100 Subject: staging: rtl8188eu: rtw_mlme_ext.c: remove commented code This line is connented since the initial import in commit 7b464c9fa5cc ("staging: r8188eu: Add files for new driver - part 4") and there's no comment stating how it could ever be useful. Signed-off-by: Luca Ceresoli Cc: Larry Finger 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 3eca6874b6df..09092bdcf7e4 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -1673,7 +1673,6 @@ static void issue_action_BA(struct adapter *padapter, unsigned char *raddr, fctrl = &(pwlanhdr->frame_ctl); *(fctrl) = 0; - /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); memcpy(pwlanhdr->addr3, pnetwork->MacAddress, ETH_ALEN); -- cgit From f0f17bed9a06edb82714ed2400aa511e66290ee9 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:03 +0100 Subject: staging: rtl8188eu: remove useless variable rtw_AcceptAddbaReq rtw_AcceptAddbaReq is a static variable, it is set once and never modified. It is referenced only once, to assign its value to a member of struct registry_priv with practically the same name. Get rid of the variable, and move the meaningful part of the comment near the declaration of the relevant field of struct registry_priv. Raises a new checkpatch issue, which is fixed in a later commit: CHECK: Avoid CamelCase: Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/drv_types.h | 2 +- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 0729bd40b02a..65e82aa04119 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -110,7 +110,7 @@ struct registry_priv { u8 wifi_spec;/* !turbo_mode */ u8 channel_plan; - bool bAcceptAddbaReq; + bool bAcceptAddbaReq; /* true = accept AP's Add BA req */ u8 antdiv_cfg; u8 antdiv_type; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 9201b94d017c..90b5ea233e84 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -101,8 +101,6 @@ static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */ static int rtw_low_power; static int rtw_wifi_spec; static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX; -/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */ -static int rtw_AcceptAddbaReq = true; static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */ @@ -593,7 +591,7 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->low_power = (u8)rtw_low_power; registry_par->wifi_spec = (u8)rtw_wifi_spec; registry_par->channel_plan = (u8)rtw_channel_plan; - registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq; + registry_par->bAcceptAddbaReq = true; registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; registry_par->antdiv_type = (u8)rtw_antdiv_type; registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; -- cgit From d6c6ad96119d8bcb3020ef33ec99179b74423cea Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:04 +0100 Subject: staging: rtl8188eu: rename camelcase bAcceptAddbaReq There is such a field both in struct mlme_ext_info and in struct registry_priv. Rename both. Also fix checkpatch issue in the lines touched: WARNING: line over 80 characters Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 4 ++-- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 3 ++- drivers/staging/rtl8188eu/include/drv_types.h | 2 +- drivers/staging/rtl8188eu/include/rtw_mlme_ext.h | 2 +- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 09092bdcf7e4..31faa266bf6b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3739,7 +3739,7 @@ static unsigned int OnAction_back(struct adapter *padapter, memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); - if (pmlmeinfo->bAcceptAddbaReq) + if (pmlmeinfo->accept_addba_req) issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0); else issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ @@ -4149,7 +4149,7 @@ int init_mlme_ext_priv(struct adapter *padapter) pmlmeext->padapter = padapter; init_mlme_ext_priv_value(padapter); - pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq; + pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; init_mlme_ext_timer(padapter); diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 59b443255a90..7d85ad1d7e02 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1579,7 +1579,8 @@ void process_addba_req(struct adapter *padapter, u8 *paddba_req, u8 *addr) tid = (param>>2)&0x0f; preorder_ctrl = &psta->recvreorder_ctrl[tid]; preorder_ctrl->indicate_seq = 0xffff; - preorder_ctrl->enable = (pmlmeinfo->bAcceptAddbaReq) ? true : false; + preorder_ctrl->enable = (pmlmeinfo->accept_addba_req) ? true + : false; } } diff --git a/drivers/staging/rtl8188eu/include/drv_types.h b/drivers/staging/rtl8188eu/include/drv_types.h index 65e82aa04119..aeaf5f7e1f01 100644 --- a/drivers/staging/rtl8188eu/include/drv_types.h +++ b/drivers/staging/rtl8188eu/include/drv_types.h @@ -110,7 +110,7 @@ struct registry_priv { u8 wifi_spec;/* !turbo_mode */ u8 channel_plan; - bool bAcceptAddbaReq; /* true = accept AP's Add BA req */ + bool accept_addba_req; /* true = accept AP's Add BA req */ u8 antdiv_cfg; u8 antdiv_type; diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h index 9093a5f94d32..44711332b90c 100644 --- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h @@ -348,7 +348,7 @@ struct mlme_ext_info { u8 candidate_tid_bitmap; u8 dialogToken; /* Accept ADDBA Request */ - bool bAcceptAddbaReq; + bool accept_addba_req; u8 bwmode_updated; u8 hidden_ssid_mode; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 90b5ea233e84..3b25acf882a3 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -591,7 +591,7 @@ static void loadparam(struct adapter *padapter, struct net_device *pnetdev) registry_par->low_power = (u8)rtw_low_power; registry_par->wifi_spec = (u8)rtw_wifi_spec; registry_par->channel_plan = (u8)rtw_channel_plan; - registry_par->bAcceptAddbaReq = true; + registry_par->accept_addba_req = true; registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg; registry_par->antdiv_type = (u8)rtw_antdiv_type; registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode; -- cgit From 35ad45a1992d43920968718f606a1ce3d9a86074 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 2 Dec 2015 22:54:05 +0100 Subject: staging: rtl8188eu: rtw_mlme_ext.c: simplify call to issue_action_BA() Using the ternary operator allows to more concisely write the same code, and to stay within 80 characters without even increasing the number of lines. Signed-off-by: Luca Ceresoli Cc: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index 31faa266bf6b..e6020265d6de 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3739,10 +3739,10 @@ static unsigned int OnAction_back(struct adapter *padapter, memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); - if (pmlmeinfo->accept_addba_req) - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0); - else - issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ + /* 37 = reject ADDBA Req */ + issue_action_BA(padapter, addr, + RTW_WLAN_ACTION_ADDBA_RESP, + pmlmeinfo->accept_addba_req ? 0 : 37); break; case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ status = get_unaligned_le16(&frame_body[3]); -- cgit From b0800a4bd9f366ebac393fe3982f0140ca120487 Mon Sep 17 00:00:00 2001 From: Alexey Tulia Date: Sat, 21 Nov 2015 13:06:37 +0300 Subject: staging: rtl8188eu: remove an extra space drivers/staging/rtl8188eu/core/rtw_wlan_util.c:1377 check_assoc_AP() warn: inconsistent indenting Signed-off-by: Alexey Tulia Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_wlan_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c index 7d85ad1d7e02..83096696cd5b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c @@ -1374,7 +1374,7 @@ unsigned char check_assoc_AP(u8 *pframe, uint len) epigram_vendor_flag = 1; if (ralink_vendor_flag) { DBG_88E("link to Tenda W311R AP\n"); - return HT_IOT_PEER_TENDA; + return HT_IOT_PEER_TENDA; } else { DBG_88E("Capture EPIGRAM_OUI\n"); } -- cgit From 5fa0e06d7ae2a0f62886bfe65273638951ee796a Mon Sep 17 00:00:00 2001 From: Chris Elliott Date: Mon, 7 Dec 2015 22:02:27 +0000 Subject: Staging: rtl8188eu: core: rtw_debug: fixed a parentheses coding style issue Removed unnecessary parentheses. Signed-off-by: Chris Elliott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_debug.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c index 2c4afb80fc64..93e898d598fe 100644 --- a/drivers/staging/rtl8188eu/core/rtw_debug.c +++ b/drivers/staging/rtl8188eu/core/rtw_debug.c @@ -149,7 +149,7 @@ int proc_get_fwstate(char *page, char **start, { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int len = 0; @@ -184,7 +184,7 @@ int proc_get_mlmext_state(char *page, char **start, struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); + struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; int len = 0; @@ -200,7 +200,7 @@ int proc_get_qos_option(char *page, char **start, { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int len = 0; @@ -216,7 +216,7 @@ int proc_get_ht_option(char *page, char **start, { struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int len = 0; @@ -247,9 +247,9 @@ int proc_get_ap_info(char *page, char **start, struct sta_info *psta; struct net_device *dev = data; struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); - struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct wlan_network *cur_network = &(pmlmepriv->cur_network); + struct wlan_network *cur_network = &pmlmepriv->cur_network; struct sta_priv *pstapriv = &padapter->stapriv; int len = 0; @@ -851,7 +851,7 @@ int proc_get_all_sta_info(char *page, char **start, spin_lock_bh(&pstapriv->sta_hash_lock); for (i = 0; i < NUM_STA; i++) { - phead = &(pstapriv->sta_hash[i]); + phead = &pstapriv->sta_hash[i]; plist = phead->next; while (phead != plist) { -- cgit From 6d7b2801446b5e6e52606eac715db9a337fb899e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 17:43:53 +0200 Subject: staging: rtl8188eu: provide an absolute path to include folder Otherwise compiler will complain as follows CC [M] drivers/staging/rtl8188eu/core/rtw_ap.o cc1: warning: drivers/staging/rtl8188eu/include: No such file or directory [-Wmissing-include-dirs] Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile index ed723585b502..29b9834870fd 100644 --- a/drivers/staging/rtl8188eu/Makefile +++ b/drivers/staging/rtl8188eu/Makefile @@ -53,4 +53,4 @@ r8188eu-y := \ obj-$(CONFIG_R8188EU) := r8188eu.o -ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/include +ccflags-y += -D__CHECK_ENDIAN__ -I$(srctree)/$(src)/include -- cgit From fb27e19c08f89426112dad291412bf89c287a68c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 17:43:54 +0200 Subject: staging: rtl8188eu: replace open-coded print_hex_dump() No need to reinvent a wheel, i.e. print_hex_dump(). Replace an open-coded variant by generic kernel helper. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 39 +++++++++++++------------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 110b8c0b6cd7..3f03999b4d22 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1274,32 +1274,25 @@ static int validate_recv_frame(struct adapter *adapter, /* Dump rx packets */ rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt)); if (bDumpRxPkt == 1) {/* dump all rx packets */ - int i; - DBG_88E("#############################\n"); - - for (i = 0; i < 64; i += 8) - DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), - *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); - DBG_88E("#############################\n"); + if (_drv_err_ <= GlobalDebugLevel) { + pr_info(DRIVER_PREFIX "#############################\n"); + print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, + 16, 1, ptr, 64, false); + pr_info(DRIVER_PREFIX "#############################\n"); + } } else if (bDumpRxPkt == 2) { - if (type == WIFI_MGT_TYPE) { - int i; - DBG_88E("#############################\n"); - - for (i = 0; i < 64; i += 8) - DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), - *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); - DBG_88E("#############################\n"); + if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_MGT_TYPE)) { + pr_info(DRIVER_PREFIX "#############################\n"); + print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, + 16, 1, ptr, 64, false); + pr_info(DRIVER_PREFIX "#############################\n"); } } else if (bDumpRxPkt == 3) { - if (type == WIFI_DATA_TYPE) { - int i; - DBG_88E("#############################\n"); - - for (i = 0; i < 64; i += 8) - DBG_88E("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), - *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); - DBG_88E("#############################\n"); + if ((_drv_err_ <= GlobalDebugLevel) && (type == WIFI_DATA_TYPE)) { + pr_info(DRIVER_PREFIX "#############################\n"); + print_hex_dump(KERN_INFO, DRIVER_PREFIX, DUMP_PREFIX_NONE, + 16, 1, ptr, 64, false); + pr_info(DRIVER_PREFIX "#############################\n"); } } switch (type) { -- cgit From a67080ee826467cbcb9691418126607bb0d1e33e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 10 Dec 2015 17:43:55 +0200 Subject: staging: rtl8188eu: print OUI with %*ph There is no need to pass each byte as a parameter when printing values in hex format. We rather use %*ph specifier for that. Signed-off-by: Andy Shevchenko Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_ieee80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c index 742b29c590df..aa7f5711a147 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c @@ -935,8 +935,8 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, } break; default: - DBG_88E("unknown vendor specific information element ignored (vendor OUI %02x:%02x:%02x len=%lu)\n", - pos[0], pos[1], pos[2], (unsigned long)elen); + DBG_88E("unknown vendor specific information element ignored (vendor OUI %3phC len=%lu)\n", + pos, (unsigned long)elen); return -1; } return 0; -- cgit From b9f1c275b695ff9339cfd0c2ea841f53d4205611 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Mon, 1 Feb 2016 22:37:13 +0800 Subject: staging: rtl8188eu: use list_first_entry_or_null() Use list_first_entry_or_null() instead of list_empty() + container_of() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_cmd.c | 12 +--- drivers/staging/rtl8188eu/core/rtw_mlme.c | 19 +++---- drivers/staging/rtl8188eu/core/rtw_recv.c | 15 ++--- drivers/staging/rtl8188eu/core/rtw_sta_mgt.c | 23 +++----- drivers/staging/rtl8188eu/core/rtw_xmit.c | 84 ++++++++-------------------- 5 files changed, 48 insertions(+), 105 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 433b926ceae7..1de792905e82 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -69,23 +69,17 @@ exit: return _SUCCESS; } -struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue) +struct cmd_obj *rtw_dequeue_cmd(struct __queue *queue) { unsigned long irqL; struct cmd_obj *obj; - spin_lock_irqsave(&queue->lock, irqL); - if (list_empty(&(queue->queue))) { - obj = NULL; - } else { - obj = container_of((&queue->queue)->next, struct cmd_obj, list); + obj = list_first_entry_or_null(&queue->queue, struct cmd_obj, list); + if (obj) list_del_init(&obj->list); - } - spin_unlock_irqrestore(&queue->lock, irqL); - return obj; } diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c index abab854e6889..9c2e65904c0f 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c @@ -128,25 +128,22 @@ void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) } } -struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv)/* _queue *free_queue) */ +struct wlan_network *_rtw_alloc_network(struct mlme_priv *pmlmepriv) + /* _queue *free_queue) */ { - struct wlan_network *pnetwork; + struct wlan_network *pnetwork; struct __queue *free_queue = &pmlmepriv->free_bss_pool; - struct list_head *plist = NULL; spin_lock_bh(&free_queue->lock); - - if (list_empty(&free_queue->queue)) { - pnetwork = NULL; + pnetwork = list_first_entry_or_null(&free_queue->queue, + struct wlan_network, list); + if (!pnetwork) goto exit; - } - plist = free_queue->queue.next; - - pnetwork = container_of(plist, struct wlan_network, list); list_del_init(&pnetwork->list); - RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr=%p\n", plist)); + RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, + ("_rtw_alloc_network: ptr=%p\n", &pnetwork->list)); pnetwork->network_type = 0; pnetwork->fixed = false; pnetwork->last_scanned = jiffies; diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 3f03999b4d22..c81639cae1ea 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -127,22 +127,15 @@ void _rtw_free_recv_priv(struct recv_priv *precvpriv) struct recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue) { struct recv_frame *hdr; - struct list_head *plist, *phead; struct adapter *padapter; struct recv_priv *precvpriv; - if (list_empty(&pfree_recv_queue->queue)) { - hdr = NULL; - } else { - phead = get_list_head(pfree_recv_queue); - - plist = phead->next; - - hdr = container_of(plist, struct recv_frame, list); - + hdr = list_first_entry_or_null(&pfree_recv_queue->queue, + struct recv_frame, list); + if (hdr) { list_del_init(&hdr->list); padapter = hdr->adapter; - if (padapter != NULL) { + if (padapter) { precvpriv = &padapter->recvpriv; if (pfree_recv_queue == &precvpriv->free_recv_queue) precvpriv->free_recvframe_cnt--; diff --git a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c index 1beeac46bfe7..ce655b6d9a23 100644 --- a/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8188eu/core/rtw_sta_mgt.c @@ -179,9 +179,9 @@ u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) return _SUCCESS; } -struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) +struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) { - s32 index; + s32 index; struct list_head *phash_list; struct sta_info *psta; struct __queue *pfree_sta_queue; @@ -189,17 +189,15 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) int i = 0; u16 wRxSeqInitialValue = 0xffff; - pfree_sta_queue = &pstapriv->free_sta_queue; - spin_lock_bh(&(pfree_sta_queue->lock)); - - if (list_empty(&pfree_sta_queue->queue)) { + spin_lock_bh(&pfree_sta_queue->lock); + psta = list_first_entry_or_null(&pfree_sta_queue->queue, + struct sta_info, list); + if (!psta) { spin_unlock_bh(&pfree_sta_queue->lock); - psta = NULL; } else { - psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list); - list_del_init(&(psta->list)); + list_del_init(&psta->list); spin_unlock_bh(&pfree_sta_queue->lock); _rtw_init_stainfo(psta); memcpy(psta->hwaddr, hwaddr, ETH_ALEN); @@ -210,14 +208,11 @@ struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) psta = NULL; goto exit; } - phash_list = &(pstapriv->sta_hash[index]); - - spin_lock_bh(&(pstapriv->sta_hash_lock)); + phash_list = &pstapriv->sta_hash[index]; + spin_lock_bh(&pstapriv->sta_hash_lock); list_add_tail(&psta->hash_list, phash_list); - pstapriv->asoc_sta_count++; - spin_unlock_bh(&pstapriv->sta_hash_lock); /* Commented by Albert 2009/08/13 */ diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c index e778132b73dc..d5ce1e2a1658 100644 --- a/drivers/staging/rtl8188eu/core/rtw_xmit.c +++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c @@ -1216,40 +1216,24 @@ void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv) { unsigned long irql; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *plist, *phead; + struct xmit_buf *pxmitbuf; struct __queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - spin_lock_irqsave(&pfree_queue->lock, irql); - - if (list_empty(&pfree_queue->queue)) { - pxmitbuf = NULL; - } else { - phead = get_list_head(pfree_queue); - - plist = phead->next; - - pxmitbuf = container_of(plist, struct xmit_buf, list); - - list_del_init(&(pxmitbuf->list)); - } - - if (pxmitbuf != NULL) { + pxmitbuf = list_first_entry_or_null(&pfree_queue->queue, + struct xmit_buf, list); + if (pxmitbuf) { + list_del_init(&pxmitbuf->list); pxmitpriv->free_xmit_extbuf_cnt--; - pxmitbuf->priv_data = NULL; /* pxmitbuf->ext_tag = true; */ - if (pxmitbuf->sctx) { DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); } } - spin_unlock_irqrestore(&pfree_queue->lock, irql); - return pxmitbuf; } @@ -1278,28 +1262,16 @@ s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) { unsigned long irql; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *plist, *phead; + struct xmit_buf *pxmitbuf; struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - /* DBG_88E("+rtw_alloc_xmitbuf\n"); */ spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irql); - - if (list_empty(&pfree_xmitbuf_queue->queue)) { - pxmitbuf = NULL; - } else { - phead = get_list_head(pfree_xmitbuf_queue); - - plist = phead->next; - - pxmitbuf = container_of(plist, struct xmit_buf, list); - - list_del_init(&(pxmitbuf->list)); - } - - if (pxmitbuf != NULL) { + pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue, + struct xmit_buf, list); + if (pxmitbuf) { + list_del_init(&pxmitbuf->list); pxmitpriv->free_xmitbuf_cnt--; pxmitbuf->priv_data = NULL; if (pxmitbuf->sctx) { @@ -1309,7 +1281,6 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) } spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irql); - return pxmitbuf; } @@ -1355,38 +1326,33 @@ Must be very very cautious... */ -struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */ +struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) + /* _queue *pfree_xmit_queue) */ { /* Please remember to use all the osdep_service api, and lock/unlock or _enter/_exit critical to protect pfree_xmit_queue */ - - struct xmit_frame *pxframe = NULL; - struct list_head *plist, *phead; + struct xmit_frame *pxframe; struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - spin_lock_bh(&pfree_xmit_queue->lock); - - if (list_empty(&pfree_xmit_queue->queue)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe:%d\n", pxmitpriv->free_xmitframe_cnt)); - pxframe = NULL; + pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, + struct xmit_frame, list); + if (!pxframe) { + RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, + ("rtw_alloc_xmitframe:%d\n", + pxmitpriv->free_xmitframe_cnt)); } else { - phead = get_list_head(pfree_xmit_queue); - - plist = phead->next; - - pxframe = container_of(plist, struct xmit_frame, list); + list_del_init(&pxframe->list); - list_del_init(&(pxframe->list)); - } - - if (pxframe != NULL) { /* default value setting */ + /* default value setting */ pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", pxmitpriv->free_xmitframe_cnt)); + RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, + ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", + pxmitpriv->free_xmitframe_cnt)); pxframe->buf_addr = NULL; pxframe->pxmitbuf = NULL; @@ -1402,10 +1368,8 @@ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pf pxframe->agg_num = 1; pxframe->ack_report = 0; } - spin_unlock_bh(&pfree_xmit_queue->lock); - return pxframe; } -- cgit From a3124e7b72bc3d9b915c690561bafe3ad8807696 Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Wed, 20 Jan 2016 12:52:58 +0000 Subject: staging: rtl8188eu: use eth_broadcast_addr() in place of memset Replace the memset of array to broadcast address 0xFF by using the eth_broadcast_addr() API Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/ioctl_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index a076ede50b22..aec20bb28ca0 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -1907,7 +1907,7 @@ static int rtw_wx_set_enc_ext(struct net_device *dev, memset(param, 0, param_len); param->cmd = IEEE_CMD_SET_ENCRYPTION; - memset(param->sta_addr, 0xff, ETH_ALEN); + eth_broadcast_addr(param->sta_addr); switch (pext->alg) { case IW_ENCODE_ALG_NONE: -- cgit From 35eb8ecd35df8d880b65789282cf97eb1dd8481c Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:15 +0000 Subject: staging: vt6655: channel.c replace pDevice with priv Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/channel.c | 58 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 7a717828fa09..6edccb42231e 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -176,62 +176,62 @@ void vnt_init_bands(struct vnt_private *priv) */ bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) { - struct vnt_private *pDevice = pDeviceHandler; + struct vnt_private *priv = pDeviceHandler; bool bResult = true; - if (pDevice->byCurrentCh == ch->hw_value) + if (priv->byCurrentCh == ch->hw_value) return bResult; /* Set VGA to max sensitivity */ - if (pDevice->bUpdateBBVGA && - pDevice->byBBVGACurrent != pDevice->abyBBVGA[0]) { - pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; + if (priv->bUpdateBBVGA && + priv->byBBVGACurrent != priv->abyBBVGA[0]) { + priv->byBBVGACurrent = priv->abyBBVGA[0]; - BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent); + BBvSetVGAGainOffset(priv, priv->byBBVGACurrent); } /* clear NAV */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); + MACvRegBitsOn(priv->PortOffset, MAC_REG_MACCR, MACCR_CLRNAV); /* TX_PE will reserve 3 us for MAX2829 A mode only, it is for better TX throughput */ - if (pDevice->byRFType == RF_AIROHA7230) - RFbAL7230SelectChannelPostProcess(pDevice, pDevice->byCurrentCh, + if (priv->byRFType == RF_AIROHA7230) + RFbAL7230SelectChannelPostProcess(priv, priv->byCurrentCh, ch->hw_value); - pDevice->byCurrentCh = ch->hw_value; - bResult &= RFbSelectChannel(pDevice, pDevice->byRFType, + priv->byCurrentCh = ch->hw_value; + bResult &= RFbSelectChannel(priv, priv->byRFType, ch->hw_value); /* Init Synthesizer Table */ - if (pDevice->bEnablePSMode) - RFvWriteWakeProgSyn(pDevice, pDevice->byRFType, ch->hw_value); + if (priv->bEnablePSMode) + RFvWriteWakeProgSyn(priv, priv->byRFType, ch->hw_value); - BBvSoftwareReset(pDevice); + BBvSoftwareReset(priv); - if (pDevice->byLocalID > REV_ID_VT3253_B1) { + if (priv->byLocalID > REV_ID_VT3253_B1) { unsigned long flags; - spin_lock_irqsave(&pDevice->lock, flags); + spin_lock_irqsave(&priv->lock, flags); /* set HW default power register */ - MACvSelectPage1(pDevice->PortOffset); - RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); - VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWRCCK, - pDevice->byCurPwr); - RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); - VNSvOutPortB(pDevice->PortOffset + MAC_REG_PWROFDM, - pDevice->byCurPwr); - MACvSelectPage0(pDevice->PortOffset); - - spin_unlock_irqrestore(&pDevice->lock, flags); + MACvSelectPage1(priv->PortOffset); + RFbSetPower(priv, RATE_1M, priv->byCurrentCh); + VNSvOutPortB(priv->PortOffset + MAC_REG_PWRCCK, + priv->byCurPwr); + RFbSetPower(priv, RATE_6M, priv->byCurrentCh); + VNSvOutPortB(priv->PortOffset + MAC_REG_PWROFDM, + priv->byCurPwr); + MACvSelectPage0(priv->PortOffset); + + spin_unlock_irqrestore(&priv->lock, flags); } - if (pDevice->byBBType == BB_TYPE_11B) - RFbSetPower(pDevice, RATE_1M, pDevice->byCurrentCh); + if (priv->byBBType == BB_TYPE_11B) + RFbSetPower(priv, RATE_1M, priv->byCurrentCh); else - RFbSetPower(pDevice, RATE_6M, pDevice->byCurrentCh); + RFbSetPower(priv, RATE_6M, priv->byCurrentCh); return bResult; } -- cgit From cea57ee6be0a94ff9f9a73e99800b5d25e7229d1 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:16 +0000 Subject: staging: vt6655: set_channel replace void handler. Replace with struct vnt_private. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/channel.c | 3 +-- drivers/staging/vt6655/channel.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index 6edccb42231e..d1c91165f769 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -174,9 +174,8 @@ void vnt_init_bands(struct vnt_private *priv) * Return Value: true if succeeded; false if failed. * */ -bool set_channel(void *pDeviceHandler, struct ieee80211_channel *ch) +bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) { - struct vnt_private *priv = pDeviceHandler; bool bResult = true; if (priv->byCurrentCh == ch->hw_value) diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h index e2be6fca5f26..2d613e7f169c 100644 --- a/drivers/staging/vt6655/channel.h +++ b/drivers/staging/vt6655/channel.h @@ -27,6 +27,6 @@ void vnt_init_bands(struct vnt_private *); -bool set_channel(void *pDeviceHandler, struct ieee80211_channel *); +bool set_channel(struct vnt_private *, struct ieee80211_channel *); #endif /* _CHANNEL_H_ */ -- cgit From b379916559b09caa64b9c4bff36ac139a42c6c7b Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:17 +0000 Subject: staging: vt6655: set_channel replace bResult with ret Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/channel.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c index d1c91165f769..9ac1ef9d0d51 100644 --- a/drivers/staging/vt6655/channel.c +++ b/drivers/staging/vt6655/channel.c @@ -176,10 +176,10 @@ void vnt_init_bands(struct vnt_private *priv) */ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) { - bool bResult = true; + bool ret = true; if (priv->byCurrentCh == ch->hw_value) - return bResult; + return ret; /* Set VGA to max sensitivity */ if (priv->bUpdateBBVGA && @@ -200,8 +200,8 @@ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) ch->hw_value); priv->byCurrentCh = ch->hw_value; - bResult &= RFbSelectChannel(priv, priv->byRFType, - ch->hw_value); + ret &= RFbSelectChannel(priv, priv->byRFType, + ch->hw_value); /* Init Synthesizer Table */ if (priv->bEnablePSMode) @@ -232,5 +232,5 @@ bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch) else RFbSetPower(priv, RATE_6M, priv->byCurrentCh); - return bResult; + return ret; } -- cgit From 9a012c4297322c228191e2c8c5632142c9f9a55a Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:18 +0000 Subject: staging: vt6655: rf.c rename bResult ret. Removing camel case and reflecting return value. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rf.c | 138 ++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 4c22bb318c79..1c0691d18583 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -420,9 +420,9 @@ static bool s_bAL7230Init(struct vnt_private *priv) { void __iomem *dwIoBase = priv->PortOffset; int ii; - bool bResult; + bool ret; - bResult = true; + ret = true; /* 3-wire control for normal mode */ VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); @@ -432,7 +432,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) BBvPowerSaveModeOFF(priv); /* RobertYu:20050106, have DC value for Calibration */ for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[ii]); /* PLL On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); @@ -440,13 +440,13 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* Calibration */ MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ /* TXDCOC:active, RCK:disable */ - bResult &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ /* TXDCOC:disable, RCK:active */ - bResult &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ /* TXDCOC:disable, RCK:disable */ - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | @@ -459,7 +459,7 @@ static bool s_bAL7230Init(struct vnt_private *priv) /* 3-wire control for power saving mode */ VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ - return bResult; + return ret; } /* Need to Pull PLLON low when writing channel registers through @@ -467,16 +467,16 @@ static bool s_bAL7230Init(struct vnt_private *priv) static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { void __iomem *dwIoBase = priv->PortOffset; - bool bResult; + bool ret; - bResult = true; + ret = true; /* PLLON Off */ MACvWordRegBitsOff(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable0[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable1[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230ChannelTable2[byChannel - 1]); /* PLLOn On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); @@ -487,7 +487,7 @@ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); - return bResult; + return ret; } /* @@ -540,9 +540,9 @@ static bool RFbAL2230Init(struct vnt_private *priv) { void __iomem *dwIoBase = priv->PortOffset; int ii; - bool bResult; + bool ret; - bResult = true; + ret = true; /* 3-wire control for normal mode */ VNSvOutPortB(dwIoBase + MAC_REG_SOFTPWRCTL, 0); @@ -556,18 +556,18 @@ static bool RFbAL2230Init(struct vnt_private *priv) IFRFbWriteEmbedded(priv, (0x07168700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) - bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */ /* PLL On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ - bResult &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ - bResult &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); + ret &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ - bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | SOFTPWRCTL_SWPE2 | @@ -577,18 +577,18 @@ static bool RFbAL2230Init(struct vnt_private *priv) /* 3-wire control for power saving mode */ VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */ - return bResult; + return ret; } static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel) { void __iomem *dwIoBase = priv->PortOffset; - bool bResult; + bool ret; - bResult = true; + ret = true; - bResult &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable0[byChannel - 1]); - bResult &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable0[byChannel - 1]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230ChannelTable1[byChannel - 1]); /* Set Channel[7] = 0 to tell H/W channel is changing now. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); @@ -596,7 +596,7 @@ static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); - return bResult; + return ret; } /* @@ -616,26 +616,26 @@ bool RFbInit( struct vnt_private *priv ) { - bool bResult = true; + bool ret = true; switch (priv->byRFType) { case RF_AIROHA: case RF_AL2230S: priv->byMaxPwrLevel = AL2230_PWR_IDX_LEN; - bResult = RFbAL2230Init(priv); + ret = RFbAL2230Init(priv); break; case RF_AIROHA7230: priv->byMaxPwrLevel = AL7230_PWR_IDX_LEN; - bResult = s_bAL7230Init(priv); + ret = s_bAL7230Init(priv); break; case RF_NOTHING: - bResult = true; + ret = true; break; default: - bResult = false; + ret = false; break; } - return bResult; + return ret; } /* @@ -654,26 +654,26 @@ bool RFbInit( bool RFbSelectChannel(struct vnt_private *priv, unsigned char byRFType, u16 byChannel) { - bool bResult = true; + bool ret = true; switch (byRFType) { case RF_AIROHA: case RF_AL2230S: - bResult = RFbAL2230SelectChannel(priv, byChannel); + ret = RFbAL2230SelectChannel(priv, byChannel); break; /*{{ RobertYu: 20050104 */ case RF_AIROHA7230: - bResult = s_bAL7230SelectChannel(priv, byChannel); + ret = s_bAL7230SelectChannel(priv, byChannel); break; /*}} RobertYu */ case RF_NOTHING: - bResult = true; + ret = true; break; default: - bResult = false; + ret = false; break; } - return bResult; + return ret; } /* @@ -772,7 +772,7 @@ bool RFbSetPower( u16 uCH ) { - bool bResult = true; + bool ret = true; unsigned char byPwr = 0; unsigned char byDec = 0; @@ -818,11 +818,11 @@ bool RFbSetPower( if (priv->byCurPwr == byPwr) return true; - bResult = RFbRawSetPower(priv, byPwr, rate); - if (bResult) + ret = RFbRawSetPower(priv, byPwr, rate); + if (ret) priv->byCurPwr = byPwr; - return bResult; + return ret; } /* @@ -845,7 +845,7 @@ bool RFbRawSetPower( unsigned int rate ) { - bool bResult = true; + bool ret = true; unsigned long dwMax7230Pwr = 0; if (byPwr >= priv->byMaxPwrLevel) @@ -853,22 +853,22 @@ bool RFbRawSetPower( switch (priv->byRFType) { case RF_AIROHA: - bResult &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) - bResult &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0001B400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); else - bResult &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); break; case RF_AL2230S: - bResult &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); + ret &= IFRFbWriteEmbedded(priv, dwAL2230PowerTable[byPwr]); if (rate <= RATE_11M) { - bResult &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x040C1400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00299B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } else { - bResult &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); - bResult &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); + ret &= IFRFbWriteEmbedded(priv, 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW); } break; @@ -879,13 +879,13 @@ bool RFbRawSetPower( dwMax7230Pwr = 0x080C0B00 | ((byPwr) << 12) | (BY_AL7230_REG_LEN << 3) | IFREGCTL_REGW; - bResult &= IFRFbWriteEmbedded(priv, dwMax7230Pwr); + ret &= IFRFbWriteEmbedded(priv, dwMax7230Pwr); break; default: break; } - return bResult; + return ret; } /*+ @@ -934,32 +934,32 @@ bool RFbAL7230SelectChannelPostProcess(struct vnt_private *priv, u16 byOldChannel, u16 byNewChannel) { - bool bResult; + bool ret; - bResult = true; + ret = true; /* if change between 11 b/g and 11a need to update the following * register * Channel Index 1~14 */ if ((byOldChannel <= CB_MAX_CHANNEL_24G) && (byNewChannel > CB_MAX_CHANNEL_24G)) { /* Change from 2.4G to 5G [Reg] */ - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[3]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[5]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[7]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[10]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[12]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[15]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[2]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[3]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[5]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[7]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[10]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[12]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTableAMode[15]); } else if ((byOldChannel > CB_MAX_CHANNEL_24G) && (byNewChannel <= CB_MAX_CHANNEL_24G)) { /* Change from 5G to 2.4G [Reg] */ - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[2]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[3]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[5]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[7]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[10]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[12]); - bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[15]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[2]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[3]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[5]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[7]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[10]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[12]); + ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[15]); } - return bResult; + return ret; } -- cgit From 16d56de650b6ef0756195f4beb449e250ba97cb5 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:19 +0000 Subject: staging: vt6655: power.c replace pDevice with priv Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/power.c | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 06e6b9d871c4..e58afbd8c89e 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -68,40 +68,40 @@ PSvEnablePowerSaving( unsigned short wListenInterval ) { - struct vnt_private *pDevice = hDeviceContext; - u16 wAID = pDevice->current_aid | BIT(14) | BIT(15); + struct vnt_private *priv = hDeviceContext; + u16 wAID = priv->current_aid | BIT(14) | BIT(15); /* set period of power up before TBTT */ - VNSvOutPortW(pDevice->PortOffset + MAC_REG_PWBT, C_PWBT); - if (pDevice->op_mode != NL80211_IFTYPE_ADHOC) { + VNSvOutPortW(priv->PortOffset + MAC_REG_PWBT, C_PWBT); + if (priv->op_mode != NL80211_IFTYPE_ADHOC) { /* set AID */ - VNSvOutPortW(pDevice->PortOffset + MAC_REG_AIDATIM, wAID); + VNSvOutPortW(priv->PortOffset + MAC_REG_AIDATIM, wAID); } else { /* set ATIM Window */ #if 0 /* TODO atim window */ - MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); + MACvWriteATIMW(priv->PortOffset, pMgmt->wCurrATIMWindow); #endif } /* Set AutoSleep */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); /* Set HWUTSF */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + MACvRegBitsOn(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); if (wListenInterval >= 2) { /* clear always listen beacon */ - MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); /* first time set listen next beacon */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); } else { /* always listen beacon */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); } /* enable power saving hw function */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); - pDevice->bEnablePSMode = true; + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PSEN); + priv->bEnablePSMode = true; - pDevice->bPWBitOn = true; + priv->bPWBitOn = true; pr_debug("PS:Power Saving Mode Enable...\n"); } @@ -120,20 +120,20 @@ PSvDisablePowerSaving( void *hDeviceContext ) { - struct vnt_private *pDevice = hDeviceContext; + struct vnt_private *priv = hDeviceContext; /* disable power saving hw function */ - MACbPSWakeup(pDevice->PortOffset); + MACbPSWakeup(priv->PortOffset); /* clear AutoSleep */ - MACvRegBitsOff(pDevice->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); + MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); /* clear HWUTSF */ - MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); + MACvRegBitsOff(priv->PortOffset, MAC_REG_TFTCTL, TFTCTL_HWUTSF); /* set always listen beacon */ - MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_ALBCN); - pDevice->bEnablePSMode = false; + priv->bEnablePSMode = false; - pDevice->bPWBitOn = false; + priv->bPWBitOn = false; } @@ -152,20 +152,20 @@ PSbIsNextTBTTWakeUp( void *hDeviceContext ) { - struct vnt_private *pDevice = hDeviceContext; - struct ieee80211_hw *hw = pDevice->hw; + struct vnt_private *priv = hDeviceContext; + struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; bool bWakeUp = false; if (conf->listen_interval > 1) { - if (!pDevice->wake_up_count) - pDevice->wake_up_count = conf->listen_interval; + if (!priv->wake_up_count) + priv->wake_up_count = conf->listen_interval; - --pDevice->wake_up_count; + --priv->wake_up_count; - if (pDevice->wake_up_count == 1) { + if (priv->wake_up_count == 1) { /* Turn on wake up to listen next beacon */ - MACvRegBitsOn(pDevice->PortOffset, + MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); bWakeUp = true; } -- cgit From c30ab9303f8c6e92d48afe1740a8483b431c195f Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:20 +0000 Subject: staging: vt6655: rf.c/h Replace DeviceContext with vnt_private Removing void and including device.h for power.h Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/power.c | 10 +++------- drivers/staging/vt6655/power.h | 8 +++++--- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index e58afbd8c89e..ad44746d4ff4 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -64,11 +64,10 @@ void PSvEnablePowerSaving( - void *hDeviceContext, + struct vnt_private *priv, unsigned short wListenInterval ) { - struct vnt_private *priv = hDeviceContext; u16 wAID = priv->current_aid | BIT(14) | BIT(15); /* set period of power up before TBTT */ @@ -117,11 +116,9 @@ PSvEnablePowerSaving( void PSvDisablePowerSaving( - void *hDeviceContext + struct vnt_private *priv ) { - struct vnt_private *priv = hDeviceContext; - /* disable power saving hw function */ MACbPSWakeup(priv->PortOffset); /* clear AutoSleep */ @@ -149,10 +146,9 @@ PSvDisablePowerSaving( bool PSbIsNextTBTTWakeUp( - void *hDeviceContext + struct vnt_private *priv ) { - struct vnt_private *priv = hDeviceContext; struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; bool bWakeUp = false; diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h index 538e68507bb0..d82dd8d6d68b 100644 --- a/drivers/staging/vt6655/power.h +++ b/drivers/staging/vt6655/power.h @@ -29,25 +29,27 @@ #ifndef __POWER_H__ #define __POWER_H__ +#include "device.h" + #define C_PWBT 1000 /* micro sec. power up before TBTT */ #define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */ #define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */ void PSvDisablePowerSaving( - void *hDeviceContext + struct vnt_private * ); void PSvEnablePowerSaving( - void *hDeviceContext, + struct vnt_private *, unsigned short wListenInterval ); bool PSbIsNextTBTTWakeUp( - void *hDeviceContext + struct vnt_private * ); #endif /* __POWER_H__ */ -- cgit From a977551be94337e8c58331b7e43f8238dcc827bf Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:21 +0000 Subject: staging: vt6655: PSbIsNextTBTTWakeUp Rename bWakeUp wake_up Removing camel case. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/power.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index ad44746d4ff4..5e968c9340d7 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -151,7 +151,7 @@ PSbIsNextTBTTWakeUp( { struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &hw->conf; - bool bWakeUp = false; + bool wake_up = false; if (conf->listen_interval > 1) { if (!priv->wake_up_count) @@ -163,9 +163,9 @@ PSbIsNextTBTTWakeUp( /* Turn on wake up to listen next beacon */ MACvRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN); - bWakeUp = true; + wake_up = true; } } - return bWakeUp; + return wake_up; } -- cgit From f9f853af84c9205ba9dbc461da0f11da1f4abb53 Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sun, 22 Nov 2015 09:07:22 +0000 Subject: staging: vt6655: mac.c replace void __iomem * with struct vnt_private Moving void __iomem down one level in the following functions MACbIsRegBitsOn MACbIsRegBitsOff MACbIsIntDisable MACvSetShortRetryLimit MACvSetLongRetryLimit MACvGetLongRetryLimit MACvSetLoopbackMode MACvSaveContext MACvRestoreContext MACbSoftwareReset MACbSafeSoftwareReset MACbSafeRxOff MACbSafeTxOff MACbSafeStop MACbShutdown MACvInitialize MACvSetCurrRx0DescAddr MACvSetCurrRx1DescAddr MACvSetCurrTXDescAddr MACvSetCurrTx0DescAddrEx MACvSetCurrAC0DescAddrEx MACvSetCurrSyncDescAddrEx MACvSetCurrATIMDescAddrEx MACvTimer0MicroSDelay MACvOneShotTimer1MicroSec MACvSetMISCFifo MACbPSWakeup MACvSetKeyEntry MACvDisableKeyEntry Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/card.c | 18 ++---- drivers/staging/vt6655/device_main.c | 24 ++++---- drivers/staging/vt6655/key.c | 8 +-- drivers/staging/vt6655/mac.c | 108 ++++++++++++++++++++++------------- drivers/staging/vt6655/mac.h | 58 +++++++++---------- drivers/staging/vt6655/power.c | 2 +- drivers/staging/vt6655/rf.c | 36 ++++++------ 7 files changed, 137 insertions(+), 117 deletions(-) diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c index b6730a8068fd..6c1b973a675f 100644 --- a/drivers/staging/vt6655/card.c +++ b/drivers/staging/vt6655/card.c @@ -535,11 +535,9 @@ CARDvSafeResetTx( } /* set MAC TD pointer */ - MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv->PortOffset, - (priv->td0_pool_dma)); + MACvSetCurrTXDescAddr(TYPE_TXDMA0, priv, priv->td0_pool_dma); - MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv->PortOffset, - (priv->td1_pool_dma)); + MACvSetCurrTXDescAddr(TYPE_AC0DMA, priv, priv->td1_pool_dma); /* set MAC Beacon TX pointer */ MACvSetCurrBCNTxDescAddr(priv->PortOffset, @@ -590,11 +588,9 @@ CARDvSafeResetRx( MACvRx0PerPktMode(priv->PortOffset); MACvRx1PerPktMode(priv->PortOffset); /* set MAC RD pointer */ - MACvSetCurrRx0DescAddr(priv->PortOffset, - priv->rd0_pool_dma); + MACvSetCurrRx0DescAddr(priv, priv->rd0_pool_dma); - MACvSetCurrRx1DescAddr(priv->PortOffset, - priv->rd1_pool_dma); + MACvSetCurrRx1DescAddr(priv, priv->rd1_pool_dma); } /* @@ -839,8 +835,6 @@ unsigned char CARDbyGetPktType(struct vnt_private *priv) */ void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode) { - void __iomem *dwIoBase = priv->PortOffset; - switch (wLoopbackMode) { case CARD_LB_NONE: case CARD_LB_MAC: @@ -850,7 +844,7 @@ void CARDvSetLoopbackMode(struct vnt_private *priv, unsigned short wLoopbackMode break; } /* set MAC loopback */ - MACvSetLoopbackMode(dwIoBase, LOBYTE(wLoopbackMode)); + MACvSetLoopbackMode(priv, LOBYTE(wLoopbackMode)); /* set Baseband loopback */ } @@ -869,7 +863,7 @@ bool CARDbSoftwareReset(struct vnt_private *priv) { /* reset MAC */ - if (!MACbSafeSoftwareReset(priv->PortOffset)) + if (!MACbSafeSoftwareReset(priv)) return false; return true; diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index fefbf826c622..ad0fb84e5096 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -211,11 +211,11 @@ static void device_init_registers(struct vnt_private *priv) unsigned char byCCKPwrdBm = 0; unsigned char byOFDMPwrdBm = 0; - MACbShutdown(priv->PortOffset); + MACbShutdown(priv); BBvSoftwareReset(priv); /* Do MACbSoftwareReset in MACvInitialize */ - MACbSoftwareReset(priv->PortOffset); + MACbSoftwareReset(priv); priv->bAES = false; @@ -229,7 +229,7 @@ static void device_init_registers(struct vnt_private *priv) priv->byTopCCKBasicRate = RATE_1M; /* init MAC */ - MACvInitialize(priv->PortOffset); + MACvInitialize(priv); /* Get Local ID */ VNSvInPortB(priv->PortOffset + MAC_REG_LOCALID, &priv->byLocalID); @@ -357,8 +357,8 @@ static void device_init_registers(struct vnt_private *priv) MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); /* set performance parameter by registry */ - MACvSetShortRetryLimit(priv->PortOffset, priv->byShortRetryLimit); - MACvSetLongRetryLimit(priv->PortOffset, priv->byLongRetryLimit); + MACvSetShortRetryLimit(priv, priv->byShortRetryLimit); + MACvSetLongRetryLimit(priv, priv->byLongRetryLimit); /* reset TSF counter */ VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); @@ -884,7 +884,7 @@ static void device_error(struct vnt_private *priv, unsigned short status) if (status & ISR_FETALERR) { dev_err(&priv->pcid->dev, "Hardware fatal error\n"); - MACbShutdown(priv->PortOffset); + MACbShutdown(priv); return; } } @@ -1012,7 +1012,7 @@ static void vnt_interrupt_process(struct vnt_private *priv) if ((priv->op_mode == NL80211_IFTYPE_AP || priv->op_mode == NL80211_IFTYPE_ADHOC) && priv->vif->bss_conf.enable_beacon) { - MACvOneShotTimer1MicroSec(priv->PortOffset, + MACvOneShotTimer1MicroSec(priv, (priv->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10); } @@ -1197,8 +1197,8 @@ static void vnt_stop(struct ieee80211_hw *hw) cancel_work_sync(&priv->interrupt_work); - MACbShutdown(priv->PortOffset); - MACbSoftwareReset(priv->PortOffset); + MACbShutdown(priv); + MACbSoftwareReset(priv); CARDbRadioPowerOff(priv); device_free_td0_ring(priv); @@ -1636,13 +1636,13 @@ vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) INIT_WORK(&priv->interrupt_work, vnt_interrupt_work); /* do reset */ - if (!MACbSoftwareReset(priv->PortOffset)) { + if (!MACbSoftwareReset(priv)) { dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); device_free_info(priv); return -ENODEV; } /* initial to reload eeprom */ - MACvInitialize(priv->PortOffset); + MACvInitialize(priv); MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr); /* Get RFType */ @@ -1690,7 +1690,7 @@ static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state) pci_save_state(pcid); - MACbShutdown(priv->PortOffset); + MACbShutdown(priv); pci_disable_device(pcid); pci_set_power_state(pcid, pci_choose_state(pcid, state)); diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c index f2b3fea90533..ffcaf25fdd8b 100644 --- a/drivers/staging/vt6655/key.c +++ b/drivers/staging/vt6655/key.c @@ -36,7 +36,7 @@ int vnt_key_init_table(struct vnt_private *priv) u32 i; for (i = 0; i < MAX_KEY_TABLE; i++) - MACvDisableKeyEntry(priv->PortOffset, i); + MACvDisableKeyEntry(priv, i); return 0; } @@ -104,7 +104,7 @@ static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr, key->key[15] |= 0x80; } - MACvSetKeyEntry(priv->PortOffset, key_mode, entry, key_inx, + MACvSetKeyEntry(priv, key_mode, entry, key_inx, bssid, (u32 *)key->key, priv->byLocalID); return 0; @@ -126,13 +126,13 @@ int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta, switch (key->cipher) { case 0: for (u = 0 ; u < MAX_KEY_TABLE; u++) - MACvDisableKeyEntry(priv->PortOffset, u); + MACvDisableKeyEntry(priv, u); return ret; case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: for (u = 0; u < MAX_KEY_TABLE; u++) - MACvDisableKeyEntry(priv->PortOffset, u); + MACvDisableKeyEntry(priv, u); vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true); diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index 688c3be168d1..e74782aa6475 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -70,9 +70,10 @@ * Return Value: true if all test bits On; otherwise false * */ -bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOn(struct vnt_private *priv, unsigned char byRegOfs, unsigned char byTestBits) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byData; VNSvInPortB(dwIoBase + byRegOfs, &byData); @@ -94,9 +95,10 @@ bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, * Return Value: true if all test bits Off; otherwise false * */ -bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOff(struct vnt_private *priv, unsigned char byRegOfs, unsigned char byTestBits) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byData; VNSvInPortB(dwIoBase + byRegOfs, &byData); @@ -116,8 +118,9 @@ bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, * Return Value: true if interrupt is disable; otherwise false * */ -bool MACbIsIntDisable(void __iomem *dwIoBase) +bool MACbIsIntDisable(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned long dwData; VNSvInPortD(dwIoBase + MAC_REG_IMR, &dwData); @@ -141,8 +144,9 @@ bool MACbIsIntDisable(void __iomem *dwIoBase) * Return Value: none * */ -void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) +void MACvSetShortRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit) { + void __iomem *dwIoBase = priv->PortOffset; /* set SRT */ VNSvOutPortB(dwIoBase + MAC_REG_SRT, byRetryLimit); } @@ -162,8 +166,9 @@ void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) * Return Value: none * */ -void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) +void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit) { + void __iomem *dwIoBase = priv->PortOffset; /* set LRT */ VNSvOutPortB(dwIoBase + MAC_REG_LRT, byRetryLimit); } @@ -182,8 +187,9 @@ void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit) * Return Value: none * */ -void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode) +void MACvSetLoopbackMode(struct vnt_private *priv, unsigned char byLoopbackMode) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byOrgValue; byLoopbackMode <<= 6; @@ -207,8 +213,9 @@ void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode) * Return Value: none * */ -void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) +void MACvSaveContext(struct vnt_private *priv, unsigned char *pbyCxtBuf) { + void __iomem *dwIoBase = priv->PortOffset; int ii; /* read page0 register */ @@ -239,8 +246,9 @@ void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) * Return Value: none * */ -void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) +void MACvRestoreContext(struct vnt_private *priv, unsigned char *pbyCxtBuf) { + void __iomem *dwIoBase = priv->PortOffset; int ii; MACvSelectPage1(dwIoBase); @@ -293,8 +301,9 @@ void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf) * Return Value: true if Reset Success; otherwise false * */ -bool MACbSoftwareReset(void __iomem *dwIoBase) +bool MACbSoftwareReset(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byData; unsigned short ww; @@ -324,7 +333,7 @@ bool MACbSoftwareReset(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeSoftwareReset(void __iomem *dwIoBase) +bool MACbSafeSoftwareReset(struct vnt_private *priv) { unsigned char abyTmpRegData[MAC_MAX_CONTEXT_SIZE_PAGE0+MAC_MAX_CONTEXT_SIZE_PAGE1]; bool bRetVal; @@ -334,11 +343,11 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase) * reset, then restore register's value */ /* save MAC context */ - MACvSaveContext(dwIoBase, abyTmpRegData); + MACvSaveContext(priv, abyTmpRegData); /* do reset */ - bRetVal = MACbSoftwareReset(dwIoBase); + bRetVal = MACbSoftwareReset(priv); /* restore MAC context, except CR0 */ - MACvRestoreContext(dwIoBase, abyTmpRegData); + MACvRestoreContext(priv, abyTmpRegData); return bRetVal; } @@ -356,8 +365,9 @@ bool MACbSafeSoftwareReset(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeRxOff(void __iomem *dwIoBase) +bool MACbSafeRxOff(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned long dwData; unsigned char byData; @@ -414,8 +424,9 @@ bool MACbSafeRxOff(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeTxOff(void __iomem *dwIoBase) +bool MACbSafeTxOff(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned long dwData; unsigned char byData; @@ -474,18 +485,19 @@ bool MACbSafeTxOff(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbSafeStop(void __iomem *dwIoBase) +bool MACbSafeStop(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX); - if (!MACbSafeRxOff(dwIoBase)) { + if (!MACbSafeRxOff(priv)) { pr_debug(" MACbSafeRxOff == false)\n"); - MACbSafeSoftwareReset(dwIoBase); + MACbSafeSoftwareReset(priv); return false; } - if (!MACbSafeTxOff(dwIoBase)) { + if (!MACbSafeTxOff(priv)) { pr_debug(" MACbSafeTxOff == false)\n"); - MACbSafeSoftwareReset(dwIoBase); + MACbSafeSoftwareReset(priv); return false; } @@ -507,17 +519,18 @@ bool MACbSafeStop(void __iomem *dwIoBase) * Return Value: true if success; otherwise false * */ -bool MACbShutdown(void __iomem *dwIoBase) +bool MACbShutdown(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; /* disable MAC IMR */ MACvIntDisable(dwIoBase); - MACvSetLoopbackMode(dwIoBase, MAC_LB_INTERNAL); + MACvSetLoopbackMode(priv, MAC_LB_INTERNAL); /* stop the adapter */ - if (!MACbSafeStop(dwIoBase)) { - MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + if (!MACbSafeStop(priv)) { + MACvSetLoopbackMode(priv, MAC_LB_NONE); return false; } - MACvSetLoopbackMode(dwIoBase, MAC_LB_NONE); + MACvSetLoopbackMode(priv, MAC_LB_NONE); return true; } @@ -534,8 +547,9 @@ bool MACbShutdown(void __iomem *dwIoBase) * Return Value: none * */ -void MACvInitialize(void __iomem *dwIoBase) +void MACvInitialize(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; /* clear sticky bits */ MACvClearStckDS(dwIoBase); /* disable force PME-enable */ @@ -543,7 +557,7 @@ void MACvInitialize(void __iomem *dwIoBase) /* only 3253 A */ /* do reset */ - MACbSoftwareReset(dwIoBase); + MACbSoftwareReset(priv); /* reset TSF counter */ VNSvOutPortB(dwIoBase + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); @@ -565,8 +579,9 @@ void MACvInitialize(void __iomem *dwIoBase) * Return Value: none * */ -void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr) +void MACvSetCurrRx0DescAddr(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -600,8 +615,9 @@ void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr * Return Value: none * */ -void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr) +void MACvSetCurrRx1DescAddr(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -636,9 +652,10 @@ void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, unsigned long dwCurrDescAddr * Return Value: none * */ -void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrTx0DescAddrEx(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -673,9 +690,10 @@ void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, * */ /* TxDMA1 = AC0DMA */ -void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrAC0DescAddrEx(struct vnt_private *priv, unsigned long dwCurrDescAddr) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short ww; unsigned char byData; unsigned char byOrgDMACtl; @@ -696,13 +714,13 @@ void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, VNSvOutPortB(dwIoBase + MAC_REG_AC0DMACTL, DMACTL_RUN); } -void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, +void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *priv, unsigned long dwCurrDescAddr) { if (iTxType == TYPE_AC0DMA) - MACvSetCurrAC0DescAddrEx(dwIoBase, dwCurrDescAddr); + MACvSetCurrAC0DescAddrEx(priv, dwCurrDescAddr); else if (iTxType == TYPE_TXDMA0) - MACvSetCurrTx0DescAddrEx(dwIoBase, dwCurrDescAddr); + MACvSetCurrTx0DescAddrEx(priv, dwCurrDescAddr); } /* @@ -719,8 +737,9 @@ void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, * Return Value: none * */ -void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay) +void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byValue; unsigned int uu, ii; @@ -754,16 +773,20 @@ void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay) * Return Value: none * */ -void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime) +void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime) { + void __iomem *dwIoBase = priv->PortOffset; + VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, 0); VNSvOutPortD(dwIoBase + MAC_REG_TMDATA1, uDelayTime); VNSvOutPortB(dwIoBase + MAC_REG_TMCTL1, (TMCTL_TMD | TMCTL_TE)); } -void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, +void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset, unsigned long dwData) { + void __iomem *dwIoBase = priv->PortOffset; + if (wOffset > 273) return; VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); @@ -771,12 +794,13 @@ void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, VNSvOutPortW(dwIoBase + MAC_REG_MISCFFCTL, MISCFFCTL_WRITE); } -bool MACbPSWakeup(void __iomem *dwIoBase) +bool MACbPSWakeup(struct vnt_private *priv) { + void __iomem *dwIoBase = priv->PortOffset; unsigned char byOrgValue; unsigned int ww; /* Read PSCTL */ - if (MACbIsRegBitsOff(dwIoBase, MAC_REG_PSCTL, PSCTL_PS)) + if (MACbIsRegBitsOff(priv, MAC_REG_PSCTL, PSCTL_PS)) return true; /* Disable PS */ @@ -810,11 +834,12 @@ bool MACbPSWakeup(void __iomem *dwIoBase) * */ -void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, +void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short wOffset; u32 dwData; int ii; @@ -878,8 +903,9 @@ void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, * Return Value: none * */ -void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx) +void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx) { + void __iomem *dwIoBase = priv->PortOffset; unsigned short wOffset; wOffset = MISCFIFO_KEYETRY0; diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h index 8e0200a78b19..192f4666539b 100644 --- a/drivers/staging/vt6655/mac.h +++ b/drivers/staging/vt6655/mac.h @@ -890,57 +890,57 @@ do { \ #define MACvSetRFLE_LatchBase(dwIoBase) \ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT) -bool MACbIsRegBitsOn(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOn(struct vnt_private *, unsigned char byRegOfs, unsigned char byTestBits); -bool MACbIsRegBitsOff(void __iomem *dwIoBase, unsigned char byRegOfs, +bool MACbIsRegBitsOff(struct vnt_private *, unsigned char byRegOfs, unsigned char byTestBits); -bool MACbIsIntDisable(void __iomem *dwIoBase); +bool MACbIsIntDisable(struct vnt_private *); -void MACvSetShortRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); +void MACvSetShortRetryLimit(struct vnt_private *, unsigned char byRetryLimit); -void MACvSetLongRetryLimit(void __iomem *dwIoBase, unsigned char byRetryLimit); -void MACvGetLongRetryLimit(void __iomem *dwIoBase, +void MACvSetLongRetryLimit(struct vnt_private *, unsigned char byRetryLimit); +void MACvGetLongRetryLimit(struct vnt_private *, unsigned char *pbyRetryLimit); -void MACvSetLoopbackMode(void __iomem *dwIoBase, unsigned char byLoopbackMode); +void MACvSetLoopbackMode(struct vnt_private *, unsigned char byLoopbackMode); -void MACvSaveContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf); -void MACvRestoreContext(void __iomem *dwIoBase, unsigned char *pbyCxtBuf); +void MACvSaveContext(struct vnt_private *, unsigned char *pbyCxtBuf); +void MACvRestoreContext(struct vnt_private *, unsigned char *pbyCxtBuf); -bool MACbSoftwareReset(void __iomem *dwIoBase); -bool MACbSafeSoftwareReset(void __iomem *dwIoBase); -bool MACbSafeRxOff(void __iomem *dwIoBase); -bool MACbSafeTxOff(void __iomem *dwIoBase); -bool MACbSafeStop(void __iomem *dwIoBase); -bool MACbShutdown(void __iomem *dwIoBase); -void MACvInitialize(void __iomem *dwIoBase); -void MACvSetCurrRx0DescAddr(void __iomem *dwIoBase, +bool MACbSoftwareReset(struct vnt_private *); +bool MACbSafeSoftwareReset(struct vnt_private *); +bool MACbSafeRxOff(struct vnt_private *); +bool MACbSafeTxOff(struct vnt_private *); +bool MACbSafeStop(struct vnt_private *); +bool MACbShutdown(struct vnt_private *); +void MACvInitialize(struct vnt_private *); +void MACvSetCurrRx0DescAddr(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrRx1DescAddr(void __iomem *dwIoBase, +void MACvSetCurrRx1DescAddr(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrTXDescAddr(int iTxType, void __iomem *dwIoBase, +void MACvSetCurrTXDescAddr(int iTxType, struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrTx0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrTx0DescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrAC0DescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrAC0DescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrSyncDescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrSyncDescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvSetCurrATIMDescAddrEx(void __iomem *dwIoBase, +void MACvSetCurrATIMDescAddrEx(struct vnt_private *, unsigned long dwCurrDescAddr); -void MACvTimer0MicroSDelay(void __iomem *dwIoBase, unsigned int uDelay); -void MACvOneShotTimer1MicroSec(void __iomem *dwIoBase, unsigned int uDelayTime); +void MACvTimer0MicroSDelay(struct vnt_private *, unsigned int uDelay); +void MACvOneShotTimer1MicroSec(struct vnt_private *, unsigned int uDelayTime); -void MACvSetMISCFifo(void __iomem *dwIoBase, unsigned short wOffset, +void MACvSetMISCFifo(struct vnt_private *, unsigned short wOffset, unsigned long dwData); -bool MACbPSWakeup(void __iomem *dwIoBase); +bool MACbPSWakeup(struct vnt_private *); -void MACvSetKeyEntry(void __iomem *dwIoBase, unsigned short wKeyCtl, +void MACvSetKeyEntry(struct vnt_private *, unsigned short wKeyCtl, unsigned int uEntryIdx, unsigned int uKeyIdx, unsigned char *pbyAddr, u32 *pdwKey, unsigned char byLocalID); -void MACvDisableKeyEntry(void __iomem *dwIoBase, unsigned int uEntryIdx); +void MACvDisableKeyEntry(struct vnt_private *, unsigned int uEntryIdx); #endif /* __MAC_H__ */ diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c index 5e968c9340d7..bc8ca981a629 100644 --- a/drivers/staging/vt6655/power.c +++ b/drivers/staging/vt6655/power.c @@ -120,7 +120,7 @@ PSvDisablePowerSaving( ) { /* disable power saving hw function */ - MACbPSWakeup(priv->PortOffset); + MACbPSWakeup(priv); /* clear AutoSleep */ MACvRegBitsOff(priv->PortOffset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); /* clear HWUTSF */ diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 1c0691d18583..3df430bf0a80 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -438,13 +438,13 @@ static bool s_bAL7230Init(struct vnt_private *priv) MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); /* Calibration */ - MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ + MACvTimer0MicroSDelay(priv, 150);/* 150us */ /* TXDCOC:active, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:active */ ret &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ /* TXDCOC:disable, RCK:disable */ ret &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]); @@ -483,7 +483,7 @@ static bool s_bAL7230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 0 to tell H/W channel is changing now. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); - MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL7230); + MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL7230); /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); @@ -557,16 +557,16 @@ static bool RFbAL2230Init(struct vnt_private *priv) for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]); - MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */ + MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */ /* PLL On */ MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3); - MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */ + MACvTimer0MicroSDelay(priv, 150);/* 150us */ ret &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW)); - MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */ + MACvTimer0MicroSDelay(priv, 30);/* 30us */ ret &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]); MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 | @@ -592,7 +592,7 @@ static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byCha /* Set Channel[7] = 0 to tell H/W channel is changing now. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel & 0x7F)); - MACvTimer0MicroSDelay(dwIoBase, SWITCH_CHANNEL_DELAY_AL2230); + MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230); /* Set Channel[7] = 1 to tell H/W channel change is done. */ VNSvOutPortB(dwIoBase + MAC_REG_CHANNEL, (byChannel | 0x80)); @@ -711,11 +711,11 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, return false; for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++) - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230InitTable[ii]); - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable0[uChannel-1]); ii++; - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL2230ChannelTable1[uChannel-1]); break; /* Need to check, PLLON need to be low for channel setting */ @@ -728,17 +728,17 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, if (uChannel <= CB_MAX_CHANNEL_24G) { for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTable[ii]); } else { for (ii = 0; ii < CB_AL7230_INIT_SEQ; ii++) - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230InitTableAMode[ii]); } - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable0[uChannel-1]); ii++; - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable1[uChannel-1]); ii++; - MACvSetMISCFifo(dwIoBase, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]); + MACvSetMISCFifo(priv, (unsigned short)(MISCFIFO_SYNDATA_IDX + ii), dwAL7230ChannelTable2[uChannel-1]); break; case RF_NOTHING: @@ -748,7 +748,7 @@ bool RFvWriteWakeProgSyn(struct vnt_private *priv, unsigned char byRFType, return false; } - MACvSetMISCFifo(dwIoBase, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount)); + MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(bySleepCount, byInitCount)); return true; } -- cgit From e7bda76fa4f54df7021e1014a9d20c5a050ca919 Mon Sep 17 00:00:00 2001 From: Alexey Tulia Date: Sat, 21 Nov 2015 15:36:47 +0300 Subject: staging: vt6656: fix definitions of DEVICE_FLAGS_* flags test_bit and set_bit take the bit number to operate on, rather than a mask. This patch fixes the DEVICE_FLAGS_* definitions so that they represent the bit index in priv->flags as opposed to the mask returned by the BIT macro. Signed-off-by: Alexey Tulia Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index 76b5f4127f95..4832666cc580 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -259,8 +259,8 @@ enum { }; /* flags for options */ -#define DEVICE_FLAGS_UNPLUG BIT(0) -#define DEVICE_FLAGS_DISCONNECTED BIT(1) +#define DEVICE_FLAGS_UNPLUG 0 +#define DEVICE_FLAGS_DISCONNECTED 1 struct vnt_private { /* mac80211 */ -- cgit From 1eba248ae125f66f6c21d99b9d33f766924e4944 Mon Sep 17 00:00:00 2001 From: Sergey Lysanov Date: Fri, 18 Dec 2015 11:06:24 +0300 Subject: drivers:staging:vt6656: Fix coding style issues This patch fixes the following issues reported by checkpatch.pl: - code indent should use tabs where possible Signed-off-by: Sergey Lysanov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index c025dab0f62c..e322b7d8c617 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -103,7 +103,7 @@ void vnt_disable_power_saving(struct vnt_private *priv) /* disable power saving hw function */ vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0, - 0, 0, NULL); + 0, 0, NULL); /* clear AutoSleep */ vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP); -- cgit From d2713e51ebc4c4684afdcc6a0ec76c2142480540 Mon Sep 17 00:00:00 2001 From: maomao xu Date: Thu, 31 Dec 2015 15:20:53 +0800 Subject: Staging: vt6656: Fixed multiple commenting codig style issues. Fixed multiple comment blocks that didn't comply with the kernels coding style. Signed-off-by: maomao xu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index ee8d1e1a24c2..a2f23aefb35d 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -74,10 +74,10 @@ MODULE_PARM_DESC(tx_buffers, "Number of receive usb tx buffers"); #define LONG_RETRY_DEF 4 /* BasebandType[] baseband type selected - 0: indicate 802.11a type - 1: indicate 802.11b type - 2: indicate 802.11g type -*/ + * 0: indicate 802.11a type + * 1: indicate 802.11b type + * 2: indicate 802.11g type + */ #define BBP_TYPE_DEF 2 @@ -284,7 +284,8 @@ static int vnt_init_registers(struct vnt_private *priv) calib_rx_iq = priv->eeprom[EEP_OFS_CALIB_RX_IQ]; if (calib_tx_iq || calib_tx_dc || calib_rx_iq) { /* CR255, enable TX/RX IQ and - DC compensation mode */ + * DC compensation mode + */ vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xff, @@ -306,7 +307,8 @@ static int vnt_init_registers(struct vnt_private *priv) calib_rx_iq); } else { /* CR255, turn off - BB Calibration compensation */ + * BB Calibration compensation + */ vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xff, -- cgit From 4a55218e0ffb65826f57121e9f0abae72f6c3e52 Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:03:49 +0530 Subject: staging: wlan-ng: Fixed block comments coding style issue All block comment lines now begin with "*" and end with "*/" on a new line. Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 1b02cdf9d1fa..3121e1dcf793 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -49,7 +49,8 @@ * * -------------------------------------------------------------------- * -*================================================================ */ +*================================================================ +*/ #include #include @@ -101,7 +102,8 @@ static u8 oui_8021h[] = { 0x00, 0x00, 0xf8 }; * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) @@ -238,7 +240,8 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, int i; /* Gather wireless spy statistics: for each packet, compare the - * source address with out list, and if match, get the stats... */ + * source address with out list, and if match, get the stats... + */ for (i = 0; i < wlandev->spy_number; i++) { @@ -273,7 +276,8 @@ static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac, * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb) { @@ -421,7 +425,8 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, && (e_llc->ctl == 0x03)) { pr_debug("802.1h/RFC1042 len: %d\n", payload_length); /* it's an 802.1h frame || (an RFC1042 && protocol not in STT) - build a DIXII + RFC894 */ + * build a DIXII + RFC894 + */ /* Test for an overlength frame */ if ((payload_length - sizeof(struct wlan_llc) - @@ -521,14 +526,15 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int p80211_stt_findproto(u16 proto) { /* Always return found for now. This is the behavior used by the */ - /* Zoom Win95 driver when 802.1h mode is selected */ + /* Zoom Win95 driver when 802.1h mode is selected */ /* TODO: If necessary, add an actual search we'll probably - need this to match the CMAC's way of doing things. - Need to do some testing to confirm. + * need this to match the CMAC's way of doing things. + * Need to do some testing to confirm. */ if (proto == ETH_P_AARP) /* APPLETALK */ @@ -551,7 +557,8 @@ int p80211_stt_findproto(u16 proto) * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ void p80211skb_rxmeta_detach(struct sk_buff *skb) { struct p80211_rxmeta *rxmeta; @@ -595,7 +602,8 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) { int result = 0; @@ -648,7 +656,8 @@ exit: * * Call context: * May be called in interrupt or non-interrupt context -----------------------------------------------------------------*/ +*---------------------------------------------------------------- +*/ void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb) { struct p80211_frmmeta *meta; -- cgit From 2584538807926344e713548e5210bded8ed22011 Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:09 +0530 Subject: staging: wlan-ng: Logical continuation fixes Logical continuation coding style issues fixed while condition checking Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 47 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 3121e1dcf793..81f36241be03 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -153,8 +153,8 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, (struct wlan_snap *) skb_push(skb, sizeof(struct wlan_snap)); e_snap->type = htons(proto); - if (ethconv == WLAN_ETHCONV_8021h - && p80211_stt_findproto(proto)) { + if (ethconv == WLAN_ETHCONV_8021h && + p80211_stt_findproto(proto)) { memcpy(e_snap->oui, oui_8021h, WLAN_IEEE_OUI_LEN); } else { @@ -204,8 +204,8 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, p80211_wep->data = NULL; - if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) - && (wlandev->hostwep & HOSTWEP_ENCRYPT)) { + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && + (wlandev->hostwep & HOSTWEP_ENCRYPT)) { /* XXXX need to pick keynum other than default? */ p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC); @@ -304,12 +304,12 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) { ether_addr_copy(daddr, w_hdr->a3.a1); ether_addr_copy(saddr, w_hdr->a3.a2); - } else if ((WLAN_GET_FC_TODS(fc) == 0) - && (WLAN_GET_FC_FROMDS(fc) == 1)) { + } else if ((WLAN_GET_FC_TODS(fc) == 0) && + (WLAN_GET_FC_FROMDS(fc) == 1)) { ether_addr_copy(daddr, w_hdr->a3.a1); ether_addr_copy(saddr, w_hdr->a3.a3); - } else if ((WLAN_GET_FC_TODS(fc) == 1) - && (WLAN_GET_FC_FROMDS(fc) == 0)) { + } else if ((WLAN_GET_FC_TODS(fc) == 1) && + (WLAN_GET_FC_FROMDS(fc) == 0)) { ether_addr_copy(daddr, w_hdr->a3.a3); ether_addr_copy(saddr, w_hdr->a3.a2); } else { @@ -324,8 +324,9 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, } /* perform de-wep if necessary.. */ - if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) - && (wlandev->hostwep & HOSTWEP_DECRYPT)) { + if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && + WLAN_GET_FC_ISWEP(fc) && + (wlandev->hostwep & HOSTWEP_DECRYPT)) { if (payload_length <= 8) { netdev_err(netdev, "WEP frame too short (%u).\n", skb->len); @@ -383,15 +384,15 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, skb_trim(skb, skb->len - WLAN_CRC_LEN); } else if ((payload_length >= sizeof(struct wlan_llc) + - sizeof(struct wlan_snap)) - && (e_llc->dsap == 0xaa) - && (e_llc->ssap == 0xaa) - && (e_llc->ctl == 0x03) - && - (((memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0) - && (ethconv == WLAN_ETHCONV_8021h) - && (p80211_stt_findproto(le16_to_cpu(e_snap->type)))) - || (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) != + sizeof(struct wlan_snap)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03) && + (((memcmp(e_snap->oui, oui_rfc1042, + WLAN_IEEE_OUI_LEN) == 0) && + (ethconv == WLAN_ETHCONV_8021h) && + (p80211_stt_findproto(le16_to_cpu(e_snap->type)))) || + (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) != 0))) { pr_debug("SNAP+RFC1042 len: %d\n", payload_length); /* it's a SNAP + RFC1042 frame && protocol is in STT */ @@ -419,10 +420,10 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, skb_trim(skb, skb->len - WLAN_CRC_LEN); } else if ((payload_length >= sizeof(struct wlan_llc) + - sizeof(struct wlan_snap)) - && (e_llc->dsap == 0xaa) - && (e_llc->ssap == 0xaa) - && (e_llc->ctl == 0x03)) { + sizeof(struct wlan_snap)) && + (e_llc->dsap == 0xaa) && + (e_llc->ssap == 0xaa) && + (e_llc->ctl == 0x03)) { pr_debug("802.1h/RFC1042 len: %d\n", payload_length); /* it's an 802.1h frame || (an RFC1042 && protocol not in STT) * build a DIXII + RFC894 -- cgit From 3c3424d2484d1fe5856d29189424893926cf7d23 Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:25 +0530 Subject: staging: wlan-ng: Removed blank lines after braces Blank lines before closing braces and after opening braces have been removed. Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 81f36241be03..00d82e25c250 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -108,7 +108,6 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, struct sk_buff *skb, union p80211_hdr *p80211_hdr, struct p80211_metawep *p80211_wep) { - __le16 fc; u16 proto; struct wlan_ethhdr e_hdr; @@ -169,7 +168,6 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ e_llc->ssap = 0xAA; e_llc->ctl = 0x03; - } } @@ -244,7 +242,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; @@ -486,7 +483,6 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); - } /* -- cgit From 40defde4a4025cd7aae3afcb54c0b9588d96cb8d Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:41 +0530 Subject: staging: wlan-ng: Coding style fix for casting operation Removed spaces after casting operating Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 00d82e25c250..c4fd5b211cd7 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -149,7 +149,7 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, /* tack on SNAP */ e_snap = - (struct wlan_snap *) skb_push(skb, + (struct wlan_snap *)skb_push(skb, sizeof(struct wlan_snap)); e_snap->type = htons(proto); if (ethconv == WLAN_ETHCONV_8021h && @@ -163,7 +163,7 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, /* tack on llc */ e_llc = - (struct wlan_llc *) skb_push(skb, + (struct wlan_llc *)skb_push(skb, sizeof(struct wlan_llc)); e_llc->dsap = 0xAA; /* SNAP, see IEEE 802 */ e_llc->ssap = 0xAA; @@ -294,7 +294,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN; payload_offset = WLAN_HDR_A3_LEN; - w_hdr = (union p80211_hdr *) skb->data; + w_hdr = (union p80211_hdr *)skb->data; /* setup some vars for convenience */ fc = le16_to_cpu(w_hdr->a3.fc); @@ -352,11 +352,11 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, wlandev->rx.decrypt++; } - e_hdr = (struct wlan_ethhdr *) (skb->data + payload_offset); + e_hdr = (struct wlan_ethhdr *)(skb->data + payload_offset); - e_llc = (struct wlan_llc *) (skb->data + payload_offset); + e_llc = (struct wlan_llc *)(skb->data + payload_offset); e_snap = - (struct wlan_snap *) (skb->data + payload_offset + + (struct wlan_snap *)(skb->data + payload_offset + sizeof(struct wlan_llc)); /* Test for the various encodings */ @@ -631,7 +631,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) /* Overlay a frmmeta_t onto skb->cb */ memset(skb->cb, 0, sizeof(struct p80211_frmmeta)); - frmmeta = (struct p80211_frmmeta *) (skb->cb); + frmmeta = (struct p80211_frmmeta *)(skb->cb); frmmeta->magic = P80211_FRMMETA_MAGIC; frmmeta->rx = rxmeta; exit: -- cgit From 64ddba5275c397e34899a1d77e2ca0ee8e169e4b Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:04:56 +0530 Subject: staging: wlan-ng: Open parenthesis alignment style fix Alignment of lines matched with open parenthesis Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index c4fd5b211cd7..81f0f06eb597 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -215,8 +215,8 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv, p80211_wep->iv, p80211_wep->icv); if (foo) { netdev_warn(wlandev->netdev, - "Host en-WEP failed, dropping frame (%d).\n", - foo); + "Host en-WEP failed, dropping frame (%d).\n", + foo); return 2; } fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1)); @@ -330,10 +330,10 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, return 1; } foo = wep_decrypt(wlandev, skb->data + payload_offset + 4, - payload_length - 8, -1, - skb->data + payload_offset, - skb->data + payload_offset + - payload_length - 4); + payload_length - 8, -1, + skb->data + payload_offset, + skb->data + payload_offset + + payload_length - 4); if (foo) { /* de-wep failed, drop skb. */ pr_debug("Host de-WEP failed, dropping frame (%d).\n", @@ -371,7 +371,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been encap'd. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "ENCAP frame too large (%d > %d)\n", - payload_length, netdev->mtu + ETH_HLEN); + payload_length, netdev->mtu + ETH_HLEN); return 1; } @@ -400,7 +400,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "SNAP frame too large (%d > %d)\n", - payload_length, netdev->mtu); + payload_length, netdev->mtu); return 1; } @@ -433,9 +433,9 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "DIXII frame too large (%ld > %d)\n", - (long int)(payload_length - - sizeof(struct wlan_llc) - - sizeof(struct wlan_snap)), netdev->mtu); + (long int)(payload_length - + sizeof(struct wlan_llc) - + sizeof(struct wlan_snap)), netdev->mtu); return 1; } @@ -468,7 +468,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv, /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ netdev_err(netdev, "OTHER frame too large (%d > %d)\n", - payload_length, netdev->mtu); + payload_length, netdev->mtu); return 1; } -- cgit From d23054350d0fafdc4a6f8d68b18cd70ec581c95d Mon Sep 17 00:00:00 2001 From: Pranjal Bhor Date: Tue, 19 Jan 2016 01:05:13 +0530 Subject: staging: wlan-ng: NULL comparisons made elegant Elegance added for NULL comparisons Signed-off-by: Pranjal Bhor Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211conv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c index 81f0f06eb597..0a8f3960d465 100644 --- a/drivers/staging/wlan-ng/p80211conv.c +++ b/drivers/staging/wlan-ng/p80211conv.c @@ -562,17 +562,17 @@ void p80211skb_rxmeta_detach(struct sk_buff *skb) struct p80211_frmmeta *frmmeta; /* Sanity checks */ - if (skb == NULL) { /* bad skb */ + if (!skb) { /* bad skb */ pr_debug("Called w/ null skb.\n"); return; } frmmeta = P80211SKB_FRMMETA(skb); - if (frmmeta == NULL) { /* no magic */ + if (!frmmeta) { /* no magic */ pr_debug("Called w/ bad frmmeta magic.\n"); return; } rxmeta = frmmeta->rx; - if (rxmeta == NULL) { /* bad meta ptr */ + if (!rxmeta) { /* bad meta ptr */ pr_debug("Called w/ bad rxmeta ptr.\n"); return; } @@ -608,7 +608,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) struct p80211_frmmeta *frmmeta; /* If these already have metadata, we error out! */ - if (P80211SKB_RXMETA(skb) != NULL) { + if (P80211SKB_RXMETA(skb)) { netdev_err(wlandev->netdev, "%s: RXmeta already attached!\n", wlandev->name); result = 0; @@ -618,7 +618,7 @@ int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb) /* Allocate the rxmeta */ rxmeta = kzalloc(sizeof(struct p80211_rxmeta), GFP_ATOMIC); - if (rxmeta == NULL) { + if (!rxmeta) { netdev_err(wlandev->netdev, "%s: Failed to allocate rxmeta.\n", wlandev->name); result = 1; -- cgit From ea37066d0ee992728c06e8d91f73b34c3982e564 Mon Sep 17 00:00:00 2001 From: Gavin O'Leary Date: Sun, 8 Nov 2015 22:44:20 -0800 Subject: Staging: wlan-ng: p80211wep: fixed a block comment style issue Fixed a comment style issue. Signed-off-by: Gavin O'Leary Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211wep.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index c363456d93a3..e9f990a52cad 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -140,8 +140,8 @@ int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) } /* - 4-byte IV at start of buffer, 4-byte ICV at end of buffer. - if successful, buf start is payload begin, length -= 8; + * 4-byte IV at start of buffer, 4-byte ICV at end of buffer. + * if successful, buf start is payload begin, length -= 8; */ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, u8 *iv, u8 *icv) -- cgit From 1534bc2c0d529cba7f67729d508e3230353c7abc Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Mon, 23 Nov 2015 14:25:05 +0100 Subject: staging: wlan-ng: (coding style) remove unnecessary blank line before "}" Fix checkpatch checks: "Blank lines aren't necessary before a close brace '}' " Remove two unnecessary blank lines. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 8c1e3f06a215..497e3c987239 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -558,7 +558,6 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, (u8 *)sme->key); if (result) goto exit; - } /* Assume we should set privacy invoked and exclude unencrypted @@ -590,7 +589,6 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, P80211ENUM_truth_false); if (result) goto exit; - } /* Now do the actual join. Note there is no way that I can -- cgit From 4f9de774a6fea88c1605b58733d7946d9339b0bf Mon Sep 17 00:00:00 2001 From: Gavin O'Leary Date: Mon, 23 Nov 2015 09:08:18 -0800 Subject: staging: wlan-ng: fixed a comment Fixed a comment style issue. Signed-off-by: Gavin O'Leary Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 497e3c987239..cdbdcdd85ac0 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -592,7 +592,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, } /* Now do the actual join. Note there is no way that I can - see to request a specific bssid */ + * see to request a specific bssid + */ msg_join.msgcode = DIDmsg_lnxreq_autojoin; memcpy(msg_join.ssid.data.data, sme->ssid, length); -- cgit From 35028fe1a604657d41e51f76e5b4eaecc42d551a Mon Sep 17 00:00:00 2001 From: Gavin O'Leary Date: Mon, 23 Nov 2015 09:23:36 -0800 Subject: staging: wlan-ng: Fixed more comments Fixed more comment issues Signed-off-by: Gavin O'Leary Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index cdbdcdd85ac0..4712da1125fa 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -239,7 +239,9 @@ static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, int result = 0; /* There is no direct way in the hardware (AFAIK) of removing - a key, so we will cheat by setting the key to a bogus value */ + * a key, so we will cheat by setting the key to a bogus value + */ + /* send key to driver */ switch (key_index) { case 0: @@ -561,8 +563,9 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, } /* Assume we should set privacy invoked and exclude unencrypted - We could possibly use sme->privacy here, but the assumption - seems reasonable anyway */ + * We could possible use sme->privacy here, but the assumption + * seems reasonable anyways + */ result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_true); @@ -577,7 +580,8 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, } else { /* Assume we should unset privacy invoked - and exclude unencrypted */ + * and exclude unencrypted + */ result = prism2_domibset_uint32(wlandev, DIDmib_dot11smt_dot11PrivacyTable_dot11PrivacyInvoked, P80211ENUM_truth_false); -- cgit From 0adf62bfa72a7f526a657db6a8420ba4de2d0205 Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Mon, 14 Dec 2015 06:11:18 -0800 Subject: drivers:staging:wlan-ng Fix all no space necesarry after a cast This fixes all messages "no space necesarry after a cast" in cfg80211.c file Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/cfg80211.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 4712da1125fa..8bad018eda47 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -73,13 +73,13 @@ static int prism2_domibset_uint32(wlandevice_t *wlandev, u32 did, u32 data) { struct p80211msg_dot11req_mibset msg; p80211item_uint32_t *mibitem = - (p80211item_uint32_t *) &msg.mibattribute.data; + (p80211item_uint32_t *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; mibitem->data = data; - return p80211req_dorequest(wlandev, (u8 *) &msg); + return p80211req_dorequest(wlandev, (u8 *)&msg); } static int prism2_domibset_pstr32(wlandevice_t *wlandev, @@ -87,14 +87,14 @@ static int prism2_domibset_pstr32(wlandevice_t *wlandev, { struct p80211msg_dot11req_mibset msg; p80211item_pstr32_t *mibitem = - (p80211item_pstr32_t *) &msg.mibattribute.data; + (p80211item_pstr32_t *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibset; mibitem->did = did; mibitem->data.len = len; memcpy(mibitem->data.data, data, len); - return p80211req_dorequest(wlandev, (u8 *) &msg); + return p80211req_dorequest(wlandev, (u8 *)&msg); } /* The interface functions, called by the cfg80211 layer */ @@ -317,7 +317,7 @@ static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, if (wlandev->mlmerequest == NULL) return -EOPNOTSUPP; - result = wlandev->mlmerequest(wlandev, (struct p80211msg *) &quality); + result = wlandev->mlmerequest(wlandev, (struct p80211msg *)&quality); if (result == 0) { sinfo->txrate.legacy = quality.txrate.data; @@ -389,7 +389,7 @@ static int prism2_scan(struct wiphy *wiphy, msg1.maxchanneltime.data = 250; msg1.minchanneltime.data = 200; - result = p80211req_dorequest(wlandev, (u8 *) &msg1); + result = p80211req_dorequest(wlandev, (u8 *)&msg1); if (result) { err = prism2_result2err(msg1.resultcode.data); goto exit; @@ -404,7 +404,7 @@ static int prism2_scan(struct wiphy *wiphy, msg2.msgcode = DIDmsg_dot11req_scan_results; msg2.bssindex.data = i; - result = p80211req_dorequest(wlandev, (u8 *) &msg2); + result = p80211req_dorequest(wlandev, (u8 *)&msg2); if ((result != 0) || (msg2.resultcode.data != P80211ENUM_resultcode_success)) { break; @@ -419,7 +419,7 @@ static int prism2_scan(struct wiphy *wiphy, bss = cfg80211_inform_bss(wiphy, ieee80211_get_channel(wiphy, freq), CFG80211_BSS_FTYPE_UNKNOWN, - (const u8 *) &(msg2.bssid.data.data), + (const u8 *)&(msg2.bssid.data.data), msg2.timestamp.data, msg2.capinfo.data, msg2.beaconperiod.data, ie_buf, @@ -603,7 +603,7 @@ static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, memcpy(msg_join.ssid.data.data, sme->ssid, length); msg_join.ssid.data.len = length; - result = p80211req_dorequest(wlandev, (u8 *) &msg_join); + result = p80211req_dorequest(wlandev, (u8 *)&msg_join); exit: if (result) @@ -626,7 +626,7 @@ static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, memcpy(msg_join.ssid.data.data, "---", 3); msg_join.ssid.data.len = 3; - result = p80211req_dorequest(wlandev, (u8 *) &msg_join); + result = p80211req_dorequest(wlandev, (u8 *)&msg_join); if (result) err = -EFAULT; @@ -682,12 +682,12 @@ static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, int result; int err = 0; - mibitem = (p80211item_uint32_t *) &msg.mibattribute.data; + mibitem = (p80211item_uint32_t *)&msg.mibattribute.data; msg.msgcode = DIDmsg_dot11req_mibget; mibitem->did = DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel; - result = p80211req_dorequest(wlandev, (u8 *) &msg); + result = p80211req_dorequest(wlandev, (u8 *)&msg); if (result) { err = -EFAULT; -- cgit From 6c37e1f957be5f67b520e004e196b0e6a9ec2950 Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Mon, 14 Dec 2015 06:25:59 -0800 Subject: drivers:staging:wlan-ng Fix space preferred around that messages This fixes all "space preferred around that ..." messages from checkpatch.pl Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index 7551ac25d89d..a5626df2bebc 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -145,11 +145,11 @@ enum cmd_mode { DOASYNC }; -#define THROTTLE_JIFFIES (HZ/8) +#define THROTTLE_JIFFIES (HZ / 8) #define URB_ASYNC_UNLINK 0 #define USB_QUEUE_BULK 0 -#define ROUNDUP64(a) (((a)+63)&~63) +#define ROUNDUP64(a) (((a) + 63) & ~63) #ifdef DEBUG_USB static void dbprint_urb(struct urb *urb); @@ -3985,8 +3985,7 @@ static void hfa384x_usb_throttlefn(unsigned long data) pr_debug("flags=0x%lx\n", hw->usb_flags); if (!hw->wlandev->hwremoved && ((test_and_clear_bit(THROTTLE_RX, &hw->usb_flags) && - !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) - | + !test_and_set_bit(WORK_RX_RESUME, &hw->usb_flags)) | (test_and_clear_bit(THROTTLE_TX, &hw->usb_flags) && !test_and_set_bit(WORK_TX_RESUME, &hw->usb_flags)) )) { -- cgit From 57477bf0d9c2d311afe5a4e6b75040aabb3a426e Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Tue, 15 Dec 2015 23:29:32 +0800 Subject: staging: wlan-ng: use list_for_each_entry* Use list_for_each_entry*() instead of list_for_each*() to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/hfa384x_usb.c | 17 ++++------------- drivers/staging/wlan-ng/prism2usb.c | 15 +++------------ 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c index a5626df2bebc..682de77e7561 100644 --- a/drivers/staging/wlan-ng/hfa384x_usb.c +++ b/drivers/staging/wlan-ng/hfa384x_usb.c @@ -2810,8 +2810,7 @@ void hfa384x_tx_timeout(wlandevice_t *wlandev) static void hfa384x_usbctlx_reaper_task(unsigned long data) { hfa384x_t *hw = (hfa384x_t *)data; - struct list_head *entry; - struct list_head *temp; + hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; spin_lock_irqsave(&hw->ctlxq.lock, flags); @@ -2819,10 +2818,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) /* This list is guaranteed to be empty if someone * has unplugged the adapter. */ - list_for_each_safe(entry, temp, &hw->ctlxq.reapable) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_for_each_entry_safe(ctlx, temp, &hw->ctlxq.reapable, list) { list_del(&ctlx->list); kfree(ctlx); } @@ -2847,8 +2843,7 @@ static void hfa384x_usbctlx_reaper_task(unsigned long data) static void hfa384x_usbctlx_completion_task(unsigned long data) { hfa384x_t *hw = (hfa384x_t *)data; - struct list_head *entry; - struct list_head *temp; + hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; int reap = 0; @@ -2858,11 +2853,7 @@ static void hfa384x_usbctlx_completion_task(unsigned long data) /* This list is guaranteed to be empty if someone * has unplugged the adapter ... */ - list_for_each_safe(entry, temp, &hw->ctlxq.completing) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); - + list_for_each_entry_safe(ctlx, temp, &hw->ctlxq.completing, list) { /* Call the completion function that this * command was assigned, assuming it has one. */ diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c index 8abf3f87a2d5..194f67e0fc06 100644 --- a/drivers/staging/wlan-ng/prism2usb.c +++ b/drivers/staging/wlan-ng/prism2usb.c @@ -139,8 +139,7 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) wlandev = (wlandevice_t *)usb_get_intfdata(interface); if (wlandev != NULL) { LIST_HEAD(cleanlist); - struct list_head *entry; - struct list_head *temp; + hfa384x_usbctlx_t *ctlx, *temp; unsigned long flags; hfa384x_t *hw = wlandev->priv; @@ -184,12 +183,8 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) * and tell everyone who is waiting for their * responses that we have shut down. */ - list_for_each(entry, &cleanlist) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_for_each_entry(ctlx, &cleanlist, list) complete(&ctlx->done); - } /* Give any outstanding synchronous commands * a chance to complete. All they need to do @@ -199,12 +194,8 @@ static void prism2sta_disconnect_usb(struct usb_interface *interface) msleep(100); /* Now delete the CTLXs, because no-one else can now. */ - list_for_each_safe(entry, temp, &cleanlist) { - hfa384x_usbctlx_t *ctlx; - - ctlx = list_entry(entry, hfa384x_usbctlx_t, list); + list_for_each_entry_safe(ctlx, temp, &cleanlist, list) kfree(ctlx); - } /* Unhook the wlandev */ unregister_wlandev(wlandev); -- cgit From 78f5d21018f65d2208c645c84228bcdc3eb68367 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 2 Feb 2016 01:01:28 +0530 Subject: Staging:speakup:add space around '|' Fix checkpatch.pl check:CHECK: spaces preferred around that '|'. Add spaces around operands to fix these warnings. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/speakup_decext.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/speakup/speakup_decext.c b/drivers/staging/speakup/speakup_decext.c index fdd7488f554c..1a5cf3d0a559 100644 --- a/drivers/staging/speakup/speakup_decext.c +++ b/drivers/staging/speakup/speakup_decext.c @@ -67,30 +67,30 @@ static struct var_t vars[] = { * These attributes will appear in /sys/accessibility/speakup/decext. */ static struct kobj_attribute caps_start_attribute = - __ATTR(caps_start, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(caps_start, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute caps_stop_attribute = - __ATTR(caps_stop, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(caps_stop, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute pitch_attribute = - __ATTR(pitch, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(pitch, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute punct_attribute = - __ATTR(punct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(punct, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute rate_attribute = - __ATTR(rate, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(rate, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute voice_attribute = - __ATTR(voice, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(voice, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute vol_attribute = - __ATTR(vol, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(vol, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute delay_time_attribute = - __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(delay_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute direct_attribute = - __ATTR(direct, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(direct, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute full_time_attribute = - __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(full_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute jiffy_delta_attribute = - __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(jiffy_delta, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); static struct kobj_attribute trigger_time_attribute = - __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store); + __ATTR(trigger_time, S_IWUSR | S_IRUGO, spk_var_show, spk_var_store); /* * Create a group of attributes so that we can create and destroy them all -- cgit From 9b1b282ccd8195e3264dbb3cd15b9d60b6345230 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:19 -0600 Subject: irqdomain: Added domain bus token DOMAIN_BUS_FSL_MC_MSI Since an FSL-MC bus is a new bus type that is neither PCI nor PLATFORM, we need a new domain bus token to disambiguate the IRQ domain for FSL-MC MSIs. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- include/linux/irqdomain.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 04579d9fbce4..0934d06c8b00 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -74,6 +74,7 @@ enum irq_domain_bus_token { DOMAIN_BUS_PCI_MSI, DOMAIN_BUS_PLATFORM_MSI, DOMAIN_BUS_NEXUS, + DOMAIN_BUS_FSL_MC_MSI, }; /** -- cgit From 550308e48cddbc2aa74f7236941b17b55b2e78e9 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:20 -0600 Subject: fsl-mc: msi: Added FSL-MC-specific member to the msi_desc's union FSL-MC is a bus type different from PCI and platform, so it needs its own member in the msi_desc's union. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- include/linux/msi.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/msi.h b/include/linux/msi.h index a2a0068a8387..8b425c66305a 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -32,6 +32,14 @@ struct platform_msi_desc { u16 msi_index; }; +/** + * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data + * @msi_index: The index of the MSI descriptor + */ +struct fsl_mc_msi_desc { + u16 msi_index; +}; + /** * struct msi_desc - Descriptor structure for MSI based interrupts * @list: List head for management @@ -87,6 +95,7 @@ struct msi_desc { * tree wide cleanup. */ struct platform_msi_desc platform; + struct fsl_mc_msi_desc fsl_mc; }; }; -- cgit From 679c2c758c501c833a271a08aa4adbb601c42f63 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:21 -0600 Subject: staging: fsl-mc: Added generic MSI support for FSL-MC devices Created an MSI domain for the fsl-mc bus-- including functions to create a domain, find a domain, alloc/free domain irqs, and bus specific overrides for domain and irq_chip ops. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/Kconfig | 1 + drivers/staging/fsl-mc/bus/Makefile | 1 + drivers/staging/fsl-mc/bus/mc-msi.c | 276 ++++++++++++++++++++++++++++ drivers/staging/fsl-mc/include/dprc.h | 2 +- drivers/staging/fsl-mc/include/mc-private.h | 17 ++ drivers/staging/fsl-mc/include/mc.h | 17 ++ 6 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 drivers/staging/fsl-mc/bus/mc-msi.c diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig index 0d779d9ccbd8..c498ac6a72d5 100644 --- a/drivers/staging/fsl-mc/bus/Kconfig +++ b/drivers/staging/fsl-mc/bus/Kconfig @@ -9,6 +9,7 @@ config FSL_MC_BUS tristate "Freescale Management Complex (MC) bus driver" depends on OF && ARM64 + select GENERIC_MSI_IRQ_DOMAIN help Driver to enable the bus infrastructure for the Freescale QorIQ Management Complex (fsl-mc). The fsl-mc is a hardware diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index 25433a998478..a5f2ba4e6bf7 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -13,5 +13,6 @@ mc-bus-driver-objs := mc-bus.o \ dpmng.o \ dprc-driver.o \ mc-allocator.o \ + mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/mc-msi.c b/drivers/staging/fsl-mc/bus/mc-msi.c new file mode 100644 index 000000000000..3a8258ff4426 --- /dev/null +++ b/drivers/staging/fsl-mc/bus/mc-msi.c @@ -0,0 +1,276 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * 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/mc-private.h" +#include +#include +#include +#include +#include +#include +#include +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg, + struct msi_desc *desc) +{ + arg->desc = desc; + arg->hwirq = (irq_hw_number_t)desc->fsl_mc.msi_index; +} + +static void fsl_mc_msi_update_dom_ops(struct msi_domain_info *info) +{ + struct msi_domain_ops *ops = info->ops; + + if (WARN_ON(!ops)) + return; + + /* + * set_desc should not be set by the caller + */ + if (WARN_ON(ops->set_desc)) + return; + + ops->set_desc = fsl_mc_msi_set_desc; +} + +static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev, + struct fsl_mc_device_irq *mc_dev_irq) +{ + int error; + struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev; + struct msi_desc *msi_desc = mc_dev_irq->msi_desc; + struct dprc_irq_cfg irq_cfg; + + /* + * msi_desc->msg.address is 0x0 when this function is invoked in + * the free_irq() code path. In this case, for the MC, we don't + * really need to "unprogram" the MSI, so we just return. + */ + if (msi_desc->msg.address_lo == 0x0 && msi_desc->msg.address_hi == 0x0) + return; + + if (WARN_ON(!owner_mc_dev)) + return; + + irq_cfg.paddr = ((u64)msi_desc->msg.address_hi << 32) | + msi_desc->msg.address_lo; + irq_cfg.val = msi_desc->msg.data; + irq_cfg.user_irq_id = msi_desc->irq; + + if (owner_mc_dev == mc_bus_dev) { + /* + * IRQ is for the mc_bus_dev's DPRC itself + */ + error = dprc_set_irq(mc_bus_dev->mc_io, + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, + mc_bus_dev->mc_handle, + mc_dev_irq->dev_irq_index, + &irq_cfg); + if (error < 0) { + dev_err(&owner_mc_dev->dev, + "dprc_set_irq() failed: %d\n", error); + } + } else { + /* + * IRQ is for for a child device of mc_bus_dev + */ + error = dprc_set_obj_irq(mc_bus_dev->mc_io, + MC_CMD_FLAG_INTR_DIS | MC_CMD_FLAG_PRI, + mc_bus_dev->mc_handle, + owner_mc_dev->obj_desc.type, + owner_mc_dev->obj_desc.id, + mc_dev_irq->dev_irq_index, + &irq_cfg); + if (error < 0) { + dev_err(&owner_mc_dev->dev, + "dprc_obj_set_irq() failed: %d\n", error); + } + } +} + +/* + * NOTE: This function is invoked with interrupts disabled + */ +static void fsl_mc_msi_write_msg(struct irq_data *irq_data, + struct msi_msg *msg) +{ + struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data); + struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev); + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); + struct fsl_mc_device_irq *mc_dev_irq = + &mc_bus->irq_resources[msi_desc->fsl_mc.msi_index]; + + WARN_ON(mc_dev_irq->msi_desc != msi_desc); + msi_desc->msg = *msg; + + /* + * Program the MSI (paddr, value) pair in the device: + */ + __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq); +} + +static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info) +{ + struct irq_chip *chip = info->chip; + + if (WARN_ON((!chip))) + return; + + /* + * irq_write_msi_msg should not be set by the caller + */ + if (WARN_ON(chip->irq_write_msi_msg)) + return; + + chip->irq_write_msi_msg = fsl_mc_msi_write_msg; +} + +/** + * fsl_mc_msi_create_irq_domain - Create a fsl-mc MSI interrupt domain + * @np: Optional device-tree node of the interrupt controller + * @info: MSI domain info + * @parent: Parent irq domain + * + * Updates the domain and chip ops and creates a fsl-mc MSI + * interrupt domain. + * + * Returns: + * A domain pointer or NULL in case of failure. + */ +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, + struct msi_domain_info *info, + struct irq_domain *parent) +{ + struct irq_domain *domain; + + if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS) + fsl_mc_msi_update_dom_ops(info); + if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS) + fsl_mc_msi_update_chip_ops(info); + + domain = msi_create_irq_domain(fwnode, info, parent); + if (domain) + domain->bus_token = DOMAIN_BUS_FSL_MC_MSI; + + return domain; +} + +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, + struct irq_domain **mc_msi_domain) +{ + struct irq_domain *msi_domain; + struct device_node *mc_of_node = mc_platform_dev->of_node; + + msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node, + DOMAIN_BUS_FSL_MC_MSI); + if (!msi_domain) { + pr_err("Unable to find fsl-mc MSI domain for %s\n", + mc_of_node->full_name); + + return -ENOENT; + } + + *mc_msi_domain = msi_domain; + return 0; +} + +static void fsl_mc_msi_free_descs(struct device *dev) +{ + struct msi_desc *desc, *tmp; + + list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) { + list_del(&desc->list); + free_msi_entry(desc); + } +} + +static int fsl_mc_msi_alloc_descs(struct device *dev, unsigned int irq_count) + +{ + unsigned int i; + int error; + struct msi_desc *msi_desc; + + for (i = 0; i < irq_count; i++) { + msi_desc = alloc_msi_entry(dev); + if (!msi_desc) { + dev_err(dev, "Failed to allocate msi entry\n"); + error = -ENOMEM; + goto cleanup_msi_descs; + } + + msi_desc->fsl_mc.msi_index = i; + msi_desc->nvec_used = 1; + INIT_LIST_HEAD(&msi_desc->list); + list_add_tail(&msi_desc->list, dev_to_msi_list(dev)); + } + + return 0; + +cleanup_msi_descs: + fsl_mc_msi_free_descs(dev); + return error; +} + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count) +{ + struct irq_domain *msi_domain; + int error; + + if (WARN_ON(!list_empty(dev_to_msi_list(dev)))) + return -EINVAL; + + error = fsl_mc_msi_alloc_descs(dev, irq_count); + if (error < 0) + return error; + + msi_domain = dev_get_msi_domain(dev); + if (WARN_ON(!msi_domain)) { + error = -EINVAL; + goto cleanup_msi_descs; + } + + /* + * NOTE: Calling this function will trigger the invocation of the + * its_fsl_mc_msi_prepare() callback + */ + error = msi_domain_alloc_irqs(msi_domain, dev, irq_count); + + if (error) { + dev_err(dev, "Failed to allocate IRQs\n"); + goto cleanup_msi_descs; + } + + return 0; + +cleanup_msi_descs: + fsl_mc_msi_free_descs(dev); + return error; +} + +void fsl_mc_msi_domain_free_irqs(struct device *dev) +{ + struct irq_domain *msi_domain; + + msi_domain = dev_get_msi_domain(dev); + if (WARN_ON(!msi_domain)) + return; + + msi_domain_free_irqs(msi_domain, dev); + + if (WARN_ON(list_empty(dev_to_msi_list(dev)))) + return; + + fsl_mc_msi_free_descs(dev); +} diff --git a/drivers/staging/fsl-mc/include/dprc.h b/drivers/staging/fsl-mc/include/dprc.h index c3152f677ff1..94c492706315 100644 --- a/drivers/staging/fsl-mc/include/dprc.h +++ b/drivers/staging/fsl-mc/include/dprc.h @@ -176,7 +176,7 @@ int dprc_reset_container(struct fsl_mc_io *mc_io, * @user_irq_id: A user defined number associated with this IRQ */ struct dprc_irq_cfg { - u64 paddr; + phys_addr_t paddr; u32 val; int user_irq_id; }; diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index c706f778626e..36b418c23fd7 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -26,6 +26,9 @@ strcmp(_obj_type, "dpmcp") == 0 || \ strcmp(_obj_type, "dpcon") == 0) +struct irq_domain; +struct msi_domain_info; + /** * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device * @root_mc_bus_dev: MC object device representing the root DPRC @@ -79,11 +82,13 @@ struct fsl_mc_resource_pool { * @resource_pools: array of resource pools (one pool per resource type) * for this MC bus. These resources represent allocatable entities * from the physical DPRC. + * @irq_resources: Pointer to array of IRQ objects for the IRQ pool * @scan_mutex: Serializes bus scanning */ struct fsl_mc_bus { struct fsl_mc_device mc_dev; struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES]; + struct fsl_mc_device_irq *irq_resources; struct mutex scan_mutex; /* serializes bus scanning */ }; @@ -116,4 +121,16 @@ int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus, void fsl_mc_resource_free(struct fsl_mc_resource *resource); +struct irq_domain *fsl_mc_msi_create_irq_domain(struct fwnode_handle *fwnode, + struct msi_domain_info *info, + struct irq_domain *parent); + +int fsl_mc_find_msi_domain(struct device *mc_platform_dev, + struct irq_domain **mc_msi_domain); + +int fsl_mc_msi_domain_alloc_irqs(struct device *dev, + unsigned int irq_count); + +void fsl_mc_msi_domain_free_irqs(struct device *dev); + #endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index a933291e400a..1c1d6ae64996 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -103,6 +103,23 @@ struct fsl_mc_resource { struct list_head node; }; +/** + * struct fsl_mc_device_irq - MC object device message-based interrupt + * @msi_desc: pointer to MSI descriptor allocated by fsl_mc_msi_alloc_descs() + * @mc_dev: MC object device that owns this interrupt + * @dev_irq_index: device-relative IRQ index + * @resource: MC generic resource associated with the interrupt + */ +struct fsl_mc_device_irq { + struct msi_desc *msi_desc; + struct fsl_mc_device *mc_dev; + u8 dev_irq_index; + struct fsl_mc_resource resource; +}; + +#define to_fsl_mc_irq(_mc_resource) \ + container_of(_mc_resource, struct fsl_mc_device_irq, resource) + /** * Bit masks for a MC object device (struct fsl_mc_device) flags */ -- cgit From 3a288fd51b41a2998195c321d8dd4a229176e6f7 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:22 -0600 Subject: staging: fsl-mc: Added GICv3-ITS support for FSL-MC MSIs Added platform-specific MSI support layer for FSL-MC devices. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/Makefile | 1 + .../staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c | 127 +++++++++++++++++++++ drivers/staging/fsl-mc/include/mc-private.h | 4 + 3 files changed, 132 insertions(+) create mode 100644 drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile index a5f2ba4e6bf7..e7315170b7a3 100644 --- a/drivers/staging/fsl-mc/bus/Makefile +++ b/drivers/staging/fsl-mc/bus/Makefile @@ -14,5 +14,6 @@ mc-bus-driver-objs := mc-bus.o \ dprc-driver.o \ mc-allocator.o \ mc-msi.o \ + irq-gic-v3-its-fsl-mc-msi.o \ dpmcp.o \ dpbp.o diff --git a/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c new file mode 100644 index 000000000000..4e8e822da51d --- /dev/null +++ b/drivers/staging/fsl-mc/bus/irq-gic-v3-its-fsl-mc-msi.c @@ -0,0 +1,127 @@ +/* + * Freescale Management Complex (MC) bus driver MSI support + * + * Copyright (C) 2015 Freescale Semiconductor, Inc. + * Author: German Rivera + * + * 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/mc-private.h" +#include +#include +#include +#include +#include +#include +#include +#include "../include/mc-sys.h" +#include "dprc-cmd.h" + +static struct irq_chip its_msi_irq_chip = { + .name = "fsl-mc-bus-msi", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = msi_domain_set_affinity +}; + +static int its_fsl_mc_msi_prepare(struct irq_domain *msi_domain, + struct device *dev, + int nvec, msi_alloc_info_t *info) +{ + struct fsl_mc_device *mc_bus_dev; + struct msi_domain_info *msi_info; + + if (WARN_ON(dev->bus != &fsl_mc_bus_type)) + return -EINVAL; + + mc_bus_dev = to_fsl_mc_device(dev); + if (WARN_ON(!(mc_bus_dev->flags & FSL_MC_IS_DPRC))) + return -EINVAL; + + /* + * Set the device Id to be passed to the GIC-ITS: + * + * NOTE: This device id corresponds to the IOMMU stream ID + * associated with the DPRC object (ICID). + */ + info->scratchpad[0].ul = mc_bus_dev->icid; + msi_info = msi_get_domain_info(msi_domain->parent); + return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info); +} + +static struct msi_domain_ops its_fsl_mc_msi_ops = { + .msi_prepare = its_fsl_mc_msi_prepare, +}; + +static struct msi_domain_info its_fsl_mc_msi_domain_info = { + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), + .ops = &its_fsl_mc_msi_ops, + .chip = &its_msi_irq_chip, +}; + +static const struct of_device_id its_device_id[] = { + { .compatible = "arm,gic-v3-its", }, + {}, +}; + +int __init its_fsl_mc_msi_init(void) +{ + struct device_node *np; + struct irq_domain *parent; + struct irq_domain *mc_msi_domain; + + for (np = of_find_matching_node(NULL, its_device_id); np; + np = of_find_matching_node(np, its_device_id)) { + if (!of_property_read_bool(np, "msi-controller")) + continue; + + parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); + if (!parent || !msi_get_domain_info(parent)) { + pr_err("%s: unable to locate ITS domain\n", + np->full_name); + continue; + } + + mc_msi_domain = fsl_mc_msi_create_irq_domain( + of_node_to_fwnode(np), + &its_fsl_mc_msi_domain_info, + parent); + if (!mc_msi_domain) { + pr_err("%s: unable to create fsl-mc domain\n", + np->full_name); + continue; + } + + WARN_ON(mc_msi_domain-> + host_data != &its_fsl_mc_msi_domain_info); + + pr_info("fsl-mc MSI: %s domain created\n", np->full_name); + } + + return 0; +} + +void its_fsl_mc_msi_cleanup(void) +{ + struct device_node *np; + + for (np = of_find_matching_node(NULL, its_device_id); np; + np = of_find_matching_node(np, its_device_id)) { + struct irq_domain *mc_msi_domain = irq_find_matching_host( + np, + DOMAIN_BUS_FSL_MC_MSI); + + if (!of_property_read_bool(np, "msi-controller")) + continue; + + mc_msi_domain = irq_find_matching_host(np, + DOMAIN_BUS_FSL_MC_MSI); + if (mc_msi_domain && + mc_msi_domain->host_data == &its_fsl_mc_msi_domain_info) + irq_domain_remove(mc_msi_domain); + } +} diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index 36b418c23fd7..28c8d322b2a3 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -133,4 +133,8 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, void fsl_mc_msi_domain_free_irqs(struct device *dev); +int __init its_fsl_mc_msi_init(void); + +void its_fsl_mc_msi_cleanup(void); + #endif /* _FSL_MC_PRIVATE_H_ */ -- cgit From 89f067df928b9bfc53430b09aa4ac894f34f7340 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:23 -0600 Subject: staging: fsl-mc: Extended MC bus allocator to include IRQs All the IRQs for DPAA2 objects in the same DPRC must use the ICID of that DPRC, as their device Id in the GIC-ITS. Thus, all these IRQs must share the same ITT table in the GIC. As a result, a pool of IRQs with the same device Id must be preallocated per DPRC (fsl-mc bus instance). So, the fsl-mc bus object allocator is extended to also provide services to allocate IRQs to DPAA2 devices, from their parent fsl-mc bus IRQ pool. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/mc-allocator.c | 199 ++++++++++++++++++++++++++++ drivers/staging/fsl-mc/include/mc-private.h | 15 +++ drivers/staging/fsl-mc/include/mc.h | 9 ++ 3 files changed, 223 insertions(+) diff --git a/drivers/staging/fsl-mc/bus/mc-allocator.c b/drivers/staging/fsl-mc/bus/mc-allocator.c index 88d1857521a5..c5fa628411ec 100644 --- a/drivers/staging/fsl-mc/bus/mc-allocator.c +++ b/drivers/staging/fsl-mc/bus/mc-allocator.c @@ -15,6 +15,7 @@ #include "../include/dpcon-cmd.h" #include "dpmcp-cmd.h" #include "dpmcp.h" +#include /** * fsl_mc_resource_pool_add_device - add allocatable device to a resource @@ -160,6 +161,7 @@ static const char *const fsl_mc_pool_type_strings[] = { [FSL_MC_POOL_DPMCP] = "dpmcp", [FSL_MC_POOL_DPBP] = "dpbp", [FSL_MC_POOL_DPCON] = "dpcon", + [FSL_MC_POOL_IRQ] = "irq", }; static int __must_check object_type_to_pool_type(const char *object_type, @@ -465,6 +467,203 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev) } EXPORT_SYMBOL_GPL(fsl_mc_object_free); +/* + * Initialize the interrupt pool associated with a MC bus. + * It allocates a block of IRQs from the GIC-ITS + */ +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, + unsigned int irq_count) +{ + unsigned int i; + struct msi_desc *msi_desc; + struct fsl_mc_device_irq *irq_resources; + struct fsl_mc_device_irq *mc_dev_irq; + int error; + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + + if (WARN_ON(irq_count == 0 || + irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS)) + return -EINVAL; + + error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count); + if (error < 0) + return error; + + irq_resources = devm_kzalloc(&mc_bus_dev->dev, + sizeof(*irq_resources) * irq_count, + GFP_KERNEL); + if (!irq_resources) { + error = -ENOMEM; + goto cleanup_msi_irqs; + } + + for (i = 0; i < irq_count; i++) { + mc_dev_irq = &irq_resources[i]; + + /* + * NOTE: This mc_dev_irq's MSI addr/value pair will be set + * by the fsl_mc_msi_write_msg() callback + */ + mc_dev_irq->resource.type = res_pool->type; + mc_dev_irq->resource.data = mc_dev_irq; + mc_dev_irq->resource.parent_pool = res_pool; + INIT_LIST_HEAD(&mc_dev_irq->resource.node); + list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list); + } + + for_each_msi_entry(msi_desc, &mc_bus_dev->dev) { + mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index]; + mc_dev_irq->msi_desc = msi_desc; + mc_dev_irq->resource.id = msi_desc->irq; + } + + res_pool->max_count = irq_count; + res_pool->free_count = irq_count; + mc_bus->irq_resources = irq_resources; + return 0; + +cleanup_msi_irqs: + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool); + +/** + * Teardown the interrupt pool associated with an MC bus. + * It frees the IRQs that were allocated to the pool, back to the GIC-ITS. + */ +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus) +{ + struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev; + struct fsl_mc_resource_pool *res_pool = + &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + + if (WARN_ON(!mc_bus->irq_resources)) + return; + + if (WARN_ON(res_pool->max_count == 0)) + return; + + if (WARN_ON(res_pool->free_count != res_pool->max_count)) + return; + + INIT_LIST_HEAD(&res_pool->free_list); + res_pool->max_count = 0; + res_pool->free_count = 0; + mc_bus->irq_resources = NULL; + fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev); +} +EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool); + +/** + * It allocates the IRQs required by a given MC object device. The + * IRQs are allocated from the interrupt pool associated with the + * MC bus that contains the device, if the device is not a DPRC device. + * Otherwise, the IRQs are allocated from the interrupt pool associated + * with the MC bus that represents the DPRC device itself. + */ +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev) +{ + int i; + int irq_count; + int res_allocated_count = 0; + int error = -EINVAL; + struct fsl_mc_device_irq **irqs = NULL; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_resource_pool *res_pool; + + if (WARN_ON(mc_dev->irqs)) + return -EINVAL; + + irq_count = mc_dev->obj_desc.irq_count; + if (WARN_ON(irq_count == 0)) + return -EINVAL; + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + mc_bus = to_fsl_mc_bus(mc_dev); + else + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); + + if (WARN_ON(!mc_bus->irq_resources)) + return -EINVAL; + + res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ]; + if (res_pool->free_count < irq_count) { + dev_err(&mc_dev->dev, + "Not able to allocate %u irqs for device\n", irq_count); + return -ENOSPC; + } + + irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]), + GFP_KERNEL); + if (!irqs) + return -ENOMEM; + + for (i = 0; i < irq_count; i++) { + struct fsl_mc_resource *resource; + + error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ, + &resource); + if (error < 0) + goto error_resource_alloc; + + irqs[i] = to_fsl_mc_irq(resource); + res_allocated_count++; + + WARN_ON(irqs[i]->mc_dev); + irqs[i]->mc_dev = mc_dev; + irqs[i]->dev_irq_index = i; + } + + mc_dev->irqs = irqs; + return 0; + +error_resource_alloc: + for (i = 0; i < res_allocated_count; i++) { + irqs[i]->mc_dev = NULL; + fsl_mc_resource_free(&irqs[i]->resource); + } + + return error; +} +EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs); + +/* + * It frees the IRQs that were allocated for a MC object device, by + * returning them to the corresponding interrupt pool. + */ +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev) +{ + int i; + int irq_count; + struct fsl_mc_bus *mc_bus; + struct fsl_mc_device_irq **irqs = mc_dev->irqs; + + if (WARN_ON(!irqs)) + return; + + irq_count = mc_dev->obj_desc.irq_count; + + if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) + mc_bus = to_fsl_mc_bus(mc_dev); + else + mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent)); + + if (WARN_ON(!mc_bus->irq_resources)) + return; + + for (i = 0; i < irq_count; i++) { + WARN_ON(!irqs[i]->mc_dev); + irqs[i]->mc_dev = NULL; + fsl_mc_resource_free(&irqs[i]->resource); + } + + mc_dev->irqs = NULL; +} +EXPORT_SYMBOL_GPL(fsl_mc_free_irqs); + /** * fsl_mc_allocator_probe - callback invoked when an allocatable device is * being added to the system diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index 28c8d322b2a3..3babe92d8abc 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -29,6 +29,16 @@ struct irq_domain; struct msi_domain_info; +/** + * Maximum number of total IRQs that can be pre-allocated for an MC bus' + * IRQ pool + */ +#define FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS 256 + +struct device_node; +struct irq_domain; +struct msi_domain_info; + /** * struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device * @root_mc_bus_dev: MC object device representing the root DPRC @@ -137,4 +147,9 @@ int __init its_fsl_mc_msi_init(void); void its_fsl_mc_msi_cleanup(void); +int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus, + unsigned int irq_count); + +void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus); + #endif /* _FSL_MC_PRIVATE_H_ */ diff --git a/drivers/staging/fsl-mc/include/mc.h b/drivers/staging/fsl-mc/include/mc.h index 1c1d6ae64996..ac7c1ce68c03 100644 --- a/drivers/staging/fsl-mc/include/mc.h +++ b/drivers/staging/fsl-mc/include/mc.h @@ -14,12 +14,14 @@ #include #include #include +#include #include "../include/dprc.h" #define FSL_MC_VENDOR_FREESCALE 0x1957 struct fsl_mc_device; struct fsl_mc_io; +struct fsl_mc_bus; /** * struct fsl_mc_driver - MC object device driver object @@ -75,6 +77,7 @@ enum fsl_mc_pool_type { FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */ FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */ FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */ + FSL_MC_POOL_IRQ, /* * NOTE: New resource pool types must be added before this entry @@ -141,6 +144,7 @@ struct fsl_mc_device_irq { * NULL if none. * @obj_desc: MC description of the DPAA device * @regions: pointer to array of MMIO region entries + * @irqs: pointer to array of pointers to interrupts allocated to this device * @resource: generic resource associated with this MC object device, if any. * * Generic device object for MC object devices that are "attached" to a @@ -172,6 +176,7 @@ struct fsl_mc_device { struct fsl_mc_io *mc_io; struct dprc_obj_desc obj_desc; struct resource *regions; + struct fsl_mc_device_irq **irqs; struct fsl_mc_resource *resource; }; @@ -215,6 +220,10 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, void fsl_mc_object_free(struct fsl_mc_device *mc_adev); +int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev); + +void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev); + extern struct bus_type fsl_mc_bus_type; #endif /* _FSL_MC_H_ */ -- cgit From 1129cde59d08afd91fb2baed66824eb2dbd079aa Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:24 -0600 Subject: staging: fsl-mc: Changed DPRC built-in portal's mc_io to be atomic The DPRC built-in portal's mc_io is used to send commands to the MC to program MSIs for MC objects. This is done by the fsl_mc_msi_write_msg() callback, which is invoked by the generic MSI layer with interrupts disabled. As a result, the mc_io used in fsl_mc_msi_write_msg needs to be an atomic mc_io. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 4 +++- drivers/staging/fsl-mc/bus/mc-bus.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 2c4cd70b4cbb..767d437837e7 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -396,7 +396,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) error = fsl_create_mc_io(&mc_dev->dev, mc_dev->regions[0].start, region_size, - NULL, 0, &mc_dev->mc_io); + NULL, + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, + &mc_dev->mc_io); if (error < 0) return error; } diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index 84db55b4dda5..d34f1af39746 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -702,7 +702,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev) mc_portal_phys_addr = res.start; mc_portal_size = resource_size(&res); error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, - mc_portal_size, NULL, 0, &mc_io); + mc_portal_size, NULL, + FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); if (error < 0) return error; -- cgit From 1e4aa42aa9a16d3ec2bbbf7e7d946603b52217de Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:25 -0600 Subject: staging: fsl-mc: Populate the IRQ pool for an MC bus instance Scan the corresponding DPRC container to get total count of IRQs needed by all its child DPAA2 objects. Then, preallocate a set of MSI IRQs with the DPRC's ICID (GIT-ITS device Id) to populate the the DPRC's IRQ pool. Each child DPAA2 object in the DPRC and the DPRC object itself will allocate their necessary MSI IRQs from the DPRC's IRQ pool, in their driver probe function. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 24 ++++++++++++++++++++++-- drivers/staging/fsl-mc/include/mc-private.h | 3 ++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 767d437837e7..ef1bb9315c4c 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -241,6 +241,7 @@ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) * dprc_scan_objects - Discover objects in a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object + * @total_irq_count: total number of IRQs needed by objects in the DPRC. * * Detects objects added and removed from a DPRC and synchronizes the * state of the Linux bus driver, MC by adding and removing @@ -254,11 +255,13 @@ static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev) * populated before they can get allocation requests from probe callbacks * of the device drivers for the non-allocatable devices. */ -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + unsigned int *total_irq_count) { int num_child_objects; int dprc_get_obj_failures; int error; + unsigned int irq_count = mc_bus_dev->obj_desc.irq_count; struct dprc_obj_desc *child_obj_desc_array = NULL; error = dprc_get_obj_count(mc_bus_dev->mc_io, @@ -307,6 +310,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) continue; } + irq_count += obj_desc->irq_count; dev_dbg(&mc_bus_dev->dev, "Discovered object: type %s, id %d\n", obj_desc->type, obj_desc->id); @@ -319,6 +323,7 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev) } } + *total_irq_count = irq_count; dprc_remove_devices(mc_bus_dev, child_obj_desc_array, num_child_objects); @@ -344,6 +349,7 @@ EXPORT_SYMBOL_GPL(dprc_scan_objects); int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) { int error; + unsigned int irq_count; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev); dprc_init_all_resource_pools(mc_bus_dev); @@ -352,11 +358,25 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev) * Discover objects in the DPRC: */ mutex_lock(&mc_bus->scan_mutex); - error = dprc_scan_objects(mc_bus_dev); + error = dprc_scan_objects(mc_bus_dev, &irq_count); mutex_unlock(&mc_bus->scan_mutex); if (error < 0) goto error; + if (dev_get_msi_domain(&mc_bus_dev->dev) && !mc_bus->irq_resources) { + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { + dev_warn(&mc_bus_dev->dev, + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + } + + error = fsl_mc_populate_irq_pool( + mc_bus, + FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + if (error < 0) + goto error; + } + return 0; error: dprc_cleanup_all_resource_pools(mc_bus_dev); diff --git a/drivers/staging/fsl-mc/include/mc-private.h b/drivers/staging/fsl-mc/include/mc-private.h index 3babe92d8abc..be72a44ba064 100644 --- a/drivers/staging/fsl-mc/include/mc-private.h +++ b/drivers/staging/fsl-mc/include/mc-private.h @@ -114,7 +114,8 @@ void fsl_mc_device_remove(struct fsl_mc_device *mc_dev); int dprc_scan_container(struct fsl_mc_device *mc_bus_dev); -int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev); +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev, + unsigned int *total_irq_count); int __init dprc_driver_init(void); -- cgit From 232ae8f2494e3ba445e7f07705f5c3296102bb4c Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:26 -0600 Subject: staging: fsl-mc: set MSI domain for DPRC objects THE MSI domain associated with a root DPRC object is obtained form the device tree. Child DPRCs inherit the parent DPRC MSI domain. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index ef1bb9315c4c..38fc404fde4f 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -13,6 +13,7 @@ #include "../include/mc-sys.h" #include #include +#include #include "dprc-cmd.h" struct dprc_child_objs { @@ -398,11 +399,16 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) { int error; size_t region_size; + struct device *parent_dev = mc_dev->dev.parent; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + bool msi_domain_set = false; if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; + if (WARN_ON(dev_get_msi_domain(&mc_dev->dev))) + return -EINVAL; + if (!mc_dev->mc_io) { /* * This is a child DPRC: @@ -421,6 +427,30 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) &mc_dev->mc_io); if (error < 0) return error; + /* + * Inherit parent MSI domain: + */ + dev_set_msi_domain(&mc_dev->dev, + dev_get_msi_domain(parent_dev)); + msi_domain_set = true; + } else { + /* + * This is a root DPRC + */ + struct irq_domain *mc_msi_domain; + + if (WARN_ON(parent_dev->bus == &fsl_mc_bus_type)) + return -EINVAL; + + error = fsl_mc_find_msi_domain(parent_dev, + &mc_msi_domain); + if (error < 0) { + dev_warn(&mc_dev->dev, + "WARNING: MC bus without interrupt support\n"); + } else { + dev_set_msi_domain(&mc_dev->dev, mc_msi_domain); + msi_domain_set = true; + } } error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id, @@ -446,6 +476,9 @@ error_cleanup_open: (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); error_cleanup_mc_io: + if (msi_domain_set) + dev_set_msi_domain(&mc_dev->dev, NULL); + fsl_destroy_mc_io(mc_dev->mc_io); return error; } @@ -463,6 +496,7 @@ error_cleanup_mc_io: static int dprc_remove(struct fsl_mc_device *mc_dev) { int error; + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) return -EINVAL; @@ -475,6 +509,11 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) if (error < 0) dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error); + if (dev_get_msi_domain(&mc_dev->dev)) { + fsl_mc_cleanup_irq_pool(mc_bus); + dev_set_msi_domain(&mc_dev->dev, NULL); + } + dev_info(&mc_dev->dev, "DPRC device unbound from driver"); return 0; } -- cgit From 8804f9fc5cf38c29c56f041341685edfc623f427 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:27 -0600 Subject: staging: fsl-mc: Fixed bug in dprc_probe() error path Destroy mc_io in error path in dprc_probe() only if the mc_io was created in this function. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 38fc404fde4f..42b249404632 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -401,6 +401,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) size_t region_size; struct device *parent_dev = mc_dev->dev.parent; struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + bool mc_io_created = false; bool msi_domain_set = false; if (WARN_ON(strcmp(mc_dev->obj_desc.type, "dprc") != 0)) @@ -413,6 +414,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) /* * This is a child DPRC: */ + if (WARN_ON(parent_dev->bus != &fsl_mc_bus_type)) + return -EINVAL; + if (WARN_ON(mc_dev->obj_desc.region_count == 0)) return -EINVAL; @@ -427,6 +431,9 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) &mc_dev->mc_io); if (error < 0) return error; + + mc_io_created = true; + /* * Inherit parent MSI domain: */ @@ -457,7 +464,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) &mc_dev->mc_handle); if (error < 0) { dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error); - goto error_cleanup_mc_io; + goto error_cleanup_msi_domain; } mutex_init(&mc_bus->scan_mutex); @@ -475,11 +482,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) error_cleanup_open: (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -error_cleanup_mc_io: +error_cleanup_msi_domain: if (msi_domain_set) dev_set_msi_domain(&mc_dev->dev, NULL); - fsl_destroy_mc_io(mc_dev->mc_io); + if (mc_io_created) { + fsl_destroy_mc_io(mc_dev->mc_io); + mc_dev->mc_io = NULL; + } + return error; } -- cgit From f52dee5ccdf57364299448c88787ff92656d1ed2 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:28 -0600 Subject: staging: fsl-mc: Added DPRC interrupt handler The interrupt handler for DPRC IRQs is added. DPRC IRQs are generated for hot plug events related to DPAA2 objects in a given DPRC. These events include, creating/destroying DPAA2 objects in the DPRC, changing the "plugged" state of DPAA2 objects and moving objects between DPRCs. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 247 +++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 42b249404632..52c6fce0fd29 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "dprc-cmd.h" struct dprc_child_objs { @@ -385,6 +386,230 @@ error: } EXPORT_SYMBOL_GPL(dprc_scan_container); +/** + * dprc_irq0_handler - Regular ISR for DPRC interrupt 0 + * + * @irq: IRQ number of the interrupt being handled + * @arg: Pointer to device structure + */ +static irqreturn_t dprc_irq0_handler(int irq_num, void *arg) +{ + return IRQ_WAKE_THREAD; +} + +/** + * dprc_irq0_handler_thread - Handler thread function for DPRC interrupt 0 + * + * @irq: IRQ number of the interrupt being handled + * @arg: Pointer to device structure + */ +static irqreturn_t dprc_irq0_handler_thread(int irq_num, void *arg) +{ + int error; + u32 status; + struct device *dev = (struct device *)arg; + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev); + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev); + struct fsl_mc_io *mc_io = mc_dev->mc_io; + struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc; + + dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n", + irq_num, smp_processor_id()); + + if (WARN_ON(!(mc_dev->flags & FSL_MC_IS_DPRC))) + return IRQ_HANDLED; + + mutex_lock(&mc_bus->scan_mutex); + if (WARN_ON(!msi_desc || msi_desc->irq != (u32)irq_num)) + goto out; + + error = dprc_get_irq_status(mc_io, 0, mc_dev->mc_handle, 0, + &status); + if (error < 0) { + dev_err(dev, + "dprc_get_irq_status() failed: %d\n", error); + goto out; + } + + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, + status); + if (error < 0) { + dev_err(dev, + "dprc_clear_irq_status() failed: %d\n", error); + goto out; + } + + if (status & (DPRC_IRQ_EVENT_OBJ_ADDED | + DPRC_IRQ_EVENT_OBJ_REMOVED | + DPRC_IRQ_EVENT_CONTAINER_DESTROYED | + DPRC_IRQ_EVENT_OBJ_DESTROYED | + DPRC_IRQ_EVENT_OBJ_CREATED)) { + unsigned int irq_count; + + error = dprc_scan_objects(mc_dev, &irq_count); + if (error < 0) { + /* + * If the error is -ENXIO, we ignore it, as it indicates + * that the object scan was aborted, as we detected that + * an object was removed from the DPRC in the MC, while + * we were scanning the DPRC. + */ + if (error != -ENXIO) { + dev_err(dev, "dprc_scan_objects() failed: %d\n", + error); + } + + goto out; + } + + if (irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS) { + dev_warn(dev, + "IRQs needed (%u) exceed IRQs preallocated (%u)\n", + irq_count, FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS); + } + } + +out: + mutex_unlock(&mc_bus->scan_mutex); + return IRQ_HANDLED; +} + +/* + * Disable and clear interrupt for a given DPRC object + */ +static int disable_dprc_irq(struct fsl_mc_device *mc_dev) +{ + int error; + struct fsl_mc_io *mc_io = mc_dev->mc_io; + + WARN_ON(mc_dev->obj_desc.irq_count != 1); + + /* + * Disable generation of interrupt, while we configure it: + */ + error = dprc_set_irq_enable(mc_io, 0, mc_dev->mc_handle, 0, 0); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", + error); + return error; + } + + /* + * Disable all interrupt causes for the interrupt: + */ + error = dprc_set_irq_mask(mc_io, 0, mc_dev->mc_handle, 0, 0x0); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", + error); + return error; + } + + /* + * Clear any leftover interrupts: + */ + error = dprc_clear_irq_status(mc_io, 0, mc_dev->mc_handle, 0, ~0x0U); + if (error < 0) { + dev_err(&mc_dev->dev, + "Disabling DPRC IRQ failed: dprc_clear_irq_status() failed: %d\n", + error); + return error; + } + + return 0; +} + +static int register_dprc_irq_handler(struct fsl_mc_device *mc_dev) +{ + int error; + struct fsl_mc_device_irq *irq = mc_dev->irqs[0]; + + WARN_ON(mc_dev->obj_desc.irq_count != 1); + + /* + * NOTE: devm_request_threaded_irq() invokes the device-specific + * function that programs the MSI physically in the device + */ + error = devm_request_threaded_irq(&mc_dev->dev, + irq->msi_desc->irq, + dprc_irq0_handler, + dprc_irq0_handler_thread, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + "FSL MC DPRC irq0", + &mc_dev->dev); + if (error < 0) { + dev_err(&mc_dev->dev, + "devm_request_threaded_irq() failed: %d\n", + error); + return error; + } + + return 0; +} + +static int enable_dprc_irq(struct fsl_mc_device *mc_dev) +{ + int error; + + /* + * Enable all interrupt causes for the interrupt: + */ + error = dprc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, + ~0x0u); + if (error < 0) { + dev_err(&mc_dev->dev, + "Enabling DPRC IRQ failed: dprc_set_irq_mask() failed: %d\n", + error); + + return error; + } + + /* + * Enable generation of the interrupt: + */ + error = dprc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle, 0, 1); + if (error < 0) { + dev_err(&mc_dev->dev, + "Enabling DPRC IRQ failed: dprc_set_irq_enable() failed: %d\n", + error); + + return error; + } + + return 0; +} + +/* + * Setup interrupt for a given DPRC device + */ +static int dprc_setup_irq(struct fsl_mc_device *mc_dev) +{ + int error; + + error = fsl_mc_allocate_irqs(mc_dev); + if (error < 0) + return error; + + error = disable_dprc_irq(mc_dev); + if (error < 0) + goto error_free_irqs; + + error = register_dprc_irq_handler(mc_dev); + if (error < 0) + goto error_free_irqs; + + error = enable_dprc_irq(mc_dev); + if (error < 0) + goto error_free_irqs; + + return 0; + +error_free_irqs: + fsl_mc_free_irqs(mc_dev); + return error; +} + /** * dprc_probe - callback invoked when a DPRC is being bound to this driver * @@ -476,6 +701,13 @@ static int dprc_probe(struct fsl_mc_device *mc_dev) if (error < 0) goto error_cleanup_open; + /* + * Configure interrupt for the DPRC object associated with this MC bus: + */ + error = dprc_setup_irq(mc_dev); + if (error < 0) + goto error_cleanup_open; + dev_info(&mc_dev->dev, "DPRC device bound to driver"); return 0; @@ -494,6 +726,15 @@ error_cleanup_msi_domain: return error; } +/* + * Tear down interrupt for a given DPRC object + */ +static void dprc_teardown_irq(struct fsl_mc_device *mc_dev) +{ + (void)disable_dprc_irq(mc_dev); + fsl_mc_free_irqs(mc_dev); +} + /** * dprc_remove - callback invoked when a DPRC is being unbound from this driver * @@ -514,6 +755,12 @@ static int dprc_remove(struct fsl_mc_device *mc_dev) if (WARN_ON(!mc_dev->mc_io)) return -EINVAL; + if (WARN_ON(!mc_bus->irq_resources)) + return -EINVAL; + + if (dev_get_msi_domain(&mc_dev->dev)) + dprc_teardown_irq(mc_dev); + device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove); dprc_cleanup_all_resource_pools(mc_dev); error = dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle); -- cgit From 660a24bf60821ce9f5799b0772a0a82c922c72c1 Mon Sep 17 00:00:00 2001 From: "J. German Rivera" Date: Wed, 6 Jan 2016 16:03:29 -0600 Subject: staging: fsl-mc: Added MSI support to the MC bus driver Initialize/Cleanup ITS-MSI support for the MC bus driver at driver init/exit time. Associate an MSI domain with each DPAA2 child device. Signed-off-by: J. German Rivera Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/mc-bus.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/fsl-mc/bus/mc-bus.c b/drivers/staging/fsl-mc/bus/mc-bus.c index d34f1af39746..9317561973b1 100644 --- a/drivers/staging/fsl-mc/bus/mc-bus.c +++ b/drivers/staging/fsl-mc/bus/mc-bus.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include "../include/dpmng.h" #include "../include/mc-sys.h" #include "dprc-cmd.h" @@ -472,6 +474,8 @@ int fsl_mc_device_add(struct dprc_obj_desc *obj_desc, mc_dev->icid = parent_mc_dev->icid; mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK; mc_dev->dev.dma_mask = &mc_dev->dma_mask; + dev_set_msi_domain(&mc_dev->dev, + dev_get_msi_domain(&parent_mc_dev->dev)); } /* @@ -833,8 +837,15 @@ static int __init fsl_mc_bus_driver_init(void) if (error < 0) goto error_cleanup_dprc_driver; + error = its_fsl_mc_msi_init(); + if (error < 0) + goto error_cleanup_mc_allocator; + return 0; +error_cleanup_mc_allocator: + fsl_mc_allocator_driver_exit(); + error_cleanup_dprc_driver: dprc_driver_exit(); @@ -856,6 +867,7 @@ static void __exit fsl_mc_bus_driver_exit(void) if (WARN_ON(!mc_dev_cache)) return; + its_fsl_mc_msi_cleanup(); fsl_mc_allocator_driver_exit(); dprc_driver_exit(); platform_driver_unregister(&fsl_mc_bus_driver); -- cgit From 5c229d00a58df469550dbc1f4e3a360eb8958661 Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 3 Feb 2016 11:55:34 +0100 Subject: dmaengine: sh: 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 Signed-off-by: Vinod Koul --- drivers/dma/sh/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma/sh/Kconfig b/drivers/dma/sh/Kconfig index f32c430eb16c..6e0685f1a838 100644 --- a/drivers/dma/sh/Kconfig +++ b/drivers/dma/sh/Kconfig @@ -12,7 +12,7 @@ config RENESAS_DMA config SH_DMAE_BASE bool "Renesas SuperH DMA Engine support" - depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST + depends on SUPERH || ARCH_RENESAS || COMPILE_TEST depends on !SUPERH || SH_DMA depends on !SH_DMA_API default y @@ -41,7 +41,7 @@ endif config RCAR_DMAC tristate "Renesas R-Car Gen2 DMA Controller" - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST select RENESAS_DMA help This driver supports the general purpose DMA controller found in the @@ -49,7 +49,7 @@ config RCAR_DMAC config RENESAS_USB_DMAC tristate "Renesas USB-DMA Controller" - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST select RENESAS_DMA select DMA_VIRTUAL_CHANNELS help -- cgit From 5a89a875c96a9d038715c42f5f712002ce5124d0 Mon Sep 17 00:00:00 2001 From: Hamish Martin Date: Tue, 22 Dec 2015 10:23:58 +1300 Subject: staging: octeon-ethernet: fix TCP/UDP checksum calc If the network portion of a frame is preceded by more than 14 bytes of data, the checksum calculated in the HW is done over the wrong data and is put in the wrong place. In our use case an Octeon ethernet controller is connected to a Broadcom switch chip. Extra data is included in the frame prior to egressing the Octeon ethernet (i.e. 4 bytes of an 802.1Q tag, 4 bytes of a proprietary BCM tag later stripped by the switch chip). This extra data causes the checksum calculation to be incorrect. The fix in this patch is to make use of the network header offset of the skb. This enables the checksum to be calculated correctly. This has been tested in both the configuration with the switch chip in the egress path (as described above) and in a simple connection direct to the wire. Reviewed-by: Richard Laing Reviewed-by: Tim Beale Reviewed-by: Chris Packham Signed-off-by: Hamish Martin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index c053c4a47a7e..5611a0269aa8 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -403,7 +403,7 @@ dont_put_skbuff_in_hw: ((ip_hdr(skb)->protocol == IPPROTO_TCP) || (ip_hdr(skb)->protocol == IPPROTO_UDP))) { /* Use hardware checksum calc */ - pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; + pko_command.s.ipoffp1 = skb_network_offset(skb) + 1; } if (USE_ASYNC_IOBDMA) { -- cgit From 7c0b6bce6e848a59cd15d1ade9db346d34d90c5a Mon Sep 17 00:00:00 2001 From: Luuk Paulussen Date: Wed, 23 Dec 2015 09:51:14 +1300 Subject: staging: octeon: Fix logic for waking octeon ethernet tx queue. Only wake tx queue when driver queue is back within bounds. The logic here was just reenabling the queue when any buffers had been freed. the queue was stopped whenever the length exceeded 1000 (MAX_OUT_QUEUE_DEPTH), but then was essentially immediately started again. On a congested link, the queue length would just keep increasing up to around 8000 (for average size packets), at which point the hardware would start refusing the packets and they would begin to be dropped. This prevented the qdisc layer from effectively managing and prioritising packets, as essentially all packets were being allowed into the driver queue and then were being dropped by the hardware. This change only restarts the queue if the length is less than 1000 (MAX_OUT_QUEUE_DEPTH). Reviewed-by: Kyeong Yoo Reviewed-by: Chris Packham Reviewed-by: Richard Laing Signed-off-by: Luuk Paulussen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 5611a0269aa8..82abaeca27a7 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -126,7 +126,7 @@ static void cvm_oct_free_tx_skbs(struct net_device *dev) } total_remaining += skb_queue_len(&priv->tx_free_list[qos]); } - if (total_freed >= 0 && netif_queue_stopped(dev)) + if (total_remaining < MAX_OUT_QUEUE_DEPTH && netif_queue_stopped(dev)) netif_wake_queue(dev); if (total_remaining) cvm_oct_kick_tx_poll_watchdog(); -- cgit From edb0d9d4a3fe65cb08dab750b4ad6c2ae5d65d50 Mon Sep 17 00:00:00 2001 From: Saatvik Arya Date: Sun, 3 Jan 2016 22:42:40 +0530 Subject: drivers: staging: octeon-usb: octeon-hcd.c: fixed coding style related warnings fixed coding style warnings related to comment blocks Signed-off-by: Saatvik Arya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/octeon-hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 6f2871784ba5..16d45879d0c4 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -2006,7 +2006,8 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, urb->hcpriv = NULL; /* For Isochronous transactions we need to update the URB packet status - list from data in our private copy */ + * list from data in our private copy + */ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { int i; /* -- cgit From a6fccdb5078e1d78df0066b7746cd06c32bc2cb8 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Wed, 3 Feb 2016 01:08:03 +0530 Subject: Staging:octeon:removed blank line after { Removed blank line after curly braces. Found using checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-rgmii.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 1055ee14b66a..9353796af0b6 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -247,9 +247,7 @@ int cvm_oct_rgmii_init(struct net_device *dev) if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - if (!octeon_is_simulation()) { - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; int interface = INTERFACE(priv->port); int index = INDEX(priv->port); @@ -283,9 +281,7 @@ void cvm_oct_rgmii_uninit(struct net_device *dev) if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) && (priv->port == 0)) || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - if (!octeon_is_simulation()) { - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; int interface = INTERFACE(priv->port); int index = INDEX(priv->port); -- cgit From 3dd0af86a05d112c72cf4d9353ed725202ed67db Mon Sep 17 00:00:00 2001 From: Bogicevic Sasa Date: Fri, 13 Nov 2015 14:55:47 +0100 Subject: drivers:staging:fwserial Fix No space is necessary after a cast This fixes all "No space is necessary after a cast" messages Signed-off-by: Bogicevic Sasa Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/fwserial.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index e481d3230f86..9b23b5c95f5e 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -1464,9 +1464,9 @@ static void fwtty_debugfs_show_peer(struct seq_file *m, struct fwtty_peer *peer) seq_printf(m, " %s:", dev_name(&peer->unit->device)); seq_printf(m, " node:%04x gen:%d", peer->node_id, generation); seq_printf(m, " sp:%d max:%d guid:%016llx", peer->speed, - peer->max_payload, (unsigned long long) peer->guid); - seq_printf(m, " mgmt:%012llx", (unsigned long long) peer->mgmt_addr); - seq_printf(m, " addr:%012llx", (unsigned long long) peer->status_addr); + peer->max_payload, (unsigned long long)peer->guid); + seq_printf(m, " mgmt:%012llx", (unsigned long long)peer->mgmt_addr); + seq_printf(m, " addr:%012llx", (unsigned long long)peer->status_addr); seq_putc(m, '\n'); } @@ -1513,7 +1513,7 @@ static int fwtty_debugfs_peers_show(struct seq_file *m, void *v) rcu_read_lock(); seq_printf(m, "card: %s guid: %016llx\n", dev_name(serial->card->device), - (unsigned long long) serial->card->guid); + (unsigned long long)serial->card->guid); list_for_each_entry_rcu(peer, &serial->peer_list, list) fwtty_debugfs_show_peer(m, peer); rcu_read_unlock(); @@ -1985,7 +1985,7 @@ static struct fwtty_peer *__fwserial_peer_by_node_id(struct fw_card *card, * been probed for any unit devices... */ fwtty_err(card, "unknown card (guid %016llx)\n", - (unsigned long long) card->guid); + (unsigned long long)card->guid); return NULL; } @@ -2015,7 +2015,7 @@ static void __dump_peer_list(struct fw_card *card) smp_rmb(); fwtty_dbg(card, "peer(%d:%x) guid: %016llx\n", - g, peer->node_id, (unsigned long long) peer->guid); + g, peer->node_id, (unsigned long long)peer->guid); } } #else @@ -2312,7 +2312,7 @@ static int fwserial_create(struct fw_unit *unit) list_add_rcu(&serial->list, &fwserial_list); fwtty_notice(&unit, "TTY over FireWire on device %s (guid %016llx)\n", - dev_name(card->device), (unsigned long long) card->guid); + dev_name(card->device), (unsigned long long)card->guid); err = fwserial_add_peer(serial, unit); if (!err) -- cgit From de593dca1b6b4a932d465214dab311d5daacfa76 Mon Sep 17 00:00:00 2001 From: Christian Colic Date: Tue, 17 Nov 2015 13:56:31 +0100 Subject: staging: fwserial: (coding-style) rewrite comparisons to NULL as "!fifo->data" Rewrite multiple comparisons to NULL as "!fifo->data" to fix the last coding style problems of this file. Signed-off-by: Christian Colic Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fwserial/dma_fifo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/fwserial/dma_fifo.c b/drivers/staging/fwserial/dma_fifo.c index 7a3347c3d02b..4cd3ed3ee141 100644 --- a/drivers/staging/fwserial/dma_fifo.c +++ b/drivers/staging/fwserial/dma_fifo.c @@ -106,7 +106,7 @@ void dma_fifo_free(struct dma_fifo *fifo) { struct dma_pending *pending, *next; - if (fifo->data == NULL) + if (!fifo->data) return; list_for_each_entry_safe(pending, next, &fifo->pending, link) @@ -123,7 +123,7 @@ void dma_fifo_reset(struct dma_fifo *fifo) { struct dma_pending *pending, *next; - if (fifo->data == NULL) + if (!fifo->data) return; list_for_each_entry_safe(pending, next, &fifo->pending, link) @@ -149,7 +149,7 @@ int dma_fifo_in(struct dma_fifo *fifo, const void *src, int n) { int ofs, l; - if (fifo->data == NULL) + if (!fifo->data) return -ENOENT; if (fifo->corrupt) return -ENXIO; @@ -192,7 +192,7 @@ int dma_fifo_out_pend(struct dma_fifo *fifo, struct dma_pending *pended) { unsigned len, n, ofs, l, limit; - if (fifo->data == NULL) + if (!fifo->data) return -ENOENT; if (fifo->corrupt) return -ENXIO; @@ -252,7 +252,7 @@ int dma_fifo_out_complete(struct dma_fifo *fifo, struct dma_pending *complete) { struct dma_pending *pending, *next, *tmp; - if (fifo->data == NULL) + if (!fifo->data) return -ENOENT; if (fifo->corrupt) return -ENXIO; -- cgit From 2fe9f8caadff1e5d3069e93192a544613d4ecbf3 Mon Sep 17 00:00:00 2001 From: Nizam Haider Date: Sun, 22 Nov 2015 09:39:26 +0530 Subject: Staging: fbtft: fbtft-core: Removed unnecessary checks The driver core clears the driver data to NULL after device_release or on probe failure. Signed-off-by: Nizam Haider Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fbtft-core.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index b1e45161eefc..6824d5ff2d8c 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -989,8 +989,6 @@ reg_fail: par->fbtftops.unregister_backlight(par); if (spi) spi_set_drvdata(spi, NULL); - if (par->pdev) - platform_set_drvdata(par->pdev, NULL); return ret; } @@ -1012,8 +1010,6 @@ int fbtft_unregister_framebuffer(struct fb_info *fb_info) if (spi) spi_set_drvdata(spi, NULL); - if (par->pdev) - platform_set_drvdata(par->pdev, NULL); if (par->fbtftops.unregister_backlight) par->fbtftops.unregister_backlight(par); fbtft_sysfs_exit(par); -- cgit From fd59f106f431e1a9ffc77ec0bbe7032249998699 Mon Sep 17 00:00:00 2001 From: Ben Gilbert Date: Mon, 14 Dec 2015 19:32:21 +0000 Subject: Staging: fbtft: Removed commented out/dead code Deleted various commented out lines that have been replaced by write_reg() Signed-off-by: Ben Gilbert Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_uc1701.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/staging/fbtft/fb_uc1701.c b/drivers/staging/fbtft/fb_uc1701.c index 212908e39277..b78045fe5393 100644 --- a/drivers/staging/fbtft/fb_uc1701.c +++ b/drivers/staging/fbtft/fb_uc1701.c @@ -78,11 +78,11 @@ static int init_display(struct fbtft_par *par) mdelay(10); /* set startpoint */ - /* LCD_START_LINE | (pos & 0x3F) */ write_reg(par, LCD_START_LINE); /* select orientation BOTTOMVIEW */ write_reg(par, LCD_BOTTOMVIEW | 1); + /* output mode select (turns display upside-down) */ write_reg(par, LCD_SCAN_DIR | 0x00); @@ -96,20 +96,14 @@ static int init_display(struct fbtft_par *par) write_reg(par, LCD_BIAS | 0); /* power control mode: all features on */ - /* LCD_POWER_CONTROL | (val&0x07) */ write_reg(par, LCD_POWER_CONTROL | 0x07); /* set voltage regulator R/R */ - /* LCD_VOLTAGE | (val&0x07) */ write_reg(par, LCD_VOLTAGE | 0x07); /* volume mode set */ - /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ write_reg(par, LCD_VOLUME_MODE); - /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ write_reg(par, 0x09); - /* ???? */ - /* LCD_VOLUME_MODE,val&0x3f,LCD_NO_OP */ write_reg(par, LCD_NO_OP); /* advanced program control */ @@ -125,17 +119,8 @@ static int init_display(struct fbtft_par *par) static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { /* goto address */ - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, LCD_PAGE_ADDRESS); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, 0x00); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, LCD_COL_ADDRESS); } @@ -156,17 +141,9 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) 1 : 0) << i; buf++; } - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ + write_reg(par, LCD_PAGE_ADDRESS | (u8)y); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, 0x00); - /* LCD_PAGE_ADDRESS | ((page) & 0x1F), - (((col)+SHIFT_ADDR_NORMAL) & 0x0F), - LCD_COL_ADDRESS | ((((col)+SHIFT_ADDR_NORMAL)>>4) & 0x0F) */ write_reg(par, LCD_COL_ADDRESS); gpio_set_value(par->gpio.dc, 1); ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); -- cgit From fbf461d176c5ee0e4889dc826a79a245f32426f7 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Sun, 20 Dec 2015 20:35:56 +0200 Subject: staging: fbtft: Use standard MIPI DCS command defines for hx8353d This patch makes use of the standard MIPI Display Command Set to remove some of the magic constants found in source code. Signed-off-by: Priit Laes Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_hx8353d.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c index 8552411695fa..064ae61a86b2 100644 --- a/drivers/staging/fbtft/fb_hx8353d.c +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -19,6 +19,7 @@ #include #include #include +#include - Matrix keyboars/keypads + Matrix keyboards/keypads !Iinclude/linux/input/matrix_keypad.h Sparse keymap support -- cgit From 2e049d6132eb960e1039b607039d0c8761ba0c31 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 2 Feb 2016 20:41:25 +0900 Subject: Doc: i2c: Fix typo in Documentation/i2c This path fix spelling typos found in Documentation/i2c. Signed-off-by: Masanari Iida Signed-off-by: Jonathan Corbet --- Documentation/i2c/dev-interface | 2 +- Documentation/i2c/slave-eeprom-backend | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/i2c/dev-interface b/Documentation/i2c/dev-interface index 2ac78ae1039d..bcf919d8625c 100644 --- a/Documentation/i2c/dev-interface +++ b/Documentation/i2c/dev-interface @@ -4,7 +4,7 @@ the /dev interface. You need to load module i2c-dev for this. Each registered i2c adapter gets a number, counting from 0. You can examine /sys/class/i2c-dev/ to see what number corresponds to which adapter. -Alternatively, you can run "i2cdetect -l" to obtain a formated list of all +Alternatively, you can run "i2cdetect -l" to obtain a formatted list of all i2c adapters present on your system at a given time. i2cdetect is part of the i2c-tools package. diff --git a/Documentation/i2c/slave-eeprom-backend b/Documentation/i2c/slave-eeprom-backend index c8444ef82acf..04f8d8a9b817 100644 --- a/Documentation/i2c/slave-eeprom-backend +++ b/Documentation/i2c/slave-eeprom-backend @@ -7,8 +7,8 @@ This is a proof-of-concept backend which acts like an EEPROM on the connected I2C bus. The memory contents can be modified from userspace via this file located in sysfs: - /sys/bus/i2c/devices//slave-eeprom + /sys/bus/i2c/devices//slave-eeprom As of 2015, Linux doesn't support poll on binary sysfs files, so there is no -notfication when another master changed the content. +notification when another master changed the content. -- cgit From 6c01ced75c40d8755371cde79bf89c8d3ac8915b Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Mon, 1 Feb 2016 13:03:27 +0900 Subject: Doc: ja_JP: Fix a typo in HOWTO This patch fix a typo witin HOWTO, which was translated in Japanese. Replace a word "kernlehacker" with "kernelhacker". Signed-off-by: Masanari Iida Signed-off-by: Jonathan Corbet --- Documentation/ja_JP/HOWTO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO index 8d5465d3fdef..52ef02b33da9 100644 --- a/Documentation/ja_JP/HOWTO +++ b/Documentation/ja_JP/HOWTO @@ -440,7 +440,7 @@ MAINTAINERS ファイルにリストがありますので参照してくださ てこの状態を変えようとしないように。人々はそのようなことは好みません。 今までのメールでのやりとりとその間のあなたの発言はそのまま残し、 -"John Kernlehacker wrote ...:" の行をあなたのリプライの先頭行にして、 +"John Kernelhacker wrote ...:" の行をあなたのリプライの先頭行にして、 メールの先頭でなく、各引用行の間にあなたの言いたいことを追加するべきで す。 -- cgit From 5645a717c6ee61e67d38aa9f15cb9db074e1e99d Mon Sep 17 00:00:00 2001 From: Peter Loeffler Date: Sat, 30 Jan 2016 21:53:53 +0100 Subject: Documentation: HOWTO: remove obsolete info about regression postings corbet@lwn.net told me that these regression postings haven't happened for several years. So i think we can remove it. Signed-off-by: Peter Loeffler Signed-off-by: Jonathan Corbet --- Documentation/HOWTO | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Documentation/HOWTO b/Documentation/HOWTO index d5a699d5a551..ef2ff1e9d3e0 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -187,7 +187,7 @@ apply a patch. If you do not know where you want to start, but you want to look for some task to start doing to join into the kernel development community, go to the Linux Kernel Janitor's project: - http://kernelnewbies.org/KernelJanitors + http://kernelnewbies.org/KernelJanitors It is a great place to start. It describes a list of relatively simple problems that need to be cleaned up and fixed within the Linux kernel source tree. Working with the developers in charge of this project, you @@ -250,11 +250,6 @@ process is as follows: release a new -rc kernel every week. - Process continues until the kernel is considered "ready", the process should last around 6 weeks. - - Known regressions in each release are periodically posted to the - linux-kernel mailing list. The goal is to reduce the length of - that list to zero before declaring the kernel to be "ready," but, in - the real world, a small number of regressions often remain at - release time. It is worth mentioning what Andrew Morton wrote on the linux-kernel mailing list about kernel releases: -- cgit From e439bb12e75c2807029853493fa787c6d70c763a Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Wed, 10 Feb 2016 10:03:29 -0800 Subject: nvme/host: reference the fabric module for each bdev open callout We don't want to be able to unload the fabric driver when we have openened referenced to our namespaces. Thus, for each nvme_open we take a reference on the fabric driver and put it in nvme_release. This behavior is consistent with the scsi model. This resolves the panic when unloading a fabric module with mpath holders. Signed-off-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Reviewed-by: Ian Bakshan Reviewed-by: Johannes Thumshirn Signed-off-by: Ming Lin Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 19 ++++++++++++++++--- drivers/nvme/host/nvme.h | 1 + drivers/nvme/host/pci.c | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index a7c29f24976c..c9cd07f02cc2 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -71,11 +71,21 @@ static struct nvme_ns *nvme_get_ns_from_disk(struct gendisk *disk) spin_lock(&dev_list_lock); ns = disk->private_data; - if (ns && !kref_get_unless_zero(&ns->kref)) - ns = NULL; + if (ns) { + if (!kref_get_unless_zero(&ns->kref)) + goto fail; + if (!try_module_get(ns->ctrl->ops->module)) + goto fail_put_ns; + } spin_unlock(&dev_list_lock); return ns; + +fail_put_ns: + kref_put(&ns->kref, nvme_free_ns); +fail: + spin_unlock(&dev_list_lock); + return NULL; } void nvme_requeue_req(struct request *req) @@ -499,7 +509,10 @@ static int nvme_open(struct block_device *bdev, fmode_t mode) static void nvme_release(struct gendisk *disk, fmode_t mode) { - nvme_put_ns(disk->private_data); + struct nvme_ns *ns = disk->private_data; + + module_put(ns->ctrl->ops->module); + nvme_put_ns(ns); } static int nvme_getgeo(struct block_device *bdev, struct hd_geometry *geo) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 4fb5bb737868..9f77386f7d1e 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -117,6 +117,7 @@ struct nvme_ns { }; struct nvme_ctrl_ops { + struct module *module; int (*reg_read32)(struct nvme_ctrl *ctrl, u32 off, u32 *val); int (*reg_write32)(struct nvme_ctrl *ctrl, u32 off, u32 val); int (*reg_read64)(struct nvme_ctrl *ctrl, u32 off, u64 *val); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index f2f55b504cf2..cb303ac91b9d 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2036,6 +2036,7 @@ static int nvme_pci_reset_ctrl(struct nvme_ctrl *ctrl) } static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = { + .module = THIS_MODULE, .reg_read32 = nvme_pci_reg_read32, .reg_write32 = nvme_pci_reg_write32, .reg_read64 = nvme_pci_reg_read64, -- cgit From ba0ba7d3e5266111ec865b0bf1ad48dd0e2a2314 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Wed, 10 Feb 2016 10:03:30 -0800 Subject: nvme: move timeout variables to core.c These variables are used by PCI driver and will also be used in the forthcoming NVMe over Fabrics drivers. Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lin Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 12 ++++++++++++ drivers/nvme/host/pci.c | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c9cd07f02cc2..0c0011b5e1b9 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -33,6 +33,18 @@ #define NVME_MINORS (1U << MINORBITS) +unsigned char admin_timeout = 60; +module_param(admin_timeout, byte, 0644); +MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands"); + +unsigned char nvme_io_timeout = 30; +module_param_named(io_timeout, nvme_io_timeout, byte, 0644); +MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O"); + +unsigned char shutdown_timeout = 5; +module_param(shutdown_timeout, byte, 0644); +MODULE_PARM_DESC(shutdown_timeout, "timeout in seconds for controller shutdown"); + static int nvme_major; module_param(nvme_major, int, 0); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index cb303ac91b9d..53a99422d44d 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -57,18 +57,6 @@ #define NVME_NR_AEN_COMMANDS 1 #define NVME_AQ_BLKMQ_DEPTH (NVME_AQ_DEPTH - NVME_NR_AEN_COMMANDS) -unsigned char admin_timeout = 60; -module_param(admin_timeout, byte, 0644); -MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands"); - -unsigned char nvme_io_timeout = 30; -module_param_named(io_timeout, nvme_io_timeout, byte, 0644); -MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O"); - -unsigned char shutdown_timeout = 5; -module_param(shutdown_timeout, byte, 0644); -MODULE_PARM_DESC(shutdown_timeout, "timeout in seconds for controller shutdown"); - static int use_threaded_interrupts; module_param(use_threaded_interrupts, int, 0); -- cgit From 9f2482b91bcd02ac2999cf04b3fb1b89e1c4d559 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Wed, 10 Feb 2016 10:03:31 -0800 Subject: nvme: split dev_list_lock Split dev_list_lock into one in the core and one in the PCI driver. Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Reviewed-by: Sagi Grimberg Signed-off-by: Ming Lin Signed-off-by: Jens Axboe --- drivers/nvme/host/core.c | 2 +- drivers/nvme/host/nvme.h | 2 -- drivers/nvme/host/pci.c | 1 + 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 0c0011b5e1b9..6eb42d24a5e9 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -52,7 +52,7 @@ static int nvme_char_major; module_param(nvme_char_major, int, 0); static LIST_HEAD(nvme_ctrl_list); -DEFINE_SPINLOCK(dev_list_lock); +static DEFINE_SPINLOCK(dev_list_lock); static struct class *nvme_class; diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 9f77386f7d1e..63ba8a500ee1 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -266,8 +266,6 @@ int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11, dma_addr_t dma_addr, u32 *result); int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count); -extern spinlock_t dev_list_lock; - struct sg_io_hdr; int nvme_sg_io(struct nvme_ns *ns, struct sg_io_hdr __user *u_hdr); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 53a99422d44d..54e79c035913 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -65,6 +65,7 @@ module_param(use_cmb_sqes, bool, 0644); MODULE_PARM_DESC(use_cmb_sqes, "use controller's memory buffer for I/O SQes"); static LIST_HEAD(dev_list); +static DEFINE_SPINLOCK(dev_list_lock); static struct task_struct *nvme_thread; static struct workqueue_struct *nvme_workq; static wait_queue_head_t nvme_kthread_wait; -- cgit From 576d55d625664a20ee4bae6500952febfb2d7b10 Mon Sep 17 00:00:00 2001 From: Ming Lin Date: Wed, 10 Feb 2016 10:03:32 -0800 Subject: nvme: split pci module out of core module NVMe over Fabrics drivers are going to reuse the core, so splits nvme.ko into 2 modules: nvme-core.ko: the core part nvme.ko: the PCI driver Export symbols from nvme-core.ko. Reviewed-by: Christoph Hellwig Signed-off-by: Ming Lin Signed-off-by: Jens Axboe --- drivers/nvme/host/Kconfig | 6 +++++- drivers/nvme/host/Makefile | 10 ++++++---- drivers/nvme/host/core.c | 24 +++++++++++++++++++++++- drivers/nvme/host/pci.c | 13 +------------ 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig index 5d6237391dcd..2ed30f063a13 100644 --- a/drivers/nvme/host/Kconfig +++ b/drivers/nvme/host/Kconfig @@ -1,6 +1,10 @@ +config NVME_CORE + tristate + config BLK_DEV_NVME tristate "NVM Express block device" depends on PCI && BLOCK + select NVME_CORE ---help--- The NVM Express driver is for solid state drives directly connected to the PCI or PCI Express bus. If you know you @@ -11,7 +15,7 @@ config BLK_DEV_NVME config BLK_DEV_NVME_SCSI bool "SCSI emulation for NVMe device nodes" - depends on BLK_DEV_NVME + 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 diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile index 51bf90871549..9a3ca892b4a7 100644 --- a/drivers/nvme/host/Makefile +++ b/drivers/nvme/host/Makefile @@ -1,6 +1,8 @@ +obj-$(CONFIG_NVME_CORE) += nvme-core.o +obj-$(CONFIG_BLK_DEV_NVME) += nvme.o -obj-$(CONFIG_BLK_DEV_NVME) += nvme.o +nvme-core-y := core.o +nvme-core-$(CONFIG_BLK_DEV_NVME_SCSI) += scsi.o +nvme-core-$(CONFIG_NVM) += lightnvm.o -lightnvm-$(CONFIG_NVM) := lightnvm.o -nvme-y += core.o pci.o $(lightnvm-y) -nvme-$(CONFIG_BLK_DEV_NVME_SCSI) += scsi.o +nvme-y += pci.o diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 6eb42d24a5e9..07b7ec699e92 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -36,10 +36,12 @@ unsigned char admin_timeout = 60; module_param(admin_timeout, byte, 0644); MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands"); +EXPORT_SYMBOL_GPL(admin_timeout); unsigned char nvme_io_timeout = 30; module_param_named(io_timeout, nvme_io_timeout, byte, 0644); MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O"); +EXPORT_SYMBOL_GPL(nvme_io_timeout); unsigned char shutdown_timeout = 5; module_param(shutdown_timeout, byte, 0644); @@ -110,6 +112,7 @@ void nvme_requeue_req(struct request *req) blk_mq_kick_requeue_list(req->q); spin_unlock_irqrestore(req->q->queue_lock, flags); } +EXPORT_SYMBOL_GPL(nvme_requeue_req); struct request *nvme_alloc_request(struct request_queue *q, struct nvme_command *cmd, unsigned int flags) @@ -133,6 +136,7 @@ struct request *nvme_alloc_request(struct request_queue *q, return req; } +EXPORT_SYMBOL_GPL(nvme_alloc_request); /* * Returns 0 on success. If the result is negative, it's a Linux error code; @@ -170,6 +174,7 @@ int nvme_submit_sync_cmd(struct request_queue *q, struct nvme_command *cmd, { return __nvme_submit_sync_cmd(q, cmd, buffer, bufflen, NULL, 0); } +EXPORT_SYMBOL_GPL(nvme_submit_sync_cmd); int __nvme_submit_user_cmd(struct request_queue *q, struct nvme_command *cmd, void __user *ubuffer, unsigned bufflen, @@ -385,6 +390,7 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count) *count = min(*count, nr_io_queues); return 0; } +EXPORT_SYMBOL_GPL(nvme_set_queue_count); static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio) { @@ -794,6 +800,7 @@ int nvme_disable_ctrl(struct nvme_ctrl *ctrl, u64 cap) return ret; return nvme_wait_ready(ctrl, cap, false); } +EXPORT_SYMBOL_GPL(nvme_disable_ctrl); int nvme_enable_ctrl(struct nvme_ctrl *ctrl, u64 cap) { @@ -825,6 +832,7 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl, u64 cap) return ret; return nvme_wait_ready(ctrl, cap, true); } +EXPORT_SYMBOL_GPL(nvme_enable_ctrl); int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl) { @@ -855,6 +863,7 @@ int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl) return ret; } +EXPORT_SYMBOL_GPL(nvme_shutdown_ctrl); /* * Initialize the cached copies of the Identify data and various controller @@ -916,6 +925,7 @@ int nvme_init_identify(struct nvme_ctrl *ctrl) kfree(id); return 0; } +EXPORT_SYMBOL_GPL(nvme_init_identify); static int nvme_dev_open(struct inode *inode, struct file *file) { @@ -1321,6 +1331,7 @@ void nvme_scan_namespaces(struct nvme_ctrl *ctrl) mutex_unlock(&ctrl->namespaces_mutex); kfree(id); } +EXPORT_SYMBOL_GPL(nvme_scan_namespaces); void nvme_remove_namespaces(struct nvme_ctrl *ctrl) { @@ -1331,6 +1342,7 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl) nvme_ns_remove(ns); mutex_unlock(&ctrl->namespaces_mutex); } +EXPORT_SYMBOL_GPL(nvme_remove_namespaces); static DEFINE_IDA(nvme_instance_ida); @@ -1362,13 +1374,14 @@ static void nvme_release_instance(struct nvme_ctrl *ctrl) } void nvme_uninit_ctrl(struct nvme_ctrl *ctrl) - { +{ device_destroy(nvme_class, MKDEV(nvme_char_major, ctrl->instance)); spin_lock(&dev_list_lock); list_del(&ctrl->node); spin_unlock(&dev_list_lock); } +EXPORT_SYMBOL_GPL(nvme_uninit_ctrl); static void nvme_free_ctrl(struct kref *kref) { @@ -1384,6 +1397,7 @@ void nvme_put_ctrl(struct nvme_ctrl *ctrl) { kref_put(&ctrl->kref, nvme_free_ctrl); } +EXPORT_SYMBOL_GPL(nvme_put_ctrl); /* * Initialize a NVMe controller structures. This needs to be called during @@ -1426,6 +1440,7 @@ out_release_instance: out: return ret; } +EXPORT_SYMBOL_GPL(nvme_init_ctrl); void nvme_stop_queues(struct nvme_ctrl *ctrl) { @@ -1442,6 +1457,7 @@ void nvme_stop_queues(struct nvme_ctrl *ctrl) } mutex_unlock(&ctrl->namespaces_mutex); } +EXPORT_SYMBOL_GPL(nvme_stop_queues); void nvme_start_queues(struct nvme_ctrl *ctrl) { @@ -1455,6 +1471,7 @@ void nvme_start_queues(struct nvme_ctrl *ctrl) } mutex_unlock(&ctrl->namespaces_mutex); } +EXPORT_SYMBOL_GPL(nvme_start_queues); int __init nvme_core_init(void) { @@ -1494,3 +1511,8 @@ void nvme_core_exit(void) class_destroy(nvme_class); __unregister_chrdev(nvme_char_major, 0, NVME_MINORS, "nvme"); } + +MODULE_LICENSE("GPL"); +MODULE_VERSION("1.0"); +module_init(nvme_core_init); +module_exit(nvme_core_exit); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 54e79c035913..fec747917690 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2230,26 +2230,15 @@ static int __init nvme_init(void) if (!nvme_workq) return -ENOMEM; - result = nvme_core_init(); - if (result < 0) - goto kill_workq; - result = pci_register_driver(&nvme_driver); if (result) - goto core_exit; - return 0; - - core_exit: - nvme_core_exit(); - kill_workq: - destroy_workqueue(nvme_workq); + destroy_workqueue(nvme_workq); return result; } static void __exit nvme_exit(void) { pci_unregister_driver(&nvme_driver); - nvme_core_exit(); destroy_workqueue(nvme_workq); BUG_ON(nvme_thread && !IS_ERR(nvme_thread)); _nvme_check_size(); -- cgit From 896d6a4c0f41a93809b83f9e58aad73874a89d99 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:40 +0530 Subject: cpufreq: dt: Convert few pr_debug/err() calls to dev_dbg/err() We have the device structure available now, lets use it for better print messages. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 0ca74d070058..ace0168274d4 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -246,7 +246,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) */ ret = dev_pm_opp_get_opp_count(cpu_dev); if (ret <= 0) { - pr_debug("OPP table is not ready, deferring probe\n"); + dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n"); ret = -EPROBE_DEFER; goto out_free_opp; } @@ -325,7 +325,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { - pr_err("failed to init cpufreq table: %d\n", ret); + dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); goto out_free_priv; } -- cgit From 457e99e60a8f5a40b7da204c0bfc8a86ad2161b9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:41 +0530 Subject: cpufreq: dt: Rename 'need_update' to 'opp_v1' That's the real purpose of this field, i.e. to take special care of old OPP V1 bindings. Lets name it accordingly, so that it can be used elsewhere. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index ace0168274d4..0047d20803db 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -199,7 +199,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) struct dev_pm_opp *suspend_opp; unsigned long min_uV = ~0, max_uV = 0; unsigned int transition_latency; - bool need_update = false; + bool opp_v1 = false; int ret; ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk); @@ -223,7 +223,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) * finding shared-OPPs for backward compatibility. */ if (ret == -ENOENT) - need_update = true; + opp_v1 = true; else goto out_node_put; } @@ -251,7 +251,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) goto out_free_opp; } - if (need_update) { + if (opp_v1) { struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data(); if (!pd || !pd->independent_clocks) -- cgit From 391d9aef8145204e0a5d67be3bd1fc45c5396dae Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:42 +0530 Subject: cpufreq: dt: OPP layers handles clock-latency for V1 bindings as well "clock-latency" is handled by OPP layer for all bindings and so there is no need to make special calls for V1 bindings. Use dev_pm_opp_get_max_clock_latency() for both the cases. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 0047d20803db..4c9f8a828f6f 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -265,10 +265,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) if (ret) dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", __func__, ret); - - of_property_read_u32(np, "clock-latency", &transition_latency); - } else { - transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev); } priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -279,6 +275,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); + transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev); if (!transition_latency) transition_latency = CPUFREQ_ETERNAL; -- cgit From 050794aaebbb9f2c2c50b340b6998273e7c64189 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:43 +0530 Subject: cpufreq: dt: Pass regulator name to the OPP core OPP core can handle the regulators by itself, and but it needs to know the name of the regulator to fetch. Add support for that. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 4c9f8a828f6f..2af75f8088bb 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -34,6 +34,7 @@ struct private_data { struct regulator *cpu_reg; struct thermal_cooling_device *cdev; unsigned int voltage_tolerance; /* in percentage */ + const char *reg_name; }; static struct freq_attr *cpufreq_dt_attr[] = { @@ -119,6 +120,30 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) return ret; } +/* + * An earlier version of opp-v1 bindings used to name the regulator + * "cpu0-supply", we still need to handle that for backwards compatibility. + */ +static const char *find_supply_name(struct device *dev, struct device_node *np) +{ + struct property *pp; + int cpu = dev->id; + + /* Try "cpu0" for older DTs */ + if (!cpu) { + pp = of_find_property(np, "cpu0-supply", NULL); + if (pp) + return "cpu0"; + } + + pp = of_find_property(np, "cpu-supply", NULL); + if (pp) + return "cpu"; + + dev_dbg(dev, "no regulator for cpu%d\n", cpu); + return NULL; +} + static int allocate_resources(int cpu, struct device **cdev, struct regulator **creg, struct clk **cclk) { @@ -200,6 +225,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) unsigned long min_uV = ~0, max_uV = 0; unsigned int transition_latency; bool opp_v1 = false; + const char *name; int ret; ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk); @@ -228,6 +254,20 @@ static int cpufreq_init(struct cpufreq_policy *policy) goto out_node_put; } + /* + * OPP layer will be taking care of regulators now, but it needs to know + * the name of the regulator first. + */ + name = find_supply_name(cpu_dev, np); + if (name) { + ret = dev_pm_opp_set_regulator(cpu_dev, name); + if (ret) { + dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n", + policy->cpu, ret); + goto out_node_put; + } + } + /* * Initialize OPP tables for all policy->cpus. They will be shared by * all CPUs which have marked their CPUs shared with OPP bindings. @@ -273,6 +313,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) goto out_free_opp; } + priv->reg_name = name; of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev); @@ -366,6 +407,8 @@ out_free_priv: kfree(priv); out_free_opp: dev_pm_opp_of_cpumask_remove_table(policy->cpus); + if (name) + dev_pm_opp_put_regulator(cpu_dev); out_node_put: of_node_put(np); out_put_reg_clk: @@ -383,6 +426,9 @@ static int cpufreq_exit(struct cpufreq_policy *policy) cpufreq_cooling_unregister(priv->cdev); dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); + if (priv->reg_name) + dev_pm_opp_put_regulator(priv->cpu_dev); + clk_put(policy->clk); if (!IS_ERR(priv->cpu_reg)) regulator_put(priv->cpu_reg); -- cgit From 6def6ea75e6dea45f01a16ae3cfb5b5ce48dd5e9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:44 +0530 Subject: cpufreq: dt: Unsupported OPPs are already disabled The core already have a valid regulator set for the device opp and the unsupported OPPs are already disabled by the core. There is no need to repeat that in the user drivers, get rid of it. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 2af75f8088bb..c3fe89461ff4 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -349,8 +349,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) min_uV = opp_uV; if (opp_uV > max_uV) max_uV = opp_uV; - } else { - dev_pm_opp_disable(cpu_dev, opp_freq); } opp_freq++; -- cgit From 755b888ff098c9f762717a9fbda7e05b16619069 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:45 +0530 Subject: cpufreq: dt: Reuse dev_pm_opp_get_max_transition_latency() OPP layer has all the information now to calculate transition latency (clock_latency + voltage_latency). Lets reuse the OPP layer helper dev_pm_opp_get_max_transition_latency() instead of open coding the same in cpufreq-dt driver. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 48 ++++---------------------------------------- 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index c3fe89461ff4..6f80ce56b4ec 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -222,7 +222,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) struct regulator *cpu_reg; struct clk *cpu_clk; struct dev_pm_opp *suspend_opp; - unsigned long min_uV = ~0, max_uV = 0; unsigned int transition_latency; bool opp_v1 = false; const char *name; @@ -316,49 +315,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) priv->reg_name = name; of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); - transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev); - if (!transition_latency) - transition_latency = CPUFREQ_ETERNAL; - - if (!IS_ERR(cpu_reg)) { - unsigned long opp_freq = 0; - - /* - * Disable any OPPs where the connected regulator isn't able to - * provide the specified voltage and record minimum and maximum - * voltage levels. - */ - while (1) { - struct dev_pm_opp *opp; - unsigned long opp_uV, tol_uV; - - rcu_read_lock(); - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq); - if (IS_ERR(opp)) { - rcu_read_unlock(); - break; - } - opp_uV = dev_pm_opp_get_voltage(opp); - rcu_read_unlock(); - - tol_uV = opp_uV * priv->voltage_tolerance / 100; - if (regulator_is_supported_voltage(cpu_reg, - opp_uV - tol_uV, - opp_uV + tol_uV)) { - if (opp_uV < min_uV) - min_uV = opp_uV; - if (opp_uV > max_uV) - max_uV = opp_uV; - } - - opp_freq++; - } - - ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); - if (ret > 0) - transition_latency += ret * 1000; - } - ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); @@ -393,6 +349,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs; } + transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev); + if (!transition_latency) + transition_latency = CPUFREQ_ETERNAL; + policy->cpuinfo.transition_latency = transition_latency; of_node_put(np); -- cgit From 78c3ba5df96c875b1668e1cd3ee0a69e62454f32 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:46 +0530 Subject: cpufreq: dt: Use dev_pm_opp_set_rate() to switch frequency OPP core supports frequency/voltage changes based on the target frequency now, use that instead of open coding the same in cpufreq-dt driver. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 73 ++------------------------------------------ 1 file changed, 2 insertions(+), 71 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 6f80ce56b4ec..150a172c7d0a 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -45,79 +45,10 @@ static struct freq_attr *cpufreq_dt_attr[] = { static int set_target(struct cpufreq_policy *policy, unsigned int index) { - struct dev_pm_opp *opp; - struct cpufreq_frequency_table *freq_table = policy->freq_table; - struct clk *cpu_clk = policy->clk; struct private_data *priv = policy->driver_data; - struct device *cpu_dev = priv->cpu_dev; - struct regulator *cpu_reg = priv->cpu_reg; - unsigned long volt = 0, tol = 0; - int volt_old = 0; - unsigned int old_freq, new_freq; - long freq_Hz, freq_exact; - int ret; - - freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000); - if (freq_Hz <= 0) - freq_Hz = freq_table[index].frequency * 1000; - - freq_exact = freq_Hz; - new_freq = freq_Hz / 1000; - old_freq = clk_get_rate(cpu_clk) / 1000; - - if (!IS_ERR(cpu_reg)) { - unsigned long opp_freq; - - rcu_read_lock(); - opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz); - if (IS_ERR(opp)) { - rcu_read_unlock(); - dev_err(cpu_dev, "failed to find OPP for %ld\n", - freq_Hz); - return PTR_ERR(opp); - } - volt = dev_pm_opp_get_voltage(opp); - opp_freq = dev_pm_opp_get_freq(opp); - rcu_read_unlock(); - tol = volt * priv->voltage_tolerance / 100; - volt_old = regulator_get_voltage(cpu_reg); - dev_dbg(cpu_dev, "Found OPP: %ld kHz, %ld uV\n", - opp_freq / 1000, volt); - } - - dev_dbg(cpu_dev, "%u MHz, %d mV --> %u MHz, %ld mV\n", - old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1, - new_freq / 1000, volt ? volt / 1000 : -1); - - /* scaling up? scale voltage before frequency */ - if (!IS_ERR(cpu_reg) && new_freq > old_freq) { - ret = regulator_set_voltage_tol(cpu_reg, volt, tol); - if (ret) { - dev_err(cpu_dev, "failed to scale voltage up: %d\n", - ret); - return ret; - } - } - - ret = clk_set_rate(cpu_clk, freq_exact); - if (ret) { - dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); - if (!IS_ERR(cpu_reg) && volt_old > 0) - regulator_set_voltage_tol(cpu_reg, volt_old, tol); - return ret; - } - /* scaling down? scale voltage after frequency */ - if (!IS_ERR(cpu_reg) && new_freq < old_freq) { - ret = regulator_set_voltage_tol(cpu_reg, volt, tol); - if (ret) { - dev_err(cpu_dev, "failed to scale voltage down: %d\n", - ret); - clk_set_rate(cpu_clk, old_freq * 1000); - } - } - - return ret; + return dev_pm_opp_set_rate(priv->cpu_dev, + policy->freq_table[index].frequency * 1000); } /* -- cgit From df2c8ec28e73d47392b8cb24828c15c54819da41 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:47 +0530 Subject: cpufreq: dt: No need to fetch voltage-tolerance Its already done by core and we don't need to get it anymore. And so, we don't need to get of node in cpufreq_init() anymore, move that to find_supply_name() instead. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 150a172c7d0a..bbafd7b63d1a 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -33,7 +33,6 @@ struct private_data { struct device *cpu_dev; struct regulator *cpu_reg; struct thermal_cooling_device *cdev; - unsigned int voltage_tolerance; /* in percentage */ const char *reg_name; }; @@ -55,24 +54,38 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) * An earlier version of opp-v1 bindings used to name the regulator * "cpu0-supply", we still need to handle that for backwards compatibility. */ -static const char *find_supply_name(struct device *dev, struct device_node *np) +static const char *find_supply_name(struct device *dev) { + struct device_node *np; struct property *pp; int cpu = dev->id; + const char *name = NULL; + + np = of_node_get(dev->of_node); + + /* This must be valid for sure */ + if (WARN_ON(!np)) + return NULL; /* Try "cpu0" for older DTs */ if (!cpu) { pp = of_find_property(np, "cpu0-supply", NULL); - if (pp) - return "cpu0"; + if (pp) { + name = "cpu0"; + goto node_put; + } } pp = of_find_property(np, "cpu-supply", NULL); - if (pp) - return "cpu"; + if (pp) { + name = "cpu"; + goto node_put; + } dev_dbg(dev, "no regulator for cpu%d\n", cpu); - return NULL; +node_put: + of_node_put(np); + return name; } static int allocate_resources(int cpu, struct device **cdev, @@ -147,7 +160,6 @@ try_again: static int cpufreq_init(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *freq_table; - struct device_node *np; struct private_data *priv; struct device *cpu_dev; struct regulator *cpu_reg; @@ -164,13 +176,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) return ret; } - np = of_node_get(cpu_dev->of_node); - if (!np) { - dev_err(cpu_dev, "failed to find cpu%d node\n", policy->cpu); - ret = -ENOENT; - goto out_put_reg_clk; - } - /* Get OPP-sharing information from "operating-points-v2" bindings */ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, policy->cpus); if (ret) { @@ -181,20 +186,20 @@ static int cpufreq_init(struct cpufreq_policy *policy) if (ret == -ENOENT) opp_v1 = true; else - goto out_node_put; + goto out_put_reg_clk; } /* * OPP layer will be taking care of regulators now, but it needs to know * the name of the regulator first. */ - name = find_supply_name(cpu_dev, np); + name = find_supply_name(cpu_dev); if (name) { ret = dev_pm_opp_set_regulator(cpu_dev, name); if (ret) { dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n", policy->cpu, ret); - goto out_node_put; + goto out_put_reg_clk; } } @@ -244,7 +249,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) } priv->reg_name = name; - of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); if (ret) { @@ -286,8 +290,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = transition_latency; - of_node_put(np); - return 0; out_free_cpufreq_table: @@ -298,8 +300,6 @@ out_free_opp: dev_pm_opp_of_cpumask_remove_table(policy->cpus); if (name) dev_pm_opp_put_regulator(cpu_dev); -out_node_put: - of_node_put(np); out_put_reg_clk: clk_put(cpu_clk); if (!IS_ERR(cpu_reg)) -- cgit From dd02a3d920083b6cb0ee4f0eaf2c599b740bf5fe Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 9 Feb 2016 10:30:48 +0530 Subject: cpufreq: dt: No need to allocate resources anymore OPP layer manages it now and cpufreq-dt driver doesn't need it. But, we still need to check for availability of resources for deferred probing. Signed-off-by: Viresh Kumar Reviewed-by: Stephen Boyd Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 112 +++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 67 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index bbafd7b63d1a..f951f911786e 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -31,7 +31,6 @@ struct private_data { struct device *cpu_dev; - struct regulator *cpu_reg; struct thermal_cooling_device *cdev; const char *reg_name; }; @@ -88,73 +87,59 @@ node_put: return name; } -static int allocate_resources(int cpu, struct device **cdev, - struct regulator **creg, struct clk **cclk) +static int resources_available(void) { struct device *cpu_dev; struct regulator *cpu_reg; struct clk *cpu_clk; int ret = 0; - char *reg_cpu0 = "cpu0", *reg_cpu = "cpu", *reg; + const char *name; - cpu_dev = get_cpu_device(cpu); + cpu_dev = get_cpu_device(0); if (!cpu_dev) { - pr_err("failed to get cpu%d device\n", cpu); + pr_err("failed to get cpu0 device\n"); return -ENODEV; } - /* Try "cpu0" for older DTs */ - if (!cpu) - reg = reg_cpu0; - else - reg = reg_cpu; - -try_again: - cpu_reg = regulator_get_optional(cpu_dev, reg); - ret = PTR_ERR_OR_ZERO(cpu_reg); + cpu_clk = clk_get(cpu_dev, NULL); + ret = PTR_ERR_OR_ZERO(cpu_clk); if (ret) { /* - * If cpu's regulator supply node is present, but regulator is - * not yet registered, we should try defering probe. + * If cpu's clk node is present, but clock is not yet + * registered, we should try defering probe. */ - if (ret == -EPROBE_DEFER) { - dev_dbg(cpu_dev, "cpu%d regulator not ready, retry\n", - cpu); - return ret; - } - - /* Try with "cpu-supply" */ - if (reg == reg_cpu0) { - reg = reg_cpu; - goto try_again; - } + if (ret == -EPROBE_DEFER) + dev_dbg(cpu_dev, "clock not ready, retry\n"); + else + dev_err(cpu_dev, "failed to get clock: %d\n", ret); - dev_dbg(cpu_dev, "no regulator for cpu%d: %d\n", cpu, ret); + return ret; } - cpu_clk = clk_get(cpu_dev, NULL); - ret = PTR_ERR_OR_ZERO(cpu_clk); - if (ret) { - /* put regulator */ - if (!IS_ERR(cpu_reg)) - regulator_put(cpu_reg); + clk_put(cpu_clk); + + name = find_supply_name(cpu_dev); + /* Platform doesn't require regulator */ + if (!name) + return 0; + cpu_reg = regulator_get_optional(cpu_dev, name); + ret = PTR_ERR_OR_ZERO(cpu_reg); + if (ret) { /* - * If cpu's clk node is present, but clock is not yet - * registered, we should try defering probe. + * If cpu's regulator supply node is present, but regulator is + * not yet registered, we should try defering probe. */ if (ret == -EPROBE_DEFER) - dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu); + dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n"); else - dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu, - ret); - } else { - *cdev = cpu_dev; - *creg = cpu_reg; - *cclk = cpu_clk; + dev_dbg(cpu_dev, "no regulator for cpu0: %d\n", ret); + + return ret; } - return ret; + regulator_put(cpu_reg); + return 0; } static int cpufreq_init(struct cpufreq_policy *policy) @@ -162,7 +147,6 @@ static int cpufreq_init(struct cpufreq_policy *policy) struct cpufreq_frequency_table *freq_table; struct private_data *priv; struct device *cpu_dev; - struct regulator *cpu_reg; struct clk *cpu_clk; struct dev_pm_opp *suspend_opp; unsigned int transition_latency; @@ -170,9 +154,16 @@ static int cpufreq_init(struct cpufreq_policy *policy) const char *name; int ret; - ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk); - if (ret) { - pr_err("%s: Failed to allocate resources: %d\n", __func__, ret); + cpu_dev = get_cpu_device(policy->cpu); + if (!cpu_dev) { + pr_err("failed to get cpu%d device\n", policy->cpu); + return -ENODEV; + } + + cpu_clk = clk_get(cpu_dev, NULL); + if (IS_ERR(cpu_clk)) { + ret = PTR_ERR(cpu_clk); + dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret); return ret; } @@ -186,7 +177,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) if (ret == -ENOENT) opp_v1 = true; else - goto out_put_reg_clk; + goto out_put_clk; } /* @@ -199,7 +190,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) if (ret) { dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n", policy->cpu, ret); - goto out_put_reg_clk; + goto out_put_clk; } } @@ -257,9 +248,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) } priv->cpu_dev = cpu_dev; - priv->cpu_reg = cpu_reg; policy->driver_data = priv; - policy->clk = cpu_clk; rcu_read_lock(); @@ -300,10 +289,8 @@ out_free_opp: dev_pm_opp_of_cpumask_remove_table(policy->cpus); if (name) dev_pm_opp_put_regulator(cpu_dev); -out_put_reg_clk: +out_put_clk: clk_put(cpu_clk); - if (!IS_ERR(cpu_reg)) - regulator_put(cpu_reg); return ret; } @@ -319,8 +306,6 @@ static int cpufreq_exit(struct cpufreq_policy *policy) dev_pm_opp_put_regulator(priv->cpu_dev); clk_put(policy->clk); - if (!IS_ERR(priv->cpu_reg)) - regulator_put(priv->cpu_reg); kfree(priv); return 0; @@ -373,9 +358,6 @@ static struct cpufreq_driver dt_cpufreq_driver = { static int dt_cpufreq_probe(struct platform_device *pdev) { - struct device *cpu_dev; - struct regulator *cpu_reg; - struct clk *cpu_clk; int ret; /* @@ -385,19 +367,15 @@ static int dt_cpufreq_probe(struct platform_device *pdev) * * FIXME: Is checking this only for CPU0 sufficient ? */ - ret = allocate_resources(0, &cpu_dev, &cpu_reg, &cpu_clk); + ret = resources_available(); if (ret) return ret; - clk_put(cpu_clk); - if (!IS_ERR(cpu_reg)) - regulator_put(cpu_reg); - dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev); ret = cpufreq_register_driver(&dt_cpufreq_driver); if (ret) - dev_err(cpu_dev, "failed register driver: %d\n", ret); + dev_err(&pdev->dev, "failed register driver: %d\n", ret); return ret; } -- cgit From 622190669403fb7a7557a8b618e57c0a3f703056 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 10 Feb 2016 22:45:53 +0530 Subject: be2net: Request RSS capability of Rx interface depending on number of Rx rings Currently we request RSS capability even if a single Rx ring is created. As a result in few cases we unnecessarily consume an RSS capable interface which is a limited resource in the chip. This patch enables RSS on an interface only if more than one Rx ring is created. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 19 +++------- drivers/net/ethernet/emulex/benet/be_main.c | 58 +++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 7d51d4733890..33cbbde218be 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1513,34 +1513,25 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, return status; } -/* Uses MCCQ */ +/* Uses MCCQ if available else MBOX */ int be_cmd_if_destroy(struct be_adapter *adapter, int interface_id, u32 domain) { - struct be_mcc_wrb *wrb; + struct be_mcc_wrb wrb = {0}; struct be_cmd_req_if_destroy *req; int status; if (interface_id == -1) return 0; - spin_lock_bh(&adapter->mcc_lock); - - wrb = wrb_from_mccq(adapter); - if (!wrb) { - status = -EBUSY; - goto err; - } - req = embedded_payload(wrb); + req = embedded_payload(&wrb); be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_INTERFACE_DESTROY, - sizeof(*req), wrb, NULL); + sizeof(*req), &wrb, NULL); req->hdr.domain = domain; req->interface_id = cpu_to_le32(interface_id); - status = be_mcc_notify_wait(adapter); -err: - spin_unlock_bh(&adapter->mcc_lock); + status = be_cmd_notify_wait(adapter, &wrb); return status; } diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 9c1fc9dcea25..e4fc87455e00 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -3365,6 +3365,7 @@ done: static void be_rx_qs_destroy(struct be_adapter *adapter) { + struct rss_info *rss = &adapter->rss_info; struct be_queue_info *q; struct be_rx_obj *rxo; int i; @@ -3391,6 +3392,12 @@ static void be_rx_qs_destroy(struct be_adapter *adapter) } be_queue_free(adapter, q); } + + if (rss->rss_flags) { + rss->rss_flags = RSS_ENABLE_NONE; + be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, + 128, rss->rss_hkey); + } } static void be_disable_if_filters(struct be_adapter *adapter) @@ -3511,20 +3518,21 @@ static int be_rx_qs_create(struct be_adapter *adapter) if (!BEx_chip(adapter)) rss->rss_flags |= RSS_ENABLE_UDP_IPV4 | RSS_ENABLE_UDP_IPV6; + + netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); + rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, + RSS_INDIR_TABLE_LEN, rss_key); + if (rc) { + rss->rss_flags = RSS_ENABLE_NONE; + return rc; + } + + memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); } else { /* Disable RSS, if only default RX Q is created */ rss->rss_flags = RSS_ENABLE_NONE; } - netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); - rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, - RSS_INDIR_TABLE_LEN, rss_key); - if (rc) { - rss->rss_flags = RSS_ENABLE_NONE; - return rc; - } - - memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); /* Post 1 less than RXQ-len to avoid head being equal to tail, * which is a queue empty condition @@ -4306,6 +4314,23 @@ err: return status; } +static int be_if_create(struct be_adapter *adapter) +{ + u32 en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS; + u32 cap_flags = be_if_cap_flags(adapter); + int status; + + if (adapter->cfg_num_qs == 1) + cap_flags &= ~(BE_IF_FLAGS_DEFQ_RSS | BE_IF_FLAGS_RSS); + + en_flags &= cap_flags; + /* will enable all the needed filter flags in be_open() */ + status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags, + &adapter->if_handle, 0); + + return status; +} + int be_update_queues(struct be_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -4323,6 +4348,9 @@ int be_update_queues(struct be_adapter *adapter) be_msix_disable(adapter); be_clear_queues(adapter); + status = be_cmd_if_destroy(adapter, adapter->if_handle, 0); + if (status) + return status; if (!msix_enabled(adapter)) { status = be_msix_enable(adapter); @@ -4330,6 +4358,10 @@ int be_update_queues(struct be_adapter *adapter) return status; } + status = be_if_create(adapter); + if (status) + return status; + status = be_setup_queues(adapter); if (status) return status; @@ -4394,7 +4426,6 @@ static int be_func_init(struct be_adapter *adapter) static int be_setup(struct be_adapter *adapter) { struct device *dev = &adapter->pdev->dev; - u32 en_flags; int status; status = be_func_init(adapter); @@ -4427,10 +4458,7 @@ static int be_setup(struct be_adapter *adapter) goto err; /* will enable all the needed filter flags in be_open() */ - en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS; - en_flags = en_flags & be_if_cap_flags(adapter); - status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags, - &adapter->if_handle, 0); + status = be_if_create(adapter); if (status) goto err; @@ -4803,7 +4831,7 @@ static void be_netdev_init(struct net_device *netdev) netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; - if (be_multi_rxq(adapter)) + if ((be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS)) netdev->hw_features |= NETIF_F_RXHASH; netdev->features |= netdev->hw_features | -- cgit From 51d1f98a136fcb16fa3304c2386d9a5202335a63 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 10 Feb 2016 22:45:54 +0530 Subject: be2net: Interpret and log new data that's added to the port misconfigure async event >From FW version 11.0. onwards, the PORT_MISCONFIG event generated by the FW will carry more information about the event in the "data_word1" and "data_word2" fields. This patch adds support in the driver to parse the new information and log it accordingly. This patch also changes some of the messages that are being logged currently. Signed-off-by: Suresh Reddy Signed-off-by: Venkat Duvvuru Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 5 +- drivers/net/ethernet/emulex/benet/be_cmds.c | 82 +++++++++++++++++++++-------- drivers/net/ethernet/emulex/benet/be_cmds.h | 45 +++++++++++++++- drivers/net/ethernet/emulex/benet/be_main.c | 11 ++-- 4 files changed, 116 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 515e206589cc..ab24f84060c6 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -115,6 +115,8 @@ #define RSS_INDIR_TABLE_LEN 128 #define RSS_HASH_KEY_LEN 40 +#define BE_UNKNOWN_PHY_STATE 0xFF + struct be_dma_mem { void *va; dma_addr_t dma; @@ -390,7 +392,7 @@ enum vf_state { #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD BIT(7) #define BE_FLAGS_VXLAN_OFFLOADS BIT(8) #define BE_FLAGS_SETUP_DONE BIT(9) -#define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10) +#define BE_FLAGS_PHY_MISCONFIGURED BIT(10) #define BE_FLAGS_ERR_DETECTION_SCHEDULED BIT(11) #define BE_FLAGS_OS2BMC BIT(12) @@ -603,6 +605,7 @@ struct be_adapter { u32 bmc_filt_mask; u32 fat_dump_len; u16 serial_num[CNTL_SERIAL_NUM_WORDS]; + u8 phy_state; /* state of sfp optics (functional, faulted, etc.,) */ }; #define be_physfn(adapter) (!adapter->virtfn) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 33cbbde218be..66fa21426fe2 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -19,19 +19,25 @@ #include "be.h" #include "be_cmds.h" -static char *be_port_misconfig_evt_desc[] = { - "A valid SFP module detected", - "Optics faulted/ incorrectly installed/ not installed.", - "Optics of two types installed.", - "Incompatible optics.", - "Unknown port SFP status" +char *be_misconfig_evt_port_state[] = { + "Physical Link is functional", + "Optics faulted/incorrectly installed/not installed - Reseat optics. If issue not resolved, replace.", + "Optics of two types installed – Remove one optic or install matching pair of optics.", + "Incompatible optics – Replace with compatible optics for card to function.", + "Unqualified optics – Replace with Avago optics for Warranty and Technical Support.", + "Uncertified optics – Replace with Avago-certified optics to enable link operation." }; -static char *be_port_misconfig_remedy_desc[] = { - "", - "Reseat optics. If issue not resolved, replace", - "Remove one optic or install matching pair of optics", - "Replace with compatible optics for card to function", +static char *be_port_misconfig_evt_severity[] = { + "KERN_WARN", + "KERN_INFO", + "KERN_ERR", + "KERN_WARN" +}; + +static char *phy_state_oper_desc[] = { + "Link is non-operational", + "Link is operational", "" }; @@ -297,22 +303,56 @@ static void be_async_port_misconfig_event_process(struct be_adapter *adapter, { struct be_async_event_misconfig_port *evt = (struct be_async_event_misconfig_port *)compl; - u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1); + u32 sfp_misconfig_evt_word1 = le32_to_cpu(evt->event_data_word1); + u32 sfp_misconfig_evt_word2 = le32_to_cpu(evt->event_data_word2); + u8 phy_oper_state = PHY_STATE_OPER_MSG_NONE; struct device *dev = &adapter->pdev->dev; - u8 port_misconfig_evt; + u8 msg_severity = DEFAULT_MSG_SEVERITY; + u8 phy_state_info; + u8 new_phy_state; + + new_phy_state = + (sfp_misconfig_evt_word1 >> (adapter->hba_port_num * 8)) & 0xff; + + if (new_phy_state == adapter->phy_state) + return; + + adapter->phy_state = new_phy_state; - port_misconfig_evt = - ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff); + /* for older fw that doesn't populate link effect data */ + if (!sfp_misconfig_evt_word2) + goto log_message; + phy_state_info = + (sfp_misconfig_evt_word2 >> (adapter->hba_port_num * 8)) & 0xff; + + if (phy_state_info & PHY_STATE_INFO_VALID) { + msg_severity = (phy_state_info & PHY_STATE_MSG_SEVERITY) >> 1; + + if (be_phy_unqualified(new_phy_state)) + phy_oper_state = (phy_state_info & PHY_STATE_OPER); + } + +log_message: /* Log an error message that would allow a user to determine * whether the SFPs have an issue */ - dev_info(dev, "Port %c: %s %s", adapter->port_name, - be_port_misconfig_evt_desc[port_misconfig_evt], - be_port_misconfig_remedy_desc[port_misconfig_evt]); - - if (port_misconfig_evt == INCOMPATIBLE_SFP) - adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP; + if (be_phy_state_unknown(new_phy_state)) + dev_printk(be_port_misconfig_evt_severity[msg_severity], dev, + "Port %c: Unrecognized Optics state: 0x%x. %s", + adapter->port_name, + new_phy_state, + phy_state_oper_desc[phy_oper_state]); + else + dev_printk(be_port_misconfig_evt_severity[msg_severity], dev, + "Port %c: %s %s", + adapter->port_name, + be_misconfig_evt_port_state[new_phy_state], + phy_state_oper_desc[phy_oper_state]); + + /* Log Vendor name and part no. if a misconfigured SFP is detected */ + if (be_phy_misconfigured(new_phy_state)) + adapter->flags |= BE_FLAGS_PHY_MISCONFIGURED; } /* Grp5 CoS Priority evt */ diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index f260ef3329a1..0b9f741f31af 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -176,10 +176,53 @@ struct be_async_event_qnq { u32 flags; } __packed; -#define INCOMPATIBLE_SFP 0x3 +enum { + BE_PHY_FUNCTIONAL = 0, + BE_PHY_NOT_PRESENT = 1, + BE_PHY_DIFF_MEDIA = 2, + BE_PHY_INCOMPATIBLE = 3, + BE_PHY_UNQUALIFIED = 4, + BE_PHY_UNCERTIFIED = 5 +}; + +#define PHY_STATE_MSG_SEVERITY 0x6 +#define PHY_STATE_OPER 0x1 +#define PHY_STATE_INFO_VALID 0x80 +#define PHY_STATE_OPER_MSG_NONE 0x2 +#define DEFAULT_MSG_SEVERITY 0x1 + +#define be_phy_state_unknown(phy_state) (phy_state > BE_PHY_UNCERTIFIED) +#define be_phy_unqualified(phy_state) \ + (phy_state == BE_PHY_UNQUALIFIED || \ + phy_state == BE_PHY_UNCERTIFIED) +#define be_phy_misconfigured(phy_state) \ + (phy_state == BE_PHY_INCOMPATIBLE || \ + phy_state == BE_PHY_UNQUALIFIED || \ + phy_state == BE_PHY_UNCERTIFIED) + +extern char *be_misconfig_evt_port_state[]; + /* async event indicating misconfigured port */ struct be_async_event_misconfig_port { + /* DATA_WORD1: + * phy state of port 0: bits 7 - 0 + * phy state of port 1: bits 15 - 8 + * phy state of port 2: bits 23 - 16 + * phy state of port 3: bits 31 - 24 + */ u32 event_data_word1; + /* DATA_WORD2: + * phy state info of port 0: bits 7 - 0 + * phy state info of port 1: bits 15 - 8 + * phy state info of port 2: bits 23 - 16 + * phy state info of port 3: bits 31 - 24 + * + * PHY STATE INFO: + * Link operability :bit 0 + * Message severity :bit 2 - 1 + * Rsvd :bits 6 - 3 + * phy state info valid :bit 7 + */ u32 event_data_word2; u32 rsvd0; u32 flags; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e4fc87455e00..4ecd8c2beaf5 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4089,6 +4089,7 @@ static void be_setup_init(struct be_adapter *adapter) adapter->if_handle = -1; adapter->be3_native = false; adapter->if_flags = 0; + adapter->phy_state = BE_UNKNOWN_PHY_STATE; if (be_physfn(adapter)) adapter->cmd_privileges = MAX_PRIVILEGES; else @@ -4961,11 +4962,13 @@ static void be_log_sfp_info(struct be_adapter *adapter) status = be_cmd_query_sfp_info(adapter); if (!status) { dev_err(&adapter->pdev->dev, - "Unqualified SFP+ detected on %c from %s part no: %s", - adapter->port_name, adapter->phy.vendor_name, + "Port %c: %s Vendor: %s part no: %s", + adapter->port_name, + be_misconfig_evt_port_state[adapter->phy_state], + adapter->phy.vendor_name, adapter->phy.vendor_pn); } - adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP; + adapter->flags &= ~BE_FLAGS_PHY_MISCONFIGURED; } static void be_worker(struct work_struct *work) @@ -5009,7 +5012,7 @@ static void be_worker(struct work_struct *work) if (!skyhawk_chip(adapter)) be_eqd_update(adapter, false); - if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP) + if (adapter->flags & BE_FLAGS_PHY_MISCONFIGURED) be_log_sfp_info(adapter); reschedule: -- cgit From 086c653f5862591a9cfe2386f5650d03adacc33a Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:35 -0500 Subject: sock: struct proto hash function may error In order to support fast reuseport lookups in TCP, the hash function defined in struct proto must be capable of returning an error code. This patch changes the function signature of all related hash functions to return an integer and handles or propagates this return value at all call sites. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- include/net/inet_hashtables.h | 2 +- include/net/phonet/phonet.h | 2 +- include/net/ping.h | 2 +- include/net/raw.h | 2 +- include/net/sock.h | 6 +++--- include/net/udp.h | 3 ++- net/ieee802154/socket.c | 17 +++++++++++++---- net/ipv4/af_inet.c | 9 ++++++--- net/ipv4/inet_connection_sock.c | 8 +++++--- net/ipv4/inet_hashtables.c | 4 +++- net/ipv4/ping.c | 4 +++- net/ipv4/raw.c | 4 +++- net/ipv6/af_inet6.c | 6 +++++- net/phonet/socket.c | 6 ++++-- net/sctp/socket.c | 3 ++- 15 files changed, 53 insertions(+), 25 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index de2e3ade6102..554440e7f83d 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -208,7 +208,7 @@ void inet_hashinfo_init(struct inet_hashinfo *h); bool inet_ehash_insert(struct sock *sk, struct sock *osk); bool inet_ehash_nolisten(struct sock *sk, struct sock *osk); void __inet_hash(struct sock *sk, struct sock *osk); -void inet_hash(struct sock *sk); +int inet_hash(struct sock *sk); void inet_unhash(struct sock *sk); struct sock *__inet_lookup_listener(struct net *net, diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h index 68e509750caa..039cc29cb4a8 100644 --- a/include/net/phonet/phonet.h +++ b/include/net/phonet/phonet.h @@ -51,7 +51,7 @@ void pn_sock_init(void); struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *sa); void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb); void phonet_get_local_port_range(int *min, int *max); -void pn_sock_hash(struct sock *sk); +int pn_sock_hash(struct sock *sk); void pn_sock_unhash(struct sock *sk); int pn_sock_get_port(struct sock *sk, unsigned short sport); diff --git a/include/net/ping.h b/include/net/ping.h index ac80cb45e630..5fd7cc244833 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -65,7 +65,7 @@ struct pingfakehdr { }; int ping_get_port(struct sock *sk, unsigned short ident); -void ping_hash(struct sock *sk); +int ping_hash(struct sock *sk); void ping_unhash(struct sock *sk); int ping_init_sock(struct sock *sk); diff --git a/include/net/raw.h b/include/net/raw.h index 6a40c6562dd2..3e789008394d 100644 --- a/include/net/raw.h +++ b/include/net/raw.h @@ -57,7 +57,7 @@ int raw_seq_open(struct inode *ino, struct file *file, #endif -void raw_hash_sk(struct sock *sk); +int raw_hash_sk(struct sock *sk); void raw_unhash_sk(struct sock *sk); struct raw_sock { diff --git a/include/net/sock.h b/include/net/sock.h index f5ea148853e2..255d3e03727b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -984,7 +984,7 @@ struct proto { void (*release_cb)(struct sock *sk); /* Keeping track of sk's, looking them up, and port selection methods. */ - void (*hash)(struct sock *sk); + int (*hash)(struct sock *sk); void (*unhash)(struct sock *sk); void (*rehash)(struct sock *sk); int (*get_port)(struct sock *sk, unsigned short snum); @@ -1194,10 +1194,10 @@ static inline void sock_prot_inuse_add(struct net *net, struct proto *prot, /* With per-bucket locks this operation is not-atomic, so that * this version is not worse. */ -static inline void __sk_prot_rehash(struct sock *sk) +static inline int __sk_prot_rehash(struct sock *sk) { sk->sk_prot->unhash(sk); - sk->sk_prot->hash(sk); + return sk->sk_prot->hash(sk); } void sk_prot_clear_portaddr_nulls(struct sock *sk, int size); diff --git a/include/net/udp.h b/include/net/udp.h index 2842541e28e7..92927f729ac8 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -177,9 +177,10 @@ static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb) } /* hash routines shared between UDPv4/6 and UDP-Litev4/6 */ -static inline void udp_lib_hash(struct sock *sk) +static inline int udp_lib_hash(struct sock *sk) { BUG(); + return 0; } void udp_lib_unhash(struct sock *sk); diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c index a548be247e15..e0bd013a1e5e 100644 --- a/net/ieee802154/socket.c +++ b/net/ieee802154/socket.c @@ -182,12 +182,14 @@ static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, static HLIST_HEAD(raw_head); static DEFINE_RWLOCK(raw_lock); -static void raw_hash(struct sock *sk) +static int raw_hash(struct sock *sk) { write_lock_bh(&raw_lock); sk_add_node(sk, &raw_head); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock_bh(&raw_lock); + + return 0; } static void raw_unhash(struct sock *sk) @@ -462,12 +464,14 @@ static inline struct dgram_sock *dgram_sk(const struct sock *sk) return container_of(sk, struct dgram_sock, sk); } -static void dgram_hash(struct sock *sk) +static int dgram_hash(struct sock *sk) { write_lock_bh(&dgram_lock); sk_add_node(sk, &dgram_head); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock_bh(&dgram_lock); + + return 0; } static void dgram_unhash(struct sock *sk) @@ -1026,8 +1030,13 @@ static int ieee802154_create(struct net *net, struct socket *sock, /* Checksums on by default */ sock_set_flag(sk, SOCK_ZAPPED); - if (sk->sk_prot->hash) - sk->sk_prot->hash(sk); + if (sk->sk_prot->hash) { + rc = sk->sk_prot->hash(sk); + if (rc) { + sk_common_release(sk); + goto out; + } + } if (sk->sk_prot->init) { rc = sk->sk_prot->init(sk); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 5c5db6636704..eade66db214e 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -370,7 +370,11 @@ lookup_protocol: */ inet->inet_sport = htons(inet->inet_num); /* Add to protocol hash chains. */ - sk->sk_prot->hash(sk); + err = sk->sk_prot->hash(sk); + if (err) { + sk_common_release(sk); + goto out; + } } if (sk->sk_prot->init) { @@ -1142,8 +1146,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) * Besides that, it does not check for connection * uniqueness. Wait for troubles. */ - __sk_prot_rehash(sk); - return 0; + return __sk_prot_rehash(sk); } int inet_sk_rebuild_header(struct sock *sk) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 9b17c1792dce..12c8d389dc18 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -734,6 +734,7 @@ int inet_csk_listen_start(struct sock *sk, int backlog) { struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); + int err = -EADDRINUSE; reqsk_queue_alloc(&icsk->icsk_accept_queue); @@ -751,13 +752,14 @@ int inet_csk_listen_start(struct sock *sk, int backlog) inet->inet_sport = htons(inet->inet_num); sk_dst_reset(sk); - sk->sk_prot->hash(sk); + err = sk->sk_prot->hash(sk); - return 0; + if (likely(!err)) + return 0; } sk->sk_state = TCP_CLOSE; - return -EADDRINUSE; + return err; } EXPORT_SYMBOL_GPL(inet_csk_listen_start); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index ccc5980797fc..b6023b7baae0 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -468,13 +468,15 @@ void __inet_hash(struct sock *sk, struct sock *osk) } EXPORT_SYMBOL(__inet_hash); -void inet_hash(struct sock *sk) +int inet_hash(struct sock *sk) { if (sk->sk_state != TCP_CLOSE) { local_bh_disable(); __inet_hash(sk, NULL); local_bh_enable(); } + + return 0; } EXPORT_SYMBOL_GPL(inet_hash); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index c117b21b937d..f6f93fc2c61f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -145,10 +145,12 @@ fail: } EXPORT_SYMBOL_GPL(ping_get_port); -void ping_hash(struct sock *sk) +int ping_hash(struct sock *sk) { pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); BUG(); /* "Please do not press this button again." */ + + return 0; } void ping_unhash(struct sock *sk) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bc35f1842512..d6352515d738 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -93,7 +93,7 @@ static struct raw_hashinfo raw_v4_hashinfo = { .lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock), }; -void raw_hash_sk(struct sock *sk) +int raw_hash_sk(struct sock *sk) { struct raw_hashinfo *h = sk->sk_prot->h.raw_hash; struct hlist_head *head; @@ -104,6 +104,8 @@ void raw_hash_sk(struct sock *sk) sk_add_node(sk, head); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); write_unlock_bh(&h->lock); + + return 0; } EXPORT_SYMBOL_GPL(raw_hash_sk); diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 9f5137cd604e..b11c37cfd67c 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -235,7 +235,11 @@ lookup_protocol: * creation time automatically shares. */ inet->inet_sport = htons(inet->inet_num); - sk->sk_prot->hash(sk); + err = sk->sk_prot->hash(sk); + if (err) { + sk_common_release(sk); + goto out; + } } if (sk->sk_prot->init) { err = sk->sk_prot->init(sk); diff --git a/net/phonet/socket.c b/net/phonet/socket.c index d575ef4e9aa6..ffd5f2297584 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -140,13 +140,15 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) rcu_read_unlock(); } -void pn_sock_hash(struct sock *sk) +int pn_sock_hash(struct sock *sk) { struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); mutex_lock(&pnsocks.lock); sk_add_node_rcu(sk, hlist); mutex_unlock(&pnsocks.lock); + + return 0; } EXPORT_SYMBOL(pn_sock_hash); @@ -200,7 +202,7 @@ static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len) pn->resource = spn->spn_resource; /* Enable RX on the socket */ - sk->sk_prot->hash(sk); + err = sk->sk_prot->hash(sk); out_port: mutex_unlock(&port_mutex); out: diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5ca2ebfe0be8..6427b9d1197e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -6101,9 +6101,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, return retval; } -static void sctp_hash(struct sock *sk) +static int sctp_hash(struct sock *sk) { /* STUB */ + return 0; } static void sctp_unhash(struct sock *sk) -- cgit From 496611d7b5eaf59c03440c8f2def1d9988ad2459 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:36 -0500 Subject: inet: create IPv6-equivalent inet_hash function In order to support fast lookups for TCP sockets with SO_REUSEPORT, the function that adds sockets to the listening hash set needs to be able to check receive address equality. Since this equality check is different for IPv4 and IPv6, we will need two different socket hashing functions. This patch adds inet6_hash identical to the existing inet_hash function and updates the appropriate references. A following patch will differentiate the two by passing different comparison functions to __inet_hash. Additionally, in order to use the IPv6 address equality function from inet6_hashtables (which is compiled as a built-in object when IPv6 is enabled) it also needs to be in a built-in object file as well. This moves ipv6_rcv_saddr_equal into inet_hashtables to accomplish this. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- include/net/inet6_hashtables.h | 2 ++ net/dccp/ipv6.c | 2 +- net/ipv6/inet6_hashtables.c | 56 ++++++++++++++++++++++++++++++++++++++++++ net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/udp.c | 44 +-------------------------------- net/l2tp/l2tp_ip6.c | 3 ++- 6 files changed, 63 insertions(+), 46 deletions(-) diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 7ff588ca6817..b3c28a9dfbf1 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -96,6 +96,8 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif); + +int inet6_hash(struct sock *sk); #endif /* IS_ENABLED(CONFIG_IPV6) */ #define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif) \ diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 9c6d0508e63a..90a8269b28d0 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -993,7 +993,7 @@ static struct proto dccp_v6_prot = { .sendmsg = dccp_sendmsg, .recvmsg = dccp_recvmsg, .backlog_rcv = dccp_v6_do_rcv, - .hash = inet_hash, + .hash = inet6_hash, .unhash = inet_unhash, .accept = inet_csk_accept, .get_port = inet_csk_get_port, diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 21ace5a2bf7c..072653dd9c98 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -274,3 +274,59 @@ int inet6_hash_connect(struct inet_timewait_death_row *death_row, __inet6_check_established); } EXPORT_SYMBOL_GPL(inet6_hash_connect); + +int inet6_hash(struct sock *sk) +{ + if (sk->sk_state != TCP_CLOSE) { + local_bh_disable(); + __inet_hash(sk, NULL); + local_bh_enable(); + } + + return 0; +} +EXPORT_SYMBOL_GPL(inet6_hash); + +/* match_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses if IPv6 + * only, and any IPv4 addresses if not IPv6 only + * match_wildcard == false: addresses must be exactly the same, i.e. + * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY, + * and 0.0.0.0 equals to 0.0.0.0 only + */ +int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, + bool match_wildcard) +{ + const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); + int sk2_ipv6only = inet_v6_ipv6only(sk2); + int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); + int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; + + /* if both are mapped, treat as IPv4 */ + if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) { + if (!sk2_ipv6only) { + if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr) + return 1; + if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr) + return match_wildcard; + } + return 0; + } + + if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY) + return 1; + + if (addr_type2 == IPV6_ADDR_ANY && match_wildcard && + !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) + return 1; + + if (addr_type == IPV6_ADDR_ANY && match_wildcard && + !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED)) + return 1; + + if (sk2_rcv_saddr6 && + ipv6_addr_equal(&sk->sk_v6_rcv_saddr, sk2_rcv_saddr6)) + return 1; + + return 0; +} +EXPORT_SYMBOL_GPL(ipv6_rcv_saddr_equal); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 006396e31cb0..d72bcfb326d8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1865,7 +1865,7 @@ struct proto tcpv6_prot = { .sendpage = tcp_sendpage, .backlog_rcv = tcp_v6_do_rcv, .release_cb = tcp_release_cb, - .hash = inet_hash, + .hash = inet6_hash, .unhash = inet_unhash, .get_port = inet_csk_get_port, .enter_memory_pressure = tcp_enter_memory_pressure, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 22e28a44e3c8..ac4e7e03dded 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -77,49 +78,6 @@ static u32 udp6_ehashfn(const struct net *net, udp_ipv6_hash_secret + net_hash_mix(net)); } -/* match_wildcard == true: IPV6_ADDR_ANY equals to any IPv6 addresses if IPv6 - * only, and any IPv4 addresses if not IPv6 only - * match_wildcard == false: addresses must be exactly the same, i.e. - * IPV6_ADDR_ANY only equals to IPV6_ADDR_ANY, - * and 0.0.0.0 equals to 0.0.0.0 only - */ -int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, - bool match_wildcard) -{ - const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); - int sk2_ipv6only = inet_v6_ipv6only(sk2); - int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); - int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; - - /* if both are mapped, treat as IPv4 */ - if (addr_type == IPV6_ADDR_MAPPED && addr_type2 == IPV6_ADDR_MAPPED) { - if (!sk2_ipv6only) { - if (sk->sk_rcv_saddr == sk2->sk_rcv_saddr) - return 1; - if (!sk->sk_rcv_saddr || !sk2->sk_rcv_saddr) - return match_wildcard; - } - return 0; - } - - if (addr_type == IPV6_ADDR_ANY && addr_type2 == IPV6_ADDR_ANY) - return 1; - - if (addr_type2 == IPV6_ADDR_ANY && match_wildcard && - !(sk2_ipv6only && addr_type == IPV6_ADDR_MAPPED)) - return 1; - - if (addr_type == IPV6_ADDR_ANY && match_wildcard && - !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED)) - return 1; - - if (sk2_rcv_saddr6 && - ipv6_addr_equal(&sk->sk_v6_rcv_saddr, sk2_rcv_saddr6)) - return 1; - - return 0; -} - static u32 udp6_portaddr_hash(const struct net *net, const struct in6_addr *addr6, unsigned int port) diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index a2c8747d2936..6b54ff3ff4cb 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -718,7 +719,7 @@ static struct proto l2tp_ip6_prot = { .sendmsg = l2tp_ip6_sendmsg, .recvmsg = l2tp_ip6_recvmsg, .backlog_rcv = l2tp_ip6_backlog_recv, - .hash = inet_hash, + .hash = inet6_hash, .unhash = inet_unhash, .obj_size = sizeof(struct l2tp_ip6_sock), #ifdef CONFIG_COMPAT -- cgit From d9b3fca27385eafe61c3ca6feab6cb1e7dc77482 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:37 -0500 Subject: tcp: __tcp_hdrlen() helper tcp_hdrlen is wasteful if you already have a pointer to struct tcphdr. This splits the size calculation into a helper function that can be used if a struct tcphdr is already available. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- include/linux/tcp.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/tcp.h b/include/linux/tcp.h index d909feeeaea2..bcbf51da4e1e 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -29,9 +29,14 @@ static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb) return (struct tcphdr *)skb_transport_header(skb); } +static inline unsigned int __tcp_hdrlen(const struct tcphdr *th) +{ + return th->doff * 4; +} + static inline unsigned int tcp_hdrlen(const struct sk_buff *skb) { - return tcp_hdr(skb)->doff * 4; + return __tcp_hdrlen(tcp_hdr(skb)); } static inline struct tcphdr *inner_tcp_hdr(const struct sk_buff *skb) -- cgit From a583636a83ea383fd07517e5a7a2eedbc5d90fb1 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:38 -0500 Subject: inet: refactor inet[6]_lookup functions to take skb This is a preliminary step to allow fast socket lookup of SO_REUSEPORT groups. Doing so with a BPF filter will require access to the skb in question. This change plumbs the skb (and offset to payload data) through the call stack to the listening socket lookup implementations where it will be used in a following patch. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- include/net/addrconf.h | 2 ++ include/net/inet6_hashtables.h | 11 +++++++---- include/net/inet_hashtables.h | 18 ++++++++++++------ net/dccp/ipv4.c | 2 +- net/dccp/ipv6.c | 2 +- net/ipv4/inet_diag.c | 6 +++--- net/ipv4/inet_hashtables.c | 1 + net/ipv4/tcp_ipv4.c | 10 ++++++---- net/ipv6/inet6_hashtables.c | 8 ++++++-- net/ipv6/tcp_ipv6.c | 8 +++++--- net/netfilter/xt_TPROXY.c | 31 ++++++++++++++++++++----------- net/netfilter/xt_socket.c | 28 +++++++++++++++++++++------- 12 files changed, 85 insertions(+), 42 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 47f52d3cd8df..730d856683e5 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -87,6 +87,8 @@ int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, u32 banned_flags); int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, u32 banned_flags); +int ipv4_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, + bool match_wildcard); int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2, bool match_wildcard); void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr); diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index b3c28a9dfbf1..28332bdac333 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -53,6 +53,7 @@ struct sock *__inet6_lookup_established(struct net *net, struct sock *inet6_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, @@ -60,6 +61,7 @@ struct sock *inet6_lookup_listener(struct net *net, static inline struct sock *__inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, @@ -71,12 +73,12 @@ static inline struct sock *__inet6_lookup(struct net *net, if (sk) return sk; - return inet6_lookup_listener(net, hashinfo, saddr, sport, + return inet6_lookup_listener(net, hashinfo, skb, doff, saddr, sport, daddr, hnum, dif); } static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, - struct sk_buff *skb, + struct sk_buff *skb, int doff, const __be16 sport, const __be16 dport, int iif) @@ -86,13 +88,14 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, if (sk) return sk; - return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, - &ipv6_hdr(skb)->saddr, sport, + return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, + doff, &ipv6_hdr(skb)->saddr, sport, &ipv6_hdr(skb)->daddr, ntohs(dport), iif); } struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif); diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 554440e7f83d..82403390af58 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -213,6 +213,7 @@ void inet_unhash(struct sock *sk); struct sock *__inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const unsigned short hnum, @@ -220,10 +221,11 @@ struct sock *__inet_lookup_listener(struct net *net, static inline struct sock *inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif) { - return __inet_lookup_listener(net, hashinfo, saddr, sport, + return __inet_lookup_listener(net, hashinfo, skb, doff, saddr, sport, daddr, ntohs(dport), dif); } @@ -299,6 +301,7 @@ static inline struct sock * static inline struct sock *__inet_lookup(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) @@ -307,12 +310,13 @@ static inline struct sock *__inet_lookup(struct net *net, struct sock *sk = __inet_lookup_established(net, hashinfo, saddr, sport, daddr, hnum, dif); - return sk ? : __inet_lookup_listener(net, hashinfo, saddr, sport, - daddr, hnum, dif); + return sk ? : __inet_lookup_listener(net, hashinfo, skb, doff, saddr, + sport, daddr, hnum, dif); } static inline struct sock *inet_lookup(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const __be32 saddr, const __be16 sport, const __be32 daddr, const __be16 dport, const int dif) @@ -320,7 +324,8 @@ static inline struct sock *inet_lookup(struct net *net, struct sock *sk; local_bh_disable(); - sk = __inet_lookup(net, hashinfo, saddr, sport, daddr, dport, dif); + sk = __inet_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, + dport, dif); local_bh_enable(); return sk; @@ -328,6 +333,7 @@ static inline struct sock *inet_lookup(struct net *net, static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, struct sk_buff *skb, + int doff, const __be16 sport, const __be16 dport) { @@ -337,8 +343,8 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, if (sk) return sk; else - return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, - iph->saddr, sport, + return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, skb, + doff, iph->saddr, sport, iph->daddr, dport, inet_iif(skb)); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 5684e14932bd..1e0c600c83ae 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -802,7 +802,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) } lookup: - sk = __inet_lookup_skb(&dccp_hashinfo, skb, + sk = __inet_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh), dh->dccph_sport, dh->dccph_dport); if (!sk) { dccp_pr_debug("failed to look up flow ID in table and " diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 90a8269b28d0..45cbe85f0940 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -668,7 +668,7 @@ static int dccp_v6_rcv(struct sk_buff *skb) DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb); lookup: - sk = __inet6_lookup_skb(&dccp_hashinfo, skb, + sk = __inet6_lookup_skb(&dccp_hashinfo, skb, __dccp_hdr_len(dh), dh->dccph_sport, dh->dccph_dport, inet6_iif(skb)); if (!sk) { diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 6029157a19ed..50c0d96b8441 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -357,18 +357,18 @@ struct sock *inet_diag_find_one_icsk(struct net *net, struct sock *sk; if (req->sdiag_family == AF_INET) - sk = inet_lookup(net, hashinfo, req->id.idiag_dst[0], + sk = inet_lookup(net, hashinfo, NULL, 0, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_src[0], req->id.idiag_sport, req->id.idiag_if); #if IS_ENABLED(CONFIG_IPV6) else if (req->sdiag_family == AF_INET6) { if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) && ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src)) - sk = inet_lookup(net, hashinfo, req->id.idiag_dst[3], + sk = inet_lookup(net, hashinfo, NULL, 0, req->id.idiag_dst[3], req->id.idiag_dport, req->id.idiag_src[3], req->id.idiag_sport, req->id.idiag_if); else - sk = inet6_lookup(net, hashinfo, + sk = inet6_lookup(net, hashinfo, NULL, 0, (struct in6_addr *)req->id.idiag_dst, req->id.idiag_dport, (struct in6_addr *)req->id.idiag_src, diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index b6023b7baae0..5e4290b83255 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -205,6 +205,7 @@ static inline int compute_score(struct sock *sk, struct net *net, struct sock *__inet_lookup_listener(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const __be32 saddr, __be16 sport, const __be32 daddr, const unsigned short hnum, const int dif) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0d381fa164f8..3f872a6bc274 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -637,8 +637,8 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) * Incoming packet is checked with md5 hash with finding key, * no RST generated if md5 hash doesn't match. */ - sk1 = __inet_lookup_listener(net, - &tcp_hashinfo, ip_hdr(skb)->saddr, + sk1 = __inet_lookup_listener(net, &tcp_hashinfo, NULL, 0, + ip_hdr(skb)->saddr, th->source, ip_hdr(skb)->daddr, ntohs(th->source), inet_iif(skb)); /* don't send rst if it can't find key */ @@ -1581,7 +1581,8 @@ int tcp_v4_rcv(struct sk_buff *skb) TCP_SKB_CB(skb)->sacked = 0; lookup: - sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); + sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source, + th->dest); if (!sk) goto no_tcp_socket; @@ -1695,7 +1696,8 @@ do_time_wait: switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) { case TCP_TW_SYN: { struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev), - &tcp_hashinfo, + &tcp_hashinfo, skb, + __tcp_hdrlen(th), iph->saddr, th->source, iph->daddr, th->dest, inet_iif(skb)); diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 072653dd9c98..004345d26808 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -121,7 +121,9 @@ static inline int compute_score(struct sock *sk, struct net *net, } struct sock *inet6_lookup_listener(struct net *net, - struct inet_hashinfo *hashinfo, const struct in6_addr *saddr, + struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, + const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const unsigned short hnum, const int dif) { @@ -177,6 +179,7 @@ begin: EXPORT_SYMBOL_GPL(inet6_lookup_listener); struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, + struct sk_buff *skb, int doff, const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif) @@ -184,7 +187,8 @@ struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, struct sock *sk; local_bh_disable(); - sk = __inet6_lookup(net, hashinfo, saddr, sport, daddr, ntohs(dport), dif); + sk = __inet6_lookup(net, hashinfo, skb, doff, saddr, sport, daddr, + ntohs(dport), dif); local_bh_enable(); return sk; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d72bcfb326d8..9977b6f19f2a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -866,7 +866,8 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) * no RST generated if md5 hash doesn't match. */ sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), - &tcp_hashinfo, &ipv6h->saddr, + &tcp_hashinfo, NULL, 0, + &ipv6h->saddr, th->source, &ipv6h->daddr, ntohs(th->source), tcp_v6_iif(skb)); if (!sk1) @@ -1375,8 +1376,8 @@ static int tcp_v6_rcv(struct sk_buff *skb) hdr = ipv6_hdr(skb); lookup: - sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, - inet6_iif(skb)); + sk = __inet6_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), + th->source, th->dest, inet6_iif(skb)); if (!sk) goto no_tcp_socket; @@ -1500,6 +1501,7 @@ do_time_wait: struct sock *sk2; sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, + skb, __tcp_hdrlen(th), &ipv6_hdr(skb)->saddr, th->source, &ipv6_hdr(skb)->daddr, ntohs(th->dest), tcp_v6_iif(skb)); diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c index 3ab591e73ec0..7f4414d26a66 100644 --- a/net/netfilter/xt_TPROXY.c +++ b/net/netfilter/xt_TPROXY.c @@ -105,19 +105,24 @@ tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) * belonging to established connections going through that one. */ static inline struct sock * -nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, +nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb, void *hp, + const u8 protocol, const __be32 saddr, const __be32 daddr, const __be16 sport, const __be16 dport, const struct net_device *in, const enum nf_tproxy_lookup_t lookup_type) { struct sock *sk; + struct tcphdr *tcph; switch (protocol) { case IPPROTO_TCP: switch (lookup_type) { case NFT_LOOKUP_LISTENER: - sk = inet_lookup_listener(net, &tcp_hashinfo, + tcph = hp; + sk = inet_lookup_listener(net, &tcp_hashinfo, skb, + ip_hdrlen(skb) + + __tcp_hdrlen(tcph), saddr, sport, daddr, dport, in->ifindex); @@ -169,19 +174,23 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, #ifdef XT_TPROXY_HAVE_IPV6 static inline struct sock * -nf_tproxy_get_sock_v6(struct net *net, const u8 protocol, +nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff, void *hp, + const u8 protocol, const struct in6_addr *saddr, const struct in6_addr *daddr, const __be16 sport, const __be16 dport, const struct net_device *in, const enum nf_tproxy_lookup_t lookup_type) { struct sock *sk; + struct tcphdr *tcph; switch (protocol) { case IPPROTO_TCP: switch (lookup_type) { case NFT_LOOKUP_LISTENER: - sk = inet6_lookup_listener(net, &tcp_hashinfo, + tcph = hp; + sk = inet6_lookup_listener(net, &tcp_hashinfo, skb, + thoff + __tcp_hdrlen(tcph), saddr, sport, daddr, ntohs(dport), in->ifindex); @@ -267,7 +276,7 @@ tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb, * to a listener socket if there's one */ struct sock *sk2; - sk2 = nf_tproxy_get_sock_v4(net, iph->protocol, + sk2 = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, iph->saddr, laddr ? laddr : iph->daddr, hp->source, lport ? lport : hp->dest, skb->dev, NFT_LOOKUP_LISTENER); @@ -305,7 +314,7 @@ tproxy_tg4(struct net *net, struct sk_buff *skb, __be32 laddr, __be16 lport, * addresses, this happens if the redirect already happened * and the current packet belongs to an already established * connection */ - sk = nf_tproxy_get_sock_v4(net, iph->protocol, + sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, iph->saddr, iph->daddr, hp->source, hp->dest, skb->dev, NFT_LOOKUP_ESTABLISHED); @@ -321,7 +330,7 @@ tproxy_tg4(struct net *net, struct sk_buff *skb, __be32 laddr, __be16 lport, else if (!sk) /* no, there's no established connection, check if * there's a listener on the redirected addr/port */ - sk = nf_tproxy_get_sock_v4(net, iph->protocol, + sk = nf_tproxy_get_sock_v4(net, skb, hp, iph->protocol, iph->saddr, laddr, hp->source, lport, skb->dev, NFT_LOOKUP_LISTENER); @@ -429,7 +438,7 @@ tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff, * to a listener socket if there's one */ struct sock *sk2; - sk2 = nf_tproxy_get_sock_v6(par->net, tproto, + sk2 = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto, &iph->saddr, tproxy_laddr6(skb, &tgi->laddr.in6, &iph->daddr), hp->source, @@ -472,7 +481,7 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par) * addresses, this happens if the redirect already happened * and the current packet belongs to an already established * connection */ - sk = nf_tproxy_get_sock_v6(par->net, tproto, + sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, tproto, &iph->saddr, &iph->daddr, hp->source, hp->dest, par->in, NFT_LOOKUP_ESTABLISHED); @@ -487,8 +496,8 @@ tproxy_tg6_v1(struct sk_buff *skb, const struct xt_action_param *par) else if (!sk) /* no there's no established connection, check if * there's a listener on the redirected addr/port */ - sk = nf_tproxy_get_sock_v6(par->net, tproto, - &iph->saddr, laddr, + sk = nf_tproxy_get_sock_v6(par->net, skb, thoff, hp, + tproto, &iph->saddr, laddr, hp->source, lport, par->in, NFT_LOOKUP_LISTENER); diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 2ec08f04b816..49d14ecad444 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c @@ -112,14 +112,15 @@ extract_icmp4_fields(const struct sk_buff *skb, * box. */ static struct sock * -xt_socket_get_sock_v4(struct net *net, const u8 protocol, +xt_socket_get_sock_v4(struct net *net, struct sk_buff *skb, const int doff, + const u8 protocol, const __be32 saddr, const __be32 daddr, const __be16 sport, const __be16 dport, const struct net_device *in) { switch (protocol) { case IPPROTO_TCP: - return __inet_lookup(net, &tcp_hashinfo, + return __inet_lookup(net, &tcp_hashinfo, skb, doff, saddr, sport, daddr, dport, in->ifindex); case IPPROTO_UDP: @@ -148,6 +149,8 @@ static struct sock *xt_socket_lookup_slow_v4(struct net *net, const struct net_device *indev) { const struct iphdr *iph = ip_hdr(skb); + struct sk_buff *data_skb = NULL; + int doff = 0; __be32 uninitialized_var(daddr), uninitialized_var(saddr); __be16 uninitialized_var(dport), uninitialized_var(sport); u8 uninitialized_var(protocol); @@ -169,6 +172,10 @@ static struct sock *xt_socket_lookup_slow_v4(struct net *net, sport = hp->source; daddr = iph->daddr; dport = hp->dest; + data_skb = (struct sk_buff *)skb; + doff = iph->protocol == IPPROTO_TCP ? + ip_hdrlen(skb) + __tcp_hdrlen((struct tcphdr *)hp) : + ip_hdrlen(skb) + sizeof(*hp); } else if (iph->protocol == IPPROTO_ICMP) { if (extract_icmp4_fields(skb, &protocol, &saddr, &daddr, @@ -198,8 +205,8 @@ static struct sock *xt_socket_lookup_slow_v4(struct net *net, } #endif - return xt_socket_get_sock_v4(net, protocol, saddr, daddr, - sport, dport, indev); + return xt_socket_get_sock_v4(net, data_skb, doff, protocol, saddr, + daddr, sport, dport, indev); } static bool @@ -318,14 +325,15 @@ extract_icmp6_fields(const struct sk_buff *skb, } static struct sock * -xt_socket_get_sock_v6(struct net *net, const u8 protocol, +xt_socket_get_sock_v6(struct net *net, struct sk_buff *skb, int doff, + const u8 protocol, const struct in6_addr *saddr, const struct in6_addr *daddr, const __be16 sport, const __be16 dport, const struct net_device *in) { switch (protocol) { case IPPROTO_TCP: - return inet6_lookup(net, &tcp_hashinfo, + return inet6_lookup(net, &tcp_hashinfo, skb, doff, saddr, sport, daddr, dport, in->ifindex); case IPPROTO_UDP: @@ -343,6 +351,8 @@ static struct sock *xt_socket_lookup_slow_v6(struct net *net, __be16 uninitialized_var(dport), uninitialized_var(sport); const struct in6_addr *daddr = NULL, *saddr = NULL; struct ipv6hdr *iph = ipv6_hdr(skb); + struct sk_buff *data_skb = NULL; + int doff = 0; int thoff = 0, tproto; tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL); @@ -362,6 +372,10 @@ static struct sock *xt_socket_lookup_slow_v6(struct net *net, sport = hp->source; daddr = &iph->daddr; dport = hp->dest; + data_skb = (struct sk_buff *)skb; + doff = tproto == IPPROTO_TCP ? + thoff + __tcp_hdrlen((struct tcphdr *)hp) : + thoff + sizeof(*hp); } else if (tproto == IPPROTO_ICMPV6) { struct ipv6hdr ipv6_var; @@ -373,7 +387,7 @@ static struct sock *xt_socket_lookup_slow_v6(struct net *net, return NULL; } - return xt_socket_get_sock_v6(net, tproto, saddr, daddr, + return xt_socket_get_sock_v6(net, data_skb, doff, tproto, saddr, daddr, sport, dport, indev); } -- cgit From fa463497679352c04d201631534955e6be66eef8 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:39 -0500 Subject: soreuseport: Prep for fast reuseport TCP socket selection Both of the lines in this patch probably should have been included in the initial implementation of this code for generic socket support, but weren't technically necessary since only UDP sockets were supported. First, the sk_reuseport_cb points to a structure which assumes each socket in the group has this pointer assigned at the same time it's added to the array in the structure. The sk_clone_lock function breaks this assumption. Since a child socket shouldn't implicitly be in a reuseport group, the simple fix is to clear the field in the clone. Second, the SO_ATTACH_REUSEPORT_xBPF socket options require that SO_REUSEPORT also be set first. For UDP sockets, this is easily enforced at bind-time since that process both puts the socket in the appropriate receive hlist and updates the reuseport structures. Since these operations can happen at two different times for TCP sockets (bind and listen) it must be explicitly checked to enforce the use of SO_REUSEPORT with SO_ATTACH_REUSEPORT_xBPF in the setsockopt call. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- net/core/filter.c | 2 +- net/core/sock.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index 94d26201080d..2a6e9562f1ab 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -1181,7 +1181,7 @@ static int __reuseport_attach_prog(struct bpf_prog *prog, struct sock *sk) if (bpf_prog_size(prog->len) > sysctl_optmem_max) return -ENOMEM; - if (sk_unhashed(sk)) { + if (sk_unhashed(sk) && sk->sk_reuseport) { err = reuseport_alloc(sk); if (err) return err; diff --git a/net/core/sock.c b/net/core/sock.c index 6c1c8bc93412..46dc8ad7d050 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1531,6 +1531,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) newsk = NULL; goto out; } + RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); newsk->sk_err = 0; newsk->sk_priority = 0; -- cgit From c125e80b88687b25b321795457309eaaee4bf270 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:40 -0500 Subject: soreuseport: fast reuseport TCP socket selection This change extends the fast SO_REUSEPORT socket lookup implemented for UDP to TCP. Listener sockets with SO_REUSEPORT and the same receive address are additionally added to an array for faster random access. This means that only a single socket from the group must be found in the listener list before any socket in the group can be used to receive a packet. Previously, every socket in the group needed to be considered before handing off the incoming packet. This feature also exposes the ability to use a BPF program when selecting a socket from a reuseport group. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- include/net/inet_hashtables.h | 5 +++- net/ipv4/inet_connection_sock.c | 14 ++++++--- net/ipv4/inet_hashtables.c | 64 +++++++++++++++++++++++++++++++++++++--- net/ipv4/udp.c | 4 +-- net/ipv6/inet6_connection_sock.c | 2 ++ net/ipv6/inet6_hashtables.c | 16 +++++++++- 6 files changed, 93 insertions(+), 12 deletions(-) diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 82403390af58..50f635c2c536 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -207,7 +207,10 @@ void inet_hashinfo_init(struct inet_hashinfo *h); bool inet_ehash_insert(struct sock *sk, struct sock *osk); bool inet_ehash_nolisten(struct sock *sk, struct sock *osk); -void __inet_hash(struct sock *sk, struct sock *osk); +int __inet_hash(struct sock *sk, struct sock *osk, + int (*saddr_same)(const struct sock *sk1, + const struct sock *sk2, + bool match_wildcard)); int inet_hash(struct sock *sk); void inet_unhash(struct sock *sk); diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 12c8d389dc18..c16a2e6273d9 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef INET_CSK_DEBUG const char inet_csk_timer_bug_msg[] = "inet_csk BUG: unknown timer value\n"; @@ -67,7 +68,8 @@ int inet_csk_bind_conflict(const struct sock *sk, if ((!reuse || !sk2->sk_reuse || sk2->sk_state == TCP_LISTEN) && (!reuseport || !sk2->sk_reuseport || - (sk2->sk_state != TCP_TIME_WAIT && + rcu_access_pointer(sk->sk_reuseport_cb) || + (sk2->sk_state != TCP_TIME_WAIT && !uid_eq(uid, sock_i_uid(sk2))))) { if (!sk2->sk_rcv_saddr || !sk->sk_rcv_saddr || @@ -132,6 +134,7 @@ again: sk->sk_state != TCP_LISTEN) || (tb->fastreuseport > 0 && sk->sk_reuseport && + !rcu_access_pointer(sk->sk_reuseport_cb) && uid_eq(tb->fastuid, uid))) && (tb->num_owners < smallest_size || smallest_size == -1)) { smallest_size = tb->num_owners; @@ -193,15 +196,18 @@ tb_found: if (((tb->fastreuse > 0 && sk->sk_reuse && sk->sk_state != TCP_LISTEN) || (tb->fastreuseport > 0 && - sk->sk_reuseport && uid_eq(tb->fastuid, uid))) && - smallest_size == -1) { + sk->sk_reuseport && + !rcu_access_pointer(sk->sk_reuseport_cb) && + uid_eq(tb->fastuid, uid))) && smallest_size == -1) { goto success; } else { ret = 1; if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) { if (((sk->sk_reuse && sk->sk_state != TCP_LISTEN) || (tb->fastreuseport > 0 && - sk->sk_reuseport && uid_eq(tb->fastuid, uid))) && + sk->sk_reuseport && + !rcu_access_pointer(sk->sk_reuseport_cb) && + uid_eq(tb->fastuid, uid))) && smallest_size != -1 && --attempts >= 0) { spin_unlock(&head->lock); goto again; diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 5e4290b83255..c0f9942de924 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -20,10 +20,12 @@ #include #include +#include #include #include #include #include +#include static u32 inet_ehashfn(const struct net *net, const __be32 laddr, const __u16 lport, const __be32 faddr, @@ -215,6 +217,7 @@ struct sock *__inet_lookup_listener(struct net *net, 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; u32 phash = 0; rcu_read_lock(); @@ -230,6 +233,15 @@ begin: 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; + } + } matches = 1; } } else if (score == hiscore && reuseport) { @@ -247,11 +259,13 @@ begin: 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; } } @@ -450,34 +464,74 @@ bool inet_ehash_nolisten(struct sock *sk, struct sock *osk) } EXPORT_SYMBOL_GPL(inet_ehash_nolisten); -void __inet_hash(struct sock *sk, struct sock *osk) +static int inet_reuseport_add_sock(struct sock *sk, + struct inet_listen_hashbucket *ilb, + int (*saddr_same)(const struct sock *sk1, + const struct sock *sk2, + 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) { + if (sk2 != sk && + sk2->sk_family == sk->sk_family && + ipv6_only_sock(sk2) == ipv6_only_sock(sk) && + sk2->sk_bound_dev_if == sk->sk_bound_dev_if && + sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) && + saddr_same(sk, sk2, false)) + return reuseport_add_sock(sk, sk2); + } + + /* Initial allocation may have already happened via setsockopt */ + if (!rcu_access_pointer(sk->sk_reuseport_cb)) + return reuseport_alloc(sk); + return 0; +} + +int __inet_hash(struct sock *sk, struct sock *osk, + int (*saddr_same)(const struct sock *sk1, + const struct sock *sk2, + bool match_wildcard)) { struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; struct inet_listen_hashbucket *ilb; + int err = 0; if (sk->sk_state != TCP_LISTEN) { inet_ehash_nolisten(sk, osk); - return; + return 0; } WARN_ON(!sk_unhashed(sk)); ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)]; spin_lock(&ilb->lock); + if (sk->sk_reuseport) { + err = inet_reuseport_add_sock(sk, ilb, saddr_same); + if (err) + goto unlock; + } __sk_nulls_add_node_rcu(sk, &ilb->head); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); +unlock: spin_unlock(&ilb->lock); + + return err; } EXPORT_SYMBOL(__inet_hash); int inet_hash(struct sock *sk) { + int err = 0; + if (sk->sk_state != TCP_CLOSE) { local_bh_disable(); - __inet_hash(sk, NULL); + err = __inet_hash(sk, NULL, ipv4_rcv_saddr_equal); local_bh_enable(); } - return 0; + return err; } EXPORT_SYMBOL_GPL(inet_hash); @@ -496,6 +550,8 @@ void inet_unhash(struct sock *sk) 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 (done) sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index be0b21852b13..ac3cedb25a9f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -356,8 +356,8 @@ EXPORT_SYMBOL(udp_lib_get_port); * match_wildcard == false: addresses must be exactly the same, i.e. * 0.0.0.0 only equals to 0.0.0.0 */ -static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2, - bool match_wildcard) +int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2, + bool match_wildcard) { struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 36c3f0155010..532c3ef282c5 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -26,6 +26,7 @@ #include #include #include +#include int inet6_csk_bind_conflict(const struct sock *sk, const struct inet_bind_bucket *tb, bool relax) @@ -48,6 +49,7 @@ int inet6_csk_bind_conflict(const struct sock *sk, if ((!reuse || !sk2->sk_reuse || sk2->sk_state == TCP_LISTEN) && (!reuseport || !sk2->sk_reuseport || + rcu_access_pointer(sk->sk_reuseport_cb) || (sk2->sk_state != TCP_TIME_WAIT && !uid_eq(uid, sock_i_uid((struct sock *)sk2))))) { diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 004345d26808..70f2628be6fa 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -17,11 +17,13 @@ #include #include +#include #include #include #include #include #include +#include u32 inet6_ehashfn(const struct net *net, const struct in6_addr *laddr, const u16 lport, @@ -131,6 +133,7 @@ struct sock *inet6_lookup_listener(struct net *net, 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]; @@ -148,6 +151,15 @@ begin: 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; + } + } matches = 1; } } else if (score == hiscore && reuseport) { @@ -165,11 +177,13 @@ begin: 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; } } @@ -283,7 +297,7 @@ int inet6_hash(struct sock *sk) { if (sk->sk_state != TCP_CLOSE) { local_bh_disable(); - __inet_hash(sk, NULL); + __inet_hash(sk, NULL, ipv6_rcv_saddr_equal); local_bh_enable(); } -- cgit From 4b2a6aed2115cd72faaffc92e03d6516e8113904 Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Wed, 10 Feb 2016 11:50:41 -0500 Subject: soreuseport: BPF selection functional test for TCP Unfortunately the existing test relied on packet payload in order to map incoming packets to sockets. In order to get this to work with TCP, TCP_FASTOPEN needed to be used. Since the fast open path is slightly different than the standard TCP path, I created a second test which sends to reuseport group members based on receiving cpu core id. This will probably serve as a better real-world example use as well. Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- tools/testing/selftests/net/.gitignore | 1 + tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/reuseport_bpf.c | 117 ++++++++++- tools/testing/selftests/net/reuseport_bpf_cpu.c | 258 ++++++++++++++++++++++++ 4 files changed, 370 insertions(+), 8 deletions(-) create mode 100644 tools/testing/selftests/net/reuseport_bpf_cpu.c diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore index 6fb23366b258..69bb3fc38fb2 100644 --- a/tools/testing/selftests/net/.gitignore +++ b/tools/testing/selftests/net/.gitignore @@ -2,3 +2,4 @@ socket psock_fanout psock_tpacket reuseport_bpf +reuseport_bpf_cpu diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 41449b5ad0a9..c658792d47b4 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -4,7 +4,7 @@ CFLAGS = -Wall -O2 -g CFLAGS += -I../../../../usr/include/ -NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf +NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu all: $(NET_PROGS) %: %.c diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c index bec1b5dd2530..96ba386b1b7b 100644 --- a/tools/testing/selftests/net/reuseport_bpf.c +++ b/tools/testing/selftests/net/reuseport_bpf.c @@ -9,10 +9,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -169,9 +171,15 @@ static void build_recv_group(const struct test_params p, int fd[], uint16_t mod, if (bind(fd[i], addr, sockaddr_size())) error(1, errno, "failed to bind recv socket %d", i); - if (p.protocol == SOCK_STREAM) + if (p.protocol == SOCK_STREAM) { + opt = 4; + if (setsockopt(fd[i], SOL_TCP, TCP_FASTOPEN, &opt, + sizeof(opt))) + error(1, errno, + "failed to set TCP_FASTOPEN on %d", i); if (listen(fd[i], p.recv_socks * 10)) error(1, errno, "failed to listen on socket"); + } } free(addr); } @@ -189,10 +197,8 @@ static void send_from(struct test_params p, uint16_t sport, char *buf, if (bind(fd, saddr, sockaddr_size())) error(1, errno, "failed to bind send socket"); - if (connect(fd, daddr, sockaddr_size())) - error(1, errno, "failed to connect"); - if (send(fd, buf, len, 0) < 0) + if (sendto(fd, buf, len, MSG_FASTOPEN, daddr, sockaddr_size()) < 0) error(1, errno, "failed to send message"); close(fd); @@ -260,7 +266,7 @@ static void test_recv_order(const struct test_params p, int fd[], int mod) } } -static void test_reuseport_ebpf(const struct test_params p) +static void test_reuseport_ebpf(struct test_params p) { int i, fd[p.recv_socks]; @@ -268,6 +274,7 @@ static void test_reuseport_ebpf(const struct test_params p) build_recv_group(p, fd, p.recv_socks, attach_ebpf); test_recv_order(p, fd, p.recv_socks); + p.send_port_min += p.recv_socks * 2; fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2); attach_ebpf(fd[0], p.recv_socks / 2); test_recv_order(p, fd, p.recv_socks / 2); @@ -276,7 +283,7 @@ static void test_reuseport_ebpf(const struct test_params p) close(fd[i]); } -static void test_reuseport_cbpf(const struct test_params p) +static void test_reuseport_cbpf(struct test_params p) { int i, fd[p.recv_socks]; @@ -284,6 +291,7 @@ static void test_reuseport_cbpf(const struct test_params p) build_recv_group(p, fd, p.recv_socks, attach_cbpf); test_recv_order(p, fd, p.recv_socks); + p.send_port_min += p.recv_socks * 2; fprintf(stderr, "Reprograming, testing mod %zd...\n", p.recv_socks / 2); attach_cbpf(fd[0], p.recv_socks / 2); test_recv_order(p, fd, p.recv_socks / 2); @@ -377,7 +385,7 @@ static void test_filter_no_reuseport(const struct test_params p) static void test_filter_without_bind(void) { - int fd1, fd2; + int fd1, fd2, opt = 1; fprintf(stderr, "Testing filter add without bind...\n"); fd1 = socket(AF_INET, SOCK_DGRAM, 0); @@ -386,6 +394,10 @@ static void test_filter_without_bind(void) fd2 = socket(AF_INET, SOCK_DGRAM, 0); if (fd2 < 0) error(1, errno, "failed to create socket 2"); + if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt))) + error(1, errno, "failed to set SO_REUSEPORT on socket 1"); + if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt))) + error(1, errno, "failed to set SO_REUSEPORT on socket 2"); attach_ebpf(fd1, 10); attach_cbpf(fd2, 10); @@ -394,6 +406,32 @@ static void test_filter_without_bind(void) close(fd2); } +void enable_fastopen(void) +{ + int fd = open("/proc/sys/net/ipv4/tcp_fastopen", 0); + int rw_mask = 3; /* bit 1: client side; bit-2 server side */ + int val, size; + char buf[16]; + + if (fd < 0) + error(1, errno, "Unable to open tcp_fastopen sysctl"); + if (read(fd, buf, sizeof(buf)) <= 0) + error(1, errno, "Unable to read tcp_fastopen sysctl"); + val = atoi(buf); + close(fd); + + if ((val & rw_mask) != rw_mask) { + fd = open("/proc/sys/net/ipv4/tcp_fastopen", O_RDWR); + if (fd < 0) + error(1, errno, + "Unable to open tcp_fastopen sysctl for writing"); + val |= rw_mask; + size = snprintf(buf, 16, "%d", val); + if (write(fd, buf, size) <= 0) + error(1, errno, "Unable to write tcp_fastopen sysctl"); + close(fd); + } +} int main(void) { @@ -506,6 +544,71 @@ int main(void) .recv_port = 8007, .send_port_min = 9100}); + /* TCP fastopen is required for the TCP tests */ + enable_fastopen(); + fprintf(stderr, "---- IPv4 TCP ----\n"); + test_reuseport_ebpf((struct test_params) { + .recv_family = AF_INET, + .send_family = AF_INET, + .protocol = SOCK_STREAM, + .recv_socks = 10, + .recv_port = 8008, + .send_port_min = 9120}); + test_reuseport_cbpf((struct test_params) { + .recv_family = AF_INET, + .send_family = AF_INET, + .protocol = SOCK_STREAM, + .recv_socks = 10, + .recv_port = 8009, + .send_port_min = 9160}); + test_extra_filter((struct test_params) { + .recv_family = AF_INET, + .protocol = SOCK_STREAM, + .recv_port = 8010}); + test_filter_no_reuseport((struct test_params) { + .recv_family = AF_INET, + .protocol = SOCK_STREAM, + .recv_port = 8011}); + + fprintf(stderr, "---- IPv6 TCP ----\n"); + test_reuseport_ebpf((struct test_params) { + .recv_family = AF_INET6, + .send_family = AF_INET6, + .protocol = SOCK_STREAM, + .recv_socks = 10, + .recv_port = 8012, + .send_port_min = 9200}); + test_reuseport_cbpf((struct test_params) { + .recv_family = AF_INET6, + .send_family = AF_INET6, + .protocol = SOCK_STREAM, + .recv_socks = 10, + .recv_port = 8013, + .send_port_min = 9240}); + test_extra_filter((struct test_params) { + .recv_family = AF_INET6, + .protocol = SOCK_STREAM, + .recv_port = 8014}); + test_filter_no_reuseport((struct test_params) { + .recv_family = AF_INET6, + .protocol = SOCK_STREAM, + .recv_port = 8015}); + + fprintf(stderr, "---- IPv6 TCP w/ mapped IPv4 ----\n"); + test_reuseport_ebpf((struct test_params) { + .recv_family = AF_INET6, + .send_family = AF_INET, + .protocol = SOCK_STREAM, + .recv_socks = 10, + .recv_port = 8016, + .send_port_min = 9320}); + test_reuseport_cbpf((struct test_params) { + .recv_family = AF_INET6, + .send_family = AF_INET, + .protocol = SOCK_STREAM, + .recv_socks = 10, + .recv_port = 8017, + .send_port_min = 9360}); test_filter_without_bind(); diff --git a/tools/testing/selftests/net/reuseport_bpf_cpu.c b/tools/testing/selftests/net/reuseport_bpf_cpu.c new file mode 100644 index 000000000000..b23d6f54de7b --- /dev/null +++ b/tools/testing/selftests/net/reuseport_bpf_cpu.c @@ -0,0 +1,258 @@ +/* + * Test functionality of BPF filters with SO_REUSEPORT. This program creates + * an SO_REUSEPORT receiver group containing one socket per CPU core. It then + * creates a BPF program that will select a socket from this group based + * on the core id that receives the packet. The sending code artificially + * moves itself to run on different core ids and sends one message from + * each core. Since these packets are delivered over loopback, they should + * arrive on the same core that sent them. The receiving code then ensures + * that the packet was received on the socket for the corresponding core id. + * This entire process is done for several different core id permutations + * and for each IPv4/IPv6 and TCP/UDP combination. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const int PORT = 8888; + +static void build_rcv_group(int *rcv_fd, size_t len, int family, int proto) +{ + struct sockaddr_storage addr; + struct sockaddr_in *addr4; + struct sockaddr_in6 *addr6; + size_t i; + int opt; + + switch (family) { + case AF_INET: + addr4 = (struct sockaddr_in *)&addr; + addr4->sin_family = AF_INET; + addr4->sin_addr.s_addr = htonl(INADDR_ANY); + addr4->sin_port = htons(PORT); + break; + case AF_INET6: + addr6 = (struct sockaddr_in6 *)&addr; + addr6->sin6_family = AF_INET6; + addr6->sin6_addr = in6addr_any; + addr6->sin6_port = htons(PORT); + break; + default: + error(1, 0, "Unsupported family %d", family); + } + + for (i = 0; i < len; ++i) { + rcv_fd[i] = socket(family, proto, 0); + if (rcv_fd[i] < 0) + error(1, errno, "failed to create receive socket"); + + opt = 1; + if (setsockopt(rcv_fd[i], SOL_SOCKET, SO_REUSEPORT, &opt, + sizeof(opt))) + error(1, errno, "failed to set SO_REUSEPORT"); + + if (bind(rcv_fd[i], (struct sockaddr *)&addr, sizeof(addr))) + error(1, errno, "failed to bind receive socket"); + + if (proto == SOCK_STREAM && listen(rcv_fd[i], len * 10)) + error(1, errno, "failed to listen on receive port"); + } +} + +static void attach_bpf(int fd) +{ + struct sock_filter code[] = { + /* A = raw_smp_processor_id() */ + { BPF_LD | BPF_W | BPF_ABS, 0, 0, SKF_AD_OFF + SKF_AD_CPU }, + /* return A */ + { BPF_RET | BPF_A, 0, 0, 0 }, + }; + struct sock_fprog p = { + .len = 2, + .filter = code, + }; + + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &p, sizeof(p))) + error(1, errno, "failed to set SO_ATTACH_REUSEPORT_CBPF"); +} + +static void send_from_cpu(int cpu_id, int family, int proto) +{ + struct sockaddr_storage saddr, daddr; + struct sockaddr_in *saddr4, *daddr4; + struct sockaddr_in6 *saddr6, *daddr6; + cpu_set_t cpu_set; + int fd; + + switch (family) { + case AF_INET: + saddr4 = (struct sockaddr_in *)&saddr; + saddr4->sin_family = AF_INET; + saddr4->sin_addr.s_addr = htonl(INADDR_ANY); + saddr4->sin_port = 0; + + daddr4 = (struct sockaddr_in *)&daddr; + daddr4->sin_family = AF_INET; + daddr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + daddr4->sin_port = htons(PORT); + break; + case AF_INET6: + saddr6 = (struct sockaddr_in6 *)&saddr; + saddr6->sin6_family = AF_INET6; + saddr6->sin6_addr = in6addr_any; + saddr6->sin6_port = 0; + + daddr6 = (struct sockaddr_in6 *)&daddr; + daddr6->sin6_family = AF_INET6; + daddr6->sin6_addr = in6addr_loopback; + daddr6->sin6_port = htons(PORT); + break; + default: + error(1, 0, "Unsupported family %d", family); + } + + memset(&cpu_set, 0, sizeof(cpu_set)); + CPU_SET(cpu_id, &cpu_set); + if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) + error(1, errno, "failed to pin to cpu"); + + fd = socket(family, proto, 0); + if (fd < 0) + error(1, errno, "failed to create send socket"); + + if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr))) + error(1, errno, "failed to bind send socket"); + + if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr))) + error(1, errno, "failed to connect send socket"); + + if (send(fd, "a", 1, 0) < 0) + error(1, errno, "failed to send message"); + + close(fd); +} + +static +void receive_on_cpu(int *rcv_fd, int len, int epfd, int cpu_id, int proto) +{ + struct epoll_event ev; + int i, fd; + char buf[8]; + + i = epoll_wait(epfd, &ev, 1, -1); + if (i < 0) + error(1, errno, "epoll_wait failed"); + + if (proto == SOCK_STREAM) { + fd = accept(ev.data.fd, NULL, NULL); + if (fd < 0) + error(1, errno, "failed to accept"); + i = recv(fd, buf, sizeof(buf), 0); + close(fd); + } else { + i = recv(ev.data.fd, buf, sizeof(buf), 0); + } + + if (i < 0) + error(1, errno, "failed to recv"); + + for (i = 0; i < len; ++i) + if (ev.data.fd == rcv_fd[i]) + break; + if (i == len) + error(1, 0, "failed to find socket"); + fprintf(stderr, "send cpu %d, receive socket %d\n", cpu_id, i); + if (cpu_id != i) + error(1, 0, "cpu id/receive socket mismatch"); +} + +static void test(int *rcv_fd, int len, int family, int proto) +{ + struct epoll_event ev; + int epfd, cpu; + + build_rcv_group(rcv_fd, len, family, proto); + attach_bpf(rcv_fd[0]); + + epfd = epoll_create(1); + if (epfd < 0) + error(1, errno, "failed to create epoll"); + for (cpu = 0; cpu < len; ++cpu) { + ev.events = EPOLLIN; + ev.data.fd = rcv_fd[cpu]; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fd[cpu], &ev)) + error(1, errno, "failed to register sock epoll"); + } + + /* Forward iterate */ + for (cpu = 0; cpu < len; ++cpu) { + send_from_cpu(cpu, family, proto); + receive_on_cpu(rcv_fd, len, epfd, cpu, proto); + } + + /* Reverse iterate */ + for (cpu = len - 1; cpu >= 0; --cpu) { + send_from_cpu(cpu, family, proto); + receive_on_cpu(rcv_fd, len, epfd, cpu, proto); + } + + /* Even cores */ + for (cpu = 0; cpu < len; cpu += 2) { + send_from_cpu(cpu, family, proto); + receive_on_cpu(rcv_fd, len, epfd, cpu, proto); + } + + /* Odd cores */ + for (cpu = 1; cpu < len; cpu += 2) { + send_from_cpu(cpu, family, proto); + receive_on_cpu(rcv_fd, len, epfd, cpu, proto); + } + + close(epfd); + for (cpu = 0; cpu < len; ++cpu) + close(rcv_fd[cpu]); +} + +int main(void) +{ + int *rcv_fd, cpus; + + cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (cpus <= 0) + error(1, errno, "failed counting cpus"); + + rcv_fd = calloc(cpus, sizeof(int)); + if (!rcv_fd) + error(1, 0, "failed to allocate array"); + + fprintf(stderr, "---- IPv4 UDP ----\n"); + test(rcv_fd, cpus, AF_INET, SOCK_DGRAM); + + fprintf(stderr, "---- IPv6 UDP ----\n"); + test(rcv_fd, cpus, AF_INET6, SOCK_DGRAM); + + fprintf(stderr, "---- IPv4 TCP ----\n"); + test(rcv_fd, cpus, AF_INET, SOCK_STREAM); + + fprintf(stderr, "---- IPv6 TCP ----\n"); + test(rcv_fd, cpus, AF_INET6, SOCK_STREAM); + + free(rcv_fd); + + fprintf(stderr, "SUCCESS\n"); + return 0; +} -- cgit From dc599f76c22b0de55a2a9141dfe52e70b32a1194 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Tue, 2 Feb 2016 08:17:07 -0800 Subject: net: Add support for filtering link dump by master device and kind Add support for filtering link dumps by master device and kind, similar to the filtering implemented for neighbor dumps. Each net_device that exists adds between 1196 bytes (eth) and 1556 bytes (bridge) to the link dump. As the number of interfaces increases so does the amount of data pushed to user space for a link list. If the user only wants to see a list of specific devices (e.g., interfaces enslaved to a specific bridge or a list of VRFs) most of that data is thrown away. Passing the filters to the kernel to have only relevant data returned makes the dump more efficient. Signed-off-by: David Ahern Acked-by: Roopa Prabhu Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 20d71358c143..62737f437c8e 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1414,6 +1414,58 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, }; +static const struct rtnl_link_ops *linkinfo_to_kind_ops(const struct nlattr *nla) +{ + const struct rtnl_link_ops *ops = NULL; + struct nlattr *linfo[IFLA_INFO_MAX + 1]; + + if (nla_parse_nested(linfo, IFLA_INFO_MAX, nla, ifla_info_policy) < 0) + return NULL; + + if (linfo[IFLA_INFO_KIND]) { + char kind[MODULE_NAME_LEN]; + + nla_strlcpy(kind, linfo[IFLA_INFO_KIND], sizeof(kind)); + ops = rtnl_link_ops_get(kind); + } + + return ops; +} + +static bool link_master_filtered(struct net_device *dev, int master_idx) +{ + struct net_device *master; + + if (!master_idx) + return false; + + master = netdev_master_upper_dev_get(dev); + if (!master || master->ifindex != master_idx) + return true; + + return false; +} + +static bool link_kind_filtered(const struct net_device *dev, + const struct rtnl_link_ops *kind_ops) +{ + if (kind_ops && dev->rtnl_link_ops != kind_ops) + return true; + + return false; +} + +static bool link_dump_filtered(struct net_device *dev, + int master_idx, + const struct rtnl_link_ops *kind_ops) +{ + if (link_master_filtered(dev, master_idx) || + link_kind_filtered(dev, kind_ops)) + return true; + + return false; +} + static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { struct net *net = sock_net(skb->sk); @@ -1423,6 +1475,9 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) struct hlist_head *head; struct nlattr *tb[IFLA_MAX+1]; u32 ext_filter_mask = 0; + const struct rtnl_link_ops *kind_ops = NULL; + unsigned int flags = NLM_F_MULTI; + int master_idx = 0; int err; int hdrlen; @@ -1445,18 +1500,29 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) if (tb[IFLA_EXT_MASK]) ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); + + if (tb[IFLA_MASTER]) + master_idx = nla_get_u32(tb[IFLA_MASTER]); + + if (tb[IFLA_LINKINFO]) + kind_ops = linkinfo_to_kind_ops(tb[IFLA_LINKINFO]); + + if (master_idx || kind_ops) + flags |= NLM_F_DUMP_FILTERED; } 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 (link_dump_filtered(dev, master_idx, kind_ops)) + continue; if (idx < s_idx) goto cont; err = rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 0, - NLM_F_MULTI, + flags, ext_filter_mask); /* If we ran out of room on the first message, * we're in trouble -- cgit From 1490d2bd1bbcf9ad127f7764b7f28b26a55e011b Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Thu, 4 Feb 2016 17:36:23 +0800 Subject: bpf_dbg: do not initialise statics to 0 This patch fixes the checkpatch.pl error to bpf_dbg.c: ERROR: do not initialise statics to 0 Signed-off-by: Wei Tang Signed-off-by: David S. Miller --- tools/net/bpf_dbg.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/net/bpf_dbg.c b/tools/net/bpf_dbg.c index 9a287bec695a..4f254bcc4423 100644 --- a/tools/net/bpf_dbg.c +++ b/tools/net/bpf_dbg.c @@ -129,16 +129,16 @@ struct bpf_regs { }; static struct sock_filter bpf_image[BPF_MAXINSNS + 1]; -static unsigned int bpf_prog_len = 0; +static unsigned int bpf_prog_len; static int bpf_breakpoints[64]; static struct bpf_regs bpf_regs[BPF_MAXINSNS + 1]; static struct bpf_regs bpf_curr; -static unsigned int bpf_regs_len = 0; +static unsigned int bpf_regs_len; static int pcap_fd = -1; -static unsigned int pcap_packet = 0; -static size_t pcap_map_size = 0; +static unsigned int pcap_packet; +static size_t pcap_map_size; static char *pcap_ptr_va_start, *pcap_ptr_va_curr; static const char * const op_table[] = { @@ -1172,7 +1172,7 @@ static int cmd_breakpoint(char *subcmd) static int cmd_run(char *num) { - static uint32_t pass = 0, fail = 0; + static uint32_t pass, fail; bool has_limit = true; int pkts = 0, i = 0; -- cgit From ccad0993567812e88617f105c01b04f1528538b6 Mon Sep 17 00:00:00 2001 From: Siva Reddy Kallam Date: Thu, 4 Feb 2016 15:20:47 +0530 Subject: MAINTAINERS: Update tg3 maintainer Signed-off-by: Siva Reddy Kallam Signed-off-by: Michael Chan Acked-by: Prashant Sreedharan Signed-off-by: David S. Miller --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 1e216aa4d25c..355e1c85bad6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2424,6 +2424,7 @@ F: include/linux/bcm963xx_nvram.h F: include/linux/bcm963xx_tag.h BROADCOM TG3 GIGABIT ETHERNET DRIVER +M: Siva Reddy Kallam M: Prashant Sreedharan M: Michael Chan L: netdev@vger.kernel.org -- cgit From 12b74dfadb5a7a23baf4db941dc9fd9d371f249a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Feb 2016 13:31:17 +0100 Subject: ipv4: add option to drop unicast encapsulated in L2 multicast In order to solve a problem with 802.11, the so-called hole-196 attack, add an option (sysctl) called "drop_unicast_in_l2_multicast" which, if enabled, causes the stack to drop IPv4 unicast packets encapsulated in link-layer multi- or broadcast frames. Such frames can (as an attack) be created by any member of the same wireless network and transmitted as valid encrypted frames since the symmetric key for broadcast frames is shared between all stations. Additionally, enabling this option provides compliance with a SHOULD clause of RFC 1122. Reviewed-by: Julian Anastasov Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 7 +++++++ include/uapi/linux/ip.h | 1 + net/ipv4/devinet.c | 2 ++ net/ipv4/ip_input.c | 25 ++++++++++++++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 73b36d7c7b0d..d5910d63214d 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1216,6 +1216,13 @@ promote_secondaries - BOOLEAN promote a corresponding secondary IP address instead of removing all the corresponding secondary IP addresses. +drop_unicast_in_l2_multicast - BOOLEAN + Drop any unicast IP packets that are received in link-layer + multicast (or broadcast) frames. + This behavior (for multicast) is actually a SHOULD in RFC + 1122, but is disabled by default for compatibility reasons. + Default: off (0) + tag - INTEGER Allows you to write a number, which can be used as required. diff --git a/include/uapi/linux/ip.h b/include/uapi/linux/ip.h index 08f894d2ddbd..584834f7e95c 100644 --- a/include/uapi/linux/ip.h +++ b/include/uapi/linux/ip.h @@ -165,6 +165,7 @@ enum IPV4_DEVCONF_IGMPV2_UNSOLICITED_REPORT_INTERVAL, IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL, IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, + IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, __IPV4_DEVCONF_MAX }; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index cebd9d31e65a..dbbab28a52a4 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -2192,6 +2192,8 @@ static struct devinet_sysctl_table { "promote_secondaries"), DEVINET_SYSCTL_FLUSHING_ENTRY(ROUTE_LOCALNET, "route_localnet"), + DEVINET_SYSCTL_FLUSHING_ENTRY(DROP_UNICAST_IN_L2_MULTICAST, + "drop_unicast_in_l2_multicast"), }, }; diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index d77eb0c3b684..852002f64c68 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -362,8 +362,31 @@ 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); - } else if (rt->rt_type == RTN_BROADCAST) + } else if (rt->rt_type == RTN_BROADCAST) { IP_UPD_PO_STATS_BH(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); + + /* RFC 1122 3.3.6: + * + * When a host sends a datagram to a link-layer broadcast + * address, the IP destination address MUST be a legal IP + * broadcast or IP multicast address. + * + * A host SHOULD silently discard a datagram that is received + * via a link-layer broadcast (see Section 2.4) but does not + * specify an IP multicast or broadcast destination address. + * + * This doesn't explicitly say L2 *broadcast*, but broadcast is + * in a way a form of multicast and the most common use case for + * this is 802.11 protecting against cross-station spoofing (the + * so-called "hole-196" attack) so do it for both. + */ + if (in_dev && + IN_DEV_ORCONF(in_dev, DROP_UNICAST_IN_L2_MULTICAST)) + goto drop; + } return dst_input(skb); -- cgit From 97daf331455077645ae1f13438bebd3d1a2e94ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Feb 2016 13:31:18 +0100 Subject: ipv4: add option to drop gratuitous ARP packets In certain 802.11 wireless deployments, there will be ARP proxies that use knowledge of the network to correctly answer requests. To prevent gratuitous ARP frames on the shared medium from being a problem, on such deployments wireless needs to drop them. Enable this by providing an option called "drop_gratuitous_arp". Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/uapi/linux/ip.h | 1 + net/ipv4/arp.c | 8 ++++++++ net/ipv4/devinet.c | 2 ++ 4 files changed, 17 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index d5910d63214d..a53bbfaff1c7 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1223,6 +1223,12 @@ drop_unicast_in_l2_multicast - BOOLEAN 1122, but is disabled by default for compatibility reasons. Default: off (0) +drop_gratuitous_arp - BOOLEAN + Drop all gratuitous ARP frames, for example if there's a known + good ARP proxy on the network and such frames need not be used + (or in the case of 802.11, must not be used to prevent attacks.) + Default: off (0) + tag - INTEGER Allows you to write a number, which can be used as required. diff --git a/include/uapi/linux/ip.h b/include/uapi/linux/ip.h index 584834f7e95c..f291569768dd 100644 --- a/include/uapi/linux/ip.h +++ b/include/uapi/linux/ip.h @@ -166,6 +166,7 @@ enum IPV4_DEVCONF_IGMPV3_UNSOLICITED_REPORT_INTERVAL, IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + IPV4_DEVCONF_DROP_GRATUITOUS_ARP, __IPV4_DEVCONF_MAX }; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 59b3e0e8fd51..c102eb5ac55c 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -735,6 +735,14 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb) (!IN_DEV_ROUTE_LOCALNET(in_dev) && ipv4_is_loopback(tip))) goto out; + /* + * For some 802.11 wireless deployments (and possibly other networks), + * there will be an ARP proxy and gratuitous ARP frames are attacks + * and thus should not be accepted. + */ + if (sip == tip && IN_DEV_ORCONF(in_dev, DROP_GRATUITOUS_ARP)) + goto out; + /* * Special case: We must set Frame Relay source Q.922 address */ diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index dbbab28a52a4..3d835313575e 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -2185,6 +2185,8 @@ static struct devinet_sysctl_table { "igmpv3_unsolicited_report_interval"), DEVINET_SYSCTL_RW_ENTRY(IGNORE_ROUTES_WITH_LINKDOWN, "ignore_routes_with_linkdown"), + DEVINET_SYSCTL_RW_ENTRY(DROP_GRATUITOUS_ARP, + "drop_gratuitous_arp"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOXFRM, "disable_xfrm"), DEVINET_SYSCTL_FLUSHING_ENTRY(NOPOLICY, "disable_policy"), -- cgit From abbc30436d39dfed8ebfca338d253f211ac7b094 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Feb 2016 13:31:19 +0100 Subject: ipv6: add option to drop unicast encapsulated in L2 multicast In order to solve a problem with 802.11, the so-called hole-196 attack, add an option (sysctl) called "drop_unicast_in_l2_multicast" which, if enabled, causes the stack to drop IPv6 unicast packets encapsulated in link-layer multi- or broadcast frames. Such frames can (as an attack) be created by any member of the same wireless network and transmitted as valid encrypted frames since the symmetric key for broadcast frames is shared between all stations. Reviewed-by: Julian Anastasov Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 6 ++++++ include/linux/ipv6.h | 1 + include/uapi/linux/ipv6.h | 1 + net/ipv6/addrconf.c | 8 ++++++++ net/ipv6/ip6_input.c | 10 ++++++++++ 5 files changed, 26 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index a53bbfaff1c7..e0e7350a4e6a 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1674,6 +1674,12 @@ stable_secret - IPv6 address By default the stable secret is unset. +drop_unicast_in_l2_multicast - BOOLEAN + Drop any unicast IPv6 packets that are received in link-layer + multicast (or broadcast) frames. + + By default this is turned off. + icmp/*: ratelimit - INTEGER Limit the maximal rates for sending ICMPv6 packets. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 402753bccafa..4a4c1ae826cb 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -50,6 +50,7 @@ struct ipv6_devconf { __s32 mc_forwarding; #endif __s32 disable_ipv6; + __s32 drop_unicast_in_l2_multicast; __s32 accept_dad; __s32 force_tllao; __s32 ndisc_notify; diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h index 38b4fef20219..4c413570efe8 100644 --- a/include/uapi/linux/ipv6.h +++ b/include/uapi/linux/ipv6.h @@ -174,6 +174,7 @@ enum { DEVCONF_USE_OIF_ADDRS_ONLY, DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT, DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, + DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, DEVCONF_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 38eeddedfc21..23e325f39f8e 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4711,6 +4711,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN] = cnf->ignore_routes_with_linkdown; /* we omit DEVCONF_STABLE_SECRET for now */ array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only; + array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast; } static inline size_t inet6_ifla6_size(void) @@ -5784,6 +5785,13 @@ static struct addrconf_sysctl_table .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, + }, { /* sentinel */ } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 9075acf081dd..31ac3c56da4b 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -134,6 +134,16 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) goto err; + /* If enabled, drop unicast packets that were encapsulated in link-layer + * multicast or broadcast to protected against the so-called "hole-196" + * attack in 802.11 wireless. + */ + if (!ipv6_addr_is_multicast(&hdr->daddr) && + (skb->pkt_type == PACKET_BROADCAST || + skb->pkt_type == PACKET_MULTICAST) && + idev->cnf.drop_unicast_in_l2_multicast) + goto err; + /* RFC4291 2.7 * Nodes must not originate a packet to a multicast address whose scope * field contains the reserved value 0; if such a packet is received, it -- cgit From 7a02bf892d8f1e5298af1676f001bee410509d80 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 4 Feb 2016 13:31:20 +0100 Subject: ipv6: add option to drop unsolicited neighbor advertisements In certain 802.11 wireless deployments, there will be NA proxies that use knowledge of the network to correctly answer requests. To prevent unsolicitd advertisements on the shared medium from being a problem, on such deployments wireless needs to drop them. Enable this by providing an option called "drop_unsolicited_na". Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.txt | 7 +++++++ include/linux/ipv6.h | 1 + include/uapi/linux/ipv6.h | 1 + net/ipv6/addrconf.c | 8 ++++++++ net/ipv6/ndisc.c | 9 +++++++++ 5 files changed, 26 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index e0e7350a4e6a..24ce97f42d35 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1680,6 +1680,13 @@ drop_unicast_in_l2_multicast - BOOLEAN By default this is turned off. +drop_unsolicited_na - BOOLEAN + Drop all unsolicited neighbor advertisements, for example if there's + a known good NA proxy on the network and such frames need not be used + (or in the case of 802.11, must not be used to prevent attacks.) + + By default this is turned off. + icmp/*: ratelimit - INTEGER Limit the maximal rates for sending ICMPv6 packets. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 4a4c1ae826cb..4b2267e1b7c3 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -56,6 +56,7 @@ struct ipv6_devconf { __s32 ndisc_notify; __s32 suppress_frag_ndisc; __s32 accept_ra_mtu; + __s32 drop_unsolicited_na; struct ipv6_stable_secret { bool initialized; struct in6_addr secret; diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h index 4c413570efe8..ec117b65d5a5 100644 --- a/include/uapi/linux/ipv6.h +++ b/include/uapi/linux/ipv6.h @@ -175,6 +175,7 @@ enum { DEVCONF_ACCEPT_RA_MIN_HOP_LIMIT, DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, + DEVCONF_DROP_UNSOLICITED_NA, DEVCONF_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 23e325f39f8e..ac0ba9e4e06b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4712,6 +4712,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, /* we omit DEVCONF_STABLE_SECRET for now */ array[DEVCONF_USE_OIF_ADDRS_ONLY] = cnf->use_oif_addrs_only; array[DEVCONF_DROP_UNICAST_IN_L2_MULTICAST] = cnf->drop_unicast_in_l2_multicast; + array[DEVCONF_DROP_UNSOLICITED_NA] = cnf->drop_unsolicited_na; } static inline size_t inet6_ifla6_size(void) @@ -5792,6 +5793,13 @@ static struct addrconf_sysctl_table .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, + }, { /* sentinel */ } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 84afb9a77278..c245895a3d41 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -883,6 +883,7 @@ static void ndisc_recv_na(struct sk_buff *skb) offsetof(struct nd_msg, opt)); struct ndisc_options ndopts; struct net_device *dev = skb->dev; + struct inet6_dev *idev = __in6_dev_get(dev); struct inet6_ifaddr *ifp; struct neighbour *neigh; @@ -902,6 +903,14 @@ static void ndisc_recv_na(struct sk_buff *skb) return; } + /* For some 802.11 wireless deployments (and possibly other networks), + * there will be a NA proxy and unsolicitd packets are attacks + * and thus should not be accepted. + */ + if (!msg->icmph.icmp6_solicited && idev && + idev->cnf.drop_unsolicited_na) + return; + if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts)) { ND_PRINTK(2, warn, "NS: invalid ND option\n"); return; -- cgit From 7f20cd252185702f951009e0a56778f870d50ca6 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Thu, 4 Feb 2016 17:42:28 +0100 Subject: bonding: 3ad: allow to set ad_actor settings while the bond is up No need to require the bond down while changing these settings, the change will be reflected immediately and the 3ad mode will sort itself out. For faster convergence set port->ntt to true in order to generate new LACPDUs immediately. CC: Jay Vosburgh CC: Veaceslav Falico CC: Andy Gospodarek Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- drivers/net/bonding/bond_3ad.c | 8 ++++++-- drivers/net/bonding/bond_options.c | 3 +-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index ee94056dbb2e..b9304a295f86 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2176,8 +2176,12 @@ void bond_3ad_update_ad_actor_settings(struct bonding *bond) *((struct mac_addr *)bond->params.ad_actor_system); spin_lock_bh(&bond->mode_lock); - bond_for_each_slave(bond, slave, iter) - __ad_actor_update_port(&(SLAVE_AD_INFO(slave)->port)); + bond_for_each_slave(bond, slave, iter) { + struct port *port = &(SLAVE_AD_INFO(slave))->port; + + __ad_actor_update_port(port); + port->ntt = true; + } spin_unlock_bh(&bond->mode_lock); } diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c index ed0bdae64f5e..577e57cad1dc 100644 --- a/drivers/net/bonding/bond_options.c +++ b/drivers/net/bonding/bond_options.c @@ -402,7 +402,6 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = { .id = BOND_OPT_AD_ACTOR_SYS_PRIO, .name = "ad_actor_sys_prio", .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)), - .flags = BOND_OPTFLAG_IFDOWN, .values = bond_ad_actor_sys_prio_tbl, .set = bond_option_ad_actor_sys_prio_set, }, @@ -410,7 +409,7 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = { .id = BOND_OPT_AD_ACTOR_SYSTEM, .name = "ad_actor_system", .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)), - .flags = BOND_OPTFLAG_RAWVAL | BOND_OPTFLAG_IFDOWN, + .flags = BOND_OPTFLAG_RAWVAL, .set = bond_option_ad_actor_system_set, }, [BOND_OPT_AD_USER_PORT_KEY] = { -- cgit From f97238373b8662a6d580e204df2e7bcbfa43e27a Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sun, 24 Jan 2016 20:08:52 -0600 Subject: PM / sleep: declare __tracedata symbols as char[] rather than char Accessing more than one byte from a symbol declared simply 'char' is undefined behavior, as reported by UBSAN: UBSAN: Undefined behaviour in drivers/base/power/trace.c:178:18 load of address ffffffff8203fc78 with insufficient space for an object of type 'char' Avoid this by declaring the symbols as arrays. Signed-off-by: Eric Biggers Signed-off-by: Rafael J. Wysocki --- drivers/base/power/trace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index a311cfa4c5bd..a6975795e7f3 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c @@ -166,14 +166,14 @@ void generate_pm_trace(const void *tracedata, unsigned int user) } EXPORT_SYMBOL(generate_pm_trace); -extern char __tracedata_start, __tracedata_end; +extern char __tracedata_start[], __tracedata_end[]; static int show_file_hash(unsigned int value) { int match; char *tracedata; match = 0; - for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; + for (tracedata = __tracedata_start ; tracedata < __tracedata_end ; tracedata += 2 + sizeof(unsigned long)) { unsigned short lineno = *(unsigned short *)tracedata; const char *file = *(const char **)(tracedata + 2); -- cgit From f7b382b988233b5851eddf4531651ffe4133e88c Mon Sep 17 00:00:00 2001 From: Abhilash Jindal Date: Sun, 31 Jan 2016 14:29:01 -0500 Subject: PM/freezer: y2038, use boottime to compare tstamps Wall time obtained from do_gettimeofday gives 32 bit timeval which can only represent time until January 2038. This patch moves to ktime_t, a 64-bit time. Also, wall time is susceptible to sudden jumps due to user setting the time or due to NTP. Boot time is constantly increasing time better suited for subtracting two timestamps. Signed-off-by: Abhilash Jindal Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- kernel/power/process.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/kernel/power/process.c b/kernel/power/process.c index 564f786df470..df058bed53ce 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -30,13 +30,12 @@ static int try_to_freeze_tasks(bool user_only) unsigned long end_time; unsigned int todo; bool wq_busy = false; - struct timeval start, end; - u64 elapsed_msecs64; + ktime_t start, end, elapsed; unsigned int elapsed_msecs; bool wakeup = false; int sleep_usecs = USEC_PER_MSEC; - do_gettimeofday(&start); + start = ktime_get_boottime(); end_time = jiffies + msecs_to_jiffies(freeze_timeout_msecs); @@ -78,10 +77,9 @@ static int try_to_freeze_tasks(bool user_only) sleep_usecs *= 2; } - do_gettimeofday(&end); - elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); - do_div(elapsed_msecs64, NSEC_PER_MSEC); - elapsed_msecs = elapsed_msecs64; + end = ktime_get_boottime(); + elapsed = ktime_sub(end, start); + elapsed_msecs = ktime_to_ms(elapsed); if (todo) { pr_cont("\n"); -- cgit From 22e09b333f0b395b3eb6ab6efa4b3284e2c06810 Mon Sep 17 00:00:00 2001 From: saurabh Date: Wed, 28 Oct 2015 08:54:01 +0530 Subject: PM / suspend: replacing printk replacing printk(s) with appropriate pr_info and pr_err in order to fix checkpatch.pl warnings Signed-off-by: Saurabh Sengar Acked-by: Pavel Machek Signed-off-by: Rafael J. Wysocki --- kernel/power/suspend.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index f9fe133c13e2..230a77225e2e 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -248,7 +248,7 @@ static int suspend_test(int level) { #ifdef CONFIG_PM_DEBUG if (pm_test_level == level) { - printk(KERN_INFO "suspend debug: Waiting for %d second(s).\n", + pr_info("suspend debug: Waiting for %d second(s).\n", pm_test_delay); mdelay(pm_test_delay * 1000); return 1; @@ -320,7 +320,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) error = dpm_suspend_late(PMSG_SUSPEND); if (error) { - printk(KERN_ERR "PM: late suspend of devices failed\n"); + pr_err("PM: late suspend of devices failed\n"); goto Platform_finish; } error = platform_suspend_prepare_late(state); @@ -329,7 +329,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) error = dpm_suspend_noirq(PMSG_SUSPEND); if (error) { - printk(KERN_ERR "PM: noirq suspend of devices failed\n"); + pr_err("PM: noirq suspend of devices failed\n"); goto Platform_early_resume; } error = platform_suspend_prepare_noirq(state); -- cgit From c4726abce63bf9b1887ce68fdf012a823bd94ec3 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 8 Feb 2016 17:45:28 -0800 Subject: mfd: intel_quark_i2c_gpio: Use clkdev_create() Convert this driver to use clkdev_create() instead of clk_register_clkdevs(). The latter API is only used by this driver, although this driver only allocates one clk to add anyway. Furthermore, this driver allocates the clk_lookup structure with devm, but clkdev_drop() will free that structure when passed, leading to a double free when this driver is removed. Clean it all up and pave the way for the removal of clk_register_clkdevs(). Cc: Andy Shevchenko Cc: Russell King Signed-off-by: Stephen Boyd Signed-off-by: Lee Jones --- drivers/mfd/intel_quark_i2c_gpio.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index 042137465300..bdc5e27222c0 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c @@ -52,8 +52,6 @@ /* The Quark I2C controller source clock */ #define INTEL_QUARK_I2C_CLK_HZ 33000000 -#define INTEL_QUARK_I2C_NCLK 1 - struct intel_quark_mfd { struct pci_dev *pdev; struct clk *i2c_clk; @@ -128,30 +126,24 @@ MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids); static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) { struct pci_dev *pdev = quark_mfd->pdev; - struct clk_lookup *i2c_clk_lookup; struct clk *i2c_clk; - int ret; - - i2c_clk_lookup = devm_kcalloc(&pdev->dev, INTEL_QUARK_I2C_NCLK, - sizeof(*i2c_clk_lookup), GFP_KERNEL); - if (!i2c_clk_lookup) - return -ENOMEM; - - i2c_clk_lookup[0].dev_id = INTEL_QUARK_I2C_CONTROLLER_CLK; i2c_clk = clk_register_fixed_rate(&pdev->dev, INTEL_QUARK_I2C_CONTROLLER_CLK, NULL, CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ); + if (IS_ERR(i2c_clk)) + return PTR_ERR(i2c_clk); - quark_mfd->i2c_clk_lookup = i2c_clk_lookup; quark_mfd->i2c_clk = i2c_clk; + quark_mfd->i2c_clk_lookup = clkdev_create(i2c_clk, NULL, + INTEL_QUARK_I2C_CONTROLLER_CLK); - ret = clk_register_clkdevs(i2c_clk, i2c_clk_lookup, - INTEL_QUARK_I2C_NCLK); - if (ret) - dev_err(&pdev->dev, "Fixed clk register failed: %d\n", ret); + if (!quark_mfd->i2c_clk_lookup) { + dev_err(&pdev->dev, "Fixed clk register failed\n"); + return -ENOMEM; + } - return ret; + return 0; } static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) -- cgit From 55cd48c821def1d3192f166b4ce48254cf2e5a69 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:43 -0700 Subject: net: fec: stop the "rcv is not +last, " error messages Setting the FTRL register will stop the fec from trying to use multiple receive buffers. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 1 + drivers/net/ethernet/freescale/fec_main.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 2106d72c91dc..cc9677ae70ab 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -64,6 +64,7 @@ #define FEC_R_FIFO_RSEM 0x194 /* Receive FIFO section empty threshold */ #define FEC_R_FIFO_RAEM 0x198 /* Receive FIFO almost empty threshold */ #define FEC_R_FIFO_RAFL 0x19c /* Receive FIFO almost full threshold */ +#define FEC_FTRL 0x1b0 /* Frame truncation receive length*/ #define FEC_RACC 0x1c4 /* Receive Accelerator function */ #define FEC_RCMR_1 0x1c8 /* Receive classification match ring 1 */ #define FEC_RCMR_2 0x1cc /* Receive classification match ring 2 */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 41c81f6ec630..3e5b24ae537e 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -988,6 +988,7 @@ fec_restart(struct net_device *ndev) val &= ~FEC_RACC_OPTIONS; writel(val, fep->hwp + FEC_RACC); } + writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); #endif /* -- cgit From 095098e194d1357a509c1d8e9a421bf825dddd2a Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:44 -0700 Subject: net: fec: fix rx error counts On an overrun, the other flags are not valid, so don't check them. Also, don't pass bad frames up the stack. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 36 +++++++++++++------------------ 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 3e5b24ae537e..162fa59e3eae 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1408,37 +1408,31 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) break; pkt_received++; - /* Since we have allocated space to hold a complete frame, - * the last indicator should be set. - */ - if ((status & BD_ENET_RX_LAST) == 0) - netdev_err(ndev, "rcv is not +last\n"); - writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT); /* Check for errors. */ + status ^= BD_ENET_RX_LAST; if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | - BD_ENET_RX_CR | BD_ENET_RX_OV)) { + BD_ENET_RX_CR | BD_ENET_RX_OV | BD_ENET_RX_LAST | + BD_ENET_RX_CL)) { ndev->stats.rx_errors++; - if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { + if (status & BD_ENET_RX_OV) { + /* FIFO overrun */ + ndev->stats.rx_fifo_errors++; + goto rx_processing_done; + } + if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH + | BD_ENET_RX_LAST)) { /* Frame too long or too short. */ ndev->stats.rx_length_errors++; + if (status & BD_ENET_RX_LAST) + netdev_err(ndev, "rcv is not +last\n"); } - if (status & BD_ENET_RX_NO) /* Frame alignment */ - ndev->stats.rx_frame_errors++; if (status & BD_ENET_RX_CR) /* CRC Error */ ndev->stats.rx_crc_errors++; - if (status & BD_ENET_RX_OV) /* FIFO overrun */ - ndev->stats.rx_fifo_errors++; - } - - /* Report late collisions as a frame error. - * On this error, the BD is closed, but we don't know what we - * have in the buffer. So, just drop this frame on the floor. - */ - if (status & BD_ENET_RX_CL) { - ndev->stats.rx_errors++; - ndev->stats.rx_frame_errors++; + /* Report late collisions as a frame error. */ + if (status & (BD_ENET_RX_NO | BD_ENET_RX_CL)) + ndev->stats.rx_frame_errors++; goto rx_processing_done; } -- cgit From 93c595f7b8c5fe98bd78bab5270a49c40a69f221 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:45 -0700 Subject: net: fec: fix fec_enet_get_free_txdesc_num When first initialized, cur_tx points to the 1st entry in the queue, and dirty_tx points to the last. At this point, fec_enet_get_free_txdesc_num will return tx_ring_size -2. If tx_ring_size -2 entries are now queued, then fec_enet_get_free_txdesc_num should return 0, but it returns tx_ring_size instead. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 162fa59e3eae..adbddfdb5474 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -296,7 +296,7 @@ static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep, entries = ((const char *)txq->dirty_tx - (const char *)txq->cur_tx) / fep->bufdesc_size - 1; - return entries > 0 ? entries : entries + txq->tx_ring_size; + return entries >= 0 ? entries : entries + txq->tx_ring_size; } static void swap_buffer(void *bufaddr, int len) -- cgit From 7355f2760620b385d1335f9cf73fbb1b640c4726 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:46 -0700 Subject: net: fec: add struct bufdesc_prop This reduces code and gains speed. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 29 ++- drivers/net/ethernet/freescale/fec_main.c | 288 ++++++++++++------------------ 2 files changed, 132 insertions(+), 185 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index cc9677ae70ab..53ec04fbdc6d 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -448,33 +448,34 @@ struct bufdesc_ex { /* Controller supports RACC register */ #define FEC_QUIRK_HAS_RACC (1 << 12) +struct bufdesc_prop { + int qid; + /* Address of Rx and Tx buffers */ + struct bufdesc *base; + struct bufdesc *last; + struct bufdesc *cur; + dma_addr_t dma; + unsigned short ring_size; + unsigned char dsize; + unsigned char dsize_log2; +}; + struct fec_enet_priv_tx_q { - int index; + struct bufdesc_prop bd; unsigned char *tx_bounce[TX_RING_SIZE]; struct sk_buff *tx_skbuff[TX_RING_SIZE]; - dma_addr_t bd_dma; - struct bufdesc *tx_bd_base; - uint tx_ring_size; - unsigned short tx_stop_threshold; unsigned short tx_wake_threshold; - struct bufdesc *cur_tx; struct bufdesc *dirty_tx; char *tso_hdrs; dma_addr_t tso_hdrs_dma; }; struct fec_enet_priv_rx_q { - int index; + struct bufdesc_prop bd; struct sk_buff *rx_skbuff[RX_RING_SIZE]; - - dma_addr_t bd_dma; - struct bufdesc *rx_bd_base; - uint rx_ring_size; - - struct bufdesc *cur_rx; }; /* The FEC buffer descriptors track the ring buffers. The rx_bd_base and @@ -514,8 +515,6 @@ struct fec_enet_private { unsigned long work_ts; unsigned long work_mdio; - unsigned short bufdesc_size; - struct platform_device *pdev; int dev_id; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index adbddfdb5474..b039288f5c98 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -217,86 +217,38 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #define IS_TSO_HEADER(txq, addr) \ ((addr >= txq->tso_hdrs_dma) && \ - (addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE)) + (addr < txq->tso_hdrs_dma + txq->bd.ring_size * TSO_HEADER_SIZE)) static int mii_cnt; -static inline -struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, - struct fec_enet_private *fep, - int queue_id) -{ - struct bufdesc *new_bd = bdp + 1; - struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp + 1; - struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; - struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id]; - struct bufdesc_ex *ex_base; - struct bufdesc *base; - int ring_size; - - if (bdp >= txq->tx_bd_base) { - base = txq->tx_bd_base; - ring_size = txq->tx_ring_size; - ex_base = (struct bufdesc_ex *)txq->tx_bd_base; - } else { - base = rxq->rx_bd_base; - ring_size = rxq->rx_ring_size; - ex_base = (struct bufdesc_ex *)rxq->rx_bd_base; - } - - if (fep->bufdesc_ex) - return (struct bufdesc *)((ex_new_bd >= (ex_base + ring_size)) ? - ex_base : ex_new_bd); - else - return (new_bd >= (base + ring_size)) ? - base : new_bd; -} - -static inline -struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, - struct fec_enet_private *fep, - int queue_id) -{ - struct bufdesc *new_bd = bdp - 1; - struct bufdesc_ex *ex_new_bd = (struct bufdesc_ex *)bdp - 1; - struct fec_enet_priv_tx_q *txq = fep->tx_queue[queue_id]; - struct fec_enet_priv_rx_q *rxq = fep->rx_queue[queue_id]; - struct bufdesc_ex *ex_base; - struct bufdesc *base; - int ring_size; - - if (bdp >= txq->tx_bd_base) { - base = txq->tx_bd_base; - ring_size = txq->tx_ring_size; - ex_base = (struct bufdesc_ex *)txq->tx_bd_base; - } else { - base = rxq->rx_bd_base; - ring_size = rxq->rx_ring_size; - ex_base = (struct bufdesc_ex *)rxq->rx_bd_base; - } +static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp, + struct bufdesc_prop *bd) +{ + return (bdp >= bd->last) ? bd->base + : (struct bufdesc *)(((unsigned)bdp) + bd->dsize); +} - if (fep->bufdesc_ex) - return (struct bufdesc *)((ex_new_bd < ex_base) ? - (ex_new_bd + ring_size) : ex_new_bd); - else - return (new_bd < base) ? (new_bd + ring_size) : new_bd; +static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp, + struct bufdesc_prop *bd) +{ + return (bdp <= bd->base) ? bd->last + : (struct bufdesc *)(((unsigned)bdp) - bd->dsize); } -static int fec_enet_get_bd_index(struct bufdesc *base, struct bufdesc *bdp, - struct fec_enet_private *fep) +static int fec_enet_get_bd_index(struct bufdesc *bdp, + struct bufdesc_prop *bd) { - return ((const char *)bdp - (const char *)base) / fep->bufdesc_size; + return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2; } -static int fec_enet_get_free_txdesc_num(struct fec_enet_private *fep, - struct fec_enet_priv_tx_q *txq) +static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq) { int entries; - entries = ((const char *)txq->dirty_tx - - (const char *)txq->cur_tx) / fep->bufdesc_size - 1; + entries = (((const char *)txq->dirty_tx - + (const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1; - return entries >= 0 ? entries : entries + txq->tx_ring_size; + return entries >= 0 ? entries : entries + txq->bd.ring_size; } static void swap_buffer(void *bufaddr, int len) @@ -329,20 +281,20 @@ static void fec_dump(struct net_device *ndev) pr_info("Nr SC addr len SKB\n"); txq = fep->tx_queue[0]; - bdp = txq->tx_bd_base; + bdp = txq->bd.base; do { pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n", index, - bdp == txq->cur_tx ? 'S' : ' ', + bdp == txq->bd.cur ? 'S' : ' ', bdp == txq->dirty_tx ? 'H' : ' ', fec16_to_cpu(bdp->cbd_sc), fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), txq->tx_skbuff[index]); - bdp = fec_enet_get_nextdesc(bdp, fep, 0); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); index++; - } while (bdp != txq->tx_bd_base); + } while (bdp != txq->bd.base); } static inline bool is_ipv4_pkt(struct sk_buff *skb) @@ -373,7 +325,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - struct bufdesc *bdp = txq->cur_tx; + struct bufdesc *bdp = txq->bd.cur; struct bufdesc_ex *ebdp; int nr_frags = skb_shinfo(skb)->nr_frags; unsigned short queue = skb_get_queue_mapping(skb); @@ -388,7 +340,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, for (frag = 0; frag < nr_frags; frag++) { this_frag = &skb_shinfo(skb)->frags[frag]; - bdp = fec_enet_get_nextdesc(bdp, fep, queue); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); ebdp = (struct bufdesc_ex *)bdp; status = fec16_to_cpu(bdp->cbd_sc); @@ -418,7 +370,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; - index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + index = fec_enet_get_bd_index(bdp, &txq->bd); if (((unsigned long) bufaddr) & fep->tx_align || fep->quirks & FEC_QUIRK_SWAP_FRAME) { memcpy(txq->tx_bounce[index], bufaddr, frag_len); @@ -444,9 +396,9 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, return bdp; dma_mapping_error: - bdp = txq->cur_tx; + bdp = txq->bd.cur; for (i = 0; i < frag; i++) { - bdp = fec_enet_get_nextdesc(bdp, fep, queue); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr), fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE); } @@ -468,7 +420,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, unsigned int index; int entries_free; - entries_free = fec_enet_get_free_txdesc_num(fep, txq); + entries_free = fec_enet_get_free_txdesc_num(txq); if (entries_free < MAX_SKB_FRAGS + 1) { dev_kfree_skb_any(skb); if (net_ratelimit()) @@ -483,7 +435,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, } /* Fill in a Tx ring entry */ - bdp = txq->cur_tx; + bdp = txq->bd.cur; last_bdp = bdp; status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; @@ -493,7 +445,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, buflen = skb_headlen(skb); queue = skb_get_queue_mapping(skb); - index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + index = fec_enet_get_bd_index(bdp, &txq->bd); if (((unsigned long) bufaddr) & fep->tx_align || fep->quirks & FEC_QUIRK_SWAP_FRAME) { memcpy(txq->tx_bounce[index], skb->data, buflen); @@ -544,7 +496,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, ebdp->cbd_esc = cpu_to_fec32(estatus); } - index = fec_enet_get_bd_index(txq->tx_bd_base, last_bdp, fep); + index = fec_enet_get_bd_index(last_bdp, &txq->bd); /* Save skb pointer */ txq->tx_skbuff[index] = skb; @@ -558,15 +510,15 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, bdp->cbd_sc = cpu_to_fec16(status); /* If this was the last BD in the ring, start at the beginning again. */ - bdp = fec_enet_get_nextdesc(last_bdp, fep, queue); + bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); skb_tx_timestamp(skb); /* Make sure the update to bdp and tx_skbuff are performed before - * cur_tx. + * txq->bd.cur. */ wmb(); - txq->cur_tx = bdp; + txq->bd.cur = bdp; /* Trigger transmission start */ writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); @@ -697,13 +649,13 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, struct fec_enet_private *fep = netdev_priv(ndev); int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); int total_len, data_left; - struct bufdesc *bdp = txq->cur_tx; + struct bufdesc *bdp = txq->bd.cur; unsigned short queue = skb_get_queue_mapping(skb); struct tso_t tso; unsigned int index = 0; int ret; - if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(fep, txq)) { + if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) { dev_kfree_skb_any(skb); if (net_ratelimit()) netdev_err(ndev, "NOT enough BD for TSO!\n"); @@ -723,7 +675,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, while (total_len > 0) { char *hdr; - index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + index = fec_enet_get_bd_index(bdp, &txq->bd); data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len); total_len -= data_left; @@ -738,9 +690,8 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, int size; size = min_t(int, tso.size, data_left); - bdp = fec_enet_get_nextdesc(bdp, fep, queue); - index = fec_enet_get_bd_index(txq->tx_bd_base, - bdp, fep); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); + index = fec_enet_get_bd_index(bdp, &txq->bd); ret = fec_enet_txq_put_data_tso(txq, skb, ndev, bdp, index, tso.data, size, @@ -753,14 +704,14 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, tso_build_data(skb, &tso, size); } - bdp = fec_enet_get_nextdesc(bdp, fep, queue); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); } /* Save skb pointer */ txq->tx_skbuff[index] = skb; skb_tx_timestamp(skb); - txq->cur_tx = bdp; + txq->bd.cur = bdp; /* Trigger transmission start */ if (!(fep->quirks & FEC_QUIRK_ERR007885) || @@ -798,7 +749,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (ret) return ret; - entries_free = fec_enet_get_free_txdesc_num(fep, txq); + entries_free = fec_enet_get_free_txdesc_num(txq); if (entries_free <= txq->tx_stop_threshold) netif_tx_stop_queue(nq); @@ -819,32 +770,32 @@ static void fec_enet_bd_init(struct net_device *dev) for (q = 0; q < fep->num_rx_queues; q++) { /* Initialize the receive buffer descriptors. */ rxq = fep->rx_queue[q]; - bdp = rxq->rx_bd_base; + bdp = rxq->bd.base; - for (i = 0; i < rxq->rx_ring_size; i++) { + for (i = 0; i < rxq->bd.ring_size; i++) { /* Initialize the BD for every fragment in the page. */ if (bdp->cbd_bufaddr) bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY); else bdp->cbd_sc = cpu_to_fec16(0); - bdp = fec_enet_get_nextdesc(bdp, fep, q); + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); } /* Set the last buffer to wrap */ - bdp = fec_enet_get_prevdesc(bdp, fep, q); + bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); - rxq->cur_rx = rxq->rx_bd_base; + rxq->bd.cur = rxq->bd.base; } for (q = 0; q < fep->num_tx_queues; q++) { /* ...and the same for transmit */ txq = fep->tx_queue[q]; - bdp = txq->tx_bd_base; - txq->cur_tx = bdp; + bdp = txq->bd.base; + txq->bd.cur = bdp; - for (i = 0; i < txq->tx_ring_size; i++) { + for (i = 0; i < txq->bd.ring_size; i++) { /* Initialize the BD for every fragment in the page. */ bdp->cbd_sc = cpu_to_fec16(0); if (txq->tx_skbuff[i]) { @@ -852,11 +803,11 @@ static void fec_enet_bd_init(struct net_device *dev) txq->tx_skbuff[i] = NULL; } bdp->cbd_bufaddr = cpu_to_fec32(0); - bdp = fec_enet_get_nextdesc(bdp, fep, q); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); } /* Set the last buffer to wrap */ - bdp = fec_enet_get_prevdesc(bdp, fep, q); + bdp = fec_enet_get_prevdesc(bdp, &txq->bd); bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); txq->dirty_tx = bdp; } @@ -880,7 +831,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) for (i = 0; i < fep->num_rx_queues; i++) { rxq = fep->rx_queue[i]; - writel(rxq->bd_dma, fep->hwp + FEC_R_DES_START(i)); + writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i)); writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i)); /* enable DMA1/2 */ @@ -891,7 +842,7 @@ static void fec_enet_enable_ring(struct net_device *ndev) for (i = 0; i < fep->num_tx_queues; i++) { txq = fep->tx_queue[i]; - writel(txq->bd_dma, fep->hwp + FEC_X_DES_START(i)); + writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i)); /* enable DMA1/2 */ if (i) @@ -909,7 +860,7 @@ static void fec_enet_reset_skb(struct net_device *ndev) for (i = 0; i < fep->num_tx_queues; i++) { txq = fep->tx_queue[i]; - for (j = 0; j < txq->tx_ring_size; j++) { + for (j = 0; j < txq->bd.ring_size; j++) { if (txq->tx_skbuff[j]) { dev_kfree_skb_any(txq->tx_skbuff[j]); txq->tx_skbuff[j] = NULL; @@ -1222,16 +1173,16 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) bdp = txq->dirty_tx; /* get next bdp of dirty_tx */ - bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); - while (bdp != READ_ONCE(txq->cur_tx)) { - /* Order the load of cur_tx and cbd_sc */ + while (bdp != READ_ONCE(txq->bd.cur)) { + /* Order the load of bd.cur and cbd_sc */ rmb(); status = fec16_to_cpu(READ_ONCE(bdp->cbd_sc)); if (status & BD_ENET_TX_READY) break; - index = fec_enet_get_bd_index(txq->tx_bd_base, bdp, fep); + index = fec_enet_get_bd_index(bdp, &txq->bd); skb = txq->tx_skbuff[index]; txq->tx_skbuff[index] = NULL; @@ -1242,7 +1193,7 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) DMA_TO_DEVICE); bdp->cbd_bufaddr = cpu_to_fec32(0); if (!skb) { - bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); continue; } @@ -1291,19 +1242,19 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) txq->dirty_tx = bdp; /* Update pointer to next buffer descriptor to be transmitted */ - bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); /* Since we have freed up a buffer, the ring is no longer full */ if (netif_queue_stopped(ndev)) { - entries_free = fec_enet_get_free_txdesc_num(fep, txq); + entries_free = fec_enet_get_free_txdesc_num(txq); if (entries_free >= txq->tx_wake_threshold) netif_tx_wake_queue(nq); } } /* ERR006538: Keep the transmitter going */ - if (bdp != txq->cur_tx && + if (bdp != txq->bd.cur && readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0) writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id)); } @@ -1367,7 +1318,7 @@ static bool fec_enet_copybreak(struct net_device *ndev, struct sk_buff **skb, return true; } -/* During a receive, the cur_rx points to the current incoming buffer. +/* During a receive, the bd_rx.cur points to the current incoming buffer. * When we update through the ring, if the next incoming buffer has * not been given to the system, we just set the empty indicator, * effectively tossing the packet. @@ -1400,7 +1351,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) /* First, grab all of the stats for the incoming packet. * These get messed up if we get called due to a busy condition. */ - bdp = rxq->cur_rx; + bdp = rxq->bd.cur; while (!((status = fec16_to_cpu(bdp->cbd_sc)) & BD_ENET_RX_EMPTY)) { @@ -1441,7 +1392,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id) pkt_len = fec16_to_cpu(bdp->cbd_datlen); ndev->stats.rx_bytes += pkt_len; - index = fec_enet_get_bd_index(rxq->rx_bd_base, bdp, fep); + index = fec_enet_get_bd_index(bdp, &rxq->bd); skb = rxq->rx_skbuff[index]; /* The packet length includes FCS, but we don't want to @@ -1541,7 +1492,7 @@ rx_processing_done: } /* Update BD pointer to next entry */ - bdp = fec_enet_get_nextdesc(bdp, fep, queue_id); + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); /* Doing this here will keep the FEC running while we process * incoming frames. On a heavily loaded network, we should be @@ -1549,7 +1500,7 @@ rx_processing_done: */ writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id)); } - rxq->cur_rx = bdp; + rxq->bd.cur = bdp; return pkt_received; } @@ -2658,8 +2609,8 @@ static void fec_enet_free_buffers(struct net_device *ndev) for (q = 0; q < fep->num_rx_queues; q++) { rxq = fep->rx_queue[q]; - bdp = rxq->rx_bd_base; - for (i = 0; i < rxq->rx_ring_size; i++) { + bdp = rxq->bd.base; + for (i = 0; i < rxq->bd.ring_size; i++) { skb = rxq->rx_skbuff[i]; rxq->rx_skbuff[i] = NULL; if (skb) { @@ -2669,14 +2620,14 @@ static void fec_enet_free_buffers(struct net_device *ndev) DMA_FROM_DEVICE); dev_kfree_skb(skb); } - bdp = fec_enet_get_nextdesc(bdp, fep, q); + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); } } for (q = 0; q < fep->num_tx_queues; q++) { txq = fep->tx_queue[q]; - bdp = txq->tx_bd_base; - for (i = 0; i < txq->tx_ring_size; i++) { + bdp = txq->bd.base; + for (i = 0; i < txq->bd.ring_size; i++) { kfree(txq->tx_bounce[i]); txq->tx_bounce[i] = NULL; skb = txq->tx_skbuff[i]; @@ -2696,7 +2647,7 @@ static void fec_enet_free_queue(struct net_device *ndev) if (fep->tx_queue[i] && fep->tx_queue[i]->tso_hdrs) { txq = fep->tx_queue[i]; dma_free_coherent(NULL, - txq->tx_ring_size * TSO_HEADER_SIZE, + txq->bd.ring_size * TSO_HEADER_SIZE, txq->tso_hdrs, txq->tso_hdrs_dma); } @@ -2722,15 +2673,15 @@ static int fec_enet_alloc_queue(struct net_device *ndev) } fep->tx_queue[i] = txq; - txq->tx_ring_size = TX_RING_SIZE; - fep->total_tx_ring_size += fep->tx_queue[i]->tx_ring_size; + txq->bd.ring_size = TX_RING_SIZE; + fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size; txq->tx_stop_threshold = FEC_MAX_SKB_DESCS; txq->tx_wake_threshold = - (txq->tx_ring_size - txq->tx_stop_threshold) / 2; + (txq->bd.ring_size - txq->tx_stop_threshold) / 2; txq->tso_hdrs = dma_alloc_coherent(NULL, - txq->tx_ring_size * TSO_HEADER_SIZE, + txq->bd.ring_size * TSO_HEADER_SIZE, &txq->tso_hdrs_dma, GFP_KERNEL); if (!txq->tso_hdrs) { @@ -2747,8 +2698,8 @@ static int fec_enet_alloc_queue(struct net_device *ndev) goto alloc_failed; } - fep->rx_queue[i]->rx_ring_size = RX_RING_SIZE; - fep->total_rx_ring_size += fep->rx_queue[i]->rx_ring_size; + fep->rx_queue[i]->bd.ring_size = RX_RING_SIZE; + fep->total_rx_ring_size += fep->rx_queue[i]->bd.ring_size; } return ret; @@ -2767,8 +2718,8 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) struct fec_enet_priv_rx_q *rxq; rxq = fep->rx_queue[queue]; - bdp = rxq->rx_bd_base; - for (i = 0; i < rxq->rx_ring_size; i++) { + bdp = rxq->bd.base; + for (i = 0; i < rxq->bd.ring_size; i++) { skb = netdev_alloc_skb(ndev, FEC_ENET_RX_FRSIZE); if (!skb) goto err_alloc; @@ -2786,11 +2737,11 @@ fec_enet_alloc_rxq_buffers(struct net_device *ndev, unsigned int queue) ebdp->cbd_esc = cpu_to_fec32(BD_ENET_RX_INT); } - bdp = fec_enet_get_nextdesc(bdp, fep, queue); + bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); } /* Set the last buffer to wrap. */ - bdp = fec_enet_get_prevdesc(bdp, fep, queue); + bdp = fec_enet_get_prevdesc(bdp, &rxq->bd); bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); return 0; @@ -2808,8 +2759,8 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) struct fec_enet_priv_tx_q *txq; txq = fep->tx_queue[queue]; - bdp = txq->tx_bd_base; - for (i = 0; i < txq->tx_ring_size; i++) { + bdp = txq->bd.base; + for (i = 0; i < txq->bd.ring_size; i++) { txq->tx_bounce[i] = kmalloc(FEC_ENET_TX_FRSIZE, GFP_KERNEL); if (!txq->tx_bounce[i]) goto err_alloc; @@ -2822,11 +2773,11 @@ fec_enet_alloc_txq_buffers(struct net_device *ndev, unsigned int queue) ebdp->cbd_esc = cpu_to_fec32(BD_ENET_TX_INT); } - bdp = fec_enet_get_nextdesc(bdp, fep, queue); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); } /* Set the last buffer to wrap. */ - bdp = fec_enet_get_prevdesc(bdp, fep, queue); + bdp = fec_enet_get_prevdesc(bdp, &txq->bd); bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP); return 0; @@ -3117,13 +3068,15 @@ static const struct net_device_ops fec_netdev_ops = { static int fec_enet_init(struct net_device *ndev) { struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_enet_priv_tx_q *txq; - struct fec_enet_priv_rx_q *rxq; struct bufdesc *cbd_base; dma_addr_t bd_dma; int bd_size; unsigned int i; + unsigned dsize = fep->bufdesc_ex ? sizeof(struct bufdesc_ex) : + sizeof(struct bufdesc); + unsigned dsize_log2 = __fls(dsize); + WARN_ON(dsize != (1 << dsize_log2)); #if defined(CONFIG_ARM) fep->rx_align = 0xf; fep->tx_align = 0xf; @@ -3134,12 +3087,7 @@ static int fec_enet_init(struct net_device *ndev) fec_enet_alloc_queue(ndev); - if (fep->bufdesc_ex) - fep->bufdesc_size = sizeof(struct bufdesc_ex); - else - fep->bufdesc_size = sizeof(struct bufdesc); - bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * - fep->bufdesc_size; + bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize; /* Allocate memory for buffer descriptors. */ cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma, @@ -3157,33 +3105,33 @@ static int fec_enet_init(struct net_device *ndev) /* Set receive and transmit descriptor base. */ for (i = 0; i < fep->num_rx_queues; i++) { - rxq = fep->rx_queue[i]; - rxq->index = i; - rxq->rx_bd_base = (struct bufdesc *)cbd_base; - rxq->bd_dma = bd_dma; - if (fep->bufdesc_ex) { - bd_dma += sizeof(struct bufdesc_ex) * rxq->rx_ring_size; - cbd_base = (struct bufdesc *) - (((struct bufdesc_ex *)cbd_base) + rxq->rx_ring_size); - } else { - bd_dma += sizeof(struct bufdesc) * rxq->rx_ring_size; - cbd_base += rxq->rx_ring_size; - } + struct fec_enet_priv_rx_q *rxq = fep->rx_queue[i]; + unsigned size = dsize * rxq->bd.ring_size; + + rxq->bd.qid = i; + rxq->bd.base = cbd_base; + rxq->bd.cur = cbd_base; + rxq->bd.dma = bd_dma; + rxq->bd.dsize = dsize; + rxq->bd.dsize_log2 = dsize_log2; + bd_dma += size; + cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); + rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); } for (i = 0; i < fep->num_tx_queues; i++) { - txq = fep->tx_queue[i]; - txq->index = i; - txq->tx_bd_base = (struct bufdesc *)cbd_base; - txq->bd_dma = bd_dma; - if (fep->bufdesc_ex) { - bd_dma += sizeof(struct bufdesc_ex) * txq->tx_ring_size; - cbd_base = (struct bufdesc *) - (((struct bufdesc_ex *)cbd_base) + txq->tx_ring_size); - } else { - bd_dma += sizeof(struct bufdesc) * txq->tx_ring_size; - cbd_base += txq->tx_ring_size; - } + struct fec_enet_priv_tx_q *txq = fep->tx_queue[i]; + unsigned size = dsize * txq->bd.ring_size; + + txq->bd.qid = i; + txq->bd.base = cbd_base; + txq->bd.cur = cbd_base; + txq->bd.dma = bd_dma; + txq->bd.dsize = dsize; + txq->bd.dsize_log2 = dsize_log2; + bd_dma += size; + cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); + txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); } -- cgit From 53bb20d1fabacc6601e68a6a69d9d1e3aff6bd69 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:47 -0700 Subject: net: fec: add variable reg_desc_active to speed things up There is no need for complex macros every time we need to activate a queue. Also, no need to call skb_get_queue_mapping when we already know which queue it is using. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 7 +---- drivers/net/ethernet/freescale/fec_main.c | 44 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 53ec04fbdc6d..bedd28a6e8f5 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -310,12 +310,6 @@ struct bufdesc_ex { #define FEC_R_BUFF_SIZE(X) (((X) == 1) ? FEC_R_BUFF_SIZE_1 : \ (((X) == 2) ? \ FEC_R_BUFF_SIZE_2 : FEC_R_BUFF_SIZE_0)) -#define FEC_R_DES_ACTIVE(X) (((X) == 1) ? FEC_R_DES_ACTIVE_1 : \ - (((X) == 2) ? \ - FEC_R_DES_ACTIVE_2 : FEC_R_DES_ACTIVE_0)) -#define FEC_X_DES_ACTIVE(X) (((X) == 1) ? FEC_X_DES_ACTIVE_1 : \ - (((X) == 2) ? \ - FEC_X_DES_ACTIVE_2 : FEC_X_DES_ACTIVE_0)) #define FEC_DMA_CFG(X) (((X) == 2) ? FEC_DMA_CFG_2 : FEC_DMA_CFG_1) @@ -454,6 +448,7 @@ struct bufdesc_prop { struct bufdesc *base; struct bufdesc *last; struct bufdesc *cur; + void __iomem *reg_desc_active; dma_addr_t dma; unsigned short ring_size; unsigned char dsize; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index b039288f5c98..712e3bb1e0d3 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -328,7 +328,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, struct bufdesc *bdp = txq->bd.cur; struct bufdesc_ex *ebdp; int nr_frags = skb_shinfo(skb)->nr_frags; - unsigned short queue = skb_get_queue_mapping(skb); int frag, frag_len; unsigned short status; unsigned int estatus = 0; @@ -361,7 +360,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, if (fep->bufdesc_ex) { if (fep->quirks & FEC_QUIRK_HAS_AVB) - estatus |= FEC_TX_BD_FTYPE(queue); + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; @@ -415,7 +414,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, dma_addr_t addr; unsigned short status; unsigned short buflen; - unsigned short queue; unsigned int estatus = 0; unsigned int index; int entries_free; @@ -444,7 +442,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, bufaddr = skb->data; buflen = skb_headlen(skb); - queue = skb_get_queue_mapping(skb); index = fec_enet_get_bd_index(bdp, &txq->bd); if (((unsigned long) bufaddr) & fep->tx_align || fep->quirks & FEC_QUIRK_SWAP_FRAME) { @@ -487,7 +484,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; if (fep->quirks & FEC_QUIRK_HAS_AVB) - estatus |= FEC_TX_BD_FTYPE(queue); + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; @@ -521,7 +518,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, txq->bd.cur = bdp; /* Trigger transmission start */ - writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); + writel(0, txq->bd.reg_desc_active); return 0; } @@ -534,7 +531,6 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, { struct fec_enet_private *fep = netdev_priv(ndev); struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); - unsigned short queue = skb_get_queue_mapping(skb); unsigned short status; unsigned int estatus = 0; dma_addr_t addr; @@ -566,7 +562,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb, if (fep->bufdesc_ex) { if (fep->quirks & FEC_QUIRK_HAS_AVB) - estatus |= FEC_TX_BD_FTYPE(queue); + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; @@ -595,7 +591,6 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, struct fec_enet_private *fep = netdev_priv(ndev); int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc); - unsigned short queue = skb_get_queue_mapping(skb); void *bufaddr; unsigned long dmabuf; unsigned short status; @@ -630,7 +625,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq, if (fep->bufdesc_ex) { if (fep->quirks & FEC_QUIRK_HAS_AVB) - estatus |= FEC_TX_BD_FTYPE(queue); + estatus |= FEC_TX_BD_FTYPE(txq->bd.qid); if (skb->ip_summed == CHECKSUM_PARTIAL) estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS; ebdp->cbd_bdu = 0; @@ -650,7 +645,6 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); int total_len, data_left; struct bufdesc *bdp = txq->bd.cur; - unsigned short queue = skb_get_queue_mapping(skb); struct tso_t tso; unsigned int index = 0; int ret; @@ -715,11 +709,11 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq, /* Trigger transmission start */ if (!(fep->quirks & FEC_QUIRK_ERR007885) || - !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || - !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || - !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) || - !readl(fep->hwp + FEC_X_DES_ACTIVE(queue))) - writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); + !readl(txq->bd.reg_desc_active) || + !readl(txq->bd.reg_desc_active) || + !readl(txq->bd.reg_desc_active) || + !readl(txq->bd.reg_desc_active)) + writel(0, txq->bd.reg_desc_active); return 0; @@ -819,7 +813,7 @@ static void fec_enet_active_rxring(struct net_device *ndev) int i; for (i = 0; i < fep->num_rx_queues; i++) - writel(0, fep->hwp + FEC_R_DES_ACTIVE(i)); + writel(0, fep->rx_queue[i]->bd.reg_desc_active); } static void fec_enet_enable_ring(struct net_device *ndev) @@ -1255,8 +1249,8 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) /* ERR006538: Keep the transmitter going */ if (bdp != txq->bd.cur && - readl(fep->hwp + FEC_X_DES_ACTIVE(queue_id)) == 0) - writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue_id)); + readl(txq->bd.reg_desc_active) == 0) + writel(0, txq->bd.reg_desc_active); } static void @@ -1498,7 +1492,7 @@ rx_processing_done: * incoming frames. On a heavily loaded network, we should be * able to keep up at the expense of system resources. */ - writel(0, fep->hwp + FEC_R_DES_ACTIVE(queue_id)); + writel(0, rxq->bd.reg_desc_active); } rxq->bd.cur = bdp; return pkt_received; @@ -3061,6 +3055,14 @@ static const struct net_device_ops fec_netdev_ops = { .ndo_set_features = fec_set_features, }; +static const unsigned short offset_des_active_rxq[] = { + FEC_R_DES_ACTIVE_0, FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2 +}; + +static const unsigned short offset_des_active_txq[] = { + FEC_X_DES_ACTIVE_0, FEC_X_DES_ACTIVE_1, FEC_X_DES_ACTIVE_2 +}; + /* * XXX: We need to clean up on failure exits here. * @@ -3114,6 +3116,7 @@ static int fec_enet_init(struct net_device *ndev) rxq->bd.dma = bd_dma; rxq->bd.dsize = dsize; rxq->bd.dsize_log2 = dsize_log2; + rxq->bd.reg_desc_active = fep->hwp + offset_des_active_rxq[i]; bd_dma += size; cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); rxq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); @@ -3129,6 +3132,7 @@ static int fec_enet_init(struct net_device *ndev) txq->bd.dma = bd_dma; txq->bd.dsize = dsize; txq->bd.dsize_log2 = dsize_log2; + txq->bd.reg_desc_active = fep->hwp + offset_des_active_txq[i]; bd_dma += size; cbd_base = (struct bufdesc *)(((void *)cbd_base) + size); txq->bd.last = (struct bufdesc *)(((void *)cbd_base) - dsize); -- cgit From 80dc6a9f8e0dfb3f2c516273b2faa29c866974b2 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:48 -0700 Subject: net: fec: don't disable FEC_ENET_TS_TIMER interrupt Only the interrupt routine processes this condition. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec.h | 1 + drivers/net/ethernet/freescale/fec_main.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index bedd28a6e8f5..195122e11f10 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -375,6 +375,7 @@ struct bufdesc_ex { #define FEC_ENET_TS_TIMER ((uint)0x00008000) #define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER) +#define FEC_NAPI_IMASK (FEC_ENET_MII | FEC_ENET_TS_TIMER) #define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF)) /* ENET interrupt coalescing macro define */ diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 712e3bb1e0d3..ca2708d13dfe 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1553,7 +1553,7 @@ fec_enet_interrupt(int irq, void *dev_id) if (napi_schedule_prep(&fep->napi)) { /* Disable the NAPI interrupts */ - writel(FEC_ENET_MII, fep->hwp + FEC_IMASK); + writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK); __napi_schedule(&fep->napi); } } -- cgit From be293467b87c30cfdb24f74dcb225b693e436121 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:49 -0700 Subject: net: fec: don't transfer ownership until descriptor write is complete If you don't own it, you shouldn't write to it. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ca2708d13dfe..97ca72a6aaf4 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -390,6 +390,10 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, bdp->cbd_bufaddr = cpu_to_fec32(addr); bdp->cbd_datlen = cpu_to_fec16(frag_len); + /* Make sure the updates to rest of the descriptor are + * performed before transferring ownership. + */ + wmb(); bdp->cbd_sc = cpu_to_fec16(status); } @@ -499,6 +503,10 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, bdp->cbd_datlen = cpu_to_fec16(buflen); bdp->cbd_bufaddr = cpu_to_fec32(addr); + /* Make sure the updates to rest of the descriptor are performed before + * transferring ownership. + */ + wmb(); /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. @@ -1475,7 +1483,6 @@ rx_processing_done: /* Mark the buffer empty */ status |= BD_ENET_RX_EMPTY; - bdp->cbd_sc = cpu_to_fec16(status); if (fep->bufdesc_ex) { struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; @@ -1484,6 +1491,11 @@ rx_processing_done: ebdp->cbd_prot = 0; ebdp->cbd_bdu = 0; } + /* Make sure the updates to rest of the descriptor are + * performed before transferring ownership. + */ + wmb(); + bdp->cbd_sc = cpu_to_fec16(status); /* Update BD pointer to next entry */ bdp = fec_enet_get_nextdesc(bdp, &rxq->bd); -- cgit From fc75ba5159a63fad40442b9a9527a0f9b06de79b Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 5 Feb 2016 14:52:50 -0700 Subject: net: fec: improve error handling Unmap initial buffer on error. Don't free skb until it has been unmapped. Move cbd_bufaddr assignment closer to the mapping function. Signed-off-by: Troy Kisky Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/fec_main.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 97ca72a6aaf4..ef18ca501f9e 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -382,7 +382,6 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq, addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len, DMA_TO_DEVICE); if (dma_mapping_error(&fep->pdev->dev, addr)) { - dev_kfree_skb_any(skb); if (net_ratelimit()) netdev_err(ndev, "Tx DMA memory map failed\n"); goto dma_mapping_error; @@ -467,8 +466,12 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, if (nr_frags) { last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev); - if (IS_ERR(last_bdp)) + if (IS_ERR(last_bdp)) { + dma_unmap_single(&fep->pdev->dev, addr, + buflen, DMA_TO_DEVICE); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; + } } else { status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST); if (fep->bufdesc_ex) { @@ -478,6 +481,8 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, estatus |= BD_ENET_TX_TS; } } + bdp->cbd_bufaddr = cpu_to_fec32(addr); + bdp->cbd_datlen = cpu_to_fec16(buflen); if (fep->bufdesc_ex) { @@ -501,8 +506,6 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, /* Save skb pointer */ txq->tx_skbuff[index] = skb; - bdp->cbd_datlen = cpu_to_fec16(buflen); - bdp->cbd_bufaddr = cpu_to_fec32(addr); /* Make sure the updates to rest of the descriptor are performed before * transferring ownership. */ -- cgit From c3eea1942a16db52ebea0382bd5826f75b9b7e9b Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 10 Feb 2016 13:26:21 -0600 Subject: EDAC, altera: Add Altera L2 cache and OCRAM support Add L2 Cache and On-Chip RAM EDAC support for the Altera SoCs. The SDRAM controller is using the Memory Controller model. Each type of ECC is individually configurable. Signed-off-by: Thor Thayer Cc: devicetree@vger.kernel.org Cc: dinguyen@opensource.altera.com Cc: galak@codeaurora.org Cc: grant.likely@linaro.org Cc: ijc+devicetree@hellion.org.uk Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-doc@vger.kernel.org Cc: linux-edac Cc: mark.rutland@arm.com Cc: Mauro Carvalho Chehab Cc: pawel.moll@arm.com Cc: robh+dt@kernel.org Link: http://lkml.kernel.org/r/1455132384-17108-1-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- drivers/edac/Kconfig | 26 ++- drivers/edac/Makefile | 2 +- drivers/edac/altera_edac.c | 492 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 512 insertions(+), 8 deletions(-) diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index ef25000a5bc6..37755e63cc28 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -367,14 +367,30 @@ config EDAC_OCTEON_PCI Support for error detection and correction on the Cavium Octeon family of SOCs. -config EDAC_ALTERA_MC - bool "Altera SDRAM Memory Controller EDAC" +config EDAC_ALTERA + bool "Altera SOCFPGA ECC" depends on EDAC_MM_EDAC=y && ARCH_SOCFPGA help Support for error detection and correction on the - Altera SDRAM memory controller. Note that the - preloader must initialize the SDRAM before loading - the kernel. + Altera SOCs. This must be selected for SDRAM ECC. + Note that the preloader must initialize the SDRAM + before loading the kernel. + +config EDAC_ALTERA_L2C + bool "Altera L2 Cache ECC" + depends on EDAC_ALTERA=y + select 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. + +config EDAC_ALTERA_OCRAM + bool "Altera On-Chip RAM ECC" + depends on EDAC_ALTERA=y && SRAM && GENERIC_ALLOCATOR + help + Support for error detection and correction on the + Altera On-Chip RAM Memory for Altera SoCs. config EDAC_SYNOPSYS tristate "Synopsys DDR Memory Controller" diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index be163e20fe56..f9e4a3e0e6e9 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -67,6 +67,6 @@ obj-$(CONFIG_EDAC_OCTEON_L2C) += octeon_edac-l2c.o obj-$(CONFIG_EDAC_OCTEON_LMC) += octeon_edac-lmc.o obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o -obj-$(CONFIG_EDAC_ALTERA_MC) += altera_edac.o +obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index 929640981d8a..63e42098726d 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -1,5 +1,5 @@ /* - * Copyright Altera Corporation (C) 2014-2015. All rights reserved. + * Copyright Altera Corporation (C) 2014-2016. All rights reserved. * Copyright 2011-2012 Calxeda, Inc. * * This program is free software; you can redistribute it and/or modify it @@ -17,8 +17,10 @@ * Adapted from the highbank_mc_edac driver. */ +#include #include #include +#include #include #include #include @@ -34,6 +36,7 @@ #define EDAC_MOD_STR "altera_edac" #define EDAC_VERSION "1" +#define EDAC_DEVICE "Altera" static const struct altr_sdram_prv_data c5_data = { .ecc_ctrl_offset = CV_CTLCFG_OFST, @@ -75,6 +78,31 @@ 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. */ + static irqreturn_t altr_sdram_mc_err_handler(int irq, void *dev_id) { struct mem_ctl_info *mci = dev_id; @@ -504,6 +532,466 @@ static struct platform_driver altr_sdram_edac_driver = { module_platform_driver(altr_sdram_edac_driver); +/************************* EDAC Parent Probe *************************/ + +static const struct of_device_id altr_edac_device_of_match[]; + +static const struct of_device_id altr_edac_of_match[] = { + { .compatible = "altr,socfpga-ecc-manager" }, + {}, +}; +MODULE_DEVICE_TABLE(of, altr_edac_of_match); + +static int altr_edac_probe(struct platform_device *pdev) +{ + of_platform_populate(pdev->dev.of_node, altr_edac_device_of_match, + NULL, &pdev->dev); + return 0; +} + +static struct platform_driver altr_edac_driver = { + .probe = altr_edac_probe, + .driver = { + .name = "socfpga_ecc_manager", + .of_match_table = altr_edac_of_match, + }, +}; +module_platform_driver(altr_edac_driver); + +/************************* EDAC Device Functions *************************/ + +/* + * EDAC Device Functions (shared between various IPs). + * The discrete memories use the EDAC Device framework. The probe + * and error handling functions are very similar between memories + * so they are shared. The memory allocation and freeing for EDAC + * trigger testing are different for each memory. + */ + +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; + struct edac_device_ctl_info *dci = dev_id; + struct altr_edac_device_dev *drvdata = dci->pvt_info; + const struct edac_device_prv_data *priv = drvdata->data; + + if (irq == drvdata->sb_irq) { + if (priv->ce_clear_mask) + writel(priv->ce_clear_mask, drvdata->base); + edac_device_handle_ce(dci, 0, 0, drvdata->edac_dev_name); + ret_value = IRQ_HANDLED; + } else if (irq == drvdata->db_irq) { + if (priv->ue_clear_mask) + writel(priv->ue_clear_mask, drvdata->base); + edac_device_handle_ue(dci, 0, 0, drvdata->edac_dev_name); + panic("\nEDAC:ECC_DEVICE[Uncorrectable errors]\n"); + ret_value = IRQ_HANDLED; + } else { + WARN_ON(1); + } + + return ret_value; +} + +static ssize_t altr_edac_device_trig(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) + +{ + u32 *ptemp, i, error_mask; + int result = 0; + u8 trig_type; + unsigned long flags; + 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 *generic_ptr = edac_dci->dev; + + if (!user_buf || get_user(trig_type, user_buf)) + return -EFAULT; + + if (!priv->alloc_mem) + return -ENOMEM; + + /* + * Note that generic_ptr is initialized to the device * but in + * some alloc_functions, this is overridden and returns data. + */ + ptemp = priv->alloc_mem(priv->trig_alloc_sz, &generic_ptr); + if (!ptemp) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "Inject: Buffer Allocation error\n"); + return -ENOMEM; + } + + if (trig_type == ALTR_UE_TRIGGER_CHAR) + error_mask = priv->ue_set_mask; + else + error_mask = priv->ce_set_mask; + + edac_printk(KERN_ALERT, EDAC_DEVICE, + "Trigger Error Mask (0x%X)\n", error_mask); + + local_irq_save(flags); + /* write ECC corrupted data out. */ + for (i = 0; i < (priv->trig_alloc_sz / sizeof(*ptemp)); i++) { + /* Read data so we're in the correct state */ + rmb(); + 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); + ptemp[i] = i; + } + /* Ensure it has been written out */ + wmb(); + local_irq_restore(flags); + + if (result) + edac_printk(KERN_ERR, EDAC_DEVICE, "Mem Not Cleared\n"); + + /* Read out written data. ECC error caused here */ + for (i = 0; i < ALTR_TRIGGER_READ_WRD_CNT; i++) + if (ACCESS_ONCE(ptemp[i]) != i) + edac_printk(KERN_ERR, EDAC_DEVICE, + "Read doesn't match written data\n"); + + if (priv->free_mem) + priv->free_mem(ptemp, priv->trig_alloc_sz, generic_ptr); + + return count; +} + +static const struct file_operations altr_edac_device_inject_fops = { + .open = simple_open, + .write = altr_edac_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) +{ + struct altr_edac_device_dev *drvdata = edac_dci->pvt_info; + + if (!IS_ENABLED(CONFIG_EDAC_DEBUG)) + return; + + drvdata->debugfs_dir = edac_debugfs_create_dir(drvdata->edac_dev_name); + if (!drvdata->debugfs_dir) + return; + + if (!edac_debugfs_create_file(priv->dbgfs_name, S_IWUSR, + drvdata->debugfs_dir, edac_dci, + &altr_edac_device_inject_fops)) + debugfs_remove_recursive(drvdata->debugfs_dir); +} + +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 }, +#endif +#ifdef CONFIG_EDAC_ALTERA_OCRAM + { .compatible = "altr,socfpga-ocram-ecc", + .data = (void *)&ocramecc_data }, +#endif + {}, +}; +MODULE_DEVICE_TABLE(of, altr_edac_device_of_match); + +/* + * altr_edac_device_probe() + * This is a generic EDAC device driver that will support + * various Altera memory devices such as the L2 cache ECC and + * OCRAM ECC as well as the memories for other peripherals. + * Module specific initialization is done by passing the + * function index in the device tree. + */ +static int altr_edac_device_probe(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci; + struct altr_edac_device_dev *drvdata; + struct resource *r; + int res = 0; + struct device_node *np = pdev->dev.of_node; + char *ecc_name = (char *)np->name; + static int dev_instance; + + if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "Unable to open devm\n"); + return -ENOMEM; + } + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "Unable to get mem resource\n"); + res = -ENODEV; + goto fail; + } + + if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r), + dev_name(&pdev->dev))) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s:Error requesting mem region\n", ecc_name); + res = -EBUSY; + goto fail; + } + + dci = edac_device_alloc_ctl_info(sizeof(*drvdata), ecc_name, + 1, ecc_name, 1, 0, NULL, 0, + dev_instance++); + + if (!dci) { + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s: Unable to allocate EDAC device\n", ecc_name); + res = -ENOMEM; + goto fail; + } + + drvdata = dci->pvt_info; + dci->dev = &pdev->dev; + platform_set_drvdata(pdev, dci); + drvdata->edac_dev_name = ecc_name; + + drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); + if (!drvdata->base) + goto fail1; + + /* Get driver specific data for this EDAC device */ + drvdata->data = of_match_node(altr_edac_device_of_match, np)->data; + + /* Check specific dependencies for the module */ + if (drvdata->data->setup) { + res = drvdata->data->setup(pdev, drvdata->base); + if (res) + goto fail1; + } + + drvdata->sb_irq = platform_get_irq(pdev, 0); + res = devm_request_irq(&pdev->dev, drvdata->sb_irq, + altr_edac_device_handler, + 0, dev_name(&pdev->dev), dci); + if (res) + goto fail1; + + drvdata->db_irq = platform_get_irq(pdev, 1); + res = devm_request_irq(&pdev->dev, drvdata->db_irq, + altr_edac_device_handler, + 0, dev_name(&pdev->dev), dci); + if (res) + goto fail1; + + dci->mod_name = "Altera ECC Manager"; + dci->dev_name = drvdata->edac_dev_name; + + res = edac_device_add_device(dci); + if (res) + goto fail1; + + altr_create_edacdev_dbgfs(dci, drvdata->data); + + devres_close_group(&pdev->dev, NULL); + + return 0; + +fail1: + edac_device_free_ctl_info(dci); +fail: + devres_release_group(&pdev->dev, NULL); + edac_printk(KERN_ERR, EDAC_DEVICE, + "%s:Error setting up EDAC device: %d\n", ecc_name, res); + + return res; +} + +static int altr_edac_device_remove(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); + struct altr_edac_device_dev *drvdata = dci->pvt_info; + + debugfs_remove_recursive(drvdata->debugfs_dir); + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(dci); + + return 0; +} + +static struct platform_driver altr_edac_device_driver = { + .probe = altr_edac_device_probe, + .remove = altr_edac_device_remove, + .driver = { + .name = "altr_edac_device", + .of_match_table = altr_edac_device_of_match, + }, +}; +module_platform_driver(altr_edac_device_driver); + +/*********************** OCRAM EDAC Device Functions *********************/ + +#ifdef CONFIG_EDAC_ALTERA_OCRAM + +static void *ocram_alloc_mem(size_t size, void **other) +{ + struct device_node *np; + struct gen_pool *gp; + void *sram_addr; + + np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc"); + if (!np) + return NULL; + + gp = of_gen_pool_get(np, "iram", 0); + of_node_put(np); + if (!gp) + return NULL; + + sram_addr = (void *)gen_pool_alloc(gp, size); + if (!sram_addr) + return NULL; + + memset(sram_addr, 0, size); + /* Ensure data is written out */ + wmb(); + + /* Remember this handle for freeing later */ + *other = gp; + + return sram_addr; +} + +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 platform_device *pdev, + void __iomem *base) +{ + if (readl(base) & ALTR_OCR_ECC_EN) + 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, + .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", + .alloc_mem = ocram_alloc_mem, + .free_mem = ocram_free_mem, + .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), + .trig_alloc_sz = ALTR_TRIG_OCRAM_BYTE_SIZE, +}; + +#endif /* CONFIG_EDAC_ALTERA_OCRAM */ + +/********************* L2 Cache EDAC Device Functions ********************/ + +#ifdef CONFIG_EDAC_ALTERA_L2C + +static void *l2_alloc_mem(size_t size, void **other) +{ + struct device *dev = *other; + void *ptemp = devm_kzalloc(dev, size, GFP_KERNEL); + + if (!ptemp) + return NULL; + + /* Make sure everything is written out */ + wmb(); + + /* + * Clean all cache levels up to LoC (includes L2) + * This ensures the corrupted data is written into + * L2 cache for readback test (which causes ECC error). + */ + flush_cache_all(); + + return ptemp; +} + +static void l2_free_mem(void *p, size_t size, void *other) +{ + struct device *dev = other; + + if (dev && p) + devm_kfree(dev, p); +} + +/* + * altr_l2_check_deps() + * Test for L2 cache ECC dependencies upon entry because + * platform specific startup should have initialized the L2 + * memory and enabled the ECC. + * 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) +{ + if (readl(base) & ALTR_L2_ECC_EN) + return 0; + + edac_printk(KERN_ERR, EDAC_DEVICE, + "L2: No ECC present, or ECC disabled\n"); + return -ENODEV; +} + +const struct edac_device_prv_data l2ecc_data = { + .setup = altr_l2_check_deps, + .ce_clear_mask = 0, + .ue_clear_mask = 0, + .dbgfs_name = "altr_l2_trigger", + .alloc_mem = l2_alloc_mem, + .free_mem = l2_free_mem, + .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), + .trig_alloc_sz = ALTR_TRIG_L2C_BYTE_SIZE, +}; + +#endif /* CONFIG_EDAC_ALTERA_L2C */ + MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Thor Thayer"); -MODULE_DESCRIPTION("EDAC Driver for Altera SDRAM Controller"); +MODULE_DESCRIPTION("EDAC Driver for Altera Memories"); -- cgit From c366c76a2c41d0c545e51b53056b21515db32e77 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Sat, 30 Jan 2016 17:06:44 +0000 Subject: gpio: add tps65218 gpio Driver for the GPIO block found in ti's tps65218 pmics. The device has two GPIOs and one GPO pin which can be configured as follows: GPIO1: -general-purpose, open-drain output controlled by GPO1 user bit and/or sequencer -DDR3 reset input signal from SOC. Signal is either latched or passed-trough to GPO2 pin. See below for details. GPO2: -general-purpose output controlled by GPO2 user bit -DDR3 reset output signal. Signal is controlled by GPIO1 and PGOOD. See below for details. -Output buffer can be configured as open-drain or push-pull. GPIO3: -general-purpose, open-drain output controlled by GPO3 user bit and/or sequencer -reset input-signal for DCDC1 and DCDC2. The input configurations are not meant to be used by the user so the driver only offers GPOs. v2: Added request routine that evaluates the fw config flags and removed module owner v3: Added .direction_input() routine, and took care of all Linus Walleij suggestions (clamp to bool, use proper include) Signed-off-by: Nicolas Saenz Julienne Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 7 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-tps65218.c | 223 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 drivers/gpio/gpio-tps65218.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 63cf6097ec81..ad226485a8e4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -889,6 +889,13 @@ config GPIO_TIMBERDALE ---help--- Add support for the GPIO IP in the timberdale FPGA. +config GPIO_TPS65218 + tristate "TPS65218 GPIO" + depends on MFD_TPS65218 + help + Select this option to enable GPIO driver for the TPS65218 + chip family. + config GPIO_TPS6586X bool "TPS6586X GPIO" depends on MFD_TPS6586X diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 8d4960390f0d..f1d3d823d1bc 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -98,6 +98,7 @@ obj-$(CONFIG_ARCH_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 +obj-$(CONFIG_GPIO_TPS65218) += gpio-tps65218.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c new file mode 100644 index 000000000000..7b02f7be9bc9 --- /dev/null +++ b/drivers/gpio/gpio-tps65218.c @@ -0,0 +1,223 @@ +/* + * Copyright 2015 Verifone Int. + * + * Author: Nicolas Saenz Julienne + * + * This program is free software; you can redistribute it and/or modify i t + * under the terms of the GNU General Public License as published by th e + * Free Software Foundation; either version 2 of the License, or (at you r + * option) any later version. + * + * This driver is based on the gpio-tps65912 implementation. + */ + +#include +#include +#include +#include +#include +#include +#include "gpiolib.h" + +struct tps65218_gpio { + struct tps65218 *tps65218; + struct gpio_chip gpio_chip; +}; + +static int tps65218_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc); + struct tps65218 *tps65218 = tps65218_gpio->tps65218; + unsigned int val; + int ret; + + ret = tps65218_reg_read(tps65218, TPS65218_REG_ENABLE2, &val); + if (ret) + return ret; + + return !!(val & (TPS65218_ENABLE2_GPIO1 << offset)); +} + +static void tps65218_gpio_set(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc); + struct tps65218 *tps65218 = tps65218_gpio->tps65218; + + if (value) + tps65218_set_bits(tps65218, TPS65218_REG_ENABLE2, + TPS65218_ENABLE2_GPIO1 << offset, + TPS65218_ENABLE2_GPIO1 << offset, + TPS65218_PROTECT_L1); + else + tps65218_clear_bits(tps65218, TPS65218_REG_ENABLE2, + TPS65218_ENABLE2_GPIO1 << offset, + TPS65218_PROTECT_L1); +} + +static int tps65218_gpio_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + /* Only drives GPOs */ + return 0; +} + +static int tps65218_gpio_input(struct gpio_chip *gc, unsigned offset) +{ + return -EPERM; +} + +static int tps65218_gpio_request(struct gpio_chip *gc, unsigned offset) +{ + struct tps65218_gpio *tps65218_gpio = gpiochip_get_data(gc); + struct tps65218 *tps65218 = tps65218_gpio->tps65218; + unsigned long flags = gc->desc[offset].flags; + int ret; + + if (flags & FLAG_OPEN_SOURCE) { + dev_err(gc->parent, "can't work as open source\n"); + return -EINVAL; + } + + switch (offset) { + case 0: + if (!(flags & FLAG_OPEN_DRAIN)) { + dev_err(gc->parent, "GPO1 works only as open drain\n"); + return -EINVAL; + } + + /* Disable sequencer for GPO1 */ + ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7, + TPS65218_SEQ7_GPO1_SEQ_MASK, + TPS65218_PROTECT_L1); + if (ret) + return ret; + + /* Setup GPO1 */ + ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG1, + TPS65218_CONFIG1_IO1_SEL, + TPS65218_PROTECT_L1); + if (ret) + return ret; + + break; + case 1: + /* GP02 is push-pull by default, can be set as open drain. */ + if (flags & FLAG_OPEN_DRAIN) { + 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, + TPS65218_PROTECT_L1); + if (ret) + return ret; + + break; + + case 2: + if (!(flags & FLAG_OPEN_DRAIN)) { + dev_err(gc->parent, "GPO3 works only as open drain\n"); + return -EINVAL; + } + + /* Disable sequencer for GPO3 */ + ret = tps65218_clear_bits(tps65218, TPS65218_REG_SEQ7, + TPS65218_SEQ7_GPO3_SEQ_MASK, + TPS65218_PROTECT_L1); + if (ret) + return ret; + + /* Setup GPO3 */ + ret = tps65218_clear_bits(tps65218, TPS65218_REG_CONFIG2, + TPS65218_CONFIG2_DC12_RST, + TPS65218_PROTECT_L1); + if (ret) + return ret; + + break; + default: + return -EINVAL; + } + + return 0; +} + +static struct gpio_chip template_chip = { + .label = "gpio-tps65218", + .owner = THIS_MODULE, + .request = tps65218_gpio_request, + .direction_output = tps65218_gpio_output, + .direction_input = tps65218_gpio_input, + .get = tps65218_gpio_get, + .set = tps65218_gpio_set, + .can_sleep = true, + .ngpio = 3, + .base = -1, +}; + +static int tps65218_gpio_probe(struct platform_device *pdev) +{ + struct tps65218 *tps65218 = dev_get_drvdata(pdev->dev.parent); + struct tps65218_gpio *tps65218_gpio; + int ret; + + tps65218_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65218_gpio), + GFP_KERNEL); + if (!tps65218_gpio) + return -ENOMEM; + + tps65218_gpio->tps65218 = tps65218; + tps65218_gpio->gpio_chip = template_chip; + tps65218_gpio->gpio_chip.parent = &pdev->dev; +#ifdef CONFIG_OF_GPIO + tps65218_gpio->gpio_chip.of_node = pdev->dev.of_node; +#endif + + ret = gpiochip_add_data(&tps65218_gpio->gpio_chip, tps65218_gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, tps65218_gpio); + + return ret; +} + +static int tps65218_gpio_remove(struct platform_device *pdev) +{ + struct tps65218_gpio *tps65218_gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&tps65218_gpio->gpio_chip); + + return 0; +} + +static const struct of_device_id tps65218_dt_match[] = { + { .compatible = "ti,tps65218-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, tps65218_dt_match); + +static struct platform_driver tps65218_gpio_driver = { + .driver = { + .name = "tps65218-gpio", + .of_match_table = of_match_ptr(tps65218_dt_match) + }, + .probe = tps65218_gpio_probe, + .remove = tps65218_gpio_remove, +}; + +module_platform_driver(tps65218_gpio_driver); + +MODULE_AUTHOR("Nicolas Saenz Julienne "); +MODULE_DESCRIPTION("GPO interface for TPS65218 PMICs"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:tps65218-gpio"); -- cgit From d31e2e846b35370a2317a211a50d8248d46fc83b Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 10 Feb 2016 13:26:22 -0600 Subject: ARM: dts: Add Altera L2 Cache and OCRAM EDAC entries Add the device tree entries and bindings needed to support the Altera L2 cache and On-Chip RAM EDAC. This patch relies upon an earlier patch to declare and setup On-chip RAM properly: 8b907c8b62ac ("arm: dts: socfpga: Add OCRAM node") Signed-off-by: Thor Thayer Acked-by: Rob Herring Cc: devicetree@vger.kernel.org Cc: Dinh Nguyen Cc: galak@codeaurora.org Cc: grant.likely@linaro.org Cc: Ian Campbell Cc: ijc+devicetree@hellion.org.uk Cc: Kumar Gala Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-doc@vger.kernel.org Cc: linux-edac Cc: Mark Rutland Cc: m.chehab@samsung.com Cc: Pawel Moll Cc: Rob Herring Cc: Russell King Link: http://lkml.kernel.org/r/1455132384-17108-2-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- .../bindings/arm/altera/socfpga-eccmgr.txt | 49 ++++++++++++++++++++++ arch/arm/boot/dts/socfpga.dtsi | 20 +++++++++ 2 files changed, 69 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt diff --git a/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt new file mode 100644 index 000000000000..885f93d14ef9 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/altera/socfpga-eccmgr.txt @@ -0,0 +1,49 @@ +Altera SoCFPGA ECC Manager +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. + +Required Properties: +- compatible : Should be "altr,socfpga-ecc-manager" +- #address-cells: must be 1 +- #size-cells: must be 1 +- ranges : standard definition, should translate from local addresses + +Subcomponents: + +L2 Cache ECC +Required Properties: +- compatible : Should be "altr,socfpga-l2-ecc" +- reg : Address and size for ECC error interrupt clear registers. +- interrupts : Should be single bit error interrupt, then double bit error + interrupt. Note the rising edge type. + +On Chip RAM ECC +Required Properties: +- compatible : Should be "altr,socfpga-ocram-ecc" +- reg : Address and size for ECC error interrupt clear registers. +- iram : phandle to On-Chip RAM definition. +- interrupts : Should be single bit error interrupt, then double bit error + interrupt. Note the rising edge type. + +Example: + + eccmgr: eccmgr@ffd08140 { + compatible = "altr,socfpga-ecc-manager"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + l2-ecc@ffd08140 { + compatible = "altr,socfpga-l2-ecc"; + reg = <0xffd08140 0x4>; + interrupts = <0 36 1>, <0 37 1>; + }; + + ocram-ecc@ffd08144 { + compatible = "altr,socfpga-ocram-ecc"; + reg = <0xffd08144 0x4>; + iram = <&ocram>; + interrupts = <0 178 1>, <0 179 1>; + }; + }; diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi index 3ed4abdaaa9c..15cbc747c242 100644 --- a/arch/arm/boot/dts/socfpga.dtsi +++ b/arch/arm/boot/dts/socfpga.dtsi @@ -656,6 +656,26 @@ status = "disabled"; }; + eccmgr: eccmgr@ffd08140 { + compatible = "altr,socfpga-ecc-manager"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + l2-ecc@ffd08140 { + compatible = "altr,socfpga-l2-ecc"; + reg = <0xffd08140 0x4>; + interrupts = <0 36 1>, <0 37 1>; + }; + + ocram-ecc@ffd08144 { + compatible = "altr,socfpga-ocram-ecc"; + reg = <0xffd08144 0x4>; + iram = <&ocram>; + interrupts = <0 178 1>, <0 179 1>; + }; + }; + L2: l2-cache@fffef000 { compatible = "arm,pl310-cache"; reg = <0xfffef000 0x1000>; -- cgit From 4d1138380ed6f1cca622e7de8bcc877c04a52d0d Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 10 Feb 2016 13:26:23 -0600 Subject: ARM: socfpga: Enable L2 cache ECC on startup Enable ECC for L2 cache on machine startup. The ECC has to be enabled 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: galak@codeaurora.org Cc: grant.likely@linaro.org Cc: ijc+devicetree@hellion.org.uk Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-doc@vger.kernel.org Cc: linux-edac Cc: mark.rutland@arm.com Cc: m.chehab@samsung.com Cc: pawel.moll@arm.com Cc: robh+dt@kernel.org Cc: Russell King Link: http://lkml.kernel.org/r/1455132384-17108-3-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- arch/arm/mach-socfpga/Makefile | 1 + arch/arm/mach-socfpga/core.h | 1 + arch/arm/mach-socfpga/l2_cache.c | 41 ++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-socfpga/socfpga.c | 2 ++ 4 files changed, 45 insertions(+) create mode 100644 arch/arm/mach-socfpga/l2_cache.c diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index b8f9e238e4ab..e9ab7c9444ff 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -5,3 +5,4 @@ obj-y := socfpga.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o obj-$(CONFIG_SOCFPGA_SUSPEND) += pm.o self-refresh.o +obj-$(CONFIG_EDAC_ALTERA_L2C) += l2_cache.o diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index 5bc6ea87cdf7..eb55d66a0eac 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -36,6 +36,7 @@ extern void socfpga_init_clocks(void); extern void socfpga_sysmgr_init(void); +void socfpga_init_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 new file mode 100644 index 000000000000..e3907ab58d05 --- /dev/null +++ b/arch/arm/mach-socfpga/l2_cache.c @@ -0,0 +1,41 @@ +/* + * Copyright Altera Corporation (C) 2016. All rights reserved. + * + * 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 + +void socfpga_init_l2_ecc(void) +{ + struct device_node *np; + void __iomem *mapped_l2_edac_addr; + + np = of_find_compatible_node(NULL, NULL, "altr,socfpga-l2-ecc"); + if (!np) { + pr_err("Unable to find socfpga-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; + } + + /* Enable ECC */ + writel(0x01, mapped_l2_edac_addr); + iounmap(mapped_l2_edac_addr); +} diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index a1c0efaa8794..dd1ff07b0472 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -59,6 +59,8 @@ static void __init socfpga_init_irq(void) { irqchip_init(); socfpga_sysmgr_init(); + if (IS_ENABLED(CONFIG_EDAC_ALTERA_L2C)) + socfpga_init_l2_ecc(); } static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) -- cgit From 7cc5a5d3cd4cca0a3852d1500e8c50fe191bcc9d Mon Sep 17 00:00:00 2001 From: Thor Thayer Date: Wed, 10 Feb 2016 13:26:24 -0600 Subject: ARM: socfpga: Enable OCRAM ECC on startup Enable ECC for On-Chip RAM on machine startup. The ECC has to be enabled 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: dougthompson@xmission.com Cc: galak@codeaurora.org Cc: grant.likely@linaro.org Cc: ijc+devicetree@hellion.org.uk Cc: linux-arm-kernel@lists.infradead.org Cc: linux@arm.linux.org.uk Cc: linux-doc@vger.kernel.org Cc: linux-edac Cc: mark.rutland@arm.com Cc: m.chehab@samsung.com Cc: pawel.moll@arm.com Cc: robh+dt@kernel.org Cc: Russell King Cc: tthayer.linux@gmail.com Cc: tthayer@opensource.altera.com Link: http://lkml.kernel.org/r/1455132384-17108-4-git-send-email-tthayer@opensource.altera.com Signed-off-by: Borislav Petkov --- arch/arm/mach-socfpga/Makefile | 1 + arch/arm/mach-socfpga/core.h | 1 + arch/arm/mach-socfpga/ocram.c | 49 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-socfpga/socfpga.c | 3 +++ 4 files changed, 54 insertions(+) create mode 100644 arch/arm/mach-socfpga/ocram.c diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index e9ab7c9444ff..ed15db19e561 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -6,3 +6,4 @@ obj-y := socfpga.o obj-$(CONFIG_SMP) += headsmp.o platsmp.o obj-$(CONFIG_SOCFPGA_SUSPEND) += pm.o self-refresh.o obj-$(CONFIG_EDAC_ALTERA_L2C) += l2_cache.o +obj-$(CONFIG_EDAC_ALTERA_OCRAM) += ocram.o diff --git a/arch/arm/mach-socfpga/core.h b/arch/arm/mach-socfpga/core.h index eb55d66a0eac..575195be6687 100644 --- a/arch/arm/mach-socfpga/core.h +++ b/arch/arm/mach-socfpga/core.h @@ -37,6 +37,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); extern void __iomem *sys_manager_base_addr; extern void __iomem *rst_manager_base_addr; diff --git a/arch/arm/mach-socfpga/ocram.c b/arch/arm/mach-socfpga/ocram.c new file mode 100644 index 000000000000..60ec643ac2be --- /dev/null +++ b/arch/arm/mach-socfpga/ocram.c @@ -0,0 +1,49 @@ +/* + * Copyright Altera Corporation (C) 2016. All rights reserved. + * + * 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 + +#define ALTR_OCRAM_CLEAR_ECC 0x00000018 +#define ALTR_OCRAM_ECC_EN 0x00000019 + +void socfpga_init_ocram_ecc(void) +{ + struct device_node *np; + void __iomem *mapped_ocr_edac_addr; + + /* Find the OCRAM EDAC device tree node */ + np = of_find_compatible_node(NULL, NULL, "altr,socfpga-ocram-ecc"); + if (!np) { + pr_err("Unable to find socfpga-ocram-ecc\n"); + return; + } + + mapped_ocr_edac_addr = of_iomap(np, 0); + of_node_put(np); + if (!mapped_ocr_edac_addr) { + pr_err("Unable to map OCRAM ecc regs.\n"); + return; + } + + /* Clear any pending OCRAM ECC interrupts, then enable ECC */ + writel(ALTR_OCRAM_CLEAR_ECC, mapped_ocr_edac_addr); + writel(ALTR_OCRAM_ECC_EN, mapped_ocr_edac_addr); + + iounmap(mapped_ocr_edac_addr); +} diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index dd1ff07b0472..7e0aad2ec3d1 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -61,6 +61,9 @@ static void __init socfpga_init_irq(void) socfpga_sysmgr_init(); if (IS_ENABLED(CONFIG_EDAC_ALTERA_L2C)) socfpga_init_l2_ecc(); + + if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM)) + socfpga_init_ocram_ecc(); } static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd) -- cgit From 9d3053ef57599025b93aab76324ae42c60d0bac2 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Fri, 5 Feb 2016 11:43:28 +0530 Subject: iw_cxgb4: make queue allocation code more readable Rename local mm* variables to more meaningful names Signed-off-by: Steve Wise Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/infiniband/hw/cxgb4/qp.c | 81 +++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index e99345eb875a..dadf5f1855b3 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1621,7 +1621,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, unsigned int sqsize, rqsize; struct c4iw_ucontext *ucontext; int ret; - struct c4iw_mm_entry *mm1, *mm2, *mm3, *mm4, *mm5 = NULL; + struct c4iw_mm_entry *sq_key_mm, *rq_key_mm = NULL, *sq_db_key_mm; + struct c4iw_mm_entry *rq_db_key_mm = NULL, *ma_sync_key_mm = NULL; PDBG("%s ib_pd %p\n", __func__, pd); @@ -1706,29 +1707,30 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, goto err2; if (udata) { - mm1 = kmalloc(sizeof *mm1, GFP_KERNEL); - if (!mm1) { + sq_key_mm = kmalloc(sizeof(*sq_key_mm), GFP_KERNEL); + if (!sq_key_mm) { ret = -ENOMEM; goto err3; } - mm2 = kmalloc(sizeof *mm2, GFP_KERNEL); - if (!mm2) { + rq_key_mm = kmalloc(sizeof(*rq_key_mm), GFP_KERNEL); + if (!rq_key_mm) { ret = -ENOMEM; goto err4; } - mm3 = kmalloc(sizeof *mm3, GFP_KERNEL); - if (!mm3) { + sq_db_key_mm = kmalloc(sizeof(*sq_db_key_mm), GFP_KERNEL); + if (!sq_db_key_mm) { ret = -ENOMEM; goto err5; } - mm4 = kmalloc(sizeof *mm4, GFP_KERNEL); - if (!mm4) { + rq_db_key_mm = kmalloc(sizeof(*rq_db_key_mm), GFP_KERNEL); + if (!rq_db_key_mm) { ret = -ENOMEM; goto err6; } if (t4_sq_onchip(&qhp->wq.sq)) { - mm5 = kmalloc(sizeof *mm5, GFP_KERNEL); - if (!mm5) { + ma_sync_key_mm = kmalloc(sizeof(*ma_sync_key_mm), + GFP_KERNEL); + if (!ma_sync_key_mm) { ret = -ENOMEM; goto err7; } @@ -1743,7 +1745,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, uresp.rq_size = qhp->wq.rq.size; uresp.rq_memsize = qhp->wq.rq.memsize; spin_lock(&ucontext->mmap_lock); - if (mm5) { + if (ma_sync_key_mm) { uresp.ma_sync_key = ucontext->key; ucontext->key += PAGE_SIZE; } else { @@ -1761,28 +1763,29 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, ret = ib_copy_to_udata(udata, &uresp, sizeof uresp); if (ret) goto err8; - mm1->key = uresp.sq_key; - mm1->addr = qhp->wq.sq.phys_addr; - mm1->len = PAGE_ALIGN(qhp->wq.sq.memsize); - insert_mmap(ucontext, mm1); - mm2->key = uresp.rq_key; - mm2->addr = virt_to_phys(qhp->wq.rq.queue); - mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize); - insert_mmap(ucontext, mm2); - mm3->key = uresp.sq_db_gts_key; - mm3->addr = (__force unsigned long)qhp->wq.sq.bar2_pa; - mm3->len = PAGE_SIZE; - insert_mmap(ucontext, mm3); - mm4->key = uresp.rq_db_gts_key; - mm4->addr = (__force unsigned long)qhp->wq.rq.bar2_pa; - mm4->len = PAGE_SIZE; - insert_mmap(ucontext, mm4); - if (mm5) { - mm5->key = uresp.ma_sync_key; - mm5->addr = (pci_resource_start(rhp->rdev.lldi.pdev, 0) - + PCIE_MA_SYNC_A) & PAGE_MASK; - mm5->len = PAGE_SIZE; - insert_mmap(ucontext, mm5); + sq_key_mm->key = uresp.sq_key; + sq_key_mm->addr = qhp->wq.sq.phys_addr; + sq_key_mm->len = PAGE_ALIGN(qhp->wq.sq.memsize); + insert_mmap(ucontext, sq_key_mm); + rq_key_mm->key = uresp.rq_key; + rq_key_mm->addr = virt_to_phys(qhp->wq.rq.queue); + rq_key_mm->len = PAGE_ALIGN(qhp->wq.rq.memsize); + insert_mmap(ucontext, rq_key_mm); + sq_db_key_mm->key = uresp.sq_db_gts_key; + sq_db_key_mm->addr = (u64)(unsigned long)qhp->wq.sq.bar2_pa; + sq_db_key_mm->len = PAGE_SIZE; + insert_mmap(ucontext, sq_db_key_mm); + rq_db_key_mm->key = uresp.rq_db_gts_key; + rq_db_key_mm->addr = (u64)(unsigned long)qhp->wq.rq.bar2_pa; + rq_db_key_mm->len = PAGE_SIZE; + insert_mmap(ucontext, rq_db_key_mm); + if (ma_sync_key_mm) { + ma_sync_key_mm->key = uresp.ma_sync_key; + ma_sync_key_mm->addr = + (pci_resource_start(rhp->rdev.lldi.pdev, 0) + + PCIE_MA_SYNC_A) & PAGE_MASK; + ma_sync_key_mm->len = PAGE_SIZE; + insert_mmap(ucontext, ma_sync_key_mm); } } qhp->ibqp.qp_num = qhp->wq.sq.qid; @@ -1795,15 +1798,15 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, qhp->wq.rq.memsize, attrs->cap.max_recv_wr); return &qhp->ibqp; err8: - kfree(mm5); + kfree(ma_sync_key_mm); err7: - kfree(mm4); + kfree(rq_db_key_mm); err6: - kfree(mm3); + kfree(sq_db_key_mm); err5: - kfree(mm2); + kfree(rq_key_mm); err4: - kfree(mm1); + kfree(sq_key_mm); err3: remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid); err2: -- cgit From 6102c66eeb7497e4462c896074315635807758d4 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Fri, 5 Feb 2016 11:43:29 +0530 Subject: iw_cxgb4: remove false error log entry Don't log errors if a listening endpoint is going away when procesing a PASS_ACCEPT_REQ message. This can happen. Change the error printk to a PDBG() debug log entry Signed-off-by: Steve Wise Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/infiniband/hw/cxgb4/cm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index cd2ff5f9518a..0c2111b5b2e4 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -2399,8 +2399,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) } if (state_read(&parent_ep->com) != LISTEN) { - printk(KERN_ERR "%s - listening ep not in LISTEN\n", - __func__); + PDBG("%s - listening ep not in LISTEN\n", __func__); goto reject; } -- cgit From ba9cee6aa67dd67ad1bf121ee20efc00241f086f Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Fri, 5 Feb 2016 11:43:30 +0530 Subject: cxgb4/iw_cxgb4: TOS support This series provides support for iWARP applications to specify a TOS value and have that map to a VLAN Priority for iw_cxgb4 iWARP connections. In iw_cxgb4, when allocating an L2T entry, pass the skb_priority based on the tos value in the cm_id. Also pass the correct tos value during connection setup so the passive side gets the client's desired tos. When sending the FLOWC work request to FW, if the egress device is in a vlan, then use the vlan priority bits as the scheduling class. This allows associating RDMA connections with scheduling classes to provide traffic shaping per flow. Signed-off-by: Steve Wise Signed-off-by: Hariprasad Shenai Signed-off-by: David S. Miller --- drivers/infiniband/hw/cxgb4/cm.c | 51 ++++++++++++++++++--------- drivers/net/ethernet/chelsio/cxgb4/t4_msg.h | 2 ++ drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 1 + 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 0c2111b5b2e4..8cd7b5e4b03d 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -485,12 +485,19 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) unsigned int flowclen = 80; struct fw_flowc_wr *flowc; int i; + u16 vlan = ep->l2t->vlan; + int nparams; + + if (vlan == CPL_L2T_VLAN_NONE) + nparams = 8; + else + nparams = 9; skb = get_skb(skb, flowclen, GFP_KERNEL); flowc = (struct fw_flowc_wr *)__skb_put(skb, flowclen); flowc->op_to_nparams = cpu_to_be32(FW_WR_OP_V(FW_FLOWC_WR) | - FW_FLOWC_WR_NPARAMS_V(8)); + FW_FLOWC_WR_NPARAMS_V(nparams)); flowc->flowid_len16 = cpu_to_be32(FW_WR_LEN16_V(DIV_ROUND_UP(flowclen, 16)) | FW_WR_FLOWID_V(ep->hwtid)); @@ -511,9 +518,17 @@ static void send_flowc(struct c4iw_ep *ep, struct sk_buff *skb) flowc->mnemval[6].val = cpu_to_be32(ep->snd_win); flowc->mnemval[7].mnemonic = FW_FLOWC_MNEM_MSS; flowc->mnemval[7].val = cpu_to_be32(ep->emss); - /* Pad WR to 16 byte boundary */ - flowc->mnemval[8].mnemonic = 0; - flowc->mnemval[8].val = 0; + if (nparams == 9) { + u16 pri; + + pri = (vlan & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; + flowc->mnemval[8].mnemonic = FW_FLOWC_MNEM_SCHEDCLASS; + flowc->mnemval[8].val = cpu_to_be32(pri); + } else { + /* Pad WR to 16 byte boundary */ + flowc->mnemval[8].mnemonic = 0; + flowc->mnemval[8].val = 0; + } for (i = 0; i < 9; i++) { flowc->mnemval[i].r4[0] = 0; flowc->mnemval[i].r4[1] = 0; @@ -710,7 +725,7 @@ static int send_connect(struct c4iw_ep *ep) L2T_IDX_V(ep->l2t->idx) | TX_CHAN_V(ep->tx_chan) | SMAC_SEL_V(ep->smac_idx) | - DSCP_V(ep->tos) | + DSCP_V(ep->tos >> 2) | ULP_MODE_V(ULP_MODE_TCPDDP) | RCV_BUFSIZ_V(win); opt2 = RX_CHANNEL_V(0) | @@ -1864,7 +1879,7 @@ static void send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) L2T_IDX_V(ep->l2t->idx) | TX_CHAN_V(ep->tx_chan) | SMAC_SEL_V(ep->smac_idx) | - DSCP_V(ep->tos) | + DSCP_V(ep->tos >> 2) | ULP_MODE_V(ULP_MODE_TCPDDP) | RCV_BUFSIZ_V(win)); req->tcb.opt2 = (__force __be32) (PACE_V(1) | @@ -1928,7 +1943,7 @@ static void set_tcp_window(struct c4iw_ep *ep, struct port_info *pi) static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, struct dst_entry *dst, struct c4iw_dev *cdev, - bool clear_mpa_v1, enum chip_type adapter_type) + bool clear_mpa_v1, enum chip_type adapter_type, u8 tos) { struct neighbour *n; int err, step; @@ -1958,7 +1973,7 @@ static int import_ep(struct c4iw_ep *ep, int iptype, __u8 *peer_ip, goto out; } ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t, - n, pdev, 0); + n, pdev, rt_tos2priority(tos)); if (!ep->l2t) goto out; ep->mtu = pdev->mtu; @@ -2041,7 +2056,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep) if (ep->com.cm_id->local_addr.ss_family == AF_INET) { ep->dst = find_route(ep->com.dev, laddr->sin_addr.s_addr, raddr->sin_addr.s_addr, laddr->sin_port, - raddr->sin_port, 0); + raddr->sin_port, ep->com.cm_id->tos); iptype = 4; ra = (__u8 *)&raddr->sin_addr; } else { @@ -2058,7 +2073,8 @@ static int c4iw_reconnect(struct c4iw_ep *ep) goto fail3; } err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, false, - ep->com.dev->rdev.lldi.adapter_type); + ep->com.dev->rdev.lldi.adapter_type, + ep->com.cm_id->tos); if (err) { pr_err("%s - cannot alloc l2e.\n", __func__); goto fail4; @@ -2069,7 +2085,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep) ep->l2t->idx); state_set(&ep->com, CONNECTING); - ep->tos = 0; + ep->tos = ep->com.cm_id->tos; /* send connect request to rnic */ err = send_connect(ep); @@ -2391,6 +2407,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) u16 peer_mss = ntohs(req->tcpopt.mss); int iptype; unsigned short hdrs; + u8 tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); parent_ep = lookup_stid(t, stid); if (!parent_ep) { @@ -2414,7 +2431,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) ntohs(peer_port), peer_mss); dst = find_route(dev, *(__be32 *)local_ip, *(__be32 *)peer_ip, local_port, peer_port, - PASS_OPEN_TOS_G(ntohl(req->tos_stid))); + tos); } else { PDBG("%s parent ep %p hwtid %u laddr %pI6 raddr %pI6 lport %d rport %d peer_mss %d\n" , __func__, parent_ep, hwtid, @@ -2440,7 +2457,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) } err = import_ep(child_ep, iptype, peer_ip, dst, dev, false, - parent_ep->com.dev->rdev.lldi.adapter_type); + parent_ep->com.dev->rdev.lldi.adapter_type, tos); if (err) { printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", __func__); @@ -2508,7 +2525,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) c4iw_get_ep(&parent_ep->com); child_ep->parent_ep = parent_ep; - child_ep->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid)); + child_ep->tos = tos; child_ep->dst = dst; child_ep->hwtid = hwtid; @@ -3202,7 +3219,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ra, ntohs(raddr->sin_port)); ep->dst = find_route(dev, laddr->sin_addr.s_addr, raddr->sin_addr.s_addr, laddr->sin_port, - raddr->sin_port, 0); + raddr->sin_port, cm_id->tos); } else { iptype = 6; ra = (__u8 *)&raddr6->sin6_addr; @@ -3233,7 +3250,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) } err = import_ep(ep, iptype, ra, ep->dst, ep->com.dev, true, - ep->com.dev->rdev.lldi.adapter_type); + ep->com.dev->rdev.lldi.adapter_type, cm_id->tos); if (err) { printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); goto fail3; @@ -3244,7 +3261,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ep->l2t->idx); state_set(&ep->com, CONNECTING); - ep->tos = 0; + ep->tos = cm_id->tos; /* send connect request to rnic */ err = send_connect(ep); diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h index a072d341e205..1d2d1da40c80 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h @@ -1021,6 +1021,8 @@ struct cpl_l2t_write_req { #define L2T_W_NOREPLY_V(x) ((x) << L2T_W_NOREPLY_S) #define L2T_W_NOREPLY_F L2T_W_NOREPLY_V(1U) +#define CPL_L2T_VLAN_NONE 0xfff + struct cpl_l2t_write_rpl { union opcode_tid ot; u8 status; diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index a32de30ea663..c8661c77b4e3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h @@ -561,6 +561,7 @@ enum fw_flowc_mnem { FW_FLOWC_MNEM_SNDBUF, FW_FLOWC_MNEM_MSS, FW_FLOWC_MNEM_TXDATAPLEN_MAX, + FW_FLOWC_MNEM_SCHEDCLASS = 11, }; struct fw_flowc_mnemval { -- cgit From 72bb68721f80a1441e871b6afc9ab0b3793d5031 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Fri, 5 Feb 2016 11:16:21 +0000 Subject: ethtool: add IPv6 to the NFC API Signed-off-by: Edward Cree Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 70 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index b2e180181629..5e0940dcbfe8 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -748,6 +748,56 @@ struct ethtool_usrip4_spec { __u8 proto; }; +/** + * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc. + * @ip6src: Source host + * @ip6dst: Destination host + * @psrc: Source port + * @pdst: Destination port + * @tclass: Traffic Class + * + * This can be used to specify a TCP/IPv6, UDP/IPv6 or SCTP/IPv6 flow. + */ +struct ethtool_tcpip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be16 psrc; + __be16 pdst; + __u8 tclass; +}; + +/** + * struct ethtool_ah_espip6_spec - flow specification for IPsec/IPv6 + * @ip6src: Source host + * @ip6dst: Destination host + * @spi: Security parameters index + * @tclass: Traffic Class + * + * This can be used to specify an IPsec transport or tunnel over IPv6. + */ +struct ethtool_ah_espip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be32 spi; + __u8 tclass; +}; + +/** + * struct ethtool_usrip6_spec - general flow specification for IPv6 + * @ip6src: Source host + * @ip6dst: Destination host + * @l4_4_bytes: First 4 bytes of transport (layer 4) header + * @tclass: Traffic Class + * @l4_proto: Transport protocol number (nexthdr after any Extension Headers) + */ +struct ethtool_usrip6_spec { + __be32 ip6src[4]; + __be32 ip6dst[4]; + __be32 l4_4_bytes; + __u8 tclass; + __u8 l4_proto; +}; + union ethtool_flow_union { struct ethtool_tcpip4_spec tcp_ip4_spec; struct ethtool_tcpip4_spec udp_ip4_spec; @@ -755,6 +805,12 @@ union ethtool_flow_union { struct ethtool_ah_espip4_spec ah_ip4_spec; struct ethtool_ah_espip4_spec esp_ip4_spec; struct ethtool_usrip4_spec usr_ip4_spec; + struct ethtool_tcpip6_spec tcp_ip6_spec; + struct ethtool_tcpip6_spec udp_ip6_spec; + struct ethtool_tcpip6_spec sctp_ip6_spec; + struct ethtool_ah_espip6_spec ah_ip6_spec; + struct ethtool_ah_espip6_spec esp_ip6_spec; + struct ethtool_usrip6_spec usr_ip6_spec; struct ethhdr ether_spec; __u8 hdata[52]; }; @@ -1401,15 +1457,17 @@ static inline int ethtool_validate_duplex(__u8 duplex) #define UDP_V4_FLOW 0x02 /* hash or spec (udp_ip4_spec) */ #define SCTP_V4_FLOW 0x03 /* hash or spec (sctp_ip4_spec) */ #define AH_ESP_V4_FLOW 0x04 /* hash only */ -#define TCP_V6_FLOW 0x05 /* hash only */ -#define UDP_V6_FLOW 0x06 /* hash only */ -#define SCTP_V6_FLOW 0x07 /* hash only */ +#define TCP_V6_FLOW 0x05 /* hash or spec (tcp_ip6_spec; nfc only) */ +#define UDP_V6_FLOW 0x06 /* hash or spec (udp_ip6_spec; nfc only) */ +#define SCTP_V6_FLOW 0x07 /* hash or spec (sctp_ip6_spec; nfc only) */ #define AH_ESP_V6_FLOW 0x08 /* hash only */ #define AH_V4_FLOW 0x09 /* hash or spec (ah_ip4_spec) */ #define ESP_V4_FLOW 0x0a /* hash or spec (esp_ip4_spec) */ -#define AH_V6_FLOW 0x0b /* hash only */ -#define ESP_V6_FLOW 0x0c /* hash only */ -#define IP_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ +#define AH_V6_FLOW 0x0b /* hash or spec (ah_ip6_spec; nfc only) */ +#define ESP_V6_FLOW 0x0c /* hash or spec (esp_ip6_spec; nfc only) */ +#define IPV4_USER_FLOW 0x0d /* spec only (usr_ip4_spec) */ +#define IP_USER_FLOW IPV4_USER_FLOW +#define IPV6_USER_FLOW 0x0e /* spec only (usr_ip6_spec; nfc only) */ #define IPV4_FLOW 0x10 /* hash only */ #define IPV6_FLOW 0x11 /* hash only */ #define ETHER_FLOW 0x12 /* spec only (ether_spec) */ -- cgit From a7ad40d00af18bff49437605f2ec148b80b16768 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Fri, 5 Feb 2016 11:16:50 +0000 Subject: sfc: implement IPv6 NFC (and IPV4_USER_FLOW) Signed-off-by: Edward Cree Reviewed-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ethtool.c | 184 +++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 034797661f96..445ccdb6bc67 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -783,14 +783,26 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) static const u8 mac_addr_ig_mask[ETH_ALEN] __aligned(2) = {0x01, 0, 0, 0, 0, 0}; #define IP4_ADDR_FULL_MASK ((__force __be32)~0) +#define IP_PROTO_FULL_MASK 0xFF #define PORT_FULL_MASK ((__force __be16)~0) #define ETHER_TYPE_FULL_MASK ((__force __be16)~0) +static inline void ip6_fill_mask(__be32 *mask) +{ + mask[0] = mask[1] = mask[2] = mask[3] = ~(__be32)0; +} + static int efx_ethtool_get_class_rule(struct efx_nic *efx, struct ethtool_rx_flow_spec *rule) { struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec; struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec; + struct ethtool_usrip4_spec *uip_entry = &rule->h_u.usr_ip4_spec; + struct ethtool_usrip4_spec *uip_mask = &rule->m_u.usr_ip4_spec; + struct ethtool_tcpip6_spec *ip6_entry = &rule->h_u.tcp_ip6_spec; + struct ethtool_tcpip6_spec *ip6_mask = &rule->m_u.tcp_ip6_spec; + struct ethtool_usrip6_spec *uip6_entry = &rule->h_u.usr_ip6_spec; + struct ethtool_usrip6_spec *uip6_mask = &rule->m_u.usr_ip6_spec; struct ethhdr *mac_entry = &rule->h_u.ether_spec; struct ethhdr *mac_mask = &rule->m_u.ether_spec; struct efx_filter_spec spec; @@ -833,6 +845,35 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, ip_entry->psrc = spec.rem_port; ip_mask->psrc = PORT_FULL_MASK; } + } else if ((spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE) && + spec.ether_type == htons(ETH_P_IPV6) && + (spec.match_flags & EFX_FILTER_MATCH_IP_PROTO) && + (spec.ip_proto == IPPROTO_TCP || spec.ip_proto == IPPROTO_UDP) && + !(spec.match_flags & + ~(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_OUTER_VID | + EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_HOST | + EFX_FILTER_MATCH_IP_PROTO | + EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_REM_PORT))) { + rule->flow_type = ((spec.ip_proto == IPPROTO_TCP) ? + TCP_V6_FLOW : UDP_V6_FLOW); + if (spec.match_flags & EFX_FILTER_MATCH_LOC_HOST) { + memcpy(ip6_entry->ip6dst, spec.loc_host, + sizeof(ip6_entry->ip6dst)); + ip6_fill_mask(ip6_mask->ip6dst); + } + if (spec.match_flags & EFX_FILTER_MATCH_REM_HOST) { + memcpy(ip6_entry->ip6src, spec.rem_host, + sizeof(ip6_entry->ip6src)); + ip6_fill_mask(ip6_mask->ip6src); + } + if (spec.match_flags & EFX_FILTER_MATCH_LOC_PORT) { + ip6_entry->pdst = spec.loc_port; + ip6_mask->pdst = PORT_FULL_MASK; + } + if (spec.match_flags & EFX_FILTER_MATCH_REM_PORT) { + ip6_entry->psrc = spec.rem_port; + ip6_mask->psrc = PORT_FULL_MASK; + } } else if (!(spec.match_flags & ~(EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG | EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_ETHER_TYPE | @@ -855,6 +896,47 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, mac_entry->h_proto = spec.ether_type; mac_mask->h_proto = ETHER_TYPE_FULL_MASK; } + } else if (spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE && + spec.ether_type == htons(ETH_P_IP) && + !(spec.match_flags & + ~(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_OUTER_VID | + EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_HOST | + EFX_FILTER_MATCH_IP_PROTO))) { + rule->flow_type = IPV4_USER_FLOW; + uip_entry->ip_ver = ETH_RX_NFC_IP4; + if (spec.match_flags & EFX_FILTER_MATCH_IP_PROTO) { + uip_mask->proto = IP_PROTO_FULL_MASK; + uip_entry->proto = spec.ip_proto; + } + if (spec.match_flags & EFX_FILTER_MATCH_LOC_HOST) { + uip_entry->ip4dst = spec.loc_host[0]; + uip_mask->ip4dst = IP4_ADDR_FULL_MASK; + } + if (spec.match_flags & EFX_FILTER_MATCH_REM_HOST) { + uip_entry->ip4src = spec.rem_host[0]; + uip_mask->ip4src = IP4_ADDR_FULL_MASK; + } + } else if (spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE && + spec.ether_type == htons(ETH_P_IPV6) && + !(spec.match_flags & + ~(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_OUTER_VID | + EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_HOST | + EFX_FILTER_MATCH_IP_PROTO))) { + rule->flow_type = IPV6_USER_FLOW; + if (spec.match_flags & EFX_FILTER_MATCH_IP_PROTO) { + uip6_mask->l4_proto = IP_PROTO_FULL_MASK; + uip6_entry->l4_proto = spec.ip_proto; + } + if (spec.match_flags & EFX_FILTER_MATCH_LOC_HOST) { + memcpy(uip6_entry->ip6dst, spec.loc_host, + sizeof(uip6_entry->ip6dst)); + ip6_fill_mask(uip6_mask->ip6dst); + } + if (spec.match_flags & EFX_FILTER_MATCH_REM_HOST) { + memcpy(uip6_entry->ip6src, spec.rem_host, + sizeof(uip6_entry->ip6src)); + ip6_fill_mask(uip6_mask->ip6src); + } } else { /* The above should handle all filters that we insert */ WARN_ON(1); @@ -946,11 +1028,27 @@ efx_ethtool_get_rxnfc(struct net_device *net_dev, } } +static inline bool ip6_mask_is_full(__be32 mask[4]) +{ + return !~(mask[0] & mask[1] & mask[2] & mask[3]); +} + +static inline bool ip6_mask_is_empty(__be32 mask[4]) +{ + return !(mask[0] | mask[1] | mask[2] | mask[3]); +} + static int efx_ethtool_set_class_rule(struct efx_nic *efx, struct ethtool_rx_flow_spec *rule) { struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec; struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec; + struct ethtool_usrip4_spec *uip_entry = &rule->h_u.usr_ip4_spec; + struct ethtool_usrip4_spec *uip_mask = &rule->m_u.usr_ip4_spec; + struct ethtool_tcpip6_spec *ip6_entry = &rule->h_u.tcp_ip6_spec; + struct ethtool_tcpip6_spec *ip6_mask = &rule->m_u.tcp_ip6_spec; + struct ethtool_usrip6_spec *uip6_entry = &rule->h_u.usr_ip6_spec; + struct ethtool_usrip6_spec *uip6_mask = &rule->m_u.usr_ip6_spec; struct ethhdr *mac_entry = &rule->h_u.ether_spec; struct ethhdr *mac_mask = &rule->m_u.ether_spec; struct efx_filter_spec spec; @@ -1012,6 +1110,92 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, return -EINVAL; break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + spec.match_flags = (EFX_FILTER_MATCH_ETHER_TYPE | + EFX_FILTER_MATCH_IP_PROTO); + spec.ether_type = htons(ETH_P_IPV6); + spec.ip_proto = ((rule->flow_type & ~FLOW_EXT) == TCP_V6_FLOW ? + IPPROTO_TCP : IPPROTO_UDP); + if (!ip6_mask_is_empty(ip6_mask->ip6dst)) { + if (!ip6_mask_is_full(ip6_mask->ip6dst)) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_LOC_HOST; + memcpy(spec.loc_host, ip6_entry->ip6dst, sizeof(spec.loc_host)); + } + if (!ip6_mask_is_empty(ip6_mask->ip6src)) { + if (!ip6_mask_is_full(ip6_mask->ip6src)) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_REM_HOST; + memcpy(spec.rem_host, ip6_entry->ip6src, sizeof(spec.rem_host)); + } + if (ip6_mask->pdst) { + if (ip6_mask->pdst != PORT_FULL_MASK) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_LOC_PORT; + spec.loc_port = ip6_entry->pdst; + } + if (ip6_mask->psrc) { + if (ip6_mask->psrc != PORT_FULL_MASK) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_REM_PORT; + spec.rem_port = ip6_entry->psrc; + } + if (ip6_mask->tclass) + return -EINVAL; + break; + + case IPV4_USER_FLOW: + if (uip_mask->l4_4_bytes || uip_mask->tos || uip_mask->ip_ver || + uip_entry->ip_ver != ETH_RX_NFC_IP4) + return -EINVAL; + spec.match_flags = EFX_FILTER_MATCH_ETHER_TYPE; + spec.ether_type = htons(ETH_P_IP); + if (uip_mask->ip4dst) { + if (uip_mask->ip4dst != IP4_ADDR_FULL_MASK) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_LOC_HOST; + spec.loc_host[0] = uip_entry->ip4dst; + } + if (uip_mask->ip4src) { + if (uip_mask->ip4src != IP4_ADDR_FULL_MASK) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_REM_HOST; + spec.rem_host[0] = uip_entry->ip4src; + } + if (uip_mask->proto) { + if (uip_mask->proto != IP_PROTO_FULL_MASK) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_IP_PROTO; + spec.ip_proto = uip_entry->proto; + } + break; + + case IPV6_USER_FLOW: + if (uip6_mask->l4_4_bytes || uip6_mask->tclass) + return -EINVAL; + spec.match_flags = EFX_FILTER_MATCH_ETHER_TYPE; + spec.ether_type = htons(ETH_P_IPV6); + if (!ip6_mask_is_empty(uip6_mask->ip6dst)) { + if (!ip6_mask_is_full(uip6_mask->ip6dst)) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_LOC_HOST; + memcpy(spec.loc_host, uip6_entry->ip6dst, sizeof(spec.loc_host)); + } + if (!ip6_mask_is_empty(uip6_mask->ip6src)) { + if (!ip6_mask_is_full(uip6_mask->ip6src)) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_REM_HOST; + memcpy(spec.rem_host, uip6_entry->ip6src, sizeof(spec.rem_host)); + } + if (uip6_mask->l4_proto) { + if (uip6_mask->l4_proto != IP_PROTO_FULL_MASK) + return -EINVAL; + spec.match_flags |= EFX_FILTER_MATCH_IP_PROTO; + spec.ip_proto = uip6_entry->l4_proto; + } + break; + case ETHER_FLOW: if (!is_zero_ether_addr(mac_mask->h_dest)) { if (ether_addr_equal(mac_mask->h_dest, -- cgit From a060679c6b3da17dc9e95d0500f811de118ec901 Mon Sep 17 00:00:00 2001 From: "sixiao@microsoft.com" Date: Thu, 4 Feb 2016 15:49:34 -0800 Subject: hv_netvsc: cleanup netdev feature flags for netvsc 1. Adding NETIF_F_TSO6 feature flag; 2. Adding NETIF_F_HW_CSUM. NETIF_F_IPV6_CSUM and NETIF_F_IP_CSUM are being deprecated; 3. Cleanup the coding style of flag assignment by using macro. Signed-off-by: Simon Xiao Reviewed-by: K. Y. Srinivasan Reviewed-by: Haiyang Zhang Signed-off-by: David S. Miller --- drivers/net/hyperv/netvsc_drv.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 1d3a66563bac..c72e5b83afdb 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -43,6 +43,11 @@ #define RING_SIZE_MIN 64 #define LINKCHANGE_INT (2 * HZ) +#define NETVSC_HW_FEATURES (NETIF_F_RXCSUM | \ + NETIF_F_SG | \ + NETIF_F_TSO | \ + NETIF_F_TSO6 | \ + NETIF_F_HW_CSUM) static int ring_size = 128; module_param(ring_size, int, S_IRUGO); MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); @@ -1081,10 +1086,8 @@ static int netvsc_probe(struct hv_device *dev, net->netdev_ops = &device_ops; - net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_TSO; - net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM | - NETIF_F_IP_CSUM | NETIF_F_TSO; + net->hw_features = NETVSC_HW_FEATURES; + net->features = NETVSC_HW_FEATURES | NETIF_F_HW_VLAN_CTAG_TX; net->ethtool_ops = ðtool_ops; SET_NETDEV_DEV(net, &dev->device); -- cgit From b802fb99ae964681d1754428f67970911e0476e9 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:56 -0200 Subject: [media] tvp5150: move input definition header to dt-bindings Add a header file for the tvp5150 input connectors constants that can be shared between the driver and Device Tree source files. [mchehab@osg.samsung.com: rename tvp5150.h also at em28xx-cards.c] Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 2 +- drivers/media/usb/em28xx/em28xx-cards.c | 2 +- include/dt-bindings/media/tvp5150.h | 34 +++++++++++++++++++++++++++++++++ include/media/i2c/tvp5150.h | 34 --------------------------------- 4 files changed, 36 insertions(+), 36 deletions(-) create mode 100644 include/dt-bindings/media/tvp5150.h delete mode 100644 include/media/i2c/tvp5150.h diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 093ff80f944c..3a32fd1df805 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -5,6 +5,7 @@ * This code is placed under the terms of the GNU General Public License v2 */ +#include #include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index ba442c967415..06a09b4e4a83 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h new file mode 100644 index 000000000000..dc347569854f --- /dev/null +++ b/include/dt-bindings/media/tvp5150.h @@ -0,0 +1,34 @@ +/* + tvp5150.h - definition for tvp5150 inputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _DT_BINDINGS_MEDIA_TVP5150_H +#define _DT_BINDINGS_MEDIA_TVP5150_H + +/* TVP5150 HW inputs */ +#define TVP5150_COMPOSITE0 0 +#define TVP5150_COMPOSITE1 1 +#define TVP5150_SVIDEO 2 +#define TVP5150_GENERATOR 3 + +/* TVP5150 HW outputs */ +#define TVP5150_NORMAL 0 +#define TVP5150_BLACK_SCREEN 1 + +#endif /* _DT_BINDINGS_MEDIA_TVP5150_H */ diff --git a/include/media/i2c/tvp5150.h b/include/media/i2c/tvp5150.h deleted file mode 100644 index 685a1e718531..000000000000 --- a/include/media/i2c/tvp5150.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - tvp5150.h - definition for tvp5150 inputs - - Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) - - 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _TVP5150_H_ -#define _TVP5150_H_ - -/* TVP5150 HW inputs */ -#define TVP5150_COMPOSITE0 0 -#define TVP5150_COMPOSITE1 1 -#define TVP5150_SVIDEO 2 -#define TVP5150_GENERATOR 3 - -/* TVP5150 HW outputs */ -#define TVP5150_NORMAL 0 -#define TVP5150_BLACK_SCREEN 1 - -#endif -- cgit From 82c2ffeb217a024084f3ad0bf3705f5661365804 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:57 -0200 Subject: [media] tvp5150: document input connectors DT bindings The tvp5150 decoder has different input connectors so extend the device tree binding to allow device tree source files to define the connectors that are available on a given board. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- .../devicetree/bindings/media/i2c/tvp5150.txt | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt index 8c0fc1a26bf0..daa20e43a8e3 100644 --- a/Documentation/devicetree/bindings/media/i2c/tvp5150.txt +++ b/Documentation/devicetree/bindings/media/i2c/tvp5150.txt @@ -12,6 +12,32 @@ Optional Properties: - pdn-gpios: phandle for the GPIO connected to the PDN pin, if any. - reset-gpios: phandle for the GPIO connected to the RESETB pin, if any. +Optional nodes: +- connectors: The input connectors of tvp5150 have to be defined under + a subnode name "connectors" using the following format: + + input-connector-name { + input connector properties + }; + +Each input connector must contain the following properties: + + - label: a name for the connector. + - input: the input connector. + +The possible values for the "input" property are: + 0: Composite0 + 1: Composite1 + 2: S-Video + +and on a tvp5150am1 and tvp5151 there is another: + 4: Signal generator + +The list of valid input connectors are defined in dt-bindings/media/tvp5150.h +header file and can be included by device tree source files. + +Each input connector can be defined only once. + The device node must contain one 'port' child node for its digital output video port, in accordance with the video interface bindings defined in Documentation/devicetree/bindings/media/video-interfaces.txt. @@ -36,6 +62,23 @@ Example: pdn-gpios = <&gpio4 30 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>; + connectors { + composite0 { + label = "Composite0"; + input = ; + }; + + composite1 { + label = "Composite1"; + input = ; + }; + + s-video { + label = "S-Video"; + input = ; + }; + }; + port { tvp5150_1: endpoint { remote-endpoint = <&ccdc_ep>; -- cgit From f7b4b54e63643b740c598e044874c4bffa0f04f2 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 5 Feb 2016 17:09:58 -0200 Subject: [media] tvp5150: add HW input connectors support The tvp5150 decoder has different input connectors. The actual list of HW inputs depends on the device version but all have at least these 3: 1) Composite0 2) Composite1 3) S-Video and some variants have a 4th possible input connector: 4) Signal generator The driver currently uses the .s_routing callback to switch the input connector but since these are separate HW blocks, it's better to use media entities to represent the input connectors and their source pads linked with the decoder's sink pad. This allows user-space to use the MEDIA_IOC_SETUP_LINK ioctl to choose the input connector. For example using the media-ctl user-space tool: $ media-ctl -r -l '"Composite0":0->"tvp5150 1-005c":0[1]' Signed-off-by: Javier Martinez Canillas Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/tvp5150.c | 150 ++++++++++++++++++++++++++++++++++++ include/dt-bindings/media/tvp5150.h | 2 + 2 files changed, 152 insertions(+) diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 3a32fd1df805..b8976028fc82 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -40,6 +40,8 @@ struct tvp5150 { struct v4l2_subdev sd; #ifdef CONFIG_MEDIA_CONTROLLER struct media_pad pads[DEMOD_NUM_PADS]; + struct media_entity input_ent[TVP5150_INPUT_NUM]; + struct media_pad input_pad[TVP5150_INPUT_NUM]; #endif struct v4l2_ctrl_handler hdl; struct v4l2_rect rect; @@ -996,6 +998,49 @@ static int tvp5150_enum_frame_size(struct v4l2_subdev *sd, return 0; } +/**************************************************************************** + Media entity ops + ****************************************************************************/ + +static int tvp5150_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); + struct tvp5150 *decoder = to_tvp5150(sd); + int i; + + for (i = 0; i < TVP5150_INPUT_NUM; i++) { + if (remote->entity == &decoder->input_ent[i]) + break; + } + + /* Do nothing for entities that are not input connectors */ + if (i == TVP5150_INPUT_NUM) + return 0; + + decoder->input = i; + + /* Only tvp5150am1 and tvp5151 have signal generator support */ + if ((decoder->dev_id == 0x5150 && decoder->rom_ver == 0x0400) || + (decoder->dev_id == 0x5151 && decoder->rom_ver == 0x0100)) { + decoder->output = (i == TVP5150_GENERATOR ? + TVP5150_BLACK_SCREEN : TVP5150_NORMAL); + } else { + decoder->output = TVP5150_NORMAL; + } + + tvp5150_selmux(sd); +#endif + + return 0; +} + +static const struct media_entity_operations tvp5150_sd_media_ops = { + .link_setup = tvp5150_link_setup, +}; + /**************************************************************************** I2C Command ****************************************************************************/ @@ -1122,6 +1167,42 @@ static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt) return 0; } +static int tvp5150_registered_async(struct v4l2_subdev *sd) +{ +#ifdef CONFIG_MEDIA_CONTROLLER + struct tvp5150 *decoder = to_tvp5150(sd); + int ret = 0; + int i; + + for (i = 0; i < TVP5150_INPUT_NUM; i++) { + struct media_entity *input = &decoder->input_ent[i]; + struct media_pad *pad = &decoder->input_pad[i]; + + if (!input->name) + continue; + + decoder->input_pad[i].flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(input, 1, pad); + if (ret < 0) + return ret; + + ret = media_device_register_entity(sd->v4l2_dev->mdev, input); + if (ret < 0) + return ret; + + ret = media_create_pad_link(input, 0, &sd->entity, + DEMOD_PAD_IF_INPUT, 0); + if (ret < 0) { + media_device_unregister_entity(input); + return ret; + } + } +#endif + + return 0; +} + /* ----------------------------------------------------------------------- */ static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = { @@ -1135,6 +1216,7 @@ static const struct v4l2_subdev_core_ops tvp5150_core_ops = { .g_register = tvp5150_g_register, .s_register = tvp5150_s_register, #endif + .registered_async = tvp5150_registered_async, }; static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { @@ -1255,6 +1337,12 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) { struct v4l2_of_endpoint bus_cfg; struct device_node *ep; +#ifdef CONFIG_MEDIA_CONTROLLER + struct device_node *connectors, *child; + struct media_entity *input; + const char *name; + u32 input_type; +#endif unsigned int flags; int ret = 0; @@ -1278,6 +1366,66 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np) decoder->mbus_type = bus_cfg.bus_type; +#ifdef CONFIG_MEDIA_CONTROLLER + connectors = of_get_child_by_name(np, "connectors"); + + if (!connectors) + goto err; + + for_each_available_child_of_node(connectors, child) { + ret = of_property_read_u32(child, "input", &input_type); + if (ret) { + v4l2_err(&decoder->sd, + "missing type property in node %s\n", + child->name); + goto err_connector; + } + + if (input_type > TVP5150_INPUT_NUM) { + ret = -EINVAL; + goto err_connector; + } + + input = &decoder->input_ent[input_type]; + + /* Each input connector can only be defined once */ + if (input->name) { + v4l2_err(&decoder->sd, + "input %s with same type already exists\n", + input->name); + ret = -EINVAL; + goto err_connector; + } + + switch (input_type) { + case TVP5150_COMPOSITE0: + case TVP5150_COMPOSITE1: + input->function = MEDIA_ENT_F_CONN_COMPOSITE; + break; + case TVP5150_SVIDEO: + input->function = MEDIA_ENT_F_CONN_SVIDEO; + break; + case TVP5150_GENERATOR: + input->function = MEDIA_ENT_F_CONN_TEST; + break; + } + + input->flags = MEDIA_ENT_FL_CONNECTOR; + + ret = of_property_read_string(child, "label", &name); + if (ret < 0) { + v4l2_err(&decoder->sd, + "missing label property in node %s\n", + child->name); + goto err_connector; + } + + input->name = name; + } + +err_connector: + of_node_put(connectors); +#endif err: of_node_put(ep); return ret; @@ -1330,6 +1478,8 @@ static int tvp5150_probe(struct i2c_client *c, res = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, core->pads); if (res < 0) return res; + + sd->entity.ops = &tvp5150_sd_media_ops; #endif res = tvp5150_detect_version(core); diff --git a/include/dt-bindings/media/tvp5150.h b/include/dt-bindings/media/tvp5150.h index dc347569854f..d30865222082 100644 --- a/include/dt-bindings/media/tvp5150.h +++ b/include/dt-bindings/media/tvp5150.h @@ -27,6 +27,8 @@ #define TVP5150_SVIDEO 2 #define TVP5150_GENERATOR 3 +#define TVP5150_INPUT_NUM 4 + /* TVP5150 HW outputs */ #define TVP5150_NORMAL 0 #define TVP5150_BLACK_SCREEN 1 -- cgit From ba83a11104ae7d156c73f4db288ec7a0b7edcdb5 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Tue, 2 Feb 2016 22:21:51 +0100 Subject: pinctrl: sunxi: Add H3 R_PIO controller support H3 has additional PIO controller similar to what we can find on A23. It's a 12 pin port, described in H3 Datasheet rev 1.1, pages 345-350. Signed-off-by: Krzysztof Adamski Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/Kconfig | 4 ++ drivers/pinctrl/sunxi/Makefile | 1 + drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c | 106 +++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig index ac8388e67340..1868b8267f10 100644 --- a/drivers/pinctrl/sunxi/Kconfig +++ b/drivers/pinctrl/sunxi/Kconfig @@ -55,6 +55,10 @@ config PINCTRL_SUN8I_H3 def_bool MACH_SUN8I select PINCTRL_SUNXI +config PINCTRL_SUN8I_H3_R + def_bool MACH_SUN8I + select PINCTRL_SUNXI_COMMON + config PINCTRL_SUN9I_A80 def_bool MACH_SUN9I select PINCTRL_SUNXI diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile index dac1bd0cda4a..f22de0e5c49a 100644 --- a/drivers/pinctrl/sunxi/Makefile +++ b/drivers/pinctrl/sunxi/Makefile @@ -14,5 +14,6 @@ obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o obj-$(CONFIG_PINCTRL_SUN8I_A33) += pinctrl-sun8i-a33.o obj-$(CONFIG_PINCTRL_SUN8I_A83T) += pinctrl-sun8i-a83t.o obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o +obj-$(CONFIG_PINCTRL_SUN8I_H3_R) += pinctrl-sun8i-h3-r.o obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c new file mode 100644 index 000000000000..686ec212120b --- /dev/null +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3-r.c @@ -0,0 +1,106 @@ +/* + * Allwinner H3 SoCs pinctrl driver. + * + * Copyright (C) 2016 Krzysztof Adamski + * + * 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 "pinctrl-sunxi.h" + +static const struct sunxi_desc_pin sun8i_h3_r_pins[] = { + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_twi"), /* SCK */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_twi"), /* SDA */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_uart"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PL_EINT2 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_uart"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PL_EINT3 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_jtag"), /* MS */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PL_EINT4 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_jtag"), /* CK */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PL_EINT5 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_jtag"), /* DO */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PL_EINT6 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_jtag"), /* DI */ + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PL_EINT7 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PL_EINT8 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PL_EINT9 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_pwm"), + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PL_EINT10 */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "s_cir_rx"), + SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PL_EINT11 */ +}; + +static const struct sunxi_pinctrl_desc sun8i_h3_r_pinctrl_data = { + .pins = sun8i_h3_r_pins, + .npins = ARRAY_SIZE(sun8i_h3_r_pins), + .irq_banks = 1, + .pin_base = PL_BASE, + .irq_read_needs_mux = true +}; + +static int sun8i_h3_r_pinctrl_probe(struct platform_device *pdev) +{ + return sunxi_pinctrl_init(pdev, + &sun8i_h3_r_pinctrl_data); +} + +static const struct of_device_id sun8i_h3_r_pinctrl_match[] = { + { .compatible = "allwinner,sun8i-h3-r-pinctrl", }, + {} +}; + +static struct platform_driver sun8i_h3_r_pinctrl_driver = { + .probe = sun8i_h3_r_pinctrl_probe, + .driver = { + .name = "sun8i-h3-r-pinctrl", + .of_match_table = sun8i_h3_r_pinctrl_match, + }, +}; +builtin_platform_driver(sun8i_h3_r_pinctrl_driver); -- cgit From be2d107f44339def4c2cfb876c7c001e4169e419 Mon Sep 17 00:00:00 2001 From: Krzysztof Adamski Date: Tue, 9 Feb 2016 15:58:49 +0100 Subject: pinctrl: sunxi: Use pin number when calling sunxi_pmx_set sunxi_pmx_set accepts pin number and then calculates offset by subtracting pin_base from it. sunxi_pinctrl_gpio_get, on the other hand, gets offset so we have to convert it to pin number so we won't get negative value in sunxi_pmx_set. This was only used on A10 so far, where there is only one GPIO chip with pin_base set to 0 so it didn't matter. However H3 also requires this workaround but have two pinmux sections, triggering problem for PL port. Signed-off-by: Krzysztof Adamski Acked-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 7a2465f5e71e..96f64a104a62 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -459,15 +459,16 @@ static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset) u8 index = sunxi_data_offset(offset); u32 set_mux = pctl->desc->irq_read_needs_mux && test_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags); + u32 pin = offset + chip->base; u32 val; if (set_mux) - sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_INPUT); + sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT); val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK; if (set_mux) - sunxi_pmx_set(pctl->pctl_dev, offset, SUN4I_FUNC_IRQ); + sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ); return !!val; } -- cgit From bef3c6c9374da40ec63698cd504474366a9de2ff Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:27:31 -0800 Subject: net: Drop unecessary enc_features variable from tunnel segmentation functions The enc_features variable isn't necessary since features isn't used anywhere after we create enc_features so instead just use a destructive AND on features itself and save ourselves the variable declaration. Signed-off-by: Alexander Duyck Acked-by: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/gre_offload.c | 6 +++--- net/ipv4/udp_offload.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 5a8ee3282550..02cb1a416c7d 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -19,7 +19,6 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, netdev_features_t features) { struct sk_buff *segs = ERR_PTR(-EINVAL); - netdev_features_t enc_features; int ghl; struct gre_base_hdr *greh; u16 mac_offset = skb->mac_header; @@ -68,9 +67,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, skb_set_network_header(skb, skb_inner_network_offset(skb)); skb->mac_len = skb_inner_network_offset(skb); + features &= skb->dev->hw_enc_features; + /* segment inner packet. */ - enc_features = skb->dev->hw_enc_features & features; - segs = skb_mac_gso_segment(skb, enc_features); + segs = skb_mac_gso_segment(skb, features); if (IS_ERR_OR_NULL(segs)) { skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); goto out; diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 4c519c1dc161..ce64c2b7ba55 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -37,7 +37,6 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, int mac_len = skb->mac_len; int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); __be16 protocol = skb->protocol; - netdev_features_t enc_features; int udp_offset, outer_hlen; unsigned int oldlen; bool need_csum = !!(skb_shinfo(skb)->gso_type & @@ -65,9 +64,10 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, (skb->dev->features & (is_ipv6 ? NETIF_F_IPV6_CSUM : NETIF_F_IP_CSUM)))); + features &= skb->dev->hw_enc_features; + /* segment inner packet. */ - enc_features = skb->dev->hw_enc_features & features; - segs = gso_inner_segment(skb, enc_features); + segs = gso_inner_segment(skb, features); if (IS_ERR_OR_NULL(segs)) { skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, mac_len); -- cgit From 76443456227097179c14826425f88a95d81a892e Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:27:37 -0800 Subject: net: Move GSO csum into SKB_GSO_CB This patch moves the checksum maintained by GSO out of skb->csum and into the GSO context block in order to allow for us to work on outer checksums while maintaining the inner checksum offsets in the case of the inner checksum being offloaded, while the outer checksums will be computed. While updating the code I also did a minor cleanu-up on gso_make_checksum. The change is mostly to make it so that we store the values and compute the checksum instead of computing the checksum and then storing the values we needed to update. Signed-off-by: Alexander Duyck Acked-by: Tom Herbert Signed-off-by: David S. Miller --- include/linux/skbuff.h | 14 +++++++------- net/core/skbuff.c | 16 +++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 11f935c1a090..acece7ce376f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3549,6 +3549,7 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb) struct skb_gso_cb { int mac_offset; int encap_level; + __wsum csum; __u16 csum_start; }; #define SKB_SGO_CB_OFFSET 32 @@ -3585,15 +3586,14 @@ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra) */ static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res) { - int plen = SKB_GSO_CB(skb)->csum_start - skb_headroom(skb) - - skb_transport_offset(skb); - __wsum partial; + unsigned char *csum_start = skb_transport_header(skb); + int plen = (skb->head + SKB_GSO_CB(skb)->csum_start) - csum_start; + __wsum partial = SKB_GSO_CB(skb)->csum; - partial = csum_partial(skb_transport_header(skb), plen, skb->csum); - skb->csum = res; - SKB_GSO_CB(skb)->csum_start -= plen; + SKB_GSO_CB(skb)->csum = res; + SKB_GSO_CB(skb)->csum_start = csum_start - skb->head; - return csum_fold(partial); + return csum_fold(csum_partial(csum_start, plen, partial)); } static inline bool skb_is_gso(const struct sk_buff *skb) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b2df375ec9c2..02c638a643ea 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3100,11 +3100,12 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, if (!sg && !nskb->remcsum_offload) { nskb->ip_summed = CHECKSUM_NONE; - nskb->csum = skb_copy_and_csum_bits(head_skb, offset, - skb_put(nskb, len), - len, 0); + SKB_GSO_CB(nskb)->csum = + skb_copy_and_csum_bits(head_skb, offset, + skb_put(nskb, len), + len, 0); SKB_GSO_CB(nskb)->csum_start = - skb_headroom(nskb) + doffset; + skb_headroom(nskb) + doffset; continue; } @@ -3171,11 +3172,12 @@ skip_fraglist: perform_csum_check: if (!csum && !nskb->remcsum_offload) { - nskb->csum = skb_checksum(nskb, doffset, - nskb->len - doffset, 0); nskb->ip_summed = CHECKSUM_NONE; + SKB_GSO_CB(nskb)->csum = + skb_checksum(nskb, doffset, + nskb->len - doffset, 0); SKB_GSO_CB(nskb)->csum_start = - skb_headroom(nskb) + doffset; + skb_headroom(nskb) + doffset; } } while ((offset += len) < head_skb->len); -- cgit From 7fbeffed77c130ecf64e8a2f7f9d6d63a9d60a19 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:27:43 -0800 Subject: net: Update remote checksum segmentation to support use of GSO checksum This patch addresses two main issues. First in the case of remote checksum offload we were avoiding dealing with scatter-gather issues. As a result it would be possible to assemble a series of frames that used frags instead of being linearized as they should have if remote checksum offload was enabled. Second I have updated the code so that we now let GSO take care of doing the checksum on the data itself and drop the special case that was added for remote checksum offload. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/core/skbuff.c | 10 ++++++---- net/ipv4/udp_offload.c | 22 ++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 02c638a643ea..9c065ac72e87 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3098,8 +3098,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, if (nskb->len == len + doffset) goto perform_csum_check; - if (!sg && !nskb->remcsum_offload) { - nskb->ip_summed = CHECKSUM_NONE; + if (!sg) { + if (!nskb->remcsum_offload) + nskb->ip_summed = CHECKSUM_NONE; SKB_GSO_CB(nskb)->csum = skb_copy_and_csum_bits(head_skb, offset, skb_put(nskb, len), @@ -3171,8 +3172,9 @@ skip_fraglist: nskb->truesize += nskb->data_len; perform_csum_check: - if (!csum && !nskb->remcsum_offload) { - nskb->ip_summed = CHECKSUM_NONE; + if (!csum) { + if (!nskb->remcsum_offload) + nskb->ip_summed = CHECKSUM_NONE; SKB_GSO_CB(nskb)->csum = skb_checksum(nskb, doffset, nskb->len - doffset, 0); diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index ce64c2b7ba55..86687f58d613 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -66,6 +66,16 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, features &= skb->dev->hw_enc_features; + /* The only checksum offload we care about from here on out is the + * outer one so strip the existing checksum feature flags and + * instead set the flag based on our outer checksum offload value. + */ + if (remcsum) { + features &= ~NETIF_F_CSUM_MASK; + if (offload_csum) + features |= NETIF_F_HW_CSUM; + } + /* segment inner packet. */ segs = gso_inner_segment(skb, features); if (IS_ERR_OR_NULL(segs)) { @@ -116,18 +126,6 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_transport_header(skb) - skb->head; skb->csum_offset = offsetof(struct udphdr, check); - } else if (remcsum) { - /* Need to calculate checksum from scratch, - * inner checksums are never when doing - * remote_checksum_offload. - */ - - skb->csum = skb_checksum(skb, udp_offset, - skb->len - udp_offset, - 0); - uh->check = csum_fold(skb->csum); - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; } else { uh->check = gso_make_checksum(skb, ~uh->check); -- cgit From 08b64fcca942733413bc5ac2321d57021d3e8578 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:27:49 -0800 Subject: net: Store checksum result for offloaded GSO checksums This patch makes it so that we can offload the checksums for a packet up to a certain point and then begin computing the checksums via software. Setting this up is fairly straight forward as all we need to do is reset the values stored in csum and csum_start for the GSO context block. One complication for this is remote checksum offload. In order to allow the inner checksums to be offloaded while computing the outer checksum manually we needed to have some way of indicating that the offload wasn't real. In order to do that I replaced CHECKSUM_PARTIAL with CHECKSUM_UNNECESSARY in the case of us computing checksums for the outer header while skipping computing checksums for the inner headers. We clean up the ip_summed flag and set it to either CHECKSUM_PARTIAL or CHECKSUM_NONE once we hand the packet off to the next lower level. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/skbuff.h | 15 +++++++++++++++ net/ipv4/tcp_offload.c | 8 ++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index acece7ce376f..a8fc2220e8ce 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2161,6 +2161,11 @@ static inline int skb_checksum_start_offset(const struct sk_buff *skb) return skb->csum_start - skb_headroom(skb); } +static inline unsigned char *skb_checksum_start(const struct sk_buff *skb) +{ + return skb->head + skb->csum_start; +} + static inline int skb_transport_offset(const struct sk_buff *skb) { return skb_transport_header(skb) - skb->data; @@ -3576,6 +3581,16 @@ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra) return 0; } +static inline void gso_reset_checksum(struct sk_buff *skb, __wsum res) +{ + /* Do not update partial checksums if remote checksum is enabled. */ + if (skb->remcsum_offload) + return; + + SKB_GSO_CB(skb)->csum = res; + SKB_GSO_CB(skb)->csum_start = skb_checksum_start(skb) - skb->head; +} + /* Compute the checksum for a gso segment. First compute the checksum value * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and * then add in skb->csum (checksum from csum_start to end of packet). diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 9864a2dbadce..773083b7f1e9 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -135,7 +135,9 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, th->fin = th->psh = 0; th->check = newcheck; - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_PARTIAL) + gso_reset_checksum(skb, ~th->check); + else th->check = gso_make_checksum(skb, ~th->check); seq += mss; @@ -169,7 +171,9 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, skb->data_len); th->check = ~csum_fold((__force __wsum)((__force u32)th->check + (__force u32)delta)); - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_PARTIAL) + gso_reset_checksum(skb, ~th->check); + else th->check = gso_make_checksum(skb, ~th->check); out: return segs; -- cgit From ddff00d420432d54eb420bb33034bb8e22dd2543 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:27:55 -0800 Subject: net: Move skb_has_shared_frag check out of GRE code and into segmentation The call skb_has_shared_frag is used in the GRE path and skb_checksum_help to verify that no frags can be modified by an external entity. This check really doesn't belong in the GRE path but in the skb_segment function itself. This way any protocol that might be segmented will be performing this check before attempting to offload a checksum to software. Signed-off-by: Alexander Duyck Acked-by: Tom Herbert Signed-off-by: David S. Miller --- net/core/skbuff.c | 5 +++++ net/ipv4/gre_offload.c | 11 ----------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 9c065ac72e87..88262c82b96a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3173,6 +3173,11 @@ skip_fraglist: perform_csum_check: if (!csum) { + if (skb_has_shared_frag(nskb)) { + err = __skb_linearize(nskb); + if (err) + goto err; + } if (!nskb->remcsum_offload) nskb->ip_summed = CHECKSUM_NONE; SKB_GSO_CB(nskb)->csum = diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 02cb1a416c7d..35a8dd35ed4e 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -83,17 +83,6 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, if (csum) { __be32 *pcsum; - if (skb_has_shared_frag(skb)) { - int err; - - err = __skb_linearize(skb); - if (err) { - kfree_skb_list(segs); - segs = ERR_PTR(err); - goto out; - } - } - skb_reset_transport_header(skb); greh = (struct gre_base_hdr *) -- cgit From 2e598af7135d1434b0ebf2e9c7ff8e014f48d572 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:28:01 -0800 Subject: gre: Use GSO flags to determine csum need instead of GRE flags This patch updates the gre checksum path to follow something much closer to the UDP checksum path. By doing this we can avoid needing to do as much header inspection and can just make use of the fields we were already reading in the sk_buff structure. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/ipv4/gre_offload.c | 64 +++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 35a8dd35ed4e..c15441b5ff61 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -18,14 +18,14 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, netdev_features_t features) { + int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); struct sk_buff *segs = ERR_PTR(-EINVAL); - int ghl; struct gre_base_hdr *greh; u16 mac_offset = skb->mac_header; - int mac_len = skb->mac_len; __be16 protocol = skb->protocol; - int tnl_hlen; - bool csum; + u16 mac_len = skb->mac_len; + int gre_offset, outer_hlen; + bool need_csum; if (unlikely(skb_shinfo(skb)->gso_type & ~(SKB_GSO_TCPV4 | @@ -42,64 +42,60 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, if (!skb->encapsulation) goto out; - if (unlikely(!pskb_may_pull(skb, sizeof(*greh)))) + if (unlikely(tnl_hlen < sizeof(struct gre_base_hdr))) goto out; - greh = (struct gre_base_hdr *)skb_transport_header(skb); - - ghl = skb_inner_mac_header(skb) - skb_transport_header(skb); - if (unlikely(ghl < sizeof(*greh))) + if (unlikely(!pskb_may_pull(skb, tnl_hlen))) goto out; - csum = !!(greh->flags & GRE_CSUM); - if (csum) - skb->encap_hdr_csum = 1; + greh = (struct gre_base_hdr *)skb_transport_header(skb); /* setup inner skb. */ skb->protocol = greh->protocol; skb->encapsulation = 0; - - if (unlikely(!pskb_may_pull(skb, ghl))) - goto out; - - __skb_pull(skb, ghl); + __skb_pull(skb, tnl_hlen); skb_reset_mac_header(skb); skb_set_network_header(skb, skb_inner_network_offset(skb)); skb->mac_len = skb_inner_network_offset(skb); + need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE_CSUM); + skb->encap_hdr_csum = need_csum; + features &= skb->dev->hw_enc_features; /* segment inner packet. */ segs = skb_mac_gso_segment(skb, features); if (IS_ERR_OR_NULL(segs)) { - skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); + skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, + mac_len); goto out; } + outer_hlen = skb_tnl_header_len(skb); + gre_offset = outer_hlen - tnl_hlen; skb = segs; - tnl_hlen = skb_tnl_header_len(skb); do { - __skb_push(skb, ghl); - if (csum) { - __be32 *pcsum; - - skb_reset_transport_header(skb); - - greh = (struct gre_base_hdr *) - skb_transport_header(skb); - pcsum = (__be32 *)(greh + 1); - *pcsum = 0; - *(__sum16 *)pcsum = gso_make_checksum(skb, 0); - } - __skb_push(skb, tnl_hlen - ghl); + __be32 *pcsum; skb_reset_inner_headers(skb); skb->encapsulation = 1; - skb_reset_mac_header(skb); - skb_set_network_header(skb, mac_len); skb->mac_len = mac_len; skb->protocol = protocol; + + __skb_push(skb, outer_hlen); + skb_reset_mac_header(skb); + skb_set_network_header(skb, mac_len); + skb_set_transport_header(skb, gre_offset); + + if (!need_csum) + continue; + + greh = (struct gre_base_hdr *)skb_transport_header(skb); + pcsum = (__be32 *)(greh + 1); + + *pcsum = 0; + *(__sum16 *)pcsum = gso_make_checksum(skb, 0); } while ((skb = skb->next)); out: return segs; -- cgit From 38720352412a4305a108ff37ae6099dab3f44a38 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:28:08 -0800 Subject: gre: Use inner_proto to obtain inner header protocol Instead of parsing headers to determine the inner protocol we can just pull the value from inner_proto. Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- net/ipv4/gre_offload.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index c15441b5ff61..003b0ebbcfdd 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -20,7 +20,6 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, { int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); struct sk_buff *segs = ERR_PTR(-EINVAL); - struct gre_base_hdr *greh; u16 mac_offset = skb->mac_header; __be16 protocol = skb->protocol; u16 mac_len = skb->mac_len; @@ -48,15 +47,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, if (unlikely(!pskb_may_pull(skb, tnl_hlen))) goto out; - greh = (struct gre_base_hdr *)skb_transport_header(skb); - /* setup inner skb. */ - skb->protocol = greh->protocol; skb->encapsulation = 0; __skb_pull(skb, tnl_hlen); skb_reset_mac_header(skb); skb_set_network_header(skb, skb_inner_network_offset(skb)); skb->mac_len = skb_inner_network_offset(skb); + skb->protocol = skb->inner_protocol; need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE_CSUM); skb->encap_hdr_csum = need_csum; @@ -75,6 +72,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, gre_offset = outer_hlen - tnl_hlen; skb = segs; do { + struct gre_base_hdr *greh; __be32 *pcsum; skb_reset_inner_headers(skb); -- cgit From fdaefd62fd658b266a8f389cdf7991630b4bc7b4 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:28:14 -0800 Subject: udp: Clean up the use of flags in UDP segmentation offload This patch goes though and cleans up the logic related to several of the control flags used in UDP segmentation. Specifically the use of dont_encap isn't really needed as we can just check the skb for CHECKSUM_PARTIAL and if it isn't set then we don't need to update the internal headers. As such we can just drop that value. Signed-off-by: Alexander Duyck Acked-by: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/udp_offload.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 86687f58d613..9e4816fc9927 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -33,16 +33,13 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, __be16 new_protocol, bool is_ipv6) { struct sk_buff *segs = ERR_PTR(-EINVAL); + bool remcsum, need_csum, offload_csum; u16 mac_offset = skb->mac_header; int mac_len = skb->mac_len; int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); __be16 protocol = skb->protocol; int udp_offset, outer_hlen; unsigned int oldlen; - bool need_csum = !!(skb_shinfo(skb)->gso_type & - SKB_GSO_UDP_TUNNEL_CSUM); - bool remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM); - bool offload_csum = false, dont_encap = (need_csum || remcsum); oldlen = (u16)~skb->len; @@ -55,14 +52,18 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, skb_set_network_header(skb, skb_inner_network_offset(skb)); skb->mac_len = skb_inner_network_offset(skb); skb->protocol = new_protocol; + + need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM); skb->encap_hdr_csum = need_csum; + + remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM); skb->remcsum_offload = remcsum; /* Try to offload checksum if possible */ offload_csum = !!(need_csum && - ((skb->dev->features & NETIF_F_HW_CSUM) || - (skb->dev->features & (is_ipv6 ? - NETIF_F_IPV6_CSUM : NETIF_F_IP_CSUM)))); + (skb->dev->features & + (is_ipv6 ? (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM) : + (NETIF_F_HW_CSUM | NETIF_F_IP_CSUM)))); features &= skb->dev->hw_enc_features; @@ -92,13 +93,11 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, int len; __be32 delta; - if (dont_encap) { - skb->encapsulation = 0; + if (remcsum) skb->ip_summed = CHECKSUM_NONE; - } else { - /* Only set up inner headers if we might be offloading - * inner checksum. - */ + + /* Set up inner headers if we are offloading inner checksum */ + if (skb->ip_summed == CHECKSUM_PARTIAL) { skb_reset_inner_headers(skb); skb->encapsulation = 1; } @@ -122,15 +121,15 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, uh->check = ~csum_fold((__force __wsum) ((__force u32)uh->check + (__force u32)delta)); - if (offload_csum) { - skb->ip_summed = CHECKSUM_PARTIAL; - skb->csum_start = skb_transport_header(skb) - skb->head; - skb->csum_offset = offsetof(struct udphdr, check); - } else { - uh->check = gso_make_checksum(skb, ~uh->check); + if (skb->encapsulation || !offload_csum) { + uh->check = gso_make_checksum(skb, ~uh->check); if (uh->check == 0) uh->check = CSUM_MANGLED_0; + } else { + skb->ip_summed = CHECKSUM_PARTIAL; + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct udphdr, check); } } while ((skb = skb->next)); out: -- cgit From dbef491ebe7f3a4fb1b9111878b86a426fd540b7 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:28:20 -0800 Subject: udp: Use uh->len instead of skb->len to compute checksum in segmentation The segmentation code was having to do a bunch of work to pull the skb->len and strip the udp header offset before the value could be used to adjust the checksum. Instead of doing all this work we can just use the value that goes into uh->len since that is the correct value with the correct byte order that we need anyway. By using this value we can save ourselves a bunch of pain as there is no need to do multiple byte swaps. Signed-off-by: Alexander Duyck Acked-by: Tom Herbert Signed-off-by: David S. Miller --- net/ipv4/udp_offload.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 9e4816fc9927..56c4c8b88b28 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -32,20 +32,23 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t features), __be16 new_protocol, bool is_ipv6) { + int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); struct sk_buff *segs = ERR_PTR(-EINVAL); bool remcsum, need_csum, offload_csum; + struct udphdr *uh = udp_hdr(skb); u16 mac_offset = skb->mac_header; - int mac_len = skb->mac_len; - int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); __be16 protocol = skb->protocol; + u16 mac_len = skb->mac_len; int udp_offset, outer_hlen; - unsigned int oldlen; - - oldlen = (u16)~skb->len; + u32 partial; if (unlikely(!pskb_may_pull(skb, tnl_hlen))) goto out; + /* adjust partial header checksum to negate old length */ + partial = (__force u32)uh->check + (__force u16)~uh->len; + + /* setup inner skb. */ skb->encapsulation = 0; __skb_pull(skb, tnl_hlen); skb_reset_mac_header(skb); @@ -89,9 +92,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, udp_offset = outer_hlen - tnl_hlen; skb = segs; do { - struct udphdr *uh; - int len; - __be32 delta; + __be16 len; if (remcsum) skb->ip_summed = CHECKSUM_NONE; @@ -105,22 +106,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb, skb->mac_len = mac_len; skb->protocol = protocol; - skb_push(skb, outer_hlen); + __skb_push(skb, outer_hlen); skb_reset_mac_header(skb); skb_set_network_header(skb, mac_len); skb_set_transport_header(skb, udp_offset); - len = skb->len - udp_offset; + len = htons(skb->len - udp_offset); uh = udp_hdr(skb); - uh->len = htons(len); + uh->len = len; if (!need_csum) continue; - delta = htonl(oldlen + len); - uh->check = ~csum_fold((__force __wsum) - ((__force u32)uh->check + - (__force u32)delta)); + ((__force u32)len + partial)); if (skb->encapsulation || !offload_csum) { uh->check = gso_make_checksum(skb, ~uh->check); -- cgit From f245d079c1d11dc6927e56f5a89dd566fef2a415 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 5 Feb 2016 15:28:26 -0800 Subject: net: Allow tunnels to use inner checksum offloads with outer checksums needed This patch enables us to use inner checksum offloads if provided by hardware with outer checksums computed by software. It basically reduces encap_hdr_csum to an advisory flag for now, but based on the fact that SCTP may be getting segmentation support before long I thought we may want to keep it as it is possible we may need to support CRC32c and 1's compliment checksum in the same packet at some point in the future. Signed-off-by: Alexander Duyck Acked-by: Tom Herbert Signed-off-by: David S. Miller --- net/core/skbuff.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 88262c82b96a..b0cce744e2a0 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3004,8 +3004,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, if (unlikely(!proto)) return ERR_PTR(-EINVAL); - csum = !head_skb->encap_hdr_csum && - !!can_checksum_protocol(features, proto); + csum = !!can_checksum_protocol(features, proto); headroom = skb_headroom(head_skb); pos = skb_headlen(head_skb); -- cgit From 6d9b6f424d0806e2a7f3e7f0a74170ec3ad30443 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sun, 7 Feb 2016 10:56:25 +0530 Subject: bonding: Return correct error code The return value of kzalloc on failure of allocation of memory should be -ENOMEM and not -1. Found using Coccinelle. A simplified version of the semantic patch used is: // @@ expression *e; @@ e = kzalloc(...); if (e == NULL) { ... return - -1 + -ENOMEM ; } // The single call site only checks that the return value is not 0, hence no change is required at the call site. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: David S. Miller --- drivers/net/bonding/bond_alb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index bb9e9fc45e1b..c5ac160a8ae9 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -159,7 +159,7 @@ static int tlb_initialize(struct bonding *bond) new_hashtbl = kzalloc(size, GFP_KERNEL); if (!new_hashtbl) - return -1; + return -ENOMEM; spin_lock_bh(&bond->mode_lock); -- cgit From f48e72318aa6f6ac792eaf74f3b77491a5c43891 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 9 Feb 2016 22:04:47 -0800 Subject: rds: duplicate include net/tcp.h Duplicate include detected. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/rds/tcp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/rds/tcp.c b/net/rds/tcp.c index 9d6ddbacd875..ad60299b088b 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "rds.h" #include "tcp.h" -- cgit From 40d29af05703555b03c689e5cecc34bdea28fa89 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 9 Feb 2016 22:07:29 -0800 Subject: vxlan: udp_tunnel duplicate include net/udp_tunnel.h Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 65f52472a52c..ebf57d90d295 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -42,7 +42,7 @@ #include #include #include -#include + #if IS_ENABLED(CONFIG_IPV6) #include #include -- cgit From 809dc75e9b82fcae9c3c48b4eec4708c005259f3 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 9 Feb 2016 22:11:27 -0800 Subject: vrf: duplicate include of rtnetlink.h Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/vrf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 76e1fc9d8748..9ce088bb28ab 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include -- cgit From 4456ed04ea44b800d691b18c14a68ec9894d2aca Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Sun, 7 Feb 2016 23:27:55 +0200 Subject: ethtool: future-proof interface for speed extensions Many virtual and not quite virtual devices allow any speed to be set through ethtool. In particular, this applies to the virtio-net devices. Document this fact to make sure people don't assume the enum lists all possible values. Reserve values greater than INT_MAX for future extension and to avoid conflict with SPEED_UNKNOWN. Signed-off-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 5e0940dcbfe8..4345f80a2e33 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -31,7 +31,7 @@ * physical connectors and other link features that are * advertised through autonegotiation or enabled for * auto-detection. - * @speed: Low bits of the speed + * @speed: Low bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN * @duplex: Duplex mode; one of %DUPLEX_* * @port: Physical connector type; one of %PORT_* * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not @@ -47,7 +47,7 @@ * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. * @maxrxpkt: Historically used to report RX IRQ coalescing; now * obsoleted by &struct ethtool_coalesce. Read-only; deprecated. - * @speed_hi: High bits of the speed + * @speed_hi: High bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of * %ETH_TP_MDI_*. If the status is unknown or not applicable, the * value will be %ETH_TP_MDI_INVALID. Read-only. @@ -1359,7 +1359,7 @@ enum ethtool_sfeatures_retval_bits { * it was forced up into this mode or autonegotiated. */ -/* The forced speed, 10Mb, 100Mb, gigabit, [2.5|5|10|20|25|40|50|56|100]GbE. */ +/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal. */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 -- cgit From 4a92602aa1cd5bbaeedbd9536ff992f7d26fe9d1 Mon Sep 17 00:00:00 2001 From: Tycho Andersen Date: Fri, 5 Feb 2016 09:20:52 -0700 Subject: openvswitch: allow management from inside user namespaces Operations with the GENL_ADMIN_PERM flag fail permissions checks because this flag means we call netlink_capable, which uses the init user ns. Instead, let's introduce a new flag, GENL_UNS_ADMIN_PERM for operations which should be allowed inside a user namespace. The motivation for this is to be able to run openvswitch in unprivileged containers. I've tested this and it seems to work, but I really have no idea about the security consequences of this patch, so thoughts would be much appreciated. v2: use the GENL_UNS_ADMIN_PERM flag instead of a check in each function v3: use separate ifs for UNS_ADMIN_PERM and ADMIN_PERM, instead of one massive one Reported-by: James Page Signed-off-by: Tycho Andersen CC: Eric Biederman CC: Pravin Shelar CC: Justin Pettit CC: "David S. Miller" Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- include/uapi/linux/genetlink.h | 1 + net/netlink/genetlink.c | 4 ++++ net/openvswitch/datapath.c | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h index c3363ba1ae05..5512c90af7e3 100644 --- a/include/uapi/linux/genetlink.h +++ b/include/uapi/linux/genetlink.h @@ -21,6 +21,7 @@ struct genlmsghdr { #define GENL_CMD_CAP_DO 0x02 #define GENL_CMD_CAP_DUMP 0x04 #define GENL_CMD_CAP_HASPOL 0x08 +#define GENL_UNS_ADMIN_PERM 0x10 /* * List of reserved static generic netlink identifiers: diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index f830326b3b1d..0ffd721126e7 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -580,6 +580,10 @@ static int genl_family_rcv_msg(struct genl_family *family, !netlink_capable(skb, CAP_NET_ADMIN)) return -EPERM; + if ((ops->flags & GENL_UNS_ADMIN_PERM) && + !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) { int rc; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index deadfdab1bc3..d6f7fe92744a 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -654,7 +654,7 @@ static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = { static const struct genl_ops dp_packet_genl_ops[] = { { .cmd = OVS_PACKET_CMD_EXECUTE, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = packet_policy, .doit = ovs_packet_cmd_execute } @@ -1391,12 +1391,12 @@ static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = { static const struct genl_ops dp_flow_genl_ops[] = { { .cmd = OVS_FLOW_CMD_NEW, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = flow_policy, .doit = ovs_flow_cmd_new }, { .cmd = OVS_FLOW_CMD_DEL, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = flow_policy, .doit = ovs_flow_cmd_del }, @@ -1407,7 +1407,7 @@ static const struct genl_ops dp_flow_genl_ops[] = { .dumpit = ovs_flow_cmd_dump }, { .cmd = OVS_FLOW_CMD_SET, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = flow_policy, .doit = ovs_flow_cmd_set, }, @@ -1777,12 +1777,12 @@ static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = { static const struct genl_ops dp_datapath_genl_ops[] = { { .cmd = OVS_DP_CMD_NEW, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = datapath_policy, .doit = ovs_dp_cmd_new }, { .cmd = OVS_DP_CMD_DEL, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = datapath_policy, .doit = ovs_dp_cmd_del }, @@ -1793,7 +1793,7 @@ static const struct genl_ops dp_datapath_genl_ops[] = { .dumpit = ovs_dp_cmd_dump }, { .cmd = OVS_DP_CMD_SET, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = datapath_policy, .doit = ovs_dp_cmd_set, }, @@ -2158,12 +2158,12 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = { static const struct genl_ops dp_vport_genl_ops[] = { { .cmd = OVS_VPORT_CMD_NEW, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = vport_policy, .doit = ovs_vport_cmd_new }, { .cmd = OVS_VPORT_CMD_DEL, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = vport_policy, .doit = ovs_vport_cmd_del }, @@ -2174,7 +2174,7 @@ static const struct genl_ops dp_vport_genl_ops[] = { .dumpit = ovs_vport_cmd_dump }, { .cmd = OVS_VPORT_CMD_SET, - .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ + .flags = GENL_UNS_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = vport_policy, .doit = ovs_vport_cmd_set, }, -- cgit From e6515203202a913816abb3fb808e71e3a2a0967e Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 10 Feb 2016 10:08:54 +0530 Subject: net: hamradio: baycom_ser_fdx: Replace timeval with timespec64 32 bit systems using 'struct timeval' will break in the year 2038, so we replace the code appropriately. However, this driver is not broken in 2038 since we are only using microseconds portion of the time. This patch replaces 'struct timeval' with 'struct timespec64'. We only need to find elapsed microseconds rather than absolute time, so it's better to use monotonic time, so using ktime_get_ts64() makes the code more efficient and more robust against concurrent settimeofday() calls. Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Arnd Bergmann Reviewed-by: Thomas Sailer Signed-off-by: David S. Miller --- drivers/net/hamradio/baycom_ser_fdx.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c index 636b65c66d49..7b916d5b14b9 100644 --- a/drivers/net/hamradio/baycom_ser_fdx.c +++ b/drivers/net/hamradio/baycom_ser_fdx.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #include @@ -228,14 +229,15 @@ static inline unsigned int hweight8(unsigned int w) /* --------------------------------------------------------------------- */ -static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timeval *tv, unsigned char curs) +static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timespec64 *ts, unsigned char curs) { int timediff; int bdus8 = bc->baud_us >> 3; int bdus4 = bc->baud_us >> 2; int bdus2 = bc->baud_us >> 1; - timediff = 1000000 + tv->tv_usec - bc->modem.ser12.pll_time; + timediff = 1000000 + ts->tv_nsec / NSEC_PER_USEC - + bc->modem.ser12.pll_time; while (timediff >= 500000) timediff -= 1000000; while (timediff >= bdus2) { @@ -287,7 +289,7 @@ static irqreturn_t ser12_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; struct baycom_state *bc = netdev_priv(dev); - struct timeval tv; + struct timespec64 ts; unsigned char iir, msr; unsigned int txcount = 0; @@ -297,7 +299,7 @@ static irqreturn_t ser12_interrupt(int irq, void *dev_id) if ((iir = inb(IIR(dev->base_addr))) & 1) return IRQ_NONE; /* get current time */ - do_gettimeofday(&tv); + ktime_get_ts64(&ts); msr = inb(MSR(dev->base_addr)); /* delta DCD */ if ((msr & 8) && bc->opt_dcd) @@ -340,7 +342,7 @@ static irqreturn_t ser12_interrupt(int irq, void *dev_id) } iir = inb(IIR(dev->base_addr)); } while (!(iir & 1)); - ser12_rx(dev, bc, &tv, msr & 0x10); /* CTS */ + ser12_rx(dev, bc, &ts, msr & 0x10); /* CTS */ if (bc->modem.ptt && txcount) { if (bc->modem.ser12.txshreg <= 1) { bc->modem.ser12.txshreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv); -- cgit From 3e2a5e1539064329f5f6888274600841ad6f87bd Mon Sep 17 00:00:00 2001 From: Sergio Prado Date: Tue, 9 Feb 2016 12:07:16 -0200 Subject: net: macb: add wake-on-lan support via magic packet Tested on Acqua A5 SoM (http://www.acmesystems.it/acqua). Signed-off-by: Sergio Prado Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/macb.txt | 2 + drivers/net/ethernet/cadence/macb.c | 67 +++++++++++++++++++++++--- drivers/net/ethernet/cadence/macb.h | 4 ++ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/net/macb.txt b/Documentation/devicetree/bindings/net/macb.txt index d2e243b1ec0e..c6b1cb5ffa87 100644 --- a/Documentation/devicetree/bindings/net/macb.txt +++ b/Documentation/devicetree/bindings/net/macb.txt @@ -25,6 +25,8 @@ Required properties: Optional properties for PHY child node: - reset-gpios : Should specify the gpio for phy reset +- cdns,magic-packet : If present, indicates that the hardware supports waking + up via magic packet. Examples: diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 50c94104f19c..69af049e55a8 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -58,6 +58,9 @@ #define GEM_MTU_MIN_SIZE 68 +#define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) +#define MACB_WOL_ENABLED (0x1 << 1) + /* * Graceful stop timeouts in us. We should allow up to * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions) @@ -2124,6 +2127,39 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs, } } +static void macb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct macb *bp = netdev_priv(netdev); + + wol->supported = 0; + wol->wolopts = 0; + + if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) { + wol->supported = WAKE_MAGIC; + + if (bp->wol & MACB_WOL_ENABLED) + wol->wolopts |= WAKE_MAGIC; + } +} + +static int macb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct macb *bp = netdev_priv(netdev); + + if (!(bp->wol & MACB_WOL_HAS_MAGIC_PACKET) || + (wol->wolopts & ~WAKE_MAGIC)) + return -EOPNOTSUPP; + + if (wol->wolopts & WAKE_MAGIC) + bp->wol |= MACB_WOL_ENABLED; + else + bp->wol &= ~MACB_WOL_ENABLED; + + device_set_wakeup_enable(&bp->pdev->dev, bp->wol & MACB_WOL_ENABLED); + + return 0; +} + static const struct ethtool_ops macb_ethtool_ops = { .get_settings = macb_get_settings, .set_settings = macb_set_settings, @@ -2131,6 +2167,8 @@ static const struct ethtool_ops macb_ethtool_ops = { .get_regs = macb_get_regs, .get_link = ethtool_op_get_link, .get_ts_info = ethtool_op_get_ts_info, + .get_wol = macb_get_wol, + .set_wol = macb_set_wol, }; static const struct ethtool_ops gem_ethtool_ops = { @@ -2890,6 +2928,11 @@ static int macb_probe(struct platform_device *pdev) if (macb_config) bp->jumbo_max_len = macb_config->jumbo_max_len; + bp->wol = 0; + if (of_get_property(np, "cdns,magic-packet", NULL)) + bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; + device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET); + spin_lock_init(&bp->lock); /* setup capabilities */ @@ -3006,9 +3049,15 @@ static int __maybe_unused macb_suspend(struct device *dev) netif_carrier_off(netdev); netif_device_detach(netdev); - clk_disable_unprepare(bp->tx_clk); - clk_disable_unprepare(bp->hclk); - clk_disable_unprepare(bp->pclk); + if (bp->wol & MACB_WOL_ENABLED) { + macb_writel(bp, IER, MACB_BIT(WOL)); + macb_writel(bp, WOL, MACB_BIT(MAG)); + enable_irq_wake(bp->queues[0].irq); + } else { + clk_disable_unprepare(bp->tx_clk); + clk_disable_unprepare(bp->hclk); + clk_disable_unprepare(bp->pclk); + } return 0; } @@ -3019,9 +3068,15 @@ static int __maybe_unused macb_resume(struct device *dev) struct net_device *netdev = platform_get_drvdata(pdev); struct macb *bp = netdev_priv(netdev); - clk_prepare_enable(bp->pclk); - clk_prepare_enable(bp->hclk); - clk_prepare_enable(bp->tx_clk); + if (bp->wol & MACB_WOL_ENABLED) { + macb_writel(bp, IDR, MACB_BIT(WOL)); + macb_writel(bp, WOL, 0); + disable_irq_wake(bp->queues[0].irq); + } else { + clk_prepare_enable(bp->pclk); + clk_prepare_enable(bp->hclk); + clk_prepare_enable(bp->tx_clk); + } netif_device_attach(netdev); diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 0d4ecfcd60b7..9ba416d5afff 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -312,6 +312,8 @@ #define MACB_PFR_SIZE 1 #define MACB_PTZ_OFFSET 13 /* Enable pause time zero interrupt */ #define MACB_PTZ_SIZE 1 +#define MACB_WOL_OFFSET 14 /* Enable wake-on-lan interrupt */ +#define MACB_WOL_SIZE 1 /* Bitfields in MAN */ #define MACB_DATA_OFFSET 0 /* data */ @@ -842,6 +844,8 @@ struct macb { unsigned int rx_frm_len_mask; unsigned int jumbo_max_len; + + u32 wol; }; static inline bool macb_is_gem(struct macb *bp) -- cgit From 1e2a8868e0541b7d8870781b714d74ac7cad9a6a Mon Sep 17 00:00:00 2001 From: Zhang Shengju Date: Tue, 9 Feb 2016 10:37:46 +0000 Subject: bonding: use return instead of goto Replace 'goto' with 'return' to remove unnecessary check at label: err_undo_flags. The reason is that 'err_undo_flags' do two things for the first slave device: 1.revert bond mac address if it is set by the slave device. 2.revert bond device type if it's not ARPHRD_ETHER. It's not necessary for the following three places, they changed neither bond mac address nor type. It's straightforward to return directly. Signed-off-by: Zhang Shengju Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 705cb0198faa..45bdd87d6b7a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1379,8 +1379,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) if (slave_dev->flags & IFF_UP) { netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n", slave_dev->name); - res = -EPERM; - goto err_undo_flags; + return -EPERM; } /* set bonding device ether type by slave - bonding netdevices are @@ -1400,8 +1399,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = notifier_to_errno(res); if (res) { netdev_err(bond_dev, "refused to change device type\n"); - res = -EBUSY; - goto err_undo_flags; + return -EBUSY; } /* Flush unicast and multicast addresses */ @@ -1421,8 +1419,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) } else if (bond_dev->type != slave_dev->type) { netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n", slave_dev->name, slave_dev->type, bond_dev->type); - res = -EINVAL; - goto err_undo_flags; + return -EINVAL; } if (slave_ops->ndo_set_mac_address == NULL) { -- cgit From 815c52700746cdcc0874a33390bac334a4b90107 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Mon, 8 Feb 2016 23:29:21 +0200 Subject: igmp: Namespaceify igmp_max_memberships sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/linux/igmp.h | 1 - include/net/netns/ipv4.h | 2 ++ net/ipv4/igmp.c | 4 +--- net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp_ipv4.c | 2 ++ 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 9c9de11549a7..57d6d06ce0b3 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -38,7 +38,6 @@ static inline struct igmpv3_query * } extern int sysctl_igmp_llm_reports; -extern int sysctl_igmp_max_memberships; extern int sysctl_igmp_max_msf; extern int sysctl_igmp_qrv; diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 4d6ec3f6fafe..759cf624eec2 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -108,6 +108,8 @@ struct netns_ipv4 { int sysctl_tcp_fin_timeout; unsigned int sysctl_tcp_notsent_lowat; + int sysctl_igmp_max_memberships; + struct ping_group_range ping_group_range; atomic_t dev_addr_genid; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 05e4cba14162..5b86257c9d6b 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -107,7 +107,6 @@ #include #endif -#define IP_MAX_MEMBERSHIPS 20 #define IP_MAX_MSF 10 /* IGMP reports for link-local multicast groups are enabled by default */ @@ -1727,7 +1726,6 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) /* * Join a socket to a group */ -int sysctl_igmp_max_memberships __read_mostly = IP_MAX_MEMBERSHIPS; int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF; #ifdef CONFIG_IP_MULTICAST int sysctl_igmp_qrv __read_mostly = IGMP_QUERY_ROBUSTNESS_VARIABLE; @@ -2074,7 +2072,7 @@ int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr) count++; } err = -ENOBUFS; - if (count >= sysctl_igmp_max_memberships) + if (count >= net->ipv4.sysctl_igmp_max_memberships) goto done; iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL); if (!iml) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 44bb59824267..6ea3dbb96db4 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -367,13 +367,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "igmp_max_memberships", - .data = &sysctl_igmp_max_memberships, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, { .procname = "igmp_max_msf", .data = &sysctl_igmp_max_msf, @@ -871,6 +864,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "igmp_max_memberships", + .data = &init_net.ipv4.sysctl_igmp_max_memberships, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { .procname = "tcp_keepalive_time", .data = &init_net.ipv4.sysctl_tcp_keepalive_time, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3f872a6bc274..4b203789900b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2399,6 +2399,8 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT; net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX; + net->ipv4.sysctl_igmp_max_memberships = 20; + return 0; fail: tcp_sk_exit(net); -- cgit From 166b6b2d6f01be67a83b87ab5c91350a68b17115 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Mon, 8 Feb 2016 23:29:22 +0200 Subject: igmp: Namespaceify igmp_max_msf sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/linux/igmp.h | 1 - include/net/netns/ipv4.h | 1 + net/ipv4/igmp.c | 5 +---- net/ipv4/ip_sockglue.c | 5 +++-- net/ipv4/sysctl_net_ipv4.c | 14 +++++++------- net/ipv4/tcp_ipv4.c | 1 + 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 57d6d06ce0b3..a91ec9f575e7 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -38,7 +38,6 @@ static inline struct igmpv3_query * } extern int sysctl_igmp_llm_reports; -extern int sysctl_igmp_max_msf; extern int sysctl_igmp_qrv; struct ip_sf_socklist { diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 759cf624eec2..522a2cfe1ad9 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -109,6 +109,7 @@ struct netns_ipv4 { unsigned int sysctl_tcp_notsent_lowat; int sysctl_igmp_max_memberships; + int sysctl_igmp_max_msf; struct ping_group_range ping_group_range; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 5b86257c9d6b..6da2e467b63c 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -107,8 +107,6 @@ #include #endif -#define IP_MAX_MSF 10 - /* IGMP reports for link-local multicast groups are enabled by default */ int sysctl_igmp_llm_reports __read_mostly = 1; @@ -1726,7 +1724,6 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) /* * Join a socket to a group */ -int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF; #ifdef CONFIG_IP_MULTICAST int sysctl_igmp_qrv __read_mostly = IGMP_QUERY_ROBUSTNESS_VARIABLE; #endif @@ -2244,7 +2241,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct } /* else, add a new source to the filter */ - if (psl && psl->sl_count >= sysctl_igmp_max_msf) { + if (psl && psl->sl_count >= net->ipv4.sysctl_igmp_max_msf) { err = -ENOBUFS; goto done; } diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 5f73a7c03e27..92808f147ef5 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -571,6 +571,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen) { struct inet_sock *inet = inet_sk(sk); + struct net *net = sock_net(sk); int val = 0, err; bool needs_rtnl = setsockopt_needs_rtnl(optname); @@ -910,7 +911,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, } /* numsrc >= (1G-4) overflow in 32 bits */ if (msf->imsf_numsrc >= 0x3ffffffcU || - msf->imsf_numsrc > sysctl_igmp_max_msf) { + msf->imsf_numsrc > net->ipv4.sysctl_igmp_max_msf) { kfree(msf); err = -ENOBUFS; break; @@ -1065,7 +1066,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, /* numsrc >= (4G-140)/128 overflow in 32 bits */ if (gsf->gf_numsrc >= 0x1ffffff || - gsf->gf_numsrc > sysctl_igmp_max_msf) { + gsf->gf_numsrc > net->ipv4.sysctl_igmp_max_msf) { err = -ENOBUFS; goto mc_msf_out; } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 6ea3dbb96db4..225659a02cf2 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -367,13 +367,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { - .procname = "igmp_max_msf", - .data = &sysctl_igmp_max_msf, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, #ifdef CONFIG_IP_MULTICAST { .procname = "igmp_qrv", @@ -871,6 +864,13 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "igmp_max_msf", + .data = &init_net.ipv4.sysctl_igmp_max_msf, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { .procname = "tcp_keepalive_time", .data = &init_net.ipv4.sysctl_tcp_keepalive_time, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4b203789900b..055d8a9a0c61 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2400,6 +2400,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX; net->ipv4.sysctl_igmp_max_memberships = 20; + net->ipv4.sysctl_igmp_max_msf = 10; return 0; fail: -- cgit From 87a8a2ae65b7721893c7922f963502be8fa01c94 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Tue, 9 Feb 2016 00:13:50 +0200 Subject: igmp: Namespaceify igmp_llm_reports sysctl knob This was initially introduced in df2cf4a78e488d26 ("IGMP: Inhibit reports for local multicast groups") by defining the sysctl in the ipv4_net_table array, however it was never implemented to be namespace aware. Fix this by changing the code accordingly. Signed-off-by: David S. Miller --- include/linux/igmp.h | 1 - include/net/netns/ipv4.h | 1 + net/ipv4/igmp.c | 26 +++++++++++++++----------- net/ipv4/sysctl_net_ipv4.c | 2 +- net/ipv4/tcp_ipv4.c | 2 ++ 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index a91ec9f575e7..c683f4bf642b 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -37,7 +37,6 @@ static inline struct igmpv3_query * return (struct igmpv3_query *)skb_transport_header(skb); } -extern int sysctl_igmp_llm_reports; extern int sysctl_igmp_qrv; struct ip_sf_socklist { diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 522a2cfe1ad9..cbbf8115e8a7 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -110,6 +110,7 @@ struct netns_ipv4 { int sysctl_igmp_max_memberships; int sysctl_igmp_max_msf; + int sysctl_igmp_llm_reports; struct ping_group_range ping_group_range; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 6da2e467b63c..2e22ee0efc98 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -107,9 +107,6 @@ #include #endif -/* IGMP reports for link-local multicast groups are enabled by default */ -int sysctl_igmp_llm_reports __read_mostly = 1; - #ifdef CONFIG_IP_MULTICAST /* Parameter names and values are taken from igmp-v2-06 draft */ @@ -430,6 +427,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted) { struct net_device *dev = pmc->interface->dev; + struct net *net = dev_net(dev); struct igmpv3_report *pih; struct igmpv3_grec *pgr = NULL; struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list; @@ -437,7 +435,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, if (pmc->multiaddr == IGMP_ALL_HOSTS) return skb; - if (ipv4_is_local_multicast(pmc->multiaddr) && !sysctl_igmp_llm_reports) + if (ipv4_is_local_multicast(pmc->multiaddr) && !net->ipv4.sysctl_igmp_llm_reports) return skb; isquery = type == IGMPV3_MODE_IS_INCLUDE || @@ -540,6 +538,7 @@ empty_source: static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc) { struct sk_buff *skb = NULL; + struct net *net = dev_net(in_dev->dev); int type; if (!pmc) { @@ -548,7 +547,7 @@ static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc) if (pmc->multiaddr == IGMP_ALL_HOSTS) continue; if (ipv4_is_local_multicast(pmc->multiaddr) && - !sysctl_igmp_llm_reports) + !net->ipv4.sysctl_igmp_llm_reports) continue; spin_lock_bh(&pmc->lock); if (pmc->sfcount[MCAST_EXCLUDE]) @@ -684,7 +683,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, if (type == IGMPV3_HOST_MEMBERSHIP_REPORT) return igmpv3_send_report(in_dev, pmc); - if (ipv4_is_local_multicast(group) && !sysctl_igmp_llm_reports) + if (ipv4_is_local_multicast(group) && !net->ipv4.sysctl_igmp_llm_reports) return 0; if (type == IGMP_HOST_LEAVE_MESSAGE) @@ -855,12 +854,13 @@ static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs) static bool igmp_heard_report(struct in_device *in_dev, __be32 group) { struct ip_mc_list *im; + struct net *net = dev_net(in_dev->dev); /* Timers are only set for non-local groups */ if (group == IGMP_ALL_HOSTS) return false; - if (ipv4_is_local_multicast(group) && !sysctl_igmp_llm_reports) + if (ipv4_is_local_multicast(group) && !net->ipv4.sysctl_igmp_llm_reports) return false; rcu_read_lock(); @@ -884,6 +884,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, __be32 group = ih->group; int max_delay; int mark = 0; + struct net *net = dev_net(in_dev->dev); if (len == 8) { @@ -969,7 +970,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, if (im->multiaddr == IGMP_ALL_HOSTS) continue; if (ipv4_is_local_multicast(im->multiaddr) && - !sysctl_igmp_llm_reports) + !net->ipv4.sysctl_igmp_llm_reports) continue; spin_lock_bh(&im->lock); if (im->tm_running) @@ -1184,6 +1185,7 @@ static void igmp_group_dropped(struct ip_mc_list *im) { struct in_device *in_dev = im->interface; #ifdef CONFIG_IP_MULTICAST + struct net *net = dev_net(in_dev->dev); int reporter; #endif @@ -1195,7 +1197,7 @@ static void igmp_group_dropped(struct ip_mc_list *im) #ifdef CONFIG_IP_MULTICAST if (im->multiaddr == IGMP_ALL_HOSTS) return; - if (ipv4_is_local_multicast(im->multiaddr) && !sysctl_igmp_llm_reports) + if (ipv4_is_local_multicast(im->multiaddr) && !net->ipv4.sysctl_igmp_llm_reports) return; reporter = im->reporter; @@ -1220,6 +1222,7 @@ static void igmp_group_dropped(struct ip_mc_list *im) static void igmp_group_added(struct ip_mc_list *im) { struct in_device *in_dev = im->interface; + struct net *net = dev_net(in_dev->dev); if (im->loaded == 0) { im->loaded = 1; @@ -1229,7 +1232,7 @@ static void igmp_group_added(struct ip_mc_list *im) #ifdef CONFIG_IP_MULTICAST if (im->multiaddr == IGMP_ALL_HOSTS) return; - if (ipv4_is_local_multicast(im->multiaddr) && !sysctl_igmp_llm_reports) + if (ipv4_is_local_multicast(im->multiaddr) && !net->ipv4.sysctl_igmp_llm_reports) return; if (in_dev->dead) @@ -1530,6 +1533,7 @@ static void ip_mc_rejoin_groups(struct in_device *in_dev) #ifdef CONFIG_IP_MULTICAST struct ip_mc_list *im; int type; + struct net *net = dev_net(in_dev->dev); ASSERT_RTNL(); @@ -1537,7 +1541,7 @@ static void ip_mc_rejoin_groups(struct in_device *in_dev) if (im->multiaddr == IGMP_ALL_HOSTS) continue; if (ipv4_is_local_multicast(im->multiaddr) && - !sysctl_igmp_llm_reports) + !net->ipv4.sysctl_igmp_llm_reports) continue; /* a failover is happening and switches diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 225659a02cf2..fc40fa1303d3 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -852,7 +852,7 @@ static struct ctl_table ipv4_net_table[] = { }, { .procname = "igmp_link_local_mcast_reports", - .data = &sysctl_igmp_llm_reports, + .data = &init_net.ipv4.sysctl_igmp_llm_reports, .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 055d8a9a0c61..6c3c1d5232c6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2401,6 +2401,8 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_igmp_max_memberships = 20; net->ipv4.sysctl_igmp_max_msf = 10; + /* IGMP reports for link-local multicast groups are enabled by default */ + net->ipv4.sysctl_igmp_llm_reports = 1; return 0; fail: -- cgit From 165094afcee79e4d5b6e94032a5d3be157460b4a Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Mon, 8 Feb 2016 23:29:24 +0200 Subject: igmp: Namespacify igmp_qrv sysctl knob Signed-off-by: Nikolay Borisov Signed-off-by: David S. Miller --- include/linux/igmp.h | 2 -- include/net/netns/ipv4.h | 1 + net/ipv4/igmp.c | 29 +++++++++++++++++------------ net/ipv4/sysctl_net_ipv4.c | 20 ++++++++++---------- net/ipv4/tcp_ipv4.c | 1 + 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index c683f4bf642b..12f6fba6d21a 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -37,8 +37,6 @@ static inline struct igmpv3_query * return (struct igmpv3_query *)skb_transport_header(skb); } -extern int sysctl_igmp_qrv; - struct ip_sf_socklist { unsigned int sl_max; unsigned int sl_count; diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index cbbf8115e8a7..848fe8056534 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -111,6 +111,7 @@ struct netns_ipv4 { int sysctl_igmp_max_memberships; int sysctl_igmp_max_msf; int sysctl_igmp_llm_reports; + int sysctl_igmp_qrv; struct ping_group_range ping_group_range; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 2e22ee0efc98..7c95335bf85e 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -762,9 +762,10 @@ static void igmp_ifc_timer_expire(unsigned long data) static void igmp_ifc_event(struct in_device *in_dev) { + struct net *net = dev_net(in_dev->dev); if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) return; - in_dev->mr_ifc_count = in_dev->mr_qrv ?: sysctl_igmp_qrv; + in_dev->mr_ifc_count = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; igmp_ifc_start_timer(in_dev, 1); } @@ -1086,6 +1087,7 @@ static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr) static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im) { struct ip_mc_list *pmc; + struct net *net = dev_net(in_dev->dev); /* this is an "ip_mc_list" for convenience; only the fields below * are actually used. In particular, the refcnt and users are not @@ -1100,7 +1102,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im) pmc->interface = im->interface; in_dev_hold(in_dev); pmc->multiaddr = im->multiaddr; - pmc->crcount = in_dev->mr_qrv ?: sysctl_igmp_qrv; + pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; pmc->sfmode = im->sfmode; if (pmc->sfmode == MCAST_INCLUDE) { struct ip_sf_list *psf; @@ -1245,7 +1247,7 @@ static void igmp_group_added(struct ip_mc_list *im) } /* else, v3 */ - im->crcount = in_dev->mr_qrv ?: sysctl_igmp_qrv; + im->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; igmp_ifc_event(in_dev); #endif } @@ -1314,6 +1316,7 @@ static void ip_mc_hash_remove(struct in_device *in_dev, void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) { struct ip_mc_list *im; + struct net *net = dev_net(in_dev->dev); ASSERT_RTNL(); @@ -1340,7 +1343,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) spin_lock_init(&im->lock); #ifdef CONFIG_IP_MULTICAST setup_timer(&im->timer, igmp_timer_expire, (unsigned long)im); - im->unsolicit_count = sysctl_igmp_qrv; + im->unsolicit_count = net->ipv4.sysctl_igmp_qrv; #endif im->next_rcu = in_dev->mc_list; @@ -1640,6 +1643,7 @@ void ip_mc_down(struct in_device *in_dev) void ip_mc_init_dev(struct in_device *in_dev) { + struct net *net = dev_net(in_dev->dev); ASSERT_RTNL(); #ifdef CONFIG_IP_MULTICAST @@ -1647,7 +1651,7 @@ void ip_mc_init_dev(struct in_device *in_dev) (unsigned long)in_dev); setup_timer(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire, (unsigned long)in_dev); - in_dev->mr_qrv = sysctl_igmp_qrv; + in_dev->mr_qrv = net->ipv4.sysctl_igmp_qrv; #endif spin_lock_init(&in_dev->mc_tomb_lock); @@ -1658,11 +1662,12 @@ void ip_mc_init_dev(struct in_device *in_dev) void ip_mc_up(struct in_device *in_dev) { struct ip_mc_list *pmc; + struct net *net = dev_net(in_dev->dev); ASSERT_RTNL(); #ifdef CONFIG_IP_MULTICAST - in_dev->mr_qrv = sysctl_igmp_qrv; + in_dev->mr_qrv = net->ipv4.sysctl_igmp_qrv; #endif ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS); @@ -1728,9 +1733,6 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr) /* * Join a socket to a group */ -#ifdef CONFIG_IP_MULTICAST -int sysctl_igmp_qrv __read_mostly = IGMP_QUERY_ROBUSTNESS_VARIABLE; -#endif static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, __be32 *psfsrc) @@ -1755,6 +1757,7 @@ static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) { #ifdef CONFIG_IP_MULTICAST struct in_device *in_dev = pmc->interface; + struct net *net = dev_net(in_dev->dev); #endif /* no more filters for this source */ @@ -1765,7 +1768,7 @@ static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, #ifdef CONFIG_IP_MULTICAST if (psf->sf_oldin && !IGMP_V1_SEEN(in_dev) && !IGMP_V2_SEEN(in_dev)) { - psf->sf_crcount = in_dev->mr_qrv ?: sysctl_igmp_qrv; + psf->sf_crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; psf->sf_next = pmc->tomb; pmc->tomb = psf; rv = 1; @@ -1823,12 +1826,13 @@ static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode, pmc->sfcount[MCAST_INCLUDE]) { #ifdef CONFIG_IP_MULTICAST struct ip_sf_list *psf; + struct net *net = dev_net(in_dev->dev); #endif /* filter mode change */ pmc->sfmode = MCAST_INCLUDE; #ifdef CONFIG_IP_MULTICAST - pmc->crcount = in_dev->mr_qrv ?: sysctl_igmp_qrv; + pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; in_dev->mr_ifc_count = pmc->crcount; for (psf = pmc->sources; psf; psf = psf->sf_next) psf->sf_crcount = 0; @@ -1995,6 +1999,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) { #ifdef CONFIG_IP_MULTICAST struct ip_sf_list *psf; + struct net *net = dev_net(pmc->interface->dev); in_dev = pmc->interface; #endif @@ -2006,7 +2011,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, #ifdef CONFIG_IP_MULTICAST /* else no filters; keep old mode for reports */ - pmc->crcount = in_dev->mr_qrv ?: sysctl_igmp_qrv; + pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; in_dev->mr_ifc_count = pmc->crcount; for (psf = pmc->sources; psf; psf = psf->sf_next) psf->sf_crcount = 0; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index fc40fa1303d3..b537338f5c97 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -367,16 +367,6 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, -#ifdef CONFIG_IP_MULTICAST - { - .procname = "igmp_qrv", - .data = &sysctl_igmp_qrv, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec_minmax, - .extra1 = &one - }, -#endif { .procname = "inet_peer_threshold", .data = &inet_peer_threshold, @@ -871,6 +861,16 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, +#ifdef CONFIG_IP_MULTICAST + { + .procname = "igmp_qrv", + .data = &init_net.ipv4.sysctl_igmp_qrv, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &one + }, +#endif { .procname = "tcp_keepalive_time", .data = &init_net.ipv4.sysctl_tcp_keepalive_time, diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 6c3c1d5232c6..ba5d0146e3f0 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2403,6 +2403,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_igmp_max_msf = 10; /* IGMP reports for link-local multicast groups are enabled by default */ net->ipv4.sysctl_igmp_llm_reports = 1; + net->ipv4.sysctl_igmp_qrv = 2; return 0; fail: -- cgit From a2127e400edd2258fda6d83fe8b10b878a3595d9 Mon Sep 17 00:00:00 2001 From: Aleksey Makarov Date: Thu, 11 Feb 2016 13:53:08 +0000 Subject: libata: support AHCI on OCTEON platform The OCTEON SATA controller is currently found on cn71XX devices. Acked-by: Arnd Bergmann Acked-by: Hans de Goede Acked-by: Rob Herring Signed-off-by: David Daney Signed-off-by: Vinita Gupta Signed-off-by: Aleksey Makarov Signed-off-by: Zubair Lutfullah Kakakhel Signed-off-by: Tejun Heo --- .../devicetree/bindings/ata/ahci-platform.txt | 1 + .../devicetree/bindings/mips/cavium/sata-uctl.txt | 42 +++++++++ arch/mips/include/asm/octeon/cvmx.h | 9 ++ drivers/ata/Kconfig | 9 ++ drivers/ata/Makefile | 1 + drivers/ata/ahci_octeon.c | 105 +++++++++++++++++++++ drivers/ata/ahci_platform.c | 1 + 7 files changed, 168 insertions(+) create mode 100644 Documentation/devicetree/bindings/mips/cavium/sata-uctl.txt create mode 100644 drivers/ata/ahci_octeon.c diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt index c2340eeeb97f..3d84dcae8475 100644 --- a/Documentation/devicetree/bindings/ata/ahci-platform.txt +++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt @@ -11,6 +11,7 @@ Required properties: - compatible : compatible string, one of: - "allwinner,sun4i-a10-ahci" - "hisilicon,hisi-ahci" + - "cavium,octeon-7130-ahci" - "ibm,476gtr-ahci" - "marvell,armada-380-ahci" - "snps,dwc-ahci" diff --git a/Documentation/devicetree/bindings/mips/cavium/sata-uctl.txt b/Documentation/devicetree/bindings/mips/cavium/sata-uctl.txt new file mode 100644 index 000000000000..3bd3c2f0b9b1 --- /dev/null +++ b/Documentation/devicetree/bindings/mips/cavium/sata-uctl.txt @@ -0,0 +1,42 @@ +* UCTL SATA controller glue + +UCTL is the bridge unit between the I/O interconnect (an internal bus) +and the SATA AHCI host controller (UAHC). It performs the following functions: + - provides interfaces for the applications to access the UAHC AHCI + registers on the CN71XX I/O space. + - provides a bridge for UAHC to fetch AHCI command table entries and data + buffers from Level 2 Cache. + - posts interrupts to the CIU. + - contains registers that: + - control the behavior of the UAHC + - control the clock/reset generation to UAHC + - control endian swapping for all UAHC registers and DMA accesses + +Properties: + +- compatible: "cavium,octeon-7130-sata-uctl" + + Compatibility with the cn7130 SOC. + +- reg: The base address of the UCTL register bank. + +- #address-cells, #size-cells, ranges and dma-ranges must be present and hold + suitable values to map all child nodes. + +Example: + + uctl@118006c000000 { + compatible = "cavium,octeon-7130-sata-uctl"; + reg = <0x11800 0x6c000000 0x0 0x100>; + ranges; /* Direct mapping */ + dma-ranges; + #address-cells = <2>; + #size-cells = <2>; + + sata: sata@16c0000000000 { + compatible = "cavium,octeon-7130-ahci"; + reg = <0x16c00 0x00000000 0x0 0x200>; + interrupt-parent = <&cibsata>; + interrupts = <2 4>; /* Bit: 2, level */ + }; + }; diff --git a/arch/mips/include/asm/octeon/cvmx.h b/arch/mips/include/asm/octeon/cvmx.h index 774bb45834cb..19e139c9f337 100644 --- a/arch/mips/include/asm/octeon/cvmx.h +++ b/arch/mips/include/asm/octeon/cvmx.h @@ -275,6 +275,11 @@ static inline void cvmx_write_csr(uint64_t csr_addr, uint64_t val) cvmx_read64(CVMX_MIO_BOOT_BIST_STAT); } +static inline void cvmx_writeq_csr(void __iomem *csr_addr, uint64_t val) +{ + cvmx_write_csr((__force uint64_t)csr_addr, val); +} + static inline void cvmx_write_io(uint64_t io_addr, uint64_t val) { cvmx_write64(io_addr, val); @@ -287,6 +292,10 @@ static inline uint64_t cvmx_read_csr(uint64_t csr_addr) return val; } +static inline uint64_t cvmx_readq_csr(void __iomem *csr_addr) +{ + return cvmx_read_csr((__force uint64_t) csr_addr); +} static inline void cvmx_send_single(uint64_t data) { diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 861643ea91b5..9c15828195df 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -151,6 +151,15 @@ config AHCI_MVEBU If unsure, say N. +config AHCI_OCTEON + tristate "Cavium Octeon Soc Serial ATA" + depends on SATA_AHCI_PLATFORM && CAVIUM_OCTEON_SOC + default y + help + This option enables support for Cavium Octeon SoC Serial ATA. + + If unsure, say N. + config AHCI_SUNXI tristate "Allwinner sunxi AHCI SATA support" depends on ARCH_SUNXI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index af45effac18c..18579521464e 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_AHCI_CEVA) += ahci_ceva.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_DA850) += ahci_da850.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_OCTEON) += ahci_octeon.o obj-$(CONFIG_AHCI_SUNXI) += ahci_sunxi.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_TEGRA) += ahci_tegra.o libahci.o libahci_platform.o diff --git a/drivers/ata/ahci_octeon.c b/drivers/ata/ahci_octeon.c new file mode 100644 index 000000000000..ea865fe953e1 --- /dev/null +++ b/drivers/ata/ahci_octeon.c @@ -0,0 +1,105 @@ +/* + * SATA glue for Cavium Octeon III SOCs. + * + * + * 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. + * + * Copyright (C) 2010-2015 Cavium Networks + * + */ + +#include +#include +#include +#include + +#include +#include + +#define CVMX_SATA_UCTL_SHIM_CFG 0xE8 + +#define SATA_UCTL_ENDIAN_MODE_BIG 1 +#define SATA_UCTL_ENDIAN_MODE_LITTLE 0 +#define SATA_UCTL_ENDIAN_MODE_MASK 3 + +#define SATA_UCTL_DMA_ENDIAN_MODE_SHIFT 8 +#define SATA_UCTL_CSR_ENDIAN_MODE_SHIFT 0 +#define SATA_UCTL_DMA_READ_CMD_SHIFT 12 + +static int ahci_octeon_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct resource *res; + void __iomem *base; + u64 cfg; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "Platform resource[0] is missing\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + cfg = cvmx_readq_csr(base + CVMX_SATA_UCTL_SHIM_CFG); + + cfg &= ~(SATA_UCTL_ENDIAN_MODE_MASK << SATA_UCTL_DMA_ENDIAN_MODE_SHIFT); + cfg &= ~(SATA_UCTL_ENDIAN_MODE_MASK << SATA_UCTL_CSR_ENDIAN_MODE_SHIFT); + +#ifdef __BIG_ENDIAN + cfg |= SATA_UCTL_ENDIAN_MODE_BIG << SATA_UCTL_DMA_ENDIAN_MODE_SHIFT; + cfg |= SATA_UCTL_ENDIAN_MODE_BIG << SATA_UCTL_CSR_ENDIAN_MODE_SHIFT; +#else + cfg |= SATA_UCTL_ENDIAN_MODE_LITTLE << SATA_UCTL_DMA_ENDIAN_MODE_SHIFT; + cfg |= SATA_UCTL_ENDIAN_MODE_LITTLE << SATA_UCTL_CSR_ENDIAN_MODE_SHIFT; +#endif + + cfg |= 1 << SATA_UCTL_DMA_READ_CMD_SHIFT; + + cvmx_writeq_csr(base + CVMX_SATA_UCTL_SHIM_CFG, cfg); + + if (!node) { + dev_err(dev, "no device node, failed to add octeon sata\n"); + return -ENODEV; + } + + ret = of_platform_populate(node, NULL, NULL, dev); + if (ret) { + dev_err(dev, "failed to add ahci-platform core\n"); + return ret; + } + + return 0; +} + +static int ahci_octeon_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id octeon_ahci_match[] = { + { .compatible = "cavium,octeon-7130-sata-uctl", }, + {}, +}; +MODULE_DEVICE_TABLE(of, octeon_ahci_match); + +static struct platform_driver ahci_octeon_driver = { + .probe = ahci_octeon_probe, + .remove = ahci_octeon_remove, + .driver = { + .name = "octeon-ahci", + .of_match_table = octeon_ahci_match, + }, +}; + +module_platform_driver(ahci_octeon_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Cavium, Inc. "); +MODULE_DESCRIPTION("Cavium Inc. sata config."); diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 04975b851c23..40442332bfa7 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -76,6 +76,7 @@ static const struct of_device_id ahci_of_match[] = { { .compatible = "ibm,476gtr-ahci", }, { .compatible = "snps,dwc-ahci", }, { .compatible = "hisilicon,hisi-ahci", }, + { .compatible = "cavium,octeon-7130-ahci", }, {}, }; MODULE_DEVICE_TABLE(of, ahci_of_match); -- cgit From d5df731ab804e0d917f44099bfeb88a5f1488a3d Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Wed, 10 Feb 2016 16:52:47 -0700 Subject: block: Initialize max_dev_sectors to 0 The new queue limit is not used by the majority of block drivers, and should be initialized to 0 for the driver's requested settings to be used. Signed-off-by: Keith Busch Acked-by: Martin K. Petersen Reviewed-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/blk-settings.c b/block/blk-settings.c index dd4973583978..c7bb666aafd1 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -91,8 +91,8 @@ void blk_set_default_limits(struct queue_limits *lim) lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK; lim->virt_boundary_mask = 0; lim->max_segment_size = BLK_MAX_SEGMENT_SIZE; - lim->max_sectors = lim->max_dev_sectors = lim->max_hw_sectors = - BLK_SAFE_MAX_SECTORS; + lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS; + lim->max_dev_sectors = 0; lim->chunk_sectors = 0; lim->max_write_same_sectors = 0; lim->max_discard_sectors = 0; -- cgit From 73e592f3bc2cdc68df9dbc92e681b61f9bc6c2bf Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 27 Jan 2016 20:14:00 +0100 Subject: ARM: 8504/1: __arch_xprod_64(): small optimization The tmp variable is used twice: first to pose as a register containing a value of zero, and then to provide a temporary register that initially is zero and get added some value. But somehow gcc decides to split those two usages in different registers. Example code: u64 div64const1000(u64 x) { u32 y = 1000; do_div(x, y); return x; } Result: div64const1000: push {r4, r5, r6, r7, lr} mov lr, #0 mov r6, r0 mov r7, r1 adr r5, .L8 ldrd r4, [r5] mov r1, lr umull r2, r3, r4, r6 cmn r2, r4 adcs r3, r3, r5 adc r2, lr, #0 umlal r3, r2, r5, r6 umlal r3, r1, r4, r7 mov r3, #0 adds r2, r1, r2 adc r3, r3, #0 umlal r2, r3, r5, r7 lsr r0, r2, #9 lsr r1, r3, #9 orr r0, r0, r3, lsl #23 pop {r4, r5, r6, r7, pc} .align 3 .L8: .word -1924145349 .word -2095944041 Full kernel build size: text data bss dec hex filename 13663814 1553940 351368 15569122 ed90e2 vmlinux Here the two instances of 'tmp' are assigned to r1 and lr. To avoid that, let's mark the first 'tmp' usage in __arch_xprod_64() with a "+r" constraint even if the register is not written to, so to create a dependency for the second usage with the effect of enforcing a single temporary register throughout. Result: div64const1000: push {r4, r5, r6, r7} movs r3, #0 adr r5, .L8 ldrd r4, [r5] umull r6, r7, r4, r0 cmn r6, r4 adcs r7, r7, r5 adc r6, r3, #0 umlal r7, r6, r5, r0 umlal r7, r3, r4, r1 mov r7, #0 adds r6, r3, r6 adc r7, r7, #0 umlal r6, r7, r5, r1 lsr r0, r6, #9 lsr r1, r7, #9 orr r0, r0, r7, lsl #23 pop {r4, r5, r6, r7} bx lr .align 3 .L8: .word -1924145349 .word -2095944041 text data bss dec hex filename 13663438 1553940 351368 15568746 ed8f6a vmlinux This time 'tmp' is assigned to r3 and used throughout. However, by being assigned to r3, that blocks usage of the r2-r3 double register slot for 64-bit values, forcing more registers to be spilled on the stack. Let's try to help it by forcing 'tmp' to the caller-saved ip register. Result: div64const1000: stmfd sp!, {r4, r5} mov ip, #0 adr r5, .L8 ldrd r4, [r5] umull r2, r3, r4, r0 cmn r2, r4 adcs r3, r3, r5 adc r2, ip, #0 umlal r3, r2, r5, r0 umlal r3, ip, r4, r1 mov r3, #0 adds r2, ip, r2 adc r3, r3, #0 umlal r2, r3, r5, r1 mov r0, r2, lsr #9 mov r1, r3, lsr #9 orr r0, r0, r3, asl #23 ldmfd sp!, {r4, r5} bx lr .align 3 .L8: .word -1924145349 .word -2095944041 text data bss dec hex filename 13662838 1553940 351368 15568146 ed8d12 vmlinux We could make the code marginally smaller yet by forcing 'tmp' to lr instead, but that would have a negative inpact on branch prediction for which "bx lr" is optimal. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/include/asm/div64.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/include/asm/div64.h b/arch/arm/include/asm/div64.h index e1f07764b0d6..7d919a9b32e5 100644 --- a/arch/arm/include/asm/div64.h +++ b/arch/arm/include/asm/div64.h @@ -74,7 +74,7 @@ static inline uint32_t __div64_32(uint64_t *n, uint32_t base) static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias) { unsigned long long res; - unsigned int tmp = 0; + register unsigned int tmp asm("ip") = 0; if (!bias) { asm ( "umull %Q0, %R0, %Q1, %Q2\n\t" @@ -90,12 +90,12 @@ static inline uint64_t __arch_xprod_64(uint64_t m, uint64_t n, bool bias) : "r" (m), "r" (n) : "cc"); } else { - asm ( "umull %Q0, %R0, %Q1, %Q2\n\t" - "cmn %Q0, %Q1\n\t" - "adcs %R0, %R0, %R1\n\t" - "adc %Q0, %3, #0" - : "=&r" (res) - : "r" (m), "r" (n), "r" (tmp) + asm ( "umull %Q0, %R0, %Q2, %Q3\n\t" + "cmn %Q0, %Q2\n\t" + "adcs %R0, %R0, %R2\n\t" + "adc %Q0, %1, #0" + : "=&r" (res), "+&r" (tmp) + : "r" (m), "r" (n) : "cc"); } -- cgit From 33298ef6d8ddef57aaa1d11ed53fc08bef2f95aa Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 29 Jan 2016 23:06:08 +0100 Subject: ARM: 8505/1: dma-mapping: Optimize allocation The __iommu_alloc_buffer() is expected to be called to allocate pretty sizeable buffers. Upon simple tests of video I saw it trying to allocate 4,194,304 bytes. The function tries to allocate large chunks in order to optimize IOMMU TLB usage. The current function is very, very slow. One problem is the way it keeps trying and trying to allocate big chunks. Imagine a very fragmented memory that has 4M free but no contiguous pages at all. Further imagine allocating 4M (1024 pages). We'll do the following memory allocations: - For page 1: - Try to allocate order 10 (no retry) - Try to allocate order 9 (no retry) - ... - Try to allocate order 0 (with retry, but not needed) - For page 2: - Try to allocate order 9 (no retry) - Try to allocate order 8 (no retry) - ... - Try to allocate order 0 (with retry, but not needed) - ... - ... Total number of calls to alloc() calls for this case is: sum(int(math.log(i, 2)) + 1 for i in range(1, 1025)) => 9228 The above is obviously worse case, but given how slow alloc can be we really want to try to avoid even somewhat bad cases. I timed the old code with a device under memory pressure and it wasn't hard to see it take more than 120 seconds to allocate 4 megs of memory! (NOTE: testing was done on kernel 3.14, so possibly mainline would behave differently). A second problem is that allocating big chunks under memory pressure when we don't need them is just not a great idea anyway unless we really need them. We can make due pretty well with smaller chunks so it's probably wise to leave bigger chunks for other users once memory pressure is on. Let's adjust the allocation like this: 1. If a big chunk fails, stop trying to hard and bump down to lower order allocations. 2. Don't try useless orders. The whole point of big chunks is to optimize the TLB and it can really only make use of 2M, 1M, 64K and 4K sizes. We'll still tend to eat up a bunch of big chunks, but that might be the right answer for some users. A future patch could possibly add a new DMA_ATTR that would let the caller decide that TLB optimization isn't important and that we should use smaller chunks. Presumably this would be a sane strategy for some callers. Signed-off-by: Douglas Anderson Acked-by: Marek Szyprowski Reviewed-by: Robin Murphy Reviewed-by: Tomasz Figa Tested-by: Javier Martinez Canillas Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 0eca3812527e..bc9cebfa0891 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1122,6 +1122,9 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping, spin_unlock_irqrestore(&mapping->lock, flags); } +/* We'll try 2M, 1M, 64K, and finally 4K; array must end with 0! */ +static const int iommu_order_array[] = { 9, 8, 4, 0 }; + static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp, struct dma_attrs *attrs) { @@ -1129,6 +1132,7 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, int count = size >> PAGE_SHIFT; int array_size = count * sizeof(struct page *); int i = 0; + int order_idx = 0; if (array_size <= PAGE_SIZE) pages = kzalloc(array_size, GFP_KERNEL); @@ -1162,22 +1166,24 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, while (count) { int j, order; - for (order = __fls(count); order > 0; --order) { - /* - * We do not want OOM killer to be invoked as long - * as we can fall back to single pages, so we force - * __GFP_NORETRY for orders higher than zero. - */ - pages[i] = alloc_pages(gfp | __GFP_NORETRY, order); - if (pages[i]) - break; + order = iommu_order_array[order_idx]; + + /* Drop down when we get small */ + if (__fls(count) < order) { + order_idx++; + continue; } - if (!pages[i]) { - /* - * Fall back to single page allocation. - * Might invoke OOM killer as last resort. - */ + if (order) { + /* See if it's easy to allocate a high-order chunk */ + pages[i] = alloc_pages(gfp | __GFP_NORETRY, order); + + /* Go down a notch at first sign of pressure */ + if (!pages[i]) { + order_idx++; + continue; + } + } else { pages[i] = alloc_pages(gfp, 0); if (!pages[i]) goto error; -- cgit From df05c6f6e0bb41380b31ef99b49796ac43a2a2df Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 29 Jan 2016 23:07:26 +0100 Subject: ARM: 8506/1: common: DMA-mapping: add DMA_ATTR_ALLOC_SINGLE_PAGES attribute This patch adds the DMA_ATTR_ALLOC_SINGLE_PAGES attribute to the DMA-mapping subsystem. This attribute can be used as a hint to the DMA-mapping subsystem that it's likely not worth it to try to allocate large pages behind the scenes. Large pages are likely to make an IOMMU TLB work more efficiently but may not be worth it. See the Documentation contained in this patch for more details about this attribute and when to use it. Note that the name of the hint (DMA_ATTR_ALLOC_SINGLE_PAGES) is loosely based on the name MADV_NOHUGEPAGE. Just as there is MADV_NOHUGEPAGE vs. MADV_HUGEPAGE we could also add an "opposite" attribute to DMA_ATTR_ALLOC_SINGLE_PAGES. Without having the "opposite" attribute the lack of DMA_ATTR_ALLOC_SINGLE_PAGES means "use your best judgement about whether to use small pages or large pages". Signed-off-by: Douglas Anderson Acked-by: Marek Szyprowski Reviewed-by: Robin Murphy Tested-by: Javier Martinez Canillas Signed-off-by: Russell King --- Documentation/DMA-attributes.txt | 26 ++++++++++++++++++++++++++ include/linux/dma-attrs.h | 1 + 2 files changed, 27 insertions(+) diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt index 18dc52c4f2a0..e8cf9cf873b3 100644 --- a/Documentation/DMA-attributes.txt +++ b/Documentation/DMA-attributes.txt @@ -100,3 +100,29 @@ allocated by dma_alloc_attrs() function from individual pages if it can be mapped as contiguous chunk into device dma address space. By specifying this attribute the allocated buffer is forced to be contiguous also in physical memory. + +DMA_ATTR_ALLOC_SINGLE_PAGES +--------------------------- + +This is a hint to the DMA-mapping subsystem that it's probably not worth +the time to try to allocate memory to in a way that gives better TLB +efficiency (AKA it's not worth trying to build the mapping out of larger +pages). You might want to specify this if: +- You know that the accesses to this memory won't thrash the TLB. + You might know that the accesses are likely to be sequential or + that they aren't sequential but it's unlikely you'll ping-pong + between many addresses that are likely to be in different physical + pages. +- You know that the penalty of TLB misses while accessing the + memory will be small enough to be inconsequential. If you are + doing a heavy operation like decryption or decompression this + might be the case. +- You know that the DMA mapping is fairly transitory. If you expect + the mapping to have a short lifetime then it may be worth it to + optimize allocation (avoid coming up with large pages) instead of + getting the slight performance win of larger pages. +Setting this hint doesn't guarantee that you won't get huge pages, but it +means that we won't try quite as hard to get them. + +NOTE: At the moment DMA_ATTR_ALLOC_SINGLE_PAGES is only implemented on ARM, +though ARM64 patches will likely be posted soon. diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h index 99c0be00b47c..5246239a4953 100644 --- a/include/linux/dma-attrs.h +++ b/include/linux/dma-attrs.h @@ -18,6 +18,7 @@ enum dma_attr { DMA_ATTR_NO_KERNEL_MAPPING, DMA_ATTR_SKIP_CPU_SYNC, DMA_ATTR_FORCE_CONTIGUOUS, + DMA_ATTR_ALLOC_SINGLE_PAGES, DMA_ATTR_MAX, }; -- cgit From 14d3ae2efeed4ebcc6313fad61470803eb904126 Mon Sep 17 00:00:00 2001 From: Doug Anderson Date: Fri, 29 Jan 2016 23:08:46 +0100 Subject: ARM: 8507/1: dma-mapping: Use DMA_ATTR_ALLOC_SINGLE_PAGES hint to optimize alloc If we know that TLB efficiency will not be an issue when memory is accessed then it's not terribly important to allocate big chunks of memory. The whole point of allocating the big chunks was that it would make TLB usage efficient. As Marek Szyprowski indicated: Please note that mapping memory with larger pages significantly improves performance, especially when IOMMU has a little TLB cache. This can be easily observed when multimedia devices do processing of RGB data with 90/270 degree rotation Image rotation is distinctly an operation that needs to bounce around through memory, so it makes sense that TLB efficiency is important there. Video decoding, on the other hand, is a fairly sequential operation. During video decoding it's not expected that we'll be jumping all over memory. Decoding video is also pretty heavy and the TLB misses aren't a huge deal. Presumably most HW video acceleration users of dma-mapping will not care about huge pages and will set DMA_ATTR_ALLOC_SINGLE_PAGES. Allocating big chunks of memory is quite expensive, especially if we're doing it repeadly and memory is full. In one (out of tree) usage model it is common that arm_iommu_alloc_attrs() is called 16 times in a row, each one trying to allocate 4 MB of memory. This is called whenever the system encounters a new video, which could easily happen while the memory system is stressed out. In fact, on certain social media websites that auto-play video and have infinite scrolling, it's quite common to see not just one of these 16x4MB allocations but 2 or 3 right after another. Asking the system even to do a small amount of extra work to give us big chunks in this case is just not a good use of time. Allocating big chunks of memory is also expensive indirectly. Even if we ask the system not to do ANY extra work to allocate _our_ memory, we're still potentially eating up all big chunks in the system. Presumably there are other users in the system that aren't quite as flexible and that actually need these big chunks. By eating all the big chunks we're causing extra work for the rest of the system. We also may start making other memory allocations fail. While the system may be robust to such failures (as is the case with dwc2 USB trying to allocate buffers for Ethernet data and with WiFi trying to allocate buffers for WiFi data), it is yet another big performance hit. Signed-off-by: Douglas Anderson Acked-by: Marek Szyprowski Tested-by: Javier Martinez Canillas Signed-off-by: Russell King --- arch/arm/mm/dma-mapping.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index bc9cebfa0891..9f996a3d79f7 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1158,6 +1158,10 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, return pages; } + /* Go straight to 4K chunks if caller says it's OK. */ + if (dma_get_attr(DMA_ATTR_ALLOC_SINGLE_PAGES, attrs)) + order_idx = ARRAY_SIZE(iommu_order_array) - 1; + /* * IOMMU can map any pages, so himem can also be used here */ -- cgit From ccc66e738252cede5c13e8d529b93b5a35b307c2 Mon Sep 17 00:00:00 2001 From: Tomasz Figa Date: Mon, 1 Feb 2016 22:34:42 +0100 Subject: ARM: 8508/2: videobuf2-dc: Let drivers specify DMA attrs DMA allocations might be subject to certain requirements specific to the hardware using the buffers, such as availability of kernel mapping (for contents fix-ups in the driver). The only entity that knows them is the driver, so it must share this knowledge with vb2-dc. This patch extends the alloc_ctx initialization interface to let the driver specify DMA attrs, which are then stored inside the allocation context and will be used for all allocations with that context. As a side effect, all dma_*_coherent() calls are turned into dma_*_attrs() calls, because the attributes need to be carried over through all DMA operations. Signed-off-by: Tomasz Figa Signed-off-by: Douglas Anderson Tested-by: Javier Martinez Canillas Acked-by: Mauro Carvalho Chehab Acked-by: Marek Szyprowski Signed-off-by: Russell King --- drivers/media/v4l2-core/videobuf2-dma-contig.c | 33 +++++++++++++++++--------- include/media/videobuf2-dma-contig.h | 11 ++++++++- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index c33127284cfe..5361197f3e57 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -23,13 +23,16 @@ struct vb2_dc_conf { struct device *dev; + struct dma_attrs attrs; }; struct vb2_dc_buf { struct device *dev; void *vaddr; unsigned long size; + void *cookie; dma_addr_t dma_addr; + struct dma_attrs attrs; enum dma_data_direction dma_dir; struct sg_table *dma_sgt; struct frame_vector *vec; @@ -131,7 +134,8 @@ static void vb2_dc_put(void *buf_priv) sg_free_table(buf->sgt_base); kfree(buf->sgt_base); } - dma_free_coherent(buf->dev, buf->size, buf->vaddr, buf->dma_addr); + dma_free_attrs(buf->dev, buf->size, buf->cookie, buf->dma_addr, + &buf->attrs); put_device(buf->dev); kfree(buf); } @@ -147,14 +151,18 @@ static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, if (!buf) return ERR_PTR(-ENOMEM); - buf->vaddr = dma_alloc_coherent(dev, size, &buf->dma_addr, - GFP_KERNEL | gfp_flags); - if (!buf->vaddr) { + buf->attrs = conf->attrs; + buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr, + GFP_KERNEL | gfp_flags, &buf->attrs); + if (!buf->cookie) { dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size); kfree(buf); return ERR_PTR(-ENOMEM); } + if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->attrs)) + buf->vaddr = buf->cookie; + /* Prevent the device from being released while the buffer is used */ buf->dev = get_device(dev); buf->size = size; @@ -185,8 +193,8 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma) */ vma->vm_pgoff = 0; - ret = dma_mmap_coherent(buf->dev, vma, buf->vaddr, - buf->dma_addr, buf->size); + ret = dma_mmap_attrs(buf->dev, vma, buf->cookie, + buf->dma_addr, buf->size, &buf->attrs); if (ret) { pr_err("Remapping memory failed, error: %d\n", ret); @@ -329,7 +337,7 @@ static void *vb2_dc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum) { struct vb2_dc_buf *buf = dbuf->priv; - return buf->vaddr + pgnum * PAGE_SIZE; + return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL; } static void *vb2_dc_dmabuf_ops_vmap(struct dma_buf *dbuf) @@ -368,8 +376,8 @@ static struct sg_table *vb2_dc_get_base_sgt(struct vb2_dc_buf *buf) return NULL; } - ret = dma_get_sgtable(buf->dev, sgt, buf->vaddr, buf->dma_addr, - buf->size); + ret = dma_get_sgtable_attrs(buf->dev, sgt, buf->cookie, buf->dma_addr, + buf->size, &buf->attrs); if (ret < 0) { dev_err(buf->dev, "failed to get scatterlist from DMA API\n"); kfree(sgt); @@ -721,7 +729,8 @@ const struct vb2_mem_ops vb2_dma_contig_memops = { }; EXPORT_SYMBOL_GPL(vb2_dma_contig_memops); -void *vb2_dma_contig_init_ctx(struct device *dev) +void *vb2_dma_contig_init_ctx_attrs(struct device *dev, + struct dma_attrs *attrs) { struct vb2_dc_conf *conf; @@ -730,10 +739,12 @@ void *vb2_dma_contig_init_ctx(struct device *dev) return ERR_PTR(-ENOMEM); conf->dev = dev; + if (attrs) + conf->attrs = *attrs; return conf; } -EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx); +EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx_attrs); void vb2_dma_contig_cleanup_ctx(void *alloc_ctx) { diff --git a/include/media/videobuf2-dma-contig.h b/include/media/videobuf2-dma-contig.h index c33dfa69d7ab..2087c9a68be3 100644 --- a/include/media/videobuf2-dma-contig.h +++ b/include/media/videobuf2-dma-contig.h @@ -16,6 +16,8 @@ #include #include +struct dma_attrs; + static inline dma_addr_t vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no) { @@ -24,7 +26,14 @@ vb2_dma_contig_plane_dma_addr(struct vb2_buffer *vb, unsigned int plane_no) return *addr; } -void *vb2_dma_contig_init_ctx(struct device *dev); +void *vb2_dma_contig_init_ctx_attrs(struct device *dev, + struct dma_attrs *attrs); + +static inline void *vb2_dma_contig_init_ctx(struct device *dev) +{ + return vb2_dma_contig_init_ctx_attrs(dev, NULL); +} + void vb2_dma_contig_cleanup_ctx(void *alloc_ctx); extern const struct vb2_mem_ops vb2_dma_contig_memops; -- cgit From 1b9bdf5c1661873a10e193b8cbb803a87fe5c4a1 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 1 Feb 2016 18:01:29 +0100 Subject: ARM: 8510/1: rework ARM_CPU_SUSPEND dependencies The code enabled by the ARM_CPU_SUSPEND config option is used by kernel subsystems for purposes that go beyond system suspend so its config entry should be augmented to take more default options into account and avoid forcing its selection to prevent dependencies override. To achieve this goal, this patch reworks the ARM_CPU_SUSPEND config entry and updates its default config value (by adding the BL_SWITCHER option to it) and its dependencies (ARCH_SUSPEND_POSSIBLE), so that the symbol is still selected by default by the subsystems requiring it and at the same time enforcing the dependencies correctly. Signed-off-by: Lorenzo Pieralisi Cc: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4f799e567fc8..8456f69bc77d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1337,7 +1337,6 @@ config BIG_LITTLE config BL_SWITCHER bool "big.LITTLE switcher support" depends on BIG_LITTLE && MCPM && HOTPLUG_CPU && ARM_GIC - select ARM_CPU_SUSPEND select CPU_PM help The big.LITTLE "switcher" provides the core functionality to @@ -2111,7 +2110,8 @@ config ARCH_SUSPEND_POSSIBLE def_bool y config ARM_CPU_SUSPEND - def_bool PM_SLEEP + def_bool PM_SLEEP || BL_SWITCHER + depends on ARCH_SUSPEND_POSSIBLE config ARCH_HIBERNATION_POSSIBLE bool -- cgit From 8b6f2499ac45d5a0ab2e4b6f9613ab3f60416be1 Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Mon, 1 Feb 2016 18:01:30 +0100 Subject: ARM: 8511/1: ARM64: kernel: PSCI: move PSCI idle management code to drivers/firmware ARM64 PSCI kernel interfaces that initialize idle states and implement the suspend API to enter them are generic and can be shared with the ARM architecture. To achieve that goal, this patch moves ARM64 PSCI idle management code to drivers/firmware, so that the interface to initialize and enter idle states can actually be shared by ARM and ARM64 arches back-ends. The ARM generic CPUidle implementation also requires the definition of a cpuidle_ops section entry for the kernel to initialize the CPUidle operations at boot based on the enable-method (ie ARM64 has the statically initialized cpu_ops counterparts for that purpose); therefore this patch also adds the required section entry on CONFIG_ARM for PSCI so that the kernel can initialize the PSCI CPUidle back-end when PSCI is the probed enable-method. On ARM64 this patch provides no functional change. Signed-off-by: Lorenzo Pieralisi Acked-by: Daniel Lezcano Acked-by: Catalin Marinas [arch/arm64] Acked-by: Mark Rutland Tested-by: Jisheng Zhang Cc: Will Deacon Cc: Sudeep Holla Cc: Daniel Lezcano Cc: Catalin Marinas Cc: Mark Rutland Cc: Jisheng Zhang Signed-off-by: Russell King --- arch/arm/Kconfig | 2 +- arch/arm64/kernel/psci.c | 99 +------------------------------------- drivers/firmware/psci.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/psci.h | 3 ++ 4 files changed, 126 insertions(+), 98 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8456f69bc77d..cc95ff8f07cb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -2110,7 +2110,7 @@ config ARCH_SUSPEND_POSSIBLE def_bool y config ARM_CPU_SUSPEND - def_bool PM_SLEEP || BL_SWITCHER + def_bool PM_SLEEP || BL_SWITCHER || ARM_PSCI_FW depends on ARCH_SUSPEND_POSSIBLE config ARCH_HIBERNATION_POSSIBLE diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index f67f35b6edb1..42816bebb1e0 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -20,7 +20,6 @@ #include #include #include -#include #include @@ -28,73 +27,6 @@ #include #include #include -#include - -static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); - -static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu) -{ - int i, ret, count = 0; - u32 *psci_states; - struct device_node *state_node, *cpu_node; - - cpu_node = of_get_cpu_node(cpu, NULL); - if (!cpu_node) - return -ENODEV; - - /* - * If the PSCI cpu_suspend function hook has not been initialized - * idle states must not be enabled, so bail out - */ - if (!psci_ops.cpu_suspend) - return -EOPNOTSUPP; - - /* Count idle states */ - while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states", - count))) { - count++; - of_node_put(state_node); - } - - if (!count) - return -ENODEV; - - psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); - if (!psci_states) - return -ENOMEM; - - for (i = 0; i < count; i++) { - u32 state; - - state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); - - ret = of_property_read_u32(state_node, - "arm,psci-suspend-param", - &state); - if (ret) { - pr_warn(" * %s missing arm,psci-suspend-param property\n", - state_node->full_name); - of_node_put(state_node); - goto free_mem; - } - - of_node_put(state_node); - pr_debug("psci-power-state %#x index %d\n", state, i); - if (!psci_power_state_is_valid(state)) { - pr_warn("Invalid PSCI power state %#x\n", state); - ret = -EINVAL; - goto free_mem; - } - psci_states[i] = state; - } - /* Idle states parsed correctly, initialize per-cpu pointer */ - per_cpu(psci_power_state, cpu) = psci_states; - return 0; - -free_mem: - kfree(psci_states); - return ret; -} static int __init cpu_psci_cpu_init(unsigned int cpu) { @@ -178,38 +110,11 @@ static int cpu_psci_cpu_kill(unsigned int cpu) } #endif -static int psci_suspend_finisher(unsigned long index) -{ - u32 *state = __this_cpu_read(psci_power_state); - - return psci_ops.cpu_suspend(state[index - 1], - virt_to_phys(cpu_resume)); -} - -static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index) -{ - int ret; - u32 *state = __this_cpu_read(psci_power_state); - /* - * idle state index 0 corresponds to wfi, should never be called - * from the cpu_suspend operations - */ - if (WARN_ON_ONCE(!index)) - return -EINVAL; - - if (!psci_power_state_loses_context(state[index - 1])) - ret = psci_ops.cpu_suspend(state[index - 1], 0); - else - ret = cpu_suspend(index, psci_suspend_finisher); - - return ret; -} - const struct cpu_operations cpu_psci_ops = { .name = "psci", #ifdef CONFIG_CPU_IDLE - .cpu_init_idle = cpu_psci_cpu_init_idle, - .cpu_suspend = cpu_psci_cpu_suspend, + .cpu_init_idle = psci_cpu_init_idle, + .cpu_suspend = psci_cpu_suspend_enter, #endif .cpu_init = cpu_psci_cpu_init, .cpu_prepare = cpu_psci_cpu_prepare, diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index f25cd79c8a79..11bfee8b79a9 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -14,6 +14,7 @@ #define pr_fmt(fmt) "psci: " fmt #include +#include #include #include #include @@ -21,10 +22,12 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -244,6 +247,123 @@ static int __init psci_features(u32 psci_func_id) psci_func_id, 0, 0); } +#ifdef CONFIG_CPU_IDLE +static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state); + +static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu) +{ + int i, ret, count = 0; + u32 *psci_states; + struct device_node *state_node; + + /* + * If the PSCI cpu_suspend function hook has not been initialized + * idle states must not be enabled, so bail out + */ + if (!psci_ops.cpu_suspend) + return -EOPNOTSUPP; + + /* Count idle states */ + while ((state_node = of_parse_phandle(cpu_node, "cpu-idle-states", + count))) { + count++; + of_node_put(state_node); + } + + if (!count) + return -ENODEV; + + psci_states = kcalloc(count, sizeof(*psci_states), GFP_KERNEL); + if (!psci_states) + return -ENOMEM; + + for (i = 0; i < count; i++) { + u32 state; + + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); + + ret = of_property_read_u32(state_node, + "arm,psci-suspend-param", + &state); + if (ret) { + pr_warn(" * %s missing arm,psci-suspend-param property\n", + state_node->full_name); + of_node_put(state_node); + goto free_mem; + } + + of_node_put(state_node); + pr_debug("psci-power-state %#x index %d\n", state, i); + if (!psci_power_state_is_valid(state)) { + pr_warn("Invalid PSCI power state %#x\n", state); + ret = -EINVAL; + goto free_mem; + } + psci_states[i] = state; + } + /* Idle states parsed correctly, initialize per-cpu pointer */ + per_cpu(psci_power_state, cpu) = psci_states; + return 0; + +free_mem: + kfree(psci_states); + return ret; +} + +int psci_cpu_init_idle(unsigned int cpu) +{ + struct device_node *cpu_node; + int ret; + + cpu_node = of_get_cpu_node(cpu, NULL); + if (!cpu_node) + return -ENODEV; + + ret = psci_dt_cpu_init_idle(cpu_node, cpu); + + of_node_put(cpu_node); + + return ret; +} + +static int psci_suspend_finisher(unsigned long index) +{ + u32 *state = __this_cpu_read(psci_power_state); + + return psci_ops.cpu_suspend(state[index - 1], + virt_to_phys(cpu_resume)); +} + +int psci_cpu_suspend_enter(unsigned long index) +{ + int ret; + u32 *state = __this_cpu_read(psci_power_state); + /* + * idle state index 0 corresponds to wfi, should never be called + * from the cpu_suspend operations + */ + if (WARN_ON_ONCE(!index)) + return -EINVAL; + + if (!psci_power_state_loses_context(state[index - 1])) + ret = psci_ops.cpu_suspend(state[index - 1], 0); + else + ret = cpu_suspend(index, psci_suspend_finisher); + + return ret; +} + +/* ARM specific CPU idle operations */ +#ifdef CONFIG_ARM +static struct cpuidle_ops psci_cpuidle_ops __initdata = { + .suspend = psci_cpu_suspend_enter, + .init = psci_dt_cpu_init_idle, +}; + +CPUIDLE_METHOD_OF_DECLARE(psci, "arm,psci", &psci_cpuidle_ops); +#endif +#endif + static int psci_system_suspend(unsigned long unused) { return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND), diff --git a/include/linux/psci.h b/include/linux/psci.h index 12c4865457ad..393efe2edf9a 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -24,6 +24,9 @@ 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); + struct psci_operations { int (*cpu_suspend)(u32 state, unsigned long entry_point); int (*cpu_off)(u32 state); -- cgit From 538bf4694898b19e76f32d554cc16135cf37b51c Mon Sep 17 00:00:00 2001 From: Chris Brandt Date: Wed, 3 Feb 2016 15:58:10 +0100 Subject: ARM: 8513/1: xip: Move XIP linking to a separate file When building an XIP kernel, the linker script needs to be much different than a conventional kernel's script. Over time, it's been difficult to maintain both XIP and non-XIP layouts in one linker script. Therefore, this patch separates the two procedures into two completely different files. The new linker script is essentially a straight copy of the current script with all the non-CONFIG_XIP_KERNEL portions removed. Additionally, all CONFIG_XIP_KERNEL portions have been removed from the existing linker script...never to return again. It should be noted that this does not fix any current XIP issues, but rather is the first move in fixing them properly with subsequent patches. Signed-off-by: Chris Brandt Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/kernel/vmlinux-xip.lds.S | 322 ++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/vmlinux.lds.S | 37 ++--- 2 files changed, 332 insertions(+), 27 deletions(-) create mode 100644 arch/arm/kernel/vmlinux-xip.lds.S diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S new file mode 100644 index 000000000000..6f59ef290289 --- /dev/null +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -0,0 +1,322 @@ +/* ld script to make ARM Linux kernel + * taken from the i386 version by Russell King + * Written by Martin Mares + */ + +#include +#include +#include +#include +#include +#ifdef CONFIG_DEBUG_RODATA +#include +#endif + +#define PROC_INFO \ + . = ALIGN(4); \ + VMLINUX_SYMBOL(__proc_info_begin) = .; \ + *(.proc.info.init) \ + VMLINUX_SYMBOL(__proc_info_end) = .; + +#define IDMAP_TEXT \ + ALIGN_FUNCTION(); \ + VMLINUX_SYMBOL(__idmap_text_start) = .; \ + *(.idmap.text) \ + VMLINUX_SYMBOL(__idmap_text_end) = .; \ + . = ALIGN(PAGE_SIZE); \ + VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \ + *(.hyp.idmap.text) \ + VMLINUX_SYMBOL(__hyp_idmap_text_end) = .; + +#ifdef CONFIG_HOTPLUG_CPU +#define ARM_CPU_DISCARD(x) +#define ARM_CPU_KEEP(x) x +#else +#define ARM_CPU_DISCARD(x) x +#define ARM_CPU_KEEP(x) +#endif + +#if (defined(CONFIG_SMP_ON_UP) && !defined(CONFIG_DEBUG_SPINLOCK)) || \ + defined(CONFIG_GENERIC_BUG) +#define ARM_EXIT_KEEP(x) x +#define ARM_EXIT_DISCARD(x) +#else +#define ARM_EXIT_KEEP(x) +#define ARM_EXIT_DISCARD(x) x +#endif + +OUTPUT_ARCH(arm) +ENTRY(stext) + +#ifndef __ARMEB__ +jiffies = jiffies_64; +#else +jiffies = jiffies_64 + 4; +#endif + +SECTIONS +{ + /* + * XXX: The linker does not define how output sections are + * assigned to input sections when there are multiple statements + * matching the same input section name. There is no documented + * order of matching. + * + * unwind exit sections must be discarded before the rest of the + * unwind sections get included. + */ + /DISCARD/ : { + *(.ARM.exidx.exit.text) + *(.ARM.extab.exit.text) + ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text)) + ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text)) + ARM_EXIT_DISCARD(EXIT_TEXT) + ARM_EXIT_DISCARD(EXIT_DATA) + EXIT_CALL +#ifndef CONFIG_MMU + *(.text.fixup) + *(__ex_table) +#endif +#ifndef CONFIG_SMP_ON_UP + *(.alt.smp.init) +#endif + *(.discard) + *(.discard.*) + } + + . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); + + .head.text : { + _text = .; + HEAD_TEXT + } + +#ifdef CONFIG_DEBUG_RODATA + . = ALIGN(1< */ +#ifdef CONFIG_XIP_KERNEL +#include "vmlinux-xip.lds.S" +#else + #include #include #include @@ -84,11 +88,7 @@ SECTIONS *(.discard.*) } -#ifdef CONFIG_XIP_KERNEL - . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); -#else . = PAGE_OFFSET + TEXT_OFFSET; -#endif .head.text : { _text = .; HEAD_TEXT @@ -152,14 +152,13 @@ SECTIONS _etext = .; /* End of text and rodata section */ -#ifndef CONFIG_XIP_KERNEL -# ifdef CONFIG_DEBUG_RODATA +#ifdef CONFIG_DEBUG_RODATA . = ALIGN(1< Date: Fri, 5 Feb 2016 10:04:47 +0100 Subject: ARM: 8514/1: remove duplicate definitions of __vectors_start and __stubs_start Commit b9b32bf70f2f ("ARM: use linker magic for vectors and vector stubs") introduced new global definitions of __vectors_start and __stubs_start, and changed the existing ones to have internal linkage only. However, these symbols are still visible to kallsyms, and due to the way the .vectors and .stubs sections are emitted at the base of the VMA space, these duplicate definitions have conflicting values. $ nm -n vmlinux |grep -E __vectors|__stubs 00000000 t __vectors_start 00001000 t __stubs_start c0e77000 T __vectors_start c0e77020 T __stubs_start This is completely harmless by itself, since the wrong values are local symbols that cannot be referenced by other object files directly. However, since these symbols are also listed in the kallsyms symbol table in some cases (i.e., CONFIG_KALLSYMS_ALL=y and CONFIG_XIP_KERNEL=y), having these conflicting values can be confusing. So either remove them, or make them strictly local. Acked-by: Chris Brandt Acked-by: Nicolas Pitre Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 3ce377f7251f..788e40c1254f 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -1064,7 +1064,6 @@ ENDPROC(vector_\name) .endm .section .stubs, "ax", %progbits -__stubs_start: @ This must be the first word .word vector_swi @@ -1206,10 +1205,10 @@ vector_addrexcptn: .equ vector_fiq_offset, vector_fiq .section .vectors, "ax", %progbits -__vectors_start: +.L__vectors_start: W(b) vector_rst W(b) vector_und - W(ldr) pc, __vectors_start + 0x1000 + W(ldr) pc, .L__vectors_start + 0x1000 W(b) vector_pabt W(b) vector_dabt W(b) vector_addrexcptn -- cgit From 31b96cae5ca2e751ce3dcf4839c2398a1e8b8fc3 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 10 Feb 2016 11:41:08 +0100 Subject: ARM: 8515/2: move .vectors and .stubs sections back into the kernel VMA Commit b9b32bf70f2f ("ARM: use linker magic for vectors and vector stubs") updated the linker script to emit the .vectors and .stubs sections into a VMA range that is zero based and disjoint from the normal static kernel region. The reason for that was that this way, the sections can be placed exactly 4 KB apart, while the payload of the .vectors section is only 32 bytes. Since the symbols that are part of the .stubs section are emitted into the kallsyms table, they appear with zero based addresses as well, e.g., 00001004 t vector_rst 00001020 t vector_irq 000010a0 t vector_dabt 00001120 t vector_pabt 000011a0 t vector_und 00001220 t vector_addrexcptn 00001240 t vector_fiq 00001240 T vector_fiq_offset As this confuses perf when it accesses the kallsyms tables, commit 7122c3e9154b ("scripts/link-vmlinux.sh: only filter kernel symbols for arm") implemented a somewhat ugly special case for ARM, where the value of CONFIG_PAGE_OFFSET is passed to scripts/kallsyms, and symbols whose addresses are below it are filtered out. Note that this special case only applies to CONFIG_XIP_KERNEL=n, not because the issue the patch addresses exists only in that case, but because finding a limit below which to apply the filtering is not entirely straightforward. Since the .vectors and .stubs sections contain position independent code that is never executed in place, we can emit it at its most likely runtime VMA (for more recent CPUs), which is 0xffff0000 for the vector table and 0xffff1000 for the stubs. Not only does this fix the perf issue with kallsyms, allowing us to drop the special case in scripts/kallsyms entirely, it also gives debuggers a more realistic view of the address space, and setting breakpoints or single stepping through code in the vector table or the stubs is more likely to work as expected on CPUs that use a high vector address. E.g., 00001240 A vector_fiq_offset ... c0c35000 T __init_begin c0c35000 T __vectors_start c0c35020 T __stubs_start c0c35020 T __vectors_end c0c352e0 T _sinittext c0c352e0 T __stubs_end ... ffff1004 t vector_rst ffff1020 t vector_irq ffff10a0 t vector_dabt ffff1120 t vector_pabt ffff11a0 t vector_und ffff1220 t vector_addrexcptn ffff1240 T vector_fiq (Note that vector_fiq_offset is now an absolute symbol, which kallsyms already ignores by default) The LMA footprint is identical with or without this change, only the VMAs are different: Before: Idx Name Size VMA LMA File off Algn ... 14 .notes 00000024 c0c34020 c0c34020 00a34020 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 15 .vectors 00000020 00000000 c0c35000 00a40000 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 16 .stubs 000002c0 00001000 c0c35020 00a41000 2**5 CONTENTS, ALLOC, LOAD, READONLY, CODE 17 .init.text 0006b1b8 c0c352e0 c0c352e0 00a452e0 2**5 CONTENTS, ALLOC, LOAD, READONLY, CODE ... After: Idx Name Size VMA LMA File off Algn ... 14 .notes 00000024 c0c34020 c0c34020 00a34020 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 15 .vectors 00000020 ffff0000 c0c35000 00a40000 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 16 .stubs 000002c0 ffff1000 c0c35020 00a41000 2**5 CONTENTS, ALLOC, LOAD, READONLY, CODE 17 .init.text 0006b1b8 c0c352e0 c0c352e0 00a452e0 2**5 CONTENTS, ALLOC, LOAD, READONLY, CODE ... Acked-by: Nicolas Pitre Acked-by: Chris Brandt Signed-off-by: Ard Biesheuvel Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 3 +-- arch/arm/kernel/vmlinux-xip.lds.S | 6 ++++-- arch/arm/kernel/vmlinux.lds.S | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 788e40c1254f..e2550500486d 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -1201,8 +1201,7 @@ vector_addrexcptn: .long __fiq_svc @ e .long __fiq_svc @ f - .globl vector_fiq_offset - .equ vector_fiq_offset, vector_fiq + .globl vector_fiq .section .vectors, "ax", %progbits .L__vectors_start: diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 6f59ef290289..7b1ded6fb628 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -154,19 +154,21 @@ SECTIONS * only thing that matters is their relative offsets */ __vectors_start = .; - .vectors 0 : AT(__vectors_start) { + .vectors 0xffff0000 : AT(__vectors_start) { *(.vectors) } . = __vectors_start + SIZEOF(.vectors); __vectors_end = .; __stubs_start = .; - .stubs 0x1000 : AT(__stubs_start) { + .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { *(.stubs) } . = __stubs_start + SIZEOF(.stubs); __stubs_end = .; + PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors)); + INIT_TEXT_SECTION(8) .exit.text : { ARM_EXIT_KEEP(EXIT_TEXT) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index cdc84693091b..e087a2ed112b 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -164,19 +164,21 @@ SECTIONS * only thing that matters is their relative offsets */ __vectors_start = .; - .vectors 0 : AT(__vectors_start) { + .vectors 0xffff0000 : AT(__vectors_start) { *(.vectors) } . = __vectors_start + SIZEOF(.vectors); __vectors_end = .; __stubs_start = .; - .stubs 0x1000 : AT(__stubs_start) { + .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { *(.stubs) } . = __stubs_start + SIZEOF(.stubs); __stubs_end = .; + PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors)); + INIT_TEXT_SECTION(8) .exit.text : { ARM_EXIT_KEEP(EXIT_TEXT) -- cgit From 43de29baa93873b48ed898ef5584c7cfa70ece3c Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 14:53:47 +0100 Subject: mfd: Add DT binding documentation for imx25 ADC/TSC This documentation describes the devicetree bindings for the ADC/Touchscreen unit of the i.MX25 SoC. Signed-off-by: Markus Pargmann Acked-by: Jonathan Cameron Acked-by: Rob Herring Signed-off-by: Lee Jones --- .../devicetree/bindings/mfd/fsl-imx25-tsadc.txt | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt diff --git a/Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt b/Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt new file mode 100644 index 000000000000..b03505286997 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/fsl-imx25-tsadc.txt @@ -0,0 +1,47 @@ +Freescale MX25 ADC/TSC MultiFunction Device (MFD) + +This device combines two general purpose conversion queues one used for general +ADC and the other used for touchscreens. + +Required properties: + - compatible: Should be "fsl,imx25-tsadc". + - reg: Start address and size of the memory area of + the device + - interrupts: Interrupt for this device + (See: ../interrupt-controller/interrupts.txt) + - clocks: An 'ipg' clock (See: ../clock/clock-bindings.txt) + - interrupt-controller: This device is an interrupt controller. It + controls the interrupts of both + conversion queues. + - #interrupt-cells: Should be '<1>'. + - #address-cells: Should be '<1>'. + - #size-cells: Should be '<1>'. + +This device includes two conversion queues which can be added as subnodes. +The first queue is for the touchscreen, the second for general purpose ADC. + +Example: + tscadc: tscadc@50030000 { + compatible = "fsl,imx25-tsadc"; + reg = <0x50030000 0xc>; + interrupts = <46>; + clocks = <&clks 119>; + clock-names = "ipg"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + tsc: tcq@50030400 { + compatible = "fsl,imx25-tcq"; + reg = <0x50030400 0x60>; + ... + }; + + adc: gcq@50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + ... + }; + }; -- cgit From 337600fbeeb70e9ec052ca5fe0a09047c70649be Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 14:53:48 +0100 Subject: iio: Add binding documentation for imx25 GCQ The documentation describes the bindings for the imx25 GCQ unit which is essentially a generic conversion queue using the imx25 ADC. Signed-off-by: Markus Pargmann Acked-by: Rob Herring Acked-by: Jonathan Cameron Signed-off-by: Lee Jones --- .../devicetree/bindings/iio/adc/fsl,imx25-gcq.txt | 58 ++++++++++++++++++++++ include/dt-bindings/iio/adc/fsl-imx25-gcq.h | 18 +++++++ 2 files changed, 76 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt create mode 100644 include/dt-bindings/iio/adc/fsl-imx25-gcq.h diff --git a/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt b/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt new file mode 100644 index 000000000000..b0866d36a307 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/fsl,imx25-gcq.txt @@ -0,0 +1,58 @@ +Freescale i.MX25 ADC GCQ device + +This is a generic conversion queue device that can convert any of the +analog inputs using the ADC unit of the i.MX25. + +Required properties: + - compatible: Should be "fsl,imx25-gcq". + - reg: Should be the register range of the module. + - interrupts: Should be the interrupt number of the module. + Typically this is <1>. + - interrupt-parent: phandle to the tsadc module of the i.MX25. + - #address-cells: Should be <1> (setting for the subnodes) + - #size-cells: Should be <0> (setting for the subnodes) + +Optional properties: + - vref-ext-supply: The regulator supplying the ADC reference voltage. + Required when at least one subnode uses the this reference. + - vref-xp-supply: The regulator supplying the ADC reference voltage on pin XP. + Required when at least one subnode uses this reference. + - vref-yp-supply: The regulator supplying the ADC reference voltage on pin YP. + Required when at least one subnode uses this reference. + +Sub-nodes: +Optionally you can define subnodes which define the reference voltage +for the analog inputs. + +Required properties for subnodes: + - reg: Should be the number of the analog input. + 0: xp + 1: yp + 2: xn + 3: yn + 4: wiper + 5: inaux0 + 6: inaux1 + 7: inaux2 +Optional properties for subnodes: + - fsl,adc-refp: specifies the positive reference input as defined in + + - fsl,adc-refn: specifies the negative reference input as defined in + + +Example: + + adc: adc@50030800 { + compatible = "fsl,imx25-gcq"; + reg = <0x50030800 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <1>; + #address-cells = <1>; + #size-cells = <0>; + + inaux@5 { + reg = <5>; + fsl,adc-refp = ; + fsl,adc-refn = ; + }; + }; diff --git a/include/dt-bindings/iio/adc/fsl-imx25-gcq.h b/include/dt-bindings/iio/adc/fsl-imx25-gcq.h new file mode 100644 index 000000000000..87abdd4a7674 --- /dev/null +++ b/include/dt-bindings/iio/adc/fsl-imx25-gcq.h @@ -0,0 +1,18 @@ +/* + * This header provides constants for configuring the I.MX25 ADC + */ + +#ifndef _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H +#define _DT_BINDINGS_IIO_ADC_FS_IMX25_GCQ_H + +#define MX25_ADC_REFP_YP 0 /* YP voltage reference */ +#define MX25_ADC_REFP_XP 1 /* XP voltage reference */ +#define MX25_ADC_REFP_EXT 2 /* External voltage reference */ +#define MX25_ADC_REFP_INT 3 /* Internal voltage reference */ + +#define MX25_ADC_REFN_XN 0 /* XN ground reference */ +#define MX25_ADC_REFN_YN 1 /* YN ground reference */ +#define MX25_ADC_REFN_NGND 2 /* Internal ground reference */ +#define MX25_ADC_REFN_NGND2 3 /* External ground reference */ + +#endif -- cgit From ff07004f4b9c5f5589e0821afd3db1e86e1102c4 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 14:53:49 +0100 Subject: Input: add binding documentation for imx25 touchscreen controller This is the touchscreen conversion queue binding documentation. It uses the shared imx25 ADC. Signed-off-by: Markus Pargmann Acked-by: Rob Herring Signed-off-by: Lee Jones --- .../bindings/input/touchscreen/fsl-mx25-tcq.txt | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt diff --git a/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt new file mode 100644 index 000000000000..cdf05f9b2329 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/fsl-mx25-tcq.txt @@ -0,0 +1,35 @@ +Freescale mx25 TS conversion queue module + +mx25 touchscreen conversion queue module which controls the ADC unit of the +mx25 for attached touchscreens. + +Required properties: + - compatible: Should be "fsl,imx25-tcq". + - reg: Memory range of the device. + - interrupts: Should be the interrupt number associated with this module within + the tscadc unit (<0>). + - interrupt-parent: Should be a phandle to the tscadc unit. + - fsl,wires: Should be '<4>' or '<5>' + +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 + 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 + the actual touch detection to wait for an even charge distribution in the + plate. + +This device includes two conversion queues which can be added as subnodes. +The first queue is for the touchscreen, the second for general purpose ADC. + +Example: + tsc: tcq@50030400 { + compatible = "fsl,imx25-tcq"; + reg = <0x50030400 0x60>; + interrupt-parent = <&tscadc>; + interrupts = <0>; + fsl,wires = <4>; + }; -- cgit From e2fccf5c15157218f0b6488168f98183f82c1eda Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 14:53:50 +0100 Subject: mfd: fsl-imx25-tsadc: Register touchscreen ADC driver This is the core driver for imx25 touchscreen/adc driver. The module has one shared ADC and two different conversion queues which use the ADC. The two queues are identical. Both can be used for general purpose ADC but one is meant to be used for touchscreens. This driver is the core which manages the central components and registers of the TSC/ADC unit. It manages the IRQs and forwards them to the correct components. Signed-off-by: Markus Pargmann Signed-off-by: Denis Carikli [ensure correct ADC clock depending on the IPG clock] Signed-off-by: Juergen Borleis Acked-by: Jonathan Cameron Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 9 ++ drivers/mfd/Makefile | 2 + drivers/mfd/fsl-imx25-tsadc.c | 203 ++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/imx25-tsadc.h | 140 +++++++++++++++++++++++++++ 4 files changed, 354 insertions(+) create mode 100644 drivers/mfd/fsl-imx25-tsadc.c create mode 100644 include/linux/mfd/imx25-tsadc.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9ca66de0c1c1..6980e0463c8c 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -271,6 +271,15 @@ config MFD_MC13XXX_I2C help Select this if your MC13xxx is connected via an I2C bus. +config MFD_MX25_TSADC + tristate "Freescale i.MX25 integrated Touchscreen and ADC unit" + select REGMAP_MMIO + depends on (SOC_IMX25 && OF) || COMPILE_TEST + help + Enable support for the integrated Touchscreen and ADC unit of the + i.MX25 processors. They consist of a conversion queue for general + purpose ADC and a queue for Touchscreens. + config MFD_HI6421_PMIC tristate "HiSilicon Hi6421 PMU/Codec IC" depends on OF diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0f230a6103f8..8706bf9cf51b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -85,6 +85,8 @@ obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o obj-$(CONFIG_MFD_TWL4030_AUDIO) += twl4030-audio.o obj-$(CONFIG_TWL6040_CORE) += twl6040.o +obj-$(CONFIG_MFD_MX25_TSADC) += fsl-imx25-tsadc.o + obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c new file mode 100644 index 000000000000..77b2675cf8f5 --- /dev/null +++ b/drivers/mfd/fsl-imx25-tsadc.c @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann + * + * 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 +#include +#include +#include +#include + +static struct regmap_config mx25_tsadc_regmap_config = { + .fast_io = true, + .max_register = 8, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static void mx25_tsadc_irq_handler(struct irq_desc *desc) +{ + struct mx25_tsadc *tsadc = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + u32 status; + + chained_irq_enter(chip, desc); + + regmap_read(tsadc->regs, MX25_TSC_TGSR, &status); + + if (status & MX25_TGSR_GCQ_INT) + generic_handle_irq(irq_find_mapping(tsadc->domain, 1)); + + if (status & MX25_TGSR_TCQ_INT) + generic_handle_irq(irq_find_mapping(tsadc->domain, 0)); + + chained_irq_exit(chip, desc); +} + +static int mx25_tsadc_domain_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct mx25_tsadc *tsadc = d->host_data; + + irq_set_chip_data(irq, tsadc); + irq_set_chip_and_handler(irq, &dummy_irq_chip, + handle_level_irq); + irq_modify_status(irq, IRQ_NOREQUEST, IRQ_NOPROBE); + + return 0; +} + +static struct irq_domain_ops mx25_tsadc_domain_ops = { + .map = mx25_tsadc_domain_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int mx25_tsadc_setup_irq(struct platform_device *pdev, + struct mx25_tsadc *tsadc) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + int irq; + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(dev, "Failed to get irq\n"); + return irq; + } + + tsadc->domain = irq_domain_add_simple(np, 2, 0, &mx25_tsadc_domain_ops, + tsadc); + if (!tsadc->domain) { + dev_err(dev, "Failed to add irq domain\n"); + return -ENOMEM; + } + + irq_set_chained_handler(irq, mx25_tsadc_irq_handler); + irq_set_handler_data(irq, tsadc); + + return 0; +} + +static void mx25_tsadc_setup_clk(struct platform_device *pdev, + struct mx25_tsadc *tsadc) +{ + unsigned clk_div; + + /* + * According to the datasheet the ADC clock should never + * exceed 1,75 MHz. Base clock is the IPG and the ADC unit uses + * a funny clock divider. To keep the ADC conversion time constant + * adapt the ADC internal clock divider to the IPG clock rate. + */ + + dev_dbg(&pdev->dev, "Found master clock at %lu Hz\n", + clk_get_rate(tsadc->clk)); + + clk_div = DIV_ROUND_UP(clk_get_rate(tsadc->clk), 1750000); + dev_dbg(&pdev->dev, "Setting up ADC clock divider to %u\n", clk_div); + + /* adc clock = IPG clock / (2 * div + 2) */ + clk_div -= 2; + clk_div /= 2; + + /* + * the ADC clock divider changes its behaviour when values below 4 + * are used: it is fixed to "/ 10" in this case + */ + clk_div = max_t(unsigned, 4, clk_div); + + dev_dbg(&pdev->dev, "Resulting ADC conversion clock at %lu Hz\n", + clk_get_rate(tsadc->clk) / (2 * clk_div + 2)); + + regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, + MX25_TGCR_ADCCLKCFG(0x1f), + MX25_TGCR_ADCCLKCFG(clk_div)); +} + +static int mx25_tsadc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct mx25_tsadc *tsadc; + struct resource *res; + int ret; + void __iomem *iomem; + + tsadc = devm_kzalloc(dev, sizeof(*tsadc), GFP_KERNEL); + if (!tsadc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + iomem = devm_ioremap_resource(dev, res); + if (IS_ERR(iomem)) + return PTR_ERR(iomem); + + tsadc->regs = devm_regmap_init_mmio(dev, iomem, + &mx25_tsadc_regmap_config); + if (IS_ERR(tsadc->regs)) { + dev_err(dev, "Failed to initialize regmap\n"); + return PTR_ERR(tsadc->regs); + } + + tsadc->clk = devm_clk_get(dev, "ipg"); + if (IS_ERR(tsadc->clk)) { + dev_err(dev, "Failed to get ipg clock\n"); + return PTR_ERR(tsadc->clk); + } + + /* setup clock according to the datasheet */ + mx25_tsadc_setup_clk(pdev, tsadc); + + /* Enable clock and reset the component */ + regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_CLK_EN, + MX25_TGCR_CLK_EN); + regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_TSC_RST, + MX25_TGCR_TSC_RST); + + /* Setup powersaving mode, but enable internal reference voltage */ + regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_POWERMODE_MASK, + MX25_TGCR_POWERMODE_SAVE); + regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_INTREFEN, + MX25_TGCR_INTREFEN); + + ret = mx25_tsadc_setup_irq(pdev, tsadc); + if (ret) + return ret; + + platform_set_drvdata(pdev, tsadc); + + of_platform_populate(np, NULL, NULL, dev); + + return 0; +} + +static const struct of_device_id mx25_tsadc_ids[] = { + { .compatible = "fsl,imx25-tsadc" }, + { /* Sentinel */ } +}; + +static struct platform_driver mx25_tsadc_driver = { + .driver = { + .name = "mx25-tsadc", + .of_match_table = of_match_ptr(mx25_tsadc_ids), + }, + .probe = mx25_tsadc_probe, +}; +module_platform_driver(mx25_tsadc_driver); + +MODULE_DESCRIPTION("MFD for ADC/TSC for Freescale mx25"); +MODULE_AUTHOR("Markus Pargmann "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:mx25-tsadc"); diff --git a/include/linux/mfd/imx25-tsadc.h b/include/linux/mfd/imx25-tsadc.h new file mode 100644 index 000000000000..7fe4b8c3baac --- /dev/null +++ b/include/linux/mfd/imx25-tsadc.h @@ -0,0 +1,140 @@ +#ifndef _LINUX_INCLUDE_MFD_IMX25_TSADC_H_ +#define _LINUX_INCLUDE_MFD_IMX25_TSADC_H_ + +struct regmap; +struct clk; + +struct mx25_tsadc { + struct regmap *regs; + struct irq_domain *domain; + struct clk *clk; +}; + +#define MX25_TSC_TGCR 0x00 +#define MX25_TSC_TGSR 0x04 +#define MX25_TSC_TICR 0x08 + +/* The same register layout for TC and GC queue */ +#define MX25_ADCQ_FIFO 0x00 +#define MX25_ADCQ_CR 0x04 +#define MX25_ADCQ_SR 0x08 +#define MX25_ADCQ_MR 0x0c +#define MX25_ADCQ_ITEM_7_0 0x20 +#define MX25_ADCQ_ITEM_15_8 0x24 +#define MX25_ADCQ_CFG(n) (0x40 + ((n) * 0x4)) + +#define MX25_ADCQ_MR_MASK 0xffffffff + +/* TGCR */ +#define MX25_TGCR_PDBTIME(x) ((x) << 25) +#define MX25_TGCR_PDBTIME_MASK GENMASK(31, 25) +#define MX25_TGCR_PDBEN BIT(24) +#define MX25_TGCR_PDEN BIT(23) +#define MX25_TGCR_ADCCLKCFG(x) ((x) << 16) +#define MX25_TGCR_GET_ADCCLK(x) (((x) >> 16) & 0x1f) +#define MX25_TGCR_INTREFEN BIT(10) +#define MX25_TGCR_POWERMODE_MASK GENMASK(9, 8) +#define MX25_TGCR_POWERMODE_SAVE (1 << 8) +#define MX25_TGCR_POWERMODE_ON (2 << 8) +#define MX25_TGCR_STLC BIT(5) +#define MX25_TGCR_SLPC BIT(4) +#define MX25_TGCR_FUNC_RST BIT(2) +#define MX25_TGCR_TSC_RST BIT(1) +#define MX25_TGCR_CLK_EN BIT(0) + +/* TGSR */ +#define MX25_TGSR_SLP_INT BIT(2) +#define MX25_TGSR_GCQ_INT BIT(1) +#define MX25_TGSR_TCQ_INT BIT(0) + +/* ADCQ_ITEM_* */ +#define _MX25_ADCQ_ITEM(item, x) ((x) << ((item) * 4)) +#define MX25_ADCQ_ITEM(item, x) ((item) >= 8 ? \ + _MX25_ADCQ_ITEM((item) - 8, (x)) : _MX25_ADCQ_ITEM((item), (x))) + +/* ADCQ_FIFO (TCQFIFO and GCQFIFO) */ +#define MX25_ADCQ_FIFO_DATA(x) (((x) >> 4) & 0xfff) +#define MX25_ADCQ_FIFO_ID(x) ((x) & 0xf) + +/* ADCQ_CR (TCQR and GCQR) */ +#define MX25_ADCQ_CR_PDCFG_LEVEL BIT(19) +#define MX25_ADCQ_CR_PDMSK BIT(18) +#define MX25_ADCQ_CR_FRST BIT(17) +#define MX25_ADCQ_CR_QRST BIT(16) +#define MX25_ADCQ_CR_RWAIT_MASK GENMASK(15, 12) +#define MX25_ADCQ_CR_RWAIT(x) ((x) << 12) +#define MX25_ADCQ_CR_WMRK_MASK GENMASK(11, 8) +#define MX25_ADCQ_CR_WMRK(x) ((x) << 8) +#define MX25_ADCQ_CR_LITEMID_MASK (0xf << 4) +#define MX25_ADCQ_CR_LITEMID(x) ((x) << 4) +#define MX25_ADCQ_CR_RPT BIT(3) +#define MX25_ADCQ_CR_FQS BIT(2) +#define MX25_ADCQ_CR_QSM_MASK GENMASK(1, 0) +#define MX25_ADCQ_CR_QSM_PD 0x1 +#define MX25_ADCQ_CR_QSM_FQS 0x2 +#define MX25_ADCQ_CR_QSM_FQS_PD 0x3 + +/* ADCQ_SR (TCQSR and GCQSR) */ +#define MX25_ADCQ_SR_FDRY BIT(15) +#define MX25_ADCQ_SR_FULL BIT(14) +#define MX25_ADCQ_SR_EMPT BIT(13) +#define MX25_ADCQ_SR_FDN(x) (((x) >> 8) & 0x1f) +#define MX25_ADCQ_SR_FRR BIT(6) +#define MX25_ADCQ_SR_FUR BIT(5) +#define MX25_ADCQ_SR_FOR BIT(4) +#define MX25_ADCQ_SR_EOQ BIT(1) +#define MX25_ADCQ_SR_PD BIT(0) + +/* ADCQ_MR (TCQMR and GCQMR) */ +#define MX25_ADCQ_MR_FDRY_DMA BIT(31) +#define MX25_ADCQ_MR_FER_DMA BIT(22) +#define MX25_ADCQ_MR_FUR_DMA BIT(21) +#define MX25_ADCQ_MR_FOR_DMA BIT(20) +#define MX25_ADCQ_MR_EOQ_DMA BIT(17) +#define MX25_ADCQ_MR_PD_DMA BIT(16) +#define MX25_ADCQ_MR_FDRY_IRQ BIT(15) +#define MX25_ADCQ_MR_FER_IRQ BIT(6) +#define MX25_ADCQ_MR_FUR_IRQ BIT(5) +#define MX25_ADCQ_MR_FOR_IRQ BIT(4) +#define MX25_ADCQ_MR_EOQ_IRQ BIT(1) +#define MX25_ADCQ_MR_PD_IRQ BIT(0) + +/* ADCQ_CFG (TICR, TCC0-7,GCC0-7) */ +#define MX25_ADCQ_CFG_SETTLING_TIME(x) ((x) << 24) +#define MX25_ADCQ_CFG_IGS (1 << 20) +#define MX25_ADCQ_CFG_NOS_MASK GENMASK(19, 16) +#define MX25_ADCQ_CFG_NOS(x) (((x) - 1) << 16) +#define MX25_ADCQ_CFG_WIPER (1 << 15) +#define MX25_ADCQ_CFG_YNLR (1 << 14) +#define MX25_ADCQ_CFG_YPLL_HIGH (0 << 12) +#define MX25_ADCQ_CFG_YPLL_OFF (1 << 12) +#define MX25_ADCQ_CFG_YPLL_LOW (3 << 12) +#define MX25_ADCQ_CFG_XNUR_HIGH (0 << 10) +#define MX25_ADCQ_CFG_XNUR_OFF (1 << 10) +#define MX25_ADCQ_CFG_XNUR_LOW (3 << 10) +#define MX25_ADCQ_CFG_XPUL_HIGH (0 << 9) +#define MX25_ADCQ_CFG_XPUL_OFF (1 << 9) +#define MX25_ADCQ_CFG_REFP(sel) ((sel) << 7) +#define MX25_ADCQ_CFG_REFP_YP MX25_ADCQ_CFG_REFP(0) +#define MX25_ADCQ_CFG_REFP_XP MX25_ADCQ_CFG_REFP(1) +#define MX25_ADCQ_CFG_REFP_EXT MX25_ADCQ_CFG_REFP(2) +#define MX25_ADCQ_CFG_REFP_INT MX25_ADCQ_CFG_REFP(3) +#define MX25_ADCQ_CFG_REFP_MASK GENMASK(8, 7) +#define MX25_ADCQ_CFG_IN(sel) ((sel) << 4) +#define MX25_ADCQ_CFG_IN_XP MX25_ADCQ_CFG_IN(0) +#define MX25_ADCQ_CFG_IN_YP MX25_ADCQ_CFG_IN(1) +#define MX25_ADCQ_CFG_IN_XN MX25_ADCQ_CFG_IN(2) +#define MX25_ADCQ_CFG_IN_YN MX25_ADCQ_CFG_IN(3) +#define MX25_ADCQ_CFG_IN_WIPER MX25_ADCQ_CFG_IN(4) +#define MX25_ADCQ_CFG_IN_AUX0 MX25_ADCQ_CFG_IN(5) +#define MX25_ADCQ_CFG_IN_AUX1 MX25_ADCQ_CFG_IN(6) +#define MX25_ADCQ_CFG_IN_AUX2 MX25_ADCQ_CFG_IN(7) +#define MX25_ADCQ_CFG_REFN(sel) ((sel) << 2) +#define MX25_ADCQ_CFG_REFN_XN MX25_ADCQ_CFG_REFN(0) +#define MX25_ADCQ_CFG_REFN_YN MX25_ADCQ_CFG_REFN(1) +#define MX25_ADCQ_CFG_REFN_NGND MX25_ADCQ_CFG_REFN(2) +#define MX25_ADCQ_CFG_REFN_NGND2 MX25_ADCQ_CFG_REFN(3) +#define MX25_ADCQ_CFG_REFN_MASK GENMASK(3, 2) +#define MX25_ADCQ_CFG_PENIACK (1 << 1) + +#endif /* _LINUX_INCLUDE_MFD_IMX25_TSADC_H_ */ -- cgit From 6df2e98c3ea567bd15b46369180266d4c4df3447 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 14:53:51 +0100 Subject: iio: adc: Add imx25-gcq ADC driver This is a conversion queue driver for the mx25 SoC. It uses the central ADC which is used by two seperate independent queues. This driver prepares different conversion configurations for each possible input. For a conversion it creates a conversionqueue of one item with the correct configuration for the chosen channel. It then executes the queue once and disables the conversion queue afterwards. The reference voltages are configurable through devicetree subnodes, depending on the connections of the ADC inputs. Signed-off-by: Markus Pargmann Signed-off-by: Denis Carikli Acked-by: Jonathan Cameron Signed-off-by: Lee Jones --- drivers/iio/adc/Kconfig | 7 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/fsl-imx25-gcq.c | 417 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 425 insertions(+) create mode 100644 drivers/iio/adc/fsl-imx25-gcq.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 605ff42c4631..a7ec74bffa5b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -183,6 +183,13 @@ config EXYNOS_ADC To compile this driver as a module, choose M here: the module will be called exynos_adc. +config FSL_MX25_ADC + tristate "Freescale MX25 ADC driver" + depends on MFD_MX25_TSADC + help + Generic Conversion Queue driver used for general purpose ADC in the + MX25. This driver supports single measurements using the MX25 ADC. + config HI8435 tristate "Holt Integrated Circuits HI-8435 threshold detector" select IIO_TRIGGERED_EVENT diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 6435780e9b71..151088f03258 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o +obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o diff --git a/drivers/iio/adc/fsl-imx25-gcq.c b/drivers/iio/adc/fsl-imx25-gcq.c new file mode 100644 index 000000000000..2fd192735d5b --- /dev/null +++ b/drivers/iio/adc/fsl-imx25-gcq.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann + * + * 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 is the driver for the imx25 GCQ (Generic Conversion Queue) + * connected to the imx25 ADC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MX25_GCQ_TIMEOUT (msecs_to_jiffies(2000)) + +static const char * const driver_name = "mx25-gcq"; + +enum mx25_gcq_cfgs { + MX25_CFG_XP = 0, + MX25_CFG_YP, + MX25_CFG_XN, + MX25_CFG_YN, + MX25_CFG_WIPER, + MX25_CFG_INAUX0, + MX25_CFG_INAUX1, + MX25_CFG_INAUX2, + MX25_NUM_CFGS, +}; + +struct mx25_gcq_priv { + struct regmap *regs; + struct completion completed; + struct clk *clk; + int irq; + struct regulator *vref[4]; + u32 channel_vref_mv[MX25_NUM_CFGS]; +}; + +#define MX25_CQG_CHAN(chan, id) {\ + .type = IIO_VOLTAGE,\ + .indexed = 1,\ + .channel = chan,\ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE),\ + .datasheet_name = id,\ +} + +static const struct iio_chan_spec mx25_gcq_channels[MX25_NUM_CFGS] = { + MX25_CQG_CHAN(MX25_CFG_XP, "xp"), + MX25_CQG_CHAN(MX25_CFG_YP, "yp"), + MX25_CQG_CHAN(MX25_CFG_XN, "xn"), + MX25_CQG_CHAN(MX25_CFG_YN, "yn"), + MX25_CQG_CHAN(MX25_CFG_WIPER, "wiper"), + MX25_CQG_CHAN(MX25_CFG_INAUX0, "inaux0"), + MX25_CQG_CHAN(MX25_CFG_INAUX1, "inaux1"), + MX25_CQG_CHAN(MX25_CFG_INAUX2, "inaux2"), +}; + +static const char * const mx25_gcq_refp_names[] = { + [MX25_ADC_REFP_YP] = "yp", + [MX25_ADC_REFP_XP] = "xp", + [MX25_ADC_REFP_INT] = "int", + [MX25_ADC_REFP_EXT] = "ext", +}; + +static irqreturn_t mx25_gcq_irq(int irq, void *data) +{ + struct mx25_gcq_priv *priv = data; + u32 stats; + + regmap_read(priv->regs, MX25_ADCQ_SR, &stats); + + if (stats & MX25_ADCQ_SR_EOQ) { + regmap_update_bits(priv->regs, MX25_ADCQ_MR, + MX25_ADCQ_MR_EOQ_IRQ, MX25_ADCQ_MR_EOQ_IRQ); + complete(&priv->completed); + } + + /* Disable conversion queue run */ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, 0); + + /* Acknowledge all possible irqs */ + regmap_write(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR | + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | + MX25_ADCQ_SR_EOQ | MX25_ADCQ_SR_PD); + + return IRQ_HANDLED; +} + +static int mx25_gcq_get_raw_value(struct device *dev, + struct iio_chan_spec const *chan, + struct mx25_gcq_priv *priv, + int *val) +{ + long timeout; + u32 data; + + /* Setup the configuration we want to use */ + regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0, + MX25_ADCQ_ITEM(0, chan->channel)); + + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_EOQ_IRQ, 0); + + /* Trigger queue for one run */ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FQS, + MX25_ADCQ_CR_FQS); + + timeout = wait_for_completion_interruptible_timeout( + &priv->completed, MX25_GCQ_TIMEOUT); + if (timeout < 0) { + dev_err(dev, "ADC wait for measurement failed\n"); + return timeout; + } else if (timeout == 0) { + dev_err(dev, "ADC timed out\n"); + return -ETIMEDOUT; + } + + regmap_read(priv->regs, MX25_ADCQ_FIFO, &data); + + *val = MX25_ADCQ_FIFO_DATA(data); + + return IIO_VAL_INT; +} + +static int mx25_gcq_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct mx25_gcq_priv *priv = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&indio_dev->mlock); + ret = mx25_gcq_get_raw_value(&indio_dev->dev, chan, priv, val); + mutex_unlock(&indio_dev->mlock); + return ret; + + case IIO_CHAN_INFO_SCALE: + *val = priv->channel_vref_mv[chan->channel]; + *val2 = 12; + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } +} + +static const struct iio_info mx25_gcq_iio_info = { + .read_raw = mx25_gcq_read_raw, +}; + +static const struct regmap_config mx25_gcq_regconfig = { + .max_register = 0x5c, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int mx25_gcq_setup_cfgs(struct platform_device *pdev, + struct mx25_gcq_priv *priv) +{ + struct device_node *np = pdev->dev.of_node; + struct device_node *child; + struct device *dev = &pdev->dev; + unsigned int refp_used[4] = {}; + int ret, i; + + /* + * Setup all configurations registers with a default conversion + * configuration for each input + */ + for (i = 0; i < MX25_NUM_CFGS; ++i) + regmap_write(priv->regs, MX25_ADCQ_CFG(i), + MX25_ADCQ_CFG_YPLL_OFF | + MX25_ADCQ_CFG_XNUR_OFF | + MX25_ADCQ_CFG_XPUL_OFF | + MX25_ADCQ_CFG_REFP_INT | + MX25_ADCQ_CFG_IN(i) | + MX25_ADCQ_CFG_REFN_NGND2); + + /* + * First get all regulators to store them in channel_vref_mv if + * necessary. Later we use that information for proper IIO scale + * information. + */ + priv->vref[MX25_ADC_REFP_INT] = NULL; + priv->vref[MX25_ADC_REFP_EXT] = + devm_regulator_get_optional(&pdev->dev, "vref-ext"); + priv->vref[MX25_ADC_REFP_XP] = + devm_regulator_get_optional(&pdev->dev, "vref-xp"); + priv->vref[MX25_ADC_REFP_YP] = + devm_regulator_get_optional(&pdev->dev, "vref-yp"); + + for_each_child_of_node(np, child) { + u32 reg; + u32 refp = MX25_ADCQ_CFG_REFP_INT; + u32 refn = MX25_ADCQ_CFG_REFN_NGND2; + + ret = of_property_read_u32(child, "reg", ®); + if (ret) { + dev_err(dev, "Failed to get reg property\n"); + return ret; + } + + if (reg >= MX25_NUM_CFGS) { + dev_err(dev, + "reg value is greater than the number of available configuration registers\n"); + return -EINVAL; + } + + of_property_read_u32(child, "fsl,adc-refp", &refp); + of_property_read_u32(child, "fsl,adc-refn", &refn); + + switch (refp) { + case MX25_ADC_REFP_EXT: + case MX25_ADC_REFP_XP: + case MX25_ADC_REFP_YP: + if (IS_ERR(priv->vref[refp])) { + dev_err(dev, "Error, trying to use external voltage reference without a vref-%s regulator.", + mx25_gcq_refp_names[refp]); + return PTR_ERR(priv->vref[refp]); + } + priv->channel_vref_mv[reg] = + regulator_get_voltage(priv->vref[refp]); + /* Conversion from uV to mV */ + do_div(priv->channel_vref_mv[reg], 1000); + break; + case MX25_ADC_REFP_INT: + priv->channel_vref_mv[reg] = 2500; + break; + default: + dev_err(dev, "Invalid positive reference %d\n", refp); + return -EINVAL; + } + + ++refp_used[refp]; + + /* + * Shift the read values to the correct positions within the + * register. + */ + refp = MX25_ADCQ_CFG_REFP(refp); + refn = MX25_ADCQ_CFG_REFN(refn); + + if ((refp & MX25_ADCQ_CFG_REFP_MASK) != refp) { + dev_err(dev, "Invalid fsl,adc-refp property value\n"); + return -EINVAL; + } + if ((refn & MX25_ADCQ_CFG_REFN_MASK) != refn) { + dev_err(dev, "Invalid fsl,adc-refn property value\n"); + return -EINVAL; + } + + regmap_update_bits(priv->regs, MX25_ADCQ_CFG(reg), + MX25_ADCQ_CFG_REFP_MASK | + MX25_ADCQ_CFG_REFN_MASK, + refp | refn); + } + regmap_update_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST, + MX25_ADCQ_CR_FRST | MX25_ADCQ_CR_QRST); + + regmap_write(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_PDMSK | MX25_ADCQ_CR_QSM_FQS); + + /* Remove unused regulators */ + for (i = 0; i != 4; ++i) { + if (!refp_used[i]) { + if (!IS_ERR_OR_NULL(priv->vref[i])) + devm_regulator_put(priv->vref[i]); + priv->vref[i] = NULL; + } + } + + return 0; +} + +static int mx25_gcq_probe(struct platform_device *pdev) +{ + struct iio_dev *indio_dev; + struct mx25_gcq_priv *priv; + struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *mem; + int ret; + int i; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + priv = iio_priv(indio_dev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem = devm_ioremap_resource(dev, res); + if (IS_ERR(mem)) + return PTR_ERR(mem); + + priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_gcq_regconfig); + if (IS_ERR(priv->regs)) { + dev_err(dev, "Failed to initialize regmap\n"); + return PTR_ERR(priv->regs); + } + + init_completion(&priv->completed); + + ret = mx25_gcq_setup_cfgs(pdev, priv); + if (ret) + return ret; + + for (i = 0; i != 4; ++i) { + if (!priv->vref[i]) + continue; + + ret = regulator_enable(priv->vref[i]); + if (ret) + goto err_regulator_disable; + } + + priv->clk = tsadc->clk; + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "Failed to enable clock\n"); + goto err_vref_disable; + } + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq <= 0) { + dev_err(dev, "Failed to get IRQ\n"); + ret = priv->irq; + if (!ret) + ret = -ENXIO; + goto err_clk_unprepare; + } + + ret = request_irq(priv->irq, mx25_gcq_irq, 0, pdev->name, priv); + if (ret) { + dev_err(dev, "Failed requesting IRQ\n"); + goto err_clk_unprepare; + } + + indio_dev->dev.parent = &pdev->dev; + indio_dev->channels = mx25_gcq_channels; + indio_dev->num_channels = ARRAY_SIZE(mx25_gcq_channels); + indio_dev->info = &mx25_gcq_iio_info; + indio_dev->name = driver_name; + + ret = iio_device_register(indio_dev); + if (ret) { + dev_err(dev, "Failed to register iio device\n"); + goto err_irq_free; + } + + platform_set_drvdata(pdev, indio_dev); + + return 0; + +err_irq_free: + free_irq(priv->irq, priv); +err_clk_unprepare: + clk_disable_unprepare(priv->clk); +err_vref_disable: + i = 4; +err_regulator_disable: + for (; i-- > 0;) { + if (priv->vref[i]) + regulator_disable(priv->vref[i]); + } + return ret; +} + +static int mx25_gcq_remove(struct platform_device *pdev) +{ + struct iio_dev *indio_dev = platform_get_drvdata(pdev); + struct mx25_gcq_priv *priv = iio_priv(indio_dev); + int i; + + iio_device_unregister(indio_dev); + free_irq(priv->irq, priv); + clk_disable_unprepare(priv->clk); + for (i = 4; i-- > 0;) { + if (priv->vref[i]) + regulator_disable(priv->vref[i]); + } + + return 0; +} + +static const struct of_device_id mx25_gcq_ids[] = { + { .compatible = "fsl,imx25-gcq", }, + { /* Sentinel */ } +}; + +static struct platform_driver mx25_gcq_driver = { + .driver = { + .name = "mx25-gcq", + .of_match_table = mx25_gcq_ids, + }, + .probe = mx25_gcq_probe, + .remove = mx25_gcq_remove, +}; +module_platform_driver(mx25_gcq_driver); + +MODULE_DESCRIPTION("ADC driver for Freescale mx25"); +MODULE_AUTHOR("Markus Pargmann "); +MODULE_LICENSE("GPL v2"); -- cgit From 4f7ed234f2a5dcc26fc56a6e8324d34bbc9afe23 Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 14 Dec 2015 14:53:52 +0100 Subject: Input: touchscreen: Add imx25 TCQ driver This is a driver for the imx25 ADC/TSC module. It controls the touchscreen conversion queue and creates a touchscreen input device. The driver currently only supports 4 wire touchscreens. The driver uses a simple conversion queue of precharge, touch detection, X measurement, Y measurement, precharge and another touch detection. This driver uses the regmap from the parent to setup some touch specific settings in the core driver and setup a idle configuration with touch detection. Signed-off-by: Markus Pargmann Signed-off-by: Denis Carikli [fix clock's period calculation] [fix calculation of the 'settling' value] Signed-off-by: Juergen Borleis Acked-by: Dmitry Torokhov Signed-off-by: Lee Jones --- drivers/input/touchscreen/Kconfig | 9 + drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/fsl-imx25-tcq.c | 596 ++++++++++++++++++++++++++++++ 3 files changed, 606 insertions(+) create mode 100644 drivers/input/touchscreen/fsl-imx25-tcq.c diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 66c62641b59a..a768806d2dbd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -822,6 +822,15 @@ config TOUCHSCREEN_USB_COMPOSITE To compile this driver as a module, choose M here: the module will be called usbtouchscreen. +config TOUCHSCREEN_MX25 + tristate "Freescale i.MX25 touchscreen input driver" + depends on MFD_MX25_TSADC + help + Enable support for touchscreen connected to your i.MX25. + + To compile this driver as a module, choose M here: the + module will be called fsl-imx25-tcq. + config TOUCHSCREEN_MC13783 tristate "Freescale MC13783 touchscreen input driver" depends on MFD_MC13XXX diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 968ff12e3132..49134efce85f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o obj-$(CONFIG_TOUCHSCREEN_IPROC) += bcm_iproc_tsc.o obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o +obj-$(CONFIG_TOUCHSCREEN_MX25) += fsl-imx25-tcq.o obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c new file mode 100644 index 000000000000..fe9877a6af9e --- /dev/null +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2014-2015 Pengutronix, Markus Pargmann + * + * 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. + * + * Based on driver from 2011: + * Juergen Beisert, Pengutronix + * + * This is the driver for the imx25 TCQ (Touchscreen Conversion Queue) + * connected to the imx25 ADC. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char mx25_tcq_name[] = "mx25-tcq"; + +enum mx25_tcq_mode { + MX25_TS_4WIRE, +}; + +struct mx25_tcq_priv { + struct regmap *regs; + struct regmap *core_regs; + struct input_dev *idev; + enum mx25_tcq_mode mode; + unsigned int pen_threshold; + unsigned int sample_count; + unsigned int expected_samples; + unsigned int pen_debounce; + unsigned int settling_time; + struct clk *clk; + int irq; + struct device *dev; +}; + +static struct regmap_config mx25_tcq_regconfig = { + .fast_io = true, + .max_register = 0x5c, + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static const struct of_device_id mx25_tcq_ids[] = { + { .compatible = "fsl,imx25-tcq", }, + { /* Sentinel */ } +}; + +#define TSC_4WIRE_PRE_INDEX 0 +#define TSC_4WIRE_X_INDEX 1 +#define TSC_4WIRE_Y_INDEX 2 +#define TSC_4WIRE_POST_INDEX 3 +#define TSC_4WIRE_LEAVE 4 + +#define MX25_TSC_DEF_THRESHOLD 80 +#define TSC_MAX_SAMPLES 16 + +#define MX25_TSC_REPEAT_WAIT 14 + +enum mx25_adc_configurations { + MX25_CFG_PRECHARGE = 0, + MX25_CFG_TOUCH_DETECT, + MX25_CFG_X_MEASUREMENT, + MX25_CFG_Y_MEASUREMENT, +}; + +#define MX25_PRECHARGE_VALUE (\ + MX25_ADCQ_CFG_YPLL_OFF | \ + MX25_ADCQ_CFG_XNUR_OFF | \ + MX25_ADCQ_CFG_XPUL_HIGH | \ + MX25_ADCQ_CFG_REFP_INT | \ + MX25_ADCQ_CFG_IN_XP | \ + MX25_ADCQ_CFG_REFN_NGND2 | \ + MX25_ADCQ_CFG_IGS) + +#define MX25_TOUCH_DETECT_VALUE (\ + MX25_ADCQ_CFG_YNLR | \ + MX25_ADCQ_CFG_YPLL_OFF | \ + MX25_ADCQ_CFG_XNUR_OFF | \ + MX25_ADCQ_CFG_XPUL_OFF | \ + MX25_ADCQ_CFG_REFP_INT | \ + MX25_ADCQ_CFG_IN_XP | \ + MX25_ADCQ_CFG_REFN_NGND2 | \ + MX25_ADCQ_CFG_PENIACK) + +static void imx25_setup_queue_cfgs(struct mx25_tcq_priv *priv, + unsigned int settling_cnt) +{ + u32 precharge_cfg = + MX25_PRECHARGE_VALUE | + MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt); + u32 touch_detect_cfg = + MX25_TOUCH_DETECT_VALUE | + MX25_ADCQ_CFG_NOS(1) | + MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt); + + regmap_write(priv->core_regs, MX25_TSC_TICR, precharge_cfg); + + /* PRECHARGE */ + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_PRECHARGE), + precharge_cfg); + + /* TOUCH_DETECT */ + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_TOUCH_DETECT), + touch_detect_cfg); + + /* X Measurement */ + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_X_MEASUREMENT), + MX25_ADCQ_CFG_YPLL_OFF | + MX25_ADCQ_CFG_XNUR_LOW | + MX25_ADCQ_CFG_XPUL_HIGH | + MX25_ADCQ_CFG_REFP_XP | + MX25_ADCQ_CFG_IN_YP | + MX25_ADCQ_CFG_REFN_XN | + MX25_ADCQ_CFG_NOS(priv->sample_count) | + MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt)); + + /* Y Measurement */ + regmap_write(priv->regs, MX25_ADCQ_CFG(MX25_CFG_Y_MEASUREMENT), + MX25_ADCQ_CFG_YNLR | + MX25_ADCQ_CFG_YPLL_HIGH | + MX25_ADCQ_CFG_XNUR_OFF | + MX25_ADCQ_CFG_XPUL_OFF | + MX25_ADCQ_CFG_REFP_YP | + MX25_ADCQ_CFG_IN_XP | + MX25_ADCQ_CFG_REFN_YN | + MX25_ADCQ_CFG_NOS(priv->sample_count) | + MX25_ADCQ_CFG_SETTLING_TIME(settling_cnt)); + + /* Enable the touch detection right now */ + regmap_write(priv->core_regs, MX25_TSC_TICR, touch_detect_cfg | + MX25_ADCQ_CFG_IGS); +} + +static int imx25_setup_queue_4wire(struct mx25_tcq_priv *priv, + unsigned settling_cnt, int *items) +{ + imx25_setup_queue_cfgs(priv, settling_cnt); + + /* Setup the conversion queue */ + regmap_write(priv->regs, MX25_ADCQ_ITEM_7_0, + MX25_ADCQ_ITEM(0, MX25_CFG_PRECHARGE) | + MX25_ADCQ_ITEM(1, MX25_CFG_TOUCH_DETECT) | + MX25_ADCQ_ITEM(2, MX25_CFG_X_MEASUREMENT) | + MX25_ADCQ_ITEM(3, MX25_CFG_Y_MEASUREMENT) | + MX25_ADCQ_ITEM(4, MX25_CFG_PRECHARGE) | + MX25_ADCQ_ITEM(5, MX25_CFG_TOUCH_DETECT)); + + /* + * We measure X/Y with 'sample_count' number of samples and execute a + * touch detection twice, with 1 sample each + */ + priv->expected_samples = priv->sample_count * 2 + 2; + *items = 6; + + return 0; +} + +static void mx25_tcq_disable_touch_irq(struct mx25_tcq_priv *priv) +{ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK, + MX25_ADCQ_CR_PDMSK); +} + +static void mx25_tcq_enable_touch_irq(struct mx25_tcq_priv *priv) +{ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_PDMSK, 0); +} + +static void mx25_tcq_disable_fifo_irq(struct mx25_tcq_priv *priv) +{ + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ, + MX25_ADCQ_MR_FDRY_IRQ); +} + +static void mx25_tcq_enable_fifo_irq(struct mx25_tcq_priv *priv) +{ + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_FDRY_IRQ, 0); +} + +static void mx25_tcq_force_queue_start(struct mx25_tcq_priv *priv) +{ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_FQS, + MX25_ADCQ_CR_FQS); +} + +static void mx25_tcq_force_queue_stop(struct mx25_tcq_priv *priv) +{ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_FQS, 0); +} + +static void mx25_tcq_fifo_reset(struct mx25_tcq_priv *priv) +{ + u32 tcqcr; + + regmap_read(priv->regs, MX25_ADCQ_CR, &tcqcr); + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST, + MX25_ADCQ_CR_FRST); + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_FRST, 0); + regmap_write(priv->regs, MX25_ADCQ_CR, tcqcr); +} + +static void mx25_tcq_re_enable_touch_detection(struct mx25_tcq_priv *priv) +{ + /* stop the queue from looping */ + mx25_tcq_force_queue_stop(priv); + + /* for a clean touch detection, preload the X plane */ + regmap_write(priv->core_regs, MX25_TSC_TICR, MX25_PRECHARGE_VALUE); + + /* waste some time now to pre-load the X plate to high voltage */ + mx25_tcq_fifo_reset(priv); + + /* re-enable the detection right now */ + regmap_write(priv->core_regs, MX25_TSC_TICR, + MX25_TOUCH_DETECT_VALUE | MX25_ADCQ_CFG_IGS); + + regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_PD, + MX25_ADCQ_SR_PD); + + /* enable the pen down event to be a source for the interrupt */ + regmap_update_bits(priv->regs, MX25_ADCQ_MR, MX25_ADCQ_MR_PD_IRQ, 0); + + /* lets fire the next IRQ if someone touches the touchscreen */ + mx25_tcq_enable_touch_irq(priv); +} + +static void mx25_tcq_create_event_for_4wire(struct mx25_tcq_priv *priv, + u32 *sample_buf, + unsigned int samples) +{ + unsigned int x_pos = 0; + unsigned int y_pos = 0; + unsigned int touch_pre = 0; + unsigned int touch_post = 0; + unsigned int i; + + for (i = 0; i < samples; i++) { + unsigned int index = MX25_ADCQ_FIFO_ID(sample_buf[i]); + unsigned int val = MX25_ADCQ_FIFO_DATA(sample_buf[i]); + + switch (index) { + case 1: + touch_pre = val; + break; + case 2: + x_pos = val; + break; + case 3: + y_pos = val; + break; + case 5: + touch_post = val; + break; + default: + dev_dbg(priv->dev, "Dropped samples because of invalid index %d\n", + index); + return; + } + } + + if (samples != 0) { + /* + * only if both touch measures are below a threshold, + * the position is valid + */ + if (touch_pre < priv->pen_threshold && + touch_post < priv->pen_threshold) { + /* valid samples, generate a report */ + x_pos /= priv->sample_count; + y_pos /= priv->sample_count; + input_report_abs(priv->idev, ABS_X, x_pos); + input_report_abs(priv->idev, ABS_Y, y_pos); + input_report_key(priv->idev, BTN_TOUCH, 1); + input_sync(priv->idev); + + /* get next sample */ + mx25_tcq_enable_fifo_irq(priv); + } else if (touch_pre >= priv->pen_threshold && + touch_post >= priv->pen_threshold) { + /* + * if both samples are invalid, + * generate a release report + */ + input_report_key(priv->idev, BTN_TOUCH, 0); + input_sync(priv->idev); + mx25_tcq_re_enable_touch_detection(priv); + } else { + /* + * if only one of both touch measurements are + * below the threshold, still some bouncing + * happens. Take additional samples in this + * case to be sure + */ + mx25_tcq_enable_fifo_irq(priv); + } + } +} + +static irqreturn_t mx25_tcq_irq_thread(int irq, void *dev_id) +{ + struct mx25_tcq_priv *priv = dev_id; + u32 sample_buf[TSC_MAX_SAMPLES]; + unsigned int samples; + u32 stats; + unsigned int i; + + /* + * Check how many samples are available. We always have to read exactly + * sample_count samples from the fifo, or a multiple of sample_count. + * Otherwise we mixup samples into different touch events. + */ + regmap_read(priv->regs, MX25_ADCQ_SR, &stats); + samples = MX25_ADCQ_SR_FDN(stats); + samples -= samples % priv->sample_count; + + if (!samples) + return IRQ_HANDLED; + + for (i = 0; i != samples; ++i) + regmap_read(priv->regs, MX25_ADCQ_FIFO, &sample_buf[i]); + + mx25_tcq_create_event_for_4wire(priv, sample_buf, samples); + + return IRQ_HANDLED; +} + +static irqreturn_t mx25_tcq_irq(int irq, void *dev_id) +{ + struct mx25_tcq_priv *priv = dev_id; + u32 stat; + int ret = IRQ_HANDLED; + + regmap_read(priv->regs, MX25_ADCQ_SR, &stat); + + if (stat & (MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR)) + mx25_tcq_re_enable_touch_detection(priv); + + if (stat & MX25_ADCQ_SR_PD) { + mx25_tcq_disable_touch_irq(priv); + mx25_tcq_force_queue_start(priv); + mx25_tcq_enable_fifo_irq(priv); + } + + if (stat & MX25_ADCQ_SR_FDRY) { + mx25_tcq_disable_fifo_irq(priv); + ret = IRQ_WAKE_THREAD; + } + + regmap_update_bits(priv->regs, MX25_ADCQ_SR, MX25_ADCQ_SR_FRR | + MX25_ADCQ_SR_FUR | MX25_ADCQ_SR_FOR | + MX25_ADCQ_SR_PD, + MX25_ADCQ_SR_FRR | MX25_ADCQ_SR_FUR | + MX25_ADCQ_SR_FOR | MX25_ADCQ_SR_PD); + + return ret; +} + +/* configure the state machine for a 4-wire touchscreen */ +static int mx25_tcq_init(struct mx25_tcq_priv *priv) +{ + u32 tgcr; + unsigned int ipg_div; + unsigned int adc_period; + unsigned int debounce_cnt; + unsigned int settling_cnt; + int itemct; + int error; + + regmap_read(priv->core_regs, MX25_TSC_TGCR, &tgcr); + ipg_div = max_t(unsigned int, 4, MX25_TGCR_GET_ADCCLK(tgcr)); + adc_period = USEC_PER_SEC * ipg_div * 2 + 2; + adc_period /= clk_get_rate(priv->clk) / 1000 + 1; + debounce_cnt = DIV_ROUND_UP(priv->pen_debounce, adc_period * 8) - 1; + settling_cnt = DIV_ROUND_UP(priv->settling_time, adc_period * 8) - 1; + + /* Reset */ + regmap_write(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_QRST | MX25_ADCQ_CR_FRST); + regmap_update_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_QRST | MX25_ADCQ_CR_FRST, 0); + + /* up to 128 * 8 ADC clocks are possible */ + if (debounce_cnt > 127) + debounce_cnt = 127; + + /* up to 255 * 8 ADC clocks are possible */ + if (settling_cnt > 255) + settling_cnt = 255; + + error = imx25_setup_queue_4wire(priv, settling_cnt, &itemct); + if (error) + return error; + + regmap_update_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_LITEMID_MASK | MX25_ADCQ_CR_WMRK_MASK, + MX25_ADCQ_CR_LITEMID(itemct - 1) | + MX25_ADCQ_CR_WMRK(priv->expected_samples - 1)); + + /* setup debounce count */ + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, + MX25_TGCR_PDBTIME_MASK, + MX25_TGCR_PDBTIME(debounce_cnt)); + + /* enable debounce */ + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDBEN, + MX25_TGCR_PDBEN); + regmap_update_bits(priv->core_regs, MX25_TSC_TGCR, MX25_TGCR_PDEN, + MX25_TGCR_PDEN); + + /* enable the engine on demand */ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, MX25_ADCQ_CR_QSM_MASK, + MX25_ADCQ_CR_QSM_FQS); + + /* Enable repeat and repeat wait */ + regmap_update_bits(priv->regs, MX25_ADCQ_CR, + MX25_ADCQ_CR_RPT | MX25_ADCQ_CR_RWAIT_MASK, + MX25_ADCQ_CR_RPT | + MX25_ADCQ_CR_RWAIT(MX25_TSC_REPEAT_WAIT)); + + return 0; +} + +static int mx25_tcq_parse_dt(struct platform_device *pdev, + struct mx25_tcq_priv *priv) +{ + struct device_node *np = pdev->dev.of_node; + u32 wires; + int error; + + /* Setup defaults */ + priv->pen_threshold = 500; + priv->sample_count = 3; + priv->pen_debounce = 1000000; + priv->settling_time = 250000; + + error = of_property_read_u32(np, "fsl,wires", &wires); + if (error) { + dev_err(&pdev->dev, "Failed to find fsl,wires properties\n"); + return error; + } + + if (wires == 4) { + priv->mode = MX25_TS_4WIRE; + } else { + dev_err(&pdev->dev, "%u-wire mode not supported\n", wires); + return -EINVAL; + } + + /* These are optional, we don't care about the return values */ + of_property_read_u32(np, "fsl,pen-threshold", &priv->pen_threshold); + of_property_read_u32(np, "fsl,settling-time-ns", &priv->settling_time); + of_property_read_u32(np, "fsl,pen-debounce-ns", &priv->pen_debounce); + + return 0; +} + +static int mx25_tcq_open(struct input_dev *idev) +{ + struct device *dev = &idev->dev; + struct mx25_tcq_priv *priv = dev_get_drvdata(dev); + int error; + + error = clk_prepare_enable(priv->clk); + if (error) { + dev_err(dev, "Failed to enable ipg clock\n"); + return error; + } + + error = mx25_tcq_init(priv); + if (error) { + dev_err(dev, "Failed to init tcq\n"); + clk_disable_unprepare(priv->clk); + return error; + } + + mx25_tcq_re_enable_touch_detection(priv); + + return 0; +} + +static void mx25_tcq_close(struct input_dev *idev) +{ + struct mx25_tcq_priv *priv = input_get_drvdata(idev); + + mx25_tcq_force_queue_stop(priv); + mx25_tcq_disable_touch_irq(priv); + mx25_tcq_disable_fifo_irq(priv); + clk_disable_unprepare(priv->clk); +} + +static int mx25_tcq_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct input_dev *idev; + struct mx25_tcq_priv *priv; + struct mx25_tsadc *tsadc = dev_get_drvdata(pdev->dev.parent); + struct resource *res; + void __iomem *mem; + int error; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem = devm_ioremap_resource(dev, res); + if (IS_ERR(mem)) + return PTR_ERR(mem); + + error = mx25_tcq_parse_dt(pdev, priv); + if (error) + return error; + + priv->regs = devm_regmap_init_mmio(dev, mem, &mx25_tcq_regconfig); + if (IS_ERR(priv->regs)) { + dev_err(dev, "Failed to initialize regmap\n"); + return PTR_ERR(priv->regs); + } + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq <= 0) { + dev_err(dev, "Failed to get IRQ\n"); + return priv->irq; + } + + idev = devm_input_allocate_device(dev); + if (!idev) { + dev_err(dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + + idev->name = mx25_tcq_name; + input_set_capability(idev, EV_KEY, BTN_TOUCH); + input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0); + input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0); + + idev->id.bustype = BUS_HOST; + idev->open = mx25_tcq_open; + idev->close = mx25_tcq_close; + + priv->idev = idev; + input_set_drvdata(idev, priv); + + priv->core_regs = tsadc->regs; + if (!priv->core_regs) + return -EINVAL; + + priv->clk = tsadc->clk; + if (!priv->clk) + return -EINVAL; + + platform_set_drvdata(pdev, priv); + + error = devm_request_threaded_irq(dev, priv->irq, mx25_tcq_irq, + mx25_tcq_irq_thread, 0, pdev->name, + priv); + if (error) { + dev_err(dev, "Failed requesting IRQ\n"); + return error; + } + + error = input_register_device(idev); + if (error) { + dev_err(dev, "Failed to register input device\n"); + return error; + } + + return 0; +} + +static struct platform_driver mx25_tcq_driver = { + .driver = { + .name = "mx25-tcq", + .of_match_table = mx25_tcq_ids, + }, + .probe = mx25_tcq_probe, +}; +module_platform_driver(mx25_tcq_driver); + +MODULE_DESCRIPTION("TS input driver for Freescale mx25"); +MODULE_AUTHOR("Markus Pargmann "); +MODULE_LICENSE("GPL v2"); -- cgit From 02afa9a87b232bca15bc30808b9310c6388ca1a8 Mon Sep 17 00:00:00 2001 From: Chris Brandt Date: Tue, 9 Feb 2016 19:34:43 +0100 Subject: ARM: 8518/1: Use correct symbols for XIP_KERNEL For an XIP build, _etext does not represent the end of the binary image that needs to stay mapped into the MODULES_VADDR area. Years ago, data came before text in the memory map. However, now that the order is text/init/data, an XIP_KERNEL needs to map up to the data location in order to keep from cutting off parts of the kernel that are needed. We only map up to the beginning of data because data has already been copied, so there's no reason to keep it around anymore. A new symbol is created to make it clear what it is we are referring to. This fixes the bug where you might lose the end of your kernel area after page table setup is complete. Signed-off-by: Chris Brandt Signed-off-by: Russell King --- arch/arm/include/asm/Kbuild | 1 - arch/arm/include/asm/sections.h | 8 ++++++++ arch/arm/kernel/module.c | 2 +- arch/arm/kernel/vmlinux-xip.lds.S | 2 ++ arch/arm/mm/mmu.c | 8 ++++++-- 5 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 arch/arm/include/asm/sections.h diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 16da6380eb85..3f6616b472af 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -23,7 +23,6 @@ generic-y += preempt.h generic-y += resource.h generic-y += rwsem.h generic-y += seccomp.h -generic-y += sections.h generic-y += segment.h generic-y += sembuf.h generic-y += serial.h diff --git a/arch/arm/include/asm/sections.h b/arch/arm/include/asm/sections.h new file mode 100644 index 000000000000..803bbf2b20b8 --- /dev/null +++ b/arch/arm/include/asm/sections.h @@ -0,0 +1,8 @@ +#ifndef _ASM_ARM_SECTIONS_H +#define _ASM_ARM_SECTIONS_H + +#include + +extern char _exiprom[]; + +#endif /* _ASM_ARM_SECTIONS_H */ diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index efdddcb97dd1..4f14b5ce6535 100644 --- a/arch/arm/kernel/module.c +++ b/arch/arm/kernel/module.c @@ -34,7 +34,7 @@ * recompiling the whole kernel when CONFIG_XIP_KERNEL is turned on/off. */ #undef MODULES_VADDR -#define MODULES_VADDR (((unsigned long)_etext + ~PMD_MASK) & PMD_MASK) +#define MODULES_VADDR (((unsigned long)_exiprom + ~PMD_MASK) & PMD_MASK) #endif #ifdef CONFIG_MMU diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index 7b1ded6fb628..40bc4cadb959 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -85,6 +85,7 @@ SECTIONS } . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR); + _xiprom = .; /* XIP ROM area to be mapped */ .head.text : { _text = .; @@ -210,6 +211,7 @@ SECTIONS PERCPU_SECTION(L1_CACHE_BYTES) #endif + _exiprom = .; /* End of XIP ROM area */ __data_loc = ALIGN(4); /* location in binary */ . = PAGE_OFFSET + TEXT_OFFSET; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 434d76f0b363..e4b681aafd6d 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1253,7 +1253,7 @@ static inline void prepare_page_table(void) #ifdef CONFIG_XIP_KERNEL /* The XIP kernel is mapped in the module area -- skip over it */ - addr = ((unsigned long)_etext + PMD_SIZE - 1) & PMD_MASK; + addr = ((unsigned long)_exiprom + PMD_SIZE - 1) & PMD_MASK; #endif for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE) pmd_clear(pmd_off_k(addr)); @@ -1335,7 +1335,7 @@ static void __init devicemaps_init(const struct machine_desc *mdesc) #ifdef CONFIG_XIP_KERNEL map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK); map.virtual = MODULES_VADDR; - map.length = ((unsigned long)_etext - map.virtual + ~SECTION_MASK) & SECTION_MASK; + map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK; map.type = MT_ROM; create_mapping(&map); #endif @@ -1426,7 +1426,11 @@ static void __init kmap_init(void) static void __init map_lowmem(void) { struct memblock_region *reg; +#ifdef CONFIG_XIP_KERNEL + phys_addr_t kernel_x_start = round_down(__pa(_sdata), SECTION_SIZE); +#else phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE); +#endif phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE); /* Map all the lowmem memory banks. */ -- cgit From 64ac2e74f0b21505606faf725cb5633d63b8b728 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 26 Jan 2016 01:20:21 +0100 Subject: ARM: 8502/1: mm: mark section-aligned portion of rodata NX When rodata is large enough that it crosses a section boundary after the kernel text, mark the rest NX. This is as close to full NX of rodata as we can get without splitting page tables or doing section alignment via CONFIG_DEBUG_ALIGN_RODATA. When the config is: CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_ALIGN_RODATA is not set Before: ---[ Kernel Mapping ]--- 0x80000000-0x80100000 1M RW NX SHD 0x80100000-0x80a00000 9M ro x SHD 0x80a00000-0xa0000000 502M RW NX SHD After: ---[ Kernel Mapping ]--- 0x80000000-0x80100000 1M RW NX SHD 0x80100000-0x80700000 6M ro x SHD 0x80700000-0x80a00000 3M ro NX SHD 0x80a00000-0xa0000000 502M RW NX SHD Signed-off-by: Kees Cook Reviewed-by: Ard Biesheuvel Signed-off-by: Russell King --- arch/arm/kernel/vmlinux.lds.S | 9 +++++++-- arch/arm/mm/init.c | 7 ++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index e087a2ed112b..fdca231e150a 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -12,9 +12,7 @@ #include #include #include -#ifdef CONFIG_DEBUG_RODATA #include -#endif #define PROC_INFO \ . = ALIGN(4); \ @@ -319,6 +317,13 @@ SECTIONS STABS_DEBUG } +/* + * Without CONFIG_DEBUG_ALIGN_RODATA, __start_rodata_section_aligned will + * be the first section-aligned location after __start_rodata. Otherwise, + * it will be equal to __start_rodata. + */ +__start_rodata_section_aligned = ALIGN(__start_rodata, 1 << SECTION_SHIFT); + /* * These must never be empty * If you have to comment these two assert statements out, your diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 53f42508025b..370581aeb871 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -582,6 +582,9 @@ struct section_perm { pmdval_t clear; }; +/* First section-aligned location at or after __start_rodata. */ +extern char __start_rodata_section_aligned[]; + static struct section_perm nx_perms[] = { /* Make pages tables, etc before _stext RW (set NX). */ { @@ -599,16 +602,14 @@ static struct section_perm nx_perms[] = { .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, }, -#ifdef CONFIG_DEBUG_ALIGN_RODATA /* Make rodata NX (set RO in ro_perms below). */ { .name = "rodata NX", - .start = (unsigned long)__start_rodata, + .start = (unsigned long)__start_rodata_section_aligned, .end = (unsigned long)__init_begin, .mask = ~PMD_SECT_XN, .prot = PMD_SECT_XN, }, -#endif }; static struct section_perm ro_perms[] = { -- cgit From c5cdf1d2b2d5e67c5f659640b7b395b47b7ed232 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 25 Jan 2016 09:43:43 -0600 Subject: Documentation: tps65912: Add DT bindings for the TPS65912 PMIC The TPS65912 PMIC contains several regulators and a GPIO controller. Add bindings for the TPS65912 PMIC. Signed-off-by: Andrew F. Davis Acked-by: Rob Herring Acked-by: Linus Walleij Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/tps65912.txt | 50 ++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/mfd/tps65912.txt diff --git a/Documentation/devicetree/bindings/mfd/tps65912.txt b/Documentation/devicetree/bindings/mfd/tps65912.txt new file mode 100644 index 000000000000..717e66d23142 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/tps65912.txt @@ -0,0 +1,50 @@ +* TPS65912 Power Management Integrated Circuit bindings + +Required properties: + - compatible : Should be "ti,tps65912". + - reg : Slave address or chip select number (I2C / SPI). + - interrupt-parent : The parent interrupt controller. + - interrupts : The interrupt line the device is connected to. + - interrupt-controller : Marks the device node as an interrupt controller. + - #interrupt-cells : The number of cells to describe an IRQ, should be 2. + The first cell is the IRQ number. + The second cell is the flags, encoded as trigger + masks from ../interrupt-controller/interrupts.txt. + - gpio-controller : Marks the device node as a GPIO Controller. + - #gpio-cells : Should be two. The first cell is the pin number and + the second cell is used to specify flags. + See ../gpio/gpio.txt for more information. + - regulators: : List of child nodes that specify the regulator + initialization data. Child nodes must be named + after their hardware counterparts: dcdc[1-4] and + ldo[1-10]. Each child nodes is defined using the + standard binding for regulators. + +Example: + + pmic: tps65912@2d { + compatible = "ti,tps65912"; + reg = <0x2d>; + interrupt-parent = <&gpio1>; + interrupts = <28 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <2>; + gpio-controller; + #gpio-cells = <2>; + + regulators { + dcdc1 { + regulator-name = "vdd_core"; + regulator-min-microvolt = <912000>; + regulator-max-microvolt = <1144000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1 { + regulator-name = "ldo1"; + regulator-min-microvolt = <1900000>; + regulator-max-microvolt = <1900000>; + }; + }; + }; -- cgit From a05d4845907a6f0296612d24956b189a51fb8df7 Mon Sep 17 00:00:00 2001 From: Thanneeru Srinivasulu Date: Thu, 11 Feb 2016 21:50:21 +0530 Subject: net, thunderx: Add TX timeout and RX buffer alloc failure stats. When system is low on atomic memory, too many error messages are logged. Since this is not a total failure but a simple switch to non-atomic allocation better to have a stat. Also add a stat for reset, kicked due to transmit watchdog timeout. Signed-off-by: Thanneeru Srinivasulu Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nic.h | 3 +++ drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c | 2 ++ drivers/net/ethernet/cavium/thunder/nicvf_main.c | 1 + drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 3 +-- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index 688828865c48..8af363a9af60 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -248,10 +248,13 @@ struct nicvf_drv_stats { u64 rx_frames_jumbo; u64 rx_drops; + u64 rcv_buffer_alloc_failures; + /* Tx */ u64 tx_frames_ok; u64 tx_drops; u64 tx_tso; + u64 tx_timeout; u64 txq_stop; u64 txq_wake; }; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index a12b2e38cf61..d2d8ef270142 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -89,9 +89,11 @@ static const struct nicvf_stat nicvf_drv_stats[] = { NICVF_DRV_STAT(rx_frames_1518), NICVF_DRV_STAT(rx_frames_jumbo), NICVF_DRV_STAT(rx_drops), + NICVF_DRV_STAT(rcv_buffer_alloc_failures), NICVF_DRV_STAT(tx_frames_ok), NICVF_DRV_STAT(tx_tso), NICVF_DRV_STAT(tx_drops), + NICVF_DRV_STAT(tx_timeout), NICVF_DRV_STAT(txq_stop), NICVF_DRV_STAT(txq_wake), }; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index c24cb2a86a42..95db6b7e3aab 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -1394,6 +1394,7 @@ static void nicvf_tx_timeout(struct net_device *dev) netdev_warn(dev, "%s: Transmit timed out, resetting\n", dev->name); + nic->drv_stats.tx_timeout++; schedule_work(&nic->reset_task); } diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index d0d1b5490061..50ab6f4d8c19 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -96,8 +96,7 @@ static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp, nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN, order); if (!nic->rb_page) { - netdev_err(nic->netdev, - "Failed to allocate new rcv buffer\n"); + nic->drv_stats.rcv_buffer_alloc_failures++; return -ENOMEM; } nic->rb_page_offset = 0; -- cgit From ef0a4d8601760b346d9d0893f2a554c338861c4f Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Thu, 11 Feb 2016 21:50:22 +0530 Subject: net: thunderx: Use napi_schedule_irqoff() napi_schedule is being called from hard irq context, hence switch to napi_schedule_irqoff which avoids unneeded call to local_irq_save and local_irq_restore. Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 95db6b7e3aab..c6f146cf266d 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -828,7 +828,7 @@ static irqreturn_t nicvf_intr_handler(int irq, void *cq_irq) nicvf_disable_intr(nic, NICVF_INTR_CQ, qidx); /* Schedule NAPI */ - napi_schedule(&cq_poll->napi); + napi_schedule_irqoff(&cq_poll->napi); /* Clear interrupt */ nicvf_clear_intr(nic, NICVF_INTR_CQ, qidx); -- cgit From fb4b7d98a0215fc3310c8415a86acfe726de395c Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Thu, 11 Feb 2016 21:50:23 +0530 Subject: net: thunderx: Assign affinity hints to vf's interrupts This affinity hint can be used by user space irqbalance tool to set preferred CPU mask for irqs registered by this VF. Irqbalance needs to be in 'exact' mode to set irq affinity same as indicated by affinity hint. Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nic.h | 1 + drivers/net/ethernet/cavium/thunder/nicvf_main.c | 37 ++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index 8af363a9af60..00cc9156abbb 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -309,6 +309,7 @@ struct nicvf { struct msix_entry msix_entries[NIC_VF_MSIX_VECTORS]; char irq_name[NIC_VF_MSIX_VECTORS][20]; bool irq_allocated[NIC_VF_MSIX_VECTORS]; + cpumask_var_t affinity_mask[NIC_VF_MSIX_VECTORS]; /* VF <-> PF mailbox communication */ bool pf_acked; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index c6f146cf266d..90ce93e380e1 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -899,6 +899,31 @@ static void nicvf_disable_msix(struct nicvf *nic) } } +static void nicvf_set_irq_affinity(struct nicvf *nic) +{ + int vec, cpu; + int irqnum; + + for (vec = 0; vec < nic->num_vec; vec++) { + if (!nic->irq_allocated[vec]) + continue; + + if (!zalloc_cpumask_var(&nic->affinity_mask[vec], GFP_KERNEL)) + return; + /* CQ interrupts */ + if (vec < NICVF_INTR_ID_SQ) + /* Leave CPU0 for RBDR and other interrupts */ + cpu = nicvf_netdev_qidx(nic, vec) + 1; + else + cpu = 0; + + cpumask_set_cpu(cpumask_local_spread(cpu, nic->node), + nic->affinity_mask[vec]); + irqnum = nic->msix_entries[vec].vector; + irq_set_affinity_hint(irqnum, nic->affinity_mask[vec]); + } +} + static int nicvf_register_interrupts(struct nicvf *nic) { int irq, ret = 0; @@ -944,8 +969,13 @@ static int nicvf_register_interrupts(struct nicvf *nic) ret = request_irq(nic->msix_entries[irq].vector, nicvf_qs_err_intr_handler, 0, nic->irq_name[irq], nic); - if (!ret) - nic->irq_allocated[irq] = true; + if (ret) + goto err; + + nic->irq_allocated[irq] = true; + + /* Set IRQ affinities */ + nicvf_set_irq_affinity(nic); err: if (ret) @@ -963,6 +993,9 @@ static void nicvf_unregister_interrupts(struct nicvf *nic) if (!nic->irq_allocated[irq]) continue; + irq_set_affinity_hint(nic->msix_entries[irq].vector, NULL); + free_cpumask_var(nic->affinity_mask[irq]); + if (irq < NICVF_INTR_ID_SQ) free_irq(nic->msix_entries[irq].vector, nic->napi[irq]); else -- cgit From eee326fd83348ed39a06c0db999ed513d10d9c39 Mon Sep 17 00:00:00 2001 From: David Daney Date: Thu, 11 Feb 2016 21:50:24 +0530 Subject: net: thunderx: bgx: Use standard firmware node infrastructure. In the case of OF device tree, the firmware information is attached to the BGX device structure in the standard manner, so use the firmware iterators and accessors where possible. Signed-off-by: David Daney Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 27 ++++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 9df26c2263bc..111835ba18e3 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -968,26 +968,27 @@ static int bgx_init_acpi_phy(struct bgx *bgx) static int bgx_init_of_phy(struct bgx *bgx) { - struct device_node *np; - struct device_node *np_child; + struct fwnode_handle *fwn; u8 lmac = 0; - char bgx_sel[5]; const char *mac; - /* Get BGX node from DT */ - snprintf(bgx_sel, 5, "bgx%d", bgx->bgx_id); - np = of_find_node_by_name(NULL, bgx_sel); - if (!np) - return -ENODEV; + device_for_each_child_node(&bgx->pdev->dev, fwn) { + struct device_node *phy_np; + struct device_node *node = to_of_node(fwn); + + /* If it is not an OF node we cannot handle it yet, so + * exit the loop. + */ + if (!node) + break; - for_each_child_of_node(np, np_child) { - struct device_node *phy_np = of_parse_phandle(np_child, - "phy-handle", 0); + phy_np = of_parse_phandle(node, "phy-handle", 0); if (!phy_np) continue; + bgx->lmac[lmac].phydev = of_phy_find_device(phy_np); - mac = of_get_mac_address(np_child); + mac = of_get_mac_address(node); if (mac) ether_addr_copy(bgx->lmac[lmac].mac, mac); @@ -995,7 +996,7 @@ static int bgx_init_of_phy(struct bgx *bgx) bgx->lmac[lmac].lmacid = lmac; lmac++; if (lmac == MAX_LMAC_PER_BGX) { - of_node_put(np_child); + of_node_put(node); break; } } -- cgit From 1d82efaca87ecf53e97c696f9d0a9adefea0c7b5 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 11 Feb 2016 21:50:25 +0530 Subject: net: thunderx: bgx: Add log message when setting mac address Signed-off-by: Robert Richter Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 111835ba18e3..f8abdffdd851 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -886,7 +886,8 @@ static void bgx_get_qlm_mode(struct bgx *bgx) #ifdef CONFIG_ACPI -static int acpi_get_mac_address(struct acpi_device *adev, u8 *dst) +static int acpi_get_mac_address(struct device *dev, struct acpi_device *adev, + u8 *dst) { u8 mac[ETH_ALEN]; int ret; @@ -897,10 +898,13 @@ static int acpi_get_mac_address(struct acpi_device *adev, u8 *dst) goto out; if (!is_valid_ether_addr(mac)) { + dev_err(dev, "MAC address invalid: %pM\n", mac); ret = -EINVAL; goto out; } + dev_info(dev, "MAC address set to: %pM\n", mac); + memcpy(dst, mac, ETH_ALEN); out: return ret; @@ -911,14 +915,15 @@ static acpi_status bgx_acpi_register_phy(acpi_handle handle, u32 lvl, void *context, void **rv) { struct bgx *bgx = context; + struct device *dev = &bgx->pdev->dev; struct acpi_device *adev; if (acpi_bus_get_device(handle, &adev)) goto out; - acpi_get_mac_address(adev, bgx->lmac[bgx->lmac_count].mac); + acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac); - SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, &bgx->pdev->dev); + SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev); bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count; out: -- cgit From 6e4be8d6717cb63c58f6b404e63a881c76d8878c Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Thu, 11 Feb 2016 21:50:26 +0530 Subject: net: thunderx: Alloc higher order pages when pagesize is small Allocate higher order pages when pagesize is small, this will reduce number of calls to page allocator and wastage of memory. Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 50ab6f4d8c19..5adb208c1ad2 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -78,7 +78,7 @@ static void nicvf_free_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem) static inline int nicvf_alloc_rcv_buffer(struct nicvf *nic, gfp_t gfp, u32 buf_len, u64 **rbuf) { - int order = get_order(buf_len); + int order = (PAGE_SIZE <= 4096) ? PAGE_ALLOC_COSTLY_ORDER : 0; /* Check if request can be accomodated in previous allocated page */ if (nic->rb_page) { -- cgit From 65b6555971d0498b18a0b2fdc6dd7c822f2d69b7 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 25 Jan 2016 09:43:44 -0600 Subject: mfd: tps65912: Remove old driver in preparation for new driver The old tps65912 driver is being replaced, delete old driver. Signed-off-by: Andrew F. Davis Acked-by: Mark Brown Acked-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/gpio/Kconfig | 6 - drivers/gpio/Makefile | 1 - drivers/gpio/gpio-tps65912.c | 151 --------- drivers/mfd/Kconfig | 26 -- drivers/mfd/Makefile | 4 - drivers/mfd/tps65912-core.c | 175 ----------- drivers/mfd/tps65912-i2c.c | 139 --------- drivers/mfd/tps65912-irq.c | 217 ------------- drivers/mfd/tps65912-spi.c | 140 --------- drivers/regulator/Kconfig | 6 - drivers/regulator/Makefile | 1 - drivers/regulator/tps65912-regulator.c | 541 --------------------------------- include/linux/mfd/tps65912.h | 328 -------------------- 13 files changed, 1735 deletions(-) delete mode 100644 drivers/gpio/gpio-tps65912.c delete mode 100644 drivers/mfd/tps65912-core.c delete mode 100644 drivers/mfd/tps65912-i2c.c delete mode 100644 drivers/mfd/tps65912-irq.c delete mode 100644 drivers/mfd/tps65912-spi.c delete mode 100644 drivers/regulator/tps65912-regulator.c delete mode 100644 include/linux/mfd/tps65912.h diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index c88dd24a4b1f..98eaeddc0ae3 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -858,12 +858,6 @@ config GPIO_TPS65910 Select this option to enable GPIO driver for the TPS65910 chip family. -config GPIO_TPS65912 - tristate "TI TPS65912 GPIO" - depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI) - help - This driver supports TPS65912 gpio chip - config GPIO_TWL4030 tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" depends on TWL4030_CORE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ece7d7cbdc80..edc33f0a6788 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -97,7 +97,6 @@ obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o -obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c deleted file mode 100644 index 4f2029c7da3a..000000000000 --- a/drivers/gpio/gpio-tps65912.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya - * - * 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 driver is based on wm8350 implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct tps65912_gpio_data { - struct tps65912 *tps65912; - struct gpio_chip gpio_chip; -}; - -static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) -{ - struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); - struct tps65912 *tps65912 = tps65912_gpio->tps65912; - int val; - - val = tps65912_reg_read(tps65912, TPS65912_GPIO1 + offset); - - if (val & GPIO_STS_MASK) - return 1; - - return 0; -} - -static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); - struct tps65912 *tps65912 = tps65912_gpio->tps65912; - - if (value) - tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_SET_MASK); - else - tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_SET_MASK); -} - -static int tps65912_gpio_output(struct gpio_chip *gc, unsigned offset, - int value) -{ - struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); - struct tps65912 *tps65912 = tps65912_gpio->tps65912; - - /* Set the initial value */ - tps65912_gpio_set(gc, offset, value); - - return tps65912_set_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_CFG_MASK); -} - -static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset) -{ - struct tps65912_gpio_data *tps65912_gpio = gpiochip_get_data(gc); - struct tps65912 *tps65912 = tps65912_gpio->tps65912; - - return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset, - GPIO_CFG_MASK); -} - -static struct gpio_chip template_chip = { - .label = "tps65912", - .owner = THIS_MODULE, - .direction_input = tps65912_gpio_input, - .direction_output = tps65912_gpio_output, - .get = tps65912_gpio_get, - .set = tps65912_gpio_set, - .can_sleep = true, - .ngpio = 5, - .base = -1, -}; - -static int tps65912_gpio_probe(struct platform_device *pdev) -{ - struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); - struct tps65912_board *pdata = dev_get_platdata(tps65912->dev); - struct tps65912_gpio_data *tps65912_gpio; - int ret; - - tps65912_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65912_gpio), - GFP_KERNEL); - if (tps65912_gpio == NULL) - return -ENOMEM; - - tps65912_gpio->tps65912 = tps65912; - tps65912_gpio->gpio_chip = template_chip; - tps65912_gpio->gpio_chip.parent = &pdev->dev; - if (pdata && pdata->gpio_base) - tps65912_gpio->gpio_chip.base = pdata->gpio_base; - - ret = gpiochip_add_data(&tps65912_gpio->gpio_chip, tps65912_gpio); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret); - return ret; - } - - platform_set_drvdata(pdev, tps65912_gpio); - - return ret; -} - -static int tps65912_gpio_remove(struct platform_device *pdev) -{ - struct tps65912_gpio_data *tps65912_gpio = platform_get_drvdata(pdev); - - gpiochip_remove(&tps65912_gpio->gpio_chip); - return 0; -} - -static struct platform_driver tps65912_gpio_driver = { - .driver = { - .name = "tps65912-gpio", - }, - .probe = tps65912_gpio_probe, - .remove = tps65912_gpio_remove, -}; - -static int __init tps65912_gpio_init(void) -{ - return platform_driver_register(&tps65912_gpio_driver); -} -subsys_initcall(tps65912_gpio_init); - -static void __exit tps65912_gpio_exit(void) -{ - platform_driver_unregister(&tps65912_gpio_driver); -} -module_exit(tps65912_gpio_exit); - -MODULE_AUTHOR("Margarita Olaya Cabrera "); -MODULE_DESCRIPTION("GPIO interface for TPS65912 PMICs"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65912-gpio"); diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9ca66de0c1c1..dd2fc0158c7a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1180,32 +1180,6 @@ config MFD_TPS65910 if you say yes here you get support for the TPS65910 series of Power Management chips. -config MFD_TPS65912 - bool "TI TPS65912 Power Management chip" - depends on GPIOLIB - select MFD_CORE - help - If you say yes here you get support for the TPS65912 series of - PM chips. - -config MFD_TPS65912_I2C - bool "TI TPS65912 Power Management chip with I2C" - select MFD_CORE - select MFD_TPS65912 - depends on I2C=y && GPIOLIB - help - If you say yes here you get support for the TPS65912 series of - PM chips with I2C interface. - -config MFD_TPS65912_SPI - bool "TI TPS65912 Power Management chip with SPI" - select MFD_CORE - select MFD_TPS65912 - depends on SPI_MASTER && GPIOLIB - help - If you say yes here you get support for the TPS65912 series of - PM chips with SPI interface. - config MFD_TPS80031 bool "TI TPS80031/TPS80032 Power Management chips" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0f230a6103f8..e33e0b48f591 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -73,10 +73,6 @@ obj-$(CONFIG_TPS6507X) += tps6507x.o obj-$(CONFIG_MFD_TPS65217) += tps65217.o obj-$(CONFIG_MFD_TPS65218) += tps65218.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o -tps65912-objs := tps65912-core.o tps65912-irq.o -obj-$(CONFIG_MFD_TPS65912) += tps65912.o -obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o -obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_MENELAUS) += menelaus.o diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c deleted file mode 100644 index 1f82d60b1d0f..000000000000 --- a/drivers/mfd/tps65912-core.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * tps65912-core.c -- TI TPS65912x - * - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya Cabrera - * - * 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 driver is based on wm8350 implementation. - */ - -#include -#include -#include -#include -#include -#include - -static const struct mfd_cell tps65912s[] = { - { - .name = "tps65912-pmic", - }, -}; - -int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask) -{ - u8 data; - int err; - - mutex_lock(&tps65912->io_mutex); - - err = tps65912->read(tps65912, reg, 1, &data); - if (err) { - dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg); - goto out; - } - - data |= mask; - err = tps65912->write(tps65912, reg, 1, &data); - if (err) - dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg); - -out: - mutex_unlock(&tps65912->io_mutex); - return err; -} -EXPORT_SYMBOL_GPL(tps65912_set_bits); - -int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask) -{ - u8 data; - int err; - - mutex_lock(&tps65912->io_mutex); - err = tps65912->read(tps65912, reg, 1, &data); - if (err) { - dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg); - goto out; - } - - data &= ~mask; - err = tps65912->write(tps65912, reg, 1, &data); - if (err) - dev_err(tps65912->dev, "Write to reg 0x%x failed\n", reg); - -out: - mutex_unlock(&tps65912->io_mutex); - return err; -} -EXPORT_SYMBOL_GPL(tps65912_clear_bits); - -static inline int tps65912_read(struct tps65912 *tps65912, u8 reg) -{ - u8 val; - int err; - - err = tps65912->read(tps65912, reg, 1, &val); - if (err < 0) - return err; - - return val; -} - -static inline int tps65912_write(struct tps65912 *tps65912, u8 reg, u8 val) -{ - return tps65912->write(tps65912, reg, 1, &val); -} - -int tps65912_reg_read(struct tps65912 *tps65912, u8 reg) -{ - int data; - - mutex_lock(&tps65912->io_mutex); - - data = tps65912_read(tps65912, reg); - if (data < 0) - dev_err(tps65912->dev, "Read from reg 0x%x failed\n", reg); - - mutex_unlock(&tps65912->io_mutex); - return data; -} -EXPORT_SYMBOL_GPL(tps65912_reg_read); - -int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val) -{ - int err; - - mutex_lock(&tps65912->io_mutex); - - err = tps65912_write(tps65912, reg, val); - if (err < 0) - dev_err(tps65912->dev, "Write for reg 0x%x failed\n", reg); - - mutex_unlock(&tps65912->io_mutex); - return err; -} -EXPORT_SYMBOL_GPL(tps65912_reg_write); - -int tps65912_device_init(struct tps65912 *tps65912) -{ - struct tps65912_board *pmic_plat_data = dev_get_platdata(tps65912->dev); - struct tps65912_platform_data *init_data; - int ret, dcdc_avs, value; - - init_data = kzalloc(sizeof(struct tps65912_platform_data), GFP_KERNEL); - if (init_data == NULL) - return -ENOMEM; - - mutex_init(&tps65912->io_mutex); - dev_set_drvdata(tps65912->dev, tps65912); - - dcdc_avs = (pmic_plat_data->is_dcdc1_avs << 0 | - pmic_plat_data->is_dcdc2_avs << 1 | - pmic_plat_data->is_dcdc3_avs << 2 | - pmic_plat_data->is_dcdc4_avs << 3); - if (dcdc_avs) { - tps65912->read(tps65912, TPS65912_I2C_SPI_CFG, 1, &value); - dcdc_avs |= value; - tps65912->write(tps65912, TPS65912_I2C_SPI_CFG, 1, &dcdc_avs); - } - - ret = mfd_add_devices(tps65912->dev, -1, - tps65912s, ARRAY_SIZE(tps65912s), - NULL, 0, NULL); - if (ret < 0) - goto err; - - init_data->irq = pmic_plat_data->irq; - init_data->irq_base = pmic_plat_data->irq_base; - ret = tps65912_irq_init(tps65912, init_data->irq, init_data); - if (ret < 0) - goto err; - - kfree(init_data); - return ret; - -err: - kfree(init_data); - mfd_remove_devices(tps65912->dev); - return ret; -} - -void tps65912_device_exit(struct tps65912 *tps65912) -{ - mfd_remove_devices(tps65912->dev); - tps65912_irq_exit(tps65912); -} - -MODULE_AUTHOR("Margarita Olaya "); -MODULE_DESCRIPTION("TPS65912x chip family multi-function driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c deleted file mode 100644 index 7e55640b3ed5..000000000000 --- a/drivers/mfd/tps65912-i2c.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * tps65912-i2c.c -- I2C access for TI TPS65912x PMIC - * - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya Cabrera - * - * 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 driver is based on wm8350 implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int tps65912_i2c_read(struct tps65912 *tps65912, u8 reg, - int bytes, void *dest) -{ - struct i2c_client *i2c = tps65912->control_data; - struct i2c_msg xfer[2]; - int ret; - - /* Write register */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = bytes; - xfer[1].buf = dest; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret == 2) - ret = 0; - else if (ret >= 0) - ret = -EIO; - return ret; -} - -static int tps65912_i2c_write(struct tps65912 *tps65912, u8 reg, - int bytes, void *src) -{ - struct i2c_client *i2c = tps65912->control_data; - /* we add 1 byte for device register */ - u8 msg[TPS6591X_MAX_REGISTER + 1]; - int ret; - - if (bytes > TPS6591X_MAX_REGISTER) - return -EINVAL; - - msg[0] = reg; - memcpy(&msg[1], src, bytes); - - ret = i2c_master_send(i2c, msg, bytes + 1); - if (ret < 0) - return ret; - if (ret != bytes + 1) - return -EIO; - - return 0; -} - -static int tps65912_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct tps65912 *tps65912; - - tps65912 = devm_kzalloc(&i2c->dev, - sizeof(struct tps65912), GFP_KERNEL); - if (tps65912 == NULL) - return -ENOMEM; - - i2c_set_clientdata(i2c, tps65912); - tps65912->dev = &i2c->dev; - tps65912->control_data = i2c; - tps65912->read = tps65912_i2c_read; - tps65912->write = tps65912_i2c_write; - - return tps65912_device_init(tps65912); -} - -static int tps65912_i2c_remove(struct i2c_client *i2c) -{ - struct tps65912 *tps65912 = i2c_get_clientdata(i2c); - - tps65912_device_exit(tps65912); - - return 0; -} - -static const struct i2c_device_id tps65912_i2c_id[] = { - {"tps65912", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tps65912_i2c_id); - -static struct i2c_driver tps65912_i2c_driver = { - .driver = { - .name = "tps65912", - }, - .probe = tps65912_i2c_probe, - .remove = tps65912_i2c_remove, - .id_table = tps65912_i2c_id, -}; - -static int __init tps65912_i2c_init(void) -{ - int ret; - - ret = i2c_add_driver(&tps65912_i2c_driver); - if (ret != 0) - pr_err("Failed to register TPS65912 I2C driver: %d\n", ret); - - return ret; -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(tps65912_i2c_init); - -static void __exit tps65912_i2c_exit(void) -{ - i2c_del_driver(&tps65912_i2c_driver); -} -module_exit(tps65912_i2c_exit); - -MODULE_AUTHOR("Margarita Olaya "); -MODULE_DESCRIPTION("TPS6591x chip family multi-function driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/tps65912-irq.c b/drivers/mfd/tps65912-irq.c deleted file mode 100644 index db2c29cb709b..000000000000 --- a/drivers/mfd/tps65912-irq.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * tps65912-irq.c -- TI TPS6591x - * - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya - * - * 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 driver is based on wm8350 implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static inline int irq_to_tps65912_irq(struct tps65912 *tps65912, - int irq) -{ - return irq - tps65912->irq_base; -} - -/* - * This is a threaded IRQ handler so can access I2C/SPI. Since the - * IRQ handler explicitly clears the IRQ it handles the IRQ line - * will be reasserted and the physical IRQ will be handled again if - * another interrupt is asserted while we run - in the normal course - * of events this is a rare occurrence so we save I2C/SPI reads. We're - * also assuming that it's rare to get lots of interrupts firing - * simultaneously so try to minimise I/O. - */ -static irqreturn_t tps65912_irq(int irq, void *irq_data) -{ - struct tps65912 *tps65912 = irq_data; - u32 irq_sts; - u32 irq_mask; - u8 reg; - int i; - - - tps65912->read(tps65912, TPS65912_INT_STS, 1, ®); - irq_sts = reg; - tps65912->read(tps65912, TPS65912_INT_STS2, 1, ®); - irq_sts |= reg << 8; - tps65912->read(tps65912, TPS65912_INT_STS3, 1, ®); - irq_sts |= reg << 16; - tps65912->read(tps65912, TPS65912_INT_STS4, 1, ®); - irq_sts |= reg << 24; - - tps65912->read(tps65912, TPS65912_INT_MSK, 1, ®); - irq_mask = reg; - tps65912->read(tps65912, TPS65912_INT_MSK2, 1, ®); - irq_mask |= reg << 8; - tps65912->read(tps65912, TPS65912_INT_MSK3, 1, ®); - irq_mask |= reg << 16; - tps65912->read(tps65912, TPS65912_INT_MSK4, 1, ®); - irq_mask |= reg << 24; - - irq_sts &= ~irq_mask; - if (!irq_sts) - return IRQ_NONE; - - for (i = 0; i < tps65912->irq_num; i++) { - if (!(irq_sts & (1 << i))) - continue; - - handle_nested_irq(tps65912->irq_base + i); - } - - /* Write the STS register back to clear IRQs we handled */ - reg = irq_sts & 0xFF; - irq_sts >>= 8; - if (reg) - tps65912->write(tps65912, TPS65912_INT_STS, 1, ®); - reg = irq_sts & 0xFF; - irq_sts >>= 8; - if (reg) - tps65912->write(tps65912, TPS65912_INT_STS2, 1, ®); - reg = irq_sts & 0xFF; - irq_sts >>= 8; - if (reg) - tps65912->write(tps65912, TPS65912_INT_STS3, 1, ®); - reg = irq_sts & 0xFF; - if (reg) - tps65912->write(tps65912, TPS65912_INT_STS4, 1, ®); - - return IRQ_HANDLED; -} - -static void tps65912_irq_lock(struct irq_data *data) -{ - struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); - - mutex_lock(&tps65912->irq_lock); -} - -static void tps65912_irq_sync_unlock(struct irq_data *data) -{ - struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); - u32 reg_mask; - u8 reg; - - tps65912->read(tps65912, TPS65912_INT_MSK, 1, ®); - reg_mask = reg; - tps65912->read(tps65912, TPS65912_INT_MSK2, 1, ®); - reg_mask |= reg << 8; - tps65912->read(tps65912, TPS65912_INT_MSK3, 1, ®); - reg_mask |= reg << 16; - tps65912->read(tps65912, TPS65912_INT_MSK4, 1, ®); - reg_mask |= reg << 24; - - if (tps65912->irq_mask != reg_mask) { - reg = tps65912->irq_mask & 0xFF; - tps65912->write(tps65912, TPS65912_INT_MSK, 1, ®); - reg = tps65912->irq_mask >> 8 & 0xFF; - tps65912->write(tps65912, TPS65912_INT_MSK2, 1, ®); - reg = tps65912->irq_mask >> 16 & 0xFF; - tps65912->write(tps65912, TPS65912_INT_MSK3, 1, ®); - reg = tps65912->irq_mask >> 24 & 0xFF; - tps65912->write(tps65912, TPS65912_INT_MSK4, 1, ®); - } - - mutex_unlock(&tps65912->irq_lock); -} - -static void tps65912_irq_enable(struct irq_data *data) -{ - struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); - - tps65912->irq_mask &= ~(1 << irq_to_tps65912_irq(tps65912, data->irq)); -} - -static void tps65912_irq_disable(struct irq_data *data) -{ - struct tps65912 *tps65912 = irq_data_get_irq_chip_data(data); - - tps65912->irq_mask |= (1 << irq_to_tps65912_irq(tps65912, data->irq)); -} - -static struct irq_chip tps65912_irq_chip = { - .name = "tps65912", - .irq_bus_lock = tps65912_irq_lock, - .irq_bus_sync_unlock = tps65912_irq_sync_unlock, - .irq_disable = tps65912_irq_disable, - .irq_enable = tps65912_irq_enable, -}; - -int tps65912_irq_init(struct tps65912 *tps65912, int irq, - struct tps65912_platform_data *pdata) -{ - int ret, cur_irq; - int flags = IRQF_ONESHOT; - u8 reg; - - if (!irq) { - dev_warn(tps65912->dev, "No interrupt support, no core IRQ\n"); - return 0; - } - - if (!pdata || !pdata->irq_base) { - dev_warn(tps65912->dev, "No interrupt support, no IRQ base\n"); - return 0; - } - - /* Clear unattended interrupts */ - tps65912->read(tps65912, TPS65912_INT_STS, 1, ®); - tps65912->write(tps65912, TPS65912_INT_STS, 1, ®); - tps65912->read(tps65912, TPS65912_INT_STS2, 1, ®); - tps65912->write(tps65912, TPS65912_INT_STS2, 1, ®); - tps65912->read(tps65912, TPS65912_INT_STS3, 1, ®); - tps65912->write(tps65912, TPS65912_INT_STS3, 1, ®); - tps65912->read(tps65912, TPS65912_INT_STS4, 1, ®); - tps65912->write(tps65912, TPS65912_INT_STS4, 1, ®); - - /* Mask top level interrupts */ - tps65912->irq_mask = 0xFFFFFFFF; - - mutex_init(&tps65912->irq_lock); - tps65912->chip_irq = irq; - tps65912->irq_base = pdata->irq_base; - - tps65912->irq_num = TPS65912_NUM_IRQ; - - /* Register with genirq */ - for (cur_irq = tps65912->irq_base; - cur_irq < tps65912->irq_num + tps65912->irq_base; - cur_irq++) { - irq_set_chip_data(cur_irq, tps65912); - irq_set_chip_and_handler(cur_irq, &tps65912_irq_chip, - handle_edge_irq); - irq_set_nested_thread(cur_irq, 1); - irq_clear_status_flags(cur_irq, IRQ_NOREQUEST | IRQ_NOPROBE); - } - - ret = request_threaded_irq(irq, NULL, tps65912_irq, flags, - "tps65912", tps65912); - - irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW); - if (ret != 0) - dev_err(tps65912->dev, "Failed to request IRQ: %d\n", ret); - - return ret; -} - -int tps65912_irq_exit(struct tps65912 *tps65912) -{ - free_irq(tps65912->chip_irq, tps65912); - return 0; -} diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c deleted file mode 100644 index d59aa55b1495..000000000000 --- a/drivers/mfd/tps65912-spi.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * tps65912-spi.c -- SPI access for TI TPS65912x PMIC - * - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya Cabrera - * - * 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 driver is based on wm8350 implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static int tps65912_spi_write(struct tps65912 *tps65912, u8 addr, - int bytes, void *src) -{ - struct spi_device *spi = tps65912->control_data; - u8 *data = (u8 *) src; - int ret; - /* bit 23 is the read/write bit */ - unsigned long spi_data = 1 << 23 | addr << 15 | *data; - struct spi_transfer xfer; - struct spi_message msg; - u32 tx_buf; - - tx_buf = spi_data; - - xfer.tx_buf = &tx_buf; - xfer.rx_buf = NULL; - xfer.len = sizeof(unsigned long); - xfer.bits_per_word = 24; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - ret = spi_sync(spi, &msg); - return ret; -} - -static int tps65912_spi_read(struct tps65912 *tps65912, u8 addr, - int bytes, void *dest) -{ - struct spi_device *spi = tps65912->control_data; - /* bit 23 is the read/write bit */ - unsigned long spi_data = 0 << 23 | addr << 15; - struct spi_transfer xfer; - struct spi_message msg; - int ret; - u8 *data = (u8 *) dest; - u32 tx_buf, rx_buf; - - tx_buf = spi_data; - rx_buf = 0; - - xfer.tx_buf = &tx_buf; - xfer.rx_buf = &rx_buf; - xfer.len = sizeof(unsigned long); - xfer.bits_per_word = 24; - - spi_message_init(&msg); - spi_message_add_tail(&xfer, &msg); - - if (spi == NULL) - return 0; - - ret = spi_sync(spi, &msg); - if (ret == 0) - *data = (u8) (rx_buf & 0xFF); - return ret; -} - -static int tps65912_spi_probe(struct spi_device *spi) -{ - struct tps65912 *tps65912; - - tps65912 = devm_kzalloc(&spi->dev, - sizeof(struct tps65912), GFP_KERNEL); - if (tps65912 == NULL) - return -ENOMEM; - - tps65912->dev = &spi->dev; - tps65912->control_data = spi; - tps65912->read = tps65912_spi_read; - tps65912->write = tps65912_spi_write; - - spi_set_drvdata(spi, tps65912); - - return tps65912_device_init(tps65912); -} - -static int tps65912_spi_remove(struct spi_device *spi) -{ - struct tps65912 *tps65912 = spi_get_drvdata(spi); - - tps65912_device_exit(tps65912); - - return 0; -} - -static struct spi_driver tps65912_spi_driver = { - .driver = { - .name = "tps65912", - }, - .probe = tps65912_spi_probe, - .remove = tps65912_spi_remove, -}; - -static int __init tps65912_spi_init(void) -{ - int ret; - - ret = spi_register_driver(&tps65912_spi_driver); - if (ret != 0) - pr_err("Failed to register TPS65912 SPI driver: %d\n", ret); - - return 0; -} -/* init early so consumer devices can complete system boot */ -subsys_initcall(tps65912_spi_init); - -static void __exit tps65912_spi_exit(void) -{ - spi_unregister_driver(&tps65912_spi_driver); -} -module_exit(tps65912_spi_exit); - -MODULE_AUTHOR("Margarita Olaya "); -MODULE_DESCRIPTION("SPI support for TPS65912 chip family mfd"); -MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8155e80dd3f8..eb1b4a26cb3e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -760,12 +760,6 @@ config REGULATOR_TPS65910 help This driver supports TPS65910/TPS65911 voltage regulator chips. -config REGULATOR_TPS65912 - tristate "TI TPS65912 Power regulator" - depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI) - help - This driver supports TPS65912 voltage regulator chip. - config REGULATOR_TPS80031 tristate "TI TPS80031/TPS80032 power regualtor driver" depends on MFD_TPS80031 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 980b1943fa81..85da3192701c 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -95,7 +95,6 @@ obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o -obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c deleted file mode 100644 index 9503d5481a52..000000000000 --- a/drivers/regulator/tps65912-regulator.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * tps65912.c -- TI tps65912 - * - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya Cabrera - * - * 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 driver is based on wm8350 implementation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* DCDC's */ -#define TPS65912_REG_DCDC1 0 -#define TPS65912_REG_DCDC2 1 -#define TPS65912_REG_DCDC3 2 -#define TPS65912_REG_DCDC4 3 - -/* LDOs */ -#define TPS65912_REG_LDO1 4 -#define TPS65912_REG_LDO2 5 -#define TPS65912_REG_LDO3 6 -#define TPS65912_REG_LDO4 7 -#define TPS65912_REG_LDO5 8 -#define TPS65912_REG_LDO6 9 -#define TPS65912_REG_LDO7 10 -#define TPS65912_REG_LDO8 11 -#define TPS65912_REG_LDO9 12 -#define TPS65912_REG_LDO10 13 - -/* Number of step-down converters available */ -#define TPS65912_NUM_DCDC 4 - -/* Number of LDO voltage regulators available */ -#define TPS65912_NUM_LDO 10 - -/* Number of total regulators available */ -#define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO) - -#define TPS65912_REG_ENABLED 0x80 -#define OP_SELREG_MASK 0x40 -#define OP_SELREG_SHIFT 6 - -struct tps_info { - const char *name; -}; - -static struct tps_info tps65912_regs[] = { - { - .name = "DCDC1", - }, - { - .name = "DCDC2", - }, - { - .name = "DCDC3", - }, - { - .name = "DCDC4", - }, - { - .name = "LDO1", - }, - { - .name = "LDO2", - }, - { - .name = "LDO3", - }, - { - .name = "LDO4", - }, - { - .name = "LDO5", - }, - { - .name = "LDO6", - }, - { - .name = "LDO7", - }, - { - .name = "LDO8", - }, - { - .name = "LDO9", - }, - { - .name = "LDO10", - }, -}; - -struct tps65912_reg { - struct regulator_desc desc[TPS65912_NUM_REGULATOR]; - struct tps65912 *mfd; - struct regulator_dev *rdev[TPS65912_NUM_REGULATOR]; - struct tps_info *info[TPS65912_NUM_REGULATOR]; - /* for read/write access */ - struct mutex io_lock; - int mode; - int (*get_ctrl_reg)(int); - int dcdc_range[TPS65912_NUM_DCDC]; - int pwm_mode_reg; - int eco_reg; -}; - -static const struct regulator_linear_range tps65912_ldo_ranges[] = { - REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000), - REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000), - REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000), -}; - -static int tps65912_get_range(struct tps65912_reg *pmic, int id) -{ - struct tps65912 *mfd = pmic->mfd; - int range; - - switch (id) { - case TPS65912_REG_DCDC1: - range = tps65912_reg_read(mfd, TPS65912_DCDC1_LIMIT); - break; - case TPS65912_REG_DCDC2: - range = tps65912_reg_read(mfd, TPS65912_DCDC2_LIMIT); - break; - case TPS65912_REG_DCDC3: - range = tps65912_reg_read(mfd, TPS65912_DCDC3_LIMIT); - break; - case TPS65912_REG_DCDC4: - range = tps65912_reg_read(mfd, TPS65912_DCDC4_LIMIT); - break; - default: - return 0; - } - - if (range >= 0) - range = (range & DCDC_LIMIT_RANGE_MASK) - >> DCDC_LIMIT_RANGE_SHIFT; - - pmic->dcdc_range[id] = range; - return range; -} - -static unsigned long tps65912_vsel_to_uv_range0(u8 vsel) -{ - unsigned long uv; - - uv = ((vsel * 12500) + 500000); - return uv; -} - -static unsigned long tps65912_vsel_to_uv_range1(u8 vsel) -{ - unsigned long uv; - - uv = ((vsel * 12500) + 700000); - return uv; -} - -static unsigned long tps65912_vsel_to_uv_range2(u8 vsel) -{ - unsigned long uv; - - uv = ((vsel * 25000) + 500000); - return uv; -} - -static unsigned long tps65912_vsel_to_uv_range3(u8 vsel) -{ - unsigned long uv; - - if (vsel == 0x3f) - uv = 3800000; - else - uv = ((vsel * 50000) + 500000); - - return uv; -} - -static int tps65912_get_ctrl_register(int id) -{ - if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) - return id * 3 + TPS65912_DCDC1_AVS; - else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10) - return id - TPS65912_REG_LDO5 + TPS65912_LDO5; - else - return -EINVAL; -} - -static int tps65912_get_sel_register(struct tps65912_reg *pmic, int id) -{ - struct tps65912 *mfd = pmic->mfd; - int opvsel; - u8 reg = 0; - - if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) { - opvsel = tps65912_reg_read(mfd, id * 3 + TPS65912_DCDC1_OP); - if (opvsel & OP_SELREG_MASK) - reg = id * 3 + TPS65912_DCDC1_AVS; - else - reg = id * 3 + TPS65912_DCDC1_OP; - } else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10) { - reg = id - TPS65912_REG_LDO5 + TPS65912_LDO5; - } else { - return -EINVAL; - } - - return reg; -} - -static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id) -{ - switch (id) { - case TPS65912_REG_DCDC1: - pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL; - pmic->eco_reg = TPS65912_DCDC1_AVS; - break; - case TPS65912_REG_DCDC2: - pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL; - pmic->eco_reg = TPS65912_DCDC2_AVS; - break; - case TPS65912_REG_DCDC3: - pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL; - pmic->eco_reg = TPS65912_DCDC3_AVS; - break; - case TPS65912_REG_DCDC4: - pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL; - pmic->eco_reg = TPS65912_DCDC4_AVS; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int tps65912_reg_is_enabled(struct regulator_dev *dev) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int reg, value, id = rdev_get_id(dev); - - if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10) - return -EINVAL; - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - value = tps65912_reg_read(mfd, reg); - if (value < 0) - return value; - - return value & TPS65912_REG_ENABLED; -} - -static int tps65912_reg_enable(struct regulator_dev *dev) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int id = rdev_get_id(dev); - int reg; - - if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10) - return -EINVAL; - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED); -} - -static int tps65912_reg_disable(struct regulator_dev *dev) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int id = rdev_get_id(dev), reg; - - reg = pmic->get_ctrl_reg(id); - if (reg < 0) - return reg; - - return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED); -} - -static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int pwm_mode, eco, id = rdev_get_id(dev); - - tps65912_get_mode_regiters(pmic, id); - - pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg); - eco = tps65912_reg_read(mfd, pmic->eco_reg); - - pwm_mode &= DCDCCTRL_DCDC_MODE_MASK; - eco &= DCDC_AVS_ECO_MASK; - - switch (mode) { - case REGULATOR_MODE_FAST: - /* Verify if mode alredy set */ - if (pwm_mode && !eco) - break; - tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK); - tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK); - break; - case REGULATOR_MODE_NORMAL: - case REGULATOR_MODE_IDLE: - if (!pwm_mode && !eco) - break; - tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK); - tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK); - break; - case REGULATOR_MODE_STANDBY: - if (!pwm_mode && eco) - break; - tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK); - tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK); - break; - default: - return -EINVAL; - } - - return 0; -} - -static unsigned int tps65912_get_mode(struct regulator_dev *dev) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int pwm_mode, eco, mode = 0, id = rdev_get_id(dev); - - tps65912_get_mode_regiters(pmic, id); - - pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg); - eco = tps65912_reg_read(mfd, pmic->eco_reg); - - pwm_mode &= DCDCCTRL_DCDC_MODE_MASK; - eco &= DCDC_AVS_ECO_MASK; - - if (pwm_mode && !eco) - mode = REGULATOR_MODE_FAST; - else if (!pwm_mode && !eco) - mode = REGULATOR_MODE_NORMAL; - else if (!pwm_mode && eco) - mode = REGULATOR_MODE_STANDBY; - - return mode; -} - -static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - int range, voltage = 0, id = rdev_get_id(dev); - - if (id > TPS65912_REG_DCDC4) - return -EINVAL; - - range = pmic->dcdc_range[id]; - - switch (range) { - case 0: - /* 0.5 - 1.2875V in 12.5mV steps */ - voltage = tps65912_vsel_to_uv_range0(selector); - break; - case 1: - /* 0.7 - 1.4875V in 12.5mV steps */ - voltage = tps65912_vsel_to_uv_range1(selector); - break; - case 2: - /* 0.5 - 2.075V in 25mV steps */ - voltage = tps65912_vsel_to_uv_range2(selector); - break; - case 3: - /* 0.5 - 3.8V in 50mV steps */ - voltage = tps65912_vsel_to_uv_range3(selector); - break; - } - return voltage; -} - -static int tps65912_get_voltage_sel(struct regulator_dev *dev) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int id = rdev_get_id(dev); - int reg, vsel; - - reg = tps65912_get_sel_register(pmic, id); - if (reg < 0) - return reg; - - vsel = tps65912_reg_read(mfd, reg); - vsel &= 0x3F; - - return vsel; -} - -static int tps65912_set_voltage_sel(struct regulator_dev *dev, - unsigned selector) -{ - struct tps65912_reg *pmic = rdev_get_drvdata(dev); - struct tps65912 *mfd = pmic->mfd; - int id = rdev_get_id(dev); - int value; - u8 reg; - - reg = tps65912_get_sel_register(pmic, id); - value = tps65912_reg_read(mfd, reg); - value &= 0xC0; - return tps65912_reg_write(mfd, reg, selector | value); -} - -/* Operations permitted on DCDCx */ -static struct regulator_ops tps65912_ops_dcdc = { - .is_enabled = tps65912_reg_is_enabled, - .enable = tps65912_reg_enable, - .disable = tps65912_reg_disable, - .set_mode = tps65912_set_mode, - .get_mode = tps65912_get_mode, - .get_voltage_sel = tps65912_get_voltage_sel, - .set_voltage_sel = tps65912_set_voltage_sel, - .list_voltage = tps65912_list_voltage, -}; - -/* Operations permitted on LDOx */ -static struct regulator_ops tps65912_ops_ldo = { - .is_enabled = tps65912_reg_is_enabled, - .enable = tps65912_reg_enable, - .disable = tps65912_reg_disable, - .get_voltage_sel = tps65912_get_voltage_sel, - .set_voltage_sel = tps65912_set_voltage_sel, - .list_voltage = regulator_list_voltage_linear_range, - .map_voltage = regulator_map_voltage_linear_range, -}; - -static int tps65912_probe(struct platform_device *pdev) -{ - struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent); - struct regulator_config config = { }; - struct tps_info *info; - struct regulator_init_data *reg_data; - struct regulator_dev *rdev; - struct tps65912_reg *pmic; - struct tps65912_board *pmic_plat_data; - int i; - - pmic_plat_data = dev_get_platdata(tps65912->dev); - if (!pmic_plat_data) - return -EINVAL; - - reg_data = pmic_plat_data->tps65912_pmic_init_data; - - pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); - if (!pmic) - return -ENOMEM; - - mutex_init(&pmic->io_lock); - pmic->mfd = tps65912; - platform_set_drvdata(pdev, pmic); - - pmic->get_ctrl_reg = &tps65912_get_ctrl_register; - info = tps65912_regs; - - for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) { - int range = 0; - /* Register the regulators */ - pmic->info[i] = info; - - pmic->desc[i].name = info->name; - pmic->desc[i].id = i; - pmic->desc[i].n_voltages = 64; - if (i > TPS65912_REG_DCDC4) { - pmic->desc[i].ops = &tps65912_ops_ldo; - pmic->desc[i].linear_ranges = tps65912_ldo_ranges; - pmic->desc[i].n_linear_ranges = - ARRAY_SIZE(tps65912_ldo_ranges); - } else { - pmic->desc[i].ops = &tps65912_ops_dcdc; - } - pmic->desc[i].type = REGULATOR_VOLTAGE; - pmic->desc[i].owner = THIS_MODULE; - range = tps65912_get_range(pmic, i); - - config.dev = tps65912->dev; - config.init_data = reg_data; - config.driver_data = pmic; - - rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i], - &config); - if (IS_ERR(rdev)) { - dev_err(tps65912->dev, - "failed to register %s regulator\n", - pdev->name); - return PTR_ERR(rdev); - } - - /* Save regulator for cleanup */ - pmic->rdev[i] = rdev; - } - return 0; -} - -static struct platform_driver tps65912_driver = { - .driver = { - .name = "tps65912-pmic", - }, - .probe = tps65912_probe, -}; - -static int __init tps65912_init(void) -{ - return platform_driver_register(&tps65912_driver); -} -subsys_initcall(tps65912_init); - -static void __exit tps65912_cleanup(void) -{ - platform_driver_unregister(&tps65912_driver); -} -module_exit(tps65912_cleanup); - -MODULE_AUTHOR("Margarita Olaya Cabrera "); -MODULE_DESCRIPTION("TPS65912 voltage regulator driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tps65912-pmic"); diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h deleted file mode 100644 index 6d309032dc0d..000000000000 --- a/include/linux/mfd/tps65912.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * tps65912.h -- TI TPS6591x - * - * Copyright 2011 Texas Instruments Inc. - * - * Author: Margarita Olaya - * - * 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 __LINUX_MFD_TPS65912_H -#define __LINUX_MFD_TPS65912_H - -/* TPS regulator type list */ -#define REGULATOR_LDO 0 -#define REGULATOR_DCDC 1 - -/* - * List of registers for TPS65912 - */ - -#define TPS65912_DCDC1_CTRL 0x00 -#define TPS65912_DCDC2_CTRL 0x01 -#define TPS65912_DCDC3_CTRL 0x02 -#define TPS65912_DCDC4_CTRL 0x03 -#define TPS65912_DCDC1_OP 0x04 -#define TPS65912_DCDC1_AVS 0x05 -#define TPS65912_DCDC1_LIMIT 0x06 -#define TPS65912_DCDC2_OP 0x07 -#define TPS65912_DCDC2_AVS 0x08 -#define TPS65912_DCDC2_LIMIT 0x09 -#define TPS65912_DCDC3_OP 0x0A -#define TPS65912_DCDC3_AVS 0x0B -#define TPS65912_DCDC3_LIMIT 0x0C -#define TPS65912_DCDC4_OP 0x0D -#define TPS65912_DCDC4_AVS 0x0E -#define TPS65912_DCDC4_LIMIT 0x0F -#define TPS65912_LDO1_OP 0x10 -#define TPS65912_LDO1_AVS 0x11 -#define TPS65912_LDO1_LIMIT 0x12 -#define TPS65912_LDO2_OP 0x13 -#define TPS65912_LDO2_AVS 0x14 -#define TPS65912_LDO2_LIMIT 0x15 -#define TPS65912_LDO3_OP 0x16 -#define TPS65912_LDO3_AVS 0x17 -#define TPS65912_LDO3_LIMIT 0x18 -#define TPS65912_LDO4_OP 0x19 -#define TPS65912_LDO4_AVS 0x1A -#define TPS65912_LDO4_LIMIT 0x1B -#define TPS65912_LDO5 0x1C -#define TPS65912_LDO6 0x1D -#define TPS65912_LDO7 0x1E -#define TPS65912_LDO8 0x1F -#define TPS65912_LDO9 0x20 -#define TPS65912_LDO10 0x21 -#define TPS65912_THRM 0x22 -#define TPS65912_CLK32OUT 0x23 -#define TPS65912_DEVCTRL 0x24 -#define TPS65912_DEVCTRL2 0x25 -#define TPS65912_I2C_SPI_CFG 0x26 -#define TPS65912_KEEP_ON 0x27 -#define TPS65912_KEEP_ON2 0x28 -#define TPS65912_SET_OFF1 0x29 -#define TPS65912_SET_OFF2 0x2A -#define TPS65912_DEF_VOLT 0x2B -#define TPS65912_DEF_VOLT_MAPPING 0x2C -#define TPS65912_DISCHARGE 0x2D -#define TPS65912_DISCHARGE2 0x2E -#define TPS65912_EN1_SET1 0x2F -#define TPS65912_EN1_SET2 0x30 -#define TPS65912_EN2_SET1 0x31 -#define TPS65912_EN2_SET2 0x32 -#define TPS65912_EN3_SET1 0x33 -#define TPS65912_EN3_SET2 0x34 -#define TPS65912_EN4_SET1 0x35 -#define TPS65912_EN4_SET2 0x36 -#define TPS65912_PGOOD 0x37 -#define TPS65912_PGOOD2 0x38 -#define TPS65912_INT_STS 0x39 -#define TPS65912_INT_MSK 0x3A -#define TPS65912_INT_STS2 0x3B -#define TPS65912_INT_MSK2 0x3C -#define TPS65912_INT_STS3 0x3D -#define TPS65912_INT_MSK3 0x3E -#define TPS65912_INT_STS4 0x3F -#define TPS65912_INT_MSK4 0x40 -#define TPS65912_GPIO1 0x41 -#define TPS65912_GPIO2 0x42 -#define TPS65912_GPIO3 0x43 -#define TPS65912_GPIO4 0x44 -#define TPS65912_GPIO5 0x45 -#define TPS65912_VMON 0x46 -#define TPS65912_LEDA_CTRL1 0x47 -#define TPS65912_LEDA_CTRL2 0x48 -#define TPS65912_LEDA_CTRL3 0x49 -#define TPS65912_LEDA_CTRL4 0x4A -#define TPS65912_LEDA_CTRL5 0x4B -#define TPS65912_LEDA_CTRL6 0x4C -#define TPS65912_LEDA_CTRL7 0x4D -#define TPS65912_LEDA_CTRL8 0x4E -#define TPS65912_LEDB_CTRL1 0x4F -#define TPS65912_LEDB_CTRL2 0x50 -#define TPS65912_LEDB_CTRL3 0x51 -#define TPS65912_LEDB_CTRL4 0x52 -#define TPS65912_LEDB_CTRL5 0x53 -#define TPS65912_LEDB_CTRL6 0x54 -#define TPS65912_LEDB_CTRL7 0x55 -#define TPS65912_LEDB_CTRL8 0x56 -#define TPS65912_LEDC_CTRL1 0x57 -#define TPS65912_LEDC_CTRL2 0x58 -#define TPS65912_LEDC_CTRL3 0x59 -#define TPS65912_LEDC_CTRL4 0x5A -#define TPS65912_LEDC_CTRL5 0x5B -#define TPS65912_LEDC_CTRL6 0x5C -#define TPS65912_LEDC_CTRL7 0x5D -#define TPS65912_LEDC_CTRL8 0x5E -#define TPS65912_LED_RAMP_UP_TIME 0x5F -#define TPS65912_LED_RAMP_DOWN_TIME 0x60 -#define TPS65912_LED_SEQ_EN 0x61 -#define TPS65912_LOADSWITCH 0x62 -#define TPS65912_SPARE 0x63 -#define TPS65912_VERNUM 0x64 -#define TPS6591X_MAX_REGISTER 0x64 - -/* IRQ Definitions */ -#define TPS65912_IRQ_PWRHOLD_F 0 -#define TPS65912_IRQ_VMON 1 -#define TPS65912_IRQ_PWRON 2 -#define TPS65912_IRQ_PWRON_LP 3 -#define TPS65912_IRQ_PWRHOLD_R 4 -#define TPS65912_IRQ_HOTDIE 5 -#define TPS65912_IRQ_GPIO1_R 6 -#define TPS65912_IRQ_GPIO1_F 7 -#define TPS65912_IRQ_GPIO2_R 8 -#define TPS65912_IRQ_GPIO2_F 9 -#define TPS65912_IRQ_GPIO3_R 10 -#define TPS65912_IRQ_GPIO3_F 11 -#define TPS65912_IRQ_GPIO4_R 12 -#define TPS65912_IRQ_GPIO4_F 13 -#define TPS65912_IRQ_GPIO5_R 14 -#define TPS65912_IRQ_GPIO5_F 15 -#define TPS65912_IRQ_PGOOD_DCDC1 16 -#define TPS65912_IRQ_PGOOD_DCDC2 17 -#define TPS65912_IRQ_PGOOD_DCDC3 18 -#define TPS65912_IRQ_PGOOD_DCDC4 19 -#define TPS65912_IRQ_PGOOD_LDO1 20 -#define TPS65912_IRQ_PGOOD_LDO2 21 -#define TPS65912_IRQ_PGOOD_LDO3 22 -#define TPS65912_IRQ_PGOOD_LDO4 23 -#define TPS65912_IRQ_PGOOD_LDO5 24 -#define TPS65912_IRQ_PGOOD_LDO6 25 -#define TPS65912_IRQ_PGOOD_LDO7 26 -#define TPS65912_IRQ_PGOOD_LD08 27 -#define TPS65912_IRQ_PGOOD_LDO9 28 -#define TPS65912_IRQ_PGOOD_LDO10 29 - -#define TPS65912_NUM_IRQ 30 - -/* GPIO 1 and 2 Register Definitions */ -#define GPIO_SLEEP_MASK 0x80 -#define GPIO_SLEEP_SHIFT 7 -#define GPIO_DEB_MASK 0x10 -#define GPIO_DEB_SHIFT 4 -#define GPIO_CFG_MASK 0x04 -#define GPIO_CFG_SHIFT 2 -#define GPIO_STS_MASK 0x02 -#define GPIO_STS_SHIFT 1 -#define GPIO_SET_MASK 0x01 -#define GPIO_SET_SHIFT 0 - -/* GPIO 3 Register Definitions */ -#define GPIO3_SLEEP_MASK 0x80 -#define GPIO3_SLEEP_SHIFT 7 -#define GPIO3_SEL_MASK 0x40 -#define GPIO3_SEL_SHIFT 6 -#define GPIO3_ODEN_MASK 0x20 -#define GPIO3_ODEN_SHIFT 5 -#define GPIO3_DEB_MASK 0x10 -#define GPIO3_DEB_SHIFT 4 -#define GPIO3_PDEN_MASK 0x08 -#define GPIO3_PDEN_SHIFT 3 -#define GPIO3_CFG_MASK 0x04 -#define GPIO3_CFG_SHIFT 2 -#define GPIO3_STS_MASK 0x02 -#define GPIO3_STS_SHIFT 1 -#define GPIO3_SET_MASK 0x01 -#define GPIO3_SET_SHIFT 0 - -/* GPIO 4 Register Definitions */ -#define GPIO4_SLEEP_MASK 0x80 -#define GPIO4_SLEEP_SHIFT 7 -#define GPIO4_SEL_MASK 0x40 -#define GPIO4_SEL_SHIFT 6 -#define GPIO4_ODEN_MASK 0x20 -#define GPIO4_ODEN_SHIFT 5 -#define GPIO4_DEB_MASK 0x10 -#define GPIO4_DEB_SHIFT 4 -#define GPIO4_PDEN_MASK 0x08 -#define GPIO4_PDEN_SHIFT 3 -#define GPIO4_CFG_MASK 0x04 -#define GPIO4_CFG_SHIFT 2 -#define GPIO4_STS_MASK 0x02 -#define GPIO4_STS_SHIFT 1 -#define GPIO4_SET_MASK 0x01 -#define GPIO4_SET_SHIFT 0 - -/* Register THERM (0x80) register.RegisterDescription */ -#define THERM_THERM_HD_MASK 0x20 -#define THERM_THERM_HD_SHIFT 5 -#define THERM_THERM_TS_MASK 0x10 -#define THERM_THERM_TS_SHIFT 4 -#define THERM_THERM_HDSEL_MASK 0x0C -#define THERM_THERM_HDSEL_SHIFT 2 -#define THERM_RSVD1_MASK 0x02 -#define THERM_RSVD1_SHIFT 1 -#define THERM_THERM_STATE_MASK 0x01 -#define THERM_THERM_STATE_SHIFT 0 - -/* Register DCDCCTRL1 register.RegisterDescription */ -#define DCDCCTRL_VCON_ENABLE_MASK 0x80 -#define DCDCCTRL_VCON_ENABLE_SHIFT 7 -#define DCDCCTRL_VCON_RANGE1_MASK 0x40 -#define DCDCCTRL_VCON_RANGE1_SHIFT 6 -#define DCDCCTRL_VCON_RANGE0_MASK 0x20 -#define DCDCCTRL_VCON_RANGE0_SHIFT 5 -#define DCDCCTRL_TSTEP2_MASK 0x10 -#define DCDCCTRL_TSTEP2_SHIFT 4 -#define DCDCCTRL_TSTEP1_MASK 0x08 -#define DCDCCTRL_TSTEP1_SHIFT 3 -#define DCDCCTRL_TSTEP0_MASK 0x04 -#define DCDCCTRL_TSTEP0_SHIFT 2 -#define DCDCCTRL_DCDC1_MODE_MASK 0x02 -#define DCDCCTRL_DCDC1_MODE_SHIFT 1 - -/* Register DCDCCTRL2 and DCDCCTRL3 register.RegisterDescription */ -#define DCDCCTRL_TSTEP2_MASK 0x10 -#define DCDCCTRL_TSTEP2_SHIFT 4 -#define DCDCCTRL_TSTEP1_MASK 0x08 -#define DCDCCTRL_TSTEP1_SHIFT 3 -#define DCDCCTRL_TSTEP0_MASK 0x04 -#define DCDCCTRL_TSTEP0_SHIFT 2 -#define DCDCCTRL_DCDC_MODE_MASK 0x02 -#define DCDCCTRL_DCDC_MODE_SHIFT 1 -#define DCDCCTRL_RSVD0_MASK 0x01 -#define DCDCCTRL_RSVD0_SHIFT 0 - -/* Register DCDCCTRL4 register.RegisterDescription */ -#define DCDCCTRL_RAMP_TIME_MASK 0x01 -#define DCDCCTRL_RAMP_TIME_SHIFT 0 - -/* Register DCDCx_AVS */ -#define DCDC_AVS_ENABLE_MASK 0x80 -#define DCDC_AVS_ENABLE_SHIFT 7 -#define DCDC_AVS_ECO_MASK 0x40 -#define DCDC_AVS_ECO_SHIFT 6 - -/* Register DCDCx_LIMIT */ -#define DCDC_LIMIT_RANGE_MASK 0xC0 -#define DCDC_LIMIT_RANGE_SHIFT 6 -#define DCDC_LIMIT_MAX_SEL_MASK 0x3F -#define DCDC_LIMIT_MAX_SEL_SHIFT 0 - -/** - * struct tps65912_board - * Board platform dat may be used to initialize regulators. - */ -struct tps65912_board { - int is_dcdc1_avs; - int is_dcdc2_avs; - int is_dcdc3_avs; - int is_dcdc4_avs; - int irq; - int irq_base; - int gpio_base; - struct regulator_init_data *tps65912_pmic_init_data; -}; - -/** - * struct tps65912 - tps65912 sub-driver chip access routines - */ - -struct tps65912 { - struct device *dev; - /* for read/write acces */ - struct mutex io_mutex; - - /* For device IO interfaces: I2C or SPI */ - void *control_data; - - int (*read)(struct tps65912 *tps65912, u8 reg, int size, void *dest); - int (*write)(struct tps65912 *tps65912, u8 reg, int size, void *src); - - /* Client devices */ - struct tps65912_pmic *pmic; - - /* GPIO Handling */ - struct gpio_chip gpio; - - /* IRQ Handling */ - struct mutex irq_lock; - int chip_irq; - int irq_base; - int irq_num; - u32 irq_mask; -}; - -struct tps65912_platform_data { - int irq; - int irq_base; -}; - -unsigned int tps_chip(void); - -int tps65912_set_bits(struct tps65912 *tps65912, u8 reg, u8 mask); -int tps65912_clear_bits(struct tps65912 *tps65912, u8 reg, u8 mask); -int tps65912_reg_read(struct tps65912 *tps65912, u8 reg); -int tps65912_reg_write(struct tps65912 *tps65912, u8 reg, u8 val); -int tps65912_device_init(struct tps65912 *tps65912); -void tps65912_device_exit(struct tps65912 *tps65912); -int tps65912_irq_init(struct tps65912 *tps65912, int irq, - struct tps65912_platform_data *pdata); -int tps65912_irq_exit(struct tps65912 *tps65912); - -#endif /* __LINUX_MFD_TPS65912_H */ -- cgit From 796f5692daac4ea47fa5252af742976cd1955f0b Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 25 Jan 2016 09:43:45 -0600 Subject: mfd: tps65912: Add driver for the TPS65912 PMIC This patch adds support for TPS65912 PMIC MFD core. It provides communication through the I2C and SPI interfaces. It contains the following components: - Regulators - GPIO controller Signed-off-by: Andrew F. Davis Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 24 +++ drivers/mfd/Makefile | 3 + drivers/mfd/tps65912-core.c | 111 ++++++++++++++ drivers/mfd/tps65912-i2c.c | 79 ++++++++++ drivers/mfd/tps65912-spi.c | 78 ++++++++++ include/linux/mfd/tps65912.h | 341 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 636 insertions(+) create mode 100644 drivers/mfd/tps65912-core.c create mode 100644 drivers/mfd/tps65912-i2c.c create mode 100644 drivers/mfd/tps65912-spi.c create mode 100644 include/linux/mfd/tps65912.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index dd2fc0158c7a..1bc97c2761e4 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1180,6 +1180,30 @@ config MFD_TPS65910 if you say yes here you get support for the TPS65910 series of Power Management chips. +config MFD_TPS65912 + tristate + select MFD_CORE + select REGMAP + select REGMAP_IRQ + +config MFD_TPS65912_I2C + tristate "TI TPS65912 Power Management chip with I2C" + select MFD_TPS65912 + select REGMAP_I2C + depends on I2C + help + If you say yes here you get support for the TPS65912 series of + PM chips with I2C interface. + +config MFD_TPS65912_SPI + tristate "TI TPS65912 Power Management chip with SPI" + select MFD_TPS65912 + select REGMAP_SPI + depends on SPI_MASTER + help + If you say yes here you get support for the TPS65912 series of + PM chips with SPI interface. + config MFD_TPS80031 bool "TI TPS80031/TPS80032 Power Management chips" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index e33e0b48f591..1811202cee19 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -73,6 +73,9 @@ obj-$(CONFIG_TPS6507X) += tps6507x.o obj-$(CONFIG_MFD_TPS65217) += tps65217.o obj-$(CONFIG_MFD_TPS65218) += tps65218.o obj-$(CONFIG_MFD_TPS65910) += tps65910.o +obj-$(CONFIG_MFD_TPS65912) += tps65912-core.o +obj-$(CONFIG_MFD_TPS65912_I2C) += tps65912-i2c.o +obj-$(CONFIG_MFD_TPS65912_SPI) += tps65912-spi.o obj-$(CONFIG_MFD_TPS80031) += tps80031.o obj-$(CONFIG_MENELAUS) += menelaus.o diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c new file mode 100644 index 000000000000..a88cfa80dbc4 --- /dev/null +++ b/drivers/mfd/tps65912-core.c @@ -0,0 +1,111 @@ +/* + * Core functions for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +static const struct mfd_cell tps65912_cells[] = { + { .name = "tps65912-regulator", }, + { .name = "tps65912-gpio", }, +}; + +static const struct regmap_irq tps65912_irqs[] = { + /* INT_STS IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_PWRHOLD_F, 0, TPS65912_INT_STS_PWRHOLD_F), + REGMAP_IRQ_REG(TPS65912_IRQ_VMON, 0, TPS65912_INT_STS_VMON), + REGMAP_IRQ_REG(TPS65912_IRQ_PWRON, 0, TPS65912_INT_STS_PWRON), + REGMAP_IRQ_REG(TPS65912_IRQ_PWRON_LP, 0, TPS65912_INT_STS_PWRON_LP), + REGMAP_IRQ_REG(TPS65912_IRQ_PWRHOLD_R, 0, TPS65912_INT_STS_PWRHOLD_R), + REGMAP_IRQ_REG(TPS65912_IRQ_HOTDIE, 0, TPS65912_INT_STS_HOTDIE), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO1_R, 0, TPS65912_INT_STS_GPIO1_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO1_F, 0, TPS65912_INT_STS_GPIO1_F), + /* INT_STS2 IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO2_R, 1, TPS65912_INT_STS2_GPIO2_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO2_F, 1, TPS65912_INT_STS2_GPIO2_F), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO3_R, 1, TPS65912_INT_STS2_GPIO3_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO3_F, 1, TPS65912_INT_STS2_GPIO3_F), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO4_R, 1, TPS65912_INT_STS2_GPIO4_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO4_F, 1, TPS65912_INT_STS2_GPIO4_F), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO5_R, 1, TPS65912_INT_STS2_GPIO5_R), + REGMAP_IRQ_REG(TPS65912_IRQ_GPIO5_F, 1, TPS65912_INT_STS2_GPIO5_F), + /* INT_STS3 IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC1, 2, TPS65912_INT_STS3_PGOOD_DCDC1), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC2, 2, TPS65912_INT_STS3_PGOOD_DCDC2), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC3, 2, TPS65912_INT_STS3_PGOOD_DCDC3), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_DCDC4, 2, TPS65912_INT_STS3_PGOOD_DCDC4), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO1, 2, TPS65912_INT_STS3_PGOOD_LDO1), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO2, 2, TPS65912_INT_STS3_PGOOD_LDO2), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO3, 2, TPS65912_INT_STS3_PGOOD_LDO3), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO4, 2, TPS65912_INT_STS3_PGOOD_LDO4), + /* INT_STS4 IRQs */ + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO5, 3, TPS65912_INT_STS4_PGOOD_LDO5), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO6, 3, TPS65912_INT_STS4_PGOOD_LDO6), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO7, 3, TPS65912_INT_STS4_PGOOD_LDO7), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO8, 3, TPS65912_INT_STS4_PGOOD_LDO8), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO9, 3, TPS65912_INT_STS4_PGOOD_LDO9), + REGMAP_IRQ_REG(TPS65912_IRQ_PGOOD_LDO10, 3, TPS65912_INT_STS4_PGOOD_LDO10), +}; + +static struct regmap_irq_chip tps65912_irq_chip = { + .name = "tps65912", + .irqs = tps65912_irqs, + .num_irqs = ARRAY_SIZE(tps65912_irqs), + .num_regs = 4, + .irq_reg_stride = 2, + .mask_base = TPS65912_INT_MSK, + .status_base = TPS65912_INT_STS, + .ack_base = TPS65912_INT_STS, + .init_ack_masked = true, +}; + +int tps65912_device_init(struct tps65912 *tps) +{ + int ret; + + ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0, + &tps65912_irq_chip, &tps->irq_data); + if (ret) + return ret; + + ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65912_cells, + ARRAY_SIZE(tps65912_cells), NULL, 0, + regmap_irq_get_domain(tps->irq_data)); + if (ret) { + regmap_del_irq_chip(tps->irq, tps->irq_data); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(tps65912_device_init); + +int tps65912_device_exit(struct tps65912 *tps) +{ + regmap_del_irq_chip(tps->irq, tps->irq_data); + + return 0; +} +EXPORT_SYMBOL_GPL(tps65912_device_exit); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912x MFD Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/tps65912-i2c.c b/drivers/mfd/tps65912-i2c.c new file mode 100644 index 000000000000..45871403f995 --- /dev/null +++ b/drivers/mfd/tps65912-i2c.c @@ -0,0 +1,79 @@ +/* + * I2C access driver for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +static const struct of_device_id tps65912_i2c_of_match_table[] = { + { .compatible = "ti,tps65912", }, + { /* sentinel */ } +}; + +static int tps65912_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *ids) +{ + struct tps65912 *tps; + + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + i2c_set_clientdata(client, tps); + tps->dev = &client->dev; + tps->irq = client->irq; + + tps->regmap = devm_regmap_init_i2c(client, &tps65912_regmap_config); + if (IS_ERR(tps->regmap)) { + dev_err(tps->dev, "Failed to initialize register map\n"); + return PTR_ERR(tps->regmap); + } + + return tps65912_device_init(tps); +} + +static int tps65912_i2c_remove(struct i2c_client *client) +{ + struct tps65912 *tps = i2c_get_clientdata(client); + + return tps65912_device_exit(tps); +} + +static const struct i2c_device_id tps65912_i2c_id_table[] = { + { "tps65912", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, tps65912_i2c_id_table); + +static struct i2c_driver tps65912_i2c_driver = { + .driver = { + .name = "tps65912", + .of_match_table = tps65912_i2c_of_match_table, + }, + .probe = tps65912_i2c_probe, + .remove = tps65912_i2c_remove, + .id_table = tps65912_i2c_id_table, +}; +module_i2c_driver(tps65912_i2c_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912x I2C Interface Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c new file mode 100644 index 000000000000..4aeba9b6942a --- /dev/null +++ b/drivers/mfd/tps65912-spi.c @@ -0,0 +1,78 @@ +/* + * SPI access driver for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +static const struct of_device_id tps65912_spi_of_match_table[] = { + { .compatible = "ti,tps65912", }, + { /* sentinel */ } +}; + +static int tps65912_spi_probe(struct spi_device *spi) +{ + struct tps65912 *tps; + + tps = devm_kzalloc(&spi->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) + return -ENOMEM; + + spi_set_drvdata(spi, tps); + tps->dev = &spi->dev; + tps->irq = spi->irq; + + tps->regmap = devm_regmap_init_spi(spi, &tps65912_regmap_config); + if (IS_ERR(tps->regmap)) { + dev_err(tps->dev, "Failed to initialize register map\n"); + return PTR_ERR(tps->regmap); + } + + return tps65912_device_init(tps); +} + +static int tps65912_spi_remove(struct spi_device *client) +{ + struct tps65912 *tps = spi_get_drvdata(client); + + return tps65912_device_exit(tps); +} + +static const struct spi_device_id tps65912_spi_id_table[] = { + { "tps65912", 0 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(spi, tps65912_spi_id_table); + +static struct spi_driver tps65912_spi_driver = { + .driver = { + .name = "tps65912", + .of_match_table = tps65912_spi_of_match_table, + }, + .probe = tps65912_spi_probe, + .remove = tps65912_spi_remove, + .id_table = tps65912_spi_id_table, +}; +module_spi_driver(tps65912_spi_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912x SPI Interface Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/tps65912.h b/include/linux/mfd/tps65912.h new file mode 100644 index 000000000000..1a603701550e --- /dev/null +++ b/include/linux/mfd/tps65912.h @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#ifndef __LINUX_MFD_TPS65912_H +#define __LINUX_MFD_TPS65912_H + +#include +#include + +/* List of registers for TPS65912 */ +#define TPS65912_DCDC1_CTRL 0x00 +#define TPS65912_DCDC2_CTRL 0x01 +#define TPS65912_DCDC3_CTRL 0x02 +#define TPS65912_DCDC4_CTRL 0x03 +#define TPS65912_DCDC1_OP 0x04 +#define TPS65912_DCDC1_AVS 0x05 +#define TPS65912_DCDC1_LIMIT 0x06 +#define TPS65912_DCDC2_OP 0x07 +#define TPS65912_DCDC2_AVS 0x08 +#define TPS65912_DCDC2_LIMIT 0x09 +#define TPS65912_DCDC3_OP 0x0A +#define TPS65912_DCDC3_AVS 0x0B +#define TPS65912_DCDC3_LIMIT 0x0C +#define TPS65912_DCDC4_OP 0x0D +#define TPS65912_DCDC4_AVS 0x0E +#define TPS65912_DCDC4_LIMIT 0x0F +#define TPS65912_LDO1_OP 0x10 +#define TPS65912_LDO1_AVS 0x11 +#define TPS65912_LDO1_LIMIT 0x12 +#define TPS65912_LDO2_OP 0x13 +#define TPS65912_LDO2_AVS 0x14 +#define TPS65912_LDO2_LIMIT 0x15 +#define TPS65912_LDO3_OP 0x16 +#define TPS65912_LDO3_AVS 0x17 +#define TPS65912_LDO3_LIMIT 0x18 +#define TPS65912_LDO4_OP 0x19 +#define TPS65912_LDO4_AVS 0x1A +#define TPS65912_LDO4_LIMIT 0x1B +#define TPS65912_LDO5 0x1C +#define TPS65912_LDO6 0x1D +#define TPS65912_LDO7 0x1E +#define TPS65912_LDO8 0x1F +#define TPS65912_LDO9 0x20 +#define TPS65912_LDO10 0x21 +#define TPS65912_THRM 0x22 +#define TPS65912_CLK32OUT 0x23 +#define TPS65912_DEVCTRL 0x24 +#define TPS65912_DEVCTRL2 0x25 +#define TPS65912_I2C_SPI_CFG 0x26 +#define TPS65912_KEEP_ON 0x27 +#define TPS65912_KEEP_ON2 0x28 +#define TPS65912_SET_OFF1 0x29 +#define TPS65912_SET_OFF2 0x2A +#define TPS65912_DEF_VOLT 0x2B +#define TPS65912_DEF_VOLT_MAPPING 0x2C +#define TPS65912_DISCHARGE 0x2D +#define TPS65912_DISCHARGE2 0x2E +#define TPS65912_EN1_SET1 0x2F +#define TPS65912_EN1_SET2 0x30 +#define TPS65912_EN2_SET1 0x31 +#define TPS65912_EN2_SET2 0x32 +#define TPS65912_EN3_SET1 0x33 +#define TPS65912_EN3_SET2 0x34 +#define TPS65912_EN4_SET1 0x35 +#define TPS65912_EN4_SET2 0x36 +#define TPS65912_PGOOD 0x37 +#define TPS65912_PGOOD2 0x38 +#define TPS65912_INT_STS 0x39 +#define TPS65912_INT_MSK 0x3A +#define TPS65912_INT_STS2 0x3B +#define TPS65912_INT_MSK2 0x3C +#define TPS65912_INT_STS3 0x3D +#define TPS65912_INT_MSK3 0x3E +#define TPS65912_INT_STS4 0x3F +#define TPS65912_INT_MSK4 0x40 +#define TPS65912_GPIO1 0x41 +#define TPS65912_GPIO2 0x42 +#define TPS65912_GPIO3 0x43 +#define TPS65912_GPIO4 0x44 +#define TPS65912_GPIO5 0x45 +#define TPS65912_VMON 0x46 +#define TPS65912_LEDA_CTRL1 0x47 +#define TPS65912_LEDA_CTRL2 0x48 +#define TPS65912_LEDA_CTRL3 0x49 +#define TPS65912_LEDA_CTRL4 0x4A +#define TPS65912_LEDA_CTRL5 0x4B +#define TPS65912_LEDA_CTRL6 0x4C +#define TPS65912_LEDA_CTRL7 0x4D +#define TPS65912_LEDA_CTRL8 0x4E +#define TPS65912_LEDB_CTRL1 0x4F +#define TPS65912_LEDB_CTRL2 0x50 +#define TPS65912_LEDB_CTRL3 0x51 +#define TPS65912_LEDB_CTRL4 0x52 +#define TPS65912_LEDB_CTRL5 0x53 +#define TPS65912_LEDB_CTRL6 0x54 +#define TPS65912_LEDB_CTRL7 0x55 +#define TPS65912_LEDB_CTRL8 0x56 +#define TPS65912_LEDC_CTRL1 0x57 +#define TPS65912_LEDC_CTRL2 0x58 +#define TPS65912_LEDC_CTRL3 0x59 +#define TPS65912_LEDC_CTRL4 0x5A +#define TPS65912_LEDC_CTRL5 0x5B +#define TPS65912_LEDC_CTRL6 0x5C +#define TPS65912_LEDC_CTRL7 0x5D +#define TPS65912_LEDC_CTRL8 0x5E +#define TPS65912_LED_RAMP_UP_TIME 0x5F +#define TPS65912_LED_RAMP_DOWN_TIME 0x60 +#define TPS65912_LED_SEQ_EN 0x61 +#define TPS65912_LOADSWITCH 0x62 +#define TPS65912_SPARE 0x63 +#define TPS65912_VERNUM 0x64 +#define TPS6591X_MAX_REGISTER 0x64 + +/* INT_STS Register field definitions */ +#define TPS65912_INT_STS_PWRHOLD_F BIT(0) +#define TPS65912_INT_STS_VMON BIT(1) +#define TPS65912_INT_STS_PWRON BIT(2) +#define TPS65912_INT_STS_PWRON_LP BIT(3) +#define TPS65912_INT_STS_PWRHOLD_R BIT(4) +#define TPS65912_INT_STS_HOTDIE BIT(5) +#define TPS65912_INT_STS_GPIO1_R BIT(6) +#define TPS65912_INT_STS_GPIO1_F BIT(7) + +/* INT_STS Register field definitions */ +#define TPS65912_INT_STS2_GPIO2_R BIT(0) +#define TPS65912_INT_STS2_GPIO2_F BIT(1) +#define TPS65912_INT_STS2_GPIO3_R BIT(2) +#define TPS65912_INT_STS2_GPIO3_F BIT(3) +#define TPS65912_INT_STS2_GPIO4_R BIT(4) +#define TPS65912_INT_STS2_GPIO4_F BIT(5) +#define TPS65912_INT_STS2_GPIO5_R BIT(6) +#define TPS65912_INT_STS2_GPIO5_F BIT(7) + +/* INT_STS Register field definitions */ +#define TPS65912_INT_STS3_PGOOD_DCDC1 BIT(0) +#define TPS65912_INT_STS3_PGOOD_DCDC2 BIT(1) +#define TPS65912_INT_STS3_PGOOD_DCDC3 BIT(2) +#define TPS65912_INT_STS3_PGOOD_DCDC4 BIT(3) +#define TPS65912_INT_STS3_PGOOD_LDO1 BIT(4) +#define TPS65912_INT_STS3_PGOOD_LDO2 BIT(5) +#define TPS65912_INT_STS3_PGOOD_LDO3 BIT(6) +#define TPS65912_INT_STS3_PGOOD_LDO4 BIT(7) + +/* INT_STS Register field definitions */ +#define TPS65912_INT_STS4_PGOOD_LDO5 BIT(0) +#define TPS65912_INT_STS4_PGOOD_LDO6 BIT(1) +#define TPS65912_INT_STS4_PGOOD_LDO7 BIT(2) +#define TPS65912_INT_STS4_PGOOD_LDO8 BIT(3) +#define TPS65912_INT_STS4_PGOOD_LDO9 BIT(4) +#define TPS65912_INT_STS4_PGOOD_LDO10 BIT(5) + +/* GPIO 1 and 2 Register field definitions */ +#define GPIO_SLEEP_MASK 0x80 +#define GPIO_SLEEP_SHIFT 7 +#define GPIO_DEB_MASK 0x10 +#define GPIO_DEB_SHIFT 4 +#define GPIO_CFG_MASK 0x04 +#define GPIO_CFG_SHIFT 2 +#define GPIO_STS_MASK 0x02 +#define GPIO_STS_SHIFT 1 +#define GPIO_SET_MASK 0x01 +#define GPIO_SET_SHIFT 0 + +/* GPIO 3 Register field definitions */ +#define GPIO3_SLEEP_MASK 0x80 +#define GPIO3_SLEEP_SHIFT 7 +#define GPIO3_SEL_MASK 0x40 +#define GPIO3_SEL_SHIFT 6 +#define GPIO3_ODEN_MASK 0x20 +#define GPIO3_ODEN_SHIFT 5 +#define GPIO3_DEB_MASK 0x10 +#define GPIO3_DEB_SHIFT 4 +#define GPIO3_PDEN_MASK 0x08 +#define GPIO3_PDEN_SHIFT 3 +#define GPIO3_CFG_MASK 0x04 +#define GPIO3_CFG_SHIFT 2 +#define GPIO3_STS_MASK 0x02 +#define GPIO3_STS_SHIFT 1 +#define GPIO3_SET_MASK 0x01 +#define GPIO3_SET_SHIFT 0 + +/* GPIO 4 Register field definitions */ +#define GPIO4_SLEEP_MASK 0x80 +#define GPIO4_SLEEP_SHIFT 7 +#define GPIO4_SEL_MASK 0x40 +#define GPIO4_SEL_SHIFT 6 +#define GPIO4_ODEN_MASK 0x20 +#define GPIO4_ODEN_SHIFT 5 +#define GPIO4_DEB_MASK 0x10 +#define GPIO4_DEB_SHIFT 4 +#define GPIO4_PDEN_MASK 0x08 +#define GPIO4_PDEN_SHIFT 3 +#define GPIO4_CFG_MASK 0x04 +#define GPIO4_CFG_SHIFT 2 +#define GPIO4_STS_MASK 0x02 +#define GPIO4_STS_SHIFT 1 +#define GPIO4_SET_MASK 0x01 +#define GPIO4_SET_SHIFT 0 + +/* Register THERM (0x80) register.RegisterDescription */ +#define THERM_THERM_HD_MASK 0x20 +#define THERM_THERM_HD_SHIFT 5 +#define THERM_THERM_TS_MASK 0x10 +#define THERM_THERM_TS_SHIFT 4 +#define THERM_THERM_HDSEL_MASK 0x0C +#define THERM_THERM_HDSEL_SHIFT 2 +#define THERM_RSVD1_MASK 0x02 +#define THERM_RSVD1_SHIFT 1 +#define THERM_THERM_STATE_MASK 0x01 +#define THERM_THERM_STATE_SHIFT 0 + +/* Register DCDCCTRL1 register.RegisterDescription */ +#define DCDCCTRL_VCON_ENABLE_MASK 0x80 +#define DCDCCTRL_VCON_ENABLE_SHIFT 7 +#define DCDCCTRL_VCON_RANGE1_MASK 0x40 +#define DCDCCTRL_VCON_RANGE1_SHIFT 6 +#define DCDCCTRL_VCON_RANGE0_MASK 0x20 +#define DCDCCTRL_VCON_RANGE0_SHIFT 5 +#define DCDCCTRL_TSTEP2_MASK 0x10 +#define DCDCCTRL_TSTEP2_SHIFT 4 +#define DCDCCTRL_TSTEP1_MASK 0x08 +#define DCDCCTRL_TSTEP1_SHIFT 3 +#define DCDCCTRL_TSTEP0_MASK 0x04 +#define DCDCCTRL_TSTEP0_SHIFT 2 +#define DCDCCTRL_DCDC1_MODE_MASK 0x02 +#define DCDCCTRL_DCDC1_MODE_SHIFT 1 + +/* Register DCDCCTRL2 and DCDCCTRL3 register.RegisterDescription */ +#define DCDCCTRL_TSTEP2_MASK 0x10 +#define DCDCCTRL_TSTEP2_SHIFT 4 +#define DCDCCTRL_TSTEP1_MASK 0x08 +#define DCDCCTRL_TSTEP1_SHIFT 3 +#define DCDCCTRL_TSTEP0_MASK 0x04 +#define DCDCCTRL_TSTEP0_SHIFT 2 +#define DCDCCTRL_DCDC_MODE_MASK 0x02 +#define DCDCCTRL_DCDC_MODE_SHIFT 1 +#define DCDCCTRL_RSVD0_MASK 0x01 +#define DCDCCTRL_RSVD0_SHIFT 0 + +/* Register DCDCCTRL4 register.RegisterDescription */ +#define DCDCCTRL_RAMP_TIME_MASK 0x01 +#define DCDCCTRL_RAMP_TIME_SHIFT 0 + +/* Register DCDCx_AVS */ +#define DCDC_AVS_ENABLE_MASK 0x80 +#define DCDC_AVS_ENABLE_SHIFT 7 +#define DCDC_AVS_ECO_MASK 0x40 +#define DCDC_AVS_ECO_SHIFT 6 + +/* Register DCDCx_LIMIT */ +#define DCDC_LIMIT_RANGE_MASK 0xC0 +#define DCDC_LIMIT_RANGE_SHIFT 6 +#define DCDC_LIMIT_MAX_SEL_MASK 0x3F +#define DCDC_LIMIT_MAX_SEL_SHIFT 0 + +/* Define the TPS65912 IRQ numbers */ +enum tps65912_irqs { + /* INT_STS registers */ + TPS65912_IRQ_PWRHOLD_F, + TPS65912_IRQ_VMON, + TPS65912_IRQ_PWRON, + TPS65912_IRQ_PWRON_LP, + TPS65912_IRQ_PWRHOLD_R, + TPS65912_IRQ_HOTDIE, + TPS65912_IRQ_GPIO1_R, + TPS65912_IRQ_GPIO1_F, + /* INT_STS2 registers */ + TPS65912_IRQ_GPIO2_R, + TPS65912_IRQ_GPIO2_F, + TPS65912_IRQ_GPIO3_R, + TPS65912_IRQ_GPIO3_F, + TPS65912_IRQ_GPIO4_R, + TPS65912_IRQ_GPIO4_F, + TPS65912_IRQ_GPIO5_R, + TPS65912_IRQ_GPIO5_F, + /* INT_STS3 registers */ + TPS65912_IRQ_PGOOD_DCDC1, + TPS65912_IRQ_PGOOD_DCDC2, + TPS65912_IRQ_PGOOD_DCDC3, + TPS65912_IRQ_PGOOD_DCDC4, + TPS65912_IRQ_PGOOD_LDO1, + TPS65912_IRQ_PGOOD_LDO2, + TPS65912_IRQ_PGOOD_LDO3, + TPS65912_IRQ_PGOOD_LDO4, + /* INT_STS4 registers */ + TPS65912_IRQ_PGOOD_LDO5, + TPS65912_IRQ_PGOOD_LDO6, + TPS65912_IRQ_PGOOD_LDO7, + TPS65912_IRQ_PGOOD_LDO8, + TPS65912_IRQ_PGOOD_LDO9, + TPS65912_IRQ_PGOOD_LDO10, +}; + +/* + * struct tps65912 - state holder for the tps65912 driver + * + * Device data may be used to access the TPS65912 chip + */ +struct tps65912 { + struct device *dev; + struct regmap *regmap; + + /* IRQ Data */ + int irq; + struct regmap_irq_chip_data *irq_data; +}; + +static const struct regmap_range tps65912_yes_ranges[] = { + regmap_reg_range(TPS65912_INT_STS, TPS65912_GPIO5), +}; + +static const struct regmap_access_table tps65912_volatile_table = { + .yes_ranges = tps65912_yes_ranges, + .n_yes_ranges = ARRAY_SIZE(tps65912_yes_ranges), +}; + +static const struct regmap_config tps65912_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_RBTREE, + .volatile_table = &tps65912_volatile_table, +}; + +int tps65912_device_init(struct tps65912 *tps); +int tps65912_device_exit(struct tps65912 *tps); + +#endif /* __LINUX_MFD_TPS65912_H */ -- cgit From 33f9d8c0b49c1e63d6efc6e60a52afcf85f5de65 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 25 Jan 2016 09:43:46 -0600 Subject: regulator: tps65912: Add regulator driver for the TPS65912 PMIC This patch adds support for TPS65912 PMIC regulators. The regulators set consists of 4 DCDCs and 10 LDOs. The output voltages are configurable and are meant to supply power to the main processor and other components. Signed-off-by: Andrew F. Davis Acked-by: Mark Brown Signed-off-by: Lee Jones --- drivers/regulator/Kconfig | 6 ++ drivers/regulator/Makefile | 1 + drivers/regulator/tps65912-regulator.c | 168 +++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) create mode 100644 drivers/regulator/tps65912-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index eb1b4a26cb3e..32f77a1e8305 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -760,6 +760,12 @@ config REGULATOR_TPS65910 help This driver supports TPS65910/TPS65911 voltage regulator chips. +config REGULATOR_TPS65912 + tristate "TI TPS65912 Power regulator" + depends on MFD_TPS65912 + help + This driver supports TPS65912 voltage regulator chip. + config REGULATOR_TPS80031 tristate "TI TPS80031/TPS80032 power regualtor driver" depends on MFD_TPS80031 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 85da3192701c..980b1943fa81 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o +obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c new file mode 100644 index 000000000000..a4921a70da55 --- /dev/null +++ b/drivers/regulator/tps65912-regulator.c @@ -0,0 +1,168 @@ +/* + * Regulator driver for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the TPS65218 driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +enum tps65912_regulators { DCDC1, DCDC2, DCDC3, DCDC4, LDO1, LDO2, LDO3, + LDO4, LDO5, LDO6, LDO7, LDO8, LDO9, LDO10 }; + +#define TPS65912_REGULATOR(_name, _id, _of_match, _ops, _vr, _er, _lr) \ + [_id] = { \ + .name = _name, \ + .of_match = _of_match, \ + .regulators_node = "regulators", \ + .id = _id, \ + .ops = &_ops, \ + .n_voltages = 64, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .vsel_reg = _vr, \ + .vsel_mask = 0x3f, \ + .enable_reg = _er, \ + .enable_mask = BIT(7), \ + .volt_table = NULL, \ + .linear_ranges = _lr, \ + .n_linear_ranges = ARRAY_SIZE(_lr), \ + } + +static const struct regulator_linear_range tps65912_dcdc_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, 0x0, 0x3f, 50000), +}; + +static const struct regulator_linear_range tps65912_ldo_ranges[] = { + REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 25000), + REGULATOR_LINEAR_RANGE(1650000, 0x21, 0x3c, 50000), + REGULATOR_LINEAR_RANGE(3100000, 0x3d, 0x3f, 100000), +}; + +/* Operations permitted on DCDCx */ +static struct regulator_ops tps65912_ops_dcdc = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, +}; + +/* Operations permitted on LDOx */ +static struct regulator_ops tps65912_ops_ldo = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .map_voltage = regulator_map_voltage_linear_range, +}; + +static const struct regulator_desc regulators[] = { + TPS65912_REGULATOR("DCDC1", DCDC1, "dcdc1", tps65912_ops_dcdc, + TPS65912_DCDC1_OP, TPS65912_DCDC1_CTRL, + tps65912_dcdc_ranges), + TPS65912_REGULATOR("DCDC2", DCDC2, "dcdc2", tps65912_ops_dcdc, + TPS65912_DCDC2_OP, TPS65912_DCDC2_CTRL, + tps65912_dcdc_ranges), + TPS65912_REGULATOR("DCDC3", DCDC3, "dcdc3", tps65912_ops_dcdc, + TPS65912_DCDC3_OP, TPS65912_DCDC3_CTRL, + tps65912_dcdc_ranges), + TPS65912_REGULATOR("DCDC4", DCDC4, "dcdc4", tps65912_ops_dcdc, + TPS65912_DCDC4_OP, TPS65912_DCDC4_CTRL, + tps65912_dcdc_ranges), + TPS65912_REGULATOR("LDO1", LDO1, "ldo1", tps65912_ops_ldo, + TPS65912_LDO1_OP, TPS65912_LDO1_AVS, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO2", LDO2, "ldo2", tps65912_ops_ldo, + TPS65912_LDO2_OP, TPS65912_LDO2_AVS, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO3", LDO3, "ldo3", tps65912_ops_ldo, + TPS65912_LDO3_OP, TPS65912_LDO3_AVS, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO4", LDO4, "ldo4", tps65912_ops_ldo, + TPS65912_LDO4_OP, TPS65912_LDO4_AVS, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO5", LDO5, "ldo5", tps65912_ops_ldo, + TPS65912_LDO5, TPS65912_LDO5, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO6", LDO6, "ldo6", tps65912_ops_ldo, + TPS65912_LDO6, TPS65912_LDO6, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO7", LDO7, "ldo7", tps65912_ops_ldo, + TPS65912_LDO7, TPS65912_LDO7, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO8", LDO8, "ldo8", tps65912_ops_ldo, + TPS65912_LDO8, TPS65912_LDO8, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO9", LDO9, "ldo9", tps65912_ops_ldo, + TPS65912_LDO9, TPS65912_LDO9, + tps65912_ldo_ranges), + TPS65912_REGULATOR("LDO10", LDO10, "ldo10", tps65912_ops_ldo, + TPS65912_LDO10, TPS65912_LDO10, + tps65912_ldo_ranges), +}; + +static int tps65912_regulator_probe(struct platform_device *pdev) +{ + struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); + struct regulator_config config = { }; + struct regulator_dev *rdev; + int i; + + platform_set_drvdata(pdev, tps); + + config.dev = &pdev->dev; + config.driver_data = tps; + config.dev->of_node = tps->dev->of_node; + config.regmap = tps->regmap; + + for (i = 0; i < ARRAY_SIZE(regulators); i++) { + rdev = devm_regulator_register(&pdev->dev, ®ulators[i], + &config); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "failed to register %s regulator\n", + pdev->name); + return PTR_ERR(rdev); + } + } + + return 0; +} + +static const struct platform_device_id tps65912_regulator_id_table[] = { + { "tps65912-regulator", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, tps65912_regulator_id_table); + +static struct platform_driver tps65912_regulator_driver = { + .driver = { + .name = "tps65912-regulator", + }, + .probe = tps65912_regulator_probe, + .id_table = tps65912_regulator_id_table, +}; +module_platform_driver(tps65912_regulator_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912 voltage regulator driver"); +MODULE_LICENSE("GPL v2"); -- cgit From ca801a22f465eae39fadc770e15b5b7e82595f81 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Mon, 25 Jan 2016 09:43:47 -0600 Subject: gpio: tps65912: Add GPIO driver for the TPS65912 PMIC This patch adds support for the TPS65912 PMIC GPIOs. TPS65912 has five configurable GPIOs that can be used for several purposes. Signed-off-by: Andrew F. Davis Reviewed-by: Linus Walleij Signed-off-by: Lee Jones --- drivers/gpio/Kconfig | 6 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-tps65912.c | 158 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 drivers/gpio/gpio-tps65912.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 98eaeddc0ae3..3d60b742e42c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -858,6 +858,12 @@ config GPIO_TPS65910 Select this option to enable GPIO driver for the TPS65910 chip family. +config GPIO_TPS65912 + tristate "TI TPS65912 GPIO" + depends on MFD_TPS65912 + help + This driver supports TPS65912 gpio chip + config GPIO_TWL4030 tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" depends on TWL4030_CORE diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index edc33f0a6788..ece7d7cbdc80 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o obj-$(CONFIG_GPIO_TPS6586X) += gpio-tps6586x.o obj-$(CONFIG_GPIO_TPS65910) += gpio-tps65910.o +obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o obj-$(CONFIG_GPIO_TS5500) += gpio-ts5500.o obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c new file mode 100644 index 000000000000..3da3840201de --- /dev/null +++ b/drivers/gpio/gpio-tps65912.c @@ -0,0 +1,158 @@ +/* + * GPIO driver for TI TPS65912x PMICs + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis + * + * 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 expressed or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License version 2 for more details. + * + * Based on the Arizona GPIO driver and the previous TPS65912 driver by + * Margarita Olaya Cabrera + */ + +#include +#include +#include + +#include + +struct tps65912_gpio { + struct gpio_chip gpio_chip; + struct tps65912 *tps; +}; + +static int tps65912_gpio_get_direction(struct gpio_chip *gc, + unsigned offset) +{ + struct tps65912_gpio *gpio = gpiochip_get_data(gc); + + int ret, val; + + ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); + if (ret) + return ret; + + if (val & GPIO_CFG_MASK) + return GPIOF_DIR_OUT; + else + return GPIOF_DIR_IN; +} + +static int tps65912_gpio_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct tps65912_gpio *gpio = gpiochip_get_data(gc); + + return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, + GPIO_CFG_MASK, 0); +} + +static int tps65912_gpio_direction_output(struct gpio_chip *gc, + unsigned offset, int value) +{ + struct tps65912_gpio *gpio = gpiochip_get_data(gc); + + /* Set the initial value */ + regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, + GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); + + return regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, + GPIO_CFG_MASK, GPIO_CFG_MASK); +} + +static int tps65912_gpio_get(struct gpio_chip *gc, unsigned offset) +{ + struct tps65912_gpio *gpio = gpiochip_get_data(gc); + int ret, val; + + ret = regmap_read(gpio->tps->regmap, TPS65912_GPIO1 + offset, &val); + if (ret) + return ret; + + if (val & GPIO_STS_MASK) + return 1; + + return 0; +} + +static void tps65912_gpio_set(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct tps65912_gpio *gpio = gpiochip_get_data(gc); + + regmap_update_bits(gpio->tps->regmap, TPS65912_GPIO1 + offset, + GPIO_SET_MASK, value ? GPIO_SET_MASK : 0); +} + +static struct gpio_chip template_chip = { + .label = "tps65912-gpio", + .owner = THIS_MODULE, + .get_direction = tps65912_gpio_get_direction, + .direction_input = tps65912_gpio_direction_input, + .direction_output = tps65912_gpio_direction_output, + .get = tps65912_gpio_get, + .set = tps65912_gpio_set, + .base = -1, + .ngpio = 5, + .can_sleep = true, +}; + +static int tps65912_gpio_probe(struct platform_device *pdev) +{ + struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent); + struct tps65912_gpio *gpio; + int ret; + + gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->tps = dev_get_drvdata(pdev->dev.parent); + gpio->gpio_chip = template_chip; + gpio->gpio_chip.parent = tps->dev; + + ret = gpiochip_add_data(&gpio->gpio_chip, gpio); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, gpio); + + return 0; +} + +static int tps65912_gpio_remove(struct platform_device *pdev) +{ + struct tps65912_gpio *gpio = platform_get_drvdata(pdev); + + gpiochip_remove(&gpio->gpio_chip); + + return 0; +} + +static const struct platform_device_id tps65912_gpio_id_table[] = { + { "tps65912-gpio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, tps65912_gpio_id_table); + +static struct platform_driver tps65912_gpio_driver = { + .driver = { + .name = "tps65912-gpio", + }, + .probe = tps65912_gpio_probe, + .remove = tps65912_gpio_remove, + .id_table = tps65912_gpio_id_table, +}; +module_platform_driver(tps65912_gpio_driver); + +MODULE_AUTHOR("Andrew F. Davis "); +MODULE_DESCRIPTION("TPS65912 GPIO driver"); +MODULE_LICENSE("GPL v2"); -- cgit From aa54c8da9a8e480861346d88b57086490bdd7b03 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Tue, 9 Feb 2016 20:47:13 +0100 Subject: net: phy: spi_ks8995: introduce spi_device_id table Refactor to use spi_device_id table to facilitate easy extendability. Signed-off-by: Helmut Buchsbaum Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index c72c42206850..e7a215d2b1ae 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -89,6 +89,28 @@ #define KS8995_RESET_DELAY 10 /* usec */ +enum ks8995_chip_variant { + ks8995, + ksz8864, + max_variant +}; + +struct ks8995_chip_params { + char *name; + int regs_size; +}; + +static const struct ks8995_chip_params ks8995_chip[] = { + [ks8995] = { + .name = "KS8995MA", + .regs_size = KS8995_REGS_SIZE, + }, + [ksz8864] = { + .name = "KSZ8864RMN", + .regs_size = KSZ8864_REGS_SIZE, + }, +}; + struct ks8995_pdata { /* not yet implemented */ }; @@ -98,8 +120,16 @@ struct ks8995_switch { struct mutex lock; struct ks8995_pdata *pdata; struct bin_attribute regs_attr; + const struct ks8995_chip_params *chip; }; +static const struct spi_device_id ks8995_id[] = { + {"ks8995", ks8995}, + {"ksz8864", ksz8864}, + { } +}; +MODULE_DEVICE_TABLE(spi, ks8995_id); + static inline u8 get_chip_id(u8 val) { return (val >> ID1_CHIPID_S) & ID1_CHIPID_M; @@ -244,17 +274,22 @@ static const struct bin_attribute ks8995_registers_attr = { }; /* ------------------------------------------------------------------------ */ - static int ks8995_probe(struct spi_device *spi) { struct ks8995_switch *ks; struct ks8995_pdata *pdata; u8 ids[2]; int err; + int variant = spi_get_device_id(spi)->driver_data; /* Chip description */ pdata = spi->dev.platform_data; + if (variant >= max_variant) { + dev_err(&spi->dev, "bad chip variant %d\n", variant); + return -ENODEV; + } + ks = devm_kzalloc(&spi->dev, sizeof(*ks), GFP_KERNEL); if (!ks) return -ENOMEM; @@ -262,6 +297,8 @@ static int ks8995_probe(struct spi_device *spi) mutex_init(&ks->lock); ks->pdata = pdata; ks->spi = spi_dev_get(spi); + ks->chip = &ks8995_chip[variant]; + spi_set_drvdata(spi, ks); spi->mode = SPI_MODE_0; @@ -287,6 +324,7 @@ static int ks8995_probe(struct spi_device *spi) return -ENODEV; } + ks->regs_attr.size = ks->chip->regs_size; memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); if (get_chip_id(ids[1]) != CHIPID_M) { u8 val; @@ -303,7 +341,6 @@ static int ks8995_probe(struct spi_device *spi) dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]); return err; } - ks->regs_attr.size = KSZ8864_REGS_SIZE; } err = ks8995_reset(ks); @@ -346,6 +383,7 @@ static struct spi_driver ks8995_driver = { }, .probe = ks8995_probe, .remove = ks8995_remove, + .id_table = ks8995_id, }; module_spi_driver(ks8995_driver); -- cgit From 484e36ff18341ca1fca4258139100b2e90530f53 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Tue, 9 Feb 2016 20:47:14 +0100 Subject: net: phy: spi_ks8995: verify chip and determine revision Since the chip variant is now determined by spi_device_id, verify family and chip id and determine the revision id. Signed-off-by: Helmut Buchsbaum Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 118 +++++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 38 deletions(-) diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index e7a215d2b1ae..5e66d4bd7325 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -83,6 +83,8 @@ #define FAMILY_KS8995 0x95 #define CHIPID_M 0 +#define KS8995_CHIP_ID 0x00 +#define KSZ8864_CHIP_ID 0x01 #define KS8995_CMD_WRITE 0x02U #define KS8995_CMD_READ 0x03U @@ -97,16 +99,22 @@ enum ks8995_chip_variant { struct ks8995_chip_params { char *name; + int family_id; + int chip_id; int regs_size; }; static const struct ks8995_chip_params ks8995_chip[] = { [ks8995] = { .name = "KS8995MA", + .family_id = FAMILY_KS8995, + .chip_id = KS8995_CHIP_ID, .regs_size = KS8995_REGS_SIZE, }, [ksz8864] = { .name = "KSZ8864RMN", + .family_id = FAMILY_KS8995, + .chip_id = KSZ8864_CHIP_ID, .regs_size = KSZ8864_REGS_SIZE, }, }; @@ -121,6 +129,7 @@ struct ks8995_switch { struct ks8995_pdata *pdata; struct bin_attribute regs_attr; const struct ks8995_chip_params *chip; + int revision_id; }; static const struct spi_device_id ks8995_id[] = { @@ -263,6 +272,73 @@ static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj, return ks8995_write(ks8995, buf, off, count); } +/* ks8995_get_revision - get chip revision + * @ks: pointer to switch instance + * + * Verify chip family and id and get chip revision. + */ +static int ks8995_get_revision(struct ks8995_switch *ks) +{ + int err; + u8 id0, id1, ksz8864_id; + + /* read family id */ + err = ks8995_read_reg(ks, KS8995_REG_ID0, &id0); + if (err) { + err = -EIO; + goto err_out; + } + + /* verify family id */ + if (id0 != ks->chip->family_id) { + dev_err(&ks->spi->dev, "chip family id mismatch: expected 0x%02x but 0x%02x read\n", + ks->chip->family_id, id0); + err = -ENODEV; + goto err_out; + } + + switch (ks->chip->family_id) { + case FAMILY_KS8995: + /* try reading chip id at CHIP ID1 */ + err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); + if (err) { + err = -EIO; + goto err_out; + } + + /* verify chip id */ + if ((get_chip_id(id1) == CHIPID_M) && + (get_chip_id(id1) == ks->chip->chip_id)) { + /* KS8995MA */ + ks->revision_id = get_chip_rev(id1); + } else if (get_chip_id(id1) != CHIPID_M) { + /* KSZ8864RMN */ + err = ks8995_read_reg(ks, KS8995_REG_ID1, &ksz8864_id); + if (err) { + err = -EIO; + goto err_out; + } + + if ((ksz8864_id & 0x80) && + (ks->chip->chip_id == KSZ8864_CHIP_ID)) { + ks->revision_id = get_chip_rev(id1); + } + + } else { + dev_err(&ks->spi->dev, "unsupported chip id for KS8995 family: 0x%02x\n", + id1); + err = -ENODEV; + } + break; + default: + dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); + err = -ENODEV; + break; + } +err_out: + return err; +} + static const struct bin_attribute ks8995_registers_attr = { .attr = { .name = "registers", @@ -278,7 +354,6 @@ static int ks8995_probe(struct spi_device *spi) { struct ks8995_switch *ks; struct ks8995_pdata *pdata; - u8 ids[2]; int err; int variant = spi_get_device_id(spi)->driver_data; @@ -309,39 +384,12 @@ static int ks8995_probe(struct spi_device *spi) return err; } - err = ks8995_read(ks, ids, KS8995_REG_ID0, sizeof(ids)); - if (err < 0) { - dev_err(&spi->dev, "unable to read id registers, err=%d\n", - err); + err = ks8995_get_revision(ks); + if (err) return err; - } - - switch (ids[0]) { - case FAMILY_KS8995: - break; - default: - dev_err(&spi->dev, "unknown family id:%02x\n", ids[0]); - return -ENODEV; - } ks->regs_attr.size = ks->chip->regs_size; memcpy(&ks->regs_attr, &ks8995_registers_attr, sizeof(ks->regs_attr)); - if (get_chip_id(ids[1]) != CHIPID_M) { - u8 val; - - /* Check if this is a KSZ8864RMN */ - err = ks8995_read(ks, &val, KSZ8864_REG_ID1, sizeof(val)); - if (err < 0) { - dev_err(&spi->dev, - "unable to read chip id register, err=%d\n", - err); - return err; - } - if ((val & 0x80) == 0) { - dev_err(&spi->dev, "unknown chip:%02x,0\n", ids[1]); - return err; - } - } err = ks8995_reset(ks); if (err) @@ -354,14 +402,8 @@ static int ks8995_probe(struct spi_device *spi) return err; } - if (get_chip_id(ids[1]) == CHIPID_M) { - dev_info(&spi->dev, - "KS8995 device found, Chip ID:%x, Revision:%x\n", - get_chip_id(ids[1]), get_chip_rev(ids[1])); - } else { - dev_info(&spi->dev, "KSZ8864 device found, Revision:%x\n", - get_chip_rev(ids[1])); - } + dev_info(&spi->dev, "%s device found, Chip ID:%x, Revision:%x\n", + ks->chip->name, ks->chip->chip_id, ks->revision_id); return 0; } -- cgit From cd6f288cbaab656cebd524c5ef2388c11378c827 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Tue, 9 Feb 2016 20:47:15 +0100 Subject: net: phy: spi_ks8995: add support for resetting switch using GPIO When using device tree it is no more possible to reset the PHY at board level. Furthermore, doing in the driver allows to power down the switch when it is not used any more. The patch introduces a new optional property "reset-gpios" denoting an appropriate GPIO handle, e.g.: reset-gpios = <&gpio0 46 GPIO_ACTIVE_LOW> Signed-off-by: Helmut Buchsbaum Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 71 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index 5e66d4bd7325..8258c166a767 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include @@ -120,7 +123,8 @@ static const struct ks8995_chip_params ks8995_chip[] = { }; struct ks8995_pdata { - /* not yet implemented */ + int reset_gpio; + enum of_gpio_flags reset_gpio_flags; }; struct ks8995_switch { @@ -339,6 +343,24 @@ err_out: return err; } +/* ks8995_parse_dt - setup platform data from devicetree + * @ks: pointer to switch instance + * + * Parses supported DT properties and sets up platform data + * accordingly. + */ +static void ks8995_parse_dt(struct ks8995_switch *ks) +{ + struct device_node *np = ks->spi->dev.of_node; + struct ks8995_pdata *pdata = ks->pdata; + + if (!np) + return; + + pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, + &pdata->reset_gpio_flags); +} + static const struct bin_attribute ks8995_registers_attr = { .attr = { .name = "registers", @@ -352,14 +374,10 @@ static const struct bin_attribute ks8995_registers_attr = { /* ------------------------------------------------------------------------ */ static int ks8995_probe(struct spi_device *spi) { - struct ks8995_switch *ks; - struct ks8995_pdata *pdata; - int err; + struct ks8995_switch *ks; + int err; int variant = spi_get_device_id(spi)->driver_data; - /* Chip description */ - pdata = spi->dev.platform_data; - if (variant >= max_variant) { dev_err(&spi->dev, "bad chip variant %d\n", variant); return -ENODEV; @@ -370,10 +388,42 @@ static int ks8995_probe(struct spi_device *spi) return -ENOMEM; mutex_init(&ks->lock); - ks->pdata = pdata; ks->spi = spi_dev_get(spi); ks->chip = &ks8995_chip[variant]; + if (ks->spi->dev.of_node) { + ks->pdata = devm_kzalloc(&spi->dev, sizeof(*ks->pdata), + GFP_KERNEL); + if (!ks->pdata) + return -ENOMEM; + + ks->pdata->reset_gpio = -1; + + ks8995_parse_dt(ks); + } + + if (!ks->pdata) + ks->pdata = spi->dev.platform_data; + + /* de-assert switch reset */ + if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio)) { + unsigned long flags; + + flags = (ks->pdata->reset_gpio_flags == OF_GPIO_ACTIVE_LOW ? + GPIOF_ACTIVE_LOW : 0); + + err = devm_gpio_request_one(&spi->dev, + ks->pdata->reset_gpio, + flags, "switch-reset"); + if (err) { + dev_err(&spi->dev, + "failed to get reset-gpios: %d\n", err); + return -EIO; + } + + gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 0); + } + spi_set_drvdata(spi, ks); spi->mode = SPI_MODE_0; @@ -414,11 +464,14 @@ static int ks8995_remove(struct spi_device *spi) sysfs_remove_bin_file(&spi->dev.kobj, &ks->regs_attr); + /* assert reset */ + if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio)) + gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 1); + return 0; } /* ------------------------------------------------------------------------ */ - static struct spi_driver ks8995_driver = { .driver = { .name = "spi-ks8995", -- cgit From 6665e62387c64054493411d00c7b0a5a37af88a5 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Tue, 9 Feb 2016 20:47:16 +0100 Subject: net: phy: spi_ks8995: generalize creation of SPI commands Prepare creating SPI reads and writes for other switch families. The KS8995 family uses the straight forward <8bit CMD><8bit ADDR> sequence. To be able to support KSZ8795 family, which uses <3bit CMD><12bit ADDR><1 bit TR> make the SPI command creation chip variant dependent. Signed-off-by: Helmut Buchsbaum Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 46 +++++++++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index 8258c166a767..9dcc5b4fd9d1 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -105,6 +105,8 @@ struct ks8995_chip_params { int family_id; int chip_id; int regs_size; + int addr_width; + int addr_shift; }; static const struct ks8995_chip_params ks8995_chip[] = { @@ -113,12 +115,16 @@ static const struct ks8995_chip_params ks8995_chip[] = { .family_id = FAMILY_KS8995, .chip_id = KS8995_CHIP_ID, .regs_size = KS8995_REGS_SIZE, + .addr_width = 8, + .addr_shift = 0, }, [ksz8864] = { .name = "KSZ8864RMN", .family_id = FAMILY_KS8995, .chip_id = KSZ8864_CHIP_ID, .regs_size = KSZ8864_REGS_SIZE, + .addr_width = 8, + .addr_shift = 0, }, }; @@ -153,20 +159,44 @@ static inline u8 get_chip_rev(u8 val) return (val >> ID1_REVISION_S) & ID1_REVISION_M; } +/* create_spi_cmd - create a chip specific SPI command header + * @ks: pointer to switch instance + * @cmd: SPI command for switch + * @address: register address for command + * + * Different chip families use different bit pattern to address the switches + * registers: + * + * KS8995: 8bit command + 8bit address + * KSZ8795: 3bit command + 12bit address + 1bit TR (?) + */ +static inline __be16 create_spi_cmd(struct ks8995_switch *ks, int cmd, + unsigned address) +{ + u16 result = cmd; + + /* make room for address (incl. address shift) */ + result <<= ks->chip->addr_width + ks->chip->addr_shift; + /* add address */ + result |= address << ks->chip->addr_shift; + /* SPI protocol needs big endian */ + return cpu_to_be16(result); +} /* ------------------------------------------------------------------------ */ static int ks8995_read(struct ks8995_switch *ks, char *buf, unsigned offset, size_t count) { - u8 cmd[2]; + __be16 cmd; struct spi_transfer t[2]; struct spi_message m; int err; + cmd = create_spi_cmd(ks, KS8995_CMD_READ, offset); spi_message_init(&m); memset(&t, 0, sizeof(t)); - t[0].tx_buf = cmd; + t[0].tx_buf = &cmd; t[0].len = sizeof(cmd); spi_message_add_tail(&t[0], &m); @@ -174,9 +204,6 @@ static int ks8995_read(struct ks8995_switch *ks, char *buf, t[1].len = count; spi_message_add_tail(&t[1], &m); - cmd[0] = KS8995_CMD_READ; - cmd[1] = offset; - mutex_lock(&ks->lock); err = spi_sync(ks->spi, &m); mutex_unlock(&ks->lock); @@ -184,20 +211,20 @@ static int ks8995_read(struct ks8995_switch *ks, char *buf, return err ? err : count; } - static int ks8995_write(struct ks8995_switch *ks, char *buf, unsigned offset, size_t count) { - u8 cmd[2]; + __be16 cmd; struct spi_transfer t[2]; struct spi_message m; int err; + cmd = create_spi_cmd(ks, KS8995_CMD_WRITE, offset); spi_message_init(&m); memset(&t, 0, sizeof(t)); - t[0].tx_buf = cmd; + t[0].tx_buf = &cmd; t[0].len = sizeof(cmd); spi_message_add_tail(&t[0], &m); @@ -205,9 +232,6 @@ static int ks8995_write(struct ks8995_switch *ks, char *buf, t[1].len = count; spi_message_add_tail(&t[1], &m); - cmd[0] = KS8995_CMD_WRITE; - cmd[1] = offset; - mutex_lock(&ks->lock); err = spi_sync(ks->spi, &m); mutex_unlock(&ks->lock); -- cgit From c0e6cb1fed5a7390ac84396f6f43e70fc2034ac6 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Tue, 9 Feb 2016 20:47:17 +0100 Subject: net: phy: spi_ks8995: add support for MICREL KSZ8795CLX Add support for MICREL KSZ8795CLX Integrated 5-Port, 10-/100-Managed Ethernet Switch with Gigabit GMII/RGMII and MII/RMII interfaces. Signed-off-by: Helmut Buchsbaum Signed-off-by: David S. Miller --- drivers/net/phy/spi_ks8995.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index 9dcc5b4fd9d1..5e7340f6b37c 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -77,6 +77,7 @@ #define KS8995_REGS_SIZE 0x80 #define KSZ8864_REGS_SIZE 0x100 +#define KSZ8795_REGS_SIZE 0x100 #define ID1_CHIPID_M 0xf #define ID1_CHIPID_S 4 @@ -85,9 +86,11 @@ #define ID1_START_SW 1 /* start the switch */ #define FAMILY_KS8995 0x95 +#define FAMILY_KSZ8795 0x87 #define CHIPID_M 0 #define KS8995_CHIP_ID 0x00 #define KSZ8864_CHIP_ID 0x01 +#define KSZ8795_CHIP_ID 0x09 #define KS8995_CMD_WRITE 0x02U #define KS8995_CMD_READ 0x03U @@ -97,6 +100,7 @@ enum ks8995_chip_variant { ks8995, ksz8864, + ksz8795, max_variant }; @@ -126,6 +130,14 @@ static const struct ks8995_chip_params ks8995_chip[] = { .addr_width = 8, .addr_shift = 0, }, + [ksz8795] = { + .name = "KSZ8795CLX", + .family_id = FAMILY_KSZ8795, + .chip_id = KSZ8795_CHIP_ID, + .regs_size = KSZ8795_REGS_SIZE, + .addr_width = 12, + .addr_shift = 1, + }, }; struct ks8995_pdata { @@ -145,6 +157,7 @@ struct ks8995_switch { static const struct spi_device_id ks8995_id[] = { {"ks8995", ks8995}, {"ksz8864", ksz8864}, + {"ksz8795", ksz8795}, { } }; MODULE_DEVICE_TABLE(spi, ks8995_id); @@ -358,6 +371,22 @@ static int ks8995_get_revision(struct ks8995_switch *ks) err = -ENODEV; } break; + case FAMILY_KSZ8795: + /* try reading chip id at CHIP ID1 */ + err = ks8995_read_reg(ks, KS8995_REG_ID1, &id1); + if (err) { + err = -EIO; + goto err_out; + } + + if (get_chip_id(id1) == ks->chip->chip_id) { + ks->revision_id = get_chip_rev(id1); + } else { + dev_err(&ks->spi->dev, "unsupported chip id for KSZ8795 family: 0x%02x\n", + id1); + err = -ENODEV; + } + break; default: dev_err(&ks->spi->dev, "unsupported family id: 0x%02x\n", id0); err = -ENODEV; -- cgit From 7e406d124c7935ee0238b957ea7e563dc1710f29 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Tue, 9 Feb 2016 20:47:18 +0100 Subject: dt-bindings: net: ks8995: add bindings documentation for ks8995 Signed-off-by: Helmut Buchsbaum Signed-off-by: David S. Miller --- .../devicetree/bindings/net/micrel-ks8995.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/micrel-ks8995.txt diff --git a/Documentation/devicetree/bindings/net/micrel-ks8995.txt b/Documentation/devicetree/bindings/net/micrel-ks8995.txt new file mode 100644 index 000000000000..281bc2498d12 --- /dev/null +++ b/Documentation/devicetree/bindings/net/micrel-ks8995.txt @@ -0,0 +1,20 @@ +Micrel KS8995 SPI controlled Ethernet Switch families + +Required properties (according to spi-bus.txt): +- compatible: either "micrel,ks8995", "micrel,ksz8864" or "micrel,ksz8795" + +Optional properties: +- reset-gpios : phandle of gpio that will be used to reset chip during probe + +Example: + +spi-master { + ... + switch@0 { + compatible = "micrel,ksz8795"; + + reg = <0>; + spi-max-frequency = <50000000>; + reset-gpios = <&gpio0 46 GPIO_ACTIVE_LOW>; + }; +}; -- cgit From 8431706b4d1e684efee4b9e91e655f1161e883a8 Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 11 Feb 2016 12:42:26 +0100 Subject: be2net: don't report EVB for older chipsets when SR-IOV is disabled The EVB (virtual bridge) functionality should be disabled on older BE3 and Lancer chips if SR-IOV is disabled in the NIC's BIOS. This setting is identified by the zero value of total VFs reported by the card. The GET_HSW_CONFIG command cannot be used as it is not supported by these older chipset's FW. v2: added the comment Cc: Sathya Perla Cc: Ajit Khaparde Cc: Padmanabh Ratnakar Cc: Sriharsha Basavapatna Cc: Somnath Kotur Signed-off-by: Ivan Vecera Acked-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 4ecd8c2beaf5..88f427cb76c3 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4617,6 +4617,9 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, /* BE and Lancer chips support VEB mode only */ if (BEx_chip(adapter) || lancer_chip(adapter)) { + /* VEB is disabled in non-SR-IOV profiles on BE3/Lancer */ + if (!pci_sriov_get_totalvfs(adapter->pdev)) + return 0; hsw_mode = PORT_FWD_TYPE_VEB; } else { status = be_cmd_get_hsw_config(adapter, NULL, 0, -- cgit From 2f67864b6d5b653ee4518ab0d20549283b49a527 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sun, 7 Feb 2016 11:47:17 -0600 Subject: net: phy: dp83848: Add macro for dp83848 compatible devices Add a helper macro for defining dp83848 compatible phy devices. Update copyright info. Signed-off-by: Andrew F. Davis Signed-off-by: David S. Miller --- drivers/net/phy/dp83848.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index 5e14e629c597..4e78f541b8c4 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -1,7 +1,7 @@ /* * Driver for the Texas Instruments DP83848 PHY * - * Copyright (C) 2015 Texas Instruments Inc. + * 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 as published by @@ -70,25 +70,28 @@ static struct mdio_device_id __maybe_unused dp83848_tbl[] = { }; MODULE_DEVICE_TABLE(mdio, dp83848_tbl); -static struct phy_driver dp83848_driver[] = { - { - .phy_id = DP83848_PHY_ID, - .phy_id_mask = 0xfffffff0, - .name = "TI DP83848", - .features = PHY_BASIC_FEATURES, - .flags = PHY_HAS_INTERRUPT, - - .soft_reset = genphy_soft_reset, - .config_init = genphy_config_init, - .suspend = genphy_suspend, - .resume = genphy_resume, - .config_aneg = genphy_config_aneg, - .read_status = genphy_read_status, +#define DP83848_PHY_DRIVER(_id, _name) \ + { \ + .phy_id = _id, \ + .phy_id_mask = 0xfffffff0, \ + .name = _name, \ + .features = PHY_BASIC_FEATURES, \ + .flags = PHY_HAS_INTERRUPT, \ + \ + .soft_reset = genphy_soft_reset, \ + .config_init = genphy_config_init, \ + .suspend = genphy_suspend, \ + .resume = genphy_resume, \ + .config_aneg = genphy_config_aneg, \ + .read_status = genphy_read_status, \ + \ + /* IRQ related */ \ + .ack_interrupt = dp83848_ack_interrupt, \ + .config_intr = dp83848_config_intr, \ + } - /* IRQ related */ - .ack_interrupt = dp83848_ack_interrupt, - .config_intr = dp83848_config_intr, - }, +static struct phy_driver dp83848_driver[] = { + DP83848_PHY_DRIVER(DP83848_PHY_ID, "TI DP83848 10/100 Mbps PHY"), }; module_phy_driver(dp83848_driver); -- cgit From 68336293462c92ba420528dd293d54ee879b6e15 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sun, 7 Feb 2016 11:47:18 -0600 Subject: net: phy: dp83848: Add PHY ID for TI version of DP83848C After acquiring National Semiconductor, TI appears to have changed the Vendor Model Number for the DP83848C PHYs, add this new ID to supported IDs. Signed-off-by: Andrew F. Davis Signed-off-by: David S. Miller --- drivers/net/phy/dp83848.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index 4e78f541b8c4..d4686d5f6e03 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -16,7 +16,8 @@ #include #include -#define DP83848_PHY_ID 0x20005c90 +#define TI_DP83848C_PHY_ID 0x20005ca0 +#define NS_DP83848C_PHY_ID 0x20005c90 /* Registers */ #define DP83848_MICR 0x11 @@ -65,7 +66,8 @@ static int dp83848_config_intr(struct phy_device *phydev) } static struct mdio_device_id __maybe_unused dp83848_tbl[] = { - { DP83848_PHY_ID, 0xfffffff0 }, + { TI_DP83848C_PHY_ID, 0xfffffff0 }, + { NS_DP83848C_PHY_ID, 0xfffffff0 }, { } }; MODULE_DEVICE_TABLE(mdio, dp83848_tbl); @@ -91,7 +93,8 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl); } static struct phy_driver dp83848_driver[] = { - DP83848_PHY_DRIVER(DP83848_PHY_ID, "TI DP83848 10/100 Mbps PHY"), + DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"), + DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"), }; module_phy_driver(dp83848_driver); -- cgit From cf13be5afd30363e5e6e1232e004bae99ee3c623 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sun, 7 Feb 2016 11:47:19 -0600 Subject: net: phy: dp83848: Reorganize code for readability and safety Reorganize code by moving the desired interrupt mask definition out of function. Also rearrange the enable/disable interrupt function to prevent accidental over-writing of values in registers. Signed-off-by: Andrew F. Davis Signed-off-by: David S. Miller --- drivers/net/phy/dp83848.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index d4686d5f6e03..20d3b9dae444 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -37,6 +37,12 @@ #define DP83848_MISR_ED_INT_EN BIT(6) /* Energy detect */ #define DP83848_MISR_LQM_INT_EN BIT(7) /* Link Quality Monitor */ +#define DP83848_INT_EN_MASK \ + (DP83848_MISR_ANC_INT_EN | \ + DP83848_MISR_DUP_INT_EN | \ + DP83848_MISR_SPD_INT_EN | \ + DP83848_MISR_LINK_INT_EN) + static int dp83848_ack_interrupt(struct phy_device *phydev) { int err = phy_read(phydev, DP83848_MISR); @@ -46,23 +52,24 @@ static int dp83848_ack_interrupt(struct phy_device *phydev) static int dp83848_config_intr(struct phy_device *phydev) { - int err; + int control, ret; + + control = phy_read(phydev, DP83848_MICR); + if (control < 0) + return control; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { - err = phy_write(phydev, DP83848_MICR, - DP83848_MICR_INT_OE | - DP83848_MICR_INTEN); - if (err < 0) - return err; - - return phy_write(phydev, DP83848_MISR, - DP83848_MISR_ANC_INT_EN | - DP83848_MISR_DUP_INT_EN | - DP83848_MISR_SPD_INT_EN | - DP83848_MISR_LINK_INT_EN); + control |= DP83848_MICR_INT_OE; + control |= DP83848_MICR_INTEN; + + ret = phy_write(phydev, DP83848_MISR, DP83848_INT_EN_MASK); + if (ret < 0) + return ret; + } else { + control &= ~DP83848_MICR_INTEN; } - return phy_write(phydev, DP83848_MICR, 0x0); + return phy_write(phydev, DP83848_MICR, control); } static struct mdio_device_id __maybe_unused dp83848_tbl[] = { -- cgit From d1782f7b0cb853ec0a9b7b3e5f8a3252ed8a054e Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sun, 7 Feb 2016 11:47:20 -0600 Subject: net: phy: dp83848: Add support for TI TLK10x Ethernet PHYs The TI TLK10x Ethernet PHYs are similar in the interrupt relevant registers and so are compatible with the DP83848x devices already supported. Signed-off-by: Andrew F. Davis Signed-off-by: David S. Miller --- drivers/net/phy/dp83848.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index 20d3b9dae444..f897989d1bf7 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -18,6 +18,7 @@ #define TI_DP83848C_PHY_ID 0x20005ca0 #define NS_DP83848C_PHY_ID 0x20005c90 +#define TLK10X_PHY_ID 0x2000a210 /* Registers */ #define DP83848_MICR 0x11 @@ -75,6 +76,7 @@ static int dp83848_config_intr(struct phy_device *phydev) static struct mdio_device_id __maybe_unused dp83848_tbl[] = { { TI_DP83848C_PHY_ID, 0xfffffff0 }, { NS_DP83848C_PHY_ID, 0xfffffff0 }, + { TLK10X_PHY_ID, 0xfffffff0 }, { } }; MODULE_DEVICE_TABLE(mdio, dp83848_tbl); @@ -102,6 +104,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl); static struct phy_driver dp83848_driver[] = { DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"), DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"), + DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"), }; module_phy_driver(dp83848_driver); -- cgit From 5fed039351dd54b295cba7c9afe34ede99d9b2e9 Mon Sep 17 00:00:00 2001 From: "Andrew F. Davis" Date: Sun, 7 Feb 2016 11:47:21 -0600 Subject: net: phy: dp83848: Add comments for register definitions Signed-off-by: Andrew F. Davis Signed-off-by: David S. Miller --- drivers/net/phy/dp83848.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c index f897989d1bf7..556904f572d6 100644 --- a/drivers/net/phy/dp83848.c +++ b/drivers/net/phy/dp83848.c @@ -21,8 +21,8 @@ #define TLK10X_PHY_ID 0x2000a210 /* Registers */ -#define DP83848_MICR 0x11 -#define DP83848_MISR 0x12 +#define DP83848_MICR 0x11 /* MII Interrupt Control Register */ +#define DP83848_MISR 0x12 /* MII Interrupt Status Register */ /* MICR Register Fields */ #define DP83848_MICR_INT_OE BIT(0) /* Interrupt Output Enable */ -- cgit From e02564ee334a7ae46b71fc18576391cb9455433e Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Sun, 7 Feb 2016 21:52:23 +0100 Subject: ethtool: make validate_speed accept all speeds between 0 and INT_MAX Devices these days can have any speed and as was recently pointed out any speed from 0 to INT_MAX is valid so adjust speed validation to accept such values. Signed-off-by: Nikolay Aleksandrov Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index 4345f80a2e33..190aea0faaf4 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -1377,24 +1377,7 @@ enum ethtool_sfeatures_retval_bits { static inline int ethtool_validate_speed(__u32 speed) { - switch (speed) { - case SPEED_10: - case SPEED_100: - case SPEED_1000: - case SPEED_2500: - case SPEED_5000: - case SPEED_10000: - case SPEED_20000: - case SPEED_25000: - case SPEED_40000: - case SPEED_50000: - case SPEED_56000: - case SPEED_100000: - case SPEED_UNKNOWN: - return 1; - } - - return 0; + return speed <= INT_MAX || speed == SPEED_UNKNOWN; } /* Duplex, half or full. */ -- cgit From 0cf3ace9e7cb47e3173561a8fb2601a12d8f75d2 Mon Sep 17 00:00:00 2001 From: Nikolay Aleksandrov Date: Sun, 7 Feb 2016 21:52:24 +0100 Subject: virtio_net: validate ethtool port setting and explain the user validation We should validate the port setting that we got from the user and check if it's what we've set it to (PORT_OTHER), also add explanation that ignoring advertising is good as long as we don't have autonegotiation. Signed-off-by: Nikolay Aleksandrov Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c9fd52a8e6ec..fb0eae42bf39 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1386,11 +1386,13 @@ static bool virtnet_validate_ethtool_cmd(const struct ethtool_cmd *cmd) struct ethtool_cmd diff1 = *cmd; struct ethtool_cmd diff2 = {}; - /* advertising and cmd are usually set, ignore port because we set it */ + /* cmd is always set so we need to clear it, validate the port type + * and also without autonegotiation we can ignore advertising + */ ethtool_cmd_speed_set(&diff1, 0); + diff2.port = PORT_OTHER; diff1.advertising = 0; diff1.duplex = 0; - diff1.port = 0; diff1.cmd = 0; return !memcmp(&diff1, &diff2, sizeof(diff1)); -- cgit From 795bb1c00dd338aa0d12f9a7f1f4776fb3160416 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 8 Feb 2016 13:14:59 +0100 Subject: net: bulk free infrastructure for NAPI context, use napi_consume_skb Discovered that network stack were hitting the kmem_cache/SLUB slowpath when freeing SKBs. Doing bulk free with kmem_cache_free_bulk can speedup this slowpath. NAPI context is a bit special, lets take advantage of that for bulk free'ing SKBs. In NAPI context we are running in softirq, which gives us certain protection. A softirq can run on several CPUs at once. BUT the important part is a softirq will never preempt another softirq running on the same CPU. This gives us the opportunity to access per-cpu variables in softirq context. Extend napi_alloc_cache (before only contained page_frag_cache) to be a struct with a small array based stack for holding SKBs. Introduce a SKB defer and flush API for accessing this. Introduce napi_consume_skb() as replacement for e.g. dev_consume_skb_any() when running in NAPI context. A small trick to handle/detect if we are called from netpoll is to see if budget is 0. In that case, we need to invoke dev_consume_skb_irq(). Joint work with Alexander Duyck. Signed-off-by: Jesper Dangaard Brouer Signed-off-by: Alexander Duyck Signed-off-by: David S. Miller --- include/linux/skbuff.h | 3 ++ net/core/dev.c | 1 + net/core/skbuff.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index a8fc2220e8ce..b56c0103fa15 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2404,6 +2404,9 @@ static inline struct sk_buff *napi_alloc_skb(struct napi_struct *napi, { return __napi_alloc_skb(napi, length, GFP_ATOMIC); } +void napi_consume_skb(struct sk_buff *skb, int budget); + +void __kfree_skb_flush(void); /** * __dev_alloc_pages - allocate page for network Rx diff --git a/net/core/dev.c b/net/core/dev.c index f1284835b8c9..9b2c7a999e71 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5155,6 +5155,7 @@ static void net_rx_action(struct softirq_action *h) } } + __kfree_skb_flush(); local_irq_disable(); list_splice_tail_init(&sd->poll_list, &list); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b0cce744e2a0..b64187b87773 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -347,8 +347,16 @@ struct sk_buff *build_skb(void *data, unsigned int frag_size) } EXPORT_SYMBOL(build_skb); +#define NAPI_SKB_CACHE_SIZE 64 + +struct napi_alloc_cache { + struct page_frag_cache page; + size_t skb_count; + void *skb_cache[NAPI_SKB_CACHE_SIZE]; +}; + static DEFINE_PER_CPU(struct page_frag_cache, netdev_alloc_cache); -static DEFINE_PER_CPU(struct page_frag_cache, napi_alloc_cache); +static DEFINE_PER_CPU(struct napi_alloc_cache, napi_alloc_cache); static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { @@ -378,9 +386,9 @@ EXPORT_SYMBOL(netdev_alloc_frag); static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { - struct page_frag_cache *nc = this_cpu_ptr(&napi_alloc_cache); + struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); - return __alloc_page_frag(nc, fragsz, gfp_mask); + return __alloc_page_frag(&nc->page, fragsz, gfp_mask); } void *napi_alloc_frag(unsigned int fragsz) @@ -474,7 +482,7 @@ EXPORT_SYMBOL(__netdev_alloc_skb); struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, gfp_t gfp_mask) { - struct page_frag_cache *nc = this_cpu_ptr(&napi_alloc_cache); + struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); struct sk_buff *skb; void *data; @@ -494,7 +502,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, if (sk_memalloc_socks()) gfp_mask |= __GFP_MEMALLOC; - data = __alloc_page_frag(nc, len, gfp_mask); + data = __alloc_page_frag(&nc->page, len, gfp_mask); if (unlikely(!data)) return NULL; @@ -505,7 +513,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, } /* use OR instead of assignment to avoid clearing of bits in mask */ - if (nc->pfmemalloc) + if (nc->page.pfmemalloc) skb->pfmemalloc = 1; skb->head_frag = 1; @@ -747,6 +755,69 @@ void consume_skb(struct sk_buff *skb) } EXPORT_SYMBOL(consume_skb); +void __kfree_skb_flush(void) +{ + struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); + + /* flush skb_cache if containing objects */ + if (nc->skb_count) { + kmem_cache_free_bulk(skbuff_head_cache, nc->skb_count, + nc->skb_cache); + nc->skb_count = 0; + } +} + +static void __kfree_skb_defer(struct sk_buff *skb) +{ + struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); + + /* drop skb->head and call any destructors for packet */ + skb_release_all(skb); + + /* record skb to CPU local list */ + nc->skb_cache[nc->skb_count++] = skb; + +#ifdef CONFIG_SLUB + /* SLUB writes into objects when freeing */ + prefetchw(skb); +#endif + + /* flush skb_cache if it is filled */ + if (unlikely(nc->skb_count == NAPI_SKB_CACHE_SIZE)) { + kmem_cache_free_bulk(skbuff_head_cache, NAPI_SKB_CACHE_SIZE, + nc->skb_cache); + nc->skb_count = 0; + } +} + +void napi_consume_skb(struct sk_buff *skb, int budget) +{ + if (unlikely(!skb)) + return; + + /* if budget is 0 assume netpoll w/ IRQs disabled */ + if (unlikely(!budget)) { + dev_consume_skb_irq(skb); + return; + } + + if (likely(atomic_read(&skb->users) == 1)) + smp_rmb(); + else if (likely(!atomic_dec_and_test(&skb->users))) + return; + /* if reaching here SKB is ready to free */ + trace_consume_skb(skb); + + /* if SKB is a clone, don't handle this case */ + if (unlikely(skb->fclone != SKB_FCLONE_UNAVAILABLE)) { + __kfree_skb(skb); + return; + } + + __kfree_skb_defer(skb); +} +EXPORT_SYMBOL(napi_consume_skb); + /* Make sure a field is enclosed inside headers_start/headers_end section */ #define CHECK_SKB_FIELD(field) \ BUILD_BUG_ON(offsetof(struct sk_buff, field) < \ -- cgit From 15fad714be86eab13e7568fecaf475b2a9730d3e Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 8 Feb 2016 13:15:04 +0100 Subject: net: bulk free SKBs that were delay free'ed due to IRQ context The network stack defers SKBs free, in-case free happens in IRQ or when IRQs are disabled. This happens in __dev_kfree_skb_irq() that writes SKBs that were free'ed during IRQ to the softirq completion queue (softnet_data.completion_queue). These SKBs are naturally delayed, and cleaned up during NET_TX_SOFTIRQ in function net_tx_action(). Take advantage of this a use the skb defer and flush API, as we are already in softirq context. For modern drivers this rarely happens. Although most drivers do call dev_kfree_skb_any(), which detects the situation and calls __dev_kfree_skb_irq() when needed. This due to netpoll can call from IRQ context. Signed-off-by: Alexander Duyck Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- include/linux/skbuff.h | 1 + net/core/dev.c | 8 +++++++- net/core/skbuff.c | 8 ++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b56c0103fa15..6ec86f1a2ed9 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2407,6 +2407,7 @@ static inline struct sk_buff *napi_alloc_skb(struct napi_struct *napi, void napi_consume_skb(struct sk_buff *skb, int budget); void __kfree_skb_flush(void); +void __kfree_skb_defer(struct sk_buff *skb); /** * __dev_alloc_pages - allocate page for network Rx diff --git a/net/core/dev.c b/net/core/dev.c index 9b2c7a999e71..3f4071a84a03 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3829,8 +3829,14 @@ static void net_tx_action(struct softirq_action *h) trace_consume_skb(skb); else trace_kfree_skb(skb, net_tx_action); - __kfree_skb(skb); + + if (skb->fclone != SKB_FCLONE_UNAVAILABLE) + __kfree_skb(skb); + else + __kfree_skb_defer(skb); } + + __kfree_skb_flush(); } if (sd->output_queue) { diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b64187b87773..a5bd067ec1a3 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -767,7 +767,7 @@ void __kfree_skb_flush(void) } } -static void __kfree_skb_defer(struct sk_buff *skb) +static inline void _kfree_skb_defer(struct sk_buff *skb) { struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); @@ -789,6 +789,10 @@ static void __kfree_skb_defer(struct sk_buff *skb) nc->skb_count = 0; } } +void __kfree_skb_defer(struct sk_buff *skb) +{ + _kfree_skb_defer(skb); +} void napi_consume_skb(struct sk_buff *skb, int budget) { @@ -814,7 +818,7 @@ void napi_consume_skb(struct sk_buff *skb, int budget) return; } - __kfree_skb_defer(skb); + _kfree_skb_defer(skb); } EXPORT_SYMBOL(napi_consume_skb); -- cgit From a3a8749d34d8a5ac071c7ead792bd21ffe328aa0 Mon Sep 17 00:00:00 2001 From: Jesper Dangaard Brouer Date: Mon, 8 Feb 2016 13:15:09 +0100 Subject: ixgbe: bulk free SKBs during TX completion cleanup cycle There is an opportunity to bulk free SKBs during reclaiming of resources after DMA transmit completes in ixgbe_clean_tx_irq. Thus, bulk freeing at this point does not introduce any added latency. Simply use napi_consume_skb() which were recently introduced. The napi_budget parameter is needed by napi_consume_skb() to detect if it is called from netpoll. Benchmarking IPv4-forwarding, on CPU i7-4790K @4.2GHz (no turbo boost) Single CPU/flow numbers: before: 1982144 pps -> after : 2064446 pps Improvement: +82302 pps, -20 nanosec, +4.1% (SLUB and GCC version 5.1.1 20150618 (Red Hat 5.1.1-4)) Joint work with Alexander Duyck. Signed-off-by: Alexander Duyck Signed-off-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c4003a88bbf6..0c701b8438b6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1089,7 +1089,7 @@ static void ixgbe_tx_timeout_reset(struct ixgbe_adapter *adapter) * @tx_ring: tx ring to clean **/ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, - struct ixgbe_ring *tx_ring) + struct ixgbe_ring *tx_ring, int napi_budget) { struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_tx_buffer *tx_buffer; @@ -1127,7 +1127,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_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, @@ -2784,7 +2784,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget) #endif ixgbe_for_each_ring(ring, q_vector->tx) - clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring); + clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring, budget); /* Exit if we are called by netpoll or busy polling is active */ if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector)) -- cgit From 491a0b08d38e7f0961a1850d43d0dea02f918d66 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Tue, 26 Jan 2016 15:08:35 -0800 Subject: Smack: Remove pointless hooks Prior to the 4.2 kernel there no no harm in providing a security module hook that does nothing, as the default hook would get called if the module did not supply one. With the list based infrastructure an empty hook adds overhead. This patch removes the three Smack hooks that don't actually do anything. Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 2d6e9bdea398..2775d658b767 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1545,12 +1545,8 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid) * File Hooks */ -/** - * smack_file_permission - Smack check on file operations - * @file: unused - * @mask: unused - * - * Returns 0 +/* + * There is no smack_file_permission hook * * Should access checks be done on each read or write? * UNICOS and SELinux say yes. @@ -1559,10 +1555,6 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid) * I'll say no for now. Smack does not do the frequent * label changing that SELinux does. */ -static int smack_file_permission(struct file *file, int mask) -{ - return 0; -} /** * smack_file_alloc_security - assign a file security blob @@ -4503,16 +4495,10 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, return 0; } -/** - * smack_audit_rule_free - free smack rule representation - * @vrule: rule to be freed. - * +/* + * There is no need for a smack_audit_rule_free hook. * No memory was allocated. */ -static void smack_audit_rule_free(void *vrule) -{ - /* No-op */ -} #endif /* CONFIG_AUDIT */ @@ -4563,16 +4549,11 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) return 0; } -/** - * smack_release_secctx - don't do anything. - * @secdata: unused - * @seclen: unused - * - * Exists to make sure nothing gets done, and properly +/* + * There used to be a smack_release_secctx hook + * that did nothing back when hooks were in a vector. + * Now that there's a list such a hook adds cost. */ -static void smack_release_secctx(char *secdata, u32 seclen) -{ -} static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) { @@ -4631,7 +4612,6 @@ static struct security_hook_list smack_hooks[] = { LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity), LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), - LSM_HOOK_INIT(file_permission, smack_file_permission), LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), LSM_HOOK_INIT(file_free_security, smack_file_free_security), LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), @@ -4726,13 +4706,11 @@ static struct security_hook_list smack_hooks[] = { LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known), LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match), - LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free), #endif /* CONFIG_AUDIT */ LSM_HOOK_INIT(ismaclabel, smack_ismaclabel), LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx), LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid), - LSM_HOOK_INIT(release_secctx, smack_release_secctx), LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx), LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx), LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx), -- cgit From 9efd9e6956adf479eb85beb74bb975f702dc01a9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Feb 2016 14:27:42 +0100 Subject: gpio: remember to finally free gpio_device When the device core reference count for the device goes to 0 and it calls .release() we free resources and so can also finally free up the GPIO state container, struct gpio_device. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 70e0fff0a8a7..36f8be3f910b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -405,6 +405,7 @@ static void gpiodevice_release(struct device *dev) cdev_del(&gdev->chrdev); list_del(&gdev->list); ida_simple_remove(&gpio_ida, gdev->id); + kfree(gdev); } /** -- cgit From afbc4f312b5e6e87fcd383eb6764e09f1324c78e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Feb 2016 13:21:06 +0100 Subject: gpio: move sysfs mock device to the gpio_device Since gpio_device is the struct that survives if the backing gpio_chip is removed, move the sysfs mock device to this state container so it becomes part of the dangling state of the GPIO device on removal. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-sysfs.c | 23 ++++++++++++----------- drivers/gpio/gpiolib.c | 4 ++-- drivers/gpio/gpiolib.h | 11 +++++++---- include/linux/gpio/driver.h | 2 -- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 28d3bf2328aa..94ba4bb8b4f8 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -572,7 +572,7 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) mutex_lock(&sysfs_lock); /* check if chip is being removed */ - if (!chip || !chip->cdev) { + if (!chip || !gdev->mockdev) { status = -ENODEV; goto err_unlock; } @@ -718,9 +718,10 @@ err_unlock: } EXPORT_SYMBOL_GPL(gpiod_unexport); -int gpiochip_sysfs_register(struct gpio_chip *chip) +int gpiochip_sysfs_register(struct gpio_device *gdev) { struct device *dev; + struct gpio_chip *chip = gdev->chip; /* * Many systems add gpio chips for SOC support very early, @@ -732,7 +733,7 @@ int gpiochip_sysfs_register(struct gpio_chip *chip) return 0; /* use chip->base for the ID; it's already known to be unique */ - dev = device_create_with_groups(&gpio_class, chip->parent, + dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), chip, gpiochip_groups, "gpiochip%d", chip->base); @@ -740,25 +741,26 @@ int gpiochip_sysfs_register(struct gpio_chip *chip) return PTR_ERR(dev); mutex_lock(&sysfs_lock); - chip->cdev = dev; + gdev->mockdev = dev; mutex_unlock(&sysfs_lock); return 0; } -void gpiochip_sysfs_unregister(struct gpio_chip *chip) +void gpiochip_sysfs_unregister(struct gpio_device *gdev) { struct gpio_desc *desc; + struct gpio_chip *chip = gdev->chip; unsigned int i; - if (!chip->cdev) + if (!gdev->mockdev) return; - device_unregister(chip->cdev); + device_unregister(gdev->mockdev); /* prevent further gpiod exports */ mutex_lock(&sysfs_lock); - chip->cdev = NULL; + gdev->mockdev = NULL; mutex_unlock(&sysfs_lock); /* unregister gpiod class devices owned by sysfs */ @@ -787,7 +789,7 @@ static int __init gpiolib_sysfs_init(void) */ spin_lock_irqsave(&gpio_lock, flags); list_for_each_entry(gdev, &gpio_devices, list) { - if (gdev->chip->cdev) + if (gdev->mockdev) continue; /* @@ -800,12 +802,11 @@ static int __init gpiolib_sysfs_init(void) * gpio_lock prevents us from doing this. */ spin_unlock_irqrestore(&gpio_lock, flags); - status = gpiochip_sysfs_register(gdev->chip); + status = gpiochip_sysfs_register(gdev); spin_lock_irqsave(&gpio_lock, flags); } spin_unlock_irqrestore(&gpio_lock, flags); - return status; } postcore_initcall(gpiolib_sysfs_init); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 36f8be3f910b..5763290f777c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -558,7 +558,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) if (status) goto err_remove_chardev; - status = gpiochip_sysfs_register(chip); + status = gpiochip_sysfs_register(gdev); if (status) goto err_remove_device; @@ -615,7 +615,7 @@ void gpiochip_remove(struct gpio_chip *chip) gdev->chip = NULL; /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ - gpiochip_sysfs_unregister(chip); + gpiochip_sysfs_unregister(gdev); gpiochip_irqchip_remove(chip); acpi_gpiochip_remove(chip); gpiochip_remove_pin_ranges(chip); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 1524ba0ca99d..c5a5b57463c7 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -27,6 +27,8 @@ struct acpi_device; * @id: numerical ID number for the GPIO chip * @dev: the GPIO device struct * @chrdev: character device for the GPIO device + * @mockdev: class device used by the deprecated sysfs interface (may be + * NULL) * @owner: helps prevent removal of modules exporting active GPIOs * @chip: pointer to the corresponding gpiochip, holding static * data for this device @@ -41,6 +43,7 @@ struct gpio_device { int id; struct device dev; struct cdev chrdev; + struct device *mockdev; struct module *owner; struct gpio_chip *chip; struct list_head list; @@ -190,17 +193,17 @@ static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc) #ifdef CONFIG_GPIO_SYSFS -int gpiochip_sysfs_register(struct gpio_chip *chip); -void gpiochip_sysfs_unregister(struct gpio_chip *chip); +int gpiochip_sysfs_register(struct gpio_device *gdev); +void gpiochip_sysfs_unregister(struct gpio_device *gdev); #else -static inline int gpiochip_sysfs_register(struct gpio_chip *chip) +static inline int gpiochip_sysfs_register(struct gpio_device *gdev) { return 0; } -static inline void gpiochip_sysfs_unregister(struct gpio_chip *chip) +static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev) { } diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index f3f1dbd43c9b..4db64ab534ef 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -24,7 +24,6 @@ struct gpio_device; * @label: for diagnostics * @gpiodev: the internal state holder, opaque struct * @parent: optional parent device providing the GPIOs - * @cdev: class device used by sysfs interface (may be NULL) * @owner: helps prevent removal of modules exporting active GPIOs * @data: per-instance data assigned by the driver * @request: optional hook for chip-specific activation, such as @@ -110,7 +109,6 @@ struct gpio_chip { const char *label; struct gpio_device *gpiodev; struct device *parent; - struct device *cdev; struct module *owner; void *data; -- cgit From 1c3cdb186172ee3be24005a7ff0e849bc17b67b8 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Feb 2016 13:51:59 +0100 Subject: gpio: move descriptors into gpio_device We need gpio_device to hold the descriptors so that they can be lifecycled with the struct gpio_device held from userspace. Move the descriptor array into gpio_device. Also rename it from "desc" (singularis) to "descs" (pluralis) to reflect the fact that it is an array. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-sysfs.c | 2 +- drivers/gpio/gpiolib.c | 53 ++++++++++++++++++-------------------------- drivers/gpio/gpiolib.h | 4 +++- include/linux/gpio/driver.h | 2 -- 4 files changed, 26 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 94ba4bb8b4f8..de65633471af 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -765,7 +765,7 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev) /* unregister gpiod class devices owned by sysfs */ for (i = 0; i < chip->ngpio; i++) { - desc = &chip->desc[i]; + desc = &chip->gpiodev->descs[i]; if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) gpiod_free(desc); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5763290f777c..f3fcd415a77b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -88,7 +88,7 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) if (gdev->chip->base <= gpio && gdev->chip->base + gdev->chip->ngpio > gpio) { spin_unlock_irqrestore(&gpio_lock, flags); - return &gdev->chip->desc[gpio - gdev->chip->base]; + return &gdev->descs[gpio - gdev->chip->base]; } } @@ -110,7 +110,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, if (hwnum >= chip->ngpio) return ERR_PTR(-EINVAL); - return &chip->desc[hwnum]; + return &chip->gpiodev->descs[hwnum]; } /** @@ -120,7 +120,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, */ int desc_to_gpio(const struct gpio_desc *desc) { - return desc->chip->base + (desc - &desc->chip->desc[0]); + return desc->chip->base + (desc - &desc->chip->gpiodev->descs[0]); } EXPORT_SYMBOL_GPL(desc_to_gpio); @@ -277,7 +277,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name) int i; for (i = 0; i != gdev->chip->ngpio; ++i) { - struct gpio_desc *gpio = &gdev->chip->desc[i]; + struct gpio_desc *gpio = &gdev->descs[i]; if (!gpio->name || !name) continue; @@ -320,7 +320,7 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) /* Then add all names to the GPIO descriptors */ for (i = 0; i != gc->ngpio; ++i) - gc->desc[i].name = gc->names[i]; + gc->gpiodev->descs[i].name = gc->names[i]; return 0; } @@ -431,7 +431,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) int status = 0; unsigned i; int base = chip->base; - struct gpio_desc *descs; struct gpio_device *gdev; /* @@ -470,9 +469,9 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) else gdev->owner = THIS_MODULE; - /* FIXME: devm_kcalloc() these and move to gpio_device */ - descs = kcalloc(chip->ngpio, sizeof(descs[0]), GFP_KERNEL); - if (!descs) { + gdev->descs = devm_kcalloc(&gdev->dev, chip->ngpio, + sizeof(gdev->descs[0]), GFP_KERNEL); + if (!gdev->descs) { status = -ENOMEM; goto err_free_gdev; } @@ -483,7 +482,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) if (chip->ngpio == 0) { chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); status = -EINVAL; - goto err_free_descs; + goto err_free_gdev; } spin_lock_irqsave(&gpio_lock, flags); @@ -493,7 +492,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) if (base < 0) { status = base; spin_unlock_irqrestore(&gpio_lock, flags); - goto err_free_descs; + goto err_free_gdev; } chip->base = base; } @@ -501,11 +500,11 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) status = gpiodev_add_to_list(gdev); if (status) { spin_unlock_irqrestore(&gpio_lock, flags); - goto err_free_descs; + goto err_free_gdev; } for (i = 0; i < chip->ngpio; i++) { - struct gpio_desc *desc = &descs[i]; + struct gpio_desc *desc = &gdev->descs[i]; /* REVISIT: maybe a pointer to gpio_device is better */ desc->chip = chip; @@ -518,7 +517,6 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) */ desc->flags = !chip->direction_input ? (1 << FLAG_IS_OUT) : 0; } - chip->desc = descs; spin_unlock_irqrestore(&gpio_lock, flags); @@ -583,9 +581,6 @@ err_remove_from_list: spin_lock_irqsave(&gpio_lock, flags); list_del(&gdev->list); spin_unlock_irqrestore(&gpio_lock, flags); - chip->desc = NULL; -err_free_descs: - kfree(descs); err_free_gdev: ida_simple_remove(&gpio_ida, gdev->id); kfree(gdev); @@ -608,7 +603,7 @@ void gpiochip_remove(struct gpio_chip *chip) struct gpio_device *gdev = chip->gpiodev; struct gpio_desc *desc; unsigned long flags; - unsigned id; + unsigned i; bool requested = false; /* Numb the device, cancelling all outstanding operations */ @@ -623,8 +618,8 @@ void gpiochip_remove(struct gpio_chip *chip) of_gpiochip_remove(chip); spin_lock_irqsave(&gpio_lock, flags); - for (id = 0; id < chip->ngpio; id++) { - desc = &chip->desc[id]; + for (i = 0; i < chip->ngpio; i++) { + desc = &gdev->descs[i]; desc->chip = NULL; if (test_bit(FLAG_REQUESTED, &desc->flags)) requested = true; @@ -635,10 +630,6 @@ void gpiochip_remove(struct gpio_chip *chip) dev_crit(&chip->gpiodev->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); - /* FIXME: need to be moved to gpio_device and held there */ - kfree(chip->desc); - chip->desc = NULL; - /* * The gpiochip side puts its use of the device to rest here: * if there are no userspace clients, the chardev and device will @@ -1250,7 +1241,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) if (offset >= chip->ngpio) return NULL; - desc = &chip->desc[offset]; + desc = &chip->gpiodev->descs[offset]; if (test_bit(FLAG_REQUESTED, &desc->flags) == 0) return NULL; @@ -1837,14 +1828,14 @@ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset) if (offset >= chip->ngpio) return -EINVAL; - if (test_bit(FLAG_IS_OUT, &chip->desc[offset].flags)) { + if (test_bit(FLAG_IS_OUT, &chip->gpiodev->descs[offset].flags)) { chip_err(chip, "%s: tried to flag a GPIO set as output for IRQ\n", __func__); return -EIO; } - set_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags); + set_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); return 0; } EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq); @@ -1862,7 +1853,7 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) if (offset >= chip->ngpio) return; - clear_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags); + clear_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); } EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq); @@ -2549,8 +2540,8 @@ static void gpiochip_free_hogs(struct gpio_chip *chip) int id; for (id = 0; id < chip->ngpio; id++) { - if (test_bit(FLAG_IS_HOGGED, &chip->desc[id].flags)) - gpiochip_free_own_desc(&chip->desc[id]); + if (test_bit(FLAG_IS_HOGGED, &chip->gpiodev->descs[id].flags)) + gpiochip_free_own_desc(&chip->gpiodev->descs[id]); } } @@ -2673,7 +2664,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) { unsigned i; unsigned gpio = chip->base; - struct gpio_desc *gdesc = &chip->desc[0]; + struct gpio_desc *gdesc = &chip->gpiodev->descs[0]; int is_out; int is_irq; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index c5a5b57463c7..39b8301c98b6 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -32,6 +32,7 @@ struct acpi_device; * @owner: helps prevent removal of modules exporting active GPIOs * @chip: pointer to the corresponding gpiochip, holding static * data for this device + * @descs: array of ngpio descriptors. * @list: links gpio_device:s together for traversal * * This state container holds most of the runtime variable data @@ -46,6 +47,7 @@ struct gpio_device { struct device *mockdev; struct module *owner; struct gpio_chip *chip; + struct gpio_desc *descs; struct list_head list; }; @@ -152,7 +154,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, */ static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc) { - return desc - &desc->chip->desc[0]; + return desc - &desc->chip->gpiodev->descs[0]; } /* With descriptor prefix */ diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 4db64ab534ef..bfc842c2fc57 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -52,7 +52,6 @@ struct gpio_device; * get rid of the static GPIO number space in the long run. * @ngpio: the number of GPIOs handled by this controller; the last GPIO * handled is (base + ngpio - 1). - * @desc: array of ngpio descriptors. Private. * @names: if set, must be an array of strings to use as alternative * names for the GPIOs in this chip. Any entry in the array * may be NULL if there is no alias for the GPIO, however the @@ -140,7 +139,6 @@ struct gpio_chip { struct gpio_chip *chip); int base; u16 ngpio; - struct gpio_desc *desc; const char *const *names; bool can_sleep; bool irq_not_threaded; -- cgit From 6cee3821e4e4bd6e6cdf0870b6c72d455460bd39 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 11 Feb 2016 20:16:45 +0100 Subject: gpio/pinctrl: sunxi: stop poking around in private vars This kind of hacks disturbs the refactoring of the gpiolib. The descriptor table belongs to the gpiolib, if we want to know something about something in it, use or define the proper accessor functions. Let's add this gpiochip_lins_is_irq() to do what the sunxi driver is trying at so we can privatize the descriptors properly. Cc: Maxime Ripard Cc: Chen-Yu Tsai Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 9 +++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 4 ++-- include/linux/gpio/driver.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f3fcd415a77b..ff8d55ad790c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1857,6 +1857,15 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset) } EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq); +bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset) +{ + if (offset >= chip->ngpio) + return false; + + return test_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags); +} +EXPORT_SYMBOL_GPL(gpiochip_line_is_irq); + /** * gpiod_get_raw_value_cansleep() - return a gpio's raw value * @desc: gpio whose value will be returned diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 7a2465f5e71e..3e95bfe66a06 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -457,8 +457,8 @@ static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset) struct sunxi_pinctrl *pctl = gpiochip_get_data(chip); u32 reg = sunxi_data_reg(offset); u8 index = sunxi_data_offset(offset); - u32 set_mux = pctl->desc->irq_read_needs_mux && - test_bit(FLAG_USED_AS_IRQ, &chip->desc[offset].flags); + bool set_mux = pctl->desc->irq_read_needs_mux && + gpiochip_line_is_irq(chip, offset); u32 val; if (set_mux) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index bfc842c2fc57..41c6144c473b 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -208,6 +208,7 @@ extern struct gpio_chip *gpiochip_find(void *data, /* lock/unlock as IRQ */ int gpiochip_lock_as_irq(struct gpio_chip *chip, unsigned int offset); void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); +bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); /* get driver data */ static inline void *gpiochip_get_data(struct gpio_chip *chip) -- cgit From fdeb8e1547cb9dd39d5d7223b33f3565cf86c28e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 10 Feb 2016 10:57:36 +0100 Subject: gpio: reflect base and ngpio into gpio_device Some information about the GPIO chip need to stay around also after the gpio_chip has been removed and only the gpio_device persist. The base and ngpio are such things, for example we don't want a new chip arriving to overlap the number space of a dangling gpio_device, and the chardev may still query the device for the number of lines etc. Note that the code that assigns base and insert gpio_device into the global list no longer check for a missing gpio_chip: we respect the number space allocated by any other gpio_device. As a consequence of the gdev being referenced directly from the gpio_desc, we need to verify it differently from all in-kernel API calls that fall through to direct queries to the gpio_chip vtable: we first check that desc is !NULL, then that desc->gdev is !NULL, then, if desc->gdev->chip is NULL, we *BAIL OUT* without any error, so as to manage the case where operations are requested on a device that is gone. These checks were non-uniform and partly missing in the past: so to simplify: create the macros VALIDATE_DESC() that will return -EINVAL if the desc or desc->gdev is missing and just 0 if the chip is gone, and conversely VALIDATE_DESC_VOID() for the case where the function does not return an error. By using these macros, we get warning messages about missing gdev with reference to the right function in the kernel log. Despite the macro business this simplifies the code and make it more readable than if we copy/paste the same descriptor checking code into all code ABI call sites (IMHO). Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-sysfs.c | 12 +- drivers/gpio/gpiolib.c | 257 +++++++++++++++++++++++-------------------- drivers/gpio/gpiolib.h | 10 +- 3 files changed, 149 insertions(+), 130 deletions(-) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index de65633471af..c56309491e8b 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -180,7 +180,7 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags) * Remove this redundant call (along with the corresponding * unlock) when those drivers have been fixed. */ - ret = gpiochip_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc)); + ret = gpiochip_lock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc)); if (ret < 0) goto err_put_kn; @@ -194,7 +194,7 @@ static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags) return 0; err_unlock: - gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc)); + gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc)); err_put_kn: sysfs_put(data->value_kn); @@ -212,7 +212,7 @@ static void gpio_sysfs_free_irq(struct device *dev) data->irq_flags = 0; free_irq(data->irq, data); - gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc)); + gpiochip_unlock_as_irq(desc->gdev->chip, gpio_chip_hwgpio(desc)); sysfs_put(data->value_kn); } @@ -566,8 +566,8 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) return -EINVAL; } - chip = desc->chip; - gdev = chip->gpiodev; + gdev = desc->gdev; + chip = gdev->chip; mutex_lock(&sysfs_lock); @@ -765,7 +765,7 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev) /* unregister gpiod class devices owned by sysfs */ for (i = 0; i < chip->ngpio; i++) { - desc = &chip->gpiodev->descs[i]; + desc = &gdev->descs[i]; if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) gpiod_free(desc); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index ff8d55ad790c..0738f9a51633 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -85,10 +85,10 @@ struct gpio_desc *gpio_to_desc(unsigned gpio) spin_lock_irqsave(&gpio_lock, flags); list_for_each_entry(gdev, &gpio_devices, list) { - if (gdev->chip->base <= gpio && - gdev->chip->base + gdev->chip->ngpio > gpio) { + if (gdev->base <= gpio && + gdev->base + gdev->ngpio > gpio) { spin_unlock_irqrestore(&gpio_lock, flags); - return &gdev->descs[gpio - gdev->chip->base]; + return &gdev->descs[gpio - gdev->base]; } } @@ -107,10 +107,12 @@ EXPORT_SYMBOL_GPL(gpio_to_desc); struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, u16 hwnum) { - if (hwnum >= chip->ngpio) + struct gpio_device *gdev = chip->gpiodev; + + if (hwnum >= gdev->ngpio) return ERR_PTR(-EINVAL); - return &chip->gpiodev->descs[hwnum]; + return &gdev->descs[hwnum]; } /** @@ -120,7 +122,7 @@ struct gpio_desc *gpiochip_get_desc(struct gpio_chip *chip, */ int desc_to_gpio(const struct gpio_desc *desc) { - return desc->chip->base + (desc - &desc->chip->gpiodev->descs[0]); + return desc->gdev->base + (desc - &desc->gdev->descs[0]); } EXPORT_SYMBOL_GPL(desc_to_gpio); @@ -131,7 +133,9 @@ EXPORT_SYMBOL_GPL(desc_to_gpio); */ struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) { - return desc ? desc->chip : NULL; + if (!desc || !desc->gdev || !desc->gdev->chip) + return NULL; + return desc->gdev->chip; } EXPORT_SYMBOL_GPL(gpiod_to_chip); @@ -143,11 +147,11 @@ static int gpiochip_find_base(int ngpio) list_for_each_entry_reverse(gdev, &gpio_devices, list) { /* found a free space? */ - if (gdev->chip->base + gdev->chip->ngpio <= base) + if (gdev->base + gdev->ngpio <= base) break; else /* nope, check the space right before the chip */ - base = gdev->chip->base - ngpio; + base = gdev->base - ngpio; } if (gpio_is_valid(base)) { @@ -214,14 +218,7 @@ static int gpiodev_add_to_list(struct gpio_device *gdev) } list_for_each_entry(iterator, &gpio_devices, list) { - /* - * The list may contain dangling GPIO devices with no - * live chip assigned. - */ - if (!iterator->chip) - continue; - if (iterator->chip->base >= - gdev->chip->base + gdev->chip->ngpio) { + if (iterator->base >= gdev->base + gdev->ngpio) { /* * Iterator is the first GPIO chip so there is no * previous one @@ -234,8 +231,8 @@ static int gpiodev_add_to_list(struct gpio_device *gdev) * [base, base + ngpio - 1]) between previous * and iterator chip. */ - if (previous->chip->base + previous->chip->ngpio - <= gdev->chip->base) + if (previous->base + previous->ngpio + <= gdev->base) goto found; } } @@ -249,7 +246,7 @@ static int gpiodev_add_to_list(struct gpio_device *gdev) */ iterator = list_last_entry(&gpio_devices, struct gpio_device, list); - if (iterator->chip->base + iterator->chip->ngpio <= gdev->chip->base) { + if (iterator->base + iterator->ngpio <= gdev->base) { list_add(&gdev->list, &iterator->list); return 0; } @@ -276,15 +273,15 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name) list_for_each_entry(gdev, &gpio_devices, list) { int i; - for (i = 0; i != gdev->chip->ngpio; ++i) { - struct gpio_desc *gpio = &gdev->descs[i]; + for (i = 0; i != gdev->ngpio; ++i) { + struct gpio_desc *desc = &gdev->descs[i]; - if (!gpio->name || !name) + if (!desc->name || !name) continue; - if (!strcmp(gpio->name, name)) { + if (!strcmp(desc->name, name)) { spin_unlock_irqrestore(&gpio_lock, flags); - return gpio; + return desc; } } } @@ -302,6 +299,7 @@ static struct gpio_desc *gpio_name_to_desc(const char * const name) */ static int gpiochip_set_desc_names(struct gpio_chip *gc) { + struct gpio_device *gdev = gc->gpiodev; int i; if (!gc->names) @@ -313,14 +311,14 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) gpio = gpio_name_to_desc(gc->names[i]); if (gpio) - dev_warn(&gc->gpiodev->dev, + dev_warn(&gdev->dev, "Detected name collision for GPIO name '%s'\n", gc->names[i]); } /* Then add all names to the GPIO descriptors */ for (i = 0; i != gc->ngpio; ++i) - gc->gpiodev->descs[i].name = gc->names[i]; + gdev->descs[i].name = gc->names[i]; return 0; } @@ -344,7 +342,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) strncpy(chipinfo.name, dev_name(&gdev->dev), sizeof(chipinfo.name)); chipinfo.name[sizeof(chipinfo.name)-1] = '\0'; - chipinfo.lines = chip->ngpio; + chipinfo.lines = gdev->ngpio; if (copy_to_user(ip, &chipinfo, sizeof(chipinfo))) return -EFAULT; return 0; @@ -476,17 +474,24 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) goto err_free_gdev; } - /* FIXME: move driver data into gpio_device dev_set_drvdata() */ - chip->data = data; - if (chip->ngpio == 0) { chip_err(chip, "tried to insert a GPIO chip with zero lines\n"); status = -EINVAL; goto err_free_gdev; } + gdev->ngpio = chip->ngpio; + /* FIXME: move driver data into gpio_device dev_set_drvdata() */ + chip->data = data; spin_lock_irqsave(&gpio_lock, flags); + /* + * TODO: this allocates a Linux GPIO number base in the global + * GPIO numberspace for this chip. In the long run we want to + * get *rid* of this numberspace and use only descriptors, but + * it may be a pipe dream. It will not happen before we get rid + * of the sysfs interface anyways. + */ if (base < 0) { base = gpiochip_find_base(chip->ngpio); if (base < 0) { @@ -494,8 +499,15 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) spin_unlock_irqrestore(&gpio_lock, flags); goto err_free_gdev; } + /* + * TODO: it should not be necessary to reflect the assigned + * base outside of the GPIO subsystem. Go over drivers and + * see if anyone makes use of this, else drop this and assign + * a poison instead. + */ chip->base = base; } + gdev->base = base; status = gpiodev_add_to_list(gdev); if (status) { @@ -506,8 +518,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) for (i = 0; i < chip->ngpio; i++) { struct gpio_desc *desc = &gdev->descs[i]; - /* REVISIT: maybe a pointer to gpio_device is better */ - desc->chip = chip; + desc->gdev = gdev; /* REVISIT: most hardware initializes GPIOs as inputs (often * with pullups enabled) so power usage is minimized. Linux @@ -563,9 +574,9 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) /* From this point, the .release() function cleans up gpio_device */ gdev->dev.release = gpiodevice_release; get_device(&gdev->dev); - pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, - chip->base, chip->base + chip->ngpio - 1, - chip->label ? : "generic"); + pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", + __func__, gdev->base, gdev->base + gdev->ngpio - 1, + dev_name(&gdev->dev), chip->label ? : "generic"); return 0; @@ -583,11 +594,11 @@ err_remove_from_list: spin_unlock_irqrestore(&gpio_lock, flags); err_free_gdev: ida_simple_remove(&gpio_ida, gdev->id); - kfree(gdev); /* failures here can mean systems won't boot... */ pr_err("%s: GPIOs %d..%d (%s) failed to register\n", __func__, - chip->base, chip->base + chip->ngpio - 1, - chip->label ? : "generic"); + gdev->base, gdev->base + gdev->ngpio - 1, + chip->label ? : "generic"); + kfree(gdev); return status; } EXPORT_SYMBOL_GPL(gpiochip_add_data); @@ -618,16 +629,15 @@ void gpiochip_remove(struct gpio_chip *chip) of_gpiochip_remove(chip); spin_lock_irqsave(&gpio_lock, flags); - for (i = 0; i < chip->ngpio; i++) { + for (i = 0; i < gdev->ngpio; i++) { desc = &gdev->descs[i]; - desc->chip = NULL; if (test_bit(FLAG_REQUESTED, &desc->flags)) requested = true; } spin_unlock_irqrestore(&gpio_lock, flags); if (requested) - dev_crit(&chip->gpiodev->dev, + dev_crit(&gdev->dev, "REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED\n"); /* @@ -967,7 +977,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) {} */ int gpiochip_generic_request(struct gpio_chip *chip, unsigned offset) { - return pinctrl_request_gpio(chip->base + offset); + return pinctrl_request_gpio(chip->gpiodev->base + offset); } EXPORT_SYMBOL_GPL(gpiochip_generic_request); @@ -978,7 +988,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_request); */ void gpiochip_generic_free(struct gpio_chip *chip, unsigned offset) { - pinctrl_free_gpio(chip->base + offset); + pinctrl_free_gpio(chip->gpiodev->base + offset); } EXPORT_SYMBOL_GPL(gpiochip_generic_free); @@ -996,6 +1006,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, unsigned int gpio_offset, const char *pin_group) { struct gpio_pin_range *pin_range; + struct gpio_device *gdev = chip->gpiodev; int ret; pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); @@ -1008,7 +1019,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, pin_range->range.id = gpio_offset; pin_range->range.gc = chip; pin_range->range.name = chip->label; - pin_range->range.base = chip->base + gpio_offset; + pin_range->range.base = gdev->base + gpio_offset; pin_range->pctldev = pctldev; ret = pinctrl_get_group_pins(pctldev, pin_group, @@ -1045,6 +1056,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, unsigned int npins) { struct gpio_pin_range *pin_range; + struct gpio_device *gdev = chip->gpiodev; int ret; pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL); @@ -1057,7 +1069,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, pin_range->range.id = gpio_offset; pin_range->range.gc = chip; pin_range->range.name = chip->label; - pin_range->range.base = chip->base + gpio_offset; + pin_range->range.base = gdev->base + gpio_offset; pin_range->range.pin_base = pin_offset; pin_range->range.npins = npins; pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name, @@ -1104,7 +1116,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges); */ static int __gpiod_request(struct gpio_desc *desc, const char *label) { - struct gpio_chip *chip = desc->chip; + struct gpio_chip *chip = desc->gdev->chip; int status; unsigned long flags; @@ -1153,27 +1165,48 @@ done: return status; } +/* + * This descriptor validation needs to be inserted verbatim into each + * function taking a descriptor, so we need to use a preprocessor + * macro to avoid endless duplication. + */ +#define VALIDATE_DESC(desc) do { \ + if (!desc || !desc->gdev) { \ + pr_warn("%s: invalid GPIO\n", __func__); \ + return -EINVAL; \ + } \ + if ( !desc->gdev->chip ) { \ + dev_warn(&desc->gdev->dev, \ + "%s: backing chip is gone\n", __func__); \ + return 0; \ + } } while (0) + +#define VALIDATE_DESC_VOID(desc) do { \ + if (!desc || !desc->gdev) { \ + pr_warn("%s: invalid GPIO\n", __func__); \ + return; \ + } \ + if (!desc->gdev->chip) { \ + dev_warn(&desc->gdev->dev, \ + "%s: backing chip is gone\n", __func__); \ + return; \ + } } while (0) + + int gpiod_request(struct gpio_desc *desc, const char *label) { int status = -EPROBE_DEFER; - struct gpio_chip *chip; - - if (!desc) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } + struct gpio_device *gdev; - chip = desc->chip; - if (!chip) - goto done; + VALIDATE_DESC(desc); + gdev = desc->gdev; - if (try_module_get(chip->gpiodev->owner)) { + if (try_module_get(gdev->owner)) { status = __gpiod_request(desc, label); if (status < 0) - module_put(chip->gpiodev->owner); + module_put(gdev->owner); } -done: if (status) gpiod_dbg(desc, "%s: status %d\n", __func__, status); @@ -1192,7 +1225,7 @@ static bool __gpiod_free(struct gpio_desc *desc) spin_lock_irqsave(&gpio_lock, flags); - chip = desc->chip; + chip = desc->gdev->chip; if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) { if (chip->free) { spin_unlock_irqrestore(&gpio_lock, flags); @@ -1216,7 +1249,7 @@ static bool __gpiod_free(struct gpio_desc *desc) void gpiod_free(struct gpio_desc *desc) { if (desc && __gpiod_free(desc)) - module_put(desc->chip->gpiodev->owner); + module_put(desc->gdev->owner); else WARN_ON(extra_checks); } @@ -1293,7 +1326,8 @@ void gpiochip_free_own_desc(struct gpio_desc *desc) } EXPORT_SYMBOL_GPL(gpiochip_free_own_desc); -/* Drivers MUST set GPIO direction before making get/set calls. In +/* + * Drivers MUST set GPIO direction before making get/set calls. In * some cases this is done in early boot, before IRQs are enabled. * * As a rule these aren't called more than once (except for drivers @@ -1316,12 +1350,9 @@ int gpiod_direction_input(struct gpio_desc *desc) struct gpio_chip *chip; int status = -EINVAL; - if (!desc || !desc->chip) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } + VALIDATE_DESC(desc); + chip = desc->gdev->chip; - chip = desc->chip; if (!chip->get || !chip->direction_input) { gpiod_warn(desc, "%s: missing get() or direction_input() operations\n", @@ -1360,7 +1391,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags)) return gpiod_direction_input(desc); - chip = desc->chip; + chip = desc->gdev->chip; if (!chip->set || !chip->direction_output) { gpiod_warn(desc, "%s: missing set() or direction_output() operations\n", @@ -1389,10 +1420,7 @@ static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value) */ int gpiod_direction_output_raw(struct gpio_desc *desc, int value) { - if (!desc || !desc->chip) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } + VALIDATE_DESC(desc); return _gpiod_direction_output_raw(desc, value); } EXPORT_SYMBOL_GPL(gpiod_direction_output_raw); @@ -1411,10 +1439,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_output_raw); */ int gpiod_direction_output(struct gpio_desc *desc, int value) { - if (!desc || !desc->chip) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } + VALIDATE_DESC(desc); if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) value = !value; return _gpiod_direction_output_raw(desc, value); @@ -1433,12 +1458,8 @@ int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) { struct gpio_chip *chip; - if (!desc || !desc->chip) { - pr_warn("%s: invalid GPIO\n", __func__); - return -EINVAL; - } - - chip = desc->chip; + VALIDATE_DESC(desc); + chip = desc->gdev->chip; if (!chip->set || !chip->set_debounce) { gpiod_dbg(desc, "%s: missing set() or set_debounce() operations\n", @@ -1458,6 +1479,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce); */ int gpiod_is_active_low(const struct gpio_desc *desc) { + VALIDATE_DESC(desc); return test_bit(FLAG_ACTIVE_LOW, &desc->flags); } EXPORT_SYMBOL_GPL(gpiod_is_active_low); @@ -1490,7 +1512,7 @@ static int _gpiod_get_raw_value(const struct gpio_desc *desc) int offset; int value; - chip = desc->chip; + chip = desc->gdev->chip; offset = gpio_chip_hwgpio(desc); value = chip->get ? chip->get(chip, offset) : -EIO; value = value < 0 ? value : !!value; @@ -1510,10 +1532,9 @@ static int _gpiod_get_raw_value(const struct gpio_desc *desc) */ int gpiod_get_raw_value(const struct gpio_desc *desc) { - if (!desc) - return 0; + VALIDATE_DESC(desc); /* Should be using gpio_get_value_cansleep() */ - WARN_ON(desc->chip->can_sleep); + WARN_ON(desc->gdev->chip->can_sleep); return _gpiod_get_raw_value(desc); } EXPORT_SYMBOL_GPL(gpiod_get_raw_value); @@ -1531,10 +1552,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value); int gpiod_get_value(const struct gpio_desc *desc) { int value; - if (!desc) - return 0; + + VALIDATE_DESC(desc); /* Should be using gpio_get_value_cansleep() */ - WARN_ON(desc->chip->can_sleep); + WARN_ON(desc->gdev->chip->can_sleep); value = _gpiod_get_raw_value(desc); if (value < 0) @@ -1555,7 +1576,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value); static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value) { int err = 0; - struct gpio_chip *chip = desc->chip; + struct gpio_chip *chip = desc->gdev->chip; int offset = gpio_chip_hwgpio(desc); if (value) { @@ -1582,7 +1603,7 @@ static void _gpio_set_open_drain_value(struct gpio_desc *desc, bool value) static void _gpio_set_open_source_value(struct gpio_desc *desc, bool value) { int err = 0; - struct gpio_chip *chip = desc->chip; + struct gpio_chip *chip = desc->gdev->chip; int offset = gpio_chip_hwgpio(desc); if (value) { @@ -1605,7 +1626,7 @@ static void _gpiod_set_raw_value(struct gpio_desc *desc, bool value) { struct gpio_chip *chip; - chip = desc->chip; + chip = desc->gdev->chip; trace_gpio_value(desc_to_gpio(desc), 0, value); if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) _gpio_set_open_drain_value(desc, value); @@ -1653,7 +1674,7 @@ static void gpiod_set_array_value_priv(bool raw, bool can_sleep, int i = 0; while (i < array_size) { - struct gpio_chip *chip = desc_array[i]->chip; + struct gpio_chip *chip = desc_array[i]->gdev->chip; unsigned long mask[BITS_TO_LONGS(chip->ngpio)]; unsigned long bits[BITS_TO_LONGS(chip->ngpio)]; int count = 0; @@ -1687,7 +1708,8 @@ static void gpiod_set_array_value_priv(bool raw, bool can_sleep, count++; } i++; - } while ((i < array_size) && (desc_array[i]->chip == chip)); + } while ((i < array_size) && + (desc_array[i]->gdev->chip == chip)); /* push collected bits to outputs */ if (count != 0) gpio_chip_set_multiple(chip, mask, bits); @@ -1707,10 +1729,9 @@ static void gpiod_set_array_value_priv(bool raw, bool can_sleep, */ void gpiod_set_raw_value(struct gpio_desc *desc, int value) { - if (!desc) - return; + VALIDATE_DESC_VOID(desc); /* Should be using gpio_set_value_cansleep() */ - WARN_ON(desc->chip->can_sleep); + WARN_ON(desc->gdev->chip->can_sleep); _gpiod_set_raw_value(desc, value); } EXPORT_SYMBOL_GPL(gpiod_set_raw_value); @@ -1728,10 +1749,9 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_value); */ void gpiod_set_value(struct gpio_desc *desc, int value) { - if (!desc) - return; + VALIDATE_DESC_VOID(desc); /* Should be using gpio_set_value_cansleep() */ - WARN_ON(desc->chip->can_sleep); + WARN_ON(desc->gdev->chip->can_sleep); if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) value = !value; _gpiod_set_raw_value(desc, value); @@ -1789,9 +1809,8 @@ EXPORT_SYMBOL_GPL(gpiod_set_array_value); */ int gpiod_cansleep(const struct gpio_desc *desc) { - if (!desc) - return 0; - return desc->chip->can_sleep; + VALIDATE_DESC(desc); + return desc->gdev->chip->can_sleep; } EXPORT_SYMBOL_GPL(gpiod_cansleep); @@ -1807,9 +1826,8 @@ int gpiod_to_irq(const struct gpio_desc *desc) struct gpio_chip *chip; int offset; - if (!desc) - return -EINVAL; - chip = desc->chip; + VALIDATE_DESC(desc); + chip = desc->gdev->chip; offset = gpio_chip_hwgpio(desc); return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; } @@ -1878,8 +1896,7 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_irq); int gpiod_get_raw_value_cansleep(const struct gpio_desc *desc) { might_sleep_if(extra_checks); - if (!desc) - return 0; + VALIDATE_DESC(desc); return _gpiod_get_raw_value(desc); } EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep); @@ -1898,9 +1915,7 @@ int gpiod_get_value_cansleep(const struct gpio_desc *desc) int value; might_sleep_if(extra_checks); - if (!desc) - return 0; - + VALIDATE_DESC(desc); value = _gpiod_get_raw_value(desc); if (value < 0) return value; @@ -1925,8 +1940,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_value_cansleep); void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) { might_sleep_if(extra_checks); - if (!desc) - return; + VALIDATE_DESC_VOID(desc); _gpiod_set_raw_value(desc, value); } EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep); @@ -1944,9 +1958,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_raw_value_cansleep); void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) { might_sleep_if(extra_checks); - if (!desc) - return; - + VALIDATE_DESC_VOID(desc); if (test_bit(FLAG_ACTIVE_LOW, &desc->flags)) value = !value; _gpiod_set_raw_value(desc, value); @@ -2669,15 +2681,16 @@ core_initcall(gpiolib_dev_init); #ifdef CONFIG_DEBUG_FS -static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) +static void gpiolib_dbg_show(struct seq_file *s, struct gpio_device *gdev) { unsigned i; - unsigned gpio = chip->base; - struct gpio_desc *gdesc = &chip->gpiodev->descs[0]; + struct gpio_chip *chip = gdev->chip; + unsigned gpio = gdev->base; + struct gpio_desc *gdesc = &gdev->descs[0]; int is_out; int is_irq; - for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) { + for (i = 0; i < gdev->ngpio; i++, gpio++, gdesc++) { if (!test_bit(FLAG_REQUESTED, &gdesc->flags)) { if (gdesc->name) { seq_printf(s, " gpio-%-3d (%-20.20s)\n", @@ -2756,7 +2769,7 @@ static int gpiolib_seq_show(struct seq_file *s, void *v) seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private, dev_name(&gdev->dev), - chip->base, chip->base + chip->ngpio - 1); + gdev->base, gdev->base + gdev->ngpio - 1); parent = chip->parent; if (parent) seq_printf(s, ", parent: %s/%s", @@ -2771,7 +2784,7 @@ static int gpiolib_seq_show(struct seq_file *s, void *v) if (chip->dbg_show) chip->dbg_show(s, chip); else - gpiolib_dbg_show(s, chip); + gpiolib_dbg_show(s, gdev); return 0; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 39b8301c98b6..d154984c71d9 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -33,6 +33,10 @@ struct acpi_device; * @chip: pointer to the corresponding gpiochip, holding static * data for this device * @descs: array of ngpio descriptors. + * @ngpio: the number of GPIO lines on this GPIO device, equal to the size + * of the @descs array. + * @base: GPIO base in the DEPRECATED global Linux GPIO numberspace, assigned + * at device creation time. * @list: links gpio_device:s together for traversal * * This state container holds most of the runtime variable data @@ -48,6 +52,8 @@ struct gpio_device { struct module *owner; struct gpio_chip *chip; struct gpio_desc *descs; + int base; + u16 ngpio; struct list_head list; }; @@ -125,7 +131,7 @@ extern struct spinlock gpio_lock; extern struct list_head gpio_devices; struct gpio_desc { - struct gpio_chip *chip; + struct gpio_device *gdev; unsigned long flags; /* flag symbols are bit numbers */ #define FLAG_REQUESTED 0 @@ -154,7 +160,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name, */ static int __maybe_unused gpio_chip_hwgpio(const struct gpio_desc *desc) { - return desc - &desc->chip->gpiodev->descs[0]; + return desc - &desc->gdev->descs[0]; } /* With descriptor prefix */ -- cgit From 33a68e86fd7741f782c71a0daa9111b352e94445 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 11 Feb 2016 10:28:44 +0100 Subject: gpio: reference count the gpio device for each desc Every time a descriptor is retrieved from the gpiolib, we issue module_get() to reference count the module supplying the GPIOs. We also need to call device_get() and device_put() as we also reference the backing gpio_device when doing this. Since the sysfs GPIO interface is using gpiod_get() this will also reference count the sysfs requests until all GPIOs are unexported. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 0738f9a51633..646dea4f96ff 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1205,6 +1205,8 @@ int gpiod_request(struct gpio_desc *desc, const char *label) status = __gpiod_request(desc, label); if (status < 0) module_put(gdev->owner); + else + get_device(&gdev->dev); } if (status) @@ -1248,10 +1250,12 @@ static bool __gpiod_free(struct gpio_desc *desc) void gpiod_free(struct gpio_desc *desc) { - if (desc && __gpiod_free(desc)) + if (desc && desc->gdev && __gpiod_free(desc)) { module_put(desc->gdev->owner); - else + put_device(&desc->gdev->dev); + } else { WARN_ON(extra_checks); + } } /** -- cgit From 78ecc56247f0ec2bc0cf6f2f2af69e98d99767bc Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Thu, 11 Feb 2016 11:25:59 +0000 Subject: PM / OPP: Fix NULL pointer dereference crash when disabling OPPs Commit 7d34d56ef334 (PM / OPP: Disable OPPs that aren't supported by the regulator) causes a crash to happen on Tegra124 Jetson TK1 when using the DFLL clock source for the CPU. The DFLL manages the voltage itself and so there is no regulator specified for the OPPs and so we get a crash when we try to dereference the regulator pointer. Fix this by checking to see if the regulator IS_ERR_OR_NULL before dereferencing it. Fixes: 7d34d56ef334 (PM / OPP: Disable OPPs that aren't supported by the regulator) Signed-off-by: Jon Hunter Reported-by: Bartlomiej Zolnierkiewicz Acked-by: Viresh Kumar [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index ab711c2c3e00..d7cd4e265766 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -975,7 +975,7 @@ static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, { struct regulator *reg = dev_opp->regulator; - if (!IS_ERR(reg) && + if (!IS_ERR_OR_NULL(reg) && !regulator_is_supported_voltage(reg, opp->u_volt_min, opp->u_volt_max)) { pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n", -- cgit From 60c7f4cb1fa4df62b7ba07e9b087728ca7ce5bc8 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Tue, 2 Feb 2016 11:02:35 -0800 Subject: scripts/dtc: dtx_diff - add info to error message If kernel config options are not properly set, "make scripts" will not compile dtc. Update the unable to find dtc error message to check the kernel config and give better advice on how to create dtc. Reword another error message to increase clarity. Signed-off-by: Frank Rowand Signed-off-by: Rob Herring --- scripts/dtc/dtx_diff | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff index f1160053d75e..959ab2646d38 100755 --- a/scripts/dtc/dtx_diff +++ b/scripts/dtc/dtx_diff @@ -136,8 +136,7 @@ compile_to_dts() { echo "" >&2 echo " architecture ${dtx_arch} is in file path," >&2 echo " but does not match shell variable \$ARCH" >&2 - echo " (${ARCH}) does not match shell variable" >&2 - echo " \$ARCH (${ARCH})" >&2 + echo " >>\$ARCH<< is: >>${ARCH}<<" >&2 fi if [ ! -d ${srctree}/arch/${ARCH} ] ; then @@ -267,6 +266,14 @@ DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc" if [ ! -x ${DTC} ] ; then __DTC="dtc" + if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config ; then + make_command=' + make scripts' + else + make_command=' + Enable CONFIG_DTC in the kernel configuration + make scripts' + fi if ( ! which ${__DTC} >/dev/null ) ; then # use spaces instead of tabs in the error message @@ -280,8 +287,7 @@ ERROR: unable to find a 'dtc' program 'dtc' is: ${DTC} If it does not exist, create it from the root of the Linux source tree: - - 'make scripts'. +${make_command} If not at the root of the Linux kernel source tree -s SRCTREE or -S may need to be specified to find 'dtc'. -- cgit From 76df69806b7fafea013e2f4f82b0bd54498f3406 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 11 Feb 2016 16:59:12 -0600 Subject: ARM: boot: Add an implementation of strnlen for libfdt Recent versions of libfdt add a dependency on strnlen. Copy the implementation in lib/string.c here, so we can update libfdt. Acked-by: Russell King Signed-off-by: Rob Herring --- arch/arm/boot/compressed/string.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm/boot/compressed/string.c b/arch/arm/boot/compressed/string.c index 36e53ef9200f..689467448736 100644 --- a/arch/arm/boot/compressed/string.c +++ b/arch/arm/boot/compressed/string.c @@ -65,6 +65,15 @@ size_t strlen(const char *s) return sc - s; } +size_t strnlen(const char *s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} + int memcmp(const void *cs, const void *ct, size_t count) { const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count; -- cgit From 91feabc2e2240ee80dc8ac08103cb83f497e4d12 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 26 Jan 2016 09:04:11 -0600 Subject: scripts/dtc: Update to upstream commit b06e55c88b9b Sync to upstream dtc commit b06e55c88b9b ("Prevent crash on modulo by zero"). This adds the following commits from upstream: b06e55c Prevent crash on modulo by zero b433450 Fix some bugs in processing of line directives d728ad5 Fix crash on nul character in string escape sequence 1ab2205 Gracefully handle bad octal literals 1937095 Prevent crash on division by zero d0b3ab0 libfdt: Fix undefined behaviour in fdt_offset_ptr() d4c7c25 libfdt: check for potential overrun in _fdt_splice() f58799b libfdt: Add some missing symbols to version.lds af9f26d Remove duplicated -Werror in dtc Makefile 604e61e fdt: Add functions to retrieve strings 8702bd1 fdt: Add a function to get the index of a string 2218387 fdt: Add a function to count strings 554fde2 libfdt: fix comment block of fdt_get_property_namelen() e5e6df7 fdtdump: Fix bug printing bytestrings with negative values 067829e Remove redundant fdtdump test code 897a429 Move fdt_path_offset alias tests to right tests section 2d1417c Add simple .travis.yml f6dbc6c guess output file format 5e78dff guess input file format based on file content or file name 8b927bf tests: convert `echo -n` to `printf` 64c46b0 Fix crash with poorly defined #size-cells Cc: Grant Likely Tested-by: Frank Rowand Reviewed-by: Frank Rowand Signed-off-by: Rob Herring --- scripts/dtc/checks.c | 2 +- scripts/dtc/dtc-lexer.l | 39 +++++++++----- scripts/dtc/dtc-lexer.lex.c_shipped | 101 +++++++++++++++++++---------------- scripts/dtc/dtc-parser.tab.c_shipped | 84 +++++++++++++++++------------ scripts/dtc/dtc-parser.y | 20 ++++++- scripts/dtc/dtc.c | 62 ++++++++++++++++++++- scripts/dtc/libfdt/fdt.c | 13 ++--- scripts/dtc/libfdt/fdt_ro.c | 100 ++++++++++++++++++++++++++++++++++ scripts/dtc/libfdt/fdt_rw.c | 2 + scripts/dtc/libfdt/libfdt.h | 73 +++++++++++++++++++++++-- scripts/dtc/util.c | 3 +- scripts/dtc/version_gen.h | 2 +- 12 files changed, 390 insertions(+), 111 deletions(-) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index e81a8c74b8d2..0c03ac9159c1 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -560,7 +560,7 @@ static void check_reg_format(struct check *c, struct node *dt, size_cells = node_size_cells(node->parent); entrylen = (addr_cells + size_cells) * sizeof(cell_t); - if ((prop->val.len % entrylen) != 0) + if (!entrylen || (prop->val.len % entrylen) != 0) FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " "(#address-cells == %d, #size-cells == %d)", node->fullpath, prop->val.len, addr_cells, size_cells); diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index 0ee1caf03dd0..790fbf6cf2d7 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -73,24 +73,32 @@ static void lexical_error(const char *fmt, ...); } <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { - char *line, *tmp, *fn; + char *line, *fnstart, *fnend; + struct data fn; /* skip text before line # */ line = yytext; while (!isdigit((unsigned char)*line)) line++; - /* skip digits in line # */ - tmp = line; - while (!isspace((unsigned char)*tmp)) - tmp++; - /* "NULL"-terminate line # */ - *tmp = '\0'; - /* start of filename */ - fn = strchr(tmp + 1, '"') + 1; - /* strip trailing " from filename */ - tmp = strchr(fn, '"'); - *tmp = 0; + + /* regexp ensures that first and list " + * in the whole yytext are those at + * beginning and end of the filename string */ + fnstart = memchr(yytext, '"', yyleng); + for (fnend = yytext + yyleng - 1; + *fnend != '"'; fnend--) + ; + assert(fnstart && fnend && (fnend > fnstart)); + + fn = data_copy_escape_string(fnstart + 1, + fnend - fnstart - 1); + + /* Don't allow nuls in filenames */ + if (memchr(fn.val, '\0', fn.len - 1)) + lexical_error("nul in line number directive"); + /* -1 since #line is the number of the next line */ - srcpos_set_line(xstrdup(fn), atoi(line) - 1); + srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); + data_free(fn); } <*><> { @@ -153,7 +161,10 @@ static void lexical_error(const char *fmt, ...); errno = 0; yylval.integer = strtoull(yytext, &e, 0); - assert(!(*e) || !e[strspn(e, "UL")]); + if (*e && e[strspn(e, "UL")]) { + lexical_error("Bad integer literal '%s'", + yytext); + } if (errno == ERANGE) lexical_error("Integer literal '%s' out of range", diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped index 11cd78e72305..ba525c2f9fc2 100644 --- a/scripts/dtc/dtc-lexer.lex.c_shipped +++ b/scripts/dtc/dtc-lexer.lex.c_shipped @@ -951,31 +951,39 @@ case 2: YY_RULE_SETUP #line 75 "dtc-lexer.l" { - char *line, *tmp, *fn; + char *line, *fnstart, *fnend; + struct data fn; /* skip text before line # */ line = yytext; while (!isdigit((unsigned char)*line)) line++; - /* skip digits in line # */ - tmp = line; - while (!isspace((unsigned char)*tmp)) - tmp++; - /* "NULL"-terminate line # */ - *tmp = '\0'; - /* start of filename */ - fn = strchr(tmp + 1, '"') + 1; - /* strip trailing " from filename */ - tmp = strchr(fn, '"'); - *tmp = 0; + + /* regexp ensures that first and list " + * in the whole yytext are those at + * beginning and end of the filename string */ + fnstart = memchr(yytext, '"', yyleng); + for (fnend = yytext + yyleng - 1; + *fnend != '"'; fnend--) + ; + assert(fnstart && fnend && (fnend > fnstart)); + + fn = data_copy_escape_string(fnstart + 1, + fnend - fnstart - 1); + + /* Don't allow nuls in filenames */ + if (memchr(fn.val, '\0', fn.len - 1)) + lexical_error("nul in line number directive"); + /* -1 since #line is the number of the next line */ - srcpos_set_line(xstrdup(fn), atoi(line) - 1); + srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); + data_free(fn); } YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(BYTESTRING): case YY_STATE_EOF(PROPNODENAME): case YY_STATE_EOF(V1): -#line 96 "dtc-lexer.l" +#line 104 "dtc-lexer.l" { if (!pop_input_file()) { yyterminate(); @@ -985,7 +993,7 @@ case YY_STATE_EOF(V1): case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 102 "dtc-lexer.l" +#line 110 "dtc-lexer.l" { DPRINT("String: %s\n", yytext); yylval.data = data_copy_escape_string(yytext+1, @@ -995,7 +1003,7 @@ YY_RULE_SETUP YY_BREAK case 4: YY_RULE_SETUP -#line 109 "dtc-lexer.l" +#line 117 "dtc-lexer.l" { DPRINT("Keyword: /dts-v1/\n"); dts_version = 1; @@ -1005,7 +1013,7 @@ YY_RULE_SETUP YY_BREAK case 5: YY_RULE_SETUP -#line 116 "dtc-lexer.l" +#line 124 "dtc-lexer.l" { DPRINT("Keyword: /memreserve/\n"); BEGIN_DEFAULT(); @@ -1014,7 +1022,7 @@ YY_RULE_SETUP YY_BREAK case 6: YY_RULE_SETUP -#line 122 "dtc-lexer.l" +#line 130 "dtc-lexer.l" { DPRINT("Keyword: /bits/\n"); BEGIN_DEFAULT(); @@ -1023,7 +1031,7 @@ YY_RULE_SETUP YY_BREAK case 7: YY_RULE_SETUP -#line 128 "dtc-lexer.l" +#line 136 "dtc-lexer.l" { DPRINT("Keyword: /delete-property/\n"); DPRINT("\n"); @@ -1033,7 +1041,7 @@ YY_RULE_SETUP YY_BREAK case 8: YY_RULE_SETUP -#line 135 "dtc-lexer.l" +#line 143 "dtc-lexer.l" { DPRINT("Keyword: /delete-node/\n"); DPRINT("\n"); @@ -1043,7 +1051,7 @@ YY_RULE_SETUP YY_BREAK case 9: YY_RULE_SETUP -#line 142 "dtc-lexer.l" +#line 150 "dtc-lexer.l" { DPRINT("Label: %s\n", yytext); yylval.labelref = xstrdup(yytext); @@ -1053,7 +1061,7 @@ YY_RULE_SETUP YY_BREAK case 10: YY_RULE_SETUP -#line 149 "dtc-lexer.l" +#line 157 "dtc-lexer.l" { char *e; DPRINT("Integer Literal: '%s'\n", yytext); @@ -1061,7 +1069,10 @@ YY_RULE_SETUP errno = 0; yylval.integer = strtoull(yytext, &e, 0); - assert(!(*e) || !e[strspn(e, "UL")]); + if (*e && e[strspn(e, "UL")]) { + lexical_error("Bad integer literal '%s'", + yytext); + } if (errno == ERANGE) lexical_error("Integer literal '%s' out of range", @@ -1076,7 +1087,7 @@ YY_RULE_SETUP case 11: /* rule 11 can match eol */ YY_RULE_SETUP -#line 168 "dtc-lexer.l" +#line 179 "dtc-lexer.l" { struct data d; DPRINT("Character literal: %s\n", yytext); @@ -1100,7 +1111,7 @@ YY_RULE_SETUP YY_BREAK case 12: YY_RULE_SETUP -#line 189 "dtc-lexer.l" +#line 200 "dtc-lexer.l" { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); @@ -1109,7 +1120,7 @@ YY_RULE_SETUP YY_BREAK case 13: YY_RULE_SETUP -#line 195 "dtc-lexer.l" +#line 206 "dtc-lexer.l" { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); @@ -1119,7 +1130,7 @@ YY_RULE_SETUP YY_BREAK case 14: YY_RULE_SETUP -#line 202 "dtc-lexer.l" +#line 213 "dtc-lexer.l" { yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); @@ -1128,7 +1139,7 @@ YY_RULE_SETUP YY_BREAK case 15: YY_RULE_SETUP -#line 208 "dtc-lexer.l" +#line 219 "dtc-lexer.l" { DPRINT("/BYTESTRING\n"); BEGIN_DEFAULT(); @@ -1137,7 +1148,7 @@ YY_RULE_SETUP YY_BREAK case 16: YY_RULE_SETUP -#line 214 "dtc-lexer.l" +#line 225 "dtc-lexer.l" { DPRINT("PropNodeName: %s\n", yytext); yylval.propnodename = xstrdup((yytext[0] == '\\') ? @@ -1148,7 +1159,7 @@ YY_RULE_SETUP YY_BREAK case 17: YY_RULE_SETUP -#line 222 "dtc-lexer.l" +#line 233 "dtc-lexer.l" { DPRINT("Binary Include\n"); return DT_INCBIN; @@ -1157,64 +1168,64 @@ YY_RULE_SETUP case 18: /* rule 18 can match eol */ YY_RULE_SETUP -#line 227 "dtc-lexer.l" +#line 238 "dtc-lexer.l" /* eat whitespace */ YY_BREAK case 19: /* rule 19 can match eol */ YY_RULE_SETUP -#line 228 "dtc-lexer.l" +#line 239 "dtc-lexer.l" /* eat C-style comments */ YY_BREAK case 20: /* rule 20 can match eol */ YY_RULE_SETUP -#line 229 "dtc-lexer.l" +#line 240 "dtc-lexer.l" /* eat C++-style comments */ YY_BREAK case 21: YY_RULE_SETUP -#line 231 "dtc-lexer.l" +#line 242 "dtc-lexer.l" { return DT_LSHIFT; }; YY_BREAK case 22: YY_RULE_SETUP -#line 232 "dtc-lexer.l" +#line 243 "dtc-lexer.l" { return DT_RSHIFT; }; YY_BREAK case 23: YY_RULE_SETUP -#line 233 "dtc-lexer.l" +#line 244 "dtc-lexer.l" { return DT_LE; }; YY_BREAK case 24: YY_RULE_SETUP -#line 234 "dtc-lexer.l" +#line 245 "dtc-lexer.l" { return DT_GE; }; YY_BREAK case 25: YY_RULE_SETUP -#line 235 "dtc-lexer.l" +#line 246 "dtc-lexer.l" { return DT_EQ; }; YY_BREAK case 26: YY_RULE_SETUP -#line 236 "dtc-lexer.l" +#line 247 "dtc-lexer.l" { return DT_NE; }; YY_BREAK case 27: YY_RULE_SETUP -#line 237 "dtc-lexer.l" +#line 248 "dtc-lexer.l" { return DT_AND; }; YY_BREAK case 28: YY_RULE_SETUP -#line 238 "dtc-lexer.l" +#line 249 "dtc-lexer.l" { return DT_OR; }; YY_BREAK case 29: YY_RULE_SETUP -#line 240 "dtc-lexer.l" +#line 251 "dtc-lexer.l" { DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); @@ -1232,10 +1243,10 @@ YY_RULE_SETUP YY_BREAK case 30: YY_RULE_SETUP -#line 255 "dtc-lexer.l" +#line 266 "dtc-lexer.l" ECHO; YY_BREAK -#line 1239 "dtc-lexer.lex.c" +#line 1250 "dtc-lexer.lex.c" case YY_END_OF_BUFFER: { @@ -2195,7 +2206,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 254 "dtc-lexer.l" +#line 265 "dtc-lexer.l" diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index 116458c8dfc4..31cec50a1265 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -499,9 +499,9 @@ static const yytype_uint16 yyrline[] = 298, 303, 322, 336, 343, 344, 345, 352, 356, 357, 361, 362, 366, 367, 371, 372, 376, 377, 381, 382, 386, 387, 388, 392, 393, 394, 395, 396, 400, 401, - 402, 406, 407, 408, 412, 413, 414, 415, 419, 420, - 421, 422, 427, 430, 434, 442, 445, 449, 457, 461, - 465 + 402, 406, 407, 408, 412, 413, 422, 431, 435, 436, + 437, 438, 443, 446, 450, 458, 461, 465, 473, 477, + 481 }; #endif @@ -1909,111 +1909,125 @@ yyreduce: break; case 65: -#line 413 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); } -#line 1915 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 414 "dtc-parser.y" /* yacc.c:1646 */ + { + if ((yyvsp[0].integer) != 0) { + (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); + } else { + ERROR(&(yyloc), "Division by zero"); + (yyval.integer) = 0; + } + } +#line 1922 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 66: -#line 414 "dtc-parser.y" /* yacc.c:1646 */ - { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); } -#line 1921 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 423 "dtc-parser.y" /* yacc.c:1646 */ + { + if ((yyvsp[0].integer) != 0) { + (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); + } else { + ERROR(&(yyloc), "Division by zero"); + (yyval.integer) = 0; + } + } +#line 1935 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 69: -#line 420 "dtc-parser.y" /* yacc.c:1646 */ +#line 436 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = -(yyvsp[0].integer); } -#line 1927 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1941 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 70: -#line 421 "dtc-parser.y" /* yacc.c:1646 */ +#line 437 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = ~(yyvsp[0].integer); } -#line 1933 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 71: -#line 422 "dtc-parser.y" /* yacc.c:1646 */ +#line 438 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.integer) = !(yyvsp[0].integer); } -#line 1939 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 72: -#line 427 "dtc-parser.y" /* yacc.c:1646 */ +#line 443 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = empty_data; } -#line 1947 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1961 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 73: -#line 431 "dtc-parser.y" /* yacc.c:1646 */ +#line 447 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte)); } -#line 1955 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1969 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 74: -#line 435 "dtc-parser.y" /* yacc.c:1646 */ +#line 451 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref)); } -#line 1963 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1977 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 75: -#line 442 "dtc-parser.y" /* yacc.c:1646 */ +#line 458 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.nodelist) = NULL; } -#line 1971 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1985 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 76: -#line 446 "dtc-parser.y" /* yacc.c:1646 */ +#line 462 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist)); } -#line 1979 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 1993 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 77: -#line 450 "dtc-parser.y" /* yacc.c:1646 */ +#line 466 "dtc-parser.y" /* yacc.c:1646 */ { ERROR(&(yylsp[0]), "Properties must precede subnodes"); YYERROR; } -#line 1988 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2002 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 78: -#line 458 "dtc-parser.y" /* yacc.c:1646 */ +#line 474 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename)); } -#line 1996 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2010 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 79: -#line 462 "dtc-parser.y" /* yacc.c:1646 */ +#line 478 "dtc-parser.y" /* yacc.c:1646 */ { (yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename)); } -#line 2004 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2018 "dtc-parser.tab.c" /* yacc.c:1646 */ break; case 80: -#line 466 "dtc-parser.y" /* yacc.c:1646 */ +#line 482 "dtc-parser.y" /* yacc.c:1646 */ { add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref)); (yyval.node) = (yyvsp[0].node); } -#line 2013 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2027 "dtc-parser.tab.c" /* yacc.c:1646 */ break; -#line 2017 "dtc-parser.tab.c" /* yacc.c:1646 */ +#line 2031 "dtc-parser.tab.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2248,7 +2262,7 @@ yyreturn: #endif return yyresult; } -#line 472 "dtc-parser.y" /* yacc.c:1906 */ +#line 488 "dtc-parser.y" /* yacc.c:1906 */ void yyerror(char const *s) diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 5a897e36562d..000873f070fd 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -410,8 +410,24 @@ integer_add: integer_mul: integer_mul '*' integer_unary { $$ = $1 * $3; } - | integer_mul '/' integer_unary { $$ = $1 / $3; } - | integer_mul '%' integer_unary { $$ = $1 % $3; } + | integer_mul '/' integer_unary + { + if ($3 != 0) { + $$ = $1 / $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } + | integer_mul '%' integer_unary + { + if ($3 != 0) { + $$ = $1 % $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } | integer_unary ; diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index 8c4add69a765..5fa23c406266 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -18,6 +18,8 @@ * USA */ +#include + #include "dtc.h" #include "srcpos.h" @@ -104,11 +106,56 @@ static const char * const usage_opts_help[] = { NULL, }; +static const char *guess_type_by_name(const char *fname, const char *fallback) +{ + const char *s; + + s = strrchr(fname, '.'); + if (s == NULL) + return fallback; + if (!strcasecmp(s, ".dts")) + return "dts"; + if (!strcasecmp(s, ".dtb")) + return "dtb"; + return fallback; +} + +static const char *guess_input_format(const char *fname, const char *fallback) +{ + struct stat statbuf; + uint32_t magic; + FILE *f; + + if (stat(fname, &statbuf) != 0) + return fallback; + + if (S_ISDIR(statbuf.st_mode)) + return "fs"; + + if (!S_ISREG(statbuf.st_mode)) + return fallback; + + f = fopen(fname, "r"); + if (f == NULL) + return fallback; + if (fread(&magic, 4, 1, f) != 1) { + fclose(f); + return fallback; + } + fclose(f); + + magic = fdt32_to_cpu(magic); + if (magic == FDT_MAGIC) + return "dtb"; + + return guess_type_by_name(fname, fallback); +} + int main(int argc, char *argv[]) { struct boot_info *bi; - const char *inform = "dts"; - const char *outform = "dts"; + const char *inform = NULL; + const char *outform = NULL; const char *outname = "-"; const char *depname = NULL; bool force = false, sort = false; @@ -213,6 +260,17 @@ int main(int argc, char *argv[]) fprintf(depfile, "%s:", outname); } + if (inform == NULL) + inform = guess_input_format(arg, "dts"); + if (outform == NULL) { + outform = guess_type_by_name(outname, NULL); + if (outform == NULL) { + if (streq(inform, "dts")) + outform = "dtb"; + else + outform = "dts"; + } + } if (streq(inform, "dts")) bi = dt_from_source(arg); else if (streq(inform, "fs")) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 2ce6a44179de..22286a1aaeaf 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { - const char *p; + unsigned absoffset = offset + fdt_off_dt_struct(fdt); + + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; - p = _fdt_offset_ptr(fdt, offset); - - if (p + len < p) - return NULL; - return p; + return _fdt_offset_ptr(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index a65e4b5b72b6..e5b313682007 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -538,6 +538,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) return 0; } +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return -length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return -length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 70adec6c371b..8be02b1f68f3 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + return -FDT_ERR_BADOFFSET; if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) return -FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index ea35ac3c9be4..59ca33976e56 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -121,7 +121,12 @@ /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells * or similar property with a bad format or value */ -#define FDT_ERR_MAX 14 +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_MAX 15 /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -457,8 +462,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, * @namelen: number of characters of name to consider * @lenp: pointer to an integer variable (will be overwritten) or NULL * - * Identical to fdt_get_property_namelen(), but only examine the first - * namelen characters of name for matching the property name. + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. */ const struct fdt_property *fdt_get_property_namelen(const void *fdt, int nodeoffset, @@ -868,6 +873,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, */ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @return: + * the number of strings in the given property + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @return: + * the index of the string in the list of strings + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist or does not contain + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @return: + * A pointer to the string at the given index in the string list or NULL on + * failure. On success the length of the string will be stored in the memory + * location pointed to by the lenp parameter, if non-NULL. On failure one of + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + /**********************************************************************/ /* Read-only functions (addressing related) */ /**********************************************************************/ diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 9d65226df9e4..fb124eea4919 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -152,7 +152,6 @@ char get_escape_char(const char *s, int *i) int j = *i + 1; char val; - assert(c); switch (c) { case 'a': val = '\a'; @@ -349,7 +348,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) void utilfdt_print_data(const char *data, int len) { int i; - const char *p = data; const char *s; /* no data, don't print */ @@ -376,6 +374,7 @@ void utilfdt_print_data(const char *data, int len) i < (len - 1) ? " " : ""); printf(">"); } else { + const unsigned char *p = (const unsigned char *)data; printf(" = ["); for (i = 0; i < len; i++) printf("%02x%s", *p++, i < len - 1 ? " " : ""); diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 5b8c7d53d608..11d93e6d8220 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.1-g9d3649bd" +#define DTC_VERSION "DTC 1.4.1-gb06e55c8" -- cgit From dfdf141429f0895b63c882facc42c86f225033cb Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Mon, 8 Feb 2016 22:04:29 +0100 Subject: nvmem: core: fix error path in nvmem_add_cells() The current code fails to nvmem_cell_drop(cells[0]) - even worse, if the loop above fails already at i==0, we'll enter an essentially infinite loop doing nvmem_cell_drop on cells[-1], cells[-2], ... which is unlikely to end well. Also, we're not freeing the temporary backing array cells on the error path. Signed-off-by: Rasmus Villemoes Signed-off-by: Greg Kroah-Hartman --- drivers/nvmem/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 9d11d9837312..de14fae6f7f6 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -294,9 +294,11 @@ static int nvmem_add_cells(struct nvmem_device *nvmem, return 0; err: - while (--i) + while (i--) nvmem_cell_drop(cells[i]); + kfree(cells); + return rval; } -- cgit From cf09d6428de3aa6bb6a8164d86bc1cc0cd678d8e Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 10 Feb 2016 11:41:08 +0100 Subject: w1: w1_process() is not freezable kthread w1_process() calls try_to_freeze(), but the thread doesn't mark itself freezable through set_freezable(), so the try_to_freeze() call is useless. Acked-by: Evgeniy Polyakov Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index c9a7ff67d395..89a784751738 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -1147,7 +1147,6 @@ int w1_process(void *data) jremain = 1; } - try_to_freeze(); __set_current_state(TASK_INTERRUPTIBLE); /* hold list_mutex until after interruptible to prevent loosing -- cgit From e1379b56e9e88653fcb58cbaa71cd6b1cc304918 Mon Sep 17 00:00:00 2001 From: Cory Tusar Date: Wed, 10 Feb 2016 14:32:07 -0500 Subject: misc: eeprom_93xx46: Add quirks to support Atmel AT93C46D device. Atmel devices in this family have some quirks not found in other similar chips - they do not support a sequential read of the entire EEPROM contents, and the control word sent at the start of each operation varies in bit length. This commit adds quirk support to the driver and modifies the read implementation to support non-sequential reads for consistency with other misc/eeprom drivers. Tested on a custom Freescale VF610-based platform, with an AT93C46D device attached via dspi2. The spi-gpio driver was used to allow the necessary non-byte-sized transfers. Signed-off-by: Cory Tusar Tested-by: Chris Healy Reviewed-by: Vladimir Zapolskiy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 126 ++++++++++++++++++++++++++---------- include/linux/eeprom_93xx46.h | 6 ++ 2 files changed, 97 insertions(+), 35 deletions(-) diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index f0c30b366218..a3c3136abf3e 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -27,6 +27,15 @@ #define ADDR_ERAL 0x20 #define ADDR_EWEN 0x30 +struct eeprom_93xx46_devtype_data { + unsigned int quirks; +}; + +static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { + .quirks = EEPROM_93XX46_QUIRK_SINGLE_WORD_READ | + EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, +}; + struct eeprom_93xx46_dev { struct spi_device *spi; struct eeprom_93xx46_platform_data *pdata; @@ -35,6 +44,16 @@ struct eeprom_93xx46_dev { int addrlen; }; +static inline bool has_quirk_single_word_read(struct eeprom_93xx46_dev *edev) +{ + return edev->pdata->quirks & EEPROM_93XX46_QUIRK_SINGLE_WORD_READ; +} + +static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev) +{ + return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH; +} + static ssize_t eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, @@ -42,58 +61,73 @@ eeprom_93xx46_bin_read(struct file *filp, struct kobject *kobj, { struct eeprom_93xx46_dev *edev; struct device *dev; - struct spi_message m; - struct spi_transfer t[2]; - int bits, ret; - u16 cmd_addr; + ssize_t ret = 0; dev = kobj_to_dev(kobj); edev = dev_get_drvdata(dev); - cmd_addr = OP_READ << edev->addrlen; + mutex_lock(&edev->lock); - if (edev->addrlen == 7) { - cmd_addr |= off & 0x7f; - bits = 10; - } else { - cmd_addr |= (off >> 1) & 0x3f; - bits = 9; - } + if (edev->pdata->prepare) + edev->pdata->prepare(edev); - dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", - cmd_addr, edev->spi->max_speed_hz); + while (count) { + struct spi_message m; + struct spi_transfer t[2] = { { 0 } }; + u16 cmd_addr = OP_READ << edev->addrlen; + size_t nbytes = count; + int bits; + int err; + + if (edev->addrlen == 7) { + cmd_addr |= off & 0x7f; + bits = 10; + if (has_quirk_single_word_read(edev)) + nbytes = 1; + } else { + cmd_addr |= (off >> 1) & 0x3f; + bits = 9; + if (has_quirk_single_word_read(edev)) + nbytes = 2; + } - spi_message_init(&m); - memset(t, 0, sizeof(t)); + dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", + cmd_addr, edev->spi->max_speed_hz); - t[0].tx_buf = (char *)&cmd_addr; - t[0].len = 2; - t[0].bits_per_word = bits; - spi_message_add_tail(&t[0], &m); + spi_message_init(&m); - t[1].rx_buf = buf; - t[1].len = count; - t[1].bits_per_word = 8; - spi_message_add_tail(&t[1], &m); + t[0].tx_buf = (char *)&cmd_addr; + t[0].len = 2; + t[0].bits_per_word = bits; + spi_message_add_tail(&t[0], &m); - mutex_lock(&edev->lock); + t[1].rx_buf = buf; + t[1].len = count; + t[1].bits_per_word = 8; + spi_message_add_tail(&t[1], &m); - if (edev->pdata->prepare) - edev->pdata->prepare(edev); + err = spi_sync(edev->spi, &m); + /* have to wait at least Tcsl ns */ + ndelay(250); - ret = spi_sync(edev->spi, &m); - /* have to wait at least Tcsl ns */ - ndelay(250); - if (ret) { - dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n", - count, (int)off, ret); + if (err) { + dev_err(&edev->spi->dev, "read %zu bytes at %d: err. %d\n", + nbytes, (int)off, err); + ret = err; + break; + } + + buf += nbytes; + off += nbytes; + count -= nbytes; + ret += nbytes; } if (edev->pdata->finish) edev->pdata->finish(edev); mutex_unlock(&edev->lock); - return ret ? : count; + return ret; } static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) @@ -112,7 +146,13 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on) bits = 9; } - dev_dbg(&edev->spi->dev, "ew cmd 0x%04x\n", cmd_addr); + if (has_quirk_instruction_length(edev)) { + cmd_addr <<= 2; + bits += 2; + } + + dev_dbg(&edev->spi->dev, "ew%s cmd 0x%04x, %d bits\n", + is_on ? "en" : "ds", cmd_addr, bits); spi_message_init(&m); memset(&t, 0, sizeof(t)); @@ -247,6 +287,13 @@ static int eeprom_93xx46_eral(struct eeprom_93xx46_dev *edev) bits = 9; } + if (has_quirk_instruction_length(edev)) { + cmd_addr <<= 2; + bits += 2; + } + + dev_dbg(&edev->spi->dev, "eral cmd 0x%04x, %d bits\n", cmd_addr, bits); + spi_message_init(&m); memset(&t, 0, sizeof(t)); @@ -298,12 +345,15 @@ static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); static const struct of_device_id eeprom_93xx46_of_table[] = { { .compatible = "eeprom-93xx46", }, + { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, {} }; MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); static int eeprom_93xx46_probe_dt(struct spi_device *spi) { + const struct of_device_id *of_id = + of_match_device(eeprom_93xx46_of_table, &spi->dev); struct device_node *np = spi->dev.of_node; struct eeprom_93xx46_platform_data *pd; u32 tmp; @@ -331,6 +381,12 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) if (of_property_read_bool(np, "read-only")) pd->flags |= EE_READONLY; + if (of_id->data) { + const struct eeprom_93xx46_devtype_data *data = of_id->data; + + pd->quirks = data->quirks; + } + spi->dev.platform_data = pd; return 0; diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h index 06791811e49d..92fa4c37ac1f 100644 --- a/include/linux/eeprom_93xx46.h +++ b/include/linux/eeprom_93xx46.h @@ -9,6 +9,12 @@ struct eeprom_93xx46_platform_data { #define EE_ADDR16 0x02 /* 16 bit addr. cfg */ #define EE_READONLY 0x08 /* forbid writing */ + unsigned int quirks; +/* Single word read transfers only; no sequential read. */ +#define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) +/* Instructions such as EWEN are (addrlen + 2) in length. */ +#define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) + /* * optional hooks to control additional logic * before and after spi transfer. -- cgit From 3ca9b1ac28398c6fe0bed335d2d71a35e1c5f7c9 Mon Sep 17 00:00:00 2001 From: Cory Tusar Date: Wed, 10 Feb 2016 14:32:08 -0500 Subject: misc: eeprom_93xx46: Add support for a GPIO 'select' line. This commit adds support to the eeprom_93x46 driver allowing a GPIO line to function as a 'select' or 'enable' signal prior to accessing the EEPROM. Signed-off-by: Cory Tusar Tested-by: Chris Healy Reviewed-by: Vladimir Zapolskiy Signed-off-by: Greg Kroah-Hartman --- drivers/misc/eeprom/eeprom_93xx46.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/eeprom_93xx46.h | 3 +++ 2 files changed, 38 insertions(+) diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index a3c3136abf3e..f62ab29e293c 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -10,11 +10,13 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -343,6 +345,20 @@ static ssize_t eeprom_93xx46_store_erase(struct device *dev, } static DEVICE_ATTR(erase, S_IWUSR, NULL, eeprom_93xx46_store_erase); +static void select_assert(void *context) +{ + struct eeprom_93xx46_dev *edev = context; + + gpiod_set_value_cansleep(edev->pdata->select, 1); +} + +static void select_deassert(void *context) +{ + struct eeprom_93xx46_dev *edev = context; + + gpiod_set_value_cansleep(edev->pdata->select, 0); +} + static const struct of_device_id eeprom_93xx46_of_table[] = { { .compatible = "eeprom-93xx46", }, { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, @@ -357,6 +373,8 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) struct device_node *np = spi->dev.of_node; struct eeprom_93xx46_platform_data *pd; u32 tmp; + int gpio; + enum of_gpio_flags of_flags; int ret; pd = devm_kzalloc(&spi->dev, sizeof(*pd), GFP_KERNEL); @@ -381,6 +399,23 @@ static int eeprom_93xx46_probe_dt(struct spi_device *spi) if (of_property_read_bool(np, "read-only")) pd->flags |= EE_READONLY; + gpio = of_get_named_gpio_flags(np, "select-gpios", 0, &of_flags); + if (gpio_is_valid(gpio)) { + unsigned long flags = + of_flags == OF_GPIO_ACTIVE_LOW ? GPIOF_ACTIVE_LOW : 0; + + ret = devm_gpio_request_one(&spi->dev, gpio, flags, + "eeprom_93xx46_select"); + if (ret) + return ret; + + pd->select = gpio_to_desc(gpio); + pd->prepare = select_assert; + pd->finish = select_deassert; + + gpiod_direction_output(pd->select, 0); + } + if (of_id->data) { const struct eeprom_93xx46_devtype_data *data = of_id->data; diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h index 92fa4c37ac1f..885f587a3555 100644 --- a/include/linux/eeprom_93xx46.h +++ b/include/linux/eeprom_93xx46.h @@ -3,6 +3,8 @@ * platform description for 93xx46 EEPROMs. */ +struct gpio_desc; + struct eeprom_93xx46_platform_data { unsigned char flags; #define EE_ADDR8 0x01 /* 8 bit addr. cfg */ @@ -21,4 +23,5 @@ struct eeprom_93xx46_platform_data { */ void (*prepare)(void *); void (*finish)(void *); + struct gpio_desc *select; }; -- cgit From 6cbb097fd3903fd6b419303ee8dc7f72b47d06f0 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Wed, 10 Feb 2016 23:57:26 +0200 Subject: mei: fix double freeing of a cb during link reset Fix double freeing of the cb that can happen if link reset kicks in the middle of blocked write from a device on the cl bus. Free cb inside mei_cl_write function on failure and drop cb free operation from callers, during a link reset the mei_cl_write function returns with an error, but the caller doesn't know if the cb was already queued or not so it doesn't know if the cb will be freed upon queue reclaim or it has to free it itself. Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/bus.c | 4 +--- drivers/misc/mei/client.c | 4 +++- drivers/misc/mei/main.c | 26 ++++++++++---------------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index f4cf43b47c7a..5d5996e39a67 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -44,7 +44,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, bool blocking) { struct mei_device *bus; - struct mei_cl_cb *cb = NULL; + struct mei_cl_cb *cb; ssize_t rets; if (WARN_ON(!cl || !cl->dev)) @@ -86,8 +86,6 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, out: mutex_unlock(&bus->device_lock); - if (rets < 0) - mei_io_cb_free(cb); return rets; } diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index af6816bc268f..a9cdb92b52d1 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1645,7 +1645,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) if (rets < 0 && rets != -EINPROGRESS) { pm_runtime_put_noidle(dev->dev); cl_err(dev, cl, "rpm: get failed %d\n", rets); - return rets; + goto free; } cb->buf_idx = 0; @@ -1724,6 +1724,8 @@ err: cl_dbg(dev, cl, "rpm: autosuspend\n"); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); +free: + mei_io_cb_free(cb); return rets; } diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 17970163eacc..05775a6f7c88 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -267,7 +267,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, size_t length, loff_t *offset) { struct mei_cl *cl = file->private_data; - struct mei_cl_cb *write_cb = NULL; + struct mei_cl_cb *cb; struct mei_device *dev; int rets; @@ -305,36 +305,30 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, } *offset = 0; - write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); - if (!write_cb) { + cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); + if (!cb) { rets = -ENOMEM; goto out; } - rets = copy_from_user(write_cb->buf.data, ubuf, length); + rets = copy_from_user(cb->buf.data, ubuf, length); if (rets) { dev_dbg(dev->dev, "failed to copy data from userland\n"); rets = -EFAULT; + mei_io_cb_free(cb); goto out; } if (cl == &dev->iamthif_cl) { - rets = mei_amthif_write(cl, write_cb); - - if (rets) { - dev_err(dev->dev, - "amthif write failed with status = %d\n", rets); - goto out; - } - mutex_unlock(&dev->device_lock); - return length; + rets = mei_amthif_write(cl, cb); + if (!rets) + rets = length; + goto out; } - rets = mei_cl_write(cl, write_cb, false); + rets = mei_cl_write(cl, cb, false); out: mutex_unlock(&dev->device_lock); - if (rets < 0) - mei_io_cb_free(write_cb); return rets; } -- cgit From bea7433bac02b1fcee71494b3939e9feed2790cf Mon Sep 17 00:00:00 2001 From: Daniel Chromik Date: Thu, 11 Feb 2016 13:29:23 +0100 Subject: misc: panel, convert struct to bitmap There is an anonymous struct which is actually used as a bitmap. So convert the struct to a bitmap and change code accordingly where needed. This also allows for a cleanup of set_data_bits and set_ctrl_bits as they can use a common helper now. The helper can also be converted to a for loop instead of doing bit OR. And given it is a for loop now, bit masking (using BIT_MSK) is moved from the callers there too. Signed-off-by: Daniel Chromik Signed-off-by: Jiri Slaby Cc: Ksenija Stanojevic Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/misc/panel.c | 87 ++++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/drivers/misc/panel.c b/drivers/misc/panel.c index 4262db0237f9..6030ac5b8c63 100644 --- a/drivers/misc/panel.c +++ b/drivers/misc/panel.c @@ -648,34 +648,28 @@ static const char nexcom_keypad_profile[][4][9] = { static const char (*keypad_profile)[4][9] = old_keypad_profile; -/* FIXME: this should be converted to a bit array containing signals states */ -static struct { - unsigned char e; /* parallel LCD E (data latch on falling edge) */ - unsigned char rs; /* parallel LCD RS (0 = cmd, 1 = data) */ - unsigned char rw; /* parallel LCD R/W (0 = W, 1 = R) */ - unsigned char bl; /* parallel LCD backlight (0 = off, 1 = on) */ - unsigned char cl; /* serial LCD clock (latch on rising edge) */ - unsigned char da; /* serial LCD data */ -} bits; +static DECLARE_BITMAP(bits, LCD_BITS); + +static void lcd_get_bits(unsigned int port, int *val) +{ + unsigned int bit, state; + + for (bit = 0; bit < LCD_BITS; bit++) { + state = test_bit(bit, bits) ? BIT_SET : BIT_CLR; + *val &= lcd_bits[port][bit][BIT_MSK]; + *val |= lcd_bits[port][bit][state]; + } +} static void init_scan_timer(void); /* sets data port bits according to current signals values */ static int set_data_bits(void) { - int val, bit; + int val; val = r_dtr(pprt); - for (bit = 0; bit < LCD_BITS; bit++) - val &= lcd_bits[LCD_PORT_D][bit][BIT_MSK]; - - val |= lcd_bits[LCD_PORT_D][LCD_BIT_E][bits.e] - | lcd_bits[LCD_PORT_D][LCD_BIT_RS][bits.rs] - | lcd_bits[LCD_PORT_D][LCD_BIT_RW][bits.rw] - | lcd_bits[LCD_PORT_D][LCD_BIT_BL][bits.bl] - | lcd_bits[LCD_PORT_D][LCD_BIT_CL][bits.cl] - | lcd_bits[LCD_PORT_D][LCD_BIT_DA][bits.da]; - + lcd_get_bits(LCD_PORT_D, &val); w_dtr(pprt, val); return val; } @@ -683,19 +677,10 @@ static int set_data_bits(void) /* sets ctrl port bits according to current signals values */ static int set_ctrl_bits(void) { - int val, bit; + int val; val = r_ctr(pprt); - for (bit = 0; bit < LCD_BITS; bit++) - val &= lcd_bits[LCD_PORT_C][bit][BIT_MSK]; - - val |= lcd_bits[LCD_PORT_C][LCD_BIT_E][bits.e] - | lcd_bits[LCD_PORT_C][LCD_BIT_RS][bits.rs] - | lcd_bits[LCD_PORT_C][LCD_BIT_RW][bits.rw] - | lcd_bits[LCD_PORT_C][LCD_BIT_BL][bits.bl] - | lcd_bits[LCD_PORT_C][LCD_BIT_CL][bits.cl] - | lcd_bits[LCD_PORT_C][LCD_BIT_DA][bits.da]; - + lcd_get_bits(LCD_PORT_C, &val); w_ctr(pprt, val); return val; } @@ -791,12 +776,17 @@ static void lcd_send_serial(int byte) * LCD reads D0 on STROBE's rising edge. */ for (bit = 0; bit < 8; bit++) { - bits.cl = BIT_CLR; /* CLK low */ + clear_bit(LCD_BIT_CL, bits); /* CLK low */ panel_set_bits(); - bits.da = byte & 1; + if (byte & 1) { + set_bit(LCD_BIT_DA, bits); + } else { + clear_bit(LCD_BIT_DA, bits); + } + panel_set_bits(); udelay(2); /* maintain the data during 2 us before CLK up */ - bits.cl = BIT_SET; /* CLK high */ + set_bit(LCD_BIT_CL, bits); /* CLK high */ panel_set_bits(); udelay(1); /* maintain the strobe during 1 us */ byte >>= 1; @@ -811,7 +801,10 @@ static void lcd_backlight(int on) /* The backlight is activated by setting the AUTOFEED line to +5V */ spin_lock_irq(&pprt_lock); - bits.bl = on; + if (on) + set_bit(LCD_BIT_BL, bits); + else + clear_bit(LCD_BIT_BL, bits); panel_set_bits(); spin_unlock_irq(&pprt_lock); } @@ -846,14 +839,14 @@ static void lcd_write_cmd_p8(int cmd) w_dtr(pprt, cmd); udelay(20); /* maintain the data during 20 us before the strobe */ - bits.e = BIT_SET; - bits.rs = BIT_CLR; - bits.rw = BIT_CLR; + set_bit(LCD_BIT_E, bits); + clear_bit(LCD_BIT_RS, bits); + clear_bit(LCD_BIT_RW, bits); set_ctrl_bits(); udelay(40); /* maintain the strobe during 40 us */ - bits.e = BIT_CLR; + clear_bit(LCD_BIT_E, bits); set_ctrl_bits(); udelay(120); /* the shortest command takes at least 120 us */ @@ -868,14 +861,14 @@ static void lcd_write_data_p8(int data) w_dtr(pprt, data); udelay(20); /* maintain the data during 20 us before the strobe */ - bits.e = BIT_SET; - bits.rs = BIT_SET; - bits.rw = BIT_CLR; + set_bit(LCD_BIT_E, bits); + set_bit(LCD_BIT_RS, bits); + clear_bit(LCD_BIT_RW, bits); set_ctrl_bits(); udelay(40); /* maintain the strobe during 40 us */ - bits.e = BIT_CLR; + clear_bit(LCD_BIT_E, bits); set_ctrl_bits(); udelay(45); /* the shortest data takes at least 45 us */ @@ -968,15 +961,15 @@ static void lcd_clear_fast_p8(void) /* maintain the data during 20 us before the strobe */ udelay(20); - bits.e = BIT_SET; - bits.rs = BIT_SET; - bits.rw = BIT_CLR; + set_bit(LCD_BIT_E, bits); + set_bit(LCD_BIT_RS, bits); + clear_bit(LCD_BIT_RW, bits); set_ctrl_bits(); /* maintain the strobe during 40 us */ udelay(40); - bits.e = BIT_CLR; + clear_bit(LCD_BIT_E, bits); set_ctrl_bits(); /* the shortest data takes at least 45 us */ -- cgit From 9b3ec23ae9e4cd810f754c4cb9bff030a3a9d3ac Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Thu, 11 Feb 2016 12:19:03 +0100 Subject: firmware: qemu_fw_cfg.c: fix typo FW_CFG_DATA_OFF s/FW_CTRL_DATA_OFF/FW_CFG_DATA_OFF/ Signed-off-by: Valentin Rothberg Signed-off-by: Andreas Ziegler Acked-by: Gabriel Somlo Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/qemu_fw_cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 19f6851be87f..fedbff55a7f3 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -98,7 +98,7 @@ static void fw_cfg_io_cleanup(void) } /* arch-specific ctrl & data register offsets are not available in ACPI, DT */ -#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CTRL_DATA_OFF)) +#if !(defined(FW_CFG_CTRL_OFF) && defined(FW_CFG_DATA_OFF)) # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) # define FW_CFG_CTRL_OFF 0x08 # define FW_CFG_DATA_OFF 0x00 -- cgit From 1f01063f714692ce5ea675ba2724e07cf9acbfcb Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 9 Feb 2016 18:42:53 +0530 Subject: Staging: lustre: lnet: Remove explicit NULL comparision Replaced explicit NULL comparision with its simplier form. Found using coccinelle: @replace_rule@ expression e; @@ -e == NULL + !e Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/lib-md.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 758f5bedef7e..b3d8364b07ba 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -184,7 +184,7 @@ lnet_md_link(lnet_libmd_t *md, lnet_handle_eq_t eq_handle, int cpt) if (!LNetHandleIsInvalid(eq_handle)) { md->md_eq = lnet_handle2eq(&eq_handle); - if (md->md_eq == NULL) + if (!md->md_eq) return -ENOENT; (*md->md_eq->eq_refs[cpt])++; @@ -221,7 +221,7 @@ lnet_md_deconstruct(lnet_libmd_t *lmd, lnet_md_t *umd) static int lnet_md_validate(lnet_md_t *umd) { - if (umd->start == NULL && umd->length != 0) { + if (!umd->start && umd->length != 0) { CERROR("MD start pointer can not be NULL with length %u\n", umd->length); return -EINVAL; @@ -285,7 +285,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, } md = lnet_md_alloc(&umd); - if (md == NULL) + if (!md) return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); @@ -296,7 +296,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, goto failed; me = lnet_handle2me(&meh); - if (me == NULL) + if (!me) rc = -ENOENT; else if (me->me_md != NULL) rc = -EBUSY; @@ -362,7 +362,7 @@ LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle) } md = lnet_md_alloc(&umd); - if (md == NULL) + if (!md) return -ENOMEM; rc = lnet_md_build(md, &umd, unlink); @@ -432,7 +432,7 @@ LNetMDUnlink(lnet_handle_md_t mdh) lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (md == NULL) { + if (!md) { lnet_res_unlock(cpt); return -ENOENT; } -- cgit From a1fcca1e9afd5e2ec64be63574b548974b391d3c Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Wed, 10 Feb 2016 14:13:47 +0530 Subject: staging: lustre: lov_pool: Fixed a return coding style warning. Remove unusefull return at the end of void function. WARNING: void function return statements are not generally useful. Signed-off-by: Rakhi Sharma Changes in v3: shortened the subject line and make the discription more clear. Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/lov/lov_pool.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c index b43ce6cd64c2..3ee1d4041368 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pool.c +++ b/drivers/staging/lustre/lustre/lov/lov_pool.c @@ -247,7 +247,6 @@ static void pool_proc_stop(struct seq_file *s, void *v) lov_pool_putref(iter->pool); kfree(iter); } - return; } static int pool_proc_show(struct seq_file *s, void *v) -- cgit From a4e872f7b629c9f5a4f83bb2a84ece91b89ade67 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Wed, 10 Feb 2016 22:47:33 -0500 Subject: staging: lustre: Modify arguments of sizeof() to pointer variables Take the size of a dereference to a variable rather than the associated type, to make the code more resistant to type changes in the future. The type of the pointer variable here is the same as the type in the argument that is being replaced in sizeof(). Signed-off-by: Janani Ravichandran Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index cb74ae731b95..49cd333a8865 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1352,7 +1352,7 @@ static void kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool) if (pool->fpo_hdev != NULL) kiblnd_hdev_decref(pool->fpo_hdev); - LIBCFS_FREE(pool, sizeof(kib_fmr_pool_t)); + LIBCFS_FREE(pool, sizeof(*pool)); } static void kiblnd_destroy_fmr_pool_list(struct list_head *head) @@ -1410,7 +1410,7 @@ static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, CERROR("Failed to create FMR pool: %d\n", rc); kiblnd_hdev_decref(fpo->fpo_hdev); - LIBCFS_FREE(fpo, sizeof(kib_fmr_pool_t)); + LIBCFS_FREE(fpo, sizeof(*fpo)); return rc; } @@ -1458,7 +1458,7 @@ static int kiblnd_init_fmr_poolset(kib_fmr_poolset_t *fps, int cpt, kib_fmr_pool_t *fpo; int rc; - memset(fps, 0, sizeof(kib_fmr_poolset_t)); + memset(fps, 0, sizeof(*fps)); fps->fps_net = net; fps->fps_cpt = cpt; @@ -1606,7 +1606,7 @@ static void kiblnd_init_pool(kib_poolset_t *ps, kib_pool_t *pool, int size) { CDEBUG(D_NET, "Initialize %s pool\n", ps->ps_name); - memset(pool, 0, sizeof(kib_pool_t)); + memset(pool, 0, sizeof(*pool)); INIT_LIST_HEAD(&pool->po_free_list); pool->po_deadline = cfs_time_shift(IBLND_POOL_DEADLINE); pool->po_owner = ps; @@ -1663,7 +1663,7 @@ static int kiblnd_init_poolset(kib_poolset_t *ps, int cpt, kib_pool_t *pool; int rc; - memset(ps, 0, sizeof(kib_poolset_t)); + memset(ps, 0, sizeof(*ps)); ps->ps_cpt = cpt; ps->ps_net = net; @@ -1834,7 +1834,7 @@ static void kiblnd_destroy_tx_pool(kib_pool_t *pool) pool->po_size * sizeof(kib_tx_t)); out: kiblnd_fini_pool(pool); - LIBCFS_FREE(tpo, sizeof(kib_tx_pool_t)); + LIBCFS_FREE(tpo, sizeof(*tpo)); } static int kiblnd_tx_pool_size(int ncpts) @@ -1866,7 +1866,7 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, npg = (size * IBLND_MSG_SIZE + PAGE_SIZE - 1) / PAGE_SIZE; if (kiblnd_alloc_pages(&tpo->tpo_tx_pages, ps->ps_cpt, npg) != 0) { CERROR("Can't allocate tx pages: %d\n", npg); - LIBCFS_FREE(tpo, sizeof(kib_tx_pool_t)); + LIBCFS_FREE(tpo, sizeof(*tpo)); return -ENOMEM; } -- cgit From 61ece0e60d5db836dcec2707c3c89bc83ac2046d Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 10 Feb 2016 13:00:18 -0500 Subject: staging/lustre/obdecho: Remove always true condition Dan Carpenter noticed that since we already checked for (oa->o_valid & OBD_MD_FLID) == 0, that means (oa->o_valid & OBD_MD_FLID) is always true after that so no point in checking for it. Signed-off-by: Oleg Drokin Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdecho/echo_client.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index d3e398f70434..e1c9d118e037 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1222,10 +1222,8 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, } /* setup object ID here */ - if (oa->o_valid & OBD_MD_FLID) { - LASSERT(oa->o_valid & OBD_MD_FLGROUP); - lsm->lsm_oi = oa->o_oi; - } + LASSERT(oa->o_valid & OBD_MD_FLGROUP); + lsm->lsm_oi = oa->o_oi; if (ostid_id(&lsm->lsm_oi) == 0) ostid_set_id(&lsm->lsm_oi, ++last_object_id); -- cgit From 01de911e140cedc64244e159cd092ff276522b39 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 10 Feb 2016 13:00:19 -0500 Subject: staging/lustre/obdecho: Better handle invalid create requests When gettng an invalid create request in echo code (wrong group, or no group at all), just return an error instead of crashing. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdecho/echo_client.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index e1c9d118e037..4ca82afaf157 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1210,8 +1210,10 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, int rc; int created = 0; - if ((oa->o_valid & OBD_MD_FLID) == 0) { /* no obj id */ - CERROR("No valid oid\n"); + if (!(oa->o_valid & OBD_MD_FLID) || + !(oa->o_valid & OBD_MD_FLGROUP) || + !fid_seq_is_echo(ostid_seq(&oa->o_oi))) { + CERROR("invalid oid " DOSTID "\n", POSTID(&oa->o_oi)); return -EINVAL; } @@ -1222,16 +1224,11 @@ static int echo_create_object(const struct lu_env *env, struct echo_device *ed, } /* setup object ID here */ - LASSERT(oa->o_valid & OBD_MD_FLGROUP); lsm->lsm_oi = oa->o_oi; if (ostid_id(&lsm->lsm_oi) == 0) ostid_set_id(&lsm->lsm_oi, ++last_object_id); - /* Only echo objects are allowed to be created */ - LASSERT((oa->o_valid & OBD_MD_FLGROUP) && - (ostid_seq(&oa->o_oi) == FID_SEQ_ECHO)); - rc = obd_create(env, ec->ec_exp, oa, &lsm, oti); if (rc != 0) { CERROR("Cannot create objects: rc = %d\n", rc); -- cgit From f3fe3718d83f0f356fbd900170b8c3e9b5817337 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 10 Feb 2016 13:00:20 -0500 Subject: staging/lustre: Adjust import state history output format New test scripts expect spaces around state names and square brackets when parsing debugfs output, so add them to avoid false failures. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/lprocfs_status.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c index 9a1434d89d57..eda44d89ffeb 100644 --- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c +++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c @@ -642,21 +642,21 @@ int lprocfs_rd_import(struct seq_file *m, void *data) " target: %s\n" " state: %s\n" " instance: %u\n" - " connect_flags: [", + " connect_flags: [ ", obd->obd_name, obd2cli_tgt(obd), ptlrpc_import_state_name(imp->imp_state), imp->imp_connect_data.ocd_instance); obd_connect_seq_flags2str(m, imp->imp_connect_data.ocd_connect_flags, ", "); seq_printf(m, - "]\n" - " import_flags: ["); + " ]\n" + " import_flags: [ "); obd_import_flags2str(imp, m); seq_printf(m, - "]\n" + " ]\n" " connection:\n" - " failover_nids: ["); + " failover_nids: [ "); spin_lock(&imp->imp_lock); j = 0; list_for_each_entry(conn, &imp->imp_conn_list, oic_item) { @@ -671,7 +671,7 @@ int lprocfs_rd_import(struct seq_file *m, void *data) else strncpy(nidstr, "", sizeof(nidstr)); seq_printf(m, - "]\n" + " ]\n" " current_connection: %s\n" " connection_attempts: %u\n" " generation: %u\n" @@ -795,7 +795,7 @@ int lprocfs_rd_state(struct seq_file *m, void *data) &imp->imp_state_hist[(k + j) % IMP_STATE_HIST_LEN]; if (ish->ish_state == 0) continue; - seq_printf(m, " - [%lld, %s]\n", (s64)ish->ish_time, + seq_printf(m, " - [ %lld, %s ]\n", (s64)ish->ish_time, ptlrpc_import_state_name(ish->ish_state)); } -- cgit From ccaeef6c4c2b09aa15822063a3be9ef9fe38a4a6 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 10 Feb 2016 13:00:21 -0500 Subject: staging/lustre: Update internal client version. While initial code drop was corresponding to 2.3.64, lots of different changes went in since then, and also quite a bunch of fixes, but almost none of the new features. Code-wise we are almost at 2.5.0, so let's call it 2.4.60 - this is a version that was never reached in the actual pre-2.5 development, so it should be a clear distinction of where we are now. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_ver.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_ver.h b/drivers/staging/lustre/lustre/include/lustre_ver.h index caa4da12f37a..01205b8e06fd 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ver.h +++ b/drivers/staging/lustre/lustre/include/lustre_ver.h @@ -1,14 +1,11 @@ #ifndef _LUSTRE_VER_H_ #define _LUSTRE_VER_H_ -/* This file automatically generated from lustre/include/lustre_ver.h.in, - * based on parameters in lustre/autoconf/lustre-version.ac. - * Changes made directly to this file will be lost. */ #define LUSTRE_MAJOR 2 -#define LUSTRE_MINOR 3 -#define LUSTRE_PATCH 64 +#define LUSTRE_MINOR 4 +#define LUSTRE_PATCH 60 #define LUSTRE_FIX 0 -#define LUSTRE_VERSION_STRING "2.3.64" +#define LUSTRE_VERSION_STRING "2.4.60" #define LUSTRE_VERSION_CODE OBD_OCD_VERSION(LUSTRE_MAJOR, \ LUSTRE_MINOR, LUSTRE_PATCH, \ -- cgit From 59ca8f20b19b652d6961c3f78ccc7aab149a1930 Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Wed, 10 Feb 2016 13:00:22 -0500 Subject: staging/lustre: Remove unused LUSTRE_VERSION_ALLOWED_OFFSET define LUSTRE_VERSION_ALLOWED_OFFSET is only used on the server to disallow connection of old userspace clients. Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/include/lustre_ver.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/lustre/lustre/include/lustre_ver.h b/drivers/staging/lustre/lustre/include/lustre_ver.h index 01205b8e06fd..64559a16f4de 100644 --- a/drivers/staging/lustre/lustre/include/lustre_ver.h +++ b/drivers/staging/lustre/lustre/include/lustre_ver.h @@ -11,13 +11,10 @@ LUSTRE_MINOR, LUSTRE_PATCH, \ LUSTRE_FIX) -/* liblustre clients are only allowed to connect if their LUSTRE_FIX mismatches - * by this amount (set in lustre/autoconf/lustre-version.ac). */ -#define LUSTRE_VERSION_ALLOWED_OFFSET OBD_OCD_VERSION(0, 0, 1, 32) - -/* If lustre version of client and servers it connects to differs by more +/* + * If lustre version of client and servers it connects to differs by more * than this amount, client would issue a warning. - * (set in lustre/autoconf/lustre-version.ac) */ + */ #define LUSTRE_VERSION_OFFSET_WARN OBD_OCD_VERSION(0, 4, 0, 0) #endif -- cgit From d99ee289b4acf29770a33f76c7f98b466f70e91d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 10 Feb 2016 12:05:40 +0300 Subject: staging: wilc1000: fix mgmt_tx() There was a missing curly brace so this function returns failure instead of succeeding. Fixes: 06fb9336acdc ('staging: wilc1000: wilc_wfi_cfgoperations.c: replaces PRINT_ER with netdev_err') Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index bf264d3657be..97d1b802a75e 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -1832,9 +1832,10 @@ static int mgmt_tx(struct wiphy *wiphy, return -EFAULT; mgmt_tx->buff = kmalloc(buf_len, GFP_KERNEL); - if (!mgmt_tx->buff) + if (!mgmt_tx->buff) { kfree(mgmt_tx); - return -EFAULT; + return -ENOMEM; + } memcpy(mgmt_tx->buff, buf, len); mgmt_tx->size = len; -- cgit From 6e944459aa868a274d07a50b3c7b774387624d94 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 11 Feb 2016 13:46:22 +0900 Subject: staging: wilc1000: fix return type of wilc_send_config_pkt wilc_send_config_pkt is returned 0 or -ETIMEDOUT according to return value of wilc_wlan_cfg_set or wilc_wlan_cfg_set. It is better to use int type to represent linux standard error code. 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, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 98b21d492720..2bc2970d7576 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1349,10 +1349,11 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) return ret; } -s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, +int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv) { - s32 counter = 0, ret = 0; + s32 counter = 0; + int ret = 0; if (mode == GET_CFG) { for (counter = 0; counter < count; counter++) { diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h index d362fa8512cf..06d02abd49a4 100644 --- a/drivers/staging/wilc1000/wilc_wlan.h +++ b/drivers/staging/wilc1000/wilc_wlan.h @@ -301,6 +301,6 @@ void host_sleep_notify(struct wilc *wilc); extern bool wilc_enable_ps; void chip_allow_sleep(struct wilc *wilc); void chip_wakeup(struct wilc *wilc); -s32 wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, +int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv); #endif -- cgit From 67ba5d6d6e12495f6c2f6ed260d13f4cf77caf1e Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 11 Feb 2016 13:46:23 +0900 Subject: staging: wilc1000: use int type for counter variable counter is used as for-loop control variable and indicating index of struct wid array so that it is better to use int type. There is no need to set to 0 when it is declared at the top of this function. It is initialized as 0 in for-loop statement. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 2bc2970d7576..f3140e0f284e 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1352,7 +1352,7 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv) { - s32 counter = 0; + int counter; int ret = 0; if (mode == GET_CFG) { -- cgit From f752fa468ad14fb772ff8611c649e8224c3796fd Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 11 Feb 2016 13:46:24 +0900 Subject: staging: wilc1000: remove initialization code of counter variable There is no need to set to 0 for counter variable before entering next for-loop statement because counter is initialized again in for-loop statement, so just remove it. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index f3140e0f284e..c6bfec39864c 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1365,7 +1365,6 @@ int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, break; } } - counter = 0; for (counter = 0; counter < count; counter++) { wids[counter].size = wilc_wlan_cfg_get_val( wids[counter].id, -- cgit From b3306362b89880da4d7c3280009da946ba42e762 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Thu, 11 Feb 2016 13:46:25 +0900 Subject: staging: wilc1000: rename counter in wilc_send_config_pkt This patch renames the name of counter variable to i. This change makes more readability because wilc_send_config_pkt has a similar argument name as count. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index c6bfec39864c..8712edaf0bb7 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -1352,32 +1352,31 @@ int wilc_wlan_cfg_get_val(u32 wid, u8 *buffer, u32 buffer_size) int wilc_send_config_pkt(struct wilc_vif *vif, u8 mode, struct wid *wids, u32 count, u32 drv) { - int counter; + int i; int ret = 0; if (mode == GET_CFG) { - for (counter = 0; counter < count; counter++) { - if (!wilc_wlan_cfg_get(vif, !counter, - wids[counter].id, - (counter == count - 1), + for (i = 0; i < count; i++) { + if (!wilc_wlan_cfg_get(vif, !i, + wids[i].id, + (i == count - 1), drv)) { ret = -ETIMEDOUT; break; } } - for (counter = 0; counter < count; counter++) { - wids[counter].size = wilc_wlan_cfg_get_val( - wids[counter].id, - wids[counter].val, - wids[counter].size); + for (i = 0; i < count; i++) { + wids[i].size = wilc_wlan_cfg_get_val(wids[i].id, + wids[i].val, + wids[i].size); } } else if (mode == SET_CFG) { - for (counter = 0; counter < count; counter++) { - if (!wilc_wlan_cfg_set(vif, !counter, - wids[counter].id, - wids[counter].val, - wids[counter].size, - (counter == count - 1), + for (i = 0; i < count; i++) { + if (!wilc_wlan_cfg_set(vif, !i, + wids[i].id, + wids[i].val, + wids[i].size, + (i == count - 1), drv)) { ret = -ETIMEDOUT; break; -- cgit From e682e91b61f879f1e3b07813b7541c37b337bdfb Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 10 Feb 2016 21:34:41 -0800 Subject: staging: wilc1000: remove parentheses on right hand side of assignment Remove the unnecessary parens on right hand side of assignment. Found using Coccinelle: @@ identifier x; expression e1, e2; @@ - x = (e1 << e2) + x = e1 << e2 Signed-off-by: Alison Schofield Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c index 8712edaf0bb7..a396ac92a650 100644 --- a/drivers/staging/wilc1000/wilc_wlan.c +++ b/drivers/staging/wilc1000/wilc_wlan.c @@ -921,11 +921,11 @@ static void wilc_wlan_handle_isr_ext(struct wilc *wilc, u32 int_status) int ret = 0; struct rxq_entry_t *rqe; - size = ((int_status & 0x7fff) << 2); + size = (int_status & 0x7fff) << 2; while (!size && retries < 10) { wilc->hif_func->hif_read_size(wilc, &size); - size = ((size & 0x7fff) << 2); + size = (size & 0x7fff) << 2; retries++; } -- cgit From 5343c7bb0a67325c8a0012324e26b11625544686 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 16:41:21 -0500 Subject: staging: wilc1000: Remove unneeded parentheses in assignment Remove parentheses around the right hand side of assignments. They are unnecessary. Semantic patch: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_sdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c index 7c20c8c9c2bc..963875afc48f 100644 --- a/drivers/staging/wilc1000/wilc_sdio.c +++ b/drivers/staging/wilc1000/wilc_sdio.c @@ -676,7 +676,7 @@ static int sdio_init(struct wilc *wilc, bool resume) if (!resume) { memset(&g_sdio, 0, sizeof(wilc_sdio_t)); - g_sdio.irq_gpio = (wilc->dev_irq_num); + g_sdio.irq_gpio = wilc->dev_irq_num; } /** -- cgit From bb6b03de3f5456a3d48a9de83eb3411d0b0ba395 Mon Sep 17 00:00:00 2001 From: "Roger H. Newell" Date: Thu, 11 Feb 2016 16:51:10 -0330 Subject: staging: wilc1000: spelling corrections This patch fixes spelling warnings generated by checkpatch.pl Signed-off-by: Roger H. Newell Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index c42286a7bab9..5570707b7376 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -543,7 +543,7 @@ static s32 handle_cfg_param(struct wilc_vif *vif, wid_list[wid_cnt].size = sizeof(char); hif_drv->cfg_values.power_mgmt_mode = (u8)cfg_param_attr->cfg_attr_info.power_mgmt_mode; } else { - PRINT_ER("Invalide power mode\n"); + PRINT_ER("Invalid power mode\n"); result = -EINVAL; goto ERRORHANDLER; } @@ -881,7 +881,7 @@ static s32 Handle_Scan(struct wilc_vif *vif, wilc_get_vif_idx(vif)); if (result) - PRINT_ER("Failed to send scan paramters config packet\n"); + PRINT_ER("Failed to send scan parameters config packet\n"); ERRORHANDLER: if (result) { @@ -2081,7 +2081,7 @@ static s32 Handle_GetStatistics(struct wilc_vif *vif, wilc_get_vif_idx(vif)); if (result) - PRINT_ER("Failed to send scan paramters config packet\n"); + PRINT_ER("Failed to send scan parameters config packet\n"); if (pstrStatistics->link_speed > TCP_ACK_FILTER_LINK_SPEED_THRESH && pstrStatistics->link_speed != DEFAULT_LINK_SPEED) -- cgit From 8052d7dd4ecc1f837f2a07d62f8bc4a89ce16582 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 11 Feb 2016 19:33:46 -0800 Subject: staging: rtl8*: fix my email address up For some reason I had an old linux.com address in these TODO files, point to my linuxfoundation.org address as that works properly here. Reported-by: Luca Ceresoli Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/TODO | 2 +- drivers/staging/rtl8723au/TODO | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/TODO b/drivers/staging/rtl8188eu/TODO index b574b235b340..ce60f07b9977 100644 --- a/drivers/staging/rtl8188eu/TODO +++ b/drivers/staging/rtl8188eu/TODO @@ -15,5 +15,5 @@ TODO: rcu_read_unlock(); Perhaps delete it, perhaps assign to some local variable. -Please send any patches to Greg Kroah-Hartman , +Please send any patches to Greg Kroah-Hartman , and Larry Finger . diff --git a/drivers/staging/rtl8723au/TODO b/drivers/staging/rtl8723au/TODO index 175a0ceb7421..f5d57d32fae6 100644 --- a/drivers/staging/rtl8723au/TODO +++ b/drivers/staging/rtl8723au/TODO @@ -9,5 +9,5 @@ TODO: - merge Realtek's bugfixes and new features into the driver - switch to use MAC80211 -Please send any patches to Greg Kroah-Hartman , +Please send any patches to Greg Kroah-Hartman , Jes Sorensen , and Larry Finger . -- cgit From 77cb59a42b566fc25c7dee5e6cc4d97017dddbe0 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 15:41:55 -0500 Subject: staging: iio: Remove parentheses on the right hand side of assignment Remove parentheses on the right hand side of assignment as they are not needed. Semantic patch used: @@ expression a, b, c, d; @@ ( a = (c == d) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/accel/lis3l02dq_core.c | 4 ++-- drivers/staging/iio/cdc/ad7746.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/accel/lis3l02dq_core.c b/drivers/staging/iio/accel/lis3l02dq_core.c index 7939ae6378d7..7a6fed3f2d3f 100644 --- a/drivers/staging/iio/accel/lis3l02dq_core.c +++ b/drivers/staging/iio/accel/lis3l02dq_core.c @@ -567,7 +567,7 @@ static int lis3l02dq_read_event_config(struct iio_dev *indio_dev, { u8 val; int ret; - u8 mask = (1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING))); + u8 mask = 1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING)); ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_WAKE_UP_CFG_ADDR, @@ -622,7 +622,7 @@ static int lis3l02dq_write_event_config(struct iio_dev *indio_dev, u8 val, control; u8 currentlyset; bool changed = false; - u8 mask = (1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING))); + u8 mask = 1 << (chan->channel2 * 2 + (dir == IIO_EV_DIR_RISING)); mutex_lock(&indio_dev->mlock); /* read current control */ diff --git a/drivers/staging/iio/cdc/ad7746.c b/drivers/staging/iio/cdc/ad7746.c index 2c5d27784ed3..5771d4ee8ef1 100644 --- a/drivers/staging/iio/cdc/ad7746.c +++ b/drivers/staging/iio/cdc/ad7746.c @@ -529,8 +529,8 @@ static int ad7746_write_raw(struct iio_dev *indio_dev, val /= 338646; - chip->capdac[chan->channel][chan->differential] = (val > 0 ? - AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0); + chip->capdac[chan->channel][chan->differential] = val > 0 ? + AD7746_CAPDAC_DACP(val) | AD7746_CAPDAC_DACEN : 0; ret = i2c_smbus_write_byte_data(chip->client, AD7746_REG_CAPDACA, -- cgit From 6924af76c20fc8f1a0923daff389f850c457f00b Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:40 -0500 Subject: staging: unisys: Fix guestlinuxdebug.h comments This patch simply cleans up all checkpatch comment issues Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/include/guestlinuxdebug.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/include/guestlinuxdebug.h b/drivers/staging/unisys/include/guestlinuxdebug.h index 82ee565395ba..b81287f5e2c3 100644 --- a/drivers/staging/unisys/include/guestlinuxdebug.h +++ b/drivers/staging/unisys/include/guestlinuxdebug.h @@ -17,9 +17,10 @@ #define __GUESTLINUXDEBUG_H__ /* -* This file contains supporting interface for "vmcallinterface.h", particularly -* regarding adding additional structure and functionality to linux -* ISSUE_IO_VMCALL_POSTCODE_SEVERITY */ + * This file contains supporting interface for "vmcallinterface.h", particularly + * regarding adding additional structure and functionality to linux + * ISSUE_IO_VMCALL_POSTCODE_SEVERITY + */ /******* INFO ON ISSUE_POSTCODE_LINUX() BELOW *******/ enum driver_pc { /* POSTCODE driver identifier tuples */ @@ -133,9 +134,9 @@ enum event_pc { /* POSTCODE event identifier tuples */ #define POSTCODE_SEVERITY_ERR DIAG_SEVERITY_ERR #define POSTCODE_SEVERITY_WARNING DIAG_SEVERITY_WARNING -#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT /* TODO-> Info currently - * doesn't show, so we - * set info=warning */ +/* TODO-> Info currently doesn't show, so we set info=warning */ +#define POSTCODE_SEVERITY_INFO DIAG_SEVERITY_PRINT + /* example call of POSTCODE_LINUX_2(VISOR_CHIPSET_PC, POSTCODE_SEVERITY_ERR); * Please also note that the resulting postcode is in hex, so if you are * searching for the __LINE__ number, convert it first to decimal. The line -- cgit From 1e3ab5219764d335391e0e673dbfcba286fc1616 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:41 -0500 Subject: staging: unisys: fix comments for controlvmchannel.h This patch simply fixes all trailing */ by modifying the comments structures while trying to reduce the total number of lines Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/controlvmchannel.h | 237 +++++++++++---------- 1 file changed, 119 insertions(+), 118 deletions(-) diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h index ec25366b127c..03e36fb6a5a0 100644 --- a/drivers/staging/unisys/visorbus/controlvmchannel.h +++ b/drivers/staging/unisys/visorbus/controlvmchannel.h @@ -55,22 +55,25 @@ #define CONTROLVM_CRASHMSG_MAX 2 struct spar_segment_state { - u16 enabled:1; /* Bit 0: May enter other states */ - u16 active:1; /* Bit 1: Assigned to active partition */ - u16 alive:1; /* Bit 2: Configure message sent to - * service/server */ - u16 revoked:1; /* Bit 3: similar to partition state - * ShuttingDown */ - u16 allocated:1; /* Bit 4: memory (device/port number) - * has been selected by Command */ - u16 known:1; /* Bit 5: has been introduced to the - * service/guest partition */ - u16 ready:1; /* Bit 6: service/Guest partition has - * responded to introduction */ - u16 operating:1; /* Bit 7: resource is configured and - * operating */ - /* Note: don't use high bit unless we need to switch to ushort - * which is non-compliant */ + /* Bit 0: May enter other states */ + u16 enabled:1; + /* Bit 1: Assigned to active partition */ + u16 active:1; + /* Bit 2: Configure message sent to service/server */ + u16 alive:1; + /* Bit 3: similar to partition state ShuttingDown */ + u16 revoked:1; + /* Bit 4: memory (device/port number) has been selected by Command */ + u16 allocated:1; + /* Bit 5: has been introduced to the service/guest partition */ + u16 known:1; + /* Bit 6: service/Guest partition has responded to introduction */ + u16 ready:1; + /* Bit 7: resource is configured and operating */ + u16 operating:1; +/* Note: don't use high bit unless we need to switch to ushort + * which is non-compliant + */ }; static const struct spar_segment_state segment_state_running = { @@ -177,53 +180,53 @@ struct controlvm_message_header { /* For requests, indicates the message type. */ /* For responses, indicates the type of message we are responding to. */ - u32 message_size; /* Includes size of this struct + size - * of message */ - u32 segment_index; /* Index of segment containing Vm - * message/information */ - u32 completion_status; /* Error status code or result of - * message completion */ + /* Includes size of this struct + size of message */ + u32 message_size; + /* Index of segment containing Vm message/information */ + u32 segment_index; + /* Error status code or result of message completion */ + u32 completion_status; struct { - u32 failed:1; /* =1 in a response to * signify - * failure */ - u32 response_expected:1; /* =1 in all messages that expect a - * response (Control ignores this - * bit) */ - u32 server:1; /* =1 in all bus & device-related - * messages where the message - * receiver is to act as the bus or - * device server */ - u32 test_message:1; /* =1 for testing use only - * (Control and Command ignore this - * bit) */ - u32 partial_completion:1; /* =1 if there are forthcoming - * responses/acks associated - * with this message */ - u32 preserve:1; /* =1 this is to let us know to - * preserve channel contents - * (for running guests)*/ - u32 writer_in_diag:1; /* =1 the DiagWriter is active in the - * Diagnostic Partition*/ + /* =1 in a response to signify failure */ + u32 failed:1; + /* =1 in all messages that expect a response */ + u32 response_expected:1; + /* =1 in all bus & device-related messages where the message + * receiver is to act as the bus or device server + */ + u32 server:1; + /* =1 for testing use only (Control and Command ignore this */ + u32 test_message:1; + /* =1 if there are forthcoming responses/acks associated + * with this message + */ + u32 partial_completion:1; + /* =1 this is to let us know to preserve channel contents */ + u32 preserve:1; + /* =1 the DiagWriter is active in the Diagnostic Partition */ + u32 writer_in_diag:1; } flags; - u32 reserved; /* Natural alignment */ - u64 message_handle; /* Identifies the particular message instance, - * and is used to match particular */ + /* Natural alignment */ + u32 reserved; + /* Identifies the particular message instance */ + u64 message_handle; /* request instances with the corresponding response instance. */ - u64 payload_vm_offset; /* Offset of payload area from start of this - * instance of ControlVm segment */ - u32 payload_max_bytes; /* Maximum bytes allocated in payload - * area of ControlVm segment */ - u32 payload_bytes; /* Actual number of bytes of payload - * area to copy between IO/Command; */ + /* Offset of payload area from start of this instance */ + u64 payload_vm_offset; + /* Maximum bytes allocated in payload area of ControlVm segment */ + u32 payload_max_bytes; + /* Actual number of bytes of payload area to copy between IO/Command */ + u32 payload_bytes; /* if non-zero, there is a payload to copy. */ }; struct controlvm_packet_device_create { u32 bus_no; /* bus # (0..n-1) from the msg receiver's end */ u32 dev_no; /* bus-relative (0..n-1) device number */ - u64 channel_addr; /* Guest physical address of the channel, which - * can be dereferenced by the receiver of this - * ControlVm command */ + /* Guest physical address of the channel, which can be dereferenced by + * the receiver of this ControlVm command + */ + u64 channel_addr; u64 channel_bytes; /* specifies size of the channel in bytes */ uuid_le data_type_uuid; /* specifies format of data in channel */ uuid_le dev_inst_uuid; /* instance guid for the device */ @@ -231,8 +234,8 @@ struct controlvm_packet_device_create { }; /* for CONTROLVM_DEVICE_CREATE */ struct controlvm_packet_device_configure { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; /* Control uses header SegmentIndex field to access bus number... */ u32 dev_no; /* bus-relative (0..n-1) device number */ } ; /* for CONTROLVM_DEVICE_CONFIGURE */ @@ -251,50 +254,50 @@ struct controlvm_message_device_configure { struct controlvm_message_packet { union { struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ - u32 dev_count; /* indicates the max number of - * devices on this bus */ - u64 channel_addr; /* Guest physical address of - * the channel, which can be - * dereferenced by the receiver - * of this ControlVm command */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; + /* indicates the max number of devices on this bus */ + u32 dev_count; + /* Guest physical address of the channel, which can be + * dereferenced by the receiver of this ControlVm command + */ + u64 channel_addr; u64 channel_bytes; /* size of the channel */ - uuid_le bus_data_type_uuid; /* indicates format of - * data in bus channel*/ + /* indicates format of data in bus channel*/ + uuid_le bus_data_type_uuid; uuid_le bus_inst_uuid; /* instance uuid for the bus */ } create_bus; /* for CONTROLVM_BUS_CREATE */ struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; u32 reserved; /* Natural alignment purposes */ } destroy_bus; /* for CONTROLVM_BUS_DESTROY */ struct { - u32 bus_no; /* bus # (0..n-1) from the receiver's - * perspective */ + /* bus # (0..n-1) from the receiver's perspective */ + u32 bus_no; u32 reserved1; /* for alignment purposes */ - u64 guest_handle; /* This is used to convert - * guest physical address to - * physical address */ + /* This is used to convert guest physical address to physical address */ + u64 guest_handle; u64 recv_bus_irq_handle; /* specifies interrupt info. It is used by SP * to register to receive interrupts from the * CP. This interrupt is used for bus level * notifications. The corresponding - * sendBusInterruptHandle is kept in CP. */ + * sendBusInterruptHandle is kept in CP. + */ } configure_bus; /* for CONTROLVM_BUS_CONFIGURE */ /* for CONTROLVM_DEVICE_CREATE */ struct controlvm_packet_device_create create_device; struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; u32 dev_no; /* bus-relative (0..n-1) device # */ } destroy_device; /* for CONTROLVM_DEVICE_DESTROY */ /* for CONTROLVM_DEVICE_CONFIGURE */ struct controlvm_packet_device_configure configure_device; struct { - u32 bus_no; /* bus # (0..n-1) from the msg - * receiver's perspective */ + /* bus # (0..n-1) from the msg receiver's perspective */ + u32 bus_no; u32 dev_no; /* bus-relative (0..n-1) device # */ } reconfigure_device; /* for CONTROLVM_DEVICE_RECONFIGURE */ struct { @@ -307,8 +310,8 @@ struct controlvm_message_packet { u32 dev_no; struct spar_segment_state state; struct { - u32 phys_device:1; /* =1 if message is for - * a physical device */ + /* =1 if message is for a physical device */ + u32 phys_device:1; } flags; u8 reserved[2]; /* Natural alignment purposes */ } device_change_state; /* for CONTROLVM_DEVICE_CHANGESTATE */ @@ -320,9 +323,10 @@ struct controlvm_message_packet { } device_change_state_event; /* for CONTROLVM_DEVICE_CHANGESTATE_EVENT */ struct { - u32 bus_count; /* indicates the max number of busses */ - u32 switch_count; /* indicates the max number of - * switches if a service partition */ + /* indicates the max number of busses */ + u32 bus_count; + /* indicates the max number of switches */ + u32 switch_count; enum ultra_chipset_feature features; u32 platform_number; /* Platform Number */ } init_chipset; /* for CONTROLVM_CHIPSET_INIT */ @@ -330,11 +334,12 @@ struct controlvm_message_packet { u32 options; /* reserved */ u32 test; /* bit 0 set to run embedded selftest */ } chipset_selftest; /* for CONTROLVM_CHIPSET_SELFTEST */ - u64 addr; /* a physical address of something, that can be - * dereferenced by the receiver of this - * ControlVm command (depends on command id) */ - u64 handle; /* a handle of something (depends on command - * id) */ + /* a physical address of something, that can be dereferenced + * by the receiver of this ControlVm command + */ + u64 addr; + /* a handle of something (depends on command id) */ + u64 handle; }; }; @@ -357,8 +362,8 @@ struct spar_controlvm_channel_protocol { u64 gp_nvram; /* guest phys addr of NVRAM channel */ u64 request_payload_offset; /* Offset to request payload area */ u64 event_payload_offset; /* Offset to event payload area */ - u32 request_payload_bytes; /* Bytes available in request payload - * area */ + /* Bytes available in request payload area */ + u32 request_payload_bytes; u32 event_payload_bytes;/* Bytes available in event payload area */ u32 control_channel_bytes; u32 nvram_channel_bytes; /* Bytes in PartitionNvram segment */ @@ -384,41 +389,37 @@ struct spar_controlvm_channel_protocol { u64 virtual_guest_image_size; u64 prototype_control_channel_offset; u64 virtual_guest_partition_handle; - - u16 restore_action; /* Restore Action field to restore the guest - * partition */ - u16 dump_action; /* For Windows guests it shows if the visordisk - * is running in dump mode */ + /* Restore Action field to restore the guest partition */ + u16 restore_action; + /* For Windows guests it shows if the visordisk is in dump mode */ + u16 dump_action; u16 nvram_fail_count; u16 saved_crash_message_count; /* = CONTROLVM_CRASHMSG_MAX */ - u32 saved_crash_message_offset; /* Offset to request payload area needed - * for crash dump */ - u32 installation_error; /* Type of error encountered during - * installation */ + /* Offset to request payload area needed for crash dump */ + u32 saved_crash_message_offset; + /* Type of error encountered during installation */ + u32 installation_error; u32 installation_text_id; /* Id of string to display */ - u16 installation_remaining_steps;/* Number of remaining installation - * steps (for progress bars) */ - u8 tool_action; /* ULTRA_TOOL_ACTIONS Installation Action - * field */ + /* Number of remaining installation steps (for progress bars) */ + u16 installation_remaining_steps; + /* ULTRA_TOOL_ACTIONS Installation Action field */ + u8 tool_action; u8 reserved; /* alignment */ struct efi_spar_indication efi_spar_ind; struct efi_spar_indication efi_spar_ind_supported; u32 sp_reserved; - u8 reserved2[28]; /* Force signals to begin on 128-byte cache - * line */ - struct signal_queue_header request_queue;/* Service or guest partition - * uses this queue to send - * requests to Control */ - struct signal_queue_header response_queue;/* Control uses this queue to - * respond to service or guest - * partition requests */ - struct signal_queue_header event_queue; /* Control uses this queue to - * send events to service or - * guest partition */ - struct signal_queue_header event_ack_queue;/* Service or guest partition - * uses this queue to ack - * Control events */ - + /* Force signals to begin on 128-byte cache line */ + u8 reserved2[28]; + /* guest partition uses this queue to send requests to Control */ + struct signal_queue_header request_queue; + /* Control uses this queue to respond to service or guest + * partition requests + */ + struct signal_queue_header response_queue; + /* Control uses this queue to send events to guest partition */ + struct signal_queue_header event_queue; + /* Service or guest partition uses this queue to ack Control events */ + struct signal_queue_header event_ack_queue; /* Request fixed-size message pool - does not include payload */ struct controlvm_message request_msg[CONTROLVM_MESSAGE_MAX]; -- cgit From 277f3f718d395653eb9f21fbda8900a65d7f2bd9 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:42 -0500 Subject: staging: unisys: Fix NULL comparison vbusdeviceinfo.h This patches resolves the NULL comparison checkpatch warnings Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/vbusdeviceinfo.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h index f59fd8a523c4..32169752c6f4 100644 --- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h +++ b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h @@ -62,7 +62,7 @@ vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) p++; remain--; chars++; - } else if (p == NULL) { + } else if (!p) { chars++; } nonprintable_streak = 0; @@ -72,7 +72,7 @@ vbuschannel_sanitize_buffer(char *p, int remain, char *src, int srcmax) p++; remain--; chars++; - } else if (p == NULL) { + } else if (!p) { chars++; } } else { -- cgit From cbc5d96ac2ab17a8be260af9f7e1fe10abb21197 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:43 -0500 Subject: staging: unisys: fix trailing comment in vbusdeviceinfo.h Fixes checkpatch trailing */ comment in vbusdeviceinfo.h Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/vbusdeviceinfo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h index 32169752c6f4..abdab4ad0b36 100644 --- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h +++ b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h @@ -124,7 +124,8 @@ vbuschannel_itoa(char *p, int remain, int num) } if (remain < digits) { /* not enough room left at

to hold number, so fill with - * '?' */ + * '?' + */ for (i = 0; i < remain; i++, p++) *p = '?'; return remain; -- cgit From 2ee0d05243a2705e29efefe9cf75c9540e471ea5 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:44 -0500 Subject: staging: unisys: fix comments in visorchipset This patch fixes all the Block comments by using a trailing */ on a separate line Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index f4c37dab9999..c3d46aac93b3 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -86,8 +86,8 @@ visorchipset_release(struct inode *inode, struct file *file) */ #define MIN_IDLE_SECONDS 10 static unsigned long poll_jiffies = POLLJIFFIES_CONTROLVMCHANNEL_FAST; -static unsigned long most_recent_message_jiffies; /* when we got our last - * controlvm message */ +/* when we got our last controlvm message */ +static unsigned long most_recent_message_jiffies; static int visorbusregistered; #define MAX_CHIPSET_EVENTS 2 @@ -120,7 +120,8 @@ static struct visorchannel *controlvm_channel; struct visor_controlvm_payload_info { u8 *ptr; /* pointer to base address of payload pool */ u64 offset; /* offset from beginning of controlvm - * channel to beginning of payload * pool */ + * channel to beginning of payload * pool + */ u32 bytes; /* number of bytes in payload pool */ }; @@ -184,7 +185,8 @@ struct putfile_request { * - this list is added to when controlvm messages come in that supply * file data * - this list is removed from via the hotplug program that is actually - * consuming these buffers to write as file data */ + * consuming these buffers to write as file data + */ struct list_head input_buffer_list; spinlock_t req_list_lock; /* lock for input_buffer_list */ @@ -788,13 +790,15 @@ chipset_init(struct controlvm_message *inmsg) POSTCODE_LINUX_2(CHIPSET_INIT_EXIT_PC, POSTCODE_SEVERITY_INFO); /* Set features to indicate we support parahotplug (if Command - * also supports it). */ + * also supports it). + */ features = inmsg->cmd.init_chipset. features & ULTRA_CHIPSET_FEATURE_PARA_HOTPLUG; /* Set the "reply" bit so Command knows this is a - * features-aware driver. */ + * features-aware driver. + */ features |= ULTRA_CHIPSET_FEATURE_REPLY; cleanup: -- cgit From 8c395e740bbbf6c29048a2fdcf33ab9ab533af09 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:45 -0500 Subject: staging: unisys: fix spacing in visorchipset.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following checkpatch warning: spaces preferred around that ‘*’ or ‘|’ Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index c3d46aac93b3..085d19a56866 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -47,7 +47,6 @@ #define VISORCHIPSET_MMAP_CONTROLCHANOFFSET 0x00000000 - #define UNISYS_SPAR_LEAF_ID 0x40000000 /* The s-Par leaf ID returns "UnisysSpar64" encoded across ebx, ecx, edx */ @@ -379,7 +378,7 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) rc = NULL; goto cleanup; } - ctx = kzalloc(allocbytes, GFP_KERNEL|__GFP_NORETRY); + ctx = kzalloc(allocbytes, GFP_KERNEL | __GFP_NORETRY); if (!ctx) { if (retry) *retry = true; @@ -522,7 +521,7 @@ parser_string_get(struct parser_context *ctx) } if (value_length < 0) /* '\0' was not included in the length */ value_length = nscan; - value = kmalloc(value_length + 1, GFP_KERNEL|__GFP_NORETRY); + value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY); if (value == NULL) return NULL; if (value_length > 0) -- cgit From e4a3dd33e5756f89c997099983e27f01727b0a37 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:46 -0500 Subject: staging: unisys: fix comparison to NULL in visorchipset.c This patch fixes the following type of check patch warnings: Comparison to NULL could be written Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 085d19a56866..ab8f9ddc6424 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -438,7 +438,7 @@ parser_id_get(struct parser_context *ctx) { struct spar_controlvm_parameters_header *phdr = NULL; - if (ctx == NULL) + if (!ctx) return NULL_UUID_LE; phdr = (struct spar_controlvm_parameters_header *)(ctx->data); return phdr->id; @@ -461,7 +461,7 @@ parser_param_start(struct parser_context *ctx, { struct spar_controlvm_parameters_header *phdr = NULL; - if (ctx == NULL) + if (!ctx) goto Away; phdr = (struct spar_controlvm_parameters_header *)(ctx->data); switch (which_string) { @@ -522,7 +522,7 @@ parser_string_get(struct parser_context *ctx) if (value_length < 0) /* '\0' was not included in the length */ value_length = nscan; value = kmalloc(value_length + 1, GFP_KERNEL | __GFP_NORETRY); - if (value == NULL) + if (!value) return NULL; if (value_length > 0) memcpy(value, pscan, value_length); @@ -875,7 +875,7 @@ bus_responder(enum controlvm_id cmd_id, struct controlvm_message_header *pending_msg_hdr, int response) { - if (pending_msg_hdr == NULL) + if (!pending_msg_hdr) return; /* no controlvm response needed */ if (pending_msg_hdr->id != (u32)cmd_id) @@ -893,7 +893,7 @@ device_changestate_responder(enum controlvm_id cmd_id, u32 bus_no = p->chipset_bus_no; u32 dev_no = p->chipset_dev_no; - if (p->pending_msg_hdr == NULL) + if (!p->pending_msg_hdr) return; /* no controlvm response needed */ if (p->pending_msg_hdr->id != cmd_id) return; @@ -914,7 +914,7 @@ device_responder(enum controlvm_id cmd_id, struct controlvm_message_header *pending_msg_hdr, int response) { - if (pending_msg_hdr == NULL) + if (!pending_msg_hdr) return; /* no controlvm response needed */ if (pending_msg_hdr->id != (u32)cmd_id) @@ -1180,7 +1180,7 @@ bus_configure(struct controlvm_message *inmsg, POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_BUS_INVALID; - } else if (bus_info->pending_msg_hdr != NULL) { + } else if (bus_info->pending_msg_hdr) { POSTCODE_LINUX_3(BUS_CONFIGURE_FAILURE_PC, bus_no, POSTCODE_SEVERITY_ERR); rc = -CONTROLVM_RESP_ERROR_MESSAGE_ID_INVALID_FOR_CLIENT; -- cgit From d1e0863701a95560d02ed22cfd15b66f82d46a9d Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:47 -0500 Subject: staging: unisys: fix blank lines in visorchipset.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this patch removes the following checkpatch warnings: please use a blank line after … Please don’t use multiple blank lines Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index ab8f9ddc6424..8d672c721ac2 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -353,7 +353,6 @@ static void controlvm_respond_physdev_changestate( struct controlvm_message_header *msg_hdr, int response, struct spar_segment_state state); - static void parser_done(struct parser_context *ctx); static struct parser_context * @@ -530,7 +529,6 @@ parser_string_get(struct parser_context *ctx) return value; } - static ssize_t toolaction_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -707,6 +705,7 @@ static int match_visorbus_dev_by_id(struct device *dev, void *data) return 0; } + struct visor_device *visorbus_get_device_by_id(u32 bus_no, u32 dev_no, struct visor_device *from) { -- cgit From 0e7bf2f4494eb5ad6411961ec1f4bd5e2c581a6f Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:48 -0500 Subject: staging: unisys: fix spaces after cast visorchipset.c This patch fixes checkpatch's no space is necessary after a cast Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 8d672c721ac2..6ad03a580a12 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -397,7 +397,7 @@ parser_init_byte_stream(u64 addr, u32 bytes, bool local, bool *retry) rc = NULL; goto cleanup; } - p = __va((unsigned long) (addr)); + p = __va((unsigned long)(addr)); memcpy(ctx->data, p, bytes); } else { void *mapping; @@ -525,7 +525,7 @@ parser_string_get(struct parser_context *ctx) return NULL; if (value_length > 0) memcpy(value, pscan, value_length); - ((u8 *) (value))[value_length] = '\0'; + ((u8 *)(value))[value_length] = '\0'; return value; } @@ -815,7 +815,7 @@ controlvm_init_response(struct controlvm_message *msg, msg->hdr.payload_max_bytes = 0; if (response < 0) { msg->hdr.flags.failed = 1; - msg->hdr.completion_status = (u32) (-response); + msg->hdr.completion_status = (u32)(-response); } } -- cgit From 7005c16cf24cb2917a91565a97119b25cf816ab3 Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:49 -0500 Subject: staging: unisys: fix comments in visorbus_main.c This patch fixes the following types of check patch warnings: Block comments use a trailing */ on a separate line Comment alignments Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorbus_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c index eac97d22278a..a3013852c0e0 100644 --- a/drivers/staging/unisys/visorbus/visorbus_main.c +++ b/drivers/staging/unisys/visorbus/visorbus_main.c @@ -1371,9 +1371,9 @@ pause_state_change_complete(struct visor_device *dev, int status) return; /* Notify the chipset driver that the pause is complete, which - * will presumably want to send some sort of response to the - * initiator. - */ + * will presumably want to send some sort of response to the + * initiator. + */ (*chipset_responders.device_pause) (dev, status); } -- cgit From 5d5a0bd9cc401e093a5b856615ffddfdbaee786f Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:50 -0500 Subject: staging: unisys: fix block comments in ultrainputreport.h This patch fixes the following types of check patch warnings: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- .../staging/unisys/visorinput/ultrainputreport.h | 45 +++++++++++++--------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/drivers/staging/unisys/visorinput/ultrainputreport.h b/drivers/staging/unisys/visorinput/ultrainputreport.h index 3e6a52f4b6bf..1bc3d2064080 100644 --- a/drivers/staging/unisys/visorinput/ultrainputreport.h +++ b/drivers/staging/unisys/visorinput/ultrainputreport.h @@ -29,33 +29,40 @@ enum ultra_inputaction { inputaction_mouse_button_up = 3, /* arg1: 1=left,2=center,3=right */ inputaction_mouse_button_click = 4, /* arg1: 1=left,2=center,3=right */ inputaction_mouse_button_dclick = 5, /* arg1: 1=left,2=center, - 3=right */ + * 3=right + */ inputaction_wheel_rotate_away = 6, /* arg1: wheel rotation away from - user */ + * user + */ inputaction_wheel_rotate_toward = 7, /* arg1: wheel rotation toward - user */ + * user + */ inputaction_set_max_xy = 8, /* set screen maxXY; arg1=x, arg2=y */ inputaction_key_down = 64, /* arg1: scancode, as follows: - If arg1 <= 0xff, it's a 1-byte - scancode and arg1 is that scancode. - If arg1 > 0xff, it's a 2-byte - scanecode, with the 1st byte in the - low 8 bits, and the 2nd byte in the - high 8 bits. E.g., the right ALT key - would appear as x'38e0'. */ + * If arg1 <= 0xff, it's a 1-byte + * scancode and arg1 is that scancode. + * If arg1 > 0xff, it's a 2-byte + * scanecode, with the 1st byte in the + * low 8 bits, and the 2nd byte in the + * high 8 bits. E.g., the right ALT key + * would appear as x'38e0'. + */ inputaction_key_up = 65, /* arg1: scancode (in same format as - inputaction_keyDown) */ + * inputaction_keyDown) + */ inputaction_set_locking_key_state = 66, /* arg1: scancode (in same format - as inputaction_keyDown); - MUST refer to one of the - locking keys, like capslock, - numlock, or scrolllock - arg2: 1 iff locking key should be - in the LOCKED position - (e.g., light is ON) */ + * as inputaction_keyDown); + * MUST refer to one of the + * locking keys, like capslock, + * numlock, or scrolllock + * arg2: 1 iff locking key should be + * in the LOCKED position + * (e.g., light is ON) + */ inputaction_key_down_up = 67, /* arg1: scancode (in same format - as inputaction_keyDown) */ + * as inputaction_keyDown) + */ inputaction_last }; -- cgit From abbceb61291b94d8c39568b1cd1daa607c58603a Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:51 -0500 Subject: staging: unisys: fix comments in visornic_main.c This patch fixes the following types of check patch warnings: Block comments use * on subsequent lines Block comments use a trailing */ on a separate line Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 9b3eb95ed183..3da849a529cd 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1219,8 +1219,9 @@ visornic_rx(struct uiscmdrsp *cmdrsp) /* length rcvd is greater than firstfrag in this skb rcv buf */ skb->tail += RCVPOST_BUF_SIZE; /* amount in skb->data */ skb->data_len = skb->len - RCVPOST_BUF_SIZE; /* amount that - will be in - frag_list */ + * will be in + * frag_list + */ } else { /* data fits in this skb - no chaining - do * PRECAUTIONARY check @@ -1316,12 +1317,14 @@ visornic_rx(struct uiscmdrsp *cmdrsp) } if (found_mc) break; /* accept packet, dest - matches a multicast - address */ + * matches a multicast + * address + */ } } else if (skb->pkt_type == PACKET_HOST) { break; /* accept packet, h_dest must match vnic - mac address */ + * mac address + */ } else if (skb->pkt_type == PACKET_OTHERHOST) { /* something is not right */ dev_err(&devdata->netdev->dev, @@ -1619,6 +1622,9 @@ service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata, struct net_device *netdev; while (*rx_work_done < budget) { + /* TODO: CLIENT ACQUIRE -- Don't really need this at the + * moment + */ if (!visorchannel_signalremove(devdata->dev->visorchannel, IOCHAN_FROM_IOPART, cmdrsp)) -- cgit From 05f1b17ec7aad4381e5a2ba3e99dc9925b4eebcb Mon Sep 17 00:00:00 2001 From: Erik Arfvidson Date: Mon, 8 Feb 2016 10:41:52 -0500 Subject: staging: unisys: fix else statement in visornic_main.c This patch fixes the following types of check patch warnings: else is not generally useful after a break or return Signed-off-by: Erik Arfvidson Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visornic/visornic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 3da849a529cd..234fa2172e0f 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -377,8 +377,8 @@ visornic_serverdown(struct visornic_devdata *devdata, __func__); spin_unlock_irqrestore(&devdata->priv_lock, flags); return -EINVAL; - } else - spin_unlock_irqrestore(&devdata->priv_lock, flags); + } + spin_unlock_irqrestore(&devdata->priv_lock, flags); return 0; } -- cgit From b4d4dfbcbb737b91bbf07c92891b2496a651be7e Mon Sep 17 00:00:00 2001 From: Benjamin Romer Date: Mon, 8 Feb 2016 10:41:53 -0500 Subject: staging: unisys: remove unnecessary goto parser_param_start() had a goto Away, which went to nothing but a return statement. Remove the goto, the CamelCased label, and just return directly. Signed-off-by: Benjamin Romer Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchipset.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 6ad03a580a12..a79aa2ddeef5 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -461,7 +461,8 @@ parser_param_start(struct parser_context *ctx, struct spar_controlvm_parameters_header *phdr = NULL; if (!ctx) - goto Away; + return; + phdr = (struct spar_controlvm_parameters_header *)(ctx->data); switch (which_string) { case PARSERSTRING_INITIATOR: @@ -483,9 +484,6 @@ parser_param_start(struct parser_context *ctx, default: break; } - -Away: - return; } static void parser_done(struct parser_context *ctx) -- cgit From 90cb147f3a701443f1e7e5b104e689b08f2677e3 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 14:02:04 -0500 Subject: staging: unisys: Remove parentheses around right hand side of assignment Remove parentheses on the right hand side of assignment as they are not needed. Semantic patch used: @@ expression a, b, c, d; @@ ( a = (c == d) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorbus/visorchannel.c | 4 ++-- drivers/staging/unisys/visorhba/visorhba_main.c | 4 ++-- drivers/staging/unisys/visornic/visornic_main.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c index 891b8db7c5ec..a80d72cfa203 100644 --- a/drivers/staging/unisys/visorbus/visorchannel.c +++ b/drivers/staging/unisys/visorbus/visorchannel.c @@ -461,7 +461,7 @@ signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg) if (!sig_read_header(channel, queue, &sig_hdr)) return false; - sig_hdr.head = ((sig_hdr.head + 1) % sig_hdr.max_slots); + sig_hdr.head = (sig_hdr.head + 1) % sig_hdr.max_slots; if (sig_hdr.head == sig_hdr.tail) { sig_hdr.num_overflows++; visorchannel_write(channel, @@ -521,7 +521,7 @@ visorchannel_signalqueue_slots_avail(struct visorchannel *channel, u32 queue) tail = sig_hdr.tail; if (head < tail) head = head + sig_hdr.max_slots; - slots_used = (head - tail); + slots_used = head - tail; slots_avail = sig_hdr.max_signals - slots_used; return (int)slots_avail; } diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 202bfabfec6c..5a78409d0293 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -323,9 +323,9 @@ static int forward_taskmgmt_command(enum task_mgmt_types tasktype, goto err_del_scsipending_ent; if (tasktype == TASK_MGMT_ABORT_TASK) - scsicmd->result = (DID_ABORT << 16); + scsicmd->result = DID_ABORT << 16; else - scsicmd->result = (DID_RESET << 16); + scsicmd->result = DID_RESET << 16; scsicmd->scsi_done(scsicmd); diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c index 234fa2172e0f..df4f68895adc 100644 --- a/drivers/staging/unisys/visornic/visornic_main.c +++ b/drivers/staging/unisys/visornic/visornic_main.c @@ -1029,7 +1029,7 @@ visornic_set_multi(struct net_device *netdev) cmdrsp->net.type = NET_RCV_PROMISC; cmdrsp->net.enbdis.context = netdev; cmdrsp->net.enbdis.enable = - (netdev->flags & IFF_PROMISC); + netdev->flags & IFF_PROMISC; visorchannel_signalinsert(devdata->dev->visorchannel, IOCHAN_TO_IOPART, cmdrsp); @@ -1772,7 +1772,7 @@ static int visornic_probe(struct visor_device *dev) } netdev->netdev_ops = &visornic_dev_ops; - netdev->watchdog_timeo = (5 * HZ); + netdev->watchdog_timeo = 5 * HZ; SET_NETDEV_DEV(netdev, &dev->device); /* Get MAC adddress from channel and read it into the device. */ -- cgit From 5fe36bf068e4bd09bc11aabb6a4f30ea831913ef Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 01:43:47 -0500 Subject: staging: unisys: Modify boolean assignment Boolean variables should be assigned true/false rather than 1/0. This patch makes a correction on such a variable which has boolean values assigned in all other places within the file. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorhba/visorhba_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c index 5a78409d0293..e93bb1dbfd97 100644 --- a/drivers/staging/unisys/visorhba/visorhba_main.c +++ b/drivers/staging/unisys/visorhba/visorhba_main.c @@ -1062,7 +1062,7 @@ static int visorhba_resume(struct visor_device *dev, return -EINVAL; if (devdata->serverdown && !devdata->serverchangingstate) - devdata->serverchangingstate = 1; + devdata->serverchangingstate = true; visor_thread_start(&devdata->threadinfo, process_incoming_rsps, devdata, "vhba_incming"); -- cgit From ea39854712ba8a0757bc9fa6b6c17e8808bc6fda Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 8 Feb 2016 22:55:34 +0530 Subject: staging: most: return error value On error we were returning retval, but retval is not having the error value. We will get the error value using PTR_ERR. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/aim-cdev/cdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c index 3a2dbf1490c6..de4f76abfb47 100644 --- a/drivers/staging/most/aim-cdev/cdev.c +++ b/drivers/staging/most/aim-cdev/cdev.c @@ -470,8 +470,8 @@ static int aim_probe(struct most_interface *iface, int channel_id, NULL, "%s", name); - retval = IS_ERR(c->dev); - if (retval) { + if (IS_ERR(c->dev)) { + retval = PTR_ERR(c->dev); pr_info("failed to create new device node %s\n", name); goto error_create_device; } -- cgit From cc4188b6bb44a68c49af981ef5ec410d66d5c84d Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Mon, 8 Feb 2016 23:26:46 +0530 Subject: staging: most: return proper error We were returning ENOMEM on all types of errors. Lets return the actual error code. At the same time remove the label which became unused as a result of this patch. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/staging/most/mostcore/core.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index ab4c32d78d9f..322ee01e1f36 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -1854,40 +1854,52 @@ EXPORT_SYMBOL_GPL(most_resume_enqueue); static int __init most_init(void) { + int err; + pr_info("init()\n"); INIT_LIST_HEAD(&instance_list); INIT_LIST_HEAD(&aim_list); ida_init(&mdev_id); - if (bus_register(&most_bus)) { + err = bus_register(&most_bus); + if (err) { pr_info("Cannot register most bus\n"); - goto exit; + return err; } most_class = class_create(THIS_MODULE, "most"); if (IS_ERR(most_class)) { pr_info("No udev support.\n"); + err = PTR_ERR(most_class); goto exit_bus; } - if (driver_register(&mostcore)) { + + err = driver_register(&mostcore); + if (err) { pr_info("Cannot register core driver\n"); goto exit_class; } class_glue_dir = device_create(most_class, NULL, 0, NULL, "mostcore"); - if (IS_ERR(class_glue_dir)) + if (IS_ERR(class_glue_dir)) { + err = PTR_ERR(class_glue_dir); goto exit_driver; + } most_aim_kset = kset_create_and_add("aims", NULL, &class_glue_dir->kobj); - if (!most_aim_kset) + if (!most_aim_kset) { + err = -ENOMEM; goto exit_class_container; + } most_inst_kset = kset_create_and_add("devices", NULL, &class_glue_dir->kobj); - if (!most_inst_kset) + if (!most_inst_kset) { + err = -ENOMEM; goto exit_driver_kset; + } return 0; @@ -1901,8 +1913,7 @@ exit_class: class_destroy(most_class); exit_bus: bus_unregister(&most_bus); -exit: - return -ENOMEM; + return err; } static void __exit most_exit(void) -- cgit From beb6e57b50dcccf14077a20789f7b9bec9f6a3ad Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Wed, 10 Feb 2016 09:02:17 -0500 Subject: staging: octeon: Add spaces around operators Add spaces around operators for better readability. Change suggested by checkpatch. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-tx.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index 82abaeca27a7..e229ebf546a8 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -95,10 +95,10 @@ static void cvm_oct_free_tx_skbs(struct net_device *dev) for (qos = 0; qos < queues_per_port; qos++) { if (skb_queue_len(&priv->tx_free_list[qos]) == 0) continue; - skb_to_free = cvmx_fau_fetch_and_add32(priv->fau+qos*4, + skb_to_free = cvmx_fau_fetch_and_add32(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); total_freed += skb_to_free; @@ -419,7 +419,8 @@ dont_put_skbuff_in_hw: cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); } - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau+qos*4); + skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, + priv->fau + qos * 4); /* * If we're sending faster than the receive can free them then @@ -430,7 +431,7 @@ dont_put_skbuff_in_hw: if (pko_command.s.dontfree) { queue_type = QUEUE_CORE; - pko_command.s.reg0 = priv->fau+qos*4; + pko_command.s.reg0 = priv->fau + qos * 4; } else { queue_type = QUEUE_HW; } -- cgit From 1d5047c981f2e5a0fe6003c98b9c742c349d75a3 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 16:33:15 -0500 Subject: staging: octeon: Remove unneeded parentheses in assignment Remove parentheses around the right hand side of assignments as they are not needed. Semantic patch used: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/octeon-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 16d45879d0c4..7844e2036060 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -1048,7 +1048,7 @@ static struct cvmx_usb_port_status cvmx_usb_get_status( result.port_speed = usbc_hprt.s.prtspd; result.connected = usbc_hprt.s.prtconnsts; result.connect_change = - (result.connected != usb->port_status.connected); + result.connected != usb->port_status.connected; return result; } -- cgit From 710086dbbbeb8ac22dc04ad5c9426b8cabac735c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 12 Feb 2016 01:02:26 +0200 Subject: staging: octeon: refactor rgmii 10 mbps preamble error checking Refactor RGMII 10 Mbps preamble error checking. The current implementation does not work correctly in phydev mode since only the link status changes trigger the callback, and if we stay on 10 Mbps operation the periodic checks for error counters are never done. Provide a periodic worker also during the phydev operation, and notify the link status changes through the phydev instead of the inband status change interrupt. This also has the benefit that we don't need to use legacy CVMX MDIO calls to check the PHY state, and we can avoid races that trigger bogus "Using 10Mbps with software preamble removal" logs when interfaces are being bringed up. It also avoids some corner-case crashes when the in-band interrupt triggers while the interface is being taken down. Tested on EdgeRouter Lite & D-Link DSR-1000N. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-mdio.c | 17 +- drivers/staging/octeon/ethernet-rgmii.c | 287 ++++++++----------------------- drivers/staging/octeon/ethernet.c | 4 +- drivers/staging/octeon/octeon-ethernet.h | 4 +- 4 files changed, 87 insertions(+), 225 deletions(-) diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index fd9b3d899c1f..55abd83c38b6 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -118,13 +118,20 @@ void cvm_oct_adjust_link(struct net_device *dev) struct octeon_ethernet *priv = netdev_priv(dev); cvmx_helper_link_info_t link_info; + link_info.u64 = 0; + link_info.s.link_up = priv->phydev->link ? 1 : 0; + link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0; + link_info.s.speed = priv->phydev->speed; + priv->link_info = link_info.u64; + + /* + * The polling task need to know about link status changes. + */ + if (priv->poll) + priv->poll(dev); + if (priv->last_link != priv->phydev->link) { priv->last_link = priv->phydev->link; - link_info.u64 = 0; - link_info.s.link_up = priv->last_link ? 1 : 0; - link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0; - link_info.s.speed = priv->phydev->speed; - cvmx_helper_link_set(priv->port, link_info); cvm_oct_note_carrier(priv, link_info); } diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 9353796af0b6..91b148cfcbdb 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -30,8 +30,6 @@ static DEFINE_SPINLOCK(global_register_lock); -static int number_rgmii_ports; - static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) { union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; @@ -63,247 +61,106 @@ static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) gmxx_rxx_int_reg.u64); } -static void cvm_oct_rgmii_poll(struct net_device *dev) +static void cvm_oct_check_preamble_errors(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); - unsigned long flags = 0; cvmx_helper_link_info_t link_info; - int use_global_register_lock = (priv->phydev == NULL); + unsigned long flags; + + link_info.u64 = priv->link_info; - BUG_ON(in_interrupt()); - if (use_global_register_lock) { + /* + * Take the global register lock since we are going to + * touch registers that affect more than one port. + */ + spin_lock_irqsave(&global_register_lock, flags); + + if (link_info.s.speed == 10 && priv->last_speed == 10) { /* - * Take the global register lock since we are going to - * touch registers that affect more than one port. + * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are + * getting preamble errors. */ - spin_lock_irqsave(&global_register_lock, flags); - } else { - mutex_lock(&priv->phydev->mdio.bus->mdio_lock); - } + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - link_info = cvmx_helper_link_get(priv->port); - if (link_info.u64 == priv->link_info) { - if (link_info.s.speed == 10) { + gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG + (index, interface)); + if (gmxx_rxx_int_reg.s.pcterr) { /* - * Read the GMXX_RXX_INT_REG[PCTERR] bit and - * see if we are getting preamble errors. + * We are getting preamble errors at 10Mbps. Most + * likely the PHY is giving us packets with misaligned + * preambles. In order to get these packets we need to + * disable preamble checking and do it in software. */ - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - - gmxx_rxx_int_reg.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_REG - (index, interface)); - if (gmxx_rxx_int_reg.s.pcterr) { - /* - * We are getting preamble errors at - * 10Mbps. Most likely the PHY is - * giving us packets with mis aligned - * preambles. In order to get these - * packets we need to disable preamble - * checking and do it in software. - */ - cvm_oct_set_hw_preamble(priv, false); - printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", - dev->name); - } + cvm_oct_set_hw_preamble(priv, false); + printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", + dev->name); } - - if (use_global_register_lock) - spin_unlock_irqrestore(&global_register_lock, flags); - else - mutex_unlock(&priv->phydev->mdio.bus->mdio_lock); - return; - } - - /* Since the 10Mbps preamble workaround is allowed we need to enable - * preamble checking, FCS stripping, and clear error bits on - * every speed change. If errors occur during 10Mbps operation - * the above code will change this stuff - */ - cvm_oct_set_hw_preamble(priv, true); - - if (priv->phydev == NULL) { - link_info = cvmx_helper_link_autoconf(priv->port); - priv->link_info = link_info.u64; - } - - if (use_global_register_lock) - spin_unlock_irqrestore(&global_register_lock, flags); - else - mutex_unlock(&priv->phydev->mdio.bus->mdio_lock); - - if (priv->phydev == NULL) { - /* Tell core. */ - if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - } - cvm_oct_note_carrier(priv, link_info); + } else { + /* + * Since the 10Mbps preamble workaround is allowed we need to + * enable preamble checking, FCS stripping, and clear error + * bits on every speed change. If errors occur during 10Mbps + * operation the above code will change this stuff + */ + if (priv->last_speed != link_info.s.speed) + cvm_oct_set_hw_preamble(priv, true); + priv->last_speed = link_info.s.speed; } + spin_unlock_irqrestore(&global_register_lock, flags); } -static int cmv_oct_rgmii_gmx_interrupt(int interface) +static void cvm_oct_rgmii_poll(struct net_device *dev) { - int index; - int count = 0; - - /* Loop through every port of this interface */ - for (index = 0; - index < cvmx_helper_ports_on_interface(interface); - index++) { - union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; + struct octeon_ethernet *priv = netdev_priv(dev); + cvmx_helper_link_info_t link_info; + bool status_change; - /* Read the GMX interrupt status bits */ - gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG - (index, interface)); - gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN - (index, interface)); + link_info = cvmx_helper_link_autoconf(priv->port); + status_change = priv->link_info != link_info.u64; + priv->link_info = link_info.u64; - /* Poll the port if inband status changed */ - if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || - gmx_rx_int_reg.s.phy_spd) { - struct net_device *dev = - cvm_oct_device[cvmx_helper_get_ipd_port - (interface, index)]; - struct octeon_ethernet *priv = netdev_priv(dev); + cvm_oct_check_preamble_errors(dev); - if (dev && !atomic_read(&cvm_oct_poll_queue_stopping)) - queue_work(cvm_oct_poll_queue, - &priv->port_work); + if (likely(!status_change)) + return; - gmx_rx_int_reg.u64 = 0; - gmx_rx_int_reg.s.phy_dupx = 1; - gmx_rx_int_reg.s.phy_link = 1; - gmx_rx_int_reg.s.phy_spd = 1; - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), - gmx_rx_int_reg.u64); - count++; - } + /* Tell core. */ + if (link_info.s.link_up) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); } - return count; -} - -static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) -{ - union cvmx_npi_rsl_int_blocks rsl_int_blocks; - int count = 0; - - rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); - - /* Check and see if this interrupt was caused by the GMX0 block */ - if (rsl_int_blocks.s.gmx0) - count += cmv_oct_rgmii_gmx_interrupt(0); - - /* Check and see if this interrupt was caused by the GMX1 block */ - if (rsl_int_blocks.s.gmx1) - count += cmv_oct_rgmii_gmx_interrupt(1); - - return count ? IRQ_HANDLED : IRQ_NONE; + cvm_oct_note_carrier(priv, link_info); } int cvm_oct_rgmii_open(struct net_device *dev) -{ - return cvm_oct_common_open(dev, cvm_oct_rgmii_poll); -} - -static void cvm_oct_rgmii_immediate_poll(struct work_struct *work) -{ - struct octeon_ethernet *priv = - container_of(work, struct octeon_ethernet, port_work); - cvm_oct_rgmii_poll(cvm_oct_device[priv->port]); -} - -int cvm_oct_rgmii_init(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); - int r; + int ret; - cvm_oct_common_init(dev); - INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll); - /* - * Due to GMX errata in CN3XXX series chips, it is necessary - * to take the link down immediately when the PHY changes - * state. In order to do this we call the poll function every - * time the RGMII inband status changes. This may cause - * problems if the PHY doesn't implement inband status - * properly. - */ - if (number_rgmii_ports == 0) { - r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt, - IRQF_SHARED, "RGMII", &number_rgmii_ports); - if (r != 0) - return r; - } - number_rgmii_ports++; - - /* - * Only true RGMII ports need to be polled. In GMII mode, port - * 0 is really a RGMII port. - */ - if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) - && (priv->port == 0)) - || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - if (!octeon_is_simulation()) { - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); + ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll); + if (ret) + return ret; - /* - * Enable interrupts on inband status changes - * for this port. - */ - gmx_rx_int_en.u64 = 0; - gmx_rx_int_en.s.phy_dupx = 1; - gmx_rx_int_en.s.phy_link = 1; - gmx_rx_int_en.s.phy_spd = 1; - cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), - gmx_rx_int_en.u64); + if (priv->phydev) { + /* + * In phydev mode, we need still periodic polling for the + * preamble error checking, and we also need to call this + * function on every link state change. + * + * Only true RGMII ports need to be polled. In GMII mode, port + * 0 is really a RGMII port. + */ + if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII && + priv->port == 0) || + (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { + priv->poll = cvm_oct_check_preamble_errors; + cvm_oct_check_preamble_errors(dev); } } return 0; } - -void cvm_oct_rgmii_uninit(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - - cvm_oct_common_uninit(dev); - - /* - * Only true RGMII ports need to be polled. In GMII mode, port - * 0 is really a RGMII port. - */ - if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) - && (priv->port == 0)) - || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - if (!octeon_is_simulation()) { - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - /* - * Disable interrupts on inband status changes - * for this port. - */ - gmx_rx_int_en.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_EN - (index, interface)); - gmx_rx_int_en.s.phy_dupx = 0; - gmx_rx_int_en.s.phy_link = 0; - gmx_rx_int_en.s.phy_spd = 0; - cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), - gmx_rx_int_en.u64); - } - } - - /* Remove the interrupt handler when the last port is removed. */ - number_rgmii_ports--; - if (number_rgmii_ports == 0) - free_irq(OCTEON_IRQ_RML, &number_rgmii_ports); - cancel_work_sync(&priv->port_work); -} diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index f69fb5cc7cb8..8d239e23e5c7 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -601,8 +601,8 @@ static const struct net_device_ops cvm_oct_spi_netdev_ops = { #endif }; static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { - .ndo_init = cvm_oct_rgmii_init, - .ndo_uninit = cvm_oct_rgmii_uninit, + .ndo_init = cvm_oct_common_init, + .ndo_uninit = cvm_oct_common_uninit, .ndo_open = cvm_oct_rgmii_open, .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index fdf24d120e77..5b4fdd21ef57 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -41,20 +41,18 @@ struct octeon_ethernet { /* Device statistics */ struct net_device_stats stats; struct phy_device *phydev; + unsigned int last_speed; unsigned int last_link; /* Last negotiated link state */ u64 link_info; /* Called periodically to check link status */ void (*poll)(struct net_device *dev); struct delayed_work port_periodic_work; - struct work_struct port_work; /* may be unused. */ struct device_node *of_node; }; int cvm_oct_free_work(void *work_queue_entry); -int cvm_oct_rgmii_init(struct net_device *dev); -void cvm_oct_rgmii_uninit(struct net_device *dev); int cvm_oct_rgmii_open(struct net_device *dev); int cvm_oct_sgmii_init(struct net_device *dev); -- cgit From 2892ffc2ec7ea61de400da18184a39d08b66dd21 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 9 Feb 2016 15:17:20 +0000 Subject: staging: comedi: comedi.h: tweak start of header comment The wording at the start of the header comment is a bit misleading, particularly the part in parentheses: "(installed as /usr/include/comedi.h)". This version of "comedi.h" certainly won't be installed as that pathname. Fix it. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index f0d1b15f3c5a..c157c41a9cc7 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -1,6 +1,6 @@ /* - * include/comedi.h (installed as /usr/include/comedi.h) - * header file for comedi + * comedi.h + * header file for COMEDI user API * * COMEDI - Linux Control and Measurement Device Interface * Copyright (C) 1998-2001 David A. Schleef -- cgit From 8fb02b29470fec3c0463d740e52f3348a701b7ca Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 9 Feb 2016 15:17:21 +0000 Subject: staging: comedi: comedi.h: add kernel-doc to common enums Add "kernel-doc"-formatted comments to COMEDI's general-purpose `enum` type declarations. Don't bother documenting the low-level driver-specific ones for now. Move the declaration of `enum comedi_counter_status_flags` next to the other general-purpose `enum` types. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 225 ++++++++++++++++++++++++++++------------ 1 file changed, 160 insertions(+), 65 deletions(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index c157c41a9cc7..9ef0963101da 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -223,24 +223,91 @@ /* subdevice types */ +/** + * enum comedi_subdevice_type - COMEDI subdevice types + * @COMEDI_SUBD_UNUSED: Unused subdevice. + * @COMEDI_SUBD_AI: Analog input. + * @COMEDI_SUBD_AO: Analog output. + * @COMEDI_SUBD_DI: Digital input. + * @COMEDI_SUBD_DO: Digital output. + * @COMEDI_SUBD_DIO: Digital input/output. + * @COMEDI_SUBD_COUNTER: Counter. + * @COMEDI_SUBD_TIMER: Timer. + * @COMEDI_SUBD_MEMORY: Memory, EEPROM, DPRAM. + * @COMEDI_SUBD_CALIB: Calibration DACs. + * @COMEDI_SUBD_PROC: Processor, DSP. + * @COMEDI_SUBD_SERIAL: Serial I/O. + * @COMEDI_SUBD_PWM: Pulse-Width Modulation output. + */ enum comedi_subdevice_type { - COMEDI_SUBD_UNUSED, /* unused by driver */ - COMEDI_SUBD_AI, /* analog input */ - COMEDI_SUBD_AO, /* analog output */ - COMEDI_SUBD_DI, /* digital input */ - COMEDI_SUBD_DO, /* digital output */ - COMEDI_SUBD_DIO, /* digital input/output */ - COMEDI_SUBD_COUNTER, /* counter */ - COMEDI_SUBD_TIMER, /* timer */ - COMEDI_SUBD_MEMORY, /* memory, EEPROM, DPRAM */ - COMEDI_SUBD_CALIB, /* calibration DACs */ - COMEDI_SUBD_PROC, /* processor, DSP */ - COMEDI_SUBD_SERIAL, /* serial IO */ - COMEDI_SUBD_PWM /* PWM */ + COMEDI_SUBD_UNUSED, + COMEDI_SUBD_AI, + COMEDI_SUBD_AO, + COMEDI_SUBD_DI, + COMEDI_SUBD_DO, + COMEDI_SUBD_DIO, + COMEDI_SUBD_COUNTER, + COMEDI_SUBD_TIMER, + COMEDI_SUBD_MEMORY, + COMEDI_SUBD_CALIB, + COMEDI_SUBD_PROC, + COMEDI_SUBD_SERIAL, + COMEDI_SUBD_PWM }; /* configuration instructions */ +/** + * enum configuration_ids - COMEDI configuration instruction codes + * @INSN_CONFIG_DIO_INPUT: Configure digital I/O as input. + * @INSN_CONFIG_DIO_OUTPUT: Configure digital I/O as output. + * @INSN_CONFIG_DIO_OPENDRAIN: Configure digital I/O as open-drain (or open + * collector) output. + * @INSN_CONFIG_ANALOG_TRIG: Configure analog trigger. + * @INSN_CONFIG_ALT_SOURCE: Configure alternate input source. + * @INSN_CONFIG_DIGITAL_TRIG: Configure digital trigger. + * @INSN_CONFIG_BLOCK_SIZE: Configure block size for DMA transfers. + * @INSN_CONFIG_TIMER_1: Configure divisor for external clock. + * @INSN_CONFIG_FILTER: Configure a filter. + * @INSN_CONFIG_CHANGE_NOTIFY: Configure change notification for digital + * inputs. (New drivers should use + * %INSN_CONFIG_DIGITAL_TRIG instead.) + * @INSN_CONFIG_SERIAL_CLOCK: Configure clock for serial I/O. + * @INSN_CONFIG_BIDIRECTIONAL_DATA: Send and receive byte over serial I/O. + * @INSN_CONFIG_DIO_QUERY: Query direction of digital I/O channel. + * @INSN_CONFIG_PWM_OUTPUT: Configure pulse-width modulator output. + * @INSN_CONFIG_GET_PWM_OUTPUT: Get pulse-width modulator output configuration. + * @INSN_CONFIG_ARM: Arm a subdevice or channel. + * @INSN_CONFIG_DISARM: Disarm a subdevice or channel. + * @INSN_CONFIG_GET_COUNTER_STATUS: Get counter status. + * @INSN_CONFIG_RESET: Reset a subdevice or channel. + * @INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR: Configure counter/timer as + * single pulse generator. + * @INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR: Configure counter/timer as + * pulse train generator. + * @INSN_CONFIG_GPCT_QUADRATURE_ENCODER: Configure counter as a quadrature + * encoder. + * @INSN_CONFIG_SET_GATE_SRC: Set counter/timer gate source. + * @INSN_CONFIG_GET_GATE_SRC: Get counter/timer gate source. + * @INSN_CONFIG_SET_CLOCK_SRC: Set counter/timer master clock source. + * @INSN_CONFIG_GET_CLOCK_SRC: Get counter/timer master clock source. + * @INSN_CONFIG_SET_OTHER_SRC: Set counter/timer "other" source. + * @INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: Get size (in bytes) of subdevice's + * on-board FIFOs used during streaming + * input/output. + * @INSN_CONFIG_SET_COUNTER_MODE: Set counter/timer mode. + * @INSN_CONFIG_8254_SET_MODE: (Deprecated) Same as + * %INSN_CONFIG_SET_COUNTER_MODE. + * @INSN_CONFIG_8254_READ_STATUS: Read status of 8254 counter channel. + * @INSN_CONFIG_SET_ROUTING: Set routing for a channel. + * @INSN_CONFIG_GET_ROUTING: Get routing for a channel. + * @INSN_CONFIG_PWM_SET_PERIOD: Set PWM period in nanoseconds. + * @INSN_CONFIG_PWM_GET_PERIOD: Get PWM period in nanoseconds. + * @INSN_CONFIG_GET_PWM_STATUS: Get PWM status. + * @INSN_CONFIG_PWM_SET_H_BRIDGE: Set PWM H bridge duty cycle and polarity for + * a relay simultaneously. + * @INSN_CONFIG_PWM_GET_H_BRIDGE: Get PWM H bridge duty cycle and polarity. + */ enum configuration_ids { INSN_CONFIG_DIO_INPUT = 0, INSN_CONFIG_DIO_OUTPUT = 1, @@ -265,72 +332,76 @@ enum configuration_ids { INSN_CONFIG_DISARM = 32, INSN_CONFIG_GET_COUNTER_STATUS = 33, INSN_CONFIG_RESET = 34, - /* Use CTR as single pulsegenerator */ INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, - /* Use CTR as pulsetraingenerator */ INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, - /* Use the counter as encoder */ INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, - INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */ - INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */ - /* Set master clock source */ + INSN_CONFIG_SET_GATE_SRC = 2001, + INSN_CONFIG_GET_GATE_SRC = 2002, INSN_CONFIG_SET_CLOCK_SRC = 2003, - INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */ - INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ - /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ - /* Get size in bytes of subdevice's on-board fifos used during - * streaming input/output - */ + INSN_CONFIG_GET_CLOCK_SRC = 2004, + INSN_CONFIG_SET_OTHER_SRC = 2005, INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, INSN_CONFIG_SET_COUNTER_MODE = 4097, - /* INSN_CONFIG_8254_SET_MODE is deprecated */ INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, INSN_CONFIG_8254_READ_STATUS = 4098, INSN_CONFIG_SET_ROUTING = 4099, INSN_CONFIG_GET_ROUTING = 4109, - /* PWM */ - INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */ - INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ - INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ - /* sets H bridge: duty cycle and sign bit for a relay at the - * same time - */ + INSN_CONFIG_PWM_SET_PERIOD = 5000, + INSN_CONFIG_PWM_GET_PERIOD = 5001, + INSN_CONFIG_GET_PWM_STATUS = 5002, INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, - /* gets H bridge data: duty cycle and the sign bit */ INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 }; -/* - * Settings for INSN_CONFIG_DIGITAL_TRIG: - * data[0] = INSN_CONFIG_DIGITAL_TRIG - * data[1] = trigger ID - * data[2] = configuration operation - * data[3] = configuration parameter 1 - * data[4] = configuration parameter 2 - * data[5] = configuration parameter 3 +/** + * enum comedi_digital_trig_op - operations for configuring a digital trigger + * @COMEDI_DIGITAL_TRIG_DISABLE: Return digital trigger to its default, + * inactive, unconfigured state. + * @COMEDI_DIGITAL_TRIG_ENABLE_EDGES: Set rising and/or falling edge inputs + * that each can fire the trigger. + * @COMEDI_DIGITAL_TRIG_ENABLE_LEVELS: Set a combination of high and/or low + * level inputs that can fire the trigger. + * + * These are used with the %INSN_CONFIG_DIGITAL_TRIG configuration instruction. + * The data for the configuration instruction is as follows... + * + * data[%0] = %INSN_CONFIG_DIGITAL_TRIG * - * operation parameter 1 parameter 2 parameter 3 - * --------------------------------- ----------- ----------- ----------- - * COMEDI_DIGITAL_TRIG_DISABLE - * COMEDI_DIGITAL_TRIG_ENABLE_EDGES left-shift rising-edges falling-edges - * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS left-shift high-levels low-levels + * data[%1] = trigger ID * - * COMEDI_DIGITAL_TRIG_DISABLE returns the trigger to its default, inactive, - * unconfigured state. + * data[%2] = configuration operation * - * COMEDI_DIGITAL_TRIG_ENABLE_EDGES sets the rising and/or falling edge inputs - * that each can fire the trigger. + * data[%3] = configuration parameter 1 * - * COMEDI_DIGITAL_TRIG_ENABLE_LEVELS sets a combination of high and/or low - * level inputs that can fire the trigger. + * data[%4] = configuration parameter 2 * - * "left-shift" is useful if the trigger has more than 32 inputs to specify the - * first input for this configuration. + * data[%5] = configuration parameter 3 * - * Some sequences of INSN_CONFIG_DIGITAL_TRIG instructions may have a (partly) + * The trigger ID (data[%1]) is used to differentiate multiple digital triggers + * belonging to the same subdevice. The configuration operation (data[%2]) is + * one of the enum comedi_digital_trig_op values. The configuration + * parameters (data[%3], data[%4], and data[%5]) depend on the operation; they + * are not used with %COMEDI_DIGITAL_TRIG_DISABLE. + * + * For %COMEDI_DIGITAL_TRIG_ENABLE_EDGES and %COMEDI_DIGITAL_TRIG_ENABLE_LEVELS, + * configuration parameter 1 (data[%3]) contains a "left-shift" value that + * specifies the input corresponding to bit 0 of configuration parameters 2 + * and 3. This is useful if the trigger has more than 32 inputs. + * + * For %COMEDI_DIGITAL_TRIG_ENABLE_EDGES, configuration parameter 2 (data[%4]) + * specifies which of up to 32 inputs have rising-edge sensitivity, and + * configuration parameter 3 (data[%5]) specifies which of up to 32 inputs + * have falling-edge sensitivity that can fire the trigger. + * + * For %COMEDI_DIGITAL_TRIG_ENABLE_LEVELS, configuration parameter 2 (data[%4]) + * specifies which of up to 32 inputs must be at a high level, and + * configuration parameter 3 (data[%5]) specifies which of up to 32 inputs + * must be at a low level for the trigger to fire. + * + * Some sequences of %INSN_CONFIG_DIGITAL_TRIG instructions may have a (partly) * accumulative effect, depending on the low-level driver. This is useful - * when setting up a trigger that has more than 32 inputs or has a combination - * of edge and level triggered inputs. + * when setting up a trigger that has more than 32 inputs, or has a combination + * of edge- and level-triggered inputs. */ enum comedi_digital_trig_op { COMEDI_DIGITAL_TRIG_DISABLE = 0, @@ -338,18 +409,49 @@ enum comedi_digital_trig_op { COMEDI_DIGITAL_TRIG_ENABLE_LEVELS = 2 }; +/** + * enum comedi_io_direction - COMEDI I/O directions + * @COMEDI_INPUT: Input. + * @COMEDI_OUTPUT: Output. + * @COMEDI_OPENDRAIN: Open-drain (or open-collector) output. + * + * These are used by the %INSN_CONFIG_DIO_QUERY configuration instruction to + * report a direction. They may also be used in other places where a direction + * needs to be specified. + */ enum comedi_io_direction { COMEDI_INPUT = 0, COMEDI_OUTPUT = 1, COMEDI_OPENDRAIN = 2 }; +/** + * enum comedi_support_level - support level for a COMEDI feature + * @COMEDI_UNKNOWN_SUPPORT: Unspecified support for feature. + * @COMEDI_SUPPORTED: Feature is supported. + * @COMEDI_UNSUPPORTED: Feature is unsupported. + */ enum comedi_support_level { COMEDI_UNKNOWN_SUPPORT = 0, COMEDI_SUPPORTED, COMEDI_UNSUPPORTED }; +/** + * enum comedi_counter_status_flags - counter status bits + * @COMEDI_COUNTER_ARMED: Counter is armed. + * @COMEDI_COUNTER_COUNTING: Counter is counting. + * @COMEDI_COUNTER_TERMINAL_COUNT: Counter reached terminal count. + * + * These bitwise values are used by the %INSN_CONFIG_GET_COUNTER_STATUS + * configuration instruction to report the status of a counter. + */ +enum comedi_counter_status_flags { + COMEDI_COUNTER_ARMED = 0x1, + COMEDI_COUNTER_COUNTING = 0x2, + COMEDI_COUNTER_TERMINAL_COUNT = 0x4, +}; + /* ioctls */ #define CIO 'd' @@ -849,13 +951,6 @@ enum ni_660x_pfi_routing { #define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1) #define NI_EXT_RTSI(x) (NI_USUAL_RTSI_SELECT(x) - 1) -/* status bits for INSN_CONFIG_GET_COUNTER_STATUS */ -enum comedi_counter_status_flags { - COMEDI_COUNTER_ARMED = 0x1, - COMEDI_COUNTER_COUNTING = 0x2, - COMEDI_COUNTER_TERMINAL_COUNT = 0x4, -}; - /* * Clock sources for CDIO subdevice on NI m-series boards. Used as the * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd -- cgit From ace7aa7f6442444848a731fcb3a445039cda32dd Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 9 Feb 2016 15:17:22 +0000 Subject: staging: comedi: comedi.h: add kernel-doc comments to struct types Add "kernel-doc"-formatted comments to the COMEDI `struct` declarations used with ioctls. Don't bother documenting `struct comedi_trig` as it is obsolete and not supported. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 332 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 325 insertions(+), 7 deletions(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 9ef0963101da..2ab48ce5c5d0 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -491,6 +491,19 @@ struct comedi_trig { unsigned int unused[3]; }; +/** + * struct comedi_insn - COMEDI instruction + * @insn: COMEDI instruction type (%INSN_xxx). + * @n: Length of @data[]. + * @data: Pointer to data array operated on by the instruction. + * @subdev: Subdevice index. + * @chanspec: A packed "chanspec" value consisting of channel number, + * analog range index, analog reference type, and flags. + * @unused: Reserved for future use. + * + * This is used with the %COMEDI_INSN ioctl, and indirectly with the + * %COMEDI_INSNLIST ioctl. + */ struct comedi_insn { unsigned int insn; unsigned int n; @@ -500,11 +513,95 @@ struct comedi_insn { unsigned int unused[3]; }; +/** + * struct comedi_insnlist - list of COMEDI instructions + * @n_insns: Number of COMEDI instructions. + * @insns: Pointer to array COMEDI instructions. + * + * This is used with the %COMEDI_INSNLIST ioctl. + */ struct comedi_insnlist { unsigned int n_insns; struct comedi_insn __user *insns; }; +/** + * struct comedi_cmd - COMEDI asynchronous acquisition command details + * @subdev: Subdevice index. + * @flags: Command flags (%CMDF_xxx). + * @start_src: "Start acquisition" trigger source (%TRIG_xxx). + * @start_arg: "Start acquisition" trigger argument. + * @scan_begin_src: "Scan begin" trigger source. + * @scan_begin_arg: "Scan begin" trigger argument. + * @convert_src: "Convert" trigger source. + * @convert_arg: "Convert" trigger argument. + * @scan_end_src: "Scan end" trigger source. + * @scan_end_arg: "Scan end" trigger argument. + * @stop_src: "Stop acquisition" trigger source. + * @stop_arg: "Stop acquisition" trigger argument. + * @chanlist: Pointer to array of "chanspec" values, containing a + * sequence of channel numbers packed with analog range + * index, etc. + * @chanlist_len: Number of channels in sequence. + * @data: Pointer to miscellaneous set-up data (not used). + * @data_len: Length of miscellaneous set-up data. + * + * This is used with the %COMEDI_CMD or %COMEDI_CMDTEST ioctl to set-up + * or validate an asynchronous acquisition command. The ioctl may modify + * the &struct comedi_cmd and copy it back to the caller. + * + * Optional command @flags values that can be ORed together... + * + * %CMDF_BOGUS - makes %COMEDI_CMD ioctl return error %EAGAIN instead of + * starting the command. + * + * %CMDF_PRIORITY - requests "hard real-time" processing (which is not + * supported in this version of COMEDI). + * + * %CMDF_WAKE_EOS - requests the command makes data available for reading + * after every "scan" period. + * + * %CMDF_WRITE - marks the command as being in the "write" (to device) + * direction. This does not need to be specified by the caller unless the + * subdevice supports commands in either direction. + * + * %CMDF_RAWDATA - prevents the command from "munging" the data between the + * COMEDI sample format and the raw hardware sample format. + * + * %CMDF_ROUND_NEAREST - requests timing periods to be rounded to nearest + * supported values. + * + * %CMDF_ROUND_DOWN - requests timing periods to be rounded down to supported + * values (frequencies rounded up). + * + * %CMDF_ROUND_UP - requests timing periods to be rounded up to supported + * values (frequencies rounded down). + * + * Trigger source values for @start_src, @scan_begin_src, @convert_src, + * @scan_end_src, and @stop_src... + * + * %TRIG_ANY - "all ones" value used to test which trigger sources are + * supported. + * + * %TRIG_INVALID - "all zeroes" value used to indicate that all requested + * trigger sources are invalid. + * + * %TRIG_NONE - never trigger (often used as a @stop_src value). + * + * %TRIG_NOW - trigger after '_arg' nanoseconds. + * + * %TRIG_FOLLOW - trigger follows another event. + * + * %TRIG_TIMER - trigger every '_arg' nanoseconds. + * + * %TRIG_COUNT - trigger when count '_arg' is reached. + * + * %TRIG_EXT - trigger on external signal specified by '_arg'. + * + * %TRIG_INT - trigger on internal, software trigger specified by '_arg'. + * + * %TRIG_OTHER - trigger on other, driver-defined signal specified by '_arg'. + */ struct comedi_cmd { unsigned int subdev; unsigned int flags; @@ -524,13 +621,31 @@ struct comedi_cmd { unsigned int stop_src; unsigned int stop_arg; - unsigned int *chanlist; /* channel/range list */ + unsigned int *chanlist; unsigned int chanlist_len; - short __user *data; /* data list, size depends on subd flags */ + short __user *data; unsigned int data_len; }; +/** + * struct comedi_chaninfo - used to retrieve per-channel information + * @subdev: Subdevice index. + * @maxdata_list: Optional pointer to per-channel maximum data values. + * @flaglist: Optional pointer to per-channel flags. + * @rangelist: Optional pointer to per-channel range types. + * @unused: Reserved for future use. + * + * This is used with the %COMEDI_CHANINFO ioctl to get per-channel information + * for the subdevice. Use of this requires knowledge of the number of channels + * and subdevice flags obtained using the %COMEDI_SUBDINFO ioctl. + * + * The @maxdata_list member must be %NULL unless the %SDF_MAXDATA subdevice + * flag is set. The @flaglist member must be %NULL unless the %SDF_FLAGS + * subdevice flag is set. The @rangelist member must be %NULL unless the + * %SDF_RANGETYPE subdevice flag is set. Otherwise, the arrays they point to + * must be at least as long as the number of channels. + */ struct comedi_chaninfo { unsigned int subdev; unsigned int __user *maxdata_list; @@ -539,17 +654,157 @@ struct comedi_chaninfo { unsigned int unused[4]; }; +/** + * struct comedi_rangeinfo - used to retrieve the range table for a channel + * @range_type: Encodes subdevice index (bits 27:24), channel index + * (bits 23:16) and range table length (bits 15:0). + * @range_ptr: Pointer to array of @struct comedi_krange to be filled + * in with the range table for the channel or subdevice. + * + * This is used with the %COMEDI_RANGEINFO ioctl to retrieve the range table + * for a specific channel (if the subdevice has the %SDF_RANGETYPE flag set to + * indicate that the range table depends on the channel), or for the subdevice + * as a whole (if the %SDF_RANGETYPE flag is clear, indicating the range table + * is shared by all channels). + * + * The @range_type value is an input to the ioctl and comes from a previous + * use of the %COMEDI_SUBDINFO ioctl (if the %SDF_RANGETYPE flag is clear), + * or the %COMEDI_CHANINFO ioctl (if the %SDF_RANGETYPE flag is set). + */ struct comedi_rangeinfo { unsigned int range_type; void __user *range_ptr; }; +/** + * struct comedi_krange - describes a range in a range table + * @min: Minimum value in millionths (1e-6) of a unit. + * @max: Maximum value in millionths (1e-6) of a unit. + * @flags: Indicates the units (in bits 7:0) OR'ed with optional flags. + * + * A range table is associated with a single channel, or with all channels in a + * subdevice, and a list of one or more ranges. A %struct comedi_krange + * describes the physical range of units for one of those ranges. Sample + * values in COMEDI are unsigned from %0 up to some 'maxdata' value. The + * mapping from sample values to physical units is assumed to be nomimally + * linear (for the purpose of describing the range), with sample value %0 + * mapping to @min, and the 'maxdata' sample value mapping to @max. + * + * The currently defined units are %UNIT_volt (%0), %UNIT_mA (%1), and + * %UNIT_none (%2). The @min and @max values are the physical range multiplied + * by 1e6, so a @max value of %1000000 (with %UNIT_volt) represents a maximal + * value of 1 volt. + * + * The only defined flag value is %RF_external (%1 << %8), indicating that the + * the range needs to be multiplied by an external reference. + */ struct comedi_krange { - int min; /* fixed point, multiply by 1e-6 */ - int max; /* fixed point, multiply by 1e-6 */ + int min; + int max; unsigned int flags; }; +/** + * struct comedi_subdinfo - used to retrieve information about a subdevice + * @type: Type of subdevice from &enum comedi_subdevice_type. + * @n_chan: Number of channels the subdevice supports. + * @subd_flags: A mixture of static and dynamic flags describing + * aspects of the subdevice and its current state. + * @timer_type: Timer type. Always set to %5 ("nanosecond timer"). + * @len_chanlist: Maximum length of a channel list if the subdevice + * supports asynchronous acquisition commands. + * @maxdata: Maximum sample value for all channels if the + * %SDF_MAXDATA subdevice flag is clear. + * @flags: Channel flags for all channels if the %SDF_FLAGS + * subdevice flag is clear. + * @range_type: The range type for all channels if the %SDF_RANGETYPE + * subdevice flag is clear. Encodes the subdevice index + * (bits 27:24), a dummy channel index %0 (bits 23:16), + * and the range table length (bits 15:0). + * @settling_time_0: Not used. + * @insn_bits_support: Set to %COMEDI_SUPPORTED if the subdevice supports the + * %INSN_BITS instruction, or to %COMEDI_UNSUPPORTED if it + * does not. + * @unused: Reserved for future use. + * + * This is used with the %COMEDI_SUBDINFO ioctl which copies an array of + * &struct comedi_subdinfo back to user space, with one element per subdevice. + * Use of this requires knowledge of the number of subdevices obtained from + * the %COMEDI_DEVINFO ioctl. + * + * These are the @subd_flags values that may be ORed together... + * + * %SDF_BUSY - the subdevice is busy processing an asynchronous command or a + * synchronous instruction. + * + * %SDF_BUSY_OWNER - the subdevice is busy processing an asynchronous + * acquisition command started on the current file object (the file object + * issuing the %COMEDI_SUBDINFO ioctl). + * + * %SDF_LOCKED - the subdevice is locked by a %COMEDI_LOCK ioctl. + * + * %SDF_LOCK_OWNER - the subdevice is locked by a %COMEDI_LOCK ioctl from the + * current file object. + * + * %SDF_MAXDATA - maximum sample values are channel-specific. + * + * %SDF_FLAGS - channel flags are channel-specific. + * + * %SDF_RANGETYPE - range types are channel-specific. + * + * %SDF_MODE0 (aliased as %SDF_PWM_COUNTER) - the subdevice can do mode 0 (?) + * or PWM can switch off automatically. + * + * %SDF_MODE1 (aliased as %SDF_PWM_HBRIDGE) - the subdevice can do mode 1 (?) + * or PWM is signed (H-bridge). + * + * %SDF_MODE2 - the subdevice can do mode 2 (?). + * + * %SDF_MODE3 - the subdevice can do mode 3 (?). + * + * %SDF_MODE4 - the subdevice can do mode 4 (?). + * + * %SDF_CMD - the subdevice supports asynchronous commands. + * + * %SDF_SOFT_CALIBRATED - the subdevice uses software calibration. + * + * %SDF_CMD_WRITE - the subdevice supports asynchronous commands in the output + * ("write") direction. + * + * %SDF_CMD_READ - the subdevice supports asynchronous commands in the input + * ("read") direction. + * + * %SDF_READABLE - the subdevice is readable (e.g. analog input). + * + * %SDF_WRITABLE (aliased as %SDF_WRITEABLE) - the subdevice is writable (e.g. + * analog output). + * + * %SDF_INTERNAL - the subdevice has no externally visible lines. + * + * %SDF_GROUND - the subdevice can use ground as an analog reference. + * + * %SDF_COMMON - the subdevice can use a common analog reference. + * + * %SDF_DIFF - the subdevice can use differential inputs (or outputs). + * + * %SDF_OTHER - the subdevice can use some other analog reference. + * + * %SDF_DITHER - the subdevice can do dithering. + * + * %SDF_DEGLITCH - the subdevice can do deglitching. + * + * %SDF_MMAP - this is never set. + * + * %SDF_RUNNING - an asynchronous command is still running. + * + * %SDF_LSAMPL - the subdevice uses "long" (32-bit) samples (for asynchronous + * command data). + * + * %SDF_PACKED - the subdevice packs several DIO samples into a single sample + * (for asynchronous command data). + * + * No "channel flags" (@flags) values are currently defined. + */ struct comedi_subdinfo { unsigned int type; unsigned int n_chan; @@ -557,14 +812,26 @@ struct comedi_subdinfo { unsigned int timer_type; unsigned int len_chanlist; unsigned int maxdata; - unsigned int flags; /* channel flags */ - unsigned int range_type; /* lookup in kernel */ + unsigned int flags; + unsigned int range_type; unsigned int settling_time_0; - /* see support_level enum for values */ unsigned insn_bits_support; unsigned int unused[8]; }; +/** + * struct comedi_devinfo - used to retrieve information about a COMEDI device + * @version_code: COMEDI version code. + * @n_subdevs: Number of subdevices the device has. + * @driver_name: Null-terminated COMEDI driver name. + * @board_name: Null-terminated COMEDI board name. + * @read_subdevice: Index of the current "read" subdevice (%-1 if none). + * @write_subdevice: Index of the current "write" subdevice (%-1 if none). + * @unused: Reserved for future use. + * + * This is used with the %COMEDI_DEVINFO ioctl to get basic information about + * the device. + */ struct comedi_devinfo { unsigned int version_code; unsigned int n_subdevs; @@ -575,11 +842,45 @@ struct comedi_devinfo { int unused[30]; }; +/** + * struct comedi_devconfig - used to configure a legacy COMEDI device + * @board_name: Null-terminated string specifying the type of board + * to configure. + * @options: An array of integer configuration options. + * + * This is used with the %COMEDI_DEVCONFIG ioctl to configure a "legacy" COMEDI + * device, such as an ISA card. Not all COMEDI drivers support this. Those + * that do either expect the specified board name to match one of a list of + * names registered with the COMEDI core, or expect the specified board name + * to match the COMEDI driver name itself. The configuration options are + * handled in a driver-specific manner. + */ struct comedi_devconfig { char board_name[COMEDI_NAMELEN]; int options[COMEDI_NDEVCONFOPTS]; }; +/** + * struct comedi_bufconfig - used to set or get buffer size for a subdevice + * @subdevice: Subdevice index. + * @flags: Not used. + * @maximum_size: Maximum allowed buffer size. + * @size: Buffer size. + * @unused: Reserved for future use. + * + * This is used with the %COMEDI_BUFCONFIG ioctl to get or configure the + * maximum buffer size and current buffer size for a COMEDI subdevice that + * supports asynchronous commands. If the subdevice does not support + * asynchronous commands, @maximum_size and @size are ignored and set to 0. + * + * On ioctl input, non-zero values of @maximum_size and @size specify a + * new maximum size and new current size (in bytes), respectively. These + * will by rounded up to a multiple of %PAGE_SIZE. Specifying a new maximum + * size requires admin capabilities. + * + * On ioctl output, @maximum_size and @size and set to the current maximum + * buffer size and current buffer size, respectively. + */ struct comedi_bufconfig { unsigned int subdevice; unsigned int flags; @@ -590,6 +891,23 @@ struct comedi_bufconfig { unsigned int unused[4]; }; +/** + * struct comedi_bufinfo - used to manipulate buffer position for a subdevice + * @subdevice: Subdevice index. + * @bytes_read: Specify amount to advance read position for an + * asynchronous command in the input ("read") direction. + * @buf_write_ptr: Current write position (index) within the buffer. + * @buf_read_ptr: Current read position (index) within the buffer. + * @buf_write_count: Total amount written, modulo 2^32. + * @buf_read_count: Total amount read, modulo 2^32. + * @bytes_written: Specify amount to advance write position for an + * asynchronous command in the output ("write") direction. + * @unused: Reserved for future use. + * + * This is used with the %COMEDI_BUFINFO ioctl to optionally advance the + * current read or write position in an asynchronous acquisition data buffer, + * and to get the current read and write positions in the buffer. + */ struct comedi_bufinfo { unsigned int subdevice; unsigned int bytes_read; -- cgit From 75aa1ca7f7d706173238907605cc4f9ada9910c4 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 9 Feb 2016 15:17:23 +0000 Subject: staging: comedi: comedi.h: remove struct comedi_trig Remove `struct comedi_trig` and some associated macros, `TRIG_DITHER`, `TRIG_DEGLITCH`, `TRIG_CONFIG`, and ioctl code `COMEDI_TRIG`. These have been obsolete since COMEDI release 0.7.61 back in November 2001. The userspace COMEDILIB library still has some deprecated code that may attempt to use these, but it uses its own, compatible version of "comedi.h", so isn't affected by their removal from the kernel copy. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 2ab48ce5c5d0..c562be866424 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -120,13 +120,6 @@ #define INSN_WAIT (5 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) #define INSN_INTTRIG (6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) -/* trigger flags */ -/* These flags are used in comedi_trig structures */ - -#define TRIG_DITHER 0x0002 /* enable dithering */ -#define TRIG_DEGLITCH 0x0004 /* enable deglitching */ -#define TRIG_CONFIG 0x0010 /* perform configuration, not triggering */ - /* command flags */ /* These flags are used in comedi_cmd structures */ @@ -459,7 +452,7 @@ enum comedi_counter_status_flags { #define COMEDI_DEVINFO _IOR(CIO, 1, struct comedi_devinfo) #define COMEDI_SUBDINFO _IOR(CIO, 2, struct comedi_subdinfo) #define COMEDI_CHANINFO _IOR(CIO, 3, struct comedi_chaninfo) -#define COMEDI_TRIG _IOWR(CIO, 4, comedi_trig) +/* _IOWR(CIO, 4, ...) is reserved */ #define COMEDI_LOCK _IO(CIO, 5) #define COMEDI_UNLOCK _IO(CIO, 6) #define COMEDI_CANCEL _IO(CIO, 7) @@ -476,21 +469,6 @@ enum comedi_counter_status_flags { /* structures */ -struct comedi_trig { - unsigned int subdev; /* subdevice */ - unsigned int mode; /* mode */ - unsigned int flags; - unsigned int n_chan; /* number of channels */ - unsigned int *chanlist; /* channel/range list */ - short *data; /* data list, size depends on subd flags */ - unsigned int n; /* number of scans */ - unsigned int trigsrc; - unsigned int trigvar; - unsigned int trigvar1; - unsigned int data_len; - unsigned int unused[3]; -}; - /** * struct comedi_insn - COMEDI instruction * @insn: COMEDI instruction type (%INSN_xxx). -- cgit From 222c402abfc864bbabd7cb359f0ebce36558f123 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 9 Feb 2016 15:17:24 +0000 Subject: staging: comedi: comedi.h: remove SDF_MODE0 etc. The macros `SDF_MODE0`, `SDF_MODE1`, `SDF_MODE2`, `SDF_MODE3`, and `SDF_MODE4` are COMEDI subdevice flags originally associated with the obsolete (and no longer present) COMEDI "trigger" functionality. They have been of no use since COMEDI release 0.7.61 back in November 2001. Since they were going spare, a couple of them have been aliased as `SDF_PWM_COUNTER` and `SDF_PWM_HBRIDGE` to mean other things. Remove the obsolete macros and redefine `SDF_PWM_COUNTER` and `SDF_PWM_HBRIDGE` as equivalent numeric values. Some code distributed with the userspace COMEDILIB library uses the `SDF_MODE0` etc. flags to display the fact that they are set, but COMEDILIB uses and installs its own, compatible version of "comedi.h" anyway so isn't affected by their removal from the kernel copy. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index c562be866424..aa7263cd926a 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -183,11 +183,8 @@ #define SDF_MAXDATA 0x0010 /* maxdata depends on channel */ #define SDF_FLAGS 0x0020 /* flags depend on channel */ #define SDF_RANGETYPE 0x0040 /* range type depends on channel */ -#define SDF_MODE0 0x0080 /* can do mode 0 */ -#define SDF_MODE1 0x0100 /* can do mode 1 */ -#define SDF_MODE2 0x0200 /* can do mode 2 */ -#define SDF_MODE3 0x0400 /* can do mode 3 */ -#define SDF_MODE4 0x0800 /* can do mode 4 */ +#define SDF_PWM_COUNTER 0x0080 /* PWM can automatically switch off */ +#define SDF_PWM_HBRIDGE 0x0100 /* PWM is signed (H-bridge) */ #define SDF_CMD 0x1000 /* can do commands (deprecated) */ #define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */ #define SDF_CMD_WRITE 0x4000 /* can do output commands */ @@ -210,9 +207,6 @@ #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ #define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */ -/* re recycle these flags for PWM */ -#define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ -#define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ /* subdevice types */ @@ -730,17 +724,9 @@ struct comedi_krange { * * %SDF_RANGETYPE - range types are channel-specific. * - * %SDF_MODE0 (aliased as %SDF_PWM_COUNTER) - the subdevice can do mode 0 (?) - * or PWM can switch off automatically. + * %SDF_PWM_COUNTER - PWM can switch off automatically. * - * %SDF_MODE1 (aliased as %SDF_PWM_HBRIDGE) - the subdevice can do mode 1 (?) - * or PWM is signed (H-bridge). - * - * %SDF_MODE2 - the subdevice can do mode 2 (?). - * - * %SDF_MODE3 - the subdevice can do mode 3 (?). - * - * %SDF_MODE4 - the subdevice can do mode 4 (?). + * %SDF_PWM_HBRIDGE - or PWM is signed (H-bridge). * * %SDF_CMD - the subdevice supports asynchronous commands. * -- cgit From e563637b5fef2d1fbcd1efe457d4168fde7b3e0d Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 19:07:48 -0500 Subject: staging: comedi: Use ARRAY_SIZE for sizes of arrays Use ARRAY_SIZE to calculate the size of an array to make code concise. The semantic patch used can be found here: https://github.com/coccinelle/coccinellery/commit/9cbab452a3a2e18439e8386d6c4a68ee42c3ee2b Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_c_common.c | 0 drivers/staging/comedi/drivers/ni_mio_common.c | 7 ++----- 2 files changed, 2 insertions(+), 5 deletions(-) create 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 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 929389b52572..1c2abb3feb42 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1166,8 +1166,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, comedi_buf_write_samples(s, &data, 1); } } else { - if (n > sizeof(devpriv->ai_fifo_buffer) / - sizeof(devpriv->ai_fifo_buffer[0])) { + if (n > ARRAY_SIZE(devpriv->ai_fifo_buffer)) { dev_err(dev->class_dev, "bug! ai_fifo_buffer too small\n"); async->events |= COMEDI_CB_ERROR; @@ -1242,9 +1241,7 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) NISTC_AI_STATUS1_FIFO_E; while (fifo_empty == 0) { for (i = 0; - i < - sizeof(devpriv->ai_fifo_buffer) / - sizeof(devpriv->ai_fifo_buffer[0]); i++) { + i < ARRAY_SIZE(devpriv->ai_fifo_buffer); i++) { fifo_empty = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & NISTC_AI_STATUS1_FIFO_E; -- cgit From 72315cdaba9db965af38c9b756333e2f2b8d48ec Mon Sep 17 00:00:00 2001 From: Aybuke Ozdemir Date: Wed, 10 Feb 2016 18:02:25 +0200 Subject: Staging: comedi: Prefer using the BIT macro Replace all instances of bit shifting on 1 with the BIT(x) macro. In addition, convert other non-1 shift operations with the equivalent BIT(x) macro for uniformity. Issue pointed out by checkpatch. CHECK: Prefer using the BIT macro Signed-off-by: Aybuke Ozdemir Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index aa7263cd926a..f1415cbcd3f0 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -72,12 +72,12 @@ #define CR_AREF(a) (((a) >> 24) & 0x03) #define CR_FLAGS_MASK 0xfc000000 -#define CR_ALT_FILTER (1 << 26) +#define CR_ALT_FILTER BIT(26) #define CR_DITHER CR_ALT_FILTER #define CR_DEGLITCH CR_ALT_FILTER -#define CR_ALT_SOURCE (1 << 27) -#define CR_EDGE (1 << 30) -#define CR_INVERT (1 << 31) +#define CR_ALT_SOURCE BIT(27) +#define CR_EDGE BIT(30) +#define CR_INVERT BIT(31) #define AREF_GROUND 0x00 /* analog ref = analog ground */ #define AREF_COMMON 0x01 /* analog ref = analog common */ @@ -894,7 +894,7 @@ struct comedi_bufinfo { #define RANGE_LENGTH(b) ((b) & 0xffff) #define RF_UNIT(flags) ((flags) & 0xff) -#define RF_EXTERNAL (1 << 8) +#define RF_EXTERNAL BIT(8) #define UNIT_volt 0 #define UNIT_mA 1 -- cgit From 89322a09f213146e92c16c0b7116c78de646827e Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 9 Feb 2016 19:57:40 +0530 Subject: Staging: xgifb: Remove space after type cast This patch removes unnecessary space after type casts. Found using checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index c886dd2892a4..bb7756c22b99 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -274,12 +274,12 @@ static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo, for (i = 0x01; i <= 0x04; i++) { data = pVBInfo->TimingH.data[i]; - xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 1), data); + xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 1), data); } for (i = 0x05; i <= 0x06; i++) { data = pVBInfo->TimingH.data[i]; - xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i + 6), data); + xgifb_reg_set(pVBInfo->P3c4, (unsigned short)(i + 6), data); } j = xgifb_reg_get(pVBInfo->P3c4, 0x0e); @@ -325,17 +325,17 @@ static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, for (i = 0x00; i <= 0x01; i++) { data = pVBInfo->TimingV.data[i]; - xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 6), data); + xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 6), data); } for (i = 0x02; i <= 0x03; i++) { data = pVBInfo->TimingV.data[i]; - xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x0e), data); + xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 0x0e), data); } for (i = 0x04; i <= 0x05; i++) { data = pVBInfo->TimingV.data[i]; - xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x11), data); + xgifb_reg_set(pVBInfo->P3d4, (unsigned short)(i + 0x11), data); } j = xgifb_reg_get(pVBInfo->P3c4, 0x0a); @@ -433,7 +433,7 @@ static void XGI_SetXG21CRTC(unsigned short RefreshRateTableIndex, Temp2 |= 0x40; /* Temp2 + 0x40 */ Temp2 &= 0xFF; - Tempax = (unsigned char) Temp2; /* Tempax: HRE[7:0] */ + Tempax = (unsigned char)Temp2; /* Tempax: HRE[7:0] */ Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */ Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */ Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */ @@ -483,11 +483,11 @@ static void XGI_SetXG21CRTC(unsigned short RefreshRateTableIndex, Temp2 |= 0x20; /* VRE + 0x20 */ Temp2 &= 0xFF; - Tempax = (unsigned char) Temp2; /* Tempax: VRE[7:0] */ + Tempax = (unsigned char)Temp2; /* Tempax: VRE[7:0] */ Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */ Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */ Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */ - Tempbx = (unsigned char) Temp1; + Tempbx = (unsigned char)Temp1; Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */ Tempax &= 0x7F; /* SR3F D[7:2]->VRE D[1:0]->VRS */ @@ -716,10 +716,10 @@ static void XGI_SetCRT1DE(unsigned short ModeIdIndex, data = xgifb_reg_get(pVBInfo->P3d4, 0x11); data &= 0x7F; xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */ - xgifb_reg_set(pVBInfo->P3d4, 0x01, (unsigned short) (tempcx & 0xff)); + xgifb_reg_set(pVBInfo->P3d4, 0x01, (unsigned short)(tempcx & 0xff)); xgifb_reg_and_or(pVBInfo->P3d4, 0x0b, ~0x0c, - (unsigned short) ((tempcx & 0x0ff00) >> 10)); - xgifb_reg_set(pVBInfo->P3d4, 0x12, (unsigned short) (tempbx & 0xff)); + (unsigned short)((tempcx & 0x0ff00) >> 10)); + xgifb_reg_set(pVBInfo->P3d4, 0x12, (unsigned short)(tempbx & 0xff)); tempax = 0; tempbx >>= 8; -- cgit From cb601424ba42ba1db2bf71a05168dc9c29036119 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Tue, 9 Feb 2016 19:57:41 +0530 Subject: Staging: xgifb: Remove unnecessary blank lines This patch removes unnecessary blank lines after { and before }. Found using checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/vb_setmode.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index bb7756c22b99..de96da181bd2 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -61,7 +61,6 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo) if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08)) pVBInfo->XGINew_CR97 = 0x80; } - } static void XGI_SetSeqRegs(struct vb_device_info *pVBInfo) @@ -155,7 +154,6 @@ static void XGI_ClearExt1Regs(struct vb_device_info *pVBInfo) static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo) { - xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x20); xgifb_reg_set(pVBInfo->P3c4, 0x2B, XGI_VCLKData[0].SR2B); xgifb_reg_set(pVBInfo->P3c4, 0x2C, XGI_VCLKData[0].SR2C); @@ -592,7 +590,6 @@ static void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo) xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80); /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */ xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80); - } static void xgifb_set_lcd(int chip_id, @@ -930,7 +927,6 @@ static void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo) xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x40, temp); /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */ xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80); - } static void XGI_SetCRT1FIFO(struct xgi_hw_device_info *HwDeviceExtension, @@ -990,7 +986,6 @@ static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, xgifb_reg_and_or(pVBInfo->P3c4, 0x07, 0xFC, data2); if (HwDeviceExtension->jChipType >= XG27) xgifb_reg_and_or(pVBInfo->P3c4, 0x40, 0xFC, data2 & 0x03); - } static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, @@ -1072,7 +1067,6 @@ static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, data = 0x6c; xgifb_reg_set(pVBInfo->P3d4, 0x52, data); } - } static void XGI_WriteDAC(unsigned short dl, -- cgit From 7aa546e4102ae86111d170ba3c36c0c7da761192 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 17:30:16 -0500 Subject: staging: xgifb: Remove unneeded parentheses Remove unneeded parentheses around the right hand side of assignments as they are not needed. Semantic patch: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/xgifb/XGI_main_26.c | 20 ++++++++++---------- drivers/staging/xgifb/vb_setmode.c | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c index f11cea17f2b8..cc55a17f9b7f 100644 --- a/drivers/staging/xgifb/XGI_main_26.c +++ b/drivers/staging/xgifb/XGI_main_26.c @@ -655,26 +655,26 @@ static void XGIfb_pre_setmode(struct xgifb_video_info *xgifb_info) switch (xgifb_info->display2) { case XGIFB_DISP_CRT: - cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr30 = SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE; cr31 |= SIS_DRIVER_MODE; break; case XGIFB_DISP_LCD: - cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr30 = SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE; cr31 |= SIS_DRIVER_MODE; break; case XGIFB_DISP_TV: if (xgifb_info->TV_type == TVMODE_HIVISION) - cr30 = (SIS_VB_OUTPUT_HIVISION - | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr30 = SIS_VB_OUTPUT_HIVISION + | SIS_SIMULTANEOUS_VIEW_ENABLE; else if (xgifb_info->TV_plug == TVPLUG_SVIDEO) - cr30 = (SIS_VB_OUTPUT_SVIDEO - | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr30 = SIS_VB_OUTPUT_SVIDEO + | SIS_SIMULTANEOUS_VIEW_ENABLE; else if (xgifb_info->TV_plug == TVPLUG_COMPOSITE) - cr30 = (SIS_VB_OUTPUT_COMPOSITE - | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr30 = SIS_VB_OUTPUT_COMPOSITE + | SIS_SIMULTANEOUS_VIEW_ENABLE; else if (xgifb_info->TV_plug == TVPLUG_SCART) - cr30 = (SIS_VB_OUTPUT_SCART - | SIS_SIMULTANEOUS_VIEW_ENABLE); + cr30 = SIS_VB_OUTPUT_SCART + | SIS_SIMULTANEOUS_VIEW_ENABLE; cr31 |= SIS_DRIVER_MODE; if (XGIfb_tvmode == 1 || xgifb_info->TV_type == TVMODE_PAL) diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index de96da181bd2..2078d57e97a4 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -1899,8 +1899,8 @@ static void XGI_GetVBInfo(unsigned short ModeIdIndex, push <<= 8; tempax = temp << 8; tempbx = tempbx | tempax; - temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA - | SetInSlaveMode | DisableCRT2Display); + temp = SetCRT2ToDualEdge | SetCRT2ToYPbPr525750 | XGI_SetCRT2ToLCDA + | SetInSlaveMode | DisableCRT2Display; temp = 0xFFFF ^ temp; tempbx &= temp; @@ -2881,7 +2881,7 @@ static void XGI_SetGroup1(unsigned short ModeIdIndex, xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp); temp = tempcx & 0x00FF; xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp); - tempcx = (pVBInfo->VGAVT - 1); + tempcx = pVBInfo->VGAVT - 1; temp = tempcx & 0x00FF; xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp); @@ -2919,7 +2919,7 @@ static void XGI_SetGroup1(unsigned short ModeIdIndex, temp = tempbx & 0x00FF; xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp); temp = ((tempbx & 0xFF00) >> 8) << 4; - temp = ((tempcx & 0x000F) | (temp)); + temp = (tempcx & 0x000F) | (temp); xgifb_reg_set(pVBInfo->Part1Port, 0x11, temp); tempax = 0; @@ -4074,7 +4074,7 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, tempcx |= 0x04000; if (tempeax <= tempebx) { - tempcx = (tempcx & (~0x4000)); + tempcx = tempcx & (~0x4000); tempeax = pVBInfo->VGAVDE; } else { tempeax -= tempebx; @@ -4124,7 +4124,7 @@ static void XGI_SetGroup4(unsigned short ModeIdIndex, temp = (tempax & 0xFF00) >> 8; temp = (temp & 0x0003) << 4; xgifb_reg_set(pVBInfo->Part4Port, 0x1E, temp); - temp = (tempax & 0x00FF); + temp = tempax & 0x00FF; xgifb_reg_set(pVBInfo->Part4Port, 0x1D, temp); if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVision)) { @@ -4926,7 +4926,7 @@ static void XGI_SetCRT2ModeRegs(struct vb_device_info *pVBInfo) tempcl -= ModeVGA; if (tempcl >= 0) { /* BT Color */ - tempah = (0x008 >> tempcl); + tempah = 0x008 >> tempcl; if (tempah == 0) tempah = 1; tempah |= 0x040; -- cgit From 210ba93a18c1192e92c3db7435b595c1fd00a510 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Wed, 10 Feb 2016 04:06:50 -0500 Subject: staging: slicoss: Align #define constants Aligning the constants in the macros improves code readability. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/slicoss/slicoss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c index c490b7166a8d..a91c60a3a202 100644 --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c @@ -58,9 +58,9 @@ #define DEBUG_MICROCODE 1 #define DBG 1 #define SLIC_INTERRUPT_PROCESS_LIMIT 1 -#define SLIC_OFFLOAD_IP_CHECKSUM 1 -#define STATS_TIMER_INTERVAL 2 -#define PING_TIMER_INTERVAL 1 +#define SLIC_OFFLOAD_IP_CHECKSUM 1 +#define STATS_TIMER_INTERVAL 2 +#define PING_TIMER_INTERVAL 1 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -- cgit From 127bf16602c47ed3c6b5ee619ac101316ea9b972 Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Mon, 8 Feb 2016 06:39:21 +0000 Subject: staging: dgnc: convert to wait_event_interruptible_timeout This patch makes use of wait_event_interruptible_timeout to achieve timeout functionality.This is a TODO mentiond in the comment which is also removed.It also aligns with what the function is supposed to do as in the comments. Signed-off-by: Hari Prasath Gujulan Elango 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 39c76e78e56a..ee3155bcc6d2 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -1306,10 +1306,10 @@ static int neo_drain(struct tty_struct *tty, uint seconds) /* * Go to sleep waiting for the tty layer to wake me back up when * the empty flag goes away. - * - * NOTE: TODO: Do something with time passed in. */ - rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0)); + rc = wait_event_interruptible_timeout(un->un_flags_wait, + ((un->un_flags & UN_EMPTY) == 0), + msecs_to_jiffies(seconds * 1000)); /* If ret is non-zero, user ctrl-c'ed us */ return rc; -- cgit From 375b4d427e469dfe4a7d3c9a9ec6ad3109744090 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:53 +0200 Subject: staging: sm750fb: formatPllReg: rename ulPllReg to reg Remove HungarianCamelCase notation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index a9a8884bbcfd..6ab26a9d5bc0 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -355,13 +355,13 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) unsigned int formatPllReg(pll_value_t *pPLL) { - unsigned int ulPllReg = 0; + unsigned int reg = 0; /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter to work out the bit fields in the register. On returning a 32 bit number, the value can be applied to any PLL in the calling function. */ - ulPllReg = + reg = FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF) | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON) | FIELD_SET(0, PANEL_PLL_CTRL, INPUT, OSC) @@ -372,7 +372,7 @@ unsigned int formatPllReg(pll_value_t *pPLL) | FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N) | FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M); - return ulPllReg; + return reg; } -- cgit From 0c4d85fc7fd3ec2a335332ec80701cee680281fd Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:54 +0200 Subject: staging: sm750fb: formatPllReg: fix comment formatting Fix comment alignment and formatting to follow kernel coding style Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 6ab26a9d5bc0..940c43ffe78b 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -357,10 +357,12 @@ unsigned int formatPllReg(pll_value_t *pPLL) { unsigned int reg = 0; - /* Note that all PLL's have the same format. Here, we just use Panel PLL parameter - to work out the bit fields in the register. - On returning a 32 bit number, the value can be applied to any PLL in the calling function. - */ + /* + * Note that all PLL's have the same format. Here, we just use + * Panel PLL parameter to work out the bit fields in the + * register. On returning a 32 bit number, the value can be + * applied to any PLL in the calling function. + */ reg = FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF) | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON) -- cgit From 54feb9315366dda58a66180ed9015974964e5cc3 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:55 +0200 Subject: staging: sm750fb: rename PANEL_PLL_CTRL_* fields to PLL_CTRL_* Several PLL control registers have the same layout and therefore the field definitions may be shared for those registers. Renaming definitions of PANEL_PLL_CTRL_* fields to more generic PLL_CTRL_* will allow reusing these definitions for other PLL control registers. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 22 +++++++++++----------- drivers/staging/sm750fb/ddk750_display.c | 4 ++-- drivers/staging/sm750fb/ddk750_reg.h | 28 ++++++++++++++-------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 940c43ffe78b..277e5c55f9e7 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -36,10 +36,10 @@ static unsigned int get_mxclk_freq(void) return MHz(130); pll_reg = PEEK32(MXCLK_PLL_CTRL); - M = FIELD_GET(pll_reg, PANEL_PLL_CTRL, M); - N = FIELD_GET(pll_reg, PANEL_PLL_CTRL, N); - OD = FIELD_GET(pll_reg, PANEL_PLL_CTRL, OD); - POD = FIELD_GET(pll_reg, PANEL_PLL_CTRL, POD); + M = FIELD_GET(pll_reg, PLL_CTRL, M); + N = FIELD_GET(pll_reg, PLL_CTRL, N); + OD = FIELD_GET(pll_reg, PLL_CTRL, OD); + POD = FIELD_GET(pll_reg, PLL_CTRL, POD); return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD); } @@ -364,15 +364,15 @@ unsigned int formatPllReg(pll_value_t *pPLL) * applied to any PLL in the calling function. */ reg = - FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF) - | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON) - | FIELD_SET(0, PANEL_PLL_CTRL, INPUT, OSC) + FIELD_SET(0, PLL_CTRL, BYPASS, OFF) + | FIELD_SET(0, PLL_CTRL, POWER, ON) + | FIELD_SET(0, PLL_CTRL, INPUT, OSC) #ifndef VALIDATION_CHIP - | FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD) + | FIELD_VALUE(0, PLL_CTRL, POD, pPLL->POD) #endif - | FIELD_VALUE(0, PANEL_PLL_CTRL, OD, pPLL->OD) - | FIELD_VALUE(0, PANEL_PLL_CTRL, N, pPLL->N) - | FIELD_VALUE(0, PANEL_PLL_CTRL, M, pPLL->M); + | FIELD_VALUE(0, PLL_CTRL, OD, pPLL->OD) + | FIELD_VALUE(0, PLL_CTRL, N, pPLL->N) + | FIELD_VALUE(0, PLL_CTRL, M, pPLL->M); return reg; } diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 1a29ae037ee3..514f909217d5 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -126,8 +126,8 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ - if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) == - PANEL_PLL_CTRL_POWER_OFF) || + if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PLL_CTRL, POWER) == + PLL_CTRL_POWER_OFF) || (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) == PANEL_DISPLAY_CTRL_TIMING_DISABLE)) { return; diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index a90b56f55f1e..1ad8d554e249 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -517,23 +517,23 @@ #define PLL_CLK_COUNT_COUNTER 15:0 #define PANEL_PLL_CTRL 0x00005C -#define PANEL_PLL_CTRL_BYPASS 18:18 -#define PANEL_PLL_CTRL_BYPASS_OFF 0 -#define PANEL_PLL_CTRL_BYPASS_ON 1 -#define PANEL_PLL_CTRL_POWER 17:17 -#define PANEL_PLL_CTRL_POWER_OFF 0 -#define PANEL_PLL_CTRL_POWER_ON 1 -#define PANEL_PLL_CTRL_INPUT 16:16 -#define PANEL_PLL_CTRL_INPUT_OSC 0 -#define PANEL_PLL_CTRL_INPUT_TESTCLK 1 +#define PLL_CTRL_BYPASS 18:18 +#define PLL_CTRL_BYPASS_OFF 0 +#define PLL_CTRL_BYPASS_ON 1 +#define PLL_CTRL_POWER 17:17 +#define PLL_CTRL_POWER_OFF 0 +#define PLL_CTRL_POWER_ON 1 +#define PLL_CTRL_INPUT 16:16 +#define PLL_CTRL_INPUT_OSC 0 +#define PLL_CTRL_INPUT_TESTCLK 1 #ifdef VALIDATION_CHIP - #define PANEL_PLL_CTRL_OD 15:14 + #define PLL_CTRL_OD 15:14 #else - #define PANEL_PLL_CTRL_POD 15:14 - #define PANEL_PLL_CTRL_OD 13:12 + #define PLL_CTRL_POD 15:14 + #define PLL_CTRL_OD 13:12 #endif -#define PANEL_PLL_CTRL_N 11:8 -#define PANEL_PLL_CTRL_M 7:0 +#define PLL_CTRL_N 11:8 +#define PLL_CTRL_M 7:0 #define CRT_PLL_CTRL 0x000060 #define CRT_PLL_CTRL_BYPASS 18:18 -- cgit From 79254c60db6a5cbb72a9cb5eb1c3c50d6cdf755a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:56 +0200 Subject: staging: sm750fb: use PLL_CTRL_POWER defines for CRT_PLL_CTRL Use PLL_CTRL_POWER definitions for CRT_PLL_CTRL register access Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 514f909217d5..5d1f9a517388 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -149,8 +149,8 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ - if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) == - CRT_PLL_CTRL_POWER_OFF) || + if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), PLL_CTRL, POWER) == + PLL_CTRL_POWER_OFF) || (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) == CRT_DISPLAY_CTRL_TIMING_DISABLE)) { return; -- cgit From 5557eb17b3f14b92f2512d43ff6d68c6f0a609ef Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:57 +0200 Subject: staging: sm750fb: use BIT macro for PLL_CTRL single-bit fields Replace complex defintion of PLL_CTRL fields with BIT() macro and use open-coded implementation for PLL register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 5 +---- drivers/staging/sm750fb/ddk750_display.c | 6 ++---- drivers/staging/sm750fb/ddk750_reg.h | 12 +++--------- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 277e5c55f9e7..467b858c8d4a 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -363,10 +363,7 @@ unsigned int formatPllReg(pll_value_t *pPLL) * register. On returning a 32 bit number, the value can be * applied to any PLL in the calling function. */ - reg = - FIELD_SET(0, PLL_CTRL, BYPASS, OFF) - | FIELD_SET(0, PLL_CTRL, POWER, ON) - | FIELD_SET(0, PLL_CTRL, INPUT, OSC) + reg = PLL_CTRL_POWER #ifndef VALIDATION_CHIP | FIELD_VALUE(0, PLL_CTRL, POD, pPLL->POD) #endif diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 5d1f9a517388..a82253c749c6 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -126,8 +126,7 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ - if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PLL_CTRL, POWER) == - PLL_CTRL_POWER_OFF) || + if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) == PANEL_DISPLAY_CTRL_TIMING_DISABLE)) { return; @@ -149,8 +148,7 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ - if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), PLL_CTRL, POWER) == - PLL_CTRL_POWER_OFF) || + if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) == CRT_DISPLAY_CTRL_TIMING_DISABLE)) { return; diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 1ad8d554e249..d13af3983b74 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -517,15 +517,9 @@ #define PLL_CLK_COUNT_COUNTER 15:0 #define PANEL_PLL_CTRL 0x00005C -#define PLL_CTRL_BYPASS 18:18 -#define PLL_CTRL_BYPASS_OFF 0 -#define PLL_CTRL_BYPASS_ON 1 -#define PLL_CTRL_POWER 17:17 -#define PLL_CTRL_POWER_OFF 0 -#define PLL_CTRL_POWER_ON 1 -#define PLL_CTRL_INPUT 16:16 -#define PLL_CTRL_INPUT_OSC 0 -#define PLL_CTRL_INPUT_TESTCLK 1 +#define PLL_CTRL_BYPASS BIT(18) +#define PLL_CTRL_POWER BIT(17) +#define PLL_CTRL_INPUT BIT(16) #ifdef VALIDATION_CHIP #define PLL_CTRL_OD 15:14 #else -- cgit From cdd5df644a69070bd68b326d589226d7c900958c Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:58 +0200 Subject: staging: sm750fb: change defintion of PANEL_PLL_CTRL multi-bit fields Use more straight-forward definitions for multi-bit field of PANEL_PLL_CTRL register and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 24 +++++++++++++++--------- drivers/staging/sm750fb/ddk750_reg.h | 15 ++++++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 467b858c8d4a..d813cc6f1c6b 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -36,10 +36,10 @@ static unsigned int get_mxclk_freq(void) return MHz(130); pll_reg = PEEK32(MXCLK_PLL_CTRL); - M = FIELD_GET(pll_reg, PLL_CTRL, M); - N = FIELD_GET(pll_reg, PLL_CTRL, N); - OD = FIELD_GET(pll_reg, PLL_CTRL, OD); - POD = FIELD_GET(pll_reg, PLL_CTRL, POD); + M = (pll_reg & PLL_CTRL_M_MASK) >> PLL_CTRL_M_SHIFT; + N = (pll_reg & PLL_CTRL_N_MASK) >> PLL_CTRL_M_SHIFT; + OD = (pll_reg & PLL_CTRL_OD_MASK) >> PLL_CTRL_OD_SHIFT; + POD = (pll_reg & PLL_CTRL_POD_MASK) >> PLL_CTRL_POD_SHIFT; return DEFAULT_INPUT_CLOCK * M / N / (1 << OD) / (1 << POD); } @@ -355,6 +355,12 @@ unsigned int calcPllValue(unsigned int request_orig, pll_value_t *pll) unsigned int formatPllReg(pll_value_t *pPLL) { +#ifndef VALIDATION_CHIP + unsigned int POD = pPLL->POD; +#endif + unsigned int OD = pPLL->OD; + unsigned int M = pPLL->M; + unsigned int N = pPLL->N; unsigned int reg = 0; /* @@ -363,13 +369,13 @@ unsigned int formatPllReg(pll_value_t *pPLL) * register. On returning a 32 bit number, the value can be * applied to any PLL in the calling function. */ - reg = PLL_CTRL_POWER + reg = PLL_CTRL_POWER | #ifndef VALIDATION_CHIP - | FIELD_VALUE(0, PLL_CTRL, POD, pPLL->POD) + ((POD << PLL_CTRL_POD_SHIFT) & PLL_CTRL_POD_MASK) | #endif - | FIELD_VALUE(0, PLL_CTRL, OD, pPLL->OD) - | FIELD_VALUE(0, PLL_CTRL, N, pPLL->N) - | FIELD_VALUE(0, PLL_CTRL, M, pPLL->M); + ((OD << PLL_CTRL_OD_SHIFT) & PLL_CTRL_OD_MASK) | + ((N << PLL_CTRL_N_SHIFT) & PLL_CTRL_N_MASK) | + ((M << PLL_CTRL_M_SHIFT) & PLL_CTRL_M_MASK); return reg; } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index d13af3983b74..52d270dd8c5e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -521,13 +521,18 @@ #define PLL_CTRL_POWER BIT(17) #define PLL_CTRL_INPUT BIT(16) #ifdef VALIDATION_CHIP - #define PLL_CTRL_OD 15:14 + #define PLL_CTRL_OD_SHIFT 14 + #define PLL_CTRL_OD_MASK (0x3 << 14) #else - #define PLL_CTRL_POD 15:14 - #define PLL_CTRL_OD 13:12 + #define PLL_CTRL_POD_SHIFT 14 + #define PLL_CTRL_POD_MASK (0x3 << 14) + #define PLL_CTRL_OD_SHIFT 12 + #define PLL_CTRL_OD_MASK (0x3 << 12) #endif -#define PLL_CTRL_N 11:8 -#define PLL_CTRL_M 7:0 +#define PLL_CTRL_N_SHIFT 8 +#define PLL_CTRL_N_MASK (0xf << 8) +#define PLL_CTRL_M_SHIFT 0 +#define PLL_CTRL_M_MASK 0xff #define CRT_PLL_CTRL 0x000060 #define CRT_PLL_CTRL_BYPASS 18:18 -- cgit From cf25a7043654184b53d9ed345e718677ee880d92 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:33:59 +0200 Subject: staging: sm750fb: drop redundant defines for PLL_CTRL fields The PLL_CTRL fields have common defines for several PLL control registers and re-defining the same values per register is not needed. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 64 ------------------------------------ 1 file changed, 64 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 52d270dd8c5e..ac3cb367fdc9 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -535,80 +535,16 @@ #define PLL_CTRL_M_MASK 0xff #define CRT_PLL_CTRL 0x000060 -#define CRT_PLL_CTRL_BYPASS 18:18 -#define CRT_PLL_CTRL_BYPASS_OFF 0 -#define CRT_PLL_CTRL_BYPASS_ON 1 -#define CRT_PLL_CTRL_POWER 17:17 -#define CRT_PLL_CTRL_POWER_OFF 0 -#define CRT_PLL_CTRL_POWER_ON 1 -#define CRT_PLL_CTRL_INPUT 16:16 -#define CRT_PLL_CTRL_INPUT_OSC 0 -#define CRT_PLL_CTRL_INPUT_TESTCLK 1 -#ifdef VALIDATION_CHIP - #define CRT_PLL_CTRL_OD 15:14 -#else - #define CRT_PLL_CTRL_POD 15:14 - #define CRT_PLL_CTRL_OD 13:12 -#endif -#define CRT_PLL_CTRL_N 11:8 -#define CRT_PLL_CTRL_M 7:0 #define VGA_PLL0_CTRL 0x000064 -#define VGA_PLL0_CTRL_BYPASS 18:18 -#define VGA_PLL0_CTRL_BYPASS_OFF 0 -#define VGA_PLL0_CTRL_BYPASS_ON 1 -#define VGA_PLL0_CTRL_POWER 17:17 -#define VGA_PLL0_CTRL_POWER_OFF 0 -#define VGA_PLL0_CTRL_POWER_ON 1 -#define VGA_PLL0_CTRL_INPUT 16:16 -#define VGA_PLL0_CTRL_INPUT_OSC 0 -#define VGA_PLL0_CTRL_INPUT_TESTCLK 1 -#ifdef VALIDATION_CHIP - #define VGA_PLL0_CTRL_OD 15:14 -#else - #define VGA_PLL0_CTRL_POD 15:14 - #define VGA_PLL0_CTRL_OD 13:12 -#endif -#define VGA_PLL0_CTRL_N 11:8 -#define VGA_PLL0_CTRL_M 7:0 #define VGA_PLL1_CTRL 0x000068 -#define VGA_PLL1_CTRL_BYPASS 18:18 -#define VGA_PLL1_CTRL_BYPASS_OFF 0 -#define VGA_PLL1_CTRL_BYPASS_ON 1 -#define VGA_PLL1_CTRL_POWER 17:17 -#define VGA_PLL1_CTRL_POWER_OFF 0 -#define VGA_PLL1_CTRL_POWER_ON 1 -#define VGA_PLL1_CTRL_INPUT 16:16 -#define VGA_PLL1_CTRL_INPUT_OSC 0 -#define VGA_PLL1_CTRL_INPUT_TESTCLK 1 -#ifdef VALIDATION_CHIP - #define VGA_PLL1_CTRL_OD 15:14 -#else - #define VGA_PLL1_CTRL_POD 15:14 - #define VGA_PLL1_CTRL_OD 13:12 -#endif -#define VGA_PLL1_CTRL_N 11:8 -#define VGA_PLL1_CTRL_M 7:0 #define SCRATCH_DATA 0x00006c #ifndef VALIDATION_CHIP #define MXCLK_PLL_CTRL 0x000070 -#define MXCLK_PLL_CTRL_BYPASS 18:18 -#define MXCLK_PLL_CTRL_BYPASS_OFF 0 -#define MXCLK_PLL_CTRL_BYPASS_ON 1 -#define MXCLK_PLL_CTRL_POWER 17:17 -#define MXCLK_PLL_CTRL_POWER_OFF 0 -#define MXCLK_PLL_CTRL_POWER_ON 1 -#define MXCLK_PLL_CTRL_INPUT 16:16 -#define MXCLK_PLL_CTRL_INPUT_OSC 0 -#define MXCLK_PLL_CTRL_INPUT_TESTCLK 1 -#define MXCLK_PLL_CTRL_POD 15:14 -#define MXCLK_PLL_CTRL_OD 13:12 -#define MXCLK_PLL_CTRL_N 11:8 -#define MXCLK_PLL_CTRL_M 7:0 #define VGA_CONFIGURATION 0x000088 #define VGA_CONFIGURATION_USER_DEFINE 5:4 -- cgit From d97981431f63ca2da4e8b9dcedc2cd3576286c0a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:00 +0200 Subject: staging: sm750fb: use BIT macro for VGA_CONFIGURATION single-bit fields Replace complex defintion of VGA_CONFIGURATION register fields with BIT() macro and use open-coded implementation for VGA_CONFIGURATION manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 3 +-- drivers/staging/sm750fb/ddk750_reg.h | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index d813cc6f1c6b..2d1128fc7b5a 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -211,8 +211,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) if (getChipType() != SM750LE) { /* set panel pll and graphic mode via mmio_88 */ reg = PEEK32(VGA_CONFIGURATION); - reg = FIELD_SET(reg, VGA_CONFIGURATION, PLL, PANEL); - reg = FIELD_SET(reg, VGA_CONFIGURATION, MODE, GRAPHIC); + reg |= (VGA_CONFIGURATION_PLL | VGA_CONFIGURATION_MODE); POKE32(VGA_CONFIGURATION, reg); } else { #if defined(__i386__) || defined(__x86_64__) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index ac3cb367fdc9..e873a1008b88 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -548,12 +548,8 @@ #define VGA_CONFIGURATION 0x000088 #define VGA_CONFIGURATION_USER_DEFINE 5:4 -#define VGA_CONFIGURATION_PLL 2:2 -#define VGA_CONFIGURATION_PLL_VGA 0 -#define VGA_CONFIGURATION_PLL_PANEL 1 -#define VGA_CONFIGURATION_MODE 1:1 -#define VGA_CONFIGURATION_MODE_TEXT 0 -#define VGA_CONFIGURATION_MODE_GRAPHIC 1 +#define VGA_CONFIGURATION_PLL BIT(2) +#define VGA_CONFIGURATION_MODE BIT(1) #endif -- cgit From e6f10d281434115d10d5bfc9c569d3d9a21225a0 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:01 +0200 Subject: staging: sm750fb: change definition of VGA_CONFIGURATION multi-bit field Use more straight-forward definitions for multi-bit field of VGA_CONFIGURATION register. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index e873a1008b88..d1e7fc4d50df 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -547,7 +547,7 @@ #define MXCLK_PLL_CTRL 0x000070 #define VGA_CONFIGURATION 0x000088 -#define VGA_CONFIGURATION_USER_DEFINE 5:4 +#define VGA_CONFIGURATION_USER_DEFINE_MASK (0x3 << 4) #define VGA_CONFIGURATION_PLL BIT(2) #define VGA_CONFIGURATION_MODE BIT(1) -- cgit From c436e6ba7eefdd0a75903283fec726888fd6ef5d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:02 +0200 Subject: staging: sm750fb: programModeRegisters: rename local vairables Remove HungarianCamelCase notation. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_mode.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index d0e3935654ff..e7fc2391c856 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -79,7 +79,7 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) { int ret = 0; int cnt = 0; - unsigned int ulTmpValue, ulReg; + unsigned int tmp, reg; if (pll->clockType == SECONDARY_PLL) { /* programe secondary pixel clock */ @@ -101,26 +101,27 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - ulTmpValue = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | + tmp = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, + pModeParam->vertical_sync_polarity) | FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE); if (getChipType() == SM750LE) { - displayControlAdjust_SM750LE(pModeParam, ulTmpValue); + displayControlAdjust_SM750LE(pModeParam, tmp); } else { - ulReg = PEEK32(CRT_DISPLAY_CTRL) + reg = PEEK32(CRT_DISPLAY_CTRL) & FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE) & FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE) & FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING) & FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE); - POKE32(CRT_DISPLAY_CTRL, ulTmpValue | ulReg); + POKE32(CRT_DISPLAY_CTRL, tmp | reg); } } else if (pll->clockType == PRIMARY_PLL) { - unsigned int ulReservedBits; + unsigned int reserved; POKE32(PANEL_PLL_CTRL, formatPllReg(pll)); @@ -140,18 +141,20 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - ulTmpValue = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | + tmp = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, + pModeParam->vertical_sync_polarity) | FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity) | FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE); - ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | + reserved = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, + ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); - ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) + reg = (PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE) & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE) & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE) @@ -167,13 +170,14 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) * next vertical sync to turn on/off the plane. */ - POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg); + POKE32(PANEL_DISPLAY_CTRL, tmp | reg); - while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue | ulReg)) { + while ((PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) != + (tmp | reg)) { cnt++; if (cnt > 1000) break; - POKE32(PANEL_DISPLAY_CTRL, ulTmpValue | ulReg); + POKE32(PANEL_DISPLAY_CTRL, tmp | reg); } } else { ret = -1; -- cgit From 7755265a9993b836f544aacc7b6a2a474fbde558 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:03 +0200 Subject: staging: sm750fb: setDisplayControl: rename local vairables Remove HungarianCamelCase notation. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index a82253c749c6..dc7060e28e22 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -9,25 +9,25 @@ static void setDisplayControl(int ctrl, int disp_state) { /* state != 0 means turn on both timing & plane en_bit */ - unsigned long ulDisplayCtrlReg, ulReservedBits; + unsigned long reg, reserved; int cnt; cnt = 0; /* Set the primary display control */ if (!ctrl) { - ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL); + reg = PEEK32(PANEL_DISPLAY_CTRL); /* Turn on/off the Panel display control */ if (disp_state) { /* Timing should be enabled first before enabling the plane * because changing at the same time does not guarantee that * the plane will also enabled or disabled. */ - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, PANEL_DISPLAY_CTRL, TIMING, ENABLE); - POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); + POKE32(PANEL_DISPLAY_CTRL, reg); - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, PANEL_DISPLAY_CTRL, PLANE, ENABLE); /* Added some masks to mask out the reserved bits. @@ -35,7 +35,7 @@ static void setDisplayControl(int ctrl, int disp_state) * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register * reserved bits are needed to be masked out. */ - ulReservedBits = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | + reserved = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE); @@ -45,9 +45,9 @@ static void setDisplayControl(int ctrl, int disp_state) */ do { cnt++; - POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); - } while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != - (ulDisplayCtrlReg & ~ulReservedBits)); + POKE32(PANEL_DISPLAY_CTRL, reg); + } while ((PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) != + (reg & ~reserved)); printk("Set Panel Plane enbit:after tried %d times\n", cnt); } else { /* When turning off, there is no rule on the programming @@ -57,28 +57,28 @@ static void setDisplayControl(int ctrl, int disp_state) * next vertical sync. Need to find out if it is necessary to * wait for 1 vsync before modifying the timing enable bit. * */ - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, PANEL_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); + POKE32(PANEL_DISPLAY_CTRL, reg); - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, PANEL_DISPLAY_CTRL, TIMING, DISABLE); - POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg); + POKE32(PANEL_DISPLAY_CTRL, reg); } } else { /* Set the secondary display control */ - ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL); + reg = PEEK32(CRT_DISPLAY_CTRL); if (disp_state) { /* Timing should be enabled first before enabling the plane because changing at the same time does not guarantee that the plane will also enabled or disabled. */ - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, TIMING, ENABLE); - POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); + POKE32(CRT_DISPLAY_CTRL, reg); - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, PLANE, ENABLE); /* Added some masks to mask out the reserved bits. @@ -87,16 +87,16 @@ static void setDisplayControl(int ctrl, int disp_state) * reserved bits are needed to be masked out. */ - ulReservedBits = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | + reserved = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE); do { cnt++; - POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); - } while ((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) != - (ulDisplayCtrlReg & ~ulReservedBits)); + POKE32(CRT_DISPLAY_CTRL, reg); + } while ((PEEK32(CRT_DISPLAY_CTRL) & ~reserved) != + (reg & ~reserved)); printk("Set Crt Plane enbit:after tried %d times\n", cnt); } else { /* When turning off, there is no rule on the programming @@ -106,13 +106,13 @@ static void setDisplayControl(int ctrl, int disp_state) * vertical sync. Need to find out if it is necessary to * wait for 1 vsync before modifying the timing enable bit. */ - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, PLANE, DISABLE); - POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); + POKE32(CRT_DISPLAY_CTRL, reg); - ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg, + reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, TIMING, DISABLE); - POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg); + POKE32(CRT_DISPLAY_CTRL, reg); } } } -- cgit From 85e4db5347a96560928d2995a2cd05f10b856d5e Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:04 +0200 Subject: staging: sm750fb: share common bits in display control registers The display control registers for primary and secondary display share some of the bits and those bits can be defined in a single place and then used for manipulations of the relevant registers. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 6 +-- drivers/staging/sm750fb/ddk750_display.c | 34 +++++++---------- drivers/staging/sm750fb/ddk750_mode.c | 42 +++++++++++---------- drivers/staging/sm750fb/ddk750_reg.h | 63 +++++++++----------------------- 4 files changed, 58 insertions(+), 87 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 2d1128fc7b5a..0031e32b8cbe 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -249,17 +249,17 @@ int ddk750_initHw(initchip_param_t *pInitParam) /* Disable Overlay, if a former application left it on */ reg = PEEK32(VIDEO_DISPLAY_CTRL); - reg = FIELD_SET(reg, VIDEO_DISPLAY_CTRL, PLANE, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); POKE32(VIDEO_DISPLAY_CTRL, reg); /* Disable video alpha, if a former application left it on */ reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); - reg = FIELD_SET(reg, VIDEO_ALPHA_DISPLAY_CTRL, PLANE, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg); /* Disable alpha plane, if a former application left it on */ reg = PEEK32(ALPHA_DISPLAY_CTRL); - reg = FIELD_SET(reg, ALPHA_DISPLAY_CTRL, PLANE, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); POKE32(ALPHA_DISPLAY_CTRL, reg); /* Disable DMA Channel, if a former application left it on */ diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index dc7060e28e22..42da3cd0dcdb 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -23,12 +23,10 @@ static void setDisplayControl(int ctrl, int disp_state) * because changing at the same time does not guarantee that * the plane will also enabled or disabled. */ - reg = FIELD_SET(reg, - PANEL_DISPLAY_CTRL, TIMING, ENABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, ENABLE); POKE32(PANEL_DISPLAY_CTRL, reg); - reg = FIELD_SET(reg, - PANEL_DISPLAY_CTRL, PLANE, ENABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, ENABLE); /* Added some masks to mask out the reserved bits. * Sometimes, the reserved bits are set/reset randomly when @@ -57,12 +55,10 @@ static void setDisplayControl(int ctrl, int disp_state) * next vertical sync. Need to find out if it is necessary to * wait for 1 vsync before modifying the timing enable bit. * */ - reg = FIELD_SET(reg, - PANEL_DISPLAY_CTRL, PLANE, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); POKE32(PANEL_DISPLAY_CTRL, reg); - reg = FIELD_SET(reg, - PANEL_DISPLAY_CTRL, TIMING, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, DISABLE); POKE32(PANEL_DISPLAY_CTRL, reg); } @@ -74,12 +70,10 @@ static void setDisplayControl(int ctrl, int disp_state) /* Timing should be enabled first before enabling the plane because changing at the same time does not guarantee that the plane will also enabled or disabled. */ - reg = FIELD_SET(reg, - CRT_DISPLAY_CTRL, TIMING, ENABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, ENABLE); POKE32(CRT_DISPLAY_CTRL, reg); - reg = FIELD_SET(reg, - CRT_DISPLAY_CTRL, PLANE, ENABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, ENABLE); /* Added some masks to mask out the reserved bits. * Sometimes, the reserved bits are set/reset randomly when @@ -106,12 +100,10 @@ static void setDisplayControl(int ctrl, int disp_state) * vertical sync. Need to find out if it is necessary to * wait for 1 vsync before modifying the timing enable bit. */ - reg = FIELD_SET(reg, - CRT_DISPLAY_CTRL, PLANE, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); POKE32(CRT_DISPLAY_CTRL, reg); - reg = FIELD_SET(reg, - CRT_DISPLAY_CTRL, TIMING, DISABLE); + reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, DISABLE); POKE32(CRT_DISPLAY_CTRL, reg); } } @@ -127,8 +119,9 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || - (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) == - PANEL_DISPLAY_CTRL_TIMING_DISABLE)) { + (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), + DISPLAY_CTRL, TIMING) == + DISPLAY_CTRL_TIMING_DISABLE)) { return; } @@ -149,8 +142,9 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || - (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) == - CRT_DISPLAY_CTRL_TIMING_DISABLE)) { + (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), + DISPLAY_CTRL, TIMING) == + DISPLAY_CTRL_TIMING_DISABLE)) { return; } diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index e7fc2391c856..f81e05323875 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -65,7 +65,8 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT); /* Set bit 14 of display controller */ - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW); + dispControl = FIELD_SET(dispControl, DISPLAY_CTRL, CLOCK_PHASE, + ACTIVE_LOW); POKE32(CRT_DISPLAY_CTRL, dispControl); @@ -101,21 +102,22 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - tmp = FIELD_VALUE(0, CRT_DISPLAY_CTRL, VSYNC_PHASE, + tmp = FIELD_VALUE(0, DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | - FIELD_VALUE(0, CRT_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | - FIELD_SET(0, CRT_DISPLAY_CTRL, TIMING, ENABLE) | - FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE); + FIELD_VALUE(0, DISPLAY_CTRL, HSYNC_PHASE, + pModeParam->horizontal_sync_polarity) | + FIELD_SET(0, DISPLAY_CTRL, TIMING, ENABLE) | + FIELD_SET(0, DISPLAY_CTRL, PLANE, ENABLE); if (getChipType() == SM750LE) { displayControlAdjust_SM750LE(pModeParam, tmp); } else { reg = PEEK32(CRT_DISPLAY_CTRL) - & FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE) - & FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE) - & FIELD_CLEAR(CRT_DISPLAY_CTRL, TIMING) - & FIELD_CLEAR(CRT_DISPLAY_CTRL, PLANE); + & FIELD_CLEAR(DISPLAY_CTRL, VSYNC_PHASE) + & FIELD_CLEAR(DISPLAY_CTRL, HSYNC_PHASE) + & FIELD_CLEAR(DISPLAY_CTRL, TIMING) + & FIELD_CLEAR(DISPLAY_CTRL, PLANE); POKE32(CRT_DISPLAY_CTRL, tmp | reg); } @@ -141,12 +143,14 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - tmp = FIELD_VALUE(0, PANEL_DISPLAY_CTRL, VSYNC_PHASE, + tmp = FIELD_VALUE(0, DISPLAY_CTRL, VSYNC_PHASE, pModeParam->vertical_sync_polarity) | - FIELD_VALUE(0, PANEL_DISPLAY_CTRL, HSYNC_PHASE, pModeParam->horizontal_sync_polarity) | - FIELD_VALUE(0, PANEL_DISPLAY_CTRL, CLOCK_PHASE, pModeParam->clock_phase_polarity) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, TIMING, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE); + FIELD_VALUE(0, DISPLAY_CTRL, HSYNC_PHASE, + pModeParam->horizontal_sync_polarity) | + FIELD_VALUE(0, DISPLAY_CTRL, CLOCK_PHASE, + pModeParam->clock_phase_polarity) | + FIELD_SET(0, DISPLAY_CTRL, TIMING, ENABLE) | + FIELD_SET(0, DISPLAY_CTRL, PLANE, ENABLE); reserved = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | @@ -155,11 +159,11 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); reg = (PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) - & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE) - & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE) - & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE) - & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING) - & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE); + & FIELD_CLEAR(DISPLAY_CTRL, CLOCK_PHASE) + & FIELD_CLEAR(DISPLAY_CTRL, VSYNC_PHASE) + & FIELD_CLEAR(DISPLAY_CTRL, HSYNC_PHASE) + & FIELD_CLEAR(DISPLAY_CTRL, TIMING) + & FIELD_CLEAR(DISPLAY_CTRL, PLANE); /* May a hardware bug or just my test chip (not confirmed). diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index d1e7fc4d50df..4d66f6127207 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -825,15 +825,15 @@ #define PANEL_DISPLAY_CTRL_RESERVED_3_MASK 15:15 #define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_DISABLE 0 #define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_ENABLE 1 -#define PANEL_DISPLAY_CTRL_CLOCK_PHASE 14:14 -#define PANEL_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH 0 -#define PANEL_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW 1 -#define PANEL_DISPLAY_CTRL_VSYNC_PHASE 13:13 -#define PANEL_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH 0 -#define PANEL_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_LOW 1 -#define PANEL_DISPLAY_CTRL_HSYNC_PHASE 12:12 -#define PANEL_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH 0 -#define PANEL_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_LOW 1 +#define DISPLAY_CTRL_CLOCK_PHASE 14:14 +#define DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH 0 +#define DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW 1 +#define DISPLAY_CTRL_VSYNC_PHASE 13:13 +#define DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH 0 +#define DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_LOW 1 +#define DISPLAY_CTRL_HSYNC_PHASE 12:12 +#define DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH 0 +#define DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_LOW 1 #define PANEL_DISPLAY_CTRL_VSYNC 11:11 #define PANEL_DISPLAY_CTRL_VSYNC_ACTIVE_HIGH 0 #define PANEL_DISPLAY_CTRL_VSYNC_ACTIVE_LOW 1 @@ -843,9 +843,9 @@ #define PANEL_DISPLAY_CTRL_COLOR_KEY 9:9 #define PANEL_DISPLAY_CTRL_COLOR_KEY_DISABLE 0 #define PANEL_DISPLAY_CTRL_COLOR_KEY_ENABLE 1 -#define PANEL_DISPLAY_CTRL_TIMING 8:8 -#define PANEL_DISPLAY_CTRL_TIMING_DISABLE 0 -#define PANEL_DISPLAY_CTRL_TIMING_ENABLE 1 +#define DISPLAY_CTRL_TIMING 8:8 +#define DISPLAY_CTRL_TIMING_DISABLE 0 +#define DISPLAY_CTRL_TIMING_ENABLE 1 #define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR 7:7 #define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR_DOWN 0 #define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR_UP 1 @@ -858,12 +858,12 @@ #define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN 4:4 #define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DISABLE 0 #define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_ENABLE 1 -#define PANEL_DISPLAY_CTRL_GAMMA 3:3 -#define PANEL_DISPLAY_CTRL_GAMMA_DISABLE 0 -#define PANEL_DISPLAY_CTRL_GAMMA_ENABLE 1 -#define PANEL_DISPLAY_CTRL_PLANE 2:2 -#define PANEL_DISPLAY_CTRL_PLANE_DISABLE 0 -#define PANEL_DISPLAY_CTRL_PLANE_ENABLE 1 +#define DISPLAY_CTRL_GAMMA 3:3 +#define DISPLAY_CTRL_GAMMA_DISABLE 0 +#define DISPLAY_CTRL_GAMMA_ENABLE 1 +#define DISPLAY_CTRL_PLANE 2:2 +#define DISPLAY_CTRL_PLANE_DISABLE 0 +#define DISPLAY_CTRL_PLANE_ENABLE 1 #define PANEL_DISPLAY_CTRL_FORMAT 1:0 #define PANEL_DISPLAY_CTRL_FORMAT_8 0 #define PANEL_DISPLAY_CTRL_FORMAT_16 1 @@ -966,9 +966,6 @@ #define VIDEO_DISPLAY_CTRL_GAMMA 3:3 #define VIDEO_DISPLAY_CTRL_GAMMA_DISABLE 0 #define VIDEO_DISPLAY_CTRL_GAMMA_ENABLE 1 -#define VIDEO_DISPLAY_CTRL_PLANE 2:2 -#define VIDEO_DISPLAY_CTRL_PLANE_DISABLE 0 -#define VIDEO_DISPLAY_CTRL_PLANE_ENABLE 1 #define VIDEO_DISPLAY_CTRL_FORMAT 1:0 #define VIDEO_DISPLAY_CTRL_FORMAT_8 0 #define VIDEO_DISPLAY_CTRL_FORMAT_16 1 @@ -1065,9 +1062,6 @@ #define VIDEO_ALPHA_DISPLAY_CTRL_CHROMA_KEY 3:3 #define VIDEO_ALPHA_DISPLAY_CTRL_CHROMA_KEY_DISABLE 0 #define VIDEO_ALPHA_DISPLAY_CTRL_CHROMA_KEY_ENABLE 1 -#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE 2:2 -#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE_DISABLE 0 -#define VIDEO_ALPHA_DISPLAY_CTRL_PLANE_ENABLE 1 #define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT 1:0 #define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT_8 0 #define VIDEO_ALPHA_DISPLAY_CTRL_FORMAT_16 1 @@ -1258,9 +1252,6 @@ #define ALPHA_DISPLAY_CTRL_CHROMA_KEY 3:3 #define ALPHA_DISPLAY_CTRL_CHROMA_KEY_DISABLE 0 #define ALPHA_DISPLAY_CTRL_CHROMA_KEY_ENABLE 1 -#define ALPHA_DISPLAY_CTRL_PLANE 2:2 -#define ALPHA_DISPLAY_CTRL_PLANE_DISABLE 0 -#define ALPHA_DISPLAY_CTRL_PLANE_ENABLE 1 #define ALPHA_DISPLAY_CTRL_FORMAT 1:0 #define ALPHA_DISPLAY_CTRL_FORMAT_16 1 #define ALPHA_DISPLAY_CTRL_FORMAT_ALPHA_4_4 2 @@ -1448,28 +1439,10 @@ #define CRT_DISPLAY_CTRL_FIFO_3 1 #define CRT_DISPLAY_CTRL_FIFO_7 2 #define CRT_DISPLAY_CTRL_FIFO_11 3 -#define CRT_DISPLAY_CTRL_CLOCK_PHASE 14:14 -#define CRT_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH 0 -#define CRT_DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW 1 -#define CRT_DISPLAY_CTRL_VSYNC_PHASE 13:13 -#define CRT_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH 0 -#define CRT_DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_LOW 1 -#define CRT_DISPLAY_CTRL_HSYNC_PHASE 12:12 -#define CRT_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH 0 -#define CRT_DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_LOW 1 #define CRT_DISPLAY_CTRL_BLANK 10:10 #define CRT_DISPLAY_CTRL_BLANK_OFF 0 #define CRT_DISPLAY_CTRL_BLANK_ON 1 -#define CRT_DISPLAY_CTRL_TIMING 8:8 -#define CRT_DISPLAY_CTRL_TIMING_DISABLE 0 -#define CRT_DISPLAY_CTRL_TIMING_ENABLE 1 #define CRT_DISPLAY_CTRL_PIXEL 7:4 -#define CRT_DISPLAY_CTRL_GAMMA 3:3 -#define CRT_DISPLAY_CTRL_GAMMA_DISABLE 0 -#define CRT_DISPLAY_CTRL_GAMMA_ENABLE 1 -#define CRT_DISPLAY_CTRL_PLANE 2:2 -#define CRT_DISPLAY_CTRL_PLANE_DISABLE 0 -#define CRT_DISPLAY_CTRL_PLANE_ENABLE 1 #define CRT_DISPLAY_CTRL_FORMAT 1:0 #define CRT_DISPLAY_CTRL_FORMAT_8 0 #define CRT_DISPLAY_CTRL_FORMAT_16 1 -- cgit From 9bd2c86b5a4d4a038c626d39a02d4dc71ac577ff Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:05 +0200 Subject: staging: sm750fb: merge reserved bits of PANEL/CRT_DISPLAY_CTRL registers Use single mask for reserved bits in PANEL_DISPLAY_CTRL and CRT_DISPLAY_CTRL registers. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 11 ++--------- drivers/staging/sm750fb/ddk750_mode.c | 7 ++----- drivers/staging/sm750fb/ddk750_reg.h | 29 ++--------------------------- 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 42da3cd0dcdb..f3f0026ac010 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -33,9 +33,7 @@ static void setDisplayControl(int ctrl, int disp_state) * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register * reserved bits are needed to be masked out. */ - reserved = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE); + reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK; /* Somehow the register value on the plane is not set * until a few delay. Need to write @@ -80,12 +78,7 @@ static void setDisplayControl(int ctrl, int disp_state) * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register * reserved bits are needed to be masked out. */ - - reserved = FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_1_MASK, ENABLE) | - FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | - FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | - FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE); - + reserved = CRT_DISPLAY_CTRL_RESERVED_MASK; do { cnt++; POKE32(CRT_DISPLAY_CTRL, reg); diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index f81e05323875..a618e86879bb 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -152,11 +152,8 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_SET(0, DISPLAY_CTRL, TIMING, ENABLE) | FIELD_SET(0, DISPLAY_CTRL, PLANE, ENABLE); - reserved = FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_1_MASK, - ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_2_MASK, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) | - FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); + reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK | + FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); reg = (PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) & FIELD_CLEAR(DISPLAY_CTRL, CLOCK_PHASE) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 4d66f6127207..dac087f74817 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -782,9 +782,7 @@ #define PANEL_DISPLAY_CTRL 0x080000 -#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK 31:30 -#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE 0 -#define PANEL_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE 3 +#define PANEL_DISPLAY_CTRL_RESERVED_MASK 0xc0f08000 #define PANEL_DISPLAY_CTRL_SELECT 29:28 #define PANEL_DISPLAY_CTRL_SELECT_PANEL 0 #define PANEL_DISPLAY_CTRL_SELECT_VGA 1 @@ -801,9 +799,6 @@ #define PANEL_DISPLAY_CTRL_FPVDDEN 24:24 #define PANEL_DISPLAY_CTRL_FPVDDEN_LOW 0 #define PANEL_DISPLAY_CTRL_FPVDDEN_HIGH 1 -#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK 23:20 -#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE 0 -#define PANEL_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE 15 #define PANEL_DISPLAY_CTRL_TFT_DISP 19:18 #define PANEL_DISPLAY_CTRL_TFT_DISP_24 0 @@ -822,9 +817,6 @@ #define PANEL_DISPLAY_CTRL_FIFO_3 1 #define PANEL_DISPLAY_CTRL_FIFO_7 2 #define PANEL_DISPLAY_CTRL_FIFO_11 3 -#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK 15:15 -#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_DISABLE 0 -#define PANEL_DISPLAY_CTRL_RESERVED_3_MASK_ENABLE 1 #define DISPLAY_CTRL_CLOCK_PHASE 14:14 #define DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH 0 #define DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW 1 @@ -1365,9 +1357,7 @@ /* CRT Graphics Control */ #define CRT_DISPLAY_CTRL 0x080200 -#define CRT_DISPLAY_CTRL_RESERVED_1_MASK 31:27 -#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE 0 -#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE 0x1F +#define CRT_DISPLAY_CTRL_RESERVED_MASK 0xfb008200 /* SM750LE definition */ #define CRT_DISPLAY_CTRL_DPMS 31:30 @@ -1388,11 +1378,6 @@ #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_DISABLE 1 #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_ENABLE 0 - -#define CRT_DISPLAY_CTRL_RESERVED_2_MASK 25:24 -#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE 3 -#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE 0 - /* SM750LE definition */ #define CRT_DISPLAY_CTRL_CRTSELECT 25:25 #define CRT_DISPLAY_CTRL_CRTSELECT_VGA 0 @@ -1401,15 +1386,6 @@ #define CRT_DISPLAY_CTRL_RGBBIT_24BIT 0 #define CRT_DISPLAY_CTRL_RGBBIT_12BIT 1 - -#define CRT_DISPLAY_CTRL_RESERVED_3_MASK 15:15 -#define CRT_DISPLAY_CTRL_RESERVED_3_MASK_DISABLE 0 -#define CRT_DISPLAY_CTRL_RESERVED_3_MASK_ENABLE 1 - -#define CRT_DISPLAY_CTRL_RESERVED_4_MASK 9:9 -#define CRT_DISPLAY_CTRL_RESERVED_4_MASK_DISABLE 0 -#define CRT_DISPLAY_CTRL_RESERVED_4_MASK_ENABLE 1 - #ifndef VALIDATION_CHIP #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC 26:26 #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_DISABLE 1 @@ -1447,7 +1423,6 @@ #define CRT_DISPLAY_CTRL_FORMAT_8 0 #define CRT_DISPLAY_CTRL_FORMAT_16 1 #define CRT_DISPLAY_CTRL_FORMAT_32 2 -#define CRT_DISPLAY_CTRL_RESERVED_BITS_MASK 0xFF000200 #define CRT_FB_ADDRESS 0x080204 #define CRT_FB_ADDRESS_STATUS 31:31 -- cgit From b117b637da2be83c8173b53986b51ad5b8169d8d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:06 +0200 Subject: staging: sm750fb: refactor setDisplayControl function The enable/disbable sequence in setDisplayControl function is duplicated for primary and secondary display controllers. The function can be refactored so that the common part of register access will be shared for both controllers. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 131 +++++++++++-------------------- 1 file changed, 45 insertions(+), 86 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index f3f0026ac010..ae8bb371d2b2 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -9,96 +9,55 @@ static void setDisplayControl(int ctrl, int disp_state) { /* state != 0 means turn on both timing & plane en_bit */ - unsigned long reg, reserved; - int cnt; + unsigned long reg, val, reserved; + int cnt = 0; - cnt = 0; - - /* Set the primary display control */ if (!ctrl) { - reg = PEEK32(PANEL_DISPLAY_CTRL); - /* Turn on/off the Panel display control */ - if (disp_state) { - /* Timing should be enabled first before enabling the plane - * because changing at the same time does not guarantee that - * the plane will also enabled or disabled. - */ - reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, ENABLE); - POKE32(PANEL_DISPLAY_CTRL, reg); - - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, ENABLE); - - /* Added some masks to mask out the reserved bits. - * Sometimes, the reserved bits are set/reset randomly when - * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register - * reserved bits are needed to be masked out. - */ - reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK; - - /* Somehow the register value on the plane is not set - * until a few delay. Need to write - * and read it a couple times - */ - do { - cnt++; - POKE32(PANEL_DISPLAY_CTRL, reg); - } while ((PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) != - (reg & ~reserved)); - printk("Set Panel Plane enbit:after tried %d times\n", cnt); - } else { - /* When turning off, there is no rule on the programming - * sequence since whenever the clock is off, then it does not - * matter whether the plane is enabled or disabled. - * Note: Modifying the plane bit will take effect on the - * next vertical sync. Need to find out if it is necessary to - * wait for 1 vsync before modifying the timing enable bit. - * */ - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); - POKE32(PANEL_DISPLAY_CTRL, reg); - - reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, DISABLE); - POKE32(PANEL_DISPLAY_CTRL, reg); - } - + reg = PANEL_DISPLAY_CTRL; + reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK; } else { - /* Set the secondary display control */ - reg = PEEK32(CRT_DISPLAY_CTRL); + reg = CRT_DISPLAY_CTRL; + reserved = CRT_DISPLAY_CTRL_RESERVED_MASK; + } - if (disp_state) { - /* Timing should be enabled first before enabling the plane because changing at the - same time does not guarantee that the plane will also enabled or disabled. - */ - reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, ENABLE); - POKE32(CRT_DISPLAY_CTRL, reg); - - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, ENABLE); - - /* Added some masks to mask out the reserved bits. - * Sometimes, the reserved bits are set/reset randomly when - * writing to the PRIMARY_DISPLAY_CTRL, therefore, the register - * reserved bits are needed to be masked out. - */ - reserved = CRT_DISPLAY_CTRL_RESERVED_MASK; - do { - cnt++; - POKE32(CRT_DISPLAY_CTRL, reg); - } while ((PEEK32(CRT_DISPLAY_CTRL) & ~reserved) != - (reg & ~reserved)); - printk("Set Crt Plane enbit:after tried %d times\n", cnt); - } else { - /* When turning off, there is no rule on the programming - * sequence since whenever the clock is off, then it does not - * matter whether the plane is enabled or disabled. - * Note: Modifying the plane bit will take effect on the next - * vertical sync. Need to find out if it is necessary to - * wait for 1 vsync before modifying the timing enable bit. - */ - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); - POKE32(CRT_DISPLAY_CTRL, reg); - - reg = FIELD_SET(reg, DISPLAY_CTRL, TIMING, DISABLE); - POKE32(CRT_DISPLAY_CTRL, reg); - } + val = PEEK32(reg); + if (disp_state) { + /* + * Timing should be enabled first before enabling the + * plane because changing at the same time does not + * guarantee that the plane will also enabled or + * disabled. + */ + val = FIELD_SET(val, DISPLAY_CTRL, TIMING, ENABLE); + POKE32(reg, val); + + val = FIELD_SET(val, DISPLAY_CTRL, PLANE, ENABLE); + + /* + * Somehow the register value on the plane is not set + * until a few delay. Need to write and read it a + * couple times + */ + do { + cnt++; + POKE32(reg, val); + } while ((PEEK32(reg) & ~reserved) != (val & ~reserved)); + pr_debug("Set Plane enbit:after tried %d times\n", cnt); + } else { + /* + * When turning off, there is no rule on the + * programming sequence since whenever the clock is + * off, then it does not matter whether the plane is + * enabled or disabled. Note: Modifying the plane bit + * will take effect on the next vertical sync. Need to + * find out if it is necessary to wait for 1 vsync + * before modifying the timing enable bit. + */ + val = FIELD_SET(val, DISPLAY_CTRL, PLANE, DISABLE); + POKE32(reg, val); + + val = FIELD_SET(val, DISPLAY_CTRL, TIMING, DISABLE); + POKE32(reg, val); } } -- cgit From 5b621779c2365216dcbf6f9166c2e791e304767a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:07 +0200 Subject: staging: sm750fb: hw_sm750_setBLANK: reduce printk verbosity pr_debug would be enough Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index c0c2f1c4de82..52fd250d7afe 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -414,13 +414,13 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) switch (blank) { case FB_BLANK_UNBLANK: - pr_info("flag = FB_BLANK_UNBLANK\n"); + pr_debug("flag = FB_BLANK_UNBLANK\n"); dpms = SYSTEM_CTRL_DPMS_VPHP; pps = PANEL_DISPLAY_CTRL_DATA_ENABLE; crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; break; case FB_BLANK_NORMAL: - pr_info("flag = FB_BLANK_NORMAL\n"); + pr_debug("flag = FB_BLANK_NORMAL\n"); dpms = SYSTEM_CTRL_DPMS_VPHP; pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; crtdb = CRT_DISPLAY_CTRL_BLANK_ON; -- cgit From 6fba39cf32a3adc84de531bb8463d208f6d6f2bf Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:08 +0200 Subject: staging: sm750fb: use BIT macro for PANEL_DISPLAY_CTRL single-bit fields Replace complex definition of PANEL_DISPLAY_CTRL register fields with BIT() macro and use open-coded implementation for register manipulations. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 6 +-- drivers/staging/sm750fb/ddk750_display.c | 24 +++++----- drivers/staging/sm750fb/ddk750_mode.c | 52 +++++++++------------ drivers/staging/sm750fb/ddk750_reg.h | 77 ++++++++------------------------ drivers/staging/sm750fb/sm750_hw.c | 15 ++++--- 5 files changed, 62 insertions(+), 112 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 0031e32b8cbe..37eae59b3726 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -249,17 +249,17 @@ int ddk750_initHw(initchip_param_t *pInitParam) /* Disable Overlay, if a former application left it on */ reg = PEEK32(VIDEO_DISPLAY_CTRL); - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); + reg &= ~DISPLAY_CTRL_PLANE; POKE32(VIDEO_DISPLAY_CTRL, reg); /* Disable video alpha, if a former application left it on */ reg = PEEK32(VIDEO_ALPHA_DISPLAY_CTRL); - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); + reg &= ~DISPLAY_CTRL_PLANE; POKE32(VIDEO_ALPHA_DISPLAY_CTRL, reg); /* Disable alpha plane, if a former application left it on */ reg = PEEK32(ALPHA_DISPLAY_CTRL); - reg = FIELD_SET(reg, DISPLAY_CTRL, PLANE, DISABLE); + reg &= ~DISPLAY_CTRL_PLANE; POKE32(ALPHA_DISPLAY_CTRL, reg); /* Disable DMA Channel, if a former application left it on */ diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index ae8bb371d2b2..f0e0444f11d1 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -28,10 +28,10 @@ static void setDisplayControl(int ctrl, int disp_state) * guarantee that the plane will also enabled or * disabled. */ - val = FIELD_SET(val, DISPLAY_CTRL, TIMING, ENABLE); + val |= DISPLAY_CTRL_TIMING; POKE32(reg, val); - val = FIELD_SET(val, DISPLAY_CTRL, PLANE, ENABLE); + val |= DISPLAY_CTRL_PLANE; /* * Somehow the register value on the plane is not set @@ -53,10 +53,10 @@ static void setDisplayControl(int ctrl, int disp_state) * find out if it is necessary to wait for 1 vsync * before modifying the timing enable bit. */ - val = FIELD_SET(val, DISPLAY_CTRL, PLANE, DISABLE); + val &= ~DISPLAY_CTRL_PLANE; POKE32(reg, val); - val = FIELD_SET(val, DISPLAY_CTRL, TIMING, DISABLE); + val &= ~DISPLAY_CTRL_TIMING; POKE32(reg, val); } } @@ -71,9 +71,7 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ if (!(PEEK32(PANEL_PLL_CTRL) & PLL_CTRL_POWER) || - (FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), - DISPLAY_CTRL, TIMING) == - DISPLAY_CTRL_TIMING_DISABLE)) { + !(PEEK32(PANEL_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { return; } @@ -94,9 +92,7 @@ static void waitNextVerticalSync(int ctrl, int delay) /* Do not wait when the Primary PLL is off or display control is already off. This will prevent the software to wait forever. */ if (!(PEEK32(CRT_PLL_CTRL) & PLL_CTRL_POWER) || - (FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), - DISPLAY_CTRL, TIMING) == - DISPLAY_CTRL_TIMING_DISABLE)) { + !(PEEK32(CRT_DISPLAY_CTRL) & DISPLAY_CTRL_TIMING)) { return; } @@ -120,22 +116,22 @@ static void swPanelPowerSequence(int disp, int delay) /* disp should be 1 to open sequence */ reg = PEEK32(PANEL_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp); + reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); primaryWaitVerticalSync(delay); reg = PEEK32(PANEL_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, DATA, disp); + reg |= (disp ? PANEL_DISPLAY_CTRL_DATA : 0); POKE32(PANEL_DISPLAY_CTRL, reg); primaryWaitVerticalSync(delay); reg = PEEK32(PANEL_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, VBIASEN, disp); + reg |= (disp ? PANEL_DISPLAY_CTRL_VBIASEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); primaryWaitVerticalSync(delay); reg = PEEK32(PANEL_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, FPEN, disp); + reg |= (disp ? PANEL_DISPLAY_CTRL_FPEN : 0); POKE32(PANEL_DISPLAY_CTRL, reg); primaryWaitVerticalSync(delay); diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index a618e86879bb..1edb23530591 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -65,8 +65,7 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT); /* Set bit 14 of display controller */ - dispControl = FIELD_SET(dispControl, DISPLAY_CTRL, CLOCK_PHASE, - ACTIVE_LOW); + dispControl = DISPLAY_CTRL_CLOCK_PHASE; POKE32(CRT_DISPLAY_CTRL, dispControl); @@ -102,22 +101,19 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - tmp = FIELD_VALUE(0, DISPLAY_CTRL, VSYNC_PHASE, - pModeParam->vertical_sync_polarity) | - FIELD_VALUE(0, DISPLAY_CTRL, HSYNC_PHASE, - pModeParam->horizontal_sync_polarity) | - FIELD_SET(0, DISPLAY_CTRL, TIMING, ENABLE) | - FIELD_SET(0, DISPLAY_CTRL, PLANE, ENABLE); - + tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE; + if (pModeParam->vertical_sync_polarity) + tmp |= DISPLAY_CTRL_VSYNC_PHASE; + if (pModeParam->horizontal_sync_polarity) + tmp |= DISPLAY_CTRL_HSYNC_PHASE; if (getChipType() == SM750LE) { displayControlAdjust_SM750LE(pModeParam, tmp); } else { - reg = PEEK32(CRT_DISPLAY_CTRL) - & FIELD_CLEAR(DISPLAY_CTRL, VSYNC_PHASE) - & FIELD_CLEAR(DISPLAY_CTRL, HSYNC_PHASE) - & FIELD_CLEAR(DISPLAY_CTRL, TIMING) - & FIELD_CLEAR(DISPLAY_CTRL, PLANE); + reg = PEEK32(CRT_DISPLAY_CTRL) & + ~(DISPLAY_CTRL_VSYNC_PHASE | + DISPLAY_CTRL_HSYNC_PHASE | + DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE); POKE32(CRT_DISPLAY_CTRL, tmp | reg); } @@ -143,25 +139,21 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height) | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1)); - tmp = FIELD_VALUE(0, DISPLAY_CTRL, VSYNC_PHASE, - pModeParam->vertical_sync_polarity) | - FIELD_VALUE(0, DISPLAY_CTRL, HSYNC_PHASE, - pModeParam->horizontal_sync_polarity) | - FIELD_VALUE(0, DISPLAY_CTRL, CLOCK_PHASE, - pModeParam->clock_phase_polarity) | - FIELD_SET(0, DISPLAY_CTRL, TIMING, ENABLE) | - FIELD_SET(0, DISPLAY_CTRL, PLANE, ENABLE); + tmp = DISPLAY_CTRL_TIMING | DISPLAY_CTRL_PLANE; + if (pModeParam->vertical_sync_polarity) + tmp |= DISPLAY_CTRL_VSYNC_PHASE; + if (pModeParam->horizontal_sync_polarity) + tmp |= DISPLAY_CTRL_HSYNC_PHASE; + if (pModeParam->clock_phase_polarity) + tmp |= DISPLAY_CTRL_CLOCK_PHASE; reserved = PANEL_DISPLAY_CTRL_RESERVED_MASK | - FIELD_SET(0, PANEL_DISPLAY_CTRL, VSYNC, ACTIVE_LOW); - - reg = (PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) - & FIELD_CLEAR(DISPLAY_CTRL, CLOCK_PHASE) - & FIELD_CLEAR(DISPLAY_CTRL, VSYNC_PHASE) - & FIELD_CLEAR(DISPLAY_CTRL, HSYNC_PHASE) - & FIELD_CLEAR(DISPLAY_CTRL, TIMING) - & FIELD_CLEAR(DISPLAY_CTRL, PLANE); + PANEL_DISPLAY_CTRL_VSYNC; + reg = (PEEK32(PANEL_DISPLAY_CTRL) & ~reserved) & + ~(DISPLAY_CTRL_CLOCK_PHASE | DISPLAY_CTRL_VSYNC_PHASE | + DISPLAY_CTRL_HSYNC_PHASE | DISPLAY_CTRL_TIMING | + DISPLAY_CTRL_PLANE); /* May a hardware bug or just my test chip (not confirmed). * PANEL_DISPLAY_CTRL register seems requiring few writes diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index dac087f74817..67533840b78e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -787,75 +787,36 @@ #define PANEL_DISPLAY_CTRL_SELECT_PANEL 0 #define PANEL_DISPLAY_CTRL_SELECT_VGA 1 #define PANEL_DISPLAY_CTRL_SELECT_CRT 2 -#define PANEL_DISPLAY_CTRL_FPEN 27:27 -#define PANEL_DISPLAY_CTRL_FPEN_LOW 0 -#define PANEL_DISPLAY_CTRL_FPEN_HIGH 1 -#define PANEL_DISPLAY_CTRL_VBIASEN 26:26 -#define PANEL_DISPLAY_CTRL_VBIASEN_LOW 0 -#define PANEL_DISPLAY_CTRL_VBIASEN_HIGH 1 -#define PANEL_DISPLAY_CTRL_DATA 25:25 -#define PANEL_DISPLAY_CTRL_DATA_DISABLE 0 -#define PANEL_DISPLAY_CTRL_DATA_ENABLE 1 -#define PANEL_DISPLAY_CTRL_FPVDDEN 24:24 -#define PANEL_DISPLAY_CTRL_FPVDDEN_LOW 0 -#define PANEL_DISPLAY_CTRL_FPVDDEN_HIGH 1 +#define PANEL_DISPLAY_CTRL_FPEN BIT(27) +#define PANEL_DISPLAY_CTRL_VBIASEN BIT(26) +#define PANEL_DISPLAY_CTRL_DATA BIT(25) +#define PANEL_DISPLAY_CTRL_FPVDDEN BIT(24) #define PANEL_DISPLAY_CTRL_TFT_DISP 19:18 #define PANEL_DISPLAY_CTRL_TFT_DISP_24 0 #define PANEL_DISPLAY_CTRL_TFT_DISP_36 1 #define PANEL_DISPLAY_CTRL_TFT_DISP_18 2 - -#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY 19:19 -#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY_DISABLE 0 -#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY_ENABLE 1 -#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL 18:18 -#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL_DISABLE 0 -#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL_ENABLE 1 +#define PANEL_DISPLAY_CTRL_DUAL_DISPLAY BIT(19) +#define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL BIT(18) #define PANEL_DISPLAY_CTRL_FIFO 17:16 #define PANEL_DISPLAY_CTRL_FIFO_1 0 #define PANEL_DISPLAY_CTRL_FIFO_3 1 #define PANEL_DISPLAY_CTRL_FIFO_7 2 #define PANEL_DISPLAY_CTRL_FIFO_11 3 -#define DISPLAY_CTRL_CLOCK_PHASE 14:14 -#define DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_HIGH 0 -#define DISPLAY_CTRL_CLOCK_PHASE_ACTIVE_LOW 1 -#define DISPLAY_CTRL_VSYNC_PHASE 13:13 -#define DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_HIGH 0 -#define DISPLAY_CTRL_VSYNC_PHASE_ACTIVE_LOW 1 -#define DISPLAY_CTRL_HSYNC_PHASE 12:12 -#define DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_HIGH 0 -#define DISPLAY_CTRL_HSYNC_PHASE_ACTIVE_LOW 1 -#define PANEL_DISPLAY_CTRL_VSYNC 11:11 -#define PANEL_DISPLAY_CTRL_VSYNC_ACTIVE_HIGH 0 -#define PANEL_DISPLAY_CTRL_VSYNC_ACTIVE_LOW 1 -#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING 10:10 -#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING_DISABLE 0 -#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING_ENABLE 1 -#define PANEL_DISPLAY_CTRL_COLOR_KEY 9:9 -#define PANEL_DISPLAY_CTRL_COLOR_KEY_DISABLE 0 -#define PANEL_DISPLAY_CTRL_COLOR_KEY_ENABLE 1 -#define DISPLAY_CTRL_TIMING 8:8 -#define DISPLAY_CTRL_TIMING_DISABLE 0 -#define DISPLAY_CTRL_TIMING_ENABLE 1 -#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR 7:7 -#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR_DOWN 0 -#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR_UP 1 -#define PANEL_DISPLAY_CTRL_VERTICAL_PAN 6:6 -#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DISABLE 0 -#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_ENABLE 1 -#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR 5:5 -#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR_RIGHT 0 -#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR_LEFT 1 -#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN 4:4 -#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DISABLE 0 -#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_ENABLE 1 -#define DISPLAY_CTRL_GAMMA 3:3 -#define DISPLAY_CTRL_GAMMA_DISABLE 0 -#define DISPLAY_CTRL_GAMMA_ENABLE 1 -#define DISPLAY_CTRL_PLANE 2:2 -#define DISPLAY_CTRL_PLANE_DISABLE 0 -#define DISPLAY_CTRL_PLANE_ENABLE 1 +#define DISPLAY_CTRL_CLOCK_PHASE BIT(14) +#define DISPLAY_CTRL_VSYNC_PHASE BIT(13) +#define DISPLAY_CTRL_HSYNC_PHASE BIT(12) +#define PANEL_DISPLAY_CTRL_VSYNC BIT(11) +#define PANEL_DISPLAY_CTRL_CAPTURE_TIMING BIT(10) +#define PANEL_DISPLAY_CTRL_COLOR_KEY BIT(9) +#define DISPLAY_CTRL_TIMING BIT(8) +#define PANEL_DISPLAY_CTRL_VERTICAL_PAN_DIR BIT(7) +#define PANEL_DISPLAY_CTRL_VERTICAL_PAN BIT(6) +#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN_DIR BIT(5) +#define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN BIT(4) +#define DISPLAY_CTRL_GAMMA BIT(3) +#define DISPLAY_CTRL_PLANE BIT(2) #define PANEL_DISPLAY_CTRL_FORMAT 1:0 #define PANEL_DISPLAY_CTRL_FORMAT_8 0 #define PANEL_DISPLAY_CTRL_FORMAT_16 1 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 52fd250d7afe..384989184537 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -416,28 +416,24 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) case FB_BLANK_UNBLANK: pr_debug("flag = FB_BLANK_UNBLANK\n"); dpms = SYSTEM_CTRL_DPMS_VPHP; - pps = PANEL_DISPLAY_CTRL_DATA_ENABLE; + pps = PANEL_DISPLAY_CTRL_DATA; crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; break; case FB_BLANK_NORMAL: pr_debug("flag = FB_BLANK_NORMAL\n"); dpms = SYSTEM_CTRL_DPMS_VPHP; - pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; crtdb = CRT_DISPLAY_CTRL_BLANK_ON; break; case FB_BLANK_VSYNC_SUSPEND: dpms = SYSTEM_CTRL_DPMS_VNHP; - pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; crtdb = CRT_DISPLAY_CTRL_BLANK_ON; break; case FB_BLANK_HSYNC_SUSPEND: dpms = SYSTEM_CTRL_DPMS_VPHN; - pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; crtdb = CRT_DISPLAY_CTRL_BLANK_ON; break; case FB_BLANK_POWERDOWN: dpms = SYSTEM_CTRL_DPMS_VNHN; - pps = PANEL_DISPLAY_CTRL_DATA_DISABLE; crtdb = CRT_DISPLAY_CTRL_BLANK_ON; break; } @@ -449,8 +445,13 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb)); } - if (output->paths & sm750_panel) - POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps)); + if (output->paths & sm750_panel) { + unsigned int val = PEEK32(PANEL_DISPLAY_CTRL); + + val &= ~PANEL_DISPLAY_CTRL_DATA; + val |= pps; + POKE32(PANEL_DISPLAY_CTRL, val); + } return 0; } -- cgit From f5d7f1905fb2e1b57e0b2f75ef21ce8b016a34b3 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:09 +0200 Subject: staging: sm750fb: remove PANEL_DISPLAY_CTRL_TFT_DISP defines The PANEL_DISPLAY_CTRL_TFT_DISP definitions artificially encode PANEL_DISPLAY_CTRL_DUAL_DISPLAY and PANEL_DISPLAY_CTRL_DOUBLE_PIXEL bits combinations. Replace the PANEL_DISPLAY_CTRL_TFT_DISP usage with direct use of the bits defined in the datasheet. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 6 ------ drivers/staging/sm750fb/sm750_hw.c | 17 ++++++++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 67533840b78e..6df382790a74 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -791,12 +791,6 @@ #define PANEL_DISPLAY_CTRL_VBIASEN BIT(26) #define PANEL_DISPLAY_CTRL_DATA BIT(25) #define PANEL_DISPLAY_CTRL_FPVDDEN BIT(24) - -#define PANEL_DISPLAY_CTRL_TFT_DISP 19:18 -#define PANEL_DISPLAY_CTRL_TFT_DISP_24 0 -#define PANEL_DISPLAY_CTRL_TFT_DISP_36 1 -#define PANEL_DISPLAY_CTRL_TFT_DISP_18 2 - #define PANEL_DISPLAY_CTRL_DUAL_DISPLAY BIT(19) #define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL BIT(18) #define PANEL_DISPLAY_CTRL_FIFO 17:16 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 384989184537..d96595433195 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -130,17 +130,20 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) POKE32(SYSTEM_CTRL, val); } + val = PEEK32(PANEL_DISPLAY_CTRL) & + ~(PANEL_DISPLAY_CTRL_DUAL_DISPLAY | + PANEL_DISPLAY_CTRL_DOUBLE_PIXEL); switch (sm750_dev->pnltype) { - case sm750_doubleTFT: case sm750_24TFT: + break; + case sm750_doubleTFT: + val |= PANEL_DISPLAY_CTRL_DOUBLE_PIXEL; + break; case sm750_dualTFT: - POKE32(PANEL_DISPLAY_CTRL, - FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), - PANEL_DISPLAY_CTRL, - TFT_DISP, - sm750_dev->pnltype)); - break; + val |= PANEL_DISPLAY_CTRL_DUAL_DISPLAY; + break; } + POKE32(PANEL_DISPLAY_CTRL, val); } else { /* for 750LE ,no DVI chip initialization makes Monitor no signal */ /* Set up GPIO for software I2C to program DVI chip in the -- cgit From c4e893b7cca833c72723f15fdfc28c9bea296e30 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:10 +0200 Subject: staging: sm750fb: change definition of PANEL_DISPLAY_CTRL multi-bit fields Use more straight-forward definitions for multi-bit fields of PANEL_DISPLAY_CTRL register and use open-coded implementation for register manipulation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 4 +++- drivers/staging/sm750fb/ddk750_reg.h | 27 ++++++++++++++------------- drivers/staging/sm750fb/sm750_hw.c | 6 +----- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index f0e0444f11d1..fb5523c445ce 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -144,7 +144,9 @@ void ddk750_setLogicalDispOut(disp_output_t output) if (output & PNL_2_USAGE) { /* set panel path controller select */ reg = PEEK32(PANEL_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, SELECT, (output & PNL_2_MASK)>>PNL_2_OFFSET); + reg &= ~PANEL_DISPLAY_CTRL_SELECT_MASK; + reg |= (((output & PNL_2_MASK) >> PNL_2_OFFSET) << + PANEL_DISPLAY_CTRL_SELECT_SHIFT); POKE32(PANEL_DISPLAY_CTRL, reg); } diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 6df382790a74..cdc5867038d8 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -783,21 +783,22 @@ #define PANEL_DISPLAY_CTRL 0x080000 #define PANEL_DISPLAY_CTRL_RESERVED_MASK 0xc0f08000 -#define PANEL_DISPLAY_CTRL_SELECT 29:28 -#define PANEL_DISPLAY_CTRL_SELECT_PANEL 0 -#define PANEL_DISPLAY_CTRL_SELECT_VGA 1 -#define PANEL_DISPLAY_CTRL_SELECT_CRT 2 +#define PANEL_DISPLAY_CTRL_SELECT_SHIFT 28 +#define PANEL_DISPLAY_CTRL_SELECT_MASK (0x3 << 28) +#define PANEL_DISPLAY_CTRL_SELECT_PANEL (0x0 << 28) +#define PANEL_DISPLAY_CTRL_SELECT_VGA (0x1 << 28) +#define PANEL_DISPLAY_CTRL_SELECT_CRT (0x2 << 28) #define PANEL_DISPLAY_CTRL_FPEN BIT(27) #define PANEL_DISPLAY_CTRL_VBIASEN BIT(26) #define PANEL_DISPLAY_CTRL_DATA BIT(25) #define PANEL_DISPLAY_CTRL_FPVDDEN BIT(24) #define PANEL_DISPLAY_CTRL_DUAL_DISPLAY BIT(19) #define PANEL_DISPLAY_CTRL_DOUBLE_PIXEL BIT(18) -#define PANEL_DISPLAY_CTRL_FIFO 17:16 -#define PANEL_DISPLAY_CTRL_FIFO_1 0 -#define PANEL_DISPLAY_CTRL_FIFO_3 1 -#define PANEL_DISPLAY_CTRL_FIFO_7 2 -#define PANEL_DISPLAY_CTRL_FIFO_11 3 +#define PANEL_DISPLAY_CTRL_FIFO (0x3 << 16) +#define PANEL_DISPLAY_CTRL_FIFO_1 (0x0 << 16) +#define PANEL_DISPLAY_CTRL_FIFO_3 (0x1 << 16) +#define PANEL_DISPLAY_CTRL_FIFO_7 (0x2 << 16) +#define PANEL_DISPLAY_CTRL_FIFO_11 (0x3 << 16) #define DISPLAY_CTRL_CLOCK_PHASE BIT(14) #define DISPLAY_CTRL_VSYNC_PHASE BIT(13) #define DISPLAY_CTRL_HSYNC_PHASE BIT(12) @@ -811,10 +812,10 @@ #define PANEL_DISPLAY_CTRL_HORIZONTAL_PAN BIT(4) #define DISPLAY_CTRL_GAMMA BIT(3) #define DISPLAY_CTRL_PLANE BIT(2) -#define PANEL_DISPLAY_CTRL_FORMAT 1:0 -#define PANEL_DISPLAY_CTRL_FORMAT_8 0 -#define PANEL_DISPLAY_CTRL_FORMAT_16 1 -#define PANEL_DISPLAY_CTRL_FORMAT_32 2 +#define PANEL_DISPLAY_CTRL_FORMAT (0x3 << 0) +#define PANEL_DISPLAY_CTRL_FORMAT_8 (0x0 << 0) +#define PANEL_DISPLAY_CTRL_FORMAT_16 (0x1 << 0) +#define PANEL_DISPLAY_CTRL_FORMAT_32 (0x2 << 0) #define PANEL_PAN_CTRL 0x080004 #define PANEL_PAN_CTRL_VERTICAL_PAN 31:24 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index d96595433195..964c5f0a7687 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -336,11 +336,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* set pixel format */ reg = PEEK32(PANEL_DISPLAY_CTRL); - POKE32(PANEL_DISPLAY_CTRL, - FIELD_VALUE(reg, - PANEL_DISPLAY_CTRL, FORMAT, - (var->bits_per_pixel >> 4) - )); + POKE32(PANEL_DISPLAY_CTRL, reg | (var->bits_per_pixel >> 4)); } else { /* not implemented now */ POKE32(CRT_FB_ADDRESS, crtc->oScreen); -- cgit From 4463690afc066b7034cd5c2bd6b0be88ab7c99ef Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:11 +0200 Subject: staging: sm750fb: change definition of PANEL_FB_ADDRESS fields Use BIT() macro for single-bit fields of PANEL_FB_ADDRESS register and define PANEL_FB_ADDRESS_ADDRESS_MASK for masking the address bits. Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 10 +++------- drivers/staging/sm750fb/sm750_hw.c | 8 +++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index cdc5867038d8..1b96af3f475d 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -828,13 +828,9 @@ #define PANEL_COLOR_KEY_VALUE 15:0 #define PANEL_FB_ADDRESS 0x08000C -#define PANEL_FB_ADDRESS_STATUS 31:31 -#define PANEL_FB_ADDRESS_STATUS_CURRENT 0 -#define PANEL_FB_ADDRESS_STATUS_PENDING 1 -#define PANEL_FB_ADDRESS_EXT 27:27 -#define PANEL_FB_ADDRESS_EXT_LOCAL 0 -#define PANEL_FB_ADDRESS_EXT_EXTERNAL 1 -#define PANEL_FB_ADDRESS_ADDRESS 25:0 +#define PANEL_FB_ADDRESS_STATUS BIT(31) +#define PANEL_FB_ADDRESS_EXT BIT(27) +#define PANEL_FB_ADDRESS_ADDRESS_MASK 0x1ffffff #define PANEL_FB_WIDTH 0x080010 #define PANEL_FB_WIDTH_WIDTH 29:16 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 964c5f0a7687..938ea7262646 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -308,9 +308,7 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, if (crtc->channel != sm750_secondary) { /* set pitch, offset ,width,start address ,etc... */ POKE32(PANEL_FB_ADDRESS, - FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)| - FIELD_SET(0, PANEL_FB_ADDRESS, EXT, LOCAL)| - FIELD_VALUE(0, PANEL_FB_ADDRESS, ADDRESS, crtc->oScreen)); + crtc->oScreen & PANEL_FB_ADDRESS_ADDRESS_MASK); reg = var->xres * (var->bits_per_pixel >> 3); /* crtc->channel is not equal to par->index on numeric,be aware of that */ @@ -538,8 +536,8 @@ int hw_sm750_pan_display(struct lynxfb_crtc *crtc, total += crtc->oScreen; if (crtc->channel == sm750_primary) { POKE32(PANEL_FB_ADDRESS, - FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS), - PANEL_FB_ADDRESS, ADDRESS, total)); + PEEK32(PANEL_FB_ADDRESS) | + (total & PANEL_FB_ADDRESS_ADDRESS_MASK)); } else { POKE32(CRT_FB_ADDRESS, FIELD_VALUE(PEEK32(CRT_FB_ADDRESS), -- cgit From 26a3cc907c324261e3d0f76869f856d1273528d5 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:12 +0200 Subject: staging: sm750fb: change definition of PANEL_FB_WIDTH fields Use stratight-forward defintion of PANEL_FB_WIDTH register fields and use open-coded implementation for register manipulations Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 5 +++-- drivers/staging/sm750fb/sm750_hw.c | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 1b96af3f475d..7e0cc95ae290 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -833,8 +833,9 @@ #define PANEL_FB_ADDRESS_ADDRESS_MASK 0x1ffffff #define PANEL_FB_WIDTH 0x080010 -#define PANEL_FB_WIDTH_WIDTH 29:16 -#define PANEL_FB_WIDTH_OFFSET 13:0 +#define PANEL_FB_WIDTH_WIDTH_SHIFT 16 +#define PANEL_FB_WIDTH_WIDTH_MASK (0x3fff << 16) +#define PANEL_FB_WIDTH_OFFSET_MASK 0x3fff #define PANEL_WINDOW_WIDTH 0x080014 #define PANEL_WINDOW_WIDTH_WIDTH 27:16 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 938ea7262646..9e350b459e9a 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -313,10 +313,10 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg = var->xres * (var->bits_per_pixel >> 3); /* crtc->channel is not equal to par->index on numeric,be aware of that */ reg = ALIGN(reg, crtc->line_pad); - - POKE32(PANEL_FB_WIDTH, - FIELD_VALUE(0, PANEL_FB_WIDTH, WIDTH, reg)| - FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length)); + reg = (reg << PANEL_FB_WIDTH_WIDTH_SHIFT) & + PANEL_FB_WIDTH_WIDTH_MASK; + reg |= (fix->line_length & PANEL_FB_WIDTH_OFFSET_MASK); + POKE32(PANEL_FB_WIDTH, reg); POKE32(PANEL_WINDOW_WIDTH, FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)| -- cgit From 4c221d82cfdb4ec0050999dd305f85670ca09fd5 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:13 +0200 Subject: staging: sm750fb: change definition of PANEL_WINDOW_WIDTH fields Use stratight-forward defintion of PANEL_WINDOW_WIDTH register fields and use open-coded implementation for register manipulations Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 5 +++-- drivers/staging/sm750fb/sm750_hw.c | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 7e0cc95ae290..6e6694d651d5 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -838,8 +838,9 @@ #define PANEL_FB_WIDTH_OFFSET_MASK 0x3fff #define PANEL_WINDOW_WIDTH 0x080014 -#define PANEL_WINDOW_WIDTH_WIDTH 27:16 -#define PANEL_WINDOW_WIDTH_X 11:0 +#define PANEL_WINDOW_WIDTH_WIDTH_SHIFT 16 +#define PANEL_WINDOW_WIDTH_WIDTH_MASK (0xfff << 16) +#define PANEL_WINDOW_WIDTH_X_MASK 0xfff #define PANEL_WINDOW_HEIGHT 0x080018 #define PANEL_WINDOW_HEIGHT_HEIGHT 27:16 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 9e350b459e9a..a0d72144392e 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -318,9 +318,10 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg |= (fix->line_length & PANEL_FB_WIDTH_OFFSET_MASK); POKE32(PANEL_FB_WIDTH, reg); - POKE32(PANEL_WINDOW_WIDTH, - FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)| - FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset)); + reg = ((var->xres - 1) << PANEL_WINDOW_WIDTH_WIDTH_SHIFT) & + PANEL_WINDOW_WIDTH_WIDTH_MASK; + reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK); + POKE32(PANEL_WINDOW_WIDTH, reg); POKE32(PANEL_WINDOW_HEIGHT, FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)| -- cgit From f91969f773478922173605c44fe0a966cf0e438d Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:14 +0200 Subject: staging: sm750fb: change definition of PANEL_WINDOW_HEIGHT fields Use stratight-forward defintion of PANEL_WINDOW_HEIGHT register fields and use open-coded implementation for register manipulations Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 5 +++-- drivers/staging/sm750fb/sm750_hw.c | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 6e6694d651d5..d3359c5e8ced 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -843,8 +843,9 @@ #define PANEL_WINDOW_WIDTH_X_MASK 0xfff #define PANEL_WINDOW_HEIGHT 0x080018 -#define PANEL_WINDOW_HEIGHT_HEIGHT 27:16 -#define PANEL_WINDOW_HEIGHT_Y 11:0 +#define PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT 16 +#define PANEL_WINDOW_HEIGHT_HEIGHT_MASK (0xfff << 16) +#define PANEL_WINDOW_HEIGHT_Y_MASK 0xfff #define PANEL_PLANE_TL 0x08001C #define PANEL_PLANE_TL_TOP 26:16 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index a0d72144392e..0ea3106183d6 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -323,9 +323,11 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, reg |= (var->xoffset & PANEL_WINDOW_WIDTH_X_MASK); POKE32(PANEL_WINDOW_WIDTH, reg); - POKE32(PANEL_WINDOW_HEIGHT, - FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, HEIGHT, var->yres_virtual - 1)| - FIELD_VALUE(0, PANEL_WINDOW_HEIGHT, Y, var->yoffset)); + reg = ((var->yres_virtual - 1) << + PANEL_WINDOW_HEIGHT_HEIGHT_SHIFT); + reg &= PANEL_WINDOW_HEIGHT_HEIGHT_MASK; + reg |= (var->yoffset & PANEL_WINDOW_HEIGHT_Y_MASK); + POKE32(PANEL_WINDOW_HEIGHT, reg); POKE32(PANEL_PLANE_TL, 0); -- cgit From 30ca5cb63c569654522c1c2501cd839e2b178221 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:15 +0200 Subject: staging: sm750fb: change definition of PANEL_PLANE_TL fields Use stratight-forward defintion of PANEL_PLANE_TL register fields Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index d3359c5e8ced..b8460a5b8c2c 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -848,8 +848,9 @@ #define PANEL_WINDOW_HEIGHT_Y_MASK 0xfff #define PANEL_PLANE_TL 0x08001C -#define PANEL_PLANE_TL_TOP 26:16 -#define PANEL_PLANE_TL_LEFT 10:0 +#define PANEL_PLANE_TL_TOP_SHIFT 16 +#define PANEL_PLANE_TL_TOP_MASK (0xeff << 16) +#define PANEL_PLANE_TL_LEFT_MASK 0xeff #define PANEL_PLANE_BR 0x080020 #define PANEL_PLANE_BR_BOTTOM 26:16 -- cgit From 27b047bbe1ee9c07749fb558a3d220dfd7288331 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:16 +0200 Subject: staging: sm750fb: change definition of PANEL_PLANE_BR fields Use stratight-forward defintion of PANEL_PLANE_BR register fields and use open-coded implementation for register manipulations Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_reg.h | 5 +++-- drivers/staging/sm750fb/sm750_hw.c | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index b8460a5b8c2c..65510983bae2 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -853,8 +853,9 @@ #define PANEL_PLANE_TL_LEFT_MASK 0xeff #define PANEL_PLANE_BR 0x080020 -#define PANEL_PLANE_BR_BOTTOM 26:16 -#define PANEL_PLANE_BR_RIGHT 10:0 +#define PANEL_PLANE_BR_BOTTOM_SHIFT 16 +#define PANEL_PLANE_BR_BOTTOM_MASK (0xeff << 16) +#define PANEL_PLANE_BR_RIGHT_MASK 0xeff #define PANEL_HORIZONTAL_TOTAL 0x080024 #define PANEL_HORIZONTAL_TOTAL_TOTAL 27:16 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 0ea3106183d6..5951d1a03c29 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -331,9 +331,10 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, POKE32(PANEL_PLANE_TL, 0); - POKE32(PANEL_PLANE_BR, - FIELD_VALUE(0, PANEL_PLANE_BR, BOTTOM, var->yres - 1)| - FIELD_VALUE(0, PANEL_PLANE_BR, RIGHT, var->xres - 1)); + reg = ((var->yres - 1) << PANEL_PLANE_BR_BOTTOM_SHIFT) & + PANEL_PLANE_BR_BOTTOM_MASK; + reg |= ((var->xres - 1) & PANEL_PLANE_BR_RIGHT_MASK); + POKE32(PANEL_PLANE_BR, reg); /* set pixel format */ reg = PEEK32(PANEL_DISPLAY_CTRL); -- cgit From 0f23be7050ca836398a5b3f2fd73227dce3ef37a Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:17 +0200 Subject: staging: sm750fb: use BIT macro for DMA_ABORT_INTERRUPT single-bit fields Replace complex definition of DMA_ABORT_INTERRUPT register fields with BIT() macro and use open-coded implementation for register manipulation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_chip.c | 2 +- drivers/staging/sm750fb/ddk750_reg.h | 20 ++++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c index 37eae59b3726..e53a3d1271ac 100644 --- a/drivers/staging/sm750fb/ddk750_chip.c +++ b/drivers/staging/sm750fb/ddk750_chip.c @@ -264,7 +264,7 @@ int ddk750_initHw(initchip_param_t *pInitParam) /* Disable DMA Channel, if a former application left it on */ reg = PEEK32(DMA_ABORT_INTERRUPT); - reg = FIELD_SET(reg, DMA_ABORT_INTERRUPT, ABORT_1, ABORT); + reg |= DMA_ABORT_INTERRUPT_ABORT_1; POKE32(DMA_ABORT_INTERRUPT, reg); /* Disable DMA Power, if a former application left it on */ diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 65510983bae2..73f3c34c236e 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -1973,22 +1973,10 @@ #define DMA_1_SIZE_CONTROL_SIZE 23:0 #define DMA_ABORT_INTERRUPT 0x0D0020 -#define DMA_ABORT_INTERRUPT_ABORT_1 5:5 -#define DMA_ABORT_INTERRUPT_ABORT_1_ENABLE 0 -#define DMA_ABORT_INTERRUPT_ABORT_1_ABORT 1 -#define DMA_ABORT_INTERRUPT_ABORT_0 4:4 -#define DMA_ABORT_INTERRUPT_ABORT_0_ENABLE 0 -#define DMA_ABORT_INTERRUPT_ABORT_0_ABORT 1 -#define DMA_ABORT_INTERRUPT_INT_1 1:1 -#define DMA_ABORT_INTERRUPT_INT_1_CLEAR 0 -#define DMA_ABORT_INTERRUPT_INT_1_FINISHED 1 -#define DMA_ABORT_INTERRUPT_INT_0 0:0 -#define DMA_ABORT_INTERRUPT_INT_0_CLEAR 0 -#define DMA_ABORT_INTERRUPT_INT_0_FINISHED 1 - - - - +#define DMA_ABORT_INTERRUPT_ABORT_1 BIT(5) +#define DMA_ABORT_INTERRUPT_ABORT_0 BIT(4) +#define DMA_ABORT_INTERRUPT_INT_1 BIT(1) +#define DMA_ABORT_INTERRUPT_INT_0 BIT(0) /* Default i2c CLK and Data GPIO. These are the default i2c pins */ #define DEFAULT_I2C_SCL 30 -- cgit From d8264edf44fefbf175542f92b3bc756f398ded9e Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:18 +0200 Subject: staging: sm750fb: use BIT macro for CRT_DISPLAY_CTRL single-bit fields Replace complex definition of CRT_DISPLAY_CTRL register fields with BIT() macro and use open-coded implementation for register manipulation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 2 +- drivers/staging/sm750fb/ddk750_mode.c | 3 +-- drivers/staging/sm750fb/ddk750_reg.h | 39 ++++++++------------------------ drivers/staging/sm750fb/sm750_hw.c | 29 ++++++++++++++---------- 4 files changed, 28 insertions(+), 45 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index fb5523c445ce..7bb6fd427608 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -155,7 +155,7 @@ void ddk750_setLogicalDispOut(disp_output_t output) reg = PEEK32(CRT_DISPLAY_CTRL); reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET); /*se blank off */ - reg = FIELD_SET(reg, CRT_DISPLAY_CTRL, BLANK, OFF); + reg &= ~CRT_DISPLAY_CTRL_BLANK; POKE32(CRT_DISPLAY_CTRL, reg); } diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 1edb23530591..96fd4bfb3494 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -61,8 +61,7 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25); /* Set bit 25:24 of display controller */ - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT); - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT); + dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT); /* Set bit 14 of display controller */ dispControl = DISPLAY_CTRL_CLOCK_PHASE; diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 73f3c34c236e..446bb85e55e0 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -1331,38 +1331,19 @@ #define CRT_DISPLAY_CTRL_CLK_PLL80 5 #define CRT_DISPLAY_CTRL_CLK_PLL108 6 #define CRT_DISPLAY_CTRL_CLK_RESERVED 7 -#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC 26:26 -#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_DISABLE 1 -#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_ENABLE 0 +#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC BIT(26) /* SM750LE definition */ -#define CRT_DISPLAY_CTRL_CRTSELECT 25:25 -#define CRT_DISPLAY_CTRL_CRTSELECT_VGA 0 -#define CRT_DISPLAY_CTRL_CRTSELECT_CRT 1 -#define CRT_DISPLAY_CTRL_RGBBIT 24:24 -#define CRT_DISPLAY_CTRL_RGBBIT_24BIT 0 -#define CRT_DISPLAY_CTRL_RGBBIT_12BIT 1 +#define CRT_DISPLAY_CTRL_CRTSELECT BIT(25) +#define CRT_DISPLAY_CTRL_RGBBIT BIT(24) #ifndef VALIDATION_CHIP - #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC 26:26 - #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_DISABLE 1 - #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_ENABLE 0 - #define CRT_DISPLAY_CTRL_CENTERING 24:24 - #define CRT_DISPLAY_CTRL_CENTERING_DISABLE 0 - #define CRT_DISPLAY_CTRL_CENTERING_ENABLE 1 + #define CRT_DISPLAY_CTRL_CENTERING BIT(24) #endif -#define CRT_DISPLAY_CTRL_LOCK_TIMING 23:23 -#define CRT_DISPLAY_CTRL_LOCK_TIMING_DISABLE 0 -#define CRT_DISPLAY_CTRL_LOCK_TIMING_ENABLE 1 -#define CRT_DISPLAY_CTRL_EXPANSION 22:22 -#define CRT_DISPLAY_CTRL_EXPANSION_DISABLE 0 -#define CRT_DISPLAY_CTRL_EXPANSION_ENABLE 1 -#define CRT_DISPLAY_CTRL_VERTICAL_MODE 21:21 -#define CRT_DISPLAY_CTRL_VERTICAL_MODE_REPLICATE 0 -#define CRT_DISPLAY_CTRL_VERTICAL_MODE_INTERPOLATE 1 -#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE 20:20 -#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE_REPLICATE 0 -#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE_INTERPOLATE 1 +#define CRT_DISPLAY_CTRL_LOCK_TIMING BIT(23) +#define CRT_DISPLAY_CTRL_EXPANSION BIT(22) +#define CRT_DISPLAY_CTRL_VERTICAL_MODE BIT(21) +#define CRT_DISPLAY_CTRL_HORIZONTAL_MODE BIT(20) #define CRT_DISPLAY_CTRL_SELECT 19:18 #define CRT_DISPLAY_CTRL_SELECT_PANEL 0 #define CRT_DISPLAY_CTRL_SELECT_VGA 1 @@ -1372,9 +1353,7 @@ #define CRT_DISPLAY_CTRL_FIFO_3 1 #define CRT_DISPLAY_CTRL_FIFO_7 2 #define CRT_DISPLAY_CTRL_FIFO_11 3 -#define CRT_DISPLAY_CTRL_BLANK 10:10 -#define CRT_DISPLAY_CTRL_BLANK_OFF 0 -#define CRT_DISPLAY_CTRL_BLANK_ON 1 +#define CRT_DISPLAY_CTRL_BLANK BIT(10) #define CRT_DISPLAY_CTRL_PIXEL 7:4 #define CRT_DISPLAY_CTRL_FORMAT 1:0 #define CRT_DISPLAY_CTRL_FORMAT_8 0 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 5951d1a03c29..ce08e6c13f03 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -378,31 +378,35 @@ int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank) switch (blank) { case FB_BLANK_UNBLANK: dpms = CRT_DISPLAY_CTRL_DPMS_0; - crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; + crtdb = 0; break; case FB_BLANK_NORMAL: dpms = CRT_DISPLAY_CTRL_DPMS_0; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; case FB_BLANK_VSYNC_SUSPEND: dpms = CRT_DISPLAY_CTRL_DPMS_2; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; case FB_BLANK_HSYNC_SUSPEND: dpms = CRT_DISPLAY_CTRL_DPMS_1; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; case FB_BLANK_POWERDOWN: dpms = CRT_DISPLAY_CTRL_DPMS_3; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; default: return -EINVAL; } if (output->paths & sm750_crt) { + unsigned int val; + POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms)); - POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb)); + + val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK; + POKE32(CRT_DISPLAY_CTRL, val | crtdb); } return 0; } @@ -418,24 +422,23 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) pr_debug("flag = FB_BLANK_UNBLANK\n"); dpms = SYSTEM_CTRL_DPMS_VPHP; pps = PANEL_DISPLAY_CTRL_DATA; - crtdb = CRT_DISPLAY_CTRL_BLANK_OFF; break; case FB_BLANK_NORMAL: pr_debug("flag = FB_BLANK_NORMAL\n"); dpms = SYSTEM_CTRL_DPMS_VPHP; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; case FB_BLANK_VSYNC_SUSPEND: dpms = SYSTEM_CTRL_DPMS_VNHP; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; case FB_BLANK_HSYNC_SUSPEND: dpms = SYSTEM_CTRL_DPMS_VPHN; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; case FB_BLANK_POWERDOWN: dpms = SYSTEM_CTRL_DPMS_VNHN; - crtdb = CRT_DISPLAY_CTRL_BLANK_ON; + crtdb = CRT_DISPLAY_CTRL_BLANK; break; } @@ -443,7 +446,9 @@ int hw_sm750_setBLANK(struct lynxfb_output *output, int blank) unsigned int val = PEEK32(SYSTEM_CTRL) & ~SYSTEM_CTRL_DPMS_MASK; POKE32(SYSTEM_CTRL, val | dpms); - POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb)); + + val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK; + POKE32(CRT_DISPLAY_CTRL, val | crtdb); } if (output->paths & sm750_panel) { -- cgit From cdce1f187733feb25a0fa5d4a3043bf635f2f8ce Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:19 +0200 Subject: staging: sm750fb: change definition of CRT_DISPLAY_CTRL multi-bit fields Use more straight-forward definitions for multi-bit fields of CRT_DISPLAY_CTRL register and use open-coded implementation for register manipulation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_display.c | 4 ++- drivers/staging/sm750fb/ddk750_mode.c | 18 +++++----- drivers/staging/sm750fb/ddk750_power.c | 6 ++-- drivers/staging/sm750fb/ddk750_reg.h | 58 +++++++++++++++++--------------- drivers/staging/sm750fb/sm750_hw.c | 6 ++-- 5 files changed, 49 insertions(+), 43 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c index 7bb6fd427608..ca4973ee49e4 100644 --- a/drivers/staging/sm750fb/ddk750_display.c +++ b/drivers/staging/sm750fb/ddk750_display.c @@ -153,7 +153,9 @@ void ddk750_setLogicalDispOut(disp_output_t output) if (output & CRT_2_USAGE) { /* set crt path controller select */ reg = PEEK32(CRT_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET); + reg &= ~CRT_DISPLAY_CTRL_SELECT_MASK; + reg |= (((output & CRT_2_MASK) >> CRT_2_OFFSET) << + CRT_DISPLAY_CTRL_SELECT_SHIFT); /*se blank off */ reg &= ~CRT_DISPLAY_CTRL_BLANK; POKE32(CRT_DISPLAY_CTRL, reg); diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 96fd4bfb3494..9ec3c6481f8d 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -39,26 +39,26 @@ static unsigned long displayControlAdjust_SM750LE(mode_parameter_t *pModeParam, */ /* Clear bit 29:27 of display control register */ - dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK); + dispControl &= ~CRT_DISPLAY_CTRL_CLK_MASK; /* Set bit 29:27 of display control register for the right clock */ /* Note that SM750LE only need to supported 7 resolutions. */ if (x == 800 && y == 600) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL41; else if (x == 1024 && y == 768) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL65; else if (x == 1152 && y == 864) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80; else if (x == 1280 && y == 768) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL80; else if (x == 1280 && y == 720) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL74; else if (x == 1280 && y == 960) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108; else if (x == 1280 && y == 1024) - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL108; else /* default to VGA clock */ - dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25); + dispControl |= CRT_DISPLAY_CTRL_CLK_PLL25; /* Set bit 25:24 of display controller */ dispControl |= (CRT_DISPLAY_CTRL_CRTSELECT | CRT_DISPLAY_CTRL_RGBBIT); diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index c85dfc509b04..ec1cac2c1793 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -7,9 +7,9 @@ void ddk750_setDPMS(DPMS_t state) unsigned int value; if (getChipType() == SM750LE) { - value = PEEK32(CRT_DISPLAY_CTRL); - POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL, - DPMS, state)); + value = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK; + value |= (state << CRT_DISPLAY_CTRL_DPMS_SHIFT); + POKE32(CRT_DISPLAY_CTRL, value); } else { value = PEEK32(SYSTEM_CTRL); value = (value & ~SYSTEM_CTRL_DPMS_MASK) | state; diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 446bb85e55e0..d033d4ff0549 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -1317,20 +1317,21 @@ #define CRT_DISPLAY_CTRL_RESERVED_MASK 0xfb008200 /* SM750LE definition */ -#define CRT_DISPLAY_CTRL_DPMS 31:30 -#define CRT_DISPLAY_CTRL_DPMS_0 0 -#define CRT_DISPLAY_CTRL_DPMS_1 1 -#define CRT_DISPLAY_CTRL_DPMS_2 2 -#define CRT_DISPLAY_CTRL_DPMS_3 3 -#define CRT_DISPLAY_CTRL_CLK 29:27 -#define CRT_DISPLAY_CTRL_CLK_PLL25 0 -#define CRT_DISPLAY_CTRL_CLK_PLL41 1 -#define CRT_DISPLAY_CTRL_CLK_PLL62 2 -#define CRT_DISPLAY_CTRL_CLK_PLL65 3 -#define CRT_DISPLAY_CTRL_CLK_PLL74 4 -#define CRT_DISPLAY_CTRL_CLK_PLL80 5 -#define CRT_DISPLAY_CTRL_CLK_PLL108 6 -#define CRT_DISPLAY_CTRL_CLK_RESERVED 7 +#define CRT_DISPLAY_CTRL_DPMS_SHIFT 30 +#define CRT_DISPLAY_CTRL_DPMS_MASK (0x3 << 30) +#define CRT_DISPLAY_CTRL_DPMS_0 (0x0 << 30) +#define CRT_DISPLAY_CTRL_DPMS_1 (0x1 << 30) +#define CRT_DISPLAY_CTRL_DPMS_2 (0x2 << 30) +#define CRT_DISPLAY_CTRL_DPMS_3 (0x3 << 30) +#define CRT_DISPLAY_CTRL_CLK_MASK (0x7 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL25 (0x0 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL41 (0x1 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL62 (0x2 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL65 (0x3 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL74 (0x4 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL80 (0x5 << 27) +#define CRT_DISPLAY_CTRL_CLK_PLL108 (0x6 << 27) +#define CRT_DISPLAY_CTRL_CLK_RESERVED (0x7 << 27) #define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC BIT(26) /* SM750LE definition */ @@ -1344,21 +1345,22 @@ #define CRT_DISPLAY_CTRL_EXPANSION BIT(22) #define CRT_DISPLAY_CTRL_VERTICAL_MODE BIT(21) #define CRT_DISPLAY_CTRL_HORIZONTAL_MODE BIT(20) -#define CRT_DISPLAY_CTRL_SELECT 19:18 -#define CRT_DISPLAY_CTRL_SELECT_PANEL 0 -#define CRT_DISPLAY_CTRL_SELECT_VGA 1 -#define CRT_DISPLAY_CTRL_SELECT_CRT 2 -#define CRT_DISPLAY_CTRL_FIFO 17:16 -#define CRT_DISPLAY_CTRL_FIFO_1 0 -#define CRT_DISPLAY_CTRL_FIFO_3 1 -#define CRT_DISPLAY_CTRL_FIFO_7 2 -#define CRT_DISPLAY_CTRL_FIFO_11 3 +#define CRT_DISPLAY_CTRL_SELECT_SHIFT 18 +#define CRT_DISPLAY_CTRL_SELECT_MASK (0x3 << 18) +#define CRT_DISPLAY_CTRL_SELECT_PANEL (0x0 << 18) +#define CRT_DISPLAY_CTRL_SELECT_VGA (0x1 << 18) +#define CRT_DISPLAY_CTRL_SELECT_CRT (0x2 << 18) +#define CRT_DISPLAY_CTRL_FIFO_MASK (0x3 << 16) +#define CRT_DISPLAY_CTRL_FIFO_1 (0x0 << 16) +#define CRT_DISPLAY_CTRL_FIFO_3 (0x1 << 16) +#define CRT_DISPLAY_CTRL_FIFO_7 (0x2 << 16) +#define CRT_DISPLAY_CTRL_FIFO_11 (0x3 << 16) #define CRT_DISPLAY_CTRL_BLANK BIT(10) -#define CRT_DISPLAY_CTRL_PIXEL 7:4 -#define CRT_DISPLAY_CTRL_FORMAT 1:0 -#define CRT_DISPLAY_CTRL_FORMAT_8 0 -#define CRT_DISPLAY_CTRL_FORMAT_16 1 -#define CRT_DISPLAY_CTRL_FORMAT_32 2 +#define CRT_DISPLAY_CTRL_PIXEL_MASK (0xf << 4) +#define CRT_DISPLAY_CTRL_FORMAT_MASK (0x3 << 0) +#define CRT_DISPLAY_CTRL_FORMAT_8 (0x0 << 0) +#define CRT_DISPLAY_CTRL_FORMAT_16 (0x1 << 0) +#define CRT_DISPLAY_CTRL_FORMAT_32 (0x2 << 0) #define CRT_FB_ADDRESS 0x080204 #define CRT_FB_ADDRESS_STATUS 31:31 diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index ce08e6c13f03..2b1cb9a6fbe7 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -352,7 +352,8 @@ int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc, /* SET PIXEL FORMAT */ reg = PEEK32(CRT_DISPLAY_CTRL); - reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, FORMAT, var->bits_per_pixel >> 4); + reg |= ((var->bits_per_pixel >> 4) & + CRT_DISPLAY_CTRL_FORMAT_MASK); POKE32(CRT_DISPLAY_CTRL, reg); } @@ -403,7 +404,8 @@ int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank) if (output->paths & sm750_crt) { unsigned int val; - POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms)); + val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_DPMS_MASK; + POKE32(CRT_DISPLAY_CTRL, val | dpms); val = PEEK32(CRT_DISPLAY_CTRL) & ~CRT_DISPLAY_CTRL_BLANK; POKE32(CRT_DISPLAY_CTRL, val | crtdb); -- cgit From b71413e0d557684293a10fb1cd5747956ef42bd4 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:20 +0200 Subject: staging: sm750fb: use BIT macro for I2C_CTRL fields Replace complex definition of I2C_CTRL register fields with BIT() macro and use open-coded implementation for register manipulation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_hwi2c.c | 19 +++++++------------ drivers/staging/sm750fb/ddk750_reg.h | 20 +++++--------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 40253bd8cf2a..1811c4bd007f 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -26,12 +26,10 @@ unsigned char bus_speed_mode enableI2C(1); /* Enable the I2C Controller and set the bus speed mode */ - value = PEEK32(I2C_CTRL); - if (bus_speed_mode == 0) - value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD); - else - value = FIELD_SET(value, I2C_CTRL, MODE, FAST); - value = FIELD_SET(value, I2C_CTRL, EN, ENABLE); + value = PEEK32(I2C_CTRL) & ~(I2C_CTRL_MODE | I2C_CTRL_EN); + if (bus_speed_mode) + value |= I2C_CTRL_MODE; + value |= I2C_CTRL_EN; POKE32(I2C_CTRL, value); return 0; @@ -42,8 +40,7 @@ void sm750_hw_i2c_close(void) unsigned int value; /* Disable I2C controller */ - value = PEEK32(I2C_CTRL); - value = FIELD_SET(value, I2C_CTRL, EN, DISABLE); + value = PEEK32(I2C_CTRL) & ~I2C_CTRL_EN; POKE32(I2C_CTRL, value); /* Disable I2C Power */ @@ -120,8 +117,7 @@ static unsigned int hw_i2c_write_data( POKE32(I2C_DATA0 + i, *buf++); /* Start the I2C */ - POKE32(I2C_CTRL, - FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START)); + POKE32(I2C_CTRL, PEEK32(I2C_CTRL) | I2C_CTRL_CTRL); /* Wait until the transfer is completed. */ if (hw_i2c_wait_tx_done() != 0) @@ -183,8 +179,7 @@ static unsigned int hw_i2c_read_data( POKE32(I2C_BYTE_COUNT, count); /* Start the I2C */ - POKE32(I2C_CTRL, - FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START)); + POKE32(I2C_CTRL, PEEK32(I2C_CTRL) | I2C_CTRL_CTRL); /* Wait until transaction done. */ if (hw_i2c_wait_tx_done() != 0) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index d033d4ff0549..2a8ad57e6311 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -1605,21 +1605,11 @@ #define I2C_BYTE_COUNT_COUNT 3:0 #define I2C_CTRL 0x010041 -#define I2C_CTRL_INT 4:4 -#define I2C_CTRL_INT_DISABLE 0 -#define I2C_CTRL_INT_ENABLE 1 -#define I2C_CTRL_DIR 3:3 -#define I2C_CTRL_DIR_WR 0 -#define I2C_CTRL_DIR_RD 1 -#define I2C_CTRL_CTRL 2:2 -#define I2C_CTRL_CTRL_STOP 0 -#define I2C_CTRL_CTRL_START 1 -#define I2C_CTRL_MODE 1:1 -#define I2C_CTRL_MODE_STANDARD 0 -#define I2C_CTRL_MODE_FAST 1 -#define I2C_CTRL_EN 0:0 -#define I2C_CTRL_EN_DISABLE 0 -#define I2C_CTRL_EN_ENABLE 1 +#define I2C_CTRL_INT BIT(4) +#define I2C_CTRL_DIR BIT(3) +#define I2C_CTRL_CTRL BIT(2) +#define I2C_CTRL_MODE BIT(1) +#define I2C_CTRL_EN BIT(0) #define I2C_STATUS 0x010042 #define I2C_STATUS_TX 3:3 -- cgit From 3e155b813406fbb4aed1a54eecd24a90cf13dd96 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:21 +0200 Subject: staging: sm750fb: use BIT macro for I2C_STATUS fields Replace complex definition of I2C_STATUS register fields with BIT() macro and use open-coded implementation for register manipulation Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_hwi2c.c | 4 +--- drivers/staging/sm750fb/ddk750_reg.h | 18 ++++-------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c index 1811c4bd007f..231c02114ed4 100644 --- a/drivers/staging/sm750fb/ddk750_hwi2c.c +++ b/drivers/staging/sm750fb/ddk750_hwi2c.c @@ -59,9 +59,7 @@ static long hw_i2c_wait_tx_done(void) /* Wait until the transfer is completed. */ timeout = HWI2C_WAIT_TIMEOUT; - while ((FIELD_GET(PEEK32(I2C_STATUS), - I2C_STATUS, TX) != I2C_STATUS_TX_COMPLETED) && - (timeout != 0)) + while (!(PEEK32(I2C_STATUS) & I2C_STATUS_TX) && (timeout != 0)) timeout--; if (timeout == 0) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 2a8ad57e6311..63995995be14 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -1612,20 +1612,10 @@ #define I2C_CTRL_EN BIT(0) #define I2C_STATUS 0x010042 -#define I2C_STATUS_TX 3:3 -#define I2C_STATUS_TX_PROGRESS 0 -#define I2C_STATUS_TX_COMPLETED 1 -#define I2C_TX_DONE 0x08 -#define I2C_STATUS_ERR 2:2 -#define I2C_STATUS_ERR_NORMAL 0 -#define I2C_STATUS_ERR_ERROR 1 -#define I2C_STATUS_ERR_CLEAR 0 -#define I2C_STATUS_ACK 1:1 -#define I2C_STATUS_ACK_RECEIVED 0 -#define I2C_STATUS_ACK_NOT 1 -#define I2C_STATUS_BSY 0:0 -#define I2C_STATUS_BSY_IDLE 0 -#define I2C_STATUS_BSY_BUSY 1 +#define I2C_STATUS_TX BIT(3) +#define I2C_STATUS_ERR BIT(2) +#define I2C_STATUS_ACK BIT(1) +#define I2C_STATUS_BSY BIT(0) #define I2C_RESET 0x010042 #define I2C_RESET_BUS_ERROR 2:2 -- cgit From 60112069a9fce40025929d3ecd908c2f628ce931 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Wed, 10 Feb 2016 18:34:22 +0200 Subject: staging: sm750fb: change definition of PANEL_HORIZONTAL_TOTAL fields Use stratight-forward defintion of PANEL_HORIZONTAL_TOTAL register fields and use open-coded implementation for register manipulations Signed-off-by: Mike Rapoport Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_mode.c | 9 ++++++--- drivers/staging/sm750fb/ddk750_reg.h | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c index 9ec3c6481f8d..7e57b57598c9 100644 --- a/drivers/staging/sm750fb/ddk750_mode.c +++ b/drivers/staging/sm750fb/ddk750_mode.c @@ -122,9 +122,12 @@ static int programModeRegisters(mode_parameter_t *pModeParam, pll_value_t *pll) POKE32(PANEL_PLL_CTRL, formatPllReg(pll)); - POKE32(PANEL_HORIZONTAL_TOTAL, - FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1) - | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1)); + reg = ((pModeParam->horizontal_total - 1) << + PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT) & + PANEL_HORIZONTAL_TOTAL_TOTAL_MASK; + reg |= ((pModeParam->horizontal_display_end - 1) & + PANEL_HORIZONTAL_TOTAL_DISPLAY_END_MASK); + POKE32(PANEL_HORIZONTAL_TOTAL, reg); POKE32(PANEL_HORIZONTAL_SYNC, FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width) diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h index 63995995be14..47028974d042 100644 --- a/drivers/staging/sm750fb/ddk750_reg.h +++ b/drivers/staging/sm750fb/ddk750_reg.h @@ -858,8 +858,9 @@ #define PANEL_PLANE_BR_RIGHT_MASK 0xeff #define PANEL_HORIZONTAL_TOTAL 0x080024 -#define PANEL_HORIZONTAL_TOTAL_TOTAL 27:16 -#define PANEL_HORIZONTAL_TOTAL_DISPLAY_END 11:0 +#define PANEL_HORIZONTAL_TOTAL_TOTAL_SHIFT 16 +#define PANEL_HORIZONTAL_TOTAL_TOTAL_MASK (0xfff << 16) +#define PANEL_HORIZONTAL_TOTAL_DISPLAY_END_MASK 0xfff #define PANEL_HORIZONTAL_SYNC 0x080028 #define PANEL_HORIZONTAL_SYNC_WIDTH 23:16 -- cgit From e0246ea37406fe0e6c794567e721b26aa8f0c831 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Wed, 10 Feb 2016 17:56:06 +0800 Subject: staging: fbtft: Fix block comments according to kernel coding style Add the required trailing * on subsequent lines as well as move the */ on a separate line. Checkpatch found this issue. Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_hx8340bn.c | 82 ++++++++++++++++++++++--------------- drivers/staging/fbtft/fb_hx8347d.c | 8 ++-- drivers/staging/fbtft/fb_hx8353d.c | 18 ++++---- drivers/staging/fbtft/fb_hx8357d.h | 28 ++++++------- 4 files changed, 75 insertions(+), 61 deletions(-) diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c index ea680e56aec7..4dd77b8a5cac 100644 --- a/drivers/staging/fbtft/fb_hx8340bn.c +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -46,55 +46,69 @@ static int init_display(struct fbtft_par *par) /* BTL221722-276L startup sequence, from datasheet */ - /* SETEXTCOM: Set extended command set (C1h) - This command is used to set extended command set access enable. - Enable: After command (C1h), must write: ffh,83h,40h */ + /* + * SETEXTCOM: Set extended command set (C1h) + * This command is used to set extended command set access enable. + * Enable: After command (C1h), must write: ffh,83h,40h + */ write_reg(par, 0xC1, 0xFF, 0x83, 0x40); - /* Sleep out - This command turns off sleep mode. - In this mode the DC/DC converter is enabled, Internal oscillator - is started, and panel scanning is started. */ + /* + * Sleep out + * This command turns off sleep mode. + * In this mode the DC/DC converter is enabled, Internal oscillator + * is started, and panel scanning is started. + */ write_reg(par, 0x11); mdelay(150); /* Undoc'd register? */ write_reg(par, 0xCA, 0x70, 0x00, 0xD9); - /* SETOSC: Set Internal Oscillator (B0h) - This command is used to set internal oscillator related settings */ - /* OSC_EN: Enable internal oscillator */ - /* Internal oscillator frequency: 125% x 2.52MHz */ + /* + * SETOSC: Set Internal Oscillator (B0h) + * This command is used to set internal oscillator related settings + * OSC_EN: Enable internal oscillator + * Internal oscillator frequency: 125% x 2.52MHz + */ write_reg(par, 0xB0, 0x01, 0x11); /* Drive ability setting */ write_reg(par, 0xC9, 0x90, 0x49, 0x10, 0x28, 0x28, 0x10, 0x00, 0x06); mdelay(20); - /* SETPWCTR5: Set Power Control 5(B5h) - This command is used to set VCOM Low and VCOM High Voltage */ - /* VCOMH 0110101 : 3.925 */ - /* VCOML 0100000 : -1.700 */ - /* 45h=69 VCOMH: "VMH" + 5d VCOML: "VMH" + 5d */ + /* + * SETPWCTR5: Set Power Control 5(B5h) + * This command is used to set VCOM Low and VCOM High Voltage + * VCOMH 0110101 : 3.925 + * VCOML 0100000 : -1.700 + * 45h=69 VCOMH: "VMH" + 5d VCOML: "VMH" + 5d + */ write_reg(par, 0xB5, 0x35, 0x20, 0x45); - /* SETPWCTR4: Set Power Control 4(B4h) - VRH[4:0]: Specify the VREG1 voltage adjusting. - VREG1 voltage is for gamma voltage setting. - BT[2:0]: Switch the output factor of step-up circuit 2 - for VGH and VGL voltage generation. */ + /* + * SETPWCTR4: Set Power Control 4(B4h) + * VRH[4:0]: Specify the VREG1 voltage adjusting. + * VREG1 voltage is for gamma voltage setting. + * BT[2:0]: Switch the output factor of step-up circuit 2 + * for VGH and VGL voltage generation. + */ write_reg(par, 0xB4, 0x33, 0x25, 0x4C); mdelay(10); - /* Interface Pixel Format (3Ah) - This command is used to define the format of RGB picture data, - which is to be transfer via the system and RGB interface. */ - /* RGB interface: 16 Bit/Pixel */ + /* + * Interface Pixel Format (3Ah) + * This command is used to define the format of RGB picture data, + * which is to be transfer via the system and RGB interface. + * RGB interface: 16 Bit/Pixel + */ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); - /* Display on (29h) - This command is used to recover from DISPLAY OFF mode. - Output from the Frame Memory is enabled. */ + /* + * Display on (29h) + * This command is used to recover from DISPLAY OFF mode. + * Output from the Frame Memory is enabled. + */ write_reg(par, MIPI_DCS_SET_DISPLAY_ON); mdelay(10); @@ -137,12 +151,12 @@ static int set_var(struct fbtft_par *par) } /* - Gamma Curve selection, GC (only GC0 can be customized): - 0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0 - Gamma string format: - OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1 - ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC -*/ + * Gamma Curve selection, GC (only GC0 can be customized): + * 0 = 2.2, 1 = 1.8, 2 = 2.5, 3 = 1.0 + * Gamma string format: + * OP0 OP1 CP0 CP1 CP2 CP3 CP4 MP0 MP1 MP2 MP3 MP4 MP5 CGM0 CGM1 + * ON0 ON1 CN0 CN1 CN2 CN3 CN4 MN0 MN1 MN2 MN3 MN4 MN5 XXXX GC + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c index 6ff76e531a37..4e9a6b0ce6a2 100644 --- a/drivers/staging/fbtft/fb_hx8347d.c +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -97,10 +97,10 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) } /* - Gamma string format: - VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM - VRN0 VRN1 VRN2 VRN3 VRN4 VRN5 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 CGM -*/ + * Gamma string format: + * VRP0 VRP1 VRP2 VRP3 VRP4 VRP5 PRP0 PRP1 PKP0 PKP1 PKP2 PKP3 PKP4 CGM + * VRN0 VRN1 VRN2 VRN3 VRN4 VRN5 PRN0 PRN1 PKN0 PKN1 PKN2 PKN3 PKN4 CGM + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c index 064ae61a86b2..cd85faa85d74 100644 --- a/drivers/staging/fbtft/fb_hx8353d.c +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -88,12 +88,14 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) #define mv BIT(5) static int set_var(struct fbtft_par *par) { - /* madctl - memory data access control - rgb/bgr: - 1. mode selection pin srgb - rgb h/w pin for color filter setting: 0=rgb, 1=bgr - 2. madctl rgb bit - rgb-bgr order color filter panel: 0=rgb, 1=bgr */ + /* + * madctl - memory data access control + * rgb/bgr: + * 1. mode selection pin srgb + * rgb h/w pin for color filter setting: 0=rgb, 1=bgr + * 2. madctl rgb bit + * rgb-bgr order color filter panel: 0=rgb, 1=bgr + */ switch (par->info->var.rotate) { case 0: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, @@ -116,9 +118,7 @@ static int set_var(struct fbtft_par *par) return 0; } -/* - gamma string format: -*/ +/* gamma string format: */ static int set_gamma(struct fbtft_par *par, unsigned long *curves) { write_reg(par, 0xE0, diff --git a/drivers/staging/fbtft/fb_hx8357d.h b/drivers/staging/fbtft/fb_hx8357d.h index 2b014ebbf81c..e281921d4a97 100644 --- a/drivers/staging/fbtft/fb_hx8357d.h +++ b/drivers/staging/fbtft/fb_hx8357d.h @@ -1,17 +1,17 @@ -/*************************************************** - This is our library for the Adafruit ILI9341 Breakout and Shield - ----> http://www.adafruit.com/products/1651 - - Check out the links above for our tutorials and wiring diagrams - These displays use SPI to communicate, 4 or 5 pins are required to - interface (RST is optional) - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! - - Written by Limor Fried/Ladyada for Adafruit Industries. - MIT license, all text above must be included in any redistribution - ****************************************************/ +/* + * This is our library for the Adafruit ILI9341 Breakout and Shield + * ----> http://www.adafruit.com/products/1651 + * + * Check out the links above for our tutorials and wiring diagrams + * These displays use SPI to communicate, 4 or 5 pins are required to + * interface (RST is optional) + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Written by Limor Fried/Ladyada for Adafruit Industries. + * MIT license, all text above must be included in any redistribution + */ #ifndef __HX8357_H__ #define __HX8357_H__ -- cgit From 5f10ef7dce02d8e36665974aca0977cda58c1122 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Wed, 10 Feb 2016 17:56:07 +0800 Subject: staging: fbtft: Indent to match open parenthesis Fix alignment issues by properly indenting function parameters in accordance to the kernel coding style. Checkpatch pointed out this issue. CHECK: Alignment should match open parenthesis Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_hx8340bn.c | 34 ++++++------ drivers/staging/fbtft/fb_hx8353d.c | 12 ++-- drivers/staging/fbtft/fb_hx8357d.c | 106 ++++++++++++++++++------------------ 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c index 4dd77b8a5cac..4ec2dc78baad 100644 --- a/drivers/staging/fbtft/fb_hx8340bn.c +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -179,25 +179,25 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) return 0; /* only GC0 can be customized */ write_reg(par, 0xC2, - (CURVE(0, 8) << 4) | CURVE(0, 7), - (CURVE(0, 10) << 4) | CURVE(0, 9), - (CURVE(0, 12) << 4) | CURVE(0, 11), - CURVE(0, 2), - (CURVE(0, 4) << 4) | CURVE(0, 3), - CURVE(0, 5), - CURVE(0, 6), - (CURVE(0, 1) << 4) | CURVE(0, 0), - (CURVE(0, 14) << 2) | CURVE(0, 13)); + (CURVE(0, 8) << 4) | CURVE(0, 7), + (CURVE(0, 10) << 4) | CURVE(0, 9), + (CURVE(0, 12) << 4) | CURVE(0, 11), + CURVE(0, 2), + (CURVE(0, 4) << 4) | CURVE(0, 3), + CURVE(0, 5), + CURVE(0, 6), + (CURVE(0, 1) << 4) | CURVE(0, 0), + (CURVE(0, 14) << 2) | CURVE(0, 13)); write_reg(par, 0xC3, - (CURVE(1, 8) << 4) | CURVE(1, 7), - (CURVE(1, 10) << 4) | CURVE(1, 9), - (CURVE(1, 12) << 4) | CURVE(1, 11), - CURVE(1, 2), - (CURVE(1, 4) << 4) | CURVE(1, 3), - CURVE(1, 5), - CURVE(1, 6), - (CURVE(1, 1) << 4) | CURVE(1, 0)); + (CURVE(1, 8) << 4) | CURVE(1, 7), + (CURVE(1, 10) << 4) | CURVE(1, 9), + (CURVE(1, 12) << 4) | CURVE(1, 11), + CURVE(1, 2), + (CURVE(1, 4) << 4) | CURVE(1, 3), + CURVE(1, 5), + CURVE(1, 6), + (CURVE(1, 1) << 4) | CURVE(1, 0)); mdelay(10); diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c index cd85faa85d74..286ae45e8930 100644 --- a/drivers/staging/fbtft/fb_hx8353d.c +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -59,7 +59,7 @@ static int init_display(struct fbtft_par *par) /* RGBSET */ write_reg(par, MIPI_DCS_WRITE_LUT, - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 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, @@ -122,11 +122,11 @@ static int set_var(struct fbtft_par *par) static int set_gamma(struct fbtft_par *par, unsigned long *curves) { write_reg(par, 0xE0, - curves[0], curves[1], curves[2], curves[3], - curves[4], curves[5], curves[6], curves[7], - curves[8], curves[9], curves[10], curves[11], - curves[12], curves[13], curves[14], curves[15], - curves[16], curves[17], curves[18]); + curves[0], curves[1], curves[2], curves[3], + curves[4], curves[5], curves[6], curves[7], + curves[8], curves[9], curves[10], curves[11], + curves[12], curves[13], curves[14], curves[15], + curves[16], curves[17], curves[18]); return 0; } diff --git a/drivers/staging/fbtft/fb_hx8357d.c b/drivers/staging/fbtft/fb_hx8357d.c index 89be9ec2e347..32e6efe1d0a7 100644 --- a/drivers/staging/fbtft/fb_hx8357d.c +++ b/drivers/staging/fbtft/fb_hx8357d.c @@ -56,65 +56,65 @@ static int init_display(struct fbtft_par *par) write_reg(par, HX8357_SETPANEL, 0x05); write_reg(par, HX8357_SETPWR1, - 0x00, /* Not deep standby */ - 0x15, /* BT */ - 0x1C, /* VSPR */ - 0x1C, /* VSNR */ - 0x83, /* AP */ - 0xAA); /* FS */ + 0x00, /* Not deep standby */ + 0x15, /* BT */ + 0x1C, /* VSPR */ + 0x1C, /* VSNR */ + 0x83, /* AP */ + 0xAA); /* FS */ write_reg(par, HX8357D_SETSTBA, - 0x50, /* OPON normal */ - 0x50, /* OPON idle */ - 0x01, /* STBA */ - 0x3C, /* STBA */ - 0x1E, /* STBA */ - 0x08); /* GEN */ + 0x50, /* OPON normal */ + 0x50, /* OPON idle */ + 0x01, /* STBA */ + 0x3C, /* STBA */ + 0x1E, /* STBA */ + 0x08); /* GEN */ write_reg(par, HX8357D_SETCYC, - 0x02, /* NW 0x02 */ - 0x40, /* RTN */ - 0x00, /* DIV */ - 0x2A, /* DUM */ - 0x2A, /* DUM */ - 0x0D, /* GDON */ - 0x78); /* GDOFF */ + 0x02, /* NW 0x02 */ + 0x40, /* RTN */ + 0x00, /* DIV */ + 0x2A, /* DUM */ + 0x2A, /* DUM */ + 0x0D, /* GDON */ + 0x78); /* GDOFF */ write_reg(par, HX8357D_SETGAMMA, - 0x02, - 0x0A, - 0x11, - 0x1d, - 0x23, - 0x35, - 0x41, - 0x4b, - 0x4b, - 0x42, - 0x3A, - 0x27, - 0x1B, - 0x08, - 0x09, - 0x03, - 0x02, - 0x0A, - 0x11, - 0x1d, - 0x23, - 0x35, - 0x41, - 0x4b, - 0x4b, - 0x42, - 0x3A, - 0x27, - 0x1B, - 0x08, - 0x09, - 0x03, - 0x00, - 0x01); + 0x02, + 0x0A, + 0x11, + 0x1d, + 0x23, + 0x35, + 0x41, + 0x4b, + 0x4b, + 0x42, + 0x3A, + 0x27, + 0x1B, + 0x08, + 0x09, + 0x03, + 0x02, + 0x0A, + 0x11, + 0x1d, + 0x23, + 0x35, + 0x41, + 0x4b, + 0x4b, + 0x42, + 0x3A, + 0x27, + 0x1B, + 0x08, + 0x09, + 0x03, + 0x00, + 0x01); /* 16 bit */ write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55); -- cgit From b15cd7e8097a3da9c11a45ce21c457bd37c67285 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Wed, 10 Feb 2016 17:56:08 +0800 Subject: staging: fbtft: Add blank line after function declaration Insert the required whitespace after the function declaration as suggested by checkpatch. 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/fbtft/fb_hx8340bn.c | 1 + drivers/staging/fbtft/fb_hx8347d.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/staging/fbtft/fb_hx8340bn.c b/drivers/staging/fbtft/fb_hx8340bn.c index 4ec2dc78baad..9970ed74bb38 100644 --- a/drivers/staging/fbtft/fb_hx8340bn.c +++ b/drivers/staging/fbtft/fb_hx8340bn.c @@ -203,6 +203,7 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) return 0; } + #undef CURVE static struct fbtft_display display = { diff --git a/drivers/staging/fbtft/fb_hx8347d.c b/drivers/staging/fbtft/fb_hx8347d.c index 4e9a6b0ce6a2..450a61e3f99c 100644 --- a/drivers/staging/fbtft/fb_hx8347d.c +++ b/drivers/staging/fbtft/fb_hx8347d.c @@ -140,6 +140,7 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) return 0; } + #undef CURVE static struct fbtft_display display = { -- cgit From faad1a6cba1e04ce062ee2cbc65049d352ab967e Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Wed, 10 Feb 2016 17:56:09 +0800 Subject: staging: fbtft: Remove blank line after '{' brace Omit the whitespace after '{' brace as suggested by checkpatch. CHECK: Blank lines aren't necessary after an open brace '{' Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_hx8353d.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/fbtft/fb_hx8353d.c b/drivers/staging/fbtft/fb_hx8353d.c index 286ae45e8930..72e4ff8c5553 100644 --- a/drivers/staging/fbtft/fb_hx8353d.c +++ b/drivers/staging/fbtft/fb_hx8353d.c @@ -28,7 +28,6 @@ static int init_display(struct fbtft_par *par) { - par->fbtftops.reset(par); mdelay(150); -- cgit From b3d0ea8d8078ee0e1ffc751c17c33fc3589b9446 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 19:48:25 -0500 Subject: staging: speakup: Eliminate commented out code This patch removes commented out code as it contributes to code clutter. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/serialio.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c index a5bbb338f275..361545770120 100644 --- a/drivers/staging/speakup/serialio.c +++ b/drivers/staging/speakup/serialio.c @@ -92,8 +92,6 @@ const struct old_serial_port *spk_serial_init(int index) static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) { unsigned long flags; -/*printk(KERN_ERR "in irq\n"); */ -/*pr_warn("in IRQ\n"); */ int c; spin_lock_irqsave(&speakup_info.spinlock, flags); @@ -101,8 +99,6 @@ static irqreturn_t synth_readbuf_handler(int irq, void *dev_id) c = inb_p(speakup_info.port_tts+UART_RX); synth->read_buff_add((u_char) c); -/*printk(KERN_ERR "c = %d\n", c); */ -/*pr_warn("C = %d\n", c); */ } spin_unlock_irqrestore(&speakup_info.spinlock, flags); return IRQ_HANDLED; @@ -175,9 +171,6 @@ int spk_wait_for_xmitr(void) while (!((inb_p(speakup_info.port_tts + UART_MSR)) & UART_MSR_CTS)) { /* CTS */ if (--tmout == 0) { - /* pr_warn("%s: timed out (cts)\n", - * synth->long_name); - */ timeouts++; return 0; } -- cgit From 5a41b934766a00764669922f1faac1fbdcc179bd Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 10 Feb 2016 10:57:31 -0800 Subject: staging: speakup: compress return logic into one line Simplify function return by merging assignment and return into one command line. Remove (now) unused local variable. Found using Coccinelle: @@ expression e, ret; @@ -ret = +return e; -return ret; Signed-off-by: Alison Schofield Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/i18n.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/staging/speakup/i18n.c b/drivers/staging/speakup/i18n.c index 12f880ed4ddf..8960079e4d60 100644 --- a/drivers/staging/speakup/i18n.c +++ b/drivers/staging/speakup/i18n.c @@ -393,10 +393,7 @@ static const int num_groups = ARRAY_SIZE(all_groups); char *spk_msg_get(enum msg_index_t index) { - char *ch; - - ch = speakup_msgs[index]; - return ch; + return speakup_msgs[index]; } /* -- cgit From 474be12de61c60503ee6164b65afd5608e60b80c Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 10 Feb 2016 10:34:00 -0800 Subject: staging: gdm72xx: compress return logic into one line Simplify function returns by merging assignment and return into one command line. Found with Coccinelle @@ expression e, ret; @@ -ret = +return e; -return ret; Signed-off-by: Alison Schofield Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm72xx/netlink_k.c | 3 +-- drivers/staging/gdm72xx/usb_boot.c | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/staging/gdm72xx/netlink_k.c b/drivers/staging/gdm72xx/netlink_k.c index b7e5e706d37a..cf0b47cb1ceb 100644 --- a/drivers/staging/gdm72xx/netlink_k.c +++ b/drivers/staging/gdm72xx/netlink_k.c @@ -151,6 +151,5 @@ int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len) pr_err("netlink_broadcast g=%d, t=%d, l=%d, r=%d\n", group, type, len, ret); } - ret = 0; - return ret; + return 0; } diff --git a/drivers/staging/gdm72xx/usb_boot.c b/drivers/staging/gdm72xx/usb_boot.c index 39ca34031a6b..30829875da2e 100644 --- a/drivers/staging/gdm72xx/usb_boot.c +++ b/drivers/staging/gdm72xx/usb_boot.c @@ -357,7 +357,5 @@ int usb_emergency(struct usb_device *usbdev) return ret; dev_info(&usbdev->dev, "GCT Emergency: Filesystem download success.\n"); - ret = em_fw_reset(usbdev); - - return ret; + return em_fw_reset(usbdev); } -- cgit From e3b07865f5f6962d83e8b94d2968a9cfab7bdce5 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 17:01:01 -0500 Subject: staging: gdm724x: Remove unneeded parentheses Remove parentheses around the right hand side of assignment statements as they are not needed. Semantic patch: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_lte.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 17d148f6e02c..98570c61d4de 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -382,7 +382,7 @@ static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb) /* Check DHCPv4 */ if (ip->protocol == IPPROTO_UDP) { struct udphdr *udp = - (network_data + sizeof(struct iphdr)); + network_data + sizeof(struct iphdr); if (ntohs(udp->dest) == 67 || ntohs(udp->dest) == 68) nic_type |= NIC_TYPE_F_DHCP; } @@ -393,12 +393,12 @@ static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb) if (ipv6->nexthdr == IPPROTO_ICMPV6) /* Check NDP request */ { struct icmp6hdr *icmp6 = - (network_data + sizeof(struct ipv6hdr)); + network_data + sizeof(struct ipv6hdr); if (icmp6->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) nic_type |= NIC_TYPE_ICMPV6; } else if (ipv6->nexthdr == IPPROTO_UDP) /* Check DHCPv6 */ { struct udphdr *udp = - (network_data + sizeof(struct ipv6hdr)); + network_data + sizeof(struct ipv6hdr); if (ntohs(udp->dest) == 546 || ntohs(udp->dest) == 547) nic_type |= NIC_TYPE_F_DHCP; } -- cgit From 27f31cf9f7235cb3aa10860bf4fde5df6893bf52 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Wed, 10 Feb 2016 23:06:45 -0800 Subject: staging: vt6656: replace explicit NULL comparison with ! operator Replace explicit NULL comparison with ! operator to simplify code. Found with Coccinelle: @@ expression e; statement s0, s1; @@ if ( ( + ! e - == NULL || ... ) ) s0 else s1 Signed-off-by: Alison Schofield Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/main_usb.c | 10 +++++----- drivers/staging/vt6656/usbpipe.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index a2f23aefb35d..05f86ff8875c 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -431,7 +431,7 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) for (ii = 0; ii < priv->num_tx_context; ii++) { tx_context = kmalloc(sizeof(struct vnt_usb_send_context), GFP_KERNEL); - if (tx_context == NULL) + if (!tx_context) goto free_tx; priv->tx_context[ii] = tx_context; @@ -462,13 +462,13 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) /* allocate URBs */ rcb->urb = usb_alloc_urb(0, GFP_ATOMIC); - if (rcb->urb == NULL) { + if (!rcb->urb) { dev_err(&priv->usb->dev, "Failed to alloc rx urb\n"); goto free_rx_tx; } rcb->skb = dev_alloc_skb(priv->rx_buf_sz); - if (rcb->skb == NULL) + if (!rcb->skb) goto free_rx_tx; rcb->in_use = false; @@ -479,13 +479,13 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) } priv->interrupt_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (priv->interrupt_urb == NULL) { + if (!priv->interrupt_urb) { dev_err(&priv->usb->dev, "Failed to alloc int urb\n"); goto free_rx_tx; } priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL); - if (priv->int_buf.data_buf == NULL) { + if (!priv->int_buf.data_buf) { usb_free_urb(priv->interrupt_urb); goto free_rx_tx; } diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 351a99f3d684..bec5bafaca3c 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -210,7 +210,7 @@ int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb) struct urb *urb; urb = rcb->urb; - if (rcb->skb == NULL) { + if (!rcb->skb) { dev_dbg(&priv->usb->dev, "rcb->skb is null\n"); return status; } -- cgit From 2fbf6d61664ba04d4c7872cbb46720e49264cf3a Mon Sep 17 00:00:00 2001 From: Haneen Mohammed Date: Thu, 11 Feb 2016 21:34:40 +0300 Subject: Staging: vt6655: Add check dma_mapping_error This patch checks for dma_mapping_error() after using dma_map_single. If the dma map fails we release skb buff allocated by dev_alloc_skb() to avoid possible causes of resource leak. Signed-off-by: Haneen Mohammed Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/device_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c index ad0fb84e5096..8a1ed62e2f57 100644 --- a/drivers/staging/vt6655/device_main.c +++ b/drivers/staging/vt6655/device_main.c @@ -742,6 +742,11 @@ static bool device_alloc_rx_buf(struct vnt_private *priv, dma_map_single(&priv->pcid->dev, skb_put(rd_info->skb, skb_tailroom(rd_info->skb)), priv->rx_buf_sz, DMA_FROM_DEVICE); + if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) { + dev_kfree_skb(rd_info->skb); + rd_info->skb = NULL; + return false; + } *((unsigned int *)&rd->rd0) = 0; /* FIX cast */ -- cgit From 993c0a0ea0062e24fb96f579d1b655b15f3c9dfa Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 18:50:40 -0500 Subject: staging: rtl8723au: Use ARRAY_SIZE macro for sizes of arrays Use ARRAY_SIZE to calculate the size of an array to make code concise. The semantic patch used can be found here: https://github.com/coccinelle/coccinellery/commit/9cbab452a3a2e18439e8386d6c4a68ee42c3ee2b Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/core/rtw_cmd.c | 3 +-- drivers/staging/rtl8723au/core/rtw_mlme_ext.c | 3 +-- drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c | 6 +++--- drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/staging/rtl8723au/core/rtw_cmd.c b/drivers/staging/rtl8723au/core/rtw_cmd.c index 3035bb864c39..cd4e0f05d82f 100644 --- a/drivers/staging/rtl8723au/core/rtw_cmd.c +++ b/drivers/staging/rtl8723au/core/rtw_cmd.c @@ -295,8 +295,7 @@ static void rtw_cmd_work(struct work_struct *work) post_process: /* call callback function for post-processed */ - if (pcmd->cmdcode < (sizeof(rtw_cmd_callback) / - sizeof(struct _cmd_callback))) { + if (pcmd->cmdcode < ARRAY_SIZE(rtw_cmd_callback)) { pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback; if (!pcmd_callback) { RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c index 7cd005215e7e..a39e441ee365 100644 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c @@ -2154,8 +2154,7 @@ OnAction23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame) category = mgmt->u.action.category; - for (i = 0; - i < sizeof(OnAction23a_tbl) / sizeof(struct action_handler); i++) { + for (i = 0; i < ARRAY_SIZE(OnAction23a_tbl); i++) { ptable = &OnAction23a_tbl[i]; if (category == ptable->num) diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c index e8cab9e97385..8d3ea6c0cbe6 100644 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c +++ b/drivers/staging/rtl8723au/hal/HalHWImg8723A_BB.c @@ -219,7 +219,7 @@ void ODM_ReadAndConfig_AGC_TAB_1T_8723A(struct dm_odm_t *pDM_Odm) u32 i; u8 platform = 0x04; u8 board = pDM_Odm->BoardType; - u32 ArrayLen = sizeof(Array_AGC_TAB_1T_8723A)/sizeof(u32); + u32 ArrayLen = ARRAY_SIZE(Array_AGC_TAB_1T_8723A); u32 *Array = Array_AGC_TAB_1T_8723A; hex = board; @@ -467,7 +467,7 @@ void ODM_ReadAndConfig_PHY_REG_1T_8723A(struct dm_odm_t *pDM_Odm) u32 i = 0; u8 platform = 0x04; u8 board = pDM_Odm->BoardType; - u32 ArrayLen = sizeof(Array_PHY_REG_1T_8723A)/sizeof(u32); + u32 ArrayLen = ARRAY_SIZE(Array_PHY_REG_1T_8723A); u32 *Array = Array_PHY_REG_1T_8723A; hex += board; @@ -523,7 +523,7 @@ void ODM_ReadAndConfig_PHY_REG_MP_8723A(struct dm_odm_t *pDM_Odm) u32 i; u8 platform = 0x04; u8 board = pDM_Odm->BoardType; - u32 ArrayLen = sizeof(Array_PHY_REG_MP_8723A)/sizeof(u32); + u32 ArrayLen = ARRAY_SIZE(Array_PHY_REG_MP_8723A); u32 *Array = Array_PHY_REG_MP_8723A; hex += board; diff --git a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c b/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c index 93b2d183d694..9bf685905e68 100644 --- a/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c +++ b/drivers/staging/rtl8723au/hal/HalHWImg8723A_MAC.c @@ -145,7 +145,7 @@ void ODM_ReadAndConfig_MAC_REG_8723A(struct dm_odm_t *pDM_Odm) u32 i = 0; u8 platform = 0x04; u8 board = pDM_Odm->BoardType; - u32 ArrayLen = sizeof(Array_MAC_REG_8723A)/sizeof(u32); + u32 ArrayLen = ARRAY_SIZE(Array_MAC_REG_8723A); u32 *Array = Array_MAC_REG_8723A; hex += board; -- cgit From 139737983db450b956930134eee755d36782c986 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Tue, 9 Feb 2016 13:07:29 -0500 Subject: staging: rtl8188eu: Remove unnecessary pointer cast Remove unnecessary pointer cast. Issue found using the following Coccinelle semantic patch. @@ type T; T e; identifier x; @@ * T x = (T)e; Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_mlme_ext.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c index e6020265d6de..96e5c6dc5b7c 100644 --- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c @@ -3652,7 +3652,7 @@ static unsigned int on_action_spct(struct adapter *padapter, struct sta_info *psta = NULL; struct sta_priv *pstapriv = &padapter->stapriv; u8 *pframe = precv_frame->rx_data; - u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr)); + u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr); u8 category; u8 action; -- cgit From f643ba69d12e31053a112ef3bfa9ead45bb71e37 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Fri, 12 Feb 2016 01:23:15 +0700 Subject: staging: rtl8188eu: remove _rtl88e_fill_dummy The _rtl88e_fill_dummy function replaced by memset in rtl88eu_download_fw. More appropriate names are used for pfwdata and fwsize variables (download_data and download_size respectively). Also u32 replaced by size_t for download_size variable. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/fw.c | 45 +++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c index 4d72537644b3..25cecaeefa51 100644 --- a/drivers/staging/rtl8188eu/hal/fw.c +++ b/drivers/staging/rtl8188eu/hal/fw.c @@ -75,16 +75,6 @@ static void _rtl88e_fw_block_write(struct adapter *adapt, usb_write8(adapt, write_address, byte_buffer[i]); } -static void _rtl88e_fill_dummy(u8 *pfwbuf, u32 *pfwlen) -{ - u32 i; - - for (i = *pfwlen; i < roundup(*pfwlen, 4); i++) - pfwbuf[i] = 0; - - *pfwlen = i; -} - static void _rtl88e_fw_page_write(struct adapter *adapt, u32 page, const u8 *buffer, u32 size) { @@ -103,8 +93,6 @@ static void _rtl88e_write_fw(struct adapter *adapt, u8 *buffer, u32 size) u32 page_no, remain; u32 page, offset; - _rtl88e_fill_dummy(buf_ptr, &size); - page_no = size / FW_8192C_PAGE_SIZE; remain = size % FW_8192C_PAGE_SIZE; @@ -176,8 +164,9 @@ int rtl88eu_download_fw(struct adapter *adapt) const struct firmware *fw; const char fw_name[] = "rtlwifi/rtl8188eufw.bin"; struct rtl92c_firmware_header *pfwheader = NULL; - u8 *pfwdata; - u32 fwsize; + u8 *download_data; + size_t download_size; + unsigned int trailing_zeros_length; if (request_firmware(&fw, fw_name, device)) { dev_err(device, "Firmware %s not available\n", fw_name); @@ -186,34 +175,40 @@ int rtl88eu_download_fw(struct adapter *adapt) if (fw->size > FW_8188E_SIZE) { dev_err(device, "Firmware size exceed 0x%X. Check it.\n", - FW_8188E_SIZE); + FW_8188E_SIZE); return -1; } - pfwdata = kzalloc(FW_8188E_SIZE, GFP_KERNEL); - if (!pfwdata) + trailing_zeros_length = (4 - fw->size % 4) % 4; + + rtlhal->fwsize = fw->size; + rtlhal->pfirmware = kmalloc(fw->size + trailing_zeros_length, + GFP_KERNEL); + if (!rtlhal->pfirmware) return -ENOMEM; - rtlhal->pfirmware = pfwdata; memcpy(rtlhal->pfirmware, fw->data, fw->size); - rtlhal->fwsize = fw->size; - release_firmware(fw); + memset(rtlhal->pfirmware + fw->size, 0, trailing_zeros_length); - fwsize = rtlhal->fwsize; - pfwheader = (struct rtl92c_firmware_header *)pfwdata; + pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; if (IS_FW_HEADER_EXIST(pfwheader)) { - pfwdata = pfwdata + 32; - fwsize = fwsize - 32; + download_data = rtlhal->pfirmware + 32; + download_size = fw->size + trailing_zeros_length - 32; + } else { + download_data = rtlhal->pfirmware; + download_size = fw->size + trailing_zeros_length; } + release_firmware(fw); + if (usb_read8(adapt, REG_MCUFWDL) & RAM_DL_SEL) { usb_write8(adapt, REG_MCUFWDL, 0); rtl88e_firmware_selfreset(adapt); } _rtl88e_enable_fw_download(adapt, true); usb_write8(adapt, REG_MCUFWDL, usb_read8(adapt, REG_MCUFWDL) | FWDL_ChkSum_rpt); - _rtl88e_write_fw(adapt, pfwdata, fwsize); + _rtl88e_write_fw(adapt, download_data, download_size); _rtl88e_enable_fw_download(adapt, false); return _rtl88e_fw_free_to_go(adapt); -- cgit From 29e20dd4c736a1f8a02d542359ba7a4e28440b73 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Fri, 12 Feb 2016 01:24:22 +0700 Subject: staging: rtl8188eu: remove pfirmware and fwsize of the hal_data_8188e structure The pfirmware is used only in rtl88eu_download_fw function (except the kfree(rtlhal->pfirmware) in netdev_close). The fwsize not used after initialization at all. The pfirmvare replaced by fw_data and fwsize removed. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/fw.c | 20 +++++++++----------- drivers/staging/rtl8188eu/include/rtl8188e_hal.h | 2 -- drivers/staging/rtl8188eu/os_dep/os_intfs.c | 4 ---- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c index 25cecaeefa51..55c17df0e839 100644 --- a/drivers/staging/rtl8188eu/hal/fw.c +++ b/drivers/staging/rtl8188eu/hal/fw.c @@ -158,13 +158,12 @@ exit: int rtl88eu_download_fw(struct adapter *adapt) { - struct hal_data_8188e *rtlhal = GET_HAL_DATA(adapt); struct dvobj_priv *dvobj = adapter_to_dvobj(adapt); struct device *device = dvobj_to_dev(dvobj); const struct firmware *fw; const char fw_name[] = "rtlwifi/rtl8188eufw.bin"; struct rtl92c_firmware_header *pfwheader = NULL; - u8 *download_data; + u8 *download_data, *fw_data; size_t download_size; unsigned int trailing_zeros_length; @@ -181,22 +180,20 @@ int rtl88eu_download_fw(struct adapter *adapt) trailing_zeros_length = (4 - fw->size % 4) % 4; - rtlhal->fwsize = fw->size; - rtlhal->pfirmware = kmalloc(fw->size + trailing_zeros_length, - GFP_KERNEL); - if (!rtlhal->pfirmware) + fw_data = kmalloc(fw->size + trailing_zeros_length, GFP_KERNEL); + if (!fw_data) return -ENOMEM; - memcpy(rtlhal->pfirmware, fw->data, fw->size); - memset(rtlhal->pfirmware + fw->size, 0, trailing_zeros_length); + memcpy(fw_data, fw->data, fw->size); + memset(fw_data + fw->size, 0, trailing_zeros_length); - pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; + pfwheader = (struct rtl92c_firmware_header *)fw_data; if (IS_FW_HEADER_EXIST(pfwheader)) { - download_data = rtlhal->pfirmware + 32; + download_data = fw_data + 32; download_size = fw->size + trailing_zeros_length - 32; } else { - download_data = rtlhal->pfirmware; + download_data = fw_data; download_size = fw->size + trailing_zeros_length; } @@ -211,5 +208,6 @@ int rtl88eu_download_fw(struct adapter *adapt) _rtl88e_write_fw(adapt, download_data, download_size); _rtl88e_enable_fw_download(adapt, false); + kfree(fw_data); return _rtl88e_fw_free_to_go(adapt); } diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h index cbad364f189c..9f5050e6f6ab 100644 --- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h +++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h @@ -191,8 +191,6 @@ struct txpowerinfo24g { struct hal_data_8188e { struct HAL_VERSION VersionID; u16 CustomerID; - u8 *pfirmware; - u32 fwsize; u16 FirmwareVersion; u16 FirmwareVersionRev; u16 FirmwareSubVersion; diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c index 3b25acf882a3..7986e678521a 100644 --- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c +++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c @@ -1155,7 +1155,6 @@ int pm_netdev_open(struct net_device *pnetdev, u8 bnormal) static int netdev_close(struct net_device *pnetdev) { struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); - struct hal_data_8188e *rtlhal = GET_HAL_DATA(padapter); RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+88eu_drv - drv_close\n")); @@ -1188,9 +1187,6 @@ static int netdev_close(struct net_device *pnetdev) rtw_led_control(padapter, LED_CTL_POWER_OFF); } - kfree(rtlhal->pfirmware); - rtlhal->pfirmware = NULL; - RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-88eu_drv - drv_close\n")); DBG_88E("-88eu_drv - drv_close, bup =%d\n", padapter->bup); return 0; -- cgit From 8b0187188a423daa741cc544205c224c1ff84c33 Mon Sep 17 00:00:00 2001 From: Ivan Safonov Date: Fri, 12 Feb 2016 01:25:30 +0700 Subject: staging: rtl8188eu: add release_firmware() between request_firmware and function error exit Small memory leak fixed. Signed-off-by: Ivan Safonov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/hal/fw.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8188eu/hal/fw.c b/drivers/staging/rtl8188eu/hal/fw.c index 55c17df0e839..656133c47426 100644 --- a/drivers/staging/rtl8188eu/hal/fw.c +++ b/drivers/staging/rtl8188eu/hal/fw.c @@ -175,14 +175,17 @@ int rtl88eu_download_fw(struct adapter *adapt) if (fw->size > FW_8188E_SIZE) { dev_err(device, "Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE); + release_firmware(fw); return -1; } trailing_zeros_length = (4 - fw->size % 4) % 4; fw_data = kmalloc(fw->size + trailing_zeros_length, GFP_KERNEL); - if (!fw_data) + if (!fw_data) { + release_firmware(fw); return -ENOMEM; + } memcpy(fw_data, fw->data, fw->size); memset(fw_data + fw->size, 0, trailing_zeros_length); -- cgit From d9b36d5225d8e9b1f055c328283632773858dd7f Mon Sep 17 00:00:00 2001 From: Andrew Bradford Date: Thu, 11 Feb 2016 20:38:05 -0500 Subject: staging: rtl8188eu: fix signal strength indication RTL8188E can only have a maximum of 2 chains so match that in the actual phy_rx_agc_info structure within phy_status_rpt. This will cause the other data received from the PHY, such as signal strength indication of beacons, to properly align and allow extraction and use within the signal strength record-keeping mechanisms. Signed-off-by: Andrew Bradford Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h | 2 +- drivers/staging/rtl8188eu/include/odm_HWConfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h index e058162fe2ba..b8833faba8ee 100644 --- a/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h +++ b/drivers/staging/rtl8188eu/include/Hal8188EPhyCfg.h @@ -75,7 +75,7 @@ enum rf_radio_path { #define MAX_PG_GROUP 13 -#define RF_PATH_MAX 3 +#define RF_PATH_MAX 2 #define MAX_RF_PATH RF_PATH_MAX #define MAX_TX_COUNT 4 /* path numbers */ diff --git a/drivers/staging/rtl8188eu/include/odm_HWConfig.h b/drivers/staging/rtl8188eu/include/odm_HWConfig.h index 62a00498e473..ef792bfd535e 100644 --- a/drivers/staging/rtl8188eu/include/odm_HWConfig.h +++ b/drivers/staging/rtl8188eu/include/odm_HWConfig.h @@ -69,7 +69,7 @@ struct phy_rx_agc_info { }; struct phy_status_rpt { - struct phy_rx_agc_info path_agc[3]; + struct phy_rx_agc_info path_agc[RF_PATH_MAX]; u8 ch_corr[2]; u8 cck_sig_qual_ofdm_pwdb_all; u8 cck_agc_rpt_ofdm_cfosho_a; -- cgit From 686f0c2301a762cf0fc73bd0cfaf62473ddc76d6 Mon Sep 17 00:00:00 2001 From: Hari Prasath Gujulan Elango Date: Mon, 8 Feb 2016 04:44:13 +0000 Subject: staging: rtl8192e: prefer using eth_broadcast_addr() Prefer using the eth_broadcast_addr() instead of memset to broadcast address 0xFF to the array. Signed-off-by: Hari Prasath Gujulan Elango Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_softmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c index acccf9b44b98..19c3bffef73c 100644 --- a/drivers/staging/rtl8192e/rtllib_softmac.c +++ b/drivers/staging/rtl8192e/rtllib_softmac.c @@ -355,9 +355,9 @@ static inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) req->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_REQ); req->header.duration_id = 0; - memset(req->header.addr1, 0xff, ETH_ALEN); + eth_broadcast_addr(req->header.addr1); ether_addr_copy(req->header.addr2, ieee->dev->dev_addr); - memset(req->header.addr3, 0xff, ETH_ALEN); + eth_broadcast_addr(req->header.addr3); tag = (u8 *) skb_put(skb, len + 2 + rate_len); -- cgit From 599b87809594e2b8f742cbd318db31935689cceb Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 16:03:08 -0500 Subject: staging: emxx_udc: Remove parentheses around the right hand side of assignment Remove parentheses around the right hand side of assignments as they are not needed. Semantic patch used: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/emxx_udc/emxx_udc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c index c408ee9a967f..a1f624f76c8a 100644 --- a/drivers/staging/emxx_udc/emxx_udc.c +++ b/drivers/staging/emxx_udc/emxx_udc.c @@ -271,21 +271,21 @@ static int _nbu2ss_ep_init(struct nbu2ss_udc *udc, struct nbu2ss_ep *ep) data = EPn_EN | EPn_BCLR | EPn_DIR0; _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data); - data = (EPn_ONAK | EPn_OSTL_EN | EPn_OSTL); + data = EPn_ONAK | EPn_OSTL_EN | EPn_OSTL; _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data); - data = (EPn_OUT_EN | EPn_OUT_END_EN); + data = EPn_OUT_EN | EPn_OUT_END_EN; _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data); } else { /*---------------------------------------------------------*/ /* IN */ - data = (EPn_EN | EPn_BCLR | EPn_AUTO); + data = EPn_EN | EPn_BCLR | EPn_AUTO; _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_CONTROL, data); - data = (EPn_ISTL); + data = EPn_ISTL; _nbu2ss_bitclr(&udc->p_regs->EP_REGS[num].EP_CONTROL, data); - data = (EPn_IN_EN | EPn_IN_END_EN); + data = EPn_IN_EN | EPn_IN_END_EN; _nbu2ss_bitset(&udc->p_regs->EP_REGS[num].EP_INT_ENA, data); } @@ -460,7 +460,7 @@ static void _nbu2ss_ep_in_end( if (length) _nbu2ss_writel(&preg->EP_REGS[num].EP_WRITE, data32); - data = (((((u32)length) << 5) & EPn_DW) | EPn_DEND); + data = ((((u32)length) << 5) & EPn_DW) | EPn_DEND; _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, data); _nbu2ss_bitset(&preg->EP_REGS[num].EP_CONTROL, EPn_AUTO); @@ -844,7 +844,7 @@ static int _nbu2ss_out_dma( /* Number of transfer packets */ mpkt = _nbu2ss_readl(&preg->EP_REGS[num].EP_PCKT_ADRS) & EPn_MPKT; - dmacnt = (length / mpkt); + dmacnt = length / mpkt; lmpkt = (length % mpkt) & ~(u32)0x03; if (dmacnt > DMA_MAX_COUNT) { -- cgit From 3a35be2a14435a88fad045fb24ca4e1c0dcf4643 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 17:52:30 -0500 Subject: staging: media: Remove unneeded parentheses Remove unneeded parentheses in assignment statements. Semantic patch: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/davinci_vpfe/dm365_isif.c | 2 +- drivers/staging/media/davinci_vpfe/dm365_resizer.c | 8 ++++---- drivers/staging/media/mn88472/mn88472.c | 6 +++--- drivers/staging/media/mn88473/mn88473.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 99057892d88d..65f6ce342a00 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -1570,7 +1570,7 @@ isif_pad_set_selection(struct v4l2_subdev *sd, sel->r.height = format->height; } /* adjust the width to 16 pixel boundary */ - sel->r.width = ((sel->r.width + 15) & ~0xf); + sel->r.width = (sel->r.width + 15) & ~0xf; vpfe_isif->crop = sel->r; if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) { isif_set_image_window(vpfe_isif); diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c index a91395ce91e1..42de95e31f6f 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c +++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c @@ -404,7 +404,7 @@ resizer_calculate_down_scale_f_div_param(struct device *dev, param->f_div.pass[0].src_hsz = upper_h1 + o; param->f_div.pass[1].o_hsz = h2 - 1; param->f_div.pass[1].i_hps = 10 + (val1 * two_power); - param->f_div.pass[1].h_phs = (val - (val1 << 8)); + param->f_div.pass[1].h_phs = val - (val1 << 8); param->f_div.pass[1].src_hps = upper_h1 - o; param->f_div.pass[1].src_hsz = upper_h2 + o; @@ -425,8 +425,8 @@ resizer_configure_common_in_params(struct vpfe_resizer_device *resizer) param->rsz_common.hps = param->user_config.hst; if (vpfe_ipipeif_decimation_enabled(vpfe_dev)) - param->rsz_common.hsz = (((informat->width - 1) * - IPIPEIF_RSZ_CONST) / vpfe_ipipeif_get_rsz(vpfe_dev)); + param->rsz_common.hsz = ((informat->width - 1) * + IPIPEIF_RSZ_CONST) / vpfe_ipipeif_get_rsz(vpfe_dev); else param->rsz_common.hsz = informat->width - 1; @@ -650,7 +650,7 @@ resizer_calculate_normal_f_div_param(struct device *dev, int input_width, param->f_div.pass[0].src_hsz = (input_width >> 2) + o; param->f_div.pass[1].o_hsz = h2 - 1; param->f_div.pass[1].i_hps = val1; - param->f_div.pass[1].h_phs = (val - (val1 << 8)); + param->f_div.pass[1].h_phs = val - (val1 << 8); param->f_div.pass[1].src_hps = (input_width >> 2) - o; param->f_div.pass[1].src_hsz = (input_width >> 2) + o; diff --git a/drivers/staging/media/mn88472/mn88472.c b/drivers/staging/media/mn88472/mn88472.c index cf2e96bcf395..c2f2a63ef3ce 100644 --- a/drivers/staging/media/mn88472/mn88472.c +++ b/drivers/staging/media/mn88472/mn88472.c @@ -96,9 +96,9 @@ static int mn88472_set_frontend(struct dvb_frontend *fe) /* Calculate IF registers ( (1<<24)*IF / Xtal ) */ tmp = div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2), dev->xtal); - if_val[0] = ((tmp >> 16) & 0xff); - if_val[1] = ((tmp >> 8) & 0xff); - if_val[2] = ((tmp >> 0) & 0xff); + if_val[0] = (tmp >> 16) & 0xff; + if_val[1] = (tmp >> 8) & 0xff; + if_val[2] = (tmp >> 0) & 0xff; ret = regmap_write(dev->regmap[2], 0xfb, 0x13); ret = regmap_write(dev->regmap[2], 0xef, 0x13); diff --git a/drivers/staging/media/mn88473/mn88473.c b/drivers/staging/media/mn88473/mn88473.c index a222e99935d2..68a614b3e3f0 100644 --- a/drivers/staging/media/mn88473/mn88473.c +++ b/drivers/staging/media/mn88473/mn88473.c @@ -94,9 +94,9 @@ static int mn88473_set_frontend(struct dvb_frontend *fe) /* Calculate IF registers ( (1<<24)*IF / Xtal ) */ tmp = div_u64(if_frequency * (u64)(1<<24) + (dev->xtal / 2), dev->xtal); - if_val[0] = ((tmp >> 16) & 0xff); - if_val[1] = ((tmp >> 8) & 0xff); - if_val[2] = ((tmp >> 0) & 0xff); + if_val[0] = (tmp >> 16) & 0xff; + if_val[1] = (tmp >> 8) & 0xff; + if_val[2] = (tmp >> 0) & 0xff; ret = regmap_write(dev->regmap[2], 0x05, 0x00); ret = regmap_write(dev->regmap[2], 0xfb, 0x13); -- cgit From 2cdb82c7ffd27f3f574e0bb80e97024a4f65c26b Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Thu, 11 Feb 2016 18:00:25 -0500 Subject: staging: fsl-mc: Remove unneeded parentheses Remove unneeded parentheses on the right hand side of assignment statements. Semantic patch: @@ expression a, b, c; @@ ( a = (b == c) | a = - ( b - ) ) Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fsl-mc/bus/dprc-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/fsl-mc/bus/dprc-driver.c b/drivers/staging/fsl-mc/bus/dprc-driver.c index 52c6fce0fd29..9380ebc9f06f 100644 --- a/drivers/staging/fsl-mc/bus/dprc-driver.c +++ b/drivers/staging/fsl-mc/bus/dprc-driver.c @@ -129,7 +129,7 @@ static void check_plugged_state_change(struct fsl_mc_device *mc_dev, { int error; u32 plugged_flag_at_mc = - (obj_desc->state & DPRC_OBJ_STATE_PLUGGED); + obj_desc->state & DPRC_OBJ_STATE_PLUGGED; if (plugged_flag_at_mc != (mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED)) { -- cgit From 46d83a8782e73468c9f744d859fbb6af4d53c520 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 10 Feb 2016 10:02:02 +0530 Subject: misc: ibmasm: Replace timeval with timespec64 This patch replaces timeval with timespec64 as 32 bit 'struct timeval' will not give current time beyond year 2038. The patch changes the code to use ktime_get_real_ts64() which returns a 'struct timespec64' instead of do_gettimeofday() which returns a 'struct timeval' This patch also alters the format strings in sprintf() for now.tv_sec and now.tv_nsec to incorporate 'long long' on 32 bit architectures and leading zeroes respectively. Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ibmasm/ibmasm.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index 5bd127727d8e..9fea49d2e15b 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -34,6 +34,7 @@ #include #include #include +#include /* Driver identification */ #define DRIVER_NAME "ibmasm" @@ -53,9 +54,11 @@ extern int ibmasm_debug; static inline char *get_timestamp(char *buf) { - struct timeval now; - do_gettimeofday(&now); - sprintf(buf, "%lu.%lu", now.tv_sec, now.tv_usec); + struct timespec64 now; + + ktime_get_real_ts64(&now); + sprintf(buf, "%llu.%.08lu", (long long)now.tv_sec, + now.tv_nsec / NSEC_PER_USEC); return buf; } -- cgit From 212265e5ad726ed7fd2ec7d61d36d9e0b0d3e655 Mon Sep 17 00:00:00 2001 From: Arve Hjønnevåg Date: Tue, 9 Feb 2016 21:05:32 -0800 Subject: android: binder: More offset validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure offsets don't point to overlapping flat_binder_object structs. Cc: Colin Cross Cc: Arve Hjønnevåg Cc: Dmitry Shmidt Cc: Rom Lemarchand Cc: Serban Constantinescu Cc: Greg Kroah-Hartman Cc: Android Kernel Team Signed-off-by: Dmitry Shmidt Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index a39e85f9efa9..1db376184955 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1321,6 +1321,7 @@ static void binder_transaction(struct binder_proc *proc, struct binder_transaction *t; struct binder_work *tcomplete; binder_size_t *offp, *off_end; + binder_size_t off_min; struct binder_proc *target_proc; struct binder_thread *target_thread = NULL; struct binder_node *target_node = NULL; @@ -1522,18 +1523,24 @@ static void binder_transaction(struct binder_proc *proc, goto err_bad_offset; } off_end = (void *)offp + tr->offsets_size; + off_min = 0; for (; offp < off_end; offp++) { struct flat_binder_object *fp; if (*offp > t->buffer->data_size - sizeof(*fp) || + *offp < off_min || t->buffer->data_size < sizeof(*fp) || !IS_ALIGNED(*offp, sizeof(u32))) { - binder_user_error("%d:%d got transaction with invalid offset, %lld\n", - proc->pid, thread->pid, (u64)*offp); + binder_user_error("%d:%d got transaction with invalid offset, %lld (min %lld, max %lld)\n", + proc->pid, thread->pid, (u64)*offp, + (u64)off_min, + (u64)(t->buffer->data_size - + sizeof(*fp))); return_error = BR_FAILED_REPLY; goto err_bad_offset; } fp = (struct flat_binder_object *)(t->buffer->data + *offp); + off_min = *offp + sizeof(struct flat_binder_object); switch (fp->type) { case BINDER_TYPE_BINDER: case BINDER_TYPE_WEAK_BINDER: { -- cgit From 83050a4e21979fe1821916fce2fca36255569ed3 Mon Sep 17 00:00:00 2001 From: Riley Andrews Date: Tue, 9 Feb 2016 21:05:33 -0800 Subject: android: drivers: Avoid debugfs race in binder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a /d/binder/proc/[pid] entry is kept open after linux has torn down the associated process, binder_proc_show can deference an invalid binder_proc that has been stashed in the debugfs inode. Validate that the binder_proc ptr passed into binder_proc_show has not been freed by looking for it within the global process list whilst the global lock is held. If the ptr is not valid, print nothing. Cc: Colin Cross Cc: Arve Hjønnevåg Cc: Dmitry Shmidt Cc: Rom Lemarchand Cc: Serban Constantinescu Cc: Greg Kroah-Hartman Cc: Android Kernel Team Signed-off-by: Dmitry Shmidt [jstultz: Minor commit message tweaks] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 1db376184955..f0ce9959d14d 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3600,13 +3600,24 @@ static int binder_transactions_show(struct seq_file *m, void *unused) static int binder_proc_show(struct seq_file *m, void *unused) { + struct binder_proc *itr; struct binder_proc *proc = m->private; int do_lock = !binder_debug_no_lock; + bool valid_proc = false; if (do_lock) binder_lock(__func__); - seq_puts(m, "binder proc state:\n"); - print_binder_proc(m, proc, 1); + + hlist_for_each_entry(itr, &binder_procs, proc_node) { + if (itr == proc) { + valid_proc = true; + break; + } + } + if (valid_proc) { + seq_puts(m, "binder proc state:\n"); + print_binder_proc(m, proc, 1); + } if (do_lock) binder_unlock(__func__); return 0; -- cgit From 28c09ec4b6b7a2f9f769966baf54eaf0d6fadf8c Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 11 Feb 2016 15:23:51 +0100 Subject: firmware: qemu config needs I/O ports Not all machines have PCI style I/O port memory, or they do not allow mapping it using the ioport_map() function, whcih results in a build error with the newly added qemu firmware code: drivers/firmware/built-in.o: In function `fw_cfg_io_cleanup': qemu_fw_cfg.c:(.text+0x144): undefined reference to `ioport_unmap' drivers/firmware/built-in.o: In function `fw_cfg_sysfs_probe': qemu_fw_cfg.c:(.text+0xb18): undefined reference to `ioport_map' This adds a Kconfig dependency to ensure the driver can only be built on platforms that support it. Signed-off-by: Arnd Bergmann Fixes: 75f3e8e47f38 ("firmware: introduce sysfs driver for QEMU's fw_cfg device") Acked-by: Gabriel Somlo Signed-off-by: Greg Kroah-Hartman --- drivers/firmware/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 5130f74ae3bd..6664f1108c7c 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -164,6 +164,7 @@ config RASPBERRYPI_FIRMWARE config FW_CFG_SYSFS tristate "QEMU fw_cfg device support in sysfs" depends on SYSFS && (ARM || ARM64 || PPC_PMAC || SPARC || X86) + depends on HAS_IOPORT_MAP default n help Say Y or M here to enable the exporting of the QEMU firmware -- cgit From 6f89fa9e5868dd9956cbc7e97adf8de5a965d69a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:38 +0800 Subject: mfd: axp20x: Add AXP223 to list of supported PMICs in DT bindings The AXP223 is a new PMIC commonly paired with Allwinner A23/A33 SoCs. It is functionally identical to AXP221; only the regulator default voltage/status and the external host interface are different. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Lee Jones --- Documentation/devicetree/bindings/mfd/axp20x.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt index a474359dd206..fd39fa54571b 100644 --- a/Documentation/devicetree/bindings/mfd/axp20x.txt +++ b/Documentation/devicetree/bindings/mfd/axp20x.txt @@ -5,11 +5,12 @@ axp152 (X-Powers) axp202 (X-Powers) axp209 (X-Powers) axp221 (X-Powers) +axp223 (X-Powers) Required properties: - compatible: "x-powers,axp152", "x-powers,axp202", "x-powers,axp209", - "x-powers,axp221" -- reg: The I2C slave address for the AXP chip + "x-powers,axp221", "x-powers,axp223" +- 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 - interrupt-controller: The PMIC has its own internal IRQs @@ -51,7 +52,7 @@ LDO3 : LDO : ldo3in-supply LDO4 : LDO : ldo24in-supply : shared supply LDO5 : LDO : ldo5in-supply -AXP221 regulators, type, and corresponding input supply names: +AXP221/AXP223 regulators, type, and corresponding input supply names: Regulator Type Supply Name Notes --------- ---- ----------- ----- -- cgit From e47a3cf741e71b8c545a826df42432fec3ea60c6 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:39 +0800 Subject: mfd: axp20x: Remove second struct device * parameter for axp20x_match_device() The first argument passed to axp20x_match_device(), struct axp20x_dev *, already contains a pointer to the device. By rearranging some code, moving the assignment of the pointer before axp20x_match_device() is called, we can eliminate the second parameter. Suggested-by: Andy Shevchenko Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 9842199e2e6c..685a78614f83 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -606,8 +606,9 @@ static void axp20x_power_off(void) AXP20X_OFF); } -static int axp20x_match_device(struct axp20x_dev *axp20x, struct device *dev) +static int axp20x_match_device(struct axp20x_dev *axp20x) { + struct device *dev = axp20x->dev; const struct acpi_device_id *acpi_id; const struct of_device_id *of_id; @@ -673,14 +674,14 @@ static int axp20x_i2c_probe(struct i2c_client *i2c, if (!axp20x) return -ENOMEM; - ret = axp20x_match_device(axp20x, &i2c->dev); - if (ret) - return ret; - axp20x->i2c_client = i2c; axp20x->dev = &i2c->dev; dev_set_drvdata(axp20x->dev, axp20x); + ret = axp20x_match_device(axp20x); + if (ret) + return ret; + axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg); if (IS_ERR(axp20x->regmap)) { ret = PTR_ERR(axp20x->regmap); -- cgit From af7acc3df7b1cad3956579c63a70a7b85b69161b Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:40 +0800 Subject: mfd: axp20x: Use dev->driver->of_match_table in axp20x_match_device() In axp20x_match_device(), match the of_device_id table bound to the device driver instead of pointing to axp20x_of_match directly. This will allow us to keep axp20x_match_device() unmodified when we expand the axp20x driver into multiple ones covering different interface types. of_device_get_match_data() cannot be used here as we need to know if it failed to get a match, or if the match data value just happened to be 0, as it is for the AXP152. Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 685a78614f83..3e186f2dcac3 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -613,7 +613,7 @@ static int axp20x_match_device(struct axp20x_dev *axp20x) const struct of_device_id *of_id; if (dev->of_node) { - of_id = of_match_device(axp20x_of_match, dev); + of_id = of_match_device(dev->driver->of_match_table, dev); if (!of_id) { dev_err(dev, "Unable to match OF ID\n"); return -ENODEV; -- cgit From e740235ddd84f4fe993af982b873578f3299b7d6 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:41 +0800 Subject: mfd: axp20x: Add missing copyright notice Supply a backdated copyright notice. Signed-off-by: Chen-Yu Tsai Acked-by: Carlo Caione Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 3e186f2dcac3..cec51e689d1d 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -5,6 +5,8 @@ * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature * as well as configurable GPIOs. * + * Copyright (C) 2014 Carlo Caione + * * Author: Carlo Caione * * This program is free software; you can redistribute it and/or modify -- cgit From aec045b80d79bdc2cdd9b0003ff85b0470107e18 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 11 Feb 2016 20:18:37 +0900 Subject: ALSA: dice: change notification mask to detect lock status change With former patchset, ALSA dice driver doesn't change clock parameters anymore, while the driver still touch clock configuration for phase lock. Although the locking status is in Dice notification, the driver doesn't detect it. Usually, this causes no issues because in most case NOTIFY_LOCK_CHG notification transfers after NOTIFY_CLOCK_ACCEPTED notification, while it's better to detect locking status. This commit changes notification mask just to detect lock status change. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/firewire/dice/dice-transaction.c b/sound/firewire/dice/dice-transaction.c index 76f9f72df2a9..0f0350320ae8 100644 --- a/sound/firewire/dice/dice-transaction.c +++ b/sound/firewire/dice/dice-transaction.c @@ -156,7 +156,7 @@ static void dice_notification(struct fw_card *card, struct fw_request *request, fw_send_response(card, request, RCODE_COMPLETE); - if (bits & NOTIFY_CLOCK_ACCEPTED) + if (bits & NOTIFY_LOCK_CHG) complete(&dice->clock_accepted); wake_up(&dice->hwdep_wait); } -- cgit From fbeac84dbe9e72d58b1377a0d1bc8a58f40ce31a Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 11 Feb 2016 20:18:38 +0900 Subject: ALSA: dice: old firmware optimization for Dice notification As long as I tested, Dice-based models produced by TC Electronic with factory-configured settings transfer no notification within ensure_phase_lock(). On the other hand, with upgraded firmwares, it starts to transfer the notification. This seems to be a quirk of earlier firmwares. This commit ensures phase lock by reading a register after waiting for the notification. Even if it's timed-out, ensure_phase_lock() return success as long as the register has expected clock status. Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-stream.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c index e4938b0cddbe..a64b3cc76bf1 100644 --- a/sound/firewire/dice/dice-stream.c +++ b/sound/firewire/dice/dice-stream.c @@ -31,7 +31,7 @@ const unsigned int snd_dice_rates[SND_DICE_RATES_COUNT] = { */ static int ensure_phase_lock(struct snd_dice *dice) { - __be32 reg; + __be32 reg, nominal; int err; err = snd_dice_transaction_read_global(dice, GLOBAL_CLOCK_SELECT, @@ -48,8 +48,19 @@ static int ensure_phase_lock(struct snd_dice *dice) return err; if (wait_for_completion_timeout(&dice->clock_accepted, - msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) - return -ETIMEDOUT; + msecs_to_jiffies(NOTIFICATION_TIMEOUT_MS)) == 0) { + /* + * Old versions of Dice firmware transfer no notification when + * the same clock status as current one is set. In this case, + * just check current clock status. + */ + err = snd_dice_transaction_read_global(dice, GLOBAL_STATUS, + &nominal, sizeof(nominal)); + if (err < 0) + return err; + if (!(be32_to_cpu(nominal) & STATUS_SOURCE_LOCKED)) + return -ETIMEDOUT; + } return 0; } -- cgit From 4fd411514291ae75053003e33a6a4a56f97467d0 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:42 +0800 Subject: mfd: axp20x: Split the driver into core and i2c bits The axp20x driver assumes the device is i2c based. This is not the case with later chips, which use a proprietary 2 wire serial bus by Allwinner called "Reduced Serial Bus". This patch follows the example of mfd/wm831x and splits it into an interface independent core, and an i2c specific glue layer. MFD_AXP20X and the new MFD_AXP20X_I2C are changed to tristate symbols, allowing the driver to be built as modules. Whitespace and other style errors in the moved i2c specific code have been fixed. Included but unused header files are removed as well. Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 14 +++--- drivers/mfd/Makefile | 1 + drivers/mfd/axp20x-i2c.c | 104 +++++++++++++++++++++++++++++++++++++++++++++ drivers/mfd/axp20x.c | 90 +++++++-------------------------------- include/linux/mfd/axp20x.h | 33 +++++++++++++- 5 files changed, 161 insertions(+), 81 deletions(-) create mode 100644 drivers/mfd/axp20x-i2c.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9ca66de0c1c1..0037b9c933d9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -91,14 +91,18 @@ config MFD_BCM590XX Support for the BCM590xx PMUs from Broadcom config MFD_AXP20X - bool "X-Powers AXP20X" + tristate select MFD_CORE - select REGMAP_I2C select REGMAP_IRQ - depends on I2C=y + +config MFD_AXP20X_I2C + tristate "X-Powers AXP series PMICs with I2C" + select MFD_AXP20X + select REGMAP_I2C + depends on I2C help - If you say Y here you get support for the X-Powers AXP202, AXP209 and - AXP288 power management IC (PMIC). + If you say Y here you get support for the X-Powers AXP series power + management ICs (PMICs) controlled with I2C. This driver include only the core APIs. You have to select individual components like regulators or the PEK (Power Enable Key) under the corresponding menus. diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0f230a6103f8..dba4f99d9044 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -111,6 +111,7 @@ obj-$(CONFIG_PMIC_DA9052) += da9052-core.o obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o obj-$(CONFIG_MFD_AXP20X) += axp20x.o +obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o obj-$(CONFIG_MFD_LP3943) += lp3943.o obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o diff --git a/drivers/mfd/axp20x-i2c.c b/drivers/mfd/axp20x-i2c.c new file mode 100644 index 000000000000..b1b865822c07 --- /dev/null +++ b/drivers/mfd/axp20x-i2c.c @@ -0,0 +1,104 @@ +/* + * I2C driver for the X-Powers' Power Management ICs + * + * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC + * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature + * as well as configurable GPIOs. + * + * This driver supports the I2C variants. + * + * Copyright (C) 2014 Carlo Caione + * + * Author: Carlo Caione + * + * 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 + +static int axp20x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct axp20x_dev *axp20x; + int ret; + + axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL); + if (!axp20x) + return -ENOMEM; + + axp20x->dev = &i2c->dev; + axp20x->irq = i2c->irq; + dev_set_drvdata(axp20x->dev, axp20x); + + ret = axp20x_match_device(axp20x); + if (ret) + return ret; + + axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg); + if (IS_ERR(axp20x->regmap)) { + ret = PTR_ERR(axp20x->regmap); + dev_err(&i2c->dev, "regmap init failed: %d\n", ret); + return ret; + } + + return axp20x_device_probe(axp20x); +} + +static int axp20x_i2c_remove(struct i2c_client *i2c) +{ + struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); + + return axp20x_device_remove(axp20x); +} + +static const struct of_device_id axp20x_i2c_of_match[] = { + { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID }, + { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, + { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, + { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, + { }, +}; +MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); + +/* + * This is useless for OF-enabled devices, but it is needed by I2C subsystem + */ +static const struct i2c_device_id axp20x_i2c_id[] = { + { }, +}; +MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); + +static const struct acpi_device_id axp20x_i2c_acpi_match[] = { + { + .id = "INT33F4", + .driver_data = AXP288_ID, + }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, axp20x_i2c_acpi_match); + +static struct i2c_driver axp20x_i2c_driver = { + .driver = { + .name = "axp20x-i2c", + .of_match_table = of_match_ptr(axp20x_i2c_of_match), + .acpi_match_table = ACPI_PTR(axp20x_i2c_acpi_match), + }, + .probe = axp20x_i2c_probe, + .remove = axp20x_i2c_remove, + .id_table = axp20x_i2c_id, +}; + +module_i2c_driver(axp20x_i2c_driver); + +MODULE_DESCRIPTION("PMIC MFD I2C driver for AXP20X"); +MODULE_AUTHOR("Carlo Caione "); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index cec51e689d1d..8e569bcfe3bc 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -1,10 +1,12 @@ /* - * axp20x.c - MFD core driver for the X-Powers' Power Management ICs + * MFD core driver for the X-Powers' Power Management ICs * * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature * as well as configurable GPIOs. * + * This file contains the interface independent core functions. + * * Copyright (C) 2014 Carlo Caione * * Author: Carlo Caione @@ -15,18 +17,15 @@ */ #include -#include #include #include #include #include #include -#include #include #include #include #include -#include #include #define AXP20X_OFF 0x80 @@ -378,32 +377,6 @@ static const struct regmap_irq axp288_regmap_irqs[] = { INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; -static const struct of_device_id axp20x_of_match[] = { - { .compatible = "x-powers,axp152", .data = (void *) AXP152_ID }, - { .compatible = "x-powers,axp202", .data = (void *) AXP202_ID }, - { .compatible = "x-powers,axp209", .data = (void *) AXP209_ID }, - { .compatible = "x-powers,axp221", .data = (void *) AXP221_ID }, - { }, -}; -MODULE_DEVICE_TABLE(of, axp20x_of_match); - -/* - * This is useless for OF-enabled devices, but it is needed by I2C subsystem - */ -static const struct i2c_device_id axp20x_i2c_id[] = { - { }, -}; -MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); - -static const struct acpi_device_id axp20x_acpi_match[] = { - { - .id = "INT33F4", - .driver_data = AXP288_ID, - }, - { }, -}; -MODULE_DEVICE_TABLE(acpi, axp20x_acpi_match); - static const struct regmap_irq_chip axp152_regmap_irq_chip = { .name = "axp152_irq_chip", .status_base = AXP152_IRQ1_STATE, @@ -608,7 +581,7 @@ static void axp20x_power_off(void) AXP20X_OFF); } -static int axp20x_match_device(struct axp20x_dev *axp20x) +int axp20x_match_device(struct axp20x_dev *axp20x) { struct device *dev = axp20x->dev; const struct acpi_device_id *acpi_id; @@ -665,38 +638,18 @@ static int axp20x_match_device(struct axp20x_dev *axp20x) return 0; } +EXPORT_SYMBOL(axp20x_match_device); -static int axp20x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +int axp20x_device_probe(struct axp20x_dev *axp20x) { - struct axp20x_dev *axp20x; int ret; - axp20x = devm_kzalloc(&i2c->dev, sizeof(*axp20x), GFP_KERNEL); - if (!axp20x) - return -ENOMEM; - - axp20x->i2c_client = i2c; - axp20x->dev = &i2c->dev; - dev_set_drvdata(axp20x->dev, axp20x); - - ret = axp20x_match_device(axp20x); - if (ret) - return ret; - - axp20x->regmap = devm_regmap_init_i2c(i2c, axp20x->regmap_cfg); - if (IS_ERR(axp20x->regmap)) { - ret = PTR_ERR(axp20x->regmap); - dev_err(&i2c->dev, "regmap init failed: %d\n", ret); - return ret; - } - - ret = regmap_add_irq_chip(axp20x->regmap, i2c->irq, + ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq, IRQF_ONESHOT | IRQF_SHARED, -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc); if (ret) { - dev_err(&i2c->dev, "failed to add irq chip: %d\n", ret); + dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret); return ret; } @@ -704,8 +657,8 @@ static int axp20x_i2c_probe(struct i2c_client *i2c, axp20x->nr_cells, NULL, 0, NULL); if (ret) { - dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret); - regmap_del_irq_chip(i2c->irq, axp20x->regmap_irqc); + dev_err(axp20x->dev, "failed to add MFD devices: %d\n", ret); + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); return ret; } @@ -714,38 +667,25 @@ static int axp20x_i2c_probe(struct i2c_client *i2c, pm_power_off = axp20x_power_off; } - dev_info(&i2c->dev, "AXP20X driver loaded\n"); + dev_info(axp20x->dev, "AXP20X driver loaded\n"); return 0; } +EXPORT_SYMBOL(axp20x_device_probe); -static int axp20x_i2c_remove(struct i2c_client *i2c) +int axp20x_device_remove(struct axp20x_dev *axp20x) { - struct axp20x_dev *axp20x = i2c_get_clientdata(i2c); - if (axp20x == axp20x_pm_power_off) { axp20x_pm_power_off = NULL; pm_power_off = NULL; } mfd_remove_devices(axp20x->dev); - regmap_del_irq_chip(axp20x->i2c_client->irq, axp20x->regmap_irqc); + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); return 0; } - -static struct i2c_driver axp20x_i2c_driver = { - .driver = { - .name = "axp20x", - .of_match_table = of_match_ptr(axp20x_of_match), - .acpi_match_table = ACPI_PTR(axp20x_acpi_match), - }, - .probe = axp20x_i2c_probe, - .remove = axp20x_i2c_remove, - .id_table = axp20x_i2c_id, -}; - -module_i2c_driver(axp20x_i2c_driver); +EXPORT_SYMBOL(axp20x_device_remove); MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X"); MODULE_AUTHOR("Carlo Caione "); diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index b24c771cebd5..00697c6ad8b0 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -396,7 +396,7 @@ enum axp288_irqs { struct axp20x_dev { struct device *dev; - struct i2c_client *i2c_client; + int irq; struct regmap *regmap; struct regmap_irq_chip_data *regmap_irqc; long variant; @@ -462,4 +462,35 @@ static inline int axp20x_read_variable_width(struct regmap *regmap, return result; } +/** + * axp20x_match_device(): Setup axp20x variant related fields + * + * @axp20x: axp20x device to setup (.dev field must be set) + * @dev: device associated with this axp20x device + * + * This lets the axp20x core configure the mfd cells and register maps + * for later use. + */ +int axp20x_match_device(struct axp20x_dev *axp20x); + +/** + * axp20x_device_probe(): Probe a configured axp20x device + * + * @axp20x: axp20x device to probe (must be configured) + * + * This function lets the axp20x core register the axp20x mfd devices + * and irqchip. The axp20x device passed in must be fully configured + * with axp20x_match_device, its irq set, and regmap created. + */ +int axp20x_device_probe(struct axp20x_dev *axp20x); + +/** + * axp20x_device_probe(): Remove a axp20x device + * + * @axp20x: axp20x device to remove + * + * This tells the axp20x core to remove the associated mfd devices + */ +int axp20x_device_remove(struct axp20x_dev *axp20x); + #endif /* __LINUX_MFD_AXP20X_H */ -- cgit From 2260a45356756285faa0b46f0afa53c7f251fb9c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:43 +0800 Subject: mfd: axp20x: Whitespace, open parenthesis alignment code style fixes This fixes some leftover code style issues in the axp20x core. Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/axp20x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 8e569bcfe3bc..3054ea4b95e8 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -593,14 +593,14 @@ int axp20x_match_device(struct axp20x_dev *axp20x) dev_err(dev, "Unable to match OF ID\n"); return -ENODEV; } - axp20x->variant = (long) of_id->data; + axp20x->variant = (long)of_id->data; } else { acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev); if (!acpi_id || !acpi_id->driver_data) { dev_err(dev, "Unable to match ACPI ID and data\n"); return -ENODEV; } - axp20x->variant = (long) acpi_id->driver_data; + axp20x->variant = (long)acpi_id->driver_data; } switch (axp20x->variant) { @@ -634,7 +634,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x) return -EINVAL; } dev_info(dev, "AXP20x variant %s found\n", - axp20x_model_names[axp20x->variant]); + axp20x_model_names[axp20x->variant]); return 0; } @@ -654,7 +654,7 @@ int axp20x_device_probe(struct axp20x_dev *axp20x) } ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells, - axp20x->nr_cells, NULL, 0, NULL); + axp20x->nr_cells, NULL, 0, NULL); if (ret) { dev_err(axp20x->dev, "failed to add MFD devices: %d\n", ret); -- cgit From 02071f0f797c989b342f46fbdf472ddb1c2cdee9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:44 +0800 Subject: mfd: axp20x: Add support for RSB based AXP223 PMIC The AXP223 is a new PMIC commonly paired with Allwinner A23/A33 SoCs. It is functionally identical to AXP221; only the regulator default voltage/status and the external host interface are different. Signed-off-by: Chen-Yu Tsai Signed-off-by: Lee Jones --- drivers/mfd/Kconfig | 11 +++++++ drivers/mfd/Makefile | 1 + drivers/mfd/axp20x-rsb.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/mfd/axp20x.c | 2 ++ include/linux/mfd/axp20x.h | 1 + 5 files changed, 95 insertions(+) create mode 100644 drivers/mfd/axp20x-rsb.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 0037b9c933d9..ae3990b5a2bf 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -107,6 +107,17 @@ config MFD_AXP20X_I2C components like regulators or the PEK (Power Enable Key) under the corresponding menus. +config MFD_AXP20X_RSB + tristate "X-Powers AXP series PMICs with RSB" + select MFD_AXP20X + depends on SUNXI_RSB + help + If you say Y here you get support for the X-Powers AXP series power + management ICs (PMICs) controlled with RSB. + This driver include only the core APIs. You have to select individual + components like regulators or the PEK (Power Enable Key) under the + corresponding menus. + config MFD_CROS_EC tristate "ChromeOS Embedded Controller" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index dba4f99d9044..c69ea744fd1a 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -112,6 +112,7 @@ obj-$(CONFIG_MFD_DA9052_SPI) += da9052-spi.o obj-$(CONFIG_MFD_DA9052_I2C) += da9052-i2c.o obj-$(CONFIG_MFD_AXP20X) += axp20x.o obj-$(CONFIG_MFD_AXP20X_I2C) += axp20x-i2c.o +obj-$(CONFIG_MFD_AXP20X_RSB) += axp20x-rsb.o obj-$(CONFIG_MFD_LP3943) += lp3943.o obj-$(CONFIG_MFD_LP8788) += lp8788.o lp8788-irq.o diff --git a/drivers/mfd/axp20x-rsb.c b/drivers/mfd/axp20x-rsb.c new file mode 100644 index 000000000000..28c20247c112 --- /dev/null +++ b/drivers/mfd/axp20x-rsb.c @@ -0,0 +1,80 @@ +/* + * RSB driver for the X-Powers' Power Management ICs + * + * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC + * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature + * as well as configurable GPIOs. + * + * This driver supports the RSB variants. + * + * Copyright (C) 2015 Chen-Yu Tsai + * + * Author: Chen-Yu Tsai + * + * 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 + +static int axp20x_rsb_probe(struct sunxi_rsb_device *rdev) +{ + struct axp20x_dev *axp20x; + int ret; + + axp20x = devm_kzalloc(&rdev->dev, sizeof(*axp20x), GFP_KERNEL); + if (!axp20x) + return -ENOMEM; + + axp20x->dev = &rdev->dev; + axp20x->irq = rdev->irq; + dev_set_drvdata(&rdev->dev, axp20x); + + ret = axp20x_match_device(axp20x); + if (ret) + return ret; + + axp20x->regmap = devm_regmap_init_sunxi_rsb(rdev, axp20x->regmap_cfg); + if (IS_ERR(axp20x->regmap)) { + ret = PTR_ERR(axp20x->regmap); + dev_err(&rdev->dev, "regmap init failed: %d\n", ret); + return ret; + } + + return axp20x_device_probe(axp20x); +} + +static int axp20x_rsb_remove(struct sunxi_rsb_device *rdev) +{ + struct axp20x_dev *axp20x = sunxi_rsb_device_get_drvdata(rdev); + + return axp20x_device_remove(axp20x); +} + +static const struct of_device_id axp20x_rsb_of_match[] = { + { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { }, +}; +MODULE_DEVICE_TABLE(of, axp20x_rsb_of_match); + +static struct sunxi_rsb_driver axp20x_rsb_driver = { + .driver = { + .name = "axp20x-rsb", + .of_match_table = of_match_ptr(axp20x_rsb_of_match), + }, + .probe = axp20x_rsb_probe, + .remove = axp20x_rsb_remove, +}; +module_sunxi_rsb_driver(axp20x_rsb_driver); + +MODULE_DESCRIPTION("PMIC MFD sunXi RSB driver for AXP20X"); +MODULE_AUTHOR("Chen-Yu Tsai "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c index 3054ea4b95e8..a57d6e940610 100644 --- a/drivers/mfd/axp20x.c +++ b/drivers/mfd/axp20x.c @@ -35,6 +35,7 @@ static const char * const axp20x_model_names[] = { "AXP202", "AXP209", "AXP221", + "AXP223", "AXP288", }; @@ -618,6 +619,7 @@ int axp20x_match_device(struct axp20x_dev *axp20x) axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip; break; case AXP221_ID: + case AXP223_ID: axp20x->nr_cells = ARRAY_SIZE(axp22x_cells); axp20x->cells = axp22x_cells; axp20x->regmap_cfg = &axp22x_regmap_config; diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h index 00697c6ad8b0..d82e7d51372b 100644 --- a/include/linux/mfd/axp20x.h +++ b/include/linux/mfd/axp20x.h @@ -18,6 +18,7 @@ enum { AXP202_ID, AXP209_ID, AXP221_ID, + AXP223_ID, AXP288_ID, NR_AXP20X_VARIANTS, }; -- cgit From 04e0981c67e6a7ba8aacac731d925f4ff21b67fb Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 12 Feb 2016 10:02:45 +0800 Subject: regulator: axp20x: Support new AXP223 PMIC The AXP223 is a new PMIC commonly paired with Allwinner A23/A33 SoCs. It is functionally identical to AXP221; only the regulator default voltage/status and the external host interface are different. Signed-off-by: Chen-Yu Tsai Reviewed-by: Mark Brown Signed-off-by: Lee Jones --- drivers/regulator/axp20x-regulator.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index f2e1a39ce0f3..e86d1fc2d80b 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -244,6 +244,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) step = 75; break; case AXP221_ID: + case AXP223_ID: min = 1800; max = 4050; def = 3000; @@ -322,6 +323,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work break; case AXP221_ID: + case AXP223_ID: if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5) return -EINVAL; @@ -360,6 +362,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev) nregulators = AXP20X_REG_ID_MAX; break; case AXP221_ID: + case AXP223_ID: regulators = axp22x_regulators; nregulators = AXP22X_REG_ID_MAX; break; -- cgit From 1580ab63fc9a03593072cc5656167a75c4f1d173 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 11 Feb 2016 16:28:49 -0800 Subject: tcp/dccp: better use of ephemeral ports in connect() In commit 07f4c90062f8 ("tcp/dccp: try to not exhaust ip_local_port_range in connect()"), I added a very simple heuristic, so that we got better chances to use even ports, and allow bind() users to have more available slots. It gave nice results, but with more than 200,000 TCP sessions on a typical server, the ~30,000 ephemeral ports are still a rare resource. I chose to go a step further, by looking at all even ports, and if none was available, fallback to odd ports. The companion patch does the same in bind(), but in opposite way. I've seen exec times of up to 30ms on busy servers, so I no longer disable BH for the whole traversal, but only for each hash bucket. I also call cond_resched() to be gentle to other tasks. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_hashtables.c | 170 ++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index c0f9942de924..bc68eced0105 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -565,106 +565,106 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, struct sock *, __u16, struct inet_timewait_sock **)) { struct inet_hashinfo *hinfo = death_row->hashinfo; - const unsigned short snum = inet_sk(sk)->inet_num; + struct inet_timewait_sock *tw = NULL; struct inet_bind_hashbucket *head; - struct inet_bind_bucket *tb; - int ret; + int port = inet_sk(sk)->inet_num; struct net *net = sock_net(sk); + struct inet_bind_bucket *tb; + u32 remaining, offset; + int ret, i, low, high; + static u32 hint; + + if (port) { + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + tb = inet_csk(sk)->icsk_bind_hash; + spin_lock_bh(&head->lock); + if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { + inet_ehash_nolisten(sk, NULL); + spin_unlock_bh(&head->lock); + return 0; + } + spin_unlock(&head->lock); + /* No definite answer... Walk to established hash table */ + ret = check_established(death_row, sk, port, NULL); + local_bh_enable(); + return ret; + } - if (!snum) { - int i, remaining, low, high, port; - static u32 hint; - u32 offset = hint + port_offset; - struct inet_timewait_sock *tw = NULL; + inet_get_local_port_range(net, &low, &high); + high++; /* [32768, 60999] -> [32768, 61000[ */ + remaining = high - low; + if (likely(remaining > 1)) + remaining &= ~1U; - inet_get_local_port_range(net, &low, &high); - remaining = (high - low) + 1; + offset = (hint + port_offset) % remaining; + /* In first pass we try ports of @low parity. + * inet_csk_get_port() does the opposite choice. + */ + offset &= ~1U; +other_parity_scan: + port = low + offset; + for (i = 0; i < remaining; i += 2, port += 2) { + if (unlikely(port >= high)) + port -= remaining; + if (inet_is_local_reserved_port(net, port)) + continue; + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); - /* By starting with offset being an even number, - * we tend to leave about 50% of ports for other uses, - * like bind(0). + /* Does not bother with rcv_saddr checks, because + * the established check is already unique enough. */ - offset &= ~1; - - local_bh_disable(); - for (i = 0; i < remaining; i++) { - port = low + (i + offset) % remaining; - if (inet_is_local_reserved_port(net, port)) - continue; - head = &hinfo->bhash[inet_bhashfn(net, port, - hinfo->bhash_size)]; - spin_lock(&head->lock); - - /* Does not bother with rcv_saddr checks, - * because the established check is already - * unique enough. - */ - inet_bind_bucket_for_each(tb, &head->chain) { - if (net_eq(ib_net(tb), net) && - tb->port == port) { - if (tb->fastreuse >= 0 || - tb->fastreuseport >= 0) - goto next_port; - WARN_ON(hlist_empty(&tb->owners)); - if (!check_established(death_row, sk, - port, &tw)) - goto ok; + inet_bind_bucket_for_each(tb, &head->chain) { + if (net_eq(ib_net(tb), net) && tb->port == port) { + if (tb->fastreuse >= 0 || + tb->fastreuseport >= 0) goto next_port; - } + WARN_ON(hlist_empty(&tb->owners)); + if (!check_established(death_row, sk, + port, &tw)) + goto ok; + goto next_port; } - - tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, - net, head, port); - if (!tb) { - spin_unlock(&head->lock); - break; - } - tb->fastreuse = -1; - tb->fastreuseport = -1; - goto ok; - - next_port: - spin_unlock(&head->lock); } - local_bh_enable(); - - return -EADDRNOTAVAIL; -ok: - hint += (i + 2) & ~1; - - /* Head lock still held and bh's disabled */ - inet_bind_hash(sk, tb, port); - if (sk_unhashed(sk)) { - inet_sk(sk)->inet_sport = htons(port); - inet_ehash_nolisten(sk, (struct sock *)tw); + tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, + net, head, port); + if (!tb) { + spin_unlock_bh(&head->lock); + return -ENOMEM; } - if (tw) - inet_twsk_bind_unhash(tw, hinfo); - spin_unlock(&head->lock); + tb->fastreuse = -1; + tb->fastreuseport = -1; + goto ok; +next_port: + spin_unlock_bh(&head->lock); + cond_resched(); + } - if (tw) - inet_twsk_deschedule_put(tw); + offset++; + if ((offset & 1) && remaining > 1) + goto other_parity_scan; - ret = 0; - goto out; - } + return -EADDRNOTAVAIL; - head = &hinfo->bhash[inet_bhashfn(net, snum, hinfo->bhash_size)]; - tb = inet_csk(sk)->icsk_bind_hash; - spin_lock_bh(&head->lock); - if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) { - inet_ehash_nolisten(sk, NULL); - spin_unlock_bh(&head->lock); - return 0; - } else { - spin_unlock(&head->lock); - /* No definite answer... Walk to established hash table */ - ret = check_established(death_row, sk, snum, NULL); -out: - local_bh_enable(); - return ret; +ok: + hint += i + 2; + + /* Head lock still held and bh's disabled */ + inet_bind_hash(sk, tb, port); + if (sk_unhashed(sk)) { + inet_sk(sk)->inet_sport = htons(port); + inet_ehash_nolisten(sk, (struct sock *)tw); } + if (tw) + inet_twsk_bind_unhash(tw, hinfo); + spin_unlock(&head->lock); + if (tw) + inet_twsk_deschedule_put(tw); + local_bh_enable(); + return 0; } /* -- cgit From ea8add2b190395408b22a9127bed2c0912aecbc8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 11 Feb 2016 16:28:50 -0800 Subject: tcp/dccp: better use of ephemeral ports in bind() Implement strategy used in __inet_hash_connect() in opposite way : Try to find a candidate using odd ports, then fallback to even ports. We no longer disable BH for whole traversal, but one bucket at a time. We also use cond_resched() to yield cpu to other tasks if needed. I removed one indentation level and tried to mirror the loop we have in __inet_hash_connect() and variable names to ease code maintenance. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 240 +++++++++++++++++++--------------------- 1 file changed, 114 insertions(+), 126 deletions(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index c16a2e6273d9..3d28c6d5c3c3 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -91,165 +91,153 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict); /* Obtain a reference to a local port for the given sock, * if snum is zero it means select any available local port. + * We try to allocate an odd port (and leave even ports for connect()) */ int inet_csk_get_port(struct sock *sk, unsigned short snum) { - struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo; + bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; + struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo; + int ret = 1, attempts = 5, port = snum; + int smallest_size = -1, smallest_port; struct inet_bind_hashbucket *head; - struct inet_bind_bucket *tb; - int ret, attempts = 5; struct net *net = sock_net(sk); - int smallest_size = -1, smallest_rover; + int i, low, high, attempt_half; + struct inet_bind_bucket *tb; kuid_t uid = sock_i_uid(sk); - int attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0; + u32 remaining, offset; - local_bh_disable(); - if (!snum) { - int remaining, rover, low, high; + if (port) { +have_port: + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); + inet_bind_bucket_for_each(tb, &head->chain) + if (net_eq(ib_net(tb), net) && tb->port == port) + goto tb_found; + goto tb_not_found; + } again: - inet_get_local_port_range(net, &low, &high); - if (attempt_half) { - int half = low + ((high - low) >> 1); - - if (attempt_half == 1) - high = half; - else - low = half; - } - remaining = (high - low) + 1; - smallest_rover = rover = prandom_u32() % remaining + low; - - smallest_size = -1; - do { - if (inet_is_local_reserved_port(net, rover)) - goto next_nolock; - head = &hashinfo->bhash[inet_bhashfn(net, rover, - hashinfo->bhash_size)]; - spin_lock(&head->lock); - inet_bind_bucket_for_each(tb, &head->chain) - if (net_eq(ib_net(tb), net) && tb->port == rover) { - if (((tb->fastreuse > 0 && - sk->sk_reuse && - sk->sk_state != TCP_LISTEN) || - (tb->fastreuseport > 0 && - sk->sk_reuseport && - !rcu_access_pointer(sk->sk_reuseport_cb) && - uid_eq(tb->fastuid, uid))) && - (tb->num_owners < smallest_size || smallest_size == -1)) { - smallest_size = tb->num_owners; - smallest_rover = rover; - } - if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false)) { - snum = rover; - goto tb_found; - } - goto next; + attempt_half = (sk->sk_reuse == SK_CAN_REUSE) ? 1 : 0; +other_half_scan: + inet_get_local_port_range(net, &low, &high); + high++; /* [32768, 60999] -> [32768, 61000[ */ + if (high - low < 4) + attempt_half = 0; + if (attempt_half) { + int half = low + (((high - low) >> 2) << 1); + + if (attempt_half == 1) + high = half; + else + low = half; + } + remaining = high - low; + if (likely(remaining > 1)) + remaining &= ~1U; + + offset = prandom_u32() % remaining; + /* __inet_hash_connect() favors ports having @low parity + * We do the opposite to not pollute connect() users. + */ + offset |= 1U; + smallest_size = -1; + smallest_port = low; /* avoid compiler warning */ + +other_parity_scan: + port = low + offset; + for (i = 0; i < remaining; i += 2, port += 2) { + if (unlikely(port >= high)) + port -= remaining; + if (inet_is_local_reserved_port(net, port)) + continue; + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); + inet_bind_bucket_for_each(tb, &head->chain) + if (net_eq(ib_net(tb), net) && tb->port == port) { + if (((tb->fastreuse > 0 && reuse) || + (tb->fastreuseport > 0 && + sk->sk_reuseport && + !rcu_access_pointer(sk->sk_reuseport_cb) && + uid_eq(tb->fastuid, uid))) && + (tb->num_owners < smallest_size || smallest_size == -1)) { + smallest_size = tb->num_owners; + smallest_port = port; } - break; - next: - spin_unlock(&head->lock); - next_nolock: - if (++rover > high) - rover = low; - } while (--remaining > 0); - - /* Exhausted local port range during search? It is not - * possible for us to be holding one of the bind hash - * locks if this test triggers, because if 'remaining' - * drops to zero, we broke out of the do/while loop at - * the top level, not from the 'break;' statement. - */ - ret = 1; - if (remaining <= 0) { - if (smallest_size != -1) { - snum = smallest_rover; - goto have_snum; + if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, false)) + goto tb_found; + goto next_port; } - if (attempt_half == 1) { - /* OK we now try the upper half of the range */ - attempt_half = 2; - goto again; - } - goto fail; - } - /* OK, here is the one we will use. HEAD is - * non-NULL and we hold it's mutex. - */ - snum = rover; - } else { -have_snum: - head = &hashinfo->bhash[inet_bhashfn(net, snum, - hashinfo->bhash_size)]; - spin_lock(&head->lock); - inet_bind_bucket_for_each(tb, &head->chain) - if (net_eq(ib_net(tb), net) && tb->port == snum) - goto tb_found; + goto tb_not_found; +next_port: + spin_unlock_bh(&head->lock); + cond_resched(); } - tb = NULL; - goto tb_not_found; + + if (smallest_size != -1) { + port = smallest_port; + goto have_port; + } + offset--; + if (!(offset & 1)) + goto other_parity_scan; + + if (attempt_half == 1) { + /* OK we now try the upper half of the range */ + attempt_half = 2; + goto other_half_scan; + } + return ret; + +tb_not_found: + tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, + net, head, port); + if (!tb) + goto fail_unlock; tb_found: if (!hlist_empty(&tb->owners)) { if (sk->sk_reuse == SK_FORCE_REUSE) goto success; - if (((tb->fastreuse > 0 && - sk->sk_reuse && sk->sk_state != TCP_LISTEN) || + if (((tb->fastreuse > 0 && reuse) || (tb->fastreuseport > 0 && - sk->sk_reuseport && - !rcu_access_pointer(sk->sk_reuseport_cb) && - uid_eq(tb->fastuid, uid))) && smallest_size == -1) { + sk->sk_reuseport && uid_eq(tb->fastuid, uid))) && + smallest_size == -1) goto success; - } else { - ret = 1; - if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) { - if (((sk->sk_reuse && sk->sk_state != TCP_LISTEN) || - (tb->fastreuseport > 0 && - sk->sk_reuseport && - !rcu_access_pointer(sk->sk_reuseport_cb) && - uid_eq(tb->fastuid, uid))) && - smallest_size != -1 && --attempts >= 0) { - spin_unlock(&head->lock); - goto again; - } - - goto fail_unlock; + if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) { + if ((reuse || + (tb->fastreuseport > 0 && + sk->sk_reuseport && + !rcu_access_pointer(sk->sk_reuseport_cb) && + uid_eq(tb->fastuid, uid))) && + smallest_size != -1 && --attempts >= 0) { + spin_unlock_bh(&head->lock); + goto again; } + goto fail_unlock; } - } -tb_not_found: - ret = 1; - if (!tb && (tb = inet_bind_bucket_create(hashinfo->bind_bucket_cachep, - net, head, snum)) == NULL) - goto fail_unlock; - if (hlist_empty(&tb->owners)) { - if (sk->sk_reuse && sk->sk_state != TCP_LISTEN) - tb->fastreuse = 1; - else + if (!reuse) tb->fastreuse = 0; + if (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid)) + tb->fastreuseport = 0; + } else { + tb->fastreuse = reuse; if (sk->sk_reuseport) { tb->fastreuseport = 1; tb->fastuid = uid; - } else - tb->fastreuseport = 0; - } else { - if (tb->fastreuse && - (!sk->sk_reuse || sk->sk_state == TCP_LISTEN)) - tb->fastreuse = 0; - if (tb->fastreuseport && - (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))) + } else { tb->fastreuseport = 0; + } } success: if (!inet_csk(sk)->icsk_bind_hash) - inet_bind_hash(sk, tb, snum); + inet_bind_hash(sk, tb, port); WARN_ON(inet_csk(sk)->icsk_bind_hash != tb); ret = 0; fail_unlock: - spin_unlock(&head->lock); -fail: - local_bh_enable(); + spin_unlock_bh(&head->lock); return ret; } EXPORT_SYMBOL_GPL(inet_csk_get_port); -- cgit From 179bc67f69b6cb53ad68cfdec5a917c2a2248355 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 20:48:04 +0000 Subject: net: local checksum offload for encapsulation The arithmetic properties of the ones-complement checksum mean that a correctly checksummed inner packet, including its checksum, has a ones complement sum depending only on whatever value was used to initialise the checksum field before checksumming (in the case of TCP and UDP, this is the ones complement sum of the pseudo header, complemented). Consequently, if we are going to offload the inner checksum with CHECKSUM_PARTIAL, we can compute the outer checksum based only on the packed data not covered by the inner checksum, and the initial value of the inner checksum field. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- include/linux/skbuff.h | 24 ++++++++++++++++++++++++ net/ipv4/ip_tunnel_core.c | 10 +++++----- net/ipv4/udp.c | 20 ++++++++++---------- net/ipv6/ip6_checksum.c | 14 +++++++------- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 6ec86f1a2ed9..cf906d1ce8a7 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3702,5 +3702,29 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) return hdr_len + skb_gso_transport_seglen(skb); } +/* Local Checksum Offload. + * Compute outer checksum based on the assumption that the + * inner checksum will be offloaded later. + * Fill in outer checksum adjustment (e.g. with sum of outer + * pseudo-header) before calling. + * Also ensure that inner checksum is in linear data area. + */ +static inline __wsum lco_csum(struct sk_buff *skb) +{ + char *inner_csum_field; + __wsum csum; + + /* Start with complement of inner checksum adjustment */ + inner_csum_field = skb->data + skb_checksum_start_offset(skb) + + skb->csum_offset; + csum = ~csum_unfold(*(__force __sum16 *)inner_csum_field); + /* Add in checksum of our headers (incl. outer checksum + * adjustment filled in by caller) + */ + csum = skb_checksum(skb, 0, skb_checksum_start_offset(skb), csum); + /* The result is the checksum from skb->data to end of packet */ + return csum; +} + #endif /* __KERNEL__ */ #endif /* _LINUX_SKBUFF_H */ diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 859d415c0b2d..d74ce93de1fe 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -166,20 +166,20 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, return skb; } - /* If packet is not gso and we are resolving any partial checksum, + /* If packet is not gso and we are not offloading inner checksum, * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL * on the outer header without confusing devices that implement * NETIF_F_IP_CSUM with encapsulation. */ - if (csum_help) - skb->encapsulation = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) { + skb->encapsulation = 0; err = skb_checksum_help(skb); if (unlikely(err)) goto error; - } else if (skb->ip_summed != CHECKSUM_PARTIAL) + } else if (skb->ip_summed != CHECKSUM_PARTIAL) { skb->ip_summed = CHECKSUM_NONE; + skb->encapsulation = 0; + } return skb; error: diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ac3cedb25a9f..a59341cf483e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -848,16 +848,18 @@ void udp_set_csum(bool nocheck, struct sk_buff *skb, { struct udphdr *uh = udp_hdr(skb); - if (nocheck) + if (nocheck) { uh->check = 0; - else if (skb_is_gso(skb)) + } else if (skb_is_gso(skb)) { uh->check = ~udp_v4_check(len, saddr, daddr, 0); - else if (skb_dst(skb) && skb_dst(skb)->dev && - (skb_dst(skb)->dev->features & - (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM))) { - - BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); - + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + uh->check = 0; + uh->check = udp_v4_check(len, saddr, daddr, lco_csum(skb)); + if (uh->check == 0) + uh->check = CSUM_MANGLED_0; + } else if (skb_dst(skb) && skb_dst(skb)->dev && + (skb_dst(skb)->dev->features & + (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM))) { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_transport_header(skb) - skb->head; skb->csum_offset = offsetof(struct udphdr, check); @@ -865,8 +867,6 @@ void udp_set_csum(bool nocheck, struct sk_buff *skb, } else { __wsum csum; - BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); - uh->check = 0; csum = skb_checksum(skb, 0, len, 0); uh->check = udp_v4_check(len, saddr, daddr, csum); diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c index 9a4d7322fb22..4924bd704e89 100644 --- a/net/ipv6/ip6_checksum.c +++ b/net/ipv6/ip6_checksum.c @@ -98,11 +98,13 @@ void udp6_set_csum(bool nocheck, struct sk_buff *skb, uh->check = 0; else if (skb_is_gso(skb)) uh->check = ~udp_v6_check(len, saddr, daddr, 0); - else if (skb_dst(skb) && skb_dst(skb)->dev && - (skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) { - - BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); - + else if (skb->ip_summed == CHECKSUM_PARTIAL) { + uh->check = 0; + uh->check = udp_v6_check(len, saddr, daddr, lco_csum(skb)); + if (uh->check == 0) + uh->check = CSUM_MANGLED_0; + } else if (skb_dst(skb) && skb_dst(skb)->dev && + (skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_transport_header(skb) - skb->head; skb->csum_offset = offsetof(struct udphdr, check); @@ -110,8 +112,6 @@ void udp6_set_csum(bool nocheck, struct sk_buff *skb, } else { __wsum csum; - BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); - uh->check = 0; csum = skb_checksum(skb, 0, len, 0); uh->check = udp_v6_check(len, saddr, daddr, csum); -- cgit From d75f1306d9464d535007f05e5da0afcf9e3916d9 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 20:49:40 +0000 Subject: net: udp: always set up for CHECKSUM_PARTIAL offload If the dst device doesn't support it, it'll get fixed up later anyway by validate_xmit_skb(). Also, this allows us to take advantage of LCO to avoid summing the payload multiple times. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- net/ipv4/udp.c | 14 +------------- net/ipv6/ip6_checksum.c | 13 +------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index a59341cf483e..9fc4e9c06aae 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -857,23 +857,11 @@ void udp_set_csum(bool nocheck, struct sk_buff *skb, uh->check = udp_v4_check(len, saddr, daddr, lco_csum(skb)); if (uh->check == 0) uh->check = CSUM_MANGLED_0; - } else if (skb_dst(skb) && skb_dst(skb)->dev && - (skb_dst(skb)->dev->features & - (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM))) { + } else { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_transport_header(skb) - skb->head; skb->csum_offset = offsetof(struct udphdr, check); uh->check = ~udp_v4_check(len, saddr, daddr, 0); - } else { - __wsum csum; - - uh->check = 0; - csum = skb_checksum(skb, 0, len, 0); - uh->check = udp_v4_check(len, saddr, daddr, csum); - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; - - skb->ip_summed = CHECKSUM_UNNECESSARY; } } EXPORT_SYMBOL(udp_set_csum); diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c index 4924bd704e89..8f920580976f 100644 --- a/net/ipv6/ip6_checksum.c +++ b/net/ipv6/ip6_checksum.c @@ -103,22 +103,11 @@ void udp6_set_csum(bool nocheck, struct sk_buff *skb, uh->check = udp_v6_check(len, saddr, daddr, lco_csum(skb)); if (uh->check == 0) uh->check = CSUM_MANGLED_0; - } else if (skb_dst(skb) && skb_dst(skb)->dev && - (skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) { + } else { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = skb_transport_header(skb) - skb->head; skb->csum_offset = offsetof(struct udphdr, check); uh->check = ~udp_v6_check(len, saddr, daddr, 0); - } else { - __wsum csum; - - uh->check = 0; - csum = skb_checksum(skb, 0, len, 0); - uh->check = udp_v6_check(len, saddr, daddr, csum); - if (uh->check == 0) - uh->check = CSUM_MANGLED_0; - - skb->ip_summed = CHECKSUM_UNNECESSARY; } } EXPORT_SYMBOL(udp6_set_csum); -- cgit From 21e2e7f9b5fefdbf94a107a9b24d74baa5148ef3 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 20:50:44 +0000 Subject: net: enable LCO for udp_tunnel_handle_offloads() users The only protocol affected at present is Geneve. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- include/net/udp_tunnel.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index cca2ad3082c3..734c15662ea9 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -103,7 +103,8 @@ static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, { int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; - return iptunnel_handle_offloads(skb, udp_csum, type); + /* As we're a UDP tunnel, we support LCO, so don't need csum_help */ + return iptunnel_handle_offloads(skb, false, type); } static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff) -- cgit From b57085019dcdd52d40ba153c6957f9e5a2f4b931 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 20:57:17 +0000 Subject: net: vxlan: enable local checksum offload Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index ebf57d90d295..9f52203ac860 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1702,10 +1702,8 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, if (csum_start <= VXLAN_MAX_REMCSUM_START && !(csum_start & VXLAN_RCO_SHIFT_MASK) && (skb->csum_offset == offsetof(struct udphdr, check) || - skb->csum_offset == offsetof(struct tcphdr, check))) { - udp_sum = false; + skb->csum_offset == offsetof(struct tcphdr, check))) type |= SKB_GSO_TUNNEL_REMCSUM; - } } min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len @@ -1723,7 +1721,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, if (WARN_ON(!skb)) return -ENOMEM; - skb = iptunnel_handle_offloads(skb, udp_sum, type); + skb = iptunnel_handle_offloads(skb, false, type); if (IS_ERR(skb)) return PTR_ERR(skb); -- cgit From 06f622926d0cdf923e9b33ab9f0a4d4b45983e8a Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 21:00:16 +0000 Subject: fou: enable LCO in FOU and GUE Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- net/ipv4/fou.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 976f0dcf6991..dac1874a5911 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -774,7 +774,6 @@ static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e, uh->dest = e->dport; uh->source = sport; uh->len = htons(skb->len); - uh->check = 0; udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb, fl4->saddr, fl4->daddr, skb->len); @@ -784,11 +783,11 @@ static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e, int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, u8 *protocol, struct flowi4 *fl4) { - bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM); - int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; + int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : + SKB_GSO_UDP_TUNNEL; __be16 sport; - skb = iptunnel_handle_offloads(skb, csum, type); + skb = iptunnel_handle_offloads(skb, false, type); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -804,8 +803,8 @@ EXPORT_SYMBOL(fou_build_header); int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, u8 *protocol, struct flowi4 *fl4) { - bool csum = !!(e->flags & TUNNEL_ENCAP_FLAG_CSUM); - int type = csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; + int type = e->flags & TUNNEL_ENCAP_FLAG_CSUM ? SKB_GSO_UDP_TUNNEL_CSUM : + SKB_GSO_UDP_TUNNEL; struct guehdr *guehdr; size_t hdrlen, optlen = 0; __be16 sport; @@ -814,7 +813,6 @@ int gue_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, if ((e->flags & TUNNEL_ENCAP_FLAG_REMCSUM) && skb->ip_summed == CHECKSUM_PARTIAL) { - csum = false; optlen += GUE_PLEN_REMCSUM; type |= SKB_GSO_TUNNEL_REMCSUM; need_priv = true; @@ -822,7 +820,7 @@ 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, csum, type); + skb = iptunnel_handle_offloads(skb, false, type); if (IS_ERR(skb)) return PTR_ERR(skb); -- cgit From 53936107ba2462f714bae19a754f3ebf69a11e40 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 21:01:07 +0000 Subject: net: gre: Implement LCO for GRE over IPv4 Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7c51c4e1661f..9b31532d95f4 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -440,6 +440,17 @@ drop: return 0; } +static __sum16 gre_checksum(struct sk_buff *skb) +{ + __wsum csum; + + if (skb->ip_summed == CHECKSUM_PARTIAL) + csum = lco_csum(skb); + else + csum = skb_checksum(skb, 0, skb->len, 0); + return csum_fold(csum); +} + static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags, __be16 proto, __be32 key, __be32 seq) { @@ -467,8 +478,7 @@ static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags, !(skb_shinfo(skb)->gso_type & (SKB_GSO_GRE | SKB_GSO_GRE_CSUM))) { *ptr = 0; - *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, - skb->len, 0)); + *(__sum16 *)ptr = gre_checksum(skb); } } } @@ -493,7 +503,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool csum) { - return iptunnel_handle_offloads(skb, csum, + return iptunnel_handle_offloads(skb, false, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); } -- cgit From 6fa79666e24d32be1b709f5269af41ed9e829e7e Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 21:02:31 +0000 Subject: net: ip_tunnel: remove 'csum_help' argument to iptunnel_handle_offloads All users now pass false, so we can remove it, and remove the code that was conditional upon it. Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 2 +- include/net/ip_tunnels.h | 3 +-- include/net/udp_tunnel.h | 3 +-- net/ipv4/fou.c | 4 ++-- net/ipv4/ip_gre.c | 3 +-- net/ipv4/ip_tunnel_core.c | 18 ++++++------------ net/ipv4/ipip.c | 2 +- net/ipv6/sit.c | 4 ++-- net/netfilter/ipvs/ip_vs_xmit.c | 6 ++---- 9 files changed, 17 insertions(+), 28 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 9f52203ac860..0a23c64379d6 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1721,7 +1721,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, if (WARN_ON(!skb)) return -ENOMEM; - skb = iptunnel_handle_offloads(skb, false, type); + skb = iptunnel_handle_offloads(skb, type); if (IS_ERR(skb)) return PTR_ERR(skb); diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 6db96ea0144f..bc439f32baa9 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -279,8 +279,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, bool gre_csum, - int gso_type_mask); +struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, int gso_type_mask); static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) { diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 734c15662ea9..97f5adb121a6 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -103,8 +103,7 @@ static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, { int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; - /* As we're a UDP tunnel, we support LCO, so don't need csum_help */ - return iptunnel_handle_offloads(skb, false, type); + return iptunnel_handle_offloads(skb, type); } static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff) diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index dac1874a5911..88dab0c1670c 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -787,7 +787,7 @@ int fou_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e, SKB_GSO_UDP_TUNNEL; __be16 sport; - skb = iptunnel_handle_offloads(skb, false, type); + skb = iptunnel_handle_offloads(skb, type); if (IS_ERR(skb)) return PTR_ERR(skb); @@ -820,7 +820,7 @@ 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, false, type); + skb = iptunnel_handle_offloads(skb, type); if (IS_ERR(skb)) return PTR_ERR(skb); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 9b31532d95f4..65748db44285 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -503,8 +503,7 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool csum) { - return iptunnel_handle_offloads(skb, false, - csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); + return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE); } static struct rtable *gre_get_rt(struct sk_buff *skb, diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index d74ce93de1fe..a6e58b6141cd 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c @@ -148,7 +148,6 @@ 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, - bool csum_help, int gso_type_mask) { int err; @@ -166,18 +165,13 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, return skb; } - /* If packet is not gso and we are not offloading inner checksum, - * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL - * on the outer header without confusing devices that implement - * NETIF_F_IP_CSUM with encapsulation. - */ - if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) { - skb->encapsulation = 0; - err = skb_checksum_help(skb); - if (unlikely(err)) - goto error; - } else if (skb->ip_summed != CHECKSUM_PARTIAL) { + if (skb->ip_summed != CHECKSUM_PARTIAL) { skb->ip_summed = CHECKSUM_NONE; + /* We clear encapsulation here to prevent badly-written + * drivers potentially deciding to offload an inner checksum + * if we set CHECKSUM_PARTIAL on the outer header. + * This should go away when the drivers are all fixed. + */ skb->encapsulation = 0; } diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 4044da61e747..6ec5b42fd172 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -219,7 +219,7 @@ 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, false, SKB_GSO_IPIP); + skb = iptunnel_handle_offloads(skb, SKB_GSO_IPIP); if (IS_ERR(skb)) goto out; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 2066d1c25a11..9a6b407f5840 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -911,7 +911,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, goto tx_error; } - skb = iptunnel_handle_offloads(skb, false, SKB_GSO_SIT); + skb = iptunnel_handle_offloads(skb, SKB_GSO_SIT); if (IS_ERR(skb)) { ip_rt_put(rt); goto out; @@ -1000,7 +1000,7 @@ 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, false, SKB_GSO_IPIP); + skb = iptunnel_handle_offloads(skb, SKB_GSO_IPIP); if (IS_ERR(skb)) goto out; diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 3264cb49b333..a3f5cd9b3c4c 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -1019,8 +1019,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, false, __tun_gso_type_mask(AF_INET, cp->af)); + skb = iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET, cp->af)); if (IS_ERR(skb)) goto tx_error; @@ -1112,8 +1111,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, false, __tun_gso_type_mask(AF_INET6, cp->af)); + skb = iptunnel_handle_offloads(skb, __tun_gso_type_mask(AF_INET6, cp->af)); if (IS_ERR(skb)) goto tx_error; -- cgit From e8ae7b000e64cf76283c72cae5e3ecd246618ef4 Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Thu, 11 Feb 2016 21:03:37 +0000 Subject: Documentation/networking: add checksum-offloads.txt to explain LCO Signed-off-by: Edward Cree Signed-off-by: David S. Miller --- Documentation/networking/00-INDEX | 2 + Documentation/networking/checksum-offloads.txt | 119 +++++++++++++++++++++++++ include/linux/skbuff.h | 2 + 3 files changed, 123 insertions(+) create mode 100644 Documentation/networking/checksum-offloads.txt diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index df27a1a50776..415154a487d0 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -44,6 +44,8 @@ can.txt - documentation on CAN protocol family. cdc_mbim.txt - 3G/LTE USB modem (Mobile Broadband Interface Model) +checksum-offloads.txt + - Explanation of checksum offloads; LCO, RCO cops.txt - info on the COPS LocalTalk Linux driver cs89x0.txt diff --git a/Documentation/networking/checksum-offloads.txt b/Documentation/networking/checksum-offloads.txt new file mode 100644 index 000000000000..de2a327766a7 --- /dev/null +++ b/Documentation/networking/checksum-offloads.txt @@ -0,0 +1,119 @@ +Checksum Offloads in the Linux Networking Stack + + +Introduction +============ + +This document describes a set of techniques in the Linux networking stack + to take advantage of checksum offload capabilities of various NICs. + +The following technologies are described: + * TX Checksum Offload + * LCO: Local Checksum Offload + * RCO: Remote Checksum Offload + +Things that should be documented here but aren't yet: + * RX Checksum Offload + * CHECKSUM_UNNECESSARY conversion + + +TX Checksum Offload +=================== + +The interface for offloading a transmit checksum to a device is explained + in detail in comments near the top of include/linux/skbuff.h. +In brief, it allows to request the device fill in a single ones-complement + checksum defined by the sk_buff fields skb->csum_start and + skb->csum_offset. The device should compute the 16-bit ones-complement + checksum (i.e. the 'IP-style' checksum) from csum_start to the end of the + packet, and fill in the result at (csum_start + csum_offset). +Because csum_offset cannot be negative, this ensures that the previous + value of the checksum field is included in the checksum computation, thus + it can be used to supply any needed corrections to the checksum (such as + the sum of the pseudo-header for UDP or TCP). +This interface only allows a single checksum to be offloaded. Where + encapsulation is used, the packet may have multiple checksum fields in + different header layers, and the rest will have to be handled by another + mechanism such as LCO or RCO. +No offloading of the IP header checksum is performed; it is always done in + software. This is OK because when we build the IP header, we obviously + have it in cache, so summing it isn't expensive. It's also rather short. +The requirements for GSO are more complicated, because when segmenting an + encapsulated packet both the inner and outer checksums may need to be + edited or recomputed for each resulting segment. See the skbuff.h comment + (section 'E') for more details. + +A driver declares its offload capabilities in netdev->hw_features; see + Documentation/networking/netdev-features for more. Note that a device + which only advertises NETIF_F_IP[V6]_CSUM must still obey the csum_start + and csum_offset given in the SKB; if it tries to deduce these itself in + hardware (as some NICs do) the driver should check that the values in the + SKB match those which the hardware will deduce, and if not, fall back to + checksumming in software instead (with skb_checksum_help or one of the + skb_csum_off_chk* functions as mentioned in include/linux/skbuff.h). This + is a pain, but that's what you get when hardware tries to be clever. + +The stack should, for the most part, assume that checksum offload is + supported by the underlying device. The only place that should check is + validate_xmit_skb(), and the functions it calls directly or indirectly. + That function compares the offload features requested by the SKB (which + may include other offloads besides TX Checksum Offload) and, if they are + not supported or enabled on the device (determined by netdev->features), + performs the corresponding offload in software. In the case of TX + Checksum Offload, that means calling skb_checksum_help(skb). + + +LCO: Local Checksum Offload +=========================== + +LCO is a technique for efficiently computing the outer checksum of an + encapsulated datagram when the inner checksum is due to be offloaded. +The ones-complement sum of a correctly checksummed TCP or UDP packet is + equal to the sum of the pseudo header, because everything else gets + 'cancelled out' by the checksum field. This is because the sum was + complemented before being written to the checksum field. +More generally, this holds in any case where the 'IP-style' ones complement + checksum is used, and thus any checksum that TX Checksum Offload supports. +That is, if we have set up TX Checksum Offload with a start/offset pair, we + know that _after the device has filled in that checksum_, the ones + complement sum from csum_start to the end of the packet will be equal to + _whatever value we put in the checksum field beforehand_. This allows us + to compute the outer checksum without looking at the payload: we simply + stop summing when we get to csum_start, then add the 16-bit word at + (csum_start + csum_offset). +Then, when the true inner checksum is filled in (either by hardware or by + skb_checksum_help()), the outer checksum will become correct by virtue of + the arithmetic. + +LCO is performed by the stack when constructing an outer UDP header for an + encapsulation such as VXLAN or GENEVE, in udp_set_csum(). Similarly for + the IPv6 equivalents, in udp6_set_csum(). +It is also performed when constructing an IPv4 GRE header, in + net/ipv4/ip_gre.c:build_header(). It is *not* currently performed when + constructing an IPv6 GRE header; the GRE checksum is computed over the + whole packet in net/ipv6/ip6_gre.c:ip6gre_xmit2(), but it should be + possible to use LCO here as IPv6 GRE still uses an IP-style checksum. +All of the LCO implementations use a helper function lco_csum(), in + include/linux/skbuff.h. + +LCO can safely be used for nested encapsulations; in this case, the outer + encapsulation layer will sum over both its own header and the 'middle' + header. This does mean that the 'middle' header will get summed multiple + times, but there doesn't seem to be a way to avoid that without incurring + bigger costs (e.g. in SKB bloat). + + +RCO: Remote Checksum Offload +============================ + +RCO is a technique for eliding the inner checksum of an encapsulated + datagram, allowing the outer checksum to be offloaded. It does, however, + involve a change to the encapsulation protocols, which the receiver must + also support. For this reason, it is disabled by default. +RCO is detailed in the following Internet-Drafts: +https://tools.ietf.org/html/draft-herbert-remotecsumoffload-00 +https://tools.ietf.org/html/draft-herbert-vxlan-rco-00 +In Linux, RCO is implemented individually in each encapsulation protocol, + and most tunnel types have flags controlling its use. For instance, VXLAN + has the flag VXLAN_F_REMCSUM_TX (per struct vxlan_rdst) to indicate that + RCO should be used when transmitting to a given remote destination. diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index cf906d1ce8a7..39206751463e 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3705,6 +3705,8 @@ static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) /* Local Checksum Offload. * Compute outer checksum based on the assumption that the * inner checksum will be offloaded later. + * See Documentation/networking/checksum-offloads.txt for + * explanation of how this works. * Fill in outer checksum adjustment (e.g. with sum of outer * pseudo-header) before calling. * Also ensure that inner checksum is in linear data area. -- cgit From 96173cc6a4c4fca5a3a83e942b09474f791c395a Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Fri, 12 Feb 2016 01:14:23 -0300 Subject: regulator: Rename files for max77686 and max77802 drivers The max77686 and max77802 regulator drivers are for sub-devices of a MFD driver for some PMIC blocks. But the same object file name (max77686.o) was used for both the common MFD driver and the max77686 regulator one. This confuses kbuild if both drivers are built as module causing the MFD driver to not be copied when installing the modules. Also, max77{686,802} are a quite generic name for MFD subdevices drivers so it is better to rename them to max77{686,802}-regulator like it's the case for most regulator drivers. Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- drivers/regulator/Makefile | 4 +- drivers/regulator/max77686-regulator.c | 570 ++++++++++++++++++++++++++++++ drivers/regulator/max77686.c | 570 ------------------------------ drivers/regulator/max77802-regulator.c | 610 +++++++++++++++++++++++++++++++++ drivers/regulator/max77802.c | 610 --------------------------------- 6 files changed, 1183 insertions(+), 1183 deletions(-) create mode 100644 drivers/regulator/max77686-regulator.c delete mode 100644 drivers/regulator/max77686.c create mode 100644 drivers/regulator/max77802-regulator.c delete mode 100644 drivers/regulator/max77802.c diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..1d88035630cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6903,7 +6903,7 @@ MAXIM MAX77802 MULTIFUNCTION PMIC DEVICE DRIVERS M: Javier Martinez Canillas L: linux-kernel@vger.kernel.org S: Supported -F: drivers/*/*max77802.c +F: drivers/*/*max77802*.c F: Documentation/devicetree/bindings/*/*max77802.txt F: include/dt-bindings/*/*max77802.h diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 980b1943fa81..a8c07a079996 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -54,9 +54,9 @@ obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o -obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o +obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o -obj-$(CONFIG_REGULATOR_MAX77802) += max77802.o +obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o diff --git a/drivers/regulator/max77686-regulator.c b/drivers/regulator/max77686-regulator.c new file mode 100644 index 000000000000..17ccf365a9c0 --- /dev/null +++ b/drivers/regulator/max77686-regulator.c @@ -0,0 +1,570 @@ +/* + * max77686.c - Regulator driver for the Maxim 77686 + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun + * 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 + * 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 + * + * This driver is based on max8997.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX77686_LDO_MINUV 800000 +#define MAX77686_LDO_UVSTEP 50000 +#define MAX77686_LDO_LOW_MINUV 800000 +#define MAX77686_LDO_LOW_UVSTEP 25000 +#define MAX77686_BUCK_MINUV 750000 +#define MAX77686_BUCK_UVSTEP 50000 +#define MAX77686_RAMP_DELAY 100000 /* uV/us */ +#define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */ +#define MAX77686_DVS_MINUV 600000 +#define MAX77686_DVS_UVSTEP 12500 + +/* + * Value for configuring buck[89] and LDO{20,21,22} as GPIO control. + * It is the same as 'off' for other regulators. + */ +#define MAX77686_GPIO_CONTROL 0x0 +/* + * Values used for configuring LDOs and bucks. + * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26 + */ +#define MAX77686_LDO_LOWPOWER 0x1 +/* + * On/off controlled by PWRREQ: + * - LDO2, 6-8, 10-12, 14-16 + * - buck[1234] + */ +#define MAX77686_OFF_PWRREQ 0x1 +/* Low power mode controlled by PWRREQ: All LDOs */ +#define MAX77686_LDO_LOWPOWER_PWRREQ 0x2 +/* Forcing low power mode: buck[234] */ +#define MAX77686_BUCK_LOWPOWER 0x2 +#define MAX77686_NORMAL 0x3 + +#define MAX77686_OPMODE_SHIFT 6 +#define MAX77686_OPMODE_BUCK234_SHIFT 4 +#define MAX77686_OPMODE_MASK 0x3 + +#define MAX77686_VSEL_MASK 0x3F +#define MAX77686_DVS_VSEL_MASK 0xFF + +#define MAX77686_RAMP_RATE_MASK 0xC0 + +#define MAX77686_REGULATORS MAX77686_REG_MAX +#define MAX77686_LDOS 26 + +enum max77686_ramp_rate { + RAMP_RATE_13P75MV, + RAMP_RATE_27P5MV, + RAMP_RATE_55MV, + RAMP_RATE_NO_CTRL, /* 100mV/us */ +}; + +struct max77686_data { + DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS); + + /* Array indexed by regulator id */ + unsigned int opmode[MAX77686_REGULATORS]; +}; + +static unsigned int max77686_get_opmode_shift(int id) +{ + switch (id) { + case MAX77686_BUCK1: + case MAX77686_BUCK5 ... MAX77686_BUCK9: + return 0; + case MAX77686_BUCK2 ... MAX77686_BUCK4: + return MAX77686_OPMODE_BUCK234_SHIFT; + default: + /* all LDOs */ + return MAX77686_OPMODE_SHIFT; + } +} + +/* + * When regulator is configured for GPIO control then it + * replaces "normal" mode. Any change from low power mode to normal + * should actually change to GPIO control. + * Map normal mode to proper value for such regulators. + */ +static unsigned int max77686_map_normal_mode(struct max77686_data *max77686, + int id) +{ + switch (id) { + case MAX77686_BUCK8: + case MAX77686_BUCK9: + case MAX77686_LDO20 ... MAX77686_LDO22: + if (test_bit(id, max77686->gpio_enabled)) + return MAX77686_GPIO_CONTROL; + } + + return MAX77686_NORMAL; +} + +/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ +static int max77686_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int val, shift; + struct max77686_data *max77686 = rdev_get_drvdata(rdev); + int ret, id = rdev_get_id(rdev); + + shift = max77686_get_opmode_shift(id); + val = MAX77686_OFF_PWRREQ; + + ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); + if (ret) + return ret; + + max77686->opmode[id] = val; + return 0; +} + +/* Some LDOs supports [LPM/Normal]ON mode during suspend state */ +static int max77686_set_suspend_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct max77686_data *max77686 = rdev_get_drvdata(rdev); + unsigned int val; + int ret, id = rdev_get_id(rdev); + + /* BUCK[5-9] doesn't support this feature */ + if (id >= MAX77686_BUCK5) + return 0; + + switch (mode) { + case REGULATOR_MODE_IDLE: /* ON in LP Mode */ + val = MAX77686_LDO_LOWPOWER_PWRREQ; + break; + case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ + val = max77686_map_normal_mode(max77686, id); + break; + default: + pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", + rdev->desc->name, mode); + return -EINVAL; + } + + ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + val << MAX77686_OPMODE_SHIFT); + if (ret) + return ret; + + max77686->opmode[id] = val; + return 0; +} + +/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */ +static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + unsigned int val; + struct max77686_data *max77686 = rdev_get_drvdata(rdev); + int ret, id = rdev_get_id(rdev); + + switch (mode) { + case REGULATOR_MODE_STANDBY: /* switch off */ + val = MAX77686_OFF_PWRREQ; + break; + case REGULATOR_MODE_IDLE: /* ON in LP Mode */ + val = MAX77686_LDO_LOWPOWER_PWRREQ; + break; + case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ + val = max77686_map_normal_mode(max77686, id); + break; + default: + pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", + rdev->desc->name, mode); + return -EINVAL; + } + + ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + val << MAX77686_OPMODE_SHIFT); + if (ret) + return ret; + + max77686->opmode[id] = val; + return 0; +} + +static int max77686_enable(struct regulator_dev *rdev) +{ + struct max77686_data *max77686 = rdev_get_drvdata(rdev); + unsigned int shift; + int id = rdev_get_id(rdev); + + shift = max77686_get_opmode_shift(id); + + if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) + max77686->opmode[id] = max77686_map_normal_mode(max77686, id); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + max77686->opmode[id] << shift); +} + +static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + unsigned int ramp_value = RAMP_RATE_NO_CTRL; + + switch (ramp_delay) { + case 1 ... 13750: + ramp_value = RAMP_RATE_13P75MV; + break; + case 13751 ... 27500: + ramp_value = RAMP_RATE_27P5MV; + break; + case 27501 ... 55000: + ramp_value = RAMP_RATE_55MV; + break; + case 55001 ... 100000: + break; + default: + pr_warn("%s: ramp_delay: %d not supported, setting 100000\n", + rdev->desc->name, ramp_delay); + } + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77686_RAMP_RATE_MASK, ramp_value << 6); +} + +static int max77686_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *config) +{ + struct max77686_data *max77686 = config->driver_data; + + switch (desc->id) { + case MAX77686_BUCK8: + case MAX77686_BUCK9: + case MAX77686_LDO20 ... MAX77686_LDO22: + config->ena_gpio = of_get_named_gpio(np, + "maxim,ena-gpios", 0); + config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH; + config->ena_gpio_initialized = true; + break; + default: + return 0; + } + + if (gpio_is_valid(config->ena_gpio)) { + set_bit(desc->id, max77686->gpio_enabled); + + return regmap_update_bits(config->regmap, desc->enable_reg, + desc->enable_mask, + MAX77686_GPIO_CONTROL); + } + + return 0; +} + +static struct regulator_ops max77686_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77686_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_mode = max77686_set_suspend_mode, +}; + +static struct regulator_ops max77686_ldo_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77686_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_mode = max77686_ldo_set_suspend_mode, + .set_suspend_disable = max77686_set_suspend_disable, +}; + +static struct regulator_ops max77686_buck1_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77686_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_disable = max77686_set_suspend_disable, +}; + +static struct regulator_ops max77686_buck_dvs_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77686_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77686_set_ramp_delay, + .set_suspend_disable = max77686_set_suspend_disable, +}; + +#define regulator_desc_ldo(num) { \ + .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .of_parse_cb = max77686_of_parse_cb, \ + .id = MAX77686_LDO##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_LDO_MINUV, \ + .uV_step = MAX77686_LDO_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_SHIFT, \ +} +#define regulator_desc_lpm_ldo(num) { \ + .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .id = MAX77686_LDO##num, \ + .ops = &max77686_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_LDO_MINUV, \ + .uV_step = MAX77686_LDO_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_SHIFT, \ +} +#define regulator_desc_ldo_low(num) { \ + .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .id = MAX77686_LDO##num, \ + .ops = &max77686_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_LDO_LOW_MINUV, \ + .uV_step = MAX77686_LDO_LOW_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_SHIFT, \ +} +#define regulator_desc_ldo1_low(num) { \ + .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .id = MAX77686_LDO##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_LDO_LOW_MINUV, \ + .uV_step = MAX77686_LDO_LOW_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_SHIFT, \ +} +#define regulator_desc_buck(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .of_parse_cb = max77686_of_parse_cb, \ + .id = MAX77686_BUCK##num, \ + .ops = &max77686_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_BUCK_MINUV, \ + .uV_step = MAX77686_BUCK_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \ + .enable_mask = MAX77686_OPMODE_MASK, \ +} +#define regulator_desc_buck1(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .id = MAX77686_BUCK##num, \ + .ops = &max77686_buck1_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_BUCK_MINUV, \ + .uV_step = MAX77686_BUCK_UVSTEP, \ + .ramp_delay = MAX77686_RAMP_DELAY, \ + .n_voltages = MAX77686_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_BUCK1OUT, \ + .vsel_mask = MAX77686_VSEL_MASK, \ + .enable_reg = MAX77686_REG_BUCK1CTRL, \ + .enable_mask = MAX77686_OPMODE_MASK, \ +} +#define regulator_desc_buck_dvs(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("voltage-regulators"), \ + .id = MAX77686_BUCK##num, \ + .ops = &max77686_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = MAX77686_DVS_MINUV, \ + .uV_step = MAX77686_DVS_UVSTEP, \ + .ramp_delay = MAX77686_DVS_RAMP_DELAY, \ + .n_voltages = MAX77686_DVS_VSEL_MASK + 1, \ + .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \ + .vsel_mask = MAX77686_DVS_VSEL_MASK, \ + .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \ + .enable_mask = MAX77686_OPMODE_MASK \ + << MAX77686_OPMODE_BUCK234_SHIFT, \ +} + +static const struct regulator_desc regulators[] = { + regulator_desc_ldo1_low(1), + regulator_desc_ldo_low(2), + regulator_desc_ldo(3), + regulator_desc_ldo(4), + regulator_desc_ldo(5), + regulator_desc_ldo_low(6), + regulator_desc_ldo_low(7), + regulator_desc_ldo_low(8), + regulator_desc_ldo(9), + regulator_desc_lpm_ldo(10), + regulator_desc_lpm_ldo(11), + regulator_desc_lpm_ldo(12), + regulator_desc_ldo(13), + regulator_desc_lpm_ldo(14), + regulator_desc_ldo_low(15), + regulator_desc_lpm_ldo(16), + regulator_desc_ldo(17), + regulator_desc_ldo(18), + regulator_desc_ldo(19), + regulator_desc_ldo(20), + regulator_desc_ldo(21), + regulator_desc_ldo(22), + regulator_desc_ldo(23), + regulator_desc_ldo(24), + regulator_desc_ldo(25), + regulator_desc_ldo(26), + regulator_desc_buck1(1), + regulator_desc_buck_dvs(2), + regulator_desc_buck_dvs(3), + regulator_desc_buck_dvs(4), + regulator_desc_buck(5), + regulator_desc_buck(6), + regulator_desc_buck(7), + regulator_desc_buck(8), + regulator_desc_buck(9), +}; + +static int max77686_pmic_probe(struct platform_device *pdev) +{ + struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct max77686_data *max77686; + int i; + struct regulator_config config = { }; + + dev_dbg(&pdev->dev, "%s\n", __func__); + + max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), + GFP_KERNEL); + if (!max77686) + return -ENOMEM; + + config.dev = iodev->dev; + config.regmap = iodev->regmap; + config.driver_data = max77686; + platform_set_drvdata(pdev, max77686); + + for (i = 0; i < MAX77686_REGULATORS; i++) { + struct regulator_dev *rdev; + int id = regulators[i].id; + + max77686->opmode[id] = MAX77686_NORMAL; + rdev = devm_regulator_register(&pdev->dev, + ®ulators[i], &config); + if (IS_ERR(rdev)) { + int ret = PTR_ERR(rdev); + dev_err(&pdev->dev, + "regulator init failed for %d: %d\n", i, ret); + return ret; + } + } + + return 0; +} + +static const struct platform_device_id max77686_pmic_id[] = { + {"max77686-pmic", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, max77686_pmic_id); + +static struct platform_driver max77686_pmic_driver = { + .driver = { + .name = "max77686-pmic", + }, + .probe = max77686_pmic_probe, + .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_DESCRIPTION("MAXIM 77686 Regulator Driver"); +MODULE_AUTHOR("Chiwoong Byun "); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c deleted file mode 100644 index 17ccf365a9c0..000000000000 --- a/drivers/regulator/max77686.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * max77686.c - Regulator driver for the Maxim 77686 - * - * Copyright (C) 2012 Samsung Electronics - * Chiwoong Byun - * 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 - * 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 - * - * This driver is based on max8997.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX77686_LDO_MINUV 800000 -#define MAX77686_LDO_UVSTEP 50000 -#define MAX77686_LDO_LOW_MINUV 800000 -#define MAX77686_LDO_LOW_UVSTEP 25000 -#define MAX77686_BUCK_MINUV 750000 -#define MAX77686_BUCK_UVSTEP 50000 -#define MAX77686_RAMP_DELAY 100000 /* uV/us */ -#define MAX77686_DVS_RAMP_DELAY 27500 /* uV/us */ -#define MAX77686_DVS_MINUV 600000 -#define MAX77686_DVS_UVSTEP 12500 - -/* - * Value for configuring buck[89] and LDO{20,21,22} as GPIO control. - * It is the same as 'off' for other regulators. - */ -#define MAX77686_GPIO_CONTROL 0x0 -/* - * Values used for configuring LDOs and bucks. - * Forcing low power mode: LDO1, 3-5, 9, 13, 17-26 - */ -#define MAX77686_LDO_LOWPOWER 0x1 -/* - * On/off controlled by PWRREQ: - * - LDO2, 6-8, 10-12, 14-16 - * - buck[1234] - */ -#define MAX77686_OFF_PWRREQ 0x1 -/* Low power mode controlled by PWRREQ: All LDOs */ -#define MAX77686_LDO_LOWPOWER_PWRREQ 0x2 -/* Forcing low power mode: buck[234] */ -#define MAX77686_BUCK_LOWPOWER 0x2 -#define MAX77686_NORMAL 0x3 - -#define MAX77686_OPMODE_SHIFT 6 -#define MAX77686_OPMODE_BUCK234_SHIFT 4 -#define MAX77686_OPMODE_MASK 0x3 - -#define MAX77686_VSEL_MASK 0x3F -#define MAX77686_DVS_VSEL_MASK 0xFF - -#define MAX77686_RAMP_RATE_MASK 0xC0 - -#define MAX77686_REGULATORS MAX77686_REG_MAX -#define MAX77686_LDOS 26 - -enum max77686_ramp_rate { - RAMP_RATE_13P75MV, - RAMP_RATE_27P5MV, - RAMP_RATE_55MV, - RAMP_RATE_NO_CTRL, /* 100mV/us */ -}; - -struct max77686_data { - DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS); - - /* Array indexed by regulator id */ - unsigned int opmode[MAX77686_REGULATORS]; -}; - -static unsigned int max77686_get_opmode_shift(int id) -{ - switch (id) { - case MAX77686_BUCK1: - case MAX77686_BUCK5 ... MAX77686_BUCK9: - return 0; - case MAX77686_BUCK2 ... MAX77686_BUCK4: - return MAX77686_OPMODE_BUCK234_SHIFT; - default: - /* all LDOs */ - return MAX77686_OPMODE_SHIFT; - } -} - -/* - * When regulator is configured for GPIO control then it - * replaces "normal" mode. Any change from low power mode to normal - * should actually change to GPIO control. - * Map normal mode to proper value for such regulators. - */ -static unsigned int max77686_map_normal_mode(struct max77686_data *max77686, - int id) -{ - switch (id) { - case MAX77686_BUCK8: - case MAX77686_BUCK9: - case MAX77686_LDO20 ... MAX77686_LDO22: - if (test_bit(id, max77686->gpio_enabled)) - return MAX77686_GPIO_CONTROL; - } - - return MAX77686_NORMAL; -} - -/* Some BUCKs and LDOs supports Normal[ON/OFF] mode during suspend */ -static int max77686_set_suspend_disable(struct regulator_dev *rdev) -{ - unsigned int val, shift; - struct max77686_data *max77686 = rdev_get_drvdata(rdev); - int ret, id = rdev_get_id(rdev); - - shift = max77686_get_opmode_shift(id); - val = MAX77686_OFF_PWRREQ; - - ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val << shift); - if (ret) - return ret; - - max77686->opmode[id] = val; - return 0; -} - -/* Some LDOs supports [LPM/Normal]ON mode during suspend state */ -static int max77686_set_suspend_mode(struct regulator_dev *rdev, - unsigned int mode) -{ - struct max77686_data *max77686 = rdev_get_drvdata(rdev); - unsigned int val; - int ret, id = rdev_get_id(rdev); - - /* BUCK[5-9] doesn't support this feature */ - if (id >= MAX77686_BUCK5) - return 0; - - switch (mode) { - case REGULATOR_MODE_IDLE: /* ON in LP Mode */ - val = MAX77686_LDO_LOWPOWER_PWRREQ; - break; - case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ - val = max77686_map_normal_mode(max77686, id); - break; - default: - pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", - rdev->desc->name, mode); - return -EINVAL; - } - - ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, - val << MAX77686_OPMODE_SHIFT); - if (ret) - return ret; - - max77686->opmode[id] = val; - return 0; -} - -/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */ -static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, - unsigned int mode) -{ - unsigned int val; - struct max77686_data *max77686 = rdev_get_drvdata(rdev); - int ret, id = rdev_get_id(rdev); - - switch (mode) { - case REGULATOR_MODE_STANDBY: /* switch off */ - val = MAX77686_OFF_PWRREQ; - break; - case REGULATOR_MODE_IDLE: /* ON in LP Mode */ - val = MAX77686_LDO_LOWPOWER_PWRREQ; - break; - case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */ - val = max77686_map_normal_mode(max77686, id); - break; - default: - pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n", - rdev->desc->name, mode); - return -EINVAL; - } - - ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, - val << MAX77686_OPMODE_SHIFT); - if (ret) - return ret; - - max77686->opmode[id] = val; - return 0; -} - -static int max77686_enable(struct regulator_dev *rdev) -{ - struct max77686_data *max77686 = rdev_get_drvdata(rdev); - unsigned int shift; - int id = rdev_get_id(rdev); - - shift = max77686_get_opmode_shift(id); - - if (max77686->opmode[id] == MAX77686_OFF_PWRREQ) - max77686->opmode[id] = max77686_map_normal_mode(max77686, id); - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, - max77686->opmode[id] << shift); -} - -static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) -{ - unsigned int ramp_value = RAMP_RATE_NO_CTRL; - - switch (ramp_delay) { - case 1 ... 13750: - ramp_value = RAMP_RATE_13P75MV; - break; - case 13751 ... 27500: - ramp_value = RAMP_RATE_27P5MV; - break; - case 27501 ... 55000: - ramp_value = RAMP_RATE_55MV; - break; - case 55001 ... 100000: - break; - default: - pr_warn("%s: ramp_delay: %d not supported, setting 100000\n", - rdev->desc->name, ramp_delay); - } - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - MAX77686_RAMP_RATE_MASK, ramp_value << 6); -} - -static int max77686_of_parse_cb(struct device_node *np, - const struct regulator_desc *desc, - struct regulator_config *config) -{ - struct max77686_data *max77686 = config->driver_data; - - switch (desc->id) { - case MAX77686_BUCK8: - case MAX77686_BUCK9: - case MAX77686_LDO20 ... MAX77686_LDO22: - config->ena_gpio = of_get_named_gpio(np, - "maxim,ena-gpios", 0); - config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH; - config->ena_gpio_initialized = true; - break; - default: - return 0; - } - - if (gpio_is_valid(config->ena_gpio)) { - set_bit(desc->id, max77686->gpio_enabled); - - return regmap_update_bits(config->regmap, desc->enable_reg, - desc->enable_mask, - MAX77686_GPIO_CONTROL); - } - - return 0; -} - -static struct regulator_ops max77686_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77686_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_mode = max77686_set_suspend_mode, -}; - -static struct regulator_ops max77686_ldo_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77686_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_mode = max77686_ldo_set_suspend_mode, - .set_suspend_disable = max77686_set_suspend_disable, -}; - -static struct regulator_ops max77686_buck1_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77686_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_disable = max77686_set_suspend_disable, -}; - -static struct regulator_ops max77686_buck_dvs_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77686_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_ramp_delay = max77686_set_ramp_delay, - .set_suspend_disable = max77686_set_suspend_disable, -}; - -#define regulator_desc_ldo(num) { \ - .name = "LDO"#num, \ - .of_match = of_match_ptr("LDO"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .of_parse_cb = max77686_of_parse_cb, \ - .id = MAX77686_LDO##num, \ - .ops = &max77686_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_LDO_MINUV, \ - .uV_step = MAX77686_LDO_UVSTEP, \ - .ramp_delay = MAX77686_RAMP_DELAY, \ - .n_voltages = MAX77686_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .vsel_mask = MAX77686_VSEL_MASK, \ - .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .enable_mask = MAX77686_OPMODE_MASK \ - << MAX77686_OPMODE_SHIFT, \ -} -#define regulator_desc_lpm_ldo(num) { \ - .name = "LDO"#num, \ - .of_match = of_match_ptr("LDO"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .id = MAX77686_LDO##num, \ - .ops = &max77686_ldo_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_LDO_MINUV, \ - .uV_step = MAX77686_LDO_UVSTEP, \ - .ramp_delay = MAX77686_RAMP_DELAY, \ - .n_voltages = MAX77686_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .vsel_mask = MAX77686_VSEL_MASK, \ - .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .enable_mask = MAX77686_OPMODE_MASK \ - << MAX77686_OPMODE_SHIFT, \ -} -#define regulator_desc_ldo_low(num) { \ - .name = "LDO"#num, \ - .of_match = of_match_ptr("LDO"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .id = MAX77686_LDO##num, \ - .ops = &max77686_ldo_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_LDO_LOW_MINUV, \ - .uV_step = MAX77686_LDO_LOW_UVSTEP, \ - .ramp_delay = MAX77686_RAMP_DELAY, \ - .n_voltages = MAX77686_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .vsel_mask = MAX77686_VSEL_MASK, \ - .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .enable_mask = MAX77686_OPMODE_MASK \ - << MAX77686_OPMODE_SHIFT, \ -} -#define regulator_desc_ldo1_low(num) { \ - .name = "LDO"#num, \ - .of_match = of_match_ptr("LDO"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .id = MAX77686_LDO##num, \ - .ops = &max77686_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_LDO_LOW_MINUV, \ - .uV_step = MAX77686_LDO_LOW_UVSTEP, \ - .ramp_delay = MAX77686_RAMP_DELAY, \ - .n_voltages = MAX77686_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .vsel_mask = MAX77686_VSEL_MASK, \ - .enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \ - .enable_mask = MAX77686_OPMODE_MASK \ - << MAX77686_OPMODE_SHIFT, \ -} -#define regulator_desc_buck(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .of_parse_cb = max77686_of_parse_cb, \ - .id = MAX77686_BUCK##num, \ - .ops = &max77686_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_BUCK_MINUV, \ - .uV_step = MAX77686_BUCK_UVSTEP, \ - .ramp_delay = MAX77686_RAMP_DELAY, \ - .n_voltages = MAX77686_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_BUCK5OUT + (num - 5) * 2, \ - .vsel_mask = MAX77686_VSEL_MASK, \ - .enable_reg = MAX77686_REG_BUCK5CTRL + (num - 5) * 2, \ - .enable_mask = MAX77686_OPMODE_MASK, \ -} -#define regulator_desc_buck1(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .id = MAX77686_BUCK##num, \ - .ops = &max77686_buck1_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_BUCK_MINUV, \ - .uV_step = MAX77686_BUCK_UVSTEP, \ - .ramp_delay = MAX77686_RAMP_DELAY, \ - .n_voltages = MAX77686_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_BUCK1OUT, \ - .vsel_mask = MAX77686_VSEL_MASK, \ - .enable_reg = MAX77686_REG_BUCK1CTRL, \ - .enable_mask = MAX77686_OPMODE_MASK, \ -} -#define regulator_desc_buck_dvs(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("voltage-regulators"), \ - .id = MAX77686_BUCK##num, \ - .ops = &max77686_buck_dvs_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = MAX77686_DVS_MINUV, \ - .uV_step = MAX77686_DVS_UVSTEP, \ - .ramp_delay = MAX77686_DVS_RAMP_DELAY, \ - .n_voltages = MAX77686_DVS_VSEL_MASK + 1, \ - .vsel_reg = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10, \ - .vsel_mask = MAX77686_DVS_VSEL_MASK, \ - .enable_reg = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10, \ - .enable_mask = MAX77686_OPMODE_MASK \ - << MAX77686_OPMODE_BUCK234_SHIFT, \ -} - -static const struct regulator_desc regulators[] = { - regulator_desc_ldo1_low(1), - regulator_desc_ldo_low(2), - regulator_desc_ldo(3), - regulator_desc_ldo(4), - regulator_desc_ldo(5), - regulator_desc_ldo_low(6), - regulator_desc_ldo_low(7), - regulator_desc_ldo_low(8), - regulator_desc_ldo(9), - regulator_desc_lpm_ldo(10), - regulator_desc_lpm_ldo(11), - regulator_desc_lpm_ldo(12), - regulator_desc_ldo(13), - regulator_desc_lpm_ldo(14), - regulator_desc_ldo_low(15), - regulator_desc_lpm_ldo(16), - regulator_desc_ldo(17), - regulator_desc_ldo(18), - regulator_desc_ldo(19), - regulator_desc_ldo(20), - regulator_desc_ldo(21), - regulator_desc_ldo(22), - regulator_desc_ldo(23), - regulator_desc_ldo(24), - regulator_desc_ldo(25), - regulator_desc_ldo(26), - regulator_desc_buck1(1), - regulator_desc_buck_dvs(2), - regulator_desc_buck_dvs(3), - regulator_desc_buck_dvs(4), - regulator_desc_buck(5), - regulator_desc_buck(6), - regulator_desc_buck(7), - regulator_desc_buck(8), - regulator_desc_buck(9), -}; - -static int max77686_pmic_probe(struct platform_device *pdev) -{ - struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max77686_data *max77686; - int i; - struct regulator_config config = { }; - - dev_dbg(&pdev->dev, "%s\n", __func__); - - max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data), - GFP_KERNEL); - if (!max77686) - return -ENOMEM; - - config.dev = iodev->dev; - config.regmap = iodev->regmap; - config.driver_data = max77686; - platform_set_drvdata(pdev, max77686); - - for (i = 0; i < MAX77686_REGULATORS; i++) { - struct regulator_dev *rdev; - int id = regulators[i].id; - - max77686->opmode[id] = MAX77686_NORMAL; - rdev = devm_regulator_register(&pdev->dev, - ®ulators[i], &config); - if (IS_ERR(rdev)) { - int ret = PTR_ERR(rdev); - dev_err(&pdev->dev, - "regulator init failed for %d: %d\n", i, ret); - return ret; - } - } - - return 0; -} - -static const struct platform_device_id max77686_pmic_id[] = { - {"max77686-pmic", 0}, - { }, -}; -MODULE_DEVICE_TABLE(platform, max77686_pmic_id); - -static struct platform_driver max77686_pmic_driver = { - .driver = { - .name = "max77686-pmic", - }, - .probe = max77686_pmic_probe, - .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_DESCRIPTION("MAXIM 77686 Regulator Driver"); -MODULE_AUTHOR("Chiwoong Byun "); -MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max77802-regulator.c b/drivers/regulator/max77802-regulator.c new file mode 100644 index 000000000000..c07ee13bd470 --- /dev/null +++ b/drivers/regulator/max77802-regulator.c @@ -0,0 +1,610 @@ +/* + * max77802.c - Regulator driver for the Maxim 77802 + * + * Copyright (C) 2013-2014 Google, Inc + * Simon Glass + * + * Copyright (C) 2012 Samsung Electronics + * Chiwoong Byun + * 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 + * 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 driver is based on max8997.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Default ramp delay in case it is not manually set */ +#define MAX77802_RAMP_DELAY 100000 /* uV/us */ + +#define MAX77802_OPMODE_SHIFT_LDO 6 +#define MAX77802_OPMODE_BUCK234_SHIFT 4 +#define MAX77802_OPMODE_MASK 0x3 + +#define MAX77802_VSEL_MASK 0x3F +#define MAX77802_DVS_VSEL_MASK 0xFF + +#define MAX77802_RAMP_RATE_MASK_2BIT 0xC0 +#define MAX77802_RAMP_RATE_SHIFT_2BIT 6 +#define MAX77802_RAMP_RATE_MASK_4BIT 0xF0 +#define MAX77802_RAMP_RATE_SHIFT_4BIT 4 + +#define MAX77802_STATUS_OFF 0x0 +#define MAX77802_OFF_PWRREQ 0x1 +#define MAX77802_LP_PWRREQ 0x2 + +/* MAX77802 has two register formats: 2-bit and 4-bit */ +static const unsigned int ramp_table_77802_2bit[] = { + 12500, + 25000, + 50000, + 100000, +}; + +static unsigned int ramp_table_77802_4bit[] = { + 1000, 2000, 3030, 4000, + 5000, 5880, 7140, 8330, + 9090, 10000, 11110, 12500, + 16670, 25000, 50000, 100000, +}; + +struct max77802_regulator_prv { + /* Array indexed by regulator id */ + unsigned int opmode[MAX77802_REG_MAX]; +}; + +static inline unsigned int max77802_map_mode(unsigned int mode) +{ + return mode == MAX77802_OPMODE_NORMAL ? + REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY; +} + +static int max77802_get_opmode_shift(int id) +{ + if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 && + id <= MAX77802_BUCK10)) + return 0; + + if (id >= MAX77802_BUCK2 && id <= MAX77802_BUCK4) + return MAX77802_OPMODE_BUCK234_SHIFT; + + if (id >= MAX77802_LDO1 && id <= MAX77802_LDO35) + return MAX77802_OPMODE_SHIFT_LDO; + + return -EINVAL; +} + +/** + * max77802_set_suspend_disable - Disable the regulator during system suspend + * @rdev: regulator to mark as disabled + * + * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ. + * Configure the regulator so the PMIC will turn it OFF during system suspend. + */ +static int max77802_set_suspend_disable(struct regulator_dev *rdev) +{ + unsigned int val = MAX77802_OFF_PWRREQ; + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int shift = max77802_get_opmode_shift(id); + + max77802->opmode[id] = val; + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); +} + +/* + * Some LDOs support Low Power Mode while the system is running. + * + * LDOs 1, 3, 20, 21. + */ +static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + unsigned int val; + int shift = max77802_get_opmode_shift(id); + + switch (mode) { + case REGULATOR_MODE_STANDBY: + val = MAX77802_OPMODE_LP; /* ON in Low Power Mode */ + break; + case REGULATOR_MODE_NORMAL: + val = MAX77802_OPMODE_NORMAL; /* ON in Normal Mode */ + break; + default: + dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", + rdev->desc->name, mode); + return -EINVAL; + } + + max77802->opmode[id] = val; + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); +} + +static unsigned max77802_get_mode(struct regulator_dev *rdev) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + + return max77802_map_mode(max77802->opmode[id]); +} + +/** + * max77802_set_suspend_mode - set regulator opmode when the system is suspended + * @rdev: regulator to change mode + * @mode: operating mode to be set + * + * Will set the operating mode for the regulators during system suspend. + * This function is valid for the three different enable control logics: + * + * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35) + * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21) + * Enable Control Logic3 by PWRREQ (LDO 3) + * + * If setting the regulator mode fails, the function only warns but does + * not return an error code to avoid the regulator core to stop setting + * the operating mode for the remaining regulators. + */ +static int max77802_set_suspend_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + unsigned int val; + int shift = max77802_get_opmode_shift(id); + + /* + * If the regulator has been disabled for suspend + * then is invalid to try setting a suspend mode. + */ + if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) { + dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n", + rdev->desc->name, mode); + return 0; + } + + switch (mode) { + case REGULATOR_MODE_STANDBY: + /* + * If the regulator opmode is normal then enable + * ON in Low Power Mode by PWRREQ. If the mode is + * already Low Power then no action is required. + */ + if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL) + val = MAX77802_LP_PWRREQ; + else + return 0; + break; + case REGULATOR_MODE_NORMAL: + /* + * If the regulator operating mode is Low Power then + * normal is not a valid opmode in suspend. If the + * mode is already normal then no action is required. + */ + if (max77802->opmode[id] == MAX77802_OPMODE_LP) + dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n", + rdev->desc->name, mode); + return 0; + default: + dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", + rdev->desc->name, mode); + return -EINVAL; + } + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, val << shift); +} + +static int max77802_enable(struct regulator_dev *rdev) +{ + struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + int shift = max77802_get_opmode_shift(id); + + if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) + max77802->opmode[id] = MAX77802_OPMODE_NORMAL; + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + rdev->desc->enable_mask, + max77802->opmode[id] << shift); +} + +static int max77802_find_ramp_value(struct regulator_dev *rdev, + const unsigned int limits[], int size, + unsigned int ramp_delay) +{ + int i; + + for (i = 0; i < size; i++) { + if (ramp_delay <= limits[i]) + return i; + } + + /* Use maximum value for no ramp control */ + dev_warn(&rdev->dev, "%s: ramp_delay: %d not supported, setting 100000\n", + rdev->desc->name, ramp_delay); + return size - 1; +} + +/* Used for BUCKs 2-4 */ +static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev, + int ramp_delay) +{ + int id = rdev_get_id(rdev); + unsigned int ramp_value; + + if (id > MAX77802_BUCK4) { + dev_warn(&rdev->dev, + "%s: regulator: ramp delay not supported\n", + rdev->desc->name); + return -EINVAL; + } + ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit, + ARRAY_SIZE(ramp_table_77802_2bit), ramp_delay); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77802_RAMP_RATE_MASK_2BIT, + ramp_value << MAX77802_RAMP_RATE_SHIFT_2BIT); +} + +/* For BUCK1, 6 */ +static int max77802_set_ramp_delay_4bit(struct regulator_dev *rdev, + int ramp_delay) +{ + unsigned int ramp_value; + + ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_4bit, + ARRAY_SIZE(ramp_table_77802_4bit), ramp_delay); + + return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, + MAX77802_RAMP_RATE_MASK_4BIT, + ramp_value << MAX77802_RAMP_RATE_SHIFT_4BIT); +} + +/* + * LDOs 2, 4-19, 22-35 + */ +static struct regulator_ops max77802_ldo_ops_logic1 = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_suspend_disable = max77802_set_suspend_disable, + .set_suspend_mode = max77802_set_suspend_mode, +}; + +/* + * LDOs 1, 20, 21, 3 + */ +static struct regulator_ops max77802_ldo_ops_logic2 = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_mode = max77802_set_mode, + .get_mode = max77802_get_mode, + .set_suspend_mode = max77802_set_suspend_mode, +}; + +/* BUCKS 1, 6 */ +static struct regulator_ops max77802_buck_16_dvs_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77802_set_ramp_delay_4bit, + .set_suspend_disable = max77802_set_suspend_disable, +}; + +/* BUCKs 2-4 */ +static struct regulator_ops max77802_buck_234_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77802_set_ramp_delay_2bit, + .set_suspend_disable = max77802_set_suspend_disable, + .set_suspend_mode = max77802_set_suspend_mode, +}; + +/* BUCKs 5, 7-10 */ +static struct regulator_ops max77802_buck_dvs_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .is_enabled = regulator_is_enabled_regmap, + .enable = max77802_enable, + .disable = regulator_disable_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .set_ramp_delay = max77802_set_ramp_delay_2bit, + .set_suspend_disable = max77802_set_suspend_disable, +}; + +/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */ +#define regulator_77802_desc_p_ldo(num, supply, log) { \ + .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77802_LDO##num, \ + .supply_name = "inl"#supply, \ + .ops = &max77802_ldo_ops_logic##log, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 800000, \ + .uV_step = 50000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ + .of_map_mode = max77802_map_mode, \ +} + +/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */ +#define regulator_77802_desc_n_ldo(num, supply, log) { \ + .name = "LDO"#num, \ + .of_match = of_match_ptr("LDO"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77802_LDO##num, \ + .supply_name = "inl"#supply, \ + .ops = &max77802_ldo_ops_logic##log, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 800000, \ + .uV_step = 25000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ + .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ + .of_map_mode = max77802_map_mode, \ +} + +/* BUCKs 1, 6 */ +#define regulator_77802_desc_16_buck(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_16_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 612500, \ + .uV_step = 6250, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 8, \ + .vsel_reg = MAX77802_REG_BUCK ## num ## DVS1, \ + .vsel_mask = MAX77802_DVS_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \ + .enable_mask = MAX77802_OPMODE_MASK, \ + .of_map_mode = max77802_map_mode, \ +} + +/* BUCKS 2-4 */ +#define regulator_77802_desc_234_buck(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_234_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 600000, \ + .uV_step = 6250, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 0x91, \ + .vsel_reg = MAX77802_REG_BUCK ## num ## DVS1, \ + .vsel_mask = MAX77802_DVS_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \ + .enable_mask = MAX77802_OPMODE_MASK << \ + MAX77802_OPMODE_BUCK234_SHIFT, \ + .of_map_mode = max77802_map_mode, \ +} + +/* BUCK 5 */ +#define regulator_77802_desc_buck5(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 750000, \ + .uV_step = 50000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_BUCK5OUT, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK5CTRL, \ + .enable_mask = MAX77802_OPMODE_MASK, \ + .of_map_mode = max77802_map_mode, \ +} + +/* BUCKs 7-10 */ +#define regulator_77802_desc_buck7_10(num) { \ + .name = "BUCK"#num, \ + .of_match = of_match_ptr("BUCK"#num), \ + .regulators_node = of_match_ptr("regulators"), \ + .id = MAX77802_BUCK##num, \ + .supply_name = "inb"#num, \ + .ops = &max77802_buck_dvs_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + .min_uV = 750000, \ + .uV_step = 50000, \ + .ramp_delay = MAX77802_RAMP_DELAY, \ + .n_voltages = 1 << 6, \ + .vsel_reg = MAX77802_REG_BUCK7OUT + (num - 7) * 3, \ + .vsel_mask = MAX77802_VSEL_MASK, \ + .enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \ + .enable_mask = MAX77802_OPMODE_MASK, \ + .of_map_mode = max77802_map_mode, \ +} + +static const struct regulator_desc regulators[] = { + regulator_77802_desc_16_buck(1), + regulator_77802_desc_234_buck(2), + regulator_77802_desc_234_buck(3), + regulator_77802_desc_234_buck(4), + regulator_77802_desc_buck5(5), + regulator_77802_desc_16_buck(6), + regulator_77802_desc_buck7_10(7), + regulator_77802_desc_buck7_10(8), + regulator_77802_desc_buck7_10(9), + regulator_77802_desc_buck7_10(10), + regulator_77802_desc_n_ldo(1, 10, 2), + regulator_77802_desc_n_ldo(2, 10, 1), + regulator_77802_desc_p_ldo(3, 3, 2), + regulator_77802_desc_p_ldo(4, 6, 1), + regulator_77802_desc_p_ldo(5, 3, 1), + regulator_77802_desc_p_ldo(6, 3, 1), + regulator_77802_desc_p_ldo(7, 3, 1), + regulator_77802_desc_n_ldo(8, 1, 1), + regulator_77802_desc_p_ldo(9, 5, 1), + regulator_77802_desc_p_ldo(10, 4, 1), + regulator_77802_desc_p_ldo(11, 4, 1), + regulator_77802_desc_p_ldo(12, 9, 1), + regulator_77802_desc_p_ldo(13, 4, 1), + regulator_77802_desc_p_ldo(14, 4, 1), + regulator_77802_desc_n_ldo(15, 1, 1), + regulator_77802_desc_n_ldo(17, 2, 1), + regulator_77802_desc_p_ldo(18, 7, 1), + regulator_77802_desc_p_ldo(19, 5, 1), + regulator_77802_desc_p_ldo(20, 7, 2), + regulator_77802_desc_p_ldo(21, 6, 2), + regulator_77802_desc_p_ldo(23, 9, 1), + regulator_77802_desc_p_ldo(24, 6, 1), + regulator_77802_desc_p_ldo(25, 9, 1), + regulator_77802_desc_p_ldo(26, 9, 1), + regulator_77802_desc_n_ldo(27, 2, 1), + regulator_77802_desc_p_ldo(28, 7, 1), + regulator_77802_desc_p_ldo(29, 7, 1), + regulator_77802_desc_n_ldo(30, 2, 1), + regulator_77802_desc_p_ldo(32, 9, 1), + regulator_77802_desc_p_ldo(33, 6, 1), + regulator_77802_desc_p_ldo(34, 9, 1), + regulator_77802_desc_n_ldo(35, 2, 1), +}; + +static int max77802_pmic_probe(struct platform_device *pdev) +{ + struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct max77802_regulator_prv *max77802; + int i, val; + struct regulator_config config = { }; + + max77802 = devm_kzalloc(&pdev->dev, + sizeof(struct max77802_regulator_prv), + GFP_KERNEL); + if (!max77802) + return -ENOMEM; + + config.dev = iodev->dev; + config.regmap = iodev->regmap; + config.driver_data = max77802; + platform_set_drvdata(pdev, max77802); + + for (i = 0; i < MAX77802_REG_MAX; i++) { + struct regulator_dev *rdev; + int id = regulators[i].id; + int shift = max77802_get_opmode_shift(id); + int ret; + + ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val); + if (ret < 0) { + dev_warn(&pdev->dev, + "cannot read current mode for %d\n", i); + val = MAX77802_OPMODE_NORMAL; + } else { + val = val >> shift & MAX77802_OPMODE_MASK; + } + + /* + * If the regulator is disabled and the system warm rebooted, + * the hardware reports OFF as the regulator operating mode. + * Default to operating mode NORMAL in that case. + */ + if (val == MAX77802_STATUS_OFF) + max77802->opmode[id] = MAX77802_OPMODE_NORMAL; + else + max77802->opmode[id] = val; + + rdev = devm_regulator_register(&pdev->dev, + ®ulators[i], &config); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); + dev_err(&pdev->dev, + "regulator init failed for %d: %d\n", i, ret); + return ret; + } + } + + return 0; +} + +static const struct platform_device_id max77802_pmic_id[] = { + {"max77802-pmic", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, max77802_pmic_id); + +static struct platform_driver max77802_pmic_driver = { + .driver = { + .name = "max77802-pmic", + }, + .probe = max77802_pmic_probe, + .id_table = max77802_pmic_id, +}; + +module_platform_driver(max77802_pmic_driver); + +MODULE_DESCRIPTION("MAXIM 77802 Regulator Driver"); +MODULE_AUTHOR("Simon Glass "); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max77802.c b/drivers/regulator/max77802.c deleted file mode 100644 index c07ee13bd470..000000000000 --- a/drivers/regulator/max77802.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * max77802.c - Regulator driver for the Maxim 77802 - * - * Copyright (C) 2013-2014 Google, Inc - * Simon Glass - * - * Copyright (C) 2012 Samsung Electronics - * Chiwoong Byun - * 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 - * 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 driver is based on max8997.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Default ramp delay in case it is not manually set */ -#define MAX77802_RAMP_DELAY 100000 /* uV/us */ - -#define MAX77802_OPMODE_SHIFT_LDO 6 -#define MAX77802_OPMODE_BUCK234_SHIFT 4 -#define MAX77802_OPMODE_MASK 0x3 - -#define MAX77802_VSEL_MASK 0x3F -#define MAX77802_DVS_VSEL_MASK 0xFF - -#define MAX77802_RAMP_RATE_MASK_2BIT 0xC0 -#define MAX77802_RAMP_RATE_SHIFT_2BIT 6 -#define MAX77802_RAMP_RATE_MASK_4BIT 0xF0 -#define MAX77802_RAMP_RATE_SHIFT_4BIT 4 - -#define MAX77802_STATUS_OFF 0x0 -#define MAX77802_OFF_PWRREQ 0x1 -#define MAX77802_LP_PWRREQ 0x2 - -/* MAX77802 has two register formats: 2-bit and 4-bit */ -static const unsigned int ramp_table_77802_2bit[] = { - 12500, - 25000, - 50000, - 100000, -}; - -static unsigned int ramp_table_77802_4bit[] = { - 1000, 2000, 3030, 4000, - 5000, 5880, 7140, 8330, - 9090, 10000, 11110, 12500, - 16670, 25000, 50000, 100000, -}; - -struct max77802_regulator_prv { - /* Array indexed by regulator id */ - unsigned int opmode[MAX77802_REG_MAX]; -}; - -static inline unsigned int max77802_map_mode(unsigned int mode) -{ - return mode == MAX77802_OPMODE_NORMAL ? - REGULATOR_MODE_NORMAL : REGULATOR_MODE_STANDBY; -} - -static int max77802_get_opmode_shift(int id) -{ - if (id == MAX77802_BUCK1 || (id >= MAX77802_BUCK5 && - id <= MAX77802_BUCK10)) - return 0; - - if (id >= MAX77802_BUCK2 && id <= MAX77802_BUCK4) - return MAX77802_OPMODE_BUCK234_SHIFT; - - if (id >= MAX77802_LDO1 && id <= MAX77802_LDO35) - return MAX77802_OPMODE_SHIFT_LDO; - - return -EINVAL; -} - -/** - * max77802_set_suspend_disable - Disable the regulator during system suspend - * @rdev: regulator to mark as disabled - * - * All regulators expect LDO 1, 3, 20 and 21 support OFF by PWRREQ. - * Configure the regulator so the PMIC will turn it OFF during system suspend. - */ -static int max77802_set_suspend_disable(struct regulator_dev *rdev) -{ - unsigned int val = MAX77802_OFF_PWRREQ; - struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - int shift = max77802_get_opmode_shift(id); - - max77802->opmode[id] = val; - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val << shift); -} - -/* - * Some LDOs support Low Power Mode while the system is running. - * - * LDOs 1, 3, 20, 21. - */ -static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode) -{ - struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - unsigned int val; - int shift = max77802_get_opmode_shift(id); - - switch (mode) { - case REGULATOR_MODE_STANDBY: - val = MAX77802_OPMODE_LP; /* ON in Low Power Mode */ - break; - case REGULATOR_MODE_NORMAL: - val = MAX77802_OPMODE_NORMAL; /* ON in Normal Mode */ - break; - default: - dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", - rdev->desc->name, mode); - return -EINVAL; - } - - max77802->opmode[id] = val; - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val << shift); -} - -static unsigned max77802_get_mode(struct regulator_dev *rdev) -{ - struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - - return max77802_map_mode(max77802->opmode[id]); -} - -/** - * max77802_set_suspend_mode - set regulator opmode when the system is suspended - * @rdev: regulator to change mode - * @mode: operating mode to be set - * - * Will set the operating mode for the regulators during system suspend. - * This function is valid for the three different enable control logics: - * - * Enable Control Logic1 by PWRREQ (BUCK 2-4 and LDOs 2, 4-19, 22-35) - * Enable Control Logic2 by PWRREQ (LDOs 1, 20, 21) - * Enable Control Logic3 by PWRREQ (LDO 3) - * - * If setting the regulator mode fails, the function only warns but does - * not return an error code to avoid the regulator core to stop setting - * the operating mode for the remaining regulators. - */ -static int max77802_set_suspend_mode(struct regulator_dev *rdev, - unsigned int mode) -{ - struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - unsigned int val; - int shift = max77802_get_opmode_shift(id); - - /* - * If the regulator has been disabled for suspend - * then is invalid to try setting a suspend mode. - */ - if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) { - dev_warn(&rdev->dev, "%s: is disabled, mode: 0x%x not set\n", - rdev->desc->name, mode); - return 0; - } - - switch (mode) { - case REGULATOR_MODE_STANDBY: - /* - * If the regulator opmode is normal then enable - * ON in Low Power Mode by PWRREQ. If the mode is - * already Low Power then no action is required. - */ - if (max77802->opmode[id] == MAX77802_OPMODE_NORMAL) - val = MAX77802_LP_PWRREQ; - else - return 0; - break; - case REGULATOR_MODE_NORMAL: - /* - * If the regulator operating mode is Low Power then - * normal is not a valid opmode in suspend. If the - * mode is already normal then no action is required. - */ - if (max77802->opmode[id] == MAX77802_OPMODE_LP) - dev_warn(&rdev->dev, "%s: in Low Power: 0x%x invalid\n", - rdev->desc->name, mode); - return 0; - default: - dev_warn(&rdev->dev, "%s: regulator mode: 0x%x not supported\n", - rdev->desc->name, mode); - return -EINVAL; - } - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, val << shift); -} - -static int max77802_enable(struct regulator_dev *rdev) -{ - struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev); - int id = rdev_get_id(rdev); - int shift = max77802_get_opmode_shift(id); - - if (max77802->opmode[id] == MAX77802_OFF_PWRREQ) - max77802->opmode[id] = MAX77802_OPMODE_NORMAL; - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - rdev->desc->enable_mask, - max77802->opmode[id] << shift); -} - -static int max77802_find_ramp_value(struct regulator_dev *rdev, - const unsigned int limits[], int size, - unsigned int ramp_delay) -{ - int i; - - for (i = 0; i < size; i++) { - if (ramp_delay <= limits[i]) - return i; - } - - /* Use maximum value for no ramp control */ - dev_warn(&rdev->dev, "%s: ramp_delay: %d not supported, setting 100000\n", - rdev->desc->name, ramp_delay); - return size - 1; -} - -/* Used for BUCKs 2-4 */ -static int max77802_set_ramp_delay_2bit(struct regulator_dev *rdev, - int ramp_delay) -{ - int id = rdev_get_id(rdev); - unsigned int ramp_value; - - if (id > MAX77802_BUCK4) { - dev_warn(&rdev->dev, - "%s: regulator: ramp delay not supported\n", - rdev->desc->name); - return -EINVAL; - } - ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_2bit, - ARRAY_SIZE(ramp_table_77802_2bit), ramp_delay); - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - MAX77802_RAMP_RATE_MASK_2BIT, - ramp_value << MAX77802_RAMP_RATE_SHIFT_2BIT); -} - -/* For BUCK1, 6 */ -static int max77802_set_ramp_delay_4bit(struct regulator_dev *rdev, - int ramp_delay) -{ - unsigned int ramp_value; - - ramp_value = max77802_find_ramp_value(rdev, ramp_table_77802_4bit, - ARRAY_SIZE(ramp_table_77802_4bit), ramp_delay); - - return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, - MAX77802_RAMP_RATE_MASK_4BIT, - ramp_value << MAX77802_RAMP_RATE_SHIFT_4BIT); -} - -/* - * LDOs 2, 4-19, 22-35 - */ -static struct regulator_ops max77802_ldo_ops_logic1 = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77802_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_suspend_disable = max77802_set_suspend_disable, - .set_suspend_mode = max77802_set_suspend_mode, -}; - -/* - * LDOs 1, 20, 21, 3 - */ -static struct regulator_ops max77802_ldo_ops_logic2 = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77802_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_mode = max77802_set_mode, - .get_mode = max77802_get_mode, - .set_suspend_mode = max77802_set_suspend_mode, -}; - -/* BUCKS 1, 6 */ -static struct regulator_ops max77802_buck_16_dvs_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77802_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_ramp_delay = max77802_set_ramp_delay_4bit, - .set_suspend_disable = max77802_set_suspend_disable, -}; - -/* BUCKs 2-4 */ -static struct regulator_ops max77802_buck_234_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77802_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_ramp_delay = max77802_set_ramp_delay_2bit, - .set_suspend_disable = max77802_set_suspend_disable, - .set_suspend_mode = max77802_set_suspend_mode, -}; - -/* BUCKs 5, 7-10 */ -static struct regulator_ops max77802_buck_dvs_ops = { - .list_voltage = regulator_list_voltage_linear, - .map_voltage = regulator_map_voltage_linear, - .is_enabled = regulator_is_enabled_regmap, - .enable = max77802_enable, - .disable = regulator_disable_regmap, - .get_voltage_sel = regulator_get_voltage_sel_regmap, - .set_voltage_sel = regulator_set_voltage_sel_regmap, - .set_voltage_time_sel = regulator_set_voltage_time_sel, - .set_ramp_delay = max77802_set_ramp_delay_2bit, - .set_suspend_disable = max77802_set_suspend_disable, -}; - -/* LDOs 3-7, 9-14, 18-26, 28, 29, 32-34 */ -#define regulator_77802_desc_p_ldo(num, supply, log) { \ - .name = "LDO"#num, \ - .of_match = of_match_ptr("LDO"#num), \ - .regulators_node = of_match_ptr("regulators"), \ - .id = MAX77802_LDO##num, \ - .supply_name = "inl"#supply, \ - .ops = &max77802_ldo_ops_logic##log, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = 800000, \ - .uV_step = 50000, \ - .ramp_delay = MAX77802_RAMP_DELAY, \ - .n_voltages = 1 << 6, \ - .vsel_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ - .vsel_mask = MAX77802_VSEL_MASK, \ - .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ - .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ - .of_map_mode = max77802_map_mode, \ -} - -/* LDOs 1, 2, 8, 15, 17, 27, 30, 35 */ -#define regulator_77802_desc_n_ldo(num, supply, log) { \ - .name = "LDO"#num, \ - .of_match = of_match_ptr("LDO"#num), \ - .regulators_node = of_match_ptr("regulators"), \ - .id = MAX77802_LDO##num, \ - .supply_name = "inl"#supply, \ - .ops = &max77802_ldo_ops_logic##log, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = 800000, \ - .uV_step = 25000, \ - .ramp_delay = MAX77802_RAMP_DELAY, \ - .n_voltages = 1 << 6, \ - .vsel_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ - .vsel_mask = MAX77802_VSEL_MASK, \ - .enable_reg = MAX77802_REG_LDO1CTRL1 + num - 1, \ - .enable_mask = MAX77802_OPMODE_MASK << MAX77802_OPMODE_SHIFT_LDO, \ - .of_map_mode = max77802_map_mode, \ -} - -/* BUCKs 1, 6 */ -#define regulator_77802_desc_16_buck(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("regulators"), \ - .id = MAX77802_BUCK##num, \ - .supply_name = "inb"#num, \ - .ops = &max77802_buck_16_dvs_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = 612500, \ - .uV_step = 6250, \ - .ramp_delay = MAX77802_RAMP_DELAY, \ - .n_voltages = 1 << 8, \ - .vsel_reg = MAX77802_REG_BUCK ## num ## DVS1, \ - .vsel_mask = MAX77802_DVS_VSEL_MASK, \ - .enable_reg = MAX77802_REG_BUCK ## num ## CTRL, \ - .enable_mask = MAX77802_OPMODE_MASK, \ - .of_map_mode = max77802_map_mode, \ -} - -/* BUCKS 2-4 */ -#define regulator_77802_desc_234_buck(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("regulators"), \ - .id = MAX77802_BUCK##num, \ - .supply_name = "inb"#num, \ - .ops = &max77802_buck_234_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = 600000, \ - .uV_step = 6250, \ - .ramp_delay = MAX77802_RAMP_DELAY, \ - .n_voltages = 0x91, \ - .vsel_reg = MAX77802_REG_BUCK ## num ## DVS1, \ - .vsel_mask = MAX77802_DVS_VSEL_MASK, \ - .enable_reg = MAX77802_REG_BUCK ## num ## CTRL1, \ - .enable_mask = MAX77802_OPMODE_MASK << \ - MAX77802_OPMODE_BUCK234_SHIFT, \ - .of_map_mode = max77802_map_mode, \ -} - -/* BUCK 5 */ -#define regulator_77802_desc_buck5(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("regulators"), \ - .id = MAX77802_BUCK##num, \ - .supply_name = "inb"#num, \ - .ops = &max77802_buck_dvs_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = 750000, \ - .uV_step = 50000, \ - .ramp_delay = MAX77802_RAMP_DELAY, \ - .n_voltages = 1 << 6, \ - .vsel_reg = MAX77802_REG_BUCK5OUT, \ - .vsel_mask = MAX77802_VSEL_MASK, \ - .enable_reg = MAX77802_REG_BUCK5CTRL, \ - .enable_mask = MAX77802_OPMODE_MASK, \ - .of_map_mode = max77802_map_mode, \ -} - -/* BUCKs 7-10 */ -#define regulator_77802_desc_buck7_10(num) { \ - .name = "BUCK"#num, \ - .of_match = of_match_ptr("BUCK"#num), \ - .regulators_node = of_match_ptr("regulators"), \ - .id = MAX77802_BUCK##num, \ - .supply_name = "inb"#num, \ - .ops = &max77802_buck_dvs_ops, \ - .type = REGULATOR_VOLTAGE, \ - .owner = THIS_MODULE, \ - .min_uV = 750000, \ - .uV_step = 50000, \ - .ramp_delay = MAX77802_RAMP_DELAY, \ - .n_voltages = 1 << 6, \ - .vsel_reg = MAX77802_REG_BUCK7OUT + (num - 7) * 3, \ - .vsel_mask = MAX77802_VSEL_MASK, \ - .enable_reg = MAX77802_REG_BUCK7CTRL + (num - 7) * 3, \ - .enable_mask = MAX77802_OPMODE_MASK, \ - .of_map_mode = max77802_map_mode, \ -} - -static const struct regulator_desc regulators[] = { - regulator_77802_desc_16_buck(1), - regulator_77802_desc_234_buck(2), - regulator_77802_desc_234_buck(3), - regulator_77802_desc_234_buck(4), - regulator_77802_desc_buck5(5), - regulator_77802_desc_16_buck(6), - regulator_77802_desc_buck7_10(7), - regulator_77802_desc_buck7_10(8), - regulator_77802_desc_buck7_10(9), - regulator_77802_desc_buck7_10(10), - regulator_77802_desc_n_ldo(1, 10, 2), - regulator_77802_desc_n_ldo(2, 10, 1), - regulator_77802_desc_p_ldo(3, 3, 2), - regulator_77802_desc_p_ldo(4, 6, 1), - regulator_77802_desc_p_ldo(5, 3, 1), - regulator_77802_desc_p_ldo(6, 3, 1), - regulator_77802_desc_p_ldo(7, 3, 1), - regulator_77802_desc_n_ldo(8, 1, 1), - regulator_77802_desc_p_ldo(9, 5, 1), - regulator_77802_desc_p_ldo(10, 4, 1), - regulator_77802_desc_p_ldo(11, 4, 1), - regulator_77802_desc_p_ldo(12, 9, 1), - regulator_77802_desc_p_ldo(13, 4, 1), - regulator_77802_desc_p_ldo(14, 4, 1), - regulator_77802_desc_n_ldo(15, 1, 1), - regulator_77802_desc_n_ldo(17, 2, 1), - regulator_77802_desc_p_ldo(18, 7, 1), - regulator_77802_desc_p_ldo(19, 5, 1), - regulator_77802_desc_p_ldo(20, 7, 2), - regulator_77802_desc_p_ldo(21, 6, 2), - regulator_77802_desc_p_ldo(23, 9, 1), - regulator_77802_desc_p_ldo(24, 6, 1), - regulator_77802_desc_p_ldo(25, 9, 1), - regulator_77802_desc_p_ldo(26, 9, 1), - regulator_77802_desc_n_ldo(27, 2, 1), - regulator_77802_desc_p_ldo(28, 7, 1), - regulator_77802_desc_p_ldo(29, 7, 1), - regulator_77802_desc_n_ldo(30, 2, 1), - regulator_77802_desc_p_ldo(32, 9, 1), - regulator_77802_desc_p_ldo(33, 6, 1), - regulator_77802_desc_p_ldo(34, 9, 1), - regulator_77802_desc_n_ldo(35, 2, 1), -}; - -static int max77802_pmic_probe(struct platform_device *pdev) -{ - struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); - struct max77802_regulator_prv *max77802; - int i, val; - struct regulator_config config = { }; - - max77802 = devm_kzalloc(&pdev->dev, - sizeof(struct max77802_regulator_prv), - GFP_KERNEL); - if (!max77802) - return -ENOMEM; - - config.dev = iodev->dev; - config.regmap = iodev->regmap; - config.driver_data = max77802; - platform_set_drvdata(pdev, max77802); - - for (i = 0; i < MAX77802_REG_MAX; i++) { - struct regulator_dev *rdev; - int id = regulators[i].id; - int shift = max77802_get_opmode_shift(id); - int ret; - - ret = regmap_read(iodev->regmap, regulators[i].enable_reg, &val); - if (ret < 0) { - dev_warn(&pdev->dev, - "cannot read current mode for %d\n", i); - val = MAX77802_OPMODE_NORMAL; - } else { - val = val >> shift & MAX77802_OPMODE_MASK; - } - - /* - * If the regulator is disabled and the system warm rebooted, - * the hardware reports OFF as the regulator operating mode. - * Default to operating mode NORMAL in that case. - */ - if (val == MAX77802_STATUS_OFF) - max77802->opmode[id] = MAX77802_OPMODE_NORMAL; - else - max77802->opmode[id] = val; - - rdev = devm_regulator_register(&pdev->dev, - ®ulators[i], &config); - if (IS_ERR(rdev)) { - ret = PTR_ERR(rdev); - dev_err(&pdev->dev, - "regulator init failed for %d: %d\n", i, ret); - return ret; - } - } - - return 0; -} - -static const struct platform_device_id max77802_pmic_id[] = { - {"max77802-pmic", 0}, - { }, -}; -MODULE_DEVICE_TABLE(platform, max77802_pmic_id); - -static struct platform_driver max77802_pmic_driver = { - .driver = { - .name = "max77802-pmic", - }, - .probe = max77802_pmic_probe, - .id_table = max77802_pmic_id, -}; - -module_platform_driver(max77802_pmic_driver); - -MODULE_DESCRIPTION("MAXIM 77802 Regulator Driver"); -MODULE_AUTHOR("Simon Glass "); -MODULE_LICENSE("GPL"); -- cgit From 2f749c3ac70334105f918d23743349e34e22c952 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 12 Feb 2016 11:13:13 +0100 Subject: pinctrl: intel: Remove unneeded header includes pinctrl-intel doesn't use anything from , , or , so it should not include these header files. Signed-off-by: Jean Delvare Cc: Heikki Krogerus Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-intel.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index c0f5586218c4..85536b467c25 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -11,13 +11,9 @@ */ #include -#include #include -#include -#include #include #include -#include #include #include #include -- cgit From c7ac24178c50a01f14eebcddf5c7b7a2e54676cc Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Thu, 11 Feb 2016 02:51:17 +0900 Subject: perf config: Add '--system' and '--user' options to select which config file is used The '--system' option means $(sysconfdir)/perfconfig and '--user' means $HOME/.perfconfig. If none is used, both system and user config file are read. E.g.: # perf config [] [options] With an specific config file: # perf config --user | --system or both user and system config file: # perf config Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1455126685-32367-2-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-config.txt | 14 +++++++++++++- tools/perf/builtin-config.c | 27 ++++++++++++++++++++++++--- tools/perf/util/cache.h | 3 +++ tools/perf/util/config.c | 4 ++-- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/tools/perf/Documentation/perf-config.txt b/tools/perf/Documentation/perf-config.txt index c7158bfb1649..15949e2a7805 100644 --- a/tools/perf/Documentation/perf-config.txt +++ b/tools/perf/Documentation/perf-config.txt @@ -8,7 +8,7 @@ perf-config - Get and set variables in a configuration file. SYNOPSIS -------- [verse] -'perf config' -l | --list +'perf config' [] -l | --list DESCRIPTION ----------- @@ -21,6 +21,14 @@ OPTIONS --list:: Show current config variables, name and value, for all sections. +--user:: + For writing and reading options: write to user + '$HOME/.perfconfig' file or read it. + +--system:: + For writing and reading options: write to system-wide + '$(sysconfdir)/perfconfig' or read it. + CONFIGURATION FILE ------------------ @@ -30,6 +38,10 @@ The '$HOME/.perfconfig' file is used to store a per-user configuration. The file '$(sysconfdir)/perfconfig' can be used to store a system-wide default configuration. +When reading or writing, the values are read from the system and user +configuration files by default, and options '--system' and '--user' +can be used to tell the command to read from or write to only that location. + Syntax ~~~~~~ diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c index f04e804a9fad..c42448ed5dfe 100644 --- a/tools/perf/builtin-config.c +++ b/tools/perf/builtin-config.c @@ -13,8 +13,10 @@ #include "util/util.h" #include "util/debug.h" +static bool use_system_config, use_user_config; + static const char * const config_usage[] = { - "perf config [options]", + "perf config [] [options]", NULL }; @@ -25,6 +27,8 @@ enum actions { static struct option config_options[] = { OPT_SET_UINT('l', "list", &actions, "show current config variables", ACTION_LIST), + OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"), + OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"), OPT_END() }; @@ -42,10 +46,23 @@ 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; + char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); argc = parse_options(argc, argv, config_options, config_usage, PARSE_OPT_STOP_AT_NON_OPTION); + if (use_system_config && use_user_config) { + pr_err("Error: only one config file at a time\n"); + parse_options_usage(config_usage, config_options, "user", 0); + parse_options_usage(NULL, config_options, "system", 0); + return -1; + } + + if (use_system_config) + config_exclusive_filename = perf_etc_perfconfig(); + else if (use_user_config) + config_exclusive_filename = user_config; + switch (actions) { case ACTION_LIST: if (argc) { @@ -53,9 +70,13 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) parse_options_usage(config_usage, config_options, "l", 1); } else { ret = perf_config(show_config, NULL); - if (ret < 0) + if (ret < 0) { + const char * config_filename = config_exclusive_filename; + if (!config_exclusive_filename) + config_filename = user_config; pr_err("Nothing configured, " - "please check your ~/.perfconfig file\n"); + "please check your %s \n", config_filename); + } } break; default: diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 07b5d63947b1..3ca453f0c51f 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -23,6 +23,8 @@ #define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" #define PERF_PAGER_ENVIRONMENT "PERF_PAGER" +extern const char *config_exclusive_filename; + typedef int (*config_fn_t)(const char *, const char *, void *); extern int perf_default_config(const char *, const char *, void *); extern int perf_config(config_fn_t fn, void *); @@ -31,6 +33,7 @@ extern u64 perf_config_u64(const char *, const char *); extern int perf_config_bool(const char *, const char *); extern int config_error_nonbool(const char *); extern const char *perf_config_dirname(const char *, const char *); +extern const char *perf_etc_perfconfig(void); char *alias_lookup(const char *alias); int split_cmdline(char *cmdline, const char ***argv); diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index d3e12e30e1d5..4e727635476e 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -26,7 +26,7 @@ static const char *config_file_name; static int config_linenr; static int config_file_eof; -static const char *config_exclusive_filename; +const char *config_exclusive_filename; static int get_next_char(void) { @@ -434,7 +434,7 @@ static int perf_config_from_file(config_fn_t fn, const char *filename, void *dat return ret; } -static const char *perf_etc_perfconfig(void) +const char *perf_etc_perfconfig(void) { static const char *system_wide; if (!system_wide) -- cgit From e7ee404757609067c8f261d90251f1e96459c535 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 5 Feb 2016 14:01:27 +0000 Subject: perf symbols: Fix symbols searching for module in buildid-cache Before this patch, if a sample is triggered inside a module not in /lib/modules/`uname -r`/, even if the module is in buildid-cache, 'perf report' will still be unable to find the correct symbol. For example: # rm -rf ~/.debug/ # perf buildid-cache -a ./mymodule.ko # perf probe -m ./mymodule.ko -a get_mymodule_val Added new event: probe:get_mymodule_val (on get_mymodule_val in mymodule) You can now use it in all perf tools, such as: perf record -e probe:get_mymodule_val -aR sleep 1 # perf record -e probe:get_mymodule_val cat /proc/mymodule mymodule:3 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.011 MB perf.data (1 samples) ] # perf report --stdio [SNIP] # # Overhead Command Shared Object Symbol # ........ ....... ................ ...................... # 100.00% cat [mymodule] [k] 0x0000000000000001 # perf report -vvvv --stdio dso__load_sym: adjusting symbol: st_value: 0 sh_addr: 0 sh_offset: 0x70 symbol__new: get_mymodule_val 0x70-0x8a [SNIP] This is caused by dso__load() -> dso__load_sym(). In dso__load(), kmod is true only when its file is found in some well know directories. All files loaded from buildid-cache are treated as user programs. Following dso__load_sym() set map->pgoff incorrectly. This patch gives kernel modules in buildid-cache a chance to adjust value of kmod. After dso__load() get the type of symbols, if it is buildid, check the last 3 chars of original filename against '.ko', and adjust the value of kmod if the file is a kernel module. Signed-off-by: Wang Nan Cc: Adrian Hunter Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Cody P Schafer Cc: He Kuang Cc: Jeremie Galarneau Cc: Jiri Olsa Cc: Kirill Smelkov Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1454680939-24963-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/build-id.h | 1 + tools/perf/util/symbol.c | 4 ++++ 3 files changed, 49 insertions(+) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index b28100ee1732..f1479eeef7da 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -166,6 +166,50 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) return build_id__filename(build_id_hex, bf, size); } +bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) +{ + char *id_name, *ch; + struct stat sb; + + id_name = dso__build_id_filename(dso, bf, size); + if (!id_name) + goto err; + if (access(id_name, F_OK)) + goto err; + if (lstat(id_name, &sb) == -1) + goto err; + if ((size_t)sb.st_size > size - 1) + goto err; + if (readlink(id_name, bf, size - 1) < 0) + goto err; + + bf[sb.st_size] = '\0'; + + /* + * link should be: + * ../../lib/modules/4.4.0-rc4/kernel/net/ipv4/netfilter/nf_nat_ipv4.ko/a09fe3eb3147dafa4e3b31dbd6257e4d696bdc92 + */ + ch = strrchr(bf, '/'); + if (!ch) + goto err; + if (ch - 3 < bf) + goto err; + + return strncmp(".ko", ch - 3, 3) == 0; +err: + /* + * If dso__build_id_filename work, get id_name again, + * because id_name points to bf and is broken. + */ + if (id_name) + id_name = dso__build_id_filename(dso, bf, size); + pr_err("Invalid build id: %s\n", id_name ? : + dso->long_name ? : + dso->short_name ? : + "[unknown]"); + return false; +} + #define dsos__for_each_with_build_id(pos, head) \ list_for_each_entry(pos, head, node) \ if (!pos->has_build_id) \ diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h index 27a14a8a945b..64af3e20610d 100644 --- a/tools/perf/util/build-id.h +++ b/tools/perf/util/build-id.h @@ -16,6 +16,7 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); int filename__sprintf_build_id(const char *pathname, char *sbuild_id); char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); +bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size); int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 90cedfa30e43..e7588dc91518 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1529,6 +1529,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) if (!runtime_ss && syms_ss) runtime_ss = syms_ss; + if (syms_ss && syms_ss->type == DSO_BINARY_TYPE__BUILD_ID_CACHE) + if (dso__build_id_is_kmod(dso, name, PATH_MAX)) + kmod = true; + if (syms_ss) ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod); else -- cgit From f65e0d299807d8a11812845c972493c3f9a18e10 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 10 Feb 2016 12:47:03 +0100 Subject: ALSA: timer: Call notifier in the same spinlock snd_timer_notify1() is called outside the spinlock and it retakes the lock after the unlock. This is rather racy, and it's safer to move snd_timer_notify() call inside the main spinlock. The patch also contains a slight refactoring / cleanup of the code. Now all start/stop/continue/pause look more symmetric and a bit better readable. Signed-off-by: Takashi Iwai --- sound/core/timer.c | 220 +++++++++++++++++++++++++---------------------------- 1 file changed, 102 insertions(+), 118 deletions(-) diff --git a/sound/core/timer.c b/sound/core/timer.c index b572a9bc31ad..aa1b15c155d1 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -305,8 +305,6 @@ int snd_timer_open(struct snd_timer_instance **ti, return 0; } -static int _snd_timer_stop(struct snd_timer_instance *timeri, int event); - /* * close a timer instance */ @@ -389,7 +387,6 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) static void snd_timer_notify1(struct snd_timer_instance *ti, int event) { struct snd_timer *timer; - unsigned long flags; unsigned long resolution = 0; struct snd_timer_instance *ts; struct timespec tstamp; @@ -413,34 +410,66 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) return; if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) return; - spin_lock_irqsave(&timer->lock, flags); list_for_each_entry(ts, &ti->slave_active_head, active_list) if (ts->ccallback) ts->ccallback(ts, event + 100, &tstamp, resolution); - spin_unlock_irqrestore(&timer->lock, flags); } -static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, - unsigned long sticks) +/* start/continue a master timer */ +static int snd_timer_start1(struct snd_timer_instance *timeri, + bool start, unsigned long ticks) { + struct snd_timer *timer; + int result; + unsigned long flags; + + timer = timeri->timer; + if (!timer) + return -EINVAL; + + spin_lock_irqsave(&timer->lock, flags); + if (timer->card && timer->card->shutdown) { + result = -ENODEV; + goto unlock; + } + if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | + SNDRV_TIMER_IFLG_START)) { + result = -EBUSY; + goto unlock; + } + + if (start) + timeri->ticks = timeri->cticks = ticks; + else if (!timeri->cticks) + timeri->cticks = 1; + timeri->pticks = 0; + list_move_tail(&timeri->active_list, &timer->active_list_head); if (timer->running) { if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) goto __start_now; timer->flags |= SNDRV_TIMER_FLG_RESCHED; timeri->flags |= SNDRV_TIMER_IFLG_START; - return 1; /* delayed start */ + result = 1; /* delayed start */ } else { - timer->sticks = sticks; + if (start) + timer->sticks = ticks; timer->hw.start(timer); __start_now: timer->running++; timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; - return 0; + result = 0; } + snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START : + SNDRV_TIMER_EVENT_CONTINUE); + unlock: + spin_unlock_irqrestore(&timer->lock, flags); + return result; } -static int snd_timer_start_slave(struct snd_timer_instance *timeri) +/* start/continue a slave timer */ +static int snd_timer_start_slave(struct snd_timer_instance *timeri, + bool start) { unsigned long flags; @@ -454,88 +483,37 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri) spin_lock(&timeri->timer->lock); list_add_tail(&timeri->active_list, &timeri->master->slave_active_head); + snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START : + SNDRV_TIMER_EVENT_CONTINUE); spin_unlock(&timeri->timer->lock); } spin_unlock_irqrestore(&slave_active_lock, flags); return 1; /* delayed start */ } -/* - * start the timer instance - */ -int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) -{ - struct snd_timer *timer; - int result = -EINVAL; - unsigned long flags; - - if (timeri == NULL || ticks < 1) - return -EINVAL; - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - result = snd_timer_start_slave(timeri); - if (result >= 0) - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); - return result; - } - timer = timeri->timer; - if (timer == NULL) - return -EINVAL; - if (timer->card && timer->card->shutdown) - return -ENODEV; - spin_lock_irqsave(&timer->lock, flags); - if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | - SNDRV_TIMER_IFLG_START)) { - result = -EBUSY; - goto unlock; - } - timeri->ticks = timeri->cticks = ticks; - timeri->pticks = 0; - result = snd_timer_start1(timer, timeri, ticks); - unlock: - spin_unlock_irqrestore(&timer->lock, flags); - if (result >= 0) - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); - return result; -} - -static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) +/* stop/pause a master timer */ +static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) { struct snd_timer *timer; + int result = 0; unsigned long flags; - if (snd_BUG_ON(!timeri)) - return -ENXIO; - - if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { - spin_lock_irqsave(&slave_active_lock, flags); - if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { - spin_unlock_irqrestore(&slave_active_lock, flags); - return -EBUSY; - } - if (timeri->timer) - spin_lock(&timeri->timer->lock); - timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; - list_del_init(&timeri->ack_list); - list_del_init(&timeri->active_list); - if (timeri->timer) - spin_unlock(&timeri->timer->lock); - spin_unlock_irqrestore(&slave_active_lock, flags); - goto __end; - } timer = timeri->timer; if (!timer) return -EINVAL; spin_lock_irqsave(&timer->lock, flags); if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START))) { - spin_unlock_irqrestore(&timer->lock, flags); - return -EBUSY; + result = -EBUSY; + goto unlock; } list_del_init(&timeri->ack_list); list_del_init(&timeri->active_list); - if (timer->card && timer->card->shutdown) { - spin_unlock_irqrestore(&timer->lock, flags); - return 0; + if (timer->card && timer->card->shutdown) + goto unlock; + if (stop) { + timeri->cticks = timeri->ticks; + timeri->pticks = 0; } if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && !(--timer->running)) { @@ -550,13 +528,49 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) } } timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); + snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : + SNDRV_TIMER_EVENT_CONTINUE); + unlock: spin_unlock_irqrestore(&timer->lock, flags); - __end: - if (event != SNDRV_TIMER_EVENT_RESOLUTION) - snd_timer_notify1(timeri, event); + return result; +} + +/* stop/pause a slave timer */ +static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop) +{ + unsigned long flags; + + spin_lock_irqsave(&slave_active_lock, flags); + if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { + spin_unlock_irqrestore(&slave_active_lock, flags); + return -EBUSY; + } + timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; + if (timeri->timer) { + spin_lock(&timeri->timer->lock); + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); + snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : + SNDRV_TIMER_EVENT_CONTINUE); + spin_unlock(&timeri->timer->lock); + } + spin_unlock_irqrestore(&slave_active_lock, flags); return 0; } +/* + * start the timer instance + */ +int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) +{ + if (timeri == NULL || ticks < 1) + return -EINVAL; + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + return snd_timer_start_slave(timeri, true); + else + return snd_timer_start1(timeri, true, ticks); +} + /* * stop the timer instance. * @@ -564,21 +578,10 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) */ int snd_timer_stop(struct snd_timer_instance *timeri) { - struct snd_timer *timer; - unsigned long flags; - int err; - - err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP); - if (err < 0) - return err; - timer = timeri->timer; - if (!timer) - return -EINVAL; - spin_lock_irqsave(&timer->lock, flags); - timeri->cticks = timeri->ticks; - timeri->pticks = 0; - spin_unlock_irqrestore(&timer->lock, flags); - return 0; + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + return snd_timer_stop_slave(timeri, true); + else + return snd_timer_stop1(timeri, true); } /* @@ -586,32 +589,10 @@ int snd_timer_stop(struct snd_timer_instance *timeri) */ int snd_timer_continue(struct snd_timer_instance *timeri) { - struct snd_timer *timer; - int result = -EINVAL; - unsigned long flags; - - if (timeri == NULL) - return result; if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) - return snd_timer_start_slave(timeri); - timer = timeri->timer; - if (! timer) - return -EINVAL; - if (timer->card && timer->card->shutdown) - return -ENODEV; - spin_lock_irqsave(&timer->lock, flags); - if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { - result = -EBUSY; - goto unlock; - } - if (!timeri->cticks) - timeri->cticks = 1; - timeri->pticks = 0; - result = snd_timer_start1(timer, timeri, timer->sticks); - unlock: - spin_unlock_irqrestore(&timer->lock, flags); - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE); - return result; + return snd_timer_start_slave(timeri, false); + else + return snd_timer_start1(timeri, false, 0); } /* @@ -619,7 +600,10 @@ int snd_timer_continue(struct snd_timer_instance *timeri) */ int snd_timer_pause(struct snd_timer_instance * timeri) { - return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE); + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) + return snd_timer_stop_slave(timeri, false); + else + return snd_timer_stop1(timeri, false); } /* -- cgit From 37b4e2020a5f4dbecf22ee3efe92de6dbea1c5f0 Mon Sep 17 00:00:00 2001 From: Zubair Lutfullah Kakakhel Date: Tue, 9 Feb 2016 13:33:38 +0000 Subject: perf build: Add EXTRA_LDFLAGS option to makefile To compile for little-endian systems, you need to pass -EL to CC and LD. EXTRA_CFLAGS works to pass -EL to CC. Add EXTRA_LDFLAGS to pass -EL to LD. Signed-off-by: Zubair Lutfullah Kakakhel Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1455024818-15842-1-git-send-email-Zubair.Kakakhel@imgtec.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile.perf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index d404117810a7..4a4fad4182f5 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -139,6 +139,8 @@ $(call allow-override,CC,$(CROSS_COMPILE)gcc) $(call allow-override,AR,$(CROSS_COMPILE)ar) $(call allow-override,LD,$(CROSS_COMPILE)ld) +LD += $(EXTRA_LDFLAGS) + PKG_CONFIG = $(CROSS_COMPILE)pkg-config RM = rm -f -- cgit From b416e204f88dd91d9e99f6deee3d57fbc90aee40 Mon Sep 17 00:00:00 2001 From: Taeung Song Date: Tue, 9 Feb 2016 20:53:10 +0900 Subject: perf python scripting: Append examples to err msg about audit-libs-python To print syscall names, the audit-libs-python package is required.. If not installed, it prints this error string: # perf script syscall-counts Install the audit-libs-python package to get syscall names. But the package name is different in Ubuntu, mention that in the error message, similar to a error message of util/trace-event-scripting.c: # perf script syscall-counts Install the audit-libs-python package to get syscall names. For example: # apt-get install python-audit (Ubuntu) # yum install audit-libs-python (Fedora) etc. Signed-off-by: Taeung Song Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/r/1455018790-13425-1-git-send-email-treeze.taeung@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py index 15c8400240fd..1d95009592eb 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py @@ -71,7 +71,10 @@ try: except: if not audit_package_warned: audit_package_warned = True - print "Install the audit-libs-python package to get syscall names" + print "Install the audit-libs-python package to get syscall names.\n" \ + "For example:\n # apt-get install python-audit (Ubuntu)" \ + "\n # yum install audit-libs-python (Fedora)" \ + "\n etc.\n" def syscall_name(id): try: -- cgit From 37d9bb580aa73c171c51fb93edf67a902bcb186f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Feb 2016 11:27:51 -0300 Subject: perf tools: Add comment explaining the repsep_snprintf function Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-4j67nvlfwbnkg85b969ewnkr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/sort.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index de620f7f40f4..8b54ede7ec1f 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -28,7 +28,15 @@ int sort__has_socket = 0; int sort__has_thread = 0; enum sort_mode sort__mode = SORT_MODE__NORMAL; - +/* + * Replaces all occurrences of a char used with the: + * + * -t, --field-separator + * + * option, that uses a special separator character and don't pad with spaces, + * replacing all occurances of this separator in symbol names (and other + * output) with a '.' character, that thus it's the only non valid separator. +*/ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) { int n; -- cgit From 89fee70943232d73e3cc328634e0da253b6de9b5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Feb 2016 17:14:13 -0300 Subject: perf hists: Do column alignment on the format iterator We were doing column alignment in the format function for each cell, returning a string padded with spaces so that when the next column is printed the cursor is at its column alignment. This ends up needlessly printing trailing spaces, do it at the format iterator, that is where we know if it is needed, i.e. if there is more columns to be printed. This eliminates the need for triming lines when doing a dump using 'P' in the TUI browser and also produces far saner results with things like piping 'perf report' to 'less'. Right now only the formatters for sym->name and the 'locked' column (perf mem report), that are the ones that end up at the end of lines in the default 'perf report', 'perf top' and 'perf mem report' tools, the others will be done in a subsequent patch. In the end the 'width' parameter for the formatters now mean, in 'printf' terms, the 'precision', where before it was the field 'width'. Reported-by: Dave Jones Cc: Jiri Olsa Cc: Namhyung Kim Link: http://lkml.kernel.org/n/tip-s7iwl2gj23w92l6tibnrcqzr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 27 ++++++++++++++++++--------- tools/perf/ui/stdio/hist.c | 1 + tools/perf/util/hist.c | 21 +++++++++++++++++++++ tools/perf/util/hist.h | 5 +++++ tools/perf/util/sort.c | 13 +++---------- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a5a5390476ac..1819771243f9 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1061,7 +1061,6 @@ static int hist_browser__show_entry(struct hist_browser *browser, struct hist_entry *entry, unsigned short row) { - char s[256]; int printed = 0; int width = browser->b.width; char folded_sign = ' '; @@ -1086,16 +1085,18 @@ static int hist_browser__show_entry(struct hist_browser *browser, .folded_sign = folded_sign, .current_entry = current_entry, }; - struct perf_hpp hpp = { - .buf = s, - .size = sizeof(s), - .ptr = &arg, - }; int column = 0; hist_browser__gotorc(browser, row, 0); hists__for_each_format(browser->hists, fmt) { + char s[2048]; + struct perf_hpp hpp = { + .buf = s, + .size = sizeof(s), + .ptr = &arg, + }; + if (perf_hpp__should_skip(fmt, entry->hists) || column++ < browser->b.horiz_scroll) continue; @@ -1120,11 +1121,18 @@ static int hist_browser__show_entry(struct hist_browser *browser, } if (fmt->color) { - width -= fmt->color(fmt, &hpp, entry); + int ret = fmt->color(fmt, &hpp, entry); + hist_entry__snprintf_alignment(entry, &hpp, fmt, ret); + /* + * fmt->color() already used ui_browser to + * print the non alignment bits, skip it (+ret): + */ + ui_browser__printf(&browser->b, "%s", s + ret); } else { - width -= fmt->entry(fmt, &hpp, entry); + hist_entry__snprintf_alignment(entry, &hpp, fmt, fmt->entry(fmt, &hpp, entry)); ui_browser__printf(&browser->b, "%s", s); } + width -= hpp.buf - s; } /* The scroll bar isn't being used */ @@ -1452,9 +1460,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, first = false; ret = fmt->entry(fmt, &hpp, he); + ret = hist_entry__snprintf_alignment(he, &hpp, fmt, ret); advance_hpp(&hpp, ret); } - printed += fprintf(fp, "%s\n", rtrim(s)); + printed += fprintf(fp, "%s\n", s); if (folded_sign == '-') printed += hist_browser__fprintf_callchain(browser, he, fp); diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 1a6e8f7f38c4..87b022ff03d8 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -403,6 +403,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) else ret = fmt->entry(fmt, hpp, he); + ret = hist_entry__snprintf_alignment(he, hpp, fmt, ret); advance_hpp(hpp, ret); } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 12f2d794dc28..561e9473a915 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1014,6 +1014,27 @@ void hist_entry__delete(struct hist_entry *he) free(he); } +/* + * If this is not the last column, then we need to pad it according to the + * pre-calculated max lenght for this column, otherwise don't bother adding + * spaces because that would break viewing this with, for instance, 'less', + * that would show tons of trailing spaces when a long C++ demangled method + * names is sampled. +*/ +int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, + struct perf_hpp_fmt *fmt, int printed) +{ + if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { + const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists)); + if (printed < width) { + advance_hpp(hpp, printed); + printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); + } + } + + return printed; +} + /* * collapse the histogram */ diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1c7544a8fe1a..840b6d6aa44f 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -122,11 +122,16 @@ struct hist_entry *__hists__add_entry(struct hists *hists, int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, int max_stack_depth, void *arg); +struct perf_hpp; +struct perf_hpp_fmt; + int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); int hist_entry__transaction_len(void); int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, struct hists *hists); +int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp, + struct perf_hpp_fmt *fmt, int printed); void hist_entry__delete(struct hist_entry *he); void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 8b54ede7ec1f..de715756f281 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -255,10 +255,8 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name); ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx", ip - map->unmap_ip(map, sym->start)); - ret += repsep_snprintf(bf + ret, size - ret, "%-*s", - width - ret, ""); } else { - ret += repsep_snprintf(bf + ret, size - ret, "%-*s", + ret += repsep_snprintf(bf + ret, size - ret, "%.*s", width - ret, sym->name); } @@ -266,14 +264,9 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym, size_t len = BITS_PER_LONG / 4; ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx", len, ip); - ret += repsep_snprintf(bf + ret, size - ret, "%-*s", - width - ret, ""); } - if (ret > width) - bf[width] = '\0'; - - return width; + return ret; } static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, @@ -819,7 +812,7 @@ static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf, else out = "No"; - return repsep_snprintf(bf, size, "%-*s", width, out); + return repsep_snprintf(bf, size, "%.*s", width, out); } static int64_t -- cgit From a8adfceb389a0045e06af22517fa3326797b160a Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 12 Feb 2016 16:31:23 -0300 Subject: perf tools: Unlink entries from terms list We were just freeing them, better unlink and init its nodes to catch bugs faster if we keep dangling references to them. Signed-off-by: Wang Nan Acked-by: Jiri Olsa Cc: Alexei Starovoitov Cc: He Kuang Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com [ Spun off from another patch, use list_del_init() instead of list_del() ] Link: http://lkml.kernel.org/r/1454680939-24963-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 813d9b272c81..133c8d28f36c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2072,8 +2072,10 @@ void parse_events__free_terms(struct list_head *terms) { struct parse_events_term *term, *h; - list_for_each_entry_safe(term, h, terms, list) + list_for_each_entry_safe(term, h, terms, list) { + list_del_init(&term->list); free(term); + } } void parse_events_evlist_error(struct parse_events_evlist *data, -- cgit From fc0a2c1d59beac70b8738f4ce14431b798837374 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Feb 2016 16:43:02 -0300 Subject: perf tools: Introduce parse_events_terms__purge() Purges 'struct parse_event_term' entries from a list_head. Some users need this because they don't allocate space for the list head, it maybe on the stack or embedded into some other struct. Next patch will convert users that need just purging and then the perf_events__free_terms() routine will free the list head as well, finally being renamed to perf_events_terms__delete(). Acked-by: Jiri Olsa Cc: Alexei Starovoitov Cc: He Kuang Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Wang Nan Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/n/tip-4w3zl4ifcl0ed0j4bu3tckqp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 7 ++++++- tools/perf/util/parse-events.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 133c8d28f36c..668afdccfcca 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2068,7 +2068,7 @@ int parse_events_term__clone(struct parse_events_term **new, term->err_term, term->err_val); } -void parse_events__free_terms(struct list_head *terms) +void parse_events_terms__purge(struct list_head *terms) { struct parse_events_term *term, *h; @@ -2078,6 +2078,11 @@ void parse_events__free_terms(struct list_head *terms) } } +void parse_events__free_terms(struct list_head *terms) +{ + parse_events_terms__purge(terms); +} + void parse_events_evlist_error(struct parse_events_evlist *data, int idx, const char *str) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index f1a6db107241..f90a04ccab39 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -116,6 +116,7 @@ int parse_events_term__sym_hw(struct parse_events_term **term, int parse_events_term__clone(struct parse_events_term **new, struct parse_events_term *term); void parse_events__free_terms(struct list_head *terms); +void parse_events_terms__purge(struct list_head *terms); int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_group(struct list_head *list, char *event_mod); int parse_events_name(struct list_head *list, char *name); -- cgit From 682dc24c2a0f13d5a16ac8f4303671eb8f11519f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Feb 2016 16:48:00 -0300 Subject: perf tools: Use perf_event_terms__purge() for non-malloced terms In these two cases, a 'perf test' entry and in the PMU code the list_head is on the stack, so we can't use perf_event__free_terms() (soon to be renamed to perf_event_terms__delete()), because it will free the list_head as well. Acked-by: Jiri Olsa Cc: Alexei Starovoitov Cc: He Kuang Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Wang Nan Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/n/tip-i956ryjhz97gnnqe8iqe7m7s@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/parse-events.c | 2 +- tools/perf/util/pmu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index abe8849d1d70..6648274f4601 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c @@ -1666,7 +1666,7 @@ static int test_term(struct terms_test *t) } ret = t->check(&terms); - parse_events__free_terms(&terms); + parse_events_terms__purge(&terms); return ret; } diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 41a9c875e492..cf59fbaee491 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -354,7 +354,7 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias, list_for_each_entry(term, &alias->terms, list) { ret = parse_events_term__clone(&cloned, term); if (ret) { - parse_events__free_terms(&list); + parse_events_terms__purge(&list); return ret; } list_add_tail(&cloned->list, &list); -- cgit From d20a5f2b277b2f46548fb60f2bb95ad9a601d3fe Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 12 Feb 2016 17:01:17 -0300 Subject: perf tools: Free the terms list_head in parse_events__free_terms() Fixing a leak, since code calling parse_events__free_terms() expect it to free the list_head too. Signed-off-by: Wang Nan Acked-by: Jiri Olsa Cc: Alexei Starovoitov Cc: He Kuang Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com [ Spun off from another patch ] Link: http://lkml.kernel.org/r/1454680939-24963-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 668afdccfcca..d1b49ec7ae46 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -2081,6 +2081,7 @@ void parse_events_terms__purge(struct list_head *terms) void parse_events__free_terms(struct list_head *terms) { parse_events_terms__purge(terms); + free(terms); } void parse_events_evlist_error(struct parse_events_evlist *data, -- cgit From 8faa268ab780a7379cfe54b882c6f6e0083233f2 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 12 Feb 2016 09:30:17 -0800 Subject: ASoC: qcom: Don't specify LE device endianness This reverts commit 18560a4e3 (ASoC: qcom: Specify LE device endianness). The commit that caused us to specify LE device endianness here, 29bb45f25ff3 (regmap-mmio: Use native endianness for read/write, 2015-10-29), has been reverted in mainline so now when we specify LE it actively breaks big endian kernels because the byte swapping in regmap-mmio is incorrect. Let's revert this change because it will 1) fix the big endian kernels and 2) be redundant to specify LE because that will become the default soon. Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 00b6c9d039cf..e5101e0d2d37 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -355,7 +355,6 @@ static struct regmap_config lpass_cpu_regmap_config = { .readable_reg = lpass_cpu_regmap_readable, .volatile_reg = lpass_cpu_regmap_volatile, .cache_type = REGCACHE_FLAT, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) -- cgit From 223ffb29f9723a4b485cacf6dc7e6d639fffc322 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Thu, 11 Feb 2016 13:34:49 -0500 Subject: cgroup: provide cgroup_nov1= to disable controllers in v1 mounts Testing cgroup2 can be painful with system software automatically mounting and populating all cgroup controllers in v1 mode. Sometimes they can be unmounted from rc.local, sometimes even that is too late. Provide a commandline option to disable certain controllers in v1 mounts, so that they remain available for cgroup2 mounts. Example use: cgroup_no_v1=memory,cpu cgroup_no_v1=all Disabling will be confirmed at boot-time as such: [ 0.013770] Disabling cpu control group subsystem in v1 mounts [ 0.016004] Disabling memory control group subsystem in v1 mounts Signed-off-by: Johannes Weiner Signed-off-by: Tejun Heo --- kernel/cgroup.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/kernel/cgroup.c b/kernel/cgroup.c index d27904c193da..7ad61915967f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -180,6 +180,9 @@ EXPORT_SYMBOL_GPL(cgrp_dfl_root); */ static bool cgrp_dfl_root_visible; +/* Controllers blocked by the commandline in v1 */ +static unsigned long cgroup_no_v1_mask; + /* some controllers are not supported in the default hierarchy */ static unsigned long cgrp_dfl_root_inhibit_ss_mask; @@ -241,6 +244,11 @@ static bool cgroup_ssid_enabled(int ssid) return static_key_enabled(cgroup_subsys_enabled_key[ssid]); } +static bool cgroup_ssid_no_v1(int ssid) +{ + return cgroup_no_v1_mask & (1 << ssid); +} + /** * cgroup_on_dfl - test whether a cgroup is on the default hierarchy * @cgrp: the cgroup of interest @@ -1678,6 +1686,8 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) continue; if (!cgroup_ssid_enabled(i)) continue; + if (cgroup_ssid_no_v1(i)) + continue; /* Mutually exclusive option 'all' + subsystem name */ if (all_ss) @@ -1698,7 +1708,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) */ if (all_ss || (!one_ss && !opts->none && !opts->name)) for_each_subsys(ss, i) - if (cgroup_ssid_enabled(i)) + if (cgroup_ssid_enabled(i) && !cgroup_ssid_no_v1(i)) opts->subsys_mask |= (1 << i); /* @@ -5324,6 +5334,10 @@ int __init cgroup_init(void) continue; } + if (cgroup_ssid_no_v1(ssid)) + printk(KERN_INFO "Disabling %s control group subsystem in v1 mounts\n", + ss->name); + cgrp_dfl_root.subsys_mask |= 1 << ss->id; if (!ss->dfl_cftypes) @@ -5750,6 +5764,33 @@ static int __init cgroup_disable(char *str) } __setup("cgroup_disable=", cgroup_disable); +static int __init cgroup_no_v1(char *str) +{ + struct cgroup_subsys *ss; + char *token; + int i; + + while ((token = strsep(&str, ",")) != NULL) { + if (!*token) + continue; + + if (!strcmp(token, "all")) { + cgroup_no_v1_mask = ~0UL; + break; + } + + for_each_subsys(ss, i) { + if (strcmp(token, ss->name) && + strcmp(token, ss->legacy_name)) + continue; + + cgroup_no_v1_mask |= 1 << i; + } + } + return 1; +} +__setup("cgroup_no_v1=", cgroup_no_v1); + /** * css_tryget_online_from_dir - get corresponding css from a cgroup dentry * @dentry: directory dentry of interest -- cgit From 2146afc6b45b3f1b967f5605d4e6d97dd9e31061 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Feb 2016 17:09:17 -0300 Subject: perf tools: Rename parse_events__free_terms() to parse_events_terms__delete() To follow convention used in other tools/perf/ areas. Also remove the need to check if it is NULL before calling the destructor, again, to follow convention that goes back to free(). Cc: Alexei Starovoitov Cc: He Kuang cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Wang Nan Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/n/tip-w6owu7rb8a46gvunlinxaqwx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/intel-pt.c | 2 +- tools/perf/util/parse-events.c | 7 ++++--- tools/perf/util/parse-events.h | 2 +- tools/perf/util/parse-events.y | 8 ++++---- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 6f7d453b0e32..a3395179c9ee 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -89,7 +89,7 @@ static int intel_pt_parse_terms_with_default(struct list_head *formats, *config = attr.config; out_free: - parse_events__free_terms(terms); + parse_events_terms__delete(terms); return err; } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index d1b49ec7ae46..e5583fd4e7bd 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1386,8 +1386,7 @@ int parse_events_terms(struct list_head *terms, const char *str) return 0; } - if (data.terms) - parse_events__free_terms(data.terms); + parse_events_terms__delete(data.terms); return ret; } @@ -2078,8 +2077,10 @@ void parse_events_terms__purge(struct list_head *terms) } } -void parse_events__free_terms(struct list_head *terms) +void parse_events_terms__delete(struct list_head *terms) { + if (!terms) + return; parse_events_terms__purge(terms); free(terms); } diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index f90a04ccab39..53628bf3da67 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -115,7 +115,7 @@ int parse_events_term__sym_hw(struct parse_events_term **term, char *config, unsigned idx); int parse_events_term__clone(struct parse_events_term **new, struct parse_events_term *term); -void parse_events__free_terms(struct list_head *terms); +void parse_events_terms__delete(struct list_head *terms); void parse_events_terms__purge(struct list_head *terms); int parse_events__modifier_event(struct list_head *list, char *str, bool add); int parse_events__modifier_group(struct list_head *list, char *event_mod); diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index ad379968d4c1..c0eac88ef474 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -218,7 +218,7 @@ PE_NAME '/' event_config '/' ALLOC_LIST(list); ABORT_ON(parse_events_add_pmu(data, list, $1, $3)); - parse_events__free_terms($3); + parse_events_terms__delete($3); $$ = list; } | @@ -246,7 +246,7 @@ PE_KERNEL_PMU_EVENT sep_dc ALLOC_LIST(list); ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); - parse_events__free_terms(head); + parse_events_terms__delete(head); $$ = list; } | @@ -266,7 +266,7 @@ PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc ALLOC_LIST(list); ABORT_ON(parse_events_add_pmu(data, list, "cpu", head)); - parse_events__free_terms(head); + parse_events_terms__delete(head); $$ = list; } @@ -285,7 +285,7 @@ value_sym '/' event_config '/' ALLOC_LIST(list); ABORT_ON(parse_events_add_numeric(data, list, type, config, $3)); - parse_events__free_terms($3); + parse_events_terms__delete($3); $$ = list; } | -- cgit From 5141d7350d3d8a12f1f76b1015b937f14d2b97e2 Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Fri, 5 Feb 2016 14:01:30 +0000 Subject: perf data: Fix releasing event_class A new patch in libbabeltrace [1] reveals a object leak problem in 'perf data' CTF support: perf code never releases the event_class which is allocated in add_event() and stored in evsel's private field. If libbabeltrace has the above patch applied, leaking event_class prevents the writer from being destroyed and flushing metadata. For example: $ perf record ls perf.data [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (12 samples) ] $ perf data convert --to-ctf ./out.ctf [ perf data convert: Converted 'perf.data' into CTF data './out.ctf' ] [ perf data convert: Converted and wrote 0.000 MB (12 samples) ] $ cat ./out.ctf/metadata $ ls -l ./out.ctf/metadata -rw-r----- 1 w00229757 mm 0 Jan 27 10:49 ./out.ctf/metadata The correct result should be: ... $ cat ./out.ctf/metadata /* CTF 1.8 */ trace { [SNIP] $ ls -l ./out.ctf/metadata -rw-r----- 1 w00229757 mm 2446 Jan 27 10:52 ./out.ctf/metadata The full story is: Patch [1] of babeltrace redesigns its reference counting scheme. In that patch: * writer <- trace (bt_ctf_writer_create) * trace <- stream_class (bt_ctf_trace_add_stream_class) * stream_class <- event_class (bt_ctf_stream_class_add_event_class) ('<-' means 'is a parent of') Holding of event_class causes reference count of corresponding 'writer' to increase through parent chain. Perf expects that 'writer' is released (so metadata is flushed) through bt_ctf_writer_put() in ctf_writer__cleanup(). However, since it never releases event_class, the reference of 'writer' won't be dropped, so bt_ctf_writer_put() won't lead to the release of writer. Before this CTF patch, !(writer <- trace). Even with event_class leaking, the writer ends up being released. [1] https://github.com/efficios/babeltrace/commit/e6a8e8e4744633807083a077ff9f101eb97d9801 Signed-off-by: Wang Nan Acked-by: Jiri Olsa Cc: Adrian Hunter Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Cody P Schafer Cc: He Kuang Cc: Jeremie Galarneau Cc: Kirill Smelkov Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1454680939-24963-6-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/data-convert-bt.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 34cd1e4039d3..b722e57d5a87 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -858,6 +858,23 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session) return 0; } +static void cleanup_events(struct perf_session *session) +{ + struct perf_evlist *evlist = session->evlist; + struct perf_evsel *evsel; + + evlist__for_each(evlist, evsel) { + struct evsel_priv *priv; + + priv = evsel->priv; + bt_ctf_event_class_put(priv->event_class); + zfree(&evsel->priv); + } + + perf_evlist__delete(evlist); + session->evlist = NULL; +} + static int setup_streams(struct ctf_writer *cw, struct perf_session *session) { struct ctf_stream **stream; @@ -1171,6 +1188,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force) (double) c.events_size / 1024.0 / 1024.0, c.events_count); + cleanup_events(session); perf_session__delete(session); ctf_writer__cleanup(cw); -- cgit From bde7fabad93ddea8fbefa8da90a4142801b03d37 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 8 Feb 2016 10:55:55 -0600 Subject: dt/bindings: add documentation on standard property unit suffixes A common review comment is to add units to DT property names. The naming convention is inconsistent unfortunately although there are clear majorities in use already. This makes it hard to remember the exact name preferred, so I'm documenting this to provide an easy point of reference. Signed-off-by: Rob Herring Cc: Pawel Moll Acked-by: Mark Rutland Cc: Ian Campbell Cc: Kumar Gala --- .../devicetree/bindings/property-units.txt | 39 ++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Documentation/devicetree/bindings/property-units.txt diff --git a/Documentation/devicetree/bindings/property-units.txt b/Documentation/devicetree/bindings/property-units.txt new file mode 100644 index 000000000000..12278d79f6c0 --- /dev/null +++ b/Documentation/devicetree/bindings/property-units.txt @@ -0,0 +1,39 @@ +Standard Unit Suffixes for Property names + +Properties which have a unit of measure are recommended to have a unit +suffix appended to the property name. The list below contains the +recommended suffixes. Other variations exist in bindings, but should not +be used in new bindings or added here. The inconsistency in the unit +prefixes is due to selecting the most commonly used variants. + +It is also recommended to use the units listed here and not add additional +unit prefixes. + +Time/Frequency +---------------------------------------- +-mhz : megahertz +-hz : Hertz (preferred) +-sec : seconds +-ms : milliseconds +-us : microseconds +-ns : nanoseconds + +Distance +---------------------------------------- +-mm : millimeters + +Electricity +---------------------------------------- +-microamp : micro amps +-ohms : Ohms +-micro-ohms : micro Ohms +-microvolt : micro volts + +Temperature +---------------------------------------- +-celsius : Degrees Celsius +-millicelsius : Degreee milli-Celsius + +Pressure +---------------------------------------- +-kpascal : kiloPascal -- cgit From 4d44e095fbb91c5503ccd119aeeb1bce9af0dee3 Mon Sep 17 00:00:00 2001 From: "Maciej S. Szmigiero" Date: Fri, 5 Feb 2016 00:19:56 +0100 Subject: of: Add United Radiant Technology Corporation vendor prefix Add vendor prefix for United Radiant Technology Corporation, a provider of liquid crystal display technologies. Signed-off-by: Maciej S. Szmigiero 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 72e2c5a2b327..1bcef7300b37 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -240,6 +240,7 @@ tplink TP-LINK Technologies Co., Ltd. tronfy Tronfy truly Truly Semiconductors Limited upisemi uPI Semiconductor Corp. +urt United Radiant Technology Corporation usi Universal Scientific Industrial Co., Ltd. v3 V3 Semiconductor variscite Variscite Ltd. -- cgit From a947b724069a25eae86d8dfed905374d04c3f93c Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 12 Feb 2016 09:30:17 -0800 Subject: ASoC: qcom: Don't specify LE device endianness This reverts commit 18560a4e3 (ASoC: qcom: Specify LE device endianness). The commit that caused us to specify LE device endianness here, 29bb45f25ff3 (regmap-mmio: Use native endianness for read/write, 2015-10-29), has been reverted in mainline so now when we specify LE it actively breaks big endian kernels because the byte swapping in regmap-mmio is incorrect. Let's revert this change because it will 1) fix the big endian kernels and 2) be redundant to specify LE because that will become the default soon. Signed-off-by: Stephen Boyd Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index 00b6c9d039cf..e5101e0d2d37 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -355,7 +355,6 @@ static struct regmap_config lpass_cpu_regmap_config = { .readable_reg = lpass_cpu_regmap_readable, .volatile_reg = lpass_cpu_regmap_volatile, .cache_type = REGCACHE_FLAT, - .val_format_endian = REGMAP_ENDIAN_LITTLE, }; int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) -- cgit From d4930cf0ae33e944427f974f33bc43b8e6c56456 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Wed, 10 Feb 2016 21:37:30 +0100 Subject: regulator: ltc3589: Make IRQ optional It's perfectly valid to use the LTC3589 without an interrupt pin connected to it. Currently, the driver probing fails when client->irq is 0 (which means "no interrupt"). Don't register the interrupt handler in that case but successfully finish the device probing instead. Signed-off-by: Bernhard Walle Signed-off-by: Mark Brown --- drivers/regulator/ltc3589.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index 972c386b2690..47bef328fb58 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -520,12 +520,15 @@ static int ltc3589_probe(struct i2c_client *client, } } - ret = devm_request_threaded_irq(dev, client->irq, NULL, ltc3589_isr, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - client->name, ltc3589); - if (ret) { - dev_err(dev, "Failed to request IRQ: %d\n", ret); - return ret; + if (client->irq) { + ret = devm_request_threaded_irq(dev, client->irq, NULL, + ltc3589_isr, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + client->name, ltc3589); + if (ret) { + dev_err(dev, "Failed to request IRQ: %d\n", ret); + return ret; + } } return 0; -- cgit From 6541aef01a9b308f280d3f2d26a46858e6dbef6a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 12 Feb 2016 23:56:21 +0100 Subject: cpufreq: Drop unnecessary checks from show() and store() The show() and store() routines in the cpufreq core don't need to check if the struct freq_attr they want to use really provides the callbacks they need as expected (if that's not the case, it means a bug in the code anyway), so change them to avoid doing that. Signed-off-by: Rafael J. Wysocki Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 34b17447e0d1..78a262f3d9ab 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -818,12 +818,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) ssize_t ret; down_read(&policy->rwsem); - - if (fattr->show) - ret = fattr->show(policy, buf); - else - ret = -EIO; - + ret = fattr->show(policy, buf); up_read(&policy->rwsem); return ret; @@ -838,18 +833,12 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, get_online_cpus(); - if (!cpu_online(policy->cpu)) - goto unlock; - - down_write(&policy->rwsem); - - if (fattr->store) + if (cpu_online(policy->cpu)) { + down_write(&policy->rwsem); ret = fattr->store(policy, buf, count); - else - ret = -EIO; + up_write(&policy->rwsem); + } - up_write(&policy->rwsem); -unlock: put_online_cpus(); return ret; -- cgit From 657d32efe04197736ed328a34ba659b5172c8cce Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 12 Feb 2016 09:38:33 +0300 Subject: spi: checking for NULL instead of IS_ERR spi_replace_transfers() returns error pointers on error, it never returns NULL. Fixes: d9f121227281 ('spi: core: add spi_split_transfers_maxsize') Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown --- drivers/spi/spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 34e3741504f9..801e8900898b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2262,8 +2262,8 @@ int __spi_split_transfer_maxsize(struct spi_master *master, /* create replacement */ srt = spi_replace_transfers(msg, xfer, 1, count, NULL, 0, gfp); - if (!srt) - return -ENOMEM; + if (IS_ERR(srt)) + return PTR_ERR(srt); xfers = srt->inserted_transfers; /* now handle each of those newly inserted spi_transfers -- cgit From 5fd7a09cfb8c6852f596c1f8c891c6158395250e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 11 Aug 2015 18:03:23 +0200 Subject: atomic: Export fetch_or() Export fetch_or() that's implemented and used internally by the scheduler. We are going to use it for NO_HZ so make it generally available. Reviewed-by: Chris Metcalf Cc: Christoph Lameter Cc: Chris Metcalf Cc: Ingo Molnar Cc: Luiz Capitulino Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Cc: Viresh Kumar Signed-off-by: Frederic Weisbecker --- include/linux/atomic.h | 21 +++++++++++++++++++++ kernel/sched/core.c | 14 -------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/linux/atomic.h b/include/linux/atomic.h index 301de78d65f7..6c502cb13c95 100644 --- a/include/linux/atomic.h +++ b/include/linux/atomic.h @@ -548,6 +548,27 @@ static inline int atomic_dec_if_positive(atomic_t *v) } #endif +/** + * fetch_or - perform *ptr |= mask and return old value of *ptr + * @ptr: pointer to value + * @mask: mask to OR on the value + * + * cmpxchg based fetch_or, macro so it works for different integer types + */ +#ifndef fetch_or +#define fetch_or(ptr, mask) \ +({ typeof(*(ptr)) __old, __val = *(ptr); \ + for (;;) { \ + __old = cmpxchg((ptr), __val, __val | (mask)); \ + if (__old == __val) \ + break; \ + __val = __old; \ + } \ + __old; \ +}) +#endif + + #ifdef CONFIG_GENERIC_ATOMIC64 #include #endif diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 9503d590e5ef..7142feb4b92d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -453,20 +453,6 @@ static inline void init_hrtick(void) } #endif /* CONFIG_SCHED_HRTICK */ -/* - * cmpxchg based fetch_or, macro so it works for different integer types - */ -#define fetch_or(ptr, val) \ -({ typeof(*(ptr)) __old, __val = *(ptr); \ - for (;;) { \ - __old = cmpxchg((ptr), __val, __val | (val)); \ - if (__old == __val) \ - break; \ - __val = __old; \ - } \ - __old; \ -}) - #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) /* * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, -- cgit From 8537bb95a63e4be330359721f0ecd422f4a4c0ca Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 7 Dec 2015 16:55:23 +0100 Subject: nohz: Implement wide kick on top of irq work It simplifies it and allows wide kick to be performed, even when IRQs are disabled, without an asynchronous level in the middle. This comes at a cost of some more overhead on features like perf and posix cpu timers slow-paths, which is probably not much important for nohz full users. Requested-by: Peter Zijlstra Reviewed-by: Chris Metcalf Cc: Christoph Lameter Cc: Chris Metcalf Cc: Ingo Molnar Cc: Luiz Capitulino Cc: Peter Zijlstra Cc: Rik van Riel Cc: Thomas Gleixner Cc: Viresh Kumar Signed-off-by: Frederic Weisbecker --- kernel/time/tick-sched.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 0b17424349eb..548a4e2551a9 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -234,24 +234,20 @@ void tick_nohz_full_kick_cpu(int cpu) irq_work_queue_on(&per_cpu(nohz_full_kick_work, cpu), cpu); } -static void nohz_full_kick_ipi(void *info) -{ - /* Empty, the tick restart happens on tick_nohz_irq_exit() */ -} - /* * Kick all full dynticks CPUs in order to force these to re-evaluate * their dependency on the tick and restart it if necessary. */ void tick_nohz_full_kick_all(void) { + int cpu; + if (!tick_nohz_full_running) return; preempt_disable(); - smp_call_function_many(tick_nohz_full_mask, - nohz_full_kick_ipi, NULL, false); - tick_nohz_full_kick(); + for_each_cpu_and(cpu, tick_nohz_full_mask, cpu_online_mask) + tick_nohz_full_kick_cpu(cpu); preempt_enable(); } -- cgit From bbcfb8930e150a5d1798dfb564c6e476e46b8ed4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 13 Feb 2016 23:46:10 +0800 Subject: spi: bcm2835: Remove duplicate depend on GPIOLIB in Kconfig Signed-off-by: Axel Lin Signed-off-by: Mark Brown --- drivers/spi/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 77064160dd76..830a30be6a5e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -79,7 +79,6 @@ config SPI_BCM2835 tristate "BCM2835 SPI controller" depends on GPIOLIB depends on ARCH_BCM2835 || COMPILE_TEST - depends on GPIOLIB help This selects a driver for the Broadcom BCM2835 SPI master. -- cgit From 82f68756e94c70767a5b4747dc084a1a81e61a00 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Wed, 3 Feb 2016 23:39:01 +0530 Subject: of: resolver: Add missing of_node_get and of_node_put In __of_find_node_by_full_name, add an of_node_get when detecting the desired element, to ensure that it ends up with a reference count that is one greater than on entering the function. Also in __of_find_node_by_full_name, add an of_node_put on breaking out of the for_each_child_of_node loop, to ensure that the reference count of the returned value is not double incremented. This change was made using Coccinelle. The semantic patch used for this is as follows: // @@ expression e; local idexpression n; @@ for_each_child_of_node(..., n) { ... when != of_node_put(n) when != e = n ( return n; | + of_node_put(n); ? return ...; ) ... } // Signed-off-by: Rob Herring --- drivers/of/resolver.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c index 640eb4cb46e3..d313d492f278 100644 --- a/drivers/of/resolver.c +++ b/drivers/of/resolver.c @@ -36,12 +36,14 @@ static struct device_node *__of_find_node_by_full_name(struct device_node *node, /* check */ if (of_node_cmp(node->full_name, full_name) == 0) - return node; + return of_node_get(node); for_each_child_of_node(node, child) { found = __of_find_node_by_full_name(child, full_name); - if (found != NULL) + if (found != NULL) { + of_node_put(child); return found; + } } return NULL; @@ -174,6 +176,7 @@ static int __of_adjust_phandle_ref(struct device_node *node, if (of_prop_cmp(sprop->name, propstr) == 0) break; } + of_node_put(refnode); if (!sprop) { pr_err("%s: Could not find property '%s'\n", -- cgit From c278ac0ecd198a3a1be5b2f1159ffec2e3107ecb Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Fri, 12 Feb 2016 13:44:42 +0200 Subject: iio: imu: inv-mpu6050: Fix interrupt pin configuration The select/deselect_bypass duo writes the irq number into the interrupt configuration register. If there is a i2c slave device connected to the mpu (eg. a magnetometer) then this can hinder interrupt delivery for the accelerometer and gyroscope. Set this register to the default configuration. Signed-off-by: Adriana Reus Reviewed-by: Lucas De Marchi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 4 ++-- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 0852b7fa777e..1121f4ee2914 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -129,7 +129,7 @@ static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, if (!ret) { st->powerup_count++; ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, - st->client->irq | + INV_MPU6050_INT_PIN_CFG | INV_MPU6050_BIT_BYPASS_EN); } write_error: @@ -147,7 +147,7 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, mutex_lock(&indio_dev->mlock); /* It doesn't really mattter, if any of the calls fails */ inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, - st->client->irq); + INV_MPU6050_INT_PIN_CFG); st->powerup_count--; if (!st->powerup_count) inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index db0a4a2758ab..455b99db64ba 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -185,6 +185,7 @@ struct inv_mpu6050_state { #define INV_MPU6050_REG_INT_PIN_CFG 0x37 #define INV_MPU6050_BIT_BYPASS_EN 0x2 +#define INV_MPU6050_INT_PIN_CFG 0 /* init parameters */ #define INV_MPU6050_INIT_FIFO_RATE 50 -- cgit From d430f3c36ca6e71f30c00757f5d43ca83b890ff4 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Fri, 12 Feb 2016 13:44:43 +0200 Subject: iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Use regmap instead of i2c specific functions. This is in preparation of splitting this driver into core and i2c specific functionality. Signed-off-by: Adriana Reus Acked-by: Crt Mori Reviewed-by: Lucas De Marchi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 1 + drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 71 ++++++++++++++------------- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 30 ++++++----- drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 6 +-- 5 files changed, 57 insertions(+), 53 deletions(-) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 48fbc0bc7e2a..f301f3a73ffa 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -8,6 +8,7 @@ config INV_MPU6050_IIO select IIO_BUFFER select IIO_TRIGGERED_BUFFER select I2C_MUX + select REGMAP_I2C help This driver supports the Invensense MPU6050 devices. This driver can also support MPU6500 in MPU6050 compatibility mode diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 1121f4ee2914..151a37879938 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -27,6 +27,11 @@ #include #include "inv_mpu_iio.h" +static const struct regmap_config inv_mpu_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + /* * this is the gyro scale translated from dynamic range plus/minus * {250, 500, 1000, 2000} to rad/s @@ -75,11 +80,6 @@ static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = { }, }; -int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d) -{ - return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d); -} - /* * The i2c read/write needs to happen in unlocked mode. As the parent * adapter is common. If we use locked versions, it will fail as @@ -159,16 +159,15 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) { - u8 d, mgmt_1; + unsigned int d, mgmt_1; int result; /* switch clock needs to be careful. Only when gyro is on, can clock source be switched to gyro. Otherwise, it must be set to internal clock */ if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) { - result = i2c_smbus_read_i2c_block_data(st->client, - st->reg->pwr_mgmt_1, 1, &mgmt_1); - if (result != 1) + result = regmap_read(st->map, st->reg->pwr_mgmt_1, &mgmt_1); + if (result) return result; mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK; @@ -178,20 +177,19 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) /* turning off gyro requires switch to internal clock first. Then turn off gyro engine */ mgmt_1 |= INV_CLK_INTERNAL; - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1); + result = regmap_write(st->map, st->reg->pwr_mgmt_1, mgmt_1); if (result) return result; } - result = i2c_smbus_read_i2c_block_data(st->client, - st->reg->pwr_mgmt_2, 1, &d); - if (result != 1) + result = regmap_read(st->map, st->reg->pwr_mgmt_2, &d); + if (result) return result; if (en) d &= ~mask; else d |= mask; - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d); + result = regmap_write(st->map, st->reg->pwr_mgmt_2, d); if (result) return result; @@ -201,7 +199,7 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) { /* switch internal clock to PLL */ mgmt_1 |= INV_CLK_PLL; - result = inv_mpu6050_write_reg(st, + result = regmap_write(st->map, st->reg->pwr_mgmt_1, mgmt_1); if (result) return result; @@ -218,15 +216,14 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) if (power_on) { /* Already under indio-dev->mlock mutex */ if (!st->powerup_count) - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, - 0); + result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0); if (!result) st->powerup_count++; } else { st->powerup_count--; if (!st->powerup_count) - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, - INV_MPU6050_BIT_SLEEP); + result = regmap_write(st->map, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); } if (result) @@ -257,22 +254,22 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev) if (result) return result; d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT); - result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d); + result = regmap_write(st->map, st->reg->gyro_config, d); if (result) return result; d = INV_MPU6050_FILTER_20HZ; - result = inv_mpu6050_write_reg(st, st->reg->lpf, d); + result = regmap_write(st->map, st->reg->lpf, d); if (result) return result; d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1; - result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d); + result = regmap_write(st->map, st->reg->sample_rate_div, d); if (result) return result; d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); - result = inv_mpu6050_write_reg(st, st->reg->accl_config, d); + result = regmap_write(st->map, st->reg->accl_config, d); if (result) return result; @@ -290,9 +287,8 @@ static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg, __be16 d; ind = (axis - IIO_MOD_X) * 2; - result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2, - (u8 *)&d); - if (result != 2) + result = regmap_bulk_read(st->map, reg + ind, (u8 *)&d, 2); + if (result) return -EINVAL; *val = (short)be16_to_cpup(&d); @@ -418,8 +414,7 @@ static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val) for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) { if (gyro_scale_6050[i] == val) { d = (i << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT); - result = inv_mpu6050_write_reg(st, - st->reg->gyro_config, d); + result = regmap_write(st->map, st->reg->gyro_config, d); if (result) return result; @@ -456,8 +451,7 @@ static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val) for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) { if (accel_scale[i] == val) { d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT); - result = inv_mpu6050_write_reg(st, - st->reg->accl_config, d); + result = regmap_write(st->map, st->reg->accl_config, d); if (result) return result; @@ -537,7 +531,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate) while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1)) i++; data = d[i]; - result = inv_mpu6050_write_reg(st, st->reg->lpf, data); + result = regmap_write(st->map, st->reg->lpf, data); if (result) return result; st->chip_config.lpf = data; @@ -575,7 +569,7 @@ static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev, goto fifo_rate_fail; d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1; - result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d); + result = regmap_write(st->map, st->reg->sample_rate_div, d); if (result) goto fifo_rate_fail; st->chip_config.fifo_rate = fifo_rate; @@ -736,8 +730,8 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) st->reg = hw_info[st->chip_type].reg; /* reset to make sure previous state are not there */ - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, - INV_MPU6050_BIT_H_RESET); + result = regmap_write(st->map, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_H_RESET); if (result) return result; msleep(INV_MPU6050_POWER_UP_TIME); @@ -778,11 +772,19 @@ static int inv_mpu_probe(struct i2c_client *client, struct iio_dev *indio_dev; struct inv_mpu6050_platform_data *pdata; int result; + struct regmap *regmap; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) 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", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -790,6 +792,7 @@ static int inv_mpu_probe(struct i2c_client *client, st = iio_priv(indio_dev); st->client = client; st->powerup_count = 0; + st->map = regmap; pdata = dev_get_platdata(&client->dev); if (pdata) st->plat_data = *pdata; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 455b99db64ba..469cd1f011de 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -125,6 +126,7 @@ struct inv_mpu6050_state { unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); + struct regmap *map; }; /*register and associated bit definition*/ diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index ba27e277511f..eb19dae8dda7 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -41,22 +40,22 @@ int inv_reset_fifo(struct iio_dev *indio_dev) struct inv_mpu6050_state *st = iio_priv(indio_dev); /* disable interrupt */ - result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0); + result = regmap_write(st->map, st->reg->int_enable, 0); if (result) { dev_err(&st->client->dev, "int_enable failed %d\n", result); return result; } /* disable the sensor output to FIFO */ - result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0); + result = regmap_write(st->map, st->reg->fifo_en, 0); if (result) goto reset_fifo_fail; /* disable fifo reading */ - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0); + result = regmap_write(st->map, st->reg->user_ctrl, 0); if (result) goto reset_fifo_fail; /* reset FIFO*/ - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, + result = regmap_write(st->map, st->reg->user_ctrl, INV_MPU6050_BIT_FIFO_RST); if (result) goto reset_fifo_fail; @@ -67,13 +66,13 @@ int inv_reset_fifo(struct iio_dev *indio_dev) /* enable interrupt */ if (st->chip_config.accl_fifo_enable || st->chip_config.gyro_fifo_enable) { - result = inv_mpu6050_write_reg(st, st->reg->int_enable, + result = regmap_write(st->map, st->reg->int_enable, INV_MPU6050_BIT_DATA_RDY_EN); if (result) return result; } /* enable FIFO reading and I2C master interface*/ - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, + result = regmap_write(st->map, st->reg->user_ctrl, INV_MPU6050_BIT_FIFO_EN); if (result) goto reset_fifo_fail; @@ -83,7 +82,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev) d |= INV_MPU6050_BITS_GYRO_OUT; if (st->chip_config.accl_fifo_enable) d |= INV_MPU6050_BIT_ACCEL_OUT; - result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d); + result = regmap_write(st->map, st->reg->fifo_en, d); if (result) goto reset_fifo_fail; @@ -91,7 +90,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev) reset_fifo_fail: dev_err(&st->client->dev, "reset fifo failed %d\n", result); - result = inv_mpu6050_write_reg(st, st->reg->int_enable, + result = regmap_write(st->map, st->reg->int_enable, INV_MPU6050_BIT_DATA_RDY_EN); return result; @@ -143,10 +142,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) * read fifo_count register to know how many bytes inside FIFO * right now */ - result = i2c_smbus_read_i2c_block_data(st->client, + result = regmap_bulk_read(st->map, st->reg->fifo_count_h, - INV_MPU6050_FIFO_COUNT_BYTE, data); - if (result != INV_MPU6050_FIFO_COUNT_BYTE) + data, INV_MPU6050_FIFO_COUNT_BYTE); + if (result) goto end_session; fifo_count = be16_to_cpup((__be16 *)(&data[0])); if (fifo_count < bytes_per_datum) @@ -161,10 +160,9 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR) goto flush_fifo; while (fifo_count >= bytes_per_datum) { - result = i2c_smbus_read_i2c_block_data(st->client, - st->reg->fifo_r_w, - bytes_per_datum, data); - if (result != bytes_per_datum) + result = regmap_bulk_read(st->map, st->reg->fifo_r_w, + data, bytes_per_datum); + if (result) goto flush_fifo; result = kfifo_out(&st->timestamps, ×tamp, 1); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index 844610c3a3a9..ee9e66dc5350 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -65,15 +65,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) if (result) return result; } else { - result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0); + result = regmap_write(st->map, st->reg->fifo_en, 0); if (result) return result; - result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0); + result = regmap_write(st->map, st->reg->int_enable, 0); if (result) return result; - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0); + result = regmap_write(st->map, st->reg->user_ctrl, 0); if (result) return result; -- cgit From b3eea8dacfb758baa0fe78e0cf24d5e5d288c5fe Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Fri, 12 Feb 2016 13:44:44 +0200 Subject: iio: imu: inv_mpu6050: Separate driver into core and i2c functionality. Separate this driver into core and i2c functionality. This is in preparation for adding spi support. Signed-off-by: Adriana Reus Reviewed-by: Lucas De Marchi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 10 +- drivers/iio/imu/inv_mpu6050/Makefile | 5 +- drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 18 ++- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 208 ++++---------------------- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 206 +++++++++++++++++++++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 12 +- drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 5 +- drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 4 +- 8 files changed, 265 insertions(+), 203 deletions(-) create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index f301f3a73ffa..b14df9a7540b 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -3,10 +3,14 @@ # config INV_MPU6050_IIO - tristate "Invensense MPU6050 devices" - depends on I2C && SYSFS + tristate select IIO_BUFFER select IIO_TRIGGERED_BUFFER + +config INV_MPU6050_I2C + tristate "Invensense MPU6050 devices (I2C)" + depends on I2C + select INV_MPU6050_IIO select I2C_MUX select REGMAP_I2C help @@ -15,4 +19,4 @@ config INV_MPU6050_IIO and also in MPU6500 mode with some limitations. It is a gyroscope/accelerometer combo device. This driver can be built as a module. The module will be called - inv-mpu6050. + inv-mpu6050-i2c. diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile index f566f6a7b3a9..ca4941d32e67 100644 --- a/drivers/iio/imu/inv_mpu6050/Makefile +++ b/drivers/iio/imu/inv_mpu6050/Makefile @@ -3,4 +3,7 @@ # obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o -inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o inv_mpu_acpi.o +inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o + +obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o +inv-mpu6050-i2c-objs := inv_mpu_i2c.o inv_mpu_acpi.o diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c index 1c982a56acd5..0bcfa8d231cf 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c @@ -139,22 +139,23 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client, return 0; } -int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st) +int inv_mpu_acpi_create_mux_client(struct i2c_client *client) { + struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev)); st->mux_client = NULL; - if (ACPI_HANDLE(&st->client->dev)) { + if (ACPI_HANDLE(&client->dev)) { struct i2c_board_info info; struct acpi_device *adev; int ret = -1; - adev = ACPI_COMPANION(&st->client->dev); + adev = ACPI_COMPANION(&client->dev); memset(&info, 0, sizeof(info)); dmi_check_system(inv_mpu_dev_list); switch (matched_product_name) { case INV_MPU_ASUS_T100TA: - ret = asus_acpi_get_sensor_info(adev, st->client, + ret = asus_acpi_get_sensor_info(adev, client, &info); break; /* Add more matched product processing here */ @@ -166,7 +167,7 @@ int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st) /* No matching DMI, so create device on INV6XX type */ unsigned short primary, secondary; - ret = inv_mpu_process_acpi_config(st->client, &primary, + ret = inv_mpu_process_acpi_config(client, &primary, &secondary); if (!ret && secondary) { char *name; @@ -191,8 +192,9 @@ int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st) return 0; } -void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st) +void inv_mpu_acpi_delete_mux_client(struct i2c_client *client) { + struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev)); if (st->mux_client) i2c_unregister_device(st->mux_client); } @@ -200,12 +202,12 @@ void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st) #include "inv_mpu_iio.h" -int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st) +int inv_mpu_acpi_create_mux_client(struct i2c_client *client) { return 0; } -void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st) +void inv_mpu_acpi_delete_mux_client(struct i2c_client *client) { } #endif diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 151a37879938..7b46db55571a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -27,11 +27,6 @@ #include #include "inv_mpu_iio.h" -static const struct regmap_config inv_mpu_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - /* * this is the gyro scale translated from dynamic range plus/minus * {250, 500, 1000, 2000} to rad/s @@ -80,83 +75,6 @@ static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = { }, }; -/* - * The i2c read/write needs to happen in unlocked mode. As the parent - * adapter is common. If we use locked versions, it will fail as - * the mux adapter will lock the parent i2c adapter, while calling - * select/deselect functions. - */ -static int inv_mpu6050_write_reg_unlocked(struct inv_mpu6050_state *st, - u8 reg, u8 d) -{ - int ret; - u8 buf[2]; - struct i2c_msg msg[1] = { - { - .addr = st->client->addr, - .flags = 0, - .len = sizeof(buf), - .buf = buf, - } - }; - - buf[0] = reg; - buf[1] = d; - ret = __i2c_transfer(st->client->adapter, msg, 1); - if (ret != 1) - return ret; - - return 0; -} - -static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, - u32 chan_id) -{ - struct iio_dev *indio_dev = mux_priv; - struct inv_mpu6050_state *st = iio_priv(indio_dev); - int ret = 0; - - /* Use the same mutex which was used everywhere to protect power-op */ - mutex_lock(&indio_dev->mlock); - if (!st->powerup_count) { - ret = inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, - 0); - if (ret) - goto write_error; - - msleep(INV_MPU6050_REG_UP_TIME); - } - if (!ret) { - st->powerup_count++; - ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, - INV_MPU6050_INT_PIN_CFG | - INV_MPU6050_BIT_BYPASS_EN); - } -write_error: - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, - void *mux_priv, u32 chan_id) -{ - struct iio_dev *indio_dev = mux_priv; - struct inv_mpu6050_state *st = iio_priv(indio_dev); - - mutex_lock(&indio_dev->mlock); - /* It doesn't really mattter, if any of the calls fails */ - inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg, - INV_MPU6050_INT_PIN_CFG); - st->powerup_count--; - if (!st->powerup_count) - inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1, - INV_MPU6050_BIT_SLEEP); - mutex_unlock(&indio_dev->mlock); - - return 0; -} - int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask) { unsigned int d, mgmt_1; @@ -758,42 +676,23 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) return 0; } -/** - * inv_mpu_probe() - probe function. - * @client: i2c client. - * @id: i2c device id. - * - * Returns 0 on success, a negative error code otherwise. - */ -static int inv_mpu_probe(struct i2c_client *client, - const struct i2c_device_id *id) +int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name) { struct inv_mpu6050_state *st; struct iio_dev *indio_dev; struct inv_mpu6050_platform_data *pdata; + struct device *dev = regmap_get_device(regmap); int result; - struct regmap *regmap; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_I2C_BLOCK)) - 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", - (int)PTR_ERR(regmap)); - return PTR_ERR(regmap); - } - - indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; st = iio_priv(indio_dev); - st->client = client; st->powerup_count = 0; + st->irq = irq; st->map = regmap; - pdata = dev_get_platdata(&client->dev); + pdata = dev_get_platdata(dev); if (pdata) st->plat_data = *pdata; /* power is turned on inside check chip type*/ @@ -803,18 +702,17 @@ static int inv_mpu_probe(struct i2c_client *client, result = inv_mpu6050_init_config(indio_dev); if (result) { - dev_err(&client->dev, - "Could not initialize device.\n"); + dev_err(dev, "Could not initialize device.\n"); return result; } - i2c_set_clientdata(client, indio_dev); - indio_dev->dev.parent = &client->dev; - /* id will be NULL when enumerated via ACPI */ - if (id) - indio_dev->name = (char *)id->name; + dev_set_drvdata(dev, indio_dev); + indio_dev->dev.parent = dev; + /* name will be NULL when enumerated via ACPI */ + if (name) + indio_dev->name = name; else - indio_dev->name = (char *)dev_name(&client->dev); + indio_dev->name = dev_name(dev); indio_dev->channels = inv_mpu_channels; indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); @@ -826,13 +724,12 @@ static int inv_mpu_probe(struct i2c_client *client, inv_mpu6050_read_fifo, NULL); if (result) { - dev_err(&st->client->dev, "configure buffer fail %d\n", - result); + dev_err(dev, "configure buffer fail %d\n", result); return result; } result = inv_mpu6050_probe_trigger(indio_dev); if (result) { - dev_err(&st->client->dev, "trigger probe fail %d\n", result); + dev_err(dev, "trigger probe fail %d\n", result); goto out_unreg_ring; } @@ -840,102 +737,47 @@ static int inv_mpu_probe(struct i2c_client *client, spin_lock_init(&st->time_stamp_lock); result = iio_device_register(indio_dev); if (result) { - dev_err(&st->client->dev, "IIO register fail %d\n", result); + dev_err(dev, "IIO register fail %d\n", result); goto out_remove_trigger; } - st->mux_adapter = i2c_add_mux_adapter(client->adapter, - &client->dev, - indio_dev, - 0, 0, 0, - inv_mpu6050_select_bypass, - inv_mpu6050_deselect_bypass); - if (!st->mux_adapter) { - result = -ENODEV; - goto out_unreg_device; - } - - result = inv_mpu_acpi_create_mux_client(st); - if (result) - goto out_del_mux; - return 0; -out_del_mux: - i2c_del_mux_adapter(st->mux_adapter); -out_unreg_device: - iio_device_unregister(indio_dev); out_remove_trigger: inv_mpu6050_remove_trigger(st); out_unreg_ring: iio_triggered_buffer_cleanup(indio_dev); return result; } +EXPORT_SYMBOL_GPL(inv_mpu_core_probe); -static int inv_mpu_remove(struct i2c_client *client) +int inv_mpu_core_remove(struct device *dev) { - struct iio_dev *indio_dev = i2c_get_clientdata(client); - struct inv_mpu6050_state *st = iio_priv(indio_dev); + struct iio_dev *indio_dev = dev_get_drvdata(dev); - inv_mpu_acpi_delete_mux_client(st); - i2c_del_mux_adapter(st->mux_adapter); iio_device_unregister(indio_dev); - inv_mpu6050_remove_trigger(st); + inv_mpu6050_remove_trigger(iio_priv(indio_dev)); iio_triggered_buffer_cleanup(indio_dev); return 0; } +EXPORT_SYMBOL_GPL(inv_mpu_core_remove); + #ifdef CONFIG_PM_SLEEP static int inv_mpu_resume(struct device *dev) { - return inv_mpu6050_set_power_itg( - iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true); + return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), true); } static int inv_mpu_suspend(struct device *dev) { - return inv_mpu6050_set_power_itg( - iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false); + return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), false); } -static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); - -#define INV_MPU6050_PMOPS (&inv_mpu_pmops) -#else -#define INV_MPU6050_PMOPS NULL #endif /* CONFIG_PM_SLEEP */ -/* - * device id table is used to identify what device can be - * supported by this driver - */ -static const struct i2c_device_id inv_mpu_id[] = { - {"mpu6050", INV_MPU6050}, - {"mpu6500", INV_MPU6500}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, inv_mpu_id); - -static const struct acpi_device_id inv_acpi_match[] = { - {"INVN6500", 0}, - { }, -}; - -MODULE_DEVICE_TABLE(acpi, inv_acpi_match); - -static struct i2c_driver inv_mpu_driver = { - .probe = inv_mpu_probe, - .remove = inv_mpu_remove, - .id_table = inv_mpu_id, - .driver = { - .name = "inv-mpu6050", - .pm = INV_MPU6050_PMOPS, - .acpi_match_table = ACPI_PTR(inv_acpi_match), - }, -}; - -module_i2c_driver(inv_mpu_driver); +SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume); +EXPORT_SYMBOL_GPL(inv_mpu_pmops); MODULE_AUTHOR("Invensense Corporation"); MODULE_DESCRIPTION("Invensense device MPU6050 driver"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c new file mode 100644 index 000000000000..eeaf969fbaef --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -0,0 +1,206 @@ +/* +* Copyright (C) 2012 Invensense, Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "inv_mpu_iio.h" + +static const struct regmap_config inv_mpu_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +/* + * The i2c read/write needs to happen in unlocked mode. As the parent + * adapter is common. If we use locked versions, it will fail as + * the mux adapter will lock the parent i2c adapter, while calling + * select/deselect functions. + */ +static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client, + u8 reg, u8 d) +{ + int ret; + u8 buf[2] = {reg, d}; + struct i2c_msg msg[1] = { + { + .addr = client->addr, + .flags = 0, + .len = sizeof(buf), + .buf = buf, + } + }; + + ret = __i2c_transfer(client->adapter, msg, 1); + if (ret != 1) + return ret; + + return 0; +} + +static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv, + u32 chan_id) +{ + struct i2c_client *client = mux_priv; + struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int ret = 0; + + /* Use the same mutex which was used everywhere to protect power-op */ + mutex_lock(&indio_dev->mlock); + if (!st->powerup_count) { + ret = inv_mpu6050_write_reg_unlocked(client, + st->reg->pwr_mgmt_1, 0); + if (ret) + goto write_error; + + msleep(INV_MPU6050_REG_UP_TIME); + } + if (!ret) { + st->powerup_count++; + ret = inv_mpu6050_write_reg_unlocked(client, + st->reg->int_pin_cfg, + INV_MPU6050_INT_PIN_CFG | + INV_MPU6050_BIT_BYPASS_EN); + } +write_error: + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap, + void *mux_priv, u32 chan_id) +{ + struct i2c_client *client = mux_priv; + struct iio_dev *indio_dev = dev_get_drvdata(&client->dev); + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + mutex_lock(&indio_dev->mlock); + /* It doesn't really mattter, if any of the calls fails */ + inv_mpu6050_write_reg_unlocked(client, st->reg->int_pin_cfg, + INV_MPU6050_INT_PIN_CFG); + st->powerup_count--; + if (!st->powerup_count) + inv_mpu6050_write_reg_unlocked(client, st->reg->pwr_mgmt_1, + INV_MPU6050_BIT_SLEEP); + mutex_unlock(&indio_dev->mlock); + + return 0; +} + +/** + * inv_mpu_probe() - probe function. + * @client: i2c client. + * @id: i2c device id. + * + * Returns 0 on success, a negative error code otherwise. + */ +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; + struct regmap *regmap; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) + 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", + (int)PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + result = inv_mpu_core_probe(regmap, client->irq, name); + if (result < 0) + 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; + goto out_unreg_device; + } + + result = inv_mpu_acpi_create_mux_client(client); + if (result) + goto out_del_mux; + + return 0; + +out_del_mux: + i2c_del_mux_adapter(st->mux_adapter); +out_unreg_device: + inv_mpu_core_remove(&client->dev); + return result; +} + +static int inv_mpu_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct inv_mpu6050_state *st = iio_priv(indio_dev); + + inv_mpu_acpi_delete_mux_client(client); + i2c_del_mux_adapter(st->mux_adapter); + + return inv_mpu_core_remove(&client->dev); +} + +/* + * device id table is used to identify what device can be + * supported by this driver + */ +static const struct i2c_device_id inv_mpu_id[] = { + {"mpu6050", INV_MPU6050}, + {"mpu6500", INV_MPU6500}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, inv_mpu_id); + +static const struct acpi_device_id inv_acpi_match[] = { + {"INVN6500", 0}, + { }, +}; + +MODULE_DEVICE_TABLE(acpi, inv_acpi_match); + +static struct i2c_driver inv_mpu_driver = { + .probe = inv_mpu_probe, + .remove = inv_mpu_remove, + .id_table = inv_mpu_id, + .driver = { + .acpi_match_table = ACPI_PTR(inv_acpi_match), + .name = "inv-mpu6050-i2c", + .pm = &inv_mpu_pmops, + }, +}; + +module_i2c_driver(inv_mpu_driver); + +MODULE_AUTHOR("Invensense Corporation"); +MODULE_DESCRIPTION("Invensense device MPU6050 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 469cd1f011de..1bf65a0fd323 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -108,9 +108,10 @@ struct inv_mpu6050_hw { * @hw: Other hardware-specific information. * @chip_type: chip type. * @time_stamp_lock: spin lock to time stamp. - * @client: i2c client handle. * @plat_data: platform data. * @timestamps: kfifo queue to store time stamp. + * @map regmap pointer. + * @irq interrupt number. */ struct inv_mpu6050_state { #define TIMESTAMP_FIFO_SIZE 16 @@ -120,13 +121,13 @@ struct inv_mpu6050_state { const struct inv_mpu6050_hw *hw; enum inv_devices chip_type; spinlock_t time_stamp_lock; - struct i2c_client *client; struct i2c_adapter *mux_adapter; struct i2c_client *mux_client; unsigned int powerup_count; struct inv_mpu6050_platform_data plat_data; DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE); struct regmap *map; + int irq; }; /*register and associated bit definition*/ @@ -255,5 +256,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev); int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask); int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val); int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on); -int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st); -void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st); +int inv_mpu_acpi_create_mux_client(struct i2c_client *client); +void inv_mpu_acpi_delete_mux_client(struct i2c_client *client); +int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name); +int inv_mpu_core_remove(struct device *dev); +extern const struct dev_pm_ops inv_mpu_pmops; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index eb19dae8dda7..1fc5fd96bb00 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -42,7 +42,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev) /* disable interrupt */ result = regmap_write(st->map, st->reg->int_enable, 0); if (result) { - dev_err(&st->client->dev, "int_enable failed %d\n", result); + dev_err(regmap_get_device(st->map), "int_enable failed %d\n", + result); return result; } /* disable the sensor output to FIFO */ @@ -89,7 +90,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev) return 0; reset_fifo_fail: - dev_err(&st->client->dev, "reset fifo failed %d\n", result); + dev_err(regmap_get_device(st->map), "reset fifo failed %d\n", result); result = regmap_write(st->map, st->reg->int_enable, INV_MPU6050_BIT_DATA_RDY_EN); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index ee9e66dc5350..72d6aae1894b 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -123,7 +123,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) if (!st->trig) return -ENOMEM; - ret = devm_request_irq(&indio_dev->dev, st->client->irq, + ret = devm_request_irq(&indio_dev->dev, st->irq, &iio_trigger_generic_data_rdy_poll, IRQF_TRIGGER_RISING, "inv_mpu", @@ -131,7 +131,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev) if (ret) return ret; - st->trig->dev.parent = &st->client->dev; + st->trig->dev.parent = regmap_get_device(st->map); st->trig->ops = &inv_mpu_trigger_ops; iio_trigger_set_drvdata(st->trig, indio_dev); -- cgit From fd64df16f40e367c393bf372fb67017301d701c2 Mon Sep 17 00:00:00 2001 From: Adriana Reus Date: Fri, 12 Feb 2016 13:44:45 +0200 Subject: iio: imu: inv_mpu6050: Add SPI support for MPU6000 The only difference between the MPU6000 and the MPU6050 is that the first also supports SPI. Add SPI driver for this chip. Signed-off-by: Adriana Reus Reviewed-by: Lucas De Marchi Signed-off-by: Jonathan Cameron --- drivers/iio/imu/inv_mpu6050/Kconfig | 11 ++++ drivers/iio/imu/inv_mpu6050/Makefile | 3 + drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 7 ++- drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 2 +- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 6 +- drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 97 ++++++++++++++++++++++++++++++ 6 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index b14df9a7540b..a7f557af4389 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -20,3 +20,14 @@ config INV_MPU6050_I2C It is a gyroscope/accelerometer combo device. This driver can be built as a module. The module will be called inv-mpu6050-i2c. + +config INV_MPU6050_SPI + tristate "Invensense MPU6050 devices (SPI)" + depends on SPI_MASTER + select INV_MPU6050_IIO + select REGMAP_SPI + help + This driver supports the Invensense MPU6050 devices. + It is a gyroscope/accelerometer combo device. + This driver can be built as a module. The module will be called + inv-mpu6050-spi. diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile index ca4941d32e67..734af5e6cef9 100644 --- a/drivers/iio/imu/inv_mpu6050/Makefile +++ b/drivers/iio/imu/inv_mpu6050/Makefile @@ -7,3 +7,6 @@ inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o inv-mpu6050-i2c-objs := inv_mpu_i2c.o inv_mpu_acpi.o + +obj-$(CONFIG_INV_MPU6050_SPI) += inv-mpu6050-spi.o +inv-mpu6050-spi-objs := inv_mpu_spi.o diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 7b46db55571a..225860016fed 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -152,6 +152,7 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on) return 0; } +EXPORT_SYMBOL_GPL(inv_mpu6050_set_power_itg); /** * inv_mpu6050_init_config() - Initialize hardware, disable FIFO. @@ -676,7 +677,8 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st) return 0; } -int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name) +int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, + int (*inv_mpu_bus_setup)(struct iio_dev *)) { struct inv_mpu6050_state *st; struct iio_dev *indio_dev; @@ -700,6 +702,9 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name) if (result) return result; + if (inv_mpu_bus_setup) + inv_mpu_bus_setup(indio_dev); + result = inv_mpu6050_init_config(indio_dev); if (result) { dev_err(dev, "Could not initialize device.\n"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index eeaf969fbaef..af400dd892a9 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -129,7 +129,7 @@ static int inv_mpu_probe(struct i2c_client *client, return PTR_ERR(regmap); } - result = inv_mpu_core_probe(regmap, client->irq, name); + result = inv_mpu_core_probe(regmap, client->irq, name, NULL); if (result < 0) return result; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 1bf65a0fd323..fcc2f3dfdfa8 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -62,6 +62,7 @@ struct inv_mpu6050_reg_map { enum inv_devices { INV_MPU6050, INV_MPU6500, + INV_MPU6000, INV_NUM_PARTS }; @@ -154,6 +155,7 @@ struct inv_mpu6050_state { #define INV_MPU6050_BIT_I2C_MST_EN 0x20 #define INV_MPU6050_BIT_FIFO_EN 0x40 #define INV_MPU6050_BIT_DMP_EN 0x80 +#define INV_MPU6050_BIT_I2C_IF_DIS 0x10 #define INV_MPU6050_REG_PWR_MGMT_1 0x6B #define INV_MPU6050_BIT_H_RESET 0x80 @@ -258,6 +260,8 @@ int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val); int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on); int inv_mpu_acpi_create_mux_client(struct i2c_client *client); void inv_mpu_acpi_delete_mux_client(struct i2c_client *client); -int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name); +int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, + int (*inv_mpu_bus_setup)(struct iio_dev *)); int inv_mpu_core_remove(struct device *dev); +int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on); extern const struct dev_pm_ops inv_mpu_pmops; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c new file mode 100644 index 000000000000..5b552a677340 --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -0,0 +1,97 @@ +/* +* Copyright (C) 2015 Intel Corporation Inc. +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ +#include +#include +#include +#include +#include +#include "inv_mpu_iio.h" + +static const struct regmap_config inv_mpu_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int inv_mpu_i2c_disable(struct iio_dev *indio_dev) +{ + struct inv_mpu6050_state *st = iio_priv(indio_dev); + int ret = 0; + + ret = inv_mpu6050_set_power_itg(st, true); + if (ret) + return ret; + + ret = regmap_write(st->map, INV_MPU6050_REG_USER_CTRL, + INV_MPU6050_BIT_I2C_IF_DIS); + if (ret) { + inv_mpu6050_set_power_itg(st, false); + return ret; + } + + return inv_mpu6050_set_power_itg(st, false); +} + +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; + + regmap = devm_regmap_init_spi(spi, &inv_mpu_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 inv_mpu_core_probe(regmap, spi->irq, name, inv_mpu_i2c_disable); +} + +static int inv_mpu_remove(struct spi_device *spi) +{ + return inv_mpu_core_remove(&spi->dev); +} + +/* + * device id table is used to identify what device can be + * supported by this driver + */ +static const struct spi_device_id inv_mpu_id[] = { + {"mpu6000", INV_MPU6000}, + {} +}; + +MODULE_DEVICE_TABLE(spi, inv_mpu_id); + +static const struct acpi_device_id inv_acpi_match[] = { + {"INVN6000", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, inv_acpi_match); + +static struct spi_driver inv_mpu_driver = { + .probe = inv_mpu_probe, + .remove = inv_mpu_remove, + .id_table = inv_mpu_id, + .driver = { + .acpi_match_table = ACPI_PTR(inv_acpi_match), + .name = "inv-mpu6000-spi", + .pm = &inv_mpu_pmops, + }, +}; + +module_spi_driver(inv_mpu_driver); + +MODULE_AUTHOR("Adriana Reus "); +MODULE_DESCRIPTION("Invensense device MPU6000 driver"); +MODULE_LICENSE("GPL"); -- cgit From 97a445dad37ab15090be910aa5295003f618ec44 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Thu, 11 Feb 2016 11:49:36 -0500 Subject: iio: Add IIO support for the DAC on the Apex Embedded Systems STX104 The Apex Embedded Systems STX104 is a 16-channel 16-bit analog input and 2-channel 16-bit analog output PC/104 card. The STX104 incorporates a large one mega-sample FIFO. This driver provides IIO support for the 2-channel DAC on the STX104. The base port addresses for the devices may be configured via the "base" module parameter array. Signed-off-by: William Breathitt Gray Signed-off-by: Jonathan Cameron --- MAINTAINERS | 6 ++ drivers/iio/dac/Kconfig | 9 +++ drivers/iio/dac/Makefile | 1 + drivers/iio/dac/stx104.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+) create mode 100644 drivers/iio/dac/stx104.c diff --git a/MAINTAINERS b/MAINTAINERS index 7c39a48b4118..3cbff940b5c9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -778,6 +778,12 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers) S: Maintained F: sound/aoa/ +APEX EMBEDDED SYSTEMS STX104 DAC DRIVER +M: William Breathitt Gray +L: linux-iio@vger.kernel.org +S: Maintained +F: drivers/iio/dac/stx104.c + APM DRIVER M: Jiri Kosina S: Odd fixes diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 3c809e2baecb..31a198510679 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -208,4 +208,13 @@ config MCP4922 To compile this driver as a module, choose M here: the module will be called mcp4922. +config STX104 + tristate "Apex Embedded Systems STX104 DAC driver" + depends on ISA + help + Say yes here to build support for the 2-channel DAC on the Apex + Embedded Systems STX104 integrated analog PC/104 card. The base port + addresses for the devices may be configured via the "base" module + parameter array. + endmenu diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index cb525b53fc7b..e2deda9c1ecb 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -22,3 +22,4 @@ obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX5821) += max5821.o obj-$(CONFIG_MCP4725) += mcp4725.o obj-$(CONFIG_MCP4922) += mcp4922.o +obj-$(CONFIG_STX104) += stx104.o diff --git a/drivers/iio/dac/stx104.c b/drivers/iio/dac/stx104.c new file mode 100644 index 000000000000..174f4b75ceed --- /dev/null +++ b/drivers/iio/dac/stx104.c @@ -0,0 +1,152 @@ +/* + * DAC driver for the Apex Embedded Systems STX104 + * Copyright (C) 2016 William Breathitt Gray + * + * 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 + +#define STX104_NUM_CHAN 2 + +#define STX104_CHAN(chan) { \ + .type = IIO_VOLTAGE, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .indexed = 1, \ + .output = 1 \ +} + +#define STX104_EXTENT 16 +/** + * The highest base address possible for an ISA device is 0x3FF; this results in + * 1024 possible base addresses. Dividing the number of possible base addresses + * by the address extent taken by each device results in the maximum number of + * devices on a system. + */ +#define MAX_NUM_STX104 (1024 / STX104_EXTENT) + +static unsigned base[MAX_NUM_STX104]; +static unsigned num_stx104; +module_param_array(base, uint, &num_stx104, 0); +MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses"); + +/** + * struct stx104_iio - IIO device private data structure + * @chan_out_states: channels' output states + * @base: base port address of the IIO device + */ +struct stx104_iio { + unsigned chan_out_states[STX104_NUM_CHAN]; + unsigned base; +}; + +static int stx104_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, int *val2, long mask) +{ + struct stx104_iio *const priv = iio_priv(indio_dev); + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + *val = priv->chan_out_states[chan->channel]; + + return IIO_VAL_INT; +} + +static int stx104_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long mask) +{ + struct stx104_iio *const priv = iio_priv(indio_dev); + const unsigned chan_addr_offset = 2 * chan->channel; + + if (mask != IIO_CHAN_INFO_RAW) + return -EINVAL; + + priv->chan_out_states[chan->channel] = val; + outw(val, priv->base + 4 + chan_addr_offset); + + return 0; +} + +static const struct iio_info stx104_info = { + .driver_module = THIS_MODULE, + .read_raw = stx104_read_raw, + .write_raw = stx104_write_raw +}; + +static const struct iio_chan_spec stx104_channels[STX104_NUM_CHAN] = { + STX104_CHAN(0), + STX104_CHAN(1) +}; + +static int stx104_probe(struct device *dev, unsigned int id) +{ + struct iio_dev *indio_dev; + struct stx104_iio *priv; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); + if (!indio_dev) + return -ENOMEM; + + if (!devm_request_region(dev, base[id], STX104_EXTENT, + dev_name(dev))) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base[id], base[id] + STX104_EXTENT); + return -EBUSY; + } + + indio_dev->info = &stx104_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = stx104_channels; + indio_dev->num_channels = STX104_NUM_CHAN; + indio_dev->name = dev_name(dev); + + priv = iio_priv(indio_dev); + priv->base = base[id]; + + /* initialize DAC output to 0V */ + outw(0, base[id] + 4); + outw(0, base[id] + 6); + + return devm_iio_device_register(dev, indio_dev); +} + +static struct isa_driver stx104_driver = { + .probe = stx104_probe, + .driver = { + .name = "stx104" + } +}; + +static void __exit stx104_exit(void) +{ + isa_unregister_driver(&stx104_driver); +} + +static int __init stx104_init(void) +{ + return isa_register_driver(&stx104_driver, num_stx104); +} + +module_init(stx104_init); +module_exit(stx104_exit); + +MODULE_AUTHOR("William Breathitt Gray "); +MODULE_DESCRIPTION("Apex Embedded Systems STX104 DAC driver"); +MODULE_LICENSE("GPL v2"); -- cgit From ecc24e72f43735cceab06f4e69aa6ce075a3ae46 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Thu, 11 Feb 2016 15:49:54 +0200 Subject: iio: adc: Add TI ADS1015 ADC driver support The driver has sysfs readings with runtime PM support for power saving. It also offers buffer support that can be used together with IIO software triggers. Datasheet can be found here: http://www.ti.com.cn/cn/lit/ds/symlink/ads1015.pdf Signed-off-by: Daniel Baluta Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 13 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ti-ads1015.c | 612 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 626 insertions(+) create mode 100644 drivers/iio/adc/ti-ads1015.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index ce152261b438..e8a0811232aa 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -394,6 +394,19 @@ config TI_ADC128S052 This driver can also be built as a module. If so, the module will be called ti-adc128s052. +config TI_ADS1015 + tristate "Texas Instruments ADS1015 ADC" + depends on I2C && !SENSORS_ADS1015 + select REGMAP_I2C + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + If you say yes here you get support for Texas Instruments ADS1015 + ADC chip. + + This driver can also be built as a module. If so, the module will be + called ti-ads1015. + config TI_ADS8688 tristate "Texas Instruments ADS8688" depends on SPI && OF diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 76c008158fa9..b1aa456e6af3 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o +obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o obj-$(CONFIG_TI_ADS8688) += ti-ads8688.o obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c new file mode 100644 index 000000000000..73cbf0b54e54 --- /dev/null +++ b/drivers/iio/adc/ti-ads1015.c @@ -0,0 +1,612 @@ +/* + * ADS1015 - Texas Instruments Analog-to-Digital Converter + * + * 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 driver for ADS1015 ADC 7-bit I2C slave address: + * * 0x48 - ADDR connected to Ground + * * 0x49 - ADDR connected to Vdd + * * 0x4A - ADDR connected to SDA + * * 0x4B - ADDR connected to SCL + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define ADS1015_DRV_NAME "ads1015" + +#define ADS1015_CONV_REG 0x00 +#define ADS1015_CFG_REG 0x01 + +#define ADS1015_CFG_DR_SHIFT 5 +#define ADS1015_CFG_MOD_SHIFT 8 +#define ADS1015_CFG_PGA_SHIFT 9 +#define ADS1015_CFG_MUX_SHIFT 12 + +#define ADS1015_CFG_DR_MASK GENMASK(7, 5) +#define ADS1015_CFG_MOD_MASK BIT(8) +#define ADS1015_CFG_PGA_MASK GENMASK(11, 9) +#define ADS1015_CFG_MUX_MASK GENMASK(14, 12) + +/* device operating modes */ +#define ADS1015_CONTINUOUS 0 +#define ADS1015_SINGLESHOT 1 + +#define ADS1015_SLEEP_DELAY_MS 2000 +#define ADS1015_DEFAULT_PGA 2 +#define ADS1015_DEFAULT_DATA_RATE 4 +#define ADS1015_DEFAULT_CHAN 0 + +enum ads1015_channels { + ADS1015_AIN0_AIN1 = 0, + ADS1015_AIN0_AIN3, + ADS1015_AIN1_AIN3, + ADS1015_AIN2_AIN3, + ADS1015_AIN0, + ADS1015_AIN1, + ADS1015_AIN2, + ADS1015_AIN3, + ADS1015_TIMESTAMP, +}; + +static const unsigned int ads1015_data_rate[] = { + 128, 250, 490, 920, 1600, 2400, 3300, 3300 +}; + +static const struct { + int scale; + int uscale; +} ads1015_scale[] = { + {3, 0}, + {2, 0}, + {1, 0}, + {0, 500000}, + {0, 250000}, + {0, 125000}, + {0, 125000}, + {0, 125000}, +}; + +#define ADS1015_V_CHAN(_chan, _addr) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .address = _addr, \ + .channel = _chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _addr, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_CPU, \ + }, \ +} + +#define ADS1015_V_DIFF_CHAN(_chan, _chan2, _addr) { \ + .type = IIO_VOLTAGE, \ + .differential = 1, \ + .indexed = 1, \ + .address = _addr, \ + .channel = _chan, \ + .channel2 = _chan2, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _addr, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 12, \ + .storagebits = 16, \ + .shift = 4, \ + .endianness = IIO_CPU, \ + }, \ +} + +struct ads1015_data { + struct regmap *regmap; + /* + * Protects ADC ops, e.g: concurrent sysfs/buffered + * data reads, configuration updates + */ + struct mutex lock; + struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; +}; + +static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg) +{ + return (reg == ADS1015_CFG_REG); +} + +static const struct regmap_config ads1015_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .max_register = ADS1015_CFG_REG, + .writeable_reg = ads1015_is_writeable_reg, +}; + +static const struct iio_chan_spec ads1015_channels[] = { + ADS1015_V_DIFF_CHAN(0, 1, ADS1015_AIN0_AIN1), + ADS1015_V_DIFF_CHAN(0, 3, ADS1015_AIN0_AIN3), + ADS1015_V_DIFF_CHAN(1, 3, ADS1015_AIN1_AIN3), + ADS1015_V_DIFF_CHAN(2, 3, ADS1015_AIN2_AIN3), + ADS1015_V_CHAN(0, ADS1015_AIN0), + ADS1015_V_CHAN(1, ADS1015_AIN1), + ADS1015_V_CHAN(2, ADS1015_AIN2), + ADS1015_V_CHAN(3, ADS1015_AIN3), + IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP), +}; + +static int ads1015_set_power_state(struct ads1015_data *data, bool on) +{ + int ret; + struct device *dev = regmap_get_device(data->regmap); + + if (on) { + ret = pm_runtime_get_sync(dev); + if (ret < 0) + pm_runtime_put_noidle(dev); + } else { + pm_runtime_mark_last_busy(dev); + ret = pm_runtime_put_autosuspend(dev); + } + + return ret; +} + +static +int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val) +{ + int ret, pga, dr, conv_time; + bool change; + + if (chan < 0 || chan >= ADS1015_CHANNELS) + return -EINVAL; + + pga = data->channel_data[chan].pga; + dr = data->channel_data[chan].data_rate; + + ret = regmap_update_bits_check(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_MUX_MASK | + ADS1015_CFG_PGA_MASK, + chan << ADS1015_CFG_MUX_SHIFT | + pga << ADS1015_CFG_PGA_SHIFT, + &change); + if (ret < 0) + return ret; + + if (change) { + conv_time = DIV_ROUND_UP(USEC_PER_SEC, ads1015_data_rate[dr]); + usleep_range(conv_time, conv_time + 1); + } + + return regmap_read(data->regmap, ADS1015_CONV_REG, val); +} + +static irqreturn_t ads1015_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ads1015_data *data = iio_priv(indio_dev); + s16 buf[8]; /* 1x s16 ADC val + 3x s16 padding + 4x s16 timestamp */ + int chan, ret, res; + + memset(buf, 0, sizeof(buf)); + + mutex_lock(&data->lock); + chan = find_first_bit(indio_dev->active_scan_mask, + indio_dev->masklength); + ret = ads1015_get_adc_result(data, chan, &res); + if (ret < 0) { + mutex_unlock(&data->lock); + goto err; + } + + buf[0] = res; + mutex_unlock(&data->lock); + + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); + +err: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int ads1015_set_scale(struct ads1015_data *data, int chan, + int scale, int uscale) +{ + int i, ret, rindex = -1; + + for (i = 0; i < ARRAY_SIZE(ads1015_scale); i++) + if (ads1015_scale[i].scale == scale && + ads1015_scale[i].uscale == uscale) { + rindex = i; + break; + } + if (rindex < 0) + return -EINVAL; + + ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_PGA_MASK, + rindex << ADS1015_CFG_PGA_SHIFT); + if (ret < 0) + return ret; + + data->channel_data[chan].pga = rindex; + + return 0; +} + +static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate) +{ + int i, ret, rindex = -1; + + for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) + if (ads1015_data_rate[i] == rate) { + rindex = i; + break; + } + if (rindex < 0) + return -EINVAL; + + ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_DR_MASK, + rindex << ADS1015_CFG_DR_SHIFT); + if (ret < 0) + return ret; + + data->channel_data[chan].data_rate = rindex; + + return 0; +} + +static int ads1015_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + int ret, idx; + struct ads1015_data *data = iio_priv(indio_dev); + + mutex_lock(&indio_dev->mlock); + mutex_lock(&data->lock); + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (iio_buffer_enabled(indio_dev)) { + ret = -EBUSY; + break; + } + + ret = ads1015_set_power_state(data, true); + if (ret < 0) + break; + + ret = ads1015_get_adc_result(data, chan->address, val); + if (ret < 0) { + ads1015_set_power_state(data, false); + break; + } + + /* 12 bit res, D0 is bit 4 in conversion register */ + *val = sign_extend32(*val >> 4, 11); + + ret = ads1015_set_power_state(data, false); + if (ret < 0) + break; + + ret = IIO_VAL_INT; + break; + case IIO_CHAN_INFO_SCALE: + idx = data->channel_data[chan->address].pga; + *val = ads1015_scale[idx].scale; + *val2 = ads1015_scale[idx].uscale; + ret = IIO_VAL_INT_PLUS_MICRO; + break; + case IIO_CHAN_INFO_SAMP_FREQ: + idx = data->channel_data[chan->address].data_rate; + *val = ads1015_data_rate[idx]; + ret = IIO_VAL_INT; + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->lock); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + +static int ads1015_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct ads1015_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = ads1015_set_scale(data, chan->address, val, val2); + break; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = ads1015_set_data_rate(data, chan->address, val); + break; + default: + ret = -EINVAL; + break; + } + mutex_unlock(&data->lock); + + return ret; +} + +static int ads1015_buffer_preenable(struct iio_dev *indio_dev) +{ + return ads1015_set_power_state(iio_priv(indio_dev), true); +} + +static int ads1015_buffer_postdisable(struct iio_dev *indio_dev) +{ + return ads1015_set_power_state(iio_priv(indio_dev), false); +} + +static const struct iio_buffer_setup_ops ads1015_buffer_setup_ops = { + .preenable = ads1015_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = ads1015_buffer_postdisable, + .validate_scan_mask = &iio_validate_scan_mask_onehot, +}; + +static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125"); +static IIO_CONST_ATTR(sampling_frequency_available, + "128 250 490 920 1600 2400 3300"); + +static struct attribute *ads1015_attributes[] = { + &iio_const_attr_scale_available.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group ads1015_attribute_group = { + .attrs = ads1015_attributes, +}; + +static const struct iio_info ads1015_info = { + .driver_module = THIS_MODULE, + .read_raw = ads1015_read_raw, + .write_raw = ads1015_write_raw, + .attrs = &ads1015_attribute_group, +}; + +#ifdef CONFIG_OF +static int ads1015_get_channels_config_of(struct i2c_client *client) +{ + struct ads1015_data *data = i2c_get_clientdata(client); + struct device_node *node; + + if (!client->dev.of_node || + !of_get_next_child(client->dev.of_node, NULL)) + return -EINVAL; + + for_each_child_of_node(client->dev.of_node, node) { + u32 pval; + unsigned int channel; + unsigned int pga = ADS1015_DEFAULT_PGA; + unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; + + if (of_property_read_u32(node, "reg", &pval)) { + dev_err(&client->dev, "invalid reg on %s\n", + node->full_name); + continue; + } + + channel = pval; + if (channel >= ADS1015_CHANNELS) { + dev_err(&client->dev, + "invalid channel index %d on %s\n", + channel, node->full_name); + continue; + } + + if (!of_property_read_u32(node, "ti,gain", &pval)) { + pga = pval; + if (pga > 6) { + dev_err(&client->dev, "invalid gain on %s\n", + node->full_name); + return -EINVAL; + } + } + + if (!of_property_read_u32(node, "ti,datarate", &pval)) { + data_rate = pval; + if (data_rate > 7) { + dev_err(&client->dev, + "invalid data_rate on %s\n", + node->full_name); + return -EINVAL; + } + } + + data->channel_data[channel].pga = pga; + data->channel_data[channel].data_rate = data_rate; + } + + return 0; +} +#endif + +static void ads1015_get_channels_config(struct i2c_client *client) +{ + unsigned int k; + + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ads1015_data *data = iio_priv(indio_dev); + struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev); + + /* prefer platform data */ + if (pdata) { + memcpy(data->channel_data, pdata->channel_data, + sizeof(data->channel_data)); + return; + } + +#ifdef CONFIG_OF + if (!ads1015_get_channels_config_of(client)) + return; +#endif + /* fallback on default configuration */ + for (k = 0; k < ADS1015_CHANNELS; ++k) { + data->channel_data[k].pga = ADS1015_DEFAULT_PGA; + data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE; + } +} + +static int ads1015_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ads1015_data *data; + 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); + + mutex_init(&data->lock); + + indio_dev->dev.parent = &client->dev; + indio_dev->info = &ads1015_info; + indio_dev->name = ADS1015_DRV_NAME; + indio_dev->channels = ads1015_channels; + indio_dev->num_channels = ARRAY_SIZE(ads1015_channels); + indio_dev->modes = INDIO_DIRECT_MODE; + + /* we need to keep this ABI the same as used by hwmon ADS1015 driver */ + ads1015_get_channels_config(client); + + data->regmap = devm_regmap_init_i2c(client, &ads1015_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(&client->dev, "Failed to allocate register map\n"); + return PTR_ERR(data->regmap); + } + + ret = iio_triggered_buffer_setup(indio_dev, NULL, + ads1015_trigger_handler, + &ads1015_buffer_setup_ops); + if (ret < 0) { + dev_err(&client->dev, "iio triggered buffer setup failed\n"); + return ret; + } + ret = pm_runtime_set_active(&client->dev); + if (ret) + goto err_buffer_cleanup; + pm_runtime_set_autosuspend_delay(&client->dev, ADS1015_SLEEP_DELAY_MS); + pm_runtime_use_autosuspend(&client->dev); + pm_runtime_enable(&client->dev); + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, "Failed to register IIO device\n"); + goto err_buffer_cleanup; + } + + return 0; + +err_buffer_cleanup: + iio_triggered_buffer_cleanup(indio_dev); + + return ret; +} + +static int ads1015_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ads1015_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); + + iio_triggered_buffer_cleanup(indio_dev); + + /* power down single shot mode */ + return regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_MOD_MASK, + ADS1015_SINGLESHOT << ADS1015_CFG_MOD_SHIFT); +} + +#ifdef CONFIG_PM +static int ads1015_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ads1015_data *data = iio_priv(indio_dev); + + return regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_MOD_MASK, + ADS1015_SINGLESHOT << ADS1015_CFG_MOD_SHIFT); +} + +static int ads1015_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); + struct ads1015_data *data = iio_priv(indio_dev); + + return regmap_update_bits(data->regmap, ADS1015_CFG_REG, + ADS1015_CFG_MOD_MASK, + ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT); +} +#endif + +static const struct dev_pm_ops ads1015_pm_ops = { + SET_RUNTIME_PM_OPS(ads1015_runtime_suspend, + ads1015_runtime_resume, NULL) +}; + +static const struct i2c_device_id ads1015_id[] = { + {"ads1015", 0}, + {} +}; +MODULE_DEVICE_TABLE(i2c, ads1015_id); + +static struct i2c_driver ads1015_driver = { + .driver = { + .name = ADS1015_DRV_NAME, + .pm = &ads1015_pm_ops, + }, + .probe = ads1015_probe, + .remove = ads1015_remove, + .id_table = ads1015_id, +}; + +module_i2c_driver(ads1015_driver); + +MODULE_AUTHOR("Daniel Baluta "); +MODULE_DESCRIPTION("Texas Instruments ADS1015 ADC driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 4a9e00600b6feeacae02b8ac3428bf98c813c1b2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 10 Feb 2016 18:54:32 +0900 Subject: pinctrl: mediatek: guard sub-directory with CONFIG_PINCTRL_MTK CONFIG_PINCTRL_MTK is more suitable than CONFIG_ARCH_MEDIATEK to guard the drivers/pinctrl/mediatek/ directory. (I renamed CONFIG_PINCTRL_MTK_COMMON to CONFIG_PINCTRL_MTK.) This allows COMPILE_TEST to descend into drivers/pinctrl/mediatek without CONFIG_ARCH_MEDIATEK define. Signed-off-by: Masahiro Yamada Signed-off-by: Linus Walleij --- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/mediatek/Kconfig | 12 ++++++------ drivers/pinctrl/mediatek/Makefile | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 7ea62ef0c4e5..e4bc1151e04f 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -50,4 +50,4 @@ obj-$(CONFIG_PINCTRL_STM32) += stm32/ obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_VT8500) += vt8500/ -obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ +obj-$(CONFIG_PINCTRL_MTK) += mediatek/ diff --git a/drivers/pinctrl/mediatek/Kconfig b/drivers/pinctrl/mediatek/Kconfig index 13e9939d9b3a..e4fbc587f1d4 100644 --- a/drivers/pinctrl/mediatek/Kconfig +++ b/drivers/pinctrl/mediatek/Kconfig @@ -1,6 +1,6 @@ if ARCH_MEDIATEK || COMPILE_TEST -config PINCTRL_MTK_COMMON +config PINCTRL_MTK bool depends on OF select PINMUX @@ -13,19 +13,19 @@ config PINCTRL_MT2701 bool "Mediatek MT2701 pin control" if COMPILE_TEST && !MACH_MT2701 depends on OF default MACH_MT2701 - select PINCTRL_MTK_COMMON + select PINCTRL_MTK config PINCTRL_MT8135 bool "Mediatek MT8135 pin control" if COMPILE_TEST && !MACH_MT8135 depends on OF default MACH_MT8135 - select PINCTRL_MTK_COMMON + select PINCTRL_MTK config PINCTRL_MT8127 bool "Mediatek MT8127 pin control" if COMPILE_TEST && !MACH_MT8127 depends on OF default MACH_MT8127 - select PINCTRL_MTK_COMMON + select PINCTRL_MTK # For ARMv8 SoCs config PINCTRL_MT8173 @@ -33,13 +33,13 @@ config PINCTRL_MT8173 depends on OF depends on ARM64 || COMPILE_TEST default ARM64 && ARCH_MEDIATEK - select PINCTRL_MTK_COMMON + select PINCTRL_MTK # For PMIC config PINCTRL_MT6397 bool "Mediatek MT6397 pin control" if COMPILE_TEST && !MFD_MT6397 depends on OF default MFD_MT6397 - select PINCTRL_MTK_COMMON + select PINCTRL_MTK endif diff --git a/drivers/pinctrl/mediatek/Makefile b/drivers/pinctrl/mediatek/Makefile index da30314a5ddc..e59c613d4ddd 100644 --- a/drivers/pinctrl/mediatek/Makefile +++ b/drivers/pinctrl/mediatek/Makefile @@ -1,9 +1,9 @@ # Core -obj-$(CONFIG_PINCTRL_MTK_COMMON) += pinctrl-mtk-common.o +obj-y += pinctrl-mtk-common.o # SoC Drivers -obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o -obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o -obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o -obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o -obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o +obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o +obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o +obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o +obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o +obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o -- cgit From e2c7698cd61f11d4077fdb28148b2d31b82ac848 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 10 Feb 2016 15:51:16 +0100 Subject: x86/mm: Fix INVPCID asm constraint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So we want to specify the dependency on both @pcid and @addr so that the compiler doesn't reorder accesses to them *before* the TLB flush. But for that to work, we need to express this properly in the inline asm and deref the whole desc array, not the pointer to it. See clwb() for an example. This fixes the build error on 32-bit: arch/x86/include/asm/tlbflush.h: In function ‘__invpcid’: arch/x86/include/asm/tlbflush.h:26:18: error: memory input 0 is not directly addressable which gcc4.7 caught but 5.x didn't. Which is strange. :-\ Signed-off-by: Borislav Petkov Cc: Andrew Morton Cc: Andrey Ryabinin Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Luis R. Rodriguez Cc: Michael Matz Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Toshi Kani Cc: linux-mm@kvack.org Signed-off-by: Ingo Molnar --- arch/x86/include/asm/tlbflush.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index fc9a2fda1404..d0cce90b0855 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -10,7 +10,7 @@ static inline void __invpcid(unsigned long pcid, unsigned long addr, unsigned long type) { - u64 desc[2] = { pcid, addr }; + struct { u64 d[2]; } desc = { { pcid, addr } }; /* * The memory clobber is because the whole point is to invalidate @@ -22,7 +22,7 @@ static inline void __invpcid(unsigned long pcid, unsigned long addr, * invpcid (%rcx), %rax in long mode. */ asm volatile (".byte 0x66, 0x0f, 0x38, 0x82, 0x01" - : : "m" (desc), "a" (type), "c" (desc) : "memory"); + : : "m" (desc), "a" (type), "c" (&desc) : "memory"); } #define INVPCID_TYPE_INDIV_ADDR 0 -- cgit From 66841672161efb9e3be4a1dbd9755020bb1d86b7 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 12 Feb 2016 15:27:00 +0800 Subject: blk-mq: mark request queue as mq asap Currently q->mq_ops is used widely to decide if the queue is mq or not, so we should set the 'flag' asap so that both block core and drivers can get the correct mq info. For example, commit 868f2f0b720(blk-mq: dynamic h/w context count) moves the hctx's initialization before setting q->mq_ops in blk_mq_init_allocated_queue(), then cause blk_alloc_flush_queue() to think the queue is non-mq and don't allocate command size for the per-hctx flush rq. This patches should fix the problem reported by Sasha. Cc: Keith Busch Reported-by: Sasha Levin Signed-off-by: Ming Lei Fixes: 868f2f0b720 ("blk-mq: dynamic h/w context count") Signed-off-by: Jens Axboe --- block/blk-mq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 645eb9e716d0..f539a53d16c3 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2010,6 +2010,9 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set, struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, struct request_queue *q) { + /* mark the queue as mq asap */ + q->mq_ops = set->ops; + q->queue_ctx = alloc_percpu(struct blk_mq_ctx); if (!q->queue_ctx) return ERR_PTR(-ENOMEM); @@ -2032,7 +2035,6 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set, q->nr_queues = nr_cpu_ids; - q->mq_ops = set->ops; q->queue_flags |= QUEUE_FLAG_MQ_DEFAULT; if (!(set->flags & BLK_MQ_F_SG_MERGE)) -- cgit From f944b5a7aff05a244a6c8cac297819af09a199e4 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 14 Jan 2016 10:54:13 +0100 Subject: genirq: Use a common macro to go through the actions list The irq code browses the list of actions differently to inspect the element one by one. Even if it is not a problem, for the sake of consistent code, provide a macro similar to for_each_irq_desc in order to have the same loop to go through the actions list and use it in the code. [ tglx: Renamed the macro ] Signed-off-by: Daniel Lezcano Link: http://lkml.kernel.org/r/1452765253-31148-1-git-send-email-daniel.lezcano@linaro.org Signed-off-by: Thomas Gleixner --- kernel/irq/handle.c | 6 ++---- kernel/irq/internals.h | 3 +++ kernel/irq/manage.c | 8 +++----- kernel/irq/proc.c | 2 +- kernel/irq/spurious.c | 4 +--- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index 57bff7857e87..a15b5485b446 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -136,10 +136,9 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc) { irqreturn_t retval = IRQ_NONE; unsigned int flags = 0, irq = desc->irq_data.irq; - struct irqaction *action = desc->action; + struct irqaction *action; - /* action might have become NULL since we dropped the lock */ - while (action) { + for_each_action_of_desc(desc, action) { irqreturn_t res; trace_irq_handler_entry(irq, action); @@ -173,7 +172,6 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc) } retval |= res; - action = action->next; } add_interrupt_randomness(irq, flags); diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index fcab63c66905..eab521fc547c 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -131,6 +131,9 @@ static inline void chip_bus_sync_unlock(struct irq_desc *desc) #define IRQ_GET_DESC_CHECK_GLOBAL (_IRQ_DESC_CHECK) #define IRQ_GET_DESC_CHECK_PERCPU (_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU) +#define for_each_action_of_desc(desc, act) \ + for (act = desc->act; act; act = act->next) + struct irq_desc * __irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus, unsigned int check); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 841187239adc..3ddd2297ee95 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -144,13 +144,11 @@ int irq_can_set_affinity(unsigned int irq) */ void irq_set_thread_affinity(struct irq_desc *desc) { - struct irqaction *action = desc->action; + struct irqaction *action; - while (action) { + for_each_action_of_desc(desc, action) if (action->thread) set_bit(IRQTF_AFFINITY, &action->thread_flags); - action = action->next; - } } #ifdef CONFIG_GENERIC_PENDING_IRQ @@ -994,7 +992,7 @@ void irq_wake_thread(unsigned int irq, void *dev_id) return; raw_spin_lock_irqsave(&desc->lock, flags); - for (action = desc->action; action; action = action->next) { + for_each_action_of_desc(desc, action) { if (action->dev_id == dev_id) { if (action->thread) __irq_wake_thread(desc, action); diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index a2c02fd5d6d0..4e1b94726818 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -291,7 +291,7 @@ static int name_unique(unsigned int irq, struct irqaction *new_action) int ret = 1; raw_spin_lock_irqsave(&desc->lock, flags); - for (action = desc->action ; action; action = action->next) { + for_each_action_of_desc(desc, action) { if ((action != new_action) && action->name && !strcmp(new_action->name, action->name)) { ret = 0; diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 32144175458d..5707f97a3e6a 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -211,14 +211,12 @@ static void __report_bad_irq(struct irq_desc *desc, irqreturn_t action_ret) * desc->lock here. See synchronize_irq(). */ raw_spin_lock_irqsave(&desc->lock, flags); - action = desc->action; - while (action) { + for_each_action_of_desc(desc, action) { printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler); if (action->thread_fn) printk(KERN_CONT " threaded [<%p>] %pf", action->thread_fn, action->thread_fn); printk(KERN_CONT "\n"); - action = action->next; } raw_spin_unlock_irqrestore(&desc->lock, flags); } -- cgit From ddbc66a5e5cd814fc5ee51adcd860389955ce021 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:05:59 -0500 Subject: staging: lustre: drop *_t from end of struct lnet_text_buf When lnet_text_buf data structure was transform from typedef to struct the *_t which is typical of typedef was not drop. This patch removes the *_t to be consistent. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/lnet/config.c | 57 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 74d644d7d729..01efe6172be8 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -37,7 +37,7 @@ #define DEBUG_SUBSYSTEM S_LNET #include "../../include/linux/lnet/lib-lnet.h" -struct lnet_text_buf_t { /* tmp struct for parsing routes */ +struct lnet_text_buf { /* tmp struct for parsing routes */ struct list_head ltb_list; /* stash on lists */ int ltb_size; /* allocated size */ char ltb_text[0]; /* text buffer */ @@ -369,14 +369,14 @@ lnet_parse_networks(struct list_head *nilist, char *networks) return -EINVAL; } -static struct lnet_text_buf_t * +static struct lnet_text_buf * lnet_new_text_buf(int str_len) { - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; int nob; /* NB allocate space for the terminating 0 */ - nob = offsetof(struct lnet_text_buf_t, ltb_text[str_len + 1]); + nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]); if (nob > LNET_SINGLE_TEXTBUF_NOB) { /* _way_ conservative for "route net gateway..." */ CERROR("text buffer too big\n"); @@ -399,7 +399,7 @@ lnet_new_text_buf(int str_len) } static void -lnet_free_text_buf(struct lnet_text_buf_t *ltb) +lnet_free_text_buf(struct lnet_text_buf *ltb) { lnet_tbnob -= ltb->ltb_size; LIBCFS_FREE(ltb, ltb->ltb_size); @@ -408,10 +408,10 @@ lnet_free_text_buf(struct lnet_text_buf_t *ltb) static void lnet_free_text_bufs(struct list_head *tbs) { - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; while (!list_empty(tbs)) { - ltb = list_entry(tbs->next, struct lnet_text_buf_t, ltb_list); + ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); list_del(<b->ltb_list); lnet_free_text_buf(ltb); @@ -425,7 +425,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) char *sep; int nob; int i; - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; INIT_LIST_HEAD(&pending); @@ -483,7 +483,7 @@ lnet_expand1tb(struct list_head *list, { int len1 = (int)(sep1 - str); int len2 = strlen(sep2 + 1); - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; LASSERT(*sep1 == '['); LASSERT(*sep2 == ']'); @@ -642,7 +642,7 @@ lnet_parse_route(char *str, int *im_a_router) struct list_head *tmp2; __u32 net; lnet_nid_t nid; - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; int rc; char *sep; char *token = str; @@ -698,8 +698,7 @@ lnet_parse_route(char *str, int *im_a_router) list_add_tail(tmp1, tmp2); while (tmp1 != tmp2) { - ltb = list_entry(tmp1, struct lnet_text_buf_t, - ltb_list); + ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); rc = lnet_str2tbs_expand(tmp1->next, ltb->ltb_text); if (rc < 0) @@ -739,13 +738,12 @@ lnet_parse_route(char *str, int *im_a_router) LASSERT(!list_empty(&gateways)); list_for_each(tmp1, &nets) { - ltb = list_entry(tmp1, struct lnet_text_buf_t, ltb_list); + ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); net = libcfs_str2net(ltb->ltb_text); LASSERT(net != LNET_NIDNET(LNET_NID_ANY)); list_for_each(tmp2, &gateways) { - ltb = list_entry(tmp2, struct lnet_text_buf_t, - ltb_list); + ltb = list_entry(tmp2, struct lnet_text_buf, ltb_list); nid = libcfs_str2nid(ltb->ltb_text); LASSERT(nid != LNET_NID_ANY); @@ -778,10 +776,10 @@ lnet_parse_route(char *str, int *im_a_router) static int lnet_parse_route_tbs(struct list_head *tbs, int *im_a_router) { - struct lnet_text_buf_t *ltb; + struct lnet_text_buf *ltb; while (!list_empty(tbs)) { - ltb = list_entry(tbs->next, struct lnet_text_buf_t, ltb_list); + ltb = list_entry(tbs->next, struct lnet_text_buf, ltb_list); if (lnet_parse_route(ltb->ltb_text, im_a_router) < 0) { lnet_free_text_bufs(tbs); @@ -915,8 +913,8 @@ lnet_splitnets(char *source, struct list_head *nets) int offset = 0; int offset2; int len; - struct lnet_text_buf_t *tb; - struct lnet_text_buf_t *tb2; + struct lnet_text_buf *tb; + struct lnet_text_buf *tb2; struct list_head *t; char *sep; char *bracket; @@ -925,7 +923,7 @@ lnet_splitnets(char *source, struct list_head *nets) LASSERT(!list_empty(nets)); LASSERT(nets->next == nets->prev); /* single entry */ - tb = list_entry(nets->next, struct lnet_text_buf_t, ltb_list); + tb = list_entry(nets->next, struct lnet_text_buf, ltb_list); for (;;) { sep = strchr(tb->ltb_text, ','); @@ -961,7 +959,7 @@ lnet_splitnets(char *source, struct list_head *nets) } list_for_each(t, nets) { - tb2 = list_entry(t, struct lnet_text_buf_t, ltb_list); + tb2 = list_entry(t, struct lnet_text_buf, ltb_list); if (tb2 == tb) continue; @@ -1002,8 +1000,8 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) struct list_head current_nets; struct list_head *t; struct list_head *t2; - struct lnet_text_buf_t *tb; - struct lnet_text_buf_t *tb2; + struct lnet_text_buf *tb; + struct lnet_text_buf *tb2; __u32 net1; __u32 net2; int len; @@ -1026,9 +1024,8 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) rc = 0; while (!list_empty(&raw_entries)) { - tb = list_entry(raw_entries.next, struct lnet_text_buf_t, - ltb_list); - + tb = list_entry(raw_entries.next, struct lnet_text_buf, + ltb_list); strncpy(source, tb->ltb_text, sizeof(source)); source[sizeof(source)-1] = '\0'; @@ -1053,13 +1050,13 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) dup = 0; list_for_each(t, ¤t_nets) { - tb = list_entry(t, struct lnet_text_buf_t, ltb_list); + tb = list_entry(t, struct lnet_text_buf, ltb_list); net1 = lnet_netspec2net(tb->ltb_text); LASSERT(net1 != LNET_NIDNET(LNET_NID_ANY)); list_for_each(t2, &matched_nets) { - tb2 = list_entry(t2, struct lnet_text_buf_t, - ltb_list); + tb2 = list_entry(t2, struct lnet_text_buf, + ltb_list); net2 = lnet_netspec2net(tb2->ltb_text); LASSERT(net2 != LNET_NIDNET(LNET_NID_ANY)); @@ -1079,7 +1076,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) } list_for_each_safe(t, t2, ¤t_nets) { - tb = list_entry(t, struct lnet_text_buf_t, ltb_list); + tb = list_entry(t, struct lnet_text_buf, ltb_list); list_del(&tb->ltb_list); list_add_tail(&tb->ltb_list, &matched_nets); -- cgit From 4420cfd3f51cf0ff21edd31fb59cdc05744b43d8 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:00 -0500 Subject: staging: lustre: format properly all comment blocks for LNet core In several places in the LNet core comment blocks don't follow the linux kernel style. This patch cleans those problems up. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/api.h | 22 ++- .../staging/lustre/include/linux/lnet/lib-lnet.h | 9 +- .../staging/lustre/include/linux/lnet/lib-types.h | 54 +++-- drivers/staging/lustre/include/linux/lnet/nidstr.h | 6 +- .../staging/lustre/include/linux/lnet/socklnd.h | 6 +- drivers/staging/lustre/include/linux/lnet/types.h | 47 +++-- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 90 ++++++--- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 181 ++++++++++------- .../lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c | 6 +- .../staging/lustre/lnet/klnds/socklnd/socklnd.c | 218 +++++++++++++-------- .../staging/lustre/lnet/klnds/socklnd/socklnd.h | 25 ++- .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 215 +++++++++++++------- .../lustre/lnet/klnds/socklnd/socklnd_lib.c | 76 ++++--- .../lustre/lnet/klnds/socklnd/socklnd_modparams.c | 6 +- .../lustre/lnet/klnds/socklnd/socklnd_proto.c | 6 +- drivers/staging/lustre/lnet/lnet/acceptor.c | 21 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 68 ++++--- drivers/staging/lustre/lnet/lnet/lib-eq.c | 37 ++-- drivers/staging/lustre/lnet/lnet/lib-md.c | 30 ++- drivers/staging/lustre/lnet/lnet/lib-move.c | 140 ++++++++----- drivers/staging/lustre/lnet/lnet/lib-msg.c | 43 ++-- drivers/staging/lustre/lnet/lnet/lib-ptl.c | 48 +++-- drivers/staging/lustre/lnet/lnet/lib-socket.c | 19 +- drivers/staging/lustre/lnet/lnet/module.c | 12 +- drivers/staging/lustre/lnet/lnet/nidstrings.c | 12 +- drivers/staging/lustre/lnet/lnet/router.c | 92 +++++---- drivers/staging/lustre/lnet/lnet/router_proc.c | 26 ++- drivers/staging/lustre/lnet/selftest/brw_test.c | 18 +- drivers/staging/lustre/lnet/selftest/conrpc.c | 19 +- drivers/staging/lustre/lnet/selftest/console.c | 12 +- drivers/staging/lustre/lnet/selftest/framework.c | 30 ++- drivers/staging/lustre/lnet/selftest/rpc.c | 91 ++++++--- drivers/staging/lustre/lnet/selftest/rpc.h | 6 +- 33 files changed, 1092 insertions(+), 599 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/api.h b/drivers/staging/lustre/include/linux/lnet/api.h index fa5fad3582b3..cb0d6b481455 100644 --- a/drivers/staging/lustre/include/linux/lnet/api.h +++ b/drivers/staging/lustre/include/linux/lnet/api.h @@ -48,7 +48,8 @@ /** \defgroup lnet_init_fini Initialization and cleanup * The LNet must be properly initialized before any LNet calls can be made. - * @{ */ + * @{ + */ int LNetNIInit(lnet_pid_t requested_pid); int LNetNIFini(void); /** @} lnet_init_fini */ @@ -71,7 +72,8 @@ int LNetNIFini(void); * it's an entry in the portals table of a process. * * \see LNetMEAttach - * @{ */ + * @{ + */ int LNetGetId(unsigned int index, lnet_process_id_t *id); int LNetDist(lnet_nid_t nid, lnet_nid_t *srcnid, __u32 *order); void LNetSnprintHandle(char *str, int str_len, lnet_handle_any_t handle); @@ -89,7 +91,8 @@ void LNetSnprintHandle(char *str, int str_len, lnet_handle_any_t handle); * incoming requests based on process ID or the match bits provided in the * request. MEs can be dynamically inserted into a match list by LNetMEAttach() * and LNetMEInsert(), and removed from its list by LNetMEUnlink(). - * @{ */ + * @{ + */ int LNetMEAttach(unsigned int portal, lnet_process_id_t match_id_in, __u64 match_bits_in, @@ -120,7 +123,8 @@ int LNetMEUnlink(lnet_handle_me_t current_in); * The LNet API provides two operations to create MDs: LNetMDAttach() * and LNetMDBind(); one operation to unlink and release the resources * associated with a MD: LNetMDUnlink(). - * @{ */ + * @{ + */ int LNetMDAttach(lnet_handle_me_t current_in, lnet_md_t md_in, lnet_unlink_t unlink_in, @@ -154,7 +158,8 @@ int LNetMDUnlink(lnet_handle_md_t md_in); * event from an EQ, and LNetEQWait() can be used to block a process until * an EQ has at least one event. LNetEQPoll() can be used to test or wait * on multiple EQs. - * @{ */ + * @{ + */ int LNetEQAlloc(unsigned int count_in, lnet_eq_handler_t handler, lnet_handle_eq_t *handle_out); @@ -172,7 +177,8 @@ int LNetEQPoll(lnet_handle_eq_t *eventqs_in, * * The LNet API provides two data movement operations: LNetPut() * and LNetGet(). - * @{ */ + * @{ + */ int LNetPut(lnet_nid_t self, lnet_handle_md_t md_in, lnet_ack_req_t ack_req_in, @@ -192,8 +198,8 @@ int LNetGet(lnet_nid_t self, /** \defgroup lnet_misc Miscellaneous operations. * Miscellaneous operations. - * @{ */ - + * @{ + */ int LNetSetLazyPortal(int portal); int LNetClearLazyPortal(int portal); int LNetCtl(unsigned int cmd, void *arg); diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 40acddd728e6..c3bf5e8a3324 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -79,7 +79,8 @@ static inline int lnet_md_exhausted(lnet_libmd_t *md) static inline int lnet_md_unlinkable(lnet_libmd_t *md) { - /* Should unlink md when its refcount is 0 and either: + /* + * Should unlink md when its refcount is 0 and either: * - md has been flagged for deletion (by auto unlink or * LNetM[DE]Unlink, in the latter case md may not be exhausted). * - auto unlink is on and md is exhausted. @@ -102,8 +103,10 @@ lnet_cpt_of_cookie(__u64 cookie) { unsigned int cpt = (cookie >> LNET_COOKIE_TYPE_BITS) & LNET_CPT_MASK; - /* LNET_CPT_NUMBER doesn't have to be power2, which means we can - * get illegal cpt from it's invalid cookie */ + /* + * LNET_CPT_NUMBER doesn't have to be power2, which means we can + * get illegal cpt from it's invalid cookie + */ return cpt < LNET_CPT_NUMBER ? cpt : cpt % LNET_CPT_NUMBER; } diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 3bb9468e0b9d..55d9d4311f0c 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -85,8 +85,7 @@ typedef struct lnet_msg { unsigned int msg_receiving:1; /* being received */ unsigned int msg_txcredit:1; /* taken an NI send credit */ unsigned int msg_peertxcredit:1; /* taken a peer send credit */ - unsigned int msg_rtrcredit:1; /* taken a global - router credit */ + unsigned int msg_rtrcredit:1; /* taken a global router credit */ unsigned int msg_peerrtrcredit:1; /* taken a peer router credit */ unsigned int msg_onactivelist:1; /* on the activelist */ @@ -190,7 +189,8 @@ typedef struct lnet_lnd { void (*lnd_shutdown)(struct lnet_ni *ni); int (*lnd_ctl)(struct lnet_ni *ni, unsigned int cmd, void *arg); - /* In data movement APIs below, payload buffers are described as a set + /* + * In data movement APIs below, payload buffers are described as a set * of 'niov' fragments which are... * EITHER * in virtual memory (struct iovec *iov != NULL) @@ -201,30 +201,36 @@ typedef struct lnet_lnd { * fragments to start from */ - /* Start sending a preformatted message. 'private' is NULL for PUT and + /* + * Start sending a preformatted message. 'private' is NULL for PUT and * GET messages; otherwise this is a response to an incoming message * and 'private' is the 'private' passed to lnet_parse(). Return * non-zero for immediate failure, otherwise complete later with - * lnet_finalize() */ + * lnet_finalize() + */ int (*lnd_send)(struct lnet_ni *ni, void *private, lnet_msg_t *msg); - /* Start receiving 'mlen' bytes of payload data, skipping the following + /* + * Start receiving 'mlen' bytes of payload data, skipping the following * 'rlen' - 'mlen' bytes. 'private' is the 'private' passed to * lnet_parse(). Return non-zero for immediate failure, otherwise * complete later with lnet_finalize(). This also gives back a receive - * credit if the LND does flow control. */ + * credit if the LND does flow control. + */ int (*lnd_recv)(struct lnet_ni *ni, void *private, lnet_msg_t *msg, int delayed, unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen); - /* lnet_parse() has had to delay processing of this message + /* + * lnet_parse() has had to delay processing of this message * (e.g. waiting for a forwarding buffer or send credits). Give the * LND a chance to free urgently needed resources. If called, return 0 * for success and do NOT give back a receive credit; that has to wait * until lnd_recv() gets called. On failure return < 0 and - * release resources; lnd_recv() will not be called. */ + * release resources; lnd_recv() will not be called. + */ int (*lnd_eager_recv)(struct lnet_ni *ni, void *private, lnet_msg_t *msg, void **new_privatep); @@ -272,8 +278,10 @@ typedef struct lnet_ni { #define LNET_PROTO_PING_MATCHBITS 0x8000000000000000LL -/* NB: value of these features equal to LNET_PROTO_PING_VERSION_x - * of old LNet, so there shouldn't be any compatibility issue */ +/* + * NB: value of these features equal to LNET_PROTO_PING_VERSION_x + * of old LNet, so there shouldn't be any compatibility issue + */ #define LNET_PING_FEAT_INVAL (0) /* no feature */ #define LNET_PING_FEAT_BASE (1 << 0) /* just a ping */ #define LNET_PING_FEAT_NI_STATUS (1 << 1) /* return NI status */ @@ -347,8 +355,10 @@ struct lnet_peer_table { struct list_head *pt_hash; /* NID->peer hash */ }; -/* peer aliveness is enabled only on routers for peers in a network where the - * lnet_ni_t::ni_peertimeout has been set to a positive value */ +/* + * peer aliveness is enabled only on routers for peers in a network where the + * lnet_ni_t::ni_peertimeout has been set to a positive value + */ #define lnet_peer_aliveness_enabled(lp) (the_lnet.ln_routing != 0 && \ (lp)->lp_ni->ni_peertimeout > 0) @@ -433,12 +443,16 @@ struct lnet_match_info { #define LNET_MT_HASH_BITS 8 #define LNET_MT_HASH_SIZE (1 << LNET_MT_HASH_BITS) #define LNET_MT_HASH_MASK (LNET_MT_HASH_SIZE - 1) -/* we allocate (LNET_MT_HASH_SIZE + 1) entries for lnet_match_table::mt_hash, - * the last entry is reserved for MEs with ignore-bits */ +/* + * we allocate (LNET_MT_HASH_SIZE + 1) entries for lnet_match_table::mt_hash, + * the last entry is reserved for MEs with ignore-bits + */ #define LNET_MT_HASH_IGNORE LNET_MT_HASH_SIZE -/* __u64 has 2^6 bits, so need 2^(LNET_MT_HASH_BITS - LNET_MT_BITS_U64) which +/* + * __u64 has 2^6 bits, so need 2^(LNET_MT_HASH_BITS - LNET_MT_BITS_U64) which * is 4 __u64s as bit-map, and add an extra __u64 (only use one bit) for the - * ME-list with ignore-bits, which is mtable::mt_hash[LNET_MT_HASH_IGNORE] */ + * ME-list with ignore-bits, which is mtable::mt_hash[LNET_MT_HASH_IGNORE] + */ #define LNET_MT_BITS_U64 6 /* 2^6 bits */ #define LNET_MT_EXHAUSTED_BITS (LNET_MT_HASH_BITS - LNET_MT_BITS_U64) #define LNET_MT_EXHAUSTED_BMAP ((1 << LNET_MT_EXHAUSTED_BITS) + 1) @@ -448,8 +462,10 @@ struct lnet_match_table { /* reserved for upcoming patches, CPU partition ID */ unsigned int mt_cpt; unsigned int mt_portal; /* portal index */ - /* match table is set as "enabled" if there's non-exhausted MD - * attached on mt_mhash, it's only valid for wildcard portal */ + /* + * match table is set as "enabled" if there's non-exhausted MD + * attached on mt_mhash, it's only valid for wildcard portal + */ unsigned int mt_enabled; /* bitmap to flag whether MEs on mt_hash are exhausted or not */ __u64 mt_exhausted[LNET_MT_EXHAUSTED_BMAP]; diff --git a/drivers/staging/lustre/include/linux/lnet/nidstr.h b/drivers/staging/lustre/include/linux/lnet/nidstr.h index 4fc9ddce829d..9a705e1d468c 100644 --- a/drivers/staging/lustre/include/linux/lnet/nidstr.h +++ b/drivers/staging/lustre/include/linux/lnet/nidstr.h @@ -34,8 +34,10 @@ * Lustre Network Driver types. */ enum { - /* Only add to these values (i.e. don't ever change or redefine them): - * network addresses depend on them... */ + /* + * Only add to these values (i.e. don't ever change or redefine them): + * network addresses depend on them... + */ QSWLND = 1, SOCKLND = 2, GMLND = 3, diff --git a/drivers/staging/lustre/include/linux/lnet/socklnd.h b/drivers/staging/lustre/include/linux/lnet/socklnd.h index 599c9f6628fb..3df5065b488d 100644 --- a/drivers/staging/lustre/include/linux/lnet/socklnd.h +++ b/drivers/staging/lustre/include/linux/lnet/socklnd.h @@ -91,8 +91,10 @@ socklnd_init_msg(ksock_msg_t *msg, int type) #define KSOCK_MSG_NOOP 0xC0 /* ksm_u empty */ #define KSOCK_MSG_LNET 0xC1 /* lnet msg */ -/* We need to know this number to parse hello msg from ksocklnd in - * other LND (usocklnd, for example) */ +/* + * We need to know this number to parse hello msg from ksocklnd in + * other LND (usocklnd, for example) + */ #define KSOCK_PROTO_V2 2 #define KSOCK_PROTO_V3 3 diff --git a/drivers/staging/lustre/include/linux/lnet/types.h b/drivers/staging/lustre/include/linux/lnet/types.h index 11630180c5e7..81d01f1e9eb6 100644 --- a/drivers/staging/lustre/include/linux/lnet/types.h +++ b/drivers/staging/lustre/include/linux/lnet/types.h @@ -36,10 +36,12 @@ #include /** \addtogroup lnet - * @{ */ + * @{ + */ /** \addtogroup lnet_addr - * @{ */ + * @{ + */ /** Portal reserved for LNet's own use. * \see lustre/include/lustre/lustre_idl.h for Lustre portal assignments. @@ -116,10 +118,12 @@ typedef struct { lnet_pid_t pid; } WIRE_ATTR lnet_process_id_packed_t; -/* The wire handle's interface cookie only matches one network interface in +/* + * The wire handle's interface cookie only matches one network interface in * one epoch (i.e. new cookie when the interface restarts or the node * reboots). The object cookie only matches one object on that interface - * during that object's lifetime (i.e. no cookie re-use). */ + * during that object's lifetime (i.e. no cookie re-use). + */ typedef struct { __u64 wh_interface_cookie; __u64 wh_object_cookie; @@ -133,10 +137,12 @@ typedef enum { LNET_MSG_HELLO, } lnet_msg_type_t; -/* The variant fields of the portals message header are aligned on an 8 +/* + * The variant fields of the portals message header are aligned on an 8 * byte boundary in the message header. Note that all types used in these * wire structs MUST be fixed size and the smaller types are placed at the - * end. */ + * end. + */ typedef struct lnet_ack { lnet_handle_wire_t dst_wmd; __u64 match_bits; @@ -185,7 +191,8 @@ typedef struct { } msg; } WIRE_ATTR lnet_hdr_t; -/* A HELLO message contains a magic number and protocol version +/* + * A HELLO message contains a magic number and protocol version * code in the header's dest_nid, the peer's NID in the src_nid, and * LNET_MSG_HELLO in the type field. All other common fields are zero * (including payload_size; i.e. no payload). @@ -208,8 +215,10 @@ typedef struct { #define LNET_PROTO_PING_MAGIC 0x70696E67 /* 'ping' */ /* Placeholder for a future "unified" protocol across all LNDs */ -/* Current LNDs that receive a request with this magic will respond with a - * "stub" reply using their current protocol */ +/* + * Current LNDs that receive a request with this magic will respond with a + * "stub" reply using their current protocol + */ #define LNET_PROTO_MAGIC 0x45726963 /* ! */ #define LNET_PROTO_TCP_VERSION_MAJOR 1 @@ -258,7 +267,7 @@ typedef struct lnet_counters { #define LNET_MAX_INTERFACES 16 -/* +/** * Objects maintained by the LNet are accessed through handles. Handle types * have names of the form lnet_handle_xx_t, where xx is one of the two letter * object type codes ('eq' for event queue, 'md' for memory descriptor, and @@ -318,7 +327,8 @@ typedef struct { /** @} lnet_addr */ /** \addtogroup lnet_me - * @{ */ + * @{ + */ /** * Specifies whether the match entry or memory descriptor should be unlinked @@ -348,7 +358,8 @@ typedef enum { /** @} lnet_me */ /** \addtogroup lnet_md - * @{ */ + * @{ + */ /** * Defines the visible parts of a memory descriptor. Values of this type @@ -450,9 +461,11 @@ typedef struct { lnet_handle_eq_t eq_handle; } lnet_md_t; -/* Max Transfer Unit (minimum supported everywhere). +/* + * Max Transfer Unit (minimum supported everywhere). * CAVEAT EMPTOR, with multinet (i.e. routers forwarding between networks) - * these limits are system wide and not interface-local. */ + * these limits are system wide and not interface-local. + */ #define LNET_MTU_BITS 20 #define LNET_MTU (1 << LNET_MTU_BITS) @@ -506,7 +519,8 @@ typedef struct { /** @} lnet_md */ /** \addtogroup lnet_eq - * @{ */ + * @{ + */ /** * Six types of events can be logged in an event queue. @@ -640,7 +654,8 @@ typedef void (*lnet_eq_handler_t)(lnet_event_t *event); /** @} lnet_eq */ /** \addtogroup lnet_data - * @{ */ + * @{ + */ /** * Specify whether an acknowledgment should be sent by target when the PUT diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 49cd333a8865..c5bf059a8d3b 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -189,8 +189,10 @@ void kiblnd_pack_msg(lnet_ni_t *ni, kib_msg_t *msg, int version, { kib_net_t *net = ni->ni_data; - /* CAVEAT EMPTOR! all message fields not set here should have been - * initialised previously. */ + /* + * CAVEAT EMPTOR! all message fields not set here should have been + * initialised previously. + */ msg->ibm_magic = IBLND_MSG_MAGIC; msg->ibm_version = version; /* ibm_type */ @@ -249,8 +251,10 @@ int kiblnd_unpack_msg(kib_msg_t *msg, int nob) return -EPROTO; } - /* checksum must be computed with ibm_cksum zero and BEFORE anything - * gets flipped */ + /* + * checksum must be computed with ibm_cksum zero and BEFORE anything + * gets flipped + */ msg_cksum = flip ? __swab32(msg->ibm_cksum) : msg->ibm_cksum; msg->ibm_cksum = 0; if (msg_cksum != 0 && @@ -375,17 +379,21 @@ void kiblnd_destroy_peer(kib_peer_t *peer) LIBCFS_FREE(peer, sizeof(*peer)); - /* NB a peer's connections keep a reference on their peer until + /* + * NB a peer's connections keep a reference on their peer until * they are destroyed, so we can be assured that _all_ state to do * with this peer has been cleaned up when its refcount drops to - * zero. */ + * zero. + */ atomic_dec(&net->ibn_npeers); } kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid) { - /* the caller is responsible for accounting the additional reference - * that this creates */ + /* + * the caller is responsible for accounting the additional reference + * that this creates + */ struct list_head *peer_list = kiblnd_nid2peerlist(nid); struct list_head *tmp; kib_peer_t *peer; @@ -474,8 +482,10 @@ static void kiblnd_del_peer_locked(kib_peer_t *peer) } /* NB closing peer's last conn unlinked it. */ } - /* NB peer now unlinked; might even be freed if the peer table had the - * last ref on it. */ + /* + * NB peer now unlinked; might even be freed if the peer table had the + * last ref on it. + */ } static int kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid) @@ -636,13 +646,15 @@ static int kiblnd_get_completion_vector(kib_conn_t *conn, int cpt) kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, int state, int version) { - /* CAVEAT EMPTOR: + /* + * CAVEAT EMPTOR: * If the new conn is created successfully it takes over the caller's * ref on 'peer'. It also "owns" 'cmid' and destroys it when it itself * is destroyed. On failure, the caller's ref on 'peer' remains and * she must dispose of 'cmid'. (Actually I'd block forever if I tried * to destroy 'cmid' here since I'm called from the CM which still has - * its ref on 'cmid'). */ + * its ref on 'cmid'). + */ rwlock_t *glock = &kiblnd_data.kib_global_lock; kib_net_t *net = peer->ibp_ni->ni_data; kib_dev_t *dev; @@ -800,15 +812,19 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, /* Make posted receives complete */ kiblnd_abort_receives(conn); - /* correct # of posted buffers - * NB locking needed now I'm racing with completion */ + /* + * correct # of posted buffers + * NB locking needed now I'm racing with completion + */ spin_lock_irqsave(&sched->ibs_lock, flags); conn->ibc_nrx -= IBLND_RX_MSGS(version) - i; spin_unlock_irqrestore(&sched->ibs_lock, flags); - /* cmid will be destroyed by CM(ofed) after cm_callback + /* + * cmid will be destroyed by CM(ofed) after cm_callback * returned, so we can't refer it anymore - * (by kiblnd_connd()->kiblnd_destroy_conn) */ + * (by kiblnd_connd()->kiblnd_destroy_conn) + */ rdma_destroy_qp(conn->ibc_cmid); conn->ibc_cmid = NULL; @@ -1077,8 +1093,10 @@ void kiblnd_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) if (last_alive != 0) *when = last_alive; - /* peer is not persistent in hash, trigger peer creation - * and connection establishment with a NULL tx */ + /* + * peer is not persistent in hash, trigger peer creation + * and connection establishment with a NULL tx + */ if (peer == NULL) kiblnd_launch_tx(ni, NULL, nid); @@ -2070,8 +2088,10 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) static int kiblnd_hdev_get_attr(kib_hca_dev_t *hdev) { - /* It's safe to assume a HCA can handle a page size - * matching that of the native system */ + /* + * It's safe to assume a HCA can handle a page size + * matching that of the native system + */ hdev->ibh_page_shift = PAGE_SHIFT; hdev->ibh_page_size = 1 << PAGE_SHIFT; hdev->ibh_page_mask = ~((__u64)hdev->ibh_page_size - 1); @@ -2175,7 +2195,8 @@ static int kiblnd_dev_need_failover(kib_dev_t *dev) *kiblnd_tunables.kib_dev_failover > 1) /* debugging */ return 1; - /* XXX: it's UGLY, but I don't have better way to find + /* + * XXX: it's UGLY, but I don't have better way to find * ib-bonding HCA failover because: * * a. no reliable CM event for HCA failover... @@ -2184,7 +2205,8 @@ static int kiblnd_dev_need_failover(kib_dev_t *dev) * We have only two choices at this point: * * a. rdma_bind_addr(), it will conflict with listener cmid - * b. rdma_resolve_addr() to zero addr */ + * b. rdma_resolve_addr() to zero addr + */ cmid = kiblnd_rdma_create_id(kiblnd_dummy_callback, dev, RDMA_PS_TCP, IB_QPT_RC); if (IS_ERR(cmid)) { @@ -2239,15 +2261,19 @@ int kiblnd_dev_failover(kib_dev_t *dev) if (dev->ibd_hdev != NULL && dev->ibd_hdev->ibh_cmid != NULL) { - /* XXX it's not good to close old listener at here, + /* + * XXX it's not good to close old listener at here, * because we can fail to create new listener. * But we have to close it now, otherwise rdma_bind_addr - * will return EADDRINUSE... How crap! */ + * will return EADDRINUSE... How crap! + */ write_lock_irqsave(&kiblnd_data.kib_global_lock, flags); cmid = dev->ibd_hdev->ibh_cmid; - /* make next schedule of kiblnd_dev_need_failover() - * return 1 for me */ + /* + * make next schedule of kiblnd_dev_need_failover() + * return 1 for me + */ dev->ibd_hdev->ibh_cmid = NULL; write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); @@ -2433,9 +2459,11 @@ static void kiblnd_base_shutdown(void) /* flag threads to terminate; wake and wait for them to die */ kiblnd_data.kib_shutdown = 1; - /* NB: we really want to stop scheduler threads net by net + /* + * NB: we really want to stop scheduler threads net by net * instead of the whole module, this should be improved - * with dynamic configuration LNet */ + * with dynamic configuration LNet + */ cfs_percpt_for_each(sched, i, kiblnd_data.kib_scheds) wake_up_all(&sched->ibs_waitq); @@ -2585,8 +2613,10 @@ static int kiblnd_base_startup(void) if (*kiblnd_tunables.kib_nscheds > 0) { nthrs = min(nthrs, *kiblnd_tunables.kib_nscheds); } else { - /* max to half of CPUs, another half is reserved for - * upper layer modules */ + /* + * max to half of CPUs, another half is reserved for + * upper layer modules + */ nthrs = min(max(IBLND_N_SCHED, nthrs >> 1), nthrs); } diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 176c79b95692..5093244ec378 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -409,10 +409,11 @@ kiblnd_handle_rx(kib_rx_t *rx) } LASSERT(tx->tx_waiting); - /* CAVEAT EMPTOR: I could be racing with tx_complete, but... + /* + * CAVEAT EMPTOR: I could be racing with tx_complete, but... * (a) I can overwrite tx_msg since my peer has received it! - * (b) tx_waiting set tells tx_complete() it's not done. */ - + * (b) tx_waiting set tells tx_complete() it's not done. + */ tx->tx_nwrq = 0; /* overwrite PUT_REQ */ rc2 = kiblnd_init_rdma(conn, tx, IBLND_MSG_PUT_DONE, @@ -587,8 +588,10 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob) return rc; } - /* If rd is not tx_rd, it's going to get sent to a peer, who will need - * the rkey */ + /* + * If rd is not tx_rd, it's going to get sent to a peer, who will need + * the rkey + */ rd->rd_key = (rd != tx->tx_rd) ? tx->fmr.fmr_pfmr->fmr->rkey : tx->fmr.fmr_pfmr->fmr->lkey; rd->rd_frags[0].rf_addr &= ~hdev->ibh_page_mask; @@ -625,8 +628,10 @@ static int kiblnd_map_tx(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, __u32 nob; int i; - /* If rd is not tx_rd, it's going to get sent to a peer and I'm the - * RDMA sink */ + /* + * If rd is not tx_rd, it's going to get sent to a peer and I'm the + * RDMA sink + */ tx->tx_dmadir = (rd != tx->tx_rd) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; tx->tx_nfrags = nfrags; @@ -799,9 +804,11 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) (!kiblnd_need_noop(conn) || /* redundant NOOP */ (IBLND_OOB_CAPABLE(ver) && /* posted enough NOOP */ conn->ibc_noops_posted == IBLND_OOB_MSGS(ver)))) { - /* OK to drop when posted enough NOOPs, since + /* + * OK to drop when posted enough NOOPs, since * kiblnd_check_sends will queue NOOP again when - * posted NOOPs complete */ + * posted NOOPs complete + */ spin_unlock(&conn->ibc_lock); kiblnd_tx_done(peer->ibp_ni, tx); spin_lock(&conn->ibc_lock); @@ -820,12 +827,14 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) if (msg->ibm_type == IBLND_MSG_NOOP) conn->ibc_noops_posted++; - /* CAVEAT EMPTOR! This tx could be the PUT_DONE of an RDMA + /* + * CAVEAT EMPTOR! This tx could be the PUT_DONE of an RDMA * PUT. If so, it was first queued here as a PUT_REQ, sent and * stashed on ibc_active_txs, matched by an incoming PUT_ACK, * and then re-queued here. It's (just) possible that * tx_sending is non-zero if we've not done the tx_complete() - * from the first send; hence the ++ rather than = below. */ + * from the first send; hence the ++ rather than = below. + */ tx->tx_sending++; list_add(&tx->tx_list, &conn->ibc_active_txs); @@ -845,8 +854,10 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) if (rc == 0) return 0; - /* NB credits are transferred in the actual - * message, which can only be the last work item */ + /* + * NB credits are transferred in the actual + * message, which can only be the last work item + */ conn->ibc_credits += credit; conn->ibc_outstanding_credits += msg->ibm_credits; conn->ibc_nsends_posted--; @@ -975,9 +986,10 @@ kiblnd_tx_complete(kib_tx_t *tx, int status) spin_lock(&conn->ibc_lock); - /* I could be racing with rdma completion. Whoever makes 'tx' idle - * gets to free it, which also drops its ref on 'conn'. */ - + /* + * I could be racing with rdma completion. Whoever makes 'tx' idle + * gets to free it, which also drops its ref on 'conn'. + */ tx->tx_sending--; conn->ibc_nsends_posted--; if (tx->tx_msg->ibm_type == IBLND_MSG_NOOP) @@ -1301,14 +1313,17 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) unsigned long flags; int rc; - /* If I get here, I've committed to send, so I complete the tx with - * failure on any problems */ - + /* + * If I get here, I've committed to send, so I complete the tx with + * failure on any problems + */ LASSERT(tx == NULL || tx->tx_conn == NULL); /* only set when assigned a conn */ LASSERT(tx == NULL || tx->tx_nwrq > 0); /* work items have been set up */ - /* First time, just use a read lock since I expect to find my peer - * connected */ + /* + * First time, just use a read lock since I expect to find my peer + * connected + */ read_lock_irqsave(g_lock, flags); peer = kiblnd_find_peer_locked(nid); @@ -1630,8 +1645,7 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) /* No RDMA: local completion may happen now! */ lnet_finalize(ni, lntmsg, 0); } else { - /* RDMA: lnet_finalize(lntmsg) when it - * completes */ + /* RDMA: lnet_finalize(lntmsg) when it completes */ tx->tx_lntmsg[0] = lntmsg; } @@ -1814,12 +1828,14 @@ kiblnd_peer_notify(kib_peer_t *peer) void kiblnd_close_conn_locked(kib_conn_t *conn, int error) { - /* This just does the immediate housekeeping. 'error' is zero for a + /* + * This just does the immediate housekeeping. 'error' is zero for a * normal shutdown which can happen only after the connection has been * established. If the connection is established, schedule the - * connection to be finished off by the connd. Otherwise the connd is + * connection to be finished off by the connd. Otherwise the connd is * already dealing with it (either to set it up or tear it down). - * Caller holds kib_global_lock exclusively in irq context */ + * Caller holds kib_global_lock exclusively in irq context + */ kib_peer_t *peer = conn->ibc_peer; kib_dev_t *dev; unsigned long flags; @@ -1957,14 +1973,17 @@ kiblnd_finalise_conn(kib_conn_t *conn) kiblnd_set_conn_state(conn, IBLND_CONN_DISCONNECTED); - /* abort_receives moves QP state to IB_QPS_ERR. This is only required + /* + * abort_receives moves QP state to IB_QPS_ERR. This is only required * for connections that didn't get as far as being connected, because - * rdma_disconnect() does this for free. */ + * rdma_disconnect() does this for free. + */ kiblnd_abort_receives(conn); - /* Complete all tx descs not waiting for sends to complete. - * NB we should be safe from RDMA now that the QP has changed state */ - + /* + * Complete all tx descs not waiting for sends to complete. + * NB we should be safe from RDMA now that the QP has changed state + */ kiblnd_abort_txs(conn, &conn->ibc_tx_noops); kiblnd_abort_txs(conn, &conn->ibc_tx_queue); kiblnd_abort_txs(conn, &conn->ibc_tx_queue_rsrvd); @@ -2067,8 +2086,10 @@ kiblnd_connreq_done(kib_conn_t *conn, int status) kiblnd_set_conn_state(conn, IBLND_CONN_ESTABLISHED); kiblnd_peer_alive(peer); - /* Add conn to peer's list and nuke any dangling conns from a different - * peer instance... */ + /* + * Add conn to peer's list and nuke any dangling conns from a different + * peer instance... + */ kiblnd_conn_addref(conn); /* +1 ref for ibc_list */ list_add(&conn->ibc_list, &peer->ibp_conns); if (active) @@ -2180,12 +2201,14 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; } - /* Future protocol version compatibility support! If the + /* + * Future protocol version compatibility support! If the * o2iblnd-specific protocol changes, or when LNET unifies * protocols over all LNDs, the initial connection will * negotiate a protocol version. I trap this here to avoid * console errors; the reject tells the peer which protocol I - * speak. */ + * speak. + */ if (reqmsg->ibm_magic == LNET_PROTO_MAGIC || reqmsg->ibm_magic == __swab32(LNET_PROTO_MAGIC)) goto failed; @@ -2352,9 +2375,10 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; } - /* conn now "owns" cmid, so I return success from here on to ensure the - * CM callback doesn't destroy cmid. */ - + /* + * conn now "owns" cmid, so I return success from here on to ensure the + * CM callback doesn't destroy cmid. + */ conn->ibc_incarnation = reqmsg->ibm_srcstamp; conn->ibc_credits = IBLND_MSG_QUEUE_SIZE(version); conn->ibc_reserved_credits = IBLND_MSG_QUEUE_SIZE(version); @@ -2423,11 +2447,13 @@ kiblnd_reconnect(kib_conn_t *conn, int version, write_lock_irqsave(&kiblnd_data.kib_global_lock, flags); - /* retry connection if it's still needed and no other connection + /* + * retry connection if it's still needed and no other connection * attempts (active or passive) are in progress * NB: reconnect is still needed even when ibp_tx_queue is * empty if ibp_version != version because reconnect may be - * initiated by kiblnd_query() */ + * initiated by kiblnd_query() + */ if ((!list_empty(&peer->ibp_tx_queue) || peer->ibp_version != version) && peer->ibp_connecting == 1 && @@ -2520,9 +2546,11 @@ kiblnd_rejected(kib_conn_t *conn, int reason, void *priv, int priv_nob) if (priv_nob >= sizeof(kib_rej_t) && rej->ibr_version > IBLND_MSG_VERSION_1) { - /* priv_nob is always 148 in current version + /* + * priv_nob is always 148 in current version * of OFED, so we still need to check version. - * (define of IB_CM_REJ_PRIVATE_DATA_SIZE) */ + * (define of IB_CM_REJ_PRIVATE_DATA_SIZE) + */ cp = &rej->ibr_cp; if (flip) { @@ -2698,11 +2726,12 @@ kiblnd_check_connreply(kib_conn_t *conn, void *priv, int priv_nob) return; failed: - /* NB My QP has already established itself, so I handle anything going + /* + * NB My QP has already established itself, so I handle anything going * wrong here by setting ibc_comms_error. * kiblnd_connreq_done(0) moves the conn state to ESTABLISHED, but then - * immediately tears it down. */ - + * immediately tears it down. + */ LASSERT(rc != 0); conn->ibc_comms_error = rc; kiblnd_connreq_done(conn, 0); @@ -2735,10 +2764,11 @@ kiblnd_active_connect(struct rdma_cm_id *cmid) return -ENOMEM; } - /* conn "owns" cmid now, so I return success from here on to ensure the + /* + * conn "owns" cmid now, so I return success from here on to ensure the * CM callback doesn't destroy cmid. conn also takes over cmid's ref - * on peer */ - + * on peer + */ msg = &conn->ibc_connvars->cv_msg; memset(msg, 0, sizeof(*msg)); @@ -2932,8 +2962,10 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) LCONSOLE_ERROR_MSG(0x131, "Received notification of device removal\n" "Please shutdown LNET to allow this to proceed\n"); - /* Can't remove network from underneath LNET for now, so I have - * to ignore this */ + /* + * Can't remove network from underneath LNET for now, so I have + * to ignore this + */ return 0; case RDMA_CM_EVENT_ADDR_CHANGE: @@ -2992,9 +3024,11 @@ kiblnd_check_conns(int idx) struct list_head *ctmp; unsigned long flags; - /* NB. We expect to have a look at all the peers and not find any + /* + * NB. We expect to have a look at all the peers and not find any * RDMAs to time out, so we just use a shared lock while we - * take a look... */ + * take a look... + */ read_lock_irqsave(&kiblnd_data.kib_global_lock, flags); list_for_each(ptmp, peers) { @@ -3039,18 +3073,22 @@ kiblnd_check_conns(int idx) read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); - /* Handle timeout by closing the whole + /* + * Handle timeout by closing the whole * connection. We can only be sure RDMA activity - * has ceased once the QP has been modified. */ + * has ceased once the QP has been modified. + */ list_for_each_entry_safe(conn, tmp, &closes, ibc_connd_list) { list_del(&conn->ibc_connd_list); kiblnd_close_conn(conn, -ETIMEDOUT); kiblnd_conn_decref(conn); } - /* In case we have enough credits to return via a + /* + * In case we have enough credits to return via a * NOOP, but there were no non-blocking tx descs - * free to do it last time... */ + * free to do it last time... + */ while (!list_empty(&checksends)) { conn = list_entry(checksends.next, kib_conn_t, ibc_connd_list); @@ -3135,14 +3173,15 @@ kiblnd_connd(void *arg) spin_unlock_irqrestore(&kiblnd_data.kib_connd_lock, flags); dropped_lock = 1; - /* Time to check for RDMA timeouts on a few more + /* + * Time to check for RDMA timeouts on a few more * peers: I do checks every 'p' seconds on a * proportion of the peer table and I need to check * every connection 'n' times within a timeout * interval, to ensure I detect a timeout on any * connection within (n+1)/n times the timeout - * interval. */ - + * interval. + */ if (*kiblnd_tunables.kib_timeout > n * p) chunk = (chunk * n * p) / *kiblnd_tunables.kib_timeout; @@ -3205,12 +3244,14 @@ kiblnd_complete(struct ib_wc *wc) LBUG(); case IBLND_WID_RDMA: - /* We only get RDMA completion notification if it fails. All + /* + * We only get RDMA completion notification if it fails. All * subsequent work items, including the final SEND will fail * too. However we can't print out any more info about the * failing RDMA because 'tx' might be back on the idle list or * even reused already if we didn't manage to post all our work - * items */ + * items + */ CNETERR("RDMA (tx: %p) failed: %d\n", kiblnd_wreqid2ptr(wc->wr_id), wc->status); return; @@ -3229,11 +3270,13 @@ kiblnd_complete(struct ib_wc *wc) void kiblnd_cq_completion(struct ib_cq *cq, void *arg) { - /* NB I'm not allowed to schedule this conn once its refcount has + /* + * NB I'm not allowed to schedule this conn once its refcount has * reached 0. Since fundamentally I'm racing with scheduler threads * consuming my CQ I could be called after all completions have * occurred. But in this case, ibc_nrx == 0 && ibc_nsends_posted == 0 - * and this CQ is about to be destroyed so I NOOP. */ + * and this CQ is about to be destroyed so I NOOP. + */ kib_conn_t *conn = arg; struct kib_sched_info *sched = conn->ibc_sched; unsigned long flags; @@ -3346,9 +3389,11 @@ kiblnd_scheduler(void *arg) spin_lock_irqsave(&sched->ibs_lock, flags); if (rc != 0 || conn->ibc_ready) { - /* There may be another completion waiting; get + /* + * There may be another completion waiting; get * another scheduler to check while I handle - * this one... */ + * this one... + */ /* +1 ref for sched_conns */ kiblnd_conn_addref(conn); list_add_tail(&conn->ibc_sched_list, @@ -3461,10 +3506,12 @@ kiblnd_failover_thread(void *arg) if (!long_sleep || rc != 0) continue; - /* have a long sleep, routine check all active devices, + /* + * have a long sleep, routine check all active devices, * we need checking like this because if there is not active * connection on the dev and no SEND from local, we may listen - * on wrong HCA for ever while there is a bonding failover */ + * on wrong HCA for ever while there is a bonding failover + */ list_for_each_entry(dev, &kiblnd_data.kib_devs, ibd_list) { if (kiblnd_dev_can_failover(dev)) { list_add_tail(&dev->ibd_fail_list, diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c index 1d4e7efb53d4..afbd6d1df31d 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c @@ -52,8 +52,10 @@ static int timeout = 50; module_param(timeout, int, 0644); MODULE_PARM_DESC(timeout, "timeout (seconds)"); -/* Number of threads in each scheduler pool which is percpt, - * we will estimate reasonable value based on CPUs if it's set to zero. */ +/* + * Number of threads in each scheduler pool which is percpt, + * we will estimate reasonable value based on CPUs if it's set to zero. + */ static int nscheds; module_param(nscheds, int, 0444); MODULE_PARM_DESC(nscheds, "number of threads in each scheduler pool"); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 05aa90ea597a..a237cde543c4 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -163,10 +163,12 @@ ksocknal_destroy_peer(ksock_peer_t *peer) LIBCFS_FREE(peer, sizeof(*peer)); - /* NB a peer's connections and routes keep a reference on their peer + /* + * NB a peer's connections and routes keep a reference on their peer * until they are destroyed, so we can be assured that _all_ state to * do with this peer has been cleaned up when its refcount drops to - * zero. */ + * zero. + */ spin_lock_bh(&net->ksnn_lock); net->ksnn_npeers--; spin_unlock_bh(&net->ksnn_lock); @@ -226,8 +228,10 @@ ksocknal_unlink_peer_locked(ksock_peer_t *peer) ip = peer->ksnp_passive_ips[i]; iface = ksocknal_ip2iface(peer->ksnp_ni, ip); - /* All IPs in peer->ksnp_passive_ips[] come from the - * interface list, therefore the call must succeed. */ + /* + * All IPs in peer->ksnp_passive_ips[] come from the + * interface list, therefore the call must succeed. + */ LASSERT(iface != NULL); CDEBUG(D_NET, "peer=%p iface=%p ksni_nroutes=%d\n", @@ -358,8 +362,10 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn) route->ksnr_connected |= (1<ksnr_conn_count++; - /* Successful connection => further attempts can - * proceed immediately */ + /* + * Successful connection => further attempts can + * proceed immediately + */ route->ksnr_retry_interval = 0; } @@ -438,8 +444,10 @@ ksocknal_del_route_locked(ksock_route_t *route) if (list_empty(&peer->ksnp_routes) && list_empty(&peer->ksnp_conns)) { - /* I've just removed the last route to a peer with no active - * connections */ + /* + * I've just removed the last route to a peer with no active + * connections + */ ksocknal_unlink_peer_locked(peer); } } @@ -539,9 +547,10 @@ ksocknal_del_peer_locked(ksock_peer_t *peer, __u32 ip) } if (nshared == 0) { - /* remove everything else if there are no explicit entries - * left */ - + /* + * remove everything else if there are no explicit entries + * left + */ list_for_each_safe(tmp, nxt, &peer->ksnp_routes) { route = list_entry(tmp, ksock_route_t, ksnr_list); @@ -692,8 +701,10 @@ ksocknal_local_ipvec(lnet_ni_t *ni, __u32 *ipaddrs) nip = net->ksnn_ninterfaces; LASSERT(nip <= LNET_MAX_INTERFACES); - /* Only offer interfaces for additional connections if I have - * more than one. */ + /* + * Only offer interfaces for additional connections if I have + * more than one. + */ if (nip < 2) { read_unlock(&ksocknal_data.ksnd_global_lock); return 0; @@ -757,33 +768,38 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips) int best_netmatch; int best_npeers; - /* CAVEAT EMPTOR: We do all our interface matching with an + /* + * CAVEAT EMPTOR: We do all our interface matching with an * exclusive hold of global lock at IRQ priority. We're only * expecting to be dealing with small numbers of interfaces, so the - * O(n**3)-ness shouldn't matter */ - - /* Also note that I'm not going to return more than n_peerips - * interfaces, even if I have more myself */ - + * O(n**3)-ness shouldn't matter + */ + /* + * Also note that I'm not going to return more than n_peerips + * interfaces, even if I have more myself + */ write_lock_bh(global_lock); LASSERT(n_peerips <= LNET_MAX_INTERFACES); LASSERT(net->ksnn_ninterfaces <= LNET_MAX_INTERFACES); - /* Only match interfaces for additional connections - * if I have > 1 interface */ + /* + * Only match interfaces for additional connections + * if I have > 1 interface + */ n_ips = (net->ksnn_ninterfaces < 2) ? 0 : min(n_peerips, net->ksnn_ninterfaces); for (i = 0; peer->ksnp_n_passive_ips < n_ips; i++) { /* ^ yes really... */ - /* If we have any new interfaces, first tick off all the + /* + * If we have any new interfaces, first tick off all the * peer IPs that match old interfaces, then choose new * interfaces to match the remaining peer IPS. * We don't forget interfaces we've stopped using; we might - * start using them again... */ - + * start using them again... + */ if (i < peer->ksnp_n_passive_ips) { /* Old interface. */ ip = peer->ksnp_passive_ips[i]; @@ -860,16 +876,19 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, int i; int j; - /* CAVEAT EMPTOR: We do all our interface matching with an + /* + * CAVEAT EMPTOR: We do all our interface matching with an * exclusive hold of global lock at IRQ priority. We're only * expecting to be dealing with small numbers of interfaces, so the - * O(n**3)-ness here shouldn't matter */ - + * O(n**3)-ness here shouldn't matter + */ write_lock_bh(global_lock); if (net->ksnn_ninterfaces < 2) { - /* Only create additional connections - * if I have > 1 interface */ + /* + * Only create additional connections + * if I have > 1 interface + */ write_unlock_bh(global_lock); return; } @@ -1039,8 +1058,10 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, conn->ksnc_peer = NULL; conn->ksnc_route = NULL; conn->ksnc_sock = sock; - /* 2 ref, 1 for conn, another extra ref prevents socket - * being closed before establishment of connection */ + /* + * 2 ref, 1 for conn, another extra ref prevents socket + * being closed before establishment of connection + */ atomic_set(&conn->ksnc_sock_refcount, 2); conn->ksnc_type = type; ksocknal_lib_save_callback(sock, conn); @@ -1067,11 +1088,12 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, if (rc != 0) goto failed_1; - /* Find out/confirm peer's NID and connection type and get the + /* + * Find out/confirm peer's NID and connection type and get the * vector of interfaces she's willing to let me connect to. * Passive connections use the listener timeout since the peer sends - * eagerly */ - + * eagerly + */ if (active) { peer = route->ksnr_peer; LASSERT(ni == peer->ksnp_ni); @@ -1130,8 +1152,10 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, peer2 = ksocknal_find_peer_locked(ni, peerid); if (peer2 == NULL) { - /* NB this puts an "empty" peer in the peer - * table (which takes my ref) */ + /* + * NB this puts an "empty" peer in the peer + * table (which takes my ref) + */ list_add_tail(&peer->ksnp_list, ksocknal_nid2peerlist(peerid.nid)); } else { @@ -1143,8 +1167,10 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, ksocknal_peer_addref(peer); peer->ksnp_accepting++; - /* Am I already connecting to this guy? Resolve in - * favour of higher NID... */ + /* + * Am I already connecting to this guy? Resolve in + * favour of higher NID... + */ if (peerid.nid < ni->ni_nid && ksocknal_connecting(peer, conn->ksnc_ipaddr)) { rc = EALREADY; @@ -1162,7 +1188,8 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, } if (peer->ksnp_proto == NULL) { - /* Never connected before. + /* + * Never connected before. * NB recv_hello may have returned EPROTO to signal my peer * wants a different protocol than the one I asked for. */ @@ -1198,8 +1225,10 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, goto failed_2; } - /* Refuse to duplicate an existing connection, unless this is a - * loopback connection */ + /* + * Refuse to duplicate an existing connection, unless this is a + * loopback connection + */ if (conn->ksnc_ipaddr != conn->ksnc_myipaddr) { list_for_each(tmp, &peer->ksnp_conns) { conn2 = list_entry(tmp, ksock_conn_t, ksnc_list); @@ -1209,8 +1238,10 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, conn2->ksnc_type != conn->ksnc_type) continue; - /* Reply on a passive connection attempt so the peer - * realises we're connected. */ + /* + * Reply on a passive connection attempt so the peer + * realises we're connected. + */ LASSERT(rc == 0); if (!active) rc = EALREADY; @@ -1220,9 +1251,11 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, } } - /* If the connection created by this route didn't bind to the IP + /* + * If the connection created by this route didn't bind to the IP * address the route connected to, the connection/route matching - * code below probably isn't going to work. */ + * code below probably isn't going to work. + */ if (active && route->ksnr_ipaddr != conn->ksnc_ipaddr) { CERROR("Route %s %pI4h connected to %pI4h\n", @@ -1231,10 +1264,12 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, &conn->ksnc_ipaddr); } - /* Search for a route corresponding to the new connection and + /* + * Search for a route corresponding to the new connection and * create an association. This allows incoming connections created * by routes in my peer to match my own route entries so I don't - * continually create duplicate routes. */ + * continually create duplicate routes. + */ list_for_each(tmp, &peer->ksnp_routes) { route = list_entry(tmp, ksock_route_t, ksnr_list); @@ -1278,14 +1313,14 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, write_unlock_bh(global_lock); - /* We've now got a new connection. Any errors from here on are just + /* + * We've now got a new connection. Any errors from here on are just * like "normal" comms errors and we close the connection normally. * NB (a) we still have to send the reply HELLO for passive * connections, * (b) normal I/O on the conn is blocked until I setup and call the * socket callbacks. */ - CDEBUG(D_NET, "New conn %s p %d.x %pI4h -> %pI4h/%d incarnation:%lld sched[%d:%d]\n", libcfs_id2str(peerid), conn->ksnc_proto->pro_version, &conn->ksnc_myipaddr, &conn->ksnc_ipaddr, @@ -1305,11 +1340,13 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, LIBCFS_FREE(hello, offsetof(ksock_hello_msg_t, kshm_ips[LNET_MAX_INTERFACES])); - /* setup the socket AFTER I've received hello (it disables + /* + * setup the socket AFTER I've received hello (it disables * SO_LINGER). I might call back to the acceptor who may want * to send a protocol version response and then close the * socket; this ensures the socket only tears down after the - * response has been sent. */ + * response has been sent. + */ if (rc == 0) rc = ksocknal_lib_setup_sock(sock); @@ -1363,8 +1400,10 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, if (!active) { if (rc > 0) { - /* Request retry by replying with CONN_NONE - * ksnc_proto has been set already */ + /* + * Request retry by replying with CONN_NONE + * ksnc_proto has been set already + */ conn->ksnc_type = SOCKLND_CONN_NONE; hello->kshm_nips = 0; ksocknal_send_hello(ni, conn, peerid.nid, hello); @@ -1393,9 +1432,11 @@ failed_0: void ksocknal_close_conn_locked(ksock_conn_t *conn, int error) { - /* This just does the immmediate housekeeping, and queues the + /* + * This just does the immmediate housekeeping, and queues the * connection for the reaper to terminate. - * Caller holds ksnd_global_lock exclusively in irq context */ + * Caller holds ksnd_global_lock exclusively in irq context + */ ksock_peer_t *peer = conn->ksnc_peer; ksock_route_t *route; ksock_conn_t *conn2; @@ -1445,8 +1486,10 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) LASSERT(conn->ksnc_proto == &ksocknal_protocol_v3x); - /* throw them to the last connection..., - * these TXs will be send to /dev/null by scheduler */ + /* + * throw them to the last connection..., + * these TXs will be send to /dev/null by scheduler + */ list_for_each_entry(tx, &peer->ksnp_tx_queue, tx_list) ksocknal_tx_prep(conn, tx); @@ -1461,8 +1504,10 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) peer->ksnp_error = error; /* stash last conn close reason */ if (list_empty(&peer->ksnp_routes)) { - /* I've just closed last conn belonging to a - * peer with no routes to it */ + /* + * I've just closed last conn belonging to a + * peer with no routes to it + */ ksocknal_unlink_peer_locked(peer); } } @@ -1482,10 +1527,11 @@ ksocknal_peer_failed(ksock_peer_t *peer) int notify = 0; unsigned long last_alive = 0; - /* There has been a connection failure or comms error; but I'll only + /* + * There has been a connection failure or comms error; but I'll only * tell LNET I think the peer is dead if it's to another kernel and - * there are no connections or connection attempts in existence. */ - + * there are no connections or connection attempts in existence. + */ read_lock(&ksocknal_data.ksnd_global_lock); if ((peer->ksnp_id.pid & LNET_PID_USERFLAG) == 0 && @@ -1511,8 +1557,10 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn) ksock_tx_t *tmp; LIST_HEAD(zlist); - /* NB safe to finalize TXs because closing of socket will - * abort all buffered data */ + /* + * NB safe to finalize TXs because closing of socket will + * abort all buffered data + */ LASSERT(conn->ksnc_sock == NULL); spin_lock(&peer->ksnp_lock); @@ -1542,10 +1590,12 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn) void ksocknal_terminate_conn(ksock_conn_t *conn) { - /* This gets called by the reaper (guaranteed thread context) to + /* + * This gets called by the reaper (guaranteed thread context) to * disengage the socket from its callbacks and close it. * ksnc_refcount will eventually hit zero, and then the reaper will - * destroy it. */ + * destroy it. + */ ksock_peer_t *peer = conn->ksnc_peer; ksock_sched_t *sched = conn->ksnc_scheduler; int failed = 0; @@ -1576,8 +1626,10 @@ ksocknal_terminate_conn(ksock_conn_t *conn) ksocknal_lib_reset_callback(conn->ksnc_sock, conn); - /* OK, so this conn may not be completely disengaged from its - * scheduler yet, but it _has_ committed to terminate... */ + /* + * OK, so this conn may not be completely disengaged from its + * scheduler yet, but it _has_ committed to terminate... + */ conn->ksnc_scheduler->kss_nconns--; if (peer->ksnp_error != 0) { @@ -1592,11 +1644,13 @@ ksocknal_terminate_conn(ksock_conn_t *conn) if (failed) ksocknal_peer_failed(peer); - /* The socket is closed on the final put; either here, or in + /* + * The socket is closed on the final put; either here, or in * ksocknal_{send,recv}msg(). Since we set up the linger2 option * when the connection was established, this will close the socket * immediately, aborting anything buffered in it. Any hung - * zero-copy transmits will therefore complete in finite time. */ + * zero-copy transmits will therefore complete in finite time. + */ ksocknal_connsock_decref(conn); } @@ -1760,8 +1814,10 @@ ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr) void ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive) { - /* The router is telling me she's been notified of a change in - * gateway state.... */ + /* + * The router is telling me she's been notified of a change in + * gateway state.... + */ lnet_process_id_t id = {0}; id.nid = gw_nid; @@ -1776,8 +1832,10 @@ ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive) return; } - /* ...otherwise do nothing. We can only establish new connections - * if we have autroutes, and these connect on demand. */ + /* + * ...otherwise do nothing. We can only establish new connections + * if we have autroutes, and these connect on demand. + */ } void @@ -2397,8 +2455,10 @@ ksocknal_base_startup(void) if (*ksocknal_tunables.ksnd_nscheds > 0) { nthrs = min(nthrs, *ksocknal_tunables.ksnd_nscheds); } else { - /* max to half of CPUs, assume another half should be - * reserved for upper layer modules */ + /* + * max to half of CPUs, assume another half should be + * reserved for upper layer modules + */ nthrs = min(max(SOCKNAL_NSCHEDS, nthrs >> 1), nthrs); } @@ -2425,8 +2485,10 @@ ksocknal_base_startup(void) ksocknal_data.ksnd_connd_starting = 0; ksocknal_data.ksnd_connd_failed_stamp = 0; ksocknal_data.ksnd_connd_starting_stamp = ktime_get_real_seconds(); - /* must have at least 2 connds to remain responsive to accepts while - * connecting */ + /* + * must have at least 2 connds to remain responsive to accepts while + * connecting + */ if (*ksocknal_tunables.ksnd_nconnds < SOCKNAL_CONND_RESV + 1) *ksocknal_tunables.ksnd_nconnds = SOCKNAL_CONND_RESV + 1; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h index f4fa72550657..a4117adabc28 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h @@ -69,8 +69,10 @@ #define SOCKNAL_VERSION_DEBUG 0 /* enable protocol version debugging */ -/* risk kmap deadlock on multi-frag I/O (backs off to single-frag if disabled). - * no risk if we're not running on a CONFIG_HIGHMEM platform. */ +/* + * risk kmap deadlock on multi-frag I/O (backs off to single-frag if disabled). + * no risk if we're not running on a CONFIG_HIGHMEM platform. + */ #ifdef CONFIG_HIGHMEM # define SOCKNAL_RISK_KMAP_DEADLOCK 0 #else @@ -237,15 +239,16 @@ typedef struct { #define SOCKNAL_INIT_DATA 1 #define SOCKNAL_INIT_ALL 2 -/* A packet just assembled for transmission is represented by 1 or more +/* + * A packet just assembled for transmission is represented by 1 or more * struct iovec fragments (the first frag contains the portals header), * followed by 0 or more lnet_kiov_t fragments. * * On the receive side, initially 1 struct iovec fragment is posted for * receive (the header). Once the header has been received, the payload is * received into either struct iovec or lnet_kiov_t fragments, depending on - * what the header matched or whether the message needs forwarding. */ - + * what the header matched or whether the message needs forwarding. + */ struct ksock_conn; /* forward ref */ struct ksock_peer; /* forward ref */ struct ksock_route; /* forward ref */ @@ -288,8 +291,10 @@ typedef struct /* transmit packet */ /* network zero copy callback descriptor embedded in ksock_tx_t */ -/* space for the rx frag descriptors; we either read a single contiguous - * header, or up to LNET_MAX_IOV frags of payload of either type. */ +/* + * space for the rx frag descriptors; we either read a single contiguous + * header, or up to LNET_MAX_IOV frags of payload of either type. + */ typedef union { struct kvec iov[LNET_MAX_IOV]; lnet_kiov_t kiov[LNET_MAX_IOV]; @@ -463,11 +468,13 @@ typedef struct ksock_proto { /* handle ZC ACK */ int (*pro_handle_zcack)(ksock_conn_t *, __u64, __u64); - /* msg type matches the connection type: + /* + * msg type matches the connection type: * return value: * return MATCH_NO : no * return MATCH_YES : matching type - * return MATCH_MAY : can be backup */ + * return MATCH_MAY : can be backup + */ int (*pro_match_tx)(ksock_conn_t *, ksock_tx_t *, int); } ksock_proto_t; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index a0955d21fec2..f53677de2a16 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -216,8 +216,10 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) conn->ksnc_tx_bufnob += rc; /* account it */ if (bufnob < conn->ksnc_tx_bufnob) { - /* allocated send buffer bytes < computed; infer - * something got ACKed */ + /* + * allocated send buffer bytes < computed; infer + * something got ACKed + */ conn->ksnc_tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout); conn->ksnc_peer->ksnp_last_alive = cfs_time_current(); @@ -256,8 +258,10 @@ ksocknal_recv_iov (ksock_conn_t *conn) LASSERT(conn->ksnc_rx_niov > 0); - /* Never touch conn->ksnc_rx_iov or change connection - * status inside ksocknal_lib_recv_iov */ + /* + * Never touch conn->ksnc_rx_iov or change connection + * status inside ksocknal_lib_recv_iov + */ rc = ksocknal_lib_recv_iov(conn); if (rc <= 0) @@ -301,8 +305,10 @@ ksocknal_recv_kiov (ksock_conn_t *conn) LASSERT(conn->ksnc_rx_nkiov > 0); - /* Never touch conn->ksnc_rx_kiov or change connection - * status inside ksocknal_lib_recv_iov */ + /* + * Never touch conn->ksnc_rx_kiov or change connection + * status inside ksocknal_lib_recv_iov + */ rc = ksocknal_lib_recv_kiov(conn); if (rc <= 0) @@ -340,9 +346,11 @@ ksocknal_recv_kiov (ksock_conn_t *conn) static int ksocknal_receive (ksock_conn_t *conn) { - /* Return 1 on success, 0 on EOF, < 0 on error. + /* + * Return 1 on success, 0 on EOF, < 0 on error. * Caller checks ksnc_rx_nob_wanted to determine - * progress/completion. */ + * progress/completion. + */ int rc; if (ksocknal_data.ksnd_stall_rx != 0) { @@ -435,12 +443,14 @@ ksocknal_check_zc_req(ksock_tx_t *tx) ksock_conn_t *conn = tx->tx_conn; ksock_peer_t *peer = conn->ksnc_peer; - /* Set tx_msg.ksm_zc_cookies[0] to a unique non-zero cookie and add tx + /* + * Set tx_msg.ksm_zc_cookies[0] to a unique non-zero cookie and add tx * to ksnp_zc_req_list if some fragment of this message should be sent * zero-copy. Our peer will send an ACK containing this cookie when * she has received this message to tell us we can signal completion. * tx_msg.ksm_zc_cookies[0] remains non-zero while tx is on - * ksnp_zc_req_list. */ + * ksnp_zc_req_list. + */ LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); LASSERT(tx->tx_zc_capable); @@ -450,9 +460,10 @@ ksocknal_check_zc_req(ksock_tx_t *tx) !conn->ksnc_zc_capable) return; - /* assign cookie and queue tx to pending list, it will be released when - * a matching ack is received. See ksocknal_handle_zcack() */ - + /* + * assign cookie and queue tx to pending list, it will be released when + * a matching ack is received. See ksocknal_handle_zcack() + */ ksocknal_tx_addref(tx); spin_lock(&peer->ksnp_lock); @@ -688,10 +699,12 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) ksock_tx_t *ztx = NULL; int bufnob = 0; - /* called holding global lock (read or irq-write) and caller may + /* + * called holding global lock (read or irq-write) and caller may * not have dropped this lock between finding conn and calling me, * so we don't need the {get,put}connsock dance to deref - * ksnc_sock... */ + * ksnc_sock... + */ LASSERT(!conn->ksnc_closing); CDEBUG(D_NET, "Sending to %s ip %pI4h:%d\n", @@ -701,12 +714,14 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) ksocknal_tx_prep(conn, tx); - /* Ensure the frags we've been given EXACTLY match the number of + /* + * Ensure the frags we've been given EXACTLY match the number of * bytes we want to send. Many TCP/IP stacks disregard any total * size parameters passed to them and just look at the frags. * * We always expect at least 1 mapped fragment containing the - * complete ksocknal message header. */ + * complete ksocknal message header. + */ LASSERT(lnet_iov_nob (tx->tx_niov, tx->tx_iov) + lnet_kiov_nob(tx->tx_nkiov, tx->tx_kiov) == (unsigned int)tx->tx_nob); @@ -736,8 +751,10 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) } if (msg->ksm_type == KSOCK_MSG_NOOP) { - /* The packet is noop ZC ACK, try to piggyback the ack_cookie - * on a normal packet so I don't need to send it */ + /* + * The packet is noop ZC ACK, try to piggyback the ack_cookie + * on a normal packet so I don't need to send it + */ LASSERT(msg->ksm_zc_cookies[1] != 0); LASSERT(conn->ksnc_proto->pro_queue_tx_zcack != NULL); @@ -745,8 +762,10 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) ztx = tx; /* ZC ACK piggybacked on ztx release tx later */ } else { - /* It's a normal packet - can it piggback a noop zc-ack that - * has been queued already? */ + /* + * It's a normal packet - can it piggback a noop zc-ack that + * has been queued already? + */ LASSERT(msg->ksm_zc_cookies[1] == 0); LASSERT(conn->ksnc_proto->pro_queue_tx_msg != NULL); @@ -846,9 +865,11 @@ ksocknal_launch_packet (lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) if (ksocknal_find_connectable_route_locked(peer) == NULL) { conn = ksocknal_find_conn_locked(peer, tx, tx->tx_nonblk); if (conn != NULL) { - /* I've got no routes that need to be + /* + * I've got no routes that need to be * connecting and I do have an actual - * connection... */ + * connection... + */ ksocknal_queue_tx_locked (tx, conn); read_unlock(g_lock); return 0; @@ -932,9 +953,10 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) int desc_size; int rc; - /* NB 'private' is different depending on what we're sending. - * Just ignore it... */ - + /* + * NB 'private' is different depending on what we're sending. + * Just ignore it... + */ CDEBUG(D_NET, "sending %u bytes in %d frags to %s\n", payload_nob, payload_niov, libcfs_id2str(target)); @@ -1075,9 +1097,10 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) return 1; } - /* Set up to skip as much as possible now. If there's more left - * (ran out of iov entries) we'll get called again */ - + /* + * Set up to skip as much as possible now. If there's more left + * (ran out of iov entries) we'll get called again + */ conn->ksnc_rx_state = SOCKNAL_RX_SLOP; conn->ksnc_rx_nob_left = nob_to_skip; conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; @@ -1416,10 +1439,12 @@ int ksocknal_scheduler(void *arg) LASSERT(conn->ksnc_rx_scheduled); LASSERT(conn->ksnc_rx_ready); - /* clear rx_ready in case receive isn't complete. + /* + * clear rx_ready in case receive isn't complete. * Do it BEFORE we call process_recv, since * data_ready can set it any time after we release - * kss_lock. */ + * kss_lock. + */ conn->ksnc_rx_ready = 0; spin_unlock_bh(&sched->kss_lock); @@ -1435,9 +1460,11 @@ int ksocknal_scheduler(void *arg) conn->ksnc_rx_ready = 1; if (conn->ksnc_rx_state == SOCKNAL_RX_PARSE) { - /* Conn blocked waiting for ksocknal_recv() + /* + * Conn blocked waiting for ksocknal_recv() * I change its state (under lock) to signal - * it can be rescheduled */ + * it can be rescheduled + */ conn->ksnc_rx_state = SOCKNAL_RX_PARSE_WAIT; } else if (conn->ksnc_rx_ready) { /* reschedule for rx */ @@ -1478,16 +1505,20 @@ int ksocknal_scheduler(void *arg) /* dequeue now so empty list => more to send */ list_del(&tx->tx_list); - /* Clear tx_ready in case send isn't complete. Do + /* + * Clear tx_ready in case send isn't complete. Do * it BEFORE we call process_transmit, since * write_space can set it any time after we release - * kss_lock. */ + * kss_lock. + */ conn->ksnc_tx_ready = 0; spin_unlock_bh(&sched->kss_lock); if (!list_empty(&zlist)) { - /* free zombie noop txs, it's fast because - * noop txs are just put in freelist */ + /* + * free zombie noop txs, it's fast because + * noop txs are just put in freelist + */ ksocknal_txlist_done(NULL, &zlist, 0); } @@ -1508,8 +1539,10 @@ int ksocknal_scheduler(void *arg) } if (rc == -ENOMEM) { - /* Do nothing; after a short timeout, this - * conn will be reposted on kss_tx_conns. */ + /* + * Do nothing; after a short timeout, this + * conn will be reposted on kss_tx_conns. + */ } else if (conn->ksnc_tx_ready && !list_empty(&conn->ksnc_tx_queue)) { /* reschedule for tx */ @@ -1850,8 +1883,10 @@ ksocknal_connect (ksock_route_t *route) for (;;) { wanted = ksocknal_route_mask() & ~route->ksnr_connected; - /* stop connecting if peer/route got closed under me, or - * route got connected while queued */ + /* + * stop connecting if peer/route got closed under me, or + * route got connected while queued + */ if (peer->ksnp_closing || route->ksnr_deleted || wanted == 0) { retry_later = 0; @@ -1904,8 +1939,10 @@ ksocknal_connect (ksock_route_t *route) goto failed; } - /* A +ve RC means I have to retry because I lost the connection - * race or I have to renegotiate protocol version */ + /* + * A +ve RC means I have to retry because I lost the connection + * race or I have to renegotiate protocol version + */ retry_later = (rc != 0); if (retry_later) CDEBUG(D_NET, "peer %s: conn race, retry later.\n", @@ -1918,15 +1955,18 @@ ksocknal_connect (ksock_route_t *route) route->ksnr_connecting = 0; if (retry_later) { - /* re-queue for attention; this frees me up to handle - * the peer's incoming connection request */ - + /* + * re-queue for attention; this frees me up to handle + * the peer's incoming connection request + */ if (rc == EALREADY || (rc == 0 && peer->ksnp_accepting > 0)) { - /* We want to introduce a delay before next + /* + * We want to introduce a delay before next * attempt to connect if we lost conn race, * but the race is resolved quickly usually, - * so min_reconnectms should be good heuristic */ + * so min_reconnectms should be good heuristic + */ route->ksnr_retry_interval = cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms)/1000; route->ksnr_timeout = cfs_time_add(cfs_time_current(), @@ -1963,16 +2003,20 @@ ksocknal_connect (ksock_route_t *route) ksocknal_find_connecting_route_locked(peer) == NULL) { ksock_conn_t *conn; - /* ksnp_tx_queue is queued on a conn on successful - * connection for V1.x and V2.x */ + /* + * ksnp_tx_queue is queued on a conn on successful + * connection for V1.x and V2.x + */ if (!list_empty (&peer->ksnp_conns)) { conn = list_entry(peer->ksnp_conns.next, ksock_conn_t, ksnc_list); LASSERT (conn->ksnc_proto == &ksocknal_protocol_v3x); } - /* take all the blocked packets while I've got the lock and - * complete below... */ + /* + * take all the blocked packets while I've got the lock and + * complete below... + */ list_splice_init(&peer->ksnp_tx_queue, &zombies); } @@ -2011,8 +2055,10 @@ ksocknal_connd_check_start(time64_t sec, long *timeout) if (total >= *ksocknal_tunables.ksnd_nconnds_max || total > ksocknal_data.ksnd_connd_connecting + SOCKNAL_CONND_RESV) { - /* can't create more connd, or still have enough - * threads to handle more connecting */ + /* + * can't create more connd, or still have enough + * threads to handle more connecting + */ return 0; } @@ -2093,8 +2139,10 @@ ksocknal_connd_check_stop(time64_t sec, long *timeout) ksocknal_data.ksnd_connd_connecting + SOCKNAL_CONND_RESV; } -/* Go through connd_routes queue looking for a route that we can process - * right now, @timeout_p can be updated if we need to come back later */ +/* + * Go through connd_routes queue looking for a route that we can process + * right now, @timeout_p can be updated if we need to come back later + */ static ksock_route_t * ksocknal_connd_get_route_locked(signed long *timeout_p) { @@ -2172,9 +2220,11 @@ ksocknal_connd (void *arg) spin_lock_bh(connd_lock); } - /* Only handle an outgoing connection request if there + /* + * Only handle an outgoing connection request if there * is a thread left to handle incoming connections and - * create new connd */ + * create new connd + */ if (ksocknal_data.ksnd_connd_connecting + SOCKNAL_CONND_RESV < ksocknal_data.ksnd_connd_running) { route = ksocknal_connd_get_route_locked(&timeout); @@ -2245,8 +2295,10 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer) /* Don't need the {get,put}connsock dance to deref ksnc_sock */ LASSERT(!conn->ksnc_closing); - /* SOCK_ERROR will reset error code of socket in - * some platform (like Darwin8.x) */ + /* + * SOCK_ERROR will reset error code of socket in + * some platform (like Darwin8.x) + */ error = conn->ksnc_sock->sk->sk_err; if (error != 0) { ksocknal_conn_addref(conn); @@ -2295,8 +2347,10 @@ ksocknal_find_timed_out_conn (ksock_peer_t *peer) conn->ksnc_sock->sk->sk_wmem_queued != 0) && cfs_time_aftereq(cfs_time_current(), conn->ksnc_tx_deadline)) { - /* Timed out messages queued for sending or - * buffered in the socket's send buffer */ + /* + * Timed out messages queued for sending or + * buffered in the socket's send buffer + */ ksocknal_conn_addref(conn); CNETERR("Timeout sending data to %s (%pI4h:%d) the network or that node may be down.\n", libcfs_id2str(peer->ksnp_id), @@ -2357,8 +2411,10 @@ ksocknal_send_keepalive_locked(ksock_peer_t *peer) if (time_before(cfs_time_current(), peer->ksnp_send_keepalive)) return 0; - /* retry 10 secs later, so we wouldn't put pressure - * on this peer if we failed to send keepalive this time */ + /* + * retry 10 secs later, so we wouldn't put pressure + * on this peer if we failed to send keepalive this time + */ peer->ksnp_send_keepalive = cfs_time_shift(10); conn = ksocknal_find_conn_locked(peer, NULL, 1); @@ -2404,9 +2460,11 @@ ksocknal_check_peer_timeouts (int idx) ksock_tx_t *tx; again: - /* NB. We expect to have a look at all the peers and not find any + /* + * NB. We expect to have a look at all the peers and not find any * connections to time out, so we just use a shared lock while we - * take a look... */ + * take a look... + */ read_lock(&ksocknal_data.ksnd_global_lock); list_for_each_entry(peer, peers, ksnp_list) { @@ -2426,15 +2484,19 @@ ksocknal_check_peer_timeouts (int idx) ksocknal_close_conn_and_siblings (conn, -ETIMEDOUT); - /* NB we won't find this one again, but we can't + /* + * NB we won't find this one again, but we can't * just proceed with the next peer, since we dropped - * ksnd_global_lock and it might be dead already! */ + * ksnd_global_lock and it might be dead already! + */ ksocknal_conn_decref(conn); goto again; } - /* we can't process stale txs right here because we're - * holding only shared lock */ + /* + * we can't process stale txs right here because we're + * holding only shared lock + */ if (!list_empty (&peer->ksnp_tx_queue)) { ksock_tx_t *tx = list_entry (peer->ksnp_tx_queue.next, @@ -2581,13 +2643,14 @@ ksocknal_reaper (void *arg) const int p = 1; int chunk = ksocknal_data.ksnd_peer_hash_size; - /* Time to check for timeouts on a few more peers: I do + /* + * Time to check for timeouts on a few more peers: I do * checks every 'p' seconds on a proportion of the peer * table and I need to check every connection 'n' times * within a timeout interval, to ensure I detect a * timeout on any connection within (n+1)/n times the - * timeout interval. */ - + * timeout interval. + */ if (*ksocknal_tunables.ksnd_timeout > n * p) chunk = (chunk * n * p) / *ksocknal_tunables.ksnd_timeout; @@ -2604,9 +2667,11 @@ ksocknal_reaper (void *arg) } if (nenomem_conns != 0) { - /* Reduce my timeout if I rescheduled ENOMEM conns. + /* + * Reduce my timeout if I rescheduled ENOMEM conns. * This also prevents me getting woken immediately - * if any go back on my enomem list. */ + * if any go back on my enomem list. + */ timeout = SOCKNAL_ENOMEM_RETRY; } ksocknal_data.ksnd_reaper_waketime = diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index cf8e43bd3c03..f0edf3071c20 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -67,8 +67,10 @@ ksocknal_lib_zc_capable(ksock_conn_t *conn) if (conn->ksnc_proto == &ksocknal_protocol_v1x) return 0; - /* ZC if the socket supports scatter/gather and doesn't need software - * checksums */ + /* + * ZC if the socket supports scatter/gather and doesn't need software + * checksums + */ return ((caps & NETIF_F_SG) != 0 && (caps & NETIF_F_CSUM_MASK) != 0); } @@ -85,9 +87,10 @@ ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx) tx->tx_msg.ksm_csum == 0) /* not checksummed */ ksocknal_lib_csum_tx(tx); - /* NB we can't trust socket ops to either consume our iovs - * or leave them alone. */ - + /* + * NB we can't trust socket ops to either consume our iovs + * or leave them alone. + */ { #if SOCKNAL_SINGLE_FRAG_TX struct kvec scratch; @@ -125,8 +128,10 @@ ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) /* Not NOOP message */ LASSERT(tx->tx_lnetmsg != NULL); - /* NB we can't trust socket ops to either consume our iovs - * or leave them alone. */ + /* + * NB we can't trust socket ops to either consume our iovs + * or leave them alone. + */ if (tx->tx_msg.ksm_zc_cookies[0] != 0) { /* Zero copy is enabled */ struct sock *sk = sock->sk; @@ -187,11 +192,12 @@ ksocknal_lib_eager_ack(ksock_conn_t *conn) int opt = 1; struct socket *sock = conn->ksnc_sock; - /* Remind the socket to ACK eagerly. If I don't, the socket might + /* + * Remind the socket to ACK eagerly. If I don't, the socket might * think I'm about to send something it could piggy-back the ACK * on, introducing delay in completing zero-copy sends in my - * peer. */ - + * peer. + */ kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK, (char *)&opt, sizeof(opt)); } @@ -218,8 +224,10 @@ ksocknal_lib_recv_iov(ksock_conn_t *conn) int sum; __u32 saved_csum; - /* NB we can't trust socket ops to either consume our iovs - * or leave them alone. */ + /* + * NB we can't trust socket ops to either consume our iovs + * or leave them alone. + */ LASSERT(niov > 0); for (nob = i = 0; i < niov; i++) { @@ -329,8 +337,10 @@ ksocknal_lib_recv_kiov(ksock_conn_t *conn) int fragnob; int n; - /* NB we can't trust socket ops to either consume our iovs - * or leave them alone. */ + /* + * NB we can't trust socket ops to either consume our iovs + * or leave them alone. + */ addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages); if (addr != NULL) { nob = scratchiov[0].iov_len; @@ -354,10 +364,12 @@ ksocknal_lib_recv_kiov(ksock_conn_t *conn) for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); - /* Dang! have to kmap again because I have nowhere to + /* + * Dang! have to kmap again because I have nowhere to * stash the mapped address. But by doing it while the * page is still mapped, the kernel just bumps the map - * count and returns me the address it stashed. */ + * count and returns me the address it stashed. + */ base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset; fragnob = kiov[i].kiov_len; if (fragnob > sum) @@ -463,9 +475,10 @@ ksocknal_lib_setup_sock(struct socket *sock) sock->sk->sk_allocation = GFP_NOFS; - /* Ensure this socket aborts active sends immediately when we close - * it. */ - + /* + * Ensure this socket aborts active sends immediately when we close + * it. + */ linger.l_onoff = 0; linger.l_linger = 0; @@ -637,10 +650,11 @@ ksocknal_write_space(struct sock *sk) if (wspace >= min_wpace) { /* got enough space */ ksocknal_write_callback(conn); - /* Clear SOCK_NOSPACE _after_ ksocknal_write_callback so the + /* + * Clear SOCK_NOSPACE _after_ ksocknal_write_callback so the * ENOMEM check in ksocknal_transmit is race-free (think about - * it). */ - + * it). + */ clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); } @@ -666,15 +680,19 @@ ksocknal_lib_set_callback(struct socket *sock, ksock_conn_t *conn) void ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn) { - /* Remove conn's network callbacks. + /* + * Remove conn's network callbacks. * NB I _have_ to restore the callback, rather than storing a noop, - * since the socket could survive past this module being unloaded!! */ + * since the socket could survive past this module being unloaded!! + */ sock->sk->sk_data_ready = conn->ksnc_saved_data_ready; sock->sk->sk_write_space = conn->ksnc_saved_write_space; - /* A callback could be in progress already; they hold a read lock + /* + * A callback could be in progress already; they hold a read lock * on ksnd_global_lock (to serialise with me) and NOOP if - * sk_user_data is NULL. */ + * sk_user_data is NULL. + */ sock->sk->sk_user_data = NULL; return ; @@ -691,14 +709,16 @@ ksocknal_lib_memory_pressure(ksock_conn_t *conn) if (!test_bit(SOCK_NOSPACE, &conn->ksnc_sock->flags) && !conn->ksnc_tx_ready) { - /* SOCK_NOSPACE is set when the socket fills + /* + * SOCK_NOSPACE is set when the socket fills * and cleared in the write_space callback * (which also sets ksnc_tx_ready). If * SOCK_NOSPACE and ksnc_tx_ready are BOTH * zero, I didn't fill the socket and * write_space won't reschedule me, so I * return -ENOMEM to get my caller to retry - * after a timeout */ + * after a timeout + */ rc = -ENOMEM; } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c index fdb2b23e2ef0..374ba6793784 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c @@ -41,8 +41,10 @@ static int peer_timeout = 180; module_param(peer_timeout, int, 0444); MODULE_PARM_DESC(peer_timeout, "Seconds without aliveness news to declare peer dead (<=0 to disable)"); -/* Number of daemons in each thread pool which is percpt, - * we will estimate reasonable value based on CPUs if it's not set. */ +/* + * Number of daemons in each thread pool which is percpt, + * we will estimate reasonable value based on CPUs if it's not set. + */ static unsigned int nscheds; module_param(nscheds, int, 0444); MODULE_PARM_DESC(nscheds, "# scheduler daemons in each pool while starting"); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index 986bce4c9f3b..82ac02c7fc11 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -468,8 +468,10 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) hmv = (lnet_magicversion_t *)&hdr->dest_nid; - /* Re-organize V2.x message header to V1.x (lnet_hdr_t) - * header and send out */ + /* + * Re-organize V2.x message header to V1.x (lnet_hdr_t) + * header and send out + */ hmv->magic = cpu_to_le32 (LNET_PROTO_TCP_MAGIC); hmv->version_major = cpu_to_le16 (KSOCK_PROTO_V1_MAJOR); hmv->version_minor = cpu_to_le16 (KSOCK_PROTO_V1_MINOR); diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index fed57d90028d..5260de24d6a5 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -78,9 +78,11 @@ static char *accept_type; static int lnet_acceptor_get_tunables(void) { - /* Userland acceptor uses 'accept_type' instead of 'accept', due to + /* + * Userland acceptor uses 'accept_type' instead of 'accept', due to * conflict with 'accept(2)', but kernel acceptor still uses 'accept' - * for compatibility. Hence the trick. */ + * for compatibility. Hence the trick. + */ accept_type = accept; return 0; } @@ -223,11 +225,12 @@ lnet_accept(struct socket *sock, __u32 magic) if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) { if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) { - /* future version compatibility! + /* + * future version compatibility! * When LNET unifies protocols over all LNDs, the first - * thing sent will be a version query. I send back - * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" */ - + * thing sent will be a version query. I send back + * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" + */ memset(&cr, 0, sizeof(cr)); cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC; cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; @@ -264,10 +267,12 @@ lnet_accept(struct socket *sock, __u32 magic) __swab32s(&cr.acr_version); if (cr.acr_version != LNET_PROTO_ACCEPTOR_VERSION) { - /* future version compatibility! + /* + * future version compatibility! * An acceptor-specific protocol rev will first send a version * query. I send back my current version to tell her I'm - * "old". */ + * "old". + */ int peer_version = cr.acr_version; memset(&cr, 0, sizeof(cr)); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index d33fbdf99505..79447bf82ec9 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -174,10 +174,12 @@ lnet_create_locks(void) static void lnet_assert_wire_constants(void) { - /* Wire protocol assertions generated by 'wirecheck' + /* + * Wire protocol assertions generated by 'wirecheck' * running on Linux robert.bartonsoftware.com 2.6.8-1.521 * #1 Mon Aug 16 09:01:18 EDT 2004 i686 athlon i386 GNU/Linux - * with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) */ + * with gcc version 3.3.3 20040412 (Red Hat Linux 3.3.3-7) + */ /* Constants... */ CLASSERT(LNET_PROTO_TCP_MAGIC == 0xeebc0ded); @@ -398,9 +400,11 @@ lnet_res_container_cleanup(struct lnet_res_container *rec) } if (count > 0) { - /* Found alive MD/ME/EQ, user really should unlink/free + /* + * Found alive MD/ME/EQ, user really should unlink/free * all of them before finalize LNet, but if someone didn't, - * we have to recycle garbage for him */ + * we have to recycle garbage for him + */ CERROR("%d active elements on exit of %s container\n", count, lnet_res_type2str(rec->rec_type)); } @@ -605,11 +609,12 @@ lnet_prepare(lnet_pid_t requested_pid) int lnet_unprepare(void) { - /* NB no LNET_LOCK since this is the last reference. All LND instances + /* + * NB no LNET_LOCK since this is the last reference. All LND instances * have shut down already, so it is safe to unlink and free all * descriptors, even those that appear committed to a network op (eg MD - * with non-zero pending count) */ - + * with non-zero pending count) + */ lnet_fail_nid(LNET_NID_ANY, 0); LASSERT(the_lnet.ln_refcount == 0); @@ -877,18 +882,24 @@ lnet_shutdown_lndnis(void) lnet_net_unlock(LNET_LOCK_EX); - /* Clear lazy portals and drop delayed messages which hold refs - * on their lnet_msg_t::msg_rxpeer */ + /* + * Clear lazy portals and drop delayed messages which hold refs + * on their lnet_msg_t::msg_rxpeer + */ for (i = 0; i < the_lnet.ln_nportals; i++) LNetClearLazyPortal(i); - /* Clear the peer table and wait for all peers to go (they hold refs on - * their NIs) */ + /* + * Clear the peer table and wait for all peers to go (they hold refs on + * their NIs) + */ lnet_peer_tables_cleanup(); lnet_net_lock(LNET_LOCK_EX); - /* Now wait for the NI's I just nuked to show up on ln_zombie_nis - * and shut them down in guaranteed thread context */ + /* + * Now wait for the NI's I just nuked to show up on ln_zombie_nis + * and shut them down in guaranteed thread context + */ i = 2; while (!list_empty(&the_lnet.ln_nis_zombie)) { int *ref; @@ -926,9 +937,10 @@ lnet_shutdown_lndnis(void) LASSERT(!in_interrupt()); (ni->ni_lnd->lnd_shutdown)(ni); - /* can't deref lnd anymore now; it might have unregistered - * itself... */ - + /* + * can't deref lnd anymore now; it might have unregistered + * itself... + */ if (!islo) CDEBUG(D_LNI, "Removed LNI %s\n", libcfs_nid2str(ni->ni_nid)); @@ -1139,9 +1151,11 @@ lnet_init(void) INIT_LIST_HEAD(&the_lnet.ln_rcd_zombie); INIT_LIST_HEAD(&the_lnet.ln_rcd_deathrow); - /* The hash table size is the number of bits it takes to express the set + /* + * The hash table size is the number of bits it takes to express the set * ln_num_routes, minus 1 (better to under estimate than over so we - * don't waste memory). */ + * don't waste memory). + */ if (rnet_htable_size <= 0) rnet_htable_size = LNET_REMOTE_NETS_HASH_DEFAULT; else if (rnet_htable_size > LNET_REMOTE_NETS_HASH_MAX) @@ -1149,9 +1163,11 @@ lnet_init(void) the_lnet.ln_remote_nets_hbits = max_t(int, 1, order_base_2(rnet_htable_size) - 1); - /* All LNDs apart from the LOLND are in separate modules. They + /* + * All LNDs apart from the LOLND are in separate modules. They * register themselves when their module loads, and unregister - * themselves when their module is unloaded. */ + * themselves when their module is unloaded. + */ lnet_register_lnd(&the_lolnd); return 0; } @@ -1244,8 +1260,10 @@ LNetNIInit(lnet_pid_t requested_pid) the_lnet.ln_refcount = 1; /* Now I may use my own API functions... */ - /* NB router checker needs the_lnet.ln_ping_info in - * lnet_router_checker -> lnet_update_ni_status_locked */ + /* + * NB router checker needs the_lnet.ln_ping_info in + * lnet_router_checker -> lnet_update_ni_status_locked + */ rc = lnet_ping_target_init(); if (rc != 0) goto failed3; @@ -1554,8 +1572,10 @@ lnet_ping_target_init(void) if (rc != 0) return rc; - /* We can have a tiny EQ since we only need to see the unlink event on - * teardown, which by definition is the last one! */ + /* + * We can have a tiny EQ since we only need to see the unlink event on + * teardown, which by definition is the last one! + */ rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &the_lnet.ln_ping_target_eq); if (rc != 0) { CERROR("Can't allocate ping EQ: %d\n", rc); diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index bfbc3136fd3b..e543cb4b11ec 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -75,18 +75,21 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); - /* We need count to be a power of 2 so that when eq_{enq,deq}_seq + /* + * We need count to be a power of 2 so that when eq_{enq,deq}_seq * overflow, they don't skip entries, so the queue has the same - * apparent capacity at all times */ - + * apparent capacity at all times + */ if (count) count = roundup_pow_of_two(count); if (callback != LNET_EQ_HANDLER_NONE && count != 0) CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count); - /* count can be 0 if only need callback, we can eliminate - * overhead of enqueue event */ + /* + * count can be 0 if only need callback, we can eliminate + * overhead of enqueue event + */ if (count == 0 && callback == LNET_EQ_HANDLER_NONE) return -EINVAL; @@ -98,8 +101,10 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, LIBCFS_ALLOC(eq->eq_events, count * sizeof(lnet_event_t)); if (eq->eq_events == NULL) goto failed; - /* NB allocator has set all event sequence numbers to 0, - * so all them should be earlier than eq_deq_seq */ + /* + * NB allocator has set all event sequence numbers to 0, + * so all them should be earlier than eq_deq_seq + */ } eq->eq_deq_seq = 1; @@ -114,8 +119,10 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, /* MUST hold both exclusive lnet_res_lock */ lnet_res_lock(LNET_LOCK_EX); - /* NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do - * both EQ lookup and poll event with only lnet_eq_wait_lock */ + /* + * NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do + * both EQ lookup and poll event with only lnet_eq_wait_lock + */ lnet_eq_wait_lock(); lnet_res_lh_initialize(&the_lnet.ln_eq_container, &eq->eq_lh); @@ -164,8 +171,10 @@ LNetEQFree(lnet_handle_eq_t eqh) LASSERT(the_lnet.ln_refcount > 0); lnet_res_lock(LNET_LOCK_EX); - /* NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do - * both EQ lookup and poll event with only lnet_eq_wait_lock */ + /* + * NB: hold lnet_eq_wait_lock for EQ link/unlink, so we can do + * both EQ lookup and poll event with only lnet_eq_wait_lock + */ lnet_eq_wait_lock(); eq = lnet_handle2eq(&eqh); @@ -256,8 +265,10 @@ lnet_eq_dequeue_event(lnet_eq_t *eq, lnet_event_t *ev) if (eq->eq_deq_seq == new_event->sequence) { rc = 1; } else { - /* don't complain with CERROR: some EQs are sized small - * anyway; if it's important, the caller should complain */ + /* + * don't complain with CERROR: some EQs are sized small + * anyway; if it's important, the caller should complain + */ CDEBUG(D_NET, "Event Queue Overflow: eq seq %lu ev seq %lu\n", eq->eq_deq_seq, new_event->sequence); rc = -EOVERFLOW; diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index b3d8364b07ba..fef517dcf92a 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -52,9 +52,11 @@ lnet_md_unlink(lnet_libmd_t *md) md->md_flags |= LNET_MD_FLAG_ZOMBIE; - /* Disassociate from ME (if any), + /* + * Disassociate from ME (if any), * and unlink it if it was created - * with LNET_UNLINK */ + * with LNET_UNLINK + */ if (me != NULL) { /* detach MD from portal */ lnet_ptl_detach_md(me, md); @@ -169,14 +171,18 @@ lnet_md_link(lnet_libmd_t *md, lnet_handle_eq_t eq_handle, int cpt) { struct lnet_res_container *container = the_lnet.ln_md_containers[cpt]; - /* NB we are passed an allocated, but inactive md. + /* + * NB we are passed an allocated, but inactive md. * if we return success, caller may lnet_md_unlink() it. * otherwise caller may only lnet_md_free() it. */ - /* This implementation doesn't know how to create START events or + /* + * This implementation doesn't know how to create START events or * disable END events. Best to LASSERT our caller is compliant so - * we find out quickly... */ - /* TODO - reevaluate what should be here in light of + * we find out quickly... + */ + /* + * TODO - reevaluate what should be here in light of * the removal of the start and end events * maybe there we shouldn't even allow LNET_EQ_NONE!) * LASSERT (eq == NULL); @@ -306,8 +312,10 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, if (rc != 0) goto failed; - /* attach this MD to portal of ME and check if it matches any - * blocked msgs on this portal */ + /* + * attach this MD to portal of ME and check if it matches any + * blocked msgs on this portal + */ lnet_ptl_attach_md(me, md, &matches, &drops); lnet_md2handle(handle, md); @@ -438,9 +446,11 @@ LNetMDUnlink(lnet_handle_md_t mdh) } md->md_flags |= LNET_MD_FLAG_ABORTED; - /* If the MD is busy, lnet_md_unlink just marks it for deletion, and + /* + * If the MD is busy, lnet_md_unlink just marks it for deletion, and * when the LND is done, the completion event flags that the MD was - * unlinked. Otherwise, we enqueue an event now... */ + * unlinked. Otherwise, we enqueue an event now... + */ if (md->md_eq != NULL && md->md_refcount == 0) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index fb8f7be043ec..0268ce5761da 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -119,9 +119,11 @@ fail_peer(lnet_nid_t nid, int outgoing) if (tp->tp_threshold == 0) { /* zombie entry */ if (outgoing) { - /* only cull zombies on outgoing tests, + /* + * only cull zombies on outgoing tests, * since we may be at interrupt priority on - * incoming messages. */ + * incoming messages. + */ list_del(&tp->tp_list); list_add(&tp->tp_list, &cull); } @@ -233,9 +235,11 @@ lnet_extract_iov(int dst_niov, struct kvec *dst, int src_niov, struct kvec *src, unsigned int offset, unsigned int len) { - /* Initialise 'dst' to the subset of 'src' starting at 'offset', + /* + * Initialise 'dst' to the subset of 'src' starting at 'offset', * for exactly 'len' bytes, and return the number of entries. - * NB not destructive to 'src' */ + * NB not destructive to 'src' + */ unsigned int frag_len; unsigned int niov; @@ -332,10 +336,11 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, saddr = ((char *)kmap(siov->kiov_page)) + siov->kiov_offset + soffset; - /* Vanishing risk of kmap deadlock when mapping 2 pages. + /* + * Vanishing risk of kmap deadlock when mapping 2 pages. * However in practice at least one of the kiovs will be mapped - * kernel pages and the map/unmap will be NOOPs */ - + * kernel pages and the map/unmap will be NOOPs + */ memcpy(daddr, saddr, this_nob); nob -= this_nob; @@ -514,9 +519,11 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, int src_niov, lnet_kiov_t *src, unsigned int offset, unsigned int len) { - /* Initialise 'dst' to the subset of 'src' starting at 'offset', + /* + * Initialise 'dst' to the subset of 'src' starting at 'offset', * for exactly 'len' bytes, and return the number of entries. - * NB not destructive to 'src' */ + * NB not destructive to 'src' + */ unsigned int frag_len; unsigned int niov; @@ -726,8 +733,10 @@ lnet_peer_is_alive(lnet_peer_t *lp, unsigned long now) return alive; } -/* NB: returns 1 when alive, 0 when dead, negative when error; - * may drop the lnet_net_lock */ +/* + * NB: returns 1 when alive, 0 when dead, negative when error; + * may drop the lnet_net_lock + */ static int lnet_peer_alive_locked(lnet_peer_t *lp) { @@ -739,8 +748,10 @@ lnet_peer_alive_locked(lnet_peer_t *lp) if (lnet_peer_is_alive(lp, now)) return 1; - /* Peer appears dead, but we should avoid frequent NI queries (at - * most once per lnet_queryinterval seconds). */ + /* + * Peer appears dead, but we should avoid frequent NI queries (at + * most once per lnet_queryinterval seconds). + */ if (lp->lp_last_query != 0) { static const int lnet_queryinterval = 1; @@ -888,9 +899,11 @@ lnet_msg2bufpool(lnet_msg_t *msg) static int lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) { - /* lnet_parse is going to lnet_net_unlock immediately after this, so it + /* + * lnet_parse is going to lnet_net_unlock immediately after this, so it * sets do_recv FALSE and I don't do the unlock/send/lock bit. I - * return EAGAIN if msg blocked and 0 if received or OK to receive */ + * return EAGAIN if msg blocked and 0 if received or OK to receive + */ lnet_peer_t *lp = msg->msg_rxpeer; lnet_rtrbufpool_t *rbp; lnet_rtrbuf_t *rb; @@ -1030,9 +1043,11 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) lnet_rtrbuf_t *rb; lnet_rtrbufpool_t *rbp; - /* NB If a msg ever blocks for a buffer in rbp_msgs, it stays + /* + * NB If a msg ever blocks for a buffer in rbp_msgs, it stays * there until it gets one allocated, or aborts the wait - * itself */ + * itself + */ LASSERT(msg->msg_kiov != NULL); rb = list_entry(msg->msg_kiov, lnet_rtrbuf_t, rb_kiov[0]); @@ -1127,9 +1142,10 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) struct lnet_peer *lp; int rc; - /* If @rtr_nid is not LNET_NID_ANY, return the gateway with - * rtr_nid nid, otherwise find the best gateway I can use */ - + /* + * If @rtr_nid is not LNET_NID_ANY, return the gateway with + * rtr_nid nid, otherwise find the best gateway I can use + */ rnet = lnet_find_net_locked(LNET_NIDNET(target)); if (rnet == NULL) return NULL; @@ -1168,9 +1184,11 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) lp_best = lp; } - /* set sequence number on the best router to the latest sequence + 1 + /* + * set sequence number on the best router to the latest sequence + 1 * so we can round-robin all routers, it's race and inaccurate but - * harmless and functional */ + * harmless and functional + */ if (rtr_best != NULL) rtr_best->lr_seq = rtr_last->lr_seq + 1; return lp_best; @@ -1187,9 +1205,11 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) int cpt2; int rc; - /* NB: rtr_nid is set to LNET_NID_ANY for all current use-cases, + /* + * NB: rtr_nid is set to LNET_NID_ANY for all current use-cases, * but we might want to use pre-determined router for ACK/REPLY - * in the future */ + * in the future + */ /* NB: ni != NULL == interface pre-determined (ACK/REPLY) */ LASSERT(msg->msg_txpeer == NULL); LASSERT(!msg->msg_sending); @@ -1283,10 +1303,12 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) return -EHOSTUNREACH; } - /* rtr_nid is LNET_NID_ANY or NID of pre-determined router, + /* + * rtr_nid is LNET_NID_ANY or NID of pre-determined router, * it's possible that rtr_nid isn't LNET_NID_ANY and lp isn't * pre-determined router, this can happen if router table - * was changed when we release the lock */ + * was changed when we release the lock + */ if (rtr_nid != lp->lp_nid) { cpt2 = lnet_cpt_of_nid_locked(lp->lp_nid); if (cpt2 != cpt) { @@ -1368,8 +1390,10 @@ lnet_recv_put(lnet_ni_t *ni, lnet_msg_t *msg) lnet_build_msg_event(msg, LNET_EVENT_PUT); - /* Must I ACK? If so I'll grab the ack_wmd out of the header and put - * it back into the ACK during lnet_finalize() */ + /* + * Must I ACK? If so I'll grab the ack_wmd out of the header and put + * it back into the ACK during lnet_finalize() + */ msg->msg_ack = (!lnet_is_wire_handle_none(&hdr->msg.put.ack_wmd) && (msg->msg_md->md_options & LNET_MD_ACK_DISABLE) == 0); @@ -1775,10 +1799,11 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, lnet_ni_unlock(ni); } - /* Regard a bad destination NID as a protocol error. Senders should + /* + * Regard a bad destination NID as a protocol error. Senders should * know what they're doing; if they don't they're misconfigured, buggy - * or malicious so we chop them off at the knees :) */ - + * or malicious so we chop them off at the knees :) + */ if (!for_me) { if (LNET_NIDNET(dest_nid) == LNET_NIDNET(ni->ni_nid)) { /* should have gone direct */ @@ -1790,8 +1815,10 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, } if (lnet_islocalnid(dest_nid)) { - /* dest is another local NI; sender should have used - * this node's NID on its own network */ + /* + * dest is another local NI; sender should have used + * this node's NID on its own network + */ CERROR("%s, src %s: Bad dest nid %s (it's my nid but on a different network)\n", libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), @@ -1816,9 +1843,10 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, } } - /* Message looks OK; we're not going to return an error, so we MUST - * call back lnd_recv() come what may... */ - + /* + * Message looks OK; we're not going to return an error, so we MUST + * call back lnd_recv() come what may... + */ if (!list_empty(&the_lnet.ln_test_peers) && /* normally we don't */ fail_peer(src_nid, 0)) { /* shall we now? */ CERROR("%s, src %s: Dropping %s to simulate failure\n", @@ -1962,10 +1990,11 @@ lnet_drop_delayed_msg_list(struct list_head *head, char *reason) msg->msg_hdr.msg.put.offset, msg->msg_hdr.payload_length, reason); - /* NB I can't drop msg's ref on msg_rxpeer until after I've + /* + * NB I can't drop msg's ref on msg_rxpeer until after I've * called lnet_drop_message(), so I just hang onto msg as well - * until that's done */ - + * until that's done + */ lnet_drop_message(msg->msg_rxpeer->lp_ni, msg->msg_rxpeer->lp_cpt, msg->msg_private, msg->msg_len); @@ -1988,9 +2017,10 @@ lnet_recv_delayed_msg_list(struct list_head *head) msg = list_entry(head->next, lnet_msg_t, msg_list); list_del(&msg->msg_list); - /* md won't disappear under me, since each msg - * holds a ref on it */ - + /* + * md won't disappear under me, since each msg + * holds a ref on it + */ id.nid = msg->msg_hdr.src_nid; id.pid = msg->msg_hdr.src_pid; @@ -2142,13 +2172,14 @@ EXPORT_SYMBOL(LNetPut); lnet_msg_t * lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) { - /* The LND can DMA direct to the GET md (i.e. no REPLY msg). This + /* + * The LND can DMA direct to the GET md (i.e. no REPLY msg). This * returns a msg for the LND to pass to lnet_finalize() when the sink * data has been received. * * CAVEAT EMPTOR: 'getmsg' is the original GET, which is freed when - * lnet_finalize() is called on it, so the LND must call this first */ - + * lnet_finalize() is called on it, so the LND must call this first + */ struct lnet_msg *msg = lnet_msg_alloc(); struct lnet_libmd *getmd = getmsg->msg_md; lnet_process_id_t peer_id = getmsg->msg_target; @@ -2219,14 +2250,18 @@ EXPORT_SYMBOL(lnet_create_reply_msg); void lnet_set_reply_msg_len(lnet_ni_t *ni, lnet_msg_t *reply, unsigned int len) { - /* Set the REPLY length, now the RDMA that elides the REPLY message has - * completed and I know it. */ + /* + * Set the REPLY length, now the RDMA that elides the REPLY message has + * completed and I know it. + */ LASSERT(reply != NULL); LASSERT(reply->msg_type == LNET_MSG_GET); LASSERT(reply->msg_ev.type == LNET_EVENT_REPLY); - /* NB I trusted my peer to RDMA. If she tells me she's written beyond - * the end of my buffer, I might as well be dead. */ + /* + * NB I trusted my peer to RDMA. If she tells me she's written beyond + * the end of my buffer, I might as well be dead. + */ LASSERT(len <= reply->msg_ev.mlength); reply->msg_ev.mlength = len; @@ -2358,11 +2393,12 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) __u32 order = 2; struct list_head *rn_list; - /* if !local_nid_dist_zero, I don't return a distance of 0 ever + /* + * if !local_nid_dist_zero, I don't return a distance of 0 ever * (when lustre sees a distance of 0, it substitutes 0@lo), so I * keep order 0 free for 0@lo and order 1 free for a local NID - * match */ - + * match + */ LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 43977e8dffbb..62717ee8c16b 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -203,8 +203,10 @@ lnet_msg_decommit_tx(lnet_msg_t *msg, int status) case LNET_EVENT_GET: LASSERT(msg->msg_rx_committed); - /* overwritten while sending reply, we should never be - * here for optimized GET */ + /* + * overwritten while sending reply, we should never be + * here for optimized GET + */ LASSERT(msg->msg_type == LNET_MSG_REPLY); msg->msg_type = LNET_MSG_GET; /* fix type */ break; @@ -240,10 +242,12 @@ lnet_msg_decommit_rx(lnet_msg_t *msg, int status) break; case LNET_EVENT_GET: - /* type is "REPLY" if it's an optimized GET on passive side, + /* + * type is "REPLY" if it's an optimized GET on passive side, * because optimized GET will never be committed for sending, * so message type wouldn't be changed back to "GET" by - * lnet_msg_decommit_tx(), see details in lnet_parse_get() */ + * lnet_msg_decommit_tx(), see details in lnet_parse_get() + */ LASSERT(msg->msg_type == LNET_MSG_REPLY || msg->msg_type == LNET_MSG_GET); counters->send_length += msg->msg_wanted; @@ -254,8 +258,10 @@ lnet_msg_decommit_rx(lnet_msg_t *msg, int status) break; case LNET_EVENT_REPLY: - /* type is "GET" if it's an optimized GET on active side, - * see details in lnet_create_reply_msg() */ + /* + * type is "GET" if it's an optimized GET on active side, + * see details in lnet_create_reply_msg() + */ LASSERT(msg->msg_type == LNET_MSG_GET || msg->msg_type == LNET_MSG_REPLY); break; @@ -309,10 +315,12 @@ lnet_msg_attach_md(lnet_msg_t *msg, lnet_libmd_t *md, unsigned int offset, unsigned int mlen) { /* NB: @offset and @len are only useful for receiving */ - /* Here, we attach the MD on lnet_msg and mark it busy and + /* + * Here, we attach the MD on lnet_msg and mark it busy and * decrementing its threshold. Come what may, the lnet_msg "owns" * the MD until a call to lnet_msg_detach_md or lnet_finalize() - * signals completion. */ + * signals completion. + */ LASSERT(!msg->msg_routing); msg->msg_md = md; @@ -383,8 +391,10 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) msg->msg_hdr.msg.ack.match_bits = msg->msg_ev.match_bits; msg->msg_hdr.msg.ack.mlength = cpu_to_le32(msg->msg_ev.mlength); - /* NB: we probably want to use NID of msg::msg_from as 3rd - * parameter (router NID) if it's routed message */ + /* + * NB: we probably want to use NID of msg::msg_from as 3rd + * parameter (router NID) if it's routed message + */ rc = lnet_send(msg->msg_ev.target.nid, msg, LNET_NID_ANY); lnet_net_lock(cpt); @@ -491,9 +501,10 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) container = the_lnet.ln_msg_containers[cpt]; list_add_tail(&msg->msg_list, &container->msc_finalizing); - /* Recursion breaker. Don't complete the message here if I am (or - * enough other threads are) already completing messages */ - + /* + * Recursion breaker. Don't complete the message here if I am (or + * enough other threads are) already completing messages + */ my_slot = -1; for (i = 0; i < container->msc_nfinalizers; i++) { if (container->msc_finalizers[i] == current) @@ -516,8 +527,10 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) list_del(&msg->msg_list); - /* NB drops and regains the lnet lock if it actually does - * anything, so my finalizing friends can chomp along too */ + /* + * NB drops and regains the lnet lock if it actually does + * anything, so my finalizing friends can chomp along too + */ rc = lnet_complete_msg_locked(msg, cpt); if (rc != 0) break; diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index bd7b071b2873..3a82fb6b55e5 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -139,8 +139,10 @@ static int lnet_try_match_md(lnet_libmd_t *md, struct lnet_match_info *info, struct lnet_msg *msg) { - /* ALWAYS called holding the lnet_res_lock, and can't lnet_res_unlock; - * lnet_match_blocked_msg() relies on this to avoid races */ + /* + * ALWAYS called holding the lnet_res_lock, and can't lnet_res_unlock; + * lnet_match_blocked_msg() relies on this to avoid races + */ unsigned int offset; unsigned int mlength; lnet_me_t *me = md->md_me; @@ -203,9 +205,11 @@ lnet_try_match_md(lnet_libmd_t *md, if (!lnet_md_exhausted(md)) return LNET_MATCHMD_OK; - /* Auto-unlink NOW, so the ME gets unlinked if required. + /* + * Auto-unlink NOW, so the ME gets unlinked if required. * We bumped md->md_refcount above so the MD just gets flagged - * for unlink when it is finalized. */ + * for unlink when it is finalized. + */ if ((md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) != 0) lnet_md_unlink(md); @@ -248,8 +252,10 @@ lnet_mt_of_attach(unsigned int index, lnet_process_id_t id, return NULL; case LNET_INS_BEFORE: case LNET_INS_AFTER: - /* posted by no affinity thread, always hash to specific - * match-table to avoid buffer stealing which is heavy */ + /* + * posted by no affinity thread, always hash to specific + * match-table to avoid buffer stealing which is heavy + */ return ptl->ptl_mtables[ptl->ptl_index % LNET_CPT_NUMBER]; case LNET_INS_LOCAL: /* posted by cpu-affinity thread */ @@ -299,9 +305,11 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) nmaps = ptl->ptl_mt_nmaps; /* map to an active mtable to avoid heavy "stealing" */ if (nmaps != 0) { - /* NB: there is possibility that ptl_mt_maps is being + /* + * NB: there is possibility that ptl_mt_maps is being * changed because we are not under protection of - * lnet_ptl_lock, but it shouldn't hurt anything */ + * lnet_ptl_lock, but it shouldn't hurt anything + */ cpt = ptl->ptl_mt_maps[rotor % nmaps]; } } @@ -401,8 +409,10 @@ lnet_mt_match_md(struct lnet_match_table *mtable, exhausted = 0; /* mlist is not empty */ if ((rc & LNET_MATCHMD_FINISH) != 0) { - /* don't return EXHAUSTED bit because we don't know - * whether the mlist is empty or not */ + /* + * don't return EXHAUSTED bit because we don't know + * whether the mlist is empty or not + */ return rc & ~LNET_MATCHMD_EXHAUSTED; } } @@ -430,8 +440,10 @@ lnet_ptl_match_early(struct lnet_portal *ptl, struct lnet_msg *msg) { int rc; - /* message arrived before any buffer posting on this portal, - * simply delay or drop this message */ + /* + * message arrived before any buffer posting on this portal, + * simply delay or drop this message + */ if (likely(lnet_ptl_is_wildcard(ptl) || lnet_ptl_is_unique(ptl))) return 0; @@ -465,9 +477,11 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, int rc = 0; int i; - /* steal buffer from other CPTs, and delay it if nothing to steal, + /* + * steal buffer from other CPTs, and delay it if nothing to steal, * this function is more expensive than a regular match, but we - * don't expect it can happen a lot */ + * don't expect it can happen a lot + */ LASSERT(lnet_ptl_is_wildcard(ptl)); for (i = 0; i < LNET_CPT_NUMBER; i++) { @@ -498,8 +512,10 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, list_del_init(&msg->msg_list); } else { - /* could be matched by lnet_ptl_attach_md() - * which is called by another thread */ + /* + * could be matched by lnet_ptl_attach_md() + * which is called by another thread + */ rc = msg->msg_md == NULL ? LNET_MATCHMD_DROP : LNET_MATCHMD_OK; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 589ecc84d1b8..c3835958b318 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -258,9 +258,10 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) struct timeval tv; LASSERT(nob > 0); - /* Caller may pass a zero timeout if she thinks the socket buffer is - * empty enough to take the whole message immediately */ - + /* + * Caller may pass a zero timeout if she thinks the socket buffer is + * empty enough to take the whole message immediately + */ for (;;) { struct kvec iov = { .iov_base = buffer, @@ -524,8 +525,10 @@ lnet_sock_accept(struct socket **newsockp, struct socket *sock) init_waitqueue_entry(&wait, current); - /* XXX this should add a ref to sock->ops->owner, if - * TCP could be a module */ + /* + * XXX this should add a ref to sock->ops->owner, if + * TCP could be a module + */ rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock); if (rc) { CERROR("Can't allocate socket\n"); @@ -578,10 +581,12 @@ lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, if (rc == 0) return 0; - /* EADDRNOTAVAIL probably means we're already connected to the same + /* + * EADDRNOTAVAIL probably means we're already connected to the same * peer/port on the same local port on a differently typed * connection. Let our caller retry with a different local - * port... */ + * port... + */ *fatal = !(rc == -EADDRNOTAVAIL); CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET, diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index c93c00752a4c..1e880336a63a 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -96,9 +96,11 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_data *data) return lnet_unconfigure(); default: - /* Passing LNET_PID_ANY only gives me a ref if the net is up + /* + * Passing LNET_PID_ANY only gives me a ref if the net is up * already; I'll need it to ensure the net can't go down while - * I'm called into it */ + * I'm called into it + */ rc = LNetNIInit(LNET_PID_ANY); if (rc >= 0) { rc = LNetCtl(cmd, data); @@ -127,8 +129,10 @@ init_lnet(void) LASSERT(rc == 0); if (config_on_load) { - /* Have to schedule a separate thread to avoid deadlocking - * in modload */ + /* + * Have to schedule a separate thread to avoid deadlocking + * in modload + */ (void) kthread_run(lnet_configure, NULL, "lnet_initd"); } diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index 80f585afa259..36577fed3a93 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -210,9 +210,11 @@ add_nidrange(const struct cfs_lstr *src, /* network name only, e.g. "elan" or "tcp" */ netnum = 0; else { - /* e.g. "elan25" or "tcp23", refuse to parse if + /* + * e.g. "elan25" or "tcp23", refuse to parse if * network name is not appended with decimal or - * hexadecimal number */ + * hexadecimal number + */ if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name), endlen, &netnum, 0, MAX_NUMERIC_VALUE)) return NULL; @@ -784,12 +786,14 @@ libcfs_ip_addr2str(__u32 addr, char *str, size_t size) (addr >> 8) & 0xff, addr & 0xff); } -/* CAVEAT EMPTOR XscanfX +/* + * CAVEAT EMPTOR XscanfX * I use "%n" at the end of a sscanf format to detect trailing junk. However * sscanf may return immediately if it sees the terminating '0' in a string, so * I initialise the %n variable to the expected length. If sscanf sets it; * fine, if it doesn't, then the scan ended at the end of the string, which is - * fine too :) */ + * fine too :) + */ static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) { diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index f5faa414d250..b6b2ed8f7003 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -61,8 +61,10 @@ lnet_peer_buffer_credits(lnet_ni_t *ni) if (peer_buffer_credits > 0) return peer_buffer_credits; - /* As an approximation, allow this peer the same number of router - * buffers as it is allowed outstanding sends */ + /* + * As an approximation, allow this peer the same number of router + * buffers as it is allowed outstanding sends + */ return ni->ni_peertxcredits; } @@ -131,10 +133,11 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) int alive; int notifylnd; - /* Notify only in 1 thread at any time to ensure ordered notification. + /* + * Notify only in 1 thread at any time to ensure ordered notification. * NB individual events can be missed; the only guarantee is that you - * always get the most recent news */ - + * always get the most recent news + */ if (lp->lp_notifying || ni == NULL) return; @@ -150,9 +153,10 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) if (notifylnd && ni->ni_lnd->lnd_notify != NULL) { lnet_net_unlock(lp->lp_cpt); - /* A new notification could happen now; I'll handle it - * when control returns to me */ - + /* + * A new notification could happen now; I'll handle it + * when control returns to me + */ (ni->ni_lnd->lnd_notify)(ni, lp->lp_nid, alive); lnet_net_lock(lp->lp_cpt); @@ -245,8 +249,10 @@ static void lnet_shuffle_seed(void) cfs_get_random_bytes(seed, sizeof(seed)); - /* Nodes with small feet have little entropy - * the NID for this node gives the most entropy in the low bits */ + /* + * Nodes with small feet have little entropy + * the NID for this node gives the most entropy in the low bits + */ list_for_each(tmp, &the_lnet.ln_nis) { ni = list_entry(tmp, lnet_ni_t, ni_list); lnd_type = LNET_NETTYP(LNET_NIDNET(ni->ni_nid)); @@ -472,9 +478,10 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid) CDEBUG(D_NET, "Del route: net %s : gw %s\n", libcfs_net2str(net), libcfs_nid2str(gw_nid)); - /* NB Caller may specify either all routes via the given gateway - * or a specific route entry actual NIDs) */ - + /* + * NB Caller may specify either all routes via the given gateway + * or a specific route entry actual NIDs) + */ lnet_net_lock(LNET_LOCK_EX); if (net == LNET_NIDNET(LNET_NID_ANY)) rn_list = &the_lnet.ln_remote_nets_hash[0]; @@ -663,8 +670,10 @@ lnet_parse_rc_info(lnet_rc_data_t *rcd) up = 1; break; } - /* ptl NIs are considered down only when - * they're all down */ + /* + * ptl NIs are considered down only when + * they're all down + */ if (LNET_NETTYP(LNET_NIDNET(nid)) == PTLLND) ptl_status = LNET_NI_STATUS_UP; continue; @@ -703,9 +712,11 @@ lnet_router_checker_event(lnet_event_t *event) lp = rcd->rcd_gateway; LASSERT(lp != NULL); - /* NB: it's called with holding lnet_res_lock, we have a few - * places need to hold both locks at the same time, please take - * care of lock ordering */ + /* + * NB: it's called with holding lnet_res_lock, we have a few + * places need to hold both locks at the same time, please take + * care of lock ordering + */ lnet_net_lock(lp->lp_cpt); if (!lnet_isrouter(lp) || lp->lp_rcd != rcd) { /* ignore if no longer a router or rcd is replaced */ @@ -719,17 +730,20 @@ lnet_router_checker_event(lnet_event_t *event) } /* LNET_EVENT_REPLY */ - /* A successful REPLY means the router is up. If _any_ comms + /* + * A successful REPLY means the router is up. If _any_ comms * to the router fail I assume it's down (this will happen if * we ping alive routers to try to detect router death before - * apps get burned). */ - + * apps get burned). + */ lnet_notify_locked(lp, 1, (event->status == 0), cfs_time_current()); - /* The router checker will wake up very shortly and do the + + /* + * The router checker will wake up very shortly and do the * actual notification. * XXX If 'lp' stops being a router before then, it will still - * have the notification pending!!! */ - + * have the notification pending!!! + */ if (avoid_asym_router_failure && event->status == 0) lnet_parse_rc_info(rcd); @@ -816,8 +830,10 @@ lnet_update_ni_status_locked(void) if (ni->ni_status->ns_status != LNET_NI_STATUS_DOWN) { CDEBUG(D_NET, "NI(%s:%d) status changed to down\n", libcfs_nid2str(ni->ni_nid), timeout); - /* NB: so far, this is the only place to set - * NI status to "down" */ + /* + * NB: so far, this is the only place to set + * NI status to "down" + */ ni->ni_status->ns_status = LNET_NI_STATUS_DOWN; } lnet_ni_unlock(ni); @@ -1018,8 +1034,10 @@ lnet_router_checker_start(void) return 0; sema_init(&the_lnet.ln_rc_signal, 0); - /* EQ size doesn't matter; the callback is guaranteed to get every - * event */ + /* + * EQ size doesn't matter; the callback is guaranteed to get every + * event + */ eqsz = 0; rc = LNetEQAlloc(eqsz, lnet_router_checker_event, &the_lnet.ln_rc_eqh); @@ -1042,9 +1060,11 @@ lnet_router_checker_start(void) } if (check_routers_before_use) { - /* Note that a helpful side-effect of pinging all known routers + /* + * Note that a helpful side-effect of pinging all known routers * at startup is that it makes them drop stale connections they - * may have to a previous instance of me. */ + * may have to a previous instance of me. + */ lnet_wait_known_routerstate(); } @@ -1199,9 +1219,11 @@ rescan: lnet_prune_rc_data(0); /* don't wait for UNLINK */ - /* Call schedule_timeout() here always adds 1 to load average + /* + * Call schedule_timeout() here always adds 1 to load average * because kernel counts # active tasks as nr_running - * + nr_uninterruptible. */ + * + nr_uninterruptible. + */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(cfs_time_seconds(1)); } @@ -1541,10 +1563,12 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) return 0; } - /* We can't fully trust LND on reporting exact peer last_alive + /* + * We can't fully trust LND on reporting exact peer last_alive * if he notifies us about dead peer. For example ksocklnd can * call us with when == _time_when_the_node_was_booted_ if - * no connections were successfully established */ + * no connections were successfully established + */ if (ni != NULL && !alive && when < lp->lp_last_alive) when = lp->lp_last_alive; diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 396c7c4e5c83..339c27667d2b 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -25,8 +25,10 @@ #include "../../include/linux/libcfs/libcfs.h" #include "../../include/linux/lnet/lib-lnet.h" -/* This is really lnet_proc.c. You might need to update sanity test 215 - * if any file format is changed. */ +/* + * This is really lnet_proc.c. You might need to update sanity test 215 + * if any file format is changed. + */ #define LNET_LOFFT_BITS (sizeof(loff_t) * 8) /* @@ -358,9 +360,11 @@ static int proc_lnet_routers(struct ctl_table *table, int write, if ((peer->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0) { list_for_each_entry(rtr, &peer->lp_routes, - lr_gwlist) { - /* downis on any route should be the - * number of downis on the gateway */ + lr_gwlist) { + /* + * downis on any route should be the + * number of downis on the gateway + */ if (rtr->lr_downis != 0) { down_ni = rtr->lr_downis; break; @@ -479,9 +483,11 @@ static int proc_lnet_peers(struct ctl_table *table, int write, if (skip == 0) { peer = lp; - /* minor optimization: start from idx+1 + /* + * minor optimization: start from idx+1 * on next iteration if we've just - * drained lp_hashlist */ + * drained lp_hashlist + */ if (lp->lp_hashlist.next == &ptable->pt_hash[hash]) { hoff = 1; @@ -710,8 +716,10 @@ static int proc_lnet_nis(struct ctl_table *table, int write, LNET_NI_STATUS_UP) ? "up" : "down"; lnet_ni_unlock(ni); - /* we actually output credits information for - * TX queue of each partition */ + /* + * we actually output credits information for + * TX queue of each partition + */ cfs_percpt_for_each(tq, i, ni->ni_tx_queues) { for (j = 0; ni->ni_cpts != NULL && j < ni->ni_ncpts; j++) { diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 1f04cc1fc31c..8b159b61e68f 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -86,15 +86,19 @@ brw_client_init(sfw_test_instance_t *tsi) opc = breq->blk_opc; flags = breq->blk_flags; npg = breq->blk_npg; - /* NB: this is not going to work for variable page size, - * but we have to keep it for compatibility */ + /* + * NB: this is not going to work for variable page size, + * 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; - /* I should never get this step if it's unknown feature - * because make_session will reject unknown feature */ + /* + * I should never get this step if it's unknown feature + * because make_session will reject unknown feature + */ LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); opc = breq->blk_opc; @@ -279,8 +283,10 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, } else { test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; - /* I should never get this step if it's unknown feature - * because make_session will reject unknown feature */ + /* + * I should never get this step if it's unknown feature + * because make_session will reject unknown feature + */ LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); opc = breq->blk_opc; diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 15a61ded6206..4f09b51ed026 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -60,8 +60,10 @@ lstcon_rpc_done(srpc_client_rpc_t *rpc) spin_lock(&rpc->crpc_lock); if (crpc->crp_trans == NULL) { - /* Orphan RPC is not in any transaction, - * I'm just a poor body and nobody loves me */ + /* + * Orphan RPC is not in any transaction, + * I'm just a poor body and nobody loves me + */ spin_unlock(&rpc->crpc_lock); /* release it */ @@ -241,8 +243,10 @@ lstcon_rpc_trans_prep(struct list_head *translist, if (translist != NULL) { list_for_each_entry(trans, translist, tas_link) { - /* Can't enqueue two private transaction on - * the same object */ + /* + * Can't enqueue two private transaction on + * the same object + */ if ((trans->tas_opc & transop) == LST_TRANS_PRIVATE) return -EPERM; } @@ -563,11 +567,12 @@ lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) continue; } - /* rpcs can be still not callbacked (even LNetMDUnlink is called) + /* + * 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 */ - + * in callback + */ LASSERT(crpc->crp_status != 0); crpc->crp_node = NULL; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 366211e02ed8..1cc703802d17 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -104,9 +104,11 @@ lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create) ndl->ndl_node->nd_timeout = 0; memset(&ndl->ndl_node->nd_ping, 0, sizeof(lstcon_rpc_t)); - /* queued in global hash & list, no refcount is taken by + /* + * queued in global hash & list, no refcount is taken by * global hash & list, if caller release his refcount, - * node will be released */ + * node will be released + */ list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]); list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list); @@ -601,8 +603,10 @@ lstcon_group_del(char *name) lstcon_rpc_trans_destroy(trans); lstcon_group_decref(grp); - /* -ref for session, it's destroyed, - * status can't be rolled back, destroy group anyway */ + /* + * -ref for session, it's destroyed, + * status can't be rolled back, destroy group anyway + */ lstcon_group_decref(grp); return rc; diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 1a2da7430190..1bf707bd4c81 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -386,8 +386,10 @@ sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) lnet_counters_get(&reply->str_lnet); srpc_get_counters(&reply->str_rpc); - /* send over the msecs since the session was started - - with 32 bits to send, this is ~49 days */ + /* + * send over the msecs since the session was started + * with 32 bits to send, this is ~49 days + */ cnt->running_ms = jiffies_to_msecs(jiffies - sn->sn_started); cnt->brw_errors = atomic_read(&sn->sn_brw_errors); cnt->ping_errors = atomic_read(&sn->sn_ping_errors); @@ -437,12 +439,14 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) } } - /* reject the request if it requires unknown features + /* + * 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 * 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. */ + * same feature mask. + */ if ((msg->msg_ses_feats & ~LST_FEATS_MASK) != 0) { reply->mksn_status = EPROTO; return 0; @@ -570,10 +574,12 @@ sfw_load_test(struct sfw_test_instance *tsi) if (rc != 0) { CWARN("Failed to reserve enough buffers: service %s, %d needed: %d\n", svc->sv_name, nbuf, rc); - /* NB: this error handler is not strictly correct, because + /* + * NB: this error handler is not strictly correct, because * it may release more buffers than already allocated, * but it doesn't matter because request portal should - * be lazy portal and will grow buffers if necessary. */ + * be lazy portal and will grow buffers if necessary. + */ srpc_service_remove_buffers(svc, nbuf); return -ENOMEM; } @@ -594,9 +600,11 @@ sfw_unload_test(struct sfw_test_instance *tsi) if (tsi->tsi_is_client) return; - /* shrink buffers, because request portal is lazy portal + /* + * shrink buffers, because request portal is lazy portal * which can grow buffers at runtime so we may leave - * some buffers behind, but never mind... */ + * some buffers behind, but never mind... + */ srpc_service_remove_buffers(tsc->tsc_srv_service, sfw_test_buffers(tsi)); return; @@ -1272,9 +1280,11 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) } } else if ((request->msg_ses_feats & ~LST_FEATS_MASK) != 0) { - /* NB: at this point, old version will ignore features and + /* + * NB: at this point, old version will ignore features and * create new session anyway, so console should be able - * to handle this */ + * to handle this + */ reply->msg_body.reply.status = EPROTO; goto out; } diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 2acf6ec717be..14f2024938ef 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -278,16 +278,20 @@ srpc_service_init(struct srpc_service *svc) scd->scd_ev.ev_data = scd; scd->scd_ev.ev_type = SRPC_REQUEST_RCVD; - /* NB: don't use lst_sched_serial for adding buffer, - * see details in srpc_service_add_buffers() */ + /* + * NB: don't use lst_sched_serial for adding buffer, + * see details in srpc_service_add_buffers() + */ swi_init_workitem(&scd->scd_buf_wi, scd, srpc_add_buffer, lst_sched_test[i]); if (i != 0 && srpc_serv_is_framework(svc)) { - /* NB: framework service only needs srpc_service_cd for + /* + * NB: framework service only needs srpc_service_cd for * one partition, but we allocate for all to make * it easier to implement, it will waste a little - * memory but nobody should care about this */ + * memory but nobody should care about this + */ continue; } @@ -414,9 +418,11 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, return -ENOMEM; } - /* this is kind of an abuse of the LNET_MD_OP_{PUT,GET} options. + /* + * this is kind of an abuse of the LNET_MD_OP_{PUT,GET} options. * they're only meaningful for MDs attached to an ME (i.e. passive - * buffers... */ + * buffers... + */ if ((options & LNET_MD_OP_PUT) != 0) { rc = LNetPut(self, *mdh, LNET_NOACK_REQ, peer, portal, matchbits, 0, 0); @@ -431,7 +437,8 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, ((options & LNET_MD_OP_PUT) != 0) ? "Put" : "Get", libcfs_id2str(peer), portal, matchbits, rc); - /* The forthcoming unlink event will complete this operation + /* + * The forthcoming unlink event will complete this operation * with failure, so fall through and return success here. */ rc = LNetMDUnlink(*mdh); @@ -476,10 +483,11 @@ srpc_service_post_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf) msg, sizeof(*msg), &buf->buf_mdh, &scd->scd_ev); - /* At this point, a RPC (new or delayed) may have arrived in + /* + * At this point, a RPC (new or delayed) may have arrived in * msg and its event handler has been called. So we must add - * buf to scd_buf_posted _before_ dropping scd_lock */ - + * buf to scd_buf_posted _before_ dropping scd_lock + */ spin_lock(&scd->scd_lock); if (rc == 0) { @@ -487,8 +495,10 @@ srpc_service_post_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf) return 0; spin_unlock(&scd->scd_lock); - /* srpc_shutdown_service might have tried to unlink me - * when my buf_mdh was still invalid */ + /* + * srpc_shutdown_service might have tried to unlink me + * when my buf_mdh was still invalid + */ LNetMDUnlink(buf->buf_mdh); spin_lock(&scd->scd_lock); return 0; @@ -514,9 +524,11 @@ srpc_add_buffer(struct swi_workitem *wi) struct srpc_buffer *buf; int rc = 0; - /* it's called by workitem scheduler threads, these threads + /* + * it's called by workitem scheduler threads, these threads * should have been set CPT affinity, so buffers will be posted - * on CPT local list of Portal */ + * on CPT local list of Portal + */ spin_lock(&scd->scd_lock); while (scd->scd_buf_adjust > 0 && @@ -732,9 +744,11 @@ srpc_abort_service(struct srpc_service *sv) cfs_percpt_for_each(scd, i, sv->sv_cpt_data) { spin_lock(&scd->scd_lock); - /* schedule in-flight RPCs to notice the abort, NB: + /* + * schedule in-flight RPCs to notice the abort, NB: * racing with incoming RPCs; complete fix should make test - * RPCs carry session ID in its headers */ + * RPCs carry session ID in its headers + */ list_for_each_entry(rpc, &scd->scd_rpc_active, srpc_list) { rpc->srpc_aborted = 1; swi_schedule_workitem(&rpc->srpc_wi); @@ -772,8 +786,10 @@ srpc_shutdown_service(srpc_service_t *sv) spin_unlock(&scd->scd_lock); - /* OK to traverse scd_buf_posted without lock, since no one - * touches scd_buf_posted now */ + /* + * OK to traverse scd_buf_posted without lock, since no one + * touches scd_buf_posted now + */ list_for_each_entry(buf, &scd->scd_buf_posted, buf_list) LNetMDUnlink(buf->buf_mdh); } @@ -915,8 +931,10 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) spin_lock(&scd->scd_lock); if (rpc->srpc_reqstbuf != NULL) { - /* NB might drop sv_lock in srpc_service_recycle_buffer, but - * sv won't go away for scd_rpc_active must not be empty */ + /* + * NB might drop sv_lock in srpc_service_recycle_buffer, but + * sv won't go away for scd_rpc_active must not be empty + */ srpc_service_recycle_buffer(scd, rpc->srpc_reqstbuf); rpc->srpc_reqstbuf = NULL; } @@ -1102,7 +1120,8 @@ srpc_add_client_rpc_timer(srpc_client_rpc_t *rpc) * Called with rpc->crpc_lock held. * * Upon exit the RPC expiry timer is not queued and the handler is not - * running on any CPU. */ + * running on any CPU. + */ static void srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc) { @@ -1210,9 +1229,11 @@ srpc_send_rpc(swi_workitem_t *wi) break; case SWI_STATE_REQUEST_SUBMITTED: - /* CAVEAT EMPTOR: rqtev, rpyev, and bulkev may come in any + /* + * CAVEAT EMPTOR: rqtev, rpyev, and bulkev may come in any * order; however, they're processed in a strict order: - * rqt, rpy, and bulk. */ + * rqt, rpy, and bulk. + */ if (!rpc->crpc_reqstev.ev_fired) break; @@ -1259,10 +1280,12 @@ srpc_send_rpc(swi_workitem_t *wi) rc = do_bulk ? rpc->crpc_bulkev.ev_status : 0; - /* Bulk buffer was unlinked due to remote error. Clear error + /* + * Bulk buffer was unlinked due to remote error. Clear error * since reply buffer still contains valid data. * NB rpc->crpc_done shouldn't look into bulk data in case of - * remote error. */ + * remote error. + */ if (do_bulk && rpc->crpc_bulkev.ev_lnet == LNET_EVENT_UNLINK && rpc->crpc_status == 0 && reply->msg_body.reply.status != 0) rc = 0; @@ -1364,8 +1387,10 @@ srpc_send_reply(struct srpc_server_rpc *rpc) spin_lock(&scd->scd_lock); if (!sv->sv_shuttingdown && !srpc_serv_is_framework(sv)) { - /* Repost buffer before replying since test client - * might send me another RPC once it gets the reply */ + /* + * Repost buffer before replying since test client + * might send me another RPC once it gets the reply + */ if (srpc_service_post_buffer(scd, buffer) != 0) CWARN("Failed to repost %s buffer\n", sv->sv_name); rpc->srpc_reqstbuf = NULL; @@ -1472,8 +1497,10 @@ srpc_lnet_ev_handler(lnet_event_t *ev) scd->scd_buf_nposted--; if (sv->sv_shuttingdown) { - /* Leave buffer on scd->scd_buf_nposted since - * srpc_finish_service needs to traverse it. */ + /* + * Leave buffer on scd->scd_buf_nposted since + * srpc_finish_service needs to traverse it. + */ spin_unlock(&scd->scd_lock); break; } @@ -1507,9 +1534,11 @@ srpc_lnet_ev_handler(lnet_event_t *ev) ev->status, ev->mlength, msg->msg_type, msg->msg_magic); - /* NB can't call srpc_service_recycle_buffer here since + /* + * NB can't call srpc_service_recycle_buffer here since * it may call LNetM[DE]Attach. The invalid magic tells - * srpc_handle_rpc to drop this RPC */ + * srpc_handle_rpc to drop this RPC + */ msg->msg_magic = 0; } diff --git a/drivers/staging/lustre/lnet/selftest/rpc.h b/drivers/staging/lustre/lnet/selftest/rpc.h index 6b4a32a90857..9dfb3662a2eb 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.h +++ b/drivers/staging/lustre/lnet/selftest/rpc.h @@ -281,8 +281,10 @@ srpc_unpack_msg_hdr(srpc_msg_t *msg) if (msg->msg_magic == SRPC_MSG_MAGIC) return; /* no flipping needed */ - /* We do not swap the magic number here as it is needed to - determine whether the body needs to be swapped. */ + /* + * We do not swap the magic number here as it is needed to + * determine whether the body needs to be swapped. + */ /* __swab32s(&msg->msg_magic); */ __swab32s(&msg->msg_type); __swab32s(&msg->msg_version); -- cgit From c314c319c044816090ba872ee06ccaaacc86cb0a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:01 -0500 Subject: staging: lustre: align all code properly for LNet core In several places in the LNet core the code doesn't align up properly. This resolves those checkpath issues. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 49 ++++++------ .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h | 10 +-- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 91 +++++++++++----------- .../staging/lustre/lnet/klnds/socklnd/socklnd.c | 80 +++++++++---------- .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 73 ++++++++--------- .../lustre/lnet/klnds/socklnd/socklnd_lib.c | 46 +++++------ .../lustre/lnet/klnds/socklnd/socklnd_proto.c | 22 +++--- drivers/staging/lustre/lnet/lnet/acceptor.c | 10 +-- drivers/staging/lustre/lnet/lnet/api-ni.c | 10 +-- drivers/staging/lustre/lnet/lnet/config.c | 7 +- drivers/staging/lustre/lnet/lnet/lib-move.c | 42 +++++----- drivers/staging/lustre/lnet/lnet/lib-msg.c | 4 +- drivers/staging/lustre/lnet/lnet/lib-ptl.c | 8 +- drivers/staging/lustre/lnet/lnet/lib-socket.c | 2 +- drivers/staging/lustre/lnet/lnet/lo.c | 6 +- drivers/staging/lustre/lnet/lnet/nidstrings.c | 2 +- drivers/staging/lustre/lnet/lnet/peer.c | 6 +- drivers/staging/lustre/lnet/lnet/router.c | 32 ++++---- drivers/staging/lustre/lnet/lnet/router_proc.c | 32 ++++---- drivers/staging/lustre/lnet/selftest/brw_test.c | 28 +++---- drivers/staging/lustre/lnet/selftest/conctl.c | 85 +++++++++----------- drivers/staging/lustre/lnet/selftest/conrpc.c | 31 ++++---- drivers/staging/lustre/lnet/selftest/console.c | 42 +++++----- drivers/staging/lustre/lnet/selftest/framework.c | 64 ++++++++------- drivers/staging/lustre/lnet/selftest/ping_test.c | 14 ++-- drivers/staging/lustre/lnet/selftest/rpc.c | 80 +++++++++---------- 26 files changed, 419 insertions(+), 457 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index c5bf059a8d3b..8ad128c9c9df 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -145,7 +145,7 @@ static int kiblnd_unpack_rd(kib_msg_t *msg, int flip) int i; LASSERT(msg->ibm_type == IBLND_MSG_GET_REQ || - msg->ibm_type == IBLND_MSG_PUT_ACK); + msg->ibm_type == IBLND_MSG_PUT_ACK); rd = msg->ibm_type == IBLND_MSG_GET_REQ ? &msg->ibm_u.get.ibgm_rd : @@ -444,8 +444,8 @@ static int kiblnd_get_peer_info(lnet_ni_t *ni, int index, peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || - peer->ibp_accepting > 0 || - !list_empty(&peer->ibp_conns)); + peer->ibp_accepting > 0 || + !list_empty(&peer->ibp_conns)); if (peer->ibp_ni != ni) continue; @@ -513,8 +513,8 @@ static int kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid) list_for_each_safe(ptmp, pnxt, &kiblnd_data.kib_peers[i]) { peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || - peer->ibp_accepting > 0 || - !list_empty(&peer->ibp_conns)); + peer->ibp_accepting > 0 || + !list_empty(&peer->ibp_conns)); if (peer->ibp_ni != ni) continue; @@ -526,7 +526,7 @@ static int kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid) LASSERT(list_empty(&peer->ibp_conns)); list_splice_init(&peer->ibp_tx_queue, - &zombies); + &zombies); } kiblnd_del_peer_locked(peer); @@ -557,8 +557,8 @@ static kib_conn_t *kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index) peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || - peer->ibp_accepting > 0 || - !list_empty(&peer->ibp_conns)); + peer->ibp_accepting > 0 || + !list_empty(&peer->ibp_conns)); if (peer->ibp_ni != ni) continue; @@ -568,7 +568,7 @@ static kib_conn_t *kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index) continue; conn = list_entry(ctmp, kib_conn_t, - ibc_list); + ibc_list); kiblnd_conn_addref(conn); read_unlock_irqrestore( &kiblnd_data.kib_global_lock, @@ -644,7 +644,7 @@ static int kiblnd_get_completion_vector(kib_conn_t *conn, int cpt) } kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, - int state, int version) + int state, int version) { /* * CAVEAT EMPTOR: @@ -838,7 +838,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, /* Init successful! */ LASSERT(state == IBLND_CONN_ACTIVE_CONNECT || - state == IBLND_CONN_PASSIVE_WAIT); + state == IBLND_CONN_PASSIVE_WAIT); conn->ibc_state = state; /* 1 more conn */ @@ -943,7 +943,7 @@ int kiblnd_close_peer_conns_locked(kib_peer_t *peer, int why) } int kiblnd_close_stale_conns_locked(kib_peer_t *peer, - int version, __u64 incarnation) + int version, __u64 incarnation) { kib_conn_t *conn; struct list_head *ctmp; @@ -995,8 +995,8 @@ static int kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid) peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || - peer->ibp_accepting > 0 || - !list_empty(&peer->ibp_conns)); + peer->ibp_accepting > 0 || + !list_empty(&peer->ibp_conns)); if (peer->ibp_ni != ni) continue; @@ -1192,7 +1192,7 @@ void kiblnd_map_rx_descs(kib_conn_t *conn) IBLND_MSG_SIZE, DMA_FROM_DEVICE); LASSERT(!kiblnd_dma_mapping_error(conn->ibc_hdev->ibh_ibdev, - rx->rx_msgaddr)); + rx->rx_msgaddr)); KIBLND_UNMAP_ADDR_SET(rx, rx_msgunmap, rx->rx_msgaddr); CDEBUG(D_NET, "rx %d: %p %#llx(%#llx)\n", @@ -1293,7 +1293,7 @@ static void kiblnd_map_tx_pool(kib_tx_pool_t *tpo) tpo->tpo_hdev->ibh_ibdev, tx->tx_msg, IBLND_MSG_SIZE, DMA_TO_DEVICE); LASSERT(!kiblnd_dma_mapping_error(tpo->tpo_hdev->ibh_ibdev, - tx->tx_msgaddr)); + tx->tx_msgaddr)); KIBLND_UNMAP_ADDR_SET(tx, tx_msgunmap, tx->tx_msgaddr); list_add(&tx->tx_list, &pool->po_free_list); @@ -1581,8 +1581,7 @@ int kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages, if (fps->fps_increasing) { spin_unlock(&fps->fps_lock); - CDEBUG(D_NET, - "Another thread is allocating new FMR pool, waiting for her to complete\n"); + CDEBUG(D_NET, "Another thread is allocating new FMR pool, waiting for her to complete\n"); schedule(); goto again; @@ -2252,8 +2251,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) int i; LASSERT(*kiblnd_tunables.kib_dev_failover > 1 || - dev->ibd_can_failover || - dev->ibd_hdev == NULL); + dev->ibd_can_failover || dev->ibd_hdev == NULL); rc = kiblnd_dev_need_failover(dev); if (rc <= 0) @@ -2432,8 +2430,7 @@ static kib_dev_t *kiblnd_create_dev(char *ifname) return NULL; } - list_add_tail(&dev->ibd_list, - &kiblnd_data.kib_devs); + list_add_tail(&dev->ibd_list, &kiblnd_data.kib_devs); return dev; } @@ -2861,11 +2858,11 @@ static int __init kiblnd_module_init(void) CLASSERT(sizeof(kib_msg_t) <= IBLND_MSG_SIZE); CLASSERT(offsetof(kib_msg_t, - ibm_u.get.ibgm_rd.rd_frags[IBLND_MAX_RDMA_FRAGS]) - <= IBLND_MSG_SIZE); + ibm_u.get.ibgm_rd.rd_frags[IBLND_MAX_RDMA_FRAGS]) + <= IBLND_MSG_SIZE); CLASSERT(offsetof(kib_msg_t, - ibm_u.putack.ibpam_rd.rd_frags[IBLND_MAX_RDMA_FRAGS]) - <= IBLND_MSG_SIZE); + ibm_u.putack.ibpam_rd.rd_frags[IBLND_MAX_RDMA_FRAGS]) + <= IBLND_MSG_SIZE); rc = kiblnd_tunables_init(); if (rc != 0) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 025faa9f86b3..dbbbf5515b6b 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -948,25 +948,25 @@ void kiblnd_peer_alive(kib_peer_t *peer); kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid); void kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error); int kiblnd_close_stale_conns_locked(kib_peer_t *peer, - int version, __u64 incarnation); + int version, __u64 incarnation); int kiblnd_close_peer_conns_locked(kib_peer_t *peer, int why); void kiblnd_connreq_done(kib_conn_t *conn, int status); kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, - int state, int version); + int state, int version); void kiblnd_destroy_conn(kib_conn_t *conn); void kiblnd_close_conn(kib_conn_t *conn, int error); void kiblnd_close_conn_locked(kib_conn_t *conn, int error); int kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, - int nob, kib_rdma_desc_t *dstrd, __u64 dstcookie); + int nob, kib_rdma_desc_t *dstrd, __u64 dstcookie); void kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid); void kiblnd_queue_tx_locked(kib_tx_t *tx, kib_conn_t *conn); void kiblnd_queue_tx(kib_tx_t *tx, kib_conn_t *conn); void kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob); void kiblnd_txlist_done(lnet_ni_t *ni, struct list_head *txlist, - int status); + int status); void kiblnd_check_sends (kib_conn_t *conn); void kiblnd_qp_event(struct ib_event *event, void *arg); @@ -974,7 +974,7 @@ void kiblnd_cq_event(struct ib_event *event, void *arg); void kiblnd_cq_completion(struct ib_cq *cq, void *arg); void kiblnd_pack_msg(lnet_ni_t *ni, kib_msg_t *msg, int version, - int credits, lnet_nid_t dstnid, __u64 dststamp); + int credits, lnet_nid_t dstnid, __u64 dststamp); int kiblnd_unpack_msg(kib_msg_t *msg, int nob); int kiblnd_post_rx(kib_rx_t *rx, int credit); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 5093244ec378..fbcbb97dda1f 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -396,7 +396,7 @@ kiblnd_handle_rx(kib_rx_t *rx) spin_lock(&conn->ibc_lock); tx = kiblnd_find_waiting_tx_locked(conn, IBLND_MSG_PUT_REQ, - msg->ibm_u.putack.ibpam_src_cookie); + msg->ibm_u.putack.ibpam_src_cookie); if (tx != NULL) list_del(&tx->tx_list); spin_unlock(&conn->ibc_lock); @@ -489,7 +489,7 @@ kiblnd_rx_complete(kib_rx_t *rx, int status, int nob) rc = kiblnd_unpack_msg(msg, rx->rx_nob); if (rc != 0) { CERROR("Error %d unpacking rx from %s\n", - rc, libcfs_nid2str(conn->ibc_peer->ibp_nid)); + rc, libcfs_nid2str(conn->ibc_peer->ibp_nid)); goto failed; } @@ -498,7 +498,7 @@ kiblnd_rx_complete(kib_rx_t *rx, int status, int nob) msg->ibm_srcstamp != conn->ibc_incarnation || msg->ibm_dststamp != net->ibn_incarnation) { CERROR("Stale rx from %s\n", - libcfs_nid2str(conn->ibc_peer->ibp_nid)); + libcfs_nid2str(conn->ibc_peer->ibp_nid)); err = -ESTALE; goto failed; } @@ -715,7 +715,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, static int kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, - int nkiov, lnet_kiov_t *kiov, int offset, int nob) + int nkiov, lnet_kiov_t *kiov, int offset, int nob) { kib_net_t *net = ni->ni_data; struct scatterlist *sg; @@ -909,13 +909,13 @@ kiblnd_check_sends(kib_conn_t *conn) LASSERT(conn->ibc_nsends_posted <= IBLND_CONCURRENT_SENDS(ver)); LASSERT(!IBLND_OOB_CAPABLE(ver) || - conn->ibc_noops_posted <= IBLND_OOB_MSGS(ver)); + conn->ibc_noops_posted <= IBLND_OOB_MSGS(ver)); LASSERT(conn->ibc_reserved_credits >= 0); while (conn->ibc_reserved_credits > 0 && !list_empty(&conn->ibc_tx_queue_rsrvd)) { tx = list_entry(conn->ibc_tx_queue_rsrvd.next, - kib_tx_t, tx_list); + kib_tx_t, tx_list); list_del(&tx->tx_list); list_add_tail(&tx->tx_list, &conn->ibc_tx_queue); conn->ibc_reserved_credits--; @@ -941,7 +941,7 @@ kiblnd_check_sends(kib_conn_t *conn) if (!list_empty(&conn->ibc_tx_queue_nocred)) { credit = 0; tx = list_entry(conn->ibc_tx_queue_nocred.next, - kib_tx_t, tx_list); + kib_tx_t, tx_list); } else if (!list_empty(&conn->ibc_tx_noops)) { LASSERT(!IBLND_OOB_CAPABLE(ver)); credit = 1; @@ -950,7 +950,7 @@ kiblnd_check_sends(kib_conn_t *conn) } else if (!list_empty(&conn->ibc_tx_queue)) { credit = 1; tx = list_entry(conn->ibc_tx_queue.next, - kib_tx_t, tx_list); + kib_tx_t, tx_list); } else break; @@ -1054,7 +1054,7 @@ kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob) int kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, - int resid, kib_rdma_desc_t *dstrd, __u64 dstcookie) + int resid, kib_rdma_desc_t *dstrd, __u64 dstcookie) { kib_msg_t *ibmsg = tx->tx_msg; kib_rdma_desc_t *srcrd = tx->tx_rd; @@ -1068,7 +1068,7 @@ kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, LASSERT(!in_interrupt()); LASSERT(tx->tx_nwrq == 0); LASSERT(type == IBLND_MSG_GET_DONE || - type == IBLND_MSG_PUT_DONE); + type == IBLND_MSG_PUT_DONE); srcidx = dstidx = 0; @@ -1349,10 +1349,10 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) if (list_empty(&peer->ibp_conns)) { /* found a peer, but it's still connecting... */ LASSERT(peer->ibp_connecting != 0 || - peer->ibp_accepting != 0); + peer->ibp_accepting != 0); if (tx != NULL) list_add_tail(&tx->tx_list, - &peer->ibp_tx_queue); + &peer->ibp_tx_queue); write_unlock_irqrestore(g_lock, flags); } else { conn = kiblnd_get_conn_locked(peer); @@ -1388,10 +1388,10 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) if (list_empty(&peer2->ibp_conns)) { /* found a peer, but it's still connecting... */ LASSERT(peer2->ibp_connecting != 0 || - peer2->ibp_accepting != 0); + peer2->ibp_accepting != 0); if (tx != NULL) list_add_tail(&tx->tx_list, - &peer2->ibp_tx_queue); + &peer2->ibp_tx_queue); write_unlock_irqrestore(g_lock, flags); } else { conn = kiblnd_get_conn_locked(peer2); @@ -1571,7 +1571,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) tx = kiblnd_get_idle_tx(ni, target.nid); if (tx == NULL) { CERROR("Can't send %d to %s: tx descs exhausted\n", - type, libcfs_nid2str(target.nid)); + type, libcfs_nid2str(target.nid)); return -ENOMEM; } @@ -1660,8 +1660,8 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, + unsigned int offset, unsigned int mlen, unsigned int rlen) { kib_rx_t *rx = private; kib_msg_t *rxmsg = rx->rx_msg; @@ -1684,8 +1684,8 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, nob = offsetof(kib_msg_t, ibm_u.immediate.ibim_payload[rlen]); if (nob > rx->rx_nob) { CERROR("Immediate message from %s too big: %d(%d)\n", - libcfs_nid2str(rxmsg->ibm_u.immediate.ibim_hdr.src_nid), - nob, rx->rx_nob); + libcfs_nid2str(rxmsg->ibm_u.immediate.ibim_hdr.src_nid), + nob, rx->rx_nob); rc = -EPROTO; break; } @@ -1858,12 +1858,12 @@ kiblnd_close_conn_locked(kib_conn_t *conn, int error) libcfs_nid2str(peer->ibp_nid)); } else { CNETERR("Closing conn to %s: error %d%s%s%s%s%s\n", - libcfs_nid2str(peer->ibp_nid), error, - list_empty(&conn->ibc_tx_queue) ? "" : "(sending)", - list_empty(&conn->ibc_tx_noops) ? "" : "(sending_noops)", - list_empty(&conn->ibc_tx_queue_rsrvd) ? "" : "(sending_rsrvd)", - list_empty(&conn->ibc_tx_queue_nocred) ? "" : "(sending_nocred)", - list_empty(&conn->ibc_active_txs) ? "" : "(waiting)"); + libcfs_nid2str(peer->ibp_nid), error, + list_empty(&conn->ibc_tx_queue) ? "" : "(sending)", + list_empty(&conn->ibc_tx_noops) ? "" : "(sending_noops)", + list_empty(&conn->ibc_tx_queue_rsrvd) ? "" : "(sending_rsrvd)", + list_empty(&conn->ibc_tx_queue_nocred) ? "" : "(sending_nocred)", + list_empty(&conn->ibc_active_txs) ? "" : "(waiting)"); } dev = ((kib_net_t *)peer->ibp_ni->ni_data)->ibn_dev; @@ -1944,8 +1944,7 @@ kiblnd_abort_txs(kib_conn_t *conn, struct list_head *txs) if (txs == &conn->ibc_active_txs) { LASSERT(!tx->tx_queued); - LASSERT(tx->tx_waiting || - tx->tx_sending != 0); + LASSERT(tx->tx_waiting || tx->tx_sending != 0); } else { LASSERT(tx->tx_queued); } @@ -2016,7 +2015,7 @@ kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error) peer->ibp_accepting != 0) { /* another connection attempt under way... */ write_unlock_irqrestore(&kiblnd_data.kib_global_lock, - flags); + flags); return; } @@ -2065,9 +2064,9 @@ kiblnd_connreq_done(kib_conn_t *conn, int status) LASSERT(!in_interrupt()); LASSERT((conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT && - peer->ibp_connecting > 0) || + peer->ibp_connecting > 0) || (conn->ibc_state == IBLND_CONN_PASSIVE_WAIT && - peer->ibp_accepting > 0)); + peer->ibp_accepting > 0)); LIBCFS_FREE(conn->ibc_connvars, sizeof(*conn->ibc_connvars)); conn->ibc_connvars = NULL; @@ -2352,7 +2351,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) /* Brand new peer */ LASSERT(peer->ibp_accepting == 0); LASSERT(peer->ibp_version == 0 && - peer->ibp_incarnation == 0); + peer->ibp_incarnation == 0); peer->ibp_accepting = 1; peer->ibp_version = version; @@ -2435,7 +2434,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) static void kiblnd_reconnect(kib_conn_t *conn, int version, - __u64 incarnation, int why, kib_connparams_t *cp) + __u64 incarnation, int why, kib_connparams_t *cp) { kib_peer_t *peer = conn->ibc_peer; char *reason; @@ -2827,7 +2826,7 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) case RDMA_CM_EVENT_ADDR_ERROR: peer = (kib_peer_t *)cmid->context; CNETERR("%s: ADDR ERROR %d\n", - libcfs_nid2str(peer->ibp_nid), event->status); + libcfs_nid2str(peer->ibp_nid), event->status); kiblnd_peer_connect_failed(peer, 1, -EHOSTUNREACH); kiblnd_peer_decref(peer); return -EHOSTUNREACH; /* rc != 0 destroys cmid */ @@ -2872,7 +2871,7 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) return kiblnd_active_connect(cmid); CNETERR("Can't resolve route for %s: %d\n", - libcfs_nid2str(peer->ibp_nid), event->status); + libcfs_nid2str(peer->ibp_nid), event->status); kiblnd_peer_connect_failed(peer, 1, event->status); kiblnd_peer_decref(peer); return event->status; /* rc != 0 destroys cmid */ @@ -2882,7 +2881,7 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) LASSERT(conn->ibc_state == IBLND_CONN_ACTIVE_CONNECT || conn->ibc_state == IBLND_CONN_PASSIVE_WAIT); CNETERR("%s: UNREACHABLE %d\n", - libcfs_nid2str(conn->ibc_peer->ibp_nid), event->status); + libcfs_nid2str(conn->ibc_peer->ibp_nid), event->status); kiblnd_connreq_done(conn, -ENETDOWN); kiblnd_conn_decref(conn); return 0; @@ -2905,8 +2904,8 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) case IBLND_CONN_PASSIVE_WAIT: CERROR("%s: REJECTED %d\n", - libcfs_nid2str(conn->ibc_peer->ibp_nid), - event->status); + libcfs_nid2str(conn->ibc_peer->ibp_nid), + event->status); kiblnd_connreq_done(conn, -ECONNRESET); break; @@ -3061,8 +3060,7 @@ kiblnd_check_conns(int idx) conn->ibc_reserved_credits); list_add(&conn->ibc_connd_list, &closes); } else { - list_add(&conn->ibc_connd_list, - &checksends); + list_add(&conn->ibc_connd_list, &checksends); } /* +ref for 'closes' or 'checksends' */ kiblnd_conn_addref(conn); @@ -3090,8 +3088,7 @@ kiblnd_check_conns(int idx) * free to do it last time... */ while (!list_empty(&checksends)) { - conn = list_entry(checksends.next, - kib_conn_t, ibc_connd_list); + conn = list_entry(checksends.next, kib_conn_t, ibc_connd_list); list_del(&conn->ibc_connd_list); kiblnd_check_sends(conn); kiblnd_conn_decref(conn); @@ -3136,7 +3133,7 @@ kiblnd_connd(void *arg) if (!list_empty(&kiblnd_data.kib_connd_zombies)) { conn = list_entry(kiblnd_data.kib_connd_zombies.next, - kib_conn_t, ibc_list); + kib_conn_t, ibc_list); list_del(&conn->ibc_list); spin_unlock_irqrestore(&kiblnd_data.kib_connd_lock, @@ -3150,7 +3147,7 @@ kiblnd_connd(void *arg) if (!list_empty(&kiblnd_data.kib_connd_conns)) { conn = list_entry(kiblnd_data.kib_connd_conns.next, - kib_conn_t, ibc_list); + kib_conn_t, ibc_list); list_del(&conn->ibc_list); spin_unlock_irqrestore(&kiblnd_data.kib_connd_lock, @@ -3350,8 +3347,8 @@ kiblnd_scheduler(void *arg) did_something = 0; if (!list_empty(&sched->ibs_conns)) { - conn = list_entry(sched->ibs_conns.next, - kib_conn_t, ibc_sched_list); + conn = list_entry(sched->ibs_conns.next, kib_conn_t, + ibc_sched_list); /* take over kib_sched_conns' ref on conn... */ LASSERT(conn->ibc_scheduled); list_del(&conn->ibc_sched_list); @@ -3369,7 +3366,7 @@ kiblnd_scheduler(void *arg) kiblnd_close_conn(conn, -EIO); kiblnd_conn_decref(conn); spin_lock_irqsave(&sched->ibs_lock, - flags); + flags); continue; } @@ -3397,7 +3394,7 @@ kiblnd_scheduler(void *arg) /* +1 ref for sched_conns */ kiblnd_conn_addref(conn); list_add_tail(&conn->ibc_sched_list, - &sched->ibs_conns); + &sched->ibs_conns); if (waitqueue_active(&sched->ibs_waitq)) wake_up(&sched->ibs_waitq); } else { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index a237cde543c4..6bf92fd0bcb8 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -152,7 +152,7 @@ ksocknal_destroy_peer(ksock_peer_t *peer) ksock_net_t *net = peer->ksnp_ni->ni_data; CDEBUG(D_NET, "peer %s %p deleted\n", - libcfs_id2str(peer->ksnp_id), peer); + libcfs_id2str(peer->ksnp_id), peer); LASSERT(atomic_read(&peer->ksnp_refcount) == 0); LASSERT(peer->ksnp_accepting == 0); @@ -250,8 +250,8 @@ ksocknal_unlink_peer_locked(ksock_peer_t *peer) static int ksocknal_get_peer_info(lnet_ni_t *ni, int index, - lnet_process_id_t *id, __u32 *myip, __u32 *peer_ip, - int *port, int *conn_count, int *share_count) + lnet_process_id_t *id, __u32 *myip, __u32 *peer_ip, + int *port, int *conn_count, int *share_count) { ksock_peer_t *peer; struct list_head *ptmp; @@ -305,7 +305,7 @@ ksocknal_get_peer_info(lnet_ni_t *ni, int index, continue; route = list_entry(rtmp, ksock_route_t, - ksnr_list); + ksnr_list); *id = peer->ksnp_id; *myip = route->ksnr_myipaddr; @@ -388,8 +388,8 @@ ksocknal_add_route_locked(ksock_peer_t *peer, ksock_route_t *route) if (route2->ksnr_ipaddr == route->ksnr_ipaddr) { CERROR("Duplicate route %s %pI4h\n", - libcfs_id2str(peer->ksnp_id), - &route->ksnr_ipaddr); + libcfs_id2str(peer->ksnp_id), + &route->ksnr_ipaddr); LBUG(); } } @@ -489,7 +489,7 @@ ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port) } else { /* peer table takes my ref on peer */ list_add_tail(&peer->ksnp_list, - ksocknal_nid2peerlist(id.nid)); + ksocknal_nid2peerlist(id.nid)); } route2 = NULL; @@ -592,8 +592,7 @@ ksocknal_del_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip) } for (i = lo; i <= hi; i++) { - list_for_each_safe(ptmp, pnxt, - &ksocknal_data.ksnd_peers[i]) { + list_for_each_safe(ptmp, pnxt, &ksocknal_data.ksnd_peers[i]) { peer = list_entry(ptmp, ksock_peer_t, ksnp_list); if (peer->ksnp_ni != ni) @@ -613,7 +612,7 @@ ksocknal_del_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip) LASSERT(list_empty(&peer->ksnp_routes)); list_splice_init(&peer->ksnp_tx_queue, - &zombies); + &zombies); } ksocknal_peer_decref(peer); /* ...till here */ @@ -654,7 +653,7 @@ ksocknal_get_conn_by_idx(lnet_ni_t *ni, int index) continue; conn = list_entry(ctmp, ksock_conn_t, - ksnc_list); + ksnc_list); ksocknal_conn_addref(conn); read_unlock(&ksocknal_data.ksnd_global_lock); return conn; @@ -939,7 +938,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, /* Using this interface already? */ list_for_each(rtmp, &peer->ksnp_routes) { route = list_entry(rtmp, ksock_route_t, - ksnr_list); + ksnr_list); if (route->ksnr_myipaddr == iface->ksni_ipaddr) break; @@ -1025,7 +1024,7 @@ ksocknal_connecting(ksock_peer_t *peer, __u32 ipaddr) int ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, - struct socket *sock, int type) + struct socket *sock, int type) { rwlock_t *global_lock = &ksocknal_data.ksnd_global_lock; LIST_HEAD(zombies); @@ -1157,7 +1156,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, * table (which takes my ref) */ list_add_tail(&peer->ksnp_list, - ksocknal_nid2peerlist(peerid.nid)); + ksocknal_nid2peerlist(peerid.nid)); } else { ksocknal_peer_decref(peer); peer = peer2; @@ -1395,7 +1394,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, libcfs_id2str(peerid), conn->ksnc_type, warn); else CDEBUG(D_NET, "Not creating conn %s type %d: %s\n", - libcfs_id2str(peerid), conn->ksnc_type, warn); + libcfs_id2str(peerid), conn->ksnc_type, warn); } if (!active) { @@ -1491,12 +1490,12 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) * these TXs will be send to /dev/null by scheduler */ list_for_each_entry(tx, &peer->ksnp_tx_queue, - tx_list) + tx_list) ksocknal_tx_prep(conn, tx); spin_lock_bh(&conn->ksnc_scheduler->kss_lock); list_splice_init(&peer->ksnp_tx_queue, - &conn->ksnc_tx_queue); + &conn->ksnc_tx_queue); spin_unlock_bh(&conn->ksnc_scheduler->kss_lock); } @@ -1515,7 +1514,7 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) spin_lock_bh(&ksocknal_data.ksnd_reaper_lock); list_add_tail(&conn->ksnc_list, - &ksocknal_data.ksnd_deathrow_conns); + &ksocknal_data.ksnd_deathrow_conns); wake_up(&ksocknal_data.ksnd_reaper_waitq); spin_unlock_bh(&ksocknal_data.ksnd_reaper_lock); @@ -1546,7 +1545,7 @@ ksocknal_peer_failed(ksock_peer_t *peer) if (notify) lnet_notify(peer->ksnp_ni, peer->ksnp_id.nid, 0, - last_alive); + last_alive); } void @@ -1611,7 +1610,7 @@ ksocknal_terminate_conn(ksock_conn_t *conn) if (!conn->ksnc_tx_scheduled && !list_empty(&conn->ksnc_tx_queue)) { list_add_tail(&conn->ksnc_tx_list, - &sched->kss_tx_conns); + &sched->kss_tx_conns); conn->ksnc_tx_scheduled = 1; /* extra ref for scheduler */ ksocknal_conn_addref(conn); @@ -1696,7 +1695,7 @@ ksocknal_destroy_conn(ksock_conn_t *conn) cfs_duration_sec(cfs_time_sub(cfs_time_current(), last_rcv))); lnet_finalize(conn->ksnc_peer->ksnp_ni, - conn->ksnc_cookie, -EIO); + conn->ksnc_cookie, -EIO); break; case SOCKNAL_RX_LNET_HEADER: if (conn->ksnc_rx_started) @@ -1787,7 +1786,7 @@ ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr) for (i = lo; i <= hi; i++) { list_for_each_safe(ptmp, pnxt, - &ksocknal_data.ksnd_peers[i]) { + &ksocknal_data.ksnd_peers[i]) { peer = list_entry(ptmp, ksock_peer_t, ksnp_list); @@ -1824,7 +1823,7 @@ ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive) id.pid = LNET_PID_ANY; CDEBUG(D_NET, "gw %s %s\n", libcfs_nid2str(gw_nid), - alive ? "up" : "down"); + alive ? "up" : "down"); if (!alive) { /* If the gateway crashed, close all open connections... */ @@ -1915,7 +1914,7 @@ ksocknal_push_peer(ksock_peer_t *peer) list_for_each(tmp, &peer->ksnp_conns) { if (i++ == index) { conn = list_entry(tmp, ksock_conn_t, - ksnc_list); + ksnc_list); ksocknal_conn_addref(conn); break; } @@ -2015,16 +2014,15 @@ ksocknal_add_interface(lnet_ni_t *ni, __u32 ipaddress, __u32 netmask) for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) { list_for_each(ptmp, &ksocknal_data.ksnd_peers[i]) { peer = list_entry(ptmp, ksock_peer_t, - ksnp_list); + ksnp_list); for (j = 0; j < peer->ksnp_n_passive_ips; j++) if (peer->ksnp_passive_ips[j] == ipaddress) iface->ksni_npeers++; list_for_each(rtmp, &peer->ksnp_routes) { - route = list_entry(rtmp, - ksock_route_t, - ksnr_list); + route = list_entry(rtmp, ksock_route_t, + ksnr_list); if (route->ksnr_myipaddr == ipaddress) iface->ksni_nroutes++; @@ -2113,9 +2111,8 @@ ksocknal_del_interface(lnet_ni_t *ni, __u32 ipaddress) for (j = 0; j < ksocknal_data.ksnd_peer_hash_size; j++) { list_for_each_safe(tmp, nxt, - &ksocknal_data.ksnd_peers[j]) { - peer = list_entry(tmp, ksock_peer_t, - ksnp_list); + &ksocknal_data.ksnd_peers[j]) { + peer = list_entry(tmp, ksock_peer_t, ksnp_list); if (peer->ksnp_ni != ni) continue; @@ -2277,8 +2274,8 @@ ksocknal_free_buffers(void) } LIBCFS_FREE(ksocknal_data.ksnd_peers, - sizeof(struct list_head) * - ksocknal_data.ksnd_peer_hash_size); + sizeof(struct list_head) * + ksocknal_data.ksnd_peer_hash_size); spin_lock(&ksocknal_data.ksnd_tx_lock); @@ -2411,8 +2408,8 @@ ksocknal_base_startup(void) ksocknal_data.ksnd_peer_hash_size = SOCKNAL_PEER_HASH_SIZE; LIBCFS_ALLOC(ksocknal_data.ksnd_peers, - sizeof(struct list_head) * - ksocknal_data.ksnd_peer_hash_size); + sizeof(struct list_head) * + ksocknal_data.ksnd_peer_hash_size); if (ksocknal_data.ksnd_peers == NULL) return -ENOMEM; @@ -2577,9 +2574,9 @@ ksocknal_debug_peerhash(lnet_ni_t *ni) list_for_each(tmp, &peer->ksnp_conns) { conn = list_entry(tmp, ksock_conn_t, ksnc_list); CWARN("Conn: ref %d, sref %d, t %d, c %d\n", - atomic_read(&conn->ksnc_conn_refcount), - atomic_read(&conn->ksnc_sock_refcount), - conn->ksnc_type, conn->ksnc_closing); + atomic_read(&conn->ksnc_conn_refcount), + atomic_read(&conn->ksnc_sock_refcount), + conn->ksnc_type, conn->ksnc_closing); } } @@ -2712,8 +2709,7 @@ ksocknal_search_new_ipif(ksock_net_t *net) if (colon != NULL) /* ignore alias device */ *colon = 0; - list_for_each_entry(tmp, &ksocknal_data.ksnd_nets, - ksnn_list) { + list_for_each_entry(tmp, &ksocknal_data.ksnd_nets, ksnn_list) { for (j = 0; !found && j < tmp->ksnn_ninterfaces; j++) { char *ifnam2 = &tmp->ksnn_interfaces[j].ksni_name[0]; @@ -2852,8 +2848,8 @@ ksocknal_startup(lnet_ni_t *ni) break; rc = lnet_ipif_query(ni->ni_interfaces[i], &up, - &net->ksnn_interfaces[i].ksni_ipaddr, - &net->ksnn_interfaces[i].ksni_netmask); + &net->ksnn_interfaces[i].ksni_ipaddr, + &net->ksnn_interfaces[i].ksni_netmask); if (rc != 0) { CERROR("Can't get interface %s info: %d\n", diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index f53677de2a16..1243f9270d6d 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -545,7 +545,7 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx) /* enomem list takes over scheduler's ref... */ LASSERT (conn->ksnc_tx_scheduled); list_add_tail(&conn->ksnc_tx_list, - &ksocknal_data.ksnd_enomem_conns); + &ksocknal_data.ksnd_enomem_conns); if (!cfs_time_aftereq(cfs_time_add(cfs_time_current(), SOCKNAL_ENOMEM_RETRY), ksocknal_data.ksnd_reaper_waketime)) @@ -602,7 +602,7 @@ ksocknal_launch_connection_locked (ksock_route_t *route) spin_lock_bh(&ksocknal_data.ksnd_connd_lock); list_add_tail(&route->ksnr_connd_list, - &ksocknal_data.ksnd_connd_routes); + &ksocknal_data.ksnd_connd_routes); wake_up(&ksocknal_data.ksnd_connd_waitq); spin_unlock_bh(&ksocknal_data.ksnd_connd_lock); @@ -708,9 +708,8 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) LASSERT(!conn->ksnc_closing); CDEBUG(D_NET, "Sending to %s ip %pI4h:%d\n", - libcfs_id2str(conn->ksnc_peer->ksnp_id), - &conn->ksnc_ipaddr, - conn->ksnc_port); + libcfs_id2str(conn->ksnc_peer->ksnp_id), + &conn->ksnc_ipaddr, conn->ksnc_port); ksocknal_tx_prep(conn, tx); @@ -782,8 +781,7 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) !conn->ksnc_tx_scheduled) { /* not scheduled to send */ /* +1 ref for scheduler */ ksocknal_conn_addref(conn); - list_add_tail (&conn->ksnc_tx_list, - &sched->kss_tx_conns); + list_add_tail(&conn->ksnc_tx_list, &sched->kss_tx_conns); conn->ksnc_tx_scheduled = 1; wake_up (&sched->kss_waitq); } @@ -1433,7 +1431,7 @@ int ksocknal_scheduler(void *arg) if (!list_empty (&sched->kss_rx_conns)) { conn = list_entry(sched->kss_rx_conns.next, - ksock_conn_t, ksnc_rx_list); + ksock_conn_t, ksnc_rx_list); list_del(&conn->ksnc_rx_list); LASSERT(conn->ksnc_rx_scheduled); @@ -1468,8 +1466,8 @@ int ksocknal_scheduler(void *arg) conn->ksnc_rx_state = SOCKNAL_RX_PARSE_WAIT; } else if (conn->ksnc_rx_ready) { /* reschedule for rx */ - list_add_tail (&conn->ksnc_rx_list, - &sched->kss_rx_conns); + list_add_tail(&conn->ksnc_rx_list, + &sched->kss_rx_conns); } else { conn->ksnc_rx_scheduled = 0; /* drop my ref */ @@ -1483,13 +1481,12 @@ int ksocknal_scheduler(void *arg) LIST_HEAD(zlist); if (!list_empty(&sched->kss_zombie_noop_txs)) { - list_add(&zlist, - &sched->kss_zombie_noop_txs); + list_add(&zlist, &sched->kss_zombie_noop_txs); list_del_init(&sched->kss_zombie_noop_txs); } conn = list_entry(sched->kss_tx_conns.next, - ksock_conn_t, ksnc_tx_list); + ksock_conn_t, ksnc_tx_list); list_del (&conn->ksnc_tx_list); LASSERT(conn->ksnc_tx_scheduled); @@ -1497,7 +1494,7 @@ int ksocknal_scheduler(void *arg) LASSERT(!list_empty(&conn->ksnc_tx_queue)); tx = list_entry(conn->ksnc_tx_queue.next, - ksock_tx_t, tx_list); + ksock_tx_t, tx_list); if (conn->ksnc_tx_carrier == tx) ksocknal_next_tx_carrier(conn); @@ -1527,8 +1524,7 @@ int ksocknal_scheduler(void *arg) if (rc == -ENOMEM || rc == -EAGAIN) { /* Incomplete send: replace tx on HEAD of tx_queue */ spin_lock_bh(&sched->kss_lock); - list_add(&tx->tx_list, - &conn->ksnc_tx_queue); + list_add(&tx->tx_list, &conn->ksnc_tx_queue); } else { /* Complete send; tx -ref */ ksocknal_tx_decref(tx); @@ -1547,7 +1543,7 @@ int ksocknal_scheduler(void *arg) !list_empty(&conn->ksnc_tx_queue)) { /* reschedule for tx */ list_add_tail(&conn->ksnc_tx_list, - &sched->kss_tx_conns); + &sched->kss_tx_conns); } else { conn->ksnc_tx_scheduled = 0; /* drop my ref */ @@ -1595,8 +1591,7 @@ void ksocknal_read_callback (ksock_conn_t *conn) conn->ksnc_rx_ready = 1; if (!conn->ksnc_rx_scheduled) { /* not being progressed */ - list_add_tail(&conn->ksnc_rx_list, - &sched->kss_rx_conns); + list_add_tail(&conn->ksnc_rx_list, &sched->kss_rx_conns); conn->ksnc_rx_scheduled = 1; /* extra ref for scheduler */ ksocknal_conn_addref(conn); @@ -1622,8 +1617,7 @@ void ksocknal_write_callback (ksock_conn_t *conn) if (!conn->ksnc_tx_scheduled && /* not being progressed */ !list_empty(&conn->ksnc_tx_queue)) { /* packets to send */ - list_add_tail (&conn->ksnc_tx_list, - &sched->kss_tx_conns); + list_add_tail(&conn->ksnc_tx_list, &sched->kss_tx_conns); conn->ksnc_tx_scheduled = 1; /* extra ref for scheduler */ ksocknal_conn_addref(conn); @@ -1741,7 +1735,7 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, rc = lnet_sock_read(sock, &hello->kshm_magic, sizeof (hello->kshm_magic), timeout); if (rc != 0) { CERROR("Error %d reading HELLO from %pI4h\n", - rc, &conn->ksnc_ipaddr); + rc, &conn->ksnc_ipaddr); LASSERT (rc < 0); return rc; } @@ -1761,7 +1755,7 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, sizeof(hello->kshm_version), timeout); if (rc != 0) { CERROR("Error %d reading HELLO from %pI4h\n", - rc, &conn->ksnc_ipaddr); + rc, &conn->ksnc_ipaddr); LASSERT(rc < 0); return rc; } @@ -1825,8 +1819,8 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, conn->ksnc_type = ksocknal_invert_type(hello->kshm_ctype); if (conn->ksnc_type == SOCKLND_CONN_NONE) { CERROR("Unexpected type %d from %s ip %pI4h\n", - hello->kshm_ctype, libcfs_id2str(*peerid), - &conn->ksnc_ipaddr); + hello->kshm_ctype, libcfs_id2str(*peerid), + &conn->ksnc_ipaddr); return -EPROTO; } @@ -1849,9 +1843,8 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, if (ksocknal_invert_type(hello->kshm_ctype) != conn->ksnc_type) { CERROR("Mismatched types: me %d, %s ip %pI4h %d\n", - conn->ksnc_type, libcfs_id2str(*peerid), - &conn->ksnc_ipaddr, - hello->kshm_ctype); + conn->ksnc_type, libcfs_id2str(*peerid), + &conn->ksnc_ipaddr, hello->kshm_ctype); return -EPROTO; } @@ -2009,7 +2002,7 @@ ksocknal_connect (ksock_route_t *route) */ if (!list_empty (&peer->ksnp_conns)) { conn = list_entry(peer->ksnp_conns.next, - ksock_conn_t, ksnc_list); + ksock_conn_t, ksnc_list); LASSERT (conn->ksnc_proto == &ksocknal_protocol_v3x); } @@ -2152,8 +2145,8 @@ ksocknal_connd_get_route_locked(signed long *timeout_p) now = cfs_time_current(); /* connd_routes can contain both pending and ordinary routes */ - list_for_each_entry (route, &ksocknal_data.ksnd_connd_routes, - ksnr_connd_list) { + list_for_each_entry(route, &ksocknal_data.ksnd_connd_routes, + ksnr_connd_list) { if (route->ksnr_retry_interval == 0 || cfs_time_aftereq(now, route->ksnr_timeout)) @@ -2372,8 +2365,7 @@ ksocknal_flush_stale_txs(ksock_peer_t *peer) write_lock_bh(&ksocknal_data.ksnd_global_lock); while (!list_empty (&peer->ksnp_tx_queue)) { - tx = list_entry (peer->ksnp_tx_queue.next, - ksock_tx_t, tx_list); + tx = list_entry(peer->ksnp_tx_queue.next, ksock_tx_t, tx_list); if (!cfs_time_aftereq(cfs_time_current(), tx->tx_deadline)) @@ -2498,9 +2490,8 @@ ksocknal_check_peer_timeouts (int idx) * holding only shared lock */ if (!list_empty (&peer->ksnp_tx_queue)) { - ksock_tx_t *tx = - list_entry (peer->ksnp_tx_queue.next, - ksock_tx_t, tx_list); + ksock_tx_t *tx = list_entry(peer->ksnp_tx_queue.next, + ksock_tx_t, tx_list); if (cfs_time_aftereq(cfs_time_current(), tx->tx_deadline)) { @@ -2535,7 +2526,7 @@ ksocknal_check_peer_timeouts (int idx) } tx = list_entry(peer->ksnp_zc_req_list.next, - ksock_tx_t, tx_zc_list); + ksock_tx_t, tx_zc_list); deadline = tx->tx_deadline; resid = tx->tx_resid; conn = tx->tx_conn; @@ -2609,7 +2600,7 @@ ksocknal_reaper (void *arg) if (!list_empty (&ksocknal_data.ksnd_enomem_conns)) { list_add(&enomem_conns, - &ksocknal_data.ksnd_enomem_conns); + &ksocknal_data.ksnd_enomem_conns); list_del_init(&ksocknal_data.ksnd_enomem_conns); } @@ -2618,8 +2609,8 @@ ksocknal_reaper (void *arg) /* reschedule all the connections that stalled with ENOMEM... */ nenomem_conns = 0; while (!list_empty (&enomem_conns)) { - conn = list_entry (enomem_conns.next, - ksock_conn_t, ksnc_tx_list); + conn = list_entry(enomem_conns.next, ksock_conn_t, + ksnc_tx_list); list_del (&conn->ksnc_tx_list); sched = conn->ksnc_scheduler; @@ -2629,7 +2620,7 @@ ksocknal_reaper (void *arg) LASSERT(conn->ksnc_tx_scheduled); conn->ksnc_tx_ready = 1; list_add_tail(&conn->ksnc_tx_list, - &sched->kss_tx_conns); + &sched->kss_tx_conns); wake_up(&sched->kss_waitq); spin_unlock_bh(&sched->kss_lock); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index f0edf3071c20..37df8a920e54 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -141,7 +141,7 @@ ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) int msgflg = MSG_DONTWAIT; CDEBUG(D_NET, "page %p + offset %x for %d\n", - page, offset, kiov->kiov_len); + page, offset, kiov->kiov_len); if (!list_empty(&conn->ksnc_tx_queue) || fragsize < tx->tx_resid) @@ -198,8 +198,8 @@ ksocknal_lib_eager_ack(ksock_conn_t *conn) * on, introducing delay in completing zero-copy sends in my * peer. */ - kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK, - (char *)&opt, sizeof(opt)); + kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK, (char *)&opt, + sizeof(opt)); } int @@ -236,8 +236,8 @@ ksocknal_lib_recv_iov(ksock_conn_t *conn) } LASSERT(nob <= conn->ksnc_rx_nob_wanted); - rc = kernel_recvmsg(conn->ksnc_sock, &msg, - scratchiov, niov, nob, MSG_DONTWAIT); + rc = kernel_recvmsg(conn->ksnc_sock, &msg, scratchiov, niov, nob, + MSG_DONTWAIT); saved_csum = 0; if (conn->ksnc_proto == &ksocknal_protocol_v2x) { @@ -357,8 +357,8 @@ ksocknal_lib_recv_kiov(ksock_conn_t *conn) LASSERT(nob <= conn->ksnc_rx_nob_wanted); - rc = kernel_recvmsg(conn->ksnc_sock, &msg, - (struct kvec *)scratchiov, n, nob, MSG_DONTWAIT); + rc = kernel_recvmsg(conn->ksnc_sock, &msg, (struct kvec *)scratchiov, + n, nob, MSG_DONTWAIT); if (conn->ksnc_msg.ksm_csum != 0) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { @@ -449,7 +449,7 @@ ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, int *rxmem, int * if (rc == 0) { len = sizeof(*nagle); rc = kernel_getsockopt(sock, SOL_TCP, TCP_NODELAY, - (char *)nagle, &len); + (char *)nagle, &len); } ksocknal_connsock_decref(conn); @@ -482,16 +482,16 @@ ksocknal_lib_setup_sock(struct socket *sock) linger.l_onoff = 0; linger.l_linger = 0; - rc = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, - (char *)&linger, sizeof(linger)); + rc = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&linger, + sizeof(linger)); if (rc != 0) { CERROR("Can't set SO_LINGER: %d\n", rc); return rc; } option = -1; - rc = kernel_setsockopt(sock, SOL_TCP, TCP_LINGER2, - (char *)&option, sizeof(option)); + rc = kernel_setsockopt(sock, SOL_TCP, TCP_LINGER2, (char *)&option, + sizeof(option)); if (rc != 0) { CERROR("Can't set SO_LINGER2: %d\n", rc); return rc; @@ -501,7 +501,7 @@ ksocknal_lib_setup_sock(struct socket *sock) option = 1; rc = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, - (char *)&option, sizeof(option)); + (char *)&option, sizeof(option)); if (rc != 0) { CERROR("Can't disable nagle: %d\n", rc); return rc; @@ -512,8 +512,8 @@ ksocknal_lib_setup_sock(struct socket *sock) *ksocknal_tunables.ksnd_rx_buffer_size); if (rc != 0) { CERROR("Can't set buffer tx %d, rx %d buffers: %d\n", - *ksocknal_tunables.ksnd_tx_buffer_size, - *ksocknal_tunables.ksnd_rx_buffer_size, rc); + *ksocknal_tunables.ksnd_tx_buffer_size, + *ksocknal_tunables.ksnd_rx_buffer_size, rc); return rc; } @@ -527,8 +527,8 @@ ksocknal_lib_setup_sock(struct socket *sock) do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0); option = (do_keepalive ? 1 : 0); - rc = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, - (char *)&option, sizeof(option)); + rc = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&option, + sizeof(option)); if (rc != 0) { CERROR("Can't set SO_KEEPALIVE: %d\n", rc); return rc; @@ -537,22 +537,22 @@ ksocknal_lib_setup_sock(struct socket *sock) if (!do_keepalive) return 0; - rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, - (char *)&keep_idle, sizeof(keep_idle)); + rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (char *)&keep_idle, + sizeof(keep_idle)); if (rc != 0) { CERROR("Can't set TCP_KEEPIDLE: %d\n", rc); return rc; } rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, - (char *)&keep_intvl, sizeof(keep_intvl)); + (char *)&keep_intvl, sizeof(keep_intvl)); if (rc != 0) { CERROR("Can't set TCP_KEEPINTVL: %d\n", rc); return rc; } - rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT, - (char *)&keep_count, sizeof(keep_count)); + rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT, (char *)&keep_count, + sizeof(keep_count)); if (rc != 0) { CERROR("Can't set TCP_KEEPCNT: %d\n", rc); return rc; @@ -583,7 +583,7 @@ ksocknal_lib_push_conn(ksock_conn_t *conn) release_sock(sk); rc = kernel_setsockopt(conn->ksnc_sock, SOL_TCP, TCP_NODELAY, - (char *)&val, sizeof(val)); + (char *)&val, sizeof(val)); LASSERT(rc == 0); lock_sock(sk); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index 82ac02c7fc11..2fe23d434cc4 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -76,7 +76,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, ksock_tx_t *tx = conn->ksnc_tx_carrier; LASSERT(tx_ack == NULL || - tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP); + tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP); /* * Enqueue or piggyback tx_ack / cookie @@ -88,7 +88,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, if (tx == NULL) { if (tx_ack != NULL) { list_add_tail(&tx_ack->tx_list, - &conn->ksnc_tx_queue); + &conn->ksnc_tx_queue); conn->ksnc_tx_carrier = tx_ack; } return 0; @@ -98,7 +98,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, /* tx is noop zc-ack, can't piggyback zc-ack cookie */ if (tx_ack != NULL) list_add_tail(&tx_ack->tx_list, - &conn->ksnc_tx_queue); + &conn->ksnc_tx_queue); return 0; } @@ -163,13 +163,13 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, /* non-blocking ZC-ACK (to router) */ LASSERT(tx_ack == NULL || - tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP); + tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP); tx = conn->ksnc_tx_carrier; if (tx == NULL) { if (tx_ack != NULL) { list_add_tail(&tx_ack->tx_list, - &conn->ksnc_tx_queue); + &conn->ksnc_tx_queue); conn->ksnc_tx_carrier = tx_ack; } return 0; @@ -424,8 +424,8 @@ ksocknal_handle_zcack(ksock_conn_t *conn, __u64 cookie1, __u64 cookie2) spin_lock(&peer->ksnp_lock); - list_for_each_entry_safe(tx, tmp, - &peer->ksnp_zc_req_list, tx_zc_list) { + list_for_each_entry_safe(tx, tmp, &peer->ksnp_zc_req_list, + tx_zc_list) { __u64 c = tx->tx_msg.ksm_zc_cookies[0]; if (c == cookie1 || c == cookie2 || (cookie1 < c && c < cookie2)) { @@ -587,7 +587,7 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, timeout); if (rc != 0) { CERROR("Error %d reading rest of HELLO hdr from %pI4h\n", - rc, &conn->ksnc_ipaddr); + rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); goto out; } @@ -622,7 +622,7 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, hello->kshm_nips * sizeof(__u32), timeout); if (rc != 0) { CERROR("Error %d reading IPs from ip %pI4h\n", - rc, &conn->ksnc_ipaddr); + rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); goto out; } @@ -661,7 +661,7 @@ ksocknal_recv_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout timeout); if (rc != 0) { CERROR("Error %d reading HELLO from %pI4h\n", - rc, &conn->ksnc_ipaddr); + rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); return rc; } @@ -690,7 +690,7 @@ ksocknal_recv_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout hello->kshm_nips * sizeof(__u32), timeout); if (rc != 0) { CERROR("Error %d reading IPs from ip %pI4h\n", - rc, &conn->ksnc_ipaddr); + rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); return rc; } diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index 5260de24d6a5..b330f6476f32 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -142,7 +142,7 @@ EXPORT_SYMBOL(lnet_connect_console_error); int lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, - __u32 local_ip, __u32 peer_ip, int peer_port) + __u32 local_ip, __u32 peer_ip, int peer_port) { lnet_acceptor_connreq_t cr; struct socket *sock; @@ -259,7 +259,7 @@ lnet_accept(struct socket *sock, __u32 magic) accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request version from %pI4h\n", - rc, &peer_ip); + rc, &peer_ip); return -EIO; } @@ -292,7 +292,7 @@ lnet_accept(struct socket *sock, __u32 magic) accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from %pI4h\n", - rc, &peer_ip); + rc, &peer_ip); return -EIO; } @@ -313,7 +313,7 @@ lnet_accept(struct socket *sock, __u32 magic) /* This catches a request for the loopback LND */ lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h for %s: NI doesn not accept IP connections\n", - &peer_ip, libcfs_nid2str(cr.acr_nid)); + &peer_ip, libcfs_nid2str(cr.acr_nid)); return -EPERM; } @@ -396,7 +396,7 @@ lnet_acceptor(void *arg) accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from %pI4h\n", - rc, &peer_ip); + rc, &peer_ip); goto failed; } diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 79447bf82ec9..aeef4803ee60 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -857,7 +857,7 @@ lnet_shutdown_lndnis(void) /* Unlink NIs from the global table */ while (!list_empty(&the_lnet.ln_nis)) { ni = list_entry(the_lnet.ln_nis.next, - lnet_ni_t, ni_list); + lnet_ni_t, ni_list); /* move it to zombie list and nobody can find it anymore */ list_move(&ni->ni_list, &the_lnet.ln_nis_zombie); lnet_ni_decref_locked(ni, 0); /* drop ln_nis' ref */ @@ -906,7 +906,7 @@ lnet_shutdown_lndnis(void) int j; ni = list_entry(the_lnet.ln_nis_zombie.next, - lnet_ni_t, ni_list); + lnet_ni_t, ni_list); list_del_init(&ni->ni_list); cfs_percpt_for_each(ref, j, ni->ni_refs) { if (*ref == 0) @@ -1004,7 +1004,7 @@ lnet_startup_lndnis(void) if (lnd == NULL) { mutex_unlock(&the_lnet.ln_lnd_mutex); rc = request_module("%s", - libcfs_lnd2modname(lnd_type)); + libcfs_lnd2modname(lnd_type)); mutex_lock(&the_lnet.ln_lnd_mutex); lnd = lnet_find_lnd_by_type(lnd_type); @@ -1046,7 +1046,7 @@ lnet_startup_lndnis(void) list_add_tail(&ni->ni_list, &the_lnet.ln_nis); if (ni->ni_cpts != NULL) { list_add_tail(&ni->ni_cptlist, - &the_lnet.ln_nis_cpt); + &the_lnet.ln_nis_cpt); lnet_ni_addref_locked(ni, 0); } @@ -1189,7 +1189,7 @@ lnet_fini(void) while (!list_empty(&the_lnet.ln_lnds)) lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next, - lnd_t, lnd_list)); + lnd_t, lnd_list)); lnet_destroy_locks(); the_lnet.ln_init = 0; diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 01efe6172be8..5339dee56840 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -542,10 +542,9 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) { /* simple string enumeration */ - if (lnet_expand1tb( - &pending, str, sep, sep2, - parsed, - (int)(enditem - parsed)) != 0) { + if (lnet_expand1tb(&pending, str, sep, sep2, + parsed, + (int)(enditem - parsed)) != 0) { goto failed; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 0268ce5761da..7e1ef1865e5c 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -173,8 +173,8 @@ EXPORT_SYMBOL(lnet_iov_nob); void lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, - unsigned int nsiov, struct kvec *siov, unsigned int soffset, - unsigned int nob) + unsigned int nsiov, struct kvec *siov, unsigned int soffset, + unsigned int nob) { /* NB diov, siov are READ-ONLY */ unsigned int this_nob; @@ -208,7 +208,7 @@ lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, this_nob = min(this_nob, nob); memcpy((char *)diov->iov_base + doffset, - (char *)siov->iov_base + soffset, this_nob); + (char *)siov->iov_base + soffset, this_nob); nob -= this_nob; if (diov->iov_len > doffset + this_nob) { @@ -232,8 +232,8 @@ EXPORT_SYMBOL(lnet_copy_iov2iov); int lnet_extract_iov(int dst_niov, struct kvec *dst, - int src_niov, struct kvec *src, - unsigned int offset, unsigned int len) + int src_niov, struct kvec *src, + unsigned int offset, unsigned int len) { /* * Initialise 'dst' to the subset of 'src' starting at 'offset', @@ -516,8 +516,8 @@ EXPORT_SYMBOL(lnet_copy_iov2kiov); int lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, - int src_niov, lnet_kiov_t *src, - unsigned int offset, unsigned int len) + int src_niov, lnet_kiov_t *src, + unsigned int offset, unsigned int len) { /* * Initialise 'dst' to the subset of 'src' starting at 'offset', @@ -550,7 +550,7 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, if (len <= frag_len) { dst->kiov_len = len; LASSERT(dst->kiov_offset + dst->kiov_len - <= PAGE_CACHE_SIZE); + <= PAGE_CACHE_SIZE); return niov; } @@ -653,7 +653,7 @@ lnet_ni_send(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(!in_interrupt()); LASSERT(LNET_NETTYP(LNET_NIDNET(ni->ni_nid)) == LOLND || - (msg->msg_txcredit && msg->msg_peertxcredit)); + (msg->msg_txcredit && msg->msg_peertxcredit)); rc = (ni->ni_lnd->lnd_send)(ni, priv, msg); if (rc < 0) @@ -835,7 +835,7 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) if (!msg->msg_peertxcredit) { LASSERT((lp->lp_txcredits < 0) == - !list_empty(&lp->lp_txq)); + !list_empty(&lp->lp_txq)); msg->msg_peertxcredit = 1; lp->lp_txqnob += msg->msg_len + sizeof(lnet_hdr_t); @@ -920,7 +920,7 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) if (!msg->msg_peerrtrcredit) { LASSERT((lp->lp_rtrcredits < 0) == - !list_empty(&lp->lp_rtrq)); + !list_empty(&lp->lp_rtrq)); msg->msg_peerrtrcredit = 1; lp->lp_rtrcredits--; @@ -993,7 +993,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) tq->tq_credits++; if (tq->tq_credits <= 0) { msg2 = list_entry(tq->tq_delayed.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); LASSERT(msg2->msg_txpeer->lp_ni == ni); @@ -1016,7 +1016,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) txpeer->lp_txcredits++; if (txpeer->lp_txcredits <= 0) { msg2 = list_entry(txpeer->lp_txq.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); LASSERT(msg2->msg_txpeer == txpeer); @@ -1066,7 +1066,7 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) rbp->rbp_credits++; if (rbp->rbp_credits <= 0) { msg2 = list_entry(rbp->rbp_msgs.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); (void) lnet_post_routed_recv_locked(msg2, 1); @@ -1083,7 +1083,7 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) rxpeer->lp_rtrcredits++; if (rxpeer->lp_rtrcredits <= 0) { msg2 = list_entry(rxpeer->lp_rtrq.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg2->msg_list); (void) lnet_post_routed_recv_locked(msg2, 1); @@ -2160,7 +2160,7 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, rc = lnet_send(self, msg, LNET_NID_ANY); if (rc != 0) { CNETERR("Error sending PUT to %s: %d\n", - libcfs_id2str(target), rc); + libcfs_id2str(target), rc); lnet_finalize(NULL, msg, rc); } @@ -2195,14 +2195,14 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) if (msg == NULL) { CERROR("%s: Dropping REPLY from %s: can't allocate msg\n", - libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id)); + libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id)); goto drop; } if (getmd->md_threshold == 0) { CERROR("%s: Dropping REPLY from %s for inactive MD %p\n", - libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), - getmd); + libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), + getmd); lnet_res_unlock(cpt); goto drop; } @@ -2358,7 +2358,7 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, rc = lnet_send(self, msg, LNET_NID_ANY); if (rc < 0) { CNETERR("Error sending GET to %s: %d\n", - libcfs_id2str(target), rc); + libcfs_id2str(target), rc); lnet_finalize(NULL, msg, rc); } @@ -2444,7 +2444,7 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) LASSERT(!list_empty(&rnet->lrn_routes)); list_for_each_entry(route, &rnet->lrn_routes, - lr_list) { + lr_list) { if (shortest == NULL || route->lr_hops < shortest->lr_hops) shortest = route; diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 62717ee8c16b..a680e6827370 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -523,7 +523,7 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) while (!list_empty(&container->msc_finalizing)) { msg = list_entry(container->msc_finalizing.next, - lnet_msg_t, msg_list); + lnet_msg_t, msg_list); list_del(&msg->msg_list); @@ -554,7 +554,7 @@ lnet_msg_container_cleanup(struct lnet_msg_container *container) while (!list_empty(&container->msc_active)) { lnet_msg_t *msg = list_entry(container->msc_active.next, - lnet_msg_t, msg_activelist); + lnet_msg_t, msg_activelist); LASSERT(msg->msg_onactivelist); msg->msg_onactivelist = 0; diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index 3a82fb6b55e5..d99364f43cca 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -458,7 +458,7 @@ lnet_ptl_match_early(struct lnet_portal *ptl, struct lnet_msg *msg) if (msg->msg_rx_ready_delay) { msg->msg_rx_delayed = 1; list_add_tail(&msg->msg_list, - &ptl->ptl_msg_delayed); + &ptl->ptl_msg_delayed); } rc = LNET_MATCHMD_NONE; } else { @@ -498,7 +498,7 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, if (i == 0) { /* the first try, attach on stealing list */ list_add_tail(&msg->msg_list, - &ptl->ptl_msg_stealing); + &ptl->ptl_msg_stealing); } if (!list_empty(&msg->msg_list)) { /* on stealing list */ @@ -531,7 +531,7 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, if (lnet_ptl_is_lazy(ptl)) { msg->msg_rx_delayed = 1; list_add_tail(&msg->msg_list, - &ptl->ptl_msg_delayed); + &ptl->ptl_msg_delayed); rc = LNET_MATCHMD_NONE; } else { rc = LNET_MATCHMD_DROP; @@ -751,7 +751,7 @@ lnet_ptl_cleanup(struct lnet_portal *ptl) for (j = 0; j < LNET_MT_HASH_SIZE + 1; j++) { while (!list_empty(&mhash[j])) { me = list_entry(mhash[j].next, - lnet_me_t, me_list); + lnet_me_t, me_list); CERROR("Active ME %p on exit\n", me); list_del(&me->me_list); lnet_me_free(me); diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index c3835958b318..0b3ef1740b26 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -440,7 +440,7 @@ lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize) if (rxbufsize != 0) { option = rxbufsize; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (char *)&option, sizeof(option)); + (char *)&option, sizeof(option)); if (rc != 0) { CERROR("Can't set receive buffer %d: %d\n", option, rc); diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 2a137f46800f..314e16422a29 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -46,9 +46,9 @@ lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) static int lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, - int delayed, unsigned int niov, - struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) + int delayed, unsigned int niov, + struct kvec *iov, lnet_kiov_t *kiov, + unsigned int offset, unsigned int mlen, unsigned int rlen) { lnet_msg_t *sendmsg = private; diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index 36577fed3a93..00de4faf2b82 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -380,7 +380,7 @@ int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist) return 1; list_for_each_entry(ar, &nr->nr_addrranges, ar_link) if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid), - &ar->ar_numaddr_ranges)) + &ar->ar_numaddr_ranges)) return 1; } return 0; diff --git a/drivers/staging/lustre/lnet/lnet/peer.c b/drivers/staging/lustre/lnet/lnet/peer.c index 1fceed3c8fc0..9c0f264ae4cb 100644 --- a/drivers/staging/lustre/lnet/lnet/peer.c +++ b/drivers/staging/lustre/lnet/lnet/peer.c @@ -155,7 +155,7 @@ lnet_peer_tables_cleanup(void) while (!list_empty(&deathrow)) { lp = list_entry(deathrow.next, - lnet_peer_t, lp_hashlist); + lnet_peer_t, lp_hashlist); list_del(&lp->lp_hashlist); LIBCFS_FREE(lp, sizeof(*lp)); } @@ -227,7 +227,7 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) if (!list_empty(&ptable->pt_deathrow)) { lp = list_entry(ptable->pt_deathrow.next, - lnet_peer_t, lp_hashlist); + lnet_peer_t, lp_hashlist); list_del(&lp->lp_hashlist); } @@ -293,7 +293,7 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) lp->lp_minrtrcredits = lnet_peer_buffer_credits(lp->lp_ni); list_add_tail(&lp->lp_hashlist, - &ptable->pt_hash[lnet_nid2peerhash(nid)]); + &ptable->pt_hash[lnet_nid2peerhash(nid)]); ptable->pt_version++; *lpp = lp; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index b6b2ed8f7003..754f7f071bbe 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -180,7 +180,7 @@ lnet_rtr_addref_locked(lnet_peer_t *lp) /* a simple insertion sort */ list_for_each_prev(pos, &the_lnet.ln_routers) { lnet_peer_t *rtr = list_entry(pos, lnet_peer_t, - lp_rtr_list); + lp_rtr_list); if (rtr->lp_nid < lp->lp_nid) break; @@ -206,7 +206,7 @@ lnet_rtr_decref_locked(lnet_peer_t *lp) if (lp->lp_rcd != NULL) { list_add(&lp->lp_rcd->rcd_list, - &the_lnet.ln_rcd_deathrow); + &the_lnet.ln_rcd_deathrow); lp->lp_rcd = NULL; } @@ -432,8 +432,7 @@ lnet_check_routes(void) lnet_nid_t nid2; int net; - route = list_entry(e2, lnet_route_t, - lr_list); + route = list_entry(e2, lnet_route_t, lr_list); if (route2 == NULL) { route2 = route; @@ -493,7 +492,7 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid) rnet = list_entry(e1, lnet_remotenet_t, lrn_list); if (!(net == LNET_NIDNET(LNET_NID_ANY) || - net == rnet->lrn_net)) + net == rnet->lrn_net)) continue; list_for_each(e2, &rnet->lrn_routes) { @@ -565,8 +564,7 @@ lnet_get_route(int idx, __u32 *net, __u32 *hops, rnet = list_entry(e1, lnet_remotenet_t, lrn_list); list_for_each(e2, &rnet->lrn_routes) { - route = list_entry(e2, lnet_route_t, - lr_list); + route = list_entry(e2, lnet_route_t, lr_list); if (idx-- == 0) { *net = rnet->lrn_net; @@ -1111,13 +1109,13 @@ lnet_prune_rc_data(int wait_unlink) if (the_lnet.ln_rc_state != LNET_RC_STATE_RUNNING) { /* router checker is stopping, prune all */ list_for_each_entry(lp, &the_lnet.ln_routers, - lp_rtr_list) { + lp_rtr_list) { if (lp->lp_rcd == NULL) continue; LASSERT(list_empty(&lp->lp_rcd->rcd_list)); list_add(&lp->lp_rcd->rcd_list, - &the_lnet.ln_rcd_deathrow); + &the_lnet.ln_rcd_deathrow); lp->lp_rcd = NULL; } } @@ -1139,7 +1137,7 @@ lnet_prune_rc_data(int wait_unlink) /* release all zombie RCDs */ while (!list_empty(&the_lnet.ln_rcd_zombie)) { list_for_each_entry_safe(rcd, tmp, &the_lnet.ln_rcd_zombie, - rcd_list) { + rcd_list) { if (LNetHandleIsInvalid(rcd->rcd_mdh)) list_move(&rcd->rcd_list, &head); } @@ -1151,7 +1149,7 @@ lnet_prune_rc_data(int wait_unlink) while (!list_empty(&head)) { rcd = list_entry(head.next, - lnet_rc_data_t, rcd_list); + lnet_rc_data_t, rcd_list); list_del_init(&rcd->rcd_list); lnet_destroy_rc_data(rcd); } @@ -1301,7 +1299,7 @@ lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp) LASSERT(rbp->rbp_credits > 0); rb = list_entry(rbp->rbp_bufs.next, - lnet_rtrbuf_t, rb_list); + lnet_rtrbuf_t, rb_list); list_del(&rb->rb_list); lnet_destroy_rtrbuf(rb, npages); nbuffers++; @@ -1521,15 +1519,15 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) LASSERT(!in_interrupt()); CDEBUG(D_NET, "%s notifying %s: %s\n", - (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid), - libcfs_nid2str(nid), - alive ? "up" : "down"); + (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid), + libcfs_nid2str(nid), + alive ? "up" : "down"); if (ni != NULL && LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) { CWARN("Ignoring notification of %s %s by %s (different net)\n", - libcfs_nid2str(nid), alive ? "birth" : "death", - libcfs_nid2str(ni->ni_nid)); + libcfs_nid2str(nid), alive ? "birth" : "death", + libcfs_nid2str(ni->ni_nid)); return -EINVAL; } diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 339c27667d2b..4a5067c43f1b 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -78,9 +78,10 @@ #define LNET_PROC_VERSION(v) ((unsigned int)((v) & LNET_PROC_VER_MASK)) static int proc_call_handler(void *data, int write, loff_t *ppos, - void __user *buffer, size_t *lenp, - int (*handler)(void *data, int write, - loff_t pos, void __user *buffer, int len)) + void __user *buffer, size_t *lenp, + int (*handler)(void *data, int write, + loff_t pos, void __user *buffer, + int len)) { int rc = handler(data, write, *ppos, buffer, *lenp); @@ -216,14 +217,14 @@ static int proc_lnet_routes(struct ctl_table *table, int write, while (n != rn_list && route == NULL) { rnet = list_entry(n, lnet_remotenet_t, - lrn_list); + lrn_list); r = rnet->lrn_routes.next; while (r != &rnet->lrn_routes) { lnet_route_t *re = list_entry(r, lnet_route_t, - lr_list); + lr_list); if (skip == 0) { route = re; break; @@ -332,7 +333,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, while (r != &the_lnet.ln_routers) { lnet_peer_t *lp = list_entry(r, lnet_peer_t, - lp_rtr_list); + lp_rtr_list); if (skip == 0) { peer = lp; @@ -479,7 +480,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, while (p != &ptable->pt_hash[hash]) { lnet_peer_t *lp = list_entry(p, lnet_peer_t, - lp_hashlist); + lp_hashlist); if (skip == 0) { peer = lp; @@ -734,13 +735,14 @@ static int proc_lnet_nis(struct ctl_table *table, int write, lnet_net_lock(i); s += snprintf(s, tmpstr + tmpsiz - s, - "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n", - libcfs_nid2str(ni->ni_nid), stat, - last_alive, *ni->ni_refs[i], - ni->ni_peertxcredits, - ni->ni_peerrtrcredits, - tq->tq_credits_max, - tq->tq_credits, tq->tq_credits_min); + "%-24s %6s %5d %4d %4d %4d %5d %5d %5d\n", + libcfs_nid2str(ni->ni_nid), stat, + last_alive, *ni->ni_refs[i], + ni->ni_peertxcredits, + ni->ni_peerrtrcredits, + tq->tq_credits_max, + tq->tq_credits, + tq->tq_credits_min); if (i != 0) lnet_net_unlock(i); } @@ -839,7 +841,7 @@ static int __proc_lnet_portal_rotor(void *data, int write, rc = 0; } else { rc = cfs_trace_copyout_string(buffer, nob, - buf + pos, "\n"); + buf + pos, "\n"); } goto out; } diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 8b159b61e68f..88fb54dc4050 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -220,7 +220,7 @@ brw_check_page(struct page *pg, int pattern, __u64 magic) bad_data: CERROR("Bad data in page %p: %#llx, %#llx expected\n", - pg, data, magic); + pg, data, magic); return 1; } @@ -246,7 +246,7 @@ brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) pg = bk->bk_iovs[i].kiov_page; if (brw_check_page(pg, pattern, magic) != 0) { CERROR("Bulk page %p (%d/%d) is corrupted!\n", - pg, i, bk->bk_niov); + pg, i, bk->bk_niov); return 1; } } @@ -256,7 +256,7 @@ brw_check_bulk(srpc_bulk_t *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, srpc_client_rpc_t **rpcpp) { srpc_bulk_t *bulk = tsu->tsu_private; sfw_test_instance_t *tsi = tsu->tsu_instance; @@ -328,7 +328,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) if (rpc->crpc_status != 0) { CERROR("BRW RPC to %s failed with %d\n", - libcfs_id2str(rpc->crpc_dest), rpc->crpc_status); + libcfs_id2str(rpc->crpc_dest), rpc->crpc_status); if (!tsi->tsi_stopping) /* rpc could have been aborted */ atomic_inc(&sn->sn_brw_errors); goto out; @@ -340,8 +340,8 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) } CDEBUG(reply->brw_status ? D_WARNING : D_NET, - "BRW RPC to %s finished with brw_status: %d\n", - libcfs_id2str(rpc->crpc_dest), reply->brw_status); + "BRW RPC to %s finished with brw_status: %d\n", + libcfs_id2str(rpc->crpc_dest), reply->brw_status); if (reply->brw_status != 0) { atomic_inc(&sn->sn_brw_errors); @@ -354,7 +354,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) { CERROR("Bulk data from %s is corrupted!\n", - libcfs_id2str(rpc->crpc_dest)); + libcfs_id2str(rpc->crpc_dest)); atomic_inc(&sn->sn_brw_errors); rpc->crpc_status = -EBADMSG; } @@ -373,12 +373,12 @@ brw_server_rpc_done(struct srpc_server_rpc *rpc) if (rpc->srpc_status != 0) CERROR("Bulk transfer %s %s has failed: %d\n", - blk->bk_sink ? "from" : "to", - libcfs_id2str(rpc->srpc_peer), rpc->srpc_status); + blk->bk_sink ? "from" : "to", + libcfs_id2str(rpc->srpc_peer), rpc->srpc_status); else CDEBUG(D_NET, "Transferred %d pages bulk data %s %s\n", - blk->bk_niov, blk->bk_sink ? "from" : "to", - libcfs_id2str(rpc->srpc_peer)); + blk->bk_niov, blk->bk_sink ? "from" : "to", + libcfs_id2str(rpc->srpc_peer)); sfw_free_pages(rpc); } @@ -399,8 +399,8 @@ brw_bulk_ready(struct srpc_server_rpc *rpc, int status) if (status != 0) { CERROR("BRW bulk %s failed for RPC from %s: %d\n", - reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE", - libcfs_id2str(rpc->srpc_peer), status); + reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE", + libcfs_id2str(rpc->srpc_peer), status); return -EIO; } @@ -412,7 +412,7 @@ brw_bulk_ready(struct srpc_server_rpc *rpc, int status) if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) { CERROR("Bulk data from %s is corrupted!\n", - libcfs_id2str(rpc->srpc_peer)); + libcfs_id2str(rpc->srpc_peer)); reply->brw_status = EBADMSG; } diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index a534665403e5..cb5c125791f7 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -62,9 +62,8 @@ lst_session_new_ioctl(lstio_session_new_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_ses_namep, - args->lstio_ses_nmlen)) { + if (copy_from_user(name, args->lstio_ses_namep, + args->lstio_ses_nmlen)) { LIBCFS_FREE(name, args->lstio_ses_nmlen + 1); return -EFAULT; } @@ -137,7 +136,7 @@ lst_debug_ioctl(lstio_debug_args_t *args) return -ENOMEM; if (copy_from_user(name, args->lstio_dbg_namep, - args->lstio_dbg_nmlen)) { + args->lstio_dbg_nmlen)) { LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1); return -EFAULT; @@ -212,9 +211,8 @@ lst_group_add_ioctl(lstio_group_add_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_grp_namep, - args->lstio_grp_nmlen)) { + if (copy_from_user(name, args->lstio_grp_namep, + args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen); return -EFAULT; } @@ -246,9 +244,8 @@ lst_group_del_ioctl(lstio_group_del_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_grp_namep, - args->lstio_grp_nmlen)) { + if (copy_from_user(name, args->lstio_grp_namep, + args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; } @@ -344,7 +341,7 @@ lst_nodes_add_ioctl(lstio_group_nodes_args_t *args) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, - args->lstio_grp_nmlen)) { + args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; @@ -408,9 +405,9 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) return -EINVAL; if (copy_from_user(&ndent, args->lstio_grp_ndentp, - sizeof(ndent)) || + sizeof(ndent)) || copy_from_user(&index, args->lstio_grp_idxp, - sizeof(index))) + sizeof(index))) return -EFAULT; if (ndent <= 0 || index < 0) @@ -421,9 +418,8 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_grp_namep, - args->lstio_grp_nmlen)) { + if (copy_from_user(name, args->lstio_grp_namep, + args->lstio_grp_nmlen)) { LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); return -EFAULT; } @@ -464,9 +460,8 @@ lst_batch_add_ioctl(lstio_batch_add_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_bat_namep, - args->lstio_bat_nmlen)) { + if (copy_from_user(name, args->lstio_bat_namep, + args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } @@ -498,9 +493,8 @@ lst_batch_run_ioctl(lstio_batch_run_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_bat_namep, - args->lstio_bat_nmlen)) { + if (copy_from_user(name, args->lstio_bat_namep, + args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } @@ -534,9 +528,8 @@ lst_batch_stop_ioctl(lstio_batch_stop_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_bat_namep, - args->lstio_bat_nmlen)) { + if (copy_from_user(name, args->lstio_bat_namep, + args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } @@ -573,9 +566,8 @@ lst_batch_query_ioctl(lstio_batch_query_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_bat_namep, - args->lstio_bat_nmlen)) { + if (copy_from_user(name, args->lstio_bat_namep, + args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } @@ -636,9 +628,9 @@ lst_batch_info_ioctl(lstio_batch_info_args_t *args) return -EINVAL; if (copy_from_user(&index, args->lstio_bat_idxp, - sizeof(index)) || + sizeof(index)) || copy_from_user(&ndent, args->lstio_bat_ndentp, - sizeof(ndent))) + sizeof(ndent))) return -EFAULT; if (ndent <= 0 || index < 0) @@ -649,18 +641,17 @@ lst_batch_info_ioctl(lstio_batch_info_args_t *args) if (name == NULL) return -ENOMEM; - if (copy_from_user(name, - args->lstio_bat_namep, args->lstio_bat_nmlen)) { + if (copy_from_user(name, args->lstio_bat_namep, + args->lstio_bat_nmlen)) { LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); return -EFAULT; } name[args->lstio_bat_nmlen] = 0; - rc = lstcon_batch_info(name, - args->lstio_bat_entp, args->lstio_bat_server, - args->lstio_bat_testidx, &index, &ndent, - args->lstio_bat_dentsp); + rc = lstcon_batch_info(name, args->lstio_bat_entp, + args->lstio_bat_server, args->lstio_bat_testidx, + &index, &ndent, args->lstio_bat_dentsp); LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); @@ -701,7 +692,7 @@ lst_stat_query_ioctl(lstio_stat_args_t *args) return -ENOMEM; if (copy_from_user(name, args->lstio_sta_namep, - args->lstio_sta_nmlen)) { + args->lstio_sta_nmlen)) { LIBCFS_FREE(name, args->lstio_sta_nmlen + 1); return -EFAULT; } @@ -781,21 +772,19 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) copy_from_user(dst_name, args->lstio_tes_dgrp_name, args->lstio_tes_dgrp_nmlen) || copy_from_user(param, args->lstio_tes_param, - args->lstio_tes_param_len)) + args->lstio_tes_param_len)) goto out; - rc = lstcon_test_add(batch_name, - args->lstio_tes_type, - args->lstio_tes_loop, - args->lstio_tes_concur, - args->lstio_tes_dist, args->lstio_tes_span, - src_name, dst_name, param, - args->lstio_tes_param_len, - &ret, args->lstio_tes_resultp); + rc = lstcon_test_add(batch_name, args->lstio_tes_type, + args->lstio_tes_loop, args->lstio_tes_concur, + args->lstio_tes_dist, args->lstio_tes_span, + src_name, dst_name, param, + args->lstio_tes_param_len, + &ret, args->lstio_tes_resultp); if (ret != 0) rc = (copy_to_user(args->lstio_tes_retp, &ret, - sizeof(ret))) ? -EFAULT : 0; + sizeof(ret))) ? -EFAULT : 0; out: if (batch_name != NULL) LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1); @@ -916,7 +905,7 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data) } if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat, - sizeof(lstcon_trans_stat_t))) + sizeof(lstcon_trans_stat_t))) rc = -EFAULT; out: mutex_unlock(&console_session.ses_mutex); diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 4f09b51ed026..3e702e234b33 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -125,7 +125,7 @@ lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, if (!list_empty(&console_session.ses_rpc_freelist)) { crpc = list_entry(console_session.ses_rpc_freelist.next, - lstcon_rpc_t, crp_link); + lstcon_rpc_t, crp_link); list_del_init(&crpc->crp_link); } @@ -174,7 +174,7 @@ lstcon_rpc_put(lstcon_rpc_t *crpc) spin_lock(&console_session.ses_rpc_lock); list_add(&crpc->crp_link, - &console_session.ses_rpc_freelist); + &console_session.ses_rpc_freelist); spin_unlock(&console_session.ses_rpc_lock); } @@ -490,7 +490,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { if (copy_from_user(&tmp, next, - sizeof(struct list_head))) + sizeof(struct list_head))) return -EFAULT; if (tmp.next == head_up) @@ -510,13 +510,13 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, (unsigned long)console_session.ses_id.ses_stamp); jiffies_to_timeval(dur, &tv); - if (copy_to_user(&ent->rpe_peer, - &nd->nd_id, sizeof(lnet_process_id_t)) || + if (copy_to_user(&ent->rpe_peer, &nd->nd_id, + sizeof(lnet_process_id_t)) || copy_to_user(&ent->rpe_stamp, &tv, sizeof(tv)) || - copy_to_user(&ent->rpe_state, - &nd->nd_state, sizeof(nd->nd_state)) || + copy_to_user(&ent->rpe_state, &nd->nd_state, + sizeof(nd->nd_state)) || copy_to_user(&ent->rpe_rpc_errno, &error, - sizeof(error))) + sizeof(error))) return -EFAULT; if (error != 0) @@ -525,10 +525,9 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, /* RPC is done */ rep = (srpc_generic_reply_t *)&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, sizeof(rep->status))) + if (copy_to_user(&ent->rpe_sid, &rep->sid, sizeof(lst_sid_t)) || + copy_to_user(&ent->rpe_fwk_errno, &rep->status, + sizeof(rep->status))) return -EFAULT; if (readent == NULL) @@ -952,8 +951,8 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, if (reply->msg_ses_feats != trans->tas_features) { CNETERR("Framework features %x from %s is different with features on this transaction: %x\n", - reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid), - trans->tas_features); + reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid), + trans->tas_features); status = mksn_rep->mksn_status = EPROTO; } @@ -1116,7 +1115,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, if (rc < 0) { CDEBUG(D_NET, "Condition error while creating RPC for transaction %d: %d\n", - transop, rc); + transop, rc); break; } @@ -1342,7 +1341,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, - tas_link); + tas_link); CDEBUG(D_NET, "Session closed, wakeup transaction %s\n", lstcon_rpc_trans_name(trans->tas_opc)); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 1cc703802d17..64d58d1dcb59 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -329,7 +329,7 @@ lstcon_group_move(lstcon_group_t *old, lstcon_group_t *new) while (!list_empty(&old->grp_ndl_list)) { ndl = list_entry(old->grp_ndl_list.next, - lstcon_ndlink_t, ndl_link); + lstcon_ndlink_t, ndl_link); lstcon_group_ndlink_move(old, new, ndl); } } @@ -378,9 +378,9 @@ lstcon_sesrpc_readent(int transop, srpc_msg_t *msg, rep = &msg->msg_body.dbg_reply; if (copy_to_user(&ent_up->rpe_priv[0], - &rep->dbg_timeout, sizeof(int)) || + &rep->dbg_timeout, sizeof(int)) || copy_to_user(&ent_up->rpe_payload[0], - &rep->dbg_name, LST_NAME_SIZE)) + &rep->dbg_name, LST_NAME_SIZE)) return -EFAULT; return 0; @@ -757,9 +757,9 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, nd = ndl->ndl_node; if (copy_to_user(&dents_up[count].nde_id, - &nd->nd_id, sizeof(nd->nd_id)) || + &nd->nd_id, sizeof(nd->nd_id)) || copy_to_user(&dents_up[count].nde_state, - &nd->nd_state, sizeof(nd->nd_state))) + &nd->nd_state, sizeof(nd->nd_state))) return -EFAULT; count++; @@ -812,7 +812,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp); rc = copy_to_user(gents_p, gentp, - sizeof(lstcon_ndlist_ent_t)) ? -EFAULT : 0; + sizeof(lstcon_ndlist_ent_t)) ? -EFAULT : 0; LIBCFS_FREE(gentp, sizeof(lstcon_ndlist_ent_t)); @@ -980,7 +980,7 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle); rc = copy_to_user(ent_up, entp, - sizeof(lstcon_test_batch_ent_t)) ? -EFAULT : 0; + sizeof(lstcon_test_batch_ent_t)) ? -EFAULT : 0; LIBCFS_FREE(entp, sizeof(lstcon_test_batch_ent_t)); @@ -1088,7 +1088,7 @@ lstcon_batch_destroy(lstcon_batch_t *bat) while (!list_empty(&bat->bat_test_list)) { test = list_entry(bat->bat_test_list.next, - lstcon_test_t, tes_link); + lstcon_test_t, tes_link); LASSERT(list_empty(&test->tes_trans_list)); list_del(&test->tes_link); @@ -1104,7 +1104,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); + lstcon_ndlink_t, ndl_link); list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); @@ -1112,7 +1112,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); + lstcon_ndlink_t, ndl_link); list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); @@ -1379,11 +1379,11 @@ lstcon_tsbrpc_readent(int transop, srpc_msg_t *msg, srpc_batch_reply_t *rep = &msg->msg_body.bat_reply; LASSERT(transop == LST_TRANS_TSBCLIQRY || - transop == LST_TRANS_TSBSRVQRY); + transop == LST_TRANS_TSBSRVQRY); /* positive errno, framework error code */ - if (copy_to_user(&ent_up->rpe_priv[0], - &rep->bar_active, sizeof(rep->bar_active))) + if (copy_to_user(&ent_up->rpe_priv[0], &rep->bar_active, + sizeof(rep->bar_active))) return -EFAULT; return 0; @@ -1757,7 +1757,7 @@ lstcon_session_new(char *name, int key, unsigned feats, } if (copy_to_user(sid_up, &console_session.ses_id, - sizeof(lst_sid_t)) == 0) + sizeof(lst_sid_t)) == 0) return rc; lstcon_session_end(); @@ -1786,11 +1786,11 @@ lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up, LST_NODE_STATE_COUNTER(ndl->ndl_node, entp); if (copy_to_user(sid_up, &console_session.ses_id, - sizeof(lst_sid_t)) || + sizeof(lst_sid_t)) || copy_to_user(key_up, &console_session.ses_key, - sizeof(*key_up)) || + sizeof(*key_up)) || copy_to_user(featp, &console_session.ses_features, - sizeof(*featp)) || + sizeof(*featp)) || copy_to_user(ndinfo_up, entp, sizeof(*entp)) || copy_to_user(name_up, console_session.ses_name, len)) rc = -EFAULT; @@ -1839,7 +1839,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); + lstcon_batch_t, bat_link); lstcon_batch_destroy(bat); } @@ -1847,7 +1847,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); + lstcon_group_t, grp_link); LASSERT(grp->grp_ref == 1); lstcon_group_decref(grp); @@ -1921,7 +1921,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) } if (jreq->join_sid.ses_nid != LNET_NID_ANY && - !lstcon_session_match(jreq->join_sid)) { + !lstcon_session_match(jreq->join_sid)) { jrep->join_status = EBUSY; goto out; } @@ -1934,7 +1934,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) } list_add_tail(&grp->grp_link, - &console_session.ses_grp_list); + &console_session.ses_grp_list); lstcon_group_addref(grp); } diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index 1bf707bd4c81..c61d3e777fab 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -141,7 +141,7 @@ sfw_register_test(srpc_service_t *service, sfw_test_client_ops_t *cliops) if (sfw_find_test_case(service->sv_id) != NULL) { CERROR("Failed to register test %s (%d)\n", - service->sv_name, service->sv_id); + service->sv_name, service->sv_id); return -EEXIST; } @@ -248,8 +248,8 @@ sfw_session_expired(void *data) LASSERT(sn == sfw_data.fw_session); CWARN("Session expired! sid: %s-%llu, name: %s\n", - libcfs_nid2str(sn->sn_id.ses_nid), - sn->sn_id.ses_stamp, &sn->sn_name[0]); + libcfs_nid2str(sn->sn_id.ses_nid), + sn->sn_id.ses_stamp, &sn->sn_name[0]); sn->sn_timer_active = 0; sfw_deactivate_session(); @@ -289,11 +289,10 @@ sfw_server_rpc_done(struct srpc_server_rpc *rpc) struct srpc_service *sv = rpc->srpc_scd->scd_svc; int status = rpc->srpc_status; - CDEBUG(D_NET, - "Incoming framework RPC done: service %s, peer %s, status %s:%d\n", - sv->sv_name, libcfs_id2str(rpc->srpc_peer), - swi_state2str(rpc->srpc_wi.swi_state), - status); + CDEBUG(D_NET, "Incoming framework RPC done: service %s, peer %s, status %s:%d\n", + sv->sv_name, libcfs_id2str(rpc->srpc_peer), + swi_state2str(rpc->srpc_wi.swi_state), + status); if (rpc->srpc_bulk != NULL) sfw_free_pages(rpc); @@ -307,11 +306,10 @@ sfw_client_rpc_fini(srpc_client_rpc_t *rpc) LASSERT(list_empty(&rpc->crpc_list)); LASSERT(atomic_read(&rpc->crpc_refcount) == 0); - CDEBUG(D_NET, - "Outgoing framework RPC done: service %d, peer %s, status %s:%d:%d\n", - rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), - swi_state2str(rpc->crpc_wi.swi_state), - rpc->crpc_aborted, rpc->crpc_status); + CDEBUG(D_NET, "Outgoing framework RPC done: service %d, peer %s, status %s:%d:%d\n", + rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), + swi_state2str(rpc->crpc_wi.swi_state), + rpc->crpc_aborted, rpc->crpc_status); spin_lock(&sfw_data.fw_lock); @@ -627,14 +625,14 @@ sfw_destroy_test_instance(sfw_test_instance_t *tsi) while (!list_empty(&tsi->tsi_units)) { tsu = list_entry(tsi->tsi_units.next, - sfw_test_unit_t, tsu_list); + sfw_test_unit_t, tsu_list); list_del(&tsu->tsu_list); LIBCFS_FREE(tsu, sizeof(*tsu)); } while (!list_empty(&tsi->tsi_free_rpcs)) { rpc = list_entry(tsi->tsi_free_rpcs.next, - srpc_client_rpc_t, crpc_list); + srpc_client_rpc_t, crpc_list); list_del(&rpc->crpc_list); LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); } @@ -655,7 +653,7 @@ sfw_destroy_batch(sfw_batch_t *tsb) while (!list_empty(&tsb->bat_tests)) { tsi = list_entry(tsb->bat_tests.next, - sfw_test_instance_t, tsi_list); + sfw_test_instance_t, tsi_list); list_del_init(&tsi->tsi_list); sfw_destroy_test_instance(tsi); } @@ -674,7 +672,7 @@ sfw_destroy_session(sfw_session_t *sn) while (!list_empty(&sn->sn_batches)) { batch = list_entry(sn->sn_batches.next, - sfw_batch_t, bat_list); + sfw_batch_t, bat_list); list_del_init(&batch->bat_list); sfw_destroy_batch(batch); } @@ -744,7 +742,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) LIBCFS_ALLOC(tsi, sizeof(*tsi)); if (tsi == NULL) { CERROR("Can't allocate test instance for batch: %llu\n", - tsb->bat_id.bat_id); + tsb->bat_id.bat_id); return -ENOMEM; } @@ -800,7 +798,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) if (tsu == NULL) { rc = -ENOMEM; CERROR("Can't allocate tsu for %d\n", - tsi->tsi_service); + tsi->tsi_service); goto error; } @@ -918,7 +916,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, if (!list_empty(&tsi->tsi_free_rpcs)) { /* pick request from buffer */ rpc = list_entry(tsi->tsi_free_rpcs.next, - srpc_client_rpc_t, crpc_list); + srpc_client_rpc_t, crpc_list); LASSERT(nblk == rpc->crpc_bulk.bk_niov); list_del_init(&rpc->crpc_list); } @@ -1152,8 +1150,8 @@ sfw_add_test(struct srpc_server_rpc *rpc) bat = sfw_bid2batch(request->tsr_bid); if (bat == NULL) { CERROR("Dropping RPC (%s) from %s under memory pressure.\n", - rpc->srpc_scd->scd_svc->sv_name, - libcfs_id2str(rpc->srpc_peer)); + rpc->srpc_scd->scd_svc->sv_name, + libcfs_id2str(rpc->srpc_peer)); return -ENOMEM; } @@ -1180,10 +1178,10 @@ sfw_add_test(struct srpc_server_rpc *rpc) rc = sfw_add_test_instance(bat, rpc); CDEBUG(rc == 0 ? D_NET : D_WARNING, - "%s test: sv %d %s, loop %d, concur %d, ndest %d\n", - rc == 0 ? "Added" : "Failed to add", request->tsr_service, - request->tsr_is_client ? "client" : "server", - request->tsr_loop, request->tsr_concur, request->tsr_ndest); + "%s test: sv %d %s, loop %d, concur %d, ndest %d\n", + rc == 0 ? "Added" : "Failed to add", request->tsr_service, + request->tsr_is_client ? "client" : "server", + request->tsr_loop, request->tsr_concur, request->tsr_ndest); reply->tsr_status = (rc < 0) ? -rc : rc; return 0; @@ -1398,7 +1396,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, if (nbulkiov == 0 && !list_empty(&sfw_data.fw_zombie_rpcs)) { rpc = list_entry(sfw_data.fw_zombie_rpcs.next, - srpc_client_rpc_t, crpc_list); + srpc_client_rpc_t, crpc_list); list_del(&rpc->crpc_list); srpc_init_client_rpc(rpc, peer, service, 0, 0, @@ -1653,13 +1651,13 @@ sfw_startup(void) if (session_timeout < 0) { CERROR("Session timeout must be non-negative: %d\n", - session_timeout); + session_timeout); return -EINVAL; } if (rpc_timeout < 0) { CERROR("RPC timeout must be non-negative: %d\n", - rpc_timeout); + rpc_timeout); return -EINVAL; } @@ -1697,7 +1695,7 @@ sfw_startup(void) LASSERT(rc != -EBUSY); if (rc != 0) { CWARN("Failed to add %s service: %d\n", - sv->sv_name, rc); + sv->sv_name, rc); error = rc; } } @@ -1717,7 +1715,7 @@ sfw_startup(void) LASSERT(rc != -EBUSY); if (rc != 0) { CWARN("Failed to add %s service: %d\n", - sv->sv_name, rc); + sv->sv_name, rc); error = rc; } @@ -1782,7 +1780,7 @@ sfw_shutdown(void) srpc_client_rpc_t *rpc; rpc = list_entry(sfw_data.fw_zombie_rpcs.next, - srpc_client_rpc_t, crpc_list); + srpc_client_rpc_t, crpc_list); list_del(&rpc->crpc_list); LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); @@ -1798,7 +1796,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); + sfw_test_case_t, tsc_list); srpc_wait_service_shutdown(tsc->tsc_srv_service); diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index d42653654fa8..1d23a3082a67 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -132,8 +132,8 @@ ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) 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), - reqst->pnr_seq, rpc->crpc_status); + libcfs_id2str(rpc->crpc_dest), + reqst->pnr_seq, rpc->crpc_status); return; } @@ -147,8 +147,8 @@ ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) rpc->crpc_status = -EBADMSG; atomic_inc(&sn->sn_ping_errors); CERROR("Bad magic %u from %s, %u expected.\n", - reply->pnr_magic, libcfs_id2str(rpc->crpc_dest), - LST_PING_TEST_MAGIC); + reply->pnr_magic, libcfs_id2str(rpc->crpc_dest), + LST_PING_TEST_MAGIC); return; } @@ -156,8 +156,8 @@ ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) rpc->crpc_status = -EBADMSG; atomic_inc(&sn->sn_ping_errors); CERROR("Bad seq %u from %s, %u expected.\n", - reply->pnr_seq, libcfs_id2str(rpc->crpc_dest), - reqst->pnr_seq); + reply->pnr_seq, libcfs_id2str(rpc->crpc_dest), + reqst->pnr_seq); return; } @@ -191,7 +191,7 @@ ping_server_handle(struct srpc_server_rpc *rpc) if (req->pnr_magic != LST_PING_TEST_MAGIC) { CERROR("Unexpected magic %08x from %s\n", - req->pnr_magic, libcfs_id2str(rpc->srpc_peer)); + req->pnr_magic, libcfs_id2str(rpc->srpc_peer)); return -EINVAL; } diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 14f2024938ef..6b102164cfc2 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -212,9 +212,8 @@ srpc_service_fini(struct srpc_service *svc) break; while (!list_empty(q)) { - buf = list_entry(q->next, - struct srpc_buffer, - buf_list); + buf = list_entry(q->next, struct srpc_buffer, + buf_list); list_del(&buf->buf_list); LIBCFS_FREE(buf, sizeof(*buf)); } @@ -224,8 +223,8 @@ srpc_service_fini(struct srpc_service *svc) while (!list_empty(&scd->scd_rpc_free)) { rpc = list_entry(scd->scd_rpc_free.next, - struct srpc_server_rpc, - srpc_list); + struct srpc_server_rpc, + srpc_list); list_del(&rpc->srpc_list); LIBCFS_FREE(rpc, sizeof(*rpc)); } @@ -390,9 +389,8 @@ srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf, return -ENOMEM; } - CDEBUG(D_NET, - "Posted passive RDMA: peer %s, portal %d, matchbits %#llx\n", - libcfs_id2str(peer), portal, matchbits); + CDEBUG(D_NET, "Posted passive RDMA: peer %s, portal %d, matchbits %#llx\n", + libcfs_id2str(peer), portal, matchbits); return 0; } @@ -434,8 +432,8 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, if (rc != 0) { CERROR("LNet%s(%s, %d, %lld) failed: %d\n", - ((options & LNET_MD_OP_PUT) != 0) ? "Put" : "Get", - libcfs_id2str(peer), portal, matchbits, rc); + ((options & LNET_MD_OP_PUT) != 0) ? "Put" : "Get", + libcfs_id2str(peer), portal, matchbits, rc); /* * The forthcoming unlink event will complete this operation @@ -444,9 +442,8 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, rc = LNetMDUnlink(*mdh); LASSERT(rc == 0); } else { - CDEBUG(D_NET, - "Posted active RDMA: peer %s, portal %u, matchbits %#llx\n", - libcfs_id2str(peer), portal, matchbits); + CDEBUG(D_NET, "Posted active RDMA: peer %s, portal %u, matchbits %#llx\n", + libcfs_id2str(peer), portal, matchbits); } return 0; } @@ -682,7 +679,7 @@ srpc_finish_service(struct srpc_service *sv) } rpc = list_entry(scd->scd_rpc_active.next, - struct srpc_server_rpc, srpc_list); + struct srpc_server_rpc, srpc_list); CNETERR("Active RPC %p on shutdown: sv %s, peer %s, wi %s scheduled %d running %d, ev fired %d type %d status %d lnet %d\n", rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer), swi_state2str(rpc->srpc_wi.swi_state), @@ -914,9 +911,9 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) rpc->srpc_status = status; CDEBUG_LIMIT(status == 0 ? D_NET : D_NETERROR, - "Server RPC %p done: service %s, peer %s, status %s:%d\n", - rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer), - swi_state2str(rpc->srpc_wi.swi_state), status); + "Server RPC %p done: service %s, peer %s, status %s:%d\n", + rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer), + swi_state2str(rpc->srpc_wi.swi_state), status); if (status != 0) { spin_lock(&srpc_data.rpc_glock); @@ -952,7 +949,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); + srpc_buffer_t, buf_list); list_del(&buffer->buf_list); srpc_init_server_rpc(rpc, scd, buffer); @@ -1085,8 +1082,8 @@ srpc_client_rpc_expired(void *data) srpc_client_rpc_t *rpc = data; CWARN("Client RPC expired: service %d, peer %s, timeout %d.\n", - rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), - rpc->crpc_timeout); + rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), + rpc->crpc_timeout); spin_lock(&rpc->crpc_lock); @@ -1159,9 +1156,9 @@ srpc_client_rpc_done(srpc_client_rpc_t *rpc, int status) srpc_del_client_rpc_timer(rpc); CDEBUG_LIMIT((status == 0) ? D_NET : D_NETERROR, - "Client RPC done: service %d, peer %s, status %s:%d:%d\n", - rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), - swi_state2str(wi->swi_state), rpc->crpc_aborted, status); + "Client RPC done: service %d, peer %s, status %s:%d:%d\n", + rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), + swi_state2str(wi->swi_state), rpc->crpc_aborted, status); /* * No one can schedule me now since: @@ -1317,9 +1314,9 @@ abort: srpc_client_rpc_t * 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) + int nbulkiov, int bulklen, + void (*rpc_done)(srpc_client_rpc_t *), + void (*rpc_fini)(srpc_client_rpc_t *), void *priv) { srpc_client_rpc_t *rpc; @@ -1343,10 +1340,9 @@ srpc_abort_rpc(srpc_client_rpc_t *rpc, int why) rpc->crpc_closed) /* callback imminent */ return; - CDEBUG(D_NET, - "Aborting RPC: service %d, peer %s, state %s, why %d\n", - rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), - swi_state2str(rpc->crpc_wi.swi_state), why); + CDEBUG(D_NET, "Aborting RPC: service %d, peer %s, state %s, why %d\n", + rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), + swi_state2str(rpc->crpc_wi.swi_state), why); rpc->crpc_aborted = 1; rpc->crpc_status = why; @@ -1362,8 +1358,8 @@ srpc_post_rpc(srpc_client_rpc_t *rpc) LASSERT(srpc_data.rpc_state == SRPC_STATE_RUNNING); CDEBUG(D_NET, "Posting RPC: peer %s, service %d, timeout %d\n", - libcfs_id2str(rpc->crpc_dest), rpc->crpc_service, - rpc->crpc_timeout); + libcfs_id2str(rpc->crpc_dest), rpc->crpc_service, + rpc->crpc_timeout); srpc_add_client_rpc_timer(rpc); swi_schedule_workitem(&rpc->crpc_wi); @@ -1485,9 +1481,9 @@ srpc_lnet_ev_handler(lnet_event_t *ev) LASSERT(ev->unlinked); LASSERT(ev->type == LNET_EVENT_PUT || - ev->type == LNET_EVENT_UNLINK); + ev->type == LNET_EVENT_UNLINK); LASSERT(ev->type != LNET_EVENT_UNLINK || - sv->sv_shuttingdown); + sv->sv_shuttingdown); buffer = container_of(ev->md.start, srpc_buffer_t, buf_msg); buffer->buf_peer = ev->initiator; @@ -1544,17 +1540,17 @@ srpc_lnet_ev_handler(lnet_event_t *ev) if (!list_empty(&scd->scd_rpc_free)) { srpc = list_entry(scd->scd_rpc_free.next, - struct srpc_server_rpc, - srpc_list); + struct srpc_server_rpc, + srpc_list); list_del(&srpc->srpc_list); srpc_init_server_rpc(srpc, scd, buffer); list_add_tail(&srpc->srpc_list, - &scd->scd_rpc_active); + &scd->scd_rpc_active); swi_schedule_workitem(&srpc->srpc_wi); } else { list_add_tail(&buffer->buf_list, - &scd->scd_buf_blocked); + &scd->scd_buf_blocked); } spin_unlock(&scd->scd_lock); @@ -1566,8 +1562,8 @@ srpc_lnet_ev_handler(lnet_event_t *ev) case SRPC_BULK_GET_RPLD: LASSERT(ev->type == LNET_EVENT_SEND || - ev->type == LNET_EVENT_REPLY || - ev->type == LNET_EVENT_UNLINK); + ev->type == LNET_EVENT_REPLY || + ev->type == LNET_EVENT_UNLINK); if (!ev->unlinked) break; /* wait for final event */ @@ -1669,8 +1665,8 @@ srpc_shutdown(void) srpc_service_t *sv = srpc_data.rpc_services[i]; LASSERTF(sv == NULL, - "service not empty: id %d, name %s\n", - i, sv->sv_name); + "service not empty: id %d, name %s\n", + i, sv->sv_name); } spin_unlock(&srpc_data.rpc_glock); -- cgit From 0eee67781c98a47ba579d92159dcd39ce2cee639 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:02 -0500 Subject: staging: lustre: remove unnecessary parentheses around LNet function pointer No need for the parentheses around any function pointer. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 2 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 4 ++-- drivers/staging/lustre/lnet/lnet/lib-move.c | 12 ++++++------ drivers/staging/lustre/lnet/lnet/router.c | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index fbcbb97dda1f..cbf5d0a495d2 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -2185,7 +2185,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) rej.ibr_why = IBLND_REJECT_FATAL; rej.ibr_cp.ibcp_max_msg_size = IBLND_MSG_SIZE; - peer_addr = (struct sockaddr_in *)&(cmid->route.addr.dst_addr); + peer_addr = (struct sockaddr_in *)&cmid->route.addr.dst_addr; if (*kiblnd_tunables.kib_require_priv_port && ntohs(peer_addr->sin_port) >= PROT_SOCK) { __u32 ip = ntohl(peer_addr->sin_addr.s_addr); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index aeef4803ee60..e59fbfb66877 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -935,7 +935,7 @@ lnet_shutdown_lndnis(void) islo = ni->ni_lnd->lnd_type == LOLND; LASSERT(!in_interrupt()); - (ni->ni_lnd->lnd_shutdown)(ni); + ni->ni_lnd->lnd_shutdown(ni); /* * can't deref lnd anymore now; it might have unregistered @@ -1023,7 +1023,7 @@ lnet_startup_lndnis(void) ni->ni_lnd = lnd; - rc = (lnd->lnd_startup)(ni); + rc = lnd->lnd_startup(ni); mutex_unlock(&the_lnet.ln_lnd_mutex); diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 7e1ef1865e5c..afc4522ea77d 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -599,8 +599,8 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, } } - rc = (ni->ni_lnd->lnd_recv)(ni, private, msg, delayed, - niov, iov, kiov, offset, mlen, rlen); + rc = ni->ni_lnd->lnd_recv(ni, private, msg, delayed, + niov, iov, kiov, offset, mlen, rlen); if (rc < 0) lnet_finalize(ni, msg, rc); } @@ -655,7 +655,7 @@ lnet_ni_send(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(LNET_NETTYP(LNET_NIDNET(ni->ni_nid)) == LOLND || (msg->msg_txcredit && msg->msg_peertxcredit)); - rc = (ni->ni_lnd->lnd_send)(ni, priv, msg); + rc = ni->ni_lnd->lnd_send(ni, priv, msg); if (rc < 0) lnet_finalize(ni, msg, rc); } @@ -671,8 +671,8 @@ lnet_ni_eager_recv(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(ni->ni_lnd->lnd_eager_recv != NULL); msg->msg_rx_ready_delay = 1; - rc = (ni->ni_lnd->lnd_eager_recv)(ni, msg->msg_private, msg, - &msg->msg_private); + rc = ni->ni_lnd->lnd_eager_recv(ni, msg->msg_private, msg, + &msg->msg_private); if (rc != 0) { CERROR("recv from %s / send to %s aborted: eager_recv failed %d\n", libcfs_nid2str(msg->msg_rxpeer->lp_nid), @@ -693,7 +693,7 @@ lnet_ni_query_locked(lnet_ni_t *ni, lnet_peer_t *lp) LASSERT(ni->ni_lnd->lnd_query != NULL); lnet_net_unlock(lp->lp_cpt); - (ni->ni_lnd->lnd_query)(ni, lp->lp_nid, &last_alive); + ni->ni_lnd->lnd_query(ni, lp->lp_nid, &last_alive); lnet_net_lock(lp->lp_cpt); lp->lp_last_query = cfs_time_current(); diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 754f7f071bbe..e447b1a13a65 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -157,7 +157,7 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) * A new notification could happen now; I'll handle it * when control returns to me */ - (ni->ni_lnd->lnd_notify)(ni, lp->lp_nid, alive); + ni->ni_lnd->lnd_notify(ni, lp->lp_nid, alive); lnet_net_lock(lp->lp_cpt); } @@ -389,7 +389,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, /* XXX Assume alive */ if (ni->ni_lnd->lnd_notify != NULL) - (ni->ni_lnd->lnd_notify)(ni, gateway, 1); + ni->ni_lnd->lnd_notify(ni, gateway, 1); lnet_net_lock(LNET_LOCK_EX); } -- cgit From e767c84028677f56035eac1004532c8b9c12b5e1 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:03 -0500 Subject: staging: lustre: remove unnecessary blank lines reported by checkpatch.pl Remove any useless blank lines reported by checkpatch.pl for LNet layer. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/nidstr.h | 3 +++ drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 6 ------ drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 2 -- drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c | 6 ------ drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 4 ---- drivers/staging/lustre/lnet/lnet/acceptor.c | 2 -- drivers/staging/lustre/lnet/lnet/api-ni.c | 1 - drivers/staging/lustre/lnet/lnet/config.c | 6 ------ drivers/staging/lustre/lnet/lnet/lib-md.c | 1 - drivers/staging/lustre/lnet/lnet/lib-move.c | 2 -- drivers/staging/lustre/lnet/lnet/lib-msg.c | 1 - drivers/staging/lustre/lnet/lnet/router.c | 1 - drivers/staging/lustre/lnet/selftest/brw_test.c | 1 - drivers/staging/lustre/lnet/selftest/console.c | 1 - 14 files changed, 3 insertions(+), 34 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/nidstr.h b/drivers/staging/lustre/include/linux/lnet/nidstr.h index 9a705e1d468c..937fcc9e4a30 100644 --- a/drivers/staging/lustre/include/linux/lnet/nidstr.h +++ b/drivers/staging/lustre/include/linux/lnet/nidstr.h @@ -69,6 +69,7 @@ static inline char *libcfs_lnd2str(__u32 lnd) return libcfs_lnd2str_r(lnd, libcfs_next_nidstring(), LNET_NIDSTR_SIZE); } + int libcfs_str2lnd(const char *str); char *libcfs_net2str_r(__u32 net, char *buf, size_t buf_size); static inline char *libcfs_net2str(__u32 net) @@ -76,12 +77,14 @@ static inline char *libcfs_net2str(__u32 net) return libcfs_net2str_r(net, libcfs_next_nidstring(), LNET_NIDSTR_SIZE); } + char *libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size); static inline char *libcfs_nid2str(lnet_nid_t nid) { return libcfs_nid2str_r(nid, libcfs_next_nidstring(), LNET_NIDSTR_SIZE); } + __u32 libcfs_str2net(const char *str); lnet_nid_t libcfs_str2nid(const char *str); int libcfs_str2anynid(lnet_nid_t *nid, const char *str); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 8ad128c9c9df..09eaecd536d2 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -399,7 +399,6 @@ kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid) kib_peer_t *peer; list_for_each(tmp, peer_list) { - peer = list_entry(tmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || /* creating conns */ @@ -439,9 +438,7 @@ static int kiblnd_get_peer_info(lnet_ni_t *ni, int index, read_lock_irqsave(&kiblnd_data.kib_global_lock, flags); for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) { - list_for_each(ptmp, &kiblnd_data.kib_peers[i]) { - peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || peer->ibp_accepting > 0 || @@ -554,7 +551,6 @@ static kib_conn_t *kiblnd_get_conn_by_idx(lnet_ni_t *ni, int index) for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) { list_for_each(ptmp, &kiblnd_data.kib_peers[i]) { - peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || peer->ibp_accepting > 0 || @@ -992,7 +988,6 @@ static int kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid) for (i = lo; i <= hi; i++) { list_for_each_safe(ptmp, pnxt, &kiblnd_data.kib_peers[i]) { - peer = list_entry(ptmp, kib_peer_t, ibp_list); LASSERT(peer->ibp_connecting > 0 || peer->ibp_accepting > 0 || @@ -1584,7 +1579,6 @@ int kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages, CDEBUG(D_NET, "Another thread is allocating new FMR pool, waiting for her to complete\n"); schedule(); goto again; - } if (time_before(cfs_time_current(), fps->fps_next_retry)) { diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index cbf5d0a495d2..6b5a0b3d6fb2 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -2287,7 +2287,6 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) rej.ibr_why = IBLND_REJECT_RDMA_FRAGS; goto failed; - } if (reqmsg->ibm_u.connparams.ibcp_max_msg_size > IBLND_MSG_SIZE) { @@ -3128,7 +3127,6 @@ kiblnd_connd(void *arg) spin_lock_irqsave(&kiblnd_data.kib_connd_lock, flags); while (!kiblnd_data.kib_shutdown) { - dropped_lock = 0; if (!list_empty(&kiblnd_data.kib_connd_zombies)) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 6bf92fd0bcb8..c428684ef93e 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -182,7 +182,6 @@ ksocknal_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id) ksock_peer_t *peer; list_for_each(tmp, peer_list) { - peer = list_entry(tmp, ksock_peer_t, ksnp_list); LASSERT(!peer->ksnp_closing); @@ -264,7 +263,6 @@ ksocknal_get_peer_info(lnet_ni_t *ni, int index, read_lock(&ksocknal_data.ksnd_global_lock); for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) { - list_for_each(ptmp, &ksocknal_data.ksnd_peers[i]) { peer = list_entry(ptmp, ksock_peer_t, ksnp_list); @@ -1015,7 +1013,6 @@ ksocknal_connecting(ksock_peer_t *peer, __u32 ipaddr) ksock_route_t *route; list_for_each_entry(route, &peer->ksnp_routes, ksnr_list) { - if (route->ksnr_ipaddr == ipaddr) return route->ksnr_connecting; } @@ -1787,7 +1784,6 @@ ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr) for (i = lo; i <= hi; i++) { list_for_each_safe(ptmp, pnxt, &ksocknal_data.ksnd_peers[i]) { - peer = list_entry(ptmp, ksock_peer_t, ksnp_list); if (!((id.nid == LNET_NID_ANY || id.nid == peer->ksnp_id.nid) && @@ -2330,7 +2326,6 @@ ksocknal_base_shutdown(void) continue; for (j = 0; j < info->ksi_nthreads_max; j++) { - sched = &info->ksi_scheds[j]; LASSERT(list_empty( &sched->kss_tx_conns)); @@ -2387,7 +2382,6 @@ ksocknal_base_shutdown(void) static __u64 ksocknal_new_incarnation(void) { - /* The incarnation number is the time this module loaded and it * identifies this particular instance of the socknal. */ diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 1243f9270d6d..c82ed27be9d7 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -589,7 +589,6 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx) static void ksocknal_launch_connection_locked (ksock_route_t *route) { - /* called holding write lock on ksnd_global_lock */ LASSERT(!route->ksnr_scheduled); @@ -2147,7 +2146,6 @@ ksocknal_connd_get_route_locked(signed long *timeout_p) /* connd_routes can contain both pending and ordinary routes */ list_for_each_entry(route, &ksocknal_data.ksnd_connd_routes, ksnr_connd_list) { - if (route->ksnr_retry_interval == 0 || cfs_time_aftereq(now, route->ksnr_timeout)) return route; @@ -2495,7 +2493,6 @@ ksocknal_check_peer_timeouts (int idx) if (cfs_time_aftereq(cfs_time_current(), tx->tx_deadline)) { - ksocknal_peer_addref(peer); read_unlock(&ksocknal_data.ksnd_global_lock); @@ -2569,7 +2566,6 @@ ksocknal_reaper (void *arg) spin_lock_bh(&ksocknal_data.ksnd_reaper_lock); while (!ksocknal_data.ksnd_shuttingdown) { - if (!list_empty (&ksocknal_data.ksnd_deathrow_conns)) { conn = list_entry (ksocknal_data. \ ksnd_deathrow_conns.next, diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index b330f6476f32..8c95cc5bc889 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -223,7 +223,6 @@ lnet_accept(struct socket *sock, __u32 magic) LASSERT(rc == 0); /* we succeeded before */ if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) { - if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) { /* * future version compatibility! @@ -363,7 +362,6 @@ lnet_acceptor(void *arg) return rc; while (!lnet_acceptor_state.pta_shutdown) { - rc = lnet_sock_accept(&newsock, lnet_acceptor_state.pta_sock); if (rc != 0) { if (rc != -EAGAIN) { diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index e59fbfb66877..78188a901753 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -340,7 +340,6 @@ lnet_counters_get(lnet_counters_t *counters) counters->recv_length += ctr->recv_length; counters->route_length += ctr->route_length; counters->drop_length += ctr->drop_length; - } lnet_net_unlock(LNET_LOCK_EX); } diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 5339dee56840..695db24d451b 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -221,7 +221,6 @@ lnet_parse_networks(struct list_head *nilist, char *networks) * NB we don't check interface conflicts here; it's the LNDs * responsibility (if it cares at all) */ - if (square != NULL && (comma == NULL || square < comma)) { /* * i.e: o2ib0(ib0)[1,2], number between square @@ -251,7 +250,6 @@ lnet_parse_networks(struct list_head *nilist, char *networks) if (bracket == NULL || (comma != NULL && comma < bracket)) { - /* no interface list specified */ if (comma != NULL) @@ -528,7 +526,6 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) goto failed; for (parsed = sep; parsed < sep2; parsed = enditem) { - enditem = ++parsed; while (enditem < sep2 && *enditem != ',') enditem++; @@ -538,9 +535,7 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) if (sscanf(parsed, "%d-%d/%d%n", &lo, &hi, &stride, &scanned) < 3) { - if (sscanf(parsed, "%d-%d%n", &lo, &hi, &scanned) < 2) { - /* simple string enumeration */ if (lnet_expand1tb(&pending, str, sep, sep2, parsed, @@ -564,7 +559,6 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) goto failed; for (i = lo; i <= hi; i += stride) { - snprintf(num, sizeof(num), "%d", i); nob = strlen(num); if (nob + 1 == sizeof(num)) diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index fef517dcf92a..4d59bac199f5 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -106,7 +106,6 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_flags = (unlink == LNET_UNLINK) ? LNET_MD_FLAG_AUTO_UNLINK : 0; if ((umd->options & LNET_MD_IOVEC) != 0) { - if ((umd->options & LNET_MD_KIOV) != 0) /* Can't specify both */ return -EINVAL; diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index afc4522ea77d..12bb983fd991 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -1726,7 +1726,6 @@ lnet_print_hdr(lnet_hdr_t *hdr) hdr->msg.reply.dst_wmd.wh_object_cookie, hdr->payload_length); } - } int @@ -1866,7 +1865,6 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, /* msg zeroed in lnet_msg_alloc; * i.e. flags all clear, pointers NULL etc */ - msg->msg_type = type; msg->msg_private = private; msg->msg_receiving = 1; diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index a680e6827370..eb4aa3430105 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -74,7 +74,6 @@ lnet_build_msg_event(lnet_msg_t *msg, lnet_event_kind_t ev_type) ev->initiator.nid = LNET_NID_ANY; ev->initiator.pid = the_lnet.ln_pid; ev->sender = LNET_NID_ANY; - } else { /* event for passive message */ ev->target.pid = hdr->dest_pid; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index e447b1a13a65..65f951ca198b 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -353,7 +353,6 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, CERROR("Error %d creating route %s %d %s\n", rc, libcfs_net2str(net), hops, libcfs_nid2str(gateway)); - return rc; } diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 88fb54dc4050..4af91cb01bae 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -505,7 +505,6 @@ void brw_init_test_client(void) srpc_service_t brw_test_service; void brw_init_test_service(void) { - brw_test_service.sv_id = SRPC_SERVICE_BRW; brw_test_service.sv_name = "brw_test"; brw_test_service.sv_handler = brw_server_handle; diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 64d58d1dcb59..ab0a3f7cf366 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -967,7 +967,6 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, 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; entp->u.tbe_test.tse_concur = test->tes_concur; -- cgit From 51078e25c141fbd79aaf3535584d1f47d28228c1 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:04 -0500 Subject: staging: lustre: add missing spaces for LNet layer reported by checkpatch.pl Add missing spaces in the code reported by checkpatch.pl. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lib-types.h | 2 +- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 2 +- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h | 4 ++-- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 2 +- drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c | 12 ++++++------ drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 6 +++--- .../staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c | 2 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 2 +- drivers/staging/lustre/lnet/lnet/config.c | 15 +++++++-------- drivers/staging/lustre/lnet/lnet/lib-eq.c | 1 - drivers/staging/lustre/lnet/lnet/lib-socket.c | 4 ++-- drivers/staging/lustre/lnet/lnet/nidstrings.c | 2 +- 12 files changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 55d9d4311f0c..42f08c889456 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -112,7 +112,7 @@ typedef struct lnet_libhandle { } lnet_libhandle_t; #define lh_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(char *)(&((type *)0)->member))) + ((type *)((char *)(ptr) - (char *)(&((type *)0)->member))) typedef struct lnet_eq { struct list_head eq_list; diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 09eaecd536d2..812d9b53c648 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -1400,7 +1400,7 @@ static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, kib_dev_t *dev = fps->fps_net->ibn_dev; kib_fmr_pool_t *fpo; struct ib_fmr_pool_param param = { - .max_pages_per_fmr = LNET_MAX_PAYLOAD/PAGE_SIZE, + .max_pages_per_fmr = LNET_MAX_PAYLOAD / PAGE_SIZE, .page_shift = PAGE_SHIFT, .access = (IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE), diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index dbbbf5515b6b..288f0d2fe0e8 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -146,7 +146,7 @@ kiblnd_concurrent_sends_v1(void) #define IBLND_OOB_CAPABLE(v) ((v) != IBLND_MSG_VERSION_1) #define IBLND_OOB_MSGS(v) (IBLND_OOB_CAPABLE(v) ? 2 : 0) -#define IBLND_MSG_SIZE (4<<10) /* max size of queued messages (inc hdr) */ +#define IBLND_MSG_SIZE (4 << 10) /* max size of queued messages (inc hdr) */ #define IBLND_MAX_RDMA_FRAGS LNET_MAX_IOV /* max # of fragments supported */ #define IBLND_CFG_RDMA_FRAGS (*kiblnd_tunables.kib_map_on_demand != 0 ? \ *kiblnd_tunables.kib_map_on_demand : \ @@ -691,7 +691,7 @@ kiblnd_send_keepalive(kib_conn_t *conn) { return (*kiblnd_tunables.kib_keepalive > 0) && cfs_time_after(jiffies, conn->ibc_last_send + - *kiblnd_tunables.kib_keepalive*HZ); + *kiblnd_tunables.kib_keepalive * HZ); } static inline int diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 6b5a0b3d6fb2..46d181095311 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1217,7 +1217,7 @@ static int kiblnd_resolve_addr(struct rdma_cm_id *cmid, } /* look for a free privileged port */ - for (port = PROT_SOCK-1; port > 0; port--) { + for (port = PROT_SOCK - 1; port > 0; port--) { srcaddr->sin_port = htons(port); rc = rdma_resolve_addr(cmid, (struct sockaddr *)srcaddr, diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index c428684ef93e..4ab7f298f8e4 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -357,7 +357,7 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn) iface->ksni_nroutes++; } - route->ksnr_connected |= (1<ksnr_connected |= (1 << type); route->ksnr_conn_count++; /* @@ -839,7 +839,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips) best_iface->ksni_npeers++; ip = best_iface->ksni_ipaddr; peer->ksnp_passive_ips[i] = ip; - peer->ksnp_n_passive_ips = i+1; + peer->ksnp_n_passive_ips = i + 1; } /* mark the best matching peer IP used */ @@ -2047,8 +2047,8 @@ ksocknal_peer_del_interface_locked(ksock_peer_t *peer, __u32 ipaddr) for (i = 0; i < peer->ksnp_n_passive_ips; i++) if (peer->ksnp_passive_ips[i] == ipaddr) { - for (j = i+1; j < peer->ksnp_n_passive_ips; j++) - peer->ksnp_passive_ips[j-1] = + for (j = i + 1; j < peer->ksnp_n_passive_ips; j++) + peer->ksnp_passive_ips[j - 1] = peer->ksnp_passive_ips[j]; peer->ksnp_n_passive_ips--; break; @@ -2099,8 +2099,8 @@ ksocknal_del_interface(lnet_ni_t *ni, __u32 ipaddress) rc = 0; - for (j = i+1; j < net->ksnn_ninterfaces; j++) - net->ksnn_interfaces[j-1] = + for (j = i + 1; j < net->ksnn_ninterfaces; j++) + net->ksnn_interfaces[j - 1] = net->ksnn_interfaces[j]; net->ksnn_ninterfaces--; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index c82ed27be9d7..31b8d46f56a1 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -1960,7 +1960,7 @@ ksocknal_connect (ksock_route_t *route) * so min_reconnectms should be good heuristic */ route->ksnr_retry_interval = - cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms)/1000; + cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms) / 1000; route->ksnr_timeout = cfs_time_add(cfs_time_current(), route->ksnr_retry_interval); } @@ -1981,10 +1981,10 @@ ksocknal_connect (ksock_route_t *route) route->ksnr_retry_interval *= 2; route->ksnr_retry_interval = max(route->ksnr_retry_interval, - cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms)/1000); + cfs_time_seconds(*ksocknal_tunables.ksnd_min_reconnectms) / 1000); route->ksnr_retry_interval = min(route->ksnr_retry_interval, - cfs_time_seconds(*ksocknal_tunables.ksnd_max_reconnectms)/1000); + cfs_time_seconds(*ksocknal_tunables.ksnd_max_reconnectms) / 1000); LASSERT (route->ksnr_retry_interval != 0); route->ksnr_timeout = cfs_time_add(cfs_time_current(), diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c index 374ba6793784..77ce597df98c 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_modparams.c @@ -74,7 +74,7 @@ static int typed_conns = 1; module_param(typed_conns, int, 0444); MODULE_PARM_DESC(typed_conns, "use different sockets for bulk"); -static int min_bulk = 1<<10; +static int min_bulk = 1 << 10; module_param(min_bulk, int, 0644); MODULE_PARM_DESC(min_bulk, "smallest 'large' message"); diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index 78188a901753..f7d53cdfbd99 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -1394,7 +1394,7 @@ LNetCtl(unsigned int cmd, void *arg) id.pid = data->ioc_u32[0]; rc = lnet_ping(id, data->ioc_u32[1], /* timeout */ data->ioc_pbuf1, - data->ioc_plen1/sizeof(lnet_process_id_t)); + data->ioc_plen1 / sizeof(lnet_process_id_t)); if (rc < 0) return rc; data->ioc_count = rc; diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index 695db24d451b..e30a959ffc03 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -44,8 +44,8 @@ struct lnet_text_buf { /* tmp struct for parsing routes */ }; static int lnet_tbnob; /* track text buf allocation */ -#define LNET_MAX_TEXTBUF_NOB (64<<10) /* bound allocation */ -#define LNET_SINGLE_TEXTBUF_NOB (4<<10) +#define LNET_MAX_TEXTBUF_NOB (64 << 10) /* bound allocation */ +#define LNET_SINGLE_TEXTBUF_NOB (4 << 10) static void lnet_syntax(char *name, char *str, int offset, int width) @@ -54,9 +54,9 @@ lnet_syntax(char *name, char *str, int offset, int width) static char dashes[LNET_SINGLE_TEXTBUF_NOB]; memset(dots, '.', sizeof(dots)); - dots[sizeof(dots)-1] = 0; + dots[sizeof(dots) - 1] = 0; memset(dashes, '-', sizeof(dashes)); - dashes[sizeof(dashes)-1] = 0; + dashes[sizeof(dashes) - 1] = 0; LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name, str); LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n", @@ -492,7 +492,7 @@ lnet_expand1tb(struct list_head *list, memcpy(ltb->ltb_text, str, len1); memcpy(<b->ltb_text[len1], item, itemlen); - memcpy(<b->ltb_text[len1+itemlen], sep2 + 1, len2); + memcpy(<b->ltb_text[len1 + itemlen], sep2 + 1, len2); ltb->ltb_text[len1 + itemlen + len2] = 0; list_add_tail(<b->ltb_list, list); @@ -542,7 +542,6 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) (int)(enditem - parsed)) != 0) { goto failed; } - continue; } @@ -605,7 +604,7 @@ lnet_parse_priority(char *str, unsigned int *priority, char **token) } len = strlen(sep + 1); - if ((sscanf((sep+1), "%u%n", priority, &nob) < 1) || (len != nob)) { + if ((sscanf((sep + 1), "%u%n", priority, &nob) < 1) || (len != nob)) { /* * Update the caller's token pointer so it treats the found * priority as the token to report in the error message. @@ -1020,7 +1019,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) tb = list_entry(raw_entries.next, struct lnet_text_buf, ltb_list); strncpy(source, tb->ltb_text, sizeof(source)); - source[sizeof(source)-1] = '\0'; + source[sizeof(source) - 1] = '\0'; /* replace ltb_text with the network(s) add on match */ rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip); diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index e543cb4b11ec..683eb45aecf5 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -332,7 +332,6 @@ __must_hold(&the_lnet.ln_eq_wait_lock) if (tms < 0) { schedule(); - } else { now = jiffies; schedule_timeout(msecs_to_jiffies(tms)); diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 0b3ef1740b26..f775879b3396 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -159,7 +159,7 @@ lnet_ipif_enumerate(char ***namesp) for (;;) { if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) { toobig = 1; - nalloc = PAGE_CACHE_SIZE/sizeof(*ifr); + nalloc = PAGE_CACHE_SIZE / sizeof(*ifr); CWARN("Too many interfaces: only enumerating first %d\n", nalloc); } @@ -183,7 +183,7 @@ lnet_ipif_enumerate(char ***namesp) LASSERT(rc == 0); - nfound = ifc.ifc_len/sizeof(*ifr); + nfound = ifc.ifc_len / sizeof(*ifr); LASSERT(nfound <= nalloc); if (nfound < nalloc || toobig) diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index 00de4faf2b82..449efc7b49ca 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -808,7 +808,7 @@ libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) n == nob && (a & ~0xff) == 0 && (b & ~0xff) == 0 && (c & ~0xff) == 0 && (d & ~0xff) == 0) { - *addr = ((a<<24)|(b<<16)|(c<<8)|d); + *addr = ((a << 24) | (b << 16) | (c << 8) | d); return 1; } -- cgit From d3d3d37a6069b343359464d32fc0d6f4fc0f3873 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:05 -0500 Subject: staging: lustre: don't set more than one variable per line in LNet layer Cleanup all occurances of more than one variable being set per line as reported by checkpatch.pl. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/include/linux/lnet/lib-lnet.h | 3 ++- drivers/staging/lustre/include/linux/lnet/socklnd.h | 3 ++- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 10 ++++++---- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 6 ++---- drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c | 17 ++++++++++------- .../staging/lustre/lnet/klnds/socklnd/socklnd_proto.c | 12 ++++++++---- drivers/staging/lustre/lnet/lnet/config.c | 3 ++- drivers/staging/lustre/lnet/lnet/lib-md.c | 9 ++++++--- drivers/staging/lustre/lnet/lnet/lib-move.c | 9 ++++++--- drivers/staging/lustre/lnet/lnet/peer.c | 6 +++--- drivers/staging/lustre/lnet/lnet/router.c | 3 ++- drivers/staging/lustre/lnet/selftest/conrpc.c | 3 ++- drivers/staging/lustre/lnet/selftest/selftest.h | 4 ++-- 13 files changed, 53 insertions(+), 35 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index c3bf5e8a3324..b8be9b6c1c03 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -681,7 +681,8 @@ void lnet_debug_peer(lnet_nid_t nid); static inline void lnet_peer_set_alive(lnet_peer_t *lp) { - lp->lp_last_alive = lp->lp_last_query = jiffies; + lp->lp_last_query = jiffies; + lp->lp_last_alive = jiffies; if (!lp->lp_alive) lnet_notify_locked(lp, 0, 1, lp->lp_last_alive); } diff --git a/drivers/staging/lustre/include/linux/lnet/socklnd.h b/drivers/staging/lustre/include/linux/lnet/socklnd.h index 3df5065b488d..bc32403f4a08 100644 --- a/drivers/staging/lustre/include/linux/lnet/socklnd.h +++ b/drivers/staging/lustre/include/linux/lnet/socklnd.h @@ -85,7 +85,8 @@ socklnd_init_msg(ksock_msg_t *msg, int type) { msg->ksm_csum = 0; msg->ksm_type = type; - msg->ksm_zc_cookies[0] = msg->ksm_zc_cookies[1] = 0; + msg->ksm_zc_cookies[0] = 0; + msg->ksm_zc_cookies[1] = 0; } #define KSOCK_MSG_NOOP 0xC0 /* ksm_u empty */ diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index 812d9b53c648..db551e4d4382 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -500,7 +500,8 @@ static int kiblnd_del_peer(lnet_ni_t *ni, lnet_nid_t nid) write_lock_irqsave(&kiblnd_data.kib_global_lock, flags); if (nid != LNET_NID_ANY) { - lo = hi = kiblnd_nid2peerlist(nid) - kiblnd_data.kib_peers; + lo = kiblnd_nid2peerlist(nid) - kiblnd_data.kib_peers; + hi = kiblnd_nid2peerlist(nid) - kiblnd_data.kib_peers; } else { lo = 0; hi = kiblnd_data.kib_peer_hash_size - 1; @@ -979,9 +980,10 @@ static int kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid) write_lock_irqsave(&kiblnd_data.kib_global_lock, flags); - if (nid != LNET_NID_ANY) - lo = hi = kiblnd_nid2peerlist(nid) - kiblnd_data.kib_peers; - else { + if (nid != LNET_NID_ANY) { + lo = kiblnd_nid2peerlist(nid) - kiblnd_data.kib_peers; + hi = kiblnd_nid2peerlist(nid) - kiblnd_data.kib_peers; + } else { lo = 0; hi = kiblnd_data.kib_peer_hash_size - 1; } diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 46d181095311..14938c361741 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -1061,8 +1061,8 @@ kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, struct ib_sge *sge = &tx->tx_sge[0]; struct ib_rdma_wr *wrq = &tx->tx_wrq[0], *next; int rc = resid; - int srcidx; - int dstidx; + int srcidx = 0; + int dstidx = 0; int wrknob; LASSERT(!in_interrupt()); @@ -1070,8 +1070,6 @@ kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, LASSERT(type == IBLND_MSG_GET_DONE || type == IBLND_MSG_PUT_DONE); - srcidx = dstidx = 0; - while (resid > 0) { if (srcidx >= srcrd->rd_nfrags) { CERROR("Src buffer exhausted: %d frags\n", srcidx); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 4ab7f298f8e4..7c9525da0058 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -582,9 +582,10 @@ ksocknal_del_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip) write_lock_bh(&ksocknal_data.ksnd_global_lock); - if (id.nid != LNET_NID_ANY) - lo = hi = (int)(ksocknal_nid2peerlist(id.nid) - ksocknal_data.ksnd_peers); - else { + if (id.nid != LNET_NID_ANY) { + lo = (int)(ksocknal_nid2peerlist(id.nid) - ksocknal_data.ksnd_peers); + hi = (int)(ksocknal_nid2peerlist(id.nid) - ksocknal_data.ksnd_peers); + } else { lo = 0; hi = ksocknal_data.ksnd_peer_hash_size - 1; } @@ -1774,9 +1775,10 @@ ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr) write_lock_bh(&ksocknal_data.ksnd_global_lock); - if (id.nid != LNET_NID_ANY) - lo = hi = (int)(ksocknal_nid2peerlist(id.nid) - ksocknal_data.ksnd_peers); - else { + if (id.nid != LNET_NID_ANY) { + lo = (int)(ksocknal_nid2peerlist(id.nid) - ksocknal_data.ksnd_peers); + hi = (int)(ksocknal_nid2peerlist(id.nid) - ksocknal_data.ksnd_peers); + } else { lo = 0; hi = ksocknal_data.ksnd_peer_hash_size - 1; } @@ -1938,7 +1940,8 @@ static int ksocknal_push(lnet_ni_t *ni, lnet_process_id_t id) start = &ksocknal_data.ksnd_peers[0]; end = &ksocknal_data.ksnd_peers[hsize - 1]; } else { - start = end = ksocknal_nid2peerlist(id.nid); + start = ksocknal_nid2peerlist(id.nid); + end = ksocknal_nid2peerlist(id.nid); } for (tmp = start; tmp <= end; tmp++) { diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index 2fe23d434cc4..c59ddc250c59 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -719,7 +719,8 @@ ksocknal_pack_msg_v1(ksock_tx_t *tx) tx->tx_iov[0].iov_base = &tx->tx_lnetmsg->msg_hdr; tx->tx_iov[0].iov_len = sizeof(lnet_hdr_t); - tx->tx_resid = tx->tx_nob = tx->tx_lnetmsg->msg_len + sizeof(lnet_hdr_t); + tx->tx_nob = tx->tx_lnetmsg->msg_len + sizeof(lnet_hdr_t); + tx->tx_resid = tx->tx_lnetmsg->msg_len + sizeof(lnet_hdr_t); } static void @@ -732,12 +733,14 @@ ksocknal_pack_msg_v2(ksock_tx_t *tx) tx->tx_msg.ksm_u.lnetmsg.ksnm_hdr = tx->tx_lnetmsg->msg_hdr; tx->tx_iov[0].iov_len = sizeof(ksock_msg_t); - tx->tx_resid = tx->tx_nob = sizeof(ksock_msg_t) + tx->tx_lnetmsg->msg_len; + tx->tx_nob = sizeof(ksock_msg_t) + tx->tx_lnetmsg->msg_len; + tx->tx_resid = sizeof(ksock_msg_t) + tx->tx_lnetmsg->msg_len; } else { LASSERT(tx->tx_msg.ksm_type == KSOCK_MSG_NOOP); tx->tx_iov[0].iov_len = offsetof(ksock_msg_t, ksm_u.lnetmsg.ksnm_hdr); - tx->tx_resid = tx->tx_nob = offsetof(ksock_msg_t, ksm_u.lnetmsg.ksnm_hdr); + tx->tx_nob = offsetof(ksock_msg_t, ksm_u.lnetmsg.ksnm_hdr); + tx->tx_resid = offsetof(ksock_msg_t, ksm_u.lnetmsg.ksnm_hdr); } /* Don't checksum before start sending, because packet can be piggybacked with ACK */ } @@ -747,7 +750,8 @@ ksocknal_unpack_msg_v1(ksock_msg_t *msg) { msg->ksm_csum = 0; msg->ksm_type = KSOCK_MSG_LNET; - msg->ksm_zc_cookies[0] = msg->ksm_zc_cookies[1] = 0; + msg->ksm_zc_cookies[0] = 0; + msg->ksm_zc_cookies[1] = 0; } static void diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index e30a959ffc03..d02353dca85e 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -202,7 +202,8 @@ lnet_parse_networks(struct list_head *nilist, char *networks) the_lnet.ln_network_tokens = tokens; the_lnet.ln_network_tokens_nob = tokensize; memcpy(tokens, networks, tokensize); - str = tmp = tokens; + tmp = tokens; + str = tokens; /* Add in the loopback network */ ni = lnet_ni_alloc(LNET_MKNET(LOLND, 0), NULL, nilist); diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 4d59bac199f5..55bd7a1f7a5d 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -109,7 +109,8 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) if ((umd->options & LNET_MD_KIOV) != 0) /* Can't specify both */ return -EINVAL; - lmd->md_niov = niov = umd->length; + niov = umd->length; + lmd->md_niov = umd->length; memcpy(lmd->md_iov.iov, umd->start, niov * sizeof(lmd->md_iov.iov[0])); @@ -130,7 +131,8 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) return -EINVAL; } else if ((umd->options & LNET_MD_KIOV) != 0) { - lmd->md_niov = niov = umd->length; + niov = umd->length; + lmd->md_niov = umd->length; memcpy(lmd->md_iov.kiov, umd->start, niov * sizeof(lmd->md_iov.kiov[0])); @@ -151,7 +153,8 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) return -EINVAL; } else { /* contiguous */ lmd->md_length = umd->length; - lmd->md_niov = niov = 1; + niov = 1; + lmd->md_niov = 1; lmd->md_iov.iov[0].iov_base = umd->start; lmd->md_iov.iov[0].iov_len = umd->length; diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 12bb983fd991..b40220a5434c 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -1151,7 +1151,8 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) return NULL; lp_best = NULL; - rtr_best = rtr_last = NULL; + rtr_best = NULL; + rtr_last = NULL; list_for_each_entry(rtr, &rnet->lrn_routes, lr_list) { lp = rtr->lr_gateway; @@ -1167,7 +1168,8 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) return lp; if (lp_best == NULL) { - rtr_best = rtr_last = rtr; + rtr_best = rtr; + rtr_last = rtr; lp_best = lp; continue; } @@ -1868,7 +1870,8 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, msg->msg_type = type; msg->msg_private = private; msg->msg_receiving = 1; - msg->msg_len = msg->msg_wanted = payload_length; + msg->msg_wanted = payload_length; + msg->msg_len = payload_length; msg->msg_offset = 0; msg->msg_hdr = *hdr; /* for building message event */ diff --git a/drivers/staging/lustre/lnet/lnet/peer.c b/drivers/staging/lustre/lnet/lnet/peer.c index 9c0f264ae4cb..a8e25b0d11b3 100644 --- a/drivers/staging/lustre/lnet/lnet/peer.c +++ b/drivers/staging/lustre/lnet/lnet/peer.c @@ -287,9 +287,9 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) goto out; } - lp->lp_txcredits = - lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits; - lp->lp_rtrcredits = + lp->lp_txcredits = lp->lp_ni->ni_peertxcredits; + lp->lp_mintxcredits = lp->lp_ni->ni_peertxcredits; + lp->lp_rtrcredits = lnet_peer_buffer_credits(lp->lp_ni); lp->lp_minrtrcredits = lnet_peer_buffer_credits(lp->lp_ni); list_add_tail(&lp->lp_hashlist, diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 65f951ca198b..36f3caabc2a6 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -1307,7 +1307,8 @@ lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp) LASSERT(rbp->rbp_nbuffers == nbuffers); LASSERT(rbp->rbp_credits == nbuffers); - rbp->rbp_nbuffers = rbp->rbp_credits = 0; + rbp->rbp_nbuffers = 0; + rbp->rbp_credits = 0; } static int diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 3e702e234b33..817be93a149d 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -953,7 +953,8 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, CNETERR("Framework features %x from %s is different with features on this transaction: %x\n", reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid), trans->tas_features); - status = mksn_rep->mksn_status = EPROTO; + mksn_rep->mksn_status = EPROTO; + status = EPROTO; } if (status == 0) { diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 870498339538..5781f7766f2d 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -546,8 +546,8 @@ srpc_init_client_rpc (srpc_client_rpc_t *rpc, lnet_process_id_t peer, LNetInvalidateHandle(&rpc->crpc_bulk.bk_mdh); /* no event is expected at this point */ - rpc->crpc_bulkev.ev_fired = - rpc->crpc_reqstev.ev_fired = + rpc->crpc_bulkev.ev_fired = 1; + rpc->crpc_reqstev.ev_fired = 1; rpc->crpc_replyev.ev_fired = 1; rpc->crpc_reqstmsg.msg_magic = SRPC_MSG_MAGIC; -- cgit From b31e64c4a106cc70e8aab168a6fb12b4e2be4647 Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:06 -0500 Subject: staging: lustre: remove space in LNet function declarations Several function declarations have spacing in them. Lets remove all those instances reported by checkpatch.pl. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h | 2 +- .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 272 ++++++++++----------- .../lustre/lnet/klnds/socklnd/socklnd_proto.c | 22 +- drivers/staging/lustre/lnet/selftest/console.h | 2 +- drivers/staging/lustre/lnet/selftest/selftest.h | 26 +- 5 files changed, 161 insertions(+), 163 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 288f0d2fe0e8..16c90ed5962e 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -967,7 +967,7 @@ void kiblnd_queue_tx(kib_tx_t *tx, kib_conn_t *conn); void kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob); void kiblnd_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int status); -void kiblnd_check_sends (kib_conn_t *conn); +void kiblnd_check_sends(kib_conn_t *conn); void kiblnd_qp_event(struct ib_event *event, void *arg); void kiblnd_cq_event(struct ib_event *event, void *arg); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 31b8d46f56a1..16c9bac99e96 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -90,7 +90,7 @@ ksocknal_alloc_tx_noop(__u64 cookie, int nonblk) } void -ksocknal_free_tx (ksock_tx_t *tx) +ksocknal_free_tx(ksock_tx_t *tx) { atomic_dec(&ksocknal_data.ksnd_nactive_txs); @@ -107,7 +107,7 @@ ksocknal_free_tx (ksock_tx_t *tx) } static int -ksocknal_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) +ksocknal_send_iov(ksock_conn_t *conn, ksock_tx_t *tx) { struct kvec *iov = tx->tx_iov; int nob; @@ -122,7 +122,7 @@ ksocknal_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) return rc; nob = rc; - LASSERT (nob <= tx->tx_resid); + LASSERT(nob <= tx->tx_resid); tx->tx_resid -= nob; /* "consume" iov */ @@ -144,7 +144,7 @@ ksocknal_send_iov (ksock_conn_t *conn, ksock_tx_t *tx) } static int -ksocknal_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx) +ksocknal_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) { lnet_kiov_t *kiov = tx->tx_kiov; int nob; @@ -160,7 +160,7 @@ ksocknal_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx) return rc; nob = rc; - LASSERT (nob <= tx->tx_resid); + LASSERT(nob <= tx->tx_resid); tx->tx_resid -= nob; /* "consume" kiov */ @@ -182,7 +182,7 @@ ksocknal_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx) } static int -ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) +ksocknal_transmit(ksock_conn_t *conn, ksock_tx_t *tx) { int rc; int bufnob; @@ -196,7 +196,7 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) rc = ksocknal_connsock_addref(conn); if (rc != 0) { - LASSERT (conn->ksnc_closing); + LASSERT(conn->ksnc_closing); return -ESHUTDOWN; } @@ -206,9 +206,9 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) ksocknal_data.ksnd_enomem_tx--; rc = -EAGAIN; } else if (tx->tx_niov != 0) { - rc = ksocknal_send_iov (conn, tx); + rc = ksocknal_send_iov(conn, tx); } else { - rc = ksocknal_send_kiov (conn, tx); + rc = ksocknal_send_kiov(conn, tx); } bufnob = conn->ksnc_sock->sk->sk_wmem_queued; @@ -240,7 +240,7 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) } /* socket's wmem_queued now includes 'rc' bytes */ - atomic_sub (rc, &conn->ksnc_tx_nob); + atomic_sub(rc, &conn->ksnc_tx_nob); rc = 0; } while (tx->tx_resid != 0); @@ -250,7 +250,7 @@ ksocknal_transmit (ksock_conn_t *conn, ksock_tx_t *tx) } static int -ksocknal_recv_iov (ksock_conn_t *conn) +ksocknal_recv_iov(ksock_conn_t *conn) { struct kvec *iov = conn->ksnc_rx_iov; int nob; @@ -297,7 +297,7 @@ ksocknal_recv_iov (ksock_conn_t *conn) } static int -ksocknal_recv_kiov (ksock_conn_t *conn) +ksocknal_recv_kiov(ksock_conn_t *conn) { lnet_kiov_t *kiov = conn->ksnc_rx_kiov; int nob; @@ -344,7 +344,7 @@ ksocknal_recv_kiov (ksock_conn_t *conn) } static int -ksocknal_receive (ksock_conn_t *conn) +ksocknal_receive(ksock_conn_t *conn) { /* * Return 1 on success, 0 on EOF, < 0 on error. @@ -360,15 +360,15 @@ ksocknal_receive (ksock_conn_t *conn) rc = ksocknal_connsock_addref(conn); if (rc != 0) { - LASSERT (conn->ksnc_closing); + LASSERT(conn->ksnc_closing); return -ESHUTDOWN; } for (;;) { if (conn->ksnc_rx_niov != 0) - rc = ksocknal_recv_iov (conn); + rc = ksocknal_recv_iov(conn); else - rc = ksocknal_recv_kiov (conn); + rc = ksocknal_recv_kiov(conn); if (rc <= 0) { /* error/EOF or partial receive */ @@ -394,7 +394,7 @@ ksocknal_receive (ksock_conn_t *conn) } void -ksocknal_tx_done (lnet_ni_t *ni, ksock_tx_t *tx) +ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx) { lnet_msg_t *lnetmsg = tx->tx_lnetmsg; int rc = (tx->tx_resid == 0 && !tx->tx_zc_aborted) ? 0 : -EIO; @@ -407,23 +407,23 @@ ksocknal_tx_done (lnet_ni_t *ni, ksock_tx_t *tx) if (ni == NULL && tx->tx_conn != NULL) ni = tx->tx_conn->ksnc_peer->ksnp_ni; - ksocknal_free_tx (tx); + ksocknal_free_tx(tx); if (lnetmsg != NULL) /* KSOCK_MSG_NOOP go without lnetmsg */ - lnet_finalize (ni, lnetmsg, rc); + lnet_finalize(ni, lnetmsg, rc); } void -ksocknal_txlist_done (lnet_ni_t *ni, struct list_head *txlist, int error) +ksocknal_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int error) { ksock_tx_t *tx; - while (!list_empty (txlist)) { + while (!list_empty(txlist)) { tx = list_entry(txlist->next, ksock_tx_t, tx_list); if (error && tx->tx_lnetmsg != NULL) { CNETERR("Deleting packet type %d len %d %s->%s\n", - le32_to_cpu (tx->tx_lnetmsg->msg_hdr.type), - le32_to_cpu (tx->tx_lnetmsg->msg_hdr.payload_length), + le32_to_cpu(tx->tx_lnetmsg->msg_hdr.type), + le32_to_cpu(tx->tx_lnetmsg->msg_hdr.payload_length), libcfs_nid2str(le64_to_cpu(tx->tx_lnetmsg->msg_hdr.src_nid)), libcfs_nid2str(le64_to_cpu(tx->tx_lnetmsg->msg_hdr.dest_nid))); } else if (error) { @@ -511,20 +511,20 @@ ksocknal_uncheck_zc_req(ksock_tx_t *tx) } static int -ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx) +ksocknal_process_transmit(ksock_conn_t *conn, ksock_tx_t *tx) { int rc; if (tx->tx_zc_capable && !tx->tx_zc_checked) ksocknal_check_zc_req(tx); - rc = ksocknal_transmit (conn, tx); + rc = ksocknal_transmit(conn, tx); CDEBUG(D_NET, "send(%d) %d\n", tx->tx_resid, rc); if (tx->tx_resid == 0) { /* Sent everything OK */ - LASSERT (rc == 0); + LASSERT(rc == 0); return 0; } @@ -543,13 +543,13 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx) spin_lock_bh(&ksocknal_data.ksnd_reaper_lock); /* enomem list takes over scheduler's ref... */ - LASSERT (conn->ksnc_tx_scheduled); + LASSERT(conn->ksnc_tx_scheduled); list_add_tail(&conn->ksnc_tx_list, &ksocknal_data.ksnd_enomem_conns); if (!cfs_time_aftereq(cfs_time_add(cfs_time_current(), SOCKNAL_ENOMEM_RETRY), ksocknal_data.ksnd_reaper_waketime)) - wake_up (&ksocknal_data.ksnd_reaper_waitq); + wake_up(&ksocknal_data.ksnd_reaper_waitq); spin_unlock_bh(&ksocknal_data.ksnd_reaper_lock); return rc; @@ -580,14 +580,13 @@ ksocknal_process_transmit (ksock_conn_t *conn, ksock_tx_t *tx) ksocknal_uncheck_zc_req(tx); /* it's not an error if conn is being closed */ - ksocknal_close_conn_and_siblings (conn, - (conn->ksnc_closing) ? 0 : rc); + ksocknal_close_conn_and_siblings(conn, (conn->ksnc_closing) ? 0 : rc); return rc; } static void -ksocknal_launch_connection_locked (ksock_route_t *route) +ksocknal_launch_connection_locked(ksock_route_t *route) { /* called holding write lock on ksnd_global_lock */ @@ -608,7 +607,7 @@ ksocknal_launch_connection_locked (ksock_route_t *route) } void -ksocknal_launch_all_connections_locked (ksock_peer_t *peer) +ksocknal_launch_all_connections_locked(ksock_peer_t *peer) { ksock_route_t *route; @@ -633,7 +632,7 @@ ksocknal_find_conn_locked(ksock_peer_t *peer, ksock_tx_t *tx, int nonblk) int tnob = 0; int fnob = 0; - list_for_each (tmp, &peer->ksnp_conns) { + list_for_each(tmp, &peer->ksnp_conns) { ksock_conn_t *c = list_entry(tmp, ksock_conn_t, ksnc_list); int nob = atomic_read(&c->ksnc_tx_nob) + c->ksnc_sock->sk->sk_wmem_queued; @@ -685,13 +684,13 @@ ksocknal_tx_prep(ksock_conn_t *conn, ksock_tx_t *tx) { conn->ksnc_proto->pro_pack(tx); - atomic_add (tx->tx_nob, &conn->ksnc_tx_nob); + atomic_add(tx->tx_nob, &conn->ksnc_tx_nob); ksocknal_conn_addref(conn); /* +1 ref for tx */ tx->tx_conn = conn; } void -ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) +ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) { ksock_sched_t *sched = conn->ksnc_scheduler; ksock_msg_t *msg = &tx->tx_msg; @@ -720,16 +719,16 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) * We always expect at least 1 mapped fragment containing the * complete ksocknal message header. */ - LASSERT(lnet_iov_nob (tx->tx_niov, tx->tx_iov) + + LASSERT(lnet_iov_nob(tx->tx_niov, tx->tx_iov) + lnet_kiov_nob(tx->tx_nkiov, tx->tx_kiov) == (unsigned int)tx->tx_nob); LASSERT(tx->tx_niov >= 1); LASSERT(tx->tx_resid == tx->tx_nob); - CDEBUG (D_NET, "Packet %p type %d, nob %d niov %d nkiov %d\n", - tx, (tx->tx_lnetmsg != NULL) ? tx->tx_lnetmsg->msg_hdr.type : - KSOCK_MSG_NOOP, - tx->tx_nob, tx->tx_niov, tx->tx_nkiov); + CDEBUG(D_NET, "Packet %p type %d, nob %d niov %d nkiov %d\n", + tx, (tx->tx_lnetmsg != NULL) ? tx->tx_lnetmsg->msg_hdr.type : + KSOCK_MSG_NOOP, + tx->tx_nob, tx->tx_niov, tx->tx_nkiov); /* * FIXME: SOCK_WMEM_QUEUED and SOCK_ERROR could block in __DARWIN8__ @@ -772,7 +771,7 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) } if (ztx != NULL) { - atomic_sub (ztx->tx_nob, &conn->ksnc_tx_nob); + atomic_sub(ztx->tx_nob, &conn->ksnc_tx_nob); list_add_tail(&ztx->tx_list, &sched->kss_zombie_noop_txs); } @@ -782,21 +781,21 @@ ksocknal_queue_tx_locked (ksock_tx_t *tx, ksock_conn_t *conn) ksocknal_conn_addref(conn); list_add_tail(&conn->ksnc_tx_list, &sched->kss_tx_conns); conn->ksnc_tx_scheduled = 1; - wake_up (&sched->kss_waitq); + wake_up(&sched->kss_waitq); } spin_unlock_bh(&sched->kss_lock); } ksock_route_t * -ksocknal_find_connectable_route_locked (ksock_peer_t *peer) +ksocknal_find_connectable_route_locked(ksock_peer_t *peer) { unsigned long now = cfs_time_current(); struct list_head *tmp; ksock_route_t *route; - list_for_each (tmp, &peer->ksnp_routes) { - route = list_entry (tmp, ksock_route_t, ksnr_list); + list_for_each(tmp, &peer->ksnp_routes) { + route = list_entry(tmp, ksock_route_t, ksnr_list); LASSERT(!route->ksnr_connecting || route->ksnr_scheduled); @@ -825,13 +824,13 @@ ksocknal_find_connectable_route_locked (ksock_peer_t *peer) } ksock_route_t * -ksocknal_find_connecting_route_locked (ksock_peer_t *peer) +ksocknal_find_connecting_route_locked(ksock_peer_t *peer) { struct list_head *tmp; ksock_route_t *route; - list_for_each (tmp, &peer->ksnp_routes) { - route = list_entry (tmp, ksock_route_t, ksnr_list); + list_for_each(tmp, &peer->ksnp_routes) { + route = list_entry(tmp, ksock_route_t, ksnr_list); LASSERT(!route->ksnr_connecting || route->ksnr_scheduled); @@ -843,7 +842,7 @@ ksocknal_find_connecting_route_locked (ksock_peer_t *peer) } int -ksocknal_launch_packet (lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) +ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) { ksock_peer_t *peer; ksock_conn_t *conn; @@ -867,7 +866,7 @@ ksocknal_launch_packet (lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) * connecting and I do have an actual * connection... */ - ksocknal_queue_tx_locked (tx, conn); + ksocknal_queue_tx_locked(tx, conn); read_unlock(g_lock); return 0; } @@ -911,19 +910,19 @@ ksocknal_launch_packet (lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) conn = ksocknal_find_conn_locked(peer, tx, tx->tx_nonblk); if (conn != NULL) { /* Connection exists; queue message on it */ - ksocknal_queue_tx_locked (tx, conn); + ksocknal_queue_tx_locked(tx, conn); write_unlock_bh(g_lock); return 0; } if (peer->ksnp_accepting > 0 || - ksocknal_find_connecting_route_locked (peer) != NULL) { + ksocknal_find_connecting_route_locked(peer) != NULL) { /* the message is going to be pinned to the peer */ tx->tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout); /* Queue the message until a connection is established */ - list_add_tail (&tx->tx_list, &peer->ksnp_tx_queue); + list_add_tail(&tx->tx_list, &peer->ksnp_tx_queue); write_unlock_bh(g_lock); return 0; } @@ -960,8 +959,8 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) LASSERT(payload_nob == 0 || payload_niov > 0); LASSERT(payload_niov <= LNET_MAX_IOV); /* payload is either all vaddrs or all pages */ - LASSERT (!(payload_kiov != NULL && payload_iov != NULL)); - LASSERT (!in_interrupt ()); + LASSERT(!(payload_kiov != NULL && payload_iov != NULL)); + LASSERT(!in_interrupt()); if (payload_iov != NULL) desc_size = offsetof(ksock_tx_t, @@ -1033,7 +1032,7 @@ ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name) } void -ksocknal_thread_fini (void) +ksocknal_thread_fini(void) { write_lock_bh(&ksocknal_data.ksnd_global_lock); ksocknal_data.ksnd_nthreads--; @@ -1041,7 +1040,7 @@ ksocknal_thread_fini (void) } int -ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) +ksocknal_new_packet(ksock_conn_t *conn, int nob_to_skip) { static char ksocknal_slop_buffer[4096]; @@ -1080,11 +1079,11 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) conn->ksnc_rx_iov = (struct kvec *)&conn->ksnc_rx_iov_space; conn->ksnc_rx_iov[0].iov_base = &conn->ksnc_msg.ksm_u.lnetmsg; - conn->ksnc_rx_iov[0].iov_len = sizeof (lnet_hdr_t); + conn->ksnc_rx_iov[0].iov_len = sizeof(lnet_hdr_t); break; default: - LBUG (); + LBUG(); } conn->ksnc_rx_niov = 1; @@ -1114,7 +1113,7 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) nob_to_skip -= nob; } while (nob_to_skip != 0 && /* mustn't overflow conn's rx iov */ - niov < sizeof(conn->ksnc_rx_iov_space) / sizeof (struct iovec)); + niov < sizeof(conn->ksnc_rx_iov_space) / sizeof(struct iovec)); conn->ksnc_rx_niov = niov; conn->ksnc_rx_kiov = NULL; @@ -1124,13 +1123,13 @@ ksocknal_new_packet (ksock_conn_t *conn, int nob_to_skip) } static int -ksocknal_process_receive (ksock_conn_t *conn) +ksocknal_process_receive(ksock_conn_t *conn) { lnet_hdr_t *lhdr; lnet_process_id_t *id; int rc; - LASSERT (atomic_read(&conn->ksnc_conn_refcount) > 0); + LASSERT(atomic_read(&conn->ksnc_conn_refcount) > 0); /* NB: sched lock NOT held */ /* SOCKNAL_RX_LNET_HEADER is here for backward compatibility */ @@ -1143,7 +1142,7 @@ ksocknal_process_receive (ksock_conn_t *conn) rc = ksocknal_receive(conn); if (rc <= 0) { - LASSERT (rc != -EAGAIN); + LASSERT(rc != -EAGAIN); if (rc == 0) CDEBUG(D_NET, "[%p] EOF from %s ip %pI4h:%d\n", @@ -1159,8 +1158,8 @@ ksocknal_process_receive (ksock_conn_t *conn) conn->ksnc_port); /* it's not an error if conn is being closed */ - ksocknal_close_conn_and_siblings (conn, - (conn->ksnc_closing) ? 0 : rc); + ksocknal_close_conn_and_siblings(conn, + (conn->ksnc_closing) ? 0 : rc); return (rc == 0 ? -ESHUTDOWN : rc); } @@ -1203,7 +1202,7 @@ ksocknal_process_receive (ksock_conn_t *conn) if (conn->ksnc_msg.ksm_zc_cookies[1] != 0) { __u64 cookie = 0; - LASSERT (conn->ksnc_proto != &ksocknal_protocol_v1x); + LASSERT(conn->ksnc_proto != &ksocknal_protocol_v1x); if (conn->ksnc_msg.ksm_type == KSOCK_MSG_NOOP) cookie = conn->ksnc_msg.ksm_zc_cookies[0]; @@ -1222,7 +1221,7 @@ ksocknal_process_receive (ksock_conn_t *conn) } if (conn->ksnc_msg.ksm_type == KSOCK_MSG_NOOP) { - ksocknal_new_packet (conn, 0); + ksocknal_new_packet(conn, 0); return 0; /* NOOP is done and just return */ } @@ -1263,14 +1262,14 @@ ksocknal_process_receive (ksock_conn_t *conn) if (rc < 0) { /* I just received garbage: give up on this conn */ ksocknal_new_packet(conn, 0); - ksocknal_close_conn_and_siblings (conn, rc); + ksocknal_close_conn_and_siblings(conn, rc); ksocknal_conn_decref(conn); return -EPROTO; } /* I'm racing with ksocknal_recv() */ - LASSERT (conn->ksnc_rx_state == SOCKNAL_RX_PARSE || - conn->ksnc_rx_state == SOCKNAL_RX_LNET_PAYLOAD); + LASSERT(conn->ksnc_rx_state == SOCKNAL_RX_PARSE || + conn->ksnc_rx_state == SOCKNAL_RX_LNET_PAYLOAD); if (conn->ksnc_rx_state != SOCKNAL_RX_LNET_PAYLOAD) return 0; @@ -1307,14 +1306,14 @@ ksocknal_process_receive (ksock_conn_t *conn) if (rc != 0) { ksocknal_new_packet(conn, 0); - ksocknal_close_conn_and_siblings (conn, rc); + ksocknal_close_conn_and_siblings(conn, rc); return -EPROTO; } /* Fall through */ case SOCKNAL_RX_SLOP: /* starting new packet? */ - if (ksocknal_new_packet (conn, conn->ksnc_rx_nob_left)) + if (ksocknal_new_packet(conn, conn->ksnc_rx_nob_left)) return 0; /* come back later */ goto again; /* try to finish reading slop now */ @@ -1328,9 +1327,9 @@ ksocknal_process_receive (ksock_conn_t *conn) } int -ksocknal_recv (lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, - unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, - unsigned int offset, unsigned int mlen, unsigned int rlen) +ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, + unsigned int niov, struct kvec *iov, lnet_kiov_t *kiov, + unsigned int offset, unsigned int mlen, unsigned int rlen) { ksock_conn_t *conn = private; ksock_sched_t *sched = conn->ksnc_scheduler; @@ -1369,8 +1368,8 @@ ksocknal_recv (lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, switch (conn->ksnc_rx_state) { case SOCKNAL_RX_PARSE_WAIT: list_add_tail(&conn->ksnc_rx_list, &sched->kss_rx_conns); - wake_up (&sched->kss_waitq); - LASSERT (conn->ksnc_rx_ready); + wake_up(&sched->kss_waitq); + LASSERT(conn->ksnc_rx_ready); break; case SOCKNAL_RX_PARSE: @@ -1428,7 +1427,7 @@ int ksocknal_scheduler(void *arg) /* Ensure I progress everything semi-fairly */ - if (!list_empty (&sched->kss_rx_conns)) { + if (!list_empty(&sched->kss_rx_conns)) { conn = list_entry(sched->kss_rx_conns.next, ksock_conn_t, ksnc_rx_list); list_del(&conn->ksnc_rx_list); @@ -1476,7 +1475,7 @@ int ksocknal_scheduler(void *arg) did_something = 1; } - if (!list_empty (&sched->kss_tx_conns)) { + if (!list_empty(&sched->kss_tx_conns)) { LIST_HEAD(zlist); if (!list_empty(&sched->kss_zombie_noop_txs)) { @@ -1486,7 +1485,7 @@ int ksocknal_scheduler(void *arg) conn = list_entry(sched->kss_tx_conns.next, ksock_conn_t, ksnc_tx_list); - list_del (&conn->ksnc_tx_list); + list_del(&conn->ksnc_tx_list); LASSERT(conn->ksnc_tx_scheduled); LASSERT(conn->ksnc_tx_ready); @@ -1561,7 +1560,7 @@ int ksocknal_scheduler(void *arg) rc = wait_event_interruptible_exclusive( sched->kss_waitq, !ksocknal_sched_cansleep(sched)); - LASSERT (rc == 0); + LASSERT(rc == 0); } else { cond_resched(); } @@ -1579,7 +1578,7 @@ int ksocknal_scheduler(void *arg) * Add connection to kss_rx_conns of scheduler * and wakeup the scheduler. */ -void ksocknal_read_callback (ksock_conn_t *conn) +void ksocknal_read_callback(ksock_conn_t *conn) { ksock_sched_t *sched; @@ -1595,7 +1594,7 @@ void ksocknal_read_callback (ksock_conn_t *conn) /* extra ref for scheduler */ ksocknal_conn_addref(conn); - wake_up (&sched->kss_waitq); + wake_up(&sched->kss_waitq); } spin_unlock_bh(&sched->kss_lock); } @@ -1604,7 +1603,7 @@ void ksocknal_read_callback (ksock_conn_t *conn) * Add connection to kss_tx_conns of scheduler * and wakeup the scheduler. */ -void ksocknal_write_callback (ksock_conn_t *conn) +void ksocknal_write_callback(ksock_conn_t *conn) { ksock_sched_t *sched; @@ -1621,14 +1620,14 @@ void ksocknal_write_callback (ksock_conn_t *conn) /* extra ref for scheduler */ ksocknal_conn_addref(conn); - wake_up (&sched->kss_waitq); + wake_up(&sched->kss_waitq); } spin_unlock_bh(&sched->kss_lock); } static ksock_proto_t * -ksocknal_parse_proto_version (ksock_hello_msg_t *hello) +ksocknal_parse_proto_version(ksock_hello_msg_t *hello) { __u32 version = 0; @@ -1658,11 +1657,11 @@ ksocknal_parse_proto_version (ksock_hello_msg_t *hello) if (hello->kshm_magic == le32_to_cpu(LNET_PROTO_TCP_MAGIC)) { lnet_magicversion_t *hmv = (lnet_magicversion_t *)hello; - CLASSERT(sizeof (lnet_magicversion_t) == - offsetof (ksock_hello_msg_t, kshm_src_nid)); + CLASSERT(sizeof(lnet_magicversion_t) == + offsetof(ksock_hello_msg_t, kshm_src_nid)); - if (hmv->version_major == cpu_to_le16 (KSOCK_PROTO_V1_MAJOR) && - hmv->version_minor == cpu_to_le16 (KSOCK_PROTO_V1_MINOR)) + if (hmv->version_major == cpu_to_le16(KSOCK_PROTO_V1_MAJOR) && + hmv->version_minor == cpu_to_le16(KSOCK_PROTO_V1_MINOR)) return &ksocknal_protocol_v1x; } @@ -1670,8 +1669,8 @@ ksocknal_parse_proto_version (ksock_hello_msg_t *hello) } int -ksocknal_send_hello (lnet_ni_t *ni, ksock_conn_t *conn, - lnet_nid_t peer_nid, ksock_hello_msg_t *hello) +ksocknal_send_hello(lnet_ni_t *ni, ksock_conn_t *conn, + lnet_nid_t peer_nid, ksock_hello_msg_t *hello) { /* CAVEAT EMPTOR: this byte flips 'ipaddrs' */ ksock_net_t *net = (ksock_net_t *)ni->ni_data; @@ -1708,9 +1707,9 @@ ksocknal_invert_type(int type) } int -ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, - ksock_hello_msg_t *hello, lnet_process_id_t *peerid, - __u64 *incarnation) +ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn, + ksock_hello_msg_t *hello, lnet_process_id_t *peerid, + __u64 *incarnation) { /* Return < 0 fatal error * 0 success @@ -1731,20 +1730,20 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, timeout = active ? *ksocknal_tunables.ksnd_timeout : lnet_acceptor_timeout(); - rc = lnet_sock_read(sock, &hello->kshm_magic, sizeof (hello->kshm_magic), timeout); + rc = lnet_sock_read(sock, &hello->kshm_magic, sizeof(hello->kshm_magic), timeout); if (rc != 0) { CERROR("Error %d reading HELLO from %pI4h\n", rc, &conn->ksnc_ipaddr); - LASSERT (rc < 0); + LASSERT(rc < 0); return rc; } if (hello->kshm_magic != LNET_PROTO_MAGIC && hello->kshm_magic != __swab32(LNET_PROTO_MAGIC) && - hello->kshm_magic != le32_to_cpu (LNET_PROTO_TCP_MAGIC)) { + hello->kshm_magic != le32_to_cpu(LNET_PROTO_TCP_MAGIC)) { /* Unexpected magic! */ CERROR("Bad magic(1) %#08x (%#08x expected) from %pI4h\n", - __cpu_to_le32 (hello->kshm_magic), + __cpu_to_le32(hello->kshm_magic), LNET_PROTO_TCP_MAGIC, &conn->ksnc_ipaddr); return -EPROTO; @@ -1851,7 +1850,7 @@ ksocknal_recv_hello (lnet_ni_t *ni, ksock_conn_t *conn, } static int -ksocknal_connect (ksock_route_t *route) +ksocknal_connect(ksock_route_t *route) { LIST_HEAD(zombies); ksock_peer_t *peer = route->ksnr_peer; @@ -1903,7 +1902,7 @@ ksocknal_connect (ksock_route_t *route) } else if ((wanted & (1 << SOCKLND_CONN_BULK_IN)) != 0) { type = SOCKLND_CONN_BULK_IN; } else { - LASSERT ((wanted & (1 << SOCKLND_CONN_BULK_OUT)) != 0); + LASSERT((wanted & (1 << SOCKLND_CONN_BULK_OUT)) != 0); type = SOCKLND_CONN_BULK_OUT; } @@ -1986,7 +1985,7 @@ ksocknal_connect (ksock_route_t *route) min(route->ksnr_retry_interval, cfs_time_seconds(*ksocknal_tunables.ksnd_max_reconnectms) / 1000); - LASSERT (route->ksnr_retry_interval != 0); + LASSERT(route->ksnr_retry_interval != 0); route->ksnr_timeout = cfs_time_add(cfs_time_current(), route->ksnr_retry_interval); @@ -1999,10 +1998,10 @@ ksocknal_connect (ksock_route_t *route) * ksnp_tx_queue is queued on a conn on successful * connection for V1.x and V2.x */ - if (!list_empty (&peer->ksnp_conns)) { + if (!list_empty(&peer->ksnp_conns)) { conn = list_entry(peer->ksnp_conns.next, ksock_conn_t, ksnc_list); - LASSERT (conn->ksnc_proto == &ksocknal_protocol_v3x); + LASSERT(conn->ksnc_proto == &ksocknal_protocol_v3x); } /* @@ -2159,7 +2158,7 @@ ksocknal_connd_get_route_locked(signed long *timeout_p) } int -ksocknal_connd (void *arg) +ksocknal_connd(void *arg) { spinlock_t *connd_lock = &ksocknal_data.ksnd_connd_lock; ksock_connreq_t *cr; @@ -2221,7 +2220,7 @@ ksocknal_connd (void *arg) route = ksocknal_connd_get_route_locked(&timeout); } if (route != NULL) { - list_del (&route->ksnr_connd_list); + list_del(&route->ksnr_connd_list); ksocknal_data.ksnd_connd_connecting++; spin_unlock_bh(connd_lock); dropped_lock = 1; @@ -2272,16 +2271,16 @@ ksocknal_connd (void *arg) } static ksock_conn_t * -ksocknal_find_timed_out_conn (ksock_peer_t *peer) +ksocknal_find_timed_out_conn(ksock_peer_t *peer) { /* We're called with a shared lock on ksnd_global_lock */ ksock_conn_t *conn; struct list_head *ctmp; - list_for_each (ctmp, &peer->ksnp_conns) { + list_for_each(ctmp, &peer->ksnp_conns) { int error; - conn = list_entry (ctmp, ksock_conn_t, ksnc_list); + conn = list_entry(ctmp, ksock_conn_t, ksnc_list); /* Don't need the {get,put}connsock dance to deref ksnc_sock */ LASSERT(!conn->ksnc_closing); @@ -2362,15 +2361,15 @@ ksocknal_flush_stale_txs(ksock_peer_t *peer) write_lock_bh(&ksocknal_data.ksnd_global_lock); - while (!list_empty (&peer->ksnp_tx_queue)) { + while (!list_empty(&peer->ksnp_tx_queue)) { tx = list_entry(peer->ksnp_tx_queue.next, ksock_tx_t, tx_list); if (!cfs_time_aftereq(cfs_time_current(), tx->tx_deadline)) break; - list_del (&tx->tx_list); - list_add_tail (&tx->tx_list, &stale_txs); + list_del(&tx->tx_list); + list_add_tail(&tx->tx_list, &stale_txs); } write_unlock_bh(&ksocknal_data.ksnd_global_lock); @@ -2442,7 +2441,7 @@ ksocknal_send_keepalive_locked(ksock_peer_t *peer) } static void -ksocknal_check_peer_timeouts (int idx) +ksocknal_check_peer_timeouts(int idx) { struct list_head *peers = &ksocknal_data.ksnd_peers[idx]; ksock_peer_t *peer; @@ -2467,12 +2466,12 @@ ksocknal_check_peer_timeouts (int idx) goto again; } - conn = ksocknal_find_timed_out_conn (peer); + conn = ksocknal_find_timed_out_conn(peer); if (conn != NULL) { read_unlock(&ksocknal_data.ksnd_global_lock); - ksocknal_close_conn_and_siblings (conn, -ETIMEDOUT); + ksocknal_close_conn_and_siblings(conn, -ETIMEDOUT); /* * NB we won't find this one again, but we can't @@ -2487,7 +2486,7 @@ ksocknal_check_peer_timeouts (int idx) * we can't process stale txs right here because we're * holding only shared lock */ - if (!list_empty (&peer->ksnp_tx_queue)) { + if (!list_empty(&peer->ksnp_tx_queue)) { ksock_tx_t *tx = list_entry(peer->ksnp_tx_queue.next, ksock_tx_t, tx_list); @@ -2537,7 +2536,7 @@ ksocknal_check_peer_timeouts (int idx) cfs_duration_sec(cfs_time_current() - deadline), resid, conn->ksnc_sock->sk->sk_wmem_queued); - ksocknal_close_conn_and_siblings (conn, -ETIMEDOUT); + ksocknal_close_conn_and_siblings(conn, -ETIMEDOUT); ksocknal_conn_decref(conn); goto again; } @@ -2546,7 +2545,7 @@ ksocknal_check_peer_timeouts (int idx) } int -ksocknal_reaper (void *arg) +ksocknal_reaper(void *arg) { wait_queue_t wait; ksock_conn_t *conn; @@ -2566,11 +2565,10 @@ ksocknal_reaper (void *arg) spin_lock_bh(&ksocknal_data.ksnd_reaper_lock); while (!ksocknal_data.ksnd_shuttingdown) { - if (!list_empty (&ksocknal_data.ksnd_deathrow_conns)) { - conn = list_entry (ksocknal_data. \ - ksnd_deathrow_conns.next, - ksock_conn_t, ksnc_list); - list_del (&conn->ksnc_list); + if (!list_empty(&ksocknal_data.ksnd_deathrow_conns)) { + conn = list_entry(ksocknal_data.ksnd_deathrow_conns.next, + ksock_conn_t, ksnc_list); + list_del(&conn->ksnc_list); spin_unlock_bh(&ksocknal_data.ksnd_reaper_lock); @@ -2581,10 +2579,10 @@ ksocknal_reaper (void *arg) continue; } - if (!list_empty (&ksocknal_data.ksnd_zombie_conns)) { - conn = list_entry (ksocknal_data.ksnd_zombie_conns.\ - next, ksock_conn_t, ksnc_list); - list_del (&conn->ksnc_list); + if (!list_empty(&ksocknal_data.ksnd_zombie_conns)) { + conn = list_entry(ksocknal_data.ksnd_zombie_conns.next, + ksock_conn_t, ksnc_list); + list_del(&conn->ksnc_list); spin_unlock_bh(&ksocknal_data.ksnd_reaper_lock); @@ -2594,7 +2592,7 @@ ksocknal_reaper (void *arg) continue; } - if (!list_empty (&ksocknal_data.ksnd_enomem_conns)) { + if (!list_empty(&ksocknal_data.ksnd_enomem_conns)) { list_add(&enomem_conns, &ksocknal_data.ksnd_enomem_conns); list_del_init(&ksocknal_data.ksnd_enomem_conns); @@ -2604,10 +2602,10 @@ ksocknal_reaper (void *arg) /* reschedule all the connections that stalled with ENOMEM... */ nenomem_conns = 0; - while (!list_empty (&enomem_conns)) { + while (!list_empty(&enomem_conns)) { conn = list_entry(enomem_conns.next, ksock_conn_t, ksnc_tx_list); - list_del (&conn->ksnc_tx_list); + list_del(&conn->ksnc_tx_list); sched = conn->ksnc_scheduler; @@ -2645,7 +2643,7 @@ ksocknal_reaper (void *arg) chunk = 1; for (i = 0; i < chunk; i++) { - ksocknal_check_peer_timeouts (peer_index); + ksocknal_check_peer_timeouts(peer_index); peer_index = (peer_index + 1) % ksocknal_data.ksnd_peer_hash_size; } @@ -2664,16 +2662,16 @@ ksocknal_reaper (void *arg) ksocknal_data.ksnd_reaper_waketime = cfs_time_add(cfs_time_current(), timeout); - set_current_state (TASK_INTERRUPTIBLE); - add_wait_queue (&ksocknal_data.ksnd_reaper_waitq, &wait); + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&ksocknal_data.ksnd_reaper_waitq, &wait); if (!ksocknal_data.ksnd_shuttingdown && - list_empty (&ksocknal_data.ksnd_deathrow_conns) && - list_empty (&ksocknal_data.ksnd_zombie_conns)) + list_empty(&ksocknal_data.ksnd_deathrow_conns) && + list_empty(&ksocknal_data.ksnd_zombie_conns)) schedule_timeout(timeout); - set_current_state (TASK_RUNNING); - remove_wait_queue (&ksocknal_data.ksnd_reaper_waitq, &wait); + set_current_state(TASK_RUNNING); + remove_wait_queue(&ksocknal_data.ksnd_reaper_waitq, &wait); spin_lock_bh(&ksocknal_data.ksnd_reaper_lock); } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index c59ddc250c59..f84d1aed9564 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -472,9 +472,9 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) * Re-organize V2.x message header to V1.x (lnet_hdr_t) * header and send out */ - hmv->magic = cpu_to_le32 (LNET_PROTO_TCP_MAGIC); - hmv->version_major = cpu_to_le16 (KSOCK_PROTO_V1_MAJOR); - hmv->version_minor = cpu_to_le16 (KSOCK_PROTO_V1_MINOR); + hmv->magic = cpu_to_le32(LNET_PROTO_TCP_MAGIC); + hmv->version_major = cpu_to_le16(KSOCK_PROTO_V1_MAJOR); + hmv->version_minor = cpu_to_le16(KSOCK_PROTO_V1_MINOR); if (the_lnet.ln_testprotocompat != 0) { /* single-shot proto check */ @@ -490,12 +490,12 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) LNET_UNLOCK(); } - hdr->src_nid = cpu_to_le64 (hello->kshm_src_nid); - hdr->src_pid = cpu_to_le32 (hello->kshm_src_pid); - hdr->type = cpu_to_le32 (LNET_MSG_HELLO); - hdr->payload_length = cpu_to_le32 (hello->kshm_nips * sizeof(__u32)); - hdr->msg.hello.type = cpu_to_le32 (hello->kshm_ctype); - hdr->msg.hello.incarnation = cpu_to_le64 (hello->kshm_src_incarnation); + hdr->src_nid = cpu_to_le64(hello->kshm_src_nid); + hdr->src_pid = cpu_to_le32(hello->kshm_src_pid); + hdr->type = cpu_to_le32(LNET_MSG_HELLO); + hdr->payload_length = cpu_to_le32(hello->kshm_nips * sizeof(__u32)); + hdr->msg.hello.type = cpu_to_le32(hello->kshm_ctype); + hdr->msg.hello.incarnation = cpu_to_le64(hello->kshm_src_incarnation); rc = lnet_sock_write(sock, hdr, sizeof(*hdr), lnet_acceptor_timeout()); if (rc != 0) { @@ -508,7 +508,7 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) goto out; for (i = 0; i < (int) hello->kshm_nips; i++) { - hello->kshm_ips[i] = __cpu_to_le32 (hello->kshm_ips[i]); + hello->kshm_ips[i] = __cpu_to_le32(hello->kshm_ips[i]); } rc = lnet_sock_write(sock, hello->kshm_ips, @@ -593,7 +593,7 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, } /* ...and check we got what we expected */ - if (hdr->type != cpu_to_le32 (LNET_MSG_HELLO)) { + if (hdr->type != cpu_to_le32(LNET_MSG_HELLO)) { CERROR("Expecting a HELLO hdr, but got type %d from %pI4h\n", le32_to_cpu(hdr->type), &conn->ksnc_ipaddr); diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h index f7ccaeb28be0..5651b085a0a1 100644 --- a/drivers/staging/lustre/lnet/selftest/console.h +++ b/drivers/staging/lustre/lnet/selftest/console.h @@ -176,7 +176,7 @@ lstcon_trans_stat(void) } static inline struct list_head * -lstcon_id2hash (lnet_process_id_t id, struct list_head *hash) +lstcon_id2hash(lnet_process_id_t id, struct list_head *hash) { unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE; diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 5781f7766f2d..5c299d6aa2ce 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -94,11 +94,11 @@ struct sfw_test_instance; #define SRPC_RDMA_PORTAL 52 static inline srpc_msg_type_t -srpc_service2request (int service) +srpc_service2request(int service) { switch (service) { default: - LBUG (); + LBUG(); case SRPC_SERVICE_DEBUG: return SRPC_MSG_DEBUG_REQST; @@ -129,7 +129,7 @@ srpc_service2request (int service) } static inline srpc_msg_type_t -srpc_service2reply (int service) +srpc_service2reply(int service) { return srpc_service2request(service) + 1; } @@ -427,7 +427,7 @@ void sfw_free_pages(struct srpc_server_rpc *rpc); void sfw_add_bulk_page(srpc_bulk_t *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(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply); srpc_client_rpc_t * srpc_create_client_rpc(lnet_process_id_t peer, int service, @@ -502,7 +502,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(srpc_client_rpc_t *rpc) { LASSERT(rpc != NULL); LASSERT(!srpc_event_pending(rpc)); @@ -518,10 +518,10 @@ 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, - int service, int nbulkiov, int bulklen, - void (*rpc_done)(srpc_client_rpc_t *), - void (*rpc_fini)(srpc_client_rpc_t *), void *priv) +srpc_init_client_rpc(srpc_client_rpc_t *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) { LASSERT(nbulkiov <= LNET_MAX_IOV); @@ -557,7 +557,7 @@ srpc_init_client_rpc (srpc_client_rpc_t *rpc, lnet_process_id_t peer, } static inline const char * -swi_state2str (int state) +swi_state2str(int state) { #define STATE2STR(x) case x: return #x switch (state) { @@ -604,9 +604,9 @@ srpc_wait_service_shutdown(srpc_service_t *sv) while (srpc_finish_service(sv) == 0) { i++; - CDEBUG (((i & -i) == i) ? D_WARNING : D_NET, - "Waiting for %s service to shutdown...\n", - sv->sv_name); + CDEBUG(((i & -i) == i) ? D_WARNING : D_NET, + "Waiting for %s service to shutdown...\n", + sv->sv_name); selftest_wait_events(); } } -- cgit From 06f2f2f2bb64a299afa626c0c28539cecbf9fc8b Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:07 -0500 Subject: staging: lustre: balance braces properly in LNet layer Properly balance the braces done wrong as reported by checkpatch.pl. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 3 ++- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c | 3 ++- drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c | 3 +-- drivers/staging/lustre/lnet/lnet/nidstrings.c | 4 ++-- drivers/staging/lustre/lnet/lnet/router_proc.c | 8 ++++---- drivers/staging/lustre/lnet/selftest/console.c | 6 ++---- drivers/staging/lustre/lnet/selftest/selftest.h | 5 ++--- 7 files changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 14938c361741..d9c708987ddf 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -951,8 +951,9 @@ kiblnd_check_sends(kib_conn_t *conn) credit = 1; tx = list_entry(conn->ibc_tx_queue.next, kib_tx_t, tx_list); - } else + } else { break; + } if (kiblnd_post_tx_locked(conn, tx, credit) != 0) break; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 37df8a920e54..db5662b13b20 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -609,8 +609,9 @@ ksocknal_data_ready(struct sock *sk) if (conn == NULL) { /* raced with ksocknal_terminate_conn */ LASSERT(sk->sk_data_ready != &ksocknal_data_ready); sk->sk_data_ready(sk); - } else + } else { ksocknal_read_callback(conn); + } read_unlock(&ksocknal_data.ksnd_global_lock); } diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index f84d1aed9564..041f97272ec3 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -507,9 +507,8 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) if (hello->kshm_nips == 0) goto out; - for (i = 0; i < (int) hello->kshm_nips; i++) { + for (i = 0; i < (int) hello->kshm_nips; i++) hello->kshm_ips[i] = __cpu_to_le32(hello->kshm_ips[i]); - } rc = lnet_sock_write(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index 449efc7b49ca..d7c983644ff0 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -1139,9 +1139,9 @@ libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size) } nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) + if (nf == NULL) { snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum); - else { + } else { size_t addr_len; nf->nf_addr2str(addr, buf, buf_size); diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 4a5067c43f1b..124737e8a4ae 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -262,9 +262,9 @@ static int proc_lnet_routes(struct ctl_table *table, int write, if (len > *lenp) { /* linux-supplied buffer is too small */ rc = -EINVAL; } else if (len > 0) { /* wrote something */ - if (copy_to_user(buffer, tmpstr, len)) + if (copy_to_user(buffer, tmpstr, len)) { rc = -EFAULT; - else { + } else { off += 1; *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off); } @@ -399,9 +399,9 @@ static int proc_lnet_routers(struct ctl_table *table, int write, if (len > *lenp) { /* linux-supplied buffer is too small */ rc = -EINVAL; } else if (len > 0) { /* wrote something */ - if (copy_to_user(buffer, tmpstr, len)) + if (copy_to_user(buffer, tmpstr, len)) { rc = -EFAULT; - else { + } else { off += 1; *ppos = LNET_PROC_POS_MAKE(0, ver, 0, off); } diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index ab0a3f7cf366..914d842929a7 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -254,9 +254,8 @@ lstcon_group_decref(lstcon_group_t *grp) lstcon_group_drain(grp, 0); - for (i = 0; i < LST_NODE_HASHSIZE; i++) { + for (i = 0; i < LST_NODE_HASHSIZE; i++) LASSERT(list_empty(&grp->grp_ndl_hash[i])); - } LIBCFS_FREE(grp, offsetof(lstcon_group_t, grp_ndl_hash[LST_NODE_HASHSIZE])); @@ -2084,9 +2083,8 @@ lstcon_console_fini(void) LASSERT(list_empty(&console_session.ses_bat_list)); LASSERT(list_empty(&console_session.ses_trans_list)); - for (i = 0; i < LST_NODE_HASHSIZE; i++) { + for (i = 0; i < LST_NODE_HASHSIZE; i++) LASSERT(list_empty(&console_session.ses_ndl_hash[i])); - } LIBCFS_FREE(console_session.ses_ndl_hash, sizeof(struct list_head) * LST_GLOBAL_HASHSIZE); diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index 5c299d6aa2ce..906e26abcd0e 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -508,11 +508,10 @@ srpc_destroy_client_rpc(srpc_client_rpc_t *rpc) LASSERT(!srpc_event_pending(rpc)); LASSERT(atomic_read(&rpc->crpc_refcount) == 0); - if (rpc->crpc_fini == NULL) { + if (rpc->crpc_fini == NULL) LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); - } else { + else (*rpc->crpc_fini) (rpc); - } return; } -- cgit From 06ace26edc140034c7f340bf41b9a2f8cbb2a3ba Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:08 -0500 Subject: staging: lustre: fix all NULL comparisons in LNet layer This removes every instance of checking a variable against NULL in the LNet source code. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/lnet/lib-lnet.h | 12 +- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 208 ++++++++++----------- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 142 +++++++------- .../staging/lustre/lnet/klnds/socklnd/socklnd.c | 122 ++++++------ .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 82 ++++---- .../lustre/lnet/klnds/socklnd/socklnd_lib.c | 28 +-- .../lustre/lnet/klnds/socklnd/socklnd_proto.c | 46 ++--- drivers/staging/lustre/lnet/lnet/acceptor.c | 16 +- drivers/staging/lustre/lnet/lnet/api-ni.c | 78 ++++---- drivers/staging/lustre/lnet/lnet/config.c | 83 ++++---- drivers/staging/lustre/lnet/lnet/lib-eq.c | 18 +- drivers/staging/lustre/lnet/lnet/lib-md.c | 10 +- drivers/staging/lustre/lnet/lnet/lib-me.c | 16 +- drivers/staging/lustre/lnet/lnet/lib-move.c | 142 +++++++------- drivers/staging/lustre/lnet/lnet/lib-msg.c | 20 +- drivers/staging/lustre/lnet/lnet/lib-ptl.c | 20 +- drivers/staging/lustre/lnet/lnet/lib-socket.c | 16 +- drivers/staging/lustre/lnet/lnet/lo.c | 8 +- drivers/staging/lustre/lnet/lnet/nidstrings.c | 48 ++--- drivers/staging/lustre/lnet/lnet/peer.c | 20 +- drivers/staging/lustre/lnet/lnet/router.c | 68 +++---- drivers/staging/lustre/lnet/lnet/router_proc.c | 43 +++-- drivers/staging/lustre/lnet/selftest/brw_test.c | 22 +-- drivers/staging/lustre/lnet/selftest/conctl.c | 157 ++++++++-------- drivers/staging/lustre/lnet/selftest/conrpc.c | 36 ++-- drivers/staging/lustre/lnet/selftest/console.c | 64 +++---- drivers/staging/lustre/lnet/selftest/framework.c | 108 +++++------ drivers/staging/lustre/lnet/selftest/module.c | 4 +- drivers/staging/lustre/lnet/selftest/ping_test.c | 8 +- drivers/staging/lustre/lnet/selftest/rpc.c | 47 +++-- drivers/staging/lustre/lnet/selftest/selftest.h | 4 +- drivers/staging/lustre/lnet/selftest/timer.c | 2 +- 32 files changed, 846 insertions(+), 852 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index b8be9b6c1c03..618126b196e4 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -197,7 +197,7 @@ lnet_md_alloc(lnet_md_t *umd) LIBCFS_ALLOC(md, size); - if (md != NULL) { + if (md) { /* Set here in case of early free */ md->md_options = umd->options; md->md_niov = niov; @@ -267,7 +267,7 @@ lnet_res_lh_invalidate(lnet_libhandle_t *lh) static inline void lnet_eq2handle(lnet_handle_eq_t *handle, lnet_eq_t *eq) { - if (eq == NULL) { + if (!eq) { LNetInvalidateHandle(handle); return; } @@ -281,7 +281,7 @@ lnet_handle2eq(lnet_handle_eq_t *handle) lnet_libhandle_t *lh; lh = lnet_res_lh_lookup(&the_lnet.ln_eq_container, handle->cookie); - if (lh == NULL) + if (!lh) return NULL; return lh_entry(lh, lnet_eq_t, eq_lh); @@ -303,7 +303,7 @@ lnet_handle2md(lnet_handle_md_t *handle) cpt = lnet_cpt_of_cookie(handle->cookie); lh = lnet_res_lh_lookup(the_lnet.ln_md_containers[cpt], handle->cookie); - if (lh == NULL) + if (!lh) return NULL; return lh_entry(lh, lnet_libmd_t, md_lh); @@ -322,7 +322,7 @@ lnet_wire_handle2md(lnet_handle_wire_t *wh) cpt = lnet_cpt_of_cookie(wh->wh_object_cookie); lh = lnet_res_lh_lookup(the_lnet.ln_md_containers[cpt], wh->wh_object_cookie); - if (lh == NULL) + if (!lh) return NULL; return lh_entry(lh, lnet_libmd_t, md_lh); @@ -344,7 +344,7 @@ lnet_handle2me(lnet_handle_me_t *handle) cpt = lnet_cpt_of_cookie(handle->cookie); lh = lnet_res_lh_lookup(the_lnet.ln_me_containers[cpt], handle->cookie); - if (lh == NULL) + if (!lh) return NULL; return lh_entry(lh, lnet_me_t, me_lh); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index db551e4d4382..a3d654ad2107 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -330,11 +330,11 @@ int kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid) int cpt = lnet_cpt_of_nid(nid); unsigned long flags; - LASSERT(net != NULL); + LASSERT(net); LASSERT(nid != LNET_NID_ANY); LIBCFS_CPT_ALLOC(peer, lnet_cpt_table(), cpt, sizeof(*peer)); - if (peer == NULL) { + if (!peer) { CERROR("Cannot allocate peer\n"); return -ENOMEM; } @@ -369,7 +369,7 @@ void kiblnd_destroy_peer(kib_peer_t *peer) { kib_net_t *net = peer->ibp_ni->ni_data; - LASSERT(net != NULL); + LASSERT(net); LASSERT(atomic_read(&peer->ibp_refcount) == 0); LASSERT(!kiblnd_peer_active(peer)); LASSERT(peer->ibp_connecting == 0); @@ -604,7 +604,7 @@ static void kiblnd_setup_mtu_locked(struct rdma_cm_id *cmid) int mtu; /* XXX There is no path record for iWARP, set by netdev->change_mtu? */ - if (cmid->route.path_rec == NULL) + if (!cmid->route.path_rec) return; mtu = kiblnd_translate_mtu(*kiblnd_tunables.kib_ib_mtu); @@ -626,7 +626,7 @@ static int kiblnd_get_completion_vector(kib_conn_t *conn, int cpt) return 0; mask = cfs_cpt_cpumask(lnet_cpt_table(), cpt); - if (mask == NULL) + if (!mask) return 0; /* hash NID to CPU id in this partition... */ @@ -665,7 +665,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, int rc; int i; - LASSERT(net != NULL); + LASSERT(net); LASSERT(!in_interrupt()); dev = net->ibn_dev; @@ -677,14 +677,14 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, LIBCFS_CPT_ALLOC(init_qp_attr, lnet_cpt_table(), cpt, sizeof(*init_qp_attr)); - if (init_qp_attr == NULL) { + if (!init_qp_attr) { CERROR("Can't allocate qp_attr for %s\n", libcfs_nid2str(peer->ibp_nid)); goto failed_0; } LIBCFS_CPT_ALLOC(conn, lnet_cpt_table(), cpt, sizeof(*conn)); - if (conn == NULL) { + if (!conn) { CERROR("Can't allocate connection for %s\n", libcfs_nid2str(peer->ibp_nid)); goto failed_1; @@ -706,7 +706,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, LIBCFS_CPT_ALLOC(conn->ibc_connvars, lnet_cpt_table(), cpt, sizeof(*conn->ibc_connvars)); - if (conn->ibc_connvars == NULL) { + if (!conn->ibc_connvars) { CERROR("Can't allocate in-progress connection state\n"); goto failed_2; } @@ -741,7 +741,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, LIBCFS_CPT_ALLOC(conn->ibc_rxs, lnet_cpt_table(), cpt, IBLND_RX_MSGS(version) * sizeof(kib_rx_t)); - if (conn->ibc_rxs == NULL) { + if (!conn->ibc_rxs) { CERROR("Cannot allocate RX buffers\n"); goto failed_2; } @@ -874,7 +874,7 @@ void kiblnd_destroy_conn(kib_conn_t *conn) case IBLND_CONN_DISCONNECTED: /* connvars should have been freed already */ - LASSERT(conn->ibc_connvars == NULL); + LASSERT(!conn->ibc_connvars); break; case IBLND_CONN_INIT: @@ -882,28 +882,28 @@ void kiblnd_destroy_conn(kib_conn_t *conn) } /* conn->ibc_cmid might be destroyed by CM already */ - if (cmid != NULL && cmid->qp != NULL) + if (cmid && cmid->qp) rdma_destroy_qp(cmid); - if (conn->ibc_cq != NULL) { + if (conn->ibc_cq) { rc = ib_destroy_cq(conn->ibc_cq); if (rc != 0) CWARN("Error destroying CQ: %d\n", rc); } - if (conn->ibc_rx_pages != NULL) + if (conn->ibc_rx_pages) kiblnd_unmap_rx_descs(conn); - if (conn->ibc_rxs != NULL) { + if (conn->ibc_rxs) { LIBCFS_FREE(conn->ibc_rxs, IBLND_RX_MSGS(conn->ibc_version) * sizeof(kib_rx_t)); } - if (conn->ibc_connvars != NULL) + if (conn->ibc_connvars) LIBCFS_FREE(conn->ibc_connvars, sizeof(*conn->ibc_connvars)); - if (conn->ibc_hdev != NULL) + if (conn->ibc_hdev) kiblnd_hdev_decref(conn->ibc_hdev); /* See CAVEAT EMPTOR above in kiblnd_create_conn */ @@ -1040,14 +1040,14 @@ int kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg) rc = 0; conn = kiblnd_get_conn_by_idx(ni, data->ioc_count); - if (conn == NULL) { + if (!conn) { rc = -ENOENT; break; } - LASSERT(conn->ibc_cmid != NULL); + LASSERT(conn->ibc_cmid); data->ioc_nid = conn->ibc_peer->ibp_nid; - if (conn->ibc_cmid->route.path_rec == NULL) + if (!conn->ibc_cmid->route.path_rec) data->ioc_u32[0] = 0; /* iWarp has no path MTU */ else data->ioc_u32[0] = @@ -1078,7 +1078,7 @@ void kiblnd_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) read_lock_irqsave(glock, flags); peer = kiblnd_find_peer_locked(nid); - if (peer != NULL) { + if (peer) { LASSERT(peer->ibp_connecting > 0 || /* creating conns */ peer->ibp_accepting > 0 || !list_empty(&peer->ibp_conns)); /* active conn */ @@ -1094,7 +1094,7 @@ void kiblnd_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) * peer is not persistent in hash, trigger peer creation * and connection establishment with a NULL tx */ - if (peer == NULL) + if (!peer) kiblnd_launch_tx(ni, NULL, nid); CDEBUG(D_NET, "Peer %s %p, alive %ld secs ago\n", @@ -1108,7 +1108,7 @@ void kiblnd_free_pages(kib_pages_t *p) int i; for (i = 0; i < npages; i++) { - if (p->ibp_pages[i] != NULL) + if (p->ibp_pages[i]) __free_page(p->ibp_pages[i]); } @@ -1122,7 +1122,7 @@ int kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages) LIBCFS_CPT_ALLOC(p, lnet_cpt_table(), cpt, offsetof(kib_pages_t, ibp_pages[npages])); - if (p == NULL) { + if (!p) { CERROR("Can't allocate descriptor for %d pages\n", npages); return -ENOMEM; } @@ -1134,7 +1134,7 @@ int kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages) p->ibp_pages[i] = alloc_pages_node( cfs_cpt_spread_node(lnet_cpt_table(), cpt), GFP_NOFS, 0); - if (p->ibp_pages[i] == NULL) { + if (!p->ibp_pages[i]) { CERROR("Can't allocate page %d of %d\n", i, npages); kiblnd_free_pages(p); return -ENOMEM; @@ -1150,8 +1150,8 @@ void kiblnd_unmap_rx_descs(kib_conn_t *conn) kib_rx_t *rx; int i; - LASSERT(conn->ibc_rxs != NULL); - LASSERT(conn->ibc_hdev != NULL); + LASSERT(conn->ibc_rxs); + LASSERT(conn->ibc_hdev); for (i = 0; i < IBLND_RX_MSGS(conn->ibc_version); i++) { rx = &conn->ibc_rxs[i]; @@ -1215,7 +1215,7 @@ static void kiblnd_unmap_tx_pool(kib_tx_pool_t *tpo) LASSERT(tpo->tpo_pool.po_allocated == 0); - if (hdev == NULL) + if (!hdev) return; for (i = 0; i < tpo->tpo_pool.po_size; i++) { @@ -1267,7 +1267,7 @@ static void kiblnd_map_tx_pool(kib_tx_pool_t *tpo) int ipage; int i; - LASSERT(net != NULL); + LASSERT(net); dev = net->ibn_dev; @@ -1310,7 +1310,7 @@ struct ib_mr *kiblnd_find_dma_mr(kib_hca_dev_t *hdev, __u64 addr, __u64 size) { __u64 index; - LASSERT(hdev->ibh_mrs[0] != NULL); + LASSERT(hdev->ibh_mrs[0]); if (hdev->ibh_nmrs == 1) return hdev->ibh_mrs[0]; @@ -1330,7 +1330,7 @@ struct ib_mr *kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd) struct ib_mr *mr; int i; - LASSERT(hdev->ibh_mrs[0] != NULL); + LASSERT(hdev->ibh_mrs[0]); if (*kiblnd_tunables.kib_map_on_demand > 0 && *kiblnd_tunables.kib_map_on_demand <= rd->rd_nfrags) @@ -1344,10 +1344,10 @@ struct ib_mr *kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd) mr = kiblnd_find_dma_mr(hdev, rd->rd_frags[i].rf_addr, rd->rd_frags[i].rf_nob); - if (prev_mr == NULL) + if (!prev_mr) prev_mr = mr; - if (mr == NULL || prev_mr != mr) { + if (!mr || prev_mr != mr) { /* Can't covered by one single MR */ mr = NULL; break; @@ -1361,10 +1361,10 @@ static void kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool) { LASSERT(pool->fpo_map_count == 0); - if (pool->fpo_fmr_pool != NULL) + if (pool->fpo_fmr_pool) ib_destroy_fmr_pool(pool->fpo_fmr_pool); - if (pool->fpo_hdev != NULL) + if (pool->fpo_hdev) kiblnd_hdev_decref(pool->fpo_hdev); LIBCFS_FREE(pool, sizeof(*pool)); @@ -1414,7 +1414,7 @@ static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, int rc; LIBCFS_CPT_ALLOC(fpo, lnet_cpt_table(), fps->fps_cpt, sizeof(*fpo)); - if (fpo == NULL) + if (!fpo) return -ENOMEM; fpo->fpo_hdev = kiblnd_current_hdev(dev); @@ -1439,7 +1439,7 @@ static int kiblnd_create_fmr_pool(kib_fmr_poolset_t *fps, static void kiblnd_fail_fmr_poolset(kib_fmr_poolset_t *fps, struct list_head *zombies) { - if (fps->fps_net == NULL) /* intialized? */ + if (!fps->fps_net) /* intialized? */ return; spin_lock(&fps->fps_lock); @@ -1460,7 +1460,7 @@ static void kiblnd_fail_fmr_poolset(kib_fmr_poolset_t *fps, static void kiblnd_fini_fmr_poolset(kib_fmr_poolset_t *fps) { - if (fps->fps_net != NULL) { /* initialized? */ + if (fps->fps_net) { /* initialized? */ kiblnd_destroy_fmr_pool_list(&fps->fps_failed_pool_list); kiblnd_destroy_fmr_pool_list(&fps->fps_pool_list); } @@ -1634,14 +1634,14 @@ static void kiblnd_destroy_pool_list(struct list_head *head) pool = list_entry(head->next, kib_pool_t, po_list); list_del(&pool->po_list); - LASSERT(pool->po_owner != NULL); + LASSERT(pool->po_owner); pool->po_owner->ps_pool_destroy(pool); } } static void kiblnd_fail_poolset(kib_poolset_t *ps, struct list_head *zombies) { - if (ps->ps_net == NULL) /* intialized? */ + if (!ps->ps_net) /* intialized? */ return; spin_lock(&ps->ps_lock); @@ -1660,7 +1660,7 @@ static void kiblnd_fail_poolset(kib_poolset_t *ps, struct list_head *zombies) static void kiblnd_fini_poolset(kib_poolset_t *ps) { - if (ps->ps_net != NULL) { /* initialized? */ + if (ps->ps_net) { /* initialized? */ kiblnd_destroy_pool_list(&ps->ps_failed_pool_list); kiblnd_destroy_pool_list(&ps->ps_pool_list); } @@ -1719,7 +1719,7 @@ void kiblnd_pool_free_node(kib_pool_t *pool, struct list_head *node) spin_lock(&ps->ps_lock); - if (ps->ps_node_fini != NULL) + if (ps->ps_node_fini) ps->ps_node_fini(pool, node); LASSERT(pool->po_allocated > 0); @@ -1757,7 +1757,7 @@ struct list_head *kiblnd_pool_alloc_node(kib_poolset_t *ps) node = pool->po_free_list.next; list_del(node); - if (ps->ps_node_init != NULL) { + if (ps->ps_node_init) { /* still hold the lock */ ps->ps_node_init(pool, node); } @@ -1809,35 +1809,35 @@ static void kiblnd_destroy_tx_pool(kib_pool_t *pool) LASSERT(pool->po_allocated == 0); - if (tpo->tpo_tx_pages != NULL) { + if (tpo->tpo_tx_pages) { kiblnd_unmap_tx_pool(tpo); kiblnd_free_pages(tpo->tpo_tx_pages); } - if (tpo->tpo_tx_descs == NULL) + if (!tpo->tpo_tx_descs) goto out; for (i = 0; i < pool->po_size; i++) { kib_tx_t *tx = &tpo->tpo_tx_descs[i]; list_del(&tx->tx_list); - if (tx->tx_pages != NULL) + if (tx->tx_pages) LIBCFS_FREE(tx->tx_pages, LNET_MAX_IOV * sizeof(*tx->tx_pages)); - if (tx->tx_frags != NULL) + if (tx->tx_frags) LIBCFS_FREE(tx->tx_frags, IBLND_MAX_RDMA_FRAGS * sizeof(*tx->tx_frags)); - if (tx->tx_wrq != NULL) + if (tx->tx_wrq) LIBCFS_FREE(tx->tx_wrq, (1 + IBLND_MAX_RDMA_FRAGS) * sizeof(*tx->tx_wrq)); - if (tx->tx_sge != NULL) + if (tx->tx_sge) LIBCFS_FREE(tx->tx_sge, (1 + IBLND_MAX_RDMA_FRAGS) * sizeof(*tx->tx_sge)); - if (tx->tx_rd != NULL) + if (tx->tx_rd) LIBCFS_FREE(tx->tx_rd, offsetof(kib_rdma_desc_t, rd_frags[IBLND_MAX_RDMA_FRAGS])); @@ -1866,7 +1866,7 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, kib_tx_pool_t *tpo; LIBCFS_CPT_ALLOC(tpo, lnet_cpt_table(), ps->ps_cpt, sizeof(*tpo)); - if (tpo == NULL) { + if (!tpo) { CERROR("Failed to allocate TX pool\n"); return -ENOMEM; } @@ -1885,7 +1885,7 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, LIBCFS_CPT_ALLOC(tpo->tpo_tx_descs, lnet_cpt_table(), ps->ps_cpt, size * sizeof(kib_tx_t)); - if (tpo->tpo_tx_descs == NULL) { + if (!tpo->tpo_tx_descs) { CERROR("Can't allocate %d tx descriptors\n", size); ps->ps_pool_destroy(pool); return -ENOMEM; @@ -1897,17 +1897,17 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, kib_tx_t *tx = &tpo->tpo_tx_descs[i]; tx->tx_pool = tpo; - if (ps->ps_net->ibn_fmr_ps != NULL) { + if (ps->ps_net->ibn_fmr_ps) { LIBCFS_CPT_ALLOC(tx->tx_pages, lnet_cpt_table(), ps->ps_cpt, LNET_MAX_IOV * sizeof(*tx->tx_pages)); - if (tx->tx_pages == NULL) + if (!tx->tx_pages) break; } LIBCFS_CPT_ALLOC(tx->tx_frags, lnet_cpt_table(), ps->ps_cpt, IBLND_MAX_RDMA_FRAGS * sizeof(*tx->tx_frags)); - if (tx->tx_frags == NULL) + if (!tx->tx_frags) break; sg_init_table(tx->tx_frags, IBLND_MAX_RDMA_FRAGS); @@ -1915,19 +1915,19 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, LIBCFS_CPT_ALLOC(tx->tx_wrq, lnet_cpt_table(), ps->ps_cpt, (1 + IBLND_MAX_RDMA_FRAGS) * sizeof(*tx->tx_wrq)); - if (tx->tx_wrq == NULL) + if (!tx->tx_wrq) break; LIBCFS_CPT_ALLOC(tx->tx_sge, lnet_cpt_table(), ps->ps_cpt, (1 + IBLND_MAX_RDMA_FRAGS) * sizeof(*tx->tx_sge)); - if (tx->tx_sge == NULL) + if (!tx->tx_sge) break; LIBCFS_CPT_ALLOC(tx->tx_rd, lnet_cpt_table(), ps->ps_cpt, offsetof(kib_rdma_desc_t, rd_frags[IBLND_MAX_RDMA_FRAGS])); - if (tx->tx_rd == NULL) + if (!tx->tx_rd) break; } @@ -1958,23 +1958,23 @@ static void kiblnd_net_fini_pools(kib_net_t *net) kib_tx_poolset_t *tps; kib_fmr_poolset_t *fps; - if (net->ibn_tx_ps != NULL) { + if (net->ibn_tx_ps) { tps = net->ibn_tx_ps[i]; kiblnd_fini_poolset(&tps->tps_poolset); } - if (net->ibn_fmr_ps != NULL) { + if (net->ibn_fmr_ps) { fps = net->ibn_fmr_ps[i]; kiblnd_fini_fmr_poolset(fps); } } - if (net->ibn_tx_ps != NULL) { + if (net->ibn_tx_ps) { cfs_percpt_free(net->ibn_tx_ps); net->ibn_tx_ps = NULL; } - if (net->ibn_fmr_ps != NULL) { + if (net->ibn_fmr_ps) { cfs_percpt_free(net->ibn_fmr_ps); net->ibn_fmr_ps = NULL; } @@ -2009,7 +2009,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) * TX pool must be created later than FMR, see LU-2268 * for details */ - LASSERT(net->ibn_tx_ps == NULL); + LASSERT(!net->ibn_tx_ps); /* * premapping can fail if ibd_nmr > 1, so we always create @@ -2018,14 +2018,14 @@ 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)); - if (net->ibn_fmr_ps == NULL) { + if (!net->ibn_fmr_ps) { CERROR("Failed to allocate FMR pool array\n"); rc = -ENOMEM; goto failed; } for (i = 0; i < ncpts; i++) { - cpt = (cpts == NULL) ? i : cpts[i]; + cpt = !cpts ? i : cpts[i]; rc = kiblnd_init_fmr_poolset(net->ibn_fmr_ps[cpt], cpt, net, kiblnd_fmr_pool_size(ncpts), kiblnd_fmr_flush_trigger(ncpts)); @@ -2053,14 +2053,14 @@ 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)); - if (net->ibn_tx_ps == NULL) { + if (!net->ibn_tx_ps) { CERROR("Failed to allocate tx pool array\n"); rc = -ENOMEM; goto failed; } for (i = 0; i < ncpts; i++) { - cpt = (cpts == NULL) ? i : cpts[i]; + cpt = !cpts ? i : cpts[i]; rc = kiblnd_init_poolset(&net->ibn_tx_ps[cpt]->tps_poolset, cpt, net, "TX", kiblnd_tx_pool_size(ncpts), @@ -2112,11 +2112,11 @@ static void kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev) { int i; - if (hdev->ibh_nmrs == 0 || hdev->ibh_mrs == NULL) + if (hdev->ibh_nmrs == 0 || !hdev->ibh_mrs) return; for (i = 0; i < hdev->ibh_nmrs; i++) { - if (hdev->ibh_mrs[i] == NULL) + if (!hdev->ibh_mrs[i]) break; ib_dereg_mr(hdev->ibh_mrs[i]); @@ -2131,10 +2131,10 @@ void kiblnd_hdev_destroy(kib_hca_dev_t *hdev) { kiblnd_hdev_cleanup_mrs(hdev); - if (hdev->ibh_pd != NULL) + if (hdev->ibh_pd) ib_dealloc_pd(hdev->ibh_pd); - if (hdev->ibh_cmid != NULL) + if (hdev->ibh_cmid) rdma_destroy_id(hdev->ibh_cmid); LIBCFS_FREE(hdev, sizeof(*hdev)); @@ -2151,7 +2151,7 @@ static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev) return rc; LIBCFS_ALLOC(hdev->ibh_mrs, 1 * sizeof(*hdev->ibh_mrs)); - if (hdev->ibh_mrs == NULL) { + if (!hdev->ibh_mrs) { CERROR("Failed to allocate MRs table\n"); return -ENOMEM; } @@ -2185,8 +2185,8 @@ static int kiblnd_dev_need_failover(kib_dev_t *dev) struct sockaddr_in dstaddr; int rc; - if (dev->ibd_hdev == NULL || /* initializing */ - dev->ibd_hdev->ibh_cmid == NULL || /* listener is dead */ + if (!dev->ibd_hdev || /* initializing */ + !dev->ibd_hdev->ibh_cmid || /* listener is dead */ *kiblnd_tunables.kib_dev_failover > 1) /* debugging */ return 1; @@ -2218,7 +2218,7 @@ static int kiblnd_dev_need_failover(kib_dev_t *dev) dstaddr.sin_family = AF_INET; rc = rdma_resolve_addr(cmid, (struct sockaddr *)&srcaddr, (struct sockaddr *)&dstaddr, 1); - if (rc != 0 || cmid->device == NULL) { + if (rc != 0 || !cmid->device) { CERROR("Failed to bind %s:%pI4h to device(%p): %d\n", dev->ibd_ifname, &dev->ibd_ifip, cmid->device, rc); @@ -2247,14 +2247,14 @@ int kiblnd_dev_failover(kib_dev_t *dev) int i; LASSERT(*kiblnd_tunables.kib_dev_failover > 1 || - dev->ibd_can_failover || dev->ibd_hdev == NULL); + dev->ibd_can_failover || !dev->ibd_hdev); rc = kiblnd_dev_need_failover(dev); if (rc <= 0) goto out; - if (dev->ibd_hdev != NULL && - dev->ibd_hdev->ibh_cmid != NULL) { + if (dev->ibd_hdev && + dev->ibd_hdev->ibh_cmid) { /* * XXX it's not good to close old listener at here, * because we can fail to create new listener. @@ -2289,7 +2289,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) /* Bind to failover device or port */ rc = rdma_bind_addr(cmid, (struct sockaddr *)&addr); - if (rc != 0 || cmid->device == NULL) { + if (rc != 0 || !cmid->device) { CERROR("Failed to bind %s:%pI4h to device(%p): %d\n", dev->ibd_ifname, &dev->ibd_ifip, cmid->device, rc); @@ -2298,7 +2298,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) } LIBCFS_ALLOC(hdev, sizeof(*hdev)); - if (hdev == NULL) { + if (!hdev) { CERROR("Failed to allocate kib_hca_dev\n"); rdma_destroy_id(cmid); rc = -ENOMEM; @@ -2354,7 +2354,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) kiblnd_destroy_pool_list(&zombie_ppo); if (!list_empty(&zombie_fpo)) kiblnd_destroy_fmr_pool_list(&zombie_fpo); - if (hdev != NULL) + if (hdev) kiblnd_hdev_decref(hdev); if (rc != 0) @@ -2373,7 +2373,7 @@ void kiblnd_destroy_dev(kib_dev_t *dev) list_del(&dev->ibd_fail_list); list_del(&dev->ibd_list); - if (dev->ibd_hdev != NULL) + if (dev->ibd_hdev) kiblnd_hdev_decref(dev->ibd_hdev); LIBCFS_FREE(dev, sizeof(*dev)); @@ -2401,11 +2401,11 @@ static kib_dev_t *kiblnd_create_dev(char *ifname) } LIBCFS_ALLOC(dev, sizeof(*dev)); - if (dev == NULL) + if (!dev) return NULL; netdev = dev_get_by_name(&init_net, ifname); - if (netdev == NULL) { + if (!netdev) { dev->ibd_can_failover = 0; } else { dev->ibd_can_failover = !!(netdev->flags & IFF_MASTER); @@ -2443,7 +2443,7 @@ static void kiblnd_base_shutdown(void) case IBLND_INIT_ALL: case IBLND_INIT_DATA: - LASSERT(kiblnd_data.kib_peers != NULL); + LASSERT(kiblnd_data.kib_peers); for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) LASSERT(list_empty(&kiblnd_data.kib_peers[i])); LASSERT(list_empty(&kiblnd_data.kib_connd_zombies)); @@ -2480,13 +2480,13 @@ static void kiblnd_base_shutdown(void) break; } - if (kiblnd_data.kib_peers != NULL) { + if (kiblnd_data.kib_peers) { LIBCFS_FREE(kiblnd_data.kib_peers, sizeof(struct list_head) * kiblnd_data.kib_peer_hash_size); } - if (kiblnd_data.kib_scheds != NULL) + if (kiblnd_data.kib_scheds) cfs_percpt_free(kiblnd_data.kib_scheds); kiblnd_data.kib_init = IBLND_INIT_NOTHING; @@ -2502,7 +2502,7 @@ void kiblnd_shutdown(lnet_ni_t *ni) LASSERT(kiblnd_data.kib_init == IBLND_INIT_ALL); - if (net == NULL) + if (!net) goto out; write_lock_irqsave(g_lock, flags); @@ -2542,7 +2542,7 @@ void kiblnd_shutdown(lnet_ni_t *ni) case IBLND_INIT_NOTHING: LASSERT(atomic_read(&net->ibn_nconns) == 0); - if (net->ibn_dev != NULL && + if (net->ibn_dev && net->ibn_dev->ibd_nnets == 0) kiblnd_destroy_dev(net->ibn_dev); @@ -2579,7 +2579,7 @@ static int kiblnd_base_startup(void) kiblnd_data.kib_peer_hash_size = IBLND_PEER_HASH_SIZE; LIBCFS_ALLOC(kiblnd_data.kib_peers, sizeof(struct list_head) * kiblnd_data.kib_peer_hash_size); - if (kiblnd_data.kib_peers == NULL) + if (!kiblnd_data.kib_peers) goto failed; for (i = 0; i < kiblnd_data.kib_peer_hash_size; i++) INIT_LIST_HEAD(&kiblnd_data.kib_peers[i]); @@ -2592,7 +2592,7 @@ static int kiblnd_base_startup(void) kiblnd_data.kib_scheds = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*sched)); - if (kiblnd_data.kib_scheds == NULL) + if (!kiblnd_data.kib_scheds) goto failed; cfs_percpt_for_each(sched, i, kiblnd_data.kib_scheds) { @@ -2700,7 +2700,7 @@ static int kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, for (i = 0; i < ncpts; i++) { struct kib_sched_info *sched; - cpt = (cpts == NULL) ? i : cpts[i]; + cpt = !cpts ? i : cpts[i]; sched = kiblnd_data.kib_scheds[cpt]; if (!newdev && sched->ibs_nthreads > 0) @@ -2728,21 +2728,21 @@ static kib_dev_t *kiblnd_dev_search(char *ifname) if (strcmp(&dev->ibd_ifname[0], ifname) == 0) return dev; - if (alias != NULL) + if (alias) continue; colon2 = strchr(dev->ibd_ifname, ':'); - if (colon != NULL) + if (colon) *colon = 0; - if (colon2 != NULL) + if (colon2) *colon2 = 0; if (strcmp(&dev->ibd_ifname[0], ifname) == 0) alias = dev; - if (colon != NULL) + if (colon) *colon = ':'; - if (colon2 != NULL) + if (colon2) *colon2 = ':'; } return alias; @@ -2768,7 +2768,7 @@ int kiblnd_startup(lnet_ni_t *ni) LIBCFS_ALLOC(net, sizeof(*net)); ni->ni_data = net; - if (net == NULL) + if (!net) goto net_failed; ktime_get_real_ts64(&tv); @@ -2780,11 +2780,11 @@ int kiblnd_startup(lnet_ni_t *ni) ni->ni_peertxcredits = *kiblnd_tunables.kib_peertxcredits; ni->ni_peerrtrcredits = *kiblnd_tunables.kib_peerrtrcredits; - if (ni->ni_interfaces[0] != NULL) { + if (ni->ni_interfaces[0]) { /* Use the IPoIB interface specified in 'networks=' */ CLASSERT(LNET_MAX_INTERFACES > 1); - if (ni->ni_interfaces[1] != NULL) { + if (ni->ni_interfaces[1]) { CERROR("Multiple interfaces not supported\n"); goto failed; } @@ -2801,12 +2801,12 @@ int kiblnd_startup(lnet_ni_t *ni) ibdev = kiblnd_dev_search(ifname); - newdev = ibdev == NULL; + newdev = !ibdev; /* hmm...create kib_dev even for alias */ - if (ibdev == NULL || strcmp(&ibdev->ibd_ifname[0], ifname) != 0) + if (!ibdev || strcmp(&ibdev->ibd_ifname[0], ifname) != 0) ibdev = kiblnd_create_dev(ifname); - if (ibdev == NULL) + if (!ibdev) goto failed; net->ibn_dev = ibdev; @@ -2833,7 +2833,7 @@ int kiblnd_startup(lnet_ni_t *ni) return 0; failed: - if (net->ibn_dev == NULL && ibdev != NULL) + if (!net->ibn_dev && ibdev) kiblnd_destroy_dev(ibdev); net_failed: diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index d9c708987ddf..674a4eea3870 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -50,12 +50,12 @@ kiblnd_tx_done(lnet_ni_t *ni, kib_tx_t *tx) int rc; int i; - LASSERT(net != NULL); + LASSERT(net); LASSERT(!in_interrupt()); LASSERT(!tx->tx_queued); /* mustn't be queued for sending */ LASSERT(tx->tx_sending == 0); /* mustn't be awaiting sent callback */ LASSERT(!tx->tx_waiting); /* mustn't be awaiting peer response */ - LASSERT(tx->tx_pool != NULL); + LASSERT(tx->tx_pool); kiblnd_unmap_tx(ni, tx); @@ -64,7 +64,7 @@ kiblnd_tx_done(lnet_ni_t *ni, kib_tx_t *tx) lntmsg[1] = tx->tx_lntmsg[1]; tx->tx_lntmsg[1] = NULL; rc = tx->tx_status; - if (tx->tx_conn != NULL) { + if (tx->tx_conn) { LASSERT(ni == tx->tx_conn->ibc_peer->ibp_ni); kiblnd_conn_decref(tx->tx_conn); @@ -78,7 +78,7 @@ kiblnd_tx_done(lnet_ni_t *ni, kib_tx_t *tx) /* delay finalize until my descs have been freed */ for (i = 0; i < 2; i++) { - if (lntmsg[i] == NULL) + if (!lntmsg[i]) continue; lnet_finalize(ni, lntmsg[i], rc); @@ -111,7 +111,7 @@ kiblnd_get_idle_tx(lnet_ni_t *ni, lnet_nid_t target) tps = net->ibn_tx_ps[lnet_cpt_of_nid(target)]; node = kiblnd_pool_alloc_node(&tps->tps_poolset); - if (node == NULL) + if (!node) return NULL; tx = container_of(node, kib_tx_t, tx_list); @@ -120,9 +120,9 @@ kiblnd_get_idle_tx(lnet_ni_t *ni, lnet_nid_t target) LASSERT(tx->tx_sending == 0); LASSERT(!tx->tx_waiting); LASSERT(tx->tx_status == 0); - LASSERT(tx->tx_conn == NULL); - LASSERT(tx->tx_lntmsg[0] == NULL); - LASSERT(tx->tx_lntmsg[1] == NULL); + LASSERT(!tx->tx_conn); + LASSERT(!tx->tx_lntmsg[0]); + LASSERT(!tx->tx_lntmsg[1]); LASSERT(tx->tx_nfrags == 0); return tx; @@ -152,14 +152,14 @@ kiblnd_post_rx(kib_rx_t *rx, int credit) struct ib_mr *mr; int rc; - LASSERT(net != NULL); + LASSERT(net); LASSERT(!in_interrupt()); LASSERT(credit == IBLND_POSTRX_NO_CREDIT || credit == IBLND_POSTRX_PEER_CREDIT || credit == IBLND_POSTRX_RSRVD_CREDIT); mr = kiblnd_find_dma_mr(conn->ibc_hdev, rx->rx_msgaddr, IBLND_MSG_SIZE); - LASSERT(mr != NULL); + LASSERT(mr); rx->rx_sge.lkey = mr->lkey; rx->rx_sge.addr = rx->rx_msgaddr; @@ -251,7 +251,7 @@ kiblnd_handle_completion(kib_conn_t *conn, int txtype, int status, __u64 cookie) spin_lock(&conn->ibc_lock); tx = kiblnd_find_waiting_tx_locked(conn, txtype, cookie); - if (tx == NULL) { + if (!tx) { spin_unlock(&conn->ibc_lock); CWARN("Unmatched completion type %x cookie %#llx from %s\n", @@ -285,7 +285,7 @@ kiblnd_send_completion(kib_conn_t *conn, int type, int status, __u64 cookie) lnet_ni_t *ni = conn->ibc_peer->ibp_ni; kib_tx_t *tx = kiblnd_get_idle_tx(ni, conn->ibc_peer->ibp_nid); - if (tx == NULL) { + if (!tx) { CERROR("Can't get tx for completion %x for %s\n", type, libcfs_nid2str(conn->ibc_peer->ibp_nid)); return; @@ -397,11 +397,11 @@ kiblnd_handle_rx(kib_rx_t *rx) spin_lock(&conn->ibc_lock); tx = kiblnd_find_waiting_tx_locked(conn, IBLND_MSG_PUT_REQ, msg->ibm_u.putack.ibpam_src_cookie); - if (tx != NULL) + if (tx) list_del(&tx->tx_list); spin_unlock(&conn->ibc_lock); - if (tx == NULL) { + if (!tx) { CERROR("Unmatched PUT_ACK from %s\n", libcfs_nid2str(conn->ibc_peer->ibp_nid)); rc = -EPROTO; @@ -470,7 +470,7 @@ kiblnd_rx_complete(kib_rx_t *rx, int status, int nob) int rc; int err = -EIO; - LASSERT(net != NULL); + LASSERT(net); LASSERT(rx->rx_nob < 0); /* was posted */ rx->rx_nob = 0; /* isn't now */ @@ -538,7 +538,7 @@ kiblnd_kvaddr_to_page(unsigned long vaddr) if (is_vmalloc_addr((void *)vaddr)) { page = vmalloc_to_page((void *)vaddr); - LASSERT(page != NULL); + LASSERT(page); return page; } #ifdef CONFIG_HIGHMEM @@ -550,7 +550,7 @@ kiblnd_kvaddr_to_page(unsigned long vaddr) } #endif page = virt_to_page(vaddr); - LASSERT(page != NULL); + LASSERT(page); return page; } @@ -566,8 +566,8 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob) int rc; int i; - LASSERT(tx->tx_pool != NULL); - LASSERT(tx->tx_pool->tpo_pool.po_owner != NULL); + LASSERT(tx->tx_pool); + LASSERT(tx->tx_pool->tpo_pool.po_owner); hdev = tx->tx_pool->tpo_hdev; @@ -605,7 +605,7 @@ static void kiblnd_unmap_tx(lnet_ni_t *ni, kib_tx_t *tx) { kib_net_t *net = ni->ni_data; - LASSERT(net != NULL); + LASSERT(net); if (net->ibn_fmr_ps && tx->fmr.fmr_pfmr) { kiblnd_fmr_pool_unmap(&tx->fmr, tx->tx_status); @@ -648,13 +648,13 @@ static int kiblnd_map_tx(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, /* looking for pre-mapping MR */ mr = kiblnd_find_rd_dma_mr(hdev, rd); - if (mr != NULL) { + if (mr) { /* found pre-mapping MR */ rd->rd_key = (rd != tx->tx_rd) ? mr->rkey : mr->lkey; return 0; } - if (net->ibn_fmr_ps != NULL) + if (net->ibn_fmr_ps) return kiblnd_fmr_map_tx(net, tx, rd, nob); return -EINVAL; @@ -673,7 +673,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, LASSERT(nob > 0); LASSERT(niov > 0); - LASSERT(net != NULL); + LASSERT(net); while (offset >= iov->iov_len) { offset -= iov->iov_len; @@ -689,7 +689,7 @@ kiblnd_setup_rd_iov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, vaddr = ((unsigned long)iov->iov_base) + offset; page_offset = vaddr & (PAGE_SIZE - 1); page = kiblnd_kvaddr_to_page(vaddr); - if (page == NULL) { + if (!page) { CERROR("Can't find page\n"); return -EFAULT; } @@ -725,7 +725,7 @@ kiblnd_setup_rd_kiov(lnet_ni_t *ni, kib_tx_t *tx, kib_rdma_desc_t *rd, LASSERT(nob > 0); LASSERT(nkiov > 0); - LASSERT(net != NULL); + LASSERT(net); while (offset >= kiov->kiov_len) { offset -= kiov->kiov_len; @@ -925,11 +925,11 @@ kiblnd_check_sends(kib_conn_t *conn) spin_unlock(&conn->ibc_lock); tx = kiblnd_get_idle_tx(ni, conn->ibc_peer->ibp_nid); - if (tx != NULL) + if (tx) kiblnd_init_tx_msg(ni, tx, IBLND_MSG_NOOP, 0); spin_lock(&conn->ibc_lock); - if (tx != NULL) + if (tx) kiblnd_queue_tx_locked(tx, conn); } @@ -1035,7 +1035,7 @@ kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob) kiblnd_init_msg(tx->tx_msg, type, body_nob); mr = kiblnd_find_dma_mr(hdev, tx->tx_msgaddr, nob); - LASSERT(mr != NULL); + LASSERT(mr); sge->lkey = mr->lkey; sge->addr = tx->tx_msgaddr; @@ -1149,7 +1149,7 @@ kiblnd_queue_tx_locked(kib_tx_t *tx, kib_conn_t *conn) tx->tx_queued = 1; tx->tx_deadline = jiffies + (*kiblnd_tunables.kib_timeout * HZ); - if (tx->tx_conn == NULL) { + if (!tx->tx_conn) { kiblnd_conn_addref(conn); tx->tx_conn = conn; LASSERT(tx->tx_msg->ibm_type != IBLND_MSG_PUT_DONE); @@ -1247,7 +1247,7 @@ kiblnd_connect_peer(kib_peer_t *peer) struct sockaddr_in dstaddr; int rc; - LASSERT(net != NULL); + LASSERT(net); LASSERT(peer->ibp_connecting > 0); cmid = kiblnd_rdma_create_id(kiblnd_cm_callback, peer, RDMA_PS_TCP, @@ -1288,7 +1288,7 @@ kiblnd_connect_peer(kib_peer_t *peer) goto failed2; } - LASSERT(cmid->device != NULL); + LASSERT(cmid->device); CDEBUG(D_NET, "%s: connection bound to %s:%pI4h:%s\n", libcfs_nid2str(peer->ibp_nid), dev->ibd_ifname, &dev->ibd_ifip, cmid->device->name); @@ -1316,8 +1316,8 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) * If I get here, I've committed to send, so I complete the tx with * failure on any problems */ - LASSERT(tx == NULL || tx->tx_conn == NULL); /* only set when assigned a conn */ - LASSERT(tx == NULL || tx->tx_nwrq > 0); /* work items have been set up */ + LASSERT(!tx || !tx->tx_conn); /* only set when assigned a conn */ + LASSERT(!tx || tx->tx_nwrq > 0); /* work items have been set up */ /* * First time, just use a read lock since I expect to find my peer @@ -1326,14 +1326,14 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) read_lock_irqsave(g_lock, flags); peer = kiblnd_find_peer_locked(nid); - if (peer != NULL && !list_empty(&peer->ibp_conns)) { + if (peer && !list_empty(&peer->ibp_conns)) { /* Found a peer with an established connection */ conn = kiblnd_get_conn_locked(peer); kiblnd_conn_addref(conn); /* 1 ref for me... */ read_unlock_irqrestore(g_lock, flags); - if (tx != NULL) + if (tx) kiblnd_queue_tx(tx, conn); kiblnd_conn_decref(conn); /* ...to here */ return; @@ -1344,12 +1344,12 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) write_lock(g_lock); peer = kiblnd_find_peer_locked(nid); - if (peer != NULL) { + if (peer) { if (list_empty(&peer->ibp_conns)) { /* found a peer, but it's still connecting... */ LASSERT(peer->ibp_connecting != 0 || peer->ibp_accepting != 0); - if (tx != NULL) + if (tx) list_add_tail(&tx->tx_list, &peer->ibp_tx_queue); write_unlock_irqrestore(g_lock, flags); @@ -1359,7 +1359,7 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) write_unlock_irqrestore(g_lock, flags); - if (tx != NULL) + if (tx) kiblnd_queue_tx(tx, conn); kiblnd_conn_decref(conn); /* ...to here */ } @@ -1372,7 +1372,7 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) rc = kiblnd_create_peer(ni, &peer, nid); if (rc != 0) { CERROR("Can't create peer %s\n", libcfs_nid2str(nid)); - if (tx != NULL) { + if (tx) { tx->tx_status = -EHOSTUNREACH; tx->tx_waiting = 0; kiblnd_tx_done(ni, tx); @@ -1383,12 +1383,12 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) write_lock_irqsave(g_lock, flags); peer2 = kiblnd_find_peer_locked(nid); - if (peer2 != NULL) { + if (peer2) { if (list_empty(&peer2->ibp_conns)) { /* found a peer, but it's still connecting... */ LASSERT(peer2->ibp_connecting != 0 || peer2->ibp_accepting != 0); - if (tx != NULL) + if (tx) list_add_tail(&tx->tx_list, &peer2->ibp_tx_queue); write_unlock_irqrestore(g_lock, flags); @@ -1398,7 +1398,7 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) write_unlock_irqrestore(g_lock, flags); - if (tx != NULL) + if (tx) kiblnd_queue_tx(tx, conn); kiblnd_conn_decref(conn); /* ...to here */ } @@ -1414,7 +1414,7 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) /* always called with a ref on ni, which prevents ni being shutdown */ LASSERT(((kib_net_t *)ni->ni_data)->ibn_shutdown == 0); - if (tx != NULL) + if (tx) list_add_tail(&tx->tx_list, &peer->ibp_tx_queue); kiblnd_peer_addref(peer); @@ -1456,7 +1456,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) /* Thread context */ LASSERT(!in_interrupt()); /* payload is either all vaddrs or all pages */ - LASSERT(!(payload_kiov != NULL && payload_iov != NULL)); + LASSERT(!(payload_kiov && payload_iov)); switch (type) { default: @@ -1477,7 +1477,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) break; /* send IMMEDIATE */ tx = kiblnd_get_idle_tx(ni, target.nid); - if (tx == NULL) { + if (!tx) { CERROR("Can't allocate txd for GET to %s\n", libcfs_nid2str(target.nid)); return -ENOMEM; @@ -1509,7 +1509,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) kiblnd_init_tx_msg(ni, tx, IBLND_MSG_GET_REQ, nob); tx->tx_lntmsg[1] = lnet_create_reply_msg(ni, lntmsg); - if (tx->tx_lntmsg[1] == NULL) { + if (!tx->tx_lntmsg[1]) { CERROR("Can't create reply for GET -> %s\n", libcfs_nid2str(target.nid)); kiblnd_tx_done(ni, tx); @@ -1529,14 +1529,14 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) break; /* send IMMEDIATE */ tx = kiblnd_get_idle_tx(ni, target.nid); - if (tx == NULL) { + if (!tx) { CERROR("Can't allocate %s txd for %s\n", type == LNET_MSG_PUT ? "PUT" : "REPLY", libcfs_nid2str(target.nid)); return -ENOMEM; } - if (payload_kiov == NULL) + if (!payload_kiov) rc = kiblnd_setup_rd_iov(ni, tx, tx->tx_rd, payload_niov, payload_iov, payload_offset, payload_nob); @@ -1568,7 +1568,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) <= IBLND_MSG_SIZE); tx = kiblnd_get_idle_tx(ni, target.nid); - if (tx == NULL) { + if (!tx) { CERROR("Can't send %d to %s: tx descs exhausted\n", type, libcfs_nid2str(target.nid)); return -ENOMEM; @@ -1577,7 +1577,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) ibmsg = tx->tx_msg; ibmsg->ibm_u.immediate.ibim_hdr = *hdr; - if (payload_kiov != NULL) + if (payload_kiov) lnet_copy_kiov2flat(IBLND_MSG_SIZE, ibmsg, offsetof(kib_msg_t, ibm_u.immediate.ibim_payload), payload_niov, payload_kiov, @@ -1609,7 +1609,7 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) int rc; tx = kiblnd_get_idle_tx(ni, rx->rx_conn->ibc_peer->ibp_nid); - if (tx == NULL) { + if (!tx) { CERROR("Can't get tx for REPLY to %s\n", libcfs_nid2str(target.nid)); goto failed_0; @@ -1617,7 +1617,7 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) if (nob == 0) rc = 0; - else if (kiov == NULL) + else if (!kiov) rc = kiblnd_setup_rd_iov(ni, tx, tx->tx_rd, niov, iov, offset, nob); else @@ -1673,7 +1673,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, LASSERT(mlen <= rlen); LASSERT(!in_interrupt()); /* Either all pages or all vaddrs */ - LASSERT(!(kiov != NULL && iov != NULL)); + LASSERT(!(kiov && iov)); switch (rxmsg->ibm_type) { default: @@ -1689,7 +1689,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, break; } - if (kiov != NULL) + if (kiov) lnet_copy_flat2kiov(niov, kiov, offset, IBLND_MSG_SIZE, rxmsg, offsetof(kib_msg_t, ibm_u.immediate.ibim_payload), @@ -1714,7 +1714,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, } tx = kiblnd_get_idle_tx(ni, conn->ibc_peer->ibp_nid); - if (tx == NULL) { + if (!tx) { CERROR("Can't allocate tx for %s\n", libcfs_nid2str(conn->ibc_peer->ibp_nid)); /* Not replying will break the connection */ @@ -1724,7 +1724,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, txmsg = tx->tx_msg; rd = &txmsg->ibm_u.putack.ibpam_rd; - if (kiov == NULL) + if (!kiov) rc = kiblnd_setup_rd_iov(ni, tx, rd, niov, iov, offset, mlen); else @@ -1756,7 +1756,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, } case IBLND_MSG_GET_REQ: - if (lntmsg != NULL) { + if (lntmsg) { /* Optimized GET; RDMA lntmsg's payload */ kiblnd_reply(ni, rx, lntmsg); } else { @@ -2177,7 +2177,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) /* cmid inherits 'context' from the corresponding listener id */ ibdev = (kib_dev_t *)cmid->context; - LASSERT(ibdev != NULL); + LASSERT(ibdev); memset(&rej, 0, sizeof(rej)); rej.ibr_magic = IBLND_MSG_MAGIC; @@ -2228,17 +2228,17 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) nid = reqmsg->ibm_srcnid; ni = lnet_net2ni(LNET_NIDNET(reqmsg->ibm_dstnid)); - if (ni != NULL) { + if (ni) { net = (kib_net_t *)ni->ni_data; rej.ibr_incarnation = net->ibn_incarnation; } - if (ni == NULL || /* no matching net */ + if (!ni || /* no matching net */ ni->ni_nid != reqmsg->ibm_dstnid || /* right NET, wrong NID! */ net->ibn_dev != ibdev) { /* wrong device */ CERROR("Can't accept %s on %s (%s:%d:%pI4h): bad dst nid %s\n", libcfs_nid2str(nid), - ni == NULL ? "NA" : libcfs_nid2str(ni->ni_nid), + !ni ? "NA" : libcfs_nid2str(ni->ni_nid), ibdev->ibd_ifname, ibdev->ibd_nnets, &ibdev->ibd_ifip, libcfs_nid2str(reqmsg->ibm_dstnid)); @@ -2307,7 +2307,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) write_lock_irqsave(g_lock, flags); peer2 = kiblnd_find_peer_locked(nid); - if (peer2 != NULL) { + if (peer2) { if (peer2->ibp_version == 0) { peer2->ibp_version = version; peer2->ibp_incarnation = reqmsg->ibm_srcstamp; @@ -2365,7 +2365,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) } conn = kiblnd_create_conn(peer, cmid, IBLND_CONN_PASSIVE_WAIT, version); - if (conn == NULL) { + if (!conn) { kiblnd_peer_connect_failed(peer, 0, -ENOMEM); kiblnd_peer_decref(peer); rej.ibr_why = IBLND_REJECT_NO_RESOURCES; @@ -2419,7 +2419,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) return 0; failed: - if (ni != NULL) + if (ni) lnet_ni_decref(ni); rej.ibr_version = version; @@ -2488,9 +2488,9 @@ kiblnd_reconnect(kib_conn_t *conn, int version, CNETERR("%s: retrying (%s), %x, %x, queue_dep: %d, max_frag: %d, msg_size: %d\n", libcfs_nid2str(peer->ibp_nid), reason, IBLND_MSG_VERSION, version, - cp != NULL ? cp->ibcp_queue_depth : IBLND_MSG_QUEUE_SIZE(version), - cp != NULL ? cp->ibcp_max_frags : IBLND_RDMA_FRAGS(version), - cp != NULL ? cp->ibcp_max_msg_size : IBLND_MSG_SIZE); + cp ? cp->ibcp_queue_depth : IBLND_MSG_QUEUE_SIZE(version), + cp ? cp->ibcp_max_frags : IBLND_RDMA_FRAGS(version), + cp ? cp->ibcp_max_msg_size : IBLND_MSG_SIZE); kiblnd_connect_peer(peer); } @@ -2595,7 +2595,7 @@ kiblnd_rejected(kib_conn_t *conn, int reason, void *priv, int priv_nob) case IBLND_REJECT_MSG_QUEUE_SIZE: CERROR("%s rejected: incompatible message queue depth %d, %d\n", libcfs_nid2str(peer->ibp_nid), - cp != NULL ? cp->ibcp_queue_depth : + cp ? cp->ibcp_queue_depth : IBLND_MSG_QUEUE_SIZE(rej->ibr_version), IBLND_MSG_QUEUE_SIZE(conn->ibc_version)); break; @@ -2603,7 +2603,7 @@ kiblnd_rejected(kib_conn_t *conn, int reason, void *priv, int priv_nob) case IBLND_REJECT_RDMA_FRAGS: CERROR("%s rejected: incompatible # of RDMA fragments %d, %d\n", libcfs_nid2str(peer->ibp_nid), - cp != NULL ? cp->ibcp_max_frags : + cp ? cp->ibcp_max_frags : IBLND_RDMA_FRAGS(rej->ibr_version), IBLND_RDMA_FRAGS(conn->ibc_version)); break; @@ -2647,7 +2647,7 @@ kiblnd_check_connreply(kib_conn_t *conn, void *priv, int priv_nob) int rc = kiblnd_unpack_msg(msg, priv_nob); unsigned long flags; - LASSERT(net != NULL); + LASSERT(net); if (rc != 0) { CERROR("Can't unpack connack from %s: %d\n", @@ -2755,7 +2755,7 @@ kiblnd_active_connect(struct rdma_cm_id *cmid) read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); conn = kiblnd_create_conn(peer, cmid, IBLND_CONN_ACTIVE_CONNECT, version); - if (conn == NULL) { + if (!conn) { kiblnd_peer_connect_failed(peer, 1, -ENOMEM); kiblnd_peer_decref(peer); /* lose cmid's ref */ return -ENOMEM; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 7c9525da0058..2c2d1c921f6c 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -70,7 +70,7 @@ ksocknal_create_route(__u32 ipaddr, int port) ksock_route_t *route; LIBCFS_ALLOC(route, sizeof(*route)); - if (route == NULL) + if (!route) return NULL; atomic_set(&route->ksnr_refcount, 1); @@ -93,7 +93,7 @@ ksocknal_destroy_route(ksock_route_t *route) { LASSERT(atomic_read(&route->ksnr_refcount) == 0); - if (route->ksnr_peer != NULL) + if (route->ksnr_peer) ksocknal_peer_decref(route->ksnr_peer); LIBCFS_FREE(route, sizeof(*route)); @@ -110,7 +110,7 @@ ksocknal_create_peer(ksock_peer_t **peerp, lnet_ni_t *ni, lnet_process_id_t id) LASSERT(!in_interrupt()); LIBCFS_ALLOC(peer, sizeof(*peer)); - if (peer == NULL) + if (!peer) return -ENOMEM; peer->ksnp_ni = ni; @@ -208,7 +208,7 @@ ksocknal_find_peer(lnet_ni_t *ni, lnet_process_id_t id) read_lock(&ksocknal_data.ksnd_global_lock); peer = ksocknal_find_peer_locked(ni, id); - if (peer != NULL) /* +1 ref for caller? */ + if (peer) /* +1 ref for caller? */ ksocknal_peer_addref(peer); read_unlock(&ksocknal_data.ksnd_global_lock); @@ -231,7 +231,7 @@ ksocknal_unlink_peer_locked(ksock_peer_t *peer) * All IPs in peer->ksnp_passive_ips[] come from the * interface list, therefore the call must succeed. */ - LASSERT(iface != NULL); + LASSERT(iface); CDEBUG(D_NET, "peer=%p iface=%p ksni_nroutes=%d\n", peer, iface, iface->ksni_nroutes); @@ -347,13 +347,13 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn) iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni, route->ksnr_myipaddr); - if (iface != NULL) + if (iface) iface->ksni_nroutes--; } route->ksnr_myipaddr = conn->ksnc_myipaddr; iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni, route->ksnr_myipaddr); - if (iface != NULL) + if (iface) iface->ksni_nroutes++; } @@ -375,7 +375,7 @@ ksocknal_add_route_locked(ksock_peer_t *peer, ksock_route_t *route) ksock_route_t *route2; LASSERT(!peer->ksnp_closing); - LASSERT(route->ksnr_peer == NULL); + LASSERT(!route->ksnr_peer); LASSERT(!route->ksnr_scheduled); LASSERT(!route->ksnr_connecting); LASSERT(route->ksnr_connected == 0); @@ -432,7 +432,7 @@ ksocknal_del_route_locked(ksock_route_t *route) if (route->ksnr_myipaddr != 0) { iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni, route->ksnr_myipaddr); - if (iface != NULL) + if (iface) iface->ksni_nroutes--; } @@ -470,7 +470,7 @@ ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port) return rc; route = ksocknal_create_route(ipaddr, port); - if (route == NULL) { + if (!route) { ksocknal_peer_decref(peer); return -ENOMEM; } @@ -481,7 +481,7 @@ ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port) LASSERT(((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0); peer2 = ksocknal_find_peer_locked(ni, id); - if (peer2 != NULL) { + if (peer2) { ksocknal_peer_decref(peer); peer = peer2; } else { @@ -499,7 +499,7 @@ ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port) route2 = NULL; } - if (route2 == NULL) { + if (!route2) { ksocknal_add_route_locked(peer, route); route->ksnr_share_count++; } else { @@ -826,7 +826,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips) xor = ip ^ peerips[k]; this_netmatch = ((xor & iface->ksni_netmask) == 0) ? 1 : 0; - if (!(best_iface == NULL || + if (!(!best_iface || best_netmatch < this_netmatch || (best_netmatch == this_netmatch && best_npeers > iface->ksni_npeers))) @@ -894,13 +894,13 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, LASSERT(npeer_ipaddrs <= LNET_MAX_INTERFACES); for (i = 0; i < npeer_ipaddrs; i++) { - if (newroute != NULL) { + if (newroute) { newroute->ksnr_ipaddr = peer_ipaddrs[i]; } else { write_unlock_bh(global_lock); newroute = ksocknal_create_route(peer_ipaddrs[i], port); - if (newroute == NULL) + if (!newroute) return; write_lock_bh(global_lock); @@ -921,7 +921,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, route = NULL; } - if (route != NULL) + if (route) continue; best_iface = NULL; @@ -944,14 +944,14 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, route = NULL; } - if (route != NULL) + if (route) continue; this_netmatch = (((iface->ksni_ipaddr ^ newroute->ksnr_ipaddr) & iface->ksni_netmask) == 0) ? 1 : 0; - if (!(best_iface == NULL || + if (!(!best_iface || best_netmatch < this_netmatch || (best_netmatch == this_netmatch && best_nroutes > iface->ksni_nroutes))) @@ -962,7 +962,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, best_nroutes = iface->ksni_nroutes; } - if (best_iface == NULL) + if (!best_iface) continue; newroute->ksnr_myipaddr = best_iface->ksni_ipaddr; @@ -973,7 +973,7 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, } write_unlock_bh(global_lock); - if (newroute != NULL) + if (newroute) ksocknal_route_decref(newroute); } @@ -989,7 +989,7 @@ ksocknal_accept(lnet_ni_t *ni, struct socket *sock) LASSERT(rc == 0); /* we succeeded before */ LIBCFS_ALLOC(cr, sizeof(*cr)); - if (cr == NULL) { + if (!cr) { LCONSOLE_ERROR_MSG(0x12f, "Dropping connection request from %pI4h: memory exhausted\n", &peer_ip); return -ENOMEM; @@ -1042,12 +1042,12 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, int active; char *warn = NULL; - active = (route != NULL); + active = !!route; LASSERT(active == (type != SOCKLND_CONN_NONE)); LIBCFS_ALLOC(conn, sizeof(*conn)); - if (conn == NULL) { + if (!conn) { rc = -ENOMEM; goto failed_0; } @@ -1075,7 +1075,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, LIBCFS_ALLOC(hello, offsetof(ksock_hello_msg_t, kshm_ips[LNET_MAX_INTERFACES])); - if (hello == NULL) { + if (!hello) { rc = -ENOMEM; goto failed_1; } @@ -1103,7 +1103,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, conn->ksnc_proto = peer->ksnp_proto; write_unlock_bh(global_lock); - if (conn->ksnc_proto == NULL) { + if (!conn->ksnc_proto) { conn->ksnc_proto = &ksocknal_protocol_v3x; #if SOCKNAL_VERSION_DEBUG if (*ksocknal_tunables.ksnd_protocol == 2) @@ -1129,7 +1129,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, goto failed_1; LASSERT(rc == 0 || active); - LASSERT(conn->ksnc_proto != NULL); + LASSERT(conn->ksnc_proto); LASSERT(peerid.nid != LNET_NID_ANY); cpt = lnet_cpt_of_nid(peerid.nid); @@ -1148,7 +1148,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, LASSERT(((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0); peer2 = ksocknal_find_peer_locked(ni, peerid); - if (peer2 == NULL) { + if (!peer2) { /* * NB this puts an "empty" peer in the peer * table (which takes my ref) @@ -1184,7 +1184,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, goto failed_2; } - if (peer->ksnp_proto == NULL) { + if (!peer->ksnp_proto) { /* * Never connected before. * NB recv_hello may have returned EPROTO to signal my peer @@ -1386,7 +1386,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, write_unlock_bh(global_lock); - if (warn != NULL) { + if (warn) { if (rc < 0) CERROR("Not creating conn %s type %d: %s\n", libcfs_id2str(peerid), conn->ksnc_type, warn); @@ -1415,7 +1415,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, ksocknal_peer_decref(peer); failed_1: - if (hello != NULL) + if (hello) LIBCFS_FREE(hello, offsetof(ksock_hello_msg_t, kshm_ips[LNET_MAX_INTERFACES])); @@ -1447,7 +1447,7 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) list_del(&conn->ksnc_list); route = conn->ksnc_route; - if (route != NULL) { + if (route) { /* dissociate conn from route... */ LASSERT(!route->ksnr_deleted); LASSERT((route->ksnr_connected & (1 << conn->ksnc_type)) != 0); @@ -1462,7 +1462,7 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) conn2 = NULL; } - if (conn2 == NULL) + if (!conn2) route->ksnr_connected &= ~(1 << conn->ksnc_type); conn->ksnc_route = NULL; @@ -1534,7 +1534,7 @@ ksocknal_peer_failed(ksock_peer_t *peer) if ((peer->ksnp_id.pid & LNET_PID_USERFLAG) == 0 && list_empty(&peer->ksnp_conns) && peer->ksnp_accepting == 0 && - ksocknal_find_connecting_route_locked(peer) == NULL) { + !ksocknal_find_connecting_route_locked(peer)) { notify = 1; last_alive = peer->ksnp_last_alive; } @@ -1558,7 +1558,7 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn) * NB safe to finalize TXs because closing of socket will * abort all buffered data */ - LASSERT(conn->ksnc_sock == NULL); + LASSERT(!conn->ksnc_sock); spin_lock(&peer->ksnp_lock); @@ -1675,8 +1675,8 @@ ksocknal_destroy_conn(ksock_conn_t *conn) LASSERT(atomic_read(&conn->ksnc_conn_refcount) == 0); LASSERT(atomic_read(&conn->ksnc_sock_refcount) == 0); - LASSERT(conn->ksnc_sock == NULL); - LASSERT(conn->ksnc_route == NULL); + LASSERT(!conn->ksnc_sock); + LASSERT(!conn->ksnc_route); LASSERT(!conn->ksnc_tx_scheduled); LASSERT(!conn->ksnc_rx_scheduled); LASSERT(list_empty(&conn->ksnc_tx_queue)); @@ -1848,7 +1848,7 @@ ksocknal_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) read_lock(glock); peer = ksocknal_find_peer_locked(ni, id); - if (peer != NULL) { + if (peer) { struct list_head *tmp; ksock_conn_t *conn; int bufnob; @@ -1867,7 +1867,7 @@ ksocknal_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) } last_alive = peer->ksnp_last_alive; - if (ksocknal_find_connectable_route_locked(peer) == NULL) + if (!ksocknal_find_connectable_route_locked(peer)) connect = 0; } @@ -1889,7 +1889,7 @@ ksocknal_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) write_lock_bh(glock); peer = ksocknal_find_peer_locked(ni, id); - if (peer != NULL) + if (peer) ksocknal_launch_all_connections_locked(peer); write_unlock_bh(glock); @@ -1920,7 +1920,7 @@ ksocknal_push_peer(ksock_peer_t *peer) read_unlock(&ksocknal_data.ksnd_global_lock); - if (conn == NULL) + if (!conn) break; ksocknal_lib_push_conn(conn); @@ -1997,7 +1997,7 @@ ksocknal_add_interface(lnet_ni_t *ni, __u32 ipaddress, __u32 netmask) write_lock_bh(&ksocknal_data.ksnd_global_lock); iface = ksocknal_ip2iface(ni, ipaddress); - if (iface != NULL) { + if (iface) { /* silently ignore dups */ rc = 0; } else if (net->ksnn_ninterfaces == LNET_MAX_INTERFACES) { @@ -2207,7 +2207,7 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg) int nagle; ksock_conn_t *conn = ksocknal_get_conn_by_idx(ni, data->ioc_count); - if (conn == NULL) + if (!conn) return -ENOENT; ksocknal_lib_get_conn_tunables(conn, &txmem, &rxmem, &nagle); @@ -2258,12 +2258,12 @@ ksocknal_free_buffers(void) { LASSERT(atomic_read(&ksocknal_data.ksnd_nactive_txs) == 0); - if (ksocknal_data.ksnd_sched_info != NULL) { + if (ksocknal_data.ksnd_sched_info) { struct ksock_sched_info *info; int i; cfs_percpt_for_each(info, i, ksocknal_data.ksnd_sched_info) { - if (info->ksi_scheds != NULL) { + if (info->ksi_scheds) { LIBCFS_FREE(info->ksi_scheds, info->ksi_nthreads_max * sizeof(info->ksi_scheds[0])); @@ -2312,7 +2312,7 @@ ksocknal_base_shutdown(void) case SOCKNAL_INIT_ALL: case SOCKNAL_INIT_DATA: - LASSERT(ksocknal_data.ksnd_peers != NULL); + LASSERT(ksocknal_data.ksnd_peers); for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) LASSERT(list_empty(&ksocknal_data.ksnd_peers[i])); @@ -2322,10 +2322,10 @@ ksocknal_base_shutdown(void) LASSERT(list_empty(&ksocknal_data.ksnd_connd_connreqs)); LASSERT(list_empty(&ksocknal_data.ksnd_connd_routes)); - if (ksocknal_data.ksnd_sched_info != NULL) { + if (ksocknal_data.ksnd_sched_info) { cfs_percpt_for_each(info, i, ksocknal_data.ksnd_sched_info) { - if (info->ksi_scheds == NULL) + if (!info->ksi_scheds) continue; for (j = 0; j < info->ksi_nthreads_max; j++) { @@ -2346,10 +2346,10 @@ ksocknal_base_shutdown(void) wake_up_all(&ksocknal_data.ksnd_connd_waitq); wake_up_all(&ksocknal_data.ksnd_reaper_waitq); - if (ksocknal_data.ksnd_sched_info != NULL) { + if (ksocknal_data.ksnd_sched_info) { cfs_percpt_for_each(info, i, ksocknal_data.ksnd_sched_info) { - if (info->ksi_scheds == NULL) + if (!info->ksi_scheds) continue; for (j = 0; j < info->ksi_nthreads_max; j++) { @@ -2407,7 +2407,7 @@ ksocknal_base_startup(void) LIBCFS_ALLOC(ksocknal_data.ksnd_peers, sizeof(struct list_head) * ksocknal_data.ksnd_peer_hash_size); - if (ksocknal_data.ksnd_peers == NULL) + if (!ksocknal_data.ksnd_peers) return -ENOMEM; for (i = 0; i < ksocknal_data.ksnd_peer_hash_size; i++) @@ -2438,7 +2438,7 @@ ksocknal_base_startup(void) ksocknal_data.ksnd_sched_info = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*info)); - if (ksocknal_data.ksnd_sched_info == NULL) + if (!ksocknal_data.ksnd_sched_info) goto failed; cfs_percpt_for_each(info, i, ksocknal_data.ksnd_sched_info) { @@ -2461,7 +2461,7 @@ ksocknal_base_startup(void) LIBCFS_CPT_ALLOC(info->ksi_scheds, lnet_cpt_table(), i, info->ksi_nthreads_max * sizeof(*sched)); - if (info->ksi_scheds == NULL) + if (!info->ksi_scheds) goto failed; for (; nthrs > 0; nthrs--) { @@ -2547,7 +2547,7 @@ ksocknal_debug_peerhash(lnet_ni_t *ni) } } - if (peer != NULL) { + if (peer) { ksock_route_t *route; ksock_conn_t *conn; @@ -2703,7 +2703,7 @@ ksocknal_search_new_ipif(ksock_net_t *net) ksock_net_t *tmp; int j; - if (colon != NULL) /* ignore alias device */ + if (colon) /* ignore alias device */ *colon = 0; list_for_each_entry(tmp, &ksocknal_data.ksnd_nets, ksnn_list) { @@ -2712,11 +2712,11 @@ ksocknal_search_new_ipif(ksock_net_t *net) &tmp->ksnn_interfaces[j].ksni_name[0]; char *colon2 = strchr(ifnam2, ':'); - if (colon2 != NULL) + if (colon2) *colon2 = 0; found = strcmp(ifnam, ifnam2) == 0; - if (colon2 != NULL) + if (colon2) *colon2 = ':'; } if (found) @@ -2724,7 +2724,7 @@ ksocknal_search_new_ipif(ksock_net_t *net) } new_ipif += !found; - if (colon != NULL) + if (colon) *colon = ':'; } @@ -2789,7 +2789,7 @@ ksocknal_net_start_threads(ksock_net_t *net, __u32 *cpts, int ncpts) for (i = 0; i < ncpts; i++) { struct ksock_sched_info *info; - int cpt = (cpts == NULL) ? i : cpts[i]; + int cpt = !cpts ? i : cpts[i]; LASSERT(cpt < cfs_cpt_number(lnet_cpt_table())); info = ksocknal_data.ksnd_sched_info[cpt]; @@ -2820,7 +2820,7 @@ ksocknal_startup(lnet_ni_t *ni) } LIBCFS_ALLOC(net, sizeof(*net)); - if (net == NULL) + if (!net) goto fail_0; spin_lock_init(&net->ksnn_lock); @@ -2831,7 +2831,7 @@ ksocknal_startup(lnet_ni_t *ni) ni->ni_peertxcredits = *ksocknal_tunables.ksnd_peertxcredits; ni->ni_peerrtrcredits = *ksocknal_tunables.ksnd_peerrtrcredits; - if (ni->ni_interfaces[0] == NULL) { + if (!ni->ni_interfaces[0]) { rc = ksocknal_enumerate_interfaces(net); if (rc <= 0) goto fail_1; @@ -2841,7 +2841,7 @@ ksocknal_startup(lnet_ni_t *ni) for (i = 0; i < LNET_MAX_INTERFACES; i++) { int up; - if (ni->ni_interfaces[i] == NULL) + if (!ni->ni_interfaces[i]) break; rc = lnet_ipif_query(ni->ni_interfaces[i], &up, diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index 16c9bac99e96..f9ec607595a3 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -47,10 +47,10 @@ ksocknal_alloc_tx(int type, int size) spin_unlock(&ksocknal_data.ksnd_tx_lock); } - if (tx == NULL) + if (!tx) LIBCFS_ALLOC(tx, size); - if (tx == NULL) + if (!tx) return NULL; atomic_set(&tx->tx_refcount, 1); @@ -70,7 +70,7 @@ ksocknal_alloc_tx_noop(__u64 cookie, int nonblk) ksock_tx_t *tx; tx = ksocknal_alloc_tx(KSOCK_MSG_NOOP, KSOCK_NOOP_TX_SIZE); - if (tx == NULL) { + if (!tx) { CERROR("Can't allocate noop tx desc\n"); return NULL; } @@ -94,7 +94,7 @@ ksocknal_free_tx(ksock_tx_t *tx) { atomic_dec(&ksocknal_data.ksnd_nactive_txs); - if (tx->tx_lnetmsg == NULL && tx->tx_desc_size == KSOCK_NOOP_TX_SIZE) { + if (!tx->tx_lnetmsg && tx->tx_desc_size == KSOCK_NOOP_TX_SIZE) { /* it's a noop tx */ spin_lock(&ksocknal_data.ksnd_tx_lock); @@ -399,16 +399,16 @@ ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx) lnet_msg_t *lnetmsg = tx->tx_lnetmsg; int rc = (tx->tx_resid == 0 && !tx->tx_zc_aborted) ? 0 : -EIO; - LASSERT(ni != NULL || tx->tx_conn != NULL); + LASSERT(ni || tx->tx_conn); - if (tx->tx_conn != NULL) + if (tx->tx_conn) ksocknal_conn_decref(tx->tx_conn); - if (ni == NULL && tx->tx_conn != NULL) + if (!ni && tx->tx_conn) ni = tx->tx_conn->ksnc_peer->ksnp_ni; ksocknal_free_tx(tx); - if (lnetmsg != NULL) /* KSOCK_MSG_NOOP go without lnetmsg */ + if (lnetmsg) /* KSOCK_MSG_NOOP go without lnetmsg */ lnet_finalize(ni, lnetmsg, rc); } @@ -420,7 +420,7 @@ ksocknal_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int error) while (!list_empty(txlist)) { tx = list_entry(txlist->next, ksock_tx_t, tx_list); - if (error && tx->tx_lnetmsg != NULL) { + if (error && tx->tx_lnetmsg) { CNETERR("Deleting packet type %d len %d %s->%s\n", le32_to_cpu(tx->tx_lnetmsg->msg_hdr.type), le32_to_cpu(tx->tx_lnetmsg->msg_hdr.payload_length), @@ -615,7 +615,7 @@ ksocknal_launch_all_connections_locked(ksock_peer_t *peer) for (;;) { /* launch any/all connections that need it */ route = ksocknal_find_connectable_route_locked(peer); - if (route == NULL) + if (!route) return; ksocknal_launch_connection_locked(route); @@ -639,8 +639,8 @@ ksocknal_find_conn_locked(ksock_peer_t *peer, ksock_tx_t *tx, int nonblk) int rc; LASSERT(!c->ksnc_closing); - LASSERT(c->ksnc_proto != NULL && - c->ksnc_proto->pro_match_tx != NULL); + LASSERT(c->ksnc_proto && + c->ksnc_proto->pro_match_tx); rc = c->ksnc_proto->pro_match_tx(c, tx, nonblk); @@ -651,7 +651,7 @@ ksocknal_find_conn_locked(ksock_peer_t *peer, ksock_tx_t *tx, int nonblk) continue; case SOCKNAL_MATCH_YES: /* typed connection */ - if (typed == NULL || tnob > nob || + if (!typed || tnob > nob || (tnob == nob && *ksocknal_tunables.ksnd_round_robin && cfs_time_after(typed->ksnc_tx_last_post, c->ksnc_tx_last_post))) { typed = c; @@ -660,7 +660,7 @@ ksocknal_find_conn_locked(ksock_peer_t *peer, ksock_tx_t *tx, int nonblk) break; case SOCKNAL_MATCH_MAY: /* fallback connection */ - if (fallback == NULL || fnob > nob || + if (!fallback || fnob > nob || (fnob == nob && *ksocknal_tunables.ksnd_round_robin && cfs_time_after(fallback->ksnc_tx_last_post, c->ksnc_tx_last_post))) { fallback = c; @@ -671,9 +671,9 @@ ksocknal_find_conn_locked(ksock_peer_t *peer, ksock_tx_t *tx, int nonblk) } /* prefer the typed selection */ - conn = (typed != NULL) ? typed : fallback; + conn = (typed) ? typed : fallback; - if (conn != NULL) + if (conn) conn->ksnc_tx_last_post = cfs_time_current(); return conn; @@ -726,7 +726,7 @@ ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) LASSERT(tx->tx_resid == tx->tx_nob); CDEBUG(D_NET, "Packet %p type %d, nob %d niov %d nkiov %d\n", - tx, (tx->tx_lnetmsg != NULL) ? tx->tx_lnetmsg->msg_hdr.type : + tx, (tx->tx_lnetmsg) ? tx->tx_lnetmsg->msg_hdr.type : KSOCK_MSG_NOOP, tx->tx_nob, tx->tx_niov, tx->tx_nkiov); @@ -753,7 +753,7 @@ ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) * on a normal packet so I don't need to send it */ LASSERT(msg->ksm_zc_cookies[1] != 0); - LASSERT(conn->ksnc_proto->pro_queue_tx_zcack != NULL); + LASSERT(conn->ksnc_proto->pro_queue_tx_zcack); if (conn->ksnc_proto->pro_queue_tx_zcack(conn, tx, 0)) ztx = tx; /* ZC ACK piggybacked on ztx release tx later */ @@ -764,13 +764,13 @@ ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) * has been queued already? */ LASSERT(msg->ksm_zc_cookies[1] == 0); - LASSERT(conn->ksnc_proto->pro_queue_tx_msg != NULL); + LASSERT(conn->ksnc_proto->pro_queue_tx_msg); ztx = conn->ksnc_proto->pro_queue_tx_msg(conn, tx); /* ztx will be released later */ } - if (ztx != NULL) { + if (ztx) { atomic_sub(ztx->tx_nob, &conn->ksnc_tx_nob); list_add_tail(&ztx->tx_list, &sched->kss_zombie_noop_txs); } @@ -850,17 +850,17 @@ ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) int retry; int rc; - LASSERT(tx->tx_conn == NULL); + LASSERT(!tx->tx_conn); g_lock = &ksocknal_data.ksnd_global_lock; for (retry = 0;; retry = 1) { read_lock(g_lock); peer = ksocknal_find_peer_locked(ni, id); - if (peer != NULL) { - if (ksocknal_find_connectable_route_locked(peer) == NULL) { + if (peer) { + if (!ksocknal_find_connectable_route_locked(peer)) { conn = ksocknal_find_conn_locked(peer, tx, tx->tx_nonblk); - if (conn != NULL) { + if (conn) { /* * I've got no routes that need to be * connecting and I do have an actual @@ -879,7 +879,7 @@ ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) write_lock_bh(g_lock); peer = ksocknal_find_peer_locked(ni, id); - if (peer != NULL) + if (peer) break; write_unlock_bh(g_lock); @@ -908,7 +908,7 @@ ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) ksocknal_launch_all_connections_locked(peer); conn = ksocknal_find_conn_locked(peer, tx, tx->tx_nonblk); - if (conn != NULL) { + if (conn) { /* Connection exists; queue message on it */ ksocknal_queue_tx_locked(tx, conn); write_unlock_bh(g_lock); @@ -916,7 +916,7 @@ ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) } if (peer->ksnp_accepting > 0 || - ksocknal_find_connecting_route_locked(peer) != NULL) { + ksocknal_find_connecting_route_locked(peer)) { /* the message is going to be pinned to the peer */ tx->tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout); @@ -959,10 +959,10 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) LASSERT(payload_nob == 0 || payload_niov > 0); LASSERT(payload_niov <= LNET_MAX_IOV); /* payload is either all vaddrs or all pages */ - LASSERT(!(payload_kiov != NULL && payload_iov != NULL)); + LASSERT(!(payload_kiov && payload_iov)); LASSERT(!in_interrupt()); - if (payload_iov != NULL) + if (payload_iov) desc_size = offsetof(ksock_tx_t, tx_frags.virt.iov[1 + payload_niov]); else @@ -972,7 +972,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) if (lntmsg->msg_vmflush) mpflag = cfs_memory_pressure_get_and_set(); tx = ksocknal_alloc_tx(KSOCK_MSG_LNET, desc_size); - if (tx == NULL) { + if (!tx) { CERROR("Can't allocate tx desc type %d size %d\n", type, desc_size); if (lntmsg->msg_vmflush) @@ -983,7 +983,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) tx->tx_conn = NULL; /* set when assigned a conn */ tx->tx_lnetmsg = lntmsg; - if (payload_iov != NULL) { + if (payload_iov) { tx->tx_kiov = NULL; tx->tx_nkiov = 0; tx->tx_iov = tx->tx_frags.virt.iov; @@ -1048,7 +1048,7 @@ ksocknal_new_packet(ksock_conn_t *conn, int nob_to_skip) unsigned int niov; int skipped; - LASSERT(conn->ksnc_proto != NULL); + LASSERT(conn->ksnc_proto); if ((*ksocknal_tunables.ksnd_eager_ack & conn->ksnc_type) != 0) { /* Remind the socket to ack eagerly... */ @@ -1341,7 +1341,7 @@ ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, conn->ksnc_rx_nob_wanted = mlen; conn->ksnc_rx_nob_left = rlen; - if (mlen == 0 || iov != NULL) { + if (mlen == 0 || iov) { conn->ksnc_rx_nkiov = 0; conn->ksnc_rx_kiov = NULL; conn->ksnc_rx_iov = conn->ksnc_rx_iov_space.iov; @@ -1678,7 +1678,7 @@ ksocknal_send_hello(lnet_ni_t *ni, ksock_conn_t *conn, LASSERT(hello->kshm_nips <= LNET_MAX_INTERFACES); /* rely on caller to hold a ref on socket so it wouldn't disappear */ - LASSERT(conn->ksnc_proto != NULL); + LASSERT(conn->ksnc_proto); hello->kshm_src_nid = ni->ni_nid; hello->kshm_dst_nid = peer_nid; @@ -1717,7 +1717,7 @@ ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn, * EPROTO protocol version mismatch */ struct socket *sock = conn->ksnc_sock; - int active = (conn->ksnc_proto != NULL); + int active = !!conn->ksnc_proto; int timeout; int proto_match; int rc; @@ -1759,7 +1759,7 @@ ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn, } proto = ksocknal_parse_proto_version(hello); - if (proto == NULL) { + if (!proto) { if (!active) { /* unknown protocol from peer, tell peer my protocol */ conn->ksnc_proto = &ksocknal_protocol_v3x; @@ -1991,7 +1991,7 @@ ksocknal_connect(ksock_route_t *route) if (!list_empty(&peer->ksnp_tx_queue) && peer->ksnp_accepting == 0 && - ksocknal_find_connecting_route_locked(peer) == NULL) { + !ksocknal_find_connecting_route_locked(peer)) { ksock_conn_t *conn; /* @@ -2219,7 +2219,7 @@ ksocknal_connd(void *arg) ksocknal_data.ksnd_connd_running) { route = ksocknal_connd_get_route_locked(&timeout); } - if (route != NULL) { + if (route) { list_del(&route->ksnr_connd_list); ksocknal_data.ksnd_connd_connecting++; spin_unlock_bh(connd_lock); @@ -2407,7 +2407,7 @@ ksocknal_send_keepalive_locked(ksock_peer_t *peer) peer->ksnp_send_keepalive = cfs_time_shift(10); conn = ksocknal_find_conn_locked(peer, NULL, 1); - if (conn != NULL) { + if (conn) { sched = conn->ksnc_scheduler; spin_lock_bh(&sched->kss_lock); @@ -2424,7 +2424,7 @@ ksocknal_send_keepalive_locked(ksock_peer_t *peer) /* cookie = 1 is reserved for keepalive PING */ tx = ksocknal_alloc_tx_noop(1, 1); - if (tx == NULL) { + if (!tx) { read_lock(&ksocknal_data.ksnd_global_lock); return -ENOMEM; } @@ -2468,7 +2468,7 @@ ksocknal_check_peer_timeouts(int idx) conn = ksocknal_find_timed_out_conn(peer); - if (conn != NULL) { + if (conn) { read_unlock(&ksocknal_data.ksnd_global_lock); ksocknal_close_conn_and_siblings(conn, -ETIMEDOUT); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index db5662b13b20..40ce45ddeb76 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -126,7 +126,7 @@ ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) int nob; /* Not NOOP message */ - LASSERT(tx->tx_lnetmsg != NULL); + LASSERT(tx->tx_lnetmsg); /* * NB we can't trust socket ops to either consume our iovs @@ -147,7 +147,7 @@ ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) fragsize < tx->tx_resid) msgflg |= MSG_MORE; - if (sk->sk_prot->sendpage != NULL) { + if (sk->sk_prot->sendpage) { rc = sk->sk_prot->sendpage(sk, page, offset, fragsize, msgflg); } else { @@ -266,7 +266,7 @@ ksocknal_lib_recv_iov(ksock_conn_t *conn) static void ksocknal_lib_kiov_vunmap(void *addr) { - if (addr == NULL) + if (!addr) return; vunmap(addr); @@ -280,7 +280,7 @@ ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, int nob; int i; - if (!*ksocknal_tunables.ksnd_zc_recv || pages == NULL) + if (!*ksocknal_tunables.ksnd_zc_recv || !pages) return NULL; LASSERT(niov <= LNET_MAX_IOV); @@ -299,7 +299,7 @@ ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, } addr = vmap(pages, niov, VM_MAP, PAGE_KERNEL); - if (addr == NULL) + if (!addr) return NULL; iov->iov_base = addr + kiov[0].kiov_offset; @@ -342,7 +342,7 @@ ksocknal_lib_recv_kiov(ksock_conn_t *conn) * or leave them alone. */ addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages); - if (addr != NULL) { + if (addr) { nob = scratchiov[0].iov_len; n = 1; @@ -382,7 +382,7 @@ ksocknal_lib_recv_kiov(ksock_conn_t *conn) } } - if (addr != NULL) { + if (addr) { ksocknal_lib_kiov_vunmap(addr); } else { for (i = 0; i < niov; i++) @@ -400,7 +400,7 @@ ksocknal_lib_csum_tx(ksock_tx_t *tx) void *base; LASSERT(tx->tx_iov[0].iov_base == &tx->tx_msg); - LASSERT(tx->tx_conn != NULL); + LASSERT(tx->tx_conn); LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x); tx->tx_msg.ksm_csum = 0; @@ -408,7 +408,7 @@ ksocknal_lib_csum_tx(ksock_tx_t *tx) csum = ksocknal_csum(~0, tx->tx_iov[0].iov_base, tx->tx_iov[0].iov_len); - if (tx->tx_kiov != NULL) { + if (tx->tx_kiov) { for (i = 0; i < tx->tx_nkiov; i++) { base = kmap(tx->tx_kiov[i].kiov_page) + tx->tx_kiov[i].kiov_offset; @@ -606,7 +606,7 @@ ksocknal_data_ready(struct sock *sk) read_lock(&ksocknal_data.ksnd_global_lock); conn = sk->sk_user_data; - if (conn == NULL) { /* raced with ksocknal_terminate_conn */ + if (!conn) { /* raced with ksocknal_terminate_conn */ LASSERT(sk->sk_data_ready != &ksocknal_data_ready); sk->sk_data_ready(sk); } else { @@ -633,14 +633,14 @@ ksocknal_write_space(struct sock *sk) CDEBUG(D_NET, "sk %p wspace %d low water %d conn %p%s%s%s\n", sk, wspace, min_wpace, conn, - (conn == NULL) ? "" : (conn->ksnc_tx_ready ? + !conn ? "" : (conn->ksnc_tx_ready ? " ready" : " blocked"), - (conn == NULL) ? "" : (conn->ksnc_tx_scheduled ? + !conn ? "" : (conn->ksnc_tx_scheduled ? " scheduled" : " idle"), - (conn == NULL) ? "" : (list_empty(&conn->ksnc_tx_queue) ? + !conn ? "" : (list_empty(&conn->ksnc_tx_queue) ? " empty" : " queued")); - if (conn == NULL) { /* raced with ksocknal_terminate_conn */ + if (!conn) { /* raced with ksocknal_terminate_conn */ LASSERT(sk->sk_write_space != &ksocknal_write_space); sk->sk_write_space(sk); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index 041f97272ec3..d5046855e318 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -56,7 +56,7 @@ ksocknal_next_tx_carrier(ksock_conn_t *conn) /* Called holding BH lock: conn->ksnc_scheduler->kss_lock */ LASSERT(!list_empty(&conn->ksnc_tx_queue)); - LASSERT(tx != NULL); + LASSERT(tx); /* Next TX that can carry ZC-ACK or LNet message */ if (tx->tx_list.next == &conn->ksnc_tx_queue) { @@ -75,7 +75,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, { ksock_tx_t *tx = conn->ksnc_tx_carrier; - LASSERT(tx_ack == NULL || + LASSERT(!tx_ack || tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP); /* @@ -85,8 +85,8 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, * . There is tx can piggyback cookie of tx_ack (or cookie), * piggyback the cookie and return the tx. */ - if (tx == NULL) { - if (tx_ack != NULL) { + if (!tx) { + if (tx_ack) { list_add_tail(&tx_ack->tx_list, &conn->ksnc_tx_queue); conn->ksnc_tx_carrier = tx_ack; @@ -96,7 +96,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, if (tx->tx_msg.ksm_type == KSOCK_MSG_NOOP) { /* tx is noop zc-ack, can't piggyback zc-ack cookie */ - if (tx_ack != NULL) + if (tx_ack) list_add_tail(&tx_ack->tx_list, &conn->ksnc_tx_queue); return 0; @@ -105,7 +105,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, LASSERT(tx->tx_msg.ksm_type == KSOCK_MSG_LNET); LASSERT(tx->tx_msg.ksm_zc_cookies[1] == 0); - if (tx_ack != NULL) + if (tx_ack) cookie = tx_ack->tx_msg.ksm_zc_cookies[1]; /* piggyback the zc-ack cookie */ @@ -128,7 +128,7 @@ ksocknal_queue_tx_msg_v2(ksock_conn_t *conn, ksock_tx_t *tx_msg) * . If there is NOOP on the connection, piggyback the cookie * and replace the NOOP tx, and return the NOOP tx. */ - if (tx == NULL) { /* nothing on queue */ + if (!tx) { /* nothing on queue */ list_add_tail(&tx_msg->tx_list, &conn->ksnc_tx_queue); conn->ksnc_tx_carrier = tx_msg; return NULL; @@ -162,12 +162,12 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, return ksocknal_queue_tx_zcack_v2(conn, tx_ack, cookie); /* non-blocking ZC-ACK (to router) */ - LASSERT(tx_ack == NULL || + LASSERT(!tx_ack || tx_ack->tx_msg.ksm_type == KSOCK_MSG_NOOP); tx = conn->ksnc_tx_carrier; - if (tx == NULL) { - if (tx_ack != NULL) { + if (!tx) { + if (tx_ack) { list_add_tail(&tx_ack->tx_list, &conn->ksnc_tx_queue); conn->ksnc_tx_carrier = tx_ack; @@ -175,9 +175,9 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, return 0; } - /* conn->ksnc_tx_carrier != NULL */ + /* conn->ksnc_tx_carrier */ - if (tx_ack != NULL) + if (tx_ack) cookie = tx_ack->tx_msg.ksm_zc_cookies[1]; if (cookie == SOCKNAL_KEEPALIVE_PING) /* ignore keepalive PING */ @@ -261,7 +261,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, } /* failed to piggyback ZC-ACK */ - if (tx_ack != NULL) { + if (tx_ack) { list_add_tail(&tx_ack->tx_list, &conn->ksnc_tx_queue); /* the next tx can piggyback at least 1 ACK */ ksocknal_next_tx_carrier(conn); @@ -280,7 +280,7 @@ ksocknal_match_tx(ksock_conn_t *conn, ksock_tx_t *tx, int nonblk) return SOCKNAL_MATCH_YES; #endif - if (tx == NULL || tx->tx_lnetmsg == NULL) { + if (!tx || !tx->tx_lnetmsg) { /* noop packet */ nob = offsetof(ksock_msg_t, ksm_u); } else { @@ -319,7 +319,7 @@ ksocknal_match_tx_v3(ksock_conn_t *conn, ksock_tx_t *tx, int nonblk) { int nob; - if (tx == NULL || tx->tx_lnetmsg == NULL) + if (!tx || !tx->tx_lnetmsg) nob = offsetof(ksock_msg_t, ksm_u); else nob = tx->tx_lnetmsg->msg_len + sizeof(ksock_msg_t); @@ -334,7 +334,7 @@ ksocknal_match_tx_v3(ksock_conn_t *conn, ksock_tx_t *tx, int nonblk) case SOCKLND_CONN_ACK: if (nonblk) return SOCKNAL_MATCH_YES; - else if (tx == NULL || tx->tx_lnetmsg == NULL) + else if (!tx || !tx->tx_lnetmsg) return SOCKNAL_MATCH_MAY; else return SOCKNAL_MATCH_NO; @@ -369,10 +369,10 @@ ksocknal_handle_zcreq(ksock_conn_t *c, __u64 cookie, int remote) read_lock(&ksocknal_data.ksnd_global_lock); conn = ksocknal_find_conn_locked(peer, NULL, !!remote); - if (conn != NULL) { + if (conn) { ksock_sched_t *sched = conn->ksnc_scheduler; - LASSERT(conn->ksnc_proto->pro_queue_tx_zcack != NULL); + LASSERT(conn->ksnc_proto->pro_queue_tx_zcack); spin_lock_bh(&sched->kss_lock); @@ -390,7 +390,7 @@ ksocknal_handle_zcreq(ksock_conn_t *c, __u64 cookie, int remote) /* ACK connection is not ready, or can't piggyback the ACK */ tx = ksocknal_alloc_tx_noop(cookie, !!remote); - if (tx == NULL) + if (!tx) return -ENOMEM; rc = ksocknal_launch_packet(peer->ksnp_ni, tx, peer->ksnp_id); @@ -461,7 +461,7 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) CLASSERT(sizeof(lnet_magicversion_t) == offsetof(lnet_hdr_t, src_nid)); LIBCFS_ALLOC(hdr, sizeof(*hdr)); - if (hdr == NULL) { + if (!hdr) { CERROR("Can't allocate lnet_hdr_t\n"); return -ENOMEM; } @@ -576,7 +576,7 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, int i; LIBCFS_ALLOC(hdr, sizeof(*hdr)); - if (hdr == NULL) { + if (!hdr) { CERROR("Can't allocate lnet_hdr_t\n"); return -ENOMEM; } @@ -713,7 +713,7 @@ ksocknal_pack_msg_v1(ksock_tx_t *tx) { /* V1.x has no KSOCK_MSG_NOOP */ LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); - LASSERT(tx->tx_lnetmsg != NULL); + LASSERT(tx->tx_lnetmsg); tx->tx_iov[0].iov_base = &tx->tx_lnetmsg->msg_hdr; tx->tx_iov[0].iov_len = sizeof(lnet_hdr_t); @@ -727,7 +727,7 @@ ksocknal_pack_msg_v2(ksock_tx_t *tx) { tx->tx_iov[0].iov_base = &tx->tx_msg; - if (tx->tx_lnetmsg != NULL) { + if (tx->tx_lnetmsg) { LASSERT(tx->tx_msg.ksm_type != KSOCK_MSG_NOOP); tx->tx_msg.ksm_u.lnetmsg.ksnm_hdr = tx->tx_lnetmsg->msg_hdr; diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index 8c95cc5bc889..ef61eafa0ab8 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -299,16 +299,16 @@ lnet_accept(struct socket *sock, __u32 magic) __swab64s(&cr.acr_nid); ni = lnet_net2ni(LNET_NIDNET(cr.acr_nid)); - if (ni == NULL || /* no matching net */ + if (!ni || /* no matching net */ ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */ - if (ni != NULL) + if (ni) lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %pI4h for %s: No matching NI\n", &peer_ip, libcfs_nid2str(cr.acr_nid)); return -EPERM; } - if (ni->ni_lnd->lnd_accept == NULL) { + if (!ni->ni_lnd->lnd_accept) { /* This catches a request for the loopback LND */ lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %pI4h for %s: NI doesn not accept IP connections\n", @@ -335,7 +335,7 @@ lnet_acceptor(void *arg) int peer_port; int secure = (int)((long_ptr_t)arg); - LASSERT(lnet_acceptor_state.pta_sock == NULL); + LASSERT(!lnet_acceptor_state.pta_sock); cfs_block_allsigs(); @@ -443,7 +443,7 @@ lnet_acceptor_start(void) long rc2; long secure; - LASSERT(lnet_acceptor_state.pta_sock == NULL); + LASSERT(!lnet_acceptor_state.pta_sock); rc = lnet_acceptor_get_tunables(); if (rc != 0) @@ -471,11 +471,11 @@ lnet_acceptor_start(void) if (!lnet_acceptor_state.pta_shutdown) { /* started OK */ - LASSERT(lnet_acceptor_state.pta_sock != NULL); + LASSERT(lnet_acceptor_state.pta_sock); return 0; } - LASSERT(lnet_acceptor_state.pta_sock == NULL); + LASSERT(!lnet_acceptor_state.pta_sock); return -ENETDOWN; } @@ -483,7 +483,7 @@ lnet_acceptor_start(void) void lnet_acceptor_stop(void) { - if (lnet_acceptor_state.pta_sock == NULL) /* not running */ + if (!lnet_acceptor_state.pta_sock) /* not running */ return; lnet_acceptor_state.pta_shutdown = 1; diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index f7d53cdfbd99..eb04958be99b 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -107,10 +107,10 @@ lnet_create_remote_nets_table(void) int i; struct list_head *hash; - LASSERT(the_lnet.ln_remote_nets_hash == NULL); + LASSERT(!the_lnet.ln_remote_nets_hash); LASSERT(the_lnet.ln_remote_nets_hbits > 0); LIBCFS_ALLOC(hash, LNET_REMOTE_NETS_HASH_SIZE * sizeof(*hash)); - if (hash == NULL) { + if (!hash) { CERROR("Failed to create remote nets hash table\n"); return -ENOMEM; } @@ -126,7 +126,7 @@ lnet_destroy_remote_nets_table(void) { int i; - if (the_lnet.ln_remote_nets_hash == NULL) + if (!the_lnet.ln_remote_nets_hash) return; for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE; i++) @@ -141,12 +141,12 @@ lnet_destroy_remote_nets_table(void) static void lnet_destroy_locks(void) { - if (the_lnet.ln_res_lock != NULL) { + if (the_lnet.ln_res_lock) { cfs_percpt_lock_free(the_lnet.ln_res_lock); the_lnet.ln_res_lock = NULL; } - if (the_lnet.ln_net_lock != NULL) { + if (the_lnet.ln_net_lock) { cfs_percpt_lock_free(the_lnet.ln_net_lock); the_lnet.ln_net_lock = NULL; } @@ -158,11 +158,11 @@ lnet_create_locks(void) lnet_init_locks(); the_lnet.ln_res_lock = cfs_percpt_lock_alloc(lnet_cpt_table()); - if (the_lnet.ln_res_lock == NULL) + if (!the_lnet.ln_res_lock) goto failed; the_lnet.ln_net_lock = cfs_percpt_lock_alloc(lnet_cpt_table()); - if (the_lnet.ln_net_lock == NULL) + if (!the_lnet.ln_net_lock) goto failed; return 0; @@ -291,7 +291,7 @@ lnet_register_lnd(lnd_t *lnd) LASSERT(the_lnet.ln_init); LASSERT(libcfs_isknown_lnd(lnd->lnd_type)); - LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == NULL); + LASSERT(!lnet_find_lnd_by_type(lnd->lnd_type)); list_add_tail(&lnd->lnd_list, &the_lnet.ln_lnds); lnd->lnd_refcount = 0; @@ -408,7 +408,7 @@ lnet_res_container_cleanup(struct lnet_res_container *rec) count, lnet_res_type2str(rec->rec_type)); } - if (rec->rec_lh_hash != NULL) { + if (rec->rec_lh_hash) { LIBCFS_FREE(rec->rec_lh_hash, LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0])); rec->rec_lh_hash = NULL; @@ -432,7 +432,7 @@ lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type) /* Arbitrary choice of hash table size */ LIBCFS_CPT_ALLOC(rec->rec_lh_hash, lnet_cpt_table(), cpt, LNET_LH_HASH_SIZE * sizeof(rec->rec_lh_hash[0])); - if (rec->rec_lh_hash == NULL) { + if (!rec->rec_lh_hash) { rc = -ENOMEM; goto out; } @@ -470,7 +470,7 @@ lnet_res_containers_create(int type) int i; recs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*rec)); - if (recs == NULL) { + if (!recs) { CERROR("Failed to allocate %s resource containers\n", lnet_res_type2str(type)); return NULL; @@ -557,7 +557,7 @@ lnet_prepare(lnet_pid_t requested_pid) the_lnet.ln_counters = cfs_percpt_alloc(lnet_cpt_table(), sizeof(lnet_counters_t)); - if (the_lnet.ln_counters == NULL) { + if (!the_lnet.ln_counters) { CERROR("Failed to allocate counters for LNet\n"); rc = -ENOMEM; goto failed; @@ -577,7 +577,7 @@ lnet_prepare(lnet_pid_t requested_pid) goto failed; recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME); - if (recs == NULL) { + if (!recs) { rc = -ENOMEM; goto failed; } @@ -585,7 +585,7 @@ lnet_prepare(lnet_pid_t requested_pid) the_lnet.ln_me_containers = recs; recs = lnet_res_containers_create(LNET_COOKIE_TYPE_MD); - if (recs == NULL) { + if (!recs) { rc = -ENOMEM; goto failed; } @@ -624,12 +624,12 @@ lnet_unprepare(void) lnet_portals_destroy(); - if (the_lnet.ln_md_containers != NULL) { + if (the_lnet.ln_md_containers) { lnet_res_containers_destroy(the_lnet.ln_md_containers); the_lnet.ln_md_containers = NULL; } - if (the_lnet.ln_me_containers != NULL) { + if (the_lnet.ln_me_containers) { lnet_res_containers_destroy(the_lnet.ln_me_containers); the_lnet.ln_me_containers = NULL; } @@ -640,7 +640,7 @@ lnet_unprepare(void) lnet_peer_tables_destroy(); lnet_rtrpools_free(); - if (the_lnet.ln_counters != NULL) { + if (the_lnet.ln_counters) { cfs_percpt_free(the_lnet.ln_counters); the_lnet.ln_counters = NULL; } @@ -716,7 +716,7 @@ lnet_cpt_of_nid_locked(lnet_nid_t nid) if (LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) continue; - LASSERT(ni->ni_cpts != NULL); + LASSERT(ni->ni_cpts); return ni->ni_cpts[lnet_nid_cpt_hash (nid, ni->ni_ncpts)]; } @@ -754,12 +754,12 @@ lnet_islocalnet(__u32 net) cpt = lnet_net_lock_current(); ni = lnet_net2ni_locked(net, cpt); - if (ni != NULL) + if (ni) lnet_ni_decref_locked(ni, cpt); lnet_net_unlock(cpt); - return ni != NULL; + return !!ni; } lnet_ni_t * @@ -790,11 +790,11 @@ lnet_islocalnid(lnet_nid_t nid) cpt = lnet_net_lock_current(); ni = lnet_nid2ni_locked(nid, cpt); - if (ni != NULL) + if (ni) lnet_ni_decref_locked(ni, cpt); lnet_net_unlock(cpt); - return ni != NULL; + return !!ni; } int @@ -810,7 +810,7 @@ lnet_count_acceptor_nis(void) list_for_each(tmp, &the_lnet.ln_nis) { ni = list_entry(tmp, lnet_ni_t, ni_list); - if (ni->ni_lnd->lnd_accept != NULL) + if (ni->ni_lnd->lnd_accept) count++; } @@ -868,13 +868,13 @@ lnet_shutdown_lndnis(void) } /* Drop the cached eqwait NI. */ - if (the_lnet.ln_eq_waitni != NULL) { + if (the_lnet.ln_eq_waitni) { lnet_ni_decref_locked(the_lnet.ln_eq_waitni, 0); the_lnet.ln_eq_waitni = NULL; } /* Drop the cached loopback NI. */ - if (the_lnet.ln_loni != NULL) { + if (the_lnet.ln_loni) { lnet_ni_decref_locked(the_lnet.ln_loni, 0); the_lnet.ln_loni = NULL; } @@ -953,7 +953,7 @@ lnet_shutdown_lndnis(void) the_lnet.ln_shutdown = 0; lnet_net_unlock(LNET_LOCK_EX); - if (the_lnet.ln_network_tokens != NULL) { + if (the_lnet.ln_network_tokens) { LIBCFS_FREE(the_lnet.ln_network_tokens, the_lnet.ln_network_tokens_nob); the_lnet.ln_network_tokens = NULL; @@ -975,7 +975,7 @@ lnet_startup_lndnis(void) INIT_LIST_HEAD(&nilist); - if (nets == NULL) + if (!nets) goto failed; rc = lnet_parse_networks(&nilist, nets); @@ -1000,14 +1000,14 @@ lnet_startup_lndnis(void) mutex_lock(&the_lnet.ln_lnd_mutex); lnd = lnet_find_lnd_by_type(lnd_type); - if (lnd == NULL) { + if (!lnd) { mutex_unlock(&the_lnet.ln_lnd_mutex); rc = request_module("%s", libcfs_lnd2modname(lnd_type)); mutex_lock(&the_lnet.ln_lnd_mutex); lnd = lnet_find_lnd_by_type(lnd_type); - if (lnd == NULL) { + if (!lnd) { mutex_unlock(&the_lnet.ln_lnd_mutex); CERROR("Can't load LND %s, module %s, rc=%d\n", libcfs_lnd2str(lnd_type), @@ -1035,7 +1035,7 @@ lnet_startup_lndnis(void) goto failed; } - LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query != NULL); + LASSERT(ni->ni_peertimeout <= 0 || lnd->lnd_query); list_del(&ni->ni_list); @@ -1043,7 +1043,7 @@ lnet_startup_lndnis(void) /* refcount for ln_nis */ lnet_ni_addref_locked(ni, 0); list_add_tail(&ni->ni_list, &the_lnet.ln_nis); - if (ni->ni_cpts != NULL) { + if (ni->ni_cpts) { list_add_tail(&ni->ni_cptlist, &the_lnet.ln_nis_cpt); lnet_ni_addref_locked(ni, 0); @@ -1053,7 +1053,7 @@ lnet_startup_lndnis(void) if (lnd->lnd_type == LOLND) { lnet_ni_addref(ni); - LASSERT(the_lnet.ln_loni == NULL); + LASSERT(!the_lnet.ln_loni); the_lnet.ln_loni = ni; continue; } @@ -1081,7 +1081,7 @@ lnet_startup_lndnis(void) nicount++; } - if (the_lnet.ln_eq_waitni != NULL && nicount > 1) { + if (the_lnet.ln_eq_waitni && nicount > 1) { lnd_type = the_lnet.ln_eq_waitni->ni_lnd->lnd_type; LCONSOLE_ERROR_MSG(0x109, "LND %s can only run single-network\n", libcfs_lnd2str(lnd_type)); @@ -1402,10 +1402,10 @@ LNetCtl(unsigned int cmd, void *arg) default: ni = lnet_net2ni(data->ioc_net); - if (ni == NULL) + if (!ni) return -EINVAL; - if (ni->ni_lnd->lnd_ctl == NULL) + if (!ni->ni_lnd->lnd_ctl) rc = -EINVAL; else rc = ni->ni_lnd->lnd_ctl(ni, cmd, arg); @@ -1499,7 +1499,7 @@ lnet_create_ping_info(void) infosz = offsetof(lnet_ping_info_t, pi_ni[n]); LIBCFS_ALLOC(pinfo, infosz); - if (pinfo == NULL) { + if (!pinfo) { CERROR("Can't allocate ping info[%d]\n", n); return -ENOMEM; } @@ -1521,10 +1521,10 @@ lnet_create_ping_info(void) lnet_net_lock(0); ni = lnet_nid2ni_locked(id.nid, 0); - LASSERT(ni != NULL); + LASSERT(ni); lnet_ni_lock(ni); - LASSERT(ni->ni_status == NULL); + LASSERT(!ni->ni_status); ni->ni_status = ns; lnet_ni_unlock(ni); @@ -1694,7 +1694,7 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, id.pid = LUSTRE_SRV_LNET_PID; LIBCFS_ALLOC(info, infosz); - if (info == NULL) + if (!info) return -ENOMEM; /* NB 2 events max (including any unlink event) */ diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index d02353dca85e..fcd2cfbccefd 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -96,13 +96,13 @@ lnet_net_unique(__u32 net, struct list_head *nilist) void lnet_ni_free(struct lnet_ni *ni) { - if (ni->ni_refs != NULL) + if (ni->ni_refs) cfs_percpt_free(ni->ni_refs); - if (ni->ni_tx_queues != NULL) + if (ni->ni_tx_queues) cfs_percpt_free(ni->ni_tx_queues); - if (ni->ni_cpts != NULL) + if (ni->ni_cpts) cfs_expr_list_values_free(ni->ni_cpts, ni->ni_ncpts); LIBCFS_FREE(ni, sizeof(*ni)); @@ -123,7 +123,7 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) } LIBCFS_ALLOC(ni, sizeof(*ni)); - if (ni == NULL) { + if (!ni) { CERROR("Out of memory creating network %s\n", libcfs_net2str(net)); return NULL; @@ -133,18 +133,18 @@ lnet_ni_alloc(__u32 net, struct cfs_expr_list *el, struct list_head *nilist) INIT_LIST_HEAD(&ni->ni_cptlist); ni->ni_refs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ni->ni_refs[0])); - if (ni->ni_refs == NULL) + if (!ni->ni_refs) goto failed; ni->ni_tx_queues = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ni->ni_tx_queues[0])); - if (ni->ni_tx_queues == NULL) + if (!ni->ni_tx_queues) goto failed; cfs_percpt_for_each(tq, i, ni->ni_tx_queues) INIT_LIST_HEAD(&tq->tq_delayed); - if (el == NULL) { + if (!el) { ni->ni_cpts = NULL; ni->ni_ncpts = LNET_CPT_NUMBER; } else { @@ -194,7 +194,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) } LIBCFS_ALLOC(tokens, tokensize); - if (tokens == NULL) { + if (!tokens) { CERROR("Can't allocate net tokens\n"); return -ENOMEM; } @@ -207,10 +207,10 @@ lnet_parse_networks(struct list_head *nilist, char *networks) /* Add in the loopback network */ ni = lnet_ni_alloc(LNET_MKNET(LOLND, 0), NULL, nilist); - if (ni == NULL) + if (!ni) goto failed; - while (str != NULL && *str != 0) { + while (str && *str != 0) { char *comma = strchr(str, ','); char *bracket = strchr(str, '('); char *square = strchr(str, '['); @@ -222,18 +222,18 @@ lnet_parse_networks(struct list_head *nilist, char *networks) * NB we don't check interface conflicts here; it's the LNDs * responsibility (if it cares at all) */ - if (square != NULL && (comma == NULL || square < comma)) { + if (square && (!comma || square < comma)) { /* * i.e: o2ib0(ib0)[1,2], number between square * brackets are CPTs this NI needs to be bond */ - if (bracket != NULL && bracket > square) { + if (bracket && bracket > square) { tmp = square; goto failed_syntax; } tmp = strchr(square, ']'); - if (tmp == NULL) { + if (!tmp) { tmp = square; goto failed_syntax; } @@ -249,11 +249,10 @@ lnet_parse_networks(struct list_head *nilist, char *networks) *square++ = ' '; } - if (bracket == NULL || - (comma != NULL && comma < bracket)) { + if (!bracket || (comma && comma < bracket)) { /* no interface list specified */ - if (comma != NULL) + if (comma) *comma++ = 0; net = libcfs_str2net(cfs_trimwhite(str)); @@ -265,10 +264,10 @@ lnet_parse_networks(struct list_head *nilist, char *networks) } if (LNET_NETTYP(net) != LOLND && /* LO is implicit */ - lnet_ni_alloc(net, el, nilist) == NULL) + !lnet_ni_alloc(net, el, nilist)) goto failed; - if (el != NULL) { + if (el) { cfs_expr_list_free(el); el = NULL; } @@ -286,10 +285,10 @@ lnet_parse_networks(struct list_head *nilist, char *networks) nnets++; ni = lnet_ni_alloc(net, el, nilist); - if (ni == NULL) + if (!ni) goto failed; - if (el != NULL) { + if (el) { cfs_expr_list_free(el); el = NULL; } @@ -298,7 +297,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) iface = bracket + 1; bracket = strchr(iface, ')'); - if (bracket == NULL) { + if (!bracket) { tmp = iface; goto failed_syntax; } @@ -306,7 +305,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) *bracket = 0; do { comma = strchr(iface, ','); - if (comma != NULL) + if (comma) *comma++ = 0; iface = cfs_trimwhite(iface); @@ -324,11 +323,11 @@ lnet_parse_networks(struct list_head *nilist, char *networks) ni->ni_interfaces[niface++] = iface; iface = comma; - } while (iface != NULL); + } while (iface); str = bracket + 1; comma = strchr(bracket + 1, ','); - if (comma != NULL) { + if (comma) { *comma = 0; str = cfs_trimwhite(str); if (*str != 0) { @@ -359,7 +358,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) lnet_ni_free(ni); } - if (el != NULL) + if (el) cfs_expr_list_free(el); LIBCFS_FREE(tokens, tokensize); @@ -388,7 +387,7 @@ lnet_new_text_buf(int str_len) } LIBCFS_ALLOC(ltb, nob); - if (ltb == NULL) + if (!ltb) return NULL; ltb->ltb_size = nob; @@ -442,7 +441,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) nob = (int)(sep - str); if (nob > 0) { ltb = lnet_new_text_buf(nob); - if (ltb == NULL) { + if (!ltb) { lnet_free_text_bufs(&pending); return -1; } @@ -488,7 +487,7 @@ lnet_expand1tb(struct list_head *list, LASSERT(*sep2 == ']'); ltb = lnet_new_text_buf(len1 + itemlen + len2); - if (ltb == NULL) + if (!ltb) return -ENOMEM; memcpy(ltb->ltb_text, str, len1); @@ -519,11 +518,11 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) INIT_LIST_HEAD(&pending); sep = strchr(str, '['); - if (sep == NULL) /* nothing to expand */ + if (!sep) /* nothing to expand */ return 0; sep2 = strchr(sep, ']'); - if (sep2 == NULL) + if (!sep2) goto failed; for (parsed = sep; parsed < sep2; parsed = enditem) { @@ -599,7 +598,7 @@ lnet_parse_priority(char *str, unsigned int *priority, char **token) int len; sep = strchr(str, LNET_PRIORITY_SEPARATOR); - if (sep == NULL) { + if (!sep) { *priority = 0; return 0; } @@ -683,7 +682,7 @@ lnet_parse_route(char *str, int *im_a_router) } ltb = lnet_new_text_buf(strlen(token)); - if (ltb == NULL) + if (!ltb) goto out; strcpy(ltb->ltb_text, token); @@ -889,12 +888,12 @@ lnet_netspec2net(char *netspec) char *bracket = strchr(netspec, '('); __u32 net; - if (bracket != NULL) + if (bracket) *bracket = 0; net = libcfs_str2net(netspec); - if (bracket != NULL) + if (bracket) *bracket = '('; return net; @@ -922,9 +921,7 @@ lnet_splitnets(char *source, struct list_head *nets) sep = strchr(tb->ltb_text, ','); bracket = strchr(tb->ltb_text, '('); - if (sep != NULL && - bracket != NULL && - bracket < sep) { + if (sep && bracket && bracket < sep) { /* netspec lists interfaces... */ offset2 = offset + (int)(bracket - tb->ltb_text); @@ -932,7 +929,7 @@ lnet_splitnets(char *source, struct list_head *nets) bracket = strchr(bracket + 1, ')'); - if (bracket == NULL || + if (!bracket || !(bracket[1] == ',' || bracket[1] == 0)) { lnet_syntax("ip2nets", source, offset2, len); return -EINVAL; @@ -941,7 +938,7 @@ lnet_splitnets(char *source, struct list_head *nets) sep = (bracket[1] == 0) ? NULL : bracket + 1; } - if (sep != NULL) + if (sep) *sep++ = 0; net = lnet_netspec2net(tb->ltb_text); @@ -965,13 +962,13 @@ lnet_splitnets(char *source, struct list_head *nets) } } - if (sep == NULL) + if (!sep) return 0; offset += (int)(sep - tb->ltb_text); len = strlen(sep); tb2 = lnet_new_text_buf(len); - if (tb2 == NULL) + if (!tb2) return -ENOMEM; strncpy(tb2->ltb_text, sep, len); @@ -1118,7 +1115,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) return nif; LIBCFS_ALLOC(ipaddrs, nif * sizeof(*ipaddrs)); - if (ipaddrs == NULL) { + if (!ipaddrs) { CERROR("Can't allocate ipaddrs[%d]\n", nif); lnet_ipif_free_enumeration(ifnames, nif); return -ENOMEM; @@ -1151,7 +1148,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) } else { if (nip > 0) { LIBCFS_ALLOC(ipaddrs2, nip * sizeof(*ipaddrs2)); - if (ipaddrs2 == NULL) { + if (!ipaddrs2) { CERROR("Can't allocate ipaddrs[%d]\n", nip); nip = -ENOMEM; } else { diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index 683eb45aecf5..34012e984245 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -94,12 +94,12 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, return -EINVAL; eq = lnet_eq_alloc(); - if (eq == NULL) + if (!eq) return -ENOMEM; if (count != 0) { LIBCFS_ALLOC(eq->eq_events, count * sizeof(lnet_event_t)); - if (eq->eq_events == NULL) + if (!eq->eq_events) goto failed; /* * NB allocator has set all event sequence numbers to 0, @@ -114,7 +114,7 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, eq->eq_refs = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*eq->eq_refs[0])); - if (eq->eq_refs == NULL) + if (!eq->eq_refs) goto failed; /* MUST hold both exclusive lnet_res_lock */ @@ -135,10 +135,10 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, return 0; failed: - if (eq->eq_events != NULL) + if (eq->eq_events) LIBCFS_FREE(eq->eq_events, count * sizeof(lnet_event_t)); - if (eq->eq_refs != NULL) + if (eq->eq_refs) cfs_percpt_free(eq->eq_refs); lnet_eq_free(eq); @@ -178,7 +178,7 @@ LNetEQFree(lnet_handle_eq_t eqh) lnet_eq_wait_lock(); eq = lnet_handle2eq(&eqh); - if (eq == NULL) { + if (!eq) { rc = -ENOENT; goto out; } @@ -206,9 +206,9 @@ LNetEQFree(lnet_handle_eq_t eqh) lnet_eq_wait_unlock(); lnet_res_unlock(LNET_LOCK_EX); - if (events != NULL) + if (events) LIBCFS_FREE(events, size * sizeof(lnet_event_t)); - if (refs != NULL) + if (refs) cfs_percpt_free(refs); return rc; @@ -395,7 +395,7 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms, for (i = 0; i < neq; i++) { lnet_eq_t *eq = lnet_handle2eq(&eventqs[i]); - if (eq == NULL) { + if (!eq) { lnet_eq_wait_unlock(); return -ENOENT; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 55bd7a1f7a5d..490edfb7cacb 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -57,7 +57,7 @@ lnet_md_unlink(lnet_libmd_t *md) * and unlink it if it was created * with LNET_UNLINK */ - if (me != NULL) { + if (me) { /* detach MD from portal */ lnet_ptl_detach_md(me, md); if (me->me_unlink == LNET_UNLINK) @@ -75,7 +75,7 @@ lnet_md_unlink(lnet_libmd_t *md) CDEBUG(D_NET, "Unlinking md %p\n", md); - if (md->md_eq != NULL) { + if (md->md_eq) { int cpt = lnet_cpt_of_cookie(md->md_lh.lh_cookie); LASSERT(*md->md_eq->eq_refs[cpt] > 0); @@ -187,7 +187,7 @@ lnet_md_link(lnet_libmd_t *md, lnet_handle_eq_t eq_handle, int cpt) * TODO - reevaluate what should be here in light of * the removal of the start and end events * maybe there we shouldn't even allow LNET_EQ_NONE!) - * LASSERT (eq == NULL); + * LASSERT(!eq); */ if (!LNetHandleIsInvalid(eq_handle)) { md->md_eq = lnet_handle2eq(&eq_handle); @@ -306,7 +306,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, me = lnet_handle2me(&meh); if (!me) rc = -ENOENT; - else if (me->me_md != NULL) + else if (me->me_md) rc = -EBUSY; else rc = lnet_md_link(md, umd.eq_handle, cpt); @@ -453,7 +453,7 @@ LNetMDUnlink(lnet_handle_md_t mdh) * when the LND is done, the completion event flags that the MD was * unlinked. Otherwise, we enqueue an event now... */ - if (md->md_eq != NULL && md->md_refcount == 0) { + if (md->md_eq && md->md_refcount == 0) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); } diff --git a/drivers/staging/lustre/lnet/lnet/lib-me.c b/drivers/staging/lustre/lnet/lnet/lib-me.c index 42fc99ef9f80..ab17bdb64071 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-me.c +++ b/drivers/staging/lustre/lnet/lnet/lib-me.c @@ -91,11 +91,11 @@ LNetMEAttach(unsigned int portal, mtable = lnet_mt_of_attach(portal, match_id, match_bits, ignore_bits, pos); - if (mtable == NULL) /* can't match portal type */ + if (!mtable) /* can't match portal type */ return -EPERM; me = lnet_me_alloc(); - if (me == NULL) + if (!me) return -ENOMEM; lnet_res_lock(mtable->mt_cpt); @@ -163,7 +163,7 @@ LNetMEInsert(lnet_handle_me_t current_meh, return -EPERM; new_me = lnet_me_alloc(); - if (new_me == NULL) + if (!new_me) return -ENOMEM; cpt = lnet_cpt_of_cookie(current_meh.cookie); @@ -171,7 +171,7 @@ LNetMEInsert(lnet_handle_me_t current_meh, lnet_res_lock(cpt); current_me = lnet_handle2me(¤t_meh); - if (current_me == NULL) { + if (!current_me) { lnet_me_free(new_me); lnet_res_unlock(cpt); @@ -240,15 +240,15 @@ LNetMEUnlink(lnet_handle_me_t meh) lnet_res_lock(cpt); me = lnet_handle2me(&meh); - if (me == NULL) { + if (!me) { lnet_res_unlock(cpt); return -ENOENT; } md = me->me_md; - if (md != NULL) { + if (md) { md->md_flags |= LNET_MD_FLAG_ABORTED; - if (md->md_eq != NULL && md->md_refcount == 0) { + if (md->md_eq && md->md_refcount == 0) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); } @@ -267,7 +267,7 @@ lnet_me_unlink(lnet_me_t *me) { list_del(&me->me_list); - if (me->me_md != NULL) { + if (me->me_md) { lnet_libmd_t *md = me->me_md; /* detach MD from portal of this ME */ diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index b40220a5434c..5e8a6ab6da62 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -60,7 +60,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) if (threshold != 0) { /* Adding a new entry */ LIBCFS_ALLOC(tp, sizeof(*tp)); - if (tp == NULL) + if (!tp) return -ENOMEM; tp->tp_nid = nid; @@ -329,10 +329,10 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, siov->kiov_len - soffset); this_nob = min(this_nob, nob); - if (daddr == NULL) + if (!daddr) daddr = ((char *)kmap(diov->kiov_page)) + diov->kiov_offset + doffset; - if (saddr == NULL) + if (!saddr) saddr = ((char *)kmap(siov->kiov_page)) + siov->kiov_offset + soffset; @@ -367,9 +367,9 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, } } while (nob > 0); - if (daddr != NULL) + if (daddr) kunmap(diov->kiov_page); - if (saddr != NULL) + if (saddr) kunmap(siov->kiov_page); } EXPORT_SYMBOL(lnet_copy_kiov2kiov); @@ -411,7 +411,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, (__kernel_size_t) kiov->kiov_len - kiovoffset); this_nob = min(this_nob, nob); - if (addr == NULL) + if (!addr) addr = ((char *)kmap(kiov->kiov_page)) + kiov->kiov_offset + kiovoffset; @@ -439,7 +439,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, } while (nob > 0); - if (addr != NULL) + if (addr) kunmap(kiov->kiov_page); } EXPORT_SYMBOL(lnet_copy_kiov2iov); @@ -482,7 +482,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, iov->iov_len - iovoffset); this_nob = min(this_nob, nob); - if (addr == NULL) + if (!addr) addr = ((char *)kmap(kiov->kiov_page)) + kiov->kiov_offset + kiovoffset; @@ -509,7 +509,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, } } while (nob > 0); - if (addr != NULL) + if (addr) kunmap(kiov->kiov_page); } EXPORT_SYMBOL(lnet_copy_iov2kiov); @@ -577,9 +577,9 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, int rc; LASSERT(!in_interrupt()); - LASSERT(mlen == 0 || msg != NULL); + LASSERT(mlen == 0 || msg); - if (msg != NULL) { + if (msg) { LASSERT(msg->msg_receiving); LASSERT(!msg->msg_sending); LASSERT(rlen == msg->msg_len); @@ -595,7 +595,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, kiov = msg->msg_kiov; LASSERT(niov > 0); - LASSERT((iov == NULL) != (kiov == NULL)); + LASSERT(!iov != !kiov); } } @@ -612,10 +612,10 @@ lnet_setpayloadbuffer(lnet_msg_t *msg) LASSERT(msg->msg_len > 0); LASSERT(!msg->msg_routing); - LASSERT(md != NULL); + LASSERT(md); LASSERT(msg->msg_niov == 0); - LASSERT(msg->msg_iov == NULL); - LASSERT(msg->msg_kiov == NULL); + LASSERT(!msg->msg_iov); + LASSERT(!msg->msg_kiov); msg->msg_niov = md->md_niov; if ((md->md_options & LNET_MD_KIOV) != 0) @@ -668,7 +668,7 @@ lnet_ni_eager_recv(lnet_ni_t *ni, lnet_msg_t *msg) LASSERT(!msg->msg_sending); LASSERT(msg->msg_receiving); LASSERT(!msg->msg_rx_ready_delay); - LASSERT(ni->ni_lnd->lnd_eager_recv != NULL); + LASSERT(ni->ni_lnd->lnd_eager_recv); msg->msg_rx_ready_delay = 1; rc = ni->ni_lnd->lnd_eager_recv(ni, msg->msg_private, msg, @@ -690,7 +690,7 @@ lnet_ni_query_locked(lnet_ni_t *ni, lnet_peer_t *lp) unsigned long last_alive = 0; LASSERT(lnet_peer_aliveness_enabled(lp)); - LASSERT(ni->ni_lnd->lnd_query != NULL); + LASSERT(ni->ni_lnd->lnd_query); lnet_net_unlock(lp->lp_cpt); ni->ni_lnd->lnd_query(ni, lp->lp_nid, &last_alive); @@ -820,7 +820,7 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) return EHOSTUNREACH; } - if (msg->msg_md != NULL && + if (msg->msg_md && (msg->msg_md->md_flags & LNET_MD_FLAG_ABORTED) != 0) { lnet_net_unlock(cpt); @@ -908,8 +908,8 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) lnet_rtrbufpool_t *rbp; lnet_rtrbuf_t *rb; - LASSERT(msg->msg_iov == NULL); - LASSERT(msg->msg_kiov == NULL); + LASSERT(!msg->msg_iov); + LASSERT(!msg->msg_kiov); LASSERT(msg->msg_niov == 0); LASSERT(msg->msg_routing); LASSERT(msg->msg_receiving); @@ -1026,7 +1026,7 @@ lnet_return_tx_credits_locked(lnet_msg_t *msg) } } - if (txpeer != NULL) { + if (txpeer) { msg->msg_txpeer = NULL; lnet_peer_decref_locked(txpeer); } @@ -1048,7 +1048,7 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) * there until it gets one allocated, or aborts the wait * itself */ - LASSERT(msg->msg_kiov != NULL); + LASSERT(msg->msg_kiov); rb = list_entry(msg->msg_kiov, lnet_rtrbuf_t, rb_kiov[0]); rbp = rb->rb_pool; @@ -1089,7 +1089,7 @@ lnet_return_rx_credits_locked(lnet_msg_t *msg) (void) lnet_post_routed_recv_locked(msg2, 1); } } - if (rxpeer != NULL) { + if (rxpeer) { msg->msg_rxpeer = NULL; lnet_peer_decref_locked(rxpeer); } @@ -1147,7 +1147,7 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) * rtr_nid nid, otherwise find the best gateway I can use */ rnet = lnet_find_net_locked(LNET_NIDNET(target)); - if (rnet == NULL) + if (!rnet) return NULL; lp_best = NULL; @@ -1161,13 +1161,13 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) rtr->lr_downis != 0)) /* NI to target is down */ continue; - if (ni != NULL && lp->lp_ni != ni) + if (ni && lp->lp_ni != ni) continue; if (lp->lp_nid == rtr_nid) /* it's pre-determined router */ return lp; - if (lp_best == NULL) { + if (!lp_best) { rtr_best = rtr; rtr_last = rtr; lp_best = lp; @@ -1191,7 +1191,7 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) * so we can round-robin all routers, it's race and inaccurate but * harmless and functional */ - if (rtr_best != NULL) + if (rtr_best) rtr_best->lr_seq = rtr_last->lr_seq + 1; return lp_best; } @@ -1212,8 +1212,8 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) * but we might want to use pre-determined router for ACK/REPLY * in the future */ - /* NB: ni != NULL == interface pre-determined (ACK/REPLY) */ - LASSERT(msg->msg_txpeer == NULL); + /* NB: ni == interface pre-determined (ACK/REPLY) */ + LASSERT(!msg->msg_txpeer); LASSERT(!msg->msg_sending); LASSERT(!msg->msg_target_is_router); LASSERT(!msg->msg_receiving); @@ -1234,7 +1234,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) src_ni = NULL; } else { src_ni = lnet_nid2ni_locked(src_nid, cpt); - if (src_ni == NULL) { + if (!src_ni) { lnet_net_unlock(cpt); LCONSOLE_WARN("Can't send to %s: src %s is not a local nid\n", libcfs_nid2str(dst_nid), @@ -1247,8 +1247,8 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) /* Is this for someone on a local network? */ local_ni = lnet_net2ni_locked(LNET_NIDNET(dst_nid), cpt); - if (local_ni != NULL) { - if (src_ni == NULL) { + if (local_ni) { + if (!src_ni) { src_ni = local_ni; src_nid = src_ni->ni_nid; } else if (src_ni == local_ni) { @@ -1294,8 +1294,8 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) } else { /* sending to a remote network */ lp = lnet_find_route_locked(src_ni, dst_nid, rtr_nid); - if (lp == NULL) { - if (src_ni != NULL) + if (!lp) { + if (src_ni) lnet_ni_decref_locked(src_ni, cpt); lnet_net_unlock(cpt); @@ -1314,7 +1314,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) if (rtr_nid != lp->lp_nid) { cpt2 = lnet_cpt_of_nid_locked(lp->lp_nid); if (cpt2 != cpt) { - if (src_ni != NULL) + if (src_ni) lnet_ni_decref_locked(src_ni, cpt); lnet_net_unlock(cpt); @@ -1328,7 +1328,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) libcfs_nid2str(dst_nid), libcfs_nid2str(lp->lp_nid), lnet_msgtyp2str(msg->msg_type), msg->msg_len); - if (src_ni == NULL) { + if (!src_ni) { src_ni = lp->lp_ni; src_nid = src_ni->ni_nid; } else { @@ -1355,7 +1355,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) LASSERT(!msg->msg_peertxcredit); LASSERT(!msg->msg_txcredit); - LASSERT(msg->msg_txpeer == NULL); + LASSERT(!msg->msg_txpeer); msg->msg_txpeer = lp; /* msg takes my ref on lp */ @@ -1423,7 +1423,7 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t *msg) info.mi_roffset = hdr->msg.put.offset; info.mi_mbits = hdr->msg.put.match_bits; - msg->msg_rx_ready_delay = ni->ni_lnd->lnd_eager_recv == NULL; + msg->msg_rx_ready_delay = !ni->ni_lnd->lnd_eager_recv; again: rc = lnet_ptl_match_md(&info, msg); @@ -1536,13 +1536,13 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) /* NB handles only looked up by creator (no flips) */ md = lnet_wire_handle2md(&hdr->msg.reply.dst_wmd); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || md->md_threshold == 0 || md->md_me) { CNETERR("%s: Dropping REPLY from %s for %s MD %#llx.%#llx\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), - (md == NULL) ? "invalid" : "inactive", + !md ? "invalid" : "inactive", hdr->msg.reply.dst_wmd.wh_interface_cookie, hdr->msg.reply.dst_wmd.wh_object_cookie); - if (md != NULL && md->md_me != NULL) + if (md && md->md_me) CERROR("REPLY MD also attached to portal %d\n", md->md_me->me_portal); @@ -1602,15 +1602,15 @@ lnet_parse_ack(lnet_ni_t *ni, lnet_msg_t *msg) /* NB handles only looked up by creator (no flips) */ md = lnet_wire_handle2md(&hdr->msg.ack.dst_wmd); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || md->md_threshold == 0 || md->md_me) { /* Don't moan; this is expected */ CDEBUG(D_NET, "%s: Dropping ACK from %s to %s MD %#llx.%#llx\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), - (md == NULL) ? "invalid" : "inactive", + !md ? "invalid" : "inactive", hdr->msg.ack.dst_wmd.wh_interface_cookie, hdr->msg.ack.dst_wmd.wh_object_cookie); - if (md != NULL && md->md_me != NULL) + if (md && md->md_me) CERROR("Source MD also attached to portal %d\n", md->md_me->me_portal); @@ -1639,7 +1639,7 @@ lnet_parse_forward_locked(lnet_ni_t *ni, lnet_msg_t *msg) if (msg->msg_rxpeer->lp_rtrcredits <= 0 || lnet_msg2bufpool(msg)->rbp_credits <= 0) { - if (ni->ni_lnd->lnd_eager_recv == NULL) { + if (!ni->ni_lnd->lnd_eager_recv) { msg->msg_rx_ready_delay = 1; } else { lnet_net_unlock(msg->msg_rx_cpt); @@ -1794,7 +1794,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, /* NB: so far here is the only place to set NI status to "up */ ni->ni_last_alive = ktime_get_real_seconds(); - if (ni->ni_status != NULL && + if (ni->ni_status && ni->ni_status->ns_status == LNET_NI_STATUS_DOWN) ni->ni_status->ns_status = LNET_NI_STATUS_UP; lnet_ni_unlock(ni); @@ -1857,7 +1857,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, } msg = lnet_msg_alloc(); - if (msg == NULL) { + if (!msg) { CERROR("%s, src %s: Dropping %s (out of memory)\n", libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), lnet_msgtyp2str(type)); @@ -1957,7 +1957,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, LASSERT(rc == ENOENT); free_drop: - LASSERT(msg->msg_md == NULL); + LASSERT(!msg->msg_md); lnet_finalize(ni, msg, rc); drop: @@ -1979,9 +1979,9 @@ lnet_drop_delayed_msg_list(struct list_head *head, char *reason) id.nid = msg->msg_hdr.src_nid; id.pid = msg->msg_hdr.src_pid; - LASSERT(msg->msg_md == NULL); + LASSERT(!msg->msg_md); LASSERT(msg->msg_rx_delayed); - LASSERT(msg->msg_rxpeer != NULL); + LASSERT(msg->msg_rxpeer); LASSERT(msg->msg_hdr.type == LNET_MSG_PUT); CWARN("Dropping delayed PUT from %s portal %d match %llu offset %d length %d: %s\n", @@ -2026,8 +2026,8 @@ lnet_recv_delayed_msg_list(struct list_head *head) id.pid = msg->msg_hdr.src_pid; LASSERT(msg->msg_rx_delayed); - LASSERT(msg->msg_md != NULL); - LASSERT(msg->msg_rxpeer != NULL); + LASSERT(msg->msg_md); + LASSERT(msg->msg_rxpeer); LASSERT(msg->msg_hdr.type == LNET_MSG_PUT); CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d match %llu offset %d length %d.\n", @@ -2106,7 +2106,7 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, } msg = lnet_msg_alloc(); - if (msg == NULL) { + if (!msg) { CERROR("Dropping PUT to %s: ENOMEM on lnet_msg_t\n", libcfs_id2str(target)); return -ENOMEM; @@ -2117,11 +2117,11 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || md->md_threshold == 0 || md->md_me) { CERROR("Dropping PUT (%llu:%d:%s): MD (%d) invalid\n", match_bits, portal, libcfs_id2str(target), - md == NULL ? -1 : md->md_threshold); - if (md != NULL && md->md_me != NULL) + !md ? -1 : md->md_threshold); + if (md && md->md_me) CERROR("Source MD also attached to portal %d\n", md->md_me->me_portal); lnet_res_unlock(cpt); @@ -2194,7 +2194,7 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) LASSERT(getmd->md_refcount > 0); - if (msg == NULL) { + if (!msg) { CERROR("%s: Dropping REPLY from %s: can't allocate msg\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id)); goto drop; @@ -2241,7 +2241,7 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) the_lnet.ln_counters[cpt]->drop_length += getmd->md_length; lnet_net_unlock(cpt); - if (msg != NULL) + if (msg) lnet_msg_free(msg); return NULL; @@ -2255,7 +2255,7 @@ lnet_set_reply_msg_len(lnet_ni_t *ni, lnet_msg_t *reply, unsigned int len) * Set the REPLY length, now the RDMA that elides the REPLY message has * completed and I know it. */ - LASSERT(reply != NULL); + LASSERT(reply); LASSERT(reply->msg_type == LNET_MSG_GET); LASSERT(reply->msg_ev.type == LNET_EVENT_REPLY); @@ -2311,7 +2311,7 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, } msg = lnet_msg_alloc(); - if (msg == NULL) { + if (!msg) { CERROR("Dropping GET to %s: ENOMEM on lnet_msg_t\n", libcfs_id2str(target)); return -ENOMEM; @@ -2321,11 +2321,11 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (md == NULL || md->md_threshold == 0 || md->md_me != NULL) { + if (!md || md->md_threshold == 0 || md->md_me) { CERROR("Dropping GET (%llu:%d:%s): MD (%d) invalid\n", match_bits, portal, libcfs_id2str(target), - md == NULL ? -1 : md->md_threshold); - if (md != NULL && md->md_me != NULL) + !md ? -1 : md->md_threshold); + if (md && md->md_me) CERROR("REPLY MD also attached to portal %d\n", md->md_me->me_portal); @@ -2409,9 +2409,9 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) ni = list_entry(e, lnet_ni_t, ni_list); if (ni->ni_nid == dstnid) { - if (srcnidp != NULL) + if (srcnidp) *srcnidp = dstnid; - if (orderp != NULL) { + if (orderp) { if (LNET_NETTYP(LNET_NIDNET(dstnid)) == LOLND) *orderp = 0; else @@ -2423,9 +2423,9 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) } if (LNET_NIDNET(ni->ni_nid) == dstnet) { - if (srcnidp != NULL) + if (srcnidp) *srcnidp = ni->ni_nid; - if (orderp != NULL) + if (orderp) *orderp = order; lnet_net_unlock(cpt); return 1; @@ -2446,16 +2446,16 @@ LNetDist(lnet_nid_t dstnid, lnet_nid_t *srcnidp, __u32 *orderp) list_for_each_entry(route, &rnet->lrn_routes, lr_list) { - if (shortest == NULL || + if (!shortest || route->lr_hops < shortest->lr_hops) shortest = route; } - LASSERT(shortest != NULL); + LASSERT(shortest); hops = shortest->lr_hops; - if (srcnidp != NULL) + if (srcnidp) *srcnidp = shortest->lr_gateway->lp_ni->ni_nid; - if (orderp != NULL) + if (orderp) *orderp = order; lnet_net_unlock(cpt); return hops + 1; diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index eb4aa3430105..5ee390cf51ad 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -350,7 +350,7 @@ lnet_msg_detach_md(lnet_msg_t *msg, int status) LASSERT(md->md_refcount >= 0); unlink = lnet_md_unlinkable(md); - if (md->md_eq != NULL) { + if (md->md_eq) { msg->msg_ev.status = status; msg->msg_ev.unlinked = unlink; lnet_eq_enqueue_event(md->md_eq, &msg->msg_ev); @@ -451,7 +451,7 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) LASSERT(!in_interrupt()); - if (msg == NULL) + if (!msg) return; #if 0 CDEBUG(D_WARNING, "%s msg->%s Flags:%s%s%s%s%s%s%s%s%s%s%s txp %s rxp %s\n", @@ -467,12 +467,12 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) msg->msg_rtrcredit ? "F" : "", msg->msg_peerrtrcredit ? "f" : "", msg->msg_onactivelist ? "!" : "", - msg->msg_txpeer == NULL ? "" : libcfs_nid2str(msg->msg_txpeer->lp_nid), - msg->msg_rxpeer == NULL ? "" : libcfs_nid2str(msg->msg_rxpeer->lp_nid)); + !msg->msg_txpeer ? "" : libcfs_nid2str(msg->msg_txpeer->lp_nid), + !msg->msg_rxpeer ? "" : libcfs_nid2str(msg->msg_rxpeer->lp_nid)); #endif msg->msg_ev.status = status; - if (msg->msg_md != NULL) { + if (msg->msg_md) { cpt = lnet_cpt_of_cookie(msg->msg_md->md_lh.lh_cookie); lnet_res_lock(cpt); @@ -509,7 +509,7 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) if (container->msc_finalizers[i] == current) break; - if (my_slot < 0 && container->msc_finalizers[i] == NULL) + if (my_slot < 0 && !container->msc_finalizers[i]) my_slot = i; } @@ -565,7 +565,7 @@ lnet_msg_container_cleanup(struct lnet_msg_container *container) if (count > 0) CERROR("%d active msg on exit\n", count); - if (container->msc_finalizers != NULL) { + if (container->msc_finalizers) { LIBCFS_FREE(container->msc_finalizers, container->msc_nfinalizers * sizeof(*container->msc_finalizers)); @@ -607,7 +607,7 @@ lnet_msg_container_setup(struct lnet_msg_container *container, int cpt) container->msc_nfinalizers * sizeof(*container->msc_finalizers)); - if (container->msc_finalizers == NULL) { + if (!container->msc_finalizers) { CERROR("Failed to allocate message finalizers\n"); lnet_msg_container_cleanup(container); return -ENOMEM; @@ -622,7 +622,7 @@ lnet_msg_containers_destroy(void) struct lnet_msg_container *container; int i; - if (the_lnet.ln_msg_containers == NULL) + if (!the_lnet.ln_msg_containers) return; cfs_percpt_for_each(container, i, the_lnet.ln_msg_containers) @@ -642,7 +642,7 @@ lnet_msg_containers_create(void) the_lnet.ln_msg_containers = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*container)); - if (the_lnet.ln_msg_containers == NULL) { + if (!the_lnet.ln_msg_containers) { CERROR("Failed to allocate cpu-partition data for network\n"); return -ENOMEM; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index d99364f43cca..aca47de2ce5a 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -243,7 +243,7 @@ lnet_mt_of_attach(unsigned int index, lnet_process_id_t id, ptl = the_lnet.ln_portals[index]; mtable = lnet_match2mt(ptl, id, mbits); - if (mtable != NULL) /* unique portal or only one match-table */ + if (mtable) /* unique portal or only one match-table */ return mtable; /* it's a wildcard portal */ @@ -280,7 +280,7 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) LASSERT(lnet_ptl_is_wildcard(ptl) || lnet_ptl_is_unique(ptl)); mtable = lnet_match2mt(ptl, info->mi_id, info->mi_mbits); - if (mtable != NULL) + if (mtable) return mtable; /* it's a wildcard portal */ @@ -399,7 +399,7 @@ lnet_mt_match_md(struct lnet_match_table *mtable, list_for_each_entry_safe(me, tmp, head, me_list) { /* ME attached but MD not attached yet */ - if (me->me_md == NULL) + if (!me->me_md) continue; LASSERT(me == me->me_md->md_me); @@ -516,7 +516,7 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, * could be matched by lnet_ptl_attach_md() * which is called by another thread */ - rc = msg->msg_md == NULL ? + rc = !msg->msg_md ? LNET_MATCHMD_DROP : LNET_MATCHMD_OK; } @@ -733,7 +733,7 @@ lnet_ptl_cleanup(struct lnet_portal *ptl) struct lnet_match_table *mtable; int i; - if (ptl->ptl_mtables == NULL) /* uninitialized portal */ + if (!ptl->ptl_mtables) /* uninitialized portal */ return; LASSERT(list_empty(&ptl->ptl_msg_delayed)); @@ -743,7 +743,7 @@ lnet_ptl_cleanup(struct lnet_portal *ptl) lnet_me_t *me; int j; - if (mtable->mt_mhash == NULL) /* uninitialized match-table */ + if (!mtable->mt_mhash) /* uninitialized match-table */ continue; mhash = mtable->mt_mhash; @@ -775,7 +775,7 @@ lnet_ptl_setup(struct lnet_portal *ptl, int index) ptl->ptl_mtables = cfs_percpt_alloc(lnet_cpt_table(), sizeof(struct lnet_match_table)); - if (ptl->ptl_mtables == NULL) { + if (!ptl->ptl_mtables) { CERROR("Failed to create match table for portal %d\n", index); return -ENOMEM; } @@ -788,7 +788,7 @@ lnet_ptl_setup(struct lnet_portal *ptl, int index) /* the extra entry is for MEs with ignore bits */ LIBCFS_CPT_ALLOC(mhash, lnet_cpt_table(), i, sizeof(*mhash) * (LNET_MT_HASH_SIZE + 1)); - if (mhash == NULL) { + if (!mhash) { CERROR("Failed to create match hash for portal %d\n", index); goto failed; @@ -816,7 +816,7 @@ lnet_portals_destroy(void) { int i; - if (the_lnet.ln_portals == NULL) + if (!the_lnet.ln_portals) return; for (i = 0; i < the_lnet.ln_nportals; i++) @@ -836,7 +836,7 @@ lnet_portals_create(void) the_lnet.ln_nportals = MAX_PORTALS; the_lnet.ln_portals = cfs_array_alloc(the_lnet.ln_nportals, size); - if (the_lnet.ln_portals == NULL) { + if (!the_lnet.ln_portals) { CERROR("Failed to allocate portals table\n"); return -ENOMEM; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index f775879b3396..0cf0645c78e3 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -165,7 +165,7 @@ lnet_ipif_enumerate(char ***namesp) } LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr)); - if (ifr == NULL) { + if (!ifr) { CERROR("ENOMEM enumerating up to %d interfaces\n", nalloc); rc = -ENOMEM; @@ -197,7 +197,7 @@ lnet_ipif_enumerate(char ***namesp) goto out1; LIBCFS_ALLOC(names, nfound * sizeof(*names)); - if (names == NULL) { + if (!names) { rc = -ENOMEM; goto out1; } @@ -213,7 +213,7 @@ lnet_ipif_enumerate(char ***namesp) } LIBCFS_ALLOC(names[i], IFNAMSIZ); - if (names[i] == NULL) { + if (!names[i]) { rc = -ENOMEM; goto out2; } @@ -242,7 +242,7 @@ lnet_ipif_free_enumeration(char **names, int n) LASSERT(n > 0); - for (i = 0; i < n && names[i] != NULL; i++) + for (i = 0; i < n && names[i]; i++) LIBCFS_FREE(names[i], IFNAMSIZ); LIBCFS_FREE(names, n * sizeof(*names)); @@ -468,10 +468,10 @@ lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port) return rc; } - if (ip != NULL) + if (ip) *ip = ntohl(sin.sin_addr.s_addr); - if (port != NULL) + if (port) *port = ntohs(sin.sin_port); return 0; @@ -481,10 +481,10 @@ EXPORT_SYMBOL(lnet_sock_getaddr); int lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize) { - if (txbufsize != NULL) + if (txbufsize) *txbufsize = sock->sk->sk_sndbuf; - if (rxbufsize != NULL) + if (rxbufsize) *rxbufsize = sock->sk->sk_rcvbuf; return 0; diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 314e16422a29..468eda611bf8 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -52,9 +52,9 @@ lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, { lnet_msg_t *sendmsg = private; - if (lntmsg != NULL) { /* not discarding */ - if (sendmsg->msg_iov != NULL) { - if (iov != NULL) + if (lntmsg) { /* not discarding */ + if (sendmsg->msg_iov) { + if (iov) lnet_copy_iov2iov(niov, iov, offset, sendmsg->msg_niov, sendmsg->msg_iov, @@ -65,7 +65,7 @@ lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, sendmsg->msg_iov, sendmsg->msg_offset, mlen); } else { - if (iov != NULL) + if (iov) lnet_copy_kiov2iov(niov, iov, offset, sendmsg->msg_niov, sendmsg->msg_kiov, diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index d7c983644ff0..c9c85e5d6aff 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -170,7 +170,7 @@ parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange) } LIBCFS_ALLOC(addrrange, sizeof(struct addrrange)); - if (addrrange == NULL) + if (!addrrange) return -ENOMEM; list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges); INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges); @@ -203,7 +203,7 @@ add_nidrange(const struct cfs_lstr *src, return NULL; nf = libcfs_namenum2netstrfns(src->ls_str); - if (nf == NULL) + if (!nf) return NULL; endlen = src->ls_len - strlen(nf->nf_name); if (endlen == 0) @@ -229,7 +229,7 @@ add_nidrange(const struct cfs_lstr *src, } LIBCFS_ALLOC(nr, sizeof(struct nidrange)); - if (nr == NULL) + if (!nr) return NULL; list_add_tail(&nr->nr_link, nidlist); INIT_LIST_HEAD(&nr->nr_addrranges); @@ -258,11 +258,11 @@ parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist) if (cfs_gettok(src, '@', &addrrange) == 0) goto failed; - if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL) + if (cfs_gettok(src, '@', &net) == 0 || src->ls_str) goto failed; nr = add_nidrange(&net, nidlist); - if (nr == NULL) + if (!nr) goto failed; if (parse_addrange(&addrrange, nr) != 0) @@ -489,13 +489,13 @@ static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid, tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) | (min_ip[2] << 8) | min_ip[3]); - if (min_nid != NULL) + if (min_nid) *min_nid = tmp_ip_addr; tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) | (max_ip[2] << 8) | max_ip[3]); - if (max_nid != NULL) + if (max_nid) *max_nid = tmp_ip_addr; } @@ -524,9 +524,9 @@ static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid, } } - if (min_nid != NULL) + if (min_nid) *min_nid = min_addr; - if (max_nid != NULL) + if (max_nid) *max_nid = max_addr; } @@ -548,7 +548,7 @@ bool cfs_nidrange_is_contiguous(struct list_head *nidlist) list_for_each_entry(nr, nidlist, nr_link) { nf = nr->nr_netstrfns; - if (lndname == NULL) + if (!lndname) lndname = nf->nf_name; if (netnum == -1) netnum = nr->nr_netnum; @@ -558,7 +558,7 @@ bool cfs_nidrange_is_contiguous(struct list_head *nidlist) return false; } - if (nf == NULL) + if (!nf) return false; if (!nf->nf_is_contiguous(nidlist)) @@ -765,9 +765,9 @@ static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid, } } - if (min_nid != NULL) + if (min_nid) *min_nid = min_ip_addr; - if (max_nid != NULL) + if (max_nid) *max_nid = max_ip_addr; } @@ -828,7 +828,7 @@ cfs_ip_addr_parse(char *str, int len, struct list_head *list) src.ls_len = len; i = 0; - while (src.ls_str != NULL) { + while (src.ls_str) { struct cfs_lstr res; if (!cfs_gettok(&src, '.', &res)) { @@ -1064,7 +1064,7 @@ libcfs_name2netstrfns(const char *name) int libcfs_isknown_lnd(__u32 lnd) { - return libcfs_lnd2netstrfns(lnd) != NULL; + return !!libcfs_lnd2netstrfns(lnd); } EXPORT_SYMBOL(libcfs_isknown_lnd); @@ -1073,7 +1073,7 @@ libcfs_lnd2modname(__u32 lnd) { struct netstrfns *nf = libcfs_lnd2netstrfns(lnd); - return (nf == NULL) ? NULL : nf->nf_modname; + return nf ? nf->nf_modname : NULL; } EXPORT_SYMBOL(libcfs_lnd2modname); @@ -1082,7 +1082,7 @@ libcfs_str2lnd(const char *str) { struct netstrfns *nf = libcfs_name2netstrfns(str); - if (nf != NULL) + if (nf) return nf->nf_type; return -1; @@ -1095,7 +1095,7 @@ libcfs_lnd2str_r(__u32 lnd, char *buf, size_t buf_size) struct netstrfns *nf; nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) + if (!nf) snprintf(buf, buf_size, "?%u?", lnd); else snprintf(buf, buf_size, "%s", nf->nf_name); @@ -1112,7 +1112,7 @@ libcfs_net2str_r(__u32 net, char *buf, size_t buf_size) struct netstrfns *nf; nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) + if (!nf) snprintf(buf, buf_size, "<%u:%u>", lnd, nnum); else if (nnum == 0) snprintf(buf, buf_size, "%s", nf->nf_name); @@ -1139,7 +1139,7 @@ libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size) } nf = libcfs_lnd2netstrfns(lnd); - if (nf == NULL) { + if (!nf) { snprintf(buf, buf_size, "%x@<%u:%u>", addr, lnd, nnum); } else { size_t addr_len; @@ -1199,7 +1199,7 @@ libcfs_str2net(const char *str) { __u32 net; - if (libcfs_str2net_internal(str, &net) != NULL) + if (libcfs_str2net_internal(str, &net)) return net; return LNET_NIDNET(LNET_NID_ANY); @@ -1214,15 +1214,15 @@ libcfs_str2nid(const char *str) __u32 net; __u32 addr; - if (sep != NULL) { + if (sep) { nf = libcfs_str2net_internal(sep + 1, &net); - if (nf == NULL) + if (!nf) return LNET_NID_ANY; } else { sep = str + strlen(str); net = LNET_MKNET(SOCKLND, 0); nf = libcfs_lnd2netstrfns(SOCKLND); - LASSERT(nf != NULL); + LASSERT(nf); } if (!nf->nf_str2addr(str, (int)(sep - str), &addr)) diff --git a/drivers/staging/lustre/lnet/lnet/peer.c b/drivers/staging/lustre/lnet/lnet/peer.c index a8e25b0d11b3..43b459e919e4 100644 --- a/drivers/staging/lustre/lnet/lnet/peer.c +++ b/drivers/staging/lustre/lnet/lnet/peer.c @@ -50,7 +50,7 @@ lnet_peer_tables_create(void) the_lnet.ln_peer_tables = cfs_percpt_alloc(lnet_cpt_table(), sizeof(*ptable)); - if (the_lnet.ln_peer_tables == NULL) { + if (!the_lnet.ln_peer_tables) { CERROR("Failed to allocate cpu-partition peer tables\n"); return -ENOMEM; } @@ -60,7 +60,7 @@ lnet_peer_tables_create(void) LIBCFS_CPT_ALLOC(hash, lnet_cpt_table(), i, LNET_PEER_HASH_SIZE * sizeof(*hash)); - if (hash == NULL) { + if (!hash) { CERROR("Failed to create peer hash table\n"); lnet_peer_tables_destroy(); return -ENOMEM; @@ -82,12 +82,12 @@ lnet_peer_tables_destroy(void) int i; int j; - if (the_lnet.ln_peer_tables == NULL) + if (!the_lnet.ln_peer_tables) return; cfs_percpt_for_each(ptable, i, the_lnet.ln_peer_tables) { hash = ptable->pt_hash; - if (hash == NULL) /* not initialized */ + if (!hash) /* not initialized */ break; LASSERT(list_empty(&ptable->pt_deathrow)); @@ -220,7 +220,7 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) ptable = the_lnet.ln_peer_tables[cpt2]; lp = lnet_find_peer_locked(ptable, nid); - if (lp != NULL) { + if (lp) { *lpp = lp; return 0; } @@ -238,12 +238,12 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) ptable->pt_number++; lnet_net_unlock(cpt); - if (lp != NULL) + if (lp) memset(lp, 0, sizeof(*lp)); else LIBCFS_CPT_ALLOC(lp, lnet_cpt_table(), cpt2, sizeof(*lp)); - if (lp == NULL) { + if (!lp) { rc = -ENOMEM; lnet_net_lock(cpt); goto out; @@ -276,13 +276,13 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) } lp2 = lnet_find_peer_locked(ptable, nid); - if (lp2 != NULL) { + if (lp2) { *lpp = lp2; goto out; } lp->lp_ni = lnet_net2ni_locked(LNET_NIDNET(nid), cpt2); - if (lp->lp_ni == NULL) { + if (!lp->lp_ni) { rc = -EHOSTUNREACH; goto out; } @@ -299,7 +299,7 @@ lnet_nid2peer_locked(lnet_peer_t **lpp, lnet_nid_t nid, int cpt) return 0; out: - if (lp != NULL) + if (lp) list_add(&lp->lp_hashlist, &ptable->pt_deathrow); ptable->pt_number--; return rc; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index 36f3caabc2a6..c6b747dae8a1 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -138,7 +138,7 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) * NB individual events can be missed; the only guarantee is that you * always get the most recent news */ - if (lp->lp_notifying || ni == NULL) + if (lp->lp_notifying || !ni) return; lp->lp_notifying = 1; @@ -150,7 +150,7 @@ lnet_ni_notify_locked(lnet_ni_t *ni, lnet_peer_t *lp) lp->lp_notifylnd = 0; lp->lp_notify = 0; - if (notifylnd && ni->ni_lnd->lnd_notify != NULL) { + if (notifylnd && ni->ni_lnd->lnd_notify) { lnet_net_unlock(lp->lp_cpt); /* @@ -204,7 +204,7 @@ lnet_rtr_decref_locked(lnet_peer_t *lp) if (lp->lp_rtr_refcount == 0) { LASSERT(list_empty(&lp->lp_routes)); - if (lp->lp_rcd != NULL) { + if (lp->lp_rcd) { list_add(&lp->lp_rcd->rcd_list, &the_lnet.ln_rcd_deathrow); lp->lp_rcd = NULL; @@ -323,12 +323,12 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, /* Assume net, route, all new */ LIBCFS_ALLOC(route, sizeof(*route)); LIBCFS_ALLOC(rnet, sizeof(*rnet)); - if (route == NULL || rnet == NULL) { + if (!route || !rnet) { CERROR("Out of memory creating route %s %d %s\n", libcfs_net2str(net), hops, libcfs_nid2str(gateway)); - if (route != NULL) + if (route) LIBCFS_FREE(route, sizeof(*route)); - if (rnet != NULL) + if (rnet) LIBCFS_FREE(rnet, sizeof(*rnet)); return -ENOMEM; } @@ -359,7 +359,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, LASSERT(!the_lnet.ln_shutdown); rnet2 = lnet_find_net_locked(net); - if (rnet2 == NULL) { + if (!rnet2) { /* new network */ list_add_tail(&rnet->lrn_list, lnet_net2rnethash(net)); rnet2 = rnet; @@ -387,7 +387,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, lnet_net_unlock(LNET_LOCK_EX); /* XXX Assume alive */ - if (ni->ni_lnd->lnd_notify != NULL) + if (ni->ni_lnd->lnd_notify) ni->ni_lnd->lnd_notify(ni, gateway, 1); lnet_net_lock(LNET_LOCK_EX); @@ -433,7 +433,7 @@ lnet_check_routes(void) route = list_entry(e2, lnet_route_t, lr_list); - if (route2 == NULL) { + if (!route2) { route2 = route; continue; } @@ -518,7 +518,7 @@ lnet_del_route(__u32 net, lnet_nid_t gw_nid) LIBCFS_FREE(route, sizeof(*route)); - if (rnet != NULL) + if (rnet) LIBCFS_FREE(rnet, sizeof(*rnet)); rc = 0; @@ -696,7 +696,7 @@ lnet_router_checker_event(lnet_event_t *event) lnet_rc_data_t *rcd = event->md.user_ptr; struct lnet_peer *lp; - LASSERT(rcd != NULL); + LASSERT(rcd); if (event->unlinked) { LNetInvalidateHandle(&rcd->rcd_mdh); @@ -707,7 +707,7 @@ lnet_router_checker_event(lnet_event_t *event) event->type == LNET_EVENT_REPLY); lp = rcd->rcd_gateway; - LASSERT(lp != NULL); + LASSERT(lp); /* * NB: it's called with holding lnet_res_lock, we have a few @@ -822,7 +822,7 @@ lnet_update_ni_status_locked(void) continue; } - LASSERT(ni->ni_status != NULL); + LASSERT(ni->ni_status); if (ni->ni_status->ns_status != LNET_NI_STATUS_DOWN) { CDEBUG(D_NET, "NI(%s:%d) status changed to down\n", @@ -844,7 +844,7 @@ lnet_destroy_rc_data(lnet_rc_data_t *rcd) /* detached from network */ LASSERT(LNetHandleIsInvalid(rcd->rcd_mdh)); - if (rcd->rcd_gateway != NULL) { + if (rcd->rcd_gateway) { int cpt = rcd->rcd_gateway->lp_cpt; lnet_net_lock(cpt); @@ -852,7 +852,7 @@ lnet_destroy_rc_data(lnet_rc_data_t *rcd) lnet_net_unlock(cpt); } - if (rcd->rcd_pinginfo != NULL) + if (rcd->rcd_pinginfo) LIBCFS_FREE(rcd->rcd_pinginfo, LNET_PINGINFO_SIZE); LIBCFS_FREE(rcd, sizeof(*rcd)); @@ -869,14 +869,14 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) lnet_net_unlock(gateway->lp_cpt); LIBCFS_ALLOC(rcd, sizeof(*rcd)); - if (rcd == NULL) + if (!rcd) goto out; LNetInvalidateHandle(&rcd->rcd_mdh); INIT_LIST_HEAD(&rcd->rcd_list); LIBCFS_ALLOC(pi, LNET_PINGINFO_SIZE); - if (pi == NULL) + if (!pi) goto out; for (i = 0; i < LNET_MAX_RTR_NIS; i++) { @@ -902,7 +902,7 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) lnet_net_lock(gateway->lp_cpt); /* router table changed or someone has created rcd for this gateway */ - if (!lnet_isrouter(gateway) || gateway->lp_rcd != NULL) { + if (!lnet_isrouter(gateway) || gateway->lp_rcd) { lnet_net_unlock(gateway->lp_cpt); goto out; } @@ -915,7 +915,7 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) return rcd; out: - if (rcd != NULL) { + if (rcd) { if (!LNetHandleIsInvalid(rcd->rcd_mdh)) { rc = LNetMDUnlink(rcd->rcd_mdh); LASSERT(rc == 0); @@ -963,10 +963,10 @@ lnet_ping_router_locked(lnet_peer_t *rtr) return; } - rcd = rtr->lp_rcd != NULL ? + rcd = rtr->lp_rcd ? rtr->lp_rcd : lnet_create_rc_data_locked(rtr); - if (rcd == NULL) + if (!rcd) return; secs = lnet_router_check_interval(rtr); @@ -1109,7 +1109,7 @@ lnet_prune_rc_data(int wait_unlink) /* router checker is stopping, prune all */ list_for_each_entry(lp, &the_lnet.ln_routers, lp_rtr_list) { - if (lp->lp_rcd == NULL) + if (!lp->lp_rcd) continue; LASSERT(list_empty(&lp->lp_rcd->rcd_list)); @@ -1256,7 +1256,7 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) int i; LIBCFS_CPT_ALLOC(rb, lnet_cpt_table(), cpt, sz); - if (rb == NULL) + if (!rb) return NULL; rb->rb_pool = rbp; @@ -1265,7 +1265,7 @@ lnet_new_rtrbuf(lnet_rtrbufpool_t *rbp, int cpt) page = alloc_pages_node( cfs_cpt_spread_node(lnet_cpt_table(), cpt), GFP_KERNEL | __GFP_ZERO, 0); - if (page == NULL) { + if (!page) { while (--i >= 0) __free_page(rb->rb_kiov[i].kiov_page); @@ -1325,7 +1325,7 @@ lnet_rtrpool_alloc_bufs(lnet_rtrbufpool_t *rbp, int nbufs, int cpt) for (i = 0; i < nbufs; i++) { rb = lnet_new_rtrbuf(rbp, cpt); - if (rb == NULL) { + if (!rb) { CERROR("Failed to allocate %d router bufs of %d pages\n", nbufs, rbp->rbp_npages); return -ENOMEM; @@ -1362,7 +1362,7 @@ lnet_rtrpools_free(void) lnet_rtrbufpool_t *rtrp; int i; - if (the_lnet.ln_rtrpools == NULL) /* uninitialized or freed */ + if (!the_lnet.ln_rtrpools) /* uninitialized or freed */ return; cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { @@ -1475,7 +1475,7 @@ lnet_rtrpools_alloc(int im_a_router) the_lnet.ln_rtrpools = cfs_percpt_alloc(lnet_cpt_table(), LNET_NRBPOOLS * sizeof(lnet_rtrbufpool_t)); - if (the_lnet.ln_rtrpools == NULL) { + if (!the_lnet.ln_rtrpools) { LCONSOLE_ERROR_MSG(0x10c, "Failed to initialize router buffe pool\n"); return -ENOMEM; @@ -1519,11 +1519,11 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) LASSERT(!in_interrupt()); CDEBUG(D_NET, "%s notifying %s: %s\n", - (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid), + !ni ? "userspace" : libcfs_nid2str(ni->ni_nid), libcfs_nid2str(nid), alive ? "up" : "down"); - if (ni != NULL && + if (ni && LNET_NIDNET(ni->ni_nid) != LNET_NIDNET(nid)) { CWARN("Ignoring notification of %s %s by %s (different net)\n", libcfs_nid2str(nid), alive ? "birth" : "death", @@ -1534,13 +1534,13 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) /* can't do predictions... */ if (cfs_time_after(when, now)) { CWARN("Ignoring prediction from %s of %s %s %ld seconds in the future\n", - (ni == NULL) ? "userspace" : libcfs_nid2str(ni->ni_nid), + !ni ? "userspace" : libcfs_nid2str(ni->ni_nid), libcfs_nid2str(nid), alive ? "up" : "down", cfs_duration_sec(cfs_time_sub(when, now))); return -EINVAL; } - if (ni != NULL && !alive && /* LND telling me she's down */ + if (ni && !alive && /* LND telling me she's down */ !auto_down) { /* auto-down disabled */ CDEBUG(D_NET, "Auto-down disabled\n"); return 0; @@ -1554,7 +1554,7 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) } lp = lnet_find_peer_locked(the_lnet.ln_peer_tables[cpt], nid); - if (lp == NULL) { + if (!lp) { /* nid not found */ lnet_net_unlock(cpt); CDEBUG(D_NET, "%s not found\n", libcfs_nid2str(nid)); @@ -1567,10 +1567,10 @@ lnet_notify(lnet_ni_t *ni, lnet_nid_t nid, int alive, unsigned long when) * call us with when == _time_when_the_node_was_booted_ if * no connections were successfully established */ - if (ni != NULL && !alive && when < lp->lp_last_alive) + if (ni && !alive && when < lp->lp_last_alive) when = lp->lp_last_alive; - lnet_notify_locked(lp, ni == NULL, alive, when); + lnet_notify_locked(lp, !ni, alive, when); lnet_ni_notify_locked(ni, lp); diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 124737e8a4ae..230fc15170b7 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -114,11 +114,11 @@ static int __proc_lnet_stats(void *data, int write, /* read */ LIBCFS_ALLOC(ctrs, sizeof(*ctrs)); - if (ctrs == NULL) + if (!ctrs) return -ENOMEM; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) { + if (!tmpstr) { LIBCFS_FREE(ctrs, sizeof(*ctrs)); return -ENOMEM; } @@ -174,7 +174,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ @@ -209,13 +209,12 @@ static int proc_lnet_routes(struct ctl_table *table, int write, return -ESTALE; } - for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE && route == NULL; - i++) { + for (i = 0; i < LNET_REMOTE_NETS_HASH_SIZE && !route; i++) { rn_list = &the_lnet.ln_remote_nets_hash[i]; n = rn_list->next; - while (n != rn_list && route == NULL) { + while (n != rn_list && !route) { rnet = list_entry(n, lnet_remotenet_t, lrn_list); @@ -238,7 +237,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, } } - if (route != NULL) { + if (route) { __u32 net = rnet->lrn_net; unsigned int hops = route->lr_hops; unsigned int priority = route->lr_priority; @@ -298,7 +297,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ @@ -344,7 +343,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, r = r->next; } - if (peer != NULL) { + if (peer) { lnet_nid_t nid = peer->lp_nid; unsigned long now = cfs_time_current(); unsigned long deadline = peer->lp_ping_deadline; @@ -441,7 +440,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, } LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ @@ -475,7 +474,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, } while (hash < LNET_PEER_HASH_SIZE) { - if (p == NULL) + if (!p) p = ptable->pt_hash[hash].next; while (p != &ptable->pt_hash[hash]) { @@ -504,7 +503,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, p = lp->lp_hashlist.next; } - if (peer != NULL) + if (peer) break; p = NULL; @@ -512,7 +511,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, hash++; } - if (peer != NULL) { + if (peer) { lnet_nid_t nid = peer->lp_nid; int nrefs = peer->lp_refcount; int lastalive = -1; @@ -560,7 +559,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, cpt++; hash = 0; hoff = 1; - if (peer == NULL && cpt < LNET_CPT_NUMBER) + if (!peer && cpt < LNET_CPT_NUMBER) goto again; } } @@ -600,7 +599,7 @@ static int __proc_lnet_buffers(void *data, int write, /* (4 %d) * 4 * LNET_CPT_NUMBER */ tmpsiz = 64 * (LNET_NRBPOOLS + 1) * LNET_CPT_NUMBER; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ @@ -610,7 +609,7 @@ static int __proc_lnet_buffers(void *data, int write, "pages", "count", "credits", "min"); LASSERT(tmpstr + tmpsiz - s > 0); - if (the_lnet.ln_rtrpools == NULL) + if (!the_lnet.ln_rtrpools) goto out; /* I'm not a router */ for (idx = 0; idx < LNET_NRBPOOLS; idx++) { @@ -664,7 +663,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); - if (tmpstr == NULL) + if (!tmpstr) return -ENOMEM; s = tmpstr; /* points to current position in tmpstr[] */ @@ -696,7 +695,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, n = n->next; } - if (ni != NULL) { + if (ni) { struct lnet_tx_queue *tq; char *stat; time64_t now = ktime_get_real_seconds(); @@ -712,7 +711,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, last_alive = 0; lnet_ni_lock(ni); - LASSERT(ni->ni_status != NULL); + LASSERT(ni->ni_status); stat = (ni->ni_status->ns_status == LNET_NI_STATUS_UP) ? "up" : "down"; lnet_ni_unlock(ni); @@ -722,7 +721,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, * TX queue of each partition */ cfs_percpt_for_each(tq, i, ni->ni_tx_queues) { - for (j = 0; ni->ni_cpts != NULL && + for (j = 0; ni->ni_cpts && j < ni->ni_ncpts; j++) { if (i == ni->ni_cpts[j]) break; @@ -817,7 +816,7 @@ static int __proc_lnet_portal_rotor(void *data, int write, int i; LIBCFS_ALLOC(buf, buf_len); - if (buf == NULL) + if (!buf) return -ENOMEM; if (!write) { @@ -854,7 +853,7 @@ static int __proc_lnet_portal_rotor(void *data, int write, rc = -EINVAL; lnet_res_lock(0); - for (i = 0; portal_rotors[i].pr_name != NULL; i++) { + for (i = 0; portal_rotors[i].pr_name; i++) { if (strncasecmp(portal_rotors[i].pr_name, tmp, strlen(portal_rotors[i].pr_name)) == 0) { portal_rotor = portal_rotors[i].pr_value; diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 4af91cb01bae..38aed80b1a4a 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -58,7 +58,7 @@ brw_client_fini(sfw_test_instance_t *tsi) list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { bulk = tsu->tsu_private; - if (bulk == NULL) + if (!bulk) continue; srpc_free_bulk(bulk); @@ -77,7 +77,7 @@ brw_client_init(sfw_test_instance_t *tsi) srpc_bulk_t *bulk; sfw_test_unit_t *tsu; - LASSERT(sn != NULL); + LASSERT(sn); LASSERT(tsi->tsi_is_client); if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { @@ -120,7 +120,7 @@ brw_client_init(sfw_test_instance_t *tsi) list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid), npg, len, opc == LST_BRW_READ); - if (bulk == NULL) { + if (!bulk) { brw_client_fini(tsi); return -ENOMEM; } @@ -157,7 +157,7 @@ brw_fill_page(struct page *pg, int pattern, __u64 magic) char *addr = page_address(pg); int i; - LASSERT(addr != NULL); + LASSERT(addr); if (pattern == LST_BRW_CHECK_NONE) return; @@ -188,7 +188,7 @@ brw_check_page(struct page *pg, int pattern, __u64 magic) __u64 data = 0; /* make compiler happy */ int i; - LASSERT(addr != NULL); + LASSERT(addr); if (pattern == LST_BRW_CHECK_NONE) return 0; @@ -269,8 +269,8 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, int opc; int rc; - LASSERT(sn != NULL); - LASSERT(bulk != NULL); + LASSERT(sn); + LASSERT(bulk); if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; @@ -324,7 +324,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; - LASSERT(sn != NULL); + LASSERT(sn); if (rpc->crpc_status != 0) { CERROR("BRW RPC to %s failed with %d\n", @@ -368,7 +368,7 @@ brw_server_rpc_done(struct srpc_server_rpc *rpc) { srpc_bulk_t *blk = rpc->srpc_bulk; - if (blk == NULL) + if (!blk) return; if (rpc->srpc_status != 0) @@ -391,8 +391,8 @@ brw_bulk_ready(struct srpc_server_rpc *rpc, int status) srpc_brw_reqst_t *reqst; srpc_msg_t *reqstmsg; - LASSERT(rpc->srpc_bulk != NULL); - LASSERT(rpc->srpc_reqstbuf != NULL); + LASSERT(rpc->srpc_bulk); + LASSERT(rpc->srpc_reqstbuf); reqstmsg = &rpc->srpc_reqstbuf->buf_msg; reqst = &reqstmsg->msg_body.brw_reqst; diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index cb5c125791f7..8b9717c63b45 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -51,15 +51,15 @@ lst_session_new_ioctl(lstio_session_new_args_t *args) char *name; int rc; - if (args->lstio_ses_idp == NULL || /* address for output sid */ + if (!args->lstio_ses_idp || /* address for output sid */ args->lstio_ses_key == 0 || /* no key is specified */ - args->lstio_ses_namep == NULL || /* session name */ + !args->lstio_ses_namep || /* session name */ args->lstio_ses_nmlen <= 0 || args->lstio_ses_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_ses_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_ses_namep, @@ -95,11 +95,11 @@ lst_session_info_ioctl(lstio_session_info_args_t *args) { /* no checking of key */ - if (args->lstio_ses_idp == NULL || /* address for output sid */ - args->lstio_ses_keyp == NULL || /* address for output key */ - args->lstio_ses_featp == NULL || /* address for output features */ - args->lstio_ses_ndinfo == NULL || /* address for output ndinfo */ - args->lstio_ses_namep == NULL || /* 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; @@ -122,17 +122,17 @@ lst_debug_ioctl(lstio_debug_args_t *args) if (args->lstio_dbg_key != console_session.ses_key) return -EACCES; - if (args->lstio_dbg_resultp == NULL) + if (!args->lstio_dbg_resultp) return -EINVAL; - if (args->lstio_dbg_namep != NULL && /* 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; - if (args->lstio_dbg_namep != NULL) { + if (args->lstio_dbg_namep) { LIBCFS_ALLOC(name, args->lstio_dbg_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_dbg_namep, @@ -156,7 +156,7 @@ lst_debug_ioctl(lstio_debug_args_t *args) case LST_OPC_BATCHSRV: client = 0; case LST_OPC_BATCHCLI: - if (name == NULL) + if (!name) goto out; rc = lstcon_batch_debug(args->lstio_dbg_timeout, @@ -164,7 +164,7 @@ lst_debug_ioctl(lstio_debug_args_t *args) break; case LST_OPC_GROUP: - if (name == NULL) + if (!name) goto out; rc = lstcon_group_debug(args->lstio_dbg_timeout, @@ -173,7 +173,7 @@ lst_debug_ioctl(lstio_debug_args_t *args) case LST_OPC_NODES: if (args->lstio_dbg_count <= 0 || - args->lstio_dbg_idsp == NULL) + !args->lstio_dbg_idsp) goto out; rc = lstcon_nodes_debug(args->lstio_dbg_timeout, @@ -187,7 +187,7 @@ lst_debug_ioctl(lstio_debug_args_t *args) } out: - if (name != NULL) + if (name) LIBCFS_FREE(name, args->lstio_dbg_nmlen + 1); return rc; @@ -202,13 +202,13 @@ lst_group_add_ioctl(lstio_group_add_args_t *args) if (args->lstio_grp_key != console_session.ses_key) return -EACCES; - if (args->lstio_grp_namep == NULL || + if (!args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, @@ -235,13 +235,13 @@ lst_group_del_ioctl(lstio_group_del_args_t *args) if (args->lstio_grp_key != console_session.ses_key) return -EACCES; - if (args->lstio_grp_namep == NULL || + if (!args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, @@ -268,14 +268,14 @@ lst_group_update_ioctl(lstio_group_update_args_t *args) if (args->lstio_grp_key != console_session.ses_key) return -EACCES; - if (args->lstio_grp_resultp == NULL || - args->lstio_grp_namep == NULL || + if (!args->lstio_grp_resultp || + !args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, @@ -298,7 +298,7 @@ lst_group_update_ioctl(lstio_group_update_args_t *args) case LST_GROUP_RMND: if (args->lstio_grp_count <= 0 || - args->lstio_grp_idsp == NULL) { + !args->lstio_grp_idsp) { rc = -EINVAL; break; } @@ -327,17 +327,17 @@ 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 == NULL || /* array of ids */ + if (!args->lstio_grp_idsp || /* array of ids */ args->lstio_grp_count <= 0 || - args->lstio_grp_resultp == NULL || - args->lstio_grp_featp == NULL || - args->lstio_grp_namep == NULL || + !args->lstio_grp_resultp || + !args->lstio_grp_featp || + !args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, @@ -369,7 +369,7 @@ lst_group_list_ioctl(lstio_group_list_args_t *args) return -EACCES; if (args->lstio_grp_idx < 0 || - args->lstio_grp_namep == NULL || + !args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; @@ -390,18 +390,18 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) if (args->lstio_grp_key != console_session.ses_key) return -EACCES; - if (args->lstio_grp_namep == NULL || + if (!args->lstio_grp_namep || args->lstio_grp_nmlen <= 0 || args->lstio_grp_nmlen > LST_NAME_SIZE) return -EINVAL; - if (args->lstio_grp_entp == NULL && /* output: group entry */ - args->lstio_grp_dentsp == NULL) /* 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 != NULL) { /* have node entry */ - if (args->lstio_grp_idxp == NULL || /* node index */ - args->lstio_grp_ndentp == NULL) /* # 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, @@ -415,7 +415,7 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) } LIBCFS_ALLOC(name, args->lstio_grp_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_grp_namep, @@ -434,7 +434,7 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) if (rc != 0) return rc; - if (args->lstio_grp_dentsp != NULL && + if (args->lstio_grp_dentsp && (copy_to_user(args->lstio_grp_idxp, &index, sizeof(index)) || copy_to_user(args->lstio_grp_ndentp, &ndent, sizeof(ndent)))) return -EFAULT; @@ -451,13 +451,13 @@ lst_batch_add_ioctl(lstio_batch_add_args_t *args) if (args->lstio_bat_key != console_session.ses_key) return -EACCES; - if (args->lstio_bat_namep == NULL || + if (!args->lstio_bat_namep || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, @@ -484,13 +484,13 @@ lst_batch_run_ioctl(lstio_batch_run_args_t *args) if (args->lstio_bat_key != console_session.ses_key) return -EACCES; - if (args->lstio_bat_namep == NULL || + if (!args->lstio_bat_namep || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, @@ -518,14 +518,14 @@ lst_batch_stop_ioctl(lstio_batch_stop_args_t *args) if (args->lstio_bat_key != console_session.ses_key) return -EACCES; - if (args->lstio_bat_resultp == NULL || - args->lstio_bat_namep == NULL || + if (!args->lstio_bat_resultp || + !args->lstio_bat_namep || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, @@ -553,8 +553,8 @@ lst_batch_query_ioctl(lstio_batch_query_args_t *args) if (args->lstio_bat_key != console_session.ses_key) return -EACCES; - if (args->lstio_bat_resultp == NULL || - args->lstio_bat_namep == NULL || + if (!args->lstio_bat_resultp || + !args->lstio_bat_namep || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; @@ -563,7 +563,7 @@ lst_batch_query_ioctl(lstio_batch_query_args_t *args) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, @@ -592,7 +592,7 @@ lst_batch_list_ioctl(lstio_batch_list_args_t *args) return -EACCES; if (args->lstio_bat_idx < 0 || - args->lstio_bat_namep == NULL || + !args->lstio_bat_namep || args->lstio_bat_nmlen <= 0 || args->lstio_bat_nmlen > LST_NAME_SIZE) return -EINVAL; @@ -613,18 +613,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 == NULL || /* 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 == NULL && /* output: batch entry */ - args->lstio_bat_dentsp == NULL) /* 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 != NULL) { /* have node entry */ - if (args->lstio_bat_idxp == NULL || /* node index */ - args->lstio_bat_ndentp == NULL) /* # 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, @@ -638,7 +638,7 @@ lst_batch_info_ioctl(lstio_batch_info_args_t *args) } LIBCFS_ALLOC(name, args->lstio_bat_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_bat_namep, @@ -658,7 +658,7 @@ lst_batch_info_ioctl(lstio_batch_info_args_t *args) if (rc != 0) return rc; - if (args->lstio_bat_dentsp != NULL && + if (args->lstio_bat_dentsp && (copy_to_user(args->lstio_bat_idxp, &index, sizeof(index)) || copy_to_user(args->lstio_bat_ndentp, &ndent, sizeof(ndent)))) rc = -EFAULT; @@ -676,19 +676,18 @@ lst_stat_query_ioctl(lstio_stat_args_t *args) if (args->lstio_sta_key != console_session.ses_key) return -EACCES; - if (args->lstio_sta_resultp == NULL || - (args->lstio_sta_namep == NULL && - args->lstio_sta_idsp == NULL) || + if (!args->lstio_sta_resultp || + (!args->lstio_sta_namep && !args->lstio_sta_idsp) || args->lstio_sta_nmlen <= 0 || args->lstio_sta_nmlen > LST_NAME_SIZE) return -EINVAL; - if (args->lstio_sta_idsp != NULL && + if (args->lstio_sta_idsp && args->lstio_sta_count <= 0) return -EINVAL; LIBCFS_ALLOC(name, args->lstio_sta_nmlen + 1); - if (name == NULL) + if (!name) return -ENOMEM; if (copy_from_user(name, args->lstio_sta_namep, @@ -697,7 +696,7 @@ lst_stat_query_ioctl(lstio_stat_args_t *args) return -EFAULT; } - if (args->lstio_sta_idsp == NULL) { + if (!args->lstio_sta_idsp) { rc = lstcon_group_stat(name, args->lstio_sta_timeout, args->lstio_sta_resultp); } else { @@ -721,15 +720,15 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) int ret = 0; int rc = -ENOMEM; - if (args->lstio_tes_resultp == NULL || - args->lstio_tes_retp == NULL || - args->lstio_tes_bat_name == NULL || /* no specified batch */ + if (!args->lstio_tes_resultp || + !args->lstio_tes_retp || + !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 == NULL || /* 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 == NULL || /* 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; @@ -741,26 +740,26 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) return -EINVAL; /* have parameter, check if parameter length is valid */ - if (args->lstio_tes_param != NULL && + if (args->lstio_tes_param && (args->lstio_tes_param_len <= 0 || args->lstio_tes_param_len > PAGE_CACHE_SIZE - sizeof(lstcon_test_t))) return -EINVAL; LIBCFS_ALLOC(batch_name, args->lstio_tes_bat_nmlen + 1); - if (batch_name == NULL) + if (!batch_name) return rc; LIBCFS_ALLOC(src_name, args->lstio_tes_sgrp_nmlen + 1); - if (src_name == NULL) + if (!src_name) goto out; LIBCFS_ALLOC(dst_name, args->lstio_tes_dgrp_nmlen + 1); - if (dst_name == NULL) + if (!dst_name) goto out; - if (args->lstio_tes_param != NULL) { + if (args->lstio_tes_param) { LIBCFS_ALLOC(param, args->lstio_tes_param_len); - if (param == NULL) + if (!param) goto out; } @@ -786,16 +785,16 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) rc = (copy_to_user(args->lstio_tes_retp, &ret, sizeof(ret))) ? -EFAULT : 0; out: - if (batch_name != NULL) + if (batch_name) LIBCFS_FREE(batch_name, args->lstio_tes_bat_nmlen + 1); - if (src_name != NULL) + if (src_name) LIBCFS_FREE(src_name, args->lstio_tes_sgrp_nmlen + 1); - if (dst_name != NULL) + if (dst_name) LIBCFS_FREE(dst_name, args->lstio_tes_dgrp_nmlen + 1); - if (param != NULL) + if (param) LIBCFS_FREE(param, args->lstio_tes_param_len); return rc; @@ -815,7 +814,7 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data) return -EINVAL; LIBCFS_ALLOC(buf, data->ioc_plen1); - if (buf == NULL) + if (!buf) return -ENOMEM; /* copy in parameter */ diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 817be93a149d..5315a37e5cf0 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -54,12 +54,12 @@ lstcon_rpc_done(srpc_client_rpc_t *rpc) { lstcon_rpc_t *crpc = (lstcon_rpc_t *)rpc->crpc_priv; - LASSERT(crpc != NULL && rpc == crpc->crp_rpc); + LASSERT(crpc && rpc == crpc->crp_rpc); LASSERT(crpc->crp_posted && !crpc->crp_finished); spin_lock(&rpc->crpc_lock); - if (crpc->crp_trans == NULL) { + if (!crpc->crp_trans) { /* * Orphan RPC is not in any transaction, * I'm just a poor body and nobody loves me @@ -96,7 +96,7 @@ lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats, crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service, feats, bulk_npg, bulk_len, lstcon_rpc_done, (void *)crpc); - if (crpc->crp_rpc == NULL) + if (!crpc->crp_rpc) return -ENOMEM; crpc->crp_trans = NULL; @@ -131,9 +131,9 @@ lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, spin_unlock(&console_session.ses_rpc_lock); - if (crpc == NULL) { + if (!crpc) { LIBCFS_ALLOC(crpc, sizeof(*crpc)); - if (crpc == NULL) + if (!crpc) return -ENOMEM; } @@ -157,7 +157,7 @@ lstcon_rpc_put(lstcon_rpc_t *crpc) LASSERT(list_empty(&crpc->crp_link)); for (i = 0; i < bulk->bk_niov; i++) { - if (bulk->bk_iovs[i].kiov_page == NULL) + if (!bulk->bk_iovs[i].kiov_page) continue; __free_page(bulk->bk_iovs[i].kiov_page); @@ -188,7 +188,7 @@ lstcon_rpc_post(lstcon_rpc_t *crpc) { lstcon_rpc_trans_t *trans = crpc->crp_trans; - LASSERT(trans != NULL); + LASSERT(trans); atomic_inc(&trans->tas_remaining); crpc->crp_posted = 1; @@ -241,7 +241,7 @@ lstcon_rpc_trans_prep(struct list_head *translist, { lstcon_rpc_trans_t *trans; - if (translist != NULL) { + if (translist) { list_for_each_entry(trans, translist, tas_link) { /* * Can't enqueue two private transaction on @@ -254,12 +254,12 @@ lstcon_rpc_trans_prep(struct list_head *translist, /* create a trans group */ LIBCFS_ALLOC(trans, sizeof(*trans)); - if (trans == NULL) + if (!trans) return -ENOMEM; trans->tas_opc = transop; - if (translist == NULL) + if (!translist) INIT_LIST_HEAD(&trans->tas_olink); else list_add_tail(&trans->tas_olink, translist); @@ -393,7 +393,7 @@ lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) srpc_client_rpc_t *rpc = crpc->crp_rpc; srpc_generic_reply_t *rep; - LASSERT(nd != NULL && rpc != NULL); + LASSERT(nd && rpc); LASSERT(crpc->crp_stamp != 0); if (crpc->crp_status != 0) { @@ -430,7 +430,7 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) srpc_msg_t *rep; int error; - LASSERT(stat != NULL); + LASSERT(stat); memset(stat, 0, sizeof(*stat)); @@ -484,7 +484,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, struct timeval tv; int error; - LASSERT(head_up != NULL); + LASSERT(head_up); next = head_up; @@ -530,7 +530,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, sizeof(rep->status))) return -EFAULT; - if (readent == NULL) + if (!readent) continue; error = readent(trans->tas_opc, msg, ent); @@ -866,7 +866,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, bulk->bk_iovs[i].kiov_page = alloc_page(GFP_KERNEL); - if (bulk->bk_iovs[i].kiov_page == NULL) { + if (!bulk->bk_iovs[i].kiov_page) { lstcon_rpc_put(*crpc); return -ENOMEM; } @@ -1108,7 +1108,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, feats = trans->tas_features; list_for_each_entry(ndl, ndlist, ndl_link) { - rc = condition == NULL ? 1 : + rc = !condition ? 1 : condition(transop, ndl->ndl_node, arg); if (rc == 0) @@ -1201,7 +1201,7 @@ lstcon_rpc_pinger(void *arg) trans = console_session.ses_ping; - LASSERT(trans != NULL); + LASSERT(trans); list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) { nd = ndl->ndl_node; @@ -1226,7 +1226,7 @@ lstcon_rpc_pinger(void *arg) crpc = &nd->nd_ping; - if (crpc->crp_rpc != NULL) { + if (crpc->crp_rpc) { LASSERT(crpc->crp_trans == trans); LASSERT(!list_empty(&crpc->crp_link)); diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 914d842929a7..89954179fdec 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -90,7 +90,7 @@ lstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create) return -ENOENT; LIBCFS_ALLOC(*ndpp, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t)); - if (*ndpp == NULL) + if (!*ndpp) return -ENOMEM; ndl = (lstcon_ndlink_t *)(*ndpp + 1); @@ -168,7 +168,7 @@ lstcon_ndlink_find(struct list_head *hash, return rc; LIBCFS_ALLOC(ndl, sizeof(lstcon_ndlink_t)); - if (ndl == NULL) { + if (!ndl) { lstcon_node_put(nd); return -ENOMEM; } @@ -202,11 +202,11 @@ lstcon_group_alloc(char *name, lstcon_group_t **grpp) LIBCFS_ALLOC(grp, offsetof(lstcon_group_t, grp_ndl_hash[LST_NODE_HASHSIZE])); - if (grp == NULL) + if (!grp) return -ENOMEM; grp->grp_ref = 1; - if (name != NULL) + if (name) strcpy(grp->grp_name, name); INIT_LIST_HEAD(&grp->grp_link); @@ -348,7 +348,7 @@ lstcon_sesrpc_condition(int transop, lstcon_node_t *nd, void *arg) if (nd->nd_state != LST_NODE_ACTIVE) return 0; - if (grp != NULL && nd->nd_ref > 1) + if (grp && nd->nd_ref > 1) return 0; break; @@ -545,7 +545,7 @@ lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up, int rc; LASSERT(count > 0); - LASSERT(ids_up != NULL); + LASSERT(ids_up); rc = lstcon_group_find(name, &grp); if (rc != 0) { @@ -721,7 +721,7 @@ lstcon_group_list(int index, int len, char __user *name_up) lstcon_group_t *grp; LASSERT(index >= 0); - LASSERT(name_up != NULL); + LASSERT(name_up); list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) { if (index-- == 0) { @@ -742,8 +742,8 @@ lstcon_nodes_getent(struct list_head *head, int *index_p, int count = 0; int index = 0; - LASSERT(index_p != NULL && count_p != NULL); - LASSERT(dents_up != NULL); + LASSERT(index_p && count_p); + LASSERT(dents_up); LASSERT(*index_p >= 0); LASSERT(*count_p > 0); @@ -800,7 +800,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, /* non-verbose query */ LIBCFS_ALLOC(gentp, sizeof(lstcon_ndlist_ent_t)); - if (gentp == NULL) { + if (!gentp) { CERROR("Can't allocate ndlist_ent\n"); lstcon_group_decref(grp); @@ -849,14 +849,14 @@ lstcon_batch_add(char *name) } LIBCFS_ALLOC(bat, sizeof(lstcon_batch_t)); - if (bat == NULL) { + if (!bat) { CERROR("Can't allocate descriptor for batch %s\n", name); return -ENOMEM; } LIBCFS_ALLOC(bat->bat_cli_hash, sizeof(struct list_head) * LST_NODE_HASHSIZE); - if (bat->bat_cli_hash == NULL) { + if (!bat->bat_cli_hash) { CERROR("Can't allocate hash for batch %s\n", name); LIBCFS_FREE(bat, sizeof(lstcon_batch_t)); @@ -865,7 +865,7 @@ lstcon_batch_add(char *name) LIBCFS_ALLOC(bat->bat_srv_hash, sizeof(struct list_head) * LST_NODE_HASHSIZE); - if (bat->bat_srv_hash == NULL) { + 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)); @@ -900,7 +900,7 @@ lstcon_batch_list(int index, int len, char __user *name_up) { lstcon_batch_t *bat; - LASSERT(name_up != NULL); + LASSERT(name_up); LASSERT(index >= 0); list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) { @@ -945,12 +945,12 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, } } - clilst = (test == NULL) ? &bat->bat_cli_list : - &test->tes_src_grp->grp_ndl_list; - srvlst = (test == NULL) ? &bat->bat_srv_list : - &test->tes_dst_grp->grp_ndl_list; + clilst = !test ? &bat->bat_cli_list : + &test->tes_src_grp->grp_ndl_list; + srvlst = !test ? &bat->bat_srv_list : + &test->tes_dst_grp->grp_ndl_list; - if (dents_up != NULL) { + if (dents_up) { rc = lstcon_nodes_getent((server ? srvlst : clilst), index_p, ndent_p, dents_up); return rc; @@ -958,10 +958,10 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, /* non-verbose query */ LIBCFS_ALLOC(entp, sizeof(lstcon_test_batch_ent_t)); - if (entp == NULL) + if (!entp) return -ENOMEM; - if (test == NULL) { + if (!test) { entp->u.tbe_batch.bae_ntest = bat->bat_ntest; entp->u.tbe_batch.bae_state = bat->bat_state; @@ -1138,10 +1138,10 @@ lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg) struct list_head *head; test = (lstcon_test_t *)arg; - LASSERT(test != NULL); + LASSERT(test); batch = test->tes_batch; - LASSERT(batch != NULL); + LASSERT(batch); if (test->tes_oneside && transop == LST_TRANS_TSBSRVADD) @@ -1180,8 +1180,8 @@ lstcon_test_nodes_add(lstcon_test_t *test, struct list_head __user *result_up) int transop; int rc; - LASSERT(test->tes_src_grp != NULL); - LASSERT(test->tes_dst_grp != NULL); + LASSERT(test->tes_src_grp); + LASSERT(test->tes_dst_grp); transop = LST_TRANS_TSBSRVADD; grp = test->tes_dst_grp; @@ -1319,7 +1319,7 @@ lstcon_test_add(char *batch_name, int type, int loop, test->tes_dst_grp = dst_grp; INIT_LIST_HEAD(&test->tes_trans_list); - if (param != NULL) { + if (param) { test->tes_paramlen = paramlen; memcpy(&test->tes_param[0], param, paramlen); } @@ -1343,13 +1343,13 @@ lstcon_test_add(char *batch_name, int type, int loop, /* hold groups so nobody can change them */ return rc; out: - if (test != NULL) + if (test) LIBCFS_FREE(test, offsetof(lstcon_test_t, tes_param[paramlen])); - if (dst_grp != NULL) + if (dst_grp) lstcon_group_decref(dst_grp); - if (src_grp != NULL) + if (src_grp) lstcon_group_decref(src_grp); return rc; @@ -1777,7 +1777,7 @@ lstcon_session_info(lst_sid_t __user *sid_up, int __user *key_up, return -ESRCH; LIBCFS_ALLOC(entp, sizeof(*entp)); - if (entp == NULL) + if (!entp) return -ENOMEM; list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) @@ -1967,7 +1967,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) out: rep->msg_ses_feats = console_session.ses_features; - if (grp != NULL) + if (grp) lstcon_group_decref(grp); mutex_unlock(&console_session.ses_mutex); @@ -2016,7 +2016,7 @@ lstcon_console_init(void) LIBCFS_ALLOC(console_session.ses_ndl_hash, sizeof(struct list_head) * LST_GLOBAL_HASHSIZE); - if (console_session.ses_ndl_hash == NULL) + if (!console_session.ses_ndl_hash) return -ENOMEM; for (i = 0; i < LST_GLOBAL_HASHSIZE; i++) diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index c61d3e777fab..e8221a744f83 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -139,14 +139,14 @@ sfw_register_test(srpc_service_t *service, sfw_test_client_ops_t *cliops) { sfw_test_case_t *tsc; - if (sfw_find_test_case(service->sv_id) != NULL) { + if (sfw_find_test_case(service->sv_id)) { CERROR("Failed to register test %s (%d)\n", service->sv_name, service->sv_id); return -EEXIST; } LIBCFS_ALLOC(tsc, sizeof(sfw_test_case_t)); - if (tsc == NULL) + if (!tsc) return -ENOMEM; tsc->tsc_cli_ops = cliops; @@ -164,7 +164,7 @@ sfw_add_session_timer(void) LASSERT(!sfw_data.fw_shuttingdown); - if (sn == NULL || sn->sn_timeout == 0) + if (!sn || sn->sn_timeout == 0) return; LASSERT(!sn->sn_timer_active); @@ -180,7 +180,7 @@ sfw_del_session_timer(void) { sfw_session_t *sn = sfw_data.fw_session; - if (sn == NULL || !sn->sn_timer_active) + if (!sn || !sn->sn_timer_active) return 0; LASSERT(sn->sn_timeout != 0); @@ -202,7 +202,7 @@ sfw_deactivate_session(void) sfw_batch_t *tsb; sfw_test_case_t *tsc; - if (sn == NULL) + if (!sn) return; LASSERT(!sn->sn_timer_active); @@ -294,7 +294,7 @@ sfw_server_rpc_done(struct srpc_server_rpc *rpc) swi_state2str(rpc->srpc_wi.swi_state), status); - if (rpc->srpc_bulk != NULL) + if (rpc->srpc_bulk) sfw_free_pages(rpc); return; } @@ -326,7 +326,7 @@ sfw_find_batch(lst_bid_t bid) sfw_session_t *sn = sfw_data.fw_session; sfw_batch_t *bat; - LASSERT(sn != NULL); + LASSERT(sn); list_for_each_entry(bat, &sn->sn_batches, bat_list) { if (bat->bat_id.bat_id == bid.bat_id) @@ -342,14 +342,14 @@ sfw_bid2batch(lst_bid_t bid) sfw_session_t *sn = sfw_data.fw_session; sfw_batch_t *bat; - LASSERT(sn != NULL); + LASSERT(sn); bat = sfw_find_batch(bid); - if (bat != NULL) + if (bat) return bat; LIBCFS_ALLOC(bat, sizeof(sfw_batch_t)); - if (bat == NULL) + if (!bat) return NULL; bat->bat_error = 0; @@ -369,14 +369,14 @@ sfw_get_stats(srpc_stat_reqst_t *request, srpc_stat_reply_t *reply) sfw_counters_t *cnt = &reply->str_fw; sfw_batch_t *bat; - reply->str_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id; + reply->str_sid = !sn ? LST_INVALID_SID : sn->sn_id; if (request->str_sid.ses_nid == LNET_NID_ANY) { reply->str_status = EINVAL; return 0; } - if (sn == NULL || !sfw_sid_equal(request->str_sid, sn->sn_id)) { + if (!sn || !sfw_sid_equal(request->str_sid, sn->sn_id)) { reply->str_status = ESRCH; return 0; } @@ -412,12 +412,12 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) int cplen = 0; if (request->mksn_sid.ses_nid == LNET_NID_ANY) { - reply->mksn_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id; + reply->mksn_sid = !sn ? LST_INVALID_SID : sn->sn_id; reply->mksn_status = EINVAL; return 0; } - if (sn != NULL) { + if (sn) { reply->mksn_status = 0; reply->mksn_sid = sn->sn_id; reply->mksn_timeout = sn->sn_timeout; @@ -452,7 +452,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)); - if (sn == NULL) { + if (!sn) { CERROR("Dropping RPC (mksn) under memory pressure.\n"); return -ENOMEM; } @@ -463,7 +463,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) spin_lock(&sfw_data.fw_lock); sfw_deactivate_session(); - LASSERT(sfw_data.fw_session == NULL); + LASSERT(!sfw_data.fw_session); sfw_data.fw_session = sn; spin_unlock(&sfw_data.fw_lock); @@ -479,15 +479,15 @@ sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply) { sfw_session_t *sn = sfw_data.fw_session; - reply->rmsn_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id; + reply->rmsn_sid = !sn ? LST_INVALID_SID : sn->sn_id; if (request->rmsn_sid.ses_nid == LNET_NID_ANY) { reply->rmsn_status = EINVAL; return 0; } - if (sn == NULL || !sfw_sid_equal(request->rmsn_sid, sn->sn_id)) { - reply->rmsn_status = (sn == NULL) ? ESRCH : EBUSY; + if (!sn || !sfw_sid_equal(request->rmsn_sid, sn->sn_id)) { + reply->rmsn_status = !sn ? ESRCH : EBUSY; return 0; } @@ -502,7 +502,7 @@ sfw_remove_session(srpc_rmsn_reqst_t *request, srpc_rmsn_reply_t *reply) reply->rmsn_status = 0; reply->rmsn_sid = LST_INVALID_SID; - LASSERT(sfw_data.fw_session == NULL); + LASSERT(!sfw_data.fw_session); return 0; } @@ -511,7 +511,7 @@ sfw_debug_session(srpc_debug_reqst_t *request, srpc_debug_reply_t *reply) { sfw_session_t *sn = sfw_data.fw_session; - if (sn == NULL) { + if (!sn) { reply->dbg_status = ESRCH; reply->dbg_sid = LST_INVALID_SID; return 0; @@ -557,10 +557,10 @@ sfw_load_test(struct sfw_test_instance *tsi) int nbuf; int rc; - LASSERT(tsi != NULL); + LASSERT(tsi); tsc = sfw_find_test_case(tsi->tsi_service); nbuf = sfw_test_buffers(tsi); - LASSERT(tsc != NULL); + LASSERT(tsc); svc = tsc->tsc_srv_service; if (tsi->tsi_is_client) { @@ -593,7 +593,7 @@ sfw_unload_test(struct sfw_test_instance *tsi) { struct sfw_test_case *tsc = sfw_find_test_case(tsi->tsi_service); - LASSERT(tsc != NULL); + LASSERT(tsc); if (tsi->tsi_is_client) return; @@ -740,7 +740,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) int rc; LIBCFS_ALLOC(tsi, sizeof(*tsi)); - if (tsi == NULL) { + if (!tsi) { CERROR("Can't allocate test instance for batch: %llu\n", tsb->bat_id.bat_id); return -ENOMEM; @@ -774,7 +774,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) return 0; } - LASSERT(bk != NULL); + LASSERT(bk); LASSERT(bk->bk_niov * SFW_ID_PER_PAGE >= (unsigned int)ndest); LASSERT((unsigned int)bk->bk_len >= sizeof(lnet_process_id_packed_t) * ndest); @@ -788,14 +788,14 @@ 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 != NULL); /* 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); for (j = 0; j < tsi->tsi_concur; j++) { LIBCFS_ALLOC(tsu, sizeof(sfw_test_unit_t)); - if (tsu == NULL) { + if (!tsu) { rc = -ENOMEM; CERROR("Can't allocate tsu for %d\n", tsi->tsi_service); @@ -923,7 +923,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, spin_unlock(&tsi->tsi_lock); - if (rpc == NULL) { + if (!rpc) { rpc = srpc_create_client_rpc(peer, tsi->tsi_service, nblk, blklen, sfw_test_rpc_done, sfw_test_rpc_fini, tsu); @@ -933,7 +933,7 @@ sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer, sfw_test_rpc_fini, tsu); } - if (rpc == NULL) { + if (!rpc) { CERROR("Can't create rpc for test %d\n", tsi->tsi_service); return -ENOMEM; } @@ -954,11 +954,11 @@ sfw_run_test(swi_workitem_t *wi) LASSERT(wi == &tsu->tsu_worker); if (tsi->tsi_ops->tso_prep_rpc(tsu, tsu->tsu_dest, &rpc) != 0) { - LASSERT(rpc == NULL); + LASSERT(!rpc); goto test_done; } - LASSERT(rpc != NULL); + LASSERT(rpc); spin_lock(&tsi->tsi_lock); @@ -1107,11 +1107,11 @@ int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len, int sink) { - LASSERT(rpc->srpc_bulk == NULL); + LASSERT(!rpc->srpc_bulk); LASSERT(npages > 0 && npages <= LNET_MAX_IOV); rpc->srpc_bulk = srpc_alloc_bulk(cpt, npages, len, sink); - if (rpc->srpc_bulk == NULL) + if (!rpc->srpc_bulk) return -ENOMEM; return 0; @@ -1127,7 +1127,7 @@ sfw_add_test(struct srpc_server_rpc *rpc) sfw_batch_t *bat; request = &rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst; - reply->tsr_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id; + reply->tsr_sid = !sn ? LST_INVALID_SID : sn->sn_id; if (request->tsr_loop == 0 || request->tsr_concur == 0 || @@ -1141,14 +1141,14 @@ sfw_add_test(struct srpc_server_rpc *rpc) return 0; } - if (sn == NULL || !sfw_sid_equal(request->tsr_sid, sn->sn_id) || - sfw_find_test_case(request->tsr_service) == NULL) { + if (!sn || !sfw_sid_equal(request->tsr_sid, sn->sn_id) || + !sfw_find_test_case(request->tsr_service)) { reply->tsr_status = ENOENT; return 0; } bat = sfw_bid2batch(request->tsr_bid); - if (bat == NULL) { + if (!bat) { CERROR("Dropping RPC (%s) from %s under memory pressure.\n", rpc->srpc_scd->scd_svc->sv_name, libcfs_id2str(rpc->srpc_peer)); @@ -1160,7 +1160,7 @@ sfw_add_test(struct srpc_server_rpc *rpc) return 0; } - if (request->tsr_is_client && rpc->srpc_bulk == NULL) { + if (request->tsr_is_client && !rpc->srpc_bulk) { /* rpc will be resumed later in sfw_bulk_ready */ int npg = sfw_id_pages(request->tsr_ndest); int len; @@ -1194,15 +1194,15 @@ sfw_control_batch(srpc_batch_reqst_t *request, srpc_batch_reply_t *reply) int rc = 0; sfw_batch_t *bat; - reply->bar_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id; + reply->bar_sid = !sn ? LST_INVALID_SID : sn->sn_id; - if (sn == NULL || !sfw_sid_equal(request->bar_sid, sn->sn_id)) { + if (!sn || !sfw_sid_equal(request->bar_sid, sn->sn_id)) { reply->bar_status = ESRCH; return 0; } bat = sfw_find_batch(request->bar_bid); - if (bat == NULL) { + if (!bat) { reply->bar_status = ENOENT; return 0; } @@ -1237,7 +1237,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) unsigned features = LST_FEATS_MASK; int rc = 0; - LASSERT(sfw_data.fw_active_srpc == NULL); + LASSERT(!sfw_data.fw_active_srpc); LASSERT(sv->sv_id <= SRPC_FRAMEWORK_SERVICE_MAX_ID); spin_lock(&sfw_data.fw_lock); @@ -1268,7 +1268,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) sv->sv_id != SRPC_SERVICE_DEBUG) { sfw_session_t *sn = sfw_data.fw_session; - if (sn != NULL && + if (sn && sn->sn_features != request->msg_ses_feats) { CNETERR("Features of framework RPC don't match features of current session: %x/%x\n", request->msg_ses_feats, sn->sn_features); @@ -1320,7 +1320,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) break; } - if (sfw_data.fw_session != NULL) + if (sfw_data.fw_session) features = sfw_data.fw_session->sn_features; out: reply->msg_ses_feats = features; @@ -1341,9 +1341,9 @@ sfw_bulk_ready(struct srpc_server_rpc *rpc, int status) struct srpc_service *sv = rpc->srpc_scd->scd_svc; int rc; - LASSERT(rpc->srpc_bulk != NULL); + LASSERT(rpc->srpc_bulk); LASSERT(sv->sv_id == SRPC_SERVICE_TEST); - LASSERT(sfw_data.fw_active_srpc == NULL); + LASSERT(!sfw_data.fw_active_srpc); LASSERT(rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst.tsr_is_client); spin_lock(&sfw_data.fw_lock); @@ -1405,7 +1405,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, spin_unlock(&sfw_data.fw_lock); - if (rpc == NULL) { + if (!rpc) { rpc = srpc_create_client_rpc(peer, service, nbulkiov, bulklen, done, nbulkiov != 0 ? NULL : @@ -1413,7 +1413,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, priv); } - if (rpc != NULL) /* "session" is concept in framework */ + if (rpc) /* "session" is concept in framework */ rpc->crpc_reqstmsg.msg_ses_feats = features; return rpc; @@ -1702,7 +1702,7 @@ sfw_startup(void) for (i = 0; ; i++) { sv = &sfw_services[i]; - if (sv->sv_name == NULL) + if (!sv->sv_name) break; sv->sv_bulk_ready = NULL; @@ -1746,11 +1746,11 @@ sfw_shutdown(void) spin_lock(&sfw_data.fw_lock); sfw_data.fw_shuttingdown = 1; - lst_wait_until(sfw_data.fw_active_srpc == NULL, sfw_data.fw_lock, + lst_wait_until(!sfw_data.fw_active_srpc, sfw_data.fw_lock, "waiting for active RPC to finish.\n"); if (sfw_del_session_timer() != 0) - lst_wait_until(sfw_data.fw_session == NULL, sfw_data.fw_lock, + lst_wait_until(!sfw_data.fw_session, sfw_data.fw_lock, "waiting for session timer to explode.\n"); sfw_deactivate_session(); @@ -1763,7 +1763,7 @@ sfw_shutdown(void) for (i = 0; ; i++) { sv = &sfw_services[i]; - if (sv->sv_name == NULL) + if (!sv->sv_name) break; srpc_shutdown_service(sv); @@ -1788,7 +1788,7 @@ sfw_shutdown(void) for (i = 0; ; i++) { sv = &sfw_services[i]; - if (sv->sv_name == NULL) + if (!sv->sv_name) break; srpc_wait_service_shutdown(sv); diff --git a/drivers/staging/lustre/lnet/selftest/module.c b/drivers/staging/lustre/lnet/selftest/module.c index 46cbdf0456cc..741509afb906 100644 --- a/drivers/staging/lustre/lnet/selftest/module.c +++ b/drivers/staging/lustre/lnet/selftest/module.c @@ -70,7 +70,7 @@ lnet_selftest_fini(void) case LST_INIT_WI_TEST: for (i = 0; i < cfs_cpt_number(lnet_cpt_table()); i++) { - if (lst_sched_test[i] == NULL) + if (!lst_sched_test[i]) continue; cfs_wi_sched_destroy(lst_sched_test[i]); } @@ -106,7 +106,7 @@ lnet_selftest_init(void) nscheds = cfs_cpt_number(lnet_cpt_table()); LIBCFS_ALLOC(lst_sched_test, sizeof(lst_sched_test[0]) * nscheds); - if (lst_sched_test == NULL) + if (!lst_sched_test) goto error; lst_init_step = LST_INIT_WI_TEST; diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 1d23a3082a67..01ceee53311b 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -61,7 +61,7 @@ ping_client_init(sfw_test_instance_t *tsi) sfw_session_t *sn = tsi->tsi_batch->bat_session; LASSERT(tsi->tsi_is_client); - LASSERT(sn != NULL && (sn->sn_features & ~LST_FEATS_MASK) == 0); + LASSERT(sn && (sn->sn_features & ~LST_FEATS_MASK) == 0); spin_lock_init(&lst_ping_data.pnd_lock); lst_ping_data.pnd_counter = 0; @@ -75,7 +75,7 @@ ping_client_fini(sfw_test_instance_t *tsi) sfw_session_t *sn = tsi->tsi_batch->bat_session; int errors; - LASSERT(sn != NULL); + LASSERT(sn); LASSERT(tsi->tsi_is_client); errors = atomic_read(&sn->sn_ping_errors); @@ -95,7 +95,7 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, struct timespec64 ts; int rc; - LASSERT(sn != NULL); + LASSERT(sn); LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, 0, 0, rpc); @@ -126,7 +126,7 @@ ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) srpc_ping_reply_t *reply = &rpc->crpc_replymsg.msg_body.ping_reply; struct timespec64 ts; - LASSERT(sn != NULL); + LASSERT(sn); if (rpc->crpc_status != 0) { if (!tsi->tsi_stopping) /* rpc could have been aborted */ diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 6b102164cfc2..1e78711634f2 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -107,11 +107,11 @@ srpc_free_bulk(srpc_bulk_t *bk) int i; struct page *pg; - LASSERT(bk != NULL); + LASSERT(bk); for (i = 0; i < bk->bk_niov; i++) { pg = bk->bk_iovs[i].kiov_page; - if (pg == NULL) + if (!pg) break; __free_page(pg); @@ -131,7 +131,7 @@ srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink) LIBCFS_CPT_ALLOC(bk, lnet_cpt_table(), cpt, offsetof(srpc_bulk_t, bk_iovs[bulk_npg])); - if (bk == NULL) { + if (!bk) { CERROR("Can't allocate descriptor for %d pages\n", bulk_npg); return NULL; } @@ -147,7 +147,7 @@ srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink) pg = alloc_pages_node(cfs_cpt_spread_node(lnet_cpt_table(), cpt), GFP_KERNEL, 0); - if (pg == NULL) { + if (!pg) { CERROR("Can't allocate page %d of %d\n", i, bulk_npg); srpc_free_bulk(bk); return NULL; @@ -199,7 +199,7 @@ srpc_service_fini(struct srpc_service *svc) struct list_head *q; int i; - if (svc->sv_cpt_data == NULL) + if (!svc->sv_cpt_data) return; cfs_percpt_for_each(scd, i, svc->sv_cpt_data) { @@ -258,7 +258,7 @@ srpc_service_init(struct srpc_service *svc) svc->sv_cpt_data = cfs_percpt_alloc(lnet_cpt_table(), sizeof(struct srpc_service_cd)); - if (svc->sv_cpt_data == NULL) + if (!svc->sv_cpt_data) return -ENOMEM; svc->sv_ncpts = srpc_serv_is_framework(svc) ? @@ -297,7 +297,7 @@ srpc_service_init(struct srpc_service *svc) for (j = 0; j < nrpcs; j++) { LIBCFS_CPT_ALLOC(rpc, lnet_cpt_table(), i, sizeof(*rpc)); - if (rpc == NULL) { + if (!rpc) { srpc_service_fini(svc); return -ENOMEM; } @@ -322,7 +322,7 @@ srpc_add_service(struct srpc_service *sv) LASSERT(srpc_data.rpc_state == SRPC_STATE_RUNNING); - if (srpc_data.rpc_services[id] != NULL) { + if (srpc_data.rpc_services[id]) { spin_unlock(&srpc_data.rpc_glock); goto failed; } @@ -536,7 +536,7 @@ srpc_add_buffer(struct swi_workitem *wi) spin_unlock(&scd->scd_lock); LIBCFS_ALLOC(buf, sizeof(*buf)); - if (buf == NULL) { + if (!buf) { CERROR("Failed to add new buf to service: %s\n", scd->scd_svc->sv_name); spin_lock(&scd->scd_lock); @@ -880,7 +880,7 @@ srpc_do_bulk(struct srpc_server_rpc *rpc) int rc; int opt; - LASSERT(bk != NULL); + LASSERT(bk); opt = bk->bk_sink ? LNET_MD_OP_GET : LNET_MD_OP_PUT; opt |= LNET_MD_KIOV; @@ -921,13 +921,13 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) spin_unlock(&srpc_data.rpc_glock); } - if (rpc->srpc_done != NULL) + if (rpc->srpc_done) (*rpc->srpc_done) (rpc); - LASSERT(rpc->srpc_bulk == NULL); + LASSERT(!rpc->srpc_bulk); spin_lock(&scd->scd_lock); - if (rpc->srpc_reqstbuf != NULL) { + if (rpc->srpc_reqstbuf) { /* * NB might drop sv_lock in srpc_service_recycle_buffer, but * sv won't go away for scd_rpc_active must not be empty @@ -980,7 +980,7 @@ srpc_handle_rpc(swi_workitem_t *wi) if (sv->sv_shuttingdown || rpc->srpc_aborted) { spin_unlock(&scd->scd_lock); - if (rpc->srpc_bulk != NULL) + if (rpc->srpc_bulk) LNetMDUnlink(rpc->srpc_bulk->bk_mdh); LNetMDUnlink(rpc->srpc_replymdh); @@ -1028,7 +1028,7 @@ srpc_handle_rpc(swi_workitem_t *wi) wi->swi_state = SWI_STATE_BULK_STARTED; - if (rpc->srpc_bulk != NULL) { + if (rpc->srpc_bulk) { rc = srpc_do_bulk(rpc); if (rc == 0) return 0; /* wait for bulk */ @@ -1038,12 +1038,12 @@ srpc_handle_rpc(swi_workitem_t *wi) } } case SWI_STATE_BULK_STARTED: - LASSERT(rpc->srpc_bulk == NULL || ev->ev_fired); + LASSERT(!rpc->srpc_bulk || ev->ev_fired); - if (rpc->srpc_bulk != NULL) { + if (rpc->srpc_bulk) { rc = ev->ev_status; - if (sv->sv_bulk_ready != NULL) + if (sv->sv_bulk_ready) rc = (*sv->sv_bulk_ready) (rpc, rc); if (rc != 0) { @@ -1186,11 +1186,11 @@ srpc_send_rpc(swi_workitem_t *wi) srpc_msg_t *reply; int do_bulk; - LASSERT(wi != NULL); + LASSERT(wi); rpc = wi->swi_workitem.wi_data; - LASSERT(rpc != NULL); + LASSERT(rpc); LASSERT(wi == &rpc->crpc_wi); reply = &rpc->crpc_replymsg; @@ -1322,7 +1322,7 @@ srpc_create_client_rpc(lnet_process_id_t peer, int service, LIBCFS_ALLOC(rpc, offsetof(srpc_client_rpc_t, crpc_bulk.bk_iovs[nbulkiov])); - if (rpc == NULL) + if (!rpc) return NULL; srpc_init_client_rpc(rpc, peer, service, nbulkiov, @@ -1377,7 +1377,7 @@ srpc_send_reply(struct srpc_server_rpc *rpc) __u64 rpyid; int rc; - LASSERT(buffer != NULL); + LASSERT(buffer); rpyid = buffer->buf_msg.msg_body.reqst.rpyid; spin_lock(&scd->scd_lock); @@ -1664,8 +1664,7 @@ srpc_shutdown(void) for (i = 0; i <= SRPC_SERVICE_MAX_ID; i++) { srpc_service_t *sv = srpc_data.rpc_services[i]; - LASSERTF(sv == NULL, - "service not empty: id %d, name %s\n", + 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 906e26abcd0e..e6367ec21453 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -504,11 +504,11 @@ void srpc_shutdown(void); static inline void srpc_destroy_client_rpc(srpc_client_rpc_t *rpc) { - LASSERT(rpc != NULL); + LASSERT(rpc); LASSERT(!srpc_event_pending(rpc)); LASSERT(atomic_read(&rpc->crpc_refcount) == 0); - if (rpc->crpc_fini == NULL) + if (!rpc->crpc_fini) LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); else (*rpc->crpc_fini) (rpc); diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index b98c08a10606..dce5137c7dfe 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -75,7 +75,7 @@ stt_add_timer(stt_timer_t *timer) LASSERT(stt_data.stt_nthreads > 0); LASSERT(!stt_data.stt_shuttingdown); - LASSERT(timer->stt_func != NULL); + LASSERT(timer->stt_func); LASSERT(list_empty(&timer->stt_list)); LASSERT(timer->stt_expires > ktime_get_real_seconds()); -- cgit From 5fd88337d209d5948ab86b6dfca968dbb29ef89a Mon Sep 17 00:00:00 2001 From: James Simmons Date: Fri, 12 Feb 2016 12:06:09 -0500 Subject: staging: lustre: fix all conditional comparison to zero in LNet layer Doing if (rc != 0) or if (rc == 0) is bad form. This patch corrects the LNet code to behavior according to kernel coding standards. Signed-off-by: James Simmons Signed-off-by: Greg Kroah-Hartman --- .../staging/lustre/include/linux/lnet/lib-lnet.h | 21 ++- .../staging/lustre/include/linux/lnet/lib-types.h | 2 +- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c | 137 ++++++++------- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h | 14 +- .../staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c | 186 ++++++++++----------- .../lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c | 2 +- .../staging/lustre/lnet/klnds/socklnd/socklnd.c | 139 ++++++++------- .../staging/lustre/lnet/klnds/socklnd/socklnd_cb.c | 148 ++++++++-------- .../lustre/lnet/klnds/socklnd/socklnd_lib.c | 42 ++--- .../lustre/lnet/klnds/socklnd/socklnd_proto.c | 54 +++--- drivers/staging/lustre/lnet/lnet/acceptor.c | 36 ++-- drivers/staging/lustre/lnet/lnet/api-ni.c | 113 +++++++------ drivers/staging/lustre/lnet/lnet/config.c | 63 +++---- drivers/staging/lustre/lnet/lnet/lib-eq.c | 18 +- drivers/staging/lustre/lnet/lnet/lib-md.c | 42 ++--- drivers/staging/lustre/lnet/lnet/lib-me.c | 4 +- drivers/staging/lustre/lnet/lnet/lib-move.c | 92 +++++----- drivers/staging/lustre/lnet/lnet/lib-msg.c | 22 +-- drivers/staging/lustre/lnet/lnet/lib-ptl.c | 52 +++--- drivers/staging/lustre/lnet/lnet/lib-socket.c | 58 +++---- drivers/staging/lustre/lnet/lnet/module.c | 8 +- drivers/staging/lustre/lnet/lnet/nidstrings.c | 52 +++--- drivers/staging/lustre/lnet/lnet/peer.c | 12 +- drivers/staging/lustre/lnet/lnet/router.c | 52 +++--- drivers/staging/lustre/lnet/lnet/router_proc.c | 46 ++--- drivers/staging/lustre/lnet/selftest/brw_test.c | 36 ++-- drivers/staging/lustre/lnet/selftest/conctl.c | 12 +- drivers/staging/lustre/lnet/selftest/conrpc.c | 102 +++++------ drivers/staging/lustre/lnet/selftest/console.c | 168 +++++++++---------- drivers/staging/lustre/lnet/selftest/framework.c | 79 +++++---- drivers/staging/lustre/lnet/selftest/module.c | 10 +- drivers/staging/lustre/lnet/selftest/ping_test.c | 10 +- drivers/staging/lustre/lnet/selftest/rpc.c | 130 +++++++------- drivers/staging/lustre/lnet/selftest/selftest.h | 10 +- drivers/staging/lustre/lnet/selftest/timer.c | 4 +- 35 files changed, 985 insertions(+), 991 deletions(-) diff --git a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h index 618126b196e4..b0f80b4c4313 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-lnet.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-lnet.h @@ -72,8 +72,8 @@ static inline int lnet_is_wire_handle_none(lnet_handle_wire_t *wh) static inline int lnet_md_exhausted(lnet_libmd_t *md) { - return (md->md_threshold == 0 || - ((md->md_options & LNET_MD_MAX_SIZE) != 0 && + return (!md->md_threshold || + ((md->md_options & LNET_MD_MAX_SIZE) && md->md_offset + md->md_max_size > md->md_length)); } @@ -85,13 +85,13 @@ static inline int lnet_md_unlinkable(lnet_libmd_t *md) * LNetM[DE]Unlink, in the latter case md may not be exhausted). * - auto unlink is on and md is exhausted. */ - if (md->md_refcount != 0) + if (md->md_refcount) return 0; - if ((md->md_flags & LNET_MD_FLAG_ZOMBIE) != 0) + if (md->md_flags & LNET_MD_FLAG_ZOMBIE) return 1; - return ((md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) != 0 && + return ((md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) && lnet_md_exhausted(md)); } @@ -186,12 +186,11 @@ lnet_md_alloc(lnet_md_t *umd) unsigned int size; unsigned int niov; - if ((umd->options & LNET_MD_KIOV) != 0) { + if (umd->options & LNET_MD_KIOV) { niov = umd->length; size = offsetof(lnet_libmd_t, md_iov.kiov[niov]); } else { - niov = ((umd->options & LNET_MD_IOVEC) != 0) ? - umd->length : 1; + niov = umd->options & LNET_MD_IOVEC ? umd->length : 1; size = offsetof(lnet_libmd_t, md_iov.iov[niov]); } @@ -212,7 +211,7 @@ lnet_md_free(lnet_libmd_t *md) { unsigned int size; - if ((md->md_options & LNET_MD_KIOV) != 0) + if (md->md_options & LNET_MD_KIOV) size = offsetof(lnet_libmd_t, md_iov.kiov[md->md_niov]); else size = offsetof(lnet_libmd_t, md_iov.iov[md->md_niov]); @@ -364,14 +363,14 @@ lnet_peer_decref_locked(lnet_peer_t *lp) { LASSERT(lp->lp_refcount > 0); lp->lp_refcount--; - if (lp->lp_refcount == 0) + if (!lp->lp_refcount) lnet_destroy_peer_locked(lp); } static inline int lnet_isrouter(lnet_peer_t *lp) { - return lp->lp_rtr_refcount != 0; + return lp->lp_rtr_refcount ? 1 : 0; } static inline void diff --git a/drivers/staging/lustre/include/linux/lnet/lib-types.h b/drivers/staging/lustre/include/linux/lnet/lib-types.h index 42f08c889456..d769c356723c 100644 --- a/drivers/staging/lustre/include/linux/lnet/lib-types.h +++ b/drivers/staging/lustre/include/linux/lnet/lib-types.h @@ -359,7 +359,7 @@ struct lnet_peer_table { * peer aliveness is enabled only on routers for peers in a network where the * lnet_ni_t::ni_peertimeout has been set to a positive value */ -#define lnet_peer_aliveness_enabled(lp) (the_lnet.ln_routing != 0 && \ +#define lnet_peer_aliveness_enabled(lp) (the_lnet.ln_routing && \ (lp)->lp_ni->ni_peertimeout > 0) typedef struct { diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c index a3d654ad2107..2e7b5ca58ea9 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c @@ -63,7 +63,7 @@ static __u32 kiblnd_cksum(void *ptr, int nob) sum = ((sum << 1) | (sum >> 31)) + *c++; /* ensure I don't return 0 (== no checksum) */ - return (sum == 0) ? 1 : sum; + return !sum ? 1 : sum; } static char *kiblnd_msgtype2str(int type) @@ -257,7 +257,7 @@ int kiblnd_unpack_msg(kib_msg_t *msg, int nob) */ msg_cksum = flip ? __swab32(msg->ibm_cksum) : msg->ibm_cksum; msg->ibm_cksum = 0; - if (msg_cksum != 0 && + if (msg_cksum && msg_cksum != kiblnd_cksum(msg, msg_nob)) { CERROR("Bad checksum\n"); return -EPROTO; @@ -354,7 +354,7 @@ int kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid) write_lock_irqsave(&kiblnd_data.kib_global_lock, flags); /* always called with a ref on ni, which prevents ni being shutdown */ - LASSERT(net->ibn_shutdown == 0); + LASSERT(!net->ibn_shutdown); /* npeers only grows with the global lock held */ atomic_inc(&net->ibn_npeers); @@ -370,10 +370,10 @@ void kiblnd_destroy_peer(kib_peer_t *peer) kib_net_t *net = peer->ibp_ni->ni_data; LASSERT(net); - LASSERT(atomic_read(&peer->ibp_refcount) == 0); + LASSERT(!atomic_read(&peer->ibp_refcount)); LASSERT(!kiblnd_peer_active(peer)); - LASSERT(peer->ibp_connecting == 0); - LASSERT(peer->ibp_accepting == 0); + LASSERT(!peer->ibp_connecting); + LASSERT(!peer->ibp_accepting); LASSERT(list_empty(&peer->ibp_conns)); LASSERT(list_empty(&peer->ibp_tx_queue)); @@ -609,7 +609,7 @@ static void kiblnd_setup_mtu_locked(struct rdma_cm_id *cmid) mtu = kiblnd_translate_mtu(*kiblnd_tunables.kib_ib_mtu); LASSERT(mtu >= 0); - if (mtu != 0) + if (mtu) cmid->route.path_rec->mtu = mtu; } @@ -632,7 +632,7 @@ static int kiblnd_get_completion_vector(kib_conn_t *conn, int cpt) /* hash NID to CPU id in this partition... */ off = do_div(nid, cpumask_weight(mask)); for_each_cpu(i, mask) { - if (off-- == 0) + if (!off--) return i % vectors; } @@ -748,7 +748,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, rc = kiblnd_alloc_pages(&conn->ibc_rx_pages, cpt, IBLND_RX_MSG_PAGES(version)); - if (rc != 0) + if (rc) goto failed_2; kiblnd_map_rx_descs(conn); @@ -767,7 +767,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, conn->ibc_cq = cq; rc = ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); - if (rc != 0) { + if (rc) { CERROR("Can't request completion notificiation: %d\n", rc); goto failed_2; } @@ -786,7 +786,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, conn->ibc_sched = sched; rc = rdma_create_qp(cmid, conn->ibc_hdev->ibh_pd, init_qp_attr); - if (rc != 0) { + if (rc) { CERROR("Can't create QP: %d, send_wr: %d, recv_wr: %d\n", rc, init_qp_attr->cap.max_send_wr, init_qp_attr->cap.max_recv_wr); @@ -803,7 +803,7 @@ kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid, for (i = 0; i < IBLND_RX_MSGS(version); i++) { rc = kiblnd_post_rx(&conn->ibc_rxs[i], IBLND_POSTRX_NO_CREDIT); - if (rc != 0) { + if (rc) { CERROR("Can't post rxmsg: %d\n", rc); /* Make posted receives complete */ @@ -857,15 +857,15 @@ void kiblnd_destroy_conn(kib_conn_t *conn) int rc; LASSERT(!in_interrupt()); - LASSERT(atomic_read(&conn->ibc_refcount) == 0); + LASSERT(!atomic_read(&conn->ibc_refcount)); LASSERT(list_empty(&conn->ibc_early_rxs)); LASSERT(list_empty(&conn->ibc_tx_noops)); LASSERT(list_empty(&conn->ibc_tx_queue)); LASSERT(list_empty(&conn->ibc_tx_queue_rsrvd)); LASSERT(list_empty(&conn->ibc_tx_queue_nocred)); LASSERT(list_empty(&conn->ibc_active_txs)); - LASSERT(conn->ibc_noops_posted == 0); - LASSERT(conn->ibc_nsends_posted == 0); + LASSERT(!conn->ibc_noops_posted); + LASSERT(!conn->ibc_nsends_posted); switch (conn->ibc_state) { default: @@ -887,7 +887,7 @@ void kiblnd_destroy_conn(kib_conn_t *conn) if (conn->ibc_cq) { rc = ib_destroy_cq(conn->ibc_cq); - if (rc != 0) + if (rc) CWARN("Error destroying CQ: %d\n", rc); } @@ -1011,7 +1011,7 @@ static int kiblnd_close_matching_conns(lnet_ni_t *ni, lnet_nid_t nid) if (nid == LNET_NID_ANY) return 0; - return (count == 0) ? -ENOENT : 0; + return !count ? -ENOENT : 0; } int kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg) @@ -1087,7 +1087,7 @@ void kiblnd_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) read_unlock_irqrestore(glock, flags); - if (last_alive != 0) + if (last_alive) *when = last_alive; /* @@ -1213,7 +1213,7 @@ static void kiblnd_unmap_tx_pool(kib_tx_pool_t *tpo) kib_tx_t *tx; int i; - LASSERT(tpo->tpo_pool.po_allocated == 0); + LASSERT(!tpo->tpo_pool.po_allocated); if (!hdev) return; @@ -1239,7 +1239,7 @@ static kib_hca_dev_t *kiblnd_current_hdev(kib_dev_t *dev) read_lock_irqsave(&kiblnd_data.kib_global_lock, flags); while (dev->ibd_failover) { read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); - if (i++ % 50 == 0) + if (!(i++ % 50)) CDEBUG(D_NET, "%s: Wait for failover\n", dev->ibd_ifname); schedule_timeout(cfs_time_seconds(1) / 100); @@ -1275,7 +1275,7 @@ static void kiblnd_map_tx_pool(kib_tx_pool_t *tpo) CLASSERT(IBLND_MSG_SIZE <= PAGE_SIZE); /* No fancy arithmetic when we do the buffer calculations */ - CLASSERT(PAGE_SIZE % IBLND_MSG_SIZE == 0); + CLASSERT(!(PAGE_SIZE % IBLND_MSG_SIZE)); tpo->tpo_hdev = kiblnd_current_hdev(dev); @@ -1359,7 +1359,7 @@ struct ib_mr *kiblnd_find_rd_dma_mr(kib_hca_dev_t *hdev, kib_rdma_desc_t *rd) static void kiblnd_destroy_fmr_pool(kib_fmr_pool_t *pool) { - LASSERT(pool->fpo_map_count == 0); + LASSERT(!pool->fpo_map_count); if (pool->fpo_fmr_pool) ib_destroy_fmr_pool(pool->fpo_fmr_pool); @@ -1449,7 +1449,7 @@ static void kiblnd_fail_fmr_poolset(kib_fmr_poolset_t *fps, kib_fmr_pool_t, fpo_list); fpo->fpo_failed = 1; list_del(&fpo->fpo_list); - if (fpo->fpo_map_count == 0) + if (!fpo->fpo_map_count) list_add(&fpo->fpo_list, zombies); else list_add(&fpo->fpo_list, &fps->fps_failed_pool_list); @@ -1484,7 +1484,7 @@ static int kiblnd_init_fmr_poolset(kib_fmr_poolset_t *fps, int cpt, INIT_LIST_HEAD(&fps->fps_failed_pool_list); rc = kiblnd_create_fmr_pool(fps, &fpo); - if (rc == 0) + if (!rc) list_add_tail(&fpo->fpo_list, &fps->fps_pool_list); return rc; @@ -1492,7 +1492,7 @@ static int kiblnd_init_fmr_poolset(kib_fmr_poolset_t *fps, int cpt, static int kiblnd_fmr_pool_is_idle(kib_fmr_pool_t *fpo, unsigned long now) { - if (fpo->fpo_map_count != 0) /* still in use */ + if (fpo->fpo_map_count) /* still in use */ return 0; if (fpo->fpo_failed) return 1; @@ -1509,11 +1509,11 @@ void kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status) int rc; rc = ib_fmr_pool_unmap(fmr->fmr_pfmr); - LASSERT(rc == 0); + LASSERT(!rc); - if (status != 0) { + if (status) { rc = ib_flush_fmr_pool(fpo->fpo_fmr_pool); - LASSERT(rc == 0); + LASSERT(!rc); } fmr->fmr_pool = NULL; @@ -1596,7 +1596,7 @@ int kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages, rc = kiblnd_create_fmr_pool(fps, &fpo); spin_lock(&fps->fps_lock); fps->fps_increasing = 0; - if (rc == 0) { + if (!rc) { fps->fps_version++; list_add_tail(&fpo->fpo_list, &fps->fps_pool_list); } else { @@ -1610,7 +1610,7 @@ int kiblnd_fmr_pool_map(kib_fmr_poolset_t *fps, __u64 *pages, int npages, static void kiblnd_fini_pool(kib_pool_t *pool) { LASSERT(list_empty(&pool->po_free_list)); - LASSERT(pool->po_allocated == 0); + LASSERT(!pool->po_allocated); CDEBUG(D_NET, "Finalize %s pool\n", pool->po_owner->ps_name); } @@ -1650,7 +1650,7 @@ static void kiblnd_fail_poolset(kib_poolset_t *ps, struct list_head *zombies) kib_pool_t, po_list); po->po_failed = 1; list_del(&po->po_list); - if (po->po_allocated == 0) + if (!po->po_allocated) list_add(&po->po_list, zombies); else list_add(&po->po_list, &ps->ps_failed_pool_list); @@ -1693,7 +1693,7 @@ static int kiblnd_init_poolset(kib_poolset_t *ps, int cpt, INIT_LIST_HEAD(&ps->ps_failed_pool_list); rc = ps->ps_pool_create(ps, size, &pool); - if (rc == 0) + if (!rc) list_add(&pool->po_list, &ps->ps_pool_list); else CERROR("Failed to create the first pool for %s\n", ps->ps_name); @@ -1703,7 +1703,7 @@ static int kiblnd_init_poolset(kib_poolset_t *ps, int cpt, static int kiblnd_pool_is_idle(kib_pool_t *pool, unsigned long now) { - if (pool->po_allocated != 0) /* still in use */ + if (pool->po_allocated) /* still in use */ return 0; if (pool->po_failed) return 1; @@ -1790,7 +1790,7 @@ struct list_head *kiblnd_pool_alloc_node(kib_poolset_t *ps) spin_lock(&ps->ps_lock); ps->ps_increasing = 0; - if (rc == 0) { + if (!rc) { list_add_tail(&pool->po_list, &ps->ps_pool_list); } else { ps->ps_next_retry = cfs_time_shift(IBLND_POOL_RETRY); @@ -1807,7 +1807,7 @@ static void kiblnd_destroy_tx_pool(kib_pool_t *pool) kib_tx_pool_t *tpo = container_of(pool, kib_tx_pool_t, tpo_pool); int i; - LASSERT(pool->po_allocated == 0); + LASSERT(!pool->po_allocated); if (tpo->tpo_tx_pages) { kiblnd_unmap_tx_pool(tpo); @@ -1877,7 +1877,7 @@ static int kiblnd_create_tx_pool(kib_poolset_t *ps, int size, tpo->tpo_tx_pages = NULL; npg = (size * IBLND_MSG_SIZE + PAGE_SIZE - 1) / PAGE_SIZE; - if (kiblnd_alloc_pages(&tpo->tpo_tx_pages, ps->ps_cpt, npg) != 0) { + if (kiblnd_alloc_pages(&tpo->tpo_tx_pages, ps->ps_cpt, npg)) { CERROR("Can't allocate tx pages: %d\n", npg); LIBCFS_FREE(tpo, sizeof(*tpo)); return -ENOMEM; @@ -1988,7 +1988,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) int i; read_lock_irqsave(&kiblnd_data.kib_global_lock, flags); - if (*kiblnd_tunables.kib_map_on_demand == 0 && + if (!*kiblnd_tunables.kib_map_on_demand && net->ibn_dev->ibd_hdev->ibh_nmrs == 1) { read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); goto create_tx_pool; @@ -2029,10 +2029,10 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) rc = kiblnd_init_fmr_poolset(net->ibn_fmr_ps[cpt], cpt, net, kiblnd_fmr_pool_size(ncpts), kiblnd_fmr_flush_trigger(ncpts)); - if (rc == -ENOSYS && i == 0) /* no FMR */ + if (rc == -ENOSYS && !i) /* no FMR */ break; - if (rc != 0) { /* a real error */ + if (rc) { /* a real error */ CERROR("Can't initialize FMR pool for CPT %d: %d\n", cpt, rc); goto failed; @@ -2067,7 +2067,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) kiblnd_create_tx_pool, kiblnd_destroy_tx_pool, kiblnd_tx_init, NULL); - if (rc != 0) { + if (rc) { CERROR("Can't initialize TX pool for CPT %d: %d\n", cpt, rc); goto failed; @@ -2077,7 +2077,7 @@ static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts) return 0; failed: kiblnd_net_fini_pools(net); - LASSERT(rc != 0); + LASSERT(rc); return rc; } @@ -2112,7 +2112,7 @@ static void kiblnd_hdev_cleanup_mrs(kib_hca_dev_t *hdev) { int i; - if (hdev->ibh_nmrs == 0 || !hdev->ibh_mrs) + if (!hdev->ibh_nmrs || !hdev->ibh_mrs) return; for (i = 0; i < hdev->ibh_nmrs; i++) { @@ -2147,7 +2147,7 @@ static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev) int acflags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE; rc = kiblnd_hdev_get_attr(hdev); - if (rc != 0) + if (rc) return rc; LIBCFS_ALLOC(hdev->ibh_mrs, 1 * sizeof(*hdev->ibh_mrs)); @@ -2218,7 +2218,7 @@ static int kiblnd_dev_need_failover(kib_dev_t *dev) dstaddr.sin_family = AF_INET; rc = rdma_resolve_addr(cmid, (struct sockaddr *)&srcaddr, (struct sockaddr *)&dstaddr, 1); - if (rc != 0 || !cmid->device) { + if (rc || !cmid->device) { CERROR("Failed to bind %s:%pI4h to device(%p): %d\n", dev->ibd_ifname, &dev->ibd_ifip, cmid->device, rc); @@ -2289,7 +2289,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) /* Bind to failover device or port */ rc = rdma_bind_addr(cmid, (struct sockaddr *)&addr); - if (rc != 0 || !cmid->device) { + if (rc || !cmid->device) { CERROR("Failed to bind %s:%pI4h to device(%p): %d\n", dev->ibd_ifname, &dev->ibd_ifip, cmid->device, rc); @@ -2320,13 +2320,13 @@ int kiblnd_dev_failover(kib_dev_t *dev) hdev->ibh_pd = pd; rc = rdma_listen(cmid, 0); - if (rc != 0) { + if (rc) { CERROR("Can't start new listener: %d\n", rc); goto out; } rc = kiblnd_hdev_setup_mrs(hdev); - if (rc != 0) { + if (rc) { CERROR("Can't setup device: %d\n", rc); goto out; } @@ -2357,7 +2357,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) if (hdev) kiblnd_hdev_decref(hdev); - if (rc != 0) + if (rc) dev->ibd_failed_failover++; else dev->ibd_failed_failover = 0; @@ -2367,7 +2367,7 @@ int kiblnd_dev_failover(kib_dev_t *dev) void kiblnd_destroy_dev(kib_dev_t *dev) { - LASSERT(dev->ibd_nnets == 0); + LASSERT(!dev->ibd_nnets); LASSERT(list_empty(&dev->ibd_nets)); list_del(&dev->ibd_fail_list); @@ -2389,7 +2389,7 @@ static kib_dev_t *kiblnd_create_dev(char *ifname) int rc; rc = lnet_ipif_query(ifname, &up, &ip, &netmask); - if (rc != 0) { + if (rc) { CERROR("Can't query IPoIB interface %s: %d\n", ifname, rc); return NULL; @@ -2420,7 +2420,7 @@ static kib_dev_t *kiblnd_create_dev(char *ifname) /* initialize the device */ rc = kiblnd_dev_failover(dev); - if (rc != 0) { + if (rc) { CERROR("Can't initialize device: %d\n", rc); LIBCFS_FREE(dev, sizeof(*dev)); return NULL; @@ -2464,7 +2464,7 @@ static void kiblnd_base_shutdown(void) wake_up_all(&kiblnd_data.kib_failover_waitq); i = 2; - while (atomic_read(&kiblnd_data.kib_nthreads) != 0) { + while (atomic_read(&kiblnd_data.kib_nthreads)) { i++; /* power of 2 ? */ CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, @@ -2519,7 +2519,7 @@ void kiblnd_shutdown(lnet_ni_t *ni) /* Wait for all peer state to clean up */ i = 2; - while (atomic_read(&net->ibn_npeers) != 0) { + while (atomic_read(&net->ibn_npeers)) { i++; CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, /* 2**n? */ "%s: waiting for %d peers to disconnect\n", @@ -2540,10 +2540,9 @@ void kiblnd_shutdown(lnet_ni_t *ni) /* fall through */ case IBLND_INIT_NOTHING: - LASSERT(atomic_read(&net->ibn_nconns) == 0); + LASSERT(!atomic_read(&net->ibn_nconns)); - if (net->ibn_dev && - net->ibn_dev->ibd_nnets == 0) + if (net->ibn_dev && !net->ibn_dev->ibd_nnets) kiblnd_destroy_dev(net->ibn_dev); break; @@ -2624,16 +2623,16 @@ static int kiblnd_base_startup(void) /*****************************************************/ rc = kiblnd_thread_start(kiblnd_connd, NULL, "kiblnd_connd"); - if (rc != 0) { + if (rc) { CERROR("Can't spawn o2iblnd connd: %d\n", rc); goto failed; } - if (*kiblnd_tunables.kib_dev_failover != 0) + if (*kiblnd_tunables.kib_dev_failover) rc = kiblnd_thread_start(kiblnd_failover_thread, NULL, "kiblnd_failover"); - if (rc != 0) { + if (rc) { CERROR("Can't spawn o2iblnd failover thread: %d\n", rc); goto failed; } @@ -2655,7 +2654,7 @@ static int kiblnd_start_schedulers(struct kib_sched_info *sched) int nthrs; int i; - if (sched->ibs_nthreads == 0) { + if (!sched->ibs_nthreads) { if (*kiblnd_tunables.kib_nscheds > 0) { nthrs = sched->ibs_nthreads_max; } else { @@ -2678,7 +2677,7 @@ static int kiblnd_start_schedulers(struct kib_sched_info *sched) snprintf(name, sizeof(name), "kiblnd_sd_%02ld_%02ld", KIB_THREAD_CPT(id), KIB_THREAD_TID(id)); rc = kiblnd_thread_start(kiblnd_scheduler, (void *)id, name); - if (rc == 0) + if (!rc) continue; CERROR("Can't spawn thread %d for scheduler[%d]: %d\n", @@ -2707,7 +2706,7 @@ static int kiblnd_dev_start_threads(kib_dev_t *dev, int newdev, __u32 *cpts, continue; rc = kiblnd_start_schedulers(kiblnd_data.kib_scheds[cpt]); - if (rc != 0) { + if (rc) { CERROR("Failed to start scheduler threads for %s\n", dev->ibd_ifname); return rc; @@ -2725,7 +2724,7 @@ static kib_dev_t *kiblnd_dev_search(char *ifname) colon = strchr(ifname, ':'); list_for_each_entry(dev, &kiblnd_data.kib_devs, ibd_list) { - if (strcmp(&dev->ibd_ifname[0], ifname) == 0) + if (!strcmp(&dev->ibd_ifname[0], ifname)) return dev; if (alias) @@ -2737,7 +2736,7 @@ static kib_dev_t *kiblnd_dev_search(char *ifname) if (colon2) *colon2 = 0; - if (strcmp(&dev->ibd_ifname[0], ifname) == 0) + if (!strcmp(&dev->ibd_ifname[0], ifname)) alias = dev; if (colon) @@ -2762,7 +2761,7 @@ int kiblnd_startup(lnet_ni_t *ni) if (kiblnd_data.kib_init == IBLND_INIT_NOTHING) { rc = kiblnd_base_startup(); - if (rc != 0) + if (rc) return rc; } @@ -2803,7 +2802,7 @@ int kiblnd_startup(lnet_ni_t *ni) newdev = !ibdev; /* hmm...create kib_dev even for alias */ - if (!ibdev || strcmp(&ibdev->ibd_ifname[0], ifname) != 0) + if (!ibdev || strcmp(&ibdev->ibd_ifname[0], ifname)) ibdev = kiblnd_create_dev(ifname); if (!ibdev) @@ -2814,11 +2813,11 @@ int kiblnd_startup(lnet_ni_t *ni) rc = kiblnd_dev_start_threads(ibdev, newdev, ni->ni_cpts, ni->ni_ncpts); - if (rc != 0) + if (rc) goto failed; rc = kiblnd_net_init_pools(net, ni->ni_cpts, ni->ni_ncpts); - if (rc != 0) { + if (rc) { CERROR("Failed to initialize NI pools: %d\n", rc); goto failed; } @@ -2861,7 +2860,7 @@ static int __init kiblnd_module_init(void) <= IBLND_MSG_SIZE); rc = kiblnd_tunables_init(); - if (rc != 0) + if (rc) return rc; lnet_register_lnd(&the_o2iblnd); diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h index 16c90ed5962e..2abb574269e9 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h @@ -148,7 +148,7 @@ kiblnd_concurrent_sends_v1(void) #define IBLND_MSG_SIZE (4 << 10) /* max size of queued messages (inc hdr) */ #define IBLND_MAX_RDMA_FRAGS LNET_MAX_IOV /* max # of fragments supported */ -#define IBLND_CFG_RDMA_FRAGS (*kiblnd_tunables.kib_map_on_demand != 0 ? \ +#define IBLND_CFG_RDMA_FRAGS (*kiblnd_tunables.kib_map_on_demand ? \ *kiblnd_tunables.kib_map_on_demand : \ IBLND_MAX_RDMA_FRAGS) /* max # of fragments configured by user */ #define IBLND_RDMA_FRAGS(v) ((v) == IBLND_MSG_VERSION_1 ? \ @@ -611,7 +611,7 @@ kiblnd_dev_can_failover(kib_dev_t *dev) if (!list_empty(&dev->ibd_fail_list)) /* already scheduled */ return 0; - if (*kiblnd_tunables.kib_dev_failover == 0) /* disabled */ + if (!*kiblnd_tunables.kib_dev_failover) /* disabled */ return 0; if (*kiblnd_tunables.kib_dev_failover > 1) /* force failover */ @@ -710,16 +710,16 @@ kiblnd_need_noop(kib_conn_t *conn) /* No tx to piggyback NOOP onto or no credit to send a tx */ return (list_empty(&conn->ibc_tx_queue) || - conn->ibc_credits == 0); + !conn->ibc_credits); } if (!list_empty(&conn->ibc_tx_noops) || /* NOOP already queued */ !list_empty(&conn->ibc_tx_queue_nocred) || /* piggyback NOOP */ - conn->ibc_credits == 0) /* no credit */ + !conn->ibc_credits) /* no credit */ return 0; if (conn->ibc_credits == 1 && /* last credit reserved for */ - conn->ibc_outstanding_credits == 0) /* giving back credits */ + !conn->ibc_outstanding_credits) /* giving back credits */ return 0; /* No tx to piggyback NOOP onto or no credit to send a tx */ @@ -765,8 +765,8 @@ kiblnd_ptr2wreqid(void *ptr, int type) { unsigned long lptr = (unsigned long)ptr; - LASSERT((lptr & IBLND_WID_MASK) == 0); - LASSERT((type & ~IBLND_WID_MASK) == 0); + LASSERT(!(lptr & IBLND_WID_MASK)); + LASSERT(!(type & ~IBLND_WID_MASK)); return (__u64)(lptr | type); } diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c index 674a4eea3870..06084315fdd1 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -53,7 +53,7 @@ kiblnd_tx_done(lnet_ni_t *ni, kib_tx_t *tx) LASSERT(net); LASSERT(!in_interrupt()); LASSERT(!tx->tx_queued); /* mustn't be queued for sending */ - LASSERT(tx->tx_sending == 0); /* mustn't be awaiting sent callback */ + LASSERT(!tx->tx_sending); /* mustn't be awaiting sent callback */ LASSERT(!tx->tx_waiting); /* mustn't be awaiting peer response */ LASSERT(tx->tx_pool); @@ -115,15 +115,15 @@ kiblnd_get_idle_tx(lnet_ni_t *ni, lnet_nid_t target) return NULL; tx = container_of(node, kib_tx_t, tx_list); - LASSERT(tx->tx_nwrq == 0); + LASSERT(!tx->tx_nwrq); LASSERT(!tx->tx_queued); - LASSERT(tx->tx_sending == 0); + LASSERT(!tx->tx_sending); LASSERT(!tx->tx_waiting); - LASSERT(tx->tx_status == 0); + LASSERT(!tx->tx_status); LASSERT(!tx->tx_conn); LASSERT(!tx->tx_lntmsg[0]); LASSERT(!tx->tx_lntmsg[1]); - LASSERT(tx->tx_nfrags == 0); + LASSERT(!tx->tx_nfrags); return tx; } @@ -185,7 +185,7 @@ kiblnd_post_rx(kib_rx_t *rx, int credit) */ kiblnd_conn_addref(conn); rc = ib_post_recv(conn->ibc_cmid->qp, &rx->rx_wrq, &bad_wrq); - if (unlikely(rc != 0)) { + if (unlikely(rc)) { CERROR("Can't post rx for %s: %d, bad_wrq: %p\n", libcfs_nid2str(conn->ibc_peer->ibp_nid), rc, bad_wrq); rx->rx_nob = 0; @@ -194,7 +194,7 @@ kiblnd_post_rx(kib_rx_t *rx, int credit) if (conn->ibc_state < IBLND_CONN_ESTABLISHED) /* Initial post */ goto out; - if (unlikely(rc != 0)) { + if (unlikely(rc)) { kiblnd_close_conn(conn, rc); kiblnd_drop_rx(rx); /* No more posts for this rx */ goto out; @@ -225,7 +225,7 @@ kiblnd_find_waiting_tx_locked(kib_conn_t *conn, int txtype, __u64 cookie) kib_tx_t *tx = list_entry(tmp, kib_tx_t, tx_list); LASSERT(!tx->tx_queued); - LASSERT(tx->tx_sending != 0 || tx->tx_waiting); + LASSERT(tx->tx_sending || tx->tx_waiting); if (tx->tx_cookie != cookie) continue; @@ -260,7 +260,7 @@ kiblnd_handle_completion(kib_conn_t *conn, int txtype, int status, __u64 cookie) return; } - if (tx->tx_status == 0) { /* success so far */ + if (!tx->tx_status) { /* success so far */ if (status < 0) /* failed? */ tx->tx_status = status; else if (txtype == IBLND_MSG_GET_REQ) @@ -269,7 +269,7 @@ kiblnd_handle_completion(kib_conn_t *conn, int txtype, int status, __u64 cookie) tx->tx_waiting = 0; - idle = !tx->tx_queued && (tx->tx_sending == 0); + idle = !tx->tx_queued && !tx->tx_sending; if (idle) list_del(&tx->tx_list); @@ -316,7 +316,7 @@ kiblnd_handle_rx(kib_rx_t *rx) msg->ibm_type, credits, libcfs_nid2str(conn->ibc_peer->ibp_nid)); - if (credits != 0) { + if (credits) { /* Have I received credits that will let me send? */ spin_lock(&conn->ibc_lock); @@ -360,7 +360,7 @@ kiblnd_handle_rx(kib_rx_t *rx) break; } - if (credits != 0) /* credit already posted */ + if (credits) /* credit already posted */ post_credit = IBLND_POSTRX_NO_CREDIT; else /* a keepalive NOOP */ post_credit = IBLND_POSTRX_PEER_CREDIT; @@ -487,7 +487,7 @@ kiblnd_rx_complete(kib_rx_t *rx, int status, int nob) rx->rx_nob = nob; rc = kiblnd_unpack_msg(msg, rx->rx_nob); - if (rc != 0) { + if (rc) { CERROR("Error %d unpacking rx from %s\n", rc, libcfs_nid2str(conn->ibc_peer->ibp_nid)); goto failed; @@ -583,7 +583,7 @@ kiblnd_fmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob) fps = net->ibn_fmr_ps[cpt]; rc = kiblnd_fmr_pool_map(fps, pages, npages, 0, &tx->fmr); - if (rc != 0) { + if (rc) { CERROR("Can't map %d pages: %d\n", npages, rc); return rc; } @@ -612,7 +612,7 @@ static void kiblnd_unmap_tx(lnet_ni_t *ni, kib_tx_t *tx) tx->fmr.fmr_pfmr = NULL; } - if (tx->tx_nfrags != 0) { + if (tx->tx_nfrags) { kiblnd_dma_unmap_sg(tx->tx_pool->tpo_hdev->ibh_ibdev, tx->tx_frags, tx->tx_nfrags, tx->tx_dmadir); tx->tx_nfrags = 0; @@ -769,7 +769,7 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) LASSERT(tx->tx_nwrq > 0); LASSERT(tx->tx_nwrq <= 1 + IBLND_RDMA_FRAGS(ver)); - LASSERT(credit == 0 || credit == 1); + LASSERT(!credit || credit == 1); LASSERT(conn->ibc_outstanding_credits >= 0); LASSERT(conn->ibc_outstanding_credits <= IBLND_MSG_QUEUE_SIZE(ver)); LASSERT(conn->ibc_credits >= 0); @@ -782,13 +782,13 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) return -EAGAIN; } - if (credit != 0 && conn->ibc_credits == 0) { /* no credits */ + if (credit && !conn->ibc_credits) { /* no credits */ CDEBUG(D_NET, "%s: no credits\n", libcfs_nid2str(peer->ibp_nid)); return -EAGAIN; } - if (credit != 0 && !IBLND_OOB_CAPABLE(ver) && + if (credit && !IBLND_OOB_CAPABLE(ver) && conn->ibc_credits == 1 && /* last credit reserved */ msg->ibm_type != IBLND_MSG_NOOP) { /* for NOOP */ CDEBUG(D_NET, "%s: not using last credit\n", @@ -851,7 +851,7 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) conn->ibc_last_send = jiffies; - if (rc == 0) + if (!rc) return 0; /* @@ -868,7 +868,7 @@ kiblnd_post_tx_locked(kib_conn_t *conn, kib_tx_t *tx, int credit) tx->tx_waiting = 0; tx->tx_sending--; - done = (tx->tx_sending == 0); + done = !tx->tx_sending; if (done) list_del(&tx->tx_list); @@ -955,7 +955,7 @@ kiblnd_check_sends(kib_conn_t *conn) break; } - if (kiblnd_post_tx_locked(conn, tx, credit) != 0) + if (kiblnd_post_tx_locked(conn, tx, credit)) break; } @@ -1001,7 +1001,7 @@ kiblnd_tx_complete(kib_tx_t *tx, int status) tx->tx_status = -EIO; } - idle = (tx->tx_sending == 0) && /* This is the final callback */ + idle = !tx->tx_sending && /* This is the final callback */ !tx->tx_waiting && /* Not waiting for peer */ !tx->tx_queued; /* Not re-queued (PUT_DONE) */ if (idle) @@ -1067,7 +1067,7 @@ kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type, int wrknob; LASSERT(!in_interrupt()); - LASSERT(tx->tx_nwrq == 0); + LASSERT(!tx->tx_nwrq); LASSERT(type == IBLND_MSG_GET_DONE || type == IBLND_MSG_PUT_DONE); @@ -1210,7 +1210,7 @@ static int kiblnd_resolve_addr(struct rdma_cm_id *cmid, /* allow the port to be reused */ rc = rdma_set_reuseaddr(cmid, 1); - if (rc != 0) { + if (rc) { CERROR("Unable to set reuse on cmid: %d\n", rc); return rc; } @@ -1222,7 +1222,7 @@ static int kiblnd_resolve_addr(struct rdma_cm_id *cmid, (struct sockaddr *)srcaddr, (struct sockaddr *)dstaddr, timeout_ms); - if (rc == 0) { + if (!rc) { CDEBUG(D_NET, "bound to port %hu\n", port); return 0; } else if (rc == -EADDRINUSE || rc == -EADDRNOTAVAIL) { @@ -1281,7 +1281,7 @@ kiblnd_connect_peer(kib_peer_t *peer) (struct sockaddr *)&dstaddr, *kiblnd_tunables.kib_timeout * 1000); } - if (rc != 0) { + if (rc) { /* Can't initiate address resolution: */ CERROR("Can't resolve addr for %s: %d\n", libcfs_nid2str(peer->ibp_nid), rc); @@ -1347,8 +1347,8 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) if (peer) { if (list_empty(&peer->ibp_conns)) { /* found a peer, but it's still connecting... */ - LASSERT(peer->ibp_connecting != 0 || - peer->ibp_accepting != 0); + LASSERT(peer->ibp_connecting || + peer->ibp_accepting); if (tx) list_add_tail(&tx->tx_list, &peer->ibp_tx_queue); @@ -1370,7 +1370,7 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) /* Allocate a peer ready to add to the peer table and retry */ rc = kiblnd_create_peer(ni, &peer, nid); - if (rc != 0) { + if (rc) { CERROR("Can't create peer %s\n", libcfs_nid2str(nid)); if (tx) { tx->tx_status = -EHOSTUNREACH; @@ -1386,8 +1386,8 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) if (peer2) { if (list_empty(&peer2->ibp_conns)) { /* found a peer, but it's still connecting... */ - LASSERT(peer2->ibp_connecting != 0 || - peer2->ibp_accepting != 0); + LASSERT(peer2->ibp_connecting || + peer2->ibp_accepting); if (tx) list_add_tail(&tx->tx_list, &peer2->ibp_tx_queue); @@ -1408,11 +1408,11 @@ kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid) } /* Brand new peer */ - LASSERT(peer->ibp_connecting == 0); + LASSERT(!peer->ibp_connecting); peer->ibp_connecting = 1; /* always called with a ref on ni, which prevents ni being shutdown */ - LASSERT(((kib_net_t *)ni->ni_data)->ibn_shutdown == 0); + LASSERT(!((kib_net_t *)ni->ni_data)->ibn_shutdown); if (tx) list_add_tail(&tx->tx_list, &peer->ibp_tx_queue); @@ -1450,7 +1450,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) CDEBUG(D_NET, "sending %d bytes in %d frags to %s\n", payload_nob, payload_niov, libcfs_id2str(target)); - LASSERT(payload_nob == 0 || payload_niov > 0); + LASSERT(!payload_nob || payload_niov > 0); LASSERT(payload_niov <= LNET_MAX_IOV); /* Thread context */ @@ -1464,7 +1464,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) return -EIO; case LNET_MSG_ACK: - LASSERT(payload_nob == 0); + LASSERT(!payload_nob); break; case LNET_MSG_GET: @@ -1485,7 +1485,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) ibmsg = tx->tx_msg; rd = &ibmsg->ibm_u.get.ibgm_rd; - if ((lntmsg->msg_md->md_options & LNET_MD_KIOV) == 0) + if (!(lntmsg->msg_md->md_options & LNET_MD_KIOV)) rc = kiblnd_setup_rd_iov(ni, tx, rd, lntmsg->msg_md->md_niov, lntmsg->msg_md->md_iov.iov, @@ -1495,7 +1495,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) lntmsg->msg_md->md_niov, lntmsg->msg_md->md_iov.kiov, 0, lntmsg->msg_md->md_length); - if (rc != 0) { + if (rc) { CERROR("Can't setup GET sink for %s: %d\n", libcfs_nid2str(target.nid), rc); kiblnd_tx_done(ni, tx); @@ -1544,7 +1544,7 @@ kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) rc = kiblnd_setup_rd_kiov(ni, tx, tx->tx_rd, payload_niov, payload_kiov, payload_offset, payload_nob); - if (rc != 0) { + if (rc) { CERROR("Can't setup PUT src for %s: %d\n", libcfs_nid2str(target.nid), rc); kiblnd_tx_done(ni, tx); @@ -1615,7 +1615,7 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) goto failed_0; } - if (nob == 0) + if (!nob) rc = 0; else if (!kiov) rc = kiblnd_setup_rd_iov(ni, tx, tx->tx_rd, @@ -1624,7 +1624,7 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) rc = kiblnd_setup_rd_kiov(ni, tx, tx->tx_rd, niov, kiov, offset, nob); - if (rc != 0) { + if (rc) { CERROR("Can't setup GET src for %s: %d\n", libcfs_nid2str(target.nid), rc); goto failed_1; @@ -1640,7 +1640,7 @@ kiblnd_reply(lnet_ni_t *ni, kib_rx_t *rx, lnet_msg_t *lntmsg) goto failed_1; } - if (nob == 0) { + if (!nob) { /* No RDMA: local completion may happen now! */ lnet_finalize(ni, lntmsg, 0); } else { @@ -1706,7 +1706,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, kib_msg_t *txmsg; kib_rdma_desc_t *rd; - if (mlen == 0) { + if (!mlen) { lnet_finalize(ni, lntmsg, 0); kiblnd_send_completion(rx->rx_conn, IBLND_MSG_PUT_NAK, 0, rxmsg->ibm_u.putreq.ibprm_cookie); @@ -1730,7 +1730,7 @@ kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, else rc = kiblnd_setup_rd_kiov(ni, tx, rd, niov, kiov, offset, mlen); - if (rc != 0) { + if (rc) { CERROR("Can't setup PUT sink for %s: %d\n", libcfs_nid2str(conn->ibc_peer->ibp_nid), rc); kiblnd_tx_done(ni, tx); @@ -1808,9 +1808,9 @@ kiblnd_peer_notify(kib_peer_t *peer) read_lock_irqsave(&kiblnd_data.kib_global_lock, flags); if (list_empty(&peer->ibp_conns) && - peer->ibp_accepting == 0 && - peer->ibp_connecting == 0 && - peer->ibp_error != 0) { + !peer->ibp_accepting && + !peer->ibp_connecting && + peer->ibp_error) { error = peer->ibp_error; peer->ibp_error = 0; @@ -1819,7 +1819,7 @@ kiblnd_peer_notify(kib_peer_t *peer) read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); - if (error != 0) + if (error) lnet_notify(peer->ibp_ni, peer->ibp_nid, 0, last_alive); } @@ -1839,15 +1839,15 @@ kiblnd_close_conn_locked(kib_conn_t *conn, int error) kib_dev_t *dev; unsigned long flags; - LASSERT(error != 0 || conn->ibc_state >= IBLND_CONN_ESTABLISHED); + LASSERT(error || conn->ibc_state >= IBLND_CONN_ESTABLISHED); - if (error != 0 && conn->ibc_comms_error == 0) + if (error && !conn->ibc_comms_error) conn->ibc_comms_error = error; if (conn->ibc_state != IBLND_CONN_ESTABLISHED) return; /* already being handled */ - if (error == 0 && + if (!error && list_empty(&conn->ibc_tx_noops) && list_empty(&conn->ibc_tx_queue) && list_empty(&conn->ibc_tx_queue_rsrvd) && @@ -1879,7 +1879,7 @@ kiblnd_close_conn_locked(kib_conn_t *conn, int error) kiblnd_set_conn_state(conn, IBLND_CONN_CLOSING); - if (error != 0 && + if (error && kiblnd_dev_can_failover(dev)) { list_add_tail(&dev->ibd_fail_list, &kiblnd_data.kib_failed_devs); @@ -1943,7 +1943,7 @@ kiblnd_abort_txs(kib_conn_t *conn, struct list_head *txs) if (txs == &conn->ibc_active_txs) { LASSERT(!tx->tx_queued); - LASSERT(tx->tx_waiting || tx->tx_sending != 0); + LASSERT(tx->tx_waiting || tx->tx_sending); } else { LASSERT(tx->tx_queued); } @@ -1951,7 +1951,7 @@ kiblnd_abort_txs(kib_conn_t *conn, struct list_head *txs) tx->tx_status = -ECONNABORTED; tx->tx_waiting = 0; - if (tx->tx_sending == 0) { + if (!tx->tx_sending) { tx->tx_queued = 0; list_del(&tx->tx_list); list_add(&tx->tx_list, &zombies); @@ -1997,7 +1997,7 @@ kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error) LIST_HEAD(zombies); unsigned long flags; - LASSERT(error != 0); + LASSERT(error); LASSERT(!in_interrupt()); write_lock_irqsave(&kiblnd_data.kib_global_lock, flags); @@ -2010,8 +2010,8 @@ kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error) peer->ibp_accepting--; } - if (peer->ibp_connecting != 0 || - peer->ibp_accepting != 0) { + if (peer->ibp_connecting || + peer->ibp_accepting) { /* another connection attempt under way... */ write_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); @@ -2070,7 +2070,7 @@ kiblnd_connreq_done(kib_conn_t *conn, int status) LIBCFS_FREE(conn->ibc_connvars, sizeof(*conn->ibc_connvars)); conn->ibc_connvars = NULL; - if (status != 0) { + if (status) { /* failed to establish connection */ kiblnd_peer_connect_failed(peer, active, status); kiblnd_finalise_conn(conn); @@ -2095,7 +2095,7 @@ kiblnd_connreq_done(kib_conn_t *conn, int status) else peer->ibp_accepting--; - if (peer->ibp_version == 0) { + if (!peer->ibp_version) { peer->ibp_version = conn->ibc_version; peer->ibp_incarnation = conn->ibc_incarnation; } @@ -2113,7 +2113,7 @@ kiblnd_connreq_done(kib_conn_t *conn, int status) list_del_init(&peer->ibp_tx_queue); if (!kiblnd_peer_active(peer) || /* peer has been deleted */ - conn->ibc_comms_error != 0) { /* error has happened already */ + conn->ibc_comms_error) { /* error has happened already */ lnet_ni_t *ni = peer->ibp_ni; /* start to shut down connection */ @@ -2149,7 +2149,7 @@ kiblnd_reject(struct rdma_cm_id *cmid, kib_rej_t *rej) rc = rdma_reject(cmid, rej, sizeof(*rej)); - if (rc != 0) + if (rc) CWARN("Error %d sending reject\n", rc); } @@ -2220,7 +2220,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) goto failed; rc = kiblnd_unpack_msg(reqmsg, priv_nob); - if (rc != 0) { + if (rc) { CERROR("Can't parse connection request: %d\n", rc); goto failed; } @@ -2247,7 +2247,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) } /* check time stamp as soon as possible */ - if (reqmsg->ibm_dststamp != 0 && + if (reqmsg->ibm_dststamp && reqmsg->ibm_dststamp != net->ibn_incarnation) { CWARN("Stale connection request\n"); rej.ibr_why = IBLND_REJECT_CONN_STALE; @@ -2298,7 +2298,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) /* assume 'nid' is a new peer; create */ rc = kiblnd_create_peer(ni, &peer, nid); - if (rc != 0) { + if (rc) { CERROR("Can't create peer for %s\n", libcfs_nid2str(nid)); rej.ibr_why = IBLND_REJECT_NO_RESOURCES; goto failed; @@ -2308,7 +2308,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) peer2 = kiblnd_find_peer_locked(nid); if (peer2) { - if (peer2->ibp_version == 0) { + if (!peer2->ibp_version) { peer2->ibp_version = version; peer2->ibp_incarnation = reqmsg->ibm_srcstamp; } @@ -2328,7 +2328,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) } /* tie-break connection race in favour of the higher NID */ - if (peer2->ibp_connecting != 0 && + if (peer2->ibp_connecting && nid < ni->ni_nid) { write_unlock_irqrestore(g_lock, flags); @@ -2347,16 +2347,16 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) peer = peer2; } else { /* Brand new peer */ - LASSERT(peer->ibp_accepting == 0); - LASSERT(peer->ibp_version == 0 && - peer->ibp_incarnation == 0); + LASSERT(!peer->ibp_accepting); + LASSERT(!peer->ibp_version && + !peer->ibp_incarnation); peer->ibp_accepting = 1; peer->ibp_version = version; peer->ibp_incarnation = reqmsg->ibm_srcstamp; /* I have a ref on ni that prevents it being shutdown */ - LASSERT(net->ibn_shutdown == 0); + LASSERT(!net->ibn_shutdown); kiblnd_peer_addref(peer); list_add_tail(&peer->ibp_list, kiblnd_nid2peerlist(nid)); @@ -2405,7 +2405,7 @@ kiblnd_passive_connect(struct rdma_cm_id *cmid, void *priv, int priv_nob) CDEBUG(D_NET, "Accept %s\n", libcfs_nid2str(nid)); rc = rdma_accept(cmid, &cp); - if (rc != 0) { + if (rc) { CERROR("Can't accept %s: %d\n", libcfs_nid2str(nid), rc); rej.ibr_version = version; rej.ibr_why = IBLND_REJECT_FATAL; @@ -2454,7 +2454,7 @@ kiblnd_reconnect(kib_conn_t *conn, int version, if ((!list_empty(&peer->ibp_tx_queue) || peer->ibp_version != version) && peer->ibp_connecting == 1 && - peer->ibp_accepting == 0) { + !peer->ibp_accepting) { retry = 1; peer->ibp_connecting++; @@ -2649,7 +2649,7 @@ kiblnd_check_connreply(kib_conn_t *conn, void *priv, int priv_nob) LASSERT(net); - if (rc != 0) { + if (rc) { CERROR("Can't unpack connack from %s: %d\n", libcfs_nid2str(peer->ibp_nid), rc); goto failed; @@ -2706,7 +2706,7 @@ kiblnd_check_connreply(kib_conn_t *conn, void *priv, int priv_nob) rc = -ESTALE; read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); - if (rc != 0) { + if (rc) { CERROR("Bad connection reply from %s, rc = %d, version: %x max_frags: %d\n", libcfs_nid2str(peer->ibp_nid), rc, msg->ibm_version, msg->ibm_u.connparams.ibcp_max_frags); @@ -2729,7 +2729,7 @@ kiblnd_check_connreply(kib_conn_t *conn, void *priv, int priv_nob) * kiblnd_connreq_done(0) moves the conn state to ESTABLISHED, but then * immediately tears it down. */ - LASSERT(rc != 0); + LASSERT(rc); conn->ibc_comms_error = rc; kiblnd_connreq_done(conn, 0); } @@ -2749,8 +2749,8 @@ kiblnd_active_connect(struct rdma_cm_id *cmid) read_lock_irqsave(&kiblnd_data.kib_global_lock, flags); incarnation = peer->ibp_incarnation; - version = (peer->ibp_version == 0) ? IBLND_MSG_VERSION : - peer->ibp_version; + version = !peer->ibp_version ? IBLND_MSG_VERSION : + peer->ibp_version; read_unlock_irqrestore(&kiblnd_data.kib_global_lock, flags); @@ -2790,7 +2790,7 @@ kiblnd_active_connect(struct rdma_cm_id *cmid) LASSERT(conn->ibc_cmid == cmid); rc = rdma_connect(cmid, &cp); - if (rc != 0) { + if (rc) { CERROR("Can't connect to %s: %d\n", libcfs_nid2str(peer->ibp_nid), rc); kiblnd_connreq_done(conn, rc); @@ -2827,7 +2827,7 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) libcfs_nid2str(peer->ibp_nid), event->status); kiblnd_peer_connect_failed(peer, 1, -EHOSTUNREACH); kiblnd_peer_decref(peer); - return -EHOSTUNREACH; /* rc != 0 destroys cmid */ + return -EHOSTUNREACH; /* rc destroys cmid */ case RDMA_CM_EVENT_ADDR_RESOLVED: peer = (kib_peer_t *)cmid->context; @@ -2835,14 +2835,14 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) CDEBUG(D_NET, "%s Addr resolved: %d\n", libcfs_nid2str(peer->ibp_nid), event->status); - if (event->status != 0) { + if (event->status) { CNETERR("Can't resolve address for %s: %d\n", libcfs_nid2str(peer->ibp_nid), event->status); rc = event->status; } else { rc = rdma_resolve_route( cmid, *kiblnd_tunables.kib_timeout * 1000); - if (rc == 0) + if (!rc) return 0; /* Can't initiate route resolution */ CERROR("Can't resolve route for %s: %d\n", @@ -2850,7 +2850,7 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) } kiblnd_peer_connect_failed(peer, 1, rc); kiblnd_peer_decref(peer); - return rc; /* rc != 0 destroys cmid */ + return rc; /* rc destroys cmid */ case RDMA_CM_EVENT_ROUTE_ERROR: peer = (kib_peer_t *)cmid->context; @@ -2858,21 +2858,21 @@ kiblnd_cm_callback(struct rdma_cm_id *cmid, struct rdma_cm_event *event) libcfs_nid2str(peer->ibp_nid), event->status); kiblnd_peer_connect_failed(peer, 1, -EHOSTUNREACH); kiblnd_peer_decref(peer); - return -EHOSTUNREACH; /* rc != 0 destroys cmid */ + return -EHOSTUNREACH; /* rc destroys cmid */ case RDMA_CM_EVENT_ROUTE_RESOLVED: peer = (kib_peer_t *)cmid->context; CDEBUG(D_NET, "%s Route resolved: %d\n", libcfs_nid2str(peer->ibp_nid), event->status); - if (event->status == 0) + if (!event->status) return kiblnd_active_connect(cmid); CNETERR("Can't resolve route for %s: %d\n", libcfs_nid2str(peer->ibp_nid), event->status); kiblnd_peer_connect_failed(peer, 1, event->status); kiblnd_peer_decref(peer); - return event->status; /* rc != 0 destroys cmid */ + return event->status; /* rc destroys cmid */ case RDMA_CM_EVENT_UNREACHABLE: conn = (kib_conn_t *)cmid->context; @@ -2984,7 +2984,7 @@ kiblnd_check_txs_locked(kib_conn_t *conn, struct list_head *txs) LASSERT(tx->tx_queued); } else { LASSERT(!tx->tx_queued); - LASSERT(tx->tx_waiting || tx->tx_sending != 0); + LASSERT(tx->tx_waiting || tx->tx_sending); } if (cfs_time_aftereq(jiffies, tx->tx_deadline)) { @@ -3179,7 +3179,7 @@ kiblnd_connd(void *arg) if (*kiblnd_tunables.kib_timeout > n * p) chunk = (chunk * n * p) / *kiblnd_tunables.kib_timeout; - if (chunk == 0) + if (!chunk) chunk = 1; for (i = 0; i < chunk; i++) { @@ -3268,7 +3268,7 @@ kiblnd_cq_completion(struct ib_cq *cq, void *arg) * NB I'm not allowed to schedule this conn once its refcount has * reached 0. Since fundamentally I'm racing with scheduler threads * consuming my CQ I could be called after all completions have - * occurred. But in this case, ibc_nrx == 0 && ibc_nsends_posted == 0 + * occurred. But in this case, !ibc_nrx && !ibc_nsends_posted * and this CQ is about to be destroyed so I NOOP. */ kib_conn_t *conn = arg; @@ -3324,7 +3324,7 @@ kiblnd_scheduler(void *arg) sched = kiblnd_data.kib_scheds[KIB_THREAD_CPT(id)]; rc = cfs_cpt_bind(lnet_cpt_table(), sched->ibs_cpt); - if (rc != 0) { + if (rc) { CWARN("Failed to bind on CPT %d, please verify whether all CPUs are healthy and reload modules if necessary, otherwise your system might under risk of low performance\n", sched->ibs_cpt); } @@ -3354,7 +3354,7 @@ kiblnd_scheduler(void *arg) spin_unlock_irqrestore(&sched->ibs_lock, flags); rc = ib_poll_cq(conn->ibc_cq, 1, &wc); - if (rc == 0) { + if (!rc) { rc = ib_req_notify_cq(conn->ibc_cq, IB_CQ_NEXT_COMP); if (rc < 0) { @@ -3382,7 +3382,7 @@ kiblnd_scheduler(void *arg) spin_lock_irqsave(&sched->ibs_lock, flags); - if (rc != 0 || conn->ibc_ready) { + if (rc || conn->ibc_ready) { /* * There may be another completion waiting; get * another scheduler to check while I handle @@ -3398,7 +3398,7 @@ kiblnd_scheduler(void *arg) conn->ibc_scheduled = 0; } - if (rc != 0) { + if (rc) { spin_unlock_irqrestore(&sched->ibs_lock, flags); kiblnd_complete(&wc); @@ -3438,7 +3438,7 @@ kiblnd_failover_thread(void *arg) unsigned long flags; int rc; - LASSERT(*kiblnd_tunables.kib_dev_failover != 0); + LASSERT(*kiblnd_tunables.kib_dev_failover); cfs_block_allsigs(); @@ -3497,7 +3497,7 @@ kiblnd_failover_thread(void *arg) remove_wait_queue(&kiblnd_data.kib_failover_waitq, &wait); write_lock_irqsave(glock, flags); - if (!long_sleep || rc != 0) + if (!long_sleep || rc) continue; /* diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c index afbd6d1df31d..b4607dad3712 100644 --- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c +++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c @@ -202,7 +202,7 @@ kiblnd_tunables_init(void) if (*kiblnd_tunables.kib_map_on_demand == 1) *kiblnd_tunables.kib_map_on_demand = 2; /* don't make sense to create map if only one fragment */ - if (*kiblnd_tunables.kib_concurrent_sends == 0) { + if (!*kiblnd_tunables.kib_concurrent_sends) { if (*kiblnd_tunables.kib_map_on_demand > 0 && *kiblnd_tunables.kib_map_on_demand <= IBLND_MAX_RDMA_FRAGS / 8) *kiblnd_tunables.kib_concurrent_sends = (*kiblnd_tunables.kib_peertxcredits) * 2; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c index 2c2d1c921f6c..49d716d6e983 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c @@ -91,7 +91,7 @@ ksocknal_create_route(__u32 ipaddr, int port) void ksocknal_destroy_route(ksock_route_t *route) { - LASSERT(atomic_read(&route->ksnr_refcount) == 0); + LASSERT(!atomic_read(&route->ksnr_refcount)); if (route->ksnr_peer) ksocknal_peer_decref(route->ksnr_peer); @@ -154,8 +154,8 @@ ksocknal_destroy_peer(ksock_peer_t *peer) CDEBUG(D_NET, "peer %s %p deleted\n", libcfs_id2str(peer->ksnp_id), peer); - LASSERT(atomic_read(&peer->ksnp_refcount) == 0); - LASSERT(peer->ksnp_accepting == 0); + LASSERT(!atomic_read(&peer->ksnp_refcount)); + LASSERT(!peer->ksnp_accepting); LASSERT(list_empty(&peer->ksnp_conns)); LASSERT(list_empty(&peer->ksnp_routes)); LASSERT(list_empty(&peer->ksnp_tx_queue)); @@ -269,7 +269,7 @@ ksocknal_get_peer_info(lnet_ni_t *ni, int index, if (peer->ksnp_ni != ni) continue; - if (peer->ksnp_n_passive_ips == 0 && + if (!peer->ksnp_n_passive_ips && list_empty(&peer->ksnp_routes)) { if (index-- > 0) continue; @@ -332,7 +332,7 @@ ksocknal_associate_route_conn_locked(ksock_route_t *route, ksock_conn_t *conn) ksocknal_route_addref(route); if (route->ksnr_myipaddr != conn->ksnc_myipaddr) { - if (route->ksnr_myipaddr == 0) { + if (!route->ksnr_myipaddr) { /* route wasn't bound locally yet (the initial route) */ CDEBUG(D_NET, "Binding %s %pI4h to %pI4h\n", libcfs_id2str(peer->ksnp_id), @@ -378,7 +378,7 @@ ksocknal_add_route_locked(ksock_peer_t *peer, ksock_route_t *route) LASSERT(!route->ksnr_peer); LASSERT(!route->ksnr_scheduled); LASSERT(!route->ksnr_connecting); - LASSERT(route->ksnr_connected == 0); + LASSERT(!route->ksnr_connected); /* LASSERT(unique) */ list_for_each(tmp, &peer->ksnp_routes) { @@ -429,7 +429,7 @@ ksocknal_del_route_locked(ksock_route_t *route) ksocknal_close_conn_locked(conn, 0); } - if (route->ksnr_myipaddr != 0) { + if (route->ksnr_myipaddr) { iface = ksocknal_ip2iface(route->ksnr_peer->ksnp_ni, route->ksnr_myipaddr); if (iface) @@ -466,7 +466,7 @@ ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port) /* Have a brand new peer ready... */ rc = ksocknal_create_peer(&peer, ni, id); - if (rc != 0) + if (rc) return rc; route = ksocknal_create_route(ipaddr, port); @@ -478,7 +478,7 @@ ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ipaddr, int port) write_lock_bh(&ksocknal_data.ksnd_global_lock); /* always called with a ref on ni, so shutdown can't have started */ - LASSERT(((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0); + LASSERT(!((ksock_net_t *) ni->ni_data)->ksnn_shutdown); peer2 = ksocknal_find_peer_locked(ni, id); if (peer2) { @@ -530,7 +530,7 @@ ksocknal_del_peer_locked(ksock_peer_t *peer, __u32 ip) route = list_entry(tmp, ksock_route_t, ksnr_list); /* no match */ - if (!(ip == 0 || route->ksnr_ipaddr == ip)) + if (!(!ip || route->ksnr_ipaddr == ip)) continue; route->ksnr_share_count = 0; @@ -544,7 +544,7 @@ ksocknal_del_peer_locked(ksock_peer_t *peer, __u32 ip) nshared += route->ksnr_share_count; } - if (nshared == 0) { + if (!nshared) { /* * remove everything else if there are no explicit entries * left @@ -553,7 +553,7 @@ ksocknal_del_peer_locked(ksock_peer_t *peer, __u32 ip) route = list_entry(tmp, ksock_route_t, ksnr_list); /* we should only be removing auto-entries */ - LASSERT(route->ksnr_share_count == 0); + LASSERT(!route->ksnr_share_count); ksocknal_del_route_locked(route); } @@ -710,7 +710,7 @@ ksocknal_local_ipvec(lnet_ni_t *ni, __u32 *ipaddrs) for (i = 0; i < nip; i++) { ipaddrs[i] = net->ksnn_interfaces[i].ksni_ipaddr; - LASSERT(ipaddrs[i] != 0); + LASSERT(ipaddrs[i]); } read_unlock(&ksocknal_data.ksnd_global_lock); @@ -728,11 +728,11 @@ ksocknal_match_peerip(ksock_interface_t *iface, __u32 *ips, int nips) int i; for (i = 0; i < nips; i++) { - if (ips[i] == 0) + if (!ips[i]) continue; this_xor = ips[i] ^ iface->ksni_ipaddr; - this_netmatch = ((this_xor & iface->ksni_netmask) == 0) ? 1 : 0; + this_netmatch = !(this_xor & iface->ksni_netmask) ? 1 : 0; if (!(best < 0 || best_netmatch < this_netmatch || @@ -824,7 +824,7 @@ ksocknal_select_ips(ksock_peer_t *peer, __u32 *peerips, int n_peerips) k = ksocknal_match_peerip(iface, peerips, n_peerips); xor = ip ^ peerips[k]; - this_netmatch = ((xor & iface->ksni_netmask) == 0) ? 1 : 0; + this_netmatch = !(xor & iface->ksni_netmask) ? 1 : 0; if (!(!best_iface || best_netmatch < this_netmatch || @@ -947,9 +947,9 @@ ksocknal_create_routes(ksock_peer_t *peer, int port, if (route) continue; - this_netmatch = (((iface->ksni_ipaddr ^ + this_netmatch = (!((iface->ksni_ipaddr ^ newroute->ksnr_ipaddr) & - iface->ksni_netmask) == 0) ? 1 : 0; + iface->ksni_netmask)) ? 1 : 0; if (!(!best_iface || best_netmatch < this_netmatch || @@ -986,7 +986,7 @@ ksocknal_accept(lnet_ni_t *ni, struct socket *sock) int peer_port; rc = lnet_sock_getaddr(sock, 1, &peer_ip, &peer_port); - LASSERT(rc == 0); /* we succeeded before */ + LASSERT(!rc); /* we succeeded before */ LIBCFS_ALLOC(cr, sizeof(*cr)); if (!cr) { @@ -1082,7 +1082,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, /* stash conn's local and remote addrs */ rc = ksocknal_lib_get_conn_addrs(conn); - if (rc != 0) + if (rc) goto failed_1; /* @@ -1114,7 +1114,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, } rc = ksocknal_send_hello(ni, conn, peerid.nid, hello); - if (rc != 0) + if (rc) goto failed_1; } else { peerid.nid = LNET_NID_ANY; @@ -1128,7 +1128,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, if (rc < 0) goto failed_1; - LASSERT(rc == 0 || active); + LASSERT(!rc || active); LASSERT(conn->ksnc_proto); LASSERT(peerid.nid != LNET_NID_ANY); @@ -1139,13 +1139,13 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, write_lock_bh(global_lock); } else { rc = ksocknal_create_peer(&peer, ni, peerid); - if (rc != 0) + if (rc) goto failed_1; write_lock_bh(global_lock); /* called with a ref on ni, so shutdown can't have started */ - LASSERT(((ksock_net_t *) ni->ni_data)->ksnn_shutdown == 0); + LASSERT(!((ksock_net_t *) ni->ni_data)->ksnn_shutdown); peer2 = ksocknal_find_peer_locked(ni, peerid); if (!peer2) { @@ -1239,7 +1239,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, * Reply on a passive connection attempt so the peer * realises we're connected. */ - LASSERT(rc == 0); + LASSERT(!rc); if (!active) rc = EALREADY; @@ -1344,7 +1344,7 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, * socket; this ensures the socket only tears down after the * response has been sent. */ - if (rc == 0) + if (!rc) rc = ksocknal_lib_setup_sock(sock); write_lock_bh(global_lock); @@ -1357,14 +1357,14 @@ ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route, write_unlock_bh(global_lock); - if (rc != 0) { + if (rc) { write_lock_bh(global_lock); if (!conn->ksnc_closing) { /* could be closed by another thread */ ksocknal_close_conn_locked(conn, rc); } write_unlock_bh(global_lock); - } else if (ksocknal_connsock_addref(conn) == 0) { + } else if (!ksocknal_connsock_addref(conn)) { /* Allow I/O to proceed. */ ksocknal_read_callback(conn); ksocknal_write_callback(conn); @@ -1439,7 +1439,7 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) ksock_conn_t *conn2; struct list_head *tmp; - LASSERT(peer->ksnp_error == 0); + LASSERT(!peer->ksnp_error); LASSERT(!conn->ksnc_closing); conn->ksnc_closing = 1; @@ -1450,7 +1450,7 @@ ksocknal_close_conn_locked(ksock_conn_t *conn, int error) if (route) { /* dissociate conn from route... */ LASSERT(!route->ksnr_deleted); - LASSERT((route->ksnr_connected & (1 << conn->ksnc_type)) != 0); + LASSERT(route->ksnr_connected & (1 << conn->ksnc_type)); conn2 = NULL; list_for_each(tmp, &peer->ksnp_conns) { @@ -1531,9 +1531,9 @@ ksocknal_peer_failed(ksock_peer_t *peer) */ read_lock(&ksocknal_data.ksnd_global_lock); - if ((peer->ksnp_id.pid & LNET_PID_USERFLAG) == 0 && + if (!(peer->ksnp_id.pid & LNET_PID_USERFLAG) && list_empty(&peer->ksnp_conns) && - peer->ksnp_accepting == 0 && + !peer->ksnp_accepting && !ksocknal_find_connecting_route_locked(peer)) { notify = 1; last_alive = peer->ksnp_last_alive; @@ -1566,7 +1566,7 @@ ksocknal_finalize_zcreq(ksock_conn_t *conn) if (tx->tx_conn != conn) continue; - LASSERT(tx->tx_msg.ksm_zc_cookies[0] != 0); + LASSERT(tx->tx_msg.ksm_zc_cookies[0]); tx->tx_msg.ksm_zc_cookies[0] = 0; tx->tx_zc_aborted = 1; /* mark it as not-acked */ @@ -1629,7 +1629,7 @@ ksocknal_terminate_conn(ksock_conn_t *conn) */ conn->ksnc_scheduler->kss_nconns--; - if (peer->ksnp_error != 0) { + if (peer->ksnp_error) { /* peer's last conn closed in error */ LASSERT(list_empty(&peer->ksnp_conns)); failed = 1; @@ -1656,7 +1656,7 @@ ksocknal_queue_zombie_conn(ksock_conn_t *conn) { /* Queue the conn for the reaper to destroy */ - LASSERT(atomic_read(&conn->ksnc_conn_refcount) == 0); + LASSERT(!atomic_read(&conn->ksnc_conn_refcount)); spin_lock_bh(&ksocknal_data.ksnd_reaper_lock); list_add_tail(&conn->ksnc_list, &ksocknal_data.ksnd_zombie_conns); @@ -1673,8 +1673,8 @@ ksocknal_destroy_conn(ksock_conn_t *conn) /* Final coup-de-grace of the reaper */ CDEBUG(D_NET, "connection %p\n", conn); - LASSERT(atomic_read(&conn->ksnc_conn_refcount) == 0); - LASSERT(atomic_read(&conn->ksnc_sock_refcount) == 0); + LASSERT(!atomic_read(&conn->ksnc_conn_refcount)); + LASSERT(!atomic_read(&conn->ksnc_sock_refcount)); LASSERT(!conn->ksnc_sock); LASSERT(!conn->ksnc_route); LASSERT(!conn->ksnc_tx_scheduled); @@ -1736,8 +1736,7 @@ ksocknal_close_peer_conns_locked(ksock_peer_t *peer, __u32 ipaddr, int why) list_for_each_safe(ctmp, cnxt, &peer->ksnp_conns) { conn = list_entry(ctmp, ksock_conn_t, ksnc_list); - if (ipaddr == 0 || - conn->ksnc_ipaddr == ipaddr) { + if (!ipaddr || conn->ksnc_ipaddr == ipaddr) { count++; ksocknal_close_conn_locked(conn, why); } @@ -1799,10 +1798,10 @@ ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr) write_unlock_bh(&ksocknal_data.ksnd_global_lock); /* wildcards always succeed */ - if (id.nid == LNET_NID_ANY || id.pid == LNET_PID_ANY || ipaddr == 0) + if (id.nid == LNET_NID_ANY || id.pid == LNET_PID_ANY || !ipaddr) return 0; - if (count == 0) + if (!count) return -ENOENT; else return 0; @@ -1873,7 +1872,7 @@ ksocknal_query(lnet_ni_t *ni, lnet_nid_t nid, unsigned long *when) read_unlock(glock); - if (last_alive != 0) + if (last_alive) *when = last_alive; CDEBUG(D_NET, "Peer %s %p, alive %ld secs ago, connect %d\n", @@ -1966,7 +1965,7 @@ static int ksocknal_push(lnet_ni_t *ni, lnet_process_id_t id) } read_unlock(&ksocknal_data.ksnd_global_lock); - if (i == 0) /* no match */ + if (!i) /* no match */ break; rc = 0; @@ -1990,8 +1989,7 @@ ksocknal_add_interface(lnet_ni_t *ni, __u32 ipaddress, __u32 netmask) struct list_head *rtmp; ksock_route_t *route; - if (ipaddress == 0 || - netmask == 0) + if (!ipaddress || !netmask) return -EINVAL; write_lock_bh(&ksocknal_data.ksnd_global_lock); @@ -2063,7 +2061,7 @@ ksocknal_peer_del_interface_locked(ksock_peer_t *peer, __u32 ipaddr) if (route->ksnr_myipaddr != ipaddr) continue; - if (route->ksnr_share_count != 0) { + if (route->ksnr_share_count) { /* Manually created; keep, but unbind */ route->ksnr_myipaddr = 0; } else { @@ -2096,8 +2094,7 @@ ksocknal_del_interface(lnet_ni_t *ni, __u32 ipaddress) for (i = 0; i < net->ksnn_ninterfaces; i++) { this_ip = net->ksnn_interfaces[i].ksni_ipaddr; - if (!(ipaddress == 0 || - ipaddress == this_ip)) + if (!(!ipaddress || ipaddress == this_ip)) continue; rc = 0; @@ -2175,7 +2172,7 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg) rc = ksocknal_get_peer_info(ni, data->ioc_count, &id, &myip, &ip, &port, &conn_count, &share_count); - if (rc != 0) + if (rc) return rc; data->ioc_nid = id.nid; @@ -2256,7 +2253,7 @@ ksocknal_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg) static void ksocknal_free_buffers(void) { - LASSERT(atomic_read(&ksocknal_data.ksnd_nactive_txs) == 0); + LASSERT(!atomic_read(&ksocknal_data.ksnd_nactive_txs)); if (ksocknal_data.ksnd_sched_info) { struct ksock_sched_info *info; @@ -2304,7 +2301,7 @@ ksocknal_base_shutdown(void) int i; int j; - LASSERT(ksocknal_data.ksnd_nnets == 0); + LASSERT(!ksocknal_data.ksnd_nnets); switch (ksocknal_data.ksnd_init) { default: @@ -2336,7 +2333,7 @@ ksocknal_base_shutdown(void) &sched->kss_rx_conns)); LASSERT(list_empty( &sched->kss_zombie_noop_txs)); - LASSERT(sched->kss_nconns == 0); + LASSERT(!sched->kss_nconns); } } } @@ -2361,7 +2358,7 @@ ksocknal_base_shutdown(void) i = 4; read_lock(&ksocknal_data.ksnd_global_lock); - while (ksocknal_data.ksnd_nthreads != 0) { + while (ksocknal_data.ksnd_nthreads) { i++; CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, /* power of 2? */ "waiting for %d threads to terminate\n", @@ -2399,7 +2396,7 @@ ksocknal_base_startup(void) int i; LASSERT(ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING); - LASSERT(ksocknal_data.ksnd_nnets == 0); + LASSERT(!ksocknal_data.ksnd_nnets); memset(&ksocknal_data, 0, sizeof(ksocknal_data)); /* zero pointers */ @@ -2502,7 +2499,7 @@ ksocknal_base_startup(void) snprintf(name, sizeof(name), "socknal_cd%02d", i); rc = ksocknal_thread_start(ksocknal_connd, (void *)((ulong_ptr_t)i), name); - if (rc != 0) { + if (rc) { spin_lock_bh(&ksocknal_data.ksnd_connd_lock); ksocknal_data.ksnd_connd_starting--; spin_unlock_bh(&ksocknal_data.ksnd_connd_lock); @@ -2512,7 +2509,7 @@ ksocknal_base_startup(void) } rc = ksocknal_thread_start(ksocknal_reaper, NULL, "socknal_reaper"); - if (rc != 0) { + if (rc) { CERROR("Can't spawn socknal reaper: %d\n", rc); goto failed; } @@ -2604,7 +2601,7 @@ ksocknal_shutdown(lnet_ni_t *ni) /* Wait for all peer state to clean up */ i = 2; spin_lock_bh(&net->ksnn_lock); - while (net->ksnn_npeers != 0) { + while (net->ksnn_npeers) { spin_unlock_bh(&net->ksnn_lock); i++; @@ -2621,15 +2618,15 @@ ksocknal_shutdown(lnet_ni_t *ni) spin_unlock_bh(&net->ksnn_lock); for (i = 0; i < net->ksnn_ninterfaces; i++) { - LASSERT(net->ksnn_interfaces[i].ksni_npeers == 0); - LASSERT(net->ksnn_interfaces[i].ksni_nroutes == 0); + LASSERT(!net->ksnn_interfaces[i].ksni_npeers); + LASSERT(!net->ksnn_interfaces[i].ksni_nroutes); } list_del(&net->ksnn_list); LIBCFS_FREE(net, sizeof(*net)); ksocknal_data.ksnd_nnets--; - if (ksocknal_data.ksnd_nnets == 0) + if (!ksocknal_data.ksnd_nnets) ksocknal_base_shutdown(); } @@ -2657,7 +2654,7 @@ ksocknal_enumerate_interfaces(ksock_net_t *net) continue; rc = lnet_ipif_query(names[i], &up, &ip, &mask); - if (rc != 0) { + if (rc) { CWARN("Can't get interface %s info: %d\n", names[i], rc); continue; @@ -2684,7 +2681,7 @@ ksocknal_enumerate_interfaces(ksock_net_t *net) lnet_ipif_free_enumeration(names, n); - if (j == 0) + if (!j) CERROR("Can't find any usable interfaces\n"); return j; @@ -2715,7 +2712,7 @@ ksocknal_search_new_ipif(ksock_net_t *net) if (colon2) *colon2 = 0; - found = strcmp(ifnam, ifnam2) == 0; + found = !strcmp(ifnam, ifnam2); if (colon2) *colon2 = ':'; } @@ -2738,7 +2735,7 @@ ksocknal_start_schedulers(struct ksock_sched_info *info) int rc = 0; int i; - if (info->ksi_nthreads == 0) { + if (!info->ksi_nthreads) { if (*ksocknal_tunables.ksnd_nscheds > 0) { nthrs = info->ksi_nthreads_max; } else { @@ -2766,7 +2763,7 @@ ksocknal_start_schedulers(struct ksock_sched_info *info) rc = ksocknal_thread_start(ksocknal_scheduler, (void *)id, name); - if (rc == 0) + if (!rc) continue; CERROR("Can't spawn thread %d for scheduler[%d]: %d\n", @@ -2798,7 +2795,7 @@ ksocknal_net_start_threads(ksock_net_t *net, __u32 *cpts, int ncpts) continue; rc = ksocknal_start_schedulers(info); - if (rc != 0) + if (rc) return rc; } return 0; @@ -2815,7 +2812,7 @@ ksocknal_startup(lnet_ni_t *ni) if (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING) { rc = ksocknal_base_startup(); - if (rc != 0) + if (rc) return rc; } @@ -2848,7 +2845,7 @@ ksocknal_startup(lnet_ni_t *ni) &net->ksnn_interfaces[i].ksni_ipaddr, &net->ksnn_interfaces[i].ksni_netmask); - if (rc != 0) { + if (rc) { CERROR("Can't get interface %s info: %d\n", ni->ni_interfaces[i], rc); goto fail_1; @@ -2869,7 +2866,7 @@ ksocknal_startup(lnet_ni_t *ni) /* call it before add it to ksocknal_data.ksnd_nets */ rc = ksocknal_net_start_threads(net, ni->ni_cpts, ni->ni_ncpts); - if (rc != 0) + if (rc) goto fail_1; ni->ni_nid = LNET_MKNID(LNET_NIDNET(ni->ni_nid), @@ -2883,7 +2880,7 @@ ksocknal_startup(lnet_ni_t *ni) fail_1: LIBCFS_FREE(net, sizeof(*net)); fail_0: - if (ksocknal_data.ksnd_nnets == 0) + if (!ksocknal_data.ksnd_nnets) ksocknal_base_shutdown(); return -ENETDOWN; @@ -2916,7 +2913,7 @@ ksocknal_module_init(void) the_ksocklnd.lnd_accept = ksocknal_accept; rc = ksocknal_tunables_init(); - if (rc != 0) + if (rc) return rc; lnet_register_lnd(&the_ksocklnd); diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c index f9ec607595a3..02da02dae850 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c @@ -138,7 +138,7 @@ ksocknal_send_iov(ksock_conn_t *conn, ksock_tx_t *tx) nob -= iov->iov_len; tx->tx_iov = ++iov; tx->tx_niov--; - } while (nob != 0); + } while (nob); return rc; } @@ -150,7 +150,7 @@ ksocknal_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) int nob; int rc; - LASSERT(tx->tx_niov == 0); + LASSERT(!tx->tx_niov); LASSERT(tx->tx_nkiov > 0); /* Never touch tx->tx_kiov inside ksocknal_lib_send_kiov() */ @@ -176,7 +176,7 @@ ksocknal_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) nob -= (int)kiov->kiov_len; tx->tx_kiov = ++kiov; tx->tx_nkiov--; - } while (nob != 0); + } while (nob); return rc; } @@ -187,15 +187,15 @@ ksocknal_transmit(ksock_conn_t *conn, ksock_tx_t *tx) int rc; int bufnob; - if (ksocknal_data.ksnd_stall_tx != 0) { + if (ksocknal_data.ksnd_stall_tx) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(cfs_time_seconds(ksocknal_data.ksnd_stall_tx)); } - LASSERT(tx->tx_resid != 0); + LASSERT(tx->tx_resid); rc = ksocknal_connsock_addref(conn); - if (rc != 0) { + if (rc) { LASSERT(conn->ksnc_closing); return -ESHUTDOWN; } @@ -205,7 +205,7 @@ ksocknal_transmit(ksock_conn_t *conn, ksock_tx_t *tx) /* testing... */ ksocknal_data.ksnd_enomem_tx--; rc = -EAGAIN; - } else if (tx->tx_niov != 0) { + } else if (tx->tx_niov) { rc = ksocknal_send_iov(conn, tx); } else { rc = ksocknal_send_kiov(conn, tx); @@ -229,7 +229,7 @@ ksocknal_transmit(ksock_conn_t *conn, ksock_tx_t *tx) if (rc <= 0) { /* Didn't write anything? */ - if (rc == 0) /* some stacks return 0 instead of -EAGAIN */ + if (!rc) /* some stacks return 0 instead of -EAGAIN */ rc = -EAGAIN; /* Check if EAGAIN is due to memory pressure */ @@ -243,7 +243,7 @@ ksocknal_transmit(ksock_conn_t *conn, ksock_tx_t *tx) atomic_sub(rc, &conn->ksnc_tx_nob); rc = 0; - } while (tx->tx_resid != 0); + } while (tx->tx_resid); ksocknal_connsock_decref(conn); return rc; @@ -291,7 +291,7 @@ ksocknal_recv_iov(ksock_conn_t *conn) nob -= iov->iov_len; conn->ksnc_rx_iov = ++iov; conn->ksnc_rx_niov--; - } while (nob != 0); + } while (nob); return rc; } @@ -338,7 +338,7 @@ ksocknal_recv_kiov(ksock_conn_t *conn) nob -= kiov->kiov_len; conn->ksnc_rx_kiov = ++kiov; conn->ksnc_rx_nkiov--; - } while (nob != 0); + } while (nob); return 1; } @@ -353,19 +353,19 @@ ksocknal_receive(ksock_conn_t *conn) */ int rc; - if (ksocknal_data.ksnd_stall_rx != 0) { + if (ksocknal_data.ksnd_stall_rx) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(cfs_time_seconds(ksocknal_data.ksnd_stall_rx)); } rc = ksocknal_connsock_addref(conn); - if (rc != 0) { + if (rc) { LASSERT(conn->ksnc_closing); return -ESHUTDOWN; } for (;;) { - if (conn->ksnc_rx_niov != 0) + if (conn->ksnc_rx_niov) rc = ksocknal_recv_iov(conn); else rc = ksocknal_recv_kiov(conn); @@ -374,7 +374,7 @@ ksocknal_receive(ksock_conn_t *conn) /* error/EOF or partial receive */ if (rc == -EAGAIN) { rc = 1; - } else if (rc == 0 && conn->ksnc_rx_started) { + } else if (!rc && conn->ksnc_rx_started) { /* EOF in the middle of a message */ rc = -EPROTO; } @@ -383,7 +383,7 @@ ksocknal_receive(ksock_conn_t *conn) /* Completed a fragment */ - if (conn->ksnc_rx_nob_wanted == 0) { + if (!conn->ksnc_rx_nob_wanted) { rc = 1; break; } @@ -397,7 +397,7 @@ void ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx) { lnet_msg_t *lnetmsg = tx->tx_lnetmsg; - int rc = (tx->tx_resid == 0 && !tx->tx_zc_aborted) ? 0 : -EIO; + int rc = (!tx->tx_resid && !tx->tx_zc_aborted) ? 0 : -EIO; LASSERT(ni || tx->tx_conn); @@ -472,11 +472,11 @@ ksocknal_check_zc_req(ksock_tx_t *tx) tx->tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout); - LASSERT(tx->tx_msg.ksm_zc_cookies[0] == 0); + LASSERT(!tx->tx_msg.ksm_zc_cookies[0]); tx->tx_msg.ksm_zc_cookies[0] = peer->ksnp_zc_next_cookie++; - if (peer->ksnp_zc_next_cookie == 0) + if (!peer->ksnp_zc_next_cookie) peer->ksnp_zc_next_cookie = SOCKNAL_KEEPALIVE_PING + 1; list_add_tail(&tx->tx_zc_list, &peer->ksnp_zc_req_list); @@ -496,7 +496,7 @@ ksocknal_uncheck_zc_req(ksock_tx_t *tx) spin_lock(&peer->ksnp_lock); - if (tx->tx_msg.ksm_zc_cookies[0] == 0) { + if (!tx->tx_msg.ksm_zc_cookies[0]) { /* Not waiting for an ACK */ spin_unlock(&peer->ksnp_lock); return; @@ -522,9 +522,9 @@ ksocknal_process_transmit(ksock_conn_t *conn, ksock_tx_t *tx) CDEBUG(D_NET, "send(%d) %d\n", tx->tx_resid, rc); - if (tx->tx_resid == 0) { + if (!tx->tx_resid) { /* Sent everything OK */ - LASSERT(rc == 0); + LASSERT(!rc); return 0; } @@ -592,7 +592,7 @@ ksocknal_launch_connection_locked(ksock_route_t *route) LASSERT(!route->ksnr_scheduled); LASSERT(!route->ksnr_connecting); - LASSERT((ksocknal_route_mask() & ~route->ksnr_connected) != 0); + LASSERT(ksocknal_route_mask() & ~route->ksnr_connected); route->ksnr_scheduled = 1; /* scheduling conn for connd */ ksocknal_route_addref(route); /* extra ref for connd */ @@ -737,7 +737,7 @@ ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) bufnob = conn->ksnc_sock->sk->sk_wmem_queued; spin_lock_bh(&sched->kss_lock); - if (list_empty(&conn->ksnc_tx_queue) && bufnob == 0) { + if (list_empty(&conn->ksnc_tx_queue) && !bufnob) { /* First packet starts the timeout */ conn->ksnc_tx_deadline = cfs_time_shift(*ksocknal_tunables.ksnd_timeout); @@ -752,7 +752,7 @@ ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) * The packet is noop ZC ACK, try to piggyback the ack_cookie * on a normal packet so I don't need to send it */ - LASSERT(msg->ksm_zc_cookies[1] != 0); + LASSERT(msg->ksm_zc_cookies[1]); LASSERT(conn->ksnc_proto->pro_queue_tx_zcack); if (conn->ksnc_proto->pro_queue_tx_zcack(conn, tx, 0)) @@ -763,7 +763,7 @@ ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn) * It's a normal packet - can it piggback a noop zc-ack that * has been queued already? */ - LASSERT(msg->ksm_zc_cookies[1] == 0); + LASSERT(!msg->ksm_zc_cookies[1]); LASSERT(conn->ksnc_proto->pro_queue_tx_msg); ztx = conn->ksnc_proto->pro_queue_tx_msg(conn, tx); @@ -803,10 +803,10 @@ ksocknal_find_connectable_route_locked(ksock_peer_t *peer) continue; /* all route types connected ? */ - if ((ksocknal_route_mask() & ~route->ksnr_connected) == 0) + if (!(ksocknal_route_mask() & ~route->ksnr_connected)) continue; - if (!(route->ksnr_retry_interval == 0 || /* first attempt */ + if (!(!route->ksnr_retry_interval || /* first attempt */ cfs_time_aftereq(now, route->ksnr_timeout))) { CDEBUG(D_NET, "Too soon to retry route %pI4h (cnted %d, interval %ld, %ld secs later)\n", @@ -884,7 +884,7 @@ ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) write_unlock_bh(g_lock); - if ((id.pid & LNET_PID_USERFLAG) != 0) { + if (id.pid & LNET_PID_USERFLAG) { CERROR("Refusing to create a connection to userspace process %s\n", libcfs_id2str(id)); return -EHOSTUNREACH; @@ -898,7 +898,7 @@ ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx, lnet_process_id_t id) rc = ksocknal_add_peer(ni, id, LNET_NIDADDR(id.nid), lnet_acceptor_port()); - if (rc != 0) { + if (rc) { CERROR("Can't add peer %s: %d\n", libcfs_id2str(id), rc); return rc; @@ -956,7 +956,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) CDEBUG(D_NET, "sending %u bytes in %d frags to %s\n", payload_nob, payload_niov, libcfs_id2str(target)); - LASSERT(payload_nob == 0 || payload_niov > 0); + LASSERT(!payload_nob || payload_niov > 0); LASSERT(payload_niov <= LNET_MAX_IOV); /* payload is either all vaddrs or all pages */ LASSERT(!(payload_kiov && payload_iov)); @@ -1010,7 +1010,7 @@ ksocknal_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) if (!mpflag) cfs_memory_pressure_restore(mpflag); - if (rc == 0) + if (!rc) return 0; ksocknal_free_tx(tx); @@ -1050,12 +1050,12 @@ ksocknal_new_packet(ksock_conn_t *conn, int nob_to_skip) LASSERT(conn->ksnc_proto); - if ((*ksocknal_tunables.ksnd_eager_ack & conn->ksnc_type) != 0) { + if (*ksocknal_tunables.ksnd_eager_ack & conn->ksnc_type) { /* Remind the socket to ack eagerly... */ ksocknal_lib_eager_ack(conn); } - if (nob_to_skip == 0) { /* right at next packet boundary now */ + if (!nob_to_skip) { /* right at next packet boundary now */ conn->ksnc_rx_started = 0; mb(); /* racing with timeout thread */ @@ -1112,7 +1112,7 @@ ksocknal_new_packet(ksock_conn_t *conn, int nob_to_skip) skipped += nob; nob_to_skip -= nob; - } while (nob_to_skip != 0 && /* mustn't overflow conn's rx iov */ + } while (nob_to_skip && /* mustn't overflow conn's rx iov */ niov < sizeof(conn->ksnc_rx_iov_space) / sizeof(struct iovec)); conn->ksnc_rx_niov = niov; @@ -1138,13 +1138,13 @@ ksocknal_process_receive(ksock_conn_t *conn) conn->ksnc_rx_state == SOCKNAL_RX_LNET_HEADER || conn->ksnc_rx_state == SOCKNAL_RX_SLOP); again: - if (conn->ksnc_rx_nob_wanted != 0) { + if (conn->ksnc_rx_nob_wanted) { rc = ksocknal_receive(conn); if (rc <= 0) { LASSERT(rc != -EAGAIN); - if (rc == 0) + if (!rc) CDEBUG(D_NET, "[%p] EOF from %s ip %pI4h:%d\n", conn, libcfs_id2str(conn->ksnc_peer->ksnp_id), @@ -1160,10 +1160,10 @@ ksocknal_process_receive(ksock_conn_t *conn) /* it's not an error if conn is being closed */ ksocknal_close_conn_and_siblings(conn, (conn->ksnc_closing) ? 0 : rc); - return (rc == 0 ? -ESHUTDOWN : rc); + return (!rc ? -ESHUTDOWN : rc); } - if (conn->ksnc_rx_nob_wanted != 0) { + if (conn->ksnc_rx_nob_wanted) { /* short read */ return -EAGAIN; } @@ -1188,7 +1188,7 @@ ksocknal_process_receive(ksock_conn_t *conn) } if (conn->ksnc_msg.ksm_type == KSOCK_MSG_NOOP && - conn->ksnc_msg.ksm_csum != 0 && /* has checksum */ + conn->ksnc_msg.ksm_csum && /* has checksum */ conn->ksnc_msg.ksm_csum != conn->ksnc_rx_csum) { /* NOOP Checksum error */ CERROR("%s: Checksum error, wire:0x%08X data:0x%08X\n", @@ -1199,7 +1199,7 @@ ksocknal_process_receive(ksock_conn_t *conn) return -EIO; } - if (conn->ksnc_msg.ksm_zc_cookies[1] != 0) { + if (conn->ksnc_msg.ksm_zc_cookies[1]) { __u64 cookie = 0; LASSERT(conn->ksnc_proto != &ksocknal_protocol_v1x); @@ -1210,7 +1210,7 @@ ksocknal_process_receive(ksock_conn_t *conn) rc = conn->ksnc_proto->pro_handle_zcack(conn, cookie, conn->ksnc_msg.ksm_zc_cookies[1]); - if (rc != 0) { + if (rc) { CERROR("%s: Unknown ZC-ACK cookie: %llu, %llu\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), cookie, conn->ksnc_msg.ksm_zc_cookies[1]); @@ -1243,7 +1243,7 @@ ksocknal_process_receive(ksock_conn_t *conn) /* unpack message header */ conn->ksnc_proto->pro_unpack(&conn->ksnc_msg); - if ((conn->ksnc_peer->ksnp_id.pid & LNET_PID_USERFLAG) != 0) { + if (conn->ksnc_peer->ksnp_id.pid & LNET_PID_USERFLAG) { /* Userspace peer */ lhdr = &conn->ksnc_msg.ksm_u.lnetmsg.ksnm_hdr; id = &conn->ksnc_peer->ksnp_id; @@ -1281,8 +1281,8 @@ ksocknal_process_receive(ksock_conn_t *conn) /* payload all received */ rc = 0; - if (conn->ksnc_rx_nob_left == 0 && /* not truncating */ - conn->ksnc_msg.ksm_csum != 0 && /* has checksum */ + if (!conn->ksnc_rx_nob_left && /* not truncating */ + conn->ksnc_msg.ksm_csum && /* has checksum */ conn->ksnc_msg.ksm_csum != conn->ksnc_rx_csum) { CERROR("%s: Checksum error, wire:0x%08X data:0x%08X\n", libcfs_id2str(conn->ksnc_peer->ksnp_id), @@ -1290,7 +1290,7 @@ ksocknal_process_receive(ksock_conn_t *conn) rc = -EIO; } - if (rc == 0 && conn->ksnc_msg.ksm_zc_cookies[0] != 0) { + if (!rc && conn->ksnc_msg.ksm_zc_cookies[0]) { LASSERT(conn->ksnc_proto != &ksocknal_protocol_v1x); lhdr = &conn->ksnc_msg.ksm_u.lnetmsg.ksnm_hdr; @@ -1304,7 +1304,7 @@ ksocknal_process_receive(ksock_conn_t *conn) lnet_finalize(conn->ksnc_peer->ksnp_ni, conn->ksnc_cookie, rc); - if (rc != 0) { + if (rc) { ksocknal_new_packet(conn, 0); ksocknal_close_conn_and_siblings(conn, rc); return -EPROTO; @@ -1341,7 +1341,7 @@ ksocknal_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, conn->ksnc_rx_nob_wanted = mlen; conn->ksnc_rx_nob_left = rlen; - if (mlen == 0 || iov) { + if (!mlen || iov) { conn->ksnc_rx_nkiov = 0; conn->ksnc_rx_kiov = NULL; conn->ksnc_rx_iov = conn->ksnc_rx_iov_space.iov; @@ -1415,7 +1415,7 @@ int ksocknal_scheduler(void *arg) cfs_block_allsigs(); rc = cfs_cpt_bind(lnet_cpt_table(), info->ksi_cpt); - if (rc != 0) { + if (rc) { CERROR("Can't set CPT affinity to %d: %d\n", info->ksi_cpt, rc); } @@ -1452,7 +1452,7 @@ int ksocknal_scheduler(void *arg) LASSERT(conn->ksnc_rx_scheduled); /* Did process_receive get everything it wanted? */ - if (rc == 0) + if (!rc) conn->ksnc_rx_ready = 1; if (conn->ksnc_rx_state == SOCKNAL_RX_PARSE) { @@ -1560,7 +1560,7 @@ int ksocknal_scheduler(void *arg) rc = wait_event_interruptible_exclusive( sched->kss_waitq, !ksocknal_sched_cansleep(sched)); - LASSERT(rc == 0); + LASSERT(!rc); } else { cond_resched(); } @@ -1636,7 +1636,7 @@ ksocknal_parse_proto_version(ksock_hello_msg_t *hello) else if (hello->kshm_magic == __swab32(LNET_PROTO_MAGIC)) version = __swab32(hello->kshm_version); - if (version != 0) { + if (version) { #if SOCKNAL_VERSION_DEBUG if (*ksocknal_tunables.ksnd_protocol == 1) return NULL; @@ -1731,7 +1731,7 @@ ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn, lnet_acceptor_timeout(); rc = lnet_sock_read(sock, &hello->kshm_magic, sizeof(hello->kshm_magic), timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading HELLO from %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0); @@ -1751,7 +1751,7 @@ ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn, rc = lnet_sock_read(sock, &hello->kshm_version, sizeof(hello->kshm_version), timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading HELLO from %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0); @@ -1785,7 +1785,7 @@ ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn, /* receive the rest of hello message anyway */ rc = conn->ksnc_proto->pro_recv_hello(conn, hello, timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading or checking hello from from %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0); @@ -1879,7 +1879,7 @@ ksocknal_connect(ksock_route_t *route) * route got connected while queued */ if (peer->ksnp_closing || route->ksnr_deleted || - wanted == 0) { + !wanted) { retry_later = 0; break; } @@ -1895,14 +1895,14 @@ ksocknal_connect(ksock_route_t *route) if (retry_later) /* needs reschedule */ break; - if ((wanted & (1 << SOCKLND_CONN_ANY)) != 0) { + if (wanted & (1 << SOCKLND_CONN_ANY)) { type = SOCKLND_CONN_ANY; - } else if ((wanted & (1 << SOCKLND_CONN_CONTROL)) != 0) { + } else if (wanted & (1 << SOCKLND_CONN_CONTROL)) { type = SOCKLND_CONN_CONTROL; - } else if ((wanted & (1 << SOCKLND_CONN_BULK_IN)) != 0) { + } else if (wanted & (1 << SOCKLND_CONN_BULK_IN)) { type = SOCKLND_CONN_BULK_IN; } else { - LASSERT((wanted & (1 << SOCKLND_CONN_BULK_OUT)) != 0); + LASSERT(wanted & (1 << SOCKLND_CONN_BULK_OUT)); type = SOCKLND_CONN_BULK_OUT; } @@ -1919,7 +1919,7 @@ ksocknal_connect(ksock_route_t *route) rc = lnet_connect(&sock, peer->ksnp_id.nid, route->ksnr_myipaddr, route->ksnr_ipaddr, route->ksnr_port); - if (rc != 0) + if (rc) goto failed; rc = ksocknal_create_conn(peer->ksnp_ni, route, sock, type); @@ -1934,7 +1934,7 @@ ksocknal_connect(ksock_route_t *route) * A +ve RC means I have to retry because I lost the connection * race or I have to renegotiate protocol version */ - retry_later = (rc != 0); + retry_later = (rc); if (retry_later) CDEBUG(D_NET, "peer %s: conn race, retry later.\n", libcfs_nid2str(peer->ksnp_id.nid)); @@ -1951,7 +1951,7 @@ ksocknal_connect(ksock_route_t *route) * the peer's incoming connection request */ if (rc == EALREADY || - (rc == 0 && peer->ksnp_accepting > 0)) { + (!rc && peer->ksnp_accepting > 0)) { /* * We want to introduce a delay before next * attempt to connect if we lost conn race, @@ -1985,12 +1985,12 @@ ksocknal_connect(ksock_route_t *route) min(route->ksnr_retry_interval, cfs_time_seconds(*ksocknal_tunables.ksnd_max_reconnectms) / 1000); - LASSERT(route->ksnr_retry_interval != 0); + LASSERT(route->ksnr_retry_interval); route->ksnr_timeout = cfs_time_add(cfs_time_current(), route->ksnr_retry_interval); if (!list_empty(&peer->ksnp_tx_queue) && - peer->ksnp_accepting == 0 && + !peer->ksnp_accepting && !ksocknal_find_connecting_route_locked(peer)) { ksock_conn_t *conn; @@ -2078,7 +2078,7 @@ ksocknal_connd_check_start(time64_t sec, long *timeout) rc = ksocknal_thread_start(ksocknal_connd, NULL, name); spin_lock_bh(&ksocknal_data.ksnd_connd_lock); - if (rc == 0) + if (!rc) return 1; /* we tried ... */ @@ -2145,7 +2145,7 @@ ksocknal_connd_get_route_locked(signed long *timeout_p) /* connd_routes can contain both pending and ordinary routes */ list_for_each_entry(route, &ksocknal_data.ksnd_connd_routes, ksnr_connd_list) { - if (route->ksnr_retry_interval == 0 || + if (!route->ksnr_retry_interval || cfs_time_aftereq(now, route->ksnr_timeout)) return route; @@ -2290,7 +2290,7 @@ ksocknal_find_timed_out_conn(ksock_peer_t *peer) * some platform (like Darwin8.x) */ error = conn->ksnc_sock->sk->sk_err; - if (error != 0) { + if (error) { ksocknal_conn_addref(conn); switch (error) { @@ -2334,7 +2334,7 @@ ksocknal_find_timed_out_conn(ksock_peer_t *peer) } if ((!list_empty(&conn->ksnc_tx_queue) || - conn->ksnc_sock->sk->sk_wmem_queued != 0) && + conn->ksnc_sock->sk->sk_wmem_queued) && cfs_time_aftereq(cfs_time_current(), conn->ksnc_tx_deadline)) { /* @@ -2429,7 +2429,7 @@ ksocknal_send_keepalive_locked(ksock_peer_t *peer) return -ENOMEM; } - if (ksocknal_launch_packet(peer->ksnp_ni, tx, peer->ksnp_id) == 0) { + if (!ksocknal_launch_packet(peer->ksnp_ni, tx, peer->ksnp_id)) { read_lock(&ksocknal_data.ksnd_global_lock); return 1; } @@ -2461,7 +2461,7 @@ ksocknal_check_peer_timeouts(int idx) int resid = 0; int n = 0; - if (ksocknal_send_keepalive_locked(peer) != 0) { + if (ksocknal_send_keepalive_locked(peer)) { read_unlock(&ksocknal_data.ksnd_global_lock); goto again; } @@ -2516,7 +2516,7 @@ ksocknal_check_peer_timeouts(int idx) n++; } - if (n == 0) { + if (!n) { spin_unlock(&peer->ksnp_lock); continue; } @@ -2639,7 +2639,7 @@ ksocknal_reaper(void *arg) if (*ksocknal_tunables.ksnd_timeout > n * p) chunk = (chunk * n * p) / *ksocknal_tunables.ksnd_timeout; - if (chunk == 0) + if (!chunk) chunk = 1; for (i = 0; i < chunk; i++) { @@ -2651,7 +2651,7 @@ ksocknal_reaper(void *arg) deadline = cfs_time_add(deadline, cfs_time_seconds(p)); } - if (nenomem_conns != 0) { + if (nenomem_conns) { /* * Reduce my timeout if I rescheduled ENOMEM conns. * This also prevents me getting woken immediately diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c index 40ce45ddeb76..3e1f24e77f64 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_lib.c @@ -45,13 +45,13 @@ ksocknal_lib_get_conn_addrs(ksock_conn_t *conn) /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */ LASSERT(!conn->ksnc_closing); - if (rc != 0) { + if (rc) { CERROR("Error %d getting sock peer IP\n", rc); return rc; } rc = lnet_sock_getaddr(conn->ksnc_sock, 0, &conn->ksnc_myipaddr, NULL); - if (rc != 0) { + if (rc) { CERROR("Error %d getting sock local IP\n", rc); return rc; } @@ -71,7 +71,7 @@ ksocknal_lib_zc_capable(ksock_conn_t *conn) * ZC if the socket supports scatter/gather and doesn't need software * checksums */ - return ((caps & NETIF_F_SG) != 0 && (caps & NETIF_F_CSUM_MASK) != 0); + return ((caps & NETIF_F_SG) && (caps & NETIF_F_CSUM_MASK)); } int @@ -84,7 +84,7 @@ ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx) if (*ksocknal_tunables.ksnd_enable_csum && /* checksum enabled */ conn->ksnc_proto == &ksocknal_protocol_v2x && /* V2.x connection */ tx->tx_nob == tx->tx_resid && /* frist sending */ - tx->tx_msg.ksm_csum == 0) /* not checksummed */ + !tx->tx_msg.ksm_csum) /* not checksummed */ ksocknal_lib_csum_tx(tx); /* @@ -132,7 +132,7 @@ ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx) * NB we can't trust socket ops to either consume our iovs * or leave them alone. */ - if (tx->tx_msg.ksm_zc_cookies[0] != 0) { + if (tx->tx_msg.ksm_zc_cookies[0]) { /* Zero copy is enabled */ struct sock *sk = sock->sk; struct page *page = kiov->kiov_page; @@ -245,7 +245,7 @@ ksocknal_lib_recv_iov(ksock_conn_t *conn) conn->ksnc_msg.ksm_csum = 0; } - if (saved_csum != 0) { + if (saved_csum) { /* accumulate checksum */ for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); @@ -290,7 +290,7 @@ ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov, return NULL; for (nob = i = 0; i < niov; i++) { - if ((kiov[i].kiov_offset != 0 && i > 0) || + if ((kiov[i].kiov_offset && i > 0) || (kiov[i].kiov_offset + kiov[i].kiov_len != PAGE_CACHE_SIZE && i < niov - 1)) return NULL; @@ -360,7 +360,7 @@ ksocknal_lib_recv_kiov(ksock_conn_t *conn) rc = kernel_recvmsg(conn->ksnc_sock, &msg, (struct kvec *)scratchiov, n, nob, MSG_DONTWAIT); - if (conn->ksnc_msg.ksm_csum != 0) { + if (conn->ksnc_msg.ksm_csum) { for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) { LASSERT(i < niov); @@ -439,14 +439,14 @@ ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, int *rxmem, int * int rc; rc = ksocknal_connsock_addref(conn); - if (rc != 0) { + if (rc) { LASSERT(conn->ksnc_closing); *txmem = *rxmem = *nagle = 0; return -ESHUTDOWN; } rc = lnet_sock_getbuf(sock, txmem, rxmem); - if (rc == 0) { + if (!rc) { len = sizeof(*nagle); rc = kernel_getsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)nagle, &len); @@ -454,7 +454,7 @@ ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem, int *rxmem, int * ksocknal_connsock_decref(conn); - if (rc == 0) + if (!rc) *nagle = !*nagle; else *txmem = *rxmem = *nagle = 0; @@ -484,7 +484,7 @@ ksocknal_lib_setup_sock(struct socket *sock) rc = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger)); - if (rc != 0) { + if (rc) { CERROR("Can't set SO_LINGER: %d\n", rc); return rc; } @@ -492,7 +492,7 @@ ksocknal_lib_setup_sock(struct socket *sock) option = -1; rc = kernel_setsockopt(sock, SOL_TCP, TCP_LINGER2, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set SO_LINGER2: %d\n", rc); return rc; } @@ -502,7 +502,7 @@ ksocknal_lib_setup_sock(struct socket *sock) rc = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't disable nagle: %d\n", rc); return rc; } @@ -510,7 +510,7 @@ ksocknal_lib_setup_sock(struct socket *sock) rc = lnet_sock_setbuf(sock, *ksocknal_tunables.ksnd_tx_buffer_size, *ksocknal_tunables.ksnd_rx_buffer_size); - if (rc != 0) { + if (rc) { CERROR("Can't set buffer tx %d, rx %d buffers: %d\n", *ksocknal_tunables.ksnd_tx_buffer_size, *ksocknal_tunables.ksnd_rx_buffer_size, rc); @@ -529,7 +529,7 @@ ksocknal_lib_setup_sock(struct socket *sock) option = (do_keepalive ? 1 : 0); rc = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set SO_KEEPALIVE: %d\n", rc); return rc; } @@ -539,21 +539,21 @@ ksocknal_lib_setup_sock(struct socket *sock) rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (char *)&keep_idle, sizeof(keep_idle)); - if (rc != 0) { + if (rc) { CERROR("Can't set TCP_KEEPIDLE: %d\n", rc); return rc; } rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, (char *)&keep_intvl, sizeof(keep_intvl)); - if (rc != 0) { + if (rc) { CERROR("Can't set TCP_KEEPINTVL: %d\n", rc); return rc; } rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT, (char *)&keep_count, sizeof(keep_count)); - if (rc != 0) { + if (rc) { CERROR("Can't set TCP_KEEPCNT: %d\n", rc); return rc; } @@ -571,7 +571,7 @@ ksocknal_lib_push_conn(ksock_conn_t *conn) int rc; rc = ksocknal_connsock_addref(conn); - if (rc != 0) /* being shut down */ + if (rc) /* being shut down */ return; sk = conn->ksnc_sock->sk; @@ -584,7 +584,7 @@ ksocknal_lib_push_conn(ksock_conn_t *conn) rc = kernel_setsockopt(conn->ksnc_sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); - LASSERT(rc == 0); + LASSERT(!rc); lock_sock(sk); tp->nonagle = nonagle; diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c index d5046855e318..70910ed596f2 100644 --- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c +++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_proto.c @@ -103,7 +103,7 @@ ksocknal_queue_tx_zcack_v2(ksock_conn_t *conn, } LASSERT(tx->tx_msg.ksm_type == KSOCK_MSG_LNET); - LASSERT(tx->tx_msg.ksm_zc_cookies[1] == 0); + LASSERT(!tx->tx_msg.ksm_zc_cookies[1]); if (tx_ack) cookie = tx_ack->tx_msg.ksm_zc_cookies[1]; @@ -185,7 +185,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, if (tx->tx_msg.ksm_zc_cookies[1] == SOCKNAL_KEEPALIVE_PING) { /* replace the keepalive PING with a real ACK */ - LASSERT(tx->tx_msg.ksm_zc_cookies[0] == 0); + LASSERT(!tx->tx_msg.ksm_zc_cookies[0]); tx->tx_msg.ksm_zc_cookies[1] = cookie; return 1; } @@ -197,7 +197,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, return 1; /* XXX return error in the future */ } - if (tx->tx_msg.ksm_zc_cookies[0] == 0) { + if (!tx->tx_msg.ksm_zc_cookies[0]) { /* NOOP tx has only one ZC-ACK cookie, can carry at least one more */ if (tx->tx_msg.ksm_zc_cookies[1] > cookie) { tx->tx_msg.ksm_zc_cookies[0] = tx->tx_msg.ksm_zc_cookies[1]; @@ -233,7 +233,7 @@ ksocknal_queue_tx_zcack_v3(ksock_conn_t *conn, tmp = tx->tx_msg.ksm_zc_cookies[0]; } - if (tmp != 0) { + if (tmp) { /* range of cookies */ tx->tx_msg.ksm_zc_cookies[0] = tmp - 1; tx->tx_msg.ksm_zc_cookies[1] = tmp + 1; @@ -394,7 +394,7 @@ ksocknal_handle_zcreq(ksock_conn_t *c, __u64 cookie, int remote) return -ENOMEM; rc = ksocknal_launch_packet(peer->ksnp_ni, tx, peer->ksnp_id); - if (rc == 0) + if (!rc) return 0; ksocknal_free_tx(tx); @@ -411,7 +411,7 @@ ksocknal_handle_zcack(ksock_conn_t *conn, __u64 cookie1, __u64 cookie2) LIST_HEAD(zlist); int count; - if (cookie1 == 0) + if (!cookie1) cookie1 = cookie2; count = (cookie1 > cookie2) ? 2 : (cookie2 - cookie1 + 1); @@ -433,7 +433,7 @@ ksocknal_handle_zcack(ksock_conn_t *conn, __u64 cookie1, __u64 cookie2) list_del(&tx->tx_zc_list); list_add(&tx->tx_zc_list, &zlist); - if (--count == 0) + if (!--count) break; } } @@ -446,7 +446,7 @@ ksocknal_handle_zcack(ksock_conn_t *conn, __u64 cookie1, __u64 cookie2) ksocknal_tx_decref(tx); } - return count == 0 ? 0 : -EPROTO; + return !count ? 0 : -EPROTO; } static int @@ -476,14 +476,14 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) hmv->version_major = cpu_to_le16(KSOCK_PROTO_V1_MAJOR); hmv->version_minor = cpu_to_le16(KSOCK_PROTO_V1_MINOR); - if (the_lnet.ln_testprotocompat != 0) { + if (the_lnet.ln_testprotocompat) { /* single-shot proto check */ LNET_LOCK(); - if ((the_lnet.ln_testprotocompat & 1) != 0) { + if (the_lnet.ln_testprotocompat & 1) { hmv->version_major++; /* just different! */ the_lnet.ln_testprotocompat &= ~1; } - if ((the_lnet.ln_testprotocompat & 2) != 0) { + if (the_lnet.ln_testprotocompat & 2) { hmv->magic = LNET_PROTO_MAGIC; the_lnet.ln_testprotocompat &= ~2; } @@ -498,13 +498,13 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) hdr->msg.hello.incarnation = cpu_to_le64(hello->kshm_src_incarnation); rc = lnet_sock_write(sock, hdr, sizeof(*hdr), lnet_acceptor_timeout()); - if (rc != 0) { + if (rc) { CNETERR("Error %d sending HELLO hdr to %pI4h/%d\n", rc, &conn->ksnc_ipaddr, conn->ksnc_port); goto out; } - if (hello->kshm_nips == 0) + if (!hello->kshm_nips) goto out; for (i = 0; i < (int) hello->kshm_nips; i++) @@ -513,7 +513,7 @@ ksocknal_send_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello) rc = lnet_sock_write(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), lnet_acceptor_timeout()); - if (rc != 0) { + if (rc) { CNETERR("Error %d sending HELLO payload (%d) to %pI4h/%d\n", rc, hello->kshm_nips, &conn->ksnc_ipaddr, conn->ksnc_port); @@ -533,10 +533,10 @@ ksocknal_send_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello) hello->kshm_magic = LNET_PROTO_MAGIC; hello->kshm_version = conn->ksnc_proto->pro_version; - if (the_lnet.ln_testprotocompat != 0) { + if (the_lnet.ln_testprotocompat) { /* single-shot proto check */ LNET_LOCK(); - if ((the_lnet.ln_testprotocompat & 1) != 0) { + if (the_lnet.ln_testprotocompat & 1) { hello->kshm_version++; /* just different! */ the_lnet.ln_testprotocompat &= ~1; } @@ -545,19 +545,19 @@ ksocknal_send_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello) rc = lnet_sock_write(sock, hello, offsetof(ksock_hello_msg_t, kshm_ips), lnet_acceptor_timeout()); - if (rc != 0) { + if (rc) { CNETERR("Error %d sending HELLO hdr to %pI4h/%d\n", rc, &conn->ksnc_ipaddr, conn->ksnc_port); return rc; } - if (hello->kshm_nips == 0) + if (!hello->kshm_nips) return 0; rc = lnet_sock_write(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), lnet_acceptor_timeout()); - if (rc != 0) { + if (rc) { CNETERR("Error %d sending HELLO payload (%d) to %pI4h/%d\n", rc, hello->kshm_nips, &conn->ksnc_ipaddr, conn->ksnc_port); @@ -584,7 +584,7 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, rc = lnet_sock_read(sock, &hdr->src_nid, sizeof(*hdr) - offsetof(lnet_hdr_t, src_nid), timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading rest of HELLO hdr from %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); @@ -614,12 +614,12 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, goto out; } - if (hello->kshm_nips == 0) + if (!hello->kshm_nips) goto out; rc = lnet_sock_read(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading IPs from ip %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); @@ -629,7 +629,7 @@ ksocknal_recv_hello_v1(ksock_conn_t *conn, ksock_hello_msg_t *hello, for (i = 0; i < (int) hello->kshm_nips; i++) { hello->kshm_ips[i] = __le32_to_cpu(hello->kshm_ips[i]); - if (hello->kshm_ips[i] == 0) { + if (!hello->kshm_ips[i]) { CERROR("Zero IP[%d] from ip %pI4h\n", i, &conn->ksnc_ipaddr); rc = -EPROTO; @@ -658,7 +658,7 @@ ksocknal_recv_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout offsetof(ksock_hello_msg_t, kshm_ips) - offsetof(ksock_hello_msg_t, kshm_src_nid), timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading HELLO from %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); @@ -682,12 +682,12 @@ ksocknal_recv_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout return -EPROTO; } - if (hello->kshm_nips == 0) + if (!hello->kshm_nips) return 0; rc = lnet_sock_read(sock, hello->kshm_ips, hello->kshm_nips * sizeof(__u32), timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading IPs from ip %pI4h\n", rc, &conn->ksnc_ipaddr); LASSERT(rc < 0 && rc != -EALREADY); @@ -698,7 +698,7 @@ ksocknal_recv_hello_v2(ksock_conn_t *conn, ksock_hello_msg_t *hello, int timeout if (conn->ksnc_flip) __swab32s(&hello->kshm_ips[i]); - if (hello->kshm_ips[i] == 0) { + if (!hello->kshm_ips[i]) { CERROR("Zero IP[%d] from ip %pI4h\n", i, &conn->ksnc_ipaddr); return -EPROTO; diff --git a/drivers/staging/lustre/lnet/lnet/acceptor.c b/drivers/staging/lustre/lnet/lnet/acceptor.c index ef61eafa0ab8..e5f24ffee5e0 100644 --- a/drivers/staging/lustre/lnet/lnet/acceptor.c +++ b/drivers/staging/lustre/lnet/lnet/acceptor.c @@ -159,7 +159,7 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, rc = lnet_sock_connect(&sock, &fatal, local_ip, port, peer_ip, peer_port); - if (rc != 0) { + if (rc) { if (fatal) goto failed; continue; @@ -171,14 +171,14 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; cr.acr_nid = peer_nid; - if (the_lnet.ln_testprotocompat != 0) { + if (the_lnet.ln_testprotocompat) { /* single-shot proto check */ lnet_net_lock(LNET_LOCK_EX); - if ((the_lnet.ln_testprotocompat & 4) != 0) { + if (the_lnet.ln_testprotocompat & 4) { cr.acr_version++; the_lnet.ln_testprotocompat &= ~4; } - if ((the_lnet.ln_testprotocompat & 8) != 0) { + if (the_lnet.ln_testprotocompat & 8) { cr.acr_magic = LNET_PROTO_MAGIC; the_lnet.ln_testprotocompat &= ~8; } @@ -186,7 +186,7 @@ lnet_connect(struct socket **sockp, lnet_nid_t peer_nid, } rc = lnet_sock_write(sock, &cr, sizeof(cr), accept_timeout); - if (rc != 0) + if (rc) goto failed_sock; *sockp = sock; @@ -220,7 +220,7 @@ lnet_accept(struct socket *sock, __u32 magic) LASSERT(sizeof(cr) <= 16); /* not too big for the stack */ rc = lnet_sock_getaddr(sock, 1, &peer_ip, &peer_port); - LASSERT(rc == 0); /* we succeeded before */ + LASSERT(!rc); /* we succeeded before */ if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) { if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) { @@ -236,7 +236,7 @@ lnet_accept(struct socket *sock, __u32 magic) rc = lnet_sock_write(sock, &cr, sizeof(cr), accept_timeout); - if (rc != 0) + if (rc) CERROR("Error sending magic+version in response to LNET magic from %pI4h: %d\n", &peer_ip, rc); return -EPROTO; @@ -256,7 +256,7 @@ lnet_accept(struct socket *sock, __u32 magic) rc = lnet_sock_read(sock, &cr.acr_version, sizeof(cr.acr_version), accept_timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading connection request version from %pI4h\n", rc, &peer_ip); return -EIO; @@ -279,7 +279,7 @@ lnet_accept(struct socket *sock, __u32 magic) cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; rc = lnet_sock_write(sock, &cr, sizeof(cr), accept_timeout); - if (rc != 0) + if (rc) CERROR("Error sending magic+version in response to version %d from %pI4h: %d\n", peer_version, &peer_ip, rc); return -EPROTO; @@ -289,7 +289,7 @@ lnet_accept(struct socket *sock, __u32 magic) sizeof(cr) - offsetof(lnet_acceptor_connreq_t, acr_nid), accept_timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading connection request from %pI4h\n", rc, &peer_ip); return -EIO; @@ -341,7 +341,7 @@ lnet_acceptor(void *arg) rc = lnet_sock_listen(&lnet_acceptor_state.pta_sock, 0, accept_port, accept_backlog); - if (rc != 0) { + if (rc) { if (rc == -EADDRINUSE) LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port %d: port already in use\n", accept_port); @@ -358,12 +358,12 @@ lnet_acceptor(void *arg) lnet_acceptor_state.pta_shutdown = rc; complete(&lnet_acceptor_state.pta_signal); - if (rc != 0) + if (rc) return rc; while (!lnet_acceptor_state.pta_shutdown) { rc = lnet_sock_accept(&newsock, lnet_acceptor_state.pta_sock); - if (rc != 0) { + if (rc) { if (rc != -EAGAIN) { CWARN("Accept error %d: pausing...\n", rc); set_current_state(TASK_UNINTERRUPTIBLE); @@ -379,7 +379,7 @@ lnet_acceptor(void *arg) } rc = lnet_sock_getaddr(newsock, 1, &peer_ip, &peer_port); - if (rc != 0) { + if (rc) { CERROR("Can't determine new connection's address\n"); goto failed; } @@ -392,14 +392,14 @@ lnet_acceptor(void *arg) rc = lnet_sock_read(newsock, &magic, sizeof(magic), accept_timeout); - if (rc != 0) { + if (rc) { CERROR("Error %d reading connection request from %pI4h\n", rc, &peer_ip); goto failed; } rc = lnet_accept(newsock, magic); - if (rc != 0) + if (rc) goto failed; continue; @@ -446,7 +446,7 @@ lnet_acceptor_start(void) LASSERT(!lnet_acceptor_state.pta_sock); rc = lnet_acceptor_get_tunables(); - if (rc != 0) + if (rc) return rc; init_completion(&lnet_acceptor_state.pta_signal); @@ -454,7 +454,7 @@ lnet_acceptor_start(void) if (rc <= 0) return rc; - if (lnet_count_acceptor_nis() == 0) /* not required */ + if (!lnet_count_acceptor_nis()) /* not required */ return 0; rc2 = PTR_ERR(kthread_run(lnet_acceptor, diff --git a/drivers/staging/lustre/lnet/lnet/api-ni.c b/drivers/staging/lustre/lnet/lnet/api-ni.c index eb04958be99b..58b30f1d4ac1 100644 --- a/drivers/staging/lustre/lnet/lnet/api-ni.c +++ b/drivers/staging/lustre/lnet/lnet/api-ni.c @@ -76,17 +76,17 @@ lnet_get_networks(void) char *nets; int rc; - if (*networks != 0 && *ip2nets != 0) { + if (*networks && *ip2nets) { LCONSOLE_ERROR_MSG(0x101, "Please specify EITHER 'networks' or 'ip2nets' but not both at once\n"); return NULL; } - if (*ip2nets != 0) { + if (*ip2nets) { rc = lnet_parse_ip2nets(&nets, ip2nets); - return (rc == 0) ? nets : NULL; + return !rc ? nets : NULL; } - if (*networks != 0) + if (*networks) return networks; return "tcp"; @@ -309,7 +309,7 @@ lnet_unregister_lnd(lnd_t *lnd) LASSERT(the_lnet.ln_init); LASSERT(lnet_find_lnd_by_type(lnd->lnd_type) == lnd); - LASSERT(lnd->lnd_refcount == 0); + LASSERT(!lnd->lnd_refcount); list_del(&lnd->lnd_list); CDEBUG(D_NET, "%s LND unregistered\n", libcfs_lnd2str(lnd->lnd_type)); @@ -379,7 +379,7 @@ lnet_res_container_cleanup(struct lnet_res_container *rec) { int count = 0; - if (rec->rec_type == 0) /* not set yet, it's uninitialized */ + if (!rec->rec_type) /* not set yet, it's uninitialized */ return; while (!list_empty(&rec->rec_active)) { @@ -423,7 +423,7 @@ lnet_res_container_setup(struct lnet_res_container *rec, int cpt, int type) int rc = 0; int i; - LASSERT(rec->rec_type == 0); + LASSERT(!rec->rec_type); rec->rec_type = type; INIT_LIST_HEAD(&rec->rec_active); @@ -478,7 +478,7 @@ lnet_res_containers_create(int type) cfs_percpt_for_each(rec, i, recs) { rc = lnet_res_container_setup(rec, i, type); - if (rc != 0) { + if (rc) { lnet_res_containers_destroy(recs); return NULL; } @@ -533,11 +533,11 @@ lnet_prepare(lnet_pid_t requested_pid) struct lnet_res_container **recs; int rc = 0; - LASSERT(the_lnet.ln_refcount == 0); + LASSERT(!the_lnet.ln_refcount); the_lnet.ln_routing = 0; - LASSERT((requested_pid & LNET_PID_USERFLAG) == 0); + LASSERT(!(requested_pid & LNET_PID_USERFLAG)); the_lnet.ln_pid = requested_pid; INIT_LIST_HEAD(&the_lnet.ln_test_peers); @@ -547,7 +547,7 @@ lnet_prepare(lnet_pid_t requested_pid) INIT_LIST_HEAD(&the_lnet.ln_routers); rc = lnet_create_remote_nets_table(); - if (rc != 0) + if (rc) goto failed; /* * NB the interface cookie in wire handles guards against delayed @@ -564,16 +564,16 @@ lnet_prepare(lnet_pid_t requested_pid) } rc = lnet_peer_tables_create(); - if (rc != 0) + if (rc) goto failed; rc = lnet_msg_containers_create(); - if (rc != 0) + if (rc) goto failed; rc = lnet_res_container_setup(&the_lnet.ln_eq_container, 0, LNET_COOKIE_TYPE_EQ); - if (rc != 0) + if (rc) goto failed; recs = lnet_res_containers_create(LNET_COOKIE_TYPE_ME); @@ -593,7 +593,7 @@ lnet_prepare(lnet_pid_t requested_pid) the_lnet.ln_md_containers = recs; rc = lnet_portals_create(); - if (rc != 0) { + if (rc) { CERROR("Failed to create portals for LNet: %d\n", rc); goto failed; } @@ -616,7 +616,7 @@ lnet_unprepare(void) */ lnet_fail_nid(LNET_NID_ANY, 0); - LASSERT(the_lnet.ln_refcount == 0); + LASSERT(!the_lnet.ln_refcount); LASSERT(list_empty(&the_lnet.ln_test_peers)); LASSERT(list_empty(&the_lnet.ln_nis)); LASSERT(list_empty(&the_lnet.ln_nis_cpt)); @@ -847,7 +847,7 @@ lnet_shutdown_lndnis(void) /* All quiet on the API front */ LASSERT(!the_lnet.ln_shutdown); - LASSERT(the_lnet.ln_refcount == 0); + LASSERT(!the_lnet.ln_refcount); LASSERT(list_empty(&the_lnet.ln_nis_zombie)); lnet_net_lock(LNET_LOCK_EX); @@ -908,7 +908,7 @@ lnet_shutdown_lndnis(void) lnet_ni_t, ni_list); list_del_init(&ni->ni_list); cfs_percpt_for_each(ref, j, ni->ni_refs) { - if (*ref == 0) + if (!*ref) continue; /* still busy, add it back to zombie list */ list_add(&ni->ni_list, &the_lnet.ln_nis_zombie); @@ -979,7 +979,7 @@ lnet_startup_lndnis(void) goto failed; rc = lnet_parse_networks(&nilist, nets); - if (rc != 0) + if (rc) goto failed; while (!list_empty(&nilist)) { @@ -1026,7 +1026,7 @@ lnet_startup_lndnis(void) mutex_unlock(&the_lnet.ln_lnd_mutex); - if (rc != 0) { + if (rc) { LCONSOLE_ERROR_MSG(0x105, "Error %d starting up LNI %s\n", rc, libcfs_lnd2str(lnd->lnd_type)); lnet_net_lock(LNET_LOCK_EX); @@ -1058,11 +1058,10 @@ lnet_startup_lndnis(void) continue; } - if (ni->ni_peertxcredits == 0 || - ni->ni_maxtxcredits == 0) { + if (!ni->ni_peertxcredits || !ni->ni_maxtxcredits) { LCONSOLE_ERROR_MSG(0x107, "LNI %s has no %scredits\n", libcfs_lnd2str(lnd->lnd_type), - ni->ni_peertxcredits == 0 ? + !ni->ni_peertxcredits ? "" : "per-peer "); goto failed; } @@ -1138,7 +1137,7 @@ lnet_init(void) the_lnet.ln_cpt_bits++; rc = lnet_create_locks(); - if (rc != 0) { + if (rc) { CERROR("Can't create LNet global locks: %d\n", rc); return -1; } @@ -1184,7 +1183,7 @@ void lnet_fini(void) { LASSERT(the_lnet.ln_init); - LASSERT(the_lnet.ln_refcount == 0); + LASSERT(!the_lnet.ln_refcount); while (!list_empty(&the_lnet.ln_lnds)) lnet_unregister_lnd(list_entry(the_lnet.ln_lnds.next, @@ -1233,27 +1232,27 @@ LNetNIInit(lnet_pid_t requested_pid) } rc = lnet_prepare(requested_pid); - if (rc != 0) + if (rc) goto failed0; rc = lnet_startup_lndnis(); - if (rc != 0) + if (rc) goto failed1; rc = lnet_parse_routes(lnet_get_routes(), &im_a_router); - if (rc != 0) + if (rc) goto failed2; rc = lnet_check_routes(); - if (rc != 0) + if (rc) goto failed2; rc = lnet_rtrpools_alloc(im_a_router); - if (rc != 0) + if (rc) goto failed2; rc = lnet_acceptor_start(); - if (rc != 0) + if (rc) goto failed2; the_lnet.ln_refcount = 1; @@ -1264,11 +1263,11 @@ LNetNIInit(lnet_pid_t requested_pid) * lnet_router_checker -> lnet_update_ni_status_locked */ rc = lnet_ping_target_init(); - if (rc != 0) + if (rc) goto failed3; rc = lnet_router_checker_start(); - if (rc != 0) + if (rc) goto failed4; lnet_router_debugfs_init(); @@ -1360,7 +1359,7 @@ LNetCtl(unsigned int cmd, void *arg) case IOC_LIBCFS_ADD_ROUTE: rc = lnet_add_route(data->ioc_net, data->ioc_count, data->ioc_nid, data->ioc_priority); - return (rc != 0) ? rc : lnet_check_routes(); + return (rc) ? rc : lnet_check_routes(); case IOC_LIBCFS_DEL_ROUTE: return lnet_del_route(data->ioc_net, data->ioc_nid); @@ -1445,13 +1444,13 @@ LNetGetId(unsigned int index, lnet_process_id_t *id) LASSERT(the_lnet.ln_init); /* LNetNI initilization failed? */ - if (the_lnet.ln_refcount == 0) + if (!the_lnet.ln_refcount) return rc; cpt = lnet_net_lock_current(); list_for_each(tmp, &the_lnet.ln_nis) { - if (index-- != 0) + if (index--) continue; ni = list_entry(tmp, lnet_ni_t, ni_list); @@ -1494,7 +1493,7 @@ lnet_create_ping_info(void) if (rc == -ENOENT) break; - LASSERT(rc == 0); + LASSERT(!rc); } infosz = offsetof(lnet_ping_info_t, pi_ni[n]); @@ -1513,7 +1512,7 @@ lnet_create_ping_info(void) lnet_ni_status_t *ns = &pinfo->pi_ni[i]; rc = LNetGetId(i, &id); - LASSERT(rc == 0); + LASSERT(!rc); ns->ns_nid = id.nid; ns->ns_status = LNET_NI_STATUS_UP; @@ -1568,7 +1567,7 @@ lnet_ping_target_init(void) int infosz; rc = lnet_create_ping_info(); - if (rc != 0) + if (rc) return rc; /* @@ -1576,7 +1575,7 @@ lnet_ping_target_init(void) * teardown, which by definition is the last one! */ rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &the_lnet.ln_ping_target_eq); - if (rc != 0) { + if (rc) { CERROR("Can't allocate ping EQ: %d\n", rc); goto failed_0; } @@ -1589,7 +1588,7 @@ lnet_ping_target_init(void) LNET_PROTO_PING_MATCHBITS, 0, LNET_UNLINK, LNET_INS_AFTER, &meh); - if (rc != 0) { + if (rc) { CERROR("Can't create ping ME: %d\n", rc); goto failed_1; } @@ -1609,7 +1608,7 @@ lnet_ping_target_init(void) rc = LNetMDAttach(meh, md, LNET_RETAIN, &the_lnet.ln_ping_target_md); - if (rc != 0) { + if (rc) { CERROR("Can't attach ping MD: %d\n", rc); goto failed_2; } @@ -1618,10 +1617,10 @@ lnet_ping_target_init(void) failed_2: rc2 = LNetMEUnlink(meh); - LASSERT(rc2 == 0); + LASSERT(!rc2); failed_1: rc2 = LNetEQFree(the_lnet.ln_ping_target_eq); - LASSERT(rc2 == 0); + LASSERT(!rc2); failed_0: lnet_destroy_ping_info(); return rc; @@ -1646,7 +1645,7 @@ lnet_ping_target_fini(void) /* I expect overflow... */ LASSERT(rc >= 0 || rc == -EOVERFLOW); - if (rc == 0) { + if (!rc) { /* timed out: provide a diagnostic */ CWARN("Still waiting for ping MD to unlink\n"); timeout_ms *= 2; @@ -1659,7 +1658,7 @@ lnet_ping_target_fini(void) } rc = LNetEQFree(the_lnet.ln_ping_target_eq); - LASSERT(rc == 0); + LASSERT(!rc); lnet_destroy_ping_info(); cfs_restore_sigs(blocked); } @@ -1699,7 +1698,7 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, /* NB 2 events max (including any unlink event) */ rc = LNetEQAlloc(2, LNET_EQ_HANDLER_NONE, &eqh); - if (rc != 0) { + if (rc) { CERROR("Can't allocate EQ: %d\n", rc); goto out_0; } @@ -1714,7 +1713,7 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, md.eq_handle = eqh; rc = LNetMDBind(md, LNET_UNLINK, &mdh); - if (rc != 0) { + if (rc) { CERROR("Can't bind MD: %d\n", rc); goto out_1; } @@ -1723,11 +1722,11 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, LNET_RESERVED_PORTAL, LNET_PROTO_PING_MATCHBITS, 0); - if (rc != 0) { + if (rc) { /* Don't CERROR; this could be deliberate! */ rc2 = LNetMDUnlink(mdh); - LASSERT(rc2 == 0); + LASSERT(!rc2); /* NB must wait for the UNLINK event below... */ unlinked = 1; @@ -1751,11 +1750,11 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, LASSERT(rc2 != -EOVERFLOW); /* can't miss anything */ - if (rc2 <= 0 || event.status != 0) { + if (rc2 <= 0 || event.status) { /* timeout or error */ - if (!replied && rc == 0) + if (!replied && !rc) rc = (rc2 < 0) ? rc2 : - (rc2 == 0) ? -ETIMEDOUT : + !rc2 ? -ETIMEDOUT : event.status; if (!unlinked) { @@ -1764,7 +1763,7 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, /* No assertion (racing with network) */ unlinked = 1; timeout_ms = a_long_time; - } else if (rc2 == 0) { + } else if (!rc2) { /* timed out waiting for unlink */ CWARN("ping %s: late network completion\n", libcfs_id2str(id)); @@ -1804,7 +1803,7 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, goto out_1; } - if ((info->pi_features & LNET_PING_FEAT_NI_STATUS) == 0) { + if (!(info->pi_features & LNET_PING_FEAT_NI_STATUS)) { CERROR("%s: ping w/o NI status: 0x%x\n", libcfs_id2str(id), info->pi_features); goto out_1; @@ -1838,9 +1837,9 @@ static int lnet_ping(lnet_process_id_t id, int timeout_ms, out_1: rc2 = LNetEQFree(eqh); - if (rc2 != 0) + if (rc2) CERROR("rc2 %d\n", rc2); - LASSERT(rc2 == 0); + LASSERT(!rc2); out_0: LIBCFS_FREE(info, infosz); diff --git a/drivers/staging/lustre/lnet/lnet/config.c b/drivers/staging/lustre/lnet/lnet/config.c index fcd2cfbccefd..e817eb3a91e9 100644 --- a/drivers/staging/lustre/lnet/lnet/config.c +++ b/drivers/staging/lustre/lnet/lnet/config.c @@ -210,7 +210,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) if (!ni) goto failed; - while (str && *str != 0) { + while (str && *str) { char *comma = strchr(str, ','); char *bracket = strchr(str, '('); char *square = strchr(str, '['); @@ -240,7 +240,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) rc = cfs_expr_list_parse(square, tmp - square + 1, 0, LNET_CPT_NUMBER - 1, &el); - if (rc != 0) { + if (rc) { tmp = square; goto failed_syntax; } @@ -309,7 +309,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) *comma++ = 0; iface = cfs_trimwhite(iface); - if (*iface == 0) { + if (!*iface) { tmp = iface; goto failed_syntax; } @@ -330,7 +330,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) if (comma) { *comma = 0; str = cfs_trimwhite(str); - if (*str != 0) { + if (*str) { tmp = str; goto failed_syntax; } @@ -339,7 +339,7 @@ lnet_parse_networks(struct list_head *nilist, char *networks) } str = cfs_trimwhite(str); - if (*str != 0) { + if (*str) { tmp = str; goto failed_syntax; } @@ -434,7 +434,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) str++; /* scan for separator or comment */ - for (sep = str; *sep != 0; sep++) + for (sep = str; *sep; sep++) if (lnet_issep(*sep) || *sep == '#') break; @@ -461,10 +461,10 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) /* scan for separator */ do { sep++; - } while (*sep != 0 && !lnet_issep(*sep)); + } while (*sep && !lnet_issep(*sep)); } - if (*sep == 0) + if (!*sep) break; str = sep + 1; @@ -539,7 +539,7 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) /* simple string enumeration */ if (lnet_expand1tb(&pending, str, sep, sep2, parsed, - (int)(enditem - parsed)) != 0) { + (int)(enditem - parsed))) { goto failed; } continue; @@ -554,7 +554,7 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) goto failed; if (hi < 0 || lo < 0 || stride < 0 || hi < lo || - (hi - lo) % stride != 0) + (hi - lo) % stride) goto failed; for (i = lo; i <= hi; i += stride) { @@ -564,7 +564,7 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) goto failed; if (lnet_expand1tb(&pending, str, sep, sep2, - num, nob) != 0) + num, nob)) goto failed; } } @@ -656,7 +656,7 @@ lnet_parse_route(char *str, int *im_a_router) /* scan for token start */ while (isspace(*sep)) sep++; - if (*sep == 0) { + if (!*sep) { if (ntokens < (got_hops ? 3 : 2)) goto token_error; break; @@ -666,9 +666,9 @@ lnet_parse_route(char *str, int *im_a_router) token = sep++; /* scan for token end */ - while (*sep != 0 && !isspace(*sep)) + while (*sep && !isspace(*sep)) sep++; - if (*sep != 0) + if (*sep) *sep++ = 0; if (ntokens == 1) { @@ -745,7 +745,7 @@ lnet_parse_route(char *str, int *im_a_router) } rc = lnet_add_route(net, hops, nid, priority); - if (rc != 0) { + if (rc) { CERROR("Can't create route to %s via %s\n", libcfs_net2str(net), libcfs_nid2str(nid)); @@ -802,7 +802,7 @@ lnet_parse_routes(char *routes, int *im_a_router) rc = lnet_parse_route_tbs(&tbs, im_a_router); } - LASSERT(lnet_tbnob == 0); + LASSERT(!lnet_tbnob); return rc; } @@ -814,7 +814,7 @@ lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip) int i; rc = cfs_ip_addr_parse(token, len, &list); - if (rc != 0) + if (rc) return rc; for (rc = i = 0; !rc && i < nip; i++) @@ -847,18 +847,18 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) /* scan for token start */ while (isspace(*sep)) sep++; - if (*sep == 0) + if (!*sep) break; token = sep++; /* scan for token end */ - while (*sep != 0 && !isspace(*sep)) + while (*sep && !isspace(*sep)) sep++; - if (*sep != 0) + if (*sep) *sep++ = 0; - if (ntokens++ == 0) { + if (!ntokens++) { net = token; continue; } @@ -872,7 +872,8 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) return rc; } - matched |= (rc != 0); + if (rc) + matched |= 1; } if (!matched) @@ -930,12 +931,12 @@ lnet_splitnets(char *source, struct list_head *nets) bracket = strchr(bracket + 1, ')'); if (!bracket || - !(bracket[1] == ',' || bracket[1] == 0)) { + !(bracket[1] == ',' || !bracket[1])) { lnet_syntax("ip2nets", source, offset2, len); return -EINVAL; } - sep = (bracket[1] == 0) ? NULL : bracket + 1; + sep = !bracket[1] ? NULL : bracket + 1; } if (sep) @@ -1002,7 +1003,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) INIT_LIST_HEAD(&raw_entries); if (lnet_str2tbs_sep(&raw_entries, ip2nets) < 0) { CERROR("Error parsing ip2nets\n"); - LASSERT(lnet_tbnob == 0); + LASSERT(!lnet_tbnob); return -EINVAL; } @@ -1026,7 +1027,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) list_del(&tb->ltb_list); - if (rc == 0) { /* no match */ + if (!rc) { /* no match */ lnet_free_text_buf(tb); continue; } @@ -1072,7 +1073,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) list_add_tail(&tb->ltb_list, &matched_nets); len += snprintf(networks + len, sizeof(networks) - len, - "%s%s", (len == 0) ? "" : ",", + "%s%s", !len ? "" : ",", tb->ltb_text); if (len >= sizeof(networks)) { @@ -1089,7 +1090,7 @@ lnet_match_networks(char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) lnet_free_text_bufs(&raw_entries); lnet_free_text_bufs(&matched_nets); lnet_free_text_bufs(¤t_nets); - LASSERT(lnet_tbnob == 0); + LASSERT(!lnet_tbnob); if (rc < 0) return rc; @@ -1126,7 +1127,7 @@ lnet_ipaddr_enumerate(__u32 **ipaddrsp) continue; rc = lnet_ipif_query(ifnames[i], &up, &ipaddrs[nip], &netmask); - if (rc != 0) { + if (rc) { CWARN("Can't query interface %s: %d\n", ifnames[i], rc); continue; @@ -1177,7 +1178,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets) return nip; } - if (nip == 0) { + if (!nip) { LCONSOLE_ERROR_MSG(0x118, "No local IP interfaces for ip2nets to match\n"); return -ENOENT; @@ -1191,7 +1192,7 @@ lnet_parse_ip2nets(char **networksp, char *ip2nets) return rc; } - if (rc == 0) { + if (!rc) { LCONSOLE_ERROR_MSG(0x11a, "ip2nets does not match any local IP interfaces\n"); return -ENOENT; diff --git a/drivers/staging/lustre/lnet/lnet/lib-eq.c b/drivers/staging/lustre/lnet/lnet/lib-eq.c index 34012e984245..b8f248e8cc57 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-eq.c +++ b/drivers/staging/lustre/lnet/lnet/lib-eq.c @@ -83,21 +83,21 @@ LNetEQAlloc(unsigned int count, lnet_eq_handler_t callback, if (count) count = roundup_pow_of_two(count); - if (callback != LNET_EQ_HANDLER_NONE && count != 0) + if (callback != LNET_EQ_HANDLER_NONE && count) CWARN("EQ callback is guaranteed to get every event, do you still want to set eqcount %d for polling event which will have locking overhead? Please contact with developer to confirm\n", count); /* * count can be 0 if only need callback, we can eliminate * overhead of enqueue event */ - if (count == 0 && callback == LNET_EQ_HANDLER_NONE) + if (!count && callback == LNET_EQ_HANDLER_NONE) return -EINVAL; eq = lnet_eq_alloc(); if (!eq) return -ENOMEM; - if (count != 0) { + if (count) { LIBCFS_ALLOC(eq->eq_events, count * sizeof(lnet_event_t)); if (!eq->eq_events) goto failed; @@ -185,7 +185,7 @@ LNetEQFree(lnet_handle_eq_t eqh) cfs_percpt_for_each(ref, i, eq->eq_refs) { LASSERT(*ref >= 0); - if (*ref == 0) + if (!*ref) continue; CDEBUG(D_NET, "Event equeue (%d: %d) busy on destroy.\n", @@ -221,7 +221,7 @@ lnet_eq_enqueue_event(lnet_eq_t *eq, lnet_event_t *ev) /* MUST called with resource lock hold but w/o lnet_eq_wait_lock */ int index; - if (eq->eq_size == 0) { + if (!eq->eq_size) { LASSERT(eq->eq_callback != LNET_EQ_HANDLER_NONE); eq->eq_callback(ev); return; @@ -321,7 +321,7 @@ __must_hold(&the_lnet.ln_eq_wait_lock) wait_queue_t wl; unsigned long now; - if (tms == 0) + if (!tms) return -1; /* don't want to wait and no new event */ init_waitqueue_entry(&wl, current); @@ -340,7 +340,7 @@ __must_hold(&the_lnet.ln_eq_wait_lock) tms = 0; } - wait = tms != 0; /* might need to call here again */ + wait = tms; /* might need to call here again */ *timeout_ms = tms; lnet_eq_wait_lock(); @@ -401,14 +401,14 @@ LNetEQPoll(lnet_handle_eq_t *eventqs, int neq, int timeout_ms, } rc = lnet_eq_dequeue_event(eq, event); - if (rc != 0) { + if (rc) { lnet_eq_wait_unlock(); *which = i; return rc; } } - if (wait == 0) + if (!wait) break; /* diff --git a/drivers/staging/lustre/lnet/lnet/lib-md.c b/drivers/staging/lustre/lnet/lnet/lib-md.c index 490edfb7cacb..f26bb03d6015 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-md.c +++ b/drivers/staging/lustre/lnet/lnet/lib-md.c @@ -46,7 +46,7 @@ void lnet_md_unlink(lnet_libmd_t *md) { - if ((md->md_flags & LNET_MD_FLAG_ZOMBIE) == 0) { + if (!(md->md_flags & LNET_MD_FLAG_ZOMBIE)) { /* first unlink attempt... */ lnet_me_t *me = md->md_me; @@ -68,7 +68,7 @@ lnet_md_unlink(lnet_libmd_t *md) lnet_res_lh_invalidate(&md->md_lh); } - if (md->md_refcount != 0) { + if (md->md_refcount) { CDEBUG(D_NET, "Queueing unlink of md %p\n", md); return; } @@ -105,8 +105,8 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_refcount = 0; lmd->md_flags = (unlink == LNET_UNLINK) ? LNET_MD_FLAG_AUTO_UNLINK : 0; - if ((umd->options & LNET_MD_IOVEC) != 0) { - if ((umd->options & LNET_MD_KIOV) != 0) /* Can't specify both */ + if (umd->options & LNET_MD_IOVEC) { + if (umd->options & LNET_MD_KIOV) /* Can't specify both */ return -EINVAL; niov = umd->length; @@ -125,12 +125,12 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_length = total_length; - if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* use max size */ + if ((umd->options & LNET_MD_MAX_SIZE) && /* use max size */ (umd->max_size < 0 || umd->max_size > total_length)) /* illegal max_size */ return -EINVAL; - } else if ((umd->options & LNET_MD_KIOV) != 0) { + } else if (umd->options & LNET_MD_KIOV) { niov = umd->length; lmd->md_niov = umd->length; memcpy(lmd->md_iov.kiov, umd->start, @@ -147,7 +147,7 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_length = total_length; - if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */ + if ((umd->options & LNET_MD_MAX_SIZE) && /* max size used */ (umd->max_size < 0 || umd->max_size > total_length)) /* illegal max_size */ return -EINVAL; @@ -158,7 +158,7 @@ lnet_md_build(lnet_libmd_t *lmd, lnet_md_t *umd, int unlink) lmd->md_iov.iov[0].iov_base = umd->start; lmd->md_iov.iov[0].iov_len = umd->length; - if ((umd->options & LNET_MD_MAX_SIZE) != 0 && /* max size used */ + if ((umd->options & LNET_MD_MAX_SIZE) && /* max size used */ (umd->max_size < 0 || umd->max_size > (int)umd->length)) /* illegal max_size */ return -EINVAL; @@ -216,8 +216,8 @@ lnet_md_deconstruct(lnet_libmd_t *lmd, lnet_md_t *umd) * and that's all. */ umd->start = lmd->md_start; - umd->length = ((lmd->md_options & - (LNET_MD_IOVEC | LNET_MD_KIOV)) == 0) ? + umd->length = !(lmd->md_options & + (LNET_MD_IOVEC | LNET_MD_KIOV)) ? lmd->md_length : lmd->md_niov; umd->threshold = lmd->md_threshold; umd->max_size = lmd->md_max_size; @@ -229,13 +229,13 @@ lnet_md_deconstruct(lnet_libmd_t *lmd, lnet_md_t *umd) static int lnet_md_validate(lnet_md_t *umd) { - if (!umd->start && umd->length != 0) { + if (!umd->start && umd->length) { CERROR("MD start pointer can not be NULL with length %u\n", umd->length); return -EINVAL; } - if ((umd->options & (LNET_MD_KIOV | LNET_MD_IOVEC)) != 0 && + if ((umd->options & (LNET_MD_KIOV | LNET_MD_IOVEC)) && umd->length > LNET_MAX_IOV) { CERROR("Invalid option: too many fragments %u, %d max\n", umd->length, LNET_MAX_IOV); @@ -284,10 +284,10 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); - if (lnet_md_validate(&umd) != 0) + if (lnet_md_validate(&umd)) return -EINVAL; - if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) == 0) { + if (!(umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT))) { CERROR("Invalid option: no MD_OP set\n"); return -EINVAL; } @@ -300,7 +300,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, cpt = lnet_cpt_of_cookie(meh.cookie); lnet_res_lock(cpt); - if (rc != 0) + if (rc) goto failed; me = lnet_handle2me(&meh); @@ -311,7 +311,7 @@ LNetMDAttach(lnet_handle_me_t meh, lnet_md_t umd, else rc = lnet_md_link(md, umd.eq_handle, cpt); - if (rc != 0) + if (rc) goto failed; /* @@ -363,10 +363,10 @@ LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle) LASSERT(the_lnet.ln_init); LASSERT(the_lnet.ln_refcount > 0); - if (lnet_md_validate(&umd) != 0) + if (lnet_md_validate(&umd)) return -EINVAL; - if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT)) != 0) { + if ((umd.options & (LNET_MD_OP_GET | LNET_MD_OP_PUT))) { CERROR("Invalid option: GET|PUT illegal on active MDs\n"); return -EINVAL; } @@ -378,11 +378,11 @@ LNetMDBind(lnet_md_t umd, lnet_unlink_t unlink, lnet_handle_md_t *handle) rc = lnet_md_build(md, &umd, unlink); cpt = lnet_res_lock_current(); - if (rc != 0) + if (rc) goto failed; rc = lnet_md_link(md, umd.eq_handle, cpt); - if (rc != 0) + if (rc) goto failed; lnet_md2handle(handle, md); @@ -453,7 +453,7 @@ LNetMDUnlink(lnet_handle_md_t mdh) * when the LND is done, the completion event flags that the MD was * unlinked. Otherwise, we enqueue an event now... */ - if (md->md_eq && md->md_refcount == 0) { + if (md->md_eq && !md->md_refcount) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); } diff --git a/drivers/staging/lustre/lnet/lnet/lib-me.c b/drivers/staging/lustre/lnet/lnet/lib-me.c index ab17bdb64071..3c59c889496a 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-me.c +++ b/drivers/staging/lustre/lnet/lnet/lib-me.c @@ -109,7 +109,7 @@ LNetMEAttach(unsigned int portal, lnet_res_lh_initialize(the_lnet.ln_me_containers[mtable->mt_cpt], &me->me_lh); - if (ignore_bits != 0) + if (ignore_bits) head = &mtable->mt_mhash[LNET_MT_HASH_IGNORE]; else head = lnet_mt_match_head(mtable, match_id, match_bits); @@ -248,7 +248,7 @@ LNetMEUnlink(lnet_handle_me_t meh) md = me->me_md; if (md) { md->md_flags |= LNET_MD_FLAG_ABORTED; - if (md->md_eq && md->md_refcount == 0) { + if (md->md_eq && !md->md_refcount) { lnet_build_unlink_event(md, &ev); lnet_eq_enqueue_event(md->md_eq, &ev); } diff --git a/drivers/staging/lustre/lnet/lnet/lib-move.c b/drivers/staging/lustre/lnet/lnet/lib-move.c index 5e8a6ab6da62..8f1691386955 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-move.c +++ b/drivers/staging/lustre/lnet/lnet/lib-move.c @@ -57,7 +57,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) LASSERT(the_lnet.ln_init); /* NB: use lnet_net_lock(0) to serialize operations on test peers */ - if (threshold != 0) { + if (threshold) { /* Adding a new entry */ LIBCFS_ALLOC(tp, sizeof(*tp)); if (!tp) @@ -80,7 +80,7 @@ lnet_fail_nid(lnet_nid_t nid, unsigned int threshold) list_for_each_safe(el, next, &the_lnet.ln_test_peers) { tp = list_entry(el, lnet_test_peer_t, tp_list); - if (tp->tp_threshold == 0 || /* needs culling anyway */ + if (!tp->tp_threshold || /* needs culling anyway */ nid == LNET_NID_ANY || /* removing all entries */ tp->tp_nid == nid) { /* matched this one */ list_del(&tp->tp_list); @@ -116,7 +116,7 @@ fail_peer(lnet_nid_t nid, int outgoing) list_for_each_safe(el, next, &the_lnet.ln_test_peers) { tp = list_entry(el, lnet_test_peer_t, tp_list); - if (tp->tp_threshold == 0) { + if (!tp->tp_threshold) { /* zombie entry */ if (outgoing) { /* @@ -137,7 +137,7 @@ fail_peer(lnet_nid_t nid, int outgoing) if (tp->tp_threshold != LNET_MD_THRESH_INF) { tp->tp_threshold--; if (outgoing && - tp->tp_threshold == 0) { + !tp->tp_threshold) { /* see above */ list_del(&tp->tp_list); list_add(&tp->tp_list, &cull); @@ -179,7 +179,7 @@ lnet_copy_iov2iov(unsigned int ndiov, struct kvec *diov, unsigned int doffset, /* NB diov, siov are READ-ONLY */ unsigned int this_nob; - if (nob == 0) + if (!nob) return; /* skip complete frags before 'doffset' */ @@ -243,7 +243,7 @@ lnet_extract_iov(int dst_niov, struct kvec *dst, unsigned int frag_len; unsigned int niov; - if (len == 0) /* no data => */ + if (!len) /* no data => */ return 0; /* no frags */ LASSERT(src_niov > 0); @@ -301,7 +301,7 @@ lnet_copy_kiov2kiov(unsigned int ndiov, lnet_kiov_t *diov, unsigned int doffset, char *daddr = NULL; char *saddr = NULL; - if (nob == 0) + if (!nob) return; LASSERT(!in_interrupt()); @@ -383,7 +383,7 @@ lnet_copy_kiov2iov(unsigned int niov, struct kvec *iov, unsigned int iovoffset, unsigned int this_nob; char *addr = NULL; - if (nob == 0) + if (!nob) return; LASSERT(!in_interrupt()); @@ -454,7 +454,7 @@ lnet_copy_iov2kiov(unsigned int nkiov, lnet_kiov_t *kiov, unsigned int this_nob; char *addr = NULL; - if (nob == 0) + if (!nob) return; LASSERT(!in_interrupt()); @@ -527,7 +527,7 @@ lnet_extract_kiov(int dst_niov, lnet_kiov_t *dst, unsigned int frag_len; unsigned int niov; - if (len == 0) /* no data => */ + if (!len) /* no data => */ return 0; /* no frags */ LASSERT(src_niov > 0); @@ -577,7 +577,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, int rc; LASSERT(!in_interrupt()); - LASSERT(mlen == 0 || msg); + LASSERT(!mlen || msg); if (msg) { LASSERT(msg->msg_receiving); @@ -589,7 +589,7 @@ lnet_ni_recv(lnet_ni_t *ni, void *private, lnet_msg_t *msg, int delayed, msg->msg_receiving = 0; - if (mlen != 0) { + if (mlen) { niov = msg->msg_niov; iov = msg->msg_iov; kiov = msg->msg_kiov; @@ -613,12 +613,12 @@ lnet_setpayloadbuffer(lnet_msg_t *msg) LASSERT(msg->msg_len > 0); LASSERT(!msg->msg_routing); LASSERT(md); - LASSERT(msg->msg_niov == 0); + LASSERT(!msg->msg_niov); LASSERT(!msg->msg_iov); LASSERT(!msg->msg_kiov); msg->msg_niov = md->md_niov; - if ((md->md_options & LNET_MD_KIOV) != 0) + if (md->md_options & LNET_MD_KIOV) msg->msg_kiov = md->md_iov.kiov; else msg->msg_iov = md->md_iov.iov; @@ -633,7 +633,7 @@ lnet_prep_send(lnet_msg_t *msg, int type, lnet_process_id_t target, msg->msg_len = len; msg->msg_offset = offset; - if (len != 0) + if (len) lnet_setpayloadbuffer(msg); memset(&msg->msg_hdr, 0, sizeof(msg->msg_hdr)); @@ -673,7 +673,7 @@ lnet_ni_eager_recv(lnet_ni_t *ni, lnet_msg_t *msg) msg->msg_rx_ready_delay = 1; rc = ni->ni_lnd->lnd_eager_recv(ni, msg->msg_private, msg, &msg->msg_private); - if (rc != 0) { + if (rc) { CERROR("recv from %s / send to %s aborted: eager_recv failed %d\n", libcfs_nid2str(msg->msg_rxpeer->lp_nid), libcfs_id2str(msg->msg_target), rc); @@ -698,7 +698,7 @@ lnet_ni_query_locked(lnet_ni_t *ni, lnet_peer_t *lp) lp->lp_last_query = cfs_time_current(); - if (last_alive != 0) /* NI has updated timestamp */ + if (last_alive) /* NI has updated timestamp */ lp->lp_last_alive = last_alive; } @@ -727,7 +727,7 @@ lnet_peer_is_alive(lnet_peer_t *lp, unsigned long now) * case, and moreover lp_last_alive at peer creation is assumed. */ if (alive && !lp->lp_alive && - !(lnet_isrouter(lp) && lp->lp_alive_count == 0)) + !(lnet_isrouter(lp) && !lp->lp_alive_count)) lnet_notify_locked(lp, 0, 1, lp->lp_last_alive); return alive; @@ -752,7 +752,7 @@ lnet_peer_alive_locked(lnet_peer_t *lp) * Peer appears dead, but we should avoid frequent NI queries (at * most once per lnet_queryinterval seconds). */ - if (lp->lp_last_query != 0) { + if (lp->lp_last_query) { static const int lnet_queryinterval = 1; unsigned long next_query = @@ -805,8 +805,8 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) LASSERT(msg->msg_tx_committed); /* NB 'lp' is always the next hop */ - if ((msg->msg_target.pid & LNET_PID_USERFLAG) == 0 && - lnet_peer_alive_locked(lp) == 0) { + if (!(msg->msg_target.pid & LNET_PID_USERFLAG) && + !lnet_peer_alive_locked(lp)) { the_lnet.ln_counters[cpt]->drop_count++; the_lnet.ln_counters[cpt]->drop_length += msg->msg_len; lnet_net_unlock(cpt); @@ -821,7 +821,7 @@ lnet_post_send_locked(lnet_msg_t *msg, int do_send) } if (msg->msg_md && - (msg->msg_md->md_flags & LNET_MD_FLAG_ABORTED) != 0) { + (msg->msg_md->md_flags & LNET_MD_FLAG_ABORTED)) { lnet_net_unlock(cpt); CNETERR("Aborting message for %s: LNetM[DE]Unlink() already called on the MD/ME.\n", @@ -910,7 +910,7 @@ lnet_post_routed_recv_locked(lnet_msg_t *msg, int do_recv) LASSERT(!msg->msg_iov); LASSERT(!msg->msg_kiov); - LASSERT(msg->msg_niov == 0); + LASSERT(!msg->msg_niov); LASSERT(msg->msg_routing); LASSERT(msg->msg_receiving); LASSERT(!msg->msg_sending); @@ -1157,8 +1157,8 @@ lnet_find_route_locked(lnet_ni_t *ni, lnet_nid_t target, lnet_nid_t rtr_nid) lp = rtr->lr_gateway; if (!lp->lp_alive || /* gateway is down */ - ((lp->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0 && - rtr->lr_downis != 0)) /* NI to target is down */ + ((lp->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) && + rtr->lr_downis)) /* NI to target is down */ continue; if (ni && lp->lp_ni != ni) @@ -1283,7 +1283,7 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) rc = lnet_nid2peer_locked(&lp, dst_nid, cpt); /* lp has ref on src_ni; lose mine */ lnet_ni_decref_locked(src_ni, cpt); - if (rc != 0) { + if (rc) { lnet_net_unlock(cpt); LCONSOLE_WARN("Error %d finding peer %s\n", rc, libcfs_nid2str(dst_nid)); @@ -1365,10 +1365,10 @@ lnet_send(lnet_nid_t src_nid, lnet_msg_t *msg, lnet_nid_t rtr_nid) if (rc == EHOSTUNREACH || rc == ECANCELED) return -rc; - if (rc == 0) + if (!rc) lnet_ni_send(src_ni, msg); - return 0; /* rc == 0 or EAGAIN */ + return 0; /* !rc or EAGAIN */ } static void @@ -1387,7 +1387,7 @@ lnet_recv_put(lnet_ni_t *ni, lnet_msg_t *msg) { lnet_hdr_t *hdr = &msg->msg_hdr; - if (msg->msg_wanted != 0) + if (msg->msg_wanted) lnet_setpayloadbuffer(msg); lnet_build_msg_event(msg, LNET_EVENT_PUT); @@ -1396,8 +1396,8 @@ lnet_recv_put(lnet_ni_t *ni, lnet_msg_t *msg) * Must I ACK? If so I'll grab the ack_wmd out of the header and put * it back into the ACK during lnet_finalize() */ - msg->msg_ack = (!lnet_is_wire_handle_none(&hdr->msg.put.ack_wmd) && - (msg->msg_md->md_options & LNET_MD_ACK_DISABLE) == 0); + msg->msg_ack = !lnet_is_wire_handle_none(&hdr->msg.put.ack_wmd) && + !(msg->msg_md->md_options & LNET_MD_ACK_DISABLE); lnet_ni_recv(ni, msg->msg_private, msg, msg->msg_rx_delayed, msg->msg_offset, msg->msg_wanted, hdr->payload_length); @@ -1440,7 +1440,7 @@ lnet_parse_put(lnet_ni_t *ni, lnet_msg_t *msg) return 0; rc = lnet_ni_eager_recv(ni, msg); - if (rc == 0) + if (!rc) goto again; /* fall through */ @@ -1536,7 +1536,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) /* NB handles only looked up by creator (no flips) */ md = lnet_wire_handle2md(&hdr->msg.reply.dst_wmd); - if (!md || md->md_threshold == 0 || md->md_me) { + if (!md || !md->md_threshold || md->md_me) { CNETERR("%s: Dropping REPLY from %s for %s MD %#llx.%#llx\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), !md ? "invalid" : "inactive", @@ -1550,13 +1550,13 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) return ENOENT; /* +ve: OK but no match */ } - LASSERT(md->md_offset == 0); + LASSERT(!md->md_offset); rlength = hdr->payload_length; mlength = min_t(uint, rlength, md->md_length); if (mlength < rlength && - (md->md_options & LNET_MD_TRUNCATE) == 0) { + !(md->md_options & LNET_MD_TRUNCATE)) { CNETERR("%s: Dropping REPLY from %s length %d for MD %#llx would overflow (%d)\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(src), rlength, hdr->msg.reply.dst_wmd.wh_object_cookie, @@ -1571,7 +1571,7 @@ lnet_parse_reply(lnet_ni_t *ni, lnet_msg_t *msg) lnet_msg_attach_md(msg, md, 0, mlength); - if (mlength != 0) + if (mlength) lnet_setpayloadbuffer(msg); lnet_res_unlock(cpt); @@ -1602,7 +1602,7 @@ lnet_parse_ack(lnet_ni_t *ni, lnet_msg_t *msg) /* NB handles only looked up by creator (no flips) */ md = lnet_wire_handle2md(&hdr->msg.ack.dst_wmd); - if (!md || md->md_threshold == 0 || md->md_me) { + if (!md || !md->md_threshold || md->md_me) { /* Don't moan; this is expected */ CDEBUG(D_NET, "%s: Dropping ACK from %s to %s MD %#llx.%#llx\n", @@ -1648,7 +1648,7 @@ lnet_parse_forward_locked(lnet_ni_t *ni, lnet_msg_t *msg) } } - if (rc == 0) + if (!rc) rc = lnet_post_routed_recv_locked(msg, 0); return rc; } @@ -1893,7 +1893,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, lnet_net_lock(cpt); rc = lnet_nid2peer_locked(&msg->msg_rxpeer, from_nid, cpt); - if (rc != 0) { + if (rc) { lnet_net_unlock(cpt); CERROR("%s, src %s: Dropping %s (error %d looking up sender)\n", libcfs_nid2str(from_nid), libcfs_nid2str(src_nid), @@ -1923,7 +1923,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, if (rc < 0) goto free_drop; - if (rc == 0) { + if (!rc) { lnet_ni_recv(ni, msg->msg_private, msg, 0, 0, payload_length, payload_length); } @@ -1951,7 +1951,7 @@ lnet_parse(lnet_ni_t *ni, lnet_hdr_t *hdr, lnet_nid_t from_nid, goto free_drop; /* prevent an unused label if !kernel */ } - if (rc == 0) + if (!rc) return 0; LASSERT(rc == ENOENT); @@ -2117,7 +2117,7 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (!md || md->md_threshold == 0 || md->md_me) { + if (!md || !md->md_threshold || md->md_me) { CERROR("Dropping PUT (%llu:%d:%s): MD (%d) invalid\n", match_bits, portal, libcfs_id2str(target), !md ? -1 : md->md_threshold); @@ -2159,7 +2159,7 @@ LNetPut(lnet_nid_t self, lnet_handle_md_t mdh, lnet_ack_req_t ack, lnet_build_msg_event(msg, LNET_EVENT_SEND); rc = lnet_send(self, msg, LNET_NID_ANY); - if (rc != 0) { + if (rc) { CNETERR("Error sending PUT to %s: %d\n", libcfs_id2str(target), rc); lnet_finalize(NULL, msg, rc); @@ -2200,7 +2200,7 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) goto drop; } - if (getmd->md_threshold == 0) { + if (!getmd->md_threshold) { CERROR("%s: Dropping REPLY from %s for inactive MD %p\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), getmd); @@ -2208,7 +2208,7 @@ lnet_create_reply_msg(lnet_ni_t *ni, lnet_msg_t *getmsg) goto drop; } - LASSERT(getmd->md_offset == 0); + LASSERT(!getmd->md_offset); CDEBUG(D_NET, "%s: Reply from %s md %p\n", libcfs_nid2str(ni->ni_nid), libcfs_id2str(peer_id), getmd); @@ -2321,7 +2321,7 @@ LNetGet(lnet_nid_t self, lnet_handle_md_t mdh, lnet_res_lock(cpt); md = lnet_handle2md(&mdh); - if (!md || md->md_threshold == 0 || md->md_me) { + if (!md || !md->md_threshold || md->md_me) { CERROR("Dropping GET (%llu:%d:%s): MD (%d) invalid\n", match_bits, portal, libcfs_id2str(target), !md ? -1 : md->md_threshold); diff --git a/drivers/staging/lustre/lnet/lnet/lib-msg.c b/drivers/staging/lustre/lnet/lnet/lib-msg.c index 5ee390cf51ad..749e76a62f95 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-msg.c +++ b/drivers/staging/lustre/lnet/lnet/lib-msg.c @@ -172,7 +172,7 @@ lnet_msg_decommit_tx(lnet_msg_t *msg, int status) lnet_event_t *ev = &msg->msg_ev; LASSERT(msg->msg_tx_committed); - if (status != 0) + if (status) goto out; counters = the_lnet.ln_counters[msg->msg_tx_cpt]; @@ -180,7 +180,7 @@ lnet_msg_decommit_tx(lnet_msg_t *msg, int status) default: /* routed message */ LASSERT(msg->msg_routing); LASSERT(msg->msg_rx_committed); - LASSERT(ev->type == 0); + LASSERT(!ev->type); counters->route_length += msg->msg_len; counters->route_count++; @@ -226,13 +226,13 @@ lnet_msg_decommit_rx(lnet_msg_t *msg, int status) LASSERT(!msg->msg_tx_committed); /* decommitted or never committed */ LASSERT(msg->msg_rx_committed); - if (status != 0) + if (status) goto out; counters = the_lnet.ln_counters[msg->msg_rx_cpt]; switch (ev->type) { default: - LASSERT(ev->type == 0); + LASSERT(!ev->type); LASSERT(msg->msg_routing); goto out; @@ -371,7 +371,7 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) LASSERT(msg->msg_onactivelist); - if (status == 0 && msg->msg_ack) { + if (!status && msg->msg_ack) { /* Only send an ACK if the PUT completed successfully */ lnet_msg_decommit(msg, cpt, 0); @@ -410,7 +410,7 @@ lnet_complete_msg_locked(lnet_msg_t *msg, int cpt) */ return rc; - } else if (status == 0 && /* OK so far */ + } else if (!status && /* OK so far */ (msg->msg_routing && !msg->msg_sending)) { /* not forwarded */ LASSERT(!msg->msg_receiving); /* called back recv already */ @@ -531,14 +531,14 @@ lnet_finalize(lnet_ni_t *ni, lnet_msg_t *msg, int status) * anything, so my finalizing friends can chomp along too */ rc = lnet_complete_msg_locked(msg, cpt); - if (rc != 0) + if (rc) break; } container->msc_finalizers[my_slot] = NULL; lnet_net_unlock(cpt); - if (rc != 0) + if (rc) goto again; } EXPORT_SYMBOL(lnet_finalize); @@ -548,7 +548,7 @@ lnet_msg_container_cleanup(struct lnet_msg_container *container) { int count = 0; - if (container->msc_init == 0) + if (!container->msc_init) return; while (!list_empty(&container->msc_active)) { @@ -592,7 +592,7 @@ lnet_msg_container_setup(struct lnet_msg_container *container, int cpt) rc = lnet_freelist_init(&container->msc_freelist, LNET_FL_MAX_MSGS, sizeof(lnet_msg_t)); - if (rc != 0) { + if (rc) { CERROR("Failed to init freelist for message container\n"); lnet_msg_container_cleanup(container); return rc; @@ -649,7 +649,7 @@ lnet_msg_containers_create(void) cfs_percpt_for_each(container, i, the_lnet.ln_msg_containers) { rc = lnet_msg_container_setup(container, i); - if (rc != 0) { + if (rc) { lnet_msg_containers_destroy(); return rc; } diff --git a/drivers/staging/lustre/lnet/lnet/lib-ptl.c b/drivers/staging/lustre/lnet/lnet/lib-ptl.c index aca47de2ce5a..0cdeea96f0b1 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-ptl.c +++ b/drivers/staging/lustre/lnet/lnet/lib-ptl.c @@ -50,7 +50,7 @@ lnet_ptl_match_type(unsigned int index, lnet_process_id_t match_id, struct lnet_portal *ptl = the_lnet.ln_portals[index]; int unique; - unique = ignore_bits == 0 && + unique = !ignore_bits && match_id.nid != LNET_NID_ANY && match_id.pid != LNET_PID_ANY; @@ -152,7 +152,7 @@ lnet_try_match_md(lnet_libmd_t *md, return LNET_MATCHMD_NONE | LNET_MATCHMD_EXHAUSTED; /* mismatched MD op */ - if ((md->md_options & info->mi_opc) == 0) + if (!(md->md_options & info->mi_opc)) return LNET_MATCHMD_NONE; /* mismatched ME nid/pid? */ @@ -165,17 +165,17 @@ lnet_try_match_md(lnet_libmd_t *md, return LNET_MATCHMD_NONE; /* mismatched ME matchbits? */ - if (((me->me_match_bits ^ info->mi_mbits) & ~me->me_ignore_bits) != 0) + if ((me->me_match_bits ^ info->mi_mbits) & ~me->me_ignore_bits) return LNET_MATCHMD_NONE; /* Hurrah! This _is_ a match; check it out... */ - if ((md->md_options & LNET_MD_MANAGE_REMOTE) == 0) + if (!(md->md_options & LNET_MD_MANAGE_REMOTE)) offset = md->md_offset; else offset = info->mi_roffset; - if ((md->md_options & LNET_MD_MAX_SIZE) != 0) { + if (md->md_options & LNET_MD_MAX_SIZE) { mlength = md->md_max_size; LASSERT(md->md_offset + mlength <= md->md_length); } else { @@ -184,7 +184,7 @@ lnet_try_match_md(lnet_libmd_t *md, if (info->mi_rlength <= mlength) { /* fits in allowed space */ mlength = info->mi_rlength; - } else if ((md->md_options & LNET_MD_TRUNCATE) == 0) { + } else if (!(md->md_options & LNET_MD_TRUNCATE)) { /* this packet _really_ is too big */ CERROR("Matching packet from %s, match %llu length %d too big: %d left, %d allowed\n", libcfs_id2str(info->mi_id), info->mi_mbits, @@ -210,7 +210,7 @@ lnet_try_match_md(lnet_libmd_t *md, * We bumped md->md_refcount above so the MD just gets flagged * for unlink when it is finalized. */ - if ((md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) != 0) + if (md->md_flags & LNET_MD_FLAG_AUTO_UNLINK) lnet_md_unlink(md); return LNET_MATCHMD_OK | LNET_MATCHMD_EXHAUSTED; @@ -304,7 +304,7 @@ lnet_mt_of_match(struct lnet_match_info *info, struct lnet_msg *msg) /* is there any active entry for this portal? */ nmaps = ptl->ptl_mt_nmaps; /* map to an active mtable to avoid heavy "stealing" */ - if (nmaps != 0) { + if (nmaps) { /* * NB: there is possibility that ptl_mt_maps is being * changed because we are not under protection of @@ -339,7 +339,7 @@ lnet_mt_test_exhausted(struct lnet_match_table *mtable, int pos) bmap = &mtable->mt_exhausted[pos >> LNET_MT_BITS_U64]; pos &= (1 << LNET_MT_BITS_U64) - 1; - return ((*bmap) & (1ULL << pos)) != 0; + return (*bmap & (1ULL << pos)); } static void @@ -405,10 +405,10 @@ lnet_mt_match_md(struct lnet_match_table *mtable, LASSERT(me == me->me_md->md_me); rc = lnet_try_match_md(me->me_md, info, msg); - if ((rc & LNET_MATCHMD_EXHAUSTED) == 0) + if (!(rc & LNET_MATCHMD_EXHAUSTED)) exhausted = 0; /* mlist is not empty */ - if ((rc & LNET_MATCHMD_FINISH) != 0) { + if (rc & LNET_MATCHMD_FINISH) { /* * don't return EXHAUSTED bit because we don't know * whether the mlist is empty or not @@ -423,7 +423,7 @@ lnet_mt_match_md(struct lnet_match_table *mtable, exhausted = 0; } - if (exhausted == 0 && head == &mtable->mt_mhash[LNET_MT_HASH_IGNORE]) { + if (!exhausted && head == &mtable->mt_mhash[LNET_MT_HASH_IGNORE]) { head = lnet_mt_match_head(mtable, info->mi_id, info->mi_mbits); goto again; /* re-check MEs w/o ignore-bits */ } @@ -490,13 +490,13 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, cpt = (first + i) % LNET_CPT_NUMBER; mtable = ptl->ptl_mtables[cpt]; - if (i != 0 && i != LNET_CPT_NUMBER - 1 && !mtable->mt_enabled) + if (i && i != LNET_CPT_NUMBER - 1 && !mtable->mt_enabled) continue; lnet_res_lock(cpt); lnet_ptl_lock(ptl); - if (i == 0) { /* the first try, attach on stealing list */ + if (!i) { /* the first try, attach on stealing list */ list_add_tail(&msg->msg_list, &ptl->ptl_msg_stealing); } @@ -504,11 +504,11 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, if (!list_empty(&msg->msg_list)) { /* on stealing list */ rc = lnet_mt_match_md(mtable, info, msg); - if ((rc & LNET_MATCHMD_EXHAUSTED) != 0 && + if ((rc & LNET_MATCHMD_EXHAUSTED) && mtable->mt_enabled) lnet_ptl_disable_mt(ptl, cpt); - if ((rc & LNET_MATCHMD_FINISH) != 0) + if (rc & LNET_MATCHMD_FINISH) list_del_init(&msg->msg_list); } else { @@ -522,7 +522,7 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, if (!list_empty(&msg->msg_list) && /* not matched yet */ (i == LNET_CPT_NUMBER - 1 || /* the last CPT */ - ptl->ptl_mt_nmaps == 0 || /* no active CPT */ + !ptl->ptl_mt_nmaps || /* no active CPT */ (ptl->ptl_mt_nmaps == 1 && /* the only active CPT */ ptl->ptl_mt_maps[0] == cpt))) { /* nothing to steal, delay or drop */ @@ -541,7 +541,7 @@ lnet_ptl_match_delay(struct lnet_portal *ptl, lnet_ptl_unlock(ptl); lnet_res_unlock(cpt); - if ((rc & LNET_MATCHMD_FINISH) != 0 || msg->msg_rx_delayed) + if ((rc & LNET_MATCHMD_FINISH) || msg->msg_rx_delayed) break; } @@ -567,7 +567,7 @@ lnet_ptl_match_md(struct lnet_match_info *info, struct lnet_msg *msg) ptl = the_lnet.ln_portals[info->mi_portal]; rc = lnet_ptl_match_early(ptl, msg); - if (rc != 0) /* matched or delayed early message */ + if (rc) /* matched or delayed early message */ return rc; mtable = lnet_mt_of_match(info, msg); @@ -579,13 +579,13 @@ lnet_ptl_match_md(struct lnet_match_info *info, struct lnet_msg *msg) } rc = lnet_mt_match_md(mtable, info, msg); - if ((rc & LNET_MATCHMD_EXHAUSTED) != 0 && mtable->mt_enabled) { + if ((rc & LNET_MATCHMD_EXHAUSTED) && mtable->mt_enabled) { lnet_ptl_lock(ptl); lnet_ptl_disable_mt(ptl, mtable->mt_cpt); lnet_ptl_unlock(ptl); } - if ((rc & LNET_MATCHMD_FINISH) != 0) /* matched or dropping */ + if (rc & LNET_MATCHMD_FINISH) /* matched or dropping */ goto out1; if (!msg->msg_rx_ready_delay) @@ -646,7 +646,7 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_libmd_t *md, int exhausted = 0; int cpt; - LASSERT(md->md_refcount == 0); /* a brand new MD */ + LASSERT(!md->md_refcount); /* a brand new MD */ me->me_md = md; md->md_me = me; @@ -680,15 +680,15 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_libmd_t *md, rc = lnet_try_match_md(md, &info, msg); - exhausted = (rc & LNET_MATCHMD_EXHAUSTED) != 0; - if ((rc & LNET_MATCHMD_NONE) != 0) { + exhausted = (rc & LNET_MATCHMD_EXHAUSTED); + if (rc & LNET_MATCHMD_NONE) { if (exhausted) break; continue; } /* Hurrah! This _is_ a match */ - LASSERT((rc & LNET_MATCHMD_FINISH) != 0); + LASSERT(rc & LNET_MATCHMD_FINISH); list_del_init(&msg->msg_list); if (head == &ptl->ptl_msg_stealing) { @@ -698,7 +698,7 @@ lnet_ptl_attach_md(lnet_me_t *me, lnet_libmd_t *md, continue; } - if ((rc & LNET_MATCHMD_OK) != 0) { + if (rc & LNET_MATCHMD_OK) { list_add_tail(&msg->msg_list, matches); CDEBUG(D_NET, "Resuming delayed PUT from %s portal %d match %llu offset %d length %d.\n", diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 0cf0645c78e3..53dd0bdcd07f 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c @@ -64,7 +64,7 @@ lnet_sock_ioctl(int cmd, unsigned long arg) int rc; rc = sock_create(PF_INET, SOCK_STREAM, 0, &sock); - if (rc != 0) { + if (rc) { CERROR("Can't create socket: %d\n", rc); return rc; } @@ -101,12 +101,12 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask) strcpy(ifr.ifr_name, name); rc = lnet_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr); - if (rc != 0) { + if (rc) { CERROR("Can't get flags for interface %s\n", name); return rc; } - if ((ifr.ifr_flags & IFF_UP) == 0) { + if (!(ifr.ifr_flags & IFF_UP)) { CDEBUG(D_NET, "Interface %s down\n", name); *up = 0; *ip = *mask = 0; @@ -117,7 +117,7 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask) strcpy(ifr.ifr_name, name); ifr.ifr_addr.sa_family = AF_INET; rc = lnet_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr); - if (rc != 0) { + if (rc) { CERROR("Can't get IP address for interface %s\n", name); return rc; } @@ -128,7 +128,7 @@ lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask) strcpy(ifr.ifr_name, name); ifr.ifr_addr.sa_family = AF_INET; rc = lnet_sock_ioctl(SIOCGIFNETMASK, (unsigned long)&ifr); - if (rc != 0) { + if (rc) { CERROR("Can't get netmask for interface %s\n", name); return rc; } @@ -181,7 +181,7 @@ lnet_ipif_enumerate(char ***namesp) goto out1; } - LASSERT(rc == 0); + LASSERT(!rc); nfound = ifc.ifc_len / sizeof(*ifr); LASSERT(nfound <= nalloc); @@ -193,7 +193,7 @@ lnet_ipif_enumerate(char ***namesp) nalloc *= 2; } - if (nfound == 0) + if (!nfound) goto out1; LIBCFS_ALLOC(names, nfound * sizeof(*names)); @@ -268,10 +268,10 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) .iov_len = nob }; struct msghdr msg = { - .msg_flags = (timeout == 0) ? MSG_DONTWAIT : 0 + .msg_flags = !timeout ? MSG_DONTWAIT : 0 }; - if (timeout != 0) { + if (timeout) { /* Set send timeout to remaining time */ tv = (struct timeval) { .tv_sec = ticks / HZ, @@ -279,7 +279,7 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) }; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); - if (rc != 0) { + if (rc) { CERROR("Can't set socket send timeout %ld.%06d: %d\n", (long)tv.tv_sec, (int)tv.tv_usec, rc); return rc; @@ -296,7 +296,7 @@ lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout) if (rc < 0) return rc; - if (rc == 0) { + if (!rc) { CERROR("Unexpected zero rc\n"); return -ECONNABORTED; } @@ -338,7 +338,7 @@ lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout) }; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); - if (rc != 0) { + if (rc) { CERROR("Can't set socket recv timeout %ld.%06d: %d\n", (long)tv.tv_sec, (int)tv.tv_usec, rc); return rc; @@ -351,13 +351,13 @@ lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout) if (rc < 0) return rc; - if (rc == 0) + if (!rc) return -ECONNRESET; buffer = ((char *)buffer) + rc; nob -= rc; - if (nob == 0) + if (!nob) return 0; if (ticks <= 0) @@ -380,7 +380,7 @@ lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip, rc = sock_create(PF_INET, SOCK_STREAM, 0, &sock); *sockp = sock; - if (rc != 0) { + if (rc) { CERROR("Can't create socket: %d\n", rc); return rc; } @@ -388,16 +388,16 @@ lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip, option = 1; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc); goto failed; } - if (local_ip != 0 || local_port != 0) { + if (local_ip || local_port) { memset(&locaddr, 0, sizeof(locaddr)); locaddr.sin_family = AF_INET; locaddr.sin_port = htons(local_port); - locaddr.sin_addr.s_addr = (local_ip == 0) ? + locaddr.sin_addr.s_addr = !local_ip ? INADDR_ANY : htonl(local_ip); rc = kernel_bind(sock, (struct sockaddr *)&locaddr, @@ -407,7 +407,7 @@ lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip, *fatal = 0; goto failed; } - if (rc != 0) { + if (rc) { CERROR("Error trying to bind to port %d: %d\n", local_port, rc); goto failed; @@ -426,22 +426,22 @@ lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize) int option; int rc; - if (txbufsize != 0) { + if (txbufsize) { option = txbufsize; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set send buffer %d: %d\n", option, rc); return rc; } } - if (rxbufsize != 0) { + if (rxbufsize) { option = rxbufsize; rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&option, sizeof(option)); - if (rc != 0) { + if (rc) { CERROR("Can't set receive buffer %d: %d\n", option, rc); return rc; @@ -462,7 +462,7 @@ lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port) rc = kernel_getpeername(sock, (struct sockaddr *)&sin, &len); else rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &len); - if (rc != 0) { + if (rc) { CERROR("Error %d getting sock %s IP/port\n", rc, remote ? "peer" : "local"); return rc; @@ -499,7 +499,7 @@ lnet_sock_listen(struct socket **sockp, __u32 local_ip, int local_port, int rc; rc = lnet_sock_create(sockp, &fatal, local_ip, local_port); - if (rc != 0) { + if (rc) { if (!fatal) CERROR("Can't create socket: port %d already in use\n", local_port); @@ -507,7 +507,7 @@ lnet_sock_listen(struct socket **sockp, __u32 local_ip, int local_port, } rc = kernel_listen(*sockp, backlog); - if (rc == 0) + if (!rc) return 0; CERROR("Can't set listen backlog %d: %d\n", backlog, rc); @@ -548,7 +548,7 @@ lnet_sock_accept(struct socket **newsockp, struct socket *sock) rc = sock->ops->accept(sock, newsock, O_NONBLOCK); } - if (rc != 0) + if (rc) goto failed; *newsockp = newsock; @@ -568,7 +568,7 @@ lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, int rc; rc = lnet_sock_create(sockp, fatal, local_ip, local_port); - if (rc != 0) + if (rc) return rc; memset(&srvaddr, 0, sizeof(srvaddr)); @@ -578,7 +578,7 @@ lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip, rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr, sizeof(srvaddr), 0); - if (rc == 0) + if (!rc) return 0; /* diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index 1e880336a63a..cd3730328117 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -80,7 +80,7 @@ lnet_unconfigure(void) mutex_unlock(&the_lnet.ln_api_mutex); mutex_unlock(&lnet_config_mutex); - return (refcount == 0) ? 0 : -EBUSY; + return !refcount ? 0 : -EBUSY; } static int @@ -120,13 +120,13 @@ init_lnet(void) mutex_init(&lnet_config_mutex); rc = lnet_init(); - if (rc != 0) { + if (rc) { CERROR("lnet_init: error %d\n", rc); return rc; } rc = libcfs_register_ioctl(&lnet_ioctl_handler); - LASSERT(rc == 0); + LASSERT(!rc); if (config_on_load) { /* @@ -145,7 +145,7 @@ fini_lnet(void) int rc; rc = libcfs_deregister_ioctl(&lnet_ioctl_handler); - LASSERT(rc == 0); + LASSERT(!rc); lnet_fini(); } diff --git a/drivers/staging/lustre/lnet/lnet/nidstrings.c b/drivers/staging/lustre/lnet/lnet/nidstrings.c index c9c85e5d6aff..00010f318b37 100644 --- a/drivers/staging/lustre/lnet/lnet/nidstrings.c +++ b/drivers/staging/lustre/lnet/lnet/nidstrings.c @@ -206,7 +206,7 @@ add_nidrange(const struct cfs_lstr *src, if (!nf) return NULL; endlen = src->ls_len - strlen(nf->nf_name); - if (endlen == 0) + if (!endlen) /* network name only, e.g. "elan" or "tcp" */ netnum = 0; else { @@ -255,17 +255,17 @@ parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist) struct nidrange *nr; tmp = *src; - if (cfs_gettok(src, '@', &addrrange) == 0) + if (!cfs_gettok(src, '@', &addrrange)) goto failed; - if (cfs_gettok(src, '@', &net) == 0 || src->ls_str) + if (!cfs_gettok(src, '@', &net) || src->ls_str) goto failed; nr = add_nidrange(&net, nidlist); if (!nr) goto failed; - if (parse_addrange(&addrrange, nr) != 0) + if (parse_addrange(&addrrange, nr)) goto failed; return 1; @@ -344,12 +344,12 @@ cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) INIT_LIST_HEAD(nidlist); while (src.ls_str) { rc = cfs_gettok(&src, ' ', &res); - if (rc == 0) { + if (!rc) { cfs_free_nidlist(nidlist); return 0; } rc = parse_nidrange(&res, nidlist); - if (rc == 0) { + if (!rc) { cfs_free_nidlist(nidlist); return 0; } @@ -397,7 +397,7 @@ cfs_print_network(char *buffer, int count, struct nidrange *nr) { struct netstrfns *nf = nr->nr_netstrfns; - if (nr->nr_netnum == 0) + if (!nr->nr_netnum) return scnprintf(buffer, count, "@%s", nf->nf_name); else return scnprintf(buffer, count, "@%s%u", @@ -419,7 +419,7 @@ cfs_print_addrranges(char *buffer, int count, struct list_head *addrranges, struct netstrfns *nf = nr->nr_netstrfns; list_for_each_entry(ar, addrranges, ar_link) { - if (i != 0) + if (i) i += scnprintf(buffer + i, count - i, " "); i += nf->nf_print_addrlist(buffer + i, count - i, &ar->ar_numaddr_ranges); @@ -444,10 +444,10 @@ int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist) return 0; list_for_each_entry(nr, nidlist, nr_link) { - if (i != 0) + if (i) i += scnprintf(buffer + i, count - i, " "); - if (nr->nr_all != 0) { + if (nr->nr_all) { LASSERT(list_empty(&nr->nr_addrranges)); i += scnprintf(buffer + i, count - i, "*"); i += cfs_print_network(buffer + i, count - i, nr); @@ -517,7 +517,7 @@ static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid, list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) { list_for_each_entry(re, &el->el_exprs, re_link) { - if (re->re_lo < min_addr || min_addr == 0) + if (re->re_lo < min_addr || !min_addr) min_addr = re->re_lo; if (re->re_hi > max_addr) max_addr = re->re_hi; @@ -553,7 +553,7 @@ bool cfs_nidrange_is_contiguous(struct list_head *nidlist) if (netnum == -1) netnum = nr->nr_netnum; - if (strcmp(lndname, nf->nf_name) != 0 || + if (strcmp(lndname, nf->nf_name) || netnum != nr->nr_netnum) return false; } @@ -592,7 +592,7 @@ static bool cfs_num_is_contiguous(struct list_head *nidlist) list_for_each_entry(ar, &nr->nr_addrranges, ar_link) { cfs_num_ar_min_max(ar, ¤t_start_nid, ¤t_end_nid); - if (last_end_nid != 0 && + if (last_end_nid && (current_start_nid - last_end_nid != 1)) return false; last_end_nid = current_end_nid; @@ -602,7 +602,7 @@ static bool cfs_num_is_contiguous(struct list_head *nidlist) re_link) { if (re->re_stride > 1) return false; - else if (last_hi != 0 && + else if (last_hi && re->re_hi - last_hi != 1) return false; last_hi = re->re_hi; @@ -642,7 +642,7 @@ static bool cfs_ip_is_contiguous(struct list_head *nidlist) last_diff = 0; cfs_ip_ar_min_max(ar, ¤t_start_nid, ¤t_end_nid); - if (last_end_nid != 0 && + if (last_end_nid && (current_start_nid - last_end_nid != 1)) return false; last_end_nid = current_end_nid; @@ -726,7 +726,7 @@ static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid, list_for_each_entry(ar, &nr->nr_addrranges, ar_link) { cfs_num_ar_min_max(ar, &tmp_min_addr, &tmp_max_addr); - if (tmp_min_addr < min_addr || min_addr == 0) + if (tmp_min_addr < min_addr || !min_addr) min_addr = tmp_min_addr; if (tmp_max_addr > max_addr) max_addr = tmp_min_addr; @@ -758,7 +758,7 @@ static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid, list_for_each_entry(ar, &nr->nr_addrranges, ar_link) { cfs_ip_ar_min_max(ar, &tmp_min_ip_addr, &tmp_max_ip_addr); - if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0) + if (tmp_min_ip_addr < min_ip_addr || !min_ip_addr) min_ip_addr = tmp_min_ip_addr; if (tmp_max_ip_addr > max_ip_addr) max_ip_addr = tmp_max_ip_addr; @@ -806,8 +806,8 @@ libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) /* numeric IP? */ if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && n == nob && - (a & ~0xff) == 0 && (b & ~0xff) == 0 && - (c & ~0xff) == 0 && (d & ~0xff) == 0) { + !(a & ~0xff) && !(b & ~0xff) && + !(c & ~0xff) && !(d & ~0xff)) { *addr = ((a << 24) | (b << 16) | (c << 8) | d); return 1; } @@ -837,7 +837,7 @@ cfs_ip_addr_parse(char *str, int len, struct list_head *list) } rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el); - if (rc != 0) + if (rc) goto out; list_add_tail(&el->el_link, list); @@ -862,7 +862,7 @@ libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list) list_for_each_entry(el, list, el_link) { LASSERT(j++ < 4); - if (i != 0) + if (i) i += scnprintf(buffer + i, count - i, "."); i += cfs_expr_list_print(buffer + i, count - i, el); } @@ -932,7 +932,7 @@ libcfs_num_parse(char *str, int len, struct list_head *list) int rc; rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); - if (rc == 0) + if (!rc) list_add_tail(&el->el_link, list); return rc; @@ -1114,7 +1114,7 @@ libcfs_net2str_r(__u32 net, char *buf, size_t buf_size) nf = libcfs_lnd2netstrfns(lnd); if (!nf) snprintf(buf, buf_size, "<%u:%u>", lnd, nnum); - else if (nnum == 0) + else if (!nnum) snprintf(buf, buf_size, "%s", nf->nf_name); else snprintf(buf, buf_size, "%s%u", nf->nf_name, nnum); @@ -1146,7 +1146,7 @@ libcfs_nid2str_r(lnet_nid_t nid, char *buf, size_t buf_size) nf->nf_addr2str(addr, buf, buf_size); addr_len = strlen(buf); - if (nnum == 0) + if (!nnum) snprintf(buf + addr_len, buf_size - addr_len, "@%s", nf->nf_name); else @@ -1244,8 +1244,8 @@ libcfs_id2str(lnet_process_id_t id) } snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s", - ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "", - (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid)); + id.pid & LNET_PID_USERFLAG ? "U" : "", + id.pid & ~LNET_PID_USERFLAG, libcfs_nid2str(id.nid)); return str; } EXPORT_SYMBOL(libcfs_id2str); diff --git a/drivers/staging/lustre/lnet/lnet/peer.c b/drivers/staging/lustre/lnet/lnet/peer.c index 43b459e919e4..00086ee90dd8 100644 --- a/drivers/staging/lustre/lnet/lnet/peer.c +++ b/drivers/staging/lustre/lnet/lnet/peer.c @@ -137,10 +137,10 @@ lnet_peer_tables_cleanup(void) lnet_net_lock(i); - for (j = 3; ptable->pt_number != 0; j++) { + for (j = 3; ptable->pt_number; j++) { lnet_net_unlock(i); - if ((j & (j - 1)) == 0) { + if (!(j & (j - 1))) { CDEBUG(D_WARNING, "Waiting for %d peers on peer table\n", ptable->pt_number); @@ -167,11 +167,11 @@ lnet_destroy_peer_locked(lnet_peer_t *lp) { struct lnet_peer_table *ptable; - LASSERT(lp->lp_refcount == 0); - LASSERT(lp->lp_rtr_refcount == 0); + LASSERT(!lp->lp_refcount); + LASSERT(!lp->lp_rtr_refcount); LASSERT(list_empty(&lp->lp_txq)); LASSERT(list_empty(&lp->lp_hashlist)); - LASSERT(lp->lp_txqnob == 0); + LASSERT(!lp->lp_txqnob); ptable = the_lnet.ln_peer_tables[lp->lp_cpt]; LASSERT(ptable->pt_number > 0); @@ -317,7 +317,7 @@ lnet_debug_peer(lnet_nid_t nid) lnet_net_lock(cpt); rc = lnet_nid2peer_locked(&lp, nid, cpt); - if (rc != 0) { + if (rc) { lnet_net_unlock(cpt); CDEBUG(D_WARNING, "No peer %s\n", libcfs_nid2str(nid)); return; diff --git a/drivers/staging/lustre/lnet/lnet/router.c b/drivers/staging/lustre/lnet/lnet/router.c index c6b747dae8a1..735a8f2bdba4 100644 --- a/drivers/staging/lustre/lnet/lnet/router.c +++ b/drivers/staging/lustre/lnet/lnet/router.c @@ -109,7 +109,7 @@ lnet_notify_locked(lnet_peer_t *lp, int notifylnd, int alive, lp->lp_timestamp = when; /* update timestamp */ lp->lp_ping_deadline = 0; /* disable ping timeout */ - if (lp->lp_alive_count != 0 && /* got old news */ + if (lp->lp_alive_count && /* got old news */ (!lp->lp_alive) == (!alive)) { /* new date for old news */ CDEBUG(D_NET, "Old news\n"); return; @@ -201,7 +201,7 @@ lnet_rtr_decref_locked(lnet_peer_t *lp) /* lnet_net_lock must be exclusively locked */ lp->lp_rtr_refcount--; - if (lp->lp_rtr_refcount == 0) { + if (!lp->lp_rtr_refcount) { LASSERT(list_empty(&lp->lp_routes)); if (lp->lp_rcd) { @@ -283,7 +283,7 @@ lnet_add_route_to_rnet(lnet_remotenet_t *rnet, lnet_route_t *route) /* len+1 positions to add a new entry, also prevents division by 0 */ offset = cfs_rand() % (len + 1); list_for_each(e, &rnet->lrn_routes) { - if (offset == 0) + if (!offset) break; offset--; } @@ -342,7 +342,7 @@ lnet_add_route(__u32 net, unsigned int hops, lnet_nid_t gateway, lnet_net_lock(LNET_LOCK_EX); rc = lnet_nid2peer_locked(&route->lr_gateway, gateway, LNET_LOCK_EX); - if (rc != 0) { + if (rc) { lnet_net_unlock(LNET_LOCK_EX); LIBCFS_FREE(route, sizeof(*route)); @@ -565,7 +565,7 @@ lnet_get_route(int idx, __u32 *net, __u32 *hops, list_for_each(e2, &rnet->lrn_routes) { route = list_entry(e2, lnet_route_t, lr_list); - if (idx-- == 0) { + if (!idx--) { *net = rnet->lrn_net; *hops = route->lr_hops; *priority = route->lr_priority; @@ -625,13 +625,13 @@ lnet_parse_rc_info(lnet_rc_data_t *rcd) } gw->lp_ping_feats = info->pi_features; - if ((gw->lp_ping_feats & LNET_PING_FEAT_MASK) == 0) { + if (!(gw->lp_ping_feats & LNET_PING_FEAT_MASK)) { CDEBUG(D_NET, "%s: Unexpected features 0x%x\n", libcfs_nid2str(gw->lp_nid), gw->lp_ping_feats); return; /* nothing I can understand */ } - if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) == 0) + if (!(gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS)) return; /* can't carry NI status info */ list_for_each_entry(rtr, &gw->lp_routes, lr_gwlist) { @@ -722,7 +722,7 @@ lnet_router_checker_event(lnet_event_t *event) if (event->type == LNET_EVENT_SEND) { lp->lp_ping_notsent = 0; - if (event->status == 0) + if (!event->status) goto out; } @@ -733,7 +733,7 @@ lnet_router_checker_event(lnet_event_t *event) * we ping alive routers to try to detect router death before * apps get burned). */ - lnet_notify_locked(lp, 1, (event->status == 0), cfs_time_current()); + lnet_notify_locked(lp, 1, !event->status, cfs_time_current()); /* * The router checker will wake up very shortly and do the @@ -741,7 +741,7 @@ lnet_router_checker_event(lnet_event_t *event) * XXX If 'lp' stops being a router before then, it will still * have the notification pending!!! */ - if (avoid_asym_router_failure && event->status == 0) + if (avoid_asym_router_failure && !event->status) lnet_parse_rc_info(rcd); out: @@ -764,7 +764,7 @@ lnet_wait_known_routerstate(void) list_for_each(entry, &the_lnet.ln_routers) { rtr = list_entry(entry, lnet_peer_t, lp_rtr_list); - if (rtr->lp_alive_count == 0) { + if (!rtr->lp_alive_count) { all_known = 0; break; } @@ -785,7 +785,7 @@ lnet_router_ni_update_locked(lnet_peer_t *gw, __u32 net) { lnet_route_t *rte; - if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS) != 0) { + if ((gw->lp_ping_feats & LNET_PING_FEAT_NI_STATUS)) { list_for_each_entry(rte, &gw->lp_routes, lr_gwlist) { if (rte->lr_net == net) { rte->lr_downis = 0; @@ -898,7 +898,7 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) CERROR("Can't bind MD: %d\n", rc); goto out; } - LASSERT(rc == 0); + LASSERT(!rc); lnet_net_lock(gateway->lp_cpt); /* router table changed or someone has created rcd for this gateway */ @@ -918,7 +918,7 @@ lnet_create_rc_data_locked(lnet_peer_t *gateway) if (rcd) { if (!LNetHandleIsInvalid(rcd->rcd_mdh)) { rc = LNetMDUnlink(rcd->rcd_mdh); - LASSERT(rc == 0); + LASSERT(!rc); } lnet_destroy_rc_data(rcd); } @@ -949,7 +949,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) lnet_peer_addref_locked(rtr); - if (rtr->lp_ping_deadline != 0 && /* ping timed out? */ + if (rtr->lp_ping_deadline && /* ping timed out? */ cfs_time_after(now, rtr->lp_ping_deadline)) lnet_notify_locked(rtr, 1, 0, now); @@ -977,7 +977,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) rtr->lp_ping_deadline, rtr->lp_ping_notsent, rtr->lp_alive, rtr->lp_alive_count, rtr->lp_ping_timestamp); - if (secs != 0 && !rtr->lp_ping_notsent && + if (secs && !rtr->lp_ping_notsent && cfs_time_after(now, cfs_time_add(rtr->lp_ping_timestamp, cfs_time_seconds(secs)))) { int rc; @@ -993,7 +993,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) mdh = rcd->rcd_mdh; - if (rtr->lp_ping_deadline == 0) { + if (!rtr->lp_ping_deadline) { rtr->lp_ping_deadline = cfs_time_shift(router_ping_timeout); } @@ -1004,7 +1004,7 @@ lnet_ping_router_locked(lnet_peer_t *rtr) LNET_PROTO_PING_MATCHBITS, 0); lnet_net_lock(rtr->lp_cpt); - if (rc != 0) + if (rc) rtr->lp_ping_notsent = 0; /* no event pending */ } @@ -1038,7 +1038,7 @@ lnet_router_checker_start(void) eqsz = 0; rc = LNetEQAlloc(eqsz, lnet_router_checker_event, &the_lnet.ln_rc_eqh); - if (rc != 0) { + if (rc) { CERROR("Can't allocate EQ(%d): %d\n", eqsz, rc); return -ENOMEM; } @@ -1051,7 +1051,7 @@ lnet_router_checker_start(void) /* block until event callback signals exit */ down(&the_lnet.ln_rc_signal); rc = LNetEQFree(the_lnet.ln_rc_eqh); - LASSERT(rc == 0); + LASSERT(!rc); the_lnet.ln_rc_state = LNET_RC_STATE_SHUTDOWN; return -ENOMEM; } @@ -1084,7 +1084,7 @@ lnet_router_checker_stop(void) LASSERT(the_lnet.ln_rc_state == LNET_RC_STATE_SHUTDOWN); rc = LNetEQFree(the_lnet.ln_rc_eqh); - LASSERT(rc == 0); + LASSERT(!rc); } static void @@ -1288,7 +1288,7 @@ lnet_rtrpool_free_bufs(lnet_rtrbufpool_t *rbp) int nbuffers = 0; lnet_rtrbuf_t *rb; - if (rbp->rbp_nbuffers == 0) /* not initialized or already freed */ + if (!rbp->rbp_nbuffers) /* not initialized or already freed */ return; LASSERT(list_empty(&rbp->rbp_msgs)); @@ -1317,7 +1317,7 @@ lnet_rtrpool_alloc_bufs(lnet_rtrbufpool_t *rbp, int nbufs, int cpt) lnet_rtrbuf_t *rb; int i; - if (rbp->rbp_nbuffers != 0) { + if (rbp->rbp_nbuffers) { LASSERT(rbp->rbp_nbuffers == nbufs); return 0; } @@ -1484,17 +1484,17 @@ lnet_rtrpools_alloc(int im_a_router) cfs_percpt_for_each(rtrp, i, the_lnet.ln_rtrpools) { lnet_rtrpool_init(&rtrp[0], 0); rc = lnet_rtrpool_alloc_bufs(&rtrp[0], nrb_tiny, i); - if (rc != 0) + if (rc) goto failed; lnet_rtrpool_init(&rtrp[1], small_pages); rc = lnet_rtrpool_alloc_bufs(&rtrp[1], nrb_small, i); - if (rc != 0) + if (rc) goto failed; lnet_rtrpool_init(&rtrp[2], large_pages); rc = lnet_rtrpool_alloc_bufs(&rtrp[2], nrb_large, i); - if (rc != 0) + if (rc) goto failed; } diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c index 230fc15170b7..a7aaf0c7e9a2 100644 --- a/drivers/staging/lustre/lnet/lnet/router_proc.c +++ b/drivers/staging/lustre/lnet/lnet/router_proc.c @@ -170,7 +170,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); @@ -179,7 +179,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "Routing %s\n", the_lnet.ln_routing ? "enabled" : "disabled"); LASSERT(tmpstr + tmpsiz - s > 0); @@ -224,7 +224,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, lnet_route_t *re = list_entry(r, lnet_route_t, lr_list); - if (skip == 0) { + if (!skip) { route = re; break; } @@ -271,7 +271,7 @@ static int proc_lnet_routes(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -293,7 +293,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); @@ -302,7 +302,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "%-4s %7s %9s %6s %12s %9s %8s %7s %s\n", "ref", "rtr_ref", "alive_cnt", "state", @@ -334,7 +334,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, lnet_peer_t *lp = list_entry(r, lnet_peer_t, lp_rtr_list); - if (skip == 0) { + if (!skip) { peer = lp; break; } @@ -358,21 +358,21 @@ static int proc_lnet_routers(struct ctl_table *table, int write, lnet_route_t *rtr; if ((peer->lp_ping_feats & - LNET_PING_FEAT_NI_STATUS) != 0) { + LNET_PING_FEAT_NI_STATUS)) { list_for_each_entry(rtr, &peer->lp_routes, lr_gwlist) { /* * downis on any route should be the * number of downis on the gateway */ - if (rtr->lr_downis != 0) { + if (rtr->lr_downis) { down_ni = rtr->lr_downis; break; } } } - if (deadline == 0) + if (!deadline) s += snprintf(s, tmpstr + tmpsiz - s, "%-4d %7d %9d %6s %12d %9d %8s %7d %s\n", nrefs, nrtrrefs, alive_cnt, @@ -408,7 +408,7 @@ static int proc_lnet_routers(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -431,7 +431,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, CLASSERT(LNET_PROC_HASH_BITS >= LNET_PEER_HASH_BITS); LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; if (cpt >= LNET_CPT_NUMBER) { @@ -445,7 +445,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "%-24s %4s %5s %5s %5s %5s %5s %5s %5s %s\n", "nid", "refs", "state", "last", "max", @@ -480,7 +480,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, while (p != &ptable->pt_hash[hash]) { lnet_peer_t *lp = list_entry(p, lnet_peer_t, lp_hashlist); - if (skip == 0) { + if (!skip) { peer = lp; /* @@ -577,7 +577,7 @@ static int proc_lnet_peers(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -659,7 +659,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, LASSERT(!write); - if (*lenp == 0) + if (!*lenp) return 0; LIBCFS_ALLOC(tmpstr, tmpsiz); @@ -668,7 +668,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, s = tmpstr; /* points to current position in tmpstr[] */ - if (*ppos == 0) { + if (!*ppos) { s += snprintf(s, tmpstr + tmpsiz - s, "%-24s %6s %5s %4s %4s %4s %5s %5s %5s\n", "nid", "status", "alive", "refs", "peer", @@ -686,7 +686,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, while (n != &the_lnet.ln_nis) { lnet_ni_t *a_ni = list_entry(n, lnet_ni_t, ni_list); - if (skip == 0) { + if (!skip) { ni = a_ni; break; } @@ -730,7 +730,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, if (j == ni->ni_ncpts) continue; - if (i != 0) + if (i) lnet_net_lock(i); s += snprintf(s, tmpstr + tmpsiz - s, @@ -742,7 +742,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, tq->tq_credits_max, tq->tq_credits, tq->tq_credits_min); - if (i != 0) + if (i) lnet_net_unlock(i); } LASSERT(tmpstr + tmpsiz - s > 0); @@ -764,7 +764,7 @@ static int proc_lnet_nis(struct ctl_table *table, int write, LIBCFS_FREE(tmpstr, tmpsiz); - if (rc == 0) + if (!rc) *lenp = len; return rc; @@ -854,8 +854,8 @@ static int __proc_lnet_portal_rotor(void *data, int write, rc = -EINVAL; lnet_res_lock(0); for (i = 0; portal_rotors[i].pr_name; i++) { - if (strncasecmp(portal_rotors[i].pr_name, tmp, - strlen(portal_rotors[i].pr_name)) == 0) { + if (!strncasecmp(portal_rotors[i].pr_name, tmp, + strlen(portal_rotors[i].pr_name))) { portal_rotor = portal_rotors[i].pr_value; rc = 0; break; diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c index 38aed80b1a4a..b71f4b42fc60 100644 --- a/drivers/staging/lustre/lnet/selftest/brw_test.c +++ b/drivers/staging/lustre/lnet/selftest/brw_test.c @@ -80,7 +80,7 @@ brw_client_init(sfw_test_instance_t *tsi) LASSERT(sn); LASSERT(tsi->tsi_is_client); - if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { + if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; opc = breq->blk_opc; @@ -99,7 +99,7 @@ brw_client_init(sfw_test_instance_t *tsi) * I should never get this step if it's unknown feature * because make_session will reject unknown feature */ - LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); + LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); opc = breq->blk_opc; flags = breq->blk_flags; @@ -145,7 +145,7 @@ brw_inject_one_error(void) ktime_get_ts64(&ts); - if (((ts.tv_nsec / NSEC_PER_USEC) & 1) == 0) + if (!((ts.tv_nsec / NSEC_PER_USEC) & 1)) return 0; return brw_inject_errors--; @@ -244,7 +244,7 @@ brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) for (i = 0; i < bk->bk_niov; i++) { pg = bk->bk_iovs[i].kiov_page; - if (brw_check_page(pg, pattern, magic) != 0) { + if (brw_check_page(pg, pattern, magic)) { CERROR("Bulk page %p (%d/%d) is corrupted!\n", pg, i, bk->bk_niov); return 1; @@ -272,7 +272,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, LASSERT(sn); LASSERT(bulk); - if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { + if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; opc = breq->blk_opc; @@ -287,7 +287,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, * I should never get this step if it's unknown feature * because make_session will reject unknown feature */ - LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); + LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); opc = breq->blk_opc; flags = breq->blk_flags; @@ -296,7 +296,7 @@ brw_client_prep_rpc(sfw_test_unit_t *tsu, } rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc); - if (rc != 0) + if (rc) return rc; memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg])); @@ -326,7 +326,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) LASSERT(sn); - if (rpc->crpc_status != 0) { + 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 */ @@ -343,7 +343,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) "BRW RPC to %s finished with brw_status: %d\n", libcfs_id2str(rpc->crpc_dest), reply->brw_status); - if (reply->brw_status != 0) { + if (reply->brw_status) { atomic_inc(&sn->sn_brw_errors); rpc->crpc_status = -(int)reply->brw_status; goto out; @@ -352,7 +352,7 @@ brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) if (reqst->brw_rw == LST_BRW_WRITE) goto out; - if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) { + if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic)) { CERROR("Bulk data from %s is corrupted!\n", libcfs_id2str(rpc->crpc_dest)); atomic_inc(&sn->sn_brw_errors); @@ -371,7 +371,7 @@ brw_server_rpc_done(struct srpc_server_rpc *rpc) if (!blk) return; - if (rpc->srpc_status != 0) + if (rpc->srpc_status) CERROR("Bulk transfer %s %s has failed: %d\n", blk->bk_sink ? "from" : "to", libcfs_id2str(rpc->srpc_peer), rpc->srpc_status); @@ -397,7 +397,7 @@ brw_bulk_ready(struct srpc_server_rpc *rpc, int status) reqstmsg = &rpc->srpc_reqstbuf->buf_msg; reqst = &reqstmsg->msg_body.brw_reqst; - if (status != 0) { + if (status) { CERROR("BRW bulk %s failed for RPC from %s: %d\n", reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE", libcfs_id2str(rpc->srpc_peer), status); @@ -410,7 +410,7 @@ brw_bulk_ready(struct srpc_server_rpc *rpc, int status) if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) __swab64s(&magic); - if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) { + if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic)) { CERROR("Bulk data from %s is corrupted!\n", libcfs_id2str(rpc->srpc_peer)); reply->brw_status = EBADMSG; @@ -454,15 +454,15 @@ brw_server_handle(struct srpc_server_rpc *rpc) return 0; } - if ((reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) != 0) { + if (reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) { replymsg->msg_ses_feats = LST_FEATS_MASK; reply->brw_status = EPROTO; return 0; } - if ((reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) { + if (!(reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN)) { /* compat with old version */ - if ((reqst->brw_len & ~CFS_PAGE_MASK) != 0) { + if (reqst->brw_len & ~CFS_PAGE_MASK) { reply->brw_status = EINVAL; return 0; } @@ -474,7 +474,7 @@ brw_server_handle(struct srpc_server_rpc *rpc) replymsg->msg_ses_feats = reqstmsg->msg_ses_feats; - if (reqst->brw_len == 0 || npg > LNET_MAX_IOV) { + if (!reqst->brw_len || npg > LNET_MAX_IOV) { reply->brw_status = EINVAL; return 0; } @@ -482,7 +482,7 @@ brw_server_handle(struct srpc_server_rpc *rpc) rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt, npg, reqst->brw_len, reqst->brw_rw == LST_BRW_WRITE); - if (rc != 0) + if (rc) return rc; if (reqst->brw_rw == LST_BRW_READ) diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c index 8b9717c63b45..210e24e6db0d 100644 --- a/drivers/staging/lustre/lnet/selftest/conctl.c +++ b/drivers/staging/lustre/lnet/selftest/conctl.c @@ -52,7 +52,7 @@ lst_session_new_ioctl(lstio_session_new_args_t *args) int rc; if (!args->lstio_ses_idp || /* address for output sid */ - args->lstio_ses_key == 0 || /* no key is specified */ + !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) @@ -354,7 +354,7 @@ lst_nodes_add_ioctl(lstio_group_nodes_args_t *args) args->lstio_grp_resultp); LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); - if (rc == 0 && + if (!rc && copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) { return -EINVAL; } @@ -431,7 +431,7 @@ lst_group_info_ioctl(lstio_group_info_args_t *args) LIBCFS_FREE(name, args->lstio_grp_nmlen + 1); - if (rc != 0) + if (rc) return rc; if (args->lstio_grp_dentsp && @@ -655,7 +655,7 @@ lst_batch_info_ioctl(lstio_batch_info_args_t *args) LIBCFS_FREE(name, args->lstio_bat_nmlen + 1); - if (rc != 0) + if (rc) return rc; if (args->lstio_bat_dentsp && @@ -733,7 +733,7 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE) return -EINVAL; - if (args->lstio_tes_loop == 0 || /* 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) @@ -781,7 +781,7 @@ static int lst_test_add_ioctl(lstio_test_args_t *args) args->lstio_tes_param_len, &ret, args->lstio_tes_resultp); - if (ret != 0) + if (ret) rc = (copy_to_user(args->lstio_tes_retp, &ret, sizeof(ret))) ? -EFAULT : 0; out: diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index 5315a37e5cf0..b02a140e0b4a 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -74,9 +74,9 @@ lstcon_rpc_done(srpc_client_rpc_t *rpc) /* not an orphan RPC */ crpc->crp_finished = 1; - if (crpc->crp_stamp == 0) { + if (!crpc->crp_stamp) { /* not aborted */ - LASSERT(crpc->crp_status == 0); + LASSERT(!crpc->crp_status); crpc->crp_stamp = cfs_time_current(); crpc->crp_status = rpc->crpc_status; @@ -138,7 +138,7 @@ lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, } rc = lstcon_rpc_init(nd, service, feats, bulk_npg, bulk_len, 0, crpc); - if (rc == 0) { + if (!rc) { *crpcpp = crpc; return 0; } @@ -298,8 +298,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 != 0) { /* rpc done or aborted already */ - if (crpc->crp_stamp == 0) { + crpc->crp_stamp) { /* rpc done or aborted already */ + if (!crpc->crp_stamp) { crpc->crp_stamp = cfs_time_current(); crpc->crp_status = -EINTR; } @@ -333,7 +333,7 @@ lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans) !list_empty(&trans->tas_olink)) /* Not an end session RPC */ return 1; - return (atomic_read(&trans->tas_remaining) == 0) ? 1 : 0; + return !atomic_read(&trans->tas_remaining) ? 1 : 0; } int @@ -370,7 +370,7 @@ lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) if (console_session.ses_shutdown) rc = -ESHUTDOWN; - if (rc != 0 || atomic_read(&trans->tas_remaining) != 0) { + if (rc || atomic_read(&trans->tas_remaining)) { /* treat short timeout as canceled */ if (rc == -ETIMEDOUT && timeout < LST_TRANS_MIN_TIMEOUT * 2) rc = -EINTR; @@ -394,9 +394,9 @@ lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) srpc_generic_reply_t *rep; LASSERT(nd && rpc); - LASSERT(crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp); - if (crpc->crp_status != 0) { + if (crpc->crp_status) { *msgpp = NULL; return crpc->crp_status; } @@ -437,12 +437,12 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { lstcon_rpc_stat_total(stat, 1); - LASSERT(crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp); error = lstcon_rpc_get_reply(crpc, &rep); - if (error != 0) { + if (error) { lstcon_rpc_stat_failure(stat, 1); - if (stat->trs_rpc_errno == 0) + if (!stat->trs_rpc_errno) stat->trs_rpc_errno = -error; continue; @@ -453,7 +453,7 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) lstcon_rpc_stat_reply(trans, rep, crpc->crp_node, stat); } - if (trans->tas_opc == LST_TRANS_SESNEW && stat->trs_fwk_errno == 0) { + if (trans->tas_opc == LST_TRANS_SESNEW && !stat->trs_fwk_errno) { stat->trs_fwk_errno = lstcon_session_feats_check(trans->tas_features); } @@ -500,7 +500,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, ent = list_entry(next, lstcon_rpc_ent_t, rpe_link); - LASSERT(crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp); error = lstcon_rpc_get_reply(crpc, &msg); @@ -519,7 +519,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, sizeof(error))) return -EFAULT; - if (error != 0) + if (error) continue; /* RPC is done */ @@ -535,7 +535,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, error = readent(trans->tas_opc, msg, ent); - if (error != 0) + if (error) return error; } @@ -572,7 +572,7 @@ lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) * user wait for them, just abandon them, they will be recycled * in callback */ - LASSERT(crpc->crp_status != 0); + LASSERT(crpc->crp_status); crpc->crp_node = NULL; crpc->crp_trans = NULL; @@ -584,7 +584,7 @@ lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) atomic_dec(&trans->tas_remaining); } - LASSERT(atomic_read(&trans->tas_remaining) == 0); + LASSERT(!atomic_read(&trans->tas_remaining)); list_del(&trans->tas_link); if (!list_empty(&trans->tas_olink)) @@ -610,7 +610,7 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, case LST_TRANS_SESNEW: rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION, feats, 0, 0, crpc); - if (rc != 0) + if (rc) return rc; msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst; @@ -623,7 +623,7 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, case LST_TRANS_SESEND: rc = lstcon_rpc_prep(nd, SRPC_SERVICE_REMOVE_SESSION, feats, 0, 0, crpc); - if (rc != 0) + if (rc) return rc; rsrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.rmsn_reqst; @@ -644,7 +644,7 @@ lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) int rc; rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, feats, 0, 0, crpc); - if (rc != 0) + if (rc) return rc; drq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst; @@ -664,7 +664,7 @@ lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, int rc; rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, feats, 0, 0, crpc); - if (rc != 0) + if (rc) return rc; brq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.bat_reqst; @@ -680,7 +680,7 @@ lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, transop != LST_TRANS_TSBSTOP) return 0; - LASSERT(tsb->tsb_index == 0); + LASSERT(!tsb->tsb_index); batch = (lstcon_batch_t *)tsb; brq->bar_arg = batch->bat_arg; @@ -695,7 +695,7 @@ lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) int rc; rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, feats, 0, 0, crpc); - if (rc != 0) + if (rc) return rc; srq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.stat_reqst; @@ -827,13 +827,13 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, if (transop == LST_TRANS_TSBCLIADD) { npg = sfw_id_pages(test->tes_span); - nob = (feats & LST_FEAT_BULK_LEN) == 0 ? + nob = !(feats & LST_FEAT_BULK_LEN) ? npg * PAGE_CACHE_SIZE : sizeof(lnet_process_id_packed_t) * test->tes_span; } rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, feats, npg, nob, crpc); - if (rc != 0) + if (rc) return rc; trq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.tes_reqst; @@ -856,7 +856,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, LASSERT(nob > 0); - len = (feats & LST_FEAT_BULK_LEN) == 0 ? + len = !(feats & LST_FEAT_BULK_LEN) ? PAGE_CACHE_SIZE : min_t(int, nob, PAGE_CACHE_SIZE); nob -= len; @@ -881,7 +881,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, test->tes_dist, test->tes_span, npg, &bulk->bk_iovs[0]); - if (rc != 0) { + if (rc) { lstcon_rpc_put(*crpc); return rc; } @@ -905,7 +905,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, case LST_TEST_BULK: trq->tsr_service = SRPC_SERVICE_BRW; - if ((feats & LST_FEAT_BULK_LEN) == 0) { + if (!(feats & LST_FEAT_BULK_LEN)) { rc = lstcon_bulkrpc_v0_prep((lst_test_bulk_param_t *) &test->tes_param[0], trq); } else { @@ -929,8 +929,8 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply; int status = mksn_rep->mksn_status; - if (status == 0 && - (reply->msg_ses_feats & ~LST_FEATS_MASK) != 0) { + if (!status && + (reply->msg_ses_feats & ~LST_FEATS_MASK)) { mksn_rep->mksn_status = EPROTO; status = EPROTO; } @@ -941,7 +941,7 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, reply->msg_ses_feats); } - if (status != 0) + if (status) return status; if (!trans->tas_feats_updated) { @@ -957,7 +957,7 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, status = EPROTO; } - if (status == 0) { + if (!status) { /* session timeout on remote node */ nd->nd_timeout = mksn_rep->mksn_timeout; } @@ -979,7 +979,7 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, switch (trans->tas_opc) { case LST_TRANS_SESNEW: rc = lstcon_sesnew_stat_reply(trans, nd, msg); - if (rc == 0) { + if (!rc) { lstcon_sesop_stat_success(stat, 1); return; } @@ -990,7 +990,7 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, case LST_TRANS_SESEND: rmsn_rep = &msg->msg_body.rmsn_reply; /* ESRCH is not an error for end session */ - if (rmsn_rep->rmsn_status == 0 || + if (!rmsn_rep->rmsn_status || rmsn_rep->rmsn_status == ESRCH) { lstcon_sesop_stat_success(stat, 1); return; @@ -1019,7 +1019,7 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, case LST_TRANS_TSBSTOP: bat_rep = &msg->msg_body.bat_reply; - if (bat_rep->bar_status == 0) { + if (!bat_rep->bar_status) { lstcon_tsbop_stat_success(stat, 1); return; } @@ -1038,12 +1038,12 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, case LST_TRANS_TSBSRVQRY: bat_rep = &msg->msg_body.bat_reply; - if (bat_rep->bar_active != 0) + if (bat_rep->bar_active) lstcon_tsbqry_stat_run(stat, 1); else lstcon_tsbqry_stat_idle(stat, 1); - if (bat_rep->bar_status == 0) + if (!bat_rep->bar_status) return; lstcon_tsbqry_stat_failure(stat, 1); @@ -1054,7 +1054,7 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, case LST_TRANS_TSBSRVADD: test_rep = &msg->msg_body.tes_reply; - if (test_rep->tsr_status == 0) { + if (!test_rep->tsr_status) { lstcon_tsbop_stat_success(stat, 1); return; } @@ -1066,7 +1066,7 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, case LST_TRANS_STATQRY: stat_rep = &msg->msg_body.stat_reply; - if (stat_rep->str_status == 0) { + if (!stat_rep->str_status) { lstcon_statqry_stat_success(stat, 1); return; } @@ -1079,7 +1079,7 @@ lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, LBUG(); } - if (stat->trs_fwk_errno == 0) + if (!stat->trs_fwk_errno) stat->trs_fwk_errno = rc; return; @@ -1101,7 +1101,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, /* Creating session RPG for list of nodes */ rc = lstcon_rpc_trans_prep(translist, transop, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction %d: %d\n", transop, rc); return rc; } @@ -1111,7 +1111,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, rc = !condition ? 1 : condition(transop, ndl->ndl_node, arg); - if (rc == 0) + if (!rc) continue; if (rc < 0) { @@ -1151,7 +1151,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, break; } - if (rc != 0) { + if (rc) { CERROR("Failed to create RPC for transaction %s: %d\n", lstcon_rpc_trans_name(transop), rc); break; @@ -1160,7 +1160,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, lstcon_rpc_trans_addreq(trans, rpc); } - if (rc == 0) { + if (!rc) { *transpp = trans; return 0; } @@ -1213,7 +1213,7 @@ lstcon_rpc_pinger(void *arg) rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND, trans->tas_features, &crpc); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); break; } @@ -1258,7 +1258,7 @@ lstcon_rpc_pinger(void *arg) rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG, trans->tas_features, 0, 0, 1, crpc); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); break; } @@ -1294,11 +1294,11 @@ lstcon_rpc_pinger_start(void) int rc; LASSERT(list_empty(&console_session.ses_rpc_freelist)); - LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0); + LASSERT(!atomic_read(&console_session.ses_rpc_counter)); rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING, &console_session.ses_ping); - if (rc != 0) { + if (rc) { CERROR("Failed to create console pinger\n"); return rc; } @@ -1361,7 +1361,7 @@ lstcon_rpc_cleanup_wait(void) spin_lock(&console_session.ses_rpc_lock); - lst_wait_until((atomic_read(&console_session.ses_rpc_counter) == 0), + lst_wait_until(!atomic_read(&console_session.ses_rpc_counter), console_session.ses_rpc_lock, "Network is not accessible or target is down, waiting for %d console RPCs to being recycled\n", atomic_read(&console_session.ses_rpc_counter)); @@ -1399,5 +1399,5 @@ void lstcon_rpc_module_fini(void) { LASSERT(list_empty(&console_session.ses_rpc_freelist)); - LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0); + LASSERT(!atomic_read(&console_session.ses_rpc_counter)); } diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 89954179fdec..59cd554e47b9 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -159,12 +159,12 @@ lstcon_ndlink_find(struct list_head *hash, return 0; } - if (create == 0) + if (!create) return -ENOENT; /* find or create in session hash */ rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0); - if (rc != 0) + if (rc) return rc; LIBCFS_ALLOC(ndl, sizeof(lstcon_ndlink_t)); @@ -236,7 +236,7 @@ lstcon_group_drain(lstcon_group_t *grp, int keep) lstcon_ndlink_t *tmp; list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) { - if ((ndl->ndl_node->nd_state & keep) == 0) + if (!(ndl->ndl_node->nd_state & keep)) lstcon_group_ndlink_release(grp, ndl); } } @@ -267,7 +267,7 @@ lstcon_group_find(const char *name, lstcon_group_t **grpp) lstcon_group_t *grp; list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) { - if (strncmp(grp->grp_name, name, LST_NAME_SIZE) != 0) + if (strncmp(grp->grp_name, name, LST_NAME_SIZE)) continue; lstcon_group_addref(grp); /* +1 ref for caller */ @@ -285,7 +285,7 @@ lstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, int rc; rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create); - if (rc != 0) + if (rc) return rc; if (!list_empty(&(*ndlpp)->ndl_link)) @@ -404,7 +404,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, int rc; rc = lstcon_group_alloc(NULL, &tmp); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); return -ENOMEM; } @@ -417,18 +417,18 @@ lstcon_group_nodes_add(lstcon_group_t *grp, /* skip if it's in this group already */ rc = lstcon_group_ndlink_find(grp, id, &ndl, 0); - if (rc == 0) + if (!rc) continue; /* add to tmp group */ rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1); - if (rc != 0) { + if (rc) { CERROR("Can't create ndlink, out of memory\n"); break; } } - if (rc != 0) { + if (rc) { lstcon_group_decref(tmp); return rc; } @@ -436,7 +436,7 @@ lstcon_group_nodes_add(lstcon_group_t *grp, rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list, &tmp->grp_trans_list, LST_TRANS_SESNEW, tmp, lstcon_sesrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); lstcon_group_decref(tmp); return rc; @@ -473,7 +473,7 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, /* End session and remove node from the group */ rc = lstcon_group_alloc(NULL, &tmp); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); return -ENOMEM; } @@ -485,14 +485,14 @@ lstcon_group_nodes_remove(lstcon_group_t *grp, } /* move node to tmp group */ - if (lstcon_group_ndlink_find(grp, id, &ndl, 0) == 0) + if (!lstcon_group_ndlink_find(grp, id, &ndl, 0)) lstcon_group_ndlink_move(grp, tmp, ndl); } rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list, &tmp->grp_trans_list, LST_TRANS_SESEND, tmp, lstcon_sesrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); goto error; } @@ -519,15 +519,15 @@ lstcon_group_add(char *name) lstcon_group_t *grp; int rc; - rc = (lstcon_group_find(name, &grp) == 0) ? -EEXIST : 0; - if (rc != 0) { + rc = lstcon_group_find(name, &grp) ? 0: -EEXIST; + if (rc) { /* find a group with same name */ lstcon_group_decref(grp); return rc; } rc = lstcon_group_alloc(name, &grp); - if (rc != 0) { + if (rc) { CERROR("Can't allocate descriptor for group %s\n", name); return -ENOMEM; } @@ -548,7 +548,7 @@ lstcon_nodes_add(char *name, int count, lnet_process_id_t __user *ids_up, LASSERT(ids_up); rc = lstcon_group_find(name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group %s\n", name); return rc; } @@ -576,7 +576,7 @@ lstcon_group_del(char *name) int rc; rc = lstcon_group_find(name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group: %s\n", name); return rc; } @@ -591,7 +591,7 @@ lstcon_group_del(char *name) rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list, &grp->grp_trans_list, LST_TRANS_SESEND, grp, lstcon_sesrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); lstcon_group_decref(grp); return rc; @@ -618,7 +618,7 @@ lstcon_group_clean(char *name, int args) int rc; rc = lstcon_group_find(name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group %s\n", name); return rc; } @@ -651,7 +651,7 @@ lstcon_nodes_remove(char *name, int count, lnet_process_id_t __user *ids_up, int rc; rc = lstcon_group_find(name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group: %s\n", name); return rc; } @@ -681,7 +681,7 @@ lstcon_group_refresh(char *name, struct list_head __user *result_up) int rc; rc = lstcon_group_find(name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group: %s\n", name); return rc; } @@ -697,7 +697,7 @@ lstcon_group_refresh(char *name, struct list_head __user *result_up) rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list, &grp->grp_trans_list, LST_TRANS_SESNEW, grp, lstcon_sesrpc_condition, &trans); - if (rc != 0) { + if (rc) { /* local error, return */ CDEBUG(D_NET, "Can't create transaction: %d\n", rc); lstcon_group_decref(grp); @@ -724,7 +724,7 @@ lstcon_group_list(int index, int len, char __user *name_up) LASSERT(name_up); list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) { - if (index-- == 0) { + if (!index--) { return copy_to_user(name_up, grp->grp_name, len) ? -EFAULT : 0; } @@ -784,7 +784,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t __user *gents_p, int rc; rc = lstcon_group_find(name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group %s\n", name); return rc; } @@ -826,7 +826,7 @@ lstcon_batch_find(const char *name, lstcon_batch_t **batpp) lstcon_batch_t *bat; list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) { - if (strncmp(bat->bat_name, name, LST_NAME_SIZE) == 0) { + if (!strncmp(bat->bat_name, name, LST_NAME_SIZE)) { *batpp = bat; return 0; } @@ -842,8 +842,8 @@ lstcon_batch_add(char *name) int i; int rc; - rc = (lstcon_batch_find(name, &bat) == 0) ? -EEXIST : 0; - if (rc != 0) { + rc = !lstcon_batch_find(name, &bat) ? -EEXIST : 0; + if (rc) { CDEBUG(D_NET, "Batch %s already exists\n", name); return rc; } @@ -904,7 +904,7 @@ lstcon_batch_list(int index, int len, char __user *name_up) LASSERT(index >= 0); list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) { - if (index-- == 0) { + if (!index--) { return copy_to_user(name_up, bat->bat_name, len) ? -EFAULT : 0; } @@ -927,7 +927,7 @@ lstcon_batch_info(char *name, lstcon_test_batch_ent_t __user *ent_up, int rc; rc = lstcon_batch_find(name, &bat); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find batch %s\n", name); return -ENOENT; } @@ -1017,7 +1017,7 @@ lstcon_batch_op(lstcon_batch_t *bat, int transop, rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list, &bat->bat_trans_list, transop, bat, lstcon_batrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); return rc; } @@ -1037,7 +1037,7 @@ lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up) lstcon_batch_t *bat; int rc; - if (lstcon_batch_find(name, &bat) != 0) { + if (lstcon_batch_find(name, &bat)) { CDEBUG(D_NET, "Can't find batch %s\n", name); return -ENOENT; } @@ -1047,7 +1047,7 @@ lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up) rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up); /* mark batch as running if it's started in any node */ - if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0) != 0) + if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0)) bat->bat_state = LST_BATCH_RUNNING; return rc; @@ -1059,7 +1059,7 @@ lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) lstcon_batch_t *bat; int rc; - if (lstcon_batch_find(name, &bat) != 0) { + if (lstcon_batch_find(name, &bat)) { CDEBUG(D_NET, "Can't find batch %s\n", name); return -ENOENT; } @@ -1069,7 +1069,7 @@ lstcon_batch_stop(char *name, int force, struct list_head __user *result_up) rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up); /* mark batch as stopped if all RPCs finished */ - if (lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0) == 0) + if (!lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0)) bat->bat_state = LST_BATCH_IDLE; return rc; @@ -1163,7 +1163,7 @@ lstcon_testrpc_condition(int transop, lstcon_node_t *nd, void *arg) LASSERT(nd->nd_id.nid != LNET_NID_ANY); - if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1) != 0) + if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1)) return -ENOMEM; if (list_empty(&ndl->ndl_link)) @@ -1189,15 +1189,15 @@ again: rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list, &test->tes_trans_list, transop, test, lstcon_testrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); return rc; } lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT); - if (lstcon_trans_stat()->trs_rpc_errno != 0 || - lstcon_trans_stat()->trs_fwk_errno != 0) { + if (lstcon_trans_stat()->trs_rpc_errno || + lstcon_trans_stat()->trs_fwk_errno) { lstcon_rpc_trans_interpreter(trans, result_up, NULL); lstcon_rpc_trans_destroy(trans); @@ -1229,7 +1229,7 @@ lstcon_verify_batch(const char *name, lstcon_batch_t **batch) int rc; rc = lstcon_batch_find(name, batch); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find batch %s\n", name); return rc; } @@ -1249,7 +1249,7 @@ lstcon_verify_group(const char *name, lstcon_group_t **grp) lstcon_ndlink_t *ndl; rc = lstcon_group_find(name, grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "can't find group %s\n", name); return rc; } @@ -1283,15 +1283,15 @@ lstcon_test_add(char *batch_name, int type, int loop, * active node */ rc = lstcon_verify_batch(batch_name, &batch); - if (rc != 0) + if (rc) goto out; rc = lstcon_verify_group(src_name, &src_grp); - if (rc != 0) + if (rc) goto out; rc = lstcon_verify_group(dst_name, &dst_grp); - if (rc != 0) + if (rc) goto out; if (dst_grp->grp_userland) @@ -1326,11 +1326,11 @@ lstcon_test_add(char *batch_name, int type, int loop, rc = lstcon_test_nodes_add(test, result_up); - if (rc != 0) + if (rc) goto out; - if (lstcon_trans_stat()->trs_rpc_errno != 0 || - lstcon_trans_stat()->trs_fwk_errno != 0) + if (lstcon_trans_stat()->trs_rpc_errno || + lstcon_trans_stat()->trs_fwk_errno) CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type, batch_name); @@ -1401,12 +1401,12 @@ lstcon_test_batch_query(char *name, int testidx, int client, int rc; rc = lstcon_batch_find(name, &batch); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find batch: %s\n", name); return rc; } - if (testidx == 0) { + if (!testidx) { translist = &batch->bat_trans_list; ndlist = &batch->bat_cli_list; hdr = &batch->bat_hdr; @@ -1414,7 +1414,7 @@ lstcon_test_batch_query(char *name, int testidx, int client, } else { /* query specified test only */ rc = lstcon_test_find(batch, testidx, &test); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find test: %d\n", testidx); return rc; } @@ -1428,16 +1428,16 @@ lstcon_test_batch_query(char *name, int testidx, int client, rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr, lstcon_batrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); return rc; } lstcon_rpc_trans_postwait(trans, timeout); - if (testidx == 0 && /* query a batch, not a test */ - lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) == 0 && - lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0) == 0) { + if (!testidx && /* query a batch, not a test */ + !lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) && + !lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0)) { /* all RPCs finished, and no active test */ batch->bat_state = LST_BATCH_IDLE; } @@ -1458,7 +1458,7 @@ lstcon_statrpc_readent(int transop, srpc_msg_t *msg, srpc_counters_t __user *srpc_stat; lnet_counters_t __user *lnet_stat; - if (rep->str_status != 0) + if (rep->str_status) return 0; sfwk_stat = (sfw_counters_t __user *)&ent_up->rpe_payload[0]; @@ -1487,7 +1487,7 @@ lstcon_ndlist_stat(struct list_head *ndlist, rc = lstcon_rpc_trans_ndlist(ndlist, &head, LST_TRANS_STATQRY, NULL, NULL, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); return rc; } @@ -1509,7 +1509,7 @@ lstcon_group_stat(char *grp_name, int timeout, int rc; rc = lstcon_group_find(grp_name, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Can't find group %s\n", grp_name); return rc; } @@ -1532,7 +1532,7 @@ lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, int rc; rc = lstcon_group_alloc(NULL, &tmp); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); return -ENOMEM; } @@ -1545,7 +1545,7 @@ lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, /* add to tmp group */ rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2); - if (rc != 0) { + if (rc) { CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET, "Failed to find or create %s: %d\n", libcfs_id2str(id), rc); @@ -1553,7 +1553,7 @@ lstcon_nodes_stat(int count, lnet_process_id_t __user *ids_up, } } - if (rc != 0) { + if (rc) { lstcon_group_decref(tmp); return rc; } @@ -1575,7 +1575,7 @@ lstcon_debug_ndlist(struct list_head *ndlist, rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY, NULL, lstcon_sesrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); return rc; } @@ -1604,7 +1604,7 @@ lstcon_batch_debug(int timeout, char *name, int rc; rc = lstcon_batch_find(name, &bat); - if (rc != 0) + if (rc) return -ENOENT; rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list : @@ -1622,7 +1622,7 @@ lstcon_group_debug(int timeout, char *name, int rc; rc = lstcon_group_find(name, &grp); - if (rc != 0) + if (rc) return -ENOENT; rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL, @@ -1644,7 +1644,7 @@ lstcon_nodes_debug(int timeout, int rc; rc = lstcon_group_alloc(NULL, &grp); - if (rc != 0) { + if (rc) { CDEBUG(D_NET, "Out of memory\n"); return rc; } @@ -1657,13 +1657,13 @@ lstcon_nodes_debug(int timeout, /* node is added to tmp group */ rc = lstcon_group_ndlink_find(grp, id, &ndl, 1); - if (rc != 0) { + if (rc) { CERROR("Can't create node link\n"); break; } } - if (rc != 0) { + if (rc) { lstcon_group_decref(grp); return rc; } @@ -1715,11 +1715,11 @@ lstcon_session_new(char *name, int key, unsigned feats, rc = lstcon_session_end(); /* lstcon_session_end() only return local error */ - if (rc != 0) + if (rc) return rc; } - if ((feats & ~LST_FEATS_MASK) != 0) { + if (feats & ~LST_FEATS_MASK) { CNETERR("Unknown session features %x\n", (feats & ~LST_FEATS_MASK)); return -EINVAL; @@ -1741,11 +1741,11 @@ lstcon_session_new(char *name, int key, unsigned feats, sizeof(console_session.ses_name)); rc = lstcon_batch_add(LST_DEFAULT_BATCH); - if (rc != 0) + if (rc) return rc; rc = lstcon_rpc_pinger_start(); - if (rc != 0) { + if (rc) { lstcon_batch_t *bat = NULL; lstcon_batch_find(LST_DEFAULT_BATCH, &bat); @@ -1754,8 +1754,8 @@ lstcon_session_new(char *name, int key, unsigned feats, return rc; } - if (copy_to_user(sid_up, &console_session.ses_id, - sizeof(lst_sid_t)) == 0) + if (!copy_to_user(sid_up, &console_session.ses_id, + sizeof(lst_sid_t))) return rc; lstcon_session_end(); @@ -1811,7 +1811,7 @@ lstcon_session_end(void) rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list, NULL, LST_TRANS_SESEND, NULL, lstcon_sesrpc_condition, &trans); - if (rc != 0) { + if (rc) { CERROR("Can't create transaction: %d\n", rc); return rc; } @@ -1865,7 +1865,7 @@ lstcon_session_feats_check(unsigned feats) { int rc = 0; - if ((feats & ~LST_FEATS_MASK) != 0) { + if (feats & ~LST_FEATS_MASK) { CERROR("Can't support these features: %x\n", (feats & ~LST_FEATS_MASK)); return -EPROTO; @@ -1883,7 +1883,7 @@ lstcon_session_feats_check(unsigned feats) spin_unlock(&console_session.ses_rpc_lock); - if (rc != 0) { + if (rc) { CERROR("remote features %x do not match with session features %x of console\n", feats, console_session.ses_features); } @@ -1913,7 +1913,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) goto out; } - if (lstcon_session_feats_check(req->msg_ses_feats) != 0) { + if (lstcon_session_feats_check(req->msg_ses_feats)) { jrep->join_status = EPROTO; goto out; } @@ -1924,9 +1924,9 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) goto out; } - if (lstcon_group_find(jreq->join_group, &grp) != 0) { + if (lstcon_group_find(jreq->join_group, &grp)) { rc = lstcon_group_alloc(jreq->join_group, &grp); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); goto out; } @@ -1943,13 +1943,13 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) } rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0); - if (rc == 0) { + if (!rc) { jrep->join_status = EEXIST; goto out; } rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1); - if (rc != 0) { + if (rc) { CERROR("Out of memory\n"); goto out; } @@ -1957,7 +1957,7 @@ lstcon_acceptor_handle(struct srpc_server_rpc *rpc) ndl->ndl_node->nd_state = LST_NODE_ACTIVE; ndl->ndl_node->nd_timeout = console_session.ses_timeout; - if (grp->grp_userland == 0) + if (!grp->grp_userland) grp->grp_userland = 1; strlcpy(jrep->join_session, console_session.ses_name, @@ -2027,7 +2027,7 @@ lstcon_console_init(void) rc = srpc_add_service(&lstcon_acceptor_service); LASSERT(rc != -EBUSY); - if (rc != 0) { + if (rc) { LIBCFS_FREE(console_session.ses_ndl_hash, sizeof(struct list_head) * LST_GLOBAL_HASHSIZE); return rc; @@ -2035,14 +2035,14 @@ lstcon_console_init(void) rc = srpc_service_add_buffers(&lstcon_acceptor_service, lstcon_acceptor_service.sv_wi_total); - if (rc != 0) { + if (rc) { rc = -ENOMEM; goto out; } rc = libcfs_register_ioctl(&lstcon_ioctl_handler); - if (rc == 0) { + if (!rc) { lstcon_rpc_module_init(); return 0; } diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c index e8221a744f83..7eca046202f2 100644 --- a/drivers/staging/lustre/lnet/selftest/framework.c +++ b/drivers/staging/lustre/lnet/selftest/framework.c @@ -100,8 +100,8 @@ do { \ __swab64s(&(lc).route_length); \ } while (0) -#define sfw_test_active(t) (atomic_read(&(t)->tsi_nactive) != 0) -#define sfw_batch_active(b) (atomic_read(&(b)->bat_nactive) != 0) +#define sfw_test_active(t) (atomic_read(&(t)->tsi_nactive)) +#define sfw_batch_active(b) (atomic_read(&(b)->bat_nactive)) static struct smoketest_framework { struct list_head fw_zombie_rpcs; /* RPCs to be recycled */ @@ -164,7 +164,7 @@ sfw_add_session_timer(void) LASSERT(!sfw_data.fw_shuttingdown); - if (!sn || sn->sn_timeout == 0) + if (!sn || !sn->sn_timeout) return; LASSERT(!sn->sn_timer_active); @@ -183,7 +183,7 @@ sfw_del_session_timer(void) if (!sn || !sn->sn_timer_active) return 0; - LASSERT(sn->sn_timeout != 0); + LASSERT(sn->sn_timeout); if (stt_del_timer(&sn->sn_timer)) { /* timer defused */ sn->sn_timer_active = 0; @@ -226,7 +226,7 @@ sfw_deactivate_session(void) } } - if (nactive != 0) + if (nactive) return; /* wait for active batches to stop */ list_del_init(&sn->sn_list); @@ -302,9 +302,9 @@ sfw_server_rpc_done(struct srpc_server_rpc *rpc) static void sfw_client_rpc_fini(srpc_client_rpc_t *rpc) { - LASSERT(rpc->crpc_bulk.bk_niov == 0); + LASSERT(!rpc->crpc_bulk.bk_niov); LASSERT(list_empty(&rpc->crpc_list)); - LASSERT(atomic_read(&rpc->crpc_refcount) == 0); + LASSERT(!atomic_read(&rpc->crpc_refcount)); CDEBUG(D_NET, "Outgoing framework RPC done: service %d, peer %s, status %s:%d:%d\n", rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), @@ -445,7 +445,7 @@ sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply) * console's responsibility to make sure all nodes in a session have * same feature mask. */ - if ((msg->msg_ses_feats & ~LST_FEATS_MASK) != 0) { + if (msg->msg_ses_feats & ~LST_FEATS_MASK) { reply->mksn_status = EPROTO; return 0; } @@ -569,7 +569,7 @@ sfw_load_test(struct sfw_test_instance *tsi) } rc = srpc_service_add_buffers(svc, nbuf); - if (rc != 0) { + if (rc) { CWARN("Failed to reserve enough buffers: service %s, %d needed: %d\n", svc->sv_name, nbuf, rc); /* @@ -696,7 +696,7 @@ sfw_unpack_addtest_req(srpc_msg_t *msg) LASSERT(msg->msg_magic == __swab32(SRPC_MSG_MAGIC)); if (req->tsr_service == SRPC_SERVICE_BRW) { - if ((msg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) { + if (!(msg->msg_ses_feats & LST_FEAT_BULK_LEN)) { test_bulk_req_t *bulk = &req->tsr_u.bulk_v0; __swab32s(&bulk->blk_opc); @@ -761,7 +761,7 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) tsi->tsi_stoptsu_onerr = !!(req->tsr_stop_onerr); rc = sfw_load_test(tsi); - if (rc != 0) { + if (rc) { LIBCFS_FREE(tsi, sizeof(*tsi)); return rc; } @@ -811,13 +811,13 @@ sfw_add_test_instance(sfw_batch_t *tsb, struct srpc_server_rpc *rpc) } rc = tsi->tsi_ops->tso_init(tsi); - if (rc == 0) { + if (!rc) { list_add_tail(&tsi->tsi_list, &tsb->bat_tests); return 0; } error: - LASSERT(rc != 0); + LASSERT(rc); sfw_destroy_test_instance(tsi); return rc; } @@ -882,9 +882,8 @@ sfw_test_rpc_done(srpc_client_rpc_t *rpc) list_del_init(&rpc->crpc_list); /* batch is stopping or loop is done or get error */ - if (tsi->tsi_stopping || - tsu->tsu_loop == 0 || - (rpc->crpc_status != 0 && tsi->tsi_stoptsu_onerr)) + if (tsi->tsi_stopping || !tsu->tsu_loop || + (rpc->crpc_status && tsi->tsi_stoptsu_onerr)) done = 1; /* dec ref for poster */ @@ -953,7 +952,7 @@ sfw_run_test(swi_workitem_t *wi) LASSERT(wi == &tsu->tsu_worker); - if (tsi->tsi_ops->tso_prep_rpc(tsu, tsu->tsu_dest, &rpc) != 0) { + if (tsi->tsi_ops->tso_prep_rpc(tsu, tsu->tsu_dest, &rpc)) { LASSERT(!rpc); goto test_done; } @@ -1080,7 +1079,7 @@ sfw_query_batch(sfw_batch_t *tsb, int testidx, srpc_batch_reply_t *reply) if (testidx < 0) return -EINVAL; - if (testidx == 0) { + if (!testidx) { reply->bar_active = atomic_read(&tsb->bat_nactive); return 0; } @@ -1129,11 +1128,11 @@ sfw_add_test(struct srpc_server_rpc *rpc) request = &rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst; reply->tsr_sid = !sn ? LST_INVALID_SID : sn->sn_id; - if (request->tsr_loop == 0 || - request->tsr_concur == 0 || + if (!request->tsr_loop || + !request->tsr_concur || request->tsr_sid.ses_nid == LNET_NID_ANY || request->tsr_ndest > SFW_MAX_NDESTS || - (request->tsr_is_client && request->tsr_ndest == 0) || + (request->tsr_is_client && !request->tsr_ndest) || request->tsr_concur > SFW_MAX_CONCUR || request->tsr_service > SRPC_SERVICE_MAX_ID || request->tsr_service <= SRPC_FRAMEWORK_SERVICE_MAX_ID) { @@ -1165,7 +1164,7 @@ sfw_add_test(struct srpc_server_rpc *rpc) int npg = sfw_id_pages(request->tsr_ndest); int len; - if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { + if (!(sn->sn_features & LST_FEAT_BULK_LEN)) { len = npg * PAGE_CACHE_SIZE; } else { @@ -1177,9 +1176,9 @@ sfw_add_test(struct srpc_server_rpc *rpc) } rc = sfw_add_test_instance(bat, rpc); - CDEBUG(rc == 0 ? D_NET : D_WARNING, + CDEBUG(!rc ? D_NET : D_WARNING, "%s test: sv %d %s, loop %d, concur %d, ndest %d\n", - rc == 0 ? "Added" : "Failed to add", request->tsr_service, + !rc ? "Added" : "Failed to add", request->tsr_service, request->tsr_is_client ? "client" : "server", request->tsr_loop, request->tsr_concur, request->tsr_ndest); @@ -1248,7 +1247,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() != 0) { + if (sfw_del_session_timer()) { CERROR("Dropping RPC (%s) from %s: racing with expiry timer.", sv->sv_name, libcfs_id2str(rpc->srpc_peer)); spin_unlock(&sfw_data.fw_lock); @@ -1277,7 +1276,7 @@ sfw_handle_server_rpc(struct srpc_server_rpc *rpc) goto out; } - } else if ((request->msg_ses_feats & ~LST_FEATS_MASK) != 0) { + } 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 @@ -1348,7 +1347,7 @@ sfw_bulk_ready(struct srpc_server_rpc *rpc, int status) spin_lock(&sfw_data.fw_lock); - if (status != 0) { + if (status) { CERROR("Bulk transfer failed for RPC: service %s, peer %s, status %d\n", sv->sv_name, libcfs_id2str(rpc->srpc_peer), status); spin_unlock(&sfw_data.fw_lock); @@ -1360,7 +1359,7 @@ sfw_bulk_ready(struct srpc_server_rpc *rpc, int status) return -ESHUTDOWN; } - if (sfw_del_session_timer() != 0) { + if (sfw_del_session_timer()) { CERROR("Dropping RPC (%s) from %s: racing with expiry timer", sv->sv_name, libcfs_id2str(rpc->srpc_peer)); spin_unlock(&sfw_data.fw_lock); @@ -1394,7 +1393,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, LASSERT(!sfw_data.fw_shuttingdown); LASSERT(service <= SRPC_FRAMEWORK_SERVICE_MAX_ID); - if (nbulkiov == 0 && !list_empty(&sfw_data.fw_zombie_rpcs)) { + if (!nbulkiov && !list_empty(&sfw_data.fw_zombie_rpcs)) { rpc = list_entry(sfw_data.fw_zombie_rpcs.next, srpc_client_rpc_t, crpc_list); list_del(&rpc->crpc_list); @@ -1408,7 +1407,7 @@ sfw_create_rpc(lnet_process_id_t peer, int service, if (!rpc) { rpc = srpc_create_client_rpc(peer, service, nbulkiov, bulklen, done, - nbulkiov != 0 ? NULL : + nbulkiov ? NULL : sfw_client_rpc_fini, priv); } @@ -1661,10 +1660,10 @@ sfw_startup(void) return -EINVAL; } - if (session_timeout == 0) + if (!session_timeout) CWARN("Zero session_timeout specified - test sessions never expire.\n"); - if (rpc_timeout == 0) + if (!rpc_timeout) CWARN("Zero rpc_timeout specified - test RPC never expire.\n"); memset(&sfw_data, 0, sizeof(struct smoketest_framework)); @@ -1680,12 +1679,12 @@ sfw_startup(void) brw_init_test_client(); brw_init_test_service(); rc = sfw_register_test(&brw_test_service, &brw_test_client); - LASSERT(rc == 0); + LASSERT(!rc); ping_init_test_client(); ping_init_test_service(); rc = sfw_register_test(&ping_test_service, &ping_test_client); - LASSERT(rc == 0); + LASSERT(!rc); error = 0; list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) { @@ -1693,7 +1692,7 @@ sfw_startup(void) rc = srpc_add_service(sv); LASSERT(rc != -EBUSY); - if (rc != 0) { + if (rc) { CWARN("Failed to add %s service: %d\n", sv->sv_name, rc); error = rc; @@ -1713,7 +1712,7 @@ sfw_startup(void) rc = srpc_add_service(sv); LASSERT(rc != -EBUSY); - if (rc != 0) { + if (rc) { CWARN("Failed to add %s service: %d\n", sv->sv_name, rc); error = rc; @@ -1724,14 +1723,14 @@ sfw_startup(void) continue; rc = srpc_service_add_buffers(sv, sv->sv_wi_total); - if (rc != 0) { + if (rc) { CWARN("Failed to reserve enough buffers: service %s, %d needed: %d\n", sv->sv_name, sv->sv_wi_total, rc); error = -ENOMEM; } } - if (error != 0) + if (error) sfw_shutdown(); return error; } @@ -1749,12 +1748,12 @@ sfw_shutdown(void) lst_wait_until(!sfw_data.fw_active_srpc, sfw_data.fw_lock, "waiting for active RPC to finish.\n"); - if (sfw_del_session_timer() != 0) + if (sfw_del_session_timer()) lst_wait_until(!sfw_data.fw_session, sfw_data.fw_lock, "waiting for session timer to explode.\n"); sfw_deactivate_session(); - lst_wait_until(atomic_read(&sfw_data.fw_nzombies) == 0, + lst_wait_until(!atomic_read(&sfw_data.fw_nzombies), sfw_data.fw_lock, "waiting for %d zombie sessions to die.\n", atomic_read(&sfw_data.fw_nzombies)); diff --git a/drivers/staging/lustre/lnet/selftest/module.c b/drivers/staging/lustre/lnet/selftest/module.c index 741509afb906..c4bf44290ed9 100644 --- a/drivers/staging/lustre/lnet/selftest/module.c +++ b/drivers/staging/lustre/lnet/selftest/module.c @@ -98,7 +98,7 @@ lnet_selftest_init(void) rc = cfs_wi_sched_create("lst_s", lnet_cpt_table(), CFS_CPT_ANY, 1, &lst_sched_serial); - if (rc != 0) { + if (rc) { CERROR("Failed to create serial WI scheduler for LST\n"); return rc; } @@ -117,7 +117,7 @@ lnet_selftest_init(void) nthrs = max(nthrs - 1, 1); rc = cfs_wi_sched_create("lst_t", lnet_cpt_table(), i, nthrs, &lst_sched_test[i]); - if (rc != 0) { + if (rc) { CERROR("Failed to create CPT affinity WI scheduler %d for LST\n", i); goto error; @@ -125,21 +125,21 @@ lnet_selftest_init(void) } rc = srpc_startup(); - if (rc != 0) { + if (rc) { CERROR("LST can't startup rpc\n"); goto error; } lst_init_step = LST_INIT_RPC; rc = sfw_startup(); - if (rc != 0) { + if (rc) { CERROR("LST can't startup framework\n"); goto error; } lst_init_step = LST_INIT_FW; rc = lstcon_console_init(); - if (rc != 0) { + if (rc) { CERROR("LST can't startup console\n"); goto error; } diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c index 01ceee53311b..9d27e395cba2 100644 --- a/drivers/staging/lustre/lnet/selftest/ping_test.c +++ b/drivers/staging/lustre/lnet/selftest/ping_test.c @@ -61,7 +61,7 @@ ping_client_init(sfw_test_instance_t *tsi) sfw_session_t *sn = tsi->tsi_batch->bat_session; LASSERT(tsi->tsi_is_client); - LASSERT(sn && (sn->sn_features & ~LST_FEATS_MASK) == 0); + LASSERT(sn && !(sn->sn_features & ~LST_FEATS_MASK)); spin_lock_init(&lst_ping_data.pnd_lock); lst_ping_data.pnd_counter = 0; @@ -96,10 +96,10 @@ ping_client_prep_rpc(sfw_test_unit_t *tsu, int rc; LASSERT(sn); - LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); + LASSERT(!(sn->sn_features & ~LST_FEATS_MASK)); rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, 0, 0, rpc); - if (rc != 0) + if (rc) return rc; req = &(*rpc)->crpc_reqstmsg.msg_body.ping_reqst; @@ -128,7 +128,7 @@ ping_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) LASSERT(sn); - if (rpc->crpc_status != 0) { + if (rpc->crpc_status) { if (!tsi->tsi_stopping) /* rpc could have been aborted */ atomic_inc(&sn->sn_ping_errors); CERROR("Unable to ping %s (%d): %d\n", @@ -198,7 +198,7 @@ ping_server_handle(struct srpc_server_rpc *rpc) rep->pnr_seq = req->pnr_seq; rep->pnr_magic = LST_PING_TEST_MAGIC; - if ((reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) != 0) { + if (reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) { replymsg->msg_ses_feats = LST_FEATS_MASK; rep->pnr_status = EPROTO; return 0; diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c index 1e78711634f2..f95fd9b32333 100644 --- a/drivers/staging/lustre/lnet/selftest/rpc.c +++ b/drivers/staging/lustre/lnet/selftest/rpc.c @@ -284,7 +284,7 @@ srpc_service_init(struct srpc_service *svc) swi_init_workitem(&scd->scd_buf_wi, scd, srpc_add_buffer, lst_sched_test[i]); - if (i != 0 && srpc_serv_is_framework(svc)) { + if (i && srpc_serv_is_framework(svc)) { /* * NB: framework service only needs srpc_service_cd for * one partition, but we allocate for all to make @@ -315,7 +315,7 @@ srpc_add_service(struct srpc_service *sv) LASSERT(0 <= id && id <= SRPC_SERVICE_MAX_ID); - if (srpc_service_init(sv) != 0) + if (srpc_service_init(sv)) return -ENOMEM; spin_lock(&srpc_data.rpc_glock); @@ -366,7 +366,7 @@ srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf, rc = LNetMEAttach(portal, peer, matchbits, 0, LNET_UNLINK, local ? LNET_INS_LOCAL : LNET_INS_AFTER, &meh); - if (rc != 0) { + if (rc) { CERROR("LNetMEAttach failed: %d\n", rc); LASSERT(rc == -ENOMEM); return -ENOMEM; @@ -380,12 +380,12 @@ srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf, md.eq_handle = srpc_data.rpc_lnet_eq; rc = LNetMDAttach(meh, md, LNET_UNLINK, mdh); - if (rc != 0) { + if (rc) { CERROR("LNetMDAttach failed: %d\n", rc); LASSERT(rc == -ENOMEM); rc = LNetMEUnlink(meh); - LASSERT(rc == 0); + LASSERT(!rc); return -ENOMEM; } @@ -406,11 +406,11 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, md.start = buf; md.length = len; md.eq_handle = srpc_data.rpc_lnet_eq; - md.threshold = ((options & LNET_MD_OP_GET) != 0) ? 2 : 1; + md.threshold = options & LNET_MD_OP_GET ? 2 : 1; md.options = options & ~(LNET_MD_OP_PUT | LNET_MD_OP_GET); rc = LNetMDBind(md, LNET_UNLINK, mdh); - if (rc != 0) { + if (rc) { CERROR("LNetMDBind failed: %d\n", rc); LASSERT(rc == -ENOMEM); return -ENOMEM; @@ -421,18 +421,18 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, * they're only meaningful for MDs attached to an ME (i.e. passive * buffers... */ - if ((options & LNET_MD_OP_PUT) != 0) { + if (options & LNET_MD_OP_PUT) { rc = LNetPut(self, *mdh, LNET_NOACK_REQ, peer, portal, matchbits, 0, 0); } else { - LASSERT((options & LNET_MD_OP_GET) != 0); + LASSERT(options & LNET_MD_OP_GET); rc = LNetGet(self, *mdh, peer, portal, matchbits, 0); } - if (rc != 0) { + if (rc) { CERROR("LNet%s(%s, %d, %lld) failed: %d\n", - ((options & LNET_MD_OP_PUT) != 0) ? "Put" : "Get", + options & LNET_MD_OP_PUT ? "Put" : "Get", libcfs_id2str(peer), portal, matchbits, rc); /* @@ -440,7 +440,7 @@ srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len, * with failure, so fall through and return success here. */ rc = LNetMDUnlink(*mdh); - LASSERT(rc == 0); + LASSERT(!rc); } else { CDEBUG(D_NET, "Posted active RDMA: peer %s, portal %u, matchbits %#llx\n", libcfs_id2str(peer), portal, matchbits); @@ -487,7 +487,7 @@ srpc_service_post_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf) */ spin_lock(&scd->scd_lock); - if (rc == 0) { + if (!rc) { if (!sv->sv_shuttingdown) return 0; @@ -555,7 +555,7 @@ srpc_add_buffer(struct swi_workitem *wi) } rc = srpc_service_post_buffer(scd, buf); - if (rc != 0) + if (rc) break; /* buf has been freed inside */ LASSERT(scd->scd_buf_posting > 0); @@ -564,7 +564,7 @@ srpc_add_buffer(struct swi_workitem *wi) scd->scd_buf_low = max(2, scd->scd_buf_total / 4); } - if (rc != 0) { + if (rc) { scd->scd_buf_err_stamp = ktime_get_real_seconds(); scd->scd_buf_err = rc; @@ -616,12 +616,12 @@ srpc_service_add_buffers(struct srpc_service *sv, int nbuffer) * block all WIs pending on lst_sched_serial for a moment * which is not good but not fatal. */ - lst_wait_until(scd->scd_buf_err != 0 || - (scd->scd_buf_adjust == 0 && - scd->scd_buf_posting == 0), + lst_wait_until(scd->scd_buf_err || + (!scd->scd_buf_adjust && + !scd->scd_buf_posting), scd->scd_lock, "waiting for adding buffer\n"); - if (scd->scd_buf_err != 0 && rc == 0) + if (scd->scd_buf_err && !rc) rc = scd->scd_buf_err; spin_unlock(&scd->scd_lock); @@ -702,7 +702,7 @@ srpc_service_recycle_buffer(struct srpc_service_cd *scd, srpc_buffer_t *buf) __must_hold(&scd->scd_lock) { if (!scd->scd_svc->sv_shuttingdown && scd->scd_buf_adjust >= 0) { - if (srpc_service_post_buffer(scd, buf) != 0) { + if (srpc_service_post_buffer(scd, buf)) { CWARN("Failed to post %s buffer\n", scd->scd_svc->sv_name); } @@ -715,7 +715,7 @@ srpc_service_recycle_buffer(struct srpc_service_cd *scd, srpc_buffer_t *buf) if (scd->scd_buf_adjust < 0) { scd->scd_buf_adjust++; if (scd->scd_buf_adjust < 0 && - scd->scd_buf_total == 0 && scd->scd_buf_posting == 0) { + !scd->scd_buf_total && !scd->scd_buf_posting) { CDEBUG(D_INFO, "Try to recycle %d buffers but nothing left\n", scd->scd_buf_adjust); @@ -807,7 +807,7 @@ srpc_send_request(srpc_client_rpc_t *rpc) sizeof(srpc_msg_t), LNET_MD_OP_PUT, rpc->crpc_dest, LNET_NID_ANY, &rpc->crpc_reqstmdh, ev); - if (rc != 0) { + if (rc) { LASSERT(rc == -ENOMEM); ev->ev_fired = 1; /* no more event expected */ } @@ -831,7 +831,7 @@ srpc_prepare_reply(srpc_client_rpc_t *rpc) &rpc->crpc_replymsg, sizeof(srpc_msg_t), LNET_MD_OP_PUT, rpc->crpc_dest, &rpc->crpc_replymdh, ev); - if (rc != 0) { + if (rc) { LASSERT(rc == -ENOMEM); ev->ev_fired = 1; /* no more event expected */ } @@ -849,7 +849,7 @@ srpc_prepare_bulk(srpc_client_rpc_t *rpc) LASSERT(bk->bk_niov <= LNET_MAX_IOV); - if (bk->bk_niov == 0) + if (!bk->bk_niov) return 0; /* nothing to do */ opt = bk->bk_sink ? LNET_MD_OP_PUT : LNET_MD_OP_GET; @@ -864,7 +864,7 @@ srpc_prepare_bulk(srpc_client_rpc_t *rpc) rc = srpc_post_passive_rdma(SRPC_RDMA_PORTAL, 0, *id, &bk->bk_iovs[0], bk->bk_niov, opt, rpc->crpc_dest, &bk->bk_mdh, ev); - if (rc != 0) { + if (rc) { LASSERT(rc == -ENOMEM); ev->ev_fired = 1; /* no more event expected */ } @@ -893,7 +893,7 @@ srpc_do_bulk(struct srpc_server_rpc *rpc) &bk->bk_iovs[0], bk->bk_niov, opt, rpc->srpc_peer, rpc->srpc_self, &bk->bk_mdh, ev); - if (rc != 0) + if (rc) ev->ev_fired = 1; /* no more event expected */ return rc; } @@ -906,16 +906,16 @@ srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status) struct srpc_service *sv = scd->scd_svc; srpc_buffer_t *buffer; - LASSERT(status != 0 || rpc->srpc_wi.swi_state == SWI_STATE_DONE); + LASSERT(status || rpc->srpc_wi.swi_state == SWI_STATE_DONE); rpc->srpc_status = status; - CDEBUG_LIMIT(status == 0 ? D_NET : D_NETERROR, + CDEBUG_LIMIT(!status ? D_NET : D_NETERROR, "Server RPC %p done: service %s, peer %s, status %s:%d\n", rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer), swi_state2str(rpc->srpc_wi.swi_state), status); - if (status != 0) { + if (status) { spin_lock(&srpc_data.rpc_glock); srpc_data.rpc_counters.rpcs_dropped++; spin_unlock(&srpc_data.rpc_glock); @@ -1003,7 +1003,7 @@ srpc_handle_rpc(swi_workitem_t *wi) msg = &rpc->srpc_reqstbuf->buf_msg; reply = &rpc->srpc_replymsg.msg_body.reply; - if (msg->msg_magic == 0) { + if (!msg->msg_magic) { /* moaned already in srpc_lnet_ev_handler */ srpc_server_rpc_done(rpc, EBADMSG); return 1; @@ -1019,8 +1019,8 @@ srpc_handle_rpc(swi_workitem_t *wi) } else { reply->status = 0; rc = (*sv->sv_handler)(rpc); - LASSERT(reply->status == 0 || !rpc->srpc_bulk); - if (rc != 0) { + LASSERT(!reply->status || !rpc->srpc_bulk); + if (rc) { srpc_server_rpc_done(rpc, rc); return 1; } @@ -1030,7 +1030,7 @@ srpc_handle_rpc(swi_workitem_t *wi) if (rpc->srpc_bulk) { rc = srpc_do_bulk(rpc); - if (rc == 0) + if (!rc) return 0; /* wait for bulk */ LASSERT(ev->ev_fired); @@ -1046,7 +1046,7 @@ srpc_handle_rpc(swi_workitem_t *wi) if (sv->sv_bulk_ready) rc = (*sv->sv_bulk_ready) (rpc, rc); - if (rc != 0) { + if (rc) { srpc_server_rpc_done(rpc, rc); return 1; } @@ -1054,7 +1054,7 @@ srpc_handle_rpc(swi_workitem_t *wi) wi->swi_state = SWI_STATE_REPLY_SUBMITTED; rc = srpc_send_reply(rpc); - if (rc == 0) + if (!rc) return 0; /* wait for reply */ srpc_server_rpc_done(rpc, rc); return 1; @@ -1102,7 +1102,7 @@ srpc_add_client_rpc_timer(srpc_client_rpc_t *rpc) { stt_timer_t *timer = &rpc->crpc_timer; - if (rpc->crpc_timeout == 0) + if (!rpc->crpc_timeout) return; INIT_LIST_HEAD(&timer->stt_list); @@ -1123,7 +1123,7 @@ static void srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc) { /* timer not planted or already exploded */ - if (rpc->crpc_timeout == 0) + if (!rpc->crpc_timeout) return; /* timer successfully defused */ @@ -1131,7 +1131,7 @@ srpc_del_client_rpc_timer(srpc_client_rpc_t *rpc) return; /* timer detonated, wait for it to explode */ - while (rpc->crpc_timeout != 0) { + while (rpc->crpc_timeout) { spin_unlock(&rpc->crpc_lock); schedule(); @@ -1145,17 +1145,17 @@ srpc_client_rpc_done(srpc_client_rpc_t *rpc, int status) { swi_workitem_t *wi = &rpc->crpc_wi; - LASSERT(status != 0 || wi->swi_state == SWI_STATE_DONE); + LASSERT(status || wi->swi_state == SWI_STATE_DONE); spin_lock(&rpc->crpc_lock); rpc->crpc_closed = 1; - if (rpc->crpc_status == 0) + if (!rpc->crpc_status) rpc->crpc_status = status; srpc_del_client_rpc_timer(rpc); - CDEBUG_LIMIT((status == 0) ? D_NET : D_NETERROR, + CDEBUG_LIMIT(!status ? D_NET : D_NETERROR, "Client RPC done: service %d, peer %s, status %s:%d:%d\n", rpc->crpc_service, libcfs_id2str(rpc->crpc_dest), swi_state2str(wi->swi_state), rpc->crpc_aborted, status); @@ -1212,13 +1212,13 @@ srpc_send_rpc(swi_workitem_t *wi) LASSERT(!srpc_event_pending(rpc)); rc = srpc_prepare_reply(rpc); - if (rc != 0) { + if (rc) { srpc_client_rpc_done(rpc, rc); return 1; } rc = srpc_prepare_bulk(rpc); - if (rc != 0) + if (rc) break; wi->swi_state = SWI_STATE_REQUEST_SUBMITTED; @@ -1235,7 +1235,7 @@ srpc_send_rpc(swi_workitem_t *wi) break; rc = rpc->crpc_reqstev.ev_status; - if (rc != 0) + if (rc) break; wi->swi_state = SWI_STATE_REQUEST_SENT; @@ -1247,7 +1247,7 @@ srpc_send_rpc(swi_workitem_t *wi) break; rc = rpc->crpc_replyev.ev_status; - if (rc != 0) + if (rc) break; srpc_unpack_msg_hdr(reply); @@ -1262,7 +1262,7 @@ srpc_send_rpc(swi_workitem_t *wi) break; } - if (do_bulk && reply->msg_body.reply.status != 0) { + if (do_bulk && reply->msg_body.reply.status) { CWARN("Remote error %d at %s, unlink bulk buffer in case peer didn't initiate bulk transfer\n", reply->msg_body.reply.status, libcfs_id2str(rpc->crpc_dest)); @@ -1284,7 +1284,7 @@ srpc_send_rpc(swi_workitem_t *wi) * remote error. */ if (do_bulk && rpc->crpc_bulkev.ev_lnet == LNET_EVENT_UNLINK && - rpc->crpc_status == 0 && reply->msg_body.reply.status != 0) + !rpc->crpc_status && reply->msg_body.reply.status) rc = 0; wi->swi_state = SWI_STATE_DONE; @@ -1292,7 +1292,7 @@ srpc_send_rpc(swi_workitem_t *wi) return 1; } - if (rc != 0) { + if (rc) { spin_lock(&rpc->crpc_lock); srpc_abort_rpc(rpc, rc); spin_unlock(&rpc->crpc_lock); @@ -1334,7 +1334,7 @@ srpc_create_client_rpc(lnet_process_id_t peer, int service, void srpc_abort_rpc(srpc_client_rpc_t *rpc, int why) { - LASSERT(why != 0); + LASSERT(why); if (rpc->crpc_aborted || /* already aborted */ rpc->crpc_closed) /* callback imminent */ @@ -1387,7 +1387,7 @@ srpc_send_reply(struct srpc_server_rpc *rpc) * Repost buffer before replying since test client * might send me another RPC once it gets the reply */ - if (srpc_service_post_buffer(scd, buffer) != 0) + if (srpc_service_post_buffer(scd, buffer)) CWARN("Failed to repost %s buffer\n", sv->sv_name); rpc->srpc_reqstbuf = NULL; } @@ -1406,7 +1406,7 @@ srpc_send_reply(struct srpc_server_rpc *rpc) sizeof(*msg), LNET_MD_OP_PUT, rpc->srpc_peer, rpc->srpc_self, &rpc->srpc_replymdh, ev); - if (rc != 0) + if (rc) ev->ev_fired = 1; /* no more event expected */ return rc; } @@ -1426,7 +1426,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) LASSERT(!in_interrupt()); - if (ev->status != 0) { + if (ev->status) { spin_lock(&srpc_data.rpc_glock); srpc_data.rpc_counters.errors++; spin_unlock(&srpc_data.rpc_glock); @@ -1440,7 +1440,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) rpcev->ev_status, rpcev->ev_type, rpcev->ev_lnet); LBUG(); case SRPC_REQUEST_SENT: - if (ev->status == 0 && ev->type != LNET_EVENT_UNLINK) { + if (!ev->status && ev->type != LNET_EVENT_UNLINK) { spin_lock(&srpc_data.rpc_glock); srpc_data.rpc_counters.rpcs_sent++; spin_unlock(&srpc_data.rpc_glock); @@ -1462,7 +1462,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) spin_lock(&crpc->crpc_lock); - LASSERT(rpcev->ev_fired == 0); + LASSERT(!rpcev->ev_fired); rpcev->ev_fired = 1; rpcev->ev_status = (ev->type == LNET_EVENT_UNLINK) ? -EINTR : ev->status; @@ -1501,15 +1501,15 @@ srpc_lnet_ev_handler(lnet_event_t *ev) break; } - if (scd->scd_buf_err_stamp != 0 && + if (scd->scd_buf_err_stamp && scd->scd_buf_err_stamp < ktime_get_real_seconds()) { /* re-enable adding buffer */ scd->scd_buf_err_stamp = 0; scd->scd_buf_err = 0; } - if (scd->scd_buf_err == 0 && /* adding buffer is enabled */ - scd->scd_buf_adjust == 0 && + 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, SFW_TEST_WI_MIN); @@ -1520,7 +1520,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) msg = &buffer->buf_msg; type = srpc_service2request(sv->sv_id); - if (ev->status != 0 || ev->mlength != sizeof(*msg) || + if (ev->status || ev->mlength != sizeof(*msg) || (msg->msg_type != type && msg->msg_type != __swab32(type)) || (msg->msg_magic != SRPC_MSG_MAGIC && @@ -1569,7 +1569,7 @@ srpc_lnet_ev_handler(lnet_event_t *ev) break; /* wait for final event */ case SRPC_BULK_PUT_SENT: - if (ev->status == 0 && ev->type != LNET_EVENT_UNLINK) { + if (!ev->status && ev->type != LNET_EVENT_UNLINK) { spin_lock(&srpc_data.rpc_glock); if (rpcev->ev_type == SRPC_BULK_GET_RPLD) @@ -1622,22 +1622,22 @@ srpc_startup(void) LNetInvalidateHandle(&srpc_data.rpc_lnet_eq); rc = LNetEQAlloc(0, srpc_lnet_ev_handler, &srpc_data.rpc_lnet_eq); - if (rc != 0) { + if (rc) { CERROR("LNetEQAlloc() has failed: %d\n", rc); goto bail; } rc = LNetSetLazyPortal(SRPC_FRAMEWORK_REQUEST_PORTAL); - LASSERT(rc == 0); + LASSERT(!rc); rc = LNetSetLazyPortal(SRPC_REQUEST_PORTAL); - LASSERT(rc == 0); + LASSERT(!rc); srpc_data.rpc_state = SRPC_STATE_EQ_INIT; rc = stt_startup(); bail: - if (rc != 0) + if (rc) srpc_shutdown(); else srpc_data.rpc_state = SRPC_STATE_RUNNING; @@ -1675,9 +1675,9 @@ srpc_shutdown(void) case SRPC_STATE_EQ_INIT: rc = LNetClearLazyPortal(SRPC_FRAMEWORK_REQUEST_PORTAL); rc = LNetClearLazyPortal(SRPC_REQUEST_PORTAL); - LASSERT(rc == 0); + LASSERT(!rc); rc = LNetEQFree(srpc_data.rpc_lnet_eq); - LASSERT(rc == 0); /* the EQ should have no user by now */ + LASSERT(!rc); /* the EQ should have no user by now */ case SRPC_STATE_NI_INIT: LNetNIFini(); diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h index e6367ec21453..f6c824472268 100644 --- a/drivers/staging/lustre/lnet/selftest/selftest.h +++ b/drivers/staging/lustre/lnet/selftest/selftest.h @@ -255,9 +255,9 @@ do { \ srpc_destroy_client_rpc(rpc); \ } while (0) -#define srpc_event_pending(rpc) ((rpc)->crpc_bulkev.ev_fired == 0 || \ - (rpc)->crpc_reqstev.ev_fired == 0 || \ - (rpc)->crpc_replyev.ev_fired == 0) +#define srpc_event_pending(rpc) (!(rpc)->crpc_bulkev.ev_fired || \ + !(rpc)->crpc_reqstev.ev_fired || \ + !(rpc)->crpc_replyev.ev_fired) /* CPU partition data of srpc service */ struct srpc_service_cd { @@ -506,7 +506,7 @@ srpc_destroy_client_rpc(srpc_client_rpc_t *rpc) { LASSERT(rpc); LASSERT(!srpc_event_pending(rpc)); - LASSERT(atomic_read(&rpc->crpc_refcount) == 0); + LASSERT(!atomic_read(&rpc->crpc_refcount)); if (!rpc->crpc_fini) LIBCFS_FREE(rpc, srpc_client_rpc_size(rpc)); @@ -601,7 +601,7 @@ srpc_wait_service_shutdown(srpc_service_t *sv) LASSERT(sv->sv_shuttingdown); - while (srpc_finish_service(sv) == 0) { + while (!srpc_finish_service(sv)) { i++; CDEBUG(((i & -i) == i) ? D_WARNING : D_NET, "Waiting for %s service to shutdown...\n", diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index dce5137c7dfe..c89137182eee 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -218,7 +218,7 @@ stt_startup(void) stt_data.stt_nthreads = 0; init_waitqueue_head(&stt_data.stt_waitq); rc = stt_start_timer_thread(); - if (rc != 0) + if (rc) CERROR("Can't spawn timer thread: %d\n", rc); return rc; @@ -237,7 +237,7 @@ stt_shutdown(void) stt_data.stt_shuttingdown = 1; wake_up(&stt_data.stt_waitq); - lst_wait_until(stt_data.stt_nthreads == 0, stt_data.stt_lock, + lst_wait_until(!stt_data.stt_nthreads, stt_data.stt_lock, "waiting for %d threads to terminate\n", stt_data.stt_nthreads); -- cgit From d60fc1bbc26a16e79258d9b11baea83f49ff7776 Mon Sep 17 00:00:00 2001 From: Niranjan Dighe Date: Sun, 14 Feb 2016 08:51:48 +0530 Subject: staging: lustre/lnet: Fix wrong typecasting warning generated by sparse Fix the following warning generated about type casting by sparse warning: cast removes address space of expression The current implementation casts the structure pointers with (char *) without __user annotation and then adds sizeof struct to it, thereby generating the sparse warning. Fixed this by removing the unnecessary char pointer type cast. Signed-off-by: Niranjan Dighe Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lnet/selftest/console.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 59cd554e47b9..54fb1ab521bd 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -1462,10 +1462,8 @@ lstcon_statrpc_readent(int transop, srpc_msg_t *msg, return 0; sfwk_stat = (sfw_counters_t __user *)&ent_up->rpe_payload[0]; - srpc_stat = (srpc_counters_t __user *) - ((char *)sfwk_stat + sizeof(*sfwk_stat)); - lnet_stat = (lnet_counters_t __user *) - ((char *)srpc_stat + sizeof(*srpc_stat)); + srpc_stat = (srpc_counters_t __user *)(sfwk_stat + 1); + lnet_stat = (lnet_counters_t __user *)(srpc_stat + 1); if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) || copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) || -- cgit From acdd1b8e681405beeb1f73333947fd5a42b871e9 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 20:32:48 +0530 Subject: staging: lustre: obdclass: Use IS_ERR_OR_NULL Use macro IS_ERR_OR_NULL in place of tests for NULL and IS_ERR. The Coccinelle semantic patch used to make the change is as follows: // @@ expression e; @@ - e == NULL || IS_ERR(e) + IS_ERR_OR_NULL(e) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/kernelcomm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c index be4867c5446c..8405eccdac19 100644 --- a/drivers/staging/lustre/lustre/obdclass/kernelcomm.c +++ b/drivers/staging/lustre/lustre/obdclass/kernelcomm.c @@ -59,7 +59,7 @@ int libcfs_kkuc_msg_put(struct file *filp, void *payload) mm_segment_t fs; int rc = -ENXIO; - if (!filp || IS_ERR(filp)) + if (IS_ERR_OR_NULL(filp)) return -EBADF; if (kuch->kuc_magic != KUC_MAGIC) { -- cgit From da58688fb02100c1275d15213d01c06565933e14 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 12 Feb 2016 20:07:54 +0530 Subject: Staging: lustre: llite: Remove NULL check before kfree NULL check before kfree is unnecessary so remove it. Semantic patch used: // @@ expression E; @@ - if (E != NULL) { kfree(E); } + kfree(E); @@ expression E; @@ - if (E != NULL) { kfree(E); E = NULL; } + kfree(E); + E = NULL; // Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/llite/xattr.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c index 8eb43f192d1f..fa477e76c7d7 100644 --- a/drivers/staging/lustre/lustre/llite/xattr.c +++ b/drivers/staging/lustre/lustre/llite/xattr.c @@ -192,11 +192,10 @@ int ll_setxattr_common(struct inode *inode, const char *name, valid, name, pv, size, 0, flags, ll_i2suppgid(inode), &req); #ifdef CONFIG_FS_POSIX_ACL - if (new_value != NULL) - /* - * Release the posix ACL space. - */ - kfree(new_value); + /* + * Release the posix ACL space. + */ + kfree(new_value); if (acl != NULL) lustre_ext_acl_xattr_free(acl); #endif -- cgit From 639868832a2c27455794d04ce30b5396eefbcd62 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 12 Feb 2016 11:53:28 +0530 Subject: Staging: lustre: obdclass: Declare function as static Declare the function cache_stats_print as static since it is used only in this file. Used grep to find occurences. Problem found using sparse. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/lustre/lustre/obdclass/cl_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/lustre/lustre/obdclass/cl_object.c b/drivers/staging/lustre/lustre/obdclass/cl_object.c index 57c8d5412bbd..f118983608cd 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_object.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_object.c @@ -362,7 +362,8 @@ void cache_stats_init(struct cache_stats *cs, const char *name) atomic_set(&cs->cs_stats[i], 0); } -int cache_stats_print(const struct cache_stats *cs, struct seq_file *m, int h) +static int cache_stats_print(const struct cache_stats *cs, + struct seq_file *m, int h) { int i; /* -- cgit From 3a334ea5105ff7a1556f351caa2d028e7e7a6c8f Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Fri, 12 Feb 2016 15:39:26 +0800 Subject: staging: fbtft: Modify block comments based on kernel coding style Add the required trailing * on subsequent lines as well as move the */ on a separate line. Checkpatch found this issue. Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9163.c | 69 ++++++++++++++++---------------- drivers/staging/fbtft/fb_ili9320.c | 8 ++-- drivers/staging/fbtft/fb_ili9325.c | 80 +++++++++++++++++++------------------- drivers/staging/fbtft/fb_ili9341.c | 8 ++-- 4 files changed, 83 insertions(+), 82 deletions(-) diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index cbcfbb531612..3f6c245ef2af 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -39,11 +39,11 @@ #endif /* ILI9163C commands */ -#define CMD_FRMCTR1 0xB1 /* Frame Rate Control - (In normal mode/Full colors) */ +#define CMD_FRMCTR1 0xB1 /* Frame Rate Control */ + /* (In normal mode/Full colors) */ #define CMD_FRMCTR2 0xB2 /* Frame Rate Control (In Idle mode/8-colors) */ -#define CMD_FRMCTR3 0xB3 /* Frame Rate Control - (In Partial mode/full colors) */ +#define CMD_FRMCTR3 0xB3 /* Frame Rate Control */ + /* (In Partial mode/full colors) */ #define CMD_DINVCTR 0xB4 /* Display Inversion Control */ #define CMD_RGBBLK 0xB5 /* RGB Interface Blanking Porch setting */ #define CMD_DFUNCTR 0xB6 /* Display Function set 5 */ @@ -63,17 +63,18 @@ #define CMD_GAMRSEL 0xF2 /* GAM_R_SEL */ /* -This display: -http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI-Color-TFT-LCD-Display-Module-/271422122271 -This particular display has a design error! The controller has 3 pins to -configure to constrain the memory and resolution to a fixed dimension (in -that case 128x128) but they leaved those pins configured for 128x160 so -there was several pixel memory addressing problems. -I solved by setup several parameters that dinamically fix the resolution as -needit so below the parameters for this display. If you have a strain or a -correct display (can happen with chinese) you can copy those parameters and -create setup for different displays. -*/ + * This display: + * http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI- + * Color-TFT-LCD-Display-Module-/271422122271 + * This particular display has a design error! The controller has 3 pins to + * configure to constrain the memory and resolution to a fixed dimension (in + * that case 128x128) but they leaved those pins configured for 128x160 so + * there was several pixel memory addressing problems. + * I solved by setup several parameters that dinamically fix the resolution as + * needit so below the parameters for this display. If you have a strain or a + * correct display (can happen with chinese) you can copy those parameters and + * create setup for different displays. + */ #ifdef RED #define __OFFSET 32 /*see note 2 - this is the red version */ @@ -153,25 +154,25 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, } /* -7) MY: 1(bottom to top), 0(top to bottom) Row Address Order -6) MX: 1(R to L), 0(L to R) Column Address Order -5) MV: 1(Exchanged), 0(normal) Row/Column exchange -4) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order -3) RGB: 1(BGR), 0(RGB) Color Space -2) MH: 1(R to L), 0(L to R) Horizontal Refresh Order -1) -0) - - MY, MX, MV, ML,RGB, MH, D1, D0 - 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal - 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror - 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror - 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror - 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange - 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror - 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange - 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 -*/ + * 7) MY: 1(bottom to top), 0(top to bottom) Row Address Order + * 6) MX: 1(R to L), 0(L to R) Column Address Order + * 5) MV: 1(Exchanged), 0(normal) Row/Column exchange + * 4) ML: 1(bottom to top), 0(top to bottom) Vertical Refresh Order + * 3) RGB: 1(BGR), 0(RGB) Color Space + * 2) MH: 1(R to L), 0(L to R) Horizontal Refresh Order + * 1) + * 0) + * + * MY, MX, MV, ML,RGB, MH, D1, D0 + * 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //normal + * 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 //Y-Mirror + * 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Mirror + * 1 | 1 | 0 | 0 | 1 | 0 | 0 | 0 //X-Y-Mirror + * 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange + * 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 //X-Y Exchange, Y-Mirror + * 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 //XY exchange + * 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 + */ static int set_var(struct fbtft_par *par) { u8 mactrl_data = 0; /* Avoid compiler warning */ diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index 3ed50febe36f..5da2764bb82a 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -216,10 +216,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 - VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 -*/ + * Gamma string format: + * VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 + * VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index 3b3a06d8a125..64cdf555ac34 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -56,42 +56,42 @@ module_param(vcm, uint, 0); MODULE_PARM_DESC(vcm, "Set the internal VcomH voltage"); /* -Verify that this configuration is within the Voltage limits - -Display module configuration: Vcc = IOVcc = Vci = 3.3V - - Voltages ----------- -Vci = 3.3 -Vci1 = Vci * 0.80 = 2.64 -DDVDH = Vci1 * 2 = 5.28 -VCL = -Vci1 = -2.64 -VREG1OUT = Vci * 1.85 = 4.88 -VCOMH = VREG1OUT * 0.735 = 3.59 -VCOM amplitude = VREG1OUT * 0.98 = 4.79 -VGH = Vci * 4 = 13.2 -VGL = -Vci * 4 = -13.2 - - Limits --------- -Power supplies -1.65 < IOVcc < 3.30 => 1.65 < 3.3 < 3.30 -2.40 < Vcc < 3.30 => 2.40 < 3.3 < 3.30 -2.50 < Vci < 3.30 => 2.50 < 3.3 < 3.30 - -Source/VCOM power supply voltage - 4.50 < DDVDH < 6.0 => 4.50 < 5.28 < 6.0 --3.0 < VCL < -2.0 => -3.0 < -2.64 < -2.0 -VCI - VCL < 6.0 => 5.94 < 6.0 - -Gate driver output voltage - 10 < VGH < 20 => 10 < 13.2 < 20 --15 < VGL < -5 => -15 < -13.2 < -5 -VGH - VGL < 32 => 26.4 < 32 - -VCOM driver output voltage -VCOMH - VCOML < 6.0 => 4.79 < 6.0 -*/ + * Verify that this configuration is within the Voltage limits + * + * Display module configuration: Vcc = IOVcc = Vci = 3.3V + * + * Voltages + * ---------- + * Vci = 3.3 + * Vci1 = Vci * 0.80 = 2.64 + * DDVDH = Vci1 * 2 = 5.28 + * VCL = -Vci1 = -2.64 + * VREG1OUT = Vci * 1.85 = 4.88 + * VCOMH = VREG1OUT * 0.735 = 3.59 + * VCOM amplitude = VREG1OUT * 0.98 = 4.79 + * VGH = Vci * 4 = 13.2 + * VGL = -Vci * 4 = -13.2 + * + * Limits + * -------- + * Power supplies + * 1.65 < IOVcc < 3.30 => 1.65 < 3.3 < 3.30 + * 2.40 < Vcc < 3.30 => 2.40 < 3.3 < 3.30 + * 2.50 < Vci < 3.30 => 2.50 < 3.3 < 3.30 + * + * Source/VCOM power supply voltage + * 4.50 < DDVDH < 6.0 => 4.50 < 5.28 < 6.0 + * -3.0 < VCL < -2.0 => -3.0 < -2.64 < -2.0 + * VCI - VCL < 6.0 => 5.94 < 6.0 + * + * Gate driver output voltage + * 10 < VGH < 20 => 10 < 13.2 < 20 + * -15 < VGL < -5 => -15 < -13.2 < -5 + * VGH - VGL < 32 => 26.4 < 32 + * + * VCOM driver output voltage + * VCOMH - VCOML < 6.0 => 4.79 < 6.0 + */ static int init_display(struct fbtft_par *par) { @@ -213,10 +213,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 - VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 -*/ + * Gamma string format: + * VRP0 VRP1 RP0 RP1 KP0 KP1 KP2 KP3 KP4 KP5 + * VRN0 VRN1 RN0 RN1 KN0 KN1 KN2 KN3 KN4 KN5 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { diff --git a/drivers/staging/fbtft/fb_ili9341.c b/drivers/staging/fbtft/fb_ili9341.c index d1e13cd93ad3..e8107d15b891 100644 --- a/drivers/staging/fbtft/fb_ili9341.c +++ b/drivers/staging/fbtft/fb_ili9341.c @@ -116,10 +116,10 @@ static int set_var(struct fbtft_par *par) } /* - Gamma string format: - Positive: Par1 Par2 [...] Par15 - Negative: Par1 Par2 [...] Par15 -*/ + * Gamma string format: + * Positive: Par1 Par2 [...] Par15 + * Negative: Par1 Par2 [...] Par15 + */ #define CURVE(num, idx) curves[num * par->gamma.num_values + idx] static int set_gamma(struct fbtft_par *par, unsigned long *curves) { -- cgit From f07e89ce1e1bdcae5427e6d37546086cb3d18369 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Fri, 12 Feb 2016 15:39:27 +0800 Subject: staging: fbtft: Fix alignment to match open parenthesis Fix alignment issues by properly indenting function parameters in accordance to the kernel coding style. Checkpatch pointed out this issue. CHECK: Alignment should match open parenthesis Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9163.c | 33 ++++++++++++++++----------------- drivers/staging/fbtft/fb_ili9320.c | 4 ++-- drivers/staging/fbtft/fb_ili9340.c | 8 ++++---- drivers/staging/fbtft/fb_ili9341.c | 10 +++++----- 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index 3f6c245ef2af..9f7c7ecc877e 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -122,7 +122,7 @@ static int init_display(struct fbtft_par *par) } static void set_addr_win(struct fbtft_par *par, int xs, int ys, - int xe, int ye) + int xe, int ye) { switch (par->info->var.rotate) { case 0: @@ -215,22 +215,21 @@ static int gamma_adj(struct fbtft_par *par, unsigned long *curves) CURVE(i, j) &= mask[i * par->gamma.num_values + j]; write_reg(par, CMD_PGAMMAC, - CURVE(0, 0), - CURVE(0, 1), - CURVE(0, 2), - CURVE(0, 3), - CURVE(0, 4), - CURVE(0, 5), - CURVE(0, 6), - (CURVE(0, 7) << 4) | CURVE(0, 8), - CURVE(0, 9), - CURVE(0, 10), - CURVE(0, 11), - CURVE(0, 12), - CURVE(0, 13), - CURVE(0, 14), - CURVE(0, 15) - ); + CURVE(0, 0), + CURVE(0, 1), + CURVE(0, 2), + CURVE(0, 3), + CURVE(0, 4), + CURVE(0, 5), + CURVE(0, 6), + (CURVE(0, 7) << 4) | CURVE(0, 8), + CURVE(0, 9), + CURVE(0, 10), + CURVE(0, 11), + CURVE(0, 12), + CURVE(0, 13), + CURVE(0, 14), + CURVE(0, 15)); /* Write Data to GRAM mode */ write_reg(par, MIPI_DCS_WRITE_MEMORY_START); diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index 5da2764bb82a..6c6bc3d87ace 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -47,10 +47,10 @@ static int init_display(struct fbtft_par *par) devcode = read_devicecode(par); fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "Device code: 0x%04X\n", - devcode); + devcode); if ((devcode != 0x0000) && (devcode != 0x9320)) dev_warn(par->info->device, - "Unrecognized Device code: 0x%04X (expected 0x9320)\n", + "Unrecognized Device code: 0x%04X (expected 0x9320)\n", devcode); /* Initialization sequence from ILI9320 Application Notes */ diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c index 9b24c9ea78d2..0711121c303c 100644 --- a/drivers/staging/fbtft/fb_ili9340.c +++ b/drivers/staging/fbtft/fb_ili9340.c @@ -71,13 +71,13 @@ static int init_display(struct fbtft_par *par) /* Positive Gamma Correction */ write_reg(par, 0xE0, - 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, - 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00); + 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, + 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00); /* Negative Gamma Correction */ write_reg(par, 0xE1, - 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, - 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F); + 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, + 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F); write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); diff --git a/drivers/staging/fbtft/fb_ili9341.c b/drivers/staging/fbtft/fb_ili9341.c index e8107d15b891..e92d771752b6 100644 --- a/drivers/staging/fbtft/fb_ili9341.c +++ b/drivers/staging/fbtft/fb_ili9341.c @@ -127,11 +127,11 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) for (i = 0; i < par->gamma.num_curves; i++) write_reg(par, 0xE0 + i, - CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), - CURVE(i, 3), CURVE(i, 4), CURVE(i, 5), - CURVE(i, 6), CURVE(i, 7), CURVE(i, 8), - CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), - CURVE(i, 12), CURVE(i, 13), CURVE(i, 14)); + CURVE(i, 0), CURVE(i, 1), CURVE(i, 2), + CURVE(i, 3), CURVE(i, 4), CURVE(i, 5), + CURVE(i, 6), CURVE(i, 7), CURVE(i, 8), + CURVE(i, 9), CURVE(i, 10), CURVE(i, 11), + CURVE(i, 12), CURVE(i, 13), CURVE(i, 14)); return 0; } -- cgit From b4ac6b2885dd5c1aa3e9905275ac30594aaf95d9 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Fri, 12 Feb 2016 15:39:28 +0800 Subject: staging: fbtft: Insert blank line after function declaration Insert the required whitespace after the function declaration as suggested by checkpatch. 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/fbtft/fb_ili9163.c | 1 + drivers/staging/fbtft/fb_ili9320.c | 1 + drivers/staging/fbtft/fb_ili9325.c | 1 + drivers/staging/fbtft/fb_ili9341.c | 1 + 4 files changed, 4 insertions(+) diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index 9f7c7ecc877e..6b8f8b17e9a3 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -236,6 +236,7 @@ static int gamma_adj(struct fbtft_par *par, unsigned long *curves) return 0; } + #undef CURVE #endif diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index 6c6bc3d87ace..6ff222d6d6d6 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -248,6 +248,7 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) return 0; } + #undef CURVE static struct fbtft_display display = { diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index 64cdf555ac34..fdf98d37550e 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -245,6 +245,7 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) return 0; } + #undef CURVE static struct fbtft_display display = { diff --git a/drivers/staging/fbtft/fb_ili9341.c b/drivers/staging/fbtft/fb_ili9341.c index e92d771752b6..ff35c8624ca3 100644 --- a/drivers/staging/fbtft/fb_ili9341.c +++ b/drivers/staging/fbtft/fb_ili9341.c @@ -135,6 +135,7 @@ static int set_gamma(struct fbtft_par *par, unsigned long *curves) return 0; } + #undef CURVE static struct fbtft_display display = { -- cgit From ead3c5ce502bf16b8f0fed2d5d9c41eafa3fd434 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Fri, 12 Feb 2016 15:39:29 +0800 Subject: staging: fbtft: Delete blank line after '{' brace Omit the whitespace after '{' brace as suggested by checkpatch. CHECK: Blank lines aren't necessary after an open brace '{' Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9481.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/fbtft/fb_ili9481.c b/drivers/staging/fbtft/fb_ili9481.c index 6fa5e4c21ab6..fb0e6c316947 100644 --- a/drivers/staging/fbtft/fb_ili9481.c +++ b/drivers/staging/fbtft/fb_ili9481.c @@ -28,7 +28,6 @@ #define HEIGHT 480 static int default_init_sequence[] = { - /* SLP_OUT - Sleep out */ -1, MIPI_DCS_EXIT_SLEEP_MODE, -2, 50, -- cgit From 61abd03a3dba2f6a73c06930075935683b474fa8 Mon Sep 17 00:00:00 2001 From: Eva Rachel Retuya Date: Fri, 12 Feb 2016 15:39:30 +0800 Subject: staging: fbtft: Remove the use of CamelCase Rename the macro defining constant ROWxCOL into ROW_X_COL to remove checkpatch check concerning use of CamelCase and to achieve better readability. CHECK: Avoid CamelCase: Signed-off-by: Eva Rachel Retuya Signed-off-by: Greg Kroah-Hartman --- drivers/staging/fbtft/fb_ili9481.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/fbtft/fb_ili9481.c b/drivers/staging/fbtft/fb_ili9481.c index fb0e6c316947..242adb3859bd 100644 --- a/drivers/staging/fbtft/fb_ili9481.c +++ b/drivers/staging/fbtft/fb_ili9481.c @@ -64,13 +64,13 @@ static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) #define HFLIP 0x01 #define VFLIP 0x02 -#define ROWxCOL 0x20 +#define ROW_X_COL 0x20 static int set_var(struct fbtft_par *par) { switch (par->info->var.rotate) { case 270: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, - ROWxCOL | HFLIP | VFLIP | (par->bgr << 3)); + ROW_X_COL | HFLIP | VFLIP | (par->bgr << 3)); break; case 180: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, @@ -78,7 +78,7 @@ static int set_var(struct fbtft_par *par) break; case 90: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, - ROWxCOL | (par->bgr << 3)); + ROW_X_COL | (par->bgr << 3)); break; default: write_reg(par, MIPI_DCS_SET_ADDRESS_MODE, -- cgit From 3e0f86b337090ec9040b68e398a85be00ddee4bc Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 12 Feb 2016 10:05:01 -0800 Subject: staging: vt6656: replace GFP_ATOMIC with GFP_KERNEL for urb allocation Replace GFP_ATOMIC with GFP_KERNEL during urb buffer allocation. This makes vnt_alloc_bufs() consistent in setting GFP_KERNEL during kmalloc() and usb_alloc_urb(). GFP_KERNEL is safe because we are in process context, not in an interrupt handler, nor holding any spinlock. Signed-off-by: Alison Schofield 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 05f86ff8875c..f9afab77b79f 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -439,7 +439,7 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) tx_context->pkt_no = ii; /* allocate URBs */ - tx_context->urb = usb_alloc_urb(0, GFP_ATOMIC); + tx_context->urb = usb_alloc_urb(0, GFP_KERNEL); if (!tx_context->urb) { dev_err(&priv->usb->dev, "alloc tx urb failed\n"); goto free_tx; @@ -461,7 +461,7 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) rcb->priv = priv; /* allocate URBs */ - rcb->urb = usb_alloc_urb(0, GFP_ATOMIC); + rcb->urb = usb_alloc_urb(0, GFP_KERNEL); if (!rcb->urb) { dev_err(&priv->usb->dev, "Failed to alloc rx urb\n"); goto free_rx_tx; @@ -478,7 +478,7 @@ static bool vnt_alloc_bufs(struct vnt_private *priv) goto free_rx_tx; } - priv->interrupt_urb = usb_alloc_urb(0, GFP_ATOMIC); + priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); if (!priv->interrupt_urb) { dev_err(&priv->usb->dev, "Failed to alloc int urb\n"); goto free_rx_tx; -- cgit From b9183fdd4121c2480855b6ded32cdd359ad6b710 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 12 Feb 2016 10:44:43 -0800 Subject: staging: vt6656: move local var init into declaration Improve readability by initializing local variables at declaration. In one instance, vnt_start_interrupt_urb_complete(), also use that local variable in subsequent switch. Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6656/usbpipe.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index bec5bafaca3c..f27eb9a8d249 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -101,9 +101,9 @@ void vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data) static void vnt_start_interrupt_urb_complete(struct urb *urb) { struct vnt_private *priv = urb->context; - int status; + int status = urb->status; - switch (urb->status) { + switch (status) { case 0: case -ETIMEDOUT: break; @@ -116,8 +116,6 @@ static void vnt_start_interrupt_urb_complete(struct urb *urb) break; } - status = urb->status; - if (status != STATUS_SUCCESS) { priv->int_buf.in_use = false; @@ -207,9 +205,8 @@ static void vnt_submit_rx_urb_complete(struct urb *urb) int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb) { int status = 0; - struct urb *urb; + struct urb *urb = rcb->urb; - urb = rcb->urb; if (!rcb->skb) { dev_dbg(&priv->usb->dev, "rcb->skb is null\n"); return status; @@ -269,15 +266,13 @@ int vnt_tx_context(struct vnt_private *priv, struct vnt_usb_send_context *context) { int status; - struct urb *urb; + struct urb *urb = context->urb; if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) { context->in_use = false; return STATUS_RESOURCES; } - urb = context->urb; - usb_fill_bulk_urb(urb, priv->usb, usb_sndbulkpipe(priv->usb, 3), -- cgit From f176429307564ae4bf6d0fc3e68294582d8e15e3 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:37 +0900 Subject: staging: wilc1000: rename au8bssid in struct join_bss_param This patch renames au8bssid to bssid to remove au8 prefix in struct join_bss_param. There is no need to use prefix to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 5570707b7376..ab02159a3c25 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -211,7 +211,7 @@ struct join_bss_param { u8 dtim_period; u16 beacon_period; u16 cap_info; - u8 au8bssid[6]; + u8 bssid[6]; char ssid[MAX_SSID_LEN]; u8 ssid_len; u8 supp_rates[MAX_RATES_SUPPORTED + 1]; @@ -4246,7 +4246,7 @@ static void *host_int_ParseJoinBssParam(struct network_info *ptstrNetworkInfo) pNewJoinBssParam->dtim_period = ptstrNetworkInfo->dtim_period; pNewJoinBssParam->beacon_period = ptstrNetworkInfo->beacon_period; pNewJoinBssParam->cap_info = ptstrNetworkInfo->cap_info; - memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->bssid, 6); + memcpy(pNewJoinBssParam->bssid, ptstrNetworkInfo->bssid, 6); memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->ssid, ptstrNetworkInfo->ssid_len + 1); pNewJoinBssParam->ssid_len = ptstrNetworkInfo->ssid_len; -- cgit From 69dc533ecc02a29eb366391df1407440ea053039 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:38 +0900 Subject: staging: wilc1000: rename au8bssid in struct found_net_info This patch renames au8bssid to bssid to remove au8 prefix. There is no need to use prefix to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 8 ++++---- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index ab02159a3c25..60c18278847d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1352,9 +1352,9 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, } for (i = 0; i < hif_drv->usr_scan_req.rcvd_ch_cnt; i++) { - if ((hif_drv->usr_scan_req.net_info[i].au8bssid) && + if ((hif_drv->usr_scan_req.net_info[i].bssid) && (pstrNetworkInfo->bssid)) { - if (memcmp(hif_drv->usr_scan_req.net_info[i].au8bssid, + if (memcmp(hif_drv->usr_scan_req.net_info[i].bssid, pstrNetworkInfo->bssid, 6) == 0) { if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { goto done; @@ -1371,9 +1371,9 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi; - if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid && + if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].bssid && pstrNetworkInfo->bssid) { - memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].au8bssid, + memcpy(hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].bssid, pstrNetworkInfo->bssid, 6); hif_drv->usr_scan_req.rcvd_ch_cnt++; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index bfa4a41264f1..e4729e33217d 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -144,7 +144,7 @@ enum cfg_param { }; struct found_net_info { - u8 au8bssid[6]; + u8 bssid[6]; s8 s8rssi; }; -- cgit From 5cfbbf1401b46d677a8c2580d5128778737b940a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:39 +0900 Subject: staging: wilc1000: rename s8rssi in struct found_net_info This patch renames s8rssi to rssi to remove s8 prefix in struct found_net_info. There is no need to use prefix to show data type of this variable. Signed-off-by: Chaehyun Lim 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 60c18278847d..cd4a0a685b7f 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -1356,10 +1356,10 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, (pstrNetworkInfo->bssid)) { if (memcmp(hif_drv->usr_scan_req.net_info[i].bssid, pstrNetworkInfo->bssid, 6) == 0) { - if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].s8rssi) { + if (pstrNetworkInfo->rssi <= hif_drv->usr_scan_req.net_info[i].rssi) { goto done; } else { - hif_drv->usr_scan_req.net_info[i].s8rssi = pstrNetworkInfo->rssi; + hif_drv->usr_scan_req.net_info[i].rssi = pstrNetworkInfo->rssi; bNewNtwrkFound = false; break; } @@ -1369,7 +1369,7 @@ static s32 Handle_RcvdNtwrkInfo(struct wilc_vif *vif, if (bNewNtwrkFound) { if (hif_drv->usr_scan_req.rcvd_ch_cnt < MAX_NUM_SCANNED_NETWORKS) { - hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].s8rssi = pstrNetworkInfo->rssi; + hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].rssi = pstrNetworkInfo->rssi; if (hif_drv->usr_scan_req.net_info[hif_drv->usr_scan_req.rcvd_ch_cnt].bssid && pstrNetworkInfo->bssid) { diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index e4729e33217d..08c072cd4388 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -145,7 +145,7 @@ enum cfg_param { struct found_net_info { u8 bssid[6]; - s8 s8rssi; + s8 rssi; }; enum scan_event { -- cgit From 788f6fc0810f35add6077f1cfd40b7f030e955ba Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:40 +0900 Subject: staging: wilc1000: rename pu8bssid in struct user_conn_req This patch renames pu8bssid to bssid to remove pu8 prefix in struct user_conn_req. There is no need to use prefix to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 30 +++++++++++++++--------------- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index cd4a0a685b7f..7cfc722d6a57 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -965,8 +965,8 @@ static s32 Handle_Connect(struct wilc_vif *vif, } if (pstrHostIFconnectAttr->bssid) { - hif_drv->usr_conn_req.pu8bssid = kmalloc(6, GFP_KERNEL); - memcpy(hif_drv->usr_conn_req.pu8bssid, pstrHostIFconnectAttr->bssid, 6); + hif_drv->usr_conn_req.bssid = kmalloc(6, GFP_KERNEL); + memcpy(hif_drv->usr_conn_req.bssid, pstrHostIFconnectAttr->bssid, 6); } hif_drv->usr_conn_req.ssid_len = pstrHostIFconnectAttr->ssid_len; @@ -1271,9 +1271,9 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) memset(&strConnectInfo, 0, sizeof(tstrConnectInfo)); if (hif_drv->usr_conn_req.conn_result) { - if (hif_drv->usr_conn_req.pu8bssid) { + if (hif_drv->usr_conn_req.bssid) { memcpy(strConnectInfo.au8bssid, - hif_drv->usr_conn_req.pu8bssid, 6); + hif_drv->usr_conn_req.bssid, 6); } if (hif_drv->usr_conn_req.ies) { @@ -1309,8 +1309,8 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) hif_drv->usr_conn_req.ssid_len = 0; kfree(hif_drv->usr_conn_req.pu8ssid); hif_drv->usr_conn_req.pu8ssid = NULL; - kfree(hif_drv->usr_conn_req.pu8bssid); - hif_drv->usr_conn_req.pu8bssid = NULL; + kfree(hif_drv->usr_conn_req.bssid); + hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; kfree(hif_drv->usr_conn_req.ies); hif_drv->usr_conn_req.ies = NULL; @@ -1503,13 +1503,13 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, eth_zero_addr(wilc_connected_ssid); } - if (hif_drv->usr_conn_req.pu8bssid) { - memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.pu8bssid, 6); + if (hif_drv->usr_conn_req.bssid) { + memcpy(strConnectInfo.au8bssid, hif_drv->usr_conn_req.bssid, 6); if ((u8MacStatus == MAC_CONNECTED) && (strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) { memcpy(hif_drv->assoc_bssid, - hif_drv->usr_conn_req.pu8bssid, ETH_ALEN); + hif_drv->usr_conn_req.bssid, ETH_ALEN); } } @@ -1550,8 +1550,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, hif_drv->usr_conn_req.ssid_len = 0; kfree(hif_drv->usr_conn_req.pu8ssid); hif_drv->usr_conn_req.pu8ssid = NULL; - kfree(hif_drv->usr_conn_req.pu8bssid); - hif_drv->usr_conn_req.pu8bssid = NULL; + kfree(hif_drv->usr_conn_req.bssid); + hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; kfree(hif_drv->usr_conn_req.ies); hif_drv->usr_conn_req.ies = NULL; @@ -1586,8 +1586,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, hif_drv->usr_conn_req.ssid_len = 0; kfree(hif_drv->usr_conn_req.pu8ssid); hif_drv->usr_conn_req.pu8ssid = NULL; - kfree(hif_drv->usr_conn_req.pu8bssid); - hif_drv->usr_conn_req.pu8bssid = NULL; + kfree(hif_drv->usr_conn_req.bssid); + hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; kfree(hif_drv->usr_conn_req.ies); hif_drv->usr_conn_req.ies = NULL; @@ -1944,8 +1944,8 @@ static void Handle_Disconnect(struct wilc_vif *vif) hif_drv->usr_conn_req.ssid_len = 0; kfree(hif_drv->usr_conn_req.pu8ssid); hif_drv->usr_conn_req.pu8ssid = NULL; - kfree(hif_drv->usr_conn_req.pu8bssid); - hif_drv->usr_conn_req.pu8bssid = NULL; + kfree(hif_drv->usr_conn_req.bssid); + hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; kfree(hif_drv->usr_conn_req.ies); hif_drv->usr_conn_req.ies = NULL; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 08c072cd4388..18d67e0586bc 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -203,7 +203,7 @@ struct user_scan_req { }; struct user_conn_req { - u8 *pu8bssid; + u8 *bssid; u8 *pu8ssid; u8 u8security; enum AUTHTYPE auth_type; -- cgit From 72216411b092101036203c0873a6a42ed33d535a Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:41 +0900 Subject: staging: wilc1000: rename pu8ssid in struct user_conn_req This patch renames pu8ssid to ssid to remove pu8 prefix in struct user_conn_req. There is no need to use prefix to show data type of this variable. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 22 +++++++++++----------- drivers/staging/wilc1000/host_interface.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 7cfc722d6a57..397ef617656e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -971,11 +971,11 @@ static s32 Handle_Connect(struct wilc_vif *vif, hif_drv->usr_conn_req.ssid_len = pstrHostIFconnectAttr->ssid_len; if (pstrHostIFconnectAttr->ssid) { - hif_drv->usr_conn_req.pu8ssid = kmalloc(pstrHostIFconnectAttr->ssid_len + 1, GFP_KERNEL); - memcpy(hif_drv->usr_conn_req.pu8ssid, + hif_drv->usr_conn_req.ssid = kmalloc(pstrHostIFconnectAttr->ssid_len + 1, GFP_KERNEL); + memcpy(hif_drv->usr_conn_req.ssid, pstrHostIFconnectAttr->ssid, pstrHostIFconnectAttr->ssid_len); - hif_drv->usr_conn_req.pu8ssid[pstrHostIFconnectAttr->ssid_len] = '\0'; + hif_drv->usr_conn_req.ssid[pstrHostIFconnectAttr->ssid_len] = '\0'; } hif_drv->usr_conn_req.ies_len = pstrHostIFconnectAttr->ies_len; @@ -1307,8 +1307,8 @@ static s32 Handle_ConnectTimeout(struct wilc_vif *vif) PRINT_ER("Failed to send dissconect config packet\n"); hif_drv->usr_conn_req.ssid_len = 0; - kfree(hif_drv->usr_conn_req.pu8ssid); - hif_drv->usr_conn_req.pu8ssid = NULL; + kfree(hif_drv->usr_conn_req.ssid); + hif_drv->usr_conn_req.ssid = NULL; kfree(hif_drv->usr_conn_req.bssid); hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; @@ -1548,8 +1548,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, kfree(strConnectInfo.pu8ReqIEs); strConnectInfo.pu8ReqIEs = NULL; hif_drv->usr_conn_req.ssid_len = 0; - kfree(hif_drv->usr_conn_req.pu8ssid); - hif_drv->usr_conn_req.pu8ssid = NULL; + kfree(hif_drv->usr_conn_req.ssid); + hif_drv->usr_conn_req.ssid = NULL; kfree(hif_drv->usr_conn_req.bssid); hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; @@ -1584,8 +1584,8 @@ static s32 Handle_RcvdGnrlAsyncInfo(struct wilc_vif *vif, eth_zero_addr(hif_drv->assoc_bssid); hif_drv->usr_conn_req.ssid_len = 0; - kfree(hif_drv->usr_conn_req.pu8ssid); - hif_drv->usr_conn_req.pu8ssid = NULL; + kfree(hif_drv->usr_conn_req.ssid); + hif_drv->usr_conn_req.ssid = NULL; kfree(hif_drv->usr_conn_req.bssid); hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; @@ -1942,8 +1942,8 @@ static void Handle_Disconnect(struct wilc_vif *vif) eth_zero_addr(hif_drv->assoc_bssid); hif_drv->usr_conn_req.ssid_len = 0; - kfree(hif_drv->usr_conn_req.pu8ssid); - hif_drv->usr_conn_req.pu8ssid = NULL; + kfree(hif_drv->usr_conn_req.ssid); + hif_drv->usr_conn_req.ssid = NULL; kfree(hif_drv->usr_conn_req.bssid); hif_drv->usr_conn_req.bssid = NULL; hif_drv->usr_conn_req.ies_len = 0; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 18d67e0586bc..30acf40e855c 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -204,7 +204,7 @@ struct user_scan_req { struct user_conn_req { u8 *bssid; - u8 *pu8ssid; + u8 *ssid; u8 u8security; enum AUTHTYPE auth_type; size_t ssid_len; -- cgit From a0942c5799e82cf20e153a8dc7a06330c0e2e51b Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:42 +0900 Subject: staging: wilc1000: rename u8security in user_conn_req This patch renames u8security to security to remove u8 prefix in struct user_conn_req. There is no need to use prefix to show data type of this variable. Signed-off-by: Chaehyun Lim 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 397ef617656e..a9c8b15f57dc 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -986,7 +986,7 @@ static s32 Handle_Connect(struct wilc_vif *vif, pstrHostIFconnectAttr->ies_len); } - hif_drv->usr_conn_req.u8security = pstrHostIFconnectAttr->security; + hif_drv->usr_conn_req.security = pstrHostIFconnectAttr->security; hif_drv->usr_conn_req.auth_type = pstrHostIFconnectAttr->auth_type; hif_drv->usr_conn_req.conn_result = pstrHostIFconnectAttr->result; hif_drv->usr_conn_req.arg = pstrHostIFconnectAttr->arg; @@ -1026,11 +1026,11 @@ static s32 Handle_Connect(struct wilc_vif *vif, strWIDList[u32WidsCount].id = (u16)WID_11I_MODE; strWIDList[u32WidsCount].type = WID_CHAR; strWIDList[u32WidsCount].size = sizeof(char); - strWIDList[u32WidsCount].val = (s8 *)&hif_drv->usr_conn_req.u8security; + strWIDList[u32WidsCount].val = (s8 *)&hif_drv->usr_conn_req.security; u32WidsCount++; if (memcmp("DIRECT-", pstrHostIFconnectAttr->ssid, 7)) - mode_11i = hif_drv->usr_conn_req.u8security; + mode_11i = hif_drv->usr_conn_req.security; strWIDList[u32WidsCount].id = (u16)WID_AUTH_TYPE; strWIDList[u32WidsCount].type = WID_CHAR; diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h index 30acf40e855c..5e65f2cfb8cb 100644 --- a/drivers/staging/wilc1000/host_interface.h +++ b/drivers/staging/wilc1000/host_interface.h @@ -205,7 +205,7 @@ struct user_scan_req { struct user_conn_req { u8 *bssid; u8 *ssid; - u8 u8security; + u8 security; enum AUTHTYPE auth_type; size_t ssid_len; u8 *ies; -- cgit From b41dfdb18e2ad1320ffea58fb7c3c8915e772660 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:43 +0900 Subject: staging: wilc1000: define a new local variable in wilc_scan struct scan_info is defined as a new local variable in wilc_scan function. It makes some assignment short as well as improve more readability. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a9c8b15f57dc..e9a6aa7f4afb 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3511,6 +3511,7 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, { int result = 0; struct host_if_msg msg; + struct scan_attr *scan_info = &msg.body.scan_info; struct host_if_drv *hif_drv = vif->hif_drv; if (!hif_drv || !scan_result) { @@ -3523,26 +3524,26 @@ int wilc_scan(struct wilc_vif *vif, u8 scan_source, u8 scan_type, msg.id = HOST_IF_MSG_SCAN; if (hidden_network) { - msg.body.scan_info.hidden_network.net_info = hidden_network->net_info; - msg.body.scan_info.hidden_network.n_ssids = hidden_network->n_ssids; + scan_info->hidden_network.net_info = hidden_network->net_info; + scan_info->hidden_network.n_ssids = hidden_network->n_ssids; } msg.vif = vif; - msg.body.scan_info.src = scan_source; - msg.body.scan_info.type = scan_type; - msg.body.scan_info.result = scan_result; - msg.body.scan_info.arg = user_arg; - - msg.body.scan_info.ch_list_len = ch_list_len; - msg.body.scan_info.ch_freq_list = kmemdup(ch_freq_list, - ch_list_len, - GFP_KERNEL); - if (!msg.body.scan_info.ch_freq_list) + scan_info->src = scan_source; + scan_info->type = scan_type; + scan_info->result = scan_result; + scan_info->arg = user_arg; + + scan_info->ch_list_len = ch_list_len; + scan_info->ch_freq_list = kmemdup(ch_freq_list, + ch_list_len, + GFP_KERNEL); + if (!scan_info->ch_freq_list) return -ENOMEM; - msg.body.scan_info.ies_len = ies_len; - msg.body.scan_info.ies = kmemdup(ies, ies_len, GFP_KERNEL); - if (!msg.body.scan_info.ies) + scan_info->ies_len = ies_len; + scan_info->ies = kmemdup(ies, ies_len, GFP_KERNEL); + if (!scan_info->ies) return -ENOMEM; result = wilc_mq_send(&hif_msg_q, &msg, sizeof(struct host_if_msg)); -- cgit From c43f5f9dc4135cdb5c252ae5d35e8ec95740c679 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:44 +0900 Subject: staging: wilc1000: change handle_set_channel's return type to void When handle_set_channel is called in hostIFthread that is a kernel thread, it is not checked return type of this function. This patch changes return type to void and removes braces if statement due to have a single statement. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index e9a6aa7f4afb..eecd697c3f02 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -299,8 +299,8 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx) return wilc->vif[index]; } -static s32 handle_set_channel(struct wilc_vif *vif, - struct channel_attr *hif_set_ch) +static void handle_set_channel(struct wilc_vif *vif, + struct channel_attr *hif_set_ch) { s32 result = 0; struct wid wid; @@ -313,12 +313,8 @@ static s32 handle_set_channel(struct wilc_vif *vif, result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, wilc_get_vif_idx(vif)); - if (result) { + if (result) PRINT_ER("Failed to set channel\n"); - return -EINVAL; - } - - return result; } static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, -- cgit From 987ab5eb5fedd3dc60fe766df01cf5042f83edf8 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:45 +0900 Subject: staging: wilc1000: change data type of result variable to int. result variable gets value from wilc_send_config_pkt that has return value of int. This patch changes data type of result variable to int. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index eecd697c3f02..0f7a36c3af7c 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -302,7 +302,7 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx) static void handle_set_channel(struct wilc_vif *vif, struct channel_attr *hif_set_ch) { - s32 result = 0; + int result = 0; struct wid wid; wid.id = (u16)WID_CURRENT_CHANNEL; -- cgit From 5349f6daa317128a87b1baa55e02593b87d21e61 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:46 +0900 Subject: staging: wilc1000: rename result in handle_set_channel This patch renames result to ret that is used to get return value from wilc_send_config_pkt. Some handle_*() function are used as result, others are used as ret. It will start to rename as ret in all handle_*() function to sync up with this variable name. 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 0f7a36c3af7c..10c5e4ef6949 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -302,7 +302,7 @@ static struct wilc_vif *wilc_get_vif_from_idx(struct wilc *wilc, int idx) static void handle_set_channel(struct wilc_vif *vif, struct channel_attr *hif_set_ch) { - int result = 0; + int ret = 0; struct wid wid; wid.id = (u16)WID_CURRENT_CHANNEL; @@ -310,10 +310,10 @@ static void handle_set_channel(struct wilc_vif *vif, wid.val = (char *)&hif_set_ch->set_ch; wid.size = sizeof(char); - result = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, - wilc_get_vif_idx(vif)); + ret = wilc_send_config_pkt(vif, SET_CFG, &wid, 1, + wilc_get_vif_idx(vif)); - if (result) + if (ret) PRINT_ER("Failed to set channel\n"); } -- cgit From ecdd5c745ed63676400f70636eeae132205d9757 Mon Sep 17 00:00:00 2001 From: Chaehyun Lim Date: Fri, 12 Feb 2016 23:04:47 +0900 Subject: staging: wilc1000: use netdev_err instead of PRINT_ER This patch uses netdev_err instead of PRINT_ER that is a custom debug print. Signed-off-by: Chaehyun Lim Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 10c5e4ef6949..a6bc8a436c7e 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -314,7 +314,7 @@ static void handle_set_channel(struct wilc_vif *vif, wilc_get_vif_idx(vif)); if (ret) - PRINT_ER("Failed to set channel\n"); + netdev_err(vif->ndev, "Failed to set channel\n"); } static s32 handle_set_wfi_drv_handler(struct wilc_vif *vif, -- cgit From 59b97b365e17c0d3b13187874e5b5aededc0ae4a Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 12 Feb 2016 22:51:04 -0800 Subject: staging: wilc1000: host_interface: remove cast on void pointers Remove cast on void pointers. C programming language guarantees the conversion from void pointer to any other pointer type. Coccinelle patch: @r@ expression x; void* e; type T; identifier f; @@ ( *((T *)e) | ((T *)x)[...] | ((T *)x)->f | - (T *) e ) Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index a6bc8a436c7e..069fac1e6cab 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -953,7 +953,7 @@ static s32 Handle_Connect(struct wilc_vif *vif, return result; } - ptstrJoinBssParam = (struct join_bss_param *)pstrHostIFconnectAttr->params; + ptstrJoinBssParam = pstrHostIFconnectAttr->params; if (!ptstrJoinBssParam) { PRINT_ER("Required BSSID not found\n"); result = -ENOENT; @@ -2675,7 +2675,7 @@ static int hostIFthread(void *pvArg) { u32 u32Ret; struct host_if_msg msg; - struct wilc *wilc = (struct wilc*)pvArg; + struct wilc *wilc = pvArg; struct wilc_vif *vif; memset(&msg, 0, sizeof(struct host_if_msg)); -- cgit From 6bcc1e1e703c2d734eec76bd104afc717a290205 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 12 Feb 2016 22:52:11 -0800 Subject: staging: wilc1000: linux_mon: remove cast on void pointer Remove cast on void pointer. C programming language guarantees the conversion from void pointer to any other pointer type. Coccinelle patch: @r@ expression x; void* e; type T; identifier f; @@ ( *((T *)e) | ((T *)x)[...] | ((T *)x)->f | - (T *) e ) Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index e9bb0ec5cbc6..ba702b23f852 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -137,7 +137,7 @@ struct tx_complete_mon_data { static void mgmt_tx_complete(void *priv, int status) { - struct tx_complete_mon_data *pv_data = (struct tx_complete_mon_data *)priv; + struct tx_complete_mon_data *pv_data = priv; u8 *buf = pv_data->buff; if (status == 1) { -- cgit From d5c89442d431afa2d5c35a5141b259c4ff5d8c03 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 12 Feb 2016 22:53:13 -0800 Subject: staging: wilc1000: linux_wlan: remove cast on void pointers Remove casts on void pointers. C programming language guarantees the conversion from void pointer to any other pointer type. Coccinelle patch: @r@ expression x; void* e; type T; identifier f; @@ ( *((T *)e) | ((T *)x)[...] | ((T *)x)->f | - (T *) e ) Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c index c11830f71f38..a731b46f9d13 100644 --- a/drivers/staging/wilc1000/linux_wlan.c +++ b/drivers/staging/wilc1000/linux_wlan.c @@ -61,7 +61,7 @@ static const struct net_device_ops wilc_netdev_ops = { static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr) { - struct in_ifaddr *dev_iface = (struct in_ifaddr *)ptr; + struct in_ifaddr *dev_iface = ptr; struct wilc_priv *priv; struct host_if_drv *hif_drv; struct net_device *dev; @@ -144,7 +144,7 @@ static irqreturn_t isr_uh_routine(int irq, void *user_data) { struct wilc_vif *vif; struct wilc *wilc; - struct net_device *dev = (struct net_device *)user_data; + struct net_device *dev = user_data; vif = netdev_priv(dev); wilc = vif->wilc; @@ -160,7 +160,7 @@ static irqreturn_t isr_bh_routine(int irq, void *userdata) { struct wilc_vif *vif; struct wilc *wilc; - struct net_device *dev = (struct net_device *)userdata; + struct net_device *dev = userdata; vif = netdev_priv(userdata); wilc = vif->wilc; @@ -235,7 +235,7 @@ int wilc_lock_timeout(struct wilc *nic, void *vp, u32 timeout) int error = -1; if (vp) - error = down_timeout((struct semaphore *)vp, + error = down_timeout(vp, msecs_to_jiffies(timeout)); return error; } @@ -1038,7 +1038,7 @@ static void wilc_set_multicast_list(struct net_device *dev) static void linux_wlan_tx_complete(void *priv, int status) { - struct tx_complete_data *pv_data = (struct tx_complete_data *)priv; + struct tx_complete_data *pv_data = priv; dev_kfree_skb(pv_data->skb); kfree(pv_data); -- cgit From 4375cad941ee9cc8f7c2a467464cd29ec3d9abd1 Mon Sep 17 00:00:00 2001 From: Alison Schofield Date: Fri, 12 Feb 2016 22:54:08 -0800 Subject: staging: wilc1000: wilc_wfi_cfgoperations: remove cast on void pointers Remove cast on void pointers. C programming language guarantees the conversion from void pointer to any other pointer type. Coccinelle patch: @r@ expression x; void* e; type T; identifier f; @@ ( *((T *)e) | ((T *)x)[...] | ((T *)x)->f | - (T *) e ) Signed-off-by: Alison Schofield Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_wfi_cfgoperations.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c index 97d1b802a75e..81a2ee9d7c32 100644 --- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c +++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c @@ -228,7 +228,7 @@ static void refresh_scan(void *user_void, u8 all, bool direct_scan) int i; int rssi = 0; - priv = (struct wilc_priv *)user_void; + priv = user_void; wiphy = priv->dev->ieee80211_ptr->wiphy; for (i = 0; i < last_scanned_cnt; i++) { @@ -404,7 +404,7 @@ static void CfgScanResult(enum scan_event scan_event, struct ieee80211_channel *channel; struct cfg80211_bss *bss = NULL; - priv = (struct wilc_priv *)user_void; + priv = user_void; if (priv->bCfgScanning) { if (scan_event == SCAN_EVENT_NETWORK_FOUND) { wiphy = priv->dev->ieee80211_ptr->wiphy; @@ -525,7 +525,7 @@ static void CfgConnectResult(enum conn_event enuConnDisconnEvent, wilc_connecting = 0; - priv = (struct wilc_priv *)pUserVoid; + priv = pUserVoid; dev = priv->dev; vif = netdev_priv(dev); wl = vif->wilc; @@ -1713,7 +1713,7 @@ void WILC_WFI_p2p_rx (struct net_device *dev, u8 *buff, u32 size) static void WILC_WFI_mgmt_tx_complete(void *priv, int status) { - struct p2p_mgmt_data *pv_data = (struct p2p_mgmt_data *)priv; + struct p2p_mgmt_data *pv_data = priv; kfree(pv_data->buff); @@ -1724,7 +1724,7 @@ static void WILC_WFI_RemainOnChannelReady(void *pUserVoid) { struct wilc_priv *priv; - priv = (struct wilc_priv *)pUserVoid; + priv = pUserVoid; priv->bInP2PlistenState = true; @@ -1739,7 +1739,7 @@ static void WILC_WFI_RemainOnChannelExpired(void *pUserVoid, u32 u32SessionID) { struct wilc_priv *priv; - priv = (struct wilc_priv *)pUserVoid; + priv = pUserVoid; if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) { priv->bInP2PlistenState = false; -- cgit From f7b7f87de753080cd6966c99fb20588258487fcf Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 23:19:10 -0500 Subject: staging: wilc1000: Include KERN_ facility level for printk() This patch includes KERN_ facility level for printk(). KERN_INFO is justified here as the messages here are informational. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index c5c8cc905630..6a39b16121d4 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -69,9 +69,9 @@ static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf, atomic_set(&WILC_DEBUG_LEVEL, (int)flag); if (flag == 0) - printk("Debug-level disabled\n"); + printk(KERN_INFO "Debug-level disabled\n"); else - printk("Debug-level enabled\n"); + printk(KERN_INFO "Debug-level enabled\n"); return count; } -- cgit From 01fe818cc3409c75bc15a5695600b43f4b354b62 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 23:10:29 -0500 Subject: staging: wilc1000: Eliminate extraneous braces Get rid of extraneous braces enclosing single statement blocks. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/wilc_debugfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c index 6a39b16121d4..da7ec8bb0dd4 100644 --- a/drivers/staging/wilc1000/wilc_debugfs.c +++ b/drivers/staging/wilc1000/wilc_debugfs.c @@ -98,9 +98,8 @@ static ssize_t wilc_debug_region_write(struct file *filp, const char __user *buf if (count > sizeof(buffer)) return -EINVAL; - if (copy_from_user(buffer, buf, count)) { + if (copy_from_user(buffer, buf, count)) return -EFAULT; - } flag = buffer[0] - '0'; -- cgit From 17a0c29935f83835a5b35b29e95f3cfc405a8f6f Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 23:26:49 -0500 Subject: staging: wilc1000: Eliminate spaces between function names and open parentheses Remove spaces between function names and open parentheses as they are unnecessary. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan_common.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index 44573e2ea0ee..f32505113b60 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -12,7 +12,7 @@ enum debug_region { #define CFG80211_DBG (1 << CFG80211_debug) #define INIT_DBG (1 << Init_debug) -#if defined (WILC_DEBUGFS) +#if defined(WILC_DEBUGFS) extern atomic_t WILC_REGION; extern atomic_t WILC_DEBUG_LEVEL; @@ -105,7 +105,7 @@ extern atomic_t WILC_DEBUG_LEVEL; #define WILC_MULTICAST_TABLE_SIZE 8 -#if defined (BEAGLE_BOARD) +#if defined(BEAGLE_BOARD) #define SPI_CHANNEL 4 #if SPI_CHANNEL == 4 @@ -118,7 +118,7 @@ extern atomic_t WILC_DEBUG_LEVEL; #elif defined(PLAT_WMS8304) /* rachel */ #define MODALIAS "wilc_spi" #define GPIO_NUM 139 -#elif defined (PLAT_RKXXXX) +#elif defined(PLAT_RKXXXX) #define MODALIAS "WILC_IRQ" #define GPIO_NUM RK30_PIN3_PD2 /* RK30_PIN3_PA1 */ /* RK30_PIN3_PD2 */ -- cgit From 6f5b8d2ace5d19bb4d1f7e9791b2ba9651297d92 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 23:31:48 -0500 Subject: staging: wilc1000: Remove useless macros Remove the macros FN_IN and FN_OUT as they haven't been used anywhere. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_wlan_common.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h index f32505113b60..0d9a71fa6de4 100644 --- a/drivers/staging/wilc1000/linux_wlan_common.h +++ b/drivers/staging/wilc1000/linux_wlan_common.h @@ -96,9 +96,6 @@ extern atomic_t WILC_DEBUG_LEVEL; #endif -#define FN_IN /* PRINT_D(">>> \n") */ -#define FN_OUT /* PRINT_D("<<<\n") */ - #define LINUX_RX_SIZE (96 * 1024) #define LINUX_TX_SIZE (64 * 1024) -- cgit From 04b2172a6a489dce3efb8d662516b16fc33002fa Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 23:53:23 -0500 Subject: staging: wilc1000: Remove useless return statement in a void function Remove the return statement at the end of the void function as it has no purpose. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 069fac1e6cab..698267ebc61d 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3850,8 +3850,6 @@ void wilc_scan_complete_received(struct wilc *wilc, u8 *pu8Buffer, if (result) PRINT_ER("Error in sending message queue scan complete parameters: Error(%d)\n", result); } - - return; } int wilc_remain_on_channel(struct wilc_vif *vif, u32 session_id, -- cgit From 24c6c29d85af3748b2d79b46f72188b335566340 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sun, 14 Feb 2016 00:09:33 -0500 Subject: staging: wilc1000: Simplify code by eliminating else block Remove else block here as it is not useful after the return statement in the corresponding if block. This simplifies code. This issue was identified by checkpatch. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/host_interface.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c index 698267ebc61d..d1eedfb5e405 100644 --- a/drivers/staging/wilc1000/host_interface.c +++ b/drivers/staging/wilc1000/host_interface.c @@ -3351,10 +3351,9 @@ static s32 host_int_get_assoc_res_info(struct wilc_vif *vif, *pu32RcvdAssocRespInfoLen = 0; PRINT_ER("Failed to send association response config packet\n"); return -EINVAL; - } else { - *pu32RcvdAssocRespInfoLen = wid.size; } - + + *pu32RcvdAssocRespInfoLen = wid.size; return result; } -- cgit From c611d48e65e25af2dc0176e9ac135116095ed03d Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sun, 14 Feb 2016 14:47:13 -0500 Subject: staging: wilc1000: linux_mon.c: Remove unneeded braces Remove braces around single statement blocks in if conditions as they are not required. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wilc1000/linux_mon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c index ba702b23f852..21f35d7bdd82 100644 --- a/drivers/staging/wilc1000/linux_mon.c +++ b/drivers/staging/wilc1000/linux_mon.c @@ -302,9 +302,8 @@ struct net_device *WILC_WFI_init_mon_interface(const char *name, struct net_devi struct WILC_WFI_mon_priv *priv; /*If monitor interface is already initialized, return it*/ - if (wilc_wfi_mon) { + if (wilc_wfi_mon) return wilc_wfi_mon; - } wilc_wfi_mon = alloc_etherdev(sizeof(struct WILC_WFI_mon_priv)); if (!wilc_wfi_mon) { -- cgit From 12f2a7b900f0fa8e2f466630c8bc76444aaf9f68 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 13 Feb 2016 11:49:35 +0530 Subject: Staging: media: Remove multiple assignments Remove multiple assignments by factorizing them. Made a coccinelle script to match cases: @@ identifier a,b; constant c; @@ -a=b=c; +a=c; +b=c; Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/media/davinci_vpfe/dm365_isif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/media/davinci_vpfe/dm365_isif.c b/drivers/staging/media/davinci_vpfe/dm365_isif.c index 65f6ce342a00..cfad426cdbb3 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_isif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_isif.c @@ -1239,7 +1239,8 @@ static int isif_config_ycbcr(struct v4l2_subdev *sd, int mode) * a lot of registers that we didn't touch */ /* start with all bits zero */ - ccdcfg = modeset = 0; + ccdcfg = 0; + modeset = 0; pix_fmt = isif_get_pix_fmt(format->code); if (pix_fmt < 0) { pr_debug("Invalid pix_fmt(input mode)\n"); -- cgit From 0c42bc25ed916d0fba1205cbdf668c38717fca77 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 13 Feb 2016 11:48:02 +0530 Subject: Staging: wlan-ng: Remove multiple assignments Remove multiple assignments by factorizing them. Made a coccinelle script to match cases: @@ identifier a,b; constant c; @@ -a=b=c; +a=c; +b=c; Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/p80211wep.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index e9f990a52cad..22c79703e328 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -188,7 +188,8 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, /* Apply the RC4 to the data, update the CRC32 */ crc = ~0; - i = j = 0; + i = 0; + j = 0; for (k = 0; k < len; k++) { i = (i + 1) & 0xff; j = (j + s[i]) & 0xff; @@ -260,7 +261,8 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, /* Update CRC32 then apply RC4 to the data */ crc = ~0; - i = j = 0; + i = 0; + j = 0; for (k = 0; k < len; k++) { crc = wep_crc32_table[(crc ^ buf[k]) & 0xff] ^ (crc >> 8); i = (i + 1) & 0xff; -- cgit From 2cfc7ba561210f706ee83653ed135907dffd3561 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 13 Feb 2016 18:49:34 +0530 Subject: Staging: wlan-ng: Drop wrapper function Drop the function prism2mgmt_pstr2bytearea and replace its function call with the standard function memcpy that it wrapped. The code becomes cleaner after this patch. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mib.c | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c index cdda07d1c268..e1b2e47aae9b 100644 --- a/drivers/staging/wlan-ng/prism2mib.c +++ b/drivers/staging/wlan-ng/prism2mib.c @@ -388,7 +388,7 @@ static int prism2mib_bytearea2pstr(struct mibrec *mib, prism2mgmt_bytearea2pstr(bytebuf, pstr, mib->parm2); } else { memset(bytebuf, 0, mib->parm2); - prism2mgmt_pstr2bytearea(bytebuf, pstr); + memcpy(bytebuf, pstr->data, pstr->len); result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, mib->parm2); } @@ -543,7 +543,7 @@ static int prism2mib_wepdefaultkey(struct mibrec *mib, len = (pstr->len > 5) ? HFA384x_RID_CNFWEP128DEFAULTKEY_LEN : HFA384x_RID_CNFWEPDEFAULTKEY_LEN; memset(bytebuf, 0, len); - prism2mgmt_pstr2bytearea(bytebuf, pstr); + memcpy(bytebuf, pstr->data, pstr->len); result = hfa384x_drvr_setconfig(hw, mib->parm1, bytebuf, len); } @@ -758,26 +758,6 @@ void prism2mgmt_pstr2bytestr(struct hfa384x_bytestr *bytestr, memcpy(bytestr->data, pstr->data, pstr->len); } -/*---------------------------------------------------------------- -* prism2mgmt_pstr2bytearea -* -* Convert the pstr data in the WLAN message structure into an hfa384x -* byte area format. -* -* Arguments: -* bytearea hfa384x byte area data type -* pstr wlan message data -* -* Returns: -* Nothing -* -----------------------------------------------------------------*/ - -void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr) -{ - memcpy(bytearea, pstr->data, pstr->len); -} - /*---------------------------------------------------------------- * prism2mgmt_bytestr2pstr * -- cgit From 4a3b3f47eda221f6b68ad601f630470fbb828e59 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 13 Feb 2016 18:49:35 +0530 Subject: Staging: wlan-ng: Remove function prototype This patch removes the function prototype for prism2mgmt_pstr2bytearea as it is no longer needed. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2mgmt.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h index 7a9f424607b7..e6472034da33 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.h +++ b/drivers/staging/wlan-ng/prism2mgmt.h @@ -87,7 +87,6 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp); * Prism2 data types ---------------------------------------------------------------*/ /* byte area conversion functions*/ -void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr); void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len); /* byte string conversion functions*/ -- cgit From 9c583af90a8ead5032b90492b66dd7117591a528 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 13 Feb 2016 18:20:17 -0500 Subject: drivers/staging/android: don't use modular references in sync_debug.c In commit 8a0044846115e74552b671a7073cffeec14b9316 ("staging/android: create a 'sync' dir for debugfs information"), modular references were introduced to this file. However if we look, we find: drivers/staging/android/Makefile:obj-$(CONFIG_SYNC) += sync.o sync_debug.o drivers/staging/android/Kconfig:config SYNC drivers/staging/android/Kconfig: bool "Synchronization framework" This file isn't currently buildable as a module, and hence the code for module_exit is just dead code. Remove it and the module.h include. Cc: Gustavo Padovan Cc: Maarten Lankhorst Cc: Greg Kroah-Hartman Signed-off-by: Paul Gortmaker Signed-off-by: Greg Kroah-Hartman --- drivers/staging/android/sync_debug.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index fd13f1e885e5..5a7ec58fbc09 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -15,7 +15,6 @@ */ #include -#include #include #include #include @@ -335,13 +334,6 @@ static __init int sync_debugfs_init(void) } late_initcall(sync_debugfs_init); -static __exit void sync_debugfs_exit(void) -{ - if (dbgfs) - debugfs_remove_recursive(dbgfs); -} -module_exit(sync_debugfs_exit); - #define DUMP_CHUNK 256 static char sync_dump_buf[64 * 1024]; void sync_dump(void) -- cgit From f3b8a53c6d0145eae7f5e9b452a9f6f3d03e17cc Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:03:47 +0530 Subject: staging: rtl8192u: ieee80211: rtl819x_TSProc: Replace MSECS with msecs_to_jiffies Replace driver specific macro MSECS with msecs_to_jiffies(). This was found using the following Coccinelle semantic patch: // @@ expression e; @@ - MSECS(e) + msecs_to_jiffies(e) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index f33c74342cf3..36a165eab3b7 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -87,7 +87,8 @@ static void RxPktPendingTimeout(unsigned long data) if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff)) { pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq; - mod_timer(&pRxTs->RxPktPendingTimer, jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime)); + mod_timer(&pRxTs->RxPktPendingTimer, + jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime)); } spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); @@ -212,7 +213,8 @@ static void AdmitTS(struct ieee80211_device *ieee, del_timer_sync(&pTsCommonInfo->InactTimer); if(InactTime!=0) - mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime)); + mod_timer(&pTsCommonInfo->InactTimer, + jiffies + msecs_to_jiffies(InactTime)); } @@ -590,7 +592,8 @@ void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS) if(pTxTS->bAddBaReqDelayed) { IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n"); - mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY)); + mod_timer(&pTxTS->TsAddBaTimer, + jiffies + msecs_to_jiffies(TS_ADDBA_DELAY)); } else { -- cgit From 69bf7ecea2f441aeed71b496d92e31c6a86d9504 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:03:54 +0530 Subject: staging: rtl8192u: ieee80211: rtl819x_BAProc: Replace MSECS with msecs_to_jiffies Replace driver specific macro MSECS with msecs_to_jiffies(). This was found using the following Coccinelle semantic patch: // @@ expression e; @@ - MSECS(e) + msecs_to_jiffies(e) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 3bde744604c2..789b7c95b86e 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -19,7 +19,7 @@ static void ActivateBAEntry(struct ieee80211_device *ieee, PBA_RECORD pBA, u16 T { pBA->bValid = true; if(Time != 0) - mod_timer(&pBA->Timer, jiffies + MSECS(Time)); + mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time)); } /******************************************************************************************************************** -- cgit From 4763a75289926cce327f7c25b4f757d29377d127 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:04:04 +0530 Subject: staging: rtl8192u: ieee80211: ieee80211_softmac: Replace MSECS with msecs_to_jiffies Replace driver specific macro MSECS with msecs_to_jiffies(). This was found using the following Coccinelle semantic patch: // @@ expression e; @@ - MSECS(e) + msecs_to_jiffies(e) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 21ee41034d7a..6d85648c6d7c 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -380,7 +380,8 @@ static void ieee80211_send_beacon(struct ieee80211_device *ieee) if (ieee->beacon_txing && ieee->ieee_up) { // if(!timer_pending(&ieee->beacon_timer)) // add_timer(&ieee->beacon_timer); - mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5))); + mod_timer(&ieee->beacon_timer, + jiffies + msecs_to_jiffies(ieee->current_network.beacon_interval-5)); } //spin_unlock_irqrestore(&ieee->beacon_lock,flags); } @@ -1735,10 +1736,12 @@ static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps)) return 2; - if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))) + if(!time_after(jiffies, + ieee->dev->trans_start + msecs_to_jiffies(timeout))) return 0; - if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))) + if(!time_after(jiffies, + ieee->last_rx_ps_time + msecs_to_jiffies(timeout))) return 0; if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) && -- cgit From b1d96609031782a219efd0b441e196b7bfc5ed05 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:04:10 +0530 Subject: staging: rtl8192u: ieee80211: ieee80211_rx: Replace MSECS with msecs_to_jiffies Replace driver specific macro MSECS with msecs_to_jiffies(). This was found using the following Coccinelle semantic patch: // @@ expression e; @@ - MSECS(e) + msecs_to_jiffies(e) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 28ad63ac289b..9dfde0794b80 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -761,7 +761,8 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee, pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq; if(timer_pending(&pTS->RxPktPendingTimer)) del_timer_sync(&pTS->RxPktPendingTimer); - pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime); + pTS->RxPktPendingTimer.expires = jiffies + + msecs_to_jiffies(pHTInfo->RxReorderPendingTime); add_timer(&pTS->RxPktPendingTimer); } -- cgit From e6be66fff720f85402be6c22ec57db154bf7df76 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:04:16 +0530 Subject: staging: rtl8192u: r8192U_dm: Replace MSECS with msecs_to_jiffies Replace driver specific macro MSECS with msecs_to_jiffies(). This was found using the following Coccinelle semantic patch: // @@ expression e; @@ - MSECS(e) + msecs_to_jiffies(e) // Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/r8192U_dm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c index 9b58b1afc1d1..d2e86b9d2c97 100644 --- a/drivers/staging/rtl8192u/r8192U_dm.c +++ b/drivers/staging/rtl8192u/r8192U_dm.c @@ -2769,12 +2769,14 @@ void dm_fsync_timer_callback(unsigned long data) if (bDoubleTimeInterval) { if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); - priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval); + priv->fsync_timer.expires = jiffies + + msecs_to_jiffies(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval); add_timer(&priv->fsync_timer); } else { if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); - priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); + priv->fsync_timer.expires = jiffies + + msecs_to_jiffies(priv->ieee80211->fsync_time_interval); add_timer(&priv->fsync_timer); } } else { @@ -2847,7 +2849,8 @@ static void dm_StartSWFsync(struct net_device *dev) } if (timer_pending(&priv->fsync_timer)) del_timer_sync(&priv->fsync_timer); - priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval); + priv->fsync_timer.expires = jiffies + + msecs_to_jiffies(priv->ieee80211->fsync_time_interval); add_timer(&priv->fsync_timer); write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd); -- cgit From 4ebeaf513310618fcc1648bbbb89b06b5ab75bee Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:04:23 +0530 Subject: staging: rtl8192u: ieee80211: Remove MSECS macro Remove driver specific macro MSECS since all instances of this macro have been replaced by direct calls to msecs_to_jiffies(). Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index 967ef9a98fc0..c0a0897bc2cd 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -329,7 +329,6 @@ typedef struct ieee_param { // linux under 2.6.9 release may not support it, so modify it for common use -#define MSECS(t) msecs_to_jiffies(t) #define msleep_interruptible_rsl msleep_interruptible #define IEEE80211_DATA_LEN 2304 -- cgit From 3a341db3dbba968baa449f85cc3efeaaf2969ade Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 12:31:33 +0530 Subject: staging: rtl8192u: ieee80211: ieee80211_softmac: Replace driver specific macro msleep_interruptible_rsl Replace driver specific msleep_interruptible_rsl macro with direct call to msleep_interruptible. Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Vaishali Thakkar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index 6d85648c6d7c..c1995f2f0918 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -469,7 +469,7 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) if (ieee->state >= IEEE80211_LINKED && ieee->sync_scan_hurryup) goto out; - msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME); + msleep_interruptible(IEEE80211_SOFTMAC_SCAN_TIME); } out: -- cgit From e4d31fbad2752ce923ee79a05ef1789acb568627 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 12:34:14 +0530 Subject: staging: rtl8192u: ieee80211: Remove msleep_interruptible_rsl Macro Remove driver specific macro msleep_interruptible_rsl as it has been replaced by a direct call to msleep_interruptible in the single instance referencing it. Signed-off-by: Amitoj Kaur Chawla Reviewed-by: Vaishali Thakkar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index c0a0897bc2cd..ae1c104ac9f3 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -329,8 +329,6 @@ typedef struct ieee_param { // linux under 2.6.9 release may not support it, so modify it for common use -#define msleep_interruptible_rsl msleep_interruptible - #define IEEE80211_DATA_LEN 2304 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section 6.2.1.1.2. -- cgit From 04bdfd20e08f9a10f6155d181a7e2e1a0d8ca24c Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 15:58:52 -0500 Subject: staging: rtl8192u: ieee80211: Fix comment style This patch changes some C99-style "//..." comments to C89 "/* ... */" style. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8192u/ieee80211/ieee80211_softmac.c | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c index c1995f2f0918..9bc5aac0ac81 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c @@ -103,12 +103,12 @@ static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) { u8 *tag = *tag_p; - *tag++ = MFIE_TYPE_GENERIC; //0 + *tag++ = MFIE_TYPE_GENERIC; /* 0 */ *tag++ = 7; *tag++ = 0x00; *tag++ = 0x50; *tag++ = 0xf2; - *tag++ = 0x02;//5 + *tag++ = 0x02; /* 5 */ *tag++ = 0x00; *tag++ = 0x01; #ifdef SUPPORT_USPD @@ -128,12 +128,12 @@ static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { u8 *tag = *tag_p; - *tag++ = MFIE_TYPE_GENERIC; //0 + *tag++ = MFIE_TYPE_GENERIC; /* 0 */ *tag++ = 7; *tag++ = 0x00; *tag++ = 0xe0; *tag++ = 0x4c; - *tag++ = 0x01;//5 + *tag++ = 0x01; /* 5 */ *tag++ = 0x02; *tag++ = 0x11; *tag++ = 0x00; @@ -186,14 +186,14 @@ static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee) PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; u8 rate; - // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. + /* 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. */ if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M) rate = 0x0c; else rate = ieee->basic_rate & 0x7f; if (rate == 0) { - // 2005.01.26, by rcnjko. + /* 2005.01.26, by rcnjko. */ if(ieee->mode == IEEE_A|| ieee->mode== IEEE_N_5G|| (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK)) @@ -340,7 +340,7 @@ inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - req->header.duration_id = 0; //FIXME: is this OK ? + req->header.duration_id = 0; /* FIXME: is this OK? */ memset(req->header.addr1, 0xff, ETH_ALEN); memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); @@ -673,7 +673,7 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be else if(ieee->auth_mode == 1) auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY); else if(ieee->auth_mode == 2) - auth->algorithm = WLAN_AUTH_OPEN;//0x80; + auth->algorithm = WLAN_AUTH_OPEN; /* 0x80; */ printk("=================>%s():auth->algorithm is %d\n",__func__,auth->algorithm); auth->transaction = cpu_to_le16(ieee->associate_seq); ieee->associate_seq++; @@ -728,7 +728,7 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len)); - //HT ralated element + /* HT ralated element */ tmp_ht_cap_buf =(u8 *) &(ieee->pHTInfo->SelfHTCap); tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); tmp_ht_info_buf =(u8 *) &(ieee->pHTInfo->SelfHTInfo); @@ -766,13 +766,13 @@ static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); - beacon_buf->header.duration_id = 0; //FIXME + beacon_buf->header.duration_id = 0; /* FIXME */ beacon_buf->beacon_interval = cpu_to_le16(ieee->current_network.beacon_interval); beacon_buf->capability = cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); beacon_buf->capability |= - cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here + cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); /* add short preamble here */ if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); @@ -1013,7 +1013,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco crypt = ieee->crypt[ieee->tx_keyidx]; encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len)); - //Include High Throuput capability && Realtek proprietary + /* Include High Throuput capability && Realtek proprietary */ if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) { ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap); @@ -1045,8 +1045,8 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco #ifdef THOMAS_TURBO len = sizeof(struct ieee80211_assoc_request_frame)+ 2 - + beacon->ssid_len//essid tagged val - + rate_len//rates tagged val + + beacon->ssid_len /* essid tagged val */ + + rate_len /* rates tagged val */ + wpa_ie_len + wmm_info_len + turbo_info_len @@ -1058,8 +1058,8 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco + ieee->tx_headroom; #else len = sizeof(struct ieee80211_assoc_request_frame)+ 2 - + beacon->ssid_len//essid tagged val - + rate_len//rates tagged val + + beacon->ssid_len /* essid tagged val */ + + rate_len /* rates tagged val */ + wpa_ie_len + wmm_info_len + ht_cap_len -- cgit From a4e320b7215d2d1f4932474276a46219d6a4e9f1 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 14 Feb 2016 20:54:03 +0530 Subject: Staging: rtl8188eu: os_dep: Remove NULL test before rtw_free_netdev The function rtw_free_netdev test whether its argument is NULL and return immediately. So NULL test before this function is not needed. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/os_dep/usb_intf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 01d50f7c1667..6a68f1759312 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -474,8 +474,7 @@ static void rtw_usb_if1_deinit(struct adapter *if1) pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n", if1->hw_init_completed); rtw_free_drv_sw(if1); - if (pnetdev) - rtw_free_netdev(pnetdev); + rtw_free_netdev(pnetdev); } static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid) -- cgit From a4d7d05b2da6afc5054cf3065084bda5751e5deb Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 14 Feb 2016 20:34:28 +0530 Subject: Staging: rdma: hfi1: Delete NULL check before vfree The function vfree test whether the argument is NULL and return immediately. SO NULL test is not needed before vfree. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/user_sdma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rdma/hfi1/user_sdma.c b/drivers/staging/rdma/hfi1/user_sdma.c index d3de771a0770..4f5595060501 100644 --- a/drivers/staging/rdma/hfi1/user_sdma.c +++ b/drivers/staging/rdma/hfi1/user_sdma.c @@ -468,8 +468,7 @@ int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd) fd->pq = NULL; } if (fd->cq) { - if (fd->cq->comps) - vfree(fd->cq->comps); + vfree(fd->cq->comps); kfree(fd->cq); fd->cq = NULL; } -- cgit From 3b15cfbbeed1f3fc898dcefa0d11340c266f09ee Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 21:57:51 -0500 Subject: staging: rts5208: Place constants on the right side of comparisons Constants should be placed on the right hand side of comparisons. This issue was identified by checkpatch. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rts5208/sd.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index d6c498209b2c..244d589db359 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -4260,10 +4260,10 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } - if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || - (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) || - (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) || - (0x64 != srb->cmnd[8])) { + if ((srb->cmnd[2] != 0x53) || (srb->cmnd[3] != 0x44) || + (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) || + (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) || + (srb->cmnd[8] != 0x64)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -4284,7 +4284,7 @@ int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } - buf[5] = (1 == CHK_SD(sd_card)) ? 0x01 : 0x02; + buf[5] = (CHK_SD(sd_card) == 1) ? 0x01 : 0x02; if (chip->card_wp & SD_CARD) buf[5] |= 0x80; @@ -5176,10 +5176,10 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) return TRANSPORT_FAILED; } - if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || - (0x20 != srb->cmnd[4]) || (0x43 != srb->cmnd[5]) || - (0x61 != srb->cmnd[6]) || (0x72 != srb->cmnd[7]) || - (0x64 != srb->cmnd[8])) { + if ((srb->cmnd[2] != 0x53) || (srb->cmnd[3] != 0x44) || + (srb->cmnd[4] != 0x20) || (srb->cmnd[5] != 0x43) || + (srb->cmnd[6] != 0x61) || (srb->cmnd[7] != 0x72) || + (srb->cmnd[8] != 0x64)) { set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD); rtsx_trace(chip); return TRANSPORT_FAILED; @@ -5188,7 +5188,7 @@ int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip) switch (srb->cmnd[1] & 0x0F) { case 0: #ifdef SUPPORT_SD_LOCK - if (0x64 == srb->cmnd[9]) + if (srb->cmnd[9] == 0x64) sd_card->sd_lock_status |= SD_SDR_RST; #endif retval = reset_sd_card(chip); -- cgit From 6d9b10c866171e77ebbbe7271dd97a758b5d0457 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 12 Feb 2016 20:40:27 +0530 Subject: Staging: iio: light: remove exceptional & on function name In this file,function names are otherwise used as pointers without &. Found using coccinelle. // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/isl29018.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c index bbf7e35cbc7d..756057cae86a 100644 --- a/drivers/staging/iio/light/isl29018.c +++ b/drivers/staging/iio/light/isl29018.c @@ -614,15 +614,15 @@ static int isl29018_chip_init(struct isl29018_chip *chip) static const struct iio_info isl29018_info = { .attrs = &isl29018_group, .driver_module = THIS_MODULE, - .read_raw = &isl29018_read_raw, - .write_raw = &isl29018_write_raw, + .read_raw = isl29018_read_raw, + .write_raw = isl29018_write_raw, }; static const struct iio_info isl29023_info = { .attrs = &isl29023_group, .driver_module = THIS_MODULE, - .read_raw = &isl29018_read_raw, - .write_raw = &isl29018_write_raw, + .read_raw = isl29018_read_raw, + .write_raw = isl29018_write_raw, }; static bool is_volatile_reg(struct device *dev, unsigned int reg) -- cgit From df271034692dfa26010f27795fe955c866320b51 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 12 Feb 2016 20:40:28 +0530 Subject: Staging: iio: light: remove exceptional & on function name In this file,function names are otherwise used as pointers without &. Found using coccinelle. // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/light/isl29028.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c index 32ae1127da33..e1bca9c55119 100644 --- a/drivers/staging/iio/light/isl29028.c +++ b/drivers/staging/iio/light/isl29028.c @@ -406,8 +406,8 @@ static const struct iio_chan_spec isl29028_channels[] = { static const struct iio_info isl29028_info = { .attrs = &isl29108_group, .driver_module = THIS_MODULE, - .read_raw = &isl29028_read_raw, - .write_raw = &isl29028_write_raw, + .read_raw = isl29028_read_raw, + .write_raw = isl29028_write_raw, }; static int isl29028_chip_init(struct isl29028_chip *chip) -- cgit From 343af6379e950266ee3d4f638a3ffe0b01b08eab Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 12 Feb 2016 20:40:29 +0530 Subject: Staging: iio: magnetometer: remove exceptional & on function name In this file,function names are otherwise used as pointers without &. Found using coccinelle. // @r@ identifier f; @@ f(...) { ... } @@ identifier r.f; @@ - &f + f // Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/iio/magnetometer/hmc5843_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c index 94897993793e..9ee9a421a8b7 100644 --- a/drivers/staging/iio/magnetometer/hmc5843_core.c +++ b/drivers/staging/iio/magnetometer/hmc5843_core.c @@ -554,9 +554,9 @@ static int hmc5843_init(struct hmc5843_data *data) static const struct iio_info hmc5843_info = { .attrs = &hmc5843_group, - .read_raw = &hmc5843_read_raw, - .write_raw = &hmc5843_write_raw, - .write_raw_get_fmt = &hmc5843_write_raw_get_fmt, + .read_raw = hmc5843_read_raw, + .write_raw = hmc5843_write_raw, + .write_raw_get_fmt = hmc5843_write_raw_get_fmt, .driver_module = THIS_MODULE, }; -- cgit From f7099ad7bd35c56795fb50f5026b7040abac62da Mon Sep 17 00:00:00 2001 From: Rakhi Sharma Date: Sat, 13 Feb 2016 10:54:20 +0530 Subject: staging: rtl8712: Fixed a comparision coding style warning. WARNING: Comparisons should place the constant on the right side of the test Fixed this warning by placing the constant on right side. Signed-off-by: Rakhi Sharma - Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl8712_efuse.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c index eaa93fbb95a3..76f60ba5ee9b 100644 --- a/drivers/staging/rtl8712/rtl8712_efuse.c +++ b/drivers/staging/rtl8712/rtl8712_efuse.c @@ -161,7 +161,7 @@ static u8 efuse_is_empty(struct _adapter *padapter, u8 *empty) /* read one byte to check if E-Fuse is empty */ if (efuse_one_byte_rw(padapter, true, 0, &value)) { - if (0xFF == value) + if (value == 0xFF) *empty = true; else *empty = false; @@ -345,7 +345,7 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr) ret = false; } else if (pkt.data[i * 2] != value) { ret = false; - if (0xFF == value) /* write again */ + if (value == 0xFF) /* write again */ efuse_one_byte_write(padapter, addr, pkt.data[i * 2]); } @@ -353,7 +353,7 @@ static u8 fix_header(struct _adapter *padapter, u8 header, u16 header_addr) ret = false; } else if (pkt.data[i * 2 + 1] != value) { ret = false; - if (0xFF == value) /* write again */ + if (value == 0xFF) /* write again */ efuse_one_byte_write(padapter, addr + 1, pkt.data[i * 2 + 1]); @@ -420,7 +420,7 @@ u8 r8712_efuse_pg_packet_write(struct _adapter *padapter, const u8 offset, } /* write header fail */ bResult = false; - if (0xFF == efuse_data) + if (efuse_data == 0xFF) return bResult; /* nothing damaged. */ /* call rescue procedure */ if (!fix_header(padapter, efuse_data, efuse_addr)) -- cgit From af09054958ba2a17586a463eecafb6f0660d4cc0 Mon Sep 17 00:00:00 2001 From: Joseph Bisch Date: Sun, 14 Feb 2016 16:57:27 -0500 Subject: staging: rtl8712: Remove unnecessary ret variable Since the variable ret is set at the beginning of the function and never changes its value, we can just return the value it was set to. Found using coccinelle with misc/returnvar.cocci. Signed-off-by: Joseph Bisch Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/os_intfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index b89e2d3c4fe1..ab19112eae13 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -269,7 +269,6 @@ void r8712_stop_drv_timers(struct _adapter *padapter) static u8 init_default_value(struct _adapter *padapter) { - u8 ret = _SUCCESS; struct registry_priv *pregistrypriv = &padapter->registrypriv; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -302,7 +301,7 @@ static u8 init_default_value(struct _adapter *padapter) r8712_init_registrypriv_dev_network(padapter); r8712_update_registrypriv_dev_network(padapter); /*misc.*/ - return ret; + return _SUCCESS; } u8 r8712_init_drv_sw(struct _adapter *padapter) -- cgit From c6d609cfe70d523821c575bb7d742814cc9cac02 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 14 Feb 2016 10:59:49 +0530 Subject: Staging: rtl8723au: Remove unused macros The macros PlatformAcquireSpinLock and PlatformReleaseSpinLock are not used anywhere so remove them. Used grep to find occurences. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c index d46d1c7be8ba..33eabf4f2ad3 100644 --- a/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c +++ b/drivers/staging/rtl8723au/hal/rtl8723a_bt-coexist.c @@ -80,8 +80,6 @@ if ((BTCoexDbgLevel == _bt_dbg_on_)) {\ #define PlatformProcessHCICommands(...) #define PlatformTxBTQueuedPackets(...) #define PlatformIndicateBTACLData(...) (RT_STATUS_SUCCESS) -#define PlatformAcquireSpinLock(padapter, type) -#define PlatformReleaseSpinLock(padapter, type) #define GET_UNDECORATED_AVERAGE_RSSI(padapter) \ (GET_HAL_DATA(padapter)->dmpriv.EntryMinUndecoratedSmoothedPWDB) -- cgit From c8279611f3fcabdb05e6fe87fe393ccfc2e3d8bc Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sun, 14 Feb 2016 10:59:50 +0530 Subject: Staging: rtl8192u: Remove useless comments Remove the commented out places where macros PlatformAcquireSpinLock and PlatformReleaseSpinLock are called as these macros are no longer used. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c index 36a165eab3b7..148d0d45547b 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c @@ -35,9 +35,7 @@ static void RxPktPendingTimeout(unsigned long data) u8 index = 0; bool bPktInBuf = false; - spin_lock_irqsave(&(ieee->reorder_spinlock), flags); - //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__func__); if(pRxTs->RxTimeoutIndicateSeq != 0xffff) { @@ -91,7 +89,6 @@ static void RxPktPendingTimeout(unsigned long data) jiffies + msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime)); } spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); - //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); } /******************************************************************************************************************** @@ -471,7 +468,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, PTS_COMMON_INFO pTs, while(!list_empty(&pRxTS->RxPendingPktList)) { - // PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); spin_lock_irqsave(&(ieee->reorder_spinlock), flags); //pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); @@ -491,7 +487,6 @@ static void RemoveTsEntry(struct ieee80211_device *ieee, PTS_COMMON_INFO pTs, prxb = NULL; } list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List); - //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); } -- cgit From a5975238323b249d75e1cf4095651d72fed11708 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 22:23:17 -0500 Subject: staging: sm750fb: Remove unneeded braces in if...else statements Remove unnecessary braces in if...else statements where both branches have a single statement each. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/ddk750_power.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c index ec1cac2c1793..33e092e026e9 100644 --- a/drivers/staging/sm750fb/ddk750_power.c +++ b/drivers/staging/sm750fb/ddk750_power.c @@ -106,11 +106,10 @@ void enable2DEngine(unsigned int enable) u32 gate; gate = PEEK32(CURRENT_GATE); - if (enable) { + if (enable) gate |= (CURRENT_GATE_DE | CURRENT_GATE_CSC); - } else { + else gate &= ~(CURRENT_GATE_DE | CURRENT_GATE_CSC); - } setCurrentGate(gate); } -- cgit From 60c0bdcb090a8e66fe8ed3190fb9e5d3d1e37623 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 22:48:42 -0500 Subject: staging: sm750fb: Eliminate commented out code This patch removes commented out code in the file. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_cursor.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c index 0a41585535a6..e887101c0974 100644 --- a/drivers/staging/sm750fb/sm750_cursor.c +++ b/drivers/staging/sm750fb/sm750_cursor.c @@ -115,15 +115,6 @@ void hw_cursor_setData(struct lynx_cursor *cursor, pstart = cursor->vstart; pbuffer = pstart; -/* - if(odd &1){ - hw_cursor_setData2(cursor,rop,pcol,pmsk); - } - odd++; - if(odd > 0xfffffff0) - odd=0; -*/ - for (i = 0; i < count; i++) { color = *pcol++; mask = *pmsk++; -- cgit From da6985f599d7c01a3f3692774b7bf5018eadfec2 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 22:59:06 -0500 Subject: staging: sm750fb: Fix indentation of if...else statements This patch clears the checkpatch warning about suspect code indent for conditional statements in the file. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/sm750fb/sm750_hw.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c index 2b1cb9a6fbe7..01850bff6de1 100644 --- a/drivers/staging/sm750fb/sm750_hw.c +++ b/drivers/staging/sm750fb/sm750_hw.c @@ -149,22 +149,21 @@ int hw_sm750_inithw(struct sm750_dev *sm750_dev, struct pci_dev *pdev) /* Set up GPIO for software I2C to program DVI chip in the Xilinx SP605 board, in order to have video signal. */ - sm750_sw_i2c_init(0, 1); + sm750_sw_i2c_init(0, 1); - - /* Customer may NOT use CH7301 DVI chip, which has to be - initialized differently. - */ - if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) { + /* Customer may NOT use CH7301 DVI chip, which has to be + initialized differently. + */ + if (sm750_sw_i2c_read_reg(0xec, 0x4a) == 0x95) { /* The following register values for CH7301 are from Chrontel app note and our experiment. */ pr_info("yes,CH7301 DVI chip found\n"); - sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16); - sm750_sw_i2c_write_reg(0xec, 0x21, 0x9); - sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0); + sm750_sw_i2c_write_reg(0xec, 0x1d, 0x16); + sm750_sw_i2c_write_reg(0xec, 0x21, 0x9); + sm750_sw_i2c_write_reg(0xec, 0x49, 0xC0); pr_info("okay,CH7301 DVI chip setup done\n"); - } + } } /* init 2d engine */ -- cgit From 26462869a6e8a4bc03d2be8d821953141c7e730c Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Fri, 12 Feb 2016 16:22:19 +0530 Subject: Staging: rtl8723au: Replace header files The headers ,, should not be directly included so replace them. Warning generated by checkpatch.pl. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/include/osdep_service.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/rtl8723au/include/osdep_service.h b/drivers/staging/rtl8723au/include/osdep_service.h index dedb41874de5..98250b12e9f2 100644 --- a/drivers/staging/rtl8723au/include/osdep_service.h +++ b/drivers/staging/rtl8723au/include/osdep_service.h @@ -29,10 +29,10 @@ #include #include #include -#include +#include #include -#include -#include +#include +#include #include #include #include -- cgit From 8cce78a73ff34ea4a5e0af03c929dc3f89781981 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Sat, 13 Feb 2016 16:42:32 +0530 Subject: Staging: rtl819u: ieee80211: Remove function ieee80211_wep_null Remove function ieee80211_wep_null from the file as is it blank and remove its declaration from the header file. Also remove its function call as it is of no use calling this function. Signed-off-by: Bhumika Goyal Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192u/ieee80211/ieee80211.h | 3 --- drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c | 3 --- drivers/staging/rtl8192u/ieee80211/ieee80211_module.c | 1 - 3 files changed, 7 deletions(-) diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h index ae1c104ac9f3..68931e5ecd8f 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h @@ -238,8 +238,6 @@ typedef struct cb_desc { #define ieee80211_tkip_null ieee80211_tkip_null_rsl -#define ieee80211_wep_null ieee80211_wep_null_rsl - #define free_ieee80211 free_ieee80211_rsl #define alloc_ieee80211 alloc_ieee80211_rsl @@ -2257,7 +2255,6 @@ void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee); /* ieee80211_crypt_ccmp&tkip&wep.c */ void ieee80211_tkip_null(void); -void ieee80211_wep_null(void); void ieee80211_ccmp_null(void); int ieee80211_crypto_init(void); diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c index 681611dc93d3..cde8e2b958cb 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_wep.c @@ -274,6 +274,3 @@ void __exit ieee80211_crypto_wep_exit(void) ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); } -void ieee80211_wep_null(void) -{ -} diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c index 425b2ddfc916..30fff6c5696b 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c @@ -177,7 +177,6 @@ struct net_device *alloc_ieee80211(int sizeof_priv) /* These function were added to load crypte module autoly */ ieee80211_tkip_null(); - ieee80211_wep_null(); ieee80211_ccmp_null(); return dev; -- cgit From 76ee538178a1eef548d130251b6a269cce26288b Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sun, 14 Feb 2016 14:10:11 +0100 Subject: staging: netlogic: Fix multiple irq assignments in a single line Avoid the use of multiple assignments in a single line. Checkpatch found this issue. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/netlogic/platform_net.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c index 7806c2bc3af3..74e154f62c70 100644 --- a/drivers/staging/netlogic/platform_net.c +++ b/drivers/staging/netlogic/platform_net.c @@ -86,7 +86,8 @@ static void xlr_resource_init(struct resource *res, int offset, int irq) res++; res->name = "gmac"; - res->start = res->end = irq; + res->start = irq; + res->end = irq; res->flags = IORESOURCE_IRQ; } -- cgit From b0b24338add9f99003f3ead56c0f15b451fba33e Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sun, 14 Feb 2016 16:26:13 +0100 Subject: staging: netlogic: Remove multiple blank lines Avoid the use of multiple blank lines. Checkpatch found this issue. Signed-off-by: Laura Garcia Liebana Signed-off-by: Greg Kroah-Hartman --- drivers/staging/netlogic/platform_net.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c index 74e154f62c70..7fcbc664e1de 100644 --- a/drivers/staging/netlogic/platform_net.c +++ b/drivers/staging/netlogic/platform_net.c @@ -209,7 +209,6 @@ static void xlr_gmac_init(void) .gpio_addr = NULL, }; - static struct platform_device xlr_net_dev0 = { .name = "xlr-net", .id = 0, -- cgit From 7d8827cf7dcaf8553244aa5c0d2b63a4577824db Mon Sep 17 00:00:00 2001 From: Laura Garcia Liebana Date: Sun, 14 Feb 2016 18:55:23 +0100 Subject: staging: netlogic: Fix parenthesis alignment Align arguments with the open parenthesis. Checkpatch found this issue. Signed-off-by: Laura Garcia Liebana Acked-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/netlogic/platform_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c index 7fcbc664e1de..9b52154048b0 100644 --- a/drivers/staging/netlogic/platform_net.c +++ b/drivers/staging/netlogic/platform_net.c @@ -122,8 +122,8 @@ static struct platform_device *gmac_controller2_init(void *gmac0_addr) ndata1.phy_addr[mac] = mac + 4 + 0x10; xlr_resource_init(&xlr_net1_res[mac * 2], - xlr_gmac_offsets[mac + 4], - xlr_gmac_irqs[mac + 4]); + xlr_gmac_offsets[mac + 4], + xlr_gmac_irqs[mac + 4]); } xlr_net_dev1.num_resources = 8; -- cgit From e6ceec822a0c1192744b15e95e9119051ea89a31 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Sat, 13 Feb 2016 22:05:01 -0500 Subject: staging: speakup: Fix block comment style Use trailing */ on a separate line when it is a block comment. This patch fixes the last of the checkpatch warnings for the file. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/serialio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c index 361545770120..c2c435cc3d63 100644 --- a/drivers/staging/speakup/serialio.c +++ b/drivers/staging/speakup/serialio.c @@ -8,7 +8,8 @@ #include /* WARNING: Do not change this to without testing that - * SERIAL_PORT_DFNS does get defined to the appropriate value. */ + * SERIAL_PORT_DFNS does get defined to the appropriate value. + */ #include #ifndef SERIAL_PORT_DFNS -- cgit From a25e278020bf4cf1d8183bb81f86ec7d73d16dca Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 14 Feb 2016 02:45:30 +0200 Subject: staging: octeon: support fixed-link phys Support fixed-link PHYs. This allows to remove some of the board-specific link cvmx_helper code in the future. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon/ethernet-mdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 55abd83c38b6..0ac11b1221b7 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -181,6 +181,15 @@ int cvm_oct_phy_setup_device(struct net_device *dev) goto no_phy; phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0); + if (!phy_node && of_phy_is_fixed_link(priv->of_node)) { + int rc; + + rc = of_phy_register_fixed_link(priv->of_node); + if (rc) + return rc; + + phy_node = of_node_get(priv->of_node); + } if (!phy_node) goto no_phy; -- cgit From bb778553d491b65310b83c55274a2f09912d47a1 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 14 Feb 2016 02:47:28 +0200 Subject: staging: octeon-usb: support official bindings Support official DT bindings alongside with the deprecated ones. Signed-off-by: Aaro Koskinen Signed-off-by: Greg Kroah-Hartman --- drivers/staging/octeon-usb/octeon-hcd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 7844e2036060..eaf6ded40990 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -3594,9 +3594,12 @@ static int octeon_usb_probe(struct platform_device *pdev) usbn_node = dev->of_node->parent; i = of_property_read_u32(usbn_node, - "refclk-frequency", &clock_rate); + "clock-frequency", &clock_rate); + if (i) + i = of_property_read_u32(usbn_node, + "refclk-frequency", &clock_rate); if (i) { - dev_err(dev, "No USBN \"refclk-frequency\"\n"); + dev_err(dev, "No USBN \"clock-frequency\"\n"); return -ENXIO; } switch (clock_rate) { @@ -3610,14 +3613,17 @@ static int octeon_usb_probe(struct platform_device *pdev) initialize_flags = CVMX_USB_INITIALIZE_FLAGS_CLOCK_48MHZ; break; default: - dev_err(dev, "Illebal USBN \"refclk-frequency\" %u\n", + dev_err(dev, "Illegal USBN \"clock-frequency\" %u\n", clock_rate); return -ENXIO; } i = of_property_read_string(usbn_node, - "refclk-type", &clock_type); + "cavium,refclk-type", &clock_type); + if (i) + i = of_property_read_string(usbn_node, + "refclk-type", &clock_type); if (!i && strcmp("crystal", clock_type) == 0) is_crystal_clock = true; -- cgit From 73b37c91ac5f31c296220bb20dabb881c80b4222 Mon Sep 17 00:00:00 2001 From: Tomás Tormo Date: Sun, 14 Feb 2016 20:30:56 +0100 Subject: Staging: nvec: Modify the nvec_write_sync method to return the error code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modify the nvec_write_sync function to return the error code instead of the received message. The received message is now returned as an output parameter. Signed-off-by: Tomás Tormo Signed-off-by: Greg Kroah-Hartman --- drivers/staging/nvec/TODO | 2 -- drivers/staging/nvec/nvec.c | 34 +++++++++++++++++++--------------- drivers/staging/nvec/nvec.h | 5 +++-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/staging/nvec/TODO b/drivers/staging/nvec/TODO index e5ae42a0b44a..e4d85d9b4681 100644 --- a/drivers/staging/nvec/TODO +++ b/drivers/staging/nvec/TODO @@ -3,6 +3,4 @@ ToDo list (incomplete, unordered) - move half of the nvec init stuff to i2c-tegra.c - move event handling to nvec_events - finish suspend/resume support - - modifiy the sync_write method to return the received - message in a variable (and return the error code). - add support for more device implementations diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c index 82f7600fead3..1503ad717645 100644 --- a/drivers/staging/nvec/nvec.c +++ b/drivers/staging/nvec/nvec.c @@ -286,28 +286,30 @@ EXPORT_SYMBOL(nvec_write_async); * @nvec: An &struct nvec_chip * @data: The data to write * @size: The size of @data + * @msg: The response message received * * This is similar to nvec_write_async(), but waits for the * request to be answered before returning. This function * uses a mutex and can thus not be called from e.g. * interrupt handlers. * - * Returns: A pointer to the response message on success, - * %NULL on failure. Free with nvec_msg_free() once no longer - * used. + * Returns: 0 on success, a negative error code on failure. + * The response message is returned in @msg. Shall be freed with + * with nvec_msg_free() once no longer used. + * */ -struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, - const unsigned char *data, short size) +int nvec_write_sync(struct nvec_chip *nvec, + const unsigned char *data, short size, + struct nvec_msg **msg) { - struct nvec_msg *msg; - mutex_lock(&nvec->sync_write_mutex); + *msg = NULL; nvec->sync_write_pending = (data[1] << 8) + data[0]; if (nvec_write_async(nvec, data, size) < 0) { mutex_unlock(&nvec->sync_write_mutex); - return NULL; + return -ENOMEM; } dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n", @@ -316,16 +318,16 @@ struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, msecs_to_jiffies(2000)))) { dev_warn(nvec->dev, "timeout waiting for sync write to complete\n"); mutex_unlock(&nvec->sync_write_mutex); - return NULL; + return -ETIMEDOUT; } dev_dbg(nvec->dev, "nvec_sync_write: pong!\n"); - msg = nvec->last_sync_msg; + *msg = nvec->last_sync_msg; mutex_unlock(&nvec->sync_write_mutex); - return msg; + return 0; } EXPORT_SYMBOL(nvec_write_sync); @@ -878,9 +880,9 @@ static int tegra_nvec_probe(struct platform_device *pdev) pm_power_off = nvec_power_off; /* Get Firmware Version */ - msg = nvec_write_sync(nvec, get_firmware_version, 2); + err = nvec_write_sync(nvec, get_firmware_version, 2, &msg); - if (msg) { + if (!err) { dev_warn(nvec->dev, "ec firmware version %02x.%02x.%02x / %02x\n", msg->data[4], msg->data[5], msg->data[6], msg->data[7]); @@ -924,6 +926,7 @@ static int tegra_nvec_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int nvec_suspend(struct device *dev) { + int err; struct platform_device *pdev = to_platform_device(dev); struct nvec_chip *nvec = platform_get_drvdata(pdev); struct nvec_msg *msg; @@ -934,8 +937,9 @@ static int nvec_suspend(struct device *dev) /* keep these sync or you'll break suspend */ nvec_toggle_global_events(nvec, false); - msg = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend)); - nvec_msg_free(nvec, msg); + err = nvec_write_sync(nvec, ap_suspend, sizeof(ap_suspend), &msg); + if (!err) + nvec_msg_free(nvec, msg); nvec_disable_i2c_slave(nvec); diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h index 2ec9de906ca3..c03ca8d9572a 100644 --- a/drivers/staging/nvec/nvec.h +++ b/drivers/staging/nvec/nvec.h @@ -168,8 +168,9 @@ struct nvec_chip { int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data, short size); -struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, - const unsigned char *data, short size); +int nvec_write_sync(struct nvec_chip *nvec, + const unsigned char *data, short size, + struct nvec_msg **msg); int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, -- cgit From c272dc2da14cde0bfd9495a5aafb8e3e94f35601 Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Sat, 13 Feb 2016 10:31:02 +0530 Subject: staging: gdm724x: gdm_mux: Remove create_workqueue() With concurrency managed workqueues, use of dedicated workqueues can be replaced by using system_wq. Drop mux_rx_wq by using system_wq. Since there is only one work item per mux_dev and different mux_devs do not need to be ordered, increase of concurrency level by switching to system_wq should not break anything. cancel_work_sync() is used to ensure that work is not pending or executing on any CPU. Lastly, since all devices are suspended, which shutdowns the work item before the driver can be unregistered, it is guaranteed that no work item is pending or executing by the time exit path runs. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gdm724x/gdm_mux.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 445f83615575..937010b3a603 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -26,8 +26,6 @@ #include "gdm_mux.h" -static struct workqueue_struct *mux_rx_wq; - static u16 packet_type[TTY_MAX_COUNT] = {0xF011, 0xF010}; #define USB_DEVICE_CDC_DATA(vid, pid) \ @@ -275,7 +273,7 @@ static void gdm_mux_rcv_complete(struct urb *urb) r->len = r->urb->actual_length; spin_lock_irqsave(&rx->to_host_lock, flags); list_add_tail(&r->to_host_list, &rx->to_host_list); - queue_work(mux_rx_wq, &mux_dev->work_rx.work); + schedule_work(&mux_dev->work_rx.work); spin_unlock_irqrestore(&rx->to_host_lock, flags); } } @@ -602,6 +600,8 @@ static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg) mux_dev = tty_dev->priv_dev; rx = &mux_dev->rx; + cancel_work_sync(&mux_dev->work_rx.work); + if (mux_dev->usb_state != PM_NORMAL) { dev_err(intf->usb_dev, "usb suspend - invalid state\n"); return -1; @@ -656,13 +656,6 @@ static struct usb_driver gdm_mux_driver = { static int __init gdm_usb_mux_init(void) { - - mux_rx_wq = create_workqueue("mux_rx_wq"); - if (!mux_rx_wq) { - pr_err("work queue create fail\n"); - return -1; - } - register_lte_tty_driver(); return usb_register(&gdm_mux_driver); @@ -672,11 +665,6 @@ static void __exit gdm_usb_mux_exit(void) { unregister_lte_tty_driver(); - if (mux_rx_wq) { - flush_workqueue(mux_rx_wq); - destroy_workqueue(mux_rx_wq); - } - usb_deregister(&gdm_mux_driver); } -- cgit From 814625b539d36d57cb06f412714ec31d7fcd23db Mon Sep 17 00:00:00 2001 From: Amitoj Kaur Chawla Date: Fri, 12 Feb 2016 14:09:49 +0530 Subject: staging: goldfish: goldfish_nand: Return correct error code The return value of devm_kzalloc on failure of allocation of memory should be -ENOMEM and not -1. Found using Coccinelle. A simplified version of the semantic patch used is: // @@ expression *e; @@ e = devm_kzalloc(...); if (e == NULL) { ... return - -1 + -ENOMEM ; } // The single call site does not perform any checks on the return value, hence no change is required at the call site. Signed-off-by: Amitoj Kaur Chawla Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/goldfish/goldfish_nand.c b/drivers/staging/goldfish/goldfish_nand.c index 623353db5a08..5c4f61c006e2 100644 --- a/drivers/staging/goldfish/goldfish_nand.c +++ b/drivers/staging/goldfish/goldfish_nand.c @@ -290,7 +290,7 @@ static int nand_setup_cmd_params(struct platform_device *pdev, nand->cmd_params = devm_kzalloc(&pdev->dev, sizeof(struct cmd_params), GFP_KERNEL); if (!nand->cmd_params) - return -1; + return -ENOMEM; paddr = __pa(nand->cmd_params); writel((u32)(paddr >> 32), base + NAND_CMD_PARAMS_ADDR_HIGH); -- cgit From 28682b557d8e89f0a805d82bd74808ff89d0c1bf Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Mon, 15 Feb 2016 00:25:23 -0500 Subject: staging: vt6655: Fit function header on the same line Improve readability by fitting all parts of the function header on the same line. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/rf.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 3df430bf0a80..ae10da21ddd0 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -612,9 +612,7 @@ static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byCha * Return Value: true if succeeded; false if failed. * */ -bool RFbInit( - struct vnt_private *priv -) +bool RFbInit(struct vnt_private *priv) { bool ret = true; -- cgit From e1c484db0329dec3859ca898afcbba6dec967e5c Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Mon, 15 Feb 2016 00:15:12 -0500 Subject: staging: vt6655: Add missing blank line after declaration Add missing blank line after declaration of variables. Issue found by checkpatch. Signed-off-by: Janani Ravichandran Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/mac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c index e74782aa6475..79e42d075cde 100644 --- a/drivers/staging/vt6655/mac.c +++ b/drivers/staging/vt6655/mac.c @@ -488,6 +488,7 @@ bool MACbSafeTxOff(struct vnt_private *priv) bool MACbSafeStop(struct vnt_private *priv) { void __iomem *dwIoBase = priv->PortOffset; + MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX); if (!MACbSafeRxOff(priv)) { -- cgit From 288f152cadf940b38f4e5c6ea59bdeb9fd0398d2 Mon Sep 17 00:00:00 2001 From: Janani Ravichandran Date: Mon, 15 Feb 2016 00:57:38 -0500 Subject: staging: xgifb: Fix comment style Fix comments to use trailing */ on separate lines. Signed-off-by: Janani Ravichandran 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 879a7e6751ac..26b539bc6faf 100644 --- a/drivers/staging/xgifb/vb_init.c +++ b/drivers/staging/xgifb/vb_init.c @@ -57,7 +57,8 @@ XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension, data = xgifb_reg_get(pVBInfo->P3d4, 0x48); /* HOTPLUG_SUPPORT */ /* for current XG20 & XG21, GPIOH is floating, driver will - * fix DDR temporarily */ + * fix DDR temporarily + */ /* DVI read GPIOH */ data &= 0x01; /* 1=DDRII, 0=DDR */ /* ~HOTPLUG_SUPPORT */ -- cgit From c8b1d8977eee3acc63a65811dd72ec4a93b74388 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:12 +0200 Subject: usb: Add USB3.1 SuperSpeedPlus Isoc Endpoint Companion descriptor USB3.1 specifies a SuperSpeedPlus Isoc endpoint companion descriptor which is returned as part of the devices complete configuration descriptor. It contains number of bytes per service interval which is needed when reserving bus time in the schedule for transfers over 48K bytes per service interval. If bmAttributes bit 7 is set in the old SuperSpeed Endpoint Companion descriptor, it will be ollowed by the new SuperSpeedPlus Isoc Endpoint Companion descriptor. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/usb/ch9.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index 779a62aafafe..a65f1f328de1 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -234,6 +234,8 @@ struct usb_ctrlrequest { #define USB_DT_PIPE_USAGE 0x24 /* From the USB 3.0 spec */ #define USB_DT_SS_ENDPOINT_COMP 0x30 +/* From the USB 3.1 spec */ +#define USB_DT_SSP_ISOC_ENDPOINT_COMP 0x31 /* Conventional codes for class-specific descriptors. The convention is * defined in the USB "Common Class" Spec (3.11). Individual class specs @@ -613,6 +615,20 @@ static inline int usb_endpoint_interrupt_type( /*-------------------------------------------------------------------------*/ +/* USB_DT_SSP_ISOC_ENDPOINT_COMP: SuperSpeedPlus Isochronous Endpoint Companion + * descriptor + */ +struct usb_ssp_isoc_ep_comp_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __le16 wReseved; + __le32 dwBytesPerInterval; +} __attribute__ ((packed)); + +#define USB_DT_SSP_ISOC_EP_COMP_SIZE 8 + +/*-------------------------------------------------------------------------*/ + /* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ struct usb_ss_ep_comp_descriptor { __u8 bLength; @@ -646,6 +662,8 @@ usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp) /* Bits 1:0 of bmAttributes if this is an isoc endpoint */ #define USB_SS_MULT(p) (1 + ((p) & 0x3)) +/* Bit 7 of bmAttributes if a SSP isoc endpoint companion descriptor exists */ +#define USB_SS_SSP_ISOC_COMP(p) ((p) & (1 << 7)) /*-------------------------------------------------------------------------*/ -- cgit From b37d83a6a41499d582b8faedff1913ec75d9e70b Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:13 +0200 Subject: usb: Parse the new USB 3.1 SuperSpeedPlus Isoc endpoint companion descriptor USB 3.1 devices can return a new SuperSpeedPlus isoc endpoint companion descriptor for a isochronous endpoint that requires more than 48K bytes per Service Interval. The new descriptor immediately follows the old USB 3.0 SuperSpeed Endpoint Companion and will provide a new BytesPerInterval value. It is parsed and stored in struct usb_host_endpoint with the other endpoint related descriptors, and should be used by USB3.1 capable hosts to reserve bus time in the schedule. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index bbcf4009f99e..58d089802ab3 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -43,6 +43,27 @@ static int find_next_descriptor(unsigned char *buffer, int size, return buffer - buffer0; } +static void usb_parse_ssp_isoc_endpoint_companion(struct device *ddev, + int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, + unsigned char *buffer, int size) +{ + struct usb_ssp_isoc_ep_comp_descriptor *desc; + + /* + * The SuperSpeedPlus Isoc endpoint companion descriptor immediately + * follows the SuperSpeed Endpoint Companion descriptor + */ + desc = (struct usb_ssp_isoc_ep_comp_descriptor *) buffer; + if (desc->bDescriptorType != USB_DT_SSP_ISOC_ENDPOINT_COMP || + size < USB_DT_SSP_ISOC_EP_COMP_SIZE) { + dev_warn(ddev, "Invalid SuperSpeedPlus isoc endpoint companion" + "for config %d interface %d altsetting %d ep %d.\n", + cfgno, inum, asnum, ep->desc.bEndpointAddress); + return; + } + memcpy(&ep->ssp_isoc_ep_comp, desc, USB_DT_SSP_ISOC_EP_COMP_SIZE); +} + static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, int inum, int asnum, struct usb_host_endpoint *ep, unsigned char *buffer, int size) @@ -54,6 +75,9 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, * be the first thing immediately following the endpoint descriptor. */ desc = (struct usb_ss_ep_comp_descriptor *) buffer; + buffer += desc->bLength; + size -= desc->bLength; + if (desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP || size < USB_DT_SS_EP_COMP_SIZE) { dev_warn(ddev, "No SuperSpeed endpoint companion for config %d " @@ -112,6 +136,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 16; } else if (usb_endpoint_xfer_isoc(&ep->desc) && + !USB_SS_SSP_ISOC_COMP(desc->bmAttributes) && USB_SS_MULT(desc->bmAttributes) > 3) { dev_warn(ddev, "Isoc endpoint has Mult of %d in " "config %d interface %d altsetting %d ep %d: " @@ -121,6 +146,12 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, ep->ss_ep_comp.bmAttributes = 2; } + /* Parse a possible SuperSpeedPlus isoc ep companion descriptor */ + if (usb_endpoint_xfer_isoc(&ep->desc) && + USB_SS_SSP_ISOC_COMP(desc->bmAttributes)) + usb_parse_ssp_isoc_endpoint_companion(ddev, cfgno, inum, asnum, + ep, buffer, size); + if (usb_endpoint_xfer_isoc(&ep->desc)) max_tx = (desc->bMaxBurst + 1) * (USB_SS_MULT(desc->bmAttributes)) * diff --git a/include/linux/usb.h b/include/linux/usb.h index dc0ea0de8a81..8fc881af8735 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -50,6 +50,7 @@ struct ep_device; * struct usb_host_endpoint - host-side endpoint descriptor and queue * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder * @ss_ep_comp: SuperSpeed companion descriptor for this endpoint + * @ssp_isoc_ep_comp: SuperSpeedPlus isoc companion descriptor for this endpoint * @urb_list: urbs queued to this endpoint; maintained by usbcore * @hcpriv: for use by HCD; typically holds hardware dma queue head (QH) * with one or more transfer descriptors (TDs) per urb @@ -65,6 +66,7 @@ struct ep_device; struct usb_host_endpoint { struct usb_endpoint_descriptor desc; struct usb_ss_ep_comp_descriptor ss_ep_comp; + struct usb_ssp_isoc_ep_comp_descriptor ssp_isoc_ep_comp; struct list_head urb_list; void *hcpriv; struct ep_device *ep_dev; /* For sysfs info */ -- cgit From faee822c5a7ab99de25cd34fcde3f8d37b6b9923 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:14 +0200 Subject: usb: Add USB 3.1 Precision time measurement capability descriptor support USB 3.1 devices that support precision time measurement have an additional PTM cabaility descriptor as part of the full BOS descriptor Look for this descriptor while parsing the BOS descriptor, and store it in struct usb_hub_bos if it exists. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 3 +++ include/linux/usb.h | 1 + include/uapi/linux/usb/ch9.h | 10 ++++++++++ 3 files changed, 14 insertions(+) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 58d089802ab3..5eb1a87228b4 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -894,6 +894,9 @@ int usb_get_bos_descriptor(struct usb_device *dev) dev->bos->ss_id = (struct usb_ss_container_id_descriptor *)buffer; break; + case USB_PTM_CAP_TYPE: + dev->bos->ptm_cap = + (struct usb_ptm_cap_descriptor *)buffer; default: break; } diff --git a/include/linux/usb.h b/include/linux/usb.h index 8fc881af8735..6a9a0c28415d 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -332,6 +332,7 @@ struct usb_host_bos { struct usb_ss_cap_descriptor *ss_cap; struct usb_ssp_cap_descriptor *ssp_cap; struct usb_ss_container_id_descriptor *ss_id; + struct usb_ptm_cap_descriptor *ptm_cap; }; int __usb_get_extra_descriptor(char *buffer, unsigned size, diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index a65f1f328de1..252ac16635dc 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -912,6 +912,16 @@ struct usb_ssp_cap_descriptor { #define USB_SSP_SUBLINK_SPEED_LSM (0xff << 16) /* Lanespeed mantissa */ } __attribute__((packed)); +/* + * Precision time measurement capability descriptor: advertised by devices and + * hubs that support PTM + */ +#define USB_PTM_CAP_TYPE 0xb +struct usb_ptm_cap_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDevCapabilityType; +} __attribute__((packed)); /*-------------------------------------------------------------------------*/ -- cgit From def4e6f7b419c4092c82222d0896d6c409692326 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:15 +0200 Subject: xhci: refactor and cleanup endpoint initialization. xhci_endpoint_init() and helper functions were a bit messy. Adding the higher bandwidth SuperSpeedPlus Isoc support on top of it would make it even harder to read. No functional changes. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 161 ++++++++++++++++++-------------------------- drivers/usb/host/xhci.h | 4 +- 2 files changed, 69 insertions(+), 96 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 42f2bec759aa..4e3abdd0ec36 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1326,7 +1326,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, default: BUG(); } - return EP_INTERVAL(interval); + return interval; } /* The "Mult" field in the endpoint context is only set for SuperSpeed isoc eps. @@ -1343,33 +1343,36 @@ static u32 xhci_get_endpoint_mult(struct usb_device *udev, return ep->ss_ep_comp.bmAttributes; } +static u32 xhci_get_endpoint_max_burst(struct usb_device *udev, + struct usb_host_endpoint *ep) +{ + /* Super speed and Plus have max burst in ep companion desc */ + if (udev->speed >= USB_SPEED_SUPER) + return ep->ss_ep_comp.bMaxBurst; + + if (udev->speed == USB_SPEED_HIGH && + (usb_endpoint_xfer_isoc(&ep->desc) || + usb_endpoint_xfer_int(&ep->desc))) + return (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; + + return 0; +} + static u32 xhci_get_endpoint_type(struct usb_host_endpoint *ep) { int in; - u32 type; in = usb_endpoint_dir_in(&ep->desc); - if (usb_endpoint_xfer_control(&ep->desc)) { - type = EP_TYPE(CTRL_EP); - } else if (usb_endpoint_xfer_bulk(&ep->desc)) { - if (in) - type = EP_TYPE(BULK_IN_EP); - else - type = EP_TYPE(BULK_OUT_EP); - } else if (usb_endpoint_xfer_isoc(&ep->desc)) { - if (in) - type = EP_TYPE(ISOC_IN_EP); - else - type = EP_TYPE(ISOC_OUT_EP); - } else if (usb_endpoint_xfer_int(&ep->desc)) { - if (in) - type = EP_TYPE(INT_IN_EP); - else - type = EP_TYPE(INT_OUT_EP); - } else { - type = 0; - } - return type; + + if (usb_endpoint_xfer_control(&ep->desc)) + return CTRL_EP; + if (usb_endpoint_xfer_bulk(&ep->desc)) + return in ? BULK_IN_EP : BULK_OUT_EP; + if (usb_endpoint_xfer_isoc(&ep->desc)) + return in ? ISOC_IN_EP : ISOC_OUT_EP; + if (usb_endpoint_xfer_int(&ep->desc)) + return in ? INT_IN_EP : INT_OUT_EP; + return 0; } /* Return the maximum endpoint service interval time (ESIT) payload. @@ -1409,10 +1412,14 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_ep_ctx *ep_ctx; struct xhci_ring *ep_ring; unsigned int max_packet; - unsigned int max_burst; - enum xhci_ring_type type; + enum xhci_ring_type ring_type; u32 max_esit_payload; u32 endpoint_type; + unsigned int max_burst; + unsigned int interval; + unsigned int mult; + unsigned int avg_trb_len; + unsigned int err_count = 0; ep_index = xhci_get_endpoint_index(&ep->desc); ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); @@ -1420,12 +1427,11 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, endpoint_type = xhci_get_endpoint_type(ep); if (!endpoint_type) return -EINVAL; - ep_ctx->ep_info2 = cpu_to_le32(endpoint_type); - type = usb_endpoint_type(&ep->desc); + ring_type = usb_endpoint_type(&ep->desc); /* Set up the endpoint ring */ virt_dev->eps[ep_index].new_ring = - xhci_ring_alloc(xhci, 2, 1, type, mem_flags); + xhci_ring_alloc(xhci, 2, 1, ring_type, mem_flags); if (!virt_dev->eps[ep_index].new_ring) { /* Attempt to use the ring cache */ if (virt_dev->num_rings_cached == 0) @@ -1435,81 +1441,48 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, virt_dev->ring_cache[virt_dev->num_rings_cached]; virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL; xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring, - 1, type); + 1, ring_type); } virt_dev->eps[ep_index].skip = false; ep_ring = virt_dev->eps[ep_index].new_ring; - ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma | ep_ring->cycle_state); - ep_ctx->ep_info = cpu_to_le32(xhci_get_endpoint_interval(udev, ep) - | EP_MULT(xhci_get_endpoint_mult(udev, ep))); + /* + * Get values to fill the endpoint context, mostly from ep descriptor. + * The average TRB buffer lengt for bulk endpoints is unclear as we + * have no clue on scatter gather list entry size. For Isoc and Int, + * set it to max available. See xHCI 1.1 spec 4.14.1.1 for details. + */ + max_esit_payload = xhci_get_max_esit_payload(udev, ep); + interval = xhci_get_endpoint_interval(udev, ep); + mult = xhci_get_endpoint_mult(udev, ep); + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_burst = xhci_get_endpoint_max_burst(udev, ep); + avg_trb_len = max_esit_payload; /* FIXME dig Mult and streams info out of ep companion desc */ - /* Allow 3 retries for everything but isoc; - * CErr shall be set to 0 for Isoch endpoints. - */ + /* Allow 3 retries for everything but isoc, set CErr = 3 */ if (!usb_endpoint_xfer_isoc(&ep->desc)) - ep_ctx->ep_info2 |= cpu_to_le32(ERROR_COUNT(3)); - else - ep_ctx->ep_info2 |= cpu_to_le32(ERROR_COUNT(0)); - - /* Set the max packet size and max burst */ - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); - max_burst = 0; - switch (udev->speed) { - case USB_SPEED_SUPER_PLUS: - case USB_SPEED_SUPER: - /* dig out max burst from ep companion desc */ - max_burst = ep->ss_ep_comp.bMaxBurst; - break; - case USB_SPEED_HIGH: - /* Some devices get this wrong */ - if (usb_endpoint_xfer_bulk(&ep->desc)) - max_packet = 512; - /* bits 11:12 specify the number of additional transaction - * opportunities per microframe (USB 2.0, section 9.6.6) - */ - if (usb_endpoint_xfer_isoc(&ep->desc) || - usb_endpoint_xfer_int(&ep->desc)) { - max_burst = (usb_endpoint_maxp(&ep->desc) - & 0x1800) >> 11; - } - break; - case USB_SPEED_FULL: - case USB_SPEED_LOW: - break; - default: - BUG(); - } - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet) | - MAX_BURST(max_burst)); - max_esit_payload = xhci_get_max_esit_payload(udev, ep); - ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload)); - - /* - * XXX no idea how to calculate the average TRB buffer length for bulk - * endpoints, as the driver gives us no clue how big each scatter gather - * list entry (or buffer) is going to be. - * - * For isochronous and interrupt endpoints, we set it to the max - * available, until we have new API in the USB core to allow drivers to - * declare how much bandwidth they actually need. - * - * Normally, it would be calculated by taking the total of the buffer - * lengths in the TD and then dividing by the number of TRBs in a TD, - * including link TRBs, No-op TRBs, and Event data TRBs. Since we don't - * use Event Data TRBs, and we don't chain in a link TRB on short - * transfers, we're basically dividing by 1. - * - * xHCI 1.0 and 1.1 specification indicates that the Average TRB Length - * should be set to 8 for control endpoints. - */ + err_count = 3; + /* Some devices get this wrong */ + if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH) + max_packet = 512; + /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */ if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) - ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(8)); - else - ep_ctx->tx_info |= - cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload)); + avg_trb_len = 8; + + /* Fill the endpoint context */ + ep_ctx->ep_info = cpu_to_le32(EP_INTERVAL(interval) | + EP_MULT(mult)); + ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) | + MAX_PACKET(max_packet) | + MAX_BURST(max_burst) | + ERROR_COUNT(err_count)); + ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma | + ep_ring->cycle_state); + + ep_ctx->tx_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_LO(max_esit_payload) | + EP_AVG_TRB_LENGTH(avg_trb_len)); /* FIXME Debug endpoint context */ return 0; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e1bee3fe1a39..a0279cf4245f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -749,8 +749,8 @@ struct xhci_ep_ctx { #define GET_MAX_PACKET(p) ((p) & 0x7ff) /* tx_info bitmasks */ -#define AVG_TRB_LENGTH_FOR_EP(p) ((p) & 0xffff) -#define MAX_ESIT_PAYLOAD_FOR_EP(p) (((p) & 0xffff) << 16) +#define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) +#define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) #define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff) /* deq bitmasks */ -- cgit From 8ef8a9f5c148ae1dbeae926e5b6129e396faded2 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:16 +0200 Subject: xhci: Add SuperSpeedPlus high bandwidth isoc support to xhci endpoints SuperSpeedPlus doubled the number of transactions per service interval the isoc endpoints supports. To support this, xhci 1.1 added Large ESIT Capability (LEC), which takes into use new bits in the endpoint context to fit the parameters. If xhci supports LEC, and the device has a SuperSpeedPlus Isoc companion descriptor then take into use the high bits of max esit payload, and skip calculating the Mult field as it wouldn't fit. LEC capable host will calculate the Mult based on other paramenters. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mem.c | 13 +++++++++++-- drivers/usb/host/xhci.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 4e3abdd0ec36..80c1de239e9a 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1390,7 +1390,12 @@ static u32 xhci_get_max_esit_payload(struct usb_device *udev, usb_endpoint_xfer_bulk(&ep->desc)) return 0; - if (udev->speed >= USB_SPEED_SUPER) + /* SuperSpeedPlus Isoc ep sending over 48k per esit */ + if ((udev->speed >= USB_SPEED_SUPER_PLUS) && + USB_SS_SSP_ISOC_COMP(ep->ss_ep_comp.bmAttributes)) + return le32_to_cpu(ep->ssp_isoc_ep_comp.dwBytesPerInterval); + /* SuperSpeed or SuperSpeedPlus Isoc ep with less than 48k per esit */ + else if (udev->speed >= USB_SPEED_SUPER) return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); @@ -1470,9 +1475,13 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */ if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100) avg_trb_len = 8; + /* xhci 1.1 with LEC support doesn't use mult field, use RsvdZ */ + if ((xhci->hci_version > 0x100) && HCC2_LEC(xhci->hcc_params2)) + mult = 0; /* Fill the endpoint context */ - ep_ctx->ep_info = cpu_to_le32(EP_INTERVAL(interval) | + ep_ctx->ep_info = cpu_to_le32(EP_MAX_ESIT_PAYLOAD_HI(max_esit_payload) | + EP_INTERVAL(interval) | EP_MULT(mult)); ep_ctx->ep_info2 = cpu_to_le32(EP_TYPE(endpoint_type) | MAX_PACKET(max_packet) | diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a0279cf4245f..40a7efd86b9c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -751,6 +751,7 @@ struct xhci_ep_ctx { /* tx_info bitmasks */ #define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) #define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) +#define EP_MAX_ESIT_PAYLOAD_HI(p) ((((p) >> 16) & 0xff) << 24) #define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff) /* deq bitmasks */ -- cgit From 09c352ed671c156b7ce30c81a4f4424641859918 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:17 +0200 Subject: xhci: cleanup isoc tranfers queuing code Clean up xhci_queue_isoc_tx() and helpers to prepare them for USB 3.1 and xhci 1.1 isoc TRB changes. Only functional change is adding xhci version 1.1 to the BEI flag check toghether with xhci version 1.0. Both versions behave the same. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 125 ++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 72 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6773e508d9bb..3b671122106d 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3558,12 +3558,11 @@ static int count_isoc_trbs_needed(struct xhci_hcd *xhci, * zero. Only xHCI 1.0 host controllers support this field. */ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, - struct usb_device *udev, struct urb *urb, unsigned int total_packet_count) { unsigned int max_burst; - if (xhci->hci_version < 0x100 || udev->speed < USB_SPEED_SUPER) + if (xhci->hci_version < 0x100 || urb->dev->speed < USB_SPEED_SUPER) return 0; max_burst = urb->ep->ss_ep_comp.bMaxBurst; @@ -3579,7 +3578,6 @@ static unsigned int xhci_get_burst_count(struct xhci_hcd *xhci, * contain 1 to (bMaxBurst + 1) packets. */ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, - struct usb_device *udev, struct urb *urb, unsigned int total_packet_count) { unsigned int max_burst; @@ -3588,9 +3586,7 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, if (xhci->hci_version < 0x100) return 0; - switch (udev->speed) { - case USB_SPEED_SUPER_PLUS: - case USB_SPEED_SUPER: + if (urb->dev->speed >= USB_SPEED_SUPER) { /* bMaxBurst is zero based: 0 means 1 packet per burst */ max_burst = urb->ep->ss_ep_comp.bMaxBurst; residue = total_packet_count % (max_burst + 1); @@ -3600,11 +3596,10 @@ static unsigned int xhci_get_last_burst_packet_count(struct xhci_hcd *xhci, if (residue == 0) return max_burst; return residue - 1; - default: - if (total_packet_count == 0) - return 0; - return total_packet_count - 1; } + if (total_packet_count == 0) + return 0; + return total_packet_count - 1; } /* @@ -3715,6 +3710,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int i, j; bool more_trbs_coming; struct xhci_virt_ep *xep; + int frame_id; xep = &xhci->devs[slot_id]->eps[ep_index]; ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; @@ -3724,33 +3720,31 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, xhci_dbg(xhci, "Isoc URB with zero packets?\n"); return -EINVAL; } - start_addr = (u64) urb->transfer_dma; start_trb = &ep_ring->enqueue->generic; start_cycle = ep_ring->cycle_state; urb_priv = urb->hcpriv; - /* Queue the first TRB, even if it's zero-length */ + /* Queue the TRBs for each TD, even if they are zero-length */ for (i = 0; i < num_tds; i++) { - unsigned int total_packet_count; - unsigned int burst_count; - unsigned int residue; + unsigned int total_pkt_count, max_pkt; + unsigned int burst_count, last_burst_pkt_count; + u32 sia_frame_id; first_trb = true; running_total = 0; addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - total_packet_count = DIV_ROUND_UP(td_len, - GET_MAX_PACKET( - usb_endpoint_maxp(&urb->ep->desc))); + max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); + total_pkt_count = DIV_ROUND_UP(td_len, max_pkt); + /* A zero-length transfer still involves at least one packet. */ - if (total_packet_count == 0) - total_packet_count++; - burst_count = xhci_get_burst_count(xhci, urb->dev, urb, - total_packet_count); - residue = xhci_get_last_burst_packet_count(xhci, - urb->dev, urb, total_packet_count); + if (total_pkt_count == 0) + total_pkt_count++; + burst_count = xhci_get_burst_count(xhci, urb, total_pkt_count); + 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); @@ -3761,68 +3755,55 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return ret; goto cleanup; } - td = urb_priv->td[i]; + + /* use SIA as default, if frame id is used overwrite it */ + sia_frame_id = TRB_SIA; + if (!(urb->transfer_flags & URB_ISO_ASAP) && + HCC_CFC(xhci->hcc_params)) { + frame_id = xhci_get_isoc_frame_id(xhci, urb, i); + if (frame_id >= 0) + sia_frame_id = TRB_FRAME_ID(frame_id); + } + /* + * Set isoc specific data for the first TRB in a TD. + * Prevent HW from getting the TRBs by keeping the cycle state + * inverted in the first TDs isoc TRB. + */ + field = TRB_TBC(burst_count) | + TRB_TYPE(TRB_ISOC) | + TRB_TLBPC(last_burst_pkt_count) | + sia_frame_id | + (i ? ep_ring->cycle_state : !start_cycle); + + /* fill the rest of the TRB fields, and remaining normal TRBs */ for (j = 0; j < trbs_per_td; j++) { - int frame_id = 0; u32 remainder = 0; - field = 0; - - if (first_trb) { - field = TRB_TBC(burst_count) | - TRB_TLBPC(residue); - /* Queue the isoc TRB */ - field |= TRB_TYPE(TRB_ISOC); - - /* Calculate Frame ID and SIA fields */ - if (!(urb->transfer_flags & URB_ISO_ASAP) && - HCC_CFC(xhci->hcc_params)) { - frame_id = xhci_get_isoc_frame_id(xhci, - urb, - i); - if (frame_id >= 0) - field |= TRB_FRAME_ID(frame_id); - else - field |= TRB_SIA; - } else - field |= TRB_SIA; - - if (i == 0) { - if (start_cycle == 0) - field |= 0x1; - } else - field |= ep_ring->cycle_state; - first_trb = false; - } else { - /* Queue other normal TRBs */ - field |= TRB_TYPE(TRB_NORMAL); - field |= ep_ring->cycle_state; - } + + /* only first TRB is isoc, overwrite otherwise */ + if (!first_trb) + field = TRB_TYPE(TRB_NORMAL) | + ep_ring->cycle_state; + first_trb = false; /* Only set interrupt on short packet for IN EPs */ if (usb_urb_dir_in(urb)) field |= TRB_ISP; - /* Chain all the TRBs together; clear the chain bit in - * the last TRB to indicate it's the last TRB in the - * chain. - */ + /* Set the chain bit for all except the last TRB */ if (j < trbs_per_td - 1) { - field |= TRB_CHAIN; more_trbs_coming = true; + field |= TRB_CHAIN; } else { + more_trbs_coming = false; td->last_trb = ep_ring->enqueue; field |= TRB_IOC; - if (xhci->hci_version == 0x100 && - !(xhci->quirks & - XHCI_AVOID_BEI)) { - /* Set BEI bit except for the last td */ - if (i < num_tds - 1) - field |= TRB_BEI; - } - more_trbs_coming = false; + /* set BEI, except for the last TD */ + if (xhci->hci_version >= 0x100 && + !(xhci->quirks & XHCI_AVOID_BEI) && + i < num_tds - 1) + field |= TRB_BEI; } - /* Calculate TRB length */ trb_buff_len = TRB_MAX_BUFF_SIZE - (addr & ((1 << TRB_MAX_BUFF_SHIFT) - 1)); -- cgit From 2f6d3b653777e68bbccfdcff3de2ea8165934531 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 12 Feb 2016 16:40:18 +0200 Subject: xhci: Support extended burst isoc TRB structure used by xhci 1.1 for USB 3.1 The transfer burst count (TBC) field in the Isoc TRB does not fit the new larger burst count available for USB 3.1 SSP Isoc tranfers. xhci 1.1 solved this by reusing the TD size field for transfer burst count. The Mult field was outgrown as well. xhci 1.1 controllers can calculate Mult itself and is not set if the new layout is used. xhci 1.1 controllers that support the new Isoc TRB format expose a Extended TBC Capability (ETC). To take the new format into use the xhci host controller driver needs to set a Extended TBC Enable (ETE) bit. Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 16 ++++++++++++---- drivers/usb/host/xhci.h | 9 ++++++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3b671122106d..7cf66212ceae 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3770,12 +3770,15 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, * Prevent HW from getting the TRBs by keeping the cycle state * inverted in the first TDs isoc TRB. */ - field = TRB_TBC(burst_count) | - TRB_TYPE(TRB_ISOC) | + field = TRB_TYPE(TRB_ISOC) | TRB_TLBPC(last_burst_pkt_count) | sia_frame_id | (i ? ep_ring->cycle_state : !start_cycle); + /* xhci 1.1 with ETE uses TD_Size field for TBC, old is Rsvdz */ + if (!xep->use_extended_tbc) + field |= TRB_TBC(burst_count); + /* fill the rest of the TRB fields, and remaining normal TRBs */ for (j = 0; j < trbs_per_td; j++) { u32 remainder = 0; @@ -3784,7 +3787,6 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (!first_trb) field = TRB_TYPE(TRB_NORMAL) | ep_ring->cycle_state; - first_trb = false; /* Only set interrupt on short packet for IN EPs */ if (usb_urb_dir_in(urb)) @@ -3816,9 +3818,15 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb, trbs_per_td - j - 1); length_field = TRB_LEN(trb_buff_len) | - TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0); + /* xhci 1.1 with ETE uses TD Size field for TBC */ + if (first_trb && xep->use_extended_tbc) + length_field |= TRB_TD_SIZE_TBC(burst_count); + else + length_field |= TRB_TD_SIZE(remainder); + first_trb = false; + queue_trb(xhci, ep_ring, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 40a7efd86b9c..e293e0974f48 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -232,7 +232,9 @@ struct xhci_op_regs { * disabled, or powered-off state. */ #define CMD_PM_INDEX (1 << 11) -/* bits 12:31 are reserved (and should be preserved on writes). */ +/* bit 14 Extended TBC Enable, changes Isoc TRB fields to support larger TBC */ +#define CMD_ETE (1 << 14) +/* bits 15:31 are reserved (and should be preserved on writes). */ /* IMAN - Interrupt Management Register */ #define IMAN_IE (1 << 1) @@ -943,6 +945,8 @@ struct xhci_virt_ep { struct list_head bw_endpoint_list; /* Isoch Frame ID checking storage */ int next_frame_id; + /* Use new Isoch TRB layout needed for extended TBC support */ + bool use_extended_tbc; }; enum xhci_overhead_type { @@ -1184,9 +1188,12 @@ enum xhci_setup_dev { #define TRB_LEN(p) ((p) & 0x1ffff) /* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */ #define TRB_TD_SIZE(p) (min((p), (u32)31) << 17) +/* xhci 1.1 uses the TD_SIZE field for TBC if Extended TBC is enabled (ETE) */ +#define TRB_TD_SIZE_TBC(p) (min((p), (u32)31) << 17) /* Interrupter Target - which MSI-X vector to target the completion event at */ #define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) #define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) +/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */ #define TRB_TBC(p) (((p) & 0x3) << 7) #define TRB_TLBPC(p) (((p) & 0xf) << 16) -- cgit From ca1c3e6f81d4aa2d0665d004521beea7fd847316 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 8 Feb 2016 18:30:34 +0100 Subject: cdc-acm: fix mail address This updates my email. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index cc2f753cb357..d894ee25a9d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11246,7 +11246,7 @@ F: include/linux/mtd/ubi.h F: include/uapi/mtd/ubi-user.h USB ACM DRIVER -M: Oliver Neukum +M: Oliver Neukum L: linux-usb@vger.kernel.org S: Maintained F: Documentation/usb/acm.txt -- cgit From a81cf9799ad7299b03a4dff020d9685f9ac5f3e0 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 10 Feb 2016 10:39:49 +0100 Subject: cdc-acm: implement put_char() and flush_chars() This should cut down latencies and waste if the tty layer writes single bytes. Signed-off-by: Oliver Neukum >oneukum@suse.com> Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/class/cdc-acm.h | 1 + 2 files changed, 68 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fa4e23930614..1d2c99af2532 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -713,9 +713,20 @@ static int acm_tty_write(struct tty_struct *tty, } if (acm->susp_count) { + if (acm->putbuffer) { + /* now to preserve order */ + usb_anchor_urb(acm->putbuffer->urb, &acm->delayed); + acm->putbuffer = NULL; + } usb_anchor_urb(wb->urb, &acm->delayed); spin_unlock_irqrestore(&acm->write_lock, flags); return count; + } else { + if (acm->putbuffer) { + /* at this point there is no good way to handle errors */ + acm_start_wb(acm, acm->putbuffer); + acm->putbuffer = NULL; + } } stat = acm_start_wb(acm, wb); @@ -726,6 +737,60 @@ static int acm_tty_write(struct tty_struct *tty, return count; } +static void acm_tty_flush_chars(struct tty_struct *tty) +{ + struct acm *acm = tty->driver_data; + struct acm_wb *cur = acm->putbuffer; + int err; + unsigned long flags; + + acm->putbuffer = NULL; + err = usb_autopm_get_interface_async(acm->control); + spin_lock_irqsave(&acm->write_lock, flags); + if (err < 0) { + cur->use = 0; + goto out; + } + + if (acm->susp_count) + usb_anchor_urb(cur->urb, &acm->delayed); + else + acm_start_wb(acm, cur); +out: + spin_unlock_irqrestore(&acm->write_lock, flags); + return; +} + +static int acm_tty_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct acm *acm = tty->driver_data; + struct acm_wb *cur; + int wbn; + unsigned long flags; + +overflow: + cur = acm->putbuffer; + if (!cur) { + spin_lock_irqsave(&acm->write_lock, flags); + wbn = acm_wb_alloc(acm); + if (wbn >= 0) { + cur = &acm->wb[wbn]; + acm->putbuffer = cur; + } + spin_unlock_irqrestore(&acm->write_lock, flags); + if (!cur) + return 0; + } + + if (cur->len == acm->writesize) { + acm_tty_flush_chars(tty); + goto overflow; + } + + cur->buf[cur->len++] = ch; + return 1; +} + static int acm_tty_write_room(struct tty_struct *tty) { struct acm *acm = tty->driver_data; @@ -1905,6 +1970,8 @@ static const struct tty_operations acm_ops = { .cleanup = acm_tty_cleanup, .hangup = acm_tty_hangup, .write = acm_tty_write, + .put_char = acm_tty_put_char, + .flush_chars = acm_tty_flush_chars, .write_room = acm_tty_write_room, .ioctl = acm_tty_ioctl, .throttle = acm_tty_throttle, diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index ccfaba9ab4e4..05ce308d5d2a 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -94,6 +94,7 @@ struct acm { unsigned long read_urbs_free; struct urb *read_urbs[ACM_NR]; struct acm_rb read_buffers[ACM_NR]; + struct acm_wb *putbuffer; /* for acm_tty_put_char() */ int rx_buflimit; int rx_endpoint; spinlock_t read_lock; -- cgit From c3853d5a70c956a4be6f6009cf46c11a03b24d4e Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 13 Feb 2016 23:10:49 +0100 Subject: usb: host: ohci-pxa27x: propagate the irq error code In several drivers in the pxa architecture, it was found that the platform_get_irq() was not propagated. This breaks the the device-tree probe deferral path, if -EPROBE_DEFER is returned. Unfortunately, the error return in this case is transformed into -ENXIO, breaking the deferral mechanism. Even if in this specific case the driver was not broken, because the interrupt controller is always probed before drivers, propagate the proper return code. Signed-off-by: Robert Jarzmik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pxa27x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e8c006e7a960..a667cf2d5788 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -435,7 +435,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device irq = platform_get_irq(pdev, 0); if (irq < 0) { pr_err("no resource of IORESOURCE_IRQ"); - return -ENXIO; + return irq; } usb_clk = devm_clk_get(&pdev->dev, NULL); -- cgit From ca23d3b747f8ed294fe9e809dca0ed518fffc8cc Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:36 +0100 Subject: usb: add HAS_IOMEM dependency to USB_ISP116X_HCD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/usb/host/isp116x-hcd.c: In function ‘isp116x_remove’: drivers/usb/host/isp116x-hcd.c:1552:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(isp116x->data_reg); ^ drivers/usb/host/isp116x-hcd.c: In function ‘isp116x_probe’: drivers/usb/host/isp116x-hcd.c:1604:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] addr_reg = ioremap(addr->start, resource_size(addr)); ^ drivers/usb/host/isp116x-hcd.c:1604:11: warning: assignment makes pointer from integer without a cast [enabled by default] addr_reg = ioremap(addr->start, resource_size(addr)); ^ drivers/usb/host/isp116x-hcd.c:1613:11: warning: assignment makes pointer from integer without a cast [enabled by default] data_reg = ioremap(data->start, resource_size(data)); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1f117c360ebb..64d78b1560ee 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -340,6 +340,7 @@ config USB_OXU210HP_HCD config USB_ISP116X_HCD tristate "ISP116X HCD support" + depends on HAS_IOMEM ---help--- The ISP1160 and ISP1161 chips are USB host controllers. Enable this option if your board has this chip. If unsure, say N. -- cgit From 7562b75b214ce86215fc028183edd50df130042f Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:37 +0100 Subject: usb: add HAS_IOMEM dependency to USB_NET2272 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/usb/gadget/udc/net2272.c: In function ‘net2272_remove’: drivers/usb/gadget/udc/net2272.c:2232:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(dev->base_addr); ^ drivers/usb/gadget/udc/net2272.c: In function ‘net2272_plat_probe’: drivers/usb/gadget/udc/net2272.c:2650:2: error: implicit declaration of function ‘ioremap_nocache’ [-Werror=implicit-function-declaration] dev->base_addr = ioremap_nocache(base, len); ^ drivers/usb/gadget/udc/net2272.c:2650:17: warning: assignment makes pointer from integer without a cast [enabled by default] dev->base_addr = ioremap_nocache(base, len); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 753c29bd11ad..ca19f6f3197a 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -287,6 +287,7 @@ config USB_FSL_QE dynamically linked module called "fsl_qe_udc". config USB_NET2272 + depends on HAS_IOMEM tristate "PLX NET2272" help PLX NET2272 is a USB peripheral controller which supports -- cgit From be6708e6f2d13b26bfdc416b5bf31c942ccff72c Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:38 +0100 Subject: usb: Add HAS_IOMEM dependency to USB_M66592 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/usb/gadget/udc/m66592-udc.c: In function ‘m66592_remove’: drivers/usb/gadget/udc/m66592-udc.c:1538:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(m66592->reg); ^ drivers/usb/gadget/udc/m66592-udc.c: In function ‘m66592_probe’: drivers/usb/gadget/udc/m66592-udc.c:1577:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] reg = ioremap(res->start, resource_size(res)); ^ drivers/usb/gadget/udc/m66592-udc.c:1577:6: warning: assignment makes pointer from integer without a cast [enabled by default] reg = ioremap(res->start, resource_size(res)); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index ca19f6f3197a..e06efa3c3033 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -244,6 +244,7 @@ config USB_MV_U3D config USB_M66592 tristate "Renesas M66592 USB Peripheral Controller" + depends on HAS_IOMEM help M66592 is a discrete USB peripheral controller chip that supports both full and high speed USB 2.0 data transfers. -- cgit From 828638e91915e347f0721ae2a2cb137c910dc592 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:39 +0100 Subject: usb: add HAS_IOMEM dependency to USB_XHCI_MVEBU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/usb/host/xhci-mvebu.c: In function ‘xhci_mvebu_mbus_init_quirk’: drivers/usb/host/xhci-mvebu.c:58:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] base = ioremap(res->start, resource_size(res)); ^ drivers/usb/host/xhci-mvebu.c:58:7: warning: assignment makes pointer from integer without a cast [enabled by default] base = ioremap(res->start, resource_size(res)); ^ drivers/usb/host/xhci-mvebu.c:69:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(base); ^ Signed-off-by: Vegard Nossum Acked-by: Gregory CLEMENT Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 64d78b1560ee..bf68bd8b60de 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -53,6 +53,7 @@ config USB_XHCI_MTK config USB_XHCI_MVEBU tristate "xHCI support for Marvell Armada 375/38x" select USB_XHCI_PLATFORM + depends on HAS_IOMEM depends on ARCH_MVEBU || COMPILE_TEST ---help--- Say 'Y' to enable the support for the xHCI host controller -- cgit From e37a6c920ac1c22206350492b7d229f05c0849e4 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:40 +0100 Subject: usb: add HAS_IOMEM dependency to USB_R8A66597_HCD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/usb/host/r8a66597-hcd.o drivers/usb/host/r8a66597-hcd.c: In function ‘r8a66597_remove’: drivers/usb/host/r8a66597-hcd.c:2401:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(r8a66597->reg); ^ drivers/usb/host/r8a66597-hcd.c: In function ‘r8a66597_probe’: drivers/usb/host/r8a66597-hcd.c:2447:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] reg = ioremap(res->start, resource_size(res)); ^ drivers/usb/host/r8a66597-hcd.c:2447:6: warning: assignment makes pointer from integer without a cast [enabled by default] reg = ioremap(res->start, resource_size(res)); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index bf68bd8b60de..af20d936d3c7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -701,6 +701,7 @@ config USB_SL811_CS config USB_R8A66597_HCD tristate "R8A66597 HCD support" + depends on HAS_IOMEM help The R8A66597 is a USB 2.0 host and peripheral controller. -- cgit From 49f77e3dbb1b91f754da93764ba020ea5eddb6ed Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:41 +0100 Subject: usb: add HAS_IOMEM dependency to USB_MUSB_TUSB6010 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/usb/musb/tusb6010.o drivers/usb/musb/tusb6010.c: In function ‘tusb_musb_init’: drivers/usb/musb/tusb6010.c:1133:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] sync = ioremap(mem->start, resource_size(mem)); ^ drivers/usb/musb/tusb6010.c:1133:7: warning: assignment makes pointer from integer without a cast [enabled by default] sync = ioremap(mem->start, resource_size(mem)); ^ drivers/usb/musb/tusb6010.c:1162:4: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(sync); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 45c83baf675d..0401573f79aa 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -85,6 +85,7 @@ config USB_MUSB_DA8XX config USB_MUSB_TUSB6010 tristate "TUSB6010" + depends on HAS_IOMEM depends on ARCH_OMAP2PLUS || COMPILE_TEST depends on NOP_USB_XCEIV = USB_MUSB_HDRC # both built-in or both modules -- cgit From 149737a7870170a48a17b5a4a7feba14f43d4a06 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:42 +0100 Subject: usb: add HAS_IOMEM dependency to USB_C67X00_HCD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/usb/c67x00/c67x00-drv.o drivers/usb/c67x00/c67x00-drv.c: In function ‘c67x00_drv_probe’: drivers/usb/c67x00/c67x00-drv.c:148:2: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] c67x00->hpi.base = ioremap(res->start, resource_size(res)); ^ drivers/usb/c67x00/c67x00-drv.c:148:19: warning: assignment makes pointer from integer without a cast [enabled by default] c67x00->hpi.base = ioremap(res->start, resource_size(res)); ^ drivers/usb/c67x00/c67x00-drv.c:185:2: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(c67x00->hpi.base); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index af20d936d3c7..e781fb114aea 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -5,6 +5,7 @@ comment "USB Host Controller Drivers" config USB_C67X00_HCD tristate "Cypress C67x00 HCD support" + depends on HAS_IOMEM help The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role host/peripheral/OTG USB controllers. -- cgit From cfa33eaeeeb89ec90ea7062b0e4035552b8dbb56 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:43 +0100 Subject: usb: add HAS_IOMEM dependency to USB_SL811_HCD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC drivers/usb/host/xhci-mtk.o drivers/usb/host/xhci-mtk.c:135:12: warning: ‘xhci_mtk_host_disable’ defined but not used [-Wunused-function] static int xhci_mtk_host_disable(struct xhci_hcd_mtk *mtk) ^ drivers/usb/host/xhci-mtk.c:313:13: warning: ‘usb_wakeup_enable’ defined but not used [-Wunused-function] static void usb_wakeup_enable(struct xhci_hcd_mtk *mtk) ^ drivers/usb/host/xhci-mtk.c:321:13: warning: ‘usb_wakeup_disable’ defined but not used [-Wunused-function] static void usb_wakeup_disable(struct xhci_hcd_mtk *mtk) ^ CC drivers/usb/host/sl811-hcd.o drivers/usb/host/sl811-hcd.c: In function ‘sl811h_remove’: drivers/usb/host/sl811-hcd.c:1607:3: error: implicit declaration of function ‘iounmap’ [-Werror=implicit-function-declaration] iounmap(sl811->data_reg); ^ drivers/usb/host/sl811-hcd.c: In function ‘sl811h_probe’: drivers/usb/host/sl811-hcd.c:1669:3: error: implicit declaration of function ‘ioremap’ [-Werror=implicit-function-declaration] addr_reg = ioremap(addr->start, 1); ^ drivers/usb/host/sl811-hcd.c:1669:12: warning: assignment makes pointer from integer without a cast [enabled by default] addr_reg = ioremap(addr->start, 1); ^ drivers/usb/host/sl811-hcd.c:1675:12: warning: assignment makes pointer from integer without a cast [enabled by default] data_reg = ioremap(data->start, 1); ^ Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index e781fb114aea..96221c43d208 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -671,6 +671,7 @@ config USB_U132_HCD config USB_SL811_HCD tristate "SL811HS HCD support" + depends on HAS_IOMEM help The SL811HS is a single-port USB controller that supports either host side or peripheral side roles. Enable this option if your -- cgit From 89f1ec8ee251920dd1bf07abf7a14c62d81d5733 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:44 +0100 Subject: usb: add HAS_IOMEM dependency to USB_DWC2 drivers/built-in.o: In function `dwc2_driver_probe': /home/vegard/linux/drivers/usb/dwc2/platform.c:491: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig index fd95ba6ec317..b56920a56a7c 100644 --- a/drivers/usb/dwc2/Kconfig +++ b/drivers/usb/dwc2/Kconfig @@ -1,6 +1,7 @@ config USB_DWC2 tristate "DesignWare USB2 DRD Core Support" depends on USB || USB_GADGET + depends on HAS_IOMEM help Say Y here if your system has a Dual Role Hi-Speed USB controller based on the DesignWare HSOTG IP Core. -- cgit From aaa98db7181f99784c900618f9c1c8b0bcab43a0 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:45 +0100 Subject: usb: add HAS_IOMEM dependency to USB_EHCI_HCD drivers/built-in.o: In function `ehci_platform_probe': /home/vegard/linux/drivers/usb/host/ehci-platform.c:282: undefined reference to `devm_ioremap_resource' drivers/built-in.o: In function `oxu_drv_probe': /home/vegard/linux/drivers/usb/host/oxu210hp-hcd.c:3821: undefined reference to `devm_ioremap_resource' drivers/built-in.o: In function `isp1362_probe': /home/vegard/linux/drivers/usb/host/isp1362-hcd.c:2668: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 96221c43d208..4c2e38ab4d4d 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -72,6 +72,7 @@ endif # USB_XHCI_HCD config USB_EHCI_HCD tristate "EHCI HCD (USB 2.0) support" + depends on HAS_IOMEM ---help--- The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. -- cgit From 8f2abe808dbfe4f84412aa3bb40f97f464727641 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:46 +0100 Subject: usb: add HAS_IOMEM dependency to USB_XHCI_HCD drivers/built-in.o: In function `xhci_plat_probe': /home/vegard/linux/drivers/usb/host/xhci-plat.c:160: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 4c2e38ab4d4d..90cb8d54a65a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -18,6 +18,7 @@ config USB_C67X00_HCD config USB_XHCI_HCD tristate "xHCI HCD (USB 3.0) support" + depends on HAS_IOMEM ---help--- The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 "SuperSpeed" host controller hardware. -- cgit From eaa86229ff32a9aea80d7aa24289754e2eed8a76 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:47 +0100 Subject: usb: add HAS_IOMEM dependency to USB_FOTG210_HCD drivers/built-in.o: In function `fotg210_hcd_probe': /home/vegard/linux/drivers/usb/host/fotg210-hcd.c:5637: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 90cb8d54a65a..89f592dfa237 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -367,6 +367,7 @@ config USB_ISP1362_HCD config USB_FOTG210_HCD tristate "FOTG210 HCD support" depends on USB + depends on HAS_IOMEM ---help--- Faraday FOTG210 is an OTG controller which can be configured as an USB2.0 host. It is designed to meet USB2.0 EHCI specification -- cgit From 17987ea59b4bacc928333d4084b5f9d8d442646b Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:48 +0100 Subject: usb: add HAS_IOMEM dependency to USB_MUSB_HDRC drivers/built-in.o: In function `musb_probe': /home/vegard/linux/drivers/usb/musb/musb_core.c:2304: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 0401573f79aa..886526b5fcdd 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -7,6 +7,7 @@ config USB_MUSB_HDRC tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)' depends on (USB || USB_GADGET) + depends on HAS_IOMEM help Say Y here if your system has a dual role high speed USB controller based on the Mentor Graphics silicon IP. Then -- cgit From 1b4ea40bbd87d963c9c6328b304aec4106ac8e89 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:49 +0100 Subject: usb: add HAS_IOMEM dependency to USB_PXA25X drivers/built-in.o: In function `pxa_udc_probe': /home/vegard/linux/drivers/usb/gadget/udc/pxa27x_udc.c:2430: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index e06efa3c3033..70feaf2a012d 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -128,6 +128,7 @@ config USB_OMAP config USB_PXA25X tristate "PXA 25x or IXP 4xx" depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX + depends on HAS_IOMEM help Intel's PXA 25x series XScale ARM-5TE processors include an integrated full speed USB 1.1 device controller. The -- cgit From 4b61b4f205eabfc9f863f805858aa5b32deb3de5 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:50 +0100 Subject: usb: add HAS_IOMEM dependency to USB_APPLEDISPLAY warning: (USB_APPLEDISPLAY) selects BACKLIGHT_LCD_SUPPORT which has unmet direct dependencies (HAS_IOMEM) Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index f7a7fc21be8a..ea10059d1b48 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -150,6 +150,7 @@ config USB_FTDI_ELAN config USB_APPLEDISPLAY tristate "Apple Cinema Display support" + depends on HAS_IOMEM select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE help -- cgit From 1043960c982b7478d3f235767632c752370aa95e Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:51 +0100 Subject: usb: add HAS_IOMEM dependency to USB_OHCI_HCD drivers/built-in.o: In function `ohci_platform_probe': /home/vegard/linux/drivers/usb/host/ohci-platform.c:246: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 89f592dfa237..af6201601f93 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -389,6 +389,7 @@ config USB_MAX3421_HCD config USB_OHCI_HCD tristate "OHCI HCD (USB 1.1) support" + depends on HAS_IOMEM ---help--- The Open Host Controller Interface (OHCI) is a standard for accessing USB 1.1 host controller hardware. It does more in hardware than Intel's -- cgit From c470ba38097b2e2adf695e4cfb8e5f6fa362e125 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:52 +0100 Subject: usb: add HAS_IOMEM dependency to USB_PXA27X drivers/built-in.o: In function `pxa_udc_probe': /home/vegard/linux/drivers/usb/gadget/udc/pxa27x_udc.c:2430: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 70feaf2a012d..d6ad7e6c978c 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -188,6 +188,7 @@ config USB_RENESAS_USB3 config USB_PXA27X tristate "PXA 27x" + depends on HAS_IOMEM help Intel's PXA 27x series XScale ARM v5TE processors include an integrated full speed USB 1.1 device controller. -- cgit From f4a5d7028a20ee87e128a0e5fec5321fc831d1de Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:53 +0100 Subject: usb: add HAS_IOMEM dependency to USB_OXU210HP_HCD drivers/built-in.o: In function `oxu_drv_probe': /home/vegard/linux/drivers/usb/host/oxu210hp-hcd.c:3821: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index af6201601f93..85230d6852e8 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -332,6 +332,7 @@ endif # USB_EHCI_HCD config USB_OXU210HP_HCD tristate "OXU210HP HCD support" + depends on HAS_IOMEM ---help--- The OXU210HP is an USB host/OTG/device controller. Enable this option if your board has this chip. If unsure, say N. -- cgit From 4a6d9f87209908fb5909c9957597e4df9c3c56fc Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 10 Feb 2016 15:29:54 +0100 Subject: usb: add HAS_IOMEM dependency to USB_ISP1362_HCD drivers/built-in.o: In function `isp1362_probe': /home/vegard/linux/drivers/usb/host/isp1362-hcd.c:2668: undefined reference to `devm_ioremap_resource' Signed-off-by: Vegard Nossum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 85230d6852e8..438dcf6289b0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -357,6 +357,7 @@ config USB_ISP116X_HCD config USB_ISP1362_HCD tristate "ISP1362 HCD support" + depends on HAS_IOMEM ---help--- Supports the Philips ISP1362 chip as a host controller -- cgit From f7d34b445abc00e979b7cf36b9580ac3d1a47cd8 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 3 Feb 2016 22:58:26 +0100 Subject: USB: Add support for usbfs zerocopy. Add a new interface for userspace to preallocate memory that can be used with usbfs. This gives two primary benefits: - Zerocopy; data no longer needs to be copied between the userspace and the kernel, but can instead be read directly by the driver from userspace's buffers. This works for all kinds of transfers (even if nonsensical for control and interrupt transfers); isochronous also no longer need to memset() the buffer to zero to avoid leaking kernel data. - Once the buffers are allocated, USB transfers can no longer fail due to memory fragmentation; previously, long-running programs could run into problems finding a large enough contiguous memory chunk, especially on embedded systems or at high rates. Memory is allocated by using mmap() against the usbfs file descriptor, and similarly deallocated by munmap(). Once memory has been allocated, using it as pointers to a bulk or isochronous operation means you will automatically get zerocopy behavior. Note that this also means you cannot modify outgoing data until the transfer is complete. The same holds for data on the same cache lines as incoming data; DMA modifying them at the same time could lead to your changes being overwritten. There's a new capability USBDEVFS_CAP_MMAP that userspace can query to see if the running kernel supports this functionality, if just trying mmap() is not acceptable. Largely based on a patch by Markus Rechberger with some updates. The original patch can be found at: http://sundtek.de/support/devio_mmap_v0.4.diff Signed-off-by: Steinar H. Gunderson Signed-off-by: Markus Rechberger Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 227 +++++++++++++++++++++++++++++++++----- include/uapi/linux/usbdevice_fs.h | 1 + 2 files changed, 203 insertions(+), 25 deletions(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 13a4b9f48739..39da1662b76f 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -69,6 +70,7 @@ struct usb_dev_state { spinlock_t lock; /* protects the async urb lists */ struct list_head async_pending; struct list_head async_completed; + struct list_head memory_list; wait_queue_head_t wait; /* wake up if a request completed */ unsigned int discsignr; struct pid *disc_pid; @@ -79,6 +81,17 @@ struct usb_dev_state { u32 disabled_bulk_eps; }; +struct usb_memory { + struct list_head memlist; + int vma_use_count; + int urb_use_count; + u32 size; + void *mem; + dma_addr_t dma_handle; + unsigned long vm_start; + struct usb_dev_state *ps; +}; + struct async { struct list_head asynclist; struct usb_dev_state *ps; @@ -89,6 +102,7 @@ struct async { void __user *userbuffer; void __user *userurb; struct urb *urb; + struct usb_memory *usbm; unsigned int mem_usage; int status; u32 secid; @@ -162,6 +176,111 @@ static int connected(struct usb_dev_state *ps) ps->dev->state != USB_STATE_NOTATTACHED); } +static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count) +{ + struct usb_dev_state *ps = usbm->ps; + unsigned long flags; + + spin_lock_irqsave(&ps->lock, flags); + --*count; + if (usbm->urb_use_count == 0 && usbm->vma_use_count == 0) { + list_del(&usbm->memlist); + spin_unlock_irqrestore(&ps->lock, flags); + + usb_free_coherent(ps->dev, usbm->size, usbm->mem, + usbm->dma_handle); + usbfs_decrease_memory_usage( + usbm->size + sizeof(struct usb_memory)); + kfree(usbm); + } else { + spin_unlock_irqrestore(&ps->lock, flags); + } +} + +static void usbdev_vm_open(struct vm_area_struct *vma) +{ + struct usb_memory *usbm = vma->vm_private_data; + unsigned long flags; + + spin_lock_irqsave(&usbm->ps->lock, flags); + ++usbm->vma_use_count; + spin_unlock_irqrestore(&usbm->ps->lock, flags); +} + +static void usbdev_vm_close(struct vm_area_struct *vma) +{ + struct usb_memory *usbm = vma->vm_private_data; + + dec_usb_memory_use_count(usbm, &usbm->vma_use_count); +} + +struct vm_operations_struct usbdev_vm_ops = { + .open = usbdev_vm_open, + .close = usbdev_vm_close +}; + +static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct usb_memory *usbm = NULL; + struct usb_dev_state *ps = file->private_data; + size_t size = vma->vm_end - vma->vm_start; + void *mem; + unsigned long flags; + dma_addr_t dma_handle; + int ret; + + ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory)); + if (ret) + goto error; + + usbm = kzalloc(sizeof(struct usb_memory), GFP_KERNEL); + if (!usbm) { + ret = -ENOMEM; + goto error_decrease_mem; + } + + mem = usb_alloc_coherent(ps->dev, size, GFP_USER, &dma_handle); + if (!mem) { + ret = -ENOMEM; + goto error_free_usbm; + } + + memset(mem, 0, size); + + usbm->mem = mem; + usbm->dma_handle = dma_handle; + usbm->size = size; + usbm->ps = ps; + usbm->vm_start = vma->vm_start; + usbm->vma_use_count = 1; + INIT_LIST_HEAD(&usbm->memlist); + + if (remap_pfn_range(vma, vma->vm_start, + virt_to_phys(usbm->mem) >> PAGE_SHIFT, + size, vma->vm_page_prot) < 0) { + dec_usb_memory_use_count(usbm, &usbm->vma_use_count); + return -EAGAIN; + } + + vma->vm_flags |= VM_IO; + vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); + vma->vm_ops = &usbdev_vm_ops; + vma->vm_private_data = usbm; + + spin_lock_irqsave(&ps->lock, flags); + list_add_tail(&usbm->memlist, &ps->memory_list); + spin_unlock_irqrestore(&ps->lock, flags); + + return 0; + +error_free_usbm: + kfree(usbm); +error_decrease_mem: + usbfs_decrease_memory_usage(size + sizeof(struct usb_memory)); +error: + return ret; +} + static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { @@ -278,8 +397,13 @@ static void free_async(struct async *as) if (sg_page(&as->urb->sg[i])) kfree(sg_virt(&as->urb->sg[i])); } + kfree(as->urb->sg); - kfree(as->urb->transfer_buffer); + if (as->usbm == NULL) + kfree(as->urb->transfer_buffer); + else + dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count); + kfree(as->urb->setup_packet); usb_free_urb(as->urb); usbfs_decrease_memory_usage(as->mem_usage); @@ -893,6 +1017,7 @@ static int usbdev_open(struct inode *inode, struct file *file) INIT_LIST_HEAD(&ps->list); INIT_LIST_HEAD(&ps->async_pending); INIT_LIST_HEAD(&ps->async_completed); + INIT_LIST_HEAD(&ps->memory_list); init_waitqueue_head(&ps->wait); ps->discsignr = 0; ps->disc_pid = get_pid(task_pid(current)); @@ -945,6 +1070,7 @@ static int usbdev_release(struct inode *inode, struct file *file) free_async(as); as = async_getcompleted(ps); } + kfree(ps); return 0; } @@ -1266,6 +1392,31 @@ static int proc_setconfig(struct usb_dev_state *ps, void __user *arg) return status; } +static struct usb_memory * +find_memory_area(struct usb_dev_state *ps, const struct usbdevfs_urb *uurb) +{ + struct usb_memory *usbm = NULL, *iter; + unsigned long flags; + unsigned long uurb_start = (unsigned long)uurb->buffer; + + spin_lock_irqsave(&ps->lock, flags); + list_for_each_entry(iter, &ps->memory_list, memlist) { + if (uurb_start >= iter->vm_start && + uurb_start < iter->vm_start + iter->size) { + if (uurb->buffer_length > iter->vm_start + iter->size - + uurb_start) { + usbm = ERR_PTR(-EINVAL); + } else { + usbm = iter; + usbm->urb_use_count++; + } + break; + } + } + spin_unlock_irqrestore(&ps->lock, flags); + return usbm; +} + static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb, struct usbdevfs_iso_packet_desc __user *iso_frame_desc, void __user *arg) @@ -1421,6 +1572,19 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb goto error; } + as->usbm = find_memory_area(ps, uurb); + if (IS_ERR(as->usbm)) { + ret = PTR_ERR(as->usbm); + as->usbm = NULL; + goto error; + } + + /* do not use SG buffers when memory mapped segments + * are in use + */ + if (as->usbm) + num_sgs = 0; + u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length + num_sgs * sizeof(struct scatterlist); ret = usbfs_increase_memory_usage(u); @@ -1458,29 +1622,35 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb totlen -= u; } } else if (uurb->buffer_length > 0) { - as->urb->transfer_buffer = kmalloc(uurb->buffer_length, - GFP_KERNEL); - if (!as->urb->transfer_buffer) { - ret = -ENOMEM; - goto error; - } + if (as->usbm) { + unsigned long uurb_start = (unsigned long)uurb->buffer; - if (!is_in) { - if (copy_from_user(as->urb->transfer_buffer, - uurb->buffer, - uurb->buffer_length)) { - ret = -EFAULT; + as->urb->transfer_buffer = as->usbm->mem + + (uurb_start - as->usbm->vm_start); + } else { + as->urb->transfer_buffer = kmalloc(uurb->buffer_length, + GFP_KERNEL); + if (!as->urb->transfer_buffer) { + ret = -ENOMEM; goto error; } - } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) { - /* - * Isochronous input data may end up being - * discontiguous if some of the packets are short. - * Clear the buffer so that the gaps don't leak - * kernel data to userspace. - */ - memset(as->urb->transfer_buffer, 0, - uurb->buffer_length); + if (!is_in) { + if (copy_from_user(as->urb->transfer_buffer, + uurb->buffer, + uurb->buffer_length)) { + ret = -EFAULT; + goto error; + } + } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) { + /* + * Isochronous input data may end up being + * discontiguous if some of the packets are + * short. Clear the buffer so that the gaps + * don't leak kernel data to userspace. + */ + memset(as->urb->transfer_buffer, 0, + uurb->buffer_length); + } } } as->urb->dev = ps->dev; @@ -1527,10 +1697,14 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb isopkt = NULL; as->ps = ps; as->userurb = arg; - if (is_in && uurb->buffer_length > 0) + if (as->usbm) { + unsigned long uurb_start = (unsigned long)uurb->buffer; + + as->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + as->urb->transfer_dma = as->usbm->dma_handle + + (uurb_start - as->usbm->vm_start); + } else if (is_in && uurb->buffer_length > 0) as->userbuffer = uurb->buffer; - else - as->userbuffer = NULL; as->signr = uurb->signr; as->ifnum = ifnum; as->pid = get_pid(task_pid(current)); @@ -1586,6 +1760,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb return 0; error: + if (as && as->usbm) + dec_usb_memory_use_count(as->usbm, &as->usbm->urb_use_count); kfree(isopkt); kfree(dr); if (as) @@ -2039,7 +2215,7 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg) __u32 caps; caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | - USBDEVFS_CAP_REAP_AFTER_DISCONNECT; + USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP; if (!ps->dev->bus->no_stop_on_short) caps |= USBDEVFS_CAP_BULK_CONTINUATION; if (ps->dev->bus->sg_tablesize) @@ -2365,6 +2541,7 @@ const struct file_operations usbdev_file_operations = { #ifdef CONFIG_COMPAT .compat_ioctl = usbdev_compat_ioctl, #endif + .mmap = usbdev_mmap, .open = usbdev_open, .release = usbdev_release, }; diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h index 019ba1e0799a..ecbd17650e6c 100644 --- a/include/uapi/linux/usbdevice_fs.h +++ b/include/uapi/linux/usbdevice_fs.h @@ -134,6 +134,7 @@ struct usbdevfs_hub_portinfo { #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04 #define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08 #define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10 +#define USBDEVFS_CAP_MMAP 0x20 /* USBDEVFS_DISCONNECT_CLAIM flags & struct */ -- cgit From acc27b6aad709997fa28da2f37f715a54eb487ab Mon Sep 17 00:00:00 2001 From: Saurabh Sengar Date: Thu, 11 Feb 2016 15:12:06 +0530 Subject: usb: host: pci_quirks: fix memory leak, by adding iounmap Added iounmap inorder to free memory mapped to pointer before returning Signed-off-by: Saurabh Sengar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 26cb8c861e6e..35af36253440 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -992,7 +992,7 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) if ((ext_cap_offset + sizeof(val)) > len) { /* We're reading garbage from the controller */ dev_warn(&pdev->dev, "xHCI controller failing to respond"); - return; + goto iounmap; } val = readl(base + ext_cap_offset); @@ -1055,6 +1055,7 @@ hc_init: XHCI_MAX_HALT_USEC, val); } +iounmap: iounmap(base); } -- cgit From df247081afc0dbd57472d653c587210c511f6931 Mon Sep 17 00:00:00 2001 From: Gabriel Krisman Bertazi Date: Mon, 8 Feb 2016 10:20:59 -0200 Subject: serial: jsm: change maintainer to myself Since Thadeu left IBM, jsm has gone mostly unmaintained, since his email address doesn't work anymore. I'm stepping up to help maintain this driver upstream. I'm adding Thadeu's personal e-mail address in Cc, hoping that we can get his ack. Signed-off-by: Gabriel Krisman Bertazi Cc: Thadeu Cascardo Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index cc2f753cb357..92d03b6cf75e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6043,7 +6043,7 @@ S: Maintained F: drivers/media/platform/rcar_jpu.c JSM Neo PCI based serial card -M: Thadeu Lima de Souza Cascardo +M: Gabriel Krisman Bertazi L: linux-serial@vger.kernel.org S: Maintained F: drivers/tty/serial/jsm/ -- cgit From 146f3808e08faabba46ea9574133a66aa4a9468d Mon Sep 17 00:00:00 2001 From: Andreas Färber Date: Mon, 8 Feb 2016 13:49:42 +0100 Subject: tty: serial: meson: Add support for XTAL clock input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the baudrate calculation for 24 MHz XTAL clock found on gxbb platforms. Signed-off-by: Andreas Färber Acked-by: Carlo Caione Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/meson_uart.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c index b12a37bd37b6..024445aa0521 100644 --- a/drivers/tty/serial/meson_uart.c +++ b/drivers/tty/serial/meson_uart.c @@ -78,6 +78,7 @@ /* AML_UART_REG5 bits */ #define AML_UART_BAUD_MASK 0x7fffff #define AML_UART_BAUD_USE BIT(23) +#define AML_UART_BAUD_XTAL BIT(24) #define AML_UART_PORT_NUM 6 #define AML_UART_DEV_NAME "ttyAML" @@ -299,7 +300,12 @@ static void meson_uart_change_speed(struct uart_port *port, unsigned long baud) val = readl(port->membase + AML_UART_REG5); val &= ~AML_UART_BAUD_MASK; - val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1; + if (port->uartclk == 24000000) { + val = ((port->uartclk / 3) / baud) - 1; + val |= AML_UART_BAUD_XTAL; + } else { + val = ((port->uartclk * 10 / (baud * 4) + 5) / 10) - 1; + } val |= AML_UART_BAUD_USE; writel(val, port->membase + AML_UART_REG5); } -- cgit From 9db669f14fd8297c42c5d3ea06720e992845f48a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Feb 2016 14:36:13 +0100 Subject: 8250: mediatek: mark PM functions as __maybe_unused The mtk8250_runtime_suspend function is not used when runtime PM is disabled, so we get a warning about an unused function: drivers/tty/serial/8250/8250_mtk.c:119:12: error: 'mtk8250_runtime_suspend' defined but not used [-Werror=unused-function] static int mtk8250_runtime_suspend(struct device *dev) This marks all the PM functions as __maybe_unused to avoid the warning, and removes the #ifdef around the PM_SLEEP functions for consistency. Signed-off-by: Arnd Bergmann Acked-by: Matthias Brugger Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_mtk.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 0e590b233f03..9038843cadc7 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -116,7 +116,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios, tty_termios_encode_baud_rate(termios, baud, baud); } -static int mtk8250_runtime_suspend(struct device *dev) +static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); @@ -126,7 +126,7 @@ static int mtk8250_runtime_suspend(struct device *dev) return 0; } -static int mtk8250_runtime_resume(struct device *dev) +static int __maybe_unused mtk8250_runtime_resume(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); int err; @@ -245,8 +245,7 @@ static int mtk8250_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int mtk8250_suspend(struct device *dev) +static int __maybe_unused mtk8250_suspend(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); @@ -255,7 +254,7 @@ static int mtk8250_suspend(struct device *dev) return 0; } -static int mtk8250_resume(struct device *dev) +static int __maybe_unused mtk8250_resume(struct device *dev) { struct mtk8250_data *data = dev_get_drvdata(dev); @@ -263,7 +262,6 @@ static int mtk8250_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_SLEEP */ static const struct dev_pm_ops mtk8250_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(mtk8250_suspend, mtk8250_resume) -- cgit From 0ab556c26690452fd66d8c95513fee201ceafbc0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Mon, 8 Feb 2016 16:27:35 +0000 Subject: serial: 8250_early: Add earlycon support for Tegra Declare an OF early console for Tegra so that the early console device can be specified via the "stdout-path" property in device-tree. Signed-off-by: Jon Hunter Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_early.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 3b3dbdc1b73e..8d08ff5c4e34 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -149,6 +149,7 @@ EARLYCON_DECLARE(uart8250, early_serial8250_setup); EARLYCON_DECLARE(uart, early_serial8250_setup); OF_EARLYCON_DECLARE(ns16550, "ns16550", early_serial8250_setup); OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup); +OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup); #ifdef CONFIG_SERIAL_8250_OMAP -- cgit From e1a7d248279e375896cf53e9cb980032a84bf83e Mon Sep 17 00:00:00 2001 From: Martin Sperl Date: Tue, 9 Feb 2016 11:47:16 +0000 Subject: serial: bcm2835: fix unsigned int issue with irq Fixes error condition check when requesting the irq, that would not trigger because of uart_port.irq being defined as unsigned int. Reported by: Dan Carpenter Signed-off-by: Martin Sperl Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_bcm2835aux.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index ecf89f13a13b..e10f1244409b 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -59,12 +59,12 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) } /* get the interrupt */ - data->uart.port.irq = platform_get_irq(pdev, 0); - if (data->uart.port.irq < 0) { - dev_err(&pdev->dev, "irq not found - %i", - data->uart.port.irq); - return data->uart.port.irq; + ret = platform_get_irq(pdev, 0); + if (ret < 0) { + dev_err(&pdev->dev, "irq not found - %i", ret); + return ret; } + data->uart.port.irq = ret; /* map the main registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit From 8f5405c9f217cb8c148a9f1372256a99623ca034 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 9 Feb 2016 07:06:47 -0800 Subject: serial: clps711x: Fix bad usage of IS_ERR_VALUE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IS_ERR_VALUE() assumes that its parameter is an unsigned long. It can not be used to check if an unsigned int reflects an error. Doing so can result in the following build warning. drivers/tty/serial/clps711x.c: In function ‘uart_clps711x_probe’: include/linux/err.h:21:38: warning: comparison is always false due to limited range of data type drivers/tty/serial/clps711x.c:471:6: note: in expansion of macro ‘IS_ERR_VALUE’ If that warning is seen, an error return from platform_get_irq() is missed. Use a temporary variable to check for errors from platform_get_irq(). Also don't use IS_ERR_VALUE() to check if an integer variable is < 0. The variable can be checked directly in that case. Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/clps711x.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index b3a4e0cdddaa..5beafd2d2218 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -450,6 +450,7 @@ static int uart_clps711x_probe(struct platform_device *pdev) struct clps711x_port *s; struct resource *res; struct clk *uart_clk; + int irq; if (index < 0 || index >= UART_CLPS711X_NR) return -EINVAL; @@ -467,12 +468,13 @@ static int uart_clps711x_probe(struct platform_device *pdev) if (IS_ERR(s->port.membase)) return PTR_ERR(s->port.membase); - s->port.irq = platform_get_irq(pdev, 0); - if (IS_ERR_VALUE(s->port.irq)) - return s->port.irq; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + s->port.irq = irq; s->rx_irq = platform_get_irq(pdev, 1); - if (IS_ERR_VALUE(s->rx_irq)) + if (s->rx_irq < 0) return s->rx_irq; if (!np) { -- cgit From dd9b55883e291a69a02a070cb27bc0c326c55bed Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 9 Feb 2016 07:08:59 -0800 Subject: tty/serial: digicolor: Fix bad usage of IS_ERR_VALUE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IS_ERR_VALUE() assumes that its parameter is an unsigned long. It can not be used to check if an unsigned int reflects an error. Doing so can result in the following build warning. drivers/tty/serial/digicolor-usart.c: In function ‘digicolor_uart_probe’: include/linux/err.h:21:38: warning: comparison is always false due to limited range of data type drivers/tty/serial/digicolor-usart.c:485:6: note: in expansion of macro ‘IS_ERR_VALUE’ If that warning is seen, an error return from platform_get_irq() is missed. Signed-off-by: Guenter Roeck Acked-by: Baruch Siach Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/digicolor-usart.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c index a80cdad114f3..02ad6953b167 100644 --- a/drivers/tty/serial/digicolor-usart.c +++ b/drivers/tty/serial/digicolor-usart.c @@ -453,7 +453,7 @@ static struct uart_driver digicolor_uart = { static int digicolor_uart_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - int ret, index; + int irq, ret, index; struct digicolor_port *dp; struct resource *res; struct clk *uart_clk; @@ -481,9 +481,10 @@ static int digicolor_uart_probe(struct platform_device *pdev) if (IS_ERR(dp->port.membase)) return PTR_ERR(dp->port.membase); - dp->port.irq = platform_get_irq(pdev, 0); - if (IS_ERR_VALUE(dp->port.irq)) - return dp->port.irq; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + dp->port.irq = irq; dp->port.iotype = UPIO_MEM; dp->port.uartclk = clk_get_rate(uart_clk); -- cgit From b7dfdea85917909b0b85913a0a727ff9dfd047f7 Mon Sep 17 00:00:00 2001 From: Maarten Brock Date: Sun, 14 Feb 2016 15:05:25 +0100 Subject: sc16is7xx: implemented set_mctrl Add support for manual setting the modem control lines. Signed-off-by: Maarten Brock Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 311e7bc07a24..025a4264430e 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -761,12 +761,20 @@ static void sc16is7xx_reg_proc(struct kthread_work *ws) memset(&one->config, 0, sizeof(one->config)); spin_unlock_irqrestore(&one->port.lock, irqflags); - if (config.flags & SC16IS7XX_RECONF_MD) + if (config.flags & SC16IS7XX_RECONF_MD) { sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_LOOP_BIT, (one->port.mctrl & TIOCM_LOOP) ? SC16IS7XX_MCR_LOOP_BIT : 0); - + sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG, + SC16IS7XX_MCR_RTS_BIT, + (one->port.mctrl & TIOCM_RTS) ? + SC16IS7XX_MCR_RTS_BIT : 0); + sc16is7xx_port_update(&one->port, SC16IS7XX_MCR_REG, + SC16IS7XX_MCR_DTR_BIT, + (one->port.mctrl & TIOCM_DTR) ? + SC16IS7XX_MCR_DTR_BIT : 0); + } if (config.flags & SC16IS7XX_RECONF_IER) sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG, config.ier_clear, 0); -- cgit From a3f0b77f36ca5c5871fb8daf7e66fa409abe1ed5 Mon Sep 17 00:00:00 2001 From: Maarten Brock Date: Sun, 14 Feb 2016 15:05:26 +0100 Subject: sc16is7xx: implemented get_mctrl Add support for manual getting the modem control lines. Signed-off-by: Maarten Brock Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/sc16is7xx.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 025a4264430e..e78fa99475c0 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -822,10 +822,16 @@ static unsigned int sc16is7xx_tx_empty(struct uart_port *port) static unsigned int sc16is7xx_get_mctrl(struct uart_port *port) { - /* DCD and DSR are not wired and CTS/RTS is handled automatically - * so just indicate DSR and CAR asserted - */ - return TIOCM_DSR | TIOCM_CAR; + unsigned int msr; + unsigned int ret = 0; + + msr = sc16is7xx_port_read(port, SC16IS7XX_MSR_REG); + + ret |= (msr & SC16IS7XX_MSR_CTS_BIT) ? TIOCM_CTS : 0; + ret |= (msr & SC16IS7XX_MSR_DSR_BIT) ? TIOCM_DSR : 0; + ret |= (msr & SC16IS7XX_MSR_RI_BIT) ? TIOCM_RNG : 0; + ret |= (msr & SC16IS7XX_MSR_CD_BIT) ? TIOCM_CAR : 0; + return ret; } static void sc16is7xx_set_mctrl(struct uart_port *port, unsigned int mctrl) -- cgit From 264904ccc33c604d4b3141bbd33808152dfac45b Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 10 Feb 2016 11:33:18 +0100 Subject: usb: retry reset if a device times out Some devices I got show an inability to operate right after power on if they are already connected. They are beyond recovery if the descriptors are requested multiple times. So in case of a timeout we rather bail early and reset again. But it must be done only on the first loop lest we get into a reset/time out spiral that can be overcome with a retry. This patch is a rework of a patch that fell through the cracks. http://www.spinics.net/lists/linux-usb/msg103263.html Signed-off-by: Oliver Neukum CC: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 681036d00528..0f82db42fd59 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4496,7 +4496,13 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, r = -EPROTO; break; } - if (r == 0) + /* + * Some devices time out if they are powered on + * when already connected. They need a second + * reset. But only on the first attempt, + * lest we get into a time out/reset loop + */ + if (r == 0 || (r == -ETIMEDOUT && j == 0)) break; } udev->descriptor.bMaxPacketSize0 = -- cgit From 6ddf2f0cb1e1931d16e08e30130ed04e5a441f2c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 12 Feb 2016 09:40:26 +0300 Subject: misc: mic: use after free printing error message Swap the printk and kfree() to avoid a use after free bug. Fixes: 61e9c905df78 ('misc: mic: Enable VOP host side functionality') Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/vop/vop_vringh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c index c1dd000f042b..c3613f39eb35 100644 --- a/drivers/misc/mic/vop/vop_vringh.c +++ b/drivers/misc/mic/vop/vop_vringh.c @@ -290,9 +290,9 @@ static int vop_virtio_add_device(struct vop_vdev *vdev, ret = vop_copy_dp_entry(vdev, argp, &type, &dd); if (ret) { - kfree(vdev); dev_err(vop_dev(vdev), "%s %d err %d\n", __func__, __LINE__, ret); + kfree(vdev); return ret; } -- cgit From 59ea25904406a606d1329650e45e13e682e89320 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 12 Feb 2016 09:44:34 +0300 Subject: misc: mic: silence an overflow warning Static checkers complain that the this is a potential array overflow. We verify that it's not on the next line so this code is OK, but static checker warnings are annoying. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mic/vop/vop_vringh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/mic/vop/vop_vringh.c b/drivers/misc/mic/vop/vop_vringh.c index c3613f39eb35..e94c7fb6712a 100644 --- a/drivers/misc/mic/vop/vop_vringh.c +++ b/drivers/misc/mic/vop/vop_vringh.c @@ -848,12 +848,13 @@ static int vop_virtio_copy_desc(struct vop_vdev *vdev, struct mic_copy_desc *copy) { int err; - struct vop_vringh *vvr = &vdev->vvr[copy->vr_idx]; + struct vop_vringh *vvr; err = vop_verify_copy_args(vdev, copy); if (err) return err; + vvr = &vdev->vvr[copy->vr_idx]; mutex_lock(&vvr->vr_mutex); if (!vop_vdevup(vdev)) { err = -ENODEV; -- cgit From 1d427da1d7f9f81c4f5439c9610683d3cb9c1921 Mon Sep 17 00:00:00 2001 From: Shraddha Barke Date: Fri, 12 Feb 2016 16:11:54 +0530 Subject: Platform: goldfish: goldfish_pipe.c: Add DMA support using managed version Coherent mapping guarantees that the device and CPU are in sync. Signed-off-by: Shraddha Barke Signed-off-by: Greg Kroah-Hartman --- drivers/platform/goldfish/goldfish_pipe.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index e7a29e2750c6..9f6734ce1873 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -57,6 +57,7 @@ #include #include #include +#include /* * IMPORTANT: The following constants must match the ones used and defined @@ -217,17 +218,16 @@ static int valid_batchbuffer_addr(struct goldfish_pipe_dev *dev, static int setup_access_params_addr(struct platform_device *pdev, struct goldfish_pipe_dev *dev) { - u64 paddr; + dma_addr_t dma_handle; struct access_params *aps; - aps = devm_kzalloc(&pdev->dev, sizeof(struct access_params), GFP_KERNEL); + aps = dmam_alloc_coherent(&pdev->dev, sizeof(struct access_params), + &dma_handle, GFP_KERNEL); if (!aps) - return -1; + return -ENOMEM; - /* FIXME */ - paddr = __pa(aps); - writel((u32)(paddr >> 32), dev->base + PIPE_REG_PARAMS_ADDR_HIGH); - writel((u32)paddr, dev->base + PIPE_REG_PARAMS_ADDR_LOW); + writel(upper_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_HIGH); + writel(lower_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_LOW); if (valid_batchbuffer_addr(dev, aps)) { dev->aps = aps; -- cgit From 783ea44db7dbe60d0def22b8812b89940b7555b4 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:39 +0530 Subject: ppdev: space prohibited between function name and parenthesis checkpatch was complaining about space between function name and open parenthesis. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 192 +++++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 9e98d0153148..80ab757de8d3 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -106,13 +106,13 @@ static DEFINE_MUTEX(pp_do_mutex); #define PPGETTIME64 _IOR(PP_IOCTL, 0x95, s64[2]) #define PPSETTIME64 _IOW(PP_IOCTL, 0x96, s64[2]) -static inline void pp_enable_irq (struct pp_struct *pp) +static inline void pp_enable_irq(struct pp_struct *pp) { struct parport *port = pp->pdev->port; - port->ops->enable_irq (port); + port->ops->enable_irq(port); } -static ssize_t pp_read (struct file * file, char __user * buf, size_t count, +static ssize_t pp_read(struct file * file, char __user * buf, size_t count, loff_t * ppos) { unsigned int minor = iminor(file_inode(file)); @@ -139,7 +139,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - parport_set_timeout (pp->pdev, + parport_set_timeout(pp->pdev, (file->f_flags & O_NONBLOCK) ? PARPORT_INACTIVITY_O_NONBLOCK : pp->default_inactivity); @@ -165,7 +165,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, } bytes_read = (*fn)(pport, kbuffer, need, flags); } else { - bytes_read = parport_read (pport, kbuffer, need); + bytes_read = parport_read(pport, kbuffer, need); } if (bytes_read != 0) @@ -176,7 +176,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, break; } - if (signal_pending (current)) { + if (signal_pending(current)) { bytes_read = -ERESTARTSYS; break; } @@ -184,17 +184,17 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, cond_resched(); } - parport_set_timeout (pp->pdev, pp->default_inactivity); + parport_set_timeout(pp->pdev, pp->default_inactivity); - if (bytes_read > 0 && copy_to_user (buf, kbuffer, bytes_read)) + if (bytes_read > 0 && copy_to_user(buf, kbuffer, bytes_read)) bytes_read = -EFAULT; - kfree (kbuffer); - pp_enable_irq (pp); + kfree(kbuffer); + pp_enable_irq(pp); return bytes_read; } -static ssize_t pp_write (struct file * file, const char __user * buf, +static ssize_t pp_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) { unsigned int minor = iminor(file_inode(file)); @@ -218,7 +218,7 @@ static ssize_t pp_write (struct file * file, const char __user * buf, pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - parport_set_timeout (pp->pdev, + parport_set_timeout(pp->pdev, (file->f_flags & O_NONBLOCK) ? PARPORT_INACTIVITY_O_NONBLOCK : pp->default_inactivity); @@ -226,7 +226,7 @@ static ssize_t pp_write (struct file * file, const char __user * buf, while (bytes_written < count) { ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE); - if (copy_from_user (kbuffer, buf + bytes_written, n)) { + if (copy_from_user(kbuffer, buf + bytes_written, n)) { bytes_written = -EFAULT; break; } @@ -234,14 +234,14 @@ static ssize_t pp_write (struct file * file, const char __user * buf, if ((pp->flags & PP_FASTWRITE) && (mode == IEEE1284_MODE_EPP)) { /* do a fast EPP write */ if (pport->ieee1284.mode & IEEE1284_ADDR) { - wrote = pport->ops->epp_write_addr (pport, + wrote = pport->ops->epp_write_addr(pport, kbuffer, n, PARPORT_EPP_FAST); } else { - wrote = pport->ops->epp_write_data (pport, + wrote = pport->ops->epp_write_data(pport, kbuffer, n, PARPORT_EPP_FAST); } } else { - wrote = parport_write (pp->pdev->port, kbuffer, n); + wrote = parport_write(pp->pdev->port, kbuffer, n); } if (wrote <= 0) { @@ -259,33 +259,33 @@ static ssize_t pp_write (struct file * file, const char __user * buf, break; } - if (signal_pending (current)) + if (signal_pending(current)) break; cond_resched(); } - parport_set_timeout (pp->pdev, pp->default_inactivity); + parport_set_timeout(pp->pdev, pp->default_inactivity); - kfree (kbuffer); - pp_enable_irq (pp); + kfree(kbuffer); + pp_enable_irq(pp); return bytes_written; } -static void pp_irq (void *private) +static void pp_irq(void *private) { struct pp_struct *pp = private; if (pp->irqresponse) { - parport_write_control (pp->pdev->port, pp->irqctl); + parport_write_control(pp->pdev->port, pp->irqctl); pp->irqresponse = 0; } - atomic_inc (&pp->irqc); - wake_up_interruptible (&pp->irq_wait); + atomic_inc(&pp->irqc); + wake_up_interruptible(&pp->irq_wait); } -static int register_device (int minor, struct pp_struct *pp) +static int register_device(int minor, struct pp_struct *pp) { struct parport *port; struct pardevice * pdev = NULL; @@ -296,21 +296,21 @@ static int register_device (int minor, struct pp_struct *pp) if (name == NULL) return -ENOMEM; - port = parport_find_number (minor); + port = parport_find_number(minor); if (!port) { - printk (KERN_WARNING "%s: no associated port!\n", name); - kfree (name); + printk(KERN_WARNING "%s: no associated port!\n", name); + kfree(name); return -ENXIO; } fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; - pdev = parport_register_device (port, name, NULL, + pdev = parport_register_device(port, name, NULL, NULL, pp_irq, fl, pp); - parport_put_port (port); + parport_put_port(port); if (!pdev) { - printk (KERN_WARNING "%s: failed to register device!\n", name); - kfree (name); + printk(KERN_WARNING "%s: failed to register device!\n", name); + kfree(name); return -ENXIO; } @@ -319,7 +319,7 @@ static int register_device (int minor, struct pp_struct *pp) return 0; } -static enum ieee1284_phase init_phase (int mode) +static enum ieee1284_phase init_phase(int mode) { switch (mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR)) { @@ -367,13 +367,13 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* Deferred device registration. */ if (!pp->pdev) { - int err = register_device (minor, pp); + int err = register_device(minor, pp); if (err) { return err; } } - ret = parport_claim_or_block (pp->pdev); + ret = parport_claim_or_block(pp->pdev); if (ret < 0) return ret; @@ -381,7 +381,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* For interrupt-reporting to work, we need to be * informed of each interrupt. */ - pp_enable_irq (pp); + pp_enable_irq(pp); /* We may need to fix up the state machine. */ info = &pp->pdev->port->ieee1284; @@ -389,8 +389,8 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pp->saved_state.phase = info->phase; info->mode = pp->state.mode; info->phase = pp->state.phase; - pp->default_inactivity = parport_set_timeout (pp->pdev, 0); - parport_set_timeout (pp->pdev, pp->default_inactivity); + pp->default_inactivity = parport_set_timeout(pp->pdev, 0); + parport_set_timeout(pp->pdev, pp->default_inactivity); return 0; } @@ -412,11 +412,11 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PPSETMODE: { int mode; - if (copy_from_user (&mode, argp, sizeof (mode))) + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; /* FIXME: validate mode */ pp->state.mode = mode; - pp->state.phase = init_phase (mode); + pp->state.phase = init_phase(mode); if (pp->flags & PP_CLAIMED) { pp->pdev->port->ieee1284.mode = mode; @@ -434,7 +434,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } else { mode = pp->state.mode; } - if (copy_to_user (argp, &mode, sizeof (mode))) { + if (copy_to_user(argp, &mode, sizeof(mode))) { return -EFAULT; } return 0; @@ -442,7 +442,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PPSETPHASE: { int phase; - if (copy_from_user (&phase, argp, sizeof (phase))) { + if (copy_from_user(&phase, argp, sizeof(phase))) { return -EFAULT; } /* FIXME: validate phase */ @@ -463,7 +463,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } else { phase = pp->state.phase; } - if (copy_to_user (argp, &phase, sizeof (phase))) { + if (copy_to_user(argp, &phase, sizeof(phase))) { return -EFAULT; } return 0; @@ -472,13 +472,13 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned int modes; - port = parport_find_number (minor); + port = parport_find_number(minor); if (!port) return -ENODEV; modes = port->modes; parport_put_port(port); - if (copy_to_user (argp, &modes, sizeof (modes))) { + if (copy_to_user(argp, &modes, sizeof(modes))) { return -EFAULT; } return 0; @@ -487,7 +487,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int uflags; - if (copy_from_user (&uflags, argp, sizeof (uflags))) { + if (copy_from_user(&uflags, argp, sizeof(uflags))) { return -EFAULT; } pp->flags &= ~PP_FLAGMASK; @@ -499,7 +499,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int uflags; uflags = pp->flags & PP_FLAGMASK; - if (copy_to_user (argp, &uflags, sizeof (uflags))) { + if (copy_to_user(argp, &uflags, sizeof(uflags))) { return -EFAULT; } return 0; @@ -525,22 +525,22 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int ret; case PPRSTATUS: - reg = parport_read_status (port); - if (copy_to_user (argp, ®, sizeof (reg))) + reg = parport_read_status(port); + if (copy_to_user(argp, ®, sizeof(reg))) return -EFAULT; return 0; case PPRDATA: - reg = parport_read_data (port); - if (copy_to_user (argp, ®, sizeof (reg))) + reg = parport_read_data(port); + if (copy_to_user(argp, ®, sizeof(reg))) return -EFAULT; return 0; case PPRCONTROL: - reg = parport_read_control (port); - if (copy_to_user (argp, ®, sizeof (reg))) + reg = parport_read_control(port); + if (copy_to_user(argp, ®, sizeof(reg))) return -EFAULT; return 0; case PPYIELD: - parport_yield_blocking (pp->pdev); + parport_yield_blocking(pp->pdev); return 0; case PPRELEASE: @@ -550,45 +550,45 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pp->state.phase = info->phase; info->mode = pp->saved_state.mode; info->phase = pp->saved_state.phase; - parport_release (pp->pdev); + parport_release(pp->pdev); pp->flags &= ~PP_CLAIMED; return 0; case PPWCONTROL: - if (copy_from_user (®, argp, sizeof (reg))) + if (copy_from_user(®, argp, sizeof(reg))) return -EFAULT; - parport_write_control (port, reg); + parport_write_control(port, reg); return 0; case PPWDATA: - if (copy_from_user (®, argp, sizeof (reg))) + if (copy_from_user(®, argp, sizeof(reg))) return -EFAULT; - parport_write_data (port, reg); + parport_write_data(port, reg); return 0; case PPFCONTROL: - if (copy_from_user (&mask, argp, - sizeof (mask))) + if (copy_from_user(&mask, argp, + sizeof(mask))) return -EFAULT; - if (copy_from_user (®, 1 + (unsigned char __user *) arg, - sizeof (reg))) + if (copy_from_user(®, 1 + (unsigned char __user *) arg, + sizeof(reg))) return -EFAULT; - parport_frob_control (port, mask, reg); + parport_frob_control(port, mask, reg); return 0; case PPDATADIR: - if (copy_from_user (&mode, argp, sizeof (mode))) + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; if (mode) - port->ops->data_reverse (port); + port->ops->data_reverse(port); else - port->ops->data_forward (port); + port->ops->data_forward(port); return 0; case PPNEGOT: - if (copy_from_user (&mode, argp, sizeof (mode))) + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; - switch ((ret = parport_negotiate (port, mode))) { + switch ((ret = parport_negotiate(port, mode))) { case 0: break; case -1: /* handshake failed, peripheral not IEEE 1284 */ ret = -EIO; @@ -597,11 +597,11 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -ENXIO; break; } - pp_enable_irq (pp); + pp_enable_irq(pp); return ret; case PPWCTLONIRQ: - if (copy_from_user (®, argp, sizeof (reg))) + if (copy_from_user(®, argp, sizeof(reg))) return -EFAULT; /* Remember what to set the control lines to, for next @@ -611,10 +611,10 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case PPCLRIRQ: - ret = atomic_read (&pp->irqc); - if (copy_to_user (argp, &ret, sizeof (ret))) + ret = atomic_read(&pp->irqc); + if (copy_to_user(argp, &ret, sizeof(ret))) return -EFAULT; - atomic_sub (ret, &pp->irqc); + atomic_sub(ret, &pp->irqc); return 0; case PPSETTIME32: @@ -679,7 +679,7 @@ static long pp_compat_ioctl(struct file *file, unsigned int cmd, } #endif -static int pp_open (struct inode * inode, struct file * file) +static int pp_open(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); struct pp_struct *pp; @@ -687,16 +687,16 @@ static int pp_open (struct inode * inode, struct file * file) if (minor >= PARPORT_MAX) return -ENXIO; - pp = kmalloc (sizeof (struct pp_struct), GFP_KERNEL); + pp = kmalloc(sizeof(struct pp_struct), GFP_KERNEL); if (!pp) return -ENOMEM; pp->state.mode = IEEE1284_MODE_COMPAT; - pp->state.phase = init_phase (pp->state.mode); + pp->state.phase = init_phase(pp->state.mode); pp->flags = 0; pp->irqresponse = 0; - atomic_set (&pp->irqc, 0); - init_waitqueue_head (&pp->irq_wait); + atomic_set(&pp->irqc, 0); + init_waitqueue_head(&pp->irq_wait); /* Defer the actual device registration until the first claim. * That way, we know whether or not the driver wants to have @@ -708,7 +708,7 @@ static int pp_open (struct inode * inode, struct file * file) return 0; } -static int pp_release (struct inode * inode, struct file * file) +static int pp_release(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); struct pp_struct *pp = file->private_data; @@ -720,7 +720,7 @@ static int pp_release (struct inode * inode, struct file * file) struct ieee1284_info *info; /* parport released, but not in compatibility mode */ - parport_claim_or_block (pp->pdev); + parport_claim_or_block(pp->pdev); pp->flags |= PP_CLAIMED; info = &pp->pdev->port->ieee1284; pp->saved_state.mode = info->mode; @@ -733,7 +733,7 @@ static int pp_release (struct inode * inode, struct file * file) compat_negot = 2; } if (compat_negot) { - parport_negotiate (pp->pdev->port, IEEE1284_MODE_COMPAT); + parport_negotiate(pp->pdev->port, IEEE1284_MODE_COMPAT); pr_debug(CHRDEV "%x: negotiated back to compatibility " "mode because user-space forgot\n", minor); } @@ -746,7 +746,7 @@ static int pp_release (struct inode * inode, struct file * file) pp->state.phase = info->phase; info->mode = pp->saved_state.mode; info->phase = pp->saved_state.phase; - parport_release (pp->pdev); + parport_release(pp->pdev); if (compat_negot != 1) { pr_debug(CHRDEV "%x: released pardevice " "because user-space forgot\n", minor); @@ -755,25 +755,25 @@ static int pp_release (struct inode * inode, struct file * file) if (pp->pdev) { const char *name = pp->pdev->name; - parport_unregister_device (pp->pdev); - kfree (name); + parport_unregister_device(pp->pdev); + kfree(name); pp->pdev = NULL; pr_debug(CHRDEV "%x: unregistered pardevice\n", minor); } - kfree (pp); + kfree(pp); return 0; } /* No kernel lock held - fine */ -static unsigned int pp_poll (struct file * file, poll_table * wait) +static unsigned int pp_poll(struct file * file, poll_table * wait) { struct pp_struct *pp = file->private_data; unsigned int mask = 0; - poll_wait (file, &pp->irq_wait, wait); - if (atomic_read (&pp->irqc)) + poll_wait(file, &pp->irq_wait, wait); + if (atomic_read(&pp->irqc)) mask |= POLLIN | POLLRDNORM; return mask; @@ -812,12 +812,12 @@ static struct parport_driver pp_driver = { .detach = pp_detach, }; -static int __init ppdev_init (void) +static int __init ppdev_init(void) { int err = 0; - if (register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { - printk (KERN_WARNING CHRDEV ": unable to get major %d\n", + if (register_chrdev(PP_MAJOR, CHRDEV, &pp_fops)) { + printk(KERN_WARNING CHRDEV ": unable to get major %d\n", PP_MAJOR); return -EIO; } @@ -828,11 +828,11 @@ static int __init ppdev_init (void) } err = parport_register_driver(&pp_driver); if (err < 0) { - printk (KERN_WARNING CHRDEV ": unable to register with parport\n"); + printk(KERN_WARNING CHRDEV ": unable to register with parport\n"); goto out_class; } - printk (KERN_INFO PP_VERSION "\n"); + printk(KERN_INFO PP_VERSION "\n"); goto out; out_class: @@ -843,12 +843,12 @@ out: return err; } -static void __exit ppdev_cleanup (void) +static void __exit ppdev_cleanup(void) { /* Clean up all parport stuff */ parport_unregister_driver(&pp_driver); class_destroy(ppdev_class); - unregister_chrdev (PP_MAJOR, CHRDEV); + unregister_chrdev(PP_MAJOR, CHRDEV); } module_init(ppdev_init); -- cgit From d85c1a2d1591e0eb04d0c77b61e1062af61a9156 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:40 +0530 Subject: ppdev: remove whitespace around pointers checkpatch was complaining about space around the pointer. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 80ab757de8d3..8a168c4d094c 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -75,7 +75,7 @@ #define CHRDEV "ppdev" struct pp_struct { - struct pardevice * pdev; + struct pardevice *pdev; wait_queue_head_t irq_wait; atomic_t irqc; unsigned int flags; @@ -112,12 +112,12 @@ static inline void pp_enable_irq(struct pp_struct *pp) port->ops->enable_irq(port); } -static ssize_t pp_read(struct file * file, char __user * buf, size_t count, - loff_t * ppos) +static ssize_t pp_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; - char * kbuffer; + char *kbuffer; ssize_t bytes_read = 0; struct parport *pport; int mode; @@ -194,12 +194,12 @@ static ssize_t pp_read(struct file * file, char __user * buf, size_t count, return bytes_read; } -static ssize_t pp_write(struct file * file, const char __user * buf, - size_t count, loff_t * ppos) +static ssize_t pp_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; - char * kbuffer; + char *kbuffer; ssize_t bytes_written = 0; ssize_t wrote; int mode; @@ -288,7 +288,7 @@ static void pp_irq(void *private) static int register_device(int minor, struct pp_struct *pp) { struct parport *port; - struct pardevice * pdev = NULL; + struct pardevice *pdev = NULL; char *name; int fl; @@ -350,7 +350,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; - struct parport * port; + struct parport *port; void __user *argp = (void __user *)arg; /* First handle the cases that don't take arguments. */ @@ -679,7 +679,7 @@ static long pp_compat_ioctl(struct file *file, unsigned int cmd, } #endif -static int pp_open(struct inode * inode, struct file * file) +static int pp_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); struct pp_struct *pp; @@ -708,7 +708,7 @@ static int pp_open(struct inode * inode, struct file * file) return 0; } -static int pp_release(struct inode * inode, struct file * file) +static int pp_release(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); struct pp_struct *pp = file->private_data; @@ -767,7 +767,7 @@ static int pp_release(struct inode * inode, struct file * file) } /* No kernel lock held - fine */ -static unsigned int pp_poll(struct file * file, poll_table * wait) +static unsigned int pp_poll(struct file *file, poll_table *wait) { struct pp_struct *pp = file->private_data; unsigned int mask = 0; -- cgit From 27f3b8a3bf1442f8b571dffcb1cdf20d72c364ad Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:41 +0530 Subject: ppdev: add missing blank line kernel coding style recommends a blank line after varaiable declaration. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 8a168c4d094c..c551c0c88d8e 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -109,6 +109,7 @@ static DEFINE_MUTEX(pp_do_mutex); static inline void pp_enable_irq(struct pp_struct *pp) { struct parport *port = pp->pdev->port; + port->ops->enable_irq(port); } @@ -368,6 +369,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* Deferred device registration. */ if (!pp->pdev) { int err = register_device(minor, pp); + if (err) { return err; } @@ -412,6 +414,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PPSETMODE: { int mode; + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; /* FIXME: validate mode */ @@ -442,6 +445,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PPSETPHASE: { int phase; + if (copy_from_user(&phase, argp, sizeof(phase))) { return -EFAULT; } @@ -665,6 +669,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret; + mutex_lock(&pp_do_mutex); ret = pp_do_ioctl(file, cmd, arg); mutex_unlock(&pp_do_mutex); @@ -755,6 +760,7 @@ static int pp_release(struct inode *inode, struct file *file) if (pp->pdev) { const char *name = pp->pdev->name; + parport_unregister_device(pp->pdev); kfree(name); pp->pdev = NULL; -- cgit From 83e80605cc3ce6a2ac966151cd515f691e4835e0 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:42 +0530 Subject: ppdev: remove braces For single statement if and else blocks we do not need braces. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 57 ++++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index c551c0c88d8e..dfb419772038 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -134,9 +134,8 @@ static ssize_t pp_read(struct file *file, char __user *buf, size_t count, return 0; kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); - if (!kbuffer) { + if (!kbuffer) return -ENOMEM; - } pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); @@ -153,17 +152,14 @@ static ssize_t pp_read(struct file *file, char __user *buf, size_t count, int flags = 0; size_t (*fn)(struct parport *, void *, size_t, int); - if (pp->flags & PP_W91284PIC) { + if (pp->flags & PP_W91284PIC) flags |= PARPORT_W91284PIC; - } - if (pp->flags & PP_FASTREAD) { + if (pp->flags & PP_FASTREAD) flags |= PARPORT_EPP_FAST; - } - if (pport->ieee1284.mode & IEEE1284_ADDR) { + if (pport->ieee1284.mode & IEEE1284_ADDR) fn = pport->ops->epp_read_addr; - } else { + else fn = pport->ops->epp_read_data; - } bytes_read = (*fn)(pport, kbuffer, need, flags); } else { bytes_read = parport_read(pport, kbuffer, need); @@ -213,9 +209,9 @@ static ssize_t pp_write(struct file *file, const char __user *buf, } kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); - if (!kbuffer) { + if (!kbuffer) return -ENOMEM; - } + pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); @@ -246,9 +242,8 @@ static ssize_t pp_write(struct file *file, const char __user *buf, } if (wrote <= 0) { - if (!bytes_written) { + if (!bytes_written) bytes_written = wrote; - } break; } @@ -370,9 +365,8 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (!pp->pdev) { int err = register_device(minor, pp); - if (err) { + if (err) return err; - } } ret = parport_claim_or_block(pp->pdev); @@ -432,29 +426,27 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int mode; - if (pp->flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) mode = pp->pdev->port->ieee1284.mode; - } else { + else mode = pp->state.mode; - } - if (copy_to_user(argp, &mode, sizeof(mode))) { + + if (copy_to_user(argp, &mode, sizeof(mode))) return -EFAULT; - } return 0; } case PPSETPHASE: { int phase; - if (copy_from_user(&phase, argp, sizeof(phase))) { + if (copy_from_user(&phase, argp, sizeof(phase))) return -EFAULT; - } + /* FIXME: validate phase */ pp->state.phase = phase; - if (pp->flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) pp->pdev->port->ieee1284.phase = phase; - } return 0; } @@ -462,14 +454,12 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int phase; - if (pp->flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) phase = pp->pdev->port->ieee1284.phase; - } else { + else phase = pp->state.phase; - } - if (copy_to_user(argp, &phase, sizeof(phase))) { + if (copy_to_user(argp, &phase, sizeof(phase))) return -EFAULT; - } return 0; } case PPGETMODES: @@ -482,18 +472,16 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) modes = port->modes; parport_put_port(port); - if (copy_to_user(argp, &modes, sizeof(modes))) { + if (copy_to_user(argp, &modes, sizeof(modes))) return -EFAULT; - } return 0; } case PPSETFLAGS: { int uflags; - if (copy_from_user(&uflags, argp, sizeof(uflags))) { + if (copy_from_user(&uflags, argp, sizeof(uflags))) return -EFAULT; - } pp->flags &= ~PP_FLAGMASK; pp->flags |= (uflags & PP_FLAGMASK); return 0; @@ -503,9 +491,8 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int uflags; uflags = pp->flags & PP_FLAGMASK; - if (copy_to_user(argp, &uflags, sizeof(uflags))) { + if (copy_to_user(argp, &uflags, sizeof(uflags))) return -EFAULT; - } return 0; } } /* end switch() */ -- cgit From a7c71c07a31fde429627f0c7eed5fb57cb986fa6 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:43 +0530 Subject: ppdev: fix parenthesis alignment checkpatch was complaining that the alignment was not matching with the open parenthesis. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index dfb419772038..39dedb775d5f 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -114,7 +114,7 @@ static inline void pp_enable_irq(struct pp_struct *pp) } static ssize_t pp_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) + loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; @@ -140,9 +140,9 @@ static ssize_t pp_read(struct file *file, char __user *buf, size_t count, mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); parport_set_timeout(pp->pdev, - (file->f_flags & O_NONBLOCK) ? - PARPORT_INACTIVITY_O_NONBLOCK : - pp->default_inactivity); + (file->f_flags & O_NONBLOCK) ? + PARPORT_INACTIVITY_O_NONBLOCK : + pp->default_inactivity); while (bytes_read == 0) { ssize_t need = min_t(unsigned long, count, PP_BUFFER_SIZE); @@ -192,7 +192,7 @@ static ssize_t pp_read(struct file *file, char __user *buf, size_t count, } static ssize_t pp_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; @@ -216,9 +216,9 @@ static ssize_t pp_write(struct file *file, const char __user *buf, mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); parport_set_timeout(pp->pdev, - (file->f_flags & O_NONBLOCK) ? - PARPORT_INACTIVITY_O_NONBLOCK : - pp->default_inactivity); + (file->f_flags & O_NONBLOCK) ? + PARPORT_INACTIVITY_O_NONBLOCK : + pp->default_inactivity); while (bytes_written < count) { ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE); @@ -301,7 +301,7 @@ static int register_device(int minor, struct pp_struct *pp) fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; pdev = parport_register_device(port, name, NULL, - NULL, pp_irq, fl, pp); + NULL, pp_irq, fl, pp); parport_put_port(port); if (!pdev) { @@ -559,10 +559,10 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PPFCONTROL: if (copy_from_user(&mask, argp, - sizeof(mask))) + sizeof(mask))) return -EFAULT; if (copy_from_user(®, 1 + (unsigned char __user *) arg, - sizeof(reg))) + sizeof(reg))) return -EFAULT; parport_frob_control(port, mask, reg); return 0; @@ -665,7 +665,7 @@ static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_COMPAT static long pp_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) + unsigned long arg) { return pp_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); } @@ -811,7 +811,7 @@ static int __init ppdev_init(void) if (register_chrdev(PP_MAJOR, CHRDEV, &pp_fops)) { printk(KERN_WARNING CHRDEV ": unable to get major %d\n", - PP_MAJOR); + PP_MAJOR); return -EIO; } ppdev_class = class_create(THIS_MODULE, CHRDEV); -- cgit From 3c8db584323875a50696718c89d94cef0ed54f30 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:44 +0530 Subject: ppdev: remove space before tab For alignment we should use tab in all possible places. checkpatch was complaining for using space before tab. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 39dedb775d5f..bccc15a4b25d 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -709,7 +709,7 @@ static int pp_release(struct inode *inode, struct file *file) compat_negot = 0; if (!(pp->flags & PP_CLAIMED) && pp->pdev && (pp->state.mode != IEEE1284_MODE_COMPAT)) { - struct ieee1284_info *info; + struct ieee1284_info *info; /* parport released, but not in compatibility mode */ parport_claim_or_block(pp->pdev); -- cgit From e7223f18603374d235d8bb0398532323e5f318b9 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:45 +0530 Subject: ppdev: use new parport device model Modify ppdev driver to use the new parallel port device model. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index bccc15a4b25d..6152c09e89d9 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -286,7 +286,7 @@ static int register_device(int minor, struct pp_struct *pp) struct parport *port; struct pardevice *pdev = NULL; char *name; - int fl; + struct pardev_cb ppdev_cb; name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor); if (name == NULL) @@ -299,9 +299,11 @@ static int register_device(int minor, struct pp_struct *pp) return -ENXIO; } - fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; - pdev = parport_register_device(port, name, NULL, - NULL, pp_irq, fl, pp); + memset(&ppdev_cb, 0, sizeof(ppdev_cb)); + ppdev_cb.irq_func = pp_irq; + ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + ppdev_cb.private = pp; + pdev = parport_register_dev_model(port, name, &ppdev_cb, minor); parport_put_port(port); if (!pdev) { @@ -799,10 +801,23 @@ static void pp_detach(struct parport *port) device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); } +static int pp_probe(struct pardevice *par_dev) +{ + struct device_driver *drv = par_dev->dev.driver; + int len = strlen(drv->name); + + if (strncmp(par_dev->name, drv->name, len)) + return -ENODEV; + + return 0; +} + static struct parport_driver pp_driver = { .name = CHRDEV, - .attach = pp_attach, + .probe = pp_probe, + .match_port = pp_attach, .detach = pp_detach, + .devmodel = true, }; static int __init ppdev_init(void) -- cgit From 396ec3dea3d82d0a32906efe9803a8ef2647df51 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Fri, 12 Feb 2016 18:33:46 +0530 Subject: ppdev: use dev_* macros It is more preffered to use the dev_* family of macros instead of using the generic pr_*. Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 6152c09e89d9..d23368874710 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -313,7 +313,7 @@ static int register_device(int minor, struct pp_struct *pp) } pp->pdev = pdev; - pr_debug("%s: registered pardevice\n", name); + dev_dbg(&pdev->dev, "registered pardevice\n"); return 0; } @@ -359,7 +359,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int ret; if (pp->flags & PP_CLAIMED) { - pr_debug(CHRDEV "%x: you've already got it!\n", minor); + dev_dbg(&pp->pdev->dev, "you've already got it!\n"); return -EINVAL; } @@ -394,8 +394,8 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case PPEXCL: if (pp->pdev) { - pr_debug(CHRDEV "%x: too late for PPEXCL; " - "already registered\n", minor); + dev_dbg(&pp->pdev->dev, + "too late for PPEXCL; already registered\n"); if (pp->flags & PP_EXCL) /* But it's not really an error. */ return 0; @@ -647,7 +647,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; default: - pr_debug(CHRDEV "%x: What? (cmd=0x%x)\n", minor, cmd); + dev_dbg(&pp->pdev->dev, "What? (cmd=0x%x)\n", cmd); return -EINVAL; } @@ -728,8 +728,8 @@ static int pp_release(struct inode *inode, struct file *file) } if (compat_negot) { parport_negotiate(pp->pdev->port, IEEE1284_MODE_COMPAT); - pr_debug(CHRDEV "%x: negotiated back to compatibility " - "mode because user-space forgot\n", minor); + dev_dbg(&pp->pdev->dev, + "negotiated back to compatibility mode because user-space forgot\n"); } if (pp->flags & PP_CLAIMED) { -- cgit From 7a1b92ca6a07b5d2a4524b22ef5aab2d674f5dd9 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sun, 17 Jan 2016 21:36:03 +0100 Subject: MAINTAINERS: update bq27xxx driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update reviewers for bq27xxx, so that Pali and Andrew are reviewers with status and maintainer inherited from the power supply subsystem entry. Signed-off-by: Sebastian Reichel Acked-by: Pali Rohár Acked-by: Andrew F. Davis --- MAINTAINERS | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..23042b3d305c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7702,13 +7702,13 @@ S: Maintained F: arch/nios2/ NOKIA N900 POWER SUPPLY DRIVERS -M: Pali Rohár -S: Maintained +R: Pali Rohár F: include/linux/power/bq2415x_charger.h F: include/linux/power/bq27xxx_battery.h F: include/linux/power/isp1704_charger.h F: drivers/power/bq2415x_charger.c F: drivers/power/bq27xxx_battery.c +F: drivers/power/bq27xxx_battery_i2c.c F: drivers/power/isp1704_charger.c F: drivers/power/rx51_battery.c @@ -9572,6 +9572,12 @@ M: Andreas Noever S: Maintained F: drivers/thunderbolt/ +TI BQ27XXX POWER SUPPLY DRIVER +R: Andrew F. Davis +F: include/linux/power/bq27xxx_battery.h +F: drivers/power/bq27xxx_battery.c +F: drivers/power/bq27xxx_battery_i2c.c + TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER M: John Stultz M: Thomas Gleixner -- cgit From 178a787502123b01499c5a4617b94bb69ad49dd5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 1 Feb 2016 11:14:15 +1100 Subject: vfio: Enable VFIO device for powerpc ec53500f "kvm: Add VFIO device" added a special KVM pseudo-device which is used to handle any necessary interactions between KVM and VFIO. Currently that device is built on x86 and ARM, but not powerpc, although powerpc does support both KVM and VFIO. This makes things awkward in userspace Currently qemu prints an alarming error message if you attempt to use VFIO and it can't initialize the KVM VFIO device. We don't want to remove the warning, because lack of the KVM VFIO device could mean coherency problems on x86. On powerpc, however, the error is harmless but looks disturbing, and a test based on host architecture in qemu would be ugly, and break if we do need the KVM VFIO device for something important in future. There's nothing preventing the KVM VFIO device from being built for powerpc, so this patch turns it on. It won't actually do anything, since we don't define any of the arch_*() hooks, but it will make qemu happy and we can extend it in future if we need to. Signed-off-by: David Gibson Reviewed-by: Eric Auger Signed-off-by: Paul Mackerras --- arch/powerpc/kvm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 0570eef83fba..7f7b6d86ac73 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile @@ -8,7 +8,7 @@ ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm KVM := ../../../virt/kvm common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ - $(KVM)/eventfd.o + $(KVM)/eventfd.o $(KVM)/vfio.o CFLAGS_e500_mmu.o := -I. CFLAGS_e500_mmu_host.o := -I. -- cgit From 5b7a0187391fe9b48eec532bf0b4b814d491d5f5 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Tue, 12 Jan 2016 21:30:59 +0100 Subject: bq24735_charger: add status property to view/enable/disable charging Add possibility to disable/re-enable charging via sysfs. Signed-off-by: Peter Rosin Signed-off-by: Sebastian Reichel --- drivers/power/bq24735-charger.c | 90 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/drivers/power/bq24735-charger.c b/drivers/power/bq24735-charger.c index eb2b3689de97..079d1c6c2a8f 100644 --- a/drivers/power/bq24735-charger.c +++ b/drivers/power/bq24735-charger.c @@ -48,6 +48,8 @@ struct bq24735 { struct power_supply_desc charger_desc; struct i2c_client *client; struct bq24735_platform *pdata; + struct mutex lock; + bool charging; }; static inline struct bq24735 *to_bq24735(struct power_supply *psy) @@ -56,9 +58,23 @@ static inline struct bq24735 *to_bq24735(struct power_supply *psy) } static enum power_supply_property bq24735_charger_properties[] = { + POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_ONLINE, }; +static int bq24735_charger_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + return 1; + default: + break; + } + + return 0; +} + static inline int bq24735_write_word(struct i2c_client *client, u8 reg, u16 value) { @@ -174,16 +190,30 @@ static bool bq24735_charger_is_present(struct bq24735 *charger) return false; } +static int bq24735_charger_is_charging(struct bq24735 *charger) +{ + int ret = bq24735_read_word(charger->client, BQ24735_CHG_OPT); + + if (ret < 0) + return ret; + + return !(ret & BQ24735_CHG_OPT_CHARGE_DISABLE); +} + static irqreturn_t bq24735_charger_isr(int irq, void *devid) { struct power_supply *psy = devid; struct bq24735 *charger = to_bq24735(psy); - if (bq24735_charger_is_present(charger)) + mutex_lock(&charger->lock); + + if (charger->charging && bq24735_charger_is_present(charger)) bq24735_enable_charging(charger); else bq24735_disable_charging(charger); + mutex_unlock(&charger->lock); + power_supply_changed(psy); return IRQ_HANDLED; @@ -199,6 +229,19 @@ static int bq24735_charger_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ONLINE: val->intval = bq24735_charger_is_present(charger) ? 1 : 0; break; + case POWER_SUPPLY_PROP_STATUS: + switch (bq24735_charger_is_charging(charger)) { + case 1: + val->intval = POWER_SUPPLY_STATUS_CHARGING; + break; + case 0: + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + break; + default: + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + break; + } + break; default: return -EINVAL; } @@ -206,6 +249,46 @@ static int bq24735_charger_get_property(struct power_supply *psy, return 0; } +static int bq24735_charger_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct bq24735 *charger = to_bq24735(psy); + int ret; + + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + switch (val->intval) { + case POWER_SUPPLY_STATUS_CHARGING: + mutex_lock(&charger->lock); + charger->charging = true; + ret = bq24735_enable_charging(charger); + mutex_unlock(&charger->lock); + if (ret) + return ret; + bq24735_config_charger(charger); + break; + case POWER_SUPPLY_STATUS_DISCHARGING: + case POWER_SUPPLY_STATUS_NOT_CHARGING: + mutex_lock(&charger->lock); + charger->charging = false; + ret = bq24735_disable_charging(charger); + mutex_unlock(&charger->lock); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + power_supply_changed(psy); + break; + default: + return -EPERM; + } + + return 0; +} + static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client) { struct bq24735_platform *pdata; @@ -255,6 +338,8 @@ static int bq24735_charger_probe(struct i2c_client *client, if (!charger) return -ENOMEM; + mutex_init(&charger->lock); + charger->charging = true; charger->pdata = client->dev.platform_data; if (IS_ENABLED(CONFIG_OF) && !charger->pdata && client->dev.of_node) @@ -285,6 +370,9 @@ static int bq24735_charger_probe(struct i2c_client *client, supply_desc->properties = bq24735_charger_properties; supply_desc->num_properties = ARRAY_SIZE(bq24735_charger_properties); supply_desc->get_property = bq24735_charger_get_property; + supply_desc->set_property = bq24735_charger_set_property; + supply_desc->property_is_writeable = + bq24735_charger_property_is_writeable; psy_cfg.supplied_to = charger->pdata->supplied_to; psy_cfg.num_supplicants = charger->pdata->num_supplicants; -- cgit From 3f652c969dd223a6ff1df6e9a7052b0424a14167 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 25 Jan 2016 09:29:53 +0100 Subject: power/reset: versatile: support the actual versatile While this driver is named after the Versatile family of boards (ARM reference designs) the machine actually called Versatile was not supported. This patch makes the driver handle also that machine. We augment the register names for the reset to *VERSATILE* as well since it is the same register offsets for Versatile and RealView. Cc: Rob Herring Signed-off-by: Linus Walleij Signed-off-by: Sebastian Reichel --- drivers/power/reset/arm-versatile-reboot.c | 39 +++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/drivers/power/reset/arm-versatile-reboot.c b/drivers/power/reset/arm-versatile-reboot.c index b208073c887d..06d34ab47df5 100644 --- a/drivers/power/reset/arm-versatile-reboot.c +++ b/drivers/power/reset/arm-versatile-reboot.c @@ -18,8 +18,8 @@ #define INTEGRATOR_HDR_LOCK_OFFSET 0x14 #define INTEGRATOR_CM_CTRL_RESET (1 << 3) -#define REALVIEW_SYS_LOCK_OFFSET 0x20 -#define REALVIEW_SYS_RESETCTL_OFFSET 0x40 +#define VERSATILE_SYS_LOCK_OFFSET 0x20 +#define VERSATILE_SYS_RESETCTL_OFFSET 0x40 /* Magic unlocking token used on all Versatile boards */ #define VERSATILE_LOCK_VAL 0xA05F @@ -29,6 +29,7 @@ */ enum versatile_reboot { INTEGRATOR_REBOOT_CM, + VERSATILE_REBOOT_CM, REALVIEW_REBOOT_EB, REALVIEW_REBOOT_PB1176, REALVIEW_REBOOT_PB11MP, @@ -45,6 +46,10 @@ static const struct of_device_id versatile_reboot_of_match[] = { .compatible = "arm,core-module-integrator", .data = (void *)INTEGRATOR_REBOOT_CM }, + { + .compatible = "arm,core-module-versatile", + .data = (void *)VERSATILE_REBOOT_CM, + }, { .compatible = "arm,realview-eb-syscon", .data = (void *)REALVIEW_REBOOT_EB, @@ -82,33 +87,43 @@ static int versatile_reboot(struct notifier_block *this, unsigned long mode, INTEGRATOR_CM_CTRL_RESET, INTEGRATOR_CM_CTRL_RESET); break; + case VERSATILE_REBOOT_CM: + regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, + VERSATILE_LOCK_VAL); + regmap_update_bits(syscon_regmap, + VERSATILE_SYS_RESETCTL_OFFSET, + 0x0107, + 0x0105); + regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, + 0); + break; case REALVIEW_REBOOT_EB: - regmap_write(syscon_regmap, REALVIEW_SYS_LOCK_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_write(syscon_regmap, - REALVIEW_SYS_RESETCTL_OFFSET, 0x0008); + VERSATILE_SYS_RESETCTL_OFFSET, 0x0008); break; case REALVIEW_REBOOT_PB1176: - regmap_write(syscon_regmap, REALVIEW_SYS_LOCK_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_write(syscon_regmap, - REALVIEW_SYS_RESETCTL_OFFSET, 0x0100); + VERSATILE_SYS_RESETCTL_OFFSET, 0x0100); break; case REALVIEW_REBOOT_PB11MP: case REALVIEW_REBOOT_PBA8: - regmap_write(syscon_regmap, REALVIEW_SYS_LOCK_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); - regmap_write(syscon_regmap, REALVIEW_SYS_RESETCTL_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0000); - regmap_write(syscon_regmap, REALVIEW_SYS_RESETCTL_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0004); break; case REALVIEW_REBOOT_PBX: - regmap_write(syscon_regmap, REALVIEW_SYS_LOCK_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); - regmap_write(syscon_regmap, REALVIEW_SYS_RESETCTL_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x00f0); - regmap_write(syscon_regmap, REALVIEW_SYS_RESETCTL_OFFSET, + regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x00f4); break; } -- cgit From 6a65b2b2af716854986b6d7d17ce096a949be863 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 25 Jan 2016 16:45:49 +0100 Subject: power: collie_battery: hide unused variable The 'wakeup_enabled' variable in this driver is only accessed by the optional power management functions and we get a warning when they are disabled: drivers/power/collie_battery.c:29:12: error: 'wakeup_enabled' defined but not used [-Werror=unused-variable] This moves the definition next to the users inside the same #ifdef, which avoids the warning. Signed-off-by: Arnd Bergmann Acked-by: Pavel Machek Signed-off-by: Sebastian Reichel --- drivers/power/collie_battery.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c index 8a971b3dbe58..3a0bc608d4b5 100644 --- a/drivers/power/collie_battery.c +++ b/drivers/power/collie_battery.c @@ -26,7 +26,6 @@ static DEFINE_MUTEX(bat_lock); /* protects gpio pins */ static struct work_struct bat_work; static struct ucb1x00 *ucb; -static int wakeup_enabled; struct collie_bat { int status; @@ -291,6 +290,8 @@ static struct gpio collie_batt_gpios[] = { }; #ifdef CONFIG_PM +static int wakeup_enabled; + static int collie_bat_suspend(struct ucb1x00_dev *dev) { /* flush all pending status updates */ -- cgit From 4f4bfe6bf116d98e336a08ee19ac5754ba0f9f4a Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 25 Jan 2016 23:24:00 +0100 Subject: power: reset: Fix dependencies for !HAS_IOMEM archs Not every arch has io memory. So, unbreak the build by fixing the dependencies. Signed-off-by: Richard Weinberger Signed-off-by: Sebastian Reichel --- drivers/power/reset/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index 1131cf75acc6..0a6408a39c66 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -148,6 +148,7 @@ config POWER_RESET_KEYSTONE config POWER_RESET_SYSCON bool "Generic SYSCON regmap reset driver" depends on OF + depends on HAS_IOMEM select MFD_SYSCON help Reboot support for generic SYSCON mapped register reset. @@ -155,6 +156,7 @@ config POWER_RESET_SYSCON config POWER_RESET_SYSCON_POWEROFF bool "Generic SYSCON regmap poweroff driver" depends on OF + depends on HAS_IOMEM select MFD_SYSCON help Poweroff support for generic SYSCON mapped register poweroff. -- cgit From 1a3adce1c2c83498f0f9285c504b380fb4182d0d Mon Sep 17 00:00:00 2001 From: Jonathan Tinkham Date: Tue, 2 Feb 2016 23:03:44 -0700 Subject: power: bq24735-charger: fix failed i2c with ac-detect When an ac-detect pin exists, but the charger is not plugged in, the chip will not respond to i2c messages, causing the module to fail when inserted. Signed-off-by: Jonathan Tinkham Signed-off-by: Sebastian Reichel --- drivers/power/bq24735-charger.c | 45 ++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/drivers/power/bq24735-charger.c b/drivers/power/bq24735-charger.c index 079d1c6c2a8f..022a09ceab73 100644 --- a/drivers/power/bq24735-charger.c +++ b/drivers/power/bq24735-charger.c @@ -381,27 +381,6 @@ static int bq24735_charger_probe(struct i2c_client *client, i2c_set_clientdata(client, charger); - ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID); - if (ret < 0) { - dev_err(&client->dev, "Failed to read manufacturer id : %d\n", - ret); - return ret; - } else if (ret != 0x0040) { - dev_err(&client->dev, - "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret); - return -ENODEV; - } - - ret = bq24735_read_word(client, BQ24735_DEVICE_ID); - if (ret < 0) { - dev_err(&client->dev, "Failed to read device id : %d\n", ret); - return ret; - } else if (ret != 0x000B) { - dev_err(&client->dev, - "device id mismatch. 0x000b != 0x%04x\n", ret); - return -ENODEV; - } - if (gpio_is_valid(charger->pdata->status_gpio)) { ret = devm_gpio_request(&client->dev, charger->pdata->status_gpio, @@ -415,6 +394,30 @@ static int bq24735_charger_probe(struct i2c_client *client, charger->pdata->status_gpio_valid = !ret; } + if (!charger->pdata->status_gpio_valid + || bq24735_charger_is_present(charger)) { + ret = bq24735_read_word(client, BQ24735_MANUFACTURER_ID); + if (ret < 0) { + dev_err(&client->dev, "Failed to read manufacturer id : %d\n", + ret); + return ret; + } else if (ret != 0x0040) { + dev_err(&client->dev, + "manufacturer id mismatch. 0x0040 != 0x%04x\n", ret); + return -ENODEV; + } + + ret = bq24735_read_word(client, BQ24735_DEVICE_ID); + if (ret < 0) { + dev_err(&client->dev, "Failed to read device id : %d\n", ret); + return ret; + } else if (ret != 0x000B) { + dev_err(&client->dev, + "device id mismatch. 0x000b != 0x%04x\n", ret); + return -ENODEV; + } + } + ret = bq24735_config_charger(charger); if (ret < 0) { dev_err(&client->dev, "failed in configuring charger"); -- cgit From a60da83fd8949ebd6000e2d4b2876a899e38612b Mon Sep 17 00:00:00 2001 From: Jonathan Tinkham Date: Tue, 2 Feb 2016 23:03:46 -0700 Subject: power: bq24735-charger: document 'ti,external-control' option Implement an 'external-control' option for when the charger shouldn't be configured by the kernel. Signed-off-by: Jonathan Tinkham Acked-by: Rob Herring Signed-off-by: Sebastian Reichel --- Documentation/devicetree/bindings/power_supply/ti,bq24735.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt b/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt index 4f6a550184d0..3bf55757ceec 100644 --- a/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt +++ b/Documentation/devicetree/bindings/power_supply/ti,bq24735.txt @@ -22,6 +22,9 @@ Optional properties : value must be between 128mA and 8.064A with a 128mA step resolution. The POR value is 0x1000h. This number is in mA (e.g. 8064), see the spec for more information about the InputCurrent (0x3fh) register. + - ti,external-control : Indicates that the charger is configured externally + and that the host should not attempt to enable/disable charging or set the + charge voltage/current. Example: -- cgit From 64024ac7bb82c41265e7ba08235591d9a2709dfc Mon Sep 17 00:00:00 2001 From: Jonathan Tinkham Date: Tue, 2 Feb 2016 23:03:45 -0700 Subject: power: bq24735-charger: add 'ti,external-control' option Implement an 'ti,external-control' option for when the charger shouldn't be configured by the host. Signed-off-by: Jonathan Tinkham Signed-off-by: Sebastian Reichel --- drivers/power/bq24735-charger.c | 11 +++++++++++ include/linux/power/bq24735-charger.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/drivers/power/bq24735-charger.c b/drivers/power/bq24735-charger.c index 022a09ceab73..fa454c19ce17 100644 --- a/drivers/power/bq24735-charger.c +++ b/drivers/power/bq24735-charger.c @@ -106,6 +106,9 @@ static int bq24735_update_word(struct i2c_client *client, u8 reg, static inline int bq24735_enable_charging(struct bq24735 *charger) { + if (charger->pdata->ext_control) + return 0; + return bq24735_update_word(charger->client, BQ24735_CHG_OPT, BQ24735_CHG_OPT_CHARGE_DISABLE, ~BQ24735_CHG_OPT_CHARGE_DISABLE); @@ -113,6 +116,9 @@ static inline int bq24735_enable_charging(struct bq24735 *charger) static inline int bq24735_disable_charging(struct bq24735 *charger) { + if (charger->pdata->ext_control) + return 0; + return bq24735_update_word(charger->client, BQ24735_CHG_OPT, BQ24735_CHG_OPT_CHARGE_DISABLE, BQ24735_CHG_OPT_CHARGE_DISABLE); @@ -124,6 +130,9 @@ static int bq24735_config_charger(struct bq24735 *charger) int ret; u16 value; + if (pdata->ext_control) + return 0; + if (pdata->charge_current) { value = pdata->charge_current & BQ24735_CHARGE_CURRENT_MASK; @@ -322,6 +331,8 @@ static struct bq24735_platform *bq24735_parse_dt_data(struct i2c_client *client) if (!ret) pdata->input_current = val; + pdata->ext_control = of_property_read_bool(np, "ti,external-control"); + return pdata; } diff --git a/include/linux/power/bq24735-charger.h b/include/linux/power/bq24735-charger.h index f536164a6069..6b750c1a45fa 100644 --- a/include/linux/power/bq24735-charger.h +++ b/include/linux/power/bq24735-charger.h @@ -32,6 +32,8 @@ struct bq24735_platform { int status_gpio_active_low; bool status_gpio_valid; + bool ext_control; + char **supplied_to; size_t num_supplicants; }; -- cgit From 6659b55dae09b2042d8cdd0f4576502c3e81957c Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Fri, 12 Feb 2016 13:56:59 +0100 Subject: power_supply: Add types for USB Type C and PD chargers This adds power supply types for USB chargers defined in the USB Type-C Specification 1.1 and in the USB Power Delivery Specification Revision 2.0 V1.1. The following are added : POWER_SUPPLY_TYPE_USB_TYPE_C, /* Type C Port */ POWER_SUPPLY_TYPE_USB_PD, /* Power Delivery Port */ POWER_SUPPLY_TYPE_USB_PD_DRP, /* PD Dual Role Port */ Signed-off-by: Benson Leung [tomeu: remove the mention to Type C from the comments] Signed-off-by: Tomeu Vizoso Reviewed-by: Alec Berg Reviewed-by: Vincent Palatin Reviewed-by: Todd Broch Signed-off-by: Sebastian Reichel --- drivers/power/power_supply_sysfs.c | 3 ++- include/linux/power_supply.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index ed2d7fd0c734..80fed98832f9 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -45,7 +45,8 @@ static ssize_t power_supply_show_property(struct device *dev, char *buf) { static char *type_text[] = { "Unknown", "Battery", "UPS", "Mains", "USB", - "USB_DCP", "USB_CDP", "USB_ACA" + "USB_DCP", "USB_CDP", "USB_ACA", "USB_C", + "USB_PD", "USB_PD_DRP" }; static char *status_text[] = { "Unknown", "Charging", "Discharging", "Not charging", "Full" diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index ef9f1592185d..751061790626 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -163,6 +163,9 @@ enum power_supply_type { POWER_SUPPLY_TYPE_USB_DCP, /* Dedicated Charging Port */ POWER_SUPPLY_TYPE_USB_CDP, /* Charging Downstream Port */ POWER_SUPPLY_TYPE_USB_ACA, /* Accessory Charger Adapters */ + POWER_SUPPLY_TYPE_USB_TYPE_C, /* Type C Port */ + POWER_SUPPLY_TYPE_USB_PD, /* Power Delivery Port */ + POWER_SUPPLY_TYPE_USB_PD_DRP, /* PD Dual Role Port */ }; enum power_supply_notifier_events { -- cgit From 37091fdd831f28a6509008542174ed324dd645bc Mon Sep 17 00:00:00 2001 From: Markus Pargmann Date: Mon, 27 Jul 2015 07:36:49 +0200 Subject: nbd: Create size change events for userspace The userspace needs to know when nbd devices are ready for use. Currently no events are created for the userspace which doesn't work for systemd. See the discussion here: https://github.com/systemd/systemd/pull/358 This patch uses a central point to setup the nbd-internal sizes. A ioctl to set a size does not lead to a visible size change. The size of the block device will be kept at 0 until nbd is connected. As soon as it connects, the size will be changed to the real value and a uevent is created. When disconnecting, the blockdevice is set to 0 size and another uevent is generated. Signed-off-by: Markus Pargmann --- drivers/block/nbd.c | 79 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 4c5d94146aa3..f6b51d76e578 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -100,6 +100,11 @@ static inline struct device *nbd_to_dev(struct nbd_device *nbd) return disk_to_dev(nbd->disk); } +static bool nbd_is_connected(struct nbd_device *nbd) +{ + return !!nbd->task_recv; +} + static const char *nbdcmd_to_ascii(int cmd) { switch (cmd) { @@ -112,6 +117,42 @@ static const char *nbdcmd_to_ascii(int cmd) return "invalid"; } +static int nbd_size_clear(struct nbd_device *nbd, struct block_device *bdev) +{ + bdev->bd_inode->i_size = 0; + set_capacity(nbd->disk, 0); + kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); + + return 0; +} + +static void nbd_size_update(struct nbd_device *nbd, struct block_device *bdev) +{ + if (!nbd_is_connected(nbd)) + return; + + bdev->bd_inode->i_size = nbd->bytesize; + set_capacity(nbd->disk, nbd->bytesize >> 9); + kobject_uevent(&nbd_to_dev(nbd)->kobj, KOBJ_CHANGE); +} + +static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev, + int blocksize, int nr_blocks) +{ + int ret; + + ret = set_blocksize(bdev, blocksize); + if (ret) + return ret; + + nbd->blksize = blocksize; + nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks; + + nbd_size_update(nbd, bdev); + + return 0; +} + static void nbd_end_request(struct nbd_device *nbd, struct request *req) { int error = req->errors ? -EIO : 0; @@ -401,7 +442,7 @@ static struct device_attribute pid_attr = { .show = pid_show, }; -static int nbd_thread_recv(struct nbd_device *nbd) +static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev) { struct request *req; int ret; @@ -421,6 +462,8 @@ static int nbd_thread_recv(struct nbd_device *nbd) return ret; } + nbd_size_update(nbd, bdev); + while (1) { req = nbd_read_stat(nbd); if (IS_ERR(req)) { @@ -431,6 +474,8 @@ static int nbd_thread_recv(struct nbd_device *nbd) nbd_end_request(nbd, req); } + nbd_size_clear(nbd, bdev); + device_remove_file(disk_to_dev(nbd->disk), &pid_attr); nbd->task_recv = NULL; @@ -707,20 +752,19 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, return err; } - case NBD_SET_BLKSIZE: - nbd->blksize = arg; - nbd->bytesize &= ~(nbd->blksize-1); - bdev->bd_inode->i_size = nbd->bytesize; - set_blocksize(bdev, nbd->blksize); - set_capacity(nbd->disk, nbd->bytesize >> 9); - return 0; + case NBD_SET_BLKSIZE: { + loff_t bsize = nbd->bytesize; + do_div(bsize, arg); + + return nbd_size_set(nbd, bdev, arg, bsize); + } case NBD_SET_SIZE: - nbd->bytesize = arg & ~(nbd->blksize-1); - bdev->bd_inode->i_size = nbd->bytesize; - set_blocksize(bdev, nbd->blksize); - set_capacity(nbd->disk, nbd->bytesize >> 9); - return 0; + return nbd_size_set(nbd, bdev, nbd->blksize, + arg / nbd->blksize); + + case NBD_SET_SIZE_BLOCKS: + return nbd_size_set(nbd, bdev, nbd->blksize, arg); case NBD_SET_TIMEOUT: nbd->xmit_timeout = arg * HZ; @@ -736,13 +780,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, nbd->flags = arg; return 0; - case NBD_SET_SIZE_BLOCKS: - nbd->bytesize = ((u64) arg) * nbd->blksize; - bdev->bd_inode->i_size = nbd->bytesize; - set_blocksize(bdev, nbd->blksize); - set_capacity(nbd->disk, nbd->bytesize >> 9); - return 0; - case NBD_DO_IT: { struct task_struct *thread; int error; @@ -764,7 +801,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, } nbd_dev_dbg_init(nbd); - error = nbd_thread_recv(nbd); + error = nbd_thread_recv(nbd, bdev); nbd_dev_dbg_close(nbd); kthread_stop(thread); -- cgit From fc4fa6e112c0f999fab022a4eb7f6614bb47c7ab Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Sun, 13 Dec 2015 15:26:11 +0900 Subject: treewide: Fix typo in printk This patch fix spelling typos found in printk and Kconfig. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina --- drivers/atm/firestream.c | 2 +- drivers/crypto/nx/nx-842.c | 2 +- drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c | 2 +- drivers/input/touchscreen/wdt87xx_i2c.c | 2 +- drivers/net/ethernet/nuvoton/w90p910_ether.c | 2 +- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c | 2 +- drivers/usb/gadget/legacy/Kconfig | 3 +-- kernel/time/timekeeping.c | 2 +- lib/842/842_decompress.c | 2 +- net/openvswitch/vport-geneve.c | 2 +- tools/testing/selftests/timers/alarmtimer-suspend.c | 2 +- 11 files changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 82f2ae0d7cc4..a969a7e443be 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -168,7 +168,7 @@ static char *res_strings[] = { "reserved 14", "Unrecognized cell", "reserved 16", - "reassemby abort: AAL5 abort", + "reassembly abort: AAL5 abort", "packet purged", "packet ageing timeout", "channel ageing timeout", diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c index 046c1c45411b..d94e25df503b 100644 --- a/drivers/crypto/nx/nx-842.c +++ b/drivers/crypto/nx/nx-842.c @@ -308,7 +308,7 @@ int nx842_crypto_compress(struct crypto_tfm *tfm, h = !n && add_header ? hdrsize : 0; if (ignore) - pr_warn("interal error, ignore is set %x\n", ignore); + pr_warn("internal error, ignore is set %x\n", ignore); ret = compress(ctx, &p, &hdr->group[n], &c, &ignore, h); if (ret) diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c index 85dc3f989ff7..704d08744116 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c @@ -64,7 +64,7 @@ const char *usnic_ib_qp_grp_state_to_string(enum ib_qp_state state) case IB_QPS_ERR: return "ERR"; default: - return "UNKOWN STATE"; + return "UNKNOWN STATE"; } } diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index 515c20a6e10f..73861ad22df4 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c @@ -848,7 +848,7 @@ static int wdt87xx_do_update_firmware(struct i2c_client *client, error = wdt87xx_get_sysparam(client, &wdt->param); if (error) dev_err(&client->dev, - "failed to refresh system paramaters: %d\n", error); + "failed to refresh system parameters: %d\n", error); out: enable_irq(client->irq); mutex_unlock(&wdt->fw_mutex); diff --git a/drivers/net/ethernet/nuvoton/w90p910_ether.c b/drivers/net/ethernet/nuvoton/w90p910_ether.c index afa445842f3e..52d9a94aebb9 100644 --- a/drivers/net/ethernet/nuvoton/w90p910_ether.c +++ b/drivers/net/ethernet/nuvoton/w90p910_ether.c @@ -1038,7 +1038,7 @@ static int w90p910_ether_probe(struct platform_device *pdev) error = register_netdev(dev); if (error != 0) { - dev_err(&pdev->dev, "Regiter EMC w90p910 FAILED\n"); + dev_err(&pdev->dev, "Register EMC w90p910 FAILED\n"); error = -ENODEV; goto failed_put_rmiiclk; } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index b57cfd965196..95dcbff4673b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -626,7 +626,7 @@ static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw) rtl_dm_dig->min_undec_pwdb_for_dm = rtlpriv->dm.entry_min_undec_sm_pwdb; RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, - "AP Ext Port or disconnet PWDB = 0x%x\n", + "AP Ext Port or disconnect PWDB = 0x%x\n", rtl_dm_dig->min_undec_pwdb_for_dm); } RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index 4d682ad7bf23..fb1cdd9af472 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -103,8 +103,7 @@ config USB_ETH - CDC Ethernet Emulation Model (EEM) is a newer standard that has a simpler interface that can be used by more USB hardware. - RNDIS support is an additional option, more demanding than than - subset. + RNDIS support is an additional option, more demanding than subset. Within the USB device, this gadget driver exposes a network device "usbX", where X depends on what other networking devices you have. diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index b1356b7ae570..0d4cc7601df7 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -131,7 +131,7 @@ static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) printk_deferred(" timekeeping: Your kernel is sick, but tries to cope by capping time updates\n"); } else { if (offset > (max_cycles >> 1)) { - printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the the '%s' clock's 50%% safety margin (%lld)\n", + printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the '%s' clock's 50%% safety margin (%lld)\n", offset, name, max_cycles >> 1); printk_deferred(" timekeeping: Your kernel is still fine, but is feeling a bit nervous\n"); } diff --git a/lib/842/842_decompress.c b/lib/842/842_decompress.c index 8881dad2a6a0..a2a941f8112d 100644 --- a/lib/842/842_decompress.c +++ b/lib/842/842_decompress.c @@ -250,7 +250,7 @@ static int do_op(struct sw842_param *p, u8 o) case OP_ACTION_NOOP: break; default: - pr_err("Interal error, invalid op %x\n", op); + pr_err("Internal error, invalid op %x\n", op); return -EINVAL; } diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index efb736bb6855..69f1de58a3b4 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c @@ -133,6 +133,6 @@ static void __exit ovs_geneve_tnl_exit(void) module_init(ovs_geneve_tnl_init); module_exit(ovs_geneve_tnl_exit); -MODULE_DESCRIPTION("OVS: Geneve swiching port"); +MODULE_DESCRIPTION("OVS: Geneve switching port"); MODULE_LICENSE("GPL"); MODULE_ALIAS("vport-type-5"); diff --git a/tools/testing/selftests/timers/alarmtimer-suspend.c b/tools/testing/selftests/timers/alarmtimer-suspend.c index 72cacf5383dd..2b361b830395 100644 --- a/tools/testing/selftests/timers/alarmtimer-suspend.c +++ b/tools/testing/selftests/timers/alarmtimer-suspend.c @@ -153,7 +153,7 @@ int main(void) alarmcount = 0; if (timer_create(alarm_clock_id, &se, &tm1) == -1) { - printf("timer_create failled, %s unspported?\n", + printf("timer_create failed, %s unsupported?\n", clockstring(alarm_clock_id)); break; } -- cgit From 971cc8767310df98d416c8cceed69bf7ac150451 Mon Sep 17 00:00:00 2001 From: Fengguang Wu Date: Fri, 18 Dec 2015 15:51:24 +0800 Subject: MAINTAINERS: add git URL for APM driver CC: Jiri Kosina Signed-off-by: Fengguang Wu Signed-off-by: Jiri Kosina --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index f56a10a3eabc..1ef51f9ddb41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -766,6 +766,7 @@ F: sound/aoa/ APM DRIVER M: Jiri Kosina S: Odd fixes +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git F: arch/x86/kernel/apm_32.c F: include/linux/apm_bios.h F: include/uapi/linux/apm_bios.h -- cgit From bdb428c82aab5d8aba6fbb29dde2cf678eadc432 Mon Sep 17 00:00:00 2001 From: Bogdan Sikora Date: Sun, 27 Dec 2015 14:58:23 +0100 Subject: lib+mm: fix few spelling mistakes All are in comments. Signed-off-by: Bogdan Sikora Cc: Cc: Rafael Aquini Cc: Kent Overstreet Cc: Jan Kara [jkosina@suse.cz: more fixup] Acked-by: Rafael Aquini Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- lib/flex_proportions.c | 2 +- lib/percpu-refcount.c | 2 +- mm/balloon_compaction.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/flex_proportions.c b/lib/flex_proportions.c index 8f25652f40d4..a71cf1bdd4c9 100644 --- a/lib/flex_proportions.c +++ b/lib/flex_proportions.c @@ -17,7 +17,7 @@ * * \Sum_{j} p_{j} = 1, * - * This formula can be straightforwardly computed by maintaing denominator + * This formula can be straightforwardly computed by maintaining denominator * (let's call it 'd') and for each event type its numerator (let's call it * 'n_j'). When an event of type 'j' happens, we simply need to do: * n_j++; d++; diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c index 6111bcb28376..27fe74948882 100644 --- a/lib/percpu-refcount.c +++ b/lib/percpu-refcount.c @@ -12,7 +12,7 @@ * particular cpu can (and will) wrap - this is fine, when we go to shutdown the * percpu counters will all sum to the correct value * - * (More precisely: because moduler arithmatic is commutative the sum of all the + * (More precisely: because modular arithmetic is commutative the sum of all the * percpu_count vars will be equal to what it would have been if all the gets * and puts were done to a single integer, even if some of the percpu integers * overflow or underflow). diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c index d3116be5a00f..59c2bc8a1efc 100644 --- a/mm/balloon_compaction.c +++ b/mm/balloon_compaction.c @@ -13,10 +13,10 @@ /* * balloon_page_enqueue - allocates a new page and inserts it into the balloon * page list. - * @b_dev_info: balloon device decriptor where we will insert a new page to + * @b_dev_info: balloon device descriptor where we will insert a new page to * * Driver must call it to properly allocate a new enlisted balloon page - * before definetively removing it from the guest system. + * before definitively removing it from the guest system. * This function returns the page address for the recently enqueued page or * NULL in the case we fail to allocate a new page this turn. */ -- cgit From 11f0090e266ca9b646d365fa4201259a89fe903d Mon Sep 17 00:00:00 2001 From: Manuel Pégourié-Gonnard Date: Mon, 28 Dec 2015 11:33:30 +0100 Subject: Docs: fix missing word in REPORTING-BUGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel versions, not the bugs, are listed on kernel.org Signed-off-by: Manuel Pégourié-Gonnard Cc: trivial@kernel.org Signed-off-by: Jiri Kosina --- REPORTING-BUGS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/REPORTING-BUGS b/REPORTING-BUGS index 0cb8cdfa63bc..914baf9cf5fa 100644 --- a/REPORTING-BUGS +++ b/REPORTING-BUGS @@ -9,7 +9,7 @@ Please see https://www.kernel.org/ for a list of supported kernels. Any kernel marked with [EOL] is "end of life" and will not have any fixes backported to it. -If you've found a bug on a kernel version isn't listed on kernel.org, +If you've found a bug on a kernel version that isn't listed on kernel.org, contact your Linux distribution or embedded vendor for support. Alternatively, you can attempt to run one of the supported stable or -rc kernels, and see if you can reproduce the bug on that. It's preferable -- cgit From 34fd3e142afb13d22ee4568ae6e151f4d6896c20 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Tue, 5 Jan 2016 12:29:17 +0900 Subject: drm/i915 Fix typos in i915_gem_fence.c This patch fix some spelling typos found in Documentation/Docbook gpu/ch04s03.html. This file was generated from comments within source, so I have to fix typos in i915_gem_fence.c. Signed-off-by: Masanari Iida Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina --- drivers/gpu/drm/i915/i915_gem_fence.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index af1f8c461060..6f7249b00d4c 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -34,8 +34,8 @@ * set of these objects. * * Fences are used to detile GTT memory mappings. They're also connected to the - * hardware frontbuffer render tracking and hence interract with frontbuffer - * conmpression. Furthermore on older platforms fences are required for tiled + * hardware frontbuffer render tracking and hence interact with frontbuffer + * compression. Furthermore on older platforms fences are required for tiled * objects used by the display engine. They can also be used by the render * engine - they're required for blitter commands and are optional for render * commands. But on gen4+ both display (with the exception of fbc) and rendering @@ -46,8 +46,8 @@ * * Finally note that because fences are such a restricted resource they're * dynamically associated with objects. Furthermore fence state is committed to - * the hardware lazily to avoid unecessary stalls on gen2/3. Therefore code must - * explictly call i915_gem_object_get_fence() to synchronize fencing status + * the hardware lazily to avoid unnecessary stalls on gen2/3. Therefore code must + * explicitly call i915_gem_object_get_fence() to synchronize fencing status * for cpu access. Also note that some code wants an unfenced view, for those * cases the fence can be removed forcefully with i915_gem_object_put_fence(). * @@ -532,7 +532,7 @@ void i915_gem_restore_fences(struct drm_device *dev) * required. * * When bit 17 is XORed in, we simply refuse to tile at all. Bit - * 17 is not just a page offset, so as we page an objet out and back in, + * 17 is not just a page offset, so as we page an object out and back in, * individual pages in it will have different bit 17 addresses, resulting in * each 64 bytes being swapped with its neighbor! * -- cgit From d00cd819d7dfb1a24d814457f47ff4d6c7be152c Mon Sep 17 00:00:00 2001 From: Leslie Lau Date: Thu, 28 Jan 2016 21:17:22 -0800 Subject: drivers/rtc: broken link fix In drivers/rtc/rtc-rx8025.c is a broken link that is supposed to lead to a form allowing users to subscribe to the lm-sensors mailing list. The link leads to a page with a 404 error. I believe the link should be replaced with . Signed-off-by: Leslie Lau Signed-off-by: Jiri Kosina --- drivers/rtc/rtc-rx8025.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index 24c3d69ce1b9..5c2e9bcec091 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -7,7 +7,7 @@ * All rights reserved. * * Modified by fengjh at rising.com.cn - * + * * 2006.11 * * Code cleanup by Sergei Poselenov, -- cgit From b8659adda9e295eca0b10a67f3b15a8644c8ed6f Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 15 Feb 2016 16:27:58 +0800 Subject: spi: rockchip: disable runtime pm when in err case Before registering master, driver enables runtime pm. This patch pm_runtime_disable in err case while probing driver to balance pm reference count. Signed-off-by: Shawn Lin Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 79a8bc4f6cec..c0f9baee1e91 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -749,6 +749,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) return 0; err_register_master: + pm_runtime_disable(&pdev->dev); if (rs->dma_tx.ch) dma_release_channel(rs->dma_tx.ch); if (rs->dma_rx.ch) -- cgit From 844c9f476a43db0bdf61df409026a026ce98ec1b Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Mon, 15 Feb 2016 16:28:12 +0800 Subject: spi: rockchip: add missing spi_master_put Add missing spi_master_put for rockchip_spi_remove since it calls spi_master_get already. Signed-off-by: Shawn Lin Signed-off-by: Mark Brown --- drivers/spi/spi-rockchip.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index c0f9baee1e91..7cb1b2d710c1 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -779,6 +779,8 @@ static int rockchip_spi_remove(struct platform_device *pdev) if (rs->dma_rx.ch) dma_release_channel(rs->dma_rx.ch); + spi_master_put(master); + return 0; } -- cgit From a2826e662eb13a041078260692b4e023ed5cbf62 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Jan 2016 13:43:13 +0200 Subject: dmaengine: idma64: clear LLP_[SD]_EN bits in last descriptor The datasheet requires that the user must clear LLP_[SD]_EN bits whenever LLP.LOC is zero, i.e. in the last descriptor of a multi-block chain. Make the driver do this. Signed-off-by: Andy Shevchenko Signed-off-by: Vinod Koul --- drivers/dma/idma64.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 3cb7b2c78197..1953e57505f4 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -289,6 +289,9 @@ static void idma64_desc_fill(struct idma64_chan *idma64c, /* Trigger an interrupt after the last block is transfered */ lli->ctllo |= IDMA64C_CTLL_INT_EN; + + /* Disable LLP transfer in the last block */ + lli->ctllo &= ~(IDMA64C_CTLL_LLP_S_EN | IDMA64C_CTLL_LLP_D_EN); } static struct dma_async_tx_descriptor *idma64_prep_slave_sg( -- cgit From 679cfbf79b4eb7d7d81195e6b9ab98106fd78a54 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 10 Feb 2016 15:00:21 -0700 Subject: dmaengine: IOATDMA: Convert pci_pool_* to dma_pool_* Converting old pci_pool_* calls to "new" dma_pool_* to make everything uniform. Signed-off-by: Dave Jiang Signed-off-by: Vinod Koul --- drivers/dma/ioat/dma.c | 6 +++--- drivers/dma/ioat/dma.h | 4 ++-- drivers/dma/ioat/init.c | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 1d5df2ef148b..7a04c16a0bfa 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -298,14 +298,14 @@ ioat_alloc_ring_ent(struct dma_chan *chan, gfp_t flags) dma_addr_t phys; ioat_dma = to_ioatdma_device(chan->device); - hw = pci_pool_alloc(ioat_dma->dma_pool, flags, &phys); + hw = dma_pool_alloc(ioat_dma->dma_pool, flags, &phys); if (!hw) return NULL; memset(hw, 0, sizeof(*hw)); desc = kmem_cache_zalloc(ioat_cache, flags); if (!desc) { - pci_pool_free(ioat_dma->dma_pool, hw, phys); + dma_pool_free(ioat_dma->dma_pool, hw, phys); return NULL; } @@ -321,7 +321,7 @@ void ioat_free_ring_ent(struct ioat_ring_ent *desc, struct dma_chan *chan) struct ioatdma_device *ioat_dma; ioat_dma = to_ioatdma_device(chan->device); - pci_pool_free(ioat_dma->dma_pool, desc->hw, desc->txd.phys); + dma_pool_free(ioat_dma->dma_pool, desc->hw, desc->txd.phys); kmem_cache_free(ioat_cache, desc); } diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index b8f48074789f..f471092440d3 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -76,8 +76,8 @@ enum ioat_irq_mode { struct ioatdma_device { struct pci_dev *pdev; void __iomem *reg_base; - struct pci_pool *dma_pool; - struct pci_pool *completion_pool; + struct dma_pool *dma_pool; + struct dma_pool *completion_pool; #define MAX_SED_POOLS 5 struct dma_pool *sed_hw_pool[MAX_SED_POOLS]; struct dma_device dma_dev; diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 4ef0c5e07912..b02b63b719db 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -505,7 +505,7 @@ static int ioat_probe(struct ioatdma_device *ioat_dma) struct device *dev = &pdev->dev; /* DMA coherent memory pool for DMA descriptor allocations */ - ioat_dma->dma_pool = pci_pool_create("dma_desc_pool", pdev, + ioat_dma->dma_pool = dma_pool_create("dma_desc_pool", dev, sizeof(struct ioat_dma_descriptor), 64, 0); if (!ioat_dma->dma_pool) { @@ -513,7 +513,7 @@ static int ioat_probe(struct ioatdma_device *ioat_dma) goto err_dma_pool; } - ioat_dma->completion_pool = pci_pool_create("completion_pool", pdev, + ioat_dma->completion_pool = dma_pool_create("completion_pool", dev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES); @@ -546,9 +546,9 @@ static int ioat_probe(struct ioatdma_device *ioat_dma) err_self_test: ioat_disable_interrupts(ioat_dma); err_setup_interrupts: - pci_pool_destroy(ioat_dma->completion_pool); + dma_pool_destroy(ioat_dma->completion_pool); err_completion_pool: - pci_pool_destroy(ioat_dma->dma_pool); + dma_pool_destroy(ioat_dma->dma_pool); err_dma_pool: return err; } @@ -559,8 +559,8 @@ static int ioat_register(struct ioatdma_device *ioat_dma) if (err) { ioat_disable_interrupts(ioat_dma); - pci_pool_destroy(ioat_dma->completion_pool); - pci_pool_destroy(ioat_dma->dma_pool); + dma_pool_destroy(ioat_dma->completion_pool); + dma_pool_destroy(ioat_dma->dma_pool); } return err; @@ -576,8 +576,8 @@ static void ioat_dma_remove(struct ioatdma_device *ioat_dma) dma_async_device_unregister(dma); - pci_pool_destroy(ioat_dma->dma_pool); - pci_pool_destroy(ioat_dma->completion_pool); + dma_pool_destroy(ioat_dma->dma_pool); + dma_pool_destroy(ioat_dma->completion_pool); INIT_LIST_HEAD(&dma->channels); } @@ -669,7 +669,7 @@ static void ioat_free_chan_resources(struct dma_chan *c) kfree(ioat_chan->ring); ioat_chan->ring = NULL; ioat_chan->alloc_order = 0; - pci_pool_free(ioat_dma->completion_pool, ioat_chan->completion, + dma_pool_free(ioat_dma->completion_pool, ioat_chan->completion, ioat_chan->completion_dma); spin_unlock_bh(&ioat_chan->prep_lock); spin_unlock_bh(&ioat_chan->cleanup_lock); @@ -701,7 +701,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c) /* allocate a completion writeback area */ /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ ioat_chan->completion = - pci_pool_alloc(ioat_chan->ioat_dma->completion_pool, + dma_pool_alloc(ioat_chan->ioat_dma->completion_pool, GFP_KERNEL, &ioat_chan->completion_dma); if (!ioat_chan->completion) return -ENOMEM; -- cgit From cd60cd96137f6cb3ea82cace9225626619e7a52d Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 10 Feb 2016 15:00:26 -0700 Subject: dmaengine: IOATDMA: Removing descriptor ring reshape Moving to contingous memory backed descriptor rings. This makes is really difficult and complex to do reshape. Going to remove this as I don't think we need to do it anymore. Signed-off-by: Dave Jiang Signed-off-by: Vinod Koul --- drivers/dma/ioat/dma.c | 143 ------------------------------------------------ drivers/dma/ioat/dma.h | 5 -- drivers/dma/ioat/init.c | 10 +--- 3 files changed, 1 insertion(+), 157 deletions(-) diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 7a04c16a0bfa..9c4d3b20f520 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -332,9 +332,6 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) int descs = 1 << order; int i; - if (order > ioat_get_max_alloc_order()) - return NULL; - /* allocate the array to hold the software ring */ ring = kcalloc(descs, sizeof(*ring), flags); if (!ring) @@ -362,114 +359,6 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) return ring; } -static bool reshape_ring(struct ioatdma_chan *ioat_chan, int order) -{ - /* reshape differs from normal ring allocation in that we want - * to allocate a new software ring while only - * extending/truncating the hardware ring - */ - struct dma_chan *c = &ioat_chan->dma_chan; - const u32 curr_size = ioat_ring_size(ioat_chan); - const u16 active = ioat_ring_active(ioat_chan); - const u32 new_size = 1 << order; - struct ioat_ring_ent **ring; - u32 i; - - if (order > ioat_get_max_alloc_order()) - return false; - - /* double check that we have at least 1 free descriptor */ - if (active == curr_size) - return false; - - /* when shrinking, verify that we can hold the current active - * set in the new ring - */ - if (active >= new_size) - return false; - - /* allocate the array to hold the software ring */ - ring = kcalloc(new_size, sizeof(*ring), GFP_NOWAIT); - if (!ring) - return false; - - /* allocate/trim descriptors as needed */ - if (new_size > curr_size) { - /* copy current descriptors to the new ring */ - for (i = 0; i < curr_size; i++) { - u16 curr_idx = (ioat_chan->tail+i) & (curr_size-1); - u16 new_idx = (ioat_chan->tail+i) & (new_size-1); - - ring[new_idx] = ioat_chan->ring[curr_idx]; - set_desc_id(ring[new_idx], new_idx); - } - - /* add new descriptors to the ring */ - for (i = curr_size; i < new_size; i++) { - u16 new_idx = (ioat_chan->tail+i) & (new_size-1); - - ring[new_idx] = ioat_alloc_ring_ent(c, GFP_NOWAIT); - if (!ring[new_idx]) { - while (i--) { - u16 new_idx = (ioat_chan->tail+i) & - (new_size-1); - - ioat_free_ring_ent(ring[new_idx], c); - } - kfree(ring); - return false; - } - set_desc_id(ring[new_idx], new_idx); - } - - /* hw link new descriptors */ - for (i = curr_size-1; i < new_size; i++) { - u16 new_idx = (ioat_chan->tail+i) & (new_size-1); - struct ioat_ring_ent *next = - ring[(new_idx+1) & (new_size-1)]; - struct ioat_dma_descriptor *hw = ring[new_idx]->hw; - - hw->next = next->txd.phys; - } - } else { - struct ioat_dma_descriptor *hw; - struct ioat_ring_ent *next; - - /* copy current descriptors to the new ring, dropping the - * removed descriptors - */ - for (i = 0; i < new_size; i++) { - u16 curr_idx = (ioat_chan->tail+i) & (curr_size-1); - u16 new_idx = (ioat_chan->tail+i) & (new_size-1); - - ring[new_idx] = ioat_chan->ring[curr_idx]; - set_desc_id(ring[new_idx], new_idx); - } - - /* free deleted descriptors */ - for (i = new_size; i < curr_size; i++) { - struct ioat_ring_ent *ent; - - ent = ioat_get_ring_ent(ioat_chan, ioat_chan->tail+i); - ioat_free_ring_ent(ent, c); - } - - /* fix up hardware ring */ - hw = ring[(ioat_chan->tail+new_size-1) & (new_size-1)]->hw; - next = ring[(ioat_chan->tail+new_size) & (new_size-1)]; - hw->next = next->txd.phys; - } - - dev_dbg(to_dev(ioat_chan), "%s: allocated %d descriptors\n", - __func__, new_size); - - kfree(ioat_chan->ring); - ioat_chan->ring = ring; - ioat_chan->alloc_order = order; - - return true; -} - /** * ioat_check_space_lock - verify space and grab ring producer lock * @ioat: ioat,3 channel (ring) to operate on @@ -478,9 +367,6 @@ static bool reshape_ring(struct ioatdma_chan *ioat_chan, int order) int ioat_check_space_lock(struct ioatdma_chan *ioat_chan, int num_descs) __acquires(&ioat_chan->prep_lock) { - bool retry; - - retry: spin_lock_bh(&ioat_chan->prep_lock); /* never allow the last descriptor to be consumed, we need at * least one free at all times to allow for on-the-fly ring @@ -493,24 +379,8 @@ int ioat_check_space_lock(struct ioatdma_chan *ioat_chan, int num_descs) ioat_chan->produce = num_descs; return 0; /* with ioat->prep_lock held */ } - retry = test_and_set_bit(IOAT_RESHAPE_PENDING, &ioat_chan->state); spin_unlock_bh(&ioat_chan->prep_lock); - /* is another cpu already trying to expand the ring? */ - if (retry) - goto retry; - - spin_lock_bh(&ioat_chan->cleanup_lock); - spin_lock_bh(&ioat_chan->prep_lock); - retry = reshape_ring(ioat_chan, ioat_chan->alloc_order + 1); - clear_bit(IOAT_RESHAPE_PENDING, &ioat_chan->state); - spin_unlock_bh(&ioat_chan->prep_lock); - spin_unlock_bh(&ioat_chan->cleanup_lock); - - /* if we were able to expand the ring retry the allocation */ - if (retry) - goto retry; - dev_dbg_ratelimited(to_dev(ioat_chan), "%s: ring full! num_descs: %d (%x:%x:%x)\n", __func__, num_descs, ioat_chan->head, @@ -823,19 +693,6 @@ static void check_active(struct ioatdma_chan *ioat_chan) if (test_and_clear_bit(IOAT_CHAN_ACTIVE, &ioat_chan->state)) mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); - else if (ioat_chan->alloc_order > ioat_get_alloc_order()) { - /* if the ring is idle, empty, and oversized try to step - * down the size - */ - reshape_ring(ioat_chan, ioat_chan->alloc_order - 1); - - /* keep shrinking until we get back to our minimum - * default size - */ - if (ioat_chan->alloc_order > ioat_get_alloc_order()) - mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); - } - } void ioat_timer_event(unsigned long data) diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index f471092440d3..5f2f9fbcf184 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -100,7 +100,6 @@ struct ioatdma_chan { #define IOAT_COMPLETION_ACK 1 #define IOAT_RESET_PENDING 2 #define IOAT_KOBJ_INIT_FAIL 3 - #define IOAT_RESHAPE_PENDING 4 #define IOAT_RUN 5 #define IOAT_CHAN_ACTIVE 6 struct timer_list timer; @@ -302,10 +301,6 @@ static inline bool is_ioat_bug(unsigned long err) } #define IOAT_MAX_ORDER 16 -#define ioat_get_alloc_order() \ - (min(ioat_ring_alloc_order, IOAT_MAX_ORDER)) -#define ioat_get_max_alloc_order() \ - (min(ioat_ring_max_alloc_order, IOAT_MAX_ORDER)) static inline u32 ioat_ring_size(struct ioatdma_chan *ioat_chan) { diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index b02b63b719db..66369204896a 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -136,14 +136,6 @@ int ioat_pending_level = 4; module_param(ioat_pending_level, int, 0644); MODULE_PARM_DESC(ioat_pending_level, "high-water mark for pushing ioat descriptors (default: 4)"); -int ioat_ring_alloc_order = 8; -module_param(ioat_ring_alloc_order, int, 0644); -MODULE_PARM_DESC(ioat_ring_alloc_order, - "ioat+: allocate 2^n descriptors per channel (default: 8 max: 16)"); -int ioat_ring_max_alloc_order = IOAT_MAX_ORDER; -module_param(ioat_ring_max_alloc_order, int, 0644); -MODULE_PARM_DESC(ioat_ring_max_alloc_order, - "ioat+: upper limit for ring size (default: 16)"); static char ioat_interrupt_style[32] = "msix"; module_param_string(ioat_interrupt_style, ioat_interrupt_style, sizeof(ioat_interrupt_style), 0644); @@ -712,7 +704,7 @@ static int ioat_alloc_chan_resources(struct dma_chan *c) writel(((u64)ioat_chan->completion_dma) >> 32, ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH); - order = ioat_get_alloc_order(); + order = IOAT_MAX_ORDER; ring = ioat_alloc_ring(c, order, GFP_KERNEL); if (!ring) return -ENOMEM; -- cgit From dd4645ebb7d100bb04ba38ec58b499cbe95322fa Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 10 Feb 2016 15:00:32 -0700 Subject: dmaengine: IOATDMA: Allocate DMA descriptor ring in contig DMA memory Future IOATDMA hardware will take advantage of descriptors residing in contiguous memory. Setting the descriptor ring in max config DMA memory of 2MB. Each channel will need 2 of these chunks. This should provide 64k of 64B descriptors. Signed-off-by: Dave Jiang Signed-off-by: Vinod Koul --- drivers/dma/ioat/dma.c | 75 ++++++++++++++++++++++++++++++++++++++----------- drivers/dma/ioat/dma.h | 11 ++++++-- drivers/dma/ioat/hw.h | 2 ++ drivers/dma/ioat/init.c | 27 ++++++++---------- 4 files changed, 81 insertions(+), 34 deletions(-) diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c index 9c4d3b20f520..14ae9a0994fd 100644 --- a/drivers/dma/ioat/dma.c +++ b/drivers/dma/ioat/dma.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "dma.h" #include "registers.h" #include "hw.h" @@ -290,24 +291,30 @@ static dma_cookie_t ioat_tx_submit_unlock(struct dma_async_tx_descriptor *tx) } static struct ioat_ring_ent * -ioat_alloc_ring_ent(struct dma_chan *chan, gfp_t flags) +ioat_alloc_ring_ent(struct dma_chan *chan, int idx, gfp_t flags) { struct ioat_dma_descriptor *hw; struct ioat_ring_ent *desc; struct ioatdma_device *ioat_dma; + struct ioatdma_chan *ioat_chan = to_ioat_chan(chan); + int chunk; dma_addr_t phys; + u8 *pos; + off_t offs; ioat_dma = to_ioatdma_device(chan->device); - hw = dma_pool_alloc(ioat_dma->dma_pool, flags, &phys); - if (!hw) - return NULL; + + chunk = idx / IOAT_DESCS_PER_2M; + idx &= (IOAT_DESCS_PER_2M - 1); + offs = idx * IOAT_DESC_SZ; + pos = (u8 *)ioat_chan->descs[chunk].virt + offs; + phys = ioat_chan->descs[chunk].hw + offs; + hw = (struct ioat_dma_descriptor *)pos; memset(hw, 0, sizeof(*hw)); desc = kmem_cache_zalloc(ioat_cache, flags); - if (!desc) { - dma_pool_free(ioat_dma->dma_pool, hw, phys); + if (!desc) return NULL; - } dma_async_tx_descriptor_init(&desc->txd, chan); desc->txd.tx_submit = ioat_tx_submit_unlock; @@ -318,29 +325,63 @@ ioat_alloc_ring_ent(struct dma_chan *chan, gfp_t flags) void ioat_free_ring_ent(struct ioat_ring_ent *desc, struct dma_chan *chan) { - struct ioatdma_device *ioat_dma; - - ioat_dma = to_ioatdma_device(chan->device); - dma_pool_free(ioat_dma->dma_pool, desc->hw, desc->txd.phys); kmem_cache_free(ioat_cache, desc); } struct ioat_ring_ent ** ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) { + struct ioatdma_chan *ioat_chan = to_ioat_chan(c); struct ioat_ring_ent **ring; - int descs = 1 << order; - int i; + int total_descs = 1 << order; + int i, chunks; /* allocate the array to hold the software ring */ - ring = kcalloc(descs, sizeof(*ring), flags); + ring = kcalloc(total_descs, sizeof(*ring), flags); if (!ring) return NULL; - for (i = 0; i < descs; i++) { - ring[i] = ioat_alloc_ring_ent(c, flags); + + ioat_chan->desc_chunks = chunks = (total_descs * IOAT_DESC_SZ) / SZ_2M; + + for (i = 0; i < chunks; i++) { + struct ioat_descs *descs = &ioat_chan->descs[i]; + + descs->virt = dma_alloc_coherent(to_dev(ioat_chan), + SZ_2M, &descs->hw, flags); + if (!descs->virt && (i > 0)) { + int idx; + + for (idx = 0; idx < i; idx++) { + dma_free_coherent(to_dev(ioat_chan), SZ_2M, + descs->virt, descs->hw); + descs->virt = NULL; + descs->hw = 0; + } + + ioat_chan->desc_chunks = 0; + kfree(ring); + return NULL; + } + } + + for (i = 0; i < total_descs; i++) { + ring[i] = ioat_alloc_ring_ent(c, i, flags); if (!ring[i]) { + int idx; + while (i--) ioat_free_ring_ent(ring[i], c); + + for (idx = 0; idx < ioat_chan->desc_chunks; idx++) { + dma_free_coherent(to_dev(ioat_chan), + SZ_2M, + ioat_chan->descs[idx].virt, + ioat_chan->descs[idx].hw); + ioat_chan->descs[idx].virt = NULL; + ioat_chan->descs[idx].hw = 0; + } + + ioat_chan->desc_chunks = 0; kfree(ring); return NULL; } @@ -348,7 +389,7 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) } /* link descs */ - for (i = 0; i < descs-1; i++) { + for (i = 0; i < total_descs-1; i++) { struct ioat_ring_ent *next = ring[i+1]; struct ioat_dma_descriptor *hw = ring[i]->hw; diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h index 5f2f9fbcf184..57a9b83db455 100644 --- a/drivers/dma/ioat/dma.h +++ b/drivers/dma/ioat/dma.h @@ -62,7 +62,6 @@ enum ioat_irq_mode { * struct ioatdma_device - internal representation of a IOAT device * @pdev: PCI-Express device * @reg_base: MMIO register space base address - * @dma_pool: for allocating DMA descriptors * @completion_pool: DMA buffers for completion ops * @sed_hw_pool: DMA super descriptor pools * @dma_dev: embedded struct dma_device @@ -76,7 +75,6 @@ enum ioat_irq_mode { struct ioatdma_device { struct pci_dev *pdev; void __iomem *reg_base; - struct dma_pool *dma_pool; struct dma_pool *completion_pool; #define MAX_SED_POOLS 5 struct dma_pool *sed_hw_pool[MAX_SED_POOLS]; @@ -90,6 +88,11 @@ struct ioatdma_device { u32 cap; }; +struct ioat_descs { + void *virt; + dma_addr_t hw; +}; + struct ioatdma_chan { struct dma_chan dma_chan; void __iomem *reg_base; @@ -132,6 +135,8 @@ struct ioatdma_chan { u16 produce; struct ioat_ring_ent **ring; spinlock_t prep_lock; + struct ioat_descs descs[2]; + int desc_chunks; }; struct ioat_sysfs_entry { @@ -301,6 +306,8 @@ static inline bool is_ioat_bug(unsigned long err) } #define IOAT_MAX_ORDER 16 +#define IOAT_MAX_DESCS 65536 +#define IOAT_DESCS_PER_2M 32768 static inline u32 ioat_ring_size(struct ioatdma_chan *ioat_chan) { diff --git a/drivers/dma/ioat/hw.h b/drivers/dma/ioat/hw.h index 690e3b4f8202..8e67895bcca3 100644 --- a/drivers/dma/ioat/hw.h +++ b/drivers/dma/ioat/hw.h @@ -73,6 +73,8 @@ int system_has_dca_enabled(struct pci_dev *pdev); +#define IOAT_DESC_SZ 64 + struct ioat_dma_descriptor { uint32_t size; union { diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c index 66369204896a..efdee1a69fc4 100644 --- a/drivers/dma/ioat/init.c +++ b/drivers/dma/ioat/init.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "dma.h" #include "registers.h" #include "hw.h" @@ -496,15 +497,6 @@ static int ioat_probe(struct ioatdma_device *ioat_dma) struct pci_dev *pdev = ioat_dma->pdev; struct device *dev = &pdev->dev; - /* DMA coherent memory pool for DMA descriptor allocations */ - ioat_dma->dma_pool = dma_pool_create("dma_desc_pool", dev, - sizeof(struct ioat_dma_descriptor), - 64, 0); - if (!ioat_dma->dma_pool) { - err = -ENOMEM; - goto err_dma_pool; - } - ioat_dma->completion_pool = dma_pool_create("completion_pool", dev, sizeof(u64), SMP_CACHE_BYTES, @@ -512,7 +504,7 @@ static int ioat_probe(struct ioatdma_device *ioat_dma) if (!ioat_dma->completion_pool) { err = -ENOMEM; - goto err_completion_pool; + goto err_out; } ioat_enumerate_channels(ioat_dma); @@ -539,9 +531,7 @@ err_self_test: ioat_disable_interrupts(ioat_dma); err_setup_interrupts: dma_pool_destroy(ioat_dma->completion_pool); -err_completion_pool: - dma_pool_destroy(ioat_dma->dma_pool); -err_dma_pool: +err_out: return err; } @@ -552,7 +542,6 @@ static int ioat_register(struct ioatdma_device *ioat_dma) if (err) { ioat_disable_interrupts(ioat_dma); dma_pool_destroy(ioat_dma->completion_pool); - dma_pool_destroy(ioat_dma->dma_pool); } return err; @@ -568,7 +557,6 @@ static void ioat_dma_remove(struct ioatdma_device *ioat_dma) dma_async_device_unregister(dma); - dma_pool_destroy(ioat_dma->dma_pool); dma_pool_destroy(ioat_dma->completion_pool); INIT_LIST_HEAD(&dma->channels); @@ -658,6 +646,15 @@ static void ioat_free_chan_resources(struct dma_chan *c) ioat_free_ring_ent(desc, c); } + for (i = 0; i < ioat_chan->desc_chunks; i++) { + dma_free_coherent(to_dev(ioat_chan), SZ_2M, + ioat_chan->descs[i].virt, + ioat_chan->descs[i].hw); + ioat_chan->descs[i].virt = NULL; + ioat_chan->descs[i].hw = 0; + } + ioat_chan->desc_chunks = 0; + kfree(ioat_chan->ring); ioat_chan->ring = NULL; ioat_chan->alloc_order = 0; -- cgit From 41bd0c52c0d3e38202608cfe133faca9a0e53ae8 Mon Sep 17 00:00:00 2001 From: Helmut Buchsbaum Date: Thu, 4 Feb 2016 09:14:08 +0100 Subject: pinctrl: zynq: fix typo in group name for qspi1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to a typo Zynq pin controller does not set pin function of qspi1 when using function qspi1. So pin group for qspi1 has to be renamed to "qspi1_0_grp" as outlined in the corresponding bindings documentation. This also removes kernel message: zynq-pinctrl 700.pinctrl: invalid group "qspi1_0_grp" for function "qspi1" Signed-off-by: Helmut Buchsbaum Acked-by: Sören Brinkmann Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-zynq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c index d57b5eca7b98..76f1abd71e31 100644 --- a/drivers/pinctrl/pinctrl-zynq.c +++ b/drivers/pinctrl/pinctrl-zynq.c @@ -590,7 +590,7 @@ static const char * const usb1_groups[] = {"usb1_0_grp"}; static const char * const mdio0_groups[] = {"mdio0_0_grp"}; static const char * const mdio1_groups[] = {"mdio1_0_grp"}; static const char * const qspi0_groups[] = {"qspi0_0_grp"}; -static const char * const qspi1_groups[] = {"qspi0_1_grp"}; +static const char * const qspi1_groups[] = {"qspi1_0_grp"}; static const char * const qspi_fbclk_groups[] = {"qspi_fbclk_grp"}; static const char * const qspi_cs1_groups[] = {"qspi_cs1_grp"}; static const char * const spi0_groups[] = {"spi0_0_grp", "spi0_1_grp", -- cgit From 0998a436b1c2d8b7037c26736ee92417ca83d361 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 15 Feb 2016 11:24:58 -0300 Subject: regulator: max77686: Fix MAINTAINER entry to match driver The max77686 regulator driver was recently renamed to max77686-regulator but the entry in the MAINTAINERS file wasn't updated to match the driver. Reported-by: Krzysztof Kozlowski Signed-off-by: Javier Martinez Canillas Signed-off-by: Mark Brown --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 30aca4aa5467..b060628112cc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6913,7 +6913,7 @@ M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Supported F: drivers/*/max14577.c -F: drivers/*/max77686.c +F: drivers/*/max77686*.c F: drivers/*/max77693.c F: drivers/extcon/extcon-max14577.c F: drivers/extcon/extcon-max77693.c -- cgit From 424a6c607c169ca0ac8431424f28fc839b45b14c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 6 Feb 2016 22:56:36 +0800 Subject: pinctrl: Fix return value check in amd_gpio_probe() In case of error, the function devm_ioremap_nocache() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Signed-off-by: Wei Yongjun Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-amd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 657449431301..5c025f5b5048 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -753,8 +753,8 @@ static int amd_gpio_probe(struct platform_device *pdev) gpio_dev->base = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); - if (IS_ERR(gpio_dev->base)) - return PTR_ERR(gpio_dev->base); + if (!gpio_dev->base) + return -ENOMEM; irq_base = platform_get_irq(pdev, 0); if (irq_base < 0) { -- cgit From 64527e8a352968bda529f01df1c9dd5fe581ff04 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 15 Jan 2016 16:13:28 +0800 Subject: ASoC: topology: Add FE DAIs dynamically Topology will create FE DAIs dynamically from the PCM objects, and register them to the component. A PCM topoplogy object describes a FE DAI and DAI link. Later patch will add FE DAI links as well. Change tplg load ops for DAI: - Only process a DAI. - Pass the DAI driver pointer to the component driver for extra initialization. Signed-off-by: Mengdong Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/soc-topology.h | 15 ++--- include/sound/soc.h | 2 +- sound/soc/soc-topology.c | 129 +++++++++++++++++++++++++++++-------------- 3 files changed, 92 insertions(+), 54 deletions(-) diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h index 5b68e3f5aa85..78813adca2a1 100644 --- a/include/sound/soc-topology.h +++ b/include/sound/soc-topology.h @@ -56,12 +56,6 @@ struct snd_soc_dobj_widget { unsigned int kcontrol_enum:1; /* this widget is an enum kcontrol */ }; -/* dynamic PCM DAI object */ -struct snd_soc_dobj_pcm_dai { - struct snd_soc_tplg_pcm_dai *pd; - unsigned int count; -}; - /* generic dynamic object - all dynamic objects belong to this struct */ struct snd_soc_dobj { enum snd_soc_dobj_type type; @@ -71,7 +65,6 @@ struct snd_soc_dobj { union { struct snd_soc_dobj_control control; struct snd_soc_dobj_widget widget; - struct snd_soc_dobj_pcm_dai pcm_dai; }; void *private; /* core does not touch this */ }; @@ -126,10 +119,10 @@ struct snd_soc_tplg_ops { int (*widget_unload)(struct snd_soc_component *, struct snd_soc_dobj *); - /* FE - used for any driver specific init */ - int (*pcm_dai_load)(struct snd_soc_component *, - struct snd_soc_tplg_pcm_dai *pcm_dai, int num_fe); - int (*pcm_dai_unload)(struct snd_soc_component *, + /* FE DAI - used for any driver specific init */ + int (*dai_load)(struct snd_soc_component *, + struct snd_soc_dai_driver *dai_drv); + int (*dai_unload)(struct snd_soc_component *, struct snd_soc_dobj *); /* callback to handle vendor bespoke data */ diff --git a/include/sound/soc.h b/include/sound/soc.h index 7afb72ceac56..02b4a215fd75 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -27,7 +27,6 @@ #include #include #include -#include /* * Convenience kcontrol builders @@ -404,6 +403,7 @@ struct snd_soc_jack_zone; struct snd_soc_jack_pin; #include #include +#include struct snd_soc_jack_gpio; diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 6963ba20991c..446ac9a93aef 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -330,12 +330,12 @@ static int soc_tplg_widget_load(struct soc_tplg *tplg, return 0; } -/* pass dynamic FEs configurations to component driver */ -static int soc_tplg_pcm_dai_load(struct soc_tplg *tplg, - struct snd_soc_tplg_pcm_dai *pcm_dai, int num_pcm_dai) +/* pass DAI configurations to component driver for extra intialization */ +static int soc_tplg_dai_load(struct soc_tplg *tplg, + struct snd_soc_dai_driver *dai_drv) { - if (tplg->comp && tplg->ops && tplg->ops->pcm_dai_load) - return tplg->ops->pcm_dai_load(tplg->comp, pcm_dai, num_pcm_dai); + if (tplg->comp && tplg->ops && tplg->ops->dai_load) + return tplg->ops->dai_load(tplg->comp, dai_drv); return 0; } @@ -495,18 +495,21 @@ static void remove_widget(struct snd_soc_component *comp, /* widget w is freed by soc-dapm.c */ } -/* remove PCM DAI configurations */ -static void remove_pcm_dai(struct snd_soc_component *comp, +/* remove DAI configurations */ +static void remove_dai(struct snd_soc_component *comp, struct snd_soc_dobj *dobj, int pass) { + struct snd_soc_dai_driver *dai_drv = + container_of(dobj, struct snd_soc_dai_driver, dobj); + if (pass != SOC_TPLG_PASS_PCM_DAI) return; - if (dobj->ops && dobj->ops->pcm_dai_unload) - dobj->ops->pcm_dai_unload(comp, dobj); + if (dobj->ops && dobj->ops->dai_unload) + dobj->ops->dai_unload(comp, dobj); list_del(&dobj->list); - kfree(dobj); + kfree(dai_drv); } /* bind a kcontrol to it's IO handlers */ @@ -1544,18 +1547,79 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg) return 0; } -static int soc_tplg_pcm_dai_elems_load(struct soc_tplg *tplg, +static int soc_tplg_dai_create(struct soc_tplg *tplg, + struct snd_soc_tplg_pcm *pcm) +{ + struct snd_soc_dai_driver *dai_drv; + struct snd_soc_pcm_stream *stream; + struct snd_soc_tplg_stream_caps *caps; + int ret; + + dai_drv = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + if (dai_drv == NULL) + return -ENOMEM; + + dai_drv->name = pcm->dai_name; + dai_drv->id = pcm->dai_id; + + if (pcm->playback) { + stream = &dai_drv->playback; + caps = &pcm->caps[SND_SOC_TPLG_STREAM_PLAYBACK]; + + stream->stream_name = kstrdup(caps->name, GFP_KERNEL); + stream->channels_min = caps->channels_min; + stream->channels_max = caps->channels_max; + stream->rates = snd_pcm_rate_range_to_bits(caps->rate_min, + caps->rate_max); + stream->formats = caps->formats; + } + + if (pcm->capture) { + stream = &dai_drv->capture; + caps = &pcm->caps[SND_SOC_TPLG_STREAM_CAPTURE]; + + stream->stream_name = kstrdup(caps->name, GFP_KERNEL); + stream->channels_min = caps->channels_min; + stream->channels_max = caps->channels_max; + stream->rates = snd_pcm_rate_range_to_bits(caps->rate_min, + caps->rate_max); + stream->formats = caps->formats; + } + + /* pass control to component driver for optional further init */ + ret = soc_tplg_dai_load(tplg, dai_drv); + if (ret < 0) { + dev_err(tplg->comp->dev, "ASoC: DAI loading failed\n"); + kfree(dai_drv); + return ret; + } + + dai_drv->dobj.index = tplg->index; + dai_drv->dobj.ops = tplg->ops; + dai_drv->dobj.type = SND_SOC_DOBJ_PCM; + list_add(&dai_drv->dobj.list, &tplg->comp->dobj_list); + + /* register the DAI to the component */ + return snd_soc_register_dai(tplg->comp, dai_drv); +} + +static int soc_tplg_pcm_create(struct soc_tplg *tplg, + struct snd_soc_tplg_pcm *pcm) +{ + return soc_tplg_dai_create(tplg, pcm); +} + +static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_pcm_dai *pcm_dai; - struct snd_soc_dobj *dobj; + struct snd_soc_tplg_pcm *pcm; int count = hdr->count; - int ret; + int i; if (tplg->pass != SOC_TPLG_PASS_PCM_DAI) return 0; - pcm_dai = (struct snd_soc_tplg_pcm_dai *)tplg->pos; + pcm = (struct snd_soc_tplg_pcm *)tplg->pos; if (soc_tplg_check_elem_count(tplg, sizeof(struct snd_soc_tplg_pcm), count, @@ -1565,31 +1629,16 @@ static int soc_tplg_pcm_dai_elems_load(struct soc_tplg *tplg, return -EINVAL; } + /* create the FE DAIs and DAI links */ + for (i = 0; i < count; i++) { + soc_tplg_pcm_create(tplg, pcm); + pcm++; + } + dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); tplg->pos += sizeof(struct snd_soc_tplg_pcm) * count; - dobj = kzalloc(sizeof(struct snd_soc_dobj), GFP_KERNEL); - if (dobj == NULL) - return -ENOMEM; - - /* Call the platform driver call back to register the dais */ - ret = soc_tplg_pcm_dai_load(tplg, pcm_dai, count); - if (ret < 0) { - dev_err(tplg->comp->dev, "ASoC: PCM DAI loading failed\n"); - goto err; - } - - dobj->type = get_dobj_type(hdr, NULL); - dobj->pcm_dai.count = count; - dobj->pcm_dai.pd = pcm_dai; - dobj->ops = tplg->ops; - dobj->index = tplg->index; - list_add(&dobj->list, &tplg->comp->dobj_list); return 0; - -err: - kfree(dobj); - return ret; } static int soc_tplg_manifest_load(struct soc_tplg *tplg, @@ -1681,9 +1730,7 @@ static int soc_tplg_load_header(struct soc_tplg *tplg, case SND_SOC_TPLG_TYPE_DAPM_WIDGET: return soc_tplg_dapm_widget_elems_load(tplg, hdr); case SND_SOC_TPLG_TYPE_PCM: - case SND_SOC_TPLG_TYPE_DAI_LINK: - case SND_SOC_TPLG_TYPE_CODEC_LINK: - return soc_tplg_pcm_dai_elems_load(tplg, hdr); + return soc_tplg_pcm_elems_load(tplg, hdr); case SND_SOC_TPLG_TYPE_MANIFEST: return soc_tplg_manifest_load(tplg, hdr); default: @@ -1841,9 +1888,7 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) remove_widget(comp, dobj, pass); break; case SND_SOC_DOBJ_PCM: - case SND_SOC_DOBJ_DAI_LINK: - case SND_SOC_DOBJ_CODEC_LINK: - remove_pcm_dai(comp, dobj, pass); + remove_dai(comp, dobj, pass); break; default: dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", -- cgit From acfc7d46cddcf71cf18772bbe8717b84eac5f672 Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 15 Jan 2016 16:13:37 +0800 Subject: ASoC: topology: Add FE DAI links dynamically Topology will also create FE DAI links dynamically from the PCM objects. These links will be removed when the component is removed and its topology info is unloaded. The component driver can implement link_load/unload ops for extra intialization (e.g. error check) and destruction. Signed-off-by: Mengdong Lin Acked-by: Liam Girdwood Signed-off-by: Mark Brown --- include/sound/soc-topology.h | 6 ++++ sound/soc/soc-topology.c | 70 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h index 78813adca2a1..b897b9d63161 100644 --- a/include/sound/soc-topology.h +++ b/include/sound/soc-topology.h @@ -125,6 +125,12 @@ struct snd_soc_tplg_ops { int (*dai_unload)(struct snd_soc_component *, struct snd_soc_dobj *); + /* DAI link - used for any driver specific init */ + int (*link_load)(struct snd_soc_component *, + struct snd_soc_dai_link *link); + int (*link_unload)(struct snd_soc_component *, + struct snd_soc_dobj *); + /* callback to handle vendor bespoke data */ int (*vendor_load)(struct snd_soc_component *, struct snd_soc_tplg_hdr *); diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 446ac9a93aef..0eb01e8155f1 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -340,6 +340,16 @@ static int soc_tplg_dai_load(struct soc_tplg *tplg, return 0; } +/* pass link configurations to component driver for extra intialization */ +static int soc_tplg_dai_link_load(struct soc_tplg *tplg, + struct snd_soc_dai_link *link) +{ + if (tplg->comp && tplg->ops && tplg->ops->link_load) + return tplg->ops->link_load(tplg->comp, link); + + return 0; +} + /* tell the component driver that all firmware has been loaded in this request */ static void soc_tplg_complete(struct soc_tplg *tplg) { @@ -512,6 +522,24 @@ static void remove_dai(struct snd_soc_component *comp, kfree(dai_drv); } +/* remove link configurations */ +static void remove_link(struct snd_soc_component *comp, + struct snd_soc_dobj *dobj, int pass) +{ + struct snd_soc_dai_link *link = + container_of(dobj, struct snd_soc_dai_link, dobj); + + if (pass != SOC_TPLG_PASS_PCM_DAI) + return; + + if (dobj->ops && dobj->ops->link_unload) + dobj->ops->link_unload(comp, dobj); + + list_del(&dobj->list); + snd_soc_remove_dai_link(comp->card, link); + kfree(link); +} + /* bind a kcontrol to it's IO handlers */ static int soc_tplg_kcontrol_bind_io(struct snd_soc_tplg_ctl_hdr *hdr, struct snd_kcontrol_new *k, @@ -1603,10 +1631,47 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg, return snd_soc_register_dai(tplg->comp, dai_drv); } +static int soc_tplg_link_create(struct soc_tplg *tplg, + struct snd_soc_tplg_pcm *pcm) +{ + struct snd_soc_dai_link *link; + int ret; + + link = kzalloc(sizeof(struct snd_soc_dai_link), GFP_KERNEL); + if (link == NULL) + return -ENOMEM; + + link->name = pcm->pcm_name; + link->stream_name = pcm->pcm_name; + + /* pass control to component driver for optional further init */ + ret = soc_tplg_dai_link_load(tplg, link); + if (ret < 0) { + dev_err(tplg->comp->dev, "ASoC: FE link loading failed\n"); + kfree(link); + return ret; + } + + link->dobj.index = tplg->index; + link->dobj.ops = tplg->ops; + link->dobj.type = SND_SOC_DOBJ_DAI_LINK; + list_add(&link->dobj.list, &tplg->comp->dobj_list); + + snd_soc_add_dai_link(tplg->comp->card, link); + return 0; +} + +/* create a FE DAI and DAI link from the PCM object */ static int soc_tplg_pcm_create(struct soc_tplg *tplg, struct snd_soc_tplg_pcm *pcm) { - return soc_tplg_dai_create(tplg, pcm); + int ret; + + ret = soc_tplg_dai_create(tplg, pcm); + if (ret < 0) + return ret; + + return soc_tplg_link_create(tplg, pcm); } static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, @@ -1890,6 +1955,9 @@ int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index) case SND_SOC_DOBJ_PCM: remove_dai(comp, dobj, pass); break; + case SND_SOC_DOBJ_DAI_LINK: + remove_link(comp, dobj, pass); + break; default: dev_err(comp->dev, "ASoC: invalid component type %d for removal\n", dobj->type); -- cgit From 800c3a0e683601c4ede490e8525852e63b0f6615 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Wed, 10 Feb 2016 14:29:50 +0530 Subject: regmap: irq: add devm apis for regmap_{add,del}_irq_chip Add device managed APIs for regmap_add_irq_chip() and regmap_del_irq_chip() so that it can be managed by device framework for freeing it. This helps on following: 1. Maintaining the sequence of resource allocation and deallocation regmap_add_irq_chip(&d); devm_requested_threaded_irq(virq) On free path: regmap_del_irq_chip(d); and then removing the irq registration. On this case, regmap irq is deleted before the irq is free. This force to use normal irq registration. By using devm apis, the sequence can be maintain properly: devm_regmap_add_irq_chip(&d); devm_requested_threaded_irq(virq); and resource deallocation will be done in reverse order by device framework. 2. No need to delete the regmap_irq_chip in error path or remove callback and hence there is less code on this path. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/base/regmap/regmap-irq.c | 82 ++++++++++++++++++++++++++++++++++++++++ include/linux/regmap.h | 8 ++++ 2 files changed, 90 insertions(+) diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 7e1e9e86c70b..36d08ca2cbe2 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -695,6 +695,88 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d) } EXPORT_SYMBOL_GPL(regmap_del_irq_chip); +static void devm_regmap_irq_chip_release(struct device *dev, void *res) +{ + struct regmap_irq_chip_data *d = *(struct regmap_irq_chip_data **)res; + + regmap_del_irq_chip(d->irq, d); +} + +static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data) + +{ + struct regmap_irq_chip_data **r = res; + + if (!r || !*r) { + WARN_ON(!r || !*r); + return 0; + } + return *r == data; +} + +/** + * devm_regmap_add_irq_chip(): Resource manager regmap_add_irq_chip() + * + * @dev: The device pointer on which irq_chip belongs to. + * @map: The regmap for the device. + * @irq: The IRQ the device uses to signal interrupts + * @irq_flags: The IRQF_ flags to use for the primary interrupt. + * @chip: Configuration for the interrupt controller. + * @data: Runtime data structure for the controller, allocated on success + * + * Returns 0 on success or an errno on failure. + * + * The regmap_irq_chip data automatically be released when the device is + * unbound. + */ +int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data) +{ + struct regmap_irq_chip_data **ptr, *d; + int ret; + + ptr = devres_alloc(devm_regmap_irq_chip_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = regmap_add_irq_chip(map, irq, irq_flags, irq_base, + chip, &d); + if (ret < 0) { + devres_free(ptr); + return ret; + } + + *ptr = d; + devres_add(dev, ptr); + *data = d; + return 0; +} +EXPORT_SYMBOL_GPL(devm_regmap_add_irq_chip); + +/** + * devm_regmap_del_irq_chip(): Resource managed regmap_del_irq_chip() + * + * @dev: Device for which which resource was allocated. + * @irq: Primary IRQ for the device + * @d: regmap_irq_chip_data allocated by regmap_add_irq_chip() + */ +void devm_regmap_del_irq_chip(struct device *dev, int irq, + struct regmap_irq_chip_data *data) +{ + int rc; + + WARN_ON(irq != data->irq); + rc = devres_release(dev, devm_regmap_irq_chip_release, + devm_regmap_irq_chip_match, data); + + if (rc != 0) + WARN_ON(rc); +} +EXPORT_SYMBOL_GPL(devm_regmap_del_irq_chip); + /** * regmap_irq_chip_get_base(): Retrieve interrupt base for a regmap IRQ chip * diff --git a/include/linux/regmap.h b/include/linux/regmap.h index 18394343f489..de428962bfe6 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h @@ -868,6 +868,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, int irq_base, const struct regmap_irq_chip *chip, struct regmap_irq_chip_data **data); void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data); + +int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq, + int irq_flags, int irq_base, + const struct regmap_irq_chip *chip, + struct regmap_irq_chip_data **data); +void devm_regmap_del_irq_chip(struct device *dev, int irq, + struct regmap_irq_chip_data *data); + int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data); int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq); struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data); -- cgit From 88aa9f74e23543307f3475b64d65f85cb91729cd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Feb 2016 15:29:49 +0100 Subject: pinctrl: coh901: fix initconst annotation Clang correctly points out that the section attribute for u300_gpio_confdata is in the wrong place: drivers/pinctrl/pinctrl-coh901.c:130:37: error: '__section__' attribute only applies to functions and global variables This moves it from the type name to the variable, so it actually gets discarded. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-coh901.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c index cf7788df0f95..741b39eaeb8b 100644 --- a/drivers/pinctrl/pinctrl-coh901.c +++ b/drivers/pinctrl/pinctrl-coh901.c @@ -127,7 +127,7 @@ struct u300_gpio_confdata { } /* Initial configuration */ -static const struct __initconst u300_gpio_confdata +static const struct u300_gpio_confdata __initconst bs335_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { /* Port 0, pins 0-7 */ { -- cgit From 16dc661e0e4cba666a751f3f552f4e2de07a2397 Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Sun, 14 Feb 2016 14:29:20 +0800 Subject: regulator: hi655x: Document for hi655x regulator This patch adds the device tree binding documentation for hi655x PMIC regulator. Signed-off-by: Chen Feng Signed-off-by: Fei Wang Signed-off-by: Xinwei Kong Reviewed-by: Haojian Zhuang Signed-off-by: Mark Brown --- .../regulator/hisilicon,hi655x-regulator.txt | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt diff --git a/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt b/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt new file mode 100644 index 000000000000..14cfdc564159 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/hisilicon,hi655x-regulator.txt @@ -0,0 +1,29 @@ +Hisilicon Hi655x Voltage regulators + +Note: +The Hi655x regulator control is managed by Hi655x PMIC. +So the node of this regulator must be child node of Hi655x +PMIC node. + +The driver uses the regulator core framework, so please also +take the bindings of regulator.txt for reference. + +The valid names for regulators are: + +LDO2_2V8 LDO7_SDIO LDO10_2V85 LDO13_1V8 LDO14_2V8 +LDO15_1V8 LDO17_2V5 LDO19_3V0 LDO21_1V8 LDO22_1V2 + +Example: + pmic: pmic@f8000000 { + compatible = "hisilicon,hi655x-pmic"; + ... + regulators { + ldo2: LDO2@a21 { + regulator-name = "LDO2_2V8"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <3200000>; + regulator-enable-ramp-delay = <120>; + }; + ... + } + } -- cgit From 4618119b9be5f5075daf995b2ab807088b14961c Mon Sep 17 00:00:00 2001 From: Chen Feng Date: Sun, 14 Feb 2016 14:29:22 +0800 Subject: regulator: hi655x: enable regulator for hi655x PMIC Add the regulator driver for hi655x PMIC. Signed-off-by: Chen Feng Signed-off-by: Fei Wang Signed-off-by: Xinwei Kong Reviewed-by: Haojian Zhuang Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 ++ drivers/regulator/Makefile | 1 + drivers/regulator/hi655x-regulator.c | 227 +++++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 drivers/regulator/hi655x-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8155e80dd3f8..cd8ce7e9d451 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -261,6 +261,14 @@ config REGULATOR_HI6421 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All of them come with support to either ECO (idle) or sleep mode. +config REGULATOR_HI655X + tristate "Hisilicon HI655X PMIC regulators support" + depends on ARCH_HISI || COMPILE_TEST + depends on MFD_HI655X_PMIC && OF + help + This driver provides support for the voltage regulators of the + Hisilicon Hi655x PMIC device. + config REGULATOR_ISL9305 tristate "Intersil ISL9305 regulator" depends on I2C diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 980b1943fa81..422786cc4b74 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o +obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c new file mode 100644 index 000000000000..aca18466f522 --- /dev/null +++ b/drivers/regulator/hi655x-regulator.c @@ -0,0 +1,227 @@ +/* + * Device driver for regulators in Hi655x IC + * + * Copyright (c) 2016 Hisilicon. + * + * Authors: + * Chen Feng + * Fei Wang + * + * 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 +#include +#include +#include +#include + +struct hi655x_regulator { + unsigned int disable_reg; + unsigned int status_reg; + unsigned int ctrl_regs; + unsigned int ctrl_mask; + struct regulator_desc rdesc; +}; + +/* LDO7 & LDO10 */ +static const unsigned int ldo7_voltages[] = { + 1800000, 1850000, 2850000, 2900000, + 3000000, 3100000, 3200000, 3300000, +}; + +static const unsigned int ldo19_voltages[] = { + 1800000, 1850000, 1900000, 1750000, + 2800000, 2850000, 2900000, 3000000, +}; + +static const unsigned int ldo22_voltages[] = { + 900000, 1000000, 1050000, 1100000, + 1150000, 1175000, 1185000, 1200000, +}; + +enum hi655x_regulator_id { + HI655X_LDO0, + HI655X_LDO1, + HI655X_LDO2, + HI655X_LDO3, + HI655X_LDO4, + HI655X_LDO5, + HI655X_LDO6, + HI655X_LDO7, + HI655X_LDO8, + HI655X_LDO9, + HI655X_LDO10, + HI655X_LDO11, + HI655X_LDO12, + HI655X_LDO13, + HI655X_LDO14, + HI655X_LDO15, + HI655X_LDO16, + HI655X_LDO17, + HI655X_LDO18, + HI655X_LDO19, + HI655X_LDO20, + HI655X_LDO21, + HI655X_LDO22, +}; + +static int hi655x_is_enabled(struct regulator_dev *rdev) +{ + unsigned int value = 0; + + struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); + + regmap_read(rdev->regmap, regulator->status_reg, &value); + return (value & BIT(regulator->ctrl_mask)); +} + +static int hi655x_disable(struct regulator_dev *rdev) +{ + int ret = 0; + + struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); + + ret = regmap_write(rdev->regmap, regulator->disable_reg, + BIT(regulator->ctrl_mask)); + return ret; +} + +static struct regulator_ops hi655x_regulator_ops = { + .enable = regulator_enable_regmap, + .disable = hi655x_disable, + .is_enabled = hi655x_is_enabled, + .list_voltage = regulator_list_voltage_table, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +static struct regulator_ops hi655x_ldo_linear_ops = { + .enable = regulator_enable_regmap, + .disable = hi655x_disable, + .is_enabled = hi655x_is_enabled, + .list_voltage = regulator_list_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +}; + +#define HI655X_LDO(_ID, vreg, vmask, ereg, dreg, \ + sreg, cmask, vtable) { \ + .rdesc = { \ + .name = #_ID, \ + .of_match = of_match_ptr(#_ID), \ + .ops = &hi655x_regulator_ops, \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = HI655X_##_ID, \ + .owner = THIS_MODULE, \ + .n_voltages = ARRAY_SIZE(vtable), \ + .volt_table = vtable, \ + .vsel_reg = HI655X_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI655X_BUS_ADDR(ereg), \ + .enable_mask = BIT(cmask), \ + }, \ + .disable_reg = HI655X_BUS_ADDR(dreg), \ + .status_reg = HI655X_BUS_ADDR(sreg), \ + .ctrl_mask = cmask, \ +} + +#define HI655X_LDO_LINEAR(_ID, vreg, vmask, ereg, dreg, \ + sreg, cmask, minv, nvolt, vstep) { \ + .rdesc = { \ + .name = #_ID, \ + .of_match = of_match_ptr(#_ID), \ + .ops = &hi655x_ldo_linear_ops, \ + .regulators_node = of_match_ptr("regulators"), \ + .type = REGULATOR_VOLTAGE, \ + .id = HI655X_##_ID, \ + .owner = THIS_MODULE, \ + .min_uV = minv, \ + .n_voltages = nvolt, \ + .uV_step = vstep, \ + .vsel_reg = HI655X_BUS_ADDR(vreg), \ + .vsel_mask = vmask, \ + .enable_reg = HI655X_BUS_ADDR(ereg), \ + .enable_mask = BIT(cmask), \ + }, \ + .disable_reg = HI655X_BUS_ADDR(dreg), \ + .status_reg = HI655X_BUS_ADDR(sreg), \ + .ctrl_mask = cmask, \ +} + +static struct hi655x_regulator regulators[] = { + HI655X_LDO_LINEAR(LDO2, 0x72, 0x07, 0x29, 0x2a, 0x2b, 0x01, + 2500000, 8, 100000), + HI655X_LDO(LDO7, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x06, ldo7_voltages), + HI655X_LDO(LDO10, 0x78, 0x07, 0x29, 0x2a, 0x2b, 0x01, ldo7_voltages), + HI655X_LDO_LINEAR(LDO13, 0x7e, 0x07, 0x2c, 0x2d, 0x2e, 0x04, + 1600000, 8, 50000), + HI655X_LDO_LINEAR(LDO14, 0x7f, 0x07, 0x2c, 0x2d, 0x2e, 0x05, + 2500000, 8, 100000), + HI655X_LDO_LINEAR(LDO15, 0x80, 0x07, 0x2c, 0x2d, 0x2e, 0x06, + 1600000, 8, 50000), + HI655X_LDO_LINEAR(LDO17, 0x82, 0x07, 0x2f, 0x30, 0x31, 0x00, + 2500000, 8, 100000), + HI655X_LDO(LDO19, 0x84, 0x07, 0x2f, 0x30, 0x31, 0x02, ldo19_voltages), + HI655X_LDO_LINEAR(LDO21, 0x86, 0x07, 0x2f, 0x30, 0x31, 0x04, + 1650000, 8, 50000), + HI655X_LDO(LDO22, 0x87, 0x07, 0x2f, 0x30, 0x31, 0x05, ldo22_voltages), +}; + +static int hi655x_regulator_probe(struct platform_device *pdev) +{ + unsigned int i; + struct hi655x_regulator *regulator; + struct hi655x_pmic *pmic; + struct regulator_config config = { }; + struct regulator_dev *rdev; + + pmic = dev_get_drvdata(pdev->dev.parent); + if (!pmic) { + dev_err(&pdev->dev, "no pmic in the regulator parent node\n"); + return -ENODEV; + } + + regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL); + if (!regulator) + return -ENOMEM; + + platform_set_drvdata(pdev, regulator); + + config.dev = pdev->dev.parent; + config.regmap = pmic->regmap; + config.driver_data = regulator; + for (i = 0; i < ARRAY_SIZE(regulators); i++) { + rdev = devm_regulator_register(&pdev->dev, + ®ulators[i].rdesc, + &config); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "failed to register regulator %s\n", + regulator->rdesc.name); + return PTR_ERR(rdev); + } + } + return 0; +} + +static struct platform_driver hi655x_regulator_driver = { + .driver = { + .name = "hi655x-regulator", + }, + .probe = hi655x_regulator_probe, +}; +module_platform_driver(hi655x_regulator_driver); + +MODULE_AUTHOR("Chen Feng "); +MODULE_DESCRIPTION("Hisilicon Hi655x regulator driver"); +MODULE_LICENSE("GPL v2"); -- cgit From 08933418d71e52f60859319ef9fb4e6f754297c1 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sun, 14 Feb 2016 13:33:50 -0200 Subject: spi: core: Staticize __spi_split_transfer_maxsize() __spi_split_transfer_maxsize() can be made static as it is only used in this file. This fixes the following sparse warning: drivers/spi/spi.c:2266:5: warning: symbol '__spi_split_transfer_maxsize' was not declared. Should it be static? Signed-off-by: Fabio Estevam Signed-off-by: Mark Brown --- drivers/spi/spi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 801e8900898b..9490273ed811 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2241,11 +2241,11 @@ struct spi_replaced_transfers *spi_replace_transfers( } EXPORT_SYMBOL_GPL(spi_replace_transfers); -int __spi_split_transfer_maxsize(struct spi_master *master, - struct spi_message *msg, - struct spi_transfer **xferp, - size_t maxsize, - gfp_t gfp) +static int __spi_split_transfer_maxsize(struct spi_master *master, + struct spi_message *msg, + struct spi_transfer **xferp, + size_t maxsize, + gfp_t gfp) { struct spi_transfer *xfer = *xferp, *xfers; struct spi_replaced_transfers *srt; -- cgit From e0bbb38c2f3ae03ec6ee707767b8964df934818e Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 15 Feb 2016 18:31:22 +0800 Subject: regulator: axp20x: Use of_match name as default regulator name Originally the helper macros used uppercase regulator names, which are primarily used to expand to the regulator ID enum, as the default names. This is aestheticly unpleasent. Since the of_match bits are the same, just lowercase, use that as the default names instead. Signed-off-by: Chen-Yu Tsai Signed-off-by: Mark Brown --- drivers/regulator/axp20x-regulator.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 7d29893f833c..214e815e98eb 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -39,7 +39,7 @@ #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _enable_val, _disable_val) \ [_family##_##_id] = { \ - .name = #_id, \ + .name = (_match), \ .supply_name = (_supply), \ .of_match = of_match_ptr(_match), \ .regulators_node = of_match_ptr("regulators"), \ @@ -61,7 +61,7 @@ #define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask) \ [_family##_##_id] = { \ - .name = #_id, \ + .name = (_match), \ .supply_name = (_supply), \ .of_match = of_match_ptr(_match), \ .regulators_node = of_match_ptr("regulators"), \ @@ -80,7 +80,7 @@ #define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \ [_family##_##_id] = { \ - .name = #_id, \ + .name = (_match), \ .supply_name = (_supply), \ .of_match = of_match_ptr(_match), \ .regulators_node = of_match_ptr("regulators"), \ @@ -94,7 +94,7 @@ #define AXP_DESC_FIXED(_family, _id, _match, _supply, _volt) \ [_family##_##_id] = { \ - .name = #_id, \ + .name = (_match), \ .supply_name = (_supply), \ .of_match = of_match_ptr(_match), \ .regulators_node = of_match_ptr("regulators"), \ @@ -109,7 +109,7 @@ #define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \ _vreg, _vmask, _ereg, _emask) \ [_family##_##_id] = { \ - .name = #_id, \ + .name = (_match), \ .supply_name = (_supply), \ .of_match = of_match_ptr(_match), \ .regulators_node = of_match_ptr("regulators"), \ -- cgit From b8a54545b00cbf2aff743578c5c69aafdcde1d64 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:01 +0530 Subject: ASoC: hdac_hdmi: Add hotplug notification and read ELD This patch uses i915 component framework to register for hotplug notification. In the hotplug notification, driver reads pin sense and ELD by sending PIN_SENSE and ELD verbs over HDA bus. Once it identifies valid pin sense and valid ELD, store the ELD into the corresponding pin map buffer. Also read the monitor present sense during resume and ignore the ELD notify from graphics during PM as is done in legacy hda, commit 8ae743e82f0b ("ALSA: hda - Skip ELD notification during system suspend") Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 217 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 5a1ec0f7a1a6..fff225d6539c 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -34,6 +34,9 @@ #define HDA_MAX_CONNECTIONS 32 +#define ELD_MAX_SIZE 256 +#define ELD_FIXED_BYTES 20 + struct hdac_hdmi_cvt_params { unsigned int channels_min; unsigned int channels_max; @@ -48,11 +51,22 @@ struct hdac_hdmi_cvt { struct hdac_hdmi_cvt_params params; }; +struct hdac_hdmi_eld { + bool monitor_present; + bool eld_valid; + int eld_size; + char eld_buffer[ELD_MAX_SIZE]; +}; + struct hdac_hdmi_pin { struct list_head head; hda_nid_t nid; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + struct hdac_hdmi_eld eld; + struct hdac_ext_device *edev; + int repoll_count; + struct delayed_work work; }; struct hdac_hdmi_dai_pin_map { @@ -76,6 +90,80 @@ static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev) return to_ehdac_device(hdac); } + /* HDMI ELD routines */ +static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec, + hda_nid_t nid, int byte_index) +{ + unsigned int val; + + val = snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_ELDD, + byte_index); + + dev_dbg(&codec->dev, "HDMI: ELD data byte %d: 0x%x\n", + byte_index, val); + + return val; +} + +static int hdac_hdmi_get_eld_size(struct hdac_device *codec, hda_nid_t nid) +{ + return snd_hdac_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, + AC_DIPSIZE_ELD_BUF); +} + +/* + * This function queries the ELD size and ELD data and fills in the buffer + * passed by user + */ +static int hdac_hdmi_get_eld(struct hdac_device *codec, hda_nid_t nid, + unsigned char *buf, int *eld_size) +{ + int i, size, ret = 0; + + /* + * ELD size is initialized to zero in caller function. If no errors and + * ELD is valid, actual eld_size is assigned. + */ + + size = hdac_hdmi_get_eld_size(codec, nid); + if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) { + dev_err(&codec->dev, "HDMI: invalid ELD buf size %d\n", size); + return -ERANGE; + } + + /* set ELD buffer */ + for (i = 0; i < size; i++) { + unsigned int val = hdac_hdmi_get_eld_data(codec, nid, i); + /* + * Graphics driver might be writing to ELD buffer right now. + * Just abort. The caller will repoll after a while. + */ + if (!(val & AC_ELDD_ELD_VALID)) { + dev_err(&codec->dev, + "HDMI: invalid ELD data byte %d\n", i); + ret = -EINVAL; + goto error; + } + val &= AC_ELDD_ELD_DATA; + /* + * The first byte cannot be zero. This can happen on some DVI + * connections. Some Intel chips may also need some 250ms delay + * to return non-zero ELD data, even when the graphics driver + * correctly writes ELD content before setting ELD_valid bit. + */ + if (!val && !i) { + dev_err(&codec->dev, "HDMI: 0 ELD data\n"); + ret = -EINVAL; + goto error; + } + buf[i] = val; + } + + *eld_size = size; +error: + return ret; +} + static int hdac_hdmi_setup_stream(struct hdac_ext_device *hdac, hda_nid_t cvt_nid, hda_nid_t pin_nid, u32 stream_tag, int format) @@ -246,7 +334,6 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); struct hdac_hdmi_priv *hdmi = hdac->private_data; struct hdac_hdmi_dai_pin_map *dai_map; - int val; if (dai->id > 0) { dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); @@ -255,12 +342,14 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, dai_map = &hdmi->dai_map[dai->id]; - val = snd_hdac_codec_read(&hdac->hdac, dai_map->pin->nid, 0, - AC_VERB_GET_PIN_SENSE, 0); - dev_info(&hdac->hdac.dev, "Val for AC_VERB_GET_PIN_SENSE: %x\n", val); + if ((!dai_map->pin->eld.monitor_present) || + (!dai_map->pin->eld.eld_valid)) { + + dev_err(&hdac->hdac.dev, + "Failed: montior present? %d ELD valid?: %d\n", + dai_map->pin->eld.monitor_present, + dai_map->pin->eld.eld_valid); - if ((!(val & AC_PINSENSE_PRESENCE)) || (!(val & AC_PINSENSE_ELDV))) { - dev_err(&hdac->hdac.dev, "Monitor presence invalid with val: %x\n", val); return -ENODEV; } @@ -410,6 +499,71 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) return hdac_hdmi_query_cvt_params(&edev->hdac, cvt); } +static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) +{ + struct hdac_ext_device *edev = pin->edev; + int val; + + if (!edev) + return; + + pin->repoll_count = repoll; + + pm_runtime_get_sync(&edev->hdac.dev); + val = snd_hdac_codec_read(&edev->hdac, pin->nid, 0, + AC_VERB_GET_PIN_SENSE, 0); + + dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n", + val, pin->nid); + + pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE); + pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV); + + if (!pin->eld.monitor_present || !pin->eld.eld_valid) { + + dev_dbg(&edev->hdac.dev, "%s: disconnect for pin %d\n", + __func__, pin->nid); + goto put_hdac_device; + } + + if (pin->eld.monitor_present && pin->eld.eld_valid) { + /* TODO: use i915 component for reading ELD later */ + if (hdac_hdmi_get_eld(&edev->hdac, pin->nid, + pin->eld.eld_buffer, + &pin->eld.eld_size) == 0) { + + print_hex_dump_bytes("ELD: ", DUMP_PREFIX_OFFSET, + pin->eld.eld_buffer, pin->eld.eld_size); + } else { + pin->eld.monitor_present = false; + pin->eld.eld_valid = false; + } + } + + /* + * Sometimes the pin_sense may present invalid monitor + * present and eld_valid. If ELD data is not valid, loop few + * more times to get correct pin sense and valid ELD. + */ + if ((!pin->eld.monitor_present || !pin->eld.eld_valid) && repoll) + schedule_delayed_work(&pin->work, msecs_to_jiffies(300)); + +put_hdac_device: + pm_runtime_put_sync(&edev->hdac.dev); +} + +static void hdac_hdmi_repoll_eld(struct work_struct *work) +{ + struct hdac_hdmi_pin *pin = + container_of(to_delayed_work(work), struct hdac_hdmi_pin, work); + + /* picked from legacy HDA driver */ + if (pin->repoll_count++ > 6) + pin->repoll_count = 0; + + hdac_hdmi_present_sense(pin, pin->repoll_count); +} + static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) { struct hdac_hdmi_priv *hdmi = edev->private_data; @@ -424,6 +578,9 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) list_add_tail(&pin->head, &hdmi->pin_list); hdmi->num_pin++; + pin->edev = edev; + INIT_DELAYED_WORK(&pin->work, hdac_hdmi_repoll_eld); + return 0; } @@ -482,17 +639,65 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev) return hdac_hdmi_init_dai_map(edev); } +static void hdac_hdmi_eld_notify_cb(void *aptr, int port) +{ + struct hdac_ext_device *edev = aptr; + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct hdac_hdmi_pin *pin; + struct snd_soc_codec *codec = edev->scodec; + + /* Don't know how this mapping is derived */ + hda_nid_t pin_nid = port + 0x04; + + dev_dbg(&edev->hdac.dev, "%s: for pin: %d\n", __func__, pin_nid); + + /* + * skip notification during system suspend (but not in runtime PM); + * the state will be updated at resume. Also since the ELD and + * connection states are updated in anyway at the end of the resume, + * we can skip it when received during PM process. + */ + if (snd_power_get_state(codec->component.card->snd_card) != + SNDRV_CTL_POWER_D0) + return; + + if (atomic_read(&edev->hdac.in_pm)) + return; + + list_for_each_entry(pin, &hdmi->pin_list, head) { + if (pin->nid == pin_nid) + hdac_hdmi_present_sense(pin, 1); + } +} + +static struct i915_audio_component_audio_ops aops = { + .pin_eld_notify = hdac_hdmi_eld_notify_cb, +}; + static int hdmi_codec_probe(struct snd_soc_codec *codec) { struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); struct hdac_hdmi_priv *hdmi = edev->private_data; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(&codec->component); + struct hdac_hdmi_pin *pin; + int ret; edev->scodec = codec; create_fill_widget_route_map(dapm, &hdmi->dai_map[0]); + aops.audio_ptr = edev; + ret = snd_hdac_i915_register_notifier(&aops); + if (ret < 0) { + dev_err(&edev->hdac.dev, "notifier register failed: err: %d\n", + ret); + return ret; + } + + list_for_each_entry(pin, &hdmi->pin_list, head) + hdac_hdmi_present_sense(pin, 1); + /* Imp: Store the card pointer in hda_codec */ edev->card = dapm->card->snd_card; -- cgit From 2428bca305e082885e08e7f3399db616daf3a51a Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:02 +0530 Subject: ASoC: hdac_hdmi: Apply constraints based on ELD Uses the drm ELD core framework to apply rate and channel Also compute the format to be set based on ELD. Even though the channel constraint is based on ELD, infoframe is set with stereo only. Multichannel support will be added later. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 1 + sound/soc/codecs/hdac_hdmi.c | 51 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 50693c867e71..8c86239cc3f2 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -490,6 +490,7 @@ config SND_SOC_GTM601 config SND_SOC_HDAC_HDMI tristate select SND_HDA_EXT_CORE + select SND_PCM_ELD select HDMI config SND_SOC_ICS43432 diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index fff225d6539c..d22fa6b66c80 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -22,10 +22,12 @@ #include #include #include +#include #include #include #include #include +#include #include "../../hda/local.h" #define AMP_OUT_MUTE 0xb080 @@ -90,6 +92,45 @@ static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev) return to_ehdac_device(hdac); } +static unsigned int sad_format(const u8 *sad) +{ + return ((sad[0] >> 0x3) & 0x1f); +} + +static unsigned int sad_sample_bits_lpcm(const u8 *sad) +{ + return (sad[2] & 7); +} + +static int hdac_hdmi_eld_limit_formats(struct snd_pcm_runtime *runtime, + void *eld) +{ + u64 formats = SNDRV_PCM_FMTBIT_S16; + int i; + const u8 *sad, *eld_buf = eld; + + sad = drm_eld_sad(eld_buf); + if (!sad) + goto format_constraint; + + for (i = drm_eld_sad_count(eld_buf); i > 0; i--, sad += 3) { + if (sad_format(sad) == 1) { /* AUDIO_CODING_TYPE_LPCM */ + + /* + * the controller support 20 and 24 bits in 32 bit + * container so we set S32 + */ + if (sad_sample_bits_lpcm(sad) & 0x6) + formats |= SNDRV_PCM_FMTBIT_S32; + } + } + +format_constraint: + return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, + formats); + +} + /* HDMI ELD routines */ static unsigned int hdac_hdmi_get_eld_data(struct hdac_device *codec, hda_nid_t nid, int byte_index) @@ -334,6 +375,7 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); struct hdac_hdmi_priv *hdmi = hdac->private_data; struct hdac_hdmi_dai_pin_map *dai_map; + int ret; if (dai->id > 0) { dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); @@ -358,10 +400,13 @@ static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, 2); + ret = hdac_hdmi_eld_limit_formats(substream->runtime, + dai_map->pin->eld.eld_buffer); + if (ret < 0) + return ret; - return 0; + return snd_pcm_hw_constraint_eld(substream->runtime, + dai_map->pin->eld.eld_buffer); } static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, -- cgit From 1aa8ec255370d3e6f60dfa4a8cdd5e1357b1ab78 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:08 +0530 Subject: drm/edid: Add API to help find connection type To fill the audio infoframe it is required to identify the connection type as DP or HDMI. This patch adds an API which parses ELD and returns the display type connected. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Reviewed-by: Jani Nikula Cc: David Airlie Cc: dri-devel@lists.freedesktop.org Cc: Daniel Vetter Signed-off-by: Mark Brown --- include/drm/drm_edid.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 2af97691e878..dec6221e8198 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -403,6 +403,18 @@ static inline int drm_eld_size(const uint8_t *eld) return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4; } +/** + * drm_eld_get_conn_type - Get device type hdmi/dp connected + * @eld: pointer to an ELD memory structure + * + * The caller need to use %DRM_ELD_CONN_TYPE_HDMI or %DRM_ELD_CONN_TYPE_DP to + * identify the display type connected. + */ +static inline u8 drm_eld_get_conn_type(const uint8_t *eld) +{ + return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK; +} + struct edid *drm_do_get_edid(struct drm_connector *connector, int (*get_edid_block)(void *data, u8 *buf, unsigned int block, size_t len), -- cgit From 1ad826bad5bd0b6ccfb203f78c70302b764df0be Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Feb 2016 18:30:01 -0300 Subject: perf tests: Fix build on older systems where 'signal' is reserved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixing the following problems, for instance, on RHEL6.7: CC /tmp/build/perf/tests/bp_signal.o cc1: warnings being treated as errors tests/bp_signal.c: In function ‘__event’: tests/bp_signal.c:106: error: declaration of ‘signal’ shadows a global declaration /usr/include/signal.h:101: error: shadowed declaration is here tests/bp_signal.c: In function ‘bp_event’: tests/bp_signal.c:144: error: declaration of ‘signal’ shadows a global declaration /usr/include/signal.h:101: error: shadowed declaration is here tests/bp_signal.c: In function ‘wp_event’: tests/bp_signal.c:149: error: declaration of ‘signal’ shadows a global declaration /usr/include/signal.h:101: error: shadowed declaration is here mv: cannot stat `/tmp/build/perf/tests/.bp_signal.o.tmp': No such file or directory make[3]: *** [/tmp/build/perf/tests/bp_signal.o] Error 1 make[2]: *** [tests] Error 2 make[1]: *** [/tmp/build/perf/perf-in.o] Error 2 make[1]: *** Waiting for unfinished jobs.... Reported-by: Vinson Lee Cc: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: He Kuang Cc: Li Zefan Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Wang Nan Cc: Will Deacon Cc: pi3orama@163.com Fixes: 8fd34e1cce18 ("perf test: Improve bp_signal") Link: http://lkml.kernel.org/n/tip-wlpx6tik1b0jirlkw64bv400@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/tests/bp_signal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index 1d1bb489b4e8..e7664fe3bd33 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c @@ -103,7 +103,7 @@ static void sig_handler(int signum __maybe_unused, } } -static int __event(bool is_x, void *addr, int signal) +static int __event(bool is_x, void *addr, int sig) { struct perf_event_attr pe; int fd; @@ -133,7 +133,7 @@ static int __event(bool is_x, void *addr, int signal) } fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); - fcntl(fd, F_SETSIG, signal); + fcntl(fd, F_SETSIG, sig); fcntl(fd, F_SETOWN, getpid()); ioctl(fd, PERF_EVENT_IOC_RESET, 0); @@ -141,14 +141,14 @@ static int __event(bool is_x, void *addr, int signal) return fd; } -static int bp_event(void *addr, int signal) +static int bp_event(void *addr, int sig) { - return __event(true, addr, signal); + return __event(true, addr, sig); } -static int wp_event(void *addr, int signal) +static int wp_event(void *addr, int sig) { - return __event(false, addr, signal); + return __event(false, addr, sig); } static long long bp_count(int fd) -- cgit From 763dedfcda5f6c9294c4a5d048f5261f442cc1e8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 14 Feb 2016 00:19:07 +0800 Subject: spi: bcm2835: Remove unnecessary workaround to call gpio_set_value This should be fixed by commit 4c02cba18cc9 ("pinctrl: bcm2835: Fix initial value for direction_output") Signed-off-by: Axel Lin Acked-by: Martin Sperl Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index cf04960cc3e6..f35cc10772f6 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -727,11 +727,6 @@ static int bcm2835_spi_setup(struct spi_device *spi) spi->chip_select, spi->cs_gpio, err); return err; } - /* the implementation of pinctrl-bcm2835 currently does not - * set the GPIO value when using gpio_direction_output - * so we are setting it here explicitly - */ - gpio_set_value(spi->cs_gpio, (spi->mode & SPI_CS_HIGH) ? 0 : 1); return 0; } -- cgit From b4e2adef62062cf716d1c81adc12ad6def516f72 Mon Sep 17 00:00:00 2001 From: Stephan Olbrich Date: Sun, 14 Feb 2016 11:04:28 +0100 Subject: spi: bcm2835aux: set up spi-mode before asserting cs-gpio When using reverse polarity for clock (spi-cpol) on a device the clock line gets altered after chip-select has been asserted resulting in an additional clock beat, which confuses hardware. This happens due to the fact, the the hardware was initialized and reset at the begin and end of each transfer which results in default state for all lines except chip-select which is handled by the spi-subsystem as gpio-cs is used. To avoid this situation this patch moves the setup of polarity (spi-cpol and spi-cpha) outside of the chip-select into prepare_message, which is run prior to asserting chip-select. Signed-off-by: Stephan Olbrich Reviewed-by: Martin Sperl Tested-by: Martin Sperl Reviewed-by: Eric Anholt Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835aux.c | 57 +++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index e1b2fec1db63..a6e25c6c66ca 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -218,9 +218,9 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) BCM2835_AUX_SPI_CNTL1_IDLE); } - /* and if rx_len is 0 then wake up completion and disable spi */ + /* and if rx_len is 0 then disable interrupts and wake up completion */ if (!bs->rx_len) { - bcm2835aux_spi_reset_hw(bs); + bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); complete(&master->xfer_completion); } @@ -313,9 +313,6 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, } } - /* Transfer complete - reset SPI HW */ - bcm2835aux_spi_reset_hw(bs); - /* and return without waiting for completion */ return 0; } @@ -336,10 +333,6 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, * resulting (potentially) in more interrupts when transferring * more than 12 bytes */ - bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | - BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | - BCM2835_AUX_SPI_CNTL0_MSBF_OUT; - bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; /* set clock */ spi_hz = tfr->speed_hz; @@ -354,17 +347,13 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, } else { /* the slowest we can go */ speed = BCM2835_AUX_SPI_CNTL0_SPEED_MAX; } + /* mask out old speed from previous spi_transfer */ + bs->cntl[0] &= ~(BCM2835_AUX_SPI_CNTL0_SPEED); + /* set the new speed */ bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT; spi_used_hz = clk_hz / (2 * (speed + 1)); - /* handle all the modes */ - if (spi->mode & SPI_CPOL) - bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; - if (spi->mode & SPI_CPHA) - bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT | - BCM2835_AUX_SPI_CNTL0_CPHA_IN; - /* set transmit buffers and length */ bs->tx_buf = tfr->tx_buf; bs->rx_buf = tfr->rx_buf; @@ -388,6 +377,40 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); } +static int bcm2835aux_spi_prepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct spi_device *spi = msg->spi; + struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + + bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | + BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | + BCM2835_AUX_SPI_CNTL0_MSBF_OUT; + bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; + + /* handle all the modes */ + if (spi->mode & SPI_CPOL) + bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; + if (spi->mode & SPI_CPHA) + bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT | + BCM2835_AUX_SPI_CNTL0_CPHA_IN; + + bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); + bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); + + return 0; +} + +static int bcm2835aux_spi_unprepare_message(struct spi_master *master, + struct spi_message *msg) +{ + struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + + bcm2835aux_spi_reset_hw(bs); + + return 0; +} + static void bcm2835aux_spi_handle_err(struct spi_master *master, struct spi_message *msg) { @@ -416,6 +439,8 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) master->num_chipselect = -1; master->transfer_one = bcm2835aux_spi_transfer_one; master->handle_err = bcm2835aux_spi_handle_err; + master->prepare_message = bcm2835aux_spi_prepare_message; + master->unprepare_message = bcm2835aux_spi_unprepare_message; master->dev.of_node = pdev->dev.of_node; bs = spi_master_get_devdata(master); -- cgit From e9dd4edcc98593bbcdffc0c4f37545b8fd0ad3ea Mon Sep 17 00:00:00 2001 From: Stephan Olbrich Date: Sun, 14 Feb 2016 11:04:29 +0100 Subject: spi: bcm2835aux: fix CPOL/CPHA setting The auxiliary spi supports only CPHA=0 modes as the first bit is always output to the pin before the first clock cycle. In CPHA=1 modes the first clock edge outputs the second bit hence the slave can never read the first bit. Also the CPHA registers switch between clocking data in/out on rising/falling edge hence depend on the CPOL setting. Signed-off-by: Stephan Olbrich Reviewed-by: Eric Anholt Signed-off-by: Mark Brown --- drivers/spi/spi-bcm2835aux.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index a6e25c6c66ca..496f9adb9fc1 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -64,9 +64,9 @@ #define BCM2835_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 #define BCM2835_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 #define BCM2835_AUX_SPI_CNTL0_ENABLE 0x00000800 -#define BCM2835_AUX_SPI_CNTL0_CPHA_IN 0x00000400 +#define BCM2835_AUX_SPI_CNTL0_IN_RISING 0x00000400 #define BCM2835_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 -#define BCM2835_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 +#define BCM2835_AUX_SPI_CNTL0_OUT_RISING 0x00000100 #define BCM2835_AUX_SPI_CNTL0_CPOL 0x00000080 #define BCM2835_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 #define BCM2835_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F @@ -92,9 +92,6 @@ #define BCM2835_AUX_SPI_POLLING_LIMIT_US 30 #define BCM2835_AUX_SPI_POLLING_JIFFIES 2 -#define BCM2835_AUX_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \ - | SPI_NO_CS) - struct bcm2835aux_spi { void __iomem *regs; struct clk *clk; @@ -389,12 +386,12 @@ static int bcm2835aux_spi_prepare_message(struct spi_master *master, bs->cntl[1] = BCM2835_AUX_SPI_CNTL1_MSBF_IN; /* handle all the modes */ - if (spi->mode & SPI_CPOL) + if (spi->mode & SPI_CPOL) { bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPOL; - if (spi->mode & SPI_CPHA) - bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_CPHA_OUT | - BCM2835_AUX_SPI_CNTL0_CPHA_IN; - + bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_OUT_RISING; + } else { + bs->cntl[0] |= BCM2835_AUX_SPI_CNTL0_IN_RISING; + } bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]); @@ -434,7 +431,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, master); - master->mode_bits = BCM2835_AUX_SPI_MODE_BITS; + master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); master->bits_per_word_mask = SPI_BPW_MASK(8); master->num_chipselect = -1; master->transfer_one = bcm2835aux_spi_transfer_one; -- cgit From 112d125a89479519efc437b2961b8d4a98761c1b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Feb 2016 12:52:59 -0800 Subject: Revert "driver-core: platform: probe of-devices only using list of compatibles" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 67d02a1bbb334558e9380409a3cd426b36d4578b This should reallow binding of of-devices by name. It turned out that there are valid reasons (e.g. step by step conversion to device tree probing using auxdata) to bind of-instantiated devices to drivers by name. So revert to the original logic. Reported-by: Guenter Roeck Acked-by: Uwe Kleine-König Cc: Thierry Reding Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/base/platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1b5b7b5b50c0..f437afa17f2b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -949,8 +949,8 @@ static int platform_match(struct device *dev, struct device_driver *drv) return !strcmp(pdev->driver_override, drv->name); /* Attempt an OF style match first */ - if (pdev->dev.of_node) - return of_driver_match_device(dev, drv); + if (of_driver_match_device(dev, drv)) + return 1; /* Then try ACPI style match */ if (acpi_driver_match_device(dev, drv)) -- cgit From 211caab73b20dcc91ac103db0f68fe2388120d59 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:03 +0530 Subject: ASoC: hdac_hdmi: Enable DP1.2 and all converters/pins Skylake supports 3 pin and 3 converter widgets. But by default only one converter and pin widget are enabled. In skylake platform the DP port is on a different port which is not enabled by default. To enable playback on DP port, enable all pin and converter widget by sending a vendor VERB for a vendor widget to set required bits. As we are enabling the DP support enable the DP1.2 feature as well. Enabling DP1.2 and all widget changes are copied from patch_hdmi.c. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index d22fa6b66c80..b2e5e549b022 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -629,6 +629,46 @@ static int hdac_hdmi_add_pin(struct hdac_ext_device *edev, hda_nid_t nid) return 0; } +#define INTEL_VENDOR_NID 0x08 +#define INTEL_GET_VENDOR_VERB 0xf81 +#define INTEL_SET_VENDOR_VERB 0x781 +#define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */ +#define INTEL_EN_ALL_PIN_CVTS 0x01 /* enable 2nd & 3rd pins and convertors */ + +static void hdac_hdmi_skl_enable_all_pins(struct hdac_device *hdac) +{ + unsigned int vendor_param; + + vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, + INTEL_GET_VENDOR_VERB, 0); + if (vendor_param == -1 || vendor_param & INTEL_EN_ALL_PIN_CVTS) + return; + + vendor_param |= INTEL_EN_ALL_PIN_CVTS; + vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, + INTEL_SET_VENDOR_VERB, vendor_param); + if (vendor_param == -1) + return; +} + +static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac) +{ + unsigned int vendor_param; + + vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, + INTEL_GET_VENDOR_VERB, 0); + if (vendor_param == -1 || vendor_param & INTEL_EN_DP12) + return; + + /* enable DP1.2 mode */ + vendor_param |= INTEL_EN_DP12; + vendor_param = snd_hdac_codec_read(hdac, INTEL_VENDOR_NID, 0, + INTEL_SET_VENDOR_VERB, vendor_param); + if (vendor_param == -1) + return; + +} + /* * Parse all nodes and store the cvt/pin nids in array * Add one time initialization for pin and cvt widgets @@ -641,6 +681,9 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev) struct hdac_hdmi_priv *hdmi = edev->private_data; int ret; + hdac_hdmi_skl_enable_all_pins(hdac); + hdac_hdmi_skl_enable_dp12(hdac); + num_nodes = snd_hdac_get_sub_nodes(hdac, hdac->afg, &nid); if (!nid || num_nodes <= 0) { dev_warn(&hdac->dev, "HDMI: failed to get afg sub nodes\n"); -- cgit From 17a42c4500b05a6af4c32eb8e9cfc44bab945d1f Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:04 +0530 Subject: ASoC: hdac_hdmi: create dais based on number of cvts After enabling all pins/cvts, Skylake HDMI codec enumerates 3 converters. Three independent streams can be supported with 3 cvts. This patch removes the static dai creation and creates dais based on the number of cvts queried. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 123 ++++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 32 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index b2e5e549b022..c85deae68064 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -30,6 +30,8 @@ #include #include "../../hda/local.h" +#define NAME_SIZE 32 + #define AMP_OUT_MUTE 0xb080 #define AMP_OUT_UNMUTE 0xb000 #define PIN_OUT (AC_PINCTL_OUT_EN) @@ -669,11 +671,82 @@ static void hdac_hdmi_skl_enable_dp12(struct hdac_device *hdac) } +static struct snd_soc_dai_ops hdmi_dai_ops = { + .startup = hdac_hdmi_pcm_open, + .shutdown = hdac_hdmi_pcm_close, + .hw_params = hdac_hdmi_set_hw_params, + .prepare = hdac_hdmi_playback_prepare, + .hw_free = hdac_hdmi_playback_cleanup, +}; + +/* + * Each converter can support a stream independently. So a dai is created + * based on the number of converter queried. + */ +static int hdac_hdmi_create_dais(struct hdac_device *hdac, + struct snd_soc_dai_driver **dais, + struct hdac_hdmi_priv *hdmi, int num_dais) +{ + struct snd_soc_dai_driver *hdmi_dais; + struct hdac_hdmi_cvt *cvt; + char name[NAME_SIZE], dai_name[NAME_SIZE]; + int i = 0; + u32 rates, bps; + unsigned int rate_max = 384000, rate_min = 8000; + u64 formats; + int ret; + + hdmi_dais = devm_kzalloc(&hdac->dev, + (sizeof(*hdmi_dais) * num_dais), + GFP_KERNEL); + if (!hdmi_dais) + return -ENOMEM; + + list_for_each_entry(cvt, &hdmi->cvt_list, head) { + ret = snd_hdac_query_supported_pcm(hdac, cvt->nid, + &rates, &formats, &bps); + if (ret) + return ret; + + sprintf(dai_name, "intel-hdmi-hifi%d", i+1); + hdmi_dais[i].name = devm_kstrdup(&hdac->dev, + dai_name, GFP_KERNEL); + + if (!hdmi_dais[i].name) + return -ENOMEM; + + snprintf(name, sizeof(name), "hifi%d", i+1); + hdmi_dais[i].playback.stream_name = + devm_kstrdup(&hdac->dev, name, GFP_KERNEL); + if (!hdmi_dais[i].playback.stream_name) + return -ENOMEM; + + /* + * Set caps based on capability queried from the converter. + * It will be constrained runtime based on ELD queried. + */ + hdmi_dais[i].playback.formats = formats; + hdmi_dais[i].playback.rates = rates; + hdmi_dais[i].playback.rate_max = rate_max; + hdmi_dais[i].playback.rate_min = rate_min; + hdmi_dais[i].playback.channels_min = 2; + hdmi_dais[i].playback.channels_max = 2; + hdmi_dais[i].ops = &hdmi_dai_ops; + + i++; + } + + *dais = hdmi_dais; + + return 0; +} + /* * Parse all nodes and store the cvt/pin nids in array * Add one time initialization for pin and cvt widgets */ -static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev) +static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev, + struct snd_soc_dai_driver **dais, int *num_dais) { hda_nid_t nid; int i, num_nodes; @@ -724,6 +797,15 @@ static int hdac_hdmi_parse_and_map_nid(struct hdac_ext_device *edev) if (!hdmi->num_pin || !hdmi->num_cvt) return -EIO; + ret = hdac_hdmi_create_dais(hdac, dais, hdmi, hdmi->num_cvt); + if (ret) { + dev_err(&hdac->dev, "Failed to create dais with err: %d\n", + ret); + return ret; + } + + *num_dais = hdmi->num_cvt; + return hdac_hdmi_init_dai_map(edev); } @@ -814,38 +896,12 @@ static struct snd_soc_codec_driver hdmi_hda_codec = { .idle_bias_off = true, }; -static struct snd_soc_dai_ops hdmi_dai_ops = { - .startup = hdac_hdmi_pcm_open, - .shutdown = hdac_hdmi_pcm_close, - .hw_params = hdac_hdmi_set_hw_params, - .prepare = hdac_hdmi_playback_prepare, - .hw_free = hdac_hdmi_playback_cleanup, -}; - -static struct snd_soc_dai_driver hdmi_dais[] = { - { .name = "intel-hdmi-hif1", - .playback = { - .stream_name = "hif1", - .channels_min = 2, - .channels_max = 2, - .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, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - - }, - .ops = &hdmi_dai_ops, - }, -}; - static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) { struct hdac_device *codec = &edev->hdac; struct hdac_hdmi_priv *hdmi_priv; + struct snd_soc_dai_driver *hdmi_dais = NULL; + int num_dais = 0; int ret = 0; hdmi_priv = devm_kzalloc(&codec->dev, sizeof(*hdmi_priv), GFP_KERNEL); @@ -859,13 +915,16 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) INIT_LIST_HEAD(&hdmi_priv->pin_list); INIT_LIST_HEAD(&hdmi_priv->cvt_list); - ret = hdac_hdmi_parse_and_map_nid(edev); - if (ret < 0) + ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais); + if (ret < 0) { + dev_err(&codec->dev, + "Failed in parse and map nid with err: %d\n", ret); return ret; + } /* ASoC specific initialization */ return snd_soc_register_codec(&codec->dev, &hdmi_hda_codec, - hdmi_dais, ARRAY_SIZE(hdmi_dais)); + hdmi_dais, num_dais); } static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) -- cgit From 79f4e922b54771a4d41b1da67caf109ba92ed95a Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:05 +0530 Subject: ASoC: hdac_hdmi: Create widget/route based on nodes enumerated In skylake, HDMI codec enumerates 3 pins and 3 cvts. Stream can be routed from any cvt to any pin based on the connection list queried from the pin. This patch removes the static modelling of widget/route and creates it dynamically based on the codec widgets enumerated. Mux widgets are added to represent the map between a cvt and pin. Ideally the mux widgets should be created based on the connection list queried from the pin widget. But due to HW behavior, if an external display is not connected on a port, querying the connection list returns zero. So create mux widgets to map all the cvt to all pins. At runtime, playback support on a pin can be verified based on the connection list query. Few function in driver have additional arguments now to support this. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 241 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 219 insertions(+), 22 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index c85deae68064..6fb44c4cc8c7 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -446,46 +446,241 @@ hdac_hdmi_query_cvt_params(struct hdac_device *hdac, struct hdac_hdmi_cvt *cvt) return err; } -static void hdac_hdmi_fill_widget_info(struct snd_soc_dapm_widget *w, - enum snd_soc_dapm_type id, - const char *wname, const char *stream) +static int hdac_hdmi_fill_widget_info(struct device *dev, + struct snd_soc_dapm_widget *w, + enum snd_soc_dapm_type id, void *priv, + const char *wname, const char *stream, + struct snd_kcontrol_new *wc, int numkc) { w->id = id; - w->name = wname; + w->name = devm_kstrdup(dev, wname, GFP_KERNEL); + if (!w->name) + return -ENOMEM; + w->sname = stream; w->reg = SND_SOC_NOPM; w->shift = 0; - w->kcontrol_news = NULL; - w->num_kcontrols = 0; - w->priv = NULL; + w->kcontrol_news = wc; + w->num_kcontrols = numkc; + w->priv = priv; + + return 0; } static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route, - const char *sink, const char *control, const char *src) + const char *sink, const char *control, const char *src, + int (*handler)(struct snd_soc_dapm_widget *src, + struct snd_soc_dapm_widget *sink)) { route->sink = sink; route->source = src; route->control = control; - route->connected = NULL; + route->connected = handler; } -static void create_fill_widget_route_map(struct snd_soc_dapm_context *dapm, - struct hdac_hdmi_dai_pin_map *dai_map) +/* + * Ideally the Mux inputs should be based on the num_muxs enumerated, but + * the display driver seem to be programming the connection list for the pin + * widget runtime. + * + * So programming all the possible inputs for the mux, the user has to take + * care of selecting the right one and leaving all other inputs selected to + * "NONE" + */ +static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, + struct hdac_hdmi_pin *pin, + struct snd_soc_dapm_widget *widget, + const char *widget_name) +{ + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct snd_kcontrol_new *kc; + struct hdac_hdmi_cvt *cvt; + struct soc_enum *se; + char kc_name[NAME_SIZE]; + char mux_items[NAME_SIZE]; + /* To hold inputs to the Pin mux */ + char *items[HDA_MAX_CONNECTIONS]; + int i = 0; + int num_items = hdmi->num_cvt + 1; + + kc = devm_kzalloc(&edev->hdac.dev, sizeof(*kc), GFP_KERNEL); + if (!kc) + return -ENOMEM; + + se = devm_kzalloc(&edev->hdac.dev, sizeof(*se), GFP_KERNEL); + if (!se) + return -ENOMEM; + + sprintf(kc_name, "Pin %d Input", pin->nid); + kc->name = devm_kstrdup(&edev->hdac.dev, kc_name, GFP_KERNEL); + if (!kc->name) + return -ENOMEM; + + kc->private_value = (long)se; + kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + kc->access = 0; + kc->info = snd_soc_info_enum_double; + kc->put = snd_soc_dapm_put_enum_double; + kc->get = snd_soc_dapm_get_enum_double; + + se->reg = SND_SOC_NOPM; + + /* enum texts: ["NONE", "cvt #", "cvt #", ...] */ + se->items = num_items; + se->mask = roundup_pow_of_two(se->items) - 1; + + sprintf(mux_items, "NONE"); + items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL); + if (!items[i]) + return -ENOMEM; + + list_for_each_entry(cvt, &hdmi->cvt_list, head) { + i++; + sprintf(mux_items, "cvt %d", cvt->nid); + items[i] = devm_kstrdup(&edev->hdac.dev, mux_items, GFP_KERNEL); + if (!items[i]) + return -ENOMEM; + } + + se->texts = devm_kmemdup(&edev->hdac.dev, items, + (num_items * sizeof(char *)), GFP_KERNEL); + if (!se->texts) + return -ENOMEM; + + return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget, + snd_soc_dapm_mux, &pin->nid, widget_name, + NULL, kc, 1); +} + +/* Add cvt <- input <- mux route map */ +static void hdac_hdmi_add_pinmux_cvt_route(struct hdac_ext_device *edev, + struct snd_soc_dapm_widget *widgets, + struct snd_soc_dapm_route *route, int rindex) +{ + struct hdac_hdmi_priv *hdmi = edev->private_data; + const struct snd_kcontrol_new *kc; + struct soc_enum *se; + int mux_index = hdmi->num_cvt + hdmi->num_pin; + int i, j; + + for (i = 0; i < hdmi->num_pin; i++) { + kc = widgets[mux_index].kcontrol_news; + se = (struct soc_enum *)kc->private_value; + for (j = 0; j < hdmi->num_cvt; j++) { + hdac_hdmi_fill_route(&route[rindex], + widgets[mux_index].name, + se->texts[j + 1], + widgets[j].name, NULL); + + rindex++; + } + + mux_index++; + } +} + +/* + * Widgets are added in the below sequence + * Converter widgets for num converters enumerated + * Pin widgets for num pins enumerated + * Pin mux widgets to represent connenction list of pin widget + * + * Total widgets elements = num_cvt + num_pin + num_pin; + * + * Routes are added as below: + * pin mux -> pin (based on num_pins) + * cvt -> "Input sel control" -> pin_mux + * + * Total route elements: + * num_pins + (pin_muxes * num_cvt) + */ +static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) { - struct snd_soc_dapm_route route[1]; - struct snd_soc_dapm_widget widgets[2] = { {0} }; + struct snd_soc_dapm_widget *widgets; + struct snd_soc_dapm_route *route; + struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev); + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct snd_soc_dai_driver *dai_drv = dapm->component->dai_drv; + char widget_name[NAME_SIZE]; + struct hdac_hdmi_cvt *cvt; + struct hdac_hdmi_pin *pin; + int ret, i = 0, num_routes = 0; - memset(&route, 0, sizeof(route)); + if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list)) + return -EINVAL; - hdac_hdmi_fill_widget_info(&widgets[0], snd_soc_dapm_output, - "hif1 Output", NULL); - hdac_hdmi_fill_widget_info(&widgets[1], snd_soc_dapm_aif_in, - "Coverter 1", "hif1"); + widgets = devm_kzalloc(dapm->dev, + (sizeof(*widgets) * ((2 * hdmi->num_pin) + hdmi->num_cvt)), + GFP_KERNEL); - hdac_hdmi_fill_route(&route[0], "hif1 Output", NULL, "Coverter 1"); + if (!widgets) + return -ENOMEM; + + /* DAPM widgets to represent each converter widget */ + list_for_each_entry(cvt, &hdmi->cvt_list, head) { + sprintf(widget_name, "Converter %d", cvt->nid); + ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], + snd_soc_dapm_aif_in, &cvt->nid, + widget_name, dai_drv[i].playback.stream_name, NULL, 0); + if (ret < 0) + return ret; + i++; + } + + list_for_each_entry(pin, &hdmi->pin_list, head) { + sprintf(widget_name, "hif%d Output", pin->nid); + ret = hdac_hdmi_fill_widget_info(dapm->dev, &widgets[i], + snd_soc_dapm_output, &pin->nid, + widget_name, NULL, NULL, 0); + if (ret < 0) + return ret; + i++; + } + + /* DAPM widgets to represent the connection list to pin widget */ + list_for_each_entry(pin, &hdmi->pin_list, head) { + sprintf(widget_name, "Pin %d Mux", pin->nid); + ret = hdac_hdmi_create_pin_muxs(edev, pin, &widgets[i], + widget_name); + if (ret < 0) + return ret; + i++; + + /* For cvt to pin_mux mapping */ + num_routes += hdmi->num_cvt; + + /* For pin_mux to pin mapping */ + num_routes++; + } + + route = devm_kzalloc(dapm->dev, (sizeof(*route) * num_routes), + GFP_KERNEL); + if (!route) + return -ENOMEM; + + i = 0; + /* Add pin <- NULL <- mux route map */ + list_for_each_entry(pin, &hdmi->pin_list, head) { + int sink_index = i + hdmi->num_cvt; + int src_index = sink_index + hdmi->num_pin; + + hdac_hdmi_fill_route(&route[i], + widgets[sink_index].name, NULL, + widgets[src_index].name, NULL); + i++; + + } + + hdac_hdmi_add_pinmux_cvt_route(edev, widgets, route, i); + + snd_soc_dapm_new_controls(dapm, widgets, + ((2 * hdmi->num_pin) + hdmi->num_cvt)); + + snd_soc_dapm_add_routes(dapm, route, num_routes); + snd_soc_dapm_new_widgets(dapm->card); + + return 0; - snd_soc_dapm_new_controls(dapm, widgets, ARRAY_SIZE(widgets)); - snd_soc_dapm_add_routes(dapm, route, ARRAY_SIZE(route)); } static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) @@ -855,7 +1050,9 @@ static int hdmi_codec_probe(struct snd_soc_codec *codec) edev->scodec = codec; - create_fill_widget_route_map(dapm, &hdmi->dai_map[0]); + ret = create_fill_widget_route_map(dapm); + if (ret < 0) + return ret; aops.audio_ptr = edev; ret = snd_hdac_i915_register_notifier(&aops); -- cgit From 4a3478debf36c0aa0cf0860daec245b13cd4448f Mon Sep 17 00:00:00 2001 From: Jeeja KP Date: Fri, 12 Feb 2016 07:46:06 +0530 Subject: ASoC: hdac_hdmi: Add jack reporting Jack is created based on pcm devices enumerated, so we will create Jack as "HDMI/DP, pcm=x Jack". This style is expected by current usermode like PulseAudio and CRAS. This patch exports an API which can be used to register Jack based on PCM. This API also establishes the map between PCM and cvt. Further cvt to pin mapping is established with the help of usermode selection based on the board topology. During device probe as the PCMs may not be registered, initial pin sense don't report jack events. So, first time jack reporting is done during user selection of mux control. Signed-off-by: Jeeja KP Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 160 ++++++++++++++++++++++++++++++++++++++++++- sound/soc/codecs/hdac_hdmi.h | 6 ++ 2 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 sound/soc/codecs/hdac_hdmi.h diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 6fb44c4cc8c7..839148688744 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -24,11 +24,13 @@ #include #include #include +#include #include #include #include #include #include "../../hda/local.h" +#include "hdac_hdmi.h" #define NAME_SIZE 32 @@ -52,6 +54,7 @@ struct hdac_hdmi_cvt_params { struct hdac_hdmi_cvt { struct list_head head; hda_nid_t nid; + const char *name; struct hdac_hdmi_cvt_params params; }; @@ -73,6 +76,14 @@ struct hdac_hdmi_pin { struct delayed_work work; }; +struct hdac_hdmi_pcm { + struct list_head head; + int pcm_id; + struct hdac_hdmi_pin *pin; + struct hdac_hdmi_cvt *cvt; + struct snd_jack *jack; +}; + struct hdac_hdmi_dai_pin_map { int dai_id; struct hdac_hdmi_pin *pin; @@ -83,8 +94,10 @@ struct hdac_hdmi_priv { struct hdac_hdmi_dai_pin_map dai_map[3]; struct list_head pin_list; struct list_head cvt_list; + struct list_head pcm_list; int num_pin; int num_cvt; + struct mutex pin_mutex; }; static inline struct hdac_ext_device *to_hda_ext_device(struct device *dev) @@ -478,6 +491,67 @@ static void hdac_hdmi_fill_route(struct snd_soc_dapm_route *route, route->connected = handler; } +static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_ext_device *edev, + struct hdac_hdmi_pin *pin) +{ + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct hdac_hdmi_pcm *pcm = NULL; + + list_for_each_entry(pcm, &hdmi->pcm_list, head) { + if (pcm->pin == pin) + return pcm; + } + + return NULL; +} + +/* + * Based on user selection, map the PINs with the PCMs. + */ +static int hdac_hdmi_set_pin_mux(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_context *dapm = w->dapm; + struct hdac_hdmi_pin *pin = w->priv; + struct hdac_ext_device *edev = to_hda_ext_device(dapm->dev); + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct hdac_hdmi_pcm *pcm = NULL; + const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]]; + + ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + if (ret < 0) + return ret; + + mutex_lock(&hdmi->pin_mutex); + list_for_each_entry(pcm, &hdmi->pcm_list, head) { + if (pcm->pin == pin) + pcm->pin = NULL; + + /* + * Jack status is not reported during device probe as the + * PCMs are not registered by then. So report it here. + */ + if (!strcmp(cvt_name, pcm->cvt->name) && !pcm->pin) { + pcm->pin = pin; + if (pin->eld.monitor_present && pin->eld.eld_valid) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); + + snd_jack_report(pcm->jack, SND_JACK_AVOUT); + } + mutex_unlock(&hdmi->pin_mutex); + return ret; + } + } + mutex_unlock(&hdmi->pin_mutex); + + return ret; +} + /* * Ideally the Mux inputs should be based on the num_muxs enumerated, but * the display driver seem to be programming the connection list for the pin @@ -520,7 +594,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, kc->iface = SNDRV_CTL_ELEM_IFACE_MIXER; kc->access = 0; kc->info = snd_soc_info_enum_double; - kc->put = snd_soc_dapm_put_enum_double; + kc->put = hdac_hdmi_set_pin_mux; kc->get = snd_soc_dapm_get_enum_double; se->reg = SND_SOC_NOPM; @@ -548,8 +622,7 @@ static int hdac_hdmi_create_pin_muxs(struct hdac_ext_device *edev, return -ENOMEM; return hdac_hdmi_fill_widget_info(&edev->hdac.dev, widget, - snd_soc_dapm_mux, &pin->nid, widget_name, - NULL, kc, 1); + snd_soc_dapm_mux, pin, widget_name, NULL, kc, 1); } /* Add cvt <- input <- mux route map */ @@ -728,12 +801,15 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) { struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_cvt *cvt; + char name[NAME_SIZE]; cvt = kzalloc(sizeof(*cvt), GFP_KERNEL); if (!cvt) return -ENOMEM; cvt->nid = nid; + sprintf(name, "cvt %d", cvt->nid); + cvt->name = kstrdup(name, GFP_KERNEL); list_add_tail(&cvt->head, &hdmi->cvt_list); hdmi->num_cvt++; @@ -744,6 +820,8 @@ static int hdac_hdmi_add_cvt(struct hdac_ext_device *edev, hda_nid_t nid) static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) { struct hdac_ext_device *edev = pin->edev; + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct hdac_hdmi_pcm *pcm; int val; if (!edev) @@ -758,13 +836,31 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) dev_dbg(&edev->hdac.dev, "Pin sense val %x for pin: %d\n", val, pin->nid); + + mutex_lock(&hdmi->pin_mutex); pin->eld.monitor_present = !!(val & AC_PINSENSE_PRESENCE); pin->eld.eld_valid = !!(val & AC_PINSENSE_ELDV); + pcm = hdac_hdmi_get_pcm(edev, pin); + if (!pin->eld.monitor_present || !pin->eld.eld_valid) { dev_dbg(&edev->hdac.dev, "%s: disconnect for pin %d\n", __func__, pin->nid); + + /* + * PCMs are not registered during device probe, so don't + * report jack here. It will be done in usermode mux + * control select. + */ + if (pcm) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", pcm->pcm_id); + + snd_jack_report(pcm->jack, 0); + } + + mutex_unlock(&hdmi->pin_mutex); goto put_hdac_device; } @@ -774,14 +870,32 @@ static void hdac_hdmi_present_sense(struct hdac_hdmi_pin *pin, int repoll) pin->eld.eld_buffer, &pin->eld.eld_size) == 0) { + if (pcm) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); + + snd_jack_report(pcm->jack, SND_JACK_AVOUT); + } + print_hex_dump_bytes("ELD: ", DUMP_PREFIX_OFFSET, pin->eld.eld_buffer, pin->eld.eld_size); } else { pin->eld.monitor_present = false; pin->eld.eld_valid = false; + + if (pcm) { + dev_dbg(&edev->hdac.dev, + "jack report for pcm=%d\n", + pcm->pcm_id); + + snd_jack_report(pcm->jack, 0); + } } } + mutex_unlock(&hdmi->pin_mutex); + /* * Sometimes the pin_sense may present invalid monitor * present and eld_valid. If ELD data is not valid, loop few @@ -1039,6 +1153,35 @@ static struct i915_audio_component_audio_ops aops = { .pin_eld_notify = hdac_hdmi_eld_notify_cb, }; +int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device) +{ + char jack_name[NAME_SIZE]; + struct snd_soc_codec *codec = dai->codec; + struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(&codec->component); + struct hdac_hdmi_priv *hdmi = edev->private_data; + struct hdac_hdmi_pcm *pcm; + + /* + * this is a new PCM device, create new pcm and + * add to the pcm list + */ + pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + pcm->pcm_id = device; + pcm->cvt = hdmi->dai_map[dai->id].cvt; + + list_add_tail(&pcm->head, &hdmi->pcm_list); + + sprintf(jack_name, "HDMI/DP, pcm=%d Jack", device); + + return snd_jack_new(dapm->card->snd_card, jack_name, + SND_JACK_AVOUT, &pcm->jack, true, false); +} +EXPORT_SYMBOL_GPL(hdac_hdmi_jack_init); + static int hdmi_codec_probe(struct snd_soc_codec *codec) { struct hdac_ext_device *edev = snd_soc_codec_get_drvdata(codec); @@ -1111,6 +1254,8 @@ static int hdac_hdmi_dev_probe(struct hdac_ext_device *edev) INIT_LIST_HEAD(&hdmi_priv->pin_list); INIT_LIST_HEAD(&hdmi_priv->cvt_list); + INIT_LIST_HEAD(&hdmi_priv->pcm_list); + mutex_init(&hdmi_priv->pin_mutex); ret = hdac_hdmi_parse_and_map_nid(edev, &hdmi_dais, &num_dais); if (ret < 0) { @@ -1129,11 +1274,20 @@ static int hdac_hdmi_dev_remove(struct hdac_ext_device *edev) struct hdac_hdmi_priv *hdmi = edev->private_data; struct hdac_hdmi_pin *pin, *pin_next; struct hdac_hdmi_cvt *cvt, *cvt_next; + struct hdac_hdmi_pcm *pcm, *pcm_next; snd_soc_unregister_codec(&edev->hdac.dev); + list_for_each_entry_safe(pcm, pcm_next, &hdmi->pcm_list, head) { + pcm->cvt = NULL; + pcm->pin = NULL; + list_del(&pcm->head); + kfree(pcm); + } + list_for_each_entry_safe(cvt, cvt_next, &hdmi->cvt_list, head) { list_del(&cvt->head); + kfree(cvt->name); kfree(cvt); } diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h new file mode 100644 index 000000000000..8dfd1e0b57b3 --- /dev/null +++ b/sound/soc/codecs/hdac_hdmi.h @@ -0,0 +1,6 @@ +#ifndef __HDAC_HDMI_H__ +#define __HDAC_HDMI_H__ + +int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm); + +#endif /* __HDAC_HDMI_H__ */ -- cgit From 148569fddbc6d3ce97236c4344068b1293e51838 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:07 +0530 Subject: ASoC: hdac_hdmi: Enable playback on all enumerated ports Last patch added infrastructure to render over all the ports, PCM<->cvt<- pin mapping and user selection of controls. But we still have restriction of playback on the default port alone, so remove that. This patch removes the hardcoding of cvt<->pin map from the dai. Cvt and pin for a dai are now derived from the already stored pcm list of device opened. We query connection list of a pin from codec to validate the cvt<->pin map. If connection list returns zero, then monitor is not connected so fail playback. Signed-off-by: Subhransu S. Prusty Signed-off-by: Jeeja KP Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 174 ++++++++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 42 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 839148688744..dcd1cb643145 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -40,6 +40,8 @@ #define HDA_MAX_CONNECTIONS 32 +#define HDA_MAX_CVTS 3 + #define ELD_MAX_SIZE 256 #define ELD_FIXED_BYTES 20 @@ -91,7 +93,7 @@ struct hdac_hdmi_dai_pin_map { }; struct hdac_hdmi_priv { - struct hdac_hdmi_dai_pin_map dai_map[3]; + struct hdac_hdmi_dai_pin_map dai_map[HDA_MAX_CVTS]; struct list_head pin_list; struct list_head cvt_list; struct list_head pcm_list; @@ -384,44 +386,136 @@ static int hdac_hdmi_playback_cleanup(struct snd_pcm_substream *substream, return 0; } +static int hdac_hdmi_enable_pin(struct hdac_ext_device *hdac, + struct hdac_hdmi_dai_pin_map *dai_map) +{ + int mux_idx; + struct hdac_hdmi_pin *pin = dai_map->pin; + + for (mux_idx = 0; mux_idx < pin->num_mux_nids; mux_idx++) { + if (pin->mux_nids[mux_idx] == dai_map->cvt->nid) { + snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, + AC_VERB_SET_CONNECT_SEL, mux_idx); + break; + } + } + + if (mux_idx == pin->num_mux_nids) + return -EIO; + + /* Enable out path for this pin widget */ + snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0); + + snd_hdac_codec_write(&hdac->hdac, pin->nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + + return 0; +} + +static int hdac_hdmi_query_pin_connlist(struct hdac_ext_device *hdac, + struct hdac_hdmi_pin *pin) +{ + if (!(get_wcaps(&hdac->hdac, pin->nid) & AC_WCAP_CONN_LIST)) { + dev_warn(&hdac->hdac.dev, + "HDMI: pin %d wcaps %#x does not support connection list\n", + pin->nid, get_wcaps(&hdac->hdac, pin->nid)); + return -EINVAL; + } + + pin->num_mux_nids = snd_hdac_get_connections(&hdac->hdac, pin->nid, + pin->mux_nids, HDA_MAX_CONNECTIONS); + if (pin->num_mux_nids == 0) + dev_warn(&hdac->hdac.dev, "No connections found for pin: %d\n", + pin->nid); + + dev_dbg(&hdac->hdac.dev, "num_mux_nids %d for pin: %d\n", + pin->num_mux_nids, pin->nid); + + return pin->num_mux_nids; +} + +/* + * Query pcm list and return pin widget to which stream is routed. + * + * Also query connection list of the pin, to validate the cvt to pin map. + * + * Same stream rendering to multiple pins simultaneously can be done + * possibly, but not supported for now in driver. So return the first pin + * connected. + */ +static struct hdac_hdmi_pin *hdac_hdmi_get_pin_from_cvt( + struct hdac_ext_device *edev, + struct hdac_hdmi_priv *hdmi, + struct hdac_hdmi_cvt *cvt) +{ + struct hdac_hdmi_pcm *pcm; + struct hdac_hdmi_pin *pin = NULL; + int ret, i; + + list_for_each_entry(pcm, &hdmi->pcm_list, head) { + if (pcm->cvt == cvt) { + pin = pcm->pin; + break; + } + } + + if (pin) { + ret = hdac_hdmi_query_pin_connlist(edev, pin); + if (ret < 0) + return NULL; + + for (i = 0; i < pin->num_mux_nids; i++) { + if (pin->mux_nids[i] == cvt->nid) + return pin; + } + } + + return NULL; +} + static int hdac_hdmi_pcm_open(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct hdac_ext_device *hdac = snd_soc_dai_get_drvdata(dai); struct hdac_hdmi_priv *hdmi = hdac->private_data; struct hdac_hdmi_dai_pin_map *dai_map; + struct hdac_hdmi_cvt *cvt; + struct hdac_hdmi_pin *pin; int ret; - if (dai->id > 0) { - dev_err(&hdac->hdac.dev, "Only one dai supported as of now\n"); - return -ENODEV; - } - dai_map = &hdmi->dai_map[dai->id]; - if ((!dai_map->pin->eld.monitor_present) || - (!dai_map->pin->eld.eld_valid)) { + cvt = dai_map->cvt; + pin = hdac_hdmi_get_pin_from_cvt(hdac, hdmi, cvt); + if (!pin) + return -EIO; + + if ((!pin->eld.monitor_present) || + (!pin->eld.eld_valid)) { dev_err(&hdac->hdac.dev, - "Failed: montior present? %d ELD valid?: %d\n", - dai_map->pin->eld.monitor_present, - dai_map->pin->eld.eld_valid); + "Failed: montior present? %d ELD valid?: %d for pin: %d\n", + pin->eld.monitor_present, pin->eld.eld_valid, pin->nid); return -ENODEV; } - hdac_hdmi_set_power_state(hdac, dai_map, AC_PWRST_D0); + dai_map->pin = pin; - snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); + ret = hdac_hdmi_enable_pin(hdac, dai_map); + if (ret < 0) + return ret; ret = hdac_hdmi_eld_limit_formats(substream->runtime, - dai_map->pin->eld.eld_buffer); + pin->eld.eld_buffer); if (ret < 0) return ret; return snd_pcm_hw_constraint_eld(substream->runtime, - dai_map->pin->eld.eld_buffer); + pin->eld.eld_buffer); } static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, @@ -437,6 +531,8 @@ static void hdac_hdmi_pcm_close(struct snd_pcm_substream *substream, snd_hdac_codec_write(&hdac->hdac, dai_map->pin->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + dai_map->pin = NULL; } static int @@ -759,40 +855,34 @@ static int create_fill_widget_route_map(struct snd_soc_dapm_context *dapm) static int hdac_hdmi_init_dai_map(struct hdac_ext_device *edev) { struct hdac_hdmi_priv *hdmi = edev->private_data; - struct hdac_hdmi_dai_pin_map *dai_map = &hdmi->dai_map[0]; + struct hdac_hdmi_dai_pin_map *dai_map; struct hdac_hdmi_cvt *cvt; - struct hdac_hdmi_pin *pin; + int dai_id = 0; - if (list_empty(&hdmi->cvt_list) || list_empty(&hdmi->pin_list)) + if (list_empty(&hdmi->cvt_list)) return -EINVAL; - /* - * Currently on board only 1 pin and 1 converter is enabled for - * simplification, more will be added eventually - * So using fixed map for dai_id:pin:cvt - */ - cvt = list_first_entry(&hdmi->cvt_list, struct hdac_hdmi_cvt, head); - pin = list_first_entry(&hdmi->pin_list, struct hdac_hdmi_pin, head); - - dai_map->dai_id = 0; - dai_map->pin = pin; + list_for_each_entry(cvt, &hdmi->cvt_list, head) { + dai_map = &hdmi->dai_map[dai_id]; + dai_map->dai_id = dai_id; + dai_map->cvt = cvt; - dai_map->cvt = cvt; + /* Enable transmission */ + snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, + AC_VERB_SET_DIGI_CONVERT_1, 1); - /* Enable out path for this pin widget */ - snd_hdac_codec_write(&edev->hdac, pin->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + /* Category Code (CC) to zero */ + snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, + AC_VERB_SET_DIGI_CONVERT_2, 0); - /* Enable transmission */ - snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, - AC_VERB_SET_DIGI_CONVERT_1, 1); + dai_id++; - /* Category Code (CC) to zero */ - snd_hdac_codec_write(&edev->hdac, cvt->nid, 0, - AC_VERB_SET_DIGI_CONVERT_2, 0); - - snd_hdac_codec_write(&edev->hdac, pin->nid, 0, - AC_VERB_SET_CONNECT_SEL, 0); + if (dai_id == HDA_MAX_CVTS) { + dev_warn(&edev->hdac.dev, + "Max dais supported: %d\n", dai_id); + break; + } + } return 0; } -- cgit From 478f544e5b5538ccbcfdb18b4e9860a2f61ab921 Mon Sep 17 00:00:00 2001 From: "Subhransu S. Prusty" Date: Fri, 12 Feb 2016 07:46:09 +0530 Subject: ASoC: hdac_hdmi: Add infoframe support for dp audio For DP audio support, infoframe needs to be different. Based on get_conn_type result we pack either HDMI or DP infoframe. Signed-off-by: Subhransu S. Prusty Signed-off-by: Vinod Koul Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 74 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index dcd1cb643145..36f12004ae9c 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -253,27 +253,75 @@ hdac_hdmi_set_dip_index(struct hdac_ext_device *hdac, hda_nid_t pin_nid, AC_VERB_SET_HDMI_DIP_INDEX, val); } +struct dp_audio_infoframe { + u8 type; /* 0x84 */ + u8 len; /* 0x1b */ + u8 ver; /* 0x11 << 2 */ + + u8 CC02_CT47; /* match with HDMI infoframe from this on */ + u8 SS01_SF24; + u8 CXT04; + u8 CA; + u8 LFEPBL01_LSV36_DM_INH7; +}; + static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, hda_nid_t cvt_nid, hda_nid_t pin_nid) { uint8_t buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AUDIO_INFOFRAME_SIZE]; struct hdmi_audio_infoframe frame; - u8 *dip = (u8 *)&frame; + struct dp_audio_infoframe dp_ai; + struct hdac_hdmi_priv *hdmi = hdac->private_data; + struct hdac_hdmi_pin *pin; + u8 *dip; int ret; int i; + const u8 *eld_buf; + u8 conn_type; + int channels = 2; - hdmi_audio_infoframe_init(&frame); + list_for_each_entry(pin, &hdmi->pin_list, head) { + if (pin->nid == pin_nid) + break; + } - /* Default stereo for now */ - frame.channels = 2; + eld_buf = pin->eld.eld_buffer; + conn_type = drm_eld_get_conn_type(eld_buf); /* setup channel count */ snd_hdac_codec_write(&hdac->hdac, cvt_nid, 0, - AC_VERB_SET_CVT_CHAN_COUNT, frame.channels - 1); + AC_VERB_SET_CVT_CHAN_COUNT, channels - 1); - ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer)); - if (ret < 0) - return ret; + switch (conn_type) { + case DRM_ELD_CONN_TYPE_HDMI: + hdmi_audio_infoframe_init(&frame); + + /* Default stereo for now */ + frame.channels = channels; + + ret = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer)); + if (ret < 0) + return ret; + + dip = (u8 *)&frame; + break; + + case DRM_ELD_CONN_TYPE_DP: + memset(&dp_ai, 0, sizeof(dp_ai)); + dp_ai.type = 0x84; + dp_ai.len = 0x1b; + dp_ai.ver = 0x11 << 2; + dp_ai.CC02_CT47 = channels - 1; + dp_ai.CA = 0; + + dip = (u8 *)&dp_ai; + break; + + default: + dev_err(&hdac->hdac.dev, "Invalid connection type: %d\n", + conn_type); + return -EIO; + } /* stop infoframe transmission */ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); @@ -283,9 +331,15 @@ static int hdac_hdmi_setup_audio_infoframe(struct hdac_ext_device *hdac, /* Fill infoframe. Index auto-incremented */ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); - for (i = 0; i < sizeof(frame); i++) - snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, + if (conn_type == DRM_ELD_CONN_TYPE_HDMI) { + for (i = 0; i < sizeof(frame); i++) + snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, dip[i]); + } else { + for (i = 0; i < sizeof(dp_ai); i++) + snd_hdac_codec_write(&hdac->hdac, pin_nid, 0, + AC_VERB_SET_HDMI_DIP_DATA, dip[i]); + } /* Start infoframe */ hdac_hdmi_set_dip_index(hdac, pin_nid, 0x0, 0x0); -- cgit From 935514c961310558ee0767e73e678b85ac37a68d Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 29 Jan 2016 17:37:01 +0000 Subject: regulator: vexpress: rename vexpress regulator implementation The vexpress regulator implementation is currently just called vexpress. This is a problem because it clashes with another module with the same name in hardware monitors. This patch renames the vexpress regulator implementation to vexpress-regulator so that there will be no clash in the module namespace. Cc: Liviu Dudau Cc: Lorenzo Pieralisi Cc: Liam Girdwood Cc: Mark Brown Reported-by: Rusty Russell Signed-off-by: Sudeep Holla Signed-off-by: Mark Brown --- drivers/regulator/Makefile | 2 +- drivers/regulator/vexpress-regulator.c | 121 +++++++++++++++++++++++++++++++++ drivers/regulator/vexpress.c | 121 --------------------------------- 3 files changed, 122 insertions(+), 122 deletions(-) create mode 100644 drivers/regulator/vexpress-regulator.c delete mode 100644 drivers/regulator/vexpress.c diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 980b1943fa81..755077a89a25 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -98,7 +98,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o -obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o +obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o diff --git a/drivers/regulator/vexpress-regulator.c b/drivers/regulator/vexpress-regulator.c new file mode 100644 index 000000000000..c810cbbd463f --- /dev/null +++ b/drivers/regulator/vexpress-regulator.c @@ -0,0 +1,121 @@ +/* + * 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. + * + * Copyright (C) 2012 ARM Limited + */ + +#define DRVNAME "vexpress-regulator" +#define pr_fmt(fmt) DRVNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +struct vexpress_regulator { + struct regulator_desc desc; + struct regulator_dev *regdev; + struct regmap *regmap; +}; + +static int vexpress_regulator_get_voltage(struct regulator_dev *regdev) +{ + struct vexpress_regulator *reg = rdev_get_drvdata(regdev); + u32 uV; + int err = regmap_read(reg->regmap, 0, &uV); + + return err ? err : uV; +} + +static int vexpress_regulator_set_voltage(struct regulator_dev *regdev, + int min_uV, int max_uV, unsigned *selector) +{ + struct vexpress_regulator *reg = rdev_get_drvdata(regdev); + + return regmap_write(reg->regmap, 0, min_uV); +} + +static struct regulator_ops vexpress_regulator_ops_ro = { + .get_voltage = vexpress_regulator_get_voltage, +}; + +static struct regulator_ops vexpress_regulator_ops = { + .get_voltage = vexpress_regulator_get_voltage, + .set_voltage = vexpress_regulator_set_voltage, +}; + +static int vexpress_regulator_probe(struct platform_device *pdev) +{ + struct vexpress_regulator *reg; + struct regulator_init_data *init_data; + struct regulator_config config = { }; + + reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL); + if (!reg) + return -ENOMEM; + + reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev); + if (IS_ERR(reg->regmap)) + return PTR_ERR(reg->regmap); + + reg->desc.name = dev_name(&pdev->dev); + reg->desc.type = REGULATOR_VOLTAGE; + reg->desc.owner = THIS_MODULE; + reg->desc.continuous_voltage_range = true; + + init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, + ®->desc); + if (!init_data) + return -EINVAL; + + init_data->constraints.apply_uV = 0; + if (init_data->constraints.min_uV && init_data->constraints.max_uV) + reg->desc.ops = &vexpress_regulator_ops; + else + reg->desc.ops = &vexpress_regulator_ops_ro; + + config.dev = &pdev->dev; + config.init_data = init_data; + config.driver_data = reg; + config.of_node = pdev->dev.of_node; + + reg->regdev = devm_regulator_register(&pdev->dev, ®->desc, &config); + if (IS_ERR(reg->regdev)) + return PTR_ERR(reg->regdev); + + platform_set_drvdata(pdev, reg); + + return 0; +} + +static const struct of_device_id vexpress_regulator_of_match[] = { + { .compatible = "arm,vexpress-volt", }, + { } +}; +MODULE_DEVICE_TABLE(of, vexpress_regulator_of_match); + +static struct platform_driver vexpress_regulator_driver = { + .probe = vexpress_regulator_probe, + .driver = { + .name = DRVNAME, + .of_match_table = vexpress_regulator_of_match, + }, +}; + +module_platform_driver(vexpress_regulator_driver); + +MODULE_AUTHOR("Pawel Moll "); +MODULE_DESCRIPTION("Versatile Express regulator"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:vexpress-regulator"); diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c deleted file mode 100644 index c810cbbd463f..000000000000 --- a/drivers/regulator/vexpress.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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. - * - * Copyright (C) 2012 ARM Limited - */ - -#define DRVNAME "vexpress-regulator" -#define pr_fmt(fmt) DRVNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -struct vexpress_regulator { - struct regulator_desc desc; - struct regulator_dev *regdev; - struct regmap *regmap; -}; - -static int vexpress_regulator_get_voltage(struct regulator_dev *regdev) -{ - struct vexpress_regulator *reg = rdev_get_drvdata(regdev); - u32 uV; - int err = regmap_read(reg->regmap, 0, &uV); - - return err ? err : uV; -} - -static int vexpress_regulator_set_voltage(struct regulator_dev *regdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct vexpress_regulator *reg = rdev_get_drvdata(regdev); - - return regmap_write(reg->regmap, 0, min_uV); -} - -static struct regulator_ops vexpress_regulator_ops_ro = { - .get_voltage = vexpress_regulator_get_voltage, -}; - -static struct regulator_ops vexpress_regulator_ops = { - .get_voltage = vexpress_regulator_get_voltage, - .set_voltage = vexpress_regulator_set_voltage, -}; - -static int vexpress_regulator_probe(struct platform_device *pdev) -{ - struct vexpress_regulator *reg; - struct regulator_init_data *init_data; - struct regulator_config config = { }; - - reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL); - if (!reg) - return -ENOMEM; - - reg->regmap = devm_regmap_init_vexpress_config(&pdev->dev); - if (IS_ERR(reg->regmap)) - return PTR_ERR(reg->regmap); - - reg->desc.name = dev_name(&pdev->dev); - reg->desc.type = REGULATOR_VOLTAGE; - reg->desc.owner = THIS_MODULE; - reg->desc.continuous_voltage_range = true; - - init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node, - ®->desc); - if (!init_data) - return -EINVAL; - - init_data->constraints.apply_uV = 0; - if (init_data->constraints.min_uV && init_data->constraints.max_uV) - reg->desc.ops = &vexpress_regulator_ops; - else - reg->desc.ops = &vexpress_regulator_ops_ro; - - config.dev = &pdev->dev; - config.init_data = init_data; - config.driver_data = reg; - config.of_node = pdev->dev.of_node; - - reg->regdev = devm_regulator_register(&pdev->dev, ®->desc, &config); - if (IS_ERR(reg->regdev)) - return PTR_ERR(reg->regdev); - - platform_set_drvdata(pdev, reg); - - return 0; -} - -static const struct of_device_id vexpress_regulator_of_match[] = { - { .compatible = "arm,vexpress-volt", }, - { } -}; -MODULE_DEVICE_TABLE(of, vexpress_regulator_of_match); - -static struct platform_driver vexpress_regulator_driver = { - .probe = vexpress_regulator_probe, - .driver = { - .name = DRVNAME, - .of_match_table = vexpress_regulator_of_match, - }, -}; - -module_platform_driver(vexpress_regulator_driver); - -MODULE_AUTHOR("Pawel Moll "); -MODULE_DESCRIPTION("Versatile Express regulator"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:vexpress-regulator"); -- cgit From c88c395f4a6485f23f81e385c79945d68bcd5c5d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 15 Feb 2016 10:21:53 +0530 Subject: PM / OPP: Initialize u_volt_min/max to a valid value We kept u_volt_min/max initialized to 0, when only the target voltage is present in DT, instead of the target/min/max triplet. This didn't go well with the regulator framework, as on few calls the min voltage was set to target and max was set to 0 and so resulted in a kernel crash like below: kernel BUG at ../drivers/regulator/core.c:216! [] (regulator_check_voltage) from [] (regulator_set_voltage_unlocked+0x58/0x230) [] (regulator_set_voltage_unlocked) from [] (regulator_set_voltage+0x28/0x54) [] (regulator_set_voltage) from [] (_set_opp_voltage+0x30/0x98) [] (_set_opp_voltage) from [] (dev_pm_opp_set_rate+0xf0/0x28c) [] (dev_pm_opp_set_rate) from [] (__cpufreq_driver_target+0x184/0x2b4) [] (__cpufreq_driver_target) from [] (dbs_check_cpu+0x1b0/0x1f4) [] (dbs_check_cpu) from [] (cpufreq_governor_dbs+0x324/0x5c4) [] (cpufreq_governor_dbs) from [] (__cpufreq_governor+0xe4/0x1ec) [] (__cpufreq_governor) from [] (cpufreq_init_policy+0x64/0x8c) [] (cpufreq_init_policy) from [] (cpufreq_online+0x2fc/0x708) [] (cpufreq_online) from [] (subsys_interface_register+0x94/0xd8) [] (subsys_interface_register) from [] (cpufreq_register_driver+0x14c/0x19c) [] (cpufreq_register_driver) from [] (dt_cpufreq_probe+0x70/0xec) [] (dt_cpufreq_probe) from [] (platform_drv_probe+0x4c/0xb0) [] (platform_drv_probe) from [] (driver_probe_device+0x214/0x2c0) [] (driver_probe_device) from [] (__driver_attach+0x8c/0x90) [] (__driver_attach) from [] (bus_for_each_dev+0x68/0x9c) [] (bus_for_each_dev) from [] (bus_add_driver+0x1a0/0x218) [] (bus_add_driver) from [] (driver_register+0x78/0xf8) [] (driver_register) from [] (do_one_initcall+0x90/0x1d8) [] (do_one_initcall) from [] (kernel_init_freeable+0x15c/0x1fc) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xf0) [] (kernel_init) from [] (ret_from_fork+0x14/0x3c) Code: e1550004 baffffeb e3a00000 e8bd8070 (e7f001f2) Fix that by initializing u_volt_min/max to the target voltage in such cases. Reported-and-tested-by: Krzysztof Kozlowski Fixes: 274659029c9d (PM / OPP: Add support to parse "operating-points-v2" bindings) Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/base/power/opp/core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index d7cd4e265766..19fd7e7a3969 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -1157,8 +1157,14 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, } opp->u_volt = microvolt[0]; - opp->u_volt_min = microvolt[1]; - opp->u_volt_max = microvolt[2]; + + if (count == 1) { + opp->u_volt_min = opp->u_volt; + opp->u_volt_max = opp->u_volt; + } else { + opp->u_volt_min = microvolt[1]; + opp->u_volt_max = microvolt[2]; + } /* Search for "opp-microamp-" */ prop = NULL; -- cgit From fc5cbf0c94b6f7fd62fdddff892207290510945d Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Mon, 15 Feb 2016 11:10:51 +0100 Subject: PM / Domains: Support for multiple states Some hardware (eg. OMAP), has the ability to enter different low power modes for a given power domain. This allows for more fine grained control over the power state of the platform. As a typical example, some registers of the hardware may be implemented with retention flip-flops and be able to retain their state at lower voltages allowing for faster on/off latencies and an increased window of opportunity to enter an intermediate low power state other than "off" When trying to set a power domain to off, the genpd governor will choose the deepest state that will respect the qos constraints of all the devices and sub-domains on the power domain. The state chosen by the governor is saved in the "state_idx" field of the generic_pm_domain structure and shall be used by the power_off and power_on callbacks to perform the necessary actions to set the power domain into (and out of) the state indicated by state_idx. States must be declared in ascending order from shallowest to deepest, deepest meaning the state which takes longer to enter and exit. For platforms that don't declare any states, a single a single "off" state is used. Once all platforms are converted to use the state array, the legacy on/off latencies will be removed. [ Lina: Modified genpd state initialization and remove use of save_state_latency_ns in genpd timing data ] Suggested-by: Kevin Hilman Signed-off-by: Lina Iyer Signed-off-by: Axel Haslam Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 39 +++++++++++++++++++--- drivers/base/power/domain_governor.c | 64 ++++++++++++++++++++++-------------- include/linux/pm_domain.h | 11 +++++++ 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 301b785f9f56..4c6f46b5c444 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -104,6 +104,7 @@ static void genpd_sd_counter_inc(struct generic_pm_domain *genpd) static int genpd_power_on(struct generic_pm_domain *genpd, bool timed) { + unsigned int state_idx = genpd->state_idx; ktime_t time_start; s64 elapsed_ns; int ret; @@ -120,10 +121,10 @@ static int genpd_power_on(struct generic_pm_domain *genpd, bool timed) return ret; elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - if (elapsed_ns <= genpd->power_on_latency_ns) + if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns) return ret; - genpd->power_on_latency_ns = elapsed_ns; + genpd->states[state_idx].power_on_latency_ns = elapsed_ns; genpd->max_off_time_changed = true; pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", genpd->name, "on", elapsed_ns); @@ -133,6 +134,7 @@ static int genpd_power_on(struct generic_pm_domain *genpd, bool timed) static int genpd_power_off(struct generic_pm_domain *genpd, bool timed) { + unsigned int state_idx = genpd->state_idx; ktime_t time_start; s64 elapsed_ns; int ret; @@ -149,10 +151,10 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool timed) return ret; elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - if (elapsed_ns <= genpd->power_off_latency_ns) + if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns) return ret; - genpd->power_off_latency_ns = elapsed_ns; + genpd->states[state_idx].power_off_latency_ns = elapsed_ns; genpd->max_off_time_changed = true; pr_debug("%s: Power-%s latency exceeded, new value %lld ns\n", genpd->name, "off", elapsed_ns); @@ -585,6 +587,8 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd, || atomic_read(&genpd->sd_count) > 0) return; + /* Choose the deepest state when suspending */ + genpd->state_idx = genpd->state_count - 1; genpd_power_off(genpd, timed); genpd->status = GPD_STATE_POWER_OFF; @@ -1508,6 +1512,26 @@ void pm_genpd_init(struct generic_pm_domain *genpd, genpd->dev_ops.start = pm_clk_resume; } + if (genpd->state_idx >= GENPD_MAX_NUM_STATES) { + pr_warn("Initial state index out of bounds.\n"); + genpd->state_idx = GENPD_MAX_NUM_STATES - 1; + } + + if (genpd->state_count > GENPD_MAX_NUM_STATES) { + pr_warn("Limiting states to %d\n", GENPD_MAX_NUM_STATES); + genpd->state_count = GENPD_MAX_NUM_STATES; + } + + /* Use only one "off" state if there were no states declared */ + if (genpd->state_count == 0) { + genpd->states[0].power_on_latency_ns = + genpd->power_on_latency_ns; + genpd->states[0].power_off_latency_ns = + genpd->power_off_latency_ns; + + genpd->state_count = 1; + } + mutex_lock(&gpd_list_lock); list_add(&genpd->gpd_list_node, &gpd_list); mutex_unlock(&gpd_list_lock); @@ -1872,7 +1896,12 @@ static int pm_genpd_summary_one(struct seq_file *s, if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup))) goto exit; - seq_printf(s, "%-30s %-15s ", genpd->name, status_lookup[genpd->status]); + seq_printf(s, "%-30s %s", genpd->name, status_lookup[genpd->status]); + + if (genpd->status == GPD_STATE_POWER_OFF) + seq_printf(s, " %-13d ", genpd->state_idx); + else + seq_printf(s, " %-15s ", ""); /* * Modifications on the list require holding locks on both diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 1e937ac5f456..00a5436dd44b 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -98,7 +98,8 @@ static bool default_stop_ok(struct device *dev) * * This routine must be executed under the PM domain's lock. */ -static bool default_power_down_ok(struct dev_pm_domain *pd) +static bool __default_power_down_ok(struct dev_pm_domain *pd, + unsigned int state) { struct generic_pm_domain *genpd = pd_to_genpd(pd); struct gpd_link *link; @@ -106,27 +107,9 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) s64 min_off_time_ns; s64 off_on_time_ns; - if (genpd->max_off_time_changed) { - struct gpd_link *link; - - /* - * We have to invalidate the cached results for the masters, so - * use the observation that default_power_down_ok() is not - * going to be called for any master until this instance - * returns. - */ - list_for_each_entry(link, &genpd->slave_links, slave_node) - link->master->max_off_time_changed = true; - - genpd->max_off_time_changed = false; - genpd->cached_power_down_ok = false; - genpd->max_off_time_ns = -1; - } else { - return genpd->cached_power_down_ok; - } + off_on_time_ns = genpd->states[state].power_off_latency_ns + + genpd->states[state].power_on_latency_ns; - off_on_time_ns = genpd->power_off_latency_ns + - genpd->power_on_latency_ns; min_off_time_ns = -1; /* @@ -186,8 +169,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) min_off_time_ns = constraint_ns; } - genpd->cached_power_down_ok = true; - /* * If the computed minimum device off time is negative, there are no * latency constraints, so the domain can spend arbitrary time in the @@ -201,10 +182,45 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) * time and the time needed to turn the domain on is the maximum * theoretical time this domain can spend in the "off" state. */ - genpd->max_off_time_ns = min_off_time_ns - genpd->power_on_latency_ns; + genpd->max_off_time_ns = min_off_time_ns - + genpd->states[state].power_on_latency_ns; return true; } +static bool default_power_down_ok(struct dev_pm_domain *pd) +{ + struct generic_pm_domain *genpd = pd_to_genpd(pd); + struct gpd_link *link; + + if (!genpd->max_off_time_changed) + return genpd->cached_power_down_ok; + + /* + * We have to invalidate the cached results for the masters, so + * use the observation that default_power_down_ok() is not + * going to be called for any master until this instance + * returns. + */ + list_for_each_entry(link, &genpd->slave_links, slave_node) + link->master->max_off_time_changed = true; + + genpd->max_off_time_ns = -1; + genpd->max_off_time_changed = false; + genpd->cached_power_down_ok = true; + genpd->state_idx = genpd->state_count - 1; + + /* Find a state to power down to, starting from the deepest. */ + while (!__default_power_down_ok(pd, genpd->state_idx)) { + if (genpd->state_idx == 0) { + genpd->cached_power_down_ok = false; + break; + } + genpd->state_idx--; + } + + return genpd->cached_power_down_ok; +} + static bool always_on_power_down_ok(struct dev_pm_domain *domain) { return false; diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index db21d3995f7e..1726c4ac6529 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -19,6 +19,8 @@ /* Defines used for the flags field in the struct generic_pm_domain */ #define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */ +#define GENPD_MAX_NUM_STATES 8 /* Number of possible low power states */ + enum gpd_status { GPD_STATE_ACTIVE = 0, /* PM domain is active */ GPD_STATE_POWER_OFF, /* PM domain is off */ @@ -37,6 +39,11 @@ struct gpd_dev_ops { bool (*active_wakeup)(struct device *dev); }; +struct genpd_power_state { + s64 power_off_latency_ns; + s64 power_on_latency_ns; +}; + struct generic_pm_domain { struct dev_pm_domain domain; /* PM domain operations */ struct list_head gpd_list_node; /* Node in the global PM domains list */ @@ -66,6 +73,10 @@ struct generic_pm_domain { void (*detach_dev)(struct generic_pm_domain *domain, struct device *dev); unsigned int flags; /* Bit field of configs for genpd */ + struct genpd_power_state states[GENPD_MAX_NUM_STATES]; + unsigned int state_count; /* number of states */ + unsigned int state_idx; /* state that genpd will go to when off */ + }; static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd) -- cgit From eaa2d73ef9985f9e0fee7c3f04268c729100498d Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Mon, 15 Feb 2016 11:10:52 +0100 Subject: ARM: imx6: pm: declare pm domain latency on power_state struct The generic_pm_domain structure uses an array of latencies to be able to declare multiple intermediate states. Declare a single "OFF" state with the default latencies So that the power_off_latency_ns and power_on_latency_ns fields of generic_pm_domain structure can be eventually removed. [ Lina: pm_genpd_init() argument changev ] Signed-off-by: Lina Iyer Signed-off-by: Axel Haslam Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-imx/gpc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c index cfc696b972f3..fd8720532471 100644 --- a/arch/arm/mach-imx/gpc.c +++ b/arch/arm/mach-imx/gpc.c @@ -374,8 +374,13 @@ static struct pu_domain imx6q_pu_domain = { .name = "PU", .power_off = imx6q_pm_pu_power_off, .power_on = imx6q_pm_pu_power_on, - .power_off_latency_ns = 25000, - .power_on_latency_ns = 2000000, + .states = { + [0] = { + .power_off_latency_ns = 25000, + .power_on_latency_ns = 2000000, + }, + }, + .state_count = 1, }, }; -- cgit From 90e63452ac3a42c9ff10b12880429e8592cf39ec Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Mon, 15 Feb 2016 11:10:53 +0100 Subject: PM / Domains: remove old power on/off latencies Now that all known users have been converted to use state latencies, we can remove the latency field in the generic_pm_domain structure. Signed-off-by: Axel Haslam Acked-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 8 +------- include/linux/pm_domain.h | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 4c6f46b5c444..e8ca290dbf9d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1523,14 +1523,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd, } /* Use only one "off" state if there were no states declared */ - if (genpd->state_count == 0) { - genpd->states[0].power_on_latency_ns = - genpd->power_on_latency_ns; - genpd->states[0].power_off_latency_ns = - genpd->power_off_latency_ns; - + if (genpd->state_count == 0) genpd->state_count = 1; - } mutex_lock(&gpd_list_lock); list_add(&genpd->gpd_list_node, &gpd_list); diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 1726c4ac6529..49cd8890b873 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -61,9 +61,7 @@ struct generic_pm_domain { unsigned int prepared_count; /* Suspend counter of prepared devices */ bool suspend_power_off; /* Power status before system suspend */ int (*power_off)(struct generic_pm_domain *domain); - s64 power_off_latency_ns; int (*power_on)(struct generic_pm_domain *domain); - s64 power_on_latency_ns; struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ bool max_off_time_changed; -- cgit From 337ea0fb15358c1dafe7f4685a6281086b5bbb40 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 11 Feb 2016 12:06:37 +0100 Subject: pinctrl: Turn AMD support to tristate The pinctrl-amd driver builds just fine as a module so give users this option. Signed-off-by: Jean Delvare Cc: Linus Walleij Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index a4c07394e313..fb8200b8e8ec 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -79,7 +79,7 @@ config PINCTRL_AT91PIO4 controller available on sama5d2 SoC. config PINCTRL_AMD - bool "AMD GPIO pin control" + tristate "AMD GPIO pin control" depends on GPIOLIB select GPIOLIB_IRQCHIP select PINCONF -- cgit From 22aeddb58dcc920cf2f78652c01272d9dff3d30a Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Mon, 1 Feb 2016 18:51:49 -0500 Subject: gpio: misc: Pass correct license string to MODULE_LICENSE The GPIO driver copyright boilerplate lacks the "or later" verbiage regarding GPL compliant distribution. The MODULE_LICENSE string should reflect the actual copyright license terms used. Signed-off-by: William Breathitt Gray Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-dio-48e.c | 2 +- drivers/gpio/gpio-104-idi-48.c | 2 +- drivers/gpio/gpio-104-idio-16.c | 2 +- drivers/gpio/gpio-ws16c48.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 279de392ac6c..1134a08304b0 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -436,4 +436,4 @@ module_exit(dio48e_exit); MODULE_AUTHOR("William Breathitt Gray "); MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 285a075e1fd7..49b1188d1b16 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -341,4 +341,4 @@ module_exit(idi_48_exit); MODULE_AUTHOR("William Breathitt Gray "); MODULE_DESCRIPTION("ACCES 104-IDI-48 GPIO driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 4d69b50b2d84..d0f797662845 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -317,4 +317,4 @@ module_exit(idio_16_exit); MODULE_AUTHOR("William Breathitt Gray "); MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index 9dd947993476..d5279a0a85bd 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c @@ -433,4 +433,4 @@ module_exit(ws16c48_exit); MODULE_AUTHOR("William Breathitt Gray "); MODULE_DESCRIPTION("WinSystems WS16C48 GPIO driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); -- cgit From aa6c3602264e3dbdbccac79e125aafee261fdf7b Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:15:21 -0500 Subject: gpio: 104-dio-48e: Use devm_request_region By the time request_region is called in the ACCES 104-DIO-48E GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-dio-48e.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 1134a08304b0..448a903089ef 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -40,7 +40,6 @@ MODULE_PARM_DESC(dio_48e_irq, "ACCES 104-DIO-48E interrupt line number"); * @control: Control registers state * @lock: synchronization lock to prevent I/O race conditions * @base: base port address of the GPIO device - * @extent: extent of port address region of the GPIO device * @irq: Interrupt line number * @irq_mask: I/O bits affected by interrupts */ @@ -51,7 +50,6 @@ struct dio48e_gpio { unsigned char control[2]; spinlock_t lock; unsigned base; - unsigned extent; unsigned irq; unsigned char irq_mask; }; @@ -310,11 +308,10 @@ static int __init dio48e_probe(struct platform_device *pdev) if (!dio48egpio) return -ENOMEM; - if (!request_region(base, extent, name)) { - dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", - name, base, base + extent); - err = -EBUSY; - goto err_lock_io_port; + if (!devm_request_region(dev, base, extent, name)) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base, base + extent); + return -EBUSY; } dio48egpio->chip.label = name; @@ -328,7 +325,6 @@ static int __init dio48e_probe(struct platform_device *pdev) dio48egpio->chip.get = dio48e_gpio_get; dio48egpio->chip.set = dio48e_gpio_set; dio48egpio->base = base; - dio48egpio->extent = extent; dio48egpio->irq = irq; spin_lock_init(&dio48egpio->lock); @@ -338,7 +334,7 @@ static int __init dio48e_probe(struct platform_device *pdev) err = gpiochip_add_data(&dio48egpio->chip, dio48egpio); if (err) { dev_err(dev, "GPIO registering failed (%d)\n", err); - goto err_gpio_register; + return err; } /* initialize all GPIO as output */ @@ -360,23 +356,19 @@ static int __init dio48e_probe(struct platform_device *pdev) handle_edge_irq, IRQ_TYPE_NONE); if (err) { dev_err(dev, "Could not add irqchip (%d)\n", err); - goto err_gpiochip_irqchip_add; + goto err_gpiochip_remove; } err = request_irq(irq, dio48e_irq_handler, 0, name, dio48egpio); if (err) { dev_err(dev, "IRQ handler registering failed (%d)\n", err); - goto err_request_irq; + goto err_gpiochip_remove; } return 0; -err_request_irq: -err_gpiochip_irqchip_add: +err_gpiochip_remove: gpiochip_remove(&dio48egpio->chip); -err_gpio_register: - release_region(base, extent); -err_lock_io_port: return err; } @@ -386,7 +378,6 @@ static int dio48e_remove(struct platform_device *pdev) free_irq(dio48egpio->irq, dio48egpio); gpiochip_remove(&dio48egpio->chip); - release_region(dio48egpio->base, dio48egpio->extent); return 0; } -- cgit From 5cfc05761ba0c7f1aa04f0d441fb68a28453d13b Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:15:22 -0500 Subject: gpio: 104-idi-48: Use devm_request_region By the time request_region is called in the ACCES 104-IDI-48 GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idi-48.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c index 49b1188d1b16..e37cd4cdda35 100644 --- a/drivers/gpio/gpio-104-idi-48.c +++ b/drivers/gpio/gpio-104-idi-48.c @@ -39,7 +39,6 @@ MODULE_PARM_DESC(idi_48_irq, "ACCES 104-IDI-48 interrupt line number"); * @ack_lock: synchronization lock to prevent IRQ handler race conditions * @irq_mask: input bits affected by interrupts * @base: base port address of the GPIO device - * @extent: extent of port address region of the GPIO device * @irq: Interrupt line number * @cos_enb: Change-Of-State IRQ enable boundaries mask */ @@ -49,7 +48,6 @@ struct idi_48_gpio { spinlock_t ack_lock; unsigned char irq_mask[6]; unsigned base; - unsigned extent; unsigned irq; unsigned char cos_enb; }; @@ -227,11 +225,10 @@ static int __init idi_48_probe(struct platform_device *pdev) if (!idi48gpio) return -ENOMEM; - if (!request_region(base, extent, name)) { - dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", - name, base, base + extent); - err = -EBUSY; - goto err_lock_io_port; + if (!devm_request_region(dev, base, extent, name)) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base, base + extent); + return -EBUSY; } idi48gpio->chip.label = name; @@ -243,7 +240,6 @@ static int __init idi_48_probe(struct platform_device *pdev) idi48gpio->chip.direction_input = idi_48_gpio_direction_input; idi48gpio->chip.get = idi_48_gpio_get; idi48gpio->base = base; - idi48gpio->extent = extent; idi48gpio->irq = irq; spin_lock_init(&idi48gpio->lock); @@ -253,7 +249,7 @@ static int __init idi_48_probe(struct platform_device *pdev) err = gpiochip_add_data(&idi48gpio->chip, idi48gpio); if (err) { dev_err(dev, "GPIO registering failed (%d)\n", err); - goto err_gpio_register; + return err; } /* Disable IRQ by default */ @@ -264,24 +260,20 @@ static int __init idi_48_probe(struct platform_device *pdev) handle_edge_irq, IRQ_TYPE_NONE); if (err) { dev_err(dev, "Could not add irqchip (%d)\n", err); - goto err_gpiochip_irqchip_add; + goto err_gpiochip_remove; } err = request_irq(irq, idi_48_irq_handler, IRQF_SHARED, name, idi48gpio); if (err) { dev_err(dev, "IRQ handler registering failed (%d)\n", err); - goto err_request_irq; + goto err_gpiochip_remove; } return 0; -err_request_irq: -err_gpiochip_irqchip_add: +err_gpiochip_remove: gpiochip_remove(&idi48gpio->chip); -err_gpio_register: - release_region(base, extent); -err_lock_io_port: return err; } @@ -291,7 +283,6 @@ static int idi_48_remove(struct platform_device *pdev) free_irq(idi48gpio->irq, idi48gpio); gpiochip_remove(&idi48gpio->chip); - release_region(idi48gpio->base, idi48gpio->extent); return 0; } -- cgit From cb32389cb9b36e4a40ecca5c10e5a80af2e97b07 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:17:02 -0500 Subject: gpio: 104-idio-16: Use devm_request_region By the time request_region is called in the ACCES 104-IDIO-16 GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-104-idio-16.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index d0f797662845..ecc85fe9323d 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -38,7 +38,6 @@ MODULE_PARM_DESC(idio_16_irq, "ACCES 104-IDIO-16 interrupt line number"); * @lock: synchronization lock to prevent I/O race conditions * @irq_mask: I/O bits affected by interrupts * @base: base port address of the GPIO device - * @extent: extent of port address region of the GPIO device * @irq: Interrupt line number * @out_state: output bits state */ @@ -47,7 +46,6 @@ struct idio_16_gpio { spinlock_t lock; unsigned long irq_mask; unsigned base; - unsigned extent; unsigned irq; unsigned out_state; }; @@ -201,11 +199,10 @@ static int __init idio_16_probe(struct platform_device *pdev) if (!idio16gpio) return -ENOMEM; - if (!request_region(base, extent, name)) { - dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", - name, base, base + extent); - err = -EBUSY; - goto err_lock_io_port; + if (!devm_request_region(dev, base, extent, name)) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base, base + extent); + return -EBUSY; } idio16gpio->chip.label = name; @@ -219,7 +216,6 @@ static int __init idio_16_probe(struct platform_device *pdev) idio16gpio->chip.get = idio_16_gpio_get; idio16gpio->chip.set = idio_16_gpio_set; idio16gpio->base = base; - idio16gpio->extent = extent; idio16gpio->irq = irq; idio16gpio->out_state = 0xFFFF; @@ -230,7 +226,7 @@ static int __init idio_16_probe(struct platform_device *pdev) err = gpiochip_add_data(&idio16gpio->chip, idio16gpio); if (err) { dev_err(dev, "GPIO registering failed (%d)\n", err); - goto err_gpio_register; + return err; } /* Disable IRQ by default */ @@ -241,23 +237,19 @@ static int __init idio_16_probe(struct platform_device *pdev) handle_edge_irq, IRQ_TYPE_NONE); if (err) { dev_err(dev, "Could not add irqchip (%d)\n", err); - goto err_gpiochip_irqchip_add; + goto err_gpiochip_remove; } err = request_irq(irq, idio_16_irq_handler, 0, name, idio16gpio); if (err) { dev_err(dev, "IRQ handler registering failed (%d)\n", err); - goto err_request_irq; + goto err_gpiochip_remove; } return 0; -err_request_irq: -err_gpiochip_irqchip_add: +err_gpiochip_remove: gpiochip_remove(&idio16gpio->chip); -err_gpio_register: - release_region(base, extent); -err_lock_io_port: return err; } @@ -267,7 +259,6 @@ static int idio_16_remove(struct platform_device *pdev) free_irq(idio16gpio->irq, idio16gpio); gpiochip_remove(&idio16gpio->chip); - release_region(idio16gpio->base, idio16gpio->extent); return 0; } -- cgit From 35568c40bd26a9036a48299f4fd0192f4fa8e6aa Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:17:13 -0500 Subject: gpio: amd8111: Use devm_request_region By the time request_region is called in the AMD 8111 GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-amd8111.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpio/gpio-amd8111.c b/drivers/gpio/gpio-amd8111.c index c7040fffc5b4..30ad7d7c1678 100644 --- a/drivers/gpio/gpio-amd8111.c +++ b/drivers/gpio/gpio-amd8111.c @@ -25,6 +25,7 @@ * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ +#include #include #include #include @@ -204,7 +205,8 @@ found: gp.pmbase &= 0x0000FF00; if (gp.pmbase == 0) goto out; - if (!request_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE, "AMD GPIO")) { + if (!devm_request_region(&pdev->dev, gp.pmbase + PMBASE_OFFSET, + PMBASE_SIZE, "AMD GPIO")) { dev_err(&pdev->dev, "AMD GPIO region 0x%x already in use!\n", gp.pmbase + PMBASE_OFFSET); err = -EBUSY; @@ -213,7 +215,6 @@ found: gp.pm = ioport_map(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); if (!gp.pm) { dev_err(&pdev->dev, "Couldn't map io port into io memory\n"); - release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); err = -ENOMEM; goto out; } @@ -228,7 +229,6 @@ found: printk(KERN_ERR "GPIO registering failed (%d)\n", err); ioport_unmap(gp.pm); - release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); goto out; } out: @@ -239,7 +239,6 @@ static void __exit amd_gpio_exit(void) { gpiochip_remove(&gp.chip); ioport_unmap(gp.pm); - release_region(gp.pmbase + PMBASE_OFFSET, PMBASE_SIZE); } module_init(amd_gpio_init); -- cgit From 8a06b08ec30723fe0064d3e7bbd1231977d9ea73 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:17:27 -0500 Subject: gpio: ich: Use devm_request_region By the time request_region is called in the Intel ICH series GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Cc: Peter Tyser Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ich.c | 51 +++++++++---------------------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index a4893386abbf..4f6d643516b7 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c @@ -20,6 +20,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -384,8 +385,8 @@ static struct ichx_desc avoton_desc = { .use_outlvl_cache = true, }; -static int ichx_gpio_request_regions(struct resource *res_base, - const char *name, u8 use_gpio) +static int ichx_gpio_request_regions(struct device *dev, + struct resource *res_base, const char *name, u8 use_gpio) { int i; @@ -395,34 +396,12 @@ static int ichx_gpio_request_regions(struct resource *res_base, for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { if (!(use_gpio & (1 << i))) continue; - if (!request_region( + if (!devm_request_region(dev, res_base->start + ichx_priv.desc->regs[0][i], ichx_priv.desc->reglen[i], name)) - goto request_err; + return -EBUSY; } return 0; - -request_err: - /* Clean up: release already requested regions, if any */ - for (i--; i >= 0; i--) { - if (!(use_gpio & (1 << i))) - continue; - release_region(res_base->start + ichx_priv.desc->regs[0][i], - ichx_priv.desc->reglen[i]); - } - return -EBUSY; -} - -static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { - if (!(use_gpio & (1 << i))) - continue; - release_region(res_base->start + ichx_priv.desc->regs[0][i], - ichx_priv.desc->reglen[i]); - } } static int ichx_gpio_probe(struct platform_device *pdev) @@ -468,7 +447,7 @@ static int ichx_gpio_probe(struct platform_device *pdev) spin_lock_init(&ichx_priv.lock); res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); ichx_priv.use_gpio = ich_info->use_gpio; - err = ichx_gpio_request_regions(res_base, pdev->name, + err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name, ichx_priv.use_gpio); if (err) return err; @@ -489,8 +468,8 @@ static int ichx_gpio_probe(struct platform_device *pdev) goto init; } - if (!request_region(res_pm->start, resource_size(res_pm), - pdev->name)) { + if (!devm_request_region(&pdev->dev, res_pm->start, + resource_size(res_pm), pdev->name)) { pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); goto init; } @@ -502,31 +481,19 @@ init: err = gpiochip_add_data(&ichx_priv.chip, NULL); if (err) { pr_err("Failed to register GPIOs\n"); - goto add_err; + return err; } pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); return 0; - -add_err: - ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio); - if (ichx_priv.pm_base) - release_region(ichx_priv.pm_base->start, - resource_size(ichx_priv.pm_base)); - return err; } static int ichx_gpio_remove(struct platform_device *pdev) { gpiochip_remove(&ichx_priv.chip); - ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio); - if (ichx_priv.pm_base) - release_region(ichx_priv.pm_base->start, - resource_size(ichx_priv.pm_base)); - return 0; } -- cgit From 134414578518f095b65185535bc696277b5c57c6 Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:17:40 -0500 Subject: gpio: sch311x: Use devm_request_region By the time request_region is called in the SMSC SCH311x GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-sch311x.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpio/gpio-sch311x.c b/drivers/gpio/gpio-sch311x.c index 1cbd77a04e7b..a03b38ee2e02 100644 --- a/drivers/gpio/gpio-sch311x.c +++ b/drivers/gpio/gpio-sch311x.c @@ -12,6 +12,7 @@ * (at your option) any later version. */ +#include #include #include #include @@ -228,7 +229,8 @@ static int sch311x_gpio_probe(struct platform_device *pdev) int err, i; /* we can register all GPIO data registers at once */ - if (!request_region(pdata->runtime_reg + GP1, 6, DRV_NAME)) { + if (!devm_request_region(&pdev->dev, pdata->runtime_reg + GP1, 6, + DRV_NAME)) { dev_err(&pdev->dev, "Failed to request region 0x%04x-0x%04x.\n", pdata->runtime_reg + GP1, pdata->runtime_reg + GP1 + 5); return -EBUSY; @@ -273,7 +275,6 @@ static int sch311x_gpio_probe(struct platform_device *pdev) return 0; exit_err: - release_region(pdata->runtime_reg + GP1, 6); /* release already registered chips */ for (--i; i >= 0; i--) gpiochip_remove(&priv->blocks[i].chip); @@ -282,12 +283,9 @@ exit_err: static int sch311x_gpio_remove(struct platform_device *pdev) { - struct sch311x_pdev_data *pdata = dev_get_platdata(&pdev->dev); struct sch311x_gpio_priv *priv = platform_get_drvdata(pdev); int i; - release_region(pdata->runtime_reg + GP1, 6); - for (i = 0; i < ARRAY_SIZE(priv->blocks); i++) { gpiochip_remove(&priv->blocks[i].chip); dev_info(&pdev->dev, -- cgit From 148ad68b3d0dd0f0068ff5f6f47bc360011c429e Mon Sep 17 00:00:00 2001 From: William Breathitt Gray Date: Wed, 3 Feb 2016 15:17:50 -0500 Subject: gpio: ws16c48: Use devm_request_region By the time request_region is called in the WinSystems WS16C48 GPIO driver, a corresponding device structure has already been allocated. The devm_request_region function should be used to help simplify the cleanup code and reduce the possible points of failure. Signed-off-by: William Breathitt Gray Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ws16c48.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index d5279a0a85bd..51f41e8fd21e 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c @@ -41,7 +41,6 @@ MODULE_PARM_DESC(ws16c48_irq, "WinSystems WS16C48 interrupt line number"); * @irq_mask: I/O bits affected by interrupts * @flow_mask: IRQ flow type mask for the respective I/O bits * @base: base port address of the GPIO device - * @extent: extent of port address region of the GPIO device * @irq: Interrupt line number */ struct ws16c48_gpio { @@ -52,7 +51,6 @@ struct ws16c48_gpio { unsigned long irq_mask; unsigned long flow_mask; unsigned base; - unsigned extent; unsigned irq; }; @@ -314,11 +312,10 @@ static int __init ws16c48_probe(struct platform_device *pdev) if (!ws16c48gpio) return -ENOMEM; - if (!request_region(base, extent, name)) { - dev_err(dev, "Unable to lock %s port addresses (0x%X-0x%X)\n", - name, base, base + extent); - err = -EBUSY; - goto err_lock_io_port; + if (!devm_request_region(dev, base, extent, name)) { + dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", + base, base + extent); + return -EBUSY; } ws16c48gpio->chip.label = name; @@ -332,7 +329,6 @@ static int __init ws16c48_probe(struct platform_device *pdev) ws16c48gpio->chip.get = ws16c48_gpio_get; ws16c48gpio->chip.set = ws16c48_gpio_set; ws16c48gpio->base = base; - ws16c48gpio->extent = extent; ws16c48gpio->irq = irq; spin_lock_init(&ws16c48gpio->lock); @@ -342,7 +338,7 @@ static int __init ws16c48_probe(struct platform_device *pdev) err = gpiochip_add_data(&ws16c48gpio->chip, ws16c48gpio); if (err) { dev_err(dev, "GPIO registering failed (%d)\n", err); - goto err_gpio_register; + return err; } /* Disable IRQ by default */ @@ -356,24 +352,20 @@ static int __init ws16c48_probe(struct platform_device *pdev) handle_edge_irq, IRQ_TYPE_NONE); if (err) { dev_err(dev, "Could not add irqchip (%d)\n", err); - goto err_gpiochip_irqchip_add; + goto err_gpiochip_remove; } err = request_irq(irq, ws16c48_irq_handler, IRQF_SHARED, name, ws16c48gpio); if (err) { dev_err(dev, "IRQ handler registering failed (%d)\n", err); - goto err_request_irq; + goto err_gpiochip_remove; } return 0; -err_request_irq: -err_gpiochip_irqchip_add: +err_gpiochip_remove: gpiochip_remove(&ws16c48gpio->chip); -err_gpio_register: - release_region(base, extent); -err_lock_io_port: return err; } @@ -383,7 +375,6 @@ static int ws16c48_remove(struct platform_device *pdev) free_irq(ws16c48gpio->irq, ws16c48gpio); gpiochip_remove(&ws16c48gpio->chip); - release_region(ws16c48gpio->base, ws16c48gpio->extent); return 0; } -- cgit From 4e6fd26dcf5d70a7700a4c15d8f239103bdce91d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 12 Feb 2016 09:22:11 +0100 Subject: pinctrl: sirf/atlas7: stop poking around in GPIO internals This code is poking around in the gpio_chip:s internal structures to achieve some kind of pin to GPIO mappings. - It is wrong to poke around in these structs and the pinctrl maintainer was stupid to let it pass unnoticed, mea culpa. - The right interface to use is gpiochip_add_pin_range() - The code appears unused: the pin control part of the driver is not adding any ranges, so we're iterating over an empty list. Maybe it is poking around in some other pin controllers GPIO ranges, and that's just totally wrong, again use gpiochip_add_pin_range() and specify the right pin controller. Cc: Barry Song Cc: Guoying Zhang Cc: Wei Chen Signed-off-by: Linus Walleij --- drivers/pinctrl/sirf/pinctrl-atlas7.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c index beb024c31a5d..3d233fc3448a 100644 --- a/drivers/pinctrl/sirf/pinctrl-atlas7.c +++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c @@ -338,7 +338,6 @@ struct atlas7_pinctrl_data { #define ATLAS7_GPIO_CTL_DATAIN_MASK BIT(7) struct atlas7_gpio_bank { - struct pinctrl_dev *pctldev; int id; int irq; void __iomem *base; @@ -6070,7 +6069,6 @@ static int atlas7_gpio_probe(struct platform_device *pdev) } for (idx = 0; idx < nbank; idx++) { - struct gpio_pin_range *pin_range; struct atlas7_gpio_bank *bank; bank = &a7gc->banks[idx]; @@ -6088,22 +6086,6 @@ static int atlas7_gpio_probe(struct platform_device *pdev) gpiochip_set_chained_irqchip(chip, &atlas7_gpio_irq_chip, bank->irq, atlas7_gpio_handle_irq); - - /* Records gpio_pin_range to a7gc */ - list_for_each_entry(pin_range, &chip->pin_ranges, node) { - struct pinctrl_gpio_range *range; - - range = &pin_range->range; - if (range->id == NGPIO_OF_BANK * idx) { - bank->gpio_offset = range->id; - bank->ngpio = range->npins; - bank->gpio_pins = range->pins; - bank->pctldev = pin_range->pctldev; - break; - } - } - - BUG_ON(!bank->pctldev); } platform_set_drvdata(pdev, a7gc); -- cgit From 20ec3e39fc12cf3a331ee73eb01d52bddcdd2fa4 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 11 Feb 2016 11:03:06 +0100 Subject: gpio: move the pin ranges into gpio_device Instead of keeping this reference to the pin ranges in the client driver-supplied gpio_chip, move it to the internal gpio_device as the drivers have no need to inspect this. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib-acpi.c | 18 +++++++++--------- drivers/gpio/gpiolib.c | 10 +++++----- drivers/gpio/gpiolib.h | 10 ++++++++++ include/linux/gpio/driver.h | 9 --------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 540cbc88c7a2..682070d20f00 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -71,29 +71,29 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) * controller uses pin controller and the mapping is not contiguous the * offset might be different. */ -static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_chip *chip, int pin) +static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev, int pin) { struct gpio_pin_range *pin_range; /* If there are no ranges in this chip, use 1:1 mapping */ - if (list_empty(&chip->pin_ranges)) + if (list_empty(&gdev->pin_ranges)) return pin; - list_for_each_entry(pin_range, &chip->pin_ranges, node) { + list_for_each_entry(pin_range, &gdev->pin_ranges, node) { const struct pinctrl_gpio_range *range = &pin_range->range; int i; if (range->pins) { for (i = 0; i < range->npins; i++) { if (range->pins[i] == pin) - return range->base + i - chip->base; + return range->base + i - gdev->base; } } else { if (pin >= range->pin_base && pin < range->pin_base + range->npins) { unsigned gpio_base; - gpio_base = range->base - chip->base; + gpio_base = range->base - gdev->base; return gpio_base + pin - range->pin_base; } } @@ -102,7 +102,7 @@ static int acpi_gpiochip_pin_to_gpio_offset(struct gpio_chip *chip, int pin) return -EINVAL; } #else -static inline int acpi_gpiochip_pin_to_gpio_offset(struct gpio_chip *chip, +static inline int acpi_gpiochip_pin_to_gpio_offset(struct gpio_device *gdev, int pin) { return pin; @@ -134,7 +134,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin) if (!chip) return ERR_PTR(-EPROBE_DEFER); - offset = acpi_gpiochip_pin_to_gpio_offset(chip, pin); + offset = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin); if (offset < 0) return ERR_PTR(offset); @@ -202,7 +202,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, if (!handler) return AE_BAD_PARAMETER; - pin = acpi_gpiochip_pin_to_gpio_offset(chip, pin); + pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin); if (pin < 0) return AE_BAD_PARAMETER; @@ -673,7 +673,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, struct gpio_desc *desc; bool found; - pin = acpi_gpiochip_pin_to_gpio_offset(chip, pin); + pin = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, pin); if (pin < 0) { status = AE_BAD_PARAMETER; goto out; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 646dea4f96ff..28984bbc079c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -532,8 +532,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) spin_unlock_irqrestore(&gpio_lock, flags); #ifdef CONFIG_PINCTRL - /* FIXME: move pin ranges to gpio_device */ - INIT_LIST_HEAD(&chip->pin_ranges); + INIT_LIST_HEAD(&gdev->pin_ranges); #endif status = gpiochip_set_desc_names(chip); @@ -1036,7 +1035,7 @@ int gpiochip_add_pingroup_range(struct gpio_chip *chip, gpio_offset, gpio_offset + pin_range->range.npins - 1, pinctrl_dev_get_devname(pctldev), pin_group); - list_add_tail(&pin_range->node, &chip->pin_ranges); + list_add_tail(&pin_range->node, &gdev->pin_ranges); return 0; } @@ -1085,7 +1084,7 @@ int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name, pinctl_name, pin_offset, pin_offset + npins - 1); - list_add_tail(&pin_range->node, &chip->pin_ranges); + list_add_tail(&pin_range->node, &gdev->pin_ranges); return 0; } @@ -1098,8 +1097,9 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pin_range); void gpiochip_remove_pin_ranges(struct gpio_chip *chip) { struct gpio_pin_range *pin_range, *tmp; + struct gpio_device *gdev = chip->gpiodev; - list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) { + list_for_each_entry_safe(pin_range, tmp, &gdev->pin_ranges, node) { list_del(&pin_range->node); pinctrl_remove_gpio_range(pin_range->pctldev, &pin_range->range); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index d154984c71d9..5a36908fd39d 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -55,6 +55,16 @@ struct gpio_device { int base; u16 ngpio; struct list_head list; + +#ifdef CONFIG_PINCTRL + /* + * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally + * describe the actual pin range which they serve in an SoC. This + * information would be used by pinctrl subsystem to configure + * corresponding pins for gpio usage. + */ + struct list_head pin_ranges; +#endif }; /** diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 41c6144c473b..e2a934ce3e64 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -181,15 +181,6 @@ struct gpio_chip { int (*of_xlate)(struct gpio_chip *gc, const struct of_phandle_args *gpiospec, u32 *flags); #endif -#ifdef CONFIG_PINCTRL - /* - * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally - * describe the actual pin range which they serve in an SoC. This - * information would be used by pinctrl subsystem to configure - * corresponding pins for gpio usage. - */ - struct list_head pin_ranges; -#endif }; extern const char *gpiochip_is_requested(struct gpio_chip *chip, -- cgit From 43c54ecade400cf6ca8203f960b525fbe5b73a13 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 11 Feb 2016 11:37:48 +0100 Subject: gpio: move the subdriver data pointer into gpio_device We move to manage this pointer under gpiolib control rather than leave it in the subdevice's gpio_chip. We can not NULL it after gpiochip_remove so at to keep things tight. Signed-off-by: Linus Walleij --- drivers/gpio/gpiolib.c | 17 +++++++++++++++-- drivers/gpio/gpiolib.h | 2 ++ include/linux/gpio/driver.h | 7 +------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 28984bbc079c..aa4a60e19339 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -480,8 +480,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data) goto err_free_gdev; } gdev->ngpio = chip->ngpio; - /* FIXME: move driver data into gpio_device dev_set_drvdata() */ - chip->data = data; + gdev->data = data; spin_lock_irqsave(&gpio_lock, flags); @@ -602,6 +601,15 @@ err_free_gdev: } EXPORT_SYMBOL_GPL(gpiochip_add_data); +/** + * gpiochip_get_data() - get per-subdriver data for the chip + */ +void *gpiochip_get_data(struct gpio_chip *chip) +{ + return chip->gpiodev->data; +} +EXPORT_SYMBOL_GPL(gpiochip_get_data); + /** * gpiochip_remove() - unregister a gpio_chip * @chip: the chip to unregister @@ -626,6 +634,11 @@ void gpiochip_remove(struct gpio_chip *chip) gpiochip_remove_pin_ranges(chip); gpiochip_free_hogs(chip); of_gpiochip_remove(chip); + /* + * We accept no more calls into the driver from this point, so + * NULL the driver data pointer + */ + gdev->data = NULL; spin_lock_irqsave(&gpio_lock, flags); for (i = 0; i < gdev->ngpio; i++) { diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 5a36908fd39d..ddbe409ad48f 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -37,6 +37,7 @@ struct acpi_device; * of the @descs array. * @base: GPIO base in the DEPRECATED global Linux GPIO numberspace, assigned * at device creation time. + * @data: per-instance data assigned by the driver * @list: links gpio_device:s together for traversal * * This state container holds most of the runtime variable data @@ -54,6 +55,7 @@ struct gpio_device { struct gpio_desc *descs; int base; u16 ngpio; + void *data; struct list_head list; #ifdef CONFIG_PINCTRL diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index e2a934ce3e64..b92ab9efdb69 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -25,7 +25,6 @@ struct gpio_device; * @gpiodev: the internal state holder, opaque struct * @parent: optional parent device providing the GPIOs * @owner: helps prevent removal of modules exporting active GPIOs - * @data: per-instance data assigned by the driver * @request: optional hook for chip-specific activation, such as * enabling module power and clock; may sleep * @free: optional hook for chip-specific deactivation, such as @@ -109,7 +108,6 @@ struct gpio_chip { struct gpio_device *gpiodev; struct device *parent; struct module *owner; - void *data; int (*request)(struct gpio_chip *chip, unsigned offset); @@ -202,10 +200,7 @@ void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset); bool gpiochip_line_is_irq(struct gpio_chip *chip, unsigned int offset); /* get driver data */ -static inline void *gpiochip_get_data(struct gpio_chip *chip) -{ - return chip->data; -} +void *gpiochip_get_data(struct gpio_chip *chip); struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc); -- cgit From 047b2f62cda57eba73751b29f3cf3ef6d17ae84f Mon Sep 17 00:00:00 2001 From: Julien Grossholtz Date: Wed, 10 Feb 2016 12:20:34 -0500 Subject: gpio: TS-4800: remove useless bgpio_init flags No flags are required for bgpio_init in the TS-4800 gpio driver. This patch set zero instead. The driver will have the same behaviour since the & operator between the flags already resulted to zero. Fixes: 5041e791440a ("gpio: add TS-4800 fpga GPIO support") Signed-off-by: Julien Grossholtz Signed-off-by: Linus Walleij --- drivers/gpio/gpio-ts4800.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c index c4908a45c523..9da79e4a67c5 100644 --- a/drivers/gpio/gpio-ts4800.c +++ b/drivers/gpio/gpio-ts4800.c @@ -48,8 +48,7 @@ static int ts4800_gpio_probe(struct platform_device *pdev) retval = bgpio_init(chip, &pdev->dev, 2, base_addr + INPUT_REG_OFFSET, base_addr + OUTPUT_REG_OFFSET, NULL, - base_addr + DIRECTION_REG_OFFSET, NULL, - BGPIOF_BIG_ENDIAN & BGPIOF_BIG_ENDIAN_BYTE_ORDER); + base_addr + DIRECTION_REG_OFFSET, NULL, 0); if (retval) { dev_err(&pdev->dev, "bgpio_init failed\n"); return retval; -- cgit From 288e6eaa06877ea925d8dcdac5e56310fa6d8c7c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 2 Feb 2016 13:53:23 -0600 Subject: gpio: Include linux/gpio.h instead of asm/gpio.h Most arches have an asm/gpio.h that merely includes linux/gpio.h. The others select ARCH_HAVE_CUSTOM_GPIO_H, and when that's selected, linux/gpio.h includes asm/gpio.h. Therefore, code should include linux/gpio.h instead of including asm/gpio.h directly. Remove includes of asm/gpio.h, adding an include of linux/gpio.h when necessary. This is a follow-on to 7563bbf89d06 ("gpiolib/arches: Centralise bolierplate asm/gpio.h"). Signed-off-by: Bjorn Helgaas Acked-by: Thomas Gleixner Acked-by: Arnd Bergmann Acked-by: Alexandre Courbot Signed-off-by: Linus Walleij --- arch/avr32/boards/merisc/setup.c | 1 - arch/avr32/mach-at32ap/pio.c | 2 +- arch/blackfin/kernel/debug-mmrs.c | 2 +- arch/blackfin/mach-bf538/boards/ezkit.c | 2 +- arch/blackfin/mach-bf538/ext-gpio.c | 2 +- arch/blackfin/mach-bf548/boards/cm_bf548.c | 2 +- arch/blackfin/mach-bf548/boards/ezkit.c | 2 +- arch/blackfin/mach-bf609/boards/ezkit.c | 2 +- arch/blackfin/mach-common/ints-priority.c | 2 +- arch/blackfin/mach-common/pm.c | 2 +- arch/sh/include/mach-common/mach/magicpanelr2.h | 2 +- drivers/ata/pata_at91.c | 3 +-- drivers/ata/pata_bf54x.c | 2 +- drivers/gpio/gpio-mpc5200.c | 1 - drivers/mfd/menelaus.c | 2 +- drivers/mtd/onenand/omap2.c | 2 +- drivers/pcmcia/bfin_cf_pcmcia.c | 2 +- drivers/pcmcia/pxa2xx_vpac270.c | 1 - drivers/usb/gadget/udc/atmel_usba_udc.c | 2 -- drivers/usb/host/ohci-at91.c | 2 -- drivers/video/fbdev/atmel_lcdfb.c | 2 -- drivers/video/fbdev/omap/lcd_h3.c | 2 +- drivers/video/fbdev/omap/lcd_osk.c | 3 +-- drivers/video/fbdev/omap/lcd_palmtt.c | 2 +- 24 files changed, 18 insertions(+), 29 deletions(-) diff --git a/arch/avr32/boards/merisc/setup.c b/arch/avr32/boards/merisc/setup.c index 83d896cc2aed..718a6d7eb808 100644 --- a/arch/avr32/boards/merisc/setup.c +++ b/arch/avr32/boards/merisc/setup.c @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 5020057ac7a2..83c2a0021b56 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c @@ -14,8 +14,8 @@ #include #include #include +#include -#include #include #include diff --git a/arch/blackfin/kernel/debug-mmrs.c b/arch/blackfin/kernel/debug-mmrs.c index 86b1cd3a0309..e272bca93c64 100644 --- a/arch/blackfin/kernel/debug-mmrs.c +++ b/arch/blackfin/kernel/debug-mmrs.c @@ -11,9 +11,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c index ae2fcbb00119..c423af36fa91 100644 --- a/arch/blackfin/mach-bf538/boards/ezkit.c +++ b/arch/blackfin/mach-bf538/boards/ezkit.c @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/blackfin/mach-bf538/ext-gpio.c b/arch/blackfin/mach-bf538/ext-gpio.c index 471a9b184d5b..d3e7b66ac8d5 100644 --- a/arch/blackfin/mach-bf538/ext-gpio.c +++ b/arch/blackfin/mach-bf538/ext-gpio.c @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #define DEFINE_REG(reg, off) \ diff --git a/arch/blackfin/mach-bf548/boards/cm_bf548.c b/arch/blackfin/mach-bf548/boards/cm_bf548.c index 6d5ffdead067..120c9941c242 100644 --- a/arch/blackfin/mach-bf548/boards/cm_bf548.c +++ b/arch/blackfin/mach-bf548/boards/cm_bf548.c @@ -17,9 +17,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 4204b9842532..3cdd4835a9f7 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -20,9 +20,9 @@ #include #include #include +#include #include #include -#include #include #include #include diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c index c7928d8ebb82..aad5d7416886 100644 --- a/arch/blackfin/mach-bf609/boards/ezkit.c +++ b/arch/blackfin/mach-bf609/boards/ezkit.c @@ -21,8 +21,8 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index e8d4d748d0fd..4986b4fbcee9 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -17,13 +17,13 @@ #include #include #include +#include #include #ifdef CONFIG_IPIPE #include #endif #include #include -#include #include #include #include diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index a66d979ec651..5ece38a5b758 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -15,9 +15,9 @@ #include #include #include +#include #include -#include #include #include #include diff --git a/arch/sh/include/mach-common/mach/magicpanelr2.h b/arch/sh/include/mach-common/mach/magicpanelr2.h index 183a2f744251..eb0cf205176f 100644 --- a/arch/sh/include/mach-common/mach/magicpanelr2.h +++ b/arch/sh/include/mach-common/mach/magicpanelr2.h @@ -13,7 +13,7 @@ #ifndef __ASM_SH_MAGICPANELR2_H #define __ASM_SH_MAGICPANELR2_H -#include +#include #define __IO_PREFIX mpr2 #include diff --git a/drivers/ata/pata_at91.c b/drivers/ata/pata_at91.c index ace0a4de3449..9f27b14009f9 100644 --- a/drivers/ata/pata_at91.c +++ b/drivers/ata/pata_at91.c @@ -30,8 +30,7 @@ #include #include #include - -#include +#include #define DRV_NAME "pata_at91" #define DRV_VERSION "0.3" diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index dd7410019d15..ec748d31928d 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -36,8 +36,8 @@ #include #include #include +#include #include -#include #include #define DRV_NAME "pata-bf54x" diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c index 0e5a6709f27d..fc10cf59691c 100644 --- a/drivers/gpio/gpio-mpc5200.c +++ b/drivers/gpio/gpio-mpc5200.c @@ -25,7 +25,6 @@ #include #include -#include #include #include diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 3ac36f5ccd3e..a4a8f1ec3fb6 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -42,10 +42,10 @@ #include #include #include +#include #include -#include #define DRIVER_NAME "menelaus" diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 0aacf125938b..24a1388d3031 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -35,10 +35,10 @@ #include #include #include +#include #include #include -#include #include diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index bba1dcbb8075..8b0923fd76c6 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c @@ -36,10 +36,10 @@ #include #include #include +#include #include #include -#include #define SZ_1K 0x00000400 #define SZ_8K 0x00002000 diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index a47dcd24a26a..33c5b8823367 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -17,7 +17,6 @@ #include -#include #include #include "soc_common.h" diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 8755b2c2aada..dbde1149c218 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -25,8 +25,6 @@ #include #include -#include - #include "atmel_usba_udc.h" #ifdef CONFIG_USB_GADGET_DEBUG_FS diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 8c6e15bd6ff0..95c8ddde0725 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -24,8 +24,6 @@ #include #include -#include - #include "ohci.h" #define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS) diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c index 19eb42b57d87..e13b9e41957a 100644 --- a/drivers/video/fbdev/atmel_lcdfb.c +++ b/drivers/video/fbdev/atmel_lcdfb.c @@ -26,8 +26,6 @@ #include #include

+ Depth Formats + Depth data provides distance to points, mapped onto the image plane + + + &sub-z16; +
+
Compressed Formats -- cgit From dd215430dc9132fc0505cb4d5aa6dc6243ce8f9c Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Thu, 3 Mar 2016 11:26:18 +0200 Subject: NFC: pn544: Drop two useless checks in ACPI probe path When pn544_hci_i2c_acpi_request_resources() gets called we already know that the entries in ->acpi_match_table have matched ACPI ID of the device. In addition I2C client pointer cannot be NULL in any case (otherwise I2C core would not call ->probe() for the driver in the first place). Drop the two useless checks from the driver. Signed-off-by: Mika Westerberg Signed-off-by: Samuel Ortiz --- drivers/nfc/pn544/i2c.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 76c318444304..45d0e667d7ae 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -877,20 +877,8 @@ exit_state_wait_secure_write_answer: static int pn544_hci_i2c_acpi_request_resources(struct i2c_client *client) { struct pn544_i2c_phy *phy = i2c_get_clientdata(client); - const struct acpi_device_id *id; struct gpio_desc *gpiod_en, *gpiod_fw; - struct device *dev; - - if (!client) - return -EINVAL; - - dev = &client->dev; - - /* Match the struct device against a given list of ACPI IDs */ - id = acpi_match_device(dev->driver->acpi_match_table, dev); - - if (!id) - return -ENODEV; + struct device *dev = &client->dev; /* Get EN GPIO from ACPI */ gpiod_en = devm_gpiod_get_index(dev, PN544_GPIO_NAME_EN, 1, -- cgit From 5d8d8db851ef81337e7026b32a9d5a9cfb2271d5 Mon Sep 17 00:00:00 2001 From: Aviv Greenberg Date: Wed, 3 Feb 2016 15:08:52 -0200 Subject: [media] UVC: Add support for R200 depth camera Add support for Intel R200 depth camera in uvc driver. This includes adding new uvc GUIDs for the new pixel formats, adding new V4L pixel format definition to user api headers, and updating the uvc driver GUID-to-4cc tables with the new formats. Tested-by: Greenberg, Aviv D Signed-off-by: Aviv Greenberg Signed-off-by: Sakari Ailus Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/usb/uvc/uvc_driver.c | 20 ++++++++++++++++++++ drivers/media/usb/uvc/uvcvideo.h | 12 ++++++++++++ include/uapi/linux/videodev2.h | 3 +++ 3 files changed, 35 insertions(+) diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 4e7148815a78..451e84e962e2 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -148,6 +148,26 @@ static struct uvc_format_desc uvc_fmts[] = { .guid = UVC_GUID_FORMAT_H264, .fcc = V4L2_PIX_FMT_H264, }, + { + .name = "Greyscale 8 L/R (Y8I)", + .guid = UVC_GUID_FORMAT_Y8I, + .fcc = V4L2_PIX_FMT_Y8I, + }, + { + .name = "Greyscale 12 L/R (Y12I)", + .guid = UVC_GUID_FORMAT_Y12I, + .fcc = V4L2_PIX_FMT_Y12I, + }, + { + .name = "Depth data 16-bit (Z16)", + .guid = UVC_GUID_FORMAT_Z16, + .fcc = V4L2_PIX_FMT_Z16, + }, + { + .name = "Bayer 10-bit (SRGGB10P)", + .guid = UVC_GUID_FORMAT_RW10, + .fcc = V4L2_PIX_FMT_SRGGB10P, + }, }; /* ------------------------------------------------------------------------ diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index f0f2391e1b43..7e4d3eea371b 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -119,6 +119,18 @@ #define UVC_GUID_FORMAT_H264 \ { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y8I \ + { 'Y', '8', 'I', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Y12I \ + { 'Y', '1', '2', 'I', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_Z16 \ + { 'Z', '1', '6', ' ', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_RW10 \ + { 'R', 'W', '1', '0', 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} /* ------------------------------------------------------------------------ * Driver specific constants. diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 466458422385..e895975c5b0e 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -625,6 +625,9 @@ struct v4l2_pix_format { #define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */ #define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */ #define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */ +#define V4L2_PIX_FMT_Y8I v4l2_fourcc('Y', '8', 'I', ' ') /* Greyscale 8-bit L/R interleaved */ +#define V4L2_PIX_FMT_Y12I v4l2_fourcc('Y', '1', '2', 'I') /* Greyscale 12-bit L/R interleaved */ +#define V4L2_PIX_FMT_Z16 v4l2_fourcc('Z', '1', '6', ' ') /* Depth data 16-bit */ /* SDR formats - used only for Software Defined Radio devices */ #define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */ -- cgit From c54ae8fea6e615dcb43fefd651e49d2d74d86daf Mon Sep 17 00:00:00 2001 From: Koji Matsuoka Date: Sun, 24 Jan 2016 14:13:29 -0200 Subject: [media] soc_camera: rcar_vin: Add ARGB8888 caputre format support This patch adds ARGB8888 capture format support for R-Car Gen3. Signed-off-by: Koji Matsuoka Signed-off-by: Yoshihiro Kaneko Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/rcar_vin.c | 39 +++++++++++++++++++++------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index dc75a80794fb..3b8edf458964 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c @@ -124,7 +124,7 @@ #define VNDMR_EXRGB (1 << 8) #define VNDMR_BPSM (1 << 4) #define VNDMR_DTMD_YCSEP (1 << 1) -#define VNDMR_DTMD_ARGB1555 (1 << 0) +#define VNDMR_DTMD_ARGB (1 << 0) /* Video n Data Mode Register 2 bits */ #define VNDMR2_VPS (1 << 30) @@ -643,21 +643,26 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) output_is_yuv = true; break; case V4L2_PIX_FMT_RGB555X: - dmr = VNDMR_DTMD_ARGB1555; + dmr = VNDMR_DTMD_ARGB; break; case V4L2_PIX_FMT_RGB565: dmr = 0; break; case V4L2_PIX_FMT_RGB32: - if (priv->chip == RCAR_GEN2 || priv->chip == RCAR_H1 || - priv->chip == RCAR_E1) { - dmr = VNDMR_EXRGB; - break; - } + if (priv->chip != RCAR_GEN2 && priv->chip != RCAR_H1 && + priv->chip != RCAR_E1) + goto e_format; + + dmr = VNDMR_EXRGB; + break; + case V4L2_PIX_FMT_ARGB32: + if (priv->chip != RCAR_GEN3) + goto e_format; + + dmr = VNDMR_EXRGB | VNDMR_DTMD_ARGB; + break; default: - dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", - icd->current_fmt->host_fmt->fourcc); - return -EINVAL; + goto e_format; } /* Always update on field change */ @@ -679,6 +684,11 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv) iowrite32(vnmc | VNMC_ME, priv->base + VNMC_REG); return 0; + +e_format: + dev_warn(icd->parent, "Invalid fourcc format (0x%x)\n", + icd->current_fmt->host_fmt->fourcc); + return -EINVAL; } static void rcar_vin_capture(struct rcar_vin_priv *priv) @@ -1304,6 +1314,14 @@ static const struct soc_mbus_pixelfmt rcar_vin_formats[] = { .order = SOC_MBUS_ORDER_LE, .layout = SOC_MBUS_LAYOUT_PACKED, }, + { + .fourcc = V4L2_PIX_FMT_ARGB32, + .name = "ARGB8888", + .bits_per_sample = 32, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, }; static int rcar_vin_get_formats(struct soc_camera_device *icd, unsigned int idx, @@ -1611,6 +1629,7 @@ static int rcar_vin_set_fmt(struct soc_camera_device *icd, case V4L2_PIX_FMT_RGB32: can_scale = priv->chip != RCAR_E1; break; + case V4L2_PIX_FMT_ARGB32: case V4L2_PIX_FMT_UYVY: case V4L2_PIX_FMT_YUYV: case V4L2_PIX_FMT_RGB565: -- cgit From 71f87b2fc64c2e9b6d53cb817f28711b959d3dfe Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 3 Mar 2016 10:52:10 +0100 Subject: cpu/hotplug: Plug death reporting race Paul noticed that the conversion of the death reporting introduced a race where the outgoing cpu might be delayed after waking the controll processor, so it might not be able to call rcu_report_dead() before being physically removed, leading to RCU stalls. We cant call complete after rcu_report_dead(), so instead of going back to busy polling, simply issue a function call to do the completion. Fixes: 27d50c7eeb0f "rcu: Make CPU_DYING_IDLE an explicit call" Reported-by: Paul E. McKenney Link: http://lkml.kernel.org/r/20160302201127.GA23440@linux.vnet.ibm.com Signed-off-by: Thomas Gleixner Acked-by: Peter Zijlstra --- kernel/cpu.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index ff8059b76a85..93e9d89bb0ab 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -755,14 +755,26 @@ static int notify_dead(unsigned int cpu) return 0; } +static void cpuhp_complete_idle_dead(void *arg) +{ + struct cpuhp_cpu_state *st = arg; + + complete(&st->done); +} + void cpuhp_report_idle_dead(void) { struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state); BUG_ON(st->state != CPUHP_AP_OFFLINE); - st->state = CPUHP_AP_IDLE_DEAD; - complete(&st->done); rcu_report_dead(smp_processor_id()); + st->state = CPUHP_AP_IDLE_DEAD; + /* + * We cannot call complete after rcu_report_dead() so we delegate it + * to an online cpu. + */ + smp_call_function_single(cpumask_first(cpu_online_mask), + cpuhp_complete_idle_dead, st, 0); } #else -- cgit From 2abd1f43c242e79c9db1050a3344cc2965eb77e3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 1 Feb 2016 14:45:39 -0200 Subject: [media] mx3_camera: use %pad format string for dma_ddr_t The mx3_camera driver prints DMA addresses using the "%x" format string, which is wrong when using a 64-bit dma_addr_t definition: media/platform/soc_camera/mx3_camera.c: In function 'mx3_cam_dma_done': media/platform/soc_camera/mx3_camera.c:149:125: error: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=] media/platform/soc_camera/mx3_camera.c: In function 'mx3_videobuf_queue': media/platform/soc_camera/mx3_camera.c:317:119: error: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=] media/platform/soc_camera/mx3_camera.c: In function 'mx3_videobuf_release': media/platform/soc_camera/mx3_camera.c:346:119: error: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'dma_addr_t {aka long long unsigned int}' [-Werror=format=] This changes the code to use the special %pad format string, which always does the right thing. Signed-off-by: Arnd Bergmann Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/mx3_camera.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 169ed1150226..aa39e9569b1a 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -146,8 +146,8 @@ static void mx3_cam_dma_done(void *arg) struct idmac_channel *ichannel = to_idmac_chan(chan); struct mx3_camera_dev *mx3_cam = ichannel->client; - dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n", - desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0); + dev_dbg(chan->device->dev, "callback cookie %d, active DMA %pad\n", + desc->txd.cookie, mx3_cam->active ? &sg_dma_address(&mx3_cam->active->sg) : NULL); spin_lock(&mx3_cam->lock); if (mx3_cam->active) { @@ -314,8 +314,8 @@ static void mx3_videobuf_queue(struct vb2_buffer *vb) spin_unlock_irq(&mx3_cam->lock); cookie = txd->tx_submit(txd); - dev_dbg(icd->parent, "Submitted cookie %d DMA 0x%08x\n", - cookie, sg_dma_address(&buf->sg)); + dev_dbg(icd->parent, "Submitted cookie %d DMA %pad\n", + cookie, &sg_dma_address(&buf->sg)); if (cookie >= 0) return; @@ -344,8 +344,8 @@ static void mx3_videobuf_release(struct vb2_buffer *vb) unsigned long flags; dev_dbg(icd->parent, - "Release%s DMA 0x%08x, queue %sempty\n", - mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg), + "Release%s DMA %pad, queue %sempty\n", + mx3_cam->active == buf ? " active" : "", &sg_dma_address(&buf->sg), list_empty(&buf->queue) ? "" : "not "); spin_lock_irqsave(&mx3_cam->lock, flags); -- cgit From 82e88ff1ea948d83125a8aaa7c9809f03ccc500f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 3 Mar 2016 11:11:12 +0100 Subject: hrtimer: Revert CLOCK_MONOTONIC_RAW support Revert commits: a6e707ddbdf1: KVM: arm/arm64: timer: Switch to CLOCK_MONOTONIC_RAW 9006a01829a5: hrtimer: Catch illegal clockids 9c808765e88e: hrtimer: Add support for CLOCK_MONOTONIC_RAW Marc found out, that there are fundamental issues with that patch series because __hrtimer_get_next_event() and hrtimer_forward() need support for CLOCK_MONOTONIC_RAW. Nothing which is easily fixed, so revert the whole lot. Reported-by: Marc Zyngier Link: http://lkml.kernel.org/r/56D6CEF0.8060607@arm.com Signed-off-by: Thomas Gleixner --- include/linux/hrtimer.h | 1 - kernel/time/hrtimer.c | 18 ++---------------- virt/kvm/arm/arch_timer.c | 4 ++-- 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index a6d64af5e73f..76dd4f0da5ca 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -151,7 +151,6 @@ enum hrtimer_base_type { HRTIMER_BASE_REALTIME, HRTIMER_BASE_BOOTTIME, HRTIMER_BASE_TAI, - HRTIMER_BASE_MONOTONIC_RAW, HRTIMER_MAX_CLOCK_BASES, }; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index cb0fe70f3c51..435b8850dd80 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -90,30 +90,19 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = .clockid = CLOCK_TAI, .get_time = &ktime_get_clocktai, }, - { - .index = HRTIMER_BASE_MONOTONIC_RAW, - .clockid = CLOCK_MONOTONIC_RAW, - .get_time = &ktime_get_raw, - }, } }; static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { - /* Make sure we catch unsupported clockids */ - [0 ... MAX_CLOCKS - 1] = HRTIMER_MAX_CLOCK_BASES, - [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, - [CLOCK_MONOTONIC_RAW] = HRTIMER_BASE_MONOTONIC_RAW, [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, [CLOCK_TAI] = HRTIMER_BASE_TAI, }; static inline int hrtimer_clockid_to_base(clockid_t clock_id) { - int base = hrtimer_clock_to_base_table[clock_id]; - BUG_ON(base == HRTIMER_MAX_CLOCK_BASES); - return base; + return hrtimer_clock_to_base_table[clock_id]; } /* @@ -1279,10 +1268,7 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now) if (!(active & 0x01)) continue; - if (unlikely(base->index == HRTIMER_BASE_MONOTONIC_RAW)) - basenow = ktime_get_raw(); - else - basenow = ktime_add(now, base->offset); + basenow = ktime_add(now, base->offset); while ((node = timerqueue_getnext(&base->active))) { struct hrtimer *timer; diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 97c58153f923..69bca185c471 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -48,7 +48,7 @@ static bool timer_is_armed(struct arch_timer_cpu *timer) static void timer_arm(struct arch_timer_cpu *timer, u64 ns) { timer->armed = true; - hrtimer_start(&timer->timer, ktime_add_ns(ktime_get_raw(), ns), + hrtimer_start(&timer->timer, ktime_add_ns(ktime_get(), ns), HRTIMER_MODE_ABS); } @@ -308,7 +308,7 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); - hrtimer_init(&timer->timer, CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS); + hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); timer->timer.function = kvm_timer_expire; } -- cgit From 8f4895f2bd83cbf5afae25f3b35ea0f5d46d48c6 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 6 Sep 2015 08:42:10 -0300 Subject: [media] pxa_camera: fix the buffer free path Fix the error path where the video buffer wasn't allocated nor mapped. In this case, in the driver free path don't try to unmap memory which was not mapped in the first place. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/pxa_camera.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 415f3bda60bf..924b07d0b6c1 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -272,8 +272,6 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) * longer in STATE_QUEUED or STATE_ACTIVE */ videobuf_waiton(vq, &buf->vb, 0, 0); - videobuf_dma_unmap(vq->dev, dma); - videobuf_dma_free(dma); for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { if (buf->dmas[i].sg_cpu) @@ -283,6 +281,8 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) buf->dmas[i].sg_dma); buf->dmas[i].sg_cpu = NULL; } + videobuf_dma_unmap(vq->dev, dma); + videobuf_dma_free(dma); buf->vb.state = VIDEOBUF_NEEDS_INIT; } @@ -479,7 +479,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, ret = videobuf_iolock(vq, vb, NULL); if (ret) - goto fail; + goto out; if (pcdev->channels == 3) { size_y = size / 2; @@ -504,7 +504,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, size_u, &sg, &next_ofs); if (ret) { dev_err(dev, "DMA initialization for U failed\n"); - goto fail_u; + goto fail; } /* init DMA for V channel */ @@ -513,7 +513,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, size_v, &sg, &next_ofs); if (ret) { dev_err(dev, "DMA initialization for V failed\n"); - goto fail_v; + goto fail; } vb->state = VIDEOBUF_PREPARED; @@ -524,12 +524,6 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, return 0; -fail_v: - dma_free_coherent(dev, buf->dmas[1].sg_size, - buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma); -fail_u: - dma_free_coherent(dev, buf->dmas[0].sg_size, - buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma); fail: free_buffer(vq, buf); out: -- cgit From 368ced78e6ed3d72c2acc61233b58487071ec289 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 1 Mar 2016 09:45:13 +0530 Subject: powerpc/mm: Switch book3s 64 with 64K page size to 4 level page table This is needed so that we can support both hash and radix page table using single kernel. Radix kernel uses a 4 level table. We now use physical address in upper page table tree levels. Even though they are aligned to their size, for the masked bits we use the bit positions as per PowerISA 3.0. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/Kconfig | 2 +- arch/powerpc/include/asm/book3s/64/hash-4k.h | 33 +-------------------------- arch/powerpc/include/asm/book3s/64/hash-64k.h | 33 ++++++++++++++------------- arch/powerpc/include/asm/book3s/64/hash.h | 11 +++++++++ arch/powerpc/include/asm/book3s/64/pgtable.h | 25 +++++++++++++++++++- arch/powerpc/include/asm/pgalloc-64.h | 28 ++++++++++++++++++++--- arch/powerpc/include/asm/pgtable-types.h | 13 +++++++---- arch/powerpc/mm/init_64.c | 21 ++++++++++++----- 8 files changed, 102 insertions(+), 64 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 9faa18c4f3f7..7efddd18d700 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -303,7 +303,7 @@ config ZONE_DMA32 config PGTABLE_LEVELS int default 2 if !PPC64 - default 3 if PPC_64K_PAGES + default 3 if PPC_64K_PAGES && !PPC_BOOK3S_64 default 4 source "init/Kconfig" diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index 7f60f7e814d4..5f08a0832238 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h @@ -58,39 +58,8 @@ #define _PAGE_4K_PFN 0 #ifndef __ASSEMBLY__ /* - * 4-level page tables related bits + * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range() */ - -#define pgd_none(pgd) (!pgd_val(pgd)) -#define pgd_bad(pgd) (pgd_val(pgd) == 0) -#define pgd_present(pgd) (pgd_val(pgd) != 0) -#define pgd_page_vaddr(pgd) __va(pgd_val(pgd) & ~PGD_MASKED_BITS) - -static inline void pgd_clear(pgd_t *pgdp) -{ - *pgdp = __pgd(0); -} - -static inline pte_t pgd_pte(pgd_t pgd) -{ - return __pte(pgd_val(pgd)); -} - -static inline pgd_t pte_pgd(pte_t pte) -{ - return __pgd(pte_val(pte)); -} -extern struct page *pgd_page(pgd_t pgd); - -#define pud_offset(pgdp, addr) \ - (((pud_t *) pgd_page_vaddr(*(pgdp))) + \ - (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))) - -#define pud_ERROR(e) \ - pr_err("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) - -/* - * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range() */ #define remap_4k_pfn(vma, addr, pfn, prot) \ remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot)) diff --git a/arch/powerpc/include/asm/book3s/64/hash-64k.h b/arch/powerpc/include/asm/book3s/64/hash-64k.h index 8bb03251f34c..0a7956a80a08 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-64k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-64k.h @@ -1,15 +1,14 @@ #ifndef _ASM_POWERPC_BOOK3S_64_HASH_64K_H #define _ASM_POWERPC_BOOK3S_64_HASH_64K_H -#include - #define PTE_INDEX_SIZE 8 -#define PMD_INDEX_SIZE 10 -#define PUD_INDEX_SIZE 0 +#define PMD_INDEX_SIZE 5 +#define PUD_INDEX_SIZE 5 #define PGD_INDEX_SIZE 12 #define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) +#define PTRS_PER_PUD (1 << PUD_INDEX_SIZE) #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) /* With 4k base page size, hugepage PTEs go at the PMD level */ @@ -20,8 +19,13 @@ #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) -/* PGDIR_SHIFT determines what a third-level page table entry can map */ -#define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) +/* PUD_SHIFT determines what a third-level page table entry can map */ +#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE-1)) + +/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ +#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE) #define PGDIR_SIZE (1UL << PGDIR_SHIFT) #define PGDIR_MASK (~(PGDIR_SIZE-1)) @@ -56,13 +60,12 @@ #define PTE_FRAG_SIZE_SHIFT 12 #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT) -/* - * Bits to mask out from a PMD to get to the PTE page - * PMDs point to PTE table fragments which are PTE_FRAG_SIZE aligned. - */ -#define PMD_MASKED_BITS (PTE_FRAG_SIZE - 1) -/* Bits to mask out from a PGD/PUD to get to the PMD page */ -#define PUD_MASKED_BITS 0x1ff +/* Bits to mask out from a PMD to get to the PTE page */ +#define PMD_MASKED_BITS 0xc0000000000000ffUL +/* Bits to mask out from a PUD to get to the PMD page */ +#define PUD_MASKED_BITS 0xc0000000000000ffUL +/* Bits to mask out from a PGD to get to the PUD page */ +#define PGD_MASKED_BITS 0xc0000000000000ffUL #ifndef __ASSEMBLY__ @@ -132,11 +135,9 @@ extern bool __rpte_sub_valid(real_pte_t rpte, unsigned long index); #else #define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) #endif +#define PUD_TABLE_SIZE (sizeof(pud_t) << PUD_INDEX_SIZE) #define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) -#define pgd_pte(pgd) (pud_pte(((pud_t){ pgd }))) -#define pte_pgd(pte) ((pgd_t)pte_pud(pte)) - #ifdef CONFIG_HUGETLB_PAGE /* * We have PGD_INDEX_SIZ = 12 and PTE_INDEX_SIZE = 8, so that we can have diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index ef9bd68f7e6d..d0ee6fcef823 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h @@ -235,6 +235,7 @@ #define __pgtable_ptr_val(ptr) __pa(ptr) #define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1)) +#define pud_index(address) (((address) >> (PUD_SHIFT)) & (PTRS_PER_PUD - 1)) #define pmd_index(address) (((address) >> (PMD_SHIFT)) & (PTRS_PER_PMD - 1)) #define pte_index(address) (((address) >> (PAGE_SHIFT)) & (PTRS_PER_PTE - 1)) @@ -363,8 +364,18 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry) :"cc"); } +static inline int pgd_bad(pgd_t pgd) +{ + return (pgd_val(pgd) == 0); +} + #define __HAVE_ARCH_PTE_SAME #define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0) +static inline unsigned long pgd_page_vaddr(pgd_t pgd) +{ + return (unsigned long)__va(pgd_val(pgd) & ~PGD_MASKED_BITS); +} + /* Generic accessors to PTE bits */ static inline int pte_write(pte_t pte) { return !!(pte_val(pte) & _PAGE_RW);} diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 7482f69117b6..77d3ce05798e 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h @@ -106,6 +106,26 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val) *pgdp = __pgd(val); } +static inline void pgd_clear(pgd_t *pgdp) +{ + *pgdp = __pgd(0); +} + +#define pgd_none(pgd) (!pgd_val(pgd)) +#define pgd_present(pgd) (!pgd_none(pgd)) + +static inline pte_t pgd_pte(pgd_t pgd) +{ + return __pte(pgd_val(pgd)); +} + +static inline pgd_t pte_pgd(pte_t pte) +{ + return __pgd(pte_val(pte)); +} + +extern struct page *pgd_page(pgd_t pgd); + /* * Find an entry in a page-table-directory. We combine the address region * (the high order N bits) and the pgd portion of the address. @@ -113,9 +133,10 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val) #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) +#define pud_offset(pgdp, addr) \ + (((pud_t *) pgd_page_vaddr(*(pgdp))) + pud_index(addr)) #define pmd_offset(pudp,addr) \ (((pmd_t *) pud_page_vaddr(*(pudp))) + pmd_index(addr)) - #define pte_offset_kernel(dir,addr) \ (((pte_t *) pmd_page_vaddr(*(dir))) + pte_index(addr)) @@ -130,6 +151,8 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val) pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) #define pmd_ERROR(e) \ pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) +#define pud_ERROR(e) \ + pr_err("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) #define pgd_ERROR(e) \ pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index 7ac59a32c66a..8d5fc3ac43da 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h @@ -171,7 +171,29 @@ extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift); extern void __tlb_remove_table(void *_table); #endif -#define pud_populate(mm, pud, pmd) pud_set(pud, __pgtable_ptr_val(pmd)) +#ifndef __PAGETABLE_PUD_FOLDED +/* book3s 64 is 4 level page table */ +static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) +{ + pgd_set(pgd, __pgtable_ptr_val(pud)); +} + +static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) +{ + return kmem_cache_alloc(PGT_CACHE(PUD_INDEX_SIZE), + GFP_KERNEL|__GFP_REPEAT); +} + +static inline void pud_free(struct mm_struct *mm, pud_t *pud) +{ + kmem_cache_free(PGT_CACHE(PUD_INDEX_SIZE), pud); +} +#endif + +static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) +{ + pud_set(pud, __pgtable_ptr_val(pmd)); +} static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte) @@ -233,11 +255,11 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) #define __pmd_free_tlb(tlb, pmd, addr) \ pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX) -#ifndef CONFIG_PPC_64K_PAGES +#ifndef __PAGETABLE_PUD_FOLDED #define __pud_free_tlb(tlb, pud, addr) \ pgtable_free_tlb(tlb, pud, PUD_INDEX_SIZE) -#endif /* CONFIG_PPC_64K_PAGES */ +#endif /* __PAGETABLE_PUD_FOLDED */ #define check_pgt_cache() do { } while (0) diff --git a/arch/powerpc/include/asm/pgtable-types.h b/arch/powerpc/include/asm/pgtable-types.h index 71487e1ca638..43140f8b0592 100644 --- a/arch/powerpc/include/asm/pgtable-types.h +++ b/arch/powerpc/include/asm/pgtable-types.h @@ -21,15 +21,18 @@ static inline unsigned long pmd_val(pmd_t x) return x.pmd; } -/* PUD level exusts only on 4k pages */ -#ifndef CONFIG_PPC_64K_PAGES +/* + * 64 bit hash always use 4 level table. Everybody else use 4 level + * only for 4K page size. + */ +#if defined(CONFIG_PPC_BOOK3S_64) || !defined(CONFIG_PPC_64K_PAGES) typedef struct { unsigned long pud; } pud_t; #define __pud(x) ((pud_t) { (x) }) static inline unsigned long pud_val(pud_t x) { return x.pud; } -#endif /* !CONFIG_PPC_64K_PAGES */ +#endif /* CONFIG_PPC_BOOK3S_64 || !CONFIG_PPC_64K_PAGES */ #endif /* CONFIG_PPC64 */ /* PGD level */ @@ -66,14 +69,14 @@ static inline unsigned long pmd_val(pmd_t pmd) return pmd; } -#ifndef CONFIG_PPC_64K_PAGES +#if defined(CONFIG_PPC_BOOK3S_64) || !defined(CONFIG_PPC_64K_PAGES) typedef unsigned long pud_t; #define __pud(x) (x) static inline unsigned long pud_val(pud_t pud) { return pud; } -#endif /* !CONFIG_PPC_64K_PAGES */ +#endif /* CONFIG_PPC_BOOK3S_64 || !CONFIG_PPC_64K_PAGES */ #endif /* CONFIG_PPC64 */ typedef unsigned long pgd_t; diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index fbc9448cca63..ba655666186d 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -85,6 +85,11 @@ static void pgd_ctor(void *addr) memset(addr, 0, PGD_TABLE_SIZE); } +static void pud_ctor(void *addr) +{ + memset(addr, 0, PUD_TABLE_SIZE); +} + static void pmd_ctor(void *addr) { memset(addr, 0, PMD_TABLE_SIZE); @@ -138,14 +143,18 @@ void pgtable_cache_init(void) { pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor); pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor); + /* + * In all current configs, when the PUD index exists it's the + * same size as either the pgd or pmd index except with THP enabled + * on book3s 64 + */ + if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE)) + pgtable_cache_add(PUD_INDEX_SIZE, pud_ctor); + if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_CACHE_INDEX)) panic("Couldn't allocate pgtable caches"); - /* In all current configs, when the PUD index exists it's the - * same size as either the pgd or pmd index. Verify that the - * initialization above has also created a PUD cache. This - * will need re-examiniation if we add new possibilities for - * the pagetable layout. */ - BUG_ON(PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE)); + if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE)) + panic("Couldn't allocate pud pgtable caches"); } #ifdef CONFIG_SPARSEMEM_VMEMMAP -- cgit From ff20c2e0acc5ad7e27c68592ade135efee399549 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Tue, 1 Mar 2016 09:45:14 +0530 Subject: mm: Some arch may want to use HPAGE_PMD related values as variables With next generation power processor, we are having a new mmu model [1] that require us to maintain a different linux page table format. Inorder to support both current and future ppc64 systems with a single kernel we need to make sure kernel can select between different page table format at runtime. With the new MMU (radix MMU) added, we will have two different pmd hugepage size 16MB for hash model and 2MB for Radix model. Hence make HPAGE_PMD related values as a variable. Actual conversion of HPAGE_PMD to a variable for ppc64 happens in a followup patch. [1] http://ibm.biz/power-isa3 (Needs registration). Signed-off-by: Kirill A. Shutemov Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/mm/pgtable_64.c | 7 +++++++ include/linux/bug.h | 9 +++++++++ include/linux/huge_mm.h | 3 --- mm/huge_memory.c | 17 ++++++++++++++--- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index af304e6d5a89..0eb53128ca2a 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c @@ -817,6 +817,13 @@ pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, int has_transparent_hugepage(void) { + + BUILD_BUG_ON_MSG((PMD_SHIFT - PAGE_SHIFT) >= MAX_ORDER, + "hugepages can't be allocated by the buddy allocator"); + + BUILD_BUG_ON_MSG((PMD_SHIFT - PAGE_SHIFT) < 2, + "We need more than 2 pages to do deferred thp split"); + if (!mmu_has_feature(MMU_FTR_16M_PAGE)) return 0; /* diff --git a/include/linux/bug.h b/include/linux/bug.h index 7f4818673c41..e51b0709e78d 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -20,6 +20,7 @@ struct pt_regs; #define BUILD_BUG_ON_MSG(cond, msg) (0) #define BUILD_BUG_ON(condition) (0) #define BUILD_BUG() (0) +#define MAYBE_BUILD_BUG_ON(cond) (0) #else /* __CHECKER__ */ /* Force a compilation error if a constant expression is not a power of 2 */ @@ -83,6 +84,14 @@ struct pt_regs; */ #define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed") +#define MAYBE_BUILD_BUG_ON(cond) \ + do { \ + if (__builtin_constant_p((cond))) \ + BUILD_BUG_ON(cond); \ + else \ + BUG_ON(cond); \ + } while (0) + #endif /* __CHECKER__ */ #ifdef CONFIG_GENERIC_BUG diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 459fd25b378e..f12513a20a06 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -111,9 +111,6 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, __split_huge_pmd(__vma, __pmd, __address); \ } while (0) -#if HPAGE_PMD_ORDER >= MAX_ORDER -#error "hugepages can't be allocated by the buddy allocator" -#endif extern int hugepage_madvise(struct vm_area_struct *vma, unsigned long *vm_flags, int advice); extern void vma_adjust_trans_huge(struct vm_area_struct *vma, diff --git a/mm/huge_memory.c b/mm/huge_memory.c index aea8f7a42df9..36c22a89df61 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -83,7 +83,7 @@ unsigned long transparent_hugepage_flags __read_mostly = (1<= MAX_ORDER); + /* + * we use page->mapping and page->index in second tail page + * as list_head: assuming THP order >= 2 + */ + MAYBE_BUILD_BUG_ON(HPAGE_PMD_ORDER < 2); + err = hugepage_init_sysfs(&hugepage_kobj); if (err) goto err_sysfs; @@ -764,7 +776,6 @@ void prep_transhuge_page(struct page *page) * we use page->mapping and page->indexlru in second tail page * as list_head: assuming THP order >= 2 */ - BUILD_BUG_ON(HPAGE_PMD_ORDER < 2); INIT_LIST_HEAD(page_deferred_list(page)); set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR); -- cgit From e9a681478ce535b4a0263a760a25a65fd8ca5ba3 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 1 Mar 2016 12:59:17 +0530 Subject: powerp/mm: Update code comments We are updating pte in those functions. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/mm/hash64_4k.c | 2 +- arch/powerpc/mm/hash64_64k.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/mm/hash64_4k.c b/arch/powerpc/mm/hash64_4k.c index e7c04542ba62..e3e76b929f33 100644 --- a/arch/powerpc/mm/hash64_4k.c +++ b/arch/powerpc/mm/hash64_4k.c @@ -106,7 +106,7 @@ repeat: } } /* - * Hypervisor failure. Restore old pmd and return -1 + * Hypervisor failure. Restore old pte and return -1 * similar to __hash_page_* */ if (unlikely(slot == -2)) { diff --git a/arch/powerpc/mm/hash64_64k.c b/arch/powerpc/mm/hash64_64k.c index ef6fac6d773c..b2d659cf51c6 100644 --- a/arch/powerpc/mm/hash64_64k.c +++ b/arch/powerpc/mm/hash64_64k.c @@ -188,7 +188,7 @@ repeat: } } /* - * Hypervisor failure. Restore old pmd and return -1 + * Hypervisor failure. Restore old pte and return -1 * similar to __hash_page_* */ if (unlikely(slot == -2)) { @@ -310,7 +310,7 @@ repeat: } } /* - * Hypervisor failure. Restore old pmd and return -1 + * Hypervisor failure. Restore old pte and return -1 * similar to __hash_page_* */ if (unlikely(slot == -2)) { -- cgit From c367a44133bcd7f94fb48b58e991dbffe7c25e22 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 1 Mar 2016 12:59:18 +0530 Subject: powerpc/mm: add _PAGE_HASHPTE similar to 4K hash We don't need to update linux page table entry with _PAGE_HASHPTE early in hash pte fault. A parallel pte update will loop via _PAGE_BUSY and look at _PAGE_HASHPTE for a required hpte flush only if _PAGE_BUSY is cleared. That ensures a pte update will wait for a parallel hpte insert to finish before looking at _PAGE_HASHPTE bit. To avoid further confusion drop setting _PAGE_HASHPTE in cmpxchg in __hash_page_4K. commit 41743a4e34f0 ("powerpc: Free a PTE bit on ppc64 with 64K pages") did similar change for 64K config Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/mm/hash64_4k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/mm/hash64_4k.c b/arch/powerpc/mm/hash64_4k.c index e3e76b929f33..47d1b26effc6 100644 --- a/arch/powerpc/mm/hash64_4k.c +++ b/arch/powerpc/mm/hash64_4k.c @@ -44,7 +44,7 @@ int __hash_page_4K(unsigned long ea, unsigned long access, unsigned long vsid, * a write access. Since this is 4K insert of 64K page size * also add _PAGE_COMBO */ - new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE; + new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; if (access & _PAGE_RW) new_pte |= _PAGE_DIRTY; } while (old_pte != __cmpxchg_u64((unsigned long *)ptep, -- cgit From f64e8084c94bb0449177364856d8117e2f14c4c0 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 1 Mar 2016 12:59:20 +0530 Subject: powerpc/mm: Move hash related mmu-*.h headers to book3s/ No code changes. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/book3s/32/mmu-hash.h | 93 ++++ arch/powerpc/include/asm/book3s/64/mmu-hash.h | 616 ++++++++++++++++++++++++++ arch/powerpc/include/asm/mmu-hash32.h | 93 ---- arch/powerpc/include/asm/mmu-hash64.h | 616 -------------------------- arch/powerpc/include/asm/mmu.h | 4 +- arch/powerpc/kernel/cpu_setup_power.S | 2 +- arch/powerpc/kernel/idle_power7.S | 2 +- arch/powerpc/kvm/book3s_32_mmu_host.c | 2 +- arch/powerpc/kvm/book3s_64_mmu.c | 2 +- arch/powerpc/kvm/book3s_64_mmu_host.c | 2 +- arch/powerpc/kvm/book3s_64_mmu_hv.c | 2 +- arch/powerpc/kvm/book3s_64_vio.c | 2 +- arch/powerpc/kvm/book3s_64_vio_hv.c | 2 +- arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +- 15 files changed, 721 insertions(+), 721 deletions(-) create mode 100644 arch/powerpc/include/asm/book3s/32/mmu-hash.h create mode 100644 arch/powerpc/include/asm/book3s/64/mmu-hash.h delete mode 100644 arch/powerpc/include/asm/mmu-hash32.h delete mode 100644 arch/powerpc/include/asm/mmu-hash64.h diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h new file mode 100644 index 000000000000..16f513e5cbd7 --- /dev/null +++ b/arch/powerpc/include/asm/book3s/32/mmu-hash.h @@ -0,0 +1,93 @@ +#ifndef _ASM_POWERPC_MMU_HASH32_H_ +#define _ASM_POWERPC_MMU_HASH32_H_ +/* + * 32-bit hash table MMU support + */ + +/* + * BATs + */ + +/* Block size masks */ +#define BL_128K 0x000 +#define BL_256K 0x001 +#define BL_512K 0x003 +#define BL_1M 0x007 +#define BL_2M 0x00F +#define BL_4M 0x01F +#define BL_8M 0x03F +#define BL_16M 0x07F +#define BL_32M 0x0FF +#define BL_64M 0x1FF +#define BL_128M 0x3FF +#define BL_256M 0x7FF + +/* BAT Access Protection */ +#define BPP_XX 0x00 /* No access */ +#define BPP_RX 0x01 /* Read only */ +#define BPP_RW 0x02 /* Read/write */ + +#ifndef __ASSEMBLY__ +/* Contort a phys_addr_t into the right format/bits for a BAT */ +#ifdef CONFIG_PHYS_64BIT +#define BAT_PHYS_ADDR(x) ((u32)((x & 0x00000000fffe0000ULL) | \ + ((x & 0x0000000e00000000ULL) >> 24) | \ + ((x & 0x0000000100000000ULL) >> 30))) +#else +#define BAT_PHYS_ADDR(x) (x) +#endif + +struct ppc_bat { + u32 batu; + u32 batl; +}; +#endif /* !__ASSEMBLY__ */ + +/* + * Hash table + */ + +/* Values for PP (assumes Ks=0, Kp=1) */ +#define PP_RWXX 0 /* Supervisor read/write, User none */ +#define PP_RWRX 1 /* Supervisor read/write, User read */ +#define PP_RWRW 2 /* Supervisor read/write, User read/write */ +#define PP_RXRX 3 /* Supervisor read, User read */ + +#ifndef __ASSEMBLY__ + +/* + * Hardware Page Table Entry + * Note that the xpn and x bitfields are used only by processors that + * support extended addressing; otherwise, those bits are reserved. + */ +struct hash_pte { + unsigned long v:1; /* Entry is valid */ + unsigned long vsid:24; /* Virtual segment identifier */ + unsigned long h:1; /* Hash algorithm indicator */ + unsigned long api:6; /* Abbreviated page index */ + unsigned long rpn:20; /* Real (physical) page number */ + unsigned long xpn:3; /* Real page number bits 0-2, optional */ + unsigned long r:1; /* Referenced */ + unsigned long c:1; /* Changed */ + unsigned long w:1; /* Write-thru cache mode */ + unsigned long i:1; /* Cache inhibited */ + unsigned long m:1; /* Memory coherence */ + unsigned long g:1; /* Guarded */ + unsigned long x:1; /* Real page number bit 3, optional */ + unsigned long pp:2; /* Page protection */ +}; + +typedef struct { + unsigned long id; + unsigned long vdso_base; +} mm_context_t; + +#endif /* !__ASSEMBLY__ */ + +/* We happily ignore the smaller BATs on 601, we don't actually use + * those definitions on hash32 at the moment anyway + */ +#define mmu_virtual_psize MMU_PAGE_4K +#define mmu_linear_psize MMU_PAGE_256M + +#endif /* _ASM_POWERPC_MMU_HASH32_H_ */ diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h new file mode 100644 index 000000000000..0cea4807e26f --- /dev/null +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h @@ -0,0 +1,616 @@ +#ifndef _ASM_POWERPC_MMU_HASH64_H_ +#define _ASM_POWERPC_MMU_HASH64_H_ +/* + * PowerPC64 memory management structures + * + * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> + * PPC64 rework. + * + * 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 + +/* + * This is necessary to get the definition of PGTABLE_RANGE which we + * need for various slices related matters. Note that this isn't the + * complete pgtable.h but only a portion of it. + */ +#include +#include +#include + +/* + * SLB + */ + +#define SLB_NUM_BOLTED 3 +#define SLB_CACHE_ENTRIES 8 +#define SLB_MIN_SIZE 32 + +/* Bits in the SLB ESID word */ +#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ + +/* Bits in the SLB VSID word */ +#define SLB_VSID_SHIFT 12 +#define SLB_VSID_SHIFT_1T 24 +#define SLB_VSID_SSIZE_SHIFT 62 +#define SLB_VSID_B ASM_CONST(0xc000000000000000) +#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) +#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) +#define SLB_VSID_KS ASM_CONST(0x0000000000000800) +#define SLB_VSID_KP ASM_CONST(0x0000000000000400) +#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ +#define SLB_VSID_L ASM_CONST(0x0000000000000100) +#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ +#define SLB_VSID_LP ASM_CONST(0x0000000000000030) +#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) +#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) +#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) +#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) +#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) + +#define SLB_VSID_KERNEL (SLB_VSID_KP) +#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) + +#define SLBIE_C (0x08000000) +#define SLBIE_SSIZE_SHIFT 25 + +/* + * Hash table + */ + +#define HPTES_PER_GROUP 8 + +#define HPTE_V_SSIZE_SHIFT 62 +#define HPTE_V_AVPN_SHIFT 7 +#define HPTE_V_AVPN ASM_CONST(0x3fffffffffffff80) +#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) +#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & 0xffffffffffffff80UL)) +#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) +#define HPTE_V_LOCK ASM_CONST(0x0000000000000008) +#define HPTE_V_LARGE ASM_CONST(0x0000000000000004) +#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002) +#define HPTE_V_VALID ASM_CONST(0x0000000000000001) + +#define HPTE_R_PP0 ASM_CONST(0x8000000000000000) +#define HPTE_R_TS ASM_CONST(0x4000000000000000) +#define HPTE_R_KEY_HI ASM_CONST(0x3000000000000000) +#define HPTE_R_RPN_SHIFT 12 +#define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000) +#define HPTE_R_PP ASM_CONST(0x0000000000000003) +#define HPTE_R_N ASM_CONST(0x0000000000000004) +#define HPTE_R_G ASM_CONST(0x0000000000000008) +#define HPTE_R_M ASM_CONST(0x0000000000000010) +#define HPTE_R_I ASM_CONST(0x0000000000000020) +#define HPTE_R_W ASM_CONST(0x0000000000000040) +#define HPTE_R_WIMG ASM_CONST(0x0000000000000078) +#define HPTE_R_C ASM_CONST(0x0000000000000080) +#define HPTE_R_R ASM_CONST(0x0000000000000100) +#define HPTE_R_KEY_LO ASM_CONST(0x0000000000000e00) + +#define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000) +#define HPTE_V_VRMA_MASK ASM_CONST(0x4001ffffff000000) + +/* Values for PP (assumes Ks=0, Kp=1) */ +#define PP_RWXX 0 /* Supervisor read/write, User none */ +#define PP_RWRX 1 /* Supervisor read/write, User read */ +#define PP_RWRW 2 /* Supervisor read/write, User read/write */ +#define PP_RXRX 3 /* Supervisor read, User read */ +#define PP_RXXX (HPTE_R_PP0 | 2) /* Supervisor read, user none */ + +/* Fields for tlbiel instruction in architecture 2.06 */ +#define TLBIEL_INVAL_SEL_MASK 0xc00 /* invalidation selector */ +#define TLBIEL_INVAL_PAGE 0x000 /* invalidate a single page */ +#define TLBIEL_INVAL_SET_LPID 0x800 /* invalidate a set for current LPID */ +#define TLBIEL_INVAL_SET 0xc00 /* invalidate a set for all LPIDs */ +#define TLBIEL_INVAL_SET_MASK 0xfff000 /* set number to inval. */ +#define TLBIEL_INVAL_SET_SHIFT 12 + +#define POWER7_TLB_SETS 128 /* # sets in POWER7 TLB */ +#define POWER8_TLB_SETS 512 /* # sets in POWER8 TLB */ +#define POWER9_TLB_SETS_HASH 256 /* # sets in POWER9 TLB Hash mode */ + +#ifndef __ASSEMBLY__ + +struct hash_pte { + __be64 v; + __be64 r; +}; + +extern struct hash_pte *htab_address; +extern unsigned long htab_size_bytes; +extern unsigned long htab_hash_mask; + +/* + * Page size definition + * + * shift : is the "PAGE_SHIFT" value for that page size + * sllp : is a bit mask with the value of SLB L || LP to be or'ed + * directly to a slbmte "vsid" value + * penc : is the HPTE encoding mask for the "LP" field: + * + */ +struct mmu_psize_def +{ + unsigned int shift; /* number of bits */ + int penc[MMU_PAGE_COUNT]; /* HPTE encoding */ + unsigned int tlbiel; /* tlbiel supported for that page size */ + unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ + unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ +}; +extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; + +static inline int shift_to_mmu_psize(unsigned int shift) +{ + int psize; + + for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) + if (mmu_psize_defs[psize].shift == shift) + return psize; + return -1; +} + +static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) +{ + if (mmu_psize_defs[mmu_psize].shift) + return mmu_psize_defs[mmu_psize].shift; + BUG(); +} + +#endif /* __ASSEMBLY__ */ + +/* + * Segment sizes. + * These are the values used by hardware in the B field of + * SLB entries and the first dword of MMU hashtable entries. + * The B field is 2 bits; the values 2 and 3 are unused and reserved. + */ +#define MMU_SEGSIZE_256M 0 +#define MMU_SEGSIZE_1T 1 + +/* + * encode page number shift. + * in order to fit the 78 bit va in a 64 bit variable we shift the va by + * 12 bits. This enable us to address upto 76 bit va. + * For hpt hash from a va we can ignore the page size bits of va and for + * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure + * we work in all cases including 4k page size. + */ +#define VPN_SHIFT 12 + +/* + * HPTE Large Page (LP) details + */ +#define LP_SHIFT 12 +#define LP_BITS 8 +#define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) + +#ifndef __ASSEMBLY__ + +static inline int slb_vsid_shift(int ssize) +{ + if (ssize == MMU_SEGSIZE_256M) + return SLB_VSID_SHIFT; + return SLB_VSID_SHIFT_1T; +} + +static inline int segment_shift(int ssize) +{ + if (ssize == MMU_SEGSIZE_256M) + return SID_SHIFT; + return SID_SHIFT_1T; +} + +/* + * The current system page and segment sizes + */ +extern int mmu_linear_psize; +extern int mmu_virtual_psize; +extern int mmu_vmalloc_psize; +extern int mmu_vmemmap_psize; +extern int mmu_io_psize; +extern int mmu_kernel_ssize; +extern int mmu_highuser_ssize; +extern u16 mmu_slb_size; +extern unsigned long tce_alloc_start, tce_alloc_end; + +/* + * If the processor supports 64k normal pages but not 64k cache + * inhibited pages, we have to be prepared to switch processes + * to use 4k pages when they create cache-inhibited mappings. + * If this is the case, mmu_ci_restrictions will be set to 1. + */ +extern int mmu_ci_restrictions; + +/* + * This computes the AVPN and B fields of the first dword of a HPTE, + * for use when we want to match an existing PTE. The bottom 7 bits + * of the returned value are zero. + */ +static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize, + int ssize) +{ + unsigned long v; + /* + * The AVA field omits the low-order 23 bits of the 78 bits VA. + * These bits are not needed in the PTE, because the + * low-order b of these bits are part of the byte offset + * into the virtual page and, if b < 23, the high-order + * 23-b of these bits are always used in selecting the + * PTEGs to be searched + */ + v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm); + v <<= HPTE_V_AVPN_SHIFT; + v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT; + return v; +} + +/* + * This function sets the AVPN and L fields of the HPTE appropriately + * using the base page size and actual page size. + */ +static inline unsigned long hpte_encode_v(unsigned long vpn, int base_psize, + int actual_psize, int ssize) +{ + unsigned long v; + v = hpte_encode_avpn(vpn, base_psize, ssize); + if (actual_psize != MMU_PAGE_4K) + v |= HPTE_V_LARGE; + return v; +} + +/* + * This function sets the ARPN, and LP fields of the HPTE appropriately + * for the page size. We assume the pa is already "clean" that is properly + * aligned for the requested page size + */ +static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize, + int actual_psize) +{ + /* A 4K page needs no special encoding */ + if (actual_psize == MMU_PAGE_4K) + return pa & HPTE_R_RPN; + else { + unsigned int penc = mmu_psize_defs[base_psize].penc[actual_psize]; + unsigned int shift = mmu_psize_defs[actual_psize].shift; + return (pa & ~((1ul << shift) - 1)) | (penc << LP_SHIFT); + } +} + +/* + * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size. + */ +static inline unsigned long hpt_vpn(unsigned long ea, + unsigned long vsid, int ssize) +{ + unsigned long mask; + int s_shift = segment_shift(ssize); + + mask = (1ul << (s_shift - VPN_SHIFT)) - 1; + return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask); +} + +/* + * This hashes a virtual address + */ +static inline unsigned long hpt_hash(unsigned long vpn, + unsigned int shift, int ssize) +{ + int mask; + unsigned long hash, vsid; + + /* VPN_SHIFT can be atmost 12 */ + if (ssize == MMU_SEGSIZE_256M) { + mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1; + hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^ + ((vpn & mask) >> (shift - VPN_SHIFT)); + } else { + mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1; + vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT); + hash = vsid ^ (vsid << 25) ^ + ((vpn & mask) >> (shift - VPN_SHIFT)) ; + } + return hash & 0x7fffffffffUL; +} + +#define HPTE_LOCAL_UPDATE 0x1 +#define HPTE_NOHPTE_UPDATE 0x2 + +extern int __hash_page_4K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned long flags, int ssize, int subpage_prot); +extern int __hash_page_64K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned long flags, int ssize); +struct mm_struct; +unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); +extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, + unsigned long access, unsigned long trap, + unsigned long flags); +extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap, + unsigned long dsisr); +int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, + pte_t *ptep, unsigned long trap, unsigned long flags, + int ssize, unsigned int shift, unsigned int mmu_psize); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +extern int __hash_page_thp(unsigned long ea, unsigned long access, + unsigned long vsid, pmd_t *pmdp, unsigned long trap, + unsigned long flags, int ssize, unsigned int psize); +#else +static inline int __hash_page_thp(unsigned long ea, unsigned long access, + unsigned long vsid, pmd_t *pmdp, + unsigned long trap, unsigned long flags, + int ssize, unsigned int psize) +{ + BUG(); + return -1; +} +#endif +extern void hash_failure_debug(unsigned long ea, unsigned long access, + unsigned long vsid, unsigned long trap, + int ssize, int psize, int lpsize, + unsigned long pte); +extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long prot, + int psize, int ssize); +int htab_remove_mapping(unsigned long vstart, unsigned long vend, + int psize, int ssize); +extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); +extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); + +extern void hpte_init_native(void); +extern void hpte_init_lpar(void); +extern void hpte_init_beat(void); +extern void hpte_init_beat_v3(void); + +extern void slb_initialize(void); +extern void slb_flush_and_rebolt(void); + +extern void slb_vmalloc_update(void); +extern void slb_set_size(u16 size); +#endif /* __ASSEMBLY__ */ + +/* + * VSID allocation (256MB segment) + * + * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated + * from mmu context id and effective segment id of the address. + * + * For user processes max context id is limited to ((1ul << 19) - 5) + * for kernel space, we use the top 4 context ids to map address as below + * NOTE: each context only support 64TB now. + * 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ] + * 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ] + * 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ] + * 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ] + * + * The proto-VSIDs are then scrambled into real VSIDs with the + * multiplicative hash: + * + * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS + * + * VSID_MULTIPLIER is prime, so in particular it is + * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. + * Because the modulus is 2^n-1 we can compute it efficiently without + * a divide or extra multiply (see below). The scramble function gives + * robust scattering in the hash table (at least based on some initial + * results). + * + * We also consider VSID 0 special. We use VSID 0 for slb entries mapping + * bad address. This enables us to consolidate bad address handling in + * hash_page. + * + * We also need to avoid the last segment of the last context, because that + * would give a protovsid of 0x1fffffffff. That will result in a VSID 0 + * because of the modulo operation in vsid scramble. But the vmemmap + * (which is what uses region 0xf) will never be close to 64TB in size + * (it's 56 bytes per page of system memory). + */ + +#define CONTEXT_BITS 19 +#define ESID_BITS 18 +#define ESID_BITS_1T 6 + +/* + * 256MB segment + * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments + * available for user + kernel mapping. The top 4 contexts are used for + * kernel mapping. Each segment contains 2^28 bytes. Each + * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts + * (19 == 37 + 28 - 46). + */ +#define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 5) + +/* + * This should be computed such that protovosid * vsid_mulitplier + * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus + */ +#define VSID_MULTIPLIER_256M ASM_CONST(12538073) /* 24-bit prime */ +#define VSID_BITS_256M (CONTEXT_BITS + ESID_BITS) +#define VSID_MODULUS_256M ((1UL<= \ + * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ + * the bit clear, r3 already has the answer we want, if it \ + * doesn't, the answer is the low 36 bits of r3+1. So in all \ + * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ + addi rx,rt,1; \ + srdi rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */ \ + add rt,rt,rx + +/* 4 bits per slice and we have one slice per 1TB */ +#define SLICE_ARRAY_SIZE (PGTABLE_RANGE >> 41) + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_PPC_SUBPAGE_PROT +/* + * For the sub-page protection option, we extend the PGD with one of + * these. Basically we have a 3-level tree, with the top level being + * the protptrs array. To optimize speed and memory consumption when + * only addresses < 4GB are being protected, pointers to the first + * four pages of sub-page protection words are stored in the low_prot + * array. + * Each page of sub-page protection words protects 1GB (4 bytes + * protects 64k). For the 3-level tree, each page of pointers then + * protects 8TB. + */ +struct subpage_prot_table { + unsigned long maxaddr; /* only addresses < this are protected */ + unsigned int **protptrs[(TASK_SIZE_USER64 >> 43)]; + unsigned int *low_prot[4]; +}; + +#define SBP_L1_BITS (PAGE_SHIFT - 2) +#define SBP_L2_BITS (PAGE_SHIFT - 3) +#define SBP_L1_COUNT (1 << SBP_L1_BITS) +#define SBP_L2_COUNT (1 << SBP_L2_BITS) +#define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) +#define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) + +extern void subpage_prot_free(struct mm_struct *mm); +extern void subpage_prot_init_new_context(struct mm_struct *mm); +#else +static inline void subpage_prot_free(struct mm_struct *mm) {} +static inline void subpage_prot_init_new_context(struct mm_struct *mm) { } +#endif /* CONFIG_PPC_SUBPAGE_PROT */ + +typedef unsigned long mm_context_id_t; +struct spinlock; + +typedef struct { + mm_context_id_t id; + u16 user_psize; /* page size index */ + +#ifdef CONFIG_PPC_MM_SLICES + u64 low_slices_psize; /* SLB page size encodings */ + unsigned char high_slices_psize[SLICE_ARRAY_SIZE]; +#else + u16 sllp; /* SLB page size encoding */ +#endif + unsigned long vdso_base; +#ifdef CONFIG_PPC_SUBPAGE_PROT + struct subpage_prot_table spt; +#endif /* CONFIG_PPC_SUBPAGE_PROT */ +#ifdef CONFIG_PPC_ICSWX + struct spinlock *cop_lockp; /* guard acop and cop_pid */ + unsigned long acop; /* mask of enabled coprocessor types */ + unsigned int cop_pid; /* pid value used with coprocessors */ +#endif /* CONFIG_PPC_ICSWX */ +#ifdef CONFIG_PPC_64K_PAGES + /* for 4K PTE fragment support */ + void *pte_frag; +#endif +#ifdef CONFIG_SPAPR_TCE_IOMMU + struct list_head iommu_group_mem_list; +#endif +} mm_context_t; + + +#if 0 +/* + * The code below is equivalent to this function for arguments + * < 2^VSID_BITS, which is all this should ever be called + * with. However gcc is not clever enough to compute the + * modulus (2^n-1) without a second multiply. + */ +#define vsid_scramble(protovsid, size) \ + ((((protovsid) * VSID_MULTIPLIER_##size) % VSID_MODULUS_##size)) + +#else /* 1 */ +#define vsid_scramble(protovsid, size) \ + ({ \ + unsigned long x; \ + x = (protovsid) * VSID_MULTIPLIER_##size; \ + x = (x >> VSID_BITS_##size) + (x & VSID_MODULUS_##size); \ + (x + ((x+1) >> VSID_BITS_##size)) & VSID_MODULUS_##size; \ + }) +#endif /* 1 */ + +/* Returns the segment size indicator for a user address */ +static inline int user_segment_size(unsigned long addr) +{ + /* Use 1T segments if possible for addresses >= 1T */ + if (addr >= (1UL << SID_SHIFT_1T)) + return mmu_highuser_ssize; + return MMU_SEGSIZE_256M; +} + +static inline unsigned long get_vsid(unsigned long context, unsigned long ea, + int ssize) +{ + /* + * Bad address. We return VSID 0 for that + */ + if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) + return 0; + + if (ssize == MMU_SEGSIZE_256M) + return vsid_scramble((context << ESID_BITS) + | (ea >> SID_SHIFT), 256M); + return vsid_scramble((context << ESID_BITS_1T) + | (ea >> SID_SHIFT_1T), 1T); +} + +/* + * This is only valid for addresses >= PAGE_OFFSET + * + * For kernel space, we use the top 4 context ids to map address as below + * 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ] + * 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ] + * 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ] + * 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ] + */ +static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) +{ + unsigned long context; + + /* + * kernel take the top 4 context from the available range + */ + context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1; + return get_vsid(context, ea, ssize); +} + +unsigned htab_shift_for_mem_size(unsigned long mem_size); + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_MMU_HASH64_H_ */ diff --git a/arch/powerpc/include/asm/mmu-hash32.h b/arch/powerpc/include/asm/mmu-hash32.h deleted file mode 100644 index 16f513e5cbd7..000000000000 --- a/arch/powerpc/include/asm/mmu-hash32.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _ASM_POWERPC_MMU_HASH32_H_ -#define _ASM_POWERPC_MMU_HASH32_H_ -/* - * 32-bit hash table MMU support - */ - -/* - * BATs - */ - -/* Block size masks */ -#define BL_128K 0x000 -#define BL_256K 0x001 -#define BL_512K 0x003 -#define BL_1M 0x007 -#define BL_2M 0x00F -#define BL_4M 0x01F -#define BL_8M 0x03F -#define BL_16M 0x07F -#define BL_32M 0x0FF -#define BL_64M 0x1FF -#define BL_128M 0x3FF -#define BL_256M 0x7FF - -/* BAT Access Protection */ -#define BPP_XX 0x00 /* No access */ -#define BPP_RX 0x01 /* Read only */ -#define BPP_RW 0x02 /* Read/write */ - -#ifndef __ASSEMBLY__ -/* Contort a phys_addr_t into the right format/bits for a BAT */ -#ifdef CONFIG_PHYS_64BIT -#define BAT_PHYS_ADDR(x) ((u32)((x & 0x00000000fffe0000ULL) | \ - ((x & 0x0000000e00000000ULL) >> 24) | \ - ((x & 0x0000000100000000ULL) >> 30))) -#else -#define BAT_PHYS_ADDR(x) (x) -#endif - -struct ppc_bat { - u32 batu; - u32 batl; -}; -#endif /* !__ASSEMBLY__ */ - -/* - * Hash table - */ - -/* Values for PP (assumes Ks=0, Kp=1) */ -#define PP_RWXX 0 /* Supervisor read/write, User none */ -#define PP_RWRX 1 /* Supervisor read/write, User read */ -#define PP_RWRW 2 /* Supervisor read/write, User read/write */ -#define PP_RXRX 3 /* Supervisor read, User read */ - -#ifndef __ASSEMBLY__ - -/* - * Hardware Page Table Entry - * Note that the xpn and x bitfields are used only by processors that - * support extended addressing; otherwise, those bits are reserved. - */ -struct hash_pte { - unsigned long v:1; /* Entry is valid */ - unsigned long vsid:24; /* Virtual segment identifier */ - unsigned long h:1; /* Hash algorithm indicator */ - unsigned long api:6; /* Abbreviated page index */ - unsigned long rpn:20; /* Real (physical) page number */ - unsigned long xpn:3; /* Real page number bits 0-2, optional */ - unsigned long r:1; /* Referenced */ - unsigned long c:1; /* Changed */ - unsigned long w:1; /* Write-thru cache mode */ - unsigned long i:1; /* Cache inhibited */ - unsigned long m:1; /* Memory coherence */ - unsigned long g:1; /* Guarded */ - unsigned long x:1; /* Real page number bit 3, optional */ - unsigned long pp:2; /* Page protection */ -}; - -typedef struct { - unsigned long id; - unsigned long vdso_base; -} mm_context_t; - -#endif /* !__ASSEMBLY__ */ - -/* We happily ignore the smaller BATs on 601, we don't actually use - * those definitions on hash32 at the moment anyway - */ -#define mmu_virtual_psize MMU_PAGE_4K -#define mmu_linear_psize MMU_PAGE_256M - -#endif /* _ASM_POWERPC_MMU_HASH32_H_ */ diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h deleted file mode 100644 index 0cea4807e26f..000000000000 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ /dev/null @@ -1,616 +0,0 @@ -#ifndef _ASM_POWERPC_MMU_HASH64_H_ -#define _ASM_POWERPC_MMU_HASH64_H_ -/* - * PowerPC64 memory management structures - * - * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> - * PPC64 rework. - * - * 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 - -/* - * This is necessary to get the definition of PGTABLE_RANGE which we - * need for various slices related matters. Note that this isn't the - * complete pgtable.h but only a portion of it. - */ -#include -#include -#include - -/* - * SLB - */ - -#define SLB_NUM_BOLTED 3 -#define SLB_CACHE_ENTRIES 8 -#define SLB_MIN_SIZE 32 - -/* Bits in the SLB ESID word */ -#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ - -/* Bits in the SLB VSID word */ -#define SLB_VSID_SHIFT 12 -#define SLB_VSID_SHIFT_1T 24 -#define SLB_VSID_SSIZE_SHIFT 62 -#define SLB_VSID_B ASM_CONST(0xc000000000000000) -#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) -#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) -#define SLB_VSID_KS ASM_CONST(0x0000000000000800) -#define SLB_VSID_KP ASM_CONST(0x0000000000000400) -#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ -#define SLB_VSID_L ASM_CONST(0x0000000000000100) -#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ -#define SLB_VSID_LP ASM_CONST(0x0000000000000030) -#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) -#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) -#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) -#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) -#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) - -#define SLB_VSID_KERNEL (SLB_VSID_KP) -#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) - -#define SLBIE_C (0x08000000) -#define SLBIE_SSIZE_SHIFT 25 - -/* - * Hash table - */ - -#define HPTES_PER_GROUP 8 - -#define HPTE_V_SSIZE_SHIFT 62 -#define HPTE_V_AVPN_SHIFT 7 -#define HPTE_V_AVPN ASM_CONST(0x3fffffffffffff80) -#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) -#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & 0xffffffffffffff80UL)) -#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) -#define HPTE_V_LOCK ASM_CONST(0x0000000000000008) -#define HPTE_V_LARGE ASM_CONST(0x0000000000000004) -#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002) -#define HPTE_V_VALID ASM_CONST(0x0000000000000001) - -#define HPTE_R_PP0 ASM_CONST(0x8000000000000000) -#define HPTE_R_TS ASM_CONST(0x4000000000000000) -#define HPTE_R_KEY_HI ASM_CONST(0x3000000000000000) -#define HPTE_R_RPN_SHIFT 12 -#define HPTE_R_RPN ASM_CONST(0x0ffffffffffff000) -#define HPTE_R_PP ASM_CONST(0x0000000000000003) -#define HPTE_R_N ASM_CONST(0x0000000000000004) -#define HPTE_R_G ASM_CONST(0x0000000000000008) -#define HPTE_R_M ASM_CONST(0x0000000000000010) -#define HPTE_R_I ASM_CONST(0x0000000000000020) -#define HPTE_R_W ASM_CONST(0x0000000000000040) -#define HPTE_R_WIMG ASM_CONST(0x0000000000000078) -#define HPTE_R_C ASM_CONST(0x0000000000000080) -#define HPTE_R_R ASM_CONST(0x0000000000000100) -#define HPTE_R_KEY_LO ASM_CONST(0x0000000000000e00) - -#define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000) -#define HPTE_V_VRMA_MASK ASM_CONST(0x4001ffffff000000) - -/* Values for PP (assumes Ks=0, Kp=1) */ -#define PP_RWXX 0 /* Supervisor read/write, User none */ -#define PP_RWRX 1 /* Supervisor read/write, User read */ -#define PP_RWRW 2 /* Supervisor read/write, User read/write */ -#define PP_RXRX 3 /* Supervisor read, User read */ -#define PP_RXXX (HPTE_R_PP0 | 2) /* Supervisor read, user none */ - -/* Fields for tlbiel instruction in architecture 2.06 */ -#define TLBIEL_INVAL_SEL_MASK 0xc00 /* invalidation selector */ -#define TLBIEL_INVAL_PAGE 0x000 /* invalidate a single page */ -#define TLBIEL_INVAL_SET_LPID 0x800 /* invalidate a set for current LPID */ -#define TLBIEL_INVAL_SET 0xc00 /* invalidate a set for all LPIDs */ -#define TLBIEL_INVAL_SET_MASK 0xfff000 /* set number to inval. */ -#define TLBIEL_INVAL_SET_SHIFT 12 - -#define POWER7_TLB_SETS 128 /* # sets in POWER7 TLB */ -#define POWER8_TLB_SETS 512 /* # sets in POWER8 TLB */ -#define POWER9_TLB_SETS_HASH 256 /* # sets in POWER9 TLB Hash mode */ - -#ifndef __ASSEMBLY__ - -struct hash_pte { - __be64 v; - __be64 r; -}; - -extern struct hash_pte *htab_address; -extern unsigned long htab_size_bytes; -extern unsigned long htab_hash_mask; - -/* - * Page size definition - * - * shift : is the "PAGE_SHIFT" value for that page size - * sllp : is a bit mask with the value of SLB L || LP to be or'ed - * directly to a slbmte "vsid" value - * penc : is the HPTE encoding mask for the "LP" field: - * - */ -struct mmu_psize_def -{ - unsigned int shift; /* number of bits */ - int penc[MMU_PAGE_COUNT]; /* HPTE encoding */ - unsigned int tlbiel; /* tlbiel supported for that page size */ - unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ - unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ -}; -extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; - -static inline int shift_to_mmu_psize(unsigned int shift) -{ - int psize; - - for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) - if (mmu_psize_defs[psize].shift == shift) - return psize; - return -1; -} - -static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) -{ - if (mmu_psize_defs[mmu_psize].shift) - return mmu_psize_defs[mmu_psize].shift; - BUG(); -} - -#endif /* __ASSEMBLY__ */ - -/* - * Segment sizes. - * These are the values used by hardware in the B field of - * SLB entries and the first dword of MMU hashtable entries. - * The B field is 2 bits; the values 2 and 3 are unused and reserved. - */ -#define MMU_SEGSIZE_256M 0 -#define MMU_SEGSIZE_1T 1 - -/* - * encode page number shift. - * in order to fit the 78 bit va in a 64 bit variable we shift the va by - * 12 bits. This enable us to address upto 76 bit va. - * For hpt hash from a va we can ignore the page size bits of va and for - * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure - * we work in all cases including 4k page size. - */ -#define VPN_SHIFT 12 - -/* - * HPTE Large Page (LP) details - */ -#define LP_SHIFT 12 -#define LP_BITS 8 -#define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) - -#ifndef __ASSEMBLY__ - -static inline int slb_vsid_shift(int ssize) -{ - if (ssize == MMU_SEGSIZE_256M) - return SLB_VSID_SHIFT; - return SLB_VSID_SHIFT_1T; -} - -static inline int segment_shift(int ssize) -{ - if (ssize == MMU_SEGSIZE_256M) - return SID_SHIFT; - return SID_SHIFT_1T; -} - -/* - * The current system page and segment sizes - */ -extern int mmu_linear_psize; -extern int mmu_virtual_psize; -extern int mmu_vmalloc_psize; -extern int mmu_vmemmap_psize; -extern int mmu_io_psize; -extern int mmu_kernel_ssize; -extern int mmu_highuser_ssize; -extern u16 mmu_slb_size; -extern unsigned long tce_alloc_start, tce_alloc_end; - -/* - * If the processor supports 64k normal pages but not 64k cache - * inhibited pages, we have to be prepared to switch processes - * to use 4k pages when they create cache-inhibited mappings. - * If this is the case, mmu_ci_restrictions will be set to 1. - */ -extern int mmu_ci_restrictions; - -/* - * This computes the AVPN and B fields of the first dword of a HPTE, - * for use when we want to match an existing PTE. The bottom 7 bits - * of the returned value are zero. - */ -static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize, - int ssize) -{ - unsigned long v; - /* - * The AVA field omits the low-order 23 bits of the 78 bits VA. - * These bits are not needed in the PTE, because the - * low-order b of these bits are part of the byte offset - * into the virtual page and, if b < 23, the high-order - * 23-b of these bits are always used in selecting the - * PTEGs to be searched - */ - v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm); - v <<= HPTE_V_AVPN_SHIFT; - v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT; - return v; -} - -/* - * This function sets the AVPN and L fields of the HPTE appropriately - * using the base page size and actual page size. - */ -static inline unsigned long hpte_encode_v(unsigned long vpn, int base_psize, - int actual_psize, int ssize) -{ - unsigned long v; - v = hpte_encode_avpn(vpn, base_psize, ssize); - if (actual_psize != MMU_PAGE_4K) - v |= HPTE_V_LARGE; - return v; -} - -/* - * This function sets the ARPN, and LP fields of the HPTE appropriately - * for the page size. We assume the pa is already "clean" that is properly - * aligned for the requested page size - */ -static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize, - int actual_psize) -{ - /* A 4K page needs no special encoding */ - if (actual_psize == MMU_PAGE_4K) - return pa & HPTE_R_RPN; - else { - unsigned int penc = mmu_psize_defs[base_psize].penc[actual_psize]; - unsigned int shift = mmu_psize_defs[actual_psize].shift; - return (pa & ~((1ul << shift) - 1)) | (penc << LP_SHIFT); - } -} - -/* - * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size. - */ -static inline unsigned long hpt_vpn(unsigned long ea, - unsigned long vsid, int ssize) -{ - unsigned long mask; - int s_shift = segment_shift(ssize); - - mask = (1ul << (s_shift - VPN_SHIFT)) - 1; - return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask); -} - -/* - * This hashes a virtual address - */ -static inline unsigned long hpt_hash(unsigned long vpn, - unsigned int shift, int ssize) -{ - int mask; - unsigned long hash, vsid; - - /* VPN_SHIFT can be atmost 12 */ - if (ssize == MMU_SEGSIZE_256M) { - mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1; - hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^ - ((vpn & mask) >> (shift - VPN_SHIFT)); - } else { - mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1; - vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT); - hash = vsid ^ (vsid << 25) ^ - ((vpn & mask) >> (shift - VPN_SHIFT)) ; - } - return hash & 0x7fffffffffUL; -} - -#define HPTE_LOCAL_UPDATE 0x1 -#define HPTE_NOHPTE_UPDATE 0x2 - -extern int __hash_page_4K(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - unsigned long flags, int ssize, int subpage_prot); -extern int __hash_page_64K(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - unsigned long flags, int ssize); -struct mm_struct; -unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap); -extern int hash_page_mm(struct mm_struct *mm, unsigned long ea, - unsigned long access, unsigned long trap, - unsigned long flags); -extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap, - unsigned long dsisr); -int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, - pte_t *ptep, unsigned long trap, unsigned long flags, - int ssize, unsigned int shift, unsigned int mmu_psize); -#ifdef CONFIG_TRANSPARENT_HUGEPAGE -extern int __hash_page_thp(unsigned long ea, unsigned long access, - unsigned long vsid, pmd_t *pmdp, unsigned long trap, - unsigned long flags, int ssize, unsigned int psize); -#else -static inline int __hash_page_thp(unsigned long ea, unsigned long access, - unsigned long vsid, pmd_t *pmdp, - unsigned long trap, unsigned long flags, - int ssize, unsigned int psize) -{ - BUG(); - return -1; -} -#endif -extern void hash_failure_debug(unsigned long ea, unsigned long access, - unsigned long vsid, unsigned long trap, - int ssize, int psize, int lpsize, - unsigned long pte); -extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, - unsigned long pstart, unsigned long prot, - int psize, int ssize); -int htab_remove_mapping(unsigned long vstart, unsigned long vend, - int psize, int ssize); -extern void add_gpage(u64 addr, u64 page_size, unsigned long number_of_pages); -extern void demote_segment_4k(struct mm_struct *mm, unsigned long addr); - -extern void hpte_init_native(void); -extern void hpte_init_lpar(void); -extern void hpte_init_beat(void); -extern void hpte_init_beat_v3(void); - -extern void slb_initialize(void); -extern void slb_flush_and_rebolt(void); - -extern void slb_vmalloc_update(void); -extern void slb_set_size(u16 size); -#endif /* __ASSEMBLY__ */ - -/* - * VSID allocation (256MB segment) - * - * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated - * from mmu context id and effective segment id of the address. - * - * For user processes max context id is limited to ((1ul << 19) - 5) - * for kernel space, we use the top 4 context ids to map address as below - * NOTE: each context only support 64TB now. - * 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ] - * 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ] - * 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ] - * 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ] - * - * The proto-VSIDs are then scrambled into real VSIDs with the - * multiplicative hash: - * - * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS - * - * VSID_MULTIPLIER is prime, so in particular it is - * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. - * Because the modulus is 2^n-1 we can compute it efficiently without - * a divide or extra multiply (see below). The scramble function gives - * robust scattering in the hash table (at least based on some initial - * results). - * - * We also consider VSID 0 special. We use VSID 0 for slb entries mapping - * bad address. This enables us to consolidate bad address handling in - * hash_page. - * - * We also need to avoid the last segment of the last context, because that - * would give a protovsid of 0x1fffffffff. That will result in a VSID 0 - * because of the modulo operation in vsid scramble. But the vmemmap - * (which is what uses region 0xf) will never be close to 64TB in size - * (it's 56 bytes per page of system memory). - */ - -#define CONTEXT_BITS 19 -#define ESID_BITS 18 -#define ESID_BITS_1T 6 - -/* - * 256MB segment - * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments - * available for user + kernel mapping. The top 4 contexts are used for - * kernel mapping. Each segment contains 2^28 bytes. Each - * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts - * (19 == 37 + 28 - 46). - */ -#define MAX_USER_CONTEXT ((ASM_CONST(1) << CONTEXT_BITS) - 5) - -/* - * This should be computed such that protovosid * vsid_mulitplier - * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus - */ -#define VSID_MULTIPLIER_256M ASM_CONST(12538073) /* 24-bit prime */ -#define VSID_BITS_256M (CONTEXT_BITS + ESID_BITS) -#define VSID_MODULUS_256M ((1UL<= \ - * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ - * the bit clear, r3 already has the answer we want, if it \ - * doesn't, the answer is the low 36 bits of r3+1. So in all \ - * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ - addi rx,rt,1; \ - srdi rx,rx,VSID_BITS_##size; /* extract 2^VSID_BITS bit */ \ - add rt,rt,rx - -/* 4 bits per slice and we have one slice per 1TB */ -#define SLICE_ARRAY_SIZE (PGTABLE_RANGE >> 41) - -#ifndef __ASSEMBLY__ - -#ifdef CONFIG_PPC_SUBPAGE_PROT -/* - * For the sub-page protection option, we extend the PGD with one of - * these. Basically we have a 3-level tree, with the top level being - * the protptrs array. To optimize speed and memory consumption when - * only addresses < 4GB are being protected, pointers to the first - * four pages of sub-page protection words are stored in the low_prot - * array. - * Each page of sub-page protection words protects 1GB (4 bytes - * protects 64k). For the 3-level tree, each page of pointers then - * protects 8TB. - */ -struct subpage_prot_table { - unsigned long maxaddr; /* only addresses < this are protected */ - unsigned int **protptrs[(TASK_SIZE_USER64 >> 43)]; - unsigned int *low_prot[4]; -}; - -#define SBP_L1_BITS (PAGE_SHIFT - 2) -#define SBP_L2_BITS (PAGE_SHIFT - 3) -#define SBP_L1_COUNT (1 << SBP_L1_BITS) -#define SBP_L2_COUNT (1 << SBP_L2_BITS) -#define SBP_L2_SHIFT (PAGE_SHIFT + SBP_L1_BITS) -#define SBP_L3_SHIFT (SBP_L2_SHIFT + SBP_L2_BITS) - -extern void subpage_prot_free(struct mm_struct *mm); -extern void subpage_prot_init_new_context(struct mm_struct *mm); -#else -static inline void subpage_prot_free(struct mm_struct *mm) {} -static inline void subpage_prot_init_new_context(struct mm_struct *mm) { } -#endif /* CONFIG_PPC_SUBPAGE_PROT */ - -typedef unsigned long mm_context_id_t; -struct spinlock; - -typedef struct { - mm_context_id_t id; - u16 user_psize; /* page size index */ - -#ifdef CONFIG_PPC_MM_SLICES - u64 low_slices_psize; /* SLB page size encodings */ - unsigned char high_slices_psize[SLICE_ARRAY_SIZE]; -#else - u16 sllp; /* SLB page size encoding */ -#endif - unsigned long vdso_base; -#ifdef CONFIG_PPC_SUBPAGE_PROT - struct subpage_prot_table spt; -#endif /* CONFIG_PPC_SUBPAGE_PROT */ -#ifdef CONFIG_PPC_ICSWX - struct spinlock *cop_lockp; /* guard acop and cop_pid */ - unsigned long acop; /* mask of enabled coprocessor types */ - unsigned int cop_pid; /* pid value used with coprocessors */ -#endif /* CONFIG_PPC_ICSWX */ -#ifdef CONFIG_PPC_64K_PAGES - /* for 4K PTE fragment support */ - void *pte_frag; -#endif -#ifdef CONFIG_SPAPR_TCE_IOMMU - struct list_head iommu_group_mem_list; -#endif -} mm_context_t; - - -#if 0 -/* - * The code below is equivalent to this function for arguments - * < 2^VSID_BITS, which is all this should ever be called - * with. However gcc is not clever enough to compute the - * modulus (2^n-1) without a second multiply. - */ -#define vsid_scramble(protovsid, size) \ - ((((protovsid) * VSID_MULTIPLIER_##size) % VSID_MODULUS_##size)) - -#else /* 1 */ -#define vsid_scramble(protovsid, size) \ - ({ \ - unsigned long x; \ - x = (protovsid) * VSID_MULTIPLIER_##size; \ - x = (x >> VSID_BITS_##size) + (x & VSID_MODULUS_##size); \ - (x + ((x+1) >> VSID_BITS_##size)) & VSID_MODULUS_##size; \ - }) -#endif /* 1 */ - -/* Returns the segment size indicator for a user address */ -static inline int user_segment_size(unsigned long addr) -{ - /* Use 1T segments if possible for addresses >= 1T */ - if (addr >= (1UL << SID_SHIFT_1T)) - return mmu_highuser_ssize; - return MMU_SEGSIZE_256M; -} - -static inline unsigned long get_vsid(unsigned long context, unsigned long ea, - int ssize) -{ - /* - * Bad address. We return VSID 0 for that - */ - if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) - return 0; - - if (ssize == MMU_SEGSIZE_256M) - return vsid_scramble((context << ESID_BITS) - | (ea >> SID_SHIFT), 256M); - return vsid_scramble((context << ESID_BITS_1T) - | (ea >> SID_SHIFT_1T), 1T); -} - -/* - * This is only valid for addresses >= PAGE_OFFSET - * - * For kernel space, we use the top 4 context ids to map address as below - * 0x7fffc - [ 0xc000000000000000 - 0xc0003fffffffffff ] - * 0x7fffd - [ 0xd000000000000000 - 0xd0003fffffffffff ] - * 0x7fffe - [ 0xe000000000000000 - 0xe0003fffffffffff ] - * 0x7ffff - [ 0xf000000000000000 - 0xf0003fffffffffff ] - */ -static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize) -{ - unsigned long context; - - /* - * kernel take the top 4 context from the available range - */ - context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1; - return get_vsid(context, ea, ssize); -} - -unsigned htab_shift_for_mem_size(unsigned long mem_size); - -#endif /* __ASSEMBLY__ */ - -#endif /* _ASM_POWERPC_MMU_HASH64_H_ */ diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 54d46504733d..8ca1c983bf6c 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h @@ -183,10 +183,10 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr) #if defined(CONFIG_PPC_STD_MMU_64) /* 64-bit classic hash table MMU */ -# include +#include #elif defined(CONFIG_PPC_STD_MMU_32) /* 32-bit classic hash table MMU */ -# include +#include #elif defined(CONFIG_40x) /* 40x-style software loaded TLB */ # include diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S index 5932219f1e79..584e119fa8b0 100644 --- a/arch/powerpc/kernel/cpu_setup_power.S +++ b/arch/powerpc/kernel/cpu_setup_power.S @@ -15,7 +15,7 @@ #include #include #include -#include +#include /* Entry: r3 = crap, r4 = ptr to cputable entry * diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index cf4fb5429cf1..470ceebd2d23 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S @@ -19,7 +19,7 @@ #include #include #include -#include +#include #undef DEBUG diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c index 55c4d51ea3e2..999106991a76 100644 --- a/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c index 9bf7031a67ff..b9131aa1aedf 100644 --- a/arch/powerpc/kvm/book3s_64_mmu.c +++ b/arch/powerpc/kvm/book3s_64_mmu.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include /* #define DEBUG_MMU */ diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 913cd2198fa6..114edace6cdd 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index fb37290a57b4..c7b78d8336b2 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c index 54cf9bc94dad..9c3b76bb69d9 100644 --- a/arch/powerpc/kvm/book3s_64_vio.c +++ b/arch/powerpc/kvm/book3s_64_vio.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c index 89e96b3e0039..039028d3ccb5 100644 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ b/arch/powerpc/kvm/book3s_64_vio_hv.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 91700518bbf3..4cb8db05f3e5 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 6ee26de9a1de..c613fee0b9f7 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM) -- cgit From ee3b93ebfbed6279f7a329001433c75c50ddfcc9 Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Tue, 1 Mar 2016 12:59:21 +0530 Subject: powerpc/mm: Move hash64 tlbflush code into a new header No code changes. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Michael Ellerman --- arch/powerpc/include/asm/book3s/64/tlbflush-hash.h | 94 ++++++++++++++++++++++ arch/powerpc/include/asm/tlbflush.h | 92 +-------------------- 2 files changed, 95 insertions(+), 91 deletions(-) create mode 100644 arch/powerpc/include/asm/book3s/64/tlbflush-hash.h diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h new file mode 100644 index 000000000000..1b753f96b374 --- /dev/null +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-hash.h @@ -0,0 +1,94 @@ +#ifndef _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H +#define _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H + +#define MMU_NO_CONTEXT 0 + +/* + * TLB flushing for 64-bit hash-MMU CPUs + */ + +#include +#include + +#define PPC64_TLB_BATCH_NR 192 + +struct ppc64_tlb_batch { + int active; + unsigned long index; + struct mm_struct *mm; + real_pte_t pte[PPC64_TLB_BATCH_NR]; + unsigned long vpn[PPC64_TLB_BATCH_NR]; + unsigned int psize; + int ssize; +}; +DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); + +extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); + +#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE + +static inline void arch_enter_lazy_mmu_mode(void) +{ + struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); + + batch->active = 1; +} + +static inline void arch_leave_lazy_mmu_mode(void) +{ + struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); + + if (batch->index) + __flush_tlb_pending(batch); + batch->active = 0; +} + +#define arch_flush_lazy_mmu_mode() do {} while (0) + + +extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, + int ssize, unsigned long flags); +extern void flush_hash_range(unsigned long number, int local); +extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr, + pmd_t *pmdp, unsigned int psize, int ssize, + unsigned long flags); + +static inline void local_flush_tlb_mm(struct mm_struct *mm) +{ +} + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ +} + +static inline void local_flush_tlb_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ +} + +static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, + unsigned long vmaddr) +{ +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ +} + +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ +} + +/* Private function for use by PCI IO mapping code */ +extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, + unsigned long end); +extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd, + unsigned long addr); +#endif /* _ASM_POWERPC_BOOK3S_64_TLBFLUSH_HASH_H */ diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h index 23d351ca0303..9f77f85e3e99 100644 --- a/arch/powerpc/include/asm/tlbflush.h +++ b/arch/powerpc/include/asm/tlbflush.h @@ -78,97 +78,7 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) } #elif defined(CONFIG_PPC_STD_MMU_64) - -#define MMU_NO_CONTEXT 0 - -/* - * TLB flushing for 64-bit hash-MMU CPUs - */ - -#include -#include - -#define PPC64_TLB_BATCH_NR 192 - -struct ppc64_tlb_batch { - int active; - unsigned long index; - struct mm_struct *mm; - real_pte_t pte[PPC64_TLB_BATCH_NR]; - unsigned long vpn[PPC64_TLB_BATCH_NR]; - unsigned int psize; - int ssize; -}; -DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); - -extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); - -#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE - -static inline void arch_enter_lazy_mmu_mode(void) -{ - struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); - - batch->active = 1; -} - -static inline void arch_leave_lazy_mmu_mode(void) -{ - struct ppc64_tlb_batch *batch = this_cpu_ptr(&ppc64_tlb_batch); - - if (batch->index) - __flush_tlb_pending(batch); - batch->active = 0; -} - -#define arch_flush_lazy_mmu_mode() do {} while (0) - - -extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, - int ssize, unsigned long flags); -extern void flush_hash_range(unsigned long number, int local); -extern void flush_hash_hugepage(unsigned long vsid, unsigned long addr, - pmd_t *pmdp, unsigned int psize, int ssize, - unsigned long flags); - -static inline void local_flush_tlb_mm(struct mm_struct *mm) -{ -} - -static inline void flush_tlb_mm(struct mm_struct *mm) -{ -} - -static inline void local_flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) -{ -} - -static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) -{ -} - -static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, - unsigned long vmaddr) -{ -} - -static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) -{ -} - -static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) -{ -} - -/* Private function for use by PCI IO mapping code */ -extern void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, - unsigned long end); -extern void flush_tlb_pmd_range(struct mm_struct *mm, pmd_t *pmd, - unsigned long addr); +#include #else #error Unsupported MMU type #endif -- cgit From e623ebe6d9f1205fe12a1a1d654f4b17ebc22a2f Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 6 Sep 2015 08:42:11 -0300 Subject: [media] pxa_camera: move interrupt to tasklet In preparation for dmaengine conversion, move the camera interrupt handling into a tasklet. This won't change the global flow, as this interrupt is only used to detect the end of frame and activate DMA fifos handling. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/pxa_camera.c | 44 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 924b07d0b6c1..74dec77f896d 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -223,6 +223,7 @@ struct pxa_camera_dev { struct pxa_buffer *active; struct pxa_dma_desc *sg_tail[3]; + struct tasklet_struct task_eof; u32 save_cicr[5]; }; @@ -597,6 +598,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) unsigned long cicr0; dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); + __raw_writel(__raw_readl(pcdev->base + CISR), pcdev->base + CISR); /* Enable End-Of-Frame Interrupt */ cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; cicr0 &= ~CICR0_EOFM; @@ -914,13 +916,35 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) clk_disable_unprepare(pcdev->clk); } -static irqreturn_t pxa_camera_irq(int irq, void *data) +static void pxa_camera_eof(unsigned long arg) { - struct pxa_camera_dev *pcdev = data; - unsigned long status, cifr, cicr0; + struct pxa_camera_dev *pcdev = (struct pxa_camera_dev *)arg; + unsigned long cifr; struct pxa_buffer *buf; struct videobuf_buffer *vb; + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "Camera interrupt status 0x%x\n", + __raw_readl(pcdev->base + CISR)); + + /* Reset the FIFOs */ + cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; + __raw_writel(cifr, pcdev->base + CIFR); + + pcdev->active = list_first_entry(&pcdev->capture, + struct pxa_buffer, vb.queue); + vb = &pcdev->active->vb; + buf = container_of(vb, struct pxa_buffer, vb); + pxa_videobuf_set_actdma(pcdev, buf); + + pxa_dma_start_channels(pcdev); +} + +static irqreturn_t pxa_camera_irq(int irq, void *data) +{ + struct pxa_camera_dev *pcdev = data; + unsigned long status, cicr0; + status = __raw_readl(pcdev->base + CISR); dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Camera interrupt status 0x%lx\n", status); @@ -931,20 +955,9 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) __raw_writel(status, pcdev->base + CISR); if (status & CISR_EOF) { - /* Reset the FIFOs */ - cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; - __raw_writel(cifr, pcdev->base + CIFR); - - pcdev->active = list_first_entry(&pcdev->capture, - struct pxa_buffer, vb.queue); - vb = &pcdev->active->vb; - buf = container_of(vb, struct pxa_buffer, vb); - pxa_videobuf_set_actdma(pcdev, buf); - - pxa_dma_start_channels(pcdev); - cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_EOFM; __raw_writel(cicr0, pcdev->base + CICR0); + tasklet_schedule(&pcdev->task_eof); } return IRQ_HANDLED; @@ -1839,6 +1852,7 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->soc_host.priv = pcdev; pcdev->soc_host.v4l2_dev.dev = &pdev->dev; pcdev->soc_host.nr = pdev->id; + tasklet_init(&pcdev->task_eof, pxa_camera_eof, (unsigned long)pcdev); err = soc_camera_host_register(&pcdev->soc_host); if (err) -- cgit From e5853918d6dc971957b7daf2a2abd4b7eba37887 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 6 Sep 2015 08:42:12 -0300 Subject: [media] pxa_camera: trivial move of dma irq functions This moves the dma irq handling functions up in the source file, so that they are available before DMA preparation functions. It prepares the conversion to DMA engine, where the descriptors are populated with these functions as callbacks. Signed-off-by: Robert Jarzmik Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/pxa_camera.c | 42 +++++++++++++++----------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 74dec77f896d..0c09002494ea 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -311,6 +311,30 @@ static int calculate_dma_sglen(struct scatterlist *sglist, int sglen, return i + 1; } +static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, + enum pxa_camera_active_dma act_dma); + +static void pxa_camera_dma_irq_y(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + + pxa_camera_dma_irq(channel, pcdev, DMA_Y); +} + +static void pxa_camera_dma_irq_u(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + + pxa_camera_dma_irq(channel, pcdev, DMA_U); +} + +static void pxa_camera_dma_irq_v(int channel, void *data) +{ + struct pxa_camera_dev *pcdev = data; + + pxa_camera_dma_irq(channel, pcdev, DMA_V); +} + /** * pxa_init_dma_channel - init dma descriptors * @pcdev: pxa camera device @@ -802,24 +826,6 @@ out: spin_unlock_irqrestore(&pcdev->lock, flags); } -static void pxa_camera_dma_irq_y(int channel, void *data) -{ - struct pxa_camera_dev *pcdev = data; - pxa_camera_dma_irq(channel, pcdev, DMA_Y); -} - -static void pxa_camera_dma_irq_u(int channel, void *data) -{ - struct pxa_camera_dev *pcdev = data; - pxa_camera_dma_irq(channel, pcdev, DMA_U); -} - -static void pxa_camera_dma_irq_v(int channel, void *data) -{ - struct pxa_camera_dev *pcdev = data; - pxa_camera_dma_irq(channel, pcdev, DMA_V); -} - static struct videobuf_queue_ops pxa_videobuf_ops = { .buf_setup = pxa_videobuf_setup, .buf_prepare = pxa_videobuf_prepare, -- cgit From 1e77d55ac9c089ea8c9e5f2375d1cac3f29a99af Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sun, 6 Sep 2015 08:42:13 -0300 Subject: [media] pxa_camera: conversion to dmaengine Convert pxa_camera to dmaengine. This removes all DMA registers manipulation in favor of the more generic dmaengine API. The functional level should be the same as before. The biggest change is in the sg_split() function, which splits a videobuf-dma into several scatterlists for 3 planes captures (Y, U, V). Signed-off-by: Robert Jarzmik [g.liakhovetski@gmx.de: fix a function prototype, use bool, struct init] Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 1 + drivers/media/platform/soc_camera/pxa_camera.c | 402 +++++++++++-------------- 2 files changed, 174 insertions(+), 229 deletions(-) diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index f2776cd415ca..e5e2d6cf6638 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -30,6 +30,7 @@ config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x && SOC_CAMERA select VIDEOBUF_DMA_SG + select SG_SPLIT ---help--- This is a v4l2 driver for the PXA27x Quick Capture Interface diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 0c09002494ea..2aaf4a8f71a0 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include @@ -38,7 +41,6 @@ #include -#include #include #define PXA_CAM_VERSION "0.0.6" @@ -175,21 +177,16 @@ enum pxa_camera_active_dma { DMA_V = 0x4, }; -/* descriptor needed for the PXA DMA engine */ -struct pxa_cam_dma { - dma_addr_t sg_dma; - struct pxa_dma_desc *sg_cpu; - size_t sg_size; - int sglen; -}; - /* buffer for one video frame */ struct pxa_buffer { /* common v4l buffer stuff -- must be first */ struct videobuf_buffer vb; u32 code; /* our descriptor lists for Y, U and V channels */ - struct pxa_cam_dma dmas[3]; + struct dma_async_tx_descriptor *descs[3]; + dma_cookie_t cookie[3]; + struct scatterlist *sg[3]; + int sg_len[3]; int inwork; enum pxa_camera_active_dma active_dma; }; @@ -207,7 +204,7 @@ struct pxa_camera_dev { void __iomem *base; int channels; - unsigned int dma_chans[3]; + struct dma_chan *dma_chans[3]; struct pxacamera_platform_data *pdata; struct resource *res; @@ -222,7 +219,6 @@ struct pxa_camera_dev { spinlock_t lock; struct pxa_buffer *active; - struct pxa_dma_desc *sg_tail[3]; struct tasklet_struct task_eof; u32 save_cicr[5]; @@ -259,7 +255,6 @@ static int pxa_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) { struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); int i; @@ -274,65 +269,44 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) */ videobuf_waiton(vq, &buf->vb, 0, 0); - for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) { - if (buf->dmas[i].sg_cpu) - dma_free_coherent(ici->v4l2_dev.dev, - buf->dmas[i].sg_size, - buf->dmas[i].sg_cpu, - buf->dmas[i].sg_dma); - buf->dmas[i].sg_cpu = NULL; + for (i = 0; i < 3 && buf->descs[i]; i++) { + dmaengine_desc_free(buf->descs[i]); + kfree(buf->sg[i]); + buf->descs[i] = NULL; + buf->sg[i] = NULL; + buf->sg_len[i] = 0; } videobuf_dma_unmap(vq->dev, dma); videobuf_dma_free(dma); buf->vb.state = VIDEOBUF_NEEDS_INIT; -} - -static int calculate_dma_sglen(struct scatterlist *sglist, int sglen, - int sg_first_ofs, int size) -{ - int i, offset, dma_len, xfer_len; - struct scatterlist *sg; - - offset = sg_first_ofs; - for_each_sg(sglist, sg, sglen, i) { - dma_len = sg_dma_len(sg); - - /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ - xfer_len = roundup(min(dma_len - offset, size), 8); - - size = max(0, size - xfer_len); - offset = 0; - if (size == 0) - break; - } - BUG_ON(size != 0); - return i + 1; + dev_dbg(icd->parent, "%s end (vb=0x%p) 0x%08lx %d\n", __func__, + &buf->vb, buf->vb.baddr, buf->vb.bsize); } -static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, +static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev, enum pxa_camera_active_dma act_dma); -static void pxa_camera_dma_irq_y(int channel, void *data) +static void pxa_camera_dma_irq_y(void *data) { struct pxa_camera_dev *pcdev = data; - pxa_camera_dma_irq(channel, pcdev, DMA_Y); + pxa_camera_dma_irq(pcdev, DMA_Y); } -static void pxa_camera_dma_irq_u(int channel, void *data) +static void pxa_camera_dma_irq_u(void *data) { struct pxa_camera_dev *pcdev = data; - pxa_camera_dma_irq(channel, pcdev, DMA_U); + pxa_camera_dma_irq(pcdev, DMA_U); } -static void pxa_camera_dma_irq_v(int channel, void *data) +static void pxa_camera_dma_irq_v(void *data) { struct pxa_camera_dev *pcdev = data; - pxa_camera_dma_irq(channel, pcdev, DMA_V); + pxa_camera_dma_irq(pcdev, DMA_V); } /** @@ -343,93 +317,53 @@ static void pxa_camera_dma_irq_v(int channel, void *data) * @channel: dma channel (0 => 'Y', 1 => 'U', 2 => 'V') * @cibr: camera Receive Buffer Register * @size: bytes to transfer - * @sg_first: first element of sg_list - * @sg_first_ofs: offset in first element of sg_list + * @offset: offset in videobuffer of the first byte to transfer * * Prepares the pxa dma descriptors to transfer one camera channel. - * Beware sg_first and sg_first_ofs are both input and output parameters. * - * Returns 0 or -ENOMEM if no coherent memory is available + * Returns 0 if success or -ENOMEM if no memory is available */ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev, struct pxa_buffer *buf, struct videobuf_dmabuf *dma, int channel, - int cibr, int size, - struct scatterlist **sg_first, int *sg_first_ofs) + int cibr, int size, int offset) { - struct pxa_cam_dma *pxa_dma = &buf->dmas[channel]; - struct device *dev = pcdev->soc_host.v4l2_dev.dev; - struct scatterlist *sg; - int i, offset, sglen; - int dma_len = 0, xfer_len = 0; - - if (pxa_dma->sg_cpu) - dma_free_coherent(dev, pxa_dma->sg_size, - pxa_dma->sg_cpu, pxa_dma->sg_dma); - - sglen = calculate_dma_sglen(*sg_first, dma->sglen, - *sg_first_ofs, size); - - pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc); - pxa_dma->sg_cpu = dma_alloc_coherent(dev, pxa_dma->sg_size, - &pxa_dma->sg_dma, GFP_KERNEL); - if (!pxa_dma->sg_cpu) - return -ENOMEM; - - pxa_dma->sglen = sglen; - offset = *sg_first_ofs; - - dev_dbg(dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n", - *sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma); - - - for_each_sg(*sg_first, sg, sglen, i) { - dma_len = sg_dma_len(sg); - - /* PXA27x Developer's Manual 27.4.4.1: round up to 8 bytes */ - xfer_len = roundup(min(dma_len - offset, size), 8); - - size = max(0, size - xfer_len); - - pxa_dma->sg_cpu[i].dsadr = pcdev->res->start + cibr; - pxa_dma->sg_cpu[i].dtadr = sg_dma_address(sg) + offset; - pxa_dma->sg_cpu[i].dcmd = - DCMD_FLOWSRC | DCMD_BURST8 | DCMD_INCTRGADDR | xfer_len; -#ifdef DEBUG - if (!i) - pxa_dma->sg_cpu[i].dcmd |= DCMD_STARTIRQEN; -#endif - pxa_dma->sg_cpu[i].ddadr = - pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc); - - dev_vdbg(dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n", - pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc), - sg_dma_address(sg) + offset, xfer_len); - offset = 0; - - if (size == 0) - break; + struct dma_chan *dma_chan = pcdev->dma_chans[channel]; + struct scatterlist *sg = buf->sg[channel]; + int sglen = buf->sg_len[channel]; + struct dma_async_tx_descriptor *tx; + + tx = dmaengine_prep_slave_sg(dma_chan, sg, sglen, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT | DMA_CTRL_REUSE); + if (!tx) { + dev_err(pcdev->soc_host.v4l2_dev.dev, + "dmaengine_prep_slave_sg failed\n"); + goto fail; } - pxa_dma->sg_cpu[sglen].ddadr = DDADR_STOP; - pxa_dma->sg_cpu[sglen].dcmd = DCMD_FLOWSRC | DCMD_BURST8 | DCMD_ENDIRQEN; - - /* - * Handle 1 special case : - * - in 3 planes (YUV422P format), we might finish with xfer_len equal - * to dma_len (end on PAGE boundary). In this case, the sg element - * for next plane should be the next after the last used to store the - * last scatter gather RAM page - */ - if (xfer_len >= dma_len) { - *sg_first_ofs = xfer_len - dma_len; - *sg_first = sg_next(sg); - } else { - *sg_first_ofs = xfer_len; - *sg_first = sg; + tx->callback_param = pcdev; + switch (channel) { + case 0: + tx->callback = pxa_camera_dma_irq_y; + break; + case 1: + tx->callback = pxa_camera_dma_irq_u; + break; + case 2: + tx->callback = pxa_camera_dma_irq_v; + break; } + buf->descs[channel] = tx; return 0; +fail: + kfree(sg); + + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s (vb=0x%p) dma_tx=%p\n", + __func__, &buf->vb, tx); + + return -ENOMEM; } static void pxa_videobuf_set_actdma(struct pxa_camera_dev *pcdev, @@ -456,6 +390,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, struct pxa_buffer *buf = container_of(vb, struct pxa_buffer, vb); int ret; int size_y, size_u = 0, size_v = 0; + size_t sizes[3]; dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, vb->baddr, vb->bsize); @@ -498,9 +433,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, if (vb->state == VIDEOBUF_NEEDS_INIT) { int size = vb->size; - int next_ofs = 0; struct videobuf_dmabuf *dma = videobuf_to_dma(vb); - struct scatterlist *sg; ret = videobuf_iolock(vq, vb, NULL); if (ret) @@ -513,11 +446,19 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, size_y = size; } - sg = dma->sglist; + sizes[0] = size_y; + sizes[1] = size_u; + sizes[2] = size_v; + ret = sg_split(dma->sglist, dma->sglen, 0, pcdev->channels, + sizes, buf->sg, buf->sg_len, GFP_KERNEL); + if (ret < 0) { + dev_err(dev, "sg_split failed: %d\n", ret); + goto fail; + } /* init DMA for Y channel */ - ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y, - &sg, &next_ofs); + ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, + size_y, 0); if (ret) { dev_err(dev, "DMA initialization for Y/RGB failed\n"); goto fail; @@ -526,7 +467,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, /* init DMA for U channel */ if (size_u) ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1, - size_u, &sg, &next_ofs); + size_u, size_y); if (ret) { dev_err(dev, "DMA initialization for U failed\n"); goto fail; @@ -535,7 +476,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq, /* init DMA for V channel */ if (size_v) ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2, - size_v, &sg, &next_ofs); + size_v, size_y + size_u); if (ret) { dev_err(dev, "DMA initialization for V failed\n"); goto fail; @@ -572,10 +513,8 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev) for (i = 0; i < pcdev->channels; i++) { dev_dbg(pcdev->soc_host.v4l2_dev.dev, - "%s (channel=%d) ddadr=%08x\n", __func__, - i, active->dmas[i].sg_dma); - DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma; - DCSR(pcdev->dma_chans[i]) = DCSR_RUN; + "%s (channel=%d)\n", __func__, i); + dma_async_issue_pending(pcdev->dma_chans[i]); } } @@ -586,7 +525,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev) for (i = 0; i < pcdev->channels; i++) { dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s (channel=%d)\n", __func__, i); - DCSR(pcdev->dma_chans[i]) = 0; + dmaengine_terminate_all(pcdev->dma_chans[i]); } } @@ -594,18 +533,12 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, struct pxa_buffer *buf) { int i; - struct pxa_dma_desc *buf_last_desc; for (i = 0; i < pcdev->channels; i++) { - buf_last_desc = buf->dmas[i].sg_cpu + buf->dmas[i].sglen; - buf_last_desc->ddadr = DDADR_STOP; - - if (pcdev->sg_tail[i]) - /* Link the new buffer to the old tail */ - pcdev->sg_tail[i]->ddadr = buf->dmas[i].sg_dma; - - /* Update the channel tail */ - pcdev->sg_tail[i] = buf_last_desc; + buf->cookie[i] = dmaengine_submit(buf->descs[i]); + dev_dbg(pcdev->soc_host.v4l2_dev.dev, + "%s (channel=%d) : submit vb=%p cookie=%d\n", + __func__, i, buf, buf->descs[i]->cookie); } } @@ -697,8 +630,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, struct videobuf_buffer *vb, struct pxa_buffer *buf) { - int i; - /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ list_del_init(&vb->queue); vb->state = VIDEOBUF_DONE; @@ -710,8 +641,6 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, if (list_empty(&pcdev->capture)) { pxa_camera_stop_capture(pcdev); - for (i = 0; i < pcdev->channels; i++) - pcdev->sg_tail[i] = NULL; return; } @@ -735,50 +664,41 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev, * * Context: should only be called within the dma irq handler */ -static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev) +static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev, + dma_cookie_t last_submitted, + dma_cookie_t last_issued) { - int i, is_dma_stopped = 1; + bool is_dma_stopped = last_submitted != last_issued; - for (i = 0; i < pcdev->channels; i++) - if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP) - is_dma_stopped = 0; dev_dbg(pcdev->soc_host.v4l2_dev.dev, - "%s : top queued buffer=%p, dma_stopped=%d\n", + "%s : top queued buffer=%p, is_dma_stopped=%d\n", __func__, pcdev->active, is_dma_stopped); + if (pcdev->active && is_dma_stopped) pxa_camera_start_capture(pcdev); } -static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, +static void pxa_camera_dma_irq(struct pxa_camera_dev *pcdev, enum pxa_camera_active_dma act_dma) { struct device *dev = pcdev->soc_host.v4l2_dev.dev; - struct pxa_buffer *buf; + struct pxa_buffer *buf, *last_buf; unsigned long flags; - u32 status, camera_status, overrun; + u32 camera_status, overrun; + int chan; struct videobuf_buffer *vb; + enum dma_status last_status; + dma_cookie_t last_issued; spin_lock_irqsave(&pcdev->lock, flags); - status = DCSR(channel); - DCSR(channel) = status; - camera_status = __raw_readl(pcdev->base + CISR); + dev_dbg(dev, "camera dma irq, cisr=0x%x dma=%d\n", + camera_status, act_dma); overrun = CISR_IFO_0; if (pcdev->channels == 3) overrun |= CISR_IFO_1 | CISR_IFO_2; - if (status & DCSR_BUSERR) { - dev_err(dev, "DMA Bus Error IRQ!\n"); - goto out; - } - - if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) { - dev_err(dev, "Unknown DMA IRQ source, status: 0x%08x\n", - status); - goto out; - } - /* * pcdev->active should not be NULL in DMA irq handler. * @@ -798,28 +718,41 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev, buf = container_of(vb, struct pxa_buffer, vb); WARN_ON(buf->inwork || list_empty(&vb->queue)); - dev_dbg(dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n", - __func__, channel, status & DCSR_STARTINTR ? "SOF " : "", - status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel)); - - if (status & DCSR_ENDINTR) { - /* - * It's normal if the last frame creates an overrun, as there - * are no more DMA descriptors to fetch from QCI fifos - */ - if (camera_status & overrun && - !list_is_last(pcdev->capture.next, &pcdev->capture)) { - dev_dbg(dev, "FIFO overrun! CISR: %x\n", - camera_status); - pxa_camera_stop_capture(pcdev); - pxa_camera_start_capture(pcdev); - goto out; - } - buf->active_dma &= ~act_dma; - if (!buf->active_dma) { - pxa_camera_wakeup(pcdev, vb, buf); - pxa_camera_check_link_miss(pcdev); - } + /* + * It's normal if the last frame creates an overrun, as there + * are no more DMA descriptors to fetch from QCI fifos + */ + switch (act_dma) { + case DMA_U: + chan = 1; + break; + case DMA_V: + chan = 2; + break; + default: + chan = 0; + break; + } + last_buf = list_entry(pcdev->capture.prev, + struct pxa_buffer, vb.queue); + last_status = dma_async_is_tx_complete(pcdev->dma_chans[chan], + last_buf->cookie[chan], + NULL, &last_issued); + if (camera_status & overrun && + last_status != DMA_COMPLETE) { + dev_dbg(dev, "FIFO overrun! CISR: %x\n", + camera_status); + pxa_camera_stop_capture(pcdev); + list_for_each_entry(buf, &pcdev->capture, vb.queue) + pxa_dma_add_tail_buf(pcdev, buf); + pxa_camera_start_capture(pcdev); + goto out; + } + buf->active_dma &= ~act_dma; + if (!buf->active_dma) { + pxa_camera_wakeup(pcdev, vb, buf); + pxa_camera_check_link_miss(pcdev, last_buf->cookie[chan], + last_issued); } out: @@ -1006,10 +939,7 @@ static void pxa_camera_clock_stop(struct soc_camera_host *ici) __raw_writel(0x3ff, pcdev->base + CICR0); /* Stop DMA engine */ - DCSR(pcdev->dma_chans[0]) = 0; - DCSR(pcdev->dma_chans[1]) = 0; - DCSR(pcdev->dma_chans[2]) = 0; - + pxa_dma_stop_channels(pcdev); pxa_camera_deactivate(pcdev); } @@ -1636,10 +1566,6 @@ static int pxa_camera_resume(struct device *dev) struct pxa_camera_dev *pcdev = ici->priv; int i = 0, ret = 0; - DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; - DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; - DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; - __raw_writel(pcdev->save_cicr[i++] & ~CICR0_ENB, pcdev->base + CICR0); __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR1); __raw_writel(pcdev->save_cicr[i++], pcdev->base + CICR2); @@ -1745,8 +1671,15 @@ static int pxa_camera_probe(struct platform_device *pdev) struct pxa_camera_dev *pcdev; struct resource *res; void __iomem *base; + struct dma_slave_config config = { + .src_addr_width = 0, + .src_maxburst = 8, + .direction = DMA_DEV_TO_MEM, + }; + dma_cap_mask_t mask; + struct pxad_param params; int irq; - int err = 0; + int err = 0, i; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); @@ -1814,36 +1747,47 @@ static int pxa_camera_probe(struct platform_device *pdev) pcdev->base = base; /* request dma */ - err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH, - pxa_camera_dma_irq_y, pcdev); - if (err < 0) { + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + + params.prio = 0; + params.drcmr = 68; + pcdev->dma_chans[0] = + dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶ms, &pdev->dev, "CI_Y"); + if (!pcdev->dma_chans[0]) { dev_err(&pdev->dev, "Can't request DMA for Y\n"); - return err; + return -ENODEV; } - pcdev->dma_chans[0] = err; - dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]); - err = pxa_request_dma("CI_U", DMA_PRIO_HIGH, - pxa_camera_dma_irq_u, pcdev); - if (err < 0) { - dev_err(&pdev->dev, "Can't request DMA for U\n"); + params.drcmr = 69; + pcdev->dma_chans[1] = + dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶ms, &pdev->dev, "CI_U"); + if (!pcdev->dma_chans[1]) { + dev_err(&pdev->dev, "Can't request DMA for Y\n"); goto exit_free_dma_y; } - pcdev->dma_chans[1] = err; - dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]); - err = pxa_request_dma("CI_V", DMA_PRIO_HIGH, - pxa_camera_dma_irq_v, pcdev); - if (err < 0) { + params.drcmr = 70; + pcdev->dma_chans[2] = + dma_request_slave_channel_compat(mask, pxad_filter_fn, + ¶ms, &pdev->dev, "CI_V"); + if (!pcdev->dma_chans[2]) { dev_err(&pdev->dev, "Can't request DMA for V\n"); goto exit_free_dma_u; } - pcdev->dma_chans[2] = err; - dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]); - DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD; - DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD; - DRCMR(70) = pcdev->dma_chans[2] | DRCMR_MAPVLD; + for (i = 0; i < 3; i++) { + config.src_addr = pcdev->res->start + CIBR0 + i * 8; + err = dmaengine_slave_config(pcdev->dma_chans[i], &config); + if (err < 0) { + dev_err(&pdev->dev, "dma slave config failed: %d\n", + err); + goto exit_free_dma; + } + } /* request irq */ err = devm_request_irq(&pdev->dev, pcdev->irq, pxa_camera_irq, 0, @@ -1867,11 +1811,11 @@ static int pxa_camera_probe(struct platform_device *pdev) return 0; exit_free_dma: - pxa_free_dma(pcdev->dma_chans[2]); + dma_release_channel(pcdev->dma_chans[2]); exit_free_dma_u: - pxa_free_dma(pcdev->dma_chans[1]); + dma_release_channel(pcdev->dma_chans[1]); exit_free_dma_y: - pxa_free_dma(pcdev->dma_chans[0]); + dma_release_channel(pcdev->dma_chans[0]); return err; } @@ -1881,9 +1825,9 @@ static int pxa_camera_remove(struct platform_device *pdev) struct pxa_camera_dev *pcdev = container_of(soc_host, struct pxa_camera_dev, soc_host); - pxa_free_dma(pcdev->dma_chans[0]); - pxa_free_dma(pcdev->dma_chans[1]); - pxa_free_dma(pcdev->dma_chans[2]); + dma_release_channel(pcdev->dma_chans[0]); + dma_release_channel(pcdev->dma_chans[1]); + dma_release_channel(pcdev->dma_chans[2]); soc_camera_host_unregister(soc_host); -- cgit From 0724745fae8e2ad1da111f38741ed39828a575b6 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 9 Feb 2016 12:43:42 -0200 Subject: [media] atmel-isi: Fix bad usage of IS_ERR_VALUE IS_ERR_VALUE() assumes that its parameter is an unsigned long. It can not be used to check if an unsigned int reflects an error. Doing so can result in the following build warning. drivers/media/platform/soc_camera/atmel-isi.c: In function "atmel_isi_probe": include/linux/err.h:21:38: warning: comparison is always false due to limited range of data type drivers/media/platform/soc_camera/atmel-isi.c:1089:6: note: in expansion of macro "IS_ERR_VALUE" If that warning is seen, the return value from platform_get_irq() is not checked for errors. Signed-off-by: Guenter Roeck Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/atmel-isi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index 1af779ee3c74..ab2d9b9b1f5d 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c @@ -1026,7 +1026,7 @@ static int atmel_isi_parse_dt(struct atmel_isi *isi, static int atmel_isi_probe(struct platform_device *pdev) { - unsigned int irq; + int irq; struct atmel_isi *isi; struct resource *regs; int ret, i; @@ -1086,7 +1086,7 @@ static int atmel_isi_probe(struct platform_device *pdev) isi->width_flags |= 1 << 9; irq = platform_get_irq(pdev, 0); - if (IS_ERR_VALUE(irq)) { + if (irq < 0) { ret = irq; goto err_req_irq; } -- cgit From 5eba1726e17926d325d7f4efb1593d582bda4dcc Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sun, 21 Feb 2016 13:34:59 -0300 Subject: [media] V4L: fix a confusing function name is_state_active_or_queued() actually returns true if the buffer's state is neither active nore queued. Rename it for clarity. Signed-off-by: Guennadi Liakhovetski Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 6c02989ee33f..def84753c4c3 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -75,7 +75,8 @@ struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q) } EXPORT_SYMBOL_GPL(videobuf_alloc_vb); -static int is_state_active_or_queued(struct videobuf_queue *q, struct videobuf_buffer *vb) +static int state_neither_active_nor_queued(struct videobuf_queue *q, + struct videobuf_buffer *vb) { unsigned long flags; bool rc; @@ -95,7 +96,7 @@ int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb, MAGIC_CHECK(vb->magic, MAGIC_BUFFER); if (non_blocking) { - if (is_state_active_or_queued(q, vb)) + if (state_neither_active_nor_queued(q, vb)) return 0; return -EAGAIN; } @@ -107,9 +108,10 @@ int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb, if (is_ext_locked) mutex_unlock(q->ext_lock); if (intr) - ret = wait_event_interruptible(vb->done, is_state_active_or_queued(q, vb)); + ret = wait_event_interruptible(vb->done, + state_neither_active_nor_queued(q, vb)); else - wait_event(vb->done, is_state_active_or_queued(q, vb)); + wait_event(vb->done, state_neither_active_nor_queued(q, vb)); /* Relock */ if (is_ext_locked) mutex_lock(q->ext_lock); -- cgit From a1a87fa3a0cf8c9d3c5939c6311621ac3dbcb0da Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 17 Feb 2016 11:21:10 -0200 Subject: [media] coda: add support for native order firmware files with Freescale header Freescale distribute their VPU firmware files with a 16 byte header in BIT processor native order. This patch allows to detect the header and to reorder the firmware on the fly. With this patch it should be possible to use the distributed vpu_fw_imx{53,6q,6d}.bin files directly after renaming them to v4l-coda*-imx{53,6q,6dl}.bin. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 35 +++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 2d782ce94a67..0bc544d578e9 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1950,6 +1950,38 @@ static int coda_register_device(struct coda_dev *dev, int i) return video_register_device(vfd, VFL_TYPE_GRABBER, 0); } +static void coda_copy_firmware(struct coda_dev *dev, const u8 * const buf, + size_t size) +{ + u32 *src = (u32 *)buf; + + /* Check if the firmware has a 16-byte Freescale header, skip it */ + if (buf[0] == 'M' && buf[1] == 'X') + src += 4; + /* + * Check whether the firmware is in native order or pre-reordered for + * memory access. The first instruction opcode always is 0xe40e. + */ + if (__le16_to_cpup((__le16 *)src) == 0xe40e) { + u32 *dst = dev->codebuf.vaddr; + int i; + + /* Firmware in native order, reorder while copying */ + if (dev->devtype->product == CODA_DX6) { + for (i = 0; i < (size - 16) / 4; i++) + dst[i] = (src[i] << 16) | (src[i] >> 16); + } else { + for (i = 0; i < (size - 16) / 4; i += 2) { + dst[i] = (src[i + 1] << 16) | (src[i + 1] >> 16); + dst[i + 1] = (src[i] << 16) | (src[i] >> 16); + } + } + } else { + /* Copy the already reordered firmware image */ + memcpy(dev->codebuf.vaddr, src, size); + } +} + static void coda_fw_callback(const struct firmware *fw, void *context) { struct coda_dev *dev = context; @@ -1967,8 +1999,7 @@ static void coda_fw_callback(const struct firmware *fw, void *context) if (ret < 0) goto put_pm; - /* Copy the whole firmware image to the code buffer */ - memcpy(dev->codebuf.vaddr, fw->data, fw->size); + coda_copy_firmware(dev, fw->data, fw->size); release_firmware(fw); ret = coda_hw_init(dev); -- cgit From b5a442aab4878489455520980d578ce665033465 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 17 Feb 2016 12:57:56 -0200 Subject: [media] adv7604: fix SPA register location for ADV7612 SPA location LSB register is at 0x70. Signed-off-by: Ulrich Hecht Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/adv7604.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index befb07df036d..41a1bfc5eaa7 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -2095,7 +2095,8 @@ static int adv76xx_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) rep_write(sd, 0x76, spa_loc & 0xff); rep_write_clr_set(sd, 0x77, 0x40, (spa_loc & 0x100) >> 2); } else { - /* FIXME: Where is the SPA location LSB register ? */ + /* ADV7612 Software Manual Rev. A, p. 15 */ + rep_write(sd, 0x70, spa_loc & 0xff); rep_write_clr_set(sd, 0x71, 0x01, (spa_loc & 0x100) >> 8); } -- cgit From 2ac7f08e307509703259bc7352f4dc22bb30ad65 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 19 Feb 2016 07:18:57 -0200 Subject: [media] coda: add support for firmware files named as distributed by NXP Try loading the firmware from firmware files named vpu_fw_imx*.bin, as they are originally distributed by NXP. Fall back to v4l-coda*-imx6*.bin. Signed-off-by: Philipp Zabel Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/coda/coda-common.c | 61 +++++++++++++++++++++++-------- drivers/media/platform/coda/coda.h | 3 +- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 0bc544d578e9..fe884c1eeb82 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1982,16 +1982,44 @@ static void coda_copy_firmware(struct coda_dev *dev, const u8 * const buf, } } +static void coda_fw_callback(const struct firmware *fw, void *context); + +static int coda_firmware_request(struct coda_dev *dev) +{ + char *fw = dev->devtype->firmware[dev->firmware]; + + dev_dbg(&dev->plat_dev->dev, "requesting firmware '%s' for %s\n", fw, + coda_product_name(dev->devtype->product)); + + return request_firmware_nowait(THIS_MODULE, true, fw, + &dev->plat_dev->dev, GFP_KERNEL, dev, + coda_fw_callback); +} + static void coda_fw_callback(const struct firmware *fw, void *context) { struct coda_dev *dev = context; struct platform_device *pdev = dev->plat_dev; int i, ret; - if (!fw) { + if (!fw && dev->firmware == 1) { v4l2_err(&dev->v4l2_dev, "firmware request failed\n"); goto put_pm; } + if (!fw) { + dev->firmware = 1; + coda_firmware_request(dev); + return; + } + if (dev->firmware == 1) { + /* + * Since we can't suppress warnings for failed asynchronous + * firmware requests, report that the fallback firmware was + * found. + */ + dev_info(&pdev->dev, "Using fallback firmware %s\n", + dev->devtype->firmware[dev->firmware]); + } /* allocate auxiliary per-device code buffer for the BIT processor */ ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf", @@ -2050,17 +2078,6 @@ put_pm: pm_runtime_put_sync(&pdev->dev); } -static int coda_firmware_request(struct coda_dev *dev) -{ - char *fw = dev->devtype->firmware; - - dev_dbg(&dev->plat_dev->dev, "requesting firmware '%s' for %s\n", fw, - coda_product_name(dev->devtype->product)); - - return request_firmware_nowait(THIS_MODULE, true, - fw, &dev->plat_dev->dev, GFP_KERNEL, dev, coda_fw_callback); -} - enum coda_platform { CODA_IMX27, CODA_IMX53, @@ -2070,7 +2087,10 @@ enum coda_platform { static const struct coda_devtype coda_devdata[] = { [CODA_IMX27] = { - .firmware = "v4l-codadx6-imx27.bin", + .firmware = { + "vpu_fw_imx27_TO2.bin", + "v4l-codadx6-imx27.bin" + }, .product = CODA_DX6, .codecs = codadx6_codecs, .num_codecs = ARRAY_SIZE(codadx6_codecs), @@ -2080,7 +2100,10 @@ static const struct coda_devtype coda_devdata[] = { .iram_size = 0xb000, }, [CODA_IMX53] = { - .firmware = "v4l-coda7541-imx53.bin", + .firmware = { + "vpu_fw_imx53.bin", + "v4l-coda7541-imx53.bin" + }, .product = CODA_7541, .codecs = coda7_codecs, .num_codecs = ARRAY_SIZE(coda7_codecs), @@ -2091,7 +2114,10 @@ static const struct coda_devtype coda_devdata[] = { .iram_size = 0x14000, }, [CODA_IMX6Q] = { - .firmware = "v4l-coda960-imx6q.bin", + .firmware = { + "vpu_fw_imx6q.bin", + "v4l-coda960-imx6q.bin" + }, .product = CODA_960, .codecs = coda9_codecs, .num_codecs = ARRAY_SIZE(coda9_codecs), @@ -2102,7 +2128,10 @@ static const struct coda_devtype coda_devdata[] = { .iram_size = 0x21000, }, [CODA_IMX6DL] = { - .firmware = "v4l-coda960-imx6dl.bin", + .firmware = { + "vpu_fw_imx6d.bin", + "v4l-coda960-imx6dl.bin" + }, .product = CODA_960, .codecs = coda9_codecs, .num_codecs = ARRAY_SIZE(coda9_codecs), diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index d08e9843e9f2..8f2c71e06966 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -50,7 +50,7 @@ enum coda_product { struct coda_video_device; struct coda_devtype { - char *firmware; + char *firmware[2]; enum coda_product product; const struct coda_codec *codecs; unsigned int num_codecs; @@ -74,6 +74,7 @@ struct coda_dev { struct video_device vfd[5]; struct platform_device *plat_dev; const struct coda_devtype *devtype; + int firmware; void __iomem *regs_base; struct clk *clk_per; -- cgit From 00036b307c9f0374ef33ede2ddd745ffbec51cad Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 20 Feb 2016 06:57:38 -0200 Subject: [media] vivid: support new multiplanar YUV formats Add support for the new YUV422M, YVU422M, YUV444M and YVU444M formats. This allows applications to check their support for these formats. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/vivid/vivid-tpg.c | 32 ++++++++++++++++++++ drivers/media/platform/vivid/vivid-vid-common.c | 39 +++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c index 14256141f905..da862bb2e5f8 100644 --- a/drivers/media/platform/vivid/vivid-tpg.c +++ b/drivers/media/platform/vivid/vivid-tpg.c @@ -251,6 +251,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) tpg->planes = 3; tpg->is_yuv = true; break; + case V4L2_PIX_FMT_YUV422M: + case V4L2_PIX_FMT_YVU422M: + tpg->buffers = 3; + /* fall through */ case V4L2_PIX_FMT_YUV422P: tpg->vdownsampling[1] = 1; tpg->vdownsampling[2] = 1; @@ -283,6 +287,16 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) tpg->planes = 2; tpg->is_yuv = true; break; + case V4L2_PIX_FMT_YUV444M: + case V4L2_PIX_FMT_YVU444M: + tpg->buffers = 3; + tpg->planes = 3; + tpg->vdownsampling[1] = 1; + tpg->vdownsampling[2] = 1; + tpg->hdownsampling[1] = 1; + tpg->hdownsampling[2] = 1; + tpg->is_yuv = true; + break; case V4L2_PIX_FMT_NV24: case V4L2_PIX_FMT_NV42: tpg->vdownsampling[1] = 1; @@ -368,6 +382,10 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) tpg->twopixelsize[0] = 4; tpg->twopixelsize[1] = 4; break; + case V4L2_PIX_FMT_YUV444M: + case V4L2_PIX_FMT_YVU444M: + case V4L2_PIX_FMT_YUV422M: + case V4L2_PIX_FMT_YVU422M: case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: @@ -933,6 +951,7 @@ static void gen_twopix(struct tpg_data *tpg, buf[0][offset] = r_y; buf[0][offset+1] = r_y == 0xff ? r_y : 0; break; + case V4L2_PIX_FMT_YUV422M: case V4L2_PIX_FMT_YUV422P: case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YUV420M: @@ -947,6 +966,7 @@ static void gen_twopix(struct tpg_data *tpg, buf[1][0] = g_u; buf[2][0] = b_v; break; + case V4L2_PIX_FMT_YVU422M: case V4L2_PIX_FMT_YVU420: case V4L2_PIX_FMT_YVU420M: buf[0][offset] = r_y; @@ -988,6 +1008,18 @@ static void gen_twopix(struct tpg_data *tpg, buf[1][1] = g_u; break; + case V4L2_PIX_FMT_YUV444M: + buf[0][offset] = r_y; + buf[1][offset] = g_u; + buf[2][offset] = b_v; + break; + + case V4L2_PIX_FMT_YVU444M: + buf[0][offset] = r_y; + buf[1][offset] = b_v; + buf[2][offset] = g_u; + break; + case V4L2_PIX_FMT_NV24: buf[0][offset] = r_y; buf[1][2 * offset] = g_u; diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c index 1678b730dba2..b0d4e3a0acf0 100644 --- a/drivers/media/platform/vivid/vivid-vid-common.c +++ b/drivers/media/platform/vivid/vivid-vid-common.c @@ -445,6 +445,9 @@ struct vivid_fmt vivid_formats[] = { .planes = 1, .buffers = 1, }, + + /* Multiplanar formats */ + { .fourcc = V4L2_PIX_FMT_NV16M, .vdownsampling = { 1, 1 }, @@ -495,10 +498,42 @@ struct vivid_fmt vivid_formats[] = { .planes = 2, .buffers = 2, }, + { + .fourcc = V4L2_PIX_FMT_YUV422M, + .vdownsampling = { 1, 1, 1 }, + .bit_depth = { 8, 4, 4 }, + .is_yuv = true, + .planes = 3, + .buffers = 3, + }, + { + .fourcc = V4L2_PIX_FMT_YVU422M, + .vdownsampling = { 1, 1, 1 }, + .bit_depth = { 8, 4, 4 }, + .is_yuv = true, + .planes = 3, + .buffers = 3, + }, + { + .fourcc = V4L2_PIX_FMT_YUV444M, + .vdownsampling = { 1, 1, 1 }, + .bit_depth = { 8, 8, 8 }, + .is_yuv = true, + .planes = 3, + .buffers = 3, + }, + { + .fourcc = V4L2_PIX_FMT_YVU444M, + .vdownsampling = { 1, 1, 1 }, + .bit_depth = { 8, 8, 8 }, + .is_yuv = true, + .planes = 3, + .buffers = 3, + }, }; -/* There are 6 multiplanar formats in the list */ -#define VIVID_MPLANAR_FORMATS 6 +/* There are this many multiplanar formats in the list */ +#define VIVID_MPLANAR_FORMATS 10 const struct vivid_fmt *vivid_get_format(struct vivid_dev *dev, u32 pixelformat) { -- cgit From f52ac3f49161c1a24e1916174217c754c9b852b8 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Feb 2016 09:13:04 -0300 Subject: [media] soc_camera/omap1: move to staging in preparation for removal This driver is deprecated: it needs to be converted to vb2 and it should become a stand-alone driver instead of using the soc-camera framework. Unless someone is willing to take this on (unlikely with such ancient hardware) it is going to be removed from the kernel soon. Acked-by: Guennadi Liakhovetski Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 10 - drivers/media/platform/soc_camera/Makefile | 1 - drivers/media/platform/soc_camera/omap1_camera.c | 1738 ---------------------- drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/omap1/Kconfig | 13 + drivers/staging/media/omap1/Makefile | 3 + drivers/staging/media/omap1/omap1_camera.c | 1738 ++++++++++++++++++++++ 8 files changed, 1757 insertions(+), 1749 deletions(-) delete mode 100644 drivers/media/platform/soc_camera/omap1_camera.c create mode 100644 drivers/staging/media/omap1/Kconfig create mode 100644 drivers/staging/media/omap1/Makefile create mode 100644 drivers/staging/media/omap1/omap1_camera.c diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index e5e2d6cf6638..21136221b696 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -61,16 +61,6 @@ config VIDEO_SH_MOBILE_CEU ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface -config VIDEO_OMAP1 - tristate "OMAP1 Camera Interface driver" - depends on VIDEO_DEV && SOC_CAMERA - depends on ARCH_OMAP1 - depends on HAS_DMA - select VIDEOBUF_DMA_CONTIG - select VIDEOBUF_DMA_SG - ---help--- - This is a v4l2 driver for the TI OMAP1 camera interface - config VIDEO_MX2 tristate "i.MX27 Camera Sensor Interface driver" depends on VIDEO_DEV && SOC_CAMERA diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index 2826382dc9f8..bdd7fc9981f2 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o -obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c deleted file mode 100644 index bd721e35474a..000000000000 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ /dev/null @@ -1,1738 +0,0 @@ -/* - * V4L2 SoC Camera driver for OMAP1 Camera Interface - * - * Copyright (C) 2010, Janusz Krzysztofik - * - * Based on V4L2 Driver for i.MXL/i.MXL camera (CSI) host - * Copyright (C) 2008, Paulius Zaleckas - * Copyright (C) 2009, Darius Augulis - * - * Based on PXA SoC camera driver - * Copyright (C) 2006, Sascha Hauer, Pengutronix - * Copyright (C) 2008, Guennadi Liakhovetski - * - * Hardware specific bits initialy based on former work by Matt Callow - * drivers/media/platform/omap/omap1510cam.c - * Copyright (C) 2006 Matt Callow - * - * 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 -#include -#include -#include - -#include - - -#define DRIVER_NAME "omap1-camera" -#define DRIVER_VERSION "0.0.2" - -#define OMAP_DMA_CAMERA_IF_RX 20 - -/* - * --------------------------------------------------------------------------- - * OMAP1 Camera Interface registers - * --------------------------------------------------------------------------- - */ - -#define REG_CTRLCLOCK 0x00 -#define REG_IT_STATUS 0x04 -#define REG_MODE 0x08 -#define REG_STATUS 0x0C -#define REG_CAMDATA 0x10 -#define REG_GPIO 0x14 -#define REG_PEAK_COUNTER 0x18 - -/* CTRLCLOCK bit shifts */ -#define LCLK_EN BIT(7) -#define DPLL_EN BIT(6) -#define MCLK_EN BIT(5) -#define CAMEXCLK_EN BIT(4) -#define POLCLK BIT(3) -#define FOSCMOD_SHIFT 0 -#define FOSCMOD_MASK (0x7 << FOSCMOD_SHIFT) -#define FOSCMOD_12MHz 0x0 -#define FOSCMOD_6MHz 0x2 -#define FOSCMOD_9_6MHz 0x4 -#define FOSCMOD_24MHz 0x5 -#define FOSCMOD_8MHz 0x6 - -/* IT_STATUS bit shifts */ -#define DATA_TRANSFER BIT(5) -#define FIFO_FULL BIT(4) -#define H_DOWN BIT(3) -#define H_UP BIT(2) -#define V_DOWN BIT(1) -#define V_UP BIT(0) - -/* MODE bit shifts */ -#define RAZ_FIFO BIT(18) -#define EN_FIFO_FULL BIT(17) -#define EN_NIRQ BIT(16) -#define THRESHOLD_SHIFT 9 -#define THRESHOLD_MASK (0x7f << THRESHOLD_SHIFT) -#define DMA BIT(8) -#define EN_H_DOWN BIT(7) -#define EN_H_UP BIT(6) -#define EN_V_DOWN BIT(5) -#define EN_V_UP BIT(4) -#define ORDERCAMD BIT(3) - -#define IRQ_MASK (EN_V_UP | EN_V_DOWN | EN_H_UP | EN_H_DOWN | \ - EN_NIRQ | EN_FIFO_FULL) - -/* STATUS bit shifts */ -#define HSTATUS BIT(1) -#define VSTATUS BIT(0) - -/* GPIO bit shifts */ -#define CAM_RST BIT(0) - -/* end of OMAP1 Camera Interface registers */ - - -#define SOCAM_BUS_FLAGS (V4L2_MBUS_MASTER | \ - V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ - V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \ - V4L2_MBUS_DATA_ACTIVE_HIGH) - - -#define FIFO_SIZE ((THRESHOLD_MASK >> THRESHOLD_SHIFT) + 1) -#define FIFO_SHIFT __fls(FIFO_SIZE) - -#define DMA_BURST_SHIFT (1 + OMAP_DMA_DATA_BURST_4) -#define DMA_BURST_SIZE (1 << DMA_BURST_SHIFT) - -#define DMA_ELEMENT_SHIFT OMAP_DMA_DATA_TYPE_S32 -#define DMA_ELEMENT_SIZE (1 << DMA_ELEMENT_SHIFT) - -#define DMA_FRAME_SHIFT_CONTIG (FIFO_SHIFT - 1) -#define DMA_FRAME_SHIFT_SG DMA_BURST_SHIFT - -#define DMA_FRAME_SHIFT(x) ((x) == OMAP1_CAM_DMA_CONTIG ? \ - DMA_FRAME_SHIFT_CONTIG : \ - DMA_FRAME_SHIFT_SG) -#define DMA_FRAME_SIZE(x) (1 << DMA_FRAME_SHIFT(x)) -#define DMA_SYNC OMAP_DMA_SYNC_FRAME -#define THRESHOLD_LEVEL DMA_FRAME_SIZE - - -#define MAX_VIDEO_MEM 4 /* arbitrary video memory limit in MB */ - - -/* - * Structures - */ - -/* buffer for one video frame */ -struct omap1_cam_buf { - struct videobuf_buffer vb; - u32 code; - int inwork; - struct scatterlist *sgbuf; - int sgcount; - int bytes_left; - enum videobuf_state result; -}; - -struct omap1_cam_dev { - struct soc_camera_host soc_host; - struct clk *clk; - - unsigned int irq; - void __iomem *base; - - int dma_ch; - - struct omap1_cam_platform_data *pdata; - struct resource *res; - unsigned long pflags; - unsigned long camexclk; - - struct list_head capture; - - /* lock used to protect videobuf */ - spinlock_t lock; - - /* Pointers to DMA buffers */ - struct omap1_cam_buf *active; - struct omap1_cam_buf *ready; - - enum omap1_cam_vb_mode vb_mode; - int (*mmap_mapper)(struct videobuf_queue *q, - struct videobuf_buffer *buf, - struct vm_area_struct *vma); - - u32 reg_cache[0]; -}; - - -static void cam_write(struct omap1_cam_dev *pcdev, u16 reg, u32 val) -{ - pcdev->reg_cache[reg / sizeof(u32)] = val; - __raw_writel(val, pcdev->base + reg); -} - -static u32 cam_read(struct omap1_cam_dev *pcdev, u16 reg, bool from_cache) -{ - return !from_cache ? __raw_readl(pcdev->base + reg) : - pcdev->reg_cache[reg / sizeof(u32)]; -} - -#define CAM_READ(pcdev, reg) \ - cam_read(pcdev, REG_##reg, false) -#define CAM_WRITE(pcdev, reg, val) \ - cam_write(pcdev, REG_##reg, val) -#define CAM_READ_CACHE(pcdev, reg) \ - cam_read(pcdev, REG_##reg, true) - -/* - * Videobuf operations - */ -static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, - unsigned int *size) -{ - struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct omap1_cam_dev *pcdev = ici->priv; - - *size = icd->sizeimage; - - if (!*count || *count < OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode)) - *count = OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode); - - if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) - *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; - - dev_dbg(icd->parent, - "%s: count=%d, size=%d\n", __func__, *count, *size); - - return 0; -} - -static void free_buffer(struct videobuf_queue *vq, struct omap1_cam_buf *buf, - enum omap1_cam_vb_mode vb_mode) -{ - struct videobuf_buffer *vb = &buf->vb; - - BUG_ON(in_interrupt()); - - videobuf_waiton(vq, vb, 0, 0); - - if (vb_mode == OMAP1_CAM_DMA_CONTIG) { - videobuf_dma_contig_free(vq, vb); - } else { - struct soc_camera_device *icd = vq->priv_data; - struct device *dev = icd->parent; - struct videobuf_dmabuf *dma = videobuf_to_dma(vb); - - videobuf_dma_unmap(dev, dma); - videobuf_dma_free(dma); - } - - vb->state = VIDEOBUF_NEEDS_INIT; -} - -static int omap1_videobuf_prepare(struct videobuf_queue *vq, - struct videobuf_buffer *vb, enum v4l2_field field) -{ - struct soc_camera_device *icd = vq->priv_data; - struct omap1_cam_buf *buf = container_of(vb, struct omap1_cam_buf, vb); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct omap1_cam_dev *pcdev = ici->priv; - int ret; - - WARN_ON(!list_empty(&vb->queue)); - - BUG_ON(NULL == icd->current_fmt); - - buf->inwork = 1; - - if (buf->code != icd->current_fmt->code || vb->field != field || - vb->width != icd->user_width || - vb->height != icd->user_height) { - buf->code = icd->current_fmt->code; - vb->width = icd->user_width; - vb->height = icd->user_height; - vb->field = field; - vb->state = VIDEOBUF_NEEDS_INIT; - } - - vb->size = icd->sizeimage; - - if (vb->baddr && vb->bsize < vb->size) { - ret = -EINVAL; - goto out; - } - - if (vb->state == VIDEOBUF_NEEDS_INIT) { - ret = videobuf_iolock(vq, vb, NULL); - if (ret) - goto fail; - - vb->state = VIDEOBUF_PREPARED; - } - buf->inwork = 0; - - return 0; -fail: - free_buffer(vq, buf, pcdev->vb_mode); -out: - buf->inwork = 0; - return ret; -} - -static void set_dma_dest_params(int dma_ch, struct omap1_cam_buf *buf, - enum omap1_cam_vb_mode vb_mode) -{ - dma_addr_t dma_addr; - unsigned int block_size; - - if (vb_mode == OMAP1_CAM_DMA_CONTIG) { - dma_addr = videobuf_to_dma_contig(&buf->vb); - block_size = buf->vb.size; - } else { - if (WARN_ON(!buf->sgbuf)) { - buf->result = VIDEOBUF_ERROR; - return; - } - dma_addr = sg_dma_address(buf->sgbuf); - if (WARN_ON(!dma_addr)) { - buf->sgbuf = NULL; - buf->result = VIDEOBUF_ERROR; - return; - } - block_size = sg_dma_len(buf->sgbuf); - if (WARN_ON(!block_size)) { - buf->sgbuf = NULL; - buf->result = VIDEOBUF_ERROR; - return; - } - if (unlikely(buf->bytes_left < block_size)) - block_size = buf->bytes_left; - if (WARN_ON(dma_addr & (DMA_FRAME_SIZE(vb_mode) * - DMA_ELEMENT_SIZE - 1))) { - dma_addr = ALIGN(dma_addr, DMA_FRAME_SIZE(vb_mode) * - DMA_ELEMENT_SIZE); - block_size &= ~(DMA_FRAME_SIZE(vb_mode) * - DMA_ELEMENT_SIZE - 1); - } - buf->bytes_left -= block_size; - buf->sgcount++; - } - - omap_set_dma_dest_params(dma_ch, - OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, dma_addr, 0, 0); - omap_set_dma_transfer_params(dma_ch, - OMAP_DMA_DATA_TYPE_S32, DMA_FRAME_SIZE(vb_mode), - block_size >> (DMA_FRAME_SHIFT(vb_mode) + DMA_ELEMENT_SHIFT), - DMA_SYNC, 0, 0); -} - -static struct omap1_cam_buf *prepare_next_vb(struct omap1_cam_dev *pcdev) -{ - struct omap1_cam_buf *buf; - - /* - * If there is already a buffer pointed out by the pcdev->ready, - * (re)use it, otherwise try to fetch and configure a new one. - */ - buf = pcdev->ready; - if (!buf) { - if (list_empty(&pcdev->capture)) - return buf; - buf = list_entry(pcdev->capture.next, - struct omap1_cam_buf, vb.queue); - buf->vb.state = VIDEOBUF_ACTIVE; - pcdev->ready = buf; - list_del_init(&buf->vb.queue); - } - - if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { - /* - * In CONTIG mode, we can safely enter next buffer parameters - * into the DMA programming register set after the DMA - * has already been activated on the previous buffer - */ - set_dma_dest_params(pcdev->dma_ch, buf, pcdev->vb_mode); - } else { - /* - * In SG mode, the above is not safe since there are probably - * a bunch of sgbufs from previous sglist still pending. - * Instead, mark the sglist fresh for the upcoming - * try_next_sgbuf(). - */ - buf->sgbuf = NULL; - } - - return buf; -} - -static struct scatterlist *try_next_sgbuf(int dma_ch, struct omap1_cam_buf *buf) -{ - struct scatterlist *sgbuf; - - if (likely(buf->sgbuf)) { - /* current sglist is active */ - if (unlikely(!buf->bytes_left)) { - /* indicate sglist complete */ - sgbuf = NULL; - } else { - /* process next sgbuf */ - sgbuf = sg_next(buf->sgbuf); - if (WARN_ON(!sgbuf)) { - buf->result = VIDEOBUF_ERROR; - } else if (WARN_ON(!sg_dma_len(sgbuf))) { - sgbuf = NULL; - buf->result = VIDEOBUF_ERROR; - } - } - buf->sgbuf = sgbuf; - } else { - /* sglist is fresh, initialize it before using */ - struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); - - sgbuf = dma->sglist; - if (!(WARN_ON(!sgbuf))) { - buf->sgbuf = sgbuf; - buf->sgcount = 0; - buf->bytes_left = buf->vb.size; - buf->result = VIDEOBUF_DONE; - } - } - if (sgbuf) - /* - * Put our next sgbuf parameters (address, size) - * into the DMA programming register set. - */ - set_dma_dest_params(dma_ch, buf, OMAP1_CAM_DMA_SG); - - return sgbuf; -} - -static void start_capture(struct omap1_cam_dev *pcdev) -{ - struct omap1_cam_buf *buf = pcdev->active; - u32 ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); - u32 mode = CAM_READ_CACHE(pcdev, MODE) & ~EN_V_DOWN; - - if (WARN_ON(!buf)) - return; - - /* - * Enable start of frame interrupt, which we will use for activating - * our end of frame watchdog when capture actually starts. - */ - mode |= EN_V_UP; - - if (unlikely(ctrlclock & LCLK_EN)) - /* stop pixel clock before FIFO reset */ - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); - /* reset FIFO */ - CAM_WRITE(pcdev, MODE, mode | RAZ_FIFO); - - omap_start_dma(pcdev->dma_ch); - - if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) { - /* - * In SG mode, it's a good moment for fetching next sgbuf - * from the current sglist and, if available, already putting - * its parameters into the DMA programming register set. - */ - try_next_sgbuf(pcdev->dma_ch, buf); - } - - /* (re)enable pixel clock */ - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | LCLK_EN); - /* release FIFO reset */ - CAM_WRITE(pcdev, MODE, mode); -} - -static void suspend_capture(struct omap1_cam_dev *pcdev) -{ - u32 ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); - - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); - omap_stop_dma(pcdev->dma_ch); -} - -static void disable_capture(struct omap1_cam_dev *pcdev) -{ - u32 mode = CAM_READ_CACHE(pcdev, MODE); - - CAM_WRITE(pcdev, MODE, mode & ~(IRQ_MASK | DMA)); -} - -static void omap1_videobuf_queue(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct soc_camera_device *icd = vq->priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct omap1_cam_dev *pcdev = ici->priv; - struct omap1_cam_buf *buf; - u32 mode; - - list_add_tail(&vb->queue, &pcdev->capture); - vb->state = VIDEOBUF_QUEUED; - - if (pcdev->active) { - /* - * Capture in progress, so don't touch pcdev->ready even if - * empty. Since the transfer of the DMA programming register set - * content to the DMA working register set is done automatically - * by the DMA hardware, this can pretty well happen while we - * are keeping the lock here. Leave fetching it from the queue - * to be done when a next DMA interrupt occures instead. - */ - return; - } - - WARN_ON(pcdev->ready); - - buf = prepare_next_vb(pcdev); - if (WARN_ON(!buf)) - return; - - pcdev->active = buf; - pcdev->ready = NULL; - - dev_dbg(icd->parent, - "%s: capture not active, setup FIFO, start DMA\n", __func__); - mode = CAM_READ_CACHE(pcdev, MODE) & ~THRESHOLD_MASK; - mode |= THRESHOLD_LEVEL(pcdev->vb_mode) << THRESHOLD_SHIFT; - CAM_WRITE(pcdev, MODE, mode | EN_FIFO_FULL | DMA); - - if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) { - /* - * In SG mode, the above prepare_next_vb() didn't actually - * put anything into the DMA programming register set, - * so we have to do it now, before activating DMA. - */ - try_next_sgbuf(pcdev->dma_ch, buf); - } - - start_capture(pcdev); -} - -static void omap1_videobuf_release(struct videobuf_queue *vq, - struct videobuf_buffer *vb) -{ - struct omap1_cam_buf *buf = - container_of(vb, struct omap1_cam_buf, vb); - struct soc_camera_device *icd = vq->priv_data; - struct device *dev = icd->parent; - struct soc_camera_host *ici = to_soc_camera_host(dev); - struct omap1_cam_dev *pcdev = ici->priv; - - switch (vb->state) { - case VIDEOBUF_DONE: - dev_dbg(dev, "%s (done)\n", __func__); - break; - case VIDEOBUF_ACTIVE: - dev_dbg(dev, "%s (active)\n", __func__); - break; - case VIDEOBUF_QUEUED: - dev_dbg(dev, "%s (queued)\n", __func__); - break; - case VIDEOBUF_PREPARED: - dev_dbg(dev, "%s (prepared)\n", __func__); - break; - default: - dev_dbg(dev, "%s (unknown %d)\n", __func__, vb->state); - break; - } - - free_buffer(vq, buf, pcdev->vb_mode); -} - -static void videobuf_done(struct omap1_cam_dev *pcdev, - enum videobuf_state result) -{ - struct omap1_cam_buf *buf = pcdev->active; - struct videobuf_buffer *vb; - struct device *dev = pcdev->soc_host.icd->parent; - - if (WARN_ON(!buf)) { - suspend_capture(pcdev); - disable_capture(pcdev); - return; - } - - if (result == VIDEOBUF_ERROR) - suspend_capture(pcdev); - - vb = &buf->vb; - if (waitqueue_active(&vb->done)) { - if (!pcdev->ready && result != VIDEOBUF_ERROR) { - /* - * No next buffer has been entered into the DMA - * programming register set on time (could be done only - * while the previous DMA interurpt was processed, not - * later), so the last DMA block, be it a whole buffer - * if in CONTIG or its last sgbuf if in SG mode, is - * about to be reused by the just autoreinitialized DMA - * engine, and overwritten with next frame data. Best we - * can do is stopping the capture as soon as possible, - * hopefully before the next frame start. - */ - suspend_capture(pcdev); - } - vb->state = result; - v4l2_get_timestamp(&vb->ts); - if (result != VIDEOBUF_ERROR) - vb->field_count++; - wake_up(&vb->done); - - /* shift in next buffer */ - buf = pcdev->ready; - pcdev->active = buf; - pcdev->ready = NULL; - - if (!buf) { - /* - * No next buffer was ready on time (see above), so - * indicate error condition to force capture restart or - * stop, depending on next buffer already queued or not. - */ - result = VIDEOBUF_ERROR; - prepare_next_vb(pcdev); - - buf = pcdev->ready; - pcdev->active = buf; - pcdev->ready = NULL; - } - } else if (pcdev->ready) { - /* - * In both CONTIG and SG mode, the DMA engine has possibly - * been already autoreinitialized with the preprogrammed - * pcdev->ready buffer. We can either accept this fact - * and just swap the buffers, or provoke an error condition - * and restart capture. The former seems less intrusive. - */ - dev_dbg(dev, "%s: nobody waiting on videobuf, swap with next\n", - __func__); - pcdev->active = pcdev->ready; - - if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) { - /* - * In SG mode, we have to make sure that the buffer we - * are putting back into the pcdev->ready is marked - * fresh. - */ - buf->sgbuf = NULL; - } - pcdev->ready = buf; - - buf = pcdev->active; - } else { - /* - * No next buffer has been entered into - * the DMA programming register set on time. - */ - if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { - /* - * In CONTIG mode, the DMA engine has already been - * reinitialized with the current buffer. Best we can do - * is not touching it. - */ - dev_dbg(dev, - "%s: nobody waiting on videobuf, reuse it\n", - __func__); - } else { - /* - * In SG mode, the DMA engine has just been - * autoreinitialized with the last sgbuf from the - * current list. Restart capture in order to transfer - * next frame start into the first sgbuf, not the last - * one. - */ - if (result != VIDEOBUF_ERROR) { - suspend_capture(pcdev); - result = VIDEOBUF_ERROR; - } - } - } - - if (!buf) { - dev_dbg(dev, "%s: no more videobufs, stop capture\n", __func__); - disable_capture(pcdev); - return; - } - - if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { - /* - * In CONTIG mode, the current buffer parameters had already - * been entered into the DMA programming register set while the - * buffer was fetched with prepare_next_vb(), they may have also - * been transferred into the runtime set and already active if - * the DMA still running. - */ - } else { - /* In SG mode, extra steps are required */ - if (result == VIDEOBUF_ERROR) - /* make sure we (re)use sglist from start on error */ - buf->sgbuf = NULL; - - /* - * In any case, enter the next sgbuf parameters into the DMA - * programming register set. They will be used either during - * nearest DMA autoreinitialization or, in case of an error, - * on DMA startup below. - */ - try_next_sgbuf(pcdev->dma_ch, buf); - } - - if (result == VIDEOBUF_ERROR) { - dev_dbg(dev, "%s: videobuf error; reset FIFO, restart DMA\n", - __func__); - start_capture(pcdev); - /* - * In SG mode, the above also resulted in the next sgbuf - * parameters being entered into the DMA programming register - * set, making them ready for next DMA autoreinitialization. - */ - } - - /* - * Finally, try fetching next buffer. - * In CONTIG mode, it will also enter it into the DMA programming - * register set, making it ready for next DMA autoreinitialization. - */ - prepare_next_vb(pcdev); -} - -static void dma_isr(int channel, unsigned short status, void *data) -{ - struct omap1_cam_dev *pcdev = data; - struct omap1_cam_buf *buf = pcdev->active; - unsigned long flags; - - spin_lock_irqsave(&pcdev->lock, flags); - - if (WARN_ON(!buf)) { - suspend_capture(pcdev); - disable_capture(pcdev); - goto out; - } - - if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { - /* - * In CONTIG mode, assume we have just managed to collect the - * whole frame, hopefully before our end of frame watchdog is - * triggered. Then, all we have to do is disabling the watchdog - * for this frame, and calling videobuf_done() with success - * indicated. - */ - CAM_WRITE(pcdev, MODE, - CAM_READ_CACHE(pcdev, MODE) & ~EN_V_DOWN); - videobuf_done(pcdev, VIDEOBUF_DONE); - } else { - /* - * In SG mode, we have to process every sgbuf from the current - * sglist, one after another. - */ - if (buf->sgbuf) { - /* - * Current sglist not completed yet, try fetching next - * sgbuf, hopefully putting it into the DMA programming - * register set, making it ready for next DMA - * autoreinitialization. - */ - try_next_sgbuf(pcdev->dma_ch, buf); - if (buf->sgbuf) - goto out; - - /* - * No more sgbufs left in the current sglist. This - * doesn't mean that the whole videobuffer is already - * complete, but only that the last sgbuf from the - * current sglist is about to be filled. It will be - * ready on next DMA interrupt, signalled with the - * buf->sgbuf set back to NULL. - */ - if (buf->result != VIDEOBUF_ERROR) { - /* - * Video frame collected without errors so far, - * we can prepare for collecting a next one - * as soon as DMA gets autoreinitialized - * after the current (last) sgbuf is completed. - */ - buf = prepare_next_vb(pcdev); - if (!buf) - goto out; - - try_next_sgbuf(pcdev->dma_ch, buf); - goto out; - } - } - /* end of videobuf */ - videobuf_done(pcdev, buf->result); - } - -out: - spin_unlock_irqrestore(&pcdev->lock, flags); -} - -static irqreturn_t cam_isr(int irq, void *data) -{ - struct omap1_cam_dev *pcdev = data; - struct device *dev = pcdev->soc_host.icd->parent; - struct omap1_cam_buf *buf = pcdev->active; - u32 it_status; - unsigned long flags; - - it_status = CAM_READ(pcdev, IT_STATUS); - if (!it_status) - return IRQ_NONE; - - spin_lock_irqsave(&pcdev->lock, flags); - - if (WARN_ON(!buf)) { - dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n", - __func__, it_status); - suspend_capture(pcdev); - disable_capture(pcdev); - goto out; - } - - if (unlikely(it_status & FIFO_FULL)) { - dev_warn(dev, "%s: FIFO overflow\n", __func__); - - } else if (it_status & V_DOWN) { - /* end of video frame watchdog */ - if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { - /* - * In CONTIG mode, the watchdog is disabled with - * successful DMA end of block interrupt, and reenabled - * on next frame start. If we get here, there is nothing - * to check, we must be out of sync. - */ - } else { - if (buf->sgcount == 2) { - /* - * If exactly 2 sgbufs from the next sglist have - * been programmed into the DMA engine (the - * first one already transferred into the DMA - * runtime register set, the second one still - * in the programming set), then we are in sync. - */ - goto out; - } - } - dev_notice(dev, "%s: unexpected end of video frame\n", - __func__); - - } else if (it_status & V_UP) { - u32 mode; - - if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { - /* - * In CONTIG mode, we need this interrupt every frame - * in oredr to reenable our end of frame watchdog. - */ - mode = CAM_READ_CACHE(pcdev, MODE); - } else { - /* - * In SG mode, the below enabled end of frame watchdog - * is kept on permanently, so we can turn this one shot - * setup off. - */ - mode = CAM_READ_CACHE(pcdev, MODE) & ~EN_V_UP; - } - - if (!(mode & EN_V_DOWN)) { - /* (re)enable end of frame watchdog interrupt */ - mode |= EN_V_DOWN; - } - CAM_WRITE(pcdev, MODE, mode); - goto out; - - } else { - dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n", - __func__, it_status); - goto out; - } - - videobuf_done(pcdev, VIDEOBUF_ERROR); -out: - spin_unlock_irqrestore(&pcdev->lock, flags); - return IRQ_HANDLED; -} - -static struct videobuf_queue_ops omap1_videobuf_ops = { - .buf_setup = omap1_videobuf_setup, - .buf_prepare = omap1_videobuf_prepare, - .buf_queue = omap1_videobuf_queue, - .buf_release = omap1_videobuf_release, -}; - - -/* - * SOC Camera host operations - */ - -static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset) -{ - /* apply/release camera sensor reset if requested by platform data */ - if (pcdev->pflags & OMAP1_CAMERA_RST_HIGH) - CAM_WRITE(pcdev, GPIO, reset); - else if (pcdev->pflags & OMAP1_CAMERA_RST_LOW) - CAM_WRITE(pcdev, GPIO, !reset); -} - -static int omap1_cam_add_device(struct soc_camera_device *icd) -{ - dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", - icd->devnum); - - return 0; -} - -static void omap1_cam_remove_device(struct soc_camera_device *icd) -{ - dev_dbg(icd->parent, - "OMAP1 Camera driver detached from camera %d\n", icd->devnum); -} - -/* - * The following two functions absolutely depend on the fact, that - * there can be only one camera on OMAP1 camera sensor interface - */ -static int omap1_cam_clock_start(struct soc_camera_host *ici) -{ - struct omap1_cam_dev *pcdev = ici->priv; - u32 ctrlclock; - - clk_enable(pcdev->clk); - - /* setup sensor clock */ - ctrlclock = CAM_READ(pcdev, CTRLCLOCK); - ctrlclock &= ~(CAMEXCLK_EN | MCLK_EN | DPLL_EN); - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - - ctrlclock &= ~FOSCMOD_MASK; - switch (pcdev->camexclk) { - case 6000000: - ctrlclock |= CAMEXCLK_EN | FOSCMOD_6MHz; - break; - case 8000000: - ctrlclock |= CAMEXCLK_EN | FOSCMOD_8MHz | DPLL_EN; - break; - case 9600000: - ctrlclock |= CAMEXCLK_EN | FOSCMOD_9_6MHz | DPLL_EN; - break; - case 12000000: - ctrlclock |= CAMEXCLK_EN | FOSCMOD_12MHz; - break; - case 24000000: - ctrlclock |= CAMEXCLK_EN | FOSCMOD_24MHz | DPLL_EN; - default: - break; - } - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~DPLL_EN); - - /* enable internal clock */ - ctrlclock |= MCLK_EN; - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - - sensor_reset(pcdev, false); - - return 0; -} - -static void omap1_cam_clock_stop(struct soc_camera_host *ici) -{ - struct omap1_cam_dev *pcdev = ici->priv; - u32 ctrlclock; - - suspend_capture(pcdev); - disable_capture(pcdev); - - sensor_reset(pcdev, true); - - /* disable and release system clocks */ - ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); - ctrlclock &= ~(MCLK_EN | DPLL_EN | CAMEXCLK_EN); - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - - ctrlclock = (ctrlclock & ~FOSCMOD_MASK) | FOSCMOD_12MHz; - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | MCLK_EN); - - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~MCLK_EN); - - clk_disable(pcdev->clk); -} - -/* Duplicate standard formats based on host capability of byte swapping */ -static const struct soc_mbus_lookup omap1_cam_formats[] = { -{ - .code = MEDIA_BUS_FMT_UYVY8_2X8, - .fmt = { - .fourcc = V4L2_PIX_FMT_YUYV, - .name = "YUYV", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_VYUY8_2X8, - .fmt = { - .fourcc = V4L2_PIX_FMT_YVYU, - .name = "YVYU", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_YUYV8_2X8, - .fmt = { - .fourcc = V4L2_PIX_FMT_UYVY, - .name = "UYVY", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_YVYU8_2X8, - .fmt = { - .fourcc = V4L2_PIX_FMT_VYUY, - .name = "VYUY", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, - .fmt = { - .fourcc = V4L2_PIX_FMT_RGB555, - .name = "RGB555", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, - .fmt = { - .fourcc = V4L2_PIX_FMT_RGB555X, - .name = "RGB555X", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_RGB565_2X8_BE, - .fmt = { - .fourcc = V4L2_PIX_FMT_RGB565, - .name = "RGB565", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, { - .code = MEDIA_BUS_FMT_RGB565_2X8_LE, - .fmt = { - .fourcc = V4L2_PIX_FMT_RGB565X, - .name = "RGB565X", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_2X8_PADHI, - .order = SOC_MBUS_ORDER_BE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}, -}; - -static int omap1_cam_get_formats(struct soc_camera_device *icd, - unsigned int idx, struct soc_camera_format_xlate *xlate) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; - int formats = 0, ret; - struct v4l2_subdev_mbus_code_enum code = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - .index = idx, - }; - const struct soc_mbus_pixelfmt *fmt; - - ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); - if (ret < 0) - /* No more formats */ - return 0; - - fmt = soc_mbus_get_fmtdesc(code.code); - if (!fmt) { - dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__, - idx, code.code); - return 0; - } - - /* Check support for the requested bits-per-sample */ - if (fmt->bits_per_sample != 8) - return 0; - - switch (code.code) { - case MEDIA_BUS_FMT_YUYV8_2X8: - case MEDIA_BUS_FMT_YVYU8_2X8: - case MEDIA_BUS_FMT_UYVY8_2X8: - case MEDIA_BUS_FMT_VYUY8_2X8: - case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE: - case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE: - case MEDIA_BUS_FMT_RGB565_2X8_BE: - case MEDIA_BUS_FMT_RGB565_2X8_LE: - formats++; - if (xlate) { - xlate->host_fmt = soc_mbus_find_fmtdesc(code.code, - omap1_cam_formats, - ARRAY_SIZE(omap1_cam_formats)); - xlate->code = code.code; - xlate++; - dev_dbg(dev, - "%s: providing format %s as byte swapped code #%d\n", - __func__, xlate->host_fmt->name, code.code); - } - default: - if (xlate) - dev_dbg(dev, - "%s: providing format %s in pass-through mode\n", - __func__, fmt->name); - } - formats++; - if (xlate) { - xlate->host_fmt = fmt; - xlate->code = code.code; - xlate++; - } - - return formats; -} - -static bool is_dma_aligned(s32 bytes_per_line, unsigned int height, - enum omap1_cam_vb_mode vb_mode) -{ - int size = bytes_per_line * height; - - return IS_ALIGNED(bytes_per_line, DMA_ELEMENT_SIZE) && - IS_ALIGNED(size, DMA_FRAME_SIZE(vb_mode) * DMA_ELEMENT_SIZE); -} - -static int dma_align(int *width, int *height, - const struct soc_mbus_pixelfmt *fmt, - enum omap1_cam_vb_mode vb_mode, bool enlarge) -{ - s32 bytes_per_line = soc_mbus_bytes_per_line(*width, fmt); - - if (bytes_per_line < 0) - return bytes_per_line; - - if (!is_dma_aligned(bytes_per_line, *height, vb_mode)) { - unsigned int pxalign = __fls(bytes_per_line / *width); - unsigned int salign = DMA_FRAME_SHIFT(vb_mode) + - DMA_ELEMENT_SHIFT - pxalign; - unsigned int incr = enlarge << salign; - - v4l_bound_align_image(width, 1, *width + incr, 0, - height, 1, *height + incr, 0, salign); - return 0; - } - return 1; -} - -#define subdev_call_with_sense(pcdev, dev, icd, sd, op, function, args...) \ -({ \ - struct soc_camera_sense sense = { \ - .master_clock = pcdev->camexclk, \ - .pixel_clock_max = 0, \ - }; \ - int __ret; \ - \ - if (pcdev->pdata) \ - sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \ - icd->sense = &sense; \ - __ret = v4l2_subdev_call(sd, op, function, ##args); \ - icd->sense = NULL; \ - \ - if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { \ - if (sense.pixel_clock > sense.pixel_clock_max) { \ - dev_err(dev, \ - "%s: pixel clock %lu set by the camera too high!\n", \ - __func__, sense.pixel_clock); \ - __ret = -EINVAL; \ - } \ - } \ - __ret; \ -}) - -static int set_format(struct omap1_cam_dev *pcdev, struct device *dev, - struct soc_camera_device *icd, struct v4l2_subdev *sd, - struct v4l2_subdev_format *format, - const struct soc_camera_format_xlate *xlate) -{ - s32 bytes_per_line; - struct v4l2_mbus_framefmt *mf = &format->format; - int ret = subdev_call_with_sense(pcdev, dev, icd, sd, pad, set_fmt, NULL, format); - - if (ret < 0) { - dev_err(dev, "%s: set_fmt failed\n", __func__); - return ret; - } - - if (mf->code != xlate->code) { - dev_err(dev, "%s: unexpected pixel code change\n", __func__); - return -EINVAL; - } - - bytes_per_line = soc_mbus_bytes_per_line(mf->width, xlate->host_fmt); - if (bytes_per_line < 0) { - dev_err(dev, "%s: soc_mbus_bytes_per_line() failed\n", - __func__); - return bytes_per_line; - } - - if (!is_dma_aligned(bytes_per_line, mf->height, pcdev->vb_mode)) { - dev_err(dev, "%s: resulting geometry %ux%u not DMA aligned\n", - __func__, mf->width, mf->height); - return -EINVAL; - } - return 0; -} - -static int omap1_cam_set_crop(struct soc_camera_device *icd, - const struct v4l2_crop *crop) -{ - const struct v4l2_rect *rect = &crop->c; - const struct soc_camera_format_xlate *xlate = icd->current_fmt; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; - struct soc_camera_host *ici = to_soc_camera_host(dev); - struct omap1_cam_dev *pcdev = ici->priv; - struct v4l2_subdev_format fmt = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_mbus_framefmt *mf = &fmt.format; - int ret; - - ret = subdev_call_with_sense(pcdev, dev, icd, sd, video, s_crop, crop); - if (ret < 0) { - dev_warn(dev, "%s: failed to crop to %ux%u@%u:%u\n", __func__, - rect->width, rect->height, rect->left, rect->top); - return ret; - } - - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); - if (ret < 0) { - dev_warn(dev, "%s: failed to fetch current format\n", __func__); - return ret; - } - - ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode, - false); - if (ret < 0) { - dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", - __func__, mf->width, mf->height, - xlate->host_fmt->name); - return ret; - } - - if (!ret) { - /* sensor returned geometry not DMA aligned, trying to fix */ - ret = set_format(pcdev, dev, icd, sd, &fmt, xlate); - if (ret < 0) { - dev_err(dev, "%s: failed to set format\n", __func__); - return ret; - } - } - - icd->user_width = mf->width; - icd->user_height = mf->height; - - return 0; -} - -static int omap1_cam_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_format_xlate *xlate; - struct device *dev = icd->parent; - struct soc_camera_host *ici = to_soc_camera_host(dev); - struct omap1_cam_dev *pcdev = ici->priv; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_mbus_framefmt *mf = &format.format; - int ret; - - xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); - if (!xlate) { - dev_warn(dev, "%s: format %#x not found\n", __func__, - pix->pixelformat); - return -EINVAL; - } - - mf->width = pix->width; - mf->height = pix->height; - mf->field = pix->field; - mf->colorspace = pix->colorspace; - mf->code = xlate->code; - - ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode, - true); - if (ret < 0) { - dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", - __func__, pix->width, pix->height, - xlate->host_fmt->name); - return ret; - } - - ret = set_format(pcdev, dev, icd, sd, &format, xlate); - if (ret < 0) { - dev_err(dev, "%s: failed to set format\n", __func__); - return ret; - } - - pix->width = mf->width; - pix->height = mf->height; - pix->field = mf->field; - pix->colorspace = mf->colorspace; - icd->current_fmt = xlate; - - return 0; -} - -static int omap1_cam_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_format_xlate *xlate; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev_pad_config pad_cfg; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_TRY, - }; - struct v4l2_mbus_framefmt *mf = &format.format; - int ret; - /* TODO: limit to mx1 hardware capabilities */ - - xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); - if (!xlate) { - dev_warn(icd->parent, "Format %#x not found\n", - pix->pixelformat); - return -EINVAL; - } - - mf->width = pix->width; - mf->height = pix->height; - mf->field = pix->field; - mf->colorspace = pix->colorspace; - mf->code = xlate->code; - - /* limit to sensor capabilities */ - ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); - if (ret < 0) - return ret; - - pix->width = mf->width; - pix->height = mf->height; - pix->field = mf->field; - pix->colorspace = mf->colorspace; - - return 0; -} - -static bool sg_mode; - -/* - * Local mmap_mapper wrapper, - * used for detecting videobuf-dma-contig buffer allocation failures - * and switching to videobuf-dma-sg automatically for future attempts. - */ -static int omap1_cam_mmap_mapper(struct videobuf_queue *q, - struct videobuf_buffer *buf, - struct vm_area_struct *vma) -{ - struct soc_camera_device *icd = q->priv_data; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct omap1_cam_dev *pcdev = ici->priv; - int ret; - - ret = pcdev->mmap_mapper(q, buf, vma); - - if (ret == -ENOMEM) - sg_mode = true; - - return ret; -} - -static void omap1_cam_init_videobuf(struct videobuf_queue *q, - struct soc_camera_device *icd) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct omap1_cam_dev *pcdev = ici->priv; - - if (!sg_mode) - videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, - icd->parent, &pcdev->lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct omap1_cam_buf), icd, &ici->host_lock); - else - videobuf_queue_sg_init(q, &omap1_videobuf_ops, - icd->parent, &pcdev->lock, - V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, - sizeof(struct omap1_cam_buf), icd, &ici->host_lock); - - /* use videobuf mode (auto)selected with the module parameter */ - pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; - - /* - * Ensure we substitute the videobuf-dma-contig version of the - * mmap_mapper() callback with our own wrapper, used for switching - * automatically to videobuf-dma-sg on buffer allocation failure. - */ - if (!sg_mode && q->int_ops->mmap_mapper != omap1_cam_mmap_mapper) { - pcdev->mmap_mapper = q->int_ops->mmap_mapper; - q->int_ops->mmap_mapper = omap1_cam_mmap_mapper; - } -} - -static int omap1_cam_reqbufs(struct soc_camera_device *icd, - struct v4l2_requestbuffers *p) -{ - int i; - - /* - * This is for locking debugging only. I removed spinlocks and now I - * check whether .prepare is ever called on a linked buffer, or whether - * a dma IRQ can occur for an in-work or unlinked buffer. Until now - * it hadn't triggered - */ - for (i = 0; i < p->count; i++) { - struct omap1_cam_buf *buf = container_of(icd->vb_vidq.bufs[i], - struct omap1_cam_buf, vb); - buf->inwork = 0; - INIT_LIST_HEAD(&buf->vb.queue); - } - - return 0; -} - -static int omap1_cam_querycap(struct soc_camera_host *ici, - struct v4l2_capability *cap) -{ - /* cap->name is set by the friendly caller:-> */ - strlcpy(cap->card, "OMAP1 Camera", sizeof(cap->card)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - - return 0; -} - -static int omap1_cam_set_bus_param(struct soc_camera_device *icd) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; - struct soc_camera_host *ici = to_soc_camera_host(dev); - struct omap1_cam_dev *pcdev = ici->priv; - u32 pixfmt = icd->current_fmt->host_fmt->fourcc; - const struct soc_camera_format_xlate *xlate; - const struct soc_mbus_pixelfmt *fmt; - struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; - unsigned long common_flags; - u32 ctrlclock, mode; - int ret; - - ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); - if (!ret) { - common_flags = soc_mbus_config_compatible(&cfg, SOCAM_BUS_FLAGS); - if (!common_flags) { - dev_warn(dev, - "Flags incompatible: camera 0x%x, host 0x%x\n", - cfg.flags, SOCAM_BUS_FLAGS); - return -EINVAL; - } - } else if (ret != -ENOIOCTLCMD) { - return ret; - } else { - common_flags = SOCAM_BUS_FLAGS; - } - - /* Make choices, possibly based on platform configuration */ - if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && - (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { - if (!pcdev->pdata || - pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING) - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; - else - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; - } - - cfg.flags = common_flags; - ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); - if (ret < 0 && ret != -ENOIOCTLCMD) { - dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n", - common_flags, ret); - return ret; - } - - ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); - if (ctrlclock & LCLK_EN) - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); - - if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) { - dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n"); - ctrlclock |= POLCLK; - } else { - dev_dbg(dev, "CTRLCLOCK_REG &= ~POLCLK\n"); - ctrlclock &= ~POLCLK; - } - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); - - if (ctrlclock & LCLK_EN) - CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); - - /* select bus endianness */ - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - fmt = xlate->host_fmt; - - mode = CAM_READ(pcdev, MODE) & ~(RAZ_FIFO | IRQ_MASK | DMA); - if (fmt->order == SOC_MBUS_ORDER_LE) { - dev_dbg(dev, "MODE_REG &= ~ORDERCAMD\n"); - CAM_WRITE(pcdev, MODE, mode & ~ORDERCAMD); - } else { - dev_dbg(dev, "MODE_REG |= ORDERCAMD\n"); - CAM_WRITE(pcdev, MODE, mode | ORDERCAMD); - } - - return 0; -} - -static unsigned int omap1_cam_poll(struct file *file, poll_table *pt) -{ - struct soc_camera_device *icd = file->private_data; - struct omap1_cam_buf *buf; - - buf = list_entry(icd->vb_vidq.stream.next, struct omap1_cam_buf, - vb.stream); - - poll_wait(file, &buf->vb.done, pt); - - if (buf->vb.state == VIDEOBUF_DONE || - buf->vb.state == VIDEOBUF_ERROR) - return POLLIN | POLLRDNORM; - - return 0; -} - -static struct soc_camera_host_ops omap1_host_ops = { - .owner = THIS_MODULE, - .add = omap1_cam_add_device, - .remove = omap1_cam_remove_device, - .clock_start = omap1_cam_clock_start, - .clock_stop = omap1_cam_clock_stop, - .get_formats = omap1_cam_get_formats, - .set_crop = omap1_cam_set_crop, - .set_fmt = omap1_cam_set_fmt, - .try_fmt = omap1_cam_try_fmt, - .init_videobuf = omap1_cam_init_videobuf, - .reqbufs = omap1_cam_reqbufs, - .querycap = omap1_cam_querycap, - .set_bus_param = omap1_cam_set_bus_param, - .poll = omap1_cam_poll, -}; - -static int omap1_cam_probe(struct platform_device *pdev) -{ - struct omap1_cam_dev *pcdev; - struct resource *res; - struct clk *clk; - void __iomem *base; - 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) { - err = -ENODEV; - goto exit; - } - - clk = clk_get(&pdev->dev, "armper_ck"); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - goto exit; - } - - 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; - } - - pcdev->res = res; - pcdev->clk = clk; - - pcdev->pdata = pdev->dev.platform_data; - if (pcdev->pdata) { - pcdev->pflags = pcdev->pdata->flags; - pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000; - } - - switch (pcdev->camexclk) { - case 6000000: - case 8000000: - case 9600000: - case 12000000: - case 24000000: - break; - default: - /* pcdev->camexclk != 0 => pcdev->pdata != NULL */ - dev_warn(&pdev->dev, - "Incorrect sensor clock frequency %ld kHz, " - "should be one of 0, 6, 8, 9.6, 12 or 24 MHz, " - "please correct your platform data\n", - pcdev->pdata->camexclk_khz); - pcdev->camexclk = 0; - case 0: - dev_info(&pdev->dev, "Not providing sensor clock\n"); - } - - INIT_LIST_HEAD(&pcdev->capture); - spin_lock_init(&pcdev->lock); - - /* - * Request the region. - */ - if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) { - err = -EBUSY; - goto exit_kfree; - } - - base = ioremap(res->start, resource_size(res)); - if (!base) { - err = -ENOMEM; - goto exit_release; - } - pcdev->irq = irq; - pcdev->base = base; - - sensor_reset(pcdev, true); - - err = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, DRIVER_NAME, - 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; - } - dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_ch); - - /* preconfigure DMA */ - omap_set_dma_src_params(pcdev->dma_ch, OMAP_DMA_PORT_TIPB, - OMAP_DMA_AMODE_CONSTANT, res->start + REG_CAMDATA, - 0, 0); - omap_set_dma_dest_burst_mode(pcdev->dma_ch, OMAP_DMA_DATA_BURST_4); - /* setup DMA autoinitialization */ - omap_dma_link_lch(pcdev->dma_ch, pcdev->dma_ch); - - err = request_irq(pcdev->irq, cam_isr, 0, DRIVER_NAME, pcdev); - if (err) { - dev_err(&pdev->dev, "Camera interrupt register failed\n"); - goto exit_free_dma; - } - - pcdev->soc_host.drv_name = DRIVER_NAME; - pcdev->soc_host.ops = &omap1_host_ops; - pcdev->soc_host.priv = pcdev; - pcdev->soc_host.v4l2_dev.dev = &pdev->dev; - pcdev->soc_host.nr = pdev->id; - - err = soc_camera_host_register(&pcdev->soc_host); - if (err) - goto exit_free_irq; - - 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_iounmap: - iounmap(base); -exit_release: - release_mem_region(res->start, resource_size(res)); -exit_kfree: - kfree(pcdev); -exit_put_clk: - clk_put(clk); -exit: - return err; -} - -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); - - omap_free_dma(pcdev->dma_ch); - - soc_camera_host_unregister(soc_host); - - iounmap(pcdev->base); - - 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"); - - return 0; -} - -static struct platform_driver omap1_cam_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = omap1_cam_probe, - .remove = omap1_cam_remove, -}; - -module_platform_driver(omap1_cam_driver); - -module_param(sg_mode, bool, 0644); -MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg"); - -MODULE_DESCRIPTION("OMAP1 Camera Interface driver"); -MODULE_AUTHOR("Janusz Krzysztofik "); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(DRIVER_VERSION); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index d48a5c29c417..382d868747b6 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -29,6 +29,8 @@ source "drivers/staging/media/mn88472/Kconfig" source "drivers/staging/media/mn88473/Kconfig" +source "drivers/staging/media/omap1/Kconfig" + source "drivers/staging/media/omap4iss/Kconfig" source "drivers/staging/media/timb/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index fb94f045c40f..89d038c1c4d5 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_I2C_BCM2048) += bcm2048/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ +obj-$(CONFIG_VIDEO_OMAP1) += omap1/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ obj-$(CONFIG_DVB_MN88473) += mn88473/ diff --git a/drivers/staging/media/omap1/Kconfig b/drivers/staging/media/omap1/Kconfig new file mode 100644 index 000000000000..6cfab3a04ae1 --- /dev/null +++ b/drivers/staging/media/omap1/Kconfig @@ -0,0 +1,13 @@ +config VIDEO_OMAP1 + tristate "OMAP1 Camera Interface driver" + depends on VIDEO_DEV && SOC_CAMERA + depends on ARCH_OMAP1 + depends on HAS_DMA + select VIDEOBUF_DMA_CONTIG + select VIDEOBUF_DMA_SG + ---help--- + This is a v4l2 driver for the TI OMAP1 camera interface + + This driver is deprecated and will be removed soon unless someone + will start the work to convert this driver to the vb2 framework + and remove the soc-camera dependency. diff --git a/drivers/staging/media/omap1/Makefile b/drivers/staging/media/omap1/Makefile new file mode 100644 index 000000000000..2885622600f2 --- /dev/null +++ b/drivers/staging/media/omap1/Makefile @@ -0,0 +1,3 @@ +# Makefile for OMAP1 driver + +obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o diff --git a/drivers/staging/media/omap1/omap1_camera.c b/drivers/staging/media/omap1/omap1_camera.c new file mode 100644 index 000000000000..bd721e35474a --- /dev/null +++ b/drivers/staging/media/omap1/omap1_camera.c @@ -0,0 +1,1738 @@ +/* + * V4L2 SoC Camera driver for OMAP1 Camera Interface + * + * Copyright (C) 2010, Janusz Krzysztofik + * + * Based on V4L2 Driver for i.MXL/i.MXL camera (CSI) host + * Copyright (C) 2008, Paulius Zaleckas + * Copyright (C) 2009, Darius Augulis + * + * Based on PXA SoC camera driver + * Copyright (C) 2006, Sascha Hauer, Pengutronix + * Copyright (C) 2008, Guennadi Liakhovetski + * + * Hardware specific bits initialy based on former work by Matt Callow + * drivers/media/platform/omap/omap1510cam.c + * Copyright (C) 2006 Matt Callow + * + * 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 +#include +#include +#include + +#include + + +#define DRIVER_NAME "omap1-camera" +#define DRIVER_VERSION "0.0.2" + +#define OMAP_DMA_CAMERA_IF_RX 20 + +/* + * --------------------------------------------------------------------------- + * OMAP1 Camera Interface registers + * --------------------------------------------------------------------------- + */ + +#define REG_CTRLCLOCK 0x00 +#define REG_IT_STATUS 0x04 +#define REG_MODE 0x08 +#define REG_STATUS 0x0C +#define REG_CAMDATA 0x10 +#define REG_GPIO 0x14 +#define REG_PEAK_COUNTER 0x18 + +/* CTRLCLOCK bit shifts */ +#define LCLK_EN BIT(7) +#define DPLL_EN BIT(6) +#define MCLK_EN BIT(5) +#define CAMEXCLK_EN BIT(4) +#define POLCLK BIT(3) +#define FOSCMOD_SHIFT 0 +#define FOSCMOD_MASK (0x7 << FOSCMOD_SHIFT) +#define FOSCMOD_12MHz 0x0 +#define FOSCMOD_6MHz 0x2 +#define FOSCMOD_9_6MHz 0x4 +#define FOSCMOD_24MHz 0x5 +#define FOSCMOD_8MHz 0x6 + +/* IT_STATUS bit shifts */ +#define DATA_TRANSFER BIT(5) +#define FIFO_FULL BIT(4) +#define H_DOWN BIT(3) +#define H_UP BIT(2) +#define V_DOWN BIT(1) +#define V_UP BIT(0) + +/* MODE bit shifts */ +#define RAZ_FIFO BIT(18) +#define EN_FIFO_FULL BIT(17) +#define EN_NIRQ BIT(16) +#define THRESHOLD_SHIFT 9 +#define THRESHOLD_MASK (0x7f << THRESHOLD_SHIFT) +#define DMA BIT(8) +#define EN_H_DOWN BIT(7) +#define EN_H_UP BIT(6) +#define EN_V_DOWN BIT(5) +#define EN_V_UP BIT(4) +#define ORDERCAMD BIT(3) + +#define IRQ_MASK (EN_V_UP | EN_V_DOWN | EN_H_UP | EN_H_DOWN | \ + EN_NIRQ | EN_FIFO_FULL) + +/* STATUS bit shifts */ +#define HSTATUS BIT(1) +#define VSTATUS BIT(0) + +/* GPIO bit shifts */ +#define CAM_RST BIT(0) + +/* end of OMAP1 Camera Interface registers */ + + +#define SOCAM_BUS_FLAGS (V4L2_MBUS_MASTER | \ + V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ + V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \ + V4L2_MBUS_DATA_ACTIVE_HIGH) + + +#define FIFO_SIZE ((THRESHOLD_MASK >> THRESHOLD_SHIFT) + 1) +#define FIFO_SHIFT __fls(FIFO_SIZE) + +#define DMA_BURST_SHIFT (1 + OMAP_DMA_DATA_BURST_4) +#define DMA_BURST_SIZE (1 << DMA_BURST_SHIFT) + +#define DMA_ELEMENT_SHIFT OMAP_DMA_DATA_TYPE_S32 +#define DMA_ELEMENT_SIZE (1 << DMA_ELEMENT_SHIFT) + +#define DMA_FRAME_SHIFT_CONTIG (FIFO_SHIFT - 1) +#define DMA_FRAME_SHIFT_SG DMA_BURST_SHIFT + +#define DMA_FRAME_SHIFT(x) ((x) == OMAP1_CAM_DMA_CONTIG ? \ + DMA_FRAME_SHIFT_CONTIG : \ + DMA_FRAME_SHIFT_SG) +#define DMA_FRAME_SIZE(x) (1 << DMA_FRAME_SHIFT(x)) +#define DMA_SYNC OMAP_DMA_SYNC_FRAME +#define THRESHOLD_LEVEL DMA_FRAME_SIZE + + +#define MAX_VIDEO_MEM 4 /* arbitrary video memory limit in MB */ + + +/* + * Structures + */ + +/* buffer for one video frame */ +struct omap1_cam_buf { + struct videobuf_buffer vb; + u32 code; + int inwork; + struct scatterlist *sgbuf; + int sgcount; + int bytes_left; + enum videobuf_state result; +}; + +struct omap1_cam_dev { + struct soc_camera_host soc_host; + struct clk *clk; + + unsigned int irq; + void __iomem *base; + + int dma_ch; + + struct omap1_cam_platform_data *pdata; + struct resource *res; + unsigned long pflags; + unsigned long camexclk; + + struct list_head capture; + + /* lock used to protect videobuf */ + spinlock_t lock; + + /* Pointers to DMA buffers */ + struct omap1_cam_buf *active; + struct omap1_cam_buf *ready; + + enum omap1_cam_vb_mode vb_mode; + int (*mmap_mapper)(struct videobuf_queue *q, + struct videobuf_buffer *buf, + struct vm_area_struct *vma); + + u32 reg_cache[0]; +}; + + +static void cam_write(struct omap1_cam_dev *pcdev, u16 reg, u32 val) +{ + pcdev->reg_cache[reg / sizeof(u32)] = val; + __raw_writel(val, pcdev->base + reg); +} + +static u32 cam_read(struct omap1_cam_dev *pcdev, u16 reg, bool from_cache) +{ + return !from_cache ? __raw_readl(pcdev->base + reg) : + pcdev->reg_cache[reg / sizeof(u32)]; +} + +#define CAM_READ(pcdev, reg) \ + cam_read(pcdev, REG_##reg, false) +#define CAM_WRITE(pcdev, reg, val) \ + cam_write(pcdev, REG_##reg, val) +#define CAM_READ_CACHE(pcdev, reg) \ + cam_read(pcdev, REG_##reg, true) + +/* + * Videobuf operations + */ +static int omap1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, + unsigned int *size) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct omap1_cam_dev *pcdev = ici->priv; + + *size = icd->sizeimage; + + if (!*count || *count < OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode)) + *count = OMAP1_CAMERA_MIN_BUF_COUNT(pcdev->vb_mode); + + if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) + *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; + + dev_dbg(icd->parent, + "%s: count=%d, size=%d\n", __func__, *count, *size); + + return 0; +} + +static void free_buffer(struct videobuf_queue *vq, struct omap1_cam_buf *buf, + enum omap1_cam_vb_mode vb_mode) +{ + struct videobuf_buffer *vb = &buf->vb; + + BUG_ON(in_interrupt()); + + videobuf_waiton(vq, vb, 0, 0); + + if (vb_mode == OMAP1_CAM_DMA_CONTIG) { + videobuf_dma_contig_free(vq, vb); + } else { + struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->parent; + struct videobuf_dmabuf *dma = videobuf_to_dma(vb); + + videobuf_dma_unmap(dev, dma); + videobuf_dma_free(dma); + } + + vb->state = VIDEOBUF_NEEDS_INIT; +} + +static int omap1_videobuf_prepare(struct videobuf_queue *vq, + struct videobuf_buffer *vb, enum v4l2_field field) +{ + struct soc_camera_device *icd = vq->priv_data; + struct omap1_cam_buf *buf = container_of(vb, struct omap1_cam_buf, vb); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct omap1_cam_dev *pcdev = ici->priv; + int ret; + + WARN_ON(!list_empty(&vb->queue)); + + BUG_ON(NULL == icd->current_fmt); + + buf->inwork = 1; + + if (buf->code != icd->current_fmt->code || vb->field != field || + vb->width != icd->user_width || + vb->height != icd->user_height) { + buf->code = icd->current_fmt->code; + vb->width = icd->user_width; + vb->height = icd->user_height; + vb->field = field; + vb->state = VIDEOBUF_NEEDS_INIT; + } + + vb->size = icd->sizeimage; + + if (vb->baddr && vb->bsize < vb->size) { + ret = -EINVAL; + goto out; + } + + if (vb->state == VIDEOBUF_NEEDS_INIT) { + ret = videobuf_iolock(vq, vb, NULL); + if (ret) + goto fail; + + vb->state = VIDEOBUF_PREPARED; + } + buf->inwork = 0; + + return 0; +fail: + free_buffer(vq, buf, pcdev->vb_mode); +out: + buf->inwork = 0; + return ret; +} + +static void set_dma_dest_params(int dma_ch, struct omap1_cam_buf *buf, + enum omap1_cam_vb_mode vb_mode) +{ + dma_addr_t dma_addr; + unsigned int block_size; + + if (vb_mode == OMAP1_CAM_DMA_CONTIG) { + dma_addr = videobuf_to_dma_contig(&buf->vb); + block_size = buf->vb.size; + } else { + if (WARN_ON(!buf->sgbuf)) { + buf->result = VIDEOBUF_ERROR; + return; + } + dma_addr = sg_dma_address(buf->sgbuf); + if (WARN_ON(!dma_addr)) { + buf->sgbuf = NULL; + buf->result = VIDEOBUF_ERROR; + return; + } + block_size = sg_dma_len(buf->sgbuf); + if (WARN_ON(!block_size)) { + buf->sgbuf = NULL; + buf->result = VIDEOBUF_ERROR; + return; + } + if (unlikely(buf->bytes_left < block_size)) + block_size = buf->bytes_left; + if (WARN_ON(dma_addr & (DMA_FRAME_SIZE(vb_mode) * + DMA_ELEMENT_SIZE - 1))) { + dma_addr = ALIGN(dma_addr, DMA_FRAME_SIZE(vb_mode) * + DMA_ELEMENT_SIZE); + block_size &= ~(DMA_FRAME_SIZE(vb_mode) * + DMA_ELEMENT_SIZE - 1); + } + buf->bytes_left -= block_size; + buf->sgcount++; + } + + omap_set_dma_dest_params(dma_ch, + OMAP_DMA_PORT_EMIFF, OMAP_DMA_AMODE_POST_INC, dma_addr, 0, 0); + omap_set_dma_transfer_params(dma_ch, + OMAP_DMA_DATA_TYPE_S32, DMA_FRAME_SIZE(vb_mode), + block_size >> (DMA_FRAME_SHIFT(vb_mode) + DMA_ELEMENT_SHIFT), + DMA_SYNC, 0, 0); +} + +static struct omap1_cam_buf *prepare_next_vb(struct omap1_cam_dev *pcdev) +{ + struct omap1_cam_buf *buf; + + /* + * If there is already a buffer pointed out by the pcdev->ready, + * (re)use it, otherwise try to fetch and configure a new one. + */ + buf = pcdev->ready; + if (!buf) { + if (list_empty(&pcdev->capture)) + return buf; + buf = list_entry(pcdev->capture.next, + struct omap1_cam_buf, vb.queue); + buf->vb.state = VIDEOBUF_ACTIVE; + pcdev->ready = buf; + list_del_init(&buf->vb.queue); + } + + if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { + /* + * In CONTIG mode, we can safely enter next buffer parameters + * into the DMA programming register set after the DMA + * has already been activated on the previous buffer + */ + set_dma_dest_params(pcdev->dma_ch, buf, pcdev->vb_mode); + } else { + /* + * In SG mode, the above is not safe since there are probably + * a bunch of sgbufs from previous sglist still pending. + * Instead, mark the sglist fresh for the upcoming + * try_next_sgbuf(). + */ + buf->sgbuf = NULL; + } + + return buf; +} + +static struct scatterlist *try_next_sgbuf(int dma_ch, struct omap1_cam_buf *buf) +{ + struct scatterlist *sgbuf; + + if (likely(buf->sgbuf)) { + /* current sglist is active */ + if (unlikely(!buf->bytes_left)) { + /* indicate sglist complete */ + sgbuf = NULL; + } else { + /* process next sgbuf */ + sgbuf = sg_next(buf->sgbuf); + if (WARN_ON(!sgbuf)) { + buf->result = VIDEOBUF_ERROR; + } else if (WARN_ON(!sg_dma_len(sgbuf))) { + sgbuf = NULL; + buf->result = VIDEOBUF_ERROR; + } + } + buf->sgbuf = sgbuf; + } else { + /* sglist is fresh, initialize it before using */ + struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); + + sgbuf = dma->sglist; + if (!(WARN_ON(!sgbuf))) { + buf->sgbuf = sgbuf; + buf->sgcount = 0; + buf->bytes_left = buf->vb.size; + buf->result = VIDEOBUF_DONE; + } + } + if (sgbuf) + /* + * Put our next sgbuf parameters (address, size) + * into the DMA programming register set. + */ + set_dma_dest_params(dma_ch, buf, OMAP1_CAM_DMA_SG); + + return sgbuf; +} + +static void start_capture(struct omap1_cam_dev *pcdev) +{ + struct omap1_cam_buf *buf = pcdev->active; + u32 ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); + u32 mode = CAM_READ_CACHE(pcdev, MODE) & ~EN_V_DOWN; + + if (WARN_ON(!buf)) + return; + + /* + * Enable start of frame interrupt, which we will use for activating + * our end of frame watchdog when capture actually starts. + */ + mode |= EN_V_UP; + + if (unlikely(ctrlclock & LCLK_EN)) + /* stop pixel clock before FIFO reset */ + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); + /* reset FIFO */ + CAM_WRITE(pcdev, MODE, mode | RAZ_FIFO); + + omap_start_dma(pcdev->dma_ch); + + if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) { + /* + * In SG mode, it's a good moment for fetching next sgbuf + * from the current sglist and, if available, already putting + * its parameters into the DMA programming register set. + */ + try_next_sgbuf(pcdev->dma_ch, buf); + } + + /* (re)enable pixel clock */ + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | LCLK_EN); + /* release FIFO reset */ + CAM_WRITE(pcdev, MODE, mode); +} + +static void suspend_capture(struct omap1_cam_dev *pcdev) +{ + u32 ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); + + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); + omap_stop_dma(pcdev->dma_ch); +} + +static void disable_capture(struct omap1_cam_dev *pcdev) +{ + u32 mode = CAM_READ_CACHE(pcdev, MODE); + + CAM_WRITE(pcdev, MODE, mode & ~(IRQ_MASK | DMA)); +} + +static void omap1_videobuf_queue(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct soc_camera_device *icd = vq->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct omap1_cam_dev *pcdev = ici->priv; + struct omap1_cam_buf *buf; + u32 mode; + + list_add_tail(&vb->queue, &pcdev->capture); + vb->state = VIDEOBUF_QUEUED; + + if (pcdev->active) { + /* + * Capture in progress, so don't touch pcdev->ready even if + * empty. Since the transfer of the DMA programming register set + * content to the DMA working register set is done automatically + * by the DMA hardware, this can pretty well happen while we + * are keeping the lock here. Leave fetching it from the queue + * to be done when a next DMA interrupt occures instead. + */ + return; + } + + WARN_ON(pcdev->ready); + + buf = prepare_next_vb(pcdev); + if (WARN_ON(!buf)) + return; + + pcdev->active = buf; + pcdev->ready = NULL; + + dev_dbg(icd->parent, + "%s: capture not active, setup FIFO, start DMA\n", __func__); + mode = CAM_READ_CACHE(pcdev, MODE) & ~THRESHOLD_MASK; + mode |= THRESHOLD_LEVEL(pcdev->vb_mode) << THRESHOLD_SHIFT; + CAM_WRITE(pcdev, MODE, mode | EN_FIFO_FULL | DMA); + + if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) { + /* + * In SG mode, the above prepare_next_vb() didn't actually + * put anything into the DMA programming register set, + * so we have to do it now, before activating DMA. + */ + try_next_sgbuf(pcdev->dma_ch, buf); + } + + start_capture(pcdev); +} + +static void omap1_videobuf_release(struct videobuf_queue *vq, + struct videobuf_buffer *vb) +{ + struct omap1_cam_buf *buf = + container_of(vb, struct omap1_cam_buf, vb); + struct soc_camera_device *icd = vq->priv_data; + struct device *dev = icd->parent; + struct soc_camera_host *ici = to_soc_camera_host(dev); + struct omap1_cam_dev *pcdev = ici->priv; + + switch (vb->state) { + case VIDEOBUF_DONE: + dev_dbg(dev, "%s (done)\n", __func__); + break; + case VIDEOBUF_ACTIVE: + dev_dbg(dev, "%s (active)\n", __func__); + break; + case VIDEOBUF_QUEUED: + dev_dbg(dev, "%s (queued)\n", __func__); + break; + case VIDEOBUF_PREPARED: + dev_dbg(dev, "%s (prepared)\n", __func__); + break; + default: + dev_dbg(dev, "%s (unknown %d)\n", __func__, vb->state); + break; + } + + free_buffer(vq, buf, pcdev->vb_mode); +} + +static void videobuf_done(struct omap1_cam_dev *pcdev, + enum videobuf_state result) +{ + struct omap1_cam_buf *buf = pcdev->active; + struct videobuf_buffer *vb; + struct device *dev = pcdev->soc_host.icd->parent; + + if (WARN_ON(!buf)) { + suspend_capture(pcdev); + disable_capture(pcdev); + return; + } + + if (result == VIDEOBUF_ERROR) + suspend_capture(pcdev); + + vb = &buf->vb; + if (waitqueue_active(&vb->done)) { + if (!pcdev->ready && result != VIDEOBUF_ERROR) { + /* + * No next buffer has been entered into the DMA + * programming register set on time (could be done only + * while the previous DMA interurpt was processed, not + * later), so the last DMA block, be it a whole buffer + * if in CONTIG or its last sgbuf if in SG mode, is + * about to be reused by the just autoreinitialized DMA + * engine, and overwritten with next frame data. Best we + * can do is stopping the capture as soon as possible, + * hopefully before the next frame start. + */ + suspend_capture(pcdev); + } + vb->state = result; + v4l2_get_timestamp(&vb->ts); + if (result != VIDEOBUF_ERROR) + vb->field_count++; + wake_up(&vb->done); + + /* shift in next buffer */ + buf = pcdev->ready; + pcdev->active = buf; + pcdev->ready = NULL; + + if (!buf) { + /* + * No next buffer was ready on time (see above), so + * indicate error condition to force capture restart or + * stop, depending on next buffer already queued or not. + */ + result = VIDEOBUF_ERROR; + prepare_next_vb(pcdev); + + buf = pcdev->ready; + pcdev->active = buf; + pcdev->ready = NULL; + } + } else if (pcdev->ready) { + /* + * In both CONTIG and SG mode, the DMA engine has possibly + * been already autoreinitialized with the preprogrammed + * pcdev->ready buffer. We can either accept this fact + * and just swap the buffers, or provoke an error condition + * and restart capture. The former seems less intrusive. + */ + dev_dbg(dev, "%s: nobody waiting on videobuf, swap with next\n", + __func__); + pcdev->active = pcdev->ready; + + if (pcdev->vb_mode == OMAP1_CAM_DMA_SG) { + /* + * In SG mode, we have to make sure that the buffer we + * are putting back into the pcdev->ready is marked + * fresh. + */ + buf->sgbuf = NULL; + } + pcdev->ready = buf; + + buf = pcdev->active; + } else { + /* + * No next buffer has been entered into + * the DMA programming register set on time. + */ + if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { + /* + * In CONTIG mode, the DMA engine has already been + * reinitialized with the current buffer. Best we can do + * is not touching it. + */ + dev_dbg(dev, + "%s: nobody waiting on videobuf, reuse it\n", + __func__); + } else { + /* + * In SG mode, the DMA engine has just been + * autoreinitialized with the last sgbuf from the + * current list. Restart capture in order to transfer + * next frame start into the first sgbuf, not the last + * one. + */ + if (result != VIDEOBUF_ERROR) { + suspend_capture(pcdev); + result = VIDEOBUF_ERROR; + } + } + } + + if (!buf) { + dev_dbg(dev, "%s: no more videobufs, stop capture\n", __func__); + disable_capture(pcdev); + return; + } + + if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { + /* + * In CONTIG mode, the current buffer parameters had already + * been entered into the DMA programming register set while the + * buffer was fetched with prepare_next_vb(), they may have also + * been transferred into the runtime set and already active if + * the DMA still running. + */ + } else { + /* In SG mode, extra steps are required */ + if (result == VIDEOBUF_ERROR) + /* make sure we (re)use sglist from start on error */ + buf->sgbuf = NULL; + + /* + * In any case, enter the next sgbuf parameters into the DMA + * programming register set. They will be used either during + * nearest DMA autoreinitialization or, in case of an error, + * on DMA startup below. + */ + try_next_sgbuf(pcdev->dma_ch, buf); + } + + if (result == VIDEOBUF_ERROR) { + dev_dbg(dev, "%s: videobuf error; reset FIFO, restart DMA\n", + __func__); + start_capture(pcdev); + /* + * In SG mode, the above also resulted in the next sgbuf + * parameters being entered into the DMA programming register + * set, making them ready for next DMA autoreinitialization. + */ + } + + /* + * Finally, try fetching next buffer. + * In CONTIG mode, it will also enter it into the DMA programming + * register set, making it ready for next DMA autoreinitialization. + */ + prepare_next_vb(pcdev); +} + +static void dma_isr(int channel, unsigned short status, void *data) +{ + struct omap1_cam_dev *pcdev = data; + struct omap1_cam_buf *buf = pcdev->active; + unsigned long flags; + + spin_lock_irqsave(&pcdev->lock, flags); + + if (WARN_ON(!buf)) { + suspend_capture(pcdev); + disable_capture(pcdev); + goto out; + } + + if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { + /* + * In CONTIG mode, assume we have just managed to collect the + * whole frame, hopefully before our end of frame watchdog is + * triggered. Then, all we have to do is disabling the watchdog + * for this frame, and calling videobuf_done() with success + * indicated. + */ + CAM_WRITE(pcdev, MODE, + CAM_READ_CACHE(pcdev, MODE) & ~EN_V_DOWN); + videobuf_done(pcdev, VIDEOBUF_DONE); + } else { + /* + * In SG mode, we have to process every sgbuf from the current + * sglist, one after another. + */ + if (buf->sgbuf) { + /* + * Current sglist not completed yet, try fetching next + * sgbuf, hopefully putting it into the DMA programming + * register set, making it ready for next DMA + * autoreinitialization. + */ + try_next_sgbuf(pcdev->dma_ch, buf); + if (buf->sgbuf) + goto out; + + /* + * No more sgbufs left in the current sglist. This + * doesn't mean that the whole videobuffer is already + * complete, but only that the last sgbuf from the + * current sglist is about to be filled. It will be + * ready on next DMA interrupt, signalled with the + * buf->sgbuf set back to NULL. + */ + if (buf->result != VIDEOBUF_ERROR) { + /* + * Video frame collected without errors so far, + * we can prepare for collecting a next one + * as soon as DMA gets autoreinitialized + * after the current (last) sgbuf is completed. + */ + buf = prepare_next_vb(pcdev); + if (!buf) + goto out; + + try_next_sgbuf(pcdev->dma_ch, buf); + goto out; + } + } + /* end of videobuf */ + videobuf_done(pcdev, buf->result); + } + +out: + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static irqreturn_t cam_isr(int irq, void *data) +{ + struct omap1_cam_dev *pcdev = data; + struct device *dev = pcdev->soc_host.icd->parent; + struct omap1_cam_buf *buf = pcdev->active; + u32 it_status; + unsigned long flags; + + it_status = CAM_READ(pcdev, IT_STATUS); + if (!it_status) + return IRQ_NONE; + + spin_lock_irqsave(&pcdev->lock, flags); + + if (WARN_ON(!buf)) { + dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n", + __func__, it_status); + suspend_capture(pcdev); + disable_capture(pcdev); + goto out; + } + + if (unlikely(it_status & FIFO_FULL)) { + dev_warn(dev, "%s: FIFO overflow\n", __func__); + + } else if (it_status & V_DOWN) { + /* end of video frame watchdog */ + if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { + /* + * In CONTIG mode, the watchdog is disabled with + * successful DMA end of block interrupt, and reenabled + * on next frame start. If we get here, there is nothing + * to check, we must be out of sync. + */ + } else { + if (buf->sgcount == 2) { + /* + * If exactly 2 sgbufs from the next sglist have + * been programmed into the DMA engine (the + * first one already transferred into the DMA + * runtime register set, the second one still + * in the programming set), then we are in sync. + */ + goto out; + } + } + dev_notice(dev, "%s: unexpected end of video frame\n", + __func__); + + } else if (it_status & V_UP) { + u32 mode; + + if (pcdev->vb_mode == OMAP1_CAM_DMA_CONTIG) { + /* + * In CONTIG mode, we need this interrupt every frame + * in oredr to reenable our end of frame watchdog. + */ + mode = CAM_READ_CACHE(pcdev, MODE); + } else { + /* + * In SG mode, the below enabled end of frame watchdog + * is kept on permanently, so we can turn this one shot + * setup off. + */ + mode = CAM_READ_CACHE(pcdev, MODE) & ~EN_V_UP; + } + + if (!(mode & EN_V_DOWN)) { + /* (re)enable end of frame watchdog interrupt */ + mode |= EN_V_DOWN; + } + CAM_WRITE(pcdev, MODE, mode); + goto out; + + } else { + dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n", + __func__, it_status); + goto out; + } + + videobuf_done(pcdev, VIDEOBUF_ERROR); +out: + spin_unlock_irqrestore(&pcdev->lock, flags); + return IRQ_HANDLED; +} + +static struct videobuf_queue_ops omap1_videobuf_ops = { + .buf_setup = omap1_videobuf_setup, + .buf_prepare = omap1_videobuf_prepare, + .buf_queue = omap1_videobuf_queue, + .buf_release = omap1_videobuf_release, +}; + + +/* + * SOC Camera host operations + */ + +static void sensor_reset(struct omap1_cam_dev *pcdev, bool reset) +{ + /* apply/release camera sensor reset if requested by platform data */ + if (pcdev->pflags & OMAP1_CAMERA_RST_HIGH) + CAM_WRITE(pcdev, GPIO, reset); + else if (pcdev->pflags & OMAP1_CAMERA_RST_LOW) + CAM_WRITE(pcdev, GPIO, !reset); +} + +static int omap1_cam_add_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, "OMAP1 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void omap1_cam_remove_device(struct soc_camera_device *icd) +{ + dev_dbg(icd->parent, + "OMAP1 Camera driver detached from camera %d\n", icd->devnum); +} + +/* + * The following two functions absolutely depend on the fact, that + * there can be only one camera on OMAP1 camera sensor interface + */ +static int omap1_cam_clock_start(struct soc_camera_host *ici) +{ + struct omap1_cam_dev *pcdev = ici->priv; + u32 ctrlclock; + + clk_enable(pcdev->clk); + + /* setup sensor clock */ + ctrlclock = CAM_READ(pcdev, CTRLCLOCK); + ctrlclock &= ~(CAMEXCLK_EN | MCLK_EN | DPLL_EN); + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); + + ctrlclock &= ~FOSCMOD_MASK; + switch (pcdev->camexclk) { + case 6000000: + ctrlclock |= CAMEXCLK_EN | FOSCMOD_6MHz; + break; + case 8000000: + ctrlclock |= CAMEXCLK_EN | FOSCMOD_8MHz | DPLL_EN; + break; + case 9600000: + ctrlclock |= CAMEXCLK_EN | FOSCMOD_9_6MHz | DPLL_EN; + break; + case 12000000: + ctrlclock |= CAMEXCLK_EN | FOSCMOD_12MHz; + break; + case 24000000: + ctrlclock |= CAMEXCLK_EN | FOSCMOD_24MHz | DPLL_EN; + default: + break; + } + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~DPLL_EN); + + /* enable internal clock */ + ctrlclock |= MCLK_EN; + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); + + sensor_reset(pcdev, false); + + return 0; +} + +static void omap1_cam_clock_stop(struct soc_camera_host *ici) +{ + struct omap1_cam_dev *pcdev = ici->priv; + u32 ctrlclock; + + suspend_capture(pcdev); + disable_capture(pcdev); + + sensor_reset(pcdev, true); + + /* disable and release system clocks */ + ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); + ctrlclock &= ~(MCLK_EN | DPLL_EN | CAMEXCLK_EN); + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); + + ctrlclock = (ctrlclock & ~FOSCMOD_MASK) | FOSCMOD_12MHz; + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock | MCLK_EN); + + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~MCLK_EN); + + clk_disable(pcdev->clk); +} + +/* Duplicate standard formats based on host capability of byte swapping */ +static const struct soc_mbus_lookup omap1_cam_formats[] = { +{ + .code = MEDIA_BUS_FMT_UYVY8_2X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_YUYV, + .name = "YUYV", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_VYUY8_2X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_YVYU, + .name = "YVYU", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_UYVY, + .name = "UYVY", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_YVYU8_2X8, + .fmt = { + .fourcc = V4L2_PIX_FMT_VYUY, + .name = "VYUY", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, + .fmt = { + .fourcc = V4L2_PIX_FMT_RGB555, + .name = "RGB555", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, + .fmt = { + .fourcc = V4L2_PIX_FMT_RGB555X, + .name = "RGB555X", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_RGB565_2X8_BE, + .fmt = { + .fourcc = V4L2_PIX_FMT_RGB565, + .name = "RGB565", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, { + .code = MEDIA_BUS_FMT_RGB565_2X8_LE, + .fmt = { + .fourcc = V4L2_PIX_FMT_RGB565X, + .name = "RGB565X", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_2X8_PADHI, + .order = SOC_MBUS_ORDER_BE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}, +}; + +static int omap1_cam_get_formats(struct soc_camera_device *icd, + unsigned int idx, struct soc_camera_format_xlate *xlate) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; + int formats = 0, ret; + struct v4l2_subdev_mbus_code_enum code = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .index = idx, + }; + const struct soc_mbus_pixelfmt *fmt; + + ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); + if (ret < 0) + /* No more formats */ + return 0; + + fmt = soc_mbus_get_fmtdesc(code.code); + if (!fmt) { + dev_warn(dev, "%s: unsupported format code #%d: %d\n", __func__, + idx, code.code); + return 0; + } + + /* Check support for the requested bits-per-sample */ + if (fmt->bits_per_sample != 8) + return 0; + + switch (code.code) { + case MEDIA_BUS_FMT_YUYV8_2X8: + case MEDIA_BUS_FMT_YVYU8_2X8: + case MEDIA_BUS_FMT_UYVY8_2X8: + case MEDIA_BUS_FMT_VYUY8_2X8: + case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE: + case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE: + case MEDIA_BUS_FMT_RGB565_2X8_BE: + case MEDIA_BUS_FMT_RGB565_2X8_LE: + formats++; + if (xlate) { + xlate->host_fmt = soc_mbus_find_fmtdesc(code.code, + omap1_cam_formats, + ARRAY_SIZE(omap1_cam_formats)); + xlate->code = code.code; + xlate++; + dev_dbg(dev, + "%s: providing format %s as byte swapped code #%d\n", + __func__, xlate->host_fmt->name, code.code); + } + default: + if (xlate) + dev_dbg(dev, + "%s: providing format %s in pass-through mode\n", + __func__, fmt->name); + } + formats++; + if (xlate) { + xlate->host_fmt = fmt; + xlate->code = code.code; + xlate++; + } + + return formats; +} + +static bool is_dma_aligned(s32 bytes_per_line, unsigned int height, + enum omap1_cam_vb_mode vb_mode) +{ + int size = bytes_per_line * height; + + return IS_ALIGNED(bytes_per_line, DMA_ELEMENT_SIZE) && + IS_ALIGNED(size, DMA_FRAME_SIZE(vb_mode) * DMA_ELEMENT_SIZE); +} + +static int dma_align(int *width, int *height, + const struct soc_mbus_pixelfmt *fmt, + enum omap1_cam_vb_mode vb_mode, bool enlarge) +{ + s32 bytes_per_line = soc_mbus_bytes_per_line(*width, fmt); + + if (bytes_per_line < 0) + return bytes_per_line; + + if (!is_dma_aligned(bytes_per_line, *height, vb_mode)) { + unsigned int pxalign = __fls(bytes_per_line / *width); + unsigned int salign = DMA_FRAME_SHIFT(vb_mode) + + DMA_ELEMENT_SHIFT - pxalign; + unsigned int incr = enlarge << salign; + + v4l_bound_align_image(width, 1, *width + incr, 0, + height, 1, *height + incr, 0, salign); + return 0; + } + return 1; +} + +#define subdev_call_with_sense(pcdev, dev, icd, sd, op, function, args...) \ +({ \ + struct soc_camera_sense sense = { \ + .master_clock = pcdev->camexclk, \ + .pixel_clock_max = 0, \ + }; \ + int __ret; \ + \ + if (pcdev->pdata) \ + sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \ + icd->sense = &sense; \ + __ret = v4l2_subdev_call(sd, op, function, ##args); \ + icd->sense = NULL; \ + \ + if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) { \ + if (sense.pixel_clock > sense.pixel_clock_max) { \ + dev_err(dev, \ + "%s: pixel clock %lu set by the camera too high!\n", \ + __func__, sense.pixel_clock); \ + __ret = -EINVAL; \ + } \ + } \ + __ret; \ +}) + +static int set_format(struct omap1_cam_dev *pcdev, struct device *dev, + struct soc_camera_device *icd, struct v4l2_subdev *sd, + struct v4l2_subdev_format *format, + const struct soc_camera_format_xlate *xlate) +{ + s32 bytes_per_line; + struct v4l2_mbus_framefmt *mf = &format->format; + int ret = subdev_call_with_sense(pcdev, dev, icd, sd, pad, set_fmt, NULL, format); + + if (ret < 0) { + dev_err(dev, "%s: set_fmt failed\n", __func__); + return ret; + } + + if (mf->code != xlate->code) { + dev_err(dev, "%s: unexpected pixel code change\n", __func__); + return -EINVAL; + } + + bytes_per_line = soc_mbus_bytes_per_line(mf->width, xlate->host_fmt); + if (bytes_per_line < 0) { + dev_err(dev, "%s: soc_mbus_bytes_per_line() failed\n", + __func__); + return bytes_per_line; + } + + if (!is_dma_aligned(bytes_per_line, mf->height, pcdev->vb_mode)) { + dev_err(dev, "%s: resulting geometry %ux%u not DMA aligned\n", + __func__, mf->width, mf->height); + return -EINVAL; + } + return 0; +} + +static int omap1_cam_set_crop(struct soc_camera_device *icd, + const struct v4l2_crop *crop) +{ + const struct v4l2_rect *rect = &crop->c; + const struct soc_camera_format_xlate *xlate = icd->current_fmt; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; + struct soc_camera_host *ici = to_soc_camera_host(dev); + struct omap1_cam_dev *pcdev = ici->priv; + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *mf = &fmt.format; + int ret; + + ret = subdev_call_with_sense(pcdev, dev, icd, sd, video, s_crop, crop); + if (ret < 0) { + dev_warn(dev, "%s: failed to crop to %ux%u@%u:%u\n", __func__, + rect->width, rect->height, rect->left, rect->top); + return ret; + } + + ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); + if (ret < 0) { + dev_warn(dev, "%s: failed to fetch current format\n", __func__); + return ret; + } + + ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode, + false); + if (ret < 0) { + dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", + __func__, mf->width, mf->height, + xlate->host_fmt->name); + return ret; + } + + if (!ret) { + /* sensor returned geometry not DMA aligned, trying to fix */ + ret = set_format(pcdev, dev, icd, sd, &fmt, xlate); + if (ret < 0) { + dev_err(dev, "%s: failed to set format\n", __func__); + return ret; + } + } + + icd->user_width = mf->width; + icd->user_height = mf->height; + + return 0; +} + +static int omap1_cam_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct device *dev = icd->parent; + struct soc_camera_host *ici = to_soc_camera_host(dev); + struct omap1_cam_dev *pcdev = ici->priv; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *mf = &format.format; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(dev, "%s: format %#x not found\n", __func__, + pix->pixelformat); + return -EINVAL; + } + + mf->width = pix->width; + mf->height = pix->height; + mf->field = pix->field; + mf->colorspace = pix->colorspace; + mf->code = xlate->code; + + ret = dma_align(&mf->width, &mf->height, xlate->host_fmt, pcdev->vb_mode, + true); + if (ret < 0) { + dev_err(dev, "%s: failed to align %ux%u %s with DMA\n", + __func__, pix->width, pix->height, + xlate->host_fmt->name); + return ret; + } + + ret = set_format(pcdev, dev, icd, sd, &format, xlate); + if (ret < 0) { + dev_err(dev, "%s: failed to set format\n", __func__); + return ret; + } + + pix->width = mf->width; + pix->height = mf->height; + pix->field = mf->field; + pix->colorspace = mf->colorspace; + icd->current_fmt = xlate; + + return 0; +} + +static int omap1_cam_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_TRY, + }; + struct v4l2_mbus_framefmt *mf = &format.format; + int ret; + /* TODO: limit to mx1 hardware capabilities */ + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(icd->parent, "Format %#x not found\n", + pix->pixelformat); + return -EINVAL; + } + + mf->width = pix->width; + mf->height = pix->height; + mf->field = pix->field; + mf->colorspace = pix->colorspace; + mf->code = xlate->code; + + /* limit to sensor capabilities */ + ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); + if (ret < 0) + return ret; + + pix->width = mf->width; + pix->height = mf->height; + pix->field = mf->field; + pix->colorspace = mf->colorspace; + + return 0; +} + +static bool sg_mode; + +/* + * Local mmap_mapper wrapper, + * used for detecting videobuf-dma-contig buffer allocation failures + * and switching to videobuf-dma-sg automatically for future attempts. + */ +static int omap1_cam_mmap_mapper(struct videobuf_queue *q, + struct videobuf_buffer *buf, + struct vm_area_struct *vma) +{ + struct soc_camera_device *icd = q->priv_data; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct omap1_cam_dev *pcdev = ici->priv; + int ret; + + ret = pcdev->mmap_mapper(q, buf, vma); + + if (ret == -ENOMEM) + sg_mode = true; + + return ret; +} + +static void omap1_cam_init_videobuf(struct videobuf_queue *q, + struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct omap1_cam_dev *pcdev = ici->priv; + + if (!sg_mode) + videobuf_queue_dma_contig_init(q, &omap1_videobuf_ops, + icd->parent, &pcdev->lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + sizeof(struct omap1_cam_buf), icd, &ici->host_lock); + else + videobuf_queue_sg_init(q, &omap1_videobuf_ops, + icd->parent, &pcdev->lock, + V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, + sizeof(struct omap1_cam_buf), icd, &ici->host_lock); + + /* use videobuf mode (auto)selected with the module parameter */ + pcdev->vb_mode = sg_mode ? OMAP1_CAM_DMA_SG : OMAP1_CAM_DMA_CONTIG; + + /* + * Ensure we substitute the videobuf-dma-contig version of the + * mmap_mapper() callback with our own wrapper, used for switching + * automatically to videobuf-dma-sg on buffer allocation failure. + */ + if (!sg_mode && q->int_ops->mmap_mapper != omap1_cam_mmap_mapper) { + pcdev->mmap_mapper = q->int_ops->mmap_mapper; + q->int_ops->mmap_mapper = omap1_cam_mmap_mapper; + } +} + +static int omap1_cam_reqbufs(struct soc_camera_device *icd, + struct v4l2_requestbuffers *p) +{ + int i; + + /* + * This is for locking debugging only. I removed spinlocks and now I + * check whether .prepare is ever called on a linked buffer, or whether + * a dma IRQ can occur for an in-work or unlinked buffer. Until now + * it hadn't triggered + */ + for (i = 0; i < p->count; i++) { + struct omap1_cam_buf *buf = container_of(icd->vb_vidq.bufs[i], + struct omap1_cam_buf, vb); + buf->inwork = 0; + INIT_LIST_HEAD(&buf->vb.queue); + } + + return 0; +} + +static int omap1_cam_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the friendly caller:-> */ + strlcpy(cap->card, "OMAP1 Camera", sizeof(cap->card)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int omap1_cam_set_bus_param(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; + struct soc_camera_host *ici = to_soc_camera_host(dev); + struct omap1_cam_dev *pcdev = ici->priv; + u32 pixfmt = icd->current_fmt->host_fmt->fourcc; + const struct soc_camera_format_xlate *xlate; + const struct soc_mbus_pixelfmt *fmt; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + unsigned long common_flags; + u32 ctrlclock, mode; + int ret; + + ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); + if (!ret) { + common_flags = soc_mbus_config_compatible(&cfg, SOCAM_BUS_FLAGS); + if (!common_flags) { + dev_warn(dev, + "Flags incompatible: camera 0x%x, host 0x%x\n", + cfg.flags, SOCAM_BUS_FLAGS); + return -EINVAL; + } + } else if (ret != -ENOIOCTLCMD) { + return ret; + } else { + common_flags = SOCAM_BUS_FLAGS; + } + + /* Make choices, possibly based on platform configuration */ + if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && + (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { + if (!pcdev->pdata || + pcdev->pdata->flags & OMAP1_CAMERA_LCLK_RISING) + common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; + else + common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; + } + + cfg.flags = common_flags; + ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); + if (ret < 0 && ret != -ENOIOCTLCMD) { + dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n", + common_flags, ret); + return ret; + } + + ctrlclock = CAM_READ_CACHE(pcdev, CTRLCLOCK); + if (ctrlclock & LCLK_EN) + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); + + if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) { + dev_dbg(dev, "CTRLCLOCK_REG |= POLCLK\n"); + ctrlclock |= POLCLK; + } else { + dev_dbg(dev, "CTRLCLOCK_REG &= ~POLCLK\n"); + ctrlclock &= ~POLCLK; + } + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock & ~LCLK_EN); + + if (ctrlclock & LCLK_EN) + CAM_WRITE(pcdev, CTRLCLOCK, ctrlclock); + + /* select bus endianness */ + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + fmt = xlate->host_fmt; + + mode = CAM_READ(pcdev, MODE) & ~(RAZ_FIFO | IRQ_MASK | DMA); + if (fmt->order == SOC_MBUS_ORDER_LE) { + dev_dbg(dev, "MODE_REG &= ~ORDERCAMD\n"); + CAM_WRITE(pcdev, MODE, mode & ~ORDERCAMD); + } else { + dev_dbg(dev, "MODE_REG |= ORDERCAMD\n"); + CAM_WRITE(pcdev, MODE, mode | ORDERCAMD); + } + + return 0; +} + +static unsigned int omap1_cam_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_device *icd = file->private_data; + struct omap1_cam_buf *buf; + + buf = list_entry(icd->vb_vidq.stream.next, struct omap1_cam_buf, + vb.stream); + + poll_wait(file, &buf->vb.done, pt); + + if (buf->vb.state == VIDEOBUF_DONE || + buf->vb.state == VIDEOBUF_ERROR) + return POLLIN | POLLRDNORM; + + return 0; +} + +static struct soc_camera_host_ops omap1_host_ops = { + .owner = THIS_MODULE, + .add = omap1_cam_add_device, + .remove = omap1_cam_remove_device, + .clock_start = omap1_cam_clock_start, + .clock_stop = omap1_cam_clock_stop, + .get_formats = omap1_cam_get_formats, + .set_crop = omap1_cam_set_crop, + .set_fmt = omap1_cam_set_fmt, + .try_fmt = omap1_cam_try_fmt, + .init_videobuf = omap1_cam_init_videobuf, + .reqbufs = omap1_cam_reqbufs, + .querycap = omap1_cam_querycap, + .set_bus_param = omap1_cam_set_bus_param, + .poll = omap1_cam_poll, +}; + +static int omap1_cam_probe(struct platform_device *pdev) +{ + struct omap1_cam_dev *pcdev; + struct resource *res; + struct clk *clk; + void __iomem *base; + 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) { + err = -ENODEV; + goto exit; + } + + clk = clk_get(&pdev->dev, "armper_ck"); + if (IS_ERR(clk)) { + err = PTR_ERR(clk); + goto exit; + } + + 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; + } + + pcdev->res = res; + pcdev->clk = clk; + + pcdev->pdata = pdev->dev.platform_data; + if (pcdev->pdata) { + pcdev->pflags = pcdev->pdata->flags; + pcdev->camexclk = pcdev->pdata->camexclk_khz * 1000; + } + + switch (pcdev->camexclk) { + case 6000000: + case 8000000: + case 9600000: + case 12000000: + case 24000000: + break; + default: + /* pcdev->camexclk != 0 => pcdev->pdata != NULL */ + dev_warn(&pdev->dev, + "Incorrect sensor clock frequency %ld kHz, " + "should be one of 0, 6, 8, 9.6, 12 or 24 MHz, " + "please correct your platform data\n", + pcdev->pdata->camexclk_khz); + pcdev->camexclk = 0; + case 0: + dev_info(&pdev->dev, "Not providing sensor clock\n"); + } + + INIT_LIST_HEAD(&pcdev->capture); + spin_lock_init(&pcdev->lock); + + /* + * Request the region. + */ + if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) { + err = -EBUSY; + goto exit_kfree; + } + + base = ioremap(res->start, resource_size(res)); + if (!base) { + err = -ENOMEM; + goto exit_release; + } + pcdev->irq = irq; + pcdev->base = base; + + sensor_reset(pcdev, true); + + err = omap_request_dma(OMAP_DMA_CAMERA_IF_RX, DRIVER_NAME, + 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; + } + dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_ch); + + /* preconfigure DMA */ + omap_set_dma_src_params(pcdev->dma_ch, OMAP_DMA_PORT_TIPB, + OMAP_DMA_AMODE_CONSTANT, res->start + REG_CAMDATA, + 0, 0); + omap_set_dma_dest_burst_mode(pcdev->dma_ch, OMAP_DMA_DATA_BURST_4); + /* setup DMA autoinitialization */ + omap_dma_link_lch(pcdev->dma_ch, pcdev->dma_ch); + + err = request_irq(pcdev->irq, cam_isr, 0, DRIVER_NAME, pcdev); + if (err) { + dev_err(&pdev->dev, "Camera interrupt register failed\n"); + goto exit_free_dma; + } + + pcdev->soc_host.drv_name = DRIVER_NAME; + pcdev->soc_host.ops = &omap1_host_ops; + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; + pcdev->soc_host.nr = pdev->id; + + err = soc_camera_host_register(&pcdev->soc_host); + if (err) + goto exit_free_irq; + + 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_iounmap: + iounmap(base); +exit_release: + release_mem_region(res->start, resource_size(res)); +exit_kfree: + kfree(pcdev); +exit_put_clk: + clk_put(clk); +exit: + return err; +} + +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); + + omap_free_dma(pcdev->dma_ch); + + soc_camera_host_unregister(soc_host); + + iounmap(pcdev->base); + + 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"); + + return 0; +} + +static struct platform_driver omap1_cam_driver = { + .driver = { + .name = DRIVER_NAME, + }, + .probe = omap1_cam_probe, + .remove = omap1_cam_remove, +}; + +module_platform_driver(omap1_cam_driver); + +module_param(sg_mode, bool, 0644); +MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg"); + +MODULE_DESCRIPTION("OMAP1 Camera Interface driver"); +MODULE_AUTHOR("Janusz Krzysztofik "); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION(DRIVER_VERSION); +MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit From 679759c13d1164be6f5451138554c2fa4fcafb3e Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Feb 2016 13:38:43 -0300 Subject: [media] soc_camera/mx2_camera.c: move to staging in preparation, for removal This driver is deprecated: it should become a stand-alone driver instead of using the soc-camera framework. Unless someone is willing to take this on (unlikely with such ancient hardware) it is going to be removed from the kernel soon. Signed-off-by: Hans Verkuil Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 9 - drivers/media/platform/soc_camera/Makefile | 1 - drivers/media/platform/soc_camera/mx2_camera.c | 1636 ------------------------ drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/mx2/Kconfig | 12 + drivers/staging/media/mx2/Makefile | 3 + drivers/staging/media/mx2/mx2_camera.c | 1636 ++++++++++++++++++++++++ 8 files changed, 1654 insertions(+), 1646 deletions(-) delete mode 100644 drivers/media/platform/soc_camera/mx2_camera.c create mode 100644 drivers/staging/media/mx2/Kconfig create mode 100644 drivers/staging/media/mx2/Makefile create mode 100644 drivers/staging/media/mx2/mx2_camera.c diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index 21136221b696..0a537aba35e2 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -61,15 +61,6 @@ config VIDEO_SH_MOBILE_CEU ---help--- This is a v4l2 driver for the SuperH Mobile CEU Interface -config VIDEO_MX2 - tristate "i.MX27 Camera Sensor Interface driver" - depends on VIDEO_DEV && SOC_CAMERA - depends on SOC_IMX27 || COMPILE_TEST - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - ---help--- - This is a v4l2 driver for the i.MX27 Camera Sensor Interface - config VIDEO_ATMEL_ISI tristate "ATMEL Image Sensor Interface (ISI) support" depends on VIDEO_DEV && SOC_CAMERA diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index bdd7fc9981f2..dad56b9fa01e 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o # soc-camera host drivers have to be linked after camera drivers obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o -obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c deleted file mode 100644 index 48dd5b7851b5..000000000000 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ /dev/null @@ -1,1636 +0,0 @@ -/* - * V4L2 Driver for i.MX27 camera host - * - * Copyright (C) 2008, Sascha Hauer, Pengutronix - * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography - * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include - -#define MX2_CAM_DRV_NAME "mx2-camera" -#define MX2_CAM_VERSION "0.0.6" -#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera" - -/* reset values */ -#define CSICR1_RESET_VAL 0x40000800 -#define CSICR2_RESET_VAL 0x0 -#define CSICR3_RESET_VAL 0x0 - -/* csi control reg 1 */ -#define CSICR1_SWAP16_EN (1 << 31) -#define CSICR1_EXT_VSYNC (1 << 30) -#define CSICR1_EOF_INTEN (1 << 29) -#define CSICR1_PRP_IF_EN (1 << 28) -#define CSICR1_CCIR_MODE (1 << 27) -#define CSICR1_COF_INTEN (1 << 26) -#define CSICR1_SF_OR_INTEN (1 << 25) -#define CSICR1_RF_OR_INTEN (1 << 24) -#define CSICR1_STATFF_LEVEL (3 << 22) -#define CSICR1_STATFF_INTEN (1 << 21) -#define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19) -#define CSICR1_RXFF_INTEN (1 << 18) -#define CSICR1_SOF_POL (1 << 17) -#define CSICR1_SOF_INTEN (1 << 16) -#define CSICR1_MCLKDIV(d) (((d) & 0xF) << 12) -#define CSICR1_HSYNC_POL (1 << 11) -#define CSICR1_CCIR_EN (1 << 10) -#define CSICR1_MCLKEN (1 << 9) -#define CSICR1_FCC (1 << 8) -#define CSICR1_PACK_DIR (1 << 7) -#define CSICR1_CLR_STATFIFO (1 << 6) -#define CSICR1_CLR_RXFIFO (1 << 5) -#define CSICR1_GCLK_MODE (1 << 4) -#define CSICR1_INV_DATA (1 << 3) -#define CSICR1_INV_PCLK (1 << 2) -#define CSICR1_REDGE (1 << 1) -#define CSICR1_FMT_MASK (CSICR1_PACK_DIR | CSICR1_SWAP16_EN) - -#define SHIFT_STATFF_LEVEL 22 -#define SHIFT_RXFF_LEVEL 19 -#define SHIFT_MCLKDIV 12 - -#define SHIFT_FRMCNT 16 - -#define CSICR1 0x00 -#define CSICR2 0x04 -#define CSISR 0x08 -#define CSISTATFIFO 0x0c -#define CSIRFIFO 0x10 -#define CSIRXCNT 0x14 -#define CSICR3 0x1c -#define CSIDMASA_STATFIFO 0x20 -#define CSIDMATA_STATFIFO 0x24 -#define CSIDMASA_FB1 0x28 -#define CSIDMASA_FB2 0x2c -#define CSIFBUF_PARA 0x30 -#define CSIIMAG_PARA 0x34 - -/* EMMA PrP */ -#define PRP_CNTL 0x00 -#define PRP_INTR_CNTL 0x04 -#define PRP_INTRSTATUS 0x08 -#define PRP_SOURCE_Y_PTR 0x0c -#define PRP_SOURCE_CB_PTR 0x10 -#define PRP_SOURCE_CR_PTR 0x14 -#define PRP_DEST_RGB1_PTR 0x18 -#define PRP_DEST_RGB2_PTR 0x1c -#define PRP_DEST_Y_PTR 0x20 -#define PRP_DEST_CB_PTR 0x24 -#define PRP_DEST_CR_PTR 0x28 -#define PRP_SRC_FRAME_SIZE 0x2c -#define PRP_DEST_CH1_LINE_STRIDE 0x30 -#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 -#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 -#define PRP_CH1_OUT_IMAGE_SIZE 0x3c -#define PRP_CH2_OUT_IMAGE_SIZE 0x40 -#define PRP_SRC_LINE_STRIDE 0x44 -#define PRP_CSC_COEF_012 0x48 -#define PRP_CSC_COEF_345 0x4c -#define PRP_CSC_COEF_678 0x50 -#define PRP_CH1_RZ_HORI_COEF1 0x54 -#define PRP_CH1_RZ_HORI_COEF2 0x58 -#define PRP_CH1_RZ_HORI_VALID 0x5c -#define PRP_CH1_RZ_VERT_COEF1 0x60 -#define PRP_CH1_RZ_VERT_COEF2 0x64 -#define PRP_CH1_RZ_VERT_VALID 0x68 -#define PRP_CH2_RZ_HORI_COEF1 0x6c -#define PRP_CH2_RZ_HORI_COEF2 0x70 -#define PRP_CH2_RZ_HORI_VALID 0x74 -#define PRP_CH2_RZ_VERT_COEF1 0x78 -#define PRP_CH2_RZ_VERT_COEF2 0x7c -#define PRP_CH2_RZ_VERT_VALID 0x80 - -#define PRP_CNTL_CH1EN (1 << 0) -#define PRP_CNTL_CH2EN (1 << 1) -#define PRP_CNTL_CSIEN (1 << 2) -#define PRP_CNTL_DATA_IN_YUV420 (0 << 3) -#define PRP_CNTL_DATA_IN_YUV422 (1 << 3) -#define PRP_CNTL_DATA_IN_RGB16 (2 << 3) -#define PRP_CNTL_DATA_IN_RGB32 (3 << 3) -#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) -#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) -#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) -#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) -#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) -#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) -#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) -#define PRP_CNTL_CH1_LEN (1 << 9) -#define PRP_CNTL_CH2_LEN (1 << 10) -#define PRP_CNTL_SKIP_FRAME (1 << 11) -#define PRP_CNTL_SWRST (1 << 12) -#define PRP_CNTL_CLKEN (1 << 13) -#define PRP_CNTL_WEN (1 << 14) -#define PRP_CNTL_CH1BYP (1 << 15) -#define PRP_CNTL_IN_TSKIP(x) ((x) << 16) -#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) -#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) -#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) -#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) -#define PRP_CNTL_CH2B1EN (1 << 29) -#define PRP_CNTL_CH2B2EN (1 << 30) -#define PRP_CNTL_CH2FEN (1 << 31) - -/* IRQ Enable and status register */ -#define PRP_INTR_RDERR (1 << 0) -#define PRP_INTR_CH1WERR (1 << 1) -#define PRP_INTR_CH2WERR (1 << 2) -#define PRP_INTR_CH1FC (1 << 3) -#define PRP_INTR_CH2FC (1 << 5) -#define PRP_INTR_LBOVF (1 << 7) -#define PRP_INTR_CH2OVF (1 << 8) - -/* Resizing registers */ -#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) -#define PRP_RZ_VALID_BILINEAR (1 << 31) - -#define MAX_VIDEO_MEM 16 - -#define RESIZE_NUM_MIN 1 -#define RESIZE_NUM_MAX 20 -#define BC_COEF 3 -#define SZ_COEF (1 << BC_COEF) - -#define RESIZE_DIR_H 0 -#define RESIZE_DIR_V 1 - -#define RESIZE_ALGO_BILINEAR 0 -#define RESIZE_ALGO_AVERAGING 1 - -struct mx2_prp_cfg { - int channel; - u32 in_fmt; - u32 out_fmt; - u32 src_pixel; - u32 ch1_pixel; - u32 irq_flags; - u32 csicr1; -}; - -/* prp resizing parameters */ -struct emma_prp_resize { - int algo; /* type of algorithm used */ - int len; /* number of coefficients */ - unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ -}; - -/* prp configuration for a client-host fmt pair */ -struct mx2_fmt_cfg { - u32 in_fmt; - u32 out_fmt; - struct mx2_prp_cfg cfg; -}; - -struct mx2_buf_internal { - struct list_head queue; - int bufnum; - bool discard; -}; - -/* buffer for one video frame */ -struct mx2_buffer { - /* common v4l buffer stuff -- must be first */ - struct vb2_v4l2_buffer vb; - struct mx2_buf_internal internal; -}; - -enum mx2_camera_type { - IMX27_CAMERA, -}; - -struct mx2_camera_dev { - struct device *dev; - struct soc_camera_host soc_host; - struct clk *clk_emma_ahb, *clk_emma_ipg; - struct clk *clk_csi_ahb, *clk_csi_per; - - void __iomem *base_csi, *base_emma; - - struct mx2_camera_platform_data *pdata; - unsigned long platform_flags; - - struct list_head capture; - struct list_head active_bufs; - struct list_head discard; - - spinlock_t lock; - - int dma; - struct mx2_buffer *active; - struct mx2_buffer *fb1_active; - struct mx2_buffer *fb2_active; - - u32 csicr1; - enum mx2_camera_type devtype; - - struct mx2_buf_internal buf_discard[2]; - void *discard_buffer; - dma_addr_t discard_buffer_dma; - size_t discard_size; - struct mx2_fmt_cfg *emma_prp; - struct emma_prp_resize resizing[2]; - unsigned int s_width, s_height; - u32 frame_count; - struct vb2_alloc_ctx *alloc_ctx; -}; - -static struct platform_device_id mx2_camera_devtype[] = { - { - .name = "imx27-camera", - .driver_data = IMX27_CAMERA, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, mx2_camera_devtype); - -static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) -{ - return container_of(int_buf, struct mx2_buffer, internal); -} - -static struct mx2_fmt_cfg mx27_emma_prp_table[] = { - /* - * This is a generic configuration which is valid for most - * prp input-output format combinations. - * We set the incoming and outgoing pixelformat to a - * 16 Bit wide format and adjust the bytesperline - * accordingly. With this configuration the inputdata - * will not be changed by the emma and could be any type - * of 16 Bit Pixelformat. - */ - { - .in_fmt = 0, - .out_fmt = 0, - .cfg = { - .channel = 1, - .in_fmt = PRP_CNTL_DATA_IN_RGB16, - .out_fmt = PRP_CNTL_CH1_OUT_RGB16, - .src_pixel = 0x2ca00565, /* RGB565 */ - .ch1_pixel = 0x2ca00565, /* RGB565 */ - .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | - PRP_INTR_CH1FC | PRP_INTR_LBOVF, - .csicr1 = 0, - } - }, - { - .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8, - .out_fmt = V4L2_PIX_FMT_YUYV, - .cfg = { - .channel = 1, - .in_fmt = PRP_CNTL_DATA_IN_YUV422, - .out_fmt = PRP_CNTL_CH1_OUT_YUV422, - .src_pixel = 0x22000888, /* YUV422 (YUYV) */ - .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ - .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | - PRP_INTR_CH1FC | PRP_INTR_LBOVF, - .csicr1 = CSICR1_SWAP16_EN, - } - }, - { - .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8, - .out_fmt = V4L2_PIX_FMT_YUYV, - .cfg = { - .channel = 1, - .in_fmt = PRP_CNTL_DATA_IN_YUV422, - .out_fmt = PRP_CNTL_CH1_OUT_YUV422, - .src_pixel = 0x22000888, /* YUV422 (YUYV) */ - .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ - .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | - PRP_INTR_CH1FC | PRP_INTR_LBOVF, - .csicr1 = CSICR1_PACK_DIR, - } - }, - { - .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8, - .out_fmt = V4L2_PIX_FMT_YUV420, - .cfg = { - .channel = 2, - .in_fmt = PRP_CNTL_DATA_IN_YUV422, - .out_fmt = PRP_CNTL_CH2_OUT_YUV420, - .src_pixel = 0x22000888, /* YUV422 (YUYV) */ - .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | - PRP_INTR_CH2FC | PRP_INTR_LBOVF | - PRP_INTR_CH2OVF, - .csicr1 = CSICR1_PACK_DIR, - } - }, - { - .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8, - .out_fmt = V4L2_PIX_FMT_YUV420, - .cfg = { - .channel = 2, - .in_fmt = PRP_CNTL_DATA_IN_YUV422, - .out_fmt = PRP_CNTL_CH2_OUT_YUV420, - .src_pixel = 0x22000888, /* YUV422 (YUYV) */ - .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | - PRP_INTR_CH2FC | PRP_INTR_LBOVF | - PRP_INTR_CH2OVF, - .csicr1 = CSICR1_SWAP16_EN, - } - }, -}; - -static struct mx2_fmt_cfg *mx27_emma_prp_get_format(u32 in_fmt, u32 out_fmt) -{ - int i; - - for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++) - if ((mx27_emma_prp_table[i].in_fmt == in_fmt) && - (mx27_emma_prp_table[i].out_fmt == out_fmt)) { - return &mx27_emma_prp_table[i]; - } - /* If no match return the most generic configuration */ - return &mx27_emma_prp_table[0]; -}; - -static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, - unsigned long phys, int bufnum) -{ - struct mx2_fmt_cfg *prp = pcdev->emma_prp; - - if (prp->cfg.channel == 1) { - writel(phys, pcdev->base_emma + - PRP_DEST_RGB1_PTR + 4 * bufnum); - } else { - writel(phys, pcdev->base_emma + - PRP_DEST_Y_PTR - 0x14 * bufnum); - if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { - u32 imgsize = pcdev->soc_host.icd->user_height * - pcdev->soc_host.icd->user_width; - - writel(phys + imgsize, pcdev->base_emma + - PRP_DEST_CB_PTR - 0x14 * bufnum); - writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + - PRP_DEST_CR_PTR - 0x14 * bufnum); - } - } -} - -static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) -{ - clk_disable_unprepare(pcdev->clk_csi_ahb); - clk_disable_unprepare(pcdev->clk_csi_per); - writel(0, pcdev->base_csi + CSICR1); - writel(0, pcdev->base_emma + PRP_CNTL); -} - -static int mx2_camera_add_device(struct soc_camera_device *icd) -{ - dev_info(icd->parent, "Camera driver attached to camera %d\n", - icd->devnum); - - return 0; -} - -static void mx2_camera_remove_device(struct soc_camera_device *icd) -{ - dev_info(icd->parent, "Camera driver detached from camera %d\n", - icd->devnum); -} - -/* - * The following two functions absolutely depend on the fact, that - * there can be only one camera on mx2 camera sensor interface - */ -static int mx2_camera_clock_start(struct soc_camera_host *ici) -{ - struct mx2_camera_dev *pcdev = ici->priv; - int ret; - u32 csicr1; - - ret = clk_prepare_enable(pcdev->clk_csi_ahb); - if (ret < 0) - return ret; - - ret = clk_prepare_enable(pcdev->clk_csi_per); - if (ret < 0) - goto exit_csi_ahb; - - csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC | - CSICR1_RXFF_LEVEL(0); - - pcdev->csicr1 = csicr1; - writel(pcdev->csicr1, pcdev->base_csi + CSICR1); - - pcdev->frame_count = 0; - - return 0; - -exit_csi_ahb: - clk_disable_unprepare(pcdev->clk_csi_ahb); - - return ret; -} - -static void mx2_camera_clock_stop(struct soc_camera_host *ici) -{ - struct mx2_camera_dev *pcdev = ici->priv; - - mx2_camera_deactivate(pcdev); -} - -/* - * Videobuf operations - */ -static int mx2_videobuf_setup(struct vb2_queue *vq, - unsigned int *count, unsigned int *num_planes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(vq); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - - dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); - - alloc_ctxs[0] = pcdev->alloc_ctx; - - sizes[0] = icd->sizeimage; - - if (0 == *count) - *count = 32; - if (!*num_planes && - sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) - *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; - - *num_planes = 1; - - return 0; -} - -static int mx2_videobuf_prepare(struct vb2_buffer *vb) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - int ret = 0; - - dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, - vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); - -#ifdef DEBUG - /* - * This can be useful if you want to see if we actually fill - * the buffer with something - */ - memset((void *)vb2_plane_vaddr(vb, 0), - 0xaa, vb2_get_plane_payload(vb, 0)); -#endif - - vb2_set_plane_payload(vb, 0, icd->sizeimage); - if (vb2_plane_vaddr(vb, 0) && - vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { - ret = -EINVAL; - goto out; - } - - return 0; - -out: - return ret; -} - -static void mx2_videobuf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct soc_camera_host *ici = - to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_buffer *buf = container_of(vbuf, struct mx2_buffer, vb); - unsigned long flags; - - dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, - vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); - - spin_lock_irqsave(&pcdev->lock, flags); - - list_add_tail(&buf->internal.queue, &pcdev->capture); - - spin_unlock_irqrestore(&pcdev->lock, flags); -} - -static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, - int bytesperline) -{ - struct soc_camera_host *ici = - to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_fmt_cfg *prp = pcdev->emma_prp; - - writel((pcdev->s_width << 16) | pcdev->s_height, - pcdev->base_emma + PRP_SRC_FRAME_SIZE); - writel(prp->cfg.src_pixel, - pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); - if (prp->cfg.channel == 1) { - writel((icd->user_width << 16) | icd->user_height, - pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); - writel(bytesperline, - pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); - writel(prp->cfg.ch1_pixel, - pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); - } else { /* channel 2 */ - writel((icd->user_width << 16) | icd->user_height, - pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); - } - - /* Enable interrupts */ - writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); -} - -static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) -{ - int dir; - - for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { - unsigned char *s = pcdev->resizing[dir].s; - int len = pcdev->resizing[dir].len; - unsigned int coeff[2] = {0, 0}; - unsigned int valid = 0; - int i; - - if (len == 0) - continue; - - for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { - int j; - - j = i > 9 ? 1 : 0; - coeff[j] = (coeff[j] << BC_COEF) | - (s[i] & (SZ_COEF - 1)); - - if (i == 5 || i == 15) - coeff[j] <<= 1; - - valid = (valid << 1) | (s[i] >> BC_COEF); - } - - valid |= PRP_RZ_VALID_TBL_LEN(len); - - if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) - valid |= PRP_RZ_VALID_BILINEAR; - - if (pcdev->emma_prp->cfg.channel == 1) { - if (dir == RESIZE_DIR_H) { - writel(coeff[0], pcdev->base_emma + - PRP_CH1_RZ_HORI_COEF1); - writel(coeff[1], pcdev->base_emma + - PRP_CH1_RZ_HORI_COEF2); - writel(valid, pcdev->base_emma + - PRP_CH1_RZ_HORI_VALID); - } else { - writel(coeff[0], pcdev->base_emma + - PRP_CH1_RZ_VERT_COEF1); - writel(coeff[1], pcdev->base_emma + - PRP_CH1_RZ_VERT_COEF2); - writel(valid, pcdev->base_emma + - PRP_CH1_RZ_VERT_VALID); - } - } else { - if (dir == RESIZE_DIR_H) { - writel(coeff[0], pcdev->base_emma + - PRP_CH2_RZ_HORI_COEF1); - writel(coeff[1], pcdev->base_emma + - PRP_CH2_RZ_HORI_COEF2); - writel(valid, pcdev->base_emma + - PRP_CH2_RZ_HORI_VALID); - } else { - writel(coeff[0], pcdev->base_emma + - PRP_CH2_RZ_VERT_COEF1); - writel(coeff[1], pcdev->base_emma + - PRP_CH2_RZ_VERT_COEF2); - writel(valid, pcdev->base_emma + - PRP_CH2_RZ_VERT_VALID); - } - } - } -} - -static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(q); - struct soc_camera_host *ici = - to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_fmt_cfg *prp = pcdev->emma_prp; - struct vb2_buffer *vb; - struct mx2_buffer *buf; - unsigned long phys; - int bytesperline; - unsigned long flags; - - if (count < 2) - return -ENOBUFS; - - spin_lock_irqsave(&pcdev->lock, flags); - - buf = list_first_entry(&pcdev->capture, struct mx2_buffer, - internal.queue); - buf->internal.bufnum = 0; - vb = &buf->vb.vb2_buf; - - phys = vb2_dma_contig_plane_dma_addr(vb, 0); - mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); - list_move_tail(pcdev->capture.next, &pcdev->active_bufs); - - buf = list_first_entry(&pcdev->capture, struct mx2_buffer, - internal.queue); - buf->internal.bufnum = 1; - vb = &buf->vb.vb2_buf; - - phys = vb2_dma_contig_plane_dma_addr(vb, 0); - mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); - list_move_tail(pcdev->capture.next, &pcdev->active_bufs); - - bytesperline = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - if (bytesperline < 0) { - spin_unlock_irqrestore(&pcdev->lock, flags); - return bytesperline; - } - - /* - * I didn't manage to properly enable/disable the prp - * on a per frame basis during running transfers, - * thus we allocate a buffer here and use it to - * discard frames when no buffer is available. - * Feel free to work on this ;) - */ - pcdev->discard_size = icd->user_height * bytesperline; - pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, - pcdev->discard_size, - &pcdev->discard_buffer_dma, GFP_ATOMIC); - if (!pcdev->discard_buffer) { - spin_unlock_irqrestore(&pcdev->lock, flags); - return -ENOMEM; - } - - pcdev->buf_discard[0].discard = true; - list_add_tail(&pcdev->buf_discard[0].queue, - &pcdev->discard); - - pcdev->buf_discard[1].discard = true; - list_add_tail(&pcdev->buf_discard[1].queue, - &pcdev->discard); - - mx2_prp_resize_commit(pcdev); - - mx27_camera_emma_buf_init(icd, bytesperline); - - if (prp->cfg.channel == 1) { - writel(PRP_CNTL_CH1EN | - PRP_CNTL_CSIEN | - prp->cfg.in_fmt | - prp->cfg.out_fmt | - PRP_CNTL_CH1_LEN | - PRP_CNTL_CH1BYP | - PRP_CNTL_CH1_TSKIP(0) | - PRP_CNTL_IN_TSKIP(0), - pcdev->base_emma + PRP_CNTL); - } else { - writel(PRP_CNTL_CH2EN | - PRP_CNTL_CSIEN | - prp->cfg.in_fmt | - prp->cfg.out_fmt | - PRP_CNTL_CH2_LEN | - PRP_CNTL_CH2_TSKIP(0) | - PRP_CNTL_IN_TSKIP(0), - pcdev->base_emma + PRP_CNTL); - } - spin_unlock_irqrestore(&pcdev->lock, flags); - - return 0; -} - -static void mx2_stop_streaming(struct vb2_queue *q) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(q); - struct soc_camera_host *ici = - to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_fmt_cfg *prp = pcdev->emma_prp; - unsigned long flags; - void *b; - u32 cntl; - - spin_lock_irqsave(&pcdev->lock, flags); - - cntl = readl(pcdev->base_emma + PRP_CNTL); - if (prp->cfg.channel == 1) { - writel(cntl & ~PRP_CNTL_CH1EN, - pcdev->base_emma + PRP_CNTL); - } else { - writel(cntl & ~PRP_CNTL_CH2EN, - pcdev->base_emma + PRP_CNTL); - } - INIT_LIST_HEAD(&pcdev->capture); - INIT_LIST_HEAD(&pcdev->active_bufs); - INIT_LIST_HEAD(&pcdev->discard); - - b = pcdev->discard_buffer; - pcdev->discard_buffer = NULL; - - spin_unlock_irqrestore(&pcdev->lock, flags); - - dma_free_coherent(ici->v4l2_dev.dev, - pcdev->discard_size, b, pcdev->discard_buffer_dma); -} - -static struct vb2_ops mx2_videobuf_ops = { - .queue_setup = mx2_videobuf_setup, - .buf_prepare = mx2_videobuf_prepare, - .buf_queue = mx2_videobuf_queue, - .start_streaming = mx2_start_streaming, - .stop_streaming = mx2_stop_streaming, -}; - -static int mx2_camera_init_videobuf(struct vb2_queue *q, - struct soc_camera_device *icd) -{ - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->drv_priv = icd; - q->ops = &mx2_videobuf_ops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct mx2_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - - return vb2_queue_init(q); -} - -#define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ - V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ - V4L2_MBUS_VSYNC_ACTIVE_LOW | \ - V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ - V4L2_MBUS_HSYNC_ACTIVE_LOW | \ - V4L2_MBUS_PCLK_SAMPLE_RISING | \ - V4L2_MBUS_PCLK_SAMPLE_FALLING | \ - V4L2_MBUS_DATA_ACTIVE_HIGH | \ - V4L2_MBUS_DATA_ACTIVE_LOW) - -static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) -{ - int count = 0; - - readl(pcdev->base_emma + PRP_CNTL); - writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); - while (count++ < 100) { - if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) - return 0; - barrier(); - udelay(1); - } - - return -ETIMEDOUT; -} - -static int mx2_camera_set_bus_param(struct soc_camera_device *icd) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; - unsigned long common_flags; - int ret; - int bytesperline; - u32 csicr1 = pcdev->csicr1; - - ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); - if (!ret) { - common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS); - if (!common_flags) { - dev_warn(icd->parent, - "Flags incompatible: camera 0x%x, host 0x%x\n", - cfg.flags, MX2_BUS_FLAGS); - return -EINVAL; - } - } else if (ret != -ENOIOCTLCMD) { - return ret; - } else { - common_flags = MX2_BUS_FLAGS; - } - - if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && - (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { - if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH) - common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; - else - common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; - } - - if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && - (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { - if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING) - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; - else - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; - } - - cfg.flags = common_flags; - ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); - if (ret < 0 && ret != -ENOIOCTLCMD) { - dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", - common_flags, ret); - return ret; - } - - csicr1 = (csicr1 & ~CSICR1_FMT_MASK) | pcdev->emma_prp->cfg.csicr1; - - if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) - csicr1 |= CSICR1_REDGE; - if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) - csicr1 |= CSICR1_SOF_POL; - if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) - csicr1 |= CSICR1_HSYNC_POL; - if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) - csicr1 |= CSICR1_EXT_VSYNC; - if (pcdev->platform_flags & MX2_CAMERA_CCIR) - csicr1 |= CSICR1_CCIR_EN; - if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE) - csicr1 |= CSICR1_CCIR_MODE; - if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK) - csicr1 |= CSICR1_GCLK_MODE; - if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) - csicr1 |= CSICR1_INV_DATA; - - pcdev->csicr1 = csicr1; - - bytesperline = soc_mbus_bytes_per_line(icd->user_width, - icd->current_fmt->host_fmt); - if (bytesperline < 0) - return bytesperline; - - ret = mx27_camera_emma_prp_reset(pcdev); - if (ret) - return ret; - - writel(pcdev->csicr1, pcdev->base_csi + CSICR1); - - return 0; -} - -static int mx2_camera_set_crop(struct soc_camera_device *icd, - const struct v4l2_crop *a) -{ - struct v4l2_crop a_writable = *a; - struct v4l2_rect *rect = &a_writable.c; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct v4l2_subdev_format fmt = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_mbus_framefmt *mf = &fmt.format; - int ret; - - soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); - soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); - - ret = v4l2_subdev_call(sd, video, s_crop, a); - if (ret < 0) - return ret; - - /* The capture device might have changed its output */ - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); - if (ret < 0) - return ret; - - dev_dbg(icd->parent, "Sensor cropped %dx%d\n", - mf->width, mf->height); - - icd->user_width = mf->width; - icd->user_height = mf->height; - - return ret; -} - -static int mx2_camera_get_formats(struct soc_camera_device *icd, - unsigned int idx, - struct soc_camera_format_xlate *xlate) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_mbus_pixelfmt *fmt; - struct device *dev = icd->parent; - struct v4l2_subdev_mbus_code_enum code = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - .index = idx, - }; - int ret, formats = 0; - - ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); - if (ret < 0) - /* no more formats */ - return 0; - - fmt = soc_mbus_get_fmtdesc(code.code); - if (!fmt) { - dev_err(dev, "Invalid format code #%u: %d\n", idx, code.code); - return 0; - } - - if (code.code == MEDIA_BUS_FMT_YUYV8_2X8 || - code.code == MEDIA_BUS_FMT_UYVY8_2X8) { - formats++; - if (xlate) { - /* - * CH2 can output YUV420 which is a standard format in - * soc_mediabus.c - */ - xlate->host_fmt = - soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_1_5X8); - xlate->code = code.code; - dev_dbg(dev, "Providing host format %s for sensor code %d\n", - xlate->host_fmt->name, code.code); - xlate++; - } - } - - if (code.code == MEDIA_BUS_FMT_UYVY8_2X8) { - formats++; - if (xlate) { - xlate->host_fmt = - soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_2X8); - xlate->code = code.code; - dev_dbg(dev, "Providing host format %s for sensor code %d\n", - xlate->host_fmt->name, code.code); - xlate++; - } - } - - /* Generic pass-trough */ - formats++; - if (xlate) { - xlate->host_fmt = fmt; - xlate->code = code.code; - xlate++; - } - return formats; -} - -static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, - struct v4l2_mbus_framefmt *mf_in, - struct v4l2_pix_format *pix_out, bool apply) -{ - unsigned int num, den; - unsigned long m; - int i, dir; - - for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { - struct emma_prp_resize tmprsz; - unsigned char *s = tmprsz.s; - int len = 0; - int in, out; - - if (dir == RESIZE_DIR_H) { - in = mf_in->width; - out = pix_out->width; - } else { - in = mf_in->height; - out = pix_out->height; - } - - if (in < out) - return -EINVAL; - else if (in == out) - continue; - - /* Calculate ratio */ - m = gcd(in, out); - num = in / m; - den = out / m; - if (num > RESIZE_NUM_MAX) - return -EINVAL; - - if ((num >= 2 * den) && (den == 1) && - (num < 9) && (!(num & 0x01))) { - int sum = 0; - int j; - - /* Average scaling for >= 2:1 ratios */ - /* Support can be added for num >=9 and odd values */ - - tmprsz.algo = RESIZE_ALGO_AVERAGING; - len = num; - - for (i = 0; i < (len / 2); i++) - s[i] = 8; - - do { - for (i = 0; i < (len / 2); i++) { - s[i] = s[i] >> 1; - sum = 0; - for (j = 0; j < (len / 2); j++) - sum += s[j]; - if (sum == 4) - break; - } - } while (sum != 4); - - for (i = (len / 2); i < len; i++) - s[i] = s[len - i - 1]; - - s[len - 1] |= SZ_COEF; - } else { - /* bilinear scaling for < 2:1 ratios */ - int v; /* overflow counter */ - int coeff, nxt; /* table output */ - int in_pos_inc = 2 * den; - int out_pos = num; - int out_pos_inc = 2 * num; - int init_carry = num - den; - int carry = init_carry; - - tmprsz.algo = RESIZE_ALGO_BILINEAR; - v = den + in_pos_inc; - do { - coeff = v - out_pos; - out_pos += out_pos_inc; - carry += out_pos_inc; - for (nxt = 0; v < out_pos; nxt++) { - v += in_pos_inc; - carry -= in_pos_inc; - } - - if (len > RESIZE_NUM_MAX) - return -EINVAL; - - coeff = ((coeff << BC_COEF) + - (in_pos_inc >> 1)) / in_pos_inc; - - if (coeff >= (SZ_COEF - 1)) - coeff--; - - coeff |= SZ_COEF; - s[len] = (unsigned char)coeff; - len++; - - for (i = 1; i < nxt; i++) { - if (len >= RESIZE_NUM_MAX) - return -EINVAL; - s[len] = 0; - len++; - } - } while (carry != init_carry); - } - tmprsz.len = len; - if (dir == RESIZE_DIR_H) - mf_in->width = pix_out->width; - else - mf_in->height = pix_out->height; - - if (apply) - memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); - } - return 0; -} - -static int mx2_camera_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_format_xlate *xlate; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_mbus_framefmt *mf = &format.format; - int ret; - - dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", - __func__, pix->width, pix->height); - - xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); - if (!xlate) { - dev_warn(icd->parent, "Format %x not found\n", - pix->pixelformat); - return -EINVAL; - } - - mf->width = pix->width; - mf->height = pix->height; - mf->field = pix->field; - mf->colorspace = pix->colorspace; - mf->code = xlate->code; - - ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format); - if (ret < 0 && ret != -ENOIOCTLCMD) - return ret; - - /* Store width and height returned by the sensor for resizing */ - pcdev->s_width = mf->width; - pcdev->s_height = mf->height; - dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", - __func__, pcdev->s_width, pcdev->s_height); - - pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, - xlate->host_fmt->fourcc); - - memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); - if ((mf->width != pix->width || mf->height != pix->height) && - pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { - if (mx2_emmaprp_resize(pcdev, mf, pix, true) < 0) - dev_dbg(icd->parent, "%s: can't resize\n", __func__); - } - - if (mf->code != xlate->code) - return -EINVAL; - - pix->width = mf->width; - pix->height = mf->height; - pix->field = mf->field; - pix->colorspace = mf->colorspace; - icd->current_fmt = xlate; - - dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", - __func__, pix->width, pix->height); - - return 0; -} - -static int mx2_camera_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_format_xlate *xlate; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev_pad_config pad_cfg; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_TRY, - }; - struct v4l2_mbus_framefmt *mf = &format.format; - __u32 pixfmt = pix->pixelformat; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx2_camera_dev *pcdev = ici->priv; - struct mx2_fmt_cfg *emma_prp; - int ret; - - dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", - __func__, pix->width, pix->height); - - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (pixfmt && !xlate) { - dev_warn(icd->parent, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - /* - * limit to MX27 hardware capabilities: width must be a multiple of 8 as - * requested by the CSI. (Table 39-2 in the i.MX27 Reference Manual). - */ - pix->width &= ~0x7; - - /* limit to sensor capabilities */ - mf->width = pix->width; - mf->height = pix->height; - mf->field = pix->field; - mf->colorspace = pix->colorspace; - mf->code = xlate->code; - - ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); - if (ret < 0) - return ret; - - dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", - __func__, pcdev->s_width, pcdev->s_height); - - /* If the sensor does not support image size try PrP resizing */ - emma_prp = mx27_emma_prp_get_format(xlate->code, - xlate->host_fmt->fourcc); - - if ((mf->width != pix->width || mf->height != pix->height) && - emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { - if (mx2_emmaprp_resize(pcdev, mf, pix, false) < 0) - dev_dbg(icd->parent, "%s: can't resize\n", __func__); - } - - if (mf->field == V4L2_FIELD_ANY) - mf->field = V4L2_FIELD_NONE; - /* - * Driver supports interlaced images provided they have - * both fields so that they can be processed as if they - * were progressive. - */ - if (mf->field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf->field)) { - dev_err(icd->parent, "Field type %d unsupported.\n", - mf->field); - return -EINVAL; - } - - pix->width = mf->width; - pix->height = mf->height; - pix->field = mf->field; - pix->colorspace = mf->colorspace; - - dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", - __func__, pix->width, pix->height); - - return 0; -} - -static int mx2_camera_querycap(struct soc_camera_host *ici, - struct v4l2_capability *cap) -{ - /* cap->name is set by the friendly caller:-> */ - strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - - return 0; -} - -static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) -{ - struct soc_camera_device *icd = file->private_data; - - return vb2_poll(&icd->vb2_vidq, file, pt); -} - -static struct soc_camera_host_ops mx2_soc_camera_host_ops = { - .owner = THIS_MODULE, - .add = mx2_camera_add_device, - .remove = mx2_camera_remove_device, - .clock_start = mx2_camera_clock_start, - .clock_stop = mx2_camera_clock_stop, - .set_fmt = mx2_camera_set_fmt, - .set_crop = mx2_camera_set_crop, - .get_formats = mx2_camera_get_formats, - .try_fmt = mx2_camera_try_fmt, - .init_videobuf2 = mx2_camera_init_videobuf, - .poll = mx2_camera_poll, - .querycap = mx2_camera_querycap, - .set_bus_param = mx2_camera_set_bus_param, -}; - -static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, - int bufnum, bool err) -{ -#ifdef DEBUG - struct mx2_fmt_cfg *prp = pcdev->emma_prp; -#endif - struct mx2_buf_internal *ibuf; - struct mx2_buffer *buf; - struct vb2_buffer *vb; - struct vb2_v4l2_buffer *vbuf; - unsigned long phys; - - ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, - queue); - - BUG_ON(ibuf->bufnum != bufnum); - - if (ibuf->discard) { - /* - * Discard buffer must not be returned to user space. - * Just return it to the discard queue. - */ - list_move_tail(pcdev->active_bufs.next, &pcdev->discard); - } else { - buf = mx2_ibuf_to_buf(ibuf); - - vb = &buf->vb.vb2_buf; - vbuf = to_vb2_v4l2_buffer(vb); -#ifdef DEBUG - phys = vb2_dma_contig_plane_dma_addr(vb, 0); - if (prp->cfg.channel == 1) { - if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + - 4 * bufnum) != phys) { - dev_err(pcdev->dev, "%lx != %x\n", phys, - readl(pcdev->base_emma + - PRP_DEST_RGB1_PTR + 4 * bufnum)); - } - } else { - if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - - 0x14 * bufnum) != phys) { - dev_err(pcdev->dev, "%lx != %x\n", phys, - readl(pcdev->base_emma + - PRP_DEST_Y_PTR - 0x14 * bufnum)); - } - } -#endif - dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, - vb2_plane_vaddr(vb, 0), - vb2_get_plane_payload(vb, 0)); - - list_del_init(&buf->internal.queue); - vb->timestamp = ktime_get_ns(); - vbuf->sequence = pcdev->frame_count; - if (err) - vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); - else - vb2_buffer_done(vb, VB2_BUF_STATE_DONE); - } - - pcdev->frame_count++; - - if (list_empty(&pcdev->capture)) { - if (list_empty(&pcdev->discard)) { - dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", - __func__); - return; - } - - ibuf = list_first_entry(&pcdev->discard, - struct mx2_buf_internal, queue); - ibuf->bufnum = bufnum; - - list_move_tail(pcdev->discard.next, &pcdev->active_bufs); - mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); - return; - } - - buf = list_first_entry(&pcdev->capture, struct mx2_buffer, - internal.queue); - - buf->internal.bufnum = bufnum; - - list_move_tail(pcdev->capture.next, &pcdev->active_bufs); - - vb = &buf->vb.vb2_buf; - - phys = vb2_dma_contig_plane_dma_addr(vb, 0); - mx27_update_emma_buf(pcdev, phys, bufnum); -} - -static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) -{ - struct mx2_camera_dev *pcdev = data; - unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); - struct mx2_buf_internal *ibuf; - - spin_lock(&pcdev->lock); - - if (list_empty(&pcdev->active_bufs)) { - dev_warn(pcdev->dev, "%s: called while active list is empty\n", - __func__); - - if (!status) { - spin_unlock(&pcdev->lock); - return IRQ_NONE; - } - } - - if (status & (1 << 7)) { /* overflow */ - u32 cntl = readl(pcdev->base_emma + PRP_CNTL); - writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), - pcdev->base_emma + PRP_CNTL); - writel(cntl, pcdev->base_emma + PRP_CNTL); - - ibuf = list_first_entry(&pcdev->active_bufs, - struct mx2_buf_internal, queue); - mx27_camera_frame_done_emma(pcdev, - ibuf->bufnum, true); - - status &= ~(1 << 7); - } else if (((status & (3 << 5)) == (3 << 5)) || - ((status & (3 << 3)) == (3 << 3))) { - /* - * Both buffers have triggered, process the one we're expecting - * to first - */ - ibuf = list_first_entry(&pcdev->active_bufs, - struct mx2_buf_internal, queue); - mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); - status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ - } else if ((status & (1 << 6)) || (status & (1 << 4))) { - mx27_camera_frame_done_emma(pcdev, 0, false); - } else if ((status & (1 << 5)) || (status & (1 << 3))) { - mx27_camera_frame_done_emma(pcdev, 1, false); - } - - spin_unlock(&pcdev->lock); - writel(status, pcdev->base_emma + PRP_INTRSTATUS); - - return IRQ_HANDLED; -} - -static int mx27_camera_emma_init(struct platform_device *pdev) -{ - struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev); - struct resource *res_emma; - int irq_emma; - int err = 0; - - res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq_emma = platform_get_irq(pdev, 1); - if (!res_emma || !irq_emma) { - dev_err(pcdev->dev, "no EMMA resources\n"); - err = -ENODEV; - goto out; - } - - pcdev->base_emma = devm_ioremap_resource(pcdev->dev, res_emma); - if (IS_ERR(pcdev->base_emma)) { - err = PTR_ERR(pcdev->base_emma); - goto out; - } - - err = devm_request_irq(pcdev->dev, irq_emma, mx27_camera_emma_irq, 0, - MX2_CAM_DRV_NAME, pcdev); - if (err) { - dev_err(pcdev->dev, "Camera EMMA interrupt register failed\n"); - goto out; - } - - pcdev->clk_emma_ipg = devm_clk_get(pcdev->dev, "emma-ipg"); - if (IS_ERR(pcdev->clk_emma_ipg)) { - err = PTR_ERR(pcdev->clk_emma_ipg); - goto out; - } - - clk_prepare_enable(pcdev->clk_emma_ipg); - - pcdev->clk_emma_ahb = devm_clk_get(pcdev->dev, "emma-ahb"); - if (IS_ERR(pcdev->clk_emma_ahb)) { - err = PTR_ERR(pcdev->clk_emma_ahb); - goto exit_clk_emma_ipg; - } - - clk_prepare_enable(pcdev->clk_emma_ahb); - - err = mx27_camera_emma_prp_reset(pcdev); - if (err) - goto exit_clk_emma_ahb; - - return err; - -exit_clk_emma_ahb: - clk_disable_unprepare(pcdev->clk_emma_ahb); -exit_clk_emma_ipg: - clk_disable_unprepare(pcdev->clk_emma_ipg); -out: - return err; -} - -static int mx2_camera_probe(struct platform_device *pdev) -{ - struct mx2_camera_dev *pcdev; - struct resource *res_csi; - int irq_csi; - int err = 0; - - dev_dbg(&pdev->dev, "initialising\n"); - - res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq_csi = platform_get_irq(pdev, 0); - if (res_csi == NULL || irq_csi < 0) { - dev_err(&pdev->dev, "Missing platform resources data\n"); - err = -ENODEV; - goto exit; - } - - pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); - if (!pcdev) { - dev_err(&pdev->dev, "Could not allocate pcdev\n"); - err = -ENOMEM; - goto exit; - } - - pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb"); - if (IS_ERR(pcdev->clk_csi_ahb)) { - dev_err(&pdev->dev, "Could not get csi ahb clock\n"); - err = PTR_ERR(pcdev->clk_csi_ahb); - goto exit; - } - - pcdev->clk_csi_per = devm_clk_get(&pdev->dev, "per"); - if (IS_ERR(pcdev->clk_csi_per)) { - dev_err(&pdev->dev, "Could not get csi per clock\n"); - err = PTR_ERR(pcdev->clk_csi_per); - goto exit; - } - - pcdev->pdata = pdev->dev.platform_data; - if (pcdev->pdata) { - long rate; - - pcdev->platform_flags = pcdev->pdata->flags; - - rate = clk_round_rate(pcdev->clk_csi_per, - pcdev->pdata->clk * 2); - if (rate <= 0) { - err = -ENODEV; - goto exit; - } - err = clk_set_rate(pcdev->clk_csi_per, rate); - if (err < 0) - goto exit; - } - - INIT_LIST_HEAD(&pcdev->capture); - INIT_LIST_HEAD(&pcdev->active_bufs); - INIT_LIST_HEAD(&pcdev->discard); - spin_lock_init(&pcdev->lock); - - pcdev->base_csi = devm_ioremap_resource(&pdev->dev, res_csi); - if (IS_ERR(pcdev->base_csi)) { - err = PTR_ERR(pcdev->base_csi); - goto exit; - } - - pcdev->dev = &pdev->dev; - platform_set_drvdata(pdev, pcdev); - - err = mx27_camera_emma_init(pdev); - if (err) - goto exit; - - /* - * We're done with drvdata here. Clear the pointer so that - * v4l2 core can start using drvdata on its purpose. - */ - platform_set_drvdata(pdev, NULL); - - pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, - pcdev->soc_host.ops = &mx2_soc_camera_host_ops, - pcdev->soc_host.priv = pcdev; - pcdev->soc_host.v4l2_dev.dev = &pdev->dev; - pcdev->soc_host.nr = pdev->id; - - pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); - if (IS_ERR(pcdev->alloc_ctx)) { - err = PTR_ERR(pcdev->alloc_ctx); - goto eallocctx; - } - err = soc_camera_host_register(&pcdev->soc_host); - if (err) - goto exit_free_emma; - - dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n", - clk_get_rate(pcdev->clk_csi_per)); - - return 0; - -exit_free_emma: - vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); -eallocctx: - clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_disable_unprepare(pcdev->clk_emma_ahb); -exit: - return err; -} - -static int mx2_camera_remove(struct platform_device *pdev) -{ - struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); - struct mx2_camera_dev *pcdev = container_of(soc_host, - struct mx2_camera_dev, soc_host); - - soc_camera_host_unregister(&pcdev->soc_host); - - vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); - - clk_disable_unprepare(pcdev->clk_emma_ipg); - clk_disable_unprepare(pcdev->clk_emma_ahb); - - dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); - - return 0; -} - -static struct platform_driver mx2_camera_driver = { - .driver = { - .name = MX2_CAM_DRV_NAME, - }, - .id_table = mx2_camera_devtype, - .remove = mx2_camera_remove, -}; - -module_platform_driver_probe(mx2_camera_driver, mx2_camera_probe); - -MODULE_DESCRIPTION("i.MX27 SoC Camera Host driver"); -MODULE_AUTHOR("Sascha Hauer "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(MX2_CAM_VERSION); diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 382d868747b6..11d62b2afae5 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -29,6 +29,8 @@ source "drivers/staging/media/mn88472/Kconfig" source "drivers/staging/media/mn88473/Kconfig" +source "drivers/staging/media/mx2/Kconfig" + source "drivers/staging/media/omap1/Kconfig" source "drivers/staging/media/omap4iss/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index 89d038c1c4d5..d3ff2d054be7 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_I2C_BCM2048) += bcm2048/ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ +obj-$(CONFIG_VIDEO_MX2) += mx2/ obj-$(CONFIG_VIDEO_OMAP1) += omap1/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ diff --git a/drivers/staging/media/mx2/Kconfig b/drivers/staging/media/mx2/Kconfig new file mode 100644 index 000000000000..e080ab9409a5 --- /dev/null +++ b/drivers/staging/media/mx2/Kconfig @@ -0,0 +1,12 @@ +config VIDEO_MX2 + tristate "i.MX27 Camera Sensor Interface driver" + depends on VIDEO_DEV && SOC_CAMERA + depends on SOC_IMX27 || COMPILE_TEST + depends on HAS_DMA + select VIDEOBUF2_DMA_CONTIG + ---help--- + This is a v4l2 driver for the i.MX27 Camera Sensor Interface + + This driver is deprecated and will be removed soon unless someone + will start the work to convert this driver to the vb2 framework + and remove the soc-camera dependency. diff --git a/drivers/staging/media/mx2/Makefile b/drivers/staging/media/mx2/Makefile new file mode 100644 index 000000000000..fc5b2826a558 --- /dev/null +++ b/drivers/staging/media/mx2/Makefile @@ -0,0 +1,3 @@ +# Makefile for i.MX27 Camera Sensor driver + +obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o diff --git a/drivers/staging/media/mx2/mx2_camera.c b/drivers/staging/media/mx2/mx2_camera.c new file mode 100644 index 000000000000..48dd5b7851b5 --- /dev/null +++ b/drivers/staging/media/mx2/mx2_camera.c @@ -0,0 +1,1636 @@ +/* + * V4L2 Driver for i.MX27 camera host + * + * Copyright (C) 2008, Sascha Hauer, Pengutronix + * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography + * Copyright (C) 2012, Javier Martin, Vista Silicon S.L. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#define MX2_CAM_DRV_NAME "mx2-camera" +#define MX2_CAM_VERSION "0.0.6" +#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera" + +/* reset values */ +#define CSICR1_RESET_VAL 0x40000800 +#define CSICR2_RESET_VAL 0x0 +#define CSICR3_RESET_VAL 0x0 + +/* csi control reg 1 */ +#define CSICR1_SWAP16_EN (1 << 31) +#define CSICR1_EXT_VSYNC (1 << 30) +#define CSICR1_EOF_INTEN (1 << 29) +#define CSICR1_PRP_IF_EN (1 << 28) +#define CSICR1_CCIR_MODE (1 << 27) +#define CSICR1_COF_INTEN (1 << 26) +#define CSICR1_SF_OR_INTEN (1 << 25) +#define CSICR1_RF_OR_INTEN (1 << 24) +#define CSICR1_STATFF_LEVEL (3 << 22) +#define CSICR1_STATFF_INTEN (1 << 21) +#define CSICR1_RXFF_LEVEL(l) (((l) & 3) << 19) +#define CSICR1_RXFF_INTEN (1 << 18) +#define CSICR1_SOF_POL (1 << 17) +#define CSICR1_SOF_INTEN (1 << 16) +#define CSICR1_MCLKDIV(d) (((d) & 0xF) << 12) +#define CSICR1_HSYNC_POL (1 << 11) +#define CSICR1_CCIR_EN (1 << 10) +#define CSICR1_MCLKEN (1 << 9) +#define CSICR1_FCC (1 << 8) +#define CSICR1_PACK_DIR (1 << 7) +#define CSICR1_CLR_STATFIFO (1 << 6) +#define CSICR1_CLR_RXFIFO (1 << 5) +#define CSICR1_GCLK_MODE (1 << 4) +#define CSICR1_INV_DATA (1 << 3) +#define CSICR1_INV_PCLK (1 << 2) +#define CSICR1_REDGE (1 << 1) +#define CSICR1_FMT_MASK (CSICR1_PACK_DIR | CSICR1_SWAP16_EN) + +#define SHIFT_STATFF_LEVEL 22 +#define SHIFT_RXFF_LEVEL 19 +#define SHIFT_MCLKDIV 12 + +#define SHIFT_FRMCNT 16 + +#define CSICR1 0x00 +#define CSICR2 0x04 +#define CSISR 0x08 +#define CSISTATFIFO 0x0c +#define CSIRFIFO 0x10 +#define CSIRXCNT 0x14 +#define CSICR3 0x1c +#define CSIDMASA_STATFIFO 0x20 +#define CSIDMATA_STATFIFO 0x24 +#define CSIDMASA_FB1 0x28 +#define CSIDMASA_FB2 0x2c +#define CSIFBUF_PARA 0x30 +#define CSIIMAG_PARA 0x34 + +/* EMMA PrP */ +#define PRP_CNTL 0x00 +#define PRP_INTR_CNTL 0x04 +#define PRP_INTRSTATUS 0x08 +#define PRP_SOURCE_Y_PTR 0x0c +#define PRP_SOURCE_CB_PTR 0x10 +#define PRP_SOURCE_CR_PTR 0x14 +#define PRP_DEST_RGB1_PTR 0x18 +#define PRP_DEST_RGB2_PTR 0x1c +#define PRP_DEST_Y_PTR 0x20 +#define PRP_DEST_CB_PTR 0x24 +#define PRP_DEST_CR_PTR 0x28 +#define PRP_SRC_FRAME_SIZE 0x2c +#define PRP_DEST_CH1_LINE_STRIDE 0x30 +#define PRP_SRC_PIXEL_FORMAT_CNTL 0x34 +#define PRP_CH1_PIXEL_FORMAT_CNTL 0x38 +#define PRP_CH1_OUT_IMAGE_SIZE 0x3c +#define PRP_CH2_OUT_IMAGE_SIZE 0x40 +#define PRP_SRC_LINE_STRIDE 0x44 +#define PRP_CSC_COEF_012 0x48 +#define PRP_CSC_COEF_345 0x4c +#define PRP_CSC_COEF_678 0x50 +#define PRP_CH1_RZ_HORI_COEF1 0x54 +#define PRP_CH1_RZ_HORI_COEF2 0x58 +#define PRP_CH1_RZ_HORI_VALID 0x5c +#define PRP_CH1_RZ_VERT_COEF1 0x60 +#define PRP_CH1_RZ_VERT_COEF2 0x64 +#define PRP_CH1_RZ_VERT_VALID 0x68 +#define PRP_CH2_RZ_HORI_COEF1 0x6c +#define PRP_CH2_RZ_HORI_COEF2 0x70 +#define PRP_CH2_RZ_HORI_VALID 0x74 +#define PRP_CH2_RZ_VERT_COEF1 0x78 +#define PRP_CH2_RZ_VERT_COEF2 0x7c +#define PRP_CH2_RZ_VERT_VALID 0x80 + +#define PRP_CNTL_CH1EN (1 << 0) +#define PRP_CNTL_CH2EN (1 << 1) +#define PRP_CNTL_CSIEN (1 << 2) +#define PRP_CNTL_DATA_IN_YUV420 (0 << 3) +#define PRP_CNTL_DATA_IN_YUV422 (1 << 3) +#define PRP_CNTL_DATA_IN_RGB16 (2 << 3) +#define PRP_CNTL_DATA_IN_RGB32 (3 << 3) +#define PRP_CNTL_CH1_OUT_RGB8 (0 << 5) +#define PRP_CNTL_CH1_OUT_RGB16 (1 << 5) +#define PRP_CNTL_CH1_OUT_RGB32 (2 << 5) +#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5) +#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7) +#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7) +#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7) +#define PRP_CNTL_CH1_LEN (1 << 9) +#define PRP_CNTL_CH2_LEN (1 << 10) +#define PRP_CNTL_SKIP_FRAME (1 << 11) +#define PRP_CNTL_SWRST (1 << 12) +#define PRP_CNTL_CLKEN (1 << 13) +#define PRP_CNTL_WEN (1 << 14) +#define PRP_CNTL_CH1BYP (1 << 15) +#define PRP_CNTL_IN_TSKIP(x) ((x) << 16) +#define PRP_CNTL_CH1_TSKIP(x) ((x) << 19) +#define PRP_CNTL_CH2_TSKIP(x) ((x) << 22) +#define PRP_CNTL_INPUT_FIFO_LEVEL(x) ((x) << 25) +#define PRP_CNTL_RZ_FIFO_LEVEL(x) ((x) << 27) +#define PRP_CNTL_CH2B1EN (1 << 29) +#define PRP_CNTL_CH2B2EN (1 << 30) +#define PRP_CNTL_CH2FEN (1 << 31) + +/* IRQ Enable and status register */ +#define PRP_INTR_RDERR (1 << 0) +#define PRP_INTR_CH1WERR (1 << 1) +#define PRP_INTR_CH2WERR (1 << 2) +#define PRP_INTR_CH1FC (1 << 3) +#define PRP_INTR_CH2FC (1 << 5) +#define PRP_INTR_LBOVF (1 << 7) +#define PRP_INTR_CH2OVF (1 << 8) + +/* Resizing registers */ +#define PRP_RZ_VALID_TBL_LEN(x) ((x) << 24) +#define PRP_RZ_VALID_BILINEAR (1 << 31) + +#define MAX_VIDEO_MEM 16 + +#define RESIZE_NUM_MIN 1 +#define RESIZE_NUM_MAX 20 +#define BC_COEF 3 +#define SZ_COEF (1 << BC_COEF) + +#define RESIZE_DIR_H 0 +#define RESIZE_DIR_V 1 + +#define RESIZE_ALGO_BILINEAR 0 +#define RESIZE_ALGO_AVERAGING 1 + +struct mx2_prp_cfg { + int channel; + u32 in_fmt; + u32 out_fmt; + u32 src_pixel; + u32 ch1_pixel; + u32 irq_flags; + u32 csicr1; +}; + +/* prp resizing parameters */ +struct emma_prp_resize { + int algo; /* type of algorithm used */ + int len; /* number of coefficients */ + unsigned char s[RESIZE_NUM_MAX]; /* table of coefficients */ +}; + +/* prp configuration for a client-host fmt pair */ +struct mx2_fmt_cfg { + u32 in_fmt; + u32 out_fmt; + struct mx2_prp_cfg cfg; +}; + +struct mx2_buf_internal { + struct list_head queue; + int bufnum; + bool discard; +}; + +/* buffer for one video frame */ +struct mx2_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; + struct mx2_buf_internal internal; +}; + +enum mx2_camera_type { + IMX27_CAMERA, +}; + +struct mx2_camera_dev { + struct device *dev; + struct soc_camera_host soc_host; + struct clk *clk_emma_ahb, *clk_emma_ipg; + struct clk *clk_csi_ahb, *clk_csi_per; + + void __iomem *base_csi, *base_emma; + + struct mx2_camera_platform_data *pdata; + unsigned long platform_flags; + + struct list_head capture; + struct list_head active_bufs; + struct list_head discard; + + spinlock_t lock; + + int dma; + struct mx2_buffer *active; + struct mx2_buffer *fb1_active; + struct mx2_buffer *fb2_active; + + u32 csicr1; + enum mx2_camera_type devtype; + + struct mx2_buf_internal buf_discard[2]; + void *discard_buffer; + dma_addr_t discard_buffer_dma; + size_t discard_size; + struct mx2_fmt_cfg *emma_prp; + struct emma_prp_resize resizing[2]; + unsigned int s_width, s_height; + u32 frame_count; + struct vb2_alloc_ctx *alloc_ctx; +}; + +static struct platform_device_id mx2_camera_devtype[] = { + { + .name = "imx27-camera", + .driver_data = IMX27_CAMERA, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, mx2_camera_devtype); + +static struct mx2_buffer *mx2_ibuf_to_buf(struct mx2_buf_internal *int_buf) +{ + return container_of(int_buf, struct mx2_buffer, internal); +} + +static struct mx2_fmt_cfg mx27_emma_prp_table[] = { + /* + * This is a generic configuration which is valid for most + * prp input-output format combinations. + * We set the incoming and outgoing pixelformat to a + * 16 Bit wide format and adjust the bytesperline + * accordingly. With this configuration the inputdata + * will not be changed by the emma and could be any type + * of 16 Bit Pixelformat. + */ + { + .in_fmt = 0, + .out_fmt = 0, + .cfg = { + .channel = 1, + .in_fmt = PRP_CNTL_DATA_IN_RGB16, + .out_fmt = PRP_CNTL_CH1_OUT_RGB16, + .src_pixel = 0x2ca00565, /* RGB565 */ + .ch1_pixel = 0x2ca00565, /* RGB565 */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | + PRP_INTR_CH1FC | PRP_INTR_LBOVF, + .csicr1 = 0, + } + }, + { + .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8, + .out_fmt = V4L2_PIX_FMT_YUYV, + .cfg = { + .channel = 1, + .in_fmt = PRP_CNTL_DATA_IN_YUV422, + .out_fmt = PRP_CNTL_CH1_OUT_YUV422, + .src_pixel = 0x22000888, /* YUV422 (YUYV) */ + .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | + PRP_INTR_CH1FC | PRP_INTR_LBOVF, + .csicr1 = CSICR1_SWAP16_EN, + } + }, + { + .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8, + .out_fmt = V4L2_PIX_FMT_YUYV, + .cfg = { + .channel = 1, + .in_fmt = PRP_CNTL_DATA_IN_YUV422, + .out_fmt = PRP_CNTL_CH1_OUT_YUV422, + .src_pixel = 0x22000888, /* YUV422 (YUYV) */ + .ch1_pixel = 0x62000888, /* YUV422 (YUYV) */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | + PRP_INTR_CH1FC | PRP_INTR_LBOVF, + .csicr1 = CSICR1_PACK_DIR, + } + }, + { + .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8, + .out_fmt = V4L2_PIX_FMT_YUV420, + .cfg = { + .channel = 2, + .in_fmt = PRP_CNTL_DATA_IN_YUV422, + .out_fmt = PRP_CNTL_CH2_OUT_YUV420, + .src_pixel = 0x22000888, /* YUV422 (YUYV) */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | + PRP_INTR_CH2FC | PRP_INTR_LBOVF | + PRP_INTR_CH2OVF, + .csicr1 = CSICR1_PACK_DIR, + } + }, + { + .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8, + .out_fmt = V4L2_PIX_FMT_YUV420, + .cfg = { + .channel = 2, + .in_fmt = PRP_CNTL_DATA_IN_YUV422, + .out_fmt = PRP_CNTL_CH2_OUT_YUV420, + .src_pixel = 0x22000888, /* YUV422 (YUYV) */ + .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | + PRP_INTR_CH2FC | PRP_INTR_LBOVF | + PRP_INTR_CH2OVF, + .csicr1 = CSICR1_SWAP16_EN, + } + }, +}; + +static struct mx2_fmt_cfg *mx27_emma_prp_get_format(u32 in_fmt, u32 out_fmt) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++) + if ((mx27_emma_prp_table[i].in_fmt == in_fmt) && + (mx27_emma_prp_table[i].out_fmt == out_fmt)) { + return &mx27_emma_prp_table[i]; + } + /* If no match return the most generic configuration */ + return &mx27_emma_prp_table[0]; +}; + +static void mx27_update_emma_buf(struct mx2_camera_dev *pcdev, + unsigned long phys, int bufnum) +{ + struct mx2_fmt_cfg *prp = pcdev->emma_prp; + + if (prp->cfg.channel == 1) { + writel(phys, pcdev->base_emma + + PRP_DEST_RGB1_PTR + 4 * bufnum); + } else { + writel(phys, pcdev->base_emma + + PRP_DEST_Y_PTR - 0x14 * bufnum); + if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { + u32 imgsize = pcdev->soc_host.icd->user_height * + pcdev->soc_host.icd->user_width; + + writel(phys + imgsize, pcdev->base_emma + + PRP_DEST_CB_PTR - 0x14 * bufnum); + writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + + PRP_DEST_CR_PTR - 0x14 * bufnum); + } + } +} + +static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) +{ + clk_disable_unprepare(pcdev->clk_csi_ahb); + clk_disable_unprepare(pcdev->clk_csi_per); + writel(0, pcdev->base_csi + CSICR1); + writel(0, pcdev->base_emma + PRP_CNTL); +} + +static int mx2_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx2_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "Camera driver detached from camera %d\n", + icd->devnum); +} + +/* + * The following two functions absolutely depend on the fact, that + * there can be only one camera on mx2 camera sensor interface + */ +static int mx2_camera_clock_start(struct soc_camera_host *ici) +{ + struct mx2_camera_dev *pcdev = ici->priv; + int ret; + u32 csicr1; + + ret = clk_prepare_enable(pcdev->clk_csi_ahb); + if (ret < 0) + return ret; + + ret = clk_prepare_enable(pcdev->clk_csi_per); + if (ret < 0) + goto exit_csi_ahb; + + csicr1 = CSICR1_MCLKEN | CSICR1_PRP_IF_EN | CSICR1_FCC | + CSICR1_RXFF_LEVEL(0); + + pcdev->csicr1 = csicr1; + writel(pcdev->csicr1, pcdev->base_csi + CSICR1); + + pcdev->frame_count = 0; + + return 0; + +exit_csi_ahb: + clk_disable_unprepare(pcdev->clk_csi_ahb); + + return ret; +} + +static void mx2_camera_clock_stop(struct soc_camera_host *ici) +{ + struct mx2_camera_dev *pcdev = ici->priv; + + mx2_camera_deactivate(pcdev); +} + +/* + * Videobuf operations + */ +static int mx2_videobuf_setup(struct vb2_queue *vq, + unsigned int *count, unsigned int *num_planes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct soc_camera_device *icd = soc_camera_from_vb2q(vq); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + + dev_dbg(icd->parent, "count=%d, size=%d\n", *count, sizes[0]); + + alloc_ctxs[0] = pcdev->alloc_ctx; + + sizes[0] = icd->sizeimage; + + if (0 == *count) + *count = 32; + if (!*num_planes && + sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024) + *count = (MAX_VIDEO_MEM * 1024 * 1024) / sizes[0]; + + *num_planes = 1; + + return 0; +} + +static int mx2_videobuf_prepare(struct vb2_buffer *vb) +{ + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + int ret = 0; + + dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, + vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + +#ifdef DEBUG + /* + * This can be useful if you want to see if we actually fill + * the buffer with something + */ + memset((void *)vb2_plane_vaddr(vb, 0), + 0xaa, vb2_get_plane_payload(vb, 0)); +#endif + + vb2_set_plane_payload(vb, 0, icd->sizeimage); + if (vb2_plane_vaddr(vb, 0) && + vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { + ret = -EINVAL; + goto out; + } + + return 0; + +out: + return ret; +} + +static void mx2_videobuf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = + to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_buffer *buf = container_of(vbuf, struct mx2_buffer, vb); + unsigned long flags; + + dev_dbg(icd->parent, "%s (vb=0x%p) 0x%p %lu\n", __func__, + vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0)); + + spin_lock_irqsave(&pcdev->lock, flags); + + list_add_tail(&buf->internal.queue, &pcdev->capture); + + spin_unlock_irqrestore(&pcdev->lock, flags); +} + +static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, + int bytesperline) +{ + struct soc_camera_host *ici = + to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_fmt_cfg *prp = pcdev->emma_prp; + + writel((pcdev->s_width << 16) | pcdev->s_height, + pcdev->base_emma + PRP_SRC_FRAME_SIZE); + writel(prp->cfg.src_pixel, + pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); + if (prp->cfg.channel == 1) { + writel((icd->user_width << 16) | icd->user_height, + pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); + writel(bytesperline, + pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); + writel(prp->cfg.ch1_pixel, + pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); + } else { /* channel 2 */ + writel((icd->user_width << 16) | icd->user_height, + pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); + } + + /* Enable interrupts */ + writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); +} + +static void mx2_prp_resize_commit(struct mx2_camera_dev *pcdev) +{ + int dir; + + for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { + unsigned char *s = pcdev->resizing[dir].s; + int len = pcdev->resizing[dir].len; + unsigned int coeff[2] = {0, 0}; + unsigned int valid = 0; + int i; + + if (len == 0) + continue; + + for (i = RESIZE_NUM_MAX - 1; i >= 0; i--) { + int j; + + j = i > 9 ? 1 : 0; + coeff[j] = (coeff[j] << BC_COEF) | + (s[i] & (SZ_COEF - 1)); + + if (i == 5 || i == 15) + coeff[j] <<= 1; + + valid = (valid << 1) | (s[i] >> BC_COEF); + } + + valid |= PRP_RZ_VALID_TBL_LEN(len); + + if (pcdev->resizing[dir].algo == RESIZE_ALGO_BILINEAR) + valid |= PRP_RZ_VALID_BILINEAR; + + if (pcdev->emma_prp->cfg.channel == 1) { + if (dir == RESIZE_DIR_H) { + writel(coeff[0], pcdev->base_emma + + PRP_CH1_RZ_HORI_COEF1); + writel(coeff[1], pcdev->base_emma + + PRP_CH1_RZ_HORI_COEF2); + writel(valid, pcdev->base_emma + + PRP_CH1_RZ_HORI_VALID); + } else { + writel(coeff[0], pcdev->base_emma + + PRP_CH1_RZ_VERT_COEF1); + writel(coeff[1], pcdev->base_emma + + PRP_CH1_RZ_VERT_COEF2); + writel(valid, pcdev->base_emma + + PRP_CH1_RZ_VERT_VALID); + } + } else { + if (dir == RESIZE_DIR_H) { + writel(coeff[0], pcdev->base_emma + + PRP_CH2_RZ_HORI_COEF1); + writel(coeff[1], pcdev->base_emma + + PRP_CH2_RZ_HORI_COEF2); + writel(valid, pcdev->base_emma + + PRP_CH2_RZ_HORI_VALID); + } else { + writel(coeff[0], pcdev->base_emma + + PRP_CH2_RZ_VERT_COEF1); + writel(coeff[1], pcdev->base_emma + + PRP_CH2_RZ_VERT_COEF2); + writel(valid, pcdev->base_emma + + PRP_CH2_RZ_VERT_VALID); + } + } + } +} + +static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) +{ + struct soc_camera_device *icd = soc_camera_from_vb2q(q); + struct soc_camera_host *ici = + to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_fmt_cfg *prp = pcdev->emma_prp; + struct vb2_buffer *vb; + struct mx2_buffer *buf; + unsigned long phys; + int bytesperline; + unsigned long flags; + + if (count < 2) + return -ENOBUFS; + + spin_lock_irqsave(&pcdev->lock, flags); + + buf = list_first_entry(&pcdev->capture, struct mx2_buffer, + internal.queue); + buf->internal.bufnum = 0; + vb = &buf->vb.vb2_buf; + + phys = vb2_dma_contig_plane_dma_addr(vb, 0); + mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); + list_move_tail(pcdev->capture.next, &pcdev->active_bufs); + + buf = list_first_entry(&pcdev->capture, struct mx2_buffer, + internal.queue); + buf->internal.bufnum = 1; + vb = &buf->vb.vb2_buf; + + phys = vb2_dma_contig_plane_dma_addr(vb, 0); + mx27_update_emma_buf(pcdev, phys, buf->internal.bufnum); + list_move_tail(pcdev->capture.next, &pcdev->active_bufs); + + bytesperline = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + if (bytesperline < 0) { + spin_unlock_irqrestore(&pcdev->lock, flags); + return bytesperline; + } + + /* + * I didn't manage to properly enable/disable the prp + * on a per frame basis during running transfers, + * thus we allocate a buffer here and use it to + * discard frames when no buffer is available. + * Feel free to work on this ;) + */ + pcdev->discard_size = icd->user_height * bytesperline; + pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, + pcdev->discard_size, + &pcdev->discard_buffer_dma, GFP_ATOMIC); + if (!pcdev->discard_buffer) { + spin_unlock_irqrestore(&pcdev->lock, flags); + return -ENOMEM; + } + + pcdev->buf_discard[0].discard = true; + list_add_tail(&pcdev->buf_discard[0].queue, + &pcdev->discard); + + pcdev->buf_discard[1].discard = true; + list_add_tail(&pcdev->buf_discard[1].queue, + &pcdev->discard); + + mx2_prp_resize_commit(pcdev); + + mx27_camera_emma_buf_init(icd, bytesperline); + + if (prp->cfg.channel == 1) { + writel(PRP_CNTL_CH1EN | + PRP_CNTL_CSIEN | + prp->cfg.in_fmt | + prp->cfg.out_fmt | + PRP_CNTL_CH1_LEN | + PRP_CNTL_CH1BYP | + PRP_CNTL_CH1_TSKIP(0) | + PRP_CNTL_IN_TSKIP(0), + pcdev->base_emma + PRP_CNTL); + } else { + writel(PRP_CNTL_CH2EN | + PRP_CNTL_CSIEN | + prp->cfg.in_fmt | + prp->cfg.out_fmt | + PRP_CNTL_CH2_LEN | + PRP_CNTL_CH2_TSKIP(0) | + PRP_CNTL_IN_TSKIP(0), + pcdev->base_emma + PRP_CNTL); + } + spin_unlock_irqrestore(&pcdev->lock, flags); + + return 0; +} + +static void mx2_stop_streaming(struct vb2_queue *q) +{ + struct soc_camera_device *icd = soc_camera_from_vb2q(q); + struct soc_camera_host *ici = + to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_fmt_cfg *prp = pcdev->emma_prp; + unsigned long flags; + void *b; + u32 cntl; + + spin_lock_irqsave(&pcdev->lock, flags); + + cntl = readl(pcdev->base_emma + PRP_CNTL); + if (prp->cfg.channel == 1) { + writel(cntl & ~PRP_CNTL_CH1EN, + pcdev->base_emma + PRP_CNTL); + } else { + writel(cntl & ~PRP_CNTL_CH2EN, + pcdev->base_emma + PRP_CNTL); + } + INIT_LIST_HEAD(&pcdev->capture); + INIT_LIST_HEAD(&pcdev->active_bufs); + INIT_LIST_HEAD(&pcdev->discard); + + b = pcdev->discard_buffer; + pcdev->discard_buffer = NULL; + + spin_unlock_irqrestore(&pcdev->lock, flags); + + dma_free_coherent(ici->v4l2_dev.dev, + pcdev->discard_size, b, pcdev->discard_buffer_dma); +} + +static struct vb2_ops mx2_videobuf_ops = { + .queue_setup = mx2_videobuf_setup, + .buf_prepare = mx2_videobuf_prepare, + .buf_queue = mx2_videobuf_queue, + .start_streaming = mx2_start_streaming, + .stop_streaming = mx2_stop_streaming, +}; + +static int mx2_camera_init_videobuf(struct vb2_queue *q, + struct soc_camera_device *icd) +{ + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = icd; + q->ops = &mx2_videobuf_ops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct mx2_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + + return vb2_queue_init(q); +} + +#define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ + V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ + V4L2_MBUS_VSYNC_ACTIVE_LOW | \ + V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ + V4L2_MBUS_HSYNC_ACTIVE_LOW | \ + V4L2_MBUS_PCLK_SAMPLE_RISING | \ + V4L2_MBUS_PCLK_SAMPLE_FALLING | \ + V4L2_MBUS_DATA_ACTIVE_HIGH | \ + V4L2_MBUS_DATA_ACTIVE_LOW) + +static int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) +{ + int count = 0; + + readl(pcdev->base_emma + PRP_CNTL); + writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); + while (count++ < 100) { + if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) + return 0; + barrier(); + udelay(1); + } + + return -ETIMEDOUT; +} + +static int mx2_camera_set_bus_param(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + unsigned long common_flags; + int ret; + int bytesperline; + u32 csicr1 = pcdev->csicr1; + + ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); + if (!ret) { + common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS); + if (!common_flags) { + dev_warn(icd->parent, + "Flags incompatible: camera 0x%x, host 0x%x\n", + cfg.flags, MX2_BUS_FLAGS); + return -EINVAL; + } + } else if (ret != -ENOIOCTLCMD) { + return ret; + } else { + common_flags = MX2_BUS_FLAGS; + } + + if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && + (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { + if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH) + common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; + else + common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; + } + + if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && + (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { + if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING) + common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; + else + common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; + } + + cfg.flags = common_flags; + ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); + if (ret < 0 && ret != -ENOIOCTLCMD) { + dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", + common_flags, ret); + return ret; + } + + csicr1 = (csicr1 & ~CSICR1_FMT_MASK) | pcdev->emma_prp->cfg.csicr1; + + if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) + csicr1 |= CSICR1_REDGE; + if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) + csicr1 |= CSICR1_SOF_POL; + if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) + csicr1 |= CSICR1_HSYNC_POL; + if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) + csicr1 |= CSICR1_EXT_VSYNC; + if (pcdev->platform_flags & MX2_CAMERA_CCIR) + csicr1 |= CSICR1_CCIR_EN; + if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE) + csicr1 |= CSICR1_CCIR_MODE; + if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK) + csicr1 |= CSICR1_GCLK_MODE; + if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) + csicr1 |= CSICR1_INV_DATA; + + pcdev->csicr1 = csicr1; + + bytesperline = soc_mbus_bytes_per_line(icd->user_width, + icd->current_fmt->host_fmt); + if (bytesperline < 0) + return bytesperline; + + ret = mx27_camera_emma_prp_reset(pcdev); + if (ret) + return ret; + + writel(pcdev->csicr1, pcdev->base_csi + CSICR1); + + return 0; +} + +static int mx2_camera_set_crop(struct soc_camera_device *icd, + const struct v4l2_crop *a) +{ + struct v4l2_crop a_writable = *a; + struct v4l2_rect *rect = &a_writable.c; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *mf = &fmt.format; + int ret; + + soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); + soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); + + ret = v4l2_subdev_call(sd, video, s_crop, a); + if (ret < 0) + return ret; + + /* The capture device might have changed its output */ + ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); + if (ret < 0) + return ret; + + dev_dbg(icd->parent, "Sensor cropped %dx%d\n", + mf->width, mf->height); + + icd->user_width = mf->width; + icd->user_height = mf->height; + + return ret; +} + +static int mx2_camera_get_formats(struct soc_camera_device *icd, + unsigned int idx, + struct soc_camera_format_xlate *xlate) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_mbus_pixelfmt *fmt; + struct device *dev = icd->parent; + struct v4l2_subdev_mbus_code_enum code = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .index = idx, + }; + int ret, formats = 0; + + ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); + if (ret < 0) + /* no more formats */ + return 0; + + fmt = soc_mbus_get_fmtdesc(code.code); + if (!fmt) { + dev_err(dev, "Invalid format code #%u: %d\n", idx, code.code); + return 0; + } + + if (code.code == MEDIA_BUS_FMT_YUYV8_2X8 || + code.code == MEDIA_BUS_FMT_UYVY8_2X8) { + formats++; + if (xlate) { + /* + * CH2 can output YUV420 which is a standard format in + * soc_mediabus.c + */ + xlate->host_fmt = + soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_1_5X8); + xlate->code = code.code; + dev_dbg(dev, "Providing host format %s for sensor code %d\n", + xlate->host_fmt->name, code.code); + xlate++; + } + } + + if (code.code == MEDIA_BUS_FMT_UYVY8_2X8) { + formats++; + if (xlate) { + xlate->host_fmt = + soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_2X8); + xlate->code = code.code; + dev_dbg(dev, "Providing host format %s for sensor code %d\n", + xlate->host_fmt->name, code.code); + xlate++; + } + } + + /* Generic pass-trough */ + formats++; + if (xlate) { + xlate->host_fmt = fmt; + xlate->code = code.code; + xlate++; + } + return formats; +} + +static int mx2_emmaprp_resize(struct mx2_camera_dev *pcdev, + struct v4l2_mbus_framefmt *mf_in, + struct v4l2_pix_format *pix_out, bool apply) +{ + unsigned int num, den; + unsigned long m; + int i, dir; + + for (dir = RESIZE_DIR_H; dir <= RESIZE_DIR_V; dir++) { + struct emma_prp_resize tmprsz; + unsigned char *s = tmprsz.s; + int len = 0; + int in, out; + + if (dir == RESIZE_DIR_H) { + in = mf_in->width; + out = pix_out->width; + } else { + in = mf_in->height; + out = pix_out->height; + } + + if (in < out) + return -EINVAL; + else if (in == out) + continue; + + /* Calculate ratio */ + m = gcd(in, out); + num = in / m; + den = out / m; + if (num > RESIZE_NUM_MAX) + return -EINVAL; + + if ((num >= 2 * den) && (den == 1) && + (num < 9) && (!(num & 0x01))) { + int sum = 0; + int j; + + /* Average scaling for >= 2:1 ratios */ + /* Support can be added for num >=9 and odd values */ + + tmprsz.algo = RESIZE_ALGO_AVERAGING; + len = num; + + for (i = 0; i < (len / 2); i++) + s[i] = 8; + + do { + for (i = 0; i < (len / 2); i++) { + s[i] = s[i] >> 1; + sum = 0; + for (j = 0; j < (len / 2); j++) + sum += s[j]; + if (sum == 4) + break; + } + } while (sum != 4); + + for (i = (len / 2); i < len; i++) + s[i] = s[len - i - 1]; + + s[len - 1] |= SZ_COEF; + } else { + /* bilinear scaling for < 2:1 ratios */ + int v; /* overflow counter */ + int coeff, nxt; /* table output */ + int in_pos_inc = 2 * den; + int out_pos = num; + int out_pos_inc = 2 * num; + int init_carry = num - den; + int carry = init_carry; + + tmprsz.algo = RESIZE_ALGO_BILINEAR; + v = den + in_pos_inc; + do { + coeff = v - out_pos; + out_pos += out_pos_inc; + carry += out_pos_inc; + for (nxt = 0; v < out_pos; nxt++) { + v += in_pos_inc; + carry -= in_pos_inc; + } + + if (len > RESIZE_NUM_MAX) + return -EINVAL; + + coeff = ((coeff << BC_COEF) + + (in_pos_inc >> 1)) / in_pos_inc; + + if (coeff >= (SZ_COEF - 1)) + coeff--; + + coeff |= SZ_COEF; + s[len] = (unsigned char)coeff; + len++; + + for (i = 1; i < nxt; i++) { + if (len >= RESIZE_NUM_MAX) + return -EINVAL; + s[len] = 0; + len++; + } + } while (carry != init_carry); + } + tmprsz.len = len; + if (dir == RESIZE_DIR_H) + mf_in->width = pix_out->width; + else + mf_in->height = pix_out->height; + + if (apply) + memcpy(&pcdev->resizing[dir], &tmprsz, sizeof(tmprsz)); + } + return 0; +} + +static int mx2_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *mf = &format.format; + int ret; + + dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", + __func__, pix->width, pix->height); + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(icd->parent, "Format %x not found\n", + pix->pixelformat); + return -EINVAL; + } + + mf->width = pix->width; + mf->height = pix->height; + mf->field = pix->field; + mf->colorspace = pix->colorspace; + mf->code = xlate->code; + + ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format); + if (ret < 0 && ret != -ENOIOCTLCMD) + return ret; + + /* Store width and height returned by the sensor for resizing */ + pcdev->s_width = mf->width; + pcdev->s_height = mf->height; + dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", + __func__, pcdev->s_width, pcdev->s_height); + + pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, + xlate->host_fmt->fourcc); + + memset(pcdev->resizing, 0, sizeof(pcdev->resizing)); + if ((mf->width != pix->width || mf->height != pix->height) && + pcdev->emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { + if (mx2_emmaprp_resize(pcdev, mf, pix, true) < 0) + dev_dbg(icd->parent, "%s: can't resize\n", __func__); + } + + if (mf->code != xlate->code) + return -EINVAL; + + pix->width = mf->width; + pix->height = mf->height; + pix->field = mf->field; + pix->colorspace = mf->colorspace; + icd->current_fmt = xlate; + + dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", + __func__, pix->width, pix->height); + + return 0; +} + +static int mx2_camera_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_TRY, + }; + struct v4l2_mbus_framefmt *mf = &format.format; + __u32 pixfmt = pix->pixelformat; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx2_camera_dev *pcdev = ici->priv; + struct mx2_fmt_cfg *emma_prp; + int ret; + + dev_dbg(icd->parent, "%s: requested params: width = %d, height = %d\n", + __func__, pix->width, pix->height); + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(icd->parent, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + /* + * limit to MX27 hardware capabilities: width must be a multiple of 8 as + * requested by the CSI. (Table 39-2 in the i.MX27 Reference Manual). + */ + pix->width &= ~0x7; + + /* limit to sensor capabilities */ + mf->width = pix->width; + mf->height = pix->height; + mf->field = pix->field; + mf->colorspace = pix->colorspace; + mf->code = xlate->code; + + ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); + if (ret < 0) + return ret; + + dev_dbg(icd->parent, "%s: sensor params: width = %d, height = %d\n", + __func__, pcdev->s_width, pcdev->s_height); + + /* If the sensor does not support image size try PrP resizing */ + emma_prp = mx27_emma_prp_get_format(xlate->code, + xlate->host_fmt->fourcc); + + if ((mf->width != pix->width || mf->height != pix->height) && + emma_prp->cfg.in_fmt == PRP_CNTL_DATA_IN_YUV422) { + if (mx2_emmaprp_resize(pcdev, mf, pix, false) < 0) + dev_dbg(icd->parent, "%s: can't resize\n", __func__); + } + + if (mf->field == V4L2_FIELD_ANY) + mf->field = V4L2_FIELD_NONE; + /* + * Driver supports interlaced images provided they have + * both fields so that they can be processed as if they + * were progressive. + */ + if (mf->field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf->field)) { + dev_err(icd->parent, "Field type %d unsupported.\n", + mf->field); + return -EINVAL; + } + + pix->width = mf->width; + pix->height = mf->height; + pix->field = mf->field; + pix->colorspace = mf->colorspace; + + dev_dbg(icd->parent, "%s: returned params: width = %d, height = %d\n", + __func__, pix->width, pix->height); + + return 0; +} + +static int mx2_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the friendly caller:-> */ + strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static unsigned int mx2_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_device *icd = file->private_data; + + return vb2_poll(&icd->vb2_vidq, file, pt); +} + +static struct soc_camera_host_ops mx2_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = mx2_camera_add_device, + .remove = mx2_camera_remove_device, + .clock_start = mx2_camera_clock_start, + .clock_stop = mx2_camera_clock_stop, + .set_fmt = mx2_camera_set_fmt, + .set_crop = mx2_camera_set_crop, + .get_formats = mx2_camera_get_formats, + .try_fmt = mx2_camera_try_fmt, + .init_videobuf2 = mx2_camera_init_videobuf, + .poll = mx2_camera_poll, + .querycap = mx2_camera_querycap, + .set_bus_param = mx2_camera_set_bus_param, +}; + +static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, + int bufnum, bool err) +{ +#ifdef DEBUG + struct mx2_fmt_cfg *prp = pcdev->emma_prp; +#endif + struct mx2_buf_internal *ibuf; + struct mx2_buffer *buf; + struct vb2_buffer *vb; + struct vb2_v4l2_buffer *vbuf; + unsigned long phys; + + ibuf = list_first_entry(&pcdev->active_bufs, struct mx2_buf_internal, + queue); + + BUG_ON(ibuf->bufnum != bufnum); + + if (ibuf->discard) { + /* + * Discard buffer must not be returned to user space. + * Just return it to the discard queue. + */ + list_move_tail(pcdev->active_bufs.next, &pcdev->discard); + } else { + buf = mx2_ibuf_to_buf(ibuf); + + vb = &buf->vb.vb2_buf; + vbuf = to_vb2_v4l2_buffer(vb); +#ifdef DEBUG + phys = vb2_dma_contig_plane_dma_addr(vb, 0); + if (prp->cfg.channel == 1) { + if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + + 4 * bufnum) != phys) { + dev_err(pcdev->dev, "%lx != %x\n", phys, + readl(pcdev->base_emma + + PRP_DEST_RGB1_PTR + 4 * bufnum)); + } + } else { + if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - + 0x14 * bufnum) != phys) { + dev_err(pcdev->dev, "%lx != %x\n", phys, + readl(pcdev->base_emma + + PRP_DEST_Y_PTR - 0x14 * bufnum)); + } + } +#endif + dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%p %lu\n", __func__, vb, + vb2_plane_vaddr(vb, 0), + vb2_get_plane_payload(vb, 0)); + + list_del_init(&buf->internal.queue); + vb->timestamp = ktime_get_ns(); + vbuf->sequence = pcdev->frame_count; + if (err) + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); + else + vb2_buffer_done(vb, VB2_BUF_STATE_DONE); + } + + pcdev->frame_count++; + + if (list_empty(&pcdev->capture)) { + if (list_empty(&pcdev->discard)) { + dev_warn(pcdev->dev, "%s: trying to access empty discard list\n", + __func__); + return; + } + + ibuf = list_first_entry(&pcdev->discard, + struct mx2_buf_internal, queue); + ibuf->bufnum = bufnum; + + list_move_tail(pcdev->discard.next, &pcdev->active_bufs); + mx27_update_emma_buf(pcdev, pcdev->discard_buffer_dma, bufnum); + return; + } + + buf = list_first_entry(&pcdev->capture, struct mx2_buffer, + internal.queue); + + buf->internal.bufnum = bufnum; + + list_move_tail(pcdev->capture.next, &pcdev->active_bufs); + + vb = &buf->vb.vb2_buf; + + phys = vb2_dma_contig_plane_dma_addr(vb, 0); + mx27_update_emma_buf(pcdev, phys, bufnum); +} + +static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) +{ + struct mx2_camera_dev *pcdev = data; + unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); + struct mx2_buf_internal *ibuf; + + spin_lock(&pcdev->lock); + + if (list_empty(&pcdev->active_bufs)) { + dev_warn(pcdev->dev, "%s: called while active list is empty\n", + __func__); + + if (!status) { + spin_unlock(&pcdev->lock); + return IRQ_NONE; + } + } + + if (status & (1 << 7)) { /* overflow */ + u32 cntl = readl(pcdev->base_emma + PRP_CNTL); + writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), + pcdev->base_emma + PRP_CNTL); + writel(cntl, pcdev->base_emma + PRP_CNTL); + + ibuf = list_first_entry(&pcdev->active_bufs, + struct mx2_buf_internal, queue); + mx27_camera_frame_done_emma(pcdev, + ibuf->bufnum, true); + + status &= ~(1 << 7); + } else if (((status & (3 << 5)) == (3 << 5)) || + ((status & (3 << 3)) == (3 << 3))) { + /* + * Both buffers have triggered, process the one we're expecting + * to first + */ + ibuf = list_first_entry(&pcdev->active_bufs, + struct mx2_buf_internal, queue); + mx27_camera_frame_done_emma(pcdev, ibuf->bufnum, false); + status &= ~(1 << (6 - ibuf->bufnum)); /* mark processed */ + } else if ((status & (1 << 6)) || (status & (1 << 4))) { + mx27_camera_frame_done_emma(pcdev, 0, false); + } else if ((status & (1 << 5)) || (status & (1 << 3))) { + mx27_camera_frame_done_emma(pcdev, 1, false); + } + + spin_unlock(&pcdev->lock); + writel(status, pcdev->base_emma + PRP_INTRSTATUS); + + return IRQ_HANDLED; +} + +static int mx27_camera_emma_init(struct platform_device *pdev) +{ + struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev); + struct resource *res_emma; + int irq_emma; + int err = 0; + + res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); + irq_emma = platform_get_irq(pdev, 1); + if (!res_emma || !irq_emma) { + dev_err(pcdev->dev, "no EMMA resources\n"); + err = -ENODEV; + goto out; + } + + pcdev->base_emma = devm_ioremap_resource(pcdev->dev, res_emma); + if (IS_ERR(pcdev->base_emma)) { + err = PTR_ERR(pcdev->base_emma); + goto out; + } + + err = devm_request_irq(pcdev->dev, irq_emma, mx27_camera_emma_irq, 0, + MX2_CAM_DRV_NAME, pcdev); + if (err) { + dev_err(pcdev->dev, "Camera EMMA interrupt register failed\n"); + goto out; + } + + pcdev->clk_emma_ipg = devm_clk_get(pcdev->dev, "emma-ipg"); + if (IS_ERR(pcdev->clk_emma_ipg)) { + err = PTR_ERR(pcdev->clk_emma_ipg); + goto out; + } + + clk_prepare_enable(pcdev->clk_emma_ipg); + + pcdev->clk_emma_ahb = devm_clk_get(pcdev->dev, "emma-ahb"); + if (IS_ERR(pcdev->clk_emma_ahb)) { + err = PTR_ERR(pcdev->clk_emma_ahb); + goto exit_clk_emma_ipg; + } + + clk_prepare_enable(pcdev->clk_emma_ahb); + + err = mx27_camera_emma_prp_reset(pcdev); + if (err) + goto exit_clk_emma_ahb; + + return err; + +exit_clk_emma_ahb: + clk_disable_unprepare(pcdev->clk_emma_ahb); +exit_clk_emma_ipg: + clk_disable_unprepare(pcdev->clk_emma_ipg); +out: + return err; +} + +static int mx2_camera_probe(struct platform_device *pdev) +{ + struct mx2_camera_dev *pcdev; + struct resource *res_csi; + int irq_csi; + int err = 0; + + dev_dbg(&pdev->dev, "initialising\n"); + + res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq_csi = platform_get_irq(pdev, 0); + if (res_csi == NULL || irq_csi < 0) { + dev_err(&pdev->dev, "Missing platform resources data\n"); + err = -ENODEV; + goto exit; + } + + pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL); + if (!pcdev) { + dev_err(&pdev->dev, "Could not allocate pcdev\n"); + err = -ENOMEM; + goto exit; + } + + pcdev->clk_csi_ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(pcdev->clk_csi_ahb)) { + dev_err(&pdev->dev, "Could not get csi ahb clock\n"); + err = PTR_ERR(pcdev->clk_csi_ahb); + goto exit; + } + + pcdev->clk_csi_per = devm_clk_get(&pdev->dev, "per"); + if (IS_ERR(pcdev->clk_csi_per)) { + dev_err(&pdev->dev, "Could not get csi per clock\n"); + err = PTR_ERR(pcdev->clk_csi_per); + goto exit; + } + + pcdev->pdata = pdev->dev.platform_data; + if (pcdev->pdata) { + long rate; + + pcdev->platform_flags = pcdev->pdata->flags; + + rate = clk_round_rate(pcdev->clk_csi_per, + pcdev->pdata->clk * 2); + if (rate <= 0) { + err = -ENODEV; + goto exit; + } + err = clk_set_rate(pcdev->clk_csi_per, rate); + if (err < 0) + goto exit; + } + + INIT_LIST_HEAD(&pcdev->capture); + INIT_LIST_HEAD(&pcdev->active_bufs); + INIT_LIST_HEAD(&pcdev->discard); + spin_lock_init(&pcdev->lock); + + pcdev->base_csi = devm_ioremap_resource(&pdev->dev, res_csi); + if (IS_ERR(pcdev->base_csi)) { + err = PTR_ERR(pcdev->base_csi); + goto exit; + } + + pcdev->dev = &pdev->dev; + platform_set_drvdata(pdev, pcdev); + + err = mx27_camera_emma_init(pdev); + if (err) + goto exit; + + /* + * We're done with drvdata here. Clear the pointer so that + * v4l2 core can start using drvdata on its purpose. + */ + platform_set_drvdata(pdev, NULL); + + pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, + pcdev->soc_host.ops = &mx2_soc_camera_host_ops, + pcdev->soc_host.priv = pcdev; + pcdev->soc_host.v4l2_dev.dev = &pdev->dev; + pcdev->soc_host.nr = pdev->id; + + pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(pcdev->alloc_ctx)) { + err = PTR_ERR(pcdev->alloc_ctx); + goto eallocctx; + } + err = soc_camera_host_register(&pcdev->soc_host); + if (err) + goto exit_free_emma; + + dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n", + clk_get_rate(pcdev->clk_csi_per)); + + return 0; + +exit_free_emma: + vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); +eallocctx: + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_disable_unprepare(pcdev->clk_emma_ahb); +exit: + return err; +} + +static int mx2_camera_remove(struct platform_device *pdev) +{ + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct mx2_camera_dev *pcdev = container_of(soc_host, + struct mx2_camera_dev, soc_host); + + soc_camera_host_unregister(&pcdev->soc_host); + + vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx); + + clk_disable_unprepare(pcdev->clk_emma_ipg); + clk_disable_unprepare(pcdev->clk_emma_ahb); + + dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); + + return 0; +} + +static struct platform_driver mx2_camera_driver = { + .driver = { + .name = MX2_CAM_DRV_NAME, + }, + .id_table = mx2_camera_devtype, + .remove = mx2_camera_remove, +}; + +module_platform_driver_probe(mx2_camera_driver, mx2_camera_probe); + +MODULE_DESCRIPTION("i.MX27 SoC Camera Host driver"); +MODULE_AUTHOR("Sascha Hauer "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(MX2_CAM_VERSION); -- cgit From 41693d1c03212de3267bc77b1cb196294a438616 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Perennou Date: Tue, 1 Mar 2016 09:53:00 +0100 Subject: sign-file: fix build with CMS support disabled Some versions of openssl might have the CMS feature disabled LibreSSL disables this feature too If the feature is disabled, fallback to PKCS7 In file included from scripts/sign-file.c:46:0: /usr/x86_64-pc-linux-gnu/include/openssl/cms.h:62:2: error: #error CMS is disabled. #error CMS is disabled. Signed-off-by: Marc-Antoine Perennou Signed-off-by: David Howells --- scripts/sign-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sign-file.c b/scripts/sign-file.c index 80b7f7f933d6..d912d5a56a5e 100755 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -41,7 +41,7 @@ * signing with anything other than SHA1 - so we're stuck with that if such is * the case. */ -#if (OPENSSL_VERSION_NUMBER < 0x10000000L || LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(OPENSSL_NO_CMS) #define USE_PKCS7 #endif #ifndef USE_PKCS7 -- cgit From 5ed08a8649ddb95860fcf6d8d2e0f34b338043a5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 23 Feb 2016 13:39:10 -0300 Subject: [media] soc_camera/mx3_camera.c: move to staging in preparation, for removal This driver is deprecated: it should become a stand-alone driver instead of using the soc-camera framework. Unless someone is willing to take this on (unlikely with such ancient hardware) it is going to be removed from the kernel soon. Signed-off-by: Hans Verkuil Acked-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/platform/soc_camera/Kconfig | 9 - drivers/media/platform/soc_camera/Makefile | 1 - drivers/media/platform/soc_camera/mx3_camera.c | 1264 ------------------------ drivers/staging/media/Kconfig | 2 + drivers/staging/media/Makefile | 1 + drivers/staging/media/mx3/Kconfig | 15 + drivers/staging/media/mx3/Makefile | 3 + drivers/staging/media/mx3/mx3_camera.c | 1264 ++++++++++++++++++++++++ 8 files changed, 1285 insertions(+), 1274 deletions(-) delete mode 100644 drivers/media/platform/soc_camera/mx3_camera.c create mode 100644 drivers/staging/media/mx3/Kconfig create mode 100644 drivers/staging/media/mx3/Makefile create mode 100644 drivers/staging/media/mx3/mx3_camera.c diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig index 0a537aba35e2..355298989dd8 100644 --- a/drivers/media/platform/soc_camera/Kconfig +++ b/drivers/media/platform/soc_camera/Kconfig @@ -17,15 +17,6 @@ config SOC_CAMERA_PLATFORM help This is a generic SoC camera platform driver, useful for testing -config VIDEO_MX3 - tristate "i.MX3x Camera Sensor Interface driver" - depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA - depends on MX3_IPU || COMPILE_TEST - depends on HAS_DMA - select VIDEOBUF2_DMA_CONTIG - ---help--- - This is a v4l2 driver for the i.MX3x Camera Sensor Interface - config VIDEO_PXA27x tristate "PXA27x Quick Capture Interface driver" depends on VIDEO_DEV && PXA27x && SOC_CAMERA diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile index dad56b9fa01e..7ee71ae231c7 100644 --- a/drivers/media/platform/soc_camera/Makefile +++ b/drivers/media/platform/soc_camera/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o # soc-camera host drivers have to be linked after camera drivers obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o -obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c deleted file mode 100644 index aa39e9569b1a..000000000000 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ /dev/null @@ -1,1264 +0,0 @@ -/* - * V4L2 Driver for i.MX3x camera host - * - * Copyright (C) 2008 - * Guennadi Liakhovetski, DENX Software Engineering, - * - * 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 -#include - -#include -#include -#include -#include -#include - -#include -#include - -#define MX3_CAM_DRV_NAME "mx3-camera" - -/* CMOS Sensor Interface Registers */ -#define CSI_REG_START 0x60 - -#define CSI_SENS_CONF (0x60 - CSI_REG_START) -#define CSI_SENS_FRM_SIZE (0x64 - CSI_REG_START) -#define CSI_ACT_FRM_SIZE (0x68 - CSI_REG_START) -#define CSI_OUT_FRM_CTRL (0x6C - CSI_REG_START) -#define CSI_TST_CTRL (0x70 - CSI_REG_START) -#define CSI_CCIR_CODE_1 (0x74 - CSI_REG_START) -#define CSI_CCIR_CODE_2 (0x78 - CSI_REG_START) -#define CSI_CCIR_CODE_3 (0x7C - CSI_REG_START) -#define CSI_FLASH_STROBE_1 (0x80 - CSI_REG_START) -#define CSI_FLASH_STROBE_2 (0x84 - CSI_REG_START) - -#define CSI_SENS_CONF_VSYNC_POL_SHIFT 0 -#define CSI_SENS_CONF_HSYNC_POL_SHIFT 1 -#define CSI_SENS_CONF_DATA_POL_SHIFT 2 -#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT 3 -#define CSI_SENS_CONF_SENS_PRTCL_SHIFT 4 -#define CSI_SENS_CONF_SENS_CLKSRC_SHIFT 7 -#define CSI_SENS_CONF_DATA_FMT_SHIFT 8 -#define CSI_SENS_CONF_DATA_WIDTH_SHIFT 10 -#define CSI_SENS_CONF_EXT_VSYNC_SHIFT 15 -#define CSI_SENS_CONF_DIVRATIO_SHIFT 16 - -#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444 (0UL << CSI_SENS_CONF_DATA_FMT_SHIFT) -#define CSI_SENS_CONF_DATA_FMT_YUV422 (2UL << CSI_SENS_CONF_DATA_FMT_SHIFT) -#define CSI_SENS_CONF_DATA_FMT_BAYER (3UL << CSI_SENS_CONF_DATA_FMT_SHIFT) - -#define MAX_VIDEO_MEM 16 - -struct mx3_camera_buffer { - /* common v4l buffer stuff -- must be first */ - struct vb2_v4l2_buffer vb; - struct list_head queue; - - /* One descriptot per scatterlist (per frame) */ - struct dma_async_tx_descriptor *txd; - - /* We have to "build" a scatterlist ourselves - one element per frame */ - struct scatterlist sg; -}; - -/** - * struct mx3_camera_dev - i.MX3x camera (CSI) object - * @dev: camera device, to which the coherent buffer is attached - * @icd: currently attached camera sensor - * @clk: pointer to clock - * @base: remapped register base address - * @pdata: platform data - * @platform_flags: platform flags - * @mclk: master clock frequency in Hz - * @capture: list of capture videobuffers - * @lock: protects video buffer lists - * @active: active video buffer - * @idmac_channel: array of pointers to IPU DMAC DMA channels - * @soc_host: embedded soc_host object - */ -struct mx3_camera_dev { - /* - * i.MX3x is only supposed to handle one camera on its Camera Sensor - * Interface. If anyone ever builds hardware to enable more than one - * camera _simultaneously_, they will have to modify this driver too - */ - struct clk *clk; - - void __iomem *base; - - struct mx3_camera_pdata *pdata; - - unsigned long platform_flags; - unsigned long mclk; - u16 width_flags; /* max 15 bits */ - - struct list_head capture; - spinlock_t lock; /* Protects video buffer lists */ - struct mx3_camera_buffer *active; - size_t buf_total; - struct vb2_alloc_ctx *alloc_ctx; - enum v4l2_field field; - int sequence; - - /* IDMAC / dmaengine interface */ - struct idmac_channel *idmac_channel[1]; /* We need one channel */ - - struct soc_camera_host soc_host; -}; - -struct dma_chan_request { - struct mx3_camera_dev *mx3_cam; - enum ipu_channel id; -}; - -static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) -{ - return __raw_readl(mx3->base + reg); -} - -static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg) -{ - __raw_writel(value, mx3->base + reg); -} - -static struct mx3_camera_buffer *to_mx3_vb(struct vb2_v4l2_buffer *vb) -{ - return container_of(vb, struct mx3_camera_buffer, vb); -} - -/* Called from the IPU IDMAC ISR */ -static void mx3_cam_dma_done(void *arg) -{ - struct idmac_tx_desc *desc = to_tx_desc(arg); - struct dma_chan *chan = desc->txd.chan; - struct idmac_channel *ichannel = to_idmac_chan(chan); - struct mx3_camera_dev *mx3_cam = ichannel->client; - - dev_dbg(chan->device->dev, "callback cookie %d, active DMA %pad\n", - desc->txd.cookie, mx3_cam->active ? &sg_dma_address(&mx3_cam->active->sg) : NULL); - - spin_lock(&mx3_cam->lock); - if (mx3_cam->active) { - struct vb2_v4l2_buffer *vb = &mx3_cam->active->vb; - struct mx3_camera_buffer *buf = to_mx3_vb(vb); - - list_del_init(&buf->queue); - vb->vb2_buf.timestamp = ktime_get_ns(); - vb->field = mx3_cam->field; - vb->sequence = mx3_cam->sequence++; - vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); - } - - if (list_empty(&mx3_cam->capture)) { - mx3_cam->active = NULL; - spin_unlock(&mx3_cam->lock); - - /* - * stop capture - without further buffers IPU_CHA_BUF0_RDY will - * not get updated - */ - return; - } - - mx3_cam->active = list_entry(mx3_cam->capture.next, - struct mx3_camera_buffer, queue); - spin_unlock(&mx3_cam->lock); -} - -/* - * Videobuf operations - */ - -/* - * Calculate the __buffer__ (not data) size and number of buffers. - */ -static int mx3_videobuf_setup(struct vb2_queue *vq, - unsigned int *count, unsigned int *num_planes, - unsigned int sizes[], void *alloc_ctxs[]) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(vq); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - - if (!mx3_cam->idmac_channel[0]) - return -EINVAL; - - alloc_ctxs[0] = mx3_cam->alloc_ctx; - - if (!vq->num_buffers) - mx3_cam->sequence = 0; - - if (!*count) - *count = 2; - - /* Called from VIDIOC_REQBUFS or in compatibility mode */ - if (!*num_planes) - sizes[0] = icd->sizeimage; - else if (sizes[0] < icd->sizeimage) - return -EINVAL; - - /* If *num_planes != 0, we have already verified *count. */ - if (sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024) - *count = (MAX_VIDEO_MEM * 1024 * 1024 - mx3_cam->buf_total) / - sizes[0]; - - *num_planes = 1; - - return 0; -} - -static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) -{ - /* Add more formats as need arises and test possibilities appear... */ - switch (fourcc) { - case V4L2_PIX_FMT_RGB24: - return IPU_PIX_FMT_RGB24; - case V4L2_PIX_FMT_UYVY: - case V4L2_PIX_FMT_RGB565: - default: - return IPU_PIX_FMT_GENERIC; - } -} - -static void mx3_videobuf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); - struct scatterlist *sg = &buf->sg; - struct dma_async_tx_descriptor *txd; - struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; - struct idmac_video_param *video = &ichan->params.video; - const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt; - dma_cookie_t cookie; - size_t new_size; - - new_size = icd->sizeimage; - - if (vb2_plane_size(vb, 0) < new_size) { - dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n", - vbuf->vb2_buf.index, vb2_plane_size(vb, 0), new_size); - goto error; - } - - if (!buf->txd) { - sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); - sg_dma_len(sg) = new_size; - - txd = dmaengine_prep_slave_sg( - &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT); - if (!txd) - goto error; - - txd->callback_param = txd; - txd->callback = mx3_cam_dma_done; - - buf->txd = txd; - } else { - txd = buf->txd; - } - - vb2_set_plane_payload(vb, 0, new_size); - - /* This is the configuration of one sg-element */ - video->out_pixel_fmt = fourcc_to_ipu_pix(host_fmt->fourcc); - - if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) { - /* - * If the IPU DMA channel is configured to transfer generic - * 8-bit data, we have to set up the geometry parameters - * correctly, according to the current pixel format. The DMA - * horizontal parameters in this case are expressed in bytes, - * not in pixels. - */ - video->out_width = icd->bytesperline; - video->out_height = icd->user_height; - video->out_stride = icd->bytesperline; - } else { - /* - * For IPU known formats the pixel unit will be managed - * successfully by the IPU code - */ - video->out_width = icd->user_width; - video->out_height = icd->user_height; - video->out_stride = icd->user_width; - } - -#ifdef DEBUG - /* helps to see what DMA actually has written */ - if (vb2_plane_vaddr(vb, 0)) - memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); -#endif - - spin_lock_irq(&mx3_cam->lock); - list_add_tail(&buf->queue, &mx3_cam->capture); - - if (!mx3_cam->active) - mx3_cam->active = buf; - - spin_unlock_irq(&mx3_cam->lock); - - cookie = txd->tx_submit(txd); - dev_dbg(icd->parent, "Submitted cookie %d DMA %pad\n", - cookie, &sg_dma_address(&buf->sg)); - - if (cookie >= 0) - return; - - spin_lock_irq(&mx3_cam->lock); - - /* Submit error */ - list_del_init(&buf->queue); - - if (mx3_cam->active == buf) - mx3_cam->active = NULL; - - spin_unlock_irq(&mx3_cam->lock); -error: - vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); -} - -static void mx3_videobuf_release(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); - struct dma_async_tx_descriptor *txd = buf->txd; - unsigned long flags; - - dev_dbg(icd->parent, - "Release%s DMA %pad, queue %sempty\n", - mx3_cam->active == buf ? " active" : "", &sg_dma_address(&buf->sg), - list_empty(&buf->queue) ? "" : "not "); - - spin_lock_irqsave(&mx3_cam->lock, flags); - - if (mx3_cam->active == buf) - mx3_cam->active = NULL; - - /* Doesn't hurt also if the list is empty */ - list_del_init(&buf->queue); - - if (txd) { - buf->txd = NULL; - if (mx3_cam->idmac_channel[0]) - async_tx_ack(txd); - } - - spin_unlock_irqrestore(&mx3_cam->lock, flags); - - mx3_cam->buf_total -= vb2_plane_size(vb, 0); -} - -static int mx3_videobuf_init(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); - - if (!buf->txd) { - /* This is for locking debugging only */ - INIT_LIST_HEAD(&buf->queue); - sg_init_table(&buf->sg, 1); - - mx3_cam->buf_total += vb2_plane_size(vb, 0); - } - - return 0; -} - -static void mx3_stop_streaming(struct vb2_queue *q) -{ - struct soc_camera_device *icd = soc_camera_from_vb2q(q); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; - struct mx3_camera_buffer *buf, *tmp; - unsigned long flags; - - if (ichan) - dmaengine_pause(&ichan->dma_chan); - - spin_lock_irqsave(&mx3_cam->lock, flags); - - mx3_cam->active = NULL; - - list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) { - list_del_init(&buf->queue); - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - - spin_unlock_irqrestore(&mx3_cam->lock, flags); -} - -static struct vb2_ops mx3_videobuf_ops = { - .queue_setup = mx3_videobuf_setup, - .buf_queue = mx3_videobuf_queue, - .buf_cleanup = mx3_videobuf_release, - .buf_init = mx3_videobuf_init, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .stop_streaming = mx3_stop_streaming, -}; - -static int mx3_camera_init_videobuf(struct vb2_queue *q, - struct soc_camera_device *icd) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_USERPTR; - q->drv_priv = icd; - q->ops = &mx3_videobuf_ops; - q->mem_ops = &vb2_dma_contig_memops; - q->buf_struct_size = sizeof(struct mx3_camera_buffer); - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &ici->host_lock; - - return vb2_queue_init(q); -} - -/* First part of ipu_csi_init_interface() */ -static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam) -{ - u32 conf; - long rate; - - /* Set default size: ipu_csi_set_window_size() */ - csi_reg_write(mx3_cam, (640 - 1) | ((480 - 1) << 16), CSI_ACT_FRM_SIZE); - /* ...and position to 0:0: ipu_csi_set_window_pos() */ - conf = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; - csi_reg_write(mx3_cam, conf, CSI_OUT_FRM_CTRL); - - /* We use only gated clock synchronisation mode so far */ - conf = 0 << CSI_SENS_CONF_SENS_PRTCL_SHIFT; - - /* Set generic data, platform-biggest bus-width */ - conf |= CSI_SENS_CONF_DATA_FMT_BAYER; - - if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) - conf |= 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) - conf |= 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) - conf |= 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - else/* if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)*/ - conf |= 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - - if (mx3_cam->platform_flags & MX3_CAMERA_CLK_SRC) - conf |= 1 << CSI_SENS_CONF_SENS_CLKSRC_SHIFT; - if (mx3_cam->platform_flags & MX3_CAMERA_EXT_VSYNC) - conf |= 1 << CSI_SENS_CONF_EXT_VSYNC_SHIFT; - if (mx3_cam->platform_flags & MX3_CAMERA_DP) - conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; - if (mx3_cam->platform_flags & MX3_CAMERA_PCP) - conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; - if (mx3_cam->platform_flags & MX3_CAMERA_HSP) - conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; - if (mx3_cam->platform_flags & MX3_CAMERA_VSP) - conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; - - /* ipu_csi_init_interface() */ - csi_reg_write(mx3_cam, conf, CSI_SENS_CONF); - - clk_prepare_enable(mx3_cam->clk); - rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); - dev_dbg(mx3_cam->soc_host.v4l2_dev.dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); - if (rate) - clk_set_rate(mx3_cam->clk, rate); -} - -static int mx3_camera_add_device(struct soc_camera_device *icd) -{ - dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", - icd->devnum); - - return 0; -} - -static void mx3_camera_remove_device(struct soc_camera_device *icd) -{ - dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", - icd->devnum); -} - -/* Called with .host_lock held */ -static int mx3_camera_clock_start(struct soc_camera_host *ici) -{ - struct mx3_camera_dev *mx3_cam = ici->priv; - - mx3_camera_activate(mx3_cam); - - mx3_cam->buf_total = 0; - - return 0; -} - -/* Called with .host_lock held */ -static void mx3_camera_clock_stop(struct soc_camera_host *ici) -{ - struct mx3_camera_dev *mx3_cam = ici->priv; - struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; - - if (*ichan) { - dma_release_channel(&(*ichan)->dma_chan); - *ichan = NULL; - } - - clk_disable_unprepare(mx3_cam->clk); -} - -static int test_platform_param(struct mx3_camera_dev *mx3_cam, - unsigned char buswidth, unsigned long *flags) -{ - /* - * If requested data width is supported by the platform, use it or any - * possible lower value - i.MX31 is smart enough to shift bits - */ - if (buswidth > fls(mx3_cam->width_flags)) - return -EINVAL; - - /* - * Platform specified synchronization and pixel clock polarities are - * only a recommendation and are only used during probing. MX3x - * camera interface only works in master mode, i.e., uses HSYNC and - * VSYNC signals from the sensor - */ - *flags = V4L2_MBUS_MASTER | - V4L2_MBUS_HSYNC_ACTIVE_HIGH | - V4L2_MBUS_HSYNC_ACTIVE_LOW | - V4L2_MBUS_VSYNC_ACTIVE_HIGH | - V4L2_MBUS_VSYNC_ACTIVE_LOW | - V4L2_MBUS_PCLK_SAMPLE_RISING | - V4L2_MBUS_PCLK_SAMPLE_FALLING | - V4L2_MBUS_DATA_ACTIVE_HIGH | - V4L2_MBUS_DATA_ACTIVE_LOW; - - return 0; -} - -static int mx3_camera_try_bus_param(struct soc_camera_device *icd, - const unsigned int depth) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; - unsigned long bus_flags, common_flags; - int ret = test_platform_param(mx3_cam, depth, &bus_flags); - - dev_dbg(icd->parent, "request bus width %d bit: %d\n", depth, ret); - - if (ret < 0) - return ret; - - ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); - if (!ret) { - common_flags = soc_mbus_config_compatible(&cfg, - bus_flags); - if (!common_flags) { - dev_warn(icd->parent, - "Flags incompatible: camera 0x%x, host 0x%lx\n", - cfg.flags, bus_flags); - return -EINVAL; - } - } else if (ret != -ENOIOCTLCMD) { - return ret; - } - - return 0; -} - -static bool chan_filter(struct dma_chan *chan, void *arg) -{ - struct dma_chan_request *rq = arg; - struct mx3_camera_pdata *pdata; - - if (!imx_dma_is_ipu(chan)) - return false; - - if (!rq) - return false; - - pdata = rq->mx3_cam->soc_host.v4l2_dev.dev->platform_data; - - return rq->id == chan->chan_id && - pdata->dma_dev == chan->device->dev; -} - -static const struct soc_mbus_pixelfmt mx3_camera_formats[] = { - { - .fourcc = V4L2_PIX_FMT_SBGGR8, - .name = "Bayer BGGR (sRGB) 8 bit", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_NONE, - .order = SOC_MBUS_ORDER_LE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, { - .fourcc = V4L2_PIX_FMT_GREY, - .name = "Monochrome 8 bit", - .bits_per_sample = 8, - .packing = SOC_MBUS_PACKING_NONE, - .order = SOC_MBUS_ORDER_LE, - .layout = SOC_MBUS_LAYOUT_PACKED, - }, -}; - -/* This will be corrected as we get more formats */ -static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) -{ - return fmt->packing == SOC_MBUS_PACKING_NONE || - (fmt->bits_per_sample == 8 && - fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || - (fmt->bits_per_sample > 8 && - fmt->packing == SOC_MBUS_PACKING_EXTEND16); -} - -static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx, - struct soc_camera_format_xlate *xlate) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct device *dev = icd->parent; - int formats = 0, ret; - struct v4l2_subdev_mbus_code_enum code = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - .index = idx, - }; - const struct soc_mbus_pixelfmt *fmt; - - ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); - if (ret < 0) - /* No more formats */ - return 0; - - fmt = soc_mbus_get_fmtdesc(code.code); - if (!fmt) { - dev_warn(icd->parent, - "Unsupported format code #%u: 0x%x\n", idx, code.code); - return 0; - } - - /* This also checks support for the requested bits-per-sample */ - ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample); - if (ret < 0) - return 0; - - switch (code.code) { - case MEDIA_BUS_FMT_SBGGR10_1X10: - formats++; - if (xlate) { - xlate->host_fmt = &mx3_camera_formats[0]; - xlate->code = code.code; - xlate++; - dev_dbg(dev, "Providing format %s using code 0x%x\n", - mx3_camera_formats[0].name, code.code); - } - break; - case MEDIA_BUS_FMT_Y10_1X10: - formats++; - if (xlate) { - xlate->host_fmt = &mx3_camera_formats[1]; - xlate->code = code.code; - xlate++; - dev_dbg(dev, "Providing format %s using code 0x%x\n", - mx3_camera_formats[1].name, code.code); - } - break; - default: - if (!mx3_camera_packing_supported(fmt)) - return 0; - } - - /* Generic pass-through */ - formats++; - if (xlate) { - xlate->host_fmt = fmt; - xlate->code = code.code; - dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n", - (fmt->fourcc >> (0*8)) & 0xFF, - (fmt->fourcc >> (1*8)) & 0xFF, - (fmt->fourcc >> (2*8)) & 0xFF, - (fmt->fourcc >> (3*8)) & 0xFF); - xlate++; - } - - return formats; -} - -static void configure_geometry(struct mx3_camera_dev *mx3_cam, - unsigned int width, unsigned int height, - const struct soc_mbus_pixelfmt *fmt) -{ - u32 ctrl, width_field, height_field; - - if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) { - /* - * As the CSI will be configured to output BAYER, here - * the width parameter count the number of samples to - * capture to complete the whole image width. - */ - unsigned int num, den; - int ret = soc_mbus_samples_per_pixel(fmt, &num, &den); - BUG_ON(ret < 0); - width = width * num / den; - } - - /* Setup frame size - this cannot be changed on-the-fly... */ - width_field = width - 1; - height_field = height - 1; - csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE); - - csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1); - csi_reg_write(mx3_cam, (height_field << 16) | 0x22, CSI_FLASH_STROBE_2); - - csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_ACT_FRM_SIZE); - - /* ...and position */ - ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; - /* Sensor does the cropping */ - csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL); -} - -static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) -{ - dma_cap_mask_t mask; - struct dma_chan *chan; - struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; - /* We have to use IDMAC_IC_7 for Bayer / generic data */ - struct dma_chan_request rq = {.mx3_cam = mx3_cam, - .id = IDMAC_IC_7}; - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - dma_cap_set(DMA_PRIVATE, mask); - chan = dma_request_channel(mask, chan_filter, &rq); - if (!chan) - return -EBUSY; - - *ichan = to_idmac_chan(chan); - (*ichan)->client = mx3_cam; - - return 0; -} - -/* - * FIXME: learn to use stride != width, then we can keep stride properly aligned - * and support arbitrary (even) widths. - */ -static inline void stride_align(__u32 *width) -{ - if (ALIGN(*width, 8) < 4096) - *width = ALIGN(*width, 8); - else - *width = *width & ~7; -} - -/* - * As long as we don't implement host-side cropping and scaling, we can use - * default g_crop and cropcap from soc_camera.c - */ -static int mx3_camera_set_crop(struct soc_camera_device *icd, - const struct v4l2_crop *a) -{ - struct v4l2_crop a_writable = *a; - struct v4l2_rect *rect = &a_writable.c; - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct v4l2_subdev_format fmt = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_mbus_framefmt *mf = &fmt.format; - int ret; - - soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); - soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); - - ret = v4l2_subdev_call(sd, video, s_crop, a); - if (ret < 0) - return ret; - - /* The capture device might have changed its output sizes */ - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); - if (ret < 0) - return ret; - - if (mf->code != icd->current_fmt->code) - return -EINVAL; - - if (mf->width & 7) { - /* Ouch! We can only handle 8-byte aligned width... */ - stride_align(&mf->width); - ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt); - if (ret < 0) - return ret; - } - - if (mf->width != icd->user_width || mf->height != icd->user_height) - configure_geometry(mx3_cam, mf->width, mf->height, - icd->current_fmt->host_fmt); - - dev_dbg(icd->parent, "Sensor cropped %dx%d\n", - mf->width, mf->height); - - icd->user_width = mf->width; - icd->user_height = mf->height; - - return ret; -} - -static int mx3_camera_set_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_format_xlate *xlate; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_ACTIVE, - }; - struct v4l2_mbus_framefmt *mf = &format.format; - int ret; - - xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); - if (!xlate) { - dev_warn(icd->parent, "Format %x not found\n", - pix->pixelformat); - return -EINVAL; - } - - stride_align(&pix->width); - dev_dbg(icd->parent, "Set format %dx%d\n", pix->width, pix->height); - - /* - * Might have to perform a complete interface initialisation like in - * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider - * mxc_v4l2_s_fmt() - */ - - configure_geometry(mx3_cam, pix->width, pix->height, xlate->host_fmt); - - mf->width = pix->width; - mf->height = pix->height; - mf->field = pix->field; - mf->colorspace = pix->colorspace; - mf->code = xlate->code; - - ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format); - if (ret < 0) - return ret; - - if (mf->code != xlate->code) - return -EINVAL; - - if (!mx3_cam->idmac_channel[0]) { - ret = acquire_dma_channel(mx3_cam); - if (ret < 0) - return ret; - } - - pix->width = mf->width; - pix->height = mf->height; - pix->field = mf->field; - mx3_cam->field = mf->field; - pix->colorspace = mf->colorspace; - icd->current_fmt = xlate; - - dev_dbg(icd->parent, "Sensor set %dx%d\n", pix->width, pix->height); - - return ret; -} - -static int mx3_camera_try_fmt(struct soc_camera_device *icd, - struct v4l2_format *f) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - const struct soc_camera_format_xlate *xlate; - struct v4l2_pix_format *pix = &f->fmt.pix; - struct v4l2_subdev_pad_config pad_cfg; - struct v4l2_subdev_format format = { - .which = V4L2_SUBDEV_FORMAT_TRY, - }; - struct v4l2_mbus_framefmt *mf = &format.format; - __u32 pixfmt = pix->pixelformat; - int ret; - - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (pixfmt && !xlate) { - dev_warn(icd->parent, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - /* limit to MX3 hardware capabilities */ - if (pix->height > 4096) - pix->height = 4096; - if (pix->width > 4096) - pix->width = 4096; - - /* limit to sensor capabilities */ - mf->width = pix->width; - mf->height = pix->height; - mf->field = pix->field; - mf->colorspace = pix->colorspace; - mf->code = xlate->code; - - ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); - if (ret < 0) - return ret; - - pix->width = mf->width; - pix->height = mf->height; - pix->colorspace = mf->colorspace; - - switch (mf->field) { - case V4L2_FIELD_ANY: - pix->field = V4L2_FIELD_NONE; - break; - case V4L2_FIELD_NONE: - break; - default: - dev_err(icd->parent, "Field type %d unsupported.\n", - mf->field); - ret = -EINVAL; - } - - return ret; -} - -static int mx3_camera_reqbufs(struct soc_camera_device *icd, - struct v4l2_requestbuffers *p) -{ - return 0; -} - -static unsigned int mx3_camera_poll(struct file *file, poll_table *pt) -{ - struct soc_camera_device *icd = file->private_data; - - return vb2_poll(&icd->vb2_vidq, file, pt); -} - -static int mx3_camera_querycap(struct soc_camera_host *ici, - struct v4l2_capability *cap) -{ - /* cap->name is set by the firendly caller:-> */ - strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card)); - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - - return 0; -} - -static int mx3_camera_set_bus_param(struct soc_camera_device *icd) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - struct soc_camera_host *ici = to_soc_camera_host(icd->parent); - struct mx3_camera_dev *mx3_cam = ici->priv; - struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; - u32 pixfmt = icd->current_fmt->host_fmt->fourcc; - unsigned long bus_flags, common_flags; - u32 dw, sens_conf; - const struct soc_mbus_pixelfmt *fmt; - int buswidth; - int ret; - const struct soc_camera_format_xlate *xlate; - struct device *dev = icd->parent; - - fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); - if (!fmt) - return -EINVAL; - - xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); - if (!xlate) { - dev_warn(dev, "Format %x not found\n", pixfmt); - return -EINVAL; - } - - buswidth = fmt->bits_per_sample; - ret = test_platform_param(mx3_cam, buswidth, &bus_flags); - - dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret); - - if (ret < 0) - return ret; - - ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); - if (!ret) { - common_flags = soc_mbus_config_compatible(&cfg, - bus_flags); - if (!common_flags) { - dev_warn(icd->parent, - "Flags incompatible: camera 0x%x, host 0x%lx\n", - cfg.flags, bus_flags); - return -EINVAL; - } - } else if (ret != -ENOIOCTLCMD) { - return ret; - } else { - common_flags = bus_flags; - } - - dev_dbg(dev, "Flags cam: 0x%x host: 0x%lx common: 0x%lx\n", - cfg.flags, bus_flags, common_flags); - - /* Make choices, based on platform preferences */ - if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && - (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { - if (mx3_cam->platform_flags & MX3_CAMERA_HSP) - common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; - else - common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; - } - - if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && - (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { - if (mx3_cam->platform_flags & MX3_CAMERA_VSP) - common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; - else - common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; - } - - if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) && - (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) { - if (mx3_cam->platform_flags & MX3_CAMERA_DP) - common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH; - else - common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW; - } - - if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && - (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { - if (mx3_cam->platform_flags & MX3_CAMERA_PCP) - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; - else - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; - } - - cfg.flags = common_flags; - ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); - if (ret < 0 && ret != -ENOIOCTLCMD) { - dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n", - common_flags, ret); - return ret; - } - - /* - * So far only gated clock mode is supported. Add a line - * (3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) | - * below and select the required mode when supporting other - * synchronisation protocols. - */ - sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) & - ~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) | - (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) | - (1 << CSI_SENS_CONF_DATA_POL_SHIFT) | - (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) | - (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) | - (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT)); - - /* TODO: Support RGB and YUV formats */ - - /* This has been set in mx3_camera_activate(), but we clear it above */ - sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER; - - if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) - sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; - if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) - sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; - if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) - sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; - if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW) - sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; - - /* Just do what we're asked to do */ - switch (xlate->host_fmt->bits_per_sample) { - case 4: - dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - break; - case 8: - dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - break; - case 10: - dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - break; - default: - /* - * Actually it can only be 15 now, default is just to silence - * compiler warnings - */ - case 15: - dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; - } - - csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); - - dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw); - - return 0; -} - -static struct soc_camera_host_ops mx3_soc_camera_host_ops = { - .owner = THIS_MODULE, - .add = mx3_camera_add_device, - .remove = mx3_camera_remove_device, - .clock_start = mx3_camera_clock_start, - .clock_stop = mx3_camera_clock_stop, - .set_crop = mx3_camera_set_crop, - .set_fmt = mx3_camera_set_fmt, - .try_fmt = mx3_camera_try_fmt, - .get_formats = mx3_camera_get_formats, - .init_videobuf2 = mx3_camera_init_videobuf, - .reqbufs = mx3_camera_reqbufs, - .poll = mx3_camera_poll, - .querycap = mx3_camera_querycap, - .set_bus_param = mx3_camera_set_bus_param, -}; - -static int mx3_camera_probe(struct platform_device *pdev) -{ - struct mx3_camera_pdata *pdata = pdev->dev.platform_data; - struct mx3_camera_dev *mx3_cam; - struct resource *res; - void __iomem *base; - int err = 0; - struct soc_camera_host *soc_host; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - - if (!pdata) - return -EINVAL; - - mx3_cam = devm_kzalloc(&pdev->dev, sizeof(*mx3_cam), GFP_KERNEL); - if (!mx3_cam) { - dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); - return -ENOMEM; - } - - mx3_cam->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(mx3_cam->clk)) - return PTR_ERR(mx3_cam->clk); - - mx3_cam->pdata = pdata; - mx3_cam->platform_flags = pdata->flags; - if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { - /* - * Platform hasn't set available data widths. This is bad. - * Warn and use a default. - */ - dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " - "data widths, using default 8 bit\n"); - mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; - } - if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4) - mx3_cam->width_flags = 1 << 3; - if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) - mx3_cam->width_flags |= 1 << 7; - if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) - mx3_cam->width_flags |= 1 << 9; - if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) - mx3_cam->width_flags |= 1 << 14; - - mx3_cam->mclk = pdata->mclk_10khz * 10000; - if (!mx3_cam->mclk) { - dev_warn(&pdev->dev, - "mclk_10khz == 0! Please, fix your platform data. " - "Using default 20MHz\n"); - mx3_cam->mclk = 20000000; - } - - /* list of video-buffers */ - INIT_LIST_HEAD(&mx3_cam->capture); - spin_lock_init(&mx3_cam->lock); - - mx3_cam->base = base; - - soc_host = &mx3_cam->soc_host; - soc_host->drv_name = MX3_CAM_DRV_NAME; - soc_host->ops = &mx3_soc_camera_host_ops; - soc_host->priv = mx3_cam; - soc_host->v4l2_dev.dev = &pdev->dev; - soc_host->nr = pdev->id; - - mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); - if (IS_ERR(mx3_cam->alloc_ctx)) - return PTR_ERR(mx3_cam->alloc_ctx); - - if (pdata->asd_sizes) { - soc_host->asd = pdata->asd; - soc_host->asd_sizes = pdata->asd_sizes; - } - - err = soc_camera_host_register(soc_host); - if (err) - goto ecamhostreg; - - /* IDMAC interface */ - dmaengine_get(); - - return 0; - -ecamhostreg: - vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); - return err; -} - -static int mx3_camera_remove(struct platform_device *pdev) -{ - struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); - struct mx3_camera_dev *mx3_cam = container_of(soc_host, - struct mx3_camera_dev, soc_host); - - soc_camera_host_unregister(soc_host); - - /* - * The channel has either not been allocated, - * or should have been released - */ - if (WARN_ON(mx3_cam->idmac_channel[0])) - dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); - - vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); - - dmaengine_put(); - - return 0; -} - -static struct platform_driver mx3_camera_driver = { - .driver = { - .name = MX3_CAM_DRV_NAME, - }, - .probe = mx3_camera_probe, - .remove = mx3_camera_remove, -}; - -module_platform_driver(mx3_camera_driver); - -MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); -MODULE_AUTHOR("Guennadi Liakhovetski "); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION("0.2.3"); -MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME); diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig index 11d62b2afae5..be271084ad91 100644 --- a/drivers/staging/media/Kconfig +++ b/drivers/staging/media/Kconfig @@ -31,6 +31,8 @@ source "drivers/staging/media/mn88473/Kconfig" source "drivers/staging/media/mx2/Kconfig" +source "drivers/staging/media/mx3/Kconfig" + source "drivers/staging/media/omap1/Kconfig" source "drivers/staging/media/omap4iss/Kconfig" diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile index d3ff2d054be7..4861163371ef 100644 --- a/drivers/staging/media/Makefile +++ b/drivers/staging/media/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_DVB_CXD2099) += cxd2099/ obj-$(CONFIG_LIRC_STAGING) += lirc/ obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/ obj-$(CONFIG_VIDEO_MX2) += mx2/ +obj-$(CONFIG_VIDEO_MX3) += mx3/ obj-$(CONFIG_VIDEO_OMAP1) += omap1/ obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/ obj-$(CONFIG_DVB_MN88472) += mn88472/ diff --git a/drivers/staging/media/mx3/Kconfig b/drivers/staging/media/mx3/Kconfig new file mode 100644 index 000000000000..595d5fe7cad1 --- /dev/null +++ b/drivers/staging/media/mx3/Kconfig @@ -0,0 +1,15 @@ +config VIDEO_MX3 + tristate "i.MX3x Camera Sensor Interface driver" + depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA + depends on MX3_IPU || COMPILE_TEST + depends on HAS_DMA + select VIDEOBUF2_DMA_CONTIG + ---help--- + This is a v4l2 driver for the i.MX3x Camera Sensor Interface + + This driver is deprecated: it should become a stand-alone driver + instead of using the soc-camera framework. + + Unless someone is willing to take this on (unlikely with such + ancient hardware) it is going to be removed from the kernel + soon. diff --git a/drivers/staging/media/mx3/Makefile b/drivers/staging/media/mx3/Makefile new file mode 100644 index 000000000000..6d91dcd80c1d --- /dev/null +++ b/drivers/staging/media/mx3/Makefile @@ -0,0 +1,3 @@ +# Makefile for i.MX3x Camera Sensor driver + +obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o diff --git a/drivers/staging/media/mx3/mx3_camera.c b/drivers/staging/media/mx3/mx3_camera.c new file mode 100644 index 000000000000..aa39e9569b1a --- /dev/null +++ b/drivers/staging/media/mx3/mx3_camera.c @@ -0,0 +1,1264 @@ +/* + * V4L2 Driver for i.MX3x camera host + * + * Copyright (C) 2008 + * Guennadi Liakhovetski, DENX Software Engineering, + * + * 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 +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define MX3_CAM_DRV_NAME "mx3-camera" + +/* CMOS Sensor Interface Registers */ +#define CSI_REG_START 0x60 + +#define CSI_SENS_CONF (0x60 - CSI_REG_START) +#define CSI_SENS_FRM_SIZE (0x64 - CSI_REG_START) +#define CSI_ACT_FRM_SIZE (0x68 - CSI_REG_START) +#define CSI_OUT_FRM_CTRL (0x6C - CSI_REG_START) +#define CSI_TST_CTRL (0x70 - CSI_REG_START) +#define CSI_CCIR_CODE_1 (0x74 - CSI_REG_START) +#define CSI_CCIR_CODE_2 (0x78 - CSI_REG_START) +#define CSI_CCIR_CODE_3 (0x7C - CSI_REG_START) +#define CSI_FLASH_STROBE_1 (0x80 - CSI_REG_START) +#define CSI_FLASH_STROBE_2 (0x84 - CSI_REG_START) + +#define CSI_SENS_CONF_VSYNC_POL_SHIFT 0 +#define CSI_SENS_CONF_HSYNC_POL_SHIFT 1 +#define CSI_SENS_CONF_DATA_POL_SHIFT 2 +#define CSI_SENS_CONF_PIX_CLK_POL_SHIFT 3 +#define CSI_SENS_CONF_SENS_PRTCL_SHIFT 4 +#define CSI_SENS_CONF_SENS_CLKSRC_SHIFT 7 +#define CSI_SENS_CONF_DATA_FMT_SHIFT 8 +#define CSI_SENS_CONF_DATA_WIDTH_SHIFT 10 +#define CSI_SENS_CONF_EXT_VSYNC_SHIFT 15 +#define CSI_SENS_CONF_DIVRATIO_SHIFT 16 + +#define CSI_SENS_CONF_DATA_FMT_RGB_YUV444 (0UL << CSI_SENS_CONF_DATA_FMT_SHIFT) +#define CSI_SENS_CONF_DATA_FMT_YUV422 (2UL << CSI_SENS_CONF_DATA_FMT_SHIFT) +#define CSI_SENS_CONF_DATA_FMT_BAYER (3UL << CSI_SENS_CONF_DATA_FMT_SHIFT) + +#define MAX_VIDEO_MEM 16 + +struct mx3_camera_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_v4l2_buffer vb; + struct list_head queue; + + /* One descriptot per scatterlist (per frame) */ + struct dma_async_tx_descriptor *txd; + + /* We have to "build" a scatterlist ourselves - one element per frame */ + struct scatterlist sg; +}; + +/** + * struct mx3_camera_dev - i.MX3x camera (CSI) object + * @dev: camera device, to which the coherent buffer is attached + * @icd: currently attached camera sensor + * @clk: pointer to clock + * @base: remapped register base address + * @pdata: platform data + * @platform_flags: platform flags + * @mclk: master clock frequency in Hz + * @capture: list of capture videobuffers + * @lock: protects video buffer lists + * @active: active video buffer + * @idmac_channel: array of pointers to IPU DMAC DMA channels + * @soc_host: embedded soc_host object + */ +struct mx3_camera_dev { + /* + * i.MX3x is only supposed to handle one camera on its Camera Sensor + * Interface. If anyone ever builds hardware to enable more than one + * camera _simultaneously_, they will have to modify this driver too + */ + struct clk *clk; + + void __iomem *base; + + struct mx3_camera_pdata *pdata; + + unsigned long platform_flags; + unsigned long mclk; + u16 width_flags; /* max 15 bits */ + + struct list_head capture; + spinlock_t lock; /* Protects video buffer lists */ + struct mx3_camera_buffer *active; + size_t buf_total; + struct vb2_alloc_ctx *alloc_ctx; + enum v4l2_field field; + int sequence; + + /* IDMAC / dmaengine interface */ + struct idmac_channel *idmac_channel[1]; /* We need one channel */ + + struct soc_camera_host soc_host; +}; + +struct dma_chan_request { + struct mx3_camera_dev *mx3_cam; + enum ipu_channel id; +}; + +static u32 csi_reg_read(struct mx3_camera_dev *mx3, off_t reg) +{ + return __raw_readl(mx3->base + reg); +} + +static void csi_reg_write(struct mx3_camera_dev *mx3, u32 value, off_t reg) +{ + __raw_writel(value, mx3->base + reg); +} + +static struct mx3_camera_buffer *to_mx3_vb(struct vb2_v4l2_buffer *vb) +{ + return container_of(vb, struct mx3_camera_buffer, vb); +} + +/* Called from the IPU IDMAC ISR */ +static void mx3_cam_dma_done(void *arg) +{ + struct idmac_tx_desc *desc = to_tx_desc(arg); + struct dma_chan *chan = desc->txd.chan; + struct idmac_channel *ichannel = to_idmac_chan(chan); + struct mx3_camera_dev *mx3_cam = ichannel->client; + + dev_dbg(chan->device->dev, "callback cookie %d, active DMA %pad\n", + desc->txd.cookie, mx3_cam->active ? &sg_dma_address(&mx3_cam->active->sg) : NULL); + + spin_lock(&mx3_cam->lock); + if (mx3_cam->active) { + struct vb2_v4l2_buffer *vb = &mx3_cam->active->vb; + struct mx3_camera_buffer *buf = to_mx3_vb(vb); + + list_del_init(&buf->queue); + vb->vb2_buf.timestamp = ktime_get_ns(); + vb->field = mx3_cam->field; + vb->sequence = mx3_cam->sequence++; + vb2_buffer_done(&vb->vb2_buf, VB2_BUF_STATE_DONE); + } + + if (list_empty(&mx3_cam->capture)) { + mx3_cam->active = NULL; + spin_unlock(&mx3_cam->lock); + + /* + * stop capture - without further buffers IPU_CHA_BUF0_RDY will + * not get updated + */ + return; + } + + mx3_cam->active = list_entry(mx3_cam->capture.next, + struct mx3_camera_buffer, queue); + spin_unlock(&mx3_cam->lock); +} + +/* + * Videobuf operations + */ + +/* + * Calculate the __buffer__ (not data) size and number of buffers. + */ +static int mx3_videobuf_setup(struct vb2_queue *vq, + unsigned int *count, unsigned int *num_planes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct soc_camera_device *icd = soc_camera_from_vb2q(vq); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + + if (!mx3_cam->idmac_channel[0]) + return -EINVAL; + + alloc_ctxs[0] = mx3_cam->alloc_ctx; + + if (!vq->num_buffers) + mx3_cam->sequence = 0; + + if (!*count) + *count = 2; + + /* Called from VIDIOC_REQBUFS or in compatibility mode */ + if (!*num_planes) + sizes[0] = icd->sizeimage; + else if (sizes[0] < icd->sizeimage) + return -EINVAL; + + /* If *num_planes != 0, we have already verified *count. */ + if (sizes[0] * *count + mx3_cam->buf_total > MAX_VIDEO_MEM * 1024 * 1024) + *count = (MAX_VIDEO_MEM * 1024 * 1024 - mx3_cam->buf_total) / + sizes[0]; + + *num_planes = 1; + + return 0; +} + +static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc) +{ + /* Add more formats as need arises and test possibilities appear... */ + switch (fourcc) { + case V4L2_PIX_FMT_RGB24: + return IPU_PIX_FMT_RGB24; + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_RGB565: + default: + return IPU_PIX_FMT_GENERIC; + } +} + +static void mx3_videobuf_queue(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); + struct scatterlist *sg = &buf->sg; + struct dma_async_tx_descriptor *txd; + struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; + struct idmac_video_param *video = &ichan->params.video; + const struct soc_mbus_pixelfmt *host_fmt = icd->current_fmt->host_fmt; + dma_cookie_t cookie; + size_t new_size; + + new_size = icd->sizeimage; + + if (vb2_plane_size(vb, 0) < new_size) { + dev_err(icd->parent, "Buffer #%d too small (%lu < %zu)\n", + vbuf->vb2_buf.index, vb2_plane_size(vb, 0), new_size); + goto error; + } + + if (!buf->txd) { + sg_dma_address(sg) = vb2_dma_contig_plane_dma_addr(vb, 0); + sg_dma_len(sg) = new_size; + + txd = dmaengine_prep_slave_sg( + &ichan->dma_chan, sg, 1, DMA_DEV_TO_MEM, + DMA_PREP_INTERRUPT); + if (!txd) + goto error; + + txd->callback_param = txd; + txd->callback = mx3_cam_dma_done; + + buf->txd = txd; + } else { + txd = buf->txd; + } + + vb2_set_plane_payload(vb, 0, new_size); + + /* This is the configuration of one sg-element */ + video->out_pixel_fmt = fourcc_to_ipu_pix(host_fmt->fourcc); + + if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) { + /* + * If the IPU DMA channel is configured to transfer generic + * 8-bit data, we have to set up the geometry parameters + * correctly, according to the current pixel format. The DMA + * horizontal parameters in this case are expressed in bytes, + * not in pixels. + */ + video->out_width = icd->bytesperline; + video->out_height = icd->user_height; + video->out_stride = icd->bytesperline; + } else { + /* + * For IPU known formats the pixel unit will be managed + * successfully by the IPU code + */ + video->out_width = icd->user_width; + video->out_height = icd->user_height; + video->out_stride = icd->user_width; + } + +#ifdef DEBUG + /* helps to see what DMA actually has written */ + if (vb2_plane_vaddr(vb, 0)) + memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0)); +#endif + + spin_lock_irq(&mx3_cam->lock); + list_add_tail(&buf->queue, &mx3_cam->capture); + + if (!mx3_cam->active) + mx3_cam->active = buf; + + spin_unlock_irq(&mx3_cam->lock); + + cookie = txd->tx_submit(txd); + dev_dbg(icd->parent, "Submitted cookie %d DMA %pad\n", + cookie, &sg_dma_address(&buf->sg)); + + if (cookie >= 0) + return; + + spin_lock_irq(&mx3_cam->lock); + + /* Submit error */ + list_del_init(&buf->queue); + + if (mx3_cam->active == buf) + mx3_cam->active = NULL; + + spin_unlock_irq(&mx3_cam->lock); +error: + vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); +} + +static void mx3_videobuf_release(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); + struct dma_async_tx_descriptor *txd = buf->txd; + unsigned long flags; + + dev_dbg(icd->parent, + "Release%s DMA %pad, queue %sempty\n", + mx3_cam->active == buf ? " active" : "", &sg_dma_address(&buf->sg), + list_empty(&buf->queue) ? "" : "not "); + + spin_lock_irqsave(&mx3_cam->lock, flags); + + if (mx3_cam->active == buf) + mx3_cam->active = NULL; + + /* Doesn't hurt also if the list is empty */ + list_del_init(&buf->queue); + + if (txd) { + buf->txd = NULL; + if (mx3_cam->idmac_channel[0]) + async_tx_ack(txd); + } + + spin_unlock_irqrestore(&mx3_cam->lock, flags); + + mx3_cam->buf_total -= vb2_plane_size(vb, 0); +} + +static int mx3_videobuf_init(struct vb2_buffer *vb) +{ + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct mx3_camera_buffer *buf = to_mx3_vb(vbuf); + + if (!buf->txd) { + /* This is for locking debugging only */ + INIT_LIST_HEAD(&buf->queue); + sg_init_table(&buf->sg, 1); + + mx3_cam->buf_total += vb2_plane_size(vb, 0); + } + + return 0; +} + +static void mx3_stop_streaming(struct vb2_queue *q) +{ + struct soc_camera_device *icd = soc_camera_from_vb2q(q); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct idmac_channel *ichan = mx3_cam->idmac_channel[0]; + struct mx3_camera_buffer *buf, *tmp; + unsigned long flags; + + if (ichan) + dmaengine_pause(&ichan->dma_chan); + + spin_lock_irqsave(&mx3_cam->lock, flags); + + mx3_cam->active = NULL; + + list_for_each_entry_safe(buf, tmp, &mx3_cam->capture, queue) { + list_del_init(&buf->queue); + vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); + } + + spin_unlock_irqrestore(&mx3_cam->lock, flags); +} + +static struct vb2_ops mx3_videobuf_ops = { + .queue_setup = mx3_videobuf_setup, + .buf_queue = mx3_videobuf_queue, + .buf_cleanup = mx3_videobuf_release, + .buf_init = mx3_videobuf_init, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, + .stop_streaming = mx3_stop_streaming, +}; + +static int mx3_camera_init_videobuf(struct vb2_queue *q, + struct soc_camera_device *icd) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + q->io_modes = VB2_MMAP | VB2_USERPTR; + q->drv_priv = icd; + q->ops = &mx3_videobuf_ops; + q->mem_ops = &vb2_dma_contig_memops; + q->buf_struct_size = sizeof(struct mx3_camera_buffer); + q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + q->lock = &ici->host_lock; + + return vb2_queue_init(q); +} + +/* First part of ipu_csi_init_interface() */ +static void mx3_camera_activate(struct mx3_camera_dev *mx3_cam) +{ + u32 conf; + long rate; + + /* Set default size: ipu_csi_set_window_size() */ + csi_reg_write(mx3_cam, (640 - 1) | ((480 - 1) << 16), CSI_ACT_FRM_SIZE); + /* ...and position to 0:0: ipu_csi_set_window_pos() */ + conf = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; + csi_reg_write(mx3_cam, conf, CSI_OUT_FRM_CTRL); + + /* We use only gated clock synchronisation mode so far */ + conf = 0 << CSI_SENS_CONF_SENS_PRTCL_SHIFT; + + /* Set generic data, platform-biggest bus-width */ + conf |= CSI_SENS_CONF_DATA_FMT_BAYER; + + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) + conf |= 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) + conf |= 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) + conf |= 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + else/* if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4)*/ + conf |= 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + + if (mx3_cam->platform_flags & MX3_CAMERA_CLK_SRC) + conf |= 1 << CSI_SENS_CONF_SENS_CLKSRC_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_EXT_VSYNC) + conf |= 1 << CSI_SENS_CONF_EXT_VSYNC_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_DP) + conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_PCP) + conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_HSP) + conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; + if (mx3_cam->platform_flags & MX3_CAMERA_VSP) + conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; + + /* ipu_csi_init_interface() */ + csi_reg_write(mx3_cam, conf, CSI_SENS_CONF); + + clk_prepare_enable(mx3_cam->clk); + rate = clk_round_rate(mx3_cam->clk, mx3_cam->mclk); + dev_dbg(mx3_cam->soc_host.v4l2_dev.dev, "Set SENS_CONF to %x, rate %ld\n", conf, rate); + if (rate) + clk_set_rate(mx3_cam->clk, rate); +} + +static int mx3_camera_add_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX3 Camera driver attached to camera %d\n", + icd->devnum); + + return 0; +} + +static void mx3_camera_remove_device(struct soc_camera_device *icd) +{ + dev_info(icd->parent, "MX3 Camera driver detached from camera %d\n", + icd->devnum); +} + +/* Called with .host_lock held */ +static int mx3_camera_clock_start(struct soc_camera_host *ici) +{ + struct mx3_camera_dev *mx3_cam = ici->priv; + + mx3_camera_activate(mx3_cam); + + mx3_cam->buf_total = 0; + + return 0; +} + +/* Called with .host_lock held */ +static void mx3_camera_clock_stop(struct soc_camera_host *ici) +{ + struct mx3_camera_dev *mx3_cam = ici->priv; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + + if (*ichan) { + dma_release_channel(&(*ichan)->dma_chan); + *ichan = NULL; + } + + clk_disable_unprepare(mx3_cam->clk); +} + +static int test_platform_param(struct mx3_camera_dev *mx3_cam, + unsigned char buswidth, unsigned long *flags) +{ + /* + * If requested data width is supported by the platform, use it or any + * possible lower value - i.MX31 is smart enough to shift bits + */ + if (buswidth > fls(mx3_cam->width_flags)) + return -EINVAL; + + /* + * Platform specified synchronization and pixel clock polarities are + * only a recommendation and are only used during probing. MX3x + * camera interface only works in master mode, i.e., uses HSYNC and + * VSYNC signals from the sensor + */ + *flags = V4L2_MBUS_MASTER | + V4L2_MBUS_HSYNC_ACTIVE_HIGH | + V4L2_MBUS_HSYNC_ACTIVE_LOW | + V4L2_MBUS_VSYNC_ACTIVE_HIGH | + V4L2_MBUS_VSYNC_ACTIVE_LOW | + V4L2_MBUS_PCLK_SAMPLE_RISING | + V4L2_MBUS_PCLK_SAMPLE_FALLING | + V4L2_MBUS_DATA_ACTIVE_HIGH | + V4L2_MBUS_DATA_ACTIVE_LOW; + + return 0; +} + +static int mx3_camera_try_bus_param(struct soc_camera_device *icd, + const unsigned int depth) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + unsigned long bus_flags, common_flags; + int ret = test_platform_param(mx3_cam, depth, &bus_flags); + + dev_dbg(icd->parent, "request bus width %d bit: %d\n", depth, ret); + + if (ret < 0) + return ret; + + ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); + if (!ret) { + common_flags = soc_mbus_config_compatible(&cfg, + bus_flags); + if (!common_flags) { + dev_warn(icd->parent, + "Flags incompatible: camera 0x%x, host 0x%lx\n", + cfg.flags, bus_flags); + return -EINVAL; + } + } else if (ret != -ENOIOCTLCMD) { + return ret; + } + + return 0; +} + +static bool chan_filter(struct dma_chan *chan, void *arg) +{ + struct dma_chan_request *rq = arg; + struct mx3_camera_pdata *pdata; + + if (!imx_dma_is_ipu(chan)) + return false; + + if (!rq) + return false; + + pdata = rq->mx3_cam->soc_host.v4l2_dev.dev->platform_data; + + return rq->id == chan->chan_id && + pdata->dma_dev == chan->device->dev; +} + +static const struct soc_mbus_pixelfmt mx3_camera_formats[] = { + { + .fourcc = V4L2_PIX_FMT_SBGGR8, + .name = "Bayer BGGR (sRGB) 8 bit", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, { + .fourcc = V4L2_PIX_FMT_GREY, + .name = "Monochrome 8 bit", + .bits_per_sample = 8, + .packing = SOC_MBUS_PACKING_NONE, + .order = SOC_MBUS_ORDER_LE, + .layout = SOC_MBUS_LAYOUT_PACKED, + }, +}; + +/* This will be corrected as we get more formats */ +static bool mx3_camera_packing_supported(const struct soc_mbus_pixelfmt *fmt) +{ + return fmt->packing == SOC_MBUS_PACKING_NONE || + (fmt->bits_per_sample == 8 && + fmt->packing == SOC_MBUS_PACKING_2X8_PADHI) || + (fmt->bits_per_sample > 8 && + fmt->packing == SOC_MBUS_PACKING_EXTEND16); +} + +static int mx3_camera_get_formats(struct soc_camera_device *icd, unsigned int idx, + struct soc_camera_format_xlate *xlate) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct device *dev = icd->parent; + int formats = 0, ret; + struct v4l2_subdev_mbus_code_enum code = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + .index = idx, + }; + const struct soc_mbus_pixelfmt *fmt; + + ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code); + if (ret < 0) + /* No more formats */ + return 0; + + fmt = soc_mbus_get_fmtdesc(code.code); + if (!fmt) { + dev_warn(icd->parent, + "Unsupported format code #%u: 0x%x\n", idx, code.code); + return 0; + } + + /* This also checks support for the requested bits-per-sample */ + ret = mx3_camera_try_bus_param(icd, fmt->bits_per_sample); + if (ret < 0) + return 0; + + switch (code.code) { + case MEDIA_BUS_FMT_SBGGR10_1X10: + formats++; + if (xlate) { + xlate->host_fmt = &mx3_camera_formats[0]; + xlate->code = code.code; + xlate++; + dev_dbg(dev, "Providing format %s using code 0x%x\n", + mx3_camera_formats[0].name, code.code); + } + break; + case MEDIA_BUS_FMT_Y10_1X10: + formats++; + if (xlate) { + xlate->host_fmt = &mx3_camera_formats[1]; + xlate->code = code.code; + xlate++; + dev_dbg(dev, "Providing format %s using code 0x%x\n", + mx3_camera_formats[1].name, code.code); + } + break; + default: + if (!mx3_camera_packing_supported(fmt)) + return 0; + } + + /* Generic pass-through */ + formats++; + if (xlate) { + xlate->host_fmt = fmt; + xlate->code = code.code; + dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n", + (fmt->fourcc >> (0*8)) & 0xFF, + (fmt->fourcc >> (1*8)) & 0xFF, + (fmt->fourcc >> (2*8)) & 0xFF, + (fmt->fourcc >> (3*8)) & 0xFF); + xlate++; + } + + return formats; +} + +static void configure_geometry(struct mx3_camera_dev *mx3_cam, + unsigned int width, unsigned int height, + const struct soc_mbus_pixelfmt *fmt) +{ + u32 ctrl, width_field, height_field; + + if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) { + /* + * As the CSI will be configured to output BAYER, here + * the width parameter count the number of samples to + * capture to complete the whole image width. + */ + unsigned int num, den; + int ret = soc_mbus_samples_per_pixel(fmt, &num, &den); + BUG_ON(ret < 0); + width = width * num / den; + } + + /* Setup frame size - this cannot be changed on-the-fly... */ + width_field = width - 1; + height_field = height - 1; + csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_SENS_FRM_SIZE); + + csi_reg_write(mx3_cam, width_field << 16, CSI_FLASH_STROBE_1); + csi_reg_write(mx3_cam, (height_field << 16) | 0x22, CSI_FLASH_STROBE_2); + + csi_reg_write(mx3_cam, width_field | (height_field << 16), CSI_ACT_FRM_SIZE); + + /* ...and position */ + ctrl = csi_reg_read(mx3_cam, CSI_OUT_FRM_CTRL) & 0xffff0000; + /* Sensor does the cropping */ + csi_reg_write(mx3_cam, ctrl | 0 | (0 << 8), CSI_OUT_FRM_CTRL); +} + +static int acquire_dma_channel(struct mx3_camera_dev *mx3_cam) +{ + dma_cap_mask_t mask; + struct dma_chan *chan; + struct idmac_channel **ichan = &mx3_cam->idmac_channel[0]; + /* We have to use IDMAC_IC_7 for Bayer / generic data */ + struct dma_chan_request rq = {.mx3_cam = mx3_cam, + .id = IDMAC_IC_7}; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_PRIVATE, mask); + chan = dma_request_channel(mask, chan_filter, &rq); + if (!chan) + return -EBUSY; + + *ichan = to_idmac_chan(chan); + (*ichan)->client = mx3_cam; + + return 0; +} + +/* + * FIXME: learn to use stride != width, then we can keep stride properly aligned + * and support arbitrary (even) widths. + */ +static inline void stride_align(__u32 *width) +{ + if (ALIGN(*width, 8) < 4096) + *width = ALIGN(*width, 8); + else + *width = *width & ~7; +} + +/* + * As long as we don't implement host-side cropping and scaling, we can use + * default g_crop and cropcap from soc_camera.c + */ +static int mx3_camera_set_crop(struct soc_camera_device *icd, + const struct v4l2_crop *a) +{ + struct v4l2_crop a_writable = *a; + struct v4l2_rect *rect = &a_writable.c; + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct v4l2_subdev_format fmt = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *mf = &fmt.format; + int ret; + + soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); + soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); + + ret = v4l2_subdev_call(sd, video, s_crop, a); + if (ret < 0) + return ret; + + /* The capture device might have changed its output sizes */ + ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); + if (ret < 0) + return ret; + + if (mf->code != icd->current_fmt->code) + return -EINVAL; + + if (mf->width & 7) { + /* Ouch! We can only handle 8-byte aligned width... */ + stride_align(&mf->width); + ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &fmt); + if (ret < 0) + return ret; + } + + if (mf->width != icd->user_width || mf->height != icd->user_height) + configure_geometry(mx3_cam, mf->width, mf->height, + icd->current_fmt->host_fmt); + + dev_dbg(icd->parent, "Sensor cropped %dx%d\n", + mf->width, mf->height); + + icd->user_width = mf->width; + icd->user_height = mf->height; + + return ret; +} + +static int mx3_camera_set_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_ACTIVE, + }; + struct v4l2_mbus_framefmt *mf = &format.format; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); + if (!xlate) { + dev_warn(icd->parent, "Format %x not found\n", + pix->pixelformat); + return -EINVAL; + } + + stride_align(&pix->width); + dev_dbg(icd->parent, "Set format %dx%d\n", pix->width, pix->height); + + /* + * Might have to perform a complete interface initialisation like in + * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider + * mxc_v4l2_s_fmt() + */ + + configure_geometry(mx3_cam, pix->width, pix->height, xlate->host_fmt); + + mf->width = pix->width; + mf->height = pix->height; + mf->field = pix->field; + mf->colorspace = pix->colorspace; + mf->code = xlate->code; + + ret = v4l2_subdev_call(sd, pad, set_fmt, NULL, &format); + if (ret < 0) + return ret; + + if (mf->code != xlate->code) + return -EINVAL; + + if (!mx3_cam->idmac_channel[0]) { + ret = acquire_dma_channel(mx3_cam); + if (ret < 0) + return ret; + } + + pix->width = mf->width; + pix->height = mf->height; + pix->field = mf->field; + mx3_cam->field = mf->field; + pix->colorspace = mf->colorspace; + icd->current_fmt = xlate; + + dev_dbg(icd->parent, "Sensor set %dx%d\n", pix->width, pix->height); + + return ret; +} + +static int mx3_camera_try_fmt(struct soc_camera_device *icd, + struct v4l2_format *f) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + const struct soc_camera_format_xlate *xlate; + struct v4l2_pix_format *pix = &f->fmt.pix; + struct v4l2_subdev_pad_config pad_cfg; + struct v4l2_subdev_format format = { + .which = V4L2_SUBDEV_FORMAT_TRY, + }; + struct v4l2_mbus_framefmt *mf = &format.format; + __u32 pixfmt = pix->pixelformat; + int ret; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (pixfmt && !xlate) { + dev_warn(icd->parent, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + /* limit to MX3 hardware capabilities */ + if (pix->height > 4096) + pix->height = 4096; + if (pix->width > 4096) + pix->width = 4096; + + /* limit to sensor capabilities */ + mf->width = pix->width; + mf->height = pix->height; + mf->field = pix->field; + mf->colorspace = pix->colorspace; + mf->code = xlate->code; + + ret = v4l2_subdev_call(sd, pad, set_fmt, &pad_cfg, &format); + if (ret < 0) + return ret; + + pix->width = mf->width; + pix->height = mf->height; + pix->colorspace = mf->colorspace; + + switch (mf->field) { + case V4L2_FIELD_ANY: + pix->field = V4L2_FIELD_NONE; + break; + case V4L2_FIELD_NONE: + break; + default: + dev_err(icd->parent, "Field type %d unsupported.\n", + mf->field); + ret = -EINVAL; + } + + return ret; +} + +static int mx3_camera_reqbufs(struct soc_camera_device *icd, + struct v4l2_requestbuffers *p) +{ + return 0; +} + +static unsigned int mx3_camera_poll(struct file *file, poll_table *pt) +{ + struct soc_camera_device *icd = file->private_data; + + return vb2_poll(&icd->vb2_vidq, file, pt); +} + +static int mx3_camera_querycap(struct soc_camera_host *ici, + struct v4l2_capability *cap) +{ + /* cap->name is set by the firendly caller:-> */ + strlcpy(cap->card, "i.MX3x Camera", sizeof(cap->card)); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int mx3_camera_set_bus_param(struct soc_camera_device *icd) +{ + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + struct soc_camera_host *ici = to_soc_camera_host(icd->parent); + struct mx3_camera_dev *mx3_cam = ici->priv; + struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; + u32 pixfmt = icd->current_fmt->host_fmt->fourcc; + unsigned long bus_flags, common_flags; + u32 dw, sens_conf; + const struct soc_mbus_pixelfmt *fmt; + int buswidth; + int ret; + const struct soc_camera_format_xlate *xlate; + struct device *dev = icd->parent; + + fmt = soc_mbus_get_fmtdesc(icd->current_fmt->code); + if (!fmt) + return -EINVAL; + + xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); + if (!xlate) { + dev_warn(dev, "Format %x not found\n", pixfmt); + return -EINVAL; + } + + buswidth = fmt->bits_per_sample; + ret = test_platform_param(mx3_cam, buswidth, &bus_flags); + + dev_dbg(dev, "requested bus width %d bit: %d\n", buswidth, ret); + + if (ret < 0) + return ret; + + ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); + if (!ret) { + common_flags = soc_mbus_config_compatible(&cfg, + bus_flags); + if (!common_flags) { + dev_warn(icd->parent, + "Flags incompatible: camera 0x%x, host 0x%lx\n", + cfg.flags, bus_flags); + return -EINVAL; + } + } else if (ret != -ENOIOCTLCMD) { + return ret; + } else { + common_flags = bus_flags; + } + + dev_dbg(dev, "Flags cam: 0x%x host: 0x%lx common: 0x%lx\n", + cfg.flags, bus_flags, common_flags); + + /* Make choices, based on platform preferences */ + if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && + (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_HSP) + common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; + else + common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; + } + + if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && + (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_VSP) + common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; + else + common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; + } + + if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) && + (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) { + if (mx3_cam->platform_flags & MX3_CAMERA_DP) + common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH; + else + common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW; + } + + if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && + (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { + if (mx3_cam->platform_flags & MX3_CAMERA_PCP) + common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; + else + common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; + } + + cfg.flags = common_flags; + ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); + if (ret < 0 && ret != -ENOIOCTLCMD) { + dev_dbg(dev, "camera s_mbus_config(0x%lx) returned %d\n", + common_flags, ret); + return ret; + } + + /* + * So far only gated clock mode is supported. Add a line + * (3 << CSI_SENS_CONF_SENS_PRTCL_SHIFT) | + * below and select the required mode when supporting other + * synchronisation protocols. + */ + sens_conf = csi_reg_read(mx3_cam, CSI_SENS_CONF) & + ~((1 << CSI_SENS_CONF_VSYNC_POL_SHIFT) | + (1 << CSI_SENS_CONF_HSYNC_POL_SHIFT) | + (1 << CSI_SENS_CONF_DATA_POL_SHIFT) | + (1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT) | + (3 << CSI_SENS_CONF_DATA_FMT_SHIFT) | + (3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT)); + + /* TODO: Support RGB and YUV formats */ + + /* This has been set in mx3_camera_activate(), but we clear it above */ + sens_conf |= CSI_SENS_CONF_DATA_FMT_BAYER; + + if (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING) + sens_conf |= 1 << CSI_SENS_CONF_PIX_CLK_POL_SHIFT; + if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_HSYNC_POL_SHIFT; + if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_VSYNC_POL_SHIFT; + if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW) + sens_conf |= 1 << CSI_SENS_CONF_DATA_POL_SHIFT; + + /* Just do what we're asked to do */ + switch (xlate->host_fmt->bits_per_sample) { + case 4: + dw = 0 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + case 8: + dw = 1 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + case 10: + dw = 2 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + break; + default: + /* + * Actually it can only be 15 now, default is just to silence + * compiler warnings + */ + case 15: + dw = 3 << CSI_SENS_CONF_DATA_WIDTH_SHIFT; + } + + csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF); + + dev_dbg(dev, "Set SENS_CONF to %x\n", sens_conf | dw); + + return 0; +} + +static struct soc_camera_host_ops mx3_soc_camera_host_ops = { + .owner = THIS_MODULE, + .add = mx3_camera_add_device, + .remove = mx3_camera_remove_device, + .clock_start = mx3_camera_clock_start, + .clock_stop = mx3_camera_clock_stop, + .set_crop = mx3_camera_set_crop, + .set_fmt = mx3_camera_set_fmt, + .try_fmt = mx3_camera_try_fmt, + .get_formats = mx3_camera_get_formats, + .init_videobuf2 = mx3_camera_init_videobuf, + .reqbufs = mx3_camera_reqbufs, + .poll = mx3_camera_poll, + .querycap = mx3_camera_querycap, + .set_bus_param = mx3_camera_set_bus_param, +}; + +static int mx3_camera_probe(struct platform_device *pdev) +{ + struct mx3_camera_pdata *pdata = pdev->dev.platform_data; + struct mx3_camera_dev *mx3_cam; + struct resource *res; + void __iomem *base; + int err = 0; + struct soc_camera_host *soc_host; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + if (!pdata) + return -EINVAL; + + mx3_cam = devm_kzalloc(&pdev->dev, sizeof(*mx3_cam), GFP_KERNEL); + if (!mx3_cam) { + dev_err(&pdev->dev, "Could not allocate mx3 camera object\n"); + return -ENOMEM; + } + + mx3_cam->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(mx3_cam->clk)) + return PTR_ERR(mx3_cam->clk); + + mx3_cam->pdata = pdata; + mx3_cam->platform_flags = pdata->flags; + if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) { + /* + * Platform hasn't set available data widths. This is bad. + * Warn and use a default. + */ + dev_warn(&pdev->dev, "WARNING! Platform hasn't set available " + "data widths, using default 8 bit\n"); + mx3_cam->platform_flags |= MX3_CAMERA_DATAWIDTH_8; + } + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_4) + mx3_cam->width_flags = 1 << 3; + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_8) + mx3_cam->width_flags |= 1 << 7; + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_10) + mx3_cam->width_flags |= 1 << 9; + if (mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_15) + mx3_cam->width_flags |= 1 << 14; + + mx3_cam->mclk = pdata->mclk_10khz * 10000; + if (!mx3_cam->mclk) { + dev_warn(&pdev->dev, + "mclk_10khz == 0! Please, fix your platform data. " + "Using default 20MHz\n"); + mx3_cam->mclk = 20000000; + } + + /* list of video-buffers */ + INIT_LIST_HEAD(&mx3_cam->capture); + spin_lock_init(&mx3_cam->lock); + + mx3_cam->base = base; + + soc_host = &mx3_cam->soc_host; + soc_host->drv_name = MX3_CAM_DRV_NAME; + soc_host->ops = &mx3_soc_camera_host_ops; + soc_host->priv = mx3_cam; + soc_host->v4l2_dev.dev = &pdev->dev; + soc_host->nr = pdev->id; + + mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); + if (IS_ERR(mx3_cam->alloc_ctx)) + return PTR_ERR(mx3_cam->alloc_ctx); + + if (pdata->asd_sizes) { + soc_host->asd = pdata->asd; + soc_host->asd_sizes = pdata->asd_sizes; + } + + err = soc_camera_host_register(soc_host); + if (err) + goto ecamhostreg; + + /* IDMAC interface */ + dmaengine_get(); + + return 0; + +ecamhostreg: + vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); + return err; +} + +static int mx3_camera_remove(struct platform_device *pdev) +{ + struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); + struct mx3_camera_dev *mx3_cam = container_of(soc_host, + struct mx3_camera_dev, soc_host); + + soc_camera_host_unregister(soc_host); + + /* + * The channel has either not been allocated, + * or should have been released + */ + if (WARN_ON(mx3_cam->idmac_channel[0])) + dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan); + + vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx); + + dmaengine_put(); + + return 0; +} + +static struct platform_driver mx3_camera_driver = { + .driver = { + .name = MX3_CAM_DRV_NAME, + }, + .probe = mx3_camera_probe, + .remove = mx3_camera_remove, +}; + +module_platform_driver(mx3_camera_driver); + +MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); +MODULE_AUTHOR("Guennadi Liakhovetski "); +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("0.2.3"); +MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME); -- cgit From 449c1fcd86f5077d5076a955e65c07a7c4cbbf9d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 8 Feb 2016 17:25:59 -0200 Subject: [media] media: rc: nuvoton: support reading / writing wakeup sequence via sysfs This patch adds a binary attribute /sys/class/rc/rc?/wakeup_data which allows to read / write the wakeup sequence. In combination with the core extension for exposing the most recent raw packet this allows to easily define and set a wakeup sequence. At least on my Zotac CI321 the BIOS resets the wakeup sequence at each boot to a factory default. Therefore I use a udev rule SUBSYSTEM=="rc", DRIVERS=="nuvoton-cir", ACTION=="add", RUN+="